@transcend-io/cli 10.25.4 → 10.26.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 (222) hide show
  1. package/README.md +264 -1
  2. package/dist/{app-CLOsNNoj.mjs → app-CZX6ZV6X.mjs} +38 -21
  3. package/dist/app-CZX6ZV6X.mjs.map +1 -0
  4. package/dist/{approvePrivacyRequests-BfULMmiN.mjs → approvePrivacyRequests-D1S2AYud.mjs} +2 -2
  5. package/dist/{approvePrivacyRequests-BfULMmiN.mjs.map → approvePrivacyRequests-D1S2AYud.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-CHogOpC8.mjs → buildExamples-CnfZJ8MD.mjs} +2 -2
  10. package/dist/{buildExamples-CHogOpC8.mjs.map → buildExamples-CnfZJ8MD.mjs.map} +1 -1
  11. package/dist/{buildXdiSyncEndpoint-BR7zCF05.mjs → buildXdiSyncEndpoint-B4l998cU.mjs} +2 -2
  12. package/dist/{buildXdiSyncEndpoint-BR7zCF05.mjs.map → buildXdiSyncEndpoint-B4l998cU.mjs.map} +1 -1
  13. package/dist/{bulkRestartRequests-D3NnqSRA.mjs → bulkRestartRequests-NAASQwvP.mjs} +2 -2
  14. package/dist/{bulkRestartRequests-D3NnqSRA.mjs.map → bulkRestartRequests-NAASQwvP.mjs.map} +1 -1
  15. package/dist/{bulkRetryEnrichers-Blydm41j.mjs → bulkRetryEnrichers-BEEVKtCH.mjs} +2 -2
  16. package/dist/{bulkRetryEnrichers-Blydm41j.mjs.map → bulkRetryEnrichers-BEEVKtCH.mjs.map} +1 -1
  17. package/dist/{cancelPrivacyRequests-Da7_hfc7.mjs → cancelPrivacyRequests-DM3Zamqd.mjs} +2 -2
  18. package/dist/{cancelPrivacyRequests-Da7_hfc7.mjs.map → cancelPrivacyRequests-DM3Zamqd.mjs.map} +1 -1
  19. package/dist/codecs-DJFlZLGT.mjs +2 -0
  20. package/dist/codecs-DJFlZLGT.mjs.map +1 -0
  21. package/dist/{collectCsvFilesOrExit-C8-Pr9Hr.mjs → collectCsvFilesOrExit-BPo8Mjy7.mjs} +1 -1
  22. package/dist/{collectCsvFilesOrExit-C8-Pr9Hr.mjs.map → collectCsvFilesOrExit-BPo8Mjy7.mjs.map} +1 -1
  23. package/dist/{collectParquetFilesOrExit-DyZISY9X.mjs → collectParquetFilesOrExit-DVS9_OSv.mjs} +1 -1
  24. package/dist/{collectParquetFilesOrExit-DyZISY9X.mjs.map → collectParquetFilesOrExit-DVS9_OSv.mjs.map} +1 -1
  25. package/dist/{command-Dpvt1BIt.mjs → command-30CgpFvx.mjs} +2 -2
  26. package/dist/{command-Dpvt1BIt.mjs.map → command-30CgpFvx.mjs.map} +1 -1
  27. package/dist/commands/admin/parquet-to-csv/worker.mjs +1 -1
  28. package/dist/{consentManagersToBusinessEntities-DGzryQ3W.mjs → consentManagersToBusinessEntities-rf8_xu71.mjs} +1 -1
  29. package/dist/{consentManagersToBusinessEntities-DGzryQ3W.mjs.map → consentManagersToBusinessEntities-rf8_xu71.mjs.map} +1 -1
  30. package/dist/{constants-DNF09zFX.mjs → constants-BgCEW975.mjs} +2 -2
  31. package/dist/{constants-DNF09zFX.mjs.map → constants-BgCEW975.mjs.map} +1 -1
  32. package/dist/{constants-BjwEFOS4.mjs → constants-CAOyAsNX.mjs} +2 -2
  33. package/dist/{constants-BjwEFOS4.mjs.map → constants-CAOyAsNX.mjs.map} +1 -1
  34. package/dist/{createExtraKeyHandler-Cg1VRPqF.mjs → createExtraKeyHandler-DbWzaD4c.mjs} +2 -2
  35. package/dist/{createExtraKeyHandler-Cg1VRPqF.mjs.map → createExtraKeyHandler-DbWzaD4c.mjs.map} +1 -1
  36. package/dist/{dataFlowsToDataSilos-DRGrUosf.mjs → dataFlowsToDataSilos-DRuAfwIn.mjs} +1 -1
  37. package/dist/{dataFlowsToDataSilos-DRGrUosf.mjs.map → dataFlowsToDataSilos-DRuAfwIn.mjs.map} +1 -1
  38. package/dist/{done-input-validation-uqIgnJcw.mjs → done-input-validation-DL31vk7g.mjs} +1 -1
  39. package/dist/{done-input-validation-uqIgnJcw.mjs.map → done-input-validation-DL31vk7g.mjs.map} +1 -1
  40. package/dist/{downloadPrivacyRequestFiles-CAGrriEp.mjs → downloadPrivacyRequestFiles-DSOTFVU6.mjs} +2 -2
  41. package/dist/{downloadPrivacyRequestFiles-CAGrriEp.mjs.map → downloadPrivacyRequestFiles-DSOTFVU6.mjs.map} +1 -1
  42. package/dist/{generateCrossAccountApiKeys-Cu35vcXs.mjs → generateCrossAccountApiKeys-C3mCgp6X.mjs} +2 -2
  43. package/dist/{generateCrossAccountApiKeys-Cu35vcXs.mjs.map → generateCrossAccountApiKeys-C3mCgp6X.mjs.map} +1 -1
  44. package/dist/{impl-DBFiULuD2.mjs → impl-1ueiw_XV2.mjs} +2 -2
  45. package/dist/{impl-DBFiULuD2.mjs.map → impl-1ueiw_XV2.mjs.map} +1 -1
  46. package/dist/{impl-Ce4Ua3nx.mjs → impl-7pxeoDZg.mjs} +2 -2
  47. package/dist/{impl-Ce4Ua3nx.mjs.map → impl-7pxeoDZg.mjs.map} +1 -1
  48. package/dist/impl-8zmHCdih.mjs +2 -0
  49. package/dist/{impl-C6jaX52V.mjs.map → impl-8zmHCdih.mjs.map} +1 -1
  50. package/dist/{impl-UEjhKO47.mjs → impl-B0fzc-Pd.mjs} +2 -2
  51. package/dist/{impl-UEjhKO47.mjs.map → impl-B0fzc-Pd.mjs.map} +1 -1
  52. package/dist/{impl-DdjTOXMv.mjs → impl-B2eZGemA.mjs} +2 -2
  53. package/dist/{impl-DdjTOXMv.mjs.map → impl-B2eZGemA.mjs.map} +1 -1
  54. package/dist/{impl-CmvkC9BB2.mjs → impl-B2yCuG6f2.mjs} +2 -2
  55. package/dist/{impl-CmvkC9BB2.mjs.map → impl-B2yCuG6f2.mjs.map} +1 -1
  56. package/dist/{impl-CvmW0u62.mjs → impl-B6_4iGM2.mjs} +2 -2
  57. package/dist/{impl-CvmW0u62.mjs.map → impl-B6_4iGM2.mjs.map} +1 -1
  58. package/dist/{impl-BGVWpusE.mjs → impl-B_1LPpGy.mjs} +2 -2
  59. package/dist/{impl-BGVWpusE.mjs.map → impl-B_1LPpGy.mjs.map} +1 -1
  60. package/dist/{impl-D8h6Rxgo2.mjs → impl-Bbtnhcy02.mjs} +2 -2
  61. package/dist/{impl-D8h6Rxgo2.mjs.map → impl-Bbtnhcy02.mjs.map} +1 -1
  62. package/dist/{impl-C5kS4BNc.mjs → impl-BdG67mkj.mjs} +2 -2
  63. package/dist/{impl-C5kS4BNc.mjs.map → impl-BdG67mkj.mjs.map} +1 -1
  64. package/dist/{impl-BpPDz_Yz.mjs → impl-BdTWl0Xm.mjs} +2 -2
  65. package/dist/{impl-BpPDz_Yz.mjs.map → impl-BdTWl0Xm.mjs.map} +1 -1
  66. package/dist/{impl-C7Xp0Txd.mjs → impl-BmQR1Pae.mjs} +2 -2
  67. package/dist/{impl-C7Xp0Txd.mjs.map → impl-BmQR1Pae.mjs.map} +1 -1
  68. package/dist/{impl-BX76WSDL.mjs → impl-BnzPrDmM.mjs} +2 -2
  69. package/dist/{impl-BX76WSDL.mjs.map → impl-BnzPrDmM.mjs.map} +1 -1
  70. package/dist/{impl-Dp8o3Xpr.mjs → impl-BohgbWOH.mjs} +2 -2
  71. package/dist/{impl-Dp8o3Xpr.mjs.map → impl-BohgbWOH.mjs.map} +1 -1
  72. package/dist/{impl-w2J6bGfU.mjs → impl-BsPgb_kT.mjs} +2 -2
  73. package/dist/{impl-w2J6bGfU.mjs.map → impl-BsPgb_kT.mjs.map} +1 -1
  74. package/dist/{impl-BvLjryD7.mjs → impl-Bur_bNXN.mjs} +2 -2
  75. package/dist/{impl-BvLjryD7.mjs.map → impl-Bur_bNXN.mjs.map} +1 -1
  76. package/dist/{impl-NUMkBg7d.mjs → impl-BwuWn3TM.mjs} +2 -2
  77. package/dist/{impl-NUMkBg7d.mjs.map → impl-BwuWn3TM.mjs.map} +1 -1
  78. package/dist/{impl-B0AKcSoy.mjs → impl-BxQE7dL92.mjs} +2 -2
  79. package/dist/impl-BxQE7dL92.mjs.map +1 -0
  80. package/dist/impl-C2DDZ1EB2.mjs +2 -0
  81. package/dist/{impl-fkYix-LF2.mjs.map → impl-C2DDZ1EB2.mjs.map} +1 -1
  82. package/dist/{impl-BF9Ekyjn.mjs → impl-C3f_H_77.mjs} +2 -2
  83. package/dist/{impl-BF9Ekyjn.mjs.map → impl-C3f_H_77.mjs.map} +1 -1
  84. package/dist/{impl-BlI9fIP5.mjs → impl-C9KCLG7s2.mjs} +2 -2
  85. package/dist/impl-C9KCLG7s2.mjs.map +1 -0
  86. package/dist/{impl-D22mHixx.mjs → impl-CWVX0Xnv.mjs} +2 -2
  87. package/dist/{impl-D22mHixx.mjs.map → impl-CWVX0Xnv.mjs.map} +1 -1
  88. package/dist/impl-CWqtBcmr.mjs +2 -0
  89. package/dist/{impl-CR_UvQXr.mjs.map → impl-CWqtBcmr.mjs.map} +1 -1
  90. package/dist/{impl-BCEw1fsj.mjs → impl-CZG9gzzR.mjs} +2 -2
  91. package/dist/{impl-BCEw1fsj.mjs.map → impl-CZG9gzzR.mjs.map} +1 -1
  92. package/dist/{impl-CiaTPxwK.mjs → impl-Ca064LmU.mjs} +2 -2
  93. package/dist/{impl-CiaTPxwK.mjs.map → impl-Ca064LmU.mjs.map} +1 -1
  94. package/dist/{impl-Bgf0a6fL2.mjs → impl-CdOwXtLY2.mjs} +2 -2
  95. package/dist/{impl-Bgf0a6fL2.mjs.map → impl-CdOwXtLY2.mjs.map} +1 -1
  96. package/dist/{impl-B_4_7a-i.mjs → impl-Chska4J8.mjs} +2 -2
  97. package/dist/{impl-B_4_7a-i.mjs.map → impl-Chska4J8.mjs.map} +1 -1
  98. package/dist/{impl-Bgg6AZQS.mjs → impl-CkoQHhc8.mjs} +2 -2
  99. package/dist/{impl-Bgg6AZQS.mjs.map → impl-CkoQHhc8.mjs.map} +1 -1
  100. package/dist/impl-Cl3hf0Pd.mjs +2 -0
  101. package/dist/impl-Cl3hf0Pd.mjs.map +1 -0
  102. package/dist/{impl-D6rMK5Us.mjs → impl-CnrK11Gr2.mjs} +2 -2
  103. package/dist/impl-CnrK11Gr2.mjs.map +1 -0
  104. package/dist/{impl-Zjvt9J28.mjs → impl-D0-ioxpZ.mjs} +2 -2
  105. package/dist/{impl-Zjvt9J28.mjs.map → impl-D0-ioxpZ.mjs.map} +1 -1
  106. package/dist/impl-D5fmpaDf2.mjs +2 -0
  107. package/dist/{impl-DdomTpuS2.mjs.map → impl-D5fmpaDf2.mjs.map} +1 -1
  108. package/dist/impl-DBK5c6d0.mjs +2 -0
  109. package/dist/impl-DBK5c6d0.mjs.map +1 -0
  110. package/dist/{impl-7obvc16D2.mjs → impl-DJHPOIQn2.mjs} +2 -2
  111. package/dist/{impl-7obvc16D2.mjs.map → impl-DJHPOIQn2.mjs.map} +1 -1
  112. package/dist/{impl-DGQW5mVR.mjs → impl-DLWhxaMi.mjs} +2 -2
  113. package/dist/{impl-DGQW5mVR.mjs.map → impl-DLWhxaMi.mjs.map} +1 -1
  114. package/dist/{impl-Cjb617E32.mjs → impl-DLypyDZV2.mjs} +2 -2
  115. package/dist/{impl-Cjb617E32.mjs.map → impl-DLypyDZV2.mjs.map} +1 -1
  116. package/dist/{impl-BBSKkDDW.mjs → impl-DNtaoKI9.mjs} +2 -2
  117. package/dist/{impl-BBSKkDDW.mjs.map → impl-DNtaoKI9.mjs.map} +1 -1
  118. package/dist/{impl-Bxhh44Tv.mjs → impl-DOQk-mfA.mjs} +2 -2
  119. package/dist/{impl-Bxhh44Tv.mjs.map → impl-DOQk-mfA.mjs.map} +1 -1
  120. package/dist/{impl-9RgMs7Ud.mjs → impl-DPC_ktM2.mjs} +2 -2
  121. package/dist/{impl-9RgMs7Ud.mjs.map → impl-DPC_ktM2.mjs.map} +1 -1
  122. package/dist/{impl-BgspL0zl2.mjs → impl-DPmitBXR2.mjs} +2 -2
  123. package/dist/{impl-BgspL0zl2.mjs.map → impl-DPmitBXR2.mjs.map} +1 -1
  124. package/dist/{impl-D8iCRZpR2.mjs → impl-DRjvMMeU2.mjs} +2 -2
  125. package/dist/{impl-D8iCRZpR2.mjs.map → impl-DRjvMMeU2.mjs.map} +1 -1
  126. package/dist/{impl-BUou3FAX2.mjs → impl-DSCuy4GU2.mjs} +2 -2
  127. package/dist/{impl-BUou3FAX2.mjs.map → impl-DSCuy4GU2.mjs.map} +1 -1
  128. package/dist/{impl-Bl714Q2W2.mjs → impl-D__B55Iu2.mjs} +2 -2
  129. package/dist/{impl-Bl714Q2W2.mjs.map → impl-D__B55Iu2.mjs.map} +1 -1
  130. package/dist/{impl-DAvX3-2i2.mjs → impl-Da1sv_hX2.mjs} +2 -2
  131. package/dist/{impl-DAvX3-2i2.mjs.map → impl-Da1sv_hX2.mjs.map} +1 -1
  132. package/dist/{impl-fiK_rZ7c.mjs → impl-DmODS2cY.mjs} +2 -2
  133. package/dist/{impl-fiK_rZ7c.mjs.map → impl-DmODS2cY.mjs.map} +1 -1
  134. package/dist/{impl-D4_KLWT_2.mjs → impl-DmbT1vXM2.mjs} +2 -2
  135. package/dist/{impl-D4_KLWT_2.mjs.map → impl-DmbT1vXM2.mjs.map} +1 -1
  136. package/dist/{impl-D-JYZ74k.mjs → impl-DvSnW_IA.mjs} +2 -2
  137. package/dist/{impl-D-JYZ74k.mjs.map → impl-DvSnW_IA.mjs.map} +1 -1
  138. package/dist/{impl-x1AgpyRL.mjs → impl-GeXGMn5G.mjs} +2 -2
  139. package/dist/{impl-x1AgpyRL.mjs.map → impl-GeXGMn5G.mjs.map} +1 -1
  140. package/dist/{impl-DI0UIHyf2.mjs → impl-YeYfan582.mjs} +2 -2
  141. package/dist/{impl-DI0UIHyf2.mjs.map → impl-YeYfan582.mjs.map} +1 -1
  142. package/dist/{impl-DC9vrPYR.mjs → impl-_BPSoSwJ.mjs} +2 -2
  143. package/dist/{impl-DC9vrPYR.mjs.map → impl-_BPSoSwJ.mjs.map} +1 -1
  144. package/dist/{impl-BqvuxZBQ2.mjs → impl-_nJfGV8K2.mjs} +2 -2
  145. package/dist/{impl-BqvuxZBQ2.mjs.map → impl-_nJfGV8K2.mjs.map} +1 -1
  146. package/dist/{impl-D3qD4wsS.mjs → impl-xIb20rTt.mjs} +2 -2
  147. package/dist/{impl-D3qD4wsS.mjs.map → impl-xIb20rTt.mjs.map} +1 -1
  148. package/dist/{impl-Dj92X5ey.mjs → impl-y01BtY2r.mjs} +2 -2
  149. package/dist/{impl-Dj92X5ey.mjs.map → impl-y01BtY2r.mjs.map} +1 -1
  150. package/dist/{impl-1ia0Gtfj.mjs → impl-yVmEK84l.mjs} +2 -2
  151. package/dist/{impl-1ia0Gtfj.mjs.map → impl-yVmEK84l.mjs.map} +1 -1
  152. package/dist/{impl-CDm8c6Cr2.mjs → impl-z5TV6Spz2.mjs} +2 -2
  153. package/dist/{impl-CDm8c6Cr2.mjs.map → impl-z5TV6Spz2.mjs.map} +1 -1
  154. package/dist/index.d.mts +129 -3
  155. package/dist/index.d.mts.map +1 -1
  156. package/dist/index.mjs +3 -3
  157. package/dist/index.mjs.map +1 -1
  158. package/dist/{listFiles-BPx3iDV6.mjs → listFiles-C5kubvdN.mjs} +1 -1
  159. package/dist/{listFiles-BPx3iDV6.mjs.map → listFiles-C5kubvdN.mjs.map} +1 -1
  160. package/dist/{markRequestDataSiloIdsCompleted-Bw_krZSS.mjs → markRequestDataSiloIdsCompleted-CDV0Ppv2.mjs} +2 -2
  161. package/dist/{markRequestDataSiloIdsCompleted-Bw_krZSS.mjs.map → markRequestDataSiloIdsCompleted-CDV0Ppv2.mjs.map} +1 -1
  162. package/dist/{markSilentPrivacyRequests-CitXF4qq.mjs → markSilentPrivacyRequests-DXLiS2jH.mjs} +2 -2
  163. package/dist/{markSilentPrivacyRequests-CitXF4qq.mjs.map → markSilentPrivacyRequests-DXLiS2jH.mjs.map} +1 -1
  164. package/dist/mergeTranscendInputs-DjPe49yR.mjs +3 -0
  165. package/dist/mergeTranscendInputs-DjPe49yR.mjs.map +1 -0
  166. package/dist/{notifyPrivacyRequestsAdditionalTime-mpYqqBxR.mjs → notifyPrivacyRequestsAdditionalTime-DPp0MyfT.mjs} +2 -2
  167. package/dist/{notifyPrivacyRequestsAdditionalTime-mpYqqBxR.mjs.map → notifyPrivacyRequestsAdditionalTime-DPp0MyfT.mjs.map} +1 -1
  168. package/dist/{parquetToCsvOneFile-13GirFzy.mjs → parquetToCsvOneFile-0O4iLz0t.mjs} +1 -1
  169. package/dist/{parquetToCsvOneFile-13GirFzy.mjs.map → parquetToCsvOneFile-0O4iLz0t.mjs.map} +1 -1
  170. package/dist/parseVariablesFromString-B4TUkJRF.mjs +2 -0
  171. package/dist/parseVariablesFromString-B4TUkJRF.mjs.map +1 -0
  172. package/dist/{pullAllDatapoints-Bvv9KRR5.mjs → pullAllDatapoints-DJno8LkB.mjs} +1 -1
  173. package/dist/{pullAllDatapoints-Bvv9KRR5.mjs.map → pullAllDatapoints-DJno8LkB.mjs.map} +1 -1
  174. package/dist/{pullChunkedCustomSiloOutstandingIdentifiers-CQTfWHbv.mjs → pullChunkedCustomSiloOutstandingIdentifiers-rKefgKKC.mjs} +2 -2
  175. package/dist/{pullChunkedCustomSiloOutstandingIdentifiers-CQTfWHbv.mjs.map → pullChunkedCustomSiloOutstandingIdentifiers-rKefgKKC.mjs.map} +1 -1
  176. package/dist/{pullConsentManagerMetrics-CR4WwUt6.mjs → pullConsentManagerMetrics-C41UhU8u.mjs} +1 -1
  177. package/dist/{pullConsentManagerMetrics-CR4WwUt6.mjs.map → pullConsentManagerMetrics-C41UhU8u.mjs.map} +1 -1
  178. package/dist/{pullManualEnrichmentIdentifiersToCsv-B0DLb0h9.mjs → pullManualEnrichmentIdentifiersToCsv-Cbk-7ztw.mjs} +2 -2
  179. package/dist/{pullManualEnrichmentIdentifiersToCsv-B0DLb0h9.mjs.map → pullManualEnrichmentIdentifiersToCsv-Cbk-7ztw.mjs.map} +1 -1
  180. package/dist/{pushCronIdentifiersFromCsv-7s9hak_0.mjs → pushCronIdentifiersFromCsv-Dj-KEFpQ.mjs} +2 -2
  181. package/dist/{pushCronIdentifiersFromCsv-7s9hak_0.mjs.map → pushCronIdentifiersFromCsv-Dj-KEFpQ.mjs.map} +1 -1
  182. package/dist/{pushManualEnrichmentIdentifiersFromCsv-h4gafAHj.mjs → pushManualEnrichmentIdentifiersFromCsv-CY4d1jQy.mjs} +2 -2
  183. package/dist/{pushManualEnrichmentIdentifiersFromCsv-h4gafAHj.mjs.map → pushManualEnrichmentIdentifiersFromCsv-CY4d1jQy.mjs.map} +1 -1
  184. package/dist/{readTranscendYaml-ceJQNB1O.mjs → readTranscendYaml-bL1qFPqv.mjs} +2 -2
  185. package/dist/{readTranscendYaml-ceJQNB1O.mjs.map → readTranscendYaml-bL1qFPqv.mjs.map} +1 -1
  186. package/dist/{removeUnverifiedRequestIdentifiers-CjgP5O-2.mjs → removeUnverifiedRequestIdentifiers-BUJZoJD9.mjs} +2 -2
  187. package/dist/{removeUnverifiedRequestIdentifiers-CjgP5O-2.mjs.map → removeUnverifiedRequestIdentifiers-BUJZoJD9.mjs.map} +1 -1
  188. package/dist/{retryRequestDataSilos-DAY3Fu3J.mjs → retryRequestDataSilos-DATDTDin.mjs} +2 -2
  189. package/dist/{retryRequestDataSilos-DAY3Fu3J.mjs.map → retryRequestDataSilos-DATDTDin.mjs.map} +1 -1
  190. package/dist/{skipPreflightJobs-D09CE-vp.mjs → skipPreflightJobs-C1go-m8K.mjs} +2 -2
  191. package/dist/{skipPreflightJobs-D09CE-vp.mjs.map → skipPreflightJobs-C1go-m8K.mjs.map} +1 -1
  192. package/dist/{skipRequestDataSilos-CDMBQH8Z.mjs → skipRequestDataSilos-1ksexte3.mjs} +2 -2
  193. package/dist/{skipRequestDataSilos-CDMBQH8Z.mjs.map → skipRequestDataSilos-1ksexte3.mjs.map} +1 -1
  194. package/dist/{streamPrivacyRequestsToCsv-C_UcaZGl.mjs → streamPrivacyRequestsToCsv-7S52MmdS.mjs} +2 -2
  195. package/dist/{streamPrivacyRequestsToCsv-C_UcaZGl.mjs.map → streamPrivacyRequestsToCsv-7S52MmdS.mjs.map} +1 -1
  196. package/dist/{updateConsentManagerVersionToLatest-B4uTgkJS.mjs → updateConsentManagerVersionToLatest-CYGRh2Mf.mjs} +2 -2
  197. package/dist/{updateConsentManagerVersionToLatest-B4uTgkJS.mjs.map → updateConsentManagerVersionToLatest-CYGRh2Mf.mjs.map} +1 -1
  198. package/dist/{uploadConsents-mr1TLN64.mjs → uploadConsents-DxzUYFP_.mjs} +2 -2
  199. package/dist/{uploadConsents-mr1TLN64.mjs.map → uploadConsents-DxzUYFP_.mjs.map} +1 -1
  200. package/dist/{uploadCookiesFromCsv-ZG1M6Lmc.mjs → uploadCookiesFromCsv-D33lINd-.mjs} +2 -2
  201. package/dist/{uploadCookiesFromCsv-ZG1M6Lmc.mjs.map → uploadCookiesFromCsv-D33lINd-.mjs.map} +1 -1
  202. package/dist/{uploadDataFlowsFromCsv-BTyYYQQR.mjs → uploadDataFlowsFromCsv-0oDEouPJ.mjs} +2 -2
  203. package/dist/{uploadDataFlowsFromCsv-BTyYYQQR.mjs.map → uploadDataFlowsFromCsv-0oDEouPJ.mjs.map} +1 -1
  204. package/dist/{uploadPrivacyRequestsFromCsv-O6_80ZLH.mjs → uploadPrivacyRequestsFromCsv-CX7JRYjH.mjs} +2 -2
  205. package/dist/{uploadPrivacyRequestsFromCsv-O6_80ZLH.mjs.map → uploadPrivacyRequestsFromCsv-CX7JRYjH.mjs.map} +1 -1
  206. package/dist/{validateTranscendAuth-Dl8UUCAQ.mjs → validateTranscendAuth-CAO5ktnu.mjs} +2 -2
  207. package/dist/{validateTranscendAuth-Dl8UUCAQ.mjs.map → validateTranscendAuth-CAO5ktnu.mjs.map} +1 -1
  208. package/dist/{writeCsv-BMVkiMHM.mjs → writeCsv-DMw5OmWp.mjs} +1 -1
  209. package/dist/{writeCsv-BMVkiMHM.mjs.map → writeCsv-DMw5OmWp.mjs.map} +1 -1
  210. package/package.json +5 -4
  211. package/dist/app-CLOsNNoj.mjs.map +0 -1
  212. package/dist/codecs-DRBjmo_R.mjs +0 -2
  213. package/dist/codecs-DRBjmo_R.mjs.map +0 -1
  214. package/dist/impl-B0AKcSoy.mjs.map +0 -1
  215. package/dist/impl-BlI9fIP5.mjs.map +0 -1
  216. package/dist/impl-C6jaX52V.mjs +0 -2
  217. package/dist/impl-CR_UvQXr.mjs +0 -2
  218. package/dist/impl-D6rMK5Us.mjs.map +0 -1
  219. package/dist/impl-DdomTpuS2.mjs +0 -2
  220. package/dist/impl-fkYix-LF2.mjs +0 -2
  221. package/dist/parseVariablesFromString-B2TB86Fo.mjs +0 -3
  222. package/dist/parseVariablesFromString-B2TB86Fo.mjs.map +0 -1
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import{i as e,n as t,r as n,t as r}from"./enums-OiLcZ26O.mjs";import{a as i,c as a,d as o,f as s,g as c,h as l,i as u,l as d,m as f,n as p,o as m,p as h,r as g,s as _,t as v,u as y}from"./constants-BjwEFOS4.mjs";import{t as b}from"./logger-Ckep4QXn.mjs";import{$ as x,A as S,B as ee,C as te,D as ne,E as re,F as ie,G as ae,H as oe,I as se,J as ce,K as C,L as w,M as T,N as E,O as D,P as O,Q as k,R as A,S as j,T as M,U as N,V as P,W as F,X as I,Y as L,Z as R,_ as z,a as B,at as V,b as H,c as U,ct as W,d as G,et as le,f as ue,g as de,h as fe,i as pe,it as me,j as he,k as ge,l as _e,lt as ve,m as ye,n as be,nt as xe,o as Se,ot as Ce,p as we,q as Te,r as Ee,rt as De,s as Oe,st as ke,t as Ae,tt as je,u as Me,ut as Ne,v as Pe,w as Fe,x as Ie,y as Le,z as Re}from"./codecs-DRBjmo_R.mjs";import{a as ze,i as Be,n as Ve,r as He,t as Ue}from"./readTranscendYaml-ceJQNB1O.mjs";import{a as We,i as Ge,n as Ke,r as qe,t as Je}from"./parseVariablesFromString-B2TB86Fo.mjs";import{a as Ye,c as Xe,i as Ze,l as Qe,n as $e,o as et,r as tt,s as nt,t as rt,u as it}from"./constants-C9xZJ9YW.mjs";import{n as at,t as ot}from"./fuzzyMatchColumns-C1STZ_T1.mjs";import{a as st,c as ct,d as lt,f as ut,i as dt,l as ft,n as pt,o as mt,r as ht,s as gt,t as _t,u as vt}from"./uploadPrivacyRequestsFromCsv-O6_80ZLH.mjs";import{n as yt,t as bt}from"./parseAttributesFromString-CYcxsS3n.mjs";import{t as xt}from"./readCsv--FfP8n-H.mjs";import{n as St,t as Ct}from"./pullUnstructuredSubDataPointRecommendations-B9xIDPf2.mjs";import{a as wt,i as Tt,n as Et,o as Dt,r as Ot,t as kt}from"./request-BIplTb3L.mjs";import{i as At,n as jt,r as Mt,t as Nt}from"./pullTranscendConfiguration-DFQkyoIo.mjs";import{i as Pt,n as Ft,r as K,t as It}from"./fetchAllRequests-DP24WqrP.mjs";import{a as Lt,i as Rt,n as zt,r as Bt,t as Vt}from"./pullChunkedCustomSiloOutstandingIdentifiers-CQTfWHbv.mjs";import{n as Ht,r as Ut,t as Wt}from"./syncCodePackages-Dhm5jI6B.mjs";import{t as Gt}from"./markSilentPrivacyRequests-CitXF4qq.mjs";import{a as Kt,i as qt,n as Jt,o as Yt,r as Xt,t as Zt}from"./downloadPrivacyRequestFiles-CAGrriEp.mjs";import{n as Qt,r as $t,t as en}from"./extractClientError-X9wJVqGq.mjs";import{t as tn}from"./approvePrivacyRequests-BfULMmiN.mjs";import{t as nn}from"./notifyPrivacyRequestsAdditionalTime-mpYqqBxR.mjs";import{t as rn}from"./cancelPrivacyRequests-Da7_hfc7.mjs";import{n as an,t as on}from"./bulkRestartRequests-D3NnqSRA.mjs";import{t as sn}from"./skipPreflightJobs-D09CE-vp.mjs";import{t as cn}from"./bulkRetryEnrichers-Blydm41j.mjs";import{t as ln}from"./retryRequestDataSilos-DAY3Fu3J.mjs";import{n as q,r as J,t as un}from"./streamPrivacyRequestsToCsv-C_UcaZGl.mjs";import{n as dn,r as fn,t as pn}from"./inquirer-B0OF_nRe.mjs";import{t as mn}from"./collectParquetFilesOrExit-DyZISY9X.mjs";import{t as hn}from"./collectCsvFilesOrExit-C8-Pr9Hr.mjs";import{t as gn}from"./parquetToCsvOneFile-13GirFzy.mjs";import{a as _n,i as vn,n as yn,o as bn,r as xn,s as Sn,t as Cn}from"./writeCsv-BMVkiMHM.mjs";import{t as wn}from"./skipRequestDataSilos-CDMBQH8Z.mjs";import{t as Tn}from"./removeUnverifiedRequestIdentifiers-CjgP5O-2.mjs";import{t as En}from"./updateConsentManagerVersionToLatest-B4uTgkJS.mjs";import{t as Dn}from"./uploadDataFlowsFromCsv-BTyYYQQR.mjs";import{t as On}from"./uploadCookiesFromCsv-ZG1M6Lmc.mjs";import{t as kn}from"./pullConsentManagerMetrics-CR4WwUt6.mjs";import{n as An,r as jn,t as Mn}from"./buildXdiSyncEndpoint-BR7zCF05.mjs";import{t as Nn}from"./consentManagersToBusinessEntities-DGzryQ3W.mjs";import{i as Pn,n as Fn,r as In,t as Ln}from"./uploadConsents-mr1TLN64.mjs";import{n as Rn,r as zn,t as Bn}from"./pushCronIdentifiersFromCsv-7s9hak_0.mjs";import{t as Vn}from"./markRequestDataSiloIdsCompleted-Bw_krZSS.mjs";import{t as Hn}from"./generateCrossAccountApiKeys-Cu35vcXs.mjs";import{t as Un}from"./validateTranscendAuth-Dl8UUCAQ.mjs";import{t as Wn}from"./listFiles-BPx3iDV6.mjs";import{t as Gn}from"./pullAllDatapoints-Bvv9KRR5.mjs";import{t as Kn}from"./pullManualEnrichmentIdentifiersToCsv-B0DLb0h9.mjs";import{n as qn,r as Jn,t as Yn}from"./pushManualEnrichmentIdentifiersFromCsv-h4gafAHj.mjs";import{chunk as Xn,difference as Zn}from"lodash-es";import{readFileSync as Qn,readdirSync as $n,statSync as er}from"node:fs";import{join as tr}from"node:path";import nr from"fast-glob";import Y from"colors";import{UPDATE_OR_CREATE_COOKIES as rr,buildTranscendGraphQLClient as X,createSombraGotInstance as ir,fetchAllRequestIdentifiers as ar,fetchConsentManagerId as or,makeGraphQLRequest as sr,validateSombraVersion as cr}from"@transcend-io/sdk";import{map as Z,mapSeries as lr}from"@transcend-io/utils";import{execSync as Q}from"child_process";async function $(e,t){let n=await or(e,{logger:b});await lr(Xn(t,100),async t=>{await sr(e,rr,{variables:{airgapBundleId:n,cookies:t.map(e=>({name:e.name,trackingPurposes:e.trackingPurposes&&e.trackingPurposes.length>0?e.trackingPurposes:void 0,description:e.description,service:e.service,status:e.status,attributes:e.attributes,isRegex:e.isRegex}))},logger:b})})}async function ur(e,t){let n=!1;b.info(Y.magenta(`Syncing "${t.length}" cookies...`));let r=t.filter(e=>t.filter(t=>e.name===t.name&&e.isRegex===t.isRegex).length>1);if(r.length>0)throw Error(`Failed to upload cookies as there were non-unique entries found: ${r.map(({name:e})=>e).join(`,`)}`);try{b.info(Y.magenta(`Upserting "${t.length}" new cookies...`)),await $(e,t),b.info(Y.green(`Successfully synced ${t.length} cookies!`))}catch(e){n=!0,b.error(Y.red(`Failed to create cookies! - ${e.message}`))}return!n}async function dr({auth:e,sombraAuth:t,actions:n=[],statuses:r=[],identifierSearch:a,pageLimit:o=100,concurrency:s=1,transcendUrl:c=i,createdAtBefore:l,skipRequestIdentifiers:u=!1,createdAtAfter:d,updatedAtBefore:f,updatedAtAfter:p,isTest:m}){let h=X(c,e),g=await ir(c,e,{logger:b,sombraApiKey:t,sombraUrl:process.env.SOMBRA_URL}),_=``;l&&(_+=` before ${l.toISOString()}`),d&&(_+=`${_?`, and`:``} after ${d.toISOString()}`),b.info(Y.magenta(`${n.length>0?`Pulling requests of type "${n.join(`" , "`)}"`:`Pulling all requests`}${_}`));let v=s>1&&d&&l,y=v?q(d,l,s):[{createdAtAfter:d,createdAtBefore:l}];v&&b.info(Y.magenta(`Splitting date range into ${s} parallel chunks`));let x=(await Z(y,e=>K(h,{actions:n,text:a,statuses:r,createdAtBefore:e.createdAtBefore,createdAtAfter:e.createdAtAfter,updatedAtBefore:f,updatedAtAfter:p,isTest:m}),{concurrency:v?s:1})).flat();u||await cr(h,{logger:b});let S=u?x.map(e=>({...e,requestIdentifiers:[]})):await Z(x,async e=>{let t=await ar(h,g,{filterBy:{requestId:e.id},skipSombraCheck:!0,logger:b});return{...e,requestIdentifiers:t}},{concurrency:o});return b.info(Y.magenta(`Pulled ${S.length} requests`)),{requestsWithRequestIdentifiers:S,requestsFormattedForCsv:S.map(J)}}function fr(e){try{return e?Qn(e,`utf8`):``}catch{return``}}function pr(e){return $n(e).filter(t=>er(tr(e,t)).isDirectory())}function mr(e){return e.replace(/(https?:\/\/[^\s]+)/g,`<link-omitted>`)}function hr(e){return Object.entries(e).reduce((e,[t,n])=>n!=null&&n!==``&&!(Array.isArray(n)&&n.length===0)&&!(typeof n==`object`&&Object.keys(n).length===0)?Object.assign(e,{[t]:n}):e,{})}function gr({baseBranch:e,rootDirectory:t,githubRepo:n,excludedGlob:r=[],fileBlockList:i=[]}){Q(`git fetch origin ${e}`);let a=Q(`git ls-remote ${n} "refs/heads/${e}" | cut -f 1`,{encoding:`utf-8`}).split(`
1
+ import{i as e,n as t,r as n,t as r}from"./enums-OiLcZ26O.mjs";import{a as i,c as a,d as o,f as s,g as c,h as l,i as u,l as d,m as f,n as p,o as m,p as h,r as g,s as _,t as v,u as y}from"./constants-CAOyAsNX.mjs";import{t as b}from"./logger-Ckep4QXn.mjs";import{$ as x,A as S,B as ee,C as te,D as ne,E as re,F as ie,G as ae,H as oe,I as se,J as ce,K as C,L as w,M as T,N as E,O as D,P as O,Q as k,R as A,S as j,T as M,U as N,V as P,W as F,X as I,Y as L,Z as R,_ as z,a as B,at as V,b as H,c as U,ct as W,d as G,dt as le,et as ue,f as de,ft as fe,g as pe,h as me,i as he,it as ge,j as _e,k as ve,l as ye,lt as be,m as xe,mt as Se,n as Ce,nt as we,o as Te,ot as Ee,p as De,pt as Oe,q as ke,r as Ae,rt as je,s as Me,st as Ne,t as Pe,tt as Fe,u as Ie,ut as Le,v as Re,w as ze,x as Be,y as Ve,z as He}from"./codecs-DJFlZLGT.mjs";import{a as Ue,i as We,n as Ge,r as Ke,t as qe}from"./readTranscendYaml-bL1qFPqv.mjs";import{i as Je,n as Ye,r as Xe,t as Ze}from"./mergeTranscendInputs-DjPe49yR.mjs";import{a as Qe,c as $e,i as et,l as tt,n as nt,o as rt,r as it,s as at,t as ot,u as st}from"./constants-C9xZJ9YW.mjs";import{n as ct,t as lt}from"./fuzzyMatchColumns-C1STZ_T1.mjs";import{a as ut,c as dt,d as ft,f as pt,i as mt,l as ht,n as gt,o as _t,r as vt,s as yt,t as bt,u as xt}from"./uploadPrivacyRequestsFromCsv-CX7JRYjH.mjs";import{n as St,t as Ct}from"./parseAttributesFromString-CYcxsS3n.mjs";import{t as wt}from"./readCsv--FfP8n-H.mjs";import{n as Tt,t as Et}from"./pullUnstructuredSubDataPointRecommendations-B9xIDPf2.mjs";import{a as Dt,i as Ot,n as kt,o as At,r as jt,t as Mt}from"./request-BIplTb3L.mjs";import{i as Nt,n as Pt,r as Ft,t as It}from"./pullTranscendConfiguration-DFQkyoIo.mjs";import{i as Lt,n as Rt,r as K,t as zt}from"./fetchAllRequests-DP24WqrP.mjs";import{a as Bt,i as Vt,n as Ht,r as Ut,t as Wt}from"./pullChunkedCustomSiloOutstandingIdentifiers-rKefgKKC.mjs";import{n as Gt,r as Kt,t as qt}from"./syncCodePackages-Dhm5jI6B.mjs";import{t as Jt}from"./markSilentPrivacyRequests-DXLiS2jH.mjs";import{a as Yt,i as Xt,n as Zt,o as Qt,r as $t,t as en}from"./downloadPrivacyRequestFiles-DSOTFVU6.mjs";import{n as tn,r as nn,t as rn}from"./extractClientError-X9wJVqGq.mjs";import{t as an}from"./approvePrivacyRequests-D1S2AYud.mjs";import{t as on}from"./notifyPrivacyRequestsAdditionalTime-DPp0MyfT.mjs";import{t as sn}from"./cancelPrivacyRequests-DM3Zamqd.mjs";import{n as cn,t as ln}from"./bulkRestartRequests-NAASQwvP.mjs";import{t as un}from"./skipPreflightJobs-C1go-m8K.mjs";import{t as dn}from"./bulkRetryEnrichers-BEEVKtCH.mjs";import{t as fn}from"./retryRequestDataSilos-DATDTDin.mjs";import{n as q,r as J,t as pn}from"./streamPrivacyRequestsToCsv-7S52MmdS.mjs";import{n as mn,r as hn,t as gn}from"./inquirer-B0OF_nRe.mjs";import{t as _n}from"./parseVariablesFromString-B4TUkJRF.mjs";import{t as vn}from"./collectParquetFilesOrExit-DVS9_OSv.mjs";import{t as yn}from"./collectCsvFilesOrExit-BPo8Mjy7.mjs";import{t as bn}from"./parquetToCsvOneFile-0O4iLz0t.mjs";import{a as xn,i as Sn,n as Cn,o as wn,r as Tn,s as En,t as Dn}from"./writeCsv-DMw5OmWp.mjs";import{t as On}from"./skipRequestDataSilos-1ksexte3.mjs";import{t as kn}from"./removeUnverifiedRequestIdentifiers-BUJZoJD9.mjs";import{t as An}from"./updateConsentManagerVersionToLatest-CYGRh2Mf.mjs";import{t as jn}from"./uploadDataFlowsFromCsv-0oDEouPJ.mjs";import{t as Mn}from"./uploadCookiesFromCsv-D33lINd-.mjs";import{t as Nn}from"./pullConsentManagerMetrics-C41UhU8u.mjs";import{n as Pn,r as Fn,t as In}from"./buildXdiSyncEndpoint-B4l998cU.mjs";import{t as Ln}from"./consentManagersToBusinessEntities-rf8_xu71.mjs";import{i as Rn,n as zn,r as Bn,t as Vn}from"./uploadConsents-DxzUYFP_.mjs";import{n as Hn,r as Un,t as Wn}from"./pushCronIdentifiersFromCsv-Dj-KEFpQ.mjs";import{t as Gn}from"./markRequestDataSiloIdsCompleted-CDV0Ppv2.mjs";import{t as Kn}from"./generateCrossAccountApiKeys-C3mCgp6X.mjs";import{t as qn}from"./validateTranscendAuth-CAO5ktnu.mjs";import{t as Jn}from"./listFiles-C5kubvdN.mjs";import{t as Yn}from"./pullAllDatapoints-DJno8LkB.mjs";import{t as Xn}from"./pullManualEnrichmentIdentifiersToCsv-Cbk-7ztw.mjs";import{n as Zn,r as Qn,t as $n}from"./pushManualEnrichmentIdentifiersFromCsv-CY4d1jQy.mjs";import{chunk as er,difference as tr}from"lodash-es";import{readFileSync as nr,readdirSync as rr,statSync as ir}from"node:fs";import{join as Y}from"node:path";import ar from"fast-glob";import X from"colors";import{UPDATE_OR_CREATE_COOKIES as or,buildTranscendGraphQLClient as sr,createSombraGotInstance as cr,fetchAllRequestIdentifiers as lr,fetchConsentManagerId as ur,makeGraphQLRequest as dr,validateSombraVersion as fr}from"@transcend-io/sdk";import{map as Z,mapSeries as pr}from"@transcend-io/utils";import{execSync as Q}from"child_process";async function $(e,t){let n=await ur(e,{logger:b});await pr(er(t,100),async t=>{await dr(e,or,{variables:{airgapBundleId:n,cookies:t.map(e=>({name:e.name,trackingPurposes:e.trackingPurposes&&e.trackingPurposes.length>0?e.trackingPurposes:void 0,description:e.description,service:e.service,status:e.status,attributes:e.attributes,isRegex:e.isRegex}))},logger:b})})}async function mr(e,t){let n=!1;b.info(X.magenta(`Syncing "${t.length}" cookies...`));let r=t.filter(e=>t.filter(t=>e.name===t.name&&e.isRegex===t.isRegex).length>1);if(r.length>0)throw Error(`Failed to upload cookies as there were non-unique entries found: ${r.map(({name:e})=>e).join(`,`)}`);try{b.info(X.magenta(`Upserting "${t.length}" new cookies...`)),await $(e,t),b.info(X.green(`Successfully synced ${t.length} cookies!`))}catch(e){n=!0,b.error(X.red(`Failed to create cookies! - ${e.message}`))}return!n}async function hr({auth:e,sombraAuth:t,actions:n=[],statuses:r=[],identifierSearch:a,pageLimit:o=100,concurrency:s=1,transcendUrl:c=i,createdAtBefore:l,skipRequestIdentifiers:u=!1,createdAtAfter:d,updatedAtBefore:f,updatedAtAfter:p,isTest:m}){let h=sr(c,e),g=await cr(c,e,{logger:b,sombraApiKey:t,sombraUrl:process.env.SOMBRA_URL}),_=``;l&&(_+=` before ${l.toISOString()}`),d&&(_+=`${_?`, and`:``} after ${d.toISOString()}`),b.info(X.magenta(`${n.length>0?`Pulling requests of type "${n.join(`" , "`)}"`:`Pulling all requests`}${_}`));let v=s>1&&d&&l,y=v?q(d,l,s):[{createdAtAfter:d,createdAtBefore:l}];v&&b.info(X.magenta(`Splitting date range into ${s} parallel chunks`));let x=(await Z(y,e=>K(h,{actions:n,text:a,statuses:r,createdAtBefore:e.createdAtBefore,createdAtAfter:e.createdAtAfter,updatedAtBefore:f,updatedAtAfter:p,isTest:m}),{concurrency:v?s:1})).flat();u||await fr(h,{logger:b});let S=u?x.map(e=>({...e,requestIdentifiers:[]})):await Z(x,async e=>{let t=await lr(h,g,{filterBy:{requestId:e.id},skipSombraCheck:!0,logger:b});return{...e,requestIdentifiers:t}},{concurrency:o});return b.info(X.magenta(`Pulled ${S.length} requests`)),{requestsWithRequestIdentifiers:S,requestsFormattedForCsv:S.map(J)}}function gr(e){try{return e?nr(e,`utf8`):``}catch{return``}}function _r(e){return rr(e).filter(t=>ir(Y(e,t)).isDirectory())}function vr(e){return e.replace(/(https?:\/\/[^\s]+)/g,`<link-omitted>`)}function yr(e){return Object.entries(e).reduce((e,[t,n])=>n!=null&&n!==``&&!(Array.isArray(n)&&n.length===0)&&!(typeof n==`object`&&Object.keys(n).length===0)?Object.assign(e,{[t]:n}):e,{})}function br({baseBranch:e,rootDirectory:t,githubRepo:n,excludedGlob:r=[],fileBlockList:i=[]}){Q(`git fetch origin ${e}`);let a=Q(`git ls-remote ${n} "refs/heads/${e}" | cut -f 1`,{encoding:`utf-8`}).split(`
2
2
  `)[0],o=Q(`git rev-parse HEAD`,{encoding:`utf-8`}).split(`
3
- `)[0];if(!a||!o)throw Error(`FAILED TO FIND COMMIT RANGE`);let s=Zn(Q(`git fetch && git diff --name-only "${e||a}...${o}" -- ${t}`,{encoding:`utf-8`}).split(`
4
- `).filter(e=>e),i),c=r.length>0?nr.sync(s,{ignore:r}):s,l={};return c.forEach(e=>{l[e]=Q(`git show ${o}:${e}`,{encoding:`utf-8`})}),{changedFiles:s,fileDiffs:l,repoName:n.split(`/`).pop().split(`.`)[0],commit:o}}export{v as ADMIN_DASH,p as ADMIN_DASH_DATAPOINTS,g as ADMIN_DASH_INTEGRATIONS,kt as APPROVE_PRIVACY_REQUEST,At as ASSESSMENT_TEMPLATES,Ae as ActionInput,be as ActionItemCollectionInput,Ee as ActionItemInput,pe as ApiKeyInput,B as AssessmentAnswerOptionInput,Se as AssessmentDisplayLogicInput,Oe as AssessmentInput,U as AssessmentNestedRuleInput,_e as AssessmentResourceInput,Me as AssessmentRetentionScheduleInput,G as AssessmentRuleInput,ue as AssessmentSectionInput,we as AssessmentSectionQuestionInput,ye as AssessmentTemplateInput,dt as AttestedExtraIdentifiers,fe as AttributeInput,de as AttributePreview,z as AttributeValueInput,rt as BLANK,$e as BULK_APPLY,Pe as BusinessEntityInput,Et as CANCEL_PRIVACY_REQUEST,tt as CAN_APPLY_IN_BULK,Ze as CachedFileState,Ye as CachedRequestState,Le as CodePackageInput,H as CodePackageSdk,et as ColumnName,Ie as ConsentManageExperienceInput,j as ConsentManagerInput,te as ConsentManagerServiceMetadata,Fe as ConsentPreferenceTopic,M as ConsentPreferenceTopicOptionValue,re as ConsentPurpose,ne as CookieCsvInput,D as CookieInput,zt as CronIdentifier,Rn as CronIdentifierPush,Bt as CronPartition,u as DEBUG,i as DEFAULT_TRANSCEND_API,m as DEFAULT_TRANSCEND_API_KEY,_ as DEFAULT_TRANSCEND_CONSENT_API,Nt as DEFAULT_TRANSCEND_PULL_RESOURCES,ge as DataCategoryGuessInput,S as DataCategoryInput,he as DataCategoryPreviewInput,T as DataCategoryRecommendationInput,E as DataFlowCsvInput,O as DataFlowInput,ie as DataSiloInput,se as DataSubjectInput,w as DatapointInput,St as ENTRY_COUNT,qn as EnrichPrivacyRequest,A as EnricherInput,Re as FieldInput,nt as IDENTIFIER_BLOCK_LIST,Mn as IP_ADDRESS_REGEX,Xe as IS_REQUIRED,ee as IdentifierInput,P as ImportOnetrustAssessmentsInput,Xt as IntlMessage,oe as IntlMessageInput,Qe as NONE,Ot as NOTIFY_ADDITIONAL_TIME,r as OneTrustFileFormat,t as OneTrustPullResource,n as OneTrustPullSource,bt as ParsedAttributeInput,N as PartitionInput,F as PolicyInput,ae as PreferenceWorkflowConfigInput,C as PreferenceWorkflowConfigPurposeInput,Te as PrivacyCenterInput,It as PrivacyRequest,st as PrivacyRequestInput,Qt as PrivacyRequestResponse,ce as ProcessingActivityInput,L as ProcessingPurposeInput,I as ProcessingPurposePreviewInput,R as PromptAVendorEmailSettings,Ln as PurposeMap,Tt as REQUESTS,wt as REQUESTS_COUNT,a as RETRYABLE_BATCH_STATUSES,k as RegionInput,x as RepositoryInput,qt as RequestFileMetadata,Kt as RequestFileMetadataResponse,Ft as RequestPurposeTrigger,le as RiskAssignmentInput,je as RiskLogicInput,d as SCOPES_BY_TITLE,y as SCOPE_TITLES,xe as SiloDiscoveryResultInput,De as SoftwareDevelopmentKitInput,me as StoredApiKey,it as SuccessfulRequest,o as TR_PULL_RESOURCE_SCOPE_MAP,s as TR_PUSH_RESOURCE_SCOPE_MAP,h as TR_YML_RESOURCE_TO_FIELD_NAME,V as TeamInput,Ce as TemplateInput,ke as TranscendInput,e as TranscendPullResource,Dt as UPDATE_PRIVACY_REQUEST,Fn as USP_STRING_REGEX,Ue as VARIABLE_PARAMETERS_NAME,Ve as VARIABLE_PARAMETERS_REGEXP,W as VendorInput,ve as WebhookHeader,Ne as WorkflowConfigInput,Cn as appendCsvRowsOrdered,yn as appendCsvSync,tn as approvePrivacyRequests,An as buildXdiSyncEndpoint,on as bulkRestartRequests,cn as bulkRetryEnrichers,rn as cancelPrivacyRequests,hn as collectCsvFilesOrExit,mn as collectParquetFilesOrExit,Nn as consentManagersToBusinessEntities,Wt as createCodePackage,Pn as createConsentToken,l as description,jn as domainToHost,Zt as downloadPrivacyRequestFiles,Jn as enrichPrivacyRequest,We as ensureAllDataSubjectsExist,en as extractClientError,Mt as fetchAllAssessmentTemplates,K as fetchAllRequests,Lt as fetchRequestDataSiloActiveCount,Pt as fetchRequestsTotalCount,hr as filterNullishValuesFromObject,vt as filterRows,J as formatRequestForCsv,ot as fuzzyMatchColumns,at as fuzzySearch,Hn as generateCrossAccountApiKeys,Yt as getFileMetadataForPrivacyRequests,gr as getGitFilesThatChanged,lt as getUniqueValuesForColumn,xn as initCsvFile,pn as inquirerAutoComplete,dn as inquirerConfirmBoolean,fn as inquirerConfirmText,pr as listDirectories,Wn as listFiles,pt as mapColumnsToAttributes,ht as mapColumnsToIdentifiers,ft as mapCsvColumnsToApi,mt as mapCsvRowsToRequestInputs,ut as mapEnumValues,ct as mapRequestEnumValues,zn as markCronIdentifierCompleted,Vn as markRequestDataSiloIdsCompleted,Gt as markSilentPrivacyRequests,Ke as mergeTranscendInputs,f as name,gt as normalizeIdentifierValue,nn as notifyPrivacyRequestsAdditionalTime,gn as parquetToCsvOneFile,yt as parseAttributesFromString,vn as parseFilePath,Je as parseVariablesFromString,Gn as pullAllDatapoints,Vt as pullChunkedCustomSiloOutstandingIdentifiers,kn as pullConsentManagerMetrics,Rt as pullCronPageOfIdentifiers,Kn as pullManualEnrichmentIdentifiersToCsv,dr as pullPrivacyRequests,jt as pullTranscendConfiguration,Ct as pullUnstructuredSubDataPointRecommendations,Bn as pushCronIdentifiersFromCsv,Yn as pushManualEnrichmentIdentifiersFromCsv,xt as readCsv,fr as readSafe,He as readTranscendYaml,mr as removeLinks,Tn as removeUnverifiedRequestIdentifiers,Be as replaceVariablesInYaml,an as restartPrivacyRequest,ln as retryRequestDataSilos,sn as skipPreflightJobs,wn as skipRequestDataSilos,q as splitDateRange,Jt as streamPrivacyRequestFiles,un as streamPrivacyRequestsToCsv,$t as submitPrivacyRequest,Ht as syncCodePackages,qe as syncConfigurationToTranscend,ur as syncCookies,Ge as syncDataSilos,Ut as updateCodePackages,En as updateConsentManagerVersionToLatest,$ as updateOrCreateCookies,In as uploadConsents,On as uploadCookiesFromCsv,Dn as uploadDataFlowsFromCsv,_t as uploadPrivacyRequestsFromCsv,Un as validateTranscendAuth,c as version,_n as writeCsv,bn as writeCsvSync,Sn as writeLargeCsv,ze as writeTranscendYaml};
3
+ `)[0];if(!a||!o)throw Error(`FAILED TO FIND COMMIT RANGE`);let s=tr(Q(`git fetch && git diff --name-only "${e||a}...${o}" -- ${t}`,{encoding:`utf-8`}).split(`
4
+ `).filter(e=>e),i),c=r.length>0?ar.sync(s,{ignore:r}):s,l={};return c.forEach(e=>{l[e]=Q(`git show ${o}:${e}`,{encoding:`utf-8`})}),{changedFiles:s,fileDiffs:l,repoName:n.split(`/`).pop().split(`.`)[0],commit:o}}export{v as ADMIN_DASH,p as ADMIN_DASH_DATAPOINTS,g as ADMIN_DASH_INTEGRATIONS,Mt as APPROVE_PRIVACY_REQUEST,Nt as ASSESSMENT_TEMPLATES,Pe as ActionInput,Ce as ActionItemCollectionInput,Ae as ActionItemInput,he as ApiKeyInput,B as AssessmentAnswerOptionInput,Te as AssessmentDisplayLogicInput,Me as AssessmentInput,U as AssessmentNestedRuleInput,ye as AssessmentResourceInput,Ie as AssessmentRetentionScheduleInput,G as AssessmentRuleInput,de as AssessmentSectionInput,De as AssessmentSectionQuestionInput,xe as AssessmentTemplateInput,mt as AttestedExtraIdentifiers,me as AttributeInput,pe as AttributePreview,z as AttributeValueInput,ot as BLANK,nt as BULK_APPLY,Re as BusinessEntityInput,kt as CANCEL_PRIVACY_REQUEST,it as CAN_APPLY_IN_BULK,et as CachedFileState,Qe as CachedRequestState,Ve as CodePackageInput,H as CodePackageSdk,rt as ColumnName,Be as ConsentManageExperienceInput,j as ConsentManagerInput,te as ConsentManagerServiceMetadata,ze as ConsentPreferenceTopic,M as ConsentPreferenceTopicOptionValue,re as ConsentPurpose,ne as CookieCsvInput,D as CookieInput,Ht as CronIdentifier,Hn as CronIdentifierPush,Ut as CronPartition,u as DEBUG,i as DEFAULT_TRANSCEND_API,m as DEFAULT_TRANSCEND_API_KEY,_ as DEFAULT_TRANSCEND_CONSENT_API,It as DEFAULT_TRANSCEND_PULL_RESOURCES,ve as DataCategoryGuessInput,S as DataCategoryInput,_e as DataCategoryPreviewInput,T as DataCategoryRecommendationInput,E as DataFlowCsvInput,O as DataFlowInput,ie as DataSiloInput,se as DataSubjectInput,w as DatapointInput,A as DeletionDependencies,He as DeletionDependency,ee as DeletionDependencyInput,P as DeletionDependencyReset,Tt as ENTRY_COUNT,Zn as EnrichPrivacyRequest,oe as EnricherInput,N as FieldInput,at as IDENTIFIER_BLOCK_LIST,In as IP_ADDRESS_REGEX,$e as IS_REQUIRED,F as IdentifierInput,ae as ImportOnetrustAssessmentsInput,$t as IntlMessage,C as IntlMessageInput,tt as NONE,jt as NOTIFY_ADDITIONAL_TIME,r as OneTrustFileFormat,t as OneTrustPullResource,n as OneTrustPullSource,Ct as ParsedAttributeInput,ke as PartitionInput,ce as PolicyInput,L as PreferenceWorkflowConfigInput,I as PreferenceWorkflowConfigPurposeInput,R as PrivacyCenterInput,zt as PrivacyRequest,ut as PrivacyRequestInput,tn as PrivacyRequestResponse,k as ProcessingActivityInput,x as ProcessingPurposeInput,ue as ProcessingPurposePreviewInput,Fe as PromptAVendorEmailSettings,Vn as PurposeMap,Ot as REQUESTS,Dt as REQUESTS_COUNT,a as RETRYABLE_BATCH_STATUSES,we as RegionInput,je as RepositoryInput,Xt as RequestFileMetadata,Yt as RequestFileMetadataResponse,Rt as RequestPurposeTrigger,ge as RiskAssignmentInput,V as RiskLogicInput,d as SCOPES_BY_TITLE,y as SCOPE_TITLES,Ee as SiloDiscoveryResultInput,Ne as SoftwareDevelopmentKitInput,W as StoredApiKey,st as SuccessfulRequest,o as TR_PULL_RESOURCE_SCOPE_MAP,s as TR_PUSH_RESOURCE_SCOPE_MAP,h as TR_YML_RESOURCE_TO_FIELD_NAME,be as TeamInput,Le as TemplateInput,le as TranscendInput,e as TranscendPullResource,At as UPDATE_PRIVACY_REQUEST,zn as USP_STRING_REGEX,qe as VARIABLE_PARAMETERS_NAME,Ge as VARIABLE_PARAMETERS_REGEXP,fe as VendorInput,Oe as WebhookHeader,Se as WorkflowConfigInput,Dn as appendCsvRowsOrdered,Cn as appendCsvSync,an as approvePrivacyRequests,Pn as buildXdiSyncEndpoint,ln as bulkRestartRequests,dn as bulkRetryEnrichers,sn as cancelPrivacyRequests,yn as collectCsvFilesOrExit,vn as collectParquetFilesOrExit,Ln as consentManagersToBusinessEntities,qt as createCodePackage,Rn as createConsentToken,l as description,Fn as domainToHost,en as downloadPrivacyRequestFiles,Qn as enrichPrivacyRequest,Je as ensureAllDataSubjectsExist,rn as extractClientError,Ft as fetchAllAssessmentTemplates,K as fetchAllRequests,Bt as fetchRequestDataSiloActiveCount,Lt as fetchRequestsTotalCount,yr as filterNullishValuesFromObject,xt as filterRows,J as formatRequestForCsv,lt as fuzzyMatchColumns,ct as fuzzySearch,Kn as generateCrossAccountApiKeys,Qt as getFileMetadataForPrivacyRequests,br as getGitFilesThatChanged,ft as getUniqueValuesForColumn,Tn as initCsvFile,gn as inquirerAutoComplete,mn as inquirerConfirmBoolean,hn as inquirerConfirmText,_r as listDirectories,Jn as listFiles,gt as mapColumnsToAttributes,vt as mapColumnsToIdentifiers,ht as mapCsvColumnsToApi,_t as mapCsvRowsToRequestInputs,pt as mapEnumValues,dt as mapRequestEnumValues,Un as markCronIdentifierCompleted,Gn as markRequestDataSiloIdsCompleted,Jt as markSilentPrivacyRequests,Ze as mergeTranscendInputs,f as name,yt as normalizeIdentifierValue,on as notifyPrivacyRequestsAdditionalTime,bn as parquetToCsvOneFile,St as parseAttributesFromString,Sn as parseFilePath,_n as parseVariablesFromString,Yn as pullAllDatapoints,Wt as pullChunkedCustomSiloOutstandingIdentifiers,Nn as pullConsentManagerMetrics,Vt as pullCronPageOfIdentifiers,Xn as pullManualEnrichmentIdentifiersToCsv,hr as pullPrivacyRequests,Pt as pullTranscendConfiguration,Et as pullUnstructuredSubDataPointRecommendations,Wn as pushCronIdentifiersFromCsv,$n as pushManualEnrichmentIdentifiersFromCsv,wt as readCsv,gr as readSafe,Ke as readTranscendYaml,vr as removeLinks,kn as removeUnverifiedRequestIdentifiers,We as replaceVariablesInYaml,cn as restartPrivacyRequest,fn as retryRequestDataSilos,un as skipPreflightJobs,On as skipRequestDataSilos,q as splitDateRange,Zt as streamPrivacyRequestFiles,pn as streamPrivacyRequestsToCsv,nn as submitPrivacyRequest,Gt as syncCodePackages,Ye as syncConfigurationToTranscend,mr as syncCookies,Xe as syncDataSilos,Kt as updateCodePackages,An as updateConsentManagerVersionToLatest,$ as updateOrCreateCookies,Bn as uploadConsents,Mn as uploadCookiesFromCsv,jn as uploadDataFlowsFromCsv,bt as uploadPrivacyRequestsFromCsv,qn as validateTranscendAuth,c as version,xn as writeCsv,wn as writeCsvSync,En as writeLargeCsv,Ue as writeTranscendYaml};
5
5
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/lib/graphql/syncCookies.ts","../src/lib/requests/pullPrivacyRequests.ts","../src/lib/helpers/readSafe.ts","../src/lib/api-keys/listDirectories.ts","../src/lib/ai/removeLinks.ts","../src/lib/ai/filterNullishValuesFromObject.ts","../src/lib/ai/getGitFilesThatChanged.ts"],"sourcesContent":["// import { keyBy } from 'lodash-es';\nimport {\n fetchConsentManagerId,\n makeGraphQLRequest,\n UPDATE_OR_CREATE_COOKIES,\n} from '@transcend-io/sdk';\nimport { mapSeries } from '@transcend-io/utils';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { chunk } from 'lodash-es';\n\nimport { CookieInput } from '../../codecs.js';\nimport { logger } from '../../logger.js';\n\nconst MAX_PAGE_SIZE = 100;\n\n/**\n * Update or create cookies that already existed\n *\n * @param client - GraphQL client\n * @param cookieInputs - List of cookie input\n */\nexport async function updateOrCreateCookies(\n client: GraphQLClient,\n cookieInputs: CookieInput[],\n): Promise<void> {\n const airgapBundleId = await fetchConsentManagerId(client, { logger });\n\n // TODO: https://transcend.height.app/T-19841 - add with custom purposes\n // const purposes = await fetchAllPurposes(client);\n // const purposeNameToId = keyBy(purposes, 'name');\n\n await mapSeries(chunk(cookieInputs, MAX_PAGE_SIZE), async (page) => {\n await makeGraphQLRequest(client, UPDATE_OR_CREATE_COOKIES, {\n variables: {\n airgapBundleId,\n cookies: page.map((cookie) => ({\n name: cookie.name,\n trackingPurposes:\n cookie.trackingPurposes && cookie.trackingPurposes.length > 0\n ? cookie.trackingPurposes\n : undefined,\n // TODO: https://transcend.height.app/T-19841 - add with custom purposes\n // purposeIds: cookie.trackingPurposes\n // ? cookie.trackingPurposes\n // .filter((purpose) => purpose !== 'Unknown')\n // .map((purpose) => purposeNameToId[purpose].id)\n // : undefined,\n description: cookie.description,\n service: cookie.service,\n status: cookie.status,\n attributes: cookie.attributes,\n isRegex: cookie.isRegex,\n // TODO: https://transcend.height.app/T-23718\n // owners,\n // teams,\n })),\n },\n logger,\n });\n });\n}\n\n/**\n * Sync the set of cookies from the YML interface into the product\n *\n * @param client - GraphQL client\n * @param cookies - Cookies to sync\n * @returns True upon success, false upon failure\n */\nexport async function syncCookies(client: GraphQLClient, cookies: CookieInput[]): Promise<boolean> {\n let encounteredError = false;\n logger.info(colors.magenta(`Syncing \"${cookies.length}\" cookies...`));\n\n // Ensure no duplicates are being uploaded\n const notUnique = cookies.filter(\n (cookie) =>\n cookies.filter((cook) => cookie.name === cook.name && cookie.isRegex === cook.isRegex)\n .length > 1,\n );\n if (notUnique.length > 0) {\n throw new Error(\n `Failed to upload cookies as there were non-unique entries found: ${notUnique\n .map(({ name }) => name)\n .join(',')}`,\n );\n }\n\n try {\n logger.info(colors.magenta(`Upserting \"${cookies.length}\" new cookies...`));\n await updateOrCreateCookies(client, cookies);\n logger.info(colors.green(`Successfully synced ${cookies.length} cookies!`));\n } catch (err) {\n encounteredError = true;\n logger.error(colors.red(`Failed to create cookies! - ${err.message}`));\n }\n\n return !encounteredError;\n}\n","import { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport {\n buildTranscendGraphQLClient,\n createSombraGotInstance,\n fetchAllRequestIdentifiers,\n validateSombraVersion,\n type RequestIdentifier,\n} from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport colors from 'colors';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\nimport { fetchAllRequests } from '../graphql/index.js';\nimport { formatRequestForCsv, CsvRow, ExportedPrivacyRequest } from './formatRequestForCsv.js';\nimport { splitDateRange } from './splitDateRange.js';\n\n/**\n * Pull down a list of privacy requests\n *\n * @param options - Options\n * @returns The requests with request identifiers and requests formatted for CSV\n */\nexport async function pullPrivacyRequests({\n auth,\n sombraAuth,\n actions = [],\n statuses = [],\n identifierSearch,\n pageLimit = 100,\n concurrency = 1,\n transcendUrl = DEFAULT_TRANSCEND_API,\n createdAtBefore,\n skipRequestIdentifiers = false,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n isTest,\n}: {\n /** Transcend API key authentication */\n auth: string;\n /** Search for a specific identifier */\n identifierSearch?: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Statuses to filter on */\n statuses?: RequestStatus[];\n /** The request action to fetch */\n actions?: RequestAction[];\n /** Page limit when fetching requests */\n pageLimit?: number;\n /** Number of parallel date-range chunks */\n concurrency?: number;\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Filter for requests updated before this date */\n updatedAtBefore?: Date;\n /** Filter for requests updated after this date */\n updatedAtAfter?: Date;\n /** Return test requests */\n isTest?: boolean;\n /** Skip fetching request identifier */\n skipRequestIdentifiers?: boolean;\n}): Promise<{\n /** All request information with attached identifiers */\n requestsWithRequestIdentifiers: ExportedPrivacyRequest[];\n /** Requests that are formatted for CSV */\n requestsFormattedForCsv: CsvRow[];\n}> {\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n const sombra = await createSombraGotInstance(transcendUrl, auth, {\n logger,\n sombraApiKey: sombraAuth,\n sombraUrl: process.env.SOMBRA_URL,\n });\n\n // Log date range\n let dateRange = '';\n if (createdAtBefore) {\n dateRange += ` before ${createdAtBefore.toISOString()}`;\n }\n if (createdAtAfter) {\n dateRange += `${dateRange ? ', and' : ''} after ${createdAtAfter.toISOString()}`;\n }\n logger.info(\n colors.magenta(\n `${\n actions.length > 0\n ? `Pulling requests of type \"${actions.join('\" , \"')}\"`\n : 'Pulling all requests'\n }${dateRange}`,\n ),\n );\n\n // Split into parallel date-range chunks when possible\n const useChunks = concurrency > 1 && createdAtAfter && createdAtBefore;\n const chunks = useChunks\n ? splitDateRange(createdAtAfter, createdAtBefore, concurrency)\n : [{ createdAtAfter, createdAtBefore }];\n\n if (useChunks) {\n logger.info(colors.magenta(`Splitting date range into ${concurrency} parallel chunks`));\n }\n\n // Fetch requests across all chunks in parallel\n const chunkResults = await map(\n chunks,\n (chunk) =>\n fetchAllRequests(client, {\n actions,\n text: identifierSearch,\n statuses,\n createdAtBefore: chunk.createdAtBefore,\n createdAtAfter: chunk.createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n isTest,\n }),\n { concurrency: useChunks ? concurrency : 1 },\n );\n const requests = chunkResults.flat();\n\n // Validate Sombra version once before bulk-fetching identifiers\n if (!skipRequestIdentifiers) {\n await validateSombraVersion(client, { logger });\n }\n\n // Fetch the request identifiers for those requests\n const requestsWithRequestIdentifiers = skipRequestIdentifiers\n ? requests.map((request) => ({\n ...request,\n requestIdentifiers: [] as RequestIdentifier[],\n }))\n : await map(\n requests,\n async (request) => {\n const requestIdentifiers = await fetchAllRequestIdentifiers(client, sombra, {\n filterBy: { requestId: request.id },\n skipSombraCheck: true,\n logger,\n });\n return {\n ...request,\n requestIdentifiers,\n };\n },\n {\n concurrency: pageLimit,\n },\n );\n\n logger.info(colors.magenta(`Pulled ${requestsWithRequestIdentifiers.length} requests`));\n\n const data = requestsWithRequestIdentifiers.map(formatRequestForCsv);\n\n return { requestsWithRequestIdentifiers, requestsFormattedForCsv: data };\n}\n","import { readFileSync } from 'node:fs';\n\n/**\n * Safely reads the contents of a file as a UTF-8 string.\n * Returns an empty string if the path is not provided or if reading fails.\n *\n * @param p - The path to the file to read.\n * @returns The file contents as a string, or an empty string on error.\n */\nexport function readSafe(p?: string): string {\n try {\n return p ? readFileSync(p, 'utf8') : '';\n } catch {\n return '';\n }\n}\n","import { readdirSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\n\n/**\n * List the folders in a directory\n *\n * @param startDir - The base directory to list from\n * @returns The list of folders in that directory\n */\nexport function listDirectories(startDir: string): string[] {\n return readdirSync(startDir).filter((entryName) =>\n statSync(join(startDir, entryName)).isDirectory(),\n );\n}\n","/**\n * Remove links from a string\n *\n * @param inputString - String\n * @returns String without links\n */\nexport function removeLinks(inputString: string): string {\n const regex = /(https?:\\/\\/[^\\s]+)/g;\n return inputString.replace(regex, '<link-omitted>');\n}\n","import { ObjByString } from '@transcend-io/type-utils';\n\n/**\n * Given an object, remove all keys that are null-ish\n *\n * @param obj - Object\n * @returns Object with null-ish values removed\n */\nexport function filterNullishValuesFromObject<T extends ObjByString>(obj: T): T {\n return Object.entries(obj).reduce(\n (acc, [k, v]) =>\n v !== null &&\n v !== undefined &&\n v !== '' &&\n !(Array.isArray(v) && v.length === 0) &&\n !(typeof v === 'object' && Object.keys(v).length === 0)\n ? Object.assign(acc, { [k]: v })\n : acc,\n {} as T,\n );\n}\n","import { execSync } from 'child_process';\n\nimport fastGlob from 'fast-glob';\nimport { difference } from 'lodash-es';\n\n/**\n * Function thats gets the git files that have changed\n * and returns the code\n *\n * @param options - Options\n * @returns Changes files and diffs\n */\nexport function getGitFilesThatChanged({\n baseBranch,\n rootDirectory,\n githubRepo,\n excludedGlob = [],\n fileBlockList = [],\n}: {\n /** Base branch */\n baseBranch: string;\n /** Github repo name */\n githubRepo: string;\n /** Root directory */\n rootDirectory: string;\n /** A glob that excludes files */\n excludedGlob?: string[];\n /** Block list of files to not process */\n fileBlockList?: string[];\n}): {\n /** The list of files that changed */\n changedFiles: string[];\n /** Github repo name */\n repoName: string;\n /** Current commit */\n commit: string;\n /** File diffs */\n fileDiffs: { [k in string]: string };\n} {\n // Pull base branch\n execSync(`git fetch origin ${baseBranch}`);\n\n // Latest commit on base branch. If we are on the base branch, we take the prior commit\n const latestBasedCommit = execSync(\n `git ls-remote ${githubRepo} \"refs/heads/${baseBranch}\" | cut -f 1`,\n { encoding: 'utf-8' },\n ).split('\\n')[0];\n\n // This commit\n const latestThisCommit = execSync('git rev-parse HEAD', {\n encoding: 'utf-8',\n }).split('\\n')[0];\n\n // Ensure commits are present\n if (!latestBasedCommit || !latestThisCommit) {\n throw new Error('FAILED TO FIND COMMIT RANGE');\n }\n\n // Get the diff between the given branch and base branch\n const diff = execSync(\n `git fetch && git diff --name-only \"${\n baseBranch || latestBasedCommit\n }...${latestThisCommit}\" -- ${rootDirectory}`,\n { encoding: 'utf-8' },\n );\n\n // Filter out block list\n const changedFiles = difference(\n diff.split('\\n').filter((f) => f),\n fileBlockList,\n );\n\n // Filter out globs\n const filteredChanges =\n excludedGlob.length > 0 ? fastGlob.sync(changedFiles, { ignore: excludedGlob }) : changedFiles;\n\n // Get the contents of only the changed files\n const fileDiffs: { [k in string]: string } = {};\n filteredChanges.forEach((file) => {\n const contents = execSync(`git show ${latestThisCommit}:${file}`, {\n encoding: 'utf-8',\n });\n fileDiffs[file] = contents;\n });\n\n // Pull the github repo name\n const repoName = githubRepo.split('/').pop()!.split('.')[0];\n\n return {\n changedFiles,\n fileDiffs,\n repoName,\n commit: latestThisCommit,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/lib/graphql/syncCookies.ts","../src/lib/requests/pullPrivacyRequests.ts","../src/lib/helpers/readSafe.ts","../src/lib/api-keys/listDirectories.ts","../src/lib/ai/removeLinks.ts","../src/lib/ai/filterNullishValuesFromObject.ts","../src/lib/ai/getGitFilesThatChanged.ts"],"sourcesContent":["// import { keyBy } from 'lodash-es';\nimport {\n fetchConsentManagerId,\n makeGraphQLRequest,\n UPDATE_OR_CREATE_COOKIES,\n} from '@transcend-io/sdk';\nimport { mapSeries } from '@transcend-io/utils';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { chunk } from 'lodash-es';\n\nimport { CookieInput } from '../../codecs.js';\nimport { logger } from '../../logger.js';\n\nconst MAX_PAGE_SIZE = 100;\n\n/**\n * Update or create cookies that already existed\n *\n * @param client - GraphQL client\n * @param cookieInputs - List of cookie input\n */\nexport async function updateOrCreateCookies(\n client: GraphQLClient,\n cookieInputs: CookieInput[],\n): Promise<void> {\n const airgapBundleId = await fetchConsentManagerId(client, { logger });\n\n // TODO: https://transcend.height.app/T-19841 - add with custom purposes\n // const purposes = await fetchAllPurposes(client);\n // const purposeNameToId = keyBy(purposes, 'name');\n\n await mapSeries(chunk(cookieInputs, MAX_PAGE_SIZE), async (page) => {\n await makeGraphQLRequest(client, UPDATE_OR_CREATE_COOKIES, {\n variables: {\n airgapBundleId,\n cookies: page.map((cookie) => ({\n name: cookie.name,\n trackingPurposes:\n cookie.trackingPurposes && cookie.trackingPurposes.length > 0\n ? cookie.trackingPurposes\n : undefined,\n // TODO: https://transcend.height.app/T-19841 - add with custom purposes\n // purposeIds: cookie.trackingPurposes\n // ? cookie.trackingPurposes\n // .filter((purpose) => purpose !== 'Unknown')\n // .map((purpose) => purposeNameToId[purpose].id)\n // : undefined,\n description: cookie.description,\n service: cookie.service,\n status: cookie.status,\n attributes: cookie.attributes,\n isRegex: cookie.isRegex,\n // TODO: https://transcend.height.app/T-23718\n // owners,\n // teams,\n })),\n },\n logger,\n });\n });\n}\n\n/**\n * Sync the set of cookies from the YML interface into the product\n *\n * @param client - GraphQL client\n * @param cookies - Cookies to sync\n * @returns True upon success, false upon failure\n */\nexport async function syncCookies(client: GraphQLClient, cookies: CookieInput[]): Promise<boolean> {\n let encounteredError = false;\n logger.info(colors.magenta(`Syncing \"${cookies.length}\" cookies...`));\n\n // Ensure no duplicates are being uploaded\n const notUnique = cookies.filter(\n (cookie) =>\n cookies.filter((cook) => cookie.name === cook.name && cookie.isRegex === cook.isRegex)\n .length > 1,\n );\n if (notUnique.length > 0) {\n throw new Error(\n `Failed to upload cookies as there were non-unique entries found: ${notUnique\n .map(({ name }) => name)\n .join(',')}`,\n );\n }\n\n try {\n logger.info(colors.magenta(`Upserting \"${cookies.length}\" new cookies...`));\n await updateOrCreateCookies(client, cookies);\n logger.info(colors.green(`Successfully synced ${cookies.length} cookies!`));\n } catch (err) {\n encounteredError = true;\n logger.error(colors.red(`Failed to create cookies! - ${err.message}`));\n }\n\n return !encounteredError;\n}\n","import { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport {\n buildTranscendGraphQLClient,\n createSombraGotInstance,\n fetchAllRequestIdentifiers,\n validateSombraVersion,\n type RequestIdentifier,\n} from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport colors from 'colors';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\nimport { fetchAllRequests } from '../graphql/index.js';\nimport { formatRequestForCsv, CsvRow, ExportedPrivacyRequest } from './formatRequestForCsv.js';\nimport { splitDateRange } from './splitDateRange.js';\n\n/**\n * Pull down a list of privacy requests\n *\n * @param options - Options\n * @returns The requests with request identifiers and requests formatted for CSV\n */\nexport async function pullPrivacyRequests({\n auth,\n sombraAuth,\n actions = [],\n statuses = [],\n identifierSearch,\n pageLimit = 100,\n concurrency = 1,\n transcendUrl = DEFAULT_TRANSCEND_API,\n createdAtBefore,\n skipRequestIdentifiers = false,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n isTest,\n}: {\n /** Transcend API key authentication */\n auth: string;\n /** Search for a specific identifier */\n identifierSearch?: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Statuses to filter on */\n statuses?: RequestStatus[];\n /** The request action to fetch */\n actions?: RequestAction[];\n /** Page limit when fetching requests */\n pageLimit?: number;\n /** Number of parallel date-range chunks */\n concurrency?: number;\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Filter for requests updated before this date */\n updatedAtBefore?: Date;\n /** Filter for requests updated after this date */\n updatedAtAfter?: Date;\n /** Return test requests */\n isTest?: boolean;\n /** Skip fetching request identifier */\n skipRequestIdentifiers?: boolean;\n}): Promise<{\n /** All request information with attached identifiers */\n requestsWithRequestIdentifiers: ExportedPrivacyRequest[];\n /** Requests that are formatted for CSV */\n requestsFormattedForCsv: CsvRow[];\n}> {\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n const sombra = await createSombraGotInstance(transcendUrl, auth, {\n logger,\n sombraApiKey: sombraAuth,\n sombraUrl: process.env.SOMBRA_URL,\n });\n\n // Log date range\n let dateRange = '';\n if (createdAtBefore) {\n dateRange += ` before ${createdAtBefore.toISOString()}`;\n }\n if (createdAtAfter) {\n dateRange += `${dateRange ? ', and' : ''} after ${createdAtAfter.toISOString()}`;\n }\n logger.info(\n colors.magenta(\n `${\n actions.length > 0\n ? `Pulling requests of type \"${actions.join('\" , \"')}\"`\n : 'Pulling all requests'\n }${dateRange}`,\n ),\n );\n\n // Split into parallel date-range chunks when possible\n const useChunks = concurrency > 1 && createdAtAfter && createdAtBefore;\n const chunks = useChunks\n ? splitDateRange(createdAtAfter, createdAtBefore, concurrency)\n : [{ createdAtAfter, createdAtBefore }];\n\n if (useChunks) {\n logger.info(colors.magenta(`Splitting date range into ${concurrency} parallel chunks`));\n }\n\n // Fetch requests across all chunks in parallel\n const chunkResults = await map(\n chunks,\n (chunk) =>\n fetchAllRequests(client, {\n actions,\n text: identifierSearch,\n statuses,\n createdAtBefore: chunk.createdAtBefore,\n createdAtAfter: chunk.createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n isTest,\n }),\n { concurrency: useChunks ? concurrency : 1 },\n );\n const requests = chunkResults.flat();\n\n // Validate Sombra version once before bulk-fetching identifiers\n if (!skipRequestIdentifiers) {\n await validateSombraVersion(client, { logger });\n }\n\n // Fetch the request identifiers for those requests\n const requestsWithRequestIdentifiers = skipRequestIdentifiers\n ? requests.map((request) => ({\n ...request,\n requestIdentifiers: [] as RequestIdentifier[],\n }))\n : await map(\n requests,\n async (request) => {\n const requestIdentifiers = await fetchAllRequestIdentifiers(client, sombra, {\n filterBy: { requestId: request.id },\n skipSombraCheck: true,\n logger,\n });\n return {\n ...request,\n requestIdentifiers,\n };\n },\n {\n concurrency: pageLimit,\n },\n );\n\n logger.info(colors.magenta(`Pulled ${requestsWithRequestIdentifiers.length} requests`));\n\n const data = requestsWithRequestIdentifiers.map(formatRequestForCsv);\n\n return { requestsWithRequestIdentifiers, requestsFormattedForCsv: data };\n}\n","import { readFileSync } from 'node:fs';\n\n/**\n * Safely reads the contents of a file as a UTF-8 string.\n * Returns an empty string if the path is not provided or if reading fails.\n *\n * @param p - The path to the file to read.\n * @returns The file contents as a string, or an empty string on error.\n */\nexport function readSafe(p?: string): string {\n try {\n return p ? readFileSync(p, 'utf8') : '';\n } catch {\n return '';\n }\n}\n","import { readdirSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\n\n/**\n * List the folders in a directory\n *\n * @param startDir - The base directory to list from\n * @returns The list of folders in that directory\n */\nexport function listDirectories(startDir: string): string[] {\n return readdirSync(startDir).filter((entryName) =>\n statSync(join(startDir, entryName)).isDirectory(),\n );\n}\n","/**\n * Remove links from a string\n *\n * @param inputString - String\n * @returns String without links\n */\nexport function removeLinks(inputString: string): string {\n const regex = /(https?:\\/\\/[^\\s]+)/g;\n return inputString.replace(regex, '<link-omitted>');\n}\n","import { ObjByString } from '@transcend-io/type-utils';\n\n/**\n * Given an object, remove all keys that are null-ish\n *\n * @param obj - Object\n * @returns Object with null-ish values removed\n */\nexport function filterNullishValuesFromObject<T extends ObjByString>(obj: T): T {\n return Object.entries(obj).reduce(\n (acc, [k, v]) =>\n v !== null &&\n v !== undefined &&\n v !== '' &&\n !(Array.isArray(v) && v.length === 0) &&\n !(typeof v === 'object' && Object.keys(v).length === 0)\n ? Object.assign(acc, { [k]: v })\n : acc,\n {} as T,\n );\n}\n","import { execSync } from 'child_process';\n\nimport fastGlob from 'fast-glob';\nimport { difference } from 'lodash-es';\n\n/**\n * Function thats gets the git files that have changed\n * and returns the code\n *\n * @param options - Options\n * @returns Changes files and diffs\n */\nexport function getGitFilesThatChanged({\n baseBranch,\n rootDirectory,\n githubRepo,\n excludedGlob = [],\n fileBlockList = [],\n}: {\n /** Base branch */\n baseBranch: string;\n /** Github repo name */\n githubRepo: string;\n /** Root directory */\n rootDirectory: string;\n /** A glob that excludes files */\n excludedGlob?: string[];\n /** Block list of files to not process */\n fileBlockList?: string[];\n}): {\n /** The list of files that changed */\n changedFiles: string[];\n /** Github repo name */\n repoName: string;\n /** Current commit */\n commit: string;\n /** File diffs */\n fileDiffs: { [k in string]: string };\n} {\n // Pull base branch\n execSync(`git fetch origin ${baseBranch}`);\n\n // Latest commit on base branch. If we are on the base branch, we take the prior commit\n const latestBasedCommit = execSync(\n `git ls-remote ${githubRepo} \"refs/heads/${baseBranch}\" | cut -f 1`,\n { encoding: 'utf-8' },\n ).split('\\n')[0];\n\n // This commit\n const latestThisCommit = execSync('git rev-parse HEAD', {\n encoding: 'utf-8',\n }).split('\\n')[0];\n\n // Ensure commits are present\n if (!latestBasedCommit || !latestThisCommit) {\n throw new Error('FAILED TO FIND COMMIT RANGE');\n }\n\n // Get the diff between the given branch and base branch\n const diff = execSync(\n `git fetch && git diff --name-only \"${\n baseBranch || latestBasedCommit\n }...${latestThisCommit}\" -- ${rootDirectory}`,\n { encoding: 'utf-8' },\n );\n\n // Filter out block list\n const changedFiles = difference(\n diff.split('\\n').filter((f) => f),\n fileBlockList,\n );\n\n // Filter out globs\n const filteredChanges =\n excludedGlob.length > 0 ? fastGlob.sync(changedFiles, { ignore: excludedGlob }) : changedFiles;\n\n // Get the contents of only the changed files\n const fileDiffs: { [k in string]: string } = {};\n filteredChanges.forEach((file) => {\n const contents = execSync(`git show ${latestThisCommit}:${file}`, {\n encoding: 'utf-8',\n });\n fileDiffs[file] = contents;\n });\n\n // Pull the github repo name\n const repoName = githubRepo.split('/').pop()!.split('.')[0];\n\n return {\n changedFiles,\n fileDiffs,\n repoName,\n commit: latestThisCommit,\n };\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
1
  import{existsSync as e,readdirSync as t}from"node:fs";function n(n,r,i=!1){if(!e(n))return[];let a=t(n).filter(e=>r?r.filter(t=>e.endsWith(t)).length:!0).filter(e=>e.indexOf(`.`)>0);return i?a.map(e=>e.replace(/\.[^/.]+$/,``)):a}export{n as t};
