@transcend-io/cli 10.16.0 → 10.17.1

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 (166) hide show
  1. package/README.md +20 -9
  2. package/dist/{app-COX_n1FP.mjs → app-BksK9SPh.mjs} +18 -18
  3. package/dist/{app-COX_n1FP.mjs.map → app-BksK9SPh.mjs.map} +1 -1
  4. package/dist/{approvePrivacyRequests-DJItn7R6.mjs → approvePrivacyRequests-CLi5rXP3.mjs} +2 -2
  5. package/dist/{approvePrivacyRequests-DJItn7R6.mjs.map → approvePrivacyRequests-CLi5rXP3.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-CZ8kcEqO.mjs → buildExamples-BrLuHDdW.mjs} +2 -2
  10. package/dist/{buildExamples-CZ8kcEqO.mjs.map → buildExamples-BrLuHDdW.mjs.map} +1 -1
  11. package/dist/{buildXdiSyncEndpoint-CSGwr2H5.mjs → buildXdiSyncEndpoint-Bxi-Dlsu.mjs} +2 -2
  12. package/dist/{buildXdiSyncEndpoint-CSGwr2H5.mjs.map → buildXdiSyncEndpoint-Bxi-Dlsu.mjs.map} +1 -1
  13. package/dist/{bulkRestartRequests-D-t58SeM.mjs → bulkRestartRequests-NrX4ED7j.mjs} +2 -2
  14. package/dist/{bulkRestartRequests-D-t58SeM.mjs.map → bulkRestartRequests-NrX4ED7j.mjs.map} +1 -1
  15. package/dist/{bulkRetryEnrichers-BmwRLF2w.mjs → bulkRetryEnrichers-BYVCTi_Q.mjs} +2 -2
  16. package/dist/{bulkRetryEnrichers-BmwRLF2w.mjs.map → bulkRetryEnrichers-BYVCTi_Q.mjs.map} +1 -1
  17. package/dist/{cancelPrivacyRequests-CFCULeSv.mjs → cancelPrivacyRequests-BxwCIpUR.mjs} +2 -2
  18. package/dist/{cancelPrivacyRequests-CFCULeSv.mjs.map → cancelPrivacyRequests-BxwCIpUR.mjs.map} +1 -1
  19. package/dist/codecs-CwRYEdQK.mjs +2 -0
  20. package/dist/{codecs-DW8SY77H.mjs.map → codecs-CwRYEdQK.mjs.map} +1 -1
  21. package/dist/{command-8AnltUOG.mjs → command-BFlaWkwf.mjs} +2 -2
  22. package/dist/{command-8AnltUOG.mjs.map → command-BFlaWkwf.mjs.map} +1 -1
  23. package/dist/constants-BX7PrKxC.mjs +2 -0
  24. package/dist/constants-BX7PrKxC.mjs.map +1 -0
  25. package/dist/{createExtraKeyHandler-DqiD609a.mjs → createExtraKeyHandler-1HjUyY-D.mjs} +2 -2
  26. package/dist/{createExtraKeyHandler-DqiD609a.mjs.map → createExtraKeyHandler-1HjUyY-D.mjs.map} +1 -1
  27. package/dist/{downloadPrivacyRequestFiles-B7HNc-Y1.mjs → downloadPrivacyRequestFiles-CnwWfn0A.mjs} +2 -2
  28. package/dist/{downloadPrivacyRequestFiles-B7HNc-Y1.mjs.map → downloadPrivacyRequestFiles-CnwWfn0A.mjs.map} +1 -1
  29. package/dist/{enums-CyFTrzXY.mjs → enums-mAXnon_I.mjs} +2 -2
  30. package/dist/enums-mAXnon_I.mjs.map +1 -0
  31. package/dist/{generateCrossAccountApiKeys-kqzneWII.mjs → generateCrossAccountApiKeys-BZiBRDZL.mjs} +2 -2
  32. package/dist/{generateCrossAccountApiKeys-kqzneWII.mjs.map → generateCrossAccountApiKeys-BZiBRDZL.mjs.map} +1 -1
  33. package/dist/{impl-BVcXWJyI2.mjs → impl-0OHjJHDD2.mjs} +2 -2
  34. package/dist/{impl-BVcXWJyI2.mjs.map → impl-0OHjJHDD2.mjs.map} +1 -1
  35. package/dist/{impl-Bvkhu8fB.mjs → impl-B-9HvUMl.mjs} +2 -2
  36. package/dist/{impl-Bvkhu8fB.mjs.map → impl-B-9HvUMl.mjs.map} +1 -1
  37. package/dist/{impl-BDc4D9nA.mjs → impl-B0CVYN6x.mjs} +2 -2
  38. package/dist/{impl-BDc4D9nA.mjs.map → impl-B0CVYN6x.mjs.map} +1 -1
  39. package/dist/{impl-CX1J2iHE.mjs → impl-B4weFiPq.mjs} +2 -2
  40. package/dist/{impl-CX1J2iHE.mjs.map → impl-B4weFiPq.mjs.map} +1 -1
  41. package/dist/{impl-CRSNjo07.mjs → impl-B7HFZI-o.mjs} +2 -2
  42. package/dist/{impl-CRSNjo07.mjs.map → impl-B7HFZI-o.mjs.map} +1 -1
  43. package/dist/impl-B9rlOyl5.mjs +2 -0
  44. package/dist/impl-B9rlOyl5.mjs.map +1 -0
  45. package/dist/{impl-BbfuEhKu.mjs → impl-BATZJZAu.mjs} +2 -2
  46. package/dist/{impl-BbfuEhKu.mjs.map → impl-BATZJZAu.mjs.map} +1 -1
  47. package/dist/{impl-6rvA_yyd.mjs → impl-BCsrAqZI.mjs} +2 -2
  48. package/dist/{impl-6rvA_yyd.mjs.map → impl-BCsrAqZI.mjs.map} +1 -1
  49. package/dist/{impl-Bul8gUqq.mjs → impl-BIDhVXeB.mjs} +2 -2
  50. package/dist/{impl-Bul8gUqq.mjs.map → impl-BIDhVXeB.mjs.map} +1 -1
  51. package/dist/{impl-DTDnN3Hn.mjs → impl-BeIevZ_X.mjs} +2 -2
  52. package/dist/{impl-DTDnN3Hn.mjs.map → impl-BeIevZ_X.mjs.map} +1 -1
  53. package/dist/{impl-0C9N9md8.mjs → impl-BimGJAmf.mjs} +2 -2
  54. package/dist/{impl-0C9N9md8.mjs.map → impl-BimGJAmf.mjs.map} +1 -1
  55. package/dist/{impl-C_K23xoc.mjs → impl-Bjr5Uf1c.mjs} +2 -2
  56. package/dist/{impl-C_K23xoc.mjs.map → impl-Bjr5Uf1c.mjs.map} +1 -1
  57. package/dist/{impl-DK2Rai3F.mjs → impl-BtgbwWAB.mjs} +2 -2
  58. package/dist/{impl-DK2Rai3F.mjs.map → impl-BtgbwWAB.mjs.map} +1 -1
  59. package/dist/{impl-DYsJKLfp.mjs → impl-BvU-r-wF.mjs} +2 -2
  60. package/dist/{impl-DYsJKLfp.mjs.map → impl-BvU-r-wF.mjs.map} +1 -1
  61. package/dist/{impl-B9AtL5ta2.mjs → impl-Bw3__zkc2.mjs} +2 -2
  62. package/dist/{impl-B9AtL5ta2.mjs.map → impl-Bw3__zkc2.mjs.map} +1 -1
  63. package/dist/{impl-CCSb7Pyd.mjs → impl-C6wqboV2.mjs} +2 -2
  64. package/dist/{impl-CCSb7Pyd.mjs.map → impl-C6wqboV2.mjs.map} +1 -1
  65. package/dist/{impl-RqwgNa2O.mjs → impl-CBFgXSWV.mjs} +2 -2
  66. package/dist/{impl-RqwgNa2O.mjs.map → impl-CBFgXSWV.mjs.map} +1 -1
  67. package/dist/{impl-C0I8JaaR.mjs → impl-CCP1-ZeX.mjs} +2 -2
  68. package/dist/{impl-C0I8JaaR.mjs.map → impl-CCP1-ZeX.mjs.map} +1 -1
  69. package/dist/{impl-DQH1CGup.mjs → impl-CNKjJBfX.mjs} +2 -2
  70. package/dist/{impl-DQH1CGup.mjs.map → impl-CNKjJBfX.mjs.map} +1 -1
  71. package/dist/{impl-Bkdu-3yo.mjs → impl-CPkl4IRz.mjs} +2 -2
  72. package/dist/{impl-Bkdu-3yo.mjs.map → impl-CPkl4IRz.mjs.map} +1 -1
  73. package/dist/{impl-DMbgck0i.mjs → impl-CUbaczq8.mjs} +2 -2
  74. package/dist/{impl-DMbgck0i.mjs.map → impl-CUbaczq8.mjs.map} +1 -1
  75. package/dist/{impl-BOXnkx44.mjs → impl-CgDCcV00.mjs} +2 -2
  76. package/dist/{impl-BOXnkx44.mjs.map → impl-CgDCcV00.mjs.map} +1 -1
  77. package/dist/{impl-DiysQB762.mjs → impl-CsSRW8xl2.mjs} +2 -2
  78. package/dist/{impl-DiysQB762.mjs.map → impl-CsSRW8xl2.mjs.map} +1 -1
  79. package/dist/{impl-BvOLkTWD.mjs → impl-CuxbHVUs.mjs} +2 -2
  80. package/dist/{impl-BvOLkTWD.mjs.map → impl-CuxbHVUs.mjs.map} +1 -1
  81. package/dist/{impl-Bq-tabdZ2.mjs → impl-Cz-cy5Q92.mjs} +2 -2
  82. package/dist/{impl-Bq-tabdZ2.mjs.map → impl-Cz-cy5Q92.mjs.map} +1 -1
  83. package/dist/{impl-CkFqqhQ-.mjs → impl-D7GBtInJ.mjs} +2 -2
  84. package/dist/{impl-CkFqqhQ-.mjs.map → impl-D7GBtInJ.mjs.map} +1 -1
  85. package/dist/{impl-BUF6G3P32.mjs → impl-DDrubha_2.mjs} +2 -2
  86. package/dist/{impl-BUF6G3P32.mjs.map → impl-DDrubha_2.mjs.map} +1 -1
  87. package/dist/{impl-Dl-XNXfK.mjs → impl-DGBJkbeS.mjs} +2 -2
  88. package/dist/{impl-Dl-XNXfK.mjs.map → impl-DGBJkbeS.mjs.map} +1 -1
  89. package/dist/{impl-CsHfqKxU.mjs → impl-DOGMbdAR.mjs} +2 -2
  90. package/dist/{impl-CsHfqKxU.mjs.map → impl-DOGMbdAR.mjs.map} +1 -1
  91. package/dist/{impl-ChDwTQ3Z2.mjs → impl-DPCAbsLy2.mjs} +2 -2
  92. package/dist/{impl-ChDwTQ3Z2.mjs.map → impl-DPCAbsLy2.mjs.map} +1 -1
  93. package/dist/{impl-TTeKThep2.mjs → impl-DZnctw762.mjs} +2 -2
  94. package/dist/{impl-TTeKThep2.mjs.map → impl-DZnctw762.mjs.map} +1 -1
  95. package/dist/{impl-BcIZos3y.mjs → impl-DcQfhjZL.mjs} +2 -2
  96. package/dist/{impl-BcIZos3y.mjs.map → impl-DcQfhjZL.mjs.map} +1 -1
  97. package/dist/{impl-CeqMxdZm2.mjs → impl-Dj5dWvYr2.mjs} +2 -2
  98. package/dist/{impl-CeqMxdZm2.mjs.map → impl-Dj5dWvYr2.mjs.map} +1 -1
  99. package/dist/{impl-X13pzYJN2.mjs → impl-DwOllcc22.mjs} +2 -2
  100. package/dist/{impl-X13pzYJN2.mjs.map → impl-DwOllcc22.mjs.map} +1 -1
  101. package/dist/{impl-BuqBEZCk.mjs → impl-ELz2nyJq.mjs} +2 -2
  102. package/dist/{impl-BuqBEZCk.mjs.map → impl-ELz2nyJq.mjs.map} +1 -1
  103. package/dist/{impl-CLrF-Xhp2.mjs → impl-kU6M_9xS2.mjs} +2 -2
  104. package/dist/{impl-CLrF-Xhp2.mjs.map → impl-kU6M_9xS2.mjs.map} +1 -1
  105. package/dist/{impl-DqyYxDti.mjs → impl-taJyQmlW.mjs} +2 -2
  106. package/dist/{impl-DqyYxDti.mjs.map → impl-taJyQmlW.mjs.map} +1 -1
  107. package/dist/{impl-CDNTdi62.mjs → impl-z2bzz69O.mjs} +2 -2
  108. package/dist/{impl-CDNTdi62.mjs.map → impl-z2bzz69O.mjs.map} +1 -1
  109. package/dist/{impl-CkU-WD3b.mjs → impl-zXXUv3a4.mjs} +2 -2
  110. package/dist/{impl-CkU-WD3b.mjs.map → impl-zXXUv3a4.mjs.map} +1 -1
  111. package/dist/index.d.mts +29 -10
  112. package/dist/index.d.mts.map +1 -1
  113. package/dist/index.mjs +1 -1
  114. package/dist/{markRequestDataSiloIdsCompleted-nAV0VLEA.mjs → markRequestDataSiloIdsCompleted-DDNYecva.mjs} +2 -2
  115. package/dist/{markRequestDataSiloIdsCompleted-nAV0VLEA.mjs.map → markRequestDataSiloIdsCompleted-DDNYecva.mjs.map} +1 -1
  116. package/dist/{markSilentPrivacyRequests-BhF4r8n9.mjs → markSilentPrivacyRequests-DDDJEoJe.mjs} +2 -2
  117. package/dist/{markSilentPrivacyRequests-BhF4r8n9.mjs.map → markSilentPrivacyRequests-DDDJEoJe.mjs.map} +1 -1
  118. package/dist/{notifyPrivacyRequestsAdditionalTime-B6e9SfP7.mjs → notifyPrivacyRequestsAdditionalTime-NGNzjpY9.mjs} +2 -2
  119. package/dist/{notifyPrivacyRequestsAdditionalTime-B6e9SfP7.mjs.map → notifyPrivacyRequestsAdditionalTime-NGNzjpY9.mjs.map} +1 -1
  120. package/dist/parseVariablesFromString-CrzXJu3n.mjs +3 -0
  121. package/dist/parseVariablesFromString-CrzXJu3n.mjs.map +1 -0
  122. package/dist/{pullChunkedCustomSiloOutstandingIdentifiers-DiZTo2K_.mjs → pullChunkedCustomSiloOutstandingIdentifiers-NtMi2t5b.mjs} +2 -2
  123. package/dist/{pullChunkedCustomSiloOutstandingIdentifiers-DiZTo2K_.mjs.map → pullChunkedCustomSiloOutstandingIdentifiers-NtMi2t5b.mjs.map} +1 -1
  124. package/dist/{pullManualEnrichmentIdentifiersToCsv--dw03arC.mjs → pullManualEnrichmentIdentifiersToCsv-Bl0qvlM2.mjs} +2 -2
  125. package/dist/{pullManualEnrichmentIdentifiersToCsv--dw03arC.mjs.map → pullManualEnrichmentIdentifiersToCsv-Bl0qvlM2.mjs.map} +1 -1
  126. package/dist/pullTranscendConfiguration-CZD-sx8L.mjs +58 -0
  127. package/dist/pullTranscendConfiguration-CZD-sx8L.mjs.map +1 -0
  128. package/dist/{pushCronIdentifiersFromCsv-DdcsnXf5.mjs → pushCronIdentifiersFromCsv-CRZnkyWD.mjs} +2 -2
  129. package/dist/{pushCronIdentifiersFromCsv-DdcsnXf5.mjs.map → pushCronIdentifiersFromCsv-CRZnkyWD.mjs.map} +1 -1
  130. package/dist/{pushManualEnrichmentIdentifiersFromCsv-BYJCQOI-.mjs → pushManualEnrichmentIdentifiersFromCsv-DSFn8TeU.mjs} +2 -2
  131. package/dist/{pushManualEnrichmentIdentifiersFromCsv-BYJCQOI-.mjs.map → pushManualEnrichmentIdentifiersFromCsv-DSFn8TeU.mjs.map} +1 -1
  132. package/dist/{readTranscendYaml-I64TqeSd.mjs → readTranscendYaml-B2Asm9c5.mjs} +2 -2
  133. package/dist/{readTranscendYaml-I64TqeSd.mjs.map → readTranscendYaml-B2Asm9c5.mjs.map} +1 -1
  134. package/dist/{removeUnverifiedRequestIdentifiers-CC471vSR.mjs → removeUnverifiedRequestIdentifiers-DCeBwyyi.mjs} +2 -2
  135. package/dist/{removeUnverifiedRequestIdentifiers-CC471vSR.mjs.map → removeUnverifiedRequestIdentifiers-DCeBwyyi.mjs.map} +1 -1
  136. package/dist/{retryRequestDataSilos-DlkJmEjH.mjs → retryRequestDataSilos-BjXaDGk3.mjs} +2 -2
  137. package/dist/{retryRequestDataSilos-DlkJmEjH.mjs.map → retryRequestDataSilos-BjXaDGk3.mjs.map} +1 -1
  138. package/dist/{skipPreflightJobs-xVBZC-iI.mjs → skipPreflightJobs-DBYfdstu.mjs} +2 -2
  139. package/dist/{skipPreflightJobs-xVBZC-iI.mjs.map → skipPreflightJobs-DBYfdstu.mjs.map} +1 -1
  140. package/dist/{skipRequestDataSilos-BriqhLT3.mjs → skipRequestDataSilos-G2Ox2c6q.mjs} +2 -2
  141. package/dist/{skipRequestDataSilos-BriqhLT3.mjs.map → skipRequestDataSilos-G2Ox2c6q.mjs.map} +1 -1
  142. package/dist/{streamPrivacyRequestsToCsv-D8b097c1.mjs → streamPrivacyRequestsToCsv-vB1a_Xmx.mjs} +2 -2
  143. package/dist/{streamPrivacyRequestsToCsv-D8b097c1.mjs.map → streamPrivacyRequestsToCsv-vB1a_Xmx.mjs.map} +1 -1
  144. package/dist/{updateConsentManagerVersionToLatest-w_ftOmxi.mjs → updateConsentManagerVersionToLatest-g5a3brwY.mjs} +2 -2
  145. package/dist/{updateConsentManagerVersionToLatest-w_ftOmxi.mjs.map → updateConsentManagerVersionToLatest-g5a3brwY.mjs.map} +1 -1
  146. package/dist/{uploadConsents-D8IJDaTN.mjs → uploadConsents-aYnPgzBZ.mjs} +2 -2
  147. package/dist/{uploadConsents-D8IJDaTN.mjs.map → uploadConsents-aYnPgzBZ.mjs.map} +1 -1
  148. package/dist/{uploadCookiesFromCsv-8hq-Of_p.mjs → uploadCookiesFromCsv-DkgIHEdl.mjs} +2 -2
  149. package/dist/{uploadCookiesFromCsv-8hq-Of_p.mjs.map → uploadCookiesFromCsv-DkgIHEdl.mjs.map} +1 -1
  150. package/dist/{uploadDataFlowsFromCsv-B854o0O5.mjs → uploadDataFlowsFromCsv-D1zxhWRt.mjs} +2 -2
  151. package/dist/{uploadDataFlowsFromCsv-B854o0O5.mjs.map → uploadDataFlowsFromCsv-D1zxhWRt.mjs.map} +1 -1
  152. package/dist/{uploadPrivacyRequestsFromCsv-D-RTgJsx.mjs → uploadPrivacyRequestsFromCsv-B8lK4TL2.mjs} +2 -2
  153. package/dist/{uploadPrivacyRequestsFromCsv-D-RTgJsx.mjs.map → uploadPrivacyRequestsFromCsv-B8lK4TL2.mjs.map} +1 -1
  154. package/dist/{validateTranscendAuth-CToEUu1U.mjs → validateTranscendAuth-DrVM-Bxh.mjs} +2 -2
  155. package/dist/{validateTranscendAuth-CToEUu1U.mjs.map → validateTranscendAuth-DrVM-Bxh.mjs.map} +1 -1
  156. package/package.json +3 -3
  157. package/dist/codecs-DW8SY77H.mjs +0 -2
  158. package/dist/constants-B7bW_WN2.mjs +0 -2
  159. package/dist/constants-B7bW_WN2.mjs.map +0 -1
  160. package/dist/enums-CyFTrzXY.mjs.map +0 -1
  161. package/dist/impl-e-_DWiv4.mjs +0 -2
  162. package/dist/impl-e-_DWiv4.mjs.map +0 -1
  163. package/dist/parseVariablesFromString-Cpjk0zeN.mjs +0 -3
  164. package/dist/parseVariablesFromString-Cpjk0zeN.mjs.map +0 -1
  165. package/dist/pullTranscendConfiguration-CICvJuZ5.mjs +0 -58
  166. package/dist/pullTranscendConfiguration-CICvJuZ5.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"uploadPrivacyRequestsFromCsv-D-RTgJsx.mjs","names":[],"sources":["../src/lib/requests/mapEnumValues.ts","../src/lib/requests/getUniqueValuesForColumn.ts","../src/lib/requests/filterRows.ts","../src/lib/requests/mapCsvColumnsToApi.ts","../src/lib/requests/mapRequestEnumValues.ts","../src/lib/requests/mapCsvRowsToRequestInputs.ts","../src/lib/requests/mapColumnsToIdentifiers.ts","../src/lib/requests/mapColumnsToAttributes.ts","../src/lib/requests/uploadPrivacyRequestsFromCsv.ts"],"sourcesContent":["import { apply, ObjByString } from '@transcend-io/type-utils';\nimport inquirer from 'inquirer';\nimport autoCompletePrompt from 'inquirer-autocomplete-prompt';\n\nimport { fuzzySearch } from './fuzzyMatchColumns.js';\n\n/**\n * Map a set of inputs to a set of outputs\n *\n * @param csvInputs - Input list\n * @param expectedOutputs - Output list\n * @param cache - Cache\n * @returns Mapping from row to enum value\n */\nexport async function mapEnumValues<TValue extends string>(\n csvInputs: string[],\n expectedOutputs: TValue[],\n cache: { [k in string]: TValue },\n): Promise<{ [k in string]: TValue }> {\n inquirer.registerPrompt('autocomplete', autoCompletePrompt);\n\n const inputs = csvInputs.map((item) => item || '<blank>').filter((value) => !cache[value]);\n if (inputs.length === 0) {\n return cache;\n }\n const result = await inquirer.prompt<{ [k in string]: TValue }>(\n inputs.map((value) => ({\n name: value,\n message: `Map value of: ${value}`,\n type: 'autocomplete',\n default: expectedOutputs.find((x) => fuzzySearch(value, x)),\n source: (answersSoFar: ObjByString, input: string) =>\n !input\n ? expectedOutputs\n : expectedOutputs.filter((x) => typeof x === 'string' && fuzzySearch(input, x)),\n })),\n );\n return {\n ...cache,\n ...apply(result, (r) =>\n typeof r === 'string' ? (r as TValue) : (Object.values(r)[0] as TValue),\n ),\n };\n}\n","import { ObjByString } from '@transcend-io/type-utils';\nimport { uniq } from 'lodash-es';\n\n/**\n * Return the unique set of values for a column in a CSV\n *\n * @param rows - Rows to look up\n * @param columnName - Name of column to grab values for\n * @returns Unique set of values in that column\n */\nexport function getUniqueValuesForColumn(rows: ObjByString[], columnName: string): string[] {\n return uniq(rows.map((row) => row[columnName] || '').flat());\n}\n","import { ObjByString } from '@transcend-io/type-utils';\nimport colors from 'colors';\nimport inquirer from 'inquirer';\nimport { uniq } from 'lodash-es';\n\nimport { logger } from '../../logger.js';\nimport { NONE } from './constants.js';\nimport { getUniqueValuesForColumn } from './getUniqueValuesForColumn.js';\n\n/**\n * Filter a list of CSV rows by column values\n * Choose columns that contain metadata to filter the requests\n *\n * @param rows - Rows to filter\n * @returns Filtered rows\n */\nexport async function filterRows(rows: ObjByString[]): Promise<ObjByString[]> {\n // Determine set of column names\n const columnNames = uniq(rows.map((x) => Object.keys(x)).flat());\n\n // update these variables recursively\n let filteredRows = rows;\n let keepFiltering = true;\n\n // loop over\n while (keepFiltering) {\n // Prompt user for column to filter on\n\n const { filterColumnName } = await inquirer.prompt<{\n /** Name of column to filter on */\n filterColumnName: string;\n }>([\n {\n name: 'filterColumnName',\n // eslint-disable-next-line max-len\n message: `If you need to filter the list of requests to import, choose the column to filter on. Currently ${filteredRows.length} rows.`,\n type: 'list',\n default: columnNames,\n choices: [NONE, ...columnNames],\n },\n ]);\n\n // Determine if filtering should continue, or loop should be exited\n keepFiltering = NONE !== filterColumnName;\n if (keepFiltering) {\n const options = getUniqueValuesForColumn(filteredRows, filterColumnName);\n\n const { valuesToKeep } = await inquirer.prompt<{\n /** Values to keep */\n valuesToKeep: string[];\n }>([\n {\n name: 'valuesToKeep',\n message: 'Keep rows matching this value',\n type: 'checkbox',\n default: columnNames,\n choices: options,\n },\n ]);\n\n filteredRows = filteredRows.filter((request) =>\n valuesToKeep.includes(request[filterColumnName]),\n );\n }\n }\n\n logger.info(colors.magenta(`Importing ${filteredRows.length} requests`));\n return filteredRows;\n}\n","import type { PersistedState } from '@transcend-io/persisted-state';\nimport { getValues, getEntries } from '@transcend-io/type-utils';\nimport inquirer from 'inquirer';\nimport { startCase } from 'lodash-es';\n\nimport { ColumnName, CachedFileState, IS_REQUIRED, CAN_APPLY_IN_BULK } from './constants.js';\nimport { fuzzyMatchColumns } from './fuzzyMatchColumns.js';\n\n/**\n * Mapping from column name to request input parameter\n */\nexport type ColumnNameMap = {\n [k in ColumnName]?: string;\n};\n\n/**\n * Determine the mapping between columns in CSV\n *\n * @param columnNames - The set of column names\n * @param state - The cached file state used to map DSR inputs\n * @returns The column name mapping\n */\nexport async function mapCsvColumnsToApi(\n columnNames: string[],\n state: PersistedState<typeof CachedFileState>,\n): Promise<ColumnNameMap> {\n // Determine the columns that should be mapped\n const columnQuestions = getValues(ColumnName).filter(\n (name) => !state.getValue('columnNames', name),\n );\n\n // Skip mapping when everything is mapped\n const columnNameMap =\n columnQuestions.length === 0\n ? {}\n : // prompt questions to map columns\n await inquirer.prompt<{\n [k in ColumnName]?: string;\n }>(\n columnQuestions.map((name) => {\n const field = startCase(name.replace('ColumnName', ''));\n const matches = fuzzyMatchColumns(\n columnNames,\n field,\n IS_REQUIRED[name],\n !!CAN_APPLY_IN_BULK[name],\n );\n return {\n name,\n message: `Choose the column that will be used to map in the field: ${field}`,\n type: 'list',\n default: matches[0],\n choices: matches,\n };\n }),\n );\n\n await Promise.all(getEntries(columnNameMap).map(([k, v]) => state.setValue(v, 'columnNames', k)));\n return columnNameMap;\n}\n","import { LOCALE_KEY, type LocaleValue } from '@transcend-io/internationalization';\nimport type { PersistedState } from '@transcend-io/persisted-state';\nimport {\n CompletedRequestStatus,\n RequestAction,\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\nimport { makeGraphQLRequest, DATA_SUBJECTS, type DataSubject } from '@transcend-io/sdk';\nimport { ObjByString } from '@transcend-io/type-utils';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\n\nimport { logger } from '../../logger.js';\nimport { CachedFileState, NONE, ColumnName } from './constants.js';\nimport { getUniqueValuesForColumn } from './getUniqueValuesForColumn.js';\nimport { ColumnNameMap } from './mapCsvColumnsToApi.js';\nimport { mapEnumValues } from './mapEnumValues.js';\n\n/**\n * Map the values in a CSV to the enum values in Transcend\n *\n * @param client - GraphQL client\n * @param requests - Set of privacy requests\n * @param options - Options\n */\nexport async function mapRequestEnumValues(\n client: GraphQLClient,\n requests: ObjByString[],\n {\n state,\n columnNameMap,\n }: {\n /** State value to write cache to */\n state: PersistedState<typeof CachedFileState>;\n /** Mapping of column names */\n columnNameMap: ColumnNameMap;\n },\n): Promise<void> {\n // Get mapped value\n const getMappedName = (attribute: ColumnName): string =>\n state.getValue('columnNames', attribute) || columnNameMap[attribute]!;\n\n // Fetch all data subjects in the organization\n const { internalSubjects } = await makeGraphQLRequest<{\n /** Query response */\n internalSubjects: DataSubject[];\n }>(client, DATA_SUBJECTS, { logger });\n\n // Map RequestAction\n logger.info(colors.magenta('Determining mapping of columns for request action'));\n const requestTypeToRequestAction: { [k in string]: RequestAction } = await mapEnumValues(\n getUniqueValuesForColumn(requests, getMappedName(ColumnName.RequestType)),\n Object.values(RequestAction),\n state.getValue('requestTypeToRequestAction'),\n );\n await state.setValue(requestTypeToRequestAction, 'requestTypeToRequestAction');\n\n // Map data subject type\n logger.info(colors.magenta('Determining mapping of columns for subject'));\n const subjectTypeToSubjectName: { [k in string]: string } = await mapEnumValues(\n getUniqueValuesForColumn(requests, getMappedName(ColumnName.SubjectType)),\n internalSubjects.map(({ type }) => type),\n state.getValue('subjectTypeToSubjectName'),\n );\n await state.setValue(subjectTypeToSubjectName, 'subjectTypeToSubjectName');\n\n // Map locale\n logger.info(colors.magenta('Determining mapping of columns for locale'));\n const languageToLocale: { [k in string]: LocaleValue } = await mapEnumValues(\n getUniqueValuesForColumn(requests, getMappedName(ColumnName.Locale)),\n Object.values(LOCALE_KEY),\n state.getValue('languageToLocale'),\n );\n await state.setValue(languageToLocale, 'languageToLocale');\n logger.info(colors.magenta('Determining mapping of columns for request status'));\n\n // Map request status\n logger.info(colors.magenta('Determining mapping of columns for request status'));\n const requestStatusColumn = getMappedName(ColumnName.RequestStatus);\n const statusToRequestStatus: {\n [k in string]: CompletedRequestStatus | typeof NONE;\n } =\n requestStatusColumn === NONE\n ? {}\n : await mapEnumValues(\n getUniqueValuesForColumn(requests, requestStatusColumn),\n [...Object.values(CompletedRequestStatus), NONE],\n state.getValue('statusToRequestStatus'),\n );\n await state.setValue(statusToRequestStatus, 'statusToRequestStatus');\n\n // Map country\n logger.info(colors.magenta('Determining mapping of columns for country'));\n const countryColumn = getMappedName(ColumnName.Country);\n const regionToCountry: {\n [k in string]: IsoCountryCode | typeof NONE;\n } =\n countryColumn === NONE\n ? {}\n : await mapEnumValues(\n getUniqueValuesForColumn(requests, countryColumn),\n [...Object.values(IsoCountryCode), NONE],\n state.getValue('regionToCountry'),\n );\n await state.setValue(regionToCountry, 'regionToCountry');\n\n // Map country sub division\n logger.info(colors.magenta('Determining mapping of columns for country sub division'));\n const countrySubDivisionColumn = getMappedName(ColumnName.CountrySubDivision);\n const regionToCountrySubDivision: {\n [k in string]: IsoCountrySubdivisionCode | typeof NONE;\n } =\n countrySubDivisionColumn === NONE\n ? {}\n : await mapEnumValues(\n getUniqueValuesForColumn(requests, countrySubDivisionColumn),\n [...Object.values(IsoCountrySubdivisionCode), NONE],\n state.getValue('regionToCountrySubDivision'),\n );\n await state.setValue(regionToCountrySubDivision, 'regionToCountrySubDivision');\n}\n","import { LOCALE_KEY } from '@transcend-io/internationalization';\nimport type { PersistedState } from '@transcend-io/persisted-state';\nimport {\n NORMALIZE_PHONE_NUMBER,\n CompletedRequestStatus,\n RequestAction,\n IdentifierType,\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\nimport type { AttributeKey } from '@transcend-io/sdk';\nimport { ObjByString, valuesOf } from '@transcend-io/type-utils';\nimport { splitCsvToList } from '@transcend-io/utils';\nimport * as t from 'io-ts';\nimport { DateFromISOString } from 'io-ts-types';\n\nimport { CachedFileState, BLANK, BULK_APPLY, ColumnName, NONE } from './constants.js';\nimport { AttributeNameMap } from './mapColumnsToAttributes.js';\nimport { IdentifierNameMap } from './mapColumnsToIdentifiers.js';\nimport { ColumnNameMap } from './mapCsvColumnsToApi.js';\nimport { ParsedAttributeInput } from './parseAttributesFromString.js';\n\n/**\n * Shape of additional identifiers\n *\n * key of object is IdentifierType\n */\nexport const AttestedExtraIdentifiers = t.record(\n t.string,\n t.array(\n t.intersection([\n t.type({\n /** Value of identifier */\n value: t.string,\n }),\n t.partial({\n /** Name of identifier - option for non-custom identifier types */\n name: t.string,\n }),\n ]),\n ),\n);\n\n/** Type override */\nexport type AttestedExtraIdentifiers = t.TypeOf<typeof AttestedExtraIdentifiers>;\n\nexport const PrivacyRequestInput = t.intersection([\n t.type({\n /** Email of user */\n email: t.string,\n /** Extra identifiers */\n attestedExtraIdentifiers: AttestedExtraIdentifiers,\n /** Core identifier for user */\n coreIdentifier: t.string,\n /** Action type being submitted */\n requestType: valuesOf(RequestAction),\n /** Type of data subject */\n subjectType: t.string,\n }),\n t.partial({\n /** Country */\n country: valuesOf(IsoCountryCode),\n /** Country sub division */\n countrySubDivision: valuesOf(IsoCountrySubdivisionCode),\n /** Attribute inputs */\n attributes: t.array(ParsedAttributeInput),\n /** The status that the request should be created as */\n status: valuesOf(CompletedRequestStatus),\n /** The time that the request was created */\n createdAt: DateFromISOString,\n /** Data silo IDs to submit for */\n dataSiloIds: t.array(t.string),\n /** Language key to map to */\n locale: valuesOf(LOCALE_KEY),\n }),\n]);\n\n/** Type override */\nexport type PrivacyRequestInput = t.TypeOf<typeof PrivacyRequestInput>;\n\n/**\n * Transform the identifier value based on type\n *\n * @param identifierValue - Value of identifier\n * @param identifierType - Type of identifier\n * @param defaultPhoneCountryCode - Default country code for phone numbers\n * @returns Post-processed identifier\n */\nexport function normalizeIdentifierValue(\n identifierValue: string,\n identifierType: IdentifierType,\n defaultPhoneCountryCode: string,\n): string {\n // Lowercase email\n if (identifierType === IdentifierType.Email) {\n return identifierValue.toLowerCase();\n }\n\n // Normalize phone number\n if (identifierType === IdentifierType.Phone) {\n const normalized = identifierValue\n .replace(NORMALIZE_PHONE_NUMBER, '')\n .replace(/[()]/g, '')\n .replace(/[–]/g, '')\n .replace(/[:]/g, '')\n .replace(/[‭‬]/g, '')\n .replace(/[A-Za-z]/g, '');\n return !normalized\n ? ''\n : normalized.startsWith('+')\n ? normalized\n : `+${defaultPhoneCountryCode}${normalized}`;\n }\n return identifierValue;\n}\n\n/**\n * Take the raw rows in a CSV upload, and map those rows to the request\n * input shape that can be passed to the Transcend API to submit a privacy\n * request.\n *\n * @param requestInputs - CSV of requests to be uploaded\n * @param state - The cached set of mapping values\n * @param options - Options\n * @returns [raw input, request input] list\n */\nexport function mapCsvRowsToRequestInputs(\n requestInputs: ObjByString[],\n state: PersistedState<typeof CachedFileState>,\n {\n columnNameMap,\n identifierNameMap,\n attributeNameMap,\n requestAttributeKeys,\n defaultPhoneCountryCode = '1', // US\n }: {\n /** Default country code */\n defaultPhoneCountryCode?: string;\n /** Mapping of column names */\n columnNameMap: ColumnNameMap;\n /** Mapping of identifier names */\n identifierNameMap: IdentifierNameMap;\n /** Mapping of attribute names */\n attributeNameMap: AttributeNameMap;\n /** Request attribute keys */\n requestAttributeKeys: AttributeKey[];\n },\n): [Record<string, string>, PrivacyRequestInput][] {\n // map the CSV to request input\n const getMappedName = (attribute: ColumnName): string =>\n state.getValue('columnNames', attribute) || columnNameMap[attribute]!;\n return requestInputs.map((input): [Record<string, string>, PrivacyRequestInput] => {\n // The extra identifiers to upload for this request\n const attestedExtraIdentifiers: AttestedExtraIdentifiers = {};\n Object.entries(identifierNameMap)\n // filter out skipped identifiers\n .filter(([, columnName]) => columnName !== NONE)\n .forEach(([identifierName, columnName]) => {\n // Determine the identifier type being specified\n const identifierType = Object.values(IdentifierType).includes(\n identifierName as any, // eslint-disable-line @typescript-eslint/no-explicit-any\n )\n ? (identifierName as IdentifierType)\n : IdentifierType.Custom;\n\n // Only add the identifier if the value exists\n const identifierValue = input[columnName];\n if (identifierValue) {\n const normalized = normalizeIdentifierValue(\n identifierValue,\n identifierType,\n defaultPhoneCountryCode,\n );\n if (normalized) {\n // Initialize\n if (!attestedExtraIdentifiers[identifierType]) {\n attestedExtraIdentifiers[identifierType] = [];\n }\n\n // Add the identifier\n attestedExtraIdentifiers[identifierType]!.push({\n value: normalized,\n name: identifierName,\n });\n }\n }\n });\n\n // The extra attributes to upload for this request\n const attributes: ParsedAttributeInput[] = [];\n Object.entries(attributeNameMap)\n // filter out skipped attributes\n .filter(([, columnName]) => columnName !== NONE)\n .forEach(([attributeName, columnName]) => {\n // Only add the identifier if the value exists\n const attributeValueString = input[columnName];\n if (attributeValueString) {\n // Add the attribute\n const isMulti =\n requestAttributeKeys.find((attr) => attr.name === attributeName)?.type ===\n 'MULTI_SELECT';\n attributes.push({\n values: isMulti ? splitCsvToList(attributeValueString) : attributeValueString,\n key: attributeName,\n });\n }\n });\n\n const requestTypeColumn = getMappedName(ColumnName.RequestType);\n const dataSubjectTypeColumn = getMappedName(ColumnName.SubjectType);\n return [\n input,\n {\n email: input[getMappedName(ColumnName.Email)],\n attestedExtraIdentifiers,\n attributes,\n coreIdentifier: input[getMappedName(ColumnName.CoreIdentifier)],\n requestType:\n requestTypeColumn === BULK_APPLY\n ? state.getValue('requestTypeToRequestAction', BLANK)\n : state.getValue('requestTypeToRequestAction', input[requestTypeColumn]),\n subjectType:\n dataSubjectTypeColumn === BULK_APPLY\n ? state.getValue('subjectTypeToSubjectName', BLANK)\n : state.getValue('subjectTypeToSubjectName', input[dataSubjectTypeColumn]),\n ...(getMappedName(ColumnName.Locale) !== NONE && input[getMappedName(ColumnName.Locale)]\n ? {\n locale: state.getValue('languageToLocale', input[getMappedName(ColumnName.Locale)]),\n }\n : {}),\n ...(getMappedName(ColumnName.Country) !== NONE && input[getMappedName(ColumnName.Country)]\n ? {\n country: state.getValue(\n 'regionToCountry',\n input[getMappedName(ColumnName.Country)],\n ) as IsoCountryCode,\n }\n : {}),\n ...(getMappedName(ColumnName.CountrySubDivision) !== NONE &&\n input[getMappedName(ColumnName.CountrySubDivision)]\n ? {\n countrySubDivision: state.getValue(\n 'regionToCountrySubDivision',\n input[getMappedName(ColumnName.CountrySubDivision)],\n ) as IsoCountrySubdivisionCode,\n }\n : {}),\n ...(getMappedName(ColumnName.RequestStatus) !== NONE &&\n state.getValue('statusToRequestStatus', input[getMappedName(ColumnName.RequestStatus)]) !==\n NONE &&\n input[getMappedName(ColumnName.RequestStatus)]\n ? {\n status: state.getValue(\n 'statusToRequestStatus',\n input[getMappedName(ColumnName.RequestStatus)],\n ) as CompletedRequestStatus,\n }\n : {}),\n ...(getMappedName(ColumnName.CreatedAt) !== NONE &&\n input[getMappedName(ColumnName.CreatedAt)]\n ? {\n createdAt: new Date(input[getMappedName(ColumnName.CreatedAt)]),\n }\n : {}),\n ...(getMappedName(ColumnName.DataSiloIds) !== NONE &&\n input[getMappedName(ColumnName.DataSiloIds)]\n ? {\n dataSiloIds: splitCsvToList(input[getMappedName(ColumnName.DataSiloIds)]),\n }\n : {}),\n },\n ];\n });\n}\n","import type { PersistedState } from '@transcend-io/persisted-state';\nimport { INITIALIZER, type Initializer, makeGraphQLRequest } from '@transcend-io/sdk';\nimport type { GraphQLClient } from 'graphql-request';\nimport inquirer from 'inquirer';\n\nimport { logger } from '../../logger.js';\nimport { CachedFileState, IDENTIFIER_BLOCK_LIST } from './constants.js';\nimport { fuzzyMatchColumns } from './fuzzyMatchColumns.js';\n\n/**\n * Mapping from identifier name to request input parameter\n */\nexport type IdentifierNameMap = {\n [k in string]: string;\n};\n\n/**\n * Create a mapping from the identifier names that can be included\n * at request submission, to the names of the columns that map to those\n * identifiers.\n *\n * @param client - GraphQL client\n * @param columnNames - The set of all column names\n * @param state - Cached state of this mapping\n * @returns Mapping from identifier name to column name\n */\nexport async function mapColumnsToIdentifiers(\n client: GraphQLClient,\n columnNames: string[],\n state: PersistedState<typeof CachedFileState>,\n): Promise<IdentifierNameMap> {\n // Grab the initializer\n const { initializer } = await makeGraphQLRequest<{\n /** Query response */\n initializer: Initializer;\n }>(client, INITIALIZER, { logger });\n\n // Determine the columns that should be mapped\n const columnQuestions = initializer.identifiers.filter(\n ({ name }) => !state.getValue('identifierNames', name) && !IDENTIFIER_BLOCK_LIST.includes(name),\n );\n\n // Skip mapping when everything is mapped\n const identifierNameMap =\n columnQuestions.length === 0\n ? {}\n : // prompt questions to map columns\n await inquirer.prompt<{\n [k in string]: string;\n }>(\n columnQuestions.map(({ name }) => {\n const matches = fuzzyMatchColumns(columnNames, name, false);\n return {\n name,\n message: `Choose the column that will be used to map in the identifier: ${name}`,\n type: 'list',\n default: matches[0],\n choices: matches,\n };\n }),\n );\n await Promise.all(\n Object.entries(identifierNameMap).map(([k, v]) => state.setValue(v, 'identifierNames', k)),\n );\n\n return {\n ...state.getValue('identifierNames'),\n ...identifierNameMap,\n };\n}\n","import type { PersistedState } from '@transcend-io/persisted-state';\nimport type { AttributeKey } from '@transcend-io/sdk';\nimport type { GraphQLClient } from 'graphql-request';\nimport inquirer from 'inquirer';\n\nimport { CachedFileState } from './constants.js';\nimport { fuzzyMatchColumns } from './fuzzyMatchColumns.js';\n\n/**\n * Mapping from attribute name to request input parameter\n */\nexport type AttributeNameMap = {\n [k in string]: string;\n};\n\n/**\n * Create a mapping from the attributes names that can be included\n * at request submission, to the names of the columns that map to those\n * attributes.\n *\n * @param client - GraphQL client\n * @param columnNames - The set of all column names\n * @param state - Cached state of this mapping\n * @param requestAttributeKeys - Attribute keys to map\n * @returns Mapping from attributes name to column name\n */\nexport async function mapColumnsToAttributes(\n client: GraphQLClient,\n columnNames: string[],\n state: PersistedState<typeof CachedFileState>,\n requestAttributeKeys: AttributeKey[],\n): Promise<AttributeNameMap> {\n // Determine the columns that should be mapped\n const columnQuestions = requestAttributeKeys.filter(\n ({ name }) => !state.getValue('attributeNames', name),\n );\n\n // Skip mapping when everything is mapped\n const attributeNameMap =\n columnQuestions.length === 0\n ? {}\n : // prompt questions to map columns\n await inquirer.prompt<{\n [k in string]: string;\n }>(\n columnQuestions.map(({ name }) => {\n const matches = fuzzyMatchColumns(columnNames, name, false);\n return {\n name,\n message: `Choose the column that will be used to map in the attribute: ${name}`,\n type: 'list',\n default: matches[0],\n choices: matches,\n };\n }),\n );\n await Promise.all(\n Object.entries(attributeNameMap).map(([k, v]) => state.setValue(v, 'attributeNames', k)),\n );\n\n return {\n ...state.getValue('attributeNames'),\n ...attributeNameMap,\n };\n}\n","import { join } from 'node:path';\n\nimport { PersistedState } from '@transcend-io/persisted-state';\nimport {\n buildTranscendGraphQLClient,\n createSombraGotInstance,\n fetchAllRequestAttributeKeys,\n} from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport cliProgress from 'cli-progress';\n/* eslint-disable max-lines */\nimport colors from 'colors';\nimport * as t from 'io-ts';\nimport { uniq } from 'lodash-es';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\nimport { CachedRequestState, CachedFileState } from './constants.js';\nimport { extractClientError } from './extractClientError.js';\nimport { filterRows } from './filterRows.js';\nimport { mapColumnsToAttributes } from './mapColumnsToAttributes.js';\nimport { mapColumnsToIdentifiers } from './mapColumnsToIdentifiers.js';\nimport { mapCsvColumnsToApi } from './mapCsvColumnsToApi.js';\nimport { mapCsvRowsToRequestInputs } from './mapCsvRowsToRequestInputs.js';\nimport { mapRequestEnumValues } from './mapRequestEnumValues.js';\nimport { parseAttributesFromString } from './parseAttributesFromString.js';\nimport { readCsv } from './readCsv.js';\nimport { submitPrivacyRequest } from './submitPrivacyRequest.js';\n\n/**\n * Upload a set of privacy requests from CSV\n *\n * @param options - Options\n */\nexport async function uploadPrivacyRequestsFromCsv({\n cacheFilepath,\n requestReceiptFolder,\n file,\n auth,\n sombraAuth,\n concurrency = 100,\n defaultPhoneCountryCode = '1', // USA\n transcendUrl = DEFAULT_TRANSCEND_API,\n attributes = [],\n emailIsVerified = true,\n skipFilterStep = false,\n skipSendingReceipt = true,\n isTest = false,\n isSilent = true,\n debug = false,\n dryRun = false,\n}: {\n /** File to cache metadata about mapping of CSV shape to script */\n cacheFilepath: string;\n /** File where request receipts are stored */\n requestReceiptFolder: string;\n /** CSV file path */\n file: string;\n /** Transcend API key authentication */\n auth: string;\n /** Default country code for phone numbers */\n defaultPhoneCountryCode?: string;\n /** Concurrency to upload in */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** Include debug logs */\n debug?: boolean;\n /** Skip the step where requests are filtered */\n skipFilterStep?: boolean;\n /** Whether test requests are being uploaded */\n isTest?: boolean;\n /** Whether requests are uploaded in silent mode */\n isSilent?: boolean;\n /** Whether to send the email receipt */\n skipSendingReceipt?: boolean;\n /** Whether the email was verified up front */\n emailIsVerified?: boolean;\n /** Attributes string pre-parse */\n attributes?: string[];\n /** Whether a dry run is happening */\n dryRun?: boolean;\n}): Promise<void> {\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 // Parse out the extra attributes to apply to all requests uploaded\n const parsedAttributes = parseAttributesFromString(attributes);\n\n // Create a new state to persist the metadata that\n // maps the request inputs to the Transcend API shape\n const state = new PersistedState(cacheFilepath, CachedFileState, {\n columnNames: {},\n requestTypeToRequestAction: {},\n subjectTypeToSubjectName: {},\n languageToLocale: {},\n statusToRequestStatus: {},\n identifierNames: {},\n attributeNames: {},\n regionToCountrySubDivision: {},\n regionToCountry: {},\n });\n\n // Create a new state file to store the requests from this run.\n // `toISOString()` contains colons (e.g. 2026-07-06T04:33:12.345Z) which are\n // illegal characters in Windows filenames, so strip them out to keep the\n // auto-generated receipt filename cross-platform.\n const requestCacheFile = join(\n requestReceiptFolder,\n `tr-request-upload-${new Date()\n .toISOString()\n .replace(/:/g, '-')}-${file.split('/').pop()}`.replace('.csv', '.json'),\n );\n const requestState = new PersistedState(requestCacheFile, CachedRequestState, {\n successfulRequests: [],\n duplicateRequests: [],\n failingRequests: [],\n });\n\n // Create sombra instance to communicate with\n const sombra = await createSombraGotInstance(transcendUrl, auth, {\n logger,\n sombraApiKey: sombraAuth,\n sombraUrl: process.env.SOMBRA_URL,\n });\n\n // Read in the list of integration requests\n const requestsList = readCsv(file, t.record(t.string, t.string));\n const columnNames = uniq(requestsList.map((x) => Object.keys(x)).flat());\n\n // Log out an example request\n if (requestsList.length === 0) {\n throw new Error(\n 'No Requests found in list! Ensure the first row of the CSV is a header and the rest are requests.',\n );\n }\n if (debug) {\n const firstRequest = requestsList[0];\n logger.info(colors.magenta(`First request: ${JSON.stringify(firstRequest, null, 2)}`));\n }\n // Determine what rows in the CSV should be imported\n // Choose columns that contain metadata to filter the requests\n const filteredRequestList = skipFilterStep ? requestsList : await filterRows(requestsList);\n\n // Build a GraphQL client\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n // Grab the request attributes\n const requestAttributeKeys = await fetchAllRequestAttributeKeys(client, { logger });\n // Determine the columns that should be mapped\n const columnNameMap = await mapCsvColumnsToApi(columnNames, state);\n const identifierNameMap = await mapColumnsToIdentifiers(client, columnNames, state);\n const attributeNameMap = await mapColumnsToAttributes(\n client,\n columnNames,\n state,\n requestAttributeKeys,\n );\n await mapRequestEnumValues(client, filteredRequestList, {\n state,\n columnNameMap,\n });\n\n // map the CSV to request input\n const requestInputs = mapCsvRowsToRequestInputs(filteredRequestList, state, {\n defaultPhoneCountryCode,\n columnNameMap,\n identifierNameMap,\n attributeNameMap,\n requestAttributeKeys,\n });\n\n // start the progress bar with a total value of 200 and start value of 0\n if (!debug) {\n progressBar.start(requestInputs.length, 0);\n }\n let total = 0;\n // Submit each request\n await map(\n requestInputs,\n async ([rawRow, requestInput], ind) => {\n // The identifier to log, only include personal data if debug mode is on\n const requestLogId = debug\n ? `email:${requestInput.email} | coreIdentifier:${requestInput.coreIdentifier}`\n : `row:${ind.toString()}`;\n\n if (debug) {\n logger.info(\n colors.magenta(\n `[${ind + 1}/${requestInputs.length}] Importing: ${JSON.stringify(\n requestInput,\n null,\n 2,\n )}`,\n ),\n );\n }\n\n // Skip on dry run\n if (dryRun) {\n logger.info(colors.magenta('Bailing out on dry run because dryRun is set'));\n return;\n }\n\n try {\n // Make the GraphQL request to submit the privacy request\n const requestResponse = await submitPrivacyRequest(sombra, requestInput, {\n details: `Uploaded by Transcend Cli: \"tr-request-upload\" : ${JSON.stringify(\n rawRow,\n null,\n 2,\n )}`,\n isTest,\n emailIsVerified,\n skipSendingReceipt,\n isSilent,\n additionalAttributes: parsedAttributes,\n });\n\n // Log success\n if (debug) {\n logger.info(\n colors.green(\n `[${ind + 1}/${\n requestInputs.length\n }] Successfully submitted the test data subject request: \"${requestLogId}\"`,\n ),\n );\n logger.info(\n colors.green(\n `[${ind + 1}/${requestInputs.length}] View it at: \"${requestResponse.link}\"`,\n ),\n );\n }\n\n // Cache successful upload\n const successfulRequests = requestState.getValue('successfulRequests');\n successfulRequests.push({\n id: requestResponse.id,\n link: requestResponse.link,\n rowIndex: ind,\n coreIdentifier: requestResponse.coreIdentifier,\n attemptedAt: new Date().toISOString(),\n });\n await requestState.setValue(successfulRequests, 'successfulRequests');\n } catch (err) {\n const msg = `${err.message} - ${JSON.stringify(err.response?.body, null, 2)}`;\n const clientError = extractClientError(msg);\n\n if (clientError === 'Client error: You have already made this request.') {\n if (debug) {\n logger.info(\n colors.yellow(\n `[${ind + 1}/${requestInputs.length}] Skipping request as it is a duplicate`,\n ),\n );\n }\n const duplicateRequests = requestState.getValue('duplicateRequests');\n duplicateRequests.push({\n coreIdentifier: requestInput.coreIdentifier,\n rowIndex: ind,\n attemptedAt: new Date().toISOString(),\n });\n await requestState.setValue(duplicateRequests, 'duplicateRequests');\n } else {\n const failingRequests = requestState.getValue('failingRequests');\n failingRequests.push({\n ...requestInput,\n rowIndex: ind,\n error: clientError || msg,\n attemptedAt: new Date().toISOString(),\n });\n await requestState.setValue(failingRequests, 'failingRequests');\n if (debug) {\n logger.error(colors.red(clientError || msg));\n logger.error(\n colors.red(\n `[${ind + 1}/${\n requestInputs.length\n }] Failed to submit request for: \"${requestLogId}\"`,\n ),\n );\n }\n }\n }\n\n total += 1;\n if (!debug) {\n progressBar.update(total);\n }\n },\n {\n concurrency,\n },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n // Log completion time\n logger.info(colors.green(`Completed upload in \"${totalTime / 1000}\" seconds.`));\n\n // Log duplicates\n if (requestState.getValue('duplicateRequests').length > 0) {\n logger.info(\n colors.yellow(\n `Encountered \"${requestState.getValue('duplicateRequests').length}\" duplicate requests. ` +\n `See \"${requestCacheFile}\" to review the core identifiers for these requests.`,\n ),\n );\n }\n\n // Log errors\n if (requestState.getValue('failingRequests').length > 0) {\n logger.error(\n colors.red(\n `Encountered \"${requestState.getValue('failingRequests').length}\" errors. ` +\n `See \"${requestCacheFile}\" to review the error messages and inputs.`,\n ),\n );\n process.exit(1);\n }\n}\n/* eslint-enable max-lines */\n"],"mappings":"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"}
