@transcend-io/cli 12.0.0 → 12.1.0

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 (201) hide show
  1. package/README.md +160 -149
  2. package/dist/{app-CR3U95JW.mjs → app-CfJlhIn8.mjs} +18 -18
  3. package/dist/app-CfJlhIn8.mjs.map +1 -0
  4. package/dist/{approvePrivacyRequests-BDG82nlp.mjs → approvePrivacyRequests-BWj6SsgX.mjs} +2 -2
  5. package/dist/{approvePrivacyRequests-BDG82nlp.mjs.map → approvePrivacyRequests-BWj6SsgX.mjs.map} +1 -1
  6. package/dist/bin/bash-complete.mjs +1 -1
  7. package/dist/bin/cli.mjs +1 -1
  8. package/dist/bin/deprecated-command.mjs +1 -1
  9. package/dist/buildExamples-1I3xKR1X.mjs +2 -0
  10. package/dist/buildExamples-1I3xKR1X.mjs.map +1 -0
  11. package/dist/{buildXdiSyncEndpoint-FExEagKc.mjs → buildXdiSyncEndpoint-CAal3Xc4.mjs} +2 -2
  12. package/dist/{buildXdiSyncEndpoint-FExEagKc.mjs.map → buildXdiSyncEndpoint-CAal3Xc4.mjs.map} +1 -1
  13. package/dist/{bulkRestartRequests-OKwKXc52.mjs → bulkRestartRequests-B3wupylo.mjs} +2 -2
  14. package/dist/{bulkRestartRequests-OKwKXc52.mjs.map → bulkRestartRequests-B3wupylo.mjs.map} +1 -1
  15. package/dist/{bulkRetryEnrichers-Dl-n8AFF.mjs → bulkRetryEnrichers-D801tBcB.mjs} +2 -2
  16. package/dist/{bulkRetryEnrichers-Dl-n8AFF.mjs.map → bulkRetryEnrichers-D801tBcB.mjs.map} +1 -1
  17. package/dist/{cancelPrivacyRequests-BIgX5SDz.mjs → cancelPrivacyRequests-CAKTZF47.mjs} +2 -2
  18. package/dist/{cancelPrivacyRequests-BIgX5SDz.mjs.map → cancelPrivacyRequests-CAKTZF47.mjs.map} +1 -1
  19. package/dist/{command-X7lkPELf.mjs → command-BDQOL_MQ.mjs} +2 -2
  20. package/dist/{command-X7lkPELf.mjs.map → command-BDQOL_MQ.mjs.map} +1 -1
  21. package/dist/{constants-BRsj50Nb.mjs → constants-BlKpAm3R.mjs} +2 -2
  22. package/dist/{constants-BRsj50Nb.mjs.map → constants-BlKpAm3R.mjs.map} +1 -1
  23. package/dist/{createPoolingCommandUi-CyPZ3GqN.mjs → createPoolingCommandUi-JBOW5UxY.mjs} +2 -2
  24. package/dist/{createPoolingCommandUi-CyPZ3GqN.mjs.map → createPoolingCommandUi-JBOW5UxY.mjs.map} +1 -1
  25. package/dist/{downloadPrivacyRequestFiles-EBySRnvd.mjs → downloadPrivacyRequestFiles-Cf14MQR4.mjs} +2 -2
  26. package/dist/{downloadPrivacyRequestFiles-EBySRnvd.mjs.map → downloadPrivacyRequestFiles-Cf14MQR4.mjs.map} +1 -1
  27. package/dist/{generateCrossAccountApiKeys-pWTrIUE6.mjs → generateCrossAccountApiKeys-CVdsJFOe.mjs} +2 -2
  28. package/dist/{generateCrossAccountApiKeys-pWTrIUE6.mjs.map → generateCrossAccountApiKeys-CVdsJFOe.mjs.map} +1 -1
  29. package/dist/{impl-1SsreZWo.mjs → impl-2sYR_UFO.mjs} +2 -2
  30. package/dist/{impl-1SsreZWo.mjs.map → impl-2sYR_UFO.mjs.map} +1 -1
  31. package/dist/impl-B-Oe7DcE2.mjs +421 -0
  32. package/dist/{impl-DQcgEx7V2.mjs.map → impl-B-Oe7DcE2.mjs.map} +1 -1
  33. package/dist/{impl-CspH2ZWx.mjs → impl-BD03bzB-.mjs} +2 -2
  34. package/dist/{impl-CspH2ZWx.mjs.map → impl-BD03bzB-.mjs.map} +1 -1
  35. package/dist/{impl-CrdqsTUy.mjs → impl-BGtup1F9.mjs} +2 -2
  36. package/dist/{impl-CrdqsTUy.mjs.map → impl-BGtup1F9.mjs.map} +1 -1
  37. package/dist/impl-BQRP9NIv.mjs +2 -0
  38. package/dist/impl-BQRP9NIv.mjs.map +1 -0
  39. package/dist/{impl-CWP6AXSb.mjs → impl-BQe6vddz.mjs} +2 -2
  40. package/dist/{impl-CWP6AXSb.mjs.map → impl-BQe6vddz.mjs.map} +1 -1
  41. package/dist/{impl-B440iuvL.mjs → impl-BQj1Ien4.mjs} +3 -3
  42. package/dist/{impl-B440iuvL.mjs.map → impl-BQj1Ien4.mjs.map} +1 -1
  43. package/dist/{impl-CU38kdj8.mjs → impl-BRFL8xp7.mjs} +2 -2
  44. package/dist/{impl-CU38kdj8.mjs.map → impl-BRFL8xp7.mjs.map} +1 -1
  45. package/dist/{impl-eeS2lVi5.mjs → impl-BTvZxws5.mjs} +2 -2
  46. package/dist/{impl-eeS2lVi5.mjs.map → impl-BTvZxws5.mjs.map} +1 -1
  47. package/dist/{impl-D1UogVAq.mjs → impl-BVcy_GYa.mjs} +2 -2
  48. package/dist/{impl-D1UogVAq.mjs.map → impl-BVcy_GYa.mjs.map} +1 -1
  49. package/dist/{impl-vmLq6HCI.mjs → impl-B_CRtRo8.mjs} +2 -2
  50. package/dist/{impl-vmLq6HCI.mjs.map → impl-B_CRtRo8.mjs.map} +1 -1
  51. package/dist/{impl-7rdGuHOC.mjs → impl-BgD7TeMD.mjs} +2 -2
  52. package/dist/{impl-7rdGuHOC.mjs.map → impl-BgD7TeMD.mjs.map} +1 -1
  53. package/dist/{impl-BdTxFv63.mjs → impl-BgkovGOz.mjs} +2 -2
  54. package/dist/{impl-BdTxFv63.mjs.map → impl-BgkovGOz.mjs.map} +1 -1
  55. package/dist/{impl-Do2TNA3-.mjs → impl-Bh02zrTq.mjs} +2 -2
  56. package/dist/{impl-Do2TNA3-.mjs.map → impl-Bh02zrTq.mjs.map} +1 -1
  57. package/dist/{impl-HUfaARep.mjs → impl-BopWGXnH.mjs} +2 -2
  58. package/dist/{impl-HUfaARep.mjs.map → impl-BopWGXnH.mjs.map} +1 -1
  59. package/dist/{impl-iD6Fknfe.mjs → impl-BxvKe9_7.mjs} +2 -2
  60. package/dist/{impl-iD6Fknfe.mjs.map → impl-BxvKe9_7.mjs.map} +1 -1
  61. package/dist/{impl-DtnYcktN.mjs → impl-BzIyVAg_.mjs} +2 -2
  62. package/dist/{impl-DtnYcktN.mjs.map → impl-BzIyVAg_.mjs.map} +1 -1
  63. package/dist/{impl-Cxprr2hw.mjs → impl-C-PvYlFE.mjs} +2 -2
  64. package/dist/{impl-Cxprr2hw.mjs.map → impl-C-PvYlFE.mjs.map} +1 -1
  65. package/dist/impl-C36c5NfN.mjs +2 -0
  66. package/dist/impl-C36c5NfN.mjs.map +1 -0
  67. package/dist/{impl-B7l4bLG5.mjs → impl-CC-yFYWt.mjs} +2 -2
  68. package/dist/{impl-B7l4bLG5.mjs.map → impl-CC-yFYWt.mjs.map} +1 -1
  69. package/dist/{impl-CudSYx-g.mjs → impl-CFB_508q.mjs} +2 -2
  70. package/dist/{impl-CudSYx-g.mjs.map → impl-CFB_508q.mjs.map} +1 -1
  71. package/dist/{impl-DxQ9yj3H.mjs → impl-CG3f4B6u.mjs} +2 -2
  72. package/dist/{impl-DxQ9yj3H.mjs.map → impl-CG3f4B6u.mjs.map} +1 -1
  73. package/dist/{impl-DqHEIzpj.mjs → impl-CVUD-7mJ.mjs} +5 -5
  74. package/dist/{impl-DqHEIzpj.mjs.map → impl-CVUD-7mJ.mjs.map} +1 -1
  75. package/dist/{impl-BWPPVXG3.mjs → impl-CoqCyj7e.mjs} +3 -3
  76. package/dist/{impl-BWPPVXG3.mjs.map → impl-CoqCyj7e.mjs.map} +1 -1
  77. package/dist/{impl-BLQDgwxL.mjs → impl-Cq-GARM1.mjs} +2 -2
  78. package/dist/{impl-BLQDgwxL.mjs.map → impl-Cq-GARM1.mjs.map} +1 -1
  79. package/dist/{impl-DQG1pMzD2.mjs → impl-Cvyc-iTI2.mjs} +2 -2
  80. package/dist/{impl-DQG1pMzD2.mjs.map → impl-Cvyc-iTI2.mjs.map} +1 -1
  81. package/dist/impl-CwBa15M42.mjs +3 -0
  82. package/dist/impl-CwBa15M42.mjs.map +1 -0
  83. package/dist/{impl-CieztjdM.mjs → impl-D3gqip90.mjs} +2 -2
  84. package/dist/{impl-CieztjdM.mjs.map → impl-D3gqip90.mjs.map} +1 -1
  85. package/dist/{impl-DcL-8NEa2.mjs → impl-D6Lzwd-R2.mjs} +2 -2
  86. package/dist/{impl-DcL-8NEa2.mjs.map → impl-D6Lzwd-R2.mjs.map} +1 -1
  87. package/dist/impl-DG-041kN.mjs +3 -0
  88. package/dist/impl-DG-041kN.mjs.map +1 -0
  89. package/dist/{impl-DXbxO2VJ.mjs → impl-DTvnDByz.mjs} +2 -2
  90. package/dist/{impl-DXbxO2VJ.mjs.map → impl-DTvnDByz.mjs.map} +1 -1
  91. package/dist/{impl-Ds-gQfdc.mjs → impl-DUg1sDwg.mjs} +2 -2
  92. package/dist/{impl-Ds-gQfdc.mjs.map → impl-DUg1sDwg.mjs.map} +1 -1
  93. package/dist/{impl-B2ZXtnpX.mjs → impl-DldrBJEa.mjs} +2 -2
  94. package/dist/{impl-B2ZXtnpX.mjs.map → impl-DldrBJEa.mjs.map} +1 -1
  95. package/dist/{impl-D-a5xGld.mjs → impl-Dmn1CWts.mjs} +3 -3
  96. package/dist/{impl-D-a5xGld.mjs.map → impl-Dmn1CWts.mjs.map} +1 -1
  97. package/dist/impl-Dr9Jezjh2.mjs +2 -0
  98. package/dist/impl-Dr9Jezjh2.mjs.map +1 -0
  99. package/dist/{impl-DRKPx_I9.mjs → impl-DtTfsHtL.mjs} +2 -2
  100. package/dist/{impl-DRKPx_I9.mjs.map → impl-DtTfsHtL.mjs.map} +1 -1
  101. package/dist/{impl-FerHBNJx2.mjs → impl-DzNEfRoS2.mjs} +2 -2
  102. package/dist/{impl-FerHBNJx2.mjs.map → impl-DzNEfRoS2.mjs.map} +1 -1
  103. package/dist/{impl-wBcVYHlA.mjs → impl-HnrcGt_T.mjs} +2 -2
  104. package/dist/{impl-wBcVYHlA.mjs.map → impl-HnrcGt_T.mjs.map} +1 -1
  105. package/dist/{impl-D1f9mJL_.mjs → impl-QdSegO65.mjs} +2 -2
  106. package/dist/{impl-D1f9mJL_.mjs.map → impl-QdSegO65.mjs.map} +1 -1
  107. package/dist/{impl-C_Ifcb00.mjs → impl-S90NUBGm.mjs} +2 -2
  108. package/dist/{impl-C_Ifcb00.mjs.map → impl-S90NUBGm.mjs.map} +1 -1
  109. package/dist/{impl-DtpgD_as.mjs → impl-Tr08dgdk.mjs} +2 -2
  110. package/dist/{impl-DtpgD_as.mjs.map → impl-Tr08dgdk.mjs.map} +1 -1
  111. package/dist/{impl-Cb42aI60.mjs → impl-WJBuS_0m.mjs} +2 -2
  112. package/dist/{impl-Cb42aI60.mjs.map → impl-WJBuS_0m.mjs.map} +1 -1
  113. package/dist/{impl-DiwxYcux.mjs → impl-b4KAEVci.mjs} +2 -2
  114. package/dist/{impl-DiwxYcux.mjs.map → impl-b4KAEVci.mjs.map} +1 -1
  115. package/dist/impl-defjX-97.mjs +3 -0
  116. package/dist/impl-defjX-97.mjs.map +1 -0
  117. package/dist/{impl-DTadLabu.mjs → impl-fg0UZYw6.mjs} +2 -2
  118. package/dist/{impl-DTadLabu.mjs.map → impl-fg0UZYw6.mjs.map} +1 -1
  119. package/dist/{impl-Dr_l_SLd.mjs → impl-hRK54juc.mjs} +2 -2
  120. package/dist/{impl-Dr_l_SLd.mjs.map → impl-hRK54juc.mjs.map} +1 -1
  121. package/dist/{impl-DJcNhpbx.mjs → impl-mjDxMEDR.mjs} +2 -2
  122. package/dist/{impl-DJcNhpbx.mjs.map → impl-mjDxMEDR.mjs.map} +1 -1
  123. package/dist/index.d.mts +1 -1
  124. package/dist/index.mjs +2 -2
  125. package/dist/{markRequestDataSiloIdsCompleted-BYNMCkhy.mjs → markRequestDataSiloIdsCompleted-C6lV_My-.mjs} +2 -2
  126. package/dist/{markRequestDataSiloIdsCompleted-BYNMCkhy.mjs.map → markRequestDataSiloIdsCompleted-C6lV_My-.mjs.map} +1 -1
  127. package/dist/{markSilentPrivacyRequests-gKYivzH1.mjs → markSilentPrivacyRequests-D3bFOMLh.mjs} +2 -2
  128. package/dist/{markSilentPrivacyRequests-gKYivzH1.mjs.map → markSilentPrivacyRequests-D3bFOMLh.mjs.map} +1 -1
  129. package/dist/{mergeTranscendInputs-D1CvxQu0.mjs → mergeTranscendInputs-B7WjxYMN.mjs} +3 -3
  130. package/dist/{mergeTranscendInputs-D1CvxQu0.mjs.map → mergeTranscendInputs-B7WjxYMN.mjs.map} +1 -1
  131. package/dist/{notifyPrivacyRequestsAdditionalTime-DbERhQ1Q.mjs → notifyPrivacyRequestsAdditionalTime-BGUxsWLN.mjs} +2 -2
  132. package/dist/{notifyPrivacyRequestsAdditionalTime-DbERhQ1Q.mjs.map → notifyPrivacyRequestsAdditionalTime-BGUxsWLN.mjs.map} +1 -1
  133. package/dist/{policy-bundle-manifest-BZnBMZQq.mjs → policy-bundle-manifest-RgsjPnfI.mjs} +3 -3
  134. package/dist/{policy-bundle-manifest-BZnBMZQq.mjs.map → policy-bundle-manifest-RgsjPnfI.mjs.map} +1 -1
  135. package/dist/{policy-project-discovery-C29UxWwt.mjs → policy-project-discovery-B4cFXUlA.mjs} +71 -68
  136. package/dist/policy-project-discovery-B4cFXUlA.mjs.map +1 -0
  137. package/dist/policy-scaffold-config-CwlygiTz.mjs +76 -0
  138. package/dist/policy-scaffold-config-CwlygiTz.mjs.map +1 -0
  139. package/dist/printResult-Dmwv78e7.mjs +33 -0
  140. package/dist/printResult-Dmwv78e7.mjs.map +1 -0
  141. package/dist/{pullAllDatapoints-Bm-Orhse.mjs → pullAllDatapoints-CNqQSSmF.mjs} +3 -3
  142. package/dist/{pullAllDatapoints-Bm-Orhse.mjs.map → pullAllDatapoints-CNqQSSmF.mjs.map} +1 -1
  143. package/dist/pullChunkedCustomSiloOutstandingIdentifiers-BfNNWqeI.mjs +2 -0
  144. package/dist/{pullChunkedCustomSiloOutstandingIdentifiers-DTGQOw--.mjs.map → pullChunkedCustomSiloOutstandingIdentifiers-BfNNWqeI.mjs.map} +1 -1
  145. package/dist/{pullManualEnrichmentIdentifiersToCsv-DMC5CQtE.mjs → pullManualEnrichmentIdentifiersToCsv-B_lWa6Yg.mjs} +2 -2
  146. package/dist/{pullManualEnrichmentIdentifiersToCsv-DMC5CQtE.mjs.map → pullManualEnrichmentIdentifiersToCsv-B_lWa6Yg.mjs.map} +1 -1
  147. package/dist/{pushCronIdentifiersFromCsv-DhS2z8IG.mjs → pushCronIdentifiersFromCsv-CDhlEf6n.mjs} +2 -2
  148. package/dist/{pushCronIdentifiersFromCsv-DhS2z8IG.mjs.map → pushCronIdentifiersFromCsv-CDhlEf6n.mjs.map} +1 -1
  149. package/dist/pushManualEnrichmentIdentifiersFromCsv-Bn_028w5.mjs +2 -0
  150. package/dist/{pushManualEnrichmentIdentifiersFromCsv-BTJGOmdU.mjs.map → pushManualEnrichmentIdentifiersFromCsv-Bn_028w5.mjs.map} +1 -1
  151. package/dist/{removeUnverifiedRequestIdentifiers-BkAcUZZN.mjs → removeUnverifiedRequestIdentifiers-DcI9ut4q.mjs} +2 -2
  152. package/dist/{removeUnverifiedRequestIdentifiers-BkAcUZZN.mjs.map → removeUnverifiedRequestIdentifiers-DcI9ut4q.mjs.map} +1 -1
  153. package/dist/resolveBundleIdByName-BPrMkU0w.mjs +2 -0
  154. package/dist/resolveBundleIdByName-BPrMkU0w.mjs.map +1 -0
  155. package/dist/resolvePolicyBundleVersion-BrVz4LKN.mjs +2 -0
  156. package/dist/resolvePolicyBundleVersion-BrVz4LKN.mjs.map +1 -0
  157. package/dist/{retryRequestDataSilos-BoPmcB8-.mjs → retryRequestDataSilos-ZdY2PM0S.mjs} +2 -2
  158. package/dist/{retryRequestDataSilos-BoPmcB8-.mjs.map → retryRequestDataSilos-ZdY2PM0S.mjs.map} +1 -1
  159. package/dist/{skipPreflightJobs-DkBdYw-r.mjs → skipPreflightJobs-KdcSw8Td.mjs} +2 -2
  160. package/dist/{skipPreflightJobs-DkBdYw-r.mjs.map → skipPreflightJobs-KdcSw8Td.mjs.map} +1 -1
  161. package/dist/{skipRequestDataSilos-BRFiokix.mjs → skipRequestDataSilos-Cy2NfP47.mjs} +2 -2
  162. package/dist/{skipRequestDataSilos-BRFiokix.mjs.map → skipRequestDataSilos-Cy2NfP47.mjs.map} +1 -1
  163. package/dist/{streamPrivacyRequestsToCsv-Bt-H5J-y.mjs → streamPrivacyRequestsToCsv-ByRBG8Mb.mjs} +2 -2
  164. package/dist/{streamPrivacyRequestsToCsv-Bt-H5J-y.mjs.map → streamPrivacyRequestsToCsv-ByRBG8Mb.mjs.map} +1 -1
  165. package/dist/{syncCodePackages-CPkEukDm.mjs → syncCodePackages-DJnrcX5l.mjs} +2 -2
  166. package/dist/{syncCodePackages-CPkEukDm.mjs.map → syncCodePackages-DJnrcX5l.mjs.map} +1 -1
  167. package/dist/updateConsentManagerVersionToLatest-KwMaAkwh.mjs +2 -0
  168. package/dist/{updateConsentManagerVersionToLatest-DWblAwus.mjs.map → updateConsentManagerVersionToLatest-KwMaAkwh.mjs.map} +1 -1
  169. package/dist/{uploadConsents-D7Vg8ZRW.mjs → uploadConsents-C5LmI-9T.mjs} +2 -2
  170. package/dist/{uploadConsents-D7Vg8ZRW.mjs.map → uploadConsents-C5LmI-9T.mjs.map} +1 -1
  171. package/dist/{uploadPrivacyRequestsFromCsv-B_hQwIn6.mjs → uploadPrivacyRequestsFromCsv-BsYnCgbl.mjs} +2 -2
  172. package/dist/{uploadPrivacyRequestsFromCsv-B_hQwIn6.mjs.map → uploadPrivacyRequestsFromCsv-BsYnCgbl.mjs.map} +1 -1
  173. package/package.json +4 -4
  174. package/dist/app-CR3U95JW.mjs.map +0 -1
  175. package/dist/buildExamples-B6BdW0FD.mjs +0 -2
  176. package/dist/buildExamples-B6BdW0FD.mjs.map +0 -1
  177. package/dist/impl-BqTMPbwc2.mjs +0 -2
  178. package/dist/impl-BqTMPbwc2.mjs.map +0 -1
  179. package/dist/impl-CAoIp9Nl2.mjs +0 -3
  180. package/dist/impl-CAoIp9Nl2.mjs.map +0 -1
  181. package/dist/impl-Cee7Q1Ne.mjs +0 -2
  182. package/dist/impl-Cee7Q1Ne.mjs.map +0 -1
  183. package/dist/impl-DQcgEx7V2.mjs +0 -298
  184. package/dist/impl-DezV3QMo.mjs +0 -3
  185. package/dist/impl-DezV3QMo.mjs.map +0 -1
  186. package/dist/impl-btKJ1-VJ.mjs +0 -3
  187. package/dist/impl-btKJ1-VJ.mjs.map +0 -1
  188. package/dist/impl-ijoNwhGI.mjs +0 -2
  189. package/dist/impl-ijoNwhGI.mjs.map +0 -1
  190. package/dist/policy-project-discovery-C29UxWwt.mjs.map +0 -1
  191. package/dist/policy-scaffold-config-BUKAyPad.mjs +0 -76
  192. package/dist/policy-scaffold-config-BUKAyPad.mjs.map +0 -1
  193. package/dist/printResult-C2K9ODeE.mjs +0 -33
  194. package/dist/printResult-C2K9ODeE.mjs.map +0 -1
  195. package/dist/pullChunkedCustomSiloOutstandingIdentifiers-DTGQOw--.mjs +0 -2
  196. package/dist/pushManualEnrichmentIdentifiersFromCsv-BTJGOmdU.mjs +0 -2
  197. package/dist/resolveBundleIdByName-Dm_o5_bg.mjs +0 -2
  198. package/dist/resolveBundleIdByName-Dm_o5_bg.mjs.map +0 -1
  199. package/dist/resolvePolicyBundleVersion-DRUwe7fA.mjs +0 -2
  200. package/dist/resolvePolicyBundleVersion-DRUwe7fA.mjs.map +0 -1
  201. package/dist/updateConsentManagerVersionToLatest-DWblAwus.mjs +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"impl-CspH2ZWx.mjs","names":[],"sources":["../src/commands/request/cron/pull-identifiers/impl.ts"],"sourcesContent":["import { RequestAction } from '@transcend-io/privacy-types';\nimport colors from 'colors';\nimport { uniq } from 'lodash-es';\n\nimport type { LocalContext } from '../../../../context.js';\nimport { doneInputValidation } from '../../../../lib/cli/done-input-validation.js';\nimport {\n CsvFormattedIdentifier,\n pullChunkedCustomSiloOutstandingIdentifiers,\n} from '../../../../lib/cron/index.js';\nimport { parseFilePath, writeLargeCsv } from '../../../../lib/helpers/index.js';\n\nexport interface PullIdentifiersCommandFlags {\n file: string;\n transcendUrl: string;\n auth: string;\n sombraAuth?: string;\n dataSiloId: string;\n actions: RequestAction[];\n pageLimit: number;\n skipRequestCount: boolean;\n chunkSize: number;\n}\n\nexport async function pullIdentifiers(\n this: LocalContext,\n {\n file,\n transcendUrl,\n auth,\n sombraAuth,\n dataSiloId,\n actions,\n pageLimit,\n skipRequestCount,\n chunkSize,\n }: PullIdentifiersCommandFlags,\n): Promise<void> {\n if (skipRequestCount) {\n this.logger.info(\n colors.yellow('Skipping request count as requested. This may help speed up the call.'),\n );\n }\n\n if (Number.isNaN(chunkSize) || chunkSize <= 0 || chunkSize % pageLimit !== 0) {\n this.logger.error(\n colors.red(\n `Invalid chunk size: \"${chunkSize}\". Must be a positive integer that is a multiple of ${pageLimit}.`,\n ),\n );\n this.process.exit(1);\n }\n\n doneInputValidation(this.process);\n\n const { baseName, extension } = parseFilePath(file);\n let fileCount = 0;\n\n const onSave = async (chunk: CsvFormattedIdentifier[]): Promise<void> => {\n const numberedFileName = `${baseName}-${fileCount}${extension}`;\n this.logger.info(\n colors.blue(`Saving ${chunk.length} identifiers to file \"${numberedFileName}\"`),\n );\n\n const headers = uniq(chunk.map((d) => Object.keys(d)).flat());\n await writeLargeCsv(numberedFileName, chunk, headers);\n this.logger.info(\n colors.green(`Successfully wrote ${chunk.length} identifiers to file \"${numberedFileName}\"`),\n );\n fileCount += 1;\n return Promise.resolve();\n };\n\n // Pull down outstanding identifiers\n await pullChunkedCustomSiloOutstandingIdentifiers({\n transcendUrl,\n apiPageSize: pageLimit,\n savePageSize: chunkSize,\n onSave,\n actions,\n auth,\n sombraAuth,\n dataSiloId,\n skipRequestCount,\n });\n}\n"],"mappings":"kPAwBA,eAAsB,EAEpB,CACE,OACA,eACA,OACA,aACA,aACA,UACA,YACA,mBACA,aAEa,CACX,GACF,KAAK,OAAO,KACV,EAAO,OAAO,wEAAwE,CACvF,EAGC,OAAO,MAAM,EAAU,EAAI,GAAa,GAAK,EAAY,IAAc,KACzE,KAAK,OAAO,MACV,EAAO,IACL,wBAAwB,EAAU,sDAAsD,EAAU,GACnG,CACF,CACD,KAAK,QAAQ,KAAK,EAAE,EAGtB,EAAoB,KAAK,QAAQ,CAEjC,GAAM,CAAE,WAAU,aAAc,EAAc,EAAK,CAC/C,EAAY,EAkBhB,MAAM,EAA4C,CAChD,eACA,YAAa,EACb,aAAc,EACd,YApBoB,IAAmD,CACvE,IAAM,EAAmB,GAAG,EAAS,GAAG,IAAY,IAWpD,OAVA,KAAK,OAAO,KACV,EAAO,KAAK,UAAU,EAAM,OAAO,wBAAwB,EAAiB,GAAG,CAChF,CAGD,MAAM,EAAc,EAAkB,EADtB,EAAK,EAAM,IAAK,GAAM,OAAO,KAAK,EAAE,CAAC,CAAC,MAAM,CACR,CAAC,CACrD,KAAK,OAAO,KACV,EAAO,MAAM,sBAAsB,EAAM,OAAO,wBAAwB,EAAiB,GAAG,CAC7F,CACD,GAAa,EACN,QAAQ,SAAS,EASxB,UACA,OACA,aACA,aACA,mBACD,CAAC"}