2
- //# sourceMappingURL=listFiles-BPx3iDV6.mjs.map
2
+ //# sourceMappingURL=listFiles-C5kubvdN.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"listFiles-BPx3iDV6.mjs","names":[],"sources":["../src/lib/api-keys/listFiles.ts"],"sourcesContent":["import { existsSync, readdirSync } from 'node:fs';\n\n/**\n * List the files in a directory\n *\n * ```typescript\n * // The directory to search\n * const directory = '/User/test/transcend/my-app/app/containers';\n * // Returns ['test.js']\n * listFiles(directory);\n * ```\n *\n * @param directory - The directory to search\n * @param validExtensions - The list of valid extensions\n * @param removeExtensions - When true, remove the extensions from the listed files\n * @returns The list of files in the directory\n */\nexport function listFiles(\n directory: string,\n validExtensions?: string[],\n removeExtensions = false,\n): string[] {\n if (!existsSync(directory)) {\n return [];\n }\n\n const files = readdirSync(directory)\n .filter((fil) =>\n validExtensions ? validExtensions.filter((ext) => fil.endsWith(ext)).length : true,\n )\n .filter((fil) => fil.indexOf('.') > 0);\n\n return removeExtensions ? files.map((fil) => fil.replace(/\\.[^/.]+$/, '')) : files;\n}\n"],"mappings":"sDAiBA,SAAgB,EACd,EACA,EACA,EAAmB,GACT,CACV,GAAI,CAAC,EAAW,EAAU,CACxB,MAAO,EAAE,CAGX,IAAM,EAAQ,EAAY,EAAU,CACjC,OAAQ,GACP,EAAkB,EAAgB,OAAQ,GAAQ,EAAI,SAAS,EAAI,CAAC,CAAC,OAAS,GAC/E,CACA,OAAQ,GAAQ,EAAI,QAAQ,IAAI,CAAG,EAAE,CAExC,OAAO,EAAmB,EAAM,IAAK,GAAQ,EAAI,QAAQ,YAAa,GAAG,CAAC,CAAG"}
1
+ {"version":3,"file":"listFiles-C5kubvdN.mjs","names":[],"sources":["../src/lib/api-keys/listFiles.ts"],"sourcesContent":["import { existsSync, readdirSync } from 'node:fs';\n\n/**\n * List the files in a directory\n *\n * ```typescript\n * // The directory to search\n * const directory = '/User/test/transcend/my-app/app/containers';\n * // Returns ['test.js']\n * listFiles(directory);\n * ```\n *\n * @param directory - The directory to search\n * @param validExtensions - The list of valid extensions\n * @param removeExtensions - When true, remove the extensions from the listed files\n * @returns The list of files in the directory\n */\nexport function listFiles(\n directory: string,\n validExtensions?: string[],\n removeExtensions = false,\n): string[] {\n if (!existsSync(directory)) {\n return [];\n }\n\n const files = readdirSync(directory)\n .filter((fil) =>\n validExtensions ? validExtensions.filter((ext) => fil.endsWith(ext)).length : true,\n )\n .filter((fil) => fil.indexOf('.') > 0);\n\n return removeExtensions ? files.map((fil) => fil.replace(/\\.[^/.]+$/, '')) : files;\n}\n"],"mappings":"sDAiBA,SAAgB,EACd,EACA,EACA,EAAmB,GACT,CACV,GAAI,CAAC,EAAW,EAAU,CACxB,MAAO,EAAE,CAGX,IAAM,EAAQ,EAAY,EAAU,CACjC,OAAQ,GACP,EAAkB,EAAgB,OAAQ,GAAQ,EAAI,SAAS,EAAI,CAAC,CAAC,OAAS,GAC/E,CACA,OAAQ,GAAQ,EAAI,QAAQ,IAAI,CAAG,EAAE,CAExC,OAAO,EAAmB,EAAM,IAAK,GAAQ,EAAI,QAAQ,YAAa,GAAG,CAAC,CAAG"}
@@ -1,2 +1,2 @@
1
- import{a as e}from"./constants-BjwEFOS4.mjs";import{t}from"./logger-Ckep4QXn.mjs";import{RequestDataSiloStatus as n}from"@transcend-io/privacy-types";import r from"colors";import{CHANGE_REQUEST_DATA_SILO_STATUS as i,buildTranscendGraphQLClient as a,fetchRequestDataSilo as o,makeGraphQLRequest as s}from"@transcend-io/sdk";import{map as c}from"@transcend-io/utils";import l from"cli-progress";async function u({requestIds:u,dataSiloId:d,auth:f,concurrency:p=100,status:m=n.Resolved,transcendUrl:h=e}){let g=a(h,f),_=new Date().getTime(),v=new l.SingleBar({},l.Presets.shades_classic);t.info(r.magenta(`Notifying Transcend for data silo "${d}" marking "${u.length}" requests as completed.`));let y=0;v.start(u.length,0),await c(u,async e=>{let n=await o(g,{logger:t,filterBy:{requestId:e,dataSiloId:d}});try{await s(g,i,{variables:{requestDataSiloId:n.id,status:m},logger:t})}catch(e){if(!e.message.includes(`Client error: Request must be active:`)&&!e.message.includes(`Failed to find RequestDataSilo`))throw e}y+=1,v.update(y)},{concurrency:p}),v.stop();let b=new Date().getTime()-_;return t.info(r.green(`Successfully notified Transcend in "${b/1e3}" seconds!`)),u.length}export{u as t};
2
- //# sourceMappingURL=markRequestDataSiloIdsCompleted-Bw_krZSS.mjs.map
1
+ import{a as e}from"./constants-CAOyAsNX.mjs";import{t}from"./logger-Ckep4QXn.mjs";import{RequestDataSiloStatus as n}from"@transcend-io/privacy-types";import r from"colors";import{CHANGE_REQUEST_DATA_SILO_STATUS as i,buildTranscendGraphQLClient as a,fetchRequestDataSilo as o,makeGraphQLRequest as s}from"@transcend-io/sdk";import{map as c}from"@transcend-io/utils";import l from"cli-progress";async function u({requestIds:u,dataSiloId:d,auth:f,concurrency:p=100,status:m=n.Resolved,transcendUrl:h=e}){let g=a(h,f),_=new Date().getTime(),v=new l.SingleBar({},l.Presets.shades_classic);t.info(r.magenta(`Notifying Transcend for data silo "${d}" marking "${u.length}" requests as completed.`));let y=0;v.start(u.length,0),await c(u,async e=>{let n=await o(g,{logger:t,filterBy:{requestId:e,dataSiloId:d}});try{await s(g,i,{variables:{requestDataSiloId:n.id,status:m},logger:t})}catch(e){if(!e.message.includes(`Client error: Request must be active:`)&&!e.message.includes(`Failed to find RequestDataSilo`))throw e}y+=1,v.update(y)},{concurrency:p}),v.stop();let b=new Date().getTime()-_;return t.info(r.green(`Successfully notified Transcend in "${b/1e3}" seconds!`)),u.length}export{u as t};
2
+ //# sourceMappingURL=markRequestDataSiloIdsCompleted-CDV0Ppv2.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"markRequestDataSiloIdsCompleted-Bw_krZSS.mjs","names":[],"sources":["../src/lib/cron/markRequestDataSiloIdsCompleted.ts"],"sourcesContent":["import { RequestDataSiloStatus } from '@transcend-io/privacy-types';\nimport {\n buildTranscendGraphQLClient,\n makeGraphQLRequest,\n CHANGE_REQUEST_DATA_SILO_STATUS,\n fetchRequestDataSilo,\n} from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\n\n/**\n * Given a CSV of Request IDs, mark associated RequestDataSilos as completed\n *\n * @param options - Options\n * @returns Number of items marked as completed\n */\nexport async function markRequestDataSiloIdsCompleted({\n requestIds,\n dataSiloId,\n auth,\n concurrency = 100,\n status = RequestDataSiloStatus.Resolved,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The list of request ids to mark as completed */\n requestIds: string[];\n /** Transcend API key authentication */\n auth: string;\n /** Data Silo ID to pull down jobs for */\n dataSiloId: string;\n /** Status to update requests to */\n status?: RequestDataSiloStatus;\n /** Upload concurrency */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Notifying Transcend for data silo \"${dataSiloId}\" marking \"${requestIds.length}\" requests as completed.`,\n ),\n );\n\n let total = 0;\n progressBar.start(requestIds.length, 0);\n await map(\n requestIds,\n async (requestId) => {\n const requestDataSilo = await fetchRequestDataSilo(client, {\n logger,\n filterBy: { requestId, dataSiloId },\n });\n\n try {\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, CHANGE_REQUEST_DATA_SILO_STATUS, {\n variables: {\n requestDataSiloId: requestDataSilo.id,\n status,\n },\n logger,\n });\n } catch (err) {\n if (\n !err.message.includes('Client error: Request must be active:') &&\n !err.message.includes('Failed to find RequestDataSilo')\n ) {\n throw err;\n }\n }\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(colors.green(`Successfully notified Transcend in \"${totalTime / 1000}\" seconds!`));\n return requestIds.length;\n}\n"],"mappings":"yYAoBA,eAAsB,EAAgC,CACpD,aACA,aACA,OACA,cAAc,IACd,SAAS,EAAsB,SAC/B,eAAe,GAcG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAI,EAAY,UAAU,EAAE,CAAE,EAAY,QAAQ,eAAe,CAGrF,EAAO,KACL,EAAO,QACL,sCAAsC,EAAW,aAAa,EAAW,OAAO,0BACjF,CACF,CAED,IAAI,EAAQ,EACZ,EAAY,MAAM,EAAW,OAAQ,EAAE,CACvC,MAAM,EACJ,EACA,KAAO,IAAc,CACnB,IAAM,EAAkB,MAAM,EAAqB,EAAQ,CACzD,SACA,SAAU,CAAE,YAAW,aAAY,CACpC,CAAC,CAEF,GAAI,CACF,MAAM,EAGH,EAAQ,EAAiC,CAC1C,UAAW,CACT,kBAAmB,EAAgB,GACnC,SACD,CACD,SACD,CAAC,OACK,EAAK,CACZ,GACE,CAAC,EAAI,QAAQ,SAAS,wCAAwC,EAC9D,CAAC,EAAI,QAAQ,SAAS,iCAAiC,CAEvD,MAAM,EAIV,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SACF,CAAG,EAGvB,OADA,EAAO,KAAK,EAAO,MAAM,uCAAuC,EAAY,IAAK,YAAY,CAAC,CACvF,EAAW"}
1
+ {"version":3,"file":"markRequestDataSiloIdsCompleted-CDV0Ppv2.mjs","names":[],"sources":["../src/lib/cron/markRequestDataSiloIdsCompleted.ts"],"sourcesContent":["import { RequestDataSiloStatus } from '@transcend-io/privacy-types';\nimport {\n buildTranscendGraphQLClient,\n makeGraphQLRequest,\n CHANGE_REQUEST_DATA_SILO_STATUS,\n fetchRequestDataSilo,\n} from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\n\n/**\n * Given a CSV of Request IDs, mark associated RequestDataSilos as completed\n *\n * @param options - Options\n * @returns Number of items marked as completed\n */\nexport async function markRequestDataSiloIdsCompleted({\n requestIds,\n dataSiloId,\n auth,\n concurrency = 100,\n status = RequestDataSiloStatus.Resolved,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The list of request ids to mark as completed */\n requestIds: string[];\n /** Transcend API key authentication */\n auth: string;\n /** Data Silo ID to pull down jobs for */\n dataSiloId: string;\n /** Status to update requests to */\n status?: RequestDataSiloStatus;\n /** Upload concurrency */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Notifying Transcend for data silo \"${dataSiloId}\" marking \"${requestIds.length}\" requests as completed.`,\n ),\n );\n\n let total = 0;\n progressBar.start(requestIds.length, 0);\n await map(\n requestIds,\n async (requestId) => {\n const requestDataSilo = await fetchRequestDataSilo(client, {\n logger,\n filterBy: { requestId, dataSiloId },\n });\n\n try {\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, CHANGE_REQUEST_DATA_SILO_STATUS, {\n variables: {\n requestDataSiloId: requestDataSilo.id,\n status,\n },\n logger,\n });\n } catch (err) {\n if (\n !err.message.includes('Client error: Request must be active:') &&\n !err.message.includes('Failed to find RequestDataSilo')\n ) {\n throw err;\n }\n }\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(colors.green(`Successfully notified Transcend in \"${totalTime / 1000}\" seconds!`));\n return requestIds.length;\n}\n"],"mappings":"yYAoBA,eAAsB,EAAgC,CACpD,aACA,aACA,OACA,cAAc,IACd,SAAS,EAAsB,SAC/B,eAAe,GAcG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAI,EAAY,UAAU,EAAE,CAAE,EAAY,QAAQ,eAAe,CAGrF,EAAO,KACL,EAAO,QACL,sCAAsC,EAAW,aAAa,EAAW,OAAO,0BACjF,CACF,CAED,IAAI,EAAQ,EACZ,EAAY,MAAM,EAAW,OAAQ,EAAE,CACvC,MAAM,EACJ,EACA,KAAO,IAAc,CACnB,IAAM,EAAkB,MAAM,EAAqB,EAAQ,CACzD,SACA,SAAU,CAAE,YAAW,aAAY,CACpC,CAAC,CAEF,GAAI,CACF,MAAM,EAGH,EAAQ,EAAiC,CAC1C,UAAW,CACT,kBAAmB,EAAgB,GACnC,SACD,CACD,SACD,CAAC,OACK,EAAK,CACZ,GACE,CAAC,EAAI,QAAQ,SAAS,wCAAwC,EAC9D,CAAC,EAAI,QAAQ,SAAS,iCAAiC,CAEvD,MAAM,EAIV,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SACF,CAAG,EAGvB,OADA,EAAO,KAAK,EAAO,MAAM,uCAAuC,EAAY,IAAK,YAAY,CAAC,CACvF,EAAW"}
@@ -1,2 +1,2 @@
1
- import{a as e}from"./constants-BjwEFOS4.mjs";import{t}from"./logger-Ckep4QXn.mjs";import{o as n}from"./request-BIplTb3L.mjs";import{r}from"./fetchAllRequests-DP24WqrP.mjs";import{RequestStatus as i}from"@transcend-io/privacy-types";import a from"colors";import{buildTranscendGraphQLClient as o,makeGraphQLRequest as s}from"@transcend-io/sdk";import{map as c}from"@transcend-io/utils";import l from"cli-progress";async function u({requestActions:u,auth:d,requestIds:f,statuses:p=[i.Compiling,i.RequestMade,i.Delayed,i.Approving,i.Secondary,i.Enriching,i.Waiting,i.SecondaryApproving],createdAtAfter:m,createdAtBefore:h,updatedAtBefore:g,updatedAtAfter:_,concurrency:v=100,transcendUrl:y=e}){let b=o(y,d),x=new Date().getTime(),S=new l.SingleBar({},l.Presets.shades_classic),C=await r(b,{actions:u,statuses:p,createdAtBefore:h,createdAtAfter:m,updatedAtBefore:g,updatedAtAfter:_,isSilent:!1,requestIds:f});t.info(a.magenta(`Marking "${C.length}" as silent mode.`));let w=0;S.start(C.length,0),await c(C,async e=>{await s(b,n,{variables:{input:{id:e.id,isSilent:!0}},logger:t}),w+=1,S.update(w)},{concurrency:v}),S.stop();let T=new Date().getTime()-x;return t.info(a.green(`Successfully marked ${w} requests as silent mode in "${T/1e3}" seconds!`)),C.length}export{u as t};
2
- //# sourceMappingURL=markSilentPrivacyRequests-CitXF4qq.mjs.map
1
+ import{a as e}from"./constants-CAOyAsNX.mjs";import{t}from"./logger-Ckep4QXn.mjs";import{o as n}from"./request-BIplTb3L.mjs";import{r}from"./fetchAllRequests-DP24WqrP.mjs";import{RequestStatus as i}from"@transcend-io/privacy-types";import a from"colors";import{buildTranscendGraphQLClient as o,makeGraphQLRequest as s}from"@transcend-io/sdk";import{map as c}from"@transcend-io/utils";import l from"cli-progress";async function u({requestActions:u,auth:d,requestIds:f,statuses:p=[i.Compiling,i.RequestMade,i.Delayed,i.Approving,i.Secondary,i.Enriching,i.Waiting,i.SecondaryApproving],createdAtAfter:m,createdAtBefore:h,updatedAtBefore:g,updatedAtAfter:_,concurrency:v=100,transcendUrl:y=e}){let b=o(y,d),x=new Date().getTime(),S=new l.SingleBar({},l.Presets.shades_classic),C=await r(b,{actions:u,statuses:p,createdAtBefore:h,createdAtAfter:m,updatedAtBefore:g,updatedAtAfter:_,isSilent:!1,requestIds:f});t.info(a.magenta(`Marking "${C.length}" as silent mode.`));let w=0;S.start(C.length,0),await c(C,async e=>{await s(b,n,{variables:{input:{id:e.id,isSilent:!0}},logger:t}),w+=1,S.update(w)},{concurrency:v}),S.stop();let T=new Date().getTime()-x;return t.info(a.green(`Successfully marked ${w} requests as silent mode in "${T/1e3}" seconds!`)),C.length}export{u as t};
2
+ //# sourceMappingURL=markSilentPrivacyRequests-DXLiS2jH.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"markSilentPrivacyRequests-CitXF4qq.mjs","names":[],"sources":["../src/lib/requests/markSilentPrivacyRequests.ts"],"sourcesContent":["import { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport { buildTranscendGraphQLClient, makeGraphQLRequest } from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\nimport { UPDATE_PRIVACY_REQUEST, fetchAllRequests } from '../graphql/index.js';\n\n/**\n * Mark a set of privacy requests to be in silent mode\n *\n * @param options - Options\n * @returns The number of requests marked silent\n */\nexport async function markSilentPrivacyRequests({\n requestActions,\n auth,\n requestIds,\n statuses = [\n RequestStatus.Compiling,\n RequestStatus.RequestMade,\n RequestStatus.Delayed,\n RequestStatus.Approving,\n RequestStatus.Secondary,\n RequestStatus.Enriching,\n RequestStatus.Waiting,\n RequestStatus.SecondaryApproving,\n ],\n createdAtAfter,\n createdAtBefore,\n updatedAtBefore,\n updatedAtAfter,\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** Transcend API key authentication */\n auth: string;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** The request statuses to mark silent */\n statuses?: RequestStatus[];\n /** The set of privacy requests to mark silent */\n requestIds?: string[];\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Filter for requests updated before this date */\n updatedAtBefore?: Date;\n /** Filter for requests updated after this date */\n updatedAtAfter?: Date;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n isSilent: false,\n requestIds,\n });\n\n // Notify Transcend\n logger.info(colors.magenta(`Marking \"${allRequests.length}\" as silent mode.`));\n\n let total = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToMarkSilent) => {\n await makeGraphQLRequest(client, UPDATE_PRIVACY_REQUEST, {\n variables: {\n input: {\n id: requestToMarkSilent.id,\n isSilent: true,\n },\n },\n logger,\n });\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully marked ${total} requests as silent mode in \"${totalTime / 1000}\" seconds!`,\n ),\n );\n return allRequests.length;\n}\n"],"mappings":"4ZAgBA,eAAsB,EAA0B,CAC9C,iBACA,OACA,aACA,WAAW,CACT,EAAc,UACd,EAAc,YACd,EAAc,QACd,EAAc,UACd,EAAc,UACd,EAAc,UACd,EAAc,QACd,EAAc,mBACf,CACD,iBACA,kBACA,kBACA,iBACA,cAAc,IACd,eAAe,GAsBG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAI,EAAY,UAAU,EAAE,CAAE,EAAY,QAAQ,eAAe,CAG/E,EAAc,MAAM,EAAiB,EAAQ,CACjD,QAAS,EACT,WACA,kBACA,iBACA,kBACA,iBACA,SAAU,GACV,aACD,CAAC,CAGF,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAY,OAAO,mBAAmB,CAAC,CAE9E,IAAI,EAAQ,EACZ,EAAY,MAAM,EAAY,OAAQ,EAAE,CACxC,MAAM,EACJ,EACA,KAAO,IAAwB,CAC7B,MAAM,EAAmB,EAAQ,EAAwB,CACvD,UAAW,CACT,MAAO,CACL,GAAI,EAAoB,GACxB,SAAU,GACX,CACF,CACD,SACD,CAAC,CAEF,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SACF,CAAG,EAOvB,OALA,EAAO,KACL,EAAO,MACL,uBAAuB,EAAM,+BAA+B,EAAY,IAAK,YAC9E,CACF,CACM,EAAY"}
1
+ {"version":3,"file":"markSilentPrivacyRequests-DXLiS2jH.mjs","names":[],"sources":["../src/lib/requests/markSilentPrivacyRequests.ts"],"sourcesContent":["import { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport { buildTranscendGraphQLClient, makeGraphQLRequest } from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\nimport { UPDATE_PRIVACY_REQUEST, fetchAllRequests } from '../graphql/index.js';\n\n/**\n * Mark a set of privacy requests to be in silent mode\n *\n * @param options - Options\n * @returns The number of requests marked silent\n */\nexport async function markSilentPrivacyRequests({\n requestActions,\n auth,\n requestIds,\n statuses = [\n RequestStatus.Compiling,\n RequestStatus.RequestMade,\n RequestStatus.Delayed,\n RequestStatus.Approving,\n RequestStatus.Secondary,\n RequestStatus.Enriching,\n RequestStatus.Waiting,\n RequestStatus.SecondaryApproving,\n ],\n createdAtAfter,\n createdAtBefore,\n updatedAtBefore,\n updatedAtAfter,\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** Transcend API key authentication */\n auth: string;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** The request statuses to mark silent */\n statuses?: RequestStatus[];\n /** The set of privacy requests to mark silent */\n requestIds?: string[];\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Filter for requests updated before this date */\n updatedAtBefore?: Date;\n /** Filter for requests updated after this date */\n updatedAtAfter?: Date;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n isSilent: false,\n requestIds,\n });\n\n // Notify Transcend\n logger.info(colors.magenta(`Marking \"${allRequests.length}\" as silent mode.`));\n\n let total = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToMarkSilent) => {\n await makeGraphQLRequest(client, UPDATE_PRIVACY_REQUEST, {\n variables: {\n input: {\n id: requestToMarkSilent.id,\n isSilent: true,\n },\n },\n logger,\n });\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully marked ${total} requests as silent mode in \"${totalTime / 1000}\" seconds!`,\n ),\n );\n return allRequests.length;\n}\n"],"mappings":"4ZAgBA,eAAsB,EAA0B,CAC9C,iBACA,OACA,aACA,WAAW,CACT,EAAc,UACd,EAAc,YACd,EAAc,QACd,EAAc,UACd,EAAc,UACd,EAAc,UACd,EAAc,QACd,EAAc,mBACf,CACD,iBACA,kBACA,kBACA,iBACA,cAAc,IACd,eAAe,GAsBG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAI,EAAY,UAAU,EAAE,CAAE,EAAY,QAAQ,eAAe,CAG/E,EAAc,MAAM,EAAiB,EAAQ,CACjD,QAAS,EACT,WACA,kBACA,iBACA,kBACA,iBACA,SAAU,GACV,aACD,CAAC,CAGF,EAAO,KAAK,EAAO,QAAQ,YAAY,EAAY,OAAO,mBAAmB,CAAC,CAE9E,IAAI,EAAQ,EACZ,EAAY,MAAM,EAAY,OAAQ,EAAE,CACxC,MAAM,EACJ,EACA,KAAO,IAAwB,CAC7B,MAAM,EAAmB,EAAQ,EAAwB,CACvD,UAAW,CACT,MAAO,CACL,GAAI,EAAoB,GACxB,SAAU,GACX,CACF,CACD,SACD,CAAC,CAEF,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SACF,CAAG,EAOvB,OALA,EAAO,KACL,EAAO,MACL,uBAAuB,EAAM,+BAA+B,EAAY,IAAK,YAC9E,CACF,CACM,EAAY"}
@@ -0,0 +1,3 @@
1
+ import{t as e}from"./logger-Ckep4QXn.mjs";import{chunk as t,difference as n,flatten as r,keyBy as i,uniq as a}from"lodash-es";import o from"colors";import{apply as s,getEntries as c}from"@transcend-io/type-utils";import{CREATE_DATA_SILOS as l,UPDATE_DATA_SILOS as u,UPDATE_OR_CREATE_DATA_POINT as d,convertToDataSubjectBlockList as f,createDataSubject as p,fetchAllActions as m,fetchAllAttributes as h,fetchAllDataSilos as g,fetchAllDataSubjects as _,fetchApiKeys as v,fetchIdentifiersAndCreateMissing as y,makeGraphQLRequest as b,syncAction as x,syncActionItemCollections as S,syncActionItems as C,syncAttribute as w,syncBusinessEntities as T,syncConsentManager as ee,syncConsentWorkflowTriggers as te,syncCookies as ne,syncDataCategories as re,syncDataFlows as ie,syncDataSiloDependencies as ae,syncDataSubject as oe,syncEnricher as se,syncIdentifier as ce,syncIntlMessages as le,syncPartitions as ue,syncPolicies as de,syncPreferenceOptionValues as fe,syncPreferenceTopics as pe,syncPrivacyCenter as me,syncProcessingActivities as he,syncProcessingPurposes as ge,syncPurposes as _e,syncTeams as ve,syncTemplate as ye,syncVendors as be,syncWorkflowConfigs as xe}from"@transcend-io/sdk";import{map as E,mapSeries as D}from"@transcend-io/utils";import O from"cli-progress";const k=/^[A-Za-z]+$/;function Se(e){let t=[],n=(e,n)=>{k.test(e)||t.push(`${n}: slug "${e}" is invalid — slugs must contain only alphabetical letters (A-Z, a-z). Topic slugs are normalized to PascalCase server-side, so YAML slugs should already be PascalCase or matching will break on subsequent pulls.`)};for(let t of e[`preference-options`]??[])n(t.slug,`preference-options`);for(let t of e.purposes??[])for(let e of t[`preference-topics`]??[]){n(e.slug,`purposes (topic "${e.title}")`);for(let t of e.options??[])n(t.slug,`purposes (topic "${e.title}" option "${t.title}")`)}return t}async function A({"data-silos":t=[],"data-subjects":s=[],"processing-activities":c=[],enrichers:l=[]},u,d=!1){let f=a([...r(t.map(e=>e[`data-subjects`]||[])||[]),...r(c.map(({dataSubjectTypes:e})=>e??[])??[]),...r(l.map(e=>e[`data-subjects`]||[])||[]),...s.map(e=>e.type)]);if(f.length===0&&!d)return{};let m=await _(u,{logger:e}),h=i(m,`type`),g=n(f,m.map(({type:e})=>e));if(g.length>0){e.info(o.magenta(`Creating ${g.length} new data subjects...`));for(let t of g){e.info(o.magenta(`Creating data subject ${t}...`));let n=await p(u,{input:t,logger:e});e.info(o.green(`Created data subject ${t}!`)),h[t]=n}}return h}function Ce(e,t){if(e.length===0)return[];if(typeof e[0]==`string`)return[{titles:a(e)}];let n,r=[],i=new Set,o=(e,n)=>{if(i.has(e))throw Error(`Data silo "${t}" has multiple deletion-dependencies entries for workflow "${e}". Combine them into a single entry.`);i.add(e),r.push({workflowConfigInternalName:e,...n})};return e.forEach(e=>{if(`reset-to-global`in e&&`titles`in e)throw Error(`Data silo "${t}" has a deletion-dependencies entry for workflow "${e.workflow}" that sets both "reset-to-global" and "titles". Use "titles: []" to override the global configuration with no dependencies, or "reset-to-global: true" to fall back to the global configuration.`);if(`reset-to-global`in e){o(e.workflow,{resetToGlobal:!0});return}if(e.workflow){o(e.workflow,{titles:e.titles});return}if(n!==void 0)throw Error(`Data silo "${t}" has multiple global deletion-dependencies entries. Combine them into a single \`{ titles: [...] }\` entry.`);n=e.titles}),[...n===void 0?[]:[{titles:a(n)}],...r]}async function j(n,r,{pageSize:a,dataSubjectsByName:c,apiKeysByTitle:p}){let m=!1,h=new Date().getTime();e.info(o.magenta(`Syncing "${n.length}" data silos...`));let _=i(await g(r,{titles:n.map(({title:e})=>e),pageSize:a,logger:e}),`title`),v=n.filter(({title:e})=>!_[e]);v.length>0&&(e.info(o.magenta(`Creating "${v.length}" data silos that did not exist...`)),await D(t(v,20),async t=>{let{createDataSilos:{dataSilos:n}}=await b(r,l,{variables:{input:t.map(e=>({name:e[`outer-type`]||e.integrationName,title:e.title,country:e.country,countrySubDivision:e.countrySubDivision,sombraId:e[`sombra-id`]}))},logger:e});n.forEach(e=>{_[e.title]=e})}),e.info(o.green(`Successfully created "${v.length}" data silos!`)));let y=t(n,20);await D(y,async(t,n)=>{e.info(o.magenta(`[Batch ${n+1}/${y.length}] Syncing "${t.length}" data silos`)),await b(r,u,{variables:{input:{dataSilos:t.map(e=>({id:_[e.title].id,country:e.country,countrySubDivision:e.countrySubDivision,url:e.url,headers:e.headers,description:e.description,identifiers:e[`identity-keys`],isLive:!e.disabled,ownerEmails:e.owners,teamNames:e.teams,dependedOnDataSilos:e[`deletion-dependencies`]?void 0:[{titles:[]}],apiKeyId:e[`api-key-title`]?p[e[`api-key-title`]].id:void 0,dataSubjectBlockListIds:e[`data-subjects`]?f(e[`data-subjects`],c):void 0,attributes:e.attributes,businessEntityTitles:e.businessEntityTitles,sombraId:e[`sombra-id`],notifyEmailAddress:e[`email-settings`]?.[`notify-email-address`],promptAVendorEmailSendFrequency:e[`email-settings`]?.[`send-frequency`],promptAVendorEmailSendType:e[`email-settings`]?.[`send-type`],promptAVendorEmailIncludeIdentifiersAttachment:e[`email-settings`]?.[`include-identifiers-attachment`],promptAVendorEmailCompletionLinkType:e[`email-settings`]?.[`completion-link-type`],manualWorkRetryFrequency:e[`email-settings`]?.[`manual-work-retry-frequency`]}))}},logger:e}),e.info(o.green(`[Batch ${n+1}/${y.length}] Synced "${t.length}" data silos!`))});let x=new O.SingleBar({},O.Presets.shades_classic),S=n.filter(({datapoints:e=[]})=>e.length>0),C=n.map(({datapoints:e=[]})=>e.length).reduce((e,t)=>e+t,0);e.info(o.magenta(`Syncing "${C}" datapoints from "${S.length}" data silos...`)),x.start(C,0);let w=0;await E(S,async({datapoints:t,title:n})=>{t&&await D(t,async t=>{let i=t.fields?t.fields.map(({key:e,description:t,categories:n,purposes:r,attributes:i,...a})=>({name:e,description:t,categories:n?n.map(e=>({...e,name:e.name||`Other`})):void 0,purposes:r?r.map(e=>({...e,name:e.name||`Other`})):void 0,attributes:i,accessRequestVisibilityEnabled:a[`access-request-visibility-enabled`],erasureRequestRedactionEnabled:a[`erasure-request-redaction-enabled`]})):void 0,a={dataSiloId:_[n].id,path:t.path,name:t.key,title:t.title,description:t.description,...t.owners?{ownerEmails:t.owners}:{},...t.teams?{teamNames:t.teams}:{},...t[`data-collection-tag`]?{dataCollectionTag:t[`data-collection-tag`]}:{},querySuggestions:t[`privacy-action-queries`]?Object.entries(t[`privacy-action-queries`]).map(([e,t])=>({requestType:e,suggestedQuery:t})):void 0,enabledActions:t[`privacy-actions`]||[],subDataPoints:i},s=(a.subDataPoints||[]).map(({name:e})=>e),c=s.filter((e,t)=>s.indexOf(e)!==t);if(c.length>0)e.info(o.red(`\nCannot update datapoint "${t.key}" as it has duplicate sub-datapoints with the same name: \n${c.join(`
2
+ `)}`)),m=!0;else try{await b(r,d,{variables:a,logger:e})}catch(r){e.info(o.red(`\nFailed to update datapoint "${t.key}" for data silo "${n}"! - \n${r.message}`)),m=!0}w+=1,x.update(w)})},{concurrency:10}),x.stop();let T=new Date().getTime()-h;return e.info(o.green(`Synced "${n.length}" data silos and "${C}" datapoints in "${T/1e3}" seconds!`)),{success:!m,dataSiloTitleToId:s(_,({id:e})=>e)}}async function M(t,n,{pageSize:r=50,publishToPrivacyCenter:i=!0,classifyService:a=!1,deleteExtraAttributeValues:s=!1,logger:c,warnings:l=[]}){let u=c??e,d=[],f=!1,p=(e,t,n)=>{d.push({resource:e,item:n,message:t}),f=!0};u.info(o.magenta(`Fetching data with page size ${r}...`));let{templates:g,attributes:b,actions:D,identifiers:O,"data-subjects":k,"business-entities":M,enrichers:N,cookies:P,"consent-manager":F,"data-silos":I,"data-flows":L,vendors:R,"data-categories":z,"processing-activities":B,"processing-purposes":V,"action-items":H,"action-item-collections":U,teams:W,"privacy-center":G,messages:K,policies:q,partitions:J,"preference-workflow-configs":we,"workflow-configs":Y}=t,Te=t[`preference-options`],X=t.purposes,Ee=Se(t);if(Ee.length>0){for(let e of Ee)p(`preference-slugs`,e);return{success:!1,errors:d,warnings:l.length>0?l:void 0}}let[Z,Q,De]=await Promise.all([N||O?y(n,{input:t,skipPublish:!i,logger:e}):{},I||k||N||B?A(t,n):{},I&&I.map(e=>e[`api-key-title`]||[]).reduce((e,t)=>e+t.length,0)>0?v(n,{apiKeyInputs:t,logger:e}):{}]);if(we?.length&&(await te(n,we,{logger:u,pageSize:r})||p(`preference-workflow-configs`,`Failed to sync preference workflow configs`)),Y?.length&&(await xe(n,Y,{logger:u})||p(`workflow-configs`,`Failed to sync workflow configs`)),Te?.length&&(await fe(n,Te,{logger:u})||p(`preference-options`,`Failed to sync preference option values`)),X?.length){let{success:e,purposeIdByTrackingType:t}=await _e(n,X,{logger:u});e||p(`purposes`,`Failed to sync one or more purposes`);let r=X.flatMap(e=>(e[`preference-topics`]??[]).map(t=>({...t,"tracking-type":e.trackingType})));r.length>0&&(await pe(n,r,{logger:u,purposeIdByTrackingType:t})||p(`preference-topics`,`Failed to sync one or more preference topics`))}if(F){u.info(o.magenta(`Syncing consent manager...`));try{await ee(n,F,{logger:u}),u.info(o.green(`Successfully synced consent manager!`))}catch(e){p(`consent-manager`,e.message),u.error(o.red(`Failed to sync consent manager! - ${e.message}`))}}if(W){let t=await ve(n,W,{logger:e});f||=!t}if(g&&(e.info(o.magenta(`Syncing "${g.length}" email templates...`)),await E(g,async t=>{e.info(o.magenta(`Syncing template "${t.title}"...`));try{await ye(n,t,{logger:e}),e.info(o.green(`Successfully synced template "${t.title}"!`))}catch(n){f=!0,e.error(o.red(`Failed to sync template "${t.title}"! - ${n.message}`))}},{concurrency:10}),e.info(o.green(`Synced "${g.length}" email templates!`))),M){let t=await T(n,M,{logger:e});f||=!t}if(R){let t=await be(n,R,{logger:e});f||=!t}if(z){let t=await re(n,z,{logger:e});f||=!t}if(V){let t=await ge(n,V,{logger:e});f||=!t}if(J){let t=await ue(n,J,{logger:e});f||=!t}if(P){let t=await ne(n,P,{logger:e});f||=!t}if(U){let t=await S(n,U,{logger:e});f||=!t}if(b){e.info(o.magenta(`Syncing "${b.length}" attributes...`));let t=await h(n,{logger:e});await E(b,async r=>{let i=t.find(e=>e.name===r.name);e.info(o.magenta(`Syncing attribute "${r.name}"...`));try{await w(n,r,{existingAttribute:i,deleteExtraAttributeValues:s,logger:e}),e.info(o.green(`Successfully synced attribute "${r.name}"!`))}catch(t){f=!0,e.error(o.red(`Failed to sync attribute "${r.name}"! - ${t.message}`))}},{concurrency:10}),e.info(o.green(`Synced "${b.length}" attributes!`))}if(H){let t=await C(n,H,{logger:e});f||=!t}if(N&&(e.info(o.magenta(`Syncing "${N.length}" enrichers...`)),await E(N,async t=>{e.info(o.magenta(`Syncing enricher "${t.title}"...`));try{await se(n,{input:t,identifierByName:Z,dataSubjectsByName:Q,logger:e}),e.info(o.green(`Successfully synced enricher "${t.title}"!`))}catch(n){f=!0,e.error(o.red(`Failed to sync enricher "${t.title}"! - ${n.message}`))}},{concurrency:10}),e.info(o.green(`Synced "${N.length}" enrichers!`))),O&&(e.info(o.magenta(`Syncing "${O.length}" identifiers...`)),await E(O,async t=>{let r=Z[t.name];if(!r)throw Error(`Failed to find identifier with name: ${t.type}. Should have been auto-created by cli.`);e.info(o.magenta(`Syncing identifier "${t.type}"...`));try{await ce(n,{input:t,dataSubjectsByName:Q,identifierId:r.id,skipPublish:!i,logger:e}),e.info(o.green(`Successfully synced identifier "${t.type}"!`))}catch(n){f=!0,e.info(o.red(`Failed to sync identifier "${t.type}"! - ${n.message}`))}},{concurrency:10}),e.info(o.green(`Synced "${O.length}" identifiers!`))),D){e.info(o.magenta(`Syncing "${D.length}" actions...`));let t=await m(n,{logger:e});await E(D,async r=>{let a=t.find(e=>e.type===r.type);if(!a)throw Error(`Failed to find action with type: ${r.type}. Should have already existing in the organization.`);e.info(o.magenta(`Syncing action "${r.type}"...`));try{await x(n,{action:r,actionId:a.id,skipPublish:!i},{logger:e}),e.info(o.green(`Successfully synced action "${r.type}"!`))}catch(t){f=!0,e.error(o.red(`Failed to sync action "${r.type}"! - ${t.message}`))}},{concurrency:10}),e.info(o.green(`Synced "${D.length}" actions!`))}if(k){e.info(o.magenta(`Syncing "${k.length}" data subjects...`));let t=await _(n,{logger:e});await E(k,async r=>{let a=t.find(e=>e.type===r.type);if(!a)throw Error(`Failed to find data subject with type: ${r.type}. Should have already existing in the organization.`);e.info(o.magenta(`Syncing data subject "${r.type}"...`));try{await oe(n,{input:r,dataSubjectId:a.id,skipPublish:!i,logger:e}),e.info(o.green(`Successfully synced data subject "${r.type}"!`))}catch(t){f=!0;let n=r.supportsAuthorizedAgent!==void 0&&/authorized.agent/i.test(t.message)?` (enable the Authorized Agents feature for this organization before setting "supportsAuthorizedAgent")`:``;e.info(o.red(`Failed to sync data subject "${r.type}"! - ${t.message}${n}`))}},{concurrency:10}),e.info(o.green(`Synced "${k.length}" data subjects!`))}if(L){let t=await ie(n,L,{classifyService:a,logger:e});f||=!t}if(G)try{await me(n,G,{logger:e,skipPublish:!i})||p(`privacy-center`,`Failed to sync privacy center`)}catch(e){p(`privacy-center`,e.message)}if(K){let t=await le(n,K,{logger:e});f||=!t}if(q){let t=await de(n,q,{logger:e});f||=!t}let $=[];if(I){let{success:e,dataSiloTitleToId:t}=await j(I,n,{dataSubjectsByName:Q,apiKeysByTitle:De,pageSize:r});I?.forEach(e=>{let n=e[`deletion-dependencies`];if(n)try{$.push([t[e.title],Ce(n,e.title)])}catch(t){p(`data-silos`,t.message,e.title),u.error(o.red(t.message))}}),f||=!e}if($.length>0){let t=await ae(n,{input:$,logger:e});f||=!t}if(B){let t=await he(n,B,{logger:e});f||=!t}return{success:!f,errors:d,warnings:l.length>0?l:void 0}}function N(e,...t){let n=JSON.parse(JSON.stringify(e));return t.forEach(e=>{c(e).forEach(([e,t])=>{n[e]===void 0?n[e]=t:Array.isArray(t)?n[e]=[...n[e],...t]:n[e]=t})}),n}export{A as i,M as n,j as r,N as t};
3
+ //# sourceMappingURL=mergeTranscendInputs-DjPe49yR.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mergeTranscendInputs-DjPe49yR.mjs","names":[],"sources":["../src/lib/preference-management/validatePreferenceManagementSlugs.ts","../src/lib/graphql/ensureAllDataSubjectsExist.ts","../src/lib/graphql/normalizeDeletionDependencies.ts","../src/lib/graphql/syncDataSilos.ts","../src/lib/graphql/syncConfigurationToTranscend.ts","../src/lib/mergeTranscendInputs.ts"],"sourcesContent":["import type { TranscendInput } from '../../codecs.js';\n\n/** Slugs for preference topics and option values must be alphabetical letters only. */\nexport const PREFERENCE_SLUG_REGEX = /^[A-Za-z]+$/;\n\n/**\n * Validate preference topic and option value slugs before push.\n *\n * @param input - Parsed transcend.yml input\n * @returns List of validation error messages (empty when valid)\n */\nexport function validatePreferenceManagementSlugs(input: TranscendInput): string[] {\n const errors: string[] = [];\n\n const validateSlug = (slug: string, context: string): void => {\n if (!PREFERENCE_SLUG_REGEX.test(slug)) {\n errors.push(\n `${context}: slug \"${slug}\" is invalid — slugs must contain only alphabetical letters (A-Z, a-z). ` +\n 'Topic slugs are normalized to PascalCase server-side, so YAML slugs should already be PascalCase ' +\n 'or matching will break on subsequent pulls.',\n );\n }\n };\n\n for (const option of input['preference-options'] ?? []) {\n validateSlug(option.slug, 'preference-options');\n }\n\n for (const purpose of input.purposes ?? []) {\n for (const topic of purpose['preference-topics'] ?? []) {\n validateSlug(topic.slug, `purposes (topic \"${topic.title}\")`);\n for (const option of topic.options ?? []) {\n validateSlug(option.slug, `purposes (topic \"${topic.title}\" option \"${option.title}\")`);\n }\n }\n }\n\n return errors;\n}\n","import { createDataSubject, fetchAllDataSubjects, type DataSubject } from '@transcend-io/sdk';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { keyBy, flatten, uniq, difference } from 'lodash-es';\n\nimport { TranscendInput } from '../../codecs.js';\nimport { logger } from '../../logger.js';\n\n/**\n * Fetch all of the data subjects in the organization\n *\n * @param input - Input to fetch\n * @param client - GraphQL client\n * @param fetchAll - When true, always fetch all subjects\n * @returns The list of data subjects\n */\nexport async function ensureAllDataSubjectsExist(\n {\n 'data-silos': dataSilos = [],\n 'data-subjects': dataSubjects = [],\n 'processing-activities': processingActivities = [],\n enrichers = [],\n }: TranscendInput,\n client: GraphQLClient,\n fetchAll = false,\n): Promise<{ [type in string]: DataSubject }> {\n const expectedDataSubjects = uniq([\n ...flatten(dataSilos.map((silo) => silo['data-subjects'] || []) || []),\n ...flatten(processingActivities.map(({ dataSubjectTypes }) => dataSubjectTypes ?? []) ?? []),\n ...flatten(enrichers.map((enricher) => enricher['data-subjects'] || []) || []),\n ...dataSubjects.map((subject) => subject.type),\n ]);\n if (expectedDataSubjects.length === 0 && !fetchAll) {\n return {};\n }\n\n const internalSubjects = await fetchAllDataSubjects(client, { logger });\n const dataSubjectByName = keyBy(internalSubjects, 'type');\n\n const missingDataSubjects = difference(\n expectedDataSubjects,\n internalSubjects.map(({ type }) => type),\n );\n\n if (missingDataSubjects.length > 0) {\n logger.info(colors.magenta(`Creating ${missingDataSubjects.length} new data subjects...`));\n for (const dataSubjectType of missingDataSubjects) {\n logger.info(colors.magenta(`Creating data subject ${dataSubjectType}...`));\n const created = await createDataSubject(client, { input: dataSubjectType, logger });\n logger.info(colors.green(`Created data subject ${dataSubjectType}!`));\n dataSubjectByName[dataSubjectType] = created;\n }\n }\n\n return dataSubjectByName;\n}\n","import type { DependedOnDataSiloInput } from '@transcend-io/sdk';\nimport { uniq } from 'lodash-es';\n\nimport type { DeletionDependencies, DeletionDependencyInput } from '../../codecs.js';\n\n/**\n * Convert the `deletion-dependencies` entries for a single data silo into the\n * `dependedOnDataSilos` input accepted by the `updateDataSilos` mutation.\n *\n * A list of titles becomes a single global entry. A list of objects may declare\n * at most one global configuration (`{ titles }`) plus per-workflow overrides;\n * workflows that are absent from the list are left untouched.\n *\n * @param dependencies - The `deletion-dependencies` entries from transcend.yml\n * @param dataSiloTitle - Title of the data silo being synced, used in error messages\n * @returns The dependency entries to send to the API\n */\nexport function normalizeDeletionDependencies(\n dependencies: DeletionDependencies,\n dataSiloTitle: string,\n): DependedOnDataSiloInput[] {\n if (dependencies.length === 0) {\n return [];\n }\n\n // Legacy / no-overrides form: a flat list of data silo titles\n if (typeof dependencies[0] === 'string') {\n return [{ titles: uniq(dependencies as string[]) }];\n }\n\n let globalTitles: string[] | undefined;\n const workflowOverrides: DependedOnDataSiloInput[] = [];\n const seenWorkflows = new Set<string>();\n\n /**\n * Record an override for a single workflow, rejecting duplicates before the API does\n * so that the error names the data silo\n *\n * @param workflow - Internal name of the workflow being overridden\n * @param override - Titles or reset flag to send for that workflow\n */\n const addWorkflowOverride = (\n workflow: string,\n override: Omit<DependedOnDataSiloInput, 'workflowConfigInternalName'>,\n ): void => {\n if (seenWorkflows.has(workflow)) {\n throw new Error(\n `Data silo \"${dataSiloTitle}\" has multiple deletion-dependencies entries for workflow ` +\n `\"${workflow}\". Combine them into a single entry.`,\n );\n }\n seenWorkflows.add(workflow);\n workflowOverrides.push({ workflowConfigInternalName: workflow, ...override });\n };\n\n (dependencies as DeletionDependencyInput[]).forEach((dependency) => {\n // io-ts codecs allow extra properties, so this combination decodes cleanly\n // even though the two halves contradict each other\n if ('reset-to-global' in dependency && 'titles' in dependency) {\n throw new Error(\n `Data silo \"${dataSiloTitle}\" has a deletion-dependencies entry for workflow ` +\n `\"${dependency.workflow}\" that sets both \"reset-to-global\" and \"titles\". ` +\n 'Use \"titles: []\" to override the global configuration with no dependencies, ' +\n 'or \"reset-to-global: true\" to fall back to the global configuration.',\n );\n }\n\n if ('reset-to-global' in dependency) {\n addWorkflowOverride(dependency.workflow, { resetToGlobal: true });\n return;\n }\n\n if (dependency.workflow) {\n addWorkflowOverride(dependency.workflow, { titles: dependency.titles });\n return;\n }\n\n if (globalTitles !== undefined) {\n throw new Error(\n `Data silo \"${dataSiloTitle}\" has multiple global deletion-dependencies entries. ` +\n 'Combine them into a single `{ titles: [...] }` entry.',\n );\n }\n globalTitles = dependency.titles;\n });\n\n return [\n ...(globalTitles !== undefined ? [{ titles: uniq(globalTitles) }] : []),\n ...workflowOverrides,\n ];\n}\n","import {\n makeGraphQLRequest,\n ApiKey,\n convertToDataSubjectBlockList,\n type DataSubject,\n fetchAllDataSilos,\n type DataSilo,\n CREATE_DATA_SILOS,\n UPDATE_DATA_SILOS,\n UPDATE_OR_CREATE_DATA_POINT,\n} from '@transcend-io/sdk';\nimport { apply } from '@transcend-io/type-utils';\nimport { mapSeries, map } from '@transcend-io/utils';\n/* eslint-disable max-lines */\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { chunk, keyBy } from 'lodash-es';\n\nimport { DataSiloInput } from '../../codecs.js';\nimport { logger } from '../../logger.js';\n\nconst BATCH_SILOS_LIMIT = 20;\n\n/**\n * Sync a data silo configuration\n *\n * @param dataSilos - Data silos to sync\n * @param client - GraphQL client\n * @param options - Options\n * @returns Data silo info\n */\nexport async function syncDataSilos(\n dataSilos: DataSiloInput[],\n client: GraphQLClient,\n {\n pageSize,\n dataSubjectsByName,\n apiKeysByTitle,\n }: {\n /** Page size */\n pageSize: number;\n /** The data subjects in the organization */\n dataSubjectsByName: { [type in string]: DataSubject };\n /** API key title to API key */\n apiKeysByTitle: { [title in string]: ApiKey };\n },\n): Promise<{\n /** Whether successfully updated */\n success: boolean;\n /** A mapping between data silo title to data silo ID */\n dataSiloTitleToId: { [k in string]: string };\n}> {\n let encounteredError = false;\n\n // Time duration\n const t0 = new Date().getTime();\n logger.info(colors.magenta(`Syncing \"${dataSilos.length}\" data silos...`));\n\n // Determine the set of data silos that already exist\n const existingDataSilos = await fetchAllDataSilos(client, {\n titles: dataSilos.map(({ title }) => title),\n pageSize,\n logger,\n });\n\n // Create a mapping of title -> existing silo, if it exists\n const existingDataSiloByTitle = keyBy<Pick<DataSilo, 'id' | 'title'>>(existingDataSilos, 'title');\n\n // Create new silos that do not exist\n const newDataSiloInputs = dataSilos.filter(({ title }) => !existingDataSiloByTitle[title]);\n if (newDataSiloInputs.length > 0) {\n logger.info(\n colors.magenta(`Creating \"${newDataSiloInputs.length}\" data silos that did not exist...`),\n );\n\n // Batch the creation\n const chunked = chunk(newDataSiloInputs, BATCH_SILOS_LIMIT);\n await mapSeries(chunked, async (dependencyUpdateChunk) => {\n const {\n createDataSilos: { dataSilos },\n } = await makeGraphQLRequest<{\n /** Mutation result */\n createDataSilos: {\n /** New data silos */\n dataSilos: Pick<DataSilo, 'id' | 'title'>[];\n };\n }>(client, CREATE_DATA_SILOS, {\n variables: {\n input: dependencyUpdateChunk.map((input) => ({\n name: input['outer-type'] || input.integrationName,\n title: input.title,\n country: input.country,\n countrySubDivision: input.countrySubDivision,\n sombraId: input['sombra-id'],\n })),\n },\n logger,\n });\n\n // save mapping of title and id\n dataSilos.forEach((silo) => {\n existingDataSiloByTitle[silo.title] = silo;\n });\n });\n\n logger.info(colors.green(`Successfully created \"${newDataSiloInputs.length}\" data silos!`));\n }\n\n // Batch the updates\n const chunkedUpdates = chunk(dataSilos, BATCH_SILOS_LIMIT);\n await mapSeries(chunkedUpdates, async (dataSiloUpdateChunk, ind) => {\n logger.info(\n colors.magenta(\n `[Batch ${ind + 1}/${chunkedUpdates.length}] Syncing \"${\n dataSiloUpdateChunk.length\n }\" data silos`,\n ),\n );\n await makeGraphQLRequest<{\n /** Mutation result */\n updateDataSilos: {\n /** New data silos */\n dataSilos: Pick<DataSilo, 'id' | 'title'>[];\n };\n }>(client, UPDATE_DATA_SILOS, {\n variables: {\n input: {\n dataSilos: dataSiloUpdateChunk.map((input) => ({\n id: existingDataSiloByTitle[input.title].id,\n country: input.country,\n countrySubDivision: input.countrySubDivision,\n url: input.url,\n headers: input.headers,\n description: input.description,\n identifiers: input['identity-keys'],\n isLive: !input.disabled,\n ownerEmails: input.owners,\n teamNames: input.teams,\n // clear out the global config if not specified, otherwise the update needs to be\n // applied after all data silos are created\n dependedOnDataSilos: input['deletion-dependencies'] ? undefined : [{ titles: [] }],\n apiKeyId: input['api-key-title']\n ? apiKeysByTitle[input['api-key-title']].id\n : undefined,\n dataSubjectBlockListIds: input['data-subjects']\n ? convertToDataSubjectBlockList(input['data-subjects'], dataSubjectsByName)\n : undefined,\n attributes: input.attributes,\n businessEntityTitles: input.businessEntityTitles,\n sombraId: input['sombra-id'],\n // AVC settings\n notifyEmailAddress: input['email-settings']?.['notify-email-address'],\n promptAVendorEmailSendFrequency: input['email-settings']?.['send-frequency'],\n promptAVendorEmailSendType: input['email-settings']?.['send-type'],\n promptAVendorEmailIncludeIdentifiersAttachment:\n input['email-settings']?.['include-identifiers-attachment'],\n promptAVendorEmailCompletionLinkType: input['email-settings']?.['completion-link-type'],\n manualWorkRetryFrequency: input['email-settings']?.['manual-work-retry-frequency'],\n })),\n },\n },\n logger,\n });\n logger.info(\n colors.green(\n `[Batch ${ind + 1}/${chunkedUpdates.length}] Synced \"${\n dataSiloUpdateChunk.length\n }\" data silos!`,\n ),\n );\n });\n\n // Sync datapoints\n\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n const dataSilosWithDataPoints = dataSilos.filter(({ datapoints = [] }) => datapoints.length > 0);\n const totalDataPoints = dataSilos\n .map(({ datapoints = [] }) => datapoints.length)\n .reduce((acc, count) => acc + count, 0);\n logger.info(\n colors.magenta(\n `Syncing \"${totalDataPoints}\" datapoints from \"${dataSilosWithDataPoints.length}\" data silos...`,\n ),\n );\n progressBar.start(totalDataPoints, 0);\n let total = 0;\n\n await map(\n dataSilosWithDataPoints,\n async ({ datapoints, title }) => {\n if (datapoints) {\n await mapSeries(datapoints, async (datapoint) => {\n const fields = datapoint.fields\n ? datapoint.fields.map(\n ({ key, description, categories, purposes, attributes, ...rest }) =>\n // TODO: Support setting title separately from the 'key/name'\n ({\n name: key,\n description,\n categories: !categories\n ? undefined\n : categories.map((category) => ({\n ...category,\n name: category.name || 'Other',\n })),\n purposes: !purposes\n ? undefined\n : purposes.map((purpose) => ({\n ...purpose,\n name: purpose.name || 'Other',\n })),\n attributes,\n accessRequestVisibilityEnabled: rest['access-request-visibility-enabled'],\n erasureRequestRedactionEnabled: rest['erasure-request-redaction-enabled'],\n }),\n )\n : undefined;\n\n const payload = {\n dataSiloId: existingDataSiloByTitle[title].id,\n path: datapoint.path,\n name: datapoint.key,\n title: datapoint.title,\n description: datapoint.description,\n ...(datapoint.owners\n ? {\n ownerEmails: datapoint.owners,\n }\n : {}),\n ...(datapoint.teams\n ? {\n teamNames: datapoint.teams,\n }\n : {}),\n ...(datapoint['data-collection-tag']\n ? { dataCollectionTag: datapoint['data-collection-tag'] }\n : {}),\n querySuggestions: !datapoint['privacy-action-queries']\n ? undefined\n : Object.entries(datapoint['privacy-action-queries']).map(([key, value]) => ({\n requestType: key,\n suggestedQuery: value,\n })),\n enabledActions: datapoint['privacy-actions'] || [], // clear out when not specified\n subDataPoints: fields,\n };\n\n // Ensure no duplicate sub-datapoints are provided\n const subDataPointsToUpdate = (payload.subDataPoints || []).map(({ name }) => name);\n const duplicateDataPoints = subDataPointsToUpdate.filter(\n (name, index) => subDataPointsToUpdate.indexOf(name) !== index,\n );\n if (duplicateDataPoints.length > 0) {\n logger.info(\n colors.red(\n `\\nCannot update datapoint \"${\n datapoint.key\n }\" as it has duplicate sub-datapoints with the same name: \\n${duplicateDataPoints.join(\n '\\n',\n )}`,\n ),\n );\n encounteredError = true;\n } else {\n try {\n await makeGraphQLRequest(client, UPDATE_OR_CREATE_DATA_POINT, {\n variables: payload,\n logger,\n });\n } catch (err) {\n logger.info(\n colors.red(\n `\\nFailed to update datapoint \"${datapoint.key}\" for data silo \"${title}\"! - \\n${err.message}`,\n ),\n );\n encounteredError = true;\n }\n }\n total += 1;\n progressBar.update(total);\n });\n }\n },\n {\n concurrency: 10,\n },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Synced \"${dataSilos.length}\" data silos and \"${totalDataPoints}\" datapoints in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n return {\n success: !encounteredError,\n dataSiloTitleToId: apply(existingDataSiloByTitle, ({ id }) => id),\n };\n}\n/* eslint-enable max-lines */\n","import {\n fetchAllActions,\n fetchAllAttributes,\n fetchAllDataSubjects,\n fetchApiKeys,\n fetchIdentifiersAndCreateMissing,\n syncAction,\n syncActionItemCollections,\n syncActionItems,\n syncAttribute,\n syncBusinessEntities,\n syncDataCategories,\n syncConsentManager,\n syncCookies,\n syncDataFlows,\n syncDataSubject,\n syncDataSiloDependencies,\n syncEnricher,\n syncIdentifier,\n syncIntlMessages,\n syncPartitions,\n syncPolicies,\n syncPrivacyCenter,\n syncProcessingActivities,\n syncProcessingPurposes,\n syncConsentWorkflowTriggers,\n syncWorkflowConfigs,\n syncPreferenceOptionValues,\n syncPurposes,\n syncPreferenceTopics,\n syncTeams,\n syncTemplate,\n syncVendors,\n type DependedOnDataSiloInput,\n type Identifier,\n} from '@transcend-io/sdk';\nimport { map, type Logger, type SyncError, type SyncResult } from '@transcend-io/utils';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\n\n/* eslint-disable max-lines */\nimport { TranscendInput } from '../../codecs.js';\nimport { logger } from '../../logger.js';\nimport { validatePreferenceManagementSlugs } from '../preference-management/validatePreferenceManagementSlugs.js';\nimport { ensureAllDataSubjectsExist } from './ensureAllDataSubjectsExist.js';\nimport { normalizeDeletionDependencies } from './normalizeDeletionDependencies.js';\nimport { syncDataSilos } from './syncDataSilos.js';\n\nconst CONCURRENCY = 10;\n\n/**\n * Sync the yaml input back to Transcend using the GraphQL APIs\n *\n * @param input - The yml input\n * @param client - GraphQL client\n * @param pageSize - Page size\n * @returns Structured sync result with per-resource errors\n */\nexport async function syncConfigurationToTranscend(\n input: TranscendInput,\n client: GraphQLClient,\n {\n pageSize = 50,\n // TODO: https://transcend.height.app/T-23779\n publishToPrivacyCenter = true,\n classifyService = false,\n deleteExtraAttributeValues = false,\n logger: syncLogger,\n warnings = [],\n }: {\n /** Page size */\n pageSize?: number;\n /** When true, skip publishing to privacy center */\n publishToPrivacyCenter?: boolean;\n /** When true, delete any attributes being synced up */\n deleteExtraAttributeValues?: boolean;\n /** classify data flow service if missing */\n classifyService?: boolean;\n /** Optional logger (e.g. collecting logger for MCP debug responses) */\n logger?: Logger;\n /** Non-fatal warnings to include in the result */\n warnings?: string[];\n },\n): Promise<SyncResult> {\n const activeLogger = syncLogger ?? logger;\n const errors: SyncError[] = [];\n let encounteredError = false;\n\n const recordError = (resource: string, message: string, item?: string): void => {\n errors.push({ resource, item, message });\n encounteredError = true;\n };\n\n activeLogger.info(colors.magenta(`Fetching data with page size ${pageSize}...`));\n\n const {\n templates,\n attributes,\n actions,\n identifiers,\n 'data-subjects': dataSubjects,\n 'business-entities': businessEntities,\n enrichers,\n cookies,\n 'consent-manager': consentManager,\n 'data-silos': dataSilos,\n 'data-flows': dataFlows,\n vendors,\n 'data-categories': dataCategories,\n 'processing-activities': processingActivities,\n 'processing-purposes': processingPurposes,\n 'action-items': actionItems,\n 'action-item-collections': actionItemCollections,\n teams,\n 'privacy-center': privacyCenter,\n messages,\n policies,\n partitions,\n 'preference-workflow-configs': preferenceWorkflowConfigs,\n 'workflow-configs': workflowConfigs,\n } = input;\n\n const preferenceOptions = input['preference-options'];\n const purposes = input.purposes;\n\n const preferenceSlugErrors = validatePreferenceManagementSlugs(input);\n if (preferenceSlugErrors.length > 0) {\n for (const message of preferenceSlugErrors) {\n recordError('preference-slugs', message);\n }\n return {\n success: false,\n errors,\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n }\n\n const [identifierByName, dataSubjectsByName, apiKeyTitleMap] = await Promise.all([\n // Ensure all identifiers are created and create a map from name -> identifier.id\n enrichers || identifiers\n ? fetchIdentifiersAndCreateMissing(client, {\n input,\n skipPublish: !publishToPrivacyCenter,\n logger,\n })\n : ({} as { [k in string]: Identifier }),\n // Grab all data subjects in the organization\n dataSilos || dataSubjects || enrichers || processingActivities\n ? ensureAllDataSubjectsExist(input, client)\n : {},\n // Grab API keys\n dataSilos &&\n dataSilos\n .map((dataSilo) => dataSilo['api-key-title'] || [])\n .reduce((acc, lst) => acc + lst.length, 0) > 0\n ? fetchApiKeys(client, { apiKeyInputs: input, logger })\n : {},\n ]);\n\n if (preferenceWorkflowConfigs?.length) {\n const preferenceWorkflowConfigsSuccess = await syncConsentWorkflowTriggers(\n client,\n preferenceWorkflowConfigs,\n {\n logger: activeLogger,\n pageSize,\n },\n );\n if (!preferenceWorkflowConfigsSuccess) {\n recordError('preference-workflow-configs', 'Failed to sync preference workflow configs');\n }\n }\n\n if (workflowConfigs?.length) {\n const workflowConfigsSuccess = await syncWorkflowConfigs(client, workflowConfigs, {\n logger: activeLogger,\n });\n if (!workflowConfigsSuccess) {\n recordError('workflow-configs', 'Failed to sync workflow configs');\n }\n }\n\n if (preferenceOptions?.length) {\n const preferenceOptionsSuccess = await syncPreferenceOptionValues(client, preferenceOptions, {\n logger: activeLogger,\n });\n if (!preferenceOptionsSuccess) {\n recordError('preference-options', 'Failed to sync preference option values');\n }\n }\n\n // Sync consent purposes and their nested preference topics.\n // Order matters: option values (above) exist first, then purposes, then topics\n // (which link to their purpose by ID and to option values by slug).\n if (purposes?.length) {\n const { success: purposesSuccess, purposeIdByTrackingType } = await syncPurposes(\n client,\n purposes,\n { logger: activeLogger },\n );\n if (!purposesSuccess) {\n recordError('purposes', 'Failed to sync one or more purposes');\n }\n\n const topics = purposes.flatMap((purpose) =>\n (purpose['preference-topics'] ?? []).map((topic) => ({\n ...topic,\n 'tracking-type': purpose.trackingType,\n })),\n );\n if (topics.length > 0) {\n const topicsSuccess = await syncPreferenceTopics(client, topics, {\n logger: activeLogger,\n purposeIdByTrackingType,\n });\n if (!topicsSuccess) {\n recordError('preference-topics', 'Failed to sync one or more preference topics');\n }\n }\n }\n\n // Sync consent manager\n if (consentManager) {\n activeLogger.info(colors.magenta('Syncing consent manager...'));\n try {\n await syncConsentManager(client, consentManager, { logger: activeLogger });\n activeLogger.info(colors.green('Successfully synced consent manager!'));\n } catch (err) {\n recordError('consent-manager', (err as Error).message);\n activeLogger.error(colors.red(`Failed to sync consent manager! - ${(err as Error).message}`));\n }\n }\n\n if (teams) {\n const teamsSuccess = await syncTeams(client, teams, { logger });\n encounteredError = encounteredError || !teamsSuccess;\n }\n\n // Sync email templates\n if (templates) {\n logger.info(colors.magenta(`Syncing \"${templates.length}\" email templates...`));\n await map(\n templates,\n async (template) => {\n logger.info(colors.magenta(`Syncing template \"${template.title}\"...`));\n try {\n await syncTemplate(client, template, { logger });\n logger.info(colors.green(`Successfully synced template \"${template.title}\"!`));\n } catch (err) {\n encounteredError = true;\n logger.error(colors.red(`Failed to sync template \"${template.title}\"! - ${err.message}`));\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${templates.length}\" email templates!`));\n }\n\n // Sync business entities\n if (businessEntities) {\n const businessEntitySuccess = await syncBusinessEntities(client, businessEntities, { logger });\n encounteredError = encounteredError || !businessEntitySuccess;\n }\n\n // Sync vendors\n if (vendors) {\n const vendorsSuccess = await syncVendors(client, vendors, { logger });\n encounteredError = encounteredError || !vendorsSuccess;\n }\n\n // Sync data categories\n if (dataCategories) {\n const dataCategoriesSuccess = await syncDataCategories(client, dataCategories, { logger });\n encounteredError = encounteredError || !dataCategoriesSuccess;\n }\n\n // Sync processing purposes\n if (processingPurposes) {\n const processingPurposesSuccess = await syncProcessingPurposes(client, processingPurposes, {\n logger,\n });\n encounteredError = encounteredError || !processingPurposesSuccess;\n }\n\n // Sync partitions\n if (partitions) {\n const partitionsSuccess = await syncPartitions(client, partitions, { logger });\n encounteredError = encounteredError || !partitionsSuccess;\n }\n\n // Sync cookies\n if (cookies) {\n const cookiesSuccess = await syncCookies(client, cookies, { logger });\n encounteredError = encounteredError || !cookiesSuccess;\n }\n\n // Sync action item collections\n if (actionItemCollections) {\n const actionItemCollectionsSuccess = await syncActionItemCollections(\n client,\n actionItemCollections,\n { logger },\n );\n encounteredError = encounteredError || !actionItemCollectionsSuccess;\n }\n\n // Sync attributes\n if (attributes) {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${attributes.length}\" attributes...`));\n const existingAttributes = await fetchAllAttributes(client, { logger });\n await map(\n attributes,\n async (attribute) => {\n const existing = existingAttributes.find((attr) => attr.name === attribute.name);\n\n logger.info(colors.magenta(`Syncing attribute \"${attribute.name}\"...`));\n try {\n await syncAttribute(client, attribute, {\n existingAttribute: existing,\n deleteExtraAttributeValues,\n logger,\n });\n logger.info(colors.green(`Successfully synced attribute \"${attribute.name}\"!`));\n } catch (err) {\n encounteredError = true;\n logger.error(\n colors.red(`Failed to sync attribute \"${attribute.name}\"! - ${err.message}`),\n );\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${attributes.length}\" attributes!`));\n }\n\n // Sync action items\n if (actionItems) {\n const actionItemsSuccess = await syncActionItems(client, actionItems, { logger });\n encounteredError = encounteredError || !actionItemsSuccess;\n }\n\n // Sync enrichers\n if (enrichers) {\n logger.info(colors.magenta(`Syncing \"${enrichers.length}\" enrichers...`));\n await map(\n enrichers,\n async (enricher) => {\n logger.info(colors.magenta(`Syncing enricher \"${enricher.title}\"...`));\n try {\n await syncEnricher(client, {\n input: enricher,\n identifierByName,\n dataSubjectsByName,\n logger,\n });\n logger.info(colors.green(`Successfully synced enricher \"${enricher.title}\"!`));\n } catch (err) {\n encounteredError = true;\n logger.error(colors.red(`Failed to sync enricher \"${enricher.title}\"! - ${err.message}`));\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${enrichers.length}\" enrichers!`));\n }\n\n // Sync identifiers\n if (identifiers) {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${identifiers.length}\" identifiers...`));\n await map(\n identifiers,\n async (identifier) => {\n const existing = identifierByName[identifier.name];\n if (!existing) {\n throw new Error(\n `Failed to find identifier with name: ${identifier.type}. Should have been auto-created by cli.`,\n );\n }\n\n logger.info(colors.magenta(`Syncing identifier \"${identifier.type}\"...`));\n try {\n await syncIdentifier(client, {\n input: identifier,\n dataSubjectsByName,\n identifierId: existing.id,\n skipPublish: !publishToPrivacyCenter,\n logger,\n });\n logger.info(colors.green(`Successfully synced identifier \"${identifier.type}\"!`));\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to sync identifier \"${identifier.type}\"! - ${err.message}`),\n );\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${identifiers.length}\" identifiers!`));\n }\n\n // Sync actions\n if (actions) {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${actions.length}\" actions...`));\n const existingActions = await fetchAllActions(client, { logger });\n await map(\n actions,\n async (action) => {\n const existing = existingActions.find((act) => act.type === action.type);\n if (!existing) {\n throw new Error(\n `Failed to find action with type: ${action.type}. Should have already existing in the organization.`,\n );\n }\n\n logger.info(colors.magenta(`Syncing action \"${action.type}\"...`));\n try {\n await syncAction(\n client,\n {\n action,\n actionId: existing.id,\n skipPublish: !publishToPrivacyCenter,\n },\n { logger },\n );\n logger.info(colors.green(`Successfully synced action \"${action.type}\"!`));\n } catch (err) {\n encounteredError = true;\n logger.error(colors.red(`Failed to sync action \"${action.type}\"! - ${err.message}`));\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${actions.length}\" actions!`));\n }\n\n // Sync data subjects\n if (dataSubjects) {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${dataSubjects.length}\" data subjects...`));\n const existingDataSubjects = await fetchAllDataSubjects(client, { logger });\n await map(\n dataSubjects,\n async (dataSubject) => {\n const existing = existingDataSubjects.find((subj) => subj.type === dataSubject.type);\n if (!existing) {\n throw new Error(\n `Failed to find data subject with type: ${dataSubject.type}. Should have already existing in the organization.`,\n );\n }\n\n logger.info(colors.magenta(`Syncing data subject \"${dataSubject.type}\"...`));\n try {\n await syncDataSubject(client, {\n input: dataSubject,\n dataSubjectId: existing.id,\n skipPublish: !publishToPrivacyCenter,\n logger,\n });\n logger.info(colors.green(`Successfully synced data subject \"${dataSubject.type}\"!`));\n } catch (err) {\n encounteredError = true;\n // supportsAuthorizedAgent is gated on the Authorized Agents feature being\n // enabled for the organization; surface a clearer hint than the raw API error\n const hint =\n dataSubject.supportsAuthorizedAgent !== undefined &&\n /authorized.agent/i.test(err.message)\n ? ' (enable the Authorized Agents feature for this organization before setting \"supportsAuthorizedAgent\")'\n : '';\n logger.info(\n colors.red(\n `Failed to sync data subject \"${dataSubject.type}\"! - ${err.message}${hint}`,\n ),\n );\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${dataSubjects.length}\" data subjects!`));\n }\n\n // Sync data flows\n if (dataFlows) {\n const syncedDataFlows = await syncDataFlows(client, dataFlows, { classifyService, logger });\n encounteredError = encounteredError || !syncedDataFlows;\n }\n\n // Sync privacy center\n if (privacyCenter) {\n try {\n const privacyCenterSuccess = await syncPrivacyCenter(client, privacyCenter, {\n logger,\n skipPublish: !publishToPrivacyCenter,\n });\n if (!privacyCenterSuccess) {\n recordError('privacy-center', 'Failed to sync privacy center');\n }\n } catch (err) {\n recordError('privacy-center', (err as Error).message);\n }\n }\n\n // Sync messages\n if (messages) {\n const messagesSuccess = await syncIntlMessages(client, messages, { logger });\n encounteredError = encounteredError || !messagesSuccess;\n }\n\n // Sync policies\n if (policies) {\n const policiesSuccess = await syncPolicies(client, policies, { logger });\n encounteredError = encounteredError || !policiesSuccess;\n }\n\n // Store dependency updates\n const dependencyUpdates: [string, DependedOnDataSiloInput[]][] = [];\n // Sync data silos\n if (dataSilos) {\n const { success, dataSiloTitleToId } = await syncDataSilos(dataSilos, client, {\n dataSubjectsByName,\n apiKeysByTitle: apiKeyTitleMap,\n pageSize,\n });\n dataSilos?.forEach((dataSilo) => {\n // Queue up dependency update\n const dependencies = dataSilo['deletion-dependencies'];\n if (dependencies) {\n try {\n dependencyUpdates.push([\n dataSiloTitleToId[dataSilo.title],\n normalizeDeletionDependencies(dependencies, dataSilo.title),\n ]);\n } catch (err) {\n recordError('data-silos', (err as Error).message, dataSilo.title);\n activeLogger.error(colors.red((err as Error).message));\n }\n }\n });\n encounteredError = encounteredError || !success;\n }\n\n // Dependencies updated at the end after all data silos are created\n if (dependencyUpdates.length > 0) {\n const dependenciesSuccess = await syncDataSiloDependencies(client, {\n input: dependencyUpdates,\n logger,\n });\n encounteredError = encounteredError || !dependenciesSuccess;\n }\n\n // Update processing activities\n if (processingActivities) {\n const processingActivitySuccess = await syncProcessingActivities(client, processingActivities, {\n logger,\n });\n encounteredError = encounteredError || !processingActivitySuccess;\n }\n\n if (publishToPrivacyCenter) {\n // TODO: https://transcend.height.app/T-23779\n }\n\n return {\n success: !encounteredError,\n errors,\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n}\n/* eslint-enable max-lines */\n","import { getEntries } from '@transcend-io/type-utils';\n\nimport { TranscendInput } from '../codecs.js';\n\n/**\n * Combine a set of TranscendInput yaml files into a single yaml\n *\n * @param base - Base input\n * @param inputs - The list of inputs\n * @returns Merged input\n */\nexport function mergeTranscendInputs(\n base: TranscendInput,\n ...inputs: TranscendInput[]\n): TranscendInput {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const cloned: any = JSON.parse(JSON.stringify(base));\n inputs.forEach((input) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getEntries(input).forEach(([key, value]: [any, any]) => {\n if (cloned[key] === undefined) {\n cloned[key] = value;\n } else if (Array.isArray(value)) {\n cloned[key] = [...cloned[key], ...value];\n } else {\n cloned[key] = value;\n }\n });\n });\n return cloned;\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{a as e}from"./constants-BjwEFOS4.mjs";import{t}from"./logger-Ckep4QXn.mjs";import{r as n}from"./request-BIplTb3L.mjs";import{r}from"./fetchAllRequests-DP24WqrP.mjs";import{RequestAction as i}from"@transcend-io/privacy-types";import a from"colors";import{buildTranscendGraphQLClient as o,fetchAllTemplates as s,makeGraphQLRequest as c}from"@transcend-io/sdk";import{map as l}from"@transcend-io/utils";import u from"cli-progress";async function d({requestActions:d=Object.values(i),auth:f,requestIds:p,createdAtBefore:m,days:h=45,daysLeft:g=10,createdAtAfter:_,updatedAtBefore:v,updatedAtAfter:y,emailTemplate:b=`Additional Time Needed`,concurrency:x=100,transcendUrl:S=e}){let C=o(S,f),w=new Date().getTime(),T=new u.SingleBar({},u.Presets.shades_classic),E=(await s(C,{logger:t,filterBy:{title:b}})).find(e=>e.title===b);if(!E)throw Error(`Failed to find a template with title: "${b}"`);let D=await r(C,{actions:d,createdAtBefore:m,createdAtAfter:_,updatedAtBefore:v,updatedAtAfter:y,isSilent:!1,isClosed:!1,requestIds:p});D=D.filter(e=>typeof e.daysRemaining==`number`&&e.daysRemaining<g),t.info(a.magenta(`Notifying "${D.length}" that more time is needed.`));let O=0;T.start(D.length,0),await l(D,async e=>{await c(C,n,{variables:{input:{requestId:e.id,template:E.template.defaultMessage,subject:E.subject.defaultMessage,additionalTime:h}},logger:t}),O+=1,T.update(O)},{concurrency:x}),T.stop();let k=new Date().getTime()-w;return t.info(a.green(`Successfully marked ${O} requests as silent mode in "${k/1e3}" seconds!`)),D.length}export{d as t};
2
- //# sourceMappingURL=notifyPrivacyRequestsAdditionalTime-mpYqqBxR.mjs.map
1
+ import{a as e}from"./constants-CAOyAsNX.mjs";import{t}from"./logger-Ckep4QXn.mjs";import{r as n}from"./request-BIplTb3L.mjs";import{r}from"./fetchAllRequests-DP24WqrP.mjs";import{RequestAction as i}from"@transcend-io/privacy-types";import a from"colors";import{buildTranscendGraphQLClient as o,fetchAllTemplates as s,makeGraphQLRequest as c}from"@transcend-io/sdk";import{map as l}from"@transcend-io/utils";import u from"cli-progress";async function d({requestActions:d=Object.values(i),auth:f,requestIds:p,createdAtBefore:m,days:h=45,daysLeft:g=10,createdAtAfter:_,updatedAtBefore:v,updatedAtAfter:y,emailTemplate:b=`Additional Time Needed`,concurrency:x=100,transcendUrl:S=e}){let C=o(S,f),w=new Date().getTime(),T=new u.SingleBar({},u.Presets.shades_classic),E=(await s(C,{logger:t,filterBy:{title:b}})).find(e=>e.title===b);if(!E)throw Error(`Failed to find a template with title: "${b}"`);let D=await r(C,{actions:d,createdAtBefore:m,createdAtAfter:_,updatedAtBefore:v,updatedAtAfter:y,isSilent:!1,isClosed:!1,requestIds:p});D=D.filter(e=>typeof e.daysRemaining==`number`&&e.daysRemaining<g),t.info(a.magenta(`Notifying "${D.length}" that more time is needed.`));let O=0;T.start(D.length,0),await l(D,async e=>{await c(C,n,{variables:{input:{requestId:e.id,template:E.template.defaultMessage,subject:E.subject.defaultMessage,additionalTime:h}},logger:t}),O+=1,T.update(O)},{concurrency:x}),T.stop();let k=new Date().getTime()-w;return t.info(a.green(`Successfully marked ${O} requests as silent mode in "${k/1e3}" seconds!`)),D.length}export{d as t};
2
+ //# sourceMappingURL=notifyPrivacyRequestsAdditionalTime-DPp0MyfT.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"notifyPrivacyRequestsAdditionalTime-mpYqqBxR.mjs","names":[],"sources":["../src/lib/requests/notifyPrivacyRequestsAdditionalTime.ts"],"sourcesContent":["import { RequestAction } from '@transcend-io/privacy-types';\nimport {\n buildTranscendGraphQLClient,\n fetchAllTemplates,\n makeGraphQLRequest,\n} from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\nimport { NOTIFY_ADDITIONAL_TIME, fetchAllRequests } from '../graphql/index.js';\n\n/**\n * Mark a set of privacy requests to be in silent mode.\n * Note requests in silent mode are ignored\n *\n * @param options - Options\n * @returns The number of requests marked silent\n */\nexport async function notifyPrivacyRequestsAdditionalTime({\n requestActions = Object.values(RequestAction),\n auth,\n requestIds,\n createdAtBefore,\n days = 45,\n daysLeft = 10,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n emailTemplate = 'Additional Time Needed',\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions?: RequestAction[];\n /** Filter for requests created before this date */\n createdAtBefore: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Filter for requests updated before this date */\n updatedAtBefore?: Date;\n /** Filter for requests updated after this date */\n updatedAtAfter?: Date;\n /** Email template */\n emailTemplate?: string;\n /** Transcend API key authentication */\n auth: string;\n /** Number of days to extend request by */\n days?: number;\n /**\n * Only notify requests that have less than this number of days until they are considered expired.\n * This allows for re-running the command without notifying the same users multiple times\n */\n daysLeft?: number;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** The set of privacy requests to notify */\n requestIds?: string[];\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n\n // Grab the template with that title\n const matchingTemplates = await fetchAllTemplates(client, {\n logger,\n filterBy: { title: emailTemplate },\n });\n const exactTemplateMatch = matchingTemplates.find((template) => template.title === emailTemplate);\n if (!exactTemplateMatch) {\n throw new Error(`Failed to find a template with title: \"${emailTemplate}\"`);\n }\n\n // Pull in the requests\n let allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n isSilent: false,\n isClosed: false,\n requestIds,\n });\n\n // Filter requests by daysLeft\n allRequests = allRequests.filter(\n (request) => typeof request.daysRemaining === 'number' && request.daysRemaining < daysLeft,\n );\n\n // Notify Transcend\n logger.info(colors.magenta(`Notifying \"${allRequests.length}\" that more time is needed.`));\n\n let total = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToNotify) => {\n await makeGraphQLRequest(client, NOTIFY_ADDITIONAL_TIME, {\n variables: {\n input: {\n requestId: requestToNotify.id,\n template: exactTemplateMatch.template.defaultMessage,\n subject: exactTemplateMatch.subject.defaultMessage,\n additionalTime: days,\n },\n },\n logger,\n });\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully marked ${total} requests as silent mode in \"${totalTime / 1000}\" seconds!`,\n ),\n );\n return allRequests.length;\n}\n"],"mappings":"mbAqBA,eAAsB,EAAoC,CACxD,iBAAiB,OAAO,OAAO,EAAc,CAC7C,OACA,aACA,kBACA,OAAO,GACP,WAAW,GACX,iBACA,kBACA,iBACA,gBAAgB,yBAChB,cAAc,IACd,eAAe,GA6BG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAI,EAAY,UAAU,EAAE,CAAE,EAAY,QAAQ,eAAe,CAO/E,GAAqB,MAJK,EAAkB,EAAQ,CACxD,SACA,SAAU,CAAE,MAAO,EAAe,CACnC,CAAC,EAC2C,KAAM,GAAa,EAAS,QAAU,EAAc,CACjG,GAAI,CAAC,EACH,MAAU,MAAM,0CAA0C,EAAc,GAAG,CAI7E,IAAI,EAAc,MAAM,EAAiB,EAAQ,CAC/C,QAAS,EACT,kBACA,iBACA,kBACA,iBACA,SAAU,GACV,SAAU,GACV,aACD,CAAC,CAGF,EAAc,EAAY,OACvB,GAAY,OAAO,EAAQ,eAAkB,UAAY,EAAQ,cAAgB,EACnF,CAGD,EAAO,KAAK,EAAO,QAAQ,cAAc,EAAY,OAAO,6BAA6B,CAAC,CAE1F,IAAI,EAAQ,EACZ,EAAY,MAAM,EAAY,OAAQ,EAAE,CACxC,MAAM,EACJ,EACA,KAAO,IAAoB,CACzB,MAAM,EAAmB,EAAQ,EAAwB,CACvD,UAAW,CACT,MAAO,CACL,UAAW,EAAgB,GAC3B,SAAU,EAAmB,SAAS,eACtC,QAAS,EAAmB,QAAQ,eACpC,eAAgB,EACjB,CACF,CACD,SACD,CAAC,CAEF,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SACF,CAAG,EAOvB,OALA,EAAO,KACL,EAAO,MACL,uBAAuB,EAAM,+BAA+B,EAAY,IAAK,YAC9E,CACF,CACM,EAAY"}
1
+ {"version":3,"file":"notifyPrivacyRequestsAdditionalTime-DPp0MyfT.mjs","names":[],"sources":["../src/lib/requests/notifyPrivacyRequestsAdditionalTime.ts"],"sourcesContent":["import { RequestAction } from '@transcend-io/privacy-types';\nimport {\n buildTranscendGraphQLClient,\n fetchAllTemplates,\n makeGraphQLRequest,\n} from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\nimport { NOTIFY_ADDITIONAL_TIME, fetchAllRequests } from '../graphql/index.js';\n\n/**\n * Mark a set of privacy requests to be in silent mode.\n * Note requests in silent mode are ignored\n *\n * @param options - Options\n * @returns The number of requests marked silent\n */\nexport async function notifyPrivacyRequestsAdditionalTime({\n requestActions = Object.values(RequestAction),\n auth,\n requestIds,\n createdAtBefore,\n days = 45,\n daysLeft = 10,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n emailTemplate = 'Additional Time Needed',\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions?: RequestAction[];\n /** Filter for requests created before this date */\n createdAtBefore: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Filter for requests updated before this date */\n updatedAtBefore?: Date;\n /** Filter for requests updated after this date */\n updatedAtAfter?: Date;\n /** Email template */\n emailTemplate?: string;\n /** Transcend API key authentication */\n auth: string;\n /** Number of days to extend request by */\n days?: number;\n /**\n * Only notify requests that have less than this number of days until they are considered expired.\n * This allows for re-running the command without notifying the same users multiple times\n */\n daysLeft?: number;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** The set of privacy requests to notify */\n requestIds?: string[];\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n\n // Grab the template with that title\n const matchingTemplates = await fetchAllTemplates(client, {\n logger,\n filterBy: { title: emailTemplate },\n });\n const exactTemplateMatch = matchingTemplates.find((template) => template.title === emailTemplate);\n if (!exactTemplateMatch) {\n throw new Error(`Failed to find a template with title: \"${emailTemplate}\"`);\n }\n\n // Pull in the requests\n let allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n isSilent: false,\n isClosed: false,\n requestIds,\n });\n\n // Filter requests by daysLeft\n allRequests = allRequests.filter(\n (request) => typeof request.daysRemaining === 'number' && request.daysRemaining < daysLeft,\n );\n\n // Notify Transcend\n logger.info(colors.magenta(`Notifying \"${allRequests.length}\" that more time is needed.`));\n\n let total = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToNotify) => {\n await makeGraphQLRequest(client, NOTIFY_ADDITIONAL_TIME, {\n variables: {\n input: {\n requestId: requestToNotify.id,\n template: exactTemplateMatch.template.defaultMessage,\n subject: exactTemplateMatch.subject.defaultMessage,\n additionalTime: days,\n },\n },\n logger,\n });\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully marked ${total} requests as silent mode in \"${totalTime / 1000}\" seconds!`,\n ),\n );\n return allRequests.length;\n}\n"],"mappings":"mbAqBA,eAAsB,EAAoC,CACxD,iBAAiB,OAAO,OAAO,EAAc,CAC7C,OACA,aACA,kBACA,OAAO,GACP,WAAW,GACX,iBACA,kBACA,iBACA,gBAAgB,yBAChB,cAAc,IACd,eAAe,GA6BG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAI,EAAY,UAAU,EAAE,CAAE,EAAY,QAAQ,eAAe,CAO/E,GAAqB,MAJK,EAAkB,EAAQ,CACxD,SACA,SAAU,CAAE,MAAO,EAAe,CACnC,CAAC,EAC2C,KAAM,GAAa,EAAS,QAAU,EAAc,CACjG,GAAI,CAAC,EACH,MAAU,MAAM,0CAA0C,EAAc,GAAG,CAI7E,IAAI,EAAc,MAAM,EAAiB,EAAQ,CAC/C,QAAS,EACT,kBACA,iBACA,kBACA,iBACA,SAAU,GACV,SAAU,GACV,aACD,CAAC,CAGF,EAAc,EAAY,OACvB,GAAY,OAAO,EAAQ,eAAkB,UAAY,EAAQ,cAAgB,EACnF,CAGD,EAAO,KAAK,EAAO,QAAQ,cAAc,EAAY,OAAO,6BAA6B,CAAC,CAE1F,IAAI,EAAQ,EACZ,EAAY,MAAM,EAAY,OAAQ,EAAE,CACxC,MAAM,EACJ,EACA,KAAO,IAAoB,CACzB,MAAM,EAAmB,EAAQ,EAAwB,CACvD,UAAW,CACT,MAAO,CACL,UAAW,EAAgB,GAC3B,SAAU,EAAmB,SAAS,eACtC,QAAS,EAAmB,QAAQ,eACpC,eAAgB,EACjB,CACF,CACD,SACD,CAAC,CAEF,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SACF,CAAG,EAOvB,OALA,EAAO,KACL,EAAO,MACL,uBAAuB,EAAM,+BAA+B,EAAY,IAAK,YAC9E,CACF,CACM,EAAY"}
@@ -3,4 +3,4 @@ import{t as e}from"./logger-Ckep4QXn.mjs";import{existsSync as t,mkdirSync as n,
3
3
  TO ${t(y)}
4
4
  (HEADER, DELIMITER ',', QUOTE '"', ESCAPE '"', NULL '');
5
5
  `),g?.(0,void 0),e.info(s.green(`Wrote CSV → ${y}`))}finally{await d(x),await d(b)}}async function l(e,t){await d(await e.run(t))}async function u(e,t){try{await l(e,t)}catch{}}async function d(e){if(!(!e||typeof e.dispose!=`function`))try{await e.dispose()}catch{}}export{c as t};
6
- //# sourceMappingURL=parquetToCsvOneFile-13GirFzy.mjs.map
6
+ //# sourceMappingURL=parquetToCsvOneFile-0O4iLz0t.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"parquetToCsvOneFile-13GirFzy.mjs","names":[],"sources":["../src/lib/helpers/parquetToCsvOneFile.ts"],"sourcesContent":["import { mkdirSync, rmSync, existsSync } from 'node:fs';\nimport { dirname, join, parse } from 'node:path';\n\nimport type { DuckDBConnection, DuckDBInstance } from '@duckdb/node-api';\nimport colors from 'colors';\n\nimport { logger } from '../../logger.js';\n\n/** Progress callback used by the parent runner to surface progress to the UI. */\ntype OnProgress = (processed: number, total?: number) => void;\n\n/**\n * Options for converting a single Parquet file into a single CSV file.\n */\nexport type ParquetToCsvOneFileOptions = {\n /** Absolute or relative path to the input `.parquet` file. */\n filePath: string;\n /**\n * Directory where the output CSV will be written.\n * If omitted, the CSV is written next to the input file.\n */\n outputDir?: string;\n /**\n * When true, removes a pre-existing output file with the same name before writing.\n * Useful for re-runs; ignored if the file does not exist.\n */\n clearOutputDir: boolean;\n /**\n * Optional progress hook. Called with the number of processed records.\n * `total` is not computed here; it will be `undefined`.\n */\n onProgress?: OnProgress;\n};\n\n/**\n * Convert a single Parquet file to a single CSV file (1:1) using DuckDB.\n *\n * Output naming: `${basename}.csv` in `outputDir ?? dirname(filePath)`.\n *\n * Errors:\n * - Throws on I/O failures or DuckDB execution errors.\n *\n * Why DuckDB?\n * - Robust reader for many Parquet dialects (e.g., Spark output, nested types, timestamps).\n * - Streaming COPY handles large files without loading everything into JS memory.\n *\n * What this does:\n * - Opens an in-memory DuckDB database (no `.db` file created).\n * - Optionally disables temp spilling to disk (so only your CSV is written).\n * - Executes a single `COPY (SELECT * FROM read_parquet(...)) TO ...` statement.\n * - Produces exactly one CSV per input Parquet (no chunking or rotation).\n *\n * Notes & defaults:\n * - DuckDBInstance: `:memory:` (ephemeral). No persistent DB file is created.\n * - Temp files: disabled via `PRAGMA temp_directory=''` (best-effort; ignored if unsupported).\n * - CSV format: header row, comma delimiter, double-quote quoting, empty string for NULL.\n * - Progress: DuckDB COPY doesn't expose row-level progress via the JS API; we emit a\n * best-effort final callback.\n *\n * Requirements:\n * - `@duckdb/node-api` npm package installed and available at runtime.\n * - Supported platform binary (mac arm64/x64, linux x64, windows x64).\n *\n * @param opts - Conversion options\n * @param DuckDb - DuckDB instance to use\n * @returns Promise<void> when the CSV has been written\n */\nexport async function parquetToCsvOneFile(\n opts: ParquetToCsvOneFileOptions,\n DuckDb: typeof DuckDBInstance,\n): Promise<void> {\n const { filePath, outputDir, clearOutputDir, onProgress } = opts;\n\n const baseDir = outputDir || dirname(filePath);\n const { name: baseName } = parse(filePath);\n const outPath = join(baseDir, `${baseName}.csv`);\n\n // Ensure output directory exists\n mkdirSync(baseDir, { recursive: true });\n\n // Remove any pre-existing output file if requested\n if (clearOutputDir && existsSync(outPath)) {\n try {\n rmSync(outPath, { force: true });\n } catch (err) {\n logger.warn(\n colors.yellow(\n `Could not remove existing output file ${outPath}: ${(err as Error).message}`,\n ),\n );\n }\n }\n\n // In-memory DB: no .db file created on disk\n const db = await DuckDb.create(':memory:');\n const conn = await db.connect();\n\n try {\n // Optional: prevent DuckDB from creating temp files on disk (best-effort).\n // Some versions may ignore or error; we ignore such errors safely.\n await runIgnoreError(conn, \"PRAGMA temp_directory='';\");\n\n // Optionally: cap memory to encourage in-memory execution or fail-fast\n // (commented out by default; uncomment to enforce a limit)\n // await runIgnoreError(conn, \"PRAGMA memory_limit='4GB';\");\n\n // Ensure stable CSV settings: header, comma delimiter, double quotes, empty string for NULLs.\n // Escape single quotes for SQL string literals\n const q = (p: string): string => `'${p.replace(/'/g, \"''\")}'`;\n\n // Use COPY with a subquery so DuckDB streams Parquet -> CSV efficiently.\n const sql = `\n COPY (SELECT * FROM read_parquet(${q(filePath)}))\n TO ${q(outPath)}\n (HEADER, DELIMITER ',', QUOTE '\"', ESCAPE '\"', NULL '');\n `;\n\n await run(conn, sql);\n\n // Best-effort progress notification (DuckDB JS API doesn't expose progress for COPY)\n onProgress?.(0, undefined);\n\n logger.info(colors.green(`Wrote CSV → ${outPath}`));\n } finally {\n // Close connection + db handles gracefully\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await disposeSafe(conn as any);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await disposeSafe(db as any);\n }\n}\n\n/* =============================================================================\n * DuckDB helpers\n * =============================================================================\n */\n\n/**\n * Execute a SQL statement on a DuckDB connection and dispose the result.\n *\n * @param conn - DuckDB connection\n * @param sql - SQL string to run\n * @returns Promise<void>\n */\nasync function run(conn: DuckDBConnection, sql: string): Promise<void> {\n const result = await conn.run(sql);\n // The high-level API returns a Result; ensure we dispose it to free buffers.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await disposeSafe(result as any);\n}\n\n/**\n * Execute a SQL statement but ignore any error that occurs.\n * Useful for best-effort PRAGMAs that may not be supported across versions.\n *\n * @param conn - DuckDB connection\n * @param sql - SQL string to run\n * @returns Promise<void>\n */\nasync function runIgnoreError(conn: DuckDBConnection, sql: string): Promise<void> {\n try {\n await run(conn, sql);\n } catch {\n // ignore\n }\n}\n\n/**\n * Dispose a DuckDB resource (connection or instance) if present.\n *\n * @param handle - Object exposing an async `dispose()` method\n * @returns Promise<void>\n */\nasync function disposeSafe(\n handle:\n | {\n /** Dispose handler */\n dispose: () => Promise<void>;\n }\n | null\n | undefined,\n): Promise<void> {\n if (!handle || typeof handle.dispose !== 'function') return;\n try {\n await handle.dispose();\n } catch {\n // ignore\n }\n}\n"],"mappings":"yLAmEA,eAAsB,EACpB,EACA,EACe,CACf,GAAM,CAAE,WAAU,YAAW,iBAAgB,cAAe,EAEtD,EAAU,GAAa,EAAQ,EAAS,CACxC,CAAE,KAAM,GAAa,EAAM,EAAS,CACpC,EAAU,EAAK,EAAS,GAAG,EAAS,MAAM,CAMhD,GAHA,EAAU,EAAS,CAAE,UAAW,GAAM,CAAC,CAGnC,GAAkB,EAAW,EAAQ,CACvC,GAAI,CACF,EAAO,EAAS,CAAE,MAAO,GAAM,CAAC,OACzB,EAAK,CACZ,EAAO,KACL,EAAO,OACL,yCAAyC,EAAQ,IAAK,EAAc,UACrE,CACF,CAKL,IAAM,EAAK,MAAM,EAAO,OAAO,WAAW,CACpC,EAAO,MAAM,EAAG,SAAS,CAE/B,GAAI,CAGF,MAAM,EAAe,EAAM,4BAA4B,CAQvD,IAAM,EAAK,GAAsB,IAAI,EAAE,QAAQ,KAAM,KAAK,CAAC,GAS3D,MAAM,EAAI,EAAM;yCALqB,EAAE,EAAS,CAAC;WAC1C,EAAE,EAAQ,CAAC;;MAIE,CAGpB,IAAa,EAAG,IAAA,GAAU,CAE1B,EAAO,KAAK,EAAO,MAAM,eAAe,IAAU,CAAC,QAC3C,CAGR,MAAM,EAAY,EAAY,CAE9B,MAAM,EAAY,EAAU,EAgBhC,eAAe,EAAI,EAAwB,EAA4B,CAIrE,MAAM,EAAY,MAHG,EAAK,IAAI,EAAI,CAGF,CAWlC,eAAe,EAAe,EAAwB,EAA4B,CAChF,GAAI,CACF,MAAM,EAAI,EAAM,EAAI,MACd,GAWV,eAAe,EACb,EAOe,CACX,MAAC,GAAU,OAAO,EAAO,SAAY,YACzC,GAAI,CACF,MAAM,EAAO,SAAS,MAChB"}
1
+ {"version":3,"file":"parquetToCsvOneFile-0O4iLz0t.mjs","names":[],"sources":["../src/lib/helpers/parquetToCsvOneFile.ts"],"sourcesContent":["import { mkdirSync, rmSync, existsSync } from 'node:fs';\nimport { dirname, join, parse } from 'node:path';\n\nimport type { DuckDBConnection, DuckDBInstance } from '@duckdb/node-api';\nimport colors from 'colors';\n\nimport { logger } from '../../logger.js';\n\n/** Progress callback used by the parent runner to surface progress to the UI. */\ntype OnProgress = (processed: number, total?: number) => void;\n\n/**\n * Options for converting a single Parquet file into a single CSV file.\n */\nexport type ParquetToCsvOneFileOptions = {\n /** Absolute or relative path to the input `.parquet` file. */\n filePath: string;\n /**\n * Directory where the output CSV will be written.\n * If omitted, the CSV is written next to the input file.\n */\n outputDir?: string;\n /**\n * When true, removes a pre-existing output file with the same name before writing.\n * Useful for re-runs; ignored if the file does not exist.\n */\n clearOutputDir: boolean;\n /**\n * Optional progress hook. Called with the number of processed records.\n * `total` is not computed here; it will be `undefined`.\n */\n onProgress?: OnProgress;\n};\n\n/**\n * Convert a single Parquet file to a single CSV file (1:1) using DuckDB.\n *\n * Output naming: `${basename}.csv` in `outputDir ?? dirname(filePath)`.\n *\n * Errors:\n * - Throws on I/O failures or DuckDB execution errors.\n *\n * Why DuckDB?\n * - Robust reader for many Parquet dialects (e.g., Spark output, nested types, timestamps).\n * - Streaming COPY handles large files without loading everything into JS memory.\n *\n * What this does:\n * - Opens an in-memory DuckDB database (no `.db` file created).\n * - Optionally disables temp spilling to disk (so only your CSV is written).\n * - Executes a single `COPY (SELECT * FROM read_parquet(...)) TO ...` statement.\n * - Produces exactly one CSV per input Parquet (no chunking or rotation).\n *\n * Notes & defaults:\n * - DuckDBInstance: `:memory:` (ephemeral). No persistent DB file is created.\n * - Temp files: disabled via `PRAGMA temp_directory=''` (best-effort; ignored if unsupported).\n * - CSV format: header row, comma delimiter, double-quote quoting, empty string for NULL.\n * - Progress: DuckDB COPY doesn't expose row-level progress via the JS API; we emit a\n * best-effort final callback.\n *\n * Requirements:\n * - `@duckdb/node-api` npm package installed and available at runtime.\n * - Supported platform binary (mac arm64/x64, linux x64, windows x64).\n *\n * @param opts - Conversion options\n * @param DuckDb - DuckDB instance to use\n * @returns Promise<void> when the CSV has been written\n */\nexport async function parquetToCsvOneFile(\n opts: ParquetToCsvOneFileOptions,\n DuckDb: typeof DuckDBInstance,\n): Promise<void> {\n const { filePath, outputDir, clearOutputDir, onProgress } = opts;\n\n const baseDir = outputDir || dirname(filePath);\n const { name: baseName } = parse(filePath);\n const outPath = join(baseDir, `${baseName}.csv`);\n\n // Ensure output directory exists\n mkdirSync(baseDir, { recursive: true });\n\n // Remove any pre-existing output file if requested\n if (clearOutputDir && existsSync(outPath)) {\n try {\n rmSync(outPath, { force: true });\n } catch (err) {\n logger.warn(\n colors.yellow(\n `Could not remove existing output file ${outPath}: ${(err as Error).message}`,\n ),\n );\n }\n }\n\n // In-memory DB: no .db file created on disk\n const db = await DuckDb.create(':memory:');\n const conn = await db.connect();\n\n try {\n // Optional: prevent DuckDB from creating temp files on disk (best-effort).\n // Some versions may ignore or error; we ignore such errors safely.\n await runIgnoreError(conn, \"PRAGMA temp_directory='';\");\n\n // Optionally: cap memory to encourage in-memory execution or fail-fast\n // (commented out by default; uncomment to enforce a limit)\n // await runIgnoreError(conn, \"PRAGMA memory_limit='4GB';\");\n\n // Ensure stable CSV settings: header, comma delimiter, double quotes, empty string for NULLs.\n // Escape single quotes for SQL string literals\n const q = (p: string): string => `'${p.replace(/'/g, \"''\")}'`;\n\n // Use COPY with a subquery so DuckDB streams Parquet -> CSV efficiently.\n const sql = `\n COPY (SELECT * FROM read_parquet(${q(filePath)}))\n TO ${q(outPath)}\n (HEADER, DELIMITER ',', QUOTE '\"', ESCAPE '\"', NULL '');\n `;\n\n await run(conn, sql);\n\n // Best-effort progress notification (DuckDB JS API doesn't expose progress for COPY)\n onProgress?.(0, undefined);\n\n logger.info(colors.green(`Wrote CSV → ${outPath}`));\n } finally {\n // Close connection + db handles gracefully\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await disposeSafe(conn as any);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await disposeSafe(db as any);\n }\n}\n\n/* =============================================================================\n * DuckDB helpers\n * =============================================================================\n */\n\n/**\n * Execute a SQL statement on a DuckDB connection and dispose the result.\n *\n * @param conn - DuckDB connection\n * @param sql - SQL string to run\n * @returns Promise<void>\n */\nasync function run(conn: DuckDBConnection, sql: string): Promise<void> {\n const result = await conn.run(sql);\n // The high-level API returns a Result; ensure we dispose it to free buffers.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await disposeSafe(result as any);\n}\n\n/**\n * Execute a SQL statement but ignore any error that occurs.\n * Useful for best-effort PRAGMAs that may not be supported across versions.\n *\n * @param conn - DuckDB connection\n * @param sql - SQL string to run\n * @returns Promise<void>\n */\nasync function runIgnoreError(conn: DuckDBConnection, sql: string): Promise<void> {\n try {\n await run(conn, sql);\n } catch {\n // ignore\n }\n}\n\n/**\n * Dispose a DuckDB resource (connection or instance) if present.\n *\n * @param handle - Object exposing an async `dispose()` method\n * @returns Promise<void>\n */\nasync function disposeSafe(\n handle:\n | {\n /** Dispose handler */\n dispose: () => Promise<void>;\n }\n | null\n | undefined,\n): Promise<void> {\n if (!handle || typeof handle.dispose !== 'function') return;\n try {\n await handle.dispose();\n } catch {\n // ignore\n }\n}\n"],"mappings":"yLAmEA,eAAsB,EACpB,EACA,EACe,CACf,GAAM,CAAE,WAAU,YAAW,iBAAgB,cAAe,EAEtD,EAAU,GAAa,EAAQ,EAAS,CACxC,CAAE,KAAM,GAAa,EAAM,EAAS,CACpC,EAAU,EAAK,EAAS,GAAG,EAAS,MAAM,CAMhD,GAHA,EAAU,EAAS,CAAE,UAAW,GAAM,CAAC,CAGnC,GAAkB,EAAW,EAAQ,CACvC,GAAI,CACF,EAAO,EAAS,CAAE,MAAO,GAAM,CAAC,OACzB,EAAK,CACZ,EAAO,KACL,EAAO,OACL,yCAAyC,EAAQ,IAAK,EAAc,UACrE,CACF,CAKL,IAAM,EAAK,MAAM,EAAO,OAAO,WAAW,CACpC,EAAO,MAAM,EAAG,SAAS,CAE/B,GAAI,CAGF,MAAM,EAAe,EAAM,4BAA4B,CAQvD,IAAM,EAAK,GAAsB,IAAI,EAAE,QAAQ,KAAM,KAAK,CAAC,GAS3D,MAAM,EAAI,EAAM;yCALqB,EAAE,EAAS,CAAC;WAC1C,EAAE,EAAQ,CAAC;;MAIE,CAGpB,IAAa,EAAG,IAAA,GAAU,CAE1B,EAAO,KAAK,EAAO,MAAM,eAAe,IAAU,CAAC,QAC3C,CAGR,MAAM,EAAY,EAAY,CAE9B,MAAM,EAAY,EAAU,EAgBhC,eAAe,EAAI,EAAwB,EAA4B,CAIrE,MAAM,EAAY,MAHG,EAAK,IAAI,EAAI,CAGF,CAWlC,eAAe,EAAe,EAAwB,EAA4B,CAChF,GAAI,CACF,MAAM,EAAI,EAAM,EAAI,MACd,GAWV,eAAe,EACb,EAOe,CACX,MAAC,GAAU,OAAO,EAAO,SAAY,YACzC,GAAI,CACF,MAAM,EAAO,SAAS,MAChB"}
@@ -0,0 +1,2 @@
1
+ function e(e){let t=e.split(`,`).filter(e=>!!e),n={};return t.forEach(e=>{let[t,r]=e.split(`:`);if(!t||!r)throw Error(`Invalid variable: ${e}. Expected format: key:value`);n[t]=r}),n}export{e as t};
2
+ //# sourceMappingURL=parseVariablesFromString-B4TUkJRF.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseVariablesFromString-B4TUkJRF.mjs","names":[],"sources":["../src/lib/helpers/parseVariablesFromString.ts"],"sourcesContent":["/**\n * Parse variables from string\n *\n * @param variables - Variables as string\n * @returns Variables as object\n */\nexport function parseVariablesFromString(variables: string): {\n [k in string]: string;\n} {\n // Parse out the variables\n const splitVars = variables.split(',').filter((x) => !!x);\n const vars: { [k in string]: string } = {};\n splitVars.forEach((variable) => {\n const [k, v] = variable.split(':');\n if (!k || !v) {\n throw new Error(`Invalid variable: ${variable}. Expected format: key:value`);\n }\n vars[k] = v;\n });\n return vars;\n}\n"],"mappings":"AAMA,SAAgB,EAAyB,EAEvC,CAEA,IAAM,EAAY,EAAU,MAAM,IAAI,CAAC,OAAQ,GAAM,CAAC,CAAC,EAAE,CACnD,EAAkC,EAAE,CAQ1C,OAPA,EAAU,QAAS,GAAa,CAC9B,GAAM,CAAC,EAAG,GAAK,EAAS,MAAM,IAAI,CAClC,GAAI,CAAC,GAAK,CAAC,EACT,MAAU,MAAM,qBAAqB,EAAS,8BAA8B,CAE9E,EAAK,GAAK,GACV,CACK"}
@@ -42,4 +42,4 @@ import{t as e}from"./logger-Ckep4QXn.mjs";import{SubDataPointDataSubCategoryGues
42
42
  }
