@transcend-io/cli 12.1.3 → 12.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/dist/{app-DjiX1gVH.mjs → app-BMLQABJX.mjs} +16 -16
  2. package/dist/{app-DjiX1gVH.mjs.map → app-BMLQABJX.mjs.map} +1 -1
  3. package/dist/{approvePrivacyRequests-lxkQc3j9.mjs → approvePrivacyRequests-CY6rQT4J.mjs} +2 -2
  4. package/dist/{approvePrivacyRequests-lxkQc3j9.mjs.map → approvePrivacyRequests-CY6rQT4J.mjs.map} +1 -1
  5. package/dist/bin/bash-complete.mjs +1 -1
  6. package/dist/bin/cli.mjs +1 -1
  7. package/dist/bin/deprecated-command.mjs +1 -1
  8. package/dist/{buildExamples-BPpsiPem.mjs → buildExamples-BNGtj-DW.mjs} +2 -2
  9. package/dist/{buildExamples-BPpsiPem.mjs.map → buildExamples-BNGtj-DW.mjs.map} +1 -1
  10. package/dist/{buildXdiSyncEndpoint-HKlaBsCz.mjs → buildXdiSyncEndpoint-BNCfOc-g.mjs} +2 -2
  11. package/dist/{buildXdiSyncEndpoint-HKlaBsCz.mjs.map → buildXdiSyncEndpoint-BNCfOc-g.mjs.map} +1 -1
  12. package/dist/{bulkRestartRequests-BI1lqrPC.mjs → bulkRestartRequests-CGvODu3r.mjs} +2 -2
  13. package/dist/{bulkRestartRequests-BI1lqrPC.mjs.map → bulkRestartRequests-CGvODu3r.mjs.map} +1 -1
  14. package/dist/{bulkRetryEnrichers-i64LOhXy.mjs → bulkRetryEnrichers-BgDd4GWH.mjs} +2 -2
  15. package/dist/{bulkRetryEnrichers-i64LOhXy.mjs.map → bulkRetryEnrichers-BgDd4GWH.mjs.map} +1 -1
  16. package/dist/{cancelPrivacyRequests-BzRQOYrf.mjs → cancelPrivacyRequests-Ccsiwrnu.mjs} +2 -2
  17. package/dist/{cancelPrivacyRequests-BzRQOYrf.mjs.map → cancelPrivacyRequests-Ccsiwrnu.mjs.map} +1 -1
  18. package/dist/{command-D9Sydip3.mjs → command-BjzdoKgJ.mjs} +2 -2
  19. package/dist/{command-D9Sydip3.mjs.map → command-BjzdoKgJ.mjs.map} +1 -1
  20. package/dist/{constants-rXUIz6Uy.mjs → constants-FDjw7bPS.mjs} +2 -2
  21. package/dist/{constants-rXUIz6Uy.mjs.map → constants-FDjw7bPS.mjs.map} +1 -1
  22. package/dist/{createPoolingCommandUi-BsU6e0Ov.mjs → createPoolingCommandUi-BdtnLBBM.mjs} +2 -2
  23. package/dist/{createPoolingCommandUi-BsU6e0Ov.mjs.map → createPoolingCommandUi-BdtnLBBM.mjs.map} +1 -1
  24. package/dist/{downloadPrivacyRequestFiles-B3Yv7zHE.mjs → downloadPrivacyRequestFiles-C9-xSCpt.mjs} +2 -2
  25. package/dist/{downloadPrivacyRequestFiles-B3Yv7zHE.mjs.map → downloadPrivacyRequestFiles-C9-xSCpt.mjs.map} +1 -1
  26. package/dist/{generateCrossAccountApiKeys-DWDNh4dG.mjs → generateCrossAccountApiKeys-FtWwlf_L.mjs} +2 -2
  27. package/dist/{generateCrossAccountApiKeys-DWDNh4dG.mjs.map → generateCrossAccountApiKeys-FtWwlf_L.mjs.map} +1 -1
  28. package/dist/{impl-DP9iMlRn.mjs → impl-Ar7VAh0Z.mjs} +2 -2
  29. package/dist/{impl-DP9iMlRn.mjs.map → impl-Ar7VAh0Z.mjs.map} +1 -1
  30. package/dist/{impl-uWnEYxoC.mjs → impl-BCKUj-ko.mjs} +2 -2
  31. package/dist/{impl-uWnEYxoC.mjs.map → impl-BCKUj-ko.mjs.map} +1 -1
  32. package/dist/{impl-CwBa15M42.mjs → impl-BEiCEzl_2.mjs} +2 -2
  33. package/dist/{impl-CwBa15M42.mjs.map → impl-BEiCEzl_2.mjs.map} +1 -1
  34. package/dist/{impl-BGgaogQG.mjs → impl-BLtOfbtk.mjs} +2 -2
  35. package/dist/{impl-BGgaogQG.mjs.map → impl-BLtOfbtk.mjs.map} +1 -1
  36. package/dist/{impl-KukgjmYS.mjs → impl-BXGpJz21.mjs} +2 -2
  37. package/dist/{impl-KukgjmYS.mjs.map → impl-BXGpJz21.mjs.map} +1 -1
  38. package/dist/{impl-DlPwOUAc.mjs → impl-B_N_fOq0.mjs} +2 -2
  39. package/dist/{impl-DlPwOUAc.mjs.map → impl-B_N_fOq0.mjs.map} +1 -1
  40. package/dist/{impl-BxJ3LBq5.mjs → impl-Bs2pNgMK.mjs} +2 -2
  41. package/dist/{impl-BxJ3LBq5.mjs.map → impl-Bs2pNgMK.mjs.map} +1 -1
  42. package/dist/{impl-C1UEaEKN.mjs → impl-BvwRiPSG.mjs} +2 -2
  43. package/dist/{impl-C1UEaEKN.mjs.map → impl-BvwRiPSG.mjs.map} +1 -1
  44. package/dist/{impl-CdFl00EX.mjs → impl-Bz1wZxa-.mjs} +2 -2
  45. package/dist/{impl-CdFl00EX.mjs.map → impl-Bz1wZxa-.mjs.map} +1 -1
  46. package/dist/{impl-DH_tLaGZ.mjs → impl-C3vTm9zQ.mjs} +2 -2
  47. package/dist/{impl-DH_tLaGZ.mjs.map → impl-C3vTm9zQ.mjs.map} +1 -1
  48. package/dist/{impl-Cr_GtYDt.mjs → impl-COqlYiiw.mjs} +2 -2
  49. package/dist/{impl-Cr_GtYDt.mjs.map → impl-COqlYiiw.mjs.map} +1 -1
  50. package/dist/{impl-CYJgNSKH.mjs → impl-CSnBFv5P.mjs} +2 -2
  51. package/dist/{impl-CYJgNSKH.mjs.map → impl-CSnBFv5P.mjs.map} +1 -1
  52. package/dist/{impl-CHY55Vge.mjs → impl-CTOgxZFi.mjs} +2 -2
  53. package/dist/{impl-CHY55Vge.mjs.map → impl-CTOgxZFi.mjs.map} +1 -1
  54. package/dist/{impl-DKhqM6hZ2.mjs → impl-Cb-7C1Ml2.mjs} +2 -2
  55. package/dist/{impl-DKhqM6hZ2.mjs.map → impl-Cb-7C1Ml2.mjs.map} +1 -1
  56. package/dist/{impl-BTXUJwyb.mjs → impl-ChQAmyBN.mjs} +2 -2
  57. package/dist/{impl-BTXUJwyb.mjs.map → impl-ChQAmyBN.mjs.map} +1 -1
  58. package/dist/{impl-DD-ICQ8E.mjs → impl-ClT3G845.mjs} +2 -2
  59. package/dist/{impl-DD-ICQ8E.mjs.map → impl-ClT3G845.mjs.map} +1 -1
  60. package/dist/{impl-BtHRf6Jp.mjs → impl-Cp5o0Q2g.mjs} +2 -2
  61. package/dist/{impl-BtHRf6Jp.mjs.map → impl-Cp5o0Q2g.mjs.map} +1 -1
  62. package/dist/{impl-CcYyiqaB.mjs → impl-D58JUOdA.mjs} +2 -2
  63. package/dist/{impl-CcYyiqaB.mjs.map → impl-D58JUOdA.mjs.map} +1 -1
  64. package/dist/{impl-fsBuXKVJ.mjs → impl-D6frX-PK.mjs} +2 -2
  65. package/dist/{impl-fsBuXKVJ.mjs.map → impl-D6frX-PK.mjs.map} +1 -1
  66. package/dist/{impl-Sx15m6eC2.mjs → impl-D6rMLiNB2.mjs} +2 -2
  67. package/dist/{impl-Sx15m6eC2.mjs.map → impl-D6rMLiNB2.mjs.map} +1 -1
  68. package/dist/{impl-CbZIfTUK.mjs → impl-DDVhG8Gf.mjs} +2 -2
  69. package/dist/{impl-CbZIfTUK.mjs.map → impl-DDVhG8Gf.mjs.map} +1 -1
  70. package/dist/{impl-Y4CI9YNK.mjs → impl-DFnWzZyY.mjs} +2 -2
  71. package/dist/{impl-Y4CI9YNK.mjs.map → impl-DFnWzZyY.mjs.map} +1 -1
  72. package/dist/{impl-hDN-9GZo.mjs → impl-DGtCNANL.mjs} +2 -2
  73. package/dist/{impl-hDN-9GZo.mjs.map → impl-DGtCNANL.mjs.map} +1 -1
  74. package/dist/{impl-CNU3pgwh.mjs → impl-DNOgBcsu.mjs} +2 -2
  75. package/dist/{impl-CNU3pgwh.mjs.map → impl-DNOgBcsu.mjs.map} +1 -1
  76. package/dist/{impl-C36c5NfN.mjs → impl-DUYRVzMo.mjs} +2 -2
  77. package/dist/{impl-C36c5NfN.mjs.map → impl-DUYRVzMo.mjs.map} +1 -1
  78. package/dist/{impl-CNURWgF12.mjs → impl-DZoTWLfw2.mjs} +2 -2
  79. package/dist/{impl-CNURWgF12.mjs.map → impl-DZoTWLfw2.mjs.map} +1 -1
  80. package/dist/{impl-BU_vn9I6.mjs → impl-Dd39KsYO.mjs} +2 -2
  81. package/dist/{impl-BU_vn9I6.mjs.map → impl-Dd39KsYO.mjs.map} +1 -1
  82. package/dist/{impl-DbqbZmAc.mjs → impl-DnDM9zcu.mjs} +2 -2
  83. package/dist/{impl-DbqbZmAc.mjs.map → impl-DnDM9zcu.mjs.map} +1 -1
  84. package/dist/{impl-BlsxbyrR.mjs → impl-EDwngLc7.mjs} +2 -2
  85. package/dist/{impl-BlsxbyrR.mjs.map → impl-EDwngLc7.mjs.map} +1 -1
  86. package/dist/{impl-CAukIeJv.mjs → impl-Hj5CgbWd.mjs} +2 -2
  87. package/dist/{impl-CAukIeJv.mjs.map → impl-Hj5CgbWd.mjs.map} +1 -1
  88. package/dist/{impl-CIHHFnIw.mjs → impl-QD3_9HTk.mjs} +2 -2
  89. package/dist/{impl-CIHHFnIw.mjs.map → impl-QD3_9HTk.mjs.map} +1 -1
  90. package/dist/{impl-C8RwWS6i.mjs → impl-SOebshza.mjs} +2 -2
  91. package/dist/{impl-C8RwWS6i.mjs.map → impl-SOebshza.mjs.map} +1 -1
  92. package/dist/{impl-mM7BgfxL.mjs → impl-VSo8bO-J.mjs} +2 -2
  93. package/dist/{impl-mM7BgfxL.mjs.map → impl-VSo8bO-J.mjs.map} +1 -1
  94. package/dist/{impl-DG-041kN.mjs → impl-VgI7mr67.mjs} +2 -2
  95. package/dist/{impl-DG-041kN.mjs.map → impl-VgI7mr67.mjs.map} +1 -1
  96. package/dist/{impl-Bnc9QUjN.mjs → impl-XxYQHKO5.mjs} +2 -2
  97. package/dist/{impl-Bnc9QUjN.mjs.map → impl-XxYQHKO5.mjs.map} +1 -1
  98. package/dist/{impl-Crkz6EBl.mjs → impl-bl6NF3Lr.mjs} +2 -2
  99. package/dist/{impl-Crkz6EBl.mjs.map → impl-bl6NF3Lr.mjs.map} +1 -1
  100. package/dist/{impl-DHhm_-pe.mjs → impl-ojAnhhbi.mjs} +2 -2
  101. package/dist/{impl-DHhm_-pe.mjs.map → impl-ojAnhhbi.mjs.map} +1 -1
  102. package/dist/{impl-defjX-97.mjs → impl-qNF5eqX-.mjs} +2 -2
  103. package/dist/{impl-defjX-97.mjs.map → impl-qNF5eqX-.mjs.map} +1 -1
  104. package/dist/{impl-Boj3WWax.mjs → impl-xVmMN-Vt.mjs} +2 -2
  105. package/dist/{impl-Boj3WWax.mjs.map → impl-xVmMN-Vt.mjs.map} +1 -1
  106. package/dist/{impl-CYpcKBww.mjs → impl-xY_5o78i.mjs} +2 -2
  107. package/dist/{impl-CYpcKBww.mjs.map → impl-xY_5o78i.mjs.map} +1 -1
  108. package/dist/{impl-DlrJX5Gl2.mjs → impl-yIVxAhCG2.mjs} +2 -2
  109. package/dist/{impl-DlrJX5Gl2.mjs.map → impl-yIVxAhCG2.mjs.map} +1 -1
  110. package/dist/{impl-B1za3AEd.mjs → impl-zZd6fuXS.mjs} +2 -2
  111. package/dist/{impl-B1za3AEd.mjs.map → impl-zZd6fuXS.mjs.map} +1 -1
  112. package/dist/index.mjs +1 -1
  113. package/dist/{markRequestDataSiloIdsCompleted-Bm61UHII.mjs → markRequestDataSiloIdsCompleted-JGJf33yp.mjs} +2 -2
  114. package/dist/{markRequestDataSiloIdsCompleted-Bm61UHII.mjs.map → markRequestDataSiloIdsCompleted-JGJf33yp.mjs.map} +1 -1
  115. package/dist/{markSilentPrivacyRequests-BtZHHUVJ.mjs → markSilentPrivacyRequests-BTI3rH-V.mjs} +2 -2
  116. package/dist/{markSilentPrivacyRequests-BtZHHUVJ.mjs.map → markSilentPrivacyRequests-BTI3rH-V.mjs.map} +1 -1
  117. package/dist/{notifyPrivacyRequestsAdditionalTime-DLW694xo.mjs → notifyPrivacyRequestsAdditionalTime-n5fvOJaA.mjs} +2 -2
  118. package/dist/{notifyPrivacyRequestsAdditionalTime-DLW694xo.mjs.map → notifyPrivacyRequestsAdditionalTime-n5fvOJaA.mjs.map} +1 -1
  119. package/dist/{policy-bundle-manifest-CDbVx8E6.mjs → policy-bundle-manifest-DbbTXe0u.mjs} +2 -2
  120. package/dist/{policy-bundle-manifest-CDbVx8E6.mjs.map → policy-bundle-manifest-DbbTXe0u.mjs.map} +1 -1
  121. package/dist/{policy-project-discovery-_6QosI9J.mjs → policy-project-discovery-DTSl0Gfl.mjs} +2 -2
  122. package/dist/{policy-project-discovery-_6QosI9J.mjs.map → policy-project-discovery-DTSl0Gfl.mjs.map} +1 -1
  123. package/dist/{policy-scaffold-config-DwZFigj7.mjs → policy-scaffold-config-RpxwwZ2H.mjs} +2 -2
  124. package/dist/{policy-scaffold-config-DwZFigj7.mjs.map → policy-scaffold-config-RpxwwZ2H.mjs.map} +1 -1
  125. package/dist/{pullChunkedCustomSiloOutstandingIdentifiers-DtDLjhzX.mjs → pullChunkedCustomSiloOutstandingIdentifiers-DbybCU2T.mjs} +2 -2
  126. package/dist/{pullChunkedCustomSiloOutstandingIdentifiers-DtDLjhzX.mjs.map → pullChunkedCustomSiloOutstandingIdentifiers-DbybCU2T.mjs.map} +1 -1
  127. package/dist/{pullManualEnrichmentIdentifiersToCsv-CWVaEx3x.mjs → pullManualEnrichmentIdentifiersToCsv-CxTPUfpV.mjs} +2 -2
  128. package/dist/{pullManualEnrichmentIdentifiersToCsv-CWVaEx3x.mjs.map → pullManualEnrichmentIdentifiersToCsv-CxTPUfpV.mjs.map} +1 -1
  129. package/dist/{pushCronIdentifiersFromCsv-J4ByJG4I.mjs → pushCronIdentifiersFromCsv-CeRVlbFE.mjs} +2 -2
  130. package/dist/{pushCronIdentifiersFromCsv-J4ByJG4I.mjs.map → pushCronIdentifiersFromCsv-CeRVlbFE.mjs.map} +1 -1
  131. package/dist/{pushManualEnrichmentIdentifiersFromCsv-Dyh7-KVs.mjs → pushManualEnrichmentIdentifiersFromCsv--4dYCvyv.mjs} +2 -2
  132. package/dist/{pushManualEnrichmentIdentifiersFromCsv-Dyh7-KVs.mjs.map → pushManualEnrichmentIdentifiersFromCsv--4dYCvyv.mjs.map} +1 -1
  133. package/dist/{removeUnverifiedRequestIdentifiers-DOXo1yCT.mjs → removeUnverifiedRequestIdentifiers-CV6JGgt_.mjs} +2 -2
  134. package/dist/{removeUnverifiedRequestIdentifiers-DOXo1yCT.mjs.map → removeUnverifiedRequestIdentifiers-CV6JGgt_.mjs.map} +1 -1
  135. package/dist/resolveBundleIdByName-D7NUOpLc.mjs +2 -0
  136. package/dist/resolveBundleIdByName-D7NUOpLc.mjs.map +1 -0
  137. package/dist/resolvePolicyBundleVersion-CKbF9vqc.mjs +2 -0
  138. package/dist/resolvePolicyBundleVersion-CKbF9vqc.mjs.map +1 -0
  139. package/dist/{retryRequestDataSilos-Dehz_PEx.mjs → retryRequestDataSilos-_OThvVwU.mjs} +2 -2
  140. package/dist/{retryRequestDataSilos-Dehz_PEx.mjs.map → retryRequestDataSilos-_OThvVwU.mjs.map} +1 -1
  141. package/dist/{skipPreflightJobs-BjFQxEwf.mjs → skipPreflightJobs-D8og5pKe.mjs} +2 -2
  142. package/dist/{skipPreflightJobs-BjFQxEwf.mjs.map → skipPreflightJobs-D8og5pKe.mjs.map} +1 -1
  143. package/dist/{skipRequestDataSilos-DB1_3m-p.mjs → skipRequestDataSilos-DUQ6AD_O.mjs} +2 -2
  144. package/dist/{skipRequestDataSilos-DB1_3m-p.mjs.map → skipRequestDataSilos-DUQ6AD_O.mjs.map} +1 -1
  145. package/dist/{streamPrivacyRequestsToCsv-BWmN5fl6.mjs → streamPrivacyRequestsToCsv-BApu4dvI.mjs} +2 -2
  146. package/dist/{streamPrivacyRequestsToCsv-BWmN5fl6.mjs.map → streamPrivacyRequestsToCsv-BApu4dvI.mjs.map} +1 -1
  147. package/dist/{updateConsentManagerVersionToLatest-C6jRvQPt.mjs → updateConsentManagerVersionToLatest-BrgPZ5hX.mjs} +2 -2
  148. package/dist/{updateConsentManagerVersionToLatest-C6jRvQPt.mjs.map → updateConsentManagerVersionToLatest-BrgPZ5hX.mjs.map} +1 -1
  149. package/dist/{uploadConsents-08KJPYm_.mjs → uploadConsents-DRlDHQak.mjs} +2 -2
  150. package/dist/{uploadConsents-08KJPYm_.mjs.map → uploadConsents-DRlDHQak.mjs.map} +1 -1
  151. package/dist/{uploadPrivacyRequestsFromCsv-M3iY9cjb.mjs → uploadPrivacyRequestsFromCsv-FAGllBdd.mjs} +2 -2
  152. package/dist/{uploadPrivacyRequestsFromCsv-M3iY9cjb.mjs.map → uploadPrivacyRequestsFromCsv-FAGllBdd.mjs.map} +1 -1
  153. package/package.json +6 -6
  154. package/dist/resolveBundleIdByName-BPrMkU0w.mjs +0 -2
  155. package/dist/resolveBundleIdByName-BPrMkU0w.mjs.map +0 -1
  156. package/dist/resolvePolicyBundleVersion-BrVz4LKN.mjs +0 -2
  157. package/dist/resolvePolicyBundleVersion-BrVz4LKN.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"impl-BTXUJwyb.mjs","names":[],"sources":["../src/commands/consent/pull-consent-metrics/impl.ts"],"sourcesContent":["import path from 'node:path';\n\nimport { ConsentManagerMetricBin } from '@transcend-io/privacy-types';\nimport { buildTranscendGraphQLClient } from '@transcend-io/sdk';\nimport { map, mapSeries } from '@transcend-io/utils';\nimport colors from 'colors';\n\nimport { ADMIN_DASH_INTEGRATIONS } from '../../../constants.js';\nimport type { LocalContext } from '../../../context.js';\nimport { validateTranscendAuth } from '../../../lib/api-keys/index.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { pullConsentManagerMetrics } from '../../../lib/consent-manager/index.js';\nimport { writeCsv } from '../../../lib/helpers/index.js';\n\nexport interface PullConsentMetricsCommandFlags {\n auth: string;\n start: Date;\n end?: Date;\n folder: string;\n bin: string;\n transcendUrl: string;\n}\n\nexport async function pullConsentMetrics(\n this: LocalContext,\n { auth, start, end, folder, bin, transcendUrl }: PullConsentMetricsCommandFlags,\n): Promise<void> {\n // Validate bin\n const parsedBin = bin as ConsentManagerMetricBin;\n if (!Object.values(ConsentManagerMetricBin).includes(parsedBin)) {\n this.logger.error(\n colors.red(\n `Failed to parse argument \"bin\" with value \"${bin}\"\\n` +\n `Expected one of: \\n${Object.values(ConsentManagerMetricBin).join('\\n')}`,\n ),\n );\n this.process.exit(1);\n }\n\n // Parse the dates\n const startDate = new Date(start);\n const endDate = end ? new Date(end) : new Date();\n if (Number.isNaN(startDate.getTime())) {\n this.logger.error(\n colors.red(\n `Start date provided is invalid date. Got --start=\"${start}\" expected --start=\"01/01/2023\"`,\n ),\n );\n this.process.exit(1);\n }\n if (Number.isNaN(endDate.getTime())) {\n this.logger.error(\n colors.red(\n `End date provided is invalid date. Got --end=\"${end}\" expected --end=\"01/01/2023\"`,\n ),\n );\n this.process.exit(1);\n }\n if (startDate > endDate) {\n this.logger.error(\n colors.red(\n `Got a start date \"${startDate.toISOString()}\" that was larger than the end date \"${endDate.toISOString()}\". ` +\n 'Start date must be before end date.',\n ),\n );\n this.process.exit(1);\n }\n\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 // Ensure folder either does not exist or is not a file\n if (this.fs.existsSync(folder) && !this.fs.lstatSync(folder).isDirectory()) {\n this.logger.error(\n colors.red(\n 'The provided argument \"folder\" was passed a file. expected: folder=\"./consent-metrics/\"',\n ),\n );\n this.process.exit(1);\n }\n\n // Create the folder if it does not exist\n if (!this.fs.existsSync(folder)) {\n this.fs.mkdirSync(folder);\n }\n\n this.logger.info(\n colors.magenta(\n `Pulling consent metrics from start=${startDate.toString()} to end=${endDate.toISOString()} with bin size \"${bin}\"`,\n ),\n );\n\n // Sync to Disk\n if (typeof apiKeyOrList === 'string') {\n try {\n // Create a GraphQL client\n const client = buildTranscendGraphQLClient(transcendUrl, apiKeyOrList);\n\n // Pull the metrics\n const configuration = await pullConsentManagerMetrics(client, {\n bin: parsedBin,\n start: startDate,\n end: endDate,\n });\n\n // Write to file\n await map(\n Object.entries(configuration),\n async ([metricName, metrics]) => {\n await map(\n metrics,\n async ({ points, name }) => {\n const file = path.join(folder, `${metricName}_${name}.csv`);\n this.logger.info(colors.magenta(`Writing configuration to file \"${file}\"...`));\n await writeCsv(\n file,\n points.map(({ key, value }: { key: string; value: string }) => ({\n timestamp: key,\n value,\n })),\n );\n },\n {\n concurrency: 5,\n },\n );\n },\n { concurrency: 5 },\n );\n } catch (err) {\n this.logger.error(colors.red(`An error occurred syncing the schema: ${err.message}`));\n this.process.exit(1);\n }\n\n // Indicate success\n this.logger.info(\n colors.green(\n `Successfully synced consent metrics to disk in folder \"${folder}\"! View at ${ADMIN_DASH_INTEGRATIONS}`,\n ),\n );\n } else {\n const encounteredErrors: string[] = [];\n await mapSeries(apiKeyOrList, async (apiKey, ind) => {\n const prefix = `[${ind + 1}/${apiKeyOrList.length}][${apiKey.organizationName}] `;\n this.logger.info(\n colors.magenta(`~~~\\n\\n${prefix}Attempting to pull consent metrics...\\n\\n~~~`),\n );\n\n // Create a GraphQL client\n const client = buildTranscendGraphQLClient(transcendUrl, apiKey.apiKey);\n\n try {\n const configuration = await pullConsentManagerMetrics(client, {\n bin: parsedBin,\n start: startDate,\n end: endDate,\n });\n\n // ensure folder exists for that organization\n const subFolder = path.join(folder, apiKey.organizationName);\n if (!this.fs.existsSync(subFolder)) {\n this.fs.mkdirSync(subFolder);\n }\n\n // Write to file\n Object.entries(configuration).forEach(([metricName, metrics]) => {\n metrics.forEach(({ points, name }) => {\n const file = path.join(subFolder, `${metricName}_${name}.csv`);\n this.logger.info(colors.magenta(`Writing configuration to file \"${file}\"...`));\n writeCsv(\n file,\n points.map(({ key, value }: { key: string; value: string }) => ({\n timestamp: key,\n value,\n })),\n );\n });\n });\n\n this.logger.info(colors.green(`${prefix}Successfully pulled configuration!`));\n } catch (err) {\n this.logger.error(colors.red(`${prefix}Failed to sync configuration.`), err);\n encounteredErrors.push(apiKey.organizationName);\n }\n });\n\n if (encounteredErrors.length > 0) {\n this.logger.info(\n colors.red(\n `Sync encountered errors for \"${encounteredErrors.join(\n ',',\n )}\". View output above for more information, or check out ${ADMIN_DASH_INTEGRATIONS}`,\n ),\n );\n\n this.process.exit(1);\n }\n }\n}\n"],"mappings":"sfAuBA,eAAsB,EAEpB,CAAE,OAAM,QAAO,MAAK,SAAQ,MAAK,gBAClB,CAEf,IAAM,EAAY,EACb,OAAO,OAAO,EAAwB,CAAC,SAAS,EAAU,GAC7D,KAAK,OAAO,MACV,EAAO,IACL,8CAA8C,EAAI,wBAC1B,OAAO,OAAO,EAAwB,CAAC,KAAK;EAAK,GAC1E,CACF,CACD,KAAK,QAAQ,KAAK,EAAE,EAItB,IAAM,EAAY,IAAI,KAAK,EAAM,CAC3B,EAAU,EAAM,IAAI,KAAK,EAAI,CAAG,IAAI,KACtC,OAAO,MAAM,EAAU,SAAS,CAAC,GACnC,KAAK,OAAO,MACV,EAAO,IACL,qDAAqD,EAAM,iCAC5D,CACF,CACD,KAAK,QAAQ,KAAK,EAAE,EAElB,OAAO,MAAM,EAAQ,SAAS,CAAC,GACjC,KAAK,OAAO,MACV,EAAO,IACL,iDAAiD,EAAI,+BACtD,CACF,CACD,KAAK,QAAQ,KAAK,EAAE,EAElB,EAAY,IACd,KAAK,OAAO,MACV,EAAO,IACL,qBAAqB,EAAU,aAAa,CAAC,uCAAuC,EAAQ,aAAa,CAAC,wCAE3G,CACF,CACD,KAAK,QAAQ,KAAK,EAAE,EAGtB,EAAoB,KAAK,QAAQ,CAGjC,IAAM,EAAe,MAAM,EAAsB,EAAM,KAAK,CAwB5D,GArBI,KAAK,GAAG,WAAW,EAAO,EAAI,CAAC,KAAK,GAAG,UAAU,EAAO,CAAC,aAAa,GACxE,KAAK,OAAO,MACV,EAAO,IACL,0FACD,CACF,CACD,KAAK,QAAQ,KAAK,EAAE,EAIjB,KAAK,GAAG,WAAW,EAAO,EAC7B,KAAK,GAAG,UAAU,EAAO,CAG3B,KAAK,OAAO,KACV,EAAO,QACL,sCAAsC,EAAU,UAAU,CAAC,UAAU,EAAQ,aAAa,CAAC,kBAAkB,EAAI,GAClH,CACF,CAGG,OAAO,GAAiB,SAAU,CACpC,GAAI,CAKF,IAAM,EAAgB,MAAM,EAHb,EAA4B,EAAc,EAGG,CAAE,CAC5D,IAAK,EACL,MAAO,EACP,IAAK,EACN,CAAC,CAGF,MAAM,EACJ,OAAO,QAAQ,EAAc,CAC7B,MAAO,CAAC,EAAY,KAAa,CAC/B,MAAM,EACJ,EACA,MAAO,CAAE,SAAQ,UAAW,CAC1B,IAAM,EAAO,EAAK,KAAK,EAAQ,GAAG,EAAW,GAAG,EAAK,MAAM,CAC3D,KAAK,OAAO,KAAK,EAAO,QAAQ,kCAAkC,EAAK,MAAM,CAAC,CAC9E,MAAM,EACJ,EACA,EAAO,KAAK,CAAE,MAAK,YAA6C,CAC9D,UAAW,EACX,QACD,EAAE,CACJ,EAEH,CACE,YAAa,EACd,CACF,EAEH,CAAE,YAAa,EAAG,CACnB,OACM,EAAK,CACZ,KAAK,OAAO,MAAM,EAAO,IAAI,yCAAyC,EAAI,UAAU,CAAC,CACrF,KAAK,QAAQ,KAAK,EAAE,CAItB,KAAK,OAAO,KACV,EAAO,MACL,0DAA0D,EAAO,aAAa,IAC/E,CACF,KACI,CACL,IAAM,EAA8B,EAAE,CACtC,MAAM,EAAU,EAAc,MAAO,EAAQ,IAAQ,CACnD,IAAM,EAAS,IAAI,EAAM,EAAE,GAAG,EAAa,OAAO,IAAI,EAAO,iBAAiB,IAC9E,KAAK,OAAO,KACV,EAAO,QAAQ,UAAU,EAAO,8CAA8C,CAC/E,CAGD,IAAM,EAAS,EAA4B,EAAc,EAAO,OAAO,CAEvE,GAAI,CACF,IAAM,EAAgB,MAAM,EAA0B,EAAQ,CAC5D,IAAK,EACL,MAAO,EACP,IAAK,EACN,CAAC,CAGI,EAAY,EAAK,KAAK,EAAQ,EAAO,iBAAiB,CACvD,KAAK,GAAG,WAAW,EAAU,EAChC,KAAK,GAAG,UAAU,EAAU,CAI9B,OAAO,QAAQ,EAAc,CAAC,SAAS,CAAC,EAAY,KAAa,CAC/D,EAAQ,SAAS,CAAE,SAAQ,UAAW,CACpC,IAAM,EAAO,EAAK,KAAK,EAAW,GAAG,EAAW,GAAG,EAAK,MAAM,CAC9D,KAAK,OAAO,KAAK,EAAO,QAAQ,kCAAkC,EAAK,MAAM,CAAC,CAC9E,EACE,EACA,EAAO,KAAK,CAAE,MAAK,YAA6C,CAC9D,UAAW,EACX,QACD,EAAE,CACJ,EACD,EACF,CAEF,KAAK,OAAO,KAAK,EAAO,MAAM,GAAG,EAAO,oCAAoC,CAAC,OACtE,EAAK,CACZ,KAAK,OAAO,MAAM,EAAO,IAAI,GAAG,EAAO,+BAA+B,CAAE,EAAI,CAC5E,EAAkB,KAAK,EAAO,iBAAiB,GAEjD,CAEE,EAAkB,OAAS,IAC7B,KAAK,OAAO,KACV,EAAO,IACL,gCAAgC,EAAkB,KAChD,IACD,CAAC,0DAA0D,IAC7D,CACF,CAED,KAAK,QAAQ,KAAK,EAAE"}
