@transcend-io/cli 10.25.3 → 10.25.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{app-Cfh4Udkq.mjs → app-DYoi_kYl.mjs} +16 -16
- package/dist/{app-Cfh4Udkq.mjs.map → app-DYoi_kYl.mjs.map} +1 -1
- package/dist/{approvePrivacyRequests-WjHVZ4-1.mjs → approvePrivacyRequests-D4ZfEesR.mjs} +2 -2
- package/dist/{approvePrivacyRequests-WjHVZ4-1.mjs.map → approvePrivacyRequests-D4ZfEesR.mjs.map} +1 -1
- package/dist/bin/bash-complete.mjs +1 -1
- package/dist/bin/cli.mjs +1 -1
- package/dist/bin/deprecated-command.mjs +1 -1
- package/dist/{buildExamples-BujEWPPq.mjs → buildExamples-Cr6HGX4h.mjs} +2 -2
- package/dist/{buildExamples-BujEWPPq.mjs.map → buildExamples-Cr6HGX4h.mjs.map} +1 -1
- package/dist/{buildXdiSyncEndpoint-sWOXCZBJ.mjs → buildXdiSyncEndpoint-CXAYh3vF.mjs} +2 -2
- package/dist/{buildXdiSyncEndpoint-sWOXCZBJ.mjs.map → buildXdiSyncEndpoint-CXAYh3vF.mjs.map} +1 -1
- package/dist/{bulkRestartRequests-mkgPyKS5.mjs → bulkRestartRequests-CSBPINdi.mjs} +2 -2
- package/dist/{bulkRestartRequests-mkgPyKS5.mjs.map → bulkRestartRequests-CSBPINdi.mjs.map} +1 -1
- package/dist/{bulkRetryEnrichers-CZvYY_M2.mjs → bulkRetryEnrichers-BPWSWNuC.mjs} +2 -2
- package/dist/{bulkRetryEnrichers-CZvYY_M2.mjs.map → bulkRetryEnrichers-BPWSWNuC.mjs.map} +1 -1
- package/dist/{cancelPrivacyRequests-CNy7OuNX.mjs → cancelPrivacyRequests-CyT7z4fs.mjs} +2 -2
- package/dist/{cancelPrivacyRequests-CNy7OuNX.mjs.map → cancelPrivacyRequests-CyT7z4fs.mjs.map} +1 -1
- package/dist/{command-7v3LMFbq.mjs → command-Cqlyn4cR.mjs} +2 -2
- package/dist/{command-7v3LMFbq.mjs.map → command-Cqlyn4cR.mjs.map} +1 -1
- package/dist/{constants-D9pBjZxu.mjs → constants-Ch1Lt8Wa.mjs} +2 -2
- package/dist/{constants-D9pBjZxu.mjs.map → constants-Ch1Lt8Wa.mjs.map} +1 -1
- package/dist/{createExtraKeyHandler-qj5-uwvg.mjs → createExtraKeyHandler-BbM9bElu.mjs} +2 -2
- package/dist/{createExtraKeyHandler-qj5-uwvg.mjs.map → createExtraKeyHandler-BbM9bElu.mjs.map} +1 -1
- package/dist/{downloadPrivacyRequestFiles-Co_eRK99.mjs → downloadPrivacyRequestFiles-CaOdAuGW.mjs} +2 -2
- package/dist/{downloadPrivacyRequestFiles-Co_eRK99.mjs.map → downloadPrivacyRequestFiles-CaOdAuGW.mjs.map} +1 -1
- package/dist/{generateCrossAccountApiKeys-B-S-evYy.mjs → generateCrossAccountApiKeys-JCZ444Xx.mjs} +2 -2
- package/dist/{generateCrossAccountApiKeys-B-S-evYy.mjs.map → generateCrossAccountApiKeys-JCZ444Xx.mjs.map} +1 -1
- package/dist/{impl-D5SSdxyU2.mjs → impl-2M02W7-p2.mjs} +2 -2
- package/dist/{impl-D5SSdxyU2.mjs.map → impl-2M02W7-p2.mjs.map} +1 -1
- package/dist/{impl-JJZtnqpQ.mjs → impl-5db-Jqms.mjs} +2 -2
- package/dist/{impl-JJZtnqpQ.mjs.map → impl-5db-Jqms.mjs.map} +1 -1
- package/dist/{impl-DdncdRTn2.mjs → impl-BLCkTzS02.mjs} +2 -2
- package/dist/{impl-DdncdRTn2.mjs.map → impl-BLCkTzS02.mjs.map} +1 -1
- package/dist/{impl-CufspKYB.mjs → impl-BMaeLKTr.mjs} +2 -2
- package/dist/{impl-CufspKYB.mjs.map → impl-BMaeLKTr.mjs.map} +1 -1
- package/dist/{impl-CmeZy5dM2.mjs → impl-BXjWAiAl2.mjs} +2 -2
- package/dist/{impl-CmeZy5dM2.mjs.map → impl-BXjWAiAl2.mjs.map} +1 -1
- package/dist/{impl-BxJOVUrh.mjs → impl-BZbjA9x3.mjs} +2 -2
- package/dist/{impl-BxJOVUrh.mjs.map → impl-BZbjA9x3.mjs.map} +1 -1
- package/dist/{impl-DsKc9G_72.mjs → impl-Bbd2DHE82.mjs} +2 -2
- package/dist/{impl-DsKc9G_72.mjs.map → impl-Bbd2DHE82.mjs.map} +1 -1
- package/dist/{impl-CkNvI-dK.mjs → impl-Be2M3iuo.mjs} +2 -2
- package/dist/{impl-CkNvI-dK.mjs.map → impl-Be2M3iuo.mjs.map} +1 -1
- package/dist/{impl-a0-5uWMu.mjs → impl-BgkjL6_C.mjs} +2 -2
- package/dist/{impl-a0-5uWMu.mjs.map → impl-BgkjL6_C.mjs.map} +1 -1
- package/dist/{impl-syYJyrYp.mjs → impl-Bk6lPywf.mjs} +2 -2
- package/dist/{impl-syYJyrYp.mjs.map → impl-Bk6lPywf.mjs.map} +1 -1
- package/dist/{impl-Be0ymKCB2.mjs → impl-C5QTz-js2.mjs} +2 -2
- package/dist/{impl-Be0ymKCB2.mjs.map → impl-C5QTz-js2.mjs.map} +1 -1
- package/dist/{impl-3FaRVZ72.mjs → impl-C9Br_VrZ.mjs} +2 -2
- package/dist/{impl-3FaRVZ72.mjs.map → impl-C9Br_VrZ.mjs.map} +1 -1
- package/dist/{impl-DK5Nkyt8.mjs → impl-CBIcjbfD.mjs} +2 -2
- package/dist/{impl-DK5Nkyt8.mjs.map → impl-CBIcjbfD.mjs.map} +1 -1
- package/dist/{impl-dyGnOBGI.mjs → impl-CCMVpNez.mjs} +2 -2
- package/dist/{impl-dyGnOBGI.mjs.map → impl-CCMVpNez.mjs.map} +1 -1
- package/dist/{impl-P4-qm5It2.mjs → impl-CMqjJCoY2.mjs} +2 -2
- package/dist/{impl-P4-qm5It2.mjs.map → impl-CMqjJCoY2.mjs.map} +1 -1
- package/dist/{impl-d1rpcacl2.mjs → impl-CPN-_vdL2.mjs} +2 -2
- package/dist/{impl-d1rpcacl2.mjs.map → impl-CPN-_vdL2.mjs.map} +1 -1
- package/dist/{impl-DDFMwvrg.mjs → impl-CRH0V2nJ.mjs} +2 -2
- package/dist/{impl-DDFMwvrg.mjs.map → impl-CRH0V2nJ.mjs.map} +1 -1
- package/dist/{impl-bPplDcBj2.mjs → impl-CZWMK-kA2.mjs} +2 -2
- package/dist/{impl-bPplDcBj2.mjs.map → impl-CZWMK-kA2.mjs.map} +1 -1
- package/dist/{impl-aKuDB4aE.mjs → impl-CxjrhJ-X.mjs} +2 -2
- package/dist/{impl-aKuDB4aE.mjs.map → impl-CxjrhJ-X.mjs.map} +1 -1
- package/dist/{impl-CeD2rBwi2.mjs → impl-D-0Z4tn72.mjs} +2 -2
- package/dist/{impl-CeD2rBwi2.mjs.map → impl-D-0Z4tn72.mjs.map} +1 -1
- package/dist/{impl-DjX1ALQC.mjs → impl-D2WYmqZ0.mjs} +2 -2
- package/dist/{impl-DjX1ALQC.mjs.map → impl-D2WYmqZ0.mjs.map} +1 -1
- package/dist/{impl-CwGAxbya2.mjs → impl-DUS_D3PU2.mjs} +2 -2
- package/dist/{impl-CwGAxbya2.mjs.map → impl-DUS_D3PU2.mjs.map} +1 -1
- package/dist/{impl-UVNiy79O.mjs → impl-DUxqEjMF.mjs} +2 -2
- package/dist/{impl-UVNiy79O.mjs.map → impl-DUxqEjMF.mjs.map} +1 -1
- package/dist/{impl-DPDaN0Cs2.mjs → impl-DgyNLnJo2.mjs} +2 -2
- package/dist/{impl-DPDaN0Cs2.mjs.map → impl-DgyNLnJo2.mjs.map} +1 -1
- package/dist/{impl-CxFcXPak.mjs → impl-DjOWgFlT.mjs} +2 -2
- package/dist/{impl-CxFcXPak.mjs.map → impl-DjOWgFlT.mjs.map} +1 -1
- package/dist/{impl-EAN_KtxS2.mjs → impl-Dv2AsuuH2.mjs} +2 -2
- package/dist/{impl-EAN_KtxS2.mjs.map → impl-Dv2AsuuH2.mjs.map} +1 -1
- package/dist/{impl-kTDQW8As.mjs → impl-X50_5E1x.mjs} +2 -2
- package/dist/{impl-kTDQW8As.mjs.map → impl-X50_5E1x.mjs.map} +1 -1
- package/dist/{impl-BbyyqJ3N.mjs → impl-iBottQJe.mjs} +2 -2
- package/dist/{impl-BbyyqJ3N.mjs.map → impl-iBottQJe.mjs.map} +1 -1
- package/dist/{impl-o7jWXu8s2.mjs → impl-iGEtfSgW2.mjs} +2 -2
- package/dist/{impl-o7jWXu8s2.mjs.map → impl-iGEtfSgW2.mjs.map} +1 -1
- package/dist/{impl-2mOeK354.mjs → impl-m1WDTmQO.mjs} +2 -2
- package/dist/{impl-2mOeK354.mjs.map → impl-m1WDTmQO.mjs.map} +1 -1
- package/dist/{impl-BGm6yQSC2.mjs → impl-o0RdOoiZ2.mjs} +2 -2
- package/dist/{impl-BGm6yQSC2.mjs.map → impl-o0RdOoiZ2.mjs.map} +1 -1
- package/dist/{impl-2BOl6Ipo2.mjs → impl-rTqHhQ7X2.mjs} +2 -2
- package/dist/{impl-2BOl6Ipo2.mjs.map → impl-rTqHhQ7X2.mjs.map} +1 -1
- package/dist/{impl-BZ6rXeeQ2.mjs → impl-tNN3yVw72.mjs} +2 -2
- package/dist/{impl-BZ6rXeeQ2.mjs.map → impl-tNN3yVw72.mjs.map} +1 -1
- package/dist/{impl-Cd5_CBXA2.mjs → impl-xNSHqJyt2.mjs} +2 -2
- package/dist/{impl-Cd5_CBXA2.mjs.map → impl-xNSHqJyt2.mjs.map} +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{markRequestDataSiloIdsCompleted-CyuHmDfw.mjs → markRequestDataSiloIdsCompleted-C7HAJehS.mjs} +2 -2
- package/dist/{markRequestDataSiloIdsCompleted-CyuHmDfw.mjs.map → markRequestDataSiloIdsCompleted-C7HAJehS.mjs.map} +1 -1
- package/dist/{markSilentPrivacyRequests-DxBYqlWf.mjs → markSilentPrivacyRequests-Ctu7drQy.mjs} +2 -2
- package/dist/{markSilentPrivacyRequests-DxBYqlWf.mjs.map → markSilentPrivacyRequests-Ctu7drQy.mjs.map} +1 -1
- package/dist/{notifyPrivacyRequestsAdditionalTime-Cz3JSj8W.mjs → notifyPrivacyRequestsAdditionalTime-Du7706Lb.mjs} +2 -2
- package/dist/{notifyPrivacyRequestsAdditionalTime-Cz3JSj8W.mjs.map → notifyPrivacyRequestsAdditionalTime-Du7706Lb.mjs.map} +1 -1
- package/dist/{pullChunkedCustomSiloOutstandingIdentifiers-B9JgAJn7.mjs → pullChunkedCustomSiloOutstandingIdentifiers-D_TkvoKK.mjs} +2 -2
- package/dist/{pullChunkedCustomSiloOutstandingIdentifiers-B9JgAJn7.mjs.map → pullChunkedCustomSiloOutstandingIdentifiers-D_TkvoKK.mjs.map} +1 -1
- package/dist/{pullManualEnrichmentIdentifiersToCsv-CPMWbTG3.mjs → pullManualEnrichmentIdentifiersToCsv-C_XrnqTo.mjs} +2 -2
- package/dist/{pullManualEnrichmentIdentifiersToCsv-CPMWbTG3.mjs.map → pullManualEnrichmentIdentifiersToCsv-C_XrnqTo.mjs.map} +1 -1
- package/dist/{pushCronIdentifiersFromCsv-9JIR6s8x.mjs → pushCronIdentifiersFromCsv-hcTHlWyf.mjs} +2 -2
- package/dist/{pushCronIdentifiersFromCsv-9JIR6s8x.mjs.map → pushCronIdentifiersFromCsv-hcTHlWyf.mjs.map} +1 -1
- package/dist/{pushManualEnrichmentIdentifiersFromCsv-DGaVSVBZ.mjs → pushManualEnrichmentIdentifiersFromCsv-5Dulzugh.mjs} +2 -2
- package/dist/{pushManualEnrichmentIdentifiersFromCsv-DGaVSVBZ.mjs.map → pushManualEnrichmentIdentifiersFromCsv-5Dulzugh.mjs.map} +1 -1
- package/dist/{removeUnverifiedRequestIdentifiers-DJ2CdC7q.mjs → removeUnverifiedRequestIdentifiers-D2tdogVl.mjs} +2 -2
- package/dist/{removeUnverifiedRequestIdentifiers-DJ2CdC7q.mjs.map → removeUnverifiedRequestIdentifiers-D2tdogVl.mjs.map} +1 -1
- package/dist/{retryRequestDataSilos-r_1ayUmk.mjs → retryRequestDataSilos-pQ4DekAX.mjs} +2 -2
- package/dist/{retryRequestDataSilos-r_1ayUmk.mjs.map → retryRequestDataSilos-pQ4DekAX.mjs.map} +1 -1
- package/dist/{skipPreflightJobs-DTdhZDyQ.mjs → skipPreflightJobs-BrBvyKxG.mjs} +2 -2
- package/dist/{skipPreflightJobs-DTdhZDyQ.mjs.map → skipPreflightJobs-BrBvyKxG.mjs.map} +1 -1
- package/dist/{skipRequestDataSilos-0DQCLmqO.mjs → skipRequestDataSilos-DrTtHtF5.mjs} +2 -2
- package/dist/{skipRequestDataSilos-0DQCLmqO.mjs.map → skipRequestDataSilos-DrTtHtF5.mjs.map} +1 -1
- package/dist/{streamPrivacyRequestsToCsv-Bv2QwqmI.mjs → streamPrivacyRequestsToCsv-zGxmk-9Z.mjs} +2 -2
- package/dist/{streamPrivacyRequestsToCsv-Bv2QwqmI.mjs.map → streamPrivacyRequestsToCsv-zGxmk-9Z.mjs.map} +1 -1
- package/dist/{updateConsentManagerVersionToLatest-DMvWDnaI.mjs → updateConsentManagerVersionToLatest-Dg-j1SQt.mjs} +2 -2
- package/dist/{updateConsentManagerVersionToLatest-DMvWDnaI.mjs.map → updateConsentManagerVersionToLatest-Dg-j1SQt.mjs.map} +1 -1
- package/dist/{uploadConsents-CmD75o8c.mjs → uploadConsents-B3lvS6hQ.mjs} +2 -2
- package/dist/{uploadConsents-CmD75o8c.mjs.map → uploadConsents-B3lvS6hQ.mjs.map} +1 -1
- package/dist/{uploadCookiesFromCsv-yZeI-o0o.mjs → uploadCookiesFromCsv-DmU8R-_E.mjs} +2 -2
- package/dist/{uploadCookiesFromCsv-yZeI-o0o.mjs.map → uploadCookiesFromCsv-DmU8R-_E.mjs.map} +1 -1
- package/dist/{uploadDataFlowsFromCsv-DuGs3eMx.mjs → uploadDataFlowsFromCsv-Ct0rye94.mjs} +2 -2
- package/dist/{uploadDataFlowsFromCsv-DuGs3eMx.mjs.map → uploadDataFlowsFromCsv-Ct0rye94.mjs.map} +1 -1
- package/dist/{uploadPrivacyRequestsFromCsv-ckCloGTs.mjs → uploadPrivacyRequestsFromCsv-BVi19fS8.mjs} +2 -2
- package/dist/{uploadPrivacyRequestsFromCsv-ckCloGTs.mjs.map → uploadPrivacyRequestsFromCsv-BVi19fS8.mjs.map} +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-DUxqEjMF.mjs","names":[],"sources":["../src/commands/admin/parquet-to-csv/ui/plugin.ts","../src/commands/admin/parquet-to-csv/impl.ts"],"sourcesContent":["import {\n makeHeader,\n makeWorkerRows,\n type ChunkSlotProgress,\n type CommonCtx,\n type DashboardPlugin,\n} from '../../../../lib/pooling/index.js';\n\n/**\n * Header for parquet-to-csv (no extra totals block).\n *\n * @param ctx - Dashboard context.\n * @returns Header lines.\n */\nfunction renderHeader<TTotals>(ctx: CommonCtx<TTotals, ChunkSlotProgress>): string[] {\n // no extra lines — reuse the shared header as-is\n return makeHeader(ctx);\n}\n\n/**\n * Worker rows for parquet-to-csv — share the generic row renderer.\n *\n * @param ctx - Dashboard context.\n * @returns Array of strings, each representing one worker row.\n */\nfunction renderWorkers<TTotals>(ctx: CommonCtx<TTotals, ChunkSlotProgress>): string[] {\n return makeWorkerRows(ctx);\n}\n\nexport const parquetToCsvPlugin: DashboardPlugin<unknown, ChunkSlotProgress> = {\n renderHeader,\n renderWorkers,\n // no extras\n};\n","import {\n CHILD_FLAG,\n type PoolHooks,\n runPool,\n computePoolSize,\n PoolCancelledError,\n resolveWorkerPath,\n} from '@transcend-io/utils';\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { collectParquetFilesOrExit } from '../../../lib/helpers/index.js';\nimport {\n createExtraKeyHandler,\n dashboardPlugin,\n installInteractiveSwitcher,\n} from '../../../lib/pooling/index.js';\nimport { logger } from '../../../logger.js';\nimport { parquetToCsvPlugin } from './ui/index.js';\nimport type { ParquetProgress, ParquetResult, ParquetTask } from './worker.js';\n\n/** No custom totals for the header; the runner’s built-ins suffice. */\ntype Totals = Record<string, never>;\n\nexport type ParquetToCsvCommandFlags = {\n directory: string;\n outputDir?: string;\n clearOutputDir: boolean;\n concurrency?: number;\n viewerMode: boolean;\n};\n\n/**\n * Convert all Parquet files in a directory to CSV, in parallel.\n *\n * @param flags - The command flags.\n */\nexport async function parquetToCsv(\n this: LocalContext,\n flags: ParquetToCsvCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process.exit);\n\n const { directory, outputDir, clearOutputDir, concurrency, viewerMode } = flags;\n\n /* 1) Discover .parquet inputs */\n const files = collectParquetFilesOrExit(directory, this);\n\n /* 2) Size the pool */\n const { poolSize, cpuCount } = computePoolSize(concurrency, files.length);\n\n logger.info(\n colors.green(\n `Converting ${files.length} Parquet file(s) → CSV with pool size ${poolSize} (CPU=${cpuCount})`,\n ),\n );\n\n /* 3) Build FIFO queue of tasks (one per file) */\n const queue = files.map<ParquetTask>((filePath) => ({\n filePath,\n options: { outputDir, clearOutputDir },\n }));\n\n /* 4) Pool hooks */\n const hooks: PoolHooks<ParquetTask, ParquetProgress, ParquetResult, Totals> = {\n nextTask: () => queue.shift(),\n taskLabel: (t) => t.filePath,\n initTotals: () => ({}) as Totals,\n initSlotProgress: () => undefined,\n onProgress: (totals) => totals,\n onResult: (totals, res) => ({ totals, ok: !!res.ok }),\n postProcess: async () => {\n // nothing special post-run\n },\n };\n\n /* 5) Launch the pool runner with custom dashboard plugin */\n await runPool({\n title: `Parquet → CSV - ${directory}`,\n baseDir: directory || outputDir || process.cwd(),\n childFlag: CHILD_FLAG,\n childModulePath: resolveWorkerPath(import.meta.url, 'commands/admin/parquet-to-csv/worker.mjs'),\n poolSize,\n cpuCount,\n filesTotal: files.length,\n hooks,\n viewerMode,\n render: (input) => dashboardPlugin(input, parquetToCsvPlugin, viewerMode),\n installInteractiveSwitcher: viewerMode\n ? undefined\n : ({\n workers,\n onCtrlC,\n getLogPaths,\n replayBytes: rb,\n replayWhich: rw,\n setPaused,\n repaint: rp,\n }) =>\n installInteractiveSwitcher({\n workers,\n onCtrlC,\n getLogPaths,\n replayBytes: rb,\n replayWhich: rw,\n onAttach: () => setPaused(true),\n onDetach: () => {\n setPaused(false);\n rp();\n },\n onEnterAttachScreen: (id) => {\n setPaused(true);\n process.stdout.write('\\x1b[2J\\x1b[H');\n process.stdout.write(\n `Attached to worker ${id}. (Esc/Ctrl+] detach \\u2022 Ctrl+D EOF \\u2022 Ctrl+C SIGINT)\\n`,\n );\n },\n }),\n extraKeyHandler: ({ logsBySlot, repaint, setPaused }) =>\n createExtraKeyHandler({ logsBySlot, repaint, setPaused }),\n }).catch((err) => {\n if (err instanceof PoolCancelledError) {\n process.exit(130);\n }\n throw err;\n });\n}\n"],"mappings":"mYAcA,SAAS,EAAsB,EAAsD,CAEnF,OAAO,EAAW,EAAI,CASxB,SAAS,EAAuB,EAAsD,CACpF,OAAO,EAAe,EAAI,CAG5B,MAAa,EAAkE,CAC7E,eACA,gBAED,CCKD,eAAsB,EAEpB,EACe,CACf,EAAoB,KAAK,QAAQ,KAAK,CAEtC,GAAM,CAAE,YAAW,YAAW,iBAAgB,cAAa,cAAe,EAGpE,EAAQ,EAA0B,EAAW,KAAK,CAGlD,CAAE,WAAU,YAAa,EAAgB,EAAa,EAAM,OAAO,CAEzE,EAAO,KACL,EAAO,MACL,cAAc,EAAM,OAAO,wCAAwC,EAAS,QAAQ,EAAS,GAC9F,CACF,CAGD,IAAM,EAAQ,EAAM,IAAkB,IAAc,CAClD,WACA,QAAS,CAAE,YAAW,iBAAgB,CACvC,EAAE,CAgBH,MAAM,EAAQ,CACZ,MAAO,mBAAmB,IAC1B,QAAS,GAAa,GAAa,QAAQ,KAAK,CAChD,UAAW,EACX,gBAAiB,EAAkB,OAAO,KAAK,IAAK,2CAA2C,CAC/F,WACA,WACA,WAAY,EAAM,OAClB,MAAA,CApBA,aAAgB,EAAM,OAAO,CAC7B,UAAY,GAAM,EAAE,SACpB,gBAAmB,EAAE,EACrB,qBAAwB,IAAA,GACxB,WAAa,GAAW,EACxB,UAAW,EAAQ,KAAS,CAAE,SAAQ,GAAI,CAAC,CAAC,EAAI,GAAI,EACpD,YAAa,SAAY,GAcpB,CACL,aACA,OAAS,GAAU,EAAgB,EAAO,EAAoB,EAAW,CACzE,2BAA4B,EACxB,IAAA,IACC,CACC,UACA,UACA,cACA,YAAa,EACb,YAAa,EACb,YACA,QAAS,KAET,EAA2B,CACzB,UACA,UACA,cACA,YAAa,EACb,YAAa,EACb,aAAgB,EAAU,GAAK,CAC/B,aAAgB,CACd,EAAU,GAAM,CAChB,GAAI,EAEN,oBAAsB,GAAO,CAC3B,EAAU,GAAK,CACf,QAAQ,OAAO,MAAM,gBAAgB,CACrC,QAAQ,OAAO,MACb,sBAAsB,EAAG,gEAC1B,EAEJ,CAAC,CACR,iBAAkB,CAAE,aAAY,UAAS,eACvC,EAAsB,CAAE,aAAY,UAAS,YAAW,CAAC,CAC5D,CAAC,CAAC,MAAO,GAAQ,CAIhB,MAHI,aAAe,GACjB,QAAQ,KAAK,IAAI,CAEb,GACN"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./approvePrivacyRequests-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./approvePrivacyRequests-D4ZfEesR.mjs";import{t}from"./done-input-validation-uqIgnJcw.mjs";async function n({auth:n,actions:r,origins:i,silentModeBefore:a,createdAtBefore:o,createdAtAfter:s,updatedAtBefore:c,updatedAtAfter:l,transcendUrl:u,concurrency:d}){t(this.process.exit),await e({transcendUrl:u,requestActions:r,auth:n,requestOrigins:i,concurrency:d,silentModeBefore:a,createdAtBefore:o,createdAtAfter:s,updatedAtBefore:c,updatedAtAfter:l})}export{n as approve};
|
|
2
|
+
//# sourceMappingURL=impl-DgyNLnJo2.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-DgyNLnJo2.mjs","names":[],"sources":["../src/commands/request/approve/impl.ts"],"sourcesContent":["import { RequestAction, RequestOrigin } from '@transcend-io/privacy-types';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { approvePrivacyRequests } from '../../../lib/requests/index.js';\n\nexport interface ApproveCommandFlags {\n auth: string;\n actions: RequestAction[];\n origins?: RequestOrigin[];\n silentModeBefore?: Date;\n createdAtBefore?: Date;\n createdAtAfter?: Date;\n updatedAtBefore?: Date;\n updatedAtAfter?: Date;\n transcendUrl: string;\n concurrency: number;\n}\n\nexport async function approve(\n this: LocalContext,\n {\n auth,\n actions,\n origins,\n silentModeBefore,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n transcendUrl,\n concurrency,\n }: ApproveCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process.exit);\n\n await approvePrivacyRequests({\n transcendUrl,\n requestActions: actions,\n auth,\n requestOrigins: origins,\n concurrency,\n silentModeBefore,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n });\n}\n"],"mappings":"8GAmBA,eAAsB,EAEpB,CACE,OACA,UACA,UACA,mBACA,kBACA,iBACA,kBACA,iBACA,eACA,eAEa,CACf,EAAoB,KAAK,QAAQ,KAAK,CAEtC,MAAM,EAAuB,CAC3B,eACA,eAAgB,EAChB,OACA,eAAgB,EAChB,cACA,mBACA,kBACA,iBACA,kBACA,iBACD,CAAC"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{t as e}from"./buildExamples-
|
|
1
|
+
import{t as e}from"./buildExamples-Cr6HGX4h.mjs";import{r as t}from"./policyEngineCliError-BnBghLd1.mjs";import{n,t as r}from"./constants-FbK2iR--.mjs";import{r as i,t as a}from"./runOpa-D511z37u.mjs";import{i as o,n as s,t as c}from"./printResult-oXnpZu_9.mjs";import{t as l}from"./formatPolicyBundleVersionSummary-Bo7DYxoy.mjs";import{n as u}from"./resolveBundleIdByName-By5Vl8Iz.mjs";import{t as d}from"./logger-Ckep4QXn.mjs";import{n as f}from"./inquirer-B0OF_nRe.mjs";import{t as p}from"./done-input-validation-uqIgnJcw.mjs";import{spawnSync as m}from"node:child_process";import h from"node:fs";import g from"node:os";import _ from"node:path";import{gunzipSync as v}from"node:zlib";import y from"fast-glob";import b from"colors";function x(e){return e.endsWith(`.rego`)&&!e.endsWith(`_test.rego`)}function S(e){let t=_.join(e,`manifest.json`);if(!h.existsSync(t))throw Error(`Policy bundle directory must contain a manifest.json file.`);let n=h.readFileSync(t,`utf8`),r;try{r=JSON.parse(n)}catch(e){throw Error(`manifest.json is not valid JSON: ${e instanceof Error?e.message:String(e)}`,{cause:e})}if(!r||typeof r!=`object`||Array.isArray(r))throw Error(`manifest.json must contain a JSON object.`);let i=r.roots;if(!Array.isArray(i)||i.length===0)throw Error(`manifest.json must declare "roots" as a non-empty array of strings (e.g. {"roots":["policy_engine"]}).`);if(!i.every(e=>typeof e==`string`&&e.length>0))throw Error(`manifest.json "roots" must be an array of non-empty strings.`);return{roots:i}}function C(e){let t=S(e),n=y.sync(`**/*.rego`,{cwd:e,onlyFiles:!0,dot:!1}).filter(x);if(n.length===0)throw Error(`Policy bundle directory must contain at least one .rego policy file.`);return{entries:[`manifest.json`,...n.sort()],manifest:t}}const w=/^\s*package\s+([A-Za-z_][\w.]*)/m;function T(e){return e.replace(/\//g,`.`)}function E(e){let t=h.readFileSync(e,`utf8`);return w.exec(t)?.[1]}function D(e,t,n){let r=n.map(T),i=[];for(let a of t){let t=E(_.join(e,a));t&&(r.some(e=>t===e||t.startsWith(`${e}.`))||i.push(` - ${a} (package ${t}) is not covered by roots [${n.join(`, `)}]`))}if(i.length>0)throw Error([`manifest.json "roots" do not cover all Rego packages in the bundle; uncovered packages will fail-closed at decide time. Either broaden "roots" or move the policy under a covered package:`,...i].join(`
|
|
2
2
|
`))}async function O(e){let t=_.join(g.tmpdir(),`transcend-policy-bundle-build-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`);try{let{code:n,stderr:r}=await a([`build`,`--v0-compatible`,`--ignore`,`*_test.rego`,`-o`,t,`.`],{cwd:e});if(n!==0)throw Error(r.trim()||`opa build failed with exit code ${n}`)}finally{h.existsSync(t)&&h.unlinkSync(t)}}function k(e){if(e<1024)return`${e} B`;let t=e/1024;if(t<1024)return`${t%1==0?t.toFixed(0):t.toFixed(1)} KiB`;let n=t/1024;return`${n%1==0?n.toFixed(0):n.toFixed(1)} MiB`}async function A(e){i();let t=_.resolve(e);if(!h.existsSync(t)||!h.statSync(t).isDirectory())throw Error(`Policy directory does not exist or is not a directory: ${t}`);let{entries:o,manifest:s}=C(t);D(t,o.filter(e=>e!==`manifest.json`),s.roots);let{code:c,stderr:l}=await a([`check`,`--strict`,`--v0-compatible`,t]);if(c!==0)throw Error(l.trim()||`opa check failed with exit code ${c}`);await O(t);let u=_.join(g.tmpdir(),`transcend-policy-bundle-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`),d=m(`tar`,[`-czf`,u,`-C`,t,...o],{env:{...process.env,COPYFILE_DISABLE:`1`},encoding:`utf8`});if(d.status!==0)throw Error(`Failed to create policy bundle archive: ${d.stderr.trim()||`tar failed`}`);let f=h.readFileSync(u);if(f.byteLength>5120)throw h.unlinkSync(u),Error(`Policy bundle exceeds the ${k(r)} compressed upload limit (bundle is ${k(f.byteLength)}). The server also rejects decompressed bundles larger than ${k(n)}.`);let p=v(f);if(p.byteLength>51200)throw h.unlinkSync(u),Error(`Policy bundle exceeds the ${k(n)} decompressed upload limit (bundle is ${k(p.byteLength)} decompressed).`);return u}function j(e){let t=h.readFileSync(e.bundlePath),n=new FormData;return n.append(`bundle`,new Blob([t],{type:`application/gzip`}),_.basename(e.bundlePath)),n.append(`version`,e.version),e.description&&n.append(`description`,e.description),e.bundleName&&n.append(`bundleName`,e.bundleName),n}function M(e){return e.toISOString().slice(0,19).replace(/[T:]/g,`-`)}function N(e,t=new Date){return`${e}-${M(t)}`}async function P({dir:n,"bundle-name":r,auth:i,"transcend-url":a,version:m,description:g,json:v,yes:y,debug:x=!1}){p(this.process.exit),t(x);let S=_.resolve(n),C=m??N(r),w=o(a,i),T;try{d.info(b.green(`Building policy bundle from ${S}...`)),T=await A(S);let t=await u(w,r),n;if(t){d.info(b.green(`Uploading new version for bundle "${r}"...`));let e=j({bundlePath:T,version:C,description:g});n=await s(w.post(`v1/policy-engine/policy-bundles/${t}/versions`,{body:e}).json())}else{if(!this.process.stdin.isTTY&&!y){d.error(b.red(`Cannot create a new bundle in a non-interactive environment; pass --yes to confirm.`)),this.process.exit(1);return}if(!y&&(d.warn(b.yellow(`No policy bundle named "${r}" exists for this organization.`)),!await f({message:`No policy bundle named "${r}" exists. Create a new bundle and upload its first version?`}))){d.info(b.yellow(`Publish cancelled.`));return}d.info(b.green(`Creating bundle "${r}" and uploading first version...`));let e=j({bundlePath:T,version:C,description:g,bundleName:r});n=await s(w.post(`v1/policy-engine/policy-bundles`,{body:e}).json())}c(this.process.stdout,{json:v,data:n,renderTable:()=>l(n.version)}),d.info(b.green(`Policy bundle version uploaded successfully.`));let i=e([`policy`,`activate`],{version:n.version.version,"bundle-name":r});d.info(b.yellow(`Publishing a policy does not activate it. To activate this version, run:\n ${i}`))}finally{T&&h.existsSync(T)&&h.unlinkSync(T)}}export{P as publish};
|
|
3
|
-
//# sourceMappingURL=impl-
|
|
3
|
+
//# sourceMappingURL=impl-DjOWgFlT.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-CxFcXPak.mjs","names":["fg"],"sources":["../src/commands/policy/helpers/buildOpaBundleTarball.ts","../src/commands/policy/helpers/buildPolicyBundleFormData.ts","../src/commands/policy/helpers/defaultPolicyVersionLabel.ts","../src/commands/policy/publish/impl.ts"],"sourcesContent":["import { spawnSync } from 'node:child_process';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { gunzipSync } from 'node:zlib';\n\nimport fg from 'fast-glob';\n\nimport { MAX_BUNDLE_COMPRESSED_BYTES, MAX_BUNDLE_DECOMPRESSED_BYTES } from '../constants.js';\nimport { assertOpaInstalled } from './assertOpaInstalled.js';\nimport { runOPACapture } from './runOpa.js';\n\n/**\n * Returns whether a relative path is a publishable Rego policy file.\n *\n * OPA test files (`*_test.rego`) are excluded because they are for local\n * validation only and are not part of the upload contract.\n *\n * @param relativePath - Path relative to the bundle directory\n * @returns Whether the file should be included in the upload archive\n */\nfunction isPublishableRegoFile(relativePath: string): boolean {\n return relativePath.endsWith('.rego') && !relativePath.endsWith('_test.rego');\n}\n\n/** Shape of the OPA bundle `manifest.json` as accepted by the Policy Engine. */\ninterface PolicyBundleManifest {\n /** Roots of the bundle, e.g. `[\"policy_engine\"]` or `[\"policy_engine/transcend\"]` */\n roots: string[];\n}\n\n/**\n * Reads and validates `manifest.json` from a policy bundle directory.\n *\n * The Policy Engine requires `manifest.json` to declare `roots` as an array of\n * strings. OPA's own tooling does not always enforce this against the Rego\n * packages on upload, so we validate the shape client-side to surface a clear,\n * actionable error instead of an opaque server `400` or a decide-time\n * fail-closed footgun.\n *\n * @param dir - Absolute path to the policy bundle directory\n * @returns The parsed manifest\n */\nfunction readPolicyBundleManifest(dir: string): PolicyBundleManifest {\n const manifestPath = path.join(dir, 'manifest.json');\n if (!fs.existsSync(manifestPath)) {\n throw new Error('Policy bundle directory must contain a manifest.json file.');\n }\n\n const raw = fs.readFileSync(manifestPath, 'utf8');\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n throw new Error(\n `manifest.json is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error('manifest.json must contain a JSON object.');\n }\n\n const roots = (parsed as { roots?: unknown }).roots;\n if (!Array.isArray(roots) || roots.length === 0) {\n throw new Error(\n 'manifest.json must declare \"roots\" as a non-empty array of strings (e.g. {\"roots\":[\"policy_engine\"]}).',\n );\n }\n\n if (!roots.every((root) => typeof root === 'string' && root.length > 0)) {\n throw new Error('manifest.json \"roots\" must be an array of non-empty strings.');\n }\n\n return { roots };\n}\n\n/** Result of collecting publishable entries from a policy bundle directory. */\ninterface PolicyBundleArchiveContents {\n /** Relative paths to include in the upload tarball (manifest first, then rego) */\n entries: string[];\n /** Parsed manifest */\n manifest: PolicyBundleManifest;\n}\n\n/**\n * Collects `manifest.json` and publishable `.rego` files from a policy directory.\n *\n * @param dir - Absolute path to the policy bundle directory\n * @returns Archive entries and the parsed manifest\n */\nfunction collectPolicyBundleArchiveEntries(dir: string): PolicyBundleArchiveContents {\n const manifest = readPolicyBundleManifest(dir);\n\n const regoFiles = fg\n .sync('**/*.rego', {\n cwd: dir,\n onlyFiles: true,\n dot: false,\n })\n .filter(isPublishableRegoFile);\n\n if (regoFiles.length === 0) {\n throw new Error('Policy bundle directory must contain at least one .rego policy file.');\n }\n\n return { entries: ['manifest.json', ...regoFiles.sort()], manifest };\n}\n\n/** Matches a Rego `package <path>` declaration. */\nconst PACKAGE_DECLARATION_PATTERN = /^\\s*package\\s+([A-Za-z_][\\w.]*)/m;\n\n/**\n * Normalizes an OPA manifest root to a dotted package prefix.\n *\n * Roots use `/` as the path separator (e.g. `policy_engine/transcend`); Rego\n * package paths use `.` (e.g. `policy_engine.transcend`).\n *\n * @param root - A manifest root string\n * @returns The root in dotted form\n */\nfunction normalizeRootToPackagePrefix(root: string): string {\n return root.replace(/\\//g, '.');\n}\n\n/**\n * Reads the Rego package path declared in a `.rego` file.\n *\n * @param filePath - Absolute path to the `.rego` file\n * @returns The dotted package path, or `undefined` if no `package` declaration\n */\nfunction readRegoPackagePath(filePath: string): string | undefined {\n const contents = fs.readFileSync(filePath, 'utf8');\n const match = PACKAGE_DECLARATION_PATTERN.exec(contents);\n return match?.[1];\n}\n\n/**\n * Verifies that every publishable `.rego` package is covered by a manifest root.\n *\n * A bundle whose `roots` do not cover its Rego packages will upload cleanly but\n * fail-closed at decide time — the customer only discovers the mismatch via\n * denied decisions. This surfaces the mismatch at upload with a clear message.\n *\n * @param dir - Absolute path to the policy bundle directory\n * @param regoFiles - Relative paths to publishable `.rego` files\n * @param roots - Manifest roots\n */\nfunction assertRootsCoverPackages(dir: string, regoFiles: string[], roots: string[]): void {\n const rootPrefixes = roots.map(normalizeRootToPackagePrefix);\n\n const uncovered: string[] = [];\n for (const relativeRego of regoFiles) {\n const pkg = readRegoPackagePath(path.join(dir, relativeRego));\n if (!pkg) {\n continue;\n }\n const covered = rootPrefixes.some((prefix) => pkg === prefix || pkg.startsWith(`${prefix}.`));\n if (!covered) {\n uncovered.push(\n ` - ${relativeRego} (package ${pkg}) is not covered by roots [${roots.join(', ')}]`,\n );\n }\n }\n\n if (uncovered.length > 0) {\n throw new Error(\n [\n 'manifest.json \"roots\" do not cover all Rego packages in the bundle; ' +\n 'uncovered packages will fail-closed at decide time. Either broaden \"roots\" or move the policy under a covered package:',\n ...uncovered,\n ].join('\\n'),\n );\n }\n}\n\n/**\n * Verifies that a policy directory compiles end-to-end with `opa build`.\n *\n * The compiled output is discarded — the server receives the `manifest.json` +\n * `.rego` archive produced by {@link buildOpaBundleTarball}, not the OPA bundle\n * — but a successful build guarantees the policies compile and link, surfacing\n * errors (syntax, missing imports, undefined references, etc.) before upload.\n *\n * @param dir - Absolute path to the policy bundle directory\n */\nasync function assertBundleCompiles(dir: string): Promise<void> {\n const buildOutputPath = path.join(\n os.tmpdir(),\n `transcend-policy-bundle-build-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`,\n );\n try {\n // Run with `cwd` set to the bundle directory and pass `.` so `opa build`\n // resolves the bundle root correctly. `*_test.rego` files are local-only.\n const { code, stderr } = await runOPACapture(\n ['build', '--v0-compatible', '--ignore', '*_test.rego', '-o', buildOutputPath, '.'],\n { cwd: dir },\n );\n if (code !== 0) {\n throw new Error(stderr.trim() || `opa build failed with exit code ${code}`);\n }\n } finally {\n if (fs.existsSync(buildOutputPath)) {\n fs.unlinkSync(buildOutputPath);\n }\n }\n}\n\n/**\n * Formats a byte count as a human-readable size with binary units.\n *\n * @param bytes - Number of bytes\n * @returns Human-readable size, e.g. `14 MiB` or `4 KiB`\n */\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} B`;\n }\n const kib = bytes / 1024;\n if (kib < 1024) {\n return `${kib % 1 === 0 ? kib.toFixed(0) : kib.toFixed(1)} KiB`;\n }\n const mib = kib / 1024;\n return `${mib % 1 === 0 ? mib.toFixed(0) : mib.toFixed(1)} MiB`;\n}\n\n/**\n * Builds a gzip-compressed policy bundle tarball for upload to Transcend.\n *\n * The Policy Engine API expects a plain archive containing `manifest.json` and\n * one or more `.rego` files. This differs from `opa build` output, which embeds\n * `.manifest`, `data.json`, and other OPA bundle metadata that the server\n * rejects. Before packaging, the manifest is validated (shape + root coverage)\n * and the bundle is validated with `opa check` (strict Rego linting) and\n * `opa build` (full compilation) so failures surface client-side rather than\n * after upload.\n *\n * @param dir - Directory containing `manifest.json` and `.rego` policy files\n * @returns Absolute path to the generated `.tar.gz` bundle\n */\nexport async function buildOpaBundleTarball(dir: string): Promise<string> {\n assertOpaInstalled();\n\n const resolvedDir = path.resolve(dir);\n if (!fs.existsSync(resolvedDir) || !fs.statSync(resolvedDir).isDirectory()) {\n throw new Error(`Policy directory does not exist or is not a directory: ${resolvedDir}`);\n }\n\n // Validate the manifest shape and that roots cover every Rego package before\n // invoking OPA, so invalid manifests surface a clear error instead of an\n // opaque `opa build failed with exit code 1`.\n const { entries: archiveEntries, manifest } = collectPolicyBundleArchiveEntries(resolvedDir);\n const regoFiles = archiveEntries.filter((entry) => entry !== 'manifest.json');\n assertRootsCoverPackages(resolvedDir, regoFiles, manifest.roots);\n\n // Match the Rego v1 validation the Policy Engine API runs on upload.\n const { code: checkCode, stderr: checkStderr } = await runOPACapture([\n 'check',\n '--strict',\n '--v0-compatible',\n resolvedDir,\n ]);\n if (checkCode !== 0) {\n throw new Error(checkStderr.trim() || `opa check failed with exit code ${checkCode}`);\n }\n\n // Ensure the bundle compiles end-to-end before packaging for upload.\n await assertBundleCompiles(resolvedDir);\n\n const outputPath = path.join(\n os.tmpdir(),\n `transcend-policy-bundle-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`,\n );\n\n const tarResult = spawnSync('tar', ['-czf', outputPath, '-C', resolvedDir, ...archiveEntries], {\n env: { ...process.env, COPYFILE_DISABLE: '1' },\n encoding: 'utf8',\n });\n if (tarResult.status !== 0) {\n throw new Error(\n `Failed to create policy bundle archive: ${tarResult.stderr.trim() || 'tar failed'}`,\n );\n }\n\n const compressedBytes = fs.readFileSync(outputPath);\n if (compressedBytes.byteLength > MAX_BUNDLE_COMPRESSED_BYTES) {\n fs.unlinkSync(outputPath);\n throw new Error(\n `Policy bundle exceeds the ${formatBytes(MAX_BUNDLE_COMPRESSED_BYTES)} compressed upload limit ` +\n `(bundle is ${formatBytes(compressedBytes.byteLength)}). ` +\n `The server also rejects decompressed bundles larger than ${formatBytes(MAX_BUNDLE_DECOMPRESSED_BYTES)}.`,\n );\n }\n\n const decompressedBytes = gunzipSync(compressedBytes);\n if (decompressedBytes.byteLength > MAX_BUNDLE_DECOMPRESSED_BYTES) {\n fs.unlinkSync(outputPath);\n throw new Error(\n `Policy bundle exceeds the ${formatBytes(MAX_BUNDLE_DECOMPRESSED_BYTES)} decompressed upload limit ` +\n `(bundle is ${formatBytes(decompressedBytes.byteLength)} decompressed).`,\n );\n }\n\n return outputPath;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\n/** Fields for building a policy bundle upload form. */\nexport interface BuildPolicyBundleFormDataOptions {\n /** Absolute path to the bundle tarball */\n bundlePath: string;\n /** Version label */\n version: string;\n /** Optional description */\n description?: string;\n /** Bundle name (only for create) */\n bundleName?: string;\n}\n\n/**\n * Builds multipart form data for a policy bundle upload.\n *\n * @param options - Upload fields\n * @returns FormData ready for POST\n */\nexport function buildPolicyBundleFormData(options: BuildPolicyBundleFormDataOptions): FormData {\n const bundleBytes = fs.readFileSync(options.bundlePath);\n const form = new FormData();\n form.append(\n 'bundle',\n new Blob([bundleBytes], { type: 'application/gzip' }),\n path.basename(options.bundlePath),\n );\n form.append('version', options.version);\n if (options.description) {\n form.append('description', options.description);\n }\n if (options.bundleName) {\n form.append('bundleName', options.bundleName);\n }\n return form;\n}\n","/**\n * Formats a date as `yyyy-mm-dd-hh-mm-ss` in UTC.\n *\n * @param date - Date to format\n * @returns Timestamp label\n */\nfunction formatPolicyVersionTimestamp(date: Date): string {\n return date.toISOString().slice(0, 19).replace(/[T:]/g, '-');\n}\n\n/**\n * Returns a default version label from the bundle name and current UTC timestamp.\n *\n * @param bundleName - Tenant-unique policy bundle name\n * @param now - Current time (for testing)\n * @returns Version label in `{bundleName}-yyyy-mm-dd-hh-mm-ss` form\n */\nexport function defaultPolicyVersionLabel(bundleName: string, now: Date = new Date()): string {\n return `${bundleName}-${formatPolicyVersionTimestamp(now)}`;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { buildExampleCommand } from '../../../lib/docgen/buildExamples.js';\nimport { inquirerConfirmBoolean } from '../../../lib/helpers/inquirer.js';\nimport { logger } from '../../../logger.js';\nimport type { ActivateCommandFlags } from '../activate/impl.js';\nimport {\n buildPolicyBundleFormData,\n buildPolicyEngineClient,\n buildOpaBundleTarball,\n defaultPolicyVersionLabel,\n formatPolicyBundleVersionSummary,\n policyEngineRequest,\n printResult,\n resolveBundleIdByName,\n setPolicyEngineCliDebug,\n} from '../helpers/index.js';\nimport type { CreatePolicyBundleResponse, CreatePolicyBundleVersionResponse } from '../types.js';\n\n/** CLI flags for `transcend policy publish`. */\nexport interface PublishCommandFlags {\n /** Directory containing Rego policy files */\n dir: string;\n /** Tenant-unique bundle name */\n 'bundle-name': string;\n /** Transcend API key */\n auth: string;\n /** Transcend API URL */\n 'transcend-url': string;\n /** Version label (defaults to `{bundleName}-yyyy-mm-dd-hh-mm-ss`) */\n version?: string;\n /** Optional version description */\n description?: string;\n /** Print raw JSON response */\n json: boolean;\n /** Skip the \"create new bundle\" confirmation */\n yes: boolean;\n /** Include technical error details when a command fails */\n debug?: boolean;\n}\n\n/**\n * Build and upload a new immutable policy bundle version.\n *\n * @param this - CLI context\n * @param flags - Command flags\n */\nexport async function publish(\n this: LocalContext,\n {\n dir,\n 'bundle-name': bundleName,\n auth,\n 'transcend-url': transcendUrl,\n version,\n description,\n json,\n yes,\n debug = false,\n }: PublishCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process.exit);\n setPolicyEngineCliDebug(debug);\n\n const resolvedDir = path.resolve(dir);\n const versionLabel = version ?? defaultPolicyVersionLabel(bundleName);\n const client = buildPolicyEngineClient(transcendUrl, auth);\n\n let bundlePath: string | undefined;\n try {\n logger.info(colors.green(`Building policy bundle from ${resolvedDir}...`));\n bundlePath = await buildOpaBundleTarball(resolvedDir);\n\n const existingBundleId = await resolveBundleIdByName(client, bundleName);\n\n let responseBody: CreatePolicyBundleResponse | CreatePolicyBundleVersionResponse;\n\n if (existingBundleId) {\n logger.info(colors.green(`Uploading new version for bundle \"${bundleName}\"...`));\n const form = buildPolicyBundleFormData({\n bundlePath,\n version: versionLabel,\n description,\n });\n responseBody = await policyEngineRequest(\n client\n .post(`v1/policy-engine/policy-bundles/${existingBundleId}/versions`, { body: form })\n .json<CreatePolicyBundleVersionResponse>(),\n );\n } else {\n if (!this.process.stdin.isTTY && !yes) {\n logger.error(\n colors.red(\n 'Cannot create a new bundle in a non-interactive environment; pass --yes to confirm.',\n ),\n );\n this.process.exit(1);\n return;\n }\n\n if (!yes) {\n logger.warn(\n colors.yellow(`No policy bundle named \"${bundleName}\" exists for this organization.`),\n );\n const shouldCreate = await inquirerConfirmBoolean({\n message: `No policy bundle named \"${bundleName}\" exists. Create a new bundle and upload its first version?`,\n });\n if (!shouldCreate) {\n logger.info(colors.yellow('Publish cancelled.'));\n return;\n }\n }\n\n logger.info(colors.green(`Creating bundle \"${bundleName}\" and uploading first version...`));\n const createForm = buildPolicyBundleFormData({\n bundlePath,\n version: versionLabel,\n description,\n bundleName,\n });\n responseBody = await policyEngineRequest(\n client\n .post('v1/policy-engine/policy-bundles', {\n body: createForm,\n })\n .json<CreatePolicyBundleResponse>(),\n );\n }\n\n printResult(this.process.stdout, {\n json,\n data: responseBody,\n renderTable: () => formatPolicyBundleVersionSummary(responseBody.version),\n });\n\n logger.info(colors.green('Policy bundle version uploaded successfully.'));\n\n const activateCommand = buildExampleCommand<ActivateCommandFlags>(['policy', 'activate'], {\n version: responseBody.version.version,\n 'bundle-name': bundleName,\n });\n logger.info(\n colors.yellow(\n `Publishing a policy does not activate it. To activate this version, run:\\n ${activateCommand}`,\n ),\n );\n } finally {\n if (bundlePath && fs.existsSync(bundlePath)) {\n fs.unlinkSync(bundlePath);\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"impl-DjOWgFlT.mjs","names":["fg"],"sources":["../src/commands/policy/helpers/buildOpaBundleTarball.ts","../src/commands/policy/helpers/buildPolicyBundleFormData.ts","../src/commands/policy/helpers/defaultPolicyVersionLabel.ts","../src/commands/policy/publish/impl.ts"],"sourcesContent":["import { spawnSync } from 'node:child_process';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { gunzipSync } from 'node:zlib';\n\nimport fg from 'fast-glob';\n\nimport { MAX_BUNDLE_COMPRESSED_BYTES, MAX_BUNDLE_DECOMPRESSED_BYTES } from '../constants.js';\nimport { assertOpaInstalled } from './assertOpaInstalled.js';\nimport { runOPACapture } from './runOpa.js';\n\n/**\n * Returns whether a relative path is a publishable Rego policy file.\n *\n * OPA test files (`*_test.rego`) are excluded because they are for local\n * validation only and are not part of the upload contract.\n *\n * @param relativePath - Path relative to the bundle directory\n * @returns Whether the file should be included in the upload archive\n */\nfunction isPublishableRegoFile(relativePath: string): boolean {\n return relativePath.endsWith('.rego') && !relativePath.endsWith('_test.rego');\n}\n\n/** Shape of the OPA bundle `manifest.json` as accepted by the Policy Engine. */\ninterface PolicyBundleManifest {\n /** Roots of the bundle, e.g. `[\"policy_engine\"]` or `[\"policy_engine/transcend\"]` */\n roots: string[];\n}\n\n/**\n * Reads and validates `manifest.json` from a policy bundle directory.\n *\n * The Policy Engine requires `manifest.json` to declare `roots` as an array of\n * strings. OPA's own tooling does not always enforce this against the Rego\n * packages on upload, so we validate the shape client-side to surface a clear,\n * actionable error instead of an opaque server `400` or a decide-time\n * fail-closed footgun.\n *\n * @param dir - Absolute path to the policy bundle directory\n * @returns The parsed manifest\n */\nfunction readPolicyBundleManifest(dir: string): PolicyBundleManifest {\n const manifestPath = path.join(dir, 'manifest.json');\n if (!fs.existsSync(manifestPath)) {\n throw new Error('Policy bundle directory must contain a manifest.json file.');\n }\n\n const raw = fs.readFileSync(manifestPath, 'utf8');\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n throw new Error(\n `manifest.json is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error('manifest.json must contain a JSON object.');\n }\n\n const roots = (parsed as { roots?: unknown }).roots;\n if (!Array.isArray(roots) || roots.length === 0) {\n throw new Error(\n 'manifest.json must declare \"roots\" as a non-empty array of strings (e.g. {\"roots\":[\"policy_engine\"]}).',\n );\n }\n\n if (!roots.every((root) => typeof root === 'string' && root.length > 0)) {\n throw new Error('manifest.json \"roots\" must be an array of non-empty strings.');\n }\n\n return { roots };\n}\n\n/** Result of collecting publishable entries from a policy bundle directory. */\ninterface PolicyBundleArchiveContents {\n /** Relative paths to include in the upload tarball (manifest first, then rego) */\n entries: string[];\n /** Parsed manifest */\n manifest: PolicyBundleManifest;\n}\n\n/**\n * Collects `manifest.json` and publishable `.rego` files from a policy directory.\n *\n * @param dir - Absolute path to the policy bundle directory\n * @returns Archive entries and the parsed manifest\n */\nfunction collectPolicyBundleArchiveEntries(dir: string): PolicyBundleArchiveContents {\n const manifest = readPolicyBundleManifest(dir);\n\n const regoFiles = fg\n .sync('**/*.rego', {\n cwd: dir,\n onlyFiles: true,\n dot: false,\n })\n .filter(isPublishableRegoFile);\n\n if (regoFiles.length === 0) {\n throw new Error('Policy bundle directory must contain at least one .rego policy file.');\n }\n\n return { entries: ['manifest.json', ...regoFiles.sort()], manifest };\n}\n\n/** Matches a Rego `package <path>` declaration. */\nconst PACKAGE_DECLARATION_PATTERN = /^\\s*package\\s+([A-Za-z_][\\w.]*)/m;\n\n/**\n * Normalizes an OPA manifest root to a dotted package prefix.\n *\n * Roots use `/` as the path separator (e.g. `policy_engine/transcend`); Rego\n * package paths use `.` (e.g. `policy_engine.transcend`).\n *\n * @param root - A manifest root string\n * @returns The root in dotted form\n */\nfunction normalizeRootToPackagePrefix(root: string): string {\n return root.replace(/\\//g, '.');\n}\n\n/**\n * Reads the Rego package path declared in a `.rego` file.\n *\n * @param filePath - Absolute path to the `.rego` file\n * @returns The dotted package path, or `undefined` if no `package` declaration\n */\nfunction readRegoPackagePath(filePath: string): string | undefined {\n const contents = fs.readFileSync(filePath, 'utf8');\n const match = PACKAGE_DECLARATION_PATTERN.exec(contents);\n return match?.[1];\n}\n\n/**\n * Verifies that every publishable `.rego` package is covered by a manifest root.\n *\n * A bundle whose `roots` do not cover its Rego packages will upload cleanly but\n * fail-closed at decide time — the customer only discovers the mismatch via\n * denied decisions. This surfaces the mismatch at upload with a clear message.\n *\n * @param dir - Absolute path to the policy bundle directory\n * @param regoFiles - Relative paths to publishable `.rego` files\n * @param roots - Manifest roots\n */\nfunction assertRootsCoverPackages(dir: string, regoFiles: string[], roots: string[]): void {\n const rootPrefixes = roots.map(normalizeRootToPackagePrefix);\n\n const uncovered: string[] = [];\n for (const relativeRego of regoFiles) {\n const pkg = readRegoPackagePath(path.join(dir, relativeRego));\n if (!pkg) {\n continue;\n }\n const covered = rootPrefixes.some((prefix) => pkg === prefix || pkg.startsWith(`${prefix}.`));\n if (!covered) {\n uncovered.push(\n ` - ${relativeRego} (package ${pkg}) is not covered by roots [${roots.join(', ')}]`,\n );\n }\n }\n\n if (uncovered.length > 0) {\n throw new Error(\n [\n 'manifest.json \"roots\" do not cover all Rego packages in the bundle; ' +\n 'uncovered packages will fail-closed at decide time. Either broaden \"roots\" or move the policy under a covered package:',\n ...uncovered,\n ].join('\\n'),\n );\n }\n}\n\n/**\n * Verifies that a policy directory compiles end-to-end with `opa build`.\n *\n * The compiled output is discarded — the server receives the `manifest.json` +\n * `.rego` archive produced by {@link buildOpaBundleTarball}, not the OPA bundle\n * — but a successful build guarantees the policies compile and link, surfacing\n * errors (syntax, missing imports, undefined references, etc.) before upload.\n *\n * @param dir - Absolute path to the policy bundle directory\n */\nasync function assertBundleCompiles(dir: string): Promise<void> {\n const buildOutputPath = path.join(\n os.tmpdir(),\n `transcend-policy-bundle-build-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`,\n );\n try {\n // Run with `cwd` set to the bundle directory and pass `.` so `opa build`\n // resolves the bundle root correctly. `*_test.rego` files are local-only.\n const { code, stderr } = await runOPACapture(\n ['build', '--v0-compatible', '--ignore', '*_test.rego', '-o', buildOutputPath, '.'],\n { cwd: dir },\n );\n if (code !== 0) {\n throw new Error(stderr.trim() || `opa build failed with exit code ${code}`);\n }\n } finally {\n if (fs.existsSync(buildOutputPath)) {\n fs.unlinkSync(buildOutputPath);\n }\n }\n}\n\n/**\n * Formats a byte count as a human-readable size with binary units.\n *\n * @param bytes - Number of bytes\n * @returns Human-readable size, e.g. `14 MiB` or `4 KiB`\n */\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} B`;\n }\n const kib = bytes / 1024;\n if (kib < 1024) {\n return `${kib % 1 === 0 ? kib.toFixed(0) : kib.toFixed(1)} KiB`;\n }\n const mib = kib / 1024;\n return `${mib % 1 === 0 ? mib.toFixed(0) : mib.toFixed(1)} MiB`;\n}\n\n/**\n * Builds a gzip-compressed policy bundle tarball for upload to Transcend.\n *\n * The Policy Engine API expects a plain archive containing `manifest.json` and\n * one or more `.rego` files. This differs from `opa build` output, which embeds\n * `.manifest`, `data.json`, and other OPA bundle metadata that the server\n * rejects. Before packaging, the manifest is validated (shape + root coverage)\n * and the bundle is validated with `opa check` (strict Rego linting) and\n * `opa build` (full compilation) so failures surface client-side rather than\n * after upload.\n *\n * @param dir - Directory containing `manifest.json` and `.rego` policy files\n * @returns Absolute path to the generated `.tar.gz` bundle\n */\nexport async function buildOpaBundleTarball(dir: string): Promise<string> {\n assertOpaInstalled();\n\n const resolvedDir = path.resolve(dir);\n if (!fs.existsSync(resolvedDir) || !fs.statSync(resolvedDir).isDirectory()) {\n throw new Error(`Policy directory does not exist or is not a directory: ${resolvedDir}`);\n }\n\n // Validate the manifest shape and that roots cover every Rego package before\n // invoking OPA, so invalid manifests surface a clear error instead of an\n // opaque `opa build failed with exit code 1`.\n const { entries: archiveEntries, manifest } = collectPolicyBundleArchiveEntries(resolvedDir);\n const regoFiles = archiveEntries.filter((entry) => entry !== 'manifest.json');\n assertRootsCoverPackages(resolvedDir, regoFiles, manifest.roots);\n\n // Match the Rego v1 validation the Policy Engine API runs on upload.\n const { code: checkCode, stderr: checkStderr } = await runOPACapture([\n 'check',\n '--strict',\n '--v0-compatible',\n resolvedDir,\n ]);\n if (checkCode !== 0) {\n throw new Error(checkStderr.trim() || `opa check failed with exit code ${checkCode}`);\n }\n\n // Ensure the bundle compiles end-to-end before packaging for upload.\n await assertBundleCompiles(resolvedDir);\n\n const outputPath = path.join(\n os.tmpdir(),\n `transcend-policy-bundle-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`,\n );\n\n const tarResult = spawnSync('tar', ['-czf', outputPath, '-C', resolvedDir, ...archiveEntries], {\n env: { ...process.env, COPYFILE_DISABLE: '1' },\n encoding: 'utf8',\n });\n if (tarResult.status !== 0) {\n throw new Error(\n `Failed to create policy bundle archive: ${tarResult.stderr.trim() || 'tar failed'}`,\n );\n }\n\n const compressedBytes = fs.readFileSync(outputPath);\n if (compressedBytes.byteLength > MAX_BUNDLE_COMPRESSED_BYTES) {\n fs.unlinkSync(outputPath);\n throw new Error(\n `Policy bundle exceeds the ${formatBytes(MAX_BUNDLE_COMPRESSED_BYTES)} compressed upload limit ` +\n `(bundle is ${formatBytes(compressedBytes.byteLength)}). ` +\n `The server also rejects decompressed bundles larger than ${formatBytes(MAX_BUNDLE_DECOMPRESSED_BYTES)}.`,\n );\n }\n\n const decompressedBytes = gunzipSync(compressedBytes);\n if (decompressedBytes.byteLength > MAX_BUNDLE_DECOMPRESSED_BYTES) {\n fs.unlinkSync(outputPath);\n throw new Error(\n `Policy bundle exceeds the ${formatBytes(MAX_BUNDLE_DECOMPRESSED_BYTES)} decompressed upload limit ` +\n `(bundle is ${formatBytes(decompressedBytes.byteLength)} decompressed).`,\n );\n }\n\n return outputPath;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\n/** Fields for building a policy bundle upload form. */\nexport interface BuildPolicyBundleFormDataOptions {\n /** Absolute path to the bundle tarball */\n bundlePath: string;\n /** Version label */\n version: string;\n /** Optional description */\n description?: string;\n /** Bundle name (only for create) */\n bundleName?: string;\n}\n\n/**\n * Builds multipart form data for a policy bundle upload.\n *\n * @param options - Upload fields\n * @returns FormData ready for POST\n */\nexport function buildPolicyBundleFormData(options: BuildPolicyBundleFormDataOptions): FormData {\n const bundleBytes = fs.readFileSync(options.bundlePath);\n const form = new FormData();\n form.append(\n 'bundle',\n new Blob([bundleBytes], { type: 'application/gzip' }),\n path.basename(options.bundlePath),\n );\n form.append('version', options.version);\n if (options.description) {\n form.append('description', options.description);\n }\n if (options.bundleName) {\n form.append('bundleName', options.bundleName);\n }\n return form;\n}\n","/**\n * Formats a date as `yyyy-mm-dd-hh-mm-ss` in UTC.\n *\n * @param date - Date to format\n * @returns Timestamp label\n */\nfunction formatPolicyVersionTimestamp(date: Date): string {\n return date.toISOString().slice(0, 19).replace(/[T:]/g, '-');\n}\n\n/**\n * Returns a default version label from the bundle name and current UTC timestamp.\n *\n * @param bundleName - Tenant-unique policy bundle name\n * @param now - Current time (for testing)\n * @returns Version label in `{bundleName}-yyyy-mm-dd-hh-mm-ss` form\n */\nexport function defaultPolicyVersionLabel(bundleName: string, now: Date = new Date()): string {\n return `${bundleName}-${formatPolicyVersionTimestamp(now)}`;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { buildExampleCommand } from '../../../lib/docgen/buildExamples.js';\nimport { inquirerConfirmBoolean } from '../../../lib/helpers/inquirer.js';\nimport { logger } from '../../../logger.js';\nimport type { ActivateCommandFlags } from '../activate/impl.js';\nimport {\n buildPolicyBundleFormData,\n buildPolicyEngineClient,\n buildOpaBundleTarball,\n defaultPolicyVersionLabel,\n formatPolicyBundleVersionSummary,\n policyEngineRequest,\n printResult,\n resolveBundleIdByName,\n setPolicyEngineCliDebug,\n} from '../helpers/index.js';\nimport type { CreatePolicyBundleResponse, CreatePolicyBundleVersionResponse } from '../types.js';\n\n/** CLI flags for `transcend policy publish`. */\nexport interface PublishCommandFlags {\n /** Directory containing Rego policy files */\n dir: string;\n /** Tenant-unique bundle name */\n 'bundle-name': string;\n /** Transcend API key */\n auth: string;\n /** Transcend API URL */\n 'transcend-url': string;\n /** Version label (defaults to `{bundleName}-yyyy-mm-dd-hh-mm-ss`) */\n version?: string;\n /** Optional version description */\n description?: string;\n /** Print raw JSON response */\n json: boolean;\n /** Skip the \"create new bundle\" confirmation */\n yes: boolean;\n /** Include technical error details when a command fails */\n debug?: boolean;\n}\n\n/**\n * Build and upload a new immutable policy bundle version.\n *\n * @param this - CLI context\n * @param flags - Command flags\n */\nexport async function publish(\n this: LocalContext,\n {\n dir,\n 'bundle-name': bundleName,\n auth,\n 'transcend-url': transcendUrl,\n version,\n description,\n json,\n yes,\n debug = false,\n }: PublishCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process.exit);\n setPolicyEngineCliDebug(debug);\n\n const resolvedDir = path.resolve(dir);\n const versionLabel = version ?? defaultPolicyVersionLabel(bundleName);\n const client = buildPolicyEngineClient(transcendUrl, auth);\n\n let bundlePath: string | undefined;\n try {\n logger.info(colors.green(`Building policy bundle from ${resolvedDir}...`));\n bundlePath = await buildOpaBundleTarball(resolvedDir);\n\n const existingBundleId = await resolveBundleIdByName(client, bundleName);\n\n let responseBody: CreatePolicyBundleResponse | CreatePolicyBundleVersionResponse;\n\n if (existingBundleId) {\n logger.info(colors.green(`Uploading new version for bundle \"${bundleName}\"...`));\n const form = buildPolicyBundleFormData({\n bundlePath,\n version: versionLabel,\n description,\n });\n responseBody = await policyEngineRequest(\n client\n .post(`v1/policy-engine/policy-bundles/${existingBundleId}/versions`, { body: form })\n .json<CreatePolicyBundleVersionResponse>(),\n );\n } else {\n if (!this.process.stdin.isTTY && !yes) {\n logger.error(\n colors.red(\n 'Cannot create a new bundle in a non-interactive environment; pass --yes to confirm.',\n ),\n );\n this.process.exit(1);\n return;\n }\n\n if (!yes) {\n logger.warn(\n colors.yellow(`No policy bundle named \"${bundleName}\" exists for this organization.`),\n );\n const shouldCreate = await inquirerConfirmBoolean({\n message: `No policy bundle named \"${bundleName}\" exists. Create a new bundle and upload its first version?`,\n });\n if (!shouldCreate) {\n logger.info(colors.yellow('Publish cancelled.'));\n return;\n }\n }\n\n logger.info(colors.green(`Creating bundle \"${bundleName}\" and uploading first version...`));\n const createForm = buildPolicyBundleFormData({\n bundlePath,\n version: versionLabel,\n description,\n bundleName,\n });\n responseBody = await policyEngineRequest(\n client\n .post('v1/policy-engine/policy-bundles', {\n body: createForm,\n })\n .json<CreatePolicyBundleResponse>(),\n );\n }\n\n printResult(this.process.stdout, {\n json,\n data: responseBody,\n renderTable: () => formatPolicyBundleVersionSummary(responseBody.version),\n });\n\n logger.info(colors.green('Policy bundle version uploaded successfully.'));\n\n const activateCommand = buildExampleCommand<ActivateCommandFlags>(['policy', 'activate'], {\n version: responseBody.version.version,\n 'bundle-name': bundleName,\n });\n logger.info(\n colors.yellow(\n `Publishing a policy does not activate it. To activate this version, run:\\n ${activateCommand}`,\n ),\n );\n } finally {\n if (bundlePath && fs.existsSync(bundlePath)) {\n fs.unlinkSync(bundlePath);\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./uploadPrivacyRequestsFromCsv-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./uploadPrivacyRequestsFromCsv-BVi19fS8.mjs";import{t}from"./done-input-validation-uqIgnJcw.mjs";import{splitCsvToList as n}from"@transcend-io/utils";async function r({auth:r,file:i,transcendUrl:a,cacheFilepath:o,requestReceiptFolder:s,sombraAuth:c,concurrency:l,attributes:u,isTest:d,isSilent:f,skipSendingReceipt:p,emailIsVerified:m,skipFilterStep:h,dryRun:g,debug:_,defaultPhoneCountryCode:v}){t(this.process.exit),await e({cacheFilepath:o,requestReceiptFolder:s,file:i,auth:r,sombraAuth:c,concurrency:l,transcendUrl:a,defaultPhoneCountryCode:v,attributes:n(u),debug:_,skipFilterStep:h,isSilent:f,skipSendingReceipt:p,emailIsVerified:m,isTest:d,dryRun:g})}export{r as upload};
|
|
2
|
+
//# sourceMappingURL=impl-Dv2AsuuH2.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-Dv2AsuuH2.mjs","names":[],"sources":["../src/commands/request/upload/impl.ts"],"sourcesContent":["import { splitCsvToList } from '@transcend-io/utils';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { uploadPrivacyRequestsFromCsv } from '../../../lib/requests/index.js';\n\nexport interface UploadCommandFlags {\n auth: string;\n file: string;\n transcendUrl: string;\n cacheFilepath: string;\n requestReceiptFolder: string;\n sombraAuth?: string;\n concurrency: number;\n attributes: string;\n isTest: boolean;\n isSilent: boolean;\n skipSendingReceipt: boolean;\n emailIsVerified: boolean;\n skipFilterStep: boolean;\n dryRun: boolean;\n debug: boolean;\n defaultPhoneCountryCode: string;\n}\n\nexport async function upload(\n this: LocalContext,\n {\n auth,\n file,\n transcendUrl,\n cacheFilepath,\n requestReceiptFolder,\n sombraAuth,\n concurrency,\n attributes,\n isTest,\n isSilent,\n skipSendingReceipt,\n emailIsVerified,\n skipFilterStep,\n dryRun,\n debug,\n defaultPhoneCountryCode,\n }: UploadCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process.exit);\n\n await uploadPrivacyRequestsFromCsv({\n cacheFilepath,\n requestReceiptFolder,\n file,\n auth,\n sombraAuth,\n concurrency,\n transcendUrl,\n defaultPhoneCountryCode,\n attributes: splitCsvToList(attributes),\n debug,\n skipFilterStep,\n isSilent,\n skipSendingReceipt,\n emailIsVerified,\n isTest,\n dryRun,\n });\n}\n"],"mappings":"yKAyBA,eAAsB,EAEpB,CACE,OACA,OACA,eACA,gBACA,uBACA,aACA,cACA,aACA,SACA,WACA,qBACA,kBACA,iBACA,SACA,QACA,2BAEa,CACf,EAAoB,KAAK,QAAQ,KAAK,CAEtC,MAAM,EAA6B,CACjC,gBACA,uBACA,OACA,OACA,aACA,cACA,eACA,0BACA,WAAY,EAAe,EAAW,CACtC,QACA,iBACA,WACA,qBACA,kBACA,SACA,SACD,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./uploadDataFlowsFromCsv-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./uploadDataFlowsFromCsv-Ct0rye94.mjs";import{t}from"./done-input-validation-uqIgnJcw.mjs";async function n({auth:n,trackerStatus:r,file:i,classifyService:a,transcendUrl:o}){t(this.process.exit),await e({auth:n,trackerStatus:r,file:i,classifyService:a,transcendUrl:o})}export{n as uploadDataFlowsFromCsv};
|
|
2
|
+
//# sourceMappingURL=impl-X50_5E1x.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-X50_5E1x.mjs","names":["uploadDataFlowsFromCsvHelper"],"sources":["../src/commands/consent/upload-data-flows-from-csv/impl.ts"],"sourcesContent":["import { ConsentTrackerStatus } from '@transcend-io/privacy-types';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { uploadDataFlowsFromCsv as uploadDataFlowsFromCsvHelper } from '../../../lib/consent-manager/index.js';\n\nexport interface UploadDataFlowsFromCsvCommandFlags {\n auth: string;\n trackerStatus: ConsentTrackerStatus;\n file: string;\n classifyService: boolean;\n transcendUrl: string;\n}\n\nexport async function uploadDataFlowsFromCsv(\n this: LocalContext,\n { auth, trackerStatus, file, classifyService, transcendUrl }: UploadDataFlowsFromCsvCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process.exit);\n\n await uploadDataFlowsFromCsvHelper({\n auth,\n trackerStatus,\n file,\n classifyService,\n transcendUrl,\n });\n}\n"],"mappings":"8GAcA,eAAsB,EAEpB,CAAE,OAAM,gBAAe,OAAM,kBAAiB,gBAC/B,CACf,EAAoB,KAAK,QAAQ,KAAK,CAEtC,MAAMA,EAA6B,CACjC,OACA,gBACA,OACA,kBACA,eACD,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{n as e}from"./constants-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{n as e}from"./constants-Ch1Lt8Wa.mjs";import{t}from"./logger-Ckep4QXn.mjs";import{s as n}from"./writeCsv-BMVkiMHM.mjs";import{t as r}from"./pullAllDatapoints-Bvv9KRR5.mjs";import{t as i}from"./done-input-validation-uqIgnJcw.mjs";import{groupBy as a,uniq as o}from"lodash-es";import s from"colors";import{buildTranscendGraphQLClient as c}from"@transcend-io/sdk";async function l({auth:l,file:u,transcendUrl:d,dataSiloIds:f,includeAttributes:p,includeGuessedCategories:m,parentCategories:h,subCategories:g=[]}){i(this.process.exit);try{let e=await r(c(d,l),{dataSiloIds:f,includeGuessedCategories:m,parentCategories:h,includeAttributes:p,subCategories:g});t.info(s.magenta(`Writing datapoints to file "${u}"...`));let i=[];await n(u,e.map(e=>{let t={"Property ID":e.id,"Data Silo":e.dataSilo.title,Object:e.dataPoint.name,"Object Path":e.dataPoint.path.join(`.`),Property:e.name,"Property Description":e.description,"Data Categories":e.categories.map(e=>`${e.category}:${e.name}`).join(`, `),"Guessed Category":e.pendingCategoryGuesses?.[0]?`${e.pendingCategoryGuesses[0].category.category}:${e.pendingCategoryGuesses[0].category.name}`:``,"Processing Purposes":e.purposes.map(e=>`${e.purpose}:${e.name}`).join(`, `),...Object.entries(a(e.attributeValues||[],({attributeKey:e})=>e.name)).reduce((e,[t,n])=>(e[t]=n.map(e=>e.name).join(`,`),e),{})};return i=o([...i,...Object.keys(t)]),t}),i)}catch(e){t.error(s.red(`An error occurred syncing the datapoints: ${e.message}`)),this.process.exit(1)}t.info(s.green(`Successfully synced datapoints to disk at ${u}! View at ${e}`))}export{l as pullDatapoints};
|
|
2
|
+
//# sourceMappingURL=impl-iBottQJe.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-iBottQJe.mjs","names":[],"sources":["../src/commands/inventory/pull-datapoints/impl.ts"],"sourcesContent":["import { DataCategoryType } from '@transcend-io/privacy-types';\nimport { buildTranscendGraphQLClient } from '@transcend-io/sdk';\nimport colors from 'colors';\nimport { uniq, groupBy } from 'lodash-es';\n\nimport { ADMIN_DASH_DATAPOINTS } from '../../../constants.js';\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { pullAllDatapoints } from '../../../lib/data-inventory/index.js';\nimport { writeLargeCsv } from '../../../lib/helpers/index.js';\nimport { logger } from '../../../logger.js';\n\nexport interface PullDatapointsCommandFlags {\n auth: string;\n file: string;\n transcendUrl: string;\n dataSiloIds?: string[];\n includeAttributes: boolean;\n includeGuessedCategories: boolean;\n parentCategories?: DataCategoryType[];\n subCategories?: string[];\n}\n\nexport async function pullDatapoints(\n this: LocalContext,\n {\n auth,\n file,\n transcendUrl,\n dataSiloIds,\n includeAttributes,\n includeGuessedCategories,\n parentCategories,\n subCategories = [],\n }: PullDatapointsCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process.exit);\n\n try {\n // Create a GraphQL client\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n const dataPoints = await pullAllDatapoints(client, {\n dataSiloIds,\n includeGuessedCategories,\n parentCategories,\n includeAttributes,\n subCategories, // TODO: https://transcend.height.app/T-40482 - do by name not ID\n });\n\n logger.info(colors.magenta(`Writing datapoints to file \"${file}\"...`));\n let headers: string[] = [];\n const inputs = dataPoints.map((point) => {\n const result = {\n 'Property ID': point.id,\n 'Data Silo': point.dataSilo.title,\n Object: point.dataPoint.name,\n 'Object Path': point.dataPoint.path.join('.'),\n Property: point.name,\n 'Property Description': point.description,\n 'Data Categories': point.categories\n .map((category) => `${category.category}:${category.name}`)\n .join(', '),\n 'Guessed Category': point.pendingCategoryGuesses?.[0]\n ? `${point.pendingCategoryGuesses![0]!.category.category}:${\n point.pendingCategoryGuesses![0]!.category.name\n }`\n : '',\n 'Processing Purposes': point.purposes\n .map((purpose) => `${purpose.purpose}:${purpose.name}`)\n .join(', '),\n ...Object.entries(\n groupBy(point.attributeValues || [], ({ attributeKey }) => attributeKey.name),\n ).reduce(\n (acc, [key, values]) => {\n acc[key] = values.map((value) => value.name).join(',');\n return acc;\n },\n {} as Record<string, string>,\n ),\n };\n headers = uniq([...headers, ...Object.keys(result)]);\n return result;\n });\n await writeLargeCsv(file, inputs, headers);\n } catch (err) {\n logger.error(colors.red(`An error occurred syncing the datapoints: ${err.message}`));\n this.process.exit(1);\n }\n\n // Indicate success\n logger.info(\n colors.green(\n `Successfully synced datapoints to disk at ${file}! View at ${ADMIN_DASH_DATAPOINTS}`,\n ),\n );\n}\n"],"mappings":"gXAuBA,eAAsB,EAEpB,CACE,OACA,OACA,eACA,cACA,oBACA,2BACA,mBACA,gBAAgB,EAAE,EAEL,CACf,EAAoB,KAAK,QAAQ,KAAK,CAEtC,GAAI,CAIF,IAAM,EAAa,MAAM,EAFV,EAA4B,EAAc,EAER,CAAE,CACjD,cACA,2BACA,mBACA,oBACA,gBACD,CAAC,CAEF,EAAO,KAAK,EAAO,QAAQ,+BAA+B,EAAK,MAAM,CAAC,CACtE,IAAI,EAAoB,EAAE,CAiC1B,MAAM,EAAc,EAhCL,EAAW,IAAK,GAAU,CACvC,IAAM,EAAS,CACb,cAAe,EAAM,GACrB,YAAa,EAAM,SAAS,MAC5B,OAAQ,EAAM,UAAU,KACxB,cAAe,EAAM,UAAU,KAAK,KAAK,IAAI,CAC7C,SAAU,EAAM,KAChB,uBAAwB,EAAM,YAC9B,kBAAmB,EAAM,WACtB,IAAK,GAAa,GAAG,EAAS,SAAS,GAAG,EAAS,OAAO,CAC1D,KAAK,KAAK,CACb,mBAAoB,EAAM,yBAAyB,GAC/C,GAAG,EAAM,uBAAwB,GAAI,SAAS,SAAS,GACrD,EAAM,uBAAwB,GAAI,SAAS,OAE7C,GACJ,sBAAuB,EAAM,SAC1B,IAAK,GAAY,GAAG,EAAQ,QAAQ,GAAG,EAAQ,OAAO,CACtD,KAAK,KAAK,CACb,GAAG,OAAO,QACR,EAAQ,EAAM,iBAAmB,EAAE,EAAG,CAAE,kBAAmB,EAAa,KAAK,CAC9E,CAAC,QACC,EAAK,CAAC,EAAK,MACV,EAAI,GAAO,EAAO,IAAK,GAAU,EAAM,KAAK,CAAC,KAAK,IAAI,CAC/C,GAET,EAAE,CACH,CACF,CAED,MADA,GAAU,EAAK,CAAC,GAAG,EAAS,GAAG,OAAO,KAAK,EAAO,CAAC,CAAC,CAC7C,GAEuB,CAAE,EAAQ,OACnC,EAAK,CACZ,EAAO,MAAM,EAAO,IAAI,6CAA6C,EAAI,UAAU,CAAC,CACpF,KAAK,QAAQ,KAAK,EAAE,CAItB,EAAO,KACL,EAAO,MACL,6CAA6C,EAAK,YAAY,IAC/D,CACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./bulkRestartRequests-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./bulkRestartRequests-CSBPINdi.mjs";import{t}from"./done-input-validation-uqIgnJcw.mjs";async function n({auth:n,requestReceiptFolder:r,sombraAuth:i,actions:a,statuses:o,requestIds:s,createdAt:c,emailIsVerified:l,silentModeBefore:u,sendEmailReceipt:d,copyIdentifiers:f,restartIdentifierStrategy:p,skipWaitingPeriod:m,createdAtBefore:h,createdAtAfter:g,updatedAtBefore:_,updatedAtAfter:v,concurrency:y,transcendUrl:b}){t(this.process.exit),await e({requestReceiptFolder:r,auth:n,sombraAuth:i,requestActions:a,requestStatuses:o,requestIds:s,createdAt:c,emailIsVerified:l,silentModeBefore:u,sendEmailReceipt:d,copyIdentifiers:f,restartIdentifierStrategy:p,skipWaitingPeriod:m,createdAtBefore:h,createdAtAfter:g,updatedAtBefore:_,updatedAtAfter:v,concurrency:y,transcendUrl:b})}export{n as restart};
|
|
2
|
+
//# sourceMappingURL=impl-iGEtfSgW2.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-iGEtfSgW2.mjs","names":[],"sources":["../src/commands/request/restart/impl.ts"],"sourcesContent":["import type {\n RequestAction,\n RequestStatus,\n RestartIdentifierStrategy,\n} from '@transcend-io/privacy-types';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { bulkRestartRequests } from '../../../lib/requests/index.js';\n\nexport interface RestartCommandFlags {\n auth: string;\n actions: RequestAction[];\n statuses: RequestStatus[];\n transcendUrl: string;\n requestReceiptFolder: string;\n sombraAuth?: string;\n concurrency: number;\n requestIds?: string[];\n emailIsVerified: boolean;\n createdAt?: Date;\n silentModeBefore?: Date;\n createdAtBefore?: Date;\n createdAtAfter?: Date;\n updatedAtBefore?: Date;\n updatedAtAfter?: Date;\n sendEmailReceipt: boolean;\n copyIdentifiers: boolean;\n restartIdentifierStrategy?: RestartIdentifierStrategy;\n skipWaitingPeriod: boolean;\n}\n\nexport async function restart(\n this: LocalContext,\n {\n auth,\n requestReceiptFolder,\n sombraAuth,\n actions,\n statuses,\n requestIds,\n createdAt,\n emailIsVerified,\n silentModeBefore,\n sendEmailReceipt,\n copyIdentifiers,\n restartIdentifierStrategy,\n skipWaitingPeriod,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n concurrency,\n transcendUrl,\n }: RestartCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process.exit);\n\n await bulkRestartRequests({\n requestReceiptFolder,\n auth,\n sombraAuth,\n requestActions: actions,\n requestStatuses: statuses,\n requestIds,\n createdAt,\n emailIsVerified,\n silentModeBefore,\n sendEmailReceipt,\n copyIdentifiers,\n restartIdentifierStrategy,\n skipWaitingPeriod,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n concurrency,\n transcendUrl,\n });\n}\n"],"mappings":"2GAgCA,eAAsB,EAEpB,CACE,OACA,uBACA,aACA,UACA,WACA,aACA,YACA,kBACA,mBACA,mBACA,kBACA,4BACA,oBACA,kBACA,iBACA,kBACA,iBACA,cACA,gBAEa,CACf,EAAoB,KAAK,QAAQ,KAAK,CAEtC,MAAM,EAAoB,CACxB,uBACA,OACA,aACA,eAAgB,EAChB,gBAAiB,EACjB,aACA,YACA,kBACA,mBACA,mBACA,kBACA,4BACA,oBACA,kBACA,iBACA,kBACA,iBACA,cACA,eACD,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{t as e}from"./constants-
|
|
1
|
+
import{t as e}from"./constants-Ch1Lt8Wa.mjs";import{t}from"./logger-Ckep4QXn.mjs";import{t as n}from"./done-input-validation-uqIgnJcw.mjs";import{n as r}from"./constants-DNF09zFX.mjs";import i from"fast-glob";import a from"colors";import{buildTranscendGraphQLClient as o,fetchActiveSiloDiscoPlugin as s,uploadSiloDiscoveryResults as c}from"@transcend-io/sdk";import{stringify as l}from"query-string";async function u({scanPath:e,fileGlobs:n,ignoreDirs:r,config:a}){let{ignoreDirs:o,supportedFiles:s,scanFunction:c}=a,l=n===``?s:s.concat(n.split(`,`)),d=[...r.split(`,`),...o].filter(e=>e.length>0);try{let n=await i(`${e}/**/${l.join(`|`)}`,{ignore:d.map(t=>`${e}/**/${t}`),unique:!0,onlyFiles:!0});t.info(`Scanning: ${n.length} files`);let r=n.map(e=>c(e)).flat().map(e=>e.softwareDevelopmentKits||[]).flat(),a=[...new Set(r.map(e=>e.name))];return t.info(`Found: ${a.length} unique dependencies`),a.map(t=>({name:t,resourceId:`${e}/**/${t}`,useStrictClassifier:!0}))}catch(e){throw Error(`Error scanning globs ${u} with error: ${e}`)}}async function d({scanPath:i,dataSiloId:d,auth:f,fileGlobs:p,ignoreDirs:m,transcendUrl:h}){n(this.process.exit);let g=o(h,f),_=await s(g,{logger:t,filterBy:{dataSiloId:d}}),v=r[_.dataSilo.type];v||(t.error(a.red(`This plugin "${_.dataSilo.type}" is not supported for offline silo discovery.`)),this.process.exit(1));let y=await u({scanPath:i,fileGlobs:p,ignoreDirs:m,config:v});await c(g,{pluginId:_.id,results:y,logger:t});let b=new URL(e);b.pathname=`/data-map/data-inventory/silo-discovery/triage`,b.search=l({filters:JSON.stringify({pluginIds:[_.id]})}),t.info(a.green(`Scan found ${y.length} potential data silos at ${i}! View at '${b.href}'
|
|
2
2
|
|
|
3
3
|
NOTE: it may take 2-3 minutes for scan results to appear in the UI.`))}export{d as discoverSilos};
|
|
4
|
-
//# sourceMappingURL=impl-
|
|
4
|
+
//# sourceMappingURL=impl-m1WDTmQO.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-m1WDTmQO.mjs","names":[],"sources":["../src/lib/code-scanning/findFilesToScan.ts","../src/commands/inventory/discover-silos/impl.ts"],"sourcesContent":["import fastGlob from 'fast-glob';\n\nimport { logger } from '../../logger.js';\nimport { CodeScanningConfig } from './types.js';\n\nexport interface SiloDiscoveryRawResults {\n /** The name of the potential data silo entry */\n name: string;\n /** A unique UUID (represents the same resource across different silo discovery runs) */\n resourceId: string;\n /** Any hosts associated with the entry */\n host?: string;\n /** Type of data silo */\n type?: string | undefined;\n}\n\n/**\n * Helper to scan for data silos in all package.json files that it can find in a directory\n *\n * @deprecated TODO: https://transcend.height.app/T-32325 - use code scanning instead\n * @param options - Options\n * @returns the list of integrations\n */\nexport async function findFilesToScan({\n scanPath,\n fileGlobs,\n ignoreDirs,\n config,\n}: {\n /** Where to look for package.json files */\n scanPath: string;\n /** Globs to look for */\n fileGlobs: string;\n /** The directories to ignore (excludes node_modules and serverless-build) */\n ignoreDirs: string;\n /** Silo Discovery configuration */\n config: CodeScanningConfig;\n}): Promise<SiloDiscoveryRawResults[]> {\n const { ignoreDirs: IGNORE_DIRS, supportedFiles, scanFunction } = config;\n const globsToSupport =\n fileGlobs === '' ? supportedFiles : supportedFiles.concat(fileGlobs.split(','));\n const dirsToIgnore = [...ignoreDirs.split(','), ...IGNORE_DIRS].filter((dir) => dir.length > 0);\n try {\n const filesToScan: string[] = await fastGlob(`${scanPath}/**/${globsToSupport.join('|')}`, {\n ignore: dirsToIgnore.map((dir: string) => `${scanPath}/**/${dir}`),\n unique: true,\n onlyFiles: true,\n });\n logger.info(`Scanning: ${filesToScan.length} files`);\n const allPackages = filesToScan.map((filePath: string) => scanFunction(filePath)).flat();\n const allSdks = allPackages\n .map((appPackage) => appPackage.softwareDevelopmentKits || [])\n .flat();\n const uniqueDeps = new Set(allSdks.map((sdk) => sdk.name));\n const deps = [...uniqueDeps];\n logger.info(`Found: ${deps.length} unique dependencies`);\n return deps.map((dep) => ({\n name: dep,\n resourceId: `${scanPath}/**/${dep}`,\n useStrictClassifier: true,\n }));\n } catch (error) {\n throw new Error(`Error scanning globs ${findFilesToScan} with error: ${error}`);\n }\n}\n","import {\n buildTranscendGraphQLClient,\n fetchActiveSiloDiscoPlugin,\n uploadSiloDiscoveryResults,\n} from '@transcend-io/sdk';\nimport colors from 'colors';\nimport { stringify } from 'query-string';\n\nimport { ADMIN_DASH } from '../../../constants.js';\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { findFilesToScan } from '../../../lib/code-scanning/findFilesToScan.js';\nimport { SILO_DISCOVERY_CONFIGS } from '../../../lib/code-scanning/index.js';\nimport { logger } from '../../../logger.js';\n\nexport interface DiscoverSilosCommandFlags {\n scanPath: string;\n dataSiloId: string;\n auth: string;\n fileGlobs: string;\n ignoreDirs: string;\n transcendUrl: string;\n}\n\nexport async function discoverSilos(\n this: LocalContext,\n { scanPath, dataSiloId, auth, fileGlobs, ignoreDirs, transcendUrl }: DiscoverSilosCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process.exit);\n\n // Create a GraphQL client\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n const plugin = await fetchActiveSiloDiscoPlugin(client, {\n logger,\n filterBy: { dataSiloId },\n });\n\n const config = SILO_DISCOVERY_CONFIGS[plugin.dataSilo.type];\n if (!config) {\n logger.error(\n colors.red(\n `This plugin \"${plugin.dataSilo.type}\" is not supported for offline silo discovery.`,\n ),\n );\n this.process.exit(1);\n }\n\n const results = await findFilesToScan({\n scanPath,\n fileGlobs,\n ignoreDirs,\n config,\n });\n\n await uploadSiloDiscoveryResults(client, {\n pluginId: plugin.id,\n results,\n logger,\n });\n\n const newUrl = new URL(ADMIN_DASH);\n newUrl.pathname = '/data-map/data-inventory/silo-discovery/triage';\n newUrl.search = stringify({\n filters: JSON.stringify({ pluginIds: [plugin.id] }),\n });\n\n // Indicate success\n logger.info(\n colors.green(\n `Scan found ${results.length} potential data silos at ${scanPath}! ` +\n `View at '${newUrl.href}' ` +\n '\\n\\n NOTE: it may take 2-3 minutes for scan results to appear in the UI.',\n ),\n );\n}\n"],"mappings":"gZAuBA,eAAsB,EAAgB,CACpC,WACA,YACA,aACA,UAUqC,CACrC,GAAM,CAAE,WAAY,EAAa,iBAAgB,gBAAiB,EAC5D,EACJ,IAAc,GAAK,EAAiB,EAAe,OAAO,EAAU,MAAM,IAAI,CAAC,CAC3E,EAAe,CAAC,GAAG,EAAW,MAAM,IAAI,CAAE,GAAG,EAAY,CAAC,OAAQ,GAAQ,EAAI,OAAS,EAAE,CAC/F,GAAI,CACF,IAAM,EAAwB,MAAM,EAAS,GAAG,EAAS,MAAM,EAAe,KAAK,IAAI,GAAI,CACzF,OAAQ,EAAa,IAAK,GAAgB,GAAG,EAAS,MAAM,IAAM,CAClE,OAAQ,GACR,UAAW,GACZ,CAAC,CACF,EAAO,KAAK,aAAa,EAAY,OAAO,QAAQ,CAEpD,IAAM,EADc,EAAY,IAAK,GAAqB,EAAa,EAAS,CAAC,CAAC,MACvD,CACxB,IAAK,GAAe,EAAW,yBAA2B,EAAE,CAAC,CAC7D,MAAM,CAEH,EAAO,CAAC,GAAG,IADM,IAAI,EAAQ,IAAK,GAAQ,EAAI,KAAK,CAC9B,CAAC,CAE5B,OADA,EAAO,KAAK,UAAU,EAAK,OAAO,sBAAsB,CACjD,EAAK,IAAK,IAAS,CACxB,KAAM,EACN,WAAY,GAAG,EAAS,MAAM,IAC9B,oBAAqB,GACtB,EAAE,OACI,EAAO,CACd,MAAU,MAAM,wBAAwB,EAAgB,eAAe,IAAQ,ECtCnF,eAAsB,EAEpB,CAAE,WAAU,aAAY,OAAM,YAAW,aAAY,gBACtC,CACf,EAAoB,KAAK,QAAQ,KAAK,CAGtC,IAAM,EAAS,EAA4B,EAAc,EAAK,CAExD,EAAS,MAAM,EAA2B,EAAQ,CACtD,SACA,SAAU,CAAE,aAAY,CACzB,CAAC,CAEI,EAAS,EAAuB,EAAO,SAAS,MACjD,IACH,EAAO,MACL,EAAO,IACL,gBAAgB,EAAO,SAAS,KAAK,gDACtC,CACF,CACD,KAAK,QAAQ,KAAK,EAAE,EAGtB,IAAM,EAAU,MAAM,EAAgB,CACpC,WACA,YACA,aACA,SACD,CAAC,CAEF,MAAM,EAA2B,EAAQ,CACvC,SAAU,EAAO,GACjB,UACA,SACD,CAAC,CAEF,IAAM,EAAS,IAAI,IAAI,EAAW,CAClC,EAAO,SAAW,iDAClB,EAAO,OAAS,EAAU,CACxB,QAAS,KAAK,UAAU,CAAE,UAAW,CAAC,EAAO,GAAG,CAAE,CAAC,CACpD,CAAC,CAGF,EAAO,KACL,EAAO,MACL,cAAc,EAAQ,OAAO,2BAA2B,EAAS,aACnD,EAAO,KAAK;;sEAE3B,CACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./skipPreflightJobs-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./skipPreflightJobs-BrBvyKxG.mjs";import{t}from"./done-input-validation-uqIgnJcw.mjs";async function n({auth:n,transcendUrl:r,enricherIds:i}){t(this.process.exit),await e({transcendUrl:r,auth:n,enricherIds:i})}export{n as skipPreflightJobs};
|
|
2
|
+
//# sourceMappingURL=impl-o0RdOoiZ2.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-o0RdOoiZ2.mjs","names":["skipPreflightJobsHelper"],"sources":["../src/commands/request/skip-preflight-jobs/impl.ts"],"sourcesContent":["import type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { skipPreflightJobs as skipPreflightJobsHelper } from '../../../lib/requests/index.js';\n\nexport interface SkipPreflightJobsCommandFlags {\n auth: string;\n enricherIds: string[];\n transcendUrl: string;\n}\n\nexport async function skipPreflightJobs(\n this: LocalContext,\n { auth, transcendUrl, enricherIds }: SkipPreflightJobsCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process.exit);\n\n await skipPreflightJobsHelper({\n transcendUrl,\n auth,\n enricherIds,\n });\n}\n"],"mappings":"yGAUA,eAAsB,EAEpB,CAAE,OAAM,eAAc,eACP,CACf,EAAoB,KAAK,QAAQ,KAAK,CAEtC,MAAMA,EAAwB,CAC5B,eACA,OACA,cACD,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./logger-Ckep4QXn.mjs";import{t}from"./readCsv--FfP8n-H.mjs";import{t as n}from"./markRequestDataSiloIdsCompleted-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./logger-Ckep4QXn.mjs";import{t}from"./readCsv--FfP8n-H.mjs";import{t as n}from"./markRequestDataSiloIdsCompleted-C7HAJehS.mjs";import{t as r}from"./done-input-validation-uqIgnJcw.mjs";import i from"colors";import*as a from"io-ts";const o=a.type({"Request Id":a.string});async function s({auth:a,dataSiloId:s,file:c,transcendUrl:l}){r(this.process.exit),e.info(i.magenta(`Reading "${c}" from disk`)),await n({requestIds:t(c,o).map(e=>e[`Request Id`]),transcendUrl:l,auth:a,dataSiloId:s})}export{s as markRequestDataSilosCompleted};
|
|
2
|
+
//# sourceMappingURL=impl-rTqHhQ7X2.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-rTqHhQ7X2.mjs","names":[],"sources":["../src/commands/request/system/mark-request-data-silos-completed/impl.ts"],"sourcesContent":["import colors from 'colors';\nimport * as t from 'io-ts';\n\nimport type { LocalContext } from '../../../../context.js';\nimport { doneInputValidation } from '../../../../lib/cli/done-input-validation.js';\nimport { markRequestDataSiloIdsCompleted } from '../../../../lib/cron/index.js';\nimport { readCsv } from '../../../../lib/requests/index.js';\nimport { logger } from '../../../../logger.js';\n\nconst RequestIdRow = t.type({\n 'Request Id': t.string,\n});\n\nexport interface MarkRequestDataSilosCompletedCommandFlags {\n auth: string;\n dataSiloId: string;\n file: string;\n transcendUrl: string;\n}\n\nexport async function markRequestDataSilosCompleted(\n this: LocalContext,\n { auth, dataSiloId, file, transcendUrl }: MarkRequestDataSilosCompletedCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process.exit);\n\n logger.info(colors.magenta(`Reading \"${file}\" from disk`));\n const activeResults = readCsv(file, RequestIdRow);\n\n await markRequestDataSiloIdsCompleted({\n requestIds: activeResults.map((request) => request['Request Id']),\n transcendUrl,\n auth,\n dataSiloId,\n });\n}\n"],"mappings":"0PASA,MAAM,EAAe,EAAE,KAAK,CAC1B,aAAc,EAAE,OACjB,CAAC,CASF,eAAsB,EAEpB,CAAE,OAAM,aAAY,OAAM,gBACX,CACf,EAAoB,KAAK,QAAQ,KAAK,CAEtC,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAK,aAAa,CAAC,CAG1D,MAAM,EAAgC,CACpC,WAHoB,EAAQ,EAAM,EAGT,CAAC,IAAK,GAAY,EAAQ,cAAc,CACjE,eACA,OACA,aACD,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./retryRequestDataSilos-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./retryRequestDataSilos-pQ4DekAX.mjs";import{t}from"./done-input-validation-uqIgnJcw.mjs";async function n({auth:n,dataSiloId:r,actions:i,transcendUrl:a}){t(this.process.exit),await e({requestActions:i,transcendUrl:a,auth:n,dataSiloId:r})}export{n as retryRequestDataSilos};
|
|
2
|
+
//# sourceMappingURL=impl-tNN3yVw72.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-tNN3yVw72.mjs","names":["retryRequestDataSilosHelper"],"sources":["../src/commands/request/system/retry-request-data-silos/impl.ts"],"sourcesContent":["import type { RequestAction } from '@transcend-io/privacy-types';\n\nimport type { LocalContext } from '../../../../context.js';\nimport { doneInputValidation } from '../../../../lib/cli/done-input-validation.js';\nimport { retryRequestDataSilos as retryRequestDataSilosHelper } from '../../../../lib/requests/index.js';\n\nexport interface RetryRequestDataSilosCommandFlags {\n auth: string;\n dataSiloId: string;\n actions: RequestAction[];\n transcendUrl: string;\n}\n\nexport async function retryRequestDataSilos(\n this: LocalContext,\n { auth, dataSiloId, actions, transcendUrl }: RetryRequestDataSilosCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process.exit);\n\n await retryRequestDataSilosHelper({\n requestActions: actions,\n transcendUrl,\n auth,\n dataSiloId,\n });\n}\n"],"mappings":"6GAaA,eAAsB,EAEpB,CAAE,OAAM,aAAY,UAAS,gBACd,CACf,EAAoB,KAAK,QAAQ,KAAK,CAEtC,MAAMA,EAA4B,CAChC,eAAgB,EAChB,eACA,OACA,aACD,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./logger-Ckep4QXn.mjs";import{t}from"./pullChunkedCustomSiloOutstandingIdentifiers-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./logger-Ckep4QXn.mjs";import{t}from"./pullChunkedCustomSiloOutstandingIdentifiers-D_TkvoKK.mjs";import{i as n,s as r}from"./writeCsv-BMVkiMHM.mjs";import{t as i}from"./done-input-validation-uqIgnJcw.mjs";import{uniq as a}from"lodash-es";import o from"colors";async function s({file:s,transcendUrl:c,auth:l,sombraAuth:u,dataSiloId:d,actions:f,pageLimit:p,skipRequestCount:m,chunkSize:h}){m&&e.info(o.yellow(`Skipping request count as requested. This may help speed up the call.`)),(Number.isNaN(h)||h<=0||h%p!==0)&&(e.error(o.red(`Invalid chunk size: "${h}". Must be a positive integer that is a multiple of ${p}.`)),this.process.exit(1)),i(this.process.exit);let{baseName:g,extension:_}=n(s),v=0;await t({transcendUrl:c,apiPageSize:p,savePageSize:h,onSave:async t=>{let n=`${g}-${v}${_}`;return e.info(o.blue(`Saving ${t.length} identifiers to file "${n}"`)),await r(n,t,a(t.map(e=>Object.keys(e)).flat())),e.info(o.green(`Successfully wrote ${t.length} identifiers to file "${n}"`)),v+=1,Promise.resolve()},actions:f,auth:l,sombraAuth:u,dataSiloId:d,skipRequestCount:m})}export{s as pullIdentifiers};
|
|
2
|
+
//# sourceMappingURL=impl-xNSHqJyt2.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-xNSHqJyt2.mjs","names":[],"sources":["../src/commands/request/cron/pull-identifiers/impl.ts"],"sourcesContent":["import { RequestAction } from '@transcend-io/privacy-types';\nimport colors from 'colors';\nimport { uniq } from 'lodash-es';\n\nimport type { LocalContext } from '../../../../context.js';\nimport { doneInputValidation } from '../../../../lib/cli/done-input-validation.js';\nimport {\n CsvFormattedIdentifier,\n pullChunkedCustomSiloOutstandingIdentifiers,\n} from '../../../../lib/cron/index.js';\nimport { parseFilePath, writeLargeCsv } from '../../../../lib/helpers/index.js';\nimport { logger } from '../../../../logger.js';\n\nexport interface PullIdentifiersCommandFlags {\n file: string;\n transcendUrl: string;\n auth: string;\n sombraAuth?: string;\n dataSiloId: string;\n actions: RequestAction[];\n pageLimit: number;\n skipRequestCount: boolean;\n chunkSize: number;\n}\n\nexport async function pullIdentifiers(\n this: LocalContext,\n {\n file,\n transcendUrl,\n auth,\n sombraAuth,\n dataSiloId,\n actions,\n pageLimit,\n skipRequestCount,\n chunkSize,\n }: PullIdentifiersCommandFlags,\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 const { baseName, extension } = parseFilePath(file);\n let fileCount = 0;\n\n const onSave = async (chunk: CsvFormattedIdentifier[]): Promise<void> => {\n const numberedFileName = `${baseName}-${fileCount}${extension}`;\n logger.info(colors.blue(`Saving ${chunk.length} identifiers to file \"${numberedFileName}\"`));\n\n const headers = uniq(chunk.map((d) => Object.keys(d)).flat());\n await writeLargeCsv(numberedFileName, chunk, headers);\n logger.info(\n colors.green(`Successfully wrote ${chunk.length} identifiers to file \"${numberedFileName}\"`),\n );\n fileCount += 1;\n return Promise.resolve();\n };\n\n // Pull down outstanding identifiers\n await pullChunkedCustomSiloOutstandingIdentifiers({\n transcendUrl,\n apiPageSize: pageLimit,\n savePageSize: chunkSize,\n onSave,\n actions,\n auth,\n sombraAuth,\n dataSiloId,\n skipRequestCount,\n });\n}\n"],"mappings":"uRAyBA,eAAsB,EAEpB,CACE,OACA,eACA,OACA,aACA,aACA,UACA,YACA,mBACA,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,CAEtC,GAAM,CAAE,WAAU,aAAc,EAAc,EAAK,CAC/C,EAAY,EAgBhB,MAAM,EAA4C,CAChD,eACA,YAAa,EACb,aAAc,EACd,YAlBoB,IAAmD,CACvE,IAAM,EAAmB,GAAG,EAAS,GAAG,IAAY,IASpD,OARA,EAAO,KAAK,EAAO,KAAK,UAAU,EAAM,OAAO,wBAAwB,EAAiB,GAAG,CAAC,CAG5F,MAAM,EAAc,EAAkB,EADtB,EAAK,EAAM,IAAK,GAAM,OAAO,KAAK,EAAE,CAAC,CAAC,MAAM,CACR,CAAC,CACrD,EAAO,KACL,EAAO,MAAM,sBAAsB,EAAM,OAAO,wBAAwB,EAAiB,GAAG,CAC7F,CACD,GAAa,EACN,QAAQ,SAAS,EASxB,UACA,OACA,aACA,aACA,mBACD,CAAC"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{i as e,n as t,r as n,t as r}from"./enums-OiLcZ26O.mjs";import{a as i,c as a,d as o,f as s,g as c,h as l,i as u,l as d,m as f,n as p,o as m,p as h,r as g,s as _,t as v,u as y}from"./constants-
|
|
1
|
+
import{i as e,n as t,r as n,t as r}from"./enums-OiLcZ26O.mjs";import{a as i,c as a,d as o,f as s,g as c,h as l,i as u,l as d,m as f,n as p,o as m,p as h,r as g,s as _,t as v,u as y}from"./constants-Ch1Lt8Wa.mjs";import{t as b}from"./logger-Ckep4QXn.mjs";import{$ as x,A as S,B as ee,C as te,D as ne,E as re,F as ie,G as ae,H as oe,I as se,J as ce,K as C,L as w,M as T,N as E,O as D,P as O,Q as k,R as A,S as j,T as M,U as N,V as P,W as F,X as I,Y as L,Z as R,_ as z,a as B,at as V,b as H,c as U,ct as W,d as G,et as le,f as ue,g as de,h as fe,i as pe,it as me,j as he,k as ge,l as _e,lt as ve,m as ye,n as be,nt as xe,o as Se,ot as Ce,p as we,q as Te,r as Ee,rt as De,s as Oe,st as ke,t as Ae,tt as je,u as Me,ut as Ne,v as Pe,w as Fe,x as Ie,y as Le,z as Re}from"./codecs-DRBjmo_R.mjs";import{a as ze,i as Be,n as Ve,r as He,t as Ue}from"./readTranscendYaml-ceJQNB1O.mjs";import{a as We,i as Ge,n as Ke,r as qe,t as Je}from"./parseVariablesFromString-B2TB86Fo.mjs";import{a as Ye,c as Xe,i as Ze,l as Qe,n as $e,o as et,r as tt,s as nt,t as rt,u as it}from"./constants-C9xZJ9YW.mjs";import{n as at,t as ot}from"./fuzzyMatchColumns-C1STZ_T1.mjs";import{a as st,c as ct,d as lt,f as ut,i as dt,l as ft,n as pt,o as mt,r as ht,s as gt,t as _t,u as vt}from"./uploadPrivacyRequestsFromCsv-BVi19fS8.mjs";import{n as yt,t as bt}from"./parseAttributesFromString-CYcxsS3n.mjs";import{t as xt}from"./readCsv--FfP8n-H.mjs";import{n as St,t as Ct}from"./pullUnstructuredSubDataPointRecommendations-B9xIDPf2.mjs";import{a as wt,i as Tt,n as Et,o as Dt,r as Ot,t as kt}from"./request-BIplTb3L.mjs";import{i as At,n as jt,r as Mt,t as Nt}from"./pullTranscendConfiguration-DFQkyoIo.mjs";import{i as Pt,n as Ft,r as K,t as It}from"./fetchAllRequests-DP24WqrP.mjs";import{a as Lt,i as Rt,n as zt,r as Bt,t as Vt}from"./pullChunkedCustomSiloOutstandingIdentifiers-D_TkvoKK.mjs";import{n as Ht,r as Ut,t as Wt}from"./syncCodePackages-Dhm5jI6B.mjs";import{t as Gt}from"./markSilentPrivacyRequests-Ctu7drQy.mjs";import{a as Kt,i as qt,n as Jt,o as Yt,r as Xt,t as Zt}from"./downloadPrivacyRequestFiles-CaOdAuGW.mjs";import{n as Qt,r as $t,t as en}from"./extractClientError-X9wJVqGq.mjs";import{t as tn}from"./approvePrivacyRequests-D4ZfEesR.mjs";import{t as nn}from"./notifyPrivacyRequestsAdditionalTime-Du7706Lb.mjs";import{t as rn}from"./cancelPrivacyRequests-CyT7z4fs.mjs";import{n as an,t as on}from"./bulkRestartRequests-CSBPINdi.mjs";import{t as sn}from"./skipPreflightJobs-BrBvyKxG.mjs";import{t as cn}from"./bulkRetryEnrichers-BPWSWNuC.mjs";import{t as ln}from"./retryRequestDataSilos-pQ4DekAX.mjs";import{n as q,r as J,t as un}from"./streamPrivacyRequestsToCsv-zGxmk-9Z.mjs";import{n as dn,r as fn,t as pn}from"./inquirer-B0OF_nRe.mjs";import{t as mn}from"./collectParquetFilesOrExit-DyZISY9X.mjs";import{t as hn}from"./collectCsvFilesOrExit-C8-Pr9Hr.mjs";import{t as gn}from"./parquetToCsvOneFile-13GirFzy.mjs";import{a as _n,i as vn,n as yn,o as bn,r as xn,s as Sn,t as Cn}from"./writeCsv-BMVkiMHM.mjs";import{t as wn}from"./skipRequestDataSilos-DrTtHtF5.mjs";import{t as Tn}from"./removeUnverifiedRequestIdentifiers-D2tdogVl.mjs";import{t as En}from"./updateConsentManagerVersionToLatest-Dg-j1SQt.mjs";import{t as Dn}from"./uploadDataFlowsFromCsv-Ct0rye94.mjs";import{t as On}from"./uploadCookiesFromCsv-DmU8R-_E.mjs";import{t as kn}from"./pullConsentManagerMetrics-CR4WwUt6.mjs";import{n as An,r as jn,t as Mn}from"./buildXdiSyncEndpoint-CXAYh3vF.mjs";import{t as Nn}from"./consentManagersToBusinessEntities-DGzryQ3W.mjs";import{i as Pn,n as Fn,r as In,t as Ln}from"./uploadConsents-B3lvS6hQ.mjs";import{n as Rn,r as zn,t as Bn}from"./pushCronIdentifiersFromCsv-hcTHlWyf.mjs";import{t as Vn}from"./markRequestDataSiloIdsCompleted-C7HAJehS.mjs";import{t as Hn}from"./generateCrossAccountApiKeys-JCZ444Xx.mjs";import{t as Un}from"./validateTranscendAuth-Dl8UUCAQ.mjs";import{t as Wn}from"./listFiles-BPx3iDV6.mjs";import{t as Gn}from"./pullAllDatapoints-Bvv9KRR5.mjs";import{t as Kn}from"./pullManualEnrichmentIdentifiersToCsv-C_XrnqTo.mjs";import{n as qn,r as Jn,t as Yn}from"./pushManualEnrichmentIdentifiersFromCsv-5Dulzugh.mjs";import{chunk as Xn,difference as Zn}from"lodash-es";import{readFileSync as Qn,readdirSync as $n,statSync as er}from"node:fs";import{join as tr}from"node:path";import nr from"fast-glob";import Y from"colors";import{UPDATE_OR_CREATE_COOKIES as rr,buildTranscendGraphQLClient as X,createSombraGotInstance as ir,fetchAllRequestIdentifiers as ar,fetchConsentManagerId as or,makeGraphQLRequest as sr,validateSombraVersion as cr}from"@transcend-io/sdk";import{map as Z,mapSeries as lr}from"@transcend-io/utils";import{execSync as Q}from"child_process";async function $(e,t){let n=await or(e,{logger:b});await lr(Xn(t,100),async t=>{await sr(e,rr,{variables:{airgapBundleId:n,cookies:t.map(e=>({name:e.name,trackingPurposes:e.trackingPurposes&&e.trackingPurposes.length>0?e.trackingPurposes:void 0,description:e.description,service:e.service,status:e.status,attributes:e.attributes,isRegex:e.isRegex}))},logger:b})})}async function ur(e,t){let n=!1;b.info(Y.magenta(`Syncing "${t.length}" cookies...`));let r=t.filter(e=>t.filter(t=>e.name===t.name&&e.isRegex===t.isRegex).length>1);if(r.length>0)throw Error(`Failed to upload cookies as there were non-unique entries found: ${r.map(({name:e})=>e).join(`,`)}`);try{b.info(Y.magenta(`Upserting "${t.length}" new cookies...`)),await $(e,t),b.info(Y.green(`Successfully synced ${t.length} cookies!`))}catch(e){n=!0,b.error(Y.red(`Failed to create cookies! - ${e.message}`))}return!n}async function dr({auth:e,sombraAuth:t,actions:n=[],statuses:r=[],identifierSearch:a,pageLimit:o=100,concurrency:s=1,transcendUrl:c=i,createdAtBefore:l,skipRequestIdentifiers:u=!1,createdAtAfter:d,updatedAtBefore:f,updatedAtAfter:p,isTest:m}){let h=X(c,e),g=await ir(c,e,{logger:b,sombraApiKey:t,sombraUrl:process.env.SOMBRA_URL}),_=``;l&&(_+=` before ${l.toISOString()}`),d&&(_+=`${_?`, and`:``} after ${d.toISOString()}`),b.info(Y.magenta(`${n.length>0?`Pulling requests of type "${n.join(`" , "`)}"`:`Pulling all requests`}${_}`));let v=s>1&&d&&l,y=v?q(d,l,s):[{createdAtAfter:d,createdAtBefore:l}];v&&b.info(Y.magenta(`Splitting date range into ${s} parallel chunks`));let x=(await Z(y,e=>K(h,{actions:n,text:a,statuses:r,createdAtBefore:e.createdAtBefore,createdAtAfter:e.createdAtAfter,updatedAtBefore:f,updatedAtAfter:p,isTest:m}),{concurrency:v?s:1})).flat();u||await cr(h,{logger:b});let S=u?x.map(e=>({...e,requestIdentifiers:[]})):await Z(x,async e=>{let t=await ar(h,g,{filterBy:{requestId:e.id},skipSombraCheck:!0,logger:b});return{...e,requestIdentifiers:t}},{concurrency:o});return b.info(Y.magenta(`Pulled ${S.length} requests`)),{requestsWithRequestIdentifiers:S,requestsFormattedForCsv:S.map(J)}}function fr(e){try{return e?Qn(e,`utf8`):``}catch{return``}}function pr(e){return $n(e).filter(t=>er(tr(e,t)).isDirectory())}function mr(e){return e.replace(/(https?:\/\/[^\s]+)/g,`<link-omitted>`)}function hr(e){return Object.entries(e).reduce((e,[t,n])=>n!=null&&n!==``&&!(Array.isArray(n)&&n.length===0)&&!(typeof n==`object`&&Object.keys(n).length===0)?Object.assign(e,{[t]:n}):e,{})}function gr({baseBranch:e,rootDirectory:t,githubRepo:n,excludedGlob:r=[],fileBlockList:i=[]}){Q(`git fetch origin ${e}`);let a=Q(`git ls-remote ${n} "refs/heads/${e}" | cut -f 1`,{encoding:`utf-8`}).split(`
|
|
2
2
|
`)[0],o=Q(`git rev-parse HEAD`,{encoding:`utf-8`}).split(`
|
|
3
3
|
`)[0];if(!a||!o)throw Error(`FAILED TO FIND COMMIT RANGE`);let s=Zn(Q(`git fetch && git diff --name-only "${e||a}...${o}" -- ${t}`,{encoding:`utf-8`}).split(`
|
|
4
4
|
`).filter(e=>e),i),c=r.length>0?nr.sync(s,{ignore:r}):s,l={};return c.forEach(e=>{l[e]=Q(`git show ${o}:${e}`,{encoding:`utf-8`})}),{changedFiles:s,fileDiffs:l,repoName:n.split(`/`).pop().split(`.`)[0],commit:o}}export{v as ADMIN_DASH,p as ADMIN_DASH_DATAPOINTS,g as ADMIN_DASH_INTEGRATIONS,kt as APPROVE_PRIVACY_REQUEST,At as ASSESSMENT_TEMPLATES,Ae as ActionInput,be as ActionItemCollectionInput,Ee as ActionItemInput,pe as ApiKeyInput,B as AssessmentAnswerOptionInput,Se as AssessmentDisplayLogicInput,Oe as AssessmentInput,U as AssessmentNestedRuleInput,_e as AssessmentResourceInput,Me as AssessmentRetentionScheduleInput,G as AssessmentRuleInput,ue as AssessmentSectionInput,we as AssessmentSectionQuestionInput,ye as AssessmentTemplateInput,dt as AttestedExtraIdentifiers,fe as AttributeInput,de as AttributePreview,z as AttributeValueInput,rt as BLANK,$e as BULK_APPLY,Pe as BusinessEntityInput,Et as CANCEL_PRIVACY_REQUEST,tt as CAN_APPLY_IN_BULK,Ze as CachedFileState,Ye as CachedRequestState,Le as CodePackageInput,H as CodePackageSdk,et as ColumnName,Ie as ConsentManageExperienceInput,j as ConsentManagerInput,te as ConsentManagerServiceMetadata,Fe as ConsentPreferenceTopic,M as ConsentPreferenceTopicOptionValue,re as ConsentPurpose,ne as CookieCsvInput,D as CookieInput,zt as CronIdentifier,Rn as CronIdentifierPush,Bt as CronPartition,u as DEBUG,i as DEFAULT_TRANSCEND_API,m as DEFAULT_TRANSCEND_API_KEY,_ as DEFAULT_TRANSCEND_CONSENT_API,Nt as DEFAULT_TRANSCEND_PULL_RESOURCES,ge as DataCategoryGuessInput,S as DataCategoryInput,he as DataCategoryPreviewInput,T as DataCategoryRecommendationInput,E as DataFlowCsvInput,O as DataFlowInput,ie as DataSiloInput,se as DataSubjectInput,w as DatapointInput,St as ENTRY_COUNT,qn as EnrichPrivacyRequest,A as EnricherInput,Re as FieldInput,nt as IDENTIFIER_BLOCK_LIST,Mn as IP_ADDRESS_REGEX,Xe as IS_REQUIRED,ee as IdentifierInput,P as ImportOnetrustAssessmentsInput,Xt as IntlMessage,oe as IntlMessageInput,Qe as NONE,Ot as NOTIFY_ADDITIONAL_TIME,r as OneTrustFileFormat,t as OneTrustPullResource,n as OneTrustPullSource,bt as ParsedAttributeInput,N as PartitionInput,F as PolicyInput,ae as PreferenceWorkflowConfigInput,C as PreferenceWorkflowConfigPurposeInput,Te as PrivacyCenterInput,It as PrivacyRequest,st as PrivacyRequestInput,Qt as PrivacyRequestResponse,ce as ProcessingActivityInput,L as ProcessingPurposeInput,I as ProcessingPurposePreviewInput,R as PromptAVendorEmailSettings,Ln as PurposeMap,Tt as REQUESTS,wt as REQUESTS_COUNT,a as RETRYABLE_BATCH_STATUSES,k as RegionInput,x as RepositoryInput,qt as RequestFileMetadata,Kt as RequestFileMetadataResponse,Ft as RequestPurposeTrigger,le as RiskAssignmentInput,je as RiskLogicInput,d as SCOPES_BY_TITLE,y as SCOPE_TITLES,xe as SiloDiscoveryResultInput,De as SoftwareDevelopmentKitInput,me as StoredApiKey,it as SuccessfulRequest,o as TR_PULL_RESOURCE_SCOPE_MAP,s as TR_PUSH_RESOURCE_SCOPE_MAP,h as TR_YML_RESOURCE_TO_FIELD_NAME,V as TeamInput,Ce as TemplateInput,ke as TranscendInput,e as TranscendPullResource,Dt as UPDATE_PRIVACY_REQUEST,Fn as USP_STRING_REGEX,Ue as VARIABLE_PARAMETERS_NAME,Ve as VARIABLE_PARAMETERS_REGEXP,W as VendorInput,ve as WebhookHeader,Ne as WorkflowConfigInput,Cn as appendCsvRowsOrdered,yn as appendCsvSync,tn as approvePrivacyRequests,An as buildXdiSyncEndpoint,on as bulkRestartRequests,cn as bulkRetryEnrichers,rn as cancelPrivacyRequests,hn as collectCsvFilesOrExit,mn as collectParquetFilesOrExit,Nn as consentManagersToBusinessEntities,Wt as createCodePackage,Pn as createConsentToken,l as description,jn as domainToHost,Zt as downloadPrivacyRequestFiles,Jn as enrichPrivacyRequest,We as ensureAllDataSubjectsExist,en as extractClientError,Mt as fetchAllAssessmentTemplates,K as fetchAllRequests,Lt as fetchRequestDataSiloActiveCount,Pt as fetchRequestsTotalCount,hr as filterNullishValuesFromObject,vt as filterRows,J as formatRequestForCsv,ot as fuzzyMatchColumns,at as fuzzySearch,Hn as generateCrossAccountApiKeys,Yt as getFileMetadataForPrivacyRequests,gr as getGitFilesThatChanged,lt as getUniqueValuesForColumn,xn as initCsvFile,pn as inquirerAutoComplete,dn as inquirerConfirmBoolean,fn as inquirerConfirmText,pr as listDirectories,Wn as listFiles,pt as mapColumnsToAttributes,ht as mapColumnsToIdentifiers,ft as mapCsvColumnsToApi,mt as mapCsvRowsToRequestInputs,ut as mapEnumValues,ct as mapRequestEnumValues,zn as markCronIdentifierCompleted,Vn as markRequestDataSiloIdsCompleted,Gt as markSilentPrivacyRequests,Ke as mergeTranscendInputs,f as name,gt as normalizeIdentifierValue,nn as notifyPrivacyRequestsAdditionalTime,gn as parquetToCsvOneFile,yt as parseAttributesFromString,vn as parseFilePath,Je as parseVariablesFromString,Gn as pullAllDatapoints,Vt as pullChunkedCustomSiloOutstandingIdentifiers,kn as pullConsentManagerMetrics,Rt as pullCronPageOfIdentifiers,Kn as pullManualEnrichmentIdentifiersToCsv,dr as pullPrivacyRequests,jt as pullTranscendConfiguration,Ct as pullUnstructuredSubDataPointRecommendations,Bn as pushCronIdentifiersFromCsv,Yn as pushManualEnrichmentIdentifiersFromCsv,xt as readCsv,fr as readSafe,He as readTranscendYaml,mr as removeLinks,Tn as removeUnverifiedRequestIdentifiers,Be as replaceVariablesInYaml,an as restartPrivacyRequest,ln as retryRequestDataSilos,sn as skipPreflightJobs,wn as skipRequestDataSilos,q as splitDateRange,Jt as streamPrivacyRequestFiles,un as streamPrivacyRequestsToCsv,$t as submitPrivacyRequest,Ht as syncCodePackages,qe as syncConfigurationToTranscend,ur as syncCookies,Ge as syncDataSilos,Ut as updateCodePackages,En as updateConsentManagerVersionToLatest,$ as updateOrCreateCookies,In as uploadConsents,On as uploadCookiesFromCsv,Dn as uploadDataFlowsFromCsv,_t as uploadPrivacyRequestsFromCsv,Un as validateTranscendAuth,c as version,_n as writeCsv,bn as writeCsvSync,Sn as writeLargeCsv,ze as writeTranscendYaml};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e}from"./constants-
|
|
2
|
-
//# sourceMappingURL=markRequestDataSiloIdsCompleted-
|
|
1
|
+
import{a as e}from"./constants-Ch1Lt8Wa.mjs";import{t}from"./logger-Ckep4QXn.mjs";import{RequestDataSiloStatus as n}from"@transcend-io/privacy-types";import r from"colors";import{CHANGE_REQUEST_DATA_SILO_STATUS as i,buildTranscendGraphQLClient as a,fetchRequestDataSilo as o,makeGraphQLRequest as s}from"@transcend-io/sdk";import{map as c}from"@transcend-io/utils";import l from"cli-progress";async function u({requestIds:u,dataSiloId:d,auth:f,concurrency:p=100,status:m=n.Resolved,transcendUrl:h=e}){let g=a(h,f),_=new Date().getTime(),v=new l.SingleBar({},l.Presets.shades_classic);t.info(r.magenta(`Notifying Transcend for data silo "${d}" marking "${u.length}" requests as completed.`));let y=0;v.start(u.length,0),await c(u,async e=>{let n=await o(g,{logger:t,filterBy:{requestId:e,dataSiloId:d}});try{await s(g,i,{variables:{requestDataSiloId:n.id,status:m},logger:t})}catch(e){if(!e.message.includes(`Client error: Request must be active:`)&&!e.message.includes(`Failed to find RequestDataSilo`))throw e}y+=1,v.update(y)},{concurrency:p}),v.stop();let b=new Date().getTime()-_;return t.info(r.green(`Successfully notified Transcend in "${b/1e3}" seconds!`)),u.length}export{u as t};
|
|
2
|
+
//# sourceMappingURL=markRequestDataSiloIdsCompleted-C7HAJehS.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markRequestDataSiloIdsCompleted-
|
|
1
|
+
{"version":3,"file":"markRequestDataSiloIdsCompleted-C7HAJehS.mjs","names":[],"sources":["../src/lib/cron/markRequestDataSiloIdsCompleted.ts"],"sourcesContent":["import { RequestDataSiloStatus } from '@transcend-io/privacy-types';\nimport {\n buildTranscendGraphQLClient,\n makeGraphQLRequest,\n CHANGE_REQUEST_DATA_SILO_STATUS,\n fetchRequestDataSilo,\n} from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\n\n/**\n * Given a CSV of Request IDs, mark associated RequestDataSilos as completed\n *\n * @param options - Options\n * @returns Number of items marked as completed\n */\nexport async function markRequestDataSiloIdsCompleted({\n requestIds,\n dataSiloId,\n auth,\n concurrency = 100,\n status = RequestDataSiloStatus.Resolved,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The list of request ids to mark as completed */\n requestIds: string[];\n /** Transcend API key authentication */\n auth: string;\n /** Data Silo ID to pull down jobs for */\n dataSiloId: string;\n /** Status to update requests to */\n status?: RequestDataSiloStatus;\n /** Upload concurrency */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Notifying Transcend for data silo \"${dataSiloId}\" marking \"${requestIds.length}\" requests as completed.`,\n ),\n );\n\n let total = 0;\n progressBar.start(requestIds.length, 0);\n await map(\n requestIds,\n async (requestId) => {\n const requestDataSilo = await fetchRequestDataSilo(client, {\n logger,\n filterBy: { requestId, dataSiloId },\n });\n\n try {\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, CHANGE_REQUEST_DATA_SILO_STATUS, {\n variables: {\n requestDataSiloId: requestDataSilo.id,\n status,\n },\n logger,\n });\n } catch (err) {\n if (\n !err.message.includes('Client error: Request must be active:') &&\n !err.message.includes('Failed to find RequestDataSilo')\n ) {\n throw err;\n }\n }\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(colors.green(`Successfully notified Transcend in \"${totalTime / 1000}\" seconds!`));\n return requestIds.length;\n}\n"],"mappings":"yYAoBA,eAAsB,EAAgC,CACpD,aACA,aACA,OACA,cAAc,IACd,SAAS,EAAsB,SAC/B,eAAe,GAcG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAI,EAAY,UAAU,EAAE,CAAE,EAAY,QAAQ,eAAe,CAGrF,EAAO,KACL,EAAO,QACL,sCAAsC,EAAW,aAAa,EAAW,OAAO,0BACjF,CACF,CAED,IAAI,EAAQ,EACZ,EAAY,MAAM,EAAW,OAAQ,EAAE,CACvC,MAAM,EACJ,EACA,KAAO,IAAc,CACnB,IAAM,EAAkB,MAAM,EAAqB,EAAQ,CACzD,SACA,SAAU,CAAE,YAAW,aAAY,CACpC,CAAC,CAEF,GAAI,CACF,MAAM,EAGH,EAAQ,EAAiC,CAC1C,UAAW,CACT,kBAAmB,EAAgB,GACnC,SACD,CACD,SACD,CAAC,OACK,EAAK,CACZ,GACE,CAAC,EAAI,QAAQ,SAAS,wCAAwC,EAC9D,CAAC,EAAI,QAAQ,SAAS,iCAAiC,CAEvD,MAAM,EAIV,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SACF,CAAG,EAGvB,OADA,EAAO,KAAK,EAAO,MAAM,uCAAuC,EAAY,IAAK,YAAY,CAAC,CACvF,EAAW"}
|
package/dist/{markSilentPrivacyRequests-DxBYqlWf.mjs → markSilentPrivacyRequests-Ctu7drQy.mjs}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e}from"./constants-
|
|
2
|
-
//# sourceMappingURL=markSilentPrivacyRequests-
|
|
1
|
+
import{a as e}from"./constants-Ch1Lt8Wa.mjs";import{t}from"./logger-Ckep4QXn.mjs";import{o as n}from"./request-BIplTb3L.mjs";import{r}from"./fetchAllRequests-DP24WqrP.mjs";import{RequestStatus as i}from"@transcend-io/privacy-types";import a from"colors";import{buildTranscendGraphQLClient as o,makeGraphQLRequest as s}from"@transcend-io/sdk";import{map as c}from"@transcend-io/utils";import l from"cli-progress";async function u({requestActions:u,auth:d,requestIds:f,statuses:p=[i.Compiling,i.RequestMade,i.Delayed,i.Approving,i.Secondary,i.Enriching,i.Waiting,i.SecondaryApproving],createdAtAfter:m,createdAtBefore:h,updatedAtBefore:g,updatedAtAfter:_,concurrency:v=100,transcendUrl:y=e}){let b=o(y,d),x=new Date().getTime(),S=new l.SingleBar({},l.Presets.shades_classic),C=await r(b,{actions:u,statuses:p,createdAtBefore:h,createdAtAfter:m,updatedAtBefore:g,updatedAtAfter:_,isSilent:!1,requestIds:f});t.info(a.magenta(`Marking "${C.length}" as silent mode.`));let w=0;S.start(C.length,0),await c(C,async e=>{await s(b,n,{variables:{input:{id:e.id,isSilent:!0}},logger:t}),w+=1,S.update(w)},{concurrency:v}),S.stop();let T=new Date().getTime()-x;return t.info(a.green(`Successfully marked ${w} requests as silent mode in "${T/1e3}" seconds!`)),C.length}export{u as t};
|
|
2
|
+
//# sourceMappingURL=markSilentPrivacyRequests-Ctu7drQy.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markSilentPrivacyRequests-
|
|
1
|
+
{"version":3,"file":"markSilentPrivacyRequests-Ctu7drQy.mjs","names":[],"sources":["../src/lib/requests/markSilentPrivacyRequests.ts"],"sourcesContent":["import { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport { buildTranscendGraphQLClient, makeGraphQLRequest } from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\nimport { UPDATE_PRIVACY_REQUEST, fetchAllRequests } from '../graphql/index.js';\n\n/**\n * Mark a set of privacy requests to be in silent mode\n *\n * @param options - Options\n * @returns The number of requests marked silent\n */\nexport async function markSilentPrivacyRequests({\n requestActions,\n auth,\n requestIds,\n statuses = [\n RequestStatus.Compiling,\n RequestStatus.RequestMade,\n RequestStatus.Delayed,\n RequestStatus.Approving,\n RequestStatus.Secondary,\n RequestStatus.Enriching,\n RequestStatus.Waiting,\n RequestStatus.SecondaryApproving,\n ],\n createdAtAfter,\n createdAtBefore,\n updatedAtBefore,\n updatedAtAfter,\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** Transcend API key authentication */\n auth: string;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** The request statuses to mark silent */\n statuses?: RequestStatus[];\n /** The set of privacy requests to mark silent */\n requestIds?: string[];\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Filter for requests updated before this date */\n updatedAtBefore?: Date;\n /** Filter for requests updated after this date */\n updatedAtAfter?: Date;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n isSilent: false,\n requestIds,\n });\n\n // Notify Transcend\n logger.info(colors.magenta(`Marking \"${allRequests.length}\" as silent mode.`));\n\n let total = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToMarkSilent) => {\n await makeGraphQLRequest(client, UPDATE_PRIVACY_REQUEST, {\n variables: {\n input: {\n id: requestToMarkSilent.id,\n isSilent: true,\n },\n },\n logger,\n });\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully marked ${total} requests as silent mode in \"${totalTime / 1000}\" seconds!`,\n ),\n );\n return allRequests.length;\n}\n"],"mappings":"4ZAgBA,eAAsB,EAA0B,CAC9C,iBACA,OACA,aACA,WAAW,CACT,EAAc,UACd,EAAc,YACd,EAAc,QACd,EAAc,UACd,EAAc,UACd,EAAc,UACd,EAAc,QACd,EAAc,mBACf,CACD,iBACA,kBACA,kBACA,iBACA,cAAc,IACd,eAAe,GAsBG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAI,EAAY,UAAU,EAAE,CAAE,EAAY,QAAQ,eAAe,CAG/E,EAAc,MAAM,EAAiB,EAAQ,CACjD,QAAS,EACT,WACA,kBACA,iBACA,kBACA,iBACA,SAAU,GACV,aACD,CAAC,CAGF,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAY,OAAO,mBAAmB,CAAC,CAE9E,IAAI,EAAQ,EACZ,EAAY,MAAM,EAAY,OAAQ,EAAE,CACxC,MAAM,EACJ,EACA,KAAO,IAAwB,CAC7B,MAAM,EAAmB,EAAQ,EAAwB,CACvD,UAAW,CACT,MAAO,CACL,GAAI,EAAoB,GACxB,SAAU,GACX,CACF,CACD,SACD,CAAC,CAEF,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SACF,CAAG,EAOvB,OALA,EAAO,KACL,EAAO,MACL,uBAAuB,EAAM,+BAA+B,EAAY,IAAK,YAC9E,CACF,CACM,EAAY"}
|