{"version":3,"file":"impl-BHwEfpwS.mjs","names":[],"sources":["../src/commands/inventory/push/impl.ts"],"sourcesContent":["import { existsSync, lstatSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport { buildTranscendGraphQLClient } from '@transcend-io/sdk';\nimport { mapSeries } from '@transcend-io/utils';\nimport colors from 'colors';\n\nimport { TranscendInput } from '../../../codecs.js';\nimport { ADMIN_DASH_INTEGRATIONS } from '../../../constants.js';\nimport type { LocalContext } from '../../../context.js';\nimport { validateTranscendAuth, listFiles } from '../../../lib/api-keys/index.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { syncConfigurationToTranscend } from '../../../lib/graphql/index.js';\nimport { parseVariablesFromString } from '../../../lib/helpers/parseVariablesFromString.js';\nimport { mergeTranscendInputs } from '../../../lib/mergeTranscendInputs.js';\nimport { readTranscendYaml } from '../../../lib/readTranscendYaml.js';\nimport { logger } from '../../../logger.js';\n\n/**\n * Sync configuration to Transcend\n *\n * @param options - Options\n * @returns True if synced successfully, false if error occurs\n */\nasync function syncConfiguration({\n  transcendUrl,\n  auth,\n  pageSize,\n  publishToPrivacyCenter,\n  contents,\n  deleteExtraAttributeValues = false,\n  classifyService = false,\n}: {\n  /** Transcend YAML */\n  contents: TranscendInput;\n  /** Transcend URL */\n  transcendUrl: string;\n  /** API key */\n  auth: string;\n  /** Page size */\n  pageSize: number;\n  /** Skip privacy center publish step */\n  publishToPrivacyCenter: boolean;\n  /** classify data flow service if missing */\n  classifyService?: boolean;\n  /** Delete attributes when syncing */\n  deleteExtraAttributeValues?: boolean;\n}): Promise<boolean> {\n  const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n  // Sync to Transcend\n  try {\n    const result = await syncConfigurationToTranscend(contents, client, {\n      pageSize,\n      publishToPrivacyCenter,\n      classifyService,\n      deleteExtraAttributeValues,\n      logger,\n    });\n    if (!result.success) {\n      result.errors.forEach(({ resource, item, message }) => {\n        logger.error(\n          colors.red(`Failed to sync ${resource}${item ? ` \"${item}\"` : ''}: ${message}`),\n        );\n      });\n    }\n    return result.success;\n  } catch (err) {\n    logger.error(colors.red(`An unexpected error occurred syncing the schema: ${err.message}`));\n    return false;\n  }\n}\n\nexport interface PushCommandFlags {\n  auth: string;\n  file: string;\n  transcendUrl: string;\n  pageSize: number;\n  variables: string;\n  publishToPrivacyCenter: boolean;\n  classifyService: boolean;\n  deleteExtraAttributeValues: boolean;\n}\n\nexport async function push(\n  this: LocalContext,\n  {\n    file = './transcend.yml',\n    transcendUrl,\n    auth,\n    variables,\n    pageSize,\n    publishToPrivacyCenter,\n    classifyService,\n    deleteExtraAttributeValues,\n  }: PushCommandFlags,\n): Promise<void> {\n  doneInputValidation(this.process.exit);\n\n  // Parse authentication as API key or path to list of API keys\n  const apiKeyOrList = await validateTranscendAuth(auth);\n\n  // Parse out the variables\n  const vars = parseVariablesFromString(variables);\n\n  // check if we are being passed a list of API keys and a list of files\n  let fileList: string[];\n  if (Array.isArray(apiKeyOrList) && lstatSync(file).isDirectory()) {\n    fileList = listFiles(file).map((filePath) => join(file, filePath));\n  } else {\n    fileList = file.split(',');\n  }\n\n  // Ensure at least one file is parsed\n  if (fileList.length < 1) {\n    throw new Error('No file specified!');\n  }\n\n  // eslint-disable-next-line array-callback-return,consistent-return\n  const transcendInputs = fileList.map((filePath) => {\n    // Ensure yaml file exists on disk\n    if (!existsSync(filePath)) {\n      logger.error(\n        colors.red(\n          `The file path does not exist on disk: ${filePath}. You can specify the filepath using --file=./examples/transcend.yml`,\n        ),\n      );\n      this.process.exit(1);\n    } else {\n      logger.info(colors.magenta(`Reading file \"${filePath}\"...`));\n    }\n\n    try {\n      // Read in the yaml file and validate it's shape\n      const newContents = readTranscendYaml(filePath, vars);\n      logger.info(colors.green(`Successfully read in \"${filePath}\"`));\n      return {\n        content: newContents,\n        name: filePath.split('/').pop()!.replace('.yml', ''),\n      };\n    } catch (err) {\n      logger.error(\n        colors.red(\n          `The shape of your yaml file is invalid with the following errors: ${err.message}`,\n        ),\n      );\n      this.process.exit(1);\n    }\n  });\n\n  // process a single API key\n  if (typeof apiKeyOrList === 'string') {\n    // if passed multiple inputs, merge them together\n    const [base, ...rest] = transcendInputs.map(({ content }) => content);\n    const contents = mergeTranscendInputs(base, ...rest);\n\n    // sync the configuration\n    const success = await syncConfiguration({\n      transcendUrl,\n      auth: apiKeyOrList,\n      contents,\n      publishToPrivacyCenter,\n      deleteExtraAttributeValues,\n      pageSize,\n      classifyService: !!classifyService,\n    });\n\n    // exist with error code\n    if (!success) {\n      logger.info(\n        colors.red(\n          `Sync encountered errors. View output above for more information, or check out ${ADMIN_DASH_INTEGRATIONS}`,\n        ),\n      );\n\n      this.process.exit(1);\n    }\n  } else {\n    // if passed multiple inputs, expect them to be one per instance\n    if (transcendInputs.length !== 1 && transcendInputs.length !== apiKeyOrList.length) {\n      throw new Error(\n        'Expected list of yml files to be equal to the list of API keys.' +\n          `Got ${transcendInputs.length} YML file${\n            transcendInputs.length === 1 ? '' : 's'\n          } and ${apiKeyOrList.length} API key${apiKeyOrList.length === 1 ? '' : 's'}`,\n      );\n    }\n\n    const encounteredErrors: string[] = [];\n    await mapSeries(apiKeyOrList, async (apiKey, ind) => {\n      const prefix = `[${ind + 1}/${apiKeyOrList.length}][${apiKey.organizationName}] `;\n      logger.info(colors.magenta(`~~~\\n\\n${prefix}Attempting to push configuration...\\n\\n~~~`));\n\n      // use the merged contents if 1 yml passed, else use the contents that map to that organization\n      const useContents =\n        transcendInputs.length === 1\n          ? transcendInputs[0].content\n          : transcendInputs.find((input) => input.name === apiKey.organizationName)?.content;\n\n      // Throw error if cannot find a yml file matching that organization name\n      if (!useContents) {\n        logger.error(\n          colors.red(\n            `${prefix}Failed to find transcend.yml file for organization: \"${apiKey.organizationName}\".`,\n          ),\n        );\n        encounteredErrors.push(apiKey.organizationName);\n        return;\n      }\n\n      const success = await syncConfiguration({\n        transcendUrl,\n        auth: apiKey.apiKey,\n        contents: useContents,\n        pageSize,\n        publishToPrivacyCenter,\n        deleteExtraAttributeValues,\n        classifyService,\n      });\n\n      if (success) {\n        logger.info(colors.green(`${prefix}Successfully pushed configuration!`));\n      } else {\n        logger.error(colors.red(`${prefix}Failed to sync configuration.`));\n        encounteredErrors.push(apiKey.organizationName);\n      }\n    });\n\n    if (encounteredErrors.length > 0) {\n      logger.info(\n        colors.red(\n          `Sync encountered errors for \"${encounteredErrors.join(\n            ',',\n          )}\". View output above for more information, or check out ${ADMIN_DASH_INTEGRATIONS}`,\n        ),\n      );\n\n      this.process.exit(1);\n    }\n  }\n\n  // Indicate success\n  logger.info(\n    colors.green(`Successfully synced yaml file to Transcend! View at ${ADMIN_DASH_INTEGRATIONS}`),\n  );\n}\n"],"mappings":"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"}