1
+ {"version":3,"file":"impl-BD03bzB-.mjs","names":[],"sources":["../src/commands/request/cron/pull-identifiers/impl.ts"],"sourcesContent":["import { RequestAction } from '@transcend-io/privacy-types';\nimport colors from 'colors';\nimport { uniq } from 'lodash-es';\n\nimport type { LocalContext } from '../../../../context.js';\nimport { doneInputValidation } from '../../../../lib/cli/done-input-validation.js';\nimport {\n CsvFormattedIdentifier,\n pullChunkedCustomSiloOutstandingIdentifiers,\n} from '../../../../lib/cron/index.js';\nimport { parseFilePath, writeLargeCsv } from '../../../../lib/helpers/index.js';\n\nexport interface PullIdentifiersCommandFlags {\n file: string;\n transcendUrl: string;\n auth: string;\n sombraAuth?: string;\n dataSiloId: string;\n actions: RequestAction[];\n pageLimit: number;\n skipRequestCount: boolean;\n chunkSize: number;\n}\n\nexport async function pullIdentifiers(\n this: LocalContext,\n {\n file,\n transcendUrl,\n auth,\n sombraAuth,\n dataSiloId,\n actions,\n pageLimit,\n skipRequestCount,\n chunkSize,\n }: PullIdentifiersCommandFlags,\n): Promise<void> {\n if (skipRequestCount) {\n this.logger.info(\n colors.yellow('Skipping request count as requested. This may help speed up the call.'),\n );\n }\n\n if (Number.isNaN(chunkSize) || chunkSize <= 0 || chunkSize % pageLimit !== 0) {\n this.logger.error(\n colors.red(\n `Invalid chunk size: \"${chunkSize}\". Must be a positive integer that is a multiple of ${pageLimit}.`,\n ),\n );\n this.process.exit(1);\n }\n\n doneInputValidation(this.process);\n\n const { baseName, extension } = parseFilePath(file);\n let fileCount = 0;\n\n const onSave = async (chunk: CsvFormattedIdentifier[]): Promise<void> => {\n const numberedFileName = `${baseName}-${fileCount}${extension}`;\n this.logger.info(\n colors.blue(`Saving ${chunk.length} identifiers to file \"${numberedFileName}\"`),\n );\n\n const headers = uniq(chunk.map((d) => Object.keys(d)).flat());\n await writeLargeCsv(numberedFileName, chunk, headers);\n this.logger.info(\n colors.green(`Successfully wrote ${chunk.length} identifiers to file \"${numberedFileName}\"`),\n );\n fileCount += 1;\n return Promise.resolve();\n };\n\n // Pull down outstanding identifiers\n await pullChunkedCustomSiloOutstandingIdentifiers({\n transcendUrl,\n apiPageSize: pageLimit,\n savePageSize: chunkSize,\n onSave,\n actions,\n auth,\n sombraAuth,\n dataSiloId,\n skipRequestCount,\n });\n}\n"],"mappings":"kPAwBA,eAAsB,EAEpB,CACE,OACA,eACA,OACA,aACA,aACA,UACA,YACA,mBACA,aAEa,CACX,GACF,KAAK,OAAO,KACV,EAAO,OAAO,wEAAwE,CACvF,EAGC,OAAO,MAAM,EAAU,EAAI,GAAa,GAAK,EAAY,IAAc,KACzE,KAAK,OAAO,MACV,EAAO,IACL,wBAAwB,EAAU,sDAAsD,EAAU,GACnG,CACF,CACD,KAAK,QAAQ,KAAK,EAAE,EAGtB,EAAoB,KAAK,QAAQ,CAEjC,GAAM,CAAE,WAAU,aAAc,EAAc,EAAK,CAC/C,EAAY,EAkBhB,MAAM,EAA4C,CAChD,eACA,YAAa,EACb,aAAc,EACd,YApBoB,IAAmD,CACvE,IAAM,EAAmB,GAAG,EAAS,GAAG,IAAY,IAWpD,OAVA,KAAK,OAAO,KACV,EAAO,KAAK,UAAU,EAAM,OAAO,wBAAwB,EAAiB,GAAG,CAChF,CAGD,MAAM,EAAc,EAAkB,EADtB,EAAK,EAAM,IAAK,GAAM,OAAO,KAAK,EAAE,CAAC,CAAC,MAAM,CACR,CAAC,CACrD,KAAK,OAAO,KACV,EAAO,MAAM,sBAAsB,EAAM,OAAO,wBAAwB,EAAiB,GAAG,CAC7F,CACD,GAAa,EACN,QAAQ,SAAS,EASxB,UACA,OACA,aACA,aACA,mBACD,CAAC"}
@@ -1,2 +1,2 @@
1
- import{t as e}from"./collectParquetFilesOrExit-CbNQ9CJc.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";import{n,r,t as i}from"./createPoolingCommandUi-CyPZ3GqN.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,concurrency:m,viewerMode:h}=n,g=i(this,p,h),_=e(r,this),{poolSize:v,cpuCount:y}=c(m,_.length);this.logger.info(a.green(`Converting ${_.length} Parquet file(s) → CSV with pool size ${v} (CPU=${y})`));let b=_.map(e=>({filePath:e,options:{outputDir:d,clearOutputDir:f}}));await u({title:`Parquet → CSV - ${r}`,baseDir:r||d||this.process.cwd(),childFlag:o,childModulePath:l(import.meta.url,`commands/admin/parquet-to-csv/worker.mjs`),poolSize:v,cpuCount:y,filesTotal:_.length,hooks:{nextTask:()=>b.shift(),taskLabel:e=>e.filePath,initTotals:()=>({}),initSlotProgress:()=>void 0,onProgress:e=>e,onResult:(e,t)=>({totals:e,ok:!!t.ok}),postProcess:async()=>{}},viewerMode:h,...g}).catch(e=>{throw e instanceof s&&this.process.exit(130),e})}export{m as parquetToCsv};
2
- //# sourceMappingURL=impl-CrdqsTUy.mjs.map
1
+ import{t as e}from"./collectParquetFilesOrExit-CbNQ9CJc.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";import{n,r,t as i}from"./createPoolingCommandUi-JBOW5UxY.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,concurrency:m,viewerMode:h}=n,g=i(this,p,h),_=e(r,this),{poolSize:v,cpuCount:y}=c(m,_.length);this.logger.info(a.green(`Converting ${_.length} Parquet file(s) → CSV with pool size ${v} (CPU=${y})`));let b=_.map(e=>({filePath:e,options:{outputDir:d,clearOutputDir:f}}));await u({title:`Parquet → CSV - ${r}`,baseDir:r||d||this.process.cwd(),childFlag:o,childModulePath:l(import.meta.url,`commands/admin/parquet-to-csv/worker.mjs`),poolSize:v,cpuCount:y,filesTotal:_.length,hooks:{nextTask:()=>b.shift(),taskLabel:e=>e.filePath,initTotals:()=>({}),initSlotProgress:()=>void 0,onProgress:e=>e,onResult:(e,t)=>({totals:e,ok:!!t.ok}),postProcess:async()=>{}},viewerMode:h,...g}).catch(e=>{throw e instanceof s&&this.process.exit(130),e})}export{m as parquetToCsv};
2
+ //# sourceMappingURL=impl-BGtup1F9.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"impl-CrdqsTUy.mjs","names":[],"sources":["../src/commands/admin/parquet-to-csv/ui/plugin.ts","../src/commands/admin/parquet-to-csv/impl.ts"],"sourcesContent":["import {\n makeHeader,\n makeWorkerRows,\n type ChunkSlotProgress,\n type CommonCtx,\n type DashboardPlugin,\n} from '../../../../lib/pooling/index.js';\n\n/**\n * Header for parquet-to-csv (no extra totals block).\n *\n * @param ctx - Dashboard context.\n * @returns Header lines.\n */\nfunction renderHeader<TTotals>(ctx: CommonCtx<TTotals, ChunkSlotProgress>): string[] {\n // no extra lines — reuse the shared header as-is\n return makeHeader(ctx);\n}\n\n/**\n * Worker rows for parquet-to-csv — share the generic row renderer.\n *\n * @param ctx - Dashboard context.\n * @returns Array of strings, each representing one worker row.\n */\nfunction renderWorkers<TTotals>(ctx: CommonCtx<TTotals, ChunkSlotProgress>): string[] {\n return makeWorkerRows(ctx);\n}\n\nexport const parquetToCsvPlugin: DashboardPlugin<unknown, ChunkSlotProgress> = {\n renderHeader,\n renderWorkers,\n // no extras\n};\n","import {\n CHILD_FLAG,\n type PoolHooks,\n runPool,\n computePoolSize,\n PoolCancelledError,\n resolveWorkerPath,\n} from '@transcend-io/utils';\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { collectParquetFilesOrExit } from '../../../lib/helpers/index.js';\nimport { createPoolingCommandUi } from '../../../lib/pooling/index.js';\nimport { parquetToCsvPlugin } from './ui/index.js';\nimport type { ParquetProgress, ParquetResult, ParquetTask } from './worker.js';\n\n/** No custom totals for the header; the runner’s built-ins suffice. */\ntype Totals = Record<string, never>;\n\nexport type ParquetToCsvCommandFlags = {\n directory: string;\n outputDir?: string;\n clearOutputDir: boolean;\n concurrency?: number;\n viewerMode: boolean;\n};\n\n/**\n * Convert all Parquet files in a directory to CSV, in parallel.\n *\n * @param flags - The command flags.\n */\nexport async function parquetToCsv(\n this: LocalContext,\n flags: ParquetToCsvCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n const { directory, outputDir, clearOutputDir, concurrency, viewerMode } = flags;\n const poolingUi = createPoolingCommandUi(this, parquetToCsvPlugin, viewerMode);\n\n /* 1) Discover .parquet inputs */\n const files = collectParquetFilesOrExit(directory, this);\n\n /* 2) Size the pool */\n const { poolSize, cpuCount } = computePoolSize(concurrency, files.length);\n\n this.logger.info(\n colors.green(\n `Converting ${files.length} Parquet file(s) → CSV with pool size ${poolSize} (CPU=${cpuCount})`,\n ),\n );\n\n /* 3) Build FIFO queue of tasks (one per file) */\n const queue = files.map<ParquetTask>((filePath) => ({\n filePath,\n options: { outputDir, clearOutputDir },\n }));\n\n /* 4) Pool hooks */\n const hooks: PoolHooks<ParquetTask, ParquetProgress, ParquetResult, Totals> = {\n nextTask: () => queue.shift(),\n taskLabel: (t) => t.filePath,\n initTotals: () => ({}) as Totals,\n initSlotProgress: () => undefined,\n onProgress: (totals) => totals,\n onResult: (totals, res) => ({ totals, ok: !!res.ok }),\n postProcess: async () => {\n // nothing special post-run\n },\n };\n\n /* 5) Launch the pool runner with custom dashboard plugin */\n await runPool({\n title: `Parquet → CSV - ${directory}`,\n baseDir: directory || outputDir || this.process.cwd(),\n childFlag: CHILD_FLAG,\n childModulePath: resolveWorkerPath(import.meta.url, 'commands/admin/parquet-to-csv/worker.mjs'),\n poolSize,\n cpuCount,\n filesTotal: files.length,\n hooks,\n viewerMode,\n ...poolingUi,\n }).catch((err) => {\n if (err instanceof PoolCancelledError) {\n this.process.exit(130);\n }\n throw err;\n });\n}\n"],"mappings":"uUAcA,SAAS,EAAsB,EAAsD,CAEnF,OAAO,EAAW,EAAI,CASxB,SAAS,EAAuB,EAAsD,CACpF,OAAO,EAAe,EAAI,CAG5B,MAAa,EAAkE,CAC7E,eACA,gBAED,CCAD,eAAsB,EAEpB,EACe,CACf,EAAoB,KAAK,QAAQ,CAEjC,GAAM,CAAE,YAAW,YAAW,iBAAgB,cAAa,cAAe,EACpE,EAAY,EAAuB,KAAM,EAAoB,EAAW,CAGxE,EAAQ,EAA0B,EAAW,KAAK,CAGlD,CAAE,WAAU,YAAa,EAAgB,EAAa,EAAM,OAAO,CAEzE,KAAK,OAAO,KACV,EAAO,MACL,cAAc,EAAM,OAAO,wCAAwC,EAAS,QAAQ,EAAS,GAC9F,CACF,CAGD,IAAM,EAAQ,EAAM,IAAkB,IAAc,CAClD,WACA,QAAS,CAAE,YAAW,iBAAgB,CACvC,EAAE,CAgBH,MAAM,EAAQ,CACZ,MAAO,mBAAmB,IAC1B,QAAS,GAAa,GAAa,KAAK,QAAQ,KAAK,CACrD,UAAW,EACX,gBAAiB,EAAkB,OAAO,KAAK,IAAK,2CAA2C,CAC/F,WACA,WACA,WAAY,EAAM,OAClB,MAAA,CApBA,aAAgB,EAAM,OAAO,CAC7B,UAAY,GAAM,EAAE,SACpB,gBAAmB,EAAE,EACrB,qBAAwB,IAAA,GACxB,WAAa,GAAW,EACxB,UAAW,EAAQ,KAAS,CAAE,SAAQ,GAAI,CAAC,CAAC,EAAI,GAAI,EACpD,YAAa,SAAY,GAcpB,CACL,aACA,GAAG,EACJ,CAAC,CAAC,MAAO,GAAQ,CAIhB,MAHI,aAAe,GACjB,KAAK,QAAQ,KAAK,IAAI,CAElB,GACN"}
1
+ {"version":3,"file":"impl-BGtup1F9.mjs","names":[],"sources":["../src/commands/admin/parquet-to-csv/ui/plugin.ts","../src/commands/admin/parquet-to-csv/impl.ts"],"sourcesContent":["import {\n makeHeader,\n makeWorkerRows,\n type ChunkSlotProgress,\n type CommonCtx,\n type DashboardPlugin,\n} from '../../../../lib/pooling/index.js';\n\n/**\n * Header for parquet-to-csv (no extra totals block).\n *\n * @param ctx - Dashboard context.\n * @returns Header lines.\n */\nfunction renderHeader<TTotals>(ctx: CommonCtx<TTotals, ChunkSlotProgress>): string[] {\n // no extra lines — reuse the shared header as-is\n return makeHeader(ctx);\n}\n\n/**\n * Worker rows for parquet-to-csv — share the generic row renderer.\n *\n * @param ctx - Dashboard context.\n * @returns Array of strings, each representing one worker row.\n */\nfunction renderWorkers<TTotals>(ctx: CommonCtx<TTotals, ChunkSlotProgress>): string[] {\n return makeWorkerRows(ctx);\n}\n\nexport const parquetToCsvPlugin: DashboardPlugin<unknown, ChunkSlotProgress> = {\n renderHeader,\n renderWorkers,\n // no extras\n};\n","import {\n CHILD_FLAG,\n type PoolHooks,\n runPool,\n computePoolSize,\n PoolCancelledError,\n resolveWorkerPath,\n} from '@transcend-io/utils';\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { collectParquetFilesOrExit } from '../../../lib/helpers/index.js';\nimport { createPoolingCommandUi } from '../../../lib/pooling/index.js';\nimport { parquetToCsvPlugin } from './ui/index.js';\nimport type { ParquetProgress, ParquetResult, ParquetTask } from './worker.js';\n\n/** No custom totals for the header; the runner’s built-ins suffice. */\ntype Totals = Record<string, never>;\n\nexport type ParquetToCsvCommandFlags = {\n directory: string;\n outputDir?: string;\n clearOutputDir: boolean;\n concurrency?: number;\n viewerMode: boolean;\n};\n\n/**\n * Convert all Parquet files in a directory to CSV, in parallel.\n *\n * @param flags - The command flags.\n */\nexport async function parquetToCsv(\n this: LocalContext,\n flags: ParquetToCsvCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n const { directory, outputDir, clearOutputDir, concurrency, viewerMode } = flags;\n const poolingUi = createPoolingCommandUi(this, parquetToCsvPlugin, viewerMode);\n\n /* 1) Discover .parquet inputs */\n const files = collectParquetFilesOrExit(directory, this);\n\n /* 2) Size the pool */\n const { poolSize, cpuCount } = computePoolSize(concurrency, files.length);\n\n this.logger.info(\n colors.green(\n `Converting ${files.length} Parquet file(s) → CSV with pool size ${poolSize} (CPU=${cpuCount})`,\n ),\n );\n\n /* 3) Build FIFO queue of tasks (one per file) */\n const queue = files.map<ParquetTask>((filePath) => ({\n filePath,\n options: { outputDir, clearOutputDir },\n }));\n\n /* 4) Pool hooks */\n const hooks: PoolHooks<ParquetTask, ParquetProgress, ParquetResult, Totals> = {\n nextTask: () => queue.shift(),\n taskLabel: (t) => t.filePath,\n initTotals: () => ({}) as Totals,\n initSlotProgress: () => undefined,\n onProgress: (totals) => totals,\n onResult: (totals, res) => ({ totals, ok: !!res.ok }),\n postProcess: async () => {\n // nothing special post-run\n },\n };\n\n /* 5) Launch the pool runner with custom dashboard plugin */\n await runPool({\n title: `Parquet → CSV - ${directory}`,\n baseDir: directory || outputDir || this.process.cwd(),\n childFlag: CHILD_FLAG,\n childModulePath: resolveWorkerPath(import.meta.url, 'commands/admin/parquet-to-csv/worker.mjs'),\n poolSize,\n cpuCount,\n filesTotal: files.length,\n hooks,\n viewerMode,\n ...poolingUi,\n }).catch((err) => {\n if (err instanceof PoolCancelledError) {\n this.process.exit(130);\n }\n throw err;\n });\n}\n"],"mappings":"uUAcA,SAAS,EAAsB,EAAsD,CAEnF,OAAO,EAAW,EAAI,CASxB,SAAS,EAAuB,EAAsD,CACpF,OAAO,EAAe,EAAI,CAG5B,MAAa,EAAkE,CAC7E,eACA,gBAED,CCAD,eAAsB,EAEpB,EACe,CACf,EAAoB,KAAK,QAAQ,CAEjC,GAAM,CAAE,YAAW,YAAW,iBAAgB,cAAa,cAAe,EACpE,EAAY,EAAuB,KAAM,EAAoB,EAAW,CAGxE,EAAQ,EAA0B,EAAW,KAAK,CAGlD,CAAE,WAAU,YAAa,EAAgB,EAAa,EAAM,OAAO,CAEzE,KAAK,OAAO,KACV,EAAO,MACL,cAAc,EAAM,OAAO,wCAAwC,EAAS,QAAQ,EAAS,GAC9F,CACF,CAGD,IAAM,EAAQ,EAAM,IAAkB,IAAc,CAClD,WACA,QAAS,CAAE,YAAW,iBAAgB,CACvC,EAAE,CAgBH,MAAM,EAAQ,CACZ,MAAO,mBAAmB,IAC1B,QAAS,GAAa,GAAa,KAAK,QAAQ,KAAK,CACrD,UAAW,EACX,gBAAiB,EAAkB,OAAO,KAAK,IAAK,2CAA2C,CAC/F,WACA,WACA,WAAY,EAAM,OAClB,MAAA,CApBA,aAAgB,EAAM,OAAO,CAC7B,UAAY,GAAM,EAAE,SACpB,gBAAmB,EAAE,EACrB,qBAAwB,IAAA,GACxB,WAAa,GAAW,EACxB,UAAW,EAAQ,KAAS,CAAE,SAAQ,GAAI,CAAC,CAAC,EAAI,GAAI,EACpD,YAAa,SAAY,GAcpB,CACL,aACA,GAAG,EACJ,CAAC,CAAC,MAAO,GAAQ,CAIhB,MAHI,aAAe,GACjB,KAAK,QAAQ,KAAK,IAAI,CAElB,GACN"}
@@ -0,0 +1,2 @@
1
+ import{g as e}from"./constants-BlKpAm3R.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-B4cFXUlA.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-CwlygiTz.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-BQRP9NIv.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impl-BQRP9NIv.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"./pullChunkedCustomSiloOutstandingIdentifiers-DTGQOw--.mjs";import{i as t,s as n}from"./writeCsv-CNZrq3zU.mjs";import{t as r}from"./done-input-validation-LiTaCEzF.mjs";import{chunk as i,uniq as a}from"lodash-es";import o from"colors";import{buildTranscendGraphQLClient as s,fetchRequestFilesForRequest as c}from"@transcend-io/sdk";import{map as l}from"@transcend-io/utils";async function u({file:u,fileTarget:d,transcendUrl:f,auth:p,sombraAuth:m,cronDataSiloId:h,targetDataSiloId:g,actions:_,skipRequestCount:v,pageLimit:y,chunkSize:b}){v&&this.logger.info(o.yellow(`Skipping request count as requested. This may help speed up the call.`)),(Number.isNaN(b)||b<=0||b%y!==0)&&(this.logger.error(o.red(`Invalid chunk size: "${b}". Must be a positive integer that is a multiple of ${y}.`)),this.process.exit(1)),r(this.process);let x=s(f,p),{baseName:S,extension:C}=t(u),{baseName:w,extension:T}=t(d),E=0,D=0,O=0;await e({dataSiloId:h,auth:p,sombraAuth:m,actions:_,apiPageSize:y,savePageSize:b,onSave:async e=>{E+=e.length;let t=await l(i(a(e.map(e=>e.requestId)),y),async e=>(this.logger.info(o.magenta(`Fetching target identifiers for ${e.length} requests`)),(await c(x,{logger:this.logger,pageSize:y*2,filterBy:{requestIds:e,dataSiloIds:[g]}})).map(({fileName:e,remoteId:t})=>{if(!t)throw Error(`Failed to find remoteId for ${e}`);return{RecordId:t,Object:e.replace(`.json`,``).split(`/`).pop()?.replace(` Information`,``),Comment:`Customer data deletion request submitted via transcend.io`}})),{concurrency:1});D+=t.flat().length;let r=a(e.map(e=>Object.keys(e)).flat()),s=`${S}-${O}${C}`,f=`${w}-${O}${T}`;await n(s,e,r),this.logger.info(o.green(`Successfully wrote ${e.length} identifiers to file "${u}"`));let p=t.flat();await n(f,p,a(p.map(e=>Object.keys(e)).flat())),this.logger.info(o.green(`Successfully wrote ${p.length} identifiers to file "${d}"`)),this.logger.info(o.blue(`Processed chunk of ${i.length} identifiers, found ${p.length} target identifiers`)),O+=1},transcendUrl:f,skipRequestCount:v}),this.logger.info(o.green(`Successfully wrote ${E} identifiers to file "${u}"`)),this.logger.info(o.green(`Successfully wrote ${D} identifiers to file "${d}"`))}export{u as pullProfiles};
2
- //# sourceMappingURL=impl-CWP6AXSb.mjs.map
1
+ import{t as e}from"./pullChunkedCustomSiloOutstandingIdentifiers-BfNNWqeI.mjs";import{i as t,s as n}from"./writeCsv-CNZrq3zU.mjs";import{t as r}from"./done-input-validation-LiTaCEzF.mjs";import{chunk as i,uniq as a}from"lodash-es";import o from"colors";import{map as s}from"@transcend-io/utils";import{buildTranscendGraphQLClient as c,fetchRequestFilesForRequest as l}from"@transcend-io/sdk";async function u({file:u,fileTarget:d,transcendUrl:f,auth:p,sombraAuth:m,cronDataSiloId:h,targetDataSiloId:g,actions:_,skipRequestCount:v,pageLimit:y,chunkSize:b}){v&&this.logger.info(o.yellow(`Skipping request count as requested. This may help speed up the call.`)),(Number.isNaN(b)||b<=0||b%y!==0)&&(this.logger.error(o.red(`Invalid chunk size: "${b}". Must be a positive integer that is a multiple of ${y}.`)),this.process.exit(1)),r(this.process);let x=c(f,p),{baseName:S,extension:C}=t(u),{baseName:w,extension:T}=t(d),E=0,D=0,O=0;await e({dataSiloId:h,auth:p,sombraAuth:m,actions:_,apiPageSize:y,savePageSize:b,onSave:async e=>{E+=e.length;let t=await s(i(a(e.map(e=>e.requestId)),y),async e=>(this.logger.info(o.magenta(`Fetching target identifiers for ${e.length} requests`)),(await l(x,{logger:this.logger,pageSize:y*2,filterBy:{requestIds:e,dataSiloIds:[g]}})).map(({fileName:e,remoteId:t})=>{if(!t)throw Error(`Failed to find remoteId for ${e}`);return{RecordId:t,Object:e.replace(`.json`,``).split(`/`).pop()?.replace(` Information`,``),Comment:`Customer data deletion request submitted via transcend.io`}})),{concurrency:1});D+=t.flat().length;let r=a(e.map(e=>Object.keys(e)).flat()),c=`${S}-${O}${C}`,f=`${w}-${O}${T}`;await n(c,e,r),this.logger.info(o.green(`Successfully wrote ${e.length} identifiers to file "${u}"`));let p=t.flat();await n(f,p,a(p.map(e=>Object.keys(e)).flat())),this.logger.info(o.green(`Successfully wrote ${p.length} identifiers to file "${d}"`)),this.logger.info(o.blue(`Processed chunk of ${i.length} identifiers, found ${p.length} target identifiers`)),O+=1},transcendUrl:f,skipRequestCount:v}),this.logger.info(o.green(`Successfully wrote ${E} identifiers to file "${u}"`)),this.logger.info(o.green(`Successfully wrote ${D} identifiers to file "${d}"`))}export{u as pullProfiles};
2
+ //# sourceMappingURL=impl-BQe6vddz.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"impl-CWP6AXSb.mjs","names":[],"sources":["../src/commands/request/cron/pull-profiles/impl.ts"],"sourcesContent":["import type { RequestAction } from '@transcend-io/privacy-types';\nimport { buildTranscendGraphQLClient, fetchRequestFilesForRequest } from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport colors from 'colors';\nimport { uniq, chunk } from 'lodash-es';\n\nimport type { LocalContext } from '../../../../context.js';\nimport { doneInputValidation } from '../../../../lib/cli/done-input-validation.js';\nimport {\n pullChunkedCustomSiloOutstandingIdentifiers,\n type CsvFormattedIdentifier,\n} from '../../../../lib/cron/index.js';\nimport { parseFilePath, writeLargeCsv } from '../../../../lib/helpers/index.js';\n\nexport interface PullProfilesCommandFlags {\n file: string;\n fileTarget: string;\n transcendUrl: string;\n auth: string;\n sombraAuth?: string;\n cronDataSiloId: string;\n targetDataSiloId: string;\n actions: RequestAction[];\n skipRequestCount: boolean;\n pageLimit: number;\n chunkSize: number;\n}\n\nexport async function pullProfiles(\n this: LocalContext,\n {\n file,\n fileTarget,\n transcendUrl,\n auth,\n sombraAuth,\n cronDataSiloId,\n targetDataSiloId,\n actions,\n skipRequestCount,\n pageLimit,\n chunkSize,\n }: PullProfilesCommandFlags,\n): Promise<void> {\n if (skipRequestCount) {\n this.logger.info(\n colors.yellow('Skipping request count as requested. This may help speed up the call.'),\n );\n }\n\n if (Number.isNaN(chunkSize) || chunkSize <= 0 || chunkSize % pageLimit !== 0) {\n this.logger.error(\n colors.red(\n `Invalid chunk size: \"${chunkSize}\". Must be a positive integer that is a multiple of ${pageLimit}.`,\n ),\n );\n this.process.exit(1);\n }\n\n doneInputValidation(this.process);\n\n // Create GraphQL client to connect to Transcend backend\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n const { baseName, extension } = parseFilePath(file);\n const { baseName: baseNameTarget, extension: extensionTarget } = parseFilePath(fileTarget);\n\n let allIdentifiersCount = 0;\n let allTargetIdentifiersCount = 0;\n let fileCount = 0;\n // Create onSave callback to handle chunked processing\n const onSave = async (chunkToSave: CsvFormattedIdentifier[]): Promise<void> => {\n // Add to all identifiers\n allIdentifiersCount += chunkToSave.length;\n\n // Get unique request IDs from this chunk\n const requestIds = chunkToSave.map((d) => d.requestId as string);\n const uniqueRequestIds = uniq(requestIds);\n\n // Pull down target identifiers for this chunk\n const chunkedRequestIds = chunk(uniqueRequestIds, pageLimit);\n const results = await map(\n chunkedRequestIds,\n async (requestIds) => {\n this.logger.info(\n colors.magenta(`Fetching target identifiers for ${requestIds.length} requests`),\n );\n const results = await fetchRequestFilesForRequest(client, {\n logger: this.logger,\n pageSize: pageLimit * 2,\n filterBy: {\n requestIds,\n dataSiloIds: [targetDataSiloId],\n },\n });\n return results.map(({ fileName, remoteId }) => {\n if (!remoteId) {\n throw new Error(`Failed to find remoteId for ${fileName}`);\n }\n return {\n RecordId: remoteId,\n Object: fileName.replace('.json', '').split('/').pop()?.replace(' Information', ''),\n Comment: 'Customer data deletion request submitted via transcend.io',\n };\n });\n },\n // We are grabbing all the request files for the 'pageLimit' # of requests at a time\n {\n concurrency: 1,\n },\n );\n\n allTargetIdentifiersCount += results.flat().length;\n\n // Write the identifiers and target identifiers to CSV\n const headers = uniq(chunkToSave.map((d) => Object.keys(d)).flat());\n const numberedFileName = `${baseName}-${fileCount}${extension}`;\n const numberedFileNameTarget = `${baseNameTarget}-${fileCount}${extensionTarget}`;\n await writeLargeCsv(numberedFileName, chunkToSave, headers);\n this.logger.info(\n colors.green(`Successfully wrote ${chunkToSave.length} identifiers to file \"${file}\"`),\n );\n\n const targetIdentifiers = results.flat();\n const headers2 = uniq(targetIdentifiers.map((d) => Object.keys(d)).flat());\n await writeLargeCsv(numberedFileNameTarget, targetIdentifiers, headers2);\n this.logger.info(\n colors.green(\n `Successfully wrote ${targetIdentifiers.length} identifiers to file \"${fileTarget}\"`,\n ),\n );\n\n this.logger.info(\n colors.blue(\n `Processed chunk of ${chunk.length} identifiers, found ${targetIdentifiers.length} target identifiers`,\n ),\n );\n fileCount += 1;\n };\n\n // Pull down outstanding identifiers using the new chunked function\n await pullChunkedCustomSiloOutstandingIdentifiers({\n dataSiloId: cronDataSiloId,\n auth,\n sombraAuth,\n actions,\n apiPageSize: pageLimit,\n savePageSize: chunkSize,\n onSave,\n transcendUrl,\n skipRequestCount,\n });\n\n this.logger.info(\n colors.green(`Successfully wrote ${allIdentifiersCount} identifiers to file \"${file}\"`),\n );\n this.logger.info(\n colors.green(\n `Successfully wrote ${allTargetIdentifiersCount} identifiers to file \"${fileTarget}\"`,\n ),\n );\n}\n"],"mappings":"wYA4BA,eAAsB,EAEpB,CACE,OACA,aACA,eACA,OACA,aACA,iBACA,mBACA,UACA,mBACA,YACA,aAEa,CACX,GACF,KAAK,OAAO,KACV,EAAO,OAAO,wEAAwE,CACvF,EAGC,OAAO,MAAM,EAAU,EAAI,GAAa,GAAK,EAAY,IAAc,KACzE,KAAK,OAAO,MACV,EAAO,IACL,wBAAwB,EAAU,sDAAsD,EAAU,GACnG,CACF,CACD,KAAK,QAAQ,KAAK,EAAE,EAGtB,EAAoB,KAAK,QAAQ,CAGjC,IAAM,EAAS,EAA4B,EAAc,EAAK,CACxD,CAAE,WAAU,aAAc,EAAc,EAAK,CAC7C,CAAE,SAAU,EAAgB,UAAW,GAAoB,EAAc,EAAW,CAEtF,EAAsB,EACtB,EAA4B,EAC5B,EAAY,EAwEhB,MAAM,EAA4C,CAChD,WAAY,EACZ,OACA,aACA,UACA,YAAa,EACb,aAAc,EACd,YA7EoB,IAAyD,CAE7E,GAAuB,EAAY,OAQnC,IAAM,EAAU,MAAM,EADI,EAHD,EADN,EAAY,IAAK,GAAM,EAAE,UACJ,CAGQ,CAAE,EAE/B,CACjB,KAAO,KACL,KAAK,OAAO,KACV,EAAO,QAAQ,mCAAmC,EAAW,OAAO,WAAW,CAChF,EASM,MARe,EAA4B,EAAQ,CACxD,OAAQ,KAAK,OACb,SAAU,EAAY,EACtB,SAAU,CACR,aACA,YAAa,CAAC,EAAiB,CAChC,CACF,CAAC,EACa,KAAK,CAAE,WAAU,cAAe,CAC7C,GAAI,CAAC,EACH,MAAU,MAAM,+BAA+B,IAAW,CAE5D,MAAO,CACL,SAAU,EACV,OAAQ,EAAS,QAAQ,QAAS,GAAG,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,QAAQ,eAAgB,GAAG,CACnF,QAAS,4DACV,EACD,EAGJ,CACE,YAAa,EACd,CACF,CAED,GAA6B,EAAQ,MAAM,CAAC,OAG5C,IAAM,EAAU,EAAK,EAAY,IAAK,GAAM,OAAO,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAC7D,EAAmB,GAAG,EAAS,GAAG,IAAY,IAC9C,EAAyB,GAAG,EAAe,GAAG,IAAY,IAChE,MAAM,EAAc,EAAkB,EAAa,EAAQ,CAC3D,KAAK,OAAO,KACV,EAAO,MAAM,sBAAsB,EAAY,OAAO,wBAAwB,EAAK,GAAG,CACvF,CAED,IAAM,EAAoB,EAAQ,MAAM,CAExC,MAAM,EAAc,EAAwB,EAD3B,EAAK,EAAkB,IAAK,GAAM,OAAO,KAAK,EAAE,CAAC,CAAC,MAAM,CACF,CAAC,CACxE,KAAK,OAAO,KACV,EAAO,MACL,sBAAsB,EAAkB,OAAO,wBAAwB,EAAW,GACnF,CACF,CAED,KAAK,OAAO,KACV,EAAO,KACL,sBAAsB,EAAM,OAAO,sBAAsB,EAAkB,OAAO,qBACnF,CACF,CACD,GAAa,GAYb,eACA,mBACD,CAAC,CAEF,KAAK,OAAO,KACV,EAAO,MAAM,sBAAsB,EAAoB,wBAAwB,EAAK,GAAG,CACxF,CACD,KAAK,OAAO,KACV,EAAO,MACL,sBAAsB,EAA0B,wBAAwB,EAAW,GACpF,CACF"}
1
+ {"version":3,"file":"impl-BQe6vddz.mjs","names":[],"sources":["../src/commands/request/cron/pull-profiles/impl.ts"],"sourcesContent":["import type { RequestAction } from '@transcend-io/privacy-types';\nimport { buildTranscendGraphQLClient, fetchRequestFilesForRequest } from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport colors from 'colors';\nimport { uniq, chunk } from 'lodash-es';\n\nimport type { LocalContext } from '../../../../context.js';\nimport { doneInputValidation } from '../../../../lib/cli/done-input-validation.js';\nimport {\n pullChunkedCustomSiloOutstandingIdentifiers,\n type CsvFormattedIdentifier,\n} from '../../../../lib/cron/index.js';\nimport { parseFilePath, writeLargeCsv } from '../../../../lib/helpers/index.js';\n\nexport interface PullProfilesCommandFlags {\n file: string;\n fileTarget: string;\n transcendUrl: string;\n auth: string;\n sombraAuth?: string;\n cronDataSiloId: string;\n targetDataSiloId: string;\n actions: RequestAction[];\n skipRequestCount: boolean;\n pageLimit: number;\n chunkSize: number;\n}\n\nexport async function pullProfiles(\n this: LocalContext,\n {\n file,\n fileTarget,\n transcendUrl,\n auth,\n sombraAuth,\n cronDataSiloId,\n targetDataSiloId,\n actions,\n skipRequestCount,\n pageLimit,\n chunkSize,\n }: PullProfilesCommandFlags,\n): Promise<void> {\n if (skipRequestCount) {\n this.logger.info(\n colors.yellow('Skipping request count as requested. This may help speed up the call.'),\n );\n }\n\n if (Number.isNaN(chunkSize) || chunkSize <= 0 || chunkSize % pageLimit !== 0) {\n this.logger.error(\n colors.red(\n `Invalid chunk size: \"${chunkSize}\". Must be a positive integer that is a multiple of ${pageLimit}.`,\n ),\n );\n this.process.exit(1);\n }\n\n doneInputValidation(this.process);\n\n // Create GraphQL client to connect to Transcend backend\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n const { baseName, extension } = parseFilePath(file);\n const { baseName: baseNameTarget, extension: extensionTarget } = parseFilePath(fileTarget);\n\n let allIdentifiersCount = 0;\n let allTargetIdentifiersCount = 0;\n let fileCount = 0;\n // Create onSave callback to handle chunked processing\n const onSave = async (chunkToSave: CsvFormattedIdentifier[]): Promise<void> => {\n // Add to all identifiers\n allIdentifiersCount += chunkToSave.length;\n\n // Get unique request IDs from this chunk\n const requestIds = chunkToSave.map((d) => d.requestId as string);\n const uniqueRequestIds = uniq(requestIds);\n\n // Pull down target identifiers for this chunk\n const chunkedRequestIds = chunk(uniqueRequestIds, pageLimit);\n const results = await map(\n chunkedRequestIds,\n async (requestIds) => {\n this.logger.info(\n colors.magenta(`Fetching target identifiers for ${requestIds.length} requests`),\n );\n const results = await fetchRequestFilesForRequest(client, {\n logger: this.logger,\n pageSize: pageLimit * 2,\n filterBy: {\n requestIds,\n dataSiloIds: [targetDataSiloId],\n },\n });\n return results.map(({ fileName, remoteId }) => {\n if (!remoteId) {\n throw new Error(`Failed to find remoteId for ${fileName}`);\n }\n return {\n RecordId: remoteId,\n Object: fileName.replace('.json', '').split('/').pop()?.replace(' Information', ''),\n Comment: 'Customer data deletion request submitted via transcend.io',\n };\n });\n },\n // We are grabbing all the request files for the 'pageLimit' # of requests at a time\n {\n concurrency: 1,\n },\n );\n\n allTargetIdentifiersCount += results.flat().length;\n\n // Write the identifiers and target identifiers to CSV\n const headers = uniq(chunkToSave.map((d) => Object.keys(d)).flat());\n const numberedFileName = `${baseName}-${fileCount}${extension}`;\n const numberedFileNameTarget = `${baseNameTarget}-${fileCount}${extensionTarget}`;\n await writeLargeCsv(numberedFileName, chunkToSave, headers);\n this.logger.info(\n colors.green(`Successfully wrote ${chunkToSave.length} identifiers to file \"${file}\"`),\n );\n\n const targetIdentifiers = results.flat();\n const headers2 = uniq(targetIdentifiers.map((d) => Object.keys(d)).flat());\n await writeLargeCsv(numberedFileNameTarget, targetIdentifiers, headers2);\n this.logger.info(\n colors.green(\n `Successfully wrote ${targetIdentifiers.length} identifiers to file \"${fileTarget}\"`,\n ),\n );\n\n this.logger.info(\n colors.blue(\n `Processed chunk of ${chunk.length} identifiers, found ${targetIdentifiers.length} target identifiers`,\n ),\n );\n fileCount += 1;\n };\n\n // Pull down outstanding identifiers using the new chunked function\n await pullChunkedCustomSiloOutstandingIdentifiers({\n dataSiloId: cronDataSiloId,\n auth,\n sombraAuth,\n actions,\n apiPageSize: pageLimit,\n savePageSize: chunkSize,\n onSave,\n transcendUrl,\n skipRequestCount,\n });\n\n this.logger.info(\n colors.green(`Successfully wrote ${allIdentifiersCount} identifiers to file \"${file}\"`),\n );\n this.logger.info(\n colors.green(\n `Successfully wrote ${allTargetIdentifiersCount} identifiers to file \"${fileTarget}\"`,\n ),\n );\n}\n"],"mappings":"wYA4BA,eAAsB,EAEpB,CACE,OACA,aACA,eACA,OACA,aACA,iBACA,mBACA,UACA,mBACA,YACA,aAEa,CACX,GACF,KAAK,OAAO,KACV,EAAO,OAAO,wEAAwE,CACvF,EAGC,OAAO,MAAM,EAAU,EAAI,GAAa,GAAK,EAAY,IAAc,KACzE,KAAK,OAAO,MACV,EAAO,IACL,wBAAwB,EAAU,sDAAsD,EAAU,GACnG,CACF,CACD,KAAK,QAAQ,KAAK,EAAE,EAGtB,EAAoB,KAAK,QAAQ,CAGjC,IAAM,EAAS,EAA4B,EAAc,EAAK,CACxD,CAAE,WAAU,aAAc,EAAc,EAAK,CAC7C,CAAE,SAAU,EAAgB,UAAW,GAAoB,EAAc,EAAW,CAEtF,EAAsB,EACtB,EAA4B,EAC5B,EAAY,EAwEhB,MAAM,EAA4C,CAChD,WAAY,EACZ,OACA,aACA,UACA,YAAa,EACb,aAAc,EACd,YA7EoB,IAAyD,CAE7E,GAAuB,EAAY,OAQnC,IAAM,EAAU,MAAM,EADI,EAHD,EADN,EAAY,IAAK,GAAM,EAAE,UACJ,CAGQ,CAAE,EAE/B,CACjB,KAAO,KACL,KAAK,OAAO,KACV,EAAO,QAAQ,mCAAmC,EAAW,OAAO,WAAW,CAChF,EASM,MARe,EAA4B,EAAQ,CACxD,OAAQ,KAAK,OACb,SAAU,EAAY,EACtB,SAAU,CACR,aACA,YAAa,CAAC,EAAiB,CAChC,CACF,CAAC,EACa,KAAK,CAAE,WAAU,cAAe,CAC7C,GAAI,CAAC,EACH,MAAU,MAAM,+BAA+B,IAAW,CAE5D,MAAO,CACL,SAAU,EACV,OAAQ,EAAS,QAAQ,QAAS,GAAG,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,QAAQ,eAAgB,GAAG,CACnF,QAAS,4DACV,EACD,EAGJ,CACE,YAAa,EACd,CACF,CAED,GAA6B,EAAQ,MAAM,CAAC,OAG5C,IAAM,EAAU,EAAK,EAAY,IAAK,GAAM,OAAO,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAC7D,EAAmB,GAAG,EAAS,GAAG,IAAY,IAC9C,EAAyB,GAAG,EAAe,GAAG,IAAY,IAChE,MAAM,EAAc,EAAkB,EAAa,EAAQ,CAC3D,KAAK,OAAO,KACV,EAAO,MAAM,sBAAsB,EAAY,OAAO,wBAAwB,EAAK,GAAG,CACvF,CAED,IAAM,EAAoB,EAAQ,MAAM,CAExC,MAAM,EAAc,EAAwB,EAD3B,EAAK,EAAkB,IAAK,GAAM,OAAO,KAAK,EAAE,CAAC,CAAC,MAAM,CACF,CAAC,CACxE,KAAK,OAAO,KACV,EAAO,MACL,sBAAsB,EAAkB,OAAO,wBAAwB,EAAW,GACnF,CACF,CAED,KAAK,OAAO,KACV,EAAO,KACL,sBAAsB,EAAM,OAAO,sBAAsB,EAAkB,OAAO,qBACnF,CACF,CACD,GAAa,GAYb,eACA,mBACD,CAAC,CAEF,KAAK,OAAO,KACV,EAAO,MAAM,sBAAsB,EAAoB,wBAAwB,EAAK,GAAG,CACxF,CACD,KAAK,OAAO,KACV,EAAO,MACL,sBAAsB,EAA0B,wBAAwB,EAAW,GACpF,CACF"}
@@ -1,3 +1,3 @@
1
- import{i as e,n as t,o as n,t as r}from"./policy-project-discovery-C29UxWwt.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-BZnBMZQq.mjs";import{n as u}from"./inquirer-BU5IpgA8.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
- `)||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:e,noInteractive:t,json:r},d,p){let _=g.map(e=>({name:e,status:`skipped`})),S=[],C={version:1,status:`passed`,directory:d,fix:e,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,n);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 n=await p(`opa`,[`fmt`,`--list`,d],{cwd:d},this);if(n.code!==0)w(`format`,`failed`),T(`opa.format`,v(n,`opa fmt --list failed with exit code ${n.code}`));else if(C.unformattedFiles=y(n.stdout,d),C.unformattedFiles.length===0)w(`format`,`passed`);else{let n=e,i=f({json:r,noInteractive:t},this.process.stdin.isTTY,this.process.stderr.isTTY);if(!r&&!e){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(!e&&i)try{n=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(n){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(n,i=r,a=p){d(this.process);let{fix:o=!1,noInteractive:s=!1,json:c=!1}=n,l=e(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=t(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-B440iuvL.mjs.map
1
+ import{c as e,i as t,n,t as r}from"./policy-project-discovery-B4cFXUlA.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-RgsjPnfI.mjs";import{n as u}from"./inquirer-BU5IpgA8.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
+ `)||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-BQj1Ien4.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"impl-B440iuvL.mjs","names":[],"sources":["../src/lib/policy/policy-lint-model.ts","../src/lib/policy/policy-lint-output.ts","../src/commands/policy/lint/impl.ts"],"sourcesContent":["/** Stable policy lint result schema version. */\nexport const POLICY_LINT_RESULT_VERSION = 1;\n\n/** Stable multi-bundle lint result schema version. */\nexport const POLICY_LINT_MULTI_RESULT_VERSION = 2;\n\n/** Status of the full gate or an individual verification. */\nexport type PolicyLintStatus = 'passed' | 'failed' | 'skipped';\n\n/** One named policy verification. */\nexport interface PolicyLintCheck {\n /** Stable verification name. */\n name:\n | 'manifest'\n | 'opa-version'\n | 'regal-version'\n | 'format'\n | 'opa-check'\n | 'regal-lint'\n | 'opa-test';\n /** Verification outcome. */\n status: PolicyLintStatus;\n}\n\n/** Stable verification execution order. */\nexport const POLICY_LINT_CHECK_NAMES: PolicyLintCheck['name'][] = [\n 'manifest',\n 'opa-version',\n 'regal-version',\n 'format',\n 'opa-check',\n 'regal-lint',\n 'opa-test',\n];\n\n/** User-facing verification labels. */\nexport const POLICY_LINT_CHECK_LABELS: Readonly<Record<PolicyLintCheck['name'], string>> = {\n manifest: 'Manifest and package roots',\n 'opa-version': 'OPA 1.x',\n 'regal-version': 'Regal',\n format: 'OPA formatting',\n 'opa-check': 'OPA strict check',\n 'regal-lint': 'Regal lint',\n 'opa-test': 'OPA tests',\n};\n\n/** One machine-readable policy lint diagnostic. */\nexport interface PolicyLintDiagnostic {\n /** Stable diagnostic identifier. */\n code: string;\n /** Diagnostic severity. */\n severity: 'error';\n /** Human-readable detail, including captured tool output when available. */\n message: string;\n /** Optional path relative to the invocation directory. */\n path?: string;\n}\n\n/** Detected local policy tool versions. */\nexport interface PolicyLintTools {\n /** Detected OPA version, or null when missing or unsupported. */\n opa: string | null;\n /** Detected Regal version, or null when missing or unsupported. */\n regal: string | null;\n}\n\n/** Stable result emitted by `transcend policy lint --json` for one bundle. */\nexport interface PolicyLintResult {\n /** Result schema version. */\n version: typeof POLICY_LINT_RESULT_VERSION;\n /** Overall verification outcome. */\n status: Exclude<PolicyLintStatus, 'skipped'>;\n /** Absolute policy bundle directory. */\n directory: string;\n /** Whether formatting repair was explicitly requested. */\n fix: boolean;\n /** Detected supported tool versions. */\n tools: PolicyLintTools;\n /** Verification outcomes in stable execution order. */\n checks: PolicyLintCheck[];\n /** Files found to need OPA formatting, relative to the policy directory. */\n unformattedFiles: string[];\n /** Files repaired with OPA formatting, relative to the policy directory. */\n fixedFiles: string[];\n /** Ordered verification diagnostics. */\n diagnostics: PolicyLintDiagnostic[];\n}\n\n/**\n * Stable result when `transcend policy lint --json` verifies multiple bundles.\n *\n * Emitted only when the selected path is a workspace with more than one\n * publishable `*-bundle/` directory.\n */\nexport interface PolicyLintMultiResult {\n /** Result schema version. */\n version: typeof POLICY_LINT_MULTI_RESULT_VERSION;\n /** Overall verification outcome across all bundles. */\n status: Exclude<PolicyLintStatus, 'skipped'>;\n /** Absolute policy workspace directory that was searched. */\n directory: string;\n /** Whether formatting repair was explicitly requested. */\n fix: boolean;\n /** Per-bundle results in discovery order. */\n results: PolicyLintResult[];\n}\n","import path from 'node:path';\n\nimport type { CapturedProcessResult } from '../cli/run-captured-process.js';\n\n/**\n * Use captured tool output as a concise diagnostic.\n *\n * @param result - Captured process result\n * @param fallback - Message used when the tool emitted no output\n * @returns Diagnostic message\n */\nexport function getPolicyProcessFailureMessage(\n result: CapturedProcessResult,\n fallback: string,\n): string {\n const output = [result.stdout.trim(), result.stderr.trim()].filter(Boolean).join('\\n');\n return output || fallback;\n}\n\n/**\n * Convert absolute OPA formatter paths to stable project-relative paths.\n *\n * @param stdout - `opa fmt --list` output\n * @param projectDirectory - Absolute policy directory\n * @returns Sorted unique paths\n */\nexport function parseUnformattedPolicyFiles(stdout: string, projectDirectory: string): string[] {\n return [\n ...new Set(\n stdout\n .split(/\\r?\\n/gu)\n .map((file) => file.trim())\n .filter(Boolean)\n .map((file) =>\n path.isAbsolute(file)\n ? path.relative(projectDirectory, file).split(path.sep).join('/')\n : file.split(path.sep).join('/'),\n ),\n ),\n ].sort();\n}\n","import path from 'node:path';\n\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport {\n runCapturedProcess,\n type CapturedProcessRunner,\n} from '../../../lib/cli/run-captured-process.js';\nimport { inquirerConfirmBoolean } from '../../../lib/helpers/inquirer.js';\nimport {\n type PolicyBundleRegoFile,\n validatePolicyBundleContents,\n} from '../../../lib/policy/policy-bundle-manifest.js';\nimport {\n type PolicyLintCheck,\n type PolicyLintDiagnostic,\n type PolicyLintMultiResult,\n type PolicyLintResult,\n POLICY_LINT_CHECK_LABELS,\n POLICY_LINT_CHECK_NAMES,\n POLICY_LINT_MULTI_RESULT_VERSION,\n POLICY_LINT_RESULT_VERSION,\n} from '../../../lib/policy/policy-lint-model.js';\nimport {\n getPolicyProcessFailureMessage,\n parseUnformattedPolicyFiles,\n} from '../../../lib/policy/policy-lint-output.js';\nimport {\n DEFAULT_POLICY_PROJECT_DIRECTORY,\n discoverPolicyBundleDirectories,\n resolvePolicyProjectDirectory,\n} from '../../../lib/policy/policy-project-discovery.js';\nimport {\n OPA_MISSING_MESSAGE,\n parsePolicyToolVersion,\n REGAL_MISSING_MESSAGE,\n unsupportedOpaVersionMessage,\n unsupportedRegalVersionMessage,\n} from '../../../lib/policy/policy-runtime.js';\nimport { POLICY_MANIFEST_FILENAME } from '../../../lib/policy/policy-scaffold-templates.js';\nimport { isInteractivePromptInvocation } from '../../../lib/scaffolding/prompts.js';\n\n/** CLI flags for `transcend policy lint`. */\nexport interface LintCommandFlags {\n /** Apply OPA formatting. */\n fix: boolean;\n /** Disable the optional formatting confirmation. */\n noInteractive: boolean;\n /** Emit one stable JSON result on stdout. */\n json: boolean;\n}\n\n/**\n * Collect Rego source snapshots without following symlinks.\n *\n * @param context - CLI context\n * @param projectDirectory - Absolute policy directory\n * @param currentDirectory - Current recursive directory\n * @returns Deterministically ordered Rego snapshots\n */\nfunction collectRegoFiles(\n context: LocalContext,\n projectDirectory: string,\n currentDirectory: string = projectDirectory,\n): PolicyBundleRegoFile[] {\n return context.fs\n .readdirSync(currentDirectory, { withFileTypes: true })\n .sort((left, right) => left.name.localeCompare(right.name))\n .flatMap((entry) => {\n const absolutePath = path.join(currentDirectory, entry.name);\n if (entry.isDirectory()) {\n return collectRegoFiles(context, projectDirectory, absolutePath);\n }\n if (!entry.isFile() || !entry.name.endsWith('.rego')) {\n return [];\n }\n return [\n {\n path: path.relative(projectDirectory, absolutePath).split(path.sep).join('/'),\n contents: context.fs.readFileSync(absolutePath, 'utf8'),\n },\n ];\n });\n}\n\n/**\n * Resolve a Regal config file for a bundle, walking up to the workspace.\n *\n * @param context - CLI context\n * @param bundleDirectory - Absolute bundle directory\n * @returns Absolute config path, or undefined when none is found\n */\nfunction resolveRegalConfigFile(\n context: LocalContext,\n bundleDirectory: string,\n): string | undefined {\n let current = bundleDirectory;\n for (;;) {\n const nestedRegalConfig = path.join(current, '.regal', 'config.yaml');\n if (context.fs.existsSync(nestedRegalConfig)) {\n return nestedRegalConfig;\n }\n const rootRegalConfig = path.join(current, '.regal.yaml');\n if (context.fs.existsSync(rootRegalConfig)) {\n return rootRegalConfig;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n return undefined;\n }\n current = parent;\n }\n}\n\n/**\n * Render the terminal summary for a policy verification result.\n *\n * @param context - CLI context\n * @param result - Completed verification result\n * @param heading - Optional section heading when linting multiple bundles\n */\nfunction renderResult(context: LocalContext, result: PolicyLintResult, heading?: string): void {\n if (heading) {\n context.logger.info(`${colors.bold(heading)}\\n`);\n } else {\n context.logger.info(`${colors.bold('Policy verification')}\\n`);\n }\n result.checks.forEach(({ name, status }) => {\n const label = status === 'passed' ? 'PASS' : status === 'failed' ? 'FAIL' : 'SKIP';\n const styledLabel =\n status === 'passed'\n ? colors.green(label)\n : status === 'failed'\n ? colors.red(label)\n : colors.yellow(label);\n const version =\n name === 'opa-version' && result.tools.opa\n ? ` (${result.tools.opa})`\n : name === 'regal-version' && result.tools.regal\n ? ` (${result.tools.regal})`\n : '';\n context.logger.info(`${styledLabel} ${POLICY_LINT_CHECK_LABELS[name]}${version}`);\n });\n if (result.diagnostics.length > 0) {\n context.logger.error('');\n }\n result.diagnostics.forEach((diagnostic) => {\n const location = diagnostic.path ? `${diagnostic.path}: ` : '';\n context.logger.error(\n colors.red(`error [${diagnostic.code}]: ${location}${diagnostic.message}`),\n );\n });\n if (result.status === 'passed') {\n context.logger.info('');\n context.logger.info(colors.green('Policy verification passed.'));\n } else {\n context.logger.error('');\n context.logger.error(colors.red('Policy verification failed.'));\n }\n}\n\n/**\n * Verify one publishable policy bundle directory.\n *\n * @param context - CLI context\n * @param flags - Command flags\n * @param resolvedDir - Absolute bundle directory\n * @param runner - Captured subprocess runner\n * @returns Completed verification result\n */\nasync function lintBundle(\n this: LocalContext,\n { fix, noInteractive, json }: LintCommandFlags,\n resolvedDir: string,\n runner: CapturedProcessRunner,\n): Promise<PolicyLintResult> {\n const checks: PolicyLintCheck[] = POLICY_LINT_CHECK_NAMES.map((name) => ({\n name,\n status: 'skipped',\n }));\n const diagnostics: PolicyLintDiagnostic[] = [];\n const result: PolicyLintResult = {\n version: POLICY_LINT_RESULT_VERSION,\n status: 'passed',\n directory: resolvedDir,\n fix,\n tools: { opa: null, regal: null },\n checks,\n unformattedFiles: [],\n fixedFiles: [],\n diagnostics,\n };\n const setStatus = (name: PolicyLintCheck['name'], status: PolicyLintCheck['status']): void => {\n checks.find((check) => check.name === name)!.status = status;\n };\n const addError = (code: string, message: string, diagnosticPath?: string): void => {\n diagnostics.push({\n code,\n severity: 'error',\n message,\n ...(diagnosticPath ? { path: diagnosticPath } : {}),\n });\n };\n\n if (!this.fs.existsSync(resolvedDir) || !this.fs.statSync(resolvedDir).isDirectory()) {\n setStatus('manifest', 'failed');\n addError(\n 'project.directory',\n `Policy directory does not exist or is not a directory: ${resolvedDir}`,\n path.relative(this.process.cwd(), resolvedDir),\n );\n result.status = 'failed';\n return result;\n }\n\n const manifestPath = path.join(resolvedDir, POLICY_MANIFEST_FILENAME);\n try {\n validatePolicyBundleContents(\n this.fs.existsSync(manifestPath) ? this.fs.readFileSync(manifestPath, 'utf8') : undefined,\n collectRegoFiles(this, resolvedDir),\n );\n setStatus('manifest', 'passed');\n } catch (error) {\n setStatus('manifest', 'failed');\n addError(\n 'manifest.invalid',\n error instanceof Error ? error.message : String(error),\n path.relative(this.process.cwd(), manifestPath),\n );\n }\n\n const opaVersionResult = await runner('opa', ['version'], { cwd: resolvedDir }, this);\n if (opaVersionResult.error?.code === 'ENOENT') {\n setStatus('opa-version', 'failed');\n addError('opa.missing', OPA_MISSING_MESSAGE);\n } else {\n const opaVersionOutput = `${opaVersionResult.stdout}\\n${opaVersionResult.stderr}`;\n const unsupportedOpa = unsupportedOpaVersionMessage(opaVersionOutput);\n if (opaVersionResult.code !== 0 || unsupportedOpa) {\n setStatus('opa-version', 'failed');\n addError(\n 'opa.version',\n unsupportedOpa ??\n getPolicyProcessFailureMessage(\n opaVersionResult,\n 'Unable to determine the installed OPA version.',\n ),\n );\n } else {\n result.tools.opa = parsePolicyToolVersion(opaVersionOutput)!.version;\n setStatus('opa-version', 'passed');\n }\n }\n\n const regalVersionResult = await runner('regal', ['version'], { cwd: resolvedDir }, this);\n if (regalVersionResult.error?.code === 'ENOENT') {\n setStatus('regal-version', 'failed');\n addError('regal.missing', REGAL_MISSING_MESSAGE);\n } else {\n const regalVersionOutput = `${regalVersionResult.stdout}\\n${regalVersionResult.stderr}`;\n const unsupportedRegal = unsupportedRegalVersionMessage(regalVersionOutput);\n if (regalVersionResult.code !== 0 || unsupportedRegal) {\n setStatus('regal-version', 'failed');\n addError(\n 'regal.version',\n unsupportedRegal ??\n getPolicyProcessFailureMessage(\n regalVersionResult,\n 'Unable to determine the installed Regal version.',\n ),\n );\n } else {\n result.tools.regal = parsePolicyToolVersion(regalVersionOutput)!.version;\n setStatus('regal-version', 'passed');\n }\n }\n\n if (result.tools.opa) {\n const formatResult = await runner(\n 'opa',\n ['fmt', '--list', resolvedDir],\n { cwd: resolvedDir },\n this,\n );\n if (formatResult.code !== 0) {\n setStatus('format', 'failed');\n addError(\n 'opa.format',\n getPolicyProcessFailureMessage(\n formatResult,\n `opa fmt --list failed with exit code ${formatResult.code}`,\n ),\n );\n } else {\n result.unformattedFiles = parseUnformattedPolicyFiles(formatResult.stdout, resolvedDir);\n if (result.unformattedFiles.length === 0) {\n setStatus('format', 'passed');\n } else {\n let shouldFormat = fix;\n const interactive = isInteractivePromptInvocation(\n { json, noInteractive },\n this.process.stdin.isTTY,\n this.process.stderr.isTTY,\n );\n if (!json && !fix) {\n this.logger.error(colors.red('Policy files are not formatted:'));\n result.unformattedFiles.forEach((file) => {\n this.logger.error(colors.red(` - ${file}`));\n });\n const diffResult = await runner(\n 'opa',\n ['fmt', '--diff', resolvedDir],\n { cwd: resolvedDir },\n this,\n );\n const diff = diffResult.stdout.trim() || diffResult.stderr.trim();\n if (diff) {\n this.logger.error('');\n this.logger.error(diff);\n }\n }\n if (!fix && interactive) {\n try {\n shouldFormat = await inquirerConfirmBoolean({\n message: 'Format the unformatted policy files listed above?',\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (/force closed|prompt.*cancel|user.*close|SIGINT/iu.test(message)) {\n this.process.exit(130);\n }\n throw error;\n }\n }\n if (shouldFormat) {\n const writeResult = await runner(\n 'opa',\n ['fmt', '--write', resolvedDir],\n { cwd: resolvedDir },\n this,\n );\n if (writeResult.code === 0) {\n result.fixedFiles = [...result.unformattedFiles];\n setStatus('format', 'passed');\n } else {\n setStatus('format', 'failed');\n addError(\n 'opa.format-fix',\n getPolicyProcessFailureMessage(\n writeResult,\n `opa fmt --write failed with exit code ${writeResult.code}`,\n ),\n );\n }\n } else {\n setStatus('format', 'failed');\n addError(\n 'opa.format-required',\n 'Policy files are not formatted. Re-run `transcend policy lint --fix` to repair them.',\n );\n }\n }\n }\n\n const checkResult = await runner(\n 'opa',\n ['check', '--strict', '--ignore', '*_test.rego', resolvedDir],\n { cwd: resolvedDir },\n this,\n );\n if (checkResult.code === 0) {\n setStatus('opa-check', 'passed');\n } else {\n setStatus('opa-check', 'failed');\n addError(\n 'opa.check',\n getPolicyProcessFailureMessage(\n checkResult,\n `opa check failed with exit code ${checkResult.code}`,\n ),\n );\n }\n }\n\n if (result.tools.regal) {\n const regalConfig = resolveRegalConfigFile(this, resolvedDir);\n const regalResult = await runner(\n 'regal',\n [\n 'lint',\n '--fail-level',\n 'warning',\n ...(regalConfig ? ['--config-file', regalConfig] : []),\n resolvedDir,\n ],\n { cwd: resolvedDir },\n this,\n );\n if (regalResult.code === 0) {\n setStatus('regal-lint', 'passed');\n } else {\n setStatus('regal-lint', 'failed');\n addError(\n 'regal.lint',\n getPolicyProcessFailureMessage(\n regalResult,\n `regal lint failed with exit code ${regalResult.code}`,\n ),\n );\n }\n }\n\n if (result.tools.opa) {\n const testResult = await runner(\n 'opa',\n ['test', '--fail-on-empty', '-b', resolvedDir],\n { cwd: resolvedDir },\n this,\n );\n if (testResult.code === 0) {\n setStatus('opa-test', 'passed');\n } else {\n setStatus('opa-test', 'failed');\n addError(\n 'opa.test',\n getPolicyProcessFailureMessage(\n testResult,\n `opa test --fail-on-empty -b failed with exit code ${testResult.code}`,\n ),\n );\n }\n }\n\n result.status = checks.some(({ status }) => status === 'failed') ? 'failed' : 'passed';\n return result;\n}\n\n/**\n * Verify local policy bundles with the shared upload contract, OPA, and Regal.\n *\n * With no directory (or the default workspace path), discovers every immediate\n * child that contains a `.manifest` and verifies each. Pass one bundle path to\n * verify a single publishable unit.\n *\n * @param this - CLI context\n * @param flags - Command flags\n * @param directory - Policy workspace or bundle directory\n * @param runner - Captured subprocess runner\n */\nexport async function lint(\n this: LocalContext,\n flags: LintCommandFlags,\n directory: string = DEFAULT_POLICY_PROJECT_DIRECTORY,\n runner: CapturedProcessRunner = runCapturedProcess,\n): Promise<void> {\n doneInputValidation(this.process);\n\n const { fix = false, noInteractive = false, json = false } = flags;\n const resolvedDir = resolvePolicyProjectDirectory(this.process.cwd(), directory);\n\n if (!this.fs.existsSync(resolvedDir) || !this.fs.statSync(resolvedDir).isDirectory()) {\n const missing: PolicyLintResult = {\n version: POLICY_LINT_RESULT_VERSION,\n status: 'failed',\n directory: resolvedDir,\n fix,\n tools: { opa: null, regal: null },\n checks: POLICY_LINT_CHECK_NAMES.map((name) => ({\n name,\n status: name === 'manifest' ? 'failed' : 'skipped',\n })),\n unformattedFiles: [],\n fixedFiles: [],\n diagnostics: [\n {\n code: 'project.directory',\n severity: 'error',\n message: `Policy directory does not exist or is not a directory: ${resolvedDir}`,\n path: path.relative(this.process.cwd(), resolvedDir),\n },\n ],\n };\n if (json) {\n this.process.stdout.write(`${JSON.stringify(missing)}\\n`);\n } else {\n renderResult(this, missing);\n }\n this.process.exitCode = 1;\n return;\n }\n\n const bundleDirectories = discoverPolicyBundleDirectories(this, resolvedDir);\n if (bundleDirectories.length === 0) {\n const empty: PolicyLintResult = {\n version: POLICY_LINT_RESULT_VERSION,\n status: 'failed',\n directory: resolvedDir,\n fix,\n tools: { opa: null, regal: null },\n checks: POLICY_LINT_CHECK_NAMES.map((name) => ({\n name,\n status: name === 'manifest' ? 'failed' : 'skipped',\n })),\n unformattedFiles: [],\n fixedFiles: [],\n diagnostics: [\n {\n code: 'project.bundles',\n severity: 'error',\n message:\n 'No publishable policy bundles found. Add one with `transcend policy new`, ' +\n 'or pass a directory that contains a `.manifest`.',\n path: path.relative(this.process.cwd(), resolvedDir) || '.',\n },\n ],\n };\n if (json) {\n this.process.stdout.write(`${JSON.stringify(empty)}\\n`);\n } else {\n renderResult(this, empty);\n }\n this.process.exitCode = 1;\n return;\n }\n\n const results: PolicyLintResult[] = [];\n for (const bundleDirectory of bundleDirectories) {\n results.push(\n await lintBundle.call(this, { fix, noInteractive, json }, bundleDirectory, runner),\n );\n }\n\n const failed = results.some((result) => result.status === 'failed');\n if (json) {\n if (results.length === 1) {\n this.process.stdout.write(`${JSON.stringify(results[0])}\\n`);\n } else {\n const multi: PolicyLintMultiResult = {\n version: POLICY_LINT_MULTI_RESULT_VERSION,\n status: failed ? 'failed' : 'passed',\n directory: resolvedDir,\n fix,\n results,\n };\n this.process.stdout.write(`${JSON.stringify(multi)}\\n`);\n }\n } else if (results.length === 1) {\n renderResult(this, results[0]!);\n } else {\n results.forEach((result, index) => {\n if (index > 0) {\n this.logger.info('');\n }\n const relative = path.relative(this.process.cwd(), result.directory) || result.directory;\n renderResult(this, result, `Policy verification — ${relative}`);\n });\n }\n\n if (failed) {\n this.process.exitCode = 1;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"impl-BQj1Ien4.mjs","names":[],"sources":["../src/lib/policy/policy-lint-model.ts","../src/lib/policy/policy-lint-output.ts","../src/commands/policy/lint/impl.ts"],"sourcesContent":["/** Stable policy lint result schema version. */\nexport const POLICY_LINT_RESULT_VERSION = 1;\n\n/** Stable multi-bundle lint result schema version. */\nexport const POLICY_LINT_MULTI_RESULT_VERSION = 2;\n\n/** Status of the full gate or an individual verification. */\nexport type PolicyLintStatus = 'passed' | 'failed' | 'skipped';\n\n/** One named policy verification. */\nexport interface PolicyLintCheck {\n /** Stable verification name. */\n name:\n | 'manifest'\n | 'opa-version'\n | 'regal-version'\n | 'format'\n | 'opa-check'\n | 'regal-lint'\n | 'opa-test';\n /** Verification outcome. */\n status: PolicyLintStatus;\n}\n\n/** Stable verification execution order. */\nexport const POLICY_LINT_CHECK_NAMES: PolicyLintCheck['name'][] = [\n 'manifest',\n 'opa-version',\n 'regal-version',\n 'format',\n 'opa-check',\n 'regal-lint',\n 'opa-test',\n];\n\n/** User-facing verification labels. */\nexport const POLICY_LINT_CHECK_LABELS: Readonly<Record<PolicyLintCheck['name'], string>> = {\n manifest: 'Manifest and package roots',\n 'opa-version': 'OPA 1.x',\n 'regal-version': 'Regal',\n format: 'OPA formatting',\n 'opa-check': 'OPA strict check',\n 'regal-lint': 'Regal lint',\n 'opa-test': 'OPA tests',\n};\n\n/** One machine-readable policy lint diagnostic. */\nexport interface PolicyLintDiagnostic {\n /** Stable diagnostic identifier. */\n code: string;\n /** Diagnostic severity. */\n severity: 'error';\n /** Human-readable detail, including captured tool output when available. */\n message: string;\n /** Optional path relative to the invocation directory. */\n path?: string;\n}\n\n/** Detected local policy tool versions. */\nexport interface PolicyLintTools {\n /** Detected OPA version, or null when missing or unsupported. */\n opa: string | null;\n /** Detected Regal version, or null when missing or unsupported. */\n regal: string | null;\n}\n\n/** Stable result emitted by `transcend policy lint --json` for one bundle. */\nexport interface PolicyLintResult {\n /** Result schema version. */\n version: typeof POLICY_LINT_RESULT_VERSION;\n /** Overall verification outcome. */\n status: Exclude<PolicyLintStatus, 'skipped'>;\n /** Absolute policy bundle directory. */\n directory: string;\n /** Whether formatting repair was explicitly requested. */\n fix: boolean;\n /** Detected supported tool versions. */\n tools: PolicyLintTools;\n /** Verification outcomes in stable execution order. */\n checks: PolicyLintCheck[];\n /** Files found to need OPA formatting, relative to the policy directory. */\n unformattedFiles: string[];\n /** Files repaired with OPA formatting, relative to the policy directory. */\n fixedFiles: string[];\n /** Ordered verification diagnostics. */\n diagnostics: PolicyLintDiagnostic[];\n}\n\n/**\n * Stable result when `transcend policy lint --json` verifies multiple bundles.\n *\n * Emitted only when the selected path is a workspace with more than one\n * publishable `*-bundle/` directory.\n */\nexport interface PolicyLintMultiResult {\n /** Result schema version. */\n version: typeof POLICY_LINT_MULTI_RESULT_VERSION;\n /** Overall verification outcome across all bundles. */\n status: Exclude<PolicyLintStatus, 'skipped'>;\n /** Absolute policy workspace directory that was searched. */\n directory: string;\n /** Whether formatting repair was explicitly requested. */\n fix: boolean;\n /** Per-bundle results in discovery order. */\n results: PolicyLintResult[];\n}\n","import path from 'node:path';\n\nimport type { CapturedProcessResult } from '../cli/run-captured-process.js';\n\n/**\n * Use captured tool output as a concise diagnostic.\n *\n * @param result - Captured process result\n * @param fallback - Message used when the tool emitted no output\n * @returns Diagnostic message\n */\nexport function getPolicyProcessFailureMessage(\n result: CapturedProcessResult,\n fallback: string,\n): string {\n const output = [result.stdout.trim(), result.stderr.trim()].filter(Boolean).join('\\n');\n return output || fallback;\n}\n\n/**\n * Convert absolute OPA formatter paths to stable project-relative paths.\n *\n * @param stdout - `opa fmt --list` output\n * @param projectDirectory - Absolute policy directory\n * @returns Sorted unique paths\n */\nexport function parseUnformattedPolicyFiles(stdout: string, projectDirectory: string): string[] {\n return [\n ...new Set(\n stdout\n .split(/\\r?\\n/gu)\n .map((file) => file.trim())\n .filter(Boolean)\n .map((file) =>\n path.isAbsolute(file)\n ? path.relative(projectDirectory, file).split(path.sep).join('/')\n : file.split(path.sep).join('/'),\n ),\n ),\n ].sort();\n}\n","import path from 'node:path';\n\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport {\n runCapturedProcess,\n type CapturedProcessRunner,\n} from '../../../lib/cli/run-captured-process.js';\nimport { inquirerConfirmBoolean } from '../../../lib/helpers/inquirer.js';\nimport {\n type PolicyBundleRegoFile,\n validatePolicyBundleContents,\n} from '../../../lib/policy/policy-bundle-manifest.js';\nimport {\n type PolicyLintCheck,\n type PolicyLintDiagnostic,\n type PolicyLintMultiResult,\n type PolicyLintResult,\n POLICY_LINT_CHECK_LABELS,\n POLICY_LINT_CHECK_NAMES,\n POLICY_LINT_MULTI_RESULT_VERSION,\n POLICY_LINT_RESULT_VERSION,\n} from '../../../lib/policy/policy-lint-model.js';\nimport {\n getPolicyProcessFailureMessage,\n parseUnformattedPolicyFiles,\n} from '../../../lib/policy/policy-lint-output.js';\nimport {\n DEFAULT_POLICY_PROJECT_DIRECTORY,\n discoverPolicyBundleDirectories,\n resolvePolicyProjectDirectory,\n} from '../../../lib/policy/policy-project-discovery.js';\nimport {\n OPA_MISSING_MESSAGE,\n parsePolicyToolVersion,\n REGAL_MISSING_MESSAGE,\n unsupportedOpaVersionMessage,\n unsupportedRegalVersionMessage,\n} from '../../../lib/policy/policy-runtime.js';\nimport { POLICY_MANIFEST_FILENAME } from '../../../lib/policy/policy-scaffold-templates.js';\nimport { isInteractivePromptInvocation } from '../../../lib/scaffolding/prompts.js';\n\n/** CLI flags for `transcend policy lint`. */\nexport interface LintCommandFlags {\n /** Apply OPA formatting. */\n fix: boolean;\n /** Disable the optional formatting confirmation. */\n noInteractive: boolean;\n /** Emit one stable JSON result on stdout. */\n json: boolean;\n}\n\n/**\n * Collect Rego source snapshots without following symlinks.\n *\n * @param context - CLI context\n * @param projectDirectory - Absolute policy directory\n * @param currentDirectory - Current recursive directory\n * @returns Deterministically ordered Rego snapshots\n */\nfunction collectRegoFiles(\n context: LocalContext,\n projectDirectory: string,\n currentDirectory: string = projectDirectory,\n): PolicyBundleRegoFile[] {\n return context.fs\n .readdirSync(currentDirectory, { withFileTypes: true })\n .sort((left, right) => left.name.localeCompare(right.name))\n .flatMap((entry) => {\n const absolutePath = path.join(currentDirectory, entry.name);\n if (entry.isDirectory()) {\n return collectRegoFiles(context, projectDirectory, absolutePath);\n }\n if (!entry.isFile() || !entry.name.endsWith('.rego')) {\n return [];\n }\n return [\n {\n path: path.relative(projectDirectory, absolutePath).split(path.sep).join('/'),\n contents: context.fs.readFileSync(absolutePath, 'utf8'),\n },\n ];\n });\n}\n\n/**\n * Resolve a Regal config file for a bundle, walking up to the workspace.\n *\n * @param context - CLI context\n * @param bundleDirectory - Absolute bundle directory\n * @returns Absolute config path, or undefined when none is found\n */\nfunction resolveRegalConfigFile(\n context: LocalContext,\n bundleDirectory: string,\n): string | undefined {\n let current = bundleDirectory;\n for (;;) {\n const nestedRegalConfig = path.join(current, '.regal', 'config.yaml');\n if (context.fs.existsSync(nestedRegalConfig)) {\n return nestedRegalConfig;\n }\n const rootRegalConfig = path.join(current, '.regal.yaml');\n if (context.fs.existsSync(rootRegalConfig)) {\n return rootRegalConfig;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n return undefined;\n }\n current = parent;\n }\n}\n\n/**\n * Render the terminal summary for a policy verification result.\n *\n * @param context - CLI context\n * @param result - Completed verification result\n * @param heading - Optional section heading when linting multiple bundles\n */\nfunction renderResult(context: LocalContext, result: PolicyLintResult, heading?: string): void {\n if (heading) {\n context.logger.info(`${colors.bold(heading)}\\n`);\n } else {\n context.logger.info(`${colors.bold('Policy verification')}\\n`);\n }\n result.checks.forEach(({ name, status }) => {\n const label = status === 'passed' ? 'PASS' : status === 'failed' ? 'FAIL' : 'SKIP';\n const styledLabel =\n status === 'passed'\n ? colors.green(label)\n : status === 'failed'\n ? colors.red(label)\n : colors.yellow(label);\n const version =\n name === 'opa-version' && result.tools.opa\n ? ` (${result.tools.opa})`\n : name === 'regal-version' && result.tools.regal\n ? ` (${result.tools.regal})`\n : '';\n context.logger.info(`${styledLabel} ${POLICY_LINT_CHECK_LABELS[name]}${version}`);\n });\n if (result.diagnostics.length > 0) {\n context.logger.error('');\n }\n result.diagnostics.forEach((diagnostic) => {\n const location = diagnostic.path ? `${diagnostic.path}: ` : '';\n context.logger.error(\n colors.red(`error [${diagnostic.code}]: ${location}${diagnostic.message}`),\n );\n });\n if (result.status === 'passed') {\n context.logger.info('');\n context.logger.info(colors.green('Policy verification passed.'));\n } else {\n context.logger.error('');\n context.logger.error(colors.red('Policy verification failed.'));\n }\n}\n\n/**\n * Verify one publishable policy bundle directory.\n *\n * @param context - CLI context\n * @param flags - Command flags\n * @param resolvedDir - Absolute bundle directory\n * @param runner - Captured subprocess runner\n * @returns Completed verification result\n */\nasync function lintBundle(\n this: LocalContext,\n { fix, noInteractive, json }: LintCommandFlags,\n resolvedDir: string,\n runner: CapturedProcessRunner,\n): Promise<PolicyLintResult> {\n const checks: PolicyLintCheck[] = POLICY_LINT_CHECK_NAMES.map((name) => ({\n name,\n status: 'skipped',\n }));\n const diagnostics: PolicyLintDiagnostic[] = [];\n const result: PolicyLintResult = {\n version: POLICY_LINT_RESULT_VERSION,\n status: 'passed',\n directory: resolvedDir,\n fix,\n tools: { opa: null, regal: null },\n checks,\n unformattedFiles: [],\n fixedFiles: [],\n diagnostics,\n };\n const setStatus = (name: PolicyLintCheck['name'], status: PolicyLintCheck['status']): void => {\n checks.find((check) => check.name === name)!.status = status;\n };\n const addError = (code: string, message: string, diagnosticPath?: string): void => {\n diagnostics.push({\n code,\n severity: 'error',\n message,\n ...(diagnosticPath ? { path: diagnosticPath } : {}),\n });\n };\n\n if (!this.fs.existsSync(resolvedDir) || !this.fs.statSync(resolvedDir).isDirectory()) {\n setStatus('manifest', 'failed');\n addError(\n 'project.directory',\n `Policy directory does not exist or is not a directory: ${resolvedDir}`,\n path.relative(this.process.cwd(), resolvedDir),\n );\n result.status = 'failed';\n return result;\n }\n\n const manifestPath = path.join(resolvedDir, POLICY_MANIFEST_FILENAME);\n try {\n validatePolicyBundleContents(\n this.fs.existsSync(manifestPath) ? this.fs.readFileSync(manifestPath, 'utf8') : undefined,\n collectRegoFiles(this, resolvedDir),\n );\n setStatus('manifest', 'passed');\n } catch (error) {\n setStatus('manifest', 'failed');\n addError(\n 'manifest.invalid',\n error instanceof Error ? error.message : String(error),\n path.relative(this.process.cwd(), manifestPath),\n );\n }\n\n const opaVersionResult = await runner('opa', ['version'], { cwd: resolvedDir }, this);\n if (opaVersionResult.error?.code === 'ENOENT') {\n setStatus('opa-version', 'failed');\n addError('opa.missing', OPA_MISSING_MESSAGE);\n } else {\n const opaVersionOutput = `${opaVersionResult.stdout}\\n${opaVersionResult.stderr}`;\n const unsupportedOpa = unsupportedOpaVersionMessage(opaVersionOutput);\n if (opaVersionResult.code !== 0 || unsupportedOpa) {\n setStatus('opa-version', 'failed');\n addError(\n 'opa.version',\n unsupportedOpa ??\n getPolicyProcessFailureMessage(\n opaVersionResult,\n 'Unable to determine the installed OPA version.',\n ),\n );\n } else {\n result.tools.opa = parsePolicyToolVersion(opaVersionOutput)!.version;\n setStatus('opa-version', 'passed');\n }\n }\n\n const regalVersionResult = await runner('regal', ['version'], { cwd: resolvedDir }, this);\n if (regalVersionResult.error?.code === 'ENOENT') {\n setStatus('regal-version', 'failed');\n addError('regal.missing', REGAL_MISSING_MESSAGE);\n } else {\n const regalVersionOutput = `${regalVersionResult.stdout}\\n${regalVersionResult.stderr}`;\n const unsupportedRegal = unsupportedRegalVersionMessage(regalVersionOutput);\n if (regalVersionResult.code !== 0 || unsupportedRegal) {\n setStatus('regal-version', 'failed');\n addError(\n 'regal.version',\n unsupportedRegal ??\n getPolicyProcessFailureMessage(\n regalVersionResult,\n 'Unable to determine the installed Regal version.',\n ),\n );\n } else {\n result.tools.regal = parsePolicyToolVersion(regalVersionOutput)!.version;\n setStatus('regal-version', 'passed');\n }\n }\n\n if (result.tools.opa) {\n const formatResult = await runner(\n 'opa',\n ['fmt', '--list', resolvedDir],\n { cwd: resolvedDir },\n this,\n );\n if (formatResult.code !== 0) {\n setStatus('format', 'failed');\n addError(\n 'opa.format',\n getPolicyProcessFailureMessage(\n formatResult,\n `opa fmt --list failed with exit code ${formatResult.code}`,\n ),\n );\n } else {\n result.unformattedFiles = parseUnformattedPolicyFiles(formatResult.stdout, resolvedDir);\n if (result.unformattedFiles.length === 0) {\n setStatus('format', 'passed');\n } else {\n let shouldFormat = fix;\n const interactive = isInteractivePromptInvocation(\n { json, noInteractive },\n this.process.stdin.isTTY,\n this.process.stderr.isTTY,\n );\n if (!json && !fix) {\n this.logger.error(colors.red('Policy files are not formatted:'));\n result.unformattedFiles.forEach((file) => {\n this.logger.error(colors.red(` - ${file}`));\n });\n const diffResult = await runner(\n 'opa',\n ['fmt', '--diff', resolvedDir],\n { cwd: resolvedDir },\n this,\n );\n const diff = diffResult.stdout.trim() || diffResult.stderr.trim();\n if (diff) {\n this.logger.error('');\n this.logger.error(diff);\n }\n }\n if (!fix && interactive) {\n try {\n shouldFormat = await inquirerConfirmBoolean({\n message: 'Format the unformatted policy files listed above?',\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (/force closed|prompt.*cancel|user.*close|SIGINT/iu.test(message)) {\n this.process.exit(130);\n }\n throw error;\n }\n }\n if (shouldFormat) {\n const writeResult = await runner(\n 'opa',\n ['fmt', '--write', resolvedDir],\n { cwd: resolvedDir },\n this,\n );\n if (writeResult.code === 0) {\n result.fixedFiles = [...result.unformattedFiles];\n setStatus('format', 'passed');\n } else {\n setStatus('format', 'failed');\n addError(\n 'opa.format-fix',\n getPolicyProcessFailureMessage(\n writeResult,\n `opa fmt --write failed with exit code ${writeResult.code}`,\n ),\n );\n }\n } else {\n setStatus('format', 'failed');\n addError(\n 'opa.format-required',\n 'Policy files are not formatted. Re-run `transcend policy lint --fix` to repair them.',\n );\n }\n }\n }\n\n const checkResult = await runner(\n 'opa',\n ['check', '--strict', '--ignore', '*_test.rego', resolvedDir],\n { cwd: resolvedDir },\n this,\n );\n if (checkResult.code === 0) {\n setStatus('opa-check', 'passed');\n } else {\n setStatus('opa-check', 'failed');\n addError(\n 'opa.check',\n getPolicyProcessFailureMessage(\n checkResult,\n `opa check failed with exit code ${checkResult.code}`,\n ),\n );\n }\n }\n\n if (result.tools.regal) {\n const regalConfig = resolveRegalConfigFile(this, resolvedDir);\n const regalResult = await runner(\n 'regal',\n [\n 'lint',\n '--fail-level',\n 'warning',\n ...(regalConfig ? ['--config-file', regalConfig] : []),\n resolvedDir,\n ],\n { cwd: resolvedDir },\n this,\n );\n if (regalResult.code === 0) {\n setStatus('regal-lint', 'passed');\n } else {\n setStatus('regal-lint', 'failed');\n addError(\n 'regal.lint',\n getPolicyProcessFailureMessage(\n regalResult,\n `regal lint failed with exit code ${regalResult.code}`,\n ),\n );\n }\n }\n\n if (result.tools.opa) {\n const testResult = await runner(\n 'opa',\n ['test', '--fail-on-empty', '-b', resolvedDir],\n { cwd: resolvedDir },\n this,\n );\n if (testResult.code === 0) {\n setStatus('opa-test', 'passed');\n } else {\n setStatus('opa-test', 'failed');\n addError(\n 'opa.test',\n getPolicyProcessFailureMessage(\n testResult,\n `opa test --fail-on-empty -b failed with exit code ${testResult.code}`,\n ),\n );\n }\n }\n\n result.status = checks.some(({ status }) => status === 'failed') ? 'failed' : 'passed';\n return result;\n}\n\n/**\n * Verify local policy bundles with the shared upload contract, OPA, and Regal.\n *\n * With no directory (or the default workspace path), discovers every immediate\n * child that contains a `.manifest` and verifies each. Pass one bundle path to\n * verify a single publishable unit.\n *\n * @param this - CLI context\n * @param flags - Command flags\n * @param directory - Policy workspace or bundle directory\n * @param runner - Captured subprocess runner\n */\nexport async function lint(\n this: LocalContext,\n flags: LintCommandFlags,\n directory: string = DEFAULT_POLICY_PROJECT_DIRECTORY,\n runner: CapturedProcessRunner = runCapturedProcess,\n): Promise<void> {\n doneInputValidation(this.process);\n\n const { fix = false, noInteractive = false, json = false } = flags;\n const resolvedDir = resolvePolicyProjectDirectory(this.process.cwd(), directory);\n\n if (!this.fs.existsSync(resolvedDir) || !this.fs.statSync(resolvedDir).isDirectory()) {\n const missing: PolicyLintResult = {\n version: POLICY_LINT_RESULT_VERSION,\n status: 'failed',\n directory: resolvedDir,\n fix,\n tools: { opa: null, regal: null },\n checks: POLICY_LINT_CHECK_NAMES.map((name) => ({\n name,\n status: name === 'manifest' ? 'failed' : 'skipped',\n })),\n unformattedFiles: [],\n fixedFiles: [],\n diagnostics: [\n {\n code: 'project.directory',\n severity: 'error',\n message: `Policy directory does not exist or is not a directory: ${resolvedDir}`,\n path: path.relative(this.process.cwd(), resolvedDir),\n },\n ],\n };\n if (json) {\n this.process.stdout.write(`${JSON.stringify(missing)}\\n`);\n } else {\n renderResult(this, missing);\n }\n this.process.exitCode = 1;\n return;\n }\n\n const bundleDirectories = discoverPolicyBundleDirectories(this, resolvedDir);\n if (bundleDirectories.length === 0) {\n const empty: PolicyLintResult = {\n version: POLICY_LINT_RESULT_VERSION,\n status: 'failed',\n directory: resolvedDir,\n fix,\n tools: { opa: null, regal: null },\n checks: POLICY_LINT_CHECK_NAMES.map((name) => ({\n name,\n status: name === 'manifest' ? 'failed' : 'skipped',\n })),\n unformattedFiles: [],\n fixedFiles: [],\n diagnostics: [\n {\n code: 'project.bundles',\n severity: 'error',\n message:\n 'No publishable policy bundles found. Add one with `transcend policy new`, ' +\n 'or pass a directory that contains a `.manifest`.',\n path: path.relative(this.process.cwd(), resolvedDir) || '.',\n },\n ],\n };\n if (json) {\n this.process.stdout.write(`${JSON.stringify(empty)}\\n`);\n } else {\n renderResult(this, empty);\n }\n this.process.exitCode = 1;\n return;\n }\n\n const results: PolicyLintResult[] = [];\n for (const bundleDirectory of bundleDirectories) {\n results.push(\n await lintBundle.call(this, { fix, noInteractive, json }, bundleDirectory, runner),\n );\n }\n\n const failed = results.some((result) => result.status === 'failed');\n if (json) {\n if (results.length === 1) {\n this.process.stdout.write(`${JSON.stringify(results[0])}\\n`);\n } else {\n const multi: PolicyLintMultiResult = {\n version: POLICY_LINT_MULTI_RESULT_VERSION,\n status: failed ? 'failed' : 'passed',\n directory: resolvedDir,\n fix,\n results,\n };\n this.process.stdout.write(`${JSON.stringify(multi)}\\n`);\n }\n } else if (results.length === 1) {\n renderResult(this, results[0]!);\n } else {\n results.forEach((result, index) => {\n if (index > 0) {\n this.logger.info('');\n }\n const relative = path.relative(this.process.cwd(), result.directory) || result.directory;\n renderResult(this, result, `Policy verification — ${relative}`);\n });\n }\n\n if (failed) {\n this.process.exitCode = 1;\n }\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{t as e}from"./markSilentPrivacyRequests-gKYivzH1.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";async function n({auth:n,transcendUrl:r,actions:i,statuses:a,requestIds:o,createdAtBefore:s,createdAtAfter:c,updatedAtBefore:l,updatedAtAfter:u,concurrency:d}){t(this.process),await e({transcendUrl:r,requestActions:i,auth:n,requestIds:o,statuses:a,concurrency:d,createdAtBefore:s,createdAtAfter:c,updatedAtBefore:l,updatedAtAfter:u})}export{n as markSilent};
2
- //# sourceMappingURL=impl-CU38kdj8.mjs.map
1
+ import{t as e}from"./markSilentPrivacyRequests-D3bFOMLh.mjs";import{t}from"./done-input-validation-LiTaCEzF.mjs";async function n({auth:n,transcendUrl:r,actions:i,statuses:a,requestIds:o,createdAtBefore:s,createdAtAfter:c,updatedAtBefore:l,updatedAtAfter:u,concurrency:d}){t(this.process),await e({transcendUrl:r,requestActions:i,auth:n,requestIds:o,statuses:a,concurrency:d,createdAtBefore:s,createdAtAfter:c,updatedAtBefore:l,updatedAtAfter:u})}export{n as markSilent};
2
+ //# sourceMappingURL=impl-BRFL8xp7.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"impl-CU38kdj8.mjs","names":[],"sources":["../src/commands/request/mark-silent/impl.ts"],"sourcesContent":["import type { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { markSilentPrivacyRequests } from '../../../lib/requests/index.js';\n\nexport interface MarkSilentCommandFlags {\n auth: string;\n actions: RequestAction[];\n statuses?: RequestStatus[];\n requestIds?: string[];\n createdAtBefore?: Date;\n createdAtAfter?: Date;\n updatedAtBefore?: Date;\n updatedAtAfter?: Date;\n transcendUrl: string;\n concurrency: number;\n}\n\nexport async function markSilent(\n this: LocalContext,\n {\n auth,\n transcendUrl,\n actions,\n statuses,\n requestIds,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n concurrency,\n }: MarkSilentCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n await markSilentPrivacyRequests({\n transcendUrl,\n requestActions: actions,\n auth,\n requestIds,\n statuses,\n concurrency,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n });\n}\n"],"mappings":"iHAmBA,eAAsB,EAEpB,CACE,OACA,eACA,UACA,WACA,aACA,kBACA,iBACA,kBACA,iBACA,eAEa,CACf,EAAoB,KAAK,QAAQ,CAEjC,MAAM,EAA0B,CAC9B,eACA,eAAgB,EAChB,OACA,aACA,WACA,cACA,kBACA,iBACA,kBACA,iBACD,CAAC"}
1
+ {"version":3,"file":"impl-BRFL8xp7.mjs","names":[],"sources":["../src/commands/request/mark-silent/impl.ts"],"sourcesContent":["import type { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { markSilentPrivacyRequests } from '../../../lib/requests/index.js';\n\nexport interface MarkSilentCommandFlags {\n auth: string;\n actions: RequestAction[];\n statuses?: RequestStatus[];\n requestIds?: string[];\n createdAtBefore?: Date;\n createdAtAfter?: Date;\n updatedAtBefore?: Date;\n updatedAtAfter?: Date;\n transcendUrl: string;\n concurrency: number;\n}\n\nexport async function markSilent(\n this: LocalContext,\n {\n auth,\n transcendUrl,\n actions,\n statuses,\n requestIds,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n concurrency,\n }: MarkSilentCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n await markSilentPrivacyRequests({\n transcendUrl,\n requestActions: actions,\n auth,\n requestIds,\n statuses,\n concurrency,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n });\n}\n"],"mappings":"iHAmBA,eAAsB,EAEpB,CACE,OACA,eACA,UACA,WACA,aACA,kBACA,iBACA,kBACA,iBACA,eAEa,CACf,EAAoB,KAAK,QAAQ,CAEjC,MAAM,EAA0B,CAC9B,eACA,eAAgB,EAChB,OACA,aACA,WACA,cACA,kBACA,iBACA,kBACA,iBACD,CAAC"}
@@ -1,2 +1,2 @@
1
- import{i as e,n as t,t as n}from"./policy-project-discovery-C29UxWwt.mjs";import{n as r,r as i}from"./runOpa-ojIqU1tO.mjs";import{t as a}from"./done-input-validation-LiTaCEzF.mjs";import o from"node:path";import s from"colors";async function c({format:c,verbose:l,run:u,coverage:d,threshold:f,timeout:p,"var-values":m,explain:h,schema:g,"exit-zero-on-skipped":_},v=n){a(this.process),i();let y=e(this.process.cwd(),v);if(!this.fs.existsSync(y)||!this.fs.statSync(y).isDirectory())throw Error(`Policy directory does not exist or is not a directory: ${y}`);if(f!==void 0&&!d)throw Error(`--threshold requires --coverage.`);if(f!==void 0){let e=Number(f);if(!Number.isFinite(e)||e<0||e>100)throw Error(`--threshold must be a number between 0 and 100, got: ${f}`)}let b=g?o.resolve(this.process.cwd(),g):void 0;if(b&&!this.fs.existsSync(b))throw Error(`Schema path not found: ${b}`);let x=t(this,y);if(x.length===0)throw Error("No publishable policy bundles found. Add one with `transcend policy new`, or pass a directory that contains a `.manifest`.");for(let e of x){this.logger.info(s.green(`Running policy tests in ${e}...`));let t=await r([`test`,`--fail-on-empty`,`-b`,e,`--format`,c,...l?[`--verbose`]:[],...u?[`--run`,u]:[],...d?[`--coverage`]:[],...f===void 0?[]:[`--threshold`,f],...p?[`--timeout`,p]:[],...m?[`--var-values`]:[],...h?[`--explain`,h]:[],...b?[`--schema`,b]:[],..._?[`--exit-zero-on-skipped`]:[]]);t!==0&&this.process.exit(t)}this.logger.info(s.green(`Policy tests passed.`))}export{c as test};
2
- //# sourceMappingURL=impl-eeS2lVi5.mjs.map
1
+ import{i as e,n as t,t as n}from"./policy-project-discovery-B4cFXUlA.mjs";import{n as r,r as i}from"./runOpa-ojIqU1tO.mjs";import{t as a}from"./done-input-validation-LiTaCEzF.mjs";import o from"node:path";import s from"colors";async function c({format:c,verbose:l,run:u,coverage:d,threshold:f,timeout:p,"var-values":m,explain:h,schema:g,"exit-zero-on-skipped":_},v=n){a(this.process),i();let y=e(this.process.cwd(),v);if(!this.fs.existsSync(y)||!this.fs.statSync(y).isDirectory())throw Error(`Policy directory does not exist or is not a directory: ${y}`);if(f!==void 0&&!d)throw Error(`--threshold requires --coverage.`);if(f!==void 0){let e=Number(f);if(!Number.isFinite(e)||e<0||e>100)throw Error(`--threshold must be a number between 0 and 100, got: ${f}`)}let b=g?o.resolve(this.process.cwd(),g):void 0;if(b&&!this.fs.existsSync(b))throw Error(`Schema path not found: ${b}`);let x=t(this,y);if(x.length===0)throw Error("No publishable policy bundles found. Add one with `transcend policy new`, or pass a directory that contains a `.manifest`.");for(let e of x){this.logger.info(s.green(`Running policy tests in ${e}...`));let t=await r([`test`,`--fail-on-empty`,`-b`,e,`--format`,c,...l?[`--verbose`]:[],...u?[`--run`,u]:[],...d?[`--coverage`]:[],...f===void 0?[]:[`--threshold`,f],...p?[`--timeout`,p]:[],...m?[`--var-values`]:[],...h?[`--explain`,h]:[],...b?[`--schema`,b]:[],..._?[`--exit-zero-on-skipped`]:[]]);t!==0&&this.process.exit(t)}this.logger.info(s.green(`Policy tests passed.`))}export{c as test};
2
+ //# sourceMappingURL=impl-BTvZxws5.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"impl-eeS2lVi5.mjs","names":[],"sources":["../src/commands/policy/test/impl.ts"],"sourcesContent":["import path from 'node:path';\n\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport {\n DEFAULT_POLICY_PROJECT_DIRECTORY,\n discoverPolicyBundleDirectories,\n resolvePolicyProjectDirectory,\n} from '../../../lib/policy/policy-project-discovery.js';\nimport { assertOpaInstalled, runOpa } from '../helpers/index.js';\nimport type { PolicyTestExplainMode, PolicyTestFormat } from './command.js';\n\n/** CLI flags for `transcend policy test`. */\nexport interface TestCommandFlags {\n /** `opa test --format` value. */\n format: PolicyTestFormat;\n /** `opa test --verbose`. */\n verbose: boolean;\n /** Optional `opa test --run` regex. */\n run?: string;\n /** `opa test --coverage`. */\n coverage: boolean;\n /** Optional `opa test --threshold` coverage percent. */\n threshold?: string;\n /** Optional `opa test --timeout` duration. */\n timeout?: string;\n /** `opa test --var-values`. */\n 'var-values': boolean;\n /** Optional `opa test --explain` mode. */\n explain?: PolicyTestExplainMode;\n /** Optional `opa test --schema` path. */\n schema?: string;\n /** `opa test --exit-zero-on-skipped`. */\n 'exit-zero-on-skipped': boolean;\n}\n\n/**\n * Run OPA tests against local policy bundles.\n *\n * With no directory (or the default workspace path), discovers every immediate\n * child that contains a `.manifest` and tests each. Pass one bundle path to\n * test a single publishable unit.\n *\n * @param this - CLI context\n * @param flags - Command flags\n * @param directory - Policy workspace or bundle directory\n */\nexport async function test(\n this: LocalContext,\n {\n format,\n verbose,\n run,\n coverage,\n threshold,\n timeout,\n 'var-values': varValues,\n explain,\n schema,\n 'exit-zero-on-skipped': exitZeroOnSkipped,\n }: TestCommandFlags,\n directory: string = DEFAULT_POLICY_PROJECT_DIRECTORY,\n): Promise<void> {\n doneInputValidation(this.process);\n\n assertOpaInstalled();\n const resolvedDir = resolvePolicyProjectDirectory(this.process.cwd(), directory);\n if (!this.fs.existsSync(resolvedDir) || !this.fs.statSync(resolvedDir).isDirectory()) {\n throw new Error(`Policy directory does not exist or is not a directory: ${resolvedDir}`);\n }\n\n if (threshold !== undefined && !coverage) {\n throw new Error('--threshold requires --coverage.');\n }\n if (threshold !== undefined) {\n const parsed = Number(threshold);\n if (!Number.isFinite(parsed) || parsed < 0 || parsed > 100) {\n throw new Error(`--threshold must be a number between 0 and 100, got: ${threshold}`);\n }\n }\n\n const schemaPath = schema ? path.resolve(this.process.cwd(), schema) : undefined;\n if (schemaPath && !this.fs.existsSync(schemaPath)) {\n throw new Error(`Schema path not found: ${schemaPath}`);\n }\n\n const bundleDirectories = discoverPolicyBundleDirectories(this, resolvedDir);\n if (bundleDirectories.length === 0) {\n throw new Error(\n 'No publishable policy bundles found. Add one with `transcend policy new`, ' +\n 'or pass a directory that contains a `.manifest`.',\n );\n }\n\n for (const bundleDirectory of bundleDirectories) {\n this.logger.info(colors.green(`Running policy tests in ${bundleDirectory}...`));\n const exitCode = await runOpa([\n 'test',\n '--fail-on-empty',\n '-b',\n bundleDirectory,\n '--format',\n format,\n ...(verbose ? ['--verbose'] : []),\n ...(run ? ['--run', run] : []),\n ...(coverage ? ['--coverage'] : []),\n ...(threshold !== undefined ? ['--threshold', threshold] : []),\n ...(timeout ? ['--timeout', timeout] : []),\n ...(varValues ? ['--var-values'] : []),\n ...(explain ? ['--explain', explain] : []),\n ...(schemaPath ? ['--schema', schemaPath] : []),\n ...(exitZeroOnSkipped ? ['--exit-zero-on-skipped'] : []),\n ]);\n if (exitCode !== 0) {\n this.process.exit(exitCode);\n }\n }\n\n this.logger.info(colors.green('Policy tests passed.'));\n}\n"],"mappings":"mOAiDA,eAAsB,EAEpB,CACE,SACA,UACA,MACA,WACA,YACA,UACA,aAAc,EACd,UACA,SACA,uBAAwB,GAE1B,EAAoB,EACL,CACf,EAAoB,KAAK,QAAQ,CAEjC,GAAoB,CACpB,IAAM,EAAc,EAA8B,KAAK,QAAQ,KAAK,CAAE,EAAU,CAChF,GAAI,CAAC,KAAK,GAAG,WAAW,EAAY,EAAI,CAAC,KAAK,GAAG,SAAS,EAAY,CAAC,aAAa,CAClF,MAAU,MAAM,0DAA0D,IAAc,CAG1F,GAAI,IAAc,IAAA,IAAa,CAAC,EAC9B,MAAU,MAAM,mCAAmC,CAErD,GAAI,IAAc,IAAA,GAAW,CAC3B,IAAM,EAAS,OAAO,EAAU,CAChC,GAAI,CAAC,OAAO,SAAS,EAAO,EAAI,EAAS,GAAK,EAAS,IACrD,MAAU,MAAM,wDAAwD,IAAY,CAIxF,IAAM,EAAa,EAAS,EAAK,QAAQ,KAAK,QAAQ,KAAK,CAAE,EAAO,CAAG,IAAA,GACvE,GAAI,GAAc,CAAC,KAAK,GAAG,WAAW,EAAW,CAC/C,MAAU,MAAM,0BAA0B,IAAa,CAGzD,IAAM,EAAoB,EAAgC,KAAM,EAAY,CAC5E,GAAI,EAAkB,SAAW,EAC/B,MAAU,MACR,6HAED,CAGH,IAAK,IAAM,KAAmB,EAAmB,CAC/C,KAAK,OAAO,KAAK,EAAO,MAAM,2BAA2B,EAAgB,KAAK,CAAC,CAC/E,IAAM,EAAW,MAAM,EAAO,CAC5B,OACA,kBACA,KACA,EACA,WACA,EACA,GAAI,EAAU,CAAC,YAAY,CAAG,EAAE,CAChC,GAAI,EAAM,CAAC,QAAS,EAAI,CAAG,EAAE,CAC7B,GAAI,EAAW,CAAC,aAAa,CAAG,EAAE,CAClC,GAAI,IAAc,IAAA,GAAyC,EAAE,CAA/B,CAAC,cAAe,EAAU,CACxD,GAAI,EAAU,CAAC,YAAa,EAAQ,CAAG,EAAE,CACzC,GAAI,EAAY,CAAC,eAAe,CAAG,EAAE,CACrC,GAAI,EAAU,CAAC,YAAa,EAAQ,CAAG,EAAE,CACzC,GAAI,EAAa,CAAC,WAAY,EAAW,CAAG,EAAE,CAC9C,GAAI,EAAoB,CAAC,yBAAyB,CAAG,EAAE,CACxD,CAAC,CACE,IAAa,GACf,KAAK,QAAQ,KAAK,EAAS,CAI/B,KAAK,OAAO,KAAK,EAAO,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"impl-BTvZxws5.mjs","names":[],"sources":["../src/commands/policy/test/impl.ts"],"sourcesContent":["import path from 'node:path';\n\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport {\n DEFAULT_POLICY_PROJECT_DIRECTORY,\n discoverPolicyBundleDirectories,\n resolvePolicyProjectDirectory,\n} from '../../../lib/policy/policy-project-discovery.js';\nimport { assertOpaInstalled, runOpa } from '../helpers/index.js';\nimport type { PolicyTestExplainMode, PolicyTestFormat } from './command.js';\n\n/** CLI flags for `transcend policy test`. */\nexport interface TestCommandFlags {\n /** `opa test --format` value. */\n format: PolicyTestFormat;\n /** `opa test --verbose`. */\n verbose: boolean;\n /** Optional `opa test --run` regex. */\n run?: string;\n /** `opa test --coverage`. */\n coverage: boolean;\n /** Optional `opa test --threshold` coverage percent. */\n threshold?: string;\n /** Optional `opa test --timeout` duration. */\n timeout?: string;\n /** `opa test --var-values`. */\n 'var-values': boolean;\n /** Optional `opa test --explain` mode. */\n explain?: PolicyTestExplainMode;\n /** Optional `opa test --schema` path. */\n schema?: string;\n /** `opa test --exit-zero-on-skipped`. */\n 'exit-zero-on-skipped': boolean;\n}\n\n/**\n * Run OPA tests against local policy bundles.\n *\n * With no directory (or the default workspace path), discovers every immediate\n * child that contains a `.manifest` and tests each. Pass one bundle path to\n * test a single publishable unit.\n *\n * @param this - CLI context\n * @param flags - Command flags\n * @param directory - Policy workspace or bundle directory\n */\nexport async function test(\n this: LocalContext,\n {\n format,\n verbose,\n run,\n coverage,\n threshold,\n timeout,\n 'var-values': varValues,\n explain,\n schema,\n 'exit-zero-on-skipped': exitZeroOnSkipped,\n }: TestCommandFlags,\n directory: string = DEFAULT_POLICY_PROJECT_DIRECTORY,\n): Promise<void> {\n doneInputValidation(this.process);\n\n assertOpaInstalled();\n const resolvedDir = resolvePolicyProjectDirectory(this.process.cwd(), directory);\n if (!this.fs.existsSync(resolvedDir) || !this.fs.statSync(resolvedDir).isDirectory()) {\n throw new Error(`Policy directory does not exist or is not a directory: ${resolvedDir}`);\n }\n\n if (threshold !== undefined && !coverage) {\n throw new Error('--threshold requires --coverage.');\n }\n if (threshold !== undefined) {\n const parsed = Number(threshold);\n if (!Number.isFinite(parsed) || parsed < 0 || parsed > 100) {\n throw new Error(`--threshold must be a number between 0 and 100, got: ${threshold}`);\n }\n }\n\n const schemaPath = schema ? path.resolve(this.process.cwd(), schema) : undefined;\n if (schemaPath && !this.fs.existsSync(schemaPath)) {\n throw new Error(`Schema path not found: ${schemaPath}`);\n }\n\n const bundleDirectories = discoverPolicyBundleDirectories(this, resolvedDir);\n if (bundleDirectories.length === 0) {\n throw new Error(\n 'No publishable policy bundles found. Add one with `transcend policy new`, ' +\n 'or pass a directory that contains a `.manifest`.',\n );\n }\n\n for (const bundleDirectory of bundleDirectories) {\n this.logger.info(colors.green(`Running policy tests in ${bundleDirectory}...`));\n const exitCode = await runOpa([\n 'test',\n '--fail-on-empty',\n '-b',\n bundleDirectory,\n '--format',\n format,\n ...(verbose ? ['--verbose'] : []),\n ...(run ? ['--run', run] : []),\n ...(coverage ? ['--coverage'] : []),\n ...(threshold !== undefined ? ['--threshold', threshold] : []),\n ...(timeout ? ['--timeout', timeout] : []),\n ...(varValues ? ['--var-values'] : []),\n ...(explain ? ['--explain', explain] : []),\n ...(schemaPath ? ['--schema', schemaPath] : []),\n ...(exitZeroOnSkipped ? ['--exit-zero-on-skipped'] : []),\n ]);\n if (exitCode !== 0) {\n this.process.exit(exitCode);\n }\n }\n\n this.logger.info(colors.green('Policy tests passed.'));\n}\n"],"mappings":"mOAiDA,eAAsB,EAEpB,CACE,SACA,UACA,MACA,WACA,YACA,UACA,aAAc,EACd,UACA,SACA,uBAAwB,GAE1B,EAAoB,EACL,CACf,EAAoB,KAAK,QAAQ,CAEjC,GAAoB,CACpB,IAAM,EAAc,EAA8B,KAAK,QAAQ,KAAK,CAAE,EAAU,CAChF,GAAI,CAAC,KAAK,GAAG,WAAW,EAAY,EAAI,CAAC,KAAK,GAAG,SAAS,EAAY,CAAC,aAAa,CAClF,MAAU,MAAM,0DAA0D,IAAc,CAG1F,GAAI,IAAc,IAAA,IAAa,CAAC,EAC9B,MAAU,MAAM,mCAAmC,CAErD,GAAI,IAAc,IAAA,GAAW,CAC3B,IAAM,EAAS,OAAO,EAAU,CAChC,GAAI,CAAC,OAAO,SAAS,EAAO,EAAI,EAAS,GAAK,EAAS,IACrD,MAAU,MAAM,wDAAwD,IAAY,CAIxF,IAAM,EAAa,EAAS,EAAK,QAAQ,KAAK,QAAQ,KAAK,CAAE,EAAO,CAAG,IAAA,GACvE,GAAI,GAAc,CAAC,KAAK,GAAG,WAAW,EAAW,CAC/C,MAAU,MAAM,0BAA0B,IAAa,CAGzD,IAAM,EAAoB,EAAgC,KAAM,EAAY,CAC5E,GAAI,EAAkB,SAAW,EAC/B,MAAU,MACR,6HAED,CAGH,IAAK,IAAM,KAAmB,EAAmB,CAC/C,KAAK,OAAO,KAAK,EAAO,MAAM,2BAA2B,EAAgB,KAAK,CAAC,CAC/E,IAAM,EAAW,MAAM,EAAO,CAC5B,OACA,kBACA,KACA,EACA,WACA,EACA,GAAI,EAAU,CAAC,YAAY,CAAG,EAAE,CAChC,GAAI,EAAM,CAAC,QAAS,EAAI,CAAG,EAAE,CAC7B,GAAI,EAAW,CAAC,aAAa,CAAG,EAAE,CAClC,GAAI,IAAc,IAAA,GAAyC,EAAE,CAA/B,CAAC,cAAe,EAAU,CACxD,GAAI,EAAU,CAAC,YAAa,EAAQ,CAAG,EAAE,CACzC,GAAI,EAAY,CAAC,eAAe,CAAG,EAAE,CACrC,GAAI,EAAU,CAAC,YAAa,EAAQ,CAAG,EAAE,CACzC,GAAI,EAAa,CAAC,WAAY,EAAW,CAAG,EAAE,CAC9C,GAAI,EAAoB,CAAC,yBAAyB,CAAG,EAAE,CACxD,CAAC,CACE,IAAa,GACf,KAAK,QAAQ,KAAK,EAAS,CAI/B,KAAK,OAAO,KAAK,EAAO,MAAM,uBAAuB,CAAC"}
@@ -1,2 +1,2 @@
1
- import{r as e}from"./constants-BRsj50Nb.mjs";import{r as t}from"./readTranscendYaml-BfqQbPiT.mjs";import{n,t as r}from"./mergeTranscendInputs-D1CvxQu0.mjs";import{t as i}from"./parseVariablesFromString-6TYW65LF.mjs";import{t as a}from"./validateTranscendAuth-D-dDINof.mjs";import{t as o}from"./listFiles-DDGCBdtx.mjs";import{t as s}from"./done-input-validation-LiTaCEzF.mjs";import c from"node:path";import l from"colors";import{buildTranscendGraphQLClient as u}from"@transcend-io/sdk";import{mapSeries as d}from"@transcend-io/utils";async function f({transcendUrl:e,auth:t,pageSize:r,publishToPrivacyCenter:i,contents:a,deleteExtraAttributeValues:o=!1,classifyService:s=!1,logger:c}){let d=u(e,t);try{let e=await n(a,d,{pageSize:r,publishToPrivacyCenter:i,classifyService:s,deleteExtraAttributeValues:o,logger:c});return e.success||e.errors.forEach(({resource:e,item:t,message:n})=>{c.error(l.red(`Failed to sync ${e}${t?` "${t}"`:``}: ${n}`))}),e.success}catch(e){return c.error(l.red(`An unexpected error occurred syncing the schema: ${e.message}`)),!1}}async function p({file:n=`./transcend.yml`,transcendUrl:u,auth:p,variables:m,pageSize:h,publishToPrivacyCenter:g,classifyService:_,deleteExtraAttributeValues:v}){s(this.process);let y=await a(p,this),b=i(m),x;if(x=Array.isArray(y)&&this.fs.lstatSync(n).isDirectory()?o(this.fs.readdirSync(n)).map(e=>c.join(n,e)):n.split(`,`),x.length<1)throw Error(`No file specified!`);let S=x.map(e=>{this.fs.existsSync(e)?this.logger.info(l.magenta(`Reading file "${e}"...`)):(this.logger.error(l.red(`The file path does not exist on disk: ${e}. You can specify the filepath using --file=./examples/transcend.yml`)),this.process.exit(1));try{let n=t(this.fs.readFileSync(e,`utf8`),b,e);return this.logger.info(l.green(`Successfully read in "${e}"`)),{content:n,name:e.split(`/`).pop().replace(`.yml`,``)}}catch(e){this.logger.error(l.red(`The shape of your yaml file is invalid with the following errors: ${e.message}`)),this.process.exit(1)}});if(typeof y==`string`){let[t,...n]=S.map(({content:e})=>e);await f({transcendUrl:u,auth:y,contents:r(t,...n),publishToPrivacyCenter:g,deleteExtraAttributeValues:v,pageSize:h,classifyService:!!_,logger:this.logger})||(this.logger.info(l.red(`Sync encountered errors. View output above for more information, or check out ${e}`)),this.process.exit(1))}else{if(S.length!==1&&S.length!==y.length)throw Error(`Expected list of yml files to be equal to the list of API keys.Got ${S.length} YML file${S.length===1?``:`s`} and ${y.length} API key${y.length===1?``:`s`}`);let t=[];await d(y,async(e,n)=>{let r=`[${n+1}/${y.length}][${e.organizationName}] `;this.logger.info(l.magenta(`~~~\n\n${r}Attempting to push configuration...\n\n~~~`));let i=S.length===1?S[0].content:S.find(t=>t.name===e.organizationName)?.content;if(!i){this.logger.error(l.red(`${r}Failed to find transcend.yml file for organization: "${e.organizationName}".`)),t.push(e.organizationName);return}await f({transcendUrl:u,auth:e.apiKey,contents:i,pageSize:h,publishToPrivacyCenter:g,deleteExtraAttributeValues:v,classifyService:_,logger:this.logger})?this.logger.info(l.green(`${r}Successfully pushed configuration!`)):(this.logger.error(l.red(`${r}Failed to sync configuration.`)),t.push(e.organizationName))}),t.length>0&&(this.logger.info(l.red(`Sync encountered errors for "${t.join(`,`)}". View output above for more information, or check out ${e}`)),this.process.exit(1))}this.logger.info(l.green(`Successfully synced yaml file to Transcend! View at ${e}`))}export{p as push};
2
- //# sourceMappingURL=impl-D1UogVAq.mjs.map
1
+ import{r as e}from"./constants-BlKpAm3R.mjs";import{r as t}from"./readTranscendYaml-BfqQbPiT.mjs";import{n,t as r}from"./mergeTranscendInputs-B7WjxYMN.mjs";import{t as i}from"./parseVariablesFromString-6TYW65LF.mjs";import{t as a}from"./validateTranscendAuth-D-dDINof.mjs";import{t as o}from"./listFiles-DDGCBdtx.mjs";import{t as s}from"./done-input-validation-LiTaCEzF.mjs";import c from"node:path";import l from"colors";import{mapSeries as u}from"@transcend-io/utils";import{buildTranscendGraphQLClient as d}from"@transcend-io/sdk";async function f({transcendUrl:e,auth:t,pageSize:r,publishToPrivacyCenter:i,contents:a,deleteExtraAttributeValues:o=!1,classifyService:s=!1,logger:c}){let u=d(e,t);try{let e=await n(a,u,{pageSize:r,publishToPrivacyCenter:i,classifyService:s,deleteExtraAttributeValues:o,logger:c});return e.success||e.errors.forEach(({resource:e,item:t,message:n})=>{c.error(l.red(`Failed to sync ${e}${t?` "${t}"`:``}: ${n}`))}),e.success}catch(e){return c.error(l.red(`An unexpected error occurred syncing the schema: ${e.message}`)),!1}}async function p({file:n=`./transcend.yml`,transcendUrl:d,auth:p,variables:m,pageSize:h,publishToPrivacyCenter:g,classifyService:_,deleteExtraAttributeValues:v}){s(this.process);let y=await a(p,this),b=i(m),x;if(x=Array.isArray(y)&&this.fs.lstatSync(n).isDirectory()?o(this.fs.readdirSync(n)).map(e=>c.join(n,e)):n.split(`,`),x.length<1)throw Error(`No file specified!`);let S=x.map(e=>{this.fs.existsSync(e)?this.logger.info(l.magenta(`Reading file "${e}"...`)):(this.logger.error(l.red(`The file path does not exist on disk: ${e}. You can specify the filepath using --file=./examples/transcend.yml`)),this.process.exit(1));try{let n=t(this.fs.readFileSync(e,`utf8`),b,e);return this.logger.info(l.green(`Successfully read in "${e}"`)),{content:n,name:e.split(`/`).pop().replace(`.yml`,``)}}catch(e){this.logger.error(l.red(`The shape of your yaml file is invalid with the following errors: ${e.message}`)),this.process.exit(1)}});if(typeof y==`string`){let[t,...n]=S.map(({content:e})=>e);await f({transcendUrl:d,auth:y,contents:r(t,...n),publishToPrivacyCenter:g,deleteExtraAttributeValues:v,pageSize:h,classifyService:!!_,logger:this.logger})||(this.logger.info(l.red(`Sync encountered errors. View output above for more information, or check out ${e}`)),this.process.exit(1))}else{if(S.length!==1&&S.length!==y.length)throw Error(`Expected list of yml files to be equal to the list of API keys.Got ${S.length} YML file${S.length===1?``:`s`} and ${y.length} API key${y.length===1?``:`s`}`);let t=[];await u(y,async(e,n)=>{let r=`[${n+1}/${y.length}][${e.organizationName}] `;this.logger.info(l.magenta(`~~~\n\n${r}Attempting to push configuration...\n\n~~~`));let i=S.length===1?S[0].content:S.find(t=>t.name===e.organizationName)?.content;if(!i){this.logger.error(l.red(`${r}Failed to find transcend.yml file for organization: "${e.organizationName}".`)),t.push(e.organizationName);return}await f({transcendUrl:d,auth:e.apiKey,contents:i,pageSize:h,publishToPrivacyCenter:g,deleteExtraAttributeValues:v,classifyService:_,logger:this.logger})?this.logger.info(l.green(`${r}Successfully pushed configuration!`)):(this.logger.error(l.red(`${r}Failed to sync configuration.`)),t.push(e.organizationName))}),t.length>0&&(this.logger.info(l.red(`Sync encountered errors for "${t.join(`,`)}". View output above for more information, or check out ${e}`)),this.process.exit(1))}this.logger.info(l.green(`Successfully synced yaml file to Transcend! View at ${e}`))}export{p as push};
2
+ //# sourceMappingURL=impl-BVcy_GYa.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"impl-D1UogVAq.mjs","names":[],"sources":["../src/commands/inventory/push/impl.ts"],"sourcesContent":["import path from 'node:path';\n\nimport { buildTranscendGraphQLClient } from '@transcend-io/sdk';\nimport { mapSeries } from '@transcend-io/utils';\nimport colors from 'colors';\n\nimport { TranscendInput } from '../../../codecs.js';\nimport { ADMIN_DASH_INTEGRATIONS } from '../../../constants.js';\nimport type { LocalContext } from '../../../context.js';\nimport { validateTranscendAuth, filterFileNames } from '../../../lib/api-keys/index.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { syncConfigurationToTranscend } from '../../../lib/graphql/index.js';\nimport { parseVariablesFromString } from '../../../lib/helpers/parseVariablesFromString.js';\nimport { mergeTranscendInputs } from '../../../lib/mergeTranscendInputs.js';\nimport { parseTranscendYaml } from '../../../lib/readTranscendYaml.js';\n\n/**\n * Sync configuration to Transcend\n *\n * @param options - Options\n * @returns True if synced successfully, false if error occurs\n */\nasync function syncConfiguration({\n transcendUrl,\n auth,\n pageSize,\n publishToPrivacyCenter,\n contents,\n deleteExtraAttributeValues = false,\n classifyService = false,\n logger,\n}: {\n /** Transcend YAML */\n contents: TranscendInput;\n /** Transcend URL */\n transcendUrl: string;\n /** API key */\n auth: string;\n /** Page size */\n pageSize: number;\n /** Skip privacy center publish step */\n publishToPrivacyCenter: boolean;\n /** classify data flow service if missing */\n classifyService?: boolean;\n /** Delete attributes when syncing */\n deleteExtraAttributeValues?: boolean;\n /** Logger for reporting sync progress and errors */\n logger: LocalContext['logger'];\n}): Promise<boolean> {\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Sync to Transcend\n try {\n const result = await syncConfigurationToTranscend(contents, client, {\n pageSize,\n publishToPrivacyCenter,\n classifyService,\n deleteExtraAttributeValues,\n logger,\n });\n if (!result.success) {\n result.errors.forEach(({ resource, item, message }) => {\n logger.error(\n colors.red(`Failed to sync ${resource}${item ? ` \"${item}\"` : ''}: ${message}`),\n );\n });\n }\n return result.success;\n } catch (err) {\n logger.error(colors.red(`An unexpected error occurred syncing the schema: ${err.message}`));\n return false;\n }\n}\n\nexport interface PushCommandFlags {\n auth: string;\n file: string;\n transcendUrl: string;\n pageSize: number;\n variables: string;\n publishToPrivacyCenter: boolean;\n classifyService: boolean;\n deleteExtraAttributeValues: boolean;\n}\n\nexport async function push(\n this: LocalContext,\n {\n file = './transcend.yml',\n transcendUrl,\n auth,\n variables,\n pageSize,\n publishToPrivacyCenter,\n classifyService,\n deleteExtraAttributeValues,\n }: PushCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n // Parse authentication as API key or path to list of API keys\n const apiKeyOrList = await validateTranscendAuth(auth, this);\n\n const vars = parseVariablesFromString(variables);\n\n // check if we are being passed a list of API keys and a list of files\n let fileList: string[];\n if (Array.isArray(apiKeyOrList) && this.fs.lstatSync(file).isDirectory()) {\n fileList = filterFileNames(this.fs.readdirSync(file)).map((filePath) =>\n path.join(file, filePath),\n );\n } else {\n fileList = file.split(',');\n }\n\n // Ensure at least one file is parsed\n if (fileList.length < 1) {\n throw new Error('No file specified!');\n }\n\n // eslint-disable-next-line array-callback-return,consistent-return\n const transcendInputs = fileList.map((filePath) => {\n // Ensure yaml file exists on disk\n if (!this.fs.existsSync(filePath)) {\n this.logger.error(\n colors.red(\n `The file path does not exist on disk: ${filePath}. You can specify the filepath using --file=./examples/transcend.yml`,\n ),\n );\n this.process.exit(1);\n } else {\n this.logger.info(colors.magenta(`Reading file \"${filePath}\"...`));\n }\n\n try {\n // Read in the yaml file and validate it's shape\n const newContents = parseTranscendYaml(\n this.fs.readFileSync(filePath, 'utf8'),\n vars,\n filePath,\n );\n this.logger.info(colors.green(`Successfully read in \"${filePath}\"`));\n return {\n content: newContents,\n name: filePath.split('/').pop()!.replace('.yml', ''),\n };\n } catch (err) {\n this.logger.error(\n colors.red(\n `The shape of your yaml file is invalid with the following errors: ${err.message}`,\n ),\n );\n this.process.exit(1);\n }\n });\n\n // process a single API key\n if (typeof apiKeyOrList === 'string') {\n // if passed multiple inputs, merge them together\n const [base, ...rest] = transcendInputs.map(({ content }) => content);\n const contents = mergeTranscendInputs(base, ...rest);\n\n // sync the configuration\n const success = await syncConfiguration({\n transcendUrl,\n auth: apiKeyOrList,\n contents,\n publishToPrivacyCenter,\n deleteExtraAttributeValues,\n pageSize,\n classifyService: !!classifyService,\n logger: this.logger,\n });\n\n // exist with error code\n if (!success) {\n this.logger.info(\n colors.red(\n `Sync encountered errors. View output above for more information, or check out ${ADMIN_DASH_INTEGRATIONS}`,\n ),\n );\n\n this.process.exit(1);\n }\n } else {\n // if passed multiple inputs, expect them to be one per instance\n if (transcendInputs.length !== 1 && transcendInputs.length !== apiKeyOrList.length) {\n throw new Error(\n 'Expected list of yml files to be equal to the list of API keys.' +\n `Got ${transcendInputs.length} YML file${\n transcendInputs.length === 1 ? '' : 's'\n } and ${apiKeyOrList.length} API key${apiKeyOrList.length === 1 ? '' : 's'}`,\n );\n }\n\n const encounteredErrors: string[] = [];\n await mapSeries(apiKeyOrList, async (apiKey, ind) => {\n const prefix = `[${ind + 1}/${apiKeyOrList.length}][${apiKey.organizationName}] `;\n this.logger.info(\n colors.magenta(`~~~\\n\\n${prefix}Attempting to push configuration...\\n\\n~~~`),\n );\n\n // use the merged contents if 1 yml passed, else use the contents that map to that organization\n const useContents =\n transcendInputs.length === 1\n ? transcendInputs[0].content\n : transcendInputs.find((input) => input.name === apiKey.organizationName)?.content;\n\n // Throw error if cannot find a yml file matching that organization name\n if (!useContents) {\n this.logger.error(\n colors.red(\n `${prefix}Failed to find transcend.yml file for organization: \"${apiKey.organizationName}\".`,\n ),\n );\n encounteredErrors.push(apiKey.organizationName);\n return;\n }\n\n const success = await syncConfiguration({\n transcendUrl,\n auth: apiKey.apiKey,\n contents: useContents,\n pageSize,\n publishToPrivacyCenter,\n deleteExtraAttributeValues,\n classifyService,\n logger: this.logger,\n });\n\n if (success) {\n this.logger.info(colors.green(`${prefix}Successfully pushed configuration!`));\n } else {\n this.logger.error(colors.red(`${prefix}Failed to sync configuration.`));\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 // Indicate success\n this.logger.info(\n colors.green(`Successfully synced yaml file to Transcend! View at ${ADMIN_DASH_INTEGRATIONS}`),\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"impl-BVcy_GYa.mjs","names":[],"sources":["../src/commands/inventory/push/impl.ts"],"sourcesContent":["import path from 'node:path';\n\nimport { buildTranscendGraphQLClient } from '@transcend-io/sdk';\nimport { mapSeries } from '@transcend-io/utils';\nimport colors from 'colors';\n\nimport { TranscendInput } from '../../../codecs.js';\nimport { ADMIN_DASH_INTEGRATIONS } from '../../../constants.js';\nimport type { LocalContext } from '../../../context.js';\nimport { validateTranscendAuth, filterFileNames } from '../../../lib/api-keys/index.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { syncConfigurationToTranscend } from '../../../lib/graphql/index.js';\nimport { parseVariablesFromString } from '../../../lib/helpers/parseVariablesFromString.js';\nimport { mergeTranscendInputs } from '../../../lib/mergeTranscendInputs.js';\nimport { parseTranscendYaml } from '../../../lib/readTranscendYaml.js';\n\n/**\n * Sync configuration to Transcend\n *\n * @param options - Options\n * @returns True if synced successfully, false if error occurs\n */\nasync function syncConfiguration({\n transcendUrl,\n auth,\n pageSize,\n publishToPrivacyCenter,\n contents,\n deleteExtraAttributeValues = false,\n classifyService = false,\n logger,\n}: {\n /** Transcend YAML */\n contents: TranscendInput;\n /** Transcend URL */\n transcendUrl: string;\n /** API key */\n auth: string;\n /** Page size */\n pageSize: number;\n /** Skip privacy center publish step */\n publishToPrivacyCenter: boolean;\n /** classify data flow service if missing */\n classifyService?: boolean;\n /** Delete attributes when syncing */\n deleteExtraAttributeValues?: boolean;\n /** Logger for reporting sync progress and errors */\n logger: LocalContext['logger'];\n}): Promise<boolean> {\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Sync to Transcend\n try {\n const result = await syncConfigurationToTranscend(contents, client, {\n pageSize,\n publishToPrivacyCenter,\n classifyService,\n deleteExtraAttributeValues,\n logger,\n });\n if (!result.success) {\n result.errors.forEach(({ resource, item, message }) => {\n logger.error(\n colors.red(`Failed to sync ${resource}${item ? ` \"${item}\"` : ''}: ${message}`),\n );\n });\n }\n return result.success;\n } catch (err) {\n logger.error(colors.red(`An unexpected error occurred syncing the schema: ${err.message}`));\n return false;\n }\n}\n\nexport interface PushCommandFlags {\n auth: string;\n file: string;\n transcendUrl: string;\n pageSize: number;\n variables: string;\n publishToPrivacyCenter: boolean;\n classifyService: boolean;\n deleteExtraAttributeValues: boolean;\n}\n\nexport async function push(\n this: LocalContext,\n {\n file = './transcend.yml',\n transcendUrl,\n auth,\n variables,\n pageSize,\n publishToPrivacyCenter,\n classifyService,\n deleteExtraAttributeValues,\n }: PushCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n // Parse authentication as API key or path to list of API keys\n const apiKeyOrList = await validateTranscendAuth(auth, this);\n\n const vars = parseVariablesFromString(variables);\n\n // check if we are being passed a list of API keys and a list of files\n let fileList: string[];\n if (Array.isArray(apiKeyOrList) && this.fs.lstatSync(file).isDirectory()) {\n fileList = filterFileNames(this.fs.readdirSync(file)).map((filePath) =>\n path.join(file, filePath),\n );\n } else {\n fileList = file.split(',');\n }\n\n // Ensure at least one file is parsed\n if (fileList.length < 1) {\n throw new Error('No file specified!');\n }\n\n // eslint-disable-next-line array-callback-return,consistent-return\n const transcendInputs = fileList.map((filePath) => {\n // Ensure yaml file exists on disk\n if (!this.fs.existsSync(filePath)) {\n this.logger.error(\n colors.red(\n `The file path does not exist on disk: ${filePath}. You can specify the filepath using --file=./examples/transcend.yml`,\n ),\n );\n this.process.exit(1);\n } else {\n this.logger.info(colors.magenta(`Reading file \"${filePath}\"...`));\n }\n\n try {\n // Read in the yaml file and validate it's shape\n const newContents = parseTranscendYaml(\n this.fs.readFileSync(filePath, 'utf8'),\n vars,\n filePath,\n );\n this.logger.info(colors.green(`Successfully read in \"${filePath}\"`));\n return {\n content: newContents,\n name: filePath.split('/').pop()!.replace('.yml', ''),\n };\n } catch (err) {\n this.logger.error(\n colors.red(\n `The shape of your yaml file is invalid with the following errors: ${err.message}`,\n ),\n );\n this.process.exit(1);\n }\n });\n\n // process a single API key\n if (typeof apiKeyOrList === 'string') {\n // if passed multiple inputs, merge them together\n const [base, ...rest] = transcendInputs.map(({ content }) => content);\n const contents = mergeTranscendInputs(base, ...rest);\n\n // sync the configuration\n const success = await syncConfiguration({\n transcendUrl,\n auth: apiKeyOrList,\n contents,\n publishToPrivacyCenter,\n deleteExtraAttributeValues,\n pageSize,\n classifyService: !!classifyService,\n logger: this.logger,\n });\n\n // exist with error code\n if (!success) {\n this.logger.info(\n colors.red(\n `Sync encountered errors. View output above for more information, or check out ${ADMIN_DASH_INTEGRATIONS}`,\n ),\n );\n\n this.process.exit(1);\n }\n } else {\n // if passed multiple inputs, expect them to be one per instance\n if (transcendInputs.length !== 1 && transcendInputs.length !== apiKeyOrList.length) {\n throw new Error(\n 'Expected list of yml files to be equal to the list of API keys.' +\n `Got ${transcendInputs.length} YML file${\n transcendInputs.length === 1 ? '' : 's'\n } and ${apiKeyOrList.length} API key${apiKeyOrList.length === 1 ? '' : 's'}`,\n );\n }\n\n const encounteredErrors: string[] = [];\n await mapSeries(apiKeyOrList, async (apiKey, ind) => {\n const prefix = `[${ind + 1}/${apiKeyOrList.length}][${apiKey.organizationName}] `;\n this.logger.info(\n colors.magenta(`~~~\\n\\n${prefix}Attempting to push configuration...\\n\\n~~~`),\n );\n\n // use the merged contents if 1 yml passed, else use the contents that map to that organization\n const useContents =\n transcendInputs.length === 1\n ? transcendInputs[0].content\n : transcendInputs.find((input) => input.name === apiKey.organizationName)?.content;\n\n // Throw error if cannot find a yml file matching that organization name\n if (!useContents) {\n this.logger.error(\n colors.red(\n `${prefix}Failed to find transcend.yml file for organization: \"${apiKey.organizationName}\".`,\n ),\n );\n encounteredErrors.push(apiKey.organizationName);\n return;\n }\n\n const success = await syncConfiguration({\n transcendUrl,\n auth: apiKey.apiKey,\n contents: useContents,\n pageSize,\n publishToPrivacyCenter,\n deleteExtraAttributeValues,\n classifyService,\n logger: this.logger,\n });\n\n if (success) {\n this.logger.info(colors.green(`${prefix}Successfully pushed configuration!`));\n } else {\n this.logger.error(colors.red(`${prefix}Failed to sync configuration.`));\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 // Indicate success\n this.logger.info(\n colors.green(`Successfully synced yaml file to Transcend! View at ${ADMIN_DASH_INTEGRATIONS}`),\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{t as e}from"./updateConsentManagerVersionToLatest-DWblAwus.mjs";import{t}from"./validateTranscendAuth-D-dDINof.mjs";import{t as n}from"./done-input-validation-LiTaCEzF.mjs";import{ConsentBundleType as r}from"@transcend-io/privacy-types";import i from"colors";import{mapSeries as a}from"@transcend-io/utils";async function o({auth:o,bundleTypes:s=[r.Production,r.Test],deploy:c,transcendUrl:l}){n(this.process);let u=await t(o,this);typeof u==`string`?(await e({deploy:c,transcendUrl:l,auth:u,bundleTypes:s}),this.logger.info(i.green(`Successfully updated Consent Manager!`))):(await a(u,async t=>{this.logger.info(i.magenta(`Updating Consent Manager for organization "${t.organizationName}"...`)),await e({deploy:c,transcendUrl:l,auth:t.apiKey,bundleTypes:s}),this.logger.info(i.green(`Successfully updated Consent Manager for organization "${t.organizationName}"!`))}),this.logger.info(i.green(`Successfully updated Consent Managers!`)))}export{o as updateConsentManager};
2
- //# sourceMappingURL=impl-vmLq6HCI.mjs.map
1
+ import{t as e}from"./updateConsentManagerVersionToLatest-KwMaAkwh.mjs";import{t}from"./validateTranscendAuth-D-dDINof.mjs";import{t as n}from"./done-input-validation-LiTaCEzF.mjs";import{ConsentBundleType as r}from"@transcend-io/privacy-types";import i from"colors";import{mapSeries as a}from"@transcend-io/utils";async function o({auth:o,bundleTypes:s=[r.Production,r.Test],deploy:c,transcendUrl:l}){n(this.process);let u=await t(o,this);typeof u==`string`?(await e({deploy:c,transcendUrl:l,auth:u,bundleTypes:s}),this.logger.info(i.green(`Successfully updated Consent Manager!`))):(await a(u,async t=>{this.logger.info(i.magenta(`Updating Consent Manager for organization "${t.organizationName}"...`)),await e({deploy:c,transcendUrl:l,auth:t.apiKey,bundleTypes:s}),this.logger.info(i.green(`Successfully updated Consent Manager for organization "${t.organizationName}"!`))}),this.logger.info(i.green(`Successfully updated Consent Managers!`)))}export{o as updateConsentManager};
2
+ //# sourceMappingURL=impl-B_CRtRo8.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"impl-vmLq6HCI.mjs","names":[],"sources":["../src/commands/consent/update-consent-manager/impl.ts"],"sourcesContent":["import { ConsentBundleType } from '@transcend-io/privacy-types';\nimport { mapSeries } from '@transcend-io/utils';\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { validateTranscendAuth } from '../../../lib/api-keys/index.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { updateConsentManagerVersionToLatest } from '../../../lib/consent-manager/index.js';\n\nexport interface UpdateConsentManagerCommandFlags {\n auth: string;\n bundleTypes: ConsentBundleType[];\n deploy: boolean;\n transcendUrl: string;\n}\n\nexport async function updateConsentManager(\n this: LocalContext,\n {\n auth,\n bundleTypes = [ConsentBundleType.Production, ConsentBundleType.Test],\n deploy,\n transcendUrl,\n }: UpdateConsentManagerCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n // Parse authentication as API key or path to list of API keys\n const apiKeyOrList = await validateTranscendAuth(auth, this);\n\n // Handle single update\n if (typeof apiKeyOrList === 'string') {\n // Update consent manager\n await updateConsentManagerVersionToLatest({\n deploy,\n transcendUrl,\n auth: apiKeyOrList,\n bundleTypes,\n });\n this.logger.info(colors.green('Successfully updated Consent Manager!'));\n } else {\n await mapSeries(apiKeyOrList, async (apiKey) => {\n this.logger.info(\n colors.magenta(`Updating Consent Manager for organization \"${apiKey.organizationName}\"...`),\n );\n\n await updateConsentManagerVersionToLatest({\n deploy,\n transcendUrl,\n auth: apiKey.apiKey,\n bundleTypes,\n });\n\n this.logger.info(\n colors.green(\n `Successfully updated Consent Manager for organization \"${apiKey.organizationName}\"!`,\n ),\n );\n });\n this.logger.info(colors.green('Successfully updated Consent Managers!'));\n }\n}\n"],"mappings":"0TAgBA,eAAsB,EAEpB,CACE,OACA,cAAc,CAAC,EAAkB,WAAY,EAAkB,KAAK,CACpE,SACA,gBAEa,CACf,EAAoB,KAAK,QAAQ,CAGjC,IAAM,EAAe,MAAM,EAAsB,EAAM,KAAK,CAGxD,OAAO,GAAiB,UAE1B,MAAM,EAAoC,CACxC,SACA,eACA,KAAM,EACN,cACD,CAAC,CACF,KAAK,OAAO,KAAK,EAAO,MAAM,wCAAwC,CAAC,GAEvE,MAAM,EAAU,EAAc,KAAO,IAAW,CAC9C,KAAK,OAAO,KACV,EAAO,QAAQ,8CAA8C,EAAO,iBAAiB,MAAM,CAC5F,CAED,MAAM,EAAoC,CACxC,SACA,eACA,KAAM,EAAO,OACb,cACD,CAAC,CAEF,KAAK,OAAO,KACV,EAAO,MACL,0DAA0D,EAAO,iBAAiB,IACnF,CACF,EACD,CACF,KAAK,OAAO,KAAK,EAAO,MAAM,yCAAyC,CAAC"}
1
+ {"version":3,"file":"impl-B_CRtRo8.mjs","names":[],"sources":["../src/commands/consent/update-consent-manager/impl.ts"],"sourcesContent":["import { ConsentBundleType } from '@transcend-io/privacy-types';\nimport { mapSeries } from '@transcend-io/utils';\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { validateTranscendAuth } from '../../../lib/api-keys/index.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { updateConsentManagerVersionToLatest } from '../../../lib/consent-manager/index.js';\n\nexport interface UpdateConsentManagerCommandFlags {\n auth: string;\n bundleTypes: ConsentBundleType[];\n deploy: boolean;\n transcendUrl: string;\n}\n\nexport async function updateConsentManager(\n this: LocalContext,\n {\n auth,\n bundleTypes = [ConsentBundleType.Production, ConsentBundleType.Test],\n deploy,\n transcendUrl,\n }: UpdateConsentManagerCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n // Parse authentication as API key or path to list of API keys\n const apiKeyOrList = await validateTranscendAuth(auth, this);\n\n // Handle single update\n if (typeof apiKeyOrList === 'string') {\n // Update consent manager\n await updateConsentManagerVersionToLatest({\n deploy,\n transcendUrl,\n auth: apiKeyOrList,\n bundleTypes,\n });\n this.logger.info(colors.green('Successfully updated Consent Manager!'));\n } else {\n await mapSeries(apiKeyOrList, async (apiKey) => {\n this.logger.info(\n colors.magenta(`Updating Consent Manager for organization \"${apiKey.organizationName}\"...`),\n );\n\n await updateConsentManagerVersionToLatest({\n deploy,\n transcendUrl,\n auth: apiKey.apiKey,\n bundleTypes,\n });\n\n this.logger.info(\n colors.green(\n `Successfully updated Consent Manager for organization \"${apiKey.organizationName}\"!`,\n ),\n );\n });\n this.logger.info(colors.green('Successfully updated Consent Managers!'));\n }\n}\n"],"mappings":"0TAgBA,eAAsB,EAEpB,CACE,OACA,cAAc,CAAC,EAAkB,WAAY,EAAkB,KAAK,CACpE,SACA,gBAEa,CACf,EAAoB,KAAK,QAAQ,CAGjC,IAAM,EAAe,MAAM,EAAsB,EAAM,KAAK,CAGxD,OAAO,GAAiB,UAE1B,MAAM,EAAoC,CACxC,SACA,eACA,KAAM,EACN,cACD,CAAC,CACF,KAAK,OAAO,KAAK,EAAO,MAAM,wCAAwC,CAAC,GAEvE,MAAM,EAAU,EAAc,KAAO,IAAW,CAC9C,KAAK,OAAO,KACV,EAAO,QAAQ,8CAA8C,EAAO,iBAAiB,MAAM,CAC5F,CAED,MAAM,EAAoC,CACxC,SACA,eACA,KAAM,EAAO,OACb,cACD,CAAC,CAEF,KAAK,OAAO,KACV,EAAO,MACL,0DAA0D,EAAO,iBAAiB,IACnF,CACF,EACD,CACF,KAAK,OAAO,KAAK,EAAO,MAAM,yCAAyC,CAAC"}
@@ -1,2 +1,2 @@
1
- import{i as e}from"./enums-OiLcZ26O.mjs";import{r as t}from"./constants-BRsj50Nb.mjs";import{n,t as r}from"./command-X7lkPELf.mjs";import{o as i}from"./readTranscendYaml-BfqQbPiT.mjs";import{n as a}from"./pullTranscendConfiguration-CDUDqxpm.mjs";import{t as o}from"./validateTranscendAuth-D-dDINof.mjs";import{t as s}from"./done-input-validation-LiTaCEzF.mjs";import c from"node:path";import l from"colors";import{buildTranscendGraphQLClient as u}from"@transcend-io/sdk";import{mapSeries as d}from"@transcend-io/utils";async function f({auth:f,resources:p=n,file:m,transcendUrl:h,dataSiloIds:g=[],integrationNames:_=[],trackerStatuses:v=r,pageSize:y,skipDatapoints:b,skipSubDatapoints:x,includeGuessedCategories:S,debug:C}){s(this.process);let w=await o(f,this),T=p.includes(`all`)?Object.values(e):p;if(typeof w==`string`){try{let e=await a(u(h,w),{dataSiloIds:g,integrationNames:_,resources:T,pageSize:y,debug:C,skipDatapoints:b,skipSubDatapoints:x,includeGuessedCategories:S,trackerStatuses:v});this.logger.info(l.magenta(`Writing configuration to file "${m}"...`)),this.fs.writeFileSync(m,i(e))}catch(e){this.logger.error(l.red(`An error occurred syncing the schema: ${C?e.stack:e.message}`)),this.process.exit(1)}this.logger.info(l.green(`Successfully synced yaml file to disk at ${m}! View at ${t}`))}else{if(!this.fs.lstatSync(m).isDirectory())throw Error(`File is expected to be a folder when passing in a list of API keys to pull from. e.g. --file=./working/`);let e=[];await d(w,async(t,n)=>{let r=`[${n+1}/${w.length}][${t.organizationName}] `;this.logger.info(l.magenta(`~~~\n\n${r}Attempting to pull configuration...\n\n~~~`));let o=u(h,t.apiKey);try{let e=await a(o,{dataSiloIds:g,integrationNames:_,resources:T,pageSize:y,debug:C,skipDatapoints:b,skipSubDatapoints:x,includeGuessedCategories:S,trackerStatuses:v}),n=c.join(m,`${t.organizationName}.yml`);this.logger.info(l.magenta(`Writing configuration to file "${n}"...`)),this.fs.writeFileSync(n,i(e)),this.logger.info(l.green(`${r}Successfully pulled configuration!`))}catch(n){this.logger.error(l.red(`${r}Failed to sync configuration. - ${n.message}`)),e.push(t.organizationName)}}),e.length>0&&(this.logger.info(l.red(`Sync encountered errors for "${e.join(`,`)}". View output above for more information, or check out ${t}`)),this.process.exit(1))}}export{f as pull};
2
- //# sourceMappingURL=impl-7rdGuHOC.mjs.map
1
+ import{i as e}from"./enums-OiLcZ26O.mjs";import{r as t}from"./constants-BlKpAm3R.mjs";import{n,t as r}from"./command-BDQOL_MQ.mjs";import{o as i}from"./readTranscendYaml-BfqQbPiT.mjs";import{n as a}from"./pullTranscendConfiguration-CDUDqxpm.mjs";import{t as o}from"./validateTranscendAuth-D-dDINof.mjs";import{t as s}from"./done-input-validation-LiTaCEzF.mjs";import c from"node:path";import l from"colors";import{mapSeries as u}from"@transcend-io/utils";import{buildTranscendGraphQLClient as d}from"@transcend-io/sdk";async function f({auth:f,resources:p=n,file:m,transcendUrl:h,dataSiloIds:g=[],integrationNames:_=[],trackerStatuses:v=r,pageSize:y,skipDatapoints:b,skipSubDatapoints:x,includeGuessedCategories:S,debug:C}){s(this.process);let w=await o(f,this),T=p.includes(`all`)?Object.values(e):p;if(typeof w==`string`){try{let e=await a(d(h,w),{dataSiloIds:g,integrationNames:_,resources:T,pageSize:y,debug:C,skipDatapoints:b,skipSubDatapoints:x,includeGuessedCategories:S,trackerStatuses:v});this.logger.info(l.magenta(`Writing configuration to file "${m}"...`)),this.fs.writeFileSync(m,i(e))}catch(e){this.logger.error(l.red(`An error occurred syncing the schema: ${C?e.stack:e.message}`)),this.process.exit(1)}this.logger.info(l.green(`Successfully synced yaml file to disk at ${m}! View at ${t}`))}else{if(!this.fs.lstatSync(m).isDirectory())throw Error(`File is expected to be a folder when passing in a list of API keys to pull from. e.g. --file=./working/`);let e=[];await u(w,async(t,n)=>{let r=`[${n+1}/${w.length}][${t.organizationName}] `;this.logger.info(l.magenta(`~~~\n\n${r}Attempting to pull configuration...\n\n~~~`));let o=d(h,t.apiKey);try{let e=await a(o,{dataSiloIds:g,integrationNames:_,resources:T,pageSize:y,debug:C,skipDatapoints:b,skipSubDatapoints:x,includeGuessedCategories:S,trackerStatuses:v}),n=c.join(m,`${t.organizationName}.yml`);this.logger.info(l.magenta(`Writing configuration to file "${n}"...`)),this.fs.writeFileSync(n,i(e)),this.logger.info(l.green(`${r}Successfully pulled configuration!`))}catch(n){this.logger.error(l.red(`${r}Failed to sync configuration. - ${n.message}`)),e.push(t.organizationName)}}),e.length>0&&(this.logger.info(l.red(`Sync encountered errors for "${e.join(`,`)}". View output above for more information, or check out ${t}`)),this.process.exit(1))}}export{f as pull};
2
+ //# sourceMappingURL=impl-BgD7TeMD.mjs.map