{"version":3,"file":"mergeTranscendInputs-DjPe49yR.mjs","names":[],"sources":["../src/lib/preference-management/validatePreferenceManagementSlugs.ts","../src/lib/graphql/ensureAllDataSubjectsExist.ts","../src/lib/graphql/normalizeDeletionDependencies.ts","../src/lib/graphql/syncDataSilos.ts","../src/lib/graphql/syncConfigurationToTranscend.ts","../src/lib/mergeTranscendInputs.ts"],"sourcesContent":["import type { TranscendInput } from '../../codecs.js';\n\n/** Slugs for preference topics and option values must be alphabetical letters only. */\nexport const PREFERENCE_SLUG_REGEX = /^[A-Za-z]+$/;\n\n/**\n * Validate preference topic and option value slugs before push.\n *\n * @param input - Parsed transcend.yml input\n * @returns List of validation error messages (empty when valid)\n */\nexport function validatePreferenceManagementSlugs(input: TranscendInput): string[] {\n  const errors: string[] = [];\n\n  const validateSlug = (slug: string, context: string): void => {\n    if (!PREFERENCE_SLUG_REGEX.test(slug)) {\n      errors.push(\n        `${context}: slug \"${slug}\" is invalid — slugs must contain only alphabetical letters (A-Z, a-z). ` +\n          'Topic slugs are normalized to PascalCase server-side, so YAML slugs should already be PascalCase ' +\n          'or matching will break on subsequent pulls.',\n      );\n    }\n  };\n\n  for (const option of input['preference-options'] ?? []) {\n    validateSlug(option.slug, 'preference-options');\n  }\n\n  for (const purpose of input.purposes ?? []) {\n    for (const topic of purpose['preference-topics'] ?? []) {\n      validateSlug(topic.slug, `purposes (topic \"${topic.title}\")`);\n      for (const option of topic.options ?? []) {\n        validateSlug(option.slug, `purposes (topic \"${topic.title}\" option \"${option.title}\")`);\n      }\n    }\n  }\n\n  return errors;\n}\n","import { createDataSubject, fetchAllDataSubjects, type DataSubject } from '@transcend-io/sdk';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { keyBy, flatten, uniq, difference } from 'lodash-es';\n\nimport { TranscendInput } from '../../codecs.js';\nimport { logger } from '../../logger.js';\n\n/**\n * Fetch all of the data subjects in the organization\n *\n * @param input - Input to fetch\n * @param client - GraphQL client\n * @param fetchAll - When true, always fetch all subjects\n * @returns The list of data subjects\n */\nexport async function ensureAllDataSubjectsExist(\n  {\n    'data-silos': dataSilos = [],\n    'data-subjects': dataSubjects = [],\n    'processing-activities': processingActivities = [],\n    enrichers = [],\n  }: TranscendInput,\n  client: GraphQLClient,\n  fetchAll = false,\n): Promise<{ [type in string]: DataSubject }> {\n  const expectedDataSubjects = uniq([\n    ...flatten(dataSilos.map((silo) => silo['data-subjects'] || []) || []),\n    ...flatten(processingActivities.map(({ dataSubjectTypes }) => dataSubjectTypes ?? []) ?? []),\n    ...flatten(enrichers.map((enricher) => enricher['data-subjects'] || []) || []),\n    ...dataSubjects.map((subject) => subject.type),\n  ]);\n  if (expectedDataSubjects.length === 0 && !fetchAll) {\n    return {};\n  }\n\n  const internalSubjects = await fetchAllDataSubjects(client, { logger });\n  const dataSubjectByName = keyBy(internalSubjects, 'type');\n\n  const missingDataSubjects = difference(\n    expectedDataSubjects,\n    internalSubjects.map(({ type }) => type),\n  );\n\n  if (missingDataSubjects.length > 0) {\n    logger.info(colors.magenta(`Creating ${missingDataSubjects.length} new data subjects...`));\n    for (const dataSubjectType of missingDataSubjects) {\n      logger.info(colors.magenta(`Creating data subject ${dataSubjectType}...`));\n      const created = await createDataSubject(client, { input: dataSubjectType, logger });\n      logger.info(colors.green(`Created data subject ${dataSubjectType}!`));\n      dataSubjectByName[dataSubjectType] = created;\n    }\n  }\n\n  return dataSubjectByName;\n}\n","import type { DependedOnDataSiloInput } from '@transcend-io/sdk';\nimport { uniq } from 'lodash-es';\n\nimport type { DeletionDependencies, DeletionDependencyInput } from '../../codecs.js';\n\n/**\n * Convert the `deletion-dependencies` entries for a single data silo into the\n * `dependedOnDataSilos` input accepted by the `updateDataSilos` mutation.\n *\n * A list of titles becomes a single global entry. A list of objects may declare\n * at most one global configuration (`{ titles }`) plus per-workflow overrides;\n * workflows that are absent from the list are left untouched.\n *\n * @param dependencies - The `deletion-dependencies` entries from transcend.yml\n * @param dataSiloTitle - Title of the data silo being synced, used in error messages\n * @returns The dependency entries to send to the API\n */\nexport function normalizeDeletionDependencies(\n  dependencies: DeletionDependencies,\n  dataSiloTitle: string,\n): DependedOnDataSiloInput[] {\n  if (dependencies.length === 0) {\n    return [];\n  }\n\n  // Legacy / no-overrides form: a flat list of data silo titles\n  if (typeof dependencies[0] === 'string') {\n    return [{ titles: uniq(dependencies as string[]) }];\n  }\n\n  let globalTitles: string[] | undefined;\n  const workflowOverrides: DependedOnDataSiloInput[] = [];\n  const seenWorkflows = new Set<string>();\n\n  /**\n   * Record an override for a single workflow, rejecting duplicates before the API does\n   * so that the error names the data silo\n   *\n   * @param workflow - Internal name of the workflow being overridden\n   * @param override - Titles or reset flag to send for that workflow\n   */\n  const addWorkflowOverride = (\n    workflow: string,\n    override: Omit<DependedOnDataSiloInput, 'workflowConfigInternalName'>,\n  ): void => {\n    if (seenWorkflows.has(workflow)) {\n      throw new Error(\n        `Data silo \"${dataSiloTitle}\" has multiple deletion-dependencies entries for workflow ` +\n          `\"${workflow}\". Combine them into a single entry.`,\n      );\n    }\n    seenWorkflows.add(workflow);\n    workflowOverrides.push({ workflowConfigInternalName: workflow, ...override });\n  };\n\n  (dependencies as DeletionDependencyInput[]).forEach((dependency) => {\n    // io-ts codecs allow extra properties, so this combination decodes cleanly\n    // even though the two halves contradict each other\n    if ('reset-to-global' in dependency && 'titles' in dependency) {\n      throw new Error(\n        `Data silo \"${dataSiloTitle}\" has a deletion-dependencies entry for workflow ` +\n          `\"${dependency.workflow}\" that sets both \"reset-to-global\" and \"titles\". ` +\n          'Use \"titles: []\" to override the global configuration with no dependencies, ' +\n          'or \"reset-to-global: true\" to fall back to the global configuration.',\n      );\n    }\n\n    if ('reset-to-global' in dependency) {\n      addWorkflowOverride(dependency.workflow, { resetToGlobal: true });\n      return;\n    }\n\n    if (dependency.workflow) {\n      addWorkflowOverride(dependency.workflow, { titles: dependency.titles });\n      return;\n    }\n\n    if (globalTitles !== undefined) {\n      throw new Error(\n        `Data silo \"${dataSiloTitle}\" has multiple global deletion-dependencies entries. ` +\n          'Combine them into a single `{ titles: [...] }` entry.',\n      );\n    }\n    globalTitles = dependency.titles;\n  });\n\n  return [\n    ...(globalTitles !== undefined ? [{ titles: uniq(globalTitles) }] : []),\n    ...workflowOverrides,\n  ];\n}\n","import {\n  makeGraphQLRequest,\n  ApiKey,\n  convertToDataSubjectBlockList,\n  type DataSubject,\n  fetchAllDataSilos,\n  type DataSilo,\n  CREATE_DATA_SILOS,\n  UPDATE_DATA_SILOS,\n  UPDATE_OR_CREATE_DATA_POINT,\n} from '@transcend-io/sdk';\nimport { apply } from '@transcend-io/type-utils';\nimport { mapSeries, map } from '@transcend-io/utils';\n/* eslint-disable max-lines */\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { chunk, keyBy } from 'lodash-es';\n\nimport { DataSiloInput } from '../../codecs.js';\nimport { logger } from '../../logger.js';\n\nconst BATCH_SILOS_LIMIT = 20;\n\n/**\n * Sync a data silo configuration\n *\n * @param dataSilos - Data silos to sync\n * @param client - GraphQL client\n * @param options - Options\n * @returns Data silo info\n */\nexport async function syncDataSilos(\n  dataSilos: DataSiloInput[],\n  client: GraphQLClient,\n  {\n    pageSize,\n    dataSubjectsByName,\n    apiKeysByTitle,\n  }: {\n    /** Page size */\n    pageSize: number;\n    /** The data subjects in the organization */\n    dataSubjectsByName: { [type in string]: DataSubject };\n    /** API key title to API key */\n    apiKeysByTitle: { [title in string]: ApiKey };\n  },\n): Promise<{\n  /** Whether successfully updated */\n  success: boolean;\n  /** A mapping between data silo title to data silo ID */\n  dataSiloTitleToId: { [k in string]: string };\n}> {\n  let encounteredError = false;\n\n  // Time duration\n  const t0 = new Date().getTime();\n  logger.info(colors.magenta(`Syncing \"${dataSilos.length}\" data silos...`));\n\n  // Determine the set of data silos that already exist\n  const existingDataSilos = await fetchAllDataSilos(client, {\n    titles: dataSilos.map(({ title }) => title),\n    pageSize,\n    logger,\n  });\n\n  // Create a mapping of title -> existing silo, if it exists\n  const existingDataSiloByTitle = keyBy<Pick<DataSilo, 'id' | 'title'>>(existingDataSilos, 'title');\n\n  // Create new silos that do not exist\n  const newDataSiloInputs = dataSilos.filter(({ title }) => !existingDataSiloByTitle[title]);\n  if (newDataSiloInputs.length > 0) {\n    logger.info(\n      colors.magenta(`Creating \"${newDataSiloInputs.length}\" data silos that did not exist...`),\n    );\n\n    // Batch the creation\n    const chunked = chunk(newDataSiloInputs, BATCH_SILOS_LIMIT);\n    await mapSeries(chunked, async (dependencyUpdateChunk) => {\n      const {\n        createDataSilos: { dataSilos },\n      } = await makeGraphQLRequest<{\n        /** Mutation result */\n        createDataSilos: {\n          /** New data silos */\n          dataSilos: Pick<DataSilo, 'id' | 'title'>[];\n        };\n      }>(client, CREATE_DATA_SILOS, {\n        variables: {\n          input: dependencyUpdateChunk.map((input) => ({\n            name: input['outer-type'] || input.integrationName,\n            title: input.title,\n            country: input.country,\n            countrySubDivision: input.countrySubDivision,\n            sombraId: input['sombra-id'],\n          })),\n        },\n        logger,\n      });\n\n      // save mapping of title and id\n      dataSilos.forEach((silo) => {\n        existingDataSiloByTitle[silo.title] = silo;\n      });\n    });\n\n    logger.info(colors.green(`Successfully created \"${newDataSiloInputs.length}\" data silos!`));\n  }\n\n  // Batch the updates\n  const chunkedUpdates = chunk(dataSilos, BATCH_SILOS_LIMIT);\n  await mapSeries(chunkedUpdates, async (dataSiloUpdateChunk, ind) => {\n    logger.info(\n      colors.magenta(\n        `[Batch ${ind + 1}/${chunkedUpdates.length}] Syncing \"${\n          dataSiloUpdateChunk.length\n        }\" data silos`,\n      ),\n    );\n    await makeGraphQLRequest<{\n      /** Mutation result */\n      updateDataSilos: {\n        /** New data silos */\n        dataSilos: Pick<DataSilo, 'id' | 'title'>[];\n      };\n    }>(client, UPDATE_DATA_SILOS, {\n      variables: {\n        input: {\n          dataSilos: dataSiloUpdateChunk.map((input) => ({\n            id: existingDataSiloByTitle[input.title].id,\n            country: input.country,\n            countrySubDivision: input.countrySubDivision,\n            url: input.url,\n            headers: input.headers,\n            description: input.description,\n            identifiers: input['identity-keys'],\n            isLive: !input.disabled,\n            ownerEmails: input.owners,\n            teamNames: input.teams,\n            // clear out the global config if not specified, otherwise the update needs to be\n            // applied after all data silos are created\n            dependedOnDataSilos: input['deletion-dependencies'] ? undefined : [{ titles: [] }],\n            apiKeyId: input['api-key-title']\n              ? apiKeysByTitle[input['api-key-title']].id\n              : undefined,\n            dataSubjectBlockListIds: input['data-subjects']\n              ? convertToDataSubjectBlockList(input['data-subjects'], dataSubjectsByName)\n              : undefined,\n            attributes: input.attributes,\n            businessEntityTitles: input.businessEntityTitles,\n            sombraId: input['sombra-id'],\n            // AVC settings\n            notifyEmailAddress: input['email-settings']?.['notify-email-address'],\n            promptAVendorEmailSendFrequency: input['email-settings']?.['send-frequency'],\n            promptAVendorEmailSendType: input['email-settings']?.['send-type'],\n            promptAVendorEmailIncludeIdentifiersAttachment:\n              input['email-settings']?.['include-identifiers-attachment'],\n            promptAVendorEmailCompletionLinkType: input['email-settings']?.['completion-link-type'],\n            manualWorkRetryFrequency: input['email-settings']?.['manual-work-retry-frequency'],\n          })),\n        },\n      },\n      logger,\n    });\n    logger.info(\n      colors.green(\n        `[Batch ${ind + 1}/${chunkedUpdates.length}] Synced \"${\n          dataSiloUpdateChunk.length\n        }\" data silos!`,\n      ),\n    );\n  });\n\n  // Sync datapoints\n\n  // create a new progress bar instance and use shades_classic theme\n  const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n  const dataSilosWithDataPoints = dataSilos.filter(({ datapoints = [] }) => datapoints.length > 0);\n  const totalDataPoints = dataSilos\n    .map(({ datapoints = [] }) => datapoints.length)\n    .reduce((acc, count) => acc + count, 0);\n  logger.info(\n    colors.magenta(\n      `Syncing \"${totalDataPoints}\" datapoints from \"${dataSilosWithDataPoints.length}\" data silos...`,\n    ),\n  );\n  progressBar.start(totalDataPoints, 0);\n  let total = 0;\n\n  await map(\n    dataSilosWithDataPoints,\n    async ({ datapoints, title }) => {\n      if (datapoints) {\n        await mapSeries(datapoints, async (datapoint) => {\n          const fields = datapoint.fields\n            ? datapoint.fields.map(\n                ({ key, description, categories, purposes, attributes, ...rest }) =>\n                  // TODO: Support setting title separately from the 'key/name'\n                  ({\n                    name: key,\n                    description,\n                    categories: !categories\n                      ? undefined\n                      : categories.map((category) => ({\n                          ...category,\n                          name: category.name || 'Other',\n                        })),\n                    purposes: !purposes\n                      ? undefined\n                      : purposes.map((purpose) => ({\n                          ...purpose,\n                          name: purpose.name || 'Other',\n                        })),\n                    attributes,\n                    accessRequestVisibilityEnabled: rest['access-request-visibility-enabled'],\n                    erasureRequestRedactionEnabled: rest['erasure-request-redaction-enabled'],\n                  }),\n              )\n            : undefined;\n\n          const payload = {\n            dataSiloId: existingDataSiloByTitle[title].id,\n            path: datapoint.path,\n            name: datapoint.key,\n            title: datapoint.title,\n            description: datapoint.description,\n            ...(datapoint.owners\n              ? {\n                  ownerEmails: datapoint.owners,\n                }\n              : {}),\n            ...(datapoint.teams\n              ? {\n                  teamNames: datapoint.teams,\n                }\n              : {}),\n            ...(datapoint['data-collection-tag']\n              ? { dataCollectionTag: datapoint['data-collection-tag'] }\n              : {}),\n            querySuggestions: !datapoint['privacy-action-queries']\n              ? undefined\n              : Object.entries(datapoint['privacy-action-queries']).map(([key, value]) => ({\n                  requestType: key,\n                  suggestedQuery: value,\n                })),\n            enabledActions: datapoint['privacy-actions'] || [], // clear out when not specified\n            subDataPoints: fields,\n          };\n\n          // Ensure no duplicate sub-datapoints are provided\n          const subDataPointsToUpdate = (payload.subDataPoints || []).map(({ name }) => name);\n          const duplicateDataPoints = subDataPointsToUpdate.filter(\n            (name, index) => subDataPointsToUpdate.indexOf(name) !== index,\n          );\n          if (duplicateDataPoints.length > 0) {\n            logger.info(\n              colors.red(\n                `\\nCannot update datapoint \"${\n                  datapoint.key\n                }\" as it has duplicate sub-datapoints with the same name: \\n${duplicateDataPoints.join(\n                  '\\n',\n                )}`,\n              ),\n            );\n            encounteredError = true;\n          } else {\n            try {\n              await makeGraphQLRequest(client, UPDATE_OR_CREATE_DATA_POINT, {\n                variables: payload,\n                logger,\n              });\n            } catch (err) {\n              logger.info(\n                colors.red(\n                  `\\nFailed to update datapoint \"${datapoint.key}\" for data silo \"${title}\"! - \\n${err.message}`,\n                ),\n              );\n              encounteredError = true;\n            }\n          }\n          total += 1;\n          progressBar.update(total);\n        });\n      }\n    },\n    {\n      concurrency: 10,\n    },\n  );\n\n  progressBar.stop();\n  const t1 = new Date().getTime();\n  const totalTime = t1 - t0;\n\n  logger.info(\n    colors.green(\n      `Synced \"${dataSilos.length}\" data silos and \"${totalDataPoints}\" datapoints in \"${\n        totalTime / 1000\n      }\" seconds!`,\n    ),\n  );\n  return {\n    success: !encounteredError,\n    dataSiloTitleToId: apply(existingDataSiloByTitle, ({ id }) => id),\n  };\n}\n/* eslint-enable max-lines */\n","import {\n  fetchAllActions,\n  fetchAllAttributes,\n  fetchAllDataSubjects,\n  fetchApiKeys,\n  fetchIdentifiersAndCreateMissing,\n  syncAction,\n  syncActionItemCollections,\n  syncActionItems,\n  syncAttribute,\n  syncBusinessEntities,\n  syncDataCategories,\n  syncConsentManager,\n  syncCookies,\n  syncDataFlows,\n  syncDataSubject,\n  syncDataSiloDependencies,\n  syncEnricher,\n  syncIdentifier,\n  syncIntlMessages,\n  syncPartitions,\n  syncPolicies,\n  syncPrivacyCenter,\n  syncProcessingActivities,\n  syncProcessingPurposes,\n  syncConsentWorkflowTriggers,\n  syncWorkflowConfigs,\n  syncPreferenceOptionValues,\n  syncPurposes,\n  syncPreferenceTopics,\n  syncTeams,\n  syncTemplate,\n  syncVendors,\n  type DependedOnDataSiloInput,\n  type Identifier,\n} from '@transcend-io/sdk';\nimport { map, type Logger, type SyncError, type SyncResult } from '@transcend-io/utils';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\n\n/* eslint-disable max-lines */\nimport { TranscendInput } from '../../codecs.js';\nimport { logger } from '../../logger.js';\nimport { validatePreferenceManagementSlugs } from '../preference-management/validatePreferenceManagementSlugs.js';\nimport { ensureAllDataSubjectsExist } from './ensureAllDataSubjectsExist.js';\nimport { normalizeDeletionDependencies } from './normalizeDeletionDependencies.js';\nimport { syncDataSilos } from './syncDataSilos.js';\n\nconst CONCURRENCY = 10;\n\n/**\n * Sync the yaml input back to Transcend using the GraphQL APIs\n *\n * @param input - The yml input\n * @param client - GraphQL client\n * @param pageSize - Page size\n * @returns Structured sync result with per-resource errors\n */\nexport async function syncConfigurationToTranscend(\n  input: TranscendInput,\n  client: GraphQLClient,\n  {\n    pageSize = 50,\n    // TODO: https://transcend.height.app/T-23779\n    publishToPrivacyCenter = true,\n    classifyService = false,\n    deleteExtraAttributeValues = false,\n    logger: syncLogger,\n    warnings = [],\n  }: {\n    /** Page size */\n    pageSize?: number;\n    /** When true, skip publishing to privacy center */\n    publishToPrivacyCenter?: boolean;\n    /** When true, delete any attributes being synced up */\n    deleteExtraAttributeValues?: boolean;\n    /** classify data flow service if missing */\n    classifyService?: boolean;\n    /** Optional logger (e.g. collecting logger for MCP debug responses) */\n    logger?: Logger;\n    /** Non-fatal warnings to include in the result */\n    warnings?: string[];\n  },\n): Promise<SyncResult> {\n  const activeLogger = syncLogger ?? logger;\n  const errors: SyncError[] = [];\n  let encounteredError = false;\n\n  const recordError = (resource: string, message: string, item?: string): void => {\n    errors.push({ resource, item, message });\n    encounteredError = true;\n  };\n\n  activeLogger.info(colors.magenta(`Fetching data with page size ${pageSize}...`));\n\n  const {\n    templates,\n    attributes,\n    actions,\n    identifiers,\n    'data-subjects': dataSubjects,\n    'business-entities': businessEntities,\n    enrichers,\n    cookies,\n    'consent-manager': consentManager,\n    'data-silos': dataSilos,\n    'data-flows': dataFlows,\n    vendors,\n    'data-categories': dataCategories,\n    'processing-activities': processingActivities,\n    'processing-purposes': processingPurposes,\n    'action-items': actionItems,\n    'action-item-collections': actionItemCollections,\n    teams,\n    'privacy-center': privacyCenter,\n    messages,\n    policies,\n    partitions,\n    'preference-workflow-configs': preferenceWorkflowConfigs,\n    'workflow-configs': workflowConfigs,\n  } = input;\n\n  const preferenceOptions = input['preference-options'];\n  const purposes = input.purposes;\n\n  const preferenceSlugErrors = validatePreferenceManagementSlugs(input);\n  if (preferenceSlugErrors.length > 0) {\n    for (const message of preferenceSlugErrors) {\n      recordError('preference-slugs', message);\n    }\n    return {\n      success: false,\n      errors,\n      warnings: warnings.length > 0 ? warnings : undefined,\n    };\n  }\n\n  const [identifierByName, dataSubjectsByName, apiKeyTitleMap] = await Promise.all([\n    // Ensure all identifiers are created and create a map from name -> identifier.id\n    enrichers || identifiers\n      ? fetchIdentifiersAndCreateMissing(client, {\n          input,\n          skipPublish: !publishToPrivacyCenter,\n          logger,\n        })\n      : ({} as { [k in string]: Identifier }),\n    // Grab all data subjects in the organization\n    dataSilos || dataSubjects || enrichers || processingActivities\n      ? ensureAllDataSubjectsExist(input, client)\n      : {},\n    // Grab API keys\n    dataSilos &&\n    dataSilos\n      .map((dataSilo) => dataSilo['api-key-title'] || [])\n      .reduce((acc, lst) => acc + lst.length, 0) > 0\n      ? fetchApiKeys(client, { apiKeyInputs: input, logger })\n      : {},\n  ]);\n\n  if (preferenceWorkflowConfigs?.length) {\n    const preferenceWorkflowConfigsSuccess = await syncConsentWorkflowTriggers(\n      client,\n      preferenceWorkflowConfigs,\n      {\n        logger: activeLogger,\n        pageSize,\n      },\n    );\n    if (!preferenceWorkflowConfigsSuccess) {\n      recordError('preference-workflow-configs', 'Failed to sync preference workflow configs');\n    }\n  }\n\n  if (workflowConfigs?.length) {\n    const workflowConfigsSuccess = await syncWorkflowConfigs(client, workflowConfigs, {\n      logger: activeLogger,\n    });\n    if (!workflowConfigsSuccess) {\n      recordError('workflow-configs', 'Failed to sync workflow configs');\n    }\n  }\n\n  if (preferenceOptions?.length) {\n    const preferenceOptionsSuccess = await syncPreferenceOptionValues(client, preferenceOptions, {\n      logger: activeLogger,\n    });\n    if (!preferenceOptionsSuccess) {\n      recordError('preference-options', 'Failed to sync preference option values');\n    }\n  }\n\n  // Sync consent purposes and their nested preference topics.\n  // Order matters: option values (above) exist first, then purposes, then topics\n  // (which link to their purpose by ID and to option values by slug).\n  if (purposes?.length) {\n    const { success: purposesSuccess, purposeIdByTrackingType } = await syncPurposes(\n      client,\n      purposes,\n      { logger: activeLogger },\n    );\n    if (!purposesSuccess) {\n      recordError('purposes', 'Failed to sync one or more purposes');\n    }\n\n    const topics = purposes.flatMap((purpose) =>\n      (purpose['preference-topics'] ?? []).map((topic) => ({\n        ...topic,\n        'tracking-type': purpose.trackingType,\n      })),\n    );\n    if (topics.length > 0) {\n      const topicsSuccess = await syncPreferenceTopics(client, topics, {\n        logger: activeLogger,\n        purposeIdByTrackingType,\n      });\n      if (!topicsSuccess) {\n        recordError('preference-topics', 'Failed to sync one or more preference topics');\n      }\n    }\n  }\n\n  // Sync consent manager\n  if (consentManager) {\n    activeLogger.info(colors.magenta('Syncing consent manager...'));\n    try {\n      await syncConsentManager(client, consentManager, { logger: activeLogger });\n      activeLogger.info(colors.green('Successfully synced consent manager!'));\n    } catch (err) {\n      recordError('consent-manager', (err as Error).message);\n      activeLogger.error(colors.red(`Failed to sync consent manager! - ${(err as Error).message}`));\n    }\n  }\n\n  if (teams) {\n    const teamsSuccess = await syncTeams(client, teams, { logger });\n    encounteredError = encounteredError || !teamsSuccess;\n  }\n\n  // Sync email templates\n  if (templates) {\n    logger.info(colors.magenta(`Syncing \"${templates.length}\" email templates...`));\n    await map(\n      templates,\n      async (template) => {\n        logger.info(colors.magenta(`Syncing template \"${template.title}\"...`));\n        try {\n          await syncTemplate(client, template, { logger });\n          logger.info(colors.green(`Successfully synced template \"${template.title}\"!`));\n        } catch (err) {\n          encounteredError = true;\n          logger.error(colors.red(`Failed to sync template \"${template.title}\"! - ${err.message}`));\n        }\n      },\n      {\n        concurrency: CONCURRENCY,\n      },\n    );\n    logger.info(colors.green(`Synced \"${templates.length}\" email templates!`));\n  }\n\n  // Sync business entities\n  if (businessEntities) {\n    const businessEntitySuccess = await syncBusinessEntities(client, businessEntities, { logger });\n    encounteredError = encounteredError || !businessEntitySuccess;\n  }\n\n  // Sync vendors\n  if (vendors) {\n    const vendorsSuccess = await syncVendors(client, vendors, { logger });\n    encounteredError = encounteredError || !vendorsSuccess;\n  }\n\n  // Sync data categories\n  if (dataCategories) {\n    const dataCategoriesSuccess = await syncDataCategories(client, dataCategories, { logger });\n    encounteredError = encounteredError || !dataCategoriesSuccess;\n  }\n\n  // Sync processing purposes\n  if (processingPurposes) {\n    const processingPurposesSuccess = await syncProcessingPurposes(client, processingPurposes, {\n      logger,\n    });\n    encounteredError = encounteredError || !processingPurposesSuccess;\n  }\n\n  // Sync partitions\n  if (partitions) {\n    const partitionsSuccess = await syncPartitions(client, partitions, { logger });\n    encounteredError = encounteredError || !partitionsSuccess;\n  }\n\n  // Sync cookies\n  if (cookies) {\n    const cookiesSuccess = await syncCookies(client, cookies, { logger });\n    encounteredError = encounteredError || !cookiesSuccess;\n  }\n\n  // Sync action item collections\n  if (actionItemCollections) {\n    const actionItemCollectionsSuccess = await syncActionItemCollections(\n      client,\n      actionItemCollections,\n      { logger },\n    );\n    encounteredError = encounteredError || !actionItemCollectionsSuccess;\n  }\n\n  // Sync attributes\n  if (attributes) {\n    // Fetch existing\n    logger.info(colors.magenta(`Syncing \"${attributes.length}\" attributes...`));\n    const existingAttributes = await fetchAllAttributes(client, { logger });\n    await map(\n      attributes,\n      async (attribute) => {\n        const existing = existingAttributes.find((attr) => attr.name === attribute.name);\n\n        logger.info(colors.magenta(`Syncing attribute \"${attribute.name}\"...`));\n        try {\n          await syncAttribute(client, attribute, {\n            existingAttribute: existing,\n            deleteExtraAttributeValues,\n            logger,\n          });\n          logger.info(colors.green(`Successfully synced attribute \"${attribute.name}\"!`));\n        } catch (err) {\n          encounteredError = true;\n          logger.error(\n            colors.red(`Failed to sync attribute \"${attribute.name}\"! - ${err.message}`),\n          );\n        }\n      },\n      {\n        concurrency: CONCURRENCY,\n      },\n    );\n    logger.info(colors.green(`Synced \"${attributes.length}\" attributes!`));\n  }\n\n  // Sync action items\n  if (actionItems) {\n    const actionItemsSuccess = await syncActionItems(client, actionItems, { logger });\n    encounteredError = encounteredError || !actionItemsSuccess;\n  }\n\n  // Sync enrichers\n  if (enrichers) {\n    logger.info(colors.magenta(`Syncing \"${enrichers.length}\" enrichers...`));\n    await map(\n      enrichers,\n      async (enricher) => {\n        logger.info(colors.magenta(`Syncing enricher \"${enricher.title}\"...`));\n        try {\n          await syncEnricher(client, {\n            input: enricher,\n            identifierByName,\n            dataSubjectsByName,\n            logger,\n          });\n          logger.info(colors.green(`Successfully synced enricher \"${enricher.title}\"!`));\n        } catch (err) {\n          encounteredError = true;\n          logger.error(colors.red(`Failed to sync enricher \"${enricher.title}\"! - ${err.message}`));\n        }\n      },\n      {\n        concurrency: CONCURRENCY,\n      },\n    );\n    logger.info(colors.green(`Synced \"${enrichers.length}\" enrichers!`));\n  }\n\n  // Sync identifiers\n  if (identifiers) {\n    // Fetch existing\n    logger.info(colors.magenta(`Syncing \"${identifiers.length}\" identifiers...`));\n    await map(\n      identifiers,\n      async (identifier) => {\n        const existing = identifierByName[identifier.name];\n        if (!existing) {\n          throw new Error(\n            `Failed to find identifier with name: ${identifier.type}. Should have been auto-created by cli.`,\n          );\n        }\n\n        logger.info(colors.magenta(`Syncing identifier \"${identifier.type}\"...`));\n        try {\n          await syncIdentifier(client, {\n            input: identifier,\n            dataSubjectsByName,\n            identifierId: existing.id,\n            skipPublish: !publishToPrivacyCenter,\n            logger,\n          });\n          logger.info(colors.green(`Successfully synced identifier \"${identifier.type}\"!`));\n        } catch (err) {\n          encounteredError = true;\n          logger.info(\n            colors.red(`Failed to sync identifier \"${identifier.type}\"! - ${err.message}`),\n          );\n        }\n      },\n      {\n        concurrency: CONCURRENCY,\n      },\n    );\n    logger.info(colors.green(`Synced \"${identifiers.length}\" identifiers!`));\n  }\n\n  // Sync actions\n  if (actions) {\n    // Fetch existing\n    logger.info(colors.magenta(`Syncing \"${actions.length}\" actions...`));\n    const existingActions = await fetchAllActions(client, { logger });\n    await map(\n      actions,\n      async (action) => {\n        const existing = existingActions.find((act) => act.type === action.type);\n        if (!existing) {\n          throw new Error(\n            `Failed to find action with type: ${action.type}. Should have already existing in the organization.`,\n          );\n        }\n\n        logger.info(colors.magenta(`Syncing action \"${action.type}\"...`));\n        try {\n          await syncAction(\n            client,\n            {\n              action,\n              actionId: existing.id,\n              skipPublish: !publishToPrivacyCenter,\n            },\n            { logger },\n          );\n          logger.info(colors.green(`Successfully synced action \"${action.type}\"!`));\n        } catch (err) {\n          encounteredError = true;\n          logger.error(colors.red(`Failed to sync action \"${action.type}\"! - ${err.message}`));\n        }\n      },\n      {\n        concurrency: CONCURRENCY,\n      },\n    );\n    logger.info(colors.green(`Synced \"${actions.length}\" actions!`));\n  }\n\n  // Sync data subjects\n  if (dataSubjects) {\n    // Fetch existing\n    logger.info(colors.magenta(`Syncing \"${dataSubjects.length}\" data subjects...`));\n    const existingDataSubjects = await fetchAllDataSubjects(client, { logger });\n    await map(\n      dataSubjects,\n      async (dataSubject) => {\n        const existing = existingDataSubjects.find((subj) => subj.type === dataSubject.type);\n        if (!existing) {\n          throw new Error(\n            `Failed to find data subject with type: ${dataSubject.type}. Should have already existing in the organization.`,\n          );\n        }\n\n        logger.info(colors.magenta(`Syncing data subject \"${dataSubject.type}\"...`));\n        try {\n          await syncDataSubject(client, {\n            input: dataSubject,\n            dataSubjectId: existing.id,\n            skipPublish: !publishToPrivacyCenter,\n            logger,\n          });\n          logger.info(colors.green(`Successfully synced data subject \"${dataSubject.type}\"!`));\n        } catch (err) {\n          encounteredError = true;\n          // supportsAuthorizedAgent is gated on the Authorized Agents feature being\n          // enabled for the organization; surface a clearer hint than the raw API error\n          const hint =\n            dataSubject.supportsAuthorizedAgent !== undefined &&\n            /authorized.agent/i.test(err.message)\n              ? ' (enable the Authorized Agents feature for this organization before setting \"supportsAuthorizedAgent\")'\n              : '';\n          logger.info(\n            colors.red(\n              `Failed to sync data subject \"${dataSubject.type}\"! - ${err.message}${hint}`,\n            ),\n          );\n        }\n      },\n      {\n        concurrency: CONCURRENCY,\n      },\n    );\n    logger.info(colors.green(`Synced \"${dataSubjects.length}\" data subjects!`));\n  }\n\n  // Sync data flows\n  if (dataFlows) {\n    const syncedDataFlows = await syncDataFlows(client, dataFlows, { classifyService, logger });\n    encounteredError = encounteredError || !syncedDataFlows;\n  }\n\n  // Sync privacy center\n  if (privacyCenter) {\n    try {\n      const privacyCenterSuccess = await syncPrivacyCenter(client, privacyCenter, {\n        logger,\n        skipPublish: !publishToPrivacyCenter,\n      });\n      if (!privacyCenterSuccess) {\n        recordError('privacy-center', 'Failed to sync privacy center');\n      }\n    } catch (err) {\n      recordError('privacy-center', (err as Error).message);\n    }\n  }\n\n  // Sync messages\n  if (messages) {\n    const messagesSuccess = await syncIntlMessages(client, messages, { logger });\n    encounteredError = encounteredError || !messagesSuccess;\n  }\n\n  // Sync policies\n  if (policies) {\n    const policiesSuccess = await syncPolicies(client, policies, { logger });\n    encounteredError = encounteredError || !policiesSuccess;\n  }\n\n  // Store dependency updates\n  const dependencyUpdates: [string, DependedOnDataSiloInput[]][] = [];\n  // Sync data silos\n  if (dataSilos) {\n    const { success, dataSiloTitleToId } = await syncDataSilos(dataSilos, client, {\n      dataSubjectsByName,\n      apiKeysByTitle: apiKeyTitleMap,\n      pageSize,\n    });\n    dataSilos?.forEach((dataSilo) => {\n      // Queue up dependency update\n      const dependencies = dataSilo['deletion-dependencies'];\n      if (dependencies) {\n        try {\n          dependencyUpdates.push([\n            dataSiloTitleToId[dataSilo.title],\n            normalizeDeletionDependencies(dependencies, dataSilo.title),\n          ]);\n        } catch (err) {\n          recordError('data-silos', (err as Error).message, dataSilo.title);\n          activeLogger.error(colors.red((err as Error).message));\n        }\n      }\n    });\n    encounteredError = encounteredError || !success;\n  }\n\n  // Dependencies updated at the end after all data silos are created\n  if (dependencyUpdates.length > 0) {\n    const dependenciesSuccess = await syncDataSiloDependencies(client, {\n      input: dependencyUpdates,\n      logger,\n    });\n    encounteredError = encounteredError || !dependenciesSuccess;\n  }\n\n  // Update processing activities\n  if (processingActivities) {\n    const processingActivitySuccess = await syncProcessingActivities(client, processingActivities, {\n      logger,\n    });\n    encounteredError = encounteredError || !processingActivitySuccess;\n  }\n\n  if (publishToPrivacyCenter) {\n    // TODO: https://transcend.height.app/T-23779\n  }\n\n  return {\n    success: !encounteredError,\n    errors,\n    warnings: warnings.length > 0 ? warnings : undefined,\n  };\n}\n/* eslint-enable max-lines */\n","import { getEntries } from '@transcend-io/type-utils';\n\nimport { TranscendInput } from '../codecs.js';\n\n/**\n * Combine a set of TranscendInput yaml files into a single yaml\n *\n * @param base - Base input\n * @param inputs - The list of inputs\n * @returns Merged input\n */\nexport function mergeTranscendInputs(\n  base: TranscendInput,\n  ...inputs: TranscendInput[]\n): TranscendInput {\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  const cloned: any = JSON.parse(JSON.stringify(base));\n  inputs.forEach((input) => {\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    getEntries(input).forEach(([key, value]: [any, any]) => {\n      if (cloned[key] === undefined) {\n        cloned[key] = value;\n      } else if (Array.isArray(value)) {\n        cloned[key] = [...cloned[key], ...value];\n      } else {\n        cloned[key] = value;\n      }\n    });\n  });\n  return cloned;\n}\n"],"mappings":"yvCAGA,MAAa,EAAwB,cAQrC,SAAgB,GAAkC,EAAiC,CACjF,IAAM,EAAmB,EAAE,CAErB,GAAgB,EAAc,IAA0B,CACvD,EAAsB,KAAK,EAAK,EACnC,EAAO,KACL,GAAG,EAAQ,UAAU,EAAK,sNAG3B,EAIL,IAAK,IAAM,KAAU,EAAM,uBAAyB,EAAE,CACpD,EAAa,EAAO,KAAM,qBAAqB,CAGjD,IAAK,IAAM,KAAW,EAAM,UAAY,EAAE,CACxC,IAAK,IAAM,KAAS,EAAQ,sBAAwB,EAAE,CAAE,CACtD,EAAa,EAAM,KAAM,oBAAoB,EAAM,MAAM,IAAI,CAC7D,IAAK,IAAM,KAAU,EAAM,SAAW,EAAE,CACtC,EAAa,EAAO,KAAM,oBAAoB,EAAM,MAAM,YAAY,EAAO,MAAM,IAAI,CAK7F,OAAO,ECrBT,eAAsB,EACpB,CACE,aAAc,EAAY,EAAE,CAC5B,gBAAiB,EAAe,EAAE,CAClC,wBAAyB,EAAuB,EAAE,CAClD,YAAY,EAAE,EAEhB,EACA,EAAW,GACiC,CAC5C,IAAM,EAAuB,EAAK,CAChC,GAAG,EAAQ,EAAU,IAAK,GAAS,EAAK,kBAAoB,EAAE,CAAC,EAAI,EAAE,CAAC,CACtE,GAAG,EAAQ,EAAqB,KAAK,CAAE,sBAAuB,GAAoB,EAAE,CAAC,EAAI,EAAE,CAAC,CAC5F,GAAG,EAAQ,EAAU,IAAK,GAAa,EAAS,kBAAoB,EAAE,CAAC,EAAI,EAAE,CAAC,CAC9E,GAAG,EAAa,IAAK,GAAY,EAAQ,KAAK,CAC/C,CAAC,CACF,GAAI,EAAqB,SAAW,GAAK,CAAC,EACxC,MAAO,EAAE,CAGX,IAAM,EAAmB,MAAM,EAAqB,EAAQ,CAAE,SAAQ,CAAC,CACjE,EAAoB,EAAM,EAAkB,OAAO,CAEnD,EAAsB,EAC1B,EACA,EAAiB,KAAK,CAAE,UAAW,EAAK,CACzC,CAED,GAAI,EAAoB,OAAS,EAAG,CAClC,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAoB,OAAO,uBAAuB,CAAC,CAC1F,IAAK,IAAM,KAAmB,EAAqB,CACjD,EAAO,KAAK,EAAO,QAAQ,yBAAyB,EAAgB,KAAK,CAAC,CAC1E,IAAM,EAAU,MAAM,EAAkB,EAAQ,CAAE,MAAO,EAAiB,SAAQ,CAAC,CACnF,EAAO,KAAK,EAAO,MAAM,wBAAwB,EAAgB,GAAG,CAAC,CACrE,EAAkB,GAAmB,GAIzC,OAAO,ECrCT,SAAgB,GACd,EACA,EAC2B,CAC3B,GAAI,EAAa,SAAW,EAC1B,MAAO,EAAE,CAIX,GAAI,OAAO,EAAa,IAAO,SAC7B,MAAO,CAAC,CAAE,OAAQ,EAAK,EAAyB,CAAE,CAAC,CAGrD,IAAI,EACE,EAA+C,EAAE,CACjD,EAAgB,IAAI,IASpB,GACJ,EACA,IACS,CACT,GAAI,EAAc,IAAI,EAAS,CAC7B,MAAU,MACR,cAAc,EAAc,6DACtB,EAAS,sCAChB,CAEH,EAAc,IAAI,EAAS,CAC3B,EAAkB,KAAK,CAAE,2BAA4B,EAAU,GAAG,EAAU,CAAC,EAkC/E,OA/BC,EAA2C,QAAS,GAAe,CAGlE,GAAI,oBAAqB,GAAc,WAAY,EACjD,MAAU,MACR,cAAc,EAAc,oDACtB,EAAW,SAAS,mMAG3B,CAGH,GAAI,oBAAqB,EAAY,CACnC,EAAoB,EAAW,SAAU,CAAE,cAAe,GAAM,CAAC,CACjE,OAGF,GAAI,EAAW,SAAU,CACvB,EAAoB,EAAW,SAAU,CAAE,OAAQ,EAAW,OAAQ,CAAC,CACvE,OAGF,GAAI,IAAiB,IAAA,GACnB,MAAU,MACR,cAAc,EAAc,8GAE7B,CAEH,EAAe,EAAW,QAC1B,CAEK,CACL,GAAI,IAAiB,IAAA,GAA+C,EAAE,CAArC,CAAC,CAAE,OAAQ,EAAK,EAAa,CAAE,CAAC,CACjE,GAAG,EACJ,CCzDH,eAAsB,EACpB,EACA,EACA,CACE,WACA,qBACA,kBAcD,CACD,IAAI,EAAmB,GAGjB,EAAK,IAAI,MAAM,CAAC,SAAS,CAC/B,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAU,OAAO,iBAAiB,CAAC,CAU1E,IAAM,EAA0B,EAAsC,MAPtC,EAAkB,EAAQ,CACxD,OAAQ,EAAU,KAAK,CAAE,WAAY,EAAM,CAC3C,WACA,SACD,CAAC,CAGuF,QAAQ,CAG3F,EAAoB,EAAU,QAAQ,CAAE,WAAY,CAAC,EAAwB,GAAO,CACtF,EAAkB,OAAS,IAC7B,EAAO,KACL,EAAO,QAAQ,aAAa,EAAkB,OAAO,oCAAoC,CAC1F,CAID,MAAM,EADU,EAAM,EAAmB,GAClB,CAAE,KAAO,IAA0B,CACxD,GAAM,CACJ,gBAAiB,CAAE,cACjB,MAAM,EAMP,EAAQ,EAAmB,CAC5B,UAAW,CACT,MAAO,EAAsB,IAAK,IAAW,CAC3C,KAAM,EAAM,eAAiB,EAAM,gBACnC,MAAO,EAAM,MACb,QAAS,EAAM,QACf,mBAAoB,EAAM,mBAC1B,SAAU,EAAM,aACjB,EAAE,CACJ,CACD,SACD,CAAC,CAGF,EAAU,QAAS,GAAS,CAC1B,EAAwB,EAAK,OAAS,GACtC,EACF,CAEF,EAAO,KAAK,EAAO,MAAM,yBAAyB,EAAkB,OAAO,eAAe,CAAC,EAI7F,IAAM,EAAiB,EAAM,EAAW,GAAkB,CAC1D,MAAM,EAAU,EAAgB,MAAO,EAAqB,IAAQ,CAClE,EAAO,KACL,EAAO,QACL,UAAU,EAAM,EAAE,GAAG,EAAe,OAAO,aACzC,EAAoB,OACrB,cACF,CACF,CACD,MAAM,EAMH,EAAQ,EAAmB,CAC5B,UAAW,CACT,MAAO,CACL,UAAW,EAAoB,IAAK,IAAW,CAC7C,GAAI,EAAwB,EAAM,OAAO,GACzC,QAAS,EAAM,QACf,mBAAoB,EAAM,mBAC1B,IAAK,EAAM,IACX,QAAS,EAAM,QACf,YAAa,EAAM,YACnB,YAAa,EAAM,iBACnB,OAAQ,CAAC,EAAM,SACf,YAAa,EAAM,OACnB,UAAW,EAAM,MAGjB,oBAAqB,EAAM,yBAA2B,IAAA,GAAY,CAAC,CAAE,OAAQ,EAAE,CAAE,CAAC,CAClF,SAAU,EAAM,iBACZ,EAAe,EAAM,kBAAkB,GACvC,IAAA,GACJ,wBAAyB,EAAM,iBAC3B,EAA8B,EAAM,iBAAkB,EAAmB,CACzE,IAAA,GACJ,WAAY,EAAM,WAClB,qBAAsB,EAAM,qBAC5B,SAAU,EAAM,aAEhB,mBAAoB,EAAM,oBAAoB,wBAC9C,gCAAiC,EAAM,oBAAoB,kBAC3D,2BAA4B,EAAM,oBAAoB,aACtD,+CACE,EAAM,oBAAoB,kCAC5B,qCAAsC,EAAM,oBAAoB,wBAChE,yBAA0B,EAAM,oBAAoB,+BACrD,EAAE,CACJ,CACF,CACD,SACD,CAAC,CACF,EAAO,KACL,EAAO,MACL,UAAU,EAAM,EAAE,GAAG,EAAe,OAAO,YACzC,EAAoB,OACrB,eACF,CACF,EACD,CAKF,IAAM,EAAc,IAAI,EAAY,UAAU,EAAE,CAAE,EAAY,QAAQ,eAAe,CAC/E,EAA0B,EAAU,QAAQ,CAAE,aAAa,EAAE,IAAO,EAAW,OAAS,EAAE,CAC1F,EAAkB,EACrB,KAAK,CAAE,aAAa,EAAE,IAAO,EAAW,OAAO,CAC/C,QAAQ,EAAK,IAAU,EAAM,EAAO,EAAE,CACzC,EAAO,KACL,EAAO,QACL,YAAY,EAAgB,qBAAqB,EAAwB,OAAO,iBACjF,CACF,CACD,EAAY,MAAM,EAAiB,EAAE,CACrC,IAAI,EAAQ,EAEZ,MAAM,EACJ,EACA,MAAO,CAAE,aAAY,WAAY,CAC3B,GACF,MAAM,EAAU,EAAY,KAAO,IAAc,CAC/C,IAAM,EAAS,EAAU,OACrB,EAAU,OAAO,KACd,CAAE,MAAK,cAAa,aAAY,WAAU,aAAY,GAAG,MAEvD,CACC,KAAM,EACN,cACA,WAAa,EAET,EAAW,IAAK,IAAc,CAC5B,GAAG,EACH,KAAM,EAAS,MAAQ,QACxB,EAAE,CAJH,IAAA,GAKJ,SAAW,EAEP,EAAS,IAAK,IAAa,CACzB,GAAG,EACH,KAAM,EAAQ,MAAQ,QACvB,EAAE,CAJH,IAAA,GAKJ,aACA,+BAAgC,EAAK,qCACrC,+BAAgC,EAAK,qCACtC,EACJ,CACD,IAAA,GAEE,EAAU,CACd,WAAY,EAAwB,GAAO,GAC3C,KAAM,EAAU,KAChB,KAAM,EAAU,IAChB,MAAO,EAAU,MACjB,YAAa,EAAU,YACvB,GAAI,EAAU,OACV,CACE,YAAa,EAAU,OACxB,CACD,EAAE,CACN,GAAI,EAAU,MACV,CACE,UAAW,EAAU,MACtB,CACD,EAAE,CACN,GAAI,EAAU,uBACV,CAAE,kBAAmB,EAAU,uBAAwB,CACvD,EAAE,CACN,iBAAmB,EAAU,0BAEzB,OAAO,QAAQ,EAAU,0BAA0B,CAAC,KAAK,CAAC,EAAK,MAAY,CACzE,YAAa,EACb,eAAgB,EACjB,EAAE,CAJH,IAAA,GAKJ,eAAgB,EAAU,oBAAsB,EAAE,CAClD,cAAe,EAChB,CAGK,GAAyB,EAAQ,eAAiB,EAAE,EAAE,KAAK,CAAE,UAAW,EAAK,CAC7E,EAAsB,EAAsB,QAC/C,EAAM,IAAU,EAAsB,QAAQ,EAAK,GAAK,EAC1D,CACD,GAAI,EAAoB,OAAS,EAC/B,EAAO,KACL,EAAO,IACL,8BACE,EAAU,IACX,6DAA6D,EAAoB,KAChF;EACD,GACF,CACF,CACD,EAAmB,QAEnB,GAAI,CACF,MAAM,EAAmB,EAAQ,EAA6B,CAC5D,UAAW,EACX,SACD,CAAC,OACK,EAAK,CACZ,EAAO,KACL,EAAO,IACL,iCAAiC,EAAU,IAAI,mBAAmB,EAAM,SAAS,EAAI,UACtF,CACF,CACD,EAAmB,GAGvB,GAAS,EACT,EAAY,OAAO,EAAM,EACzB,EAGN,CACE,YAAa,GACd,CACF,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SACF,CAAG,EASvB,OAPA,EAAO,KACL,EAAO,MACL,WAAW,EAAU,OAAO,oBAAoB,EAAgB,mBAC9D,EAAY,IACb,YACF,CACF,CACM,CACL,QAAS,CAAC,EACV,kBAAmB,EAAM,GAA0B,CAAE,QAAS,EAAG,CAClE,CCtPH,eAAsB,EACpB,EACA,EACA,CACE,WAAW,GAEX,yBAAyB,GACzB,kBAAkB,GAClB,6BAA6B,GAC7B,OAAQ,EACR,WAAW,EAAE,EAeM,CACrB,IAAM,EAAe,GAAc,EAC7B,EAAsB,EAAE,CAC1B,EAAmB,GAEjB,GAAe,EAAkB,EAAiB,IAAwB,CAC9E,EAAO,KAAK,CAAE,WAAU,OAAM,UAAS,CAAC,CACxC,EAAmB,IAGrB,EAAa,KAAK,EAAO,QAAQ,gCAAgC,EAAS,KAAK,CAAC,CAEhF,GAAM,CACJ,YACA,aACA,UACA,cACA,gBAAiB,EACjB,oBAAqB,EACrB,YACA,UACA,kBAAmB,EACnB,aAAc,EACd,aAAc,EACd,UACA,kBAAmB,EACnB,wBAAyB,EACzB,sBAAuB,EACvB,eAAgB,EAChB,0BAA2B,EAC3B,QACA,iBAAkB,EAClB,WACA,WACA,aACA,8BAA+B,GAC/B,mBAAoB,GAClB,EAEE,GAAoB,EAAM,sBAC1B,EAAW,EAAM,SAEjB,GAAuB,GAAkC,EAAM,CACrE,GAAI,GAAqB,OAAS,EAAG,CACnC,IAAK,IAAM,KAAW,GACpB,EAAY,mBAAoB,EAAQ,CAE1C,MAAO,CACL,QAAS,GACT,SACA,SAAU,EAAS,OAAS,EAAI,EAAW,IAAA,GAC5C,CAGH,GAAM,CAAC,EAAkB,EAAoB,IAAkB,MAAM,QAAQ,IAAI,CAE/E,GAAa,EACT,EAAiC,EAAQ,CACvC,QACA,YAAa,CAAC,EACd,SACD,CAAC,CACD,EAAE,CAEP,GAAa,GAAgB,GAAa,EACtC,EAA2B,EAAO,EAAO,CACzC,EAAE,CAEN,GACA,EACG,IAAK,GAAa,EAAS,kBAAoB,EAAE,CAAC,CAClD,QAAQ,EAAK,IAAQ,EAAM,EAAI,OAAQ,EAAE,CAAG,EAC3C,EAAa,EAAQ,CAAE,aAAc,EAAO,SAAQ,CAAC,CACrD,EAAE,CACP,CAAC,CAqCF,GAnCI,IAA2B,SASxB,MAR0C,GAC7C,EACA,GACA,CACE,OAAQ,EACR,WACD,CACF,EAEC,EAAY,8BAA+B,6CAA6C,EAIxF,GAAiB,SAId,MAHgC,GAAoB,EAAQ,EAAiB,CAChF,OAAQ,EACT,CAAC,EAEA,EAAY,mBAAoB,kCAAkC,EAIlE,IAAmB,SAIhB,MAHkC,GAA2B,EAAQ,GAAmB,CAC3F,OAAQ,EACT,CAAC,EAEA,EAAY,qBAAsB,0CAA0C,EAO5E,GAAU,OAAQ,CACpB,GAAM,CAAE,QAAS,EAAiB,2BAA4B,MAAM,GAClE,EACA,EACA,CAAE,OAAQ,EAAc,CACzB,CACI,GACH,EAAY,WAAY,sCAAsC,CAGhE,IAAM,EAAS,EAAS,QAAS,IAC9B,EAAQ,sBAAwB,EAAE,EAAE,IAAK,IAAW,CACnD,GAAG,EACH,gBAAiB,EAAQ,aAC1B,EAAE,CACJ,CACG,EAAO,OAAS,IAKb,MAJuB,GAAqB,EAAQ,EAAQ,CAC/D,OAAQ,EACR,0BACD,CAAC,EAEA,EAAY,oBAAqB,+CAA+C,EAMtF,GAAI,EAAgB,CAClB,EAAa,KAAK,EAAO,QAAQ,6BAA6B,CAAC,CAC/D,GAAI,CACF,MAAM,GAAmB,EAAQ,EAAgB,CAAE,OAAQ,EAAc,CAAC,CAC1E,EAAa,KAAK,EAAO,MAAM,uCAAuC,CAAC,OAChE,EAAK,CACZ,EAAY,kBAAoB,EAAc,QAAQ,CACtD,EAAa,MAAM,EAAO,IAAI,qCAAsC,EAAc,UAAU,CAAC,EAIjG,GAAI,EAAO,CACT,IAAM,EAAe,MAAM,GAAU,EAAQ,EAAO,CAAE,SAAQ,CAAC,CAC/D,IAAuC,CAAC,EA0B1C,GAtBI,IACF,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAU,OAAO,sBAAsB,CAAC,CAC/E,MAAM,EACJ,EACA,KAAO,IAAa,CAClB,EAAO,KAAK,EAAO,QAAQ,qBAAqB,EAAS,MAAM,MAAM,CAAC,CACtE,GAAI,CACF,MAAM,GAAa,EAAQ,EAAU,CAAE,SAAQ,CAAC,CAChD,EAAO,KAAK,EAAO,MAAM,iCAAiC,EAAS,MAAM,IAAI,CAAC,OACvE,EAAK,CACZ,EAAmB,GACnB,EAAO,MAAM,EAAO,IAAI,4BAA4B,EAAS,MAAM,OAAO,EAAI,UAAU,CAAC,GAG7F,CACE,YAAa,GACd,CACF,CACD,EAAO,KAAK,EAAO,MAAM,WAAW,EAAU,OAAO,oBAAoB,CAAC,EAIxE,EAAkB,CACpB,IAAM,EAAwB,MAAM,EAAqB,EAAQ,EAAkB,CAAE,SAAQ,CAAC,CAC9F,IAAuC,CAAC,EAI1C,GAAI,EAAS,CACX,IAAM,EAAiB,MAAM,GAAY,EAAQ,EAAS,CAAE,SAAQ,CAAC,CACrE,IAAuC,CAAC,EAI1C,GAAI,EAAgB,CAClB,IAAM,EAAwB,MAAM,GAAmB,EAAQ,EAAgB,CAAE,SAAQ,CAAC,CAC1F,IAAuC,CAAC,EAI1C,GAAI,EAAoB,CACtB,IAAM,EAA4B,MAAM,GAAuB,EAAQ,EAAoB,CACzF,SACD,CAAC,CACF,IAAuC,CAAC,EAI1C,GAAI,EAAY,CACd,IAAM,EAAoB,MAAM,GAAe,EAAQ,EAAY,CAAE,SAAQ,CAAC,CAC9E,IAAuC,CAAC,EAI1C,GAAI,EAAS,CACX,IAAM,EAAiB,MAAM,GAAY,EAAQ,EAAS,CAAE,SAAQ,CAAC,CACrE,IAAuC,CAAC,EAI1C,GAAI,EAAuB,CACzB,IAAM,EAA+B,MAAM,EACzC,EACA,EACA,CAAE,SAAQ,CACX,CACD,IAAuC,CAAC,EAI1C,GAAI,EAAY,CAEd,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAW,OAAO,iBAAiB,CAAC,CAC3E,IAAM,EAAqB,MAAM,EAAmB,EAAQ,CAAE,SAAQ,CAAC,CACvE,MAAM,EACJ,EACA,KAAO,IAAc,CACnB,IAAM,EAAW,EAAmB,KAAM,GAAS,EAAK,OAAS,EAAU,KAAK,CAEhF,EAAO,KAAK,EAAO,QAAQ,sBAAsB,EAAU,KAAK,MAAM,CAAC,CACvE,GAAI,CACF,MAAM,EAAc,EAAQ,EAAW,CACrC,kBAAmB,EACnB,6BACA,SACD,CAAC,CACF,EAAO,KAAK,EAAO,MAAM,kCAAkC,EAAU,KAAK,IAAI,CAAC,OACxE,EAAK,CACZ,EAAmB,GACnB,EAAO,MACL,EAAO,IAAI,6BAA6B,EAAU,KAAK,OAAO,EAAI,UAAU,CAC7E,GAGL,CACE,YAAa,GACd,CACF,CACD,EAAO,KAAK,EAAO,MAAM,WAAW,EAAW,OAAO,eAAe,CAAC,CAIxE,GAAI,EAAa,CACf,IAAM,EAAqB,MAAM,EAAgB,EAAQ,EAAa,CAAE,SAAQ,CAAC,CACjF,IAAuC,CAAC,EAqE1C,GAjEI,IACF,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAU,OAAO,gBAAgB,CAAC,CACzE,MAAM,EACJ,EACA,KAAO,IAAa,CAClB,EAAO,KAAK,EAAO,QAAQ,qBAAqB,EAAS,MAAM,MAAM,CAAC,CACtE,GAAI,CACF,MAAM,GAAa,EAAQ,CACzB,MAAO,EACP,mBACA,qBACA,SACD,CAAC,CACF,EAAO,KAAK,EAAO,MAAM,iCAAiC,EAAS,MAAM,IAAI,CAAC,OACvE,EAAK,CACZ,EAAmB,GACnB,EAAO,MAAM,EAAO,IAAI,4BAA4B,EAAS,MAAM,OAAO,EAAI,UAAU,CAAC,GAG7F,CACE,YAAa,GACd,CACF,CACD,EAAO,KAAK,EAAO,MAAM,WAAW,EAAU,OAAO,cAAc,CAAC,EAIlE,IAEF,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAY,OAAO,kBAAkB,CAAC,CAC7E,MAAM,EACJ,EACA,KAAO,IAAe,CACpB,IAAM,EAAW,EAAiB,EAAW,MAC7C,GAAI,CAAC,EACH,MAAU,MACR,wCAAwC,EAAW,KAAK,yCACzD,CAGH,EAAO,KAAK,EAAO,QAAQ,uBAAuB,EAAW,KAAK,MAAM,CAAC,CACzE,GAAI,CACF,MAAM,GAAe,EAAQ,CAC3B,MAAO,EACP,qBACA,aAAc,EAAS,GACvB,YAAa,CAAC,EACd,SACD,CAAC,CACF,EAAO,KAAK,EAAO,MAAM,mCAAmC,EAAW,KAAK,IAAI,CAAC,OAC1E,EAAK,CACZ,EAAmB,GACnB,EAAO,KACL,EAAO,IAAI,8BAA8B,EAAW,KAAK,OAAO,EAAI,UAAU,CAC/E,GAGL,CACE,YAAa,GACd,CACF,CACD,EAAO,KAAK,EAAO,MAAM,WAAW,EAAY,OAAO,gBAAgB,CAAC,EAItE,EAAS,CAEX,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAQ,OAAO,cAAc,CAAC,CACrE,IAAM,EAAkB,MAAM,EAAgB,EAAQ,CAAE,SAAQ,CAAC,CACjE,MAAM,EACJ,EACA,KAAO,IAAW,CAChB,IAAM,EAAW,EAAgB,KAAM,GAAQ,EAAI,OAAS,EAAO,KAAK,CACxE,GAAI,CAAC,EACH,MAAU,MACR,oCAAoC,EAAO,KAAK,qDACjD,CAGH,EAAO,KAAK,EAAO,QAAQ,mBAAmB,EAAO,KAAK,MAAM,CAAC,CACjE,GAAI,CACF,MAAM,EACJ,EACA,CACE,SACA,SAAU,EAAS,GACnB,YAAa,CAAC,EACf,CACD,CAAE,SAAQ,CACX,CACD,EAAO,KAAK,EAAO,MAAM,+BAA+B,EAAO,KAAK,IAAI,CAAC,OAClE,EAAK,CACZ,EAAmB,GACnB,EAAO,MAAM,EAAO,IAAI,0BAA0B,EAAO,KAAK,OAAO,EAAI,UAAU,CAAC,GAGxF,CACE,YAAa,GACd,CACF,CACD,EAAO,KAAK,EAAO,MAAM,WAAW,EAAQ,OAAO,YAAY,CAAC,CAIlE,GAAI,EAAc,CAEhB,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAa,OAAO,oBAAoB,CAAC,CAChF,IAAM,EAAuB,MAAM,EAAqB,EAAQ,CAAE,SAAQ,CAAC,CAC3E,MAAM,EACJ,EACA,KAAO,IAAgB,CACrB,IAAM,EAAW,EAAqB,KAAM,GAAS,EAAK,OAAS,EAAY,KAAK,CACpF,GAAI,CAAC,EACH,MAAU,MACR,0CAA0C,EAAY,KAAK,qDAC5D,CAGH,EAAO,KAAK,EAAO,QAAQ,yBAAyB,EAAY,KAAK,MAAM,CAAC,CAC5E,GAAI,CACF,MAAM,GAAgB,EAAQ,CAC5B,MAAO,EACP,cAAe,EAAS,GACxB,YAAa,CAAC,EACd,SACD,CAAC,CACF,EAAO,KAAK,EAAO,MAAM,qCAAqC,EAAY,KAAK,IAAI,CAAC,OAC7E,EAAK,CACZ,EAAmB,GAGnB,IAAM,EACJ,EAAY,0BAA4B,IAAA,IACxC,oBAAoB,KAAK,EAAI,QAAQ,CACjC,yGACA,GACN,EAAO,KACL,EAAO,IACL,gCAAgC,EAAY,KAAK,OAAO,EAAI,UAAU,IACvE,CACF,GAGL,CACE,YAAa,GACd,CACF,CACD,EAAO,KAAK,EAAO,MAAM,WAAW,EAAa,OAAO,kBAAkB,CAAC,CAI7E,GAAI,EAAW,CACb,IAAM,EAAkB,MAAM,GAAc,EAAQ,EAAW,CAAE,kBAAiB,SAAQ,CAAC,CAC3F,IAAuC,CAAC,EAI1C,GAAI,EACF,GAAI,CAKG,MAJ8B,GAAkB,EAAQ,EAAe,CAC1E,SACA,YAAa,CAAC,EACf,CAAC,EAEA,EAAY,iBAAkB,gCAAgC,OAEzD,EAAK,CACZ,EAAY,iBAAmB,EAAc,QAAQ,CAKzD,GAAI,EAAU,CACZ,IAAM,EAAkB,MAAM,GAAiB,EAAQ,EAAU,CAAE,SAAQ,CAAC,CAC5E,IAAuC,CAAC,EAI1C,GAAI,EAAU,CACZ,IAAM,EAAkB,MAAM,GAAa,EAAQ,EAAU,CAAE,SAAQ,CAAC,CACxE,IAAuC,CAAC,EAI1C,IAAM,EAA2D,EAAE,CAEnE,GAAI,EAAW,CACb,GAAM,CAAE,UAAS,qBAAsB,MAAM,EAAc,EAAW,EAAQ,CAC5E,qBACA,eAAgB,GAChB,WACD,CAAC,CACF,GAAW,QAAS,GAAa,CAE/B,IAAM,EAAe,EAAS,yBAC9B,GAAI,EACF,GAAI,CACF,EAAkB,KAAK,CACrB,EAAkB,EAAS,OAC3B,GAA8B,EAAc,EAAS,MAAM,CAC5D,CAAC,OACK,EAAK,CACZ,EAAY,aAAe,EAAc,QAAS,EAAS,MAAM,CACjE,EAAa,MAAM,EAAO,IAAK,EAAc,QAAQ,CAAC,GAG1D,CACF,IAAuC,CAAC,EAI1C,GAAI,EAAkB,OAAS,EAAG,CAChC,IAAM,EAAsB,MAAM,GAAyB,EAAQ,CACjE,MAAO,EACP,SACD,CAAC,CACF,IAAuC,CAAC,EAI1C,GAAI,EAAsB,CACxB,IAAM,EAA4B,MAAM,GAAyB,EAAQ,EAAsB,CAC7F,SACD,CAAC,CACF,IAAuC,CAAC,EAO1C,MAAO,CACL,QAAS,CAAC,EACV,SACA,SAAU,EAAS,OAAS,EAAI,EAAW,IAAA,GAC5C,CC3jBH,SAAgB,EACd,EACA,GAAG,EACa,CAEhB,IAAM,EAAc,KAAK,MAAM,KAAK,UAAU,EAAK,CAAC,CAapD,OAZA,EAAO,QAAS,GAAU,CAExB,EAAW,EAAM,CAAC,SAAS,CAAC,EAAK,KAAuB,CAClD,EAAO,KAAS,IAAA,GAClB,EAAO,GAAO,EACL,MAAM,QAAQ,EAAM,CAC7B,EAAO,GAAO,CAAC,GAAG,EAAO,GAAM,GAAG,EAAM,CAExC,EAAO,GAAO,GAEhB,EACF,CACK"}