1
+ {"version":3,"file":"impl-ChQAmyBN.mjs","names":[],"sources":["../src/commands/consent/pull-consent-metrics/impl.ts"],"sourcesContent":["import path from 'node:path';\n\nimport { ConsentManagerMetricBin } from '@transcend-io/privacy-types';\nimport { buildTranscendGraphQLClient } from '@transcend-io/sdk';\nimport { map, mapSeries } from '@transcend-io/utils';\nimport colors from 'colors';\n\nimport { ADMIN_DASH_INTEGRATIONS } from '../../../constants.js';\nimport type { LocalContext } from '../../../context.js';\nimport { validateTranscendAuth } from '../../../lib/api-keys/index.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { pullConsentManagerMetrics } from '../../../lib/consent-manager/index.js';\nimport { writeCsv } from '../../../lib/helpers/index.js';\n\nexport interface PullConsentMetricsCommandFlags {\n auth: string;\n start: Date;\n end?: Date;\n folder: string;\n bin: string;\n transcendUrl: string;\n}\n\nexport async function pullConsentMetrics(\n this: LocalContext,\n { auth, start, end, folder, bin, transcendUrl }: PullConsentMetricsCommandFlags,\n): Promise<void> {\n // Validate bin\n const parsedBin = bin as ConsentManagerMetricBin;\n if (!Object.values(ConsentManagerMetricBin).includes(parsedBin)) {\n this.logger.error(\n colors.red(\n `Failed to parse argument \"bin\" with value \"${bin}\"\\n` +\n `Expected one of: \\n${Object.values(ConsentManagerMetricBin).join('\\n')}`,\n ),\n );\n this.process.exit(1);\n }\n\n // Parse the dates\n const startDate = new Date(start);\n const endDate = end ? new Date(end) : new Date();\n if (Number.isNaN(startDate.getTime())) {\n this.logger.error(\n colors.red(\n `Start date provided is invalid date. Got --start=\"${start}\" expected --start=\"01/01/2023\"`,\n ),\n );\n this.process.exit(1);\n }\n if (Number.isNaN(endDate.getTime())) {\n this.logger.error(\n colors.red(\n `End date provided is invalid date. Got --end=\"${end}\" expected --end=\"01/01/2023\"`,\n ),\n );\n this.process.exit(1);\n }\n if (startDate > endDate) {\n this.logger.error(\n colors.red(\n `Got a start date \"${startDate.toISOString()}\" that was larger than the end date \"${endDate.toISOString()}\". ` +\n 'Start date must be before end date.',\n ),\n );\n this.process.exit(1);\n }\n\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 // Ensure folder either does not exist or is not a file\n if (this.fs.existsSync(folder) && !this.fs.lstatSync(folder).isDirectory()) {\n this.logger.error(\n colors.red(\n 'The provided argument \"folder\" was passed a file. expected: folder=\"./consent-metrics/\"',\n ),\n );\n this.process.exit(1);\n }\n\n // Create the folder if it does not exist\n if (!this.fs.existsSync(folder)) {\n this.fs.mkdirSync(folder);\n }\n\n this.logger.info(\n colors.magenta(\n `Pulling consent metrics from start=${startDate.toString()} to end=${endDate.toISOString()} with bin size \"${bin}\"`,\n ),\n );\n\n // Sync to Disk\n if (typeof apiKeyOrList === 'string') {\n try {\n // Create a GraphQL client\n const client = buildTranscendGraphQLClient(transcendUrl, apiKeyOrList);\n\n // Pull the metrics\n const configuration = await pullConsentManagerMetrics(client, {\n bin: parsedBin,\n start: startDate,\n end: endDate,\n });\n\n // Write to file\n await map(\n Object.entries(configuration),\n async ([metricName, metrics]) => {\n await map(\n metrics,\n async ({ points, name }) => {\n const file = path.join(folder, `${metricName}_${name}.csv`);\n this.logger.info(colors.magenta(`Writing configuration to file \"${file}\"...`));\n await writeCsv(\n file,\n points.map(({ key, value }: { key: string; value: string }) => ({\n timestamp: key,\n value,\n })),\n );\n },\n {\n concurrency: 5,\n },\n );\n },\n { concurrency: 5 },\n );\n } catch (err) {\n this.logger.error(colors.red(`An error occurred syncing the schema: ${err.message}`));\n this.process.exit(1);\n }\n\n // Indicate success\n this.logger.info(\n colors.green(\n `Successfully synced consent metrics to disk in folder \"${folder}\"! View at ${ADMIN_DASH_INTEGRATIONS}`,\n ),\n );\n } else {\n const encounteredErrors: string[] = [];\n await mapSeries(apiKeyOrList, async (apiKey, ind) => {\n const prefix = `[${ind + 1}/${apiKeyOrList.length}][${apiKey.organizationName}] `;\n this.logger.info(\n colors.magenta(`~~~\\n\\n${prefix}Attempting to pull consent metrics...\\n\\n~~~`),\n );\n\n // Create a GraphQL client\n const client = buildTranscendGraphQLClient(transcendUrl, apiKey.apiKey);\n\n try {\n const configuration = await pullConsentManagerMetrics(client, {\n bin: parsedBin,\n start: startDate,\n end: endDate,\n });\n\n // ensure folder exists for that organization\n const subFolder = path.join(folder, apiKey.organizationName);\n if (!this.fs.existsSync(subFolder)) {\n this.fs.mkdirSync(subFolder);\n }\n\n // Write to file\n Object.entries(configuration).forEach(([metricName, metrics]) => {\n metrics.forEach(({ points, name }) => {\n const file = path.join(subFolder, `${metricName}_${name}.csv`);\n this.logger.info(colors.magenta(`Writing configuration to file \"${file}\"...`));\n writeCsv(\n file,\n points.map(({ key, value }: { key: string; value: string }) => ({\n timestamp: key,\n value,\n })),\n );\n });\n });\n\n this.logger.info(colors.green(`${prefix}Successfully pulled configuration!`));\n } catch (err) {\n this.logger.error(colors.red(`${prefix}Failed to sync configuration.`), err);\n encounteredErrors.push(apiKey.organizationName);\n }\n });\n\n if (encounteredErrors.length > 0) {\n this.logger.info(\n colors.red(\n `Sync encountered errors for \"${encounteredErrors.join(\n ',',\n )}\". View output above for more information, or check out ${ADMIN_DASH_INTEGRATIONS}`,\n ),\n );\n\n this.process.exit(1);\n }\n }\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{t as e}from"./pushCronIdentifiersFromCsv-J4ByJG4I.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";async function n({file:n,transcendUrl:r,auth:i,sombraAuth:a,dataSiloId:o}){t(this.process),await e({file:n,transcendUrl:r,auth:i,sombraAuth:a,dataSiloId:o})}export{n as markIdentifiersCompleted};
2
- //# sourceMappingURL=impl-DD-ICQ8E.mjs.map
1
+ import{t as e}from"./pushCronIdentifiersFromCsv-CeRVlbFE.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";async function n({file:n,transcendUrl:r,auth:i,sombraAuth:a,dataSiloId:o}){t(this.process),await e({file:n,transcendUrl:r,auth:i,sombraAuth:a,dataSiloId:o})}export{n as markIdentifiersCompleted};
2
+ //# sourceMappingURL=impl-ClT3G845.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"impl-DD-ICQ8E.mjs","names":[],"sources":["../src/commands/request/cron/mark-identifiers-completed/impl.ts"],"sourcesContent":["import type { LocalContext } from '../../../../context.js';\nimport { doneInputValidation } from '../../../../lib/cli/done-input-validation.js';\nimport { pushCronIdentifiersFromCsv } from '../../../../lib/cron/index.js';\n\nexport interface MarkIdentifiersCompletedCommandFlags {\n file: string;\n transcendUrl: string;\n auth: string;\n sombraAuth?: string;\n dataSiloId: string;\n}\n\nexport async function markIdentifiersCompleted(\n this: LocalContext,\n { file, transcendUrl, auth, sombraAuth, dataSiloId }: MarkIdentifiersCompletedCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n await pushCronIdentifiersFromCsv({\n file,\n transcendUrl,\n auth,\n sombraAuth,\n dataSiloId,\n });\n}\n"],"mappings":"kHAYA,eAAsB,EAEpB,CAAE,OAAM,eAAc,OAAM,aAAY,cACzB,CACf,EAAoB,KAAK,QAAQ,CAEjC,MAAM,EAA2B,CAC/B,OACA,eACA,OACA,aACA,aACD,CAAC"}
1
+ {"version":3,"file":"impl-ClT3G845.mjs","names":[],"sources":["../src/commands/request/cron/mark-identifiers-completed/impl.ts"],"sourcesContent":["import type { LocalContext } from '../../../../context.js';\nimport { doneInputValidation } from '../../../../lib/cli/done-input-validation.js';\nimport { pushCronIdentifiersFromCsv } from '../../../../lib/cron/index.js';\n\nexport interface MarkIdentifiersCompletedCommandFlags {\n file: string;\n transcendUrl: string;\n auth: string;\n sombraAuth?: string;\n dataSiloId: string;\n}\n\nexport async function markIdentifiersCompleted(\n this: LocalContext,\n { file, transcendUrl, auth, sombraAuth, dataSiloId }: MarkIdentifiersCompletedCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n await pushCronIdentifiersFromCsv({\n file,\n transcendUrl,\n auth,\n sombraAuth,\n dataSiloId,\n });\n}\n"],"mappings":"kHAYA,eAAsB,EAEpB,CAAE,OAAM,eAAc,OAAM,aAAY,cACzB,CACf,EAAoB,KAAK,QAAQ,CAEjC,MAAM,EAA2B,CAC/B,OACA,eACA,OACA,aACA,aACD,CAAC"}
@@ -1,2 +1,2 @@
1
- import{t as e}from"./readCsv-DNcJ_UfU.mjs";import{r as t}from"./uploadConsents-08KJPYm_.mjs";import{t as n}from"./done-input-validation-LiTaCEzF.mjs";import*as r from"io-ts";const i=r.intersection([r.type({userId:r.string,timestamp:r.string}),r.partial({confirmed:r.union([r.literal(`true`),r.literal(`false`)]),updated:r.union([r.literal(`true`),r.literal(`false`)]),prompted:r.union([r.literal(`true`),r.literal(`false`)]),metadata:r.string,usp:r.union([r.string,r.null]),gpp:r.union([r.string,r.null]),purposes:r.string})]);async function a({base64EncryptionKey:r,base64SigningKey:a,partition:o,file:s,consentUrl:c,concurrency:l}){n(this.process),await t({base64EncryptionKey:r,base64SigningKey:a,preferences:e(this.fs.readFileSync(s,`utf8`),i),partition:o,concurrency:l,transcendUrl:c})}export{a as uploadConsentPreferences};
2
- //# sourceMappingURL=impl-BtHRf6Jp.mjs.map
1
+ import{t as e}from"./readCsv-DNcJ_UfU.mjs";import{r as t}from"./uploadConsents-DRlDHQak.mjs";import{t as n}from"./done-input-validation-LiTaCEzF.mjs";import*as r from"io-ts";const i=r.intersection([r.type({userId:r.string,timestamp:r.string}),r.partial({confirmed:r.union([r.literal(`true`),r.literal(`false`)]),updated:r.union([r.literal(`true`),r.literal(`false`)]),prompted:r.union([r.literal(`true`),r.literal(`false`)]),metadata:r.string,usp:r.union([r.string,r.null]),gpp:r.union([r.string,r.null]),purposes:r.string})]);async function a({base64EncryptionKey:r,base64SigningKey:a,partition:o,file:s,consentUrl:c,concurrency:l}){n(this.process),await t({base64EncryptionKey:r,base64SigningKey:a,preferences:e(this.fs.readFileSync(s,`utf8`),i),partition:o,concurrency:l,transcendUrl:c})}export{a as uploadConsentPreferences};
2
+ //# sourceMappingURL=impl-Cp5o0Q2g.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"impl-BtHRf6Jp.mjs","names":[],"sources":["../src/lib/consent-manager/types.ts","../src/commands/consent/upload-consent-preferences/impl.ts"],"sourcesContent":["import * as t from 'io-ts';\n\nexport const ConsentPreferenceUpload = t.intersection([\n t.type({\n /** User ID */\n userId: t.string,\n /** Has the consent been updated (including no-change confirmation) since default resolution */\n timestamp: t.string,\n }),\n t.partial({\n /** Was tracking consent confirmed by the user? If this is false, the consent was resolved from defaults & is not yet confirmed */\n confirmed: t.union([t.literal('true'), t.literal('false')]),\n /**\n * Has the consent been updated (including no-change confirmation) since default resolution\n */\n updated: t.union([t.literal('true'), t.literal('false')]),\n /**\n * Whether or not the UI has been shown to the end-user (undefined in older versions of airgap.js)\n */\n prompted: t.union([t.literal('true'), t.literal('false')]),\n /** Consent metadata */\n metadata: t.string,\n /** US Privacy (USP) String */\n usp: t.union([t.string, t.null]),\n /** IAB GPP String */\n gpp: t.union([t.string, t.null]),\n /**\n * Purpose map\n * This is a stringified JSON object with keys as purpose names and values as booleans or 'Auto'\n */\n purposes: t.string,\n }),\n]);\n\n/** Type override */\nexport type ConsentPreferenceUpload = t.TypeOf<typeof ConsentPreferenceUpload>;\n","import type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { ConsentPreferenceUpload } from '../../../lib/consent-manager/types.js';\nimport { uploadConsents } from '../../../lib/consent-manager/uploadConsents.js';\nimport { parseCsv } from '../../../lib/requests/readCsv.js';\n\nexport interface UploadConsentPreferencesCommandFlags {\n base64EncryptionKey: string;\n base64SigningKey: string;\n partition: string;\n file: string;\n consentUrl: string;\n concurrency: number;\n}\n\nexport async function uploadConsentPreferences(\n this: LocalContext,\n {\n base64EncryptionKey,\n base64SigningKey,\n partition,\n file,\n consentUrl,\n concurrency,\n }: UploadConsentPreferencesCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n // Load in preferences from csv\n const preferences = parseCsv(this.fs.readFileSync(file, 'utf8'), ConsentPreferenceUpload);\n\n // Upload cookies\n await uploadConsents({\n base64EncryptionKey,\n base64SigningKey,\n preferences,\n partition,\n concurrency,\n transcendUrl: consentUrl,\n });\n}\n"],"mappings":"8KAEA,MAAa,EAA0B,EAAE,aAAa,CACpD,EAAE,KAAK,CAEL,OAAQ,EAAE,OAEV,UAAW,EAAE,OACd,CAAC,CACF,EAAE,QAAQ,CAER,UAAW,EAAE,MAAM,CAAC,EAAE,QAAQ,OAAO,CAAE,EAAE,QAAQ,QAAQ,CAAC,CAAC,CAI3D,QAAS,EAAE,MAAM,CAAC,EAAE,QAAQ,OAAO,CAAE,EAAE,QAAQ,QAAQ,CAAC,CAAC,CAIzD,SAAU,EAAE,MAAM,CAAC,EAAE,QAAQ,OAAO,CAAE,EAAE,QAAQ,QAAQ,CAAC,CAAC,CAE1D,SAAU,EAAE,OAEZ,IAAK,EAAE,MAAM,CAAC,EAAE,OAAQ,EAAE,KAAK,CAAC,CAEhC,IAAK,EAAE,MAAM,CAAC,EAAE,OAAQ,EAAE,KAAK,CAAC,CAKhC,SAAU,EAAE,OACb,CAAC,CACH,CAAC,CCjBF,eAAsB,EAEpB,CACE,sBACA,mBACA,YACA,OACA,aACA,eAEa,CACf,EAAoB,KAAK,QAAQ,CAMjC,MAAM,EAAe,CACnB,sBACA,mBACA,YANkB,EAAS,KAAK,GAAG,aAAa,EAAM,OAAO,CAAE,EAMpD,CACX,YACA,cACA,aAAc,EACf,CAAC"}
1
+ {"version":3,"file":"impl-Cp5o0Q2g.mjs","names":[],"sources":["../src/lib/consent-manager/types.ts","../src/commands/consent/upload-consent-preferences/impl.ts"],"sourcesContent":["import * as t from 'io-ts';\n\nexport const ConsentPreferenceUpload = t.intersection([\n t.type({\n /** User ID */\n userId: t.string,\n /** Has the consent been updated (including no-change confirmation) since default resolution */\n timestamp: t.string,\n }),\n t.partial({\n /** Was tracking consent confirmed by the user? If this is false, the consent was resolved from defaults & is not yet confirmed */\n confirmed: t.union([t.literal('true'), t.literal('false')]),\n /**\n * Has the consent been updated (including no-change confirmation) since default resolution\n */\n updated: t.union([t.literal('true'), t.literal('false')]),\n /**\n * Whether or not the UI has been shown to the end-user (undefined in older versions of airgap.js)\n */\n prompted: t.union([t.literal('true'), t.literal('false')]),\n /** Consent metadata */\n metadata: t.string,\n /** US Privacy (USP) String */\n usp: t.union([t.string, t.null]),\n /** IAB GPP String */\n gpp: t.union([t.string, t.null]),\n /**\n * Purpose map\n * This is a stringified JSON object with keys as purpose names and values as booleans or 'Auto'\n */\n purposes: t.string,\n }),\n]);\n\n/** Type override */\nexport type ConsentPreferenceUpload = t.TypeOf<typeof ConsentPreferenceUpload>;\n","import type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { ConsentPreferenceUpload } from '../../../lib/consent-manager/types.js';\nimport { uploadConsents } from '../../../lib/consent-manager/uploadConsents.js';\nimport { parseCsv } from '../../../lib/requests/readCsv.js';\n\nexport interface UploadConsentPreferencesCommandFlags {\n base64EncryptionKey: string;\n base64SigningKey: string;\n partition: string;\n file: string;\n consentUrl: string;\n concurrency: number;\n}\n\nexport async function uploadConsentPreferences(\n this: LocalContext,\n {\n base64EncryptionKey,\n base64SigningKey,\n partition,\n file,\n consentUrl,\n concurrency,\n }: UploadConsentPreferencesCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n // Load in preferences from csv\n const preferences = parseCsv(this.fs.readFileSync(file, 'utf8'), ConsentPreferenceUpload);\n\n // Upload cookies\n await uploadConsents({\n base64EncryptionKey,\n base64SigningKey,\n preferences,\n partition,\n concurrency,\n transcendUrl: consentUrl,\n });\n}\n"],"mappings":"8KAEA,MAAa,EAA0B,EAAE,aAAa,CACpD,EAAE,KAAK,CAEL,OAAQ,EAAE,OAEV,UAAW,EAAE,OACd,CAAC,CACF,EAAE,QAAQ,CAER,UAAW,EAAE,MAAM,CAAC,EAAE,QAAQ,OAAO,CAAE,EAAE,QAAQ,QAAQ,CAAC,CAAC,CAI3D,QAAS,EAAE,MAAM,CAAC,EAAE,QAAQ,OAAO,CAAE,EAAE,QAAQ,QAAQ,CAAC,CAAC,CAIzD,SAAU,EAAE,MAAM,CAAC,EAAE,QAAQ,OAAO,CAAE,EAAE,QAAQ,QAAQ,CAAC,CAAC,CAE1D,SAAU,EAAE,OAEZ,IAAK,EAAE,MAAM,CAAC,EAAE,OAAQ,EAAE,KAAK,CAAC,CAEhC,IAAK,EAAE,MAAM,CAAC,EAAE,OAAQ,EAAE,KAAK,CAAC,CAKhC,SAAU,EAAE,OACb,CAAC,CACH,CAAC,CCjBF,eAAsB,EAEpB,CACE,sBACA,mBACA,YACA,OACA,aACA,eAEa,CACf,EAAoB,KAAK,QAAQ,CAMjC,MAAM,EAAe,CACnB,sBACA,mBACA,YANkB,EAAS,KAAK,GAAG,aAAa,EAAM,OAAO,CAAE,EAMpD,CACX,YACA,cACA,aAAc,EACf,CAAC"}
@@ -1,2 +1,2 @@
1
- import{t as e}from"./notifyPrivacyRequestsAdditionalTime-DLW694xo.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";async function n({auth:n,transcendUrl:r,createdAtBefore:i,createdAtAfter:a,updatedAtBefore:o,updatedAtAfter:s,actions:c,daysLeft:l,days:u,requestIds:d,emailTemplate:f,concurrency:p}){t(this.process),await e({transcendUrl:r,requestActions:c,auth:n,emailTemplate:f,days:u,daysLeft:l,requestIds:d,concurrency:p,createdAtBefore:i,createdAtAfter:a,updatedAtBefore:o,updatedAtAfter:s})}export{n as notifyAdditionalTime};
2
- //# sourceMappingURL=impl-CcYyiqaB.mjs.map
1
+ import{t as e}from"./notifyPrivacyRequestsAdditionalTime-n5fvOJaA.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";async function n({auth:n,transcendUrl:r,createdAtBefore:i,createdAtAfter:a,updatedAtBefore:o,updatedAtAfter:s,actions:c,daysLeft:l,days:u,requestIds:d,emailTemplate:f,concurrency:p}){t(this.process),await e({transcendUrl:r,requestActions:c,auth:n,emailTemplate:f,days:u,daysLeft:l,requestIds:d,concurrency:p,createdAtBefore:i,createdAtAfter:a,updatedAtBefore:o,updatedAtAfter:s})}export{n as notifyAdditionalTime};
2
+ //# sourceMappingURL=impl-D58JUOdA.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"impl-CcYyiqaB.mjs","names":[],"sources":["../src/commands/request/notify-additional-time/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 { notifyPrivacyRequestsAdditionalTime } from '../../../lib/requests/index.js';\n\nexport interface NotifyAdditionalTimeCommandFlags {\n auth: string;\n createdAtBefore: Date;\n createdAtAfter?: Date;\n updatedAtBefore?: Date;\n updatedAtAfter?: Date;\n actions?: RequestAction[];\n daysLeft: number;\n days: number;\n requestIds?: string[];\n emailTemplate: string;\n transcendUrl: string;\n concurrency: number;\n}\n\nexport async function notifyAdditionalTime(\n this: LocalContext,\n {\n auth,\n transcendUrl,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n actions,\n daysLeft,\n days,\n requestIds,\n emailTemplate,\n concurrency,\n }: NotifyAdditionalTimeCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n await notifyPrivacyRequestsAdditionalTime({\n transcendUrl,\n requestActions: actions,\n auth,\n emailTemplate,\n days,\n daysLeft,\n requestIds,\n concurrency,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n });\n}\n"],"mappings":"2HAqBA,eAAsB,EAEpB,CACE,OACA,eACA,kBACA,iBACA,kBACA,iBACA,UACA,WACA,OACA,aACA,gBACA,eAEa,CACf,EAAoB,KAAK,QAAQ,CAEjC,MAAM,EAAoC,CACxC,eACA,eAAgB,EAChB,OACA,gBACA,OACA,WACA,aACA,cACA,kBACA,iBACA,kBACA,iBACD,CAAC"}
1
+ {"version":3,"file":"impl-D58JUOdA.mjs","names":[],"sources":["../src/commands/request/notify-additional-time/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 { notifyPrivacyRequestsAdditionalTime } from '../../../lib/requests/index.js';\n\nexport interface NotifyAdditionalTimeCommandFlags {\n auth: string;\n createdAtBefore: Date;\n createdAtAfter?: Date;\n updatedAtBefore?: Date;\n updatedAtAfter?: Date;\n actions?: RequestAction[];\n daysLeft: number;\n days: number;\n requestIds?: string[];\n emailTemplate: string;\n transcendUrl: string;\n concurrency: number;\n}\n\nexport async function notifyAdditionalTime(\n this: LocalContext,\n {\n auth,\n transcendUrl,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n actions,\n daysLeft,\n days,\n requestIds,\n emailTemplate,\n concurrency,\n }: NotifyAdditionalTimeCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n await notifyPrivacyRequestsAdditionalTime({\n transcendUrl,\n requestActions: actions,\n auth,\n emailTemplate,\n days,\n daysLeft,\n requestIds,\n concurrency,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n });\n}\n"],"mappings":"2HAqBA,eAAsB,EAEpB,CACE,OACA,eACA,kBACA,iBACA,kBACA,iBACA,UACA,WACA,OACA,aACA,gBACA,eAEa,CACf,EAAoB,KAAK,QAAQ,CAEjC,MAAM,EAAoC,CACxC,eACA,eAAgB,EAChB,OACA,gBACA,OACA,WACA,aACA,cACA,kBACA,iBACA,kBACA,iBACD,CAAC"}
@@ -1,2 +1,2 @@
1
- import{t as e}from"./removeUnverifiedRequestIdentifiers-DOXo1yCT.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";async function n({auth:n,transcendUrl:r,identifierNames:i,actions:a=[]}){t(this.process),await e({requestActions:a,transcendUrl:r,auth:n,identifierNames:i})}export{n as rejectUnverifiedIdentifiers};
2
- //# sourceMappingURL=impl-fsBuXKVJ.mjs.map
1
+ import{t as e}from"./removeUnverifiedRequestIdentifiers-CV6JGgt_.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";async function n({auth:n,transcendUrl:r,identifierNames:i,actions:a=[]}){t(this.process),await e({requestActions:a,transcendUrl:r,auth:n,identifierNames:i})}export{n as rejectUnverifiedIdentifiers};
2
+ //# sourceMappingURL=impl-D6frX-PK.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"impl-fsBuXKVJ.mjs","names":[],"sources":["../src/commands/request/reject-unverified-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 { removeUnverifiedRequestIdentifiers } from '../../../lib/requests/index.js';\n\nexport interface RejectUnverifiedIdentifiersCommandFlags {\n auth: string;\n identifierNames: string[];\n actions?: RequestAction[];\n transcendUrl: string;\n}\n\nexport async function rejectUnverifiedIdentifiers(\n this: LocalContext,\n { auth, transcendUrl, identifierNames, actions = [] }: RejectUnverifiedIdentifiersCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n await removeUnverifiedRequestIdentifiers({\n requestActions: actions,\n transcendUrl,\n auth,\n identifierNames,\n });\n}\n"],"mappings":"0HAaA,eAAsB,EAEpB,CAAE,OAAM,eAAc,kBAAiB,UAAU,EAAE,EACpC,CACf,EAAoB,KAAK,QAAQ,CAEjC,MAAM,EAAmC,CACvC,eAAgB,EAChB,eACA,OACA,kBACD,CAAC"}
1
+ {"version":3,"file":"impl-D6frX-PK.mjs","names":[],"sources":["../src/commands/request/reject-unverified-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 { removeUnverifiedRequestIdentifiers } from '../../../lib/requests/index.js';\n\nexport interface RejectUnverifiedIdentifiersCommandFlags {\n auth: string;\n identifierNames: string[];\n actions?: RequestAction[];\n transcendUrl: string;\n}\n\nexport async function rejectUnverifiedIdentifiers(\n this: LocalContext,\n { auth, transcendUrl, identifierNames, actions = [] }: RejectUnverifiedIdentifiersCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n await removeUnverifiedRequestIdentifiers({\n requestActions: actions,\n transcendUrl,\n auth,\n identifierNames,\n });\n}\n"],"mappings":"0HAaA,eAAsB,EAEpB,CAAE,OAAM,eAAc,kBAAiB,UAAU,EAAE,EACpC,CACf,EAAoB,KAAK,QAAQ,CAEjC,MAAM,EAAmC,CACvC,eAAgB,EAChB,eACA,OACA,kBACD,CAAC"}
@@ -1,2 +1,2 @@
1
- import{t as e}from"./buildExamples-BPpsiPem.mjs";import{r as t}from"./policyEngineCliError-CZrOHhLv.mjs";import{a as n,c as r,g as i,i as a}from"./policy-project-discovery-_6QosI9J.mjs";import{r as o,t as s}from"./runOpa-ojIqU1tO.mjs";import{n as c,t as l}from"./policy-bundle-manifest-CDbVx8E6.mjs";import{i as u,n as d,t as f}from"./printResult-Dmwv78e7.mjs";import{t as p}from"./formatPolicyBundleVersionSummary-DCHl1Vhy.mjs";import{n as m}from"./resolveBundleIdByName-BPrMkU0w.mjs";import{n as h}from"./inquirer-jzIQWAvq.mjs";import{t as g}from"./done-input-validation-LiTaCEzF.mjs";import{r as _}from"./prompts-BhXfYD6g.mjs";import{t as v}from"./command-output-BJcDRXNr.mjs";import y,{join as b}from"node:path";import x from"colors";import{spawnSync as S}from"node:child_process";import C from"node:fs";import w from"node:os";import{gunzipSync as T}from"node:zlib";import{MAX_BUNDLE_COMPRESSED_BYTES as E,MAX_BUNDLE_DECOMPRESSED_BYTES as D}from"@transcend-io/utils";import O from"fast-glob";function k(e){let t=O.sync(`**/*.rego`,{cwd:e,onlyFiles:!0,dot:!1}).sort(),n=y.join(e,r),{publishableRegoPaths:i}=c(C.existsSync(n)?C.readFileSync(n,`utf8`):void 0,t.map(t=>({path:t,contents:C.readFileSync(y.join(e,t),`utf8`)})));return{entries:[r,...i]}}async function A(e){let t=y.join(w.tmpdir(),`transcend-policy-bundle-build-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`);try{let{code:n,stderr:r}=await s([`build`,`--ignore`,`*_test.rego`,`-b`,`-o`,t,`.`],{cwd:e});if(n!==0)throw Error(r.trim()||`opa build failed with exit code ${n}`)}finally{C.existsSync(t)&&C.unlinkSync(t)}}function j(e){if(e<1024)return`${e} B`;let t=e/1024;if(t<1024)return`${t%1==0?t.toFixed(0):t.toFixed(1)} KiB`;let n=t/1024;return`${n%1==0?n.toFixed(0):n.toFixed(1)} MiB`}async function M(e){o();let t=y.resolve(e);if(!C.existsSync(t)||!C.statSync(t).isDirectory())throw Error(`Policy directory does not exist or is not a directory: ${t}`);let{entries:n}=k(t),{code:r,stderr:i}=await s([`check`,`--strict`,t]);if(r!==0)throw Error(i.trim()||`opa check failed with exit code ${r}`);await A(t);let a=y.join(w.tmpdir(),`transcend-policy-bundle-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`),c=S(`tar`,[`-czf`,a,`-C`,t,...n],{env:{...process.env,COPYFILE_DISABLE:`1`},encoding:`utf8`});if(c.status!==0)throw Error(`Failed to create policy bundle archive: ${c.stderr.trim()||`tar failed`}`);let l=C.readFileSync(a);if(l.byteLength>E)throw C.unlinkSync(a),Error(`Policy bundle exceeds the ${j(E)} compressed upload limit (bundle is ${j(l.byteLength)}). The server also rejects decompressed bundles larger than ${j(D)}.`);let u=T(l);if(u.byteLength>D)throw C.unlinkSync(a),Error(`Policy bundle exceeds the ${j(D)} decompressed upload limit (bundle is ${j(u.byteLength)} decompressed).`);return a}function N(e){let t=C.readFileSync(e.bundlePath),n=new FormData;return n.append(`bundle`,new Blob([t],{type:`application/gzip`}),y.basename(e.bundlePath)),n.append(`version`,e.version),e.description&&n.append(`description`,e.description),e.bundleName&&n.append(`bundleName`,e.bundleName),n}function P(e){return e.toISOString().slice(0,19).replace(/[T:]/g,`-`)}function F(e,t=new Date){return`${e}-${P(t)}`}function I(e){return e.template===i.Permissions?!0:e.template===i.Generic?!1:e.roots.some(e=>e===`permissions`||e.startsWith(`permissions/`))}function L(e,t){let r=I(t),i=e===n;if(r&&!i)return`This directory looks like a Permissions API policy, but --remote-bundle-name is "${e}". Permissions API only loads the remote bundle named "${n}". Upload still succeeds; pass --remote-bundle-name=${n} if that is the intended path.`;if(!r&&i)return`--remote-bundle-name=${n} reserves the Permissions API path. Upload treats all bundles the same; only that fixed name is queried by the Permissions API. Continue only if you intend this bundle for the Permissions API.`}async function R({"remote-bundle-name":n,auth:i,"transcend-url":o,version:s,description:c,json:y,yes:S,debug:C=!1},w){g(this.process),t(C);let T=v(this.logger,y),E=a(this.process.cwd(),w),D=s??F(n),O=u(o,i),k=_({json:y,noInteractive:!1},this.process.stdin.isTTY,this.process.stderr.isTTY),A;try{T.info(x.green(`Building policy bundle from ${E}...`)),A=await M(E);try{let e=b(E,r),t=L(n,l(this.fs.readFileSync(e,`utf8`)));t&&T.warn(x.yellow(t))}catch{}let t=await m(O,n),i;if(t){T.info(x.green(`Uploading new version for bundle "${n}"...`));let e=N({bundlePath:A,version:D,description:c});i=await d(O.post(`v1/policy-engine/policy-bundles/${t}/versions`,{body:e}).json())}else{if(!k&&!S){this.logger.error(x.red(`Cannot create a new bundle in non-interactive or JSON mode; pass --yes to confirm.`)),this.process.exit(1);return}if(!S&&(T.warn(x.yellow(`No policy bundle named "${n}" exists for this organization.`)),!await h({message:`No policy bundle named "${n}" exists. Create a new bundle and upload its first version?`}))){T.info(x.yellow(`Publish cancelled.`));return}T.info(x.green(`Creating bundle "${n}" and uploading first version...`));let e=N({bundlePath:A,version:D,description:c,bundleName:n});i=await d(O.post(`v1/policy-engine/policy-bundles`,{body:e}).json())}f(this.process.stdout,{json:y,data:i,renderTable:()=>p(i.version)}),T.info(x.green(`Policy bundle version uploaded successfully.`));let a=e([`policy`,`activate`],{version:i.version.version,"remote-bundle-name":n});T.info(x.yellow(`Publishing a policy does not activate it. To activate this version, run:\n ${a}`))}finally{A&&this.fs.existsSync(A)&&this.fs.unlinkSync(A)}}export{R as publish};
2
- //# sourceMappingURL=impl-Sx15m6eC2.mjs.map
1
+ import{t as e}from"./buildExamples-BNGtj-DW.mjs";import{r as t}from"./policyEngineCliError-CZrOHhLv.mjs";import{a as n,c as r,g as i,i as a}from"./policy-project-discovery-DTSl0Gfl.mjs";import{r as o,t as s}from"./runOpa-ojIqU1tO.mjs";import{n as c,t as l}from"./policy-bundle-manifest-DbbTXe0u.mjs";import{i as u,n as d,t as f}from"./printResult-Dmwv78e7.mjs";import{t as p}from"./formatPolicyBundleVersionSummary-DCHl1Vhy.mjs";import{n as m}from"./resolveBundleIdByName-D7NUOpLc.mjs";import{n as h}from"./inquirer-jzIQWAvq.mjs";import{t as g}from"./done-input-validation-LiTaCEzF.mjs";import{r as _}from"./prompts-BhXfYD6g.mjs";import{t as v}from"./command-output-BJcDRXNr.mjs";import y,{join as b}from"node:path";import x from"colors";import{spawnSync as S}from"node:child_process";import C from"node:fs";import w from"node:os";import{gunzipSync as T}from"node:zlib";import{MAX_BUNDLE_COMPRESSED_BYTES as E,MAX_BUNDLE_DECOMPRESSED_BYTES as D}from"@transcend-io/utils";import O from"fast-glob";function k(e){let t=O.sync(`**/*.rego`,{cwd:e,onlyFiles:!0,dot:!1}).sort(),n=y.join(e,r),{publishableRegoPaths:i}=c(C.existsSync(n)?C.readFileSync(n,`utf8`):void 0,t.map(t=>({path:t,contents:C.readFileSync(y.join(e,t),`utf8`)})));return{entries:[r,...i]}}async function A(e){let t=y.join(w.tmpdir(),`transcend-policy-bundle-build-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`);try{let{code:n,stderr:r}=await s([`build`,`--ignore`,`*_test.rego`,`-b`,`-o`,t,`.`],{cwd:e});if(n!==0)throw Error(r.trim()||`opa build failed with exit code ${n}`)}finally{C.existsSync(t)&&C.unlinkSync(t)}}function j(e){if(e<1024)return`${e} B`;let t=e/1024;if(t<1024)return`${t%1==0?t.toFixed(0):t.toFixed(1)} KiB`;let n=t/1024;return`${n%1==0?n.toFixed(0):n.toFixed(1)} MiB`}async function M(e){o();let t=y.resolve(e);if(!C.existsSync(t)||!C.statSync(t).isDirectory())throw Error(`Policy directory does not exist or is not a directory: ${t}`);let{entries:n}=k(t),{code:r,stderr:i}=await s([`check`,`--strict`,t]);if(r!==0)throw Error(i.trim()||`opa check failed with exit code ${r}`);await A(t);let a=y.join(w.tmpdir(),`transcend-policy-bundle-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`),c=S(`tar`,[`-czf`,a,`-C`,t,...n],{env:{...process.env,COPYFILE_DISABLE:`1`},encoding:`utf8`});if(c.status!==0)throw Error(`Failed to create policy bundle archive: ${c.stderr.trim()||`tar failed`}`);let l=C.readFileSync(a);if(l.byteLength>E)throw C.unlinkSync(a),Error(`Policy bundle exceeds the ${j(E)} compressed upload limit (bundle is ${j(l.byteLength)}). The server also rejects decompressed bundles larger than ${j(D)}.`);let u=T(l);if(u.byteLength>D)throw C.unlinkSync(a),Error(`Policy bundle exceeds the ${j(D)} decompressed upload limit (bundle is ${j(u.byteLength)} decompressed).`);return a}function N(e){let t=C.readFileSync(e.bundlePath),n=new FormData;return n.append(`bundle`,new Blob([t],{type:`application/gzip`}),y.basename(e.bundlePath)),n.append(`version`,e.version),e.description&&n.append(`description`,e.description),e.bundleName&&n.append(`bundleName`,e.bundleName),n}function P(e){return e.toISOString().slice(0,19).replace(/[T:]/g,`-`)}function F(e,t=new Date){return`${e}-${P(t)}`}function I(e){return e.template===i.Permissions?!0:e.template===i.Generic?!1:e.roots.some(e=>e===`permissions`||e.startsWith(`permissions/`))}function L(e,t){let r=I(t),i=e===n;if(r&&!i)return`This directory looks like a Permissions API policy, but --remote-bundle-name is "${e}". Permissions API only loads the remote bundle named "${n}". Upload still succeeds; pass --remote-bundle-name=${n} if that is the intended path.`;if(!r&&i)return`--remote-bundle-name=${n} reserves the Permissions API path. Upload treats all bundles the same; only that fixed name is queried by the Permissions API. Continue only if you intend this bundle for the Permissions API.`}async function R({"remote-bundle-name":n,auth:i,"transcend-url":o,version:s,description:c,json:y,yes:S,debug:C=!1},w){g(this.process),t(C);let T=v(this.logger,y),E=a(this.process.cwd(),w),D=s??F(n),O=u(o,i),k=_({json:y,noInteractive:!1},this.process.stdin.isTTY,this.process.stderr.isTTY),A;try{T.info(x.green(`Building policy bundle from ${E}...`)),A=await M(E);try{let e=b(E,r),t=L(n,l(this.fs.readFileSync(e,`utf8`)));t&&T.warn(x.yellow(t))}catch{}let t=await m(O,n),i;if(t){T.info(x.green(`Uploading new version for bundle "${n}"...`));let e=N({bundlePath:A,version:D,description:c});i=await d(O.post(`v1/policy-engine/policy-bundles/${t}/versions`,{body:e}).json())}else{if(!k&&!S){this.logger.error(x.red(`Cannot create a new bundle in non-interactive or JSON mode; pass --yes to confirm.`)),this.process.exit(1);return}if(!S&&(T.warn(x.yellow(`No policy bundle named "${n}" exists for this organization.`)),!await h({message:`No policy bundle named "${n}" exists. Create a new bundle and upload its first version?`}))){T.info(x.yellow(`Publish cancelled.`));return}T.info(x.green(`Creating bundle "${n}" and uploading first version...`));let e=N({bundlePath:A,version:D,description:c,bundleName:n});i=await d(O.post(`v1/policy-engine/policy-bundles`,{body:e}).json())}f(this.process.stdout,{json:y,data:i,renderTable:()=>p(i.version)}),T.info(x.green(`Policy bundle version uploaded successfully.`));let a=e([`policy`,`activate`],{version:i.version.version,"remote-bundle-name":n});T.info(x.yellow(`Publishing a policy does not activate it. To activate this version, run:\n ${a}`))}finally{A&&this.fs.existsSync(A)&&this.fs.unlinkSync(A)}}export{R as publish};
2
+ //# sourceMappingURL=impl-D6rMLiNB2.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"impl-Sx15m6eC2.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-D6rMLiNB2.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{g as e}from"./constants-rXUIz6Uy.mjs";import{r as t,t as n}from"./project-plan-output-BHHlkLxe.mjs";import{d as r,f as i,t as a,u as o}from"./project-discovery-CWRjlFnC.mjs";import{S as s,_ as ee,c,h as te,m as l,p as u,r as d,t as f,v as p,x as ne,y as m}from"./policy-project-discovery-_6QosI9J.mjs";import{t as h}from"./done-input-validation-LiTaCEzF.mjs";import{n as g,r as _,t as v}from"./prompts-BhXfYD6g.mjs";import{t as y}from"./project-plan-apply-Bg_1eMX9.mjs";import{a as b,i as x,n as S,o as re,r as ie}from"./policy-scaffold-config-DwZFigj7.mjs";import{join as C,relative as ae,sep as w}from"node:path";import T from"colors";const E=/^[a-z][a-z0-9_]*$/u;function D(e){return e?E.test(e)?e.length>64?`Root name cannot exceed 64 characters.`:!0:`Root name must be lowercase alphanumeric with underscores (e.g. "example", "permissions").`:`Enter a bundle root name.`}async function O(E,O=f){h(this.process);try{let f=d(this,O),h=C(f.targetDirectory,`.regal`,`config.yaml`);if(!this.fs.existsSync(h))throw Error(`No policy workspace found at ${n(f.invocationDirectory,f.targetDirectory)}. Run \`transcend policy init\` first.`);let v=new g(this),k=_(E,this.process.stdin.isTTY,this.process.stderr.isTTY),A=E.template??(k?await v.select(`Template:`,l.map(e=>({name:te[e],value:e})),l[0]):void 0);if(!A||!l.includes(A))throw Error(`Missing policy template. Pass --template=${l.join(` or --template=`)}.`);let j=u[A],M=E.name??(k?await v.text(`Bundle root name:`,j,e=>{let t=D(e);return t===!0?!0:t}):void 0);if(!M)throw Error(`Missing bundle root name. Pass --name in a non-interactive invocation.`);let N=D(M);if(N!==!0)throw Error(N);let P=ee(M),F=E[`bundle-dir`]??(k?await v.text(`Bundle directory name:`,P,e=>{let t=s(e);return t===!0?!0:t}):P),I=s(F);if(I!==!0)throw Error(I);let L=C(f.targetDirectory,F);if(this.fs.existsSync(L))throw Error(`Bundle directory already exists: ${n(f.invocationDirectory,L)}. Choose a different --bundle-dir.`);let R=m(A,M,F),{contents:z,roots:B}=ne(this.fs.readFileSync(h,`utf8`),M),V=B.map(e=>e===M?{root:e,bundleDir:F,template:A}:x(e)),H=[h,...R.map(({path:e})=>C(f.targetDirectory,e))],U=C(f.projectRoot,`.vscode`,`settings.json`),W=C(f.projectRoot,`.vscode`,`tasks.json`),G=this.fs.existsSync(C(f.projectRoot,`.vscode`));G&&H.push(U,W);let K=f.repositoryRoot&&f.usesGithub?C(f.repositoryRoot,b):void 0;K&&this.fs.existsSync(K)&&H.push(K);let q=a(this,f.projectRoot,H.sort((e,t)=>e.localeCompare(t))),J=[],Y=[],X=[],Z=i({snapshot:o(q,h),after:z,description:`Merge ${M} root into Regal config`});if(Z?J.push(Z):X.push(h),R.forEach(e=>{let t=C(f.targetDirectory,e.path);if(r(q,t).kind!==`absent`)throw Error(`Expected an empty path but found an entry at: ${t}`);let n=i({snapshot:o(q,t),after:e.contents,description:e.description});n?J.push(n):X.push(t)}),G){let e=r(q,U);if(e.kind===`file`||e.kind===`absent`){let t=S(e.kind===`file`?e.contents:null,f.projectRoot,f.targetDirectory,V),r=i({snapshot:e.kind===`file`?{path:U,contents:e.contents,mode:e.mode}:{path:U,contents:null},after:t.contents,description:`Merge bundle root into VS Code OPA settings`});r?J.push(r):X.push(U),Y.push(...t.warnings.map(e=>`${e} (${n(f.invocationDirectory,U)})`))}let t=r(q,W);if(t.kind===`file`||t.kind===`absent`){let e=ie(t.kind===`file`?t.contents:null,f.projectRoot,f.targetDirectory,V),r=i({snapshot:t.kind===`file`?{path:W,contents:t.contents,mode:t.mode}:{path:W,contents:null},after:e.contents,description:`Add per-bundle and aggregate lint tasks`});r?J.push(r):X.push(W),Y.push(...e.warnings.map(e=>`${e} (${n(f.invocationDirectory,W)})`))}}if(K&&f.repositoryRoot){let t=r(q,K);if(t.kind===`file`){let r=ae(f.repositoryRoot,f.targetDirectory).split(w).join(`/`)||`.`,a=re({cliVersion:e,workspaceDirectory:r,bundleDirectories:V.map(e=>r===`.`?e.bundleDir:`${r}/${e.bundleDir}`)});if(t.contents.startsWith(`# Generated by transcend policy init`)){let e=i({snapshot:{path:K,contents:t.contents,mode:t.mode},after:a,description:`Update Policy Engine CI matrix for all publish directories`});e?J.push(e):X.push(K)}else Y.push(`Existing GitHub Actions workflow was left unchanged: ${n(f.invocationDirectory,K)}. Adapt it manually to lint each \`*-bundle/\` publish directory.`),X.push(K)}}let oe=p({bundleDirectory:n(f.invocationDirectory,L),root:M,template:A}),Q={rootDirectory:f.projectRoot,targetDirectory:f.targetDirectory,manifestPath:C(L,c),changes:J,unchanged:X,warnings:Y,nextSteps:[oe]};E.json||this.logger.info(t(Q,{cwd:this.process.cwd(),title:`Policy bundle plan`,details:[{label:`Workspace`,path:Q.targetDirectory},{label:`Bundle`,path:L}]}));let $=Q.changes.length===0||E.dryRun;if(Q.changes.length>0&&!E.dryRun)if(E.yes)$=!0;else if(k)$=await v.confirm(`Apply this complete plan?`,!0);else throw Error(`The plan requires approval in a non-interactive invocation. Review with --dryRun, then pass --yes.`);$&&!E.dryRun&&Q.changes.length>0&&await y(this,Q);let se=$&&!E.dryRun&&Q.changes.length>0;if(E.json){this.process.stdout.write(`${JSON.stringify({applied:se,dryRun:E.dryRun,template:A,root:M,bundleDirectory:L,targetDirectory:Q.targetDirectory,manifestPath:Q.manifestPath,changes:Q.changes.map(e=>({kind:e.kind,target:n(this.process.cwd(),e.path),description:e.description})),warnings:Q.warnings,nextSteps:Q.nextSteps})}\n`);return}if(E.dryRun){this.logger.info(T.yellow(`Dry run complete. No changes were written.`));return}if(!$){this.logger.info(T.yellow(`No changes applied.`));return}this.logger.info(T.green(`Policy bundle ${M} added.`)),Q.nextSteps.length>0&&(this.logger.info(`\n${T.bold(`Next steps`)}`),Q.nextSteps.forEach(e=>this.logger.info(e)))}catch(e){throw e instanceof v&&this.process.exit(130),e}}export{O as _new};
2
- //# sourceMappingURL=impl-CbZIfTUK.mjs.map
1
+ import{g as e}from"./constants-FDjw7bPS.mjs";import{r as t,t as n}from"./project-plan-output-BHHlkLxe.mjs";import{d as r,f as i,t as a,u as o}from"./project-discovery-CWRjlFnC.mjs";import{S as s,_ as ee,c,h as te,m as l,p as u,r as d,t as f,v as p,x as ne,y as m}from"./policy-project-discovery-DTSl0Gfl.mjs";import{t as h}from"./done-input-validation-LiTaCEzF.mjs";import{n as g,r as _,t as v}from"./prompts-BhXfYD6g.mjs";import{t as y}from"./project-plan-apply-Bg_1eMX9.mjs";import{a as b,i as x,n as S,o as re,r as ie}from"./policy-scaffold-config-RpxwwZ2H.mjs";import{join as C,relative as ae,sep as w}from"node:path";import T from"colors";const E=/^[a-z][a-z0-9_]*$/u;function D(e){return e?E.test(e)?e.length>64?`Root name cannot exceed 64 characters.`:!0:`Root name must be lowercase alphanumeric with underscores (e.g. "example", "permissions").`:`Enter a bundle root name.`}async function O(E,O=f){h(this.process);try{let f=d(this,O),h=C(f.targetDirectory,`.regal`,`config.yaml`);if(!this.fs.existsSync(h))throw Error(`No policy workspace found at ${n(f.invocationDirectory,f.targetDirectory)}. Run \`transcend policy init\` first.`);let v=new g(this),k=_(E,this.process.stdin.isTTY,this.process.stderr.isTTY),A=E.template??(k?await v.select(`Template:`,l.map(e=>({name:te[e],value:e})),l[0]):void 0);if(!A||!l.includes(A))throw Error(`Missing policy template. Pass --template=${l.join(` or --template=`)}.`);let j=u[A],M=E.name??(k?await v.text(`Bundle root name:`,j,e=>{let t=D(e);return t===!0?!0:t}):void 0);if(!M)throw Error(`Missing bundle root name. Pass --name in a non-interactive invocation.`);let N=D(M);if(N!==!0)throw Error(N);let P=ee(M),F=E[`bundle-dir`]??(k?await v.text(`Bundle directory name:`,P,e=>{let t=s(e);return t===!0?!0:t}):P),I=s(F);if(I!==!0)throw Error(I);let L=C(f.targetDirectory,F);if(this.fs.existsSync(L))throw Error(`Bundle directory already exists: ${n(f.invocationDirectory,L)}. Choose a different --bundle-dir.`);let R=m(A,M,F),{contents:z,roots:B}=ne(this.fs.readFileSync(h,`utf8`),M),V=B.map(e=>e===M?{root:e,bundleDir:F,template:A}:x(e)),H=[h,...R.map(({path:e})=>C(f.targetDirectory,e))],U=C(f.projectRoot,`.vscode`,`settings.json`),W=C(f.projectRoot,`.vscode`,`tasks.json`),G=this.fs.existsSync(C(f.projectRoot,`.vscode`));G&&H.push(U,W);let K=f.repositoryRoot&&f.usesGithub?C(f.repositoryRoot,b):void 0;K&&this.fs.existsSync(K)&&H.push(K);let q=a(this,f.projectRoot,H.sort((e,t)=>e.localeCompare(t))),J=[],Y=[],X=[],Z=i({snapshot:o(q,h),after:z,description:`Merge ${M} root into Regal config`});if(Z?J.push(Z):X.push(h),R.forEach(e=>{let t=C(f.targetDirectory,e.path);if(r(q,t).kind!==`absent`)throw Error(`Expected an empty path but found an entry at: ${t}`);let n=i({snapshot:o(q,t),after:e.contents,description:e.description});n?J.push(n):X.push(t)}),G){let e=r(q,U);if(e.kind===`file`||e.kind===`absent`){let t=S(e.kind===`file`?e.contents:null,f.projectRoot,f.targetDirectory,V),r=i({snapshot:e.kind===`file`?{path:U,contents:e.contents,mode:e.mode}:{path:U,contents:null},after:t.contents,description:`Merge bundle root into VS Code OPA settings`});r?J.push(r):X.push(U),Y.push(...t.warnings.map(e=>`${e} (${n(f.invocationDirectory,U)})`))}let t=r(q,W);if(t.kind===`file`||t.kind===`absent`){let e=ie(t.kind===`file`?t.contents:null,f.projectRoot,f.targetDirectory,V),r=i({snapshot:t.kind===`file`?{path:W,contents:t.contents,mode:t.mode}:{path:W,contents:null},after:e.contents,description:`Add per-bundle and aggregate lint tasks`});r?J.push(r):X.push(W),Y.push(...e.warnings.map(e=>`${e} (${n(f.invocationDirectory,W)})`))}}if(K&&f.repositoryRoot){let t=r(q,K);if(t.kind===`file`){let r=ae(f.repositoryRoot,f.targetDirectory).split(w).join(`/`)||`.`,a=re({cliVersion:e,workspaceDirectory:r,bundleDirectories:V.map(e=>r===`.`?e.bundleDir:`${r}/${e.bundleDir}`)});if(t.contents.startsWith(`# Generated by transcend policy init`)){let e=i({snapshot:{path:K,contents:t.contents,mode:t.mode},after:a,description:`Update Policy Engine CI matrix for all publish directories`});e?J.push(e):X.push(K)}else Y.push(`Existing GitHub Actions workflow was left unchanged: ${n(f.invocationDirectory,K)}. Adapt it manually to lint each \`*-bundle/\` publish directory.`),X.push(K)}}let oe=p({bundleDirectory:n(f.invocationDirectory,L),root:M,template:A}),Q={rootDirectory:f.projectRoot,targetDirectory:f.targetDirectory,manifestPath:C(L,c),changes:J,unchanged:X,warnings:Y,nextSteps:[oe]};E.json||this.logger.info(t(Q,{cwd:this.process.cwd(),title:`Policy bundle plan`,details:[{label:`Workspace`,path:Q.targetDirectory},{label:`Bundle`,path:L}]}));let $=Q.changes.length===0||E.dryRun;if(Q.changes.length>0&&!E.dryRun)if(E.yes)$=!0;else if(k)$=await v.confirm(`Apply this complete plan?`,!0);else throw Error(`The plan requires approval in a non-interactive invocation. Review with --dryRun, then pass --yes.`);$&&!E.dryRun&&Q.changes.length>0&&await y(this,Q);let se=$&&!E.dryRun&&Q.changes.length>0;if(E.json){this.process.stdout.write(`${JSON.stringify({applied:se,dryRun:E.dryRun,template:A,root:M,bundleDirectory:L,targetDirectory:Q.targetDirectory,manifestPath:Q.manifestPath,changes:Q.changes.map(e=>({kind:e.kind,target:n(this.process.cwd(),e.path),description:e.description})),warnings:Q.warnings,nextSteps:Q.nextSteps})}\n`);return}if(E.dryRun){this.logger.info(T.yellow(`Dry run complete. No changes were written.`));return}if(!$){this.logger.info(T.yellow(`No changes applied.`));return}this.logger.info(T.green(`Policy bundle ${M} added.`)),Q.nextSteps.length>0&&(this.logger.info(`\n${T.bold(`Next steps`)}`),Q.nextSteps.forEach(e=>this.logger.info(e)))}catch(e){throw e instanceof v&&this.process.exit(130),e}}export{O as _new};
2
+ //# sourceMappingURL=impl-DDVhG8Gf.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"impl-CbZIfTUK.mjs","names":["CLI_VERSION"],"sources":["../src/commands/policy/new/impl.ts"],"sourcesContent":["import { join, relative, sep } from 'node:path';\n\nimport colors from 'colors';\n\nimport { version as CLI_VERSION } from '../../../constants.js';\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport {\n DEFAULT_POLICY_PROJECT_DIRECTORY,\n discoverPolicyProject,\n} from '../../../lib/policy/policy-project-discovery.js';\nimport {\n generatePolicyGithubActionsWorkflow,\n POLICY_CI_WORKFLOW_PATH,\n} from '../../../lib/policy/policy-scaffold-artifacts.js';\nimport {\n mergePolicyEditorSettings,\n mergePolicyEditorTasks,\n policyBundleRef,\n type PolicyBundleRef,\n} from '../../../lib/policy/policy-scaffold-config.js';\nimport {\n buildBundleDirectoryName,\n buildPolicyBundleEvalNextStep,\n generatePolicyBundleFiles,\n mergePolicyRegalConfigRoots,\n POLICY_MANIFEST_FILENAME,\n POLICY_TEMPLATE_DEFAULT_ROOTS,\n POLICY_TEMPLATE_NAMES,\n POLICY_TEMPLATE_PROMPT_LABELS,\n validateBundleDirectoryName,\n type PolicyTemplateName,\n} from '../../../lib/policy/policy-scaffold-templates.js';\nimport { collectPlanningSnapshots } from '../../../lib/scaffolding/project-discovery.js';\nimport { applyProjectPlan } from '../../../lib/scaffolding/project-plan-apply.js';\nimport {\n displayProjectPath,\n renderProjectPlan,\n} from '../../../lib/scaffolding/project-plan-output.js';\nimport {\n planFileChange,\n getPlanningFileSnapshot,\n getPlanningPathSnapshot,\n type PlannedChange,\n type ProjectPlan,\n} from '../../../lib/scaffolding/project-plan.js';\nimport {\n isInteractivePromptInvocation,\n PromptCancelledError,\n ScaffoldPrompts,\n} from '../../../lib/scaffolding/prompts.js';\n\n/** Flags for `transcend policy new`. */\nexport interface PolicyNewFlags {\n /** Package root name. */\n name?: string;\n /** Local publish directory basename under the workspace. */\n 'bundle-dir'?: string;\n /** Starter template. */\n template?: PolicyTemplateName;\n /** Disable prompts. */\n noInteractive: boolean;\n /** Render but do not apply. */\n dryRun: boolean;\n /** Approve the final displayed plan. */\n yes: boolean;\n /** Emit one stable JSON result on stdout. */\n json: boolean;\n}\n\n/** Validate a bundle root name. */\nconst VALID_ROOT_PATTERN = /^[a-z][a-z0-9_]*$/u;\n\n/**\n * Validate a policy bundle root name.\n *\n * @param value - Proposed root name\n * @returns True or error message\n */\nfunction validateRootName(value: string): true | string {\n if (!value) {\n return 'Enter a bundle root name.';\n }\n if (!VALID_ROOT_PATTERN.test(value)) {\n return 'Root name must be lowercase alphanumeric with underscores (e.g. \"example\", \"permissions\").';\n }\n if (value.length > 64) {\n return 'Root name cannot exceed 64 characters.';\n }\n return true;\n}\n\n/**\n * Scaffold one policy bundle from a template.\n *\n * @param this - CLI context\n * @param flags - Template and interaction flags\n * @param directory - Target policy workspace directory\n */\nexport async function _new(\n this: LocalContext,\n flags: PolicyNewFlags,\n directory: string = DEFAULT_POLICY_PROJECT_DIRECTORY,\n): Promise<void> {\n doneInputValidation(this.process);\n try {\n const state = discoverPolicyProject(this, directory);\n const regalConfigPath = join(state.targetDirectory, '.regal', 'config.yaml');\n\n if (!this.fs.existsSync(regalConfigPath)) {\n throw new Error(\n `No policy workspace found at ${displayProjectPath(\n state.invocationDirectory,\n state.targetDirectory,\n )}. Run \\`transcend policy init\\` first.`,\n );\n }\n\n const prompts = new ScaffoldPrompts(this);\n const interactive = isInteractivePromptInvocation(\n flags,\n this.process.stdin.isTTY,\n this.process.stderr.isTTY,\n );\n\n const template =\n flags.template ??\n (interactive\n ? await prompts.select<PolicyTemplateName>(\n 'Template:',\n POLICY_TEMPLATE_NAMES.map((value) => ({\n name: POLICY_TEMPLATE_PROMPT_LABELS[value],\n value,\n })),\n POLICY_TEMPLATE_NAMES[0],\n )\n : undefined);\n if (!template || !POLICY_TEMPLATE_NAMES.includes(template)) {\n throw new Error(\n `Missing policy template. Pass --template=${POLICY_TEMPLATE_NAMES.join(' or --template=')}.`,\n );\n }\n\n const defaultRoot = POLICY_TEMPLATE_DEFAULT_ROOTS[template];\n const name =\n flags.name ??\n (interactive\n ? await prompts.text('Bundle root name:', defaultRoot, (value) => {\n const result = validateRootName(value);\n return result === true ? true : result;\n })\n : undefined);\n if (!name) {\n throw new Error('Missing bundle root name. Pass --name in a non-interactive invocation.');\n }\n const rootValidation = validateRootName(name);\n if (rootValidation !== true) {\n throw new Error(rootValidation);\n }\n\n const defaultBundleDir = buildBundleDirectoryName(name);\n const bundleDir =\n flags['bundle-dir'] ??\n (interactive\n ? await prompts.text('Bundle directory name:', defaultBundleDir, (value) => {\n const result = validateBundleDirectoryName(value);\n return result === true ? true : result;\n })\n : defaultBundleDir);\n const bundleDirValidation = validateBundleDirectoryName(bundleDir);\n if (bundleDirValidation !== true) {\n throw new Error(bundleDirValidation);\n }\n\n const bundlePath = join(state.targetDirectory, bundleDir);\n if (this.fs.existsSync(bundlePath)) {\n throw new Error(\n `Bundle directory already exists: ${displayProjectPath(\n state.invocationDirectory,\n bundlePath,\n )}. Choose a different --bundle-dir.`,\n );\n }\n\n const files = generatePolicyBundleFiles(template, name, bundleDir);\n const existingRegalContents = this.fs.readFileSync(regalConfigPath, 'utf8');\n const { contents: updatedRegalConfig, roots: allRoots } = mergePolicyRegalConfigRoots(\n existingRegalContents,\n name,\n );\n const bundleRefs: PolicyBundleRef[] = allRoots.map((root) =>\n root === name ? { root, bundleDir, template } : policyBundleRef(root),\n );\n\n const candidatePaths = [\n regalConfigPath,\n ...files.map(({ path }) => join(state.targetDirectory, path)),\n ];\n\n const vscodeSettingsPath = join(state.projectRoot, '.vscode', 'settings.json');\n const vscodeTasksPath = join(state.projectRoot, '.vscode', 'tasks.json');\n const hasVscode = this.fs.existsSync(join(state.projectRoot, '.vscode'));\n if (hasVscode) {\n candidatePaths.push(vscodeSettingsPath, vscodeTasksPath);\n }\n\n const workflowPath =\n state.repositoryRoot && state.usesGithub\n ? join(state.repositoryRoot, POLICY_CI_WORKFLOW_PATH)\n : undefined;\n if (workflowPath && this.fs.existsSync(workflowPath)) {\n candidatePaths.push(workflowPath);\n }\n\n const snapshots = collectPlanningSnapshots(\n this,\n state.projectRoot,\n candidatePaths.sort((a, b) => a.localeCompare(b)),\n );\n\n const changes: PlannedChange[] = [];\n const warnings: string[] = [];\n const unchanged: string[] = [];\n\n const regalChange = planFileChange({\n snapshot: getPlanningFileSnapshot(snapshots, regalConfigPath),\n after: updatedRegalConfig,\n description: `Merge ${name} root into Regal config`,\n });\n if (regalChange) {\n changes.push(regalChange);\n } else {\n unchanged.push(regalConfigPath);\n }\n\n files.forEach((file) => {\n const path = join(state.targetDirectory, file.path);\n const snapshot = getPlanningPathSnapshot(snapshots, path);\n if (snapshot.kind !== 'absent') {\n throw new Error(`Expected an empty path but found an entry at: ${path}`);\n }\n const change = planFileChange({\n snapshot: getPlanningFileSnapshot(snapshots, path),\n after: file.contents,\n description: file.description,\n });\n if (change) {\n changes.push(change);\n } else {\n unchanged.push(path);\n }\n });\n\n if (hasVscode) {\n const settingsSnapshot = getPlanningPathSnapshot(snapshots, vscodeSettingsPath);\n if (settingsSnapshot.kind === 'file' || settingsSnapshot.kind === 'absent') {\n const settingsResult = mergePolicyEditorSettings(\n settingsSnapshot.kind === 'file' ? settingsSnapshot.contents : null,\n state.projectRoot,\n state.targetDirectory,\n bundleRefs,\n );\n const settingsChange = planFileChange({\n snapshot:\n settingsSnapshot.kind === 'file'\n ? {\n path: vscodeSettingsPath,\n contents: settingsSnapshot.contents,\n mode: settingsSnapshot.mode,\n }\n : { path: vscodeSettingsPath, contents: null },\n after: settingsResult.contents,\n description: 'Merge bundle root into VS Code OPA settings',\n });\n if (settingsChange) {\n changes.push(settingsChange);\n } else {\n unchanged.push(vscodeSettingsPath);\n }\n warnings.push(\n ...settingsResult.warnings.map(\n (w) => `${w} (${displayProjectPath(state.invocationDirectory, vscodeSettingsPath)})`,\n ),\n );\n }\n\n const tasksSnapshot = getPlanningPathSnapshot(snapshots, vscodeTasksPath);\n if (tasksSnapshot.kind === 'file' || tasksSnapshot.kind === 'absent') {\n const tasksResult = mergePolicyEditorTasks(\n tasksSnapshot.kind === 'file' ? tasksSnapshot.contents : null,\n state.projectRoot,\n state.targetDirectory,\n bundleRefs,\n );\n const tasksChange = planFileChange({\n snapshot:\n tasksSnapshot.kind === 'file'\n ? {\n path: vscodeTasksPath,\n contents: tasksSnapshot.contents,\n mode: tasksSnapshot.mode,\n }\n : { path: vscodeTasksPath, contents: null },\n after: tasksResult.contents,\n description: 'Add per-bundle and aggregate lint tasks',\n });\n if (tasksChange) {\n changes.push(tasksChange);\n } else {\n unchanged.push(vscodeTasksPath);\n }\n warnings.push(\n ...tasksResult.warnings.map(\n (w) => `${w} (${displayProjectPath(state.invocationDirectory, vscodeTasksPath)})`,\n ),\n );\n }\n }\n\n if (workflowPath && state.repositoryRoot) {\n const workflowSnapshot = getPlanningPathSnapshot(snapshots, workflowPath);\n if (workflowSnapshot.kind === 'file') {\n const workspaceDirectory =\n relative(state.repositoryRoot, state.targetDirectory).split(sep).join('/') || '.';\n const bundleDirectories = bundleRefs.map((bundle) => {\n return workspaceDirectory === '.'\n ? bundle.bundleDir\n : `${workspaceDirectory}/${bundle.bundleDir}`;\n });\n const desiredWorkflow = generatePolicyGithubActionsWorkflow({\n cliVersion: CLI_VERSION,\n workspaceDirectory,\n bundleDirectories,\n });\n if (workflowSnapshot.contents.startsWith('# Generated by transcend policy init')) {\n const workflowChange = planFileChange({\n snapshot: {\n path: workflowPath,\n contents: workflowSnapshot.contents,\n mode: workflowSnapshot.mode,\n },\n after: desiredWorkflow,\n description: 'Update Policy Engine CI matrix for all publish directories',\n });\n if (workflowChange) {\n changes.push(workflowChange);\n } else {\n unchanged.push(workflowPath);\n }\n } else {\n warnings.push(\n `Existing GitHub Actions workflow was left unchanged: ${displayProjectPath(\n state.invocationDirectory,\n workflowPath,\n )}. Adapt it manually to lint each \\`*-bundle/\\` publish directory.`,\n );\n unchanged.push(workflowPath);\n }\n }\n }\n\n const bundleDisplayPath = displayProjectPath(state.invocationDirectory, bundlePath);\n const evalCommand = buildPolicyBundleEvalNextStep({\n bundleDirectory: bundleDisplayPath,\n root: name,\n template,\n });\n\n const plan: ProjectPlan & {\n /** Absolute workspace directory. */\n targetDirectory: string;\n /** Absolute manifest path. */\n manifestPath: string;\n /** Unchanged paths. */\n unchanged: string[];\n /** Non-fatal warnings. */\n warnings: string[];\n /** Follow-up commands. */\n nextSteps: string[];\n } = {\n rootDirectory: state.projectRoot,\n targetDirectory: state.targetDirectory,\n manifestPath: join(bundlePath, POLICY_MANIFEST_FILENAME),\n changes,\n unchanged,\n warnings,\n nextSteps: [evalCommand],\n };\n\n if (!flags.json) {\n this.logger.info(\n renderProjectPlan(plan, {\n cwd: this.process.cwd(),\n title: 'Policy bundle plan',\n details: [\n { label: 'Workspace', path: plan.targetDirectory },\n { label: 'Bundle', path: bundlePath },\n ],\n }),\n );\n }\n\n let approved = plan.changes.length === 0 || flags.dryRun;\n if (plan.changes.length > 0 && !flags.dryRun) {\n if (flags.yes) {\n approved = true;\n } else if (interactive) {\n approved = await prompts.confirm('Apply this complete plan?', true);\n } else {\n throw new Error(\n 'The plan requires approval in a non-interactive invocation. Review with --dryRun, then pass --yes.',\n );\n }\n }\n\n if (approved && !flags.dryRun && plan.changes.length > 0) {\n await applyProjectPlan(this, plan);\n }\n const applied = approved && !flags.dryRun && plan.changes.length > 0;\n\n if (flags.json) {\n this.process.stdout.write(\n `${JSON.stringify({\n applied,\n dryRun: flags.dryRun,\n template,\n root: name,\n bundleDirectory: bundlePath,\n targetDirectory: plan.targetDirectory,\n manifestPath: plan.manifestPath,\n changes: plan.changes.map((change) => ({\n kind: change.kind,\n target: displayProjectPath(this.process.cwd(), change.path),\n description: change.description,\n })),\n warnings: plan.warnings,\n nextSteps: plan.nextSteps,\n })}\\n`,\n );\n return;\n }\n if (flags.dryRun) {\n this.logger.info(colors.yellow('Dry run complete. No changes were written.'));\n return;\n }\n if (!approved) {\n this.logger.info(colors.yellow('No changes applied.'));\n return;\n }\n this.logger.info(colors.green(`Policy bundle ${name} added.`));\n if (plan.nextSteps.length > 0) {\n this.logger.info(`\\n${colors.bold('Next steps')}`);\n plan.nextSteps.forEach((step) => this.logger.info(step));\n }\n } catch (error) {\n if (error instanceof PromptCancelledError) {\n this.process.exit(130);\n }\n throw error;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"impl-DDVhG8Gf.mjs","names":["CLI_VERSION"],"sources":["../src/commands/policy/new/impl.ts"],"sourcesContent":["import { join, relative, sep } from 'node:path';\n\nimport colors from 'colors';\n\nimport { version as CLI_VERSION } from '../../../constants.js';\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport {\n DEFAULT_POLICY_PROJECT_DIRECTORY,\n discoverPolicyProject,\n} from '../../../lib/policy/policy-project-discovery.js';\nimport {\n generatePolicyGithubActionsWorkflow,\n POLICY_CI_WORKFLOW_PATH,\n} from '../../../lib/policy/policy-scaffold-artifacts.js';\nimport {\n mergePolicyEditorSettings,\n mergePolicyEditorTasks,\n policyBundleRef,\n type PolicyBundleRef,\n} from '../../../lib/policy/policy-scaffold-config.js';\nimport {\n buildBundleDirectoryName,\n buildPolicyBundleEvalNextStep,\n generatePolicyBundleFiles,\n mergePolicyRegalConfigRoots,\n POLICY_MANIFEST_FILENAME,\n POLICY_TEMPLATE_DEFAULT_ROOTS,\n POLICY_TEMPLATE_NAMES,\n POLICY_TEMPLATE_PROMPT_LABELS,\n validateBundleDirectoryName,\n type PolicyTemplateName,\n} from '../../../lib/policy/policy-scaffold-templates.js';\nimport { collectPlanningSnapshots } from '../../../lib/scaffolding/project-discovery.js';\nimport { applyProjectPlan } from '../../../lib/scaffolding/project-plan-apply.js';\nimport {\n displayProjectPath,\n renderProjectPlan,\n} from '../../../lib/scaffolding/project-plan-output.js';\nimport {\n planFileChange,\n getPlanningFileSnapshot,\n getPlanningPathSnapshot,\n type PlannedChange,\n type ProjectPlan,\n} from '../../../lib/scaffolding/project-plan.js';\nimport {\n isInteractivePromptInvocation,\n PromptCancelledError,\n ScaffoldPrompts,\n} from '../../../lib/scaffolding/prompts.js';\n\n/** Flags for `transcend policy new`. */\nexport interface PolicyNewFlags {\n /** Package root name. */\n name?: string;\n /** Local publish directory basename under the workspace. */\n 'bundle-dir'?: string;\n /** Starter template. */\n template?: PolicyTemplateName;\n /** Disable prompts. */\n noInteractive: boolean;\n /** Render but do not apply. */\n dryRun: boolean;\n /** Approve the final displayed plan. */\n yes: boolean;\n /** Emit one stable JSON result on stdout. */\n json: boolean;\n}\n\n/** Validate a bundle root name. */\nconst VALID_ROOT_PATTERN = /^[a-z][a-z0-9_]*$/u;\n\n/**\n * Validate a policy bundle root name.\n *\n * @param value - Proposed root name\n * @returns True or error message\n */\nfunction validateRootName(value: string): true | string {\n if (!value) {\n return 'Enter a bundle root name.';\n }\n if (!VALID_ROOT_PATTERN.test(value)) {\n return 'Root name must be lowercase alphanumeric with underscores (e.g. \"example\", \"permissions\").';\n }\n if (value.length > 64) {\n return 'Root name cannot exceed 64 characters.';\n }\n return true;\n}\n\n/**\n * Scaffold one policy bundle from a template.\n *\n * @param this - CLI context\n * @param flags - Template and interaction flags\n * @param directory - Target policy workspace directory\n */\nexport async function _new(\n this: LocalContext,\n flags: PolicyNewFlags,\n directory: string = DEFAULT_POLICY_PROJECT_DIRECTORY,\n): Promise<void> {\n doneInputValidation(this.process);\n try {\n const state = discoverPolicyProject(this, directory);\n const regalConfigPath = join(state.targetDirectory, '.regal', 'config.yaml');\n\n if (!this.fs.existsSync(regalConfigPath)) {\n throw new Error(\n `No policy workspace found at ${displayProjectPath(\n state.invocationDirectory,\n state.targetDirectory,\n )}. Run \\`transcend policy init\\` first.`,\n );\n }\n\n const prompts = new ScaffoldPrompts(this);\n const interactive = isInteractivePromptInvocation(\n flags,\n this.process.stdin.isTTY,\n this.process.stderr.isTTY,\n );\n\n const template =\n flags.template ??\n (interactive\n ? await prompts.select<PolicyTemplateName>(\n 'Template:',\n POLICY_TEMPLATE_NAMES.map((value) => ({\n name: POLICY_TEMPLATE_PROMPT_LABELS[value],\n value,\n })),\n POLICY_TEMPLATE_NAMES[0],\n )\n : undefined);\n if (!template || !POLICY_TEMPLATE_NAMES.includes(template)) {\n throw new Error(\n `Missing policy template. Pass --template=${POLICY_TEMPLATE_NAMES.join(' or --template=')}.`,\n );\n }\n\n const defaultRoot = POLICY_TEMPLATE_DEFAULT_ROOTS[template];\n const name =\n flags.name ??\n (interactive\n ? await prompts.text('Bundle root name:', defaultRoot, (value) => {\n const result = validateRootName(value);\n return result === true ? true : result;\n })\n : undefined);\n if (!name) {\n throw new Error('Missing bundle root name. Pass --name in a non-interactive invocation.');\n }\n const rootValidation = validateRootName(name);\n if (rootValidation !== true) {\n throw new Error(rootValidation);\n }\n\n const defaultBundleDir = buildBundleDirectoryName(name);\n const bundleDir =\n flags['bundle-dir'] ??\n (interactive\n ? await prompts.text('Bundle directory name:', defaultBundleDir, (value) => {\n const result = validateBundleDirectoryName(value);\n return result === true ? true : result;\n })\n : defaultBundleDir);\n const bundleDirValidation = validateBundleDirectoryName(bundleDir);\n if (bundleDirValidation !== true) {\n throw new Error(bundleDirValidation);\n }\n\n const bundlePath = join(state.targetDirectory, bundleDir);\n if (this.fs.existsSync(bundlePath)) {\n throw new Error(\n `Bundle directory already exists: ${displayProjectPath(\n state.invocationDirectory,\n bundlePath,\n )}. Choose a different --bundle-dir.`,\n );\n }\n\n const files = generatePolicyBundleFiles(template, name, bundleDir);\n const existingRegalContents = this.fs.readFileSync(regalConfigPath, 'utf8');\n const { contents: updatedRegalConfig, roots: allRoots } = mergePolicyRegalConfigRoots(\n existingRegalContents,\n name,\n );\n const bundleRefs: PolicyBundleRef[] = allRoots.map((root) =>\n root === name ? { root, bundleDir, template } : policyBundleRef(root),\n );\n\n const candidatePaths = [\n regalConfigPath,\n ...files.map(({ path }) => join(state.targetDirectory, path)),\n ];\n\n const vscodeSettingsPath = join(state.projectRoot, '.vscode', 'settings.json');\n const vscodeTasksPath = join(state.projectRoot, '.vscode', 'tasks.json');\n const hasVscode = this.fs.existsSync(join(state.projectRoot, '.vscode'));\n if (hasVscode) {\n candidatePaths.push(vscodeSettingsPath, vscodeTasksPath);\n }\n\n const workflowPath =\n state.repositoryRoot && state.usesGithub\n ? join(state.repositoryRoot, POLICY_CI_WORKFLOW_PATH)\n : undefined;\n if (workflowPath && this.fs.existsSync(workflowPath)) {\n candidatePaths.push(workflowPath);\n }\n\n const snapshots = collectPlanningSnapshots(\n this,\n state.projectRoot,\n candidatePaths.sort((a, b) => a.localeCompare(b)),\n );\n\n const changes: PlannedChange[] = [];\n const warnings: string[] = [];\n const unchanged: string[] = [];\n\n const regalChange = planFileChange({\n snapshot: getPlanningFileSnapshot(snapshots, regalConfigPath),\n after: updatedRegalConfig,\n description: `Merge ${name} root into Regal config`,\n });\n if (regalChange) {\n changes.push(regalChange);\n } else {\n unchanged.push(regalConfigPath);\n }\n\n files.forEach((file) => {\n const path = join(state.targetDirectory, file.path);\n const snapshot = getPlanningPathSnapshot(snapshots, path);\n if (snapshot.kind !== 'absent') {\n throw new Error(`Expected an empty path but found an entry at: ${path}`);\n }\n const change = planFileChange({\n snapshot: getPlanningFileSnapshot(snapshots, path),\n after: file.contents,\n description: file.description,\n });\n if (change) {\n changes.push(change);\n } else {\n unchanged.push(path);\n }\n });\n\n if (hasVscode) {\n const settingsSnapshot = getPlanningPathSnapshot(snapshots, vscodeSettingsPath);\n if (settingsSnapshot.kind === 'file' || settingsSnapshot.kind === 'absent') {\n const settingsResult = mergePolicyEditorSettings(\n settingsSnapshot.kind === 'file' ? settingsSnapshot.contents : null,\n state.projectRoot,\n state.targetDirectory,\n bundleRefs,\n );\n const settingsChange = planFileChange({\n snapshot:\n settingsSnapshot.kind === 'file'\n ? {\n path: vscodeSettingsPath,\n contents: settingsSnapshot.contents,\n mode: settingsSnapshot.mode,\n }\n : { path: vscodeSettingsPath, contents: null },\n after: settingsResult.contents,\n description: 'Merge bundle root into VS Code OPA settings',\n });\n if (settingsChange) {\n changes.push(settingsChange);\n } else {\n unchanged.push(vscodeSettingsPath);\n }\n warnings.push(\n ...settingsResult.warnings.map(\n (w) => `${w} (${displayProjectPath(state.invocationDirectory, vscodeSettingsPath)})`,\n ),\n );\n }\n\n const tasksSnapshot = getPlanningPathSnapshot(snapshots, vscodeTasksPath);\n if (tasksSnapshot.kind === 'file' || tasksSnapshot.kind === 'absent') {\n const tasksResult = mergePolicyEditorTasks(\n tasksSnapshot.kind === 'file' ? tasksSnapshot.contents : null,\n state.projectRoot,\n state.targetDirectory,\n bundleRefs,\n );\n const tasksChange = planFileChange({\n snapshot:\n tasksSnapshot.kind === 'file'\n ? {\n path: vscodeTasksPath,\n contents: tasksSnapshot.contents,\n mode: tasksSnapshot.mode,\n }\n : { path: vscodeTasksPath, contents: null },\n after: tasksResult.contents,\n description: 'Add per-bundle and aggregate lint tasks',\n });\n if (tasksChange) {\n changes.push(tasksChange);\n } else {\n unchanged.push(vscodeTasksPath);\n }\n warnings.push(\n ...tasksResult.warnings.map(\n (w) => `${w} (${displayProjectPath(state.invocationDirectory, vscodeTasksPath)})`,\n ),\n );\n }\n }\n\n if (workflowPath && state.repositoryRoot) {\n const workflowSnapshot = getPlanningPathSnapshot(snapshots, workflowPath);\n if (workflowSnapshot.kind === 'file') {\n const workspaceDirectory =\n relative(state.repositoryRoot, state.targetDirectory).split(sep).join('/') || '.';\n const bundleDirectories = bundleRefs.map((bundle) => {\n return workspaceDirectory === '.'\n ? bundle.bundleDir\n : `${workspaceDirectory}/${bundle.bundleDir}`;\n });\n const desiredWorkflow = generatePolicyGithubActionsWorkflow({\n cliVersion: CLI_VERSION,\n workspaceDirectory,\n bundleDirectories,\n });\n if (workflowSnapshot.contents.startsWith('# Generated by transcend policy init')) {\n const workflowChange = planFileChange({\n snapshot: {\n path: workflowPath,\n contents: workflowSnapshot.contents,\n mode: workflowSnapshot.mode,\n },\n after: desiredWorkflow,\n description: 'Update Policy Engine CI matrix for all publish directories',\n });\n if (workflowChange) {\n changes.push(workflowChange);\n } else {\n unchanged.push(workflowPath);\n }\n } else {\n warnings.push(\n `Existing GitHub Actions workflow was left unchanged: ${displayProjectPath(\n state.invocationDirectory,\n workflowPath,\n )}. Adapt it manually to lint each \\`*-bundle/\\` publish directory.`,\n );\n unchanged.push(workflowPath);\n }\n }\n }\n\n const bundleDisplayPath = displayProjectPath(state.invocationDirectory, bundlePath);\n const evalCommand = buildPolicyBundleEvalNextStep({\n bundleDirectory: bundleDisplayPath,\n root: name,\n template,\n });\n\n const plan: ProjectPlan & {\n /** Absolute workspace directory. */\n targetDirectory: string;\n /** Absolute manifest path. */\n manifestPath: string;\n /** Unchanged paths. */\n unchanged: string[];\n /** Non-fatal warnings. */\n warnings: string[];\n /** Follow-up commands. */\n nextSteps: string[];\n } = {\n rootDirectory: state.projectRoot,\n targetDirectory: state.targetDirectory,\n manifestPath: join(bundlePath, POLICY_MANIFEST_FILENAME),\n changes,\n unchanged,\n warnings,\n nextSteps: [evalCommand],\n };\n\n if (!flags.json) {\n this.logger.info(\n renderProjectPlan(plan, {\n cwd: this.process.cwd(),\n title: 'Policy bundle plan',\n details: [\n { label: 'Workspace', path: plan.targetDirectory },\n { label: 'Bundle', path: bundlePath },\n ],\n }),\n );\n }\n\n let approved = plan.changes.length === 0 || flags.dryRun;\n if (plan.changes.length > 0 && !flags.dryRun) {\n if (flags.yes) {\n approved = true;\n } else if (interactive) {\n approved = await prompts.confirm('Apply this complete plan?', true);\n } else {\n throw new Error(\n 'The plan requires approval in a non-interactive invocation. Review with --dryRun, then pass --yes.',\n );\n }\n }\n\n if (approved && !flags.dryRun && plan.changes.length > 0) {\n await applyProjectPlan(this, plan);\n }\n const applied = approved && !flags.dryRun && plan.changes.length > 0;\n\n if (flags.json) {\n this.process.stdout.write(\n `${JSON.stringify({\n applied,\n dryRun: flags.dryRun,\n template,\n root: name,\n bundleDirectory: bundlePath,\n targetDirectory: plan.targetDirectory,\n manifestPath: plan.manifestPath,\n changes: plan.changes.map((change) => ({\n kind: change.kind,\n target: displayProjectPath(this.process.cwd(), change.path),\n description: change.description,\n })),\n warnings: plan.warnings,\n nextSteps: plan.nextSteps,\n })}\\n`,\n );\n return;\n }\n if (flags.dryRun) {\n this.logger.info(colors.yellow('Dry run complete. No changes were written.'));\n return;\n }\n if (!approved) {\n this.logger.info(colors.yellow('No changes applied.'));\n return;\n }\n this.logger.info(colors.green(`Policy bundle ${name} added.`));\n if (plan.nextSteps.length > 0) {\n this.logger.info(`\\n${colors.bold('Next steps')}`);\n plan.nextSteps.forEach((step) => this.logger.info(step));\n }\n } catch (error) {\n if (error instanceof PromptCancelledError) {\n this.process.exit(130);\n }\n throw error;\n }\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{t as e}from"./streamPrivacyRequestsToCsv-BWmN5fl6.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-Y4CI9YNK.mjs.map
1
+ import{t as e}from"./streamPrivacyRequestsToCsv-BApu4dvI.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-DFnWzZyY.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"impl-Y4CI9YNK.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
+ {"version":3,"file":"impl-DFnWzZyY.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"./collectCsvFilesOrExit-BindZ0dF.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";import{n,r,t as i}from"./createPoolingCommandUi-BsU6e0Ov.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-hDN-9GZo.mjs.map
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-BdtnLBBM.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-DGtCNANL.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"impl-hDN-9GZo.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
+ {"version":3,"file":"impl-DGtCNANL.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,3 +1,3 @@
1
- import{c as e,i as t,n,t as r}from"./policy-project-discovery-_6QosI9J.mjs";import{c as i,i as a,l as o,o as s,s as c}from"./policy-runtime-6jmkXlBk.mjs";import{n as l}from"./policy-bundle-manifest-CDbVx8E6.mjs";import{n as u}from"./inquirer-jzIQWAvq.mjs";import{t as d}from"./done-input-validation-LiTaCEzF.mjs";import{r as f}from"./prompts-BhXfYD6g.mjs";import{t as p}from"./run-captured-process-BjaSDWXG.mjs";import m from"node:path";import h from"colors";const g=[`manifest`,`opa-version`,`regal-version`,`format`,`opa-check`,`regal-lint`,`opa-test`],_={manifest:`Manifest and package roots`,"opa-version":`OPA 1.x`,"regal-version":`Regal`,format:`OPA formatting`,"opa-check":`OPA strict check`,"regal-lint":`Regal lint`,"opa-test":`OPA tests`};function v(e,t){return[e.stdout.trim(),e.stderr.trim()].filter(Boolean).join(`
1
+ import{c as e,i as t,n,t as r}from"./policy-project-discovery-DTSl0Gfl.mjs";import{c as i,i as a,l as o,o as s,s as c}from"./policy-runtime-6jmkXlBk.mjs";import{n as l}from"./policy-bundle-manifest-DbbTXe0u.mjs";import{n as u}from"./inquirer-jzIQWAvq.mjs";import{t as d}from"./done-input-validation-LiTaCEzF.mjs";import{r as f}from"./prompts-BhXfYD6g.mjs";import{t as p}from"./run-captured-process-BjaSDWXG.mjs";import m from"node:path";import h from"colors";const g=[`manifest`,`opa-version`,`regal-version`,`format`,`opa-check`,`regal-lint`,`opa-test`],_={manifest:`Manifest and package roots`,"opa-version":`OPA 1.x`,"regal-version":`Regal`,format:`OPA formatting`,"opa-check":`OPA strict check`,"regal-lint":`Regal lint`,"opa-test":`OPA tests`};function v(e,t){return[e.stdout.trim(),e.stderr.trim()].filter(Boolean).join(`
2
2
  `)||t}function y(e,t){return[...new Set(e.split(/\r?\n/gu).map(e=>e.trim()).filter(Boolean).map(e=>m.isAbsolute(e)?m.relative(t,e).split(m.sep).join(`/`):e.split(m.sep).join(`/`)))].sort()}function b(e,t,n=t){return e.fs.readdirSync(n,{withFileTypes:!0}).sort((e,t)=>e.name.localeCompare(t.name)).flatMap(r=>{let i=m.join(n,r.name);return r.isDirectory()?b(e,t,i):!r.isFile()||!r.name.endsWith(`.rego`)?[]:[{path:m.relative(t,i).split(m.sep).join(`/`),contents:e.fs.readFileSync(i,`utf8`)}]})}function x(e,t){let n=t;for(;;){let t=m.join(n,`.regal`,`config.yaml`);if(e.fs.existsSync(t))return t;let r=m.join(n,`.regal.yaml`);if(e.fs.existsSync(r))return r;let i=m.dirname(n);if(i===n)return;n=i}}function S(e,t,n){n?e.logger.info(`${h.bold(n)}\n`):e.logger.info(`${h.bold(`Policy verification`)}\n`),t.checks.forEach(({name:n,status:r})=>{let i=r===`passed`?`PASS`:r===`failed`?`FAIL`:`SKIP`,a=r===`passed`?h.green(i):r===`failed`?h.red(i):h.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} ${_[n]}${o}`)}),t.diagnostics.length>0&&e.logger.error(``),t.diagnostics.forEach(t=>{let n=t.path?`${t.path}: `:``;e.logger.error(h.red(`error [${t.code}]: ${n}${t.message}`))}),t.status===`passed`?(e.logger.info(``),e.logger.info(h.green(`Policy verification passed.`))):(e.logger.error(``),e.logger.error(h.red(`Policy verification failed.`)))}async function C({fix:t,noInteractive:n,json:r},d,p){let _=g.map(e=>({name:e,status:`skipped`})),S=[],C={version:1,status:`passed`,directory:d,fix:t,tools:{opa:null,regal:null},checks:_,unformattedFiles:[],fixedFiles:[],diagnostics:S},w=(e,t)=>{_.find(t=>t.name===e).status=t},T=(e,t,n)=>{S.push({code:e,severity:`error`,message:t,...n?{path:n}:{}})};if(!this.fs.existsSync(d)||!this.fs.statSync(d).isDirectory())return w(`manifest`,`failed`),T(`project.directory`,`Policy directory does not exist or is not a directory: ${d}`,m.relative(this.process.cwd(),d)),C.status=`failed`,C;let E=m.join(d,e);try{l(this.fs.existsSync(E)?this.fs.readFileSync(E,`utf8`):void 0,b(this,d)),w(`manifest`,`passed`)}catch(e){w(`manifest`,`failed`),T(`manifest.invalid`,e instanceof Error?e.message:String(e),m.relative(this.process.cwd(),E))}let D=await p(`opa`,[`version`],{cwd:d},this);if(D.error?.code===`ENOENT`)w(`opa-version`,`failed`),T(`opa.missing`,a);else{let e=`${D.stdout}\n${D.stderr}`,t=i(e);D.code!==0||t?(w(`opa-version`,`failed`),T(`opa.version`,t??v(D,`Unable to determine the installed OPA version.`))):(C.tools.opa=c(e).version,w(`opa-version`,`passed`))}let O=await p(`regal`,[`version`],{cwd:d},this);if(O.error?.code===`ENOENT`)w(`regal-version`,`failed`),T(`regal.missing`,s);else{let e=`${O.stdout}\n${O.stderr}`,t=o(e);O.code!==0||t?(w(`regal-version`,`failed`),T(`regal.version`,t??v(O,`Unable to determine the installed Regal version.`))):(C.tools.regal=c(e).version,w(`regal-version`,`passed`))}if(C.tools.opa){let e=await p(`opa`,[`fmt`,`--list`,d],{cwd:d},this);if(e.code!==0)w(`format`,`failed`),T(`opa.format`,v(e,`opa fmt --list failed with exit code ${e.code}`));else if(C.unformattedFiles=y(e.stdout,d),C.unformattedFiles.length===0)w(`format`,`passed`);else{let e=t,i=f({json:r,noInteractive:n},this.process.stdin.isTTY,this.process.stderr.isTTY);if(!r&&!t){this.logger.error(h.red(`Policy files are not formatted:`)),C.unformattedFiles.forEach(e=>{this.logger.error(h.red(` - ${e}`))});let e=await p(`opa`,[`fmt`,`--diff`,d],{cwd:d},this),t=e.stdout.trim()||e.stderr.trim();t&&(this.logger.error(``),this.logger.error(t))}if(!t&&i)try{e=await u({message:`Format the unformatted policy files listed above?`})}catch(e){let t=e instanceof Error?e.message:String(e);throw/force closed|prompt.*cancel|user.*close|SIGINT/iu.test(t)&&this.process.exit(130),e}if(e){let e=await p(`opa`,[`fmt`,`--write`,d],{cwd:d},this);e.code===0?(C.fixedFiles=[...C.unformattedFiles],w(`format`,`passed`)):(w(`format`,`failed`),T(`opa.format-fix`,v(e,`opa fmt --write failed with exit code ${e.code}`)))}else w(`format`,`failed`),T(`opa.format-required`,"Policy files are not formatted. Re-run `transcend policy lint --fix` to repair them.")}let i=await p(`opa`,[`check`,`--strict`,`--ignore`,`*_test.rego`,d],{cwd:d},this);i.code===0?w(`opa-check`,`passed`):(w(`opa-check`,`failed`),T(`opa.check`,v(i,`opa check failed with exit code ${i.code}`)))}if(C.tools.regal){let e=x(this,d),t=await p(`regal`,[`lint`,`--fail-level`,`warning`,...e?[`--config-file`,e]:[],d],{cwd:d},this);t.code===0?w(`regal-lint`,`passed`):(w(`regal-lint`,`failed`),T(`regal.lint`,v(t,`regal lint failed with exit code ${t.code}`)))}if(C.tools.opa){let e=await p(`opa`,[`test`,`--fail-on-empty`,`-b`,d],{cwd:d},this);e.code===0?w(`opa-test`,`passed`):(w(`opa-test`,`failed`),T(`opa.test`,v(e,`opa test --fail-on-empty -b failed with exit code ${e.code}`)))}return C.status=_.some(({status:e})=>e===`failed`)?`failed`:`passed`,C}async function w(e,i=r,a=p){d(this.process);let{fix:o=!1,noInteractive:s=!1,json:c=!1}=e,l=t(this.process.cwd(),i);if(!this.fs.existsSync(l)||!this.fs.statSync(l).isDirectory()){let e={version:1,status:`failed`,directory:l,fix:o,tools:{opa:null,regal:null},checks:g.map(e=>({name:e,status:e===`manifest`?`failed`:`skipped`})),unformattedFiles:[],fixedFiles:[],diagnostics:[{code:`project.directory`,severity:`error`,message:`Policy directory does not exist or is not a directory: ${l}`,path:m.relative(this.process.cwd(),l)}]};c?this.process.stdout.write(`${JSON.stringify(e)}\n`):S(this,e),this.process.exitCode=1;return}let u=n(this,l);if(u.length===0){let e={version:1,status:`failed`,directory:l,fix:o,tools:{opa:null,regal:null},checks:g.map(e=>({name:e,status:e===`manifest`?`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:m.relative(this.process.cwd(),l)||`.`}]};c?this.process.stdout.write(`${JSON.stringify(e)}\n`):S(this,e),this.process.exitCode=1;return}let f=[];for(let e of u)f.push(await C.call(this,{fix:o,noInteractive:s,json:c},e,a));let h=f.some(e=>e.status===`failed`);if(c)if(f.length===1)this.process.stdout.write(`${JSON.stringify(f[0])}\n`);else{let e={version:2,status:h?`failed`:`passed`,directory:l,fix:o,results:f};this.process.stdout.write(`${JSON.stringify(e)}\n`)}else f.length===1?S(this,f[0]):f.forEach((e,t)=>{t>0&&this.logger.info(``);let n=m.relative(this.process.cwd(),e.directory)||e.directory;S(this,e,`Policy verification — ${n}`)});h&&(this.process.exitCode=1)}export{w as lint};
3
- //# sourceMappingURL=impl-CNU3pgwh.mjs.map
3
+ //# sourceMappingURL=impl-DNOgBcsu.mjs.map