@transcend-io/cli 10.1.0 → 10.2.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.
- package/dist/{app-Cx8-4u8K.mjs → app-DLzaZHc8.mjs} +20 -20
- package/dist/{app-Cx8-4u8K.mjs.map → app-DLzaZHc8.mjs.map} +1 -1
- package/dist/{approvePrivacyRequests-Bjq5cPSI.mjs → approvePrivacyRequests-BlUcYXpH.mjs} +2 -2
- package/dist/{approvePrivacyRequests-Bjq5cPSI.mjs.map → approvePrivacyRequests-BlUcYXpH.mjs.map} +1 -1
- package/dist/bin/bash-complete.mjs +1 -1
- package/dist/bin/cli.mjs +1 -1
- package/dist/bin/deprecated-command.mjs +1 -1
- package/dist/{buildXdiSyncEndpoint-DWs9ImOw.mjs → buildXdiSyncEndpoint-D5GxPH6o.mjs} +2 -2
- package/dist/{buildXdiSyncEndpoint-DWs9ImOw.mjs.map → buildXdiSyncEndpoint-D5GxPH6o.mjs.map} +1 -1
- package/dist/bulkRestartRequests-DILDBdc1.mjs +2 -0
- package/dist/bulkRestartRequests-DILDBdc1.mjs.map +1 -0
- package/dist/bulkRetryEnrichers-CjSz1472.mjs +2 -0
- package/dist/bulkRetryEnrichers-CjSz1472.mjs.map +1 -0
- package/dist/cancelPrivacyRequests-BWJZmZVY.mjs +2 -0
- package/dist/cancelPrivacyRequests-BWJZmZVY.mjs.map +1 -0
- package/dist/{collectCsvFilesOrExit-D-csvd13.mjs → collectCsvFilesOrExit-CbtyKAzu.mjs} +1 -1
- package/dist/{collectCsvFilesOrExit-D-csvd13.mjs.map → collectCsvFilesOrExit-CbtyKAzu.mjs.map} +1 -1
- package/dist/{collectParquetFilesOrExit-C8qT5_57.mjs → collectParquetFilesOrExit-BJiAyaQ5.mjs} +1 -1
- package/dist/{collectParquetFilesOrExit-C8qT5_57.mjs.map → collectParquetFilesOrExit-BJiAyaQ5.mjs.map} +1 -1
- package/dist/{command-rzZKmlky.mjs → command-BMa3UWax.mjs} +2 -2
- package/dist/{command-rzZKmlky.mjs.map → command-BMa3UWax.mjs.map} +1 -1
- package/dist/commands/admin/parquet-to-csv/worker.mjs +1 -1
- package/dist/{consentManagersToBusinessEntities-D1bdBgnA.mjs → consentManagersToBusinessEntities-BdKDganK.mjs} +1 -1
- package/dist/{consentManagersToBusinessEntities-D1bdBgnA.mjs.map → consentManagersToBusinessEntities-BdKDganK.mjs.map} +1 -1
- package/dist/{constants-mjLYTIJm.mjs → constants-BmwXDQu9.mjs} +2 -2
- package/dist/{constants-mjLYTIJm.mjs.map → constants-BmwXDQu9.mjs.map} +1 -1
- package/dist/{constants-DYbzl8QH.mjs → constants-ClkQQhJs.mjs} +1 -1
- package/dist/{constants-DYbzl8QH.mjs.map → constants-ClkQQhJs.mjs.map} +1 -1
- package/dist/{constants-XOsAW1__.mjs → constants-TpID7AXE.mjs} +2 -2
- package/dist/{constants-XOsAW1__.mjs.map → constants-TpID7AXE.mjs.map} +1 -1
- package/dist/{createExtraKeyHandler-Jp5XpTJi.mjs → createExtraKeyHandler-BO4lu0HO.mjs} +2 -2
- package/dist/{createExtraKeyHandler-Jp5XpTJi.mjs.map → createExtraKeyHandler-BO4lu0HO.mjs.map} +1 -1
- package/dist/{dataFlowsToDataSilos-DUj1NhOt.mjs → dataFlowsToDataSilos-Ca2DtTsd.mjs} +1 -1
- package/dist/{dataFlowsToDataSilos-DUj1NhOt.mjs.map → dataFlowsToDataSilos-Ca2DtTsd.mjs.map} +1 -1
- package/dist/{done-input-validation-C5rgR0Wr.mjs → done-input-validation-BcNBxhEs.mjs} +1 -1
- package/dist/{done-input-validation-C5rgR0Wr.mjs.map → done-input-validation-BcNBxhEs.mjs.map} +1 -1
- package/dist/{downloadPrivacyRequestFiles-GUbd_PRc.mjs → downloadPrivacyRequestFiles-8DtRUNXp.mjs} +2 -2
- package/dist/{downloadPrivacyRequestFiles-GUbd_PRc.mjs.map → downloadPrivacyRequestFiles-8DtRUNXp.mjs.map} +1 -1
- package/dist/{extractClientError-X9wJVqGq.mjs → extractClientError-i-Tw_az7.mjs} +1 -1
- package/dist/{extractClientError-X9wJVqGq.mjs.map → extractClientError-i-Tw_az7.mjs.map} +1 -1
- package/dist/{fetchAllRequests-xGgt_STo.mjs → fetchAllRequests-CHHdyb4Q.mjs} +2 -2
- package/dist/{fetchAllRequests-xGgt_STo.mjs.map → fetchAllRequests-CHHdyb4Q.mjs.map} +1 -1
- package/dist/generateCrossAccountApiKeys-D6hg9146.mjs +2 -0
- package/dist/generateCrossAccountApiKeys-D6hg9146.mjs.map +1 -0
- package/dist/{impl-ogUHfunr.mjs → impl--VlanXjT.mjs} +2 -2
- package/dist/{impl-ogUHfunr.mjs.map → impl--VlanXjT.mjs.map} +1 -1
- package/dist/{impl-B-PzeHxN.mjs → impl-3VLH9aat.mjs} +2 -2
- package/dist/{impl-B-PzeHxN.mjs.map → impl-3VLH9aat.mjs.map} +1 -1
- package/dist/{impl-DfVep2mE.mjs → impl-6mCOBlSD.mjs} +2 -2
- package/dist/{impl-DfVep2mE.mjs.map → impl-6mCOBlSD.mjs.map} +1 -1
- package/dist/impl-AEjPyfhu.mjs +2 -0
- package/dist/impl-AEjPyfhu.mjs.map +1 -0
- package/dist/{impl-CZsYoSZQ.mjs → impl-BC17WMY4.mjs} +2 -2
- package/dist/{impl-CZsYoSZQ.mjs.map → impl-BC17WMY4.mjs.map} +1 -1
- package/dist/{impl-yvc0y1uO.mjs → impl-BECek1in.mjs} +2 -2
- package/dist/{impl-yvc0y1uO.mjs.map → impl-BECek1in.mjs.map} +1 -1
- package/dist/{impl-B6TXE2oE.mjs → impl-BKvcmB7W.mjs} +2 -2
- package/dist/{impl-B6TXE2oE.mjs.map → impl-BKvcmB7W.mjs.map} +1 -1
- package/dist/impl-BNDNzc2I.mjs +2 -0
- package/dist/impl-BNDNzc2I.mjs.map +1 -0
- package/dist/{impl-Cy8-6_Oo2.mjs → impl-BTZOd3VN.mjs} +2 -2
- package/dist/impl-BTZOd3VN.mjs.map +1 -0
- package/dist/{impl-BffzTHKU.mjs → impl-BXb07jBU.mjs} +2 -2
- package/dist/{impl-BffzTHKU.mjs.map → impl-BXb07jBU.mjs.map} +1 -1
- package/dist/{impl-BBnnC5xq.mjs → impl-BaHZqboi.mjs} +2 -2
- package/dist/{impl-BBnnC5xq.mjs.map → impl-BaHZqboi.mjs.map} +1 -1
- package/dist/{impl-BSKl6rC6.mjs → impl-BhnojAfL.mjs} +2 -2
- package/dist/{impl-BSKl6rC6.mjs.map → impl-BhnojAfL.mjs.map} +1 -1
- package/dist/{impl-CqH3YYuv.mjs → impl-BjCQSRLu.mjs} +2 -2
- package/dist/{impl-CqH3YYuv.mjs.map → impl-BjCQSRLu.mjs.map} +1 -1
- package/dist/{impl-Cpndlxar.mjs → impl-BjIylEKQ.mjs} +2 -2
- package/dist/{impl-Cpndlxar.mjs.map → impl-BjIylEKQ.mjs.map} +1 -1
- package/dist/{impl-DKAV-8XC.mjs → impl-BsecIND0.mjs} +2 -2
- package/dist/{impl-DKAV-8XC.mjs.map → impl-BsecIND0.mjs.map} +1 -1
- package/dist/{impl-Dw9uW5zy2.mjs → impl-BtIsgTGn.mjs} +2 -2
- package/dist/impl-BtIsgTGn.mjs.map +1 -0
- package/dist/{impl-BMnXA_Vd.mjs → impl-BuvbXmXj.mjs} +2 -2
- package/dist/{impl-BMnXA_Vd.mjs.map → impl-BuvbXmXj.mjs.map} +1 -1
- package/dist/{impl-BBKJIP0Q.mjs → impl-C71CkarV.mjs} +2 -2
- package/dist/{impl-BBKJIP0Q.mjs.map → impl-C71CkarV.mjs.map} +1 -1
- package/dist/{impl-CpJljZV2.mjs → impl-CIYSnaMG.mjs} +2 -2
- package/dist/{impl-CpJljZV2.mjs.map → impl-CIYSnaMG.mjs.map} +1 -1
- package/dist/{impl-DhXQb3bm.mjs → impl-CLznNZ5F.mjs} +2 -2
- package/dist/{impl-DhXQb3bm.mjs.map → impl-CLznNZ5F.mjs.map} +1 -1
- package/dist/{impl-BGGm947r2.mjs → impl-CR6tW9Jz.mjs} +2 -2
- package/dist/impl-CR6tW9Jz.mjs.map +1 -0
- package/dist/{impl-CPIMsZg-.mjs → impl-CScy-GrG.mjs} +2 -2
- package/dist/{impl-CPIMsZg-.mjs.map → impl-CScy-GrG.mjs.map} +1 -1
- package/dist/{impl-uwkj-RbF.mjs → impl-CYS38cQM.mjs} +2 -2
- package/dist/{impl-uwkj-RbF.mjs.map → impl-CYS38cQM.mjs.map} +1 -1
- package/dist/{impl-BVnfUDUm.mjs → impl-Cw3_0zqC.mjs} +2 -2
- package/dist/{impl-BVnfUDUm.mjs.map → impl-Cw3_0zqC.mjs.map} +1 -1
- package/dist/{impl-D_AxguFh2.mjs → impl-CxwEMQhw.mjs} +2 -2
- package/dist/impl-CxwEMQhw.mjs.map +1 -0
- package/dist/{impl-DaK9UOwL.mjs → impl-CzvCA0Ev.mjs} +2 -2
- package/dist/{impl-DaK9UOwL.mjs.map → impl-CzvCA0Ev.mjs.map} +1 -1
- package/dist/{impl-StdJMCiM.mjs → impl-DAkBsgQN.mjs} +2 -2
- package/dist/{impl-StdJMCiM.mjs.map → impl-DAkBsgQN.mjs.map} +1 -1
- package/dist/{impl-iGMjSniP.mjs → impl-DAu079Yl.mjs} +2 -2
- package/dist/{impl-iGMjSniP.mjs.map → impl-DAu079Yl.mjs.map} +1 -1
- package/dist/{impl-BKrNGF2F.mjs → impl-DTaM3UE3.mjs} +2 -2
- package/dist/{impl-BKrNGF2F.mjs.map → impl-DTaM3UE3.mjs.map} +1 -1
- package/dist/{impl-CnHiD4zU.mjs → impl-DWiE5RsV.mjs} +2 -2
- package/dist/{impl-CnHiD4zU.mjs.map → impl-DWiE5RsV.mjs.map} +1 -1
- package/dist/{impl-CODwodEc.mjs → impl-DXHqqWJb.mjs} +2 -2
- package/dist/{impl-CODwodEc.mjs.map → impl-DXHqqWJb.mjs.map} +1 -1
- package/dist/impl-DZicly6r.mjs +2 -0
- package/dist/{impl-BVHfSIVG.mjs.map → impl-DZicly6r.mjs.map} +1 -1
- package/dist/{impl-CvJtt8H2.mjs → impl-DbGCApR_.mjs} +2 -2
- package/dist/{impl-CvJtt8H2.mjs.map → impl-DbGCApR_.mjs.map} +1 -1
- package/dist/{impl-BxOydpyJ.mjs → impl-DgG4lZ9T.mjs} +2 -2
- package/dist/{impl-BxOydpyJ.mjs.map → impl-DgG4lZ9T.mjs.map} +1 -1
- package/dist/{impl-DpwyYsfg.mjs → impl-Dik9I7Bz.mjs} +2 -2
- package/dist/{impl-DpwyYsfg.mjs.map → impl-Dik9I7Bz.mjs.map} +1 -1
- package/dist/impl-Djlx-Dqj.mjs +2 -0
- package/dist/impl-Djlx-Dqj.mjs.map +1 -0
- package/dist/{impl-CC0rkA9s.mjs → impl-DmQAAT-u.mjs} +2 -2
- package/dist/{impl-CC0rkA9s.mjs.map → impl-DmQAAT-u.mjs.map} +1 -1
- package/dist/{impl-C3DXXn8M.mjs → impl-DpuPyy-w.mjs} +2 -2
- package/dist/{impl-C3DXXn8M.mjs.map → impl-DpuPyy-w.mjs.map} +1 -1
- package/dist/{impl-C-u5h8We.mjs → impl-Du8quB1O.mjs} +2 -2
- package/dist/{impl-C-u5h8We.mjs.map → impl-Du8quB1O.mjs.map} +1 -1
- package/dist/{impl-BRiRfzgu.mjs → impl-OxHej0UO.mjs} +2 -2
- package/dist/{impl-BRiRfzgu.mjs.map → impl-OxHej0UO.mjs.map} +1 -1
- package/dist/{impl-DJ4VCAcc.mjs → impl-c7VvcNpZ.mjs} +2 -2
- package/dist/{impl-DJ4VCAcc.mjs.map → impl-c7VvcNpZ.mjs.map} +1 -1
- package/dist/{impl-DvrSuAJv.mjs → impl-fZQxhZRu.mjs} +2 -2
- package/dist/{impl-DvrSuAJv.mjs.map → impl-fZQxhZRu.mjs.map} +1 -1
- package/dist/{impl-DpGVNllB.mjs → impl-xtlx25UP.mjs} +2 -2
- package/dist/{impl-DpGVNllB.mjs.map → impl-xtlx25UP.mjs.map} +1 -1
- package/dist/{impl-Cw10WeUv.mjs → impl-yMumZUUX.mjs} +2 -2
- package/dist/{impl-Cw10WeUv.mjs.map → impl-yMumZUUX.mjs.map} +1 -1
- package/dist/index.d.mts +895 -1698
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +4 -4
- package/dist/index.mjs.map +1 -1
- package/dist/{inquirer-DyRwhvoh.mjs → inquirer-BqZXFEt1.mjs} +2 -2
- package/dist/{inquirer-DyRwhvoh.mjs.map → inquirer-BqZXFEt1.mjs.map} +1 -1
- package/dist/{listFiles-Odj7j2E1.mjs → listFiles-D2wMHnEr.mjs} +1 -1
- package/dist/{listFiles-Odj7j2E1.mjs.map → listFiles-D2wMHnEr.mjs.map} +1 -1
- package/dist/markRequestDataSiloIdsCompleted-sDBo1vUD.mjs +2 -0
- package/dist/markRequestDataSiloIdsCompleted-sDBo1vUD.mjs.map +1 -0
- package/dist/{markSilentPrivacyRequests-ytCzpUkY.mjs → markSilentPrivacyRequests-Cmn1fxHI.mjs} +2 -2
- package/dist/{markSilentPrivacyRequests-ytCzpUkY.mjs.map → markSilentPrivacyRequests-Cmn1fxHI.mjs.map} +1 -1
- package/dist/notifyPrivacyRequestsAdditionalTime-CmhFE4b0.mjs +2 -0
- package/dist/notifyPrivacyRequestsAdditionalTime-CmhFE4b0.mjs.map +1 -0
- package/dist/{parquetToCsvOneFile-bgEgRoAi.mjs → parquetToCsvOneFile-B84XXInh.mjs} +1 -1
- package/dist/{parquetToCsvOneFile-bgEgRoAi.mjs.map → parquetToCsvOneFile-B84XXInh.mjs.map} +1 -1
- package/dist/{parseAttributesFromString-B8h4DudO.mjs → parseAttributesFromString-D1Yl0xwT.mjs} +2 -2
- package/dist/{parseAttributesFromString-B8h4DudO.mjs.map → parseAttributesFromString-D1Yl0xwT.mjs.map} +1 -1
- package/dist/parseVariablesFromString-BeKOGw5n.mjs +3 -0
- package/dist/parseVariablesFromString-BeKOGw5n.mjs.map +1 -0
- package/dist/pullAllDatapoints-Bbmky50p.mjs +45 -0
- package/dist/pullAllDatapoints-Bbmky50p.mjs.map +1 -0
- package/dist/pullChunkedCustomSiloOutstandingIdentifiers-QRET4M0x.mjs +2 -0
- package/dist/pullChunkedCustomSiloOutstandingIdentifiers-QRET4M0x.mjs.map +1 -0
- package/dist/{pullConsentManagerMetrics-BO0hYPDG.mjs → pullConsentManagerMetrics-zKgjc3Ap.mjs} +1 -1
- package/dist/{pullConsentManagerMetrics-BO0hYPDG.mjs.map → pullConsentManagerMetrics-zKgjc3Ap.mjs.map} +1 -1
- package/dist/pullManualEnrichmentIdentifiersToCsv-8I6PgBQc.mjs +2 -0
- package/dist/pullManualEnrichmentIdentifiersToCsv-8I6PgBQc.mjs.map +1 -0
- package/dist/pullTranscendConfiguration-DjOELnPo.mjs +58 -0
- package/dist/pullTranscendConfiguration-DjOELnPo.mjs.map +1 -0
- package/dist/{pullUnstructuredSubDataPointRecommendations-jE-tdoVK.mjs → pullUnstructuredSubDataPointRecommendations-D0z-vPgq.mjs} +3 -3
- package/dist/{pullUnstructuredSubDataPointRecommendations-jE-tdoVK.mjs.map → pullUnstructuredSubDataPointRecommendations-D0z-vPgq.mjs.map} +1 -1
- package/dist/{pushCronIdentifiersFromCsv-D9Hzna0W.mjs → pushCronIdentifiersFromCsv-CBb2FvPD.mjs} +2 -2
- package/dist/{pushCronIdentifiersFromCsv-D9Hzna0W.mjs.map → pushCronIdentifiersFromCsv-CBb2FvPD.mjs.map} +1 -1
- package/dist/{pushManualEnrichmentIdentifiersFromCsv-BiR7PS_d.mjs → pushManualEnrichmentIdentifiersFromCsv-DYQq7hsN.mjs} +2 -2
- package/dist/{pushManualEnrichmentIdentifiersFromCsv-BiR7PS_d.mjs.map → pushManualEnrichmentIdentifiersFromCsv-DYQq7hsN.mjs.map} +1 -1
- package/dist/{readCsv-0PIlJQCN.mjs → readCsv-C4TyEs-r.mjs} +1 -1
- package/dist/{readCsv-0PIlJQCN.mjs.map → readCsv-C4TyEs-r.mjs.map} +1 -1
- package/dist/removeUnverifiedRequestIdentifiers-VCbL2BXD.mjs +2 -0
- package/dist/removeUnverifiedRequestIdentifiers-VCbL2BXD.mjs.map +1 -0
- package/dist/{request-SLqRySNU.mjs → request-DfkRPQFr.mjs} +1 -1
- package/dist/{request-SLqRySNU.mjs.map → request-DfkRPQFr.mjs.map} +1 -1
- package/dist/retryRequestDataSilos-BCe-WGdL.mjs +2 -0
- package/dist/retryRequestDataSilos-BCe-WGdL.mjs.map +1 -0
- package/dist/skipPreflightJobs-Bc0--Bvs.mjs +2 -0
- package/dist/skipPreflightJobs-Bc0--Bvs.mjs.map +1 -0
- package/dist/skipRequestDataSilos-BHbAQkpb.mjs +2 -0
- package/dist/skipRequestDataSilos-BHbAQkpb.mjs.map +1 -0
- package/dist/streamPrivacyRequestsToCsv-eB3gNhol.mjs +2 -0
- package/dist/streamPrivacyRequestsToCsv-eB3gNhol.mjs.map +1 -0
- package/dist/{syncCodePackages-BOS5foh6.mjs → syncCodePackages-CAk_Hjyl.mjs} +1 -1
- package/dist/{syncCodePackages-BOS5foh6.mjs.map → syncCodePackages-CAk_Hjyl.mjs.map} +1 -1
- package/dist/updateConsentManagerVersionToLatest-D6i1Xh6o.mjs +2 -0
- package/dist/updateConsentManagerVersionToLatest-D6i1Xh6o.mjs.map +1 -0
- package/dist/{uploadConsents-BP5XILuw.mjs → uploadConsents-BTM49EbZ.mjs} +2 -2
- package/dist/{uploadConsents-BP5XILuw.mjs.map → uploadConsents-BTM49EbZ.mjs.map} +1 -1
- package/dist/{uploadCookiesFromCsv-B42cZgYW.mjs → uploadCookiesFromCsv-DoC9rtEF.mjs} +2 -2
- package/dist/{uploadCookiesFromCsv-B42cZgYW.mjs.map → uploadCookiesFromCsv-DoC9rtEF.mjs.map} +1 -1
- package/dist/{uploadDataFlowsFromCsv-D2V567pP.mjs → uploadDataFlowsFromCsv-DL1-cAit.mjs} +2 -2
- package/dist/{uploadDataFlowsFromCsv-D2V567pP.mjs.map → uploadDataFlowsFromCsv-DL1-cAit.mjs.map} +1 -1
- package/dist/uploadPrivacyRequestsFromCsv-wXm4H4FH.mjs +2 -0
- package/dist/uploadPrivacyRequestsFromCsv-wXm4H4FH.mjs.map +1 -0
- package/dist/{validateTranscendAuth-DCwAtgvh.mjs → validateTranscendAuth-Cuh2Qfdl.mjs} +1 -1
- package/dist/{validateTranscendAuth-DCwAtgvh.mjs.map → validateTranscendAuth-Cuh2Qfdl.mjs.map} +1 -1
- package/dist/{writeCsv-Da8NUe1V.mjs → writeCsv-C4pjXGsD.mjs} +1 -1
- package/dist/{writeCsv-Da8NUe1V.mjs.map → writeCsv-C4pjXGsD.mjs.map} +1 -1
- package/package.json +8 -8
- package/dist/RequestDataSilo-Rrc2dL9g.mjs +0 -54
- package/dist/RequestDataSilo-Rrc2dL9g.mjs.map +0 -1
- package/dist/bulkRestartRequests-sie3tM3W.mjs +0 -2
- package/dist/bulkRestartRequests-sie3tM3W.mjs.map +0 -1
- package/dist/bulkRetryEnrichers-C1RrxiTR.mjs +0 -2
- package/dist/bulkRetryEnrichers-C1RrxiTR.mjs.map +0 -1
- package/dist/cancelPrivacyRequests-DmvFijq_.mjs +0 -2
- package/dist/cancelPrivacyRequests-DmvFijq_.mjs.map +0 -1
- package/dist/dataSilo-Dvi8-PkH.mjs +0 -302
- package/dist/dataSilo-Dvi8-PkH.mjs.map +0 -1
- package/dist/dataSubject-CF784Ug0.mjs +0 -92
- package/dist/dataSubject-CF784Ug0.mjs.map +0 -1
- package/dist/fetchAllRequestEnrichers-Bt97Bb7F.mjs +0 -42
- package/dist/fetchAllRequestEnrichers-Bt97Bb7F.mjs.map +0 -1
- package/dist/fetchAllRequestIdentifiers-BXx3rSee.mjs +0 -10
- package/dist/fetchAllRequestIdentifiers-BXx3rSee.mjs.map +0 -1
- package/dist/fetchRequestDataSilo-0UvyeL60.mjs +0 -2
- package/dist/fetchRequestDataSilo-0UvyeL60.mjs.map +0 -1
- package/dist/fetchRequestFilesForRequest-CJH2iB-P.mjs +0 -33
- package/dist/fetchRequestFilesForRequest-CJH2iB-P.mjs.map +0 -1
- package/dist/generateCrossAccountApiKeys-DztJoLQS.mjs +0 -2
- package/dist/generateCrossAccountApiKeys-DztJoLQS.mjs.map +0 -1
- package/dist/impl-BGGm947r2.mjs.map +0 -1
- package/dist/impl-BVHfSIVG.mjs +0 -2
- package/dist/impl-BfeWet_F2.mjs +0 -2
- package/dist/impl-BfeWet_F2.mjs.map +0 -1
- package/dist/impl-Cy8-6_Oo2.mjs.map +0 -1
- package/dist/impl-D_AxguFh2.mjs.map +0 -1
- package/dist/impl-Dw9uW5zy2.mjs.map +0 -1
- package/dist/impl-PdIU1pLr2.mjs +0 -2
- package/dist/impl-PdIU1pLr2.mjs.map +0 -1
- package/dist/impl-daUiLV3c.mjs +0 -2
- package/dist/impl-daUiLV3c.mjs.map +0 -1
- package/dist/markRequestDataSiloIdsCompleted-DJSICILv.mjs +0 -2
- package/dist/markRequestDataSiloIdsCompleted-DJSICILv.mjs.map +0 -1
- package/dist/notifyPrivacyRequestsAdditionalTime-D8v68eAg.mjs +0 -2
- package/dist/notifyPrivacyRequestsAdditionalTime-D8v68eAg.mjs.map +0 -1
- package/dist/parseVariablesFromString-CvoeZZ75.mjs +0 -23
- package/dist/parseVariablesFromString-CvoeZZ75.mjs.map +0 -1
- package/dist/pullAllDatapoints-CqgqXRbp.mjs +0 -45
- package/dist/pullAllDatapoints-CqgqXRbp.mjs.map +0 -1
- package/dist/pullChunkedCustomSiloOutstandingIdentifiers-DaYEDZ66.mjs +0 -2
- package/dist/pullChunkedCustomSiloOutstandingIdentifiers-DaYEDZ66.mjs.map +0 -1
- package/dist/pullManualEnrichmentIdentifiersToCsv-BNuhsG20.mjs +0 -2
- package/dist/pullManualEnrichmentIdentifiersToCsv-BNuhsG20.mjs.map +0 -1
- package/dist/pullTranscendConfiguration-DSyMRyPe.mjs +0 -58
- package/dist/pullTranscendConfiguration-DSyMRyPe.mjs.map +0 -1
- package/dist/removeUnverifiedRequestIdentifiers-B0Gx09XN.mjs +0 -35
- package/dist/removeUnverifiedRequestIdentifiers-B0Gx09XN.mjs.map +0 -1
- package/dist/retryRequestDataSilos-DFjFhhC0.mjs +0 -2
- package/dist/retryRequestDataSilos-DFjFhhC0.mjs.map +0 -1
- package/dist/skipPreflightJobs-Bm8lZZk-.mjs +0 -2
- package/dist/skipPreflightJobs-Bm8lZZk-.mjs.map +0 -1
- package/dist/skipRequestDataSilos-B5FByYTj.mjs +0 -2
- package/dist/skipRequestDataSilos-B5FByYTj.mjs.map +0 -1
- package/dist/streamPrivacyRequestsToCsv-CBzh80oQ.mjs +0 -2
- package/dist/streamPrivacyRequestsToCsv-CBzh80oQ.mjs.map +0 -1
- package/dist/syncEnrichers-C9HcWCrs.mjs +0 -3
- package/dist/syncEnrichers-C9HcWCrs.mjs.map +0 -1
- package/dist/updateConsentManagerVersionToLatest-X1HAM_IX.mjs +0 -2
- package/dist/updateConsentManagerVersionToLatest-X1HAM_IX.mjs.map +0 -1
- package/dist/uploadPrivacyRequestsFromCsv-Czc3vGfJ.mjs +0 -2
- package/dist/uploadPrivacyRequestsFromCsv-Czc3vGfJ.mjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pullTranscendConfiguration-DSyMRyPe.mjs","names":[],"sources":["../src/lib/graphql/gqls/assessmentTemplate.ts","../src/lib/graphql/fetchAllAssessmentTemplates.ts","../src/lib/graphql/formatAttributeValues.ts","../src/lib/graphql/pullTranscendConfiguration.ts"],"sourcesContent":["import { ASSESSMENT_SECTION_FIELDS } from '@transcend-io/sdk';\nimport { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\n// orderBy: [\n// { field: createdAt, direction: ASC }\n// { field: name, direction: ASC }\n// ]\nexport const ASSESSMENT_TEMPLATES = gql`\n query TranscendCliAssessmentTemplates(\n $first: Int!\n $offset: Int!\n $filterBy: AssessmentFormTemplateFiltersInput\n ) {\n assessmentFormTemplates(\n first: $first\n offset: $offset\n filterBy: $filterBy\n ) {\n nodes {\n id\n creator {\n id\n email\n name\n }\n lastEditor {\n id\n email\n name\n }\n title\n description\n status\n source\n parentId\n isLocked\n isArchived\n createdAt\n updatedAt\n retentionSchedule {\n id\n type\n durationDays\n operation\n createdAt\n updatedAt\n }\n assessmentEmailSet {\n id\n title\n description\n isDefault\n templates {\n id\n title\n }\n }\n sections {\n ${ASSESSMENT_SECTION_FIELDS}\n }\n }\n }\n }\n`;\n","import {\n AssessmentFormTemplateSource,\n AssessmentFormTemplateStatus,\n} from '@transcend-io/privacy-types';\nimport {\n makeGraphQLRequest,\n type AssessmentSection,\n type RetentionSchedule,\n type UserPreview,\n} from '@transcend-io/sdk';\nimport { GraphQLClient } from 'graphql-request';\n\nimport { logger } from '../../logger.js';\nimport { ASSESSMENT_TEMPLATES } from './gqls/index.js';\n\n/**\n * Represents an assessment template with various properties and metadata.\n */\nexport interface AssessmentTemplate {\n /** The ID of the assessment template */\n id: string;\n /** The user who created the assessment template */\n creator: UserPreview;\n /** The user who last edited the assessment template */\n lastEditor: UserPreview;\n /** The title of the assessment template */\n title: string;\n /** The description of the assessment template */\n description: string;\n /** The current status of the assessment template */\n status: AssessmentFormTemplateStatus;\n /** The source fo the form template */\n source: AssessmentFormTemplateSource;\n /** ID of parent template */\n parentId: string;\n /** Indicates if the assessment template is locked */\n isLocked: boolean;\n /** Indicates if the assessment template is archived */\n isArchived: boolean;\n /** The date when the assessment template was created */\n createdAt: string;\n /** The date when the assessment template was last updated */\n updatedAt: string;\n /** The retention schedule of the assessment template */\n retentionSchedule?: RetentionSchedule;\n /** The sections of the assessment template */\n sections: AssessmentSection[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all assessment templates in the organization\n *\n * @param client - GraphQL client\n * @returns All assessment templates in the organization\n */\nexport async function fetchAllAssessmentTemplates(\n client: GraphQLClient,\n): Promise<AssessmentTemplate[]> {\n const assessmentTemplates: AssessmentTemplate[] = [];\n let offset = 0;\n\n let shouldContinue = false;\n do {\n const {\n assessmentFormTemplates: { nodes },\n } = await makeGraphQLRequest<{\n /** Templates */\n assessmentFormTemplates: {\n /** Nodes */\n nodes: AssessmentTemplate[];\n };\n }>(client, ASSESSMENT_TEMPLATES, {\n variables: { first: PAGE_SIZE, offset },\n logger,\n });\n assessmentTemplates.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return assessmentTemplates.sort((a, b) => a.title.localeCompare(b.title));\n}\n","import type { DataSiloAttributeValue } from './syncDataSilos.js';\n\nexport interface FormattedAttribute {\n /** Attribute key */\n key: string;\n /** Attribute values */\n values: string[];\n}\n\n/**\n * Format attribute value objects to key-pair values\n *\n * @param vals - Attribute values\n * @returns formatted attributes\n */\nexport function formatAttributeValues(vals: DataSiloAttributeValue[]): FormattedAttribute[] {\n const attributes: FormattedAttribute[] = [];\n\n vals.map((val) => {\n let foundKey = attributes.find((att) => att.key === val.attributeKey.name);\n\n if (foundKey === undefined) {\n foundKey = {\n key: val.attributeKey.name,\n values: [val.name],\n };\n attributes.push(foundKey);\n } else {\n foundKey.values.push(val.name);\n }\n return attributes;\n });\n\n return attributes;\n}\n","import { LocaleValue } from '@transcend-io/internationalization';\nimport {\n RequestAction,\n ConsentTrackerStatus,\n ActionItemCode,\n RetentionType,\n} from '@transcend-io/privacy-types';\nimport {\n fetchAllActionItemCollections,\n fetchAllActionItems,\n fetchAllActions,\n fetchAllAgentFiles,\n fetchAllAgentFunctions,\n fetchAllAgents,\n fetchAllAssessments,\n fetchAllAttributes,\n fetchAllBusinessEntities,\n fetchAllCookies,\n fetchAllDataCategories,\n fetchAllDataFlows,\n fetchAllPolicies,\n fetchAllPrivacyCenters,\n fetchAllProcessingPurposes,\n fetchAllSiloDiscoveryResults,\n fetchAllTemplates,\n fetchConsentManager,\n fetchConsentManagerExperiences,\n fetchConsentManagerTheme,\n fetchAllIdentifiers,\n fetchAllMessages,\n fetchAllPromptGroups,\n fetchAllPromptPartials,\n fetchAllProcessingActivities,\n fetchAllPrompts,\n fetchAllPurposesAndPreferences,\n fetchPartitions,\n fetchAllTeams,\n fetchAllVendors,\n fetchApiKeys,\n formatRegions,\n parseAssessmentDisplayLogic,\n parseAssessmentRiskLogic,\n type AssessmentRule,\n} from '@transcend-io/sdk';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { flatten, keyBy, mapValues } from 'lodash-es';\n\n/* eslint-disable max-lines */\nimport {\n TranscendInput,\n ApiKeyInput,\n DataSiloInput,\n AttributeInput,\n ActionInput,\n IdentifierInput,\n BusinessEntityInput,\n EnricherInput,\n PromptGroupInput,\n DataFlowInput,\n PromptPartialInput,\n DataSubjectInput,\n CookieInput,\n PromptInput,\n DatapointInput,\n FieldInput,\n ProcessingPurposeInput,\n ProcessingActivityInput,\n DataCategoryInput,\n VendorInput,\n AgentFileInput,\n AgentFunctionInput,\n AgentInput,\n PolicyInput,\n IntlMessageInput,\n ActionItemInput,\n TeamInput,\n ActionItemCollectionInput,\n AssessmentInput,\n AssessmentTemplateInput,\n AssessmentSectionInput,\n AssessmentSectionQuestionInput,\n RiskLogicInput,\n ConsentPurpose,\n type SiloDiscoveryResultInput,\n} from '../../codecs.js';\nimport { TranscendPullResource } from '../../enums.js';\nimport { logger } from '../../logger.js';\nimport { fetchAllAssessmentTemplates } from './fetchAllAssessmentTemplates.js';\nimport { convertToDataSubjectAllowlist, fetchAllDataSubjects } from './fetchDataSubjects.js';\nimport { formatAttributeValues } from './formatAttributeValues.js';\nimport { fetchEnrichedDataSilos } from './syncDataSilos.js';\nimport { fetchAllEnrichers } from './syncEnrichers.js';\n\nexport const DEFAULT_TRANSCEND_PULL_RESOURCES = [\n TranscendPullResource.DataSilos,\n TranscendPullResource.Enrichers,\n TranscendPullResource.Templates,\n TranscendPullResource.ApiKeys,\n];\n\nexport interface TranscendPullConfigurationInput {\n /** Page size */\n pageSize: number;\n /** Enable debug logs */\n debug: boolean;\n /** The data silo IDs to sync. If empty list, pull all. */\n dataSiloIds: string[];\n /** Resources to pull in */\n resources?: TranscendPullResource[];\n /** The data silo types to sync.If empty list, pull all. */\n integrationNames: string[];\n /** The tracker statuses to pull */\n trackerStatuses?: ConsentTrackerStatus[];\n /** Skip fetching of datapoints */\n skipDatapoints?: boolean;\n /** Skip fetching of subdatapoints */\n skipSubDatapoints?: boolean;\n /** When true, metadata around guessed data categories should be included */\n includeGuessedCategories?: boolean;\n}\n\n/**\n * Pull a yaml configuration from Transcend\n *\n * @param client - GraphQL client\n * @param dataSiloIds - The data silos to sync. If empty list, pull all.\n * @returns The configuration\n */\nexport async function pullTranscendConfiguration(\n client: GraphQLClient,\n {\n dataSiloIds,\n integrationNames,\n debug,\n resources = DEFAULT_TRANSCEND_PULL_RESOURCES,\n pageSize,\n skipDatapoints,\n includeGuessedCategories,\n skipSubDatapoints,\n trackerStatuses = Object.values(ConsentTrackerStatus),\n }: TranscendPullConfigurationInput,\n): Promise<TranscendInput> {\n if (dataSiloIds.length > 0 && integrationNames.length > 0) {\n throw new Error('Only 1 of integrationNames OR dataSiloIds can be provided');\n }\n\n logger.info(colors.magenta(`Fetching data with page size ${pageSize}...`));\n\n // Fetch all data, but only conditional fetch data that is requested\n const [\n dataSubjects,\n apiKeyTitleMap,\n dataSilos,\n enrichers,\n dataFlows,\n cookies,\n attributes,\n templates,\n identifiers,\n actions,\n businessEntities,\n processingActivities,\n consentManager,\n consentManagerExperiences,\n prompts,\n promptPartials,\n promptGroups,\n agents,\n agentFunctions,\n agentFiles,\n vendors,\n dataCategories,\n processingPurposes,\n actionItems,\n actionItemCollections,\n teams,\n policies,\n privacyCenters,\n messages,\n partitions,\n assessments,\n assessmentTemplates,\n purposes,\n siloDiscoveryResults,\n ] = await Promise.all([\n // Grab all data subjects in the organization\n resources.includes(TranscendPullResource.DataSilos) ||\n resources.includes(TranscendPullResource.DataSubjects)\n ? fetchAllDataSubjects(client)\n : [],\n // Grab API keys\n resources.includes(TranscendPullResource.ApiKeys)\n ? fetchApiKeys({}, client, true, { logger })\n : [],\n // Fetch the data silos\n resources.includes(TranscendPullResource.DataSilos)\n ? fetchEnrichedDataSilos(client, {\n ids: dataSiloIds,\n integrationNames,\n pageSize,\n debug,\n includeGuessedCategories,\n skipDatapoints,\n skipSubDatapoints,\n })\n : [],\n // Fetch enrichers\n resources.includes(TranscendPullResource.Enrichers) ? fetchAllEnrichers(client) : [],\n // Fetch data flows\n resources.includes(TranscendPullResource.DataFlows)\n ? [\n ...(trackerStatuses.includes(ConsentTrackerStatus.Live)\n ? await fetchAllDataFlows(client, ConsentTrackerStatus.Live, { logger })\n : []),\n ...(trackerStatuses.includes(ConsentTrackerStatus.NeedsReview)\n ? await fetchAllDataFlows(client, ConsentTrackerStatus.NeedsReview, { logger })\n : []),\n ]\n : [],\n // Fetch data flows\n resources.includes(TranscendPullResource.Cookies)\n ? [\n ...(trackerStatuses.includes(ConsentTrackerStatus.Live)\n ? await fetchAllCookies(client, ConsentTrackerStatus.Live, { logger })\n : []),\n ...(trackerStatuses.includes(ConsentTrackerStatus.NeedsReview)\n ? await fetchAllCookies(client, ConsentTrackerStatus.NeedsReview, { logger })\n : []),\n ]\n : [],\n // Fetch attributes\n resources.includes(TranscendPullResource.Attributes)\n ? fetchAllAttributes(client, { logger })\n : [],\n // Fetch email templates\n resources.includes(TranscendPullResource.Templates)\n ? fetchAllTemplates(client, { logger })\n : [],\n // Fetch identifiers\n resources.includes(TranscendPullResource.Identifiers)\n ? fetchAllIdentifiers(client, { logger })\n : [],\n // Fetch actions\n resources.includes(TranscendPullResource.Actions) ? fetchAllActions(client, { logger }) : [],\n // Fetch business entities\n resources.includes(TranscendPullResource.BusinessEntities)\n ? fetchAllBusinessEntities(client, { logger })\n : [],\n // Fetch processing activities\n resources.includes(TranscendPullResource.ProcessingActivities)\n ? fetchAllProcessingActivities(client, { logger })\n : [],\n // Fetch consent manager\n resources.includes(TranscendPullResource.ConsentManager)\n ? fetchConsentManager(client, { logger })\n : undefined,\n // Fetch consent manager experiences\n resources.includes(TranscendPullResource.ConsentManager)\n ? fetchConsentManagerExperiences(client, { logger })\n : [],\n // Fetch prompts\n resources.includes(TranscendPullResource.Prompts) ? fetchAllPrompts(client, { logger }) : [],\n // Fetch promptPartials\n resources.includes(TranscendPullResource.PromptPartials)\n ? fetchAllPromptPartials(client, { logger })\n : [],\n // Fetch promptGroups\n resources.includes(TranscendPullResource.PromptGroups)\n ? fetchAllPromptGroups(client, { logger })\n : [],\n // Fetch agents\n resources.includes(TranscendPullResource.Agents) ? fetchAllAgents(client, { logger }) : [],\n // Fetch agentFunctions\n resources.includes(TranscendPullResource.AgentFunctions)\n ? fetchAllAgentFunctions(client, { logger })\n : [],\n // Fetch agentFiles\n resources.includes(TranscendPullResource.AgentFiles)\n ? fetchAllAgentFiles(client, { logger })\n : [],\n // Fetch vendors\n resources.includes(TranscendPullResource.Vendors) ? fetchAllVendors(client, { logger }) : [],\n // Fetch dataCategories\n resources.includes(TranscendPullResource.DataCategories)\n ? fetchAllDataCategories(client, { logger })\n : [],\n // Fetch dataCategories\n resources.includes(TranscendPullResource.ProcessingPurposes)\n ? fetchAllProcessingPurposes(client, { logger })\n : [],\n // Fetch actionItems\n resources.includes(TranscendPullResource.ActionItems)\n ? fetchAllActionItems(client, {\n logger,\n filterBy: { type: [ActionItemCode.Onboarding] },\n })\n : [],\n // Fetch actionItemCollections\n resources.includes(TranscendPullResource.ActionItemCollections)\n ? fetchAllActionItemCollections(client, { logger })\n : [],\n // Fetch teams\n resources.includes(TranscendPullResource.Teams) ? fetchAllTeams(client, { logger }) : [],\n // Fetch policies\n resources.includes(TranscendPullResource.Policies) ? fetchAllPolicies(client, { logger }) : [],\n // Fetch privacy centers\n resources.includes(TranscendPullResource.PrivacyCenters)\n ? fetchAllPrivacyCenters(client, { logger })\n : [],\n // Fetch messages\n resources.includes(TranscendPullResource.Messages) ? fetchAllMessages(client, { logger }) : [],\n // Fetch partitions\n resources.includes(TranscendPullResource.Partitions) ? fetchPartitions(client, { logger }) : [],\n // Fetch assessments\n resources.includes(TranscendPullResource.Assessments)\n ? fetchAllAssessments(client, { logger })\n : [],\n // Fetch assessmentTemplates\n resources.includes(TranscendPullResource.AssessmentTemplates)\n ? fetchAllAssessmentTemplates(client)\n : [],\n // Fetch purpose and preferences\n resources.includes(TranscendPullResource.Purposes)\n ? fetchAllPurposesAndPreferences(client, { logger })\n : [],\n // Fetch silo discovery results\n resources.includes(TranscendPullResource.SystemDiscovery)\n ? fetchAllSiloDiscoveryResults(client, { logger })\n : [],\n ]);\n\n const consentManagerTheme =\n resources.includes(TranscendPullResource.ConsentManager) && consentManager\n ? await fetchConsentManagerTheme(client, consentManager.id, { logger })\n : undefined;\n\n const result: TranscendInput = {};\n\n // Save API keys\n const apiKeyTitles = flatten(dataSilos.map(([{ apiKeys }]) => apiKeys.map(({ title }) => title)));\n const relevantApiKeys = Object.values(apiKeyTitleMap).filter(({ title }) =>\n resources.includes(TranscendPullResource.ApiKeys) ? true : apiKeyTitles.includes(title),\n );\n if (relevantApiKeys.length > 0 && resources.includes(TranscendPullResource.ApiKeys)) {\n result['api-keys'] = relevantApiKeys.map(\n ({ title }): ApiKeyInput => ({\n title,\n }),\n );\n }\n\n // Save Partitions\n if (partitions.length > 0 && resources.includes(TranscendPullResource.Partitions)) {\n result.partitions = partitions.map(({ name, partition }) => ({\n name,\n partition,\n }));\n }\n\n // Save Consent Manager\n if (consentManager && resources.includes(TranscendPullResource.ConsentManager)) {\n result['consent-manager'] = {\n bundleUrls: {\n TEST: consentManager.testBundleURL,\n PRODUCTION: consentManager.bundleURL,\n },\n domains: consentManager.configuration.domains || undefined,\n partition: consentManager.configuration.partition || undefined,\n consentPrecedence: consentManager.configuration.consentPrecedence || undefined,\n unknownRequestPolicy: consentManager.configuration.unknownRequestPolicy || undefined,\n unknownCookiePolicy: consentManager.configuration.unknownCookiePolicy || undefined,\n syncEndpoint: consentManager.configuration.syncEndpoint || undefined,\n telemetryPartitioning: consentManager.configuration.telemetryPartitioning || undefined,\n signedIabAgreement: consentManager.configuration.signedIabAgreement || undefined,\n // TODO: https://transcend.height.app/T-23919 - reconsider simpler yml shape\n syncGroups: consentManager.configuration.syncGroups || undefined,\n theme: !consentManagerTheme\n ? undefined\n : {\n primaryColor: consentManagerTheme.primaryColor || undefined,\n fontColor: consentManagerTheme.fontColor || undefined,\n privacyPolicy: consentManagerTheme.privacyPolicy || undefined,\n prompt: consentManagerTheme.prompt,\n },\n experiences: consentManagerExperiences.map((experience) => ({\n name: experience.name,\n displayName: experience.displayName || undefined,\n regions: experience.regions.map((region) => ({\n countrySubDivision: region.countrySubDivision || undefined,\n country: region.country || undefined,\n })),\n onConsentExpiry: experience.onConsentExpiry,\n consentExpiry: experience.consentExpiry,\n operator: experience.operator,\n displayPriority: experience.displayPriority,\n viewState: experience.viewState,\n purposes: experience.purposes.map((purpose) => ({\n trackingType: purpose.trackingType,\n })),\n optedOutPurposes: experience.optedOutPurposes.map((purpose) => ({\n trackingType: purpose.trackingType,\n })),\n browserLanguages: experience.browserLanguages,\n browserTimeZones: experience.browserTimeZones,\n })),\n };\n }\n\n // Save assessments\n if (assessments.length > 0 && resources.includes(TranscendPullResource.Assessments)) {\n result.assessments = assessments.map(\n ({\n title,\n assessmentGroup,\n sections,\n creator,\n description,\n status,\n assignees,\n externalAssignees,\n reviewers,\n isLocked,\n isArchived,\n isExternallyCreated,\n dueDate,\n createdAt,\n assignedAt,\n submittedAt,\n approvedAt,\n rejectedAt,\n titleIsInternal,\n retentionSchedule,\n attributeValues,\n resources,\n syncedRows,\n }): AssessmentInput => ({\n title,\n group: assessmentGroup.title,\n sections: sections.map(\n ({\n title,\n status,\n questions,\n assignees,\n isReviewed,\n externalAssignees,\n }): AssessmentSectionInput => ({\n title,\n status,\n questions: questions.map(\n ({\n title,\n type,\n subType,\n placeholder,\n description,\n isRequired,\n referenceId,\n displayLogic,\n riskLogic,\n riskCategories,\n riskFramework,\n answerOptions,\n selectedAnswers,\n allowedMimeTypes,\n allowSelectOther,\n syncModel,\n syncColumn,\n attributeKey,\n requireRiskEvaluation,\n requireRiskMatrixEvaluation,\n }): AssessmentSectionQuestionInput => {\n const displayLogicParsed = displayLogic\n ? parseAssessmentDisplayLogic(displayLogic)\n : undefined;\n return {\n title,\n type,\n 'sub-type': subType,\n placeholder,\n description,\n 'is-required': isRequired,\n 'reference-id': referenceId,\n 'display-logic':\n displayLogicParsed && Object.keys(displayLogicParsed).length > 0\n ? {\n action: displayLogicParsed.action!,\n rule: displayLogicParsed.rule\n ? {\n 'depends-on-question-reference-id':\n displayLogicParsed.rule.dependsOnQuestionReferenceId,\n 'comparison-operator': displayLogicParsed.rule.comparisonOperator,\n 'comparison-operands':\n // Safely access property with a check\n 'comparisonOperands' in displayLogicParsed.rule\n ? displayLogicParsed.rule.comparisonOperands\n : undefined,\n }\n : undefined,\n 'nested-rule': displayLogicParsed.nestedRule\n ? {\n 'logic-operator': displayLogicParsed.nestedRule.logicOperator,\n rules: (displayLogicParsed.nestedRule.rules || []).map(\n (rule: AssessmentRule) => ({\n 'depends-on-question-reference-id':\n rule.dependsOnQuestionReferenceId,\n 'comparison-operator': rule.comparisonOperator,\n 'comparison-operands':\n // Safely access property on the nested rule\n 'comparisonOperands' in rule\n ? rule.comparisonOperands\n : undefined,\n }),\n ),\n }\n : undefined,\n }\n : undefined,\n 'risk-logic': riskLogic.map((logic): RiskLogicInput => {\n const parsed = parseAssessmentRiskLogic(logic);\n return {\n 'risk-level': parsed.riskAssignment?.riskLevelId,\n 'comparison-operands': parsed.comparisonOperands,\n 'comparison-operator': parsed.comparisonOperator,\n };\n }),\n 'risk-categories': riskCategories.map(({ title }) => title),\n 'risk-framework': riskFramework?.title,\n 'answer-options': answerOptions.map(({ value }) => ({\n value,\n })),\n 'selected-answers': selectedAnswers.map(({ value }) => value),\n 'allowed-mime-types': allowedMimeTypes,\n 'allow-select-other': allowSelectOther,\n 'sync-model': syncModel || undefined,\n 'sync-column': syncColumn || undefined,\n 'attribute-key': attributeKey?.name,\n 'require-risk-evaluation': requireRiskEvaluation,\n 'require-risk-matrix-evaluation': requireRiskMatrixEvaluation,\n };\n },\n ),\n assignees: assignees.map(({ email }) => email),\n 'external-assignees': externalAssignees.map(({ email }) => email),\n 'is-reviewed': isReviewed,\n }),\n ),\n creator: creator?.email,\n description,\n status,\n assignees: assignees.map(({ email }) => email),\n 'external-assignees': externalAssignees.map(({ email }) => email),\n reviewers: reviewers.map(({ email }) => email),\n locked: isLocked,\n archived: isArchived,\n external: isExternallyCreated,\n 'title-is-internal': titleIsInternal,\n 'due-date': dueDate || undefined,\n 'created-at': createdAt || undefined,\n 'assigned-at': assignedAt || undefined,\n 'submitted-at': submittedAt || undefined,\n 'approved-at': approvedAt || undefined,\n 'rejected-at': rejectedAt || undefined,\n 'retention-schedule': retentionSchedule\n ? {\n type: retentionSchedule.type,\n 'duration-days': retentionSchedule.durationDays,\n operand: retentionSchedule.operation,\n }\n : undefined,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n resources: resources.map(({ resourceType, title, name, category, type, purpose }) => ({\n type: resourceType,\n title: category\n ? `${category} - ${name}`\n : purpose\n ? `${purpose} - ${name}`\n : title || name || type || '',\n })),\n rows: syncedRows.map(({ resourceType, title, name, category, type, purpose }) => ({\n type: resourceType,\n title: category\n ? `${category} - ${name}`\n : purpose\n ? `${purpose} - ${name}`\n : title || name || type || '',\n })),\n }),\n );\n }\n\n // Save assessmentTemplates\n if (\n assessmentTemplates.length > 0 &&\n resources.includes(TranscendPullResource.AssessmentTemplates)\n ) {\n result['assessment-templates'] = assessmentTemplates.map(\n ({\n title,\n description,\n sections,\n status,\n source,\n creator,\n isLocked,\n isArchived,\n createdAt,\n retentionSchedule,\n }): AssessmentTemplateInput => ({\n title,\n description,\n sections: sections.map(\n ({ title, questions }): AssessmentSectionInput => ({\n title,\n questions: questions.map(\n ({\n title,\n type,\n subType,\n placeholder,\n description,\n isRequired,\n referenceId,\n displayLogic,\n riskLogic,\n riskCategories,\n riskFramework,\n answerOptions,\n allowedMimeTypes,\n allowSelectOther,\n syncModel,\n syncColumn,\n attributeKey,\n requireRiskEvaluation,\n requireRiskMatrixEvaluation,\n }): AssessmentSectionQuestionInput => {\n const displayLogicParsed = displayLogic\n ? parseAssessmentDisplayLogic(displayLogic)\n : undefined;\n return {\n title,\n type,\n 'sub-type': subType,\n placeholder,\n description,\n 'is-required': isRequired,\n 'reference-id': referenceId,\n 'display-logic':\n displayLogicParsed && Object.keys(displayLogicParsed).length > 0\n ? {\n action: displayLogicParsed.action!,\n rule: displayLogicParsed.rule\n ? {\n 'depends-on-question-reference-id':\n displayLogicParsed.rule.dependsOnQuestionReferenceId,\n 'comparison-operator': displayLogicParsed.rule.comparisonOperator,\n 'comparison-operands':\n // Safely access property with a check\n 'comparisonOperands' in displayLogicParsed.rule\n ? displayLogicParsed.rule.comparisonOperands\n : undefined,\n }\n : undefined,\n 'nested-rule': displayLogicParsed.nestedRule\n ? {\n 'logic-operator': displayLogicParsed.nestedRule.logicOperator,\n rules: (displayLogicParsed.nestedRule.rules || []).map(\n (rule: AssessmentRule) => ({\n 'depends-on-question-reference-id':\n rule.dependsOnQuestionReferenceId,\n 'comparison-operator': rule.comparisonOperator,\n 'comparison-operands':\n // Safely access property on the nested rule\n 'comparisonOperands' in rule\n ? rule.comparisonOperands\n : undefined,\n }),\n ),\n }\n : undefined,\n }\n : undefined,\n 'risk-logic': riskLogic.map((logic): RiskLogicInput => {\n const parsed = parseAssessmentRiskLogic(logic);\n return {\n 'risk-level': parsed.riskAssignment?.riskLevelId,\n 'risk-matrix-row': parsed.riskAssignment?.riskMatrixRowId,\n 'risk-matrix-column': parsed.riskAssignment?.riskMatrixColumnId,\n 'comparison-operands': parsed.comparisonOperands,\n 'comparison-operator': parsed.comparisonOperator,\n };\n }),\n 'risk-categories': riskCategories.map(({ title }) => title),\n 'risk-framework': riskFramework?.title,\n 'answer-options': answerOptions.map(({ value }) => ({\n value,\n })),\n 'allowed-mime-types': allowedMimeTypes,\n 'allow-select-other': allowSelectOther,\n 'sync-model': syncModel || undefined,\n 'sync-column': syncColumn || undefined,\n 'attribute-key': attributeKey?.name,\n 'require-risk-evaluation': requireRiskEvaluation,\n 'require-risk-matrix-evaluation': requireRiskMatrixEvaluation,\n };\n },\n ),\n }),\n ),\n status,\n source,\n creator: creator?.email,\n locked: isLocked,\n archived: isArchived,\n 'created-at': createdAt || undefined,\n 'retention-schedule': retentionSchedule\n ? {\n type: retentionSchedule.type,\n 'duration-days': retentionSchedule.durationDays,\n operand: retentionSchedule.operation,\n }\n : undefined,\n }),\n );\n }\n\n // Save Silo Discovery Results\n if (\n siloDiscoveryResults.length > 0 &&\n resources.includes(TranscendPullResource.SystemDiscovery)\n ) {\n result['system-discovery'] = siloDiscoveryResults.map(\n ({\n title,\n resourceId,\n suggestedCatalog: { title: suggestedCatalogTitle },\n plugin: {\n dataSilo: { title: dataSiloTitle },\n },\n country,\n countrySubDivision,\n plaintextContext,\n containsSensitiveData,\n status,\n }): SiloDiscoveryResultInput => ({\n title,\n resourceId,\n suggestedCatalog: suggestedCatalogTitle,\n plugin: dataSiloTitle,\n country: country || undefined,\n countrySubDivision: countrySubDivision || undefined,\n plaintextContext,\n containsSensitiveData,\n status,\n }),\n );\n }\n\n // Save prompts\n if (prompts.length > 0 && resources.includes(TranscendPullResource.Prompts)) {\n result.prompts = prompts.map(\n ({ title, content }): PromptInput => ({\n title,\n content,\n }),\n );\n }\n\n // Save promptPartials\n if (promptPartials.length > 0 && resources.includes(TranscendPullResource.PromptPartials)) {\n result['prompt-partials'] = promptPartials.map(\n ({ title, content }): PromptPartialInput => ({\n title,\n content,\n }),\n );\n }\n\n // Save promptGroups\n if (promptGroups.length > 0 && resources.includes(TranscendPullResource.PromptGroups)) {\n result['prompt-groups'] = promptGroups.map(\n ({ title, description, prompts }): PromptGroupInput => ({\n title,\n description,\n prompts: prompts.map(({ title }) => title),\n }),\n );\n }\n\n // Save teams\n if (teams.length > 0 && resources.includes(TranscendPullResource.Teams)) {\n result.teams = teams.map(\n ({ name, description, ssoDepartment, ssoGroup, ssoTitle, users, scopes }): TeamInput => ({\n name,\n description,\n 'sso-department': ssoDepartment || undefined,\n 'sso-group': ssoGroup || undefined,\n 'sso-title': ssoTitle || undefined,\n users: users.map(({ email }) => email),\n scopes: scopes.map(({ name }) => name),\n }),\n );\n }\n\n // Save Data Subjects\n if (dataSubjects.length > 0 && resources.includes(TranscendPullResource.DataSubjects)) {\n result['data-subjects'] = dataSubjects.map(\n ({ type, title, active, adminDashboardDefaultSilentMode, actions }): DataSubjectInput => ({\n type,\n title: title?.defaultMessage,\n active,\n adminDashboardDefaultSilentMode,\n actions: actions.map(({ type }) => type),\n }),\n );\n }\n\n // Save privacy policies\n if (policies.length > 0) {\n result.policies = policies.map(\n ({ title, versions, disabledLocales }): PolicyInput => ({\n title: title?.defaultMessage,\n content: versions?.[0]?.content?.defaultMessage,\n disabledLocales,\n }),\n );\n }\n\n // Save messages\n if (messages.length > 0) {\n result.messages = messages.map(\n ({ id, defaultMessage, targetReactIntlId, description, translations }): IntlMessageInput => ({\n id,\n defaultMessage,\n description,\n targetReactIntlId: targetReactIntlId || undefined,\n translations: translations.reduce(\n (acc, { locale, value }) => Object.assign(acc, { [locale]: value }),\n {} as Record<LocaleValue, string>,\n ),\n }),\n );\n }\n\n // Save privacy center\n if (privacyCenters.length > 0) {\n const privacyCenter = privacyCenters[0];\n result['privacy-center'] = {\n isDisabled: privacyCenter.isDisabled,\n showPrivacyRequestButton: privacyCenter.showPrivacyRequestButton,\n showPolicies: privacyCenter.showPolicies,\n showTrackingTechnologies: privacyCenter.showTrackingTechnologies,\n showCookies: privacyCenter.showCookies,\n showDataFlows: privacyCenter.showDataFlows,\n showConsentManager: privacyCenter.showConsentManager,\n showManageYourPrivacy: privacyCenter.showManageYourPrivacy,\n showMarketingPreferences: privacyCenter.showMarketingPreferences,\n locales: privacyCenter.locales,\n defaultLocale: privacyCenter.defaultLocale,\n preferBrowserDefaultLocale: privacyCenter.preferBrowserDefaultLocale,\n supportEmail: privacyCenter.supportEmail || undefined,\n replyToEmail: privacyCenter.replyToEmail || undefined,\n useNoReplyEmailAddress: privacyCenter.useNoReplyEmailAddress,\n useCustomEmailDomain: privacyCenter.useCustomEmailDomain,\n transformAccessReportJsonToCsv: privacyCenter.transformAccessReportJsonToCsv,\n theme: privacyCenter.theme,\n };\n }\n\n // Save business entities\n if (businessEntities.length > 0 && resources.includes(TranscendPullResource.BusinessEntities)) {\n result['business-entities'] = businessEntities.map(\n ({\n title,\n description,\n address,\n headquarterCountry,\n headquarterSubDivision,\n dataProtectionOfficerName,\n dataProtectionOfficerEmail,\n attributeValues,\n }): BusinessEntityInput => ({\n title,\n description: description || undefined,\n address: address || undefined,\n headquarterCountry: headquarterCountry || undefined,\n headquarterSubDivision: headquarterSubDivision || undefined,\n dataProtectionOfficerName: dataProtectionOfficerName || undefined,\n dataProtectionOfficerEmail: dataProtectionOfficerEmail || undefined,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save processing activities\n if (\n processingActivities.length > 0 &&\n resources.includes(TranscendPullResource.ProcessingActivities)\n ) {\n result['processing-activities'] = processingActivities.map(\n ({\n title,\n description,\n securityMeasureDetails,\n controllerships,\n storageRegions,\n transferRegions,\n retentionType,\n retentionPeriod,\n dataProtectionImpactAssessmentLink,\n dataProtectionImpactAssessmentStatus,\n attributeValues,\n dataSilos,\n dataSubjects,\n teams,\n owners,\n processingPurposeSubCategories,\n dataSubCategories,\n saaSCategories,\n }): ProcessingActivityInput => ({\n title,\n description,\n securityMeasureDetails: securityMeasureDetails ?? undefined,\n controllerships: controllerships.length > 0 ? controllerships : undefined,\n storageRegions: storageRegions.length > 0 ? formatRegions(storageRegions) : undefined,\n transferRegions: transferRegions.length > 0 ? formatRegions(transferRegions) : undefined,\n retentionType,\n retentionPeriod: retentionType === RetentionType.StatedPeriod ? retentionPeriod : undefined,\n dataProtectionImpactAssessmentLink: dataProtectionImpactAssessmentLink ?? undefined,\n dataProtectionImpactAssessmentStatus,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n dataSiloTitles: dataSilos.length > 0 ? dataSilos.map(({ title }) => title) : undefined,\n dataSubjectTypes:\n dataSubjects.length > 0 ? dataSubjects.map(({ type }) => type) : undefined,\n teamNames: teams.length > 0 ? teams.map(({ name }) => name) : undefined,\n ownerEmails: owners.length > 0 ? owners.map(({ email }) => email) : undefined,\n processingSubPurposes:\n processingPurposeSubCategories.length > 0\n ? processingPurposeSubCategories.map(({ name, purpose }) => ({\n purpose,\n ...(name ? { name } : {}),\n }))\n : undefined,\n dataSubCategories:\n dataSubCategories.length > 0\n ? dataSubCategories.map(({ name, category }) => ({\n category,\n ...(name ? { name } : {}),\n }))\n : undefined,\n saaSCategories:\n saaSCategories.length > 0 ? saaSCategories.map(({ title }) => title) : undefined,\n }),\n );\n }\n\n // Save Actions\n if (actions.length > 0 && resources.includes(TranscendPullResource.Actions)) {\n result.actions = actions.map(\n ({\n type,\n skipSecondaryIfNoFiles,\n skipDownloadableStep,\n requiresReview,\n regionList,\n regionDetectionMethod,\n waitingPeriod,\n }): ActionInput => ({\n type,\n ...(type === RequestAction.Erasure\n ? {\n skipSecondaryIfNoFiles,\n skipDownloadableStep,\n }\n : {}),\n requiresReview,\n waitingPeriod,\n regionDetectionMethod,\n regionList: regionList.length > 0 ? regionList : undefined,\n }),\n );\n }\n\n // Save identifiers\n if (identifiers.length > 0 && resources.includes(TranscendPullResource.Identifiers)) {\n result.identifiers = identifiers.map(\n ({\n name,\n type,\n regex,\n selectOptions,\n privacyCenterVisibility,\n isRequiredInForm,\n placeholder,\n displayTitle,\n dataSubjects,\n displayDescription,\n displayOrder,\n isUniqueOnPreferenceStore,\n }): IdentifierInput => ({\n name,\n type,\n regex,\n selectOptions: selectOptions.length > 0 ? selectOptions : undefined,\n privacyCenterVisibility:\n privacyCenterVisibility.length > 0 ? privacyCenterVisibility : undefined,\n isRequiredInForm,\n placeholder: placeholder || undefined,\n dataSubjects: dataSubjects.length > 0 ? dataSubjects.map(({ type }) => type) : undefined,\n displayTitle: displayTitle?.defaultMessage,\n displayDescription: displayDescription?.defaultMessage,\n displayOrder,\n isUniqueOnPreferenceStore,\n }),\n );\n }\n\n // Save agents\n if (agents.length > 0 && resources.includes(TranscendPullResource.Agents)) {\n result.agents = agents.map(\n ({\n name,\n agentId,\n description,\n instructions,\n codeInterpreterEnabled,\n retrievalEnabled,\n prompt,\n largeLanguageModel,\n teams,\n owners,\n agentFunctions,\n agentFiles,\n }): AgentInput => ({\n name,\n agentId,\n description: description || undefined,\n instructions,\n codeInterpreterEnabled,\n retrievalEnabled,\n prompt: prompt?.title,\n 'large-language-model': {\n name: largeLanguageModel.name,\n client: largeLanguageModel.client,\n },\n teams: teams && teams.length > 0 ? teams.map(({ name }) => name) : undefined,\n owners: owners && owners.length > 0 ? owners.map(({ email }) => email) : undefined,\n 'agent-functions':\n agentFunctions && agentFunctions.length > 0\n ? agentFunctions.map(({ name }) => name)\n : undefined,\n 'agent-files':\n agentFiles && agentFiles.length > 0 ? agentFiles.map(({ name }) => name) : undefined,\n }),\n );\n }\n\n // Save action items\n if (actionItems.length > 0 && resources.includes(TranscendPullResource.ActionItems)) {\n result['action-items'] = actionItems.map(\n ({\n teams,\n users,\n customerExperienceActionItemIds: [customerExperienceActionItemId],\n dueDate,\n priority,\n resolved,\n collections,\n notes,\n link,\n title,\n type,\n attributeValues,\n }): ActionItemInput => ({\n teams: teams.map(({ name }) => name),\n users: users.map(({ email }) => email),\n dueDate: dueDate || undefined,\n title,\n notes,\n customerExperienceActionItemId,\n collections: collections.map(({ title }) => title),\n link,\n priority: priority || undefined,\n resolved,\n type,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save action item collections\n if (\n actionItemCollections.length > 0 &&\n resources.includes(TranscendPullResource.ActionItemCollections)\n ) {\n result['action-item-collections'] = actionItemCollections.map(\n ({ title, description, hidden, productLine }): ActionItemCollectionInput => ({\n title,\n description: description || undefined,\n hidden,\n productLine,\n }),\n );\n }\n\n // Save agent functions\n if (agentFunctions.length > 0 && resources.includes(TranscendPullResource.AgentFunctions)) {\n result['agent-functions'] = agentFunctions.map(\n ({ name, description, parameters }): AgentFunctionInput => ({\n name,\n description,\n parameters: JSON.stringify(parameters),\n }),\n );\n }\n\n // Save agent files\n if (agentFiles.length > 0 && resources.includes(TranscendPullResource.AgentFiles)) {\n result['agent-files'] = agentFiles.map(\n ({ name, description, fileId, size, purpose }): AgentFileInput => ({\n name,\n description,\n fileId,\n size,\n purpose,\n }),\n );\n }\n\n // Save vendors\n if (vendors.length > 0 && resources.includes(TranscendPullResource.Vendors)) {\n result.vendors = vendors.map(\n ({\n title,\n description,\n dataProcessingAgreementLink,\n contactName,\n contactPhone,\n address,\n headquarterCountry,\n headquarterSubDivision,\n websiteUrl,\n businessEntity,\n teams,\n owners,\n attributeValues,\n }): VendorInput => ({\n title,\n description: description || undefined,\n dataProcessingAgreementLink: dataProcessingAgreementLink || undefined,\n contactName: contactName || undefined,\n contactPhone: contactPhone || undefined,\n address: address || undefined,\n headquarterCountry: headquarterCountry || undefined,\n headquarterSubDivision: headquarterSubDivision || undefined,\n websiteUrl: websiteUrl || undefined,\n businessEntity: businessEntity?.title,\n teams: teams && teams.length > 0 ? teams.map(({ name }) => name) : undefined,\n owners: owners && owners.length > 0 ? owners.map(({ email }) => email) : undefined,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save data categories\n if (dataCategories.length > 0 && resources.includes(TranscendPullResource.DataCategories)) {\n result['data-categories'] = dataCategories.map(\n ({\n name,\n category,\n description,\n regex,\n owners,\n teams,\n attributeValues,\n }): DataCategoryInput => ({\n name,\n category,\n description: description || undefined,\n regex: regex || undefined,\n owners: owners && owners.length > 0 ? owners.map(({ email }) => email) : undefined,\n teams: teams && teams.length > 0 ? teams.map(({ name }) => name) : undefined,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save processing purposes\n if (\n processingPurposes.length > 0 &&\n resources.includes(TranscendPullResource.ProcessingPurposes)\n ) {\n result['processing-purposes'] = processingPurposes.map(\n ({ name, purpose, description, owners, teams, attributeValues }): ProcessingPurposeInput => ({\n name,\n purpose,\n description: description || undefined,\n owners: owners && owners.length > 0 ? owners.map(({ email }) => email) : undefined,\n teams: teams && teams.length > 0 ? teams.map(({ name }) => name) : undefined,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save data flows\n if (dataFlows.length > 0 && resources.includes(TranscendPullResource.DataFlows)) {\n result['data-flows'] = dataFlows.map(\n ({\n value,\n type,\n description,\n trackingType,\n service,\n status,\n owners,\n teams,\n attributeValues,\n }): DataFlowInput => ({\n value,\n type,\n description: description || undefined,\n trackingPurposes: trackingType,\n status,\n service: service?.integrationName,\n owners: owners.map(({ email }) => email),\n teams: teams.map(({ name }) => name),\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save cookies\n if (cookies.length > 0 && resources.includes(TranscendPullResource.Cookies)) {\n result.cookies = cookies.map(\n ({\n name,\n isRegex,\n description,\n trackingPurposes,\n service,\n status,\n owners,\n teams,\n attributeValues,\n }): CookieInput => ({\n name,\n isRegex,\n description: description || undefined,\n trackingPurposes,\n status,\n service: service?.integrationName,\n owners: owners.map(({ email }) => email),\n teams: teams.map(({ name }) => name),\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save attributes\n if (attributes.length > 0 && resources.includes(TranscendPullResource.Attributes)) {\n result.attributes = attributes.map(\n ({ description, name, type, values, enabledOn = [] }): AttributeInput => ({\n description: description || undefined,\n resources: enabledOn,\n name,\n type,\n values: values.map(({ name, color, description }) => ({\n name,\n color: color || undefined,\n description,\n })),\n }),\n );\n }\n\n // save purposes\n if (purposes.length > 0) {\n result.purposes = purposes.map(\n ({\n name,\n description,\n trackingType,\n defaultConsent,\n configurable,\n showInConsentManager,\n isActive,\n displayOrder,\n optOutSignals,\n authLevel,\n topics,\n showInPrivacyCenter,\n title,\n }): ConsentPurpose => ({\n name,\n title,\n description: description || undefined,\n trackingType,\n 'default-consent': defaultConsent,\n configurable,\n 'show-in-consent-manager': showInConsentManager,\n 'show-in-privacy-center': showInPrivacyCenter,\n 'is-active': isActive,\n 'display-order': displayOrder,\n 'opt-out-signals': optOutSignals.length > 0 ? optOutSignals : undefined,\n 'auth-level': authLevel || undefined,\n 'preference-topics': topics.map(\n ({\n title,\n type,\n displayDescription,\n defaultConfiguration,\n showInPrivacyCenter,\n preferenceOptionValues,\n }) => ({\n title: title.defaultMessage,\n type,\n description: displayDescription.defaultMessage,\n 'default-configuration': defaultConfiguration,\n 'show-in-privacy-center': showInPrivacyCenter,\n ...(preferenceOptionValues.length > 0\n ? {\n options: preferenceOptionValues.map(({ title, slug }) => ({\n title: title.defaultMessage,\n slug,\n })),\n }\n : {}),\n }),\n ),\n }),\n );\n }\n\n // save email templates\n if (\n dataSiloIds.length === 0 &&\n templates.length > 0 &&\n resources.includes(TranscendPullResource.Templates)\n ) {\n result.templates = templates.map(({ title }) => ({ title }));\n }\n\n // Save enrichers\n if (enrichers.length > 0 && resources.includes(TranscendPullResource.Enrichers)) {\n result.enrichers = enrichers.map(\n ({\n title,\n url,\n type,\n inputIdentifier,\n identifiers,\n actions,\n testRegex,\n dataSubjects,\n expirationDuration,\n lookerQueryTitle,\n transitionRequestStatus,\n phoneNumbers,\n regionList,\n }): EnricherInput => ({\n title,\n url: url || undefined,\n type,\n 'input-identifier': inputIdentifier?.name,\n 'output-identifiers': identifiers.map(({ name }) => name),\n 'privacy-actions':\n Object.values(RequestAction).length === actions.length ? undefined : actions,\n testRegex: testRegex || undefined,\n lookerQueryTitle: lookerQueryTitle || undefined,\n expirationDuration: parseInt(expirationDuration, 10),\n transitionRequestStatus: transitionRequestStatus || undefined,\n phoneNumbers: phoneNumbers && phoneNumbers.length > 0 ? phoneNumbers : undefined,\n regionList: regionList && regionList.length > 0 ? regionList : undefined,\n 'data-subjects': dataSubjects.map(({ type }) => type),\n }),\n );\n }\n\n // Save data silos\n if (dataSilos.length > 0 && resources.includes(TranscendPullResource.DataSilos)) {\n const indexedDataSubjects = keyBy(dataSubjects, 'type');\n result['data-silos'] = dataSilos.map(\n ([\n {\n title,\n description,\n url,\n type,\n outerType,\n apiKeys,\n notifyEmailAddress,\n identifiers,\n dependentDataSilos,\n owners,\n country,\n countrySubDivision,\n teams,\n subjectBlocklist,\n isLive,\n promptAVendorEmailSendFrequency,\n promptAVendorEmailSendType,\n promptAVendorEmailIncludeIdentifiersAttachment,\n promptAVendorEmailCompletionLinkType,\n manualWorkRetryFrequency,\n catalog,\n attributeValues,\n discoveredBy,\n businessEntities,\n },\n dataPoints,\n ]): DataSiloInput => ({\n title,\n description,\n integrationName: type,\n 'outer-type': outerType || undefined,\n url: url || undefined,\n 'api-key-title': apiKeys[0]?.title,\n 'identity-keys': identifiers\n .filter(({ isConnected }) => isConnected)\n .map(({ name }) => name),\n ...(dependentDataSilos.length > 0\n ? {\n 'deletion-dependencies': dependentDataSilos.map(({ title }) => title),\n }\n : {}),\n ...(owners.length > 0 ? { owners: owners.map(({ email }) => email) } : {}),\n ...(teams.length > 0 ? { teams: teams.map(({ name }) => name) } : {}),\n ...(discoveredBy.length > 0\n ? { discoveredBy: discoveredBy.map(({ title }) => title) }\n : {}),\n ...(businessEntities.length > 0\n ? {\n businessEntities: businessEntities.map(({ title }) => title),\n }\n : {}),\n country: country || undefined,\n countrySubDivision: countrySubDivision || undefined,\n disabled: !isLive,\n 'data-subjects':\n subjectBlocklist.length > 0\n ? convertToDataSubjectAllowlist(\n subjectBlocklist.map(({ type }) => type),\n indexedDataSubjects,\n )\n : undefined,\n ...(catalog.hasAvcFunctionality\n ? {\n 'email-settings': {\n 'notify-email-address': notifyEmailAddress || undefined,\n 'send-frequency': promptAVendorEmailSendFrequency,\n 'send-type': promptAVendorEmailSendType,\n 'include-identifiers-attachment': promptAVendorEmailIncludeIdentifiersAttachment,\n 'completion-link-type': promptAVendorEmailCompletionLinkType,\n 'manual-work-retry-frequency': manualWorkRetryFrequency,\n },\n }\n : {}),\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n\n datapoints: dataPoints\n .map(\n (dataPoint): DatapointInput => ({\n key: dataPoint.name,\n title: dataPoint.title?.defaultMessage,\n description: dataPoint.description?.defaultMessage,\n owners: dataPoint.owners.map(({ email }) => email),\n teams: dataPoint.teams.map(({ name }) => name),\n ...(dataPoint.path.length > 0 ? { path: dataPoint.path } : {}),\n ...(dataPoint.dataCollection?.title\n ? {\n 'data-collection-tag': dataPoint.dataCollection.title.defaultMessage,\n }\n : {}),\n ...(dataPoint.dbIntegrationQueries.length > 0\n ? {\n 'privacy-action-queries': mapValues(\n keyBy(dataPoint.dbIntegrationQueries, 'requestType'),\n (databaseIntegrationQuery) =>\n databaseIntegrationQuery.suggestedQuery ||\n databaseIntegrationQuery.query ||\n undefined,\n ),\n }\n : {}),\n ...(dataPoint.subDataPoints.length > 0\n ? {\n fields: dataPoint.subDataPoints\n .map(\n (field): FieldInput => ({\n key: field.name,\n description: field.description,\n purposes: field.purposes,\n categories: field.categories,\n ...(includeGuessedCategories && field.pendingCategoryGuesses\n ? {\n 'guessed-categories': field.pendingCategoryGuesses\n .filter((guess) => guess.status === 'PENDING')\n .map((guess) => ({\n category: {\n name: guess.category.name,\n category: guess.category.category,\n },\n status: guess.status,\n confidence: guess.confidence,\n classifierVersion: guess.classifierVersion || undefined,\n })),\n }\n : {}),\n 'access-request-visibility-enabled': field.accessRequestVisibilityEnabled,\n 'erasure-request-redaction-enabled': field.erasureRequestRedactionEnabled,\n attributes:\n field.attributeValues !== undefined && field.attributeValues.length > 0\n ? formatAttributeValues(field.attributeValues)\n : undefined,\n }),\n )\n .sort((a, b) => a.key.localeCompare(b.key)),\n }\n : {}),\n 'privacy-actions': dataPoint.actionSettings\n .filter(({ active }) => active)\n .map(({ type }) => type),\n }),\n )\n .sort((a, b) =>\n [...(a.path ?? []), a.key]\n .join('.')\n .localeCompare([...(b.path ?? []), b.key].join('.')),\n ),\n }),\n );\n }\n return result;\n}\n/* eslint-enable max-lines */\n"],"mappings":"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"}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import{a as e}from"./constants-XOsAW1__.mjs";import{t}from"./logger-Bj782ZYD.mjs";import{r as n}from"./fetchAllRequests-xGgt_STo.mjs";import{RequestStatus as r}from"@transcend-io/privacy-types";import i from"colors";import{buildTranscendGraphQLClient as a,makeGraphQLRequest as o}from"@transcend-io/sdk";import{map as s}from"@transcend-io/utils";import{gql as c}from"graphql-request";import l from"cli-progress";const u=c`
|
|
2
|
-
mutation TranscendCliRemoveRequestIdentifiers($input: RemoveRequestIdentifiersInput!) {
|
|
3
|
-
removeRequestIdentifiers(input: $input) {
|
|
4
|
-
count
|
|
5
|
-
}
|
|
6
|
-
}
|
|
7
|
-
`,d=c`
|
|
8
|
-
query TranscendCliRequestIdentifiers(
|
|
9
|
-
$first: Int!
|
|
10
|
-
$offset: Int!
|
|
11
|
-
$requestIds: [ID!]
|
|
12
|
-
$updatedAtBefore: Date
|
|
13
|
-
$updatedAtAfter: Date
|
|
14
|
-
) {
|
|
15
|
-
requestIdentifiers(
|
|
16
|
-
input: {
|
|
17
|
-
requestIds: $requestIds
|
|
18
|
-
updatedAtBefore: $updatedAtBefore
|
|
19
|
-
updatedAtAfter: $updatedAtAfter
|
|
20
|
-
}
|
|
21
|
-
first: $first
|
|
22
|
-
offset: $offset
|
|
23
|
-
useMaster: false
|
|
24
|
-
orderBy: [{ field: createdAt, direction: ASC }, { field: name, direction: ASC }]
|
|
25
|
-
) {
|
|
26
|
-
nodes {
|
|
27
|
-
id
|
|
28
|
-
name
|
|
29
|
-
isVerifiedAtLeastOnce
|
|
30
|
-
}
|
|
31
|
-
totalCount
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
`;async function f(e,{requestId:n,requestIds:r,updatedAtBefore:i,updatedAtAfter:a}){let s=r??(n?[n]:void 0),c=[],l=0,u=!1;do{let{requestIdentifiers:{nodes:n}}=await o(e,d,{variables:{first:50,offset:l,requestIds:s,updatedAtBefore:i?i.toISOString():void 0,updatedAtAfter:a?a.toISOString():void 0},logger:t});c.push(...n),l+=50,u=n.length===50}while(u);return c}async function p({requestActions:c,identifierNames:d,auth:p,concurrency:m=20,transcendUrl:h=e}){let g=a(h,p),_=new Date().getTime(),v=new l.SingleBar({},l.Presets.shades_classic),y=await n(g,{actions:c,statuses:[r.Enriching]});t.info(i.magenta(`Fetched requests in preflight/enriching state.`));let b=0,x=0;v.start(y.length,0),await s(y,async e=>{let n=(await f(g,{requestId:e.id})).filter(({isVerifiedAtLeastOnce:e,name:t})=>e===!1&&d.includes(t)).map(({id:e})=>e);n.length>0&&(await o(g,u,{variables:{input:{requestId:e.id,requestIdentifierIds:n}},logger:t}),x+=n.length),b+=1,v.update(b)},{concurrency:m}),v.stop();let S=new Date().getTime()-_;return t.info(i.green(`Successfully cleared out unverified identifiers "${S/1e3}" seconds for ${b} requests, ${x} identifiers were cleared out!`)),y.length}export{d as i,f as n,u as r,p as t};
|
|
35
|
-
//# sourceMappingURL=removeUnverifiedRequestIdentifiers-B0Gx09XN.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"removeUnverifiedRequestIdentifiers-B0Gx09XN.mjs","names":[],"sources":["../src/lib/graphql/gqls/RequestIdentifier.ts","../src/lib/graphql/fetchAllRequestIdentifierMetadata.ts","../src/lib/requests/removeUnverifiedRequestIdentifiers.ts"],"sourcesContent":["import { gql } from 'graphql-request';\n\nexport const REMOVE_REQUEST_IDENTIFIERS = gql`\n mutation TranscendCliRemoveRequestIdentifiers($input: RemoveRequestIdentifiersInput!) {\n removeRequestIdentifiers(input: $input) {\n count\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const REQUEST_IDENTIFIERS = gql`\n query TranscendCliRequestIdentifiers(\n $first: Int!\n $offset: Int!\n $requestIds: [ID!]\n $updatedAtBefore: Date\n $updatedAtAfter: Date\n ) {\n requestIdentifiers(\n input: {\n requestIds: $requestIds\n updatedAtBefore: $updatedAtBefore\n updatedAtAfter: $updatedAtAfter\n }\n first: $first\n offset: $offset\n useMaster: false\n orderBy: [{ field: createdAt, direction: ASC }, { field: name, direction: ASC }]\n ) {\n nodes {\n id\n name\n isVerifiedAtLeastOnce\n }\n totalCount\n }\n }\n`;\n","import { makeGraphQLRequest } from '@transcend-io/sdk';\nimport { GraphQLClient } from 'graphql-request';\n\nimport { logger } from '../../logger.js';\nimport { REQUEST_IDENTIFIERS } from './gqls/index.js';\n\nexport interface RequestIdentifierMetadata {\n /** ID of request identifier */\n id: string;\n /** Name of identifier */\n name: string;\n /** Status of identifier */\n isVerifiedAtLeastOnce: boolean;\n}\n\nconst PAGE_SIZE = 50;\n\n/**\n * Fetch all request identifier metadata for a particular request\n *\n * @param client - GraphQL client\n * @param options - Filter options\n * @returns List of request identifiers\n */\nexport async function fetchAllRequestIdentifierMetadata(\n client: GraphQLClient,\n {\n requestId,\n requestIds,\n updatedAtBefore,\n updatedAtAfter,\n }: {\n /** ID of request to filter on */\n requestId?: string;\n /** IDs of requests to filter on */\n requestIds?: string[];\n /** Filter for request identifiers updated before this date */\n updatedAtBefore?: Date;\n /** Filter for request identifiers updated after this date */\n updatedAtAfter?: Date;\n },\n): Promise<RequestIdentifierMetadata[]> {\n const resolvedRequestIds = requestIds ?? (requestId ? [requestId] : undefined);\n const requestIdentifiers: RequestIdentifierMetadata[] = [];\n let offset = 0;\n\n // Paginate\n let shouldContinue = false;\n do {\n const {\n requestIdentifiers: { nodes },\n } = await makeGraphQLRequest<{\n /** Request Identifiers */\n requestIdentifiers: {\n /** List */\n nodes: RequestIdentifierMetadata[];\n };\n }>(client, REQUEST_IDENTIFIERS, {\n variables: {\n first: PAGE_SIZE,\n offset,\n requestIds: resolvedRequestIds,\n updatedAtBefore: updatedAtBefore ? updatedAtBefore.toISOString() : undefined,\n updatedAtAfter: updatedAtAfter ? updatedAtAfter.toISOString() : undefined,\n },\n logger,\n });\n requestIdentifiers.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return requestIdentifiers;\n}\n","import { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport { buildTranscendGraphQLClient, makeGraphQLRequest } from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\nimport {\n REMOVE_REQUEST_IDENTIFIERS,\n fetchAllRequests,\n fetchAllRequestIdentifierMetadata,\n} from '../graphql/index.js';\n\n/**\n * Remove a set of unverified request identifier\n *\n * @param options - Options\n * @returns Number of items marked as completed\n */\nexport async function removeUnverifiedRequestIdentifiers({\n requestActions,\n identifierNames,\n auth,\n concurrency = 20,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** Transcend API key authentication */\n auth: string;\n /** The set of identifier names to remove */\n identifierNames: string[];\n /** Concurrency to upload requests in parallel */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses: [RequestStatus.Enriching],\n });\n\n // Notify Transcend\n logger.info(colors.magenta('Fetched requests in preflight/enriching state.'));\n\n let total = 0;\n let processed = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToRestart) => {\n const requestIdentifiers = await fetchAllRequestIdentifierMetadata(client, {\n requestId: requestToRestart.id,\n });\n const clearOut = requestIdentifiers\n .filter(\n ({ isVerifiedAtLeastOnce, name }) =>\n isVerifiedAtLeastOnce === false && identifierNames.includes(name),\n )\n .map(({ id }) => id);\n\n if (clearOut.length > 0) {\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, REMOVE_REQUEST_IDENTIFIERS, {\n variables: {\n input: {\n requestId: requestToRestart.id,\n requestIdentifierIds: clearOut,\n },\n },\n logger,\n });\n processed += clearOut.length;\n }\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully cleared out unverified identifiers \"${\n totalTime / 1000\n }\" seconds for ${total} requests, ${processed} identifiers were cleared out!`,\n ),\n );\n return allRequests.length;\n}\n"],"mappings":"4ZAEA,MAAa,EAA6B,CAAG;;;;;;EAUhC,EAAsB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;ECYtC,eAAsB,EACpB,EACA,CACE,YACA,aACA,kBACA,kBAWoC,CACtC,IAAM,EAAqB,IAAe,EAAY,CAAC,EAAU,CAAG,IAAA,IAC9D,EAAkD,EAAE,CACtD,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,mBAAoB,CAAE,UACpB,MAAM,EAMP,EAAQ,EAAqB,CAC9B,UAAW,CACT,MAAO,GACP,SACA,WAAY,EACZ,gBAAiB,EAAkB,EAAgB,aAAa,CAAG,IAAA,GACnE,eAAgB,EAAiB,EAAe,aAAa,CAAG,IAAA,GACjE,CACD,SACD,CAAC,CACF,EAAmB,KAAK,GAAG,EAAM,CACjC,GAAU,GACV,EAAiB,EAAM,SAAW,SAC3B,GAET,OAAO,ECpDT,eAAsB,EAAmC,CACvD,iBACA,kBACA,OACA,cAAc,GACd,eAAe,GAYG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAI,EAAY,UAAU,EAAE,CAAE,EAAY,QAAQ,eAAe,CAG/E,EAAc,MAAM,EAAiB,EAAQ,CACjD,QAAS,EACT,SAAU,CAAC,EAAc,UAAU,CACpC,CAAC,CAGF,EAAO,KAAK,EAAO,QAAQ,iDAAiD,CAAC,CAE7E,IAAI,EAAQ,EACR,EAAY,EAChB,EAAY,MAAM,EAAY,OAAQ,EAAE,CACxC,MAAM,EACJ,EACA,KAAO,IAAqB,CAI1B,IAAM,GAHqB,MAAM,EAAkC,EAAQ,CACzE,UAAW,EAAiB,GAC7B,CAAC,EAEC,QACE,CAAE,wBAAuB,UACxB,IAA0B,IAAS,EAAgB,SAAS,EAAK,CACpE,CACA,KAAK,CAAE,QAAS,EAAG,CAElB,EAAS,OAAS,IACpB,MAAM,EAGH,EAAQ,EAA4B,CACrC,UAAW,CACT,MAAO,CACL,UAAW,EAAiB,GAC5B,qBAAsB,EACvB,CACF,CACD,SACD,CAAC,CACF,GAAa,EAAS,QAGxB,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SAAS,CACR,EASvB,OAPA,EAAO,KACL,EAAO,MACL,oDACE,EAAY,IACb,gBAAgB,EAAM,aAAa,EAAU,gCAC/C,CACF,CACM,EAAY"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{a as e}from"./constants-XOsAW1__.mjs";import{t}from"./logger-Bj782ZYD.mjs";import{i as n}from"./RequestDataSilo-Rrc2dL9g.mjs";import{r}from"./fetchAllRequests-xGgt_STo.mjs";import{t as i}from"./fetchRequestDataSilo-0UvyeL60.mjs";import{RequestStatus as a}from"@transcend-io/privacy-types";import o from"colors";import{buildTranscendGraphQLClient as s,makeGraphQLRequest as c}from"@transcend-io/sdk";import{map as l}from"@transcend-io/utils";import u from"cli-progress";async function d({requestActions:d,dataSiloId:f,auth:p,concurrency:m=20,transcendUrl:h=e}){let g=s(h,p),_=new Date().getTime(),v=new u.SingleBar({},u.Presets.shades_classic),y=await r(g,{actions:d,statuses:[a.Compiling,a.Approving]});t.info(o.magenta(`Retrying requests for Data Silo: "${f}", restarting "${y.length}" requests.`));let b=0,x=0;v.start(y.length,0),await l(y,async e=>{try{await c(g,n,{variables:{requestDataSiloId:(await i(g,{requestId:e.id,dataSiloId:f})).id},logger:t})}catch(e){if(!e.message.includes(`Failed to find RequestDataSilo`))throw e;x+=1}b+=1,v.update(b)},{concurrency:m}),v.stop();let S=new Date().getTime()-_;return t.info(o.green(`Successfully notified Transcend in "${S/1e3}" seconds for ${b} requests, ${x} requests were skipped because data silo was not attached to the request!`)),y.length}export{d as t};
|
|
2
|
-
//# sourceMappingURL=retryRequestDataSilos-DFjFhhC0.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"retryRequestDataSilos-DFjFhhC0.mjs","names":[],"sources":["../src/lib/requests/retryRequestDataSilos.ts"],"sourcesContent":["import { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport { buildTranscendGraphQLClient, makeGraphQLRequest } from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\nimport {\n RETRY_REQUEST_DATA_SILO,\n fetchRequestDataSilo,\n fetchAllRequests,\n} from '../graphql/index.js';\n\n/**\n * Retry a set of RequestDataSilos\n *\n * @param options - Options\n * @returns Number of items marked as completed\n */\nexport async function retryRequestDataSilos({\n requestActions,\n dataSiloId,\n auth,\n concurrency = 20,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** Transcend API key authentication */\n auth: string;\n /** Data Silo ID to pull down jobs for */\n dataSiloId: string;\n /** Concurrency to upload requests in parallel */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses: [RequestStatus.Compiling, RequestStatus.Approving],\n });\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Retrying requests for Data Silo: \"${dataSiloId}\", restarting \"${allRequests.length}\" requests.`,\n ),\n );\n\n let total = 0;\n let skipped = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToRestart) => {\n try {\n const requestDataSilo = await fetchRequestDataSilo(client, {\n requestId: requestToRestart.id,\n dataSiloId,\n });\n\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, RETRY_REQUEST_DATA_SILO, {\n variables: { requestDataSiloId: requestDataSilo.id },\n logger,\n });\n } catch (err) {\n // some requests may not have this data silo connected\n if (!err.message.includes('Failed to find RequestDataSilo')) {\n throw err;\n }\n skipped += 1;\n }\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully notified Transcend in \"${\n totalTime / 1000\n }\" seconds for ${total} requests, ${skipped} requests were skipped because data silo was not attached to the request!`,\n ),\n );\n return allRequests.length;\n}\n"],"mappings":"4dAoBA,eAAsB,EAAsB,CAC1C,iBACA,aACA,OACA,cAAc,GACd,eAAe,GAYG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAI,EAAY,UAAU,EAAE,CAAE,EAAY,QAAQ,eAAe,CAG/E,EAAc,MAAM,EAAiB,EAAQ,CACjD,QAAS,EACT,SAAU,CAAC,EAAc,UAAW,EAAc,UAAU,CAC7D,CAAC,CAGF,EAAO,KACL,EAAO,QACL,qCAAqC,EAAW,iBAAiB,EAAY,OAAO,aACrF,CACF,CAED,IAAI,EAAQ,EACR,EAAU,EACd,EAAY,MAAM,EAAY,OAAQ,EAAE,CACxC,MAAM,EACJ,EACA,KAAO,IAAqB,CAC1B,GAAI,CAMF,MAAM,EAGH,EAAQ,EAAyB,CAClC,UAAW,CAAE,mBATS,MAAM,EAAqB,EAAQ,CACzD,UAAW,EAAiB,GAC5B,aACD,CAAC,EAMgD,GAAI,CACpD,SACD,CAAC,OACK,EAAK,CAEZ,GAAI,CAAC,EAAI,QAAQ,SAAS,iCAAiC,CACzD,MAAM,EAER,GAAW,EAGb,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SAAS,CACR,EASvB,OAPA,EAAO,KACL,EAAO,MACL,uCACE,EAAY,IACb,gBAAgB,EAAM,aAAa,EAAQ,2EAC7C,CACF,CACM,EAAY"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{a as e}from"./constants-XOsAW1__.mjs";import{t}from"./logger-Bj782ZYD.mjs";import{i as n,t as r}from"./fetchAllRequestEnrichers-Bt97Bb7F.mjs";import{r as i}from"./fetchAllRequests-xGgt_STo.mjs";import{RequestEnricherStatus as a,RequestStatus as o}from"@transcend-io/privacy-types";import s from"colors";import{buildTranscendGraphQLClient as c,makeGraphQLRequest as l}from"@transcend-io/sdk";import{map as u,mapSeries as d}from"@transcend-io/utils";import f from"cli-progress";async function p({enricherIds:p,auth:m,concurrency:h=100,transcendUrl:g=e}){let _=c(g,m),v=new Date().getTime(),y=await i(_,{statuses:[o.Enriching]});t.info(s.magenta(`Processing enricher: "${p.join(`,`)}" fetched "${y.length}" in enriching status.`));let b=new f.SingleBar({},f.Presets.shades_classic),x=0;b.start(y.length,0);let S=0;await u(y,async e=>{let i=(await r(_,{requestId:e.id})).filter(e=>p.includes(e.enricher.id)&&![a.Resolved,a.Skipped].includes(e.status));i.length>0&&await d(i,async e=>{try{await l(_,n,{variables:{requestEnricherId:e.id},logger:t}),S+=1}catch(e){if(!e.message.includes(`Client error: Cannot skip Request enricher because it has already completed`))throw e}}),x+=1,b.update(x)},{concurrency:h}),b.stop();let C=new Date().getTime()-v;return t.info(s.green(`Successfully skipped "${S}" for "${y.length}" requests in "${C/1e3}" seconds!`)),y.length}export{p as t};
|
|
2
|
-
//# sourceMappingURL=skipPreflightJobs-Bm8lZZk-.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"skipPreflightJobs-Bm8lZZk-.mjs","names":[],"sources":["../src/lib/requests/skipPreflightJobs.ts"],"sourcesContent":["import { RequestEnricherStatus, RequestStatus } from '@transcend-io/privacy-types';\nimport { buildTranscendGraphQLClient, makeGraphQLRequest } from '@transcend-io/sdk';\nimport { mapSeries, map } from '@transcend-io/utils';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\nimport {\n fetchAllRequestEnrichers,\n fetchAllRequests,\n SKIP_REQUEST_ENRICHER,\n} from '../graphql/index.js';\n\n/**\n * Given an enricher ID, mark all open request enrichers as skipped\n *\n * @param options - Options\n * @returns Number of items skipped\n */\nexport async function skipPreflightJobs({\n enricherIds,\n auth,\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** Transcend API key authentication */\n auth: string;\n /** Enricher IDs to pull down jobs for */\n enricherIds: string[];\n /** Upload concurrency */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Request statuses to mark as completed */\n requestStatuses?: RequestStatus[];\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n\n // fetch all RequestDataSilos that are open\n const requests = await fetchAllRequests(client, {\n statuses: [RequestStatus.Enriching],\n });\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Processing enricher: \"${enricherIds.join(',')}\" fetched \"${\n requests.length\n }\" in enriching status.`,\n ),\n );\n\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n\n let total = 0;\n progressBar.start(requests.length, 0);\n let totalSkipped = 0;\n await map(\n requests,\n async (request) => {\n // TODO dont pull all in\n const requestEnrichers = await fetchAllRequestEnrichers(client, {\n requestId: request.id,\n });\n const requestEnrichersFiltered = requestEnrichers.filter(\n (enricher) =>\n enricherIds.includes(enricher.enricher.id) &&\n ![\n RequestEnricherStatus.Resolved,\n RequestEnricherStatus.Skipped,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ].includes(enricher.status as any),\n );\n\n // TODO\n if (requestEnrichersFiltered.length > 0) {\n await mapSeries(requestEnrichersFiltered, async (requestEnricher) => {\n try {\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, SKIP_REQUEST_ENRICHER, {\n variables: { requestEnricherId: requestEnricher.id },\n logger,\n });\n totalSkipped += 1;\n } catch (err) {\n if (\n !err.message.includes(\n 'Client error: Cannot skip Request enricher because it has already completed',\n )\n ) {\n throw err;\n }\n }\n });\n }\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully skipped \"${totalSkipped}\" for \"${\n requests.length\n }\" requests in \"${totalTime / 1000}\" seconds!`,\n ),\n );\n return requests.length;\n}\n"],"mappings":"meAoBA,eAAsB,EAAkB,CACtC,cACA,OACA,cAAc,IACd,eAAe,GAYG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAGzB,EAAW,MAAM,EAAiB,EAAQ,CAC9C,SAAU,CAAC,EAAc,UAAU,CACpC,CAAC,CAGF,EAAO,KACL,EAAO,QACL,yBAAyB,EAAY,KAAK,IAAI,CAAC,aAC7C,EAAS,OACV,wBACF,CACF,CAGD,IAAM,EAAc,IAAI,EAAY,UAAU,EAAE,CAAE,EAAY,QAAQ,eAAe,CAEjF,EAAQ,EACZ,EAAY,MAAM,EAAS,OAAQ,EAAE,CACrC,IAAI,EAAe,EACnB,MAAM,EACJ,EACA,KAAO,IAAY,CAKjB,IAAM,GAHmB,MAAM,EAAyB,EAAQ,CAC9D,UAAW,EAAQ,GACpB,CAAC,EACgD,OAC/C,GACC,EAAY,SAAS,EAAS,SAAS,GAAG,EAC1C,CAAC,CACC,EAAsB,SACtB,EAAsB,QAEvB,CAAC,SAAS,EAAS,OAAc,CACrC,CAGG,EAAyB,OAAS,GACpC,MAAM,EAAU,EAA0B,KAAO,IAAoB,CACnE,GAAI,CACF,MAAM,EAGH,EAAQ,EAAuB,CAChC,UAAW,CAAE,kBAAmB,EAAgB,GAAI,CACpD,SACD,CAAC,CACF,GAAgB,QACT,EAAK,CACZ,GACE,CAAC,EAAI,QAAQ,SACX,8EACD,CAED,MAAM,IAGV,CAEJ,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SAAS,CACR,EASvB,OAPA,EAAO,KACL,EAAO,MACL,yBAAyB,EAAa,UACpC,EAAS,OACV,iBAAiB,EAAY,IAAK,YACpC,CACF,CACM,EAAS"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{a as e}from"./constants-XOsAW1__.mjs";import{t}from"./logger-Bj782ZYD.mjs";import{t as n}from"./RequestDataSilo-Rrc2dL9g.mjs";import{n as r,r as i}from"./fetchRequestDataSilo-0UvyeL60.mjs";import{RequestStatus as a}from"@transcend-io/privacy-types";import o from"colors";import{buildTranscendGraphQLClient as s,makeGraphQLRequest as c}from"@transcend-io/sdk";import{map as l}from"@transcend-io/utils";import u from"cli-progress";async function d({dataSiloId:d,auth:f,concurrency:p=50,status:m=`SKIPPED`,transcendUrl:h=e,requestStatuses:g=[a.Compiling,a.Secondary],actionTypes:_=[]}){let v=s(h,f),y=new Date().getTime(),b=await i(v,{dataSiloId:d,requestStatuses:g});t.info(o.magenta(`Marking ${b} request data silos as completed${_.length>0?` for action types: ${_.join(`,`)}`:``}`));let x=new u.SingleBar({},u.Presets.shades_classic),S=0;x.start(b,0),await l(await r(v,{dataSiloId:d,requestStatuses:g,onProgress:e=>{S+=e/2,x.update(S)}}),async e=>{if(_.length===0||_.includes(e.request.type))try{await c(v,n,{variables:{requestDataSiloId:e.id,status:m},logger:t})}catch(e){if(!e.message.includes(`Client error: Request must be active:`))throw e}S+=.5,x.update(S)},{concurrency:p}),x.stop();let C=new Date().getTime()-y;return t.info(o.green(`Successfully skipped "${b}" requests in "${C/1e3}" seconds!`)),b}export{d as t};
|
|
2
|
-
//# sourceMappingURL=skipRequestDataSilos-B5FByYTj.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"skipRequestDataSilos-B5FByYTj.mjs","names":[],"sources":["../src/lib/requests/skipRequestDataSilos.ts"],"sourcesContent":["import { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport { buildTranscendGraphQLClient, makeGraphQLRequest } from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\nimport {\n CHANGE_REQUEST_DATA_SILO_STATUS,\n fetchRequestDataSilos,\n fetchRequestDataSilosCount,\n} from '../graphql/index.js';\n\n/**\n * Given a data silo ID, mark all open request data silos as skipped\n *\n * @param options - Options\n * @returns Number of items skipped\n */\nexport async function skipRequestDataSilos({\n dataSiloId,\n auth,\n concurrency = 50,\n status = 'SKIPPED',\n transcendUrl = DEFAULT_TRANSCEND_API,\n requestStatuses = [RequestStatus.Compiling, RequestStatus.Secondary],\n actionTypes = [],\n}: {\n /** Transcend API key authentication */\n auth: string;\n /** Data Silo ID to pull down jobs for */\n dataSiloId: string;\n /** Status to set */\n status?: 'SKIPPED' | 'RESOLVED';\n /** Upload concurrency */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Request statuses to mark as completed */\n requestStatuses?: RequestStatus[];\n /** Request action types to filter on */\n actionTypes?: RequestAction[];\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n\n // Determine total number of request data silos\n const requestDataSiloCount = await fetchRequestDataSilosCount(client, {\n dataSiloId,\n requestStatuses,\n });\n logger.info(\n colors.magenta(\n `Marking ${requestDataSiloCount} request data silos as completed${actionTypes.length > 0 ? ` for action types: ${actionTypes.join(',')}` : ''}`,\n ),\n );\n\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n\n let total = 0;\n progressBar.start(requestDataSiloCount, 0);\n\n // Fetch all matching request data silos, updating progress as pages are fetched\n const requestDataSilos = await fetchRequestDataSilos(client, {\n dataSiloId,\n requestStatuses,\n onProgress: (numFetched) => {\n total += numFetched / 2;\n progressBar.update(total);\n },\n });\n\n await map(\n requestDataSilos,\n async (requestDataSilo) => {\n if (actionTypes.length === 0 || actionTypes.includes(requestDataSilo.request.type)) {\n try {\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, CHANGE_REQUEST_DATA_SILO_STATUS, {\n variables: { requestDataSiloId: requestDataSilo.id, status },\n logger,\n });\n } catch (err) {\n if (!err.message.includes('Client error: Request must be active:')) {\n throw err;\n }\n }\n }\n\n total += 0.5;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully skipped \"${requestDataSiloCount}\" requests in \"${totalTime / 1000}\" seconds!`,\n ),\n );\n return requestDataSiloCount;\n}\n"],"mappings":"obAoBA,eAAsB,EAAqB,CACzC,aACA,OACA,cAAc,GACd,SAAS,UACT,eAAe,EACf,kBAAkB,CAAC,EAAc,UAAW,EAAc,UAAU,CACpE,cAAc,EAAE,EAgBE,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAGzB,EAAuB,MAAM,EAA2B,EAAQ,CACpE,aACA,kBACD,CAAC,CACF,EAAO,KACL,EAAO,QACL,WAAW,EAAqB,kCAAkC,EAAY,OAAS,EAAI,sBAAsB,EAAY,KAAK,IAAI,GAAK,KAC5I,CACF,CAGD,IAAM,EAAc,IAAI,EAAY,UAAU,EAAE,CAAE,EAAY,QAAQ,eAAe,CAEjF,EAAQ,EACZ,EAAY,MAAM,EAAsB,EAAE,CAY1C,MAAM,EATmB,MAAM,EAAsB,EAAQ,CAC3D,aACA,kBACA,WAAa,GAAe,CAC1B,GAAS,EAAa,EACtB,EAAY,OAAO,EAAM,EAE5B,CAAC,CAIA,KAAO,IAAoB,CACzB,GAAI,EAAY,SAAW,GAAK,EAAY,SAAS,EAAgB,QAAQ,KAAK,CAChF,GAAI,CACF,MAAM,EAGH,EAAQ,EAAiC,CAC1C,UAAW,CAAE,kBAAmB,EAAgB,GAAI,SAAQ,CAC5D,SACD,CAAC,OACK,EAAK,CACZ,GAAI,CAAC,EAAI,QAAQ,SAAS,wCAAwC,CAChE,MAAM,EAKZ,GAAS,GACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SAAS,CACR,EAOvB,OALA,EAAO,KACL,EAAO,MACL,yBAAyB,EAAqB,iBAAiB,EAAY,IAAK,YACjF,CACF,CACM"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{a as e}from"./constants-XOsAW1__.mjs";import{t}from"./logger-Bj782ZYD.mjs";import{n,r}from"./fetchAllRequestIdentifiers-BXx3rSee.mjs";import{i,r as a}from"./fetchAllRequests-xGgt_STo.mjs";import{i as o,r as s,t as c}from"./writeCsv-Da8NUe1V.mjs";import{groupBy as l,uniq as u}from"lodash-es";import d from"colors";import{buildTranscendGraphQLClient as f,createSombraGotInstance as p}from"@transcend-io/sdk";import{map as m}from"@transcend-io/utils";import h from"cli-progress";function g({attributeValues:e,requestIdentifiers:t,id:n,email:r,type:i,status:a,subjectType:o,details:s,createdAt:c,successfullyCompletedAt:u,country:d,locale:f,origin:p,countrySubDivision:m,isSilent:h,isTest:g,coreIdentifier:_,purpose:v,...y}){return{"Request ID":n,"Created At":c,"Successfully Completed At":u||``,Email:r,"Core Identifier":_,"Request Type":i,"Data Subject Type":o,Status:a,Country:d,"Country Sub Division":m,Details:s,Origin:p,"Silent Mode":h,"Is Test Request":g,Language:f,"Purpose Trigger Name":v?.title||v?.name||``,"Purpose Trigger Value":v?.consent?.toString()||``,...(v?.enrichedPreferences||[]).reduce((e,t)=>{let n=t.preferenceTopic?.title.defaultMessage||t.name;return n?{...e,[n]:t.selectValues?t.selectValues.map(e=>e.name).join(`;`):t.selectValue?.name||t.booleanValue}:e},{}),...y,...Object.entries(l(e,`attributeKey.name`)).reduce((e,[t,n])=>Object.assign(e,{[t]:n.map(({name:e})=>e).join(`,`)}),{}),...Object.entries(l(t,`name`)).reduce((e,[t,n])=>Object.assign(e,{[t]:n.map(({value:e})=>e).join(`,`)}),{})}}function _(e,t,n){let r=e.getTime(),i=t.getTime(),a=(i-r)/n;return Array.from({length:n},(e,t)=>({createdAtAfter:new Date(r+a*t),createdAtBefore:new Date(t===n-1?i:r+a*(t+1))}))}async function v({auth:l,sombraAuth:v,actions:y=[],statuses:b=[],identifierSearch:x,concurrency:S=1,pageLimit:C=100,transcendUrl:w=e,createdAtBefore:T,createdAtAfter:E,updatedAtBefore:D,updatedAtAfter:O,isTest:k,skipRequestIdentifiers:A=!1,file:j}){let M=f(w,l),N=A?void 0:await p(w,l,{logger:t,sombraApiKey:v,sombraUrl:process.env.SOMBRA_URL}),P=``;T&&(P+=` before ${T.toISOString()}`),E&&(P+=`${P?`, and`:``} after ${E.toISOString()}`),t.info(d.magenta(`${y.length>0?`Pulling requests of type "${y.join(`" , "`)}"`:`Pulling all requests`}${P}`));let F=S>1&&E&&T,I=F?_(E,T,S):[{createdAtAfter:E,createdAtBefore:T}];F&&t.info(d.magenta(`Splitting date range into ${S} parallel chunks`));let L={type:y.length>0?y:void 0,status:b.length>0?b:void 0,isTest:k,createdAtBefore:T?T.toISOString():void 0,createdAtAfter:E?E.toISOString():void 0,updatedAtBefore:D?D.toISOString():void 0,updatedAtAfter:O?O.toISOString():void 0},R=Date.now();A||await r(M);let z=await i(M,L);t.info(d.magenta(`Fetching ${z} requests`));let B=new h.SingleBar({},h.Presets.shades_classic);B.start(z,0);let V=0,{baseName:H,extension:U}=o(j),W=I.map((e,t)=>I.length===1?j:`${H}-${t}${U}`),G=[],K=await m(I,async(e,r)=>{let i=W[r],o,l=0;try{await a(M,{actions:y,text:x,statuses:b,createdAtBefore:e.createdAtBefore,createdAtAfter:e.createdAtAfter,updatedAtBefore:D,updatedAtAfter:O,isTest:k,onPage:async e=>{if(e.length===0)return;let t=(A?e.map(e=>({...e,requestIdentifiers:[]})):await m(e,async e=>({...e,requestIdentifiers:await n(M,N,{requestId:e.id,skipSombraCheck:!0})}),{concurrency:C})).map(g);o||(o=u(t.map(e=>Object.keys(e)).flat()),s(i,o)),c(i,t,o),l+=t.length,V+=t.length,B.update(V)}})}catch(n){let i=n instanceof Error?n.message:String(n);t.error(d.red(`Chunk ${r} failed (${e.createdAtAfter?.toISOString()??`start`} → ${e.createdAtBefore?.toISOString()??`end`}): ${i}`)),G.push({index:r,createdAtAfter:e.createdAtAfter,createdAtBefore:e.createdAtBefore,error:i})}return o||s(i,[]),l},{concurrency:F?S:1});B.stop();let q=K.reduce((e,t)=>e+t,0),J=(Date.now()-R)/1e3;if(G.length>0){t.error(d.red(`\n${G.length} chunk(s) failed. Re-run with these date ranges to fill the gaps:`));for(let e of G)t.error(d.red(` Chunk ${e.index}: --createdAtAfter=${e.createdAtAfter?.toISOString()??``} --createdAtBefore=${e.createdAtBefore?.toISOString()??``}`))}return t.info(d.green(`Streamed ${q} requests to ${W.length} file(s) in ${J}s`)),{filePaths:W,totalCount:q}}export{g as n,v as t};
|
|
2
|
-
//# sourceMappingURL=streamPrivacyRequestsToCsv-CBzh80oQ.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"streamPrivacyRequestsToCsv-CBzh80oQ.mjs","names":[],"sources":["../src/lib/requests/formatRequestForCsv.ts","../src/lib/requests/streamPrivacyRequestsToCsv.ts"],"sourcesContent":["import { groupBy } from 'lodash-es';\n\nimport type { PrivacyRequest, RequestIdentifier } from '../graphql/index.js';\n\nexport interface ExportedPrivacyRequest extends PrivacyRequest {\n /** Request identifiers */\n requestIdentifiers: RequestIdentifier[];\n}\n\n/** A single CSV row */\nexport type CsvRow = { [k in string]: string | null | number | boolean };\n\n/**\n * Format a single privacy request (with optional identifiers) into a flat CSV row.\n *\n * @param request - The request with identifiers attached\n * @returns Flat object suitable for CSV output\n */\nexport function formatRequestForCsv({\n attributeValues,\n requestIdentifiers,\n id,\n email,\n type,\n status,\n subjectType,\n details,\n createdAt,\n successfullyCompletedAt,\n country,\n locale,\n origin,\n countrySubDivision,\n isSilent,\n isTest,\n coreIdentifier,\n purpose,\n ...request\n}: ExportedPrivacyRequest): CsvRow {\n return {\n 'Request ID': id,\n 'Created At': createdAt,\n 'Successfully Completed At': successfullyCompletedAt || '',\n Email: email,\n 'Core Identifier': coreIdentifier,\n 'Request Type': type,\n 'Data Subject Type': subjectType,\n Status: status,\n Country: country,\n 'Country Sub Division': countrySubDivision,\n Details: details,\n Origin: origin,\n 'Silent Mode': isSilent,\n 'Is Test Request': isTest,\n Language: locale,\n 'Purpose Trigger Name': purpose?.title || purpose?.name || '',\n 'Purpose Trigger Value': purpose?.consent?.toString() || '',\n ...(purpose?.enrichedPreferences || []).reduce((acc: Record<string, string | boolean>, p) => {\n const title = p.preferenceTopic?.title.defaultMessage || p.name;\n return title\n ? {\n ...acc,\n [title]: p.selectValues\n ? p.selectValues.map((x) => x.name).join(';')\n : p.selectValue?.name || p.booleanValue,\n }\n : acc;\n }, {}),\n ...request,\n ...Object.entries(groupBy(attributeValues, 'attributeKey.name')).reduce(\n (acc, [name, values]) =>\n Object.assign(acc, {\n [name]: values.map(({ name: n }) => n).join(','),\n }),\n {},\n ),\n ...Object.entries(groupBy(requestIdentifiers, 'name')).reduce(\n (acc, [name, values]) =>\n Object.assign(acc, {\n [name]: values.map(({ value }) => value).join(','),\n }),\n {},\n ),\n };\n}\n","import { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport { buildTranscendGraphQLClient, createSombraGotInstance } from '@transcend-io/sdk';\nimport { map } from '@transcend-io/utils';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\nimport { uniq } from 'lodash-es';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\nimport {\n fetchAllRequestIdentifiers,\n fetchAllRequests,\n fetchRequestsTotalCount,\n validateSombraVersion,\n} from '../graphql/index.js';\nimport { initCsvFile, appendCsvRowsOrdered, parseFilePath } from '../helpers/index.js';\nimport { formatRequestForCsv, ExportedPrivacyRequest } from './formatRequestForCsv.js';\n\ninterface ChunkedDateRange {\n /** Chunk start */\n createdAtAfter: Date;\n /** Chunk end */\n createdAtBefore: Date;\n}\n\n/**\n * Split a date range into N evenly-spaced chunks.\n *\n * @param after - Start of the date range\n * @param before - End of the date range\n * @param chunks - Number of chunks to split into\n * @returns Array of date range bounds\n */\nfunction splitDateRange(after: Date, before: Date, chunks: number): ChunkedDateRange[] {\n const startMs = after.getTime();\n const endMs = before.getTime();\n const chunkSize = (endMs - startMs) / chunks;\n return Array.from({ length: chunks }, (_, i) => ({\n createdAtAfter: new Date(startMs + chunkSize * i),\n createdAtBefore: new Date(i === chunks - 1 ? endMs : startMs + chunkSize * (i + 1)),\n }));\n}\n\n/**\n * Stream privacy requests directly to CSV files, one file per date-range chunk.\n * Memory stays bounded to a single page of results at a time.\n * Supports both with and without request identifier enrichment.\n *\n * @param options - Options\n * @returns The list of written file paths and total row count\n */\nexport async function streamPrivacyRequestsToCsv({\n auth,\n sombraAuth,\n actions = [],\n statuses = [],\n identifierSearch,\n concurrency = 1,\n pageLimit = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n isTest,\n skipRequestIdentifiers = false,\n file,\n}: {\n /** Transcend API key authentication */\n auth: string;\n /** Search for a specific identifier */\n identifierSearch?: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Statuses to filter on */\n statuses?: RequestStatus[];\n /** The request action to fetch */\n actions?: RequestAction[];\n /** Number of parallel date-range chunks */\n concurrency?: number;\n /** Concurrency for fetching identifiers per page */\n pageLimit?: number;\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Filter for requests updated before this date */\n updatedAtBefore?: Date;\n /** Filter for requests updated after this date */\n updatedAtAfter?: Date;\n /** Return test requests */\n isTest?: boolean;\n /** Skip fetching request identifiers */\n skipRequestIdentifiers?: boolean;\n /** Output CSV file path */\n file: string;\n}): Promise<{\n /** Paths to written CSV files */\n filePaths: string[];\n /** Total rows written */\n totalCount: number;\n}> {\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n const sombra = skipRequestIdentifiers\n ? undefined\n : await createSombraGotInstance(transcendUrl, auth, {\n logger,\n sombraApiKey: sombraAuth,\n sombraUrl: process.env.SOMBRA_URL,\n });\n\n // Log date range\n let dateRange = '';\n if (createdAtBefore) {\n dateRange += ` before ${createdAtBefore.toISOString()}`;\n }\n if (createdAtAfter) {\n dateRange += `${dateRange ? ', and' : ''} after ${createdAtAfter.toISOString()}`;\n }\n logger.info(\n colors.magenta(\n `${\n actions.length > 0\n ? `Pulling requests of type \"${actions.join('\" , \"')}\"`\n : 'Pulling all requests'\n }${dateRange}`,\n ),\n );\n\n // Split into parallel date-range chunks when possible\n const useChunks = concurrency > 1 && createdAtAfter && createdAtBefore;\n const chunks = useChunks\n ? splitDateRange(createdAtAfter, createdAtBefore, concurrency)\n : [{ createdAtAfter, createdAtBefore }];\n\n if (useChunks) {\n logger.info(colors.magenta(`Splitting date range into ${concurrency} parallel chunks`));\n }\n\n // Fetch total count once for the shared progress bar\n const filterBy = {\n type: actions.length > 0 ? actions : undefined,\n status: statuses.length > 0 ? statuses : undefined,\n isTest,\n createdAtBefore: createdAtBefore ? createdAtBefore.toISOString() : undefined,\n createdAtAfter: createdAtAfter ? createdAtAfter.toISOString() : undefined,\n updatedAtBefore: updatedAtBefore ? updatedAtBefore.toISOString() : undefined,\n updatedAtAfter: updatedAtAfter ? updatedAtAfter.toISOString() : undefined,\n };\n\n const t0 = Date.now();\n\n // Validate Sombra version once before bulk-fetching identifiers\n if (!skipRequestIdentifiers) {\n await validateSombraVersion(client);\n }\n\n const totalExpected = await fetchRequestsTotalCount(client, filterBy);\n logger.info(colors.magenta(`Fetching ${totalExpected} requests`));\n\n const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n progressBar.start(totalExpected, 0);\n\n let globalFetched = 0;\n\n const { baseName, extension } = parseFilePath(file);\n\n const filePaths = chunks.map((_, i) =>\n chunks.length === 1 ? file : `${baseName}-${i}${extension}`,\n );\n\n interface FailedChunk {\n /** Chunk index */\n index: number;\n /** Start of failed date range */\n createdAtAfter?: Date;\n /** End of failed date range */\n createdAtBefore?: Date;\n /** Error message */\n error: string;\n }\n\n const failedChunks: FailedChunk[] = [];\n\n const chunkCounts = await map(\n chunks,\n async (chunk, i) => {\n const chunkFile = filePaths[i];\n let headers: string[] | undefined;\n let rowCount = 0;\n\n try {\n await fetchAllRequests(client, {\n actions,\n text: identifierSearch,\n statuses,\n createdAtBefore: chunk.createdAtBefore,\n createdAtAfter: chunk.createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n isTest,\n onPage: async (nodes) => {\n if (nodes.length === 0) return;\n\n // Optionally enrich each request with its identifiers\n const enriched: ExportedPrivacyRequest[] = skipRequestIdentifiers\n ? nodes.map((n) => ({ ...n, requestIdentifiers: [] }))\n : await map(\n nodes,\n async (n) => ({\n ...n,\n requestIdentifiers: await fetchAllRequestIdentifiers(client, sombra!, {\n requestId: n.id,\n skipSombraCheck: true,\n }),\n }),\n { concurrency: pageLimit },\n );\n\n const rows: Record<string, string | null | number | boolean>[] =\n enriched.map(formatRequestForCsv);\n\n if (!headers) {\n headers = uniq(rows.map((r: Record<string, unknown>) => Object.keys(r)).flat());\n initCsvFile(chunkFile, headers);\n }\n\n appendCsvRowsOrdered(chunkFile, rows, headers);\n rowCount += rows.length;\n globalFetched += rows.length;\n progressBar.update(globalFetched);\n },\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logger.error(\n colors.red(\n `Chunk ${i} failed (${\n chunk.createdAtAfter?.toISOString() ?? 'start'\n } → ${chunk.createdAtBefore?.toISOString() ?? 'end'}): ${message}`,\n ),\n );\n failedChunks.push({\n index: i,\n createdAtAfter: chunk.createdAtAfter,\n createdAtBefore: chunk.createdAtBefore,\n error: message,\n });\n }\n\n if (!headers) {\n initCsvFile(chunkFile, []);\n }\n\n return rowCount;\n },\n { concurrency: useChunks ? concurrency : 1 },\n );\n\n progressBar.stop();\n const totalCount = chunkCounts.reduce((a, b) => a + b, 0);\n const elapsed = (Date.now() - t0) / 1000;\n\n if (failedChunks.length > 0) {\n logger.error(\n colors.red(\n `\\n${failedChunks.length} chunk(s) failed. ` +\n 'Re-run with these date ranges to fill the gaps:',\n ),\n );\n for (const fc of failedChunks) {\n logger.error(\n colors.red(\n ` Chunk ${fc.index}: --createdAtAfter=${\n fc.createdAtAfter?.toISOString() ?? ''\n } --createdAtBefore=${fc.createdAtBefore?.toISOString() ?? ''}`,\n ),\n );\n }\n }\n\n logger.info(\n colors.green(`Streamed ${totalCount} requests to ${filePaths.length} file(s) in ${elapsed}s`),\n );\n\n return { filePaths, totalCount };\n}\n"],"mappings":"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"}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./logger-Bj782ZYD.mjs";import{a as t,d as n,f as r,l as i,n as a,r as o,s,t as c}from"./dataSilo-Dvi8-PkH.mjs";import{a as l,c as u,n as d,o as f,t as p}from"./dataSubject-CF784Ug0.mjs";import{EnricherType as m,RequestAction as h}from"@transcend-io/privacy-types";import{chunk as g,difference as _,flatten as v,keyBy as y,sortBy as b,uniq as x}from"lodash-es";import{apply as S}from"@transcend-io/type-utils";import C from"colors";import{makeGraphQLRequest as w}from"@transcend-io/sdk";import{map as T,mapSeries as E}from"@transcend-io/utils";import D from"cli-progress";async function O(t){let{internalSubjects:n}=await w(t,d,{logger:e});return n}async function k({"data-silos":t=[],"data-subjects":n=[],"processing-activities":r=[],enrichers:i=[]},a,o=!1){let s=x([...v(t.map(e=>e[`data-subjects`]||[])||[]),...v(r.map(({dataSubjectTypes:e})=>e??[])??[]),...v(i.map(e=>e[`data-subjects`]||[])||[]),...n.map(e=>e.type)]);if(s.length===0&&!o)return{};let c=await O(a),l=y(c,`type`),u=_(s,c.map(({type:e})=>e));return u.length>0&&(e.info(C.magenta(`Creating ${u.length} new data subjects...`)),await E(u,async t=>{e.info(C.magenta(`Creating data subject ${t}...`));let{createSubject:n}=await w(a,p,{variables:{type:t,skipPublish:!0},logger:e});e.info(C.green(`Created data subject ${t}!`)),l[t]=n.subject})),l}function A(e,t){return e.forEach(e=>{if(!t[e])throw Error(`Expected to find data subject definition: ${e}`)}),Object.values(t).filter(t=>!e.includes(t.type)).map(({id:e})=>e)}function j(e,t){return e.forEach(e=>{if(!t[e])throw Error(`Expected to find data subject definition: ${e}`)}),Object.values(t).filter(t=>!e.includes(t.type)).map(({type:e})=>e)}async function M(t,{titles:n,pageSize:r,ids:i=[],gql:o=a,integrationNames:s=[]}){e.info(C.magenta(`Fetching ${i.length===0?`all`:i.length} Data Silos...`));let c=[],l=0,u=!1;do{let{dataSilos:{nodes:a}}=await w(t,o,{variables:{filterBy:{ids:i.length>0?i:void 0,type:s.length>0?s:void 0,titles:n},first:r,offset:l},logger:e});c.push(...a),l+=r,u=a.length===r}while(u);return e.info(C.green(`Found a total of ${c.length} data silo${i.length>0?` matching IDs ${i.join(`,`)}`:``}s${s.length>0?` matching integrationNames ${s.join(`,`)}`:``}`)),c.sort((e,t)=>e.title.localeCompare(t.title))}async function N(t,r,{debug:a,includeGuessedCategories:o,pageSize:s}){let c=[],l=0,u=!1;do try{a&&e.log(C.magenta(`Pulling in subdatapoints for offset ${l}`));let{subDataPoints:{nodes:d}}=await w(t,o?n:i,{variables:{first:s,filterBy:{dataPoints:[r]},offset:l},logger:e});c.push(...d),l+=s,u=d.length===s,a&&e.log(C.green(`Pulled in subdatapoints for offset ${l} for dataPointId=${r}`))}catch(t){throw e.error(C.red(`An error fetching subdatapoints for offset ${l} for dataPointId=${r}`)),t}while(u);return b(c,`name`)}async function P(t,n,{debug:r,pageSize:i,skipSubDatapoints:a,includeGuessedCategories:o}){let c=[],l=0,u=!1;do{r&&e.info(C.magenta(`Fetching datapoints with offset: ${l}`));let{dataPoints:{nodes:d}}=await w(t,s,{variables:{first:i,filterBy:{dataSilos:[n]},offset:l},logger:e});r&&e.info(C.magenta(`Fetched ${d.length} datapoints at offset: ${l}`)),a||(await T(d,async n=>{try{r&&e.info(C.magenta(`Fetching subdatapoints for ${n.name} for datapoint offset ${l}`));let i=await N(t,n.id,{pageSize:1e3,debug:r,includeGuessedCategories:o});c.push({...n,subDataPoints:i.sort((e,t)=>e.name.localeCompare(t.name))}),r&&e.info(C.green(`Successfully fetched subdatapoints for ${n.name}`))}catch(t){throw e.error(C.red(`An error fetching subdatapoints for ${n.name} datapoint offset ${l}`)),t}},{concurrency:5}),r&&e.info(C.green(`Fetched all subdatapoints for page of datapoints at offset: ${l}`))),l+=i,u=d.length===i}while(u);return c.sort((e,t)=>e.name.localeCompare(t.name))}async function F(t,{ids:n,pageSize:r,titles:i,debug:a,skipDatapoints:s,skipSubDatapoints:c,includeGuessedCategories:l,integrationNames:u}){let d=[],f=await M(t,{titles:i,ids:n,integrationNames:u,pageSize:r,gql:o});return s||await E(f,async(n,i)=>{e.info(C.magenta(`[${i+1}/${f.length}] Fetching data silo - ${n.title}`));let o=await P(t,n.id,{debug:a,pageSize:r,skipSubDatapoints:c,includeGuessedCategories:l});a&&e.info(C.green(`[${i+1}/${f.length}] Successfully fetched datapoint for - ${n.title}`)),d.push([n,o])}),e.info(C.green(`Successfully fetched all ${f.length} data silo configurations`)),d}async function I(n,i,{pageSize:a,dataSubjectsByName:o,apiKeysByTitle:s}){let l=!1,u=new Date().getTime();e.info(C.magenta(`Syncing "${n.length}" data silos...`));let d=y(await M(i,{titles:n.map(({title:e})=>e),pageSize:a}),`title`),f=n.filter(({title:e})=>!d[e]);f.length>0&&(e.info(C.magenta(`Creating "${f.length}" data silos that did not exist...`)),await E(g(f,20),async t=>{let{createDataSilos:{dataSilos:n}}=await w(i,c,{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=>{d[e.title]=e})}),e.info(C.green(`Successfully created "${f.length}" data silos!`)));let p=g(n,20);await E(p,async(n,r)=>{e.info(C.magenta(`[Batch ${r+1}/${p.length}] Syncing "${n.length}" data silos`)),await w(i,t,{variables:{input:{dataSilos:n.map(e=>({id:d[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`]?s[e[`api-key-title`]].id:void 0,dataSubjectBlockListIds:e[`data-subjects`]?A(e[`data-subjects`],o):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 ${r+1}/${p.length}] Synced "${n.length}" data silos!`))});let m=new D.SingleBar({},D.Presets.shades_classic),h=n.filter(({datapoints:e=[]})=>e.length>0),_=n.map(({datapoints:e=[]})=>e.length).reduce((e,t)=>e+t,0);e.info(C.magenta(`Syncing "${_}" datapoints from "${h.length}" data silos...`)),m.start(_,0);let v=0;await T(h,async({datapoints:t,title:n})=>{t&&await E(t,async t=>{let a=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,o={dataSiloId:d[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:a},s=(o.subDataPoints||[]).map(({name:e})=>e),c=s.filter((e,t)=>s.indexOf(e)!==t);if(c.length>0)e.info(C.red(`\nCannot update datapoint "${t.key}" as it has duplicate sub-datapoints with the same name: \n${c.join(`
|
|
2
|
-
`)}`)),l=!0;else try{await w(i,r,{variables:o,logger:e})}catch(r){e.info(C.red(`\nFailed to update datapoint "${t.key}" for data silo "${n}"! - \n${r.message}`)),l=!0}v+=1,m.update(v)})},{concurrency:10}),m.stop();let b=new Date().getTime()-u;return e.info(C.green(`Synced "${n.length}" data silos and "${_}" datapoints in "${b/1e3}" seconds!`)),{success:!l,dataSiloTitleToId:S(d,({id:e})=>e)}}async function L(n,r){let i=!1;return e.info(C.magenta(`Syncing "${r.length}" data silo dependencies...`)),await E(g(r,20),async(r,a)=>{e.info(C.magenta(`[Batch ${a}/${r.length}] Updating "${r.length}" data silos...`));try{await w(n,t,{variables:{input:{dataSilos:r.map(([e,t])=>({id:e,dependedOnDataSiloTitles:t}))}},logger:e}),e.info(C.green(`[Batch ${a+1}/${r.length}] Synced "${r.length}" data silos!`))}catch(t){i=!0,e.info(C.red(`[Batch ${a+1}/${r.length}] Failed to update "${r.length}" silos! - ${t.message}`))}}),!i}async function R(t,n){let r=[],i=0,a=!1;do{let{enrichers:{nodes:o}}=await w(t,f,{variables:{first:20,offset:i,title:n},logger:e});r.push(...o),i+=20,a=o.length===20}while(a);return r.sort((e,t)=>e.title.localeCompare(t.title))}async function z(t,{enricher:n,identifierByName:r,dataSubjectsByName:i}){let a=(await R(t,n.title)).find(({title:e})=>e===n.title),o=n[`data-subjects`]?.map(e=>{let t=i[e];if(!t)throw Error(`Failed to find a data subject with name: ${e}`);return t.id}),s=n[`input-identifier`],c=n[`privacy-actions`]||Object.values(h);a?await w(t,u,{variables:{input:{id:a.id,title:n.title,url:n.url,headers:n.headers,testRegex:n.testRegex,lookerQueryTitle:n.lookerQueryTitle,expirationDuration:typeof n.expirationDuration==`number`?n.expirationDuration.toString():void 0,transitionRequestStatus:n.transitionRequestStatus,phoneNumbers:n.phoneNumbers,regionList:n.regionList,dataSubjectIds:o,description:n.description||``,inputIdentifier:s?r[s].id:void 0,identifiers:n[`output-identifiers`].map(e=>r[e].id),...a.type===m.Sombra?{}:{actions:c}}},logger:e}):s&&await w(t,l,{variables:{input:{title:n.title,url:n.url,type:n.type||m.Server,headers:n.headers,testRegex:n.testRegex,lookerQueryTitle:n.lookerQueryTitle,expirationDuration:typeof n.expirationDuration==`number`?n.expirationDuration.toString():void 0,transitionRequestStatus:n.transitionRequestStatus,phoneNumbers:n.phoneNumbers,dataSubjectIds:o,regionList:n.regionList,description:n.description||``,inputIdentifier:r[s].id,identifiers:n[`output-identifiers`].map(e=>r[e].id),actions:c}},logger:e})}export{N as a,I as c,k as d,O as f,M as i,j as l,z as n,F as o,P as r,L as s,R as t,A as u};
|
|
3
|
-
//# sourceMappingURL=syncEnrichers-C9HcWCrs.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"syncEnrichers-C9HcWCrs.mjs","names":[],"sources":["../src/lib/graphql/fetchDataSubjects.ts","../src/lib/graphql/syncDataSilos.ts","../src/lib/graphql/syncEnrichers.ts"],"sourcesContent":["import { RequestActionObjectResolver } from '@transcend-io/privacy-types';\nimport { makeGraphQLRequest } from '@transcend-io/sdk';\nimport { mapSeries } from '@transcend-io/utils';\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';\nimport { CREATE_DATA_SUBJECT, DATA_SUBJECTS } from './gqls/index.js';\n\nexport interface DataSubject {\n /** ID of data subject */\n id: string;\n /** Type of data subject */\n type: string;\n /** Whether active */\n active: boolean;\n /** Title of data subject */\n title: {\n /** Default message */\n defaultMessage: string;\n };\n /** Whether silent mode is enabled by default */\n adminDashboardDefaultSilentMode: boolean;\n /** Enabled actions */\n actions: {\n /** Type of action */\n type: RequestActionObjectResolver;\n }[];\n}\n\n/**\n * Fetch all data subjects in an organization\n *\n * @param client - GraphQL client\n * @returns List of data subject configurations\n */\nexport async function fetchAllDataSubjects(client: GraphQLClient): Promise<DataSubject[]> {\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 return internalSubjects;\n}\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 // Only need to fetch data subjects if specified in config\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 // Fetch all data subjects in the organization\n const internalSubjects = await fetchAllDataSubjects(client);\n const dataSubjectByName = keyBy(internalSubjects, 'type');\n\n // Determine expected set of data subjects to create\n const missingDataSubjects = difference(\n expectedDataSubjects,\n internalSubjects.map(({ type }) => type),\n );\n\n // If there are missing data subjects, create new ones\n if (missingDataSubjects.length > 0) {\n logger.info(colors.magenta(`Creating ${missingDataSubjects.length} new data subjects...`));\n await mapSeries(missingDataSubjects, async (dataSubject) => {\n logger.info(colors.magenta(`Creating data subject ${dataSubject}...`));\n const { createSubject } = await makeGraphQLRequest<{\n /** Create Subject Response */\n createSubject: {\n /** Created Data Subject */\n subject: DataSubject;\n };\n }>(client, CREATE_DATA_SUBJECT, {\n variables: { type: dataSubject, skipPublish: true },\n logger,\n });\n logger.info(colors.green(`Created data subject ${dataSubject}!`));\n\n dataSubjectByName[dataSubject] = createSubject.subject;\n });\n }\n\n return dataSubjectByName;\n}\n\n/**\n * Convert a list of data subject types into the block list of IDs to assign to the data silo\n *\n * @param dataSubjectTypes - The list of data subject types that the data silo should be for\n * @param allDataSubjects - All data subjects in the organization\n * @returns The block list of data subject ids to not process against this data silo\n */\nexport function convertToDataSubjectBlockList(\n dataSubjectTypes: string[],\n allDataSubjects: { [type in string]: DataSubject },\n): string[] {\n dataSubjectTypes.forEach((type) => {\n if (!allDataSubjects[type]) {\n throw new Error(`Expected to find data subject definition: ${type}`);\n }\n });\n\n return Object.values(allDataSubjects)\n .filter((silo) => !dataSubjectTypes.includes(silo.type))\n .map(({ id }) => id);\n}\n\n/**\n * Convert a list of data subject types into the allow list of types\n *\n * @param dataSubjectTypes - The list of data subject types that the data silo should be for\n * @param allDataSubjects - All data subjects in the organization\n * @returns The allow list of data subjects for that silo\n */\nexport function convertToDataSubjectAllowlist(\n dataSubjectTypes: string[],\n allDataSubjects: { [type in string]: DataSubject },\n): string[] {\n dataSubjectTypes.forEach((type) => {\n if (!allDataSubjects[type]) {\n throw new Error(`Expected to find data subject definition: ${type}`);\n }\n });\n\n return Object.values(allDataSubjects)\n .filter((silo) => !dataSubjectTypes.includes(silo.type))\n .map(({ type }) => type);\n}\n","import {\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n PromptAVendorEmailCompletionLinkType,\n PromptAVendorEmailSendType,\n ConfidenceLabel,\n RequestActionObjectResolver,\n SubDataPointDataSubCategoryGuessStatus,\n} from '@transcend-io/privacy-types';\nimport { makeGraphQLRequest, ApiKey } 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 { sortBy, chunk, keyBy } from 'lodash-es';\n\nimport { DataCategoryInput, DataSiloInput, ProcessingPurposeInput } from '../../codecs.js';\nimport { logger } from '../../logger.js';\nimport { convertToDataSubjectBlockList, DataSubject } from './fetchDataSubjects.js';\nimport {\n DATA_SILOS,\n CREATE_DATA_SILOS,\n UPDATE_OR_CREATE_DATA_POINT,\n DATA_POINTS,\n SUB_DATA_POINTS,\n UPDATE_DATA_SILOS,\n DATA_SILOS_ENRICHED,\n SUB_DATA_POINTS_WITH_GUESSES,\n} from './gqls/index.js';\n\nexport interface DataSiloAttributeValue {\n /** Key associated to value */\n attributeKey: {\n /** Name of key */\n name: string;\n };\n /** Name of value */\n name: string;\n}\nexport interface DataSilo {\n /** ID of dataSilo */\n id: string;\n /** Title of dataSilo */\n title: string;\n /** Type of silo */\n type: string;\n /** The link to the data silo */\n link: string;\n /** Attribute labels */\n attributeValues: DataSiloAttributeValue[];\n /** description */\n description: string;\n /** Metadata for this data silo */\n catalog: {\n /** Whether the data silo supports automated vendor coordination */\n hasAvcFunctionality: boolean;\n };\n}\n\nconst BATCH_SILOS_LIMIT = 20;\n\n/**\n * Fetch all dataSilos in the organization\n *\n * @param client - GraphQL client\n * @param title - Filter by title\n * @returns All dataSilos in the organization\n */\nexport async function fetchAllDataSilos<TDataSilo extends DataSilo>(\n client: GraphQLClient,\n {\n titles,\n pageSize,\n ids = [],\n gql = DATA_SILOS,\n integrationNames = [],\n }: {\n /** Page size to fetch datapoints in */\n pageSize: number;\n /** Title */\n titles?: string[];\n /** IDs */\n ids?: string[];\n /** Set of integration names to fetch */\n integrationNames?: string[];\n /** GQL query for data silos */\n gql?: string;\n },\n): Promise<TDataSilo[]> {\n logger.info(colors.magenta(`Fetching ${ids.length === 0 ? 'all' : ids.length} Data Silos...`));\n\n const dataSilos: TDataSilo[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n dataSilos: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n dataSilos: {\n /** List of matches */\n nodes: TDataSilo[];\n };\n }>(client, gql, {\n variables: {\n filterBy: {\n ids: ids.length > 0 ? ids : undefined,\n type: integrationNames.length > 0 ? integrationNames : undefined,\n titles,\n },\n first: pageSize,\n offset,\n },\n logger,\n });\n dataSilos.push(...nodes);\n offset += pageSize;\n shouldContinue = nodes.length === pageSize;\n } while (shouldContinue);\n logger.info(\n colors.green(\n `Found a total of ${dataSilos.length} data silo${\n ids.length > 0 ? ` matching IDs ${ids.join(',')}` : ''\n }s${\n integrationNames.length > 0\n ? ` matching integrationNames ${integrationNames.join(',')}`\n : ''\n }`,\n ),\n );\n\n return dataSilos.sort((a, b) => a.title.localeCompare(b.title));\n}\n\nexport interface SubDataPoint {\n /** Name (or key) of the subdatapoint */\n name: string;\n /** The description */\n description?: string;\n /** Personal data category */\n categories: DataCategoryInput[];\n /** The processing purpose for this sub datapoint */\n purposes: ProcessingPurposeInput[];\n /**\n * When true, this subdatapoint should be revealed in a data access request.\n * When false, this field should be redacted\n */\n accessRequestVisibilityEnabled: boolean;\n /**\n * When true, this subdatapoint should be redacted during an erasure request.\n * There normally is a choice of enabling hard deletion or redaction at the\n * datapoint level, but if redaction is enabled, this column can be used\n * to define which fields should be redacted.\n */\n erasureRequestRedactionEnabled: boolean;\n /** Attribute attached to subdatapoint */\n attributeValues: DataSiloAttributeValue[];\n /** Data category guesses that are output by the classifier */\n pendingCategoryGuesses?: {\n /** Data category being guessed */\n category: DataCategoryInput;\n /** Status of guess */\n status: SubDataPointDataSubCategoryGuessStatus;\n /** Confidence level of guess */\n confidence: number;\n /** Confidence label */\n confidenceLabel: ConfidenceLabel;\n /** classifier version that produced the guess */\n classifierVersion: number;\n }[];\n}\n\ninterface DataPoint {\n /** ID of dataPoint */\n id: string;\n /** Title of dataPoint */\n title: {\n /** Default message */\n defaultMessage: string;\n };\n /** The path to this data point */\n path: string[];\n /** Description */\n description: {\n /** Default message */\n defaultMessage: string;\n };\n /** Name */\n name: string;\n /** Global actions */\n actionSettings: {\n /** Action type */\n type: RequestActionObjectResolver;\n /** Is enabled */\n active: boolean;\n }[];\n /** Data collection tag for privacy request download zip labeling */\n dataCollection?: {\n /** Title of data collection */\n title: {\n /** Default message (since message can be translated) */\n defaultMessage: string;\n };\n };\n /** Metadata for this data silo */\n catalog: {\n /** Whether the data silo supports automated vendor coordination */\n hasAvcFunctionality: boolean;\n };\n /** Owners of the datapoint */\n owners: {\n /** Email address of the owner */\n email: string;\n }[];\n /** Teams that own the datapoint */\n teams: {\n /** Name of the team */\n name: string;\n }[];\n /** Database integration queries */\n dbIntegrationQueries: {\n /** Approved query */\n query: string | null;\n /** Suggested query */\n suggestedQuery: string | null;\n /** Request action */\n requestType: RequestActionObjectResolver;\n }[];\n}\n\ninterface DataPointWithSubDataPoint extends DataPoint {\n /** The associated subdatapoints */\n subDataPoints: SubDataPoint[];\n}\n\n/**\n * Helper to fetch all subdatapoints for a given datapoint\n *\n * @param client - The GraphQL client\n * @param dataPointId - The datapoint ID\n * @param options - Options\n * @returns The list of subdatapoints\n */\nexport async function fetchAllSubDataPoints(\n client: GraphQLClient,\n dataPointId: string,\n {\n debug,\n includeGuessedCategories,\n pageSize,\n }: {\n /** Debug logs */\n debug: boolean;\n /** Page size */\n pageSize: number;\n /** When true, metadata around guessed data categories should be included */\n includeGuessedCategories?: boolean;\n },\n): Promise<SubDataPoint[]> {\n const subDataPoints: SubDataPoint[] = [];\n\n let offset = 0;\n\n let shouldContinue = false;\n do {\n try {\n if (debug) {\n logger.log(colors.magenta(`Pulling in subdatapoints for offset ${offset}`));\n }\n const {\n subDataPoints: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n subDataPoints: {\n /** List of matches */\n nodes: SubDataPoint[];\n };\n }>(client, includeGuessedCategories ? SUB_DATA_POINTS_WITH_GUESSES : SUB_DATA_POINTS, {\n variables: {\n first: pageSize,\n filterBy: {\n dataPoints: [dataPointId],\n },\n offset,\n },\n logger,\n });\n\n subDataPoints.push(...nodes);\n offset += pageSize;\n shouldContinue = nodes.length === pageSize;\n\n if (debug) {\n logger.log(\n colors.green(\n `Pulled in subdatapoints for offset ${offset} for dataPointId=${dataPointId}`,\n ),\n );\n }\n } catch (err) {\n logger.error(\n colors.red(\n `An error fetching subdatapoints for offset ${offset} for dataPointId=${dataPointId}`,\n ),\n );\n throw err;\n }\n } while (shouldContinue);\n return sortBy(subDataPoints, 'name');\n}\n\n/**\n * Fetch all datapoints for a data silo\n *\n * @param client - GraphQL client\n * @param dataSiloId - Data silo ID\n * @param options - Options\n * @returns List of datapoints\n */\nexport async function fetchAllDataPoints(\n client: GraphQLClient,\n dataSiloId: string,\n {\n debug,\n pageSize,\n skipSubDatapoints,\n includeGuessedCategories,\n }: {\n /** Debug logs */\n debug: boolean;\n /** Page size */\n pageSize: number;\n /** Skip fetching of subdatapoints */\n skipSubDatapoints?: boolean;\n /** When true, metadata around guessed data categories should be included */\n includeGuessedCategories?: boolean;\n },\n): Promise<DataPointWithSubDataPoint[]> {\n const dataPoints: DataPointWithSubDataPoint[] = [];\n\n // TODO: https://transcend.height.app/T-40481 - add cursor pagination\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n if (debug) {\n logger.info(colors.magenta(`Fetching datapoints with offset: ${offset}`));\n }\n\n const {\n dataPoints: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n dataPoints: {\n /** List of matches */\n nodes: DataPoint[];\n };\n }>(client, DATA_POINTS, {\n variables: {\n first: pageSize,\n filterBy: {\n dataSilos: [dataSiloId],\n },\n offset,\n },\n logger,\n });\n\n if (debug) {\n logger.info(colors.magenta(`Fetched ${nodes.length} datapoints at offset: ${offset}`));\n }\n\n if (!skipSubDatapoints) {\n await map(\n nodes,\n /* eslint-disable no-loop-func */\n async (node) => {\n try {\n if (debug) {\n logger.info(\n colors.magenta(\n `Fetching subdatapoints for ${node.name} for datapoint offset ${offset}`,\n ),\n );\n }\n\n const subDataPoints = await fetchAllSubDataPoints(client, node.id, {\n pageSize: 1000, // max page size\n debug,\n includeGuessedCategories,\n });\n dataPoints.push({\n ...node,\n subDataPoints: subDataPoints.sort((a, b) => a.name.localeCompare(b.name)),\n });\n\n if (debug) {\n logger.info(colors.green(`Successfully fetched subdatapoints for ${node.name}`));\n }\n } catch (err) {\n logger.error(\n colors.red(\n `An error fetching subdatapoints for ${node.name} datapoint offset ${offset}`,\n ),\n );\n throw err;\n }\n },\n /* eslint-enable no-loop-func */\n {\n concurrency: 5,\n },\n );\n\n if (debug) {\n logger.info(\n colors.green(`Fetched all subdatapoints for page of datapoints at offset: ${offset}`),\n );\n }\n }\n\n offset += pageSize;\n shouldContinue = nodes.length === pageSize;\n } while (shouldContinue);\n return dataPoints.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport interface DataSiloEnriched {\n /** ID of dataSilo */\n id: string;\n /** Title of dataSilo */\n title: string;\n /** Type of silo */\n type: string;\n /** Link to silo */\n link: string;\n /** Outer type of silo */\n outerType: string;\n /** Description of data silo */\n description: string;\n /** Webhook URL */\n url?: string;\n /** Email address of user to notify for prompt a person use case */\n notifyEmailAddress?: string;\n /** Associated API keys */\n apiKeys: {\n /** Title */\n title: string;\n }[];\n /** Data subject block list */\n subjectBlocklist: {\n /** Type of data subject */\n type: string;\n }[];\n /** Identifiers */\n identifiers: {\n /** Name of identifier */\n name: string;\n /** True if identifier is wired */\n isConnected: boolean;\n }[];\n /** Dependent data silos */\n dependentDataSilos: {\n /** Title of silo */\n title: string;\n }[];\n /** Silo owners */\n owners: {\n /** Email owners */\n email: string;\n }[];\n /** The teams assigned to this data silo */\n teams: {\n /** Name of the team assigned to this data silo */\n name: string;\n }[];\n /** Metadata for this data silo */\n catalog: {\n /** Whether the data silo supports automated vendor coordination */\n hasAvcFunctionality: boolean;\n };\n /** Silo is live */\n isLive: boolean;\n /** Hosting country of data silo */\n country?: IsoCountryCode;\n /** Hosting subdivision data silo */\n countrySubDivision?: IsoCountrySubdivisionCode;\n /**\n * The frequency with which we should be sending emails for this data silo, in milliseconds.\n */\n promptAVendorEmailSendFrequency: number;\n /**\n * The type of emails to send for this data silo, i.e. send an email for each DSR, across all open DSRs,\n * or per profile in a DSR.\n */\n promptAVendorEmailSendType: PromptAVendorEmailSendType;\n /**\n * Indicates whether prompt-a-vendor emails should include a list of identifiers\n * in addition to a link to the bulk processing UI.\n */\n promptAVendorEmailIncludeIdentifiersAttachment: boolean;\n /**\n * Indicates what kind of link to generate as part of the emails sent out for this Prompt-a-Vendor silo.\n */\n promptAVendorEmailCompletionLinkType: PromptAVendorEmailCompletionLinkType;\n /**\n * The frequency with which we should retry sending emails for this data silo, in milliseconds.\n * Needs to be a string because the number can be larger than the MAX_INT\n */\n manualWorkRetryFrequency: string;\n /** Attribute values tagged to data silo */\n attributeValues: DataSiloAttributeValue[];\n /**\n * The data silos that discovered this particular data silo\n */\n discoveredBy: {\n /** Title of data silo */\n title: string;\n }[];\n /**\n * The business entities assigned directly to this data silo\n */\n businessEntities: {\n /** Title of business entity */\n title: string;\n }[];\n}\n\n/**\n * Fetch all dataSilos with additional metadata\n *\n * @param client - GraphQL client\n * @param options - Filter options\n * @returns All dataSilos in the organization\n */\nexport async function fetchEnrichedDataSilos(\n client: GraphQLClient,\n {\n ids,\n pageSize,\n titles,\n debug,\n skipDatapoints,\n skipSubDatapoints,\n includeGuessedCategories,\n integrationNames,\n }: {\n /** Page size */\n pageSize: number;\n /** Filter by IDs */\n ids?: string[];\n /** Enable debug logs */\n debug: boolean;\n /** Filter by title */\n titles?: string[];\n /** Integration names */\n integrationNames?: string[];\n /** Skip fetching of datapoints */\n skipDatapoints?: boolean;\n /** Skip fetching of subdatapoints */\n skipSubDatapoints?: boolean;\n /** When true, metadata around guessed data categories should be included */\n includeGuessedCategories?: boolean;\n },\n): Promise<[DataSiloEnriched, DataPointWithSubDataPoint[]][]> {\n const dataSilos: [DataSiloEnriched, DataPointWithSubDataPoint[]][] = [];\n\n // Grab silos\n const silos = await fetchAllDataSilos<DataSiloEnriched>(client, {\n titles,\n ids,\n integrationNames,\n pageSize,\n gql: DATA_SILOS_ENRICHED,\n });\n\n // Graph datapoints for each silo\n if (!skipDatapoints) {\n await mapSeries(silos, async (silo, index) => {\n logger.info(\n colors.magenta(`[${index + 1}/${silos.length}] Fetching data silo - ${silo.title}`),\n );\n\n const dataPoints = await fetchAllDataPoints(client, silo.id, {\n debug,\n pageSize,\n skipSubDatapoints,\n includeGuessedCategories,\n });\n\n if (debug) {\n logger.info(\n colors.green(\n `[${index + 1}/${silos.length}] Successfully fetched datapoint for - ${silo.title}`,\n ),\n );\n }\n\n dataSilos.push([silo, dataPoints]);\n });\n }\n\n logger.info(colors.green(`Successfully fetched all ${silos.length} data silo configurations`));\n\n return dataSilos;\n}\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 });\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\n/**\n * Sync data silo dependencies\n *\n * @param client - GraphQL client\n * @param dependencyUpdates - Mapping from [data silo ID, dependency titles]\n * @returns True upon success\n */\nexport async function syncDataSiloDependencies(\n client: GraphQLClient,\n dependencyUpdates: [string, string[]][],\n): Promise<boolean> {\n let encounteredError = false;\n logger.info(colors.magenta(`Syncing \"${dependencyUpdates.length}\" data silo dependencies...`));\n\n // Batch the updates\n const chunkedUpdates = chunk(dependencyUpdates, BATCH_SILOS_LIMIT);\n await mapSeries(chunkedUpdates, async (dependencyUpdateChunk, ind) => {\n logger.info(\n colors.magenta(\n `[Batch ${ind}/${dependencyUpdateChunk.length}] Updating \"${dependencyUpdateChunk.length}\" data silos...`,\n ),\n );\n try {\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: dependencyUpdateChunk.map(([id, dependedOnDataSiloTitles]) => ({\n id,\n dependedOnDataSiloTitles,\n })),\n },\n },\n logger,\n });\n logger.info(\n colors.green(\n `[Batch ${ind + 1}/${dependencyUpdateChunk.length}] ` +\n `Synced \"${dependencyUpdateChunk.length}\" data silos!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `[Batch ${ind + 1}/${dependencyUpdateChunk.length}] ` +\n `Failed to update \"${dependencyUpdateChunk.length}\" silos! - ${err.message}`,\n ),\n );\n }\n });\n return !encounteredError;\n}\n/* eslint-enable max-lines */\n","import {\n EnricherType,\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n PreflightRequestStatus,\n RequestAction,\n} from '@transcend-io/privacy-types';\nimport { makeGraphQLRequest, type Identifier } from '@transcend-io/sdk';\nimport { GraphQLClient } from 'graphql-request';\n\nimport { EnricherInput } from '../../codecs.js';\nimport { logger } from '../../logger.js';\nimport { DataSubject } from './fetchDataSubjects.js';\nimport { ENRICHERS, CREATE_ENRICHER, UPDATE_ENRICHER } from './gqls/index.js';\n\nexport interface Enricher {\n /** ID of enricher */\n id: string;\n /** Title of enricher */\n title: string;\n /** URL of enricher */\n url: string;\n /** Server silo */\n type: EnricherType;\n /** Input identifier */\n inputIdentifier: {\n /** Identifier name */\n name: string;\n };\n /** The selected actions */\n actions: RequestAction[];\n /** Output identifiers */\n identifiers: {\n /** Identifier name */\n name: string;\n }[];\n /** Data subjects that the preflight check is configured for */\n dataSubjects: {\n /** Data subject type */\n type: string;\n }[];\n /** The duration (in ms) that the enricher should take to execute. - BigInt */\n expirationDuration: string;\n /** Looker query title */\n lookerQueryTitle?: string;\n /** A regular expression that can be used to match on for cancelation */\n testRegex?: string;\n /** The status that the enricher should transfer to when condition is met. */\n transitionRequestStatus?: PreflightRequestStatus;\n /** The twilio phone number to send from */\n phoneNumbers: string[];\n /**\n * The list of regions that should trigger the enrichment condition\n */\n regionList: (IsoCountryCode | IsoCountrySubdivisionCode)[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all enrichers in the organization\n *\n * @param client - GraphQL client\n * @param title - Filter by title\n * @returns All enrichers in the organization\n */\nexport async function fetchAllEnrichers(\n client: GraphQLClient,\n title?: string,\n): Promise<Enricher[]> {\n const enrichers: Enricher[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n enrichers: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n enrichers: {\n /** List of matches */\n nodes: Enricher[];\n };\n }>(client, ENRICHERS, {\n variables: { first: PAGE_SIZE, offset, title },\n logger,\n });\n enrichers.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return enrichers.sort((a, b) => a.title.localeCompare(b.title));\n}\n\n/**\n * Sync an enricher configuration\n *\n * @param client - GraphQL client\n * @param options - Options\n */\nexport async function syncEnricher(\n client: GraphQLClient,\n {\n enricher,\n identifierByName,\n dataSubjectsByName,\n }: {\n /** The enricher input */\n enricher: EnricherInput;\n /** Index of identifiers in the organization */\n identifierByName: { [name in string]: Identifier };\n /** Lookup data subject by name */\n dataSubjectsByName: { [name in string]: DataSubject };\n },\n): Promise<void> {\n // Whether to continue looping\n const matches = await fetchAllEnrichers(client, enricher.title);\n const existingEnricher = matches.find(({ title }) => title === enricher.title);\n\n // Map to data subject Ids\n const dataSubjectIds = enricher['data-subjects']?.map((subject) => {\n const existing = dataSubjectsByName[subject];\n if (!existing) {\n throw new Error(`Failed to find a data subject with name: ${subject}`);\n }\n return existing.id;\n });\n\n // If enricher exists, update it, else create new\n const inputIdentifier = enricher['input-identifier'];\n const actionUpdates = enricher['privacy-actions'] || Object.values(RequestAction);\n if (existingEnricher) {\n await makeGraphQLRequest(client, UPDATE_ENRICHER, {\n variables: {\n input: {\n id: existingEnricher.id,\n title: enricher.title,\n url: enricher.url,\n headers: enricher.headers,\n testRegex: enricher.testRegex,\n lookerQueryTitle: enricher.lookerQueryTitle,\n expirationDuration:\n typeof enricher.expirationDuration === 'number'\n ? enricher.expirationDuration.toString()\n : undefined,\n transitionRequestStatus: enricher.transitionRequestStatus,\n phoneNumbers: enricher.phoneNumbers,\n regionList: enricher.regionList,\n dataSubjectIds,\n description: enricher.description || '',\n inputIdentifier: inputIdentifier ? identifierByName[inputIdentifier].id : undefined,\n identifiers: enricher['output-identifiers'].map((id) => identifierByName[id].id),\n ...(existingEnricher.type === EnricherType.Sombra ? {} : { actions: actionUpdates }),\n },\n },\n logger,\n });\n } else if (inputIdentifier) {\n await makeGraphQLRequest(client, CREATE_ENRICHER, {\n variables: {\n input: {\n title: enricher.title,\n url: enricher.url,\n type: enricher.type || EnricherType.Server,\n headers: enricher.headers,\n testRegex: enricher.testRegex,\n lookerQueryTitle: enricher.lookerQueryTitle,\n expirationDuration:\n typeof enricher.expirationDuration === 'number'\n ? enricher.expirationDuration.toString()\n : undefined,\n transitionRequestStatus: enricher.transitionRequestStatus,\n phoneNumbers: enricher.phoneNumbers,\n dataSubjectIds,\n regionList: enricher.regionList,\n description: enricher.description || '',\n inputIdentifier: identifierByName[inputIdentifier].id,\n identifiers: enricher['output-identifiers'].map((id) => identifierByName[id].id),\n actions: actionUpdates,\n },\n },\n logger,\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{a as e}from"./constants-XOsAW1__.mjs";import{t}from"./logger-Bj782ZYD.mjs";import{ConsentBundleType as n}from"@transcend-io/privacy-types";import r from"colors";import{buildTranscendGraphQLClient as i,deployConsentManager as a,fetchConsentManagerId as o,updateConsentManagerToLatest as s}from"@transcend-io/sdk";import{mapSeries as c}from"@transcend-io/utils";async function l({auth:l,deploy:u=!1,transcendUrl:d=e,bundleTypes:f=Object.values(n)}){let p=i(d,l),m=await o(p,{logger:t});await c(f,async e=>{t.info(r.magenta(`Update Consent Manager bundle with ID "${m}" and type "${e}" to latest version...`)),await s(p,{id:m,bundleType:e},{logger:t}),t.info(r.green(`Updated Consent Manager bundle with ID "${m}" and type "${e}" to latest version!`))}),u&&await c(f,async e=>{t.info(r.magenta(`Deploying Consent Manager bundle with ID "${m}" and type "${e}"...`)),await a(p,{id:m,bundleType:e},{logger:t}),t.info(r.green(`Deployed Consent Manager bundle with ID "${m}" and type "${e}"!`))})}export{l as t};
|
|
2
|
-
//# sourceMappingURL=updateConsentManagerVersionToLatest-X1HAM_IX.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"updateConsentManagerVersionToLatest-X1HAM_IX.mjs","names":[],"sources":["../src/lib/consent-manager/updateConsentManagerVersionToLatest.ts"],"sourcesContent":["import { ConsentBundleType } from '@transcend-io/privacy-types';\nimport {\n buildTranscendGraphQLClient,\n deployConsentManager,\n fetchConsentManagerId,\n updateConsentManagerToLatest,\n} from '@transcend-io/sdk';\nimport { mapSeries } from '@transcend-io/utils';\nimport colors from 'colors';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants.js';\nimport { logger } from '../../logger.js';\n\n/**\n * Update the consent manager to latest version\n *\n * @param options - Options\n */\nexport async function updateConsentManagerVersionToLatest({\n auth,\n deploy = false,\n transcendUrl = DEFAULT_TRANSCEND_API,\n bundleTypes = Object.values(ConsentBundleType),\n}: {\n /** Transcend API key authentication */\n auth: string;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Deploy consent manager with this update */\n deploy?: boolean;\n /** The bundle types to update and deploy */\n bundleTypes?: ConsentBundleType[];\n}): Promise<void> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Grab Consent Manager ID\n const consentManagerId = await fetchConsentManagerId(client, { logger });\n\n // Update each bundle type to latest version\n await mapSeries(bundleTypes, async (bundleType) => {\n logger.info(\n colors.magenta(\n `Update Consent Manager bundle with ID \"${consentManagerId}\" and type \"${bundleType}\" to latest version...`,\n ),\n );\n await updateConsentManagerToLatest(\n client,\n {\n id: consentManagerId,\n bundleType,\n },\n { logger },\n );\n logger.info(\n colors.green(\n `Updated Consent Manager bundle with ID \"${consentManagerId}\" and type \"${bundleType}\" to latest version!`,\n ),\n );\n });\n\n // deploy Consent Managers\n if (deploy) {\n // Update each bundle type to latest version\n await mapSeries(bundleTypes, async (bundleType) => {\n logger.info(\n colors.magenta(\n `Deploying Consent Manager bundle with ID \"${consentManagerId}\" and type \"${bundleType}\"...`,\n ),\n );\n await deployConsentManager(\n client,\n {\n id: consentManagerId,\n bundleType,\n },\n { logger },\n );\n logger.info(\n colors.green(\n `Deployed Consent Manager bundle with ID \"${consentManagerId}\" and type \"${bundleType}\"!`,\n ),\n );\n });\n }\n}\n"],"mappings":"+WAkBA,eAAsB,EAAoC,CACxD,OACA,SAAS,GACT,eAAe,EACf,cAAc,OAAO,OAAO,EAAkB,EAU9B,CAEhB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAmB,MAAM,EAAsB,EAAQ,CAAE,SAAQ,CAAC,CAGxE,MAAM,EAAU,EAAa,KAAO,IAAe,CACjD,EAAO,KACL,EAAO,QACL,0CAA0C,EAAiB,cAAc,EAAW,wBACrF,CACF,CACD,MAAM,EACJ,EACA,CACE,GAAI,EACJ,aACD,CACD,CAAE,SAAQ,CACX,CACD,EAAO,KACL,EAAO,MACL,2CAA2C,EAAiB,cAAc,EAAW,sBACtF,CACF,EACD,CAGE,GAEF,MAAM,EAAU,EAAa,KAAO,IAAe,CACjD,EAAO,KACL,EAAO,QACL,6CAA6C,EAAiB,cAAc,EAAW,MACxF,CACF,CACD,MAAM,EACJ,EACA,CACE,GAAI,EACJ,aACD,CACD,CAAE,SAAQ,CACX,CACD,EAAO,KACL,EAAO,MACL,4CAA4C,EAAiB,cAAc,EAAW,IACvF,CACF,EACD"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{a as e}from"./constants-XOsAW1__.mjs";import{t}from"./logger-Bj782ZYD.mjs";import{n,s as r}from"./dataSubject-CF784Ug0.mjs";import{a as i,c as a,i as o,l as s,o as c,r as l,s as u,t as d}from"./constants-DYbzl8QH.mjs";import{i as f,n as p,r as m,t as h}from"./parseAttributesFromString-B8h4DudO.mjs";import{t as g}from"./readCsv-0PIlJQCN.mjs";import{r as _,t as v}from"./extractClientError-X9wJVqGq.mjs";import{CompletedRequestStatus as y,IdentifierType as b,IsoCountryCode as x,IsoCountrySubdivisionCode as S,NORMALIZE_PHONE_NUMBER as C,RequestAction as w}from"@transcend-io/privacy-types";import{startCase as T,uniq as E}from"lodash-es";import{apply as D,getEntries as O,getValues as k,valuesOf as A}from"@transcend-io/type-utils";import{join as ee}from"node:path";import j from"colors";import{LOCALE_KEY as M}from"@transcend-io/internationalization";import*as N from"io-ts";import{ATTRIBUTE_KEYS_REQUESTS as P,buildTranscendGraphQLClient as te,createSombraGotInstance as ne,makeGraphQLRequest as F}from"@transcend-io/sdk";import{map as re,splitCsvToList as I}from"@transcend-io/utils";import L from"cli-progress";import R from"inquirer";import z from"inquirer-autocomplete-prompt";import{DateFromISOString as B}from"io-ts-types";import{PersistedState as V}from"@transcend-io/persisted-state";async function H(e,t,n){R.registerPrompt(`autocomplete`,z);let r=e.map(e=>e||`<blank>`).filter(e=>!n[e]);if(r.length===0)return n;let i=await R.prompt(r.map(e=>({name:e,message:`Map value of: ${e}`,type:`autocomplete`,default:t.find(t=>f(e,t)),source:(e,n)=>n?t.filter(e=>typeof e==`string`&&f(n,e)):t})));return{...n,...D(i,e=>typeof e==`string`?e:Object.values(e)[0])}}function U(e,t){return E(e.map(e=>e[t]||``).flat())}async function W(e){let n=E(e.map(e=>Object.keys(e)).flat()),r=e,i=!0;for(;i;){let{filterColumnName:e}=await R.prompt([{name:`filterColumnName`,message:`If you need to filter the list of requests to import, choose the column to filter on. Currently ${r.length} rows.`,type:`list`,default:n,choices:[s,...n]}]);if(i=s!==e,i){let t=U(r,e),{valuesToKeep:i}=await R.prompt([{name:`valuesToKeep`,message:`Keep rows matching this value`,type:`checkbox`,default:n,choices:t}]);r=r.filter(t=>i.includes(t[e]))}}return t.info(j.magenta(`Importing ${r.length} requests`)),r}async function G(e){let n=[],r=0,i=!1;do{let{attributeKeys:{nodes:a}}=await F(e,P,{variables:{first:20,offset:r},logger:t});n.push(...a),r+=20,i=a.length===20}while(i);return n.sort((e,t)=>e.name.localeCompare(t.name))}async function K(e,t){let n=k(c).filter(e=>!t.getValue(`columnNames`,e)),r=n.length===0?{}:await R.prompt(n.map(t=>{let n=T(t.replace(`ColumnName`,``)),r=m(e,n,a[t],!!l[t]);return{name:t,message:`Choose the column that will be used to map in the field: ${n}`,type:`list`,default:r[0],choices:r}}));return await Promise.all(O(r).map(([e,n])=>t.setValue(n,`columnNames`,e))),r}async function q(e,r,{state:i,columnNameMap:a}){let o=e=>i.getValue(`columnNames`,e)||a[e],{internalSubjects:l}=await F(e,n,{logger:t});t.info(j.magenta(`Determining mapping of columns for request action`));let u=await H(U(r,o(c.RequestType)),Object.values(w),i.getValue(`requestTypeToRequestAction`));await i.setValue(u,`requestTypeToRequestAction`),t.info(j.magenta(`Determining mapping of columns for subject`));let d=await H(U(r,o(c.SubjectType)),l.map(({type:e})=>e),i.getValue(`subjectTypeToSubjectName`));await i.setValue(d,`subjectTypeToSubjectName`),t.info(j.magenta(`Determining mapping of columns for locale`));let f=await H(U(r,o(c.Locale)),Object.values(M),i.getValue(`languageToLocale`));await i.setValue(f,`languageToLocale`),t.info(j.magenta(`Determining mapping of columns for request status`)),t.info(j.magenta(`Determining mapping of columns for request status`));let p=o(c.RequestStatus),m=p===`[NONE]`?{}:await H(U(r,p),[...Object.values(y),s],i.getValue(`statusToRequestStatus`));await i.setValue(m,`statusToRequestStatus`),t.info(j.magenta(`Determining mapping of columns for country`));let h=o(c.Country),g=h===`[NONE]`?{}:await H(U(r,h),[...Object.values(x),s],i.getValue(`regionToCountry`));await i.setValue(g,`regionToCountry`),t.info(j.magenta(`Determining mapping of columns for country sub division`));let _=o(c.CountrySubDivision),v=_===`[NONE]`?{}:await H(U(r,_),[...Object.values(S),s],i.getValue(`regionToCountrySubDivision`));await i.setValue(v,`regionToCountrySubDivision`)}const J=N.record(N.string,N.array(N.intersection([N.type({value:N.string}),N.partial({name:N.string})]))),Y=N.intersection([N.type({email:N.string,attestedExtraIdentifiers:J,coreIdentifier:N.string,requestType:A(w),subjectType:N.string}),N.partial({country:A(x),countrySubDivision:A(S),attributes:N.array(h),status:A(y),createdAt:B,dataSiloIds:N.array(N.string),locale:A(M)})]);function X(e,t,n){if(t===b.Email)return e.toLowerCase();if(t===b.Phone){let t=e.replace(C,``).replace(/[()]/g,``).replace(/[–]/g,``).replace(/[:]/g,``).replace(/[]/g,``).replace(/[A-Za-z]/g,``);return t?t.startsWith(`+`)?t:`+${n}${t}`:``}return e}function Z(e,t,{columnNameMap:n,identifierNameMap:r,attributeNameMap:i,requestAttributeKeys:a,defaultPhoneCountryCode:o=`1`}){let l=e=>t.getValue(`columnNames`,e)||n[e];return e.map(e=>{let n={};Object.entries(r).filter(([,e])=>e!==s).forEach(([t,r])=>{let i=Object.values(b).includes(t)?t:b.Custom,a=e[r];if(a){let e=X(a,i,o);e&&(n[i]||(n[i]=[]),n[i].push({value:e,name:t}))}});let u=[];Object.entries(i).filter(([,e])=>e!==s).forEach(([t,n])=>{let r=e[n];if(r){let e=a.find(e=>e.name===t)?.type===`MULTI_SELECT`;u.push({values:e?I(r):r,key:t})}});let f=l(c.RequestType),p=l(c.SubjectType);return[e,{email:e[l(c.Email)],attestedExtraIdentifiers:n,attributes:u,coreIdentifier:e[l(c.CoreIdentifier)],requestType:f===`[APPLY VALUE TO ALL ROWS]`?t.getValue(`requestTypeToRequestAction`,d):t.getValue(`requestTypeToRequestAction`,e[f]),subjectType:p===`[APPLY VALUE TO ALL ROWS]`?t.getValue(`subjectTypeToSubjectName`,d):t.getValue(`subjectTypeToSubjectName`,e[p]),...l(c.Locale)!==`[NONE]`&&e[l(c.Locale)]?{locale:t.getValue(`languageToLocale`,e[l(c.Locale)])}:{},...l(c.Country)!==`[NONE]`&&e[l(c.Country)]?{country:t.getValue(`regionToCountry`,e[l(c.Country)])}:{},...l(c.CountrySubDivision)!==`[NONE]`&&e[l(c.CountrySubDivision)]?{countrySubDivision:t.getValue(`regionToCountrySubDivision`,e[l(c.CountrySubDivision)])}:{},...l(c.RequestStatus)!==`[NONE]`&&t.getValue(`statusToRequestStatus`,e[l(c.RequestStatus)])!==`[NONE]`&&e[l(c.RequestStatus)]?{status:t.getValue(`statusToRequestStatus`,e[l(c.RequestStatus)])}:{},...l(c.CreatedAt)!==`[NONE]`&&e[l(c.CreatedAt)]?{createdAt:new Date(e[l(c.CreatedAt)])}:{},...l(c.DataSiloIds)!==`[NONE]`&&e[l(c.DataSiloIds)]?{dataSiloIds:I(e[l(c.DataSiloIds)])}:{}}]})}async function Q(e,n,i){let{initializer:a}=await F(e,r,{logger:t}),o=a.identifiers.filter(({name:e})=>!i.getValue(`identifierNames`,e)&&!u.includes(e)),s=o.length===0?{}:await R.prompt(o.map(({name:e})=>{let t=m(n,e,!1);return{name:e,message:`Choose the column that will be used to map in the identifier: ${e}`,type:`list`,default:t[0],choices:t}}));return await Promise.all(Object.entries(s).map(([e,t])=>i.setValue(t,`identifierNames`,e))),{...i.getValue(`identifierNames`),...s}}async function $(e,t,n,r){let i=r.filter(({name:e})=>!n.getValue(`attributeNames`,e)),a=i.length===0?{}:await R.prompt(i.map(({name:e})=>{let n=m(t,e,!1);return{name:e,message:`Choose the column that will be used to map in the attribute: ${e}`,type:`list`,default:n[0],choices:n}}));return await Promise.all(Object.entries(a).map(([e,t])=>n.setValue(t,`attributeNames`,e))),{...n.getValue(`attributeNames`),...a}}async function ie({cacheFilepath:n,requestReceiptFolder:r,file:a,auth:s,sombraAuth:c,concurrency:l=100,defaultPhoneCountryCode:u=`1`,transcendUrl:d=e,attributes:f=[],emailIsVerified:m=!0,skipFilterStep:h=!1,skipSendingReceipt:y=!0,isTest:b=!1,isSilent:x=!0,debug:S=!1,dryRun:C=!1}){let w=new Date().getTime(),T=new L.SingleBar({},L.Presets.shades_classic),D=p(f),O=new V(n,o,{columnNames:{},requestTypeToRequestAction:{},subjectTypeToSubjectName:{},languageToLocale:{},statusToRequestStatus:{},identifierNames:{},attributeNames:{},regionToCountrySubDivision:{},regionToCountry:{}}),k=ee(r,`tr-request-upload-${new Date().toISOString()}-${a.split(`/`).pop()}`.replace(`.csv`,`.json`)),A=new V(k,i,{successfulRequests:[],duplicateRequests:[],failingRequests:[]}),M=await ne(d,s,{logger:t,sombraApiKey:c,sombraUrl:process.env.SOMBRA_URL}),P=g(a,N.record(N.string,N.string)),F=E(P.map(e=>Object.keys(e)).flat());if(P.length===0)throw Error(`No Requests found in list! Ensure the first row of the CSV is a header and the rest are requests.`);if(S){let e=P[0];t.info(j.magenta(`First request: ${JSON.stringify(e,null,2)}`))}let I=h?P:await W(P),R=te(d,s),z=await G(R),B=await K(F,O),H=await Q(R,F,O),U=await $(R,F,O,z);await q(R,I,{state:O,columnNameMap:B});let J=Z(I,O,{defaultPhoneCountryCode:u,columnNameMap:B,identifierNameMap:H,attributeNameMap:U,requestAttributeKeys:z});S||T.start(J.length,0);let Y=0;await re(J,async([e,n],r)=>{let i=S?`email:${n.email} | coreIdentifier:${n.coreIdentifier}`:`row:${r.toString()}`;if(S&&t.info(j.magenta(`[${r+1}/${J.length}] Importing: ${JSON.stringify(n,null,2)}`)),C){t.info(j.magenta(`Bailing out on dry run because dryRun is set`));return}try{let a=await _(M,n,{details:`Uploaded by Transcend Cli: "tr-request-upload" : ${JSON.stringify(e,null,2)}`,isTest:b,emailIsVerified:m,skipSendingReceipt:y,isSilent:x,additionalAttributes:D});S&&(t.info(j.green(`[${r+1}/${J.length}] Successfully submitted the test data subject request: "${i}"`)),t.info(j.green(`[${r+1}/${J.length}] View it at: "${a.link}"`)));let o=A.getValue(`successfulRequests`);o.push({id:a.id,link:a.link,rowIndex:r,coreIdentifier:a.coreIdentifier,attemptedAt:new Date().toISOString()}),await A.setValue(o,`successfulRequests`)}catch(e){let a=`${e.message} - ${JSON.stringify(e.response?.body,null,2)}`,o=v(a);if(o===`Client error: You have already made this request.`){S&&t.info(j.yellow(`[${r+1}/${J.length}] Skipping request as it is a duplicate`));let e=A.getValue(`duplicateRequests`);e.push({coreIdentifier:n.coreIdentifier,rowIndex:r,attemptedAt:new Date().toISOString()}),await A.setValue(e,`duplicateRequests`)}else{let e=A.getValue(`failingRequests`);e.push({...n,rowIndex:r,error:o||a,attemptedAt:new Date().toISOString()}),await A.setValue(e,`failingRequests`),S&&(t.error(j.red(o||a)),t.error(j.red(`[${r+1}/${J.length}] Failed to submit request for: "${i}"`)))}}Y+=1,S||T.update(Y)},{concurrency:l}),T.stop();let X=new Date().getTime()-w;t.info(j.green(`Completed upload in "${X/1e3}" seconds.`)),A.getValue(`duplicateRequests`).length>0&&t.info(j.yellow(`Encountered "${A.getValue(`duplicateRequests`).length}" duplicate requests. See "${k}" to review the core identifiers for these requests.`)),A.getValue(`failingRequests`).length>0&&(t.error(j.red(`Encountered "${A.getValue(`failingRequests`).length}" errors. See "${k}" to review the error messages and inputs.`)),process.exit(1))}export{Y as a,q as c,W as d,U as f,J as i,K as l,$ as n,Z as o,H as p,Q as r,X as s,ie as t,G as u};
|
|
2
|
-
//# sourceMappingURL=uploadPrivacyRequestsFromCsv-Czc3vGfJ.mjs.map
|