@transcend-io/cli 11.0.0 → 12.0.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 (365) hide show
  1. package/README.md +229 -84
  2. package/dist/app-CR3U95JW.mjs +148 -0
  3. package/dist/app-CR3U95JW.mjs.map +1 -0
  4. package/dist/{approvePrivacyRequests-C165wLBa.mjs → approvePrivacyRequests-BDG82nlp.mjs} +2 -2
  5. package/dist/{approvePrivacyRequests-C165wLBa.mjs.map → approvePrivacyRequests-BDG82nlp.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-DOopJFYY.mjs → buildExamples-B6BdW0FD.mjs} +2 -2
  10. package/dist/{buildExamples-DOopJFYY.mjs.map → buildExamples-B6BdW0FD.mjs.map} +1 -1
  11. package/dist/{buildXdiSyncEndpoint-DeStnIit.mjs → buildXdiSyncEndpoint-FExEagKc.mjs} +2 -2
  12. package/dist/{buildXdiSyncEndpoint-DeStnIit.mjs.map → buildXdiSyncEndpoint-FExEagKc.mjs.map} +1 -1
  13. package/dist/{bulkRestartRequests-_Mu1rwZQ.mjs → bulkRestartRequests-OKwKXc52.mjs} +2 -2
  14. package/dist/{bulkRestartRequests-_Mu1rwZQ.mjs.map → bulkRestartRequests-OKwKXc52.mjs.map} +1 -1
  15. package/dist/{bulkRetryEnrichers-C2keTKuQ.mjs → bulkRetryEnrichers-Dl-n8AFF.mjs} +2 -2
  16. package/dist/{bulkRetryEnrichers-C2keTKuQ.mjs.map → bulkRetryEnrichers-Dl-n8AFF.mjs.map} +1 -1
  17. package/dist/{cancelPrivacyRequests-DwQr18Fk.mjs → cancelPrivacyRequests-BIgX5SDz.mjs} +2 -2
  18. package/dist/{cancelPrivacyRequests-DwQr18Fk.mjs.map → cancelPrivacyRequests-BIgX5SDz.mjs.map} +1 -1
  19. package/dist/{codecs-CTxFjCg4.mjs → codecs-CfcaFoZR.mjs} +1 -1
  20. package/dist/{codecs-CTxFjCg4.mjs.map → codecs-CfcaFoZR.mjs.map} +1 -1
  21. package/dist/{collectCsvFilesOrExit-B1VOVGWN.mjs → collectCsvFilesOrExit-BindZ0dF.mjs} +1 -1
  22. package/dist/{collectCsvFilesOrExit-B1VOVGWN.mjs.map → collectCsvFilesOrExit-BindZ0dF.mjs.map} +1 -1
  23. package/dist/{collectParquetFilesOrExit-DVlv5ctt.mjs → collectParquetFilesOrExit-CbNQ9CJc.mjs} +1 -1
  24. package/dist/{collectParquetFilesOrExit-DVlv5ctt.mjs.map → collectParquetFilesOrExit-CbNQ9CJc.mjs.map} +1 -1
  25. package/dist/command-X7lkPELf.mjs +9 -0
  26. package/dist/command-X7lkPELf.mjs.map +1 -0
  27. package/dist/command-output-BJcDRXNr.mjs +2 -0
  28. package/dist/command-output-BJcDRXNr.mjs.map +1 -0
  29. package/dist/command-output-BRfF3YFv.mjs +2 -0
  30. package/dist/command-output-BRfF3YFv.mjs.map +1 -0
  31. package/dist/commands/admin/chunk-csv/worker.mjs +1 -1
  32. package/dist/commands/admin/parquet-to-csv/worker.mjs +1 -1
  33. package/dist/{consentManagersToBusinessEntities-CBJ81aGO.mjs → consentManagersToBusinessEntities-DG0_eby5.mjs} +1 -1
  34. package/dist/{consentManagersToBusinessEntities-CBJ81aGO.mjs.map → consentManagersToBusinessEntities-DG0_eby5.mjs.map} +1 -1
  35. package/dist/{constants-Upxn_rQF.mjs → constants-BRsj50Nb.mjs} +2 -2
  36. package/dist/{constants-Upxn_rQF.mjs.map → constants-BRsj50Nb.mjs.map} +1 -1
  37. package/dist/{constants-DXzsg2CQ.mjs → constants-DC_bBO09.mjs} +3 -3
  38. package/dist/{constants-DXzsg2CQ.mjs.map → constants-DC_bBO09.mjs.map} +1 -1
  39. package/dist/{constants-D_HVDaOy.mjs → constants-qvGk0wlN.mjs} +1 -1
  40. package/dist/{constants-D_HVDaOy.mjs.map → constants-qvGk0wlN.mjs.map} +1 -1
  41. package/dist/{context-B33NT3ki.mjs → context-D0A0LxsP.mjs} +1 -1
  42. package/dist/{context-B33NT3ki.mjs.map → context-D0A0LxsP.mjs.map} +1 -1
  43. package/dist/{createPoolingCommandUi-CKH-24w5.mjs → createPoolingCommandUi-CyPZ3GqN.mjs} +5 -5
  44. package/dist/{createPoolingCommandUi-CKH-24w5.mjs.map → createPoolingCommandUi-CyPZ3GqN.mjs.map} +1 -1
  45. package/dist/{dataFlowsToDataSilos-BF6fzWcm.mjs → dataFlowsToDataSilos-CRqbNjZ0.mjs} +1 -1
  46. package/dist/{dataFlowsToDataSilos-BF6fzWcm.mjs.map → dataFlowsToDataSilos-CRqbNjZ0.mjs.map} +1 -1
  47. package/dist/deno-runtime-CB2HBach.mjs +2 -0
  48. package/dist/deno-runtime-CB2HBach.mjs.map +1 -0
  49. package/dist/{done-input-validation-BUz-aVC5.mjs → done-input-validation-LiTaCEzF.mjs} +1 -1
  50. package/dist/{done-input-validation-BUz-aVC5.mjs.map → done-input-validation-LiTaCEzF.mjs.map} +1 -1
  51. package/dist/{downloadPrivacyRequestFiles-D3bzcegH.mjs → downloadPrivacyRequestFiles-EBySRnvd.mjs} +2 -2
  52. package/dist/{downloadPrivacyRequestFiles-D3bzcegH.mjs.map → downloadPrivacyRequestFiles-EBySRnvd.mjs.map} +1 -1
  53. package/dist/{extractClientError-HZ2U7yqV.mjs → extractClientError-DUJxHv07.mjs} +1 -1
  54. package/dist/{extractClientError-HZ2U7yqV.mjs.map → extractClientError-DUJxHv07.mjs.map} +1 -1
  55. package/dist/{fetchAllRequests-2TZr-LfT.mjs → fetchAllRequests-BI0tFl_a.mjs} +2 -2
  56. package/dist/{fetchAllRequests-2TZr-LfT.mjs.map → fetchAllRequests-BI0tFl_a.mjs.map} +1 -1
  57. package/dist/{formatPolicyBundleVersionSummary-CJmMCLtJ.mjs → formatPolicyBundleVersionSummary-DCHl1Vhy.mjs} +1 -1
  58. package/dist/{formatPolicyBundleVersionSummary-CJmMCLtJ.mjs.map → formatPolicyBundleVersionSummary-DCHl1Vhy.mjs.map} +1 -1
  59. package/dist/{fuzzyMatchColumns-CQCzpjWC.mjs → fuzzyMatchColumns-2NmQqCZI.mjs} +2 -2
  60. package/dist/{fuzzyMatchColumns-CQCzpjWC.mjs.map → fuzzyMatchColumns-2NmQqCZI.mjs.map} +1 -1
  61. package/dist/{generateCrossAccountApiKeys-DWfJtB3t.mjs → generateCrossAccountApiKeys-pWTrIUE6.mjs} +2 -2
  62. package/dist/{generateCrossAccountApiKeys-DWfJtB3t.mjs.map → generateCrossAccountApiKeys-pWTrIUE6.mjs.map} +1 -1
  63. package/dist/impl-0-_oxvck.mjs +2 -0
  64. package/dist/impl-0-_oxvck.mjs.map +1 -0
  65. package/dist/{impl-ByFyaZkK.mjs → impl-1SsreZWo.mjs} +2 -2
  66. package/dist/{impl-ByFyaZkK.mjs.map → impl-1SsreZWo.mjs.map} +1 -1
  67. package/dist/{impl-D4Ne3Vbg.mjs → impl-7rdGuHOC.mjs} +2 -2
  68. package/dist/{impl-D4Ne3Vbg.mjs.map → impl-7rdGuHOC.mjs.map} +1 -1
  69. package/dist/{impl-DRpK-QLC.mjs → impl-ApZGIx6l.mjs} +2 -2
  70. package/dist/{impl-DRpK-QLC.mjs.map → impl-ApZGIx6l.mjs.map} +1 -1
  71. package/dist/{impl-DVeGQCrr.mjs → impl-Ay6JeH-7.mjs} +2 -2
  72. package/dist/{impl-DVeGQCrr.mjs.map → impl-Ay6JeH-7.mjs.map} +1 -1
  73. package/dist/{impl-C2sSZ8qF.mjs → impl-B2ZXtnpX.mjs} +2 -2
  74. package/dist/{impl-C2sSZ8qF.mjs.map → impl-B2ZXtnpX.mjs.map} +1 -1
  75. package/dist/impl-B440iuvL.mjs +3 -0
  76. package/dist/impl-B440iuvL.mjs.map +1 -0
  77. package/dist/{impl-BhfxcCgN2.mjs → impl-B7l4bLG5.mjs} +2 -2
  78. package/dist/impl-B7l4bLG5.mjs.map +1 -0
  79. package/dist/{impl-BPoEH3Nf2.mjs → impl-B94dMG4x2.mjs} +2 -2
  80. package/dist/{impl-BPoEH3Nf2.mjs.map → impl-B94dMG4x2.mjs.map} +1 -1
  81. package/dist/{impl-DXowiNOz.mjs → impl-BH1fCPDh.mjs} +2 -2
  82. package/dist/{impl-DXowiNOz.mjs.map → impl-BH1fCPDh.mjs.map} +1 -1
  83. package/dist/{impl-CfvxD3RI.mjs → impl-BLOhoP-b2.mjs} +2 -2
  84. package/dist/impl-BLOhoP-b2.mjs.map +1 -0
  85. package/dist/{impl-CHUxKOz_.mjs → impl-BLQDgwxL.mjs} +2 -2
  86. package/dist/{impl-CHUxKOz_.mjs.map → impl-BLQDgwxL.mjs.map} +1 -1
  87. package/dist/{impl-Dqqb0lVN.mjs → impl-BWPPVXG3.mjs} +3 -3
  88. package/dist/{impl-Dqqb0lVN.mjs.map → impl-BWPPVXG3.mjs.map} +1 -1
  89. package/dist/{impl-Cw0L2xEU.mjs → impl-BdTxFv63.mjs} +2 -2
  90. package/dist/{impl-Cw0L2xEU.mjs.map → impl-BdTxFv63.mjs.map} +1 -1
  91. package/dist/impl-BpVe6fMe.mjs +3 -0
  92. package/dist/{impl--JGnR3wp.mjs.map → impl-BpVe6fMe.mjs.map} +1 -1
  93. package/dist/impl-BqTMPbwc2.mjs +2 -0
  94. package/dist/impl-BqTMPbwc2.mjs.map +1 -0
  95. package/dist/impl-CAoIp9Nl2.mjs +3 -0
  96. package/dist/impl-CAoIp9Nl2.mjs.map +1 -0
  97. package/dist/{impl-C_62Z4ED.mjs → impl-CU38kdj8.mjs} +2 -2
  98. package/dist/{impl-C_62Z4ED.mjs.map → impl-CU38kdj8.mjs.map} +1 -1
  99. package/dist/{impl-BppXJ1AD2.mjs → impl-CWP6AXSb.mjs} +2 -2
  100. package/dist/impl-CWP6AXSb.mjs.map +1 -0
  101. package/dist/impl-CY8C-Fvj2.mjs +2 -0
  102. package/dist/impl-CY8C-Fvj2.mjs.map +1 -0
  103. package/dist/{impl-BJyzyrZD.mjs → impl-C_Ifcb00.mjs} +2 -2
  104. package/dist/{impl-BJyzyrZD.mjs.map → impl-C_Ifcb00.mjs.map} +1 -1
  105. package/dist/{impl-CPSEzCc9.mjs → impl-Cb42aI60.mjs} +2 -2
  106. package/dist/{impl-CPSEzCc9.mjs.map → impl-Cb42aI60.mjs.map} +1 -1
  107. package/dist/impl-Cee7Q1Ne.mjs +2 -0
  108. package/dist/impl-Cee7Q1Ne.mjs.map +1 -0
  109. package/dist/impl-CieztjdM.mjs +2 -0
  110. package/dist/impl-CieztjdM.mjs.map +1 -0
  111. package/dist/{impl-DqhZR11m.mjs → impl-ClqrQo1M.mjs} +2 -2
  112. package/dist/{impl-DqhZR11m.mjs.map → impl-ClqrQo1M.mjs.map} +1 -1
  113. package/dist/impl-CnHfn7rr.mjs +5 -0
  114. package/dist/{impl-DPtx5iZO.mjs.map → impl-CnHfn7rr.mjs.map} +1 -1
  115. package/dist/{impl-BpMQYnbR.mjs → impl-CrdqsTUy.mjs} +2 -2
  116. package/dist/{impl-BpMQYnbR.mjs.map → impl-CrdqsTUy.mjs.map} +1 -1
  117. package/dist/{impl-DzUTmaID2.mjs → impl-CsaT3aM2.mjs} +2 -2
  118. package/dist/impl-CsaT3aM2.mjs.map +1 -0
  119. package/dist/{impl-BEA5cQOT2.mjs → impl-CspH2ZWx.mjs} +2 -2
  120. package/dist/impl-CspH2ZWx.mjs.map +1 -0
  121. package/dist/{impl-lsmXIGSo2.mjs → impl-CudSYx-g.mjs} +2 -2
  122. package/dist/impl-CudSYx-g.mjs.map +1 -0
  123. package/dist/{impl-DXQHLpMw.mjs → impl-Cxprr2hw.mjs} +2 -2
  124. package/dist/{impl-DXQHLpMw.mjs.map → impl-Cxprr2hw.mjs.map} +1 -1
  125. package/dist/{impl-gs5wJ1BK.mjs → impl-D-a5xGld.mjs} +2 -2
  126. package/dist/{impl-gs5wJ1BK.mjs.map → impl-D-a5xGld.mjs.map} +1 -1
  127. package/dist/{impl-D94m3EPp.mjs → impl-D1UogVAq.mjs} +2 -2
  128. package/dist/{impl-D94m3EPp.mjs.map → impl-D1UogVAq.mjs.map} +1 -1
  129. package/dist/{impl-B5df-igZ.mjs → impl-D1f9mJL_.mjs} +2 -2
  130. package/dist/{impl-B5df-igZ.mjs.map → impl-D1f9mJL_.mjs.map} +1 -1
  131. package/dist/{impl-CSk_okwj.mjs → impl-DJcNhpbx.mjs} +2 -2
  132. package/dist/{impl-CSk_okwj.mjs.map → impl-DJcNhpbx.mjs.map} +1 -1
  133. package/dist/impl-DQG1pMzD2.mjs +2 -0
  134. package/dist/impl-DQG1pMzD2.mjs.map +1 -0
  135. package/dist/impl-DQcgEx7V2.mjs +298 -0
  136. package/dist/impl-DQcgEx7V2.mjs.map +1 -0
  137. package/dist/impl-DRKPx_I9.mjs +2 -0
  138. package/dist/impl-DRKPx_I9.mjs.map +1 -0
  139. package/dist/{impl-DhxDp4GN.mjs → impl-DTadLabu.mjs} +2 -2
  140. package/dist/{impl-DhxDp4GN.mjs.map → impl-DTadLabu.mjs.map} +1 -1
  141. package/dist/{impl-CD2R3L0v.mjs → impl-DXbxO2VJ.mjs} +2 -2
  142. package/dist/{impl-CD2R3L0v.mjs.map → impl-DXbxO2VJ.mjs.map} +1 -1
  143. package/dist/{impl-nz1MyjX22.mjs → impl-DcL-8NEa2.mjs} +2 -2
  144. package/dist/{impl-nz1MyjX22.mjs.map → impl-DcL-8NEa2.mjs.map} +1 -1
  145. package/dist/{impl-DKepRc812.mjs → impl-DeCRXfAh2.mjs} +2 -2
  146. package/dist/{impl-DKepRc812.mjs.map → impl-DeCRXfAh2.mjs.map} +1 -1
  147. package/dist/impl-DezV3QMo.mjs +3 -0
  148. package/dist/impl-DezV3QMo.mjs.map +1 -0
  149. package/dist/{impl-COujMWgp.mjs → impl-Dg7XSQdO2.mjs} +2 -2
  150. package/dist/impl-Dg7XSQdO2.mjs.map +1 -0
  151. package/dist/{impl-a_Y8bnSn.mjs → impl-DhXzxQDN2.mjs} +5 -5
  152. package/dist/impl-DhXzxQDN2.mjs.map +1 -0
  153. package/dist/impl-DiwxYcux.mjs +2 -0
  154. package/dist/{impl-GytUVAMP.mjs.map → impl-DiwxYcux.mjs.map} +1 -1
  155. package/dist/{impl-C9OmNI49.mjs → impl-Do2TNA3-.mjs} +2 -2
  156. package/dist/{impl-C9OmNI49.mjs.map → impl-Do2TNA3-.mjs.map} +1 -1
  157. package/dist/{impl-DaH1_ZzK.mjs → impl-DqHEIzpj.mjs} +2 -2
  158. package/dist/{impl-DaH1_ZzK.mjs.map → impl-DqHEIzpj.mjs.map} +1 -1
  159. package/dist/{impl-CzdUHruN.mjs → impl-Dr_l_SLd.mjs} +2 -2
  160. package/dist/{impl-CzdUHruN.mjs.map → impl-Dr_l_SLd.mjs.map} +1 -1
  161. package/dist/{impl-CTwyYUw3.mjs → impl-Ds-gQfdc.mjs} +2 -2
  162. package/dist/{impl-CTwyYUw3.mjs.map → impl-Ds-gQfdc.mjs.map} +1 -1
  163. package/dist/{impl-C8jjYvgu.mjs → impl-DtnYcktN.mjs} +2 -2
  164. package/dist/{impl-C8jjYvgu.mjs.map → impl-DtnYcktN.mjs.map} +1 -1
  165. package/dist/impl-DtpgD_as.mjs +2 -0
  166. package/dist/{impl-DQPmSYSE.mjs.map → impl-DtpgD_as.mjs.map} +1 -1
  167. package/dist/{impl-D2Q4nxUO.mjs → impl-DxQ9yj3H.mjs} +2 -2
  168. package/dist/{impl-D2Q4nxUO.mjs.map → impl-DxQ9yj3H.mjs.map} +1 -1
  169. package/dist/impl-FerHBNJx2.mjs +4 -0
  170. package/dist/{impl-D-AHlqlD2.mjs.map → impl-FerHBNJx2.mjs.map} +1 -1
  171. package/dist/{impl-CiBT9-GH2.mjs → impl-HUfaARep.mjs} +2 -2
  172. package/dist/impl-HUfaARep.mjs.map +1 -0
  173. package/dist/impl-btKJ1-VJ.mjs +3 -0
  174. package/dist/impl-btKJ1-VJ.mjs.map +1 -0
  175. package/dist/impl-eeS2lVi5.mjs +2 -0
  176. package/dist/impl-eeS2lVi5.mjs.map +1 -0
  177. package/dist/impl-iD6Fknfe.mjs +2 -0
  178. package/dist/impl-iD6Fknfe.mjs.map +1 -0
  179. package/dist/impl-ijoNwhGI.mjs +2 -0
  180. package/dist/impl-ijoNwhGI.mjs.map +1 -0
  181. package/dist/{impl-zRAjMVgz.mjs → impl-vmLq6HCI.mjs} +2 -2
  182. package/dist/{impl-zRAjMVgz.mjs.map → impl-vmLq6HCI.mjs.map} +1 -1
  183. package/dist/{impl-a0BFtbna.mjs → impl-wBcVYHlA.mjs} +2 -2
  184. package/dist/{impl-a0BFtbna.mjs.map → impl-wBcVYHlA.mjs.map} +1 -1
  185. package/dist/index.mjs +2 -2
  186. package/dist/index.mjs.map +1 -1
  187. package/dist/{initializeCliRuntime-6wI_VIHV.mjs → initializeCliRuntime-BaATMO1X.mjs} +1 -1
  188. package/dist/{initializeCliRuntime-6wI_VIHV.mjs.map → initializeCliRuntime-BaATMO1X.mjs.map} +1 -1
  189. package/dist/{inquirer-BeaBetMO.mjs → inquirer-BU5IpgA8.mjs} +2 -2
  190. package/dist/{inquirer-BeaBetMO.mjs.map → inquirer-BU5IpgA8.mjs.map} +1 -1
  191. package/dist/{jsonc-D9dDWb1J.mjs → jsonc-CdTubr53.mjs} +1 -1
  192. package/dist/{jsonc-D9dDWb1J.mjs.map → jsonc-CdTubr53.mjs.map} +1 -1
  193. package/dist/{listFiles-BdFUbX5x.mjs → listFiles-DDGCBdtx.mjs} +1 -1
  194. package/dist/{listFiles-BdFUbX5x.mjs.map → listFiles-DDGCBdtx.mjs.map} +1 -1
  195. package/dist/logger-CPu6zbyQ.mjs +2 -0
  196. package/dist/logger-CPu6zbyQ.mjs.map +1 -0
  197. package/dist/{mapConsentCsvRowsToInputs-Dqb6WL4r.mjs → mapConsentCsvRowsToInputs-CkLfxaIf.mjs} +1 -1
  198. package/dist/{mapConsentCsvRowsToInputs-Dqb6WL4r.mjs.map → mapConsentCsvRowsToInputs-CkLfxaIf.mjs.map} +1 -1
  199. package/dist/{markRequestDataSiloIdsCompleted-Br5gIS3S.mjs → markRequestDataSiloIdsCompleted-BYNMCkhy.mjs} +2 -2
  200. package/dist/{markRequestDataSiloIdsCompleted-Br5gIS3S.mjs.map → markRequestDataSiloIdsCompleted-BYNMCkhy.mjs.map} +1 -1
  201. package/dist/{markSilentPrivacyRequests-Cs_iZNJs.mjs → markSilentPrivacyRequests-gKYivzH1.mjs} +2 -2
  202. package/dist/{markSilentPrivacyRequests-Cs_iZNJs.mjs.map → markSilentPrivacyRequests-gKYivzH1.mjs.map} +1 -1
  203. package/dist/{mergeTranscendInputs-DFQcbh8b.mjs → mergeTranscendInputs-D1CvxQu0.mjs} +2 -2
  204. package/dist/{mergeTranscendInputs-DFQcbh8b.mjs.map → mergeTranscendInputs-D1CvxQu0.mjs.map} +1 -1
  205. package/dist/missing-manifest-D8y1VL4p.mjs +2 -0
  206. package/dist/missing-manifest-D8y1VL4p.mjs.map +1 -0
  207. package/dist/{module-graph-Cb0g74Ft.mjs → module-graph-CAT8_JCG.mjs} +1 -1
  208. package/dist/{module-graph-Cb0g74Ft.mjs.map → module-graph-CAT8_JCG.mjs.map} +1 -1
  209. package/dist/{notifyPrivacyRequestsAdditionalTime-kPXTdjgT.mjs → notifyPrivacyRequestsAdditionalTime-DbERhQ1Q.mjs} +2 -2
  210. package/dist/{notifyPrivacyRequestsAdditionalTime-kPXTdjgT.mjs.map → notifyPrivacyRequestsAdditionalTime-DbERhQ1Q.mjs.map} +1 -1
  211. package/dist/{parquetToCsvOneFile-ChmPC6dL.mjs → parquetToCsvOneFile-DtbCFm08.mjs} +3 -3
  212. package/dist/{parquetToCsvOneFile-ChmPC6dL.mjs.map → parquetToCsvOneFile-DtbCFm08.mjs.map} +1 -1
  213. package/dist/{parseAttributesFromString-CO16oAlx.mjs → parseAttributesFromString-C5hJMRvt.mjs} +2 -2
  214. package/dist/{parseAttributesFromString-CO16oAlx.mjs.map → parseAttributesFromString-C5hJMRvt.mjs.map} +1 -1
  215. package/dist/{parseVariablesFromString-BOSfQ4QF.mjs → parseVariablesFromString-6TYW65LF.mjs} +1 -1
  216. package/dist/{parseVariablesFromString-BOSfQ4QF.mjs.map → parseVariablesFromString-6TYW65LF.mjs.map} +1 -1
  217. package/dist/paths-J5KScOaQ.mjs +2 -0
  218. package/dist/paths-J5KScOaQ.mjs.map +1 -0
  219. package/dist/policy-bundle-manifest-BZnBMZQq.mjs +7 -0
  220. package/dist/policy-bundle-manifest-BZnBMZQq.mjs.map +1 -0
  221. package/dist/policy-project-discovery-C29UxWwt.mjs +427 -0
  222. package/dist/policy-project-discovery-C29UxWwt.mjs.map +1 -0
  223. package/dist/{policy-runtime-BMKa-Upy.mjs → policy-runtime-6jmkXlBk.mjs} +2 -2
  224. package/dist/{policy-runtime-BMKa-Upy.mjs.map → policy-runtime-6jmkXlBk.mjs.map} +1 -1
  225. package/dist/policy-scaffold-config-BUKAyPad.mjs +76 -0
  226. package/dist/policy-scaffold-config-BUKAyPad.mjs.map +1 -0
  227. package/dist/{policyEngineCliError-DY8V-qkK.mjs → policyEngineCliError-CZrOHhLv.mjs} +1 -1
  228. package/dist/{policyEngineCliError-DY8V-qkK.mjs.map → policyEngineCliError-CZrOHhLv.mjs.map} +1 -1
  229. package/dist/{printResult-CHe3nRN4.mjs → printResult-C2K9ODeE.mjs} +3 -3
  230. package/dist/printResult-C2K9ODeE.mjs.map +1 -0
  231. package/dist/project-discovery-BkHpTXDx.mjs +2 -0
  232. package/dist/project-discovery-BkHpTXDx.mjs.map +1 -0
  233. package/dist/project-discovery-CWRjlFnC.mjs +2 -0
  234. package/dist/project-discovery-CWRjlFnC.mjs.map +1 -0
  235. package/dist/project-plan-apply-Bg_1eMX9.mjs +3 -0
  236. package/dist/{project-plan-apply-Dvndx455.mjs.map → project-plan-apply-Bg_1eMX9.mjs.map} +1 -1
  237. package/dist/project-plan-output-BHHlkLxe.mjs +4 -0
  238. package/dist/project-plan-output-BHHlkLxe.mjs.map +1 -0
  239. package/dist/prompts-BhXfYD6g.mjs +2 -0
  240. package/dist/prompts-BhXfYD6g.mjs.map +1 -0
  241. package/dist/{pullAllDatapoints-uk5ggk6O.mjs → pullAllDatapoints-Bm-Orhse.mjs} +2 -2
  242. package/dist/{pullAllDatapoints-uk5ggk6O.mjs.map → pullAllDatapoints-Bm-Orhse.mjs.map} +1 -1
  243. package/dist/{pullChunkedCustomSiloOutstandingIdentifiers-DbFFXAVM.mjs → pullChunkedCustomSiloOutstandingIdentifiers-DTGQOw--.mjs} +2 -2
  244. package/dist/{pullChunkedCustomSiloOutstandingIdentifiers-DbFFXAVM.mjs.map → pullChunkedCustomSiloOutstandingIdentifiers-DTGQOw--.mjs.map} +1 -1
  245. package/dist/{pullConsentManagerMetrics-Dv5n1ZGp.mjs → pullConsentManagerMetrics-DKCkfbCB.mjs} +2 -2
  246. package/dist/{pullConsentManagerMetrics-Dv5n1ZGp.mjs.map → pullConsentManagerMetrics-DKCkfbCB.mjs.map} +1 -1
  247. package/dist/{pullManualEnrichmentIdentifiersToCsv-D5is0Nrs.mjs → pullManualEnrichmentIdentifiersToCsv-DMC5CQtE.mjs} +2 -2
  248. package/dist/{pullManualEnrichmentIdentifiersToCsv-D5is0Nrs.mjs.map → pullManualEnrichmentIdentifiersToCsv-DMC5CQtE.mjs.map} +1 -1
  249. package/dist/{pullTranscendConfiguration-B63M3ild.mjs → pullTranscendConfiguration-CDUDqxpm.mjs} +2 -2
  250. package/dist/{pullTranscendConfiguration-B63M3ild.mjs.map → pullTranscendConfiguration-CDUDqxpm.mjs.map} +1 -1
  251. package/dist/{pullUnstructuredSubDataPointRecommendations-YTBzfkRZ.mjs → pullUnstructuredSubDataPointRecommendations-Ci4AOxyH.mjs} +2 -2
  252. package/dist/{pullUnstructuredSubDataPointRecommendations-YTBzfkRZ.mjs.map → pullUnstructuredSubDataPointRecommendations-Ci4AOxyH.mjs.map} +1 -1
  253. package/dist/{pushCronIdentifiersFromCsv-Ctq38wAY.mjs → pushCronIdentifiersFromCsv-DhS2z8IG.mjs} +2 -2
  254. package/dist/{pushCronIdentifiersFromCsv-Ctq38wAY.mjs.map → pushCronIdentifiersFromCsv-DhS2z8IG.mjs.map} +1 -1
  255. package/dist/{pushManualEnrichmentIdentifiersFromCsv-0WHf6d_m.mjs → pushManualEnrichmentIdentifiersFromCsv-BTJGOmdU.mjs} +2 -2
  256. package/dist/{pushManualEnrichmentIdentifiersFromCsv-0WHf6d_m.mjs.map → pushManualEnrichmentIdentifiersFromCsv-BTJGOmdU.mjs.map} +1 -1
  257. package/dist/{readCsv-DLg8pwjd.mjs → readCsv-DNcJ_UfU.mjs} +1 -1
  258. package/dist/{readCsv-DLg8pwjd.mjs.map → readCsv-DNcJ_UfU.mjs.map} +1 -1
  259. package/dist/{readTranscendYaml-BNn6-Ofi.mjs → readTranscendYaml-BfqQbPiT.mjs} +3 -3
  260. package/dist/{readTranscendYaml-BNn6-Ofi.mjs.map → readTranscendYaml-BfqQbPiT.mjs.map} +1 -1
  261. package/dist/{removeUnverifiedRequestIdentifiers-Do3Pus6m.mjs → removeUnverifiedRequestIdentifiers-BkAcUZZN.mjs} +2 -2
  262. package/dist/{removeUnverifiedRequestIdentifiers-Do3Pus6m.mjs.map → removeUnverifiedRequestIdentifiers-BkAcUZZN.mjs.map} +1 -1
  263. package/dist/{renderTable-D68QasPc.mjs → renderTable-CZP2roD1.mjs} +1 -1
  264. package/dist/{renderTable-D68QasPc.mjs.map → renderTable-CZP2roD1.mjs.map} +1 -1
  265. package/dist/{request-BiPv6jmP.mjs → request-BpKyN9Xm.mjs} +1 -1
  266. package/dist/{request-BiPv6jmP.mjs.map → request-BpKyN9Xm.mjs.map} +1 -1
  267. package/dist/{resolveBundleIdByName-qXZBrUz_.mjs → resolveBundleIdByName-Dm_o5_bg.mjs} +2 -2
  268. package/dist/{resolveBundleIdByName-qXZBrUz_.mjs.map → resolveBundleIdByName-Dm_o5_bg.mjs.map} +1 -1
  269. package/dist/{resolvePolicyBundleVersion-BG7XqBBP.mjs → resolvePolicyBundleVersion-DRUwe7fA.mjs} +2 -2
  270. package/dist/{resolvePolicyBundleVersion-BG7XqBBP.mjs.map → resolvePolicyBundleVersion-DRUwe7fA.mjs.map} +1 -1
  271. package/dist/{retryRequestDataSilos-CEgUW6Fx.mjs → retryRequestDataSilos-BoPmcB8-.mjs} +2 -2
  272. package/dist/{retryRequestDataSilos-CEgUW6Fx.mjs.map → retryRequestDataSilos-BoPmcB8-.mjs.map} +1 -1
  273. package/dist/{run-captured-process-BXwWXuTh.mjs → run-captured-process-BjaSDWXG.mjs} +1 -1
  274. package/dist/{run-captured-process-BXwWXuTh.mjs.map → run-captured-process-BjaSDWXG.mjs.map} +1 -1
  275. package/dist/{runOpa-CswzJxIs.mjs → runOpa-ojIqU1tO.mjs} +2 -2
  276. package/dist/{runOpa-CswzJxIs.mjs.map → runOpa-ojIqU1tO.mjs.map} +1 -1
  277. package/dist/{scaffold-model-BAbYTR0q.mjs → scaffold-model-CUZER0BC.mjs} +1 -1
  278. package/dist/scaffold-model-CUZER0BC.mjs.map +1 -0
  279. package/dist/{scaffold-planning-CNv83t_v.mjs → scaffold-planning-CaetLfv8.mjs} +9 -9
  280. package/dist/{scaffold-planning-CNv83t_v.mjs.map → scaffold-planning-CaetLfv8.mjs.map} +1 -1
  281. package/dist/{scaffold-templates-DzDGTZie.mjs → scaffold-templates-CUL82Zf8.mjs} +1 -1
  282. package/dist/{scaffold-templates-DzDGTZie.mjs.map → scaffold-templates-CUL82Zf8.mjs.map} +1 -1
  283. package/dist/{skipPreflightJobs-D_1mZ9mr.mjs → skipPreflightJobs-DkBdYw-r.mjs} +2 -2
  284. package/dist/{skipPreflightJobs-D_1mZ9mr.mjs.map → skipPreflightJobs-DkBdYw-r.mjs.map} +1 -1
  285. package/dist/{skipRequestDataSilos-CcGl9Z8M.mjs → skipRequestDataSilos-BRFiokix.mjs} +2 -2
  286. package/dist/{skipRequestDataSilos-CcGl9Z8M.mjs.map → skipRequestDataSilos-BRFiokix.mjs.map} +1 -1
  287. package/dist/{streamPrivacyRequestsToCsv-1l8RAcnK.mjs → streamPrivacyRequestsToCsv-Bt-H5J-y.mjs} +2 -2
  288. package/dist/{streamPrivacyRequestsToCsv-1l8RAcnK.mjs.map → streamPrivacyRequestsToCsv-Bt-H5J-y.mjs.map} +1 -1
  289. package/dist/{syncCodePackages-BHE2Tn1Q.mjs → syncCodePackages-CPkEukDm.mjs} +2 -2
  290. package/dist/{syncCodePackages-BHE2Tn1Q.mjs.map → syncCodePackages-CPkEukDm.mjs.map} +1 -1
  291. package/dist/{updateConsentManagerVersionToLatest-yZhBDcv8.mjs → updateConsentManagerVersionToLatest-DWblAwus.mjs} +2 -2
  292. package/dist/{updateConsentManagerVersionToLatest-yZhBDcv8.mjs.map → updateConsentManagerVersionToLatest-DWblAwus.mjs.map} +1 -1
  293. package/dist/{uploadConsents-DQqApEaH.mjs → uploadConsents-D7Vg8ZRW.mjs} +2 -2
  294. package/dist/{uploadConsents-DQqApEaH.mjs.map → uploadConsents-D7Vg8ZRW.mjs.map} +1 -1
  295. package/dist/{uploadPrivacyRequestsFromCsv-ntuK0eSR.mjs → uploadPrivacyRequestsFromCsv-B_hQwIn6.mjs} +2 -2
  296. package/dist/{uploadPrivacyRequestsFromCsv-ntuK0eSR.mjs.map → uploadPrivacyRequestsFromCsv-B_hQwIn6.mjs.map} +1 -1
  297. package/dist/validateTranscendAuth-D-dDINof.mjs +2 -0
  298. package/dist/{validateTranscendAuth-D6Wr1cxY.mjs.map → validateTranscendAuth-D-dDINof.mjs.map} +1 -1
  299. package/dist/{writeCsv-D-2siSwE.mjs → writeCsv-CNZrq3zU.mjs} +1 -1
  300. package/dist/{writeCsv-D-2siSwE.mjs.map → writeCsv-CNZrq3zU.mjs.map} +1 -1
  301. package/package.json +6 -5
  302. package/dist/app-DhG-JhT3.mjs +0 -148
  303. package/dist/app-DhG-JhT3.mjs.map +0 -1
  304. package/dist/command-Ds6oNo0v.mjs +0 -9
  305. package/dist/command-Ds6oNo0v.mjs.map +0 -1
  306. package/dist/deno-runtime-DV52X8-P.mjs +0 -2
  307. package/dist/deno-runtime-DV52X8-P.mjs.map +0 -1
  308. package/dist/impl--JGnR3wp.mjs +0 -3
  309. package/dist/impl-7UqkSO3x2.mjs +0 -2
  310. package/dist/impl-7UqkSO3x2.mjs.map +0 -1
  311. package/dist/impl-B4BgGuF_.mjs +0 -3
  312. package/dist/impl-B4BgGuF_.mjs.map +0 -1
  313. package/dist/impl-B5oVsX-F2.mjs +0 -303
  314. package/dist/impl-B5oVsX-F2.mjs.map +0 -1
  315. package/dist/impl-BEA5cQOT2.mjs.map +0 -1
  316. package/dist/impl-BhfxcCgN2.mjs.map +0 -1
  317. package/dist/impl-BppXJ1AD2.mjs.map +0 -1
  318. package/dist/impl-C6HtWd1t.mjs +0 -2
  319. package/dist/impl-C6HtWd1t.mjs.map +0 -1
  320. package/dist/impl-CO4ZqlLV.mjs +0 -3
  321. package/dist/impl-CO4ZqlLV.mjs.map +0 -1
  322. package/dist/impl-COujMWgp.mjs.map +0 -1
  323. package/dist/impl-CUOVJsRg.mjs +0 -3
  324. package/dist/impl-CUOVJsRg.mjs.map +0 -1
  325. package/dist/impl-CUiYbk6G.mjs +0 -3
  326. package/dist/impl-CUiYbk6G.mjs.map +0 -1
  327. package/dist/impl-CfvxD3RI.mjs.map +0 -1
  328. package/dist/impl-CiBT9-GH2.mjs.map +0 -1
  329. package/dist/impl-Cli2XRp02.mjs +0 -2
  330. package/dist/impl-Cli2XRp02.mjs.map +0 -1
  331. package/dist/impl-D-AHlqlD2.mjs +0 -4
  332. package/dist/impl-DPN1En7L.mjs +0 -2
  333. package/dist/impl-DPN1En7L.mjs.map +0 -1
  334. package/dist/impl-DPtx5iZO.mjs +0 -5
  335. package/dist/impl-DQPmSYSE.mjs +0 -2
  336. package/dist/impl-DXRDWiB1.mjs +0 -2
  337. package/dist/impl-DXRDWiB1.mjs.map +0 -1
  338. package/dist/impl-DdIa0zla.mjs +0 -2
  339. package/dist/impl-DdIa0zla.mjs.map +0 -1
  340. package/dist/impl-Dp4bZvAV.mjs +0 -2
  341. package/dist/impl-Dp4bZvAV.mjs.map +0 -1
  342. package/dist/impl-DryC3OJu.mjs +0 -2
  343. package/dist/impl-DryC3OJu.mjs.map +0 -1
  344. package/dist/impl-DzUTmaID2.mjs.map +0 -1
  345. package/dist/impl-GytUVAMP.mjs +0 -2
  346. package/dist/impl-Z8oWVENM.mjs +0 -2
  347. package/dist/impl-Z8oWVENM.mjs.map +0 -1
  348. package/dist/impl-a_Y8bnSn.mjs.map +0 -1
  349. package/dist/impl-lsmXIGSo2.mjs.map +0 -1
  350. package/dist/logger-zplFSeXU.mjs +0 -2
  351. package/dist/logger-zplFSeXU.mjs.map +0 -1
  352. package/dist/manifest-BNIpO_zW.mjs +0 -2
  353. package/dist/manifest-BNIpO_zW.mjs.map +0 -1
  354. package/dist/missing-manifest-DgcukXfg.mjs +0 -2
  355. package/dist/missing-manifest-DgcukXfg.mjs.map +0 -1
  356. package/dist/path-safety-D5Qwl40b.mjs +0 -2
  357. package/dist/path-safety-D5Qwl40b.mjs.map +0 -1
  358. package/dist/policy-bundle-manifest-D6dkbjNi.mjs +0 -7
  359. package/dist/policy-bundle-manifest-D6dkbjNi.mjs.map +0 -1
  360. package/dist/printResult-CHe3nRN4.mjs.map +0 -1
  361. package/dist/project-plan-apply-Dvndx455.mjs +0 -3
  362. package/dist/prompts-ClBXdELk.mjs +0 -4
  363. package/dist/prompts-ClBXdELk.mjs.map +0 -1
  364. package/dist/scaffold-model-BAbYTR0q.mjs.map +0 -1
  365. package/dist/validateTranscendAuth-D6Wr1cxY.mjs +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"impl-Dqqb0lVN.mjs","names":[],"sources":["../src/lib/oneTrust/helpers/oneTrustAssessmentToJson.ts","../src/lib/oneTrust/helpers/syncOneTrustAssessmentToDisk.ts","../src/lib/oneTrust/endpoints/getListOfOneTrustAssessments.ts","../src/lib/oneTrust/endpoints/getOneTrustAssessment.ts","../src/lib/oneTrust/endpoints/getOneTrustRisk.ts","../src/lib/oneTrust/endpoints/getOneTrustUser.ts","../src/lib/oneTrust/helpers/enrichOneTrustAssessment.ts","../src/lib/oneTrust/helpers/syncOneTrustAssessmentToTranscend.ts","../src/lib/oneTrust/helpers/syncOneTrustAssessmentsFromOneTrust.ts","../src/lib/oneTrust/helpers/syncOneTrustAssessmentsFromFile.ts","../src/lib/oneTrust/createOneTrustGotInstance.ts","../src/commands/migration/sync-ot/impl.ts"],"sourcesContent":["import { OneTrustEnrichedAssessment } from '@transcend-io/privacy-types';\n\n/**\n * Converts the assessment into a json entry.\n *\n * @param param - information about the assessment and amount of entries\n * @returns a stringified json entry ready to be appended to a file\n */\nexport const oneTrustAssessmentToJson = ({\n assessment,\n index,\n total,\n wrap = true,\n}: {\n /** The assessment to convert */\n assessment: OneTrustEnrichedAssessment;\n /** The position of the assessment in the final Json object */\n index: number;\n /** The total amount of the assessments in the final Json object */\n total?: number;\n /** Whether to wrap every entry in brackets */\n wrap?: boolean;\n}): string => {\n let jsonEntry = '';\n // start with an opening bracket\n if (index === 0 || wrap) {\n jsonEntry = '[\\n';\n }\n\n const stringifiedAssessment = JSON.stringify(assessment);\n\n // Add comma for all items except the last one\n const comma = total && index < total - 1 && !wrap ? ',' : '';\n\n // write to file\n jsonEntry = `${jsonEntry + stringifiedAssessment + comma}\\n`;\n\n // end with closing bracket\n if ((total && index === total - 1) || wrap) {\n jsonEntry += '\\n]';\n }\n\n return jsonEntry;\n};\n","import fs from 'node:fs';\n\nimport { OneTrustEnrichedAssessment } from '@transcend-io/privacy-types';\nimport colors from 'colors';\n\nimport { logger } from '../../../logger.js';\nimport { oneTrustAssessmentToJson } from './oneTrustAssessmentToJson.js';\n\n/**\n * Write the assessment to disk at the specified file path.\n *\n *\n * @param param - information about the assessment to write\n */\nexport const syncOneTrustAssessmentToDisk = ({\n file,\n assessment,\n index,\n total,\n}: {\n /** The file path to write the assessment to */\n file: string;\n /** The basic assessment */\n assessment: OneTrustEnrichedAssessment;\n /** The index of the assessment being written to the file */\n index: number;\n /** The total amount of assessments that we will write */\n total: number;\n}): void => {\n logger.info(\n colors.magenta(`Writing enriched assessment ${index + 1} of ${total} to file \"${file}\"...`),\n );\n\n if (index === 0) {\n fs.writeFileSync(\n file,\n oneTrustAssessmentToJson({\n assessment,\n index,\n total,\n wrap: false,\n }),\n );\n } else {\n fs.appendFileSync(\n file,\n oneTrustAssessmentToJson({\n assessment,\n index,\n total,\n wrap: false,\n }),\n );\n }\n};\n","import {\n OneTrustAssessment,\n OneTrustGetListOfAssessmentsResponse,\n} from '@transcend-io/privacy-types';\nimport { decodeCodec } from '@transcend-io/type-utils';\nimport { Got } from 'got';\n\nimport { logger } from '../../../logger.js';\n\n/**\n * Fetch a list of all assessments from the OneTrust client.\n * ref: https://developer.onetrust.com/onetrust/reference/getallassessmentbasicdetailsusingget\n *\n * @param param - the information about the OneTrust client\n * @returns a list of OneTrustAssessment\n */\nexport const getListOfOneTrustAssessments = async ({\n oneTrust,\n}: {\n /** The OneTrust client instance */\n oneTrust: Got;\n}): Promise<OneTrustAssessment[]> => {\n let currentPage = 0;\n let totalPages = 1;\n let totalElements = 0;\n\n const allAssessments: OneTrustAssessment[] = [];\n\n while (currentPage < totalPages) {\n const { body } = await oneTrust.get(\n `api/assessment/v2/assessments?page=${currentPage}&size=2000`,\n );\n\n const { page, content } = decodeCodec(OneTrustGetListOfAssessmentsResponse, body);\n allAssessments.push(...(content ?? []));\n if (currentPage === 0) {\n totalPages = page?.totalPages ?? 0;\n totalElements = page?.totalElements ?? 0;\n }\n currentPage += 1;\n\n // log progress\n logger.info(`Fetched ${allAssessments.length} of ${totalElements} assessments.`);\n }\n\n return allAssessments;\n};\n","import { OneTrustGetAssessmentResponse } from '@transcend-io/privacy-types';\nimport { decodeCodec } from '@transcend-io/type-utils';\nimport { Got } from 'got';\n\n/**\n * Retrieve details about a particular assessment.\n * ref: https://developer.onetrust.com/onetrust/reference/exportassessmentusingget\n *\n * @param param - the information about the OneTrust client and assessment to retrieve\n * @returns details about the assessment\n */\nexport const getOneTrustAssessment = async ({\n oneTrust,\n assessmentId,\n}: {\n /** The OneTrust client instance */\n oneTrust: Got;\n /** The ID of the assessment to retrieve */\n assessmentId: string;\n}): Promise<OneTrustGetAssessmentResponse> => {\n const { body } = await oneTrust.get(\n `api/assessment/v2/assessments/${assessmentId}/export?ExcludeSkippedQuestions=false`,\n );\n\n return decodeCodec(OneTrustGetAssessmentResponse, body);\n};\n","import { OneTrustGetRiskResponse } from '@transcend-io/privacy-types';\nimport { decodeCodec } from '@transcend-io/type-utils';\nimport { Got } from 'got';\n\n/**\n * Retrieve details about a particular risk.\n * ref: https://developer.onetrust.com/onetrust/reference/getriskusingget\n *\n * @param param - the information about the OneTrust client and risk to retrieve\n * @returns the OneTrust risk\n */\nexport const getOneTrustRisk = async ({\n oneTrust,\n riskId,\n}: {\n /** The OneTrust client instance */\n oneTrust: Got;\n /** The ID of the OneTrust risk to retrieve */\n riskId: string;\n}): Promise<OneTrustGetRiskResponse> => {\n const { body } = await oneTrust.get(`api/risk/v2/risks/${riskId}`);\n\n return decodeCodec(OneTrustGetRiskResponse, body);\n};\n","import { OneTrustGetUserResponse } from '@transcend-io/privacy-types';\nimport { decodeCodec } from '@transcend-io/type-utils';\nimport { Got } from 'got';\n\n/**\n * Retrieve details about a particular user.\n * ref: https://developer.onetrust.com/onetrust/reference/getriskusingget\n *\n * @param param - the information about the OneTrust client and risk to retrieve\n * @returns the OneTrust risk\n */\nexport const getOneTrustUser = async ({\n oneTrust,\n userId,\n}: {\n /** The OneTrust client instance */\n oneTrust: Got;\n /** The ID of the OneTrust user to retrieve */\n userId: string;\n}): Promise<OneTrustGetUserResponse> => {\n const { body } = await oneTrust.get(`api/scim/v2/Users/${userId}`);\n\n return decodeCodec(OneTrustGetUserResponse, body);\n};\n","import {\n OneTrustAssessment,\n OneTrustEnrichedAssessment,\n OneTrustGetAssessmentResponse,\n OneTrustGetRiskResponse,\n OneTrustGetUserResponse,\n} from '@transcend-io/privacy-types';\nimport { keyBy } from 'lodash-es';\n\n/**\n * Merge the assessment, assessmentDetails, and riskDetails into one object.\n *\n * @param param - the assessment and risk information\n * @returns the assessment enriched with details and risk information\n */\nexport const enrichOneTrustAssessment = ({\n assessment,\n assessmentDetails,\n riskDetails,\n creatorDetails,\n approversDetails,\n respondentsDetails,\n}: {\n /** The OneTrust risk details */\n riskDetails: OneTrustGetRiskResponse[];\n /** The OneTrust assessment as returned from Get List of Assessments endpoint */\n assessment: OneTrustAssessment;\n /** The OneTrust assessment details */\n assessmentDetails: OneTrustGetAssessmentResponse;\n /** The OneTrust assessment creator details */\n creatorDetails: OneTrustGetUserResponse;\n /** The OneTrust assessment approvers details */\n approversDetails: OneTrustGetUserResponse[];\n /** The OneTrust assessment internal respondents details */\n respondentsDetails: OneTrustGetUserResponse[];\n}): OneTrustEnrichedAssessment => {\n const riskDetailsById = keyBy(riskDetails, 'id');\n const { sections, createdBy, ...restAssessmentDetails } = assessmentDetails;\n const sectionsWithEnrichedRisk = sections.map((section) => {\n const { questions, ...restSection } = section;\n const enrichedQuestions = questions.map((question) => {\n const { risks, ...restQuestion } = question;\n const enrichedRisks = (risks ?? []).map((risk) => {\n const details = riskDetailsById[risk.riskId];\n return {\n ...risk,\n ...details,\n level: risk.level,\n impactLevel: risk.impactLevel ?? 0,\n };\n });\n return {\n ...restQuestion,\n risks: enrichedRisks,\n };\n });\n return {\n ...restSection,\n questions: enrichedQuestions,\n };\n });\n\n // grab creator details\n const enrichedCreatedBy = {\n ...createdBy,\n active: creatorDetails?.active ?? false,\n userType: creatorDetails?.userType ?? 'Internal',\n emails: creatorDetails?.emails ?? [],\n title: creatorDetails?.title ?? null,\n givenName: creatorDetails?.name.givenName ?? null,\n familyName: creatorDetails?.name.familyName ?? null,\n };\n\n // grab approvers details\n const approverDetailsById = keyBy(approversDetails, 'id');\n const enrichedApprovers = assessmentDetails.approvers.flatMap((originalApprover) =>\n approverDetailsById[originalApprover.id]\n ? [\n {\n ...originalApprover,\n approver: {\n ...originalApprover.approver,\n active: approverDetailsById[originalApprover.id].active,\n userType: approverDetailsById[originalApprover.id].userType,\n emails: approverDetailsById[originalApprover.id].emails,\n title: approverDetailsById[originalApprover.id].title,\n givenName: approverDetailsById[originalApprover.id].name.givenName ?? null,\n familyName: approverDetailsById[originalApprover.id].name.familyName ?? null,\n },\n },\n ]\n : [],\n );\n\n // grab respondents details\n const respondentsDetailsById = keyBy(respondentsDetails, 'id');\n const enrichedRespondents = assessmentDetails.respondents\n .filter((r) => !r.name.includes('@')) // search only internal respondents\n .flatMap((respondent) =>\n respondentsDetailsById[respondent.id]\n ? [\n {\n ...respondent,\n active: respondentsDetailsById[respondent.id].active,\n userType: respondentsDetailsById[respondent.id].userType,\n emails: respondentsDetailsById[respondent.id].emails,\n title: respondentsDetailsById[respondent.id].title,\n givenName: respondentsDetailsById[respondent.id].name.givenName ?? null,\n familyName: respondentsDetailsById[respondent.id].name.familyName ?? null,\n },\n ]\n : [],\n );\n\n // combine everything into a single enriched assessment\n return {\n ...assessment,\n ...restAssessmentDetails,\n approvers: enrichedApprovers,\n respondents: enrichedRespondents,\n createdBy: enrichedCreatedBy,\n sections: sectionsWithEnrichedRisk,\n };\n};\n","import { OneTrustEnrichedAssessment } from '@transcend-io/privacy-types';\nimport { makeGraphQLRequest, IMPORT_ONE_TRUST_ASSESSMENT_FORMS } from '@transcend-io/sdk';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\n\nimport { ImportOnetrustAssessmentsInput } from '../../../codecs.js';\nimport { logger } from '../../../logger.js';\nimport { oneTrustAssessmentToJson } from './oneTrustAssessmentToJson.js';\n\nexport interface AssessmentForm {\n /** ID of Assessment Form */\n id: string;\n /** Title of Assessment Form */\n name: string;\n}\n\n/**\n * Write the assessment to a Transcend instance.\n *\n *\n * @param param - information about the assessment and Transcend instance to write to\n */\nexport const syncOneTrustAssessmentToTranscend = async ({\n transcend,\n assessment,\n total,\n index,\n}: {\n /** the Transcend client instance */\n transcend: GraphQLClient;\n /** the assessment to sync to Transcend */\n assessment: OneTrustEnrichedAssessment;\n /** The index of the assessment being written to the file */\n index: number;\n /** The total amount of assessments that we will write */\n total?: number;\n}): Promise<void> => {\n logger.info(\n colors.magenta(\n `Writing enriched assessment ${index + 1} ${total ? `of ${total} ` : ' '}to Transcend...`,\n ),\n );\n\n // convert the OneTrust assessment object into a json record\n const json = oneTrustAssessmentToJson({\n assessment,\n index,\n total,\n });\n\n // transform the json record into a valid input to the mutation\n const input: ImportOnetrustAssessmentsInput = {\n json,\n };\n\n try {\n await makeGraphQLRequest<{\n /** the importOneTrustAssessmentForms mutation */\n importOneTrustAssessmentForms: {\n /** Created Assessment Forms */\n assessmentForms: AssessmentForm[];\n };\n }>(transcend, IMPORT_ONE_TRUST_ASSESSMENT_FORMS, {\n variables: { input },\n logger,\n });\n } catch (error) {\n logger.error(\n colors.red(\n `Failed to sync assessment ${index + 1} ${total ? `of ${total} ` : ' '}to Transcend.\\n` +\n `\\tAssessment Title: ${assessment.name}. Template Title: ${assessment.template.name}\\n`,\n ),\n error,\n );\n }\n};\n","import {\n OneTrustAssessmentQuestion,\n OneTrustAssessmentSection,\n OneTrustEnrichedAssessment,\n OneTrustGetRiskResponse,\n OneTrustGetUserResponse,\n} from '@transcend-io/privacy-types';\nimport { mapSeries, map } from '@transcend-io/utils';\nimport colors from 'colors';\nimport type { Got } from 'got';\nimport { GraphQLClient } from 'graphql-request';\nimport { uniq } from 'lodash-es';\n\nimport { logger } from '../../../logger.js';\nimport {\n getListOfOneTrustAssessments,\n getOneTrustAssessment,\n getOneTrustRisk,\n getOneTrustUser,\n} from '../endpoints/index.js';\nimport { enrichOneTrustAssessment } from './enrichOneTrustAssessment.js';\nimport { syncOneTrustAssessmentToDisk } from './syncOneTrustAssessmentToDisk.js';\nimport { syncOneTrustAssessmentToTranscend } from './syncOneTrustAssessmentToTranscend.js';\n\nexport interface AssessmentForm {\n /** ID of Assessment Form */\n id: string;\n /** Title of Assessment Form */\n name: string;\n}\n\n/**\n * Reads all the assessments from a OneTrust instance and syncs them to Transcend or to Disk.\n *\n * @param param - the information about the assessment, its OneTrust source, and destination (disk or Transcend)\n */\nexport const syncOneTrustAssessmentsFromOneTrust = async ({\n oneTrust,\n file,\n dryRun,\n transcend,\n}: {\n /** the OneTrust client instance */\n oneTrust: Got;\n /** the Transcend client instance */\n transcend?: GraphQLClient;\n /** Whether to write to file instead of syncing to Transcend */\n dryRun: boolean;\n /** the path to the file in case dryRun is true */\n file?: string;\n}): Promise<void> => {\n // fetch the list of all assessments in the OneTrust organization\n logger.info('Getting list of all assessments from OneTrust...');\n const assessments = await getListOfOneTrustAssessments({ oneTrust });\n\n // a cache of OneTrust users so we avoid requesting already fetched users\n const oneTrustCachedUsers: Record<string, OneTrustGetUserResponse> = {};\n\n // split all assessments in batches, so we can process some of steps in parallel\n const BATCH_SIZE = 5;\n const assessmentBatches = Array.from(\n {\n length: Math.ceil(assessments.length / BATCH_SIZE),\n },\n (_, i) => assessments.slice(i * BATCH_SIZE, (i + 1) * BATCH_SIZE),\n );\n\n // process each batch and sync the batch right away so it's garbage collected and we don't run out of memory\n await mapSeries(assessmentBatches, async (assessmentBatch, batch) => {\n const batchEnrichedAssessments: OneTrustEnrichedAssessment[] = [];\n\n // fetch assessment details from OneTrust in parallel\n await map(\n assessmentBatch,\n async (assessment, index) => {\n const assessmentNumber = BATCH_SIZE * batch + index + 1;\n logger.info(\n `[assessment ${assessmentNumber} of ${assessments.length}]: fetching details...`,\n );\n const { templateName, assessmentId } = assessment;\n const assessmentDetails = await getOneTrustAssessment({\n oneTrust,\n assessmentId,\n });\n // fetch assessment's creator information\n const creatorId = assessmentDetails.createdBy.id;\n let creator = oneTrustCachedUsers[creatorId];\n if (!creator) {\n logger.info(\n `[assessment ${assessmentNumber} of ${assessments.length}]: fetching creator...`,\n );\n try {\n creator = await getOneTrustUser({\n oneTrust,\n userId: creatorId,\n });\n oneTrustCachedUsers[creatorId] = creator;\n } catch (error) {\n logger.warn(\n colors.yellow(\n `[assessment ${assessmentNumber} of ${assessments.length}]: failed to fetch form creator.` +\n `\\tcreatorId: ${creatorId}. Assessment Title: ${assessment.name}. Template Title: ${templateName}`,\n ),\n error,\n );\n }\n }\n\n // fetch assessment approvers information\n const { approvers } = assessmentDetails;\n let approversDetails: OneTrustGetUserResponse[][] = [];\n if (approvers.length > 0) {\n logger.info(\n `[assessment ${assessmentNumber} of ${assessments.length}]: fetching approvers...`,\n );\n approversDetails = await map(\n approvers.map(({ id }) => id),\n async (userId) => {\n try {\n let approver = oneTrustCachedUsers[userId];\n if (!approver) {\n approver = await getOneTrustUser({ oneTrust, userId });\n oneTrustCachedUsers[userId] = approver;\n }\n return [approver];\n } catch (error) {\n logger.warn(\n colors.yellow(\n `[assessment ${assessmentNumber} of ${assessments.length}]: failed to fetch a form approver.` +\n `\\tapproverId: ${userId}. Assessment Title: ${assessment.name}. Template Title: ${templateName}`,\n ),\n error,\n );\n return [];\n }\n },\n { concurrency: 5 },\n );\n }\n\n // fetch assessment internal respondents information\n const { respondents } = assessmentDetails;\n // if a user is an internal respondents, their 'name' field can't be an email.\n const internalRespondents = respondents.filter((r) => !r.name.includes('@'));\n let respondentsDetails: OneTrustGetUserResponse[][] = [];\n if (internalRespondents.length > 0) {\n logger.info(\n `[assessment ${assessmentNumber} of ${assessments.length}]: fetching respondents...`,\n );\n respondentsDetails = await map(\n internalRespondents.map(({ id }) => id),\n async (userId) => {\n try {\n let respondent = oneTrustCachedUsers[userId];\n if (!respondent) {\n respondent = await getOneTrustUser({ oneTrust, userId });\n oneTrustCachedUsers[userId] = respondent;\n }\n return [respondent];\n } catch (error) {\n logger.warn(\n colors.yellow(\n `[assessment ${assessmentNumber} of ${assessments.length}]: failed to fetch a respondent.` +\n `\\trespondentId: ${userId}. Assessment Title: ${assessment.name}. Template Title: ${templateName}`,\n ),\n error,\n );\n return [];\n }\n },\n { concurrency: 5 },\n );\n }\n\n // fetch assessment risk information\n let riskDetails: OneTrustGetRiskResponse[] = [];\n const riskIds = uniq(\n assessmentDetails.sections.flatMap((s: OneTrustAssessmentSection) =>\n s.questions.flatMap((q: OneTrustAssessmentQuestion) =>\n (q.risks ?? []).flatMap((r) => r.riskId),\n ),\n ),\n );\n if (riskIds.length > 0) {\n logger.info(\n `[assessment ${assessmentNumber} of ${assessments.length}]: fetching risks...`,\n );\n riskDetails = await map(\n riskIds,\n (riskId) => getOneTrustRisk({ oneTrust, riskId: riskId as string }),\n {\n concurrency: 5,\n },\n );\n }\n\n // enrich the assessments with user and risk details\n const enrichedAssessment = enrichOneTrustAssessment({\n assessment,\n assessmentDetails,\n riskDetails,\n creatorDetails: creator,\n approversDetails: approversDetails.flat(),\n respondentsDetails: respondentsDetails.flat(),\n });\n\n batchEnrichedAssessments.push(enrichedAssessment);\n },\n { concurrency: BATCH_SIZE },\n );\n\n // sync assessments in series to avoid concurrency bugs\n await mapSeries(batchEnrichedAssessments, async (enrichedAssessment, index) => {\n // the assessment's global index takes its batch into consideration\n const globalIndex = batch * BATCH_SIZE + index;\n\n if (dryRun && file) {\n // sync to file\n syncOneTrustAssessmentToDisk({\n assessment: enrichedAssessment,\n index: globalIndex,\n total: assessments.length,\n file,\n });\n } else if (transcend) {\n // sync to transcend\n await syncOneTrustAssessmentToTranscend({\n assessment: enrichedAssessment,\n transcend,\n total: assessments.length,\n index: globalIndex,\n });\n }\n });\n });\n};\n","import { createReadStream } from 'node:fs';\n\nimport { OneTrustEnrichedAssessment } from '@transcend-io/privacy-types';\nimport { decodeCodec } from '@transcend-io/type-utils';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport JSONStream from 'JSONStream';\n\nimport { logger } from '../../../logger.js';\nimport { syncOneTrustAssessmentToTranscend } from './syncOneTrustAssessmentToTranscend.js';\n\n/**\n * Reads assessments from a file and syncs them to Transcend.\n *\n * @param param - the information about the source file and Transcend instance to write them to.\n */\nexport const syncOneTrustAssessmentsFromFile = ({\n transcend,\n file,\n}: {\n /** the Transcend client instance */\n transcend: GraphQLClient;\n /** The name of the file from which to read the OneTrust assessments */\n file: string;\n}): Promise<void> => {\n logger.info(`Getting list of all assessments from file ${file}...`);\n\n return new Promise((resolve, reject) => {\n // Create a readable stream from the file\n const fileStream = createReadStream(file, {\n encoding: 'utf-8',\n highWaterMark: 64 * 1024, // 64KB chunks\n });\n\n // Create a JSONStream parser to parse the array of OneTrust assessments from the file\n const parser = JSONStream.parse('*'); // '*' matches each element in the root array\n\n let index = 0;\n\n // Pipe the file stream into the JSON parser\n fileStream.pipe(parser);\n\n // Handle each parsed assessment object\n parser.on('data', async (assessment) => {\n try {\n // Pause the stream while processing to avoid overwhelming memory\n parser.pause();\n\n // Decode and validate the assessment\n const parsedAssessment = decodeCodec(OneTrustEnrichedAssessment, assessment);\n\n // Sync the assessment to transcend\n await syncOneTrustAssessmentToTranscend({\n assessment: parsedAssessment,\n transcend,\n index,\n });\n\n index += 1;\n\n // Resume the stream after processing\n parser.resume();\n } catch (e) {\n // if failed to parse a line, report error and continue\n logger.error(\n colors.red(`Failed to parse the assessment ${index} from file '${file}': ${e.message}.`),\n );\n }\n });\n\n // Handle completion\n parser.on('end', () => {\n logger.info(`Finished processing ${index} assessments from file ${file}`);\n resolve();\n });\n\n // Handle stream or parsing errors\n parser.on('error', (error) => {\n logger.error(colors.red(`Error parsing file '${file}': ${error.message}`));\n reject(error);\n });\n\n fileStream.on('error', (error) => {\n logger.error(colors.red(`Error reading file '${file}': ${error.message}`));\n reject(error);\n });\n });\n};\n","import got, { Got } from 'got';\n\n/**\n * Instantiate an instance of got that is capable of making requests to OneTrust\n *\n * @param param - information about the OneTrust URL\n * @returns The instance of got that is capable of making requests to the customer ingress\n */\nexport const createOneTrustGotInstance = ({\n hostname,\n auth,\n}: {\n /** Hostname of the OneTrust API */\n hostname: string;\n /** The OAuth access token */\n auth: string;\n}): Got =>\n got.extend({\n prefixUrl: `https://${hostname}`,\n headers: {\n accept: 'application/json',\n 'content-type': 'application/json',\n authorization: `Bearer ${auth}`,\n },\n });\n","import { buildTranscendGraphQLClient } from '@transcend-io/sdk';\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { OneTrustFileFormat, OneTrustPullResource, OneTrustPullSource } from '../../../enums.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport {\n syncOneTrustAssessmentsFromFile,\n syncOneTrustAssessmentsFromOneTrust,\n} from '../../../lib/oneTrust/helpers/index.js';\nimport { createOneTrustGotInstance } from '../../../lib/oneTrust/index.js';\n\n// Command flag interface\nexport interface SyncOtCommandFlags {\n hostname?: string;\n oneTrustAuth?: string;\n source: OneTrustPullSource;\n transcendAuth?: string;\n transcendUrl: string;\n file?: string;\n resource: OneTrustPullResource;\n dryRun: boolean;\n debug: boolean;\n}\n\n// Command implementation\nexport async function syncOt(\n this: LocalContext,\n {\n hostname,\n oneTrustAuth,\n source,\n transcendAuth,\n transcendUrl,\n resource,\n file,\n dryRun,\n debug,\n }: SyncOtCommandFlags,\n): Promise<void> {\n // Must be able to authenticate to transcend to sync resources to it\n if (!dryRun && !transcendAuth) {\n throw new Error(\n // eslint-disable-next-line no-template-curly-in-string\n 'Must specify a \"transcendAuth\" parameter to sync resources to Transcend. e.g. --transcendAuth=${TRANSCEND_API_KEY}',\n );\n }\n\n // If trying to sync to disk, must specify a file path\n if (dryRun && !file) {\n throw new Error(\n 'Must set a \"file\" parameter when \"dryRun\" is \"true\". e.g. --file=./oneTrustAssessments.json',\n );\n }\n\n if (file) {\n const splitFile = file.split('.');\n if (splitFile.length < 2) {\n throw new Error(\n 'The \"file\" parameter has an invalid format. Expected a path with extensions. e.g. --file=./pathToFile.json.',\n );\n }\n if (splitFile.at(-1) !== OneTrustFileFormat.Json) {\n throw new Error(\n `Expected the format of the \"file\" parameters '${file}' to be '${\n OneTrustFileFormat.Json\n }', but got '${splitFile.at(-1)}'.`,\n );\n }\n }\n\n // if reading assessments from a OneTrust\n if (source === OneTrustPullSource.OneTrust) {\n // must specify the OneTrust hostname\n if (!hostname) {\n throw new Error(\n 'Missing required parameter \"hostname\". e.g. --hostname=customer.my.onetrust.com',\n );\n }\n // must specify the OneTrust auth\n if (!oneTrustAuth) {\n throw new Error(\n 'Missing required parameter \"oneTrustAuth\". e.g. --oneTrustAuth=$ONE_TRUST_AUTH_TOKEN',\n );\n }\n } else {\n // if reading the assessments from a file, must specify a file to read from\n if (!file) {\n throw new Error(\n 'Must specify a \"file\" parameter to read the OneTrust assessments from. e.g. --source=./oneTrustAssessments.json',\n );\n }\n\n // Cannot try reading from file and save assessments to a file simultaneously\n if (dryRun) {\n throw new Error(\n 'Cannot read and write to a file simultaneously.' +\n ` Emit the \"source\" parameter or set it to ${OneTrustPullSource.OneTrust} if \"dryRun\" is enabled.`,\n );\n }\n }\n\n doneInputValidation(this.process);\n\n // instantiate a client to talk to OneTrust\n const oneTrust =\n hostname && oneTrustAuth\n ? createOneTrustGotInstance({\n hostname,\n auth: oneTrustAuth,\n })\n : undefined;\n\n // instantiate a client to talk to Transcend\n const transcend =\n transcendUrl && transcendAuth\n ? buildTranscendGraphQLClient(transcendUrl, transcendAuth)\n : undefined;\n\n try {\n if (resource === OneTrustPullResource.Assessments) {\n if (source === OneTrustPullSource.OneTrust && oneTrust) {\n await syncOneTrustAssessmentsFromOneTrust({\n oneTrust,\n file,\n dryRun,\n ...(transcend && { transcend }),\n });\n } else if (source === OneTrustPullSource.File && file && transcend) {\n await syncOneTrustAssessmentsFromFile({ file, transcend });\n }\n }\n } catch (err) {\n throw new Error(\n `An error occurred syncing the resource ${resource} from OneTrust: ${\n debug ? err.stack : err.message\n }`,\n );\n }\n\n // Indicate success\n this.logger.info(\n colors.green(\n `Successfully synced OneTrust ${resource} to ${dryRun ? `disk at \"${file}\"` : 'Transcend'}!`,\n ),\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"impl-BWPPVXG3.mjs","names":[],"sources":["../src/lib/oneTrust/helpers/oneTrustAssessmentToJson.ts","../src/lib/oneTrust/helpers/syncOneTrustAssessmentToDisk.ts","../src/lib/oneTrust/endpoints/getListOfOneTrustAssessments.ts","../src/lib/oneTrust/endpoints/getOneTrustAssessment.ts","../src/lib/oneTrust/endpoints/getOneTrustRisk.ts","../src/lib/oneTrust/endpoints/getOneTrustUser.ts","../src/lib/oneTrust/helpers/enrichOneTrustAssessment.ts","../src/lib/oneTrust/helpers/syncOneTrustAssessmentToTranscend.ts","../src/lib/oneTrust/helpers/syncOneTrustAssessmentsFromOneTrust.ts","../src/lib/oneTrust/helpers/syncOneTrustAssessmentsFromFile.ts","../src/lib/oneTrust/createOneTrustGotInstance.ts","../src/commands/migration/sync-ot/impl.ts"],"sourcesContent":["import { OneTrustEnrichedAssessment } from '@transcend-io/privacy-types';\n\n/**\n * Converts the assessment into a json entry.\n *\n * @param param - information about the assessment and amount of entries\n * @returns a stringified json entry ready to be appended to a file\n */\nexport const oneTrustAssessmentToJson = ({\n assessment,\n index,\n total,\n wrap = true,\n}: {\n /** The assessment to convert */\n assessment: OneTrustEnrichedAssessment;\n /** The position of the assessment in the final Json object */\n index: number;\n /** The total amount of the assessments in the final Json object */\n total?: number;\n /** Whether to wrap every entry in brackets */\n wrap?: boolean;\n}): string => {\n let jsonEntry = '';\n // start with an opening bracket\n if (index === 0 || wrap) {\n jsonEntry = '[\\n';\n }\n\n const stringifiedAssessment = JSON.stringify(assessment);\n\n // Add comma for all items except the last one\n const comma = total && index < total - 1 && !wrap ? ',' : '';\n\n // write to file\n jsonEntry = `${jsonEntry + stringifiedAssessment + comma}\\n`;\n\n // end with closing bracket\n if ((total && index === total - 1) || wrap) {\n jsonEntry += '\\n]';\n }\n\n return jsonEntry;\n};\n","import fs from 'node:fs';\n\nimport { OneTrustEnrichedAssessment } from '@transcend-io/privacy-types';\nimport colors from 'colors';\n\nimport { logger } from '../../../logger.js';\nimport { oneTrustAssessmentToJson } from './oneTrustAssessmentToJson.js';\n\n/**\n * Write the assessment to disk at the specified file path.\n *\n *\n * @param param - information about the assessment to write\n */\nexport const syncOneTrustAssessmentToDisk = ({\n file,\n assessment,\n index,\n total,\n}: {\n /** The file path to write the assessment to */\n file: string;\n /** The basic assessment */\n assessment: OneTrustEnrichedAssessment;\n /** The index of the assessment being written to the file */\n index: number;\n /** The total amount of assessments that we will write */\n total: number;\n}): void => {\n logger.info(\n colors.magenta(`Writing enriched assessment ${index + 1} of ${total} to file \"${file}\"...`),\n );\n\n if (index === 0) {\n fs.writeFileSync(\n file,\n oneTrustAssessmentToJson({\n assessment,\n index,\n total,\n wrap: false,\n }),\n );\n } else {\n fs.appendFileSync(\n file,\n oneTrustAssessmentToJson({\n assessment,\n index,\n total,\n wrap: false,\n }),\n );\n }\n};\n","import {\n OneTrustAssessment,\n OneTrustGetListOfAssessmentsResponse,\n} from '@transcend-io/privacy-types';\nimport { decodeCodec } from '@transcend-io/type-utils';\nimport { Got } from 'got';\n\nimport { logger } from '../../../logger.js';\n\n/**\n * Fetch a list of all assessments from the OneTrust client.\n * ref: https://developer.onetrust.com/onetrust/reference/getallassessmentbasicdetailsusingget\n *\n * @param param - the information about the OneTrust client\n * @returns a list of OneTrustAssessment\n */\nexport const getListOfOneTrustAssessments = async ({\n oneTrust,\n}: {\n /** The OneTrust client instance */\n oneTrust: Got;\n}): Promise<OneTrustAssessment[]> => {\n let currentPage = 0;\n let totalPages = 1;\n let totalElements = 0;\n\n const allAssessments: OneTrustAssessment[] = [];\n\n while (currentPage < totalPages) {\n const { body } = await oneTrust.get(\n `api/assessment/v2/assessments?page=${currentPage}&size=2000`,\n );\n\n const { page, content } = decodeCodec(OneTrustGetListOfAssessmentsResponse, body);\n allAssessments.push(...(content ?? []));\n if (currentPage === 0) {\n totalPages = page?.totalPages ?? 0;\n totalElements = page?.totalElements ?? 0;\n }\n currentPage += 1;\n\n // log progress\n logger.info(`Fetched ${allAssessments.length} of ${totalElements} assessments.`);\n }\n\n return allAssessments;\n};\n","import { OneTrustGetAssessmentResponse } from '@transcend-io/privacy-types';\nimport { decodeCodec } from '@transcend-io/type-utils';\nimport { Got } from 'got';\n\n/**\n * Retrieve details about a particular assessment.\n * ref: https://developer.onetrust.com/onetrust/reference/exportassessmentusingget\n *\n * @param param - the information about the OneTrust client and assessment to retrieve\n * @returns details about the assessment\n */\nexport const getOneTrustAssessment = async ({\n oneTrust,\n assessmentId,\n}: {\n /** The OneTrust client instance */\n oneTrust: Got;\n /** The ID of the assessment to retrieve */\n assessmentId: string;\n}): Promise<OneTrustGetAssessmentResponse> => {\n const { body } = await oneTrust.get(\n `api/assessment/v2/assessments/${assessmentId}/export?ExcludeSkippedQuestions=false`,\n );\n\n return decodeCodec(OneTrustGetAssessmentResponse, body);\n};\n","import { OneTrustGetRiskResponse } from '@transcend-io/privacy-types';\nimport { decodeCodec } from '@transcend-io/type-utils';\nimport { Got } from 'got';\n\n/**\n * Retrieve details about a particular risk.\n * ref: https://developer.onetrust.com/onetrust/reference/getriskusingget\n *\n * @param param - the information about the OneTrust client and risk to retrieve\n * @returns the OneTrust risk\n */\nexport const getOneTrustRisk = async ({\n oneTrust,\n riskId,\n}: {\n /** The OneTrust client instance */\n oneTrust: Got;\n /** The ID of the OneTrust risk to retrieve */\n riskId: string;\n}): Promise<OneTrustGetRiskResponse> => {\n const { body } = await oneTrust.get(`api/risk/v2/risks/${riskId}`);\n\n return decodeCodec(OneTrustGetRiskResponse, body);\n};\n","import { OneTrustGetUserResponse } from '@transcend-io/privacy-types';\nimport { decodeCodec } from '@transcend-io/type-utils';\nimport { Got } from 'got';\n\n/**\n * Retrieve details about a particular user.\n * ref: https://developer.onetrust.com/onetrust/reference/getriskusingget\n *\n * @param param - the information about the OneTrust client and risk to retrieve\n * @returns the OneTrust risk\n */\nexport const getOneTrustUser = async ({\n oneTrust,\n userId,\n}: {\n /** The OneTrust client instance */\n oneTrust: Got;\n /** The ID of the OneTrust user to retrieve */\n userId: string;\n}): Promise<OneTrustGetUserResponse> => {\n const { body } = await oneTrust.get(`api/scim/v2/Users/${userId}`);\n\n return decodeCodec(OneTrustGetUserResponse, body);\n};\n","import {\n OneTrustAssessment,\n OneTrustEnrichedAssessment,\n OneTrustGetAssessmentResponse,\n OneTrustGetRiskResponse,\n OneTrustGetUserResponse,\n} from '@transcend-io/privacy-types';\nimport { keyBy } from 'lodash-es';\n\n/**\n * Merge the assessment, assessmentDetails, and riskDetails into one object.\n *\n * @param param - the assessment and risk information\n * @returns the assessment enriched with details and risk information\n */\nexport const enrichOneTrustAssessment = ({\n assessment,\n assessmentDetails,\n riskDetails,\n creatorDetails,\n approversDetails,\n respondentsDetails,\n}: {\n /** The OneTrust risk details */\n riskDetails: OneTrustGetRiskResponse[];\n /** The OneTrust assessment as returned from Get List of Assessments endpoint */\n assessment: OneTrustAssessment;\n /** The OneTrust assessment details */\n assessmentDetails: OneTrustGetAssessmentResponse;\n /** The OneTrust assessment creator details */\n creatorDetails: OneTrustGetUserResponse;\n /** The OneTrust assessment approvers details */\n approversDetails: OneTrustGetUserResponse[];\n /** The OneTrust assessment internal respondents details */\n respondentsDetails: OneTrustGetUserResponse[];\n}): OneTrustEnrichedAssessment => {\n const riskDetailsById = keyBy(riskDetails, 'id');\n const { sections, createdBy, ...restAssessmentDetails } = assessmentDetails;\n const sectionsWithEnrichedRisk = sections.map((section) => {\n const { questions, ...restSection } = section;\n const enrichedQuestions = questions.map((question) => {\n const { risks, ...restQuestion } = question;\n const enrichedRisks = (risks ?? []).map((risk) => {\n const details = riskDetailsById[risk.riskId];\n return {\n ...risk,\n ...details,\n level: risk.level,\n impactLevel: risk.impactLevel ?? 0,\n };\n });\n return {\n ...restQuestion,\n risks: enrichedRisks,\n };\n });\n return {\n ...restSection,\n questions: enrichedQuestions,\n };\n });\n\n // grab creator details\n const enrichedCreatedBy = {\n ...createdBy,\n active: creatorDetails?.active ?? false,\n userType: creatorDetails?.userType ?? 'Internal',\n emails: creatorDetails?.emails ?? [],\n title: creatorDetails?.title ?? null,\n givenName: creatorDetails?.name.givenName ?? null,\n familyName: creatorDetails?.name.familyName ?? null,\n };\n\n // grab approvers details\n const approverDetailsById = keyBy(approversDetails, 'id');\n const enrichedApprovers = assessmentDetails.approvers.flatMap((originalApprover) =>\n approverDetailsById[originalApprover.id]\n ? [\n {\n ...originalApprover,\n approver: {\n ...originalApprover.approver,\n active: approverDetailsById[originalApprover.id].active,\n userType: approverDetailsById[originalApprover.id].userType,\n emails: approverDetailsById[originalApprover.id].emails,\n title: approverDetailsById[originalApprover.id].title,\n givenName: approverDetailsById[originalApprover.id].name.givenName ?? null,\n familyName: approverDetailsById[originalApprover.id].name.familyName ?? null,\n },\n },\n ]\n : [],\n );\n\n // grab respondents details\n const respondentsDetailsById = keyBy(respondentsDetails, 'id');\n const enrichedRespondents = assessmentDetails.respondents\n .filter((r) => !r.name.includes('@')) // search only internal respondents\n .flatMap((respondent) =>\n respondentsDetailsById[respondent.id]\n ? [\n {\n ...respondent,\n active: respondentsDetailsById[respondent.id].active,\n userType: respondentsDetailsById[respondent.id].userType,\n emails: respondentsDetailsById[respondent.id].emails,\n title: respondentsDetailsById[respondent.id].title,\n givenName: respondentsDetailsById[respondent.id].name.givenName ?? null,\n familyName: respondentsDetailsById[respondent.id].name.familyName ?? null,\n },\n ]\n : [],\n );\n\n // combine everything into a single enriched assessment\n return {\n ...assessment,\n ...restAssessmentDetails,\n approvers: enrichedApprovers,\n respondents: enrichedRespondents,\n createdBy: enrichedCreatedBy,\n sections: sectionsWithEnrichedRisk,\n };\n};\n","import { OneTrustEnrichedAssessment } from '@transcend-io/privacy-types';\nimport { makeGraphQLRequest, IMPORT_ONE_TRUST_ASSESSMENT_FORMS } from '@transcend-io/sdk';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\n\nimport { ImportOnetrustAssessmentsInput } from '../../../codecs.js';\nimport { logger } from '../../../logger.js';\nimport { oneTrustAssessmentToJson } from './oneTrustAssessmentToJson.js';\n\nexport interface AssessmentForm {\n /** ID of Assessment Form */\n id: string;\n /** Title of Assessment Form */\n name: string;\n}\n\n/**\n * Write the assessment to a Transcend instance.\n *\n *\n * @param param - information about the assessment and Transcend instance to write to\n */\nexport const syncOneTrustAssessmentToTranscend = async ({\n transcend,\n assessment,\n total,\n index,\n}: {\n /** the Transcend client instance */\n transcend: GraphQLClient;\n /** the assessment to sync to Transcend */\n assessment: OneTrustEnrichedAssessment;\n /** The index of the assessment being written to the file */\n index: number;\n /** The total amount of assessments that we will write */\n total?: number;\n}): Promise<void> => {\n logger.info(\n colors.magenta(\n `Writing enriched assessment ${index + 1} ${total ? `of ${total} ` : ' '}to Transcend...`,\n ),\n );\n\n // convert the OneTrust assessment object into a json record\n const json = oneTrustAssessmentToJson({\n assessment,\n index,\n total,\n });\n\n // transform the json record into a valid input to the mutation\n const input: ImportOnetrustAssessmentsInput = {\n json,\n };\n\n try {\n await makeGraphQLRequest<{\n /** the importOneTrustAssessmentForms mutation */\n importOneTrustAssessmentForms: {\n /** Created Assessment Forms */\n assessmentForms: AssessmentForm[];\n };\n }>(transcend, IMPORT_ONE_TRUST_ASSESSMENT_FORMS, {\n variables: { input },\n logger,\n });\n } catch (error) {\n logger.error(\n colors.red(\n `Failed to sync assessment ${index + 1} ${total ? `of ${total} ` : ' '}to Transcend.\\n` +\n `\\tAssessment Title: ${assessment.name}. Template Title: ${assessment.template.name}\\n`,\n ),\n error,\n );\n }\n};\n","import {\n OneTrustAssessmentQuestion,\n OneTrustAssessmentSection,\n OneTrustEnrichedAssessment,\n OneTrustGetRiskResponse,\n OneTrustGetUserResponse,\n} from '@transcend-io/privacy-types';\nimport { mapSeries, map } from '@transcend-io/utils';\nimport colors from 'colors';\nimport type { Got } from 'got';\nimport { GraphQLClient } from 'graphql-request';\nimport { uniq } from 'lodash-es';\n\nimport { logger } from '../../../logger.js';\nimport {\n getListOfOneTrustAssessments,\n getOneTrustAssessment,\n getOneTrustRisk,\n getOneTrustUser,\n} from '../endpoints/index.js';\nimport { enrichOneTrustAssessment } from './enrichOneTrustAssessment.js';\nimport { syncOneTrustAssessmentToDisk } from './syncOneTrustAssessmentToDisk.js';\nimport { syncOneTrustAssessmentToTranscend } from './syncOneTrustAssessmentToTranscend.js';\n\nexport interface AssessmentForm {\n /** ID of Assessment Form */\n id: string;\n /** Title of Assessment Form */\n name: string;\n}\n\n/**\n * Reads all the assessments from a OneTrust instance and syncs them to Transcend or to Disk.\n *\n * @param param - the information about the assessment, its OneTrust source, and destination (disk or Transcend)\n */\nexport const syncOneTrustAssessmentsFromOneTrust = async ({\n oneTrust,\n file,\n dryRun,\n transcend,\n}: {\n /** the OneTrust client instance */\n oneTrust: Got;\n /** the Transcend client instance */\n transcend?: GraphQLClient;\n /** Whether to write to file instead of syncing to Transcend */\n dryRun: boolean;\n /** the path to the file in case dryRun is true */\n file?: string;\n}): Promise<void> => {\n // fetch the list of all assessments in the OneTrust organization\n logger.info('Getting list of all assessments from OneTrust...');\n const assessments = await getListOfOneTrustAssessments({ oneTrust });\n\n // a cache of OneTrust users so we avoid requesting already fetched users\n const oneTrustCachedUsers: Record<string, OneTrustGetUserResponse> = {};\n\n // split all assessments in batches, so we can process some of steps in parallel\n const BATCH_SIZE = 5;\n const assessmentBatches = Array.from(\n {\n length: Math.ceil(assessments.length / BATCH_SIZE),\n },\n (_, i) => assessments.slice(i * BATCH_SIZE, (i + 1) * BATCH_SIZE),\n );\n\n // process each batch and sync the batch right away so it's garbage collected and we don't run out of memory\n await mapSeries(assessmentBatches, async (assessmentBatch, batch) => {\n const batchEnrichedAssessments: OneTrustEnrichedAssessment[] = [];\n\n // fetch assessment details from OneTrust in parallel\n await map(\n assessmentBatch,\n async (assessment, index) => {\n const assessmentNumber = BATCH_SIZE * batch + index + 1;\n logger.info(\n `[assessment ${assessmentNumber} of ${assessments.length}]: fetching details...`,\n );\n const { templateName, assessmentId } = assessment;\n const assessmentDetails = await getOneTrustAssessment({\n oneTrust,\n assessmentId,\n });\n // fetch assessment's creator information\n const creatorId = assessmentDetails.createdBy.id;\n let creator = oneTrustCachedUsers[creatorId];\n if (!creator) {\n logger.info(\n `[assessment ${assessmentNumber} of ${assessments.length}]: fetching creator...`,\n );\n try {\n creator = await getOneTrustUser({\n oneTrust,\n userId: creatorId,\n });\n oneTrustCachedUsers[creatorId] = creator;\n } catch (error) {\n logger.warn(\n colors.yellow(\n `[assessment ${assessmentNumber} of ${assessments.length}]: failed to fetch form creator.` +\n `\\tcreatorId: ${creatorId}. Assessment Title: ${assessment.name}. Template Title: ${templateName}`,\n ),\n error,\n );\n }\n }\n\n // fetch assessment approvers information\n const { approvers } = assessmentDetails;\n let approversDetails: OneTrustGetUserResponse[][] = [];\n if (approvers.length > 0) {\n logger.info(\n `[assessment ${assessmentNumber} of ${assessments.length}]: fetching approvers...`,\n );\n approversDetails = await map(\n approvers.map(({ id }) => id),\n async (userId) => {\n try {\n let approver = oneTrustCachedUsers[userId];\n if (!approver) {\n approver = await getOneTrustUser({ oneTrust, userId });\n oneTrustCachedUsers[userId] = approver;\n }\n return [approver];\n } catch (error) {\n logger.warn(\n colors.yellow(\n `[assessment ${assessmentNumber} of ${assessments.length}]: failed to fetch a form approver.` +\n `\\tapproverId: ${userId}. Assessment Title: ${assessment.name}. Template Title: ${templateName}`,\n ),\n error,\n );\n return [];\n }\n },\n { concurrency: 5 },\n );\n }\n\n // fetch assessment internal respondents information\n const { respondents } = assessmentDetails;\n // if a user is an internal respondents, their 'name' field can't be an email.\n const internalRespondents = respondents.filter((r) => !r.name.includes('@'));\n let respondentsDetails: OneTrustGetUserResponse[][] = [];\n if (internalRespondents.length > 0) {\n logger.info(\n `[assessment ${assessmentNumber} of ${assessments.length}]: fetching respondents...`,\n );\n respondentsDetails = await map(\n internalRespondents.map(({ id }) => id),\n async (userId) => {\n try {\n let respondent = oneTrustCachedUsers[userId];\n if (!respondent) {\n respondent = await getOneTrustUser({ oneTrust, userId });\n oneTrustCachedUsers[userId] = respondent;\n }\n return [respondent];\n } catch (error) {\n logger.warn(\n colors.yellow(\n `[assessment ${assessmentNumber} of ${assessments.length}]: failed to fetch a respondent.` +\n `\\trespondentId: ${userId}. Assessment Title: ${assessment.name}. Template Title: ${templateName}`,\n ),\n error,\n );\n return [];\n }\n },\n { concurrency: 5 },\n );\n }\n\n // fetch assessment risk information\n let riskDetails: OneTrustGetRiskResponse[] = [];\n const riskIds = uniq(\n assessmentDetails.sections.flatMap((s: OneTrustAssessmentSection) =>\n s.questions.flatMap((q: OneTrustAssessmentQuestion) =>\n (q.risks ?? []).flatMap((r) => r.riskId),\n ),\n ),\n );\n if (riskIds.length > 0) {\n logger.info(\n `[assessment ${assessmentNumber} of ${assessments.length}]: fetching risks...`,\n );\n riskDetails = await map(\n riskIds,\n (riskId) => getOneTrustRisk({ oneTrust, riskId: riskId as string }),\n {\n concurrency: 5,\n },\n );\n }\n\n // enrich the assessments with user and risk details\n const enrichedAssessment = enrichOneTrustAssessment({\n assessment,\n assessmentDetails,\n riskDetails,\n creatorDetails: creator,\n approversDetails: approversDetails.flat(),\n respondentsDetails: respondentsDetails.flat(),\n });\n\n batchEnrichedAssessments.push(enrichedAssessment);\n },\n { concurrency: BATCH_SIZE },\n );\n\n // sync assessments in series to avoid concurrency bugs\n await mapSeries(batchEnrichedAssessments, async (enrichedAssessment, index) => {\n // the assessment's global index takes its batch into consideration\n const globalIndex = batch * BATCH_SIZE + index;\n\n if (dryRun && file) {\n // sync to file\n syncOneTrustAssessmentToDisk({\n assessment: enrichedAssessment,\n index: globalIndex,\n total: assessments.length,\n file,\n });\n } else if (transcend) {\n // sync to transcend\n await syncOneTrustAssessmentToTranscend({\n assessment: enrichedAssessment,\n transcend,\n total: assessments.length,\n index: globalIndex,\n });\n }\n });\n });\n};\n","import { createReadStream } from 'node:fs';\n\nimport { OneTrustEnrichedAssessment } from '@transcend-io/privacy-types';\nimport { decodeCodec } from '@transcend-io/type-utils';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport JSONStream from 'JSONStream';\n\nimport { logger } from '../../../logger.js';\nimport { syncOneTrustAssessmentToTranscend } from './syncOneTrustAssessmentToTranscend.js';\n\n/**\n * Reads assessments from a file and syncs them to Transcend.\n *\n * @param param - the information about the source file and Transcend instance to write them to.\n */\nexport const syncOneTrustAssessmentsFromFile = ({\n transcend,\n file,\n}: {\n /** the Transcend client instance */\n transcend: GraphQLClient;\n /** The name of the file from which to read the OneTrust assessments */\n file: string;\n}): Promise<void> => {\n logger.info(`Getting list of all assessments from file ${file}...`);\n\n return new Promise((resolve, reject) => {\n // Create a readable stream from the file\n const fileStream = createReadStream(file, {\n encoding: 'utf-8',\n highWaterMark: 64 * 1024, // 64KB chunks\n });\n\n // Create a JSONStream parser to parse the array of OneTrust assessments from the file\n const parser = JSONStream.parse('*'); // '*' matches each element in the root array\n\n let index = 0;\n\n // Pipe the file stream into the JSON parser\n fileStream.pipe(parser);\n\n // Handle each parsed assessment object\n parser.on('data', async (assessment) => {\n try {\n // Pause the stream while processing to avoid overwhelming memory\n parser.pause();\n\n // Decode and validate the assessment\n const parsedAssessment = decodeCodec(OneTrustEnrichedAssessment, assessment);\n\n // Sync the assessment to transcend\n await syncOneTrustAssessmentToTranscend({\n assessment: parsedAssessment,\n transcend,\n index,\n });\n\n index += 1;\n\n // Resume the stream after processing\n parser.resume();\n } catch (e) {\n // if failed to parse a line, report error and continue\n logger.error(\n colors.red(`Failed to parse the assessment ${index} from file '${file}': ${e.message}.`),\n );\n }\n });\n\n // Handle completion\n parser.on('end', () => {\n logger.info(`Finished processing ${index} assessments from file ${file}`);\n resolve();\n });\n\n // Handle stream or parsing errors\n parser.on('error', (error) => {\n logger.error(colors.red(`Error parsing file '${file}': ${error.message}`));\n reject(error);\n });\n\n fileStream.on('error', (error) => {\n logger.error(colors.red(`Error reading file '${file}': ${error.message}`));\n reject(error);\n });\n });\n};\n","import got, { Got } from 'got';\n\n/**\n * Instantiate an instance of got that is capable of making requests to OneTrust\n *\n * @param param - information about the OneTrust URL\n * @returns The instance of got that is capable of making requests to the customer ingress\n */\nexport const createOneTrustGotInstance = ({\n hostname,\n auth,\n}: {\n /** Hostname of the OneTrust API */\n hostname: string;\n /** The OAuth access token */\n auth: string;\n}): Got =>\n got.extend({\n prefixUrl: `https://${hostname}`,\n headers: {\n accept: 'application/json',\n 'content-type': 'application/json',\n authorization: `Bearer ${auth}`,\n },\n });\n","import { buildTranscendGraphQLClient } from '@transcend-io/sdk';\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { OneTrustFileFormat, OneTrustPullResource, OneTrustPullSource } from '../../../enums.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport {\n syncOneTrustAssessmentsFromFile,\n syncOneTrustAssessmentsFromOneTrust,\n} from '../../../lib/oneTrust/helpers/index.js';\nimport { createOneTrustGotInstance } from '../../../lib/oneTrust/index.js';\n\n// Command flag interface\nexport interface SyncOtCommandFlags {\n hostname?: string;\n oneTrustAuth?: string;\n source: OneTrustPullSource;\n transcendAuth?: string;\n transcendUrl: string;\n file?: string;\n resource: OneTrustPullResource;\n dryRun: boolean;\n debug: boolean;\n}\n\n// Command implementation\nexport async function syncOt(\n this: LocalContext,\n {\n hostname,\n oneTrustAuth,\n source,\n transcendAuth,\n transcendUrl,\n resource,\n file,\n dryRun,\n debug,\n }: SyncOtCommandFlags,\n): Promise<void> {\n // Must be able to authenticate to transcend to sync resources to it\n if (!dryRun && !transcendAuth) {\n throw new Error(\n // eslint-disable-next-line no-template-curly-in-string\n 'Must specify a \"transcendAuth\" parameter to sync resources to Transcend. e.g. --transcendAuth=${TRANSCEND_API_KEY}',\n );\n }\n\n // If trying to sync to disk, must specify a file path\n if (dryRun && !file) {\n throw new Error(\n 'Must set a \"file\" parameter when \"dryRun\" is \"true\". e.g. --file=./oneTrustAssessments.json',\n );\n }\n\n if (file) {\n const splitFile = file.split('.');\n if (splitFile.length < 2) {\n throw new Error(\n 'The \"file\" parameter has an invalid format. Expected a path with extensions. e.g. --file=./pathToFile.json.',\n );\n }\n if (splitFile.at(-1) !== OneTrustFileFormat.Json) {\n throw new Error(\n `Expected the format of the \"file\" parameters '${file}' to be '${\n OneTrustFileFormat.Json\n }', but got '${splitFile.at(-1)}'.`,\n );\n }\n }\n\n // if reading assessments from a OneTrust\n if (source === OneTrustPullSource.OneTrust) {\n // must specify the OneTrust hostname\n if (!hostname) {\n throw new Error(\n 'Missing required parameter \"hostname\". e.g. --hostname=customer.my.onetrust.com',\n );\n }\n // must specify the OneTrust auth\n if (!oneTrustAuth) {\n throw new Error(\n 'Missing required parameter \"oneTrustAuth\". e.g. --oneTrustAuth=$ONE_TRUST_AUTH_TOKEN',\n );\n }\n } else {\n // if reading the assessments from a file, must specify a file to read from\n if (!file) {\n throw new Error(\n 'Must specify a \"file\" parameter to read the OneTrust assessments from. e.g. --source=./oneTrustAssessments.json',\n );\n }\n\n // Cannot try reading from file and save assessments to a file simultaneously\n if (dryRun) {\n throw new Error(\n 'Cannot read and write to a file simultaneously.' +\n ` Emit the \"source\" parameter or set it to ${OneTrustPullSource.OneTrust} if \"dryRun\" is enabled.`,\n );\n }\n }\n\n doneInputValidation(this.process);\n\n // instantiate a client to talk to OneTrust\n const oneTrust =\n hostname && oneTrustAuth\n ? createOneTrustGotInstance({\n hostname,\n auth: oneTrustAuth,\n })\n : undefined;\n\n // instantiate a client to talk to Transcend\n const transcend =\n transcendUrl && transcendAuth\n ? buildTranscendGraphQLClient(transcendUrl, transcendAuth)\n : undefined;\n\n try {\n if (resource === OneTrustPullResource.Assessments) {\n if (source === OneTrustPullSource.OneTrust && oneTrust) {\n await syncOneTrustAssessmentsFromOneTrust({\n oneTrust,\n file,\n dryRun,\n ...(transcend && { transcend }),\n });\n } else if (source === OneTrustPullSource.File && file && transcend) {\n await syncOneTrustAssessmentsFromFile({ file, transcend });\n }\n }\n } catch (err) {\n throw new Error(\n `An error occurred syncing the resource ${resource} from OneTrust: ${\n debug ? err.stack : err.message\n }`,\n );\n }\n\n // Indicate success\n this.logger.info(\n colors.green(\n `Successfully synced OneTrust ${resource} to ${dryRun ? `disk at \"${file}\"` : 'Transcend'}!`,\n ),\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{t as e}from"./readCsv-DLg8pwjd.mjs";import{t}from"./markRequestDataSiloIdsCompleted-Br5gIS3S.mjs";import{t as n}from"./done-input-validation-BUz-aVC5.mjs";import r from"colors";import*as i from"io-ts";const a=i.type({"Request Id":i.string});async function o({auth:i,dataSiloId:o,file:s,transcendUrl:c}){n(this.process),this.logger.info(r.magenta(`Reading "${s}" from disk`)),await t({requestIds:e(this.fs.readFileSync(s,`utf8`),a).map(e=>e[`Request Id`]),transcendUrl:c,auth:i,dataSiloId:o})}export{o as markRequestDataSilosCompleted};
2
- //# sourceMappingURL=impl-Cw0L2xEU.mjs.map
1
+ import{t as e}from"./readCsv-DNcJ_UfU.mjs";import{t}from"./markRequestDataSiloIdsCompleted-BYNMCkhy.mjs";import{t as n}from"./done-input-validation-LiTaCEzF.mjs";import r from"colors";import*as i from"io-ts";const a=i.type({"Request Id":i.string});async function o({auth:i,dataSiloId:o,file:s,transcendUrl:c}){n(this.process),this.logger.info(r.magenta(`Reading "${s}" from disk`)),await t({requestIds:e(this.fs.readFileSync(s,`utf8`),a).map(e=>e[`Request Id`]),transcendUrl:c,auth:i,dataSiloId:o})}export{o as markRequestDataSilosCompleted};
2
+ //# sourceMappingURL=impl-BdTxFv63.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"impl-Cw0L2xEU.mjs","names":[],"sources":["../src/commands/request/system/mark-request-data-silos-completed/impl.ts"],"sourcesContent":["import colors from 'colors';\nimport * as t from 'io-ts';\n\nimport type { LocalContext } from '../../../../context.js';\nimport { doneInputValidation } from '../../../../lib/cli/done-input-validation.js';\nimport { markRequestDataSiloIdsCompleted } from '../../../../lib/cron/index.js';\nimport { parseCsv } from '../../../../lib/requests/readCsv.js';\n\nconst RequestIdRow = t.type({\n 'Request Id': t.string,\n});\n\nexport interface MarkRequestDataSilosCompletedCommandFlags {\n auth: string;\n dataSiloId: string;\n file: string;\n transcendUrl: string;\n}\n\nexport async function markRequestDataSilosCompleted(\n this: LocalContext,\n { auth, dataSiloId, file, transcendUrl }: MarkRequestDataSilosCompletedCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n this.logger.info(colors.magenta(`Reading \"${file}\" from disk`));\n const activeResults = parseCsv(this.fs.readFileSync(file, 'utf8'), RequestIdRow);\n\n await markRequestDataSiloIdsCompleted({\n requestIds: activeResults.map((request) => request['Request Id']),\n transcendUrl,\n auth,\n dataSiloId,\n });\n}\n"],"mappings":"gNAQA,MAAM,EAAe,EAAE,KAAK,CAC1B,aAAc,EAAE,OACjB,CAAC,CASF,eAAsB,EAEpB,CAAE,OAAM,aAAY,OAAM,gBACX,CACf,EAAoB,KAAK,QAAQ,CAEjC,KAAK,OAAO,KAAK,EAAO,QAAQ,YAAY,EAAK,aAAa,CAAC,CAG/D,MAAM,EAAgC,CACpC,WAHoB,EAAS,KAAK,GAAG,aAAa,EAAM,OAAO,CAAE,EAGxC,CAAC,IAAK,GAAY,EAAQ,cAAc,CACjE,eACA,OACA,aACD,CAAC"}
1
+ {"version":3,"file":"impl-BdTxFv63.mjs","names":[],"sources":["../src/commands/request/system/mark-request-data-silos-completed/impl.ts"],"sourcesContent":["import colors from 'colors';\nimport * as t from 'io-ts';\n\nimport type { LocalContext } from '../../../../context.js';\nimport { doneInputValidation } from '../../../../lib/cli/done-input-validation.js';\nimport { markRequestDataSiloIdsCompleted } from '../../../../lib/cron/index.js';\nimport { parseCsv } from '../../../../lib/requests/readCsv.js';\n\nconst RequestIdRow = t.type({\n 'Request Id': t.string,\n});\n\nexport interface MarkRequestDataSilosCompletedCommandFlags {\n auth: string;\n dataSiloId: string;\n file: string;\n transcendUrl: string;\n}\n\nexport async function markRequestDataSilosCompleted(\n this: LocalContext,\n { auth, dataSiloId, file, transcendUrl }: MarkRequestDataSilosCompletedCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n this.logger.info(colors.magenta(`Reading \"${file}\" from disk`));\n const activeResults = parseCsv(this.fs.readFileSync(file, 'utf8'), RequestIdRow);\n\n await markRequestDataSiloIdsCompleted({\n requestIds: activeResults.map((request) => request['Request Id']),\n transcendUrl,\n auth,\n dataSiloId,\n });\n}\n"],"mappings":"gNAQA,MAAM,EAAe,EAAE,KAAK,CAC1B,aAAc,EAAE,OACjB,CAAC,CASF,eAAsB,EAEpB,CAAE,OAAM,aAAY,OAAM,gBACX,CACf,EAAoB,KAAK,QAAQ,CAEjC,KAAK,OAAO,KAAK,EAAO,QAAQ,YAAY,EAAK,aAAa,CAAC,CAG/D,MAAM,EAAgC,CACpC,WAHoB,EAAS,KAAK,GAAG,aAAa,EAAM,OAAO,CAAE,EAGxC,CAAC,IAAK,GAAY,EAAQ,cAAc,CACjE,eACA,OACA,aACD,CAAC"}
@@ -0,0 +1,3 @@
1
+ import{i as e}from"./paths-J5KScOaQ.mjs";import{o as t,s as n}from"./project-discovery-CWRjlFnC.mjs";import{a as r}from"./readTranscendYaml-BfqQbPiT.mjs";import{t as i}from"./parseVariablesFromString-6TYW65LF.mjs";import{t as a}from"./done-input-validation-LiTaCEzF.mjs";import{t as o}from"./missing-manifest-D8y1VL4p.mjs";import{a as s,i as c,l,t as u}from"./project-discovery-BkHpTXDx.mjs";import{n as d,r as f,t as p}from"./prompts-BhXfYD6g.mjs";import{t as m}from"./run-captured-process-BjaSDWXG.mjs";import{r as h,t as g}from"./deno-runtime-CB2HBach.mjs";import{t as _}from"./module-graph-CAT8_JCG.mjs";import{t as v}from"./project-plan-apply-Bg_1eMX9.mjs";import{dirname as y,extname as b,join as x,relative as S,resolve as C,sep as w}from"node:path";import T from"colors";import{createTwoFilesPatch as E}from"diff";import{DSR_DATAPOINT_CUSTOM_FUNCTION_PAYLOAD_SCHEMA as D,DSR_REQUEST_ENRICHER_CUSTOM_FUNCTION_PAYLOAD_SCHEMA as O,GENERAL_CUSTOM_FUNCTION_PAYLOAD_SCHEMA as k}from"@transcend-io/custom-function-types";import A from"ajv";import{parse as j}from"jsonc-parser";function M(e,t){e.push({severity:`error`,...t})}function N(e,t){return S(e,t).split(w).join(`/`)||`.`}function P(e){let t=t=>e.type===`DSR`?t===`REQUEST_ENRICHER`?`dsr-enricher`:`dsr-datapoint`:`general`;return e[`test-payload`]?[{entry:e,path:e[`test-payload`],type:t(e[`test-payload-type`])}]:(e[`test-payloads`]??[]).map(n=>({entry:e,path:n.payload,type:t(n[`payload-type`])}))}function F(e,t){let n=P(e).map(({type:e})=>e),r=e.type===`DSR`&&n.length===0;return{entry:e,path:C(t,e.code),needsDefault:e.type!==`DSR`||n.includes(`dsr-datapoint`),needsEnricher:n.includes(`dsr-enricher`),needsAnyDsrExport:r}}function I(){let e=new A({allErrors:!0,strict:!1});return{general:e.compile(k),"dsr-datapoint":e.compile(D),"dsr-enricher":e.compile(O)}}function L(e){return`${e.instancePath||`/`} ${e.message??`is invalid`}`}function R(e,t,r,i){let a=I(),o=[],s=[];return r.forEach(r=>{if(/<<parameters\.[^>]+>>/u.test(r.code))M(i,{code:`manifest.unresolved-code-path`,message:`Code paths cannot contain unresolved parameter placeholders.`,path:r.code,functionName:r.name});else if(c(r.code)){let a=F(r,t);e.fs.existsSync(a.path)?n(e,t,a.path)?e.fs.statSync(a.path).isFile()?o.push(a):M(i,{code:`source.not-file`,message:`Referenced source path is not a regular file.`,path:r.code,functionName:r.name}):M(i,{code:`source.outside-project`,message:`Referenced source resolves outside the manifest directory through a symlink.`,path:r.code,functionName:r.name}):M(i,{code:`source.missing`,message:`Referenced source file does not exist.`,path:r.code,functionName:r.name})}P(r).forEach(o=>{if(/<<parameters\.[^>]+>>/u.test(o.path)){M(i,{code:`manifest.unresolved-payload-path`,message:`Payload paths cannot contain unresolved parameter placeholders.`,path:o.path,functionName:r.name});return}let c=C(t,o.path);if(!e.fs.existsSync(c)){M(i,{code:`payload.missing`,message:`Referenced test payload does not exist.`,path:o.path,functionName:r.name});return}if(!n(e,t,c)){M(i,{code:`payload.outside-project`,message:`Referenced test payload resolves outside the manifest directory through a symlink.`,path:o.path,functionName:r.name});return}if(!e.fs.statSync(c).isFile()){M(i,{code:`payload.not-file`,message:`Referenced test payload is not a regular file.`,path:o.path,functionName:r.name});return}s.push(c);let l;try{l=JSON.parse(e.fs.readFileSync(c,`utf8`))}catch(e){M(i,{code:`payload.invalid-json`,message:`Invalid JSON: ${e.message}`,path:o.path,functionName:r.name});return}let u=a[o.type];u(l)||(u.errors??[]).forEach(e=>M(i,{code:`payload.schema`,message:L(e),path:o.path,functionName:r.name}))})}),{sources:o,payloadPaths:[...new Set(s)]}}function z(e){try{let t=JSON.parse(e),n=Array.isArray(t)?t:t&&typeof t==`object`&&Array.isArray(t.nodes)?t.nodes:void 0;return n?new Set(n.flatMap(e=>{if(!e||typeof e!=`object`)return[];let t=e.name;return typeof t==`string`?[t]:[]})):new Set}catch{return new Set}}function B(e){switch(b(e)){case`.ts`:case`.tsx`:return`ts`;case`.json`:case`.jsonc`:return`json`;case`.yaml`:case`.yml`:return`yaml`;default:return`ts`}}function V(e,n,r){if(!r)return;let i=j(e.fs.readFileSync(r,`utf8`));if(typeof i?.importMap==`string`){if(/^[a-z][a-z\d+.-]*:/iu.test(i.importMap))return i.importMap;let a=C(y(r),i.importMap);return t(e,n,a),a}let a={};if(i.imports!==void 0&&(a.imports=i.imports),i.scopes!==void 0&&(a.scopes=i.scopes),Object.keys(a).length!==0)return`data:application/json,${encodeURIComponent(JSON.stringify(a))}`}async function H(e,n,r,i,a){let o=[],s=[];for(let c of a){t(e,r,c);let a=e.fs.readFileSync(c,`utf8`),l=await n(`deno`,[`fmt`,...i,`--ext=${B(c)}`,`-`],{cwd:r,input:a},e);if(l.code!==0)throw Error(`Deno could not preview formatting for ${N(r,c)}.${l.stderr.trim()?`\n${l.stderr.trim()}`:``}`);if(l.stdout!==a){let t=N(r,c);o.push(E(t,t,a,l.stdout,``,``,{context:3})),s.push({kind:`file`,path:c,before:a,after:l.stdout,description:`Format ${t}`,mode:e.fs.statSync(c).mode})}}return{patch:o.join(`
2
+ `),changes:s}}function U(e,t,n,r){M(e,{code:t,message:`${n}${r.stderr.trim()?`\n${r.stderr.trim()}`:``}`})}async function W(e,i,a=m){let o=C(i.manifestPath),c=y(o),u=[],d=new Map([[`manifest`,`passed`],[`files`,`passed`],[`payloads`,`passed`],[`runtime`,`passed`],[`exports`,`passed`],[`typecheck`,`passed`],[`lint`,`passed`],[`format`,`passed`]]),f=()=>({version:1,status:u.some(({severity:e})=>e===`error`)?`failed`:`passed`,manifestPath:o,checks:[...d].map(([e,t])=>({name:e,status:t})),diagnostics:u});if(!e.fs.existsSync(o))return M(u,{code:`manifest.missing`,message:`Custom Function manifest does not exist.`,path:N(e.process.cwd(),o)}),d.set(`manifest`,`failed`),[`files`,`payloads`,`runtime`,`exports`,`typecheck`,`lint`,`format`].forEach(e=>d.set(e,`skipped`)),f();let p=[];try{p=s(r(e.fs.readFileSync(o,`utf8`),i.variables??{})).functions}catch(e){return M(u,{code:`manifest.invalid`,message:e.message,path:N(c,o)}),d.set(`manifest`,`failed`),[`files`,`payloads`,`runtime`,`exports`,`typecheck`,`lint`,`format`].forEach(e=>d.set(e,`skipped`)),f()}p.forEach(e=>{try{l({...e.env?{env:e.env}:{},...e[`allowed-hosts`]?{allowedHosts:e[`allowed-hosts`]}:{}})}catch(t){d.set(`manifest`,`failed`),M(u,{code:`manifest.execution-context`,message:t.message,path:N(c,o),functionName:e.name})}});let{sources:b,payloadPaths:S}=R(e,c,p,u);u.some(({code:e})=>[`source.`,`manifest.unresolved-code-path`].some(t=>e.startsWith(t)))&&(d.set(`files`,`failed`),[`exports`,`typecheck`,`lint`].forEach(e=>d.set(e,`failed`))),u.some(({code:e})=>[`payload.`,`manifest.unresolved-payload-path`].some(t=>e.startsWith(t)))&&d.set(`payloads`,`failed`);let w=x(c,`deno.jsonc`),T=x(c,`deno.json`),E=e.fs.existsSync(w)?w:e.fs.existsSync(T)?T:void 0,D=E!==void 0&&!n(e,c,E),O=D,k;if(D)M(u,{code:`deno.config-outside-project`,message:`Deno configuration resolves outside the manifest directory through a symlink.`,path:N(c,E)}),[`exports`,`typecheck`,`lint`,`format`].forEach(e=>d.set(e,`failed`));else try{k=V(e,c,E)}catch(e){O=!0,M(u,{code:`deno.import-map-outside-project`,message:e.message}),[`exports`,`typecheck`,`lint`,`format`].forEach(e=>d.set(e,`failed`))}let A=E&&!O?[`--config=${E}`]:[`--no-config`],j=()=>{[`exports`,`typecheck`,`lint`,`format`].forEach(e=>{d.get(e)!==`failed`&&d.set(e,`skipped`)})},P=await a(`deno`,[`--version`],{cwd:c},e),F=P.code===0?h(P.stdout):void 0;if(F?.level===`warning`&&u.push({code:`deno.version-mismatch`,severity:`warning`,message:F.message}),P.error?.code===`ENOENT`)d.set(`runtime`,`failed`),j(),M(u,{code:`deno.missing`,message:`Deno 2.x is required for export, type, lint, and format checks. Install it from ${g}`});else if(P.code!==0)d.set(`runtime`,`failed`),j(),U(u,`deno.unavailable`,`Deno could not be started.`,P);else if(F?.level===`error`)d.set(`runtime`,`failed`),j(),M(u,{code:`deno.unsupported-version`,message:F.message});else if(!O){for(let t of b){let n=await a(`deno`,[`info`,`--json`,...A,t.path],{cwd:c},e);if(n.code!==0)d.set(`files`,`failed`),U(u,`source.module-graph`,`Could not inspect runtime imports for ${N(c,t.path)}.`,n);else try{let e=_(n.stdout);e.length>0&&(d.set(`files`,`failed`),M(u,{code:`source.local-runtime-import`,message:`Custom Functions must be self-contained. Local or import-map runtime dependencies are not deployed: `+e.join(`, `),path:N(c,t.path),functionName:t.entry.name}))}catch(e){d.set(`files`,`failed`),M(u,{code:`source.module-graph`,message:e.message,path:N(c,t.path),functionName:t.entry.name})}let r=await a(`deno`,[`doc`,`--json`,...k?[`--import-map`,k]:[],t.path],{cwd:c},e);if(r.code!==0){d.set(`exports`,`failed`),U(u,`exports.inspect`,`Could not inspect exports for ${N(c,t.path)}.`,r);continue}let i=z(r.stdout);t.needsDefault&&!i.has(`default`)&&(d.set(`exports`,`failed`),M(u,{code:`exports.default-missing`,message:`The manifest fixtures require a default export.`,path:N(c,t.path),functionName:t.entry.name})),t.needsEnricher&&!i.has(`enricher`)&&(d.set(`exports`,`failed`),M(u,{code:`exports.enricher-missing`,message:"A REQUEST_ENRICHER fixture requires an `enricher` export.",path:N(c,t.path),functionName:t.entry.name})),t.needsAnyDsrExport&&!i.has(`default`)&&!i.has(`enricher`)&&(d.set(`exports`,`failed`),M(u,{code:`exports.dsr-missing`,message:"A DSR Custom Function requires a `default` or `enricher` export.",path:N(c,t.path),functionName:t.entry.name}))}let n=[...new Set(b.map(({path:e})=>e))];if(n.length>0){let t=await a(`deno`,[`check`,...A,...n],{cwd:c},e);t.code!==0&&(d.set(`typecheck`,`failed`),U(u,`deno.typecheck`,`Deno type checking failed.`,t));let r=await a(`deno`,[`lint`,...A,...n],{cwd:c},e);r.code!==0&&(d.set(`lint`,`failed`),U(u,`deno.lint`,`Deno linting failed.`,r))}let r=[...n,...S,o,...E?[E]:[],...k&&k!==E&&!/^[a-z][a-z\d+.-]*:/iu.test(k)?[k]:[]];r.forEach(n=>t(e,c,n));let s=await a(`deno`,[`fmt`,`--check`,...A,...r],{cwd:c},e);if(s.code!==0){let t;try{t=await H(e,a,c,A,r)}catch(e){return d.set(`format`,`failed`),M(u,{code:`deno.format-preview`,message:e.message}),f()}if(t.changes.length===0)return d.set(`format`,`failed`),U(u,`deno.format`,`Deno reported a formatting failure but did not produce a repair.`,s),f();if(i.fix||i.confirmFormat&&await i.confirmFormat(t.patch))try{await v(e,{rootDirectory:c,changes:t.changes})}catch(e){d.set(`format`,`failed`),M(u,{code:`deno.format-fix`,message:`Could not apply formatting transaction: ${e.message}`})}else d.set(`format`,`failed`),t.changes.forEach((e,n)=>{M(u,{code:`deno.format`,message:`Referenced file is not formatted.`+(n===0&&i.includeFormatPatchInDiagnostics&&t.patch?`\n${t.patch}`:``),path:N(c,e.path)})})}}return f()}async function G(t,n){a(this.process);let{manifestPath:r}=e(this.process.cwd(),{...n?{directory:n}:{},...t.manifest?{manifest:t.manifest}:{}}),s=this.fs.existsSync(r)?void 0:o({cwd:this.process.cwd(),manifestPath:r,discoveredManifestPaths:u(this,this.process.cwd()),command:`check`}),c=f(t,this.process.stdin.isTTY,this.process.stderr.isTTY),l=new d(this);try{let e=await W(this,{manifestPath:r,variables:i(t.variables),fix:t.fix,includeFormatPatchInDiagnostics:!t.json,...c&&!t.fix?{confirmFormat:async e=>(e&&this.logger.error(e),l.confirm(`Format the files shown above?`,!0))}:{}});s&&e.diagnostics.forEach(e=>{e.code===`manifest.missing`&&(e.message=s)}),t.json?this.process.stdout.write(`${JSON.stringify(e)}\n`):(this.logger.info(`${T.bold(`Custom Function checks`)}\n`),e.checks.forEach(({name:e,status:t})=>{let n=t===`passed`?`PASS`:t===`failed`?`FAIL`:`SKIP`,r=t===`passed`?T.green(n):t===`failed`?T.red(n):T.yellow(n);this.logger.info(`${r} ${e[0].toUpperCase()}${e.slice(1)}`)}),e.diagnostics.length>0&&this.logger.error(``),e.diagnostics.forEach(e=>{let t=e.path?`${e.path}: `:``,n=e.functionName?`[${e.functionName}] `:``,r=`${e.severity}: ${t}${n}${e.message}`;e.severity===`warning`?this.logger.warn(T.yellow(r)):this.logger.error(T.red(r))}),e.status===`passed`?(this.logger.info(``),this.logger.info(T.green(`Custom Function checks passed.`))):(this.logger.error(``),this.logger.error(T.red(`Custom Function checks failed.`)))),e.status===`failed`&&(this.process.exitCode=1)}catch(e){throw e instanceof p&&this.process.exit(130),e}}export{G as check};
3
+ //# sourceMappingURL=impl-BpVe6fMe.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"impl--JGnR3wp.mjs","names":["parseJsonc"],"sources":["../src/commands/custom-functions/check/helpers.ts","../src/commands/custom-functions/check/impl.ts"],"sourcesContent":["import { dirname, extname, join, relative, resolve, sep } from 'node:path';\n\nimport {\n DSR_DATAPOINT_CUSTOM_FUNCTION_PAYLOAD_SCHEMA,\n DSR_REQUEST_ENRICHER_CUSTOM_FUNCTION_PAYLOAD_SCHEMA,\n GENERAL_CUSTOM_FUNCTION_PAYLOAD_SCHEMA,\n} from '@transcend-io/custom-function-types';\nimport Ajv, { type ErrorObject, type ValidateFunction } from 'ajv';\nimport { createTwoFilesPatch } from 'diff';\nimport { parse as parseJsonc } from 'jsonc-parser';\n\nimport type { LocalContext } from '../../../context.js';\nimport {\n runCapturedProcess,\n type CapturedProcessResult,\n type CapturedProcessRunner,\n} from '../../../lib/cli/run-captured-process.js';\nimport {\n type CustomFunctionCheckResult,\n type CustomFunctionCheckStatus,\n type CustomFunctionDiagnostic,\n} from '../../../lib/custom-functions/check-model.js';\nimport {\n DENO_INSTALL_URL,\n getDenoRuntimeCompatibility,\n SUPPORTED_DENO_MAJOR_VERSION,\n} from '../../../lib/custom-functions/deno-runtime.js';\nimport { validateCustomFunctionExecutionContext } from '../../../lib/custom-functions/execution-context.js';\nimport {\n isCustomFunctionManifestPathContained,\n parseCustomFunctionsManifest,\n type CustomFunctionManifestEntry,\n} from '../../../lib/custom-functions/manifest.js';\nimport { findNonSelfContainedRuntimeImports } from '../../../lib/custom-functions/module-graph.js';\nimport { CUSTOM_FUNCTION_RESULT_VERSION } from '../../../lib/custom-functions/scaffold-model.js';\nimport { replaceVariablesInYaml } from '../../../lib/readTranscendYaml.js';\nimport {\n assertPathPhysicallyContained,\n isPathPhysicallyContained,\n} from '../../../lib/scaffolding/path-safety.js';\nimport { applyProjectPlan } from '../../../lib/scaffolding/project-plan-apply.js';\nimport type { PlannedFileChange } from '../../../lib/scaffolding/project-plan.js';\n\n/** Payload file plus its validation contract. */\ninterface PayloadReference {\n /** Manifest entry. */\n entry: CustomFunctionManifestEntry;\n /** Manifest-relative payload path. */\n path: string;\n /** Schema variant. */\n type: 'general' | 'dsr-datapoint' | 'dsr-enricher';\n}\n\n/** Source file plus exports required by fixtures. */\ninterface SourceReference {\n /** Manifest entry. */\n entry: CustomFunctionManifestEntry;\n /** Absolute source path. */\n path: string;\n /** Whether a default export is required. */\n needsDefault: boolean;\n /** Whether an enricher export is required. */\n needsEnricher: boolean;\n /** Whether either DSR export is acceptable when no fixtures identify one. */\n needsAnyDsrExport: boolean;\n}\n\n/** Options for local validation. */\nexport interface RunCustomFunctionChecksOptions {\n /** Absolute manifest path. */\n manifestPath: string;\n /** Variables used to resolve manifest placeholders. */\n variables?: Record<string, string>;\n /** Apply Deno formatting. */\n fix: boolean;\n /** Ask for an interactive formatting repair after receiving a patch. */\n confirmFormat?: (patch: string) => Promise<boolean>;\n /** Include a unified format patch in human-oriented diagnostics. */\n includeFormatPatchInDiagnostics?: boolean;\n}\n\n/**\n * Add one diagnostic.\n *\n * @param diagnostics - Result collection\n * @param diagnostic - Diagnostic without severity\n */\nfunction addError(\n diagnostics: CustomFunctionDiagnostic[],\n diagnostic: Omit<CustomFunctionDiagnostic, 'severity'>,\n): void {\n diagnostics.push({ severity: 'error', ...diagnostic });\n}\n\n/**\n * Normalize an absolute path relative to the manifest.\n *\n * @param manifestDirectory - Manifest directory\n * @param path - Absolute path\n * @returns Portable display path\n */\nfunction relativePath(manifestDirectory: string, path: string): string {\n const value = relative(manifestDirectory, path).split(sep).join('/');\n return value || '.';\n}\n\n/**\n * Select all payload files and schema variants.\n *\n * @param entry - Manifest entry\n * @returns Payload references\n */\nfunction payloadReferences(entry: CustomFunctionManifestEntry): PayloadReference[] {\n const variant = (\n payloadType: 'DATA_POINT' | 'REQUEST_ENRICHER' | undefined,\n ): PayloadReference['type'] => {\n if (entry.type !== 'DSR') {\n return 'general';\n }\n return payloadType === 'REQUEST_ENRICHER' ? 'dsr-enricher' : 'dsr-datapoint';\n };\n if (entry['test-payload']) {\n return [\n {\n entry,\n path: entry['test-payload'],\n type: variant(entry['test-payload-type']),\n },\n ];\n }\n return (entry['test-payloads'] ?? []).map((item) => ({\n entry,\n path: item.payload,\n type: variant(item['payload-type']),\n }));\n}\n\n/**\n * Select export expectations from the registered fixtures.\n *\n * @param entry - Manifest entry\n * @param manifestDirectory - Manifest directory\n * @returns Source reference\n */\nfunction sourceReference(\n entry: CustomFunctionManifestEntry,\n manifestDirectory: string,\n): SourceReference {\n const payloadTypes = payloadReferences(entry).map(({ type }) => type);\n const dsrWithoutPayloads = entry.type === 'DSR' && payloadTypes.length === 0;\n return {\n entry,\n path: resolve(manifestDirectory, entry.code),\n needsDefault: entry.type !== 'DSR' || payloadTypes.includes('dsr-datapoint'),\n needsEnricher: payloadTypes.includes('dsr-enricher'),\n needsAnyDsrExport: dsrWithoutPayloads,\n };\n}\n\n/**\n * Compile published payload schemas.\n *\n * @returns Validators by local variant\n */\nfunction buildPayloadValidators(): Record<PayloadReference['type'], ValidateFunction> {\n const ajv = new Ajv({ allErrors: true, strict: false });\n return {\n general: ajv.compile(GENERAL_CUSTOM_FUNCTION_PAYLOAD_SCHEMA),\n 'dsr-datapoint': ajv.compile(DSR_DATAPOINT_CUSTOM_FUNCTION_PAYLOAD_SCHEMA),\n 'dsr-enricher': ajv.compile(DSR_REQUEST_ENRICHER_CUSTOM_FUNCTION_PAYLOAD_SCHEMA),\n };\n}\n\n/**\n * Format one Ajv failure.\n *\n * @param error - Ajv error\n * @returns Concise path and message\n */\nfunction formatSchemaError(error: ErrorObject): string {\n return `${error.instancePath || '/'} ${error.message ?? 'is invalid'}`;\n}\n\n/**\n * Validate referenced source and payload files without invoking Deno.\n *\n * @param context - CLI context\n * @param manifestDirectory - Manifest directory\n * @param entries - Parsed manifest entries\n * @param diagnostics - Result collection\n * @returns Existing source and format paths\n */\nfunction validateReferencedFiles(\n context: LocalContext,\n manifestDirectory: string,\n entries: readonly CustomFunctionManifestEntry[],\n diagnostics: CustomFunctionDiagnostic[],\n): {\n /** Existing source references. */\n sources: SourceReference[];\n /** Existing payload paths. */\n payloadPaths: string[];\n} {\n const validators = buildPayloadValidators();\n const sources: SourceReference[] = [];\n const payloadPaths: string[] = [];\n entries.forEach((entry) => {\n if (/<<parameters\\.[^>]+>>/u.test(entry.code)) {\n addError(diagnostics, {\n code: 'manifest.unresolved-code-path',\n message: 'Code paths cannot contain unresolved parameter placeholders.',\n path: entry.code,\n functionName: entry.name,\n });\n } else if (isCustomFunctionManifestPathContained(entry.code)) {\n const source = sourceReference(entry, manifestDirectory);\n if (!context.fs.existsSync(source.path)) {\n addError(diagnostics, {\n code: 'source.missing',\n message: 'Referenced source file does not exist.',\n path: entry.code,\n functionName: entry.name,\n });\n } else if (!isPathPhysicallyContained(context, manifestDirectory, source.path)) {\n addError(diagnostics, {\n code: 'source.outside-project',\n message: 'Referenced source resolves outside the manifest directory through a symlink.',\n path: entry.code,\n functionName: entry.name,\n });\n } else if (!context.fs.statSync(source.path).isFile()) {\n addError(diagnostics, {\n code: 'source.not-file',\n message: 'Referenced source path is not a regular file.',\n path: entry.code,\n functionName: entry.name,\n });\n } else {\n sources.push(source);\n }\n }\n\n payloadReferences(entry).forEach((reference) => {\n if (/<<parameters\\.[^>]+>>/u.test(reference.path)) {\n addError(diagnostics, {\n code: 'manifest.unresolved-payload-path',\n message: 'Payload paths cannot contain unresolved parameter placeholders.',\n path: reference.path,\n functionName: entry.name,\n });\n return;\n }\n const payloadPath = resolve(manifestDirectory, reference.path);\n if (!context.fs.existsSync(payloadPath)) {\n addError(diagnostics, {\n code: 'payload.missing',\n message: 'Referenced test payload does not exist.',\n path: reference.path,\n functionName: entry.name,\n });\n return;\n }\n if (!isPathPhysicallyContained(context, manifestDirectory, payloadPath)) {\n addError(diagnostics, {\n code: 'payload.outside-project',\n message:\n 'Referenced test payload resolves outside the manifest directory through a symlink.',\n path: reference.path,\n functionName: entry.name,\n });\n return;\n }\n if (!context.fs.statSync(payloadPath).isFile()) {\n addError(diagnostics, {\n code: 'payload.not-file',\n message: 'Referenced test payload is not a regular file.',\n path: reference.path,\n functionName: entry.name,\n });\n return;\n }\n payloadPaths.push(payloadPath);\n let payload: unknown;\n try {\n payload = JSON.parse(context.fs.readFileSync(payloadPath, 'utf8'));\n } catch (error) {\n addError(diagnostics, {\n code: 'payload.invalid-json',\n message: `Invalid JSON: ${(error as Error).message}`,\n path: reference.path,\n functionName: entry.name,\n });\n return;\n }\n const validate = validators[reference.type];\n if (!validate(payload)) {\n (validate.errors ?? []).forEach((error) =>\n addError(diagnostics, {\n code: 'payload.schema',\n message: formatSchemaError(error),\n path: reference.path,\n functionName: entry.name,\n }),\n );\n }\n });\n });\n return {\n sources,\n payloadPaths: [...new Set(payloadPaths)],\n };\n}\n\n/**\n * Read Deno's JSON documentation output for exported names.\n *\n * @param output - `deno doc --json` output\n * @returns Exported names\n */\nfunction exportedNames(output: string): Set<string> {\n try {\n const document = JSON.parse(output) as unknown;\n const nodes = Array.isArray(document)\n ? document\n : document &&\n typeof document === 'object' &&\n Array.isArray((document as Record<string, unknown>).nodes)\n ? ((document as Record<string, unknown>).nodes as unknown[])\n : undefined;\n if (!nodes) {\n return new Set();\n }\n return new Set(\n nodes.flatMap((node) => {\n if (!node || typeof node !== 'object') {\n return [];\n }\n const name = (node as Record<string, unknown>).name;\n return typeof name === 'string' ? [name] : [];\n }),\n );\n } catch {\n return new Set();\n }\n}\n\n/**\n * Choose the Deno formatter extension for stdin.\n *\n * @param path - Source path\n * @returns Deno extension\n */\nfunction denoExtension(path: string): string {\n switch (extname(path)) {\n case '.ts':\n case '.tsx':\n return 'ts';\n case '.json':\n case '.jsonc':\n return 'json';\n case '.yaml':\n case '.yml':\n return 'yaml';\n default:\n return 'ts';\n }\n}\n\n/**\n * Resolve the import-map input supported by `deno doc`.\n *\n * Deno 2.4 does not expose `--config` for `doc`. A full `deno.json` is not a\n * valid import map when it also has `tasks`, `lint`, `fmt`, or\n * `compilerOptions`, so inline `imports` / `scopes` are passed as a data URL.\n * An `importMap` reference is followed explicitly.\n *\n * @param context - CLI context\n * @param manifestDirectory - Approved project root\n * @param configPath - Selected Deno config\n * @returns Import map path or URL\n */\nfunction resolveDocImportMap(\n context: LocalContext,\n manifestDirectory: string,\n configPath: string | undefined,\n): string | undefined {\n if (!configPath) {\n return undefined;\n }\n const config = parseJsonc(context.fs.readFileSync(configPath, 'utf8')) as {\n /** Optional separate import map. */\n importMap?: unknown;\n /** Inline import map entries. */\n imports?: unknown;\n /** Inline import map scopes. */\n scopes?: unknown;\n };\n if (typeof config?.importMap === 'string') {\n if (/^[a-z][a-z\\d+.-]*:/iu.test(config.importMap)) {\n return config.importMap;\n }\n const importMapPath = resolve(dirname(configPath), config.importMap);\n assertPathPhysicallyContained(context, manifestDirectory, importMapPath);\n return importMapPath;\n }\n const importMap: {\n /** Bare-specifier remappings. */\n imports?: unknown;\n /** Scoped remappings. */\n scopes?: unknown;\n } = {};\n if (config.imports !== undefined) {\n importMap.imports = config.imports;\n }\n if (config.scopes !== undefined) {\n importMap.scopes = config.scopes;\n }\n if (Object.keys(importMap).length === 0) {\n return undefined;\n }\n return `data:application/json,${encodeURIComponent(JSON.stringify(importMap))}`;\n}\n\n/**\n * Render deterministic formatter patches without changing files.\n *\n * @param context - CLI context\n * @param runner - Process runner\n * @param manifestDirectory - Working directory\n * @param configArgs - Deno config arguments\n * @param paths - Target files\n * @returns Unified patches and transactional file changes\n */\nasync function buildFormatPlan(\n context: LocalContext,\n runner: CapturedProcessRunner,\n manifestDirectory: string,\n configArgs: readonly string[],\n paths: readonly string[],\n): Promise<{ patch: string; changes: PlannedFileChange[] }> {\n const patches: string[] = [];\n const changes: PlannedFileChange[] = [];\n for (const path of paths) {\n assertPathPhysicallyContained(context, manifestDirectory, path);\n const before = context.fs.readFileSync(path, 'utf8');\n const result = await runner(\n 'deno',\n ['fmt', ...configArgs, `--ext=${denoExtension(path)}`, '-'],\n { cwd: manifestDirectory, input: before },\n context,\n );\n if (result.code !== 0) {\n throw new Error(\n `Deno could not preview formatting for ${relativePath(manifestDirectory, path)}.${\n result.stderr.trim() ? `\\n${result.stderr.trim()}` : ''\n }`,\n );\n }\n if (result.stdout !== before) {\n const display = relativePath(manifestDirectory, path);\n patches.push(\n createTwoFilesPatch(display, display, before, result.stdout, '', '', { context: 3 }),\n );\n changes.push({\n kind: 'file',\n path,\n before,\n after: result.stdout,\n description: `Format ${display}`,\n mode: context.fs.statSync(path).mode,\n });\n }\n }\n return { patch: patches.join('\\n'), changes };\n}\n\n/**\n * Record one Deno command failure.\n *\n * @param diagnostics - Result collection\n * @param code - Stable code\n * @param message - Summary\n * @param result - Captured process result\n */\nfunction recordDenoFailure(\n diagnostics: CustomFunctionDiagnostic[],\n code: string,\n message: string,\n result: CapturedProcessResult,\n): void {\n addError(diagnostics, {\n code,\n message: `${message}${result.stderr.trim() ? `\\n${result.stderr.trim()}` : ''}`,\n });\n}\n\n/**\n * Run credential-free local validation without executing user modules.\n *\n * @param context - CLI context\n * @param options - Manifest and format behavior\n * @param runner - Captured process runner\n * @returns Stable check result\n */\nexport async function runCustomFunctionChecks(\n context: LocalContext,\n options: RunCustomFunctionChecksOptions,\n runner: CapturedProcessRunner = runCapturedProcess,\n): Promise<CustomFunctionCheckResult> {\n const manifestPath = resolve(options.manifestPath);\n const manifestDirectory = dirname(manifestPath);\n const diagnostics: CustomFunctionDiagnostic[] = [];\n const statuses = new Map<string, CustomFunctionCheckStatus>([\n ['manifest', 'passed'],\n ['files', 'passed'],\n ['payloads', 'passed'],\n ['runtime', 'passed'],\n ['exports', 'passed'],\n ['typecheck', 'passed'],\n ['lint', 'passed'],\n ['format', 'passed'],\n ]);\n const buildResult = (): CustomFunctionCheckResult => ({\n version: CUSTOM_FUNCTION_RESULT_VERSION,\n status: diagnostics.some(({ severity }) => severity === 'error') ? 'failed' : 'passed',\n manifestPath,\n checks: [...statuses].map(([name, status]) => ({ name, status })),\n diagnostics,\n });\n if (!context.fs.existsSync(manifestPath)) {\n addError(diagnostics, {\n code: 'manifest.missing',\n message: 'Custom Function manifest does not exist.',\n path: relativePath(context.process.cwd(), manifestPath),\n });\n statuses.set('manifest', 'failed');\n ['files', 'payloads', 'runtime', 'exports', 'typecheck', 'lint', 'format'].forEach((name) =>\n statuses.set(name, 'skipped'),\n );\n return buildResult();\n }\n\n let entries: readonly CustomFunctionManifestEntry[] = [];\n try {\n const manifestContents = replaceVariablesInYaml(\n context.fs.readFileSync(manifestPath, 'utf8'),\n options.variables ?? {},\n );\n entries = parseCustomFunctionsManifest(manifestContents).functions;\n } catch (error) {\n addError(diagnostics, {\n code: 'manifest.invalid',\n message: (error as Error).message,\n path: relativePath(manifestDirectory, manifestPath),\n });\n statuses.set('manifest', 'failed');\n ['files', 'payloads', 'runtime', 'exports', 'typecheck', 'lint', 'format'].forEach((name) =>\n statuses.set(name, 'skipped'),\n );\n return buildResult();\n }\n entries.forEach((entry) => {\n try {\n validateCustomFunctionExecutionContext({\n ...(entry.env ? { env: entry.env } : {}),\n ...(entry['allowed-hosts'] ? { allowedHosts: entry['allowed-hosts'] } : {}),\n });\n } catch (error) {\n statuses.set('manifest', 'failed');\n addError(diagnostics, {\n code: 'manifest.execution-context',\n message: (error as Error).message,\n path: relativePath(manifestDirectory, manifestPath),\n functionName: entry.name,\n });\n }\n });\n\n const { sources, payloadPaths } = validateReferencedFiles(\n context,\n manifestDirectory,\n entries,\n diagnostics,\n );\n if (\n diagnostics.some(({ code }) =>\n ['source.', 'manifest.unresolved-code-path'].some((prefix) => code.startsWith(prefix)),\n )\n ) {\n statuses.set('files', 'failed');\n ['exports', 'typecheck', 'lint'].forEach((name) => statuses.set(name, 'failed'));\n }\n if (\n diagnostics.some(({ code }) =>\n ['payload.', 'manifest.unresolved-payload-path'].some((prefix) => code.startsWith(prefix)),\n )\n ) {\n statuses.set('payloads', 'failed');\n }\n\n const denoJsonc = join(manifestDirectory, 'deno.jsonc');\n const denoJson = join(manifestDirectory, 'deno.json');\n const configPath = context.fs.existsSync(denoJsonc)\n ? denoJsonc\n : context.fs.existsSync(denoJson)\n ? denoJson\n : undefined;\n const unsafeConfig =\n configPath !== undefined && !isPathPhysicallyContained(context, manifestDirectory, configPath);\n let unsafeConfiguration = unsafeConfig;\n let docImportMap: string | undefined;\n if (unsafeConfig) {\n addError(diagnostics, {\n code: 'deno.config-outside-project',\n message: 'Deno configuration resolves outside the manifest directory through a symlink.',\n path: relativePath(manifestDirectory, configPath),\n });\n ['exports', 'typecheck', 'lint', 'format'].forEach((name) => statuses.set(name, 'failed'));\n } else {\n try {\n docImportMap = resolveDocImportMap(context, manifestDirectory, configPath);\n } catch (error) {\n unsafeConfiguration = true;\n addError(diagnostics, {\n code: 'deno.import-map-outside-project',\n message: (error as Error).message,\n });\n ['exports', 'typecheck', 'lint', 'format'].forEach((name) => statuses.set(name, 'failed'));\n }\n }\n const configArgs =\n configPath && !unsafeConfiguration ? [`--config=${configPath}`] : ['--no-config'];\n const skipPendingDenoChecks = (): void => {\n ['exports', 'typecheck', 'lint', 'format'].forEach((name) => {\n if (statuses.get(name) !== 'failed') {\n statuses.set(name, 'skipped');\n }\n });\n };\n const denoVersion = await runner('deno', ['--version'], { cwd: manifestDirectory }, context);\n const compatibility =\n denoVersion.code === 0 ? getDenoRuntimeCompatibility(denoVersion.stdout) : undefined;\n if (compatibility?.level === 'warning') {\n diagnostics.push({\n code: 'deno.version-mismatch',\n severity: 'warning',\n message: compatibility.message,\n });\n }\n if (denoVersion.error?.code === 'ENOENT') {\n statuses.set('runtime', 'failed');\n skipPendingDenoChecks();\n addError(diagnostics, {\n code: 'deno.missing',\n message: `Deno ${SUPPORTED_DENO_MAJOR_VERSION}.x is required for export, type, lint, and format checks. Install it from ${DENO_INSTALL_URL}`,\n });\n } else if (denoVersion.code !== 0) {\n statuses.set('runtime', 'failed');\n skipPendingDenoChecks();\n recordDenoFailure(diagnostics, 'deno.unavailable', 'Deno could not be started.', denoVersion);\n } else if (compatibility?.level === 'error') {\n statuses.set('runtime', 'failed');\n skipPendingDenoChecks();\n addError(diagnostics, {\n code: 'deno.unsupported-version',\n message: compatibility.message,\n });\n } else if (!unsafeConfiguration) {\n for (const source of sources) {\n const moduleGraph = await runner(\n 'deno',\n ['info', '--json', ...configArgs, source.path],\n { cwd: manifestDirectory },\n context,\n );\n if (moduleGraph.code !== 0) {\n statuses.set('files', 'failed');\n recordDenoFailure(\n diagnostics,\n 'source.module-graph',\n `Could not inspect runtime imports for ${relativePath(manifestDirectory, source.path)}.`,\n moduleGraph,\n );\n } else {\n try {\n const unsupportedImports = findNonSelfContainedRuntimeImports(moduleGraph.stdout);\n if (unsupportedImports.length > 0) {\n statuses.set('files', 'failed');\n addError(diagnostics, {\n code: 'source.local-runtime-import',\n message:\n 'Custom Functions must be self-contained. Local or import-map runtime dependencies are not deployed: ' +\n unsupportedImports.join(', '),\n path: relativePath(manifestDirectory, source.path),\n functionName: source.entry.name,\n });\n }\n } catch (error) {\n statuses.set('files', 'failed');\n addError(diagnostics, {\n code: 'source.module-graph',\n message: (error as Error).message,\n path: relativePath(manifestDirectory, source.path),\n functionName: source.entry.name,\n });\n }\n }\n const result = await runner(\n 'deno',\n ['doc', '--json', ...(docImportMap ? ['--import-map', docImportMap] : []), source.path],\n { cwd: manifestDirectory },\n context,\n );\n if (result.code !== 0) {\n statuses.set('exports', 'failed');\n recordDenoFailure(\n diagnostics,\n 'exports.inspect',\n `Could not inspect exports for ${relativePath(manifestDirectory, source.path)}.`,\n result,\n );\n continue;\n }\n const names = exportedNames(result.stdout);\n if (source.needsDefault && !names.has('default')) {\n statuses.set('exports', 'failed');\n addError(diagnostics, {\n code: 'exports.default-missing',\n message: 'The manifest fixtures require a default export.',\n path: relativePath(manifestDirectory, source.path),\n functionName: source.entry.name,\n });\n }\n if (source.needsEnricher && !names.has('enricher')) {\n statuses.set('exports', 'failed');\n addError(diagnostics, {\n code: 'exports.enricher-missing',\n message: 'A REQUEST_ENRICHER fixture requires an `enricher` export.',\n path: relativePath(manifestDirectory, source.path),\n functionName: source.entry.name,\n });\n }\n if (source.needsAnyDsrExport && !names.has('default') && !names.has('enricher')) {\n statuses.set('exports', 'failed');\n addError(diagnostics, {\n code: 'exports.dsr-missing',\n message: 'A DSR Custom Function requires a `default` or `enricher` export.',\n path: relativePath(manifestDirectory, source.path),\n functionName: source.entry.name,\n });\n }\n }\n\n const sourcePaths = [...new Set(sources.map(({ path }) => path))];\n if (sourcePaths.length > 0) {\n const typecheck = await runner(\n 'deno',\n ['check', ...configArgs, ...sourcePaths],\n { cwd: manifestDirectory },\n context,\n );\n if (typecheck.code !== 0) {\n statuses.set('typecheck', 'failed');\n recordDenoFailure(diagnostics, 'deno.typecheck', 'Deno type checking failed.', typecheck);\n }\n const lint = await runner(\n 'deno',\n ['lint', ...configArgs, ...sourcePaths],\n { cwd: manifestDirectory },\n context,\n );\n if (lint.code !== 0) {\n statuses.set('lint', 'failed');\n recordDenoFailure(diagnostics, 'deno.lint', 'Deno linting failed.', lint);\n }\n }\n\n const formatPaths = [\n ...sourcePaths,\n ...payloadPaths,\n manifestPath,\n ...(configPath ? [configPath] : []),\n ...(docImportMap && docImportMap !== configPath && !/^[a-z][a-z\\d+.-]*:/iu.test(docImportMap)\n ? [docImportMap]\n : []),\n ];\n formatPaths.forEach((path) => assertPathPhysicallyContained(context, manifestDirectory, path));\n const format = await runner(\n 'deno',\n ['fmt', '--check', ...configArgs, ...formatPaths],\n { cwd: manifestDirectory },\n context,\n );\n if (format.code !== 0) {\n let formatPlan: Awaited<ReturnType<typeof buildFormatPlan>>;\n try {\n formatPlan = await buildFormatPlan(\n context,\n runner,\n manifestDirectory,\n configArgs,\n formatPaths,\n );\n } catch (error) {\n statuses.set('format', 'failed');\n addError(diagnostics, {\n code: 'deno.format-preview',\n message: (error as Error).message,\n });\n return buildResult();\n }\n if (formatPlan.changes.length === 0) {\n statuses.set('format', 'failed');\n recordDenoFailure(\n diagnostics,\n 'deno.format',\n 'Deno reported a formatting failure but did not produce a repair.',\n format,\n );\n return buildResult();\n }\n const shouldFix =\n options.fix ||\n (options.confirmFormat ? await options.confirmFormat(formatPlan.patch) : false);\n if (shouldFix) {\n try {\n await applyProjectPlan(context, {\n rootDirectory: manifestDirectory,\n changes: formatPlan.changes,\n });\n } catch (error) {\n statuses.set('format', 'failed');\n addError(diagnostics, {\n code: 'deno.format-fix',\n message: `Could not apply formatting transaction: ${(error as Error).message}`,\n });\n }\n } else {\n statuses.set('format', 'failed');\n formatPlan.changes.forEach((change, index) => {\n addError(diagnostics, {\n code: 'deno.format',\n message:\n 'Referenced file is not formatted.' +\n (index === 0 && options.includeFormatPatchInDiagnostics && formatPlan.patch\n ? `\\n${formatPlan.patch}`\n : ''),\n path: relativePath(manifestDirectory, change.path),\n });\n });\n }\n }\n }\n\n return buildResult();\n}\n","import colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { formatMissingManifestMessage } from '../../../lib/custom-functions/missing-manifest.js';\nimport { resolveCustomFunctionProjectPaths } from '../../../lib/custom-functions/paths.js';\nimport { discoverCustomFunctionManifests } from '../../../lib/custom-functions/project-discovery.js';\nimport { parseVariablesFromString } from '../../../lib/helpers/parseVariablesFromString.js';\nimport { PromptCancelledError, ScaffoldPrompts } from '../../../lib/scaffolding/prompts.js';\nimport { runCustomFunctionChecks } from './helpers.js';\n\n/** CLI flags for `transcend custom-functions check`. */\nexport interface CustomFunctionsCheckFlags {\n /** Explicit manifest path. */\n manifest?: string;\n /** Manifest variable substitutions. */\n variables: string;\n /** Apply Deno formatting. */\n fix: boolean;\n /** Disable prompts. */\n noInteractive: boolean;\n /** Emit JSON on stdout. */\n json: boolean;\n}\n\n/**\n * Validate a local Custom Function project without credentials.\n *\n * @param this - CLI context\n * @param flags - Check and interaction flags\n * @param directory - Optional target directory\n */\nexport async function check(\n this: LocalContext,\n flags: CustomFunctionsCheckFlags,\n directory?: string,\n): Promise<void> {\n doneInputValidation(this.process);\n const { manifestPath } = resolveCustomFunctionProjectPaths(this.process.cwd(), {\n ...(directory ? { directory } : {}),\n ...(flags.manifest ? { manifest: flags.manifest } : {}),\n });\n const missingMessage = this.fs.existsSync(manifestPath)\n ? undefined\n : formatMissingManifestMessage({\n cwd: this.process.cwd(),\n manifestPath,\n discoveredManifestPaths: discoverCustomFunctionManifests(this, this.process.cwd()),\n command: 'check',\n });\n const interactive =\n !flags.json &&\n !flags.noInteractive &&\n Boolean(this.process.stdin.isTTY && this.process.stderr.isTTY);\n const prompts = new ScaffoldPrompts(this);\n try {\n const result = await runCustomFunctionChecks(this, {\n manifestPath,\n variables: parseVariablesFromString(flags.variables),\n fix: flags.fix,\n includeFormatPatchInDiagnostics: !flags.json,\n ...(interactive && !flags.fix\n ? {\n confirmFormat: async (patch: string): Promise<boolean> => {\n if (patch) {\n this.logger.error(patch);\n }\n return prompts.confirm('Format the files shown above?', true);\n },\n }\n : {}),\n });\n if (missingMessage) {\n result.diagnostics.forEach((diagnostic) => {\n if (diagnostic.code === 'manifest.missing') {\n diagnostic.message = missingMessage;\n }\n });\n }\n if (flags.json) {\n this.process.stdout.write(`${JSON.stringify(result)}\\n`);\n } else {\n this.logger.info(`${colors.bold('Custom Function checks')}\\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 this.logger.info(`${styledLabel} ${name[0]!.toUpperCase()}${name.slice(1)}`);\n });\n if (result.diagnostics.length > 0) {\n this.logger.error('');\n }\n result.diagnostics.forEach((diagnostic) => {\n const location = diagnostic.path ? `${diagnostic.path}: ` : '';\n const owner = diagnostic.functionName ? `[${diagnostic.functionName}] ` : '';\n const message = `${diagnostic.severity}: ${location}${owner}${diagnostic.message}`;\n if (diagnostic.severity === 'warning') {\n this.logger.warn(colors.yellow(message));\n } else {\n this.logger.error(colors.red(message));\n }\n });\n if (result.status === 'passed') {\n this.logger.info('');\n this.logger.info(colors.green('Custom Function checks passed.'));\n } else {\n this.logger.error('');\n this.logger.error(colors.red('Custom Function checks failed.'));\n }\n }\n if (result.status === 'failed') {\n this.process.exitCode = 1;\n }\n } catch (error) {\n if (error instanceof PromptCancelledError) {\n this.process.exit(130);\n }\n throw error;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"impl-BpVe6fMe.mjs","names":["parseJsonc"],"sources":["../src/commands/custom-functions/check/helpers.ts","../src/commands/custom-functions/check/impl.ts"],"sourcesContent":["import { dirname, extname, join, relative, resolve, sep } from 'node:path';\n\nimport {\n DSR_DATAPOINT_CUSTOM_FUNCTION_PAYLOAD_SCHEMA,\n DSR_REQUEST_ENRICHER_CUSTOM_FUNCTION_PAYLOAD_SCHEMA,\n GENERAL_CUSTOM_FUNCTION_PAYLOAD_SCHEMA,\n} from '@transcend-io/custom-function-types';\nimport Ajv, { type ErrorObject, type ValidateFunction } from 'ajv';\nimport { createTwoFilesPatch } from 'diff';\nimport { parse as parseJsonc } from 'jsonc-parser';\n\nimport type { LocalContext } from '../../../context.js';\nimport {\n runCapturedProcess,\n type CapturedProcessResult,\n type CapturedProcessRunner,\n} from '../../../lib/cli/run-captured-process.js';\nimport {\n type CustomFunctionCheckResult,\n type CustomFunctionCheckStatus,\n type CustomFunctionDiagnostic,\n} from '../../../lib/custom-functions/check-model.js';\nimport {\n DENO_INSTALL_URL,\n getDenoRuntimeCompatibility,\n SUPPORTED_DENO_MAJOR_VERSION,\n} from '../../../lib/custom-functions/deno-runtime.js';\nimport { validateCustomFunctionExecutionContext } from '../../../lib/custom-functions/execution-context.js';\nimport {\n isCustomFunctionManifestPathContained,\n parseCustomFunctionsManifest,\n type CustomFunctionManifestEntry,\n} from '../../../lib/custom-functions/manifest.js';\nimport { findNonSelfContainedRuntimeImports } from '../../../lib/custom-functions/module-graph.js';\nimport { CUSTOM_FUNCTION_RESULT_VERSION } from '../../../lib/custom-functions/scaffold-model.js';\nimport { replaceVariablesInYaml } from '../../../lib/readTranscendYaml.js';\nimport {\n assertPathPhysicallyContained,\n isPathPhysicallyContained,\n} from '../../../lib/scaffolding/path-safety.js';\nimport { applyProjectPlan } from '../../../lib/scaffolding/project-plan-apply.js';\nimport type { PlannedFileChange } from '../../../lib/scaffolding/project-plan.js';\n\n/** Payload file plus its validation contract. */\ninterface PayloadReference {\n /** Manifest entry. */\n entry: CustomFunctionManifestEntry;\n /** Manifest-relative payload path. */\n path: string;\n /** Schema variant. */\n type: 'general' | 'dsr-datapoint' | 'dsr-enricher';\n}\n\n/** Source file plus exports required by fixtures. */\ninterface SourceReference {\n /** Manifest entry. */\n entry: CustomFunctionManifestEntry;\n /** Absolute source path. */\n path: string;\n /** Whether a default export is required. */\n needsDefault: boolean;\n /** Whether an enricher export is required. */\n needsEnricher: boolean;\n /** Whether either DSR export is acceptable when no fixtures identify one. */\n needsAnyDsrExport: boolean;\n}\n\n/** Options for local validation. */\nexport interface RunCustomFunctionChecksOptions {\n /** Absolute manifest path. */\n manifestPath: string;\n /** Variables used to resolve manifest placeholders. */\n variables?: Record<string, string>;\n /** Apply Deno formatting. */\n fix: boolean;\n /** Ask for an interactive formatting repair after receiving a patch. */\n confirmFormat?: (patch: string) => Promise<boolean>;\n /** Include a unified format patch in human-oriented diagnostics. */\n includeFormatPatchInDiagnostics?: boolean;\n}\n\n/**\n * Add one diagnostic.\n *\n * @param diagnostics - Result collection\n * @param diagnostic - Diagnostic without severity\n */\nfunction addError(\n diagnostics: CustomFunctionDiagnostic[],\n diagnostic: Omit<CustomFunctionDiagnostic, 'severity'>,\n): void {\n diagnostics.push({ severity: 'error', ...diagnostic });\n}\n\n/**\n * Normalize an absolute path relative to the manifest.\n *\n * @param manifestDirectory - Manifest directory\n * @param path - Absolute path\n * @returns Portable display path\n */\nfunction relativePath(manifestDirectory: string, path: string): string {\n const value = relative(manifestDirectory, path).split(sep).join('/');\n return value || '.';\n}\n\n/**\n * Select all payload files and schema variants.\n *\n * @param entry - Manifest entry\n * @returns Payload references\n */\nfunction payloadReferences(entry: CustomFunctionManifestEntry): PayloadReference[] {\n const variant = (\n payloadType: 'DATA_POINT' | 'REQUEST_ENRICHER' | undefined,\n ): PayloadReference['type'] => {\n if (entry.type !== 'DSR') {\n return 'general';\n }\n return payloadType === 'REQUEST_ENRICHER' ? 'dsr-enricher' : 'dsr-datapoint';\n };\n if (entry['test-payload']) {\n return [\n {\n entry,\n path: entry['test-payload'],\n type: variant(entry['test-payload-type']),\n },\n ];\n }\n return (entry['test-payloads'] ?? []).map((item) => ({\n entry,\n path: item.payload,\n type: variant(item['payload-type']),\n }));\n}\n\n/**\n * Select export expectations from the registered fixtures.\n *\n * @param entry - Manifest entry\n * @param manifestDirectory - Manifest directory\n * @returns Source reference\n */\nfunction sourceReference(\n entry: CustomFunctionManifestEntry,\n manifestDirectory: string,\n): SourceReference {\n const payloadTypes = payloadReferences(entry).map(({ type }) => type);\n const dsrWithoutPayloads = entry.type === 'DSR' && payloadTypes.length === 0;\n return {\n entry,\n path: resolve(manifestDirectory, entry.code),\n needsDefault: entry.type !== 'DSR' || payloadTypes.includes('dsr-datapoint'),\n needsEnricher: payloadTypes.includes('dsr-enricher'),\n needsAnyDsrExport: dsrWithoutPayloads,\n };\n}\n\n/**\n * Compile published payload schemas.\n *\n * @returns Validators by local variant\n */\nfunction buildPayloadValidators(): Record<PayloadReference['type'], ValidateFunction> {\n const ajv = new Ajv({ allErrors: true, strict: false });\n return {\n general: ajv.compile(GENERAL_CUSTOM_FUNCTION_PAYLOAD_SCHEMA),\n 'dsr-datapoint': ajv.compile(DSR_DATAPOINT_CUSTOM_FUNCTION_PAYLOAD_SCHEMA),\n 'dsr-enricher': ajv.compile(DSR_REQUEST_ENRICHER_CUSTOM_FUNCTION_PAYLOAD_SCHEMA),\n };\n}\n\n/**\n * Format one Ajv failure.\n *\n * @param error - Ajv error\n * @returns Concise path and message\n */\nfunction formatSchemaError(error: ErrorObject): string {\n return `${error.instancePath || '/'} ${error.message ?? 'is invalid'}`;\n}\n\n/**\n * Validate referenced source and payload files without invoking Deno.\n *\n * @param context - CLI context\n * @param manifestDirectory - Manifest directory\n * @param entries - Parsed manifest entries\n * @param diagnostics - Result collection\n * @returns Existing source and format paths\n */\nfunction validateReferencedFiles(\n context: LocalContext,\n manifestDirectory: string,\n entries: readonly CustomFunctionManifestEntry[],\n diagnostics: CustomFunctionDiagnostic[],\n): {\n /** Existing source references. */\n sources: SourceReference[];\n /** Existing payload paths. */\n payloadPaths: string[];\n} {\n const validators = buildPayloadValidators();\n const sources: SourceReference[] = [];\n const payloadPaths: string[] = [];\n entries.forEach((entry) => {\n if (/<<parameters\\.[^>]+>>/u.test(entry.code)) {\n addError(diagnostics, {\n code: 'manifest.unresolved-code-path',\n message: 'Code paths cannot contain unresolved parameter placeholders.',\n path: entry.code,\n functionName: entry.name,\n });\n } else if (isCustomFunctionManifestPathContained(entry.code)) {\n const source = sourceReference(entry, manifestDirectory);\n if (!context.fs.existsSync(source.path)) {\n addError(diagnostics, {\n code: 'source.missing',\n message: 'Referenced source file does not exist.',\n path: entry.code,\n functionName: entry.name,\n });\n } else if (!isPathPhysicallyContained(context, manifestDirectory, source.path)) {\n addError(diagnostics, {\n code: 'source.outside-project',\n message: 'Referenced source resolves outside the manifest directory through a symlink.',\n path: entry.code,\n functionName: entry.name,\n });\n } else if (!context.fs.statSync(source.path).isFile()) {\n addError(diagnostics, {\n code: 'source.not-file',\n message: 'Referenced source path is not a regular file.',\n path: entry.code,\n functionName: entry.name,\n });\n } else {\n sources.push(source);\n }\n }\n\n payloadReferences(entry).forEach((reference) => {\n if (/<<parameters\\.[^>]+>>/u.test(reference.path)) {\n addError(diagnostics, {\n code: 'manifest.unresolved-payload-path',\n message: 'Payload paths cannot contain unresolved parameter placeholders.',\n path: reference.path,\n functionName: entry.name,\n });\n return;\n }\n const payloadPath = resolve(manifestDirectory, reference.path);\n if (!context.fs.existsSync(payloadPath)) {\n addError(diagnostics, {\n code: 'payload.missing',\n message: 'Referenced test payload does not exist.',\n path: reference.path,\n functionName: entry.name,\n });\n return;\n }\n if (!isPathPhysicallyContained(context, manifestDirectory, payloadPath)) {\n addError(diagnostics, {\n code: 'payload.outside-project',\n message:\n 'Referenced test payload resolves outside the manifest directory through a symlink.',\n path: reference.path,\n functionName: entry.name,\n });\n return;\n }\n if (!context.fs.statSync(payloadPath).isFile()) {\n addError(diagnostics, {\n code: 'payload.not-file',\n message: 'Referenced test payload is not a regular file.',\n path: reference.path,\n functionName: entry.name,\n });\n return;\n }\n payloadPaths.push(payloadPath);\n let payload: unknown;\n try {\n payload = JSON.parse(context.fs.readFileSync(payloadPath, 'utf8'));\n } catch (error) {\n addError(diagnostics, {\n code: 'payload.invalid-json',\n message: `Invalid JSON: ${(error as Error).message}`,\n path: reference.path,\n functionName: entry.name,\n });\n return;\n }\n const validate = validators[reference.type];\n if (!validate(payload)) {\n (validate.errors ?? []).forEach((error) =>\n addError(diagnostics, {\n code: 'payload.schema',\n message: formatSchemaError(error),\n path: reference.path,\n functionName: entry.name,\n }),\n );\n }\n });\n });\n return {\n sources,\n payloadPaths: [...new Set(payloadPaths)],\n };\n}\n\n/**\n * Read Deno's JSON documentation output for exported names.\n *\n * @param output - `deno doc --json` output\n * @returns Exported names\n */\nfunction exportedNames(output: string): Set<string> {\n try {\n const document = JSON.parse(output) as unknown;\n const nodes = Array.isArray(document)\n ? document\n : document &&\n typeof document === 'object' &&\n Array.isArray((document as Record<string, unknown>).nodes)\n ? ((document as Record<string, unknown>).nodes as unknown[])\n : undefined;\n if (!nodes) {\n return new Set();\n }\n return new Set(\n nodes.flatMap((node) => {\n if (!node || typeof node !== 'object') {\n return [];\n }\n const name = (node as Record<string, unknown>).name;\n return typeof name === 'string' ? [name] : [];\n }),\n );\n } catch {\n return new Set();\n }\n}\n\n/**\n * Choose the Deno formatter extension for stdin.\n *\n * @param path - Source path\n * @returns Deno extension\n */\nfunction denoExtension(path: string): string {\n switch (extname(path)) {\n case '.ts':\n case '.tsx':\n return 'ts';\n case '.json':\n case '.jsonc':\n return 'json';\n case '.yaml':\n case '.yml':\n return 'yaml';\n default:\n return 'ts';\n }\n}\n\n/**\n * Resolve the import-map input supported by `deno doc`.\n *\n * Deno 2.4 does not expose `--config` for `doc`. A full `deno.json` is not a\n * valid import map when it also has `tasks`, `lint`, `fmt`, or\n * `compilerOptions`, so inline `imports` / `scopes` are passed as a data URL.\n * An `importMap` reference is followed explicitly.\n *\n * @param context - CLI context\n * @param manifestDirectory - Approved project root\n * @param configPath - Selected Deno config\n * @returns Import map path or URL\n */\nfunction resolveDocImportMap(\n context: LocalContext,\n manifestDirectory: string,\n configPath: string | undefined,\n): string | undefined {\n if (!configPath) {\n return undefined;\n }\n const config = parseJsonc(context.fs.readFileSync(configPath, 'utf8')) as {\n /** Optional separate import map. */\n importMap?: unknown;\n /** Inline import map entries. */\n imports?: unknown;\n /** Inline import map scopes. */\n scopes?: unknown;\n };\n if (typeof config?.importMap === 'string') {\n if (/^[a-z][a-z\\d+.-]*:/iu.test(config.importMap)) {\n return config.importMap;\n }\n const importMapPath = resolve(dirname(configPath), config.importMap);\n assertPathPhysicallyContained(context, manifestDirectory, importMapPath);\n return importMapPath;\n }\n const importMap: {\n /** Bare-specifier remappings. */\n imports?: unknown;\n /** Scoped remappings. */\n scopes?: unknown;\n } = {};\n if (config.imports !== undefined) {\n importMap.imports = config.imports;\n }\n if (config.scopes !== undefined) {\n importMap.scopes = config.scopes;\n }\n if (Object.keys(importMap).length === 0) {\n return undefined;\n }\n return `data:application/json,${encodeURIComponent(JSON.stringify(importMap))}`;\n}\n\n/**\n * Render deterministic formatter patches without changing files.\n *\n * @param context - CLI context\n * @param runner - Process runner\n * @param manifestDirectory - Working directory\n * @param configArgs - Deno config arguments\n * @param paths - Target files\n * @returns Unified patches and transactional file changes\n */\nasync function buildFormatPlan(\n context: LocalContext,\n runner: CapturedProcessRunner,\n manifestDirectory: string,\n configArgs: readonly string[],\n paths: readonly string[],\n): Promise<{ patch: string; changes: PlannedFileChange[] }> {\n const patches: string[] = [];\n const changes: PlannedFileChange[] = [];\n for (const path of paths) {\n assertPathPhysicallyContained(context, manifestDirectory, path);\n const before = context.fs.readFileSync(path, 'utf8');\n const result = await runner(\n 'deno',\n ['fmt', ...configArgs, `--ext=${denoExtension(path)}`, '-'],\n { cwd: manifestDirectory, input: before },\n context,\n );\n if (result.code !== 0) {\n throw new Error(\n `Deno could not preview formatting for ${relativePath(manifestDirectory, path)}.${\n result.stderr.trim() ? `\\n${result.stderr.trim()}` : ''\n }`,\n );\n }\n if (result.stdout !== before) {\n const display = relativePath(manifestDirectory, path);\n patches.push(\n createTwoFilesPatch(display, display, before, result.stdout, '', '', { context: 3 }),\n );\n changes.push({\n kind: 'file',\n path,\n before,\n after: result.stdout,\n description: `Format ${display}`,\n mode: context.fs.statSync(path).mode,\n });\n }\n }\n return { patch: patches.join('\\n'), changes };\n}\n\n/**\n * Record one Deno command failure.\n *\n * @param diagnostics - Result collection\n * @param code - Stable code\n * @param message - Summary\n * @param result - Captured process result\n */\nfunction recordDenoFailure(\n diagnostics: CustomFunctionDiagnostic[],\n code: string,\n message: string,\n result: CapturedProcessResult,\n): void {\n addError(diagnostics, {\n code,\n message: `${message}${result.stderr.trim() ? `\\n${result.stderr.trim()}` : ''}`,\n });\n}\n\n/**\n * Run credential-free local validation without executing user modules.\n *\n * @param context - CLI context\n * @param options - Manifest and format behavior\n * @param runner - Captured process runner\n * @returns Stable check result\n */\nexport async function runCustomFunctionChecks(\n context: LocalContext,\n options: RunCustomFunctionChecksOptions,\n runner: CapturedProcessRunner = runCapturedProcess,\n): Promise<CustomFunctionCheckResult> {\n const manifestPath = resolve(options.manifestPath);\n const manifestDirectory = dirname(manifestPath);\n const diagnostics: CustomFunctionDiagnostic[] = [];\n const statuses = new Map<string, CustomFunctionCheckStatus>([\n ['manifest', 'passed'],\n ['files', 'passed'],\n ['payloads', 'passed'],\n ['runtime', 'passed'],\n ['exports', 'passed'],\n ['typecheck', 'passed'],\n ['lint', 'passed'],\n ['format', 'passed'],\n ]);\n const buildResult = (): CustomFunctionCheckResult => ({\n version: CUSTOM_FUNCTION_RESULT_VERSION,\n status: diagnostics.some(({ severity }) => severity === 'error') ? 'failed' : 'passed',\n manifestPath,\n checks: [...statuses].map(([name, status]) => ({ name, status })),\n diagnostics,\n });\n if (!context.fs.existsSync(manifestPath)) {\n addError(diagnostics, {\n code: 'manifest.missing',\n message: 'Custom Function manifest does not exist.',\n path: relativePath(context.process.cwd(), manifestPath),\n });\n statuses.set('manifest', 'failed');\n ['files', 'payloads', 'runtime', 'exports', 'typecheck', 'lint', 'format'].forEach((name) =>\n statuses.set(name, 'skipped'),\n );\n return buildResult();\n }\n\n let entries: readonly CustomFunctionManifestEntry[] = [];\n try {\n const manifestContents = replaceVariablesInYaml(\n context.fs.readFileSync(manifestPath, 'utf8'),\n options.variables ?? {},\n );\n entries = parseCustomFunctionsManifest(manifestContents).functions;\n } catch (error) {\n addError(diagnostics, {\n code: 'manifest.invalid',\n message: (error as Error).message,\n path: relativePath(manifestDirectory, manifestPath),\n });\n statuses.set('manifest', 'failed');\n ['files', 'payloads', 'runtime', 'exports', 'typecheck', 'lint', 'format'].forEach((name) =>\n statuses.set(name, 'skipped'),\n );\n return buildResult();\n }\n entries.forEach((entry) => {\n try {\n validateCustomFunctionExecutionContext({\n ...(entry.env ? { env: entry.env } : {}),\n ...(entry['allowed-hosts'] ? { allowedHosts: entry['allowed-hosts'] } : {}),\n });\n } catch (error) {\n statuses.set('manifest', 'failed');\n addError(diagnostics, {\n code: 'manifest.execution-context',\n message: (error as Error).message,\n path: relativePath(manifestDirectory, manifestPath),\n functionName: entry.name,\n });\n }\n });\n\n const { sources, payloadPaths } = validateReferencedFiles(\n context,\n manifestDirectory,\n entries,\n diagnostics,\n );\n if (\n diagnostics.some(({ code }) =>\n ['source.', 'manifest.unresolved-code-path'].some((prefix) => code.startsWith(prefix)),\n )\n ) {\n statuses.set('files', 'failed');\n ['exports', 'typecheck', 'lint'].forEach((name) => statuses.set(name, 'failed'));\n }\n if (\n diagnostics.some(({ code }) =>\n ['payload.', 'manifest.unresolved-payload-path'].some((prefix) => code.startsWith(prefix)),\n )\n ) {\n statuses.set('payloads', 'failed');\n }\n\n const denoJsonc = join(manifestDirectory, 'deno.jsonc');\n const denoJson = join(manifestDirectory, 'deno.json');\n const configPath = context.fs.existsSync(denoJsonc)\n ? denoJsonc\n : context.fs.existsSync(denoJson)\n ? denoJson\n : undefined;\n const unsafeConfig =\n configPath !== undefined && !isPathPhysicallyContained(context, manifestDirectory, configPath);\n let unsafeConfiguration = unsafeConfig;\n let docImportMap: string | undefined;\n if (unsafeConfig) {\n addError(diagnostics, {\n code: 'deno.config-outside-project',\n message: 'Deno configuration resolves outside the manifest directory through a symlink.',\n path: relativePath(manifestDirectory, configPath),\n });\n ['exports', 'typecheck', 'lint', 'format'].forEach((name) => statuses.set(name, 'failed'));\n } else {\n try {\n docImportMap = resolveDocImportMap(context, manifestDirectory, configPath);\n } catch (error) {\n unsafeConfiguration = true;\n addError(diagnostics, {\n code: 'deno.import-map-outside-project',\n message: (error as Error).message,\n });\n ['exports', 'typecheck', 'lint', 'format'].forEach((name) => statuses.set(name, 'failed'));\n }\n }\n const configArgs =\n configPath && !unsafeConfiguration ? [`--config=${configPath}`] : ['--no-config'];\n const skipPendingDenoChecks = (): void => {\n ['exports', 'typecheck', 'lint', 'format'].forEach((name) => {\n if (statuses.get(name) !== 'failed') {\n statuses.set(name, 'skipped');\n }\n });\n };\n const denoVersion = await runner('deno', ['--version'], { cwd: manifestDirectory }, context);\n const compatibility =\n denoVersion.code === 0 ? getDenoRuntimeCompatibility(denoVersion.stdout) : undefined;\n if (compatibility?.level === 'warning') {\n diagnostics.push({\n code: 'deno.version-mismatch',\n severity: 'warning',\n message: compatibility.message,\n });\n }\n if (denoVersion.error?.code === 'ENOENT') {\n statuses.set('runtime', 'failed');\n skipPendingDenoChecks();\n addError(diagnostics, {\n code: 'deno.missing',\n message: `Deno ${SUPPORTED_DENO_MAJOR_VERSION}.x is required for export, type, lint, and format checks. Install it from ${DENO_INSTALL_URL}`,\n });\n } else if (denoVersion.code !== 0) {\n statuses.set('runtime', 'failed');\n skipPendingDenoChecks();\n recordDenoFailure(diagnostics, 'deno.unavailable', 'Deno could not be started.', denoVersion);\n } else if (compatibility?.level === 'error') {\n statuses.set('runtime', 'failed');\n skipPendingDenoChecks();\n addError(diagnostics, {\n code: 'deno.unsupported-version',\n message: compatibility.message,\n });\n } else if (!unsafeConfiguration) {\n for (const source of sources) {\n const moduleGraph = await runner(\n 'deno',\n ['info', '--json', ...configArgs, source.path],\n { cwd: manifestDirectory },\n context,\n );\n if (moduleGraph.code !== 0) {\n statuses.set('files', 'failed');\n recordDenoFailure(\n diagnostics,\n 'source.module-graph',\n `Could not inspect runtime imports for ${relativePath(manifestDirectory, source.path)}.`,\n moduleGraph,\n );\n } else {\n try {\n const unsupportedImports = findNonSelfContainedRuntimeImports(moduleGraph.stdout);\n if (unsupportedImports.length > 0) {\n statuses.set('files', 'failed');\n addError(diagnostics, {\n code: 'source.local-runtime-import',\n message:\n 'Custom Functions must be self-contained. Local or import-map runtime dependencies are not deployed: ' +\n unsupportedImports.join(', '),\n path: relativePath(manifestDirectory, source.path),\n functionName: source.entry.name,\n });\n }\n } catch (error) {\n statuses.set('files', 'failed');\n addError(diagnostics, {\n code: 'source.module-graph',\n message: (error as Error).message,\n path: relativePath(manifestDirectory, source.path),\n functionName: source.entry.name,\n });\n }\n }\n const result = await runner(\n 'deno',\n ['doc', '--json', ...(docImportMap ? ['--import-map', docImportMap] : []), source.path],\n { cwd: manifestDirectory },\n context,\n );\n if (result.code !== 0) {\n statuses.set('exports', 'failed');\n recordDenoFailure(\n diagnostics,\n 'exports.inspect',\n `Could not inspect exports for ${relativePath(manifestDirectory, source.path)}.`,\n result,\n );\n continue;\n }\n const names = exportedNames(result.stdout);\n if (source.needsDefault && !names.has('default')) {\n statuses.set('exports', 'failed');\n addError(diagnostics, {\n code: 'exports.default-missing',\n message: 'The manifest fixtures require a default export.',\n path: relativePath(manifestDirectory, source.path),\n functionName: source.entry.name,\n });\n }\n if (source.needsEnricher && !names.has('enricher')) {\n statuses.set('exports', 'failed');\n addError(diagnostics, {\n code: 'exports.enricher-missing',\n message: 'A REQUEST_ENRICHER fixture requires an `enricher` export.',\n path: relativePath(manifestDirectory, source.path),\n functionName: source.entry.name,\n });\n }\n if (source.needsAnyDsrExport && !names.has('default') && !names.has('enricher')) {\n statuses.set('exports', 'failed');\n addError(diagnostics, {\n code: 'exports.dsr-missing',\n message: 'A DSR Custom Function requires a `default` or `enricher` export.',\n path: relativePath(manifestDirectory, source.path),\n functionName: source.entry.name,\n });\n }\n }\n\n const sourcePaths = [...new Set(sources.map(({ path }) => path))];\n if (sourcePaths.length > 0) {\n const typecheck = await runner(\n 'deno',\n ['check', ...configArgs, ...sourcePaths],\n { cwd: manifestDirectory },\n context,\n );\n if (typecheck.code !== 0) {\n statuses.set('typecheck', 'failed');\n recordDenoFailure(diagnostics, 'deno.typecheck', 'Deno type checking failed.', typecheck);\n }\n const lint = await runner(\n 'deno',\n ['lint', ...configArgs, ...sourcePaths],\n { cwd: manifestDirectory },\n context,\n );\n if (lint.code !== 0) {\n statuses.set('lint', 'failed');\n recordDenoFailure(diagnostics, 'deno.lint', 'Deno linting failed.', lint);\n }\n }\n\n const formatPaths = [\n ...sourcePaths,\n ...payloadPaths,\n manifestPath,\n ...(configPath ? [configPath] : []),\n ...(docImportMap && docImportMap !== configPath && !/^[a-z][a-z\\d+.-]*:/iu.test(docImportMap)\n ? [docImportMap]\n : []),\n ];\n formatPaths.forEach((path) => assertPathPhysicallyContained(context, manifestDirectory, path));\n const format = await runner(\n 'deno',\n ['fmt', '--check', ...configArgs, ...formatPaths],\n { cwd: manifestDirectory },\n context,\n );\n if (format.code !== 0) {\n let formatPlan: Awaited<ReturnType<typeof buildFormatPlan>>;\n try {\n formatPlan = await buildFormatPlan(\n context,\n runner,\n manifestDirectory,\n configArgs,\n formatPaths,\n );\n } catch (error) {\n statuses.set('format', 'failed');\n addError(diagnostics, {\n code: 'deno.format-preview',\n message: (error as Error).message,\n });\n return buildResult();\n }\n if (formatPlan.changes.length === 0) {\n statuses.set('format', 'failed');\n recordDenoFailure(\n diagnostics,\n 'deno.format',\n 'Deno reported a formatting failure but did not produce a repair.',\n format,\n );\n return buildResult();\n }\n const shouldFix =\n options.fix ||\n (options.confirmFormat ? await options.confirmFormat(formatPlan.patch) : false);\n if (shouldFix) {\n try {\n await applyProjectPlan(context, {\n rootDirectory: manifestDirectory,\n changes: formatPlan.changes,\n });\n } catch (error) {\n statuses.set('format', 'failed');\n addError(diagnostics, {\n code: 'deno.format-fix',\n message: `Could not apply formatting transaction: ${(error as Error).message}`,\n });\n }\n } else {\n statuses.set('format', 'failed');\n formatPlan.changes.forEach((change, index) => {\n addError(diagnostics, {\n code: 'deno.format',\n message:\n 'Referenced file is not formatted.' +\n (index === 0 && options.includeFormatPatchInDiagnostics && formatPlan.patch\n ? `\\n${formatPlan.patch}`\n : ''),\n path: relativePath(manifestDirectory, change.path),\n });\n });\n }\n }\n }\n\n return buildResult();\n}\n","import colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { formatMissingManifestMessage } from '../../../lib/custom-functions/missing-manifest.js';\nimport { resolveCustomFunctionProjectPaths } from '../../../lib/custom-functions/paths.js';\nimport { discoverCustomFunctionManifests } from '../../../lib/custom-functions/project-discovery.js';\nimport { parseVariablesFromString } from '../../../lib/helpers/parseVariablesFromString.js';\nimport {\n isInteractivePromptInvocation,\n PromptCancelledError,\n ScaffoldPrompts,\n} from '../../../lib/scaffolding/prompts.js';\nimport { runCustomFunctionChecks } from './helpers.js';\n\n/** CLI flags for `transcend custom-functions check`. */\nexport interface CustomFunctionsCheckFlags {\n /** Explicit manifest path. */\n manifest?: string;\n /** Manifest variable substitutions. */\n variables: string;\n /** Apply Deno formatting. */\n fix: boolean;\n /** Disable prompts. */\n noInteractive: boolean;\n /** Emit JSON on stdout. */\n json: boolean;\n}\n\n/**\n * Validate a local Custom Function project without credentials.\n *\n * @param this - CLI context\n * @param flags - Check and interaction flags\n * @param directory - Optional target directory\n */\nexport async function check(\n this: LocalContext,\n flags: CustomFunctionsCheckFlags,\n directory?: string,\n): Promise<void> {\n doneInputValidation(this.process);\n const { manifestPath } = resolveCustomFunctionProjectPaths(this.process.cwd(), {\n ...(directory ? { directory } : {}),\n ...(flags.manifest ? { manifest: flags.manifest } : {}),\n });\n const missingMessage = this.fs.existsSync(manifestPath)\n ? undefined\n : formatMissingManifestMessage({\n cwd: this.process.cwd(),\n manifestPath,\n discoveredManifestPaths: discoverCustomFunctionManifests(this, this.process.cwd()),\n command: 'check',\n });\n const interactive = isInteractivePromptInvocation(\n flags,\n this.process.stdin.isTTY,\n this.process.stderr.isTTY,\n );\n const prompts = new ScaffoldPrompts(this);\n try {\n const result = await runCustomFunctionChecks(this, {\n manifestPath,\n variables: parseVariablesFromString(flags.variables),\n fix: flags.fix,\n includeFormatPatchInDiagnostics: !flags.json,\n ...(interactive && !flags.fix\n ? {\n confirmFormat: async (patch: string): Promise<boolean> => {\n if (patch) {\n this.logger.error(patch);\n }\n return prompts.confirm('Format the files shown above?', true);\n },\n }\n : {}),\n });\n if (missingMessage) {\n result.diagnostics.forEach((diagnostic) => {\n if (diagnostic.code === 'manifest.missing') {\n diagnostic.message = missingMessage;\n }\n });\n }\n if (flags.json) {\n this.process.stdout.write(`${JSON.stringify(result)}\\n`);\n } else {\n this.logger.info(`${colors.bold('Custom Function checks')}\\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 this.logger.info(`${styledLabel} ${name[0]!.toUpperCase()}${name.slice(1)}`);\n });\n if (result.diagnostics.length > 0) {\n this.logger.error('');\n }\n result.diagnostics.forEach((diagnostic) => {\n const location = diagnostic.path ? `${diagnostic.path}: ` : '';\n const owner = diagnostic.functionName ? `[${diagnostic.functionName}] ` : '';\n const message = `${diagnostic.severity}: ${location}${owner}${diagnostic.message}`;\n if (diagnostic.severity === 'warning') {\n this.logger.warn(colors.yellow(message));\n } else {\n this.logger.error(colors.red(message));\n }\n });\n if (result.status === 'passed') {\n this.logger.info('');\n this.logger.info(colors.green('Custom Function checks passed.'));\n } else {\n this.logger.error('');\n this.logger.error(colors.red('Custom Function checks failed.'));\n }\n }\n if (result.status === 'failed') {\n this.process.exitCode = 1;\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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"}
@@ -0,0 +1,2 @@
1
+ import{t as e}from"./buildExamples-B6BdW0FD.mjs";import{r as t}from"./policyEngineCliError-CZrOHhLv.mjs";import{a as n,i as r,o as i}from"./policy-project-discovery-C29UxWwt.mjs";import{r as a,t as o}from"./runOpa-ojIqU1tO.mjs";import{n as s,t as c}from"./policy-bundle-manifest-BZnBMZQq.mjs";import{a as l,i as u,n as d,o as f,t as p}from"./printResult-C2K9ODeE.mjs";import{t as m}from"./formatPolicyBundleVersionSummary-DCHl1Vhy.mjs";import{n as h}from"./resolveBundleIdByName-Dm_o5_bg.mjs";import{n as g}from"./inquirer-BU5IpgA8.mjs";import{t as _}from"./done-input-validation-LiTaCEzF.mjs";import{r as v}from"./prompts-BhXfYD6g.mjs";import{t as y}from"./command-output-BJcDRXNr.mjs";import b,{join as x}from"node:path";import S from"colors";import{spawnSync as C}from"node:child_process";import w from"node:fs";import T from"node:os";import{gunzipSync as E}from"node:zlib";import D from"fast-glob";function O(e){let t=D.sync(`**/*.rego`,{cwd:e,onlyFiles:!0,dot:!1}).sort(),n=b.join(e,i),{publishableRegoPaths:r}=s(w.existsSync(n)?w.readFileSync(n,`utf8`):void 0,t.map(t=>({path:t,contents:w.readFileSync(b.join(e,t),`utf8`)})));return{entries:[i,...r]}}async function k(e){let t=b.join(T.tmpdir(),`transcend-policy-bundle-build-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`);try{let{code:n,stderr:r}=await o([`build`,`--ignore`,`*_test.rego`,`-b`,`-o`,t,`.`],{cwd:e});if(n!==0)throw Error(r.trim()||`opa build failed with exit code ${n}`)}finally{w.existsSync(t)&&w.unlinkSync(t)}}function A(e){if(e<1024)return`${e} B`;let t=e/1024;if(t<1024)return`${t%1==0?t.toFixed(0):t.toFixed(1)} KiB`;let n=t/1024;return`${n%1==0?n.toFixed(0):n.toFixed(1)} MiB`}async function j(e){a();let t=b.resolve(e);if(!w.existsSync(t)||!w.statSync(t).isDirectory())throw Error(`Policy directory does not exist or is not a directory: ${t}`);let{entries:n}=O(t),{code:r,stderr:i}=await o([`check`,`--strict`,t]);if(r!==0)throw Error(i.trim()||`opa check failed with exit code ${r}`);await k(t);let s=b.join(T.tmpdir(),`transcend-policy-bundle-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`),c=C(`tar`,[`-czf`,s,`-C`,t,...n],{env:{...process.env,COPYFILE_DISABLE:`1`},encoding:`utf8`});if(c.status!==0)throw Error(`Failed to create policy bundle archive: ${c.stderr.trim()||`tar failed`}`);let u=w.readFileSync(s);if(u.byteLength>5120)throw w.unlinkSync(s),Error(`Policy bundle exceeds the ${A(l)} compressed upload limit (bundle is ${A(u.byteLength)}). The server also rejects decompressed bundles larger than ${A(f)}.`);let d=E(u);if(d.byteLength>51200)throw w.unlinkSync(s),Error(`Policy bundle exceeds the ${A(f)} decompressed upload limit (bundle is ${A(d.byteLength)} decompressed).`);return s}function M(e){let t=w.readFileSync(e.bundlePath),n=new FormData;return n.append(`bundle`,new Blob([t],{type:`application/gzip`}),b.basename(e.bundlePath)),n.append(`version`,e.version),e.description&&n.append(`description`,e.description),e.bundleName&&n.append(`bundleName`,e.bundleName),n}function N(e){return e.toISOString().slice(0,19).replace(/[T:]/g,`-`)}function P(e,t=new Date){return`${e}-${N(t)}`}function F(e){return e.template===`permissions`?!0:e.template===`generic`?!1:e.roots.some(e=>e===`permissions`||e.startsWith(`permissions/`))}function I(e,t){let r=F(t),i=e===n;if(r&&!i)return`This directory looks like a Permissions API policy, but --bundle-name is "${e}". Permissions API only loads the remote bundle named "${n}". Upload still succeeds; pass --bundle-name=${n} if that is the intended path.`;if(!r&&i)return`--bundle-name=${n} reserves the Permissions API path. Upload treats all bundles the same; only that fixed name is queried by the Permissions API. Continue only if you intend this bundle for the Permissions API.`}async function L({"bundle-name":n,auth:a,"transcend-url":o,version:s,description:l,json:f,yes:b,debug:C=!1},w){_(this.process),t(C);let T=y(this.logger,f),E=r(this.process.cwd(),w),D=s??P(n),O=u(o,a),k=v({json:f,noInteractive:!1},this.process.stdin.isTTY,this.process.stderr.isTTY),A;try{T.info(S.green(`Building policy bundle from ${E}...`)),A=await j(E);try{let e=x(E,i),t=I(n,c(this.fs.readFileSync(e,`utf8`)));t&&T.warn(S.yellow(t))}catch{}let t=await h(O,n),r;if(t){T.info(S.green(`Uploading new version for bundle "${n}"...`));let e=M({bundlePath:A,version:D,description:l});r=await d(O.post(`v1/policy-engine/policy-bundles/${t}/versions`,{body:e}).json())}else{if(!k&&!b){this.logger.error(S.red(`Cannot create a new bundle in non-interactive or JSON mode; pass --yes to confirm.`)),this.process.exit(1);return}if(!b&&(T.warn(S.yellow(`No policy bundle named "${n}" exists for this organization.`)),!await g({message:`No policy bundle named "${n}" exists. Create a new bundle and upload its first version?`}))){T.info(S.yellow(`Publish cancelled.`));return}T.info(S.green(`Creating bundle "${n}" and uploading first version...`));let e=M({bundlePath:A,version:D,description:l,bundleName:n});r=await d(O.post(`v1/policy-engine/policy-bundles`,{body:e}).json())}p(this.process.stdout,{json:f,data:r,renderTable:()=>m(r.version)}),T.info(S.green(`Policy bundle version uploaded successfully.`));let a=e([`policy`,`activate`],{version:r.version.version,"bundle-name":n});T.info(S.yellow(`Publishing a policy does not activate it. To activate this version, run:\n ${a}`))}finally{A&&this.fs.existsSync(A)&&this.fs.unlinkSync(A)}}export{L as publish};
2
+ //# sourceMappingURL=impl-BqTMPbwc2.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impl-BqTMPbwc2.mjs","names":["fg"],"sources":["../src/commands/policy/helpers/buildOpaBundleTarball.ts","../src/commands/policy/helpers/buildPolicyBundleFormData.ts","../src/commands/policy/helpers/defaultPolicyVersionLabel.ts","../src/lib/policy/policy-publish-hints.ts","../src/commands/policy/publish/impl.ts"],"sourcesContent":["import { spawnSync } from 'node:child_process';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { gunzipSync } from 'node:zlib';\n\nimport fg from 'fast-glob';\n\nimport { validatePolicyBundleContents } from '../../../lib/policy/policy-bundle-manifest.js';\nimport { POLICY_MANIFEST_FILENAME } from '../../../lib/policy/policy-scaffold-templates.js';\nimport { MAX_BUNDLE_COMPRESSED_BYTES, MAX_BUNDLE_DECOMPRESSED_BYTES } from '../constants.js';\nimport { assertOpaInstalled } from './assertOpaInstalled.js';\nimport { runOPACapture } from './runOpa.js';\n\n/** Result of collecting publishable entries from a policy bundle directory. */\ninterface PolicyBundleArchiveContents {\n /** Relative paths to include in the upload tarball (manifest first, then rego) */\n entries: string[];\n}\n\n/**\n * Collects `.manifest` and publishable `.rego` files from a policy directory.\n *\n * @param dir - Absolute path to the policy bundle directory\n * @returns Validated archive entries\n */\nfunction collectPolicyBundleArchiveEntries(dir: string): PolicyBundleArchiveContents {\n const regoFiles = fg\n .sync('**/*.rego', {\n cwd: dir,\n onlyFiles: true,\n dot: false,\n })\n .sort();\n const onDiskManifestPath = path.join(dir, POLICY_MANIFEST_FILENAME);\n const { publishableRegoPaths } = validatePolicyBundleContents(\n fs.existsSync(onDiskManifestPath) ? fs.readFileSync(onDiskManifestPath, 'utf8') : undefined,\n regoFiles.map((relativePath) => ({\n path: relativePath,\n contents: fs.readFileSync(path.join(dir, relativePath), 'utf8'),\n })),\n );\n\n return {\n entries: [POLICY_MANIFEST_FILENAME, ...publishableRegoPaths],\n };\n}\n\n/**\n * Verifies that a policy directory compiles end-to-end with `opa build`.\n *\n * The compiled output is discarded — the server receives the `.manifest` +\n * `.rego` archive produced by {@link buildOpaBundleTarball}, not the OPA bundle\n * — but a successful build guarantees the policies compile and link, surfacing\n * errors (syntax, missing imports, undefined references, etc.) before upload.\n *\n * @param dir - Absolute path to the policy bundle directory\n */\nasync function assertBundleCompiles(dir: string): Promise<void> {\n const buildOutputPath = path.join(\n os.tmpdir(),\n `transcend-policy-bundle-build-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`,\n );\n try {\n // Run with `cwd` set to the bundle directory and pass `.` so `opa build`\n // resolves the bundle root correctly. Bundle mode (`-b`) keeps local\n // `input.json` / `input.example.json` fixtures from merging as data.\n // `*_test.rego` files are local-only.\n const { code, stderr } = await runOPACapture(\n ['build', '--ignore', '*_test.rego', '-b', '-o', buildOutputPath, '.'],\n { cwd: dir },\n );\n if (code !== 0) {\n throw new Error(stderr.trim() || `opa build failed with exit code ${code}`);\n }\n } finally {\n if (fs.existsSync(buildOutputPath)) {\n fs.unlinkSync(buildOutputPath);\n }\n }\n}\n\n/**\n * Formats a byte count as a human-readable size with binary units.\n *\n * @param bytes - Number of bytes\n * @returns Human-readable size, e.g. `14 MiB` or `4 KiB`\n */\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} B`;\n }\n const kib = bytes / 1024;\n if (kib < 1024) {\n return `${kib % 1 === 0 ? kib.toFixed(0) : kib.toFixed(1)} KiB`;\n }\n const mib = kib / 1024;\n return `${mib % 1 === 0 ? mib.toFixed(0) : mib.toFixed(1)} MiB`;\n}\n\n/**\n * Builds a gzip-compressed policy bundle tarball for upload to Transcend.\n *\n * The Policy Engine API expects a plain archive containing `.manifest` and\n * one or more `.rego` files. Local projects author an OPA `.manifest` and it\n * is uploaded directly — no rename at pack time. Before packaging, the\n * manifest is validated (shape + root coverage) and the bundle is validated\n * with `opa check` (strict Rego linting) and `opa build` (full compilation) so\n * failures surface client-side rather than after upload.\n *\n * @param dir - Directory containing `.manifest` and `.rego` policy files\n * @returns Absolute path to the generated `.tar.gz` bundle\n */\nexport async function buildOpaBundleTarball(dir: string): Promise<string> {\n assertOpaInstalled();\n\n const resolvedDir = path.resolve(dir);\n if (!fs.existsSync(resolvedDir) || !fs.statSync(resolvedDir).isDirectory()) {\n throw new Error(`Policy directory does not exist or is not a directory: ${resolvedDir}`);\n }\n\n // Validate the manifest shape and that roots cover every Rego package before\n // invoking OPA, so invalid manifests surface a clear error instead of an\n // opaque `opa build failed with exit code 1`.\n const { entries: archiveEntries } = collectPolicyBundleArchiveEntries(resolvedDir);\n\n // Match the Rego v1 validation the Policy Engine API runs on upload.\n const { code: checkCode, stderr: checkStderr } = await runOPACapture([\n 'check',\n '--strict',\n resolvedDir,\n ]);\n if (checkCode !== 0) {\n throw new Error(checkStderr.trim() || `opa check failed with exit code ${checkCode}`);\n }\n\n // Ensure the bundle compiles end-to-end before packaging for upload.\n await assertBundleCompiles(resolvedDir);\n\n const outputPath = path.join(\n os.tmpdir(),\n `transcend-policy-bundle-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`,\n );\n const tarResult = spawnSync('tar', ['-czf', outputPath, '-C', resolvedDir, ...archiveEntries], {\n env: { ...process.env, COPYFILE_DISABLE: '1' },\n encoding: 'utf8',\n });\n if (tarResult.status !== 0) {\n throw new Error(\n `Failed to create policy bundle archive: ${tarResult.stderr.trim() || 'tar failed'}`,\n );\n }\n\n const compressedBytes = fs.readFileSync(outputPath);\n if (compressedBytes.byteLength > MAX_BUNDLE_COMPRESSED_BYTES) {\n fs.unlinkSync(outputPath);\n throw new Error(\n `Policy bundle exceeds the ${formatBytes(MAX_BUNDLE_COMPRESSED_BYTES)} compressed upload limit ` +\n `(bundle is ${formatBytes(compressedBytes.byteLength)}). ` +\n `The server also rejects decompressed bundles larger than ${formatBytes(MAX_BUNDLE_DECOMPRESSED_BYTES)}.`,\n );\n }\n\n const decompressedBytes = gunzipSync(compressedBytes);\n if (decompressedBytes.byteLength > MAX_BUNDLE_DECOMPRESSED_BYTES) {\n fs.unlinkSync(outputPath);\n throw new Error(\n `Policy bundle exceeds the ${formatBytes(MAX_BUNDLE_DECOMPRESSED_BYTES)} decompressed upload limit ` +\n `(bundle is ${formatBytes(decompressedBytes.byteLength)} decompressed).`,\n );\n }\n\n return outputPath;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\n/** Fields for building a policy bundle upload form. */\nexport interface BuildPolicyBundleFormDataOptions {\n /** Absolute path to the bundle tarball */\n bundlePath: string;\n /** Version label */\n version: string;\n /** Optional description */\n description?: string;\n /** Bundle name (only for create) */\n bundleName?: string;\n}\n\n/**\n * Builds multipart form data for a policy bundle upload.\n *\n * @param options - Upload fields\n * @returns FormData ready for POST\n */\nexport function buildPolicyBundleFormData(options: BuildPolicyBundleFormDataOptions): FormData {\n const bundleBytes = fs.readFileSync(options.bundlePath);\n const form = new FormData();\n form.append(\n 'bundle',\n new Blob([bundleBytes], { type: 'application/gzip' }),\n path.basename(options.bundlePath),\n );\n form.append('version', options.version);\n if (options.description) {\n form.append('description', options.description);\n }\n if (options.bundleName) {\n form.append('bundleName', options.bundleName);\n }\n return form;\n}\n","/**\n * Formats a date as `yyyy-mm-dd-hh-mm-ss` in UTC.\n *\n * @param date - Date to format\n * @returns Timestamp label\n */\nfunction formatPolicyVersionTimestamp(date: Date): string {\n return date.toISOString().slice(0, 19).replace(/[T:]/g, '-');\n}\n\n/**\n * Returns a default version label from the bundle name and current UTC timestamp.\n *\n * @param bundleName - Tenant-unique policy bundle name\n * @param now - Current time (for testing)\n * @returns Version label in `{bundleName}-yyyy-mm-dd-hh-mm-ss` form\n */\nexport function defaultPolicyVersionLabel(bundleName: string, now: Date = new Date()): string {\n return `${bundleName}-${formatPolicyVersionTimestamp(now)}`;\n}\n","import {\n PERMISSIONS_POLICY_BUNDLE_NAME,\n type PolicyTemplateName,\n} from './policy-scaffold-templates.js';\n\n/** Inputs used to soft-warn about Permissions vs generic publish naming. */\nexport interface PolicyPublishBundleNameHintInput {\n /** Optional scaffold template from `.manifest` metadata. */\n template?: PolicyTemplateName;\n /** Declared OPA package roots. */\n roots: string[];\n}\n\n/**\n * Whether local authoring signals suggest a Permissions API bundle.\n *\n * Prefers explicit `metadata.transcend.io.template`. Without metadata, falls\n * back to a root that is exactly `permissions` or nested under it.\n *\n * @param input - Manifest template hint and roots\n * @returns Whether the local tree looks Permissions-oriented\n */\nfunction looksLikePermissionsBundle(input: PolicyPublishBundleNameHintInput): boolean {\n if (input.template === 'permissions') {\n return true;\n }\n if (input.template === 'generic') {\n return false;\n }\n return input.roots.some(\n (root) =>\n root === PERMISSIONS_POLICY_BUNDLE_NAME ||\n root.startsWith(`${PERMISSIONS_POLICY_BUNDLE_NAME}/`),\n );\n}\n\n/**\n * Soft-warning when `--bundle-name` disagrees with Permissions conventions.\n *\n * Upload does not enforce bundle kinds. Permissions API only loads the\n * remote bundle named {@link PERMISSIONS_POLICY_BUNDLE_NAME}.\n *\n * @param bundleName - Value of `--bundle-name`\n * @param input - Local manifest template/roots\n * @returns Warning text, or undefined when names align\n */\nexport function formatPolicyPublishBundleNameHint(\n bundleName: string,\n input: PolicyPublishBundleNameHintInput,\n): string | undefined {\n const permissionsLocal = looksLikePermissionsBundle(input);\n const permissionsRemote = bundleName === PERMISSIONS_POLICY_BUNDLE_NAME;\n\n if (permissionsLocal && !permissionsRemote) {\n return (\n `This directory looks like a Permissions API policy, but --bundle-name is ` +\n `\"${bundleName}\". Permissions API only loads the remote bundle named ` +\n `\"${PERMISSIONS_POLICY_BUNDLE_NAME}\". Upload still succeeds; pass ` +\n `--bundle-name=${PERMISSIONS_POLICY_BUNDLE_NAME} if that is the intended path.`\n );\n }\n\n if (!permissionsLocal && permissionsRemote) {\n return (\n `--bundle-name=${PERMISSIONS_POLICY_BUNDLE_NAME} reserves the Permissions API ` +\n `path. Upload treats all bundles the same; only that fixed name is queried by ` +\n `the Permissions API. Continue only if you intend this bundle for the Permissions API.`\n );\n }\n\n return undefined;\n}\n","import { join } from 'node:path';\n\nimport colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { selectCommandLogger } from '../../../lib/cli/command-output.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { buildExampleCommand } from '../../../lib/docgen/buildExamples.js';\nimport { inquirerConfirmBoolean } from '../../../lib/helpers/inquirer.js';\nimport { parsePolicyBundleManifest } from '../../../lib/policy/policy-bundle-manifest.js';\nimport { resolvePolicyProjectDirectory } from '../../../lib/policy/policy-project-discovery.js';\nimport { formatPolicyPublishBundleNameHint } from '../../../lib/policy/policy-publish-hints.js';\nimport { POLICY_MANIFEST_FILENAME } from '../../../lib/policy/policy-scaffold-templates.js';\nimport { isInteractivePromptInvocation } from '../../../lib/scaffolding/prompts.js';\nimport type { ActivateCommandFlags } from '../activate/impl.js';\nimport {\n buildPolicyBundleFormData,\n buildPolicyEngineClient,\n buildOpaBundleTarball,\n defaultPolicyVersionLabel,\n formatPolicyBundleVersionSummary,\n policyEngineRequest,\n printResult,\n resolveBundleIdByName,\n setPolicyEngineCliDebug,\n} from '../helpers/index.js';\nimport type { CreatePolicyBundleResponse, CreatePolicyBundleVersionResponse } from '../types.js';\n\n/** CLI flags for `transcend policy publish`. */\nexport interface PublishCommandFlags {\n /** Tenant-unique bundle name */\n 'bundle-name': string;\n /** Transcend API key */\n auth: string;\n /** Transcend API URL */\n 'transcend-url': string;\n /** Version label (defaults to `{bundleName}-yyyy-mm-dd-hh-mm-ss`) */\n version?: string;\n /** Optional version description */\n description?: string;\n /** Print raw JSON response */\n json: boolean;\n /** Skip the \"create new bundle\" confirmation */\n yes: boolean;\n /** Include technical error details when a command fails */\n debug?: boolean;\n}\n\n/**\n * Build and upload a new immutable policy bundle version.\n *\n * @param this - CLI context\n * @param flags - Command flags\n * @param directory - Policy bundle directory containing a `.manifest`\n */\nexport async function publish(\n this: LocalContext,\n {\n 'bundle-name': bundleName,\n auth,\n 'transcend-url': transcendUrl,\n version,\n description,\n json,\n yes,\n debug = false,\n }: PublishCommandFlags,\n directory: string,\n): Promise<void> {\n doneInputValidation(this.process);\n setPolicyEngineCliDebug(debug);\n\n const commandLogger = selectCommandLogger(this.logger, json);\n const resolvedDir = resolvePolicyProjectDirectory(this.process.cwd(), directory);\n const versionLabel = version ?? defaultPolicyVersionLabel(bundleName);\n const client = buildPolicyEngineClient(transcendUrl, auth);\n const interactive = isInteractivePromptInvocation(\n { json, noInteractive: false },\n this.process.stdin.isTTY,\n this.process.stderr.isTTY,\n );\n\n let bundlePath: string | undefined;\n try {\n commandLogger.info(colors.green(`Building policy bundle from ${resolvedDir}...`));\n bundlePath = await buildOpaBundleTarball(resolvedDir);\n\n try {\n const manifestPath = join(resolvedDir, POLICY_MANIFEST_FILENAME);\n const manifest = parsePolicyBundleManifest(this.fs.readFileSync(manifestPath, 'utf8'));\n const bundleNameHint = formatPolicyPublishBundleNameHint(bundleName, manifest);\n if (bundleNameHint) {\n commandLogger.warn(colors.yellow(bundleNameHint));\n }\n } catch {\n // Best-effort authoring hint; tarball build already validated the manifest.\n }\n\n const existingBundleId = await resolveBundleIdByName(client, bundleName);\n\n let responseBody: CreatePolicyBundleResponse | CreatePolicyBundleVersionResponse;\n\n if (existingBundleId) {\n commandLogger.info(colors.green(`Uploading new version for bundle \"${bundleName}\"...`));\n const form = buildPolicyBundleFormData({\n bundlePath,\n version: versionLabel,\n description,\n });\n responseBody = await policyEngineRequest(\n client\n .post(`v1/policy-engine/policy-bundles/${existingBundleId}/versions`, { body: form })\n .json<CreatePolicyBundleVersionResponse>(),\n );\n } else {\n if (!interactive && !yes) {\n this.logger.error(\n colors.red(\n 'Cannot create a new bundle in non-interactive or JSON mode; pass --yes to confirm.',\n ),\n );\n this.process.exit(1);\n return;\n }\n\n if (!yes) {\n commandLogger.warn(\n colors.yellow(`No policy bundle named \"${bundleName}\" exists for this organization.`),\n );\n const shouldCreate = await inquirerConfirmBoolean({\n message: `No policy bundle named \"${bundleName}\" exists. Create a new bundle and upload its first version?`,\n });\n if (!shouldCreate) {\n commandLogger.info(colors.yellow('Publish cancelled.'));\n return;\n }\n }\n\n commandLogger.info(\n colors.green(`Creating bundle \"${bundleName}\" and uploading first version...`),\n );\n const createForm = buildPolicyBundleFormData({\n bundlePath,\n version: versionLabel,\n description,\n bundleName,\n });\n responseBody = await policyEngineRequest(\n client\n .post('v1/policy-engine/policy-bundles', {\n body: createForm,\n })\n .json<CreatePolicyBundleResponse>(),\n );\n }\n\n printResult(this.process.stdout, {\n json,\n data: responseBody,\n renderTable: () => formatPolicyBundleVersionSummary(responseBody.version),\n });\n\n commandLogger.info(colors.green('Policy bundle version uploaded successfully.'));\n\n const activateCommand = buildExampleCommand<ActivateCommandFlags>(['policy', 'activate'], {\n version: responseBody.version.version,\n 'bundle-name': bundleName,\n });\n commandLogger.info(\n colors.yellow(\n `Publishing a policy does not activate it. To activate this version, run:\\n ${activateCommand}`,\n ),\n );\n } finally {\n if (bundlePath && this.fs.existsSync(bundlePath)) {\n this.fs.unlinkSync(bundlePath);\n }\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import{r as e}from"./policyEngineCliError-CZrOHhLv.mjs";import{i as t,n,t as r}from"./printResult-C2K9ODeE.mjs";import{t as i}from"./resolveBundleIdByName-Dm_o5_bg.mjs";import{t as a}from"./resolvePolicyBundleVersion-DRUwe7fA.mjs";import{t as o}from"./done-input-validation-LiTaCEzF.mjs";import{t as s}from"./command-output-BJcDRXNr.mjs";import c from"node:path";import l from"colors";import u from"got";function d(e,t){return`${e}-${t}.tar.gz`}function f(e,t){return[`bundleName ${e.bundleName}`,`version ${e.version}`,`output ${t}`,`sha256 ${e.sha256}`,`sizeBytes ${e.sizeBytes}`,`uploadedAt ${e.uploadedAt}`,`activatedAt ${e.activatedAt??`-`}`].join(`
2
+ `)}async function p({"bundle-name":p,version:m,output:h,auth:g,"transcend-url":_,json:v,debug:y=!1}){o(this.process),e(y);let b=t(_,g),x=s(this.logger,v),S=await i(b,p);if(!S)throw Error(`Policy bundle "${p}" was not found for this organization.`);let C;if(m)C=(await a(b,S.id,{version:m})).id;else{if(!S.activeVersionId)throw Error(`Policy bundle "${p}" has no active version.`);C=S.activeVersionId}x.info(l.green(m?`Fetching download URL for bundle "${p}" version "${m}"...`:`Fetching download URL for active version of bundle "${p}"...`));let w=await n(b.get(`v1/policy-engine/policy-bundles/${S.id}/versions/${C}`).json());if(v){r(this.process.stdout,{json:!0,data:w});return}let T=c.resolve(h??d(p,w.version));x.info(l.green(`Downloading policy bundle to ${T}...`));let E;try{E=await u(w.downloadUrl).buffer()}catch(e){throw Error(`Failed to download policy bundle from the presigned URL: ${e instanceof Error?e.message:String(e)}`,{cause:e})}let D=c.dirname(T);this.fs.mkdirSync(D,{recursive:!0}),this.fs.writeFileSync(T,E),r(this.process.stdout,{json:!1,data:w,renderTable:()=>f(w,T)}),x.info(l.green(`Policy bundle downloaded successfully.`))}export{p as download};
3
+ //# sourceMappingURL=impl-CAoIp9Nl2.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impl-CAoIp9Nl2.mjs","names":[],"sources":["../src/commands/policy/download/impl.ts"],"sourcesContent":["import path from 'node:path';\n\nimport colors from 'colors';\nimport got from 'got';\n\nimport type { LocalContext } from '../../../context.js';\nimport { selectCommandLogger } from '../../../lib/cli/command-output.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { EMPTY_CELL } from '../constants.js';\nimport {\n buildPolicyEngineClient,\n policyEngineRequest,\n printResult,\n resolveBundleByName,\n resolvePolicyBundleVersion,\n setPolicyEngineCliDebug,\n} from '../helpers/index.js';\nimport type { GetPolicyBundleVersionResponse } from '../types.js';\n\n/** CLI flags for `transcend policy download`. */\nexport interface DownloadCommandFlags {\n /** Tenant-unique bundle name */\n 'bundle-name': string;\n /**\n * Caller-supplied version label to download.\n * When omitted, downloads the bundle's currently active version.\n */\n version?: string;\n /** Destination file path; defaults to `{bundleName}-{version}.tar.gz` */\n output?: string;\n /** Transcend API key */\n auth: string;\n /** Transcend API URL */\n 'transcend-url': string;\n /** Print metadata + presigned URL as JSON without writing a file */\n json: boolean;\n /** Include technical error details when a command fails */\n debug?: boolean;\n}\n\n/**\n * Builds the default output path for a downloaded policy bundle.\n *\n * @param bundleName - Tenant-unique bundle name\n * @param version - Caller-supplied version label\n * @returns Relative path `{bundleName}-{version}.tar.gz`\n */\nexport function defaultPolicyDownloadOutputPath(bundleName: string, version: string): string {\n return `${bundleName}-${version}.tar.gz`;\n}\n\n/**\n * Formats download metadata for human-readable CLI output.\n *\n * @param body - Version metadata from the Policy Engine API\n * @param outputPath - Destination path written (or that would be written)\n * @returns Summary lines\n */\nfunction formatDownloadSummary(body: GetPolicyBundleVersionResponse, outputPath: string): string {\n return [\n `bundleName ${body.bundleName}`,\n `version ${body.version}`,\n `output ${outputPath}`,\n `sha256 ${body.sha256}`,\n `sizeBytes ${body.sizeBytes}`,\n `uploadedAt ${body.uploadedAt}`,\n `activatedAt ${body.activatedAt ?? EMPTY_CELL}`,\n ].join('\\n');\n}\n\n/**\n * Download a compiled policy bundle version to disk.\n *\n * Resolves `--bundle-name` and an optional `--version` to IDs, fetches a\n * short-lived presigned S3 URL from the monolith, then downloads the `.tar.gz`\n * bytes directly from S3 (the monolith does not proxy the artifact).\n *\n * When `--version` is omitted, downloads the bundle's currently active version.\n * If the bundle has no active version, exits with an error.\n *\n * @param this - CLI context\n * @param flags - Command flags\n */\nexport async function download(\n this: LocalContext,\n {\n 'bundle-name': bundleName,\n version,\n output,\n auth,\n 'transcend-url': transcendUrl,\n json,\n debug = false,\n }: DownloadCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n setPolicyEngineCliDebug(debug);\n\n const client = buildPolicyEngineClient(transcendUrl, auth);\n const commandLogger = selectCommandLogger(this.logger, json);\n\n const bundle = await resolveBundleByName(client, bundleName);\n if (!bundle) {\n throw new Error(`Policy bundle \"${bundleName}\" was not found for this organization.`);\n }\n\n let versionId: string;\n if (version) {\n const resolvedVersion = await resolvePolicyBundleVersion(client, bundle.id, { version });\n versionId = resolvedVersion.id;\n } else {\n if (!bundle.activeVersionId) {\n throw new Error(`Policy bundle \"${bundleName}\" has no active version.`);\n }\n versionId = bundle.activeVersionId;\n }\n\n commandLogger.info(\n colors.green(\n version\n ? `Fetching download URL for bundle \"${bundleName}\" version \"${version}\"...`\n : `Fetching download URL for active version of bundle \"${bundleName}\"...`,\n ),\n );\n\n const body = await policyEngineRequest(\n client\n .get(`v1/policy-engine/policy-bundles/${bundle.id}/versions/${versionId}`)\n .json<GetPolicyBundleVersionResponse>(),\n );\n\n if (json) {\n printResult(this.process.stdout, {\n json: true,\n data: body,\n });\n return;\n }\n\n const outputPath = path.resolve(\n output ?? defaultPolicyDownloadOutputPath(bundleName, body.version),\n );\n\n commandLogger.info(colors.green(`Downloading policy bundle to ${outputPath}...`));\n\n let bundleBytes: Uint8Array;\n try {\n bundleBytes = await got(body.downloadUrl).buffer();\n } catch (err) {\n throw new Error(\n `Failed to download policy bundle from the presigned URL: ${\n err instanceof Error ? err.message : String(err)\n }`,\n { cause: err },\n );\n }\n\n const outputDir = path.dirname(outputPath);\n this.fs.mkdirSync(outputDir, { recursive: true });\n this.fs.writeFileSync(outputPath, bundleBytes);\n\n printResult(this.process.stdout, {\n json: false,\n data: body,\n renderTable: () => formatDownloadSummary(body, outputPath),\n });\n\n commandLogger.info(colors.green('Policy bundle downloaded successfully.'));\n}\n"],"mappings":"oZA+CA,SAAgB,EAAgC,EAAoB,EAAyB,CAC3F,MAAO,GAAG,EAAW,GAAG,EAAQ,SAUlC,SAAS,EAAsB,EAAsC,EAA4B,CAC/F,MAAO,CACL,eAAe,EAAK,aACpB,eAAe,EAAK,UACpB,eAAe,IACf,eAAe,EAAK,SACpB,eAAe,EAAK,YACpB,eAAe,EAAK,aACpB,eAAe,EAAK,aAAA,MACrB,CAAC,KAAK;EAAK,CAgBd,eAAsB,EAEpB,CACE,cAAe,EACf,UACA,SACA,OACA,gBAAiB,EACjB,OACA,QAAQ,IAEK,CACf,EAAoB,KAAK,QAAQ,CACjC,EAAwB,EAAM,CAE9B,IAAM,EAAS,EAAwB,EAAc,EAAK,CACpD,EAAgB,EAAoB,KAAK,OAAQ,EAAK,CAEtD,EAAS,MAAM,EAAoB,EAAQ,EAAW,CAC5D,GAAI,CAAC,EACH,MAAU,MAAM,kBAAkB,EAAW,wCAAwC,CAGvF,IAAI,EACJ,GAAI,EAEF,GAAY,MADkB,EAA2B,EAAQ,EAAO,GAAI,CAAE,UAAS,CAAC,EAC5D,OACvB,CACL,GAAI,CAAC,EAAO,gBACV,MAAU,MAAM,kBAAkB,EAAW,0BAA0B,CAEzE,EAAY,EAAO,gBAGrB,EAAc,KACZ,EAAO,MACL,EACI,qCAAqC,EAAW,aAAa,EAAQ,MACrE,uDAAuD,EAAW,MACvE,CACF,CAED,IAAM,EAAO,MAAM,EACjB,EACG,IAAI,mCAAmC,EAAO,GAAG,YAAY,IAAY,CACzE,MAAsC,CAC1C,CAED,GAAI,EAAM,CACR,EAAY,KAAK,QAAQ,OAAQ,CAC/B,KAAM,GACN,KAAM,EACP,CAAC,CACF,OAGF,IAAM,EAAa,EAAK,QACtB,GAAU,EAAgC,EAAY,EAAK,QAAQ,CACpE,CAED,EAAc,KAAK,EAAO,MAAM,gCAAgC,EAAW,KAAK,CAAC,CAEjF,IAAI,EACJ,GAAI,CACF,EAAc,MAAM,EAAI,EAAK,YAAY,CAAC,QAAQ,OAC3C,EAAK,CACZ,MAAU,MACR,4DACE,aAAe,MAAQ,EAAI,QAAU,OAAO,EAAI,GAElD,CAAE,MAAO,EAAK,CACf,CAGH,IAAM,EAAY,EAAK,QAAQ,EAAW,CAC1C,KAAK,GAAG,UAAU,EAAW,CAAE,UAAW,GAAM,CAAC,CACjD,KAAK,GAAG,cAAc,EAAY,EAAY,CAE9C,EAAY,KAAK,QAAQ,OAAQ,CAC/B,KAAM,GACN,KAAM,EACN,gBAAmB,EAAsB,EAAM,EAAW,CAC3D,CAAC,CAEF,EAAc,KAAK,EAAO,MAAM,yCAAyC,CAAC"}