@transcend-io/cli 13.0.6 → 13.0.8
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/README.md +2 -2
- package/dist/{app-CgHCDGve.mjs → app-C30CjSkC.mjs} +16 -16
- package/dist/{app-CgHCDGve.mjs.map → app-C30CjSkC.mjs.map} +1 -1
- package/dist/{approvePrivacyRequests-BrnJ-CVF.mjs → approvePrivacyRequests-BWwO-VkZ.mjs} +2 -2
- package/dist/{approvePrivacyRequests-BrnJ-CVF.mjs.map → approvePrivacyRequests-BWwO-VkZ.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-CnR3Kr1g.mjs → buildExamples-CNJja2-q.mjs} +2 -2
- package/dist/{buildExamples-CnR3Kr1g.mjs.map → buildExamples-CNJja2-q.mjs.map} +1 -1
- package/dist/{buildXdiSyncEndpoint-C5d116vB.mjs → buildXdiSyncEndpoint-CB10Y5Zh.mjs} +2 -2
- package/dist/{buildXdiSyncEndpoint-C5d116vB.mjs.map → buildXdiSyncEndpoint-CB10Y5Zh.mjs.map} +1 -1
- package/dist/{bulkRestartRequests-C3cbvO42.mjs → bulkRestartRequests-CQ3xJ0_a.mjs} +2 -2
- package/dist/{bulkRestartRequests-C3cbvO42.mjs.map → bulkRestartRequests-CQ3xJ0_a.mjs.map} +1 -1
- package/dist/{bulkRetryEnrichers-C0Z-5oAG.mjs → bulkRetryEnrichers-C6EC7hDi.mjs} +2 -2
- package/dist/{bulkRetryEnrichers-C0Z-5oAG.mjs.map → bulkRetryEnrichers-C6EC7hDi.mjs.map} +1 -1
- package/dist/{cancelPrivacyRequests-i7HTC4_n.mjs → cancelPrivacyRequests-RYf84Ife.mjs} +2 -2
- package/dist/{cancelPrivacyRequests-i7HTC4_n.mjs.map → cancelPrivacyRequests-RYf84Ife.mjs.map} +1 -1
- package/dist/{command-hkvdh57O.mjs → command-2mycAA8T.mjs} +2 -2
- package/dist/{command-hkvdh57O.mjs.map → command-2mycAA8T.mjs.map} +1 -1
- package/dist/{constants-CusZYsjT.mjs → constants-B0oaHpig.mjs} +2 -2
- package/dist/{constants-CusZYsjT.mjs.map → constants-B0oaHpig.mjs.map} +1 -1
- package/dist/{createPoolingCommandUi-C6uf3bzG.mjs → createPoolingCommandUi-CDtlHb8_.mjs} +2 -2
- package/dist/{createPoolingCommandUi-C6uf3bzG.mjs.map → createPoolingCommandUi-CDtlHb8_.mjs.map} +1 -1
- package/dist/{downloadPrivacyRequestFiles-Do8cKTNC.mjs → downloadPrivacyRequestFiles-CgVZOWgS.mjs} +2 -2
- package/dist/{downloadPrivacyRequestFiles-Do8cKTNC.mjs.map → downloadPrivacyRequestFiles-CgVZOWgS.mjs.map} +1 -1
- package/dist/{generateCrossAccountApiKeys-D3EzSJV7.mjs → generateCrossAccountApiKeys-BG3A4CKS.mjs} +2 -2
- package/dist/{generateCrossAccountApiKeys-D3EzSJV7.mjs.map → generateCrossAccountApiKeys-BG3A4CKS.mjs.map} +1 -1
- package/dist/{impl-C9JlWA7i.mjs → impl-9sk_xUm1.mjs} +2 -2
- package/dist/{impl-C9JlWA7i.mjs.map → impl-9sk_xUm1.mjs.map} +1 -1
- package/dist/{impl-D-1QAfLV.mjs → impl-Ap1oZlzF.mjs} +2 -2
- package/dist/{impl-D-1QAfLV.mjs.map → impl-Ap1oZlzF.mjs.map} +1 -1
- package/dist/{impl-B964vhTe.mjs → impl-B4PSQtDD.mjs} +2 -2
- package/dist/{impl-B964vhTe.mjs.map → impl-B4PSQtDD.mjs.map} +1 -1
- package/dist/{impl-DHTAxvp8.mjs → impl-B6PDRnqA.mjs} +2 -2
- package/dist/{impl-DHTAxvp8.mjs.map → impl-B6PDRnqA.mjs.map} +1 -1
- package/dist/{impl-D_03KeBQ.mjs → impl-B7Rfw4nS.mjs} +2 -2
- package/dist/{impl-D_03KeBQ.mjs.map → impl-B7Rfw4nS.mjs.map} +1 -1
- package/dist/{impl-L-TZRGF5.mjs → impl-BAzZNoIY.mjs} +2 -2
- package/dist/{impl-L-TZRGF5.mjs.map → impl-BAzZNoIY.mjs.map} +1 -1
- package/dist/{impl-COpuW67i.mjs → impl-BSZmuX3n.mjs} +2 -2
- package/dist/{impl-COpuW67i.mjs.map → impl-BSZmuX3n.mjs.map} +1 -1
- package/dist/{impl-Cm_hCZ5h.mjs → impl-BaC1mNZ_.mjs} +2 -2
- package/dist/{impl-Cm_hCZ5h.mjs.map → impl-BaC1mNZ_.mjs.map} +1 -1
- package/dist/{impl-DWmQ_15Y.mjs → impl-BlzJ6Ych.mjs} +2 -2
- package/dist/{impl-DWmQ_15Y.mjs.map → impl-BlzJ6Ych.mjs.map} +1 -1
- package/dist/{impl-DLaSUiZ7.mjs → impl-Bs5fBEjH.mjs} +2 -2
- package/dist/{impl-DLaSUiZ7.mjs.map → impl-Bs5fBEjH.mjs.map} +1 -1
- package/dist/{impl-DbTZmp_W2.mjs → impl-BvyB3epw2.mjs} +2 -2
- package/dist/{impl-DbTZmp_W2.mjs.map → impl-BvyB3epw2.mjs.map} +1 -1
- package/dist/{impl-CVjaQ_-Y2.mjs → impl-C3zfU0Jt2.mjs} +2 -2
- package/dist/{impl-CVjaQ_-Y2.mjs.map → impl-C3zfU0Jt2.mjs.map} +1 -1
- package/dist/{impl-UlLFb3UK2.mjs → impl-C4CrzZFK2.mjs} +2 -2
- package/dist/{impl-UlLFb3UK2.mjs.map → impl-C4CrzZFK2.mjs.map} +1 -1
- package/dist/{impl-DQbP4dBX.mjs → impl-C5A6boYU.mjs} +2 -2
- package/dist/{impl-DQbP4dBX.mjs.map → impl-C5A6boYU.mjs.map} +1 -1
- package/dist/{impl-COD03bOu.mjs → impl-C5o7iqlK.mjs} +2 -2
- package/dist/{impl-COD03bOu.mjs.map → impl-C5o7iqlK.mjs.map} +1 -1
- package/dist/{impl-DvLO4Qn3.mjs → impl-C8oTRXHj.mjs} +2 -2
- package/dist/{impl-DvLO4Qn3.mjs.map → impl-C8oTRXHj.mjs.map} +1 -1
- package/dist/{impl-F0lRLx7N.mjs → impl-CB1QyjSs.mjs} +2 -2
- package/dist/{impl-F0lRLx7N.mjs.map → impl-CB1QyjSs.mjs.map} +1 -1
- package/dist/{impl-DnPaAp-d.mjs → impl-CRUywZ24.mjs} +2 -2
- package/dist/{impl-DnPaAp-d.mjs.map → impl-CRUywZ24.mjs.map} +1 -1
- package/dist/{impl-S3znb469.mjs → impl-CY-fXikv.mjs} +2 -2
- package/dist/{impl-S3znb469.mjs.map → impl-CY-fXikv.mjs.map} +1 -1
- package/dist/{impl-CBLQwa8E.mjs → impl-CfYLIyNs.mjs} +2 -2
- package/dist/{impl-CBLQwa8E.mjs.map → impl-CfYLIyNs.mjs.map} +1 -1
- package/dist/{impl-CALzjhEc.mjs → impl-CrCGRoa3.mjs} +2 -2
- package/dist/{impl-CALzjhEc.mjs.map → impl-CrCGRoa3.mjs.map} +1 -1
- package/dist/{impl-DwBrrrR3.mjs → impl-CyPfmNE5.mjs} +2 -2
- package/dist/{impl-DwBrrrR3.mjs.map → impl-CyPfmNE5.mjs.map} +1 -1
- package/dist/{impl-8kZN8w0q.mjs → impl-D5MKgDo-.mjs} +2 -2
- package/dist/{impl-8kZN8w0q.mjs.map → impl-D5MKgDo-.mjs.map} +1 -1
- package/dist/{impl-CuII9KiJ.mjs → impl-DBMDFKIK.mjs} +2 -2
- package/dist/{impl-CuII9KiJ.mjs.map → impl-DBMDFKIK.mjs.map} +1 -1
- package/dist/{impl-CFPN8z3c.mjs → impl-DJbykleN.mjs} +2 -2
- package/dist/{impl-CFPN8z3c.mjs.map → impl-DJbykleN.mjs.map} +1 -1
- package/dist/{impl-wymd_Y3k.mjs → impl-DbDqwIOm.mjs} +2 -2
- package/dist/{impl-wymd_Y3k.mjs.map → impl-DbDqwIOm.mjs.map} +1 -1
- package/dist/{impl-De1JItpM2.mjs → impl-DgMvt8lw2.mjs} +2 -2
- package/dist/{impl-De1JItpM2.mjs.map → impl-DgMvt8lw2.mjs.map} +1 -1
- package/dist/{impl-Dd60oodD2.mjs → impl-Dgzu4S-l2.mjs} +2 -2
- package/dist/{impl-Dd60oodD2.mjs.map → impl-Dgzu4S-l2.mjs.map} +1 -1
- package/dist/{impl-Dw-MR5nR.mjs → impl-DibupTqM.mjs} +2 -2
- package/dist/{impl-Dw-MR5nR.mjs.map → impl-DibupTqM.mjs.map} +1 -1
- package/dist/{impl-BiQ9lDze.mjs → impl-DjbKuC16.mjs} +2 -2
- package/dist/{impl-BiQ9lDze.mjs.map → impl-DjbKuC16.mjs.map} +1 -1
- package/dist/{impl-C7iC7S5D.mjs → impl-DsMlD5qQ.mjs} +2 -2
- package/dist/{impl-C7iC7S5D.mjs.map → impl-DsMlD5qQ.mjs.map} +1 -1
- package/dist/{impl-zH16n-0l.mjs → impl-DyCOfEyz.mjs} +2 -2
- package/dist/{impl-zH16n-0l.mjs.map → impl-DyCOfEyz.mjs.map} +1 -1
- package/dist/{impl-Q8a16IkZ.mjs → impl-DyRlE2dG.mjs} +2 -2
- package/dist/{impl-Q8a16IkZ.mjs.map → impl-DyRlE2dG.mjs.map} +1 -1
- package/dist/{impl-DwGZvFYI.mjs → impl-IsLLLZ8_.mjs} +2 -2
- package/dist/{impl-DwGZvFYI.mjs.map → impl-IsLLLZ8_.mjs.map} +1 -1
- package/dist/{impl-BY1HzPeX.mjs → impl-XurXwXBn.mjs} +2 -2
- package/dist/{impl-BY1HzPeX.mjs.map → impl-XurXwXBn.mjs.map} +1 -1
- package/dist/{impl-DAlYoIsj.mjs → impl-lhik35ZQ.mjs} +2 -2
- package/dist/{impl-DAlYoIsj.mjs.map → impl-lhik35ZQ.mjs.map} +1 -1
- package/dist/{impl-D8KUHOU8.mjs → impl-m3xHPKGn.mjs} +2 -2
- package/dist/{impl-D8KUHOU8.mjs.map → impl-m3xHPKGn.mjs.map} +1 -1
- package/dist/{impl-B5CqfbCN.mjs → impl-wsqV83LN.mjs} +2 -2
- package/dist/{impl-B5CqfbCN.mjs.map → impl-wsqV83LN.mjs.map} +1 -1
- package/dist/{impl-BUbwefXr.mjs → impl-xfle7PY2.mjs} +2 -2
- package/dist/{impl-BUbwefXr.mjs.map → impl-xfle7PY2.mjs.map} +1 -1
- package/dist/index.d.mts +4 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{markRequestDataSiloIdsCompleted-CJdC2ta9.mjs → markRequestDataSiloIdsCompleted-hJUkApfy.mjs} +2 -2
- package/dist/{markRequestDataSiloIdsCompleted-CJdC2ta9.mjs.map → markRequestDataSiloIdsCompleted-hJUkApfy.mjs.map} +1 -1
- package/dist/{markSilentPrivacyRequests-CIjtVoXr.mjs → markSilentPrivacyRequests-CHZW_BF1.mjs} +2 -2
- package/dist/{markSilentPrivacyRequests-CIjtVoXr.mjs.map → markSilentPrivacyRequests-CHZW_BF1.mjs.map} +1 -1
- package/dist/{notifyPrivacyRequestsAdditionalTime-DsjlAlh8.mjs → notifyPrivacyRequestsAdditionalTime-Bbf8jD3v.mjs} +2 -2
- package/dist/{notifyPrivacyRequestsAdditionalTime-DsjlAlh8.mjs.map → notifyPrivacyRequestsAdditionalTime-Bbf8jD3v.mjs.map} +1 -1
- package/dist/{policy-bundle-manifest-xaiuhXv5.mjs → policy-bundle-manifest-C72R7B1B.mjs} +2 -2
- package/dist/{policy-bundle-manifest-xaiuhXv5.mjs.map → policy-bundle-manifest-C72R7B1B.mjs.map} +1 -1
- package/dist/{policy-project-discovery-Dxikd8NT.mjs → policy-project-discovery-B3x2Rsb4.mjs} +2 -2
- package/dist/{policy-project-discovery-Dxikd8NT.mjs.map → policy-project-discovery-B3x2Rsb4.mjs.map} +1 -1
- package/dist/{policy-scaffold-config-DRWTaw0k.mjs → policy-scaffold-config-CX_yfLIH.mjs} +2 -2
- package/dist/{policy-scaffold-config-DRWTaw0k.mjs.map → policy-scaffold-config-CX_yfLIH.mjs.map} +1 -1
- package/dist/{pullChunkedCustomSiloOutstandingIdentifiers-DbNvJJrP.mjs → pullChunkedCustomSiloOutstandingIdentifiers-DbN50nXD.mjs} +2 -2
- package/dist/{pullChunkedCustomSiloOutstandingIdentifiers-DbNvJJrP.mjs.map → pullChunkedCustomSiloOutstandingIdentifiers-DbN50nXD.mjs.map} +1 -1
- package/dist/{pullManualEnrichmentIdentifiersToCsv-3hX7b2sn.mjs → pullManualEnrichmentIdentifiersToCsv-CVdPCVBt.mjs} +2 -2
- package/dist/{pullManualEnrichmentIdentifiersToCsv-3hX7b2sn.mjs.map → pullManualEnrichmentIdentifiersToCsv-CVdPCVBt.mjs.map} +1 -1
- package/dist/{pushCronIdentifiersFromCsv-DSsDe8er.mjs → pushCronIdentifiersFromCsv-BOxNiYeL.mjs} +2 -2
- package/dist/{pushCronIdentifiersFromCsv-DSsDe8er.mjs.map → pushCronIdentifiersFromCsv-BOxNiYeL.mjs.map} +1 -1
- package/dist/{pushManualEnrichmentIdentifiersFromCsv-B4NWrYLP.mjs → pushManualEnrichmentIdentifiersFromCsv-CMtEFHNu.mjs} +2 -2
- package/dist/{pushManualEnrichmentIdentifiersFromCsv-B4NWrYLP.mjs.map → pushManualEnrichmentIdentifiersFromCsv-CMtEFHNu.mjs.map} +1 -1
- package/dist/{removeUnverifiedRequestIdentifiers-eub1buew.mjs → removeUnverifiedRequestIdentifiers-uy507BaB.mjs} +2 -2
- package/dist/{removeUnverifiedRequestIdentifiers-eub1buew.mjs.map → removeUnverifiedRequestIdentifiers-uy507BaB.mjs.map} +1 -1
- package/dist/{retryRequestDataSilos-Bz2krPpO.mjs → retryRequestDataSilos-CawyTtni.mjs} +2 -2
- package/dist/{retryRequestDataSilos-Bz2krPpO.mjs.map → retryRequestDataSilos-CawyTtni.mjs.map} +1 -1
- package/dist/{skipPreflightJobs-DnMtLNHR.mjs → skipPreflightJobs-Dc9C6XLJ.mjs} +2 -2
- package/dist/{skipPreflightJobs-DnMtLNHR.mjs.map → skipPreflightJobs-Dc9C6XLJ.mjs.map} +1 -1
- package/dist/{skipRequestDataSilos-hFvX-tmq.mjs → skipRequestDataSilos-CTTxm3mv.mjs} +2 -2
- package/dist/{skipRequestDataSilos-hFvX-tmq.mjs.map → skipRequestDataSilos-CTTxm3mv.mjs.map} +1 -1
- package/dist/{streamPrivacyRequestsToCsv-1D5tgLIt.mjs → streamPrivacyRequestsToCsv-BPL16Yrs.mjs} +2 -2
- package/dist/{streamPrivacyRequestsToCsv-1D5tgLIt.mjs.map → streamPrivacyRequestsToCsv-BPL16Yrs.mjs.map} +1 -1
- package/dist/{updateConsentManagerVersionToLatest-DYvkq9Lr.mjs → updateConsentManagerVersionToLatest-1XbAWmkS.mjs} +2 -2
- package/dist/{updateConsentManagerVersionToLatest-DYvkq9Lr.mjs.map → updateConsentManagerVersionToLatest-1XbAWmkS.mjs.map} +1 -1
- package/dist/{uploadConsents-BIt4fC8B.mjs → uploadConsents-BugquZ_E.mjs} +2 -2
- package/dist/{uploadConsents-BIt4fC8B.mjs.map → uploadConsents-BugquZ_E.mjs.map} +1 -1
- package/dist/{uploadPrivacyRequestsFromCsv-Df79Xp4b.mjs → uploadPrivacyRequestsFromCsv-DQLyRjWA.mjs} +2 -2
- package/dist/{uploadPrivacyRequestsFromCsv-Df79Xp4b.mjs.map → uploadPrivacyRequestsFromCsv-DQLyRjWA.mjs.map} +1 -1
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-B964vhTe.mjs","names":["fg"],"sources":["../src/commands/policy/helpers/buildOpaBundleTarball.ts","../src/commands/policy/helpers/buildPolicyBundleFormData.ts","../src/commands/policy/helpers/defaultPolicyVersionLabel.ts","../src/lib/policy/policy-publish-hints.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 { MAX_BUNDLE_COMPRESSED_BYTES, MAX_BUNDLE_DECOMPRESSED_BYTES } from '@transcend-io/utils';\nimport fg from 'fast-glob';\n\nimport { validatePolicyBundleContents } from '../../../lib/policy/policy-bundle-manifest.js';\nimport { POLICY_MANIFEST_FILENAME } from '../../../lib/policy/policy-scaffold-templates.js';\nimport { assertOpaInstalled } from './assertOpaInstalled.js';\nimport { runOPACapture } from './runOpa.js';\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}\n\n/**\n * Collects `.manifest` and publishable `.rego` files from a policy directory.\n *\n * @param dir - Absolute path to the policy bundle directory\n * @returns Validated archive entries\n */\nfunction collectPolicyBundleArchiveEntries(dir: string): PolicyBundleArchiveContents {\n const regoFiles = fg\n .sync('**/*.rego', {\n cwd: dir,\n onlyFiles: true,\n dot: false,\n })\n .sort();\n const onDiskManifestPath = path.join(dir, POLICY_MANIFEST_FILENAME);\n const { publishableRegoPaths } = validatePolicyBundleContents(\n fs.existsSync(onDiskManifestPath) ? fs.readFileSync(onDiskManifestPath, 'utf8') : undefined,\n regoFiles.map((relativePath) => ({\n path: relativePath,\n contents: fs.readFileSync(path.join(dir, relativePath), 'utf8'),\n })),\n );\n\n return {\n entries: [POLICY_MANIFEST_FILENAME, ...publishableRegoPaths],\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` +\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. Bundle mode (`-b`) keeps local\n // `input.json` / `input.example.json` fixtures from merging as data.\n // `*_test.rego` files are local-only.\n const { code, stderr } = await runOPACapture(\n ['build', '--ignore', '*_test.rego', '-b', '-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` and\n * one or more `.rego` files. Local projects author an OPA `.manifest` and it\n * is uploaded directly — no rename at pack time. Before packaging, the\n * manifest is validated (shape + root coverage) and the bundle is validated\n * with `opa check` (strict Rego linting) and `opa build` (full compilation) so\n * failures surface client-side rather than after upload.\n *\n * @param dir - Directory containing `.manifest` 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 } = collectPolicyBundleArchiveEntries(resolvedDir);\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 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 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 {\n PERMISSIONS_POLICY_BUNDLE_NAME,\n PolicyTemplate,\n type PolicyTemplateName,\n} from './policy-scaffold-templates.js';\n\n/** Inputs used to soft-warn about Permissions vs generic publish naming. */\nexport interface PolicyPublishBundleNameHintInput {\n /** Optional scaffold template from `.manifest` metadata. */\n template?: PolicyTemplateName;\n /** Declared OPA package roots. */\n roots: string[];\n}\n\n/**\n * Whether local authoring signals suggest a Permissions API bundle.\n *\n * Prefers explicit `metadata.transcend.io.template`. Without metadata, falls\n * back to a root that is exactly `permissions` or nested under it.\n *\n * @param input - Manifest template hint and roots\n * @returns Whether the local tree looks Permissions-oriented\n */\nfunction looksLikePermissionsBundle(input: PolicyPublishBundleNameHintInput): boolean {\n if (input.template === PolicyTemplate.Permissions) {\n return true;\n }\n if (input.template === PolicyTemplate.Generic) {\n return false;\n }\n return input.roots.some(\n (root) =>\n root === PERMISSIONS_POLICY_BUNDLE_NAME ||\n root.startsWith(`${PERMISSIONS_POLICY_BUNDLE_NAME}/`),\n );\n}\n\n/**\n * Soft-warning when `--remote-bundle-name` disagrees with Permissions conventions.\n *\n * Upload does not enforce bundle kinds. Permissions API only loads the\n * remote bundle named {@link PERMISSIONS_POLICY_BUNDLE_NAME}.\n *\n * @param bundleName - Value of `--remote-bundle-name`\n * @param input - Local manifest template/roots\n * @returns Warning text, or undefined when names align\n */\nexport function formatPolicyPublishBundleNameHint(\n bundleName: string,\n input: PolicyPublishBundleNameHintInput,\n): string | undefined {\n const permissionsLocal = looksLikePermissionsBundle(input);\n const permissionsRemote = bundleName === PERMISSIONS_POLICY_BUNDLE_NAME;\n\n if (permissionsLocal && !permissionsRemote) {\n return (\n `This directory looks like a Permissions API policy, but --remote-bundle-name is ` +\n `\"${bundleName}\". Permissions API only loads the remote bundle named ` +\n `\"${PERMISSIONS_POLICY_BUNDLE_NAME}\". Upload still succeeds; pass ` +\n `--remote-bundle-name=${PERMISSIONS_POLICY_BUNDLE_NAME} if that is the intended path.`\n );\n }\n\n if (!permissionsLocal && permissionsRemote) {\n return (\n `--remote-bundle-name=${PERMISSIONS_POLICY_BUNDLE_NAME} reserves the Permissions API ` +\n `path. Upload treats all bundles the same; only that fixed name is queried by ` +\n `the Permissions API. Continue only if you intend this bundle for the Permissions API.`\n );\n }\n\n return undefined;\n}\n","import { join } from 'node:path';\n\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { selectCommandLogger } from '../../../lib/cli/command-output.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 { parsePolicyBundleManifest } from '../../../lib/policy/policy-bundle-manifest.js';\nimport { resolvePolicyProjectDirectory } from '../../../lib/policy/policy-project-discovery.js';\nimport { formatPolicyPublishBundleNameHint } from '../../../lib/policy/policy-publish-hints.js';\nimport { POLICY_MANIFEST_FILENAME } from '../../../lib/policy/policy-scaffold-templates.js';\nimport { isInteractivePromptInvocation } from '../../../lib/scaffolding/prompts.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 /** Tenant-unique bundle name */\n 'remote-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 * @param directory - Policy bundle directory containing a `.manifest`\n */\nexport async function publish(\n this: LocalContext,\n {\n 'remote-bundle-name': bundleName,\n auth,\n 'transcend-url': transcendUrl,\n version,\n description,\n json,\n yes,\n debug = false,\n }: PublishCommandFlags,\n directory: string,\n): Promise<void> {\n doneInputValidation(this.process);\n setPolicyEngineCliDebug(debug);\n\n const commandLogger = selectCommandLogger(this.logger, json);\n const resolvedDir = resolvePolicyProjectDirectory(this.process.cwd(), directory);\n const versionLabel = version ?? defaultPolicyVersionLabel(bundleName);\n const client = buildPolicyEngineClient(transcendUrl, auth);\n const interactive = isInteractivePromptInvocation(\n { json, noInteractive: false },\n this.process.stdin.isTTY,\n this.process.stderr.isTTY,\n );\n\n let bundlePath: string | undefined;\n try {\n commandLogger.info(colors.green(`Building policy bundle from ${resolvedDir}...`));\n bundlePath = await buildOpaBundleTarball(resolvedDir);\n\n try {\n const manifestPath = join(resolvedDir, POLICY_MANIFEST_FILENAME);\n const manifest = parsePolicyBundleManifest(this.fs.readFileSync(manifestPath, 'utf8'));\n const bundleNameHint = formatPolicyPublishBundleNameHint(bundleName, manifest);\n if (bundleNameHint) {\n commandLogger.warn(colors.yellow(bundleNameHint));\n }\n } catch {\n // Best-effort authoring hint; tarball build already validated the manifest.\n }\n\n const existingBundleId = await resolveBundleIdByName(client, bundleName);\n\n let responseBody: CreatePolicyBundleResponse | CreatePolicyBundleVersionResponse;\n\n if (existingBundleId) {\n commandLogger.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 (!interactive && !yes) {\n this.logger.error(\n colors.red(\n 'Cannot create a new bundle in non-interactive or JSON mode; pass --yes to confirm.',\n ),\n );\n this.process.exit(1);\n return;\n }\n\n if (!yes) {\n commandLogger.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 commandLogger.info(colors.yellow('Publish cancelled.'));\n return;\n }\n }\n\n commandLogger.info(\n colors.green(`Creating bundle \"${bundleName}\" and uploading first version...`),\n );\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 commandLogger.info(colors.green('Policy bundle version uploaded successfully.'));\n\n const activateCommand = buildExampleCommand<ActivateCommandFlags>(['policy', 'activate'], {\n version: responseBody.version.version,\n 'remote-bundle-name': bundleName,\n });\n commandLogger.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 && this.fs.existsSync(bundlePath)) {\n this.fs.unlinkSync(bundlePath);\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"impl-B4PSQtDD.mjs","names":["fg"],"sources":["../src/commands/policy/helpers/buildOpaBundleTarball.ts","../src/commands/policy/helpers/buildPolicyBundleFormData.ts","../src/commands/policy/helpers/defaultPolicyVersionLabel.ts","../src/lib/policy/policy-publish-hints.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 { MAX_BUNDLE_COMPRESSED_BYTES, MAX_BUNDLE_DECOMPRESSED_BYTES } from '@transcend-io/utils';\nimport fg from 'fast-glob';\n\nimport { validatePolicyBundleContents } from '../../../lib/policy/policy-bundle-manifest.js';\nimport { POLICY_MANIFEST_FILENAME } from '../../../lib/policy/policy-scaffold-templates.js';\nimport { assertOpaInstalled } from './assertOpaInstalled.js';\nimport { runOPACapture } from './runOpa.js';\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}\n\n/**\n * Collects `.manifest` and publishable `.rego` files from a policy directory.\n *\n * @param dir - Absolute path to the policy bundle directory\n * @returns Validated archive entries\n */\nfunction collectPolicyBundleArchiveEntries(dir: string): PolicyBundleArchiveContents {\n const regoFiles = fg\n .sync('**/*.rego', {\n cwd: dir,\n onlyFiles: true,\n dot: false,\n })\n .sort();\n const onDiskManifestPath = path.join(dir, POLICY_MANIFEST_FILENAME);\n const { publishableRegoPaths } = validatePolicyBundleContents(\n fs.existsSync(onDiskManifestPath) ? fs.readFileSync(onDiskManifestPath, 'utf8') : undefined,\n regoFiles.map((relativePath) => ({\n path: relativePath,\n contents: fs.readFileSync(path.join(dir, relativePath), 'utf8'),\n })),\n );\n\n return {\n entries: [POLICY_MANIFEST_FILENAME, ...publishableRegoPaths],\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` +\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. Bundle mode (`-b`) keeps local\n // `input.json` / `input.example.json` fixtures from merging as data.\n // `*_test.rego` files are local-only.\n const { code, stderr } = await runOPACapture(\n ['build', '--ignore', '*_test.rego', '-b', '-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` and\n * one or more `.rego` files. Local projects author an OPA `.manifest` and it\n * is uploaded directly — no rename at pack time. Before packaging, the\n * manifest is validated (shape + root coverage) and the bundle is validated\n * with `opa check` (strict Rego linting) and `opa build` (full compilation) so\n * failures surface client-side rather than after upload.\n *\n * @param dir - Directory containing `.manifest` 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 } = collectPolicyBundleArchiveEntries(resolvedDir);\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 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 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 {\n PERMISSIONS_POLICY_BUNDLE_NAME,\n PolicyTemplate,\n type PolicyTemplateName,\n} from './policy-scaffold-templates.js';\n\n/** Inputs used to soft-warn about Permissions vs generic publish naming. */\nexport interface PolicyPublishBundleNameHintInput {\n /** Optional scaffold template from `.manifest` metadata. */\n template?: PolicyTemplateName;\n /** Declared OPA package roots. */\n roots: string[];\n}\n\n/**\n * Whether local authoring signals suggest a Permissions API bundle.\n *\n * Prefers explicit `metadata.transcend.io.template`. Without metadata, falls\n * back to a root that is exactly `permissions` or nested under it.\n *\n * @param input - Manifest template hint and roots\n * @returns Whether the local tree looks Permissions-oriented\n */\nfunction looksLikePermissionsBundle(input: PolicyPublishBundleNameHintInput): boolean {\n if (input.template === PolicyTemplate.Permissions) {\n return true;\n }\n if (input.template === PolicyTemplate.Generic) {\n return false;\n }\n return input.roots.some(\n (root) =>\n root === PERMISSIONS_POLICY_BUNDLE_NAME ||\n root.startsWith(`${PERMISSIONS_POLICY_BUNDLE_NAME}/`),\n );\n}\n\n/**\n * Soft-warning when `--remote-bundle-name` disagrees with Permissions conventions.\n *\n * Upload does not enforce bundle kinds. Permissions API only loads the\n * remote bundle named {@link PERMISSIONS_POLICY_BUNDLE_NAME}.\n *\n * @param bundleName - Value of `--remote-bundle-name`\n * @param input - Local manifest template/roots\n * @returns Warning text, or undefined when names align\n */\nexport function formatPolicyPublishBundleNameHint(\n bundleName: string,\n input: PolicyPublishBundleNameHintInput,\n): string | undefined {\n const permissionsLocal = looksLikePermissionsBundle(input);\n const permissionsRemote = bundleName === PERMISSIONS_POLICY_BUNDLE_NAME;\n\n if (permissionsLocal && !permissionsRemote) {\n return (\n `This directory looks like a Permissions API policy, but --remote-bundle-name is ` +\n `\"${bundleName}\". Permissions API only loads the remote bundle named ` +\n `\"${PERMISSIONS_POLICY_BUNDLE_NAME}\". Upload still succeeds; pass ` +\n `--remote-bundle-name=${PERMISSIONS_POLICY_BUNDLE_NAME} if that is the intended path.`\n );\n }\n\n if (!permissionsLocal && permissionsRemote) {\n return (\n `--remote-bundle-name=${PERMISSIONS_POLICY_BUNDLE_NAME} reserves the Permissions API ` +\n `path. Upload treats all bundles the same; only that fixed name is queried by ` +\n `the Permissions API. Continue only if you intend this bundle for the Permissions API.`\n );\n }\n\n return undefined;\n}\n","import { join } from 'node:path';\n\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { selectCommandLogger } from '../../../lib/cli/command-output.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 { parsePolicyBundleManifest } from '../../../lib/policy/policy-bundle-manifest.js';\nimport { resolvePolicyProjectDirectory } from '../../../lib/policy/policy-project-discovery.js';\nimport { formatPolicyPublishBundleNameHint } from '../../../lib/policy/policy-publish-hints.js';\nimport { POLICY_MANIFEST_FILENAME } from '../../../lib/policy/policy-scaffold-templates.js';\nimport { isInteractivePromptInvocation } from '../../../lib/scaffolding/prompts.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 /** Tenant-unique bundle name */\n 'remote-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 * @param directory - Policy bundle directory containing a `.manifest`\n */\nexport async function publish(\n this: LocalContext,\n {\n 'remote-bundle-name': bundleName,\n auth,\n 'transcend-url': transcendUrl,\n version,\n description,\n json,\n yes,\n debug = false,\n }: PublishCommandFlags,\n directory: string,\n): Promise<void> {\n doneInputValidation(this.process);\n setPolicyEngineCliDebug(debug);\n\n const commandLogger = selectCommandLogger(this.logger, json);\n const resolvedDir = resolvePolicyProjectDirectory(this.process.cwd(), directory);\n const versionLabel = version ?? defaultPolicyVersionLabel(bundleName);\n const client = buildPolicyEngineClient(transcendUrl, auth);\n const interactive = isInteractivePromptInvocation(\n { json, noInteractive: false },\n this.process.stdin.isTTY,\n this.process.stderr.isTTY,\n );\n\n let bundlePath: string | undefined;\n try {\n commandLogger.info(colors.green(`Building policy bundle from ${resolvedDir}...`));\n bundlePath = await buildOpaBundleTarball(resolvedDir);\n\n try {\n const manifestPath = join(resolvedDir, POLICY_MANIFEST_FILENAME);\n const manifest = parsePolicyBundleManifest(this.fs.readFileSync(manifestPath, 'utf8'));\n const bundleNameHint = formatPolicyPublishBundleNameHint(bundleName, manifest);\n if (bundleNameHint) {\n commandLogger.warn(colors.yellow(bundleNameHint));\n }\n } catch {\n // Best-effort authoring hint; tarball build already validated the manifest.\n }\n\n const existingBundleId = await resolveBundleIdByName(client, bundleName);\n\n let responseBody: CreatePolicyBundleResponse | CreatePolicyBundleVersionResponse;\n\n if (existingBundleId) {\n commandLogger.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 (!interactive && !yes) {\n this.logger.error(\n colors.red(\n 'Cannot create a new bundle in non-interactive or JSON mode; pass --yes to confirm.',\n ),\n );\n this.process.exit(1);\n return;\n }\n\n if (!yes) {\n commandLogger.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 commandLogger.info(colors.yellow('Publish cancelled.'));\n return;\n }\n }\n\n commandLogger.info(\n colors.green(`Creating bundle \"${bundleName}\" and uploading first version...`),\n );\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 commandLogger.info(colors.green('Policy bundle version uploaded successfully.'));\n\n const activateCommand = buildExampleCommand<ActivateCommandFlags>(['policy', 'activate'], {\n version: responseBody.version.version,\n 'remote-bundle-name': bundleName,\n });\n commandLogger.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 && this.fs.existsSync(bundlePath)) {\n this.fs.unlinkSync(bundlePath);\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./skipRequestDataSilos-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./skipRequestDataSilos-CTTxm3mv.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";async function n({auth:n,dataSiloId:r,status:i,statuses:a,transcendUrl:o,actionTypes:s}){t(this.process),await e({transcendUrl:o,auth:n,status:i,dataSiloId:r,requestStatuses:a,actionTypes:s})}export{n as skipRequestDataSilos};
|
|
2
|
+
//# sourceMappingURL=impl-B6PDRnqA.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-B6PDRnqA.mjs","names":["skipRequestDataSilosHelper"],"sources":["../src/commands/request/system/skip-request-data-silos/impl.ts"],"sourcesContent":["import type {\n RequestAction,\n RequestDataSiloStatus,\n RequestStatus,\n} from '@transcend-io/privacy-types';\n\nimport type { LocalContext } from '../../../../context.js';\nimport { doneInputValidation } from '../../../../lib/cli/done-input-validation.js';\nimport { skipRequestDataSilos as skipRequestDataSilosHelper } from '../../../../lib/requests/index.js';\n\nexport interface SkipRequestDataSilosCommandFlags {\n auth: string;\n dataSiloId: string;\n transcendUrl: string;\n statuses: RequestStatus[];\n status: (typeof RequestDataSiloStatus)['Skipped'] | (typeof RequestDataSiloStatus)['Resolved'];\n actionTypes?: RequestAction[];\n}\n\nexport async function skipRequestDataSilos(\n this: LocalContext,\n {\n auth,\n dataSiloId,\n status,\n statuses,\n transcendUrl,\n actionTypes,\n }: SkipRequestDataSilosCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n await skipRequestDataSilosHelper({\n transcendUrl,\n auth,\n status,\n dataSiloId,\n requestStatuses: statuses,\n actionTypes,\n });\n}\n"],"mappings":"4GAmBA,eAAsB,EAEpB,CACE,OACA,aACA,SACA,WACA,eACA,eAEa,CACf,EAAoB,KAAK,QAAQ,CAEjC,MAAMA,EAA2B,CAC/B,eACA,OACA,SACA,aACA,gBAAiB,EACjB,cACD,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./skipPreflightJobs-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./skipPreflightJobs-Dc9C6XLJ.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";async function n({auth:n,transcendUrl:r,enricherIds:i}){t(this.process),await e({transcendUrl:r,auth:n,enricherIds:i})}export{n as skipPreflightJobs};
|
|
2
|
+
//# sourceMappingURL=impl-B7Rfw4nS.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-B7Rfw4nS.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);\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,CAEjC,MAAMA,EAAwB,CAC5B,eACA,OACA,cACD,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./updateConsentManagerVersionToLatest-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./updateConsentManagerVersionToLatest-1XbAWmkS.mjs";import{t}from"./validateTranscendAuth-BrVGfq6X.mjs";import{t as n}from"./done-input-validation-LiTaCEzF.mjs";import{ConsentBundleType as r}from"@transcend-io/privacy-types";import i from"colors";import{mapSeries as a}from"@transcend-io/utils";async function o({auth:o,bundleTypes:s=[r.Production,r.Test],deploy:c,transcendUrl:l}){n(this.process);let u=await t(o,this);typeof u==`string`?(await e({deploy:c,transcendUrl:l,auth:u,bundleTypes:s}),this.logger.info(i.green(`Successfully updated Consent Manager!`))):(await a(u,async t=>{this.logger.info(i.magenta(`Updating Consent Manager for organization "${t.organizationName}"...`)),await e({deploy:c,transcendUrl:l,auth:t.apiKey,bundleTypes:s}),this.logger.info(i.green(`Successfully updated Consent Manager for organization "${t.organizationName}"!`))}),this.logger.info(i.green(`Successfully updated Consent Managers!`)))}export{o as updateConsentManager};
|
|
2
|
+
//# sourceMappingURL=impl-BAzZNoIY.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-BAzZNoIY.mjs","names":[],"sources":["../src/commands/consent/update-consent-manager/impl.ts"],"sourcesContent":["import { ConsentBundleType } from '@transcend-io/privacy-types';\nimport { mapSeries } from '@transcend-io/utils';\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { validateTranscendAuth } from '../../../lib/api-keys/index.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { updateConsentManagerVersionToLatest } from '../../../lib/consent-manager/index.js';\n\nexport interface UpdateConsentManagerCommandFlags {\n auth: string;\n bundleTypes: ConsentBundleType[];\n deploy: boolean;\n transcendUrl: string;\n}\n\nexport async function updateConsentManager(\n this: LocalContext,\n {\n auth,\n bundleTypes = [ConsentBundleType.Production, ConsentBundleType.Test],\n deploy,\n transcendUrl,\n }: UpdateConsentManagerCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n // Parse authentication as API key or path to list of API keys\n const apiKeyOrList = await validateTranscendAuth(auth, this);\n\n // Handle single update\n if (typeof apiKeyOrList === 'string') {\n // Update consent manager\n await updateConsentManagerVersionToLatest({\n deploy,\n transcendUrl,\n auth: apiKeyOrList,\n bundleTypes,\n });\n this.logger.info(colors.green('Successfully updated Consent Manager!'));\n } else {\n await mapSeries(apiKeyOrList, async (apiKey) => {\n this.logger.info(\n colors.magenta(`Updating Consent Manager for organization \"${apiKey.organizationName}\"...`),\n );\n\n await updateConsentManagerVersionToLatest({\n deploy,\n transcendUrl,\n auth: apiKey.apiKey,\n bundleTypes,\n });\n\n this.logger.info(\n colors.green(\n `Successfully updated Consent Manager for organization \"${apiKey.organizationName}\"!`,\n ),\n );\n });\n this.logger.info(colors.green('Successfully updated Consent Managers!'));\n }\n}\n"],"mappings":"0TAgBA,eAAsB,EAEpB,CACE,OACA,cAAc,CAAC,EAAkB,WAAY,EAAkB,KAAK,CACpE,SACA,gBAEa,CACf,EAAoB,KAAK,QAAQ,CAGjC,IAAM,EAAe,MAAM,EAAsB,EAAM,KAAK,CAGxD,OAAO,GAAiB,UAE1B,MAAM,EAAoC,CACxC,SACA,eACA,KAAM,EACN,cACD,CAAC,CACF,KAAK,OAAO,KAAK,EAAO,MAAM,wCAAwC,CAAC,GAEvE,MAAM,EAAU,EAAc,KAAO,IAAW,CAC9C,KAAK,OAAO,KACV,EAAO,QAAQ,8CAA8C,EAAO,iBAAiB,MAAM,CAC5F,CAED,MAAM,EAAoC,CACxC,SACA,eACA,KAAM,EAAO,OACb,cACD,CAAC,CAEF,KAAK,OAAO,KACV,EAAO,MACL,0DAA0D,EAAO,iBAAiB,IACnF,CACF,EACD,CACF,KAAK,OAAO,KAAK,EAAO,MAAM,yCAAyC,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./pullManualEnrichmentIdentifiersToCsv-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./pullManualEnrichmentIdentifiersToCsv-CVdPCVBt.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";async function n({auth:n,transcendUrl:r,file:i,concurrency:a,actions:o,sombraAuth:s}){t(this.process),await e({file:i,transcendUrl:r,concurrency:a,requestActions:o,auth:n,sombraAuth:s})}export{n as pullIdentifiers};
|
|
2
|
+
//# sourceMappingURL=impl-BSZmuX3n.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-BSZmuX3n.mjs","names":[],"sources":["../src/commands/request/preflight/pull-identifiers/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 { pullManualEnrichmentIdentifiersToCsv } from '../../../../lib/manual-enrichment/index.js';\n\nexport interface PullIdentifiersCommandFlags {\n auth: string;\n sombraAuth?: string;\n transcendUrl: string;\n file: string;\n actions?: RequestAction[];\n concurrency: number;\n}\n\nexport async function pullIdentifiers(\n this: LocalContext,\n { auth, transcendUrl, file, concurrency, actions, sombraAuth }: PullIdentifiersCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n await pullManualEnrichmentIdentifiersToCsv({\n file,\n transcendUrl,\n concurrency,\n requestActions: actions,\n auth,\n sombraAuth,\n });\n}\n"],"mappings":"4HAeA,eAAsB,EAEpB,CAAE,OAAM,eAAc,OAAM,cAAa,UAAS,cACnC,CACf,EAAoB,KAAK,QAAQ,CAEjC,MAAM,EAAqC,CACzC,OACA,eACA,cACA,eAAgB,EAChB,OACA,aACD,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./approvePrivacyRequests-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./approvePrivacyRequests-BWwO-VkZ.mjs";import{t}from"./done-input-validation-LiTaCEzF.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),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-BaC1mNZ_.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-BaC1mNZ_.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);\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,CAEjC,MAAM,EAAuB,CAC3B,eACA,eAAgB,EAChB,OACA,eAAgB,EAChB,cACA,mBACA,kBACA,iBACA,kBACA,iBACD,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./collectCsvFilesOrExit-BindZ0dF.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";import{n,r,t as i}from"./createPoolingCommandUi-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./collectCsvFilesOrExit-BindZ0dF.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";import{n,r,t as i}from"./createPoolingCommandUi-CDtlHb8_.mjs";import a from"colors";import{CHILD_FLAG as o,PoolCancelledError as s,computePoolSize as c,resolveWorkerPath as l,runPool as u}from"@transcend-io/utils";function d(e){return n(e)}function f(e){return r(e)}const p={renderHeader:d,renderWorkers:f};async function m(n){t(this.process);let{directory:r,outputDir:d,clearOutputDir:f,chunkSizeMB:m,concurrency:h,viewerMode:g}=n,_=i(this,p,g),v=e(r,this),{poolSize:y,cpuCount:b}=c(h,v.length);this.logger.info(a.green(`Chunking ${v.length} CSV file(s) with pool size ${y} (CPU=${b})`));let x=v.map(e=>({filePath:e,options:{outputDir:d,clearOutputDir:f,chunkSizeMB:m}}));await u({title:`Chunk CSV - ${r}`,baseDir:r||d||this.process.cwd(),childFlag:o,childModulePath:l(import.meta.url,`commands/admin/chunk-csv/worker.mjs`),poolSize:y,cpuCount:b,filesTotal:v.length,hooks:{nextTask:()=>x.shift(),taskLabel:e=>e.filePath,initTotals:()=>({}),initSlotProgress:()=>void 0,onProgress:e=>e,onResult:(e,t)=>({totals:e,ok:!!t.ok}),postProcess:async()=>{}},viewerMode:g,..._}).catch(e=>{throw e instanceof s&&this.process.exit(130),e})}export{m as chunkCsv};
|
|
2
|
+
//# sourceMappingURL=impl-BlzJ6Ych.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-BlzJ6Ych.mjs","names":[],"sources":["../src/commands/admin/chunk-csv/ui/plugin.ts","../src/commands/admin/chunk-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 chunk-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 chunk-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 chunkCsvPlugin: 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 { collectCsvFilesOrExit } from '../../../lib/helpers/collectCsvFilesOrExit.js';\nimport { createPoolingCommandUi } from '../../../lib/pooling/index.js';\nimport { chunkCsvPlugin } from './ui/index.js';\nimport type { ChunkProgress, ChunkResult, ChunkTask } from './worker.js';\n\n/**\n * Totals aggregate for this command.\n * We don’t need custom counters since the runner already tracks\n * completed/failed counts in its header — so we just use an empty record.\n */\ntype Totals = Record<string, never>;\n\n/**\n * CLI flags accepted by the `chunk-csv` command.\n *\n * These are passed down from the CLI parser into the parent process.\n */\nexport type ChunkCsvCommandFlags = {\n directory: string;\n outputDir?: string;\n clearOutputDir: boolean;\n chunkSizeMB: number;\n concurrency?: number;\n viewerMode: boolean;\n};\n\n/**\n * Parent entrypoint for chunking many CSVs in parallel using the worker pool runner.\n *\n * Lifecycle:\n * 1) Discover CSV inputs (exit if none).\n * 2) Compute pool size (CPU-count heuristic or --concurrency).\n * 3) Build a FIFO queue of `ChunkTask`s.\n * 4) Define pool hooks to drive task assignment, progress, and result handling.\n * 5) Launch the pool with `runPool`, rendering via the `chunkCsvPlugin`.\n *\n * @param this - Bound CLI context (provides process exit + logging).\n * @param flags - CLI options for the run.\n */\nexport async function chunkCsv(this: LocalContext, flags: ChunkCsvCommandFlags): Promise<void> {\n doneInputValidation(this.process);\n\n const { directory, outputDir, clearOutputDir, chunkSizeMB, concurrency, viewerMode } = flags;\n const poolingUi = createPoolingCommandUi(this, chunkCsvPlugin, viewerMode);\n\n /* 1) Discover CSV inputs */\n const files = collectCsvFilesOrExit(directory, this);\n\n /* 2) Size the pool */\n const { poolSize, cpuCount } = computePoolSize(concurrency, files.length);\n\n this.logger.info(\n colors.green(\n `Chunking ${files.length} CSV file(s) with pool size ${poolSize} (CPU=${cpuCount})`,\n ),\n );\n\n /* 3) Prepare a simple FIFO queue of tasks (one per file). */\n const queue = files.map<ChunkTask>((filePath) => ({\n filePath,\n options: { outputDir, clearOutputDir, chunkSizeMB },\n }));\n\n /* 4) Define pool hooks to adapt runner to this command. */\n const hooks: PoolHooks<ChunkTask, ChunkProgress, ChunkResult, 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 receives log context when viewerMode=true — we don’t need it here.\n postProcess: async () => {\n // nothing extra for chunk-csv\n },\n };\n\n /* 5) Launch the pool runner with our hooks and custom dashboard plugin. */\n await runPool({\n title: `Chunk CSV - ${directory}`,\n baseDir: directory || outputDir || this.process.cwd(),\n childFlag: CHILD_FLAG,\n childModulePath: resolveWorkerPath(import.meta.url, 'commands/admin/chunk-csv/worker.mjs'),\n poolSize,\n cpuCount,\n filesTotal: files.length,\n hooks,\n viewerMode,\n ...poolingUi,\n }).catch((err) => {\n if (err instanceof PoolCancelledError) {\n this.process.exit(130);\n }\n throw err;\n });\n}\n"],"mappings":"mUAcA,SAAS,EAAsB,EAAsD,CAEnF,OAAO,EAAW,EAAI,CASxB,SAAS,EAAuB,EAAsD,CACpF,OAAO,EAAe,EAAI,CAG5B,MAAa,EAA8D,CACzE,eACA,gBAED,CCkBD,eAAsB,EAA6B,EAA4C,CAC7F,EAAoB,KAAK,QAAQ,CAEjC,GAAM,CAAE,YAAW,YAAW,iBAAgB,cAAa,cAAa,cAAe,EACjF,EAAY,EAAuB,KAAM,EAAgB,EAAW,CAGpE,EAAQ,EAAsB,EAAW,KAAK,CAG9C,CAAE,WAAU,YAAa,EAAgB,EAAa,EAAM,OAAO,CAEzE,KAAK,OAAO,KACV,EAAO,MACL,YAAY,EAAM,OAAO,8BAA8B,EAAS,QAAQ,EAAS,GAClF,CACF,CAGD,IAAM,EAAQ,EAAM,IAAgB,IAAc,CAChD,WACA,QAAS,CAAE,YAAW,iBAAgB,cAAa,CACpD,EAAE,CAiBH,MAAM,EAAQ,CACZ,MAAO,eAAe,IACtB,QAAS,GAAa,GAAa,KAAK,QAAQ,KAAK,CACrD,UAAW,EACX,gBAAiB,EAAkB,OAAO,KAAK,IAAK,sCAAsC,CAC1F,WACA,WACA,WAAY,EAAM,OAClB,MAAA,CArBA,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,EAEpD,YAAa,SAAY,GAcpB,CACL,aACA,GAAG,EACJ,CAAC,CAAC,MAAO,GAAQ,CAIhB,MAHI,aAAe,GACjB,KAAK,QAAQ,KAAK,IAAI,CAElB,GACN"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./markSilentPrivacyRequests-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./markSilentPrivacyRequests-CHZW_BF1.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";async function n({auth:n,transcendUrl:r,actions:i,statuses:a,requestIds:o,createdAtBefore:s,createdAtAfter:c,updatedAtBefore:l,updatedAtAfter:u,concurrency:d}){t(this.process),await e({transcendUrl:r,requestActions:i,auth:n,requestIds:o,statuses:a,concurrency:d,createdAtBefore:s,createdAtAfter:c,updatedAtBefore:l,updatedAtAfter:u})}export{n as markSilent};
|
|
2
|
+
//# sourceMappingURL=impl-Bs5fBEjH.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-Bs5fBEjH.mjs","names":[],"sources":["../src/commands/request/mark-silent/impl.ts"],"sourcesContent":["import type { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { markSilentPrivacyRequests } from '../../../lib/requests/index.js';\n\nexport interface MarkSilentCommandFlags {\n auth: string;\n actions: RequestAction[];\n statuses?: RequestStatus[];\n requestIds?: string[];\n createdAtBefore?: Date;\n createdAtAfter?: Date;\n updatedAtBefore?: Date;\n updatedAtAfter?: Date;\n transcendUrl: string;\n concurrency: number;\n}\n\nexport async function markSilent(\n this: LocalContext,\n {\n auth,\n transcendUrl,\n actions,\n statuses,\n requestIds,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n concurrency,\n }: MarkSilentCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n await markSilentPrivacyRequests({\n transcendUrl,\n requestActions: actions,\n auth,\n requestIds,\n statuses,\n concurrency,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n });\n}\n"],"mappings":"iHAmBA,eAAsB,EAEpB,CACE,OACA,eACA,UACA,WACA,aACA,kBACA,iBACA,kBACA,iBACA,eAEa,CACf,EAAoB,KAAK,QAAQ,CAEjC,MAAM,EAA0B,CAC9B,eACA,eAAgB,EAChB,OACA,aACA,WACA,cACA,kBACA,iBACA,kBACA,iBACD,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{t as e}from"./constants-
|
|
1
|
+
import{t as e}from"./constants-B0oaHpig.mjs";import{t}from"./logger-CPu6zbyQ.mjs";import{t as n}from"./done-input-validation-LiTaCEzF.mjs";import{n as r}from"./constants-DC_bBO09.mjs";import i from"colors";import a from"fast-glob";import{buildTranscendGraphQLClient as o,fetchActiveSiloDiscoPlugin as s,uploadSiloDiscoveryResults as c}from"@transcend-io/sdk";async function l({scanPath:e,fileGlobs:n,ignoreDirs:r,config:i}){let{ignoreDirs:o,supportedFiles:s,scanFunction:c}=i,u=n===``?s:s.concat(n.split(`,`)),d=[...r.split(`,`),...o].filter(e=>e.length>0);try{let n=await a(`${e}/**/${u.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(),i=[...new Set(r.map(e=>e.name))];return t.info(`Found: ${i.length} unique dependencies`),i.map(t=>({name:t,resourceId:`${e}/**/${t}`,useStrictClassifier:!0}))}catch(e){throw Error(`Error scanning globs ${l} with error: ${e}`)}}async function u({scanPath:t,dataSiloId:a,auth:u,fileGlobs:d,ignoreDirs:f,transcendUrl:p}){n(this.process);let m=o(p,u),h=await s(m,{logger:this.logger,filterBy:{dataSiloId:a}}),g=r[h.dataSilo.type];g||(this.logger.error(i.red(`This plugin "${h.dataSilo.type}" is not supported for offline silo discovery.`)),this.process.exit(1));let _=await l({scanPath:t,fileGlobs:d,ignoreDirs:f,config:g});await c(m,{pluginId:h.id,results:_,logger:this.logger});let v=new URL(e);v.pathname=`/data-map/data-inventory/silo-discovery/triage`,v.searchParams.set(`filters`,JSON.stringify({pluginIds:[h.id]})),this.logger.info(i.green(`Scan found ${_.length} potential data silos at ${t}! View at '${v.href}'
|
|
2
2
|
|
|
3
3
|
NOTE: it may take 2-3 minutes for scan results to appear in the UI.`))}export{u as discoverSilos};
|
|
4
|
-
//# sourceMappingURL=impl-
|
|
4
|
+
//# sourceMappingURL=impl-BvyB3epw2.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-BvyB3epw2.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';\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';\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);\n\n // Create a GraphQL client\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n const plugin = await fetchActiveSiloDiscoPlugin(client, {\n logger: this.logger,\n filterBy: { dataSiloId },\n });\n\n const config = SILO_DISCOVERY_CONFIGS[plugin.dataSilo.type];\n if (!config) {\n this.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: this.logger,\n });\n\n const newUrl = new URL(ADMIN_DASH);\n newUrl.pathname = '/data-map/data-inventory/silo-discovery/triage';\n newUrl.searchParams.set(\n 'filters',\n JSON.stringify({\n pluginIds: [plugin.id],\n }),\n );\n\n // Indicate success\n this.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":"uWAuBA,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,ECxCnF,eAAsB,EAEpB,CAAE,WAAU,aAAY,OAAM,YAAW,aAAY,gBACtC,CACf,EAAoB,KAAK,QAAQ,CAGjC,IAAM,EAAS,EAA4B,EAAc,EAAK,CAExD,EAAS,MAAM,EAA2B,EAAQ,CACtD,OAAQ,KAAK,OACb,SAAU,CAAE,aAAY,CACzB,CAAC,CAEI,EAAS,EAAuB,EAAO,SAAS,MACjD,IACH,KAAK,OAAO,MACV,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,OAAQ,KAAK,OACd,CAAC,CAEF,IAAM,EAAS,IAAI,IAAI,EAAW,CAClC,EAAO,SAAW,iDAClB,EAAO,aAAa,IAClB,UACA,KAAK,UAAU,CACb,UAAW,CAAC,EAAO,GAAG,CACvB,CAAC,CACH,CAGD,KAAK,OAAO,KACV,EAAO,MACL,cAAc,EAAQ,OAAO,2BAA2B,EAAS,aACnD,EAAO,KAAK;;sEAE3B,CACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{n as e}from"./constants-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{n as e}from"./constants-B0oaHpig.mjs";import{s as t}from"./writeCsv-CNZrq3zU.mjs";import{t as n}from"./pullAllDatapoints-CNqQSSmF.mjs";import{t as r}from"./done-input-validation-LiTaCEzF.mjs";import{groupBy as i,uniq as a}from"lodash-es";import o from"colors";import{buildTranscendGraphQLClient as s}from"@transcend-io/sdk";async function c({auth:c,file:l,transcendUrl:u,dataSiloIds:d,includeAttributes:f,includeGuessedCategories:p,parentCategories:m,subCategories:h=[]}){r(this.process);try{let e=await n(s(u,c),{dataSiloIds:d,includeGuessedCategories:p,parentCategories:m,includeAttributes:f,subCategories:h});this.logger.info(o.magenta(`Writing datapoints to file "${l}"...`));let r=[];await t(l,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(i(e.attributeValues||[],({attributeKey:e})=>e.name)).reduce((e,[t,n])=>(e[t]=n.map(e=>e.name).join(`,`),e),{})};return r=a([...r,...Object.keys(t)]),t}),r)}catch(e){this.logger.error(o.red(`An error occurred syncing the datapoints: ${e.message}`)),this.process.exit(1)}this.logger.info(o.green(`Successfully synced datapoints to disk at ${l}! View at ${e}`))}export{c as pullDatapoints};
|
|
2
|
+
//# sourceMappingURL=impl-C3zfU0Jt2.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-C3zfU0Jt2.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';\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);\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 this.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 this.logger.error(colors.red(`An error occurred syncing the datapoints: ${err.message}`));\n this.process.exit(1);\n }\n\n // Indicate success\n this.logger.info(\n colors.green(\n `Successfully synced datapoints to disk at ${file}! View at ${ADMIN_DASH_DATAPOINTS}`,\n ),\n );\n}\n"],"mappings":"2UAsBA,eAAsB,EAEpB,CACE,OACA,OACA,eACA,cACA,oBACA,2BACA,mBACA,gBAAgB,EAAE,EAEL,CACf,EAAoB,KAAK,QAAQ,CAEjC,GAAI,CAIF,IAAM,EAAa,MAAM,EAFV,EAA4B,EAAc,EAER,CAAE,CACjD,cACA,2BACA,mBACA,oBACA,gBACD,CAAC,CAEF,KAAK,OAAO,KAAK,EAAO,QAAQ,+BAA+B,EAAK,MAAM,CAAC,CAC3E,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,KAAK,OAAO,MAAM,EAAO,IAAI,6CAA6C,EAAI,UAAU,CAAC,CACzF,KAAK,QAAQ,KAAK,EAAE,CAItB,KAAK,OAAO,KACV,EAAO,MACL,6CAA6C,EAAK,YAAY,IAC/D,CACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{i as e,n as t,t as n}from"./policy-project-discovery-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{i as e,n as t,t as n}from"./policy-project-discovery-B3x2Rsb4.mjs";import{t as r}from"./done-input-validation-LiTaCEzF.mjs";import{t as i}from"./run-captured-process-BjaSDWXG.mjs";import{n as a,r as o,t as s}from"./runRegalLintStep-DPaMm7Gg.mjs";import c from"node:path";import l from"colors";const u=[`opa-version`,`regal-version`,`format`,`regal-lint`],d={"opa-version":`OPA 1.x`,"regal-version":`Regal`,format:`OPA formatting`,"regal-lint":`Regal lint`};function f(e,t,n){n?e.logger.info(`${l.bold(n)}\n`):e.logger.info(`${l.bold(`Policy lint`)}\n`),t.checks.forEach(({name:n,status:r})=>{let i=r===`passed`?`PASS`:r===`failed`?`FAIL`:`SKIP`,a=r===`passed`?l.green(i):r===`failed`?l.red(i):l.yellow(i),o=n===`opa-version`&&t.tools.opa?` (${t.tools.opa})`:n===`regal-version`&&t.tools.regal?` (${t.tools.regal})`:``;e.logger.info(`${a} ${d[n]}${o}`)}),t.diagnostics.length>0&&e.logger.error(``),t.diagnostics.forEach(t=>{let n=t.path?`${t.path}: `:``;e.logger.error(l.red(`error [${t.code}]: ${n}${t.message}`))}),t.status===`passed`?(e.logger.info(``),e.logger.info(l.green(`Policy lint passed.`))):(e.logger.error(``),e.logger.error(l.red(`Policy lint failed.`)))}async function p({fix:e,noInteractive:t,json:n},r,i){let l=u.map(e=>({name:e,status:`skipped`})),d=[],f={version:1,status:`passed`,directory:r,fix:e,tools:{opa:null,regal:null},checks:l,unformattedFiles:[],fixedFiles:[],diagnostics:d},p=(e,t)=>{l.find(t=>t.name===e).status=t},m=(e,t,n)=>{d.push({code:e,severity:`error`,message:t,...n?{path:n}:{}})};if(!this.fs.existsSync(r)||!this.fs.statSync(r).isDirectory())return p(`opa-version`,`failed`),m(`project.directory`,`Policy directory does not exist or is not a directory: ${r}`,c.relative(this.process.cwd(),r)),f.status=`failed`,f;let h=await o.call(this,r,i);if(f.tools={opa:h.opa,regal:h.regal},p(`opa-version`,h.opaStatus),p(`regal-version`,h.regalStatus),h.diagnostics.forEach(e=>{m(e.code,e.message)}),f.tools.opa){let o=await a.call(this,{resolvedDir:r,fix:e,noInteractive:t,json:n,fixCommandHint:`transcend policy lint --fix`,runner:i});f.unformattedFiles=o.unformattedFiles,f.fixedFiles=o.fixedFiles,p(`format`,o.status),o.diagnostics.forEach(e=>{m(e.code,e.message)})}if(f.tools.regal){let e=await s.call(this,{resolvedDir:r,runner:i});p(`regal-lint`,e.status),e.diagnostics.forEach(e=>{m(e.code,e.message)})}return f.status=l.some(({status:e})=>e===`failed`)?`failed`:`passed`,f}async function m(a,o=n,s=i){r(this.process);let{fix:l=!1,noInteractive:d=!1,json:m=!1}=a,h=e(this.process.cwd(),o);if(!this.fs.existsSync(h)||!this.fs.statSync(h).isDirectory()){let e={version:1,status:`failed`,directory:h,fix:l,tools:{opa:null,regal:null},checks:u.map(e=>({name:e,status:e===`opa-version`?`failed`:`skipped`})),unformattedFiles:[],fixedFiles:[],diagnostics:[{code:`project.directory`,severity:`error`,message:`Policy directory does not exist or is not a directory: ${h}`,path:c.relative(this.process.cwd(),h)}]};m?this.process.stdout.write(`${JSON.stringify(e)}\n`):f(this,e),this.process.exitCode=1;return}let g=t(this,h);if(g.length===0){let e={version:1,status:`failed`,directory:h,fix:l,tools:{opa:null,regal:null},checks:u.map(e=>({name:e,status:e===`opa-version`?`failed`:`skipped`})),unformattedFiles:[],fixedFiles:[],diagnostics:[{code:`project.bundles`,severity:`error`,message:"No publishable policy bundles found. Add one with `transcend policy new`, or pass a directory that contains a `.manifest`.",path:c.relative(this.process.cwd(),h)||`.`}]};m?this.process.stdout.write(`${JSON.stringify(e)}\n`):f(this,e),this.process.exitCode=1;return}let _=[];for(let e of g)_.push(await p.call(this,{fix:l,noInteractive:d,json:m},e,s));let v=_.some(e=>e.status===`failed`);if(m)if(_.length===1)this.process.stdout.write(`${JSON.stringify(_[0])}\n`);else{let e={version:1,status:v?`failed`:`passed`,directory:h,fix:l,results:_};this.process.stdout.write(`${JSON.stringify(e)}\n`)}else _.length===1?f(this,_[0]):_.forEach((e,t)=>{t>0&&this.logger.info(``);let n=c.relative(this.process.cwd(),e.directory)||e.directory;f(this,e,`Policy lint — ${n}`)});v&&(this.process.exitCode=1)}export{m as lint};
|
|
2
|
+
//# sourceMappingURL=impl-C4CrzZFK2.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-UlLFb3UK2.mjs","names":[],"sources":["../src/lib/policy/policy-lint-model.ts","../src/commands/policy/lint/impl.ts"],"sourcesContent":["/** Stable policy lint result schema version. */\nexport const POLICY_LINT_RESULT_VERSION = 1;\n\n/** Stable multi-bundle lint result schema version. */\nexport const POLICY_LINT_MULTI_RESULT_VERSION = 1;\n\n/** Status of the lint gate or an individual step. */\nexport type PolicyLintStatus = 'passed' | 'failed' | 'skipped';\n\n/** One named policy lint step. */\nexport interface PolicyLintStep {\n /** Stable step name. */\n name: 'opa-version' | 'regal-version' | 'format' | 'regal-lint';\n /** Step outcome. */\n status: PolicyLintStatus;\n}\n\n/** Stable lint step execution order. */\nexport const POLICY_LINT_STEP_NAMES: PolicyLintStep['name'][] = [\n 'opa-version',\n 'regal-version',\n 'format',\n 'regal-lint',\n];\n\n/** User-facing lint step labels. */\nexport const POLICY_LINT_STEP_LABELS: Readonly<Record<PolicyLintStep['name'], string>> = {\n 'opa-version': 'OPA 1.x',\n 'regal-version': 'Regal',\n format: 'OPA formatting',\n 'regal-lint': 'Regal lint',\n};\n\n/** One machine-readable policy lint diagnostic. */\nexport interface PolicyLintDiagnostic {\n /** Stable diagnostic identifier. */\n code: string;\n /** Diagnostic severity. */\n severity: 'error';\n /** Human-readable detail, including captured tool output when available. */\n message: string;\n /** Optional path relative to the invocation directory. */\n path?: string;\n}\n\n/** Detected local policy tool versions. */\nexport interface PolicyLintTools {\n /** Detected OPA version, or null when missing or unsupported. */\n opa: string | null;\n /** Detected Regal version, or null when missing or unsupported. */\n regal: string | null;\n}\n\n/** Stable result emitted by `transcend policy lint --json` for one bundle. */\nexport interface PolicyLintResult {\n /** Result schema version. */\n version: typeof POLICY_LINT_RESULT_VERSION;\n /** Overall lint outcome. */\n status: Exclude<PolicyLintStatus, 'skipped'>;\n /** Absolute policy bundle directory. */\n directory: string;\n /** Whether formatting repair was explicitly requested. */\n fix: boolean;\n /** Detected supported tool versions. */\n tools: PolicyLintTools;\n /** Lint step outcomes in stable execution order. */\n checks: PolicyLintStep[];\n /** Files found to need OPA formatting, relative to the policy directory. */\n unformattedFiles: string[];\n /** Files repaired with OPA formatting, relative to the policy directory. */\n fixedFiles: string[];\n /** Ordered lint diagnostics. */\n diagnostics: PolicyLintDiagnostic[];\n}\n\n/**\n * Stable result when `transcend policy lint --json` lints multiple bundles.\n *\n * Emitted only when the selected path is a workspace with more than one\n * publishable `*-bundle/` directory.\n */\nexport interface PolicyLintMultiResult {\n /** Result schema version. */\n version: typeof POLICY_LINT_MULTI_RESULT_VERSION;\n /** Overall lint outcome across all bundles. */\n status: Exclude<PolicyLintStatus, 'skipped'>;\n /** Absolute policy workspace directory that was searched. */\n directory: string;\n /** Whether formatting repair was explicitly requested. */\n fix: boolean;\n /** Per-bundle results in discovery order. */\n results: PolicyLintResult[];\n}\n","import 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 {\n runCapturedProcess,\n type CapturedProcessRunner,\n} from '../../../lib/cli/run-captured-process.js';\nimport {\n type PolicyLintDiagnostic,\n type PolicyLintMultiResult,\n type PolicyLintResult,\n type PolicyLintStep,\n POLICY_LINT_MULTI_RESULT_VERSION,\n POLICY_LINT_RESULT_VERSION,\n POLICY_LINT_STEP_LABELS,\n POLICY_LINT_STEP_NAMES,\n} from '../../../lib/policy/policy-lint-model.js';\nimport {\n DEFAULT_POLICY_PROJECT_DIRECTORY,\n discoverPolicyBundleDirectories,\n resolvePolicyProjectDirectory,\n} from '../../../lib/policy/policy-project-discovery.js';\nimport { probePolicyToolVersions } from '../helpers/probePolicyToolVersions.js';\nimport { runOpaFormatStep } from '../helpers/runOpaFormatStep.js';\nimport { runRegalLintStep } from '../helpers/runRegalLintStep.js';\n\n/** CLI flags for `transcend policy lint`. */\nexport interface LintCommandFlags {\n /** Apply OPA formatting. */\n fix: boolean;\n /** Disable the optional formatting confirmation. */\n noInteractive: boolean;\n /** Emit one stable JSON result on stdout. */\n json: boolean;\n}\n\n/**\n * Render the terminal summary for a policy lint result.\n *\n * @param context - CLI context\n * @param result - Completed lint result\n * @param heading - Optional section heading when linting multiple bundles\n */\nfunction renderResult(context: LocalContext, result: PolicyLintResult, heading?: string): void {\n if (heading) {\n context.logger.info(`${colors.bold(heading)}\\n`);\n } else {\n context.logger.info(`${colors.bold('Policy lint')}\\n`);\n }\n result.checks.forEach(({ name, status }) => {\n const label = status === 'passed' ? 'PASS' : status === 'failed' ? 'FAIL' : 'SKIP';\n const styledLabel =\n status === 'passed'\n ? colors.green(label)\n : status === 'failed'\n ? colors.red(label)\n : colors.yellow(label);\n const version =\n name === 'opa-version' && result.tools.opa\n ? ` (${result.tools.opa})`\n : name === 'regal-version' && result.tools.regal\n ? ` (${result.tools.regal})`\n : '';\n context.logger.info(`${styledLabel} ${POLICY_LINT_STEP_LABELS[name]}${version}`);\n });\n if (result.diagnostics.length > 0) {\n context.logger.error('');\n }\n result.diagnostics.forEach((diagnostic) => {\n const location = diagnostic.path ? `${diagnostic.path}: ` : '';\n context.logger.error(\n colors.red(`error [${diagnostic.code}]: ${location}${diagnostic.message}`),\n );\n });\n if (result.status === 'passed') {\n context.logger.info('');\n context.logger.info(colors.green('Policy lint passed.'));\n } else {\n context.logger.error('');\n context.logger.error(colors.red('Policy lint failed.'));\n }\n}\n\n/**\n * Lint one publishable policy bundle directory (format + Regal).\n *\n * @param this - CLI context\n * @param flags - Command flags\n * @param resolvedDir - Absolute bundle directory\n * @param runner - Captured subprocess runner\n * @returns Completed lint result\n */\nasync function lintBundle(\n this: LocalContext,\n { fix, noInteractive, json }: LintCommandFlags,\n resolvedDir: string,\n runner: CapturedProcessRunner,\n): Promise<PolicyLintResult> {\n const checks: PolicyLintStep[] = POLICY_LINT_STEP_NAMES.map((name) => ({\n name,\n status: 'skipped',\n }));\n const diagnostics: PolicyLintDiagnostic[] = [];\n const result: PolicyLintResult = {\n version: POLICY_LINT_RESULT_VERSION,\n status: 'passed',\n directory: resolvedDir,\n fix,\n tools: { opa: null, regal: null },\n checks,\n unformattedFiles: [],\n fixedFiles: [],\n diagnostics,\n };\n const setStatus = (name: PolicyLintStep['name'], status: PolicyLintStep['status']): void => {\n checks.find((check) => check.name === name)!.status = status;\n };\n const addError = (code: string, message: string, diagnosticPath?: string): void => {\n diagnostics.push({\n code,\n severity: 'error',\n message,\n ...(diagnosticPath ? { path: diagnosticPath } : {}),\n });\n };\n\n if (!this.fs.existsSync(resolvedDir) || !this.fs.statSync(resolvedDir).isDirectory()) {\n setStatus('opa-version', 'failed');\n addError(\n 'project.directory',\n `Policy directory does not exist or is not a directory: ${resolvedDir}`,\n path.relative(this.process.cwd(), resolvedDir),\n );\n result.status = 'failed';\n return result;\n }\n\n const toolVersions = await probePolicyToolVersions.call(this, resolvedDir, runner);\n result.tools = { opa: toolVersions.opa, regal: toolVersions.regal };\n setStatus('opa-version', toolVersions.opaStatus);\n setStatus('regal-version', toolVersions.regalStatus);\n toolVersions.diagnostics.forEach((diagnostic) => {\n addError(diagnostic.code, diagnostic.message);\n });\n\n if (result.tools.opa) {\n const formatStep = await runOpaFormatStep.call(this, {\n resolvedDir,\n fix,\n noInteractive,\n json,\n fixCommandHint: 'transcend policy lint --fix',\n runner,\n });\n result.unformattedFiles = formatStep.unformattedFiles;\n result.fixedFiles = formatStep.fixedFiles;\n setStatus('format', formatStep.status);\n formatStep.diagnostics.forEach((diagnostic) => {\n addError(diagnostic.code, diagnostic.message);\n });\n }\n\n if (result.tools.regal) {\n const regalStep = await runRegalLintStep.call(this, { resolvedDir, runner });\n setStatus('regal-lint', regalStep.status);\n regalStep.diagnostics.forEach((diagnostic) => {\n addError(diagnostic.code, diagnostic.message);\n });\n }\n\n result.status = checks.some(({ status }) => status === 'failed') ? 'failed' : 'passed';\n return result;\n}\n\n/**\n * Lint local policy bundles with OPA formatting and Regal.\n *\n * With no directory (or the default workspace path), discovers every immediate\n * child that contains a `.manifest` and lints each. Pass one bundle path to\n * lint a single publishable unit.\n *\n * @param this - CLI context\n * @param flags - Command flags\n * @param directory - Policy workspace or bundle directory\n * @param runner - Captured subprocess runner\n */\nexport async function lint(\n this: LocalContext,\n flags: LintCommandFlags,\n directory: string = DEFAULT_POLICY_PROJECT_DIRECTORY,\n runner: CapturedProcessRunner = runCapturedProcess,\n): Promise<void> {\n doneInputValidation(this.process);\n\n const { fix = false, noInteractive = false, json = false } = flags;\n const resolvedDir = resolvePolicyProjectDirectory(this.process.cwd(), directory);\n\n if (!this.fs.existsSync(resolvedDir) || !this.fs.statSync(resolvedDir).isDirectory()) {\n const missing: PolicyLintResult = {\n version: POLICY_LINT_RESULT_VERSION,\n status: 'failed',\n directory: resolvedDir,\n fix,\n tools: { opa: null, regal: null },\n checks: POLICY_LINT_STEP_NAMES.map((name) => ({\n name,\n status: name === 'opa-version' ? 'failed' : 'skipped',\n })),\n unformattedFiles: [],\n fixedFiles: [],\n diagnostics: [\n {\n code: 'project.directory',\n severity: 'error',\n message: `Policy directory does not exist or is not a directory: ${resolvedDir}`,\n path: path.relative(this.process.cwd(), resolvedDir),\n },\n ],\n };\n if (json) {\n this.process.stdout.write(`${JSON.stringify(missing)}\\n`);\n } else {\n renderResult(this, missing);\n }\n this.process.exitCode = 1;\n return;\n }\n\n const bundleDirectories = discoverPolicyBundleDirectories(this, resolvedDir);\n if (bundleDirectories.length === 0) {\n const empty: PolicyLintResult = {\n version: POLICY_LINT_RESULT_VERSION,\n status: 'failed',\n directory: resolvedDir,\n fix,\n tools: { opa: null, regal: null },\n checks: POLICY_LINT_STEP_NAMES.map((name) => ({\n name,\n status: name === 'opa-version' ? 'failed' : 'skipped',\n })),\n unformattedFiles: [],\n fixedFiles: [],\n diagnostics: [\n {\n code: 'project.bundles',\n severity: 'error',\n message:\n 'No publishable policy bundles found. Add one with `transcend policy new`, ' +\n 'or pass a directory that contains a `.manifest`.',\n path: path.relative(this.process.cwd(), resolvedDir) || '.',\n },\n ],\n };\n if (json) {\n this.process.stdout.write(`${JSON.stringify(empty)}\\n`);\n } else {\n renderResult(this, empty);\n }\n this.process.exitCode = 1;\n return;\n }\n\n const results: PolicyLintResult[] = [];\n for (const bundleDirectory of bundleDirectories) {\n results.push(\n await lintBundle.call(this, { fix, noInteractive, json }, bundleDirectory, runner),\n );\n }\n\n const failed = results.some((result) => result.status === 'failed');\n if (json) {\n if (results.length === 1) {\n this.process.stdout.write(`${JSON.stringify(results[0])}\\n`);\n } else {\n const multi: PolicyLintMultiResult = {\n version: POLICY_LINT_MULTI_RESULT_VERSION,\n status: failed ? 'failed' : 'passed',\n directory: resolvedDir,\n fix,\n results,\n };\n this.process.stdout.write(`${JSON.stringify(multi)}\\n`);\n }\n } else if (results.length === 1) {\n renderResult(this, results[0]!);\n } else {\n results.forEach((result, index) => {\n if (index > 0) {\n this.logger.info('');\n }\n const relative = path.relative(this.process.cwd(), result.directory) || result.directory;\n renderResult(this, result, `Policy lint — ${relative}`);\n });\n }\n\n if (failed) {\n this.process.exitCode = 1;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"impl-C4CrzZFK2.mjs","names":[],"sources":["../src/lib/policy/policy-lint-model.ts","../src/commands/policy/lint/impl.ts"],"sourcesContent":["/** Stable policy lint result schema version. */\nexport const POLICY_LINT_RESULT_VERSION = 1;\n\n/** Stable multi-bundle lint result schema version. */\nexport const POLICY_LINT_MULTI_RESULT_VERSION = 1;\n\n/** Status of the lint gate or an individual step. */\nexport type PolicyLintStatus = 'passed' | 'failed' | 'skipped';\n\n/** One named policy lint step. */\nexport interface PolicyLintStep {\n /** Stable step name. */\n name: 'opa-version' | 'regal-version' | 'format' | 'regal-lint';\n /** Step outcome. */\n status: PolicyLintStatus;\n}\n\n/** Stable lint step execution order. */\nexport const POLICY_LINT_STEP_NAMES: PolicyLintStep['name'][] = [\n 'opa-version',\n 'regal-version',\n 'format',\n 'regal-lint',\n];\n\n/** User-facing lint step labels. */\nexport const POLICY_LINT_STEP_LABELS: Readonly<Record<PolicyLintStep['name'], string>> = {\n 'opa-version': 'OPA 1.x',\n 'regal-version': 'Regal',\n format: 'OPA formatting',\n 'regal-lint': 'Regal lint',\n};\n\n/** One machine-readable policy lint diagnostic. */\nexport interface PolicyLintDiagnostic {\n /** Stable diagnostic identifier. */\n code: string;\n /** Diagnostic severity. */\n severity: 'error';\n /** Human-readable detail, including captured tool output when available. */\n message: string;\n /** Optional path relative to the invocation directory. */\n path?: string;\n}\n\n/** Detected local policy tool versions. */\nexport interface PolicyLintTools {\n /** Detected OPA version, or null when missing or unsupported. */\n opa: string | null;\n /** Detected Regal version, or null when missing or unsupported. */\n regal: string | null;\n}\n\n/** Stable result emitted by `transcend policy lint --json` for one bundle. */\nexport interface PolicyLintResult {\n /** Result schema version. */\n version: typeof POLICY_LINT_RESULT_VERSION;\n /** Overall lint outcome. */\n status: Exclude<PolicyLintStatus, 'skipped'>;\n /** Absolute policy bundle directory. */\n directory: string;\n /** Whether formatting repair was explicitly requested. */\n fix: boolean;\n /** Detected supported tool versions. */\n tools: PolicyLintTools;\n /** Lint step outcomes in stable execution order. */\n checks: PolicyLintStep[];\n /** Files found to need OPA formatting, relative to the policy directory. */\n unformattedFiles: string[];\n /** Files repaired with OPA formatting, relative to the policy directory. */\n fixedFiles: string[];\n /** Ordered lint diagnostics. */\n diagnostics: PolicyLintDiagnostic[];\n}\n\n/**\n * Stable result when `transcend policy lint --json` lints multiple bundles.\n *\n * Emitted only when the selected path is a workspace with more than one\n * publishable `*-bundle/` directory.\n */\nexport interface PolicyLintMultiResult {\n /** Result schema version. */\n version: typeof POLICY_LINT_MULTI_RESULT_VERSION;\n /** Overall lint outcome across all bundles. */\n status: Exclude<PolicyLintStatus, 'skipped'>;\n /** Absolute policy workspace directory that was searched. */\n directory: string;\n /** Whether formatting repair was explicitly requested. */\n fix: boolean;\n /** Per-bundle results in discovery order. */\n results: PolicyLintResult[];\n}\n","import 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 {\n runCapturedProcess,\n type CapturedProcessRunner,\n} from '../../../lib/cli/run-captured-process.js';\nimport {\n type PolicyLintDiagnostic,\n type PolicyLintMultiResult,\n type PolicyLintResult,\n type PolicyLintStep,\n POLICY_LINT_MULTI_RESULT_VERSION,\n POLICY_LINT_RESULT_VERSION,\n POLICY_LINT_STEP_LABELS,\n POLICY_LINT_STEP_NAMES,\n} from '../../../lib/policy/policy-lint-model.js';\nimport {\n DEFAULT_POLICY_PROJECT_DIRECTORY,\n discoverPolicyBundleDirectories,\n resolvePolicyProjectDirectory,\n} from '../../../lib/policy/policy-project-discovery.js';\nimport { probePolicyToolVersions } from '../helpers/probePolicyToolVersions.js';\nimport { runOpaFormatStep } from '../helpers/runOpaFormatStep.js';\nimport { runRegalLintStep } from '../helpers/runRegalLintStep.js';\n\n/** CLI flags for `transcend policy lint`. */\nexport interface LintCommandFlags {\n /** Apply OPA formatting. */\n fix: boolean;\n /** Disable the optional formatting confirmation. */\n noInteractive: boolean;\n /** Emit one stable JSON result on stdout. */\n json: boolean;\n}\n\n/**\n * Render the terminal summary for a policy lint result.\n *\n * @param context - CLI context\n * @param result - Completed lint result\n * @param heading - Optional section heading when linting multiple bundles\n */\nfunction renderResult(context: LocalContext, result: PolicyLintResult, heading?: string): void {\n if (heading) {\n context.logger.info(`${colors.bold(heading)}\\n`);\n } else {\n context.logger.info(`${colors.bold('Policy lint')}\\n`);\n }\n result.checks.forEach(({ name, status }) => {\n const label = status === 'passed' ? 'PASS' : status === 'failed' ? 'FAIL' : 'SKIP';\n const styledLabel =\n status === 'passed'\n ? colors.green(label)\n : status === 'failed'\n ? colors.red(label)\n : colors.yellow(label);\n const version =\n name === 'opa-version' && result.tools.opa\n ? ` (${result.tools.opa})`\n : name === 'regal-version' && result.tools.regal\n ? ` (${result.tools.regal})`\n : '';\n context.logger.info(`${styledLabel} ${POLICY_LINT_STEP_LABELS[name]}${version}`);\n });\n if (result.diagnostics.length > 0) {\n context.logger.error('');\n }\n result.diagnostics.forEach((diagnostic) => {\n const location = diagnostic.path ? `${diagnostic.path}: ` : '';\n context.logger.error(\n colors.red(`error [${diagnostic.code}]: ${location}${diagnostic.message}`),\n );\n });\n if (result.status === 'passed') {\n context.logger.info('');\n context.logger.info(colors.green('Policy lint passed.'));\n } else {\n context.logger.error('');\n context.logger.error(colors.red('Policy lint failed.'));\n }\n}\n\n/**\n * Lint one publishable policy bundle directory (format + Regal).\n *\n * @param this - CLI context\n * @param flags - Command flags\n * @param resolvedDir - Absolute bundle directory\n * @param runner - Captured subprocess runner\n * @returns Completed lint result\n */\nasync function lintBundle(\n this: LocalContext,\n { fix, noInteractive, json }: LintCommandFlags,\n resolvedDir: string,\n runner: CapturedProcessRunner,\n): Promise<PolicyLintResult> {\n const checks: PolicyLintStep[] = POLICY_LINT_STEP_NAMES.map((name) => ({\n name,\n status: 'skipped',\n }));\n const diagnostics: PolicyLintDiagnostic[] = [];\n const result: PolicyLintResult = {\n version: POLICY_LINT_RESULT_VERSION,\n status: 'passed',\n directory: resolvedDir,\n fix,\n tools: { opa: null, regal: null },\n checks,\n unformattedFiles: [],\n fixedFiles: [],\n diagnostics,\n };\n const setStatus = (name: PolicyLintStep['name'], status: PolicyLintStep['status']): void => {\n checks.find((check) => check.name === name)!.status = status;\n };\n const addError = (code: string, message: string, diagnosticPath?: string): void => {\n diagnostics.push({\n code,\n severity: 'error',\n message,\n ...(diagnosticPath ? { path: diagnosticPath } : {}),\n });\n };\n\n if (!this.fs.existsSync(resolvedDir) || !this.fs.statSync(resolvedDir).isDirectory()) {\n setStatus('opa-version', 'failed');\n addError(\n 'project.directory',\n `Policy directory does not exist or is not a directory: ${resolvedDir}`,\n path.relative(this.process.cwd(), resolvedDir),\n );\n result.status = 'failed';\n return result;\n }\n\n const toolVersions = await probePolicyToolVersions.call(this, resolvedDir, runner);\n result.tools = { opa: toolVersions.opa, regal: toolVersions.regal };\n setStatus('opa-version', toolVersions.opaStatus);\n setStatus('regal-version', toolVersions.regalStatus);\n toolVersions.diagnostics.forEach((diagnostic) => {\n addError(diagnostic.code, diagnostic.message);\n });\n\n if (result.tools.opa) {\n const formatStep = await runOpaFormatStep.call(this, {\n resolvedDir,\n fix,\n noInteractive,\n json,\n fixCommandHint: 'transcend policy lint --fix',\n runner,\n });\n result.unformattedFiles = formatStep.unformattedFiles;\n result.fixedFiles = formatStep.fixedFiles;\n setStatus('format', formatStep.status);\n formatStep.diagnostics.forEach((diagnostic) => {\n addError(diagnostic.code, diagnostic.message);\n });\n }\n\n if (result.tools.regal) {\n const regalStep = await runRegalLintStep.call(this, { resolvedDir, runner });\n setStatus('regal-lint', regalStep.status);\n regalStep.diagnostics.forEach((diagnostic) => {\n addError(diagnostic.code, diagnostic.message);\n });\n }\n\n result.status = checks.some(({ status }) => status === 'failed') ? 'failed' : 'passed';\n return result;\n}\n\n/**\n * Lint local policy bundles with OPA formatting and Regal.\n *\n * With no directory (or the default workspace path), discovers every immediate\n * child that contains a `.manifest` and lints each. Pass one bundle path to\n * lint a single publishable unit.\n *\n * @param this - CLI context\n * @param flags - Command flags\n * @param directory - Policy workspace or bundle directory\n * @param runner - Captured subprocess runner\n */\nexport async function lint(\n this: LocalContext,\n flags: LintCommandFlags,\n directory: string = DEFAULT_POLICY_PROJECT_DIRECTORY,\n runner: CapturedProcessRunner = runCapturedProcess,\n): Promise<void> {\n doneInputValidation(this.process);\n\n const { fix = false, noInteractive = false, json = false } = flags;\n const resolvedDir = resolvePolicyProjectDirectory(this.process.cwd(), directory);\n\n if (!this.fs.existsSync(resolvedDir) || !this.fs.statSync(resolvedDir).isDirectory()) {\n const missing: PolicyLintResult = {\n version: POLICY_LINT_RESULT_VERSION,\n status: 'failed',\n directory: resolvedDir,\n fix,\n tools: { opa: null, regal: null },\n checks: POLICY_LINT_STEP_NAMES.map((name) => ({\n name,\n status: name === 'opa-version' ? 'failed' : 'skipped',\n })),\n unformattedFiles: [],\n fixedFiles: [],\n diagnostics: [\n {\n code: 'project.directory',\n severity: 'error',\n message: `Policy directory does not exist or is not a directory: ${resolvedDir}`,\n path: path.relative(this.process.cwd(), resolvedDir),\n },\n ],\n };\n if (json) {\n this.process.stdout.write(`${JSON.stringify(missing)}\\n`);\n } else {\n renderResult(this, missing);\n }\n this.process.exitCode = 1;\n return;\n }\n\n const bundleDirectories = discoverPolicyBundleDirectories(this, resolvedDir);\n if (bundleDirectories.length === 0) {\n const empty: PolicyLintResult = {\n version: POLICY_LINT_RESULT_VERSION,\n status: 'failed',\n directory: resolvedDir,\n fix,\n tools: { opa: null, regal: null },\n checks: POLICY_LINT_STEP_NAMES.map((name) => ({\n name,\n status: name === 'opa-version' ? 'failed' : 'skipped',\n })),\n unformattedFiles: [],\n fixedFiles: [],\n diagnostics: [\n {\n code: 'project.bundles',\n severity: 'error',\n message:\n 'No publishable policy bundles found. Add one with `transcend policy new`, ' +\n 'or pass a directory that contains a `.manifest`.',\n path: path.relative(this.process.cwd(), resolvedDir) || '.',\n },\n ],\n };\n if (json) {\n this.process.stdout.write(`${JSON.stringify(empty)}\\n`);\n } else {\n renderResult(this, empty);\n }\n this.process.exitCode = 1;\n return;\n }\n\n const results: PolicyLintResult[] = [];\n for (const bundleDirectory of bundleDirectories) {\n results.push(\n await lintBundle.call(this, { fix, noInteractive, json }, bundleDirectory, runner),\n );\n }\n\n const failed = results.some((result) => result.status === 'failed');\n if (json) {\n if (results.length === 1) {\n this.process.stdout.write(`${JSON.stringify(results[0])}\\n`);\n } else {\n const multi: PolicyLintMultiResult = {\n version: POLICY_LINT_MULTI_RESULT_VERSION,\n status: failed ? 'failed' : 'passed',\n directory: resolvedDir,\n fix,\n results,\n };\n this.process.stdout.write(`${JSON.stringify(multi)}\\n`);\n }\n } else if (results.length === 1) {\n renderResult(this, results[0]!);\n } else {\n results.forEach((result, index) => {\n if (index > 0) {\n this.logger.info('');\n }\n const relative = path.relative(this.process.cwd(), result.directory) || result.directory;\n renderResult(this, result, `Policy lint — ${relative}`);\n });\n }\n\n if (failed) {\n this.process.exitCode = 1;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./streamPrivacyRequestsToCsv-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./streamPrivacyRequestsToCsv-BPL16Yrs.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";import n from"colors";async function r({auth:r,transcendUrl:i,file:a,pageLimit:o,concurrency:s,actions:c,sombraAuth:l,skipRequestIdentifiers:u,statuses:d,createdAtBefore:f,createdAtAfter:p,updatedAtBefore:m,updatedAtAfter:h,showTests:g}){t(this.process);let{filePaths:_,totalCount:v}=await e({transcendUrl:i,concurrency:s,pageLimit:o,actions:c,statuses:d,auth:r,sombraAuth:l,skipRequestIdentifiers:u,createdAtBefore:f,createdAtAfter:p,updatedAtBefore:m,updatedAtAfter:h,isTest:g,file:a});this.logger.info(n.green(`Successfully wrote ${v} requests to ${_.length} file(s): ${_.join(`, `)}`))}export{r as _export};
|
|
2
|
+
//# sourceMappingURL=impl-C5A6boYU.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-C5A6boYU.mjs","names":[],"sources":["../src/commands/request/export/impl.ts"],"sourcesContent":["import type { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { streamPrivacyRequestsToCsv } from '../../../lib/requests/index.js';\n\nexport interface ExportCommandFlags {\n auth: string;\n sombraAuth?: string;\n actions?: RequestAction[];\n statuses?: RequestStatus[];\n transcendUrl: string;\n file: string;\n concurrency: number;\n createdAtBefore?: Date;\n createdAtAfter?: Date;\n updatedAtBefore?: Date;\n updatedAtAfter?: Date;\n showTests?: boolean;\n skipRequestIdentifiers?: boolean;\n pageLimit: number;\n}\n\n// `export` is a reserved keyword, so we need to prefix it with an underscore\n// eslint-disable-next-line no-underscore-dangle\nexport async function _export(\n this: LocalContext,\n {\n auth,\n transcendUrl,\n file,\n pageLimit,\n concurrency,\n actions,\n sombraAuth,\n skipRequestIdentifiers,\n statuses,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n showTests,\n }: ExportCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n const { filePaths, totalCount } = await streamPrivacyRequestsToCsv({\n transcendUrl,\n concurrency,\n pageLimit,\n actions,\n statuses,\n auth,\n sombraAuth,\n skipRequestIdentifiers,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n isTest: showTests,\n file,\n });\n\n this.logger.info(\n colors.green(\n `Successfully wrote ${totalCount} requests to ` +\n `${filePaths.length} file(s): ${filePaths.join(', ')}`,\n ),\n );\n}\n"],"mappings":"wIA0BA,eAAsB,EAEpB,CACE,OACA,eACA,OACA,YACA,cACA,UACA,aACA,yBACA,WACA,kBACA,iBACA,kBACA,iBACA,aAEa,CACf,EAAoB,KAAK,QAAQ,CAEjC,GAAM,CAAE,YAAW,cAAe,MAAM,EAA2B,CACjE,eACA,cACA,YACA,UACA,WACA,OACA,aACA,yBACA,kBACA,iBACA,kBACA,iBACA,OAAQ,EACR,OACD,CAAC,CAEF,KAAK,OAAO,KACV,EAAO,MACL,sBAAsB,EAAW,eAC5B,EAAU,OAAO,YAAY,EAAU,KAAK,KAAK,GACvD,CACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./bulkRetryEnrichers-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./bulkRetryEnrichers-C6EC7hDi.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";async function n({auth:n,enricherId:r,actions:i,requestEnricherStatuses:a,requestIds:o,createdAtBefore:s,createdAtAfter:c,updatedAtBefore:l,updatedAtAfter:u,concurrency:d,transcendUrl:f}){t(this.process),await e({auth:n,enricherId:r,requestActions:i,requestEnricherStatuses:a,requestIds:o,createdAtBefore:s?new Date(s):void 0,createdAtAfter:c?new Date(c):void 0,updatedAtBefore:l?new Date(l):void 0,updatedAtAfter:u?new Date(u):void 0,concurrency:d,transcendUrl:f})}export{n as enricherRestart};
|
|
2
|
+
//# sourceMappingURL=impl-C5o7iqlK.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-C5o7iqlK.mjs","names":[],"sources":["../src/commands/request/enricher-restart/impl.ts"],"sourcesContent":["import type { RequestAction, RequestEnricherStatus } from '@transcend-io/privacy-types';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { bulkRetryEnrichers } from '../../../lib/requests/index.js';\n\nexport interface EnricherRestartCommandFlags {\n auth: string;\n enricherId: string;\n actions?: RequestAction[];\n requestEnricherStatuses?: RequestEnricherStatus[];\n transcendUrl: string;\n concurrency: number;\n requestIds?: string[];\n createdAtBefore?: Date;\n createdAtAfter?: Date;\n updatedAtBefore?: Date;\n updatedAtAfter?: Date;\n}\n\nexport async function enricherRestart(\n this: LocalContext,\n {\n auth,\n enricherId,\n actions,\n requestEnricherStatuses,\n requestIds,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n concurrency,\n transcendUrl,\n }: EnricherRestartCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n await bulkRetryEnrichers({\n auth,\n enricherId,\n requestActions: actions,\n requestEnricherStatuses,\n requestIds,\n createdAtBefore: createdAtBefore ? new Date(createdAtBefore) : undefined,\n createdAtAfter: createdAtAfter ? new Date(createdAtAfter) : undefined,\n updatedAtBefore: updatedAtBefore ? new Date(updatedAtBefore) : undefined,\n updatedAtAfter: updatedAtAfter ? new Date(updatedAtAfter) : undefined,\n concurrency,\n transcendUrl,\n });\n}\n"],"mappings":"0GAoBA,eAAsB,EAEpB,CACE,OACA,aACA,UACA,0BACA,aACA,kBACA,iBACA,kBACA,iBACA,cACA,gBAEa,CACf,EAAoB,KAAK,QAAQ,CAEjC,MAAM,EAAmB,CACvB,OACA,aACA,eAAgB,EAChB,0BACA,aACA,gBAAiB,EAAkB,IAAI,KAAK,EAAgB,CAAG,IAAA,GAC/D,eAAgB,EAAiB,IAAI,KAAK,EAAe,CAAG,IAAA,GAC5D,gBAAiB,EAAkB,IAAI,KAAK,EAAgB,CAAG,IAAA,GAC/D,eAAgB,EAAiB,IAAI,KAAK,EAAe,CAAG,IAAA,GAC5D,cACA,eACD,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./downloadPrivacyRequestFiles-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./downloadPrivacyRequestFiles-CgVZOWgS.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";import{RequestStatus as n}from"@transcend-io/privacy-types";async function r({auth:r,transcendUrl:i,folderPath:a,requestIds:o,statuses:s=[n.Approving,n.Downloadable],concurrency:c,createdAtBefore:l,createdAtAfter:u,updatedAtBefore:d,updatedAtAfter:f,approveAfterDownload:p}){t(this.process),await e({transcendUrl:i,auth:r,folderPath:a,requestIds:o,statuses:s,concurrency:c,createdAtBefore:l,createdAtAfter:u,updatedAtBefore:d,updatedAtAfter:f,approveAfterDownload:p})}export{r as downloadFiles};
|
|
2
|
+
//# sourceMappingURL=impl-C8oTRXHj.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-C8oTRXHj.mjs","names":[],"sources":["../src/commands/request/download-files/impl.ts"],"sourcesContent":["import { RequestStatus } from '@transcend-io/privacy-types';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { downloadPrivacyRequestFiles } from '../../../lib/requests/index.js';\n\nexport interface DownloadFilesCommandFlags {\n auth: string;\n sombraAuth?: string;\n concurrency: number;\n requestIds?: string[];\n statuses?: RequestStatus[];\n folderPath: string;\n createdAtBefore?: Date;\n createdAtAfter?: Date;\n updatedAtBefore?: Date;\n updatedAtAfter?: Date;\n approveAfterDownload: boolean;\n transcendUrl: string;\n}\n\nexport async function downloadFiles(\n this: LocalContext,\n {\n auth,\n transcendUrl,\n folderPath,\n requestIds,\n statuses = [RequestStatus.Approving, RequestStatus.Downloadable],\n concurrency,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n approveAfterDownload,\n }: DownloadFilesCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n await downloadPrivacyRequestFiles({\n transcendUrl,\n auth,\n folderPath,\n requestIds,\n statuses,\n concurrency,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n approveAfterDownload,\n });\n}\n"],"mappings":"+KAqBA,eAAsB,EAEpB,CACE,OACA,eACA,aACA,aACA,WAAW,CAAC,EAAc,UAAW,EAAc,aAAa,CAChE,cACA,kBACA,iBACA,kBACA,iBACA,wBAEa,CACf,EAAoB,KAAK,QAAQ,CAEjC,MAAM,EAA4B,CAChC,eACA,OACA,aACA,aACA,WACA,cACA,kBACA,iBACA,kBACA,iBACA,uBACD,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./cancelPrivacyRequests-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./cancelPrivacyRequests-RYf84Ife.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";async function n({auth:n,actions:r,statuses:i=[],requestIds:a,silentModeBefore:o,createdAtBefore:s,createdAtAfter:c,updatedAtBefore:l,updatedAtAfter:u,cancellationTitle:d,transcendUrl:f,concurrency:p}){t(this.process),await e({transcendUrl:f,requestActions:r,auth:n,cancellationTitle:d,requestIds:a,statuses:i,concurrency:p,silentModeBefore:o?new Date(o):void 0,createdAtBefore:s?new Date(s):void 0,createdAtAfter:c?new Date(c):void 0,updatedAtBefore:l?new Date(l):void 0,updatedAtAfter:u?new Date(u):void 0})}export{n as cancel};
|
|
2
|
+
//# sourceMappingURL=impl-CB1QyjSs.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-CB1QyjSs.mjs","names":[],"sources":["../src/commands/request/cancel/impl.ts"],"sourcesContent":["import { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { cancelPrivacyRequests } from '../../../lib/requests/index.js';\n\nexport interface CancelCommandFlags {\n auth: string;\n actions: RequestAction[];\n statuses?: RequestStatus[];\n requestIds?: string[];\n silentModeBefore?: Date;\n createdAtBefore?: Date;\n createdAtAfter?: Date;\n updatedAtBefore?: Date;\n updatedAtAfter?: Date;\n cancellationTitle: string;\n transcendUrl: string;\n concurrency: number;\n}\n\nexport async function cancel(\n this: LocalContext,\n {\n auth,\n actions,\n statuses = [],\n requestIds,\n silentModeBefore,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n cancellationTitle,\n transcendUrl,\n concurrency,\n }: CancelCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n await cancelPrivacyRequests({\n transcendUrl,\n requestActions: actions,\n auth,\n cancellationTitle,\n requestIds,\n statuses,\n concurrency,\n silentModeBefore: silentModeBefore ? new Date(silentModeBefore) : undefined,\n createdAtBefore: createdAtBefore ? new Date(createdAtBefore) : undefined,\n createdAtAfter: createdAtAfter ? new Date(createdAtAfter) : undefined,\n updatedAtBefore: updatedAtBefore ? new Date(updatedAtBefore) : undefined,\n updatedAtAfter: updatedAtAfter ? new Date(updatedAtAfter) : undefined,\n });\n}\n"],"mappings":"6GAqBA,eAAsB,EAEpB,CACE,OACA,UACA,WAAW,EAAE,CACb,aACA,mBACA,kBACA,iBACA,kBACA,iBACA,oBACA,eACA,eAEa,CACf,EAAoB,KAAK,QAAQ,CAEjC,MAAM,EAAsB,CAC1B,eACA,eAAgB,EAChB,OACA,oBACA,aACA,WACA,cACA,iBAAkB,EAAmB,IAAI,KAAK,EAAiB,CAAG,IAAA,GAClE,gBAAiB,EAAkB,IAAI,KAAK,EAAgB,CAAG,IAAA,GAC/D,eAAgB,EAAiB,IAAI,KAAK,EAAe,CAAG,IAAA,GAC5D,gBAAiB,EAAkB,IAAI,KAAK,EAAgB,CAAG,IAAA,GAC/D,eAAgB,EAAiB,IAAI,KAAK,EAAe,CAAG,IAAA,GAC7D,CAAC"}
|