{"version":3,"file":"impl-DxHAM8YW2.mjs","names":[],"sources":["../src/commands/request/cron/pull-profiles/impl.ts"],"sourcesContent":["import type { RequestAction } from '@transcend-io/privacy-types';\nimport { buildTranscendGraphQLClient, fetchRequestFilesForRequest } from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport colors from 'colors';\nimport { uniq, chunk } from 'lodash-es';\n\nimport type { LocalContext } from '../../../../context.js';\nimport { doneInputValidation } from '../../../../lib/cli/done-input-validation.js';\nimport {\n  pullChunkedCustomSiloOutstandingIdentifiers,\n  type CsvFormattedIdentifier,\n} from '../../../../lib/cron/index.js';\nimport { parseFilePath, writeLargeCsv } from '../../../../lib/helpers/index.js';\nimport { logger } from '../../../../logger.js';\n\nexport interface PullProfilesCommandFlags {\n  file: string;\n  fileTarget: string;\n  transcendUrl: string;\n  auth: string;\n  sombraAuth?: string;\n  cronDataSiloId: string;\n  targetDataSiloId: string;\n  actions: RequestAction[];\n  skipRequestCount: boolean;\n  pageLimit: number;\n  chunkSize: number;\n}\n\nexport async function pullProfiles(\n  this: LocalContext,\n  {\n    file,\n    fileTarget,\n    transcendUrl,\n    auth,\n    sombraAuth,\n    cronDataSiloId,\n    targetDataSiloId,\n    actions,\n    skipRequestCount,\n    pageLimit,\n    chunkSize,\n  }: PullProfilesCommandFlags,\n): Promise<void> {\n  if (skipRequestCount) {\n    logger.info(\n      colors.yellow('Skipping request count as requested. This may help speed up the call.'),\n    );\n  }\n\n  if (Number.isNaN(chunkSize) || chunkSize <= 0 || chunkSize % pageLimit !== 0) {\n    logger.error(\n      colors.red(\n        `Invalid chunk size: \"${chunkSize}\". Must be a positive integer that is a multiple of ${pageLimit}.`,\n      ),\n    );\n    this.process.exit(1);\n  }\n\n  doneInputValidation(this.process.exit);\n\n  // Create GraphQL client to connect to Transcend backend\n  const client = buildTranscendGraphQLClient(transcendUrl, auth);\n  const { baseName, extension } = parseFilePath(file);\n  const { baseName: baseNameTarget, extension: extensionTarget } = parseFilePath(fileTarget);\n\n  let allIdentifiersCount = 0;\n  let allTargetIdentifiersCount = 0;\n  let fileCount = 0;\n  // Create onSave callback to handle chunked processing\n  const onSave = async (chunkToSave: CsvFormattedIdentifier[]): Promise<void> => {\n    // Add to all identifiers\n    allIdentifiersCount += chunkToSave.length;\n\n    // Get unique request IDs from this chunk\n    const requestIds = chunkToSave.map((d) => d.requestId as string);\n    const uniqueRequestIds = uniq(requestIds);\n\n    // Pull down target identifiers for this chunk\n    const chunkedRequestIds = chunk(uniqueRequestIds, pageLimit);\n    const results = await map(\n      chunkedRequestIds,\n      async (requestIds) => {\n        logger.info(\n          colors.magenta(`Fetching target identifiers for ${requestIds.length} requests`),\n        );\n        const results = await fetchRequestFilesForRequest(client, {\n          logger,\n          pageSize: pageLimit * 2,\n          filterBy: {\n            requestIds,\n            dataSiloIds: [targetDataSiloId],\n          },\n        });\n        return results.map(({ fileName, remoteId }) => {\n          if (!remoteId) {\n            throw new Error(`Failed to find remoteId for ${fileName}`);\n          }\n          return {\n            RecordId: remoteId,\n            Object: fileName.replace('.json', '').split('/').pop()?.replace(' Information', ''),\n            Comment: 'Customer data deletion request submitted via transcend.io',\n          };\n        });\n      },\n      // We are grabbing all the request files for the 'pageLimit' # of requests at a time\n      {\n        concurrency: 1,\n      },\n    );\n\n    allTargetIdentifiersCount += results.flat().length;\n\n    // Write the identifiers and target identifiers to CSV\n    const headers = uniq(chunkToSave.map((d) => Object.keys(d)).flat());\n    const numberedFileName = `${baseName}-${fileCount}${extension}`;\n    const numberedFileNameTarget = `${baseNameTarget}-${fileCount}${extensionTarget}`;\n    await writeLargeCsv(numberedFileName, chunkToSave, headers);\n    logger.info(\n      colors.green(`Successfully wrote ${chunkToSave.length} identifiers to file \"${file}\"`),\n    );\n\n    const targetIdentifiers = results.flat();\n    const headers2 = uniq(targetIdentifiers.map((d) => Object.keys(d)).flat());\n    await writeLargeCsv(numberedFileNameTarget, targetIdentifiers, headers2);\n    logger.info(\n      colors.green(\n        `Successfully wrote ${targetIdentifiers.length} identifiers to file \"${fileTarget}\"`,\n      ),\n    );\n\n    logger.info(\n      colors.blue(\n        `Processed chunk of ${chunk.length} identifiers, found ${targetIdentifiers.length} target identifiers`,\n      ),\n    );\n    fileCount += 1;\n  };\n\n  // Pull down outstanding identifiers using the new chunked function\n  await pullChunkedCustomSiloOutstandingIdentifiers({\n    dataSiloId: cronDataSiloId,\n    auth,\n    sombraAuth,\n    actions,\n    apiPageSize: pageLimit,\n    savePageSize: chunkSize,\n    onSave,\n    transcendUrl,\n    skipRequestCount,\n  });\n\n  logger.info(\n    colors.green(`Successfully wrote ${allIdentifiersCount} identifiers to file \"${file}\"`),\n  );\n  logger.info(\n    colors.green(\n      `Successfully wrote ${allTargetIdentifiersCount} identifiers to file \"${fileTarget}\"`,\n    ),\n  );\n}\n"],"mappings":"6aA6BA,eAAsB,EAEpB,CACE,OACA,aACA,eACA,OACA,aACA,iBACA,mBACA,UACA,mBACA,YACA,aAEa,CACX,GACF,EAAO,KACL,EAAO,OAAO,wEAAwE,CACvF,EAGC,OAAO,MAAM,EAAU,EAAI,GAAa,GAAK,EAAY,IAAc,KACzE,EAAO,MACL,EAAO,IACL,wBAAwB,EAAU,sDAAsD,EAAU,GACnG,CACF,CACD,KAAK,QAAQ,KAAK,EAAE,EAGtB,EAAoB,KAAK,QAAQ,KAAK,CAGtC,IAAM,EAAS,EAA4B,EAAc,EAAK,CACxD,CAAE,WAAU,aAAc,EAAc,EAAK,CAC7C,CAAE,SAAU,EAAgB,UAAW,GAAoB,EAAc,EAAW,CAEtF,EAAsB,EACtB,EAA4B,EAC5B,EAAY,EAwEhB,MAAM,EAA4C,CAChD,WAAY,EACZ,OACA,aACA,UACA,YAAa,EACb,aAAc,EACd,YA7EoB,IAAyD,CAE7E,GAAuB,EAAY,OAQnC,IAAM,EAAU,MAAM,EADI,EAHD,EADN,EAAY,IAAK,GAAM,EAAE,UACJ,CAGQ,CAAE,EAE/B,CACjB,KAAO,KACL,EAAO,KACL,EAAO,QAAQ,mCAAmC,EAAW,OAAO,WAAW,CAChF,EASM,MARe,EAA4B,EAAQ,CACxD,SACA,SAAU,EAAY,EACtB,SAAU,CACR,aACA,YAAa,CAAC,EAAiB,CAChC,CACF,CAAC,EACa,KAAK,CAAE,WAAU,cAAe,CAC7C,GAAI,CAAC,EACH,MAAU,MAAM,+BAA+B,IAAW,CAE5D,MAAO,CACL,SAAU,EACV,OAAQ,EAAS,QAAQ,QAAS,GAAG,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,QAAQ,eAAgB,GAAG,CACnF,QAAS,4DACV,EACD,EAGJ,CACE,YAAa,EACd,CACF,CAED,GAA6B,EAAQ,MAAM,CAAC,OAG5C,IAAM,EAAU,EAAK,EAAY,IAAK,GAAM,OAAO,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAC7D,EAAmB,GAAG,EAAS,GAAG,IAAY,IAC9C,EAAyB,GAAG,EAAe,GAAG,IAAY,IAChE,MAAM,EAAc,EAAkB,EAAa,EAAQ,CAC3D,EAAO,KACL,EAAO,MAAM,sBAAsB,EAAY,OAAO,wBAAwB,EAAK,GAAG,CACvF,CAED,IAAM,EAAoB,EAAQ,MAAM,CAExC,MAAM,EAAc,EAAwB,EAD3B,EAAK,EAAkB,IAAK,GAAM,OAAO,KAAK,EAAE,CAAC,CAAC,MAAM,CACF,CAAC,CACxE,EAAO,KACL,EAAO,MACL,sBAAsB,EAAkB,OAAO,wBAAwB,EAAW,GACnF,CACF,CAED,EAAO,KACL,EAAO,KACL,sBAAsB,EAAM,OAAO,sBAAsB,EAAkB,OAAO,qBACnF,CACF,CACD,GAAa,GAYb,eACA,mBACD,CAAC,CAEF,EAAO,KACL,EAAO,MAAM,sBAAsB,EAAoB,wBAAwB,EAAK,GAAG,CACxF,CACD,EAAO,KACL,EAAO,MACL,sBAAsB,EAA0B,wBAAwB,EAAW,GACpF,CACF"}