43
43
  }
44
44
  `,{variables:{first:m,offset:C,filterBy:{...v}},logger:e});S=t[t.length-1]?.id,h.push(...t),x=t.length===m,b+=t.length,C+=t.length,_.update(b)}catch(t){throw e.error(o.red(`An error fetching subdatapoints for cursor ${S} and offset ${C}`)),t}while(x);_.stop();let w=new Date().getTime()-g,T=i(h,`name`);return e.info(o.green(`Successfully pulled in ${T.length} subdatapoints in ${w/1e3} seconds!`)),T}async function h(t,{dataPointIds:r=[],pageSize:i=100}){let a=[],c=new Date().getTime(),l=new f.SingleBar({},f.Presets.shades_classic);e.info(o.magenta(`[Step 2/3] Fetching metadata for ${r.length} datapoints`));let p=n(r,i);l.start(r.length,0);let m=0;await d(p,async n=>{try{let{dataPoints:{nodes:r}}=await u(t,s,{variables:{first:i,filterBy:{ids:n}},logger:e});a.push(...r),m+=n.length,l.update(m)}catch(t){throw e.error(o.red(`An error fetching subdatapoints for IDs ${n.join(`, `)}`)),t}}),l.stop();let h=new Date().getTime()-c;return e.info(o.green(`Successfully pulled in ${a.length} dataPoints in ${h/1e3} seconds!`)),a}async function g(t,{dataSiloIds:r=[],pageSize:i=100}){let a=[],s=new Date().getTime(),l=new f.SingleBar({},f.Presets.shades_classic);e.info(o.magenta(`[Step 3/3] Fetching metadata for ${r.length} data silos`));let p=n(r,i);l.start(r.length,0);let m=0;await d(p,async n=>{try{let{dataSilos:{nodes:r}}=await u(t,c,{variables:{first:i,filterBy:{ids:n}},logger:e});a.push(...r),m+=n.length,l.update(m)}catch(t){throw e.error(o.red(`An error fetching data silos for IDs ${n.join(`, `)}`)),t}}),l.stop();let h=new Date().getTime()-s;return e.info(o.green(`Successfully pulled in ${a.length} data silos in ${h/1e3} seconds!`)),a}async function _(e,{dataSiloIds:t=[],includeGuessedCategories:n,includeAttributes:i,parentCategories:o=[],subCategories:s=[],pageSize:c=1e3}={}){let l=await m(e,{dataSiloIds:t,includeGuessedCategories:n,includeAttributes:i,parentCategories:o,subCategories:s,pageSize:c}),u=r(await h(e,{dataPointIds:a(l.map(e=>e.dataPointId))}),`id`),d=r(await g(e,{dataSiloIds:a(l.map(e=>e.dataSiloId))}),`id`);return l.map(e=>({...e,dataPoint:u[e.dataPointId],dataSilo:d[e.dataSiloId]}))}export{_ as t};
45
- //# sourceMappingURL=pullAllDatapoints-Bvv9KRR5.mjs.map
45
+ //# sourceMappingURL=pullAllDatapoints-DJno8LkB.mjs.map