1
+ {"version":3,"file":"uploadPrivacyRequestsFromCsv-B8lK4TL2.mjs","names":[],"sources":["../src/lib/requests/mapEnumValues.ts","../src/lib/requests/getUniqueValuesForColumn.ts","../src/lib/requests/filterRows.ts","../src/lib/requests/mapCsvColumnsToApi.ts","../src/lib/requests/mapRequestEnumValues.ts","../src/lib/requests/mapCsvRowsToRequestInputs.ts","../src/lib/requests/mapColumnsToIdentifiers.ts","../src/lib/requests/mapColumnsToAttributes.ts","../src/lib/requests/uploadPrivacyRequestsFromCsv.ts"],"sourcesContent":["import { apply, ObjByString } from '@transcend-io/type-utils';\nimport inquirer from 'inquirer';\nimport autoCompletePrompt from 'inquirer-autocomplete-prompt';\n\nimport { fuzzySearch } from './fuzzyMatchColumns.js';\n\n/**\n * Map a set of inputs to a set of outputs\n *\n * @param csvInputs - Input list\n * @param expectedOutputs - Output list\n * @param cache - Cache\n * @returns Mapping from row to enum value\n */\nexport async function mapEnumValues<TValue extends string>(\n csvInputs: string[],\n expectedOutputs: TValue[],\n cache: { [k in string]: TValue },\n): Promise<{ [k in string]: TValue }> {\n inquirer.registerPrompt('autocomplete', autoCompletePrompt);\n\n const inputs = csvInputs.map((item) => item || '<blank>').filter((value) => !cache[value]);\n if (inputs.length === 0) {\n return cache;\n }\n const result = await inquirer.prompt<{ [k in string]: TValue }>(\n inputs.map((value) => ({\n name: value,\n message: `Map value of: ${value}`,\n type: 'autocomplete',\n default: expectedOutputs.find((x) => fuzzySearch(value, x)),\n source: (answersSoFar: ObjByString, input: string) =>\n !input\n ? expectedOutputs\n : expectedOutputs.filter((x) => typeof x === 'string' && fuzzySearch(input, x)),\n })),\n );\n return {\n ...cache,\n ...apply(result, (r) =>\n typeof r === 'string' ? (r as TValue) : (Object.values(r)[0] as TValue),\n ),\n };\n}\n","import { ObjByString } from '@transcend-io/type-utils';\nimport { uniq } from 'lodash-es';\n\n/**\n * Return the unique set of values for a column in a CSV\n *\n * @param rows - Rows to look up\n * @param columnName - Name of column to grab values for\n * @returns Unique set of values in that column\n */\nexport function getUniqueValuesForColumn(rows: ObjByString[], columnName: string): string[] {\n return uniq(rows.map((row) => row[columnName] || '').flat());\n}\n","import { ObjByString } from '@transcend-io/type-utils';\nimport colors from 'colors';\nimport inquirer from 'inquirer';\nimport { uniq } from 'lodash-es';\n\nimport { logger } from '../../logger.js';\nimport { NONE } from './constants.js';\nimport { getUniqueValuesForColumn } from './getUniqueValuesForColumn.js';\n\n/**\n * Filter a list of CSV rows by column values\n * Choose columns that contain metadata to filter the requests\n *\n * @param rows - Rows to filter\n * @returns Filtered rows\n */\nexport async function filterRows(rows: ObjByString[]): Promise<ObjByString[]> {\n // Determine set of column names\n const columnNames = uniq(rows.map((x) => Object.keys(x)).flat());\n\n // update these variables recursively\n let filteredRows = rows;\n let keepFiltering = true;\n\n // loop over\n while (keepFiltering) {\n // Prompt user for column to filter on\n\n const { filterColumnName } = await inquirer.prompt<{\n /** Name of column to filter on */\n filterColumnName: string;\n }>([\n {\n name: 'filterColumnName',\n // eslint-disable-next-line max-len\n message: `If you need to filter the list of requests to import, choose the column to filter on. Currently ${filteredRows.length} rows.`,\n type: 'list',\n default: columnNames,\n choices: [NONE, ...columnNames],\n },\n ]);\n\n // Determine if filtering should continue, or loop should be exited\n keepFiltering = NONE !== filterColumnName;\n if (keepFiltering) {\n const options = getUniqueValuesForColumn(filteredRows, filterColumnName);\n\n const { valuesToKeep } = await inquirer.prompt<{\n /** Values to keep */\n valuesToKeep: string[];\n }>([\n {\n name: 'valuesToKeep',\n message: 'Keep rows matching this value',\n type: 'checkbox',\n default: columnNames,\n choices: options,\n },\n ]);\n\n filteredRows = filteredRows.filter((request) =>\n valuesToKeep.includes(request[filterColumnName]),\n );\n }\n }\n\n logger.info(colors.magenta(`Importing ${filteredRows.length} requests`));\n return filteredRows;\n}\n","import type { PersistedState } from '@transcend-io/persisted-state';\nimport { getValues, getEntries } from '@transcend-io/type-utils';\nimport inquirer from 'inquirer';\nimport { startCase } from 'lodash-es';\n\nimport { ColumnName, CachedFileState, IS_REQUIRED, CAN_APPLY_IN_BULK } from './constants.js';\nimport { fuzzyMatchColumns } from './fuzzyMatchColumns.js';\n\n/**\n * Mapping from column name to request input parameter\n */\nexport type ColumnNameMap = {\n [k in ColumnName]?: string;\n};\n\n/**\n * Determine the mapping between columns in CSV\n *\n * @param columnNames - The set of column names\n * @param state - The cached file state used to map DSR inputs\n * @returns The column name mapping\n */\nexport async function mapCsvColumnsToApi(\n columnNames: string[],\n state: PersistedState<typeof CachedFileState>,\n): Promise<ColumnNameMap> {\n // Determine the columns that should be mapped\n const columnQuestions = getValues(ColumnName).filter(\n (name) => !state.getValue('columnNames', name),\n );\n\n // Skip mapping when everything is mapped\n const columnNameMap =\n columnQuestions.length === 0\n ? {}\n : // prompt questions to map columns\n await inquirer.prompt<{\n [k in ColumnName]?: string;\n }>(\n columnQuestions.map((name) => {\n const field = startCase(name.replace('ColumnName', ''));\n const matches = fuzzyMatchColumns(\n columnNames,\n field,\n IS_REQUIRED[name],\n !!CAN_APPLY_IN_BULK[name],\n );\n return {\n name,\n message: `Choose the column that will be used to map in the field: ${field}`,\n type: 'list',\n default: matches[0],\n choices: matches,\n };\n }),\n );\n\n await Promise.all(getEntries(columnNameMap).map(([k, v]) => state.setValue(v, 'columnNames', k)));\n return columnNameMap;\n}\n","import { LOCALE_KEY, type LocaleValue } from '@transcend-io/internationalization';\nimport type { PersistedState } from '@transcend-io/persisted-state';\nimport {\n CompletedRequestStatus,\n RequestAction,\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\nimport { makeGraphQLRequest, DATA_SUBJECTS, type DataSubject } from '@transcend-io/sdk';\nimport { ObjByString } from '@transcend-io/type-utils';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\n\nimport { logger } from '../../logger.js';\nimport { CachedFileState, NONE, ColumnName } from './constants.js';\nimport { getUniqueValuesForColumn } from './getUniqueValuesForColumn.js';\nimport { ColumnNameMap } from './mapCsvColumnsToApi.js';\nimport { mapEnumValues } from './mapEnumValues.js';\n\n/**\n * Map the values in a CSV to the enum values in Transcend\n *\n * @param client - GraphQL client\n * @param requests - Set of privacy requests\n * @param options - Options\n */\nexport async function mapRequestEnumValues(\n client: GraphQLClient,\n requests: ObjByString[],\n {\n state,\n columnNameMap,\n }: {\n /** State value to write cache to */\n state: PersistedState<typeof CachedFileState>;\n /** Mapping of column names */\n columnNameMap: ColumnNameMap;\n },\n): Promise<void> {\n // Get mapped value\n const getMappedName = (attribute: ColumnName): string =>\n state.getValue('columnNames', attribute) || columnNameMap[attribute]!;\n\n // Fetch all data subjects in the organization\n const { internalSubjects } = await makeGraphQLRequest<{\n /** Query response */\n internalSubjects: DataSubject[];\n }>(client, DATA_SUBJECTS, { logger });\n\n // Map RequestAction\n logger.info(colors.magenta('Determining mapping of columns for request action'));\n const requestTypeToRequestAction: { [k in string]: RequestAction } = await mapEnumValues(\n getUniqueValuesForColumn(requests, getMappedName(ColumnName.RequestType)),\n Object.values(RequestAction),\n state.getValue('requestTypeToRequestAction'),\n );\n await state.setValue(requestTypeToRequestAction, 'requestTypeToRequestAction');\n\n // Map data subject type\n logger.info(colors.magenta('Determining mapping of columns for subject'));\n const subjectTypeToSubjectName: { [k in string]: string } = await mapEnumValues(\n getUniqueValuesForColumn(requests, getMappedName(ColumnName.SubjectType)),\n internalSubjects.map(({ type }) => type),\n state.getValue('subjectTypeToSubjectName'),\n );\n await state.setValue(subjectTypeToSubjectName, 'subjectTypeToSubjectName');\n\n // Map locale\n logger.info(colors.magenta('Determining mapping of columns for locale'));\n const languageToLocale: { [k in string]: LocaleValue } = await mapEnumValues(\n getUniqueValuesForColumn(requests, getMappedName(ColumnName.Locale)),\n Object.values(LOCALE_KEY),\n state.getValue('languageToLocale'),\n );\n await state.setValue(languageToLocale, 'languageToLocale');\n logger.info(colors.magenta('Determining mapping of columns for request status'));\n\n // Map request status\n logger.info(colors.magenta('Determining mapping of columns for request status'));\n const requestStatusColumn = getMappedName(ColumnName.RequestStatus);\n const statusToRequestStatus: {\n [k in string]: CompletedRequestStatus | typeof NONE;\n } =\n requestStatusColumn === NONE\n ? {}\n : await mapEnumValues(\n getUniqueValuesForColumn(requests, requestStatusColumn),\n [...Object.values(CompletedRequestStatus), NONE],\n state.getValue('statusToRequestStatus'),\n );\n await state.setValue(statusToRequestStatus, 'statusToRequestStatus');\n\n // Map country\n logger.info(colors.magenta('Determining mapping of columns for country'));\n const countryColumn = getMappedName(ColumnName.Country);\n const regionToCountry: {\n [k in string]: IsoCountryCode | typeof NONE;\n } =\n countryColumn === NONE\n ? {}\n : await mapEnumValues(\n getUniqueValuesForColumn(requests, countryColumn),\n [...Object.values(IsoCountryCode), NONE],\n state.getValue('regionToCountry'),\n );\n await state.setValue(regionToCountry, 'regionToCountry');\n\n // Map country sub division\n logger.info(colors.magenta('Determining mapping of columns for country sub division'));\n const countrySubDivisionColumn = getMappedName(ColumnName.CountrySubDivision);\n const regionToCountrySubDivision: {\n [k in string]: IsoCountrySubdivisionCode | typeof NONE;\n } =\n countrySubDivisionColumn === NONE\n ? {}\n : await mapEnumValues(\n getUniqueValuesForColumn(requests, countrySubDivisionColumn),\n [...Object.values(IsoCountrySubdivisionCode), NONE],\n state.getValue('regionToCountrySubDivision'),\n );\n await state.setValue(regionToCountrySubDivision, 'regionToCountrySubDivision');\n}\n","import { LOCALE_KEY } from '@transcend-io/internationalization';\nimport type { PersistedState } from '@transcend-io/persisted-state';\nimport {\n NORMALIZE_PHONE_NUMBER,\n CompletedRequestStatus,\n RequestAction,\n IdentifierType,\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\nimport type { AttributeKey } from '@transcend-io/sdk';\nimport { ObjByString, valuesOf } from '@transcend-io/type-utils';\nimport { splitCsvToList } from '@transcend-io/utils';\nimport * as t from 'io-ts';\nimport { DateFromISOString } from 'io-ts-types';\n\nimport { CachedFileState, BLANK, BULK_APPLY, ColumnName, NONE } from './constants.js';\nimport { AttributeNameMap } from './mapColumnsToAttributes.js';\nimport { IdentifierNameMap } from './mapColumnsToIdentifiers.js';\nimport { ColumnNameMap } from './mapCsvColumnsToApi.js';\nimport { ParsedAttributeInput } from './parseAttributesFromString.js';\n\n/**\n * Shape of additional identifiers\n *\n * key of object is IdentifierType\n */\nexport const AttestedExtraIdentifiers = t.record(\n t.string,\n t.array(\n t.intersection([\n t.type({\n /** Value of identifier */\n value: t.string,\n }),\n t.partial({\n /** Name of identifier - option for non-custom identifier types */\n name: t.string,\n }),\n ]),\n ),\n);\n\n/** Type override */\nexport type AttestedExtraIdentifiers = t.TypeOf<typeof AttestedExtraIdentifiers>;\n\nexport const PrivacyRequestInput = t.intersection([\n t.type({\n /** Email of user */\n email: t.string,\n /** Extra identifiers */\n attestedExtraIdentifiers: AttestedExtraIdentifiers,\n /** Core identifier for user */\n coreIdentifier: t.string,\n /** Action type being submitted */\n requestType: valuesOf(RequestAction),\n /** Type of data subject */\n subjectType: t.string,\n }),\n t.partial({\n /** Country */\n country: valuesOf(IsoCountryCode),\n /** Country sub division */\n countrySubDivision: valuesOf(IsoCountrySubdivisionCode),\n /** Attribute inputs */\n attributes: t.array(ParsedAttributeInput),\n /** The status that the request should be created as */\n status: valuesOf(CompletedRequestStatus),\n /** The time that the request was created */\n createdAt: DateFromISOString,\n /** Data silo IDs to submit for */\n dataSiloIds: t.array(t.string),\n /** Language key to map to */\n locale: valuesOf(LOCALE_KEY),\n }),\n]);\n\n/** Type override */\nexport type PrivacyRequestInput = t.TypeOf<typeof PrivacyRequestInput>;\n\n/**\n * Transform the identifier value based on type\n *\n * @param identifierValue - Value of identifier\n * @param identifierType - Type of identifier\n * @param defaultPhoneCountryCode - Default country code for phone numbers\n * @returns Post-processed identifier\n */\nexport function normalizeIdentifierValue(\n identifierValue: string,\n identifierType: IdentifierType,\n defaultPhoneCountryCode: string,\n): string {\n // Lowercase email\n if (identifierType === IdentifierType.Email) {\n return identifierValue.toLowerCase();\n }\n\n // Normalize phone number\n if (identifierType === IdentifierType.Phone) {\n const normalized = identifierValue\n .replace(NORMALIZE_PHONE_NUMBER, '')\n .replace(/[()]/g, '')\n .replace(/[–]/g, '')\n .replace(/[:]/g, '')\n .replace(/[‭‬]/g, '')\n .replace(/[A-Za-z]/g, '');\n return !normalized\n ? ''\n : normalized.startsWith('+')\n ? normalized\n : `+${defaultPhoneCountryCode}${normalized}`;\n }\n return identifierValue;\n}\n\n/**\n * Take the raw rows in a CSV upload, and map those rows to the request\n * input shape that can be passed to the Transcend API to submit a privacy\n * request.\n *\n * @param requestInputs - CSV of requests to be uploaded\n * @param state - The cached set of mapping values\n * @param options - Options\n * @returns [raw input, request input] list\n */\nexport function mapCsvRowsToRequestInputs(\n requestInputs: ObjByString[],\n state: PersistedState<typeof CachedFileState>,\n {\n columnNameMap,\n identifierNameMap,\n attributeNameMap,\n requestAttributeKeys,\n defaultPhoneCountryCode = '1', // US\n }: {\n /** Default country code */\n defaultPhoneCountryCode?: string;\n /** Mapping of column names */\n columnNameMap: ColumnNameMap;\n /** Mapping of identifier names */\n identifierNameMap: IdentifierNameMap;\n /** Mapping of attribute names */\n attributeNameMap: AttributeNameMap;\n /** Request attribute keys */\n requestAttributeKeys: AttributeKey[];\n },\n): [Record<string, string>, PrivacyRequestInput][] {\n // map the CSV to request input\n const getMappedName = (attribute: ColumnName): string =>\n state.getValue('columnNames', attribute) || columnNameMap[attribute]!;\n return requestInputs.map((input): [Record<string, string>, PrivacyRequestInput] => {\n // The extra identifiers to upload for this request\n const attestedExtraIdentifiers: AttestedExtraIdentifiers = {};\n Object.entries(identifierNameMap)\n // filter out skipped identifiers\n .filter(([, columnName]) => columnName !== NONE)\n .forEach(([identifierName, columnName]) => {\n // Determine the identifier type being specified\n const identifierType = Object.values(IdentifierType).includes(\n identifierName as any, // eslint-disable-line @typescript-eslint/no-explicit-any\n )\n ? (identifierName as IdentifierType)\n : IdentifierType.Custom;\n\n // Only add the identifier if the value exists\n const identifierValue = input[columnName];\n if (identifierValue) {\n const normalized = normalizeIdentifierValue(\n identifierValue,\n identifierType,\n defaultPhoneCountryCode,\n );\n if (normalized) {\n // Initialize\n if (!attestedExtraIdentifiers[identifierType]) {\n attestedExtraIdentifiers[identifierType] = [];\n }\n\n // Add the identifier\n attestedExtraIdentifiers[identifierType]!.push({\n value: normalized,\n name: identifierName,\n });\n }\n }\n });\n\n // The extra attributes to upload for this request\n const attributes: ParsedAttributeInput[] = [];\n Object.entries(attributeNameMap)\n // filter out skipped attributes\n .filter(([, columnName]) => columnName !== NONE)\n .forEach(([attributeName, columnName]) => {\n // Only add the identifier if the value exists\n const attributeValueString = input[columnName];\n if (attributeValueString) {\n // Add the attribute\n const isMulti =\n requestAttributeKeys.find((attr) => attr.name === attributeName)?.type ===\n 'MULTI_SELECT';\n attributes.push({\n values: isMulti ? splitCsvToList(attributeValueString) : attributeValueString,\n key: attributeName,\n });\n }\n });\n\n const requestTypeColumn = getMappedName(ColumnName.RequestType);\n const dataSubjectTypeColumn = getMappedName(ColumnName.SubjectType);\n return [\n input,\n {\n email: input[getMappedName(ColumnName.Email)],\n attestedExtraIdentifiers,\n attributes,\n coreIdentifier: input[getMappedName(ColumnName.CoreIdentifier)],\n requestType:\n requestTypeColumn === BULK_APPLY\n ? state.getValue('requestTypeToRequestAction', BLANK)\n : state.getValue('requestTypeToRequestAction', input[requestTypeColumn]),\n subjectType:\n dataSubjectTypeColumn === BULK_APPLY\n ? state.getValue('subjectTypeToSubjectName', BLANK)\n : state.getValue('subjectTypeToSubjectName', input[dataSubjectTypeColumn]),\n ...(getMappedName(ColumnName.Locale) !== NONE && input[getMappedName(ColumnName.Locale)]\n ? {\n locale: state.getValue('languageToLocale', input[getMappedName(ColumnName.Locale)]),\n }\n : {}),\n ...(getMappedName(ColumnName.Country) !== NONE && input[getMappedName(ColumnName.Country)]\n ? {\n country: state.getValue(\n 'regionToCountry',\n input[getMappedName(ColumnName.Country)],\n ) as IsoCountryCode,\n }\n : {}),\n ...(getMappedName(ColumnName.CountrySubDivision) !== NONE &&\n input[getMappedName(ColumnName.CountrySubDivision)]\n ? {\n countrySubDivision: state.getValue(\n 'regionToCountrySubDivision',\n input[getMappedName(ColumnName.CountrySubDivision)],\n ) as IsoCountrySubdivisionCode,\n }\n : {}),\n ...(getMappedName(ColumnName.RequestStatus) !== NONE &&\n state.getValue('statusToRequestStatus', input[getMappedName(ColumnName.RequestStatus)]) !==\n NONE &&\n input[getMappedName(ColumnName.RequestStatus)]\n ? {\n status: state.getValue(\n 'statusToRequestStatus',\n input[getMappedName(ColumnName.RequestStatus)],\n ) as CompletedRequestStatus,\n }\n : {}),\n ...(getMappedName(ColumnName.CreatedAt) !== NONE &&\n input[getMappedName(ColumnName.CreatedAt)]\n ? {\n createdAt: new Date(input[getMappedName(ColumnName.CreatedAt)]),\n }\n : {}),\n ...(getMappedName(ColumnName.DataSiloIds) !== NONE &&\n input[getMappedName(ColumnName.DataSiloIds)]\n ? {\n dataSiloIds: splitCsvToList(input[getMappedName(ColumnName.DataSiloIds)]),\n }\n : {}),\n },\n ];\n });\n}\n","import type { PersistedState } from '@transcend-io/persisted-state';\nimport { INITIALIZER, type Initializer, makeGraphQLRequest } from '@transcend-io/sdk';\nimport type { GraphQLClient } from 'graphql-request';\nimport inquirer from 'inquirer';\n\nimport { logger } from '../../logger.js';\nimport { CachedFileState, IDENTIFIER_BLOCK_LIST } from './constants.js';\nimport { fuzzyMatchColumns } from './fuzzyMatchColumns.js';\n\n/**\n * Mapping from identifier name to request input parameter\n */\nexport type IdentifierNameMap = {\n [k in string]: string;\n};\n\n/**\n * Create a mapping from the identifier names that can be included\n * at request submission, to the names of the columns that map to those\n * identifiers.\n *\n * @param client - GraphQL client\n * @param columnNames - The set of all column names\n * @param state - Cached state of this mapping\n * @returns Mapping from identifier name to column name\n */\nexport async function mapColumnsToIdentifiers(\n client: GraphQLClient,\n columnNames: string[],\n state: PersistedState<typeof CachedFileState>,\n): Promise<IdentifierNameMap> {\n // Grab the initializer\n const { initializer } = await makeGraphQLRequest<{\n /** Query response */\n initializer: Initializer;\n }>(client, INITIALIZER, { logger });\n\n // Determine the columns that should be mapped\n const columnQuestions = initializer.identifiers.filter(\n ({ name }) => !state.getValue('identifierNames', name) && !IDENTIFIER_BLOCK_LIST.includes(name),\n );\n\n // Skip mapping when everything is mapped\n const identifierNameMap =\n columnQuestions.length === 0\n ? {}\n : // prompt questions to map columns\n await inquirer.prompt<{\n [k in string]: string;\n }>(\n columnQuestions.map(({ name }) => {\n const matches = fuzzyMatchColumns(columnNames, name, false);\n return {\n name,\n message: `Choose the column that will be used to map in the identifier: ${name}`,\n type: 'list',\n default: matches[0],\n choices: matches,\n };\n }),\n );\n await Promise.all(\n Object.entries(identifierNameMap).map(([k, v]) => state.setValue(v, 'identifierNames', k)),\n );\n\n return {\n ...state.getValue('identifierNames'),\n ...identifierNameMap,\n };\n}\n","import type { PersistedState } from '@transcend-io/persisted-state';\nimport type { AttributeKey } from '@transcend-io/sdk';\nimport type { GraphQLClient } from 'graphql-request';\nimport inquirer from 'inquirer';\n\nimport { CachedFileState } from './constants.js';\nimport { fuzzyMatchColumns } from './fuzzyMatchColumns.js';\n\n/**\n * Mapping from attribute name to request input parameter\n */\nexport type AttributeNameMap = {\n [k in string]: string;\n};\n\n/**\n * Create a mapping from the attributes names that can be included\n * at request submission, to the names of the columns that map to those\n * attributes.\n *\n * @param client - GraphQL client\n * @param columnNames - The set of all column names\n * @param state - Cached state of this mapping\n * @param requestAttributeKeys - Attribute keys to map\n * @returns Mapping from attributes name to column name\n */\nexport async function mapColumnsToAttributes(\n client: GraphQLClient,\n columnNames: string[],\n state: PersistedState<typeof CachedFileState>,\n requestAttributeKeys: AttributeKey[],\n): Promise<AttributeNameMap> {\n // Determine the columns that should be mapped\n const columnQuestions = requestAttributeKeys.filter(\n ({ name }) => !state.getValue('attributeNames', name),\n );\n\n // Skip mapping when everything is mapped\n const attributeNameMap =\n columnQuestions.length === 0\n ? {}\n : // prompt questions to map columns\n await inquirer.prompt<{\n [k in string]: string;\n }>(\n columnQuestions.map(({ name }) => {\n const matches = fuzzyMatchColumns(columnNames, name, false);\n return {\n name,\n message: `Choose the column that will be used to map in the attribute: ${name}`,\n type: 'list',\n default: matches[0],\n choices: matches,\n };\n }),\n );\n await Promise.all(\n Object.entries(attributeNameMap).map(([k, v]) => state.setValue(v, 'attributeNames', k)),\n );\n\n return {\n ...state.getValue('attributeNames'),\n ...attributeNameMap,\n };\n}\n","import { join } from 'node:path';\n\nimport { PersistedState } from '@transcend-io/persisted-state';\nimport {\n buildTranscendGraphQLClient,\n createSombraGotInstance,\n fetchAllRequestAttributeKeys,\n} from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport cliProgress from 'cli-progress';\n/* eslint-disable max-lines */\nimport colors from 'colors';\nimport * as t from 'io-ts';\nimport { uniq } from 'lodash-es';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\nimport { CachedRequestState, CachedFileState } from './constants.js';\nimport { extractClientError } from './extractClientError.js';\nimport { filterRows } from './filterRows.js';\nimport { mapColumnsToAttributes } from './mapColumnsToAttributes.js';\nimport { mapColumnsToIdentifiers } from './mapColumnsToIdentifiers.js';\nimport { mapCsvColumnsToApi } from './mapCsvColumnsToApi.js';\nimport { mapCsvRowsToRequestInputs } from './mapCsvRowsToRequestInputs.js';\nimport { mapRequestEnumValues } from './mapRequestEnumValues.js';\nimport { parseAttributesFromString } from './parseAttributesFromString.js';\nimport { readCsv } from './readCsv.js';\nimport { submitPrivacyRequest } from './submitPrivacyRequest.js';\n\n/**\n * Upload a set of privacy requests from CSV\n *\n * @param options - Options\n */\nexport async function uploadPrivacyRequestsFromCsv({\n cacheFilepath,\n requestReceiptFolder,\n file,\n auth,\n sombraAuth,\n concurrency = 100,\n defaultPhoneCountryCode = '1', // USA\n transcendUrl = DEFAULT_TRANSCEND_API,\n attributes = [],\n emailIsVerified = true,\n skipFilterStep = false,\n skipSendingReceipt = true,\n isTest = false,\n isSilent = true,\n debug = false,\n dryRun = false,\n}: {\n /** File to cache metadata about mapping of CSV shape to script */\n cacheFilepath: string;\n /** File where request receipts are stored */\n requestReceiptFolder: string;\n /** CSV file path */\n file: string;\n /** Transcend API key authentication */\n auth: string;\n /** Default country code for phone numbers */\n defaultPhoneCountryCode?: string;\n /** Concurrency to upload in */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** Include debug logs */\n debug?: boolean;\n /** Skip the step where requests are filtered */\n skipFilterStep?: boolean;\n /** Whether test requests are being uploaded */\n isTest?: boolean;\n /** Whether requests are uploaded in silent mode */\n isSilent?: boolean;\n /** Whether to send the email receipt */\n skipSendingReceipt?: boolean;\n /** Whether the email was verified up front */\n emailIsVerified?: boolean;\n /** Attributes string pre-parse */\n attributes?: string[];\n /** Whether a dry run is happening */\n dryRun?: boolean;\n}): Promise<void> {\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 // Parse out the extra attributes to apply to all requests uploaded\n const parsedAttributes = parseAttributesFromString(attributes);\n\n // Create a new state to persist the metadata that\n // maps the request inputs to the Transcend API shape\n const state = new PersistedState(cacheFilepath, CachedFileState, {\n columnNames: {},\n requestTypeToRequestAction: {},\n subjectTypeToSubjectName: {},\n languageToLocale: {},\n statusToRequestStatus: {},\n identifierNames: {},\n attributeNames: {},\n regionToCountrySubDivision: {},\n regionToCountry: {},\n });\n\n // Create a new state file to store the requests from this run.\n // `toISOString()` contains colons (e.g. 2026-07-06T04:33:12.345Z) which are\n // illegal characters in Windows filenames, so strip them out to keep the\n // auto-generated receipt filename cross-platform.\n const requestCacheFile = join(\n requestReceiptFolder,\n `tr-request-upload-${new Date()\n .toISOString()\n .replace(/:/g, '-')}-${file.split('/').pop()}`.replace('.csv', '.json'),\n );\n const requestState = new PersistedState(requestCacheFile, CachedRequestState, {\n successfulRequests: [],\n duplicateRequests: [],\n failingRequests: [],\n });\n\n // Create sombra instance to communicate with\n const sombra = await createSombraGotInstance(transcendUrl, auth, {\n logger,\n sombraApiKey: sombraAuth,\n sombraUrl: process.env.SOMBRA_URL,\n });\n\n // Read in the list of integration requests\n const requestsList = readCsv(file, t.record(t.string, t.string));\n const columnNames = uniq(requestsList.map((x) => Object.keys(x)).flat());\n\n // Log out an example request\n if (requestsList.length === 0) {\n throw new Error(\n 'No Requests found in list! Ensure the first row of the CSV is a header and the rest are requests.',\n );\n }\n if (debug) {\n const firstRequest = requestsList[0];\n logger.info(colors.magenta(`First request: ${JSON.stringify(firstRequest, null, 2)}`));\n }\n // Determine what rows in the CSV should be imported\n // Choose columns that contain metadata to filter the requests\n const filteredRequestList = skipFilterStep ? requestsList : await filterRows(requestsList);\n\n // Build a GraphQL client\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n // Grab the request attributes\n const requestAttributeKeys = await fetchAllRequestAttributeKeys(client, { logger });\n // Determine the columns that should be mapped\n const columnNameMap = await mapCsvColumnsToApi(columnNames, state);\n const identifierNameMap = await mapColumnsToIdentifiers(client, columnNames, state);\n const attributeNameMap = await mapColumnsToAttributes(\n client,\n columnNames,\n state,\n requestAttributeKeys,\n );\n await mapRequestEnumValues(client, filteredRequestList, {\n state,\n columnNameMap,\n });\n\n // map the CSV to request input\n const requestInputs = mapCsvRowsToRequestInputs(filteredRequestList, state, {\n defaultPhoneCountryCode,\n columnNameMap,\n identifierNameMap,\n attributeNameMap,\n requestAttributeKeys,\n });\n\n // start the progress bar with a total value of 200 and start value of 0\n if (!debug) {\n progressBar.start(requestInputs.length, 0);\n }\n let total = 0;\n // Submit each request\n await map(\n requestInputs,\n async ([rawRow, requestInput], ind) => {\n // The identifier to log, only include personal data if debug mode is on\n const requestLogId = debug\n ? `email:${requestInput.email} | coreIdentifier:${requestInput.coreIdentifier}`\n : `row:${ind.toString()}`;\n\n if (debug) {\n logger.info(\n colors.magenta(\n `[${ind + 1}/${requestInputs.length}] Importing: ${JSON.stringify(\n requestInput,\n null,\n 2,\n )}`,\n ),\n );\n }\n\n // Skip on dry run\n if (dryRun) {\n logger.info(colors.magenta('Bailing out on dry run because dryRun is set'));\n return;\n }\n\n try {\n // Make the GraphQL request to submit the privacy request\n const requestResponse = await submitPrivacyRequest(sombra, requestInput, {\n details: `Uploaded by Transcend Cli: \"tr-request-upload\" : ${JSON.stringify(\n rawRow,\n null,\n 2,\n )}`,\n isTest,\n emailIsVerified,\n skipSendingReceipt,\n isSilent,\n additionalAttributes: parsedAttributes,\n });\n\n // Log success\n if (debug) {\n logger.info(\n colors.green(\n `[${ind + 1}/${\n requestInputs.length\n }] Successfully submitted the test data subject request: \"${requestLogId}\"`,\n ),\n );\n logger.info(\n colors.green(\n `[${ind + 1}/${requestInputs.length}] View it at: \"${requestResponse.link}\"`,\n ),\n );\n }\n\n // Cache successful upload\n const successfulRequests = requestState.getValue('successfulRequests');\n successfulRequests.push({\n id: requestResponse.id,\n link: requestResponse.link,\n rowIndex: ind,\n coreIdentifier: requestResponse.coreIdentifier,\n attemptedAt: new Date().toISOString(),\n });\n await requestState.setValue(successfulRequests, 'successfulRequests');\n } catch (err) {\n const msg = `${err.message} - ${JSON.stringify(err.response?.body, null, 2)}`;\n const clientError = extractClientError(msg);\n\n if (clientError === 'Client error: You have already made this request.') {\n if (debug) {\n logger.info(\n colors.yellow(\n `[${ind + 1}/${requestInputs.length}] Skipping request as it is a duplicate`,\n ),\n );\n }\n const duplicateRequests = requestState.getValue('duplicateRequests');\n duplicateRequests.push({\n coreIdentifier: requestInput.coreIdentifier,\n rowIndex: ind,\n attemptedAt: new Date().toISOString(),\n });\n await requestState.setValue(duplicateRequests, 'duplicateRequests');\n } else {\n const failingRequests = requestState.getValue('failingRequests');\n failingRequests.push({\n ...requestInput,\n rowIndex: ind,\n error: clientError || msg,\n attemptedAt: new Date().toISOString(),\n });\n await requestState.setValue(failingRequests, 'failingRequests');\n if (debug) {\n logger.error(colors.red(clientError || msg));\n logger.error(\n colors.red(\n `[${ind + 1}/${\n requestInputs.length\n }] Failed to submit request for: \"${requestLogId}\"`,\n ),\n );\n }\n }\n }\n\n total += 1;\n if (!debug) {\n progressBar.update(total);\n }\n },\n {\n concurrency,\n },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n // Log completion time\n logger.info(colors.green(`Completed upload in \"${totalTime / 1000}\" seconds.`));\n\n // Log duplicates\n if (requestState.getValue('duplicateRequests').length > 0) {\n logger.info(\n colors.yellow(\n `Encountered \"${requestState.getValue('duplicateRequests').length}\" duplicate requests. ` +\n `See \"${requestCacheFile}\" to review the core identifiers for these requests.`,\n ),\n );\n }\n\n // Log errors\n if (requestState.getValue('failingRequests').length > 0) {\n logger.error(\n colors.red(\n `Encountered \"${requestState.getValue('failingRequests').length}\" errors. ` +\n `See \"${requestCacheFile}\" to review the error messages and inputs.`,\n ),\n );\n process.exit(1);\n }\n}\n/* eslint-enable max-lines */\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{t as e}from"./logger-D1tXVwJj.mjs";import{mt as t}from"./codecs-DW8SY77H.mjs";import{decodeCodec as n}from"@transcend-io/type-utils";import{existsSync as r,readFileSync as i}from"node:fs";import a from"colors";import*as o from"io-ts";function s(s){return s||(e.error(a.red(`A Transcend API key must be provided. You can specify using --auth=$TRANSCEND_API_KEY`)),process.exit(1)),r(s)?n(o.array(t),i(s,`utf-8`)):s}export{s as t};
2
- //# sourceMappingURL=validateTranscendAuth-CToEUu1U.mjs.map
1
+ import{t as e}from"./logger-D1tXVwJj.mjs";import{mt as t}from"./codecs-CwRYEdQK.mjs";import{decodeCodec as n}from"@transcend-io/type-utils";import{existsSync as r,readFileSync as i}from"node:fs";import a from"colors";import*as o from"io-ts";function s(s){return s||(e.error(a.red(`A Transcend API key must be provided. You can specify using --auth=$TRANSCEND_API_KEY`)),process.exit(1)),r(s)?n(o.array(t),i(s,`utf-8`)):s}export{s as t};
2
+ //# sourceMappingURL=validateTranscendAuth-DrVM-Bxh.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"validateTranscendAuth-CToEUu1U.mjs","names":[],"sources":["../src/lib/api-keys/validateTranscendAuth.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\n\nimport { decodeCodec } from '@transcend-io/type-utils';\nimport colors from 'colors';\nimport * as t from 'io-ts';\n\nimport { StoredApiKey } from '../../codecs.js';\nimport { logger } from '../../logger.js';\n\n/**\n * Determine if the `--auth` parameter is an API key or a path to a JSON\n * file containing a list of API keys.\n *\n * @param auth - Raw auth parameter\n * @returns The API key or the list API keys\n */\nexport function validateTranscendAuth(auth: string): string | StoredApiKey[] {\n // Ensure auth is passed\n if (!auth) {\n logger.error(\n colors.red(\n 'A Transcend API key must be provided. You can specify using --auth=$TRANSCEND_API_KEY',\n ),\n );\n process.exit(1);\n }\n\n // Read from disk\n if (existsSync(auth)) {\n // validate that file is a list of API keys\n return decodeCodec(t.array(StoredApiKey), readFileSync(auth, 'utf-8'));\n }\n\n // Return as single API key\n return auth;\n}\n"],"mappings":"iPAgBA,SAAgB,EAAsB,EAAuC,CAkB3E,OAhBK,IACH,EAAO,MACL,EAAO,IACL,wFACD,CACF,CACD,QAAQ,KAAK,EAAE,EAIb,EAAW,EAAK,CAEX,EAAY,EAAE,MAAM,EAAa,CAAE,EAAa,EAAM,QAAQ,CAAC,CAIjE"}
1
+ {"version":3,"file":"validateTranscendAuth-DrVM-Bxh.mjs","names":[],"sources":["../src/lib/api-keys/validateTranscendAuth.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\n\nimport { decodeCodec } from '@transcend-io/type-utils';\nimport colors from 'colors';\nimport * as t from 'io-ts';\n\nimport { StoredApiKey } from '../../codecs.js';\nimport { logger } from '../../logger.js';\n\n/**\n * Determine if the `--auth` parameter is an API key or a path to a JSON\n * file containing a list of API keys.\n *\n * @param auth - Raw auth parameter\n * @returns The API key or the list API keys\n */\nexport function validateTranscendAuth(auth: string): string | StoredApiKey[] {\n // Ensure auth is passed\n if (!auth) {\n logger.error(\n colors.red(\n 'A Transcend API key must be provided. You can specify using --auth=$TRANSCEND_API_KEY',\n ),\n );\n process.exit(1);\n }\n\n // Read from disk\n if (existsSync(auth)) {\n // validate that file is a list of API keys\n return decodeCodec(t.array(StoredApiKey), readFileSync(auth, 'utf-8'));\n }\n\n // Return as single API key\n return auth;\n}\n"],"mappings":"iPAgBA,SAAgB,EAAsB,EAAuC,CAkB3E,OAhBK,IACH,EAAO,MACL,EAAO,IACL,wFACD,CACF,CACD,QAAQ,KAAK,EAAE,EAIb,EAAW,EAAK,CAEX,EAAY,EAAE,MAAM,EAAa,CAAE,EAAa,EAAM,QAAQ,CAAC,CAIjE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@transcend-io/cli",
3
- "version": "10.16.0",
3
+ "version": "10.17.1",
4
4
  "description": "A command line interface for programmatic operations across Transcend.",
5
5
  "homepage": "https://github.com/transcend-io/tools/tree/main/packages/cli",
6
6
  "license": "Apache-2.0",
@@ -105,10 +105,10 @@
105
105
  "yargs-parser": "^21.1.1",
106
106
  "@transcend-io/airgap.js-types": "14.2.13",
107
107
  "@transcend-io/internationalization": "4.1.1",
108
+ "@transcend-io/sdk": "1.3.0",
108
109
  "@transcend-io/privacy-types": "5.4.0",
109
- "@transcend-io/sdk": "1.2.11",
110
110
  "@transcend-io/type-utils": "3.0.1",
111
- "@transcend-io/utils": "0.1.3"
111
+ "@transcend-io/utils": "0.2.0"
112
112
  },
113
113
  "devDependencies": {
114
114
  "@arethetypeswrong/cli": "^0.18.2",
@@ -1,2 +0,0 @@
1
- import{a as e,i as t}from"./enums-CyFTrzXY.mjs";import{ActionItemCode as ee,ActionItemPriorityOverride as te,AssessmentFormStatus as ne,AssessmentFormTemplateSource as re,AssessmentFormTemplateStatus as ie,AssessmentQuestionSubType as ae,AssessmentQuestionType as oe,AssessmentSyncColumn as se,AssessmentSyncModel as ce,AssessmentsDisplayLogicAction as le,AttributeKeyType as ue,AttributeSupportedResourceType as n,BrowserTimeZone as de,CodePackageType as r,ComparisonOperator as i,ConfigurableColorPaletteColor as fe,ConsentBundleType as pe,ConsentPrecedenceOption as me,ConsentThemeInput as he,ConsentTrackerStatus as a,ConsentVariantInput as ge,Controllership as _e,DataCategoryType as o,DataFlowScope as s,DataProtectionImpactAssessmentStatus as ve,DefaultConsentOption as ye,EnricherType as be,IsoCountryCode as c,IsoCountrySubdivisionCode as l,LargeLanguageModelClient as xe,LogicOperator as Se,PreferenceStoreAuthLevel as Ce,PreferenceTopicType as we,PreflightRequestStatus as Te,PrivacyCenterComponentStyles as Ee,PrivacyCenterTextStyles as De,ProcessingPurpose as u,PromptAVendorEmailCompletionLinkType as Oe,PromptAVendorEmailSendType as ke,PromptFilePurpose as Ae,RegionDetectionMethod as je,RegionsOperator as Me,RequestAction as d,RequestActionObjectResolver as f,RetentionScheduleOperation as Ne,RetentionScheduleType as Pe,RetentionType as Fe,ScopeName as Ie,SignedIabAgreementOption as Le,SubDataPointDataSubCategoryGuessStatus as Re,TelemetryPartitionStrategy as ze,TranscendProduct as Be,UnknownRequestPolicy as p,UnstructuredSubDataPointRecommendationStatus as Ve}from"@transcend-io/privacy-types";import{applyEnum as m,valuesOf as h}from"@transcend-io/type-utils";import{BrowserLanguage as He,InitialViewState as Ue,OnConsentExpiry as We,UserPrivacySignalEnum as Ge}from"@transcend-io/airgap.js-types";import{LOCALE_KEY as g}from"@transcend-io/internationalization";import*as _ from"io-ts";const v=({TEnabledRoutes:e})=>_.type({enabledRoutes:e}),y=({TRouteName:t})=>_.type({routeName:t,enabledPolicies:_.array(h(e))}),b=_.type({title:_.string}),x=_.intersection([_.type({name:_.string,value:_.string}),_.partial({isSecret:_.boolean})]),S=_.type({title:_.string}),C=_.intersection([_.type({name:_.string,description:_.string}),_.partial({"sso-department":_.string,"sso-group":_.string,"sso-title":_.string,"parent-team-name":_.string,users:_.array(_.string),scopes:_.array(h(Ie))})]),w=_.intersection([_.type({title:_.string,"output-identifiers":_.array(_.string)}),_.partial({description:_.string,url:_.string,type:h(be),"input-identifier":_.string,testRegex:_.string,lookerQueryTitle:_.string,expirationDuration:_.number,transitionRequestStatus:h(Te),phoneNumbers:_.array(_.string),regionList:_.array(h({...c,...l})),"data-subjects":_.array(_.string),headers:_.array(x),"privacy-actions":_.array(h(d))})]),T=_.intersection([_.type({purpose:h(u)}),_.partial({name:_.string})]),E=_.intersection([_.type({category:h(o)}),_.partial({name:_.string})]),D=_.intersection([_.type({category:E,status:h(Re),confidence:_.number}),_.partial({classifierVersion:_.number})]),Ke=_.intersection([_.type({category:E,status:h(Ve),confidence:_.number}),_.partial({classifierVersion:_.number})]),O=_.intersection([_.type({name:_.string}),_.partial({description:_.string,color:_.string})]),k=_.intersection([_.type({name:_.string,type:h(ue)}),_.partial({description:_.string,resources:_.array(h(n)),values:_.array(O)})]),A=_.type({key:_.string,values:_.array(_.string)}),j=_.intersection([_.type({name:_.string,instructions:_.string,agentId:_.string,codeInterpreterEnabled:_.boolean,retrievalEnabled:_.boolean,"large-language-model":_.type({name:_.string,client:h(xe)})}),_.partial({description:_.string,prompt:_.string,owners:_.array(_.string),teams:_.array(_.string),"agent-functions":_.array(_.string),"agent-files":_.array(_.string)})]),M=_.type({name:_.string,description:_.string,parameters:_.string}),N=_.intersection([_.type({name:_.string,fileId:_.string,size:_.number,purpose:h(Ae)}),_.partial({description:_.string})]),P=_.intersection([_.type({title:_.string}),_.partial({description:_.string,dataProcessingAgreementLink:_.string,contactName:_.string,contactPhone:_.string,address:_.string,headquarterCountry:h(c),headquarterSubDivision:h(l),websiteUrl:_.string,businessEntity:_.string,owners:_.array(_.string),teams:_.array(_.string),attributes:_.array(A)})]),F=_.intersection([_.type({name:_.string,category:h(o)}),_.partial({description:_.string,regex:_.string,owners:_.array(_.string),teams:_.array(_.string),attributes:_.array(A)})]),I=_.intersection([_.type({name:_.string,purpose:h(u)}),_.partial({description:_.string,owners:_.array(_.string),teams:_.array(_.string),attributes:_.array(A)})]),L=_.type({title:_.string,content:_.string}),qe=_.type({title:_.string,content:_.string}),R=_.type({title:_.string,description:_.string,prompts:_.array(_.string)}),z=_.intersection([_.type({key:_.string}),_.partial({title:_.string,description:_.union([_.string,_.null]),purposes:_.array(T),categories:_.array(E),"guessed-categories":_.array(D),"access-request-visibility-enabled":_.boolean,"erasure-request-redaction-enabled":_.boolean,attributes:_.array(A)})]),B=_.intersection([_.type({key:_.string}),_.partial({path:_.array(_.string),title:_.string,description:_.string,"data-collection-tag":_.string,"privacy-action-queries":_.partial(m(f,()=>_.string)),"privacy-actions":_.array(h(f)),fields:_.array(z),owners:_.array(_.string),teams:_.array(_.string)})]),V=_.partial({"notify-email-address":_.string,"send-frequency":_.number,"send-type":h(ke),"include-identifiers-attachment":_.boolean,"completion-link-type":h(Oe),"manual-work-retry-frequency":_.string}),H=_.intersection([_.type({title:_.string}),_.partial({description:_.string,address:_.string,headquarterCountry:h(c),headquarterSubDivision:h(l),dataProtectionOfficerName:_.string,dataProtectionOfficerEmail:_.string,attributes:_.array(A),owners:_.array(_.string),teams:_.array(_.string)})]),U=_.partial({country:h(c),countrySubDivision:h(l)}),W=_.intersection([_.type({title:_.string}),_.partial({description:_.string,securityMeasureDetails:_.string,controllerships:_.array(h(_e)),storageRegions:_.array(U),transferRegions:_.array(U),retentionType:h(Fe),retentionPeriod:_.number,dataProtectionImpactAssessmentLink:_.string,dataProtectionImpactAssessmentStatus:h(ve),attributes:_.array(A),dataSiloTitles:_.array(_.string),dataSubjectTypes:_.array(_.string),teamNames:_.array(_.string),ownerEmails:_.array(_.string),processingSubPurposes:_.array(T),dataSubCategories:_.array(E),saaSCategories:_.array(_.string)})]),Je=_.intersection([_.type({name:_.string,codePackageType:h(r)}),_.partial({description:_.string,repositoryUrl:_.string,catalogIntegrationName:_.string,documentationLinks:_.array(_.string),ownerEmails:_.array(_.string),teamNames:_.array(_.string)})]),G=_.intersection([_.type({name:_.string}),_.partial({version:_.string,isDevDependency:_.boolean})]),Ye=_.intersection([_.type({name:_.string,type:h(r),relativePath:_.string,repositoryName:_.string}),_.partial({description:_.string,softwareDevelopmentKits:_.array(G),teamNames:_.array(_.string),ownerEmails:_.array(_.string)})]),Xe=_.intersection([_.type({name:_.string,url:_.string}),_.partial({description:_.string,teamNames:_.array(_.string),ownerEmails:_.array(_.string)})]),K=_.intersection([_.type({type:_.string}),_.partial({active:_.boolean,title:_.string,adminDashboardDefaultSilentMode:_.boolean,actions:_.array(h(d))})]),q=_.intersection([_.type({type:h(d)}),_.partial({skipSecondaryIfNoFiles:_.boolean,skipDownloadableStep:_.boolean,requiresReview:_.boolean,waitingPeriod:_.number,regionDetectionMethod:h(je),regionList:_.array(h({...c,...l})),regionBlockList:_.array(h({...c,...l}))})]),J=_.intersection([_.type({name:_.string,type:_.string}),_.partial({regex:_.string,selectOptions:_.array(_.string),privacyCenterVisibility:_.array(h(d)),dataSubjects:_.array(_.string),isRequiredInForm:_.boolean,placeholder:_.string,displayTitle:_.string,displayDescription:_.string,displayOrder:_.number,isUniqueOnPreferenceStore:_.boolean})]),Ze=_.intersection([_.type({value:_.string,type:h(s)}),_.partial({description:_.string,trackingPurposes:_.array(_.string),service:_.string,status:h(a),owners:_.array(_.string),teams:_.array(_.string),attributes:_.array(A)})]),Qe=_.intersection([_.type({name:_.string}),_.partial({isRegex:_.boolean,description:_.string,trackingPurposes:_.array(_.string),service:_.string,status:h(a),owners:_.array(_.string),teams:_.array(_.string),attributes:_.array(A)})]),$e=_.intersection([_.type({name:_.string}),_.partial({displayName:_.string,regions:_.array(U),onConsentExpiry:h(We),consentExpiry:_.number,operator:h(Me),displayPriority:_.number,viewState:h(Ue),purposes:_.array(_.type({trackingType:_.string})),optedOutPurposes:_.array(_.type({trackingType:_.string})),browserLanguages:_.array(h(He)),browserTimeZones:_.array(h(de)),consentUiVariantSlug:_.string})]),et=_.intersection([_.type({name:_.string}),_.partial({partition:_.string})]),tt=_.partial({version:_.string,bundleUrls:_.record(h(pe),_.string),domains:_.array(_.string),partition:_.string,consentPrecedence:h(me),unknownRequestPolicy:h(p),unknownCookiePolicy:h(p),syncEndpoint:_.string,telemetryPartitioning:h(ze),signedIabAgreement:h(Le),experiences:_.array($e),theme:_.partial({primaryColor:_.string,fontColor:_.string,privacyPolicy:_.string,prompt:_.number}),syncGroups:_.string,consentVariants:_.array(ge),consentThemes:_.array(he)}),nt=_.partial({isDisabled:_.boolean,showPrivacyRequestButton:_.boolean,showDataPractices:_.boolean,showPolicies:_.boolean,showTrackingTechnologies:_.boolean,showCookies:_.boolean,showDataFlows:_.boolean,showConsentManager:_.boolean,showManageYourPrivacy:_.boolean,showMarketingPreferences:_.boolean,locales:_.array(h(g)),defaultLocale:h(g),preferBrowserDefaultLocale:_.boolean,supportEmail:_.string,replyToEmail:_.string,useNoReplyEmailAddress:_.boolean,useCustomEmailDomain:_.boolean,transformAccessReportJsonToCsv:_.boolean,theme:_.partial({colors:_.partial(m(fe,()=>_.string)),componentStyles:Ee,textStyles:De})}),rt=_.intersection([_.type({title:_.string}),_.partial({effectiveOn:_.string,disableEffectiveOn:_.boolean,content:_.string,disabledLocales:_.array(h(g))})]),it=_.intersection([_.type({id:_.string}),_.partial({targetReactIntlId:_.string,description:_.string,defaultMessage:_.string,translations:_.partial(m(g,()=>_.string))})]),at=_.intersection([_.type({title:_.string,integrationName:_.string}),_.partial({"outer-type":_.string,description:_.string,url:_.string,"api-key-title":_.string,headers:_.array(x),"data-subjects":_.array(_.string),"identity-keys":_.array(_.string),"deletion-dependencies":_.array(_.string),owners:_.array(_.string),teams:_.array(_.string),disabled:_.boolean,datapoints:_.array(B),"email-settings":V,country:h(c),countrySubDivision:h(l),attributes:_.array(A),businessEntityTitles:_.array(_.string)})]),ot=_.intersection([_.type({title:_.string,productLine:h(Be)}),_.partial({description:_.string,hidden:_.boolean})]),st=_.intersection([_.type({title:_.string,type:h(ee),collections:_.array(_.string)}),_.partial({priority:h(te),customerExperienceActionItemId:_.string,dueDate:_.string,resolved:_.boolean,notes:_.string,link:_.string,users:_.array(_.string),teams:_.array(_.string),attributes:_.array(A)})]),Y=_.intersection([_.type({"depends-on-question-reference-id":_.string,"comparison-operator":h(i)}),_.partial({"comparison-operands":_.array(_.string)})]),ct=_.recursion(`AssessmentNestedRuleInput`,e=>_.intersection([_.type({"logic-operator":h(Se)}),_.partial({rules:_.array(Y),"nested-rules":_.array(e)})])),lt=_.intersection([_.type({action:h(le)}),_.partial({rule:Y,"nested-rule":ct})]),ut=_.partial({"risk-level":_.string,"risk-matrix-column":_.string,"risk-matrix-row":_.string}),dt=_.intersection([_.type({"comparison-operands":_.array(_.string),"comparison-operator":h(i)}),_.partial({"risk-level":_.string,"risk-matrix-column":_.string,"risk-matrix-row":_.string})]),ft=_.type({value:_.string}),pt=_.intersection([_.type({title:_.string,type:h(oe)}),_.partial({"sub-type":h(ae),placeholder:_.string,description:_.string,"is-required":_.boolean,"reference-id":_.string,"display-logic":lt,"risk-logic":_.array(dt),"risk-categories":_.array(_.string),"risk-framework":_.string,"answer-options":_.array(ft),"selected-answers":_.array(_.string),"allowed-mime-types":_.array(_.string),"allow-select-other":_.boolean,"sync-model":h(ce),"sync-column":h(se),"attribute-key":_.string,"require-risk-evaluation":_.boolean,"require-risk-matrix-evaluation":_.boolean})]),X=_.intersection([_.type({title:_.string,questions:_.array(pt)}),_.partial({assignees:_.array(_.string),"external-assignees":_.array(_.string),status:_.string,"is-reviewed":_.boolean})]),Z=_.type({type:h(Pe),"duration-days":_.number,operand:h(Ne)}),mt=_.intersection([_.type({title:_.string}),_.partial({sections:_.array(X),description:_.string,status:h(ie),source:h(re),creator:_.string,locked:_.boolean,"parent-id":_.string,archived:_.boolean,"created-at":_.string,"attribute-keys":_.array(_.string),"retention-schedule":Z,templates:_.array(_.string)})]),Q=_.type({title:_.string,type:h(n)}),ht=_.intersection([_.type({title:_.string,group:_.string}),_.partial({sections:_.array(X),creator:_.string,description:_.string,status:h(ne),assignees:_.array(_.string),"external-assignees":_.array(_.string),reviewers:_.array(_.string),locked:_.boolean,archived:_.boolean,external:_.boolean,"title-is-internal":_.boolean,"due-date":_.string,"created-at":_.string,"assigned-at":_.string,"submitted-at":_.string,"approved-at":_.string,"rejected-at":_.string,resources:_.array(Q),rows:_.array(Q),"retention-schedule":Z,attributes:_.array(A)})]),gt=_.type({title:_.string,slug:_.string}),_t=_.intersection([_.type({type:h(we),title:_.string,description:_.string}),_.partial({"default-configuration":_.string,"show-in-privacy-center":_.boolean,options:_.array(gt)})]),vt=_.intersection([_.type({trackingType:_.string,title:_.string,name:_.string}),_.partial({description:_.string,"is-active":_.boolean,configurable:_.boolean,"display-order":_.number,"show-in-privacy-center":_.boolean,"show-in-consent-manager":_.boolean,"preference-topics":_.array(_t),"auth-level":h(Ce),"opt-out-signals":_.array(h(Ge)),"default-consent":h(ye)})]),yt=_.intersection([_.type({resourceId:_.string,plugin:_.string,suggestedCatalog:_.string,containsSensitiveData:_.string,status:_.string}),_.partial({country:h(c),countrySubDivision:h(l),plaintextContext:_.string,title:_.union([_.string,_.null])})]),bt=_.partial({"action-items":_.array(st),"action-item-collections":_.array(ot),"api-keys":_.array(S),teams:_.array(C),templates:_.array(b),enrichers:_.array(w),attributes:_.array(k),"business-entities":_.array(H),vendors:_.array(P),"data-categories":_.array(F),"processing-purposes":_.array(I),"data-subjects":_.array(K),actions:_.array(q),identifiers:_.array(J),"data-silos":_.array(at),"data-flows":_.array(Ze),cookies:_.array(Qe),"consent-manager":tt,prompts:_.array(L),"prompt-partials":_.array(qe),"prompt-groups":_.array(R),agents:_.array(j),"agent-functions":_.array(M),"agent-files":_.array(N),"privacy-center":nt,policies:_.array(rt),messages:_.array(it),partitions:_.array(et),"assessment-templates":_.array(mt),assessments:_.array(ht),"processing-activities":_.array(W),purposes:_.array(vt),"system-discovery":_.array(yt)}),xt=_.type({organizationName:_.string,apiKey:_.string,organizationId:_.string}),St=_.intersection([_.type({"Connections Made To":_.string,Type:h(s),Purpose:_.string}),_.partial({Service:_.string,Notes:_.string,Owners:_.string,Teams:_.string,Status:h(a)}),_.record(_.string,_.string)]),Ct=_.intersection([_.type({Name:_.string,Purpose:_.string}),_.partial({Service:_.string,Notes:_.string,Owners:_.string,Teams:_.string,Status:h(a)}),_.record(_.string,_.string)]),wt=_.type({title:_.string,description:_.string,cookies:_.array(_.type({name:_.string,trackingPurposes:_.array(_.string)})),dataFlows:_.array(_.type({value:_.string,type:h(s),trackingPurposes:_.array(_.string)}))}),Tt=h(e),Et=y({TRouteName:h(t)});h(t);const Dt=_.array(Et),$=v({TEnabledRoutes:Dt}),Ot=_.partial({enabledIntegrations:_.partial({openAI:$})}),kt=_.partial({promptRunName:_.string,promptId:_.string,promptTitle:_.string,promptGroupId:_.string,promptGroupTitle:_.string,runByEmployeeEmail:_.string,applicationId:_.string,applicationName:_.string,codePackageName:_.string,repositoryName:_.string,applicationUserCoreIdentifier:_.string,applicationUserName:_.string,slackMessageTs:_.string,slackTeamId:_.string,slackChannelId:_.string,slackChannelName:_.string}),At=_.intersection([_.type({title:_.string}),_.partial({value:_.string})]),jt=_.type({columns:_.array(At)}),Mt=_.partial({rows:_.array(jt),json:_.string});export{rt as $,Ct as A,B,G as C,_t as D,wt as E,Ke as F,it as G,z as H,St as I,$ as J,Et as K,Ze as L,D as M,F as N,gt as O,E as P,kt as Q,at as R,Ye as S,tt as T,J as U,w as V,Mt as W,Ot as X,et as Y,Tt as Z,mt as _,bt as _t,M as a,R as at,O as b,y as bt,ft as c,U as ct,ct as d,dt,nt as et,Q as f,yt as ft,pt as g,b as gt,X as h,C as ht,N as i,V as it,Qe as j,vt as k,lt as l,Xe as lt,Y as m,xt as mt,ot as n,I as nt,j as o,L as ot,Z as p,Je as pt,Dt as q,st as r,T as rt,S as s,qe as st,q as t,W as tt,ht as u,ut,k as v,P as vt,$e as w,H as x,v as xt,A as y,x as yt,K as z};
2
- //# sourceMappingURL=codecs-DW8SY77H.mjs.map
@@ -1,2 +0,0 @@
1
- import"./enums-CyFTrzXY.mjs";import{ScopeName as e,TRANSCEND_SCOPES as t}from"@transcend-io/privacy-types";import{keyBy as n}from"lodash-es";var r=`10.16.0`,i=`A command line interface for programmatic operations across Transcend.`;const a=`transcend`,o=`https://app.transcend.io`,s=`${o}/infrastructure/integrations`,c=`${o}/data-map/data-inventory/data-points`,l=process.env.TRANSCEND_API_URL||`https://api.transcend.io`,u=process.env.TRANSCEND_API_KEY||void 0,d=process.env.TRANSCEND_CONSENT_API_URL||`https://consent.transcend.io`,f={apiKeys:[e.ViewApiKeys],templates:[e.ManageEmailTemplates],dataSilos:[e.ManageDataMap,e.ConnectDataSilos],enrichers:[e.ManageRequestIdentities],businessEntities:[e.ManageDataInventory],processingActivities:[e.ManageDataMap],identifiers:[e.ManageRequestIdentities],customFields:[e.ManageGlobalAttributes],dataFlows:[e.ManageDataFlow],cookies:[e.ManageDataFlow],consentManager:[e.ManageConsentManagerDeveloperSettings],partitions:[e.ManageConsentManagerDeveloperSettings],actions:[e.ManageDataSubjectRequestSettings],dataSubjects:[e.ManageDataSubjectRequestSettings],prompts:[e.ManagePrompts],promptPartials:[e.ManagePrompts],promptGroups:[e.ManagePrompts],agents:[e.ManagePathfinder],agentFunctions:[e.ManagePathfinder],agentFiles:[e.ManagePathfinder],vendors:[e.ManageDataInventory],dataCategories:[e.ManageDataInventory],processingPurposes:[e.ManageDataInventory],actionItems:[e.ManageAllActionItems,e.ViewGlobalAttributes],actionItemCollections:[e.ManageActionItemCollections],teams:[e.ManageAccessControl],messages:[e.ManageIntlMessages],privacyCenters:[e.ManagePrivacyCenter],policies:[e.ManagePolicies],assessments:[e.ManageAssessments],assessmentTemplates:[e.ManageAssessments],purposes:[e.ManageConsentManager,e.ManagePreferenceStoreSettings],systemDiscovery:[e.ManageDataMap]},p={apiKeys:[e.ViewApiKeys],templates:[e.ViewEmailTemplates],dataSilos:[e.ViewDataMap,e.ViewDataSubjectRequestSettings],enrichers:[e.ViewRequestIdentitySettings],businessEntities:[e.ViewDataInventory],processingActivities:[e.ViewDataInventory],identifiers:[e.ViewRequestIdentitySettings],customFields:[e.ViewGlobalAttributes],dataFlows:[e.ViewDataFlow],cookies:[e.ViewDataFlow],consentManager:[e.ViewConsentManager],partitions:[e.ViewConsentManager],actions:[e.ViewDataSubjectRequestSettings],dataSubjects:[e.ViewDataSubjectRequestSettings],prompts:[e.ViewPrompts],promptPartials:[e.ViewPrompts],promptGroups:[e.ViewPrompts],agents:[e.ViewPathfinder],agentFunctions:[e.ViewPathfinder],agentFiles:[e.ViewPathfinder],vendors:[e.ViewDataInventory],dataCategories:[e.ViewDataInventory],processingPurposes:[e.ViewDataInventory],actionItemCollections:[e.ViewAllActionItems],actionItems:[e.ViewAllActionItems],teams:[e.ViewScopes],messages:[e.ViewIntlMessages],privacyCenters:[e.ViewPrivacyCenter],policies:[e.ViewPolicies],assessments:[e.ViewAssessments],assessmentTemplates:[e.ViewAssessments],purposes:[e.ViewConsentManager,e.ViewPreferenceStoreSettings],systemDiscovery:[e.ViewDataMap]},m={apiKeys:`api-keys`,customFields:`attributes`,dataFlows:`data-flows`,cookies:`cookies`,consentManager:`consent-manager`,partitions:`partitions`,actions:`actions`,dataSubjects:`data-subjects`,businessEntities:`business-entities`,processingActivities:`processing-activities`,identifiers:`identifiers`,enrichers:`enrichers`,dataSilos:`data-silos`,templates:`templates`,prompts:`prompts`,promptPartials:`prompt-partials`,promptGroups:`prompt-groups`,agents:`agents`,agentFunctions:`agent-functions`,agentFiles:`agent-files`,vendors:`vendors`,dataCategories:`data-categories`,processingPurposes:`processing-purposes`,actionItems:`action-items`,actionItemCollections:`action-item-collections`,teams:`teams`,messages:`messages`,privacyCenters:`privacy-center`,policies:`policies`,assessments:`assessments`,assessmentTemplates:`assessment-templates`,purposes:`purposes`,systemDiscovery:`system-discovery`},h=n(Object.entries(t).map(([e,t])=>({...t,name:e})),`title`),g=Object.keys(h),_=new Set([429,502,500,504,329]),v=process.env.DEBUG===`1`;export{l as a,_ as c,p as d,f,r as g,i as h,v as i,h as l,a as m,c as n,u as o,m as p,s as r,d as s,o as t,g as u};
2
- //# sourceMappingURL=constants-B7bW_WN2.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"constants-B7bW_WN2.mjs","names":[],"sources":["../package.json","../src/constants.ts"],"sourcesContent":["","import { ScopeName, TRANSCEND_SCOPES, type ScopeDefinition } from '@transcend-io/privacy-types';\nimport { keyBy } from 'lodash-es';\n\nimport { TranscendInput } from './codecs.js';\nimport { TranscendPullResource } from './enums.js';\n\nexport { description, version } from '../package.json';\n/**\n * The name of the main binary for the CLI\n */\nexport const name = 'transcend';\n\nexport const ADMIN_DASH = 'https://app.transcend.io';\n\nexport const ADMIN_DASH_INTEGRATIONS = `${ADMIN_DASH}/infrastructure/integrations`;\nexport const ADMIN_DASH_DATAPOINTS = `${ADMIN_DASH}/data-map/data-inventory/data-points`;\n\n/**\n * Override default transcend API url using\n * TRANSCEND_API_URL=https://api.us.transcend.io transcend ...\n */\nexport const DEFAULT_TRANSCEND_API = process.env.TRANSCEND_API_URL || 'https://api.transcend.io';\n\n/**\n * Default the `--auth` flag to the `TRANSCEND_API_KEY` environment variable\n * when it is set, so callers do not need to pass `--auth` on every invocation:\n * TRANSCEND_API_KEY=... transcend policy list\n * When unset, `--auth` remains required.\n */\nexport const DEFAULT_TRANSCEND_API_KEY = process.env.TRANSCEND_API_KEY || undefined;\n\n/**\n * Override default transcend API url using\n * TRANSCEND_CONSENT_API_URL=https://consent.us.transcend.io transcend ...\n */\nexport const DEFAULT_TRANSCEND_CONSENT_API =\n process.env.TRANSCEND_CONSENT_API_URL || 'https://consent.transcend.io';\n\n/**\n * Mapping between resource type and scopes required for cli\n */\nexport const TR_PUSH_RESOURCE_SCOPE_MAP: {\n [k in TranscendPullResource]: ScopeName[];\n} = {\n [TranscendPullResource.ApiKeys]: [ScopeName.ViewApiKeys],\n [TranscendPullResource.Templates]: [ScopeName.ManageEmailTemplates],\n [TranscendPullResource.DataSilos]: [ScopeName.ManageDataMap, ScopeName.ConnectDataSilos],\n [TranscendPullResource.Enrichers]: [ScopeName.ManageRequestIdentities],\n [TranscendPullResource.BusinessEntities]: [ScopeName.ManageDataInventory],\n [TranscendPullResource.ProcessingActivities]: [ScopeName.ManageDataMap],\n [TranscendPullResource.Identifiers]: [ScopeName.ManageRequestIdentities],\n [TranscendPullResource.Attributes]: [ScopeName.ManageGlobalAttributes],\n [TranscendPullResource.DataFlows]: [ScopeName.ManageDataFlow],\n [TranscendPullResource.Cookies]: [ScopeName.ManageDataFlow],\n [TranscendPullResource.ConsentManager]: [ScopeName.ManageConsentManagerDeveloperSettings],\n [TranscendPullResource.Partitions]: [ScopeName.ManageConsentManagerDeveloperSettings],\n [TranscendPullResource.Actions]: [ScopeName.ManageDataSubjectRequestSettings],\n [TranscendPullResource.DataSubjects]: [ScopeName.ManageDataSubjectRequestSettings],\n [TranscendPullResource.Prompts]: [ScopeName.ManagePrompts],\n [TranscendPullResource.PromptPartials]: [ScopeName.ManagePrompts],\n [TranscendPullResource.PromptGroups]: [ScopeName.ManagePrompts],\n [TranscendPullResource.Agents]: [ScopeName.ManagePathfinder],\n [TranscendPullResource.AgentFunctions]: [ScopeName.ManagePathfinder],\n [TranscendPullResource.AgentFiles]: [ScopeName.ManagePathfinder],\n [TranscendPullResource.Vendors]: [ScopeName.ManageDataInventory],\n [TranscendPullResource.DataCategories]: [ScopeName.ManageDataInventory],\n [TranscendPullResource.ProcessingPurposes]: [ScopeName.ManageDataInventory],\n [TranscendPullResource.ActionItems]: [\n ScopeName.ManageAllActionItems,\n ScopeName.ViewGlobalAttributes,\n ],\n [TranscendPullResource.ActionItemCollections]: [ScopeName.ManageActionItemCollections],\n [TranscendPullResource.Teams]: [ScopeName.ManageAccessControl],\n [TranscendPullResource.Messages]: [ScopeName.ManageIntlMessages],\n [TranscendPullResource.PrivacyCenters]: [ScopeName.ManagePrivacyCenter],\n [TranscendPullResource.Policies]: [ScopeName.ManagePolicies],\n [TranscendPullResource.Assessments]: [ScopeName.ManageAssessments],\n [TranscendPullResource.AssessmentTemplates]: [ScopeName.ManageAssessments],\n [TranscendPullResource.Purposes]: [\n ScopeName.ManageConsentManager,\n ScopeName.ManagePreferenceStoreSettings,\n ],\n [TranscendPullResource.SystemDiscovery]: [ScopeName.ManageDataMap],\n};\n\n/**\n * Mapping between resource type and scopes required for cli\n */\nexport const TR_PULL_RESOURCE_SCOPE_MAP: {\n [k in TranscendPullResource]: ScopeName[];\n} = {\n [TranscendPullResource.ApiKeys]: [ScopeName.ViewApiKeys],\n [TranscendPullResource.Templates]: [ScopeName.ViewEmailTemplates],\n [TranscendPullResource.DataSilos]: [\n ScopeName.ViewDataMap,\n ScopeName.ViewDataSubjectRequestSettings,\n ],\n [TranscendPullResource.Enrichers]: [ScopeName.ViewRequestIdentitySettings],\n [TranscendPullResource.BusinessEntities]: [ScopeName.ViewDataInventory],\n [TranscendPullResource.ProcessingActivities]: [ScopeName.ViewDataInventory],\n [TranscendPullResource.Identifiers]: [ScopeName.ViewRequestIdentitySettings],\n [TranscendPullResource.Attributes]: [ScopeName.ViewGlobalAttributes],\n [TranscendPullResource.DataFlows]: [ScopeName.ViewDataFlow],\n [TranscendPullResource.Cookies]: [ScopeName.ViewDataFlow],\n [TranscendPullResource.ConsentManager]: [ScopeName.ViewConsentManager],\n [TranscendPullResource.Partitions]: [ScopeName.ViewConsentManager],\n [TranscendPullResource.Actions]: [ScopeName.ViewDataSubjectRequestSettings],\n [TranscendPullResource.DataSubjects]: [ScopeName.ViewDataSubjectRequestSettings],\n [TranscendPullResource.Prompts]: [ScopeName.ViewPrompts],\n [TranscendPullResource.PromptPartials]: [ScopeName.ViewPrompts],\n [TranscendPullResource.PromptGroups]: [ScopeName.ViewPrompts],\n [TranscendPullResource.Agents]: [ScopeName.ViewPathfinder],\n [TranscendPullResource.AgentFunctions]: [ScopeName.ViewPathfinder],\n [TranscendPullResource.AgentFiles]: [ScopeName.ViewPathfinder],\n [TranscendPullResource.Vendors]: [ScopeName.ViewDataInventory],\n [TranscendPullResource.DataCategories]: [ScopeName.ViewDataInventory],\n [TranscendPullResource.ProcessingPurposes]: [ScopeName.ViewDataInventory],\n [TranscendPullResource.ActionItemCollections]: [ScopeName.ViewAllActionItems],\n [TranscendPullResource.ActionItems]: [ScopeName.ViewAllActionItems],\n [TranscendPullResource.Teams]: [ScopeName.ViewScopes],\n [TranscendPullResource.Messages]: [ScopeName.ViewIntlMessages],\n [TranscendPullResource.PrivacyCenters]: [ScopeName.ViewPrivacyCenter],\n [TranscendPullResource.Policies]: [ScopeName.ViewPolicies],\n [TranscendPullResource.Assessments]: [ScopeName.ViewAssessments],\n [TranscendPullResource.AssessmentTemplates]: [ScopeName.ViewAssessments],\n [TranscendPullResource.Purposes]: [\n ScopeName.ViewConsentManager,\n ScopeName.ViewPreferenceStoreSettings,\n ],\n [TranscendPullResource.SystemDiscovery]: [ScopeName.ViewDataMap],\n};\n\nexport const TR_YML_RESOURCE_TO_FIELD_NAME: Record<TranscendPullResource, keyof TranscendInput> = {\n [TranscendPullResource.ApiKeys]: 'api-keys',\n [TranscendPullResource.Attributes]: 'attributes',\n [TranscendPullResource.DataFlows]: 'data-flows',\n [TranscendPullResource.Cookies]: 'cookies',\n [TranscendPullResource.ConsentManager]: 'consent-manager',\n [TranscendPullResource.Partitions]: 'partitions',\n [TranscendPullResource.Actions]: 'actions',\n [TranscendPullResource.DataSubjects]: 'data-subjects',\n [TranscendPullResource.BusinessEntities]: 'business-entities',\n [TranscendPullResource.ProcessingActivities]: 'processing-activities',\n [TranscendPullResource.Identifiers]: 'identifiers',\n [TranscendPullResource.Enrichers]: 'enrichers',\n [TranscendPullResource.DataSilos]: 'data-silos',\n [TranscendPullResource.Templates]: 'templates',\n [TranscendPullResource.Prompts]: 'prompts',\n [TranscendPullResource.PromptPartials]: 'prompt-partials',\n [TranscendPullResource.PromptGroups]: 'prompt-groups',\n [TranscendPullResource.Agents]: 'agents',\n [TranscendPullResource.AgentFunctions]: 'agent-functions',\n [TranscendPullResource.AgentFiles]: 'agent-files',\n [TranscendPullResource.Vendors]: 'vendors',\n [TranscendPullResource.DataCategories]: 'data-categories',\n [TranscendPullResource.ProcessingPurposes]: 'processing-purposes',\n [TranscendPullResource.ActionItems]: 'action-items',\n [TranscendPullResource.ActionItemCollections]: 'action-item-collections',\n [TranscendPullResource.Teams]: 'teams',\n [TranscendPullResource.Messages]: 'messages',\n [TranscendPullResource.PrivacyCenters]: 'privacy-center',\n [TranscendPullResource.Policies]: 'policies',\n [TranscendPullResource.Assessments]: 'assessments',\n [TranscendPullResource.AssessmentTemplates]: 'assessment-templates',\n [TranscendPullResource.Purposes]: 'purposes',\n [TranscendPullResource.SystemDiscovery]: 'system-discovery',\n};\n\nexport const SCOPES_BY_TITLE = keyBy(\n Object.entries(TRANSCEND_SCOPES).map(([name, value]) => ({\n ...value,\n name,\n })),\n 'title',\n) as Record<\n string,\n ScopeDefinition & {\n /** The camelCased name which identifies the scope */\n name: ScopeName;\n }\n>;\n\nexport const SCOPE_TITLES = Object.keys(SCOPES_BY_TITLE);\n\n/**\n * HTTP statuses that should be retried *in place* without splitting.\n * 429: Rate-limited\n * 502: Upstream/edge gateway error\n * 329: Reserved for custom infra (kept defensively)\n */\nexport const RETRYABLE_BATCH_STATUSES = new Set([429, 502, 500, 504, 329] as const);\n\n/**\n * Debugging\n */\nexport const DEBUG = process.env.DEBUG === '1';\n"],"mappings":"wOCUA,MAAa,EAAO,YAEP,EAAa,2BAEb,EAA0B,GAAG,EAAW,8BACxC,EAAwB,GAAG,EAAW,sCAMtC,EAAwB,QAAQ,IAAI,mBAAqB,2BAQzD,EAA4B,QAAQ,IAAI,mBAAqB,IAAA,GAM7D,EACX,QAAQ,IAAI,2BAA6B,+BAK9B,EAET,SAC+B,CAAC,EAAU,YAAY,WACrB,CAAC,EAAU,qBAAqB,WAChC,CAAC,EAAU,cAAe,EAAU,iBAAiB,WACrD,CAAC,EAAU,wBAAwB,kBAC5B,CAAC,EAAU,oBAAoB,sBAC3B,CAAC,EAAU,cAAc,aAClC,CAAC,EAAU,wBAAwB,cACpC,CAAC,EAAU,uBAAuB,WACnC,CAAC,EAAU,eAAe,SAC5B,CAAC,EAAU,eAAe,gBACnB,CAAC,EAAU,sCAAsC,YACrD,CAAC,EAAU,sCAAsC,SACpD,CAAC,EAAU,iCAAiC,cACvC,CAAC,EAAU,iCAAiC,SACjD,CAAC,EAAU,cAAc,gBAClB,CAAC,EAAU,cAAc,cAC3B,CAAC,EAAU,cAAc,QAC/B,CAAC,EAAU,iBAAiB,gBACpB,CAAC,EAAU,iBAAiB,YAChC,CAAC,EAAU,iBAAiB,SAC/B,CAAC,EAAU,oBAAoB,gBACxB,CAAC,EAAU,oBAAoB,oBAC3B,CAAC,EAAU,oBAAoB,aACtC,CACnC,EAAU,qBACV,EAAU,qBACX,uBAC8C,CAAC,EAAU,4BAA4B,OACvD,CAAC,EAAU,oBAAoB,UAC5B,CAAC,EAAU,mBAAmB,gBACxB,CAAC,EAAU,oBAAoB,UACrC,CAAC,EAAU,eAAe,aACvB,CAAC,EAAU,kBAAkB,qBACrB,CAAC,EAAU,kBAAkB,UACxC,CAChC,EAAU,qBACV,EAAU,8BACX,iBACwC,CAAC,EAAU,cAAc,CACnE,CAKY,EAET,SAC+B,CAAC,EAAU,YAAY,WACrB,CAAC,EAAU,mBAAmB,WAC9B,CACjC,EAAU,YACV,EAAU,+BACX,WACkC,CAAC,EAAU,4BAA4B,kBAChC,CAAC,EAAU,kBAAkB,sBACzB,CAAC,EAAU,kBAAkB,aACtC,CAAC,EAAU,4BAA4B,cACxC,CAAC,EAAU,qBAAqB,WACjC,CAAC,EAAU,aAAa,SAC1B,CAAC,EAAU,aAAa,gBACjB,CAAC,EAAU,mBAAmB,YAClC,CAAC,EAAU,mBAAmB,SACjC,CAAC,EAAU,+BAA+B,cACrC,CAAC,EAAU,+BAA+B,SAC/C,CAAC,EAAU,YAAY,gBAChB,CAAC,EAAU,YAAY,cACzB,CAAC,EAAU,YAAY,QAC7B,CAAC,EAAU,eAAe,gBAClB,CAAC,EAAU,eAAe,YAC9B,CAAC,EAAU,eAAe,SAC7B,CAAC,EAAU,kBAAkB,gBACtB,CAAC,EAAU,kBAAkB,oBACzB,CAAC,EAAU,kBAAkB,uBAC1B,CAAC,EAAU,mBAAmB,aACxC,CAAC,EAAU,mBAAmB,OACpC,CAAC,EAAU,WAAW,UACnB,CAAC,EAAU,iBAAiB,gBACtB,CAAC,EAAU,kBAAkB,UACnC,CAAC,EAAU,aAAa,aACrB,CAAC,EAAU,gBAAgB,qBACnB,CAAC,EAAU,gBAAgB,UACtC,CAChC,EAAU,mBACV,EAAU,4BACX,iBACwC,CAAC,EAAU,YAAY,CACjE,CAEY,EAAqF,SAC/D,wBACG,uBACD,qBACF,yBACO,6BACJ,qBACH,uBACK,iCACI,yCACI,oCACT,wBACF,sBACA,uBACA,oBACF,yBACO,+BACF,uBACN,wBACQ,6BACJ,sBACH,yBACO,qCACI,kCACP,qCACU,gCAChB,iBACG,0BACM,0BACN,uBACG,kCACQ,gCACX,2BACO,mBAC1C,CAEY,EAAkB,EAC7B,OAAO,QAAQ,EAAiB,CAAC,KAAK,CAAC,EAAM,MAAY,CACvD,GAAG,EACH,OACD,EAAE,CACH,QACD,CAQY,EAAe,OAAO,KAAK,EAAgB,CAQ3C,EAA2B,IAAI,IAAI,CAAC,IAAK,IAAK,IAAK,IAAK,IAAI,CAAU,CAKtE,EAAQ,QAAQ,IAAI,QAAU"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"enums-CyFTrzXY.mjs","names":[],"sources":["../src/enums.ts"],"sourcesContent":["import { makeEnum } from '@transcend-io/type-utils';\n\n/** Accepted file formats for exporting resources from OneTrust */\nexport enum OneTrustFileFormat {\n Json = 'json',\n}\n\n/**\n * Resources that can be pulled in from OneTrust\n */\nexport enum OneTrustPullResource {\n Assessments = 'assessments',\n}\n\n/**\n * Where to read OneTrust resources from\n */\nexport enum OneTrustPullSource {\n OneTrust = 'oneTrust',\n File = 'file',\n}\n\n/**\n * Resources that can be pulled in\n */\nexport enum TranscendPullResource {\n ApiKeys = 'apiKeys',\n Attributes = 'customFields',\n Templates = 'templates',\n DataSilos = 'dataSilos',\n Enrichers = 'enrichers',\n DataFlows = 'dataFlows',\n BusinessEntities = 'businessEntities',\n ProcessingActivities = 'processingActivities',\n Actions = 'actions',\n DataSubjects = 'dataSubjects',\n Identifiers = 'identifiers',\n Cookies = 'cookies',\n ConsentManager = 'consentManager',\n Partitions = 'partitions',\n Prompts = 'prompts',\n PromptPartials = 'promptPartials',\n PromptGroups = 'promptGroups',\n Agents = 'agents',\n AgentFunctions = 'agentFunctions',\n AgentFiles = 'agentFiles',\n Vendors = 'vendors',\n DataCategories = 'dataCategories',\n ProcessingPurposes = 'processingPurposes',\n ActionItems = 'actionItems',\n ActionItemCollections = 'actionItemCollections',\n Teams = 'teams',\n PrivacyCenters = 'privacyCenters',\n Policies = 'policies',\n Messages = 'messages',\n Assessments = 'assessments',\n AssessmentTemplates = 'assessmentTemplates',\n Purposes = 'purposes',\n SystemDiscovery = 'systemDiscovery',\n}\n\n/**\n * Names of built in policies for pathfinder\n */\nexport const PathfinderPolicyName = makeEnum({\n RedactEmail: 'redactEmail',\n Log: 'log',\n LogToTranscend: 'logToTranscend',\n ApplyTranscendPolicies: 'applyTranscendPolicies',\n});\n\n/**\n * Type override\n */\nexport type PathfinderPolicyName = (typeof PathfinderPolicyName)[keyof typeof PathfinderPolicyName];\n\n/**\n * The names of the OpenAI routes that we support setting policies for\n * reference: https://platform.openai.com/docs/api-reference/introduction\n */\nexport const OpenAIRouteName = makeEnum({\n ChatCompletion: '/v1/chat/completions',\n Embeddings: '/v1/embeddings',\n Completions: '/v1/completions',\n Agents: '/v1/assistants',\n Agent: '/v1/assistants/:assistantId',\n Threads: '/v1/threads',\n Thread: '/v1/threads/:threadId',\n Messages: '/v1/threads/:threadId/messages',\n Message: '/v1/threads/:threadId/messages/:messageId',\n Runs: '/v1/threads/:threadId/runs',\n Run: '/v1/threads/:threadId/runs/:runId',\n Files: '/v1/files',\n File: '/v1/files/:fileId',\n});\n\n/**\n * Type override\n */\nexport type OpenAIRouteName = (typeof OpenAIRouteName)[keyof typeof OpenAIRouteName];\n"],"mappings":"oDAGA,IAAY,EAAL,SAAA,EAAA,OACL,GAAA,KAAA,aACD,CAKW,EAAL,SAAA,EAAA,OACL,GAAA,YAAA,oBACD,CAKW,EAAL,SAAA,EAAA,OACL,GAAA,SAAA,WACA,EAAA,KAAA,aACD,CAKW,EAAL,SAAA,EAAA,OACL,GAAA,QAAA,UACA,EAAA,WAAA,eACA,EAAA,UAAA,YACA,EAAA,UAAA,YACA,EAAA,UAAA,YACA,EAAA,UAAA,YACA,EAAA,iBAAA,mBACA,EAAA,qBAAA,uBACA,EAAA,QAAA,UACA,EAAA,aAAA,eACA,EAAA,YAAA,cACA,EAAA,QAAA,UACA,EAAA,eAAA,iBACA,EAAA,WAAA,aACA,EAAA,QAAA,UACA,EAAA,eAAA,iBACA,EAAA,aAAA,eACA,EAAA,OAAA,SACA,EAAA,eAAA,iBACA,EAAA,WAAA,aACA,EAAA,QAAA,UACA,EAAA,eAAA,iBACA,EAAA,mBAAA,qBACA,EAAA,YAAA,cACA,EAAA,sBAAA,wBACA,EAAA,MAAA,QACA,EAAA,eAAA,iBACA,EAAA,SAAA,WACA,EAAA,SAAA,WACA,EAAA,YAAA,cACA,EAAA,oBAAA,sBACA,EAAA,SAAA,WACA,EAAA,gBAAA,wBACD,CAKD,MAAa,EAAuB,EAAS,CAC3C,YAAa,cACb,IAAK,MACL,eAAgB,iBAChB,uBAAwB,yBACzB,CAAC,CAWW,EAAkB,EAAS,CACtC,eAAgB,uBAChB,WAAY,iBACZ,YAAa,kBACb,OAAQ,iBACR,MAAO,8BACP,QAAS,cACT,OAAQ,wBACR,SAAU,iCACV,QAAS,4CACT,KAAM,6BACN,IAAK,oCACL,MAAO,YACP,KAAM,oBACP,CAAC"}
@@ -1,2 +0,0 @@
1
- import{r as e}from"./constants-B7bW_WN2.mjs";import{t}from"./logger-D1tXVwJj.mjs";import{r as n}from"./readTranscendYaml-I64TqeSd.mjs";import{n as r,r as i,t as a}from"./parseVariablesFromString-Cpjk0zeN.mjs";import{t as o}from"./validateTranscendAuth-CToEUu1U.mjs";import{t as s}from"./listFiles-DsUfOUWr.mjs";import{t as c}from"./done-input-validation-D25TzrxG.mjs";import{existsSync as l,lstatSync as u}from"node:fs";import{join as d}from"node:path";import f from"colors";import{buildTranscendGraphQLClient as p}from"@transcend-io/sdk";import{mapSeries as m}from"@transcend-io/utils";async function h({transcendUrl:e,auth:n,pageSize:r,publishToPrivacyCenter:a,contents:o,deleteExtraAttributeValues:s=!1,classifyService:c=!1}){let l=p(e,n);try{return!await i(o,l,{pageSize:r,publishToPrivacyCenter:a,classifyService:c,deleteExtraAttributeValues:s})}catch(e){return t.error(f.red(`An unexpected error occurred syncing the schema: ${e.message}`)),!1}}async function g({file:i=`./transcend.yml`,transcendUrl:p,auth:g,variables:_,pageSize:v,publishToPrivacyCenter:y,classifyService:b,deleteExtraAttributeValues:x}){c(this.process.exit);let S=await o(g),C=a(_),w;if(w=Array.isArray(S)&&u(i).isDirectory()?s(i).map(e=>d(i,e)):i.split(`,`),w.length<1)throw Error(`No file specified!`);let T=w.map(e=>{l(e)?t.info(f.magenta(`Reading file "${e}"...`)):(t.error(f.red(`The file path does not exist on disk: ${e}. You can specify the filepath using --file=./examples/transcend.yml`)),this.process.exit(1));try{let r=n(e,C);return t.info(f.green(`Successfully read in "${e}"`)),{content:r,name:e.split(`/`).pop().replace(`.yml`,``)}}catch(e){t.error(f.red(`The shape of your yaml file is invalid with the following errors: ${e.message}`)),this.process.exit(1)}});if(typeof S==`string`){let[n,...i]=T.map(({content:e})=>e);await h({transcendUrl:p,auth:S,contents:r(n,...i),publishToPrivacyCenter:y,deleteExtraAttributeValues:x,pageSize:v,classifyService:!!b})||(t.info(f.red(`Sync encountered errors. View output above for more information, or check out ${e}`)),this.process.exit(1))}else{if(T.length!==1&&T.length!==S.length)throw Error(`Expected list of yml files to be equal to the list of API keys.Got ${T.length} YML file${T.length===1?``:`s`} and ${S.length} API key${S.length===1?``:`s`}`);let n=[];await m(S,async(e,r)=>{let i=`[${r+1}/${S.length}][${e.organizationName}] `;t.info(f.magenta(`~~~\n\n${i}Attempting to push configuration...\n\n~~~`));let a=T.length===1?T[0].content:T.find(t=>t.name===e.organizationName)?.content;if(!a){t.error(f.red(`${i}Failed to find transcend.yml file for organization: "${e.organizationName}".`)),n.push(e.organizationName);return}await h({transcendUrl:p,auth:e.apiKey,contents:a,pageSize:v,publishToPrivacyCenter:y,deleteExtraAttributeValues:x,classifyService:b})?t.info(f.green(`${i}Successfully pushed configuration!`)):(t.error(f.red(`${i}Failed to sync configuration.`)),n.push(e.organizationName))}),n.length>0&&(t.info(f.red(`Sync encountered errors for "${n.join(`,`)}". View output above for more information, or check out ${e}`)),this.process.exit(1))}t.info(f.green(`Successfully synced yaml file to Transcend! View at ${e}`))}export{g as push};
2
- //# sourceMappingURL=impl-e-_DWiv4.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"impl-e-_DWiv4.mjs","names":[],"sources":["../src/commands/inventory/push/impl.ts"],"sourcesContent":["import { existsSync, lstatSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport { buildTranscendGraphQLClient } from '@transcend-io/sdk';\nimport { mapSeries } from '@transcend-io/utils';\nimport colors from 'colors';\n\nimport { TranscendInput } from '../../../codecs.js';\nimport { ADMIN_DASH_INTEGRATIONS } from '../../../constants.js';\nimport type { LocalContext } from '../../../context.js';\nimport { validateTranscendAuth, listFiles } from '../../../lib/api-keys/index.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { syncConfigurationToTranscend } from '../../../lib/graphql/index.js';\nimport { parseVariablesFromString } from '../../../lib/helpers/parseVariablesFromString.js';\nimport { mergeTranscendInputs } from '../../../lib/mergeTranscendInputs.js';\nimport { readTranscendYaml } from '../../../lib/readTranscendYaml.js';\nimport { logger } from '../../../logger.js';\n\n/**\n * Sync configuration to Transcend\n *\n * @param options - Options\n * @returns True if synced successfully, false if error occurs\n */\nasync function syncConfiguration({\n transcendUrl,\n auth,\n pageSize,\n publishToPrivacyCenter,\n contents,\n deleteExtraAttributeValues = false,\n classifyService = false,\n}: {\n /** Transcend YAML */\n contents: TranscendInput;\n /** Transcend URL */\n transcendUrl: string;\n /** API key */\n auth: string;\n /** Page size */\n pageSize: number;\n /** Skip privacy center publish step */\n publishToPrivacyCenter: boolean;\n /** classify data flow service if missing */\n classifyService?: boolean;\n /** Delete attributes when syncing */\n deleteExtraAttributeValues?: boolean;\n}): Promise<boolean> {\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Sync to Transcend\n try {\n const encounteredError = await syncConfigurationToTranscend(contents, client, {\n pageSize,\n publishToPrivacyCenter,\n classifyService,\n deleteExtraAttributeValues,\n });\n return !encounteredError;\n } catch (err) {\n logger.error(colors.red(`An unexpected error occurred syncing the schema: ${err.message}`));\n return false;\n }\n}\n\nexport interface PushCommandFlags {\n auth: string;\n file: string;\n transcendUrl: string;\n pageSize: number;\n variables: string;\n publishToPrivacyCenter: boolean;\n classifyService: boolean;\n deleteExtraAttributeValues: boolean;\n}\n\nexport async function push(\n this: LocalContext,\n {\n file = './transcend.yml',\n transcendUrl,\n auth,\n variables,\n pageSize,\n publishToPrivacyCenter,\n classifyService,\n deleteExtraAttributeValues,\n }: PushCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process.exit);\n\n // Parse authentication as API key or path to list of API keys\n const apiKeyOrList = await validateTranscendAuth(auth);\n\n // Parse out the variables\n const vars = parseVariablesFromString(variables);\n\n // check if we are being passed a list of API keys and a list of files\n let fileList: string[];\n if (Array.isArray(apiKeyOrList) && lstatSync(file).isDirectory()) {\n fileList = listFiles(file).map((filePath) => join(file, filePath));\n } else {\n fileList = file.split(',');\n }\n\n // Ensure at least one file is parsed\n if (fileList.length < 1) {\n throw new Error('No file specified!');\n }\n\n // eslint-disable-next-line array-callback-return,consistent-return\n const transcendInputs = fileList.map((filePath) => {\n // Ensure yaml file exists on disk\n if (!existsSync(filePath)) {\n logger.error(\n colors.red(\n `The file path does not exist on disk: ${filePath}. You can specify the filepath using --file=./examples/transcend.yml`,\n ),\n );\n this.process.exit(1);\n } else {\n logger.info(colors.magenta(`Reading file \"${filePath}\"...`));\n }\n\n try {\n // Read in the yaml file and validate it's shape\n const newContents = readTranscendYaml(filePath, vars);\n logger.info(colors.green(`Successfully read in \"${filePath}\"`));\n return {\n content: newContents,\n name: filePath.split('/').pop()!.replace('.yml', ''),\n };\n } catch (err) {\n logger.error(\n colors.red(\n `The shape of your yaml file is invalid with the following errors: ${err.message}`,\n ),\n );\n this.process.exit(1);\n }\n });\n\n // process a single API key\n if (typeof apiKeyOrList === 'string') {\n // if passed multiple inputs, merge them together\n const [base, ...rest] = transcendInputs.map(({ content }) => content);\n const contents = mergeTranscendInputs(base, ...rest);\n\n // sync the configuration\n const success = await syncConfiguration({\n transcendUrl,\n auth: apiKeyOrList,\n contents,\n publishToPrivacyCenter,\n deleteExtraAttributeValues,\n pageSize,\n classifyService: !!classifyService,\n });\n\n // exist with error code\n if (!success) {\n logger.info(\n colors.red(\n `Sync encountered errors. View output above for more information, or check out ${ADMIN_DASH_INTEGRATIONS}`,\n ),\n );\n\n this.process.exit(1);\n }\n } else {\n // if passed multiple inputs, expect them to be one per instance\n if (transcendInputs.length !== 1 && transcendInputs.length !== apiKeyOrList.length) {\n throw new Error(\n 'Expected list of yml files to be equal to the list of API keys.' +\n `Got ${transcendInputs.length} YML file${\n transcendInputs.length === 1 ? '' : 's'\n } and ${apiKeyOrList.length} API key${apiKeyOrList.length === 1 ? '' : 's'}`,\n );\n }\n\n const encounteredErrors: string[] = [];\n await mapSeries(apiKeyOrList, async (apiKey, ind) => {\n const prefix = `[${ind + 1}/${apiKeyOrList.length}][${apiKey.organizationName}] `;\n logger.info(colors.magenta(`~~~\\n\\n${prefix}Attempting to push configuration...\\n\\n~~~`));\n\n // use the merged contents if 1 yml passed, else use the contents that map to that organization\n const useContents =\n transcendInputs.length === 1\n ? transcendInputs[0].content\n : transcendInputs.find((input) => input.name === apiKey.organizationName)?.content;\n\n // Throw error if cannot find a yml file matching that organization name\n if (!useContents) {\n logger.error(\n colors.red(\n `${prefix}Failed to find transcend.yml file for organization: \"${apiKey.organizationName}\".`,\n ),\n );\n encounteredErrors.push(apiKey.organizationName);\n return;\n }\n\n const success = await syncConfiguration({\n transcendUrl,\n auth: apiKey.apiKey,\n contents: useContents,\n pageSize,\n publishToPrivacyCenter,\n deleteExtraAttributeValues,\n classifyService,\n });\n\n if (success) {\n logger.info(colors.green(`${prefix}Successfully pushed configuration!`));\n } else {\n logger.error(colors.red(`${prefix}Failed to sync configuration.`));\n encounteredErrors.push(apiKey.organizationName);\n }\n });\n\n if (encounteredErrors.length > 0) {\n logger.info(\n colors.red(\n `Sync encountered errors for \"${encounteredErrors.join(\n ',',\n )}\". View output above for more information, or check out ${ADMIN_DASH_INTEGRATIONS}`,\n ),\n );\n\n this.process.exit(1);\n }\n }\n\n // Indicate success\n logger.info(\n colors.green(`Successfully synced yaml file to Transcend! View at ${ADMIN_DASH_INTEGRATIONS}`),\n );\n}\n"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- import{t as e}from"./logger-D1tXVwJj.mjs";import{chunk as t,difference as n,flatten as r,keyBy as i,uniq as a}from"lodash-es";import{apply as o,getEntries as s}from"@transcend-io/type-utils";import c from"colors";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,syncAgentFiles as w,syncAgentFunctions as T,syncAgents as ee,syncAttribute as te,syncBusinessEntities as ne,syncConsentManager as E,syncCookies as re,syncDataCategories as ie,syncDataFlows as ae,syncDataSiloDependencies as oe,syncDataSubject as se,syncEnricher as ce,syncIdentifier as le,syncIntlMessages as ue,syncPartitions as de,syncPolicies as fe,syncPrivacyCenter as pe,syncProcessingActivities as me,syncProcessingPurposes as he,syncPromptGroups as ge,syncPromptPartials as _e,syncPrompts as ve,syncTeams as ye,syncTemplate as be,syncVendors as xe}from"@transcend-io/sdk";import{map as D,mapSeries as O}from"@transcend-io/utils";import k from"cli-progress";async function A({"data-silos":t=[],"data-subjects":o=[],"processing-activities":s=[],enrichers:l=[]},u,d=!1){let f=a([...r(t.map(e=>e[`data-subjects`]||[])||[]),...r(s.map(({dataSubjectTypes:e})=>e??[])??[]),...r(l.map(e=>e[`data-subjects`]||[])||[]),...o.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(c.magenta(`Creating ${g.length} new data subjects...`));for(let t of g){e.info(c.magenta(`Creating data subject ${t}...`));let n=await p(u,{input:t,logger:e});e.info(c.green(`Created data subject ${t}!`)),h[t]=n}}return h}async function j(n,r,{pageSize:a,dataSubjectsByName:s,apiKeysByTitle:p}){let m=!1,h=new Date().getTime();e.info(c.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(c.magenta(`Creating "${v.length}" data silos that did not exist...`)),await O(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}))},logger:e});n.forEach(e=>{_[e.title]=e})}),e.info(c.green(`Successfully created "${v.length}" data silos!`)));let y=t(n,20);await O(y,async(t,n)=>{e.info(c.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,dependedOnDataSiloTitles:e[`deletion-dependencies`]?void 0:[],apiKeyId:e[`api-key-title`]?p[e[`api-key-title`]].id:void 0,dataSubjectBlockListIds:e[`data-subjects`]?f(e[`data-subjects`],s):void 0,attributes:e.attributes,businessEntityTitles:e.businessEntityTitles,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(c.green(`[Batch ${n+1}/${y.length}] Synced "${t.length}" data silos!`))});let x=new k.SingleBar({},k.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(c.magenta(`Syncing "${C}" datapoints from "${S.length}" data silos...`)),x.start(C,0);let w=0;await D(S,async({datapoints:t,title:n})=>{t&&await O(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},o=(a.subDataPoints||[]).map(({name:e})=>e),s=o.filter((e,t)=>o.indexOf(e)!==t);if(s.length>0)e.info(c.red(`\nCannot update datapoint "${t.key}" as it has duplicate sub-datapoints with the same name: \n${s.join(`
2
- `)}`)),m=!0;else try{await b(r,d,{variables:a,logger:e})}catch(r){e.info(c.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(c.green(`Synced "${n.length}" data silos and "${C}" datapoints in "${T/1e3}" seconds!`)),{success:!m,dataSiloTitleToId:o(_,({id:e})=>e)}}async function M(t,n,{pageSize:r=50,publishToPrivacyCenter:i=!0,classifyService:a=!1,deleteExtraAttributeValues:o=!1}){let s=!1;e.info(c.magenta(`Fetching data with page size ${r}...`));let{templates:l,attributes:u,actions:d,identifiers:f,"data-subjects":p,"business-entities":g,enrichers:b,cookies:O,"consent-manager":k,"data-silos":M,"data-flows":N,prompts:P,"prompt-groups":F,"prompt-partials":I,agents:L,"agent-functions":R,"agent-files":z,vendors:B,"data-categories":V,"processing-activities":H,"processing-purposes":U,"action-items":W,"action-item-collections":G,teams:K,"privacy-center":q,messages:J,policies:Y,partitions:X}=t,[Z,Q,Se]=await Promise.all([b||f?y(n,{input:t,skipPublish:!i,logger:e}):{},M||p||b||H?A(t,n):{},M&&M.map(e=>e[`api-key-title`]||[]).reduce((e,t)=>e+t.length,0)>0?v(n,{apiKeyInputs:t,logger:e}):{}]);if(k){e.info(c.magenta(`Syncing consent manager...`));try{await E(n,k,{logger:e}),e.info(c.green(`Successfully synced consent manager!`))}catch(t){s=!0,e.error(c.red(`Failed to sync consent manager! - ${t.message}`))}}if(P){let t=await ve(n,P,{logger:e});s||=!t}if(I){let t=await _e(n,I,{logger:e});s||=!t}if(F){let t=await ge(n,F,{logger:e});s||=!t}if(K){let t=await ye(n,K,{logger:e});s||=!t}if(l&&(e.info(c.magenta(`Syncing "${l.length}" email templates...`)),await D(l,async t=>{e.info(c.magenta(`Syncing template "${t.title}"...`));try{await be(n,t,{logger:e}),e.info(c.green(`Successfully synced template "${t.title}"!`))}catch(n){s=!0,e.error(c.red(`Failed to sync template "${t.title}"! - ${n.message}`))}},{concurrency:10}),e.info(c.green(`Synced "${l.length}" email templates!`))),g){let t=await ne(n,g,{logger:e});s||=!t}if(B){let t=await xe(n,B,{logger:e});s||=!t}if(V){let t=await ie(n,V,{logger:e});s||=!t}if(U){let t=await he(n,U,{logger:e});s||=!t}if(X){let t=await de(n,X,{logger:e});s||=!t}if(L){let t=await ee(n,L,{logger:e});s||=!t}if(R){let t=await T(n,R,{logger:e});s||=!t}if(z){let t=await w(n,z,{logger:e});s||=!t}if(O){let t=await re(n,O,{logger:e});s||=!t}if(G){let t=await S(n,G,{logger:e});s||=!t}if(u){e.info(c.magenta(`Syncing "${u.length}" attributes...`));let t=await h(n,{logger:e});await D(u,async r=>{let i=t.find(e=>e.name===r.name);e.info(c.magenta(`Syncing attribute "${r.name}"...`));try{await te(n,r,{existingAttribute:i,deleteExtraAttributeValues:o,logger:e}),e.info(c.green(`Successfully synced attribute "${r.name}"!`))}catch(t){s=!0,e.error(c.red(`Failed to sync attribute "${r.name}"! - ${t.message}`))}},{concurrency:10}),e.info(c.green(`Synced "${u.length}" attributes!`))}if(W){let t=await C(n,W,{logger:e});s||=!t}if(b&&(e.info(c.magenta(`Syncing "${b.length}" enrichers...`)),await D(b,async t=>{e.info(c.magenta(`Syncing enricher "${t.title}"...`));try{await ce(n,{input:t,identifierByName:Z,dataSubjectsByName:Q,logger:e}),e.info(c.green(`Successfully synced enricher "${t.title}"!`))}catch(n){s=!0,e.error(c.red(`Failed to sync enricher "${t.title}"! - ${n.message}`))}},{concurrency:10}),e.info(c.green(`Synced "${b.length}" enrichers!`))),f&&(e.info(c.magenta(`Syncing "${f.length}" identifiers...`)),await D(f,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(c.magenta(`Syncing identifier "${t.type}"...`));try{await le(n,{input:t,dataSubjectsByName:Q,identifierId:r.id,skipPublish:!i,logger:e}),e.info(c.green(`Successfully synced identifier "${t.type}"!`))}catch(n){s=!0,e.info(c.red(`Failed to sync identifier "${t.type}"! - ${n.message}`))}},{concurrency:10}),e.info(c.green(`Synced "${f.length}" identifiers!`))),d){e.info(c.magenta(`Syncing "${d.length}" actions...`));let t=await m(n,{logger:e});await D(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(c.magenta(`Syncing action "${r.type}"...`));try{await x(n,{action:r,actionId:a.id,skipPublish:!i},{logger:e}),e.info(c.green(`Successfully synced action "${r.type}"!`))}catch(t){s=!0,e.error(c.red(`Failed to sync action "${r.type}"! - ${t.message}`))}},{concurrency:10}),e.info(c.green(`Synced "${d.length}" actions!`))}if(p){e.info(c.magenta(`Syncing "${p.length}" data subjects...`));let t=await _(n,{logger:e});await D(p,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(c.magenta(`Syncing data subject "${r.type}"...`));try{await se(n,{input:r,dataSubjectId:a.id,skipPublish:!i,logger:e}),e.info(c.green(`Successfully synced data subject "${r.type}"!`))}catch(t){s=!0,e.info(c.red(`Failed to sync data subject "${r.type}"! - ${t.message}`))}},{concurrency:10}),e.info(c.green(`Synced "${p.length}" data subjects!`))}if(N){let t=await ae(n,N,{classifyService:a,logger:e});s||=!t}if(q){let t=await pe(n,q,{logger:e});s||=!t}if(J){let t=await ue(n,J,{logger:e});s||=!t}if(Y){let t=await fe(n,Y,{logger:e});s||=!t}let $=[];if(M){let{success:e,dataSiloTitleToId:t}=await j(M,n,{dataSubjectsByName:Q,apiKeysByTitle:Se,pageSize:r});M?.forEach(e=>{e[`deletion-dependencies`]&&$.push([t[e.title],e[`deletion-dependencies`]])}),s||=!e}if($.length>0&&await oe(n,{input:$,logger:e}),H){let t=await me(n,H,{logger:e});s||=!t}return s}function N(e,...t){let n=JSON.parse(JSON.stringify(e));return t.forEach(e=>{s(e).forEach(([e,t])=>{n[e]===void 0?n[e]=t:Array.isArray(t)?n[e]=[...n[e],...t]:n[e]=t})}),n}function P(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{A as a,j as i,N as n,M as r,P as t};
3
- //# sourceMappingURL=parseVariablesFromString-Cpjk0zeN.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"parseVariablesFromString-Cpjk0zeN.mjs","names":[],"sources":["../src/lib/graphql/ensureAllDataSubjectsExist.ts","../src/lib/graphql/syncDataSilos.ts","../src/lib/graphql/syncConfigurationToTranscend.ts","../src/lib/mergeTranscendInputs.ts","../src/lib/helpers/parseVariablesFromString.ts"],"sourcesContent":["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 {\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 })),\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 if not specified, otherwise the update needs to be applied after\n // all data silos are created\n dependedOnDataSiloTitles: input['deletion-dependencies'] ? undefined : [],\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 // 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 syncAgentFiles,\n syncAgentFunctions,\n syncAgents,\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 syncPromptGroups,\n syncPromptPartials,\n syncPrompts,\n syncTeams,\n syncTemplate,\n syncVendors,\n type Identifier,\n} from '@transcend-io/sdk';\nimport { map } 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 { ensureAllDataSubjectsExist } from './ensureAllDataSubjectsExist.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 True if an error was encountered\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 }: {\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 },\n): Promise<boolean> {\n let encounteredError = false;\n\n logger.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 prompts,\n 'prompt-groups': promptGroups,\n 'prompt-partials': promptPartials,\n agents,\n 'agent-functions': agentFunctions,\n 'agent-files': agentFiles,\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 } = input;\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 // Sync consent manager\n if (consentManager) {\n logger.info(colors.magenta('Syncing consent manager...'));\n try {\n await syncConsentManager(client, consentManager, { logger });\n logger.info(colors.green('Successfully synced consent manager!'));\n } catch (err) {\n encounteredError = true;\n logger.error(colors.red(`Failed to sync consent manager! - ${err.message}`));\n }\n }\n\n // Sync prompts\n if (prompts) {\n const promptsSuccess = await syncPrompts(client, prompts, { logger });\n encounteredError = encounteredError || !promptsSuccess;\n }\n if (promptPartials) {\n const promptsSuccess = await syncPromptPartials(client, promptPartials, { logger });\n encounteredError = encounteredError || !promptsSuccess;\n }\n if (promptGroups) {\n const promptsSuccess = await syncPromptGroups(client, promptGroups, { logger });\n encounteredError = encounteredError || !promptsSuccess;\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 agents\n if (agents) {\n const agentsSuccess = await syncAgents(client, agents, { logger });\n encounteredError = encounteredError || !agentsSuccess;\n }\n\n // Sync agent functions\n if (agentFunctions) {\n const agentFunctionsSuccess = await syncAgentFunctions(client, agentFunctions, { logger });\n encounteredError = encounteredError || !agentFunctionsSuccess;\n }\n\n // Sync agent files\n if (agentFiles) {\n const agentFilesSuccess = await syncAgentFiles(client, agentFiles, { logger });\n encounteredError = encounteredError || !agentFilesSuccess;\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 logger.info(\n colors.red(`Failed to sync data subject \"${dataSubject.type}\"! - ${err.message}`),\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 const privacyCenterSuccess = await syncPrivacyCenter(client, privacyCenter, { logger });\n encounteredError = encounteredError || !privacyCenterSuccess;\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, string[]][] = [];\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 if (dataSilo['deletion-dependencies']) {\n dependencyUpdates.push([\n dataSiloTitleToId[dataSilo.title],\n dataSilo['deletion-dependencies'],\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 await syncDataSiloDependencies(client, { input: dependencyUpdates, logger });\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 encounteredError;\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","/**\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":"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"}