@transcend-io/cli 7.0.1 → 8.0.0-alpha.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/bin/bash-complete.js +4 -0
- package/dist/bin/bash-complete.js.map +1 -0
- package/dist/bin/cli.js +3 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/bin/deprecated-command.js +7 -0
- package/dist/bin/deprecated-command.js.map +1 -0
- package/dist/chunk-26T4RUOI.js +12 -0
- package/dist/chunk-26T4RUOI.js.map +1 -0
- package/dist/chunk-2LCGZ77N.js +2 -0
- package/dist/chunk-2LCGZ77N.js.map +1 -0
- package/dist/chunk-2V6ABZRI.js +2 -0
- package/dist/chunk-2V6ABZRI.js.map +1 -0
- package/dist/chunk-347UQP43.js +2 -0
- package/dist/chunk-347UQP43.js.map +1 -0
- package/dist/chunk-43JWXG77.js +2 -0
- package/dist/chunk-43JWXG77.js.map +1 -0
- package/dist/chunk-4GLITB3Y.js +2 -0
- package/dist/chunk-4GLITB3Y.js.map +1 -0
- package/dist/chunk-65I2PF73.js +2 -0
- package/dist/chunk-65I2PF73.js.map +1 -0
- package/dist/chunk-72U6ETHG.js +2 -0
- package/dist/chunk-72U6ETHG.js.map +1 -0
- package/dist/chunk-ARVEJERC.js +2 -0
- package/dist/chunk-ARVEJERC.js.map +1 -0
- package/dist/chunk-CBAHSBSW.js +2 -0
- package/dist/{chunk-MQNOIHZN.cjs.map → chunk-CBAHSBSW.js.map} +1 -1
- package/dist/chunk-EZHASXA5.js +2 -0
- package/dist/chunk-EZHASXA5.js.map +1 -0
- package/dist/chunk-FHZRITAV.js +2 -0
- package/dist/chunk-FHZRITAV.js.map +1 -0
- package/dist/chunk-HJULYIHF.js +3 -0
- package/dist/chunk-HJULYIHF.js.map +1 -0
- package/dist/chunk-HOZXN2EM.js +94 -0
- package/dist/chunk-HOZXN2EM.js.map +1 -0
- package/dist/chunk-L5ULN3IT.js +2 -0
- package/dist/chunk-L5ULN3IT.js.map +1 -0
- package/dist/chunk-L7ZIX4SU.js +2 -0
- package/dist/chunk-L7ZIX4SU.js.map +1 -0
- package/dist/chunk-LAYHULHH.js +2 -0
- package/dist/chunk-LAYHULHH.js.map +1 -0
- package/dist/chunk-MA4JWWRO.js +6 -0
- package/dist/chunk-MA4JWWRO.js.map +1 -0
- package/dist/chunk-MK5T6DBK.js +2831 -0
- package/dist/chunk-MK5T6DBK.js.map +1 -0
- package/dist/chunk-N6JZHL5U.js +2 -0
- package/dist/chunk-N6JZHL5U.js.map +1 -0
- package/dist/chunk-NZZKRVAI.js +4 -0
- package/dist/chunk-NZZKRVAI.js.map +1 -0
- package/dist/chunk-OEB7WG3G.js +4 -0
- package/dist/chunk-OEB7WG3G.js.map +1 -0
- package/dist/chunk-SRLEEKKQ.js +9 -0
- package/dist/chunk-SRLEEKKQ.js.map +1 -0
- package/dist/chunk-WO5MQBXP.js +75 -0
- package/dist/chunk-WO5MQBXP.js.map +1 -0
- package/dist/impl-24IS3GIF.js +2 -0
- package/dist/impl-24IS3GIF.js.map +1 -0
- package/dist/impl-3YESYKVQ.js +2 -0
- package/dist/impl-3YESYKVQ.js.map +1 -0
- package/dist/impl-6MGNPY7O.js +2 -0
- package/dist/impl-6MGNPY7O.js.map +1 -0
- package/dist/impl-6SYXV3YI.js +2 -0
- package/dist/impl-6SYXV3YI.js.map +1 -0
- package/dist/impl-BVOF3W2V.js +4 -0
- package/dist/impl-BVOF3W2V.js.map +1 -0
- package/dist/impl-D4AEXEMN.js +12 -0
- package/dist/impl-D4AEXEMN.js.map +1 -0
- package/dist/impl-EAY4M3OY.js +2 -0
- package/dist/impl-EAY4M3OY.js.map +1 -0
- package/dist/impl-F4IQEKTF.js +9 -0
- package/dist/impl-F4IQEKTF.js.map +1 -0
- package/dist/impl-G4JGSVWD.js +2 -0
- package/dist/impl-G4JGSVWD.js.map +1 -0
- package/dist/impl-HFXHM3PH.js +2 -0
- package/dist/impl-HFXHM3PH.js.map +1 -0
- package/dist/impl-HMHOYOZZ.js +2 -0
- package/dist/impl-HMHOYOZZ.js.map +1 -0
- package/dist/impl-IU4EANSX.js +7 -0
- package/dist/impl-IU4EANSX.js.map +1 -0
- package/dist/impl-IWDHKBWZ.js +2 -0
- package/dist/impl-IWDHKBWZ.js.map +1 -0
- package/dist/impl-JFD2JMP6.js +2 -0
- package/dist/impl-JFD2JMP6.js.map +1 -0
- package/dist/impl-JH4VBMNT.js +2 -0
- package/dist/impl-JH4VBMNT.js.map +1 -0
- package/dist/impl-LSP4V37Z.js +6 -0
- package/dist/impl-LSP4V37Z.js.map +1 -0
- package/dist/impl-MIJFNSLS.js +2 -0
- package/dist/impl-MIJFNSLS.js.map +1 -0
- package/dist/impl-NL32KFH4.js +2 -0
- package/dist/impl-NL32KFH4.js.map +1 -0
- package/dist/impl-NLCPSIYZ.js +2 -0
- package/dist/impl-NLCPSIYZ.js.map +1 -0
- package/dist/impl-NXRQU2U5.js +6 -0
- package/dist/impl-NXRQU2U5.js.map +1 -0
- package/dist/impl-QEOVZIM5.js +2 -0
- package/dist/impl-QEOVZIM5.js.map +1 -0
- package/dist/impl-QRK4B3FD.js +2 -0
- package/dist/impl-QRK4B3FD.js.map +1 -0
- package/dist/impl-QZBKOJBQ.js +2 -0
- package/dist/impl-QZBKOJBQ.js.map +1 -0
- package/dist/impl-RFRQUKQY.js +2 -0
- package/dist/impl-RFRQUKQY.js.map +1 -0
- package/dist/impl-RIVVHWBR.js +2 -0
- package/dist/impl-RIVVHWBR.js.map +1 -0
- package/dist/impl-SJHU5PR7.js +2 -0
- package/dist/impl-SJHU5PR7.js.map +1 -0
- package/dist/impl-SYC5TORT.js +2 -0
- package/dist/impl-SYC5TORT.js.map +1 -0
- package/dist/impl-TP4QITXR.js +2 -0
- package/dist/impl-TP4QITXR.js.map +1 -0
- package/dist/impl-UOB7PV4W.js +2 -0
- package/dist/impl-UOB7PV4W.js.map +1 -0
- package/dist/impl-UUQ2BEZR.js +2 -0
- package/dist/impl-UUQ2BEZR.js.map +1 -0
- package/dist/impl-WH2I2JB7.js +2 -0
- package/dist/impl-WH2I2JB7.js.map +1 -0
- package/dist/impl-X6N6NFUV.js +6 -0
- package/dist/impl-X6N6NFUV.js.map +1 -0
- package/dist/impl-XF3OTAQZ.js +2 -0
- package/dist/impl-XF3OTAQZ.js.map +1 -0
- package/dist/impl-XH3KTZRN.js +2 -0
- package/dist/{impl-4WA4CEB2.cjs.map → impl-XH3KTZRN.js.map} +1 -1
- package/dist/impl-XQBTTRCU.js +2 -0
- package/dist/impl-XQBTTRCU.js.map +1 -0
- package/dist/impl-YA2HU57Y.js +2 -0
- package/dist/impl-YA2HU57Y.js.map +1 -0
- package/dist/impl-YEGS4G24.js +2 -0
- package/dist/impl-YEGS4G24.js.map +1 -0
- package/dist/impl-YNBHGQJK.js +2 -0
- package/dist/impl-YNBHGQJK.js.map +1 -0
- package/dist/impl-ZJL2YE7A.js +2 -0
- package/dist/impl-ZJL2YE7A.js.map +1 -0
- package/dist/{index.d.cts → index.d.ts} +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/package.json +45 -49
- package/dist/bin/bash-complete.cjs +0 -4
- package/dist/bin/bash-complete.cjs.map +0 -1
- package/dist/bin/cli.cjs +0 -3
- package/dist/bin/cli.cjs.map +0 -1
- package/dist/bin/deprecated-command.cjs +0 -7
- package/dist/bin/deprecated-command.cjs.map +0 -1
- package/dist/chunk-4J2KYJVS.cjs +0 -2
- package/dist/chunk-4J2KYJVS.cjs.map +0 -1
- package/dist/chunk-5SI74STE.cjs +0 -12
- package/dist/chunk-5SI74STE.cjs.map +0 -1
- package/dist/chunk-BY7W4UQF.cjs +0 -2
- package/dist/chunk-BY7W4UQF.cjs.map +0 -1
- package/dist/chunk-DF4YVZJQ.cjs +0 -94
- package/dist/chunk-DF4YVZJQ.cjs.map +0 -1
- package/dist/chunk-E4Y3D2JZ.cjs +0 -75
- package/dist/chunk-E4Y3D2JZ.cjs.map +0 -1
- package/dist/chunk-EG4L6YAJ.cjs +0 -2
- package/dist/chunk-EG4L6YAJ.cjs.map +0 -1
- package/dist/chunk-IBTP5OXE.cjs +0 -2
- package/dist/chunk-IBTP5OXE.cjs.map +0 -1
- package/dist/chunk-J72CSV4R.cjs +0 -2
- package/dist/chunk-J72CSV4R.cjs.map +0 -1
- package/dist/chunk-KOV2SQO2.cjs +0 -4
- package/dist/chunk-KOV2SQO2.cjs.map +0 -1
- package/dist/chunk-LL7YE3LT.cjs +0 -2
- package/dist/chunk-LL7YE3LT.cjs.map +0 -1
- package/dist/chunk-MQNOIHZN.cjs +0 -2
- package/dist/chunk-OL2YE5SK.cjs +0 -2
- package/dist/chunk-OL2YE5SK.cjs.map +0 -1
- package/dist/chunk-P6ZHBB6P.cjs +0 -3
- package/dist/chunk-P6ZHBB6P.cjs.map +0 -1
- package/dist/chunk-QUYFJVAC.cjs +0 -9
- package/dist/chunk-QUYFJVAC.cjs.map +0 -1
- package/dist/chunk-RPJHDKU6.cjs +0 -4
- package/dist/chunk-RPJHDKU6.cjs.map +0 -1
- package/dist/chunk-SAEKBZGF.cjs +0 -2
- package/dist/chunk-SAEKBZGF.cjs.map +0 -1
- package/dist/chunk-SDZR3H23.cjs +0 -2
- package/dist/chunk-SDZR3H23.cjs.map +0 -1
- package/dist/chunk-T462ONFX.cjs +0 -2
- package/dist/chunk-T462ONFX.cjs.map +0 -1
- package/dist/chunk-TD7ADMVO.cjs +0 -2
- package/dist/chunk-TD7ADMVO.cjs.map +0 -1
- package/dist/chunk-UEGX6GZ2.cjs +0 -2
- package/dist/chunk-UEGX6GZ2.cjs.map +0 -1
- package/dist/chunk-XXGX7FUC.cjs +0 -2
- package/dist/chunk-XXGX7FUC.cjs.map +0 -1
- package/dist/chunk-YVY4TZ2O.cjs +0 -2844
- package/dist/chunk-YVY4TZ2O.cjs.map +0 -1
- package/dist/chunk-ZUNVPK23.cjs +0 -2
- package/dist/chunk-ZUNVPK23.cjs.map +0 -1
- package/dist/chunk-ZVK4HIDF.cjs +0 -6
- package/dist/chunk-ZVK4HIDF.cjs.map +0 -1
- package/dist/impl-4WA4CEB2.cjs +0 -2
- package/dist/impl-7K57DEDR.cjs +0 -2
- package/dist/impl-7K57DEDR.cjs.map +0 -1
- package/dist/impl-AC2WQUNH.cjs +0 -2
- package/dist/impl-AC2WQUNH.cjs.map +0 -1
- package/dist/impl-B7WQMB3O.cjs +0 -2
- package/dist/impl-B7WQMB3O.cjs.map +0 -1
- package/dist/impl-DCTVGKDZ.cjs +0 -2
- package/dist/impl-DCTVGKDZ.cjs.map +0 -1
- package/dist/impl-DTFM3SWD.cjs +0 -2
- package/dist/impl-DTFM3SWD.cjs.map +0 -1
- package/dist/impl-GBTW2VLR.cjs +0 -2
- package/dist/impl-GBTW2VLR.cjs.map +0 -1
- package/dist/impl-HI27O5MJ.cjs +0 -4
- package/dist/impl-HI27O5MJ.cjs.map +0 -1
- package/dist/impl-I3RNGLKH.cjs +0 -2
- package/dist/impl-I3RNGLKH.cjs.map +0 -1
- package/dist/impl-IXNKRWC7.cjs +0 -2
- package/dist/impl-IXNKRWC7.cjs.map +0 -1
- package/dist/impl-IY2QSXYK.cjs +0 -2
- package/dist/impl-IY2QSXYK.cjs.map +0 -1
- package/dist/impl-KLXVHSVI.cjs +0 -2
- package/dist/impl-KLXVHSVI.cjs.map +0 -1
- package/dist/impl-L63MYKIO.cjs +0 -2
- package/dist/impl-L63MYKIO.cjs.map +0 -1
- package/dist/impl-LBZ5KQCA.cjs +0 -2
- package/dist/impl-LBZ5KQCA.cjs.map +0 -1
- package/dist/impl-LCGB6L6S.cjs +0 -2
- package/dist/impl-LCGB6L6S.cjs.map +0 -1
- package/dist/impl-MHMLFQYV.cjs +0 -2
- package/dist/impl-MHMLFQYV.cjs.map +0 -1
- package/dist/impl-MP7KOII5.cjs +0 -2
- package/dist/impl-MP7KOII5.cjs.map +0 -1
- package/dist/impl-MZEAMC6V.cjs +0 -2
- package/dist/impl-MZEAMC6V.cjs.map +0 -1
- package/dist/impl-N2Q4635G.cjs +0 -2
- package/dist/impl-N2Q4635G.cjs.map +0 -1
- package/dist/impl-NIMCX7UC.cjs +0 -2
- package/dist/impl-NIMCX7UC.cjs.map +0 -1
- package/dist/impl-NURZ5XJQ.cjs +0 -2
- package/dist/impl-NURZ5XJQ.cjs.map +0 -1
- package/dist/impl-NZFTTWVH.cjs +0 -7
- package/dist/impl-NZFTTWVH.cjs.map +0 -1
- package/dist/impl-O5UHTMMM.cjs +0 -6
- package/dist/impl-O5UHTMMM.cjs.map +0 -1
- package/dist/impl-PRYWCT7Y.cjs +0 -12
- package/dist/impl-PRYWCT7Y.cjs.map +0 -1
- package/dist/impl-RKMMHSRM.cjs +0 -2
- package/dist/impl-RKMMHSRM.cjs.map +0 -1
- package/dist/impl-RWHAQHPT.cjs +0 -2
- package/dist/impl-RWHAQHPT.cjs.map +0 -1
- package/dist/impl-SBE23MJO.cjs +0 -2
- package/dist/impl-SBE23MJO.cjs.map +0 -1
- package/dist/impl-SC4TK2TM.cjs +0 -2
- package/dist/impl-SC4TK2TM.cjs.map +0 -1
- package/dist/impl-TIBNP5YM.cjs +0 -6
- package/dist/impl-TIBNP5YM.cjs.map +0 -1
- package/dist/impl-UNB3DZOL.cjs +0 -2
- package/dist/impl-UNB3DZOL.cjs.map +0 -1
- package/dist/impl-V4UKISVS.cjs +0 -2
- package/dist/impl-V4UKISVS.cjs.map +0 -1
- package/dist/impl-V5ICYKCT.cjs +0 -6
- package/dist/impl-V5ICYKCT.cjs.map +0 -1
- package/dist/impl-VQGXD5O3.cjs +0 -2
- package/dist/impl-VQGXD5O3.cjs.map +0 -1
- package/dist/impl-X2YAN6YV.cjs +0 -9
- package/dist/impl-X2YAN6YV.cjs.map +0 -1
- package/dist/impl-XKATFWGB.cjs +0 -2
- package/dist/impl-XKATFWGB.cjs.map +0 -1
- package/dist/impl-XRRNIJUK.cjs +0 -2
- package/dist/impl-XRRNIJUK.cjs.map +0 -1
- package/dist/impl-Y3ZMWRT7.cjs +0 -2
- package/dist/impl-Y3ZMWRT7.cjs.map +0 -1
- package/dist/impl-YDPROAJW.cjs +0 -2
- package/dist/impl-YDPROAJW.cjs.map +0 -1
- package/dist/impl-YTAZCQDL.cjs +0 -2
- package/dist/impl-YTAZCQDL.cjs.map +0 -1
- package/dist/index.cjs +0 -5
- package/dist/index.cjs.map +0 -1
- /package/dist/bin/{bash-complete.d.cts → bash-complete.d.ts} +0 -0
- /package/dist/bin/{cli.d.cts → cli.d.ts} +0 -0
- /package/dist/bin/{deprecated-command.d.cts → deprecated-command.d.ts} +0 -0
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{a as t}from"../chunk-72U6ETHG.js";import{a as s}from"../chunk-HOZXN2EM.js";import"../chunk-SRLEEKKQ.js";import"../chunk-L5ULN3IT.js";import"../chunk-EZHASXA5.js";import"../chunk-ARVEJERC.js";import{proposeCompletions as i}from"@stricli/core";async function e(){let o=process.argv.slice(3);process.env.COMP_LINE?.endsWith(" ")&&o.push(""),await i(s,o,t(process));try{for(let{completion:r}of await i(s,o,t(process)))process.stdout.write(`${r}
|
|
3
|
+
`)}catch{}}e();
|
|
4
|
+
//# sourceMappingURL=bash-complete.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/bin/bash-complete.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { proposeCompletions } from '@stricli/core';\nimport { app } from '../app';\nimport { buildContext } from '../context';\n\n/**\n * Install bash complete\n */\nasync function main(): Promise<void> {\n const inputs = process.argv.slice(3);\n if (process.env.COMP_LINE?.endsWith(' ')) {\n inputs.push('');\n }\n await proposeCompletions(app, inputs, buildContext(process));\n try {\n for (const { completion } of await proposeCompletions(\n app,\n inputs,\n buildContext(process),\n )) {\n process.stdout.write(`${completion}\\n`);\n }\n } catch {\n // ignore\n }\n}\n\nmain();\n"],"mappings":";sMACA,OAAS,sBAAAA,MAA0B,gBAOnC,eAAeC,GAAsB,CACnC,IAAMC,EAAS,QAAQ,KAAK,MAAM,CAAC,EAC/B,QAAQ,IAAI,WAAW,SAAS,GAAG,GACrCA,EAAO,KAAK,EAAE,EAEhB,MAAMC,EAAmBC,EAAKF,EAAQG,EAAa,OAAO,CAAC,EAC3D,GAAI,CACF,OAAW,CAAE,WAAAC,CAAW,IAAK,MAAMH,EACjCC,EACAF,EACAG,EAAa,OAAO,CACtB,EACE,QAAQ,OAAO,MAAM,GAAGC,CAAU;AAAA,CAAI,CAE1C,MAAQ,CAER,CACF,CAEAL,EAAK","names":["proposeCompletions","main","inputs","proposeCompletions","app","buildContext","completion"]}
|
package/dist/bin/cli.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{a as r}from"../chunk-72U6ETHG.js";import{a as o}from"../chunk-HOZXN2EM.js";import"../chunk-SRLEEKKQ.js";import"../chunk-L5ULN3IT.js";import"../chunk-EZHASXA5.js";import"../chunk-ARVEJERC.js";import{run as i}from"@stricli/core";async function n(){await i(o,process.argv.slice(2),r(process))}n();
|
|
3
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/bin/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { run } from '@stricli/core';\nimport { app } from '../app';\nimport { buildContext } from '../context';\n\n/**\n * Entrypoint for `transcend` CLI\n */\nasync function main(): Promise<void> {\n await run(app, process.argv.slice(2), buildContext(process));\n}\n\nmain();\n"],"mappings":";sMACA,OAAS,OAAAA,MAAW,gBAOpB,eAAeC,GAAsB,CACnC,MAAMC,EAAIC,EAAK,QAAQ,KAAK,MAAM,CAAC,EAAGC,EAAa,OAAO,CAAC,CAC7D,CAEAH,EAAK","names":["run","main","run","app","buildContext"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{a as n}from"../chunk-HOZXN2EM.js";import"../chunk-SRLEEKKQ.js";import{a as r}from"../chunk-43JWXG77.js";import"../chunk-L5ULN3IT.js";import"../chunk-EZHASXA5.js";import"../chunk-ARVEJERC.js";import{generateHelpTextForAllCommands as c}from"@stricli/core";var o={"tr-build-xdi-sync-endpoint":["consent","build-xdi-sync-endpoint"],"tr-consent-manager-service-json-to-yml":["inventory","consent-manager-service-json-to-yml"],"tr-consent-managers-to-business-entities":["inventory","consent-managers-to-business-entities"],"tr-cron-mark-identifiers-completed":["request","cron","mark-identifiers-completed"],"tr-cron-pull-identifiers":["request","cron","pull-identifiers"],"tr-derive-data-silos-from-data-flows":["inventory","derive-data-silos-from-data-flows"],"tr-derive-data-silos-from-data-flows-cross-instance":["inventory","derive-data-silos-from-data-flows-cross-instance"],"tr-discover-silos":["inventory","discover-silos"],"tr-generate-api-keys":["admin","generate-api-keys"],"tr-manual-enrichment-pull-identifiers":["request","preflight","pull-identifiers"],"tr-manual-enrichment-push-identifiers":["request","preflight","push-identifiers"],"tr-mark-request-data-silos-completed":["request","system","mark-request-data-silos-completed"],"tr-pull":["inventory","pull"],"tr-pull-consent-metrics":["consent","pull-consent-metrics"],"tr-pull-consent-preferences":["consent","pull-consent-preferences"],"tr-pull-datapoints":["inventory","pull-datapoints"],"tr-pull-pull-unstructured-discovery-files":["inventory","pull-unstructured-discovery-files"],"tr-push":["inventory","push"],"tr-request-approve":["request","approve"],"tr-request-cancel":["request","cancel"],"tr-request-download-files":["request","download-files"],"tr-request-enricher-restart":["request","enricher-restart"],"tr-request-export":["request","export"],"tr-request-mark-silent":["request","mark-silent"],"tr-request-notify-additional-time":["request","notify-additional-time"],"tr-request-reject-unverified-identifiers":["request","reject-unverified-identifiers"],"tr-request-restart":["request","restart"],"tr-request-upload":["request","upload"],"tr-retry-request-data-silos":["request","system","retry-request-data-silos"],"tr-scan-packages":["inventory","scan-packages"],"tr-skip-preflight-jobs":["request","skip-preflight-jobs"],"tr-skip-request-data-silos":["request","system","skip-request-data-silos"],"tr-sync-ot":["migration","sync-ot"],"tr-update-consent-manager":["consent","update-consent-manager"],"tr-upload-consent-preferences":["consent","upload-consent-preferences"],"tr-upload-cookies-from-csv":["consent","upload-cookies-from-csv"],"tr-upload-data-flows-from-csv":["consent","upload-data-flows-from-csv"],"tr-upload-preferences":["consent","upload-preferences"]};function p(t){return c(n).find(s=>s[0]===`${n.config.name} ${t.join(" ")}`)?.[1]}function i(t){r.log("[DEPRECATION NOTICE]");let e=o[t];if(!e){let a=Object.entries(o).map(([l,d])=>`\`${l}\` -> \`${n.config.name} ${d.join(" ")}\``).join(`
|
|
3
|
+
`);r.log(`This command is deprecated as of v7.0.0. Here is a list of new commands, mapped to their legacy command names:
|
|
4
|
+
${a}`);return}r.log(`\`${t}\` is deprecated as of v7.0.0.
|
|
5
|
+
Use \`${n.config.name} ${e.join(" ")}\` instead.
|
|
6
|
+
`);let s=p(e);if(!s)throw new Error(`Failed to get help text for command: \`${e.join(" ")}\``);r.log(s)}function m(){let e=process.argv.at(-1)?.split("/").pop()?.trim();if(e)i(e);else throw new Error("Deprecated command");process.exit(1)}m();
|
|
7
|
+
//# sourceMappingURL=deprecated-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/cli/legacy-commands.ts","../../src/bin/deprecated-command.ts"],"sourcesContent":["import {\n generateHelpTextForAllCommands,\n type Application,\n type CommandContext,\n} from '@stricli/core';\nimport { app } from '../../app';\nimport { logger } from '../../logger';\n\n// Maps legacy (<7.0.0) command names to their modern command structure\nexport const LEGACY_COMMAND_TO_MODERN_COMMAND_MAP: Record<string, string[]> = {\n 'tr-build-xdi-sync-endpoint': ['consent', 'build-xdi-sync-endpoint'],\n 'tr-consent-manager-service-json-to-yml': [\n 'inventory',\n 'consent-manager-service-json-to-yml',\n ],\n 'tr-consent-managers-to-business-entities': [\n 'inventory',\n 'consent-managers-to-business-entities',\n ],\n 'tr-cron-mark-identifiers-completed': [\n 'request',\n 'cron',\n 'mark-identifiers-completed',\n ],\n 'tr-cron-pull-identifiers': ['request', 'cron', 'pull-identifiers'],\n 'tr-derive-data-silos-from-data-flows': [\n 'inventory',\n 'derive-data-silos-from-data-flows',\n ],\n 'tr-derive-data-silos-from-data-flows-cross-instance': [\n 'inventory',\n 'derive-data-silos-from-data-flows-cross-instance',\n ],\n 'tr-discover-silos': ['inventory', 'discover-silos'],\n 'tr-generate-api-keys': ['admin', 'generate-api-keys'],\n 'tr-manual-enrichment-pull-identifiers': [\n 'request',\n 'preflight',\n 'pull-identifiers',\n ],\n 'tr-manual-enrichment-push-identifiers': [\n 'request',\n 'preflight',\n 'push-identifiers',\n ],\n 'tr-mark-request-data-silos-completed': [\n 'request',\n 'system',\n 'mark-request-data-silos-completed',\n ],\n 'tr-pull': ['inventory', 'pull'],\n 'tr-pull-consent-metrics': ['consent', 'pull-consent-metrics'],\n 'tr-pull-consent-preferences': ['consent', 'pull-consent-preferences'],\n 'tr-pull-datapoints': ['inventory', 'pull-datapoints'],\n 'tr-pull-pull-unstructured-discovery-files': [\n 'inventory',\n 'pull-unstructured-discovery-files',\n ],\n 'tr-push': ['inventory', 'push'],\n 'tr-request-approve': ['request', 'approve'],\n 'tr-request-cancel': ['request', 'cancel'],\n 'tr-request-download-files': ['request', 'download-files'],\n 'tr-request-enricher-restart': ['request', 'enricher-restart'],\n 'tr-request-export': ['request', 'export'],\n 'tr-request-mark-silent': ['request', 'mark-silent'],\n 'tr-request-notify-additional-time': ['request', 'notify-additional-time'],\n 'tr-request-reject-unverified-identifiers': [\n 'request',\n 'reject-unverified-identifiers',\n ],\n 'tr-request-restart': ['request', 'restart'],\n 'tr-request-upload': ['request', 'upload'],\n 'tr-retry-request-data-silos': [\n 'request',\n 'system',\n 'retry-request-data-silos',\n ],\n 'tr-scan-packages': ['inventory', 'scan-packages'],\n 'tr-skip-preflight-jobs': ['request', 'skip-preflight-jobs'],\n 'tr-skip-request-data-silos': [\n 'request',\n 'system',\n 'skip-request-data-silos',\n ],\n 'tr-sync-ot': ['migration', 'sync-ot'],\n 'tr-update-consent-manager': ['consent', 'update-consent-manager'],\n 'tr-upload-consent-preferences': ['consent', 'upload-consent-preferences'],\n 'tr-upload-cookies-from-csv': ['consent', 'upload-cookies-from-csv'],\n 'tr-upload-data-flows-from-csv': ['consent', 'upload-data-flows-from-csv'],\n 'tr-upload-preferences': ['consent', 'upload-preferences'],\n};\n\n// All commands have been migrated to the modern command structure\n\n/**\n * Gets the help text for a command\n *\n * @param command - The command to get help text for\n * @returns The help text for the command\n */\nexport function getHelpTextForCommand(command: string[]): string | undefined {\n const helpTextForAllCommands = generateHelpTextForAllCommands(\n app as Application<CommandContext>,\n );\n\n return helpTextForAllCommands.find(\n (x) => x[0] === `${app.config.name} ${command.join(' ')}`,\n )?.[1];\n}\n\n/**\n * Logs a modern command recommendation for a legacy command\n *\n * @param legacyCommand - The legacy command to log a modern command recommendation for\n * @example\n * logModernCommandRecommendation('tr-cron-mark-identifiers-completed');\n */\nexport function logModernCommandRecommendation(\n legacyCommand: keyof typeof LEGACY_COMMAND_TO_MODERN_COMMAND_MAP,\n): void {\n logger.log('[DEPRECATION NOTICE]');\n\n const modernCommand = LEGACY_COMMAND_TO_MODERN_COMMAND_MAP[legacyCommand];\n if (!modernCommand) {\n const modernCommandString = Object.entries(\n LEGACY_COMMAND_TO_MODERN_COMMAND_MAP,\n )\n .map(\n ([legacyCommand, modernCommand]) =>\n `\\`${legacyCommand}\\` -> \\`${app.config.name} ${modernCommand.join(\n ' ',\n )}\\``,\n )\n .join('\\n');\n logger.log(\n 'This command is deprecated as of v7.0.0.' +\n ` Here is a list of new commands, mapped to their legacy command names:\n${modernCommandString}`,\n );\n return;\n }\n\n logger.log(\n `\\`${legacyCommand}\\` is deprecated as of v7.0.0.\\nUse \\`${\n app.config.name\n } ${modernCommand.join(' ')}\\` instead.\\n`,\n );\n\n const helpText = getHelpTextForCommand(modernCommand);\n if (!helpText) {\n throw new Error(\n `Failed to get help text for command: \\`${modernCommand.join(' ')}\\``,\n );\n }\n\n logger.log(helpText);\n}\n","#!/usr/bin/env node\nimport { logModernCommandRecommendation } from '../lib/cli/legacy-commands';\n\n/**\n * Runs when a deprecated command is called.\n */\nfunction main(): void {\n const command = process.argv.at(-1);\n const legacyCommand = command?.split('/').pop()?.trim();\n if (legacyCommand) {\n logModernCommandRecommendation(legacyCommand);\n } else {\n throw new Error('Deprecated command');\n }\n\n process.exit(1);\n}\n\nmain();\n"],"mappings":"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","names":["generateHelpTextForAllCommands","LEGACY_COMMAND_TO_MODERN_COMMAND_MAP","getHelpTextForCommand","command","generateHelpTextForAllCommands","app","x","logModernCommandRecommendation","legacyCommand","logger","modernCommand","modernCommandString","helpText","main","legacyCommand","logModernCommandRecommendation"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import{c as x}from"./chunk-2V6ABZRI.js";import{n as u,q as D}from"./chunk-N6JZHL5U.js";import{ga as w,ha as _}from"./chunk-LAYHULHH.js";import{Le as O,Me as U,a as R,b as P,bd as b,pc as L,pe as S,qc as M,tc as N,wc as k}from"./chunk-MK5T6DBK.js";import{a as c}from"./chunk-43JWXG77.js";import{e as C}from"./chunk-L5ULN3IT.js";import{ConsentBundleType as H}from"@transcend-io/privacy-types";import A from"colors";async function at({auth:e,deploy:i=!1,transcendUrl:o=C,bundleTypes:t=Object.values(H)}){let r=S(o,e),n=await M(r);await R(t,async a=>{c.info(A.magenta(`Update Consent Manager bundle with ID "${n}" and type "${a}" to latest version...`)),await U(r,{id:n,bundleType:a}),c.info(A.green(`Updated Consent Manager bundle with ID "${n}" and type "${a}" to latest version!`))}),i&&await R(t,async a=>{c.info(A.magenta(`Deploying Consent Manager bundle with ID "${n}" and type "${a}"...`)),await O(r,{id:n,bundleType:a}),c.info(A.green(`Deployed Consent Manager bundle with ID "${n}" and type "${a}"!`))})}import G from"colors";var K=["ID","Activity","Encounters","Last Seen At","Has Native Do Not Sell/Share Support","IAB USP API Support","Service Description","Website URL","Categories of Recipients"];async function Ct({auth:e,trackerStatus:i,file:o,classifyService:t=!1,transcendUrl:r=C}){let n=S(r,e);c.info(G.magenta(`Reading "${o}" from disk`));let l=D(o,w).map(({Type:d,Notes:m,Service:f,Purpose:E,Status:g,Owners:I,Teams:T,"Connections Made To":v,...y})=>({value:v,type:d,description:m,trackingPurposes:u(E),status:g||i,owners:I?u(I):void 0,teams:T?u(T):void 0,attributes:Object.entries(y).filter(([h])=>!K.includes(h)).map(([h,B])=>({key:h,values:u(B)}))}));await b(n,l,t)||(c.error(G.red("Encountered error(s) syncing data flows from CSV, see logs above for more info. ")),process.exit(1))}import F from"colors";var j=["ID","Activity","Encounters","Last Seen At","Has Native Do Not Sell/Share Support","IAB USP API Support","Service Description","Website URL","Categories of Recipients"];async function vt({auth:e,trackerStatus:i,file:o,transcendUrl:t=C}){let r=S(t,e);c.info(F.magenta(`Reading "${o}" from disk`));let a=D(o,_).map(({"Is Regex?":s,Notes:d,Service:m,Purpose:f,Status:E,Owners:g,Teams:I,Name:T,...v})=>({...typeof s=="string"?{isRegex:s.toLowerCase()==="true"}:{},name:T,description:d,trackingPurposes:u(f),status:E||i,owners:g?u(g):void 0,teams:I?u(I):void 0,attributes:Object.entries(v).filter(([y])=>!j.includes(y)).map(([y,h])=>({key:y,values:u(h)}))}));await k(r,a)||(c.error(F.red("Encountered error(s) syncing cookies from CSV, see logs above for more info. ")),process.exit(1))}var Y=1e3,Q=60*Y,V=60*Q,X=24*V,z=7*X;async function Lt(e,{bin:i,start:o,end:t=new Date}){let r=await M(e),n=Math.floor(o.getTime()/1e3),a=Math.floor(t.getTime()/1e3);if(n>a)throw new Error('Received "end" date that happened before "start" date');if(i==="1h"&&t.getTime()-o.getTime()>z*2)throw new Error("When using bin=1h, start and end time can be no more than 2 weeks apart");let l=o.toISOString(),s=t.toISOString(),[d,m,f]=await Promise.all([N(e,{dataSource:"PRIVACY_SIGNAL_TIMESERIES",startDate:l,endDate:s,forceRefetch:!0,airgapBundleId:r,binInterval:i,smoothTimeseries:!1}),N(e,{dataSource:"CONSENT_CHANGES_TIMESERIES",startDate:l,endDate:s,forceRefetch:!0,airgapBundleId:r,binInterval:i,smoothTimeseries:!1}),N(e,{dataSource:"CONSENT_SESSIONS_BY_REGIME",startDate:l,endDate:s,forceRefetch:!0,airgapBundleId:r,binInterval:i,smoothTimeseries:!1})]);return{PRIVACY_SIGNAL_TIMESERIES:d,CONSENT_CHANGES_TIMESERIES:m,CONSENT_SESSIONS_BY_REGIME:f}}var $=e=>new URL(`https://${e}`).hostname.split(".").slice(-2).join(".");import W from"colors";import{difference as q}from"lodash-es";var J=/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;async function Ht(e,{xdiLocation:i,transcendUrl:o=C,removeIpAddresses:t=!0,domainBlockList:r=["localhost"],xdiAllowedCommands:n="ConsentManager:Sync"}){let a=Array.isArray(e)?e:[{apiKey:e,organizationId:"",organizationName:""}],l=await P(a,async m=>{c.info(W.magenta(`Pulling consent metadata for organization - ${m.organizationName}`));let f=S(o,m.apiKey);return await L(f)},{concurrency:5}),s={};return l.forEach(m=>{let f=m.partition?.partition||m.bundleURL.split("/").reverse()[1];s[f]||(s[f]=[]);let E=q(m.configuration.domains.filter(g=>!t||!J.test(g)).map(g=>$(g)),r);s[f]=[...new Set([...s[f]||[],...E])]}),{html:`
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<script
|
|
4
|
+
src="${i}"
|
|
5
|
+
data-sync-groups='${JSON.stringify(s,null,2)}'
|
|
6
|
+
data-xdi-commands="${n}"
|
|
7
|
+
></script>
|
|
8
|
+
`,syncGroups:s}}function Yt(e){let i=e.map(({name:o,input:t})=>({title:o.replace(".yml",""),attributes:[...t?.domains?[{key:"Transcend Domain List",values:[...new Set(t.domains)]}]:[],...t?.bundleUrls?[{key:"Airgap Production URL",values:[t.bundleUrls.PRODUCTION]},{key:"Airgap Test URL",values:[t.bundleUrls.TEST]},{key:"Airgap XDI URL",values:[t.bundleUrls.PRODUCTION.replace("airgap.js","xdi.js")]}]:[],...t?.partition?[{key:"Consent Partition Key",values:[t.partition]}]:[]]}));return c.info(`
|
|
9
|
+
|
|
10
|
+
~~~~~~~~~~~
|
|
11
|
+
Airgap scripts to host:`),i.forEach(({attributes:o,title:t},r)=>{o?.find(n=>n.key==="Airgap Production URL")?.values?.forEach(n=>{c.info(`${r}) ${t} - ${n}`)})}),i}import*as p from"io-ts";import{decodeCodec as Z}from"@transcend-io/type-utils";var tt=p.intersection([p.type({nodes:p.array(x)}),p.partial({lastKey:p.partial({userId:p.string,partition:p.string,timestamp:p.string})})]);async function zt(e,{partition:i,filterBy:o={},limit:t=50}){let r,n=[],a=!0;for(;a;){let l=await e.post("v1/consent-preferences",{json:{partition:i,...o,startKey:r||void 0,limit:t}}).json(),{nodes:s,lastKey:d}=Z(tt,l);if(!s||s.length===0)break;n.push(...s),r=d,a=!!d&&Object.keys(d).length>0}return n}export{at as a,Ct as b,vt as c,Lt as d,$ as e,J as f,Ht as g,Yt as h,tt as i,zt as j};
|
|
12
|
+
//# sourceMappingURL=chunk-26T4RUOI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/consent-manager/updateConsentManagerVersionToLatest.ts","../src/lib/consent-manager/uploadDataFlowsFromCsv.ts","../src/lib/consent-manager/uploadCookiesFromCsv.ts","../src/lib/consent-manager/pullConsentManagerMetrics.ts","../src/lib/consent-manager/domainToHost.ts","../src/lib/consent-manager/buildXdiSyncEndpoint.ts","../src/lib/consent-manager/consentManagersToBusinessEntities.ts","../src/lib/consent-manager/fetchConsentPreferences.ts"],"sourcesContent":["import { ConsentBundleType } from '@transcend-io/privacy-types';\nimport { mapSeries } from '../bluebird-replace';\nimport {\n updateConsentManagerToLatest,\n buildTranscendGraphQLClient,\n fetchConsentManagerId,\n deployConsentManager,\n} from '../graphql';\nimport colors from 'colors';\n\nimport { logger } from '../../logger';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\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);\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(client, {\n id: consentManagerId,\n bundleType,\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(client, {\n id: consentManagerId,\n bundleType,\n });\n logger.info(\n colors.green(\n `Deployed Consent Manager bundle with ID \"${consentManagerId}\" and type \"${bundleType}\"!`,\n ),\n );\n });\n }\n}\n","import colors from 'colors';\nimport { logger } from '../../logger';\nimport { ConsentTrackerStatus } from '@transcend-io/privacy-types';\nimport { buildTranscendGraphQLClient, syncDataFlows } from '../graphql';\nimport { readCsv } from '../requests/readCsv';\nimport { DataFlowInput, DataFlowCsvInput } from '../../codecs';\nimport { splitCsvToList } from '../requests';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\nconst OMIT_COLUMNS = [\n 'ID',\n 'Activity',\n 'Encounters',\n 'Last Seen At',\n 'Has Native Do Not Sell/Share Support',\n 'IAB USP API Support',\n 'Service Description',\n 'Website URL',\n 'Categories of Recipients',\n];\n\n/**\n * Upload a set of data flows from CSV\n *\n * @param options - Options\n */\nexport async function uploadDataFlowsFromCsv({\n auth,\n trackerStatus,\n file,\n classifyService = false,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** CSV file path */\n file: string;\n /** Transcend API key authentication */\n auth: string;\n /** Sombra API key authentication */\n trackerStatus: ConsentTrackerStatus;\n /** classify data flow service if missing */\n classifyService?: boolean;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<void> {\n // Build a GraphQL client\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Read from CSV the set of data flow inputs\n logger.info(colors.magenta(`Reading \"${file}\" from disk`));\n const dataFlowInputs = readCsv(file, DataFlowCsvInput);\n\n // Convert these data flow inputs into a format that the other function can use\n const validatedDataFlowInputs = dataFlowInputs.map(\n ({\n Type,\n Notes,\n // TODO: https://transcend.height.app/T-26391 - export in CSV\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n Service,\n Purpose,\n Status,\n Owners,\n Teams,\n 'Connections Made To': value,\n ...rest\n }): DataFlowInput => ({\n value,\n type: Type,\n description: Notes,\n trackingPurposes: splitCsvToList(Purpose),\n // TODO: https://transcend.height.app/T-26391\n // service: Service,\n // Apply the trackerStatus to all values in the CSV -> allows for customer to define tracker status\n // on a row by row basis if needed\n status: Status || trackerStatus,\n owners: Owners ? splitCsvToList(Owners) : undefined,\n teams: Teams ? splitCsvToList(Teams) : undefined,\n // all remaining options are attribute\n attributes: Object.entries(rest)\n // filter out native columns that are exported from the admin dashboard\n // but not custom attributes\n .filter(([key]) => !OMIT_COLUMNS.includes(key))\n .map(([key, value]) => ({\n key,\n values: splitCsvToList(value),\n })),\n }),\n );\n\n // Upload the data flows into Transcend dashboard\n const syncedDataFlows = await syncDataFlows(\n client,\n validatedDataFlowInputs,\n classifyService,\n );\n\n // Log errors\n if (!syncedDataFlows) {\n logger.error(\n colors.red(\n 'Encountered error(s) syncing data flows from CSV, see logs above for more info. ',\n ),\n );\n process.exit(1);\n }\n}\n","import colors from 'colors';\nimport { logger } from '../../logger';\nimport { ConsentTrackerStatus } from '@transcend-io/privacy-types';\nimport { buildTranscendGraphQLClient, syncCookies } from '../graphql';\nimport { readCsv } from '../requests/readCsv';\nimport { CookieInput, CookieCsvInput } from '../../codecs';\nimport { splitCsvToList } from '../requests';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\nconst OMIT_COLUMNS = [\n 'ID',\n 'Activity',\n 'Encounters',\n 'Last Seen At',\n 'Has Native Do Not Sell/Share Support',\n 'IAB USP API Support',\n 'Service Description',\n 'Website URL',\n 'Categories of Recipients',\n];\n\n/**\n * Upload a set of cookies from CSV\n *\n * @param options - Options\n */\nexport async function uploadCookiesFromCsv({\n auth,\n trackerStatus,\n file,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** CSV file path */\n file: string;\n /** Transcend API key authentication */\n auth: string;\n /** Sombra API key authentication */\n trackerStatus: ConsentTrackerStatus;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<void> {\n // Build a GraphQL client\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Read from CSV the set of cookie inputs\n logger.info(colors.magenta(`Reading \"${file}\" from disk`));\n const cookieInputs = readCsv(file, CookieCsvInput);\n\n // Convert these inputs into a format that the other function can use\n const validatedCookieInputs = cookieInputs.map(\n ({\n 'Is Regex?': isRegex,\n Notes,\n // TODO: https://transcend.height.app/T-26391 - export in CSV\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n Service,\n Purpose,\n Status,\n Owners,\n Teams,\n Name,\n ...rest\n }): CookieInput => ({\n ...(typeof isRegex === 'string'\n ? { isRegex: isRegex.toLowerCase() === 'true' }\n : {}),\n name: Name,\n description: Notes,\n trackingPurposes: splitCsvToList(Purpose),\n // TODO: https://transcend.height.app/T-26391\n // service: Service,\n // Apply the trackerStatus to all values in the CSV -> allows for customer to define tracker status\n // on a row by row basis if needed\n status: Status || trackerStatus,\n owners: Owners ? splitCsvToList(Owners) : undefined,\n teams: Teams ? splitCsvToList(Teams) : undefined,\n // all remaining options are attribute\n attributes: Object.entries(rest)\n // filter out native columns that are exported from the admin dashboard\n // but not custom attributes\n .filter(([key]) => !OMIT_COLUMNS.includes(key))\n .map(([key, value]) => ({\n key,\n values: splitCsvToList(value),\n })),\n }),\n );\n\n // Upload the cookies into Transcend dashboard\n const syncedCookies = await syncCookies(client, validatedCookieInputs);\n\n // Log errors\n if (!syncedCookies) {\n logger.error(\n colors.red(\n 'Encountered error(s) syncing cookies from CSV, see logs above for more info. ',\n ),\n );\n process.exit(1);\n }\n}\n","import type { GraphQLClient } from 'graphql-request';\nimport {\n ConsentManagerMetric,\n ConsentManagerMetricBin,\n fetchConsentManagerAnalyticsData,\n fetchConsentManagerId,\n} from '../graphql';\n\n/**\n * One second of time in ms\n */\nconst ONE_SECOND = 1000;\nconst ONE_MINUTE = 60 * ONE_SECOND;\nconst ONE_HOUR = 60 * ONE_MINUTE;\nconst ONE_DAY = 24 * ONE_HOUR;\nconst ONE_WEEK = 7 * ONE_DAY;\n\n/**\n * Pull consent manager metrics in an organization\n *\n * @param client - GraphQL client\n * @param options - Options\n * @returns The consent manager metrics\n */\nexport async function pullConsentManagerMetrics(\n client: GraphQLClient,\n {\n bin,\n start,\n end = new Date(),\n }: {\n /** Start date to pull metrics from */\n start: Date;\n /** End date to pull metrics from (assumes now) */\n end?: Date;\n /** Bin size to pull metrics */\n bin: ConsentManagerMetricBin;\n },\n): Promise<{\n /** Privacy signal data */\n PRIVACY_SIGNAL_TIMESERIES: ConsentManagerMetric[];\n /** Consent changes data */\n CONSENT_CHANGES_TIMESERIES: ConsentManagerMetric[];\n /** Consent sessions by regime */\n CONSENT_SESSIONS_BY_REGIME: ConsentManagerMetric[];\n}> {\n // Grab the bundleId associated with this API key\n const airgapBundleId = await fetchConsentManagerId(client);\n\n // convert start and end to times\n const startTime = Math.floor(start.getTime() / 1000);\n const endTime = Math.floor(end.getTime() / 1000);\n if (startTime > endTime) {\n throw new Error('Received \"end\" date that happened before \"start\" date');\n }\n\n // do not allow hourly bins greater than 2 weeks\n if (bin === '1h' && end.getTime() - start.getTime() > ONE_WEEK * 2) {\n throw new Error(\n 'When using bin=1h, start and end time can be no more than 2 weeks apart',\n );\n }\n\n // Pull in the metrics\n const startDate = start.toISOString();\n const endDate = end.toISOString();\n const [privacySignalData, consentChangesData, consentSessionsByRegimeData] =\n await Promise.all([\n fetchConsentManagerAnalyticsData(client, {\n dataSource: 'PRIVACY_SIGNAL_TIMESERIES',\n startDate,\n endDate,\n forceRefetch: true,\n airgapBundleId,\n binInterval: bin,\n smoothTimeseries: false,\n }),\n fetchConsentManagerAnalyticsData(client, {\n dataSource: 'CONSENT_CHANGES_TIMESERIES',\n startDate,\n endDate,\n forceRefetch: true,\n airgapBundleId,\n binInterval: bin,\n smoothTimeseries: false,\n }),\n fetchConsentManagerAnalyticsData(client, {\n dataSource: 'CONSENT_SESSIONS_BY_REGIME',\n startDate,\n endDate,\n forceRefetch: true,\n airgapBundleId,\n binInterval: bin,\n smoothTimeseries: false,\n }),\n ]);\n\n return {\n PRIVACY_SIGNAL_TIMESERIES: privacySignalData,\n CONSENT_CHANGES_TIMESERIES: consentChangesData,\n CONSENT_SESSIONS_BY_REGIME: consentSessionsByRegimeData,\n };\n}\n","/**\n * Convert a domain to host\n *\n * @param domain - e.g. test.acme.com\n * @returns Host acme.com\n */\nexport const domainToHost = (domain: string): string =>\n new URL(`https://${domain}`).hostname.split('.').slice(-2).join('.');\n","import colors from 'colors';\n\nimport { buildTranscendGraphQLClient, fetchConsentManager } from '../graphql';\nimport { difference } from 'lodash-es';\nimport { map } from '../bluebird-replace';\nimport { StoredApiKey } from '../../codecs';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\nimport { logger } from '../../logger';\nimport { domainToHost } from './domainToHost';\n\n/**\n * Sync group configuration mapping\n * e.g.\n * {\n * \"abdb5e78-0d69-4554-a3bd-84b72ca3b3d9\": [\n * \"test.com\"\n * ],\n * \"f6b3ba87-c9df-444f-b420-6fac49e35910\": [\n * \"blue.com\"\n * ]\n * }\n */\nexport type XdiSyncGroups = { [k in string]: string[] };\n\n/** Regular expression for IP addresses - remove these from sync endpoint */\nexport const IP_ADDRESS_REGEX =\n // eslint-disable-next-line max-len\n /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;\n\n/**\n * Build the sync endpoint definition for a set of Transcend accounts\n *\n * @param apiKeys - The API keys that will be used to pull down configurations for\n * @param options - Options\n * @returns The XDI configuration\n */\nexport async function buildXdiSyncEndpoint(\n apiKeys: string | StoredApiKey[],\n {\n xdiLocation,\n transcendUrl = DEFAULT_TRANSCEND_API,\n removeIpAddresses = true,\n domainBlockList = ['localhost'],\n xdiAllowedCommands = 'ConsentManager:Sync',\n }: {\n /** The file location where the XDI file is hosted */\n xdiLocation: string;\n /** URL of Transcend API */\n transcendUrl?: string;\n /** When true, remove IP addresses (defaults to true) */\n removeIpAddresses?: boolean;\n /** Block list of domains to omit from sync endpoint - includes `localhost` by default */\n domainBlockList?: string[];\n /** Allows XDI commands */\n xdiAllowedCommands?: string;\n },\n): Promise<{\n /** Sync group configurations */\n syncGroups: XdiSyncGroups;\n /** The HTML string */\n html: string;\n}> {\n // Convert API keys to list\n const apiKeysAsList = Array.isArray(apiKeys)\n ? apiKeys\n : [{ apiKey: apiKeys, organizationId: '', organizationName: '' }];\n\n // Fetch configuration for each account\n const consentManagers = await map(\n apiKeysAsList,\n async (apiKey) => {\n logger.info(\n colors.magenta(\n `Pulling consent metadata for organization - ${apiKey.organizationName}`,\n ),\n );\n\n // Create a GraphQL client\n const client = buildTranscendGraphQLClient(transcendUrl, apiKey.apiKey);\n\n // Grab consent manager\n const consentManager = await fetchConsentManager(client);\n return consentManager;\n },\n { concurrency: 5 },\n );\n\n // construct the sync groups\n const syncGroups: XdiSyncGroups = {};\n consentManagers.forEach((consentManager) => {\n // grab the partition key\n const partitionKey =\n // take explicit key first\n consentManager.partition?.partition ||\n // fallback to bundle ID\n consentManager.bundleURL.split('/').reverse()[1];\n\n // Ensure that partition exists in the sync groups\n if (!syncGroups[partitionKey]) {\n syncGroups[partitionKey] = [];\n }\n\n // Map domain list to a host list\n const hosts = difference(\n consentManager.configuration.domains\n .filter(\n // ignore IP addresses\n (domain) => !removeIpAddresses || !IP_ADDRESS_REGEX.test(domain),\n )\n .map((domain) => domainToHost(domain)),\n // ignore block list\n domainBlockList,\n );\n // merge existing sync group with hosts for this consent manager\n syncGroups[partitionKey] = [\n ...new Set([...(syncGroups[partitionKey] || []), ...hosts]),\n ];\n });\n\n // Construct the HTML\n const syncEndpointHtml = `\n<!DOCTYPE html>\n<script\nsrc=\"${xdiLocation}\"\ndata-sync-groups='${JSON.stringify(syncGroups, null, 2)}'\ndata-xdi-commands=\"${xdiAllowedCommands}\"\n></script>\n`;\n\n return {\n html: syncEndpointHtml,\n syncGroups,\n };\n}\n","import { BusinessEntityInput, ConsentManagerInput } from '../../codecs';\nimport { logger } from '../../logger';\n\n/**\n * Combine multiple consent manager configurations into a list of business entity configurations\n *\n * @param inputs - Consent manager configurations to combine\n * @returns Business entity configuration input\n */\nexport function consentManagersToBusinessEntities(\n inputs: {\n /** Name of business entity */\n name: string;\n /** Consent manager input */\n input?: ConsentManagerInput;\n }[],\n): BusinessEntityInput[] {\n // Construct the business entities YAML definition\n const businessEntities = inputs.map(\n ({ name, input }): BusinessEntityInput => ({\n // Title of Transcend Instance\n title: name.replace('.yml', ''),\n attributes: [\n // Sync domain list\n ...(input?.domains\n ? [\n {\n key: 'Transcend Domain List',\n values: [...new Set(input.domains)],\n },\n ]\n : []),\n // Sync bundle URLs\n ...(input?.bundleUrls\n ? [\n {\n key: 'Airgap Production URL',\n values: [input.bundleUrls.PRODUCTION],\n },\n {\n key: 'Airgap Test URL',\n values: [input.bundleUrls.TEST],\n },\n {\n key: 'Airgap XDI URL',\n values: [\n input.bundleUrls.PRODUCTION.replace('airgap.js', 'xdi.js'),\n ],\n },\n ]\n : []),\n // Sync partition keys\n ...(input?.partition\n ? [\n {\n key: 'Consent Partition Key',\n values: [input.partition],\n },\n ]\n : []),\n ],\n }),\n );\n\n // Log out info on airgap scripts to host\n logger.info('\\n\\n~~~~~~~~~~~\\nAirgap scripts to host:');\n businessEntities.forEach(({ attributes, title }, ind) => {\n attributes\n ?.find((attr) => attr.key === 'Airgap Production URL')\n ?.values?.forEach((url) => {\n logger.info(`${ind}) ${title} - ${url}`);\n });\n });\n\n return businessEntities;\n}\n","import * as t from 'io-ts';\nimport { decodeCodec } from '@transcend-io/type-utils';\nimport type { Got } from 'got';\nimport { ConsentPreferenceFetch } from './types';\n\nexport const ConsentPreferenceResponse = t.intersection([\n t.type({\n nodes: t.array(ConsentPreferenceFetch),\n }),\n t.partial({\n lastKey: t.partial({\n userId: t.string,\n partition: t.string,\n timestamp: t.string,\n }),\n }),\n]);\n\n/** Type override */\nexport type ConsentPreferenceResponse = t.TypeOf<\n typeof ConsentPreferenceResponse\n>;\n\n/**\n * Fetch consent preferences for the managed consent database\n *\n * @param sombra - Sombra instance configured to make requests\n * @param options - Additional options\n * @returns The consent preferences\n */\nexport async function fetchConsentPreferences(\n sombra: Got,\n {\n partition,\n filterBy = {},\n limit = 50,\n }: {\n /** Partition key to fetch */\n partition: string;\n /** Filter consent preferences */\n filterBy?: {\n /** Fetch specific identifiers */\n identifiers?: string[];\n /** Filter before timestamp */\n timestampBefore?: string;\n /** Filter after timestamp */\n timestampAfter?: string;\n };\n /** Number of items to pull back at once */\n limit?: number;\n },\n): Promise<ConsentPreferenceFetch[]> {\n let currentLastKey: ConsentPreferenceResponse['lastKey'];\n const data: ConsentPreferenceFetch[] = [];\n let shouldContinue = true;\n\n while (shouldContinue) {\n const response = await sombra\n .post('v1/consent-preferences', {\n json: {\n partition,\n ...filterBy,\n // using lastKey to paginate if it exists (will not for first iteration)\n startKey: currentLastKey || undefined,\n limit,\n },\n })\n .json();\n const { nodes, lastKey } = decodeCodec(ConsentPreferenceResponse, response);\n\n if (!nodes || nodes.length === 0) {\n break;\n }\n\n // Process the data received from the API call\n // For example, push the new data into an array\n data.push(...nodes);\n\n // Extract the lastKey from the API response\n currentLastKey = lastKey;\n shouldContinue = !!lastKey && Object.keys(lastKey).length > 0;\n }\n\n return data;\n}\n"],"mappings":"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","names":["ConsentBundleType","colors","updateConsentManagerVersionToLatest","auth","deploy","transcendUrl","DEFAULT_TRANSCEND_API","bundleTypes","ConsentBundleType","client","buildTranscendGraphQLClient","consentManagerId","fetchConsentManagerId","mapSeries","bundleType","logger","colors","updateConsentManagerToLatest","deployConsentManager","colors","OMIT_COLUMNS","uploadDataFlowsFromCsv","auth","trackerStatus","file","classifyService","transcendUrl","DEFAULT_TRANSCEND_API","client","buildTranscendGraphQLClient","logger","colors","validatedDataFlowInputs","readCsv","DataFlowCsvInput","Type","Notes","Service","Purpose","Status","Owners","Teams","value","rest","splitCsvToList","key","syncDataFlows","colors","OMIT_COLUMNS","uploadCookiesFromCsv","auth","trackerStatus","file","transcendUrl","DEFAULT_TRANSCEND_API","client","buildTranscendGraphQLClient","logger","colors","validatedCookieInputs","readCsv","CookieCsvInput","isRegex","Notes","Service","Purpose","Status","Owners","Teams","Name","rest","splitCsvToList","key","value","syncCookies","ONE_SECOND","ONE_MINUTE","ONE_HOUR","ONE_DAY","ONE_WEEK","pullConsentManagerMetrics","client","bin","start","end","airgapBundleId","fetchConsentManagerId","startTime","endTime","startDate","endDate","privacySignalData","consentChangesData","consentSessionsByRegimeData","fetchConsentManagerAnalyticsData","domainToHost","domain","colors","difference","IP_ADDRESS_REGEX","buildXdiSyncEndpoint","apiKeys","xdiLocation","transcendUrl","DEFAULT_TRANSCEND_API","removeIpAddresses","domainBlockList","xdiAllowedCommands","apiKeysAsList","consentManagers","map","apiKey","logger","colors","client","buildTranscendGraphQLClient","fetchConsentManager","syncGroups","consentManager","partitionKey","hosts","difference","domain","domainToHost","consentManagersToBusinessEntities","inputs","businessEntities","name","input","logger","attributes","title","ind","attr","url","t","decodeCodec","ConsentPreferenceResponse","ConsentPreferenceFetch","fetchConsentPreferences","sombra","partition","filterBy","limit","currentLastKey","data","shouldContinue","response","nodes","lastKey","decodeCodec"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{q as N}from"./chunk-N6JZHL5U.js";import{De as U,_b as F,a as v,b as q,pe as D,qe as R,ve as O,wa as G}from"./chunk-MK5T6DBK.js";import{a as t}from"./chunk-43JWXG77.js";import{e as T}from"./chunk-L5ULN3IT.js";import*as e from"io-ts";import{decodeCodec as Y}from"@transcend-io/type-utils";var Z=e.type({identifier:e.string,type:e.string,coreIdentifier:e.string,dataSiloId:e.string,requestId:e.string,nonce:e.string,requestCreatedAt:e.string,daysUntilOverdue:e.number,attributes:e.array(e.type({key:e.string,values:e.array(e.string)}))});async function L(r,{dataSiloId:s,limit:c=100,offset:n=0,requestType:a}){try{let i=await r.get(`v1/data-silo/${s}/pending-requests/${a}`,{searchParams:{offset:n,limit:c}}).json(),{items:f}=Y(e.type({items:e.array(Z)}),i);return f}catch(i){throw new Error(`Received an error from server: ${i?.response?.body||i?.message}`)}}import*as S from"io-ts";var B=S.type({nonce:S.string,identifier:S.string});async function j(r,{nonce:s,identifier:c}){try{return await r.put("v1/data-silo",{headers:{"x-transcend-nonce":s},json:{profiles:[{profileId:c}]}}),!0}catch(n){if(n.response?.statusCode===409)return!1;throw new Error(`Received an error from server: ${n?.response?.body||n?.message}`)}}import{chunk as W}from"lodash-es";import p from"colors";import Q from"cli-progress";async function ue({file:r,dataSiloId:s,auth:c,sombraAuth:n,concurrency:a=100,transcendUrl:i=T,sleepSeconds:f=10}){let y=await R(i,c,n);t.info(p.magenta(`Reading "${r}" from disk`));let o=N(r,B);t.info(p.magenta(`Notifying Transcend for data silo "${s}" marking "${o.length}" identifiers as completed.`));let C=new Date().getTime(),w=new Q.SingleBar({},Q.Presets.shades_classic),d=0,u=0,l=0;w.start(o.length,0);let m=W(o,a),I=m.length;await v(m,async($,P)=>{t.info(p.blue(`Processing chunk ${P+1}/${I} (${W.length} items)`)),await q($,async h=>{try{await j(y,h)?d+=1:u+=1}catch(b){t.error(p.red(`Error notifying Transcend for identifier "${h.identifier}" - ${b?.message}`)),l+=1}w.update(d+u)}),f>0&&P<I-1&&(t.info(p.yellow(`Sleeping for ${f}s before next chunk...`)),await new Promise(h=>{setTimeout(h,f*1e3)}))}),w.stop();let x=new Date().getTime()-C;if(t.info(p.green(`Successfully notified Transcend for ${d} identifiers in "${x/1e3}" seconds!`)),u&&t.info(p.magenta(`There were ${u} identifiers that were not in a state to be updated.They likely have already been resolved.`)),l)throw t.error(p.red(`There were ${l} identifiers that failed to be updated. Please review the logs for more information.`)),new Error("Failed to update all identifiers");return o.length}import z from"colors";import H from"cli-progress";import{RequestDataSiloStatus as ee}from"@transcend-io/privacy-types";async function Te({requestIds:r,dataSiloId:s,auth:c,concurrency:n=100,status:a=ee.Resolved,transcendUrl:i=T}){let f=D(i,c),y=new Date().getTime(),o=new H.SingleBar({},H.Presets.shades_classic);t.info(z.magenta(`Notifying Transcend for data silo "${s}" marking "${r.length}" requests as completed.`));let C=0;o.start(r.length,0),await q(r,async u=>{let l=await U(f,{requestId:u,dataSiloId:s});try{await F(f,G,{requestDataSiloId:l.id,status:a})}catch(m){if(!m.message.includes("Client error: Request must be active:"))throw m}C+=1,o.update(C)},{concurrency:n}),o.stop();let d=new Date().getTime()-y;return t.info(z.green(`Successfully notified Transcend in "${d/1e3}" seconds!`)),r.length}import k from"colors";import J from"cli-progress";async function ke({dataSiloId:r,auth:s,sombraAuth:c,actions:n,apiPageSize:a=100,savePageSize:i=1e3,onSave:f,transcendUrl:y=T,skipRequestCount:o=!1}){if(i%a!==0)throw new Error(`savePageSize must be a multiple of apiPageSize. savePageSize: ${i}, apiPageSize: ${a}`);let C=await R(y,s,c),w=D(y,s),d=0;o||(d=await O(w,{dataSiloId:r})),t.info(k.magenta(`Pulling ${o?"all":d} outstanding request identifiers for data silo: "${r}" for requests of types "${n.join('", "')}"`));let u=new Date().getTime(),l=new J.SingleBar({},J.Presets.shades_classic),m=new Set,I=[],g=[];o||l.start(d,0),await v(n,async $=>{let P=0,h=!0;for(;h;){let b=await L(C,{dataSiloId:r,limit:a,offset:P,requestType:$}),E=b.map(A=>(m.add(A.requestId),{...A,action:$})),M=E.map(({attributes:A,...V})=>({...V,...A.reduce((X,_)=>Object.assign(X,{[_.key]:_.values.join(",")}),{})}));I.push(...E),g.push(...M),g.length>=i&&(await f(g),g=[]),h=b.length===a,P+=a,o?t.info(k.magenta(`Pulled ${b.length} outstanding identifiers for ${m.size} requests`)):l.update(m.size)}}),g.length>0&&await f(g),o||l.stop();let x=new Date().getTime()-u;return t.info(k.green(`Successfully pulled ${I.length} outstanding identifiers from ${m.size} requests in "${x/1e3}" seconds!`)),{identifiers:I}}export{Z as a,L as b,B as c,j as d,ue as e,Te as f,ke as g};
|
|
2
|
+
//# sourceMappingURL=chunk-2LCGZ77N.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/cron/pullCronPageOfIdentifiers.ts","../src/lib/cron/markCronIdentifierCompleted.ts","../src/lib/cron/pushCronIdentifiersFromCsv.ts","../src/lib/cron/markRequestDataSiloIdsCompleted.ts","../src/lib/cron/pullChunkedCustomSiloOutstandingIdentifiers.ts"],"sourcesContent":["import * as t from 'io-ts';\nimport { decodeCodec } from '@transcend-io/type-utils';\nimport { RequestAction } from '@transcend-io/privacy-types';\nimport type { Got } from 'got';\n\nexport const CronIdentifier = t.type({\n /** The identifier value */\n identifier: t.string,\n /** The type of identifier */\n type: t.string,\n /** The core identifier of the request */\n coreIdentifier: t.string,\n /** The ID of the underlying data silo */\n dataSiloId: t.string,\n /** The ID of the underlying request */\n requestId: t.string,\n /** The request nonce */\n nonce: t.string,\n /** The time the request was created */\n requestCreatedAt: t.string,\n /** The number of days until the request is overdue */\n daysUntilOverdue: t.number,\n /** Request attributes */\n attributes: t.array(\n t.type({\n key: t.string,\n values: t.array(t.string),\n }),\n ),\n});\n\n/** Type override */\nexport type CronIdentifier = t.TypeOf<typeof CronIdentifier>;\n\n/**\n * Pull a offset of identifiers for a cron job\n *\n * @see https://docs.transcend.io/docs/api-reference/GET/v1/data-silo/(id)/pending-requests/(type)\n * @param sombra - Sombra instance configured to make requests\n * @param options - Additional options\n * @returns Successfully submitted request\n */\nexport async function pullCronPageOfIdentifiers(\n sombra: Got,\n {\n dataSiloId,\n limit = 100,\n offset = 0,\n requestType,\n }: {\n /** Data Silo ID */\n dataSiloId: string;\n /** Type of request */\n requestType: RequestAction;\n /** Number of identifiers to pull in */\n limit?: number;\n /** Page to pull in */\n offset?: number;\n },\n): Promise<CronIdentifier[]> {\n try {\n // Make the GraphQL request\n const response = await sombra\n .get(`v1/data-silo/${dataSiloId}/pending-requests/${requestType}`, {\n searchParams: {\n offset,\n limit,\n },\n })\n .json();\n\n const { items } = decodeCodec(\n t.type({\n items: t.array(CronIdentifier),\n }),\n response,\n );\n return items;\n } catch (err) {\n throw new Error(\n `Received an error from server: ${err?.response?.body || err?.message}`,\n );\n }\n}\n","import type { Got } from 'got';\nimport * as t from 'io-ts';\n\n/**\n * Minimal set required to mark as completed\n */\nexport const CronIdentifierPush = t.type({\n nonce: t.string,\n identifier: t.string,\n});\n\n/** Type override */\nexport type CronIdentifierPush = t.TypeOf<typeof CronIdentifierPush>;\n\n/**\n * Mark an identifier output by the cron job as completed.\n *\n * @see https://docs.transcend.io/docs/api-reference/PUT/v1/data-silo\n * @param sombra - Sombra instance configured to make requests\n * @param options - Additional options\n * @returns Successfully submitted request, false if not in a state to update\n */\nexport async function markCronIdentifierCompleted(\n sombra: Got,\n { nonce, identifier }: CronIdentifierPush,\n): Promise<boolean> {\n try {\n // Make the GraphQL request\n await sombra.put('v1/data-silo', {\n headers: {\n 'x-transcend-nonce': nonce,\n },\n json: {\n profiles: [\n {\n profileId: identifier,\n },\n ],\n },\n });\n return true;\n } catch (err) {\n // handle gracefully\n if (err.response?.statusCode === 409) {\n return false;\n }\n throw new Error(\n `Received an error from server: ${err?.response?.body || err?.message}`,\n );\n }\n}\n","import { map, mapSeries } from '../bluebird-replace';\nimport { chunk } from 'lodash-es';\nimport { createSombraGotInstance } from '../graphql';\nimport colors from 'colors';\nimport {\n markCronIdentifierCompleted,\n CronIdentifierPush,\n} from './markCronIdentifierCompleted';\nimport cliProgress from 'cli-progress';\nimport { logger } from '../../logger';\nimport { readCsv } from '../requests';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Given a CSV of cron job outputs, mark all requests as completed in Transcend\n *\n * @param options - Options\n * @returns Number of items marked as completed\n */\nexport async function pushCronIdentifiersFromCsv({\n file,\n dataSiloId,\n auth,\n sombraAuth,\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n sleepSeconds = 10,\n}: {\n /** CSV file path */\n file: string;\n /** Transcend API key authentication */\n auth: string;\n /** Data Silo ID to pull down jobs for */\n dataSiloId: string;\n /** Upload concurrency */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** Sleep time in seconds between chunks of concurrent calls */\n sleepSeconds?: number;\n}): Promise<number> {\n // Create sombra instance to communicate with\n const sombra = await createSombraGotInstance(transcendUrl, auth, sombraAuth);\n\n // Read from CSV\n logger.info(colors.magenta(`Reading \"${file}\" from disk`));\n const activeResults = readCsv(file, CronIdentifierPush);\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Notifying Transcend for data silo \"${dataSiloId}\" marking \"${activeResults.length}\" identifiers as completed.`,\n ),\n );\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(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n let successCount = 0;\n let failureCount = 0;\n let errorCount = 0;\n progressBar.start(activeResults.length, 0);\n\n // Process in chunks with sleep intervals\n const chunks = chunk(activeResults, concurrency);\n const totalChunks = chunks.length;\n const processChunk = async (\n items: CronIdentifierPush[],\n chunkIndex: number,\n ): Promise<void> => {\n logger.info(\n colors.blue(\n `Processing chunk ${chunkIndex + 1}/${totalChunks} (${\n chunk.length\n } items)`,\n ),\n );\n\n // Process the items of the chunk concurrently\n await map(items, async (identifier) => {\n try {\n const success = await markCronIdentifierCompleted(sombra, identifier);\n if (success) {\n successCount += 1;\n } else {\n failureCount += 1;\n }\n } catch (e) {\n logger.error(\n colors.red(\n `Error notifying Transcend for identifier \"${identifier.identifier}\" - ${e?.message}`,\n ),\n );\n errorCount += 1;\n }\n progressBar.update(successCount + failureCount);\n });\n\n // Sleep between chunks (except for the last chunk)\n if (sleepSeconds > 0 && chunkIndex < totalChunks - 1) {\n logger.info(\n colors.yellow(`Sleeping for ${sleepSeconds}s before next chunk...`),\n );\n\n await new Promise((resolve) => {\n setTimeout(resolve, sleepSeconds * 1000);\n });\n }\n };\n\n // Process all chunks sequentially\n await mapSeries(chunks, processChunk);\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 for ${successCount} identifiers in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n if (failureCount) {\n logger.info(\n colors.magenta(\n `There were ${failureCount} identifiers that were not in a state to be updated.` +\n 'They likely have already been resolved.',\n ),\n );\n }\n if (errorCount) {\n logger.error(\n colors.red(\n `There were ${errorCount} identifiers that failed to be updated. Please review the logs for more information.`,\n ),\n );\n throw new Error('Failed to update all identifiers');\n }\n return activeResults.length;\n}\n","import { map } from '../bluebird-replace';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport {\n CHANGE_REQUEST_DATA_SILO_STATUS,\n fetchRequestDataSilo,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\nimport { RequestDataSiloStatus } from '@transcend-io/privacy-types';\n\n/**\n * Given a CSV of Request IDs, mark associated RequestDataSilos as completed\n *\n * @param options - Options\n * @returns Number of items marked as completed\n */\nexport async function markRequestDataSiloIdsCompleted({\n requestIds,\n dataSiloId,\n auth,\n concurrency = 100,\n status = RequestDataSiloStatus.Resolved,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The list of request ids to mark as completed */\n requestIds: string[];\n /** Transcend API key authentication */\n auth: string;\n /** Data Silo ID to pull down jobs for */\n dataSiloId: string;\n /** Status to update requests to */\n status?: RequestDataSiloStatus;\n /** Upload concurrency */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Notifying Transcend for data silo \"${dataSiloId}\" marking \"${requestIds.length}\" requests as completed.`,\n ),\n );\n\n let total = 0;\n progressBar.start(requestIds.length, 0);\n await map(\n requestIds,\n async (requestId) => {\n const requestDataSilo = await fetchRequestDataSilo(client, {\n requestId,\n dataSiloId,\n });\n\n try {\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, CHANGE_REQUEST_DATA_SILO_STATUS, {\n requestDataSiloId: requestDataSilo.id,\n status,\n });\n } catch (err) {\n if (!err.message.includes('Client error: Request must be active:')) {\n throw err;\n }\n }\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully notified Transcend in \"${totalTime / 1000}\" seconds!`,\n ),\n );\n return requestIds.length;\n}\n","import {\n buildTranscendGraphQLClient,\n createSombraGotInstance,\n fetchRequestDataSiloActiveCount,\n} from '../graphql';\nimport colors from 'colors';\nimport cliProgress from 'cli-progress';\nimport {\n pullCronPageOfIdentifiers,\n CronIdentifier,\n} from './pullCronPageOfIdentifiers';\nimport { RequestAction } from '@transcend-io/privacy-types';\n\nimport { logger } from '../../logger';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\nimport { mapSeries } from '../bluebird-replace';\n\n/**\n * A CSV formatted identifier\n */\nexport type CsvFormattedIdentifier = {\n [k in string]: string | null | boolean | number;\n};\n\nexport interface CronIdentifierWithAction extends CronIdentifier {\n /** The request action that the identifier relates to */\n action: RequestAction;\n}\n\n/**\n * Pull the set of identifiers outstanding for a cron or AVC integration\n *\n * This function is designed to be used in a loop, and will call the onSave callback\n * with a chunk of identifiers when the savePageSize is reached.\n *\n * @param options - Options\n * @returns The identifiers and identifiers formatted for CSV\n */\nexport async function pullChunkedCustomSiloOutstandingIdentifiers({\n dataSiloId,\n auth,\n sombraAuth,\n actions,\n apiPageSize = 100,\n savePageSize = 1000,\n onSave,\n transcendUrl = DEFAULT_TRANSCEND_API,\n skipRequestCount = false,\n}: {\n /** Transcend API key authentication */\n auth: string;\n /** Data Silo ID to pull down jobs for */\n dataSiloId: string;\n /** The request actions to fetch */\n actions: RequestAction[];\n /** How many identifiers to pull in a single call to the backend */\n apiPageSize: number;\n /** How many identifiers to save at a time (usually to a CSV file, should be a multiple of apiPageSize) */\n savePageSize: number;\n /** Callback function called when a chunk of identifiers is ready to be saved */\n onSave: (chunk: CsvFormattedIdentifier[]) => Promise<void>;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** Skip request count */\n skipRequestCount?: boolean;\n}): Promise<{\n /** Raw Identifiers */\n identifiers: CronIdentifierWithAction[];\n}> {\n // Validate savePageSize\n if (savePageSize % apiPageSize !== 0) {\n throw new Error(\n `savePageSize must be a multiple of apiPageSize. savePageSize: ${savePageSize}, apiPageSize: ${apiPageSize}`,\n );\n }\n\n // Create sombra instance to communicate with\n const sombra = await createSombraGotInstance(transcendUrl, auth, sombraAuth);\n\n // Create GraphQL client to connect to Transcend backend\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n let totalRequestCount = 0;\n if (!skipRequestCount) {\n totalRequestCount = await fetchRequestDataSiloActiveCount(client, {\n dataSiloId,\n });\n }\n\n logger.info(\n colors.magenta(\n `Pulling ${\n skipRequestCount ? 'all' : totalRequestCount\n } outstanding request identifiers ` +\n `for data silo: \"${dataSiloId}\" for requests of types \"${actions.join(\n '\", \"',\n )}\"`,\n ),\n );\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(\n {},\n cliProgress.Presets.shades_classic,\n );\n const foundRequestIds = new Set<string>();\n\n // identifiers found in total\n const identifiers: CronIdentifierWithAction[] = [];\n // current chunk of identifiers to be saved\n let currentChunk: CsvFormattedIdentifier[] = [];\n\n // map over each action\n if (!skipRequestCount) {\n progressBar.start(totalRequestCount, 0);\n }\n await mapSeries(actions, async (action) => {\n let offset = 0;\n let shouldContinue = true;\n\n // Fetch a page of identifiers\n while (shouldContinue) {\n const pageIdentifiers = await pullCronPageOfIdentifiers(sombra, {\n dataSiloId,\n limit: apiPageSize,\n offset,\n requestType: action,\n });\n\n const identifiersWithAction: CronIdentifierWithAction[] =\n pageIdentifiers.map((identifier) => {\n foundRequestIds.add(identifier.requestId);\n return {\n ...identifier,\n action,\n };\n });\n\n const csvFormattedIdentifiers = identifiersWithAction.map(\n ({ attributes, ...identifier }) => ({\n ...identifier,\n ...attributes.reduce(\n (acc, val) =>\n Object.assign(acc, {\n [val.key]: val.values.join(','),\n }),\n {},\n ),\n }),\n );\n\n identifiers.push(...identifiersWithAction);\n currentChunk.push(...csvFormattedIdentifiers);\n\n // Check if we've reached the savePageSize and call the onSave callback\n if (currentChunk.length >= savePageSize) {\n await onSave(currentChunk);\n currentChunk = [];\n }\n\n shouldContinue = pageIdentifiers.length === apiPageSize;\n offset += apiPageSize;\n if (!skipRequestCount) {\n progressBar.update(foundRequestIds.size);\n } else {\n logger.info(\n colors.magenta(\n `Pulled ${pageIdentifiers.length} outstanding identifiers for ${foundRequestIds.size} requests`,\n ),\n );\n }\n }\n });\n\n // Save any remaining identifiers in the current chunk\n if (currentChunk.length > 0) {\n await onSave(currentChunk);\n }\n\n if (!skipRequestCount) {\n progressBar.stop();\n }\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully pulled ${identifiers.length} outstanding identifiers from ${\n foundRequestIds.size\n } requests in \"${totalTime / 1000}\" seconds!`,\n ),\n );\n\n return { identifiers };\n}\n"],"mappings":"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","names":["t","decodeCodec","CronIdentifier","pullCronPageOfIdentifiers","sombra","dataSiloId","limit","offset","requestType","response","items","err","t","CronIdentifierPush","markCronIdentifierCompleted","sombra","nonce","identifier","err","chunk","colors","cliProgress","pushCronIdentifiersFromCsv","file","dataSiloId","auth","sombraAuth","concurrency","transcendUrl","DEFAULT_TRANSCEND_API","sleepSeconds","sombra","createSombraGotInstance","logger","colors","activeResults","readCsv","CronIdentifierPush","t0","progressBar","cliProgress","successCount","failureCount","errorCount","chunks","chunk","totalChunks","mapSeries","items","chunkIndex","map","identifier","markCronIdentifierCompleted","e","resolve","totalTime","colors","cliProgress","RequestDataSiloStatus","markRequestDataSiloIdsCompleted","requestIds","dataSiloId","auth","concurrency","status","transcendUrl","DEFAULT_TRANSCEND_API","client","buildTranscendGraphQLClient","t0","progressBar","cliProgress","logger","colors","total","map","requestId","requestDataSilo","fetchRequestDataSilo","makeGraphQLRequest","CHANGE_REQUEST_DATA_SILO_STATUS","err","totalTime","colors","cliProgress","pullChunkedCustomSiloOutstandingIdentifiers","dataSiloId","auth","sombraAuth","actions","apiPageSize","savePageSize","onSave","transcendUrl","DEFAULT_TRANSCEND_API","skipRequestCount","sombra","createSombraGotInstance","client","buildTranscendGraphQLClient","totalRequestCount","fetchRequestDataSiloActiveCount","logger","colors","t0","progressBar","cliProgress","foundRequestIds","identifiers","currentChunk","mapSeries","action","offset","shouldContinue","pageIdentifiers","pullCronPageOfIdentifiers","identifiersWithAction","identifier","csvFormattedIdentifiers","attributes","acc","val","totalTime"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{Ee as N,b}from"./chunk-MK5T6DBK.js";import{a}from"./chunk-43JWXG77.js";import{f as U}from"./chunk-L5ULN3IT.js";import*as E from"crypto";import*as $ from"jsonwebtoken";function B(c,l,n){let o=Buffer.from(n,"base64"),f=Buffer.from(l,"base64"),u="id-aes256-wrap-pad",d=Buffer.from("A65959A6","hex"),s=E.createCipheriv(u,f,d),i={encryptedIdentifier:Buffer.concat([s.update(c),s.final()]).toString("base64")};return $.sign(i,o,{algorithm:"HS384"})}import*as e from"io-ts";var O=e.intersection([e.type({userId:e.string,timestamp:e.string}),e.partial({confirmed:e.union([e.literal("true"),e.literal("false")]),updated:e.union([e.literal("true"),e.literal("false")]),prompted:e.union([e.literal("true"),e.literal("false")]),metadata:e.string,usp:e.union([e.string,e.null]),gpp:e.union([e.string,e.null])})]),Y=e.intersection([O,e.partial({purposes:e.string})]),G=e.intersection([O,e.type({partition:e.string}),e.partial({tcf:e.union([e.string,e.null]),purposes:e.record(e.string,e.union([e.boolean,e.string]))})]);import P from"colors";import*as r from"io-ts";import A from"cli-progress";import{decodeCodec as I}from"@transcend-io/type-utils";var R=/^[0-9][Y|N]([Y|N])[Y|N]$/,_=r.record(r.string,r.union([r.boolean,r.literal("Auto")]));async function Z({base64EncryptionKey:c,base64SigningKey:l,preferences:n,partition:o,concurrency:f=100,transcendUrl:u=U}){let d=N(u),s=n.filter(t=>t.usp&&!R.test(t.usp));if(s.length>0)throw new Error(`Received invalid usp strings: ${JSON.stringify(s,null,2)}`);let m=n.map((t,y)=>[t,y]).filter(([t])=>{if(!t.purposes)return!1;try{return I(_,t.purposes),!1}catch{return!0}});if(m.length>0)throw new Error(`Received invalid purpose maps: ${JSON.stringify(m,null,2)}`);let i=n.filter(t=>!t.usp&&!t.purposes);if(i.length>0)throw new Error(`Received invalid inputs, expected either purposes or usp to be defined: ${JSON.stringify(i,null,2)}`);a.info(P.magenta(`Uploading ${n.length} user preferences to partition ${o}`));let w=new Date().getTime(),g=new A.SingleBar({},A.Presets.shades_classic),S=0;g.start(n.length,0),await b(n,async({userId:t,confirmed:y="true",updated:T,prompted:v,purposes:x,...p})=>{let k=B(t,c,l),[,D]=p.usp?R.exec(p.usp)||[]:[],F={token:k,partition:o,consent:{confirmed:y==="true",purposes:x?I(_,x):p.usp?{SaleOfInfo:D==="Y"}:{},...T?{updated:T==="true"}:{},...v?{prompted:v==="true"}:{},...p}};try{await d.post("sync",{json:F}).json()}catch(h){try{let C=JSON.parse(h?.response?.body||"{}");C.error&&a.error(P.red(`Error: ${C.error}`))}catch{}throw new Error(`Received an error from server: ${h?.response?.body||h?.message}`)}S+=1,g.update(S)},{concurrency:f}),g.stop();let j=new Date().getTime()-w;a.info(P.green(`Successfully uploaded ${n.length} user preferences to partition ${o} in "${j/1e3}" seconds!`))}export{B as a,Y as b,G as c,R as d,_ as e,Z as f};
|
|
2
|
+
//# sourceMappingURL=chunk-2V6ABZRI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/consent-manager/createConsentToken.ts","../src/lib/consent-manager/types.ts","../src/lib/consent-manager/uploadConsents.ts"],"sourcesContent":["import * as crypto from 'crypto';\nimport * as jwt from 'jsonwebtoken';\n\n/**\n * Function to create a consent manager token\n *\n * @see https://docs.transcend.io/docs/consent/reference/managed-consent-database\n * @param userId - User ID\n * @param base64EncryptionKey - Encryption key\n * @param base64SigningKey - Signing key\n * @returns Token\n */\nexport function createConsentToken(\n userId: string,\n base64EncryptionKey: string,\n base64SigningKey: string,\n): string {\n // Read on for where to find these keys\n const signingKey = Buffer.from(base64SigningKey, 'base64');\n const encryptionKey = Buffer.from(base64EncryptionKey, 'base64');\n\n // NIST's AES-KWP implementation { aes 48 } - see https://tools.ietf.org/html/rfc5649\n const encryptionAlgorithm = 'id-aes256-wrap-pad';\n // Initial Value for AES-KWP integrity check - see https://tools.ietf.org/html/rfc5649#section-3\n const iv = Buffer.from('A65959A6', 'hex');\n // Set up encryption algorithm\n const cipher = crypto.createCipheriv(encryptionAlgorithm, encryptionKey, iv);\n\n // Encrypt the userId and base64-encode the result\n const encryptedIdentifier = Buffer.concat([\n cipher.update(userId),\n cipher.final(),\n ]).toString('base64');\n\n // Create the JWT content - jwt.sign will add a 'iat' (issued at) field to the payload\n // If you wanted to add something manually, consider\n // const issued: Date = new Date();\n // const isoDate = issued.toISOString();\n const jwtPayload = {\n encryptedIdentifier,\n };\n\n // Create a JSON web token and HMAC it with SHA-384\n const consentToken = jwt.sign(jwtPayload, signingKey, {\n algorithm: 'HS384',\n });\n\n return consentToken;\n}\n","import * as t from 'io-ts';\n\nexport const ConsentPreferenceBase = t.intersection([\n t.type({\n /** User ID */\n userId: t.string,\n /** Has the consent been updated (including no-change confirmation) since default resolution */\n timestamp: t.string,\n }),\n t.partial({\n /** Was tracking consent confirmed by the user? If this is false, the consent was resolved from defaults & is not yet confirmed */\n confirmed: t.union([t.literal('true'), t.literal('false')]),\n /**\n * Has the consent been updated (including no-change confirmation) since default resolution\n */\n updated: t.union([t.literal('true'), t.literal('false')]),\n /**\n * Whether or not the UI has been shown to the end-user (undefined in older versions of airgap.js)\n */\n prompted: t.union([t.literal('true'), t.literal('false')]),\n /** Consent metadata */\n metadata: t.string,\n /** US Privacy (USP) String */\n usp: t.union([t.string, t.null]),\n /** IAB GPP String */\n gpp: t.union([t.string, t.null]),\n }),\n]);\n\n/** Type override */\nexport type ConsentPreferenceBase = t.TypeOf<typeof ConsentPreferenceUpload>;\n\nexport const ConsentPreferenceUpload = t.intersection([\n ConsentPreferenceBase,\n t.partial({\n /**\n * Purpose map\n * This is a stringified JSON object with keys as purpose names and values as booleans or 'Auto'\n */\n purposes: t.string,\n }),\n]);\n\n/** Type override */\nexport type ConsentPreferenceUpload = t.TypeOf<typeof ConsentPreferenceUpload>;\n\nexport const ConsentPreferenceFetch = t.intersection([\n ConsentPreferenceBase,\n t.type({\n /** This is the partition key used for the dynamo entry */\n partition: t.string,\n }),\n t.partial({\n /** IAB TCF String */\n tcf: t.union([t.string, t.null]),\n /**\n * Purpose map\n * This is a JSON object with keys as purpose names and values as booleans or 'Auto'\n */\n purposes: t.record(t.string, t.union([t.boolean, t.string])),\n }),\n]);\n\n/** Type override */\nexport type ConsentPreferenceFetch = t.TypeOf<typeof ConsentPreferenceFetch>;\n","import { createTranscendConsentGotInstance } from '../graphql';\nimport colors from 'colors';\nimport * as t from 'io-ts';\nimport { DEFAULT_TRANSCEND_CONSENT_API } from '../../constants';\nimport { map } from '../bluebird-replace';\nimport { createConsentToken } from './createConsentToken';\nimport { logger } from '../../logger';\nimport cliProgress from 'cli-progress';\nimport { decodeCodec } from '@transcend-io/type-utils';\nimport type { ConsentPreferenceUpload } from './types';\nimport { ConsentPreferencesBody } from '@transcend-io/airgap.js-types';\n\nexport const USP_STRING_REGEX = /^[0-9][Y|N]([Y|N])[Y|N]$/;\n\nexport const PurposeMap = t.record(\n t.string,\n t.union([t.boolean, t.literal('Auto')]),\n);\n\n/**\n * Upload a set of consent preferences\n *\n * @param options - Options\n */\nexport async function uploadConsents({\n base64EncryptionKey,\n base64SigningKey,\n preferences,\n partition,\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_CONSENT_API,\n}: {\n /** base64 encryption key */\n base64EncryptionKey: string;\n /** base64 signing key */\n base64SigningKey: string;\n /** Partition key */\n partition: string;\n /** Sombra API key authentication */\n preferences: ConsentPreferenceUpload[];\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Concurrency limit for approving */\n concurrency?: number;\n}): Promise<void> {\n // Create connection to API\n const transcendConsentApi = createTranscendConsentGotInstance(transcendUrl);\n\n // Ensure usp strings are valid\n const invalidUspStrings = preferences.filter(\n (pref) => pref.usp && !USP_STRING_REGEX.test(pref.usp),\n );\n if (invalidUspStrings.length > 0) {\n throw new Error(\n `Received invalid usp strings: ${JSON.stringify(\n invalidUspStrings,\n null,\n 2,\n )}`,\n );\n }\n\n // Ensure purpose maps are valid\n const invalidPurposeMaps = preferences\n .map((pref, ind) => [pref, ind] as [ConsentPreferenceUpload, number])\n .filter(([pref]) => {\n if (!pref.purposes) {\n return false;\n }\n try {\n decodeCodec(PurposeMap, pref.purposes);\n return false;\n } catch {\n return true;\n }\n });\n if (invalidPurposeMaps.length > 0) {\n throw new Error(\n `Received invalid purpose maps: ${JSON.stringify(\n invalidPurposeMaps,\n null,\n 2,\n )}`,\n );\n }\n\n // Ensure usp or preferences are provided\n const invalidInputs = preferences.filter(\n (pref) => !pref.usp && !pref.purposes,\n );\n if (invalidInputs.length > 0) {\n throw new Error(\n `Received invalid inputs, expected either purposes or usp to be defined: ${JSON.stringify(\n invalidInputs,\n null,\n 2,\n )}`,\n );\n }\n\n logger.info(\n colors.magenta(\n `Uploading ${preferences.length} user preferences to partition ${partition}`,\n ),\n );\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(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Build a GraphQL client\n let total = 0;\n progressBar.start(preferences.length, 0);\n await map(\n preferences,\n async ({\n userId,\n confirmed = 'true',\n updated,\n prompted,\n purposes,\n ...consent\n }) => {\n const token = createConsentToken(\n userId,\n base64EncryptionKey,\n base64SigningKey,\n );\n\n // parse usp string\n const [, saleStatus] = consent.usp\n ? USP_STRING_REGEX.exec(consent.usp) || []\n : [];\n\n const input = {\n token,\n partition,\n consent: {\n confirmed: confirmed === 'true',\n purposes: purposes\n ? decodeCodec(PurposeMap, purposes)\n : consent.usp\n ? { SaleOfInfo: saleStatus === 'Y' }\n : {},\n ...(updated ? { updated: updated === 'true' } : {}),\n ...(prompted ? { prompted: prompted === 'true' } : {}),\n ...consent,\n },\n } as ConsentPreferencesBody;\n\n // Make the request\n try {\n await transcendConsentApi\n .post('sync', {\n json: input,\n })\n .json();\n } catch (err) {\n try {\n const parsed = JSON.parse(err?.response?.body || '{}');\n if (parsed.error) {\n logger.error(colors.red(`Error: ${parsed.error}`));\n }\n } catch (e) {\n // continue\n }\n throw new Error(\n `Received an error from server: ${\n err?.response?.body || err?.message\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 uploaded ${\n preferences.length\n } user preferences to partition ${partition} in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n}\n"],"mappings":"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","names":["crypto","jwt","createConsentToken","userId","base64EncryptionKey","base64SigningKey","signingKey","encryptionKey","encryptionAlgorithm","iv","cipher","jwtPayload","t","ConsentPreferenceBase","ConsentPreferenceUpload","ConsentPreferenceFetch","colors","t","cliProgress","decodeCodec","USP_STRING_REGEX","PurposeMap","uploadConsents","base64EncryptionKey","base64SigningKey","preferences","partition","concurrency","transcendUrl","DEFAULT_TRANSCEND_CONSENT_API","transcendConsentApi","createTranscendConsentGotInstance","invalidUspStrings","pref","invalidPurposeMaps","ind","invalidInputs","logger","colors","t0","progressBar","total","map","userId","confirmed","updated","prompted","purposes","consent","token","createConsentToken","saleStatus","input","err","parsed","totalTime"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{e as o}from"./chunk-ARVEJERC.js";import*as e from"io-ts";import{valuesOf as a}from"@transcend-io/type-utils";var d=({TRouteName:t})=>e.type({routeName:t,enabledPolicies:e.array(a(o))});import*as r from"io-ts";var l=({TEnabledRoutes:t})=>r.type({enabledRoutes:t});export{d as a,l as b};
|
|
2
|
+
//# sourceMappingURL=chunk-347UQP43.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/helpers/buildEnabledRouteType.ts","../src/lib/helpers/buildAIIntegrationType.ts"],"sourcesContent":["import * as t from 'io-ts';\nimport { EnabledRouteC } from '../../codecs';\nimport { valuesOf } from '@transcend-io/type-utils';\nimport { PathfinderPolicyName } from '../../enums';\n\n/**\n * Builds a custom io-ts type that represents a route allowed by the proxy\n *\n * @param TRouteName - the string with the name of the allowed route\n * @returns custom io-ts AllowedRoute type\n */\nexport const buildEnabledRouteType = <T extends t.Mixed>({\n TRouteName,\n}: {\n /** the type of the routeName property */\n TRouteName: T;\n}): EnabledRouteC<T> =>\n t.type({\n routeName: TRouteName,\n enabledPolicies: t.array(valuesOf(PathfinderPolicyName)),\n });\n","import * as t from 'io-ts';\nimport { AIIntegrationC, EnabledRouteC } from '../../codecs';\n\n/**\n * Helper to build a custom io-ts type representing an AIIntegration\n *\n * @param TEnabledRoutes - the type of the enabledRoutes for the AIIntegration type\n * @returns an AIIntegration type\n */\nexport const buildAIIntegrationType = <\n T extends t.Mixed,\n P extends t.ArrayC<EnabledRouteC<T>>,\n>({\n TEnabledRoutes,\n}: {\n /** the type of the enabledRoutes property */\n TEnabledRoutes: P;\n}): AIIntegrationC<T> =>\n t.type({\n enabledRoutes: TEnabledRoutes,\n });\n"],"mappings":"wCAAA,UAAYA,MAAO,QAEnB,OAAS,YAAAC,MAAgB,2BASlB,IAAMC,EAAwB,CAAoB,CACvD,WAAAC,CACF,IAII,OAAK,CACL,UAAWA,EACX,gBAAmB,QAAMC,EAASC,CAAoB,CAAC,CACzD,CAAC,ECpBH,UAAYC,MAAO,QASZ,IAAMC,EAAyB,CAGpC,CACA,eAAAC,CACF,IAII,OAAK,CACL,cAAeA,CACjB,CAAC","names":["t","valuesOf","buildEnabledRouteType","TRouteName","valuesOf","PathfinderPolicyName","t","buildAIIntegrationType","TEnabledRoutes"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import r from"colors";import{bootstrap as t}from"global-agent";import{ProxyAgent as e,setGlobalDispatcher as s}from"undici";import p from"yargs-parser";var i=console,{httpProxy:o=process.env.http_proxy}=p(process.argv.slice(2));o&&(i.info(r.green(`Initializing proxy: ${o}`)),process.env.GLOBAL_AGENT_HTTP_PROXY=o,t(),s(new e(o)));export{i as a};
|
|
2
|
+
//# sourceMappingURL=chunk-43JWXG77.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/logger.ts"],"sourcesContent":["import colors from 'colors';\nimport { bootstrap } from 'global-agent';\nimport { ProxyAgent, setGlobalDispatcher } from 'undici';\nimport yargs from 'yargs-parser';\n\nexport const logger = console;\n\n// When the proxy env var of flag is specified, initiate the proxy\nconst { httpProxy = process.env.http_proxy } = yargs(process.argv.slice(2));\nif (httpProxy) {\n logger.info(colors.green(`Initializing proxy: ${httpProxy}`));\n\n // Use global-agent, which overrides `request` based requests\n process.env.GLOBAL_AGENT_HTTP_PROXY = httpProxy;\n bootstrap();\n\n // Use undici, which overrides `fetch` based requests\n setGlobalDispatcher(new ProxyAgent(httpProxy));\n}\n"],"mappings":"AAAA,OAAOA,MAAY,SACnB,OAAS,aAAAC,MAAiB,eAC1B,OAAS,cAAAC,EAAY,uBAAAC,MAA2B,SAChD,OAAOC,MAAW,eAEX,IAAMC,EAAS,QAGhB,CAAE,UAAAC,EAAY,QAAQ,IAAI,UAAW,EAAIF,EAAM,QAAQ,KAAK,MAAM,CAAC,CAAC,EACtEE,IACFD,EAAO,KAAKL,EAAO,MAAM,uBAAuBM,CAAS,EAAE,CAAC,EAG5D,QAAQ,IAAI,wBAA0BA,EACtCL,EAAU,EAGVE,EAAoB,IAAID,EAAWI,CAAS,CAAC","names":["colors","bootstrap","ProxyAgent","setGlobalDispatcher","yargs","logger","httpProxy"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/helpers/parseVariablesFromString.ts"],"sourcesContent":["/**\n * Parse variables from string\n *\n * @param variables - Variables as string\n * @returns Variables as object\n */\nexport function parseVariablesFromString(variables: string): {\n [k in string]: string;\n} {\n // Parse out the variables\n const splitVars = variables.split(',').filter((x) => !!x);\n const vars: { [k in string]: string } = {};\n splitVars.forEach((variable) => {\n const [k, v] = variable.split(':');\n if (!k || !v) {\n throw new Error(\n `Invalid variable: ${variable}. Expected format: key:value`,\n );\n }\n vars[k] = v;\n });\n return vars;\n}\n"],"mappings":"AAMO,SAASA,EAAyBC,EAEvC,CAEA,IAAMC,EAAYD,EAAU,MAAM,GAAG,EAAE,OAAQE,GAAM,CAAC,CAACA,CAAC,EAClDC,EAAkC,CAAC,EACzC,OAAAF,EAAU,QAASG,GAAa,CAC9B,GAAM,CAACC,EAAGC,CAAC,EAAIF,EAAS,MAAM,GAAG,EACjC,GAAI,CAACC,GAAK,CAACC,EACT,MAAM,IAAI,MACR,qBAAqBF,CAAQ,8BAC/B,EAEFD,EAAKE,CAAC,EAAIC,CACZ,CAAC,EACMH,CACT","names":["parseVariablesFromString","variables","splitVars","x","vars","variable","k","v"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{fa as p}from"./chunk-LAYHULHH.js";import{Fe as h,Ge as z,Ie as $,Je as w,a as y,oe as u,zc as A}from"./chunk-MK5T6DBK.js";import{a as i}from"./chunk-43JWXG77.js";import{e as S}from"./chunk-L5ULN3IT.js";import n from"colors";async function H({email:r,password:a,scopes:f,apiKeyTitle:t,parentOrganizationId:o,deleteExistingApiKey:l=!0,createNewApiKey:x=!0,transcendUrl:k=S}){let s=await u(k,{});i.info(n.magenta("Logging in using email and password."));let{roles:d,loginCookie:P}=await h(s,{email:r,password:a});i.info(n.green(`Successfully logged in and found ${d.length} role${d.length===1?"":"s"}!`));let K=o?d.filter(e=>e.organization.id===o||e.organization.parentOrganizationId===o):d;s.setHeaders({Cookie:P});let m=[],c=[];return i.info(n.magenta(`Generating API keys with title: ${t}, scopes: ${f.join(",")}.`)),await y(K,async e=>{try{await z(s,{roleId:e.id,email:r}),i.info(n.magenta(`Checking if API key already exists in organization "${e.organization.name}" with title: "${t}".`));let[g]=await A(s,[t]);if(g&&l)i.info(n.yellow(`Deleting existing API key in "${e.organization.name}" with title: "${t}".`)),await w(s,g.id),i.info(n.green(`Successfully deleted API key in "${e.organization.name}" with title: "${t}".`));else if(g)throw new Error(`API key already exists with title: "${t}"`);if(x){i.info(n.magenta(`Creating API key in "${e.organization.name}" with title: "${t}".`));let{apiKey:N}=await $(s,{title:t,scopes:f});m.push({organizationName:e.organization.name,organizationId:e.organization.id,apiKey:N}),i.info(n.green(`Successfully created API key in "${e.organization.name}" with title: "${t}".`))}else m.push({organizationName:e.organization.name,organizationId:e.organization.id,apiKey:""})}catch(g){i.error(n.red(`Failed to create API key in organization "${e.organization.name}"! - ${g.message}`)),c.push({organizationName:e.organization.name,organizationId:e.organization.id,error:g.message})}}),i.info(n.green(`Successfully created ${m.length} API key${m.length===1?"":"s"}`)),c.length>0&&i.error(n.red(`Failed to create ${c.length} API key${c.length===1?"":"s"}!`)),{errors:c,apiKeys:m}}import{decodeCodec as C}from"@transcend-io/type-utils";import E from"colors";import*as I from"io-ts";import{existsSync as G,readFileSync as D}from"fs";function T(r){return r||(i.error(E.red("A Transcend API key must be provided. You can specify using --auth=$TRANSCEND_API_KEY")),process.exit(1)),G(r)?C(I.array(p),D(r,"utf-8")):r}import{existsSync as F,readdirSync as b}from"fs";function Z(r,a,f=!1){if(!F(r))return[];let t=b(r).filter(o=>a?a.filter(l=>o.endsWith(l)).length:!0).filter(o=>o.indexOf(".")>0);return f?t.map(o=>o.replace(/\.[^/.]+$/,"")):t}import{readdirSync as R,statSync as _}from"fs";import{join as L}from"path";function te(r){return R(r).filter(a=>_(L(r,a)).isDirectory())}export{H as a,T as b,Z as c,te as d};
|
|
2
|
+
//# sourceMappingURL=chunk-65I2PF73.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/api-keys/generateCrossAccountApiKeys.ts","../src/lib/api-keys/validateTranscendAuth.ts","../src/lib/api-keys/listFiles.ts","../src/lib/api-keys/listDirectories.ts"],"sourcesContent":["import { mapSeries } from '../bluebird-replace';\nimport {\n buildTranscendGraphQLClientGeneric,\n loginUser,\n createApiKey,\n fetchAllApiKeys,\n deleteApiKey,\n assumeRole,\n} from '../graphql';\nimport { ScopeName } from '@transcend-io/privacy-types';\nimport colors from 'colors';\nimport { StoredApiKey } from '../../codecs';\nimport { logger } from '../../logger';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\nexport interface ApiKeyGenerateError {\n /** Name of instance */\n organizationName: string;\n /** Error */\n error: string;\n /** Organization ID API key is for */\n organizationId: string;\n}\n\n/**\n * Generate API keys across multiple transcend accounts\n *\n * @param options - Options\n * @returns Number of API keys created\n */\nexport async function generateCrossAccountApiKeys({\n email,\n password,\n scopes,\n apiKeyTitle,\n parentOrganizationId,\n deleteExistingApiKey = true,\n createNewApiKey = true,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** Email address of user generating API keys */\n email: string;\n /** Password of user generating API keys */\n password: string;\n /** Filter for organizations that match this parent organization ID */\n parentOrganizationId?: string;\n /** Title of the API create to create */\n apiKeyTitle: string;\n /** Title of the API create to create */\n scopes: ScopeName[];\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** When true delete existing API keys with that title, if set to false an API key exists with that title, an error is thrown */\n deleteExistingApiKey?: boolean;\n /** When true, generate new API keys, otherwise only will delete past API keys */\n createNewApiKey?: boolean;\n}): Promise<{\n /** Successfully generated */\n apiKeys: StoredApiKey[];\n /** Error results */\n errors: ApiKeyGenerateError[];\n}> {\n // Create GraphQL client\n const client = await buildTranscendGraphQLClientGeneric(transcendUrl, {});\n\n // Login the user\n logger.info(colors.magenta('Logging in using email and password.'));\n const { roles, loginCookie } = await loginUser(client, { email, password });\n logger.info(\n colors.green(\n `Successfully logged in and found ${roles.length} role${\n roles.length === 1 ? '' : 's'\n }!`,\n ),\n );\n\n // Filter down by parentOrganizationId\n const filteredRoles = parentOrganizationId\n ? roles.filter(\n (role) =>\n role.organization.id === parentOrganizationId ||\n role.organization.parentOrganizationId === parentOrganizationId,\n )\n : roles;\n\n // Save cookie to call route subsequent times\n client.setHeaders({\n Cookie: loginCookie,\n });\n\n // Save the resulting API keys\n const results: StoredApiKey[] = [];\n const errors: ApiKeyGenerateError[] = [];\n\n // Generate API keys\n logger.info(\n colors.magenta(\n `Generating API keys with title: ${apiKeyTitle}, scopes: ${scopes.join(\n ',',\n )}.`,\n ),\n );\n\n // Map over each role\n await mapSeries(filteredRoles, async (role) => {\n try {\n // Log into the other instance\n await assumeRole(client, { roleId: role.id, email });\n\n // Grab API keys with that title\n logger.info(\n colors.magenta(\n `Checking if API key already exists in organization \"${role.organization.name}\" with title: \"${apiKeyTitle}\".`,\n ),\n );\n\n // Delete existing API key\n const [apiKeyWithTitle] = await fetchAllApiKeys(client, [apiKeyTitle]);\n if (apiKeyWithTitle && deleteExistingApiKey) {\n logger.info(\n colors.yellow(\n `Deleting existing API key in \"${role.organization.name}\" with title: \"${apiKeyTitle}\".`,\n ),\n );\n await deleteApiKey(client, apiKeyWithTitle.id);\n logger.info(\n colors.green(\n `Successfully deleted API key in \"${role.organization.name}\" with title: \"${apiKeyTitle}\".`,\n ),\n );\n } else if (apiKeyWithTitle) {\n // throw error if one exists but not configured to delete\n throw new Error(`API key already exists with title: \"${apiKeyTitle}\"`);\n }\n\n // Create the API key\n if (createNewApiKey) {\n logger.info(\n colors.magenta(\n `Creating API key in \"${role.organization.name}\" with title: \"${apiKeyTitle}\".`,\n ),\n );\n const { apiKey } = await createApiKey(client, {\n title: apiKeyTitle,\n scopes,\n });\n results.push({\n organizationName: role.organization.name,\n organizationId: role.organization.id,\n apiKey,\n });\n logger.info(\n colors.green(\n `Successfully created API key in \"${role.organization.name}\" with title: \"${apiKeyTitle}\".`,\n ),\n );\n } else {\n // Delete only\n results.push({\n organizationName: role.organization.name,\n organizationId: role.organization.id,\n apiKey: '',\n });\n }\n } catch (err) {\n logger.error(\n colors.red(\n `Failed to create API key in organization \"${role.organization.name}\"! - ${err.message}`,\n ),\n );\n errors.push({\n organizationName: role.organization.name,\n organizationId: role.organization.id,\n error: err.message,\n });\n }\n });\n logger.info(\n colors.green(\n `Successfully created ${results.length} API key${\n results.length === 1 ? '' : 's'\n }`,\n ),\n );\n\n if (errors.length > 0) {\n logger.error(\n colors.red(\n `Failed to create ${errors.length} API key${\n errors.length === 1 ? '' : 's'\n }!`,\n ),\n );\n }\n\n return { errors, apiKeys: results };\n}\n","import { decodeCodec } from '@transcend-io/type-utils';\nimport colors from 'colors';\nimport * as t from 'io-ts';\nimport { logger } from '../../logger';\nimport { existsSync, readFileSync } from 'fs';\nimport { StoredApiKey } from '../../codecs';\n\n/**\n * Determine if the `--auth` parameter is an API key or a path to a JSON\n * file containing a list of API keys.\n *\n * @param auth - Raw auth parameter\n * @returns The API key or the list API keys\n */\nexport function validateTranscendAuth(auth: string): string | StoredApiKey[] {\n // Ensure auth is passed\n if (!auth) {\n logger.error(\n colors.red(\n 'A Transcend API key must be provided. You can specify using --auth=$TRANSCEND_API_KEY',\n ),\n );\n process.exit(1);\n }\n\n // Read from disk\n if (existsSync(auth)) {\n // validate that file is a list of API keys\n return decodeCodec(t.array(StoredApiKey), readFileSync(auth, 'utf-8'));\n }\n\n // Return as single API key\n return auth;\n}\n","import { existsSync, readdirSync } from 'fs';\n\n/**\n * List the files in a directory\n *\n * ```typescript\n * // The directory to search\n * const directory = '/User/test/transcend/my-app/app/containers';\n * // Returns ['test.js']\n * listFiles(directory);\n * ```\n *\n * @param directory - The directory to search\n * @param validExtensions - The list of valid extensions\n * @param removeExtensions - When true, remove the extensions from the listed files\n * @returns The list of files in the directory\n */\nexport function listFiles(\n directory: string,\n validExtensions?: string[],\n removeExtensions = false,\n): string[] {\n if (!existsSync(directory)) {\n return [];\n }\n\n const files = readdirSync(directory)\n .filter((fil) =>\n validExtensions\n ? validExtensions.filter((ext) => fil.endsWith(ext)).length\n : true,\n )\n .filter((fil) => fil.indexOf('.') > 0);\n\n return removeExtensions\n ? files.map((fil) => fil.replace(/\\.[^/.]+$/, ''))\n : files;\n}\n","import { readdirSync, statSync } from 'fs';\nimport { join } from 'path';\n\n/**\n * List the folders in a directory\n *\n * @param startDir - The base directory to list from\n * @returns The list of folders in that directory\n */\nexport function listDirectories(startDir: string): string[] {\n return readdirSync(startDir).filter((entryName) =>\n statSync(join(startDir, entryName)).isDirectory(),\n );\n}\n"],"mappings":"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","names":["colors","generateCrossAccountApiKeys","email","password","scopes","apiKeyTitle","parentOrganizationId","deleteExistingApiKey","createNewApiKey","transcendUrl","DEFAULT_TRANSCEND_API","client","buildTranscendGraphQLClientGeneric","logger","colors","roles","loginCookie","loginUser","filteredRoles","role","results","errors","mapSeries","assumeRole","apiKeyWithTitle","fetchAllApiKeys","deleteApiKey","apiKey","createApiKey","err","decodeCodec","colors","t","existsSync","readFileSync","validateTranscendAuth","auth","logger","colors","existsSync","decodeCodec","StoredApiKey","readFileSync","existsSync","readdirSync","listFiles","directory","validExtensions","removeExtensions","files","fil","ext","readdirSync","statSync","join","listDirectories","startDir","entryName"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/context.ts"],"sourcesContent":["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport type { StricliAutoCompleteContext } from '@stricli/auto-complete';\nimport type { CommandContext } from '@stricli/core';\n\nexport interface LocalContext\n extends CommandContext,\n StricliAutoCompleteContext {\n /** The Node.js process object */\n readonly process: NodeJS.Process;\n // ...\n}\n\n/**\n * Builds the context for the CLI.\n *\n * @param process - The Node.js process object.\n * @returns The context for the CLI.\n */\nexport function buildContext(process: NodeJS.Process): LocalContext {\n return {\n process,\n os,\n fs,\n path,\n };\n}\n"],"mappings":"AAAA,OAAOA,MAAQ,KACf,OAAOC,MAAQ,KACf,OAAOC,MAAU,OAkBV,SAASC,EAAaC,EAAuC,CAClE,MAAO,CACL,QAAAA,EACA,GAAAH,EACA,GAAAD,EACA,KAAAE,CACF,CACF","names":["fs","os","path","buildContext","process"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{makeEnum as e}from"@transcend-io/type-utils";var a=(s=>(s.Json="json",s))(a||{}),o=(s=>(s.Assessments="assessments",s))(o||{}),p=(i=>(i.OneTrust="oneTrust",i.File="file",i))(p||{}),m=(t=>(t.ApiKeys="apiKeys",t.Attributes="customFields",t.Templates="templates",t.DataSilos="dataSilos",t.Enrichers="enrichers",t.DataFlows="dataFlows",t.BusinessEntities="businessEntities",t.Actions="actions",t.DataSubjects="dataSubjects",t.Identifiers="identifiers",t.Cookies="cookies",t.ConsentManager="consentManager",t.Partitions="partitions",t.Prompts="prompts",t.PromptPartials="promptPartials",t.PromptGroups="promptGroups",t.Agents="agents",t.AgentFunctions="agentFunctions",t.AgentFiles="agentFiles",t.Vendors="vendors",t.DataCategories="dataCategories",t.ProcessingPurposes="processingPurposes",t.ActionItems="actionItems",t.ActionItemCollections="actionItemCollections",t.Teams="teams",t.PrivacyCenters="privacyCenters",t.Policies="policies",t.Messages="messages",t.Assessments="assessments",t.AssessmentTemplates="assessmentTemplates",t.Purposes="purposes",t))(m||{}),n=e({RedactEmail:"redactEmail",Log:"log",LogToTranscend:"logToTranscend",ApplyTranscendPolicies:"applyTranscendPolicies"}),h=e({ChatCompletion:"/v1/chat/completions",Embeddings:"/v1/embeddings",Completions:"/v1/completions",Agents:"/v1/assistants",Agent:"/v1/assistants/:assistantId",Threads:"/v1/threads",Thread:"/v1/threads/:threadId",Messages:"/v1/threads/:threadId/messages",Message:"/v1/threads/:threadId/messages/:messageId",Runs:"/v1/threads/:threadId/runs",Run:"/v1/threads/:threadId/runs/:runId",Files:"/v1/files",File:"/v1/files/:fileId"});export{a,o as b,p as c,m as d,n as e,h as f};
|
|
2
|
+
//# sourceMappingURL=chunk-ARVEJERC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/enums.ts"],"sourcesContent":["import { makeEnum } from '@transcend-io/type-utils';\n\n/** Accepted file formats for exporting resources from OneTrust */\nexport enum OneTrustFileFormat {\n Json = 'json',\n}\n\n/**\n * Resources that can be pulled in from OneTrust\n */\nexport enum OneTrustPullResource {\n Assessments = 'assessments',\n}\n\n/**\n * Where to read OneTrust resources from\n */\nexport enum OneTrustPullSource {\n OneTrust = 'oneTrust',\n File = 'file',\n}\n\n/**\n * Resources that can be pulled in\n */\nexport enum TranscendPullResource {\n ApiKeys = 'apiKeys',\n Attributes = 'customFields',\n Templates = 'templates',\n DataSilos = 'dataSilos',\n Enrichers = 'enrichers',\n DataFlows = 'dataFlows',\n BusinessEntities = 'businessEntities',\n Actions = 'actions',\n DataSubjects = 'dataSubjects',\n Identifiers = 'identifiers',\n Cookies = 'cookies',\n ConsentManager = 'consentManager',\n Partitions = 'partitions',\n Prompts = 'prompts',\n PromptPartials = 'promptPartials',\n PromptGroups = 'promptGroups',\n Agents = 'agents',\n AgentFunctions = 'agentFunctions',\n AgentFiles = 'agentFiles',\n Vendors = 'vendors',\n DataCategories = 'dataCategories',\n ProcessingPurposes = 'processingPurposes',\n ActionItems = 'actionItems',\n ActionItemCollections = 'actionItemCollections',\n Teams = 'teams',\n PrivacyCenters = 'privacyCenters',\n Policies = 'policies',\n Messages = 'messages',\n Assessments = 'assessments',\n AssessmentTemplates = 'assessmentTemplates',\n Purposes = 'purposes',\n}\n\n/**\n * Names of built in policies for pathfinder\n */\nexport const PathfinderPolicyName = makeEnum({\n RedactEmail: 'redactEmail',\n Log: 'log',\n LogToTranscend: 'logToTranscend',\n ApplyTranscendPolicies: 'applyTranscendPolicies',\n});\n\n/**\n * Type override\n */\nexport type PathfinderPolicyName =\n (typeof PathfinderPolicyName)[keyof typeof PathfinderPolicyName];\n\n/**\n * The names of the OpenAI routes that we support setting policies for\n * reference: https://platform.openai.com/docs/api-reference/introduction\n */\nexport const OpenAIRouteName = makeEnum({\n ChatCompletion: '/v1/chat/completions',\n Embeddings: '/v1/embeddings',\n Completions: '/v1/completions',\n Agents: '/v1/assistants',\n Agent: '/v1/assistants/:assistantId',\n Threads: '/v1/threads',\n Thread: '/v1/threads/:threadId',\n Messages: '/v1/threads/:threadId/messages',\n Message: '/v1/threads/:threadId/messages/:messageId',\n Runs: '/v1/threads/:threadId/runs',\n Run: '/v1/threads/:threadId/runs/:runId',\n Files: '/v1/files',\n File: '/v1/files/:fileId',\n});\n\n/**\n * Type override\n */\nexport type OpenAIRouteName =\n (typeof OpenAIRouteName)[keyof typeof OpenAIRouteName];\n"],"mappings":"AAAA,OAAS,YAAAA,MAAgB,2BAGlB,IAAKC,OACVA,EAAA,KAAO,OADGA,OAAA,IAOAC,OACVA,EAAA,YAAc,cADJA,OAAA,IAOAC,OACVA,EAAA,SAAW,WACXA,EAAA,KAAO,OAFGA,OAAA,IAQAC,OACVA,EAAA,QAAU,UACVA,EAAA,WAAa,eACbA,EAAA,UAAY,YACZA,EAAA,UAAY,YACZA,EAAA,UAAY,YACZA,EAAA,UAAY,YACZA,EAAA,iBAAmB,mBACnBA,EAAA,QAAU,UACVA,EAAA,aAAe,eACfA,EAAA,YAAc,cACdA,EAAA,QAAU,UACVA,EAAA,eAAiB,iBACjBA,EAAA,WAAa,aACbA,EAAA,QAAU,UACVA,EAAA,eAAiB,iBACjBA,EAAA,aAAe,eACfA,EAAA,OAAS,SACTA,EAAA,eAAiB,iBACjBA,EAAA,WAAa,aACbA,EAAA,QAAU,UACVA,EAAA,eAAiB,iBACjBA,EAAA,mBAAqB,qBACrBA,EAAA,YAAc,cACdA,EAAA,sBAAwB,wBACxBA,EAAA,MAAQ,QACRA,EAAA,eAAiB,iBACjBA,EAAA,SAAW,WACXA,EAAA,SAAW,WACXA,EAAA,YAAc,cACdA,EAAA,oBAAsB,sBACtBA,EAAA,SAAW,WA/BDA,OAAA,IAqCCC,EAAuBL,EAAS,CAC3C,YAAa,cACb,IAAK,MACL,eAAgB,iBAChB,uBAAwB,wBAC1B,CAAC,EAYYM,EAAkBN,EAAS,CACtC,eAAgB,uBAChB,WAAY,iBACZ,YAAa,kBACb,OAAQ,iBACR,MAAO,8BACP,QAAS,cACT,OAAQ,wBACR,SAAU,iCACV,QAAS,4CACT,KAAM,6BACN,IAAK,oCACL,MAAO,YACP,KAAM,mBACR,CAAC","names":["makeEnum","OneTrustFileFormat","OneTrustPullResource","OneTrustPullSource","TranscendPullResource","PathfinderPolicyName","OpenAIRouteName"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{union as c}from"lodash-es";function f(l,{adTechPurposes:p=["SaleOfInfo"],serviceToTitle:s,serviceToSupportedIntegration:r}){let e=[],i=[],n={};l.forEach(t=>{let{service:a,attributes:h=[]}=t;if(!a||a==="internalService")return;let u=h.find(o=>o.key==="Found on Domain");u&&(n[a]||(n[a]=[]),n[a].push(...u.values.map(o=>o.replace("https://","").replace("http://",""))),n[a]=[...new Set(n[a])]),c(t.trackingPurposes,p).length>0?(i.push(a),e.includes(a)&&(e=e.filter(o=>o!==a))):i.includes(a)||e.push(a)});let m=[...new Set(i)].map(t=>({title:s[t],...r[t]?{integrationName:t}:{integrationName:"promptAPerson","outer-type":t},attributes:[{key:"Tech Type",values:["Ad Tech"]},{key:"Found On Domain",values:n[t]||[]}]}));return{siteTechDataSilos:[...new Set(e)].map(t=>({title:s[t],...r[t]?{integrationName:t}:{integrationName:"promptAPerson",outerType:t},attributes:[{key:"Tech Type",values:["Site Tech"]},{key:"Found On Domain",values:n[t]||[]}]})),adTechDataSilos:m}}export{f as a};
|
|
2
|
+
//# sourceMappingURL=chunk-CBAHSBSW.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["
|
|
1
|
+
{"version":3,"sources":["../src/lib/consent-manager/dataFlowsToDataSilos.ts"],"sourcesContent":["import { DataFlowInput, DataSiloInput } from '../../codecs';\nimport { union } from 'lodash-es';\nimport { IndexedCatalogs } from '../graphql';\n\n/**\n * Convert data flow configurations into a set of data silo configurations\n *\n * @param inputs - Data flow input to convert to data silos\n * @param options - Additional options\n * @returns Business entity configuration input\n */\nexport function dataFlowsToDataSilos(\n inputs: DataFlowInput[],\n {\n adTechPurposes = ['SaleOfInfo'],\n serviceToTitle,\n serviceToSupportedIntegration,\n }: IndexedCatalogs & {\n /** List of purposes that are considered \"Ad Tech\" */\n adTechPurposes?: string[];\n },\n): {\n /** List of data silo configurations for site-tech services */\n siteTechDataSilos: DataSiloInput[];\n /** List of data silo configurations for ad-tech services */\n adTechDataSilos: DataSiloInput[];\n} {\n // List of site tech integrations\n let siteTechIntegrations: string[] = [];\n\n // List of ad tech integrations\n const adTechIntegrations: string[] = [];\n\n // Mapping from service name to list of\n const serviceToFoundOnDomain: { [k in string]: string[] } = {};\n\n // iterate over each flow\n inputs.forEach((flow) => {\n // process data flows with services\n const { service, attributes = [] } = flow;\n if (!service || service === 'internalService') {\n return;\n }\n\n // create mapping to found on domain\n const foundOnDomain = attributes.find(\n (attr) => attr.key === 'Found on Domain',\n );\n\n // Create a list of all domains where the data flow was found\n if (foundOnDomain) {\n if (!serviceToFoundOnDomain[service]) {\n serviceToFoundOnDomain[service] = [];\n }\n serviceToFoundOnDomain[service]!.push(\n ...foundOnDomain.values.map((v) =>\n v.replace('https://', '').replace('http://', ''),\n ),\n );\n serviceToFoundOnDomain[service] = [\n ...new Set(serviceToFoundOnDomain[service]),\n ];\n }\n\n // Keep track of ad tech\n if (union(flow.trackingPurposes, adTechPurposes).length > 0) {\n // add service to ad tech list\n adTechIntegrations.push(service);\n\n // remove from site tech list\n if (siteTechIntegrations.includes(service)) {\n siteTechIntegrations = siteTechIntegrations.filter(\n (s) => s !== service,\n );\n }\n } else if (!adTechIntegrations.includes(service)) {\n // add to site tech list\n siteTechIntegrations.push(service);\n }\n });\n\n // create the list of ad tech integrations\n const adTechDataSilos = [...new Set(adTechIntegrations)].map((service) => ({\n title: serviceToTitle[service],\n ...(serviceToSupportedIntegration[service]\n ? { integrationName: service }\n : { integrationName: 'promptAPerson', 'outer-type': service }),\n attributes: [\n {\n key: 'Tech Type',\n values: ['Ad Tech'],\n },\n {\n key: 'Found On Domain',\n values: serviceToFoundOnDomain[service] || [],\n },\n ],\n }));\n\n // create the list of site tech integrations\n const siteTechDataSilos = [...new Set(siteTechIntegrations)].map(\n (service) => ({\n title: serviceToTitle[service],\n ...(serviceToSupportedIntegration[service]\n ? { integrationName: service }\n : { integrationName: 'promptAPerson', outerType: service }),\n attributes: [\n {\n key: 'Tech Type',\n values: ['Site Tech'],\n },\n {\n key: 'Found On Domain',\n values: serviceToFoundOnDomain[service] || [],\n },\n ],\n }),\n );\n\n return {\n siteTechDataSilos,\n adTechDataSilos,\n };\n}\n"],"mappings":"AACA,OAAS,SAAAA,MAAa,YAUf,SAASC,EACdC,EACA,CACE,eAAAC,EAAiB,CAAC,YAAY,EAC9B,eAAAC,EACA,8BAAAC,CACF,EASA,CAEA,IAAIC,EAAiC,CAAC,EAGhCC,EAA+B,CAAC,EAGhCC,EAAsD,CAAC,EAG7DN,EAAO,QAASO,GAAS,CAEvB,GAAM,CAAE,QAAAC,EAAS,WAAAC,EAAa,CAAC,CAAE,EAAIF,EACrC,GAAI,CAACC,GAAWA,IAAY,kBAC1B,OAIF,IAAME,EAAgBD,EAAW,KAC9BE,GAASA,EAAK,MAAQ,iBACzB,EAGID,IACGJ,EAAuBE,CAAO,IACjCF,EAAuBE,CAAO,EAAI,CAAC,GAErCF,EAAuBE,CAAO,EAAG,KAC/B,GAAGE,EAAc,OAAO,IAAKE,GAC3BA,EAAE,QAAQ,WAAY,EAAE,EAAE,QAAQ,UAAW,EAAE,CACjD,CACF,EACAN,EAAuBE,CAAO,EAAI,CAChC,GAAG,IAAI,IAAIF,EAAuBE,CAAO,CAAC,CAC5C,GAIEV,EAAMS,EAAK,iBAAkBN,CAAc,EAAE,OAAS,GAExDI,EAAmB,KAAKG,CAAO,EAG3BJ,EAAqB,SAASI,CAAO,IACvCJ,EAAuBA,EAAqB,OACzCS,GAAMA,IAAML,CACf,IAEQH,EAAmB,SAASG,CAAO,GAE7CJ,EAAqB,KAAKI,CAAO,CAErC,CAAC,EAGD,IAAMM,EAAkB,CAAC,GAAG,IAAI,IAAIT,CAAkB,CAAC,EAAE,IAAKG,IAAa,CACzE,MAAON,EAAeM,CAAO,EAC7B,GAAIL,EAA8BK,CAAO,EACrC,CAAE,gBAAiBA,CAAQ,EAC3B,CAAE,gBAAiB,gBAAiB,aAAcA,CAAQ,EAC9D,WAAY,CACV,CACE,IAAK,YACL,OAAQ,CAAC,SAAS,CACpB,EACA,CACE,IAAK,kBACL,OAAQF,EAAuBE,CAAO,GAAK,CAAC,CAC9C,CACF,CACF,EAAE,EAsBF,MAAO,CACL,kBApBwB,CAAC,GAAG,IAAI,IAAIJ,CAAoB,CAAC,EAAE,IAC1DI,IAAa,CACZ,MAAON,EAAeM,CAAO,EAC7B,GAAIL,EAA8BK,CAAO,EACrC,CAAE,gBAAiBA,CAAQ,EAC3B,CAAE,gBAAiB,gBAAiB,UAAWA,CAAQ,EAC3D,WAAY,CACV,CACE,IAAK,YACL,OAAQ,CAAC,WAAW,CACtB,EACA,CACE,IAAK,kBACL,OAAQF,EAAuBE,CAAO,GAAK,CAAC,CAC9C,CACF,CACF,EACF,EAIE,gBAAAM,CACF,CACF","names":["union","dataFlowsToDataSilos","inputs","adTechPurposes","serviceToTitle","serviceToSupportedIntegration","siteTechIntegrations","adTechIntegrations","serviceToFoundOnDomain","flow","service","attributes","foundOnDomain","attr","v","s","adTechDataSilos"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../package.json"],"sourcesContent":["{\n \"author\": \"Transcend Inc.\",\n \"name\": \"@transcend-io/cli\",\n \"description\": \"A command line interface for programmatic operations across Transcend.\",\n \"version\": \"8.0.0-alpha.1\",\n \"homepage\": \"https://github.com/transcend-io/cli\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/transcend-io/cli.git\"\n },\n \"type\": \"module\",\n \"license\": \"UNLICENSED\",\n \"main\": \"dist/index.js\",\n \"bin\": {\n \"transcend\": \"dist/bin/cli.js\",\n \"__transcend_bash_complete\": \"dist/bin/bash-complete.js\",\n \"__tr-build-xdi-sync-endpoint\": \"dist/bin/deprecated-command.js\",\n \"__tr-consent-manager-service-json-to-yml\": \"dist/bin/deprecated-command.js\",\n \"__tr-consent-managers-to-business-entities\": \"dist/bin/deprecated-command.js\",\n \"__tr-cron-mark-identifiers-completed\": \"dist/bin/deprecated-command.js\",\n \"__tr-cron-pull-identifiers\": \"dist/bin/deprecated-command.js\",\n \"__tr-cron-pull-profiles\": \"dist/bin/deprecated-command.js\",\n \"__tr-derive-data-silos-from-data-flows\": \"dist/bin/deprecated-command.js\",\n \"__tr-derive-data-silos-from-data-flows-cross-instance\": \"dist/bin/deprecated-command.js\",\n \"__tr-discover-silos\": \"dist/bin/deprecated-command.js\",\n \"__tr-generate-api-keys\": \"dist/bin/deprecated-command.js\",\n \"__tr-manual-enrichment-pull-identifiers\": \"dist/bin/deprecated-command.js\",\n \"__tr-manual-enrichment-push-identifiers\": \"dist/bin/deprecated-command.js\",\n \"__tr-mark-request-data-silos-completed\": \"dist/bin/deprecated-command.js\",\n \"__tr-pull\": \"dist/bin/deprecated-command.js\",\n \"__tr-pull-consent-metrics\": \"dist/bin/deprecated-command.js\",\n \"__tr-pull-consent-preferences\": \"dist/bin/deprecated-command.js\",\n \"__tr-pull-datapoints\": \"dist/bin/deprecated-command.js\",\n \"__tr-pull-unstructured-discovery-files\": \"dist/bin/deprecated-command.js\",\n \"__tr-push\": \"dist/bin/deprecated-command.js\",\n \"__tr-request-approve\": \"dist/bin/deprecated-command.js\",\n \"__tr-request-cancel\": \"dist/bin/deprecated-command.js\",\n \"__tr-request-download-files\": \"dist/bin/deprecated-command.js\",\n \"__tr-request-enricher-restart\": \"dist/bin/deprecated-command.js\",\n \"__tr-request-export\": \"dist/bin/deprecated-command.js\",\n \"__tr-request-mark-silent\": \"dist/bin/deprecated-command.js\",\n \"__tr-request-notify-additional-time\": \"dist/bin/deprecated-command.js\",\n \"__tr-request-reject-unverified-identifiers\": \"dist/bin/deprecated-command.js\",\n \"__tr-request-restart\": \"dist/bin/deprecated-command.js\",\n \"__tr-request-upload\": \"dist/bin/deprecated-command.js\",\n \"__tr-retry-request-data-silos\": \"dist/bin/deprecated-command.js\",\n \"__tr-scan-packages\": \"dist/bin/deprecated-command.js\",\n \"__tr-skip-request-data-silos\": \"dist/bin/deprecated-command.js\",\n \"__tr-sync-ot\": \"dist/bin/deprecated-command.js\",\n \"__tr-update-consent-manager\": \"dist/bin/deprecated-command.js\",\n \"__tr-upload-consent-preferences\": \"dist/bin/deprecated-command.js\",\n \"__tr-upload-cookies-from-csv\": \"dist/bin/deprecated-command.js\",\n \"__tr-upload-data-flows-from-csv\": \"dist/bin/deprecated-command.js\",\n \"__tr-upload-preferences\": \"dist/bin/deprecated-command.js\"\n },\n \"engines\": {\n \"node\": \">=18\"\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"start\": \"./dist/bin/cli.js\",\n \"prebuild\": \"tsc -p tsconfig.json\",\n \"build\": \"tsup\",\n \"build:watch\": \"tsup --watch\",\n \"prepublishOnly\": \"pnpm lint && pnpm build && pnpm test && pnpm publint\",\n \"lint\": \"pnpm run /^lint:/\",\n \"lint:prettier\": \"prettier --check . --loglevel=warn\",\n \"lint:types\": \"tsc --noEmit\",\n \"lint:eslint\": \"eslint .\",\n \"format\": \"prettier --write . --loglevel=warn\",\n \"test\": \"vitest run\",\n \"script:transcend-json-schema\": \"tsx scripts/buildTranscendJsonSchema.ts && prettier ./transcend-yml-schema-*.json --write\",\n \"script:pathfinder-json-schema\": \"tsx scripts/buildPathfinderJsonSchema.ts && prettier ./pathfinder-policy-yml-schema.json --write\",\n \"docgen\": \"tsx scripts/buildReadmeDocs.ts\"\n },\n \"tsup\": {\n \"entry\": [\n \"src/bin/cli.ts\",\n \"src/bin/bash-complete.ts\",\n \"src/bin/deprecated-command.ts\",\n \"src/index.ts\"\n ],\n \"format\": [\n \"esm\"\n ],\n \"sourcemap\": true,\n \"dts\": true,\n \"tsconfig\": \"tsconfig.json\",\n \"clean\": true,\n \"splitting\": true,\n \"minify\": true\n },\n \"dependencies\": {\n \"@stricli/auto-complete\": \"^1.2.0\",\n \"@stricli/core\": \"^1.2.0\",\n \"@transcend-io/airgap.js-types\": \"^12.12.1\",\n \"@transcend-io/handlebars-utils\": \"^1.1.0\",\n \"@transcend-io/internationalization\": \"^1.6.0\",\n \"@transcend-io/persisted-state\": \"^1.0.4\",\n \"@transcend-io/privacy-types\": \"^4.124.1\",\n \"@transcend-io/secret-value\": \"^1.2.0\",\n \"@transcend-io/type-utils\": \"^1.8.0\",\n \"JSONStream\": \"^1.3.5\",\n \"cli-progress\": \"^3.11.2\",\n \"colors\": \"^1.4.0\",\n \"csv-parse\": \"^5.6.0\",\n \"fast-csv\": \"^4.3.6\",\n \"fast-glob\": \"^3.2.12\",\n \"fp-ts\": \"^2.16.1\",\n \"fuzzysearch\": \"^1.0.3\",\n \"global-agent\": \"^3.0.0\",\n \"got\": \"^11.8.5\",\n \"graphql-request\": \"^5.0.0\",\n \"inquirer\": \"=7.3.3\",\n \"inquirer-autocomplete-prompt\": \"=1.3.0\",\n \"io-ts\": \"^2.2.21\",\n \"io-ts-types\": \"^0.5.16\",\n \"js-yaml\": \"^4.1.0\",\n \"jsonwebtoken\": \"^9.0.2\",\n \"lodash-es\": \"^4.17.21\",\n \"monocle-ts\": \"^2.3.13\",\n \"newtype-ts\": \"^0.3.5\",\n \"query-string\": \"=7.0.0\",\n \"semver\": \"^7.6.0\",\n \"undici\": \"^5.22.1\",\n \"yargs-parser\": \"^21.1.1\"\n },\n \"devDependencies\": {\n \"@types/JSONStream\": \"npm:@types/jsonstream@^0.8.33\",\n \"@types/cli-progress\": \"^3.11.0\",\n \"@types/colors\": \"^1.2.1\",\n \"@types/fuzzysearch\": \"^1.0.0\",\n \"@types/global-agent\": \"^2.1.1\",\n \"@types/inquirer\": \"^7.3.1\",\n \"@types/inquirer-autocomplete-prompt\": \"^3.0.0\",\n \"@types/js-yaml\": \"^4.0.5\",\n \"@types/json-schema\": \"^7.0.15\",\n \"@types/jsonwebtoken\": \"^9\",\n \"@types/lodash-es\": \"^4.17.12\",\n \"@types/node\": \"^18.15.11\",\n \"@types/semver\": \"^7\",\n \"@types/yargs-parser\": \"^21.0.0\",\n \"@typescript-eslint/eslint-plugin\": \"^5.58.0\",\n \"@typescript-eslint/parser\": \"^5.58.0\",\n \"depcheck\": \"^1.4.3\",\n \"doctoc\": \"^2.2.1\",\n \"eslint\": \"^8.38.0\",\n \"eslint-config-airbnb-base\": \"^15.0.0\",\n \"eslint-import-resolver-typescript\": \"^3.5.5\",\n \"eslint-plugin-eslint-comments\": \"^3.2.0\",\n \"eslint-plugin-import\": \"2.27.5\",\n \"eslint-plugin-jsdoc\": \"^41.1.1\",\n \"fdir\": \"^6.4.6\",\n \"prettier\": \"^2.8.7\",\n \"publint\": \"^0.3.12\",\n \"tsup\": \"^8.5.0\",\n \"tsx\": \"^4.20.3\",\n \"typescript\": \"^5.0.4\",\n \"vite-tsconfig-paths\": \"^5.1.4\",\n \"vitest\": \"^3.2.4\"\n },\n \"packageManager\": \"pnpm@10.12.4+sha512.5ea8b0deed94ed68691c9bad4c955492705c5eeb8a87ef86bc62c74a26b037b08ff9570f108b2e4dbd1dd1a9186fea925e527f141c648e85af45631074680184\"\n}\n"],"mappings":"AAGE,IAAAA,EAAe,yEACfC,EAAW","names":["description","version"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{k as i}from"./chunk-N6JZHL5U.js";import o from"inquirer";import m from"inquirer-autocomplete-prompt";async function c({message:e}){let{response:r}=await o.prompt([{name:"response",message:e,type:"confirm"}]);return r}async function l({message:e}){let{response:r}=await o.prompt([{name:"response",message:e,type:"text",validate:t=>t.trim().length>0}]);return r}async function y({defaultValue:e,values:r,message:t}){o.registerPrompt("autocomplete",m);let{response:p}=await o.prompt([{name:"response",message:t,type:"autocomplete",default:e,source:(a,n)=>n?r.filter(s=>typeof s=="string"&&i(n,s)):r}]);return p}export{c as a,l as b,y as c};
|
|
2
|
+
//# sourceMappingURL=chunk-FHZRITAV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/helpers/inquirer.ts"],"sourcesContent":["import inquirer from 'inquirer';\nimport autoCompletePrompt from 'inquirer-autocomplete-prompt';\nimport { fuzzySearch } from '../requests';\nimport { ObjByString } from '@transcend-io/type-utils';\n\n/**\n * Inquirer confirm text\n *\n * @param options - Options\n * @returns The response\n */\nexport async function inquirerConfirmBoolean({\n message,\n}: {\n /** Message */\n message: string;\n}): Promise<boolean> {\n const { response } = await inquirer.prompt<{\n /** confirmation */\n response: boolean;\n }>([\n {\n name: 'response',\n message,\n type: 'confirm',\n },\n ]);\n return response;\n}\n\n/**\n * Inquirer confirm text\n *\n * @param options - Options\n * @returns The response\n */\nexport async function inquirerConfirmText({\n message,\n}: {\n /** Message */\n message: string;\n}): Promise<string> {\n const { response } = await inquirer.prompt<{\n /** confirmation */\n response: string;\n }>([\n {\n name: 'response',\n message,\n type: 'text',\n validate: (x) => x.trim().length > 0,\n },\n ]);\n return response;\n}\n\n/**\n * Inquirer auto complete\n *\n * @param options - Options\n * @returns The response\n */\nexport async function inquirerAutoComplete({\n defaultValue,\n values,\n message,\n}: {\n /** Default value */\n defaultValue?: string;\n /** Message */\n message: string;\n /** Values to select */\n values: string[];\n}): Promise<string> {\n inquirer.registerPrompt('autocomplete', autoCompletePrompt);\n const { response } = await inquirer.prompt<{\n /** confirmation */\n response: string;\n }>([\n {\n name: 'response',\n message,\n type: 'autocomplete',\n default: defaultValue,\n source: (answersSoFar: ObjByString, input: string) =>\n !input\n ? values\n : values.filter(\n (x) => typeof x === 'string' && fuzzySearch(input, x),\n ),\n },\n ]);\n return response;\n}\n"],"mappings":"wCAAA,OAAOA,MAAc,WACrB,OAAOC,MAAwB,+BAU/B,eAAsBC,EAAuB,CAC3C,QAAAC,CACF,EAGqB,CACnB,GAAM,CAAE,SAAAC,CAAS,EAAI,MAAMC,EAAS,OAGjC,CACD,CACE,KAAM,WACN,QAAAF,EACA,KAAM,SACR,CACF,CAAC,EACD,OAAOC,CACT,CAQA,eAAsBE,EAAoB,CACxC,QAAAH,CACF,EAGoB,CAClB,GAAM,CAAE,SAAAC,CAAS,EAAI,MAAMC,EAAS,OAGjC,CACD,CACE,KAAM,WACN,QAAAF,EACA,KAAM,OACN,SAAWI,GAAMA,EAAE,KAAK,EAAE,OAAS,CACrC,CACF,CAAC,EACD,OAAOH,CACT,CAQA,eAAsBI,EAAqB,CACzC,aAAAC,EACA,OAAAC,EACA,QAAAP,CACF,EAOoB,CAClBE,EAAS,eAAe,eAAgBM,CAAkB,EAC1D,GAAM,CAAE,SAAAP,CAAS,EAAI,MAAMC,EAAS,OAGjC,CACD,CACE,KAAM,WACN,QAAAF,EACA,KAAM,eACN,QAASM,EACT,OAAQ,CAACG,EAA2BC,IACjCA,EAEGH,EAAO,OACJH,GAAM,OAAOA,GAAM,UAAYO,EAAYD,EAAON,CAAC,CACtD,EAHAG,CAIR,CACF,CAAC,EACD,OAAON,CACT","names":["inquirer","autoCompletePrompt","inquirerConfirmBoolean","message","response","inquirer","inquirerConfirmText","x","inquirerAutoComplete","defaultValue","values","autoCompletePrompt","answersSoFar","input","fuzzySearch"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{c as _}from"./chunk-MA4JWWRO.js";import{n as A,q as x}from"./chunk-N6JZHL5U.js";import{Ae as O,Be as D,_ as T,_b as j,b as R,pe as y,qe as E,ye as L}from"./chunk-MK5T6DBK.js";import{a as r}from"./chunk-43JWXG77.js";import{e as b}from"./chunk-L5ULN3IT.js";import{RequestStatus as U}from"@transcend-io/privacy-types";import k from"colors";import{groupBy as G,uniq as Q}from"lodash-es";async function te({file:u,auth:s,sombraAuth:g,requestActions:f=[],concurrency:p=100,transcendUrl:n=b}){let o=y(n,s),e=await E(n,s,g);r.info(k.magenta(`Pulling manual enrichment requests, filtered for actions: ${f.join(",")}`));let d=await L(o,{actions:f,statuses:[U.Enriching]}),i=[];await R(d,async t=>{let c=await D(o,{requestId:t.id});if(c.filter(({status:m})=>m==="ACTION_REQUIRED")){let m=await O(o,e,{requestId:t.id});i.push({...t,requestIdentifiers:m,requestEnrichers:c})}},{concurrency:p});let l=i.map(({attributeValues:t,requestIdentifiers:c,requestEnrichers:I,...m})=>({...m,...Object.entries(G(c,"name")).reduce((w,[P,$])=>Object.assign(w,{[P]:$.map(({value:C})=>C).join(",")}),{}),...Object.entries(G(t,"attributeKey.name")).reduce((w,[P,$])=>Object.assign(w,{[P]:$.map(({name:C})=>C).join(",")}),{})})),a=Q(l.map(t=>Object.keys(t)).flat());return _(u,l,a),r.info(k.green(`Successfully wrote ${i.length} requests to file "${u}"`)),i}import*as q from"io-ts";import{uniq as F}from"lodash-es";import v from"colors";var S="https://app.transcend.io/privacy-requests/incoming-requests/",M=q.record(q.string,q.string);async function N(u,{id:s,...g},f,p){if(!s){let e=`Request ID must be provided to enricher request.${p?` Found error in row: ${p}`:""}`;throw r.error(v.red(e)),new Error(e)}let n=s.toLowerCase(),o=Object.entries(g).reduce((e,[d,i])=>F(A(i)).length===0?e:Object.assign(e,{[d]:F(A(i)).map(a=>({value:d==="email"?a.toLowerCase():a}))}),{});try{return await u.post("v1/enrich-identifiers",{headers:{"x-transcend-request-id":n,"x-transcend-enricher-id":f},json:{enrichedIdentifiers:o}}).json(),r.error(v.green(`Successfully enriched request: ${S}${n}`)),!0}catch(e){if(typeof e.response.body=="string"&&e.response.body.includes("Cannot update a resolved RequestEnricher"))return r.warn(v.magenta(`Skipped enrichment for request: ${S}${n}, request is no longer in the enriching phase.`)),!1;throw r.error(v.red(`Failed to enricher identifiers for request with id: ${S}${n} - ${e.message} - ${e.response.body}`)),e}}import h from"colors";async function ge({file:u,auth:s,sombraAuth:g,enricherId:f,markSilent:p,concurrency:n=100,transcendUrl:o=b}){let e=await E(o,s,g),d=y(o,s);r.info(h.magenta(`Reading "${u}" from disk`));let i=x(u,M);r.info(h.magenta(`Enriching "${i.length}" privacy requests.`));let l=0,a=0,t=0;if(await R(i,async(c,I)=>{try{p&&(await j(d,T,{input:{id:c.id,isSilent:!0}}),r.info(h.magenta(`Mark request as silent mode - ${c.id}`))),await N(e,c,f,I)?l+=1:a+=1}catch{t+=1}},{concurrency:n}),r.info(h.green(`Successfully notified Transcend!
|
|
2
|
+
Success count: ${l}.`)),a>0&&r.info(h.magenta(`Skipped count: ${a}.`)),t>0)throw r.info(h.red(`Error Count: ${t}.`)),new Error(`Failed to enrich: ${t} requests.`);return i.length}export{te as a,M as b,N as c,ge as d};
|
|
3
|
+
//# sourceMappingURL=chunk-HJULYIHF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/manual-enrichment/pullManualEnrichmentIdentifiersToCsv.ts","../src/lib/manual-enrichment/enrichPrivacyRequest.ts","../src/lib/manual-enrichment/pushManualEnrichmentIdentifiersFromCsv.ts"],"sourcesContent":["import { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport { map } from '../bluebird-replace';\nimport colors from 'colors';\nimport { groupBy, uniq } from 'lodash-es';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\nimport { writeCsv } from '../cron/writeCsv';\nimport {\n PrivacyRequest,\n RequestEnricher,\n RequestIdentifier,\n buildTranscendGraphQLClient,\n createSombraGotInstance,\n fetchAllRequestEnrichers,\n fetchAllRequestIdentifiers,\n fetchAllRequests,\n} from '../graphql';\nimport { logger } from '../../logger';\n\nexport interface PrivacyRequestWithIdentifiers extends PrivacyRequest {\n /** Request Enrichers */\n requestEnrichers: RequestEnricher[];\n /** Request Identifiers */\n requestIdentifiers: RequestIdentifier[];\n}\n\n/**\n * Pull the set of manual enrichment jobs to CSV\n *\n * @param options - Options\n * @returns List of requests with identifiers\n */\nexport async function pullManualEnrichmentIdentifiersToCsv({\n file,\n auth,\n sombraAuth,\n requestActions = [],\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** CSV file path */\n file: string;\n /** Transcend API key authentication */\n auth: string;\n /** Sombra API key */\n sombraAuth?: string;\n /** Concurrency */\n concurrency?: number;\n /** The request actions to fetch */\n requestActions?: RequestAction[];\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<PrivacyRequestWithIdentifiers[]> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n const sombra = await createSombraGotInstance(transcendUrl, auth, sombraAuth);\n\n logger.info(\n colors.magenta(\n `Pulling manual enrichment requests, filtered for actions: ${requestActions.join(\n ',',\n )}`,\n ),\n );\n\n // Pull all privacy requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses: [RequestStatus.Enriching],\n });\n\n // Requests to save\n const savedRequests: PrivacyRequestWithIdentifiers[] = [];\n\n // Filter down requests to what is needed\n await map(\n allRequests,\n async (request) => {\n // Fetch enrichers\n const requestEnrichers = await fetchAllRequestEnrichers(client, {\n requestId: request.id,\n });\n\n // Check if manual enrichment exists for that request\n const hasManualEnrichment = requestEnrichers.filter(\n ({ status }) => status === 'ACTION_REQUIRED',\n );\n\n // Save request to queue\n if (hasManualEnrichment) {\n const requestIdentifiers = await fetchAllRequestIdentifiers(\n client,\n sombra,\n {\n requestId: request.id,\n },\n );\n savedRequests.push({\n ...request,\n requestIdentifiers,\n requestEnrichers,\n });\n }\n },\n {\n concurrency,\n },\n );\n\n const data = savedRequests.map(\n ({\n attributeValues,\n requestIdentifiers,\n requestEnrichers, // eslint-disable-line @typescript-eslint/no-unused-vars\n ...request\n }) => ({\n ...request,\n // flatten identifiers\n ...Object.entries(groupBy(requestIdentifiers, 'name')).reduce(\n (acc, [key, values]) =>\n Object.assign(acc, {\n [key]: values.map(({ value }) => value).join(','),\n }),\n {},\n ),\n // flatten attributes\n ...Object.entries(groupBy(attributeValues, 'attributeKey.name')).reduce(\n (acc, [key, values]) =>\n Object.assign(acc, {\n [key]: values.map(({ name }) => name).join(','),\n }),\n {},\n ),\n }),\n );\n\n // Write out to CSV\n const headers = uniq(data.map((d) => Object.keys(d)).flat());\n writeCsv(file, data, headers);\n\n logger.info(\n colors.green(\n `Successfully wrote ${savedRequests.length} requests to file \"${file}\"`,\n ),\n );\n\n return savedRequests;\n}\n","import type { Got } from 'got';\nimport * as t from 'io-ts';\nimport { logger } from '../../logger';\nimport { uniq } from 'lodash-es';\nimport colors from 'colors';\nimport { splitCsvToList } from '../requests/splitCsvToList';\n\nconst ADMIN_URL =\n 'https://app.transcend.io/privacy-requests/incoming-requests/';\n/**\n * Minimal set required to mark as completed\n */\nexport const EnrichPrivacyRequest = t.record(t.string, t.string);\n\n/** Type override */\nexport type EnrichPrivacyRequest = t.TypeOf<typeof EnrichPrivacyRequest>;\n\n/**\n * Upload identifiers to a privacy request or mark request as\n *\n * @param sombra - Sombra instance configured to make requests\n * @param request - Request to enricher\n * @param enricherId - The ID of the enricher being uploaded to\n * @param index - Index of request ID\n * @returns True if enriched successfully, false if skipped, throws error if failed\n */\nexport async function enrichPrivacyRequest(\n sombra: Got,\n { id: rawId, ...rest }: EnrichPrivacyRequest,\n enricherId: string,\n index?: number,\n): Promise<boolean> {\n if (!rawId) {\n // error\n const msg = `Request ID must be provided to enricher request.${\n index ? ` Found error in row: ${index}` : ''\n }`;\n logger.error(colors.red(msg));\n throw new Error(msg);\n }\n\n const id = rawId.toLowerCase();\n\n // Pull out the identifiers\n const enrichedIdentifiers = Object.entries(rest).reduce(\n (acc, [key, value]) => {\n const values = uniq(splitCsvToList(value));\n return values.length === 0\n ? acc\n : Object.assign(acc, {\n [key]: uniq(splitCsvToList(value)).map((val) => ({\n value: key === 'email' ? val.toLowerCase() : val,\n })),\n });\n },\n {} as Record<string, string[]>,\n );\n\n // Make the GraphQL request\n try {\n await sombra\n .post('v1/enrich-identifiers', {\n headers: {\n 'x-transcend-request-id': id,\n 'x-transcend-enricher-id': enricherId,\n },\n json: {\n enrichedIdentifiers,\n },\n })\n .json();\n\n logger.error(\n colors.green(`Successfully enriched request: ${ADMIN_URL}${id}`),\n );\n return true;\n } catch (err) {\n // skip if already enriched\n if (\n typeof err.response.body === 'string' &&\n err.response.body.includes('Cannot update a resolved RequestEnricher')\n ) {\n logger.warn(\n colors.magenta(\n `Skipped enrichment for request: ${ADMIN_URL}${id}, request is no longer in the enriching phase.`,\n ),\n );\n return false;\n }\n\n // error\n logger.error(\n colors.red(\n `Failed to enricher identifiers for request with id: ${ADMIN_URL}${id} - ${err.message} - ${err.response.body}`,\n ),\n );\n throw err;\n }\n}\n","import colors from 'colors';\nimport { map } from '../bluebird-replace';\nimport { logger } from '../../logger';\nimport {\n UPDATE_PRIVACY_REQUEST,\n buildTranscendGraphQLClient,\n createSombraGotInstance,\n makeGraphQLRequest,\n} from '../graphql';\nimport {\n enrichPrivacyRequest,\n EnrichPrivacyRequest,\n} from './enrichPrivacyRequest';\nimport { readCsv } from '../requests';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Push a CSV of enriched requests back into Transcend\n *\n * @param options - Options\n * @returns Number of items processed\n */\nexport async function pushManualEnrichmentIdentifiersFromCsv({\n file,\n auth,\n sombraAuth,\n enricherId,\n markSilent,\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** CSV file path */\n file: string;\n /** Transcend API key authentication */\n auth: string;\n /** ID of enricher being uploaded to */\n enricherId: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** Concurrency */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Mark requests in silent mode before enriching */\n markSilent?: boolean;\n}): Promise<number> {\n // Create sombra instance to communicate with\n const sombra = await createSombraGotInstance(transcendUrl, auth, sombraAuth);\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Read from CSV\n logger.info(colors.magenta(`Reading \"${file}\" from disk`));\n const activeResults = readCsv(file, EnrichPrivacyRequest);\n\n // Notify Transcend\n logger.info(\n colors.magenta(`Enriching \"${activeResults.length}\" privacy requests.`),\n );\n\n let successCount = 0;\n let skippedCount = 0;\n let errorCount = 0;\n\n await map(\n activeResults,\n async (request, index) => {\n try {\n // Mark requests in silent mode before a certain date\n if (markSilent) {\n await makeGraphQLRequest(client, UPDATE_PRIVACY_REQUEST, {\n input: {\n id: request.id,\n isSilent: true,\n },\n });\n\n logger.info(\n colors.magenta(`Mark request as silent mode - ${request.id}`),\n );\n }\n\n const result = await enrichPrivacyRequest(\n sombra,\n request,\n enricherId,\n index,\n );\n if (result) {\n successCount += 1;\n } else {\n skippedCount += 1;\n }\n } catch (err) {\n errorCount += 1;\n }\n },\n { concurrency },\n );\n\n logger.info(\n colors.green(\n `Successfully notified Transcend! \\n Success count: ${successCount}.`,\n ),\n );\n\n if (skippedCount > 0) {\n logger.info(colors.magenta(`Skipped count: ${skippedCount}.`));\n }\n\n if (errorCount > 0) {\n logger.info(colors.red(`Error Count: ${errorCount}.`));\n throw new Error(`Failed to enrich: ${errorCount} requests.`);\n }\n\n return activeResults.length;\n}\n"],"mappings":"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","names":["RequestStatus","colors","groupBy","uniq","pullManualEnrichmentIdentifiersToCsv","file","auth","sombraAuth","requestActions","concurrency","transcendUrl","DEFAULT_TRANSCEND_API","client","buildTranscendGraphQLClient","sombra","createSombraGotInstance","logger","colors","allRequests","fetchAllRequests","RequestStatus","savedRequests","map","request","requestEnrichers","fetchAllRequestEnrichers","status","requestIdentifiers","fetchAllRequestIdentifiers","data","attributeValues","groupBy","acc","key","values","value","name","headers","uniq","d","writeCsv","t","uniq","colors","ADMIN_URL","EnrichPrivacyRequest","enrichPrivacyRequest","sombra","rawId","rest","enricherId","index","msg","logger","colors","id","enrichedIdentifiers","acc","key","value","uniq","splitCsvToList","val","err","colors","pushManualEnrichmentIdentifiersFromCsv","file","auth","sombraAuth","enricherId","markSilent","concurrency","transcendUrl","DEFAULT_TRANSCEND_API","sombra","createSombraGotInstance","client","buildTranscendGraphQLClient","logger","colors","activeResults","readCsv","EnrichPrivacyRequest","successCount","skippedCount","errorCount","map","request","index","makeGraphQLRequest","UPDATE_PRIVACY_REQUEST","enrichPrivacyRequest"]}
|