@transcend-io/cli 8.36.1 → 8.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -0
- package/dist/{api-keys-DB0BZSh5.cjs → api-keys-eh_rPCV_.cjs} +2 -2
- package/dist/{api-keys-DB0BZSh5.cjs.map → api-keys-eh_rPCV_.cjs.map} +1 -1
- package/dist/app-D0ewaGAn.cjs +131 -0
- package/dist/app-D0ewaGAn.cjs.map +1 -0
- package/dist/bin/bash-complete.cjs +1 -1
- package/dist/bin/bash-complete.cjs.map +1 -1
- package/dist/bin/cli.cjs +1 -1
- package/dist/bin/cli.cjs.map +1 -1
- package/dist/bin/deprecated-command.cjs +1 -1
- package/dist/bin/deprecated-command.cjs.map +1 -1
- package/dist/buildAIIntegrationType-BwuCYR-o.cjs +2 -0
- package/dist/{buildAIIntegrationType-n_Qlv8wG.cjs.map → buildAIIntegrationType-BwuCYR-o.cjs.map} +1 -1
- package/dist/chunk-Bmb41Sf3.cjs +1 -0
- package/dist/{code-scanning-Yc7rgoTY.cjs → code-scanning-BB6Ncuzh.cjs} +2 -2
- package/dist/{code-scanning-Yc7rgoTY.cjs.map → code-scanning-BB6Ncuzh.cjs.map} +1 -1
- package/dist/codecs-Bvmb8o9R.cjs +2 -0
- package/dist/{codecs-JSDJgtyL.cjs.map → codecs-Bvmb8o9R.cjs.map} +1 -1
- package/dist/command-BUkTNNIa.cjs +9 -0
- package/dist/{command-41dUPvEa.cjs.map → command-BUkTNNIa.cjs.map} +1 -1
- package/dist/{consent-manager-BNMaKHId.cjs → consent-manager-Df8gw2Qh.cjs} +2 -2
- package/dist/{consent-manager-BNMaKHId.cjs.map → consent-manager-Df8gw2Qh.cjs.map} +1 -1
- package/dist/constants-7qBywLgI.cjs +2 -0
- package/dist/{constants-JoCDv9ym.cjs.map → constants-7qBywLgI.cjs.map} +1 -1
- package/dist/context-_8xfl0dt.cjs +2 -0
- package/dist/{context-Bw1xk9Q_.cjs.map → context-_8xfl0dt.cjs.map} +1 -1
- package/dist/{cron-ClvgH2uD.cjs → cron-BhfbISdy.cjs} +2 -2
- package/dist/{cron-ClvgH2uD.cjs.map → cron-BhfbISdy.cjs.map} +1 -1
- package/dist/{data-inventory-BzEYoxaa.cjs → data-inventory-D36n1YAJ.cjs} +2 -2
- package/dist/{data-inventory-BzEYoxaa.cjs.map → data-inventory-D36n1YAJ.cjs.map} +1 -1
- package/dist/{dataFlowsToDataSilos-daBgPi7V.cjs → dataFlowsToDataSilos-BLNhWeOw.cjs} +2 -2
- package/dist/{dataFlowsToDataSilos-daBgPi7V.cjs.map → dataFlowsToDataSilos-BLNhWeOw.cjs.map} +1 -1
- package/dist/{done-input-validation-Cgk5kNBs.cjs → done-input-validation-DGckEJ5a.cjs} +1 -1
- package/dist/{done-input-validation-Cgk5kNBs.cjs.map → done-input-validation-DGckEJ5a.cjs.map} +1 -1
- package/dist/enums-BZulhPFa.cjs +2 -0
- package/dist/{enums-CBXlBJii.cjs.map → enums-BZulhPFa.cjs.map} +1 -1
- package/dist/impl--CgaKM4x.cjs +2 -0
- package/dist/{impl-BFOghVmx.cjs.map → impl--CgaKM4x.cjs.map} +1 -1
- package/dist/impl--PmMYd1g.cjs +2 -0
- package/dist/{impl-BouHRicT.cjs.map → impl--PmMYd1g.cjs.map} +1 -1
- package/dist/impl-47WGWxyj.cjs +2 -0
- package/dist/{impl-CFmFCVt8.cjs.map → impl-47WGWxyj.cjs.map} +1 -1
- package/dist/impl-4NCrJ_Y6.cjs +2 -0
- package/dist/{impl-cfDtPbS9.cjs.map → impl-4NCrJ_Y6.cjs.map} +1 -1
- package/dist/impl-5AfPlpzA.cjs +2 -0
- package/dist/{impl-hGu8uCC4.cjs.map → impl-5AfPlpzA.cjs.map} +1 -1
- package/dist/impl-73q3K0b_.cjs +2 -0
- package/dist/{impl-BN61r-PG.cjs.map → impl-73q3K0b_.cjs.map} +1 -1
- package/dist/impl-8Basu9U-.cjs +2 -0
- package/dist/{impl-BXMfTm4K.cjs.map → impl-8Basu9U-.cjs.map} +1 -1
- package/dist/impl-BC1mCUl1.cjs +2 -0
- package/dist/{impl-CCOEjRnr.cjs.map → impl-BC1mCUl1.cjs.map} +1 -1
- package/dist/impl-BNEgHNz7.cjs +4 -0
- package/dist/{impl-8bci0gd2.cjs.map → impl-BNEgHNz7.cjs.map} +1 -1
- package/dist/impl-BPq8EyHn.cjs +2 -0
- package/dist/{impl-BRuqPhJU.cjs.map → impl-BPq8EyHn.cjs.map} +1 -1
- package/dist/impl-BfN9XMNM.cjs +2 -0
- package/dist/{impl-ClDXxODZ.cjs.map → impl-BfN9XMNM.cjs.map} +1 -1
- package/dist/impl-Boa1Uuzk.cjs +2 -0
- package/dist/{impl-DpdGWdrr.cjs.map → impl-Boa1Uuzk.cjs.map} +1 -1
- package/dist/impl-Bv2mYf1w.cjs +2 -0
- package/dist/{impl-C4D1tHjp.cjs.map → impl-Bv2mYf1w.cjs.map} +1 -1
- package/dist/impl-BxOeeF35.cjs +2 -0
- package/dist/{impl-CoxOrlXu.cjs.map → impl-BxOeeF35.cjs.map} +1 -1
- package/dist/impl-ByQI5s4b.cjs +2 -0
- package/dist/{impl-D7WBmmHb.cjs.map → impl-ByQI5s4b.cjs.map} +1 -1
- package/dist/impl-C1IjDv1N.cjs +2 -0
- package/dist/{impl-_dGu54cO.cjs.map → impl-C1IjDv1N.cjs.map} +1 -1
- package/dist/impl-CVsXgVaf.cjs +2 -0
- package/dist/{impl-BWiNjS6v.cjs.map → impl-CVsXgVaf.cjs.map} +1 -1
- package/dist/impl-CdXk78ar.cjs +2 -0
- package/dist/{impl-DhdY6lbj.cjs.map → impl-CdXk78ar.cjs.map} +1 -1
- package/dist/impl-CfsKuglq.cjs +2 -0
- package/dist/{impl-BH0HWnIY.cjs.map → impl-CfsKuglq.cjs.map} +1 -1
- package/dist/impl-CkkD_smS.cjs +2 -0
- package/dist/{impl-BS8t24Z7.cjs.map → impl-CkkD_smS.cjs.map} +1 -1
- package/dist/impl-Cotrjytz.cjs +2 -0
- package/dist/{impl-yHutqfbd.cjs.map → impl-Cotrjytz.cjs.map} +1 -1
- package/dist/impl-Crhm9eFe.cjs +2 -0
- package/dist/{impl-BYK9pQs0.cjs.map → impl-Crhm9eFe.cjs.map} +1 -1
- package/dist/impl-Cru4riTc.cjs +5 -0
- package/dist/impl-Cru4riTc.cjs.map +1 -0
- package/dist/impl-D2P_gDE8.cjs +2 -0
- package/dist/{impl-CA_CO88W.cjs.map → impl-D2P_gDE8.cjs.map} +1 -1
- package/dist/{impl-DjVmOb9T.cjs → impl-DDHduv-X.cjs} +2 -2
- package/dist/{impl-DjVmOb9T.cjs.map → impl-DDHduv-X.cjs.map} +1 -1
- package/dist/impl-DEULjxRp.cjs +2 -0
- package/dist/{impl-8zottXEQ.cjs.map → impl-DEULjxRp.cjs.map} +1 -1
- package/dist/impl-DHUnZ-Qx.cjs +2 -0
- package/dist/{impl-CSZwdpH-.cjs.map → impl-DHUnZ-Qx.cjs.map} +1 -1
- package/dist/impl-DI3lTLCy.cjs +2 -0
- package/dist/{impl-D3sI4I1g.cjs.map → impl-DI3lTLCy.cjs.map} +1 -1
- package/dist/impl-DKMxd5Wy.cjs +2 -0
- package/dist/{impl-ay7i0K_5.cjs.map → impl-DKMxd5Wy.cjs.map} +1 -1
- package/dist/impl-DNDs3FFG.cjs +2 -0
- package/dist/{impl-BjOFvm4E.cjs.map → impl-DNDs3FFG.cjs.map} +1 -1
- package/dist/impl-DQTfX_qq.cjs +4 -0
- package/dist/{impl-FlZPR0yd.cjs.map → impl-DQTfX_qq.cjs.map} +1 -1
- package/dist/impl-DS2IlxS3.cjs +2 -0
- package/dist/{impl-BIqdEXRo.cjs.map → impl-DS2IlxS3.cjs.map} +1 -1
- package/dist/impl-DVCUGrVY.cjs +2 -0
- package/dist/{impl-SkiG9sWb.cjs.map → impl-DVCUGrVY.cjs.map} +1 -1
- package/dist/{impl-C-_9uRms.cjs → impl-DZbi3AkB.cjs} +2 -2
- package/dist/{impl-C-_9uRms.cjs.map → impl-DZbi3AkB.cjs.map} +1 -1
- package/dist/impl-DcMkDhXY.cjs +2 -0
- package/dist/{impl-NLEQuKnT.cjs.map → impl-DcMkDhXY.cjs.map} +1 -1
- package/dist/impl-DlB56v12.cjs +2 -0
- package/dist/{impl-DU-WTXTY.cjs.map → impl-DlB56v12.cjs.map} +1 -1
- package/dist/impl-Du1Ty4JE.cjs +2 -0
- package/dist/{impl-Cp12F9tr.cjs.map → impl-Du1Ty4JE.cjs.map} +1 -1
- package/dist/{impl-KgEJvOhE.cjs → impl-DxDGyjMI.cjs} +2 -2
- package/dist/{impl-KgEJvOhE.cjs.map → impl-DxDGyjMI.cjs.map} +1 -1
- package/dist/impl-Dxgw6Xfk.cjs +2 -0
- package/dist/{impl-J5fV8gbh.cjs.map → impl-Dxgw6Xfk.cjs.map} +1 -1
- package/dist/impl-IQ7JOZxt.cjs +2 -0
- package/dist/{impl-Bv4gPikD.cjs.map → impl-IQ7JOZxt.cjs.map} +1 -1
- package/dist/impl-bgI-lF8x.cjs +2 -0
- package/dist/{impl-4pmSDQvA.cjs.map → impl-bgI-lF8x.cjs.map} +1 -1
- package/dist/impl-feFIqpBO.cjs +2 -0
- package/dist/{impl-BwAnSxkP.cjs.map → impl-feFIqpBO.cjs.map} +1 -1
- package/dist/impl-orpaJd8b.cjs +12 -0
- package/dist/{impl-BMxxKrNz.cjs.map → impl-orpaJd8b.cjs.map} +1 -1
- package/dist/{impl-ChNLuyNq.cjs → impl-xUzH7vUF.cjs} +2 -2
- package/dist/{impl-ChNLuyNq.cjs.map → impl-xUzH7vUF.cjs.map} +1 -1
- package/dist/index.cjs +4 -4
- package/dist/index.cjs.map +1 -1
- package/dist/{logger-BaHHbWVd.cjs → logger-DQwEYtSS.cjs} +2 -2
- package/dist/{logger-BaHHbWVd.cjs.map → logger-DQwEYtSS.cjs.map} +1 -1
- package/dist/{manual-enrichment-D-0rM9KN.cjs → manual-enrichment-CzRiIFev.cjs} +2 -2
- package/dist/{manual-enrichment-D-0rM9KN.cjs.map → manual-enrichment-CzRiIFev.cjs.map} +1 -1
- package/dist/{mergeTranscendInputs-PPpGbYgG.cjs → mergeTranscendInputs-BIBCYbug.cjs} +2 -2
- package/dist/{mergeTranscendInputs-PPpGbYgG.cjs.map → mergeTranscendInputs-BIBCYbug.cjs.map} +1 -1
- package/dist/{pooling-DbIx6-i7.cjs → pooling-BJAPXDiq.cjs} +2 -2
- package/dist/{pooling-DbIx6-i7.cjs.map → pooling-BJAPXDiq.cjs.map} +1 -1
- package/dist/{preference-management-Dapt3Li3.cjs → preference-management-DV6NIcXt.cjs} +2 -2
- package/dist/{preference-management-Dapt3Li3.cjs.map → preference-management-DV6NIcXt.cjs.map} +1 -1
- package/dist/{readTranscendYaml-CL9nujUr.cjs → readTranscendYaml-Cycz6RxW.cjs} +2 -2
- package/dist/{readTranscendYaml-CL9nujUr.cjs.map → readTranscendYaml-Cycz6RxW.cjs.map} +1 -1
- package/dist/syncConfigurationToTranscend-Bd0ZTIm1.cjs +2994 -0
- package/dist/{syncConfigurationToTranscend-D4PLA70C.cjs.map → syncConfigurationToTranscend-Bd0ZTIm1.cjs.map} +1 -1
- package/dist/{uploadConsents-CN1JucL3.cjs → uploadConsents-XYRco1_L.cjs} +2 -2
- package/dist/{uploadConsents-CN1JucL3.cjs.map → uploadConsents-XYRco1_L.cjs.map} +1 -1
- package/package.json +1 -1
- package/dist/app-BOlZhpYh.cjs +0 -118
- package/dist/app-BOlZhpYh.cjs.map +0 -1
- package/dist/buildAIIntegrationType-n_Qlv8wG.cjs +0 -2
- package/dist/codecs-JSDJgtyL.cjs +0 -2
- package/dist/command-41dUPvEa.cjs +0 -9
- package/dist/constants-JoCDv9ym.cjs +0 -2
- package/dist/context-Bw1xk9Q_.cjs +0 -2
- package/dist/enums-CBXlBJii.cjs +0 -2
- package/dist/impl-4pmSDQvA.cjs +0 -2
- package/dist/impl-8bci0gd2.cjs +0 -4
- package/dist/impl-8zottXEQ.cjs +0 -2
- package/dist/impl-BFOghVmx.cjs +0 -2
- package/dist/impl-BH0HWnIY.cjs +0 -2
- package/dist/impl-BIqdEXRo.cjs +0 -2
- package/dist/impl-BMxxKrNz.cjs +0 -12
- package/dist/impl-BN61r-PG.cjs +0 -2
- package/dist/impl-BRuqPhJU.cjs +0 -2
- package/dist/impl-BS8t24Z7.cjs +0 -2
- package/dist/impl-BWiNjS6v.cjs +0 -2
- package/dist/impl-BXMfTm4K.cjs +0 -2
- package/dist/impl-BYK9pQs0.cjs +0 -2
- package/dist/impl-BjOFvm4E.cjs +0 -2
- package/dist/impl-BouHRicT.cjs +0 -2
- package/dist/impl-Bv4gPikD.cjs +0 -2
- package/dist/impl-BwAnSxkP.cjs +0 -2
- package/dist/impl-C4D1tHjp.cjs +0 -2
- package/dist/impl-CA_CO88W.cjs +0 -2
- package/dist/impl-CCOEjRnr.cjs +0 -2
- package/dist/impl-CFmFCVt8.cjs +0 -2
- package/dist/impl-CSZwdpH-.cjs +0 -2
- package/dist/impl-ClDXxODZ.cjs +0 -2
- package/dist/impl-CoxOrlXu.cjs +0 -2
- package/dist/impl-Cp12F9tr.cjs +0 -2
- package/dist/impl-D3sI4I1g.cjs +0 -2
- package/dist/impl-D7WBmmHb.cjs +0 -2
- package/dist/impl-DU-WTXTY.cjs +0 -2
- package/dist/impl-DhdY6lbj.cjs +0 -2
- package/dist/impl-DpdGWdrr.cjs +0 -2
- package/dist/impl-FlZPR0yd.cjs +0 -4
- package/dist/impl-J5fV8gbh.cjs +0 -2
- package/dist/impl-NLEQuKnT.cjs +0 -2
- package/dist/impl-SkiG9sWb.cjs +0 -2
- package/dist/impl-_dGu54cO.cjs +0 -2
- package/dist/impl-ay7i0K_5.cjs +0 -2
- package/dist/impl-cfDtPbS9.cjs +0 -2
- package/dist/impl-hGu8uCC4.cjs +0 -2
- package/dist/impl-yHutqfbd.cjs +0 -2
- package/dist/syncConfigurationToTranscend-D4PLA70C.cjs +0 -2994
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncConfigurationToTranscend-D4PLA70C.cjs","names":["trimmedEndIndex","isSymbol","isObject","baseTrim","toNumber","toFinite","apply","defineProperty","identity","constant","shortOut","baseSetToString","strictIndexOf","baseFindIndex","baseIsNaN","baseIndexOf","nativeMax","apply","setToString","overRest","identity","isObject","isArrayLike","isIndex","eq","Symbol","isArray","isArguments","isFlattenable","baseFlatten","baseSlice","rsAstralRange","rsComboRange","rsVarRange","rsCombo","rsModifier","rsNonAstral","rsRegional","rsSurrPair","rsZWJ","reOptMod","rsOptVar","rsOptJoin","rsSeq","hasUnicode","unicodeToArray","asciiToArray","toString","hasUnicode","stringToArray","castSlice","createCaseFirst","basePropertyOf","toString","deburrLetter","toString","hasUnicodeWord","unicodeWords","asciiWords","arrayReduce","words","deburr","isIterateeCall","toInteger","baseSlice","isObjectLike","isArrayLike","LARGE_ARRAY_SIZE","arrayIncludes","arrayMap","baseUnary","arrayIncludesWith","cacheHas","SetCache","baseRest","isArrayLikeObject","baseDifference","baseFlatten","isArrayLike","collection","createAggregator","baseIteratee","object","isSymbol","compareAscending","arrayMap","isArray","baseGet","identity","baseUnary","baseIteratee","baseSortBy","baseMap","compareMultiple","baseRest","isIterateeCall","baseOrderBy","baseFlatten","createCompounder","upperFirst","Set","setToArray","noop","arrayIncludes","arrayIncludesWith","createSet","setToArray","cacheHas","SetCache","baseUniq","baseUniq","baseIteratee","Bluebird","t","RequestAction","LOCALE_KEY","IsoCountryCode","IsoCountrySubdivisionCode","CompletedRequestStatus","CachedRequestState","autoCompletePrompt","t","t","uniq","uniq","rest","GraphQLClient","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","chunk","PAGE_SIZE","PAGE_SIZE","AttributeKeyType","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","ConsentTrackerStatus","PAGE_SIZE","PAGE_SIZE","ConsentTrackerStatus","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","t","IdentifierType","PAGE_SIZE","version","t","RequestAction","RequestOrigin","LOCALE_KEY","RequestStatus","IsoCountryCode","IsoCountrySubdivisionCode","PAGE_SIZE","cliProgress","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","uniq","keyBy","difference","PAGE_SIZE","uniq","flatten","keyBy","difference","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","t","ComparisonOperator","LogicOperator","AssessmentsDisplayLogicAction","t","ComparisonOperator","gql","sortBy","keyBy","chunk","cliProgress","PAGE_SIZE","RequestAction","EnricherType","PAGE_SIZE","PAGE_SIZE","difference","PAGE_SIZE","TranscendPullResource","ConsentTrackerStatus","ActionItemCode","flatten","title","assignees","externalAssignees","resources","prompts","name","actions","type","RetentionType","dataSilos","dataSubjects","teams","RequestAction","agentFunctions","agentFiles","showInPrivacyCenter","identifiers","keyBy","businessEntities","mapValues","IsoCountryCode","IsoCountrySubdivisionCode","difference","createActionItemCollection","keyBy","chunk","keyBy","uniq","createAgentFile","keyBy","createAgentFunction","keyBy","createAgent","keyBy","keyBy","groupBy","difference","createBusinessEntity","chunk","keyBy","PAGE_SIZE","PAGE_SIZE","CHUNK_SIZE","keyBy","chunk","PAGE_SIZE","CHUNK_SIZE","keyBy","chunk","CHUNK_SIZE","uniqBy","keyBy","uniq","chunk","keyBy","OnConsentExpiry","InitialViewState","MAX_PAGE_SIZE","chunk","createDataCategory","keyBy","MAX_PAGE_SIZE","chunk","ConsentTrackerStatus","MAX_PAGE_SIZE","chunk","chunk","keyBy","createProcessingActivity","keyBy","keyBy","input","keyBy","createVendor","keyBy","chunk","RequestStatus","DEFAULT_TRANSCEND_API","cliProgress","startCase","RequestAction","LOCALE_KEY","CompletedRequestStatus","IsoCountryCode","IsoCountrySubdivisionCode","t","RequestAction","IsoCountryCode","IsoCountrySubdivisionCode","CompletedRequestStatus","DateFromISOString","LOCALE_KEY","IdentifierType","NORMALIZE_PHONE_NUMBER","t","TableEncryptionType","cliProgress","RequestStatus","DEFAULT_TRANSCEND_API","RequestAction","cliProgress","t","RequestStatus","RequestAction","IsoCountryCode","IsoCountrySubdivisionCode","uniq","DEFAULT_TRANSCEND_API","cliProgress","RequestStatus","RequestAction","DEFAULT_TRANSCEND_API","cliProgress","RequestStatus","DEFAULT_TRANSCEND_API","cliProgress","DEFAULT_TRANSCEND_API","cliProgress","PersistedState","CachedRequestState","t","uniq","groupBy","IdentifierType","t","t","DEFAULT_TRANSCEND_API","cliProgress","PersistedState","difference","DEFAULT_TRANSCEND_API","RequestStatus","cliProgress","RequestEnricherStatus","DEFAULT_TRANSCEND_API","RequestEnricherStatus","cliProgress","RequestStatus","difference","DEFAULT_TRANSCEND_API","cliProgress","RequestStatus","DEFAULT_TRANSCEND_API","isTest","groupBy","name","DEFAULT_TRANSCEND_API","RequestStatus","cliProgress","DEFAULT_TRANSCEND_API","cliProgress","RequestStatus","autoCompletePrompt","resolve","fastcsv","resolve","keyBy","difference","uniq","flatten","createTeam","updateTeam","keyBy","input","keyBy","input","keyBy","existing","prompt"],"sources":["../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_trimmedEndIndex.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseTrim.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/toNumber.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/toFinite.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/toInteger.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_apply.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/noop.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_shortOut.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/constant.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseSetToString.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_setToString.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseFindIndex.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseIsNaN.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_strictIndexOf.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseIndexOf.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_arrayIncludes.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_overRest.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseRest.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_isIterateeCall.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_isFlattenable.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseFlatten.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/flatten.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseSlice.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_castSlice.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_hasUnicode.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_asciiToArray.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_unicodeToArray.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_stringToArray.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_createCaseFirst.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/upperFirst.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_arrayReduce.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_basePropertyOf.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_deburrLetter.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/deburr.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_asciiWords.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_hasUnicodeWord.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_unicodeWords.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/words.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_createCompounder.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/chunk.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isArrayLikeObject.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_arrayIncludesWith.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseDifference.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/difference.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseMap.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/groupBy.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/mapValues.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseSortBy.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_compareAscending.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_compareMultiple.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseOrderBy.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/sortBy.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/startCase.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_createSet.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseUniq.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/uniq.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/uniqBy.js","../src/lib/bluebird.ts","../src/lib/graphql/gqls/dataPoint.ts","../src/lib/graphql/gqls/entry.ts","../src/lib/graphql/gqls/dataSilo.ts","../src/lib/graphql/gqls/enricher.ts","../src/lib/graphql/gqls/catalog.ts","../src/lib/graphql/gqls/identifier.ts","../src/lib/graphql/gqls/dataSubject.ts","../src/lib/graphql/gqls/repository.ts","../src/lib/graphql/gqls/apiKey.ts","../src/lib/graphql/gqls/preferenceAccessTokens.ts","../src/lib/graphql/gqls/siloDiscovery.ts","../src/lib/graphql/gqls/template.ts","../src/lib/graphql/gqls/organization.ts","../src/lib/graphql/gqls/attributeKey.ts","../src/lib/graphql/gqls/softwareDevelopmentKit.ts","../src/lib/graphql/gqls/codePackage.ts","../src/lib/graphql/gqls/promptThread.ts","../src/lib/graphql/gqls/policy.ts","../src/lib/graphql/gqls/request.ts","../src/lib/graphql/gqls/message.ts","../src/lib/graphql/gqls/RequestEnricher.ts","../src/lib/graphql/gqls/assessment.ts","../src/lib/graphql/gqls/purpose.ts","../src/lib/graphql/gqls/preferenceTopic.ts","../src/lib/graphql/gqls/assessmentTemplate.ts","../src/lib/graphql/gqls/prompt.ts","../src/lib/graphql/gqls/RequestDataSilo.ts","../src/lib/graphql/gqls/team.ts","../src/lib/graphql/gqls/RequestIdentifier.ts","../src/lib/graphql/gqls/user.ts","../src/lib/graphql/gqls/requestFile.ts","../src/lib/graphql/gqls/promptRun.ts","../src/lib/graphql/gqls/actionItemCollection.ts","../src/lib/graphql/gqls/attribute.ts","../src/lib/graphql/gqls/consentManager.ts","../src/lib/graphql/gqls/consentManagerMetrics.ts","../src/lib/graphql/gqls/businessEntity.ts","../src/lib/graphql/gqls/action.ts","../src/lib/graphql/gqls/actionItem.ts","../src/lib/graphql/gqls/privacyCenter.ts","../src/lib/graphql/gqls/auth.ts","../src/lib/graphql/gqls/largeLanguageModel.ts","../src/lib/graphql/gqls/agent.ts","../src/lib/graphql/gqls/agentFile.ts","../src/lib/graphql/gqls/agentFunction.ts","../src/lib/graphql/gqls/vendor.ts","../src/lib/graphql/gqls/dataCategory.ts","../src/lib/graphql/gqls/processingPurpose.ts","../src/lib/graphql/gqls/processingActivity.ts","../src/lib/graphql/gqls/sombraVersion.ts","../src/lib/graphql/gqls/siloDiscoveryResult.ts","../src/lib/requests/constants.ts","../src/lib/requests/fuzzyMatchColumns.ts","../src/lib/requests/mapEnumValues.ts","../src/lib/requests/splitCsvToList.ts","../src/lib/requests/parseAttributesFromString.ts","../src/lib/requests/readCsv.ts","../src/lib/requests/getUniqueValuesForColumn.ts","../src/lib/requests/filterRows.ts","../src/lib/graphql/addMessagesToPromptRun.ts","../src/lib/graphql/buildTranscendGraphQLClient.ts","../src/lib/graphql/createSombraGotInstance.ts","../src/lib/graphql/createTranscendConsentGotInstance.ts","../src/lib/graphql/deployConsentManager.ts","../src/lib/graphql/fetchActiveSiloDiscoPlugin.ts","../src/lib/graphql/fetchAllActionItems.ts","../src/lib/graphql/fetchAllActions.ts","../src/lib/graphql/fetchAllAgentFiles.ts","../src/lib/graphql/fetchAllAgentFunctions.ts","../src/lib/graphql/fetchAllAgents.ts","../src/lib/graphql/fetchAllAssessments.ts","../src/lib/graphql/fetchAllAssessmentTemplates.ts","../src/lib/graphql/createPreferenceAccessTokens.ts","../src/lib/graphql/fetchAllAttributeKeys.ts","../src/lib/graphql/fetchAllAttributes.ts","../src/lib/graphql/fetchAllBusinessEntities.ts","../src/lib/graphql/fetchConsentManagerId.ts","../src/lib/graphql/fetchAllCookies.ts","../src/lib/graphql/fetchAllDataCategories.ts","../src/lib/graphql/fetchAllDataFlows.ts","../src/lib/graphql/fetchAllMessages.ts","../src/lib/graphql/fetchPrivacyCenterId.ts","../src/lib/graphql/fetchAllPolicies.ts","../src/lib/graphql/formatAttributeValues.ts","../src/lib/graphql/fetchAllPreferenceTopics.ts","../src/lib/graphql/fetchAllPrivacyCenters.ts","../src/lib/graphql/fetchAllProcessingActivities.ts","../src/lib/graphql/fetchAllProcessingPurposes.ts","../src/lib/graphql/fetchAllPurposes.ts","../src/lib/graphql/fetchAllPurposesAndPreferences.ts","../src/lib/graphql/fetchAllRequestEnrichers.ts","../src/lib/graphql/fetchAllRequestIdentifierMetadata.ts","../src/lib/graphql/fetchAllRequestIdentifiers.ts","../src/lib/graphql/fetchAllRequests.ts","../src/lib/graphql/fetchAllTeams.ts","../src/lib/graphql/fetchAllUsers.ts","../src/lib/graphql/fetchAllVendors.ts","../src/lib/graphql/fetchApiKeys.ts","../src/lib/graphql/fetchCatalogs.ts","../src/lib/graphql/fetchDataSubjects.ts","../src/lib/graphql/fetchPromptGroups.ts","../src/lib/graphql/fetchPromptPartials.ts","../src/lib/graphql/fetchPrompts.ts","../src/lib/graphql/fetchPromptThreads.ts","../src/lib/graphql/fetchRequestDataSilo.ts","../src/lib/graphql/fetchRequestDataSiloActiveCount.ts","../src/lib/graphql/fetchRequestFilesForRequest.ts","../src/lib/graphql/loginUser.ts","../src/lib/graphql/manageApiKeys.ts","../src/lib/graphql/parseAssessmentDisplayLogic.ts","../src/lib/graphql/parseAssessmentRiskLogic.ts","../src/lib/graphql/syncDataSilos.ts","../src/lib/graphql/syncEnrichers.ts","../src/lib/graphql/syncTemplates.ts","../src/lib/graphql/formatRegions.ts","../src/lib/graphql/fetchAllActionItemCollections.ts","../src/lib/graphql/syncPartitions.ts","../src/lib/graphql/fetchAllSiloDiscoveryResults.ts","../src/lib/graphql/pullTranscendConfiguration.ts","../src/lib/graphql/reportPromptRun.ts","../src/lib/graphql/retryRequestEnricher.ts","../src/lib/graphql/setResourceAttributes.ts","../src/lib/graphql/syncAction.ts","../src/lib/graphql/syncActionItemCollections.ts","../src/lib/graphql/syncActionItems.ts","../src/lib/graphql/syncAgentFiles.ts","../src/lib/graphql/syncAgentFunctions.ts","../src/lib/graphql/syncAgents.ts","../src/lib/graphql/syncAttribute.ts","../src/lib/graphql/syncBusinessEntities.ts","../src/lib/graphql/fetchAllCodePackages.ts","../src/lib/graphql/fetchAllSoftwareDevelopmentKits.ts","../src/lib/graphql/syncSoftwareDevelopmentKits.ts","../src/lib/graphql/fetchAllRepositories.ts","../src/lib/graphql/syncRepositories.ts","../src/lib/graphql/syncCodePackages.ts","../src/lib/graphql/syncConsentManager.ts","../src/lib/graphql/syncCookies.ts","../src/lib/graphql/syncDataCategories.ts","../src/lib/graphql/syncDataFlows.ts","../src/lib/graphql/syncDataSubject.ts","../src/lib/graphql/syncIdentifier.ts","../src/lib/graphql/syncIntlMessages.ts","../src/lib/graphql/syncPolicies.ts","../src/lib/graphql/syncPrivacyCenter.ts","../src/lib/graphql/syncProcessingActivities.ts","../src/lib/graphql/syncProcessingPurposes.ts","../src/lib/graphql/syncPrompts.ts","../src/lib/graphql/syncVendors.ts","../src/lib/graphql/uploadSiloDiscoveryResults.ts","../src/lib/requests/markSilentPrivacyRequests.ts","../src/lib/requests/mapCsvColumnsToApi.ts","../src/lib/requests/mapRequestEnumValues.ts","../src/lib/requests/mapCsvRowsToRequestInputs.ts","../src/lib/requests/getFileMetadataForPrivacyRequests.ts","../src/lib/requests/streamPrivacyRequestFiles.ts","../src/lib/requests/downloadPrivacyRequestFiles.ts","../src/lib/requests/submitPrivacyRequest.ts","../src/lib/requests/approvePrivacyRequests.ts","../src/lib/requests/notifyPrivacyRequestsAdditionalTime.ts","../src/lib/requests/mapColumnsToIdentifiers.ts","../src/lib/requests/cancelPrivacyRequests.ts","../src/lib/requests/mapColumnsToAttributes.ts","../src/lib/requests/extractClientError.ts","../src/lib/requests/uploadPrivacyRequestsFromCsv.ts","../src/lib/requests/restartPrivacyRequest.ts","../src/lib/requests/bulkRestartRequests.ts","../src/lib/requests/skipPreflightJobs.ts","../src/lib/requests/bulkRetryEnrichers.ts","../src/lib/requests/retryRequestDataSilos.ts","../src/lib/requests/pullPrivacyRequests.ts","../src/lib/requests/skipRequestDataSilos.ts","../src/lib/requests/removeUnverifiedRequestIdentifiers.ts","../src/lib/helpers/inquirer.ts","../src/lib/helpers/parseVariablesFromString.ts","../src/lib/helpers/getErrorStatus.ts","../src/lib/helpers/extractErrorMessage.ts","../src/lib/helpers/sleepPromise.ts","../src/lib/helpers/splitInHalf.ts","../src/lib/helpers/retrySamePromise.ts","../src/lib/helpers/limitRecords.ts","../src/lib/helpers/RateCounter.ts","../src/lib/helpers/readSafe.ts","../src/lib/helpers/collectParquetFilesOrExit.ts","../src/lib/helpers/parquetToCsvOneFile.ts","../src/lib/helpers/time.ts","../src/lib/helpers/writeCsv.ts","../src/lib/graphql/makeGraphQLRequest.ts","../src/lib/graphql/fetchIdentifiers.ts","../src/lib/graphql/syncTeams.ts","../src/lib/graphql/syncPromptPartials.ts","../src/lib/graphql/syncPromptGroups.ts","../src/lib/graphql/syncConfigurationToTranscend.ts"],"sourcesContent":["/** Used to match a single whitespace character. */\nvar reWhitespace = /\\s/;\n\n/**\n * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace\n * character of `string`.\n *\n * @private\n * @param {string} string The string to inspect.\n * @returns {number} Returns the index of the last non-whitespace character.\n */\nfunction trimmedEndIndex(string) {\n var index = string.length;\n\n while (index-- && reWhitespace.test(string.charAt(index))) {}\n return index;\n}\n\nexport default trimmedEndIndex;\n","import trimmedEndIndex from './_trimmedEndIndex.js';\n\n/** Used to match leading whitespace. */\nvar reTrimStart = /^\\s+/;\n\n/**\n * The base implementation of `_.trim`.\n *\n * @private\n * @param {string} string The string to trim.\n * @returns {string} Returns the trimmed string.\n */\nfunction baseTrim(string) {\n return string\n ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '')\n : string;\n}\n\nexport default baseTrim;\n","import baseTrim from './_baseTrim.js';\nimport isObject from './isObject.js';\nimport isSymbol from './isSymbol.js';\n\n/** Used as references for various `Number` constants. */\nvar NAN = 0 / 0;\n\n/** Used to detect bad signed hexadecimal string values. */\nvar reIsBadHex = /^[-+]0x[0-9a-f]+$/i;\n\n/** Used to detect binary string values. */\nvar reIsBinary = /^0b[01]+$/i;\n\n/** Used to detect octal string values. */\nvar reIsOctal = /^0o[0-7]+$/i;\n\n/** Built-in method references without a dependency on `root`. */\nvar freeParseInt = parseInt;\n\n/**\n * Converts `value` to a number.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to process.\n * @returns {number} Returns the number.\n * @example\n *\n * _.toNumber(3.2);\n * // => 3.2\n *\n * _.toNumber(Number.MIN_VALUE);\n * // => 5e-324\n *\n * _.toNumber(Infinity);\n * // => Infinity\n *\n * _.toNumber('3.2');\n * // => 3.2\n */\nfunction toNumber(value) {\n if (typeof value == 'number') {\n return value;\n }\n if (isSymbol(value)) {\n return NAN;\n }\n if (isObject(value)) {\n var other = typeof value.valueOf == 'function' ? value.valueOf() : value;\n value = isObject(other) ? (other + '') : other;\n }\n if (typeof value != 'string') {\n return value === 0 ? value : +value;\n }\n value = baseTrim(value);\n var isBinary = reIsBinary.test(value);\n return (isBinary || reIsOctal.test(value))\n ? freeParseInt(value.slice(2), isBinary ? 2 : 8)\n : (reIsBadHex.test(value) ? NAN : +value);\n}\n\nexport default toNumber;\n","import toNumber from './toNumber.js';\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0,\n MAX_INTEGER = 1.7976931348623157e+308;\n\n/**\n * Converts `value` to a finite number.\n *\n * @static\n * @memberOf _\n * @since 4.12.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {number} Returns the converted number.\n * @example\n *\n * _.toFinite(3.2);\n * // => 3.2\n *\n * _.toFinite(Number.MIN_VALUE);\n * // => 5e-324\n *\n * _.toFinite(Infinity);\n * // => 1.7976931348623157e+308\n *\n * _.toFinite('3.2');\n * // => 3.2\n */\nfunction toFinite(value) {\n if (!value) {\n return value === 0 ? value : 0;\n }\n value = toNumber(value);\n if (value === INFINITY || value === -INFINITY) {\n var sign = (value < 0 ? -1 : 1);\n return sign * MAX_INTEGER;\n }\n return value === value ? value : 0;\n}\n\nexport default toFinite;\n","import toFinite from './toFinite.js';\n\n/**\n * Converts `value` to an integer.\n *\n * **Note:** This method is loosely based on\n * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {number} Returns the converted integer.\n * @example\n *\n * _.toInteger(3.2);\n * // => 3\n *\n * _.toInteger(Number.MIN_VALUE);\n * // => 0\n *\n * _.toInteger(Infinity);\n * // => 1.7976931348623157e+308\n *\n * _.toInteger('3.2');\n * // => 3\n */\nfunction toInteger(value) {\n var result = toFinite(value),\n remainder = result % 1;\n\n return result === result ? (remainder ? result - remainder : result) : 0;\n}\n\nexport default toInteger;\n","/**\n * A faster alternative to `Function#apply`, this function invokes `func`\n * with the `this` binding of `thisArg` and the arguments of `args`.\n *\n * @private\n * @param {Function} func The function to invoke.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} args The arguments to invoke `func` with.\n * @returns {*} Returns the result of `func`.\n */\nfunction apply(func, thisArg, args) {\n switch (args.length) {\n case 0: return func.call(thisArg);\n case 1: return func.call(thisArg, args[0]);\n case 2: return func.call(thisArg, args[0], args[1]);\n case 3: return func.call(thisArg, args[0], args[1], args[2]);\n }\n return func.apply(thisArg, args);\n}\n\nexport default apply;\n","/**\n * This method returns `undefined`.\n *\n * @static\n * @memberOf _\n * @since 2.3.0\n * @category Util\n * @example\n *\n * _.times(2, _.noop);\n * // => [undefined, undefined]\n */\nfunction noop() {\n // No operation performed.\n}\n\nexport default noop;\n","/** Used to detect hot functions by number of calls within a span of milliseconds. */\nvar HOT_COUNT = 800,\n HOT_SPAN = 16;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeNow = Date.now;\n\n/**\n * Creates a function that'll short out and invoke `identity` instead\n * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`\n * milliseconds.\n *\n * @private\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new shortable function.\n */\nfunction shortOut(func) {\n var count = 0,\n lastCalled = 0;\n\n return function() {\n var stamp = nativeNow(),\n remaining = HOT_SPAN - (stamp - lastCalled);\n\n lastCalled = stamp;\n if (remaining > 0) {\n if (++count >= HOT_COUNT) {\n return arguments[0];\n }\n } else {\n count = 0;\n }\n return func.apply(undefined, arguments);\n };\n}\n\nexport default shortOut;\n","/**\n * Creates a function that returns `value`.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Util\n * @param {*} value The value to return from the new function.\n * @returns {Function} Returns the new constant function.\n * @example\n *\n * var objects = _.times(2, _.constant({ 'a': 1 }));\n *\n * console.log(objects);\n * // => [{ 'a': 1 }, { 'a': 1 }]\n *\n * console.log(objects[0] === objects[1]);\n * // => true\n */\nfunction constant(value) {\n return function() {\n return value;\n };\n}\n\nexport default constant;\n","import constant from './constant.js';\nimport defineProperty from './_defineProperty.js';\nimport identity from './identity.js';\n\n/**\n * The base implementation of `setToString` without support for hot loop shorting.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar baseSetToString = !defineProperty ? identity : function(func, string) {\n return defineProperty(func, 'toString', {\n 'configurable': true,\n 'enumerable': false,\n 'value': constant(string),\n 'writable': true\n });\n};\n\nexport default baseSetToString;\n","import baseSetToString from './_baseSetToString.js';\nimport shortOut from './_shortOut.js';\n\n/**\n * Sets the `toString` method of `func` to return `string`.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar setToString = shortOut(baseSetToString);\n\nexport default setToString;\n","/**\n * The base implementation of `_.findIndex` and `_.findLastIndex` without\n * support for iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Function} predicate The function invoked per iteration.\n * @param {number} fromIndex The index to search from.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction baseFindIndex(array, predicate, fromIndex, fromRight) {\n var length = array.length,\n index = fromIndex + (fromRight ? 1 : -1);\n\n while ((fromRight ? index-- : ++index < length)) {\n if (predicate(array[index], index, array)) {\n return index;\n }\n }\n return -1;\n}\n\nexport default baseFindIndex;\n","/**\n * The base implementation of `_.isNaN` without support for number objects.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.\n */\nfunction baseIsNaN(value) {\n return value !== value;\n}\n\nexport default baseIsNaN;\n","/**\n * A specialized version of `_.indexOf` which performs strict equality\n * comparisons of values, i.e. `===`.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction strictIndexOf(array, value, fromIndex) {\n var index = fromIndex - 1,\n length = array.length;\n\n while (++index < length) {\n if (array[index] === value) {\n return index;\n }\n }\n return -1;\n}\n\nexport default strictIndexOf;\n","import baseFindIndex from './_baseFindIndex.js';\nimport baseIsNaN from './_baseIsNaN.js';\nimport strictIndexOf from './_strictIndexOf.js';\n\n/**\n * The base implementation of `_.indexOf` without `fromIndex` bounds checks.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction baseIndexOf(array, value, fromIndex) {\n return value === value\n ? strictIndexOf(array, value, fromIndex)\n : baseFindIndex(array, baseIsNaN, fromIndex);\n}\n\nexport default baseIndexOf;\n","import baseIndexOf from './_baseIndexOf.js';\n\n/**\n * A specialized version of `_.includes` for arrays without support for\n * specifying an index to search from.\n *\n * @private\n * @param {Array} [array] The array to inspect.\n * @param {*} target The value to search for.\n * @returns {boolean} Returns `true` if `target` is found, else `false`.\n */\nfunction arrayIncludes(array, value) {\n var length = array == null ? 0 : array.length;\n return !!length && baseIndexOf(array, value, 0) > -1;\n}\n\nexport default arrayIncludes;\n","import apply from './_apply.js';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * A specialized version of `baseRest` which transforms the rest array.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @param {Function} transform The rest array transform.\n * @returns {Function} Returns the new function.\n */\nfunction overRest(func, start, transform) {\n start = nativeMax(start === undefined ? (func.length - 1) : start, 0);\n return function() {\n var args = arguments,\n index = -1,\n length = nativeMax(args.length - start, 0),\n array = Array(length);\n\n while (++index < length) {\n array[index] = args[start + index];\n }\n index = -1;\n var otherArgs = Array(start + 1);\n while (++index < start) {\n otherArgs[index] = args[index];\n }\n otherArgs[start] = transform(array);\n return apply(func, this, otherArgs);\n };\n}\n\nexport default overRest;\n","import identity from './identity.js';\nimport overRest from './_overRest.js';\nimport setToString from './_setToString.js';\n\n/**\n * The base implementation of `_.rest` which doesn't validate or coerce arguments.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @returns {Function} Returns the new function.\n */\nfunction baseRest(func, start) {\n return setToString(overRest(func, start, identity), func + '');\n}\n\nexport default baseRest;\n","import eq from './eq.js';\nimport isArrayLike from './isArrayLike.js';\nimport isIndex from './_isIndex.js';\nimport isObject from './isObject.js';\n\n/**\n * Checks if the given arguments are from an iteratee call.\n *\n * @private\n * @param {*} value The potential iteratee value argument.\n * @param {*} index The potential iteratee index or key argument.\n * @param {*} object The potential iteratee object argument.\n * @returns {boolean} Returns `true` if the arguments are from an iteratee call,\n * else `false`.\n */\nfunction isIterateeCall(value, index, object) {\n if (!isObject(object)) {\n return false;\n }\n var type = typeof index;\n if (type == 'number'\n ? (isArrayLike(object) && isIndex(index, object.length))\n : (type == 'string' && index in object)\n ) {\n return eq(object[index], value);\n }\n return false;\n}\n\nexport default isIterateeCall;\n","import Symbol from './_Symbol.js';\nimport isArguments from './isArguments.js';\nimport isArray from './isArray.js';\n\n/** Built-in value references. */\nvar spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined;\n\n/**\n * Checks if `value` is a flattenable `arguments` object or array.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.\n */\nfunction isFlattenable(value) {\n return isArray(value) || isArguments(value) ||\n !!(spreadableSymbol && value && value[spreadableSymbol]);\n}\n\nexport default isFlattenable;\n","import arrayPush from './_arrayPush.js';\nimport isFlattenable from './_isFlattenable.js';\n\n/**\n * The base implementation of `_.flatten` with support for restricting flattening.\n *\n * @private\n * @param {Array} array The array to flatten.\n * @param {number} depth The maximum recursion depth.\n * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.\n * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.\n * @param {Array} [result=[]] The initial result value.\n * @returns {Array} Returns the new flattened array.\n */\nfunction baseFlatten(array, depth, predicate, isStrict, result) {\n var index = -1,\n length = array.length;\n\n predicate || (predicate = isFlattenable);\n result || (result = []);\n\n while (++index < length) {\n var value = array[index];\n if (depth > 0 && predicate(value)) {\n if (depth > 1) {\n // Recursively flatten arrays (susceptible to call stack limits).\n baseFlatten(value, depth - 1, predicate, isStrict, result);\n } else {\n arrayPush(result, value);\n }\n } else if (!isStrict) {\n result[result.length] = value;\n }\n }\n return result;\n}\n\nexport default baseFlatten;\n","import baseFlatten from './_baseFlatten.js';\n\n/**\n * Flattens `array` a single level deep.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to flatten.\n * @returns {Array} Returns the new flattened array.\n * @example\n *\n * _.flatten([1, [2, [3, [4]], 5]]);\n * // => [1, 2, [3, [4]], 5]\n */\nfunction flatten(array) {\n var length = array == null ? 0 : array.length;\n return length ? baseFlatten(array, 1) : [];\n}\n\nexport default flatten;\n","/**\n * The base implementation of `_.slice` without an iteratee call guard.\n *\n * @private\n * @param {Array} array The array to slice.\n * @param {number} [start=0] The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns the slice of `array`.\n */\nfunction baseSlice(array, start, end) {\n var index = -1,\n length = array.length;\n\n if (start < 0) {\n start = -start > length ? 0 : (length + start);\n }\n end = end > length ? length : end;\n if (end < 0) {\n end += length;\n }\n length = start > end ? 0 : ((end - start) >>> 0);\n start >>>= 0;\n\n var result = Array(length);\n while (++index < length) {\n result[index] = array[index + start];\n }\n return result;\n}\n\nexport default baseSlice;\n","import baseSlice from './_baseSlice.js';\n\n/**\n * Casts `array` to a slice if it's needed.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {number} start The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns the cast slice.\n */\nfunction castSlice(array, start, end) {\n var length = array.length;\n end = end === undefined ? length : end;\n return (!start && end >= length) ? array : baseSlice(array, start, end);\n}\n\nexport default castSlice;\n","/** Used to compose unicode character classes. */\nvar rsAstralRange = '\\\\ud800-\\\\udfff',\n rsComboMarksRange = '\\\\u0300-\\\\u036f',\n reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,\n rsVarRange = '\\\\ufe0e\\\\ufe0f';\n\n/** Used to compose unicode capture groups. */\nvar rsZWJ = '\\\\u200d';\n\n/** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */\nvar reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');\n\n/**\n * Checks if `string` contains Unicode symbols.\n *\n * @private\n * @param {string} string The string to inspect.\n * @returns {boolean} Returns `true` if a symbol is found, else `false`.\n */\nfunction hasUnicode(string) {\n return reHasUnicode.test(string);\n}\n\nexport default hasUnicode;\n","/**\n * Converts an ASCII `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\nfunction asciiToArray(string) {\n return string.split('');\n}\n\nexport default asciiToArray;\n","/** Used to compose unicode character classes. */\nvar rsAstralRange = '\\\\ud800-\\\\udfff',\n rsComboMarksRange = '\\\\u0300-\\\\u036f',\n reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,\n rsVarRange = '\\\\ufe0e\\\\ufe0f';\n\n/** Used to compose unicode capture groups. */\nvar rsAstral = '[' + rsAstralRange + ']',\n rsCombo = '[' + rsComboRange + ']',\n rsFitz = '\\\\ud83c[\\\\udffb-\\\\udfff]',\n rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',\n rsNonAstral = '[^' + rsAstralRange + ']',\n rsRegional = '(?:\\\\ud83c[\\\\udde6-\\\\uddff]){2}',\n rsSurrPair = '[\\\\ud800-\\\\udbff][\\\\udc00-\\\\udfff]',\n rsZWJ = '\\\\u200d';\n\n/** Used to compose unicode regexes. */\nvar reOptMod = rsModifier + '?',\n rsOptVar = '[' + rsVarRange + ']?',\n rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',\n rsSeq = rsOptVar + reOptMod + rsOptJoin,\n rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';\n\n/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */\nvar reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');\n\n/**\n * Converts a Unicode `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\nfunction unicodeToArray(string) {\n return string.match(reUnicode) || [];\n}\n\nexport default unicodeToArray;\n","import asciiToArray from './_asciiToArray.js';\nimport hasUnicode from './_hasUnicode.js';\nimport unicodeToArray from './_unicodeToArray.js';\n\n/**\n * Converts `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\nfunction stringToArray(string) {\n return hasUnicode(string)\n ? unicodeToArray(string)\n : asciiToArray(string);\n}\n\nexport default stringToArray;\n","import castSlice from './_castSlice.js';\nimport hasUnicode from './_hasUnicode.js';\nimport stringToArray from './_stringToArray.js';\nimport toString from './toString.js';\n\n/**\n * Creates a function like `_.lowerFirst`.\n *\n * @private\n * @param {string} methodName The name of the `String` case method to use.\n * @returns {Function} Returns the new case function.\n */\nfunction createCaseFirst(methodName) {\n return function(string) {\n string = toString(string);\n\n var strSymbols = hasUnicode(string)\n ? stringToArray(string)\n : undefined;\n\n var chr = strSymbols\n ? strSymbols[0]\n : string.charAt(0);\n\n var trailing = strSymbols\n ? castSlice(strSymbols, 1).join('')\n : string.slice(1);\n\n return chr[methodName]() + trailing;\n };\n}\n\nexport default createCaseFirst;\n","import createCaseFirst from './_createCaseFirst.js';\n\n/**\n * Converts the first character of `string` to upper case.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the converted string.\n * @example\n *\n * _.upperFirst('fred');\n * // => 'Fred'\n *\n * _.upperFirst('FRED');\n * // => 'FRED'\n */\nvar upperFirst = createCaseFirst('toUpperCase');\n\nexport default upperFirst;\n","/**\n * A specialized version of `_.reduce` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {*} [accumulator] The initial value.\n * @param {boolean} [initAccum] Specify using the first element of `array` as\n * the initial value.\n * @returns {*} Returns the accumulated value.\n */\nfunction arrayReduce(array, iteratee, accumulator, initAccum) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n if (initAccum && length) {\n accumulator = array[++index];\n }\n while (++index < length) {\n accumulator = iteratee(accumulator, array[index], index, array);\n }\n return accumulator;\n}\n\nexport default arrayReduce;\n","/**\n * The base implementation of `_.propertyOf` without support for deep paths.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Function} Returns the new accessor function.\n */\nfunction basePropertyOf(object) {\n return function(key) {\n return object == null ? undefined : object[key];\n };\n}\n\nexport default basePropertyOf;\n","import basePropertyOf from './_basePropertyOf.js';\n\n/** Used to map Latin Unicode letters to basic Latin letters. */\nvar deburredLetters = {\n // Latin-1 Supplement block.\n '\\xc0': 'A', '\\xc1': 'A', '\\xc2': 'A', '\\xc3': 'A', '\\xc4': 'A', '\\xc5': 'A',\n '\\xe0': 'a', '\\xe1': 'a', '\\xe2': 'a', '\\xe3': 'a', '\\xe4': 'a', '\\xe5': 'a',\n '\\xc7': 'C', '\\xe7': 'c',\n '\\xd0': 'D', '\\xf0': 'd',\n '\\xc8': 'E', '\\xc9': 'E', '\\xca': 'E', '\\xcb': 'E',\n '\\xe8': 'e', '\\xe9': 'e', '\\xea': 'e', '\\xeb': 'e',\n '\\xcc': 'I', '\\xcd': 'I', '\\xce': 'I', '\\xcf': 'I',\n '\\xec': 'i', '\\xed': 'i', '\\xee': 'i', '\\xef': 'i',\n '\\xd1': 'N', '\\xf1': 'n',\n '\\xd2': 'O', '\\xd3': 'O', '\\xd4': 'O', '\\xd5': 'O', '\\xd6': 'O', '\\xd8': 'O',\n '\\xf2': 'o', '\\xf3': 'o', '\\xf4': 'o', '\\xf5': 'o', '\\xf6': 'o', '\\xf8': 'o',\n '\\xd9': 'U', '\\xda': 'U', '\\xdb': 'U', '\\xdc': 'U',\n '\\xf9': 'u', '\\xfa': 'u', '\\xfb': 'u', '\\xfc': 'u',\n '\\xdd': 'Y', '\\xfd': 'y', '\\xff': 'y',\n '\\xc6': 'Ae', '\\xe6': 'ae',\n '\\xde': 'Th', '\\xfe': 'th',\n '\\xdf': 'ss',\n // Latin Extended-A block.\n '\\u0100': 'A', '\\u0102': 'A', '\\u0104': 'A',\n '\\u0101': 'a', '\\u0103': 'a', '\\u0105': 'a',\n '\\u0106': 'C', '\\u0108': 'C', '\\u010a': 'C', '\\u010c': 'C',\n '\\u0107': 'c', '\\u0109': 'c', '\\u010b': 'c', '\\u010d': 'c',\n '\\u010e': 'D', '\\u0110': 'D', '\\u010f': 'd', '\\u0111': 'd',\n '\\u0112': 'E', '\\u0114': 'E', '\\u0116': 'E', '\\u0118': 'E', '\\u011a': 'E',\n '\\u0113': 'e', '\\u0115': 'e', '\\u0117': 'e', '\\u0119': 'e', '\\u011b': 'e',\n '\\u011c': 'G', '\\u011e': 'G', '\\u0120': 'G', '\\u0122': 'G',\n '\\u011d': 'g', '\\u011f': 'g', '\\u0121': 'g', '\\u0123': 'g',\n '\\u0124': 'H', '\\u0126': 'H', '\\u0125': 'h', '\\u0127': 'h',\n '\\u0128': 'I', '\\u012a': 'I', '\\u012c': 'I', '\\u012e': 'I', '\\u0130': 'I',\n '\\u0129': 'i', '\\u012b': 'i', '\\u012d': 'i', '\\u012f': 'i', '\\u0131': 'i',\n '\\u0134': 'J', '\\u0135': 'j',\n '\\u0136': 'K', '\\u0137': 'k', '\\u0138': 'k',\n '\\u0139': 'L', '\\u013b': 'L', '\\u013d': 'L', '\\u013f': 'L', '\\u0141': 'L',\n '\\u013a': 'l', '\\u013c': 'l', '\\u013e': 'l', '\\u0140': 'l', '\\u0142': 'l',\n '\\u0143': 'N', '\\u0145': 'N', '\\u0147': 'N', '\\u014a': 'N',\n '\\u0144': 'n', '\\u0146': 'n', '\\u0148': 'n', '\\u014b': 'n',\n '\\u014c': 'O', '\\u014e': 'O', '\\u0150': 'O',\n '\\u014d': 'o', '\\u014f': 'o', '\\u0151': 'o',\n '\\u0154': 'R', '\\u0156': 'R', '\\u0158': 'R',\n '\\u0155': 'r', '\\u0157': 'r', '\\u0159': 'r',\n '\\u015a': 'S', '\\u015c': 'S', '\\u015e': 'S', '\\u0160': 'S',\n '\\u015b': 's', '\\u015d': 's', '\\u015f': 's', '\\u0161': 's',\n '\\u0162': 'T', '\\u0164': 'T', '\\u0166': 'T',\n '\\u0163': 't', '\\u0165': 't', '\\u0167': 't',\n '\\u0168': 'U', '\\u016a': 'U', '\\u016c': 'U', '\\u016e': 'U', '\\u0170': 'U', '\\u0172': 'U',\n '\\u0169': 'u', '\\u016b': 'u', '\\u016d': 'u', '\\u016f': 'u', '\\u0171': 'u', '\\u0173': 'u',\n '\\u0174': 'W', '\\u0175': 'w',\n '\\u0176': 'Y', '\\u0177': 'y', '\\u0178': 'Y',\n '\\u0179': 'Z', '\\u017b': 'Z', '\\u017d': 'Z',\n '\\u017a': 'z', '\\u017c': 'z', '\\u017e': 'z',\n '\\u0132': 'IJ', '\\u0133': 'ij',\n '\\u0152': 'Oe', '\\u0153': 'oe',\n '\\u0149': \"'n\", '\\u017f': 's'\n};\n\n/**\n * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A\n * letters to basic Latin letters.\n *\n * @private\n * @param {string} letter The matched letter to deburr.\n * @returns {string} Returns the deburred letter.\n */\nvar deburrLetter = basePropertyOf(deburredLetters);\n\nexport default deburrLetter;\n","import deburrLetter from './_deburrLetter.js';\nimport toString from './toString.js';\n\n/** Used to match Latin Unicode letters (excluding mathematical operators). */\nvar reLatin = /[\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\xff\\u0100-\\u017f]/g;\n\n/** Used to compose unicode character classes. */\nvar rsComboMarksRange = '\\\\u0300-\\\\u036f',\n reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange;\n\n/** Used to compose unicode capture groups. */\nvar rsCombo = '[' + rsComboRange + ']';\n\n/**\n * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and\n * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).\n */\nvar reComboMark = RegExp(rsCombo, 'g');\n\n/**\n * Deburrs `string` by converting\n * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)\n * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)\n * letters to basic Latin letters and removing\n * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to deburr.\n * @returns {string} Returns the deburred string.\n * @example\n *\n * _.deburr('déjà vu');\n * // => 'deja vu'\n */\nfunction deburr(string) {\n string = toString(string);\n return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');\n}\n\nexport default deburr;\n","/** Used to match words composed of alphanumeric characters. */\nvar reAsciiWord = /[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\x7f]+/g;\n\n/**\n * Splits an ASCII `string` into an array of its words.\n *\n * @private\n * @param {string} The string to inspect.\n * @returns {Array} Returns the words of `string`.\n */\nfunction asciiWords(string) {\n return string.match(reAsciiWord) || [];\n}\n\nexport default asciiWords;\n","/** Used to detect strings that need a more robust regexp to match words. */\nvar reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;\n\n/**\n * Checks if `string` contains a word composed of Unicode symbols.\n *\n * @private\n * @param {string} string The string to inspect.\n * @returns {boolean} Returns `true` if a word is found, else `false`.\n */\nfunction hasUnicodeWord(string) {\n return reHasUnicodeWord.test(string);\n}\n\nexport default hasUnicodeWord;\n","/** Used to compose unicode character classes. */\nvar rsAstralRange = '\\\\ud800-\\\\udfff',\n rsComboMarksRange = '\\\\u0300-\\\\u036f',\n reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,\n rsDingbatRange = '\\\\u2700-\\\\u27bf',\n rsLowerRange = 'a-z\\\\xdf-\\\\xf6\\\\xf8-\\\\xff',\n rsMathOpRange = '\\\\xac\\\\xb1\\\\xd7\\\\xf7',\n rsNonCharRange = '\\\\x00-\\\\x2f\\\\x3a-\\\\x40\\\\x5b-\\\\x60\\\\x7b-\\\\xbf',\n rsPunctuationRange = '\\\\u2000-\\\\u206f',\n rsSpaceRange = ' \\\\t\\\\x0b\\\\f\\\\xa0\\\\ufeff\\\\n\\\\r\\\\u2028\\\\u2029\\\\u1680\\\\u180e\\\\u2000\\\\u2001\\\\u2002\\\\u2003\\\\u2004\\\\u2005\\\\u2006\\\\u2007\\\\u2008\\\\u2009\\\\u200a\\\\u202f\\\\u205f\\\\u3000',\n rsUpperRange = 'A-Z\\\\xc0-\\\\xd6\\\\xd8-\\\\xde',\n rsVarRange = '\\\\ufe0e\\\\ufe0f',\n rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;\n\n/** Used to compose unicode capture groups. */\nvar rsApos = \"['\\u2019]\",\n rsBreak = '[' + rsBreakRange + ']',\n rsCombo = '[' + rsComboRange + ']',\n rsDigits = '\\\\d+',\n rsDingbat = '[' + rsDingbatRange + ']',\n rsLower = '[' + rsLowerRange + ']',\n rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',\n rsFitz = '\\\\ud83c[\\\\udffb-\\\\udfff]',\n rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',\n rsNonAstral = '[^' + rsAstralRange + ']',\n rsRegional = '(?:\\\\ud83c[\\\\udde6-\\\\uddff]){2}',\n rsSurrPair = '[\\\\ud800-\\\\udbff][\\\\udc00-\\\\udfff]',\n rsUpper = '[' + rsUpperRange + ']',\n rsZWJ = '\\\\u200d';\n\n/** Used to compose unicode regexes. */\nvar rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')',\n rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')',\n rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',\n rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',\n reOptMod = rsModifier + '?',\n rsOptVar = '[' + rsVarRange + ']?',\n rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',\n rsOrdLower = '\\\\d*(?:1st|2nd|3rd|(?![123])\\\\dth)(?=\\\\b|[A-Z_])',\n rsOrdUpper = '\\\\d*(?:1ST|2ND|3RD|(?![123])\\\\dTH)(?=\\\\b|[a-z_])',\n rsSeq = rsOptVar + reOptMod + rsOptJoin,\n rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq;\n\n/** Used to match complex or compound words. */\nvar reUnicodeWord = RegExp([\n rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',\n rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')',\n rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower,\n rsUpper + '+' + rsOptContrUpper,\n rsOrdUpper,\n rsOrdLower,\n rsDigits,\n rsEmoji\n].join('|'), 'g');\n\n/**\n * Splits a Unicode `string` into an array of its words.\n *\n * @private\n * @param {string} The string to inspect.\n * @returns {Array} Returns the words of `string`.\n */\nfunction unicodeWords(string) {\n return string.match(reUnicodeWord) || [];\n}\n\nexport default unicodeWords;\n","import asciiWords from './_asciiWords.js';\nimport hasUnicodeWord from './_hasUnicodeWord.js';\nimport toString from './toString.js';\nimport unicodeWords from './_unicodeWords.js';\n\n/**\n * Splits `string` into an array of its words.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to inspect.\n * @param {RegExp|string} [pattern] The pattern to match words.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Array} Returns the words of `string`.\n * @example\n *\n * _.words('fred, barney, & pebbles');\n * // => ['fred', 'barney', 'pebbles']\n *\n * _.words('fred, barney, & pebbles', /[^, ]+/g);\n * // => ['fred', 'barney', '&', 'pebbles']\n */\nfunction words(string, pattern, guard) {\n string = toString(string);\n pattern = guard ? undefined : pattern;\n\n if (pattern === undefined) {\n return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);\n }\n return string.match(pattern) || [];\n}\n\nexport default words;\n","import arrayReduce from './_arrayReduce.js';\nimport deburr from './deburr.js';\nimport words from './words.js';\n\n/** Used to compose unicode capture groups. */\nvar rsApos = \"['\\u2019]\";\n\n/** Used to match apostrophes. */\nvar reApos = RegExp(rsApos, 'g');\n\n/**\n * Creates a function like `_.camelCase`.\n *\n * @private\n * @param {Function} callback The function to combine each word.\n * @returns {Function} Returns the new compounder function.\n */\nfunction createCompounder(callback) {\n return function(string) {\n return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');\n };\n}\n\nexport default createCompounder;\n","import baseSlice from './_baseSlice.js';\nimport isIterateeCall from './_isIterateeCall.js';\nimport toInteger from './toInteger.js';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeCeil = Math.ceil,\n nativeMax = Math.max;\n\n/**\n * Creates an array of elements split into groups the length of `size`.\n * If `array` can't be split evenly, the final chunk will be the remaining\n * elements.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to process.\n * @param {number} [size=1] The length of each chunk\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Array} Returns the new array of chunks.\n * @example\n *\n * _.chunk(['a', 'b', 'c', 'd'], 2);\n * // => [['a', 'b'], ['c', 'd']]\n *\n * _.chunk(['a', 'b', 'c', 'd'], 3);\n * // => [['a', 'b', 'c'], ['d']]\n */\nfunction chunk(array, size, guard) {\n if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) {\n size = 1;\n } else {\n size = nativeMax(toInteger(size), 0);\n }\n var length = array == null ? 0 : array.length;\n if (!length || size < 1) {\n return [];\n }\n var index = 0,\n resIndex = 0,\n result = Array(nativeCeil(length / size));\n\n while (index < length) {\n result[resIndex++] = baseSlice(array, index, (index += size));\n }\n return result;\n}\n\nexport default chunk;\n","import isArrayLike from './isArrayLike.js';\nimport isObjectLike from './isObjectLike.js';\n\n/**\n * This method is like `_.isArrayLike` except that it also checks if `value`\n * is an object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array-like object,\n * else `false`.\n * @example\n *\n * _.isArrayLikeObject([1, 2, 3]);\n * // => true\n *\n * _.isArrayLikeObject(document.body.children);\n * // => true\n *\n * _.isArrayLikeObject('abc');\n * // => false\n *\n * _.isArrayLikeObject(_.noop);\n * // => false\n */\nfunction isArrayLikeObject(value) {\n return isObjectLike(value) && isArrayLike(value);\n}\n\nexport default isArrayLikeObject;\n","/**\n * This function is like `arrayIncludes` except that it accepts a comparator.\n *\n * @private\n * @param {Array} [array] The array to inspect.\n * @param {*} target The value to search for.\n * @param {Function} comparator The comparator invoked per element.\n * @returns {boolean} Returns `true` if `target` is found, else `false`.\n */\nfunction arrayIncludesWith(array, value, comparator) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (comparator(value, array[index])) {\n return true;\n }\n }\n return false;\n}\n\nexport default arrayIncludesWith;\n","import SetCache from './_SetCache.js';\nimport arrayIncludes from './_arrayIncludes.js';\nimport arrayIncludesWith from './_arrayIncludesWith.js';\nimport arrayMap from './_arrayMap.js';\nimport baseUnary from './_baseUnary.js';\nimport cacheHas from './_cacheHas.js';\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/**\n * The base implementation of methods like `_.difference` without support\n * for excluding multiple arrays or iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Array} values The values to exclude.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of filtered values.\n */\nfunction baseDifference(array, values, iteratee, comparator) {\n var index = -1,\n includes = arrayIncludes,\n isCommon = true,\n length = array.length,\n result = [],\n valuesLength = values.length;\n\n if (!length) {\n return result;\n }\n if (iteratee) {\n values = arrayMap(values, baseUnary(iteratee));\n }\n if (comparator) {\n includes = arrayIncludesWith;\n isCommon = false;\n }\n else if (values.length >= LARGE_ARRAY_SIZE) {\n includes = cacheHas;\n isCommon = false;\n values = new SetCache(values);\n }\n outer:\n while (++index < length) {\n var value = array[index],\n computed = iteratee == null ? value : iteratee(value);\n\n value = (comparator || value !== 0) ? value : 0;\n if (isCommon && computed === computed) {\n var valuesIndex = valuesLength;\n while (valuesIndex--) {\n if (values[valuesIndex] === computed) {\n continue outer;\n }\n }\n result.push(value);\n }\n else if (!includes(values, computed, comparator)) {\n result.push(value);\n }\n }\n return result;\n}\n\nexport default baseDifference;\n","import baseDifference from './_baseDifference.js';\nimport baseFlatten from './_baseFlatten.js';\nimport baseRest from './_baseRest.js';\nimport isArrayLikeObject from './isArrayLikeObject.js';\n\n/**\n * Creates an array of `array` values not included in the other given arrays\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons. The order and references of result values are\n * determined by the first array.\n *\n * **Note:** Unlike `_.pullAll`, this method returns a new array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {...Array} [values] The values to exclude.\n * @returns {Array} Returns the new array of filtered values.\n * @see _.without, _.xor\n * @example\n *\n * _.difference([2, 1], [2, 3]);\n * // => [1]\n */\nvar difference = baseRest(function(array, values) {\n return isArrayLikeObject(array)\n ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))\n : [];\n});\n\nexport default difference;\n","import baseEach from './_baseEach.js';\nimport isArrayLike from './isArrayLike.js';\n\n/**\n * The base implementation of `_.map` without support for iteratee shorthands.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction baseMap(collection, iteratee) {\n var index = -1,\n result = isArrayLike(collection) ? Array(collection.length) : [];\n\n baseEach(collection, function(value, key, collection) {\n result[++index] = iteratee(value, key, collection);\n });\n return result;\n}\n\nexport default baseMap;\n","import baseAssignValue from './_baseAssignValue.js';\nimport createAggregator from './_createAggregator.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Creates an object composed of keys generated from the results of running\n * each element of `collection` thru `iteratee`. The order of grouped values\n * is determined by the order they occur in `collection`. The corresponding\n * value of each key is an array of elements responsible for generating the\n * key. The iteratee is invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The iteratee to transform keys.\n * @returns {Object} Returns the composed aggregate object.\n * @example\n *\n * _.groupBy([6.1, 4.2, 6.3], Math.floor);\n * // => { '4': [4.2], '6': [6.1, 6.3] }\n *\n * // The `_.property` iteratee shorthand.\n * _.groupBy(['one', 'two', 'three'], 'length');\n * // => { '3': ['one', 'two'], '5': ['three'] }\n */\nvar groupBy = createAggregator(function(result, value, key) {\n if (hasOwnProperty.call(result, key)) {\n result[key].push(value);\n } else {\n baseAssignValue(result, key, [value]);\n }\n});\n\nexport default groupBy;\n","import baseAssignValue from './_baseAssignValue.js';\nimport baseForOwn from './_baseForOwn.js';\nimport baseIteratee from './_baseIteratee.js';\n\n/**\n * Creates an object with the same keys as `object` and values generated\n * by running each own enumerable string keyed property of `object` thru\n * `iteratee`. The iteratee is invoked with three arguments:\n * (value, key, object).\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Object} Returns the new mapped object.\n * @see _.mapKeys\n * @example\n *\n * var users = {\n * 'fred': { 'user': 'fred', 'age': 40 },\n * 'pebbles': { 'user': 'pebbles', 'age': 1 }\n * };\n *\n * _.mapValues(users, function(o) { return o.age; });\n * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)\n *\n * // The `_.property` iteratee shorthand.\n * _.mapValues(users, 'age');\n * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)\n */\nfunction mapValues(object, iteratee) {\n var result = {};\n iteratee = baseIteratee(iteratee, 3);\n\n baseForOwn(object, function(value, key, object) {\n baseAssignValue(result, key, iteratee(value, key, object));\n });\n return result;\n}\n\nexport default mapValues;\n","/**\n * The base implementation of `_.sortBy` which uses `comparer` to define the\n * sort order of `array` and replaces criteria objects with their corresponding\n * values.\n *\n * @private\n * @param {Array} array The array to sort.\n * @param {Function} comparer The function to define sort order.\n * @returns {Array} Returns `array`.\n */\nfunction baseSortBy(array, comparer) {\n var length = array.length;\n\n array.sort(comparer);\n while (length--) {\n array[length] = array[length].value;\n }\n return array;\n}\n\nexport default baseSortBy;\n","import isSymbol from './isSymbol.js';\n\n/**\n * Compares values to sort them in ascending order.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {number} Returns the sort order indicator for `value`.\n */\nfunction compareAscending(value, other) {\n if (value !== other) {\n var valIsDefined = value !== undefined,\n valIsNull = value === null,\n valIsReflexive = value === value,\n valIsSymbol = isSymbol(value);\n\n var othIsDefined = other !== undefined,\n othIsNull = other === null,\n othIsReflexive = other === other,\n othIsSymbol = isSymbol(other);\n\n if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||\n (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||\n (valIsNull && othIsDefined && othIsReflexive) ||\n (!valIsDefined && othIsReflexive) ||\n !valIsReflexive) {\n return 1;\n }\n if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||\n (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||\n (othIsNull && valIsDefined && valIsReflexive) ||\n (!othIsDefined && valIsReflexive) ||\n !othIsReflexive) {\n return -1;\n }\n }\n return 0;\n}\n\nexport default compareAscending;\n","import compareAscending from './_compareAscending.js';\n\n/**\n * Used by `_.orderBy` to compare multiple properties of a value to another\n * and stable sort them.\n *\n * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,\n * specify an order of \"desc\" for descending or \"asc\" for ascending sort order\n * of corresponding values.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {boolean[]|string[]} orders The order to sort by for each property.\n * @returns {number} Returns the sort order indicator for `object`.\n */\nfunction compareMultiple(object, other, orders) {\n var index = -1,\n objCriteria = object.criteria,\n othCriteria = other.criteria,\n length = objCriteria.length,\n ordersLength = orders.length;\n\n while (++index < length) {\n var result = compareAscending(objCriteria[index], othCriteria[index]);\n if (result) {\n if (index >= ordersLength) {\n return result;\n }\n var order = orders[index];\n return result * (order == 'desc' ? -1 : 1);\n }\n }\n // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications\n // that causes it, under certain circumstances, to provide the same value for\n // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247\n // for more details.\n //\n // This also ensures a stable sort in V8 and other engines.\n // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.\n return object.index - other.index;\n}\n\nexport default compareMultiple;\n","import arrayMap from './_arrayMap.js';\nimport baseGet from './_baseGet.js';\nimport baseIteratee from './_baseIteratee.js';\nimport baseMap from './_baseMap.js';\nimport baseSortBy from './_baseSortBy.js';\nimport baseUnary from './_baseUnary.js';\nimport compareMultiple from './_compareMultiple.js';\nimport identity from './identity.js';\nimport isArray from './isArray.js';\n\n/**\n * The base implementation of `_.orderBy` without param guards.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.\n * @param {string[]} orders The sort orders of `iteratees`.\n * @returns {Array} Returns the new sorted array.\n */\nfunction baseOrderBy(collection, iteratees, orders) {\n if (iteratees.length) {\n iteratees = arrayMap(iteratees, function(iteratee) {\n if (isArray(iteratee)) {\n return function(value) {\n return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee);\n }\n }\n return iteratee;\n });\n } else {\n iteratees = [identity];\n }\n\n var index = -1;\n iteratees = arrayMap(iteratees, baseUnary(baseIteratee));\n\n var result = baseMap(collection, function(value, key, collection) {\n var criteria = arrayMap(iteratees, function(iteratee) {\n return iteratee(value);\n });\n return { 'criteria': criteria, 'index': ++index, 'value': value };\n });\n\n return baseSortBy(result, function(object, other) {\n return compareMultiple(object, other, orders);\n });\n}\n\nexport default baseOrderBy;\n","import baseFlatten from './_baseFlatten.js';\nimport baseOrderBy from './_baseOrderBy.js';\nimport baseRest from './_baseRest.js';\nimport isIterateeCall from './_isIterateeCall.js';\n\n/**\n * Creates an array of elements, sorted in ascending order by the results of\n * running each element in a collection thru each iteratee. This method\n * performs a stable sort, that is, it preserves the original sort order of\n * equal elements. The iteratees are invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {...(Function|Function[])} [iteratees=[_.identity]]\n * The iteratees to sort by.\n * @returns {Array} Returns the new sorted array.\n * @example\n *\n * var users = [\n * { 'user': 'fred', 'age': 48 },\n * { 'user': 'barney', 'age': 36 },\n * { 'user': 'fred', 'age': 30 },\n * { 'user': 'barney', 'age': 34 }\n * ];\n *\n * _.sortBy(users, [function(o) { return o.user; }]);\n * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 30]]\n *\n * _.sortBy(users, ['user', 'age']);\n * // => objects for [['barney', 34], ['barney', 36], ['fred', 30], ['fred', 48]]\n */\nvar sortBy = baseRest(function(collection, iteratees) {\n if (collection == null) {\n return [];\n }\n var length = iteratees.length;\n if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {\n iteratees = [];\n } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {\n iteratees = [iteratees[0]];\n }\n return baseOrderBy(collection, baseFlatten(iteratees, 1), []);\n});\n\nexport default sortBy;\n","import createCompounder from './_createCompounder.js';\nimport upperFirst from './upperFirst.js';\n\n/**\n * Converts `string` to\n * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).\n *\n * @static\n * @memberOf _\n * @since 3.1.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the start cased string.\n * @example\n *\n * _.startCase('--foo-bar--');\n * // => 'Foo Bar'\n *\n * _.startCase('fooBar');\n * // => 'Foo Bar'\n *\n * _.startCase('__FOO_BAR__');\n * // => 'FOO BAR'\n */\nvar startCase = createCompounder(function(result, word, index) {\n return result + (index ? ' ' : '') + upperFirst(word);\n});\n\nexport default startCase;\n","import Set from './_Set.js';\nimport noop from './noop.js';\nimport setToArray from './_setToArray.js';\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0;\n\n/**\n * Creates a set object of `values`.\n *\n * @private\n * @param {Array} values The values to add to the set.\n * @returns {Object} Returns the new set.\n */\nvar createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {\n return new Set(values);\n};\n\nexport default createSet;\n","import SetCache from './_SetCache.js';\nimport arrayIncludes from './_arrayIncludes.js';\nimport arrayIncludesWith from './_arrayIncludesWith.js';\nimport cacheHas from './_cacheHas.js';\nimport createSet from './_createSet.js';\nimport setToArray from './_setToArray.js';\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/**\n * The base implementation of `_.uniqBy` without support for iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n */\nfunction baseUniq(array, iteratee, comparator) {\n var index = -1,\n includes = arrayIncludes,\n length = array.length,\n isCommon = true,\n result = [],\n seen = result;\n\n if (comparator) {\n isCommon = false;\n includes = arrayIncludesWith;\n }\n else if (length >= LARGE_ARRAY_SIZE) {\n var set = iteratee ? null : createSet(array);\n if (set) {\n return setToArray(set);\n }\n isCommon = false;\n includes = cacheHas;\n seen = new SetCache;\n }\n else {\n seen = iteratee ? [] : result;\n }\n outer:\n while (++index < length) {\n var value = array[index],\n computed = iteratee ? iteratee(value) : value;\n\n value = (comparator || value !== 0) ? value : 0;\n if (isCommon && computed === computed) {\n var seenIndex = seen.length;\n while (seenIndex--) {\n if (seen[seenIndex] === computed) {\n continue outer;\n }\n }\n if (iteratee) {\n seen.push(computed);\n }\n result.push(value);\n }\n else if (!includes(seen, computed, comparator)) {\n if (seen !== result) {\n seen.push(computed);\n }\n result.push(value);\n }\n }\n return result;\n}\n\nexport default baseUniq;\n","import baseUniq from './_baseUniq.js';\n\n/**\n * Creates a duplicate-free version of an array, using\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons, in which only the first occurrence of each element\n * is kept. The order of result values is determined by the order they occur\n * in the array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @returns {Array} Returns the new duplicate free array.\n * @example\n *\n * _.uniq([2, 1, 2]);\n * // => [2, 1]\n */\nfunction uniq(array) {\n return (array && array.length) ? baseUniq(array) : [];\n}\n\nexport default uniq;\n","import baseIteratee from './_baseIteratee.js';\nimport baseUniq from './_baseUniq.js';\n\n/**\n * This method is like `_.uniq` except that it accepts `iteratee` which is\n * invoked for each element in `array` to generate the criterion by which\n * uniqueness is computed. The order of result values is determined by the\n * order they occur in the array. The iteratee is invoked with one argument:\n * (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n * @example\n *\n * _.uniqBy([2.1, 1.2, 2.3], Math.floor);\n * // => [2.1, 1.2]\n *\n * // The `_.property` iteratee shorthand.\n * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');\n * // => [{ 'x': 1 }, { 'x': 2 }]\n */\nfunction uniqBy(array, iteratee) {\n return (array && array.length) ? baseUniq(array, baseIteratee(iteratee, 2)) : [];\n}\n\nexport default uniqBy;\n","import Bluebird from 'bluebird';\n\nconst { map, mapSeries } = Bluebird;\n\nexport { map, mapSeries };\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const DATA_POINTS = gql`\n query TranscendCliDataPoints(\n $filterBy: DataPointFiltersInput\n $first: Int!\n $offset: Int!\n ) {\n dataPoints(\n filterBy: $filterBy\n first: $first\n offset: $offset\n useMaster: false\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n title {\n defaultMessage\n }\n description {\n defaultMessage\n }\n owners {\n email\n }\n teams {\n name\n }\n name\n path\n actionSettings {\n type\n active\n }\n dataCollection {\n title {\n defaultMessage\n }\n }\n dbIntegrationQueries {\n query\n suggestedQuery\n requestType\n }\n }\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const DATA_POINT_COUNT = gql`\n query TranscendCliDataPointCount($filterBy: DataPointFiltersInput) {\n dataPoints(filterBy: $filterBy, useMaster: false) {\n totalCount\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - add orderBy\n// isExportCsv: true\nexport const SUB_DATA_POINTS = gql`\n query TranscendCliSubDataPoints(\n $filterBy: SubDataPointFiltersInput\n $first: Int!\n $offset: Int!\n ) {\n subDataPoints(\n filterBy: $filterBy\n first: $first\n offset: $offset\n useMaster: false\n ) {\n nodes {\n id\n name\n description\n purposes {\n name\n purpose\n }\n categories {\n name\n category\n }\n accessRequestVisibilityEnabled\n erasureRequestRedactionEnabled\n attributeValues {\n attributeKey {\n name\n }\n name\n }\n }\n }\n }\n`;\n\nexport const SUB_DATA_POINTS_COUNT = gql`\n query TranscendCliSubDataPointsCount($filterBy: SubDataPointFiltersInput) {\n subDataPoints(filterBy: $filterBy, useMaster: false) {\n totalCount\n }\n }\n`;\n\nexport const SUB_DATA_POINTS_WITH_GUESSES = gql`\n query TranscendCliSubDataPointGuesses(\n $filterBy: SubDataPointFiltersInput\n $first: Int!\n $offset: Int!\n ) {\n subDataPoints(\n filterBy: $filterBy\n first: $first\n offset: $offset\n useMaster: false\n ) {\n nodes {\n id\n name\n description\n purposes {\n name\n purpose\n }\n categories {\n name\n category\n }\n pendingCategoryGuesses {\n category {\n name\n category\n }\n status\n confidence\n classifierVersion\n }\n accessRequestVisibilityEnabled\n erasureRequestRedactionEnabled\n attributeValues {\n attributeKey {\n name\n }\n name\n }\n }\n }\n }\n`;\n\nexport const UPDATE_OR_CREATE_DATA_POINT = gql`\n mutation TranscendCliUpdateOrCreateDataPoint(\n $dataSiloId: ID!\n $name: String!\n $path: [String!]\n $title: String\n $description: String\n $ownerIds: [ID!]\n $ownerEmails: [String!]\n $teamNames: [String!]\n $teamIds: [ID!]\n $dataCollectionTag: String\n $querySuggestions: [DbIntegrationQuerySuggestionInput!]\n $enabledActions: [RequestActionObjectResolver!]\n $subDataPoints: [DataPointSubDataPointInput!]\n ) {\n updateOrCreateDataPoint(\n input: {\n dataSiloId: $dataSiloId\n name: $name\n path: $path\n title: $title\n teamNames: $teamNames\n ownerEmails: $ownerEmails\n dataCollectionTag: $dataCollectionTag\n description: $description\n ownerIds: $ownerIds\n teamIds: $teamIds\n querySuggestions: $querySuggestions\n enabledActions: $enabledActions\n subDataPoints: $subDataPoints\n }\n ) {\n dataPoint {\n id\n name\n }\n }\n }\n`;\n\nexport const DATAPOINT_EXPORT = gql`\n query TranscendCliDataPointCsvExport(\n $filterBy: DataPointFiltersInput\n $first: Int!\n ) {\n dataPoints(filterBy: $filterBy, first: $first, useMaster: false) {\n nodes {\n id\n title {\n defaultMessage\n }\n description {\n defaultMessage\n }\n owners {\n email\n }\n teams {\n name\n }\n name\n path\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const ENTRY_COUNT = gql`\n query TranscendCliEntryCount(\n $filterBy: UnstructuredSubDataPointRecommendationsFilterInput\n ) {\n unstructuredSubDataPointRecommendations(\n filterBy: $filterBy\n useMaster: false\n ) {\n totalCount\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const DATA_SILOS = gql`\n query TranscendCliDataSilos(\n $filterBy: DataSiloFiltersInput!\n $first: Int!\n $offset: Int!\n ) {\n dataSilos(\n filterBy: $filterBy\n first: $first\n offset: $offset\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: title, direction: ASC }\n ]\n useMaster: false\n ) {\n nodes {\n id\n title\n link\n type\n catalog {\n hasAvcFunctionality\n }\n }\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const DATA_SILO_EXPORT = gql`\n query TranscendCliDataSiloExport(\n $filterBy: DataSiloFiltersInput!\n $first: Int!\n ) {\n dataSilos(filterBy: $filterBy, first: $first, useMaster: false) {\n nodes {\n id\n title\n }\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const DATA_SILOS_ENRICHED = gql`\n query TranscendCliDataSilosEnriched(\n $filterBy: DataSiloFiltersInput!\n $first: Int!\n $offset: Int!\n ) {\n dataSilos(\n filterBy: $filterBy\n first: $first\n offset: $offset\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: title, direction: ASC }\n ]\n useMaster: false\n ) {\n nodes {\n id\n title\n description\n type\n outerType\n link\n country\n countrySubDivision\n url\n notifyEmailAddress\n attributeValues {\n attributeKey {\n name\n }\n name\n }\n apiKeys {\n title\n }\n subjectBlocklist {\n type\n }\n identifiers {\n name\n isConnected\n }\n dependentDataSilos {\n title\n }\n owners {\n email\n }\n teams {\n id\n name\n }\n catalog {\n hasAvcFunctionality\n }\n isLive\n promptAVendorEmailSendFrequency\n promptAVendorEmailSendType\n promptAVendorEmailIncludeIdentifiersAttachment\n promptAVendorEmailCompletionLinkType\n manualWorkRetryFrequency\n discoveredBy {\n title\n }\n businessEntities {\n title\n }\n }\n }\n }\n`;\n\nexport const UPDATE_DATA_SILOS = gql`\n mutation TranscendCliUpdateDataSilo($input: UpdateDataSilosInput!) {\n updateDataSilos(input: $input) {\n clientMutationId\n dataSilos {\n id\n title\n }\n }\n }\n`;\n\nexport const CREATE_DATA_SILOS = gql`\n mutation TranscendCliCreateDataSilo($input: [CreateDataSilosInput!]!) {\n createDataSilos(input: $input) {\n dataSilos {\n id\n title\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const ENRICHERS = gql`\n query TranscendCliEnrichers($title: String, $first: Int!, $offset: Int!) {\n enrichers(\n filterBy: { text: $title }\n first: $first\n offset: $offset\n useMaster: false\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: title, direction: ASC }\n ]\n ) {\n nodes {\n id\n title\n url\n type\n expirationDuration\n lookerQueryTitle\n testRegex\n transitionRequestStatus\n phoneNumbers\n regionList\n inputIdentifier {\n name\n }\n identifiers {\n name\n }\n dataSubjects {\n type\n }\n actions\n }\n }\n }\n`;\n\nexport interface Initializer {\n /** ID of enricher */\n id: string;\n /** Identifiers */\n identifiers: {\n /** Name of identifier */\n name: string;\n }[];\n}\n\nexport const INITIALIZER = gql`\n query TranscendCliInitializer {\n initializer {\n id\n identifiers {\n name\n }\n }\n }\n`;\n\nexport const CREATE_ENRICHER = gql`\n mutation TranscendCliCreateEnricher($input: EnricherInput!) {\n createEnricher(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const UPDATE_ENRICHER = gql`\n mutation TranscendCliUpdateEnricher($input: UpdateEnricherInput!) {\n updateEnricher(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - order by createdAt\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const CATALOGS = gql`\n query TranscendCliCatalogs($first: Int!, $offset: Int!) {\n catalogs(first: $first, offset: $offset, filterBy: {}, useMaster: false) {\n nodes {\n integrationName\n title\n hasApiFunctionality\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const IDENTIFIERS = gql`\n query TranscendCliIdentifiers($first: Int!, $offset: Int!) {\n identifiers(\n first: $first\n offset: $offset\n useMaster: false\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n name\n type\n regex\n selectOptions\n privacyCenterVisibility\n dataSubjects {\n type\n }\n isRequiredInForm\n placeholder\n displayTitle {\n defaultMessage\n }\n displayDescription {\n defaultMessage\n }\n displayOrder\n isUniqueOnPreferenceStore\n }\n }\n }\n`;\n\nexport const NEW_IDENTIFIER_TYPES = gql`\n query TranscendCliNewIdentifierTypes {\n newIdentifierTypes {\n name\n }\n }\n`;\n\nexport const CREATE_IDENTIFIER = gql`\n mutation TranscendCliCreateIdentifier($input: IdentifierInput!) {\n createIdentifier(input: $input) {\n identifier {\n id\n name\n }\n }\n }\n`;\n\nexport const UPDATE_IDENTIFIER = gql`\n mutation TranscendCliUpdateIdentifier($input: UpdateIdentifierInput!) {\n updateIdentifier(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const DATA_SUBJECTS = gql`\n query TranscendCliDataSubjects {\n internalSubjects {\n id\n title {\n defaultMessage\n }\n active\n type\n adminDashboardDefaultSilentMode\n actions {\n type\n }\n }\n }\n`;\n\nexport const CREATE_DATA_SUBJECT = gql`\n mutation TranscendCliCreateDataSubject($type: String!) {\n createSubject(input: { type: $type, title: $type, subjectClass: OTHER }) {\n subject {\n id\n type\n }\n }\n }\n`;\n\nexport const UPDATE_DATA_SUBJECT = gql`\n mutation TranscendCliUpdateDataSubject($input: UpdateSubjectInput!) {\n updateSubject(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const TOGGLE_DATA_SUBJECT = gql`\n mutation TranscendCliToggleDataSubject($input: ToggleSubjectInput!) {\n toggleSubject(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const REPOSITORIES = gql`\n query TranscendCliRepositories(\n $first: Int!\n $offset: Int!\n $input: RepositoryFiltersInput\n ) {\n repositories(\n first: $first\n offset: $offset\n filterBy: $input\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n name\n description\n url\n teams {\n id\n name\n }\n owners {\n id\n email\n }\n }\n }\n }\n`;\n\nexport const UPDATE_REPOSITORIES = gql`\n mutation TranscendCliUpdateRepositories($input: UpdateRepositoriesInput!) {\n updateRepositories(input: $input) {\n clientMutationId\n repositories {\n id\n name\n url\n teams {\n id\n name\n }\n owners {\n id\n email\n }\n }\n }\n }\n`;\n\nexport const CREATE_REPOSITORY = gql`\n mutation TranscendCliCreateRepository($input: CreateRepositoryInput!) {\n createRepository(input: $input) {\n clientMutationId\n repository {\n id\n name\n url\n teams {\n id\n name\n }\n owners {\n id\n email\n }\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const API_KEYS = gql`\n query TranscendCliApiKeys($first: Int!, $offset: Int!, $titles: [String!]) {\n apiKeys(\n first: $first\n offset: $offset\n filterBy: { titles: $titles }\n useMaster: false\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: title, direction: ASC }\n ]\n ) {\n nodes {\n id\n title\n }\n }\n }\n`;\n\nexport const CREATE_API_KEY = gql`\n mutation TranscendCliCreateApiKey($input: ApiKeyInput!) {\n createApiKey(input: $input) {\n apiKey {\n id\n apiKey\n title\n }\n }\n }\n`;\n\nexport const DELETE_API_KEY = gql`\n mutation TranscendCliDeleteApiKey($id: ID!) {\n deleteApiKey(id: $id) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const CREATE_PREFERENCE_ACCESS_TOKENS = gql`\n mutation TranscendCliCreatePreferenceAccessTokens(\n $input: CreatePrivacyCenterAccessTokensInput!\n ) {\n createPrivacyCenterAccessTokens(input: $input) {\n nodes {\n token\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const ADD_SILO_DISCOVERY_RESULTS = gql`\n mutation AddSiloDiscoveryResults(\n $pluginId: ID!\n $rawResults: [SiloDiscoveryRawResultInput!]!\n ) {\n addSiloDiscoveryResults(\n input: { pluginId: $pluginId, rawResults: $rawResults }\n ) {\n success\n }\n }\n`;\n\nexport const ENABLED_PLUGINS = gql`\n query Plugins($dataSiloId: String!, $type: PluginType!) {\n plugins(filterBy: { dataSiloId: $dataSiloId, type: $type, enabled: true }) {\n plugins {\n id\n dataSilo {\n type\n }\n }\n totalCount\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - order by createdAt\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const TEMPLATES = gql`\n query TranscendCliTemplates($title: String, $first: Int!, $offset: Int!) {\n templates(\n filterBy: { text: $title }\n first: $first\n offset: $offset\n useMaster: false\n ) {\n nodes {\n id\n title\n subject {\n defaultMessage\n }\n template {\n defaultMessage\n }\n }\n }\n }\n`;\n\nexport const CREATE_TEMPLATE = gql`\n mutation TranscendCliCreateTemplate($title: String!) {\n createTemplate(input: { title: $title, template: \"\", subject: $title }) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const ORGANIZATION = gql`\n query TranscendCliOrganization {\n organization {\n sombra {\n customerUrl\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// TODO: https://transcend.height.app/T-27909 - order by createdAt\nexport const ATTRIBUTE_KEYS_REQUESTS = gql`\n query TranscendCliAttributeKeys($first: Int!, $offset: Int!) {\n attributeKeys(\n filterBy: { enabledOn: [request] }\n first: $first\n useMaster: false\n offset: $offset\n ) {\n nodes {\n id\n name\n type\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const SOFTWARE_DEVELOPMENT_KITS = gql`\n query TranscendCliSoftwareDevelopmentKits(\n $first: Int!\n $offset: Int!\n $input: SoftwareDevelopmentKitFiltersInput\n ) {\n softwareDevelopmentKits(\n first: $first\n offset: $offset\n filterBy: $input\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n name\n description\n codePackageType\n documentationLinks\n repositoryUrl\n teams {\n id\n name\n }\n owners {\n id\n email\n }\n }\n }\n }\n`;\n\nexport const UPDATE_SOFTWARE_DEVELOPMENT_KITS = gql`\n mutation TranscendCliUpdateSoftwareDevelopmentKits(\n $input: UpdateSoftwareDevelopmentKitsInput!\n ) {\n updateSoftwareDevelopmentKits(input: $input) {\n clientMutationId\n softwareDevelopmentKits {\n id\n name\n description\n codePackageType\n documentationLinks\n repositoryUrl\n teams {\n id\n name\n }\n owners {\n id\n email\n }\n }\n }\n }\n`;\n\nexport const CREATE_SOFTWARE_DEVELOPMENT_KIT = gql`\n mutation TranscendCliCreateSoftwareDevelopmentKit(\n $input: CreateSoftwareDevelopmentKitInput!\n ) {\n createSoftwareDevelopmentKit(input: $input) {\n clientMutationId\n softwareDevelopmentKit {\n id\n name\n description\n codePackageType\n documentationLinks\n repositoryUrl\n teams {\n id\n name\n }\n owners {\n id\n email\n }\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const CODE_PACKAGES = gql`\n query TranscendCliCodePackages(\n $first: Int!\n $offset: Int!\n $input: CodePackageFiltersInput\n ) {\n codePackages(\n first: $first\n offset: $offset\n filterBy: $input\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n name\n description\n type\n relativePath\n teams {\n id\n name\n }\n owners {\n id\n email\n }\n repository {\n id\n name\n }\n dataSilo {\n id\n title\n type\n }\n }\n }\n }\n`;\n\nexport const UPDATE_CODE_PACKAGES = gql`\n mutation TranscendCliUpdateCodePackages($input: UpdateCodePackagesInput!) {\n updateCodePackages(input: $input) {\n clientMutationId\n codePackages {\n id\n name\n description\n type\n relativePath\n teams {\n id\n name\n }\n owners {\n id\n email\n }\n repository {\n id\n name\n }\n dataSilo {\n id\n title\n type\n }\n }\n }\n }\n`;\n\nexport const CREATE_CODE_PACKAGE = gql`\n mutation TranscendCliCreateCodePackage($input: CreateCodePackageInput!) {\n createCodePackage(input: $input) {\n clientMutationId\n codePackage {\n id\n name\n description\n type\n relativePath\n teams {\n id\n name\n }\n owners {\n id\n email\n }\n repository {\n id\n name\n }\n dataSilo {\n id\n title\n type\n }\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const PROMPT_THREADS = gql`\n query TranscendCliPromptThreads(\n $first: Int!\n $offset: Int!\n $filterBy: PromptThreadFiltersInput!\n ) {\n promptThreads(first: $first, offset: $offset, filterBy: $filterBy) {\n nodes {\n id\n threadId\n slackMessageTs\n slackTeamId\n slackChannelId\n slackChannelName\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const POLICIES = gql`\n query TranscendCliFetchPolicies($url: String!) {\n privacyCenterPolicies(lookup: { url: $url }) {\n id\n title {\n defaultMessage\n }\n disableEffectiveOn\n disabledLocales\n versions {\n effectiveOn\n content {\n defaultMessage\n }\n }\n }\n }\n`;\n\nexport const UPDATE_POLICIES = gql`\n mutation TranscendCliUpdatePolicies(\n $policies: [PolicyInput!]!\n $privacyCenterId: ID!\n ) {\n updatePolicies(\n input: {\n privacyCenterId: $privacyCenterId\n policies: $policies\n skipPublish: true\n }\n ) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const REQUESTS = gql`\n query TranscendCliRequests(\n $first: Int!\n $offset: Int!\n $filterBy: RequestFiltersInput!\n ) {\n requests(\n filterBy: $filterBy\n first: $first\n offset: $offset\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: id, direction: ASC }\n ]\n useMaster: false\n ) {\n nodes {\n id\n createdAt\n email\n link\n status\n details\n isTest\n locale\n origin\n isSilent\n coreIdentifier\n daysRemaining\n type\n subjectType\n country\n countrySubDivision\n purpose {\n title\n name\n consent\n enrichedPreferences {\n topic\n selectValues {\n id\n name\n preferenceOption {\n id\n slug\n title {\n defaultMessage\n }\n }\n }\n selectValue {\n id\n name\n }\n selectValue {\n id\n name\n }\n preferenceTopic {\n title {\n defaultMessage\n }\n id\n slug\n }\n name\n id\n booleanValue\n }\n }\n attributeValues {\n id\n name\n attributeKey {\n id\n name\n }\n }\n }\n totalCount\n }\n }\n`;\n\nexport const APPROVE_PRIVACY_REQUEST = gql`\n mutation TranscendCliApprovePrivacyRequest($input: CommunicationInput!) {\n approveRequest(input: $input) {\n request {\n id\n }\n }\n }\n`;\nexport const CANCEL_PRIVACY_REQUEST = gql`\n mutation TranscendCliCancelPrivacyRequest($input: CommunicationInput!) {\n cancelRequest(input: $input) {\n request {\n id\n }\n }\n }\n`;\n\nexport const UPDATE_PRIVACY_REQUEST = gql`\n mutation TranscendCliUpdatePrivacyRequest($input: UpdateRequestInput!) {\n updateRequest(input: $input) {\n request {\n id\n }\n }\n }\n`;\n\nexport const NOTIFY_ADDITIONAL_TIME = gql`\n mutation TranscendCliNotifyAdditionalTime($input: AdditionalTimeInput!) {\n notifyAdditionalTime(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const MESSAGES = gql`\n query TranscendCliFetchMessage {\n translatedMessages {\n id\n defaultMessage\n description\n targetReactIntlId\n translations {\n locale\n value\n }\n }\n }\n`;\n\nexport const UPDATE_INTL_MESSAGES = gql`\n mutation TranscendCliUpdateIntlMessages($messages: [MessageInput!]!) {\n updateIntlMessages(input: { messages: $messages, skipPublish: true }) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const REQUEST_ENRICHERS = gql`\n query TranscendCliRequestEnrichers(\n $first: Int!\n $offset: Int!\n $requestId: ID!\n ) {\n requestEnrichers(\n input: { requestId: $requestId }\n first: $first\n offset: $offset\n useMaster: false\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: title, direction: ASC, model: enricher }\n ]\n ) {\n nodes {\n id\n status\n enricher {\n id\n type\n title\n }\n }\n totalCount\n }\n }\n`;\n\nexport const RETRY_REQUEST_ENRICHER = gql`\n mutation TranscendCliRetryRequestEnricher($requestEnricherId: ID!) {\n retryRequestEnricher(id: $requestEnricherId) {\n requestEnricher {\n id\n }\n }\n }\n`;\n\nexport const SKIP_REQUEST_ENRICHER = gql`\n mutation TranscendCliSkipRequestEnricher($requestEnricherId: ID!) {\n skipRequestEnricher(id: $requestEnricherId) {\n requestEnricher {\n id\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const ASSESSMENT_SECTION_FIELDS = `\n id\n title\n status\n index\n questions {\n id\n title\n index\n type\n subType\n placeholder\n description\n isRequired\n displayLogic\n riskLogic\n requireRiskEvaluation\n requireRiskMatrixEvaluation\n riskCategories {\n id\n title\n }\n riskFramework {\n id\n title\n description\n riskLevels {\n id\n title\n }\n riskCategories {\n id\n title\n }\n riskMatrixColumns {\n id\n title\n }\n riskMatrixRows {\n id\n title\n }\n riskMatrix {\n id\n title\n }\n creator {\n id\n email\n name\n }\n riskMatrixRowTitle\n riskMatrixColumnTitle\n }\n riskLevel {\n id\n title\n }\n reviewerRiskLevel {\n id\n title\n }\n riskLevelFromRiskMatrix {\n id\n title\n }\n answerOptions {\n id\n index\n value\n }\n selectedAnswers {\n ... on AssessmentAnswerInterface {\n id\n index\n value\n }\n }\n respondent {\n id\n email\n name\n }\n attributeKey {\n name\n }\n externalRespondentEmail\n comments {\n id\n content\n createdAt\n updatedAt\n author {\n id\n email\n name\n }\n }\n allowedMimeTypes\n updatedAt\n referenceId\n previousSubmissions {\n id\n updatedAt\n assessmentQuestionId\n answers {\n ... on AssessmentAnswerInterface {\n id\n index\n value\n }\n }\n }\n allowSelectOther\n syncModel\n syncColumn\n syncRowIds\n syncOverride\n }\n assignees {\n id\n email\n name\n }\n externalAssignees {\n id\n email\n }\n isReviewed\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\n// orderBy: [\n// { field: createdAt, direction: ASC }\n// { field: name, direction: ASC }\n// ]\nexport const ASSESSMENTS = gql`\n query TranscendCliAssessments(\n $first: Int!\n $offset: Int!\n $filterBy: AssessmentFormFiltersInput\n ) {\n assessmentForms(first: $first, offset: $offset, filterBy: $filterBy) {\n nodes {\n id\n creator {\n id\n email\n name\n }\n lastEditor {\n id\n email\n name\n }\n title\n description\n status\n assignees {\n id\n email\n name\n }\n externalAssignees {\n id\n email\n }\n reviewers {\n id\n email\n name\n }\n isLocked\n isArchived\n isExternallyCreated\n dueDate\n createdAt\n updatedAt\n assignedAt\n submittedAt\n approvedAt\n rejectedAt\n titleIsInternal\n retentionSchedule {\n id\n type\n durationDays\n operation\n }\n attributeValues {\n name\n attributeKey {\n name\n }\n }\n sections {\n ${ASSESSMENT_SECTION_FIELDS}\n }\n assessmentGroup {\n id\n title\n description\n }\n resources {\n resourceType\n ... on AttributeBusinessEntityResource {\n id\n title\n }\n ... on AttributeDataSiloResource {\n id\n title\n }\n ... on AttributeDataSubCategoryResource {\n id\n name\n category\n }\n ... on AttributeSubDataPointResource {\n id\n name\n }\n ... on AttributeProcessingPurposeSubCategoryResource {\n id\n name\n purpose\n }\n ... on AttributeRequestResource {\n id\n type\n }\n ... on AttributeVendorResource {\n id\n title\n }\n ... on AttributePromptResource {\n id\n title\n }\n ... on AttributePromptRunResource {\n id\n title\n }\n ... on AttributePromptGroupResource {\n id\n title\n }\n }\n syncedRows {\n resourceType\n ... on AttributeBusinessEntityResource {\n id\n title\n }\n ... on AttributeDataSiloResource {\n id\n title\n }\n ... on AttributeDataSubCategoryResource {\n id\n name\n category\n }\n ... on AttributeSubDataPointResource {\n id\n name\n }\n ... on AttributeProcessingPurposeSubCategoryResource {\n id\n name\n purpose\n }\n ... on AttributeVendorResource {\n id\n title\n }\n }\n }\n }\n }\n`;\n\nexport const IMPORT_ONE_TRUST_ASSESSMENT_FORMS = gql`\n mutation TranscendCliImportOneTrustAssessmentForms(\n $input: ImportOnetrustAssessmentsInput!\n ) {\n importOneTrustAssessmentForms(input: $input) {\n assessmentForms {\n id\n title\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\n// orderBy: [\n// { field: createdAt, direction: ASC }\n// { field: name, direction: ASC }\n// ]\nexport const PURPOSES = gql`\n query TranscendCliPurposes(\n $first: Int!\n $offset: Int!\n $filterBy: TrackingPurposeFiltersInput\n $input: TrackingPurposeInput!\n ) {\n purposes(\n first: $first\n offset: $offset\n filterBy: $filterBy\n input: $input\n ) {\n nodes {\n id\n name\n description\n defaultConsent\n trackingType\n configurable\n essential\n showInConsentManager\n isActive\n displayOrder\n optOutSignals\n deletedAt\n authLevel\n showInPrivacyCenter\n title\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\n// orderBy: [\n// { field: createdAt, direction: ASC }\n// { field: name, direction: ASC }\n// ]\nexport const PREFERENCE_TOPICS = gql`\n query TranscendCliPreferenceTopics(\n $first: Int!\n $offset: Int!\n $filterBy: PreferenceTopicFilterInput\n ) {\n preferenceTopics(first: $first, offset: $offset, filterBy: $filterBy) {\n nodes {\n id\n slug\n type\n title {\n id\n defaultMessage\n }\n showInPrivacyCenter\n displayDescription {\n id\n defaultMessage\n }\n defaultConfiguration\n preferenceOptionValues {\n slug\n title {\n id\n defaultMessage\n }\n }\n purpose {\n trackingType\n }\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\nimport { ASSESSMENT_SECTION_FIELDS } from './assessment';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\n// orderBy: [\n// { field: createdAt, direction: ASC }\n// { field: name, direction: ASC }\n// ]\nexport const ASSESSMENT_TEMPLATES = gql`\n query TranscendCliAssessmentTemplates(\n $first: Int!\n $offset: Int!\n $filterBy: AssessmentFormTemplateFiltersInput\n ) {\n assessmentFormTemplates(\n first: $first\n offset: $offset\n filterBy: $filterBy\n ) {\n nodes {\n id\n creator {\n id\n email\n name\n }\n lastEditor {\n id\n email\n name\n }\n title\n description\n status\n source\n parentId\n isLocked\n isArchived\n createdAt\n updatedAt\n retentionSchedule {\n id\n type\n durationDays\n operation\n createdAt\n updatedAt\n }\n assessmentEmailSet {\n id\n title\n description\n isDefault\n templates {\n id\n title\n }\n }\n sections {\n ${ASSESSMENT_SECTION_FIELDS}\n }\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const PROMPTS = gql`\n query TranscendCliPrompts(\n $first: Int!\n $offset: Int!\n $filterBy: PromptFiltersInput\n ) {\n prompts(\n first: $first\n orderBy: [{ field: title, direction: ASC }]\n offset: $offset\n filterBy: $filterBy\n ) {\n nodes {\n id\n title\n status\n content\n temperature\n topP\n maxTokensToSample\n }\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\n// TODO: https://transcend.height.app/T-27909 - order by createdAt\n// orderBy: [{ field: title, direction: ASC }]\nexport const PROMPT_PARTIALS = gql`\n query TranscendCliPromptPartials($first: Int!, $offset: Int!) {\n promptPartials(first: $first, offset: $offset) {\n nodes {\n id\n title\n content\n }\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\n// TODO: https://transcend.height.app/T-27909 - order by createdAt\n// orderBy: [{ field: title, direction: ASC }]\nexport const PROMPT_GROUPS = gql`\n query TranscendCliPromptGroups($first: Int!, $offset: Int!) {\n promptGroups(\n first: $first\n\n offset: $offset\n ) {\n nodes {\n id\n title\n description\n prompts {\n title\n }\n }\n }\n }\n`;\n\nexport const PROMPTS_WITH_VARIABLES = gql`\n query TranscendCliPromptsWithVariables($input: PromptsWithVariablesInput!) {\n promptsWithVariables(input: $input) {\n prompts {\n id\n title\n content\n status\n temperature\n topP\n maxTokensToSample\n responseFormat\n }\n promptPartials {\n id\n title\n content\n slug\n }\n calculatedVariables {\n data\n name\n }\n runtimeVariables {\n name\n }\n }\n }\n`;\n\nexport const UPDATE_PROMPTS = gql`\n mutation TranscendCliUpdatePrompts($input: UpdatePromptsInput!) {\n updatePrompts(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const CREATE_PROMPT = gql`\n mutation TranscendCliCreatePrompt($input: CreatePromptInput!) {\n createPrompt(input: $input) {\n clientMutationId\n prompt {\n id\n }\n }\n }\n`;\n\nexport const UPDATE_PROMPT_PARTIALS = gql`\n mutation TranscendCliUpdatePromptPartials(\n $input: UpdatePromptPartialsInput!\n ) {\n updatePromptPartials(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const CREATE_PROMPT_PARTIAL = gql`\n mutation TranscendCliCreatePromptPartial($input: CreatePromptPartialInput!) {\n createPromptPartial(input: $input) {\n clientMutationId\n promptPartial {\n id\n }\n }\n }\n`;\n\nexport const UPDATE_PROMPT_GROUPS = gql`\n mutation TranscendCliUpdatePromptGroups($input: UpdatePromptGroupsInput!) {\n updatePromptGroups(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const CREATE_PROMPT_GROUP = gql`\n mutation TranscendCliCreatePromptPartial($input: CreatePromptGroupInput!) {\n createPromptGroup(input: $input) {\n clientMutationId\n promptGroup {\n id\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const REQUEST_DATA_SILOS = gql`\n query TranscendCliRequestDataSilos(\n $first: Int!\n $offset: Int!\n $filterBy: RequestDataSiloFiltersInput!\n ) {\n requestDataSilos(\n filterBy: $filterBy\n first: $first\n offset: $offset\n useMaster: false\n orderBy: [\n { field: createdAt, direction: DESC }\n { field: title, direction: ASC, model: dataSilo }\n ]\n ) {\n nodes {\n id\n }\n totalCount\n }\n }\n`;\n\nexport const CHANGE_REQUEST_DATA_SILO_STATUS = gql`\n mutation TranscendCliMarkRequestDataSiloCompleted(\n $requestDataSiloId: ID!\n $status: UpdateRequestDataSiloStatus!\n ) {\n changeRequestDataSiloStatus(\n input: { id: $requestDataSiloId, status: $status }\n ) {\n requestDataSilo {\n id\n }\n }\n }\n`;\n\nexport const RETRY_REQUEST_DATA_SILO = gql`\n mutation TranscendCliRetryRequestDataSilo($requestDataSiloId: ID!) {\n retryRequestDataSilo(id: $requestDataSiloId) {\n requestDataSilo {\n id\n }\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\n// orderBy: [\n// { field: createdAt, direction: DESC }\n// { field: title, direction: ASC, model: dataSilo }\n// ]\nexport const REDUCED_REQUESTS_FOR_DATA_SILO_COUNT = gql`\n query TranscendCliListReducedRequestsForDataSiloCount(\n $input: BulkCompletionReducedRequestInput!\n ) {\n listReducedRequestsForDataSilo(input: $input) {\n totalCount\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const TEAMS = gql`\n query TranscendCliTeams(\n $first: Int!\n $offset: Int!\n $input: TeamFiltersInput\n ) {\n teams(\n first: $first\n offset: $offset\n filterBy: $input\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n name\n description\n ssoDepartment\n ssoGroup\n ssoTitle\n users {\n id\n email\n name\n }\n scopes {\n id\n name\n title\n }\n }\n }\n }\n`;\n\nexport const CREATE_TEAM = gql`\n mutation TranscendCliCreateTeam($input: TeamInput!) {\n createTeam(input: $input) {\n team {\n id\n name\n }\n }\n }\n`;\n\nexport const UPDATE_TEAM = gql`\n mutation TranscendCliUpdateTeam($input: UpdateTeamInput!) {\n updateTeam(input: $input) {\n team {\n id\n name\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const REMOVE_REQUEST_IDENTIFIERS = gql`\n mutation TranscendCliRemoveRequestIdentifiers(\n $input: RemoveRequestIdentifiersInput!\n ) {\n removeRequestIdentifiers(input: $input) {\n count\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const REQUEST_IDENTIFIERS = gql`\n query TranscendCliRequestIdentifiers(\n $first: Int!\n $offset: Int!\n $requestIds: [ID!]!\n ) {\n requestIdentifiers(\n input: { requestIds: $requestIds }\n first: $first\n offset: $offset\n useMaster: false\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n name\n isVerifiedAtLeastOnce\n }\n totalCount\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const USERS = gql`\n query TranscendCliUsers(\n $first: Int!\n $offset: Int!\n $input: UserFiltersInput\n ) {\n users(\n first: $first\n offset: $offset\n filterBy: $input\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n name\n email\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const REQUEST_FILES = gql`\n query TranscendCliRequestFiles(\n $first: Int!\n $offset: Int!\n $filterBy: RequestFileFiltersInput!\n ) {\n requestFiles(\n filterBy: $filterBy\n first: $first\n offset: $offset\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: id, direction: ASC }\n ]\n ) {\n nodes {\n remoteId\n fileName\n }\n }\n }\n`;\n\nexport const BULK_REQUEST_FILES = gql`\n query TranscendCliBulkRequestFiles(\n $filterBy: BulkRequestFilesFiltersInput!\n $first: Int!\n $after: String\n ) {\n bulkRequestFiles(filterBy: $filterBy, first: $first, after: $after) {\n nodes {\n remoteId\n fileName\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const REPORT_PROMPT_RUN = gql`\n mutation TranscendCliReportPromptRun($input: ReportPromptRunInput!) {\n reportPromptRun(input: $input) {\n clientMutationId\n promptRun {\n id\n }\n }\n }\n`;\n\nexport const ADD_MESSAGES_TO_PROMPT_RUN = gql`\n mutation TranscendCliAddMessagesToPromptRun(\n $input: AddMessagesToPromptRunInput!\n ) {\n addMessagesToPromptRun(input: $input) {\n clientMutationId\n promptRun {\n id\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\n// orderBy: [\n// { field: createdAt, direction: ASC }\n// { field: title, direction: ASC }\n// ]\nexport const GLOBAL_ACTION_ITEM_COLLECTIONS = gql`\n query TranscendCliGlobalActionItemCollectionss(\n $filterBy: GlobalActionItemCollectionFiltersInput!\n ) {\n globalActionItemCollections(filterBy: $filterBy) {\n nodes {\n id\n title\n description\n hidden\n productLine\n }\n }\n }\n`;\n\nexport const CREATE_ACTION_ITEM_COLLECTION = gql`\n mutation TranscendCliCreateActionItemCollection(\n $input: CreateActionItemCollectionInput!\n ) {\n createActionItemCollection(input: $input) {\n created {\n id\n title\n }\n }\n }\n`;\n\nexport const UPDATE_ACTION_ITEM_COLLECTION = gql`\n mutation TranscendCliUpdateActionItemCollection(\n $input: UpdateActionItemCollectionInput!\n ) {\n updateActionItemCollection(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - order by createdAt\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const ATTRIBUTES = gql`\n query TranscendCliAttributes($first: Int!, $offset: Int!) {\n attributeKeys(first: $first, offset: $offset, useMaster: false) {\n nodes {\n id\n isCustom\n description\n enabledOn\n name\n type\n }\n }\n }\n`;\n\nexport const CREATE_ATTRIBUTE_VALUES = gql`\n mutation TranscendCliCreateAttributeValues(\n $input: [CreateAttributeValuesInput!]!\n ) {\n createAttributeValues(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const UPDATE_ATTRIBUTE_VALUES = gql`\n mutation TranscendCliUpdateAttributeValues(\n $input: [UpdateAttributeValueInput!]!\n ) {\n updateAttributeValues(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const DELETE_ATTRIBUTE_VALUE = gql`\n mutation TranscendCliDeleteAttributeValue($id: ID!) {\n deleteAttributeValue(id: $id) {\n clientMutationId\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - order by createdAt\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const ATTRIBUTE_VALUES = gql`\n query TranscendCliAttributeValues(\n $first: Int!\n $offset: Int!\n $attributeKeyId: ID!\n ) {\n attributeValues(\n first: $first\n offset: $offset\n useMaster: false\n filterBy: { attributeKeys: [$attributeKeyId] }\n ) {\n nodes {\n id\n name\n description\n color\n }\n }\n }\n`;\n\nexport const CREATE_ATTRIBUTE = gql`\n mutation TranscendCliCreateAttribute(\n $name: String!\n $type: AttributeKeyType!\n $description: String\n $enabledOn: [AttributeSupportedResourceType!]\n ) {\n createAttributeKey(\n input: {\n name: $name\n type: $type\n description: $description\n enabledOn: $enabledOn\n }\n ) {\n clientMutationId\n attributeKey {\n id\n }\n }\n }\n`;\n\nexport const UPDATE_ATTRIBUTE = gql`\n mutation TranscendCliCreateAttribute(\n $attributeKeyId: ID!\n $description: String\n $enabledOn: [AttributeSupportedResourceType!]\n ) {\n updateAttributeKey(\n input: {\n id: $attributeKeyId\n description: $description\n enabledOn: $enabledOn\n }\n ) {\n clientMutationId\n attributeKey {\n id\n }\n }\n }\n`;\n\nexport const SET_RESOURCE_ATTRIBUTES = gql`\n mutation TranscendCliSetResourceAttributes(\n $input: SetResourceAttributesInput!\n ) {\n setResourceAttributes(input: $input) {\n clientMutationId\n }\n }\n`;\n","/* eslint-disable max-lines */\nimport { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - order by createdAt\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const EXPERIENCES = gql`\n query TranscendCliExperiences($first: Int!, $offset: Int!) {\n experiences(first: $first, offset: $offset, useMaster: false) {\n nodes {\n id\n name\n displayName\n regions {\n countrySubDivision\n country\n }\n operator\n displayPriority\n onConsentExpiry\n consentExpiry\n viewState\n purposes {\n name\n trackingType\n }\n optedOutPurposes {\n name\n trackingType\n }\n browserLanguages\n browserTimeZones\n }\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - order by createdAt\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// useMaster: false\n// isExportCsv: true\nexport const CONSENT_PARTITIONS = gql`\n query TranscendCliConsentPartitions($first: Int!, $offset: Int!) {\n consentPartitions(first: $first, offset: $offset) {\n nodes {\n id\n name\n partition\n }\n }\n }\n`;\n\nexport const CREATE_DATA_FLOWS = gql`\n mutation TranscendCliCreateDataFlows(\n $dataFlows: [DataFlowInput!]!\n $airgapBundleId: ID!\n $classifyService: Boolean\n ) {\n createDataFlows(\n input: {\n airgapBundleId: $airgapBundleId\n dataFlows: $dataFlows\n classifyService: $classifyService\n }\n ) {\n dataFlows {\n id\n }\n }\n }\n`;\n\nexport const UPDATE_DATA_FLOWS = gql`\n mutation TranscendCliUpdateDataFlows(\n $airgapBundleId: ID!\n $dataFlows: [UpdateDataFlowInput!]!\n $classifyService: Boolean\n ) {\n updateDataFlows(\n input: {\n airgapBundleId: $airgapBundleId\n dataFlows: $dataFlows\n classifyService: $classifyService\n }\n ) {\n dataFlows {\n id\n }\n }\n }\n`;\n\nexport const UPDATE_OR_CREATE_COOKIES = gql`\n mutation TranscendCliUpdateOrCreateCookies(\n $cookies: [UpdateOrCreateCookieInput!]!\n $airgapBundleId: ID!\n ) {\n updateOrCreateCookies(\n input: { airgapBundleId: $airgapBundleId, cookies: $cookies }\n ) {\n clientMutationId\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const DATA_FLOWS = gql`\n query TranscendCliDataFlows(\n $first: Int!\n $airgapBundleId: ID!\n $offset: Int!\n $status: ConsentTrackerStatus\n $showZeroActivity: Boolean\n ) {\n dataFlows(\n first: $first\n offset: $offset\n filterBy: { status: $status, showZeroActivity: $showZeroActivity }\n input: { airgapBundleId: $airgapBundleId }\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: value, direction: ASC }\n ]\n useMaster: false\n ) {\n nodes {\n id\n value\n type\n description\n trackingType\n service {\n integrationName\n }\n source\n status\n owners {\n email\n }\n teams {\n name\n }\n attributeValues {\n name\n attributeKey {\n name\n }\n }\n }\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const COOKIES = gql`\n query TranscendCliCookies(\n $first: Int!\n $offset: Int!\n $airgapBundleId: ID!\n $status: ConsentTrackerStatus\n ) {\n cookies(\n first: $first\n offset: $offset\n filterBy: { status: $status }\n input: { airgapBundleId: $airgapBundleId }\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n useMaster: false\n ) {\n nodes {\n id\n name\n isRegex\n description\n trackingPurposes\n service {\n integrationName\n }\n source\n status\n owners {\n email\n }\n teams {\n name\n }\n attributeValues {\n name\n attributeKey {\n name\n }\n }\n }\n }\n }\n`;\n\nexport const FETCH_CONSENT_MANAGER_ID = gql`\n query TranscendCliFetchConsentManagerId {\n consentManager {\n consentManager {\n id\n }\n }\n }\n`;\n\nexport const FETCH_CONSENT_MANAGER = gql`\n query TranscendCliFetchConsentManager {\n consentManager {\n consentManager {\n id\n bundleURL\n testBundleURL\n configuration {\n domains\n consentPrecedence\n unknownRequestPolicy\n unknownCookiePolicy\n syncEndpoint\n telemetryPartitioning\n signedIabAgreement\n syncGroups\n partition\n }\n partition {\n partition\n }\n }\n }\n }\n`;\n\nexport const FETCH_CONSENT_MANAGER_THEME = gql`\n query TranscendCliFetchConsentManagerTheme($airgapBundleId: ID!) {\n consentManagerTheme(input: { airgapBundleId: $airgapBundleId }) {\n theme {\n primaryColor\n fontColor\n privacyPolicy\n prompt\n }\n }\n }\n`;\n\nexport const CREATE_CONSENT_MANAGER = gql`\n mutation TranscendCliCreateConsentManager($privacyCenterId: ID!) {\n createConsentManager(input: { privacyCenterId: $privacyCenterId }) {\n consentManager {\n id\n }\n }\n }\n`;\n\nexport const UPDATE_CONSENT_MANAGER_VERSION = gql`\n mutation TranscendCliUpdateConsentManager(\n $airgapBundleId: ID!\n $version: String!\n ) {\n updateConsentManager(id: $airgapBundleId, input: { version: $version }) {\n clientMutationId\n }\n }\n`;\n\nexport const UPDATE_CONSENT_MANAGER_TO_LATEST = gql`\n mutation TranscendCliUpdateConsentManagerToLatest(\n $airgapBundleId: ID!\n $bundleType: ConsentBundleType!\n ) {\n updateConsentManagerToLatestVersion(\n id: $airgapBundleId\n input: { bundleType: $bundleType }\n ) {\n clientMutationId\n }\n }\n`;\n\nexport const DEPLOY_CONSENT_MANAGER = gql`\n mutation TranscendCliDeployConsentManager(\n $airgapBundleId: ID!\n $bundleType: ConsentBundleType!\n ) {\n deployConsentManagerBundle(\n id: $airgapBundleId\n input: { bundleType: $bundleType }\n ) {\n clientMutationId\n }\n }\n`;\n\nexport const UPDATE_CONSENT_MANAGER_DOMAINS = gql`\n mutation TranscendCliUpdateConsentManagerDomains(\n $airgapBundleId: ID!\n $domains: [String!]!\n ) {\n updateConsentManagerDomains(\n input: { id: $airgapBundleId, domains: $domains }\n ) {\n clientMutationId\n }\n }\n`;\n\nexport const UPDATE_CONSENT_MANAGER_PARTITION = gql`\n mutation TranscendCliUpdateConsentManagerPartition(\n $airgapBundleId: ID!\n $partitionId: ID!\n ) {\n updateConsentManagerPartition(\n input: { id: $airgapBundleId, partitionId: $partitionId }\n ) {\n clientMutationId\n }\n }\n`;\n\nexport const UPDATE_LOAD_OPTIONS = gql`\n mutation TranscendCliUpdateLoadOptions($input: UpdateLoadOptionsInput!) {\n updateLoadOptions(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const TOGGLE_UNKNOWN_REQUEST_POLICY = gql`\n mutation TranscendCliToggleUnknownRequestPolicy(\n $input: ToggleUnknownRequestPolicyInput!\n ) {\n toggleUnknownRequestPolicy(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const TOGGLE_UNKNOWN_COOKIE_POLICY = gql`\n mutation TranscendCliToggleUnknownCookiePolicy(\n $input: ToggleUnknownCookiePolicyInput!\n ) {\n toggleUnknownCookiePolicy(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const TOGGLE_TELEMETRY_PARTITION_STRATEGY = gql`\n mutation TranscendCliToggleTelemetryPartitionStrategy(\n $input: ToggleTelemetryPartitionStrategyInput!\n ) {\n toggleTelemetryPartitioning(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const TOGGLE_CONSENT_PRECEDENCE = gql`\n mutation TranscendCliToggleConsentPrecedence(\n $input: ToggleConsentPrecedenceInput!\n ) {\n toggleConsentPrecedence(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const UPDATE_CONSENT_MANAGER_THEME = gql`\n mutation TranscendCliUpdateConsentManagerTheme(\n $input: UpdateConsentManagerThemeInput!\n ) {\n updateConsentManagerTheme(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const UPDATE_CONSENT_EXPERIENCE = gql`\n mutation TranscendCliUpdateConsentExperience($input: UpdateExperienceInput!) {\n updateExperience(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const CREATE_CONSENT_EXPERIENCE = gql`\n mutation TranscendCliCreateConsentExperience($input: CreateExperienceInput!) {\n createExperience(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const CREATE_CONSENT_PARTITION = gql`\n mutation TranscendCliCreateConsentPartition(\n $input: CreateConsentPartitionInput!\n ) {\n createConsentPartition(input: $input) {\n clientMutationId\n }\n }\n`;\n/* eslint-enable max-lines */\n","import { gql } from 'graphql-request';\n\nexport const CONSENT_MANAGER_ANALYTICS_DATA = gql`\n query TranscendCliConsentManagerAnalyticsData($input: AnalyticsInput!) {\n analyticsData(input: $input) {\n series {\n name\n points {\n key\n value\n }\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const BUSINESS_ENTITIES = gql`\n query TranscendCliBusinessEntities($first: Int!, $offset: Int!) {\n businessEntities(\n first: $first\n offset: $offset\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: title, direction: ASC }\n ]\n useMaster: false\n ) {\n nodes {\n id\n title\n description\n dataProtectionOfficerName\n dataProtectionOfficerEmail\n address\n headquarterCountry\n headquarterSubDivision\n attributeValues {\n name\n attributeKey {\n name\n }\n }\n }\n }\n }\n`;\n\nexport const CREATE_BUSINESS_ENTITY = gql`\n mutation TranscendCliCreateBusinessEntity(\n $input: CreateBusinessEntityInput!\n ) {\n createBusinessEntity(input: $input) {\n businessEntity {\n id\n title\n description\n dataProtectionOfficerName\n dataProtectionOfficerEmail\n address\n headquarterCountry\n headquarterSubDivision\n attributeValues {\n name\n attributeKey {\n name\n }\n }\n }\n }\n }\n`;\n\nexport const UPDATE_BUSINESS_ENTITIES = gql`\n mutation TranscendCliUpdateBusinessEntities(\n $input: [UpdateBusinessEntityInput!]!\n ) {\n updateBusinessEntities(input: { businessEntities: $input }) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// TODO: https://transcend.height.app/T-27909 - order by createdAt\nexport const ACTIONS = gql`\n query TranscendCliActions($first: Int!, $offset: Int!) {\n actions(\n first: $first\n offset: $offset\n useMaster: false\n orderBy: [{ field: type, direction: ASC }]\n ) {\n nodes {\n id\n type\n skipSecondaryIfNoFiles\n skipDownloadableStep\n requiresReview\n regionList\n regionDetectionMethod\n waitingPeriod\n }\n }\n }\n`;\n\nexport const UPDATE_ACTION = gql`\n mutation TranscendCliUpdateAction($input: UpdateActionInput!) {\n updateAction(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\n// orderBy: [\n// { field: createdAt, direction: ASC }\n// { field: title, direction: ASC }\n// ]\nexport const GLOBAL_ACTION_ITEMS = gql`\n query TranscendCliGlobalActionItems(\n $first: Int!\n $offset: Int!\n $filterBy: GlobalActionItemFiltersInput!\n ) {\n globalActionItems(first: $first, offset: $offset, filterBy: $filterBy) {\n nodes {\n ids\n count\n teams {\n id\n name\n }\n customerExperienceActionItemIds\n users {\n id\n email\n }\n collections {\n title\n id\n }\n dueDate\n priority\n titles\n resolved\n notes\n links\n type\n additionalContexts {\n iconOverride\n requestId\n dataSiloId\n requestType\n latestAirgapVersion\n parentTitle\n }\n attributeValues {\n name\n attributeKey {\n name\n }\n }\n }\n }\n }\n`;\n\nexport const UPDATE_ACTION_ITEMS = gql`\n mutation TranscendCliUpdateActionItems($input: UpdateActionItemsInput!) {\n updateActionItems(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const CREATE_ACTION_ITEMS = gql`\n mutation TranscendCliCreateActionItems($input: [CreateActionItemsInput!]!) {\n createActionItems(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const FETCH_PRIVACY_CENTER_ID = gql`\n query TranscendCliFetchPrivacyCenterId($url: String!) {\n privacyCenter(lookup: { url: $url }) {\n id\n }\n }\n`;\n\nexport const DEPLOYED_PRIVACY_CENTER_URL = gql`\n query TranscendCliDeployedPrivacyCenterUrl {\n organization {\n deployedPrivacyCenterUrl\n }\n }\n`;\n\nexport const PRIVACY_CENTER = gql`\n query TranscendCliFetchPrivacyCenters($url: String!) {\n privacyCenter(lookup: { url: $url }) {\n id\n url\n isDisabled\n showPrivacyRequestButton\n showPolicies\n showTrackingTechnologies\n showCookies\n showDataFlows\n showConsentManager\n showManageYourPrivacy\n showMarketingPreferences\n locales\n defaultLocale\n preferBrowserDefaultLocale\n supportEmail\n replyToEmail\n useNoReplyEmailAddress\n useCustomEmailDomain\n transformAccessReportJsonToCsv\n themeStr\n }\n }\n`;\n\nexport const UPDATE_PRIVACY_CENTER = gql`\n mutation TranscendCliUpdatePrivacyCenter($input: UpdatePrivacyCenterInput!) {\n updatePrivacyCenter(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const DETERMINE_LOGIN_METHOD = gql`\n mutation TranscendCliDetermineLoginMethod($email: String!) {\n determineLoginMethod(input: { email: $email }) {\n loginMethod {\n email\n sombraPublicKey\n }\n }\n }\n`;\n\nexport const LOGIN = gql`\n mutation TranscendCliLogin(\n $email: String!\n $password: String!\n $publicKey: String!\n ) {\n login(\n input: { email: $email, password: $password }\n publicKey: $publicKey\n ) {\n user {\n roles {\n id\n organization {\n name\n id\n uri\n parentOrganizationId\n }\n }\n }\n }\n }\n`;\n\nexport const ASSUME_ROLE = gql`\n mutation TranscendCliAssumeRole($id: ID!, $publicKey: String!) {\n assumeRole(id: $id, publicKey: $publicKey) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const LARGE_LANGUAGE_MODELS = gql`\n query TranscendCliLargeLanguageModels(\n $first: Int!\n $offset: Int!\n $filterBy: LargeLanguageModelFiltersInput\n ) {\n largeLanguageModels(\n first: $first\n orderBy: [\n { field: name, direction: ASC }\n { field: client, direction: ASC }\n { field: isTranscendHosted, direction: ASC }\n ]\n offset: $offset\n filterBy: $filterBy\n ) {\n nodes {\n id\n name\n client\n isTranscendHosted\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const AGENTS = gql`\n query TranscendCliAgents(\n $first: Int!\n $offset: Int!\n $filterBy: AgentFiltersInput\n ) {\n agents(\n first: $first\n offset: $offset\n filterBy: $filterBy\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n name\n agentId\n instructions\n description\n codeInterpreterEnabled\n retrievalEnabled\n prompt {\n title\n }\n largeLanguageModel {\n name\n client\n }\n teams {\n name\n }\n owners {\n email\n }\n agentFunctions {\n name\n }\n agentFiles {\n name\n }\n }\n }\n }\n`;\n\nexport const CREATE_AGENT = gql`\n mutation TranscendCliCreateAgent($input: CreateAgentInput!) {\n createAgent(input: $input) {\n agent {\n id\n name\n agentId\n }\n }\n }\n`;\n\nexport const UPDATE_AGENTS = gql`\n mutation TranscendCliUpdateAgents($input: UpdateAgentsInput!) {\n updateAgents(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const AGENT_FILES = gql`\n query TranscendCliAgentFiles(\n $first: Int!\n $offset: Int!\n $filterBy: AgentFileFiltersInput\n ) {\n agentFiles(\n first: $first\n offset: $offset\n filterBy: $filterBy\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n name\n description\n fileId\n size\n purpose\n initialFileName\n }\n }\n }\n`;\n\nexport const CREATE_AGENT_FILE = gql`\n mutation TranscendCliCreateAgentFile($input: CreateAgentFileInput!) {\n createAgentFile(input: $input) {\n agentFile {\n id\n name\n fileId\n initialFileName\n }\n }\n }\n`;\n\nexport const UPDATE_AGENT_FILES = gql`\n mutation TranscendCliUpdateAgentFiles($input: UpdateAgentFilesInput!) {\n updateAgentFiles(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const AGENT_FUNCTIONS = gql`\n query TranscendCliAgentFunctions($first: Int!, $offset: Int!) {\n agentFunctions(\n first: $first\n offset: $offset\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n name\n description\n parameters\n }\n }\n }\n`;\n\nexport const CREATE_AGENT_FUNCTION = gql`\n mutation TranscendCliCreateAgentFunction($input: CreateAgentFunctionInput!) {\n createAgentFunction(input: $input) {\n agentFunction {\n id\n name\n }\n }\n }\n`;\n\nexport const UPDATE_AGENT_FUNCTIONS = gql`\n mutation TranscendCliUpdateAgentFunctions(\n $input: UpdateAgentFunctionsInput!\n ) {\n updateAgentFunctions(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const VENDORS = gql`\n query TranscendCliVendors($first: Int!, $offset: Int!) {\n vendors(\n first: $first\n offset: $offset\n useMaster: false\n isExportCsv: true\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: title, direction: ASC }\n ]\n ) {\n nodes {\n id\n title\n description\n dataProcessingAgreementLink\n contactName\n contactEmail\n contactPhone\n address\n headquarterCountry\n headquarterSubDivision\n websiteUrl\n businessEntity {\n title\n }\n teams {\n name\n }\n owners {\n email\n }\n attributeValues {\n attributeKey {\n name\n }\n name\n }\n }\n }\n }\n`;\n\nexport const CREATE_VENDOR = gql`\n mutation TranscendCliCreateVendor($input: CreateVendorInput!) {\n createVendor(input: $input) {\n vendor {\n id\n title\n }\n }\n }\n`;\n\nexport const UPDATE_VENDORS = gql`\n mutation TranscendCliUpdateVendor($input: UpdateVendorsInput!) {\n updateVendors(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// orderBy: [\n// { field: createdAt, direction: ASC }\n// { field: name, direction: ASC }\n// ]\nexport const DATA_SUB_CATEGORIES = gql`\n query TranscendCliDataSubCategories($first: Int!, $offset: Int!) {\n dataSubCategories(\n first: $first\n offset: $offset\n isExportCsv: true\n useMaster: false\n ) {\n nodes {\n id\n name\n category\n description\n regex\n teams {\n name\n }\n owners {\n email\n }\n attributeValues {\n attributeKey {\n name\n }\n name\n }\n }\n }\n }\n`;\n\nexport const CREATE_DATA_SUB_CATEGORY = gql`\n mutation TranscendCliCreateDataSubCategory(\n $input: CreateDataInventorySubCategoryInput!\n ) {\n createDataSubCategory(input: $input) {\n dataSubCategory {\n id\n name\n category\n }\n }\n }\n`;\n\nexport const UPDATE_DATA_SUB_CATEGORIES = gql`\n mutation TranscendCliUpdateDataSubCategories(\n $input: UpdateDataSubCategoriesInput!\n ) {\n updateDataSubCategories(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// orderBy: [\n// { field: createdAt, direction: ASC }\n// { field: name, direction: ASC }\n// ]\nexport const PROCESSING_PURPOSE_SUB_CATEGORIES = gql`\n query TranscendCliProcessingPurposeSubCategories(\n $first: Int!\n $offset: Int!\n ) {\n processingPurposeSubCategories(\n first: $first\n offset: $offset\n isExportCsv: true\n useMaster: false\n ) {\n nodes {\n id\n name\n purpose\n description\n teams {\n name\n }\n owners {\n email\n }\n attributeValues {\n attributeKey {\n name\n }\n name\n }\n }\n }\n }\n`;\n\nexport const CREATE_PROCESSING_PURPOSE_SUB_CATEGORY = gql`\n mutation TranscendCliCreateProcessingPurposeSubCategory(\n $input: CreateProcessingPurposeCategoryInput!\n ) {\n createProcessingPurposeSubCategory(input: $input) {\n processingPurposeSubCategory {\n id\n name\n purpose\n }\n }\n }\n`;\n\nexport const UPDATE_PROCESSING_PURPOSE_SUB_CATEGORIES = gql`\n mutation TranscendCliUpdateProcessingPurposeSubCategories(\n $input: UpdateProcessingPurposeSubCategoriesInput!\n ) {\n updateProcessingPurposeSubCategories(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const PROCESSING_ACTIVITIES = gql`\n query TranscendCliProcessingActivities($first: Int!, $offset: Int!) {\n processingActivities(first: $first, offset: $offset, useMaster: false) {\n nodes {\n id\n title\n description\n securityMeasureDetails\n controllerships\n storageRegions {\n countrySubDivision\n country\n }\n transferRegions {\n countrySubDivision\n country\n }\n retentionType\n retentionPeriod\n dataProtectionImpactAssessmentLink\n dataProtectionImpactAssessmentStatus\n attributeValues {\n name\n attributeKey {\n name\n }\n }\n dataSilos {\n title\n }\n dataSubjects {\n type\n }\n teams {\n name\n }\n owners {\n email\n }\n processingPurposeSubCategories {\n name\n purpose\n }\n dataSubCategories {\n name\n category\n }\n saaSCategories {\n title\n }\n }\n }\n }\n`;\n\nexport const CREATE_PROCESSING_ACTIVITY = gql`\n mutation TranscendCliCreateProcessingActivity(\n $input: CreateProcessingActivityInput!\n ) {\n createProcessingActivity(input: $input) {\n processingActivity {\n id\n title\n }\n }\n }\n`;\n\nexport const UPDATE_PROCESSING_ACTIVITIES = gql`\n mutation TranscendCliUpdateProcessingActivities(\n $input: UpdateProcessingActivitiesInput!\n ) {\n updateProcessingActivities(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const SOMBRA_VERSION = gql`\n query TranscendSombraVersion {\n organization {\n sombra {\n version\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const SILO_DISCOVERY_RESULTS = gql`\n query TranscendCliSiloDiscoveryResults($first: Int!, $offset: Int!) {\n siloDiscoveryResults(first: $first, offset: $offset) {\n nodes {\n title\n resourceId\n country\n countrySubDivision\n plaintextContext\n status\n containsSensitiveData\n suggestedCatalog {\n title\n }\n plugin {\n dataSilo {\n title\n }\n }\n }\n }\n }\n`;\n","import { applyEnum, valuesOf } from '@transcend-io/type-utils';\nimport { LOCALE_KEY } from '@transcend-io/internationalization';\nimport {\n CompletedRequestStatus,\n RequestAction,\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\nimport * as t from 'io-ts';\n\nexport const NONE = '[NONE]' as const;\nexport const BULK_APPLY = '[APPLY VALUE TO ALL ROWS]' as const;\nexport const BLANK = '<blank>' as const;\n\n/** These are uploaded at the top level of the request */\nexport const IDENTIFIER_BLOCK_LIST = ['email', 'coreIdentifier'];\n\n/**\n * Column names to map\n */\nexport enum ColumnName {\n /** The title of the email column */\n Email = 'email',\n /** The title of the core identifier column */\n CoreIdentifier = 'coreIdentifier',\n /** The title of the requestType column */\n RequestType = 'requestType',\n /** The title of the subjectType column */\n SubjectType = 'subjectType',\n /** The title of the locale column */\n Locale = 'locale',\n /** The country */\n Country = 'country',\n /** The country sub division */\n CountrySubDivision = 'countrySubDivision',\n /** The title of the requestStatus column */\n RequestStatus = 'requestStatus',\n /** The title of the createdAt column */\n CreatedAt = 'createdAt',\n /** The title of the dataSiloIds column */\n DataSiloIds = 'dataSiloIds',\n}\n\n/** These parameters are required in the Transcend DSR API */\nexport const IS_REQUIRED: { [k in ColumnName]: boolean } = {\n [ColumnName.Email]: false,\n [ColumnName.CoreIdentifier]: true,\n [ColumnName.RequestType]: true,\n [ColumnName.SubjectType]: true,\n [ColumnName.RequestStatus]: false,\n [ColumnName.CreatedAt]: false,\n [ColumnName.DataSiloIds]: false,\n [ColumnName.Locale]: false,\n [ColumnName.Country]: false,\n [ColumnName.CountrySubDivision]: false,\n};\n\n/** These parameters can be specified for the entire CSV set if needed */\nexport const CAN_APPLY_IN_BULK: { [k in ColumnName]?: boolean } = {\n [ColumnName.RequestType]: true,\n [ColumnName.SubjectType]: true,\n};\n\n// Cache state\nexport const CachedFileState = t.type({\n /** Mapping between the default request input column names and the CSV column name for that input */\n columnNames: t.partial(applyEnum(ColumnName, () => t.string)),\n /** Mapping between the identifier names and the CSV column name for that input */\n identifierNames: t.record(t.string, t.string),\n /** Mapping between the request attribute inputs and the CSV column name for that input */\n attributeNames: t.record(t.string, t.string),\n /** Mapping between CSV request type and Transcend Request Action */\n requestTypeToRequestAction: t.record(t.string, valuesOf(RequestAction)),\n /** Mapping between CSV data subject type and the name of the data subject in Transcend */\n subjectTypeToSubjectName: t.record(t.string, t.string),\n /** Mapping between language imported and Transcend locale code */\n languageToLocale: t.record(t.string, valuesOf(LOCALE_KEY)),\n /** Mapping between region and country code */\n regionToCountry: t.record(\n t.string,\n valuesOf({ ...IsoCountryCode, [NONE]: NONE }),\n ),\n /** Mapping between region and country sub division code */\n regionToCountrySubDivision: t.record(\n t.string,\n valuesOf({ ...IsoCountrySubdivisionCode, [NONE]: NONE }),\n ),\n /** Mapping between request status in import to Transcend request status */\n statusToRequestStatus: t.record(\n t.string,\n valuesOf({ ...CompletedRequestStatus, [NONE]: NONE }),\n ),\n});\n\n/** Type override */\nexport type CachedFileState = t.TypeOf<typeof CachedFileState>;\n\n/**\n * Successfully processed request\n */\nexport const SuccessfulRequest = t.type({\n id: t.string,\n link: t.string,\n rowIndex: t.number,\n coreIdentifier: t.string,\n attemptedAt: t.string,\n});\n\n/** Type override */\nexport type SuccessfulRequest = t.TypeOf<typeof SuccessfulRequest>;\n\n// Cache state\nexport const CachedRequestState = t.type({\n /** Set of privacy requests that failed to upload */\n failingRequests: t.array(t.record(t.string, t.any)),\n /** Successfully uploaded requests */\n successfulRequests: t.array(SuccessfulRequest),\n /** Duplicate requests */\n duplicateRequests: t.array(\n t.type({\n rowIndex: t.number,\n coreIdentifier: t.string,\n attemptedAt: t.string,\n }),\n ),\n});\n\n/** Type override */\nexport type CachedRequestState = t.TypeOf<typeof CachedRequestState>;\n","import inquirer from 'inquirer';\nimport { NONE, BULK_APPLY } from './constants';\n\nimport fuzzysearch from 'fuzzysearch';\n\n/**\n * Check if word1 and word2 are a fuzzy match of each other.\n * Returns true if word1 is fuzzy match of word2 or vice versa.\n *\n * @param word1 - First word\n * @param word2 - Second word\n * @returns True if words are fuzzy match\n */\nexport function fuzzySearch(word1: string, word2: string): boolean {\n return (\n fuzzysearch(word1.toLowerCase(), word2.toLowerCase()) ||\n fuzzysearch(word2.toLowerCase(), word1.toLowerCase())\n );\n}\n\n/**\n * Fuzzy match column names for a particular field\n *\n * @param allColumnNames - List of all column names\n * @param fuzzyMapName - The name of field being mapped to\n * @param isRequired - When true, don't include \"NONE\" as an option\n * @param canApplyAll - When true, include an option to specify the value in bulk\n * @returns The list of suggestions for inquirer\n */\nexport function fuzzyMatchColumns(\n allColumnNames: string[],\n fuzzyMapName: string,\n isRequired: boolean,\n canApplyAll?: boolean,\n): (string | InstanceType<typeof inquirer.Separator>)[] {\n const matchingColumnNames = allColumnNames.filter((x) =>\n fuzzySearch(fuzzyMapName.toLowerCase(), x.toLowerCase()),\n );\n return [\n ...matchingColumnNames,\n new inquirer.Separator(),\n ...(isRequired ? [] : [NONE]),\n ...(canApplyAll ? [BULK_APPLY] : []),\n ...allColumnNames.filter((x) => !matchingColumnNames.includes(x)),\n ];\n}\n","import inquirer from 'inquirer';\nimport autoCompletePrompt from 'inquirer-autocomplete-prompt';\nimport { apply, ObjByString } from '@transcend-io/type-utils';\nimport { fuzzySearch } from './fuzzyMatchColumns';\n\n/**\n * Map a set of inputs to a set of outputs\n *\n * @param csvInputs - Input list\n * @param expectedOutputs - Output list\n * @param cache - Cache\n * @returns Mapping from row to enum value\n */\nexport async function mapEnumValues<TValue extends string>(\n csvInputs: string[],\n expectedOutputs: TValue[],\n cache: { [k in string]: TValue },\n): Promise<{ [k in string]: TValue }> {\n inquirer.registerPrompt('autocomplete', autoCompletePrompt);\n\n const inputs = csvInputs\n .map((item) => item || '<blank>')\n .filter((value) => !cache[value]);\n if (inputs.length === 0) {\n return cache;\n }\n const result = await inquirer.prompt<{ [k in string]: TValue }>(\n inputs.map((value) => ({\n name: value,\n message: `Map value of: ${value}`,\n type: 'autocomplete',\n default: expectedOutputs.find((x) => fuzzySearch(value, x)),\n source: (answersSoFar: ObjByString, input: string) =>\n !input\n ? expectedOutputs\n : expectedOutputs.filter(\n (x) => typeof x === 'string' && fuzzySearch(input, x),\n ),\n })),\n );\n return {\n ...cache,\n ...apply(result, (r) =>\n typeof r === 'string' ? (r as TValue) : (Object.values(r)[0] as TValue),\n ),\n };\n}\n","/**\n * Split string to CSV\n *\n * Filter out double commas and spaces like:\n * Dog, Cat -> ['Dog', 'Cat']\n * Dog,,Cat -> ['Dog', 'Cat']\n *\n * @param value - Value\n * @returns List of values\n */\nexport function splitCsvToList(value: string): string[] {\n return value\n .split(',')\n .map((x) => x.trim())\n .filter((x) => x);\n}\n","import colors from 'colors';\nimport * as t from 'io-ts';\nimport { logger } from '../../logger';\n\nexport const ParsedAttributeInput = t.type({\n /** Attribute key */\n key: t.string,\n /** Attribute values */\n values: t.array(t.string),\n});\n\n/** Type override */\nexport type ParsedAttributeInput = t.TypeOf<typeof ParsedAttributeInput>;\n\n/**\n * Parse out the extra attributes to apply to all requests uploaded\n *\n * @param attributes - input as string, e.g. ['key:value1;value2','key2:value3;value4']\n * @returns The parsed attributes\n */\nexport function parseAttributesFromString(\n attributes: string[],\n): ParsedAttributeInput[] {\n // Parse out the extra attributes to apply to all requests uploaded\n const parsedAttributes = attributes.map((attribute) => {\n const [attributeKey, attributeValuesRaw] = attribute.trim().split(':');\n if (!attributeValuesRaw) {\n throw new Error(\n 'Expected attributes in key:value1;value2,key2:value3;value4',\n );\n }\n const attributeValues = attributeValuesRaw.split(';');\n return {\n key: attributeKey,\n values: attributeValues,\n };\n });\n logger.info(colors.magenta('Attributes to apply to all requests:'));\n logger.info(colors.magenta(JSON.stringify(parsedAttributes, null, 2)));\n return parsedAttributes;\n}\n","import type { Options } from 'csv-parse';\nimport { parse } from 'csv-parse/sync';\nimport { readFileSync } from 'node:fs';\nimport * as t from 'io-ts';\n\nimport { decodeCodec } from '@transcend-io/type-utils';\n\n/**\n * Read in a CSV and validate its shape\n *\n * @param pathToFile - Path to file\n * @param codec - The codec to validate against. This is the codec for individual, non-header, rows\n * @param options - CSV parse options\n * @returns The JSON data\n */\nexport function readCsv<T extends t.Any>(\n pathToFile: string,\n codec: T,\n options: Options = { columns: true },\n): t.TypeOf<T>[] {\n // read file contents and parse\n const fileContent = parse(readFileSync(pathToFile, 'utf-8'), options);\n\n // validate codec\n const data = decodeCodec(t.array(codec), fileContent);\n\n // remove any special characters from object keys\n const parsed = data.map((datum) =>\n Object.entries(datum).reduce(\n (acc, [key, value]) =>\n Object.assign(acc, {\n [key.replace(/[^a-z_.+\\-A-Z -~]/g, '')]: value,\n }),\n {} as T,\n ),\n );\n return parsed;\n}\n","import { ObjByString } from '@transcend-io/type-utils';\nimport { uniq } from 'lodash-es';\n\n/**\n * Return the unique set of values for a column in a CSV\n *\n * @param rows - Rows to look up\n * @param columnName - Name of column to grab values for\n * @returns Unique set of values in that column\n */\nexport function getUniqueValuesForColumn(\n rows: ObjByString[],\n columnName: string,\n): string[] {\n return uniq(rows.map((row) => row[columnName] || '').flat());\n}\n","import inquirer from 'inquirer';\nimport { ObjByString } from '@transcend-io/type-utils';\nimport colors from 'colors';\nimport { uniq } from 'lodash-es';\nimport { logger } from '../../logger';\nimport { NONE } from './constants';\nimport { getUniqueValuesForColumn } from './getUniqueValuesForColumn';\n\n/**\n * Filter a list of CSV rows by column values\n * Choose columns that contain metadata to filter the requests\n *\n * @param rows - Rows to filter\n * @returns Filtered rows\n */\nexport async function filterRows(rows: ObjByString[]): Promise<ObjByString[]> {\n // Determine set of column names\n const columnNames = uniq(rows.map((x) => Object.keys(x)).flat());\n\n // update these variables recursively\n let filteredRows = rows;\n let keepFiltering = true;\n\n // loop over\n while (keepFiltering) {\n // Prompt user for column to filter on\n\n const { filterColumnName } = await inquirer.prompt<{\n /** Name of column to filter on */\n filterColumnName: string;\n }>([\n {\n name: 'filterColumnName',\n // eslint-disable-next-line max-len\n message: `If you need to filter the list of requests to import, choose the column to filter on. Currently ${filteredRows.length} rows.`,\n type: 'list',\n default: columnNames,\n choices: [NONE, ...columnNames],\n },\n ]);\n\n // Determine if filtering should continue, or loop should be exited\n keepFiltering = NONE !== filterColumnName;\n if (keepFiltering) {\n const options = getUniqueValuesForColumn(filteredRows, filterColumnName);\n\n const { valuesToKeep } = await inquirer.prompt<{\n /** Values to keep */\n valuesToKeep: string[];\n }>([\n {\n name: 'valuesToKeep',\n message: 'Keep rows matching this value',\n type: 'checkbox',\n default: columnNames,\n choices: options,\n },\n ]);\n\n filteredRows = filteredRows.filter((request) =>\n valuesToKeep.includes(request[filterColumnName]),\n );\n }\n }\n\n logger.info(colors.magenta(`Importing ${filteredRows.length} requests`));\n return filteredRows;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { ADD_MESSAGES_TO_PROMPT_RUN } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { QueueStatus, ChatCompletionRole } from '@transcend-io/privacy-types';\n\nexport interface AddMessagesToPromptRunInput {\n /** ID of run */\n promptRunId:\n | {\n /** Report by prompt run name */\n name: string;\n /** Don't report by ID */\n id?: undefined;\n }\n | {\n /** Don't report by name */\n name?: undefined;\n /** Report by prompt run ID */\n id: string;\n };\n /** Messages to report on */\n promptRunMessages?: {\n /** Message reported */\n content: string;\n /** Role of message */\n role: ChatCompletionRole;\n /** Template used if created from prompt */\n template?: string;\n }[];\n /** Error message (if one exists) */\n error?: string;\n /** The status of the run */\n status?: QueueStatus;\n /** Duration of time that it took to execute the prompt */\n duration?: number;\n}\n\n/**\n * Record a new prompt run\n *\n * @param client - GraphQL client\n * @param input - Prompt input\n * @returns Prompt ID\n */\nexport async function addMessagesToPromptRun(\n client: GraphQLClient,\n { promptRunId, promptRunMessages = [], ...rest }: AddMessagesToPromptRunInput,\n): Promise<string> {\n const {\n addMessagesToPromptRun: { promptRun },\n } = await makeGraphQLRequest<{\n /** addMessagesToPromptRun mutation */\n addMessagesToPromptRun: {\n /** Prompt */\n promptRun: {\n /** ID */\n id: string;\n };\n };\n }>(client, ADD_MESSAGES_TO_PROMPT_RUN, {\n input: {\n ...rest,\n ...promptRunId,\n promptRunMessages: promptRunMessages.map(({ content, ...rest }) => ({\n ...rest,\n message: content,\n })),\n },\n });\n return promptRun.id;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { version } from '../../../package.json';\n\n/**\n * Create a GraphQL client\n *\n * @param transcendUrl - Transcend API URL\n * @param headers - Request headers to include in each request\n * @returns GraphQL client\n */\nexport function buildTranscendGraphQLClientGeneric(\n transcendUrl: string,\n headers: Record<string, string>,\n): GraphQLClient {\n // Create a GraphQL client\n return new GraphQLClient(`${transcendUrl}/graphql`, {\n headers: {\n ...headers,\n version,\n },\n });\n}\n\n/**\n * Create a GraphQL client capable of submitting requests with an API key\n *\n * @param transcendUrl - Transcend API URL\n * @param auth - API key to authenticate to API\n * @returns GraphQL client\n */\nexport function buildTranscendGraphQLClient(\n transcendUrl: string,\n auth: string,\n): GraphQLClient {\n return buildTranscendGraphQLClientGeneric(transcendUrl, {\n Authorization: `Bearer ${auth}`,\n });\n}\n","import got, { Got } from 'got';\nimport colors from 'colors';\nimport { ORGANIZATION } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { buildTranscendGraphQLClient } from './buildTranscendGraphQLClient';\nimport { logger } from '../../logger';\n\n/**\n * Instantiate an instance of got that is capable of making requests\n * to a sombra gateway.\n *\n * @param transcendUrl - URL of Transcend API\n * @param transcendApiKey - Transcend API key\n * @param sombraApiKey - Sombra API key\n * @returns The instance of got that is capable of making requests to the customer ingress\n */\nexport async function createSombraGotInstance(\n transcendUrl: string,\n transcendApiKey: string,\n sombraApiKey?: string,\n): Promise<Got> {\n // Create GraphQL client to connect to Transcend backend\n const client = buildTranscendGraphQLClient(transcendUrl, transcendApiKey);\n // Grab metadata about organization's sombra from GraphQL endpoint\n const { organization } = await makeGraphQLRequest<{\n /** Requests */\n organization: {\n /** PrimarySombra related to organization */\n sombra: {\n /** URL of sombra */\n customerUrl: string;\n };\n };\n }>(client, ORGANIZATION);\n // Use SOMBRA_URL env var if provided, otherwise fall back to the primary sombra's customerUrl\n const { customerUrl } = organization.sombra;\n const sombraToUse = process.env.SOMBRA_URL || customerUrl;\n\n // Only validate the reverse tunnel URL if we're using the primary sombra (not SOMBRA_URL override)\n if (\n !process.env.SOMBRA_URL &&\n [\n 'https://sombra-reverse-tunnel.transcend.io',\n 'https://sombra-reverse-tunnel.us.transcend.io',\n ].includes(customerUrl)\n ) {\n throw new Error(\n 'It looks like your Sombra customer ingress URL has not been set up. ' +\n 'Please follow the instructions here to configure networking for Sombra: ' +\n 'https://docs.transcend.io/docs/articles/sombra/deploying/customizing-sombra/networking',\n );\n }\n logger.info(colors.green(`Using sombra: ${sombraToUse}`));\n\n // Create got instance with default values\n return got.extend({\n prefixUrl: sombraToUse,\n headers: {\n Authorization: `Bearer ${transcendApiKey}`,\n ...(sombraApiKey\n ? {\n 'X-Sombra-Authorization': `Bearer ${sombraApiKey}`,\n }\n : {}),\n },\n });\n}\n","import got, { Got } from 'got';\n\n/**\n * Instantiate an instance of got that is capable of making requests\n * to a sombra gateway.\n *\n * @param transcendUrl - URL of Transcend API\n * @returns The instance of got that is capable of making requests to the customer ingress\n */\nexport function createTranscendConsentGotInstance(transcendUrl: string): Got {\n // Create got instance with default values\n return got.extend({\n prefixUrl: transcendUrl,\n });\n}\n","import { ConsentBundleType } from '@transcend-io/privacy-types';\nimport { GraphQLClient } from 'graphql-request';\nimport {\n UPDATE_CONSENT_MANAGER_TO_LATEST,\n DEPLOY_CONSENT_MANAGER,\n} from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\n/**\n * Deploy the Consent Manager\n *\n * @param client - GraphQL client\n * @param options - Options\n */\nexport async function deployConsentManager(\n client: GraphQLClient,\n {\n id,\n bundleType,\n }: {\n /** ID of Consent Manager */\n id: string;\n /** Type of bundle */\n bundleType: ConsentBundleType;\n },\n): Promise<void> {\n await makeGraphQLRequest(client, DEPLOY_CONSENT_MANAGER, {\n airgapBundleId: id,\n bundleType,\n });\n}\n\n/**\n * Update the Consent Manager to the latest airgap.jz version\n *\n * @param client - GraphQL client\n * @param options - Options\n */\nexport async function updateConsentManagerToLatest(\n client: GraphQLClient,\n {\n id,\n bundleType,\n }: {\n /** ID of Consent Manager */\n id: string;\n /** Type of bundle */\n bundleType: ConsentBundleType;\n },\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_CONSENT_MANAGER_TO_LATEST, {\n airgapBundleId: id,\n bundleType,\n });\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { logger } from '../../logger';\nimport { ENABLED_PLUGINS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface Plugin {\n /** Associated data silo */\n dataSilo: {\n /** The type of plugin */\n type: string;\n };\n /** The ID of this plugin */\n id: string;\n}\n\nexport interface PluginResponse {\n /** The key object of the response */\n plugins: {\n /** The total count */\n totalCount: number;\n /** The list of plugins */\n plugins: Plugin[];\n };\n}\n\n/**\n * Fetch a data silo discovery plugin\n *\n * @param client - GraphQL client\n * @param dataSiloId - The data silo to look up plugins for\n * @returns An active data silo plugin (if multiple, returns the first)\n */\nexport async function fetchActiveSiloDiscoPlugin(\n client: GraphQLClient,\n dataSiloId: string,\n): Promise<Plugin> {\n const response = await makeGraphQLRequest<PluginResponse>(\n client,\n ENABLED_PLUGINS,\n {\n dataSiloId,\n type: 'DATA_SILO_DISCOVERY',\n },\n );\n\n const { plugins, totalCount } = response.plugins;\n if (totalCount === 0) {\n logger.error('No active data silo plugins found for this data silo.');\n process.exit(1);\n }\n\n const plugin = plugins[0];\n return plugin;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { GLOBAL_ACTION_ITEMS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n ActionItemCode,\n ActionItemPriorityOverride,\n} from '@transcend-io/privacy-types';\n\nexport interface ActionItemRaw {\n /** ID of action item */\n ids: string[];\n /** Count of action items */\n count: number;\n /** Teams assigned to action items */\n teams: {\n /** ID of team */\n id: string;\n /** Name of team */\n name: string;\n }[];\n /** Customer experience action item ID */\n customerExperienceActionItemIds: string[];\n /** Users assigned to the action item */\n users: {\n /** ID of user */\n id: string;\n /** User email */\n email: string;\n }[];\n /** Due date of action item */\n dueDate?: string;\n /** Priority of action item */\n priority?: ActionItemPriorityOverride;\n /** Titles of action items */\n titles: string[];\n /** Description of the action item */\n resolved: boolean;\n /** Notes */\n notes: string[];\n /** links */\n links: string[];\n /** Action item types */\n type: ActionItemCode;\n /** Custom fields */\n attributeValues: {\n /** Name of attribute value */\n name: string;\n /** Attribute key that the value represents */\n attributeKey: {\n /** Name of attribute team */\n name: string;\n };\n }[];\n /** Additional context related to action item */\n additionalContexts?: {\n /** Override of icon */\n iconOverride?: string;\n /** Request ID */\n requestId?: string;\n /** Data Silo ID */\n dataSiloId?: string;\n /** Request type */\n requestType?: string;\n /** Airgap version */\n latestAirgapVersion?: string;\n /** Parent title */\n parentTitle?: string;\n };\n /** Sections where action item is grouped under */\n collections: {\n /** ID of collection that action item belongs to */\n id: string;\n /** Title of collection */\n title: string;\n }[];\n}\n\nexport interface ActionItem\n extends Omit<ActionItemRaw, 'ids' | 'titles' | 'links' | 'notes'> {\n /** ID of action item */\n id: string;\n /** Title of action item */\n title: string;\n /** Notes */\n notes: string;\n /** Links */\n link: string;\n /** Sections where action item is grouped under */\n collections: {\n /** ID of collection that action item belongs to */\n id: string;\n /** Title of collection */\n title: string;\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all action items in the organization\n *\n * @param client - GraphQL client\n * @param filterBy - Filter by\n * @returns All action items in the organization\n */\nexport async function fetchAllActionItems(\n client: GraphQLClient,\n filterBy: {\n /** Names of the action items to filter for */\n priority?: ActionItemPriorityOverride[];\n /** Type of action item */\n type?: ActionItemCode[];\n /** Whether resolved or not */\n resolved?: boolean;\n /** Filter for action items due before this date */\n startDueDate?: Date;\n /** Filter for action items due after this date */\n endDueDate?: Date;\n } = {},\n): Promise<ActionItem[]> {\n const actionItems: ActionItem[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n globalActionItems: { nodes },\n } = await makeGraphQLRequest<{\n /** ActionItems */\n globalActionItems: {\n /** List */\n nodes: ActionItemRaw[];\n };\n }>(client, GLOBAL_ACTION_ITEMS, {\n first: PAGE_SIZE,\n offset,\n filterBy: {\n ...filterBy,\n ...(filterBy.startDueDate\n ? { startDueDate: filterBy.startDueDate.toISOString() }\n : {}),\n ...(filterBy.endDueDate\n ? { endDueDate: filterBy.endDueDate.toISOString() }\n : {}),\n },\n });\n actionItems.push(\n ...nodes.map((node) => ({\n ...node,\n id: node.ids[0],\n title: node.titles[0],\n notes: node.notes[0],\n link: node.links[0],\n })),\n );\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return actionItems;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport {\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n RegionDetectionMethod,\n RequestAction,\n} from '@transcend-io/privacy-types';\nimport { ACTIONS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface Action {\n /** ID of identifier */\n id: string;\n /** Type of action */\n type: RequestAction;\n /** Whether to skip secondary when no files exist */\n skipSecondaryIfNoFiles: boolean;\n /** Whether to skip downloadable step */\n skipDownloadableStep: boolean;\n /** Whether action requires review */\n requiresReview: boolean;\n /** Waiting period for action */\n waitingPeriod: number;\n /** Method in which the data subject's region is detected */\n regionDetectionMethod: RegionDetectionMethod;\n /** The list of regions to show in the form */\n regionList: (IsoCountryCode | IsoCountrySubdivisionCode)[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all actions in the organization\n *\n * @param client - GraphQL client\n * @returns All actions in the organization\n */\nexport async function fetchAllActions(\n client: GraphQLClient,\n): Promise<Action[]> {\n const actions: Action[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n actions: { nodes },\n } = await makeGraphQLRequest<{\n /** Actions */\n actions: {\n /** List */\n nodes: Action[];\n };\n }>(client, ACTIONS, {\n first: PAGE_SIZE,\n offset,\n });\n actions.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return actions.sort((a, b) => a.type.localeCompare(b.type));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { AGENT_FILES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { PromptFilePurpose } from '@transcend-io/privacy-types';\n\nexport interface AgentFile {\n /** ID of agentFile */\n id: string;\n /** Name of agentFile */\n name: string;\n /** Description of the agentFile */\n description: string;\n /** Initial file name, useful to track if a file was split into multiple chunks */\n initialFileName?: string;\n /** File ID */\n fileId: string;\n /** File size */\n size: number;\n /** File purpose */\n purpose: PromptFilePurpose;\n}\n\nconst PAGE_SIZE = 20;\n\nexport interface AgentFileFilterBy {\n /** Filter by remote file IDs */\n fileIds?: string[];\n /** Filter by file names */\n names?: string[];\n /** Filter by initial file names (when split into chunks) */\n initialFileNames?: string[];\n}\n\n/**\n * Fetch all agentFiles in the organization\n *\n * @param client - GraphQL client\n * @param filterBy - Filter by options\n * @returns All agentFiles in the organization\n */\nexport async function fetchAllAgentFiles(\n client: GraphQLClient,\n filterBy: AgentFileFilterBy = {},\n): Promise<AgentFile[]> {\n const agentFiles: AgentFile[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n agentFiles: { nodes },\n } = await makeGraphQLRequest<{\n /** AgentFiles */\n agentFiles: {\n /** List */\n nodes: AgentFile[];\n };\n }>(client, AGENT_FILES, {\n first: PAGE_SIZE,\n offset,\n filterBy,\n });\n agentFiles.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return agentFiles.sort((a, b) => a.name.localeCompare(b.name));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { AGENT_FUNCTIONS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport type { JSONSchema7 } from 'json-schema';\n\nexport interface AgentFunction {\n /** ID of agentFunction */\n id: string;\n /** Name of agentFunction */\n name: string;\n /** Description of the agentFunction */\n description: string;\n /** The JSON schema */\n parameters: JSONSchema7;\n}\n\ninterface AgentFunctionInput extends Omit<AgentFunction, 'parameters'> {\n /** Stringified parameters */\n parameters: string;\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all agentFunctions in the organization\n *\n * @param client - GraphQL client\n * @returns All agentFunctions in the organization\n */\nexport async function fetchAllAgentFunctions(\n client: GraphQLClient,\n): Promise<AgentFunction[]> {\n const agentFunctions: AgentFunction[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n agentFunctions: { nodes },\n } = await makeGraphQLRequest<{\n /** AgentFunctions */\n agentFunctions: {\n /** List */\n nodes: AgentFunctionInput[];\n };\n }>(client, AGENT_FUNCTIONS, {\n first: PAGE_SIZE,\n offset,\n });\n agentFunctions.push(\n ...nodes.map((node) => ({\n ...node,\n parameters: JSON.parse(node.parameters),\n })),\n );\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return agentFunctions.sort((a, b) => a.name.localeCompare(b.name));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { AGENTS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { LargeLanguageModelClient } from '@transcend-io/privacy-types';\n\nexport interface Agent {\n /** ID of agent */\n id: string;\n /** Name of agent */\n name: string;\n /** Agent instructions */\n instructions: string;\n /** The ID of the agent */\n agentId: string;\n /** Description of the agent */\n description: string;\n /** Whether the agent has code interpreter enabled */\n codeInterpreterEnabled: boolean;\n /** Whether the agent has retrieval enabled */\n retrievalEnabled: boolean;\n /** The prompt that the agent is based on */\n prompt?: {\n /** Title of the prompt */\n title: string;\n };\n /** Large language model that the agent is based on */\n largeLanguageModel: {\n /** Name of model */\n name: string;\n /** Client */\n client: LargeLanguageModelClient;\n };\n /** Teams assigned to the agent */\n teams: {\n /** Team name */\n name: string;\n }[];\n /** Users assigned to the agent */\n owners: {\n /** User email */\n email: string;\n }[];\n /** Functions that the agent has access to */\n agentFunctions: {\n /** Function name */\n name: string;\n }[];\n /** Files that the agent has access to */\n agentFiles: {\n /** File name */\n name: string;\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all agents in the organization\n *\n * @param client - GraphQL client\n * @param filterBy - Filter by\n * @returns All agents in the organization\n */\nexport async function fetchAllAgents(\n client: GraphQLClient,\n filterBy: {\n /** Names of the agents to filter for */\n names?: string[];\n /** IDs of agents */\n agentIds?: string[];\n } = {},\n): Promise<Agent[]> {\n const agents: Agent[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n agents: { nodes },\n } = await makeGraphQLRequest<{\n /** Agents */\n agents: {\n /** List */\n nodes: Agent[];\n };\n }>(client, AGENTS, {\n first: PAGE_SIZE,\n offset,\n filterBy,\n });\n agents.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return agents.sort((a, b) => a.name.localeCompare(b.name));\n}\n","/* eslint-disable max-lines */\nimport { GraphQLClient } from 'graphql-request';\nimport { ASSESSMENTS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n AssessmentFormStatus,\n AssessmentQuestionSubType,\n AssessmentQuestionType,\n AssessmentSyncColumn,\n AssessmentSyncModel,\n AttributeSupportedResourceType,\n DataCategoryType,\n ProcessingPurpose,\n RetentionScheduleOperation,\n RetentionScheduleType,\n} from '@transcend-io/privacy-types';\n\n/**\n * Represents an assessment with various properties and metadata.\n */\nexport interface Assessment {\n /** The ID of the assessment */\n id: string;\n /** The user who created the assessment */\n creator: UserPreview;\n /** The user who last edited the assessment */\n lastEditor: UserPreview;\n /** The title of the assessment */\n title: string;\n /** The description of the assessment */\n description: string;\n /** The current status of the assessment */\n status: AssessmentFormStatus;\n /** The users assigned to the assessment */\n assignees: UserPreview[];\n /** The external users assigned to the assessment */\n externalAssignees: ExternalUser[];\n /** The users who are reviewers of the assessment */\n reviewers: UserPreview[];\n /** Indicates if the assessment is locked */\n isLocked: boolean;\n /** Indicates if the assessment is archived */\n isArchived: boolean;\n /** Indicates if the assessment was created externally */\n isExternallyCreated: boolean;\n /** The due date of the assessment */\n dueDate: string;\n /** The date when the assessment was created */\n createdAt: string;\n /** The date when the assessment was last updated */\n updatedAt: string;\n /** The date when the assessment was assigned */\n assignedAt: string;\n /** The date when the assessment was submitted */\n submittedAt: string;\n /** The date when the assessment was approved */\n approvedAt: string;\n /** The date when the assessment was rejected */\n rejectedAt: string;\n /** Indicates if the title of the assessment is internal */\n titleIsInternal: boolean;\n /** The retention schedule of the assessment */\n retentionSchedule?: RetentionSchedule;\n /** The attribute values associated with the assessment */\n attributeValues: AttributeValue[];\n /** The sections of the assessment */\n sections: AssessmentSection[];\n /** The group to which the assessment belongs */\n assessmentGroup: AssessmentGroup;\n /** The resources associated with the assessment */\n resources: AssessmentResource[];\n /** The rows that are synced with the assessment */\n syncedRows: AssessmentResource[];\n}\n\nexport interface UserPreview {\n /** ID of user */\n id: string;\n /** Email of user */\n email: string;\n /** Name of user */\n name: string;\n}\n\nexport interface ExternalUser {\n /** ID of external user */\n id: string;\n /** Email of external user */\n email: string;\n}\n\nexport interface RetentionSchedule {\n /** ID of retention schedule */\n id: string;\n /** Type */\n type: RetentionScheduleType;\n /** Duration of retention schedule */\n durationDays: number;\n /** The operation to perform on the retention schedule */\n operation: RetentionScheduleOperation;\n}\n\ninterface AttributeValue {\n /** Name of attribute value */\n name: string;\n /** Key */\n attributeKey: {\n /** Name of key */\n name: string;\n };\n}\n\nexport interface AssessmentSection {\n /** ID of section */\n id: string;\n /** Title of section */\n title: string;\n /** Status of section */\n status: string;\n /** Index of section */\n index: number;\n /** Questions */\n questions: AssessmentQuestion[];\n /** Assignees */\n assignees: UserPreview[];\n /** External assignees */\n externalAssignees: ExternalUser[];\n /** Whether is reviewed */\n isReviewed: boolean;\n}\n\n/**\n * Represents a question in the assessment.\n */\nexport interface AssessmentQuestion {\n /**\n * Unique identifier for the question.\n */\n id: string;\n /** Title of the question */\n title: string;\n /** Index of the question in the assessment */\n index: number;\n /** Type of the question */\n type: AssessmentQuestionType;\n /** Subtype of the question */\n subType: AssessmentQuestionSubType;\n /** Placeholder text for the question */\n placeholder: string;\n /** Description of the question */\n description: string;\n /** Indicates if the question is required */\n isRequired: boolean;\n /** Logic for displaying the question */\n displayLogic: string;\n /** Logic for assessing risk related to the question */\n riskLogic: string[];\n /** Indicates if risk evaluation is required for the question */\n requireRiskEvaluation: boolean;\n /** Indicates if risk matrix evaluation is required for the question */\n requireRiskMatrixEvaluation: boolean;\n /** Categories of risk associated with the question */\n riskCategories: RiskCategory[];\n /** Framework used for risk assessment */\n riskFramework?: RiskFramework;\n /** Level of risk associated with the question */\n riskLevel?: RiskLevel;\n /** Risk level assigned by the reviewer */\n reviewerRiskLevel?: RiskLevel;\n /** Risk level derived from the risk matrix */\n riskLevelFromRiskMatrix?: RiskLevel;\n /** Options available for answering the question */\n answerOptions: AssessmentAnswerOption[];\n /** Answers selected for the question */\n selectedAnswers: AssessmentAnswer[];\n /** User who responded to the question */\n respondent: UserPreview;\n /** Key attribute associated with the question */\n attributeKey?: {\n /** Name of key */\n name: string;\n };\n /** Email of the external respondent */\n externalRespondentEmail?: string;\n /** Comments related to the question */\n comments: unknown[];\n /** Allowed MIME types for file uploads in the question */\n allowedMimeTypes: string[];\n /** Timestamp of the last update to the question */\n updatedAt: string;\n /** Reference identifier for the question */\n referenceId: string;\n /** Previous submissions related to the question */\n previousSubmissions: AssessmentPreviousSubmission[];\n /** Indicates if selecting \"Other\" is allowed for the question */\n allowSelectOther: boolean;\n /** Model used for synchronization */\n syncModel: AssessmentSyncModel;\n /** Column used for synchronization */\n syncColumn: AssessmentSyncColumn;\n /** Row IDs used for synchronization */\n syncRowIds: string[];\n /** Indicates if synchronization override is allowed */\n syncOverride: boolean;\n}\n\nexport interface RiskCategory {\n /** ID of category */\n id: string;\n /** Title of category */\n title: string;\n}\n\nexport interface RiskFramework {\n /** ID of framework */\n id: string;\n /** Title of framework */\n title: string;\n /** Description of framework */\n description: string;\n /** Risk levels */\n riskLevels: RiskLevel[];\n /** Risk categories */\n riskCategories: RiskCategory[];\n /** Risk matrix columns */\n riskMatrixColumns: RiskMatrixColumn[];\n /** Risk matrix rows */\n riskMatrixRows: RiskMatrixRow[];\n /** Risk matrix settings */\n riskMatrix: RiskMatrix[][];\n /** Creator of risk framework */\n creator?: UserPreview;\n /** Risk matrix row title */\n riskMatrixRowTitle: string;\n /** Risk matrix column title */\n riskMatrixColumnTitle: string;\n}\n\nexport interface RiskLevel {\n /** ID of risk level */\n id: string;\n /** Title of risk level */\n title: string;\n}\n\nexport interface RiskMatrix {\n /** ID of risk matrix */\n id: string;\n /** Title of risk matrix */\n title: string;\n}\n\nexport interface RiskMatrixColumn {\n /** ID of column */\n id: string;\n /** Title of column */\n title: string;\n}\n\nexport interface RiskMatrixRow {\n /** ID of row */\n id: string;\n /** Title of row */\n title: string;\n}\n\nexport interface AssessmentAnswerOption {\n /** ID of answer option */\n id: string;\n /** Index of answer option */\n index: number;\n /** Value of answer */\n value: string;\n}\n\nexport interface AssessmentAnswer {\n /** ID of answer */\n id: string;\n /** Index of answer */\n index: number;\n /** Value of answer */\n value: string;\n}\n\nexport interface AssessmentComment {\n /** ID of comment */\n id: string;\n /** Content of comment */\n content: string;\n /** Date comment made */\n createdAt: string;\n /** Date comment updated */\n updatedAt: string;\n /** Author of comment */\n author?: UserPreview;\n}\n\nexport interface AssessmentPreviousSubmission {\n /** Id of submission */\n id: string;\n /** Date updated */\n updatedAt: string;\n /** ID of question */\n assessmentQuestionId: string;\n /** Answers */\n answers: AssessmentAnswer[];\n}\n\nexport interface AssessmentGroup {\n /** ID of group */\n id: string;\n /** Title of group */\n title: string;\n /** Description of group */\n description: string;\n}\n\nexport interface AssessmentResource {\n /** Type of resource */\n resourceType: AttributeSupportedResourceType;\n /** ID of resource */\n id: string;\n /** Title of resource */\n title?: string;\n /** Name of resource */\n name?: string;\n /** Category of resource */\n category?: DataCategoryType;\n /** Purpose of resource */\n purpose?: ProcessingPurpose;\n /** Type of integration */\n type?: string;\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all assessments in the organization\n *\n * @param client - GraphQL client\n * @returns All assessments in the organization\n */\nexport async function fetchAllAssessments(\n client: GraphQLClient,\n): Promise<Assessment[]> {\n const assessments: Assessment[] = [];\n let offset = 0;\n\n let shouldContinue = false;\n do {\n const {\n assessmentForms: { nodes },\n } = await makeGraphQLRequest<{\n /** Forms */\n assessmentForms: {\n /** Nodes */\n nodes: Assessment[];\n };\n }>(client, ASSESSMENTS, {\n first: PAGE_SIZE,\n offset,\n });\n assessments.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return assessments.sort((a, b) => a.title.localeCompare(b.title));\n}\n/* eslint-enable max-lines */\n","import { GraphQLClient } from 'graphql-request';\nimport { ASSESSMENT_TEMPLATES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport type {\n AssessmentSection,\n RetentionSchedule,\n UserPreview,\n} from './fetchAllAssessments';\nimport {\n AssessmentFormTemplateSource,\n AssessmentFormTemplateStatus,\n} from '@transcend-io/privacy-types';\n\n/**\n * Represents an assessment template with various properties and metadata.\n */\nexport interface AssessmentTemplate {\n /** The ID of the assessment template */\n id: string;\n /** The user who created the assessment template */\n creator: UserPreview;\n /** The user who last edited the assessment template */\n lastEditor: UserPreview;\n /** The title of the assessment template */\n title: string;\n /** The description of the assessment template */\n description: string;\n /** The current status of the assessment template */\n status: AssessmentFormTemplateStatus;\n /** The source fo the form template */\n source: AssessmentFormTemplateSource;\n /** ID of parent template */\n parentId: string;\n /** Indicates if the assessment template is locked */\n isLocked: boolean;\n /** Indicates if the assessment template is archived */\n isArchived: boolean;\n /** The date when the assessment template was created */\n createdAt: string;\n /** The date when the assessment template was last updated */\n updatedAt: string;\n /** The retention schedule of the assessment template */\n retentionSchedule?: RetentionSchedule;\n /** The sections of the assessment template */\n sections: AssessmentSection[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all assessment templates in the organization\n *\n * @param client - GraphQL client\n * @returns All assessment templates in the organization\n */\nexport async function fetchAllAssessmentTemplates(\n client: GraphQLClient,\n): Promise<AssessmentTemplate[]> {\n const assessmentTemplates: AssessmentTemplate[] = [];\n let offset = 0;\n\n let shouldContinue = false;\n do {\n const {\n assessmentFormTemplates: { nodes },\n } = await makeGraphQLRequest<{\n /** Templates */\n assessmentFormTemplates: {\n /** Nodes */\n nodes: AssessmentTemplate[];\n };\n }>(client, ASSESSMENT_TEMPLATES, {\n first: PAGE_SIZE,\n offset,\n });\n assessmentTemplates.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return assessmentTemplates.sort((a, b) => a.title.localeCompare(b.title));\n}\n","import type { SombraStandardScope } from '@transcend-io/privacy-types';\nimport { CREATE_PREFERENCE_ACCESS_TOKENS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport type { GraphQLClient } from 'graphql-request';\nimport { chunk } from 'lodash-es';\nimport { map } from '../bluebird';\n\nexport interface PreferenceAccessTokenInput {\n /** Slug of data subject to authenticate as */\n subjectType: string;\n /** Scopes to grant */\n scopes: SombraStandardScope[];\n /** Expiration time in seconds */\n expiresIn?: number;\n /** Email address of user */\n email: string;\n /** Core identifier for the user */\n coreIdentifier?: string;\n}\n\nconst MAX_BATCH_SIZE = 50;\n\n/**\n * Create preference access tokens for the given identifiers.\n *\n * @see https://docs.transcend.io/docs/articles/preference-management/access-links\n * @param client - GraphQL\n * @param records - Inputs to sign\n * @returns list of access tokens\n */\nasync function createPreferenceAccessTokensPage(\n client: GraphQLClient,\n records: PreferenceAccessTokenInput[],\n): Promise<string[]> {\n const {\n createPrivacyCenterAccessTokens: { nodes },\n } = await makeGraphQLRequest<{\n /** createPrivacyCenterAccessTokens mutation */\n createPrivacyCenterAccessTokens: {\n /** Nodes */\n nodes: {\n /** Token */\n token: string;\n }[];\n };\n }>(client, CREATE_PREFERENCE_ACCESS_TOKENS, {\n input: {\n records,\n },\n });\n return nodes.map((node) => node.token);\n}\n\nexport interface PreferenceAccessTokenInputWithIndex\n extends PreferenceAccessTokenInput {\n /** Index of the input record */\n index?: number;\n}\n\n/**\n * Create preference access tokens for the given identifiers.\n *\n * @see https://docs.transcend.io/docs/articles/preference-management/access-links\n * @param client - GraphQL\n * @param records - Inputs to sign\n * @param emitProgress - Optional progress emitter\n * @param concurrency - Number of concurrent requests to make (default: 10)\n * @returns list of access tokens/input identifiers\n */\nexport async function createPreferenceAccessTokens(\n client: GraphQLClient,\n records: PreferenceAccessTokenInputWithIndex[],\n emitProgress?: (progress: number) => void,\n concurrency = 10,\n): Promise<\n {\n /** Identifier for the record */\n input: PreferenceAccessTokenInputWithIndex;\n /** Access token */\n accessToken: string;\n }[]\n> {\n let completed = 0;\n if (emitProgress) {\n emitProgress(0);\n }\n const results: {\n /** Identifier for the record */\n input: PreferenceAccessTokenInput;\n /** Access token */\n accessToken: string;\n }[] = [];\n\n // Then replace the selection with:\n await map(\n chunk(records, MAX_BATCH_SIZE),\n async (chunkedRecords) => {\n const tokens = await createPreferenceAccessTokensPage(\n client,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n chunkedRecords.map(({ index, ...rest }) => rest),\n );\n const mappedResults = tokens.map((token, index) => ({\n input: chunkedRecords[index],\n accessToken: token,\n }));\n results.push(...mappedResults);\n completed += chunkedRecords.length;\n if (emitProgress) {\n emitProgress(completed);\n }\n },\n { concurrency },\n );\n\n return results;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { ATTRIBUTE_KEYS_REQUESTS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface AttributeKey {\n /** ID of attribute key */\n id: string;\n /** Name of attribute key */\n name: string;\n /** Attribute key type */\n type: string;\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all attribute keys enabled for privacy requests\n *\n * @param client - GraphQL client\n * @returns All attribute keys in the organization\n */\nexport async function fetchAllRequestAttributeKeys(\n client: GraphQLClient,\n): Promise<AttributeKey[]> {\n const attributeKeys: AttributeKey[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n attributeKeys: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n attributeKeys: {\n /** List of matches */\n nodes: AttributeKey[];\n };\n }>(client, ATTRIBUTE_KEYS_REQUESTS, {\n first: PAGE_SIZE,\n offset,\n });\n attributeKeys.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return attributeKeys.sort((a, b) => a.name.localeCompare(b.name));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { ATTRIBUTES, ATTRIBUTE_VALUES } from './gqls';\n\nimport { logger } from '../../logger';\nimport colors from 'colors';\nimport {\n AttributeKeyType,\n AttributeSupportedResourceType,\n} from '@transcend-io/privacy-types';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface AttributeValue {\n /** Attribute ID */\n id: string;\n /** Attribute name */\n name: string;\n /** Attribute description */\n description: string;\n /** Color of attribute value */\n color: string;\n}\n\nexport interface Attribute {\n /** ID of attribute */\n id: string;\n /** Name of attribute */\n name: string;\n /** if custom attribute */\n isCustom: boolean;\n /** Description */\n description: string;\n /** Type of attribute */\n type: AttributeKeyType;\n /** Values */\n values: AttributeValue[];\n /** The different fields that the attribute is enabled on */\n enabledOn: AttributeSupportedResourceType[];\n}\n\nconst PAGE_SIZE = 100;\n\n/**\n * Fetch all attribute values for an attribute key\n *\n * @param client - GraphQL client\n * @param attributeKeyId - Attribute keyID\n * @returns A map from apiKey title to Identifier\n */\nexport async function fetchAllAttributeValues(\n client: GraphQLClient,\n attributeKeyId: string,\n): Promise<AttributeValue[]> {\n logger.info(\n colors.magenta(`Fetching all attribute values for ${attributeKeyId}...`),\n );\n const attributeValues: AttributeValue[] = [];\n let offset = 0;\n\n // Paginate\n let shouldContinue = false;\n do {\n const {\n attributeValues: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n attributeValues: {\n /** List of matches */\n nodes: AttributeValue[];\n };\n }>(client, ATTRIBUTE_VALUES, {\n first: PAGE_SIZE,\n offset,\n attributeKeyId,\n });\n attributeValues.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return attributeValues.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport const SYNC_ATTRIBUTE_TYPES = [\n AttributeKeyType.MultiSelect,\n AttributeKeyType.SingleSelect,\n];\n\n/**\n * Fetch all attributes in an organization\n *\n * @param client - GraphQL client\n * @returns A map from apiKey title to Identifier\n */\nexport async function fetchAllAttributes(\n client: GraphQLClient,\n): Promise<Attribute[]> {\n logger.info(colors.magenta('Fetching all attributes...'));\n const attributes: Attribute[] = [];\n let offset = 0;\n\n // Paginate\n let shouldContinue = false;\n do {\n const {\n attributeKeys: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n attributeKeys: {\n /** List of matches */\n nodes: Attribute[];\n };\n }>(client, ATTRIBUTES, {\n first: PAGE_SIZE,\n offset,\n });\n attributes.push(\n ...(await Promise.all(\n nodes.map(async (node) => ({\n ...node,\n values: SYNC_ATTRIBUTE_TYPES.includes(node.type)\n ? await fetchAllAttributeValues(client, node.id)\n : [],\n })),\n )),\n );\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return attributes.sort((a, b) => a.name.localeCompare(b.name));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { BUSINESS_ENTITIES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\n\nexport interface BusinessEntity {\n /** ID of business entity */\n id: string;\n /** Title of business entity */\n title: string;\n /** Description of business entity */\n description?: string;\n /** Data protection officer name */\n dataProtectionOfficerName?: string;\n /** Data protection officer email */\n dataProtectionOfficerEmail?: string;\n /** Address of business entity */\n address?: string;\n /** Headquarters of business entity */\n headquarterCountry?: IsoCountryCode;\n /** Subdivision of business entity */\n headquarterSubDivision?: IsoCountrySubdivisionCode;\n /** Attributes */\n attributeValues: {\n /** Name of attribute value */\n name: string;\n /** Attribute key */\n attributeKey: {\n /** Name of attribute key */\n name: string;\n };\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all businessEntities in the organization\n *\n * @param client - GraphQL client\n * @returns All businessEntities in the organization\n */\nexport async function fetchAllBusinessEntities(\n client: GraphQLClient,\n): Promise<BusinessEntity[]> {\n const businessEntities: BusinessEntity[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n businessEntities: { nodes },\n } = await makeGraphQLRequest<{\n /** Business entities */\n businessEntities: {\n /** List */\n nodes: BusinessEntity[];\n };\n }>(client, BUSINESS_ENTITIES, {\n first: PAGE_SIZE,\n offset,\n });\n businessEntities.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return businessEntities.sort((a, b) => a.title.localeCompare(b.title));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport {\n ConsentPrecedenceOption,\n UnknownRequestPolicy,\n TelemetryPartitionStrategy,\n RegionsOperator,\n IsoCountrySubdivisionCode,\n IsoCountryCode,\n BrowserTimeZone,\n SignedIabAgreementOption,\n} from '@transcend-io/privacy-types';\nimport {\n InitialViewState,\n BrowserLanguage,\n OnConsentExpiry,\n} from '@transcend-io/airgap.js-types';\nimport {\n FETCH_CONSENT_MANAGER_ID,\n FETCH_CONSENT_MANAGER,\n EXPERIENCES,\n CONSENT_MANAGER_ANALYTICS_DATA,\n FETCH_CONSENT_MANAGER_THEME,\n} from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface ConsentManager {\n /** ID of consent manager */\n id: string;\n /** Production bundle URL */\n bundleURL: string;\n /** Test bundle URL */\n testBundleURL: string;\n /** Configuration of consent manager */\n configuration: {\n /** Domain list */\n domains: string[];\n /** Consent precedence of user vs signal */\n consentPrecedence: ConsentPrecedenceOption;\n /** Unknown request policy */\n unknownRequestPolicy: UnknownRequestPolicy;\n /** Unknown cookie policy */\n unknownCookiePolicy: UnknownRequestPolicy;\n /** Sync endpoint */\n syncEndpoint: string;\n /** Telemetry partitioning */\n telemetryPartitioning: TelemetryPartitionStrategy;\n /** Signed IAB agreement */\n signedIabAgreement: SignedIabAgreementOption;\n /** Sync groups */\n syncGroups: string;\n /** Partition parameter */\n partition: string;\n };\n /** When using a custom partition, this is the partition value */\n partition?: {\n /** Partition value */\n partition: string;\n };\n}\n\n/**\n * Fetch consent manager\n *\n * @param client - GraphQL client\n * @returns Consent manager ID in organization\n */\nexport async function fetchConsentManager(\n client: GraphQLClient,\n): Promise<ConsentManager> {\n const {\n consentManager: { consentManager },\n } = await makeGraphQLRequest<{\n /** Consent manager query */\n consentManager: {\n /** Consent manager object */\n consentManager: ConsentManager;\n };\n }>(client, FETCH_CONSENT_MANAGER);\n return consentManager;\n}\n\n/**\n * Fetch consent manager ID\n *\n * @param client - GraphQL client\n * @param maxRequests - = Max number of requests to send\n * @returns Consent manager ID in organization\n */\nexport async function fetchConsentManagerId(\n client: GraphQLClient,\n maxRequests?: number,\n): Promise<string> {\n const {\n consentManager: { consentManager },\n } = await makeGraphQLRequest<{\n /** Consent manager query */\n consentManager: {\n /** Consent manager object */\n consentManager: {\n /** ID of bundle */\n id: string;\n };\n };\n }>(client, FETCH_CONSENT_MANAGER_ID, {}, {}, maxRequests);\n return consentManager.id;\n}\n\nconst PAGE_SIZE = 50;\n\nexport interface ConsentExperience {\n /** ID of experience */\n id: string;\n /** Name of experience */\n name: string;\n /** Experience display name */\n displayName?: string;\n /** Region that define this regional experience */\n regions: {\n /** Sub division */\n countrySubDivision?: IsoCountrySubdivisionCode;\n /** Country */\n country?: IsoCountryCode;\n }[];\n /** In vs not in operator */\n operator: RegionsOperator;\n /** Priority of experience */\n displayPriority: number;\n /** View state to prompt when auto prompting is enabled */\n viewState: InitialViewState;\n /** Consent expiry setting */\n onConsentExpiry: OnConsentExpiry;\n /** Consent expiry */\n consentExpiry: number;\n /** Purposes that can be opted out of in a particular experience */\n purposes: {\n /** Name of purpose */\n name: string;\n /** Purpose slug */\n trackingType: string;\n }[];\n /** Purposes that are opted out by default in a particular experience */\n optedOutPurposes: {\n /** Name of purpose */\n name: string;\n /** Purpose slug */\n trackingType: string;\n }[];\n /**\n * Browser languages that define this regional experience\n */\n browserLanguages: BrowserLanguage[];\n /** Browser time zones that define this regional experience */\n browserTimeZones: BrowserTimeZone[];\n}\n\n/**\n * Fetch consent manager experiences\n *\n * @param client - GraphQL client\n * @returns Consent manager experiences in the organization\n */\nexport async function fetchConsentManagerExperiences(\n client: GraphQLClient,\n): Promise<ConsentExperience[]> {\n const experiences: ConsentExperience[] = [];\n let offset = 0;\n\n // Fetch all experiences\n let shouldContinue = false;\n do {\n const {\n experiences: { nodes },\n } = await makeGraphQLRequest<{\n /** Consent experience */\n experiences: {\n /** List */\n nodes: ConsentExperience[];\n };\n }>(client, EXPERIENCES, {\n first: PAGE_SIZE,\n offset,\n });\n experiences.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return experiences.sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/**\n * The allowed bin sizes for pulling consent metrics\n */\nexport enum ConsentManagerMetricBin {\n Hourly = '1h',\n Daily = '1d',\n}\n\nexport interface ConsentManagerMetric {\n /** Name of metric */\n name: string;\n /** The metrics */\n points: {\n /** Key of metric */\n key: string;\n /** Value of metric */\n value: string;\n }[];\n}\n\n/**\n * Fetch consent manager analytics data\n *\n * @param client - GraphQL client\n * @param input - Input for fetching data\n * @returns Consent manager purposes in the organization\n */\nexport async function fetchConsentManagerAnalyticsData(\n client: GraphQLClient,\n input: {\n /** Data source */\n dataSource:\n | 'PRIVACY_SIGNAL_TIMESERIES'\n | 'CONSENT_CHANGES_TIMESERIES'\n | 'CONSENT_SESSIONS_BY_REGIME';\n /** Start date, in ISO string format */\n startDate: string;\n /** End date, in ISO string format */\n endDate: string;\n /** Force refetching */\n forceRefetch?: boolean;\n /** Airgap bundle ID */\n airgapBundleId: string;\n /** Bin interval */\n binInterval: ConsentManagerMetricBin;\n /** Whether or not to smooth the time series */\n smoothTimeseries: false;\n },\n): Promise<ConsentManagerMetric[]> {\n const {\n analyticsData: { series },\n } = await makeGraphQLRequest<{\n /** Analytics data response */\n analyticsData: {\n /** Consent manager metrics */\n series: ConsentManagerMetric[];\n };\n }>(client, CONSENT_MANAGER_ANALYTICS_DATA, {\n input,\n });\n return series;\n}\n\nexport interface ConsentManagerTheme {\n /** Primary color */\n primaryColor: string;\n /** Font color */\n fontColor: string;\n /** Privacy policy URL */\n privacyPolicy?: string;\n /** Auto-prompt setting */\n prompt: number;\n}\n\n/**\n * Fetch consent manager theme\n *\n * @param client - GraphQL client\n * @param airgapBundleId - Airgap bundle ID to fetch for\n * @returns Consent manager ID in organization\n */\nexport async function fetchConsentManagerTheme(\n client: GraphQLClient,\n airgapBundleId: string,\n): Promise<ConsentManagerTheme> {\n const {\n consentManagerTheme: { theme },\n } = await makeGraphQLRequest<{\n /** Consent manager query */\n consentManagerTheme: {\n /** Consent manager object */\n theme: ConsentManagerTheme;\n };\n }>(client, FETCH_CONSENT_MANAGER_THEME, {\n airgapBundleId,\n });\n return theme;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { COOKIES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { fetchConsentManagerId } from './fetchConsentManagerId';\nimport {\n ConsentTrackerSource,\n ConsentTrackerStatus,\n} from '@transcend-io/privacy-types';\n\nexport interface Cookie {\n /** ID of the cookie */\n id: string;\n /** Name of the cookie */\n name: string;\n /** Whether cookie is a regular express */\n isRegex: boolean;\n /** Description of cookie */\n description: string;\n /** Enabled tracking purposes for the cookie */\n trackingPurposes: string[];\n /** The consent service */\n service: {\n /** Integration name of service */\n integrationName: string;\n };\n /** Source of how tracker was added */\n source: ConsentTrackerSource;\n /** Status of cookie labeling */\n status: ConsentTrackerStatus;\n /** Owners of that cookie */\n owners: {\n /** Email address of owner */\n email: string;\n }[];\n /** Teams assigned to that cookie */\n teams: {\n /** Name of team */\n name: string;\n }[];\n /** Attributes assigned to that cookie */\n attributeValues: {\n /** Name of attribute value */\n name: string;\n /** Attribute key that the value represents */\n attributeKey: {\n /** Name of attribute team */\n name: string;\n };\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all Cookies in the organization\n *\n * @param client - GraphQL client\n * @param status - The status to fetch\n * @returns All Cookies in the organization\n */\nexport async function fetchAllCookies(\n client: GraphQLClient,\n status = ConsentTrackerStatus.Live,\n): Promise<Cookie[]> {\n const cookies: Cookie[] = [];\n let offset = 0;\n\n const airgapBundleId = await fetchConsentManagerId(client);\n\n // Try to fetch an Cookies with the same title\n let shouldContinue = false;\n do {\n const {\n cookies: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n cookies: {\n /** List of matches */\n nodes: Cookie[];\n };\n }>(client, COOKIES, {\n first: PAGE_SIZE,\n offset,\n airgapBundleId,\n status,\n });\n cookies.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return cookies.sort((a, b) => a.name.localeCompare(b.name));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { DATA_SUB_CATEGORIES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { DataCategoryType } from '@transcend-io/privacy-types';\n\nexport interface DataSubCategory {\n /** ID of data category */\n id: string;\n /** Name of data category */\n name: string;\n /** Type of data category */\n category: DataCategoryType;\n /** Description of data category */\n description?: string;\n /** Regex for data category */\n regex?: string;\n /** Assigned teams */\n teams: {\n /** Team name */\n name: string;\n }[];\n /** Assigned owners */\n owners: {\n /** Email */\n email: string;\n }[];\n /** Custom fields */\n attributeValues: {\n /** Name of attribute value */\n name: string;\n /** Attribute key that the value represents */\n attributeKey: {\n /** Name of attribute team */\n name: string;\n };\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all dataSubCategories in the organization\n *\n * @param client - GraphQL client\n * @returns All dataSubCategories in the organization\n */\nexport async function fetchAllDataCategories(\n client: GraphQLClient,\n): Promise<DataSubCategory[]> {\n const dataSubCategories: DataSubCategory[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n dataSubCategories: { nodes },\n } = await makeGraphQLRequest<{\n /** DataCategories */\n dataSubCategories: {\n /** List */\n nodes: DataSubCategory[];\n };\n }>(client, DATA_SUB_CATEGORIES, {\n first: PAGE_SIZE,\n offset,\n });\n dataSubCategories.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return dataSubCategories.sort((a, b) => a.name.localeCompare(b.name));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { DATA_FLOWS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { fetchConsentManagerId } from './fetchConsentManagerId';\nimport {\n DataFlowScope,\n ConsentTrackerSource,\n ConsentTrackerStatus,\n} from '@transcend-io/privacy-types';\n\nexport interface DataFlow {\n /** ID of data flow */\n id: string;\n /** Value of data flow */\n value: string;\n /** Type of data flow */\n type: DataFlowScope;\n /** Description of data flow */\n description: string;\n /** Enabled tracking purposes */\n trackingType: string[];\n /** The consent service */\n service: {\n /** Integration name of service */\n integrationName: string;\n };\n /** Source of how tracker was added */\n source: ConsentTrackerSource;\n /** Status of data flow labeling */\n status: ConsentTrackerStatus;\n /** Owners of that data flow */\n owners: {\n /** Email address of owner */\n email: string;\n }[];\n /** Teams assigned to that data flow */\n teams: {\n /** Name of team */\n name: string;\n }[];\n /** Attributes assigned to that data flow */\n attributeValues: {\n /** Name of attribute value */\n name: string;\n /** Attribute key that the value represents */\n attributeKey: {\n /** Name of attribute team */\n name: string;\n };\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all DataFlows in the organization\n *\n * @param client - GraphQL client\n * @param status - The status to fetch\n * @returns All DataFlows in the organization\n */\nexport async function fetchAllDataFlows(\n client: GraphQLClient,\n status = ConsentTrackerStatus.Live,\n): Promise<DataFlow[]> {\n const dataFlows: DataFlow[] = [];\n let offset = 0;\n\n const airgapBundleId = await fetchConsentManagerId(client);\n\n // Try to fetch an DataFlow with the same title\n let shouldContinue = false;\n do {\n const {\n dataFlows: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n dataFlows: {\n /** List of matches */\n nodes: DataFlow[];\n };\n }>(client, DATA_FLOWS, {\n first: PAGE_SIZE,\n offset,\n airgapBundleId,\n status,\n ...(status === ConsentTrackerStatus.NeedsReview\n ? { showZeroActivity: true }\n : {}),\n });\n dataFlows.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return dataFlows.sort((a, b) => a.value.localeCompare(b.value));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { MESSAGES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport type { LocaleValue } from '@transcend-io/internationalization';\n\nexport interface Message {\n /** ID of message */\n id: string;\n /** Default message */\n defaultMessage: string;\n /** Description */\n description: string;\n /** React Intl ID */\n targetReactIntlId: string | null;\n /** Disabled locales */\n translations: {\n /** Locale */\n locale: LocaleValue;\n /** Value */\n value: string;\n }[];\n}\n\n/**\n * Fetch all messages in the organization\n *\n * @param client - GraphQL client\n * @returns All messages in the organization\n */\nexport async function fetchAllMessages(\n client: GraphQLClient,\n): Promise<Message[]> {\n const { translatedMessages } = await makeGraphQLRequest<{\n /** Messages */\n translatedMessages: Message[];\n }>(client, MESSAGES, {});\n return translatedMessages;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { DEPLOYED_PRIVACY_CENTER_URL, FETCH_PRIVACY_CENTER_ID } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\n/**\n * Fetch default privacy center URL\n *\n * @param client - GraphQL client\n * @returns Privacy Center ID in organization\n */\nexport async function fetchPrivacyCenterUrl(\n client: GraphQLClient,\n): Promise<string> {\n const { organization } = await makeGraphQLRequest<{\n /** Organization */\n organization: {\n /** URL */\n deployedPrivacyCenterUrl: string;\n };\n }>(client, DEPLOYED_PRIVACY_CENTER_URL);\n return organization.deployedPrivacyCenterUrl;\n}\n\n/**\n * Fetch privacy center ID\n *\n * @param client - GraphQL client\n * @param url - URLto lookup\n * @returns Privacy Center ID in organization\n */\nexport async function fetchPrivacyCenterId(\n client: GraphQLClient,\n url?: string,\n): Promise<string> {\n let urlToUse = url;\n if (!urlToUse) {\n urlToUse = await fetchPrivacyCenterUrl(client);\n }\n const { privacyCenter } = await makeGraphQLRequest<{\n /** Privacy Center query */\n privacyCenter: {\n /** ID of bundle */\n id: string;\n };\n }>(client, FETCH_PRIVACY_CENTER_ID, {\n url: urlToUse,\n });\n return privacyCenter.id;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { POLICIES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport type { LocaleValue } from '@transcend-io/internationalization';\nimport { fetchPrivacyCenterUrl } from './fetchPrivacyCenterId';\n\nexport interface Policy {\n /** ID of policy */\n id: string;\n /** Title of policy */\n title: {\n /** Default message */\n defaultMessage: string;\n };\n /** Disabled locales */\n disabledLocales: LocaleValue[];\n /** Versions */\n versions: {\n /** Message content */\n content: {\n /** Default message */\n defaultMessage: string;\n };\n }[];\n}\n\n/**\n * Fetch all policies in the organization\n *\n * @param client - GraphQL client\n * @returns All policies in the organization\n */\nexport async function fetchAllPolicies(\n client: GraphQLClient,\n): Promise<Policy[]> {\n const deployedPrivacyCenterUrl = await fetchPrivacyCenterUrl(client);\n const { privacyCenterPolicies } = await makeGraphQLRequest<{\n /** Policies */\n privacyCenterPolicies: Policy[];\n }>(client, POLICIES, {\n url: deployedPrivacyCenterUrl,\n });\n\n return privacyCenterPolicies.sort((a, b) =>\n a.title.defaultMessage.localeCompare(b.title.defaultMessage),\n );\n}\n","import type { DataSiloAttributeValue } from './syncDataSilos';\n\nexport interface FormattedAttribute {\n /** Attribute key */\n key: string;\n /** Attribute values */\n values: string[];\n}\n\n/**\n * Format attribute value objects to key-pair values\n *\n * @param vals - Attribute values\n * @returns formatted attributes\n */\nexport function formatAttributeValues(\n vals: DataSiloAttributeValue[],\n): FormattedAttribute[] {\n const attributes: FormattedAttribute[] = [];\n\n vals.map((val) => {\n let foundKey = attributes.find((att) => att.key === val.attributeKey.name);\n\n if (foundKey === undefined) {\n foundKey = {\n key: val.attributeKey.name,\n values: [val.name],\n };\n attributes.push(foundKey);\n } else {\n foundKey.values.push(val.name);\n }\n return attributes;\n });\n\n return attributes;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { PREFERENCE_TOPICS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { PreferenceTopicType } from '@transcend-io/privacy-types';\n\nexport interface PreferenceTopic {\n /** ID of preference topic */\n id: string;\n /** Slug of preference topic */\n slug: string;\n /** Title of topic */\n title: {\n /** ID */\n id: string;\n /** Default message */\n defaultMessage: string;\n };\n /** Whether to show in privacy center */\n showInPrivacyCenter: boolean;\n /** Description to display in privacy center */\n displayDescription: {\n /** ID */\n id: string;\n /** Default message */\n defaultMessage: string;\n };\n /** Type of preference topic */\n type: PreferenceTopicType;\n /** Default configuration */\n defaultConfiguration: string;\n /** Option values */\n preferenceOptionValues: {\n /** Slug of value */\n slug: string;\n /** Title of value */\n title: {\n /** ID */\n id: string;\n /** Default message */\n defaultMessage: string;\n };\n }[];\n /** Related purpose */\n purpose: {\n /** Slug */\n trackingType: string;\n };\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all preference topics in the organization\n *\n * @param client - GraphQL client\n * @returns All preference topics in the organization\n */\nexport async function fetchAllPreferenceTopics(\n client: GraphQLClient,\n): Promise<PreferenceTopic[]> {\n const preferenceTopics: PreferenceTopic[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n preferenceTopics: { nodes },\n } = await makeGraphQLRequest<{\n /** Preference topics */\n preferenceTopics: {\n /** List */\n nodes: PreferenceTopic[];\n };\n }>(client, PREFERENCE_TOPICS, {\n first: PAGE_SIZE,\n offset,\n });\n preferenceTopics.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return preferenceTopics.sort((a, b) =>\n `${a.slug}:${a.purpose.trackingType}`.localeCompare(\n `${b.slug}:${b.purpose.trackingType}`,\n ),\n );\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { PRIVACY_CENTER } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport type { LocaleValue } from '@transcend-io/internationalization';\nimport { PrivacyCenterThemePartial } from '@transcend-io/privacy-types';\nimport { fetchPrivacyCenterUrl } from './fetchPrivacyCenterId';\n\nexport interface PrivacyCenter {\n /** ID of the privacy center */\n id: string;\n /** The URL of the privacy center */\n url: string;\n /** Whether or not the entire privacy center is enabled or disabled */\n isDisabled: boolean;\n /** Whether or not to show the privacy requests button */\n showPrivacyRequestButton: boolean;\n /** Whether or not to show the policies page */\n showPolicies: boolean;\n /** Whether or not to show the tracking technologies page */\n showTrackingTechnologies: boolean;\n /** Whether or not to show the cookies on the tracking technologies page */\n showCookies: boolean;\n /** Whether or not to show the data flows on the tracking technologies page */\n showDataFlows: boolean;\n /** Whether or not to show the consent manager opt out options on the tracking technologies page */\n showConsentManager: boolean;\n /** Whether or not to show the manage your privacy page */\n showManageYourPrivacy: boolean;\n /** Whether or not to show the marketing preferences page */\n showMarketingPreferences: boolean;\n /** What languages are supported for the privacy center */\n locales: LocaleValue[];\n /** The default locale for the privacy center */\n defaultLocale: LocaleValue;\n /** Whether or not to prefer the browser default locale */\n preferBrowserDefaultLocale: boolean;\n /** The email addresses of the employees within your company that are the go-to individuals for managing this privacy center */\n supportEmail: string;\n /** The email addresses of the employees within your company that are the go-to individuals for managing this privacy center */\n replyToEmail: string;\n /** Whether or not to send emails from a no reply email */\n useNoReplyEmailAddress: boolean;\n /** Whether or not to use a custom email domain */\n useCustomEmailDomain: boolean;\n /** Whether or not to transcend access requests from JSON to CSV */\n transformAccessReportJsonToCsv: boolean;\n /** The theme object of colors to display on the privacy center */\n theme: PrivacyCenterThemePartial;\n}\n\n/**\n * Fetch all privacy centers in the organization\n *\n * @param client - GraphQL client\n * @returns All privacy centers in the organization\n */\nexport async function fetchAllPrivacyCenters(\n client: GraphQLClient,\n): Promise<PrivacyCenter[]> {\n const deployedPrivacyCenterUrl = await fetchPrivacyCenterUrl(client);\n const {\n privacyCenter: { themeStr, ...rest },\n } = await makeGraphQLRequest<{\n /** Privacy centers */\n privacyCenter: Omit<PrivacyCenter, 'theme'> & {\n /** Theme string */\n themeStr: string;\n };\n }>(client, PRIVACY_CENTER, {\n url: deployedPrivacyCenterUrl,\n });\n\n return [\n {\n ...rest,\n theme: JSON.parse(themeStr),\n },\n ];\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { PROCESSING_ACTIVITIES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport type {\n ProcessingPurpose,\n DataCategoryType,\n DataProtectionImpactAssessmentStatus,\n Controllership,\n RetentionType,\n} from '@transcend-io/privacy-types';\nimport type { Region } from './formatRegions';\n\nexport interface ProcessingActivity {\n /** ID of processing activity */\n id: string;\n /** Title of processing activity */\n title: string;\n /** Description of processing activity */\n description: string;\n /** Security measure details */\n securityMeasureDetails?: string;\n /** Controllerships */\n controllerships: Controllership[];\n /** Storage regions */\n storageRegions: Region[];\n /** Transfer regions */\n transferRegions: Region[];\n /** Retention type */\n retentionType: RetentionType;\n /** Retention period in days */\n retentionPeriod?: number;\n /** Data protection impact assessment link */\n dataProtectionImpactAssessmentLink?: string;\n /** Data protection impact assessment status */\n dataProtectionImpactAssessmentStatus: DataProtectionImpactAssessmentStatus;\n /** Attribute values */\n attributeValues: {\n /** Name of attribute value */\n name: string;\n /** Attribute key */\n attributeKey: {\n /** Name of attribute key */\n name: string;\n };\n }[];\n /** Data silos */\n dataSilos: {\n /** Data silo title */\n title: string;\n }[];\n /** Data subjects */\n dataSubjects: {\n /** Data subject type */\n type: string;\n }[];\n /** Teams */\n teams: {\n /** Team name */\n name: string;\n }[];\n /** Owners */\n owners: {\n /** Owner email */\n email: string;\n }[];\n /** Processing purpose sub categories */\n processingPurposeSubCategories: {\n /** Processing purpose sub category name */\n name: string;\n /** Processing purpose */\n purpose: ProcessingPurpose;\n }[];\n /** Data sub categories */\n dataSubCategories: {\n /** Data sub category name */\n name: string;\n /** Data category */\n category: DataCategoryType;\n }[];\n /** SaaS categories */\n saaSCategories: {\n /** Title */\n title: string;\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all processingActivities in the organization\n *\n * @param client - GraphQL client\n * @returns All processingActivities in the organization\n */\nexport async function fetchAllProcessingActivities(\n client: GraphQLClient,\n): Promise<ProcessingActivity[]> {\n const processingActivities: ProcessingActivity[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n processingActivities: { nodes },\n } = await makeGraphQLRequest<{\n /** Processing activities */\n processingActivities: {\n /** List */\n nodes: ProcessingActivity[];\n };\n }>(client, PROCESSING_ACTIVITIES, {\n first: PAGE_SIZE,\n offset,\n });\n processingActivities.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return processingActivities.sort((a, b) => a.title.localeCompare(b.title));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { PROCESSING_PURPOSE_SUB_CATEGORIES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { ProcessingPurpose } from '@transcend-io/privacy-types';\n\nexport interface ProcessingPurposeSubCategory {\n /** ID of processing purpose */\n id: string;\n /** Name of processing purpose */\n name: string;\n /** Type of processing purpose */\n purpose: ProcessingPurpose;\n /** Description of processing purpose */\n description?: string;\n /** Assigned teams */\n teams: {\n /** Team name */\n name: string;\n }[];\n /** Assigned owners */\n owners: {\n /** Email */\n email: string;\n }[];\n /** Custom fields */\n attributeValues: {\n /** Name of attribute value */\n name: string;\n /** Attribute key that the value represents */\n attributeKey: {\n /** Name of attribute team */\n name: string;\n };\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all processingPurposeSubCategories in the organization\n *\n * @param client - GraphQL client\n * @returns All processingPurposeSubCategories in the organization\n */\nexport async function fetchAllProcessingPurposes(\n client: GraphQLClient,\n): Promise<ProcessingPurposeSubCategory[]> {\n const processingPurposeSubCategories: ProcessingPurposeSubCategory[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n processingPurposeSubCategories: { nodes },\n } = await makeGraphQLRequest<{\n /** DataCategories */\n processingPurposeSubCategories: {\n /** List */\n nodes: ProcessingPurposeSubCategory[];\n };\n }>(client, PROCESSING_PURPOSE_SUB_CATEGORIES, {\n first: PAGE_SIZE,\n offset,\n });\n processingPurposeSubCategories.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return processingPurposeSubCategories.sort((a, b) =>\n a.name.localeCompare(b.name),\n );\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { PURPOSES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n DefaultConsentOption,\n PreferenceStoreAuthLevel,\n} from '@transcend-io/privacy-types';\nimport { UserPrivacySignalEnum } from '@transcend-io/airgap.js-types';\n\nexport interface Purpose {\n /** ID of purpose */\n id: string;\n /** Name of purpose */\n name: string;\n /** Description of purpose */\n description: string;\n /** Default consent status */\n defaultConsent: DefaultConsentOption;\n /** Slug of purpose */\n trackingType: string;\n /** Whether the purpose is configurable */\n configurable: boolean;\n /** Whether the purpose is essential */\n essential: boolean;\n /** Whether to show the purpose in the consent manager */\n showInConsentManager: boolean;\n /** Whether the purpose is active */\n isActive: boolean;\n /** Display order of the purpose */\n displayOrder: number;\n /** Opt-out signals for the purpose */\n optOutSignals: UserPrivacySignalEnum[];\n /** Whether the purpose is deleted */\n deletedAt?: string;\n /** Authorization level required for the purpose */\n authLevel: PreferenceStoreAuthLevel;\n /** Whether to show the purpose in the privacy center */\n showInPrivacyCenter: boolean;\n /** Title of the purpose */\n title: string;\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all purposes in the organization\n *\n * @param client - GraphQL client\n * @param input - Input\n * @returns All purposes in the organization\n */\nexport async function fetchAllPurposes(\n client: GraphQLClient,\n {\n includeDeleted = false,\n }: {\n /** Whether to include deleted purposes */\n includeDeleted?: boolean;\n } = {},\n): Promise<Purpose[]> {\n const purposes: Purpose[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n purposes: { nodes },\n } = await makeGraphQLRequest<{\n /** Purposes */\n purposes: {\n /** List */\n nodes: Purpose[];\n };\n }>(client, PURPOSES, {\n first: PAGE_SIZE,\n offset,\n input: {\n includeDeleted,\n },\n });\n purposes.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return purposes.sort((a, b) => a.trackingType.localeCompare(b.trackingType));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { Purpose, fetchAllPurposes } from './fetchAllPurposes';\nimport {\n PreferenceTopic,\n fetchAllPreferenceTopics,\n} from './fetchAllPreferenceTopics';\n\nexport interface PurposeWithPreferences extends Purpose {\n /** Topics */\n topics: PreferenceTopic[];\n}\n\n/**\n * Fetch all purposes and preferences for a request]\n *\n * @param client - GraphQL client\n * @returns List of request enrichers\n */\nexport async function fetchAllPurposesAndPreferences(\n client: GraphQLClient,\n): Promise<PurposeWithPreferences[]> {\n const [purposes, topics] = await Promise.all([\n fetchAllPurposes(client),\n fetchAllPreferenceTopics(client),\n ]);\n\n return purposes.map((purpose) => {\n const purposeTopics = topics.filter(\n (topic) => topic.purpose.trackingType === purpose.trackingType,\n );\n return {\n ...purpose,\n topics: purposeTopics,\n };\n });\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { RequestEnricherStatus } from '@transcend-io/privacy-types';\nimport { REQUEST_ENRICHERS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface RequestEnricher {\n /** ID of request enricher */\n id: string;\n /** Name of identifier */\n enricher: {\n /** ID of enricher */\n id: string;\n /** Title of enricher */\n title: string;\n /** Typeof of enricher */\n type: string;\n };\n /** The status of the enricher */\n status: RequestEnricherStatus;\n}\n\nconst PAGE_SIZE = 50;\n\n/**\n * Fetch all request enrichers for a particular request\n *\n * @param client - GraphQL client\n * @param options - Filter options\n * @returns List of request enrichers\n */\nexport async function fetchAllRequestEnrichers(\n client: GraphQLClient,\n {\n requestId,\n }: {\n /** ID of request to filter on */\n requestId: string;\n },\n): Promise<RequestEnricher[]> {\n const requestEnrichers: RequestEnricher[] = [];\n let offset = 0;\n\n // Paginate\n let shouldContinue = false;\n do {\n const {\n requestEnrichers: { nodes },\n } = await makeGraphQLRequest<{\n /** Request Enrichers */\n requestEnrichers: {\n /** List */\n nodes: RequestEnricher[];\n };\n }>(client, REQUEST_ENRICHERS, {\n first: PAGE_SIZE,\n offset,\n requestId,\n });\n requestEnrichers.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return requestEnrichers;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { REQUEST_IDENTIFIERS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface RequestIdentifierMetadata {\n /** ID of request identifier */\n id: string;\n /** Name of identifier */\n name: string;\n /** Status of identifier */\n isVerifiedAtLeastOnce: boolean;\n}\n\nconst PAGE_SIZE = 50;\n\n/**\n * Fetch all request identifier metadata for a particular request\n *\n * @param client - GraphQL client\n * @param options - Filter options\n * @returns List of request identifiers\n */\nexport async function fetchAllRequestIdentifierMetadata(\n client: GraphQLClient,\n {\n requestId,\n }: {\n /** ID of request to filter on */\n requestId: string;\n },\n): Promise<RequestIdentifierMetadata[]> {\n const requestIdentifiers: RequestIdentifierMetadata[] = [];\n let offset = 0;\n\n // Paginate\n let shouldContinue = false;\n do {\n const {\n requestIdentifiers: { nodes },\n } = await makeGraphQLRequest<{\n /** Request Identifiers */\n requestIdentifiers: {\n /** List */\n nodes: RequestIdentifierMetadata[];\n };\n }>(client, REQUEST_IDENTIFIERS, {\n first: PAGE_SIZE,\n offset,\n requestIds: [requestId],\n });\n requestIdentifiers.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return requestIdentifiers;\n}\n","import { IdentifierType } from '@transcend-io/privacy-types';\nimport { decodeCodec, valuesOf } from '@transcend-io/type-utils';\nimport type { Got } from 'got';\nimport { GraphQLClient } from 'graphql-request';\nimport * as t from 'io-ts';\nimport semver from 'semver';\n\nimport { SOMBRA_VERSION } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nconst MIN_SOMBRA_VERSION_TO_DECRYPT = '7.180.0';\n\nconst RequestIdentifier = t.type({\n /** ID of request */\n id: t.string,\n /** Name of identifier */\n name: t.string,\n /** The underlying identifier value */\n value: t.string,\n /** Type of identifier */\n type: valuesOf(IdentifierType),\n});\n\n/** Type override */\nexport type RequestIdentifier = t.TypeOf<typeof RequestIdentifier>;\n\nconst PAGE_SIZE = 50;\n\nexport const RequestIdentifiersResponse = t.type({\n identifiers: t.array(RequestIdentifier),\n});\n\n/**\n * Fetch all request identifiers for a particular request\n *\n * @param client - GraphQL client\n * @param sombra - Sombra client\n * @param options - Options\n * @returns List of request identifiers\n */\nexport async function fetchAllRequestIdentifiers(\n client: GraphQLClient,\n sombra: Got,\n {\n requestId,\n }: {\n /** ID of request to filter on */\n requestId: string;\n },\n): Promise<RequestIdentifier[]> {\n const requestIdentifiers: RequestIdentifier[] = [];\n let offset = 0;\n let shouldContinue = false;\n\n // determine sombra version\n const {\n organization: {\n sombra: { version },\n },\n } = await makeGraphQLRequest<{\n /** The organization */\n organization: {\n /** Sombra */\n sombra: {\n /** Version string */\n version: string;\n };\n };\n }>(client!, SOMBRA_VERSION);\n\n if (version && semver.lt(version, MIN_SOMBRA_VERSION_TO_DECRYPT)) {\n throw new Error(\n `Please upgrade Sombra to ${MIN_SOMBRA_VERSION_TO_DECRYPT} or greater to use this command.`,\n );\n }\n\n do {\n let response: unknown;\n try {\n response = await sombra!\n .post<{\n /** Decrypted identifiers */\n identifiers: RequestIdentifier[];\n }>('v1/request-identifiers', {\n json: {\n first: PAGE_SIZE,\n offset,\n requestId,\n },\n })\n .json();\n } catch (err) {\n throw new Error(\n `Failed to fetch request identifiers: ${\n err?.response?.body || err?.message\n }`,\n );\n }\n\n const { identifiers: nodes } = decodeCodec(\n RequestIdentifiersResponse,\n response,\n );\n\n requestIdentifiers.push(...nodes);\n\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return requestIdentifiers;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport colors from 'colors';\nimport { REQUESTS } from './gqls';\nimport * as t from 'io-ts';\nimport cliProgress from 'cli-progress';\nimport { valuesOf } from '@transcend-io/type-utils';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n RequestAction,\n RequestOrigin,\n RequestStatus,\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\nimport { logger } from '../../logger';\nimport { LOCALE_KEY } from '@transcend-io/internationalization';\n\nexport const RequestPurposeTrigger = t.type({\n title: t.string,\n name: t.string,\n consent: t.boolean,\n enrichedPreferences: t.array(\n t.type({\n topic: t.string,\n selectValues: t.array(\n t.type({\n id: t.string,\n name: t.string,\n preferenceOption: t.type({\n id: t.string,\n slug: t.string,\n title: t.type({\n defaultMessage: t.string,\n }),\n }),\n }),\n ),\n selectValue: t.type({\n id: t.string,\n name: t.string,\n }),\n preferenceTopic: t.type({\n title: t.type({\n defaultMessage: t.string,\n }),\n id: t.string,\n slug: t.string,\n }),\n name: t.string,\n id: t.string,\n booleanValue: t.boolean,\n }),\n ),\n});\n\n/** Override type */\nexport type RequestPurposeTrigger = t.TypeOf<typeof RequestPurposeTrigger>;\n\nexport const PrivacyRequest = t.intersection([\n t.type({\n /** Request ID */\n id: t.string,\n /** Time request was made */\n createdAt: t.string,\n /** Email of request */\n email: t.string,\n /** The type of request */\n type: valuesOf(RequestAction),\n /** Link to request in Transcend dashboard */\n link: t.string,\n /** Whether request is in silent mode */\n isSilent: t.boolean,\n /** Where request was made */\n origin: valuesOf(RequestOrigin),\n /** Whether request is a test request */\n isTest: t.boolean,\n /** The core identifier of the request */\n coreIdentifier: t.string,\n /** Request details */\n details: t.string,\n /** Locale of request */\n locale: valuesOf(LOCALE_KEY),\n /** Status of request */\n status: valuesOf(RequestStatus),\n /** Type of data subject */\n subjectType: t.string,\n /** Country of request */\n country: t.union([t.null, valuesOf(IsoCountryCode)]),\n /** Subdivision of request */\n countrySubDivision: t.union([t.null, valuesOf(IsoCountrySubdivisionCode)]),\n /** Request attributes */\n attributeValues: t.array(\n t.type({\n id: t.string,\n attributeKey: t.type({ name: t.string, id: t.string }),\n name: t.string,\n }),\n ),\n }),\n t.partial({\n /** Days remaining until expired */\n daysRemaining: t.union([t.null, t.number]),\n /** Purpose */\n purpose: RequestPurposeTrigger,\n }),\n]);\n\n/** Type override */\nexport type PrivacyRequest = t.TypeOf<typeof PrivacyRequest>;\n\nconst PAGE_SIZE = 50;\n\n/**\n * Fetch all requests matching a set of filters\n *\n * @param client - GraphQL client\n * @param options - Filter options\n * @returns List of requests\n */\nexport async function fetchAllRequests(\n client: GraphQLClient,\n {\n actions = [],\n statuses = [],\n origins = [],\n text,\n createdAtBefore,\n createdAtAfter,\n isTest,\n isSilent,\n isClosed,\n requestIds = [],\n }: {\n /** Actions to filter on */\n actions?: RequestAction[];\n /** Origins to filter on */\n origins?: RequestOrigin[];\n /** Statuses to filter on */\n statuses?: RequestStatus[];\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Filter for requests with a specific identifier */\n text?: string;\n /** Return test requests */\n isTest?: boolean;\n /** Return silent mode requests */\n isSilent?: boolean;\n /** Filter by whether request is active */\n isClosed?: boolean;\n /**\n * Filter the list of requests for a set of IDs - these are applied\n * at runtime while other filters are applied at the GraphQL level.\n */\n requestIds?: string[];\n } = {},\n): Promise<PrivacyRequest[]> {\n logger.info(colors.magenta('Fetching requests...'));\n\n // create a new progress bar instance and use shades_classic theme\n const t0 = new Date().getTime();\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // read in requests\n const requests: PrivacyRequest[] = [];\n let offset = 0;\n\n // Paginate\n let shouldContinue = false;\n do {\n const {\n requests: { nodes, totalCount },\n } = await makeGraphQLRequest<{\n /** Requests */\n requests: {\n /** List */\n nodes: PrivacyRequest[];\n /** Total count */\n totalCount: number;\n };\n }>(client, REQUESTS, {\n first: PAGE_SIZE,\n offset,\n filterBy: {\n text,\n type: actions.length > 0 ? actions : undefined,\n status: statuses.length > 0 ? statuses : undefined,\n origin: origins.length > 0 ? origins : undefined,\n isTest,\n isSilent,\n isClosed,\n createdAtBefore: createdAtBefore\n ? createdAtBefore.toISOString()\n : undefined,\n createdAtAfter: createdAtAfter\n ? createdAtAfter.toISOString()\n : undefined,\n },\n });\n if (offset === 0 && totalCount > PAGE_SIZE) {\n logger.info(colors.magenta(`Fetching ${totalCount} requests`));\n progressBar.start(totalCount, 0);\n }\n\n requests.push(...nodes);\n offset += PAGE_SIZE;\n progressBar.update(offset);\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n // Log completion time\n logger.info(\n colors.green(\n `Completed fetching of ${requests.length} request in \"${\n totalTime / 1000\n }\" seconds.`,\n ),\n );\n\n // Filter down requests by request ID\n let allRequests = requests;\n if (requestIds && requestIds.length > 0) {\n allRequests = allRequests.filter((request) =>\n requestIds.includes(request.id),\n );\n logger.info(\n colors.green(\n `Filtered down to ${allRequests.length} requests based on ${requestIds.length} provided IDs.`,\n ),\n );\n }\n\n return allRequests;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { TEAMS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { ScopeName } from '@transcend-io/privacy-types';\n\nexport interface Team {\n /** ID of team */\n id: string;\n /** Name of team */\n name: string;\n /** Description of team */\n description: string;\n /** SSO department for automated provisioning */\n ssoDepartment?: string;\n /** SSO group name for automated provisioning */\n ssoGroup?: string;\n /** SSO title mapping for automated provisioning */\n ssoTitle?: string;\n /** List of users on the team */\n users: {\n /** ID of user */\n id: string;\n /** Email of user */\n email: string;\n /** Name of user */\n name: string;\n }[];\n /** List of scopes on the team */\n scopes: {\n /** ID of scope */\n id: string;\n /** Name of scope */\n name: ScopeName;\n /** Title of scope */\n title: string;\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all teams in the organization\n *\n * @param client - GraphQL client\n * @returns All teams in the organization\n */\nexport async function fetchAllTeams(client: GraphQLClient): Promise<Team[]> {\n const teams: Team[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n teams: { nodes },\n } = await makeGraphQLRequest<{\n /** Teams */\n teams: {\n /** List */\n nodes: Team[];\n };\n }>(client, TEAMS, {\n first: PAGE_SIZE,\n offset,\n });\n teams.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return teams.sort((a, b) => a.name.localeCompare(b.name));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { USERS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface User {\n /** ID of user */\n id: string;\n /** Name of user */\n name: string;\n /** Email of user */\n email: string;\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all users in the organization\n *\n * @param client - GraphQL client\n * @returns All users in the organization\n */\nexport async function fetchAllUsers(client: GraphQLClient): Promise<User[]> {\n const users: User[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n users: { nodes },\n } = await makeGraphQLRequest<{\n /** Users */\n users: {\n /** List */\n nodes: User[];\n };\n }>(client, USERS, {\n first: PAGE_SIZE,\n offset,\n });\n users.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return users.sort((a, b) => a.email.localeCompare(b.email));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { VENDORS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\n\nexport interface Vendor {\n /** ID of vendor */\n id: string;\n /** Title of vendor */\n title: string;\n /** Description of vendor */\n description: string;\n /** DPA link */\n dataProcessingAgreementLink?: string;\n /** Contract email */\n contactName?: string;\n /** Contract phone */\n contactPhone?: string;\n /** Address */\n address?: string;\n /** Headquarters country */\n headquarterCountry?: IsoCountryCode;\n /** Headquarters subdivision */\n headquarterSubDivision?: IsoCountrySubdivisionCode;\n /** Website URL */\n websiteUrl?: string;\n /** Business entity */\n businessEntity?: {\n /** Business entity title */\n title: string;\n };\n /** Assigned teams */\n teams: {\n /** Team name */\n name: string;\n }[];\n /** Assigned owners */\n owners: {\n /** Email */\n email: string;\n }[];\n /** Custom fields */\n attributeValues: {\n /** Name of attribute value */\n name: string;\n /** Attribute key that the value represents */\n attributeKey: {\n /** Name of attribute team */\n name: string;\n };\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all vendors in the organization\n *\n * @param client - GraphQL client\n * @returns All vendors in the organization\n */\nexport async function fetchAllVendors(\n client: GraphQLClient,\n): Promise<Vendor[]> {\n const vendors: Vendor[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n vendors: { nodes },\n } = await makeGraphQLRequest<{\n /** Vendors */\n vendors: {\n /** List */\n nodes: Vendor[];\n };\n }>(client, VENDORS, {\n first: PAGE_SIZE,\n offset,\n });\n vendors.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return vendors.sort((a, b) => a.title.localeCompare(b.title));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { API_KEYS } from './gqls';\nimport { keyBy, uniq, difference } from 'lodash-es';\nimport { logger } from '../../logger';\nimport colors from 'colors';\nimport { TranscendInput } from '../../codecs';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface ApiKey {\n /** ID of API key */\n id: string;\n /** Title of API key */\n title: string;\n}\n\nconst PAGE_SIZE = 20;\n\nconst ADMIN_LINK = 'https://app.transcend.io/infrastructure/api-keys';\n\n/**\n * Fetch all API keys in an organization\n *\n * @param client - Client\n * @param titles - Filter on titles\n * @returns API keys\n */\nexport async function fetchAllApiKeys(\n client: GraphQLClient,\n titles?: string[],\n): Promise<ApiKey[]> {\n const apiKeys: ApiKey[] = [];\n let offset = 0;\n\n // Paginate\n let shouldContinue = false;\n do {\n const {\n apiKeys: { nodes },\n } = await makeGraphQLRequest<{\n /** API keys */\n apiKeys: {\n /** List */\n nodes: ApiKey[];\n };\n }>(client, API_KEYS, {\n first: PAGE_SIZE,\n offset,\n titles,\n });\n apiKeys.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n return apiKeys.sort((a, b) => a.title.localeCompare(b.title));\n}\n\n/**\n * Fetch all apiKeys and if any are found in the config that are\n * missing, create those apiKeys.\n *\n * @param apiKeyInputs - API keys to fetch metadata on\n * @param client - GraphQL client\n * @param fetchAll - When true, fetch all API keys\n * @returns A map from apiKey title to Identifier\n */\nexport async function fetchApiKeys(\n {\n 'api-keys': apiKeyInputs = [],\n 'data-silos': dataSilos = [],\n }: TranscendInput,\n client: GraphQLClient,\n fetchAll = false,\n): Promise<{ [k in string]: ApiKey }> {\n logger.info(\n colors.magenta(\n `Fetching ${fetchAll ? 'all' : apiKeyInputs.length} API keys...`,\n ),\n );\n const titles = apiKeyInputs.map(({ title }) => title);\n const expectedApiKeyTitles = uniq(\n dataSilos\n .map((silo) => silo['api-key-title'])\n .filter((x): x is string => !!x),\n );\n const allTitlesExpected = [...expectedApiKeyTitles, ...titles];\n const apiKeys = await fetchAllApiKeys(\n client,\n fetchAll ? undefined : [...expectedApiKeyTitles, ...titles],\n );\n\n // Create a map\n const apiKeysByTitle = keyBy(apiKeys, 'title');\n\n // Determine expected set of apiKeys expected\n const missingApiKeys = difference(\n allTitlesExpected,\n apiKeys.map(({ title }) => title),\n );\n\n // If there are missing apiKeys, throw an error\n if (missingApiKeys.length > 0) {\n logger.info(\n colors.red(\n `Failed to find API keys \"${missingApiKeys.join(\n '\", \"',\n )}\"! Make sure these API keys are created at: ${ADMIN_LINK}`,\n ),\n );\n process.exit(1);\n }\n return apiKeysByTitle;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { CATALOGS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface Catalog {\n /** Integration name */\n integrationName: string;\n /** Title of Data Silo */\n title: string;\n /** Whether API is supported */\n hasApiFunctionality: boolean;\n}\n\nconst PAGE_SIZE = 100;\n\n/**\n * Fetch all integration catalogs in an organization\n *\n * @param client - Client\n * @returns Integration catalogs\n */\nexport async function fetchAllCatalogs(\n client: GraphQLClient,\n): Promise<Catalog[]> {\n const catalogs: Catalog[] = [];\n let offset = 0;\n\n // Paginate\n let shouldContinue = false;\n do {\n const {\n catalogs: { nodes },\n } = await makeGraphQLRequest<{\n /** integration catalogs */\n catalogs: {\n /** List */\n nodes: Catalog[];\n };\n }>(client, CATALOGS, {\n first: PAGE_SIZE,\n offset,\n });\n catalogs.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n return catalogs.sort((a, b) =>\n a.integrationName.localeCompare(b.integrationName),\n );\n}\n\nexport interface IndexedCatalogs {\n /** Mapping from service name to service title */\n serviceToTitle: { [k in string]: string };\n /** Mapping from service name to boolean indicate if service has API integration support */\n serviceToSupportedIntegration: { [k in string]: boolean };\n}\n\n/**\n * Fetch all integration catalogs and index them for usage in common utility manners\n *\n * @param client - Client\n * @returns Integration catalogs\n */\nexport async function fetchAndIndexCatalogs(client: GraphQLClient): Promise<\n {\n /** List of all catalogs */\n catalogs: Catalog[];\n } & IndexedCatalogs\n> {\n // Fetch all integrations in the catalog\n const catalogs = await fetchAllCatalogs(client);\n\n // Create mapping from service name to service title\n const serviceToTitle = catalogs.reduce(\n (acc, catalog) =>\n Object.assign(acc, { [catalog.integrationName]: catalog.title }),\n {} as { [k in string]: string },\n );\n\n // Create mapping from service name to boolean indicate if service has API integration support\n const serviceToSupportedIntegration = catalogs.reduce(\n (acc, catalog) =>\n Object.assign(acc, {\n [catalog.integrationName]: catalog.hasApiFunctionality,\n }),\n {} as { [k in string]: boolean },\n );\n\n return {\n catalogs,\n serviceToTitle,\n serviceToSupportedIntegration,\n };\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { CREATE_DATA_SUBJECT, DATA_SUBJECTS } from './gqls';\nimport { keyBy, flatten, uniq, difference } from 'lodash-es';\nimport { RequestActionObjectResolver } from '@transcend-io/privacy-types';\nimport { TranscendInput } from '../../codecs';\nimport { logger } from '../../logger';\nimport colors from 'colors';\nimport { mapSeries } from '../bluebird';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface DataSubject {\n /** ID of data subject */\n id: string;\n /** Type of data subject */\n type: string;\n /** Whether active */\n active: boolean;\n /** Title of data subject */\n title: {\n /** Default message */\n defaultMessage: string;\n };\n /** Whether silent mode is enabled by default */\n adminDashboardDefaultSilentMode: boolean;\n /** Enabled actions */\n actions: {\n /** Type of action */\n type: RequestActionObjectResolver;\n }[];\n}\n\n/**\n * Fetch all data subjects in an organization\n *\n * @param client - GraphQL client\n * @returns List of data subject configurations\n */\nexport async function fetchAllDataSubjects(\n client: GraphQLClient,\n): Promise<DataSubject[]> {\n // Fetch all data subjects in the organization\n const { internalSubjects } = await makeGraphQLRequest<{\n /** Query response */\n internalSubjects: DataSubject[];\n }>(client, DATA_SUBJECTS);\n return internalSubjects;\n}\n\n/**\n * Fetch all of the data subjects in the organization\n *\n * @param input - Input to fetch\n * @param client - GraphQL client\n * @param fetchAll - When true, always fetch all subjects\n * @returns The list of data subjects\n */\nexport async function ensureAllDataSubjectsExist(\n {\n 'data-silos': dataSilos = [],\n 'data-subjects': dataSubjects = [],\n 'processing-activities': processingActivities = [],\n enrichers = [],\n }: TranscendInput,\n client: GraphQLClient,\n fetchAll = false,\n): Promise<{ [type in string]: DataSubject }> {\n // Only need to fetch data subjects if specified in config\n const expectedDataSubjects = uniq([\n ...flatten(dataSilos.map((silo) => silo['data-subjects'] || []) || []),\n ...flatten(\n processingActivities.map(\n ({ dataSubjectTypes }) => dataSubjectTypes ?? [],\n ) ?? [],\n ),\n ...flatten(\n enrichers.map((enricher) => enricher['data-subjects'] || []) || [],\n ),\n ...dataSubjects.map((subject) => subject.type),\n ]);\n if (expectedDataSubjects.length === 0 && !fetchAll) {\n return {};\n }\n\n // Fetch all data subjects in the organization\n const internalSubjects = await fetchAllDataSubjects(client);\n const dataSubjectByName = keyBy(internalSubjects, 'type');\n\n // Determine expected set of data subjects to create\n const missingDataSubjects = difference(\n expectedDataSubjects,\n internalSubjects.map(({ type }) => type),\n );\n\n // If there are missing data subjects, create new ones\n if (missingDataSubjects.length > 0) {\n logger.info(\n colors.magenta(\n `Creating ${missingDataSubjects.length} new data subjects...`,\n ),\n );\n await mapSeries(missingDataSubjects, async (dataSubject) => {\n logger.info(colors.magenta(`Creating data subject ${dataSubject}...`));\n const { createSubject } = await makeGraphQLRequest<{\n /** Create Subject Response */\n createSubject: {\n /** Created Data Subject */\n subject: DataSubject;\n };\n }>(client, CREATE_DATA_SUBJECT, {\n type: dataSubject,\n skipPublish: true,\n });\n logger.info(colors.green(`Created data subject ${dataSubject}!`));\n\n dataSubjectByName[dataSubject] = createSubject.subject;\n });\n }\n\n return dataSubjectByName;\n}\n\n/**\n * Convert a list of data subject types into the block list of IDs to assign to the data silo\n *\n * @param dataSubjectTypes - The list of data subject types that the data silo should be for\n * @param allDataSubjects - All data subjects in the organization\n * @returns The block list of data subject ids to not process against this data silo\n */\nexport function convertToDataSubjectBlockList(\n dataSubjectTypes: string[],\n allDataSubjects: { [type in string]: DataSubject },\n): string[] {\n dataSubjectTypes.forEach((type) => {\n if (!allDataSubjects[type]) {\n throw new Error(`Expected to find data subject definition: ${type}`);\n }\n });\n\n return Object.values(allDataSubjects)\n .filter((silo) => !dataSubjectTypes.includes(silo.type))\n .map(({ id }) => id);\n}\n\n/**\n * Convert a list of data subject types into the allow list of types\n *\n * @param dataSubjectTypes - The list of data subject types that the data silo should be for\n * @param allDataSubjects - All data subjects in the organization\n * @returns The allow list of data subjects for that silo\n */\nexport function convertToDataSubjectAllowlist(\n dataSubjectTypes: string[],\n allDataSubjects: { [type in string]: DataSubject },\n): string[] {\n dataSubjectTypes.forEach((type) => {\n if (!allDataSubjects[type]) {\n throw new Error(`Expected to find data subject definition: ${type}`);\n }\n });\n\n return Object.values(allDataSubjects)\n .filter((silo) => !dataSubjectTypes.includes(silo.type))\n .map(({ type }) => type);\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { PROMPT_GROUPS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface PromptGroup {\n /** ID of prompts */\n id: string;\n /** The title of the prompt group. */\n title: string;\n /** The description of the prompt group. */\n description: string;\n /** Prompts in the group */\n prompts: {\n /** Title of prompt */\n title: string;\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all PromptGroups in the organization\n *\n * @param client - GraphQL client\n * @returns All PromptGroups in the organization\n */\nexport async function fetchAllPromptGroups(\n client: GraphQLClient,\n): Promise<PromptGroup[]> {\n const promptGroups: PromptGroup[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n promptGroups: { nodes },\n } = await makeGraphQLRequest<{\n /** PromptGroups */\n promptGroups: {\n /** List */\n nodes: PromptGroup[];\n };\n }>(client, PROMPT_GROUPS, {\n first: PAGE_SIZE,\n offset,\n });\n promptGroups.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return promptGroups.sort((a, b) => a.title.localeCompare(b.title));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { PROMPT_PARTIALS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface PromptPartial {\n /** ID of prompts */\n id: string;\n /** The title of the prompt partial. */\n title: string;\n /** The content of the prompt partial. */\n content: string;\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all PromptPartials in the organization\n *\n * @param client - GraphQL client\n * @returns All PromptPartials in the organization\n */\nexport async function fetchAllPromptPartials(\n client: GraphQLClient,\n): Promise<PromptPartial[]> {\n const promptPartials: PromptPartial[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n promptPartials: { nodes },\n } = await makeGraphQLRequest<{\n /** PromptPartials */\n promptPartials: {\n /** List */\n nodes: PromptPartial[];\n };\n }>(client, PROMPT_PARTIALS, {\n first: PAGE_SIZE,\n offset,\n });\n promptPartials.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return promptPartials.sort((a, b) => a.title.localeCompare(b.title));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { PROMPTS, PROMPTS_WITH_VARIABLES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n PromptStatus,\n PromptResponseFormat,\n} from '@transcend-io/privacy-types';\n\nexport interface Prompt {\n /** ID of prompt */\n id: string;\n /** The title of the prompt */\n title: string;\n /** The status of the prompt */\n status: PromptStatus;\n /** The content of the prompt */\n content: string;\n /** Temperature to use with prompt */\n temperature: number;\n /** Top P to use with prompt */\n topP: number;\n /** Max tokens to sample for prompt */\n maxTokensToSample: number;\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all Prompts in the organization\n *\n * @param client - GraphQL client\n * @param options - Options\n * @returns All Prompts in the organization\n */\nexport async function fetchAllPrompts(\n client: GraphQLClient,\n {\n text,\n titles = [],\n ids = [],\n }: {\n /** Filter by text */\n text?: string;\n /** Filter by ids */\n ids?: string[];\n /** Filter by titles */\n titles?: string[];\n } = {},\n): Promise<Prompt[]> {\n const prompts: Prompt[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n prompts: { nodes },\n } = await makeGraphQLRequest<{\n /** Prompts */\n prompts: {\n /** List */\n nodes: Prompt[];\n };\n }>(client, PROMPTS, {\n first: PAGE_SIZE,\n offset,\n filterBy: {\n ...(text ? { text } : {}),\n ...(titles.length > 0 ? { title: titles } : {}),\n ...(ids.length > 0 ? { id: ids } : {}),\n },\n });\n prompts.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return prompts.sort((a, b) => a.title.localeCompare(b.title));\n}\n\n/**\n * The basic metadata needed to use a prompt at runtime\n */\nexport type TranscendPromptTemplated = {\n /** ID of prompt */\n id: string;\n /** Title of prompt */\n title: string;\n /** Content of prompt */\n content: string;\n /** Status of prompt */\n status: PromptStatus;\n /** Temperature */\n temperature?: number;\n /** Top P */\n topP?: number;\n /** Max tokens to sample */\n maxTokensToSample?: number;\n /** Response format */\n responseFormat?: PromptResponseFormat;\n};\n\n/**\n * The basic metadata needed to use a prompt partial at runtime\n */\nexport type TranscendPromptPartialTemplated = {\n /** ID of prompt */\n id: string;\n /** Title of prompt */\n title: string;\n /** Slug of prompt */\n slug: string;\n /** Content of prompt */\n content: string;\n};\n\n/**\n * Calculated variables\n */\nexport type PromptCalculatedVariable = {\n /** JSON stringified data to template */\n data: string | null;\n /** Name of variable */\n name: string;\n};\n\n/**\n * Runtime variables\n */\nexport type PromptRuntimeVariable = {\n /** Type of variable */\n type: string;\n /** Name of variable */\n name: string;\n};\n\n/**\n * Metadata useful for filling variables within a prompt\n */\nexport type TranscendPromptsAndVariables = {\n /** Prompts ready to be templated */\n prompts: TranscendPromptTemplated[];\n /** Prompt partials */\n promptPartials: TranscendPromptPartialTemplated[];\n /** Calculated variables to be templated */\n calculatedVariables: PromptCalculatedVariable[];\n /** Runtime variables to be templated */\n runtimeVariables: PromptRuntimeVariable[];\n};\n\n/**\n * Fetch prompts with templated variables\n *\n * @param client - GraphQL client\n * @param options - Options\n * @returns Prompts and template variables\n */\nexport async function fetchPromptsWithVariables(\n client: GraphQLClient,\n {\n promptTitles = [],\n promptIds = [],\n }: {\n /** Filter by prompt ids */\n promptIds?: string[];\n /** Filter by prompt titles */\n promptTitles?: string[];\n } = {},\n): Promise<TranscendPromptsAndVariables> {\n const { promptsWithVariables } = await makeGraphQLRequest<{\n /** Prompts */\n promptsWithVariables: TranscendPromptsAndVariables;\n }>(client, PROMPTS_WITH_VARIABLES, {\n input: {\n ...(promptTitles.length > 0 ? { promptTitles } : {}),\n ...(promptIds.length > 0 ? { promptIds } : {}),\n },\n });\n\n return promptsWithVariables;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { PROMPT_THREADS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface PromptThread {\n /** ID of prompts */\n id: string;\n /** Thread ID from API */\n threadId: string;\n /** Related slack message TS */\n slackMessageTs?: string;\n /** Related slack message team ID */\n slackTeamId?: string;\n /** Related slack channel ID */\n slackChannelId?: string;\n /** Related slack channel name */\n slackChannelName?: string;\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all PromptThreads in the organization\n *\n * @param client - GraphQL client\n * @param filterBy - Filter options\n * @returns All PromptThreads in the organization\n */\nexport async function fetchAllPromptThreads(\n client: GraphQLClient,\n filterBy: {\n /** Thread IDs to filter on */\n threadIds?: string[];\n /** Slack message timestamps to filter on */\n slackMessageTs?: string[];\n },\n): Promise<PromptThread[]> {\n const promptThreads: PromptThread[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n promptThreads: { nodes },\n } = await makeGraphQLRequest<{\n /** PromptThreads */\n promptThreads: {\n /** List */\n nodes: PromptThread[];\n };\n }>(client, PROMPT_THREADS, {\n first: PAGE_SIZE,\n offset,\n filterBy,\n });\n promptThreads.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return promptThreads.sort((a, b) => a.threadId.localeCompare(b.threadId));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { REQUEST_DATA_SILOS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n RequestDataSiloStatus,\n RequestStatus,\n} from '@transcend-io/privacy-types';\n\nexport interface RequestDataSilo {\n /** ID of RequestDataSilo */\n id: string;\n}\n\nexport interface RequestDataSiloFilters {\n /** ID of request to filter on */\n requestId?: string;\n /** Data silo ID */\n dataSiloId?: string;\n /**\n * The statuses to filter on\n */\n statuses?: RequestDataSiloStatus[];\n /** The request statuses to filter on */\n requestStatuses?: RequestStatus[];\n}\n\n/**\n * Fetch a count of request data silos\n *\n * @param client - GraphQL client\n * @param options - Filter options\n * @returns List of request identifiers\n */\nexport async function fetchRequestDataSilosCount(\n client: GraphQLClient,\n { requestId, dataSiloId, requestStatuses, statuses }: RequestDataSiloFilters,\n): Promise<number> {\n const {\n requestDataSilos: { totalCount },\n } = await makeGraphQLRequest<{\n /** Request Data Silos */\n requestDataSilos: {\n /** List */\n nodes: RequestDataSilo[];\n /** Total count */\n totalCount: number;\n };\n }>(client, REQUEST_DATA_SILOS, {\n first: 1,\n offset: 0,\n filterBy: {\n dataSiloId,\n requestId,\n status: statuses,\n requestStatus: requestStatuses,\n },\n });\n\n return totalCount;\n}\n\nconst PAGE_SIZE = 100;\n\n/**\n * Fetch all request data silos by some filter criteria\n *\n * @param client - GraphQL client\n * @param options - Filter options\n * @returns List of request identifiers\n */\nexport async function fetchRequestDataSilos(\n client: GraphQLClient,\n {\n requestId,\n dataSiloId,\n requestStatuses,\n statuses,\n limit,\n onProgress,\n }: {\n /** ID of request to filter on */\n requestId?: string;\n /** Data silo ID */\n dataSiloId?: string;\n /**\n * The statuses to filter on\n */\n statuses?: RequestDataSiloStatus[];\n /** The request statuses to filter on */\n requestStatuses?: RequestStatus[];\n /** Limit on number of requests */\n limit?: number;\n /** Handle progress updates */\n onProgress?: (numUpdated: number) => void;\n },\n): Promise<RequestDataSilo[]> {\n const requestDataSilos: RequestDataSilo[] = [];\n let offset = 0;\n\n // Try to fetch an DataFlow with the same title\n let shouldContinue = false;\n do {\n const {\n requestDataSilos: { nodes },\n } = await makeGraphQLRequest<{\n /** Request Data Silos */\n requestDataSilos: {\n /** List */\n nodes: RequestDataSilo[];\n /** Total count */\n totalCount: number;\n };\n }>(client, REQUEST_DATA_SILOS, {\n first: PAGE_SIZE,\n offset,\n filterBy: {\n dataSiloId,\n requestId,\n status: statuses,\n requestStatus: requestStatuses,\n },\n });\n requestDataSilos.push(...nodes);\n\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n onProgress?.(nodes.length);\n } while (shouldContinue && (!limit || offset < limit));\n\n return requestDataSilos;\n}\n\n/**\n * Fetch all request identifiers for a particular request\n *\n * @param client - GraphQL client\n * @param options - Filter options\n * @returns List of request identifiers\n */\nexport async function fetchRequestDataSilo(\n client: GraphQLClient,\n {\n requestId,\n dataSiloId,\n }: {\n /** ID of request to filter on */\n requestId: string;\n /** Data silo ID */\n dataSiloId: string;\n },\n): Promise<RequestDataSilo> {\n const nodes = await fetchRequestDataSilos(client, {\n requestId,\n dataSiloId,\n });\n if (nodes.length !== 1) {\n throw new Error(\n `Failed to find RequestDataSilo with requestId:${requestId},dataSiloId:${dataSiloId}`,\n );\n }\n\n return nodes[0];\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { REDUCED_REQUESTS_FOR_DATA_SILO_COUNT } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\n/**\n * Get number of open requests for a data silo\n *\n * @param client - GraphQL client\n * @param options - Filter options\n * @returns List of request identifiers\n */\nexport async function fetchRequestDataSiloActiveCount(\n client: GraphQLClient,\n {\n dataSiloId,\n }: {\n /** Data silo ID */\n dataSiloId: string;\n },\n): Promise<number> {\n const {\n listReducedRequestsForDataSilo: { totalCount },\n } = await makeGraphQLRequest<{\n /** Requests */\n listReducedRequestsForDataSilo: {\n /** Total count */\n totalCount: number;\n };\n }>(client, REDUCED_REQUESTS_FOR_DATA_SILO_COUNT, {\n input: {\n dataSiloId,\n isResolved: false,\n },\n });\n\n return totalCount;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { BULK_REQUEST_FILES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface RequestFileCursor {\n /** The ID of the request file */\n id: string;\n /** The created at timestamp */\n createdAt: string;\n}\n\nexport interface RequestFile {\n /** The remote ID */\n remoteId: string;\n /** The file name */\n fileName: string;\n}\n\nexport interface RequestFileResponse {\n /** RequestFiles */\n bulkRequestFiles: {\n /** List */\n nodes: RequestFile[];\n /** The page info */\n pageInfo: {\n /** Whether there is a next page */\n hasNextPage: boolean;\n /** The end cursor */\n endCursor: string;\n };\n };\n}\n\n/**\n * Fetch all RequestFiles for a single request\n *\n * @param client - GraphQL client\n * @param pageSize - How many request files to fetch per API call\n * @param filterBy - Filter by\n * @returns All RequestFiles in the organization\n */\nexport async function fetchRequestFilesForRequest(\n client: GraphQLClient,\n /** How many request files to fetch per API call */\n pageSize: number,\n filterBy: {\n /** Filter by request IDs */\n requestIds: string[];\n /** Filter by data silo ID */\n dataSiloIds: string[];\n },\n): Promise<RequestFile[]> {\n const requestFiles: RequestFile[] = [];\n let cursor: string | null = null;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const response: RequestFileResponse =\n await makeGraphQLRequest<RequestFileResponse>(\n client,\n BULK_REQUEST_FILES,\n {\n filterBy: {\n ...filterBy,\n },\n first: pageSize,\n after: cursor ?? undefined,\n },\n );\n const {\n bulkRequestFiles: { nodes, pageInfo },\n } = response;\n requestFiles.push(...nodes);\n shouldContinue = pageInfo.hasNextPage;\n cursor = pageInfo.endCursor;\n } while (shouldContinue);\n\n return requestFiles.sort((a, b) => a.remoteId.localeCompare(b.remoteId));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { DETERMINE_LOGIN_METHOD, ASSUME_ROLE, LOGIN } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface OrganizationPreview {\n /** Name of organization */\n name: string;\n /** Id of organization */\n id: string;\n /** uri of organization */\n uri: string;\n /** ID of parent organization */\n parentOrganizationId?: string;\n}\n\nexport interface UserRole {\n /** ID of role */\n id: string;\n /** Related organization */\n organization: OrganizationPreview;\n}\n\n/**\n * Log in as a user\n *\n * @param client - GraphQL client\n * @param options - Email/password\n * @returns Cookie and roles\n */\nexport async function loginUser(\n client: GraphQLClient,\n {\n email,\n password,\n }: {\n /** Email of user */\n email: string;\n /** Password of user */\n password: string;\n },\n): Promise<{\n /** Cookie to be used to make subsequent requests */\n loginCookie: string;\n /** Roles of the user */\n roles: UserRole[];\n}> {\n const {\n determineLoginMethod: { loginMethod },\n } = await makeGraphQLRequest<{\n /** Determine login method */\n determineLoginMethod: {\n /** Login method info */\n loginMethod: {\n /** Email being logged in */\n email: string;\n /** Sombra public key */\n sombraPublicKey: string;\n };\n };\n }>(client, DETERMINE_LOGIN_METHOD, {\n email,\n });\n\n const res = await client.rawRequest<{\n /** Login */\n login: {\n /** User */\n user: {\n /** Roles of user */\n roles: UserRole[];\n };\n };\n }>(LOGIN, {\n email,\n password,\n publicKey: loginMethod.sombraPublicKey,\n });\n const {\n login: { user },\n } = res.data;\n\n // Get login cookie from response\n const loginCookie = res.headers.get('set-cookie');\n if (!loginCookie || !loginCookie.includes('laravel')) {\n throw new Error('Failed to get login cookie in response');\n }\n\n return {\n roles: user.roles,\n loginCookie,\n };\n}\n\n/**\n * Assume role for user into another organization\n *\n * @param client - GraphQL client\n * @param options - Email/password\n */\nexport async function assumeRole(\n client: GraphQLClient,\n {\n email,\n roleId,\n }: {\n /** Email of user */\n email: string;\n /** Role of user assuming into */\n roleId: string;\n },\n): Promise<void> {\n const {\n determineLoginMethod: { loginMethod },\n } = await makeGraphQLRequest<{\n /** Determine login method */\n determineLoginMethod: {\n /** Login method info */\n loginMethod: {\n /** Email being logged in */\n email: string;\n /** Sombra public key */\n sombraPublicKey: string;\n };\n };\n }>(client, DETERMINE_LOGIN_METHOD, {\n email,\n userId: roleId,\n });\n\n await client.rawRequest<{\n /** Assume role */\n assumeRole: {\n /** Mutation ID */\n clientMutationId: string;\n };\n }>(ASSUME_ROLE, {\n id: roleId,\n publicKey: loginMethod.sombraPublicKey,\n });\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { CREATE_API_KEY, DELETE_API_KEY } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { ScopeName } from '@transcend-io/privacy-types';\n\nexport interface CreatedApiKey {\n /** ID of API key */\n id: string;\n /** Actual API key */\n apiKey: string;\n /** Title of the API key */\n title: string;\n}\n\n/**\n * Create an API key\n *\n * @param client - GraphQL client\n * @param input - Input\n * @returns The API key\n */\nexport async function createApiKey(\n client: GraphQLClient,\n input: {\n /** Title of API key */\n title: string;\n /** Scopes for API key */\n scopes: ScopeName[];\n },\n): Promise<CreatedApiKey> {\n const {\n createApiKey: { apiKey },\n } = await makeGraphQLRequest<{\n /** Create API key */\n createApiKey: {\n /** API key */\n apiKey: CreatedApiKey;\n };\n }>(client, CREATE_API_KEY, { input });\n\n return apiKey;\n}\n\n/**\n * Delete an API key\n *\n * @param client - GraphQL client\n * @param id - API key Id\n */\nexport async function deleteApiKey(\n client: GraphQLClient,\n id: string,\n): Promise<void> {\n await makeGraphQLRequest(client, DELETE_API_KEY, { id });\n}\n","import {\n AssessmentsDisplayLogicAction,\n ComparisonOperator,\n LogicOperator,\n} from '@transcend-io/privacy-types';\nimport { decodeCodec, valuesOf } from '@transcend-io/type-utils';\nimport * as t from 'io-ts';\n\n// This codec is for rules that logically require a list of values to compare against.\nexport const AssessmentRuleWithOperands = t.type({\n dependsOnQuestionReferenceId: t.string,\n comparisonOperator: t.union([\n t.literal(ComparisonOperator.IsEqualTo),\n t.literal(ComparisonOperator.IsNotEqualTo),\n t.literal(ComparisonOperator.IsOneOf),\n t.literal(ComparisonOperator.IsNotOneOf),\n t.literal(ComparisonOperator.Contains),\n ]),\n comparisonOperands: t.array(t.string),\n});\n\n// This codec is for the specific rule that does NOT require comparison operands.\nexport const AssessmentRuleWithoutOperands = t.type({\n dependsOnQuestionReferenceId: t.string,\n comparisonOperator: t.union([\n t.literal(ComparisonOperator.IsNotShown),\n t.literal(ComparisonOperator.IsShown),\n ]),\n});\n\n/**\n * The final, flexible codec that accepts EITHER a rule with operands OR a rule without them.\n */\nexport const AssessmentRule = t.union([\n AssessmentRuleWithOperands,\n AssessmentRuleWithoutOperands,\n]);\n/** Type override */\nexport type AssessmentRule = t.TypeOf<typeof AssessmentRule>;\n\nexport interface AssessmentNestedRule {\n /** The operator to use when comparing the nested rules */\n logicOperator: LogicOperator;\n /** The rules to evaluate and be compared with to other using the LogicOperator */\n rules?: AssessmentRule[];\n /** The nested rules to add one more level of nesting to the rules. They are also compared to each other. */\n nestedRules?: AssessmentNestedRule[];\n}\n\nexport const AssessmentNestedRule: t.RecursiveType<\n t.Type<AssessmentNestedRule>\n> = t.recursion('AssessmentNestedRule', (self) =>\n t.intersection([\n t.type({\n /** The operator to use when comparing the nested rules */\n logicOperator: valuesOf(LogicOperator),\n }),\n t.partial({\n /** The rules to evaluate and be compared with to other using the LogicOperator */\n rules: t.array(AssessmentRule),\n /** The nested rules to add one more level of nesting to the rules. They are also compared to each other. */\n nestedRules: t.array(self),\n }),\n ]),\n);\n\nexport const AssessmentAction = t.partial({\n action: valuesOf(AssessmentsDisplayLogicAction),\n rule: AssessmentRule,\n nestedRule: AssessmentNestedRule,\n});\n\n/** Type override */\nexport type AssessmentAction = t.TypeOf<typeof AssessmentAction>;\n\n/**\n * Parse the assessment display logic\n *\n * @param displayLogic - Stringified rule\n * @returns The parsed assessment display logic\n */\nexport function parseAssessmentDisplayLogic(\n displayLogic: string,\n): AssessmentAction {\n return decodeCodec(AssessmentAction, displayLogic);\n}\n","import { ComparisonOperator } from '@transcend-io/privacy-types';\nimport { decodeCodec, valuesOf } from '@transcend-io/type-utils';\nimport * as t from 'io-ts';\n\nexport const AssessmentRiskLogic = t.intersection([\n t.partial({\n riskAssignment: t.partial({\n riskLevelId: t.string,\n riskMatrixRowId: t.string,\n riskMatrixColumnId: t.string,\n }),\n }),\n t.type({\n comparisonOperands: t.array(t.string),\n comparisonOperator: valuesOf(ComparisonOperator),\n }),\n]);\n\n/** Type override */\nexport type AssessmentRiskLogic = t.TypeOf<typeof AssessmentRiskLogic>;\n\n/**\n * Parse the assessment risk logic\n *\n * @param riskLogic - Stringified rule\n * @returns The parsed assessment risk logic\n */\nexport function parseAssessmentRiskLogic(\n riskLogic: string,\n): AssessmentRiskLogic {\n return decodeCodec(AssessmentRiskLogic, riskLogic);\n}\n","/* eslint-disable max-lines */\nimport cliProgress from 'cli-progress';\nimport {\n DataCategoryInput,\n DataSiloInput,\n ProcessingPurposeInput,\n} from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { logger } from '../../logger';\nimport colors from 'colors';\nimport { mapSeries, map } from '../bluebird';\nimport {\n DATA_SILOS,\n CREATE_DATA_SILOS,\n UPDATE_OR_CREATE_DATA_POINT,\n DATA_POINTS,\n SUB_DATA_POINTS,\n UPDATE_DATA_SILOS,\n DATA_SILOS_ENRICHED,\n SUB_DATA_POINTS_WITH_GUESSES,\n} from './gqls';\nimport {\n convertToDataSubjectBlockList,\n DataSubject,\n} from './fetchDataSubjects';\nimport { ApiKey } from './fetchApiKeys';\nimport {\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n PromptAVendorEmailCompletionLinkType,\n PromptAVendorEmailSendType,\n ConfidenceLabel,\n RequestActionObjectResolver,\n SubDataPointDataSubCategoryGuessStatus,\n} from '@transcend-io/privacy-types';\nimport { sortBy, chunk, keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { apply } from '@transcend-io/type-utils';\n\nexport interface DataSiloAttributeValue {\n /** Key associated to value */\n attributeKey: {\n /** Name of key */\n name: string;\n };\n /** Name of value */\n name: string;\n}\nexport interface DataSilo {\n /** ID of dataSilo */\n id: string;\n /** Title of dataSilo */\n title: string;\n /** Type of silo */\n type: string;\n /** The link to the data silo */\n link: string;\n /** Attribute labels */\n attributeValues: DataSiloAttributeValue[];\n /** description */\n description: string;\n /** Metadata for this data silo */\n catalog: {\n /** Whether the data silo supports automated vendor coordination */\n hasAvcFunctionality: boolean;\n };\n}\n\nconst BATCH_SILOS_LIMIT = 20;\n\n/**\n * Fetch all dataSilos in the organization\n *\n * @param client - GraphQL client\n * @param title - Filter by title\n * @returns All dataSilos in the organization\n */\nexport async function fetchAllDataSilos<TDataSilo extends DataSilo>(\n client: GraphQLClient,\n {\n titles,\n pageSize,\n ids = [],\n gql = DATA_SILOS,\n integrationNames = [],\n }: {\n /** Page size to fetch datapoints in */\n pageSize: number;\n /** Title */\n titles?: string[];\n /** IDs */\n ids?: string[];\n /** Set of integration names to fetch */\n integrationNames?: string[];\n /** GQL query for data silos */\n gql?: string;\n },\n): Promise<TDataSilo[]> {\n logger.info(\n colors.magenta(\n `Fetching ${ids.length === 0 ? 'all' : ids.length} Data Silos...`,\n ),\n );\n\n const dataSilos: TDataSilo[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n dataSilos: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n dataSilos: {\n /** List of matches */\n nodes: TDataSilo[];\n };\n }>(client, gql, {\n filterBy: {\n ids: ids.length > 0 ? ids : undefined,\n type: integrationNames.length > 0 ? integrationNames : undefined,\n titles,\n },\n first: pageSize,\n offset,\n });\n dataSilos.push(...nodes);\n offset += pageSize;\n shouldContinue = nodes.length === pageSize;\n } while (shouldContinue);\n logger.info(\n colors.green(\n `Found a total of ${dataSilos.length} data silo${\n ids.length > 0 ? ` matching IDs ${ids.join(',')}` : ''\n }s${\n integrationNames.length > 0\n ? ` matching integrationNames ${integrationNames.join(',')}`\n : ''\n }`,\n ),\n );\n\n return dataSilos.sort((a, b) => a.title.localeCompare(b.title));\n}\n\nexport interface SubDataPoint {\n /** Name (or key) of the subdatapoint */\n name: string;\n /** The description */\n description?: string;\n /** Personal data category */\n categories: DataCategoryInput[];\n /** The processing purpose for this sub datapoint */\n purposes: ProcessingPurposeInput[];\n /**\n * When true, this subdatapoint should be revealed in a data access request.\n * When false, this field should be redacted\n */\n accessRequestVisibilityEnabled: boolean;\n /**\n * When true, this subdatapoint should be redacted during an erasure request.\n * There normally is a choice of enabling hard deletion or redaction at the\n * datapoint level, but if redaction is enabled, this column can be used\n * to define which fields should be redacted.\n */\n erasureRequestRedactionEnabled: boolean;\n /** Attribute attached to subdatapoint */\n attributeValues: DataSiloAttributeValue[];\n /** Data category guesses that are output by the classifier */\n pendingCategoryGuesses?: {\n /** Data category being guessed */\n category: DataCategoryInput;\n /** Status of guess */\n status: SubDataPointDataSubCategoryGuessStatus;\n /** Confidence level of guess */\n confidence: number;\n /** Confidence label */\n confidenceLabel: ConfidenceLabel;\n /** classifier version that produced the guess */\n classifierVersion: number;\n }[];\n}\n\ninterface DataPoint {\n /** ID of dataPoint */\n id: string;\n /** Title of dataPoint */\n title: {\n /** Default message */\n defaultMessage: string;\n };\n /** The path to this data point */\n path: string[];\n /** Description */\n description: {\n /** Default message */\n defaultMessage: string;\n };\n /** Name */\n name: string;\n /** Global actions */\n actionSettings: {\n /** Action type */\n type: RequestActionObjectResolver;\n /** Is enabled */\n active: boolean;\n }[];\n /** Data collection tag for privacy request download zip labeling */\n dataCollection?: {\n /** Title of data collection */\n title: {\n /** Default message (since message can be translated) */\n defaultMessage: string;\n };\n };\n /** Metadata for this data silo */\n catalog: {\n /** Whether the data silo supports automated vendor coordination */\n hasAvcFunctionality: boolean;\n };\n /** Owners of the datapoint */\n owners: {\n /** Email address of the owner */\n email: string;\n }[];\n /** Teams that own the datapoint */\n teams: {\n /** Name of the team */\n name: string;\n }[];\n /** Database integration queries */\n dbIntegrationQueries: {\n /** Approved query */\n query: string | null;\n /** Suggested query */\n suggestedQuery: string | null;\n /** Request action */\n requestType: RequestActionObjectResolver;\n }[];\n}\n\ninterface DataPointWithSubDataPoint extends DataPoint {\n /** The associated subdatapoints */\n subDataPoints: SubDataPoint[];\n}\n\n/**\n * Helper to fetch all subdatapoints for a given datapoint\n *\n * @param client - The GraphQL client\n * @param dataPointId - The datapoint ID\n * @param options - Options\n * @returns The list of subdatapoints\n */\nexport async function fetchAllSubDataPoints(\n client: GraphQLClient,\n dataPointId: string,\n {\n debug,\n includeGuessedCategories,\n pageSize,\n }: {\n /** Debug logs */\n debug: boolean;\n /** Page size */\n pageSize: number;\n /** When true, metadata around guessed data categories should be included */\n includeGuessedCategories?: boolean;\n },\n): Promise<SubDataPoint[]> {\n const subDataPoints: SubDataPoint[] = [];\n\n let offset = 0;\n\n let shouldContinue = false;\n do {\n try {\n if (debug) {\n logger.log(\n colors.magenta(`Pulling in subdatapoints for offset ${offset}`),\n );\n }\n const {\n subDataPoints: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n subDataPoints: {\n /** List of matches */\n nodes: SubDataPoint[];\n };\n }>(\n client,\n includeGuessedCategories\n ? SUB_DATA_POINTS_WITH_GUESSES\n : SUB_DATA_POINTS,\n {\n first: pageSize,\n filterBy: {\n dataPoints: [dataPointId],\n },\n offset,\n },\n );\n\n subDataPoints.push(...nodes);\n offset += pageSize;\n shouldContinue = nodes.length === pageSize;\n\n if (debug) {\n logger.log(\n colors.green(\n `Pulled in subdatapoints for offset ${offset} for dataPointId=${dataPointId}`,\n ),\n );\n }\n } catch (err) {\n logger.error(\n colors.red(\n `An error fetching subdatapoints for offset ${offset} for dataPointId=${dataPointId}`,\n ),\n );\n throw err;\n }\n } while (shouldContinue);\n return sortBy(subDataPoints, 'name');\n}\n\n/**\n * Fetch all datapoints for a data silo\n *\n * @param client - GraphQL client\n * @param dataSiloId - Data silo ID\n * @param options - Options\n * @returns List of datapoints\n */\nexport async function fetchAllDataPoints(\n client: GraphQLClient,\n dataSiloId: string,\n {\n debug,\n pageSize,\n skipSubDatapoints,\n includeGuessedCategories,\n }: {\n /** Debug logs */\n debug: boolean;\n /** Page size */\n pageSize: number;\n /** Skip fetching of subdatapoints */\n skipSubDatapoints?: boolean;\n /** When true, metadata around guessed data categories should be included */\n includeGuessedCategories?: boolean;\n },\n): Promise<DataPointWithSubDataPoint[]> {\n const dataPoints: DataPointWithSubDataPoint[] = [];\n\n // TODO: https://transcend.height.app/T-40481 - add cursor pagination\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n if (debug) {\n logger.info(colors.magenta(`Fetching datapoints with offset: ${offset}`));\n }\n\n const {\n dataPoints: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n dataPoints: {\n /** List of matches */\n nodes: DataPoint[];\n };\n }>(client, DATA_POINTS, {\n first: pageSize,\n filterBy: {\n dataSilos: [dataSiloId],\n },\n offset,\n });\n\n if (debug) {\n logger.info(\n colors.magenta(\n `Fetched ${nodes.length} datapoints at offset: ${offset}`,\n ),\n );\n }\n\n if (!skipSubDatapoints) {\n await map(\n nodes,\n /* eslint-disable no-loop-func */\n async (node) => {\n try {\n if (debug) {\n logger.info(\n colors.magenta(\n `Fetching subdatapoints for ${node.name} for datapoint offset ${offset}`,\n ),\n );\n }\n\n const subDataPoints = await fetchAllSubDataPoints(client, node.id, {\n pageSize: 1000, // max page size\n debug,\n includeGuessedCategories,\n });\n dataPoints.push({\n ...node,\n subDataPoints: subDataPoints.sort((a, b) =>\n a.name.localeCompare(b.name),\n ),\n });\n\n if (debug) {\n logger.info(\n colors.green(\n `Successfully fetched subdatapoints for ${node.name}`,\n ),\n );\n }\n } catch (err) {\n logger.error(\n colors.red(\n `An error fetching subdatapoints for ${node.name} datapoint offset ${offset}`,\n ),\n );\n throw err;\n }\n },\n /* eslint-enable no-loop-func */\n {\n concurrency: 5,\n },\n );\n\n if (debug) {\n logger.info(\n colors.green(\n `Fetched all subdatapoints for page of datapoints at offset: ${offset}`,\n ),\n );\n }\n }\n\n offset += pageSize;\n shouldContinue = nodes.length === pageSize;\n } while (shouldContinue);\n return dataPoints.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport interface DataSiloEnriched {\n /** ID of dataSilo */\n id: string;\n /** Title of dataSilo */\n title: string;\n /** Type of silo */\n type: string;\n /** Link to silo */\n link: string;\n /** Outer type of silo */\n outerType: string;\n /** Description of data silo */\n description: string;\n /** Webhook URL */\n url?: string;\n /** Email address of user to notify for prompt a person use case */\n notifyEmailAddress?: string;\n /** Associated API keys */\n apiKeys: {\n /** Title */\n title: string;\n }[];\n /** Data subject block list */\n subjectBlocklist: {\n /** Type of data subject */\n type: string;\n }[];\n /** Identifiers */\n identifiers: {\n /** Name of identifier */\n name: string;\n /** True if identifier is wired */\n isConnected: boolean;\n }[];\n /** Dependent data silos */\n dependentDataSilos: {\n /** Title of silo */\n title: string;\n }[];\n /** Silo owners */\n owners: {\n /** Email owners */\n email: string;\n }[];\n /** The teams assigned to this data silo */\n teams: {\n /** Name of the team assigned to this data silo */\n name: string;\n }[];\n /** Metadata for this data silo */\n catalog: {\n /** Whether the data silo supports automated vendor coordination */\n hasAvcFunctionality: boolean;\n };\n /** Silo is live */\n isLive: boolean;\n /** Hosting country of data silo */\n country?: IsoCountryCode;\n /** Hosting subdivision data silo */\n countrySubDivision?: IsoCountrySubdivisionCode;\n /**\n * The frequency with which we should be sending emails for this data silo, in milliseconds.\n */\n promptAVendorEmailSendFrequency: number;\n /**\n * The type of emails to send for this data silo, i.e. send an email for each DSR, across all open DSRs,\n * or per profile in a DSR.\n */\n promptAVendorEmailSendType: PromptAVendorEmailSendType;\n /**\n * Indicates whether prompt-a-vendor emails should include a list of identifiers\n * in addition to a link to the bulk processing UI.\n */\n promptAVendorEmailIncludeIdentifiersAttachment: boolean;\n /**\n * Indicates what kind of link to generate as part of the emails sent out for this Prompt-a-Vendor silo.\n */\n promptAVendorEmailCompletionLinkType: PromptAVendorEmailCompletionLinkType;\n /**\n * The frequency with which we should retry sending emails for this data silo, in milliseconds.\n * Needs to be a string because the number can be larger than the MAX_INT\n */\n manualWorkRetryFrequency: string;\n /** Attribute values tagged to data silo */\n attributeValues: DataSiloAttributeValue[];\n /**\n * The data silos that discovered this particular data silo\n */\n discoveredBy: {\n /** Title of data silo */\n title: string;\n }[];\n /**\n * The business entities assigned directly to this data silo\n */\n businessEntities: {\n /** Title of business entity */\n title: string;\n }[];\n}\n\n/**\n * Fetch all dataSilos with additional metadata\n *\n * @param client - GraphQL client\n * @param options - Filter options\n * @returns All dataSilos in the organization\n */\nexport async function fetchEnrichedDataSilos(\n client: GraphQLClient,\n {\n ids,\n pageSize,\n titles,\n debug,\n skipDatapoints,\n skipSubDatapoints,\n includeGuessedCategories,\n integrationNames,\n }: {\n /** Page size */\n pageSize: number;\n /** Filter by IDs */\n ids?: string[];\n /** Enable debug logs */\n debug: boolean;\n /** Filter by title */\n titles?: string[];\n /** Integration names */\n integrationNames?: string[];\n /** Skip fetching of datapoints */\n skipDatapoints?: boolean;\n /** Skip fetching of subdatapoints */\n skipSubDatapoints?: boolean;\n /** When true, metadata around guessed data categories should be included */\n includeGuessedCategories?: boolean;\n },\n): Promise<[DataSiloEnriched, DataPointWithSubDataPoint[]][]> {\n const dataSilos: [DataSiloEnriched, DataPointWithSubDataPoint[]][] = [];\n\n // Grab silos\n const silos = await fetchAllDataSilos<DataSiloEnriched>(client, {\n titles,\n ids,\n integrationNames,\n pageSize,\n gql: DATA_SILOS_ENRICHED,\n });\n\n // Graph datapoints for each silo\n if (!skipDatapoints) {\n await mapSeries(silos, async (silo, index) => {\n logger.info(\n colors.magenta(\n `[${index + 1}/${silos.length}] Fetching data silo - ${silo.title}`,\n ),\n );\n\n const dataPoints = await fetchAllDataPoints(client, silo.id, {\n debug,\n pageSize,\n skipSubDatapoints,\n includeGuessedCategories,\n });\n\n if (debug) {\n logger.info(\n colors.green(\n `[${index + 1}/${\n silos.length\n }] Successfully fetched datapoint for - ${silo.title}`,\n ),\n );\n }\n\n dataSilos.push([silo, dataPoints]);\n });\n }\n\n logger.info(\n colors.green(\n `Successfully fetched all ${silos.length} data silo configurations`,\n ),\n );\n\n return dataSilos;\n}\n\n/**\n * Sync a data silo configuration\n *\n * @param dataSilos - Data silos to sync\n * @param client - GraphQL client\n * @param options - Options\n * @returns Data silo info\n */\nexport async function syncDataSilos(\n dataSilos: DataSiloInput[],\n client: GraphQLClient,\n {\n pageSize,\n dataSubjectsByName,\n apiKeysByTitle,\n }: {\n /** Page size */\n pageSize: number;\n /** The data subjects in the organization */\n dataSubjectsByName: { [type in string]: DataSubject };\n /** API key title to API key */\n apiKeysByTitle: { [title in string]: ApiKey };\n },\n): Promise<{\n /** Whether successfully updated */\n success: boolean;\n /** A mapping between data silo title to data silo ID */\n dataSiloTitleToId: { [k in string]: string };\n}> {\n let encounteredError = false;\n\n // Time duration\n const t0 = new Date().getTime();\n logger.info(colors.magenta(`Syncing \"${dataSilos.length}\" data silos...`));\n\n // Determine the set of data silos that already exist\n const existingDataSilos = await fetchAllDataSilos(client, {\n titles: dataSilos.map(({ title }) => title),\n pageSize,\n });\n\n // Create a mapping of title -> existing silo, if it exists\n const existingDataSiloByTitle = keyBy<Pick<DataSilo, 'id' | 'title'>>(\n existingDataSilos,\n 'title',\n );\n\n // Create new silos that do not exist\n const newDataSiloInputs = dataSilos.filter(\n ({ title }) => !existingDataSiloByTitle[title],\n );\n if (newDataSiloInputs.length > 0) {\n logger.info(\n colors.magenta(\n `Creating \"${newDataSiloInputs.length}\" data silos that did not exist...`,\n ),\n );\n\n // Batch the creation\n const chunked = chunk(newDataSiloInputs, BATCH_SILOS_LIMIT);\n await mapSeries(chunked, async (dependencyUpdateChunk) => {\n const {\n createDataSilos: { dataSilos },\n } = await makeGraphQLRequest<{\n /** Mutation result */\n createDataSilos: {\n /** New data silos */\n dataSilos: Pick<DataSilo, 'id' | 'title'>[];\n };\n }>(client, CREATE_DATA_SILOS, {\n input: dependencyUpdateChunk.map((input) => ({\n name: input['outer-type'] || input.integrationName,\n title: input.title,\n country: input.country,\n countrySubDivision: input.countrySubDivision,\n })),\n });\n\n // save mapping of title and id\n dataSilos.forEach((silo) => {\n existingDataSiloByTitle[silo.title] = silo;\n });\n });\n\n logger.info(\n colors.green(\n `Successfully created \"${newDataSiloInputs.length}\" data silos!`,\n ),\n );\n }\n\n // Batch the updates\n const chunkedUpdates = chunk(dataSilos, BATCH_SILOS_LIMIT);\n await mapSeries(chunkedUpdates, async (dataSiloUpdateChunk, ind) => {\n logger.info(\n colors.magenta(\n `[Batch ${ind + 1}/${chunkedUpdates.length}] Syncing \"${\n dataSiloUpdateChunk.length\n }\" data silos`,\n ),\n );\n await makeGraphQLRequest<{\n /** Mutation result */\n updateDataSilos: {\n /** New data silos */\n dataSilos: Pick<DataSilo, 'id' | 'title'>[];\n };\n }>(client, UPDATE_DATA_SILOS, {\n input: {\n dataSilos: dataSiloUpdateChunk.map((input) => ({\n id: existingDataSiloByTitle[input.title].id,\n country: input.country,\n countrySubDivision: input.countrySubDivision,\n url: input.url,\n headers: input.headers,\n description: input.description,\n identifiers: input['identity-keys'],\n isLive: !input.disabled,\n ownerEmails: input.owners,\n teamNames: input.teams,\n // clear out if not specified, otherwise the update needs to be applied after\n // all data silos are created\n dependedOnDataSiloTitles: input['deletion-dependencies']\n ? undefined\n : [],\n apiKeyId: input['api-key-title']\n ? apiKeysByTitle[input['api-key-title']].id\n : undefined,\n dataSubjectBlockListIds: input['data-subjects']\n ? convertToDataSubjectBlockList(\n input['data-subjects'],\n dataSubjectsByName,\n )\n : undefined,\n attributes: input.attributes,\n businessEntityTitles: input.businessEntityTitles,\n // AVC settings\n notifyEmailAddress: input['email-settings']?.['notify-email-address'],\n promptAVendorEmailSendFrequency:\n input['email-settings']?.['send-frequency'],\n promptAVendorEmailSendType: input['email-settings']?.['send-type'],\n promptAVendorEmailIncludeIdentifiersAttachment:\n input['email-settings']?.['include-identifiers-attachment'],\n promptAVendorEmailCompletionLinkType:\n input['email-settings']?.['completion-link-type'],\n manualWorkRetryFrequency:\n input['email-settings']?.['manual-work-retry-frequency'],\n })),\n },\n });\n logger.info(\n colors.green(\n `[Batch ${ind + 1}/${chunkedUpdates.length}] Synced \"${\n dataSiloUpdateChunk.length\n }\" data silos!`,\n ),\n );\n });\n\n // Sync datapoints\n\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n const dataSilosWithDataPoints = dataSilos.filter(\n ({ datapoints = [] }) => datapoints.length > 0,\n );\n const totalDataPoints = dataSilos\n .map(({ datapoints = [] }) => datapoints.length)\n .reduce((acc, count) => acc + count, 0);\n logger.info(\n colors.magenta(\n `Syncing \"${totalDataPoints}\" datapoints from \"${dataSilosWithDataPoints.length}\" data silos...`,\n ),\n );\n progressBar.start(totalDataPoints, 0);\n let total = 0;\n\n await map(\n dataSilosWithDataPoints,\n async ({ datapoints, title }) => {\n if (datapoints) {\n await mapSeries(datapoints, async (datapoint) => {\n const fields = datapoint.fields\n ? datapoint.fields.map(\n ({\n key,\n description,\n categories,\n purposes,\n attributes,\n ...rest\n }) =>\n // TODO: Support setting title separately from the 'key/name'\n ({\n name: key,\n description,\n categories: !categories\n ? undefined\n : categories.map((category) => ({\n ...category,\n name: category.name || 'Other',\n })),\n purposes: !purposes\n ? undefined\n : purposes.map((purpose) => ({\n ...purpose,\n name: purpose.name || 'Other',\n })),\n attributes,\n accessRequestVisibilityEnabled:\n rest['access-request-visibility-enabled'],\n erasureRequestRedactionEnabled:\n rest['erasure-request-redaction-enabled'],\n }),\n )\n : undefined;\n\n const payload = {\n dataSiloId: existingDataSiloByTitle[title].id,\n path: datapoint.path,\n name: datapoint.key,\n title: datapoint.title,\n description: datapoint.description,\n ...(datapoint.owners\n ? {\n ownerEmails: datapoint.owners,\n }\n : {}),\n ...(datapoint.teams\n ? {\n teamNames: datapoint.teams,\n }\n : {}),\n ...(datapoint['data-collection-tag']\n ? { dataCollectionTag: datapoint['data-collection-tag'] }\n : {}),\n querySuggestions: !datapoint['privacy-action-queries']\n ? undefined\n : Object.entries(datapoint['privacy-action-queries']).map(\n ([key, value]) => ({\n requestType: key,\n suggestedQuery: value,\n }),\n ),\n enabledActions: datapoint['privacy-actions'] || [], // clear out when not specified\n subDataPoints: fields,\n };\n\n // Ensure no duplicate sub-datapoints are provided\n const subDataPointsToUpdate = (payload.subDataPoints || []).map(\n ({ name }) => name,\n );\n const duplicateDataPoints = subDataPointsToUpdate.filter(\n (name, index) => subDataPointsToUpdate.indexOf(name) !== index,\n );\n if (duplicateDataPoints.length > 0) {\n logger.info(\n colors.red(\n `\\nCannot update datapoint \"${\n datapoint.key\n }\" as it has duplicate sub-datapoints with the same name: \\n${duplicateDataPoints.join(\n '\\n',\n )}`,\n ),\n );\n encounteredError = true;\n } else {\n try {\n await makeGraphQLRequest(\n client,\n UPDATE_OR_CREATE_DATA_POINT,\n payload,\n );\n } catch (err) {\n logger.info(\n colors.red(\n `\\nFailed to update datapoint \"${datapoint.key}\" for data silo \"${title}\"! - \\n${err.message}`,\n ),\n );\n encounteredError = true;\n }\n }\n total += 1;\n progressBar.update(total);\n });\n }\n },\n {\n concurrency: 10,\n },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Synced \"${\n dataSilos.length\n }\" data silos and \"${totalDataPoints}\" datapoints in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n return {\n success: !encounteredError,\n dataSiloTitleToId: apply(existingDataSiloByTitle, ({ id }) => id),\n };\n}\n\n/**\n * Sync data silo dependencies\n *\n * @param client - GraphQL client\n * @param dependencyUpdates - Mapping from [data silo ID, dependency titles]\n * @returns True upon success\n */\nexport async function syncDataSiloDependencies(\n client: GraphQLClient,\n dependencyUpdates: [string, string[]][],\n): Promise<boolean> {\n let encounteredError = false;\n logger.info(\n colors.magenta(\n `Syncing \"${dependencyUpdates.length}\" data silo dependencies...`,\n ),\n );\n\n // Batch the updates\n const chunkedUpdates = chunk(dependencyUpdates, BATCH_SILOS_LIMIT);\n await mapSeries(chunkedUpdates, async (dependencyUpdateChunk, ind) => {\n logger.info(\n colors.magenta(\n `[Batch ${ind}/${dependencyUpdateChunk.length}] Updating \"${dependencyUpdateChunk.length}\" data silos...`,\n ),\n );\n try {\n await makeGraphQLRequest<{\n /** Mutation result */\n updateDataSilos: {\n /** New data silos */\n dataSilos: Pick<DataSilo, 'id' | 'title'>[];\n };\n }>(client, UPDATE_DATA_SILOS, {\n input: {\n dataSilos: dependencyUpdateChunk.map(\n ([id, dependedOnDataSiloTitles]) => ({\n id,\n dependedOnDataSiloTitles,\n }),\n ),\n },\n });\n logger.info(\n colors.green(\n `[Batch ${ind + 1}/${dependencyUpdateChunk.length}] ` +\n `Synced \"${dependencyUpdateChunk.length}\" data silos!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `[Batch ${ind + 1}/${dependencyUpdateChunk.length}] ` +\n `Failed to update \"${dependencyUpdateChunk.length}\" silos! - ${err.message}`,\n ),\n );\n }\n });\n return !encounteredError;\n}\n/* eslint-enable max-lines */\n","import { EnricherInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { ENRICHERS, CREATE_ENRICHER, UPDATE_ENRICHER } from './gqls';\nimport {\n EnricherType,\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n PreflightRequestStatus,\n RequestAction,\n} from '@transcend-io/privacy-types';\nimport { Identifier } from './fetchIdentifiers';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { DataSubject } from './fetchDataSubjects';\n\nexport interface Enricher {\n /** ID of enricher */\n id: string;\n /** Title of enricher */\n title: string;\n /** URL of enricher */\n url: string;\n /** Server silo */\n type: EnricherType;\n /** Input identifier */\n inputIdentifier: {\n /** Identifier name */\n name: string;\n };\n /** The selected actions */\n actions: RequestAction[];\n /** Output identifiers */\n identifiers: {\n /** Identifier name */\n name: string;\n }[];\n /** Data subjects that the preflight check is configured for */\n dataSubjects: {\n /** Data subject type */\n type: string;\n }[];\n /** The duration (in ms) that the enricher should take to execute. - BigInt */\n expirationDuration: string;\n /** Looker query title */\n lookerQueryTitle?: string;\n /** A regular expression that can be used to match on for cancelation */\n testRegex?: string;\n /** The status that the enricher should transfer to when condition is met. */\n transitionRequestStatus?: PreflightRequestStatus;\n /** The twilio phone number to send from */\n phoneNumbers: string[];\n /**\n * The list of regions that should trigger the enrichment condition\n */\n regionList: (IsoCountryCode | IsoCountrySubdivisionCode)[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all enrichers in the organization\n *\n * @param client - GraphQL client\n * @param title - Filter by title\n * @returns All enrichers in the organization\n */\nexport async function fetchAllEnrichers(\n client: GraphQLClient,\n title?: string,\n): Promise<Enricher[]> {\n const enrichers: Enricher[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n enrichers: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n enrichers: {\n /** List of matches */\n nodes: Enricher[];\n };\n }>(client, ENRICHERS, {\n first: PAGE_SIZE,\n offset,\n title,\n });\n enrichers.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return enrichers.sort((a, b) => a.title.localeCompare(b.title));\n}\n\n/**\n * Sync an enricher configuration\n *\n * @param client - GraphQL client\n * @param options - Options\n */\nexport async function syncEnricher(\n client: GraphQLClient,\n {\n enricher,\n identifierByName,\n dataSubjectsByName,\n }: {\n /** The enricher input */\n enricher: EnricherInput;\n /** Index of identifiers in the organization */\n identifierByName: { [name in string]: Identifier };\n /** Lookup data subject by name */\n dataSubjectsByName: { [name in string]: DataSubject };\n },\n): Promise<void> {\n // Whether to continue looping\n const matches = await fetchAllEnrichers(client, enricher.title);\n const existingEnricher = matches.find(\n ({ title }) => title === enricher.title,\n );\n\n // Map to data subject Ids\n const dataSubjectIds = enricher['data-subjects']?.map((subject) => {\n const existing = dataSubjectsByName[subject];\n if (!existing) {\n throw new Error(`Failed to find a data subject with name: ${subject}`);\n }\n return existing.id;\n });\n\n // If enricher exists, update it, else create new\n const inputIdentifier = enricher['input-identifier'];\n const actionUpdates =\n enricher['privacy-actions'] || Object.values(RequestAction);\n if (existingEnricher) {\n await makeGraphQLRequest(client, UPDATE_ENRICHER, {\n input: {\n id: existingEnricher.id,\n title: enricher.title,\n url: enricher.url,\n headers: enricher.headers,\n testRegex: enricher.testRegex,\n lookerQueryTitle: enricher.lookerQueryTitle,\n expirationDuration:\n typeof enricher.expirationDuration === 'number'\n ? enricher.expirationDuration.toString()\n : undefined,\n transitionRequestStatus: enricher.transitionRequestStatus,\n phoneNumbers: enricher.phoneNumbers,\n regionList: enricher.regionList,\n dataSubjectIds,\n description: enricher.description || '',\n inputIdentifier: inputIdentifier\n ? identifierByName[inputIdentifier].id\n : undefined,\n identifiers: enricher['output-identifiers'].map(\n (id) => identifierByName[id].id,\n ),\n ...(existingEnricher.type === EnricherType.Sombra\n ? {}\n : { actions: actionUpdates }),\n },\n });\n } else if (inputIdentifier) {\n await makeGraphQLRequest(client, CREATE_ENRICHER, {\n input: {\n title: enricher.title,\n url: enricher.url,\n type: enricher.type || EnricherType.Server,\n headers: enricher.headers,\n testRegex: enricher.testRegex,\n lookerQueryTitle: enricher.lookerQueryTitle,\n expirationDuration:\n typeof enricher.expirationDuration === 'number'\n ? enricher.expirationDuration.toString()\n : undefined,\n transitionRequestStatus: enricher.transitionRequestStatus,\n phoneNumbers: enricher.phoneNumbers,\n dataSubjectIds,\n regionList: enricher.regionList,\n description: enricher.description || '',\n inputIdentifier: identifierByName[inputIdentifier].id,\n identifiers: enricher['output-identifiers'].map(\n (id) => identifierByName[id].id,\n ),\n actions: actionUpdates,\n },\n });\n }\n}\n","import { TemplateInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { TEMPLATES, CREATE_TEMPLATE } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface Template {\n /** ID of Template */\n id: string;\n /** Title of Template */\n title: string;\n /** Template subject (e.g. email subject) */\n subject: {\n /** Default message for template subject */\n defaultMessage: string;\n };\n /** Template body - rich text HTML */\n template: {\n /** Default message for template body */\n defaultMessage: string;\n };\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all Templates in the organization\n *\n * @param client - GraphQL client\n * @param title - Filter by title\n * @returns All Templates in the organization\n */\nexport async function fetchAllTemplates(\n client: GraphQLClient,\n title?: string,\n): Promise<Template[]> {\n const templates: Template[] = [];\n let offset = 0;\n\n // Try to fetch an Template with the same title\n let shouldContinue = false;\n do {\n const {\n templates: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n templates: {\n /** List of matches */\n nodes: Template[];\n };\n }>(client, TEMPLATES, {\n first: PAGE_SIZE,\n offset,\n title,\n });\n templates.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return templates.sort((a, b) => a.title.localeCompare(b.title));\n}\n\n/**\n * Sync an email template configuration\n *\n * @param template - The email template input\n * @param client - GraphQL client\n */\nexport async function syncTemplate(\n template: TemplateInput,\n client: GraphQLClient,\n): Promise<void> {\n // Try to fetch an Template with the same title\n const matches = await fetchAllTemplates(client, template.title);\n const existingTemplate = matches.find(\n ({ title }) => title === template.title,\n );\n\n // If Template exists, update it\n if (!existingTemplate) {\n await makeGraphQLRequest(client, CREATE_TEMPLATE, {\n title: template.title,\n });\n }\n}\n","import {\n IsoCountrySubdivisionCode,\n IsoCountryCode,\n} from '@transcend-io/privacy-types';\nimport type { RegionInput } from '../../codecs';\n\n// Country subdivision is nullable in DB\nexport interface Region {\n /** Country */\n country: IsoCountryCode;\n /** Sub division (may be null in DB) */\n countrySubDivision?: IsoCountrySubdivisionCode | null;\n}\n\n/**\n * Format regions list to remove null country subdivisions\n *\n * @param vals - Regions\n * @returns formatted regions\n */\nexport function formatRegions(vals: Region[]): RegionInput[] {\n return vals.map(({ country, countrySubDivision }) => ({\n country,\n ...(countrySubDivision ? { countrySubDivision } : {}),\n }));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { GLOBAL_ACTION_ITEM_COLLECTIONS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { TranscendProduct } from '@transcend-io/privacy-types';\n\nexport interface ActionItemCollection {\n /** ID of collection */\n id: string;\n /** Title of collection */\n title: string;\n /** Description of collection */\n description: string;\n /** Whether section is hidden */\n hidden: boolean;\n /** Which locations/products the action item shows up in */\n productLine: TranscendProduct;\n}\n\n/**\n * Fetch all action item collections in the organization\n *\n * @param client - GraphQL client\n * @param filterBy - Filter by\n * @returns All action item collections in the organization\n */\nexport async function fetchAllActionItemCollections(\n client: GraphQLClient,\n filterBy: {\n /** Filter on location */\n location?: TranscendProduct;\n } = {},\n): Promise<ActionItemCollection[]> {\n const {\n globalActionItemCollections: { nodes },\n } = await makeGraphQLRequest<{\n /** ActionItemCollections */\n globalActionItemCollections: {\n /** List */\n nodes: ActionItemCollection[];\n };\n }>(client, GLOBAL_ACTION_ITEM_COLLECTIONS, {\n filterBy: {\n ...filterBy,\n },\n });\n return nodes;\n}\n","import colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { CREATE_CONSENT_PARTITION, CONSENT_PARTITIONS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { mapSeries } from '../bluebird';\nimport { difference } from 'lodash-es';\nimport { logger } from '../../logger';\nimport { PartitionInput } from '../../codecs';\nimport { fetchConsentManagerId } from './fetchConsentManagerId';\n\nconst PAGE_SIZE = 50;\n\nexport interface TranscendPartition {\n /** ID of the partition */\n id: string;\n /** Name of partition */\n name: string;\n /** Partition value */\n partition: string;\n}\n\n/**\n * Fetch the list of partitions\n *\n * @param client - GraphQL client\n * @returns Partition list\n */\nexport async function fetchPartitions(\n client: GraphQLClient,\n): Promise<TranscendPartition[]> {\n const partitions: TranscendPartition[] = [];\n let offset = 0;\n\n // Fetch all partitions\n let shouldContinue = false;\n do {\n const {\n consentPartitions: { nodes },\n } = await makeGraphQLRequest<{\n /** Consent experience */\n consentPartitions: {\n /** List */\n nodes: TranscendPartition[];\n };\n }>(client, CONSENT_PARTITIONS, {\n first: PAGE_SIZE,\n offset,\n });\n partitions.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return partitions.sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/**\n * Sync the consent manager\n *\n * @param client - GraphQL client\n * @param partitionInputs - The partition input\n *@returns true on success\n */\nexport async function syncPartitions(\n client: GraphQLClient,\n partitionInputs: PartitionInput[],\n): Promise<boolean> {\n // Grab the bundleId associated with this API key\n const airgapBundleId = await fetchConsentManagerId(client);\n let encounteredError = false;\n const partitions = await fetchPartitions(client);\n const newPartitionNames = difference(\n partitionInputs.map(({ name }) => name),\n partitions.map(({ name }) => name),\n );\n await mapSeries(newPartitionNames, async (name) => {\n try {\n await makeGraphQLRequest(client, CREATE_CONSENT_PARTITION, {\n input: {\n id: airgapBundleId,\n name,\n },\n });\n logger.info(\n colors.green(`Successfully created consent partition: ${name}!`),\n );\n } catch (err) {\n logger.error(\n colors.red(\n `Failed to create consent partition: ${name}! - ${err.message}`,\n ),\n );\n encounteredError = true;\n }\n });\n return !encounteredError;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { SILO_DISCOVERY_RESULTS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport type {\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\n\nexport interface SiloDiscoveryResult {\n /** Title of silo discovery result */\n title?: string;\n /** Resource ID of silo discovery result */\n resourceId: string;\n /** Suggested catalog */\n suggestedCatalog: {\n /** Title for the suggested catalog */\n title: string;\n };\n /** The likelihood that data is sensitive for this results */\n containsSensitiveData: string;\n /** The status of silo discovery triage */\n status: string;\n /** Hosting country of data silo discovery result */\n country?: IsoCountryCode;\n /** Hosting subdivision data silo discovery result */\n countrySubDivision?: IsoCountrySubdivisionCode;\n /** Plaintext context data silo discovery result */\n plaintextContext: string;\n /** The plugin that found this result */\n plugin: {\n /** The data silo the plugin belongs to */\n dataSilo: {\n /** The internal display title */\n title: string;\n };\n };\n}\n\nconst PAGE_SIZE = 30;\n\n/**\n * Fetch all silo discovery results in the organization\n *\n * @param client - GraphQL client\n * @returns All silo discovery results in the organization\n */\nexport async function fetchAllSiloDiscoveryResults(\n client: GraphQLClient,\n): Promise<SiloDiscoveryResult[]> {\n const siloDiscoveryResults: SiloDiscoveryResult[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n siloDiscoveryResults: { nodes },\n } = await makeGraphQLRequest<{\n /** Discovery results */\n siloDiscoveryResults: {\n /** Nodes */\n nodes: SiloDiscoveryResult[];\n };\n }>(client, SILO_DISCOVERY_RESULTS, {\n first: PAGE_SIZE,\n offset,\n input: {},\n filterBy: {},\n });\n\n const titledNodes = nodes.map((node) =>\n node.title === null && node.suggestedCatalog?.title\n ? { ...node, title: node.suggestedCatalog.title }\n : node,\n );\n\n siloDiscoveryResults.push(...titledNodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return siloDiscoveryResults;\n}\n","/* eslint-disable max-lines */\nimport {\n TranscendInput,\n ApiKeyInput,\n DataSiloInput,\n AttributeInput,\n ActionInput,\n IdentifierInput,\n BusinessEntityInput,\n EnricherInput,\n PromptGroupInput,\n DataFlowInput,\n PromptPartialInput,\n DataSubjectInput,\n CookieInput,\n PromptInput,\n DatapointInput,\n FieldInput,\n ProcessingPurposeInput,\n ProcessingActivityInput,\n DataCategoryInput,\n VendorInput,\n AgentFileInput,\n AgentFunctionInput,\n AgentInput,\n PolicyInput,\n IntlMessageInput,\n ActionItemInput,\n TeamInput,\n ActionItemCollectionInput,\n AssessmentInput,\n AssessmentTemplateInput,\n AssessmentSectionInput,\n AssessmentSectionQuestionInput,\n RiskLogicInput,\n ConsentPurpose,\n type SiloDiscoveryResultInput,\n} from '../../codecs';\nimport {\n RequestAction,\n ConsentTrackerStatus,\n ActionItemCode,\n RetentionType,\n} from '@transcend-io/privacy-types';\nimport { GraphQLClient } from 'graphql-request';\nimport { flatten, keyBy, mapValues } from 'lodash-es';\nimport { fetchEnrichedDataSilos } from './syncDataSilos';\nimport {\n convertToDataSubjectAllowlist,\n fetchAllDataSubjects,\n} from './fetchDataSubjects';\nimport { fetchApiKeys } from './fetchApiKeys';\nimport {\n fetchConsentManager,\n fetchConsentManagerExperiences,\n fetchConsentManagerTheme,\n} from './fetchConsentManagerId';\nimport { fetchAllEnrichers } from './syncEnrichers';\nimport { fetchAllDataFlows } from './fetchAllDataFlows';\nimport { fetchAllBusinessEntities } from './fetchAllBusinessEntities';\nimport { fetchAllProcessingActivities } from './fetchAllProcessingActivities';\nimport { fetchAllActions } from './fetchAllActions';\nimport { fetchAllAgents } from './fetchAllAgents';\nimport { fetchAllAgentFunctions } from './fetchAllAgentFunctions';\nimport { fetchAllAgentFiles } from './fetchAllAgentFiles';\nimport { fetchAllVendors } from './fetchAllVendors';\nimport { fetchAllDataCategories } from './fetchAllDataCategories';\nimport { fetchAllProcessingPurposes } from './fetchAllProcessingPurposes';\nimport { fetchAllIdentifiers } from './fetchIdentifiers';\nimport { fetchAllPrompts } from './fetchPrompts';\nimport { fetchAllPromptPartials } from './fetchPromptPartials';\nimport { fetchAllPolicies } from './fetchAllPolicies';\nimport { fetchAllPrivacyCenters } from './fetchAllPrivacyCenters';\nimport { fetchAllMessages } from './fetchAllMessages';\nimport { fetchAllPromptGroups } from './fetchPromptGroups';\nimport { fetchAllCookies } from './fetchAllCookies';\nimport { fetchAllTemplates } from './syncTemplates';\nimport { fetchAllAttributes } from './fetchAllAttributes';\nimport { formatAttributeValues } from './formatAttributeValues';\nimport { formatRegions } from './formatRegions';\nimport { logger } from '../../logger';\nimport colors from 'colors';\nimport { TranscendPullResource } from '../../enums';\nimport { fetchAllActionItems } from './fetchAllActionItems';\nimport { fetchAllTeams } from './fetchAllTeams';\nimport { fetchAllActionItemCollections } from './fetchAllActionItemCollections';\nimport { LocaleValue } from '@transcend-io/internationalization';\nimport { fetchPartitions } from './syncPartitions';\nimport { fetchAllAssessments } from './fetchAllAssessments';\nimport { fetchAllAssessmentTemplates } from './fetchAllAssessmentTemplates';\nimport {\n parseAssessmentDisplayLogic,\n type AssessmentRule,\n} from './parseAssessmentDisplayLogic';\nimport { parseAssessmentRiskLogic } from './parseAssessmentRiskLogic';\nimport { fetchAllPurposesAndPreferences } from './fetchAllPurposesAndPreferences';\nimport { fetchAllSiloDiscoveryResults } from './fetchAllSiloDiscoveryResults';\n\nexport const DEFAULT_TRANSCEND_PULL_RESOURCES = [\n TranscendPullResource.DataSilos,\n TranscendPullResource.Enrichers,\n TranscendPullResource.Templates,\n TranscendPullResource.ApiKeys,\n];\n\nexport interface TranscendPullConfigurationInput {\n /** Page size */\n pageSize: number;\n /** Enable debug logs */\n debug: boolean;\n /** The data silo IDs to sync. If empty list, pull all. */\n dataSiloIds: string[];\n /** Resources to pull in */\n resources?: TranscendPullResource[];\n /** The data silo types to sync.If empty list, pull all. */\n integrationNames: string[];\n /** The tracker statuses to pull */\n trackerStatuses?: ConsentTrackerStatus[];\n /** Skip fetching of datapoints */\n skipDatapoints?: boolean;\n /** Skip fetching of subdatapoints */\n skipSubDatapoints?: boolean;\n /** When true, metadata around guessed data categories should be included */\n includeGuessedCategories?: boolean;\n}\n\n/**\n * Pull a yaml configuration from Transcend\n *\n * @param client - GraphQL client\n * @param dataSiloIds - The data silos to sync. If empty list, pull all.\n * @returns The configuration\n */\nexport async function pullTranscendConfiguration(\n client: GraphQLClient,\n {\n dataSiloIds,\n integrationNames,\n debug,\n resources = DEFAULT_TRANSCEND_PULL_RESOURCES,\n pageSize,\n skipDatapoints,\n includeGuessedCategories,\n skipSubDatapoints,\n trackerStatuses = Object.values(ConsentTrackerStatus),\n }: TranscendPullConfigurationInput,\n): Promise<TranscendInput> {\n if (dataSiloIds.length > 0 && integrationNames.length > 0) {\n throw new Error(\n 'Only 1 of integrationNames OR dataSiloIds can be provided',\n );\n }\n\n logger.info(colors.magenta(`Fetching data with page size ${pageSize}...`));\n\n // Fetch all data, but only conditional fetch data that is requested\n const [\n dataSubjects,\n apiKeyTitleMap,\n dataSilos,\n enrichers,\n dataFlows,\n cookies,\n attributes,\n templates,\n identifiers,\n actions,\n businessEntities,\n processingActivities,\n consentManager,\n consentManagerExperiences,\n prompts,\n promptPartials,\n promptGroups,\n agents,\n agentFunctions,\n agentFiles,\n vendors,\n dataCategories,\n processingPurposes,\n actionItems,\n actionItemCollections,\n teams,\n policies,\n privacyCenters,\n messages,\n partitions,\n assessments,\n assessmentTemplates,\n purposes,\n siloDiscoveryResults,\n ] = await Promise.all([\n // Grab all data subjects in the organization\n resources.includes(TranscendPullResource.DataSilos) ||\n resources.includes(TranscendPullResource.DataSubjects)\n ? fetchAllDataSubjects(client)\n : [],\n // Grab API keys\n resources.includes(TranscendPullResource.ApiKeys)\n ? fetchApiKeys({}, client, true)\n : [],\n // Fetch the data silos\n resources.includes(TranscendPullResource.DataSilos)\n ? fetchEnrichedDataSilos(client, {\n ids: dataSiloIds,\n integrationNames,\n pageSize,\n debug,\n includeGuessedCategories,\n skipDatapoints,\n skipSubDatapoints,\n })\n : [],\n // Fetch enrichers\n resources.includes(TranscendPullResource.Enrichers)\n ? fetchAllEnrichers(client)\n : [],\n // Fetch data flows\n resources.includes(TranscendPullResource.DataFlows)\n ? [\n ...(trackerStatuses.includes(ConsentTrackerStatus.Live)\n ? await fetchAllDataFlows(client, ConsentTrackerStatus.Live)\n : []),\n ...(trackerStatuses.includes(ConsentTrackerStatus.NeedsReview)\n ? await fetchAllDataFlows(client, ConsentTrackerStatus.NeedsReview)\n : []),\n ]\n : [],\n // Fetch data flows\n resources.includes(TranscendPullResource.Cookies)\n ? [\n ...(trackerStatuses.includes(ConsentTrackerStatus.Live)\n ? await fetchAllCookies(client, ConsentTrackerStatus.Live)\n : []),\n ...(trackerStatuses.includes(ConsentTrackerStatus.NeedsReview)\n ? await fetchAllCookies(client, ConsentTrackerStatus.NeedsReview)\n : []),\n ]\n : [],\n // Fetch attributes\n resources.includes(TranscendPullResource.Attributes)\n ? fetchAllAttributes(client)\n : [],\n // Fetch email templates\n resources.includes(TranscendPullResource.Templates)\n ? fetchAllTemplates(client)\n : [],\n // Fetch identifiers\n resources.includes(TranscendPullResource.Identifiers)\n ? fetchAllIdentifiers(client)\n : [],\n // Fetch actions\n resources.includes(TranscendPullResource.Actions)\n ? fetchAllActions(client)\n : [],\n // Fetch business entities\n resources.includes(TranscendPullResource.BusinessEntities)\n ? fetchAllBusinessEntities(client)\n : [],\n // Fetch processing activities\n resources.includes(TranscendPullResource.ProcessingActivities)\n ? fetchAllProcessingActivities(client)\n : [],\n // Fetch consent manager\n resources.includes(TranscendPullResource.ConsentManager)\n ? fetchConsentManager(client)\n : undefined,\n // Fetch consent manager experiences\n resources.includes(TranscendPullResource.ConsentManager)\n ? fetchConsentManagerExperiences(client)\n : [],\n // Fetch prompts\n resources.includes(TranscendPullResource.Prompts)\n ? fetchAllPrompts(client)\n : [],\n // Fetch promptPartials\n resources.includes(TranscendPullResource.PromptPartials)\n ? fetchAllPromptPartials(client)\n : [],\n // Fetch promptGroups\n resources.includes(TranscendPullResource.PromptGroups)\n ? fetchAllPromptGroups(client)\n : [],\n // Fetch agents\n resources.includes(TranscendPullResource.Agents)\n ? fetchAllAgents(client)\n : [],\n // Fetch agentFunctions\n resources.includes(TranscendPullResource.AgentFunctions)\n ? fetchAllAgentFunctions(client)\n : [],\n // Fetch agentFiles\n resources.includes(TranscendPullResource.AgentFiles)\n ? fetchAllAgentFiles(client)\n : [],\n // Fetch vendors\n resources.includes(TranscendPullResource.Vendors)\n ? fetchAllVendors(client)\n : [],\n // Fetch dataCategories\n resources.includes(TranscendPullResource.DataCategories)\n ? fetchAllDataCategories(client)\n : [],\n // Fetch dataCategories\n resources.includes(TranscendPullResource.ProcessingPurposes)\n ? fetchAllProcessingPurposes(client)\n : [],\n // Fetch actionItems\n resources.includes(TranscendPullResource.ActionItems)\n ? fetchAllActionItems(client, { type: [ActionItemCode.Onboarding] })\n : [],\n // Fetch actionItemCollections\n resources.includes(TranscendPullResource.ActionItemCollections)\n ? fetchAllActionItemCollections(client)\n : [],\n // Fetch teams\n resources.includes(TranscendPullResource.Teams)\n ? fetchAllTeams(client)\n : [],\n // Fetch policies\n resources.includes(TranscendPullResource.Policies)\n ? fetchAllPolicies(client)\n : [],\n // Fetch privacy centers\n resources.includes(TranscendPullResource.PrivacyCenters)\n ? fetchAllPrivacyCenters(client)\n : [],\n // Fetch messages\n resources.includes(TranscendPullResource.Messages)\n ? fetchAllMessages(client)\n : [],\n // Fetch partitions\n resources.includes(TranscendPullResource.Partitions)\n ? fetchPartitions(client)\n : [],\n // Fetch assessments\n resources.includes(TranscendPullResource.Assessments)\n ? fetchAllAssessments(client)\n : [],\n // Fetch assessmentTemplates\n resources.includes(TranscendPullResource.AssessmentTemplates)\n ? fetchAllAssessmentTemplates(client)\n : [],\n // Fetch purpose and preferences\n resources.includes(TranscendPullResource.Purposes)\n ? fetchAllPurposesAndPreferences(client)\n : [],\n // Fetch silo discovery results\n resources.includes(TranscendPullResource.SystemDiscovery)\n ? fetchAllSiloDiscoveryResults(client)\n : [],\n ]);\n\n const consentManagerTheme =\n resources.includes(TranscendPullResource.ConsentManager) && consentManager\n ? await fetchConsentManagerTheme(client, consentManager.id)\n : undefined;\n\n const result: TranscendInput = {};\n\n // Save API keys\n const apiKeyTitles = flatten(\n dataSilos.map(([{ apiKeys }]) => apiKeys.map(({ title }) => title)),\n );\n const relevantApiKeys = Object.values(apiKeyTitleMap).filter(({ title }) =>\n resources.includes(TranscendPullResource.ApiKeys)\n ? true\n : apiKeyTitles.includes(title),\n );\n if (\n relevantApiKeys.length > 0 &&\n resources.includes(TranscendPullResource.ApiKeys)\n ) {\n result['api-keys'] = relevantApiKeys.map(\n ({ title }): ApiKeyInput => ({\n title,\n }),\n );\n }\n\n // Save Partitions\n if (\n partitions.length > 0 &&\n resources.includes(TranscendPullResource.Partitions)\n ) {\n result.partitions = partitions.map(({ name, partition }) => ({\n name,\n partition,\n }));\n }\n\n // Save Consent Manager\n if (\n consentManager &&\n resources.includes(TranscendPullResource.ConsentManager)\n ) {\n result['consent-manager'] = {\n bundleUrls: {\n TEST: consentManager.testBundleURL,\n PRODUCTION: consentManager.bundleURL,\n },\n domains: consentManager.configuration.domains || undefined,\n partition: consentManager.configuration.partition || undefined,\n consentPrecedence:\n consentManager.configuration.consentPrecedence || undefined,\n unknownRequestPolicy:\n consentManager.configuration.unknownRequestPolicy || undefined,\n unknownCookiePolicy:\n consentManager.configuration.unknownCookiePolicy || undefined,\n syncEndpoint: consentManager.configuration.syncEndpoint || undefined,\n telemetryPartitioning:\n consentManager.configuration.telemetryPartitioning || undefined,\n signedIabAgreement:\n consentManager.configuration.signedIabAgreement || undefined,\n // TODO: https://transcend.height.app/T-23919 - reconsider simpler yml shape\n syncGroups: consentManager.configuration.syncGroups || undefined,\n theme: !consentManagerTheme\n ? undefined\n : {\n primaryColor: consentManagerTheme.primaryColor || undefined,\n fontColor: consentManagerTheme.fontColor || undefined,\n privacyPolicy: consentManagerTheme.privacyPolicy || undefined,\n prompt: consentManagerTheme.prompt,\n },\n experiences: consentManagerExperiences.map((experience) => ({\n name: experience.name,\n displayName: experience.displayName || undefined,\n regions: experience.regions.map((region) => ({\n countrySubDivision: region.countrySubDivision || undefined,\n country: region.country || undefined,\n })),\n onConsentExpiry: experience.onConsentExpiry,\n consentExpiry: experience.consentExpiry,\n operator: experience.operator,\n displayPriority: experience.displayPriority,\n viewState: experience.viewState,\n purposes: experience.purposes.map((purpose) => ({\n trackingType: purpose.trackingType,\n })),\n optedOutPurposes: experience.optedOutPurposes.map((purpose) => ({\n trackingType: purpose.trackingType,\n })),\n browserLanguages: experience.browserLanguages,\n browserTimeZones: experience.browserTimeZones,\n })),\n };\n }\n\n // Save assessments\n if (\n assessments.length > 0 &&\n resources.includes(TranscendPullResource.Assessments)\n ) {\n result.assessments = assessments.map(\n ({\n title,\n assessmentGroup,\n sections,\n creator,\n description,\n status,\n assignees,\n externalAssignees,\n reviewers,\n isLocked,\n isArchived,\n isExternallyCreated,\n dueDate,\n createdAt,\n assignedAt,\n submittedAt,\n approvedAt,\n rejectedAt,\n titleIsInternal,\n retentionSchedule,\n attributeValues,\n resources,\n syncedRows,\n }): AssessmentInput => ({\n title,\n group: assessmentGroup.title,\n sections: sections.map(\n ({\n title,\n status,\n questions,\n assignees,\n isReviewed,\n externalAssignees,\n }): AssessmentSectionInput => ({\n title,\n status,\n questions: questions.map(\n ({\n title,\n type,\n subType,\n placeholder,\n description,\n isRequired,\n referenceId,\n displayLogic,\n riskLogic,\n riskCategories,\n riskFramework,\n answerOptions,\n selectedAnswers,\n allowedMimeTypes,\n allowSelectOther,\n syncModel,\n syncColumn,\n attributeKey,\n requireRiskEvaluation,\n requireRiskMatrixEvaluation,\n }): AssessmentSectionQuestionInput => {\n const displayLogicParsed = displayLogic\n ? parseAssessmentDisplayLogic(displayLogic)\n : undefined;\n return {\n title,\n type,\n 'sub-type': subType,\n placeholder,\n description,\n 'is-required': isRequired,\n 'reference-id': referenceId,\n 'display-logic':\n displayLogicParsed &&\n Object.keys(displayLogicParsed).length > 0\n ? {\n action: displayLogicParsed.action!,\n rule: displayLogicParsed.rule\n ? {\n 'depends-on-question-reference-id':\n displayLogicParsed.rule\n .dependsOnQuestionReferenceId,\n 'comparison-operator':\n displayLogicParsed.rule.comparisonOperator,\n 'comparison-operands':\n // Safely access property with a check\n 'comparisonOperands' in\n displayLogicParsed.rule\n ? displayLogicParsed.rule.comparisonOperands\n : undefined,\n }\n : undefined,\n 'nested-rule': displayLogicParsed.nestedRule\n ? {\n 'logic-operator':\n displayLogicParsed.nestedRule.logicOperator,\n rules: (\n displayLogicParsed.nestedRule.rules || []\n ).map((rule: AssessmentRule) => ({\n 'depends-on-question-reference-id':\n rule.dependsOnQuestionReferenceId,\n 'comparison-operator':\n rule.comparisonOperator,\n 'comparison-operands':\n // Safely access property on the nested rule\n 'comparisonOperands' in rule\n ? rule.comparisonOperands\n : undefined,\n })),\n }\n : undefined,\n }\n : undefined,\n 'risk-logic': riskLogic.map((logic): RiskLogicInput => {\n const parsed = parseAssessmentRiskLogic(logic);\n return {\n 'risk-level': parsed.riskAssignment?.riskLevelId,\n 'comparison-operands': parsed.comparisonOperands,\n 'comparison-operator': parsed.comparisonOperator,\n };\n }),\n 'risk-categories': riskCategories.map(({ title }) => title),\n 'risk-framework': riskFramework?.title,\n 'answer-options': answerOptions.map(({ value }) => ({\n value,\n })),\n 'selected-answers': selectedAnswers.map(({ value }) => value),\n 'allowed-mime-types': allowedMimeTypes,\n 'allow-select-other': allowSelectOther,\n 'sync-model': syncModel || undefined,\n 'sync-column': syncColumn || undefined,\n 'attribute-key': attributeKey?.name,\n 'require-risk-evaluation': requireRiskEvaluation,\n 'require-risk-matrix-evaluation': requireRiskMatrixEvaluation,\n };\n },\n ),\n assignees: assignees.map(({ email }) => email),\n 'external-assignees': externalAssignees.map(({ email }) => email),\n 'is-reviewed': isReviewed,\n }),\n ),\n creator: creator?.email,\n description,\n status,\n assignees: assignees.map(({ email }) => email),\n 'external-assignees': externalAssignees.map(({ email }) => email),\n reviewers: reviewers.map(({ email }) => email),\n locked: isLocked,\n archived: isArchived,\n external: isExternallyCreated,\n 'title-is-internal': titleIsInternal,\n 'due-date': dueDate || undefined,\n 'created-at': createdAt || undefined,\n 'assigned-at': assignedAt || undefined,\n 'submitted-at': submittedAt || undefined,\n 'approved-at': approvedAt || undefined,\n 'rejected-at': rejectedAt || undefined,\n 'retention-schedule': retentionSchedule\n ? {\n type: retentionSchedule.type,\n 'duration-days': retentionSchedule.durationDays,\n operand: retentionSchedule.operation,\n }\n : undefined,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n resources: resources.map(\n ({ resourceType, title, name, category, type, purpose }) => ({\n type: resourceType,\n title: category\n ? `${category} - ${name}`\n : purpose\n ? `${purpose} - ${name}`\n : title || name || type || '',\n }),\n ),\n rows: syncedRows.map(\n ({ resourceType, title, name, category, type, purpose }) => ({\n type: resourceType,\n title: category\n ? `${category} - ${name}`\n : purpose\n ? `${purpose} - ${name}`\n : title || name || type || '',\n }),\n ),\n }),\n );\n }\n\n // Save assessmentTemplates\n if (\n assessmentTemplates.length > 0 &&\n resources.includes(TranscendPullResource.AssessmentTemplates)\n ) {\n result['assessment-templates'] = assessmentTemplates.map(\n ({\n title,\n description,\n sections,\n status,\n source,\n creator,\n isLocked,\n isArchived,\n createdAt,\n retentionSchedule,\n }): AssessmentTemplateInput => ({\n title,\n description,\n sections: sections.map(\n ({ title, questions }): AssessmentSectionInput => ({\n title,\n questions: questions.map(\n ({\n title,\n type,\n subType,\n placeholder,\n description,\n isRequired,\n referenceId,\n displayLogic,\n riskLogic,\n riskCategories,\n riskFramework,\n answerOptions,\n allowedMimeTypes,\n allowSelectOther,\n syncModel,\n syncColumn,\n attributeKey,\n requireRiskEvaluation,\n requireRiskMatrixEvaluation,\n }): AssessmentSectionQuestionInput => {\n const displayLogicParsed = displayLogic\n ? parseAssessmentDisplayLogic(displayLogic)\n : undefined;\n return {\n title,\n type,\n 'sub-type': subType,\n placeholder,\n description,\n 'is-required': isRequired,\n 'reference-id': referenceId,\n 'display-logic':\n displayLogicParsed &&\n Object.keys(displayLogicParsed).length > 0\n ? {\n action: displayLogicParsed.action!,\n rule: displayLogicParsed.rule\n ? {\n 'depends-on-question-reference-id':\n displayLogicParsed.rule\n .dependsOnQuestionReferenceId,\n 'comparison-operator':\n displayLogicParsed.rule.comparisonOperator,\n 'comparison-operands':\n // Safely access property with a check\n 'comparisonOperands' in\n displayLogicParsed.rule\n ? displayLogicParsed.rule.comparisonOperands\n : undefined,\n }\n : undefined,\n 'nested-rule': displayLogicParsed.nestedRule\n ? {\n 'logic-operator':\n displayLogicParsed.nestedRule.logicOperator,\n rules: (\n displayLogicParsed.nestedRule.rules || []\n ).map((rule: AssessmentRule) => ({\n 'depends-on-question-reference-id':\n rule.dependsOnQuestionReferenceId,\n 'comparison-operator':\n rule.comparisonOperator,\n 'comparison-operands':\n // Safely access property on the nested rule\n 'comparisonOperands' in rule\n ? rule.comparisonOperands\n : undefined,\n })),\n }\n : undefined,\n }\n : undefined,\n 'risk-logic': riskLogic.map((logic): RiskLogicInput => {\n const parsed = parseAssessmentRiskLogic(logic);\n return {\n 'risk-level': parsed.riskAssignment?.riskLevelId,\n 'risk-matrix-row': parsed.riskAssignment?.riskMatrixRowId,\n 'risk-matrix-column':\n parsed.riskAssignment?.riskMatrixColumnId,\n 'comparison-operands': parsed.comparisonOperands,\n 'comparison-operator': parsed.comparisonOperator,\n };\n }),\n 'risk-categories': riskCategories.map(({ title }) => title),\n 'risk-framework': riskFramework?.title,\n 'answer-options': answerOptions.map(({ value }) => ({\n value,\n })),\n 'allowed-mime-types': allowedMimeTypes,\n 'allow-select-other': allowSelectOther,\n 'sync-model': syncModel || undefined,\n 'sync-column': syncColumn || undefined,\n 'attribute-key': attributeKey?.name,\n 'require-risk-evaluation': requireRiskEvaluation,\n 'require-risk-matrix-evaluation': requireRiskMatrixEvaluation,\n };\n },\n ),\n }),\n ),\n status,\n source,\n creator: creator?.email,\n locked: isLocked,\n archived: isArchived,\n 'created-at': createdAt || undefined,\n 'retention-schedule': retentionSchedule\n ? {\n type: retentionSchedule.type,\n 'duration-days': retentionSchedule.durationDays,\n operand: retentionSchedule.operation,\n }\n : undefined,\n }),\n );\n }\n\n // Save Silo Discovery Results\n if (\n siloDiscoveryResults.length > 0 &&\n resources.includes(TranscendPullResource.SystemDiscovery)\n ) {\n result['system-discovery'] = siloDiscoveryResults.map(\n ({\n title,\n resourceId,\n suggestedCatalog: { title: suggestedCatalogTitle },\n plugin: {\n dataSilo: { title: dataSiloTitle },\n },\n country,\n countrySubDivision,\n plaintextContext,\n containsSensitiveData,\n status,\n }): SiloDiscoveryResultInput => ({\n title,\n resourceId,\n suggestedCatalog: suggestedCatalogTitle,\n plugin: dataSiloTitle,\n country: country || undefined,\n countrySubDivision: countrySubDivision || undefined,\n plaintextContext,\n containsSensitiveData,\n status,\n }),\n );\n }\n\n // Save prompts\n if (prompts.length > 0 && resources.includes(TranscendPullResource.Prompts)) {\n result.prompts = prompts.map(\n ({ title, content }): PromptInput => ({\n title,\n content,\n }),\n );\n }\n\n // Save promptPartials\n if (\n promptPartials.length > 0 &&\n resources.includes(TranscendPullResource.PromptPartials)\n ) {\n result['prompt-partials'] = promptPartials.map(\n ({ title, content }): PromptPartialInput => ({\n title,\n content,\n }),\n );\n }\n\n // Save promptGroups\n if (\n promptGroups.length > 0 &&\n resources.includes(TranscendPullResource.PromptGroups)\n ) {\n result['prompt-groups'] = promptGroups.map(\n ({ title, description, prompts }): PromptGroupInput => ({\n title,\n description,\n prompts: prompts.map(({ title }) => title),\n }),\n );\n }\n\n // Save teams\n if (teams.length > 0 && resources.includes(TranscendPullResource.Teams)) {\n result.teams = teams.map(\n ({\n name,\n description,\n ssoDepartment,\n ssoGroup,\n ssoTitle,\n users,\n scopes,\n }): TeamInput => ({\n name,\n description,\n 'sso-department': ssoDepartment || undefined,\n 'sso-group': ssoGroup || undefined,\n 'sso-title': ssoTitle || undefined,\n users: users.map(({ email }) => email),\n scopes: scopes.map(({ name }) => name),\n }),\n );\n }\n\n // Save Data Subjects\n if (\n dataSubjects.length > 0 &&\n resources.includes(TranscendPullResource.DataSubjects)\n ) {\n result['data-subjects'] = dataSubjects.map(\n ({\n type,\n title,\n active,\n adminDashboardDefaultSilentMode,\n actions,\n }): DataSubjectInput => ({\n type,\n title: title?.defaultMessage,\n active,\n adminDashboardDefaultSilentMode,\n actions: actions.map(({ type }) => type),\n }),\n );\n }\n\n // Save privacy policies\n if (policies.length > 0) {\n result.policies = policies.map(\n ({ title, versions, disabledLocales }): PolicyInput => ({\n title: title?.defaultMessage,\n content: versions?.[0]?.content?.defaultMessage,\n disabledLocales,\n }),\n );\n }\n\n // Save messages\n if (messages.length > 0) {\n result.messages = messages.map(\n ({\n id,\n defaultMessage,\n targetReactIntlId,\n description,\n translations,\n }): IntlMessageInput => ({\n id,\n defaultMessage,\n description,\n targetReactIntlId: targetReactIntlId || undefined,\n translations: translations.reduce(\n (acc, { locale, value }) => Object.assign(acc, { [locale]: value }),\n {} as Record<LocaleValue, string>,\n ),\n }),\n );\n }\n\n // Save privacy center\n if (privacyCenters.length > 0) {\n const privacyCenter = privacyCenters[0];\n result['privacy-center'] = {\n isDisabled: privacyCenter.isDisabled,\n showPrivacyRequestButton: privacyCenter.showPrivacyRequestButton,\n showPolicies: privacyCenter.showPolicies,\n showTrackingTechnologies: privacyCenter.showTrackingTechnologies,\n showCookies: privacyCenter.showCookies,\n showDataFlows: privacyCenter.showDataFlows,\n showConsentManager: privacyCenter.showConsentManager,\n showManageYourPrivacy: privacyCenter.showManageYourPrivacy,\n showMarketingPreferences: privacyCenter.showMarketingPreferences,\n locales: privacyCenter.locales,\n defaultLocale: privacyCenter.defaultLocale,\n preferBrowserDefaultLocale: privacyCenter.preferBrowserDefaultLocale,\n supportEmail: privacyCenter.supportEmail || undefined,\n replyToEmail: privacyCenter.replyToEmail || undefined,\n useNoReplyEmailAddress: privacyCenter.useNoReplyEmailAddress,\n useCustomEmailDomain: privacyCenter.useCustomEmailDomain,\n transformAccessReportJsonToCsv:\n privacyCenter.transformAccessReportJsonToCsv,\n theme: privacyCenter.theme,\n };\n }\n\n // Save business entities\n if (\n businessEntities.length > 0 &&\n resources.includes(TranscendPullResource.BusinessEntities)\n ) {\n result['business-entities'] = businessEntities.map(\n ({\n title,\n description,\n address,\n headquarterCountry,\n headquarterSubDivision,\n dataProtectionOfficerName,\n dataProtectionOfficerEmail,\n attributeValues,\n }): BusinessEntityInput => ({\n title,\n description: description || undefined,\n address: address || undefined,\n headquarterCountry: headquarterCountry || undefined,\n headquarterSubDivision: headquarterSubDivision || undefined,\n dataProtectionOfficerName: dataProtectionOfficerName || undefined,\n dataProtectionOfficerEmail: dataProtectionOfficerEmail || undefined,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save processing activities\n if (\n processingActivities.length > 0 &&\n resources.includes(TranscendPullResource.ProcessingActivities)\n ) {\n result['processing-activities'] = processingActivities.map(\n ({\n title,\n description,\n securityMeasureDetails,\n controllerships,\n storageRegions,\n transferRegions,\n retentionType,\n retentionPeriod,\n dataProtectionImpactAssessmentLink,\n dataProtectionImpactAssessmentStatus,\n attributeValues,\n dataSilos,\n dataSubjects,\n teams,\n owners,\n processingPurposeSubCategories,\n dataSubCategories,\n saaSCategories,\n }): ProcessingActivityInput => ({\n title,\n description,\n securityMeasureDetails: securityMeasureDetails ?? undefined,\n controllerships:\n controllerships.length > 0 ? controllerships : undefined,\n storageRegions:\n storageRegions.length > 0 ? formatRegions(storageRegions) : undefined,\n transferRegions:\n transferRegions.length > 0\n ? formatRegions(transferRegions)\n : undefined,\n retentionType,\n retentionPeriod:\n retentionType === RetentionType.StatedPeriod\n ? retentionPeriod\n : undefined,\n dataProtectionImpactAssessmentLink:\n dataProtectionImpactAssessmentLink ?? undefined,\n dataProtectionImpactAssessmentStatus,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n dataSiloTitles:\n dataSilos.length > 0\n ? dataSilos.map(({ title }) => title)\n : undefined,\n dataSubjectTypes:\n dataSubjects.length > 0\n ? dataSubjects.map(({ type }) => type)\n : undefined,\n teamNames: teams.length > 0 ? teams.map(({ name }) => name) : undefined,\n ownerEmails:\n owners.length > 0 ? owners.map(({ email }) => email) : undefined,\n processingSubPurposes:\n processingPurposeSubCategories.length > 0\n ? processingPurposeSubCategories.map(({ name, purpose }) => ({\n purpose,\n ...(name ? { name } : {}),\n }))\n : undefined,\n dataSubCategories:\n dataSubCategories.length > 0\n ? dataSubCategories.map(({ name, category }) => ({\n category,\n ...(name ? { name } : {}),\n }))\n : undefined,\n saaSCategories:\n saaSCategories.length > 0\n ? saaSCategories.map(({ title }) => title)\n : undefined,\n }),\n );\n }\n\n // Save Actions\n if (actions.length > 0 && resources.includes(TranscendPullResource.Actions)) {\n result.actions = actions.map(\n ({\n type,\n skipSecondaryIfNoFiles,\n skipDownloadableStep,\n requiresReview,\n regionList,\n regionDetectionMethod,\n waitingPeriod,\n }): ActionInput => ({\n type,\n ...(type === RequestAction.Erasure\n ? {\n skipSecondaryIfNoFiles,\n skipDownloadableStep,\n }\n : {}),\n requiresReview,\n waitingPeriod,\n regionDetectionMethod,\n regionList: regionList.length > 0 ? regionList : undefined,\n }),\n );\n }\n\n // Save identifiers\n if (\n identifiers.length > 0 &&\n resources.includes(TranscendPullResource.Identifiers)\n ) {\n result.identifiers = identifiers.map(\n ({\n name,\n type,\n regex,\n selectOptions,\n privacyCenterVisibility,\n isRequiredInForm,\n placeholder,\n displayTitle,\n dataSubjects,\n displayDescription,\n displayOrder,\n isUniqueOnPreferenceStore,\n }): IdentifierInput => ({\n name,\n type,\n regex,\n selectOptions: selectOptions.length > 0 ? selectOptions : undefined,\n privacyCenterVisibility:\n privacyCenterVisibility.length > 0\n ? privacyCenterVisibility\n : undefined,\n isRequiredInForm,\n placeholder: placeholder || undefined,\n dataSubjects:\n dataSubjects.length > 0\n ? dataSubjects.map(({ type }) => type)\n : undefined,\n displayTitle: displayTitle?.defaultMessage,\n displayDescription: displayDescription?.defaultMessage,\n displayOrder,\n isUniqueOnPreferenceStore,\n }),\n );\n }\n\n // Save agents\n if (agents.length > 0 && resources.includes(TranscendPullResource.Agents)) {\n result.agents = agents.map(\n ({\n name,\n agentId,\n description,\n instructions,\n codeInterpreterEnabled,\n retrievalEnabled,\n prompt,\n largeLanguageModel,\n teams,\n owners,\n agentFunctions,\n agentFiles,\n }): AgentInput => ({\n name,\n agentId,\n description: description || undefined,\n instructions,\n codeInterpreterEnabled,\n retrievalEnabled,\n prompt: prompt?.title,\n 'large-language-model': {\n name: largeLanguageModel.name,\n client: largeLanguageModel.client,\n },\n teams:\n teams && teams.length > 0 ? teams.map(({ name }) => name) : undefined,\n owners:\n owners && owners.length > 0\n ? owners.map(({ email }) => email)\n : undefined,\n 'agent-functions':\n agentFunctions && agentFunctions.length > 0\n ? agentFunctions.map(({ name }) => name)\n : undefined,\n 'agent-files':\n agentFiles && agentFiles.length > 0\n ? agentFiles.map(({ name }) => name)\n : undefined,\n }),\n );\n }\n\n // Save action items\n if (\n actionItems.length > 0 &&\n resources.includes(TranscendPullResource.ActionItems)\n ) {\n result['action-items'] = actionItems.map(\n ({\n teams,\n users,\n customerExperienceActionItemIds: [customerExperienceActionItemId],\n dueDate,\n priority,\n resolved,\n collections,\n notes,\n link,\n title,\n type,\n attributeValues,\n }): ActionItemInput => ({\n teams: teams.map(({ name }) => name),\n users: users.map(({ email }) => email),\n dueDate: dueDate || undefined,\n title,\n notes,\n customerExperienceActionItemId,\n collections: collections.map(({ title }) => title),\n link,\n priority: priority || undefined,\n resolved,\n type,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save action item collections\n if (\n actionItemCollections.length > 0 &&\n resources.includes(TranscendPullResource.ActionItemCollections)\n ) {\n result['action-item-collections'] = actionItemCollections.map(\n ({\n title,\n description,\n hidden,\n productLine,\n }): ActionItemCollectionInput => ({\n title,\n description: description || undefined,\n hidden,\n productLine,\n }),\n );\n }\n\n // Save agent functions\n if (\n agentFunctions.length > 0 &&\n resources.includes(TranscendPullResource.AgentFunctions)\n ) {\n result['agent-functions'] = agentFunctions.map(\n ({ name, description, parameters }): AgentFunctionInput => ({\n name,\n description,\n parameters: JSON.stringify(parameters),\n }),\n );\n }\n\n // Save agent files\n if (\n agentFiles.length > 0 &&\n resources.includes(TranscendPullResource.AgentFiles)\n ) {\n result['agent-files'] = agentFiles.map(\n ({ name, description, fileId, size, purpose }): AgentFileInput => ({\n name,\n description,\n fileId,\n size,\n purpose,\n }),\n );\n }\n\n // Save vendors\n if (vendors.length > 0 && resources.includes(TranscendPullResource.Vendors)) {\n result.vendors = vendors.map(\n ({\n title,\n description,\n dataProcessingAgreementLink,\n contactName,\n contactPhone,\n address,\n headquarterCountry,\n headquarterSubDivision,\n websiteUrl,\n businessEntity,\n teams,\n owners,\n attributeValues,\n }): VendorInput => ({\n title,\n description: description || undefined,\n dataProcessingAgreementLink: dataProcessingAgreementLink || undefined,\n contactName: contactName || undefined,\n contactPhone: contactPhone || undefined,\n address: address || undefined,\n headquarterCountry: headquarterCountry || undefined,\n headquarterSubDivision: headquarterSubDivision || undefined,\n websiteUrl: websiteUrl || undefined,\n businessEntity: businessEntity?.title,\n teams:\n teams && teams.length > 0 ? teams.map(({ name }) => name) : undefined,\n owners:\n owners && owners.length > 0\n ? owners.map(({ email }) => email)\n : undefined,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save data categories\n if (\n dataCategories.length > 0 &&\n resources.includes(TranscendPullResource.DataCategories)\n ) {\n result['data-categories'] = dataCategories.map(\n ({\n name,\n category,\n description,\n regex,\n owners,\n teams,\n attributeValues,\n }): DataCategoryInput => ({\n name,\n category,\n description: description || undefined,\n regex: regex || undefined,\n owners:\n owners && owners.length > 0\n ? owners.map(({ email }) => email)\n : undefined,\n teams:\n teams && teams.length > 0 ? teams.map(({ name }) => name) : undefined,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save processing purposes\n if (\n processingPurposes.length > 0 &&\n resources.includes(TranscendPullResource.ProcessingPurposes)\n ) {\n result['processing-purposes'] = processingPurposes.map(\n ({\n name,\n purpose,\n description,\n owners,\n teams,\n attributeValues,\n }): ProcessingPurposeInput => ({\n name,\n purpose,\n description: description || undefined,\n owners:\n owners && owners.length > 0\n ? owners.map(({ email }) => email)\n : undefined,\n teams:\n teams && teams.length > 0 ? teams.map(({ name }) => name) : undefined,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save data flows\n if (\n dataFlows.length > 0 &&\n resources.includes(TranscendPullResource.DataFlows)\n ) {\n result['data-flows'] = dataFlows.map(\n ({\n value,\n type,\n description,\n trackingType,\n service,\n status,\n owners,\n teams,\n attributeValues,\n }): DataFlowInput => ({\n value,\n type,\n description: description || undefined,\n trackingPurposes: trackingType,\n status,\n service: service?.integrationName,\n owners: owners.map(({ email }) => email),\n teams: teams.map(({ name }) => name),\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save cookies\n if (cookies.length > 0 && resources.includes(TranscendPullResource.Cookies)) {\n result.cookies = cookies.map(\n ({\n name,\n isRegex,\n description,\n trackingPurposes,\n service,\n status,\n owners,\n teams,\n attributeValues,\n }): CookieInput => ({\n name,\n isRegex,\n description: description || undefined,\n trackingPurposes,\n status,\n service: service?.integrationName,\n owners: owners.map(({ email }) => email),\n teams: teams.map(({ name }) => name),\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save attributes\n if (\n attributes.length > 0 &&\n resources.includes(TranscendPullResource.Attributes)\n ) {\n result.attributes = attributes.map(\n ({\n description,\n name,\n type,\n values,\n enabledOn = [],\n }): AttributeInput => ({\n description: description || undefined,\n resources: enabledOn,\n name,\n type,\n values: values.map(({ name, color, description }) => ({\n name,\n color: color || undefined,\n description,\n })),\n }),\n );\n }\n\n // save purposes\n if (purposes.length > 0) {\n result.purposes = purposes.map(\n ({\n name,\n description,\n trackingType,\n defaultConsent,\n configurable,\n showInConsentManager,\n isActive,\n displayOrder,\n optOutSignals,\n authLevel,\n topics,\n showInPrivacyCenter,\n title,\n }): ConsentPurpose => ({\n name,\n title,\n description: description || undefined,\n trackingType,\n 'default-consent': defaultConsent,\n configurable,\n 'show-in-consent-manager': showInConsentManager,\n 'show-in-privacy-center': showInPrivacyCenter,\n 'is-active': isActive,\n 'display-order': displayOrder,\n 'opt-out-signals': optOutSignals.length > 0 ? optOutSignals : undefined,\n 'auth-level': authLevel || undefined,\n 'preference-topics': topics.map(\n ({\n title,\n type,\n displayDescription,\n defaultConfiguration,\n showInPrivacyCenter,\n preferenceOptionValues,\n }) => ({\n title: title.defaultMessage,\n type,\n description: displayDescription.defaultMessage,\n 'default-configuration': defaultConfiguration,\n 'show-in-privacy-center': showInPrivacyCenter,\n ...(preferenceOptionValues.length > 0\n ? {\n options: preferenceOptionValues.map(({ title, slug }) => ({\n title: title.defaultMessage,\n slug,\n })),\n }\n : {}),\n }),\n ),\n }),\n );\n }\n\n // save email templates\n if (\n dataSiloIds.length === 0 &&\n templates.length > 0 &&\n resources.includes(TranscendPullResource.Templates)\n ) {\n result.templates = templates.map(({ title }) => ({ title }));\n }\n\n // Save enrichers\n if (\n enrichers.length > 0 &&\n resources.includes(TranscendPullResource.Enrichers)\n ) {\n result.enrichers = enrichers.map(\n ({\n title,\n url,\n type,\n inputIdentifier,\n identifiers,\n actions,\n testRegex,\n dataSubjects,\n expirationDuration,\n lookerQueryTitle,\n transitionRequestStatus,\n phoneNumbers,\n regionList,\n }): EnricherInput => ({\n title,\n url: url || undefined,\n type,\n 'input-identifier': inputIdentifier?.name,\n 'output-identifiers': identifiers.map(({ name }) => name),\n 'privacy-actions':\n Object.values(RequestAction).length === actions.length\n ? undefined\n : actions,\n testRegex: testRegex || undefined,\n lookerQueryTitle: lookerQueryTitle || undefined,\n expirationDuration: parseInt(expirationDuration, 10),\n transitionRequestStatus: transitionRequestStatus || undefined,\n phoneNumbers:\n phoneNumbers && phoneNumbers.length > 0 ? phoneNumbers : undefined,\n regionList:\n regionList && regionList.length > 0 ? regionList : undefined,\n 'data-subjects': dataSubjects.map(({ type }) => type),\n }),\n );\n }\n\n // Save data silos\n if (\n dataSilos.length > 0 &&\n resources.includes(TranscendPullResource.DataSilos)\n ) {\n const indexedDataSubjects = keyBy(dataSubjects, 'type');\n result['data-silos'] = dataSilos.map(\n ([\n {\n title,\n description,\n url,\n type,\n outerType,\n apiKeys,\n notifyEmailAddress,\n identifiers,\n dependentDataSilos,\n owners,\n country,\n countrySubDivision,\n teams,\n subjectBlocklist,\n isLive,\n promptAVendorEmailSendFrequency,\n promptAVendorEmailSendType,\n promptAVendorEmailIncludeIdentifiersAttachment,\n promptAVendorEmailCompletionLinkType,\n manualWorkRetryFrequency,\n catalog,\n attributeValues,\n discoveredBy,\n businessEntities,\n },\n dataPoints,\n ]): DataSiloInput => ({\n title,\n description,\n integrationName: type,\n 'outer-type': outerType || undefined,\n url: url || undefined,\n 'api-key-title': apiKeys[0]?.title,\n 'identity-keys': identifiers\n .filter(({ isConnected }) => isConnected)\n .map(({ name }) => name),\n ...(dependentDataSilos.length > 0\n ? {\n 'deletion-dependencies': dependentDataSilos.map(\n ({ title }) => title,\n ),\n }\n : {}),\n ...(owners.length > 0\n ? { owners: owners.map(({ email }) => email) }\n : {}),\n ...(teams.length > 0 ? { teams: teams.map(({ name }) => name) } : {}),\n ...(discoveredBy.length > 0\n ? { discoveredBy: discoveredBy.map(({ title }) => title) }\n : {}),\n ...(businessEntities.length > 0\n ? {\n businessEntities: businessEntities.map(({ title }) => title),\n }\n : {}),\n country: country || undefined,\n countrySubDivision: countrySubDivision || undefined,\n disabled: !isLive,\n 'data-subjects':\n subjectBlocklist.length > 0\n ? convertToDataSubjectAllowlist(\n subjectBlocklist.map(({ type }) => type),\n indexedDataSubjects,\n )\n : undefined,\n ...(catalog.hasAvcFunctionality\n ? {\n 'email-settings': {\n 'notify-email-address': notifyEmailAddress || undefined,\n 'send-frequency': promptAVendorEmailSendFrequency,\n 'send-type': promptAVendorEmailSendType,\n 'include-identifiers-attachment':\n promptAVendorEmailIncludeIdentifiersAttachment,\n 'completion-link-type': promptAVendorEmailCompletionLinkType,\n 'manual-work-retry-frequency': manualWorkRetryFrequency,\n },\n }\n : {}),\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n\n datapoints: dataPoints\n .map(\n (dataPoint): DatapointInput => ({\n key: dataPoint.name,\n title: dataPoint.title?.defaultMessage,\n description: dataPoint.description?.defaultMessage,\n owners: dataPoint.owners.map(({ email }) => email),\n teams: dataPoint.teams.map(({ name }) => name),\n ...(dataPoint.path.length > 0 ? { path: dataPoint.path } : {}),\n ...(dataPoint.dataCollection?.title\n ? {\n 'data-collection-tag':\n dataPoint.dataCollection.title.defaultMessage,\n }\n : {}),\n ...(dataPoint.dbIntegrationQueries.length > 0\n ? {\n 'privacy-action-queries': mapValues(\n keyBy(dataPoint.dbIntegrationQueries, 'requestType'),\n (databaseIntegrationQuery) =>\n databaseIntegrationQuery.suggestedQuery ||\n databaseIntegrationQuery.query ||\n undefined,\n ),\n }\n : {}),\n ...(dataPoint.subDataPoints.length > 0\n ? {\n fields: dataPoint.subDataPoints\n .map(\n (field): FieldInput => ({\n key: field.name,\n description: field.description,\n purposes: field.purposes,\n categories: field.categories,\n ...(includeGuessedCategories &&\n field.pendingCategoryGuesses\n ? {\n 'guessed-categories':\n field.pendingCategoryGuesses\n .filter(\n (guess) => guess.status === 'PENDING',\n )\n .map((guess) => ({\n category: {\n name: guess.category.name,\n category: guess.category.category,\n },\n status: guess.status,\n confidence: guess.confidence,\n classifierVersion:\n guess.classifierVersion || undefined,\n })),\n }\n : {}),\n 'access-request-visibility-enabled':\n field.accessRequestVisibilityEnabled,\n 'erasure-request-redaction-enabled':\n field.erasureRequestRedactionEnabled,\n attributes:\n field.attributeValues !== undefined &&\n field.attributeValues.length > 0\n ? formatAttributeValues(field.attributeValues)\n : undefined,\n }),\n )\n .sort((a, b) => a.key.localeCompare(b.key)),\n }\n : {}),\n 'privacy-actions': dataPoint.actionSettings\n .filter(({ active }) => active)\n .map(({ type }) => type),\n }),\n )\n .sort((a, b) =>\n [...(a.path ?? []), a.key]\n .join('.')\n .localeCompare([...(b.path ?? []), b.key].join('.')),\n ),\n }),\n );\n }\n return result;\n}\n/* eslint-enable max-lines */\n","import { GraphQLClient } from 'graphql-request';\nimport { REPORT_PROMPT_RUN } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n QueueStatus,\n ChatCompletionRole,\n PromptRunProductArea,\n LargeLanguageModelClient,\n} from '@transcend-io/privacy-types';\n\nexport interface ReportPromptRunInput {\n /** Name of run */\n name: string;\n /** The related product area being uploaded to */\n productArea: PromptRunProductArea;\n /** Messages reported on */\n promptRunMessages: {\n /** Message reported */\n content: string;\n /** Role of message */\n role: ChatCompletionRole;\n /** Template used if created from prompt */\n template?: string;\n }[];\n /** ID of the Transcend prompt being reported */\n promptId?: string;\n /** Title of the prompt being reported on */\n promptTitle?: string;\n /** Error message (if one exists) */\n error?: string;\n /** The status of the run */\n status?: QueueStatus;\n /** Employee email that is executing the request */\n runByEmployeeEmail?: string;\n /** Duration of time that it took to execute the prompt */\n duration?: number;\n /** Temperature used when running prompt */\n temperature?: number;\n /** TopP parameter used when running prompt */\n topP?: number;\n /** Max tokens ot sample parameter used when running prompt */\n maxTokensToSample?: number;\n /** The ID of the prompt group being reported */\n promptGroupId?: string;\n /** The title of the prompt group being reported */\n promptGroupTitle?: string;\n /** The LLM Id being reported on */\n largeLanguageModelId?: string;\n /** The name of the large language model being reported on */\n largeLanguageModelName?: string;\n /** The name of the large language model client reported on */\n largeLanguageModelClient?: LargeLanguageModelClient;\n /** ID of the application calling pathfinder */\n applicationId?: string;\n /** Name of the application calling pathfinder */\n applicationName?: string;\n /** Name of the code package calling pathfinder */\n codePackageName?: string;\n /** Name of the repository calling pathfinder */\n repositoryName?: string;\n /** ID of the pathfinder applying policies */\n pathfinderId?: string;\n /** Name of the pathfinder applying policies */\n pathfinderName?: string;\n /** Core identifier of the application user being reported on */\n applicationUserCoreIdentifier?: string;\n /** Name of the application user being reported on */\n applicationUserName?: string;\n}\n\n/**\n * Record a new prompt run\n *\n * @param client - GraphQL client\n * @param input - Prompt input\n * @returns Prompt ID\n */\nexport async function reportPromptRun(\n client: GraphQLClient,\n input: ReportPromptRunInput,\n): Promise<string> {\n const {\n reportPromptRun: { promptRun },\n } = await makeGraphQLRequest<{\n /** reportPromptRun mutation */\n reportPromptRun: {\n /** Prompt */\n promptRun: {\n /** ID */\n id: string;\n };\n };\n }>(client, REPORT_PROMPT_RUN, {\n input: {\n ...input,\n promptRunMessages: input.promptRunMessages.map(\n ({ content, ...rest }) => ({\n ...rest,\n message: content,\n }),\n ),\n },\n });\n return promptRun.id;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { RETRY_REQUEST_ENRICHER } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\n/**\n * Retry a request enricher\n *\n * @param client - GraphQL client\n * @param id - The ID of the request enricher to restart\n */\nexport async function retryRequestEnricher(\n client: GraphQLClient,\n id: string,\n): Promise<void> {\n await makeGraphQLRequest(client, RETRY_REQUEST_ENRICHER, {\n requestEnricherId: id,\n });\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { SET_RESOURCE_ATTRIBUTES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { AttributeSupportedResourceType } from '@transcend-io/privacy-types';\n\ninterface SetResourceAttributesInput {\n /** ID of resource */\n resourceId: string;\n /** Type of resource */\n resourceType: AttributeSupportedResourceType;\n /** Attribute key ID */\n attributeKeyId: string;\n /** Attribute values by ID */\n attributeValueIds?: string[];\n /** Attribute values by name */\n attributeValueNames?: string[];\n}\n\n/**\n * Set attribute values on a particular resource\n *\n * @param client - GraphQL client\n * @param input - Input\n */\nexport async function setResourceAttributes(\n client: GraphQLClient,\n input: SetResourceAttributesInput,\n): Promise<void> {\n await makeGraphQLRequest(client, SET_RESOURCE_ATTRIBUTES, {\n input,\n });\n}\n","import { ActionInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { UPDATE_ACTION } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { difference } from 'lodash-es';\nimport {\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\n\nconst ALL_COUNTRIES_AND_SUBDIVISIONS = [\n ...Object.values(IsoCountryCode),\n ...Object.values(IsoCountrySubdivisionCode),\n];\n\n/**\n * Sync the consent manager\n *\n * @param client - GraphQL client\n * @param options - Options\n */\nexport async function syncAction(\n client: GraphQLClient,\n {\n action,\n actionId,\n skipPublish = false,\n }: {\n /** Action update input */\n action: ActionInput;\n /** Existing action Id */\n actionId: string;\n /** When true, skip publishing to privacy center */\n skipPublish?: boolean;\n },\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_ACTION, {\n input: {\n id: actionId,\n skipSecondaryIfNoFiles: action.skipSecondaryIfNoFiles,\n skipDownloadableStep: action.skipDownloadableStep,\n requiresReview: action.requiresReview,\n waitingPeriod: action.waitingPeriod,\n skipPublish,\n regionList: action.regionBlockList\n ? difference(ALL_COUNTRIES_AND_SUBDIVISIONS, action.regionBlockList)\n : action.regionList,\n regionDetectionMethod: action.regionDetectionMethod,\n },\n });\n}\n","import { ActionItemCollectionInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport {\n UPDATE_ACTION_ITEM_COLLECTION,\n CREATE_ACTION_ITEM_COLLECTION,\n} from './gqls';\nimport { logger } from '../../logger';\nimport { keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport colors from 'colors';\nimport {\n ActionItemCollection,\n fetchAllActionItemCollections,\n} from './fetchAllActionItemCollections';\n\n/**\n * Input to create a new action item collection\n *\n * @param client - GraphQL client\n * @param actionItemCollection - Input\n * @returns Created action item collection\n */\nexport async function createActionItemCollection(\n client: GraphQLClient,\n actionItemCollection: ActionItemCollectionInput,\n): Promise<Pick<ActionItemCollection, 'id' | 'title'>> {\n const input = {\n title: actionItemCollection.title,\n description: actionItemCollection.description || '',\n hidden: actionItemCollection.hidden || false,\n productLine: actionItemCollection.productLine,\n };\n\n const { createActionItemCollection } = await makeGraphQLRequest<{\n /** Create actionItemCollection mutation */\n createActionItemCollection: {\n /** Created actionItemCollection */\n created: ActionItemCollection;\n };\n }>(client, CREATE_ACTION_ITEM_COLLECTION, {\n input,\n });\n return createActionItemCollection.created;\n}\n\n/**\n * Input to update actionItem collection\n *\n * @param client - GraphQL client\n * @param input - Input to update\n * @param actionItemCollectionId - ID of action item collection to update\n */\nexport async function updateActionItemCollection(\n client: GraphQLClient,\n input: ActionItemCollectionInput,\n actionItemCollectionId: string,\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_ACTION_ITEM_COLLECTION, {\n input: {\n id: actionItemCollectionId,\n title: input.title,\n description: input.description,\n hidden: input.hidden,\n productLine: input.productLine,\n },\n });\n}\n\n/**\n * Sync the action item collections\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncActionItemCollections(\n client: GraphQLClient,\n inputs: ActionItemCollectionInput[],\n): Promise<boolean> {\n let encounteredError = false;\n // Fetch existing\n logger.info(\n colors.magenta(`Syncing \"${inputs.length}\" action item collections...`),\n );\n\n // Fetch existing\n const existingActionItemCollections = await fetchAllActionItemCollections(\n client,\n );\n\n // Look up by title\n const collectionByTitle: { [k in string]: ActionItemCollection } = keyBy(\n existingActionItemCollections,\n 'title',\n );\n\n // Create new actionItems\n const newCollections = inputs.filter(\n (input) => !collectionByTitle[input.title],\n );\n\n // Create new actionItem collections\n await mapSeries(newCollections, async (input) => {\n try {\n await createActionItemCollection(client, input);\n logger.info(\n colors.green(\n `Successfully created action item collection \"${input.title}\"!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to create action item collection \"${input.title}\"! - ${err.message}`,\n ),\n );\n }\n });\n\n // Update all actionItems\n const actionItemsToUpdate = inputs\n .map((input) => [input, collectionByTitle[input.title]?.id])\n .filter((x): x is [ActionItemCollectionInput, string] => !!x[1]);\n await mapSeries(actionItemsToUpdate, async ([input, actionItemId]) => {\n try {\n await updateActionItemCollection(client, input, actionItemId);\n logger.info(\n colors.green(\n `Successfully synced action item collection \"${input.title}\"!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync action item collection \"${input.title}\"! - ${err.message}`,\n ),\n );\n }\n });\n\n return !encounteredError;\n}\n","import { ActionItemInput } from '../../codecs';\nimport { uniq, keyBy, chunk } from 'lodash-es';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport { UPDATE_ACTION_ITEMS, CREATE_ACTION_ITEMS } from './gqls';\nimport { logger } from '../../logger';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport colors from 'colors';\nimport { fetchAllActionItems, ActionItem } from './fetchAllActionItems';\nimport {\n ActionItemCollection,\n fetchAllActionItemCollections,\n} from './fetchAllActionItemCollections';\nimport { Attribute, fetchAllAttributes } from './fetchAllAttributes';\n\n/**\n * Input to create a new actionItem\n *\n * @param client - GraphQL client\n * @param actionItems - Action item inputs\n * @param actionItemCollectionByTitle - Action item collections indexed by title\n * @param attributeKeysByName - Lookup attribute by name\n */\nexport async function createActionItems(\n client: GraphQLClient,\n actionItems: ActionItemInput[],\n actionItemCollectionByTitle: { [k in string]: ActionItemCollection },\n // TODO: https://transcend.height.app/T-38961 - insert attributes\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n attributeKeysByName: { [k in string]: Attribute } = {},\n): Promise<void> {\n // TODO: https://transcend.height.app/T-38961 - insert attributes\n // const getAttribute = (key: string): string => {\n // const existing = attributeKeysByName[key];\n // if (!existing) {\n // throw new Error(`Attribute key \"${key}\" does not exist!`);\n // }\n // return existing.id;\n // };\n const chunked = chunk(actionItems, 100);\n await mapSeries(chunked, async (chunkToUpload) => {\n await makeGraphQLRequest(client, CREATE_ACTION_ITEMS, {\n input: chunkToUpload.map((actionItem) => ({\n title: actionItem.title,\n type: actionItem.type,\n priorityOverride: actionItem.priority,\n dueDate: actionItem.dueDate,\n customerExperienceActionItemId:\n actionItem.customerExperienceActionItemId,\n resolved: actionItem.resolved,\n notes: actionItem.notes,\n link: actionItem.link,\n assigneesUserEmails: actionItem.users,\n assigneesTeamNames: actionItem.teams,\n ...(actionItem.attributes\n ? {\n // TODO: https://transcend.height.app/T-38961 - insert attributes\n // attributes: actionItem.attributes.map(({ key, values }) => ({\n // attributeKeyId: getAttribute(key),\n // attributeValueNames: values,\n // })),\n }\n : {}),\n collectionIds: actionItem.collections.map(\n (collectionTitle) => actionItemCollectionByTitle[collectionTitle].id,\n ),\n })),\n });\n });\n}\n\n/**\n * Input to update actionItems\n *\n * @param client - GraphQL client\n * @param input - Input to update\n * @param actionItemId - ID of action item to update\n * @param attributeKeysByName - Attribute keys by name\n */\nexport async function updateActionItem(\n client: GraphQLClient,\n input: ActionItemInput,\n actionItemId: string,\n attributeKeysByName: {\n [k in string]: Attribute;\n } = {},\n): Promise<void> {\n const getAttribute = (key: string): string => {\n const existing = attributeKeysByName[key];\n if (!existing) {\n throw new Error(`Attribute key \"${key}\" does not exist!`);\n }\n return existing.id;\n };\n await makeGraphQLRequest(client, UPDATE_ACTION_ITEMS, {\n input: {\n ids: [actionItemId],\n title: input.title,\n priorityOverride: input.priority,\n dueDate: input.dueDate,\n resolved: input.resolved,\n customerExperienceActionItemId: input.customerExperienceActionItemId,\n notes: input.notes,\n link: input.link,\n assigneesUserEmails: input.users,\n assigneesTeamNames: input.teams,\n ...(input.attributes\n ? {\n attributes: input.attributes.map(({ key, values }) => ({\n attributeKeyId: getAttribute(key),\n attributeValueNames: values,\n })),\n }\n : {}),\n },\n });\n}\n\n/**\n * Convert action item to a unique key\n *\n * @param actionItem - action item\n * @returns Unique key\n */\nfunction actionItemToUniqueCode({\n title,\n collections,\n}: Pick<ActionItem, 'title' | 'collections'>): string {\n return `${title}-${collections\n .map((c) => c.title)\n .sort()\n .join('-')}`;\n}\n\n/**\n * Convert action item to a unique key\n *\n * @param actionItem - action item\n * @returns Unique key\n */\nfunction actionItemInputToUniqueCode({\n title,\n collections,\n}: Pick<ActionItemInput, 'title' | 'collections'>): string {\n return `${title}-${collections.sort().join('-')}`;\n}\n\n/**\n * Sync the action item\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncActionItems(\n client: GraphQLClient,\n inputs: ActionItemInput[],\n): Promise<boolean> {\n let encounteredError = false;\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${inputs.length}\" actionItems...`));\n\n // Determine if attributes are syncing\n const hasAttributes = inputs.some(\n (input) => input.attributes && input.attributes.length > 0,\n );\n\n // Fetch existing\n const [existingActionItems, existingActionItemCollections, attributeKeys] =\n await Promise.all([\n fetchAllActionItems(client),\n fetchAllActionItemCollections(client),\n hasAttributes ? fetchAllAttributes(client) : [],\n ]);\n\n // Look up by title\n const actionItemCollectionByTitle: { [k in string]: ActionItemCollection } =\n keyBy(existingActionItemCollections, 'title');\n const actionItemByTitle: { [k in string]: ActionItem } = keyBy(\n existingActionItems,\n actionItemToUniqueCode,\n );\n const attributeKeysByName = keyBy(attributeKeys, 'name');\n const actionItemByCxId: { [k in string]: ActionItem } = keyBy(\n existingActionItems.filter((x) => !!x.customerExperienceActionItemIds),\n ({ customerExperienceActionItemIds }) => customerExperienceActionItemIds[0],\n );\n\n // Ensure all collections exist\n const missingCollections = uniq(\n inputs.map((input) => input.collections).flat(),\n ).filter((collectionTitle) => !actionItemCollectionByTitle[collectionTitle]);\n if (missingCollections.length > 0) {\n logger.info(\n colors.red(\n `Missing action item collections: \"${missingCollections.join(\n '\", \"',\n )}\" - please create them first!`,\n ),\n );\n return false;\n }\n\n // Create new actionItems\n const newActionItems = inputs.filter(\n (input) =>\n !actionItemByTitle[actionItemInputToUniqueCode(input)] &&\n !actionItemByCxId[input.customerExperienceActionItemId!],\n );\n\n // Create new actionItems\n if (newActionItems.length > 0) {\n try {\n logger.info(\n colors.magenta(`Creating \"${newActionItems.length}\" actionItems...`),\n );\n await createActionItems(\n client,\n newActionItems,\n actionItemCollectionByTitle,\n attributeKeysByName,\n );\n logger.info(\n colors.green(\n `Successfully created \"${newActionItems.length}\" actionItems!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to create action items! - ${err.message}`),\n );\n }\n }\n\n // Update all actionItems\n const actionItemsToUpdate = inputs\n .map((input) => [\n input,\n actionItemByTitle[actionItemInputToUniqueCode(input)]?.id ||\n actionItemByCxId[input.customerExperienceActionItemId!]?.id,\n ])\n .filter((x): x is [ActionItemInput, string] => !!x[1]);\n await mapSeries(actionItemsToUpdate, async ([input, actionItemId]) => {\n try {\n await updateActionItem(client, input, actionItemId, attributeKeysByName);\n logger.info(\n colors.green(`Successfully synced action item \"${input.title}\"!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync action item \"${input.title}\"! - ${err.message}`,\n ),\n );\n }\n });\n\n return !encounteredError;\n}\n","import { AgentFileInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport { UPDATE_AGENT_FILES, CREATE_AGENT_FILE } from './gqls';\nimport { logger } from '../../logger';\nimport { keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport colors from 'colors';\nimport { fetchAllAgentFiles, AgentFile } from './fetchAllAgentFiles';\n\n/**\n * Input to create a new agent file\n *\n * @param client - GraphQL client\n * @param agentFile - Input\n * @returns Created agent file\n */\nexport async function createAgentFile(\n client: GraphQLClient,\n agentFile: AgentFileInput,\n): Promise<Pick<AgentFile, 'id' | 'name' | 'fileId'>> {\n const input = {\n name: agentFile.name,\n description: agentFile.description,\n fileId: agentFile.fileId,\n size: agentFile.size,\n purpose: agentFile.purpose,\n fileUploadedAt: new Date(),\n agentIds: [],\n // TODO: https://transcend.height.app/T-31994 - sync agents\n };\n\n const { createAgentFile } = await makeGraphQLRequest<{\n /** Create agent file mutation */\n createAgentFile: {\n /** Created agent file */\n agentFile: AgentFile;\n };\n }>(client, CREATE_AGENT_FILE, {\n input,\n });\n return createAgentFile.agentFile;\n}\n\n/**\n * Input to update agent files\n *\n * @param client - GraphQL client\n * @param agentFileIdPairs - [AgentFileInput, agentFileId] list\n */\nexport async function updateAgentFiles(\n client: GraphQLClient,\n agentFileIdPairs: [AgentFileInput, string][],\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_AGENT_FILES, {\n input: {\n agentFiles: agentFileIdPairs.map(([agentFile, id]) => ({\n id,\n name: agentFile.name,\n description: agentFile.description,\n fileId: agentFile.fileId,\n size: agentFile.size,\n purpose: agentFile.purpose,\n })),\n },\n });\n}\n\n/**\n * Sync the data inventory agent files\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncAgentFiles(\n client: GraphQLClient,\n inputs: AgentFileInput[],\n): Promise<boolean> {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${inputs.length}\" agent files...`));\n\n let encounteredError = false;\n\n // Fetch existing\n const existingAgentFiles = await fetchAllAgentFiles(client);\n\n // Look up by name\n const agentFileByName: {\n [k in string]: Pick<AgentFile, 'id' | 'name' | 'fileId'>;\n } = keyBy(existingAgentFiles, 'name');\n\n // Create new agent files\n const newAgentFiles = inputs.filter((input) => !agentFileByName[input.name]);\n\n // Create new agent files\n await mapSeries(newAgentFiles, async (agentFile) => {\n try {\n const newAgentFile = await createAgentFile(client, agentFile);\n agentFileByName[newAgentFile.name] = newAgentFile;\n logger.info(\n colors.green(`Successfully synced agent file \"${agentFile.name}\"!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync agent file \"${agentFile.name}\"! - ${err.message}`,\n ),\n );\n }\n });\n\n // Update all agent files\n try {\n logger.info(colors.magenta(`Updating \"${inputs.length}\" agent files!`));\n await updateAgentFiles(\n client,\n inputs.map((input) => [input, agentFileByName[input.name].id]),\n );\n logger.info(\n colors.green(`Successfully synced \"${inputs.length}\" agent files!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync \"${inputs.length}\" agent files! - ${err.message}`,\n ),\n );\n }\n\n return !encounteredError;\n}\n","import { AgentFunctionInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport { UPDATE_AGENT_FUNCTIONS, CREATE_AGENT_FUNCTION } from './gqls';\nimport { logger } from '../../logger';\nimport { keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport colors from 'colors';\nimport {\n fetchAllAgentFunctions,\n AgentFunction,\n} from './fetchAllAgentFunctions';\n\n/**\n * Input to create a new agent function\n *\n * @param client - GraphQL client\n * @param agentFunction - Input\n * @returns Created agent function\n */\nexport async function createAgentFunction(\n client: GraphQLClient,\n agentFunction: AgentFunctionInput,\n): Promise<Pick<AgentFunction, 'id' | 'name'>> {\n const input = {\n name: agentFunction.name,\n description: agentFunction.description,\n parameters: agentFunction.parameters,\n agentIds: [],\n // TODO: https://transcend.height.app/T-31994 - sync agents\n };\n\n const { createAgentFunction } = await makeGraphQLRequest<{\n /** Create agent function mutation */\n createAgentFunction: {\n /** Created agent function */\n agentFunction: AgentFunction;\n };\n }>(client, CREATE_AGENT_FUNCTION, {\n input,\n });\n return createAgentFunction.agentFunction;\n}\n\n/**\n * Input to update agent functions\n *\n * @param client - GraphQL client\n * @param agentFunctionIdPairs - [AgentFunctionInput, agentFunctionId] list\n */\nexport async function updateAgentFunctions(\n client: GraphQLClient,\n agentFunctionIdPairs: [AgentFunctionInput, string][],\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_AGENT_FUNCTIONS, {\n input: {\n agentFunctions: agentFunctionIdPairs.map(([agentFunction, id]) => ({\n id,\n name: agentFunction.name,\n description: agentFunction.description,\n parameters: agentFunction.parameters,\n })),\n },\n });\n}\n\n/**\n * Sync the data inventory agent functions\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncAgentFunctions(\n client: GraphQLClient,\n inputs: AgentFunctionInput[],\n): Promise<boolean> {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${inputs.length}\" agent functions...`));\n\n let encounteredError = false;\n\n // Fetch existing\n const existingAgentFunctions = await fetchAllAgentFunctions(client);\n\n // Look up by name\n const agentFunctionByName: {\n [k in string]: Pick<AgentFunction, 'id' | 'name'>;\n } = keyBy(existingAgentFunctions, 'name');\n\n // Create new agent functions\n const newAgentFunctions = inputs.filter(\n (input) => !agentFunctionByName[input.name],\n );\n\n // Create new agent functions\n await mapSeries(newAgentFunctions, async (agentFunction) => {\n try {\n const newAgentFunction = await createAgentFunction(client, agentFunction);\n agentFunctionByName[newAgentFunction.name] = newAgentFunction;\n logger.info(\n colors.green(\n `Successfully synced agent function \"${agentFunction.name}\"!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync agent function \"${agentFunction.name}\"! - ${err.message}`,\n ),\n );\n }\n });\n\n // Update all agent functions\n try {\n logger.info(colors.magenta(`Updating \"${inputs.length}\" agent functions!`));\n await updateAgentFunctions(\n client,\n inputs.map((input) => [input, agentFunctionByName[input.name].id]),\n );\n logger.info(\n colors.green(`Successfully synced \"${inputs.length}\" agent functions!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync \"${inputs.length}\" agent functions! - ${err.message}`,\n ),\n );\n }\n\n return !encounteredError;\n}\n","import { AgentInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport { UPDATE_AGENTS, CREATE_AGENT } from './gqls';\nimport { logger } from '../../logger';\nimport { keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport colors from 'colors';\nimport { fetchAllAgents, Agent } from './fetchAllAgents';\n\n/**\n * Input to create a new agent\n *\n * @param client - GraphQL client\n * @param agent - Input\n * @returns Created agent\n */\nexport async function createAgent(\n client: GraphQLClient,\n agent: AgentInput,\n): Promise<Pick<Agent, 'id' | 'name' | 'agentId'>> {\n const input = {\n name: agent.name,\n description: agent.description,\n codeInterpreterEnabled: agent.codeInterpreterEnabled,\n retrievalEnabled: agent.retrievalEnabled,\n promptTitle: agent.prompt,\n largeLanguageModelName: agent['large-language-model'].name,\n largeLanguageModelClient: agent['large-language-model'].client,\n // TODO: https://transcend.height.app/T-32760 - agentFunction, agentFile\n // TODO: https://transcend.height.app/T-31994 - owners and teams\n };\n\n const { createAgent } = await makeGraphQLRequest<{\n /** Create agent mutation */\n createAgent: {\n /** Created agent */\n agent: Agent;\n };\n }>(client, CREATE_AGENT, {\n input,\n });\n return createAgent.agent;\n}\n\n/**\n * Input to update agents\n *\n * @param client - GraphQL client\n * @param agentIdParis - [AgentInput, agentId] list\n */\nexport async function updateAgents(\n client: GraphQLClient,\n agentIdParis: [AgentInput, string][],\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_AGENTS, {\n input: {\n agents: agentIdParis.map(([agent, id]) => ({\n id,\n name: agent.name,\n description: agent.description,\n codeInterpreterEnabled: agent.codeInterpreterEnabled,\n retrievalEnabled: agent.retrievalEnabled,\n // TODO: https://transcend.height.app/T-31995 - prompt, largeLanguageModel, agentFunction, agentFile\n })),\n },\n });\n}\n\n/**\n * Sync the data inventory agents\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncAgents(\n client: GraphQLClient,\n inputs: AgentInput[],\n): Promise<boolean> {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${inputs.length}\" agents...`));\n\n let encounteredError = false;\n\n // Fetch existing\n const existingAgents = await fetchAllAgents(client);\n\n // Look up by name\n const agentByName: {\n [k in string]: Pick<Agent, 'id' | 'name' | 'agentId'>;\n } = keyBy(existingAgents, 'name');\n\n // Create new agents\n const newAgents = inputs.filter((input) => !agentByName[input.name]);\n\n // Create new agents\n await mapSeries(newAgents, async (agent) => {\n try {\n const newAgent = await createAgent(client, agent);\n agentByName[newAgent.name] = newAgent;\n logger.info(colors.green(`Successfully synced agent \"${agent.name}\"!`));\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to sync agent \"${agent.name}\"! - ${err.message}`),\n );\n }\n });\n\n // Update all agents\n try {\n logger.info(colors.magenta(`Updating \"${inputs.length}\" agents!`));\n await updateAgents(\n client,\n inputs.map((input) => [input, agentByName[input.name].id]),\n );\n logger.info(colors.green(`Successfully synced \"${inputs.length}\" agents!`));\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to sync \"${inputs.length}\" agents ! - ${err.message}`),\n );\n }\n\n return !encounteredError;\n}\n","import { AttributeInput } from '../../codecs';\nimport colors from 'colors';\nimport { keyBy, difference, groupBy } from 'lodash-es';\nimport { GraphQLClient } from 'graphql-request';\nimport {\n CREATE_ATTRIBUTE,\n CREATE_ATTRIBUTE_VALUES,\n DELETE_ATTRIBUTE_VALUE,\n UPDATE_ATTRIBUTE,\n UPDATE_ATTRIBUTE_VALUES,\n} from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { Attribute } from './fetchAllAttributes';\nimport { map } from '../bluebird';\nimport { logger } from '../../logger';\n\n/**\n * Sync attribute\n *\n * @param client - GraphQL client\n * @param attribute - The attribute input\n * @param options - Options\n */\nexport async function syncAttribute(\n client: GraphQLClient,\n attribute: AttributeInput,\n {\n existingAttribute,\n deleteExtraAttributeValues,\n }: {\n /** The existing attribute configuration if it exists */\n existingAttribute?: Attribute;\n /** When true, delete extra attributes not specified in the list of values */\n deleteExtraAttributeValues?: boolean;\n },\n): Promise<void> {\n // attribute key input\n const input = {\n name: attribute.name,\n enabledOn: attribute.resources,\n };\n\n // create or update attribute key\n let attributeKeyId: string;\n if (!existingAttribute) {\n const {\n createAttributeKey: { attributeKey },\n } = await makeGraphQLRequest<{\n /** Create attribute key response */\n createAttributeKey: {\n /** Attribute key */\n attributeKey: {\n /** ID */\n id: string;\n };\n };\n }>(client, CREATE_ATTRIBUTE, {\n type: attribute.type,\n description: attribute.description,\n ...input,\n });\n attributeKeyId = attributeKey.id;\n } else {\n await makeGraphQLRequest(client, UPDATE_ATTRIBUTE, {\n attributeKeyId: existingAttribute.id,\n description: existingAttribute.isCustom\n ? attribute.description\n : undefined,\n ...input,\n });\n attributeKeyId = existingAttribute.id;\n }\n\n // upsert attribute values\n const existingAttributeMap = keyBy(existingAttribute?.values || [], 'name');\n const { existingValues = [], newValues = [] } = groupBy(\n attribute.values || [],\n (field) =>\n existingAttributeMap[field.name] ? 'existingValues' : 'newValues',\n );\n const removedValues = difference(\n (existingAttribute?.values || []).map(({ name }) => name),\n (attribute.values || []).map(({ name }) => name),\n );\n\n // Create new attribute values\n if (newValues.length > 0) {\n await makeGraphQLRequest(client, CREATE_ATTRIBUTE_VALUES, {\n input: newValues.map(({ name, ...rest }) => ({\n name,\n attributeKeyId,\n ...rest,\n })),\n });\n logger.info(colors.green(`Created ${newValues.length} attribute values`));\n }\n\n // Update existing attribute values\n if (existingValues.length > 0) {\n await makeGraphQLRequest(client, UPDATE_ATTRIBUTE_VALUES, {\n input: existingValues.map(({ name, ...rest }) => ({\n id: existingAttributeMap[name].id,\n name,\n description: existingAttributeMap[name].description,\n color: existingAttributeMap[name].color,\n ...rest,\n attributeKeyId,\n })),\n });\n logger.info(\n colors.green(`Updated ${existingValues.length} attribute values`),\n );\n }\n\n // Delete removed attribute values\n if (removedValues.length > 0 && deleteExtraAttributeValues) {\n await map(\n removedValues,\n async (value) => {\n await makeGraphQLRequest(client, DELETE_ATTRIBUTE_VALUE, {\n id: existingAttributeMap[value].id,\n });\n },\n {\n concurrency: 10,\n },\n );\n logger.info(\n colors.green(`Deleted ${removedValues.length} attribute values`),\n );\n }\n}\n","import { BusinessEntityInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport { UPDATE_BUSINESS_ENTITIES, CREATE_BUSINESS_ENTITY } from './gqls';\nimport { logger } from '../../logger';\nimport { keyBy, chunk } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n fetchAllBusinessEntities,\n BusinessEntity,\n} from './fetchAllBusinessEntities';\nimport colors from 'colors';\n\n/**\n * Input to create a new business entity\n *\n * @param client - GraphQL client\n * @param businessEntity - Input\n * @returns Created business entity\n */\nexport async function createBusinessEntity(\n client: GraphQLClient,\n businessEntity: BusinessEntityInput,\n): Promise<BusinessEntity> {\n const input = {\n title: businessEntity.title,\n description: businessEntity.description,\n address: businessEntity.address,\n headquarterCountry: businessEntity.headquarterCountry,\n headquarterSubDivision: businessEntity.headquarterSubDivision,\n dataProtectionOfficerName: businessEntity.dataProtectionOfficerName,\n dataProtectionOfficerEmail: businessEntity.dataProtectionOfficerEmail,\n attributes: businessEntity.attributes,\n teamNames: businessEntity.teams,\n ownerEmails: businessEntity.owners,\n };\n\n const { createBusinessEntity } = await makeGraphQLRequest<{\n /** Create business entity mutation */\n createBusinessEntity: {\n /** Created business entity */\n businessEntity: BusinessEntity;\n };\n }>(client, CREATE_BUSINESS_ENTITY, {\n input,\n });\n return createBusinessEntity.businessEntity;\n}\n\n/**\n * Input to update business entities\n *\n * @param client - GraphQL client\n * @param businessEntityIdParis - [BusinessEntityInput, businessEntityId] list\n */\nexport async function updateBusinessEntities(\n client: GraphQLClient,\n businessEntityIdParis: [BusinessEntityInput, string][],\n): Promise<void> {\n const chunkedUpdates = chunk(businessEntityIdParis, 100);\n await mapSeries(chunkedUpdates, async (chunked) => {\n await makeGraphQLRequest(client, UPDATE_BUSINESS_ENTITIES, {\n input: chunked.map(([businessEntity, id]) => ({\n id,\n title: businessEntity.title,\n description: businessEntity.description,\n address: businessEntity.address,\n headquarterCountry: businessEntity.headquarterCountry,\n headquarterSubDivision: businessEntity.headquarterSubDivision,\n dataProtectionOfficerName: businessEntity.dataProtectionOfficerName,\n dataProtectionOfficerEmail: businessEntity.dataProtectionOfficerEmail,\n attributes: businessEntity.attributes,\n teamNames: businessEntity.teams,\n ownerEmails: businessEntity.owners,\n })),\n });\n });\n}\n\n/**\n * Sync the data inventory business entities\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncBusinessEntities(\n client: GraphQLClient,\n inputs: BusinessEntityInput[],\n): Promise<boolean> {\n // Fetch existing\n logger.info(\n colors.magenta(`Syncing \"${inputs.length}\" business entities...`),\n );\n\n let encounteredError = false;\n\n // Fetch existing\n const existingBusinessEntities = await fetchAllBusinessEntities(client);\n\n // Look up by title\n const businessEntityByTitle = keyBy(existingBusinessEntities, 'title');\n\n // Create new business entities\n const newBusinessEntities = inputs.filter(\n (input) => !businessEntityByTitle[input.title],\n );\n\n // Create new business entities\n await mapSeries(newBusinessEntities, async (businessEntity) => {\n try {\n const newBusinessEntity = await createBusinessEntity(\n client,\n businessEntity,\n );\n businessEntityByTitle[newBusinessEntity.title] = newBusinessEntity;\n logger.info(\n colors.green(\n `Successfully synced business entity \"${businessEntity.title}\"!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync business entity \"${businessEntity.title}\"! - ${err.message}`,\n ),\n );\n }\n });\n\n // Update all business entities\n try {\n logger.info(\n colors.magenta(`Updating \"${inputs.length}\" business entities!`),\n );\n await updateBusinessEntities(\n client,\n inputs.map((input) => [input, businessEntityByTitle[input.title].id]),\n );\n logger.info(\n colors.green(`Successfully synced \"${inputs.length}\" business entities!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync \"${inputs.length}\" business entities ! - ${err.message}`,\n ),\n );\n }\n\n return !encounteredError;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { CODE_PACKAGES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { CodePackageType } from '@transcend-io/privacy-types';\n\nexport interface CodePackage {\n /** ID of code package */\n id: string;\n /** Name of code package */\n name: string;\n /** Description of code package */\n description: string;\n /** Type of code package */\n type: CodePackageType;\n /** Relative path to code package in repository */\n relativePath: string;\n /** The teams that manage the code package */\n teams: {\n /** ID of team */\n id: string;\n /** Name of team */\n name: string;\n }[];\n /** The users that manage the code package */\n owners: {\n /** ID of user */\n id: string;\n /** Email of user */\n email: string;\n }[];\n /** The repository where the code package belongs */\n repository: {\n /** ID of repository */\n id: string;\n /** Name of repository */\n name: string;\n };\n /** The data silo that the code package relates to */\n dataSilo?: {\n /** ID of repository */\n id: string;\n /** Title of repository */\n title: string;\n /** Type of data silo */\n type: string;\n };\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all code packages in the organization\n *\n * @param client - GraphQL client\n * @returns All code packages in the organization\n */\nexport async function fetchAllCodePackages(\n client: GraphQLClient,\n): Promise<CodePackage[]> {\n const codePackages: CodePackage[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n codePackages: { nodes },\n } = await makeGraphQLRequest<{\n /** Code packages */\n codePackages: {\n /** List */\n nodes: CodePackage[];\n };\n }>(client, CODE_PACKAGES, {\n first: PAGE_SIZE,\n offset,\n });\n codePackages.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return codePackages.sort((a, b) => a.name.localeCompare(b.name));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { SOFTWARE_DEVELOPMENT_KITS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { CodePackageType } from '@transcend-io/privacy-types';\n\nexport interface SoftwareDevelopmentKit {\n /** ID of software development kit */\n id: string;\n /** Name of software development kit */\n name: string;\n /** Description of software development kit */\n description: string;\n /** Type of software development kit */\n codePackageType: CodePackageType;\n /** Related documentation */\n documentationLinks: string[];\n /** Link to git repository */\n repositoryUrl?: string;\n /** The teams that manage the software development kit */\n teams: {\n /** ID of team */\n id: string;\n /** Name of team */\n name: string;\n }[];\n /** The users that manage the software development kit */\n owners: {\n /** ID of user */\n id: string;\n /** Email of user */\n email: string;\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all software development kits in the organization\n *\n * @param client - GraphQL client\n * @returns All software development kits in the organization\n */\nexport async function fetchAllSoftwareDevelopmentKits(\n client: GraphQLClient,\n): Promise<SoftwareDevelopmentKit[]> {\n const softwareDevelopmentKits: SoftwareDevelopmentKit[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n softwareDevelopmentKits: { nodes },\n } = await makeGraphQLRequest<{\n /** Software development kits */\n softwareDevelopmentKits: {\n /** List */\n nodes: SoftwareDevelopmentKit[];\n };\n }>(client, SOFTWARE_DEVELOPMENT_KITS, {\n first: PAGE_SIZE,\n offset,\n });\n softwareDevelopmentKits.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return softwareDevelopmentKits.sort((a, b) => a.name.localeCompare(b.name));\n}\n","import colors from 'colors';\nimport { chunk, keyBy } from 'lodash-es';\nimport { SoftwareDevelopmentKitInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport {\n UPDATE_SOFTWARE_DEVELOPMENT_KITS,\n CREATE_SOFTWARE_DEVELOPMENT_KIT,\n} from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { mapSeries, map } from '../bluebird';\nimport {\n fetchAllSoftwareDevelopmentKits,\n SoftwareDevelopmentKit,\n} from './fetchAllSoftwareDevelopmentKits';\nimport { logger } from '../../logger';\nimport { CodePackageType } from '@transcend-io/privacy-types';\n\nconst CHUNK_SIZE = 100;\n\n/**\n * Create a new software development kit\n *\n * @param client - GraphQL client\n * @param input - Software development kit input\n * @returns Created software development kit\n */\nexport async function createSoftwareDevelopmentKit(\n client: GraphQLClient,\n input: {\n /** Title of software development kit */\n name: string;\n /** Code package type */\n codePackageType: CodePackageType;\n /** Description of the SDK */\n description?: string;\n /** Github repository */\n repositoryUrl?: string;\n /** Integration name */\n catalogIntegrationName?: string;\n /** Doc links */\n documentationLinks?: string[];\n /** Code package IDs */\n codePackageIds?: string[];\n /** Code package names */\n codePackageNames?: string[];\n /** User IDs of owners */\n ownerIds?: string[];\n /** Emails of owners */\n ownerEmails?: string[];\n /** Team IDs */\n teamIds?: string[];\n /** Team names */\n teamNames?: string[];\n },\n): Promise<SoftwareDevelopmentKit> {\n const {\n createSoftwareDevelopmentKit: { softwareDevelopmentKit },\n } = await makeGraphQLRequest<{\n /** createSoftwareDevelopmentKit mutation */\n createSoftwareDevelopmentKit: {\n /** Software development kit */\n softwareDevelopmentKit: SoftwareDevelopmentKit;\n };\n }>(client, CREATE_SOFTWARE_DEVELOPMENT_KIT, {\n input,\n });\n logger.info(\n colors.green(\n `Successfully created software development kit \"${input.name}\"!`,\n ),\n );\n return softwareDevelopmentKit;\n}\n\n/**\n * Update an existing software development kit\n *\n * @param client - GraphQL client\n * @param inputs - Software development kit input\n * @returns Updated software development kits\n */\nexport async function updateSoftwareDevelopmentKits(\n client: GraphQLClient,\n inputs: {\n /** ID of software development kit */\n id: string;\n /** Title of software development kit */\n name?: string;\n /** Description of the SDK */\n description?: string;\n /** Github repository */\n repositoryUrl?: string;\n /** Integration name */\n catalogIntegrationName?: string;\n /** Doc links */\n documentationLinks?: string[];\n /** Code package IDs */\n codePackageIds?: string[];\n /** Code package names */\n codePackageNames?: string[];\n /** User IDs of owners */\n ownerIds?: string[];\n /** Emails of owners */\n ownerEmails?: string[];\n /** Team IDs */\n teamIds?: string[];\n /** Team names */\n teamNames?: string[];\n }[],\n): Promise<SoftwareDevelopmentKit[]> {\n const {\n updateSoftwareDevelopmentKits: { softwareDevelopmentKits },\n } = await makeGraphQLRequest<{\n /** updateSoftwareDevelopmentKits mutation */\n updateSoftwareDevelopmentKits: {\n /** Software development kit */\n softwareDevelopmentKits: SoftwareDevelopmentKit[];\n };\n }>(client, UPDATE_SOFTWARE_DEVELOPMENT_KITS, {\n input: {\n softwareDevelopmentKits: inputs,\n },\n });\n logger.info(\n colors.green(\n `Successfully updated ${inputs.length} software development kits!`,\n ),\n );\n return softwareDevelopmentKits;\n}\n\n/**\n * Sync the software development kits\n *\n * @param client - GraphQL client\n * @param softwareDevelopmentKits - Software development kits\n * @param concurrency - Concurrency\n * @returns The software development kits that were upserted and whether the sync was successful\n */\nexport async function syncSoftwareDevelopmentKits(\n client: GraphQLClient,\n softwareDevelopmentKits: SoftwareDevelopmentKitInput[],\n concurrency = 20,\n): Promise<{\n /** The SDKs that were upserted */\n softwareDevelopmentKits: SoftwareDevelopmentKit[];\n /** If successful */\n success: boolean;\n}> {\n let encounteredError = false;\n const sdks: SoftwareDevelopmentKit[] = [];\n logger.info(colors.magenta('Syncing software development kits...'));\n\n // Index existing software development kits\n const existing = await fetchAllSoftwareDevelopmentKits(client);\n const softwareDevelopmentKitByTitle = keyBy(\n existing,\n ({ name, codePackageType }) => JSON.stringify({ name, codePackageType }),\n );\n\n // Determine which software development kits are new vs existing\n const mapSoftwareDevelopmentKitsToExisting = softwareDevelopmentKits.map(\n (sdkInput) => [\n sdkInput,\n softwareDevelopmentKitByTitle[\n JSON.stringify({\n name: sdkInput.name,\n codePackageType: sdkInput.codePackageType,\n })\n ]?.id,\n ],\n );\n\n // Create the new software development kits\n const newSoftwareDevelopmentKits = mapSoftwareDevelopmentKitsToExisting\n .filter(([, existing]) => !existing)\n .map(([sdkInput]) => sdkInput as SoftwareDevelopmentKitInput);\n try {\n logger.info(\n colors.magenta(\n `Creating \"${newSoftwareDevelopmentKits.length}\" new software development kits...`,\n ),\n );\n await map(\n newSoftwareDevelopmentKits,\n async (sdk) => {\n const newSdk = await createSoftwareDevelopmentKit(client, sdk);\n sdks.push(newSdk);\n },\n {\n concurrency,\n },\n );\n logger.info(\n colors.green(\n `Successfully synced ${newSoftwareDevelopmentKits.length} software development kits!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to create software development kits! - ${err.message}`,\n ),\n );\n }\n\n // Update existing software development kits\n const existingSoftwareDevelopmentKits =\n mapSoftwareDevelopmentKitsToExisting.filter(\n (x): x is [SoftwareDevelopmentKitInput, string] => !!x[1],\n );\n const chunks = chunk(existingSoftwareDevelopmentKits, CHUNK_SIZE);\n logger.info(\n colors.magenta(\n `Updating \"${existingSoftwareDevelopmentKits.length}\" software development kits...`,\n ),\n );\n\n await mapSeries(chunks, async (chunk) => {\n try {\n const updatedSdks = await updateSoftwareDevelopmentKits(\n client,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n chunk.map(([{ codePackageType, ...input }, id]) => ({\n ...input,\n id,\n })),\n );\n sdks.push(...updatedSdks);\n logger.info(\n colors.green(\n `Successfully updated \"${existingSoftwareDevelopmentKits.length}\" software development kits!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to update software development kits! - ${err.message}`,\n ),\n );\n }\n\n logger.info(\n colors.green(\n `Synced \"${softwareDevelopmentKits.length}\" software development kits!`,\n ),\n );\n });\n\n // Return true upon success\n return {\n softwareDevelopmentKits: sdks,\n success: !encounteredError,\n };\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { REPOSITORIES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface Repository {\n /** ID of repository */\n id: string;\n /** Name of repository */\n name: string;\n /** Description of repository */\n description: string;\n /** URL of repo */\n url: string;\n /** The teams that manage the repository */\n teams: {\n /** ID of team */\n id: string;\n /** Name of team */\n name: string;\n }[];\n /** The users that manage the repository */\n owners: {\n /** ID of user */\n id: string;\n /** Email of user */\n email: string;\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all repositories in the organization\n *\n * @param client - GraphQL client\n * @returns All repositories in the organization\n */\nexport async function fetchAllRepositories(\n client: GraphQLClient,\n): Promise<Repository[]> {\n const repositories: Repository[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n repositories: { nodes },\n } = await makeGraphQLRequest<{\n /** Repositories */\n repositories: {\n /** List */\n nodes: Repository[];\n };\n }>(client, REPOSITORIES, {\n first: PAGE_SIZE,\n offset,\n });\n repositories.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return repositories.sort((a, b) => a.name.localeCompare(b.name));\n}\n","import colors from 'colors';\nimport { chunk, keyBy } from 'lodash-es';\nimport { RepositoryInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { UPDATE_REPOSITORIES, CREATE_REPOSITORY } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { mapSeries, map } from '../bluebird';\nimport { fetchAllRepositories, Repository } from './fetchAllRepositories';\nimport { logger } from '../../logger';\n\nconst CHUNK_SIZE = 100;\n\n/**\n * Create a new repository\n *\n * @param client - GraphQL client\n * @param input - Repository input\n * @returns Created repository\n */\nexport async function createRepository(\n client: GraphQLClient,\n input: {\n /** Title of repository */\n name: string;\n /** Description of the repository */\n description?: string;\n /** Github repository */\n url: string;\n /** User IDs of owners */\n ownerIds?: string[];\n /** Emails of owners */\n ownerEmails?: string[];\n /** Team IDs */\n teamIds?: string[];\n /** Team names */\n teamNames?: string[];\n },\n): Promise<Repository> {\n const {\n createRepository: { repository },\n } = await makeGraphQLRequest<{\n /** createRepository mutation */\n createRepository: {\n /** Software development kit */\n repository: Repository;\n };\n }>(client, CREATE_REPOSITORY, {\n input,\n });\n logger.info(colors.green(`Successfully created repository \"${input.name}\"!`));\n return repository;\n}\n\n/**\n * Update an existing repository\n *\n * @param client - GraphQL client\n * @param inputs - Repository input\n * @returns Updated repositories\n */\nexport async function updateRepositories(\n client: GraphQLClient,\n inputs: {\n /** ID of repository */\n id: string;\n /** Title of repository */\n name?: string;\n /** Description of the repository */\n description?: string;\n /** Github repository */\n url?: string;\n /** User IDs of owners */\n ownerIds?: string[];\n /** Emails of owners */\n ownerEmails?: string[];\n /** Team IDs */\n teamIds?: string[];\n /** Team names */\n teamNames?: string[];\n }[],\n): Promise<Repository[]> {\n const {\n updateRepositories: { repositories },\n } = await makeGraphQLRequest<{\n /** updateRepositories mutation */\n updateRepositories: {\n /** Software development kit */\n repositories: Repository[];\n };\n }>(client, UPDATE_REPOSITORIES, {\n input: {\n repositories: inputs,\n },\n });\n logger.info(\n colors.green(`Successfully updated ${inputs.length} repositories!`),\n );\n return repositories;\n}\n\n/**\n * Sync the repositories\n *\n * @param client - GraphQL client\n * @param repositories - Repositories\n * @param concurrency - Concurrency\n * @returns The repositories that were upserted and whether the sync was successful\n */\nexport async function syncRepositories(\n client: GraphQLClient,\n repositories: RepositoryInput[],\n concurrency = 20,\n): Promise<{\n /** The repositories that were upserted */\n repositories: Repository[];\n /** If successful */\n success: boolean;\n}> {\n let encounteredError = false;\n const repos: Repository[] = [];\n\n // Index existing repositories\n const existing = await fetchAllRepositories(client);\n const repositoryByName = keyBy(existing, 'name');\n\n // Determine which repositories are new vs existing\n const mapRepositoriesToExisting = repositories.map((repoInput) => [\n repoInput,\n repositoryByName[repoInput.name]?.id,\n ]);\n\n // Create the new repositories\n const newRepositories = mapRepositoriesToExisting\n .filter(([, existing]) => !existing)\n .map(([repoInput]) => repoInput as RepositoryInput);\n try {\n logger.info(\n colors.magenta(\n `Creating \"${newRepositories.length}\" new repositories...`,\n ),\n );\n await map(\n newRepositories,\n async (repo) => {\n const newRepo = await createRepository(client, repo);\n repos.push(newRepo);\n },\n {\n concurrency,\n },\n );\n logger.info(\n colors.green(\n `Successfully synced ${newRepositories.length} repositories!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create repositories! - ${err.message}`));\n }\n\n // Update existing repositories\n const existingRepositories = mapRepositoriesToExisting.filter(\n (x): x is [RepositoryInput, string] => !!x[1],\n );\n const chunks = chunk(existingRepositories, CHUNK_SIZE);\n logger.info(\n colors.magenta(`Updating \"${existingRepositories.length}\" repositories...`),\n );\n\n await mapSeries(chunks, async (chunk) => {\n try {\n const updatedRepos = await updateRepositories(\n client,\n chunk.map(([input, id]) => ({\n ...input,\n id,\n })),\n );\n repos.push(...updatedRepos);\n logger.info(\n colors.green(\n `Successfully updated \"${existingRepositories.length}\" repositories!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to update repositories! - ${err.message}`),\n );\n }\n\n logger.info(colors.green(`Synced \"${repositories.length}\" repositories!`));\n });\n\n // Return true upon success\n return {\n repositories: repos,\n success: !encounteredError,\n };\n}\n","import { chunk, uniq, keyBy, uniqBy } from 'lodash-es';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { CodePackage, fetchAllCodePackages } from './fetchAllCodePackages';\nimport { logger } from '../../logger';\nimport { syncSoftwareDevelopmentKits } from './syncSoftwareDevelopmentKits';\nimport { map, mapSeries } from '../bluebird';\nimport { CodePackageInput, RepositoryInput } from '../../codecs';\nimport { CodePackageType } from '@transcend-io/privacy-types';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { CREATE_CODE_PACKAGE, UPDATE_CODE_PACKAGES } from './gqls';\nimport { syncRepositories } from './syncRepositories';\n\nconst CHUNK_SIZE = 100;\n\nconst LOOKUP_SPLIT_KEY = '%%%%';\n\n/**\n * Create a new code package\n *\n * @param client - GraphQL client\n * @param input - Code package input\n * @returns Code package ID\n */\nexport async function createCodePackage(\n client: GraphQLClient,\n input: {\n /** Name of package */\n name: string;\n /** Description of package */\n description?: string;\n /** Type of package */\n type: CodePackageType;\n /** Relative path to package */\n relativePath: string;\n /** Repository ID */\n repositoryId?: string;\n /** Name of repository */\n repositoryName?: string;\n /** IDs of SDKs */\n softwareDevelopmentKitIds?: string[];\n /** IDs of owners */\n ownerIds?: string[];\n /** Emails of owners */\n ownerEmails?: string[];\n /** IDs of teams */\n teamIds?: string[];\n /** Names of teams */\n teamNames?: string[];\n },\n): Promise<CodePackage> {\n const {\n createCodePackage: { codePackage },\n } = await makeGraphQLRequest<{\n /** createCodePackage mutation */\n createCodePackage: {\n /** Code package */\n codePackage: CodePackage;\n };\n }>(client, CREATE_CODE_PACKAGE, {\n input,\n });\n logger.info(\n colors.green(`Successfully created code package \"${input.name}\"!`),\n );\n return codePackage;\n}\n\n/**\n * Update an existing code package\n *\n * @param client - GraphQL client\n * @param inputs - Code package input\n * @returns Code packages that were updated\n */\nexport async function updateCodePackages(\n client: GraphQLClient,\n inputs: {\n /** ID of code package */\n id: string;\n /** Name of package */\n name: string;\n /** Description of package */\n description?: string;\n /** Type of package */\n type: CodePackageType;\n /** Relative path to package */\n relativePath: string;\n /** Repository ID */\n repositoryId?: string;\n /** Name of repository */\n repositoryName?: string;\n /** IDs of SDKs */\n softwareDevelopmentKitIds?: string[];\n /** IDs of owners */\n ownerIds?: string[];\n /** Emails of owners */\n ownerEmails?: string[];\n /** IDs of teams */\n teamIds?: string[];\n /** Names of teams */\n teamNames?: string[];\n }[],\n): Promise<CodePackage[]> {\n const {\n updateCodePackages: { codePackages },\n } = await makeGraphQLRequest<{\n /** updateCodePackages mutation */\n updateCodePackages: {\n /** Code packages */\n codePackages: CodePackage[];\n };\n }>(client, UPDATE_CODE_PACKAGES, {\n input: {\n codePackages: inputs,\n },\n });\n logger.info(\n colors.green(`Successfully updated ${inputs.length} code packages!`),\n );\n return codePackages;\n}\n\n/**\n * Uploads silo discovery results for Transcend to classify\n *\n * @param client - GraphQL Client\n * @param codePackages - Packages to upload\n * @param concurrency - How many concurrent requests to make\n * @returns True if successful, false if any updates failed, or an error occurs\n */\nexport async function syncCodePackages(\n client: GraphQLClient,\n codePackages: CodePackageInput[],\n concurrency = 20,\n): Promise<boolean> {\n let encounteredError = false;\n const [\n existingCodePackages,\n { softwareDevelopmentKits: existingSoftwareDevelopmentKits },\n ] = await Promise.all([\n // fetch all code packages\n fetchAllCodePackages(client),\n // make sure all SDKs exist\n syncSoftwareDevelopmentKits(\n client,\n uniqBy(\n codePackages\n .map(({ type, softwareDevelopmentKits = [] }) =>\n softwareDevelopmentKits.map(({ name }) => ({\n name,\n codePackageType: type,\n })),\n )\n .flat(),\n ({ name, codePackageType }) =>\n `${name}${LOOKUP_SPLIT_KEY}${codePackageType}`,\n ),\n concurrency,\n ),\n // make sure all Repositories exist\n syncRepositories(\n client,\n uniqBy(codePackages, 'repositoryName').map(\n ({ repositoryName }) =>\n ({\n name: repositoryName,\n url: `https://github.com/${repositoryName}`,\n } as RepositoryInput),\n ),\n ),\n ]);\n\n const softwareDevelopmentKitLookup = keyBy(\n existingSoftwareDevelopmentKits,\n ({ name, codePackageType }) =>\n `${name}${LOOKUP_SPLIT_KEY}${codePackageType}`,\n );\n const codePackagesLookup = keyBy(\n existingCodePackages,\n ({ name, type }) => `${name}${LOOKUP_SPLIT_KEY}${type}`,\n );\n\n // Determine which codePackages are new vs existing\n const mapCodePackagesToExisting = codePackages.map((codePackageInput) => [\n codePackageInput,\n codePackagesLookup[\n `${codePackageInput.name}${LOOKUP_SPLIT_KEY}${codePackageInput.type}`\n ]?.id,\n ]);\n\n // Create the new codePackages\n const newCodePackages = mapCodePackagesToExisting\n .filter(([, existing]) => !existing)\n .map(([codePackageInput]) => codePackageInput as CodePackageInput);\n try {\n logger.info(\n colors.magenta(\n `Creating \"${newCodePackages.length}\" new code packages...`,\n ),\n );\n await map(\n newCodePackages,\n async ({ softwareDevelopmentKits, ...codePackage }) => {\n await createCodePackage(client, {\n ...codePackage,\n ...(softwareDevelopmentKits\n ? {\n softwareDevelopmentKitIds: uniq(\n softwareDevelopmentKits.map(({ name }) => {\n const sdk =\n softwareDevelopmentKitLookup[\n `${name}${LOOKUP_SPLIT_KEY}${codePackage.type}`\n ];\n if (!sdk) {\n throw new Error(\n `Failed to find SDK with name: \"${name}\"`,\n );\n }\n return sdk.id;\n }),\n ),\n }\n : {}),\n });\n },\n {\n concurrency,\n },\n );\n logger.info(\n colors.green(\n `Successfully synced ${newCodePackages.length} code packages!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create code packages! - ${err.message}`));\n }\n\n // Update existing codePackages\n const existingCodePackageInputs = mapCodePackagesToExisting.filter(\n (x): x is [CodePackageInput, string] => !!x[1],\n );\n logger.info(\n colors.magenta(\n `Updating \"${existingCodePackageInputs.length}\" code packages...`,\n ),\n );\n const chunks = chunk(existingCodePackageInputs, CHUNK_SIZE);\n\n await mapSeries(chunks, async (chunk) => {\n try {\n await updateCodePackages(\n client,\n chunk.map(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n ([{ softwareDevelopmentKits, repositoryName, ...input }, id]) => ({\n ...input,\n ...(softwareDevelopmentKits\n ? {\n softwareDevelopmentKitIds: uniq(\n softwareDevelopmentKits.map(({ name }) => {\n const sdk =\n softwareDevelopmentKitLookup[\n `${name}${LOOKUP_SPLIT_KEY}${input.type}`\n ];\n if (!sdk) {\n throw new Error(\n `Failed to find SDK with name: \"${name}\"`,\n );\n }\n return sdk.id;\n }),\n ),\n }\n : {}),\n id,\n }),\n ),\n );\n logger.info(\n colors.green(`Successfully updated \"${chunk.length}\" code packages!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to update code packages! - ${err.message}`),\n );\n }\n });\n\n logger.info(colors.green(`Synced \"${codePackages.length}\" code packages!`));\n return !encounteredError;\n}\n","import {\n ConsentManageExperienceInput,\n ConsentManagerInput,\n} from '../../codecs';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport {\n UPDATE_CONSENT_MANAGER_DOMAINS,\n CREATE_CONSENT_MANAGER,\n UPDATE_LOAD_OPTIONS,\n UPDATE_CONSENT_MANAGER_PARTITION,\n UPDATE_CONSENT_MANAGER_VERSION,\n TOGGLE_TELEMETRY_PARTITION_STRATEGY,\n TOGGLE_UNKNOWN_COOKIE_POLICY,\n TOGGLE_CONSENT_PRECEDENCE,\n TOGGLE_UNKNOWN_REQUEST_POLICY,\n UPDATE_CONSENT_EXPERIENCE,\n CREATE_CONSENT_EXPERIENCE,\n UPDATE_CONSENT_MANAGER_THEME,\n} from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n fetchConsentManagerId,\n fetchConsentManagerExperiences,\n} from './fetchConsentManagerId';\nimport { keyBy } from 'lodash-es';\nimport { map } from '../bluebird';\nimport {\n InitialViewState,\n OnConsentExpiry,\n} from '@transcend-io/airgap.js-types';\nimport { logger } from '../../logger';\nimport { fetchPrivacyCenterId } from './fetchPrivacyCenterId';\nimport { fetchPartitions } from './syncPartitions';\nimport { fetchAllPurposes } from './fetchAllPurposes';\n\nconst PURPOSES_LINK =\n 'https://app.transcend.io/consent-manager/regional-experiences/purposes';\n\n/**\n * Sync consent manager experiences up to Transcend\n *\n * @param client - GraphQL client\n * @param experiences - The experience inputs\n */\nexport async function syncConsentManagerExperiences(\n client: GraphQLClient,\n experiences: ConsentManageExperienceInput[],\n): Promise<void> {\n // Fetch existing experiences and\n const existingExperiences = await fetchConsentManagerExperiences(client);\n const experienceLookup = keyBy(existingExperiences, 'name');\n\n // Fetch existing purposes\n const purposes = await fetchAllPurposes(client);\n const purposeLookup = keyBy(purposes, 'trackingType');\n\n // Bulk update or create experiences\n await map(\n experiences,\n async (exp, ind) => {\n // Purpose IDs\n const purposeIds = exp.purposes?.map((purpose, ind2) => {\n const existingPurpose = purposeLookup[purpose.trackingType];\n if (!existingPurpose) {\n throw new Error(\n `Invalid purpose trackingType provided at consentManager.experiences[${ind}].purposes[${ind2}]: ` +\n `${purpose.trackingType}. See list of valid purposes ${PURPOSES_LINK}`,\n );\n }\n return existingPurpose.id;\n });\n const optedOutPurposeIds = exp.optedOutPurposes?.map((purpose, ind2) => {\n const existingPurpose = purposeLookup[purpose.trackingType];\n if (!existingPurpose) {\n throw new Error(\n `Invalid purpose trackingType provided at consentManager.experiences[${ind}].optedOutPurposes[${ind2}]: ` +\n `${purpose.trackingType}. See list of valid purposes ${PURPOSES_LINK}`,\n );\n }\n return existingPurpose.id;\n });\n\n // update experience\n const existingExperience = experienceLookup[exp.name];\n if (existingExperience) {\n await makeGraphQLRequest(client, UPDATE_CONSENT_EXPERIENCE, {\n input: {\n id: existingExperience.id,\n name: exp.displayName,\n regions: exp.regions,\n operator: exp.operator,\n onConsentExpiry: exp.onConsentExpiry,\n consentExpiry: exp.consentExpiry,\n displayPriority:\n exp.displayPriority !== existingExperience.displayPriority\n ? exp.displayPriority\n : undefined,\n viewState: exp.viewState,\n purposes: purposeIds,\n optedOutPurposes: optedOutPurposeIds,\n browserLanguages: exp.browserLanguages,\n browserTimeZones: exp.browserTimeZones,\n },\n });\n logger.info(\n colors.green(`Successfully synced consent experience \"${exp.name}\"!`),\n );\n } else {\n // create new experience\n await makeGraphQLRequest(client, CREATE_CONSENT_EXPERIENCE, {\n input: {\n name: exp.name,\n displayName: exp.displayName,\n regions: exp.regions,\n operator: exp.operator,\n onConsentExpiry: exp.onConsentExpiry || OnConsentExpiry.Prompt,\n consentExpiry: exp.consentExpiry,\n displayPriority: exp.displayPriority,\n viewState: exp.viewState || InitialViewState.Hidden,\n purposes: purposeIds || [],\n optedOutPurposes: optedOutPurposeIds || [],\n browserLanguages: exp.browserLanguages,\n browserTimeZones: exp.browserTimeZones,\n },\n });\n logger.info(\n colors.green(\n `Successfully created consent experience \"${exp.name}\"!`,\n ),\n );\n }\n },\n {\n concurrency: 10,\n },\n );\n}\n\n/**\n * Sync the consent manager\n *\n * @param client - GraphQL client\n * @param consentManager - The consent manager input\n */\nexport async function syncConsentManager(\n client: GraphQLClient,\n consentManager: ConsentManagerInput,\n): Promise<void> {\n let airgapBundleId: string;\n\n // ensure the consent manager is created and deployed\n try {\n airgapBundleId = await fetchConsentManagerId(client, 1);\n } catch (err) {\n // TODO: https://transcend.height.app/T-23778\n if (err.message.includes('AirgapBundle not found')) {\n const privacyCenterId = await fetchPrivacyCenterId(client);\n\n const { createConsentManager } = await makeGraphQLRequest<{\n /** Create consent manager */\n createConsentManager: {\n /** Consent manager */\n consentManager: {\n /** ID */\n id: string;\n };\n };\n }>(client, CREATE_CONSENT_MANAGER, {\n domains: consentManager.domains,\n privacyCenterId,\n });\n airgapBundleId = createConsentManager.consentManager.id;\n } else {\n throw err;\n }\n }\n\n // sync domains\n if (consentManager.domains) {\n await makeGraphQLRequest(client, UPDATE_CONSENT_MANAGER_DOMAINS, {\n domains: consentManager.domains,\n airgapBundleId,\n });\n }\n\n // sync partition\n if (consentManager.partition) {\n const partitions = await fetchPartitions(client);\n const partitionToUpdate = partitions.find(\n (part) => part.name === consentManager.partition,\n );\n if (!partitionToUpdate) {\n throw new Error(\n `Partition \"${consentManager.partition}\" not found. Please create the partition first.`,\n );\n }\n await makeGraphQLRequest(client, UPDATE_CONSENT_MANAGER_PARTITION, {\n partitionId: partitionToUpdate.id,\n airgapBundleId,\n });\n }\n\n if (consentManager.version) {\n await makeGraphQLRequest(client, UPDATE_CONSENT_MANAGER_VERSION, {\n airgapBundleId,\n version: consentManager.version,\n });\n }\n\n // sync signed IAB agreement\n if (consentManager.signedIabAgreement) {\n await makeGraphQLRequest(client, UPDATE_LOAD_OPTIONS, {\n input: {\n id: airgapBundleId,\n ...(consentManager.signedIabAgreement\n ? { signedIabAgreement: consentManager.signedIabAgreement }\n : {}),\n },\n });\n }\n\n // sync default request policy\n if (consentManager.unknownRequestPolicy) {\n await makeGraphQLRequest(client, TOGGLE_UNKNOWN_REQUEST_POLICY, {\n input: {\n id: airgapBundleId,\n unknownRequestPolicy: consentManager.unknownRequestPolicy,\n },\n });\n }\n\n // sync default cookie policy\n if (consentManager.unknownRequestPolicy) {\n await makeGraphQLRequest(client, TOGGLE_UNKNOWN_COOKIE_POLICY, {\n input: {\n id: airgapBundleId,\n unknownCookiePolicy: consentManager.unknownCookiePolicy,\n },\n });\n }\n\n // sync telemetry partition strategy\n if (consentManager.telemetryPartitioning) {\n await makeGraphQLRequest(client, TOGGLE_TELEMETRY_PARTITION_STRATEGY, {\n input: {\n id: airgapBundleId,\n strategy: consentManager.telemetryPartitioning,\n },\n });\n }\n\n // sync telemetry partition strategy\n if (consentManager.consentPrecedence) {\n await makeGraphQLRequest(client, TOGGLE_CONSENT_PRECEDENCE, {\n input: {\n id: airgapBundleId,\n consentPrecedence: consentManager.consentPrecedence,\n },\n });\n }\n\n // Update experience configurations\n if (consentManager.experiences) {\n await syncConsentManagerExperiences(client, consentManager.experiences);\n }\n\n // update theme\n if (consentManager.theme) {\n await makeGraphQLRequest(client, UPDATE_CONSENT_MANAGER_THEME, {\n input: {\n airgapBundleId,\n ...consentManager.theme,\n },\n });\n }\n\n // TODO: https://transcend.height.app/T-23875\n // syncEndpoint: string;\n // TODO: https://transcend.height.app/T-23919\n // syncGroups: string;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { logger } from '../../logger';\nimport { CookieInput } from '../../codecs';\nimport colors from 'colors';\nimport { UPDATE_OR_CREATE_COOKIES } from './gqls';\nimport { chunk } from 'lodash-es';\nimport { fetchConsentManagerId } from './fetchConsentManagerId';\nimport { mapSeries } from '../bluebird';\n// import { keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nconst MAX_PAGE_SIZE = 100;\n\n/**\n * Update or create cookies that already existed\n *\n * @param client - GraphQL client\n * @param cookieInputs - List of cookie input\n */\nexport async function updateOrCreateCookies(\n client: GraphQLClient,\n cookieInputs: CookieInput[],\n): Promise<void> {\n const airgapBundleId = await fetchConsentManagerId(client);\n\n // TODO: https://transcend.height.app/T-19841 - add with custom purposes\n // const purposes = await fetchAllPurposes(client);\n // const purposeNameToId = keyBy(purposes, 'name');\n\n await mapSeries(chunk(cookieInputs, MAX_PAGE_SIZE), async (page) => {\n await makeGraphQLRequest(client, UPDATE_OR_CREATE_COOKIES, {\n airgapBundleId,\n cookies: page.map((cookie) => ({\n name: cookie.name,\n trackingPurposes:\n cookie.trackingPurposes && cookie.trackingPurposes.length > 0\n ? cookie.trackingPurposes\n : undefined,\n // TODO: https://transcend.height.app/T-19841 - add with custom purposes\n // purposeIds: cookie.trackingPurposes\n // ? cookie.trackingPurposes\n // .filter((purpose) => purpose !== 'Unknown')\n // .map((purpose) => purposeNameToId[purpose].id)\n // : undefined,\n description: cookie.description,\n service: cookie.service,\n status: cookie.status,\n attributes: cookie.attributes,\n isRegex: cookie.isRegex,\n // TODO: https://transcend.height.app/T-23718\n // owners,\n // teams,\n })),\n });\n });\n}\n\n/**\n * Sync the set of cookies from the YML interface into the product\n *\n * @param client - GraphQL client\n * @param cookies - Cookies to sync\n * @returns True upon success, false upon failure\n */\nexport async function syncCookies(\n client: GraphQLClient,\n cookies: CookieInput[],\n): Promise<boolean> {\n let encounteredError = false;\n logger.info(colors.magenta(`Syncing \"${cookies.length}\" cookies...`));\n\n // Ensure no duplicates are being uploaded\n const notUnique = cookies.filter(\n (cookie) =>\n cookies.filter(\n (cook) => cookie.name === cook.name && cookie.isRegex === cook.isRegex,\n ).length > 1,\n );\n if (notUnique.length > 0) {\n throw new Error(\n `Failed to upload cookies as there were non-unique entries found: ${notUnique\n .map(({ name }) => name)\n .join(',')}`,\n );\n }\n\n try {\n logger.info(colors.magenta(`Upserting \"${cookies.length}\" new cookies...`));\n await updateOrCreateCookies(client, cookies);\n logger.info(colors.green(`Successfully synced ${cookies.length} cookies!`));\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create cookies! - ${err.message}`));\n }\n\n return !encounteredError;\n}\n","import { DataCategoryInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport { UPDATE_DATA_SUB_CATEGORIES, CREATE_DATA_SUB_CATEGORY } from './gqls';\nimport { logger } from '../../logger';\nimport { keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport colors from 'colors';\nimport {\n fetchAllDataCategories,\n DataSubCategory,\n} from './fetchAllDataCategories';\n\n/**\n * Input to create a new data category\n *\n * @param client - GraphQL client\n * @param dataCategory - Input\n * @returns Created data category\n */\nexport async function createDataCategory(\n client: GraphQLClient,\n dataCategory: DataCategoryInput,\n): Promise<Pick<DataSubCategory, 'id' | 'name' | 'category'>> {\n const input = {\n name: dataCategory.name,\n category: dataCategory.category,\n description: dataCategory.description,\n // TODO: https://transcend.height.app/T-31994 - add attributes, teams, owners\n };\n\n const { createDataCategory } = await makeGraphQLRequest<{\n /** Create data category mutation */\n createDataCategory: {\n /** Created data category */\n dataCategory: DataSubCategory;\n };\n }>(client, CREATE_DATA_SUB_CATEGORY, {\n input,\n });\n return createDataCategory.dataCategory;\n}\n\n/**\n * Input to update data categories\n *\n * @param client - GraphQL client\n * @param dataCategoryIdPairs - [DataCategoryInput, dataCategoryId] list\n */\nexport async function updateDataCategories(\n client: GraphQLClient,\n dataCategoryIdPairs: [DataCategoryInput, string][],\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_DATA_SUB_CATEGORIES, {\n input: {\n dataSubCategories: dataCategoryIdPairs.map(([dataCategory, id]) => ({\n id,\n description: dataCategory.description,\n // TODO: https://transcend.height.app/T-31994 - add teams, owners\n attributes: dataCategory.attributes,\n })),\n },\n });\n}\n\n/**\n * Sync the data inventory data categories\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncDataCategories(\n client: GraphQLClient,\n inputs: DataCategoryInput[],\n): Promise<boolean> {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${inputs.length}\" data categories...`));\n\n let encounteredError = false;\n\n // Fetch existing\n const existingDataCategories = await fetchAllDataCategories(client);\n\n // Look up by name\n const dataCategoryByName: {\n [k in string]: Pick<DataSubCategory, 'id' | 'name' | 'category'>;\n } = keyBy(\n existingDataCategories,\n ({ name, category }) => `${name}:${category}`,\n );\n\n // Create new data categories\n const newDataCategories = inputs.filter(\n (input) => !dataCategoryByName[`${input.name}:${input.category}`],\n );\n\n // Create new data categories\n await mapSeries(newDataCategories, async (dataCategory) => {\n try {\n const newDataCategory = await createDataCategory(client, dataCategory);\n dataCategoryByName[\n `${newDataCategory.name}:${newDataCategory.category}`\n ] = newDataCategory;\n logger.info(\n colors.green(\n `Successfully synced data category \"${dataCategory.name}\"!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync data category \"${dataCategory.name}\"! - ${err.message}`,\n ),\n );\n }\n });\n\n // Update all data categories\n try {\n logger.info(colors.magenta(`Updating \"${inputs.length}\" data categories!`));\n await updateDataCategories(\n client,\n inputs.map((input) => [\n input,\n dataCategoryByName[`${input.name}:${input.category}`].id,\n ]),\n );\n logger.info(\n colors.green(`Successfully synced \"${inputs.length}\" data categories!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync \"${inputs.length}\" data categories ! - ${err.message}`,\n ),\n );\n }\n\n return !encounteredError;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { CREATE_DATA_FLOWS, UPDATE_DATA_FLOWS } from './gqls';\nimport { chunk } from 'lodash-es';\nimport { mapSeries } from '../bluebird';\nimport { DataFlowInput } from '../../codecs';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { fetchConsentManagerId } from './fetchConsentManagerId';\nimport { logger } from '../../logger';\nimport colors from 'colors';\nimport { fetchAllDataFlows } from './fetchAllDataFlows';\nimport { ConsentTrackerStatus } from '@transcend-io/privacy-types';\n\nconst MAX_PAGE_SIZE = 100;\n\n/**\n * Update data flows that already existed\n *\n * @param client - GraphQL client\n * @param dataFlowInputs - [DataFlowInput, Data Flow ID] mappings to update\n * @param classifyService - classify service if missing\n */\nexport async function updateDataFlows(\n client: GraphQLClient,\n dataFlowInputs: [DataFlowInput, string][],\n classifyService = false,\n): Promise<void> {\n const airgapBundleId = await fetchConsentManagerId(client);\n\n // TODO: https://transcend.height.app/T-19841 - add with custom purposes\n // const purposes = await fetchAllPurposes(client);\n // const purposeNameToId = keyBy(purposes, 'name');\n\n await mapSeries(chunk(dataFlowInputs, MAX_PAGE_SIZE), async (page) => {\n await makeGraphQLRequest(client, UPDATE_DATA_FLOWS, {\n airgapBundleId,\n dataFlows: page.map(([flow, id]) => ({\n id,\n value: flow.value,\n type: flow.type,\n trackingType:\n flow.trackingPurposes && flow.trackingPurposes.length > 0\n ? flow.trackingPurposes\n : undefined,\n // TODO: https://transcend.height.app/T-19841 - add with custom purposes\n // purposeIds: flow.trackingPurposes\n // ? flow.trackingPurposes\n // .filter((purpose) => purpose !== 'Unknown')\n // .map((purpose) => purposeNameToId[purpose].id)\n // : undefined,\n description: flow.description,\n service: flow.service,\n status: flow.status,\n attributes: flow.attributes,\n // TODO: https://transcend.height.app/T-23718\n // owners,\n // teams,\n })),\n classifyService,\n });\n });\n}\n\n/**\n * Create new data flows\n *\n * @param client - GraphQL client\n * @param dataFlowInputs - List of data flows to create\n * @param classifyService - classify service if missing\n */\nexport async function createDataFlows(\n client: GraphQLClient,\n dataFlowInputs: DataFlowInput[],\n classifyService = false,\n): Promise<void> {\n const airgapBundleId = await fetchConsentManagerId(client);\n // TODO: https://transcend.height.app/T-19841 - add with custom purposes\n // const purposes = await fetchAllPurposes(client);\n // const purposeNameToId = keyBy(purposes, 'name');\n await mapSeries(chunk(dataFlowInputs, MAX_PAGE_SIZE), async (page) => {\n await makeGraphQLRequest(client, CREATE_DATA_FLOWS, {\n airgapBundleId,\n dataFlows: page.map((flow) => ({\n value: flow.value,\n type: flow.type,\n trackingType:\n flow.trackingPurposes && flow.trackingPurposes.length > 0\n ? flow.trackingPurposes\n : undefined,\n // TODO: https://transcend.height.app/T-19841 - add with custom purposes\n // purposeIds: flow.trackingPurposes\n // ? flow.trackingPurposes\n // .filter((purpose) => purpose !== 'Unknown')\n // .map((purpose) => purposeNameToId[purpose].id)\n // : undefined,\n description: flow.description,\n service: flow.service,\n status: flow.status,\n attributes: flow.attributes,\n // TODO: https://transcend.height.app/T-23718\n // owners,\n // teams,\n })),\n dropMatchingDataFlowsInTriage: true,\n classifyService,\n });\n });\n}\n\n/**\n * Sync data flow configurations into Transcend\n *\n * @param client - GraphQL client\n * @param dataFlows - The data flows to upload\n * @param classifyService - When true, auto classify the service based on the data flow value\n * @returns True if the command ran successfully, returns false if an error occurred\n */\nexport async function syncDataFlows(\n client: GraphQLClient,\n dataFlows: DataFlowInput[],\n classifyService: boolean,\n): Promise<boolean> {\n let encounteredError = false;\n logger.info(colors.magenta(`Syncing \"${dataFlows.length}\" data flows...`));\n\n // Ensure no duplicates are being uploaded\n // De-dupe the data flows based on [value, type]\n const notUnique = dataFlows.filter(\n (dataFlow) =>\n dataFlows.filter(\n (flow) => dataFlow.value === flow.value && dataFlow.type === flow.type,\n ).length > 1,\n );\n\n // Throw error to prompt user to de-dupe before uploading\n if (notUnique.length > 0) {\n throw new Error(\n `Failed to upload data flows as there were non-unique entries found: ${notUnique\n .map(({ value }) => value)\n .join(',')}`,\n );\n }\n\n // Fetch existing data flows to determine whether we are creating a new data flow\n // or updating an existing data flow\n logger.info(colors.magenta('Fetching data flows...'));\n const [existingLiveDataFlows, existingInReviewDataFlows] = await Promise.all([\n fetchAllDataFlows(client, ConsentTrackerStatus.Live),\n fetchAllDataFlows(client, ConsentTrackerStatus.NeedsReview),\n ]);\n const allDataFlows = [...existingLiveDataFlows, ...existingInReviewDataFlows];\n\n // Determine which data flows are new vs existing\n const mapDataFlowsToExisting = dataFlows.map((dataFlow) => [\n dataFlow,\n allDataFlows.find(\n (flow) => dataFlow.value === flow.value && dataFlow.type === flow.type,\n )?.id,\n ]);\n\n // Create the new data flows\n const newDataFlows = mapDataFlowsToExisting\n .filter(([, existing]) => !existing)\n .map(([flow]) => flow as DataFlowInput);\n try {\n logger.info(\n colors.magenta(`Creating \"${newDataFlows.length}\" new data flows...`),\n );\n await createDataFlows(client, newDataFlows, classifyService);\n logger.info(\n colors.green(`Successfully synced ${newDataFlows.length} data flows!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create data flows! - ${err.message}`));\n }\n\n // Update existing data flows\n const existingDataFlows = mapDataFlowsToExisting.filter(\n (x): x is [DataFlowInput, string] => !!x[1],\n );\n try {\n logger.info(\n colors.magenta(`Updating \"${existingDataFlows.length}\" data flows...`),\n );\n await updateDataFlows(client, existingDataFlows, classifyService);\n logger.info(\n colors.green(\n `Successfully updated \"${existingDataFlows.length}\" data flows!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create data flows! - ${err.message}`));\n }\n\n logger.info(colors.green(`Synced \"${dataFlows.length}\" data flows!`));\n\n // Return true upon success\n return !encounteredError;\n}\n","import { DataSubjectInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { UPDATE_DATA_SUBJECT, TOGGLE_DATA_SUBJECT } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\n/**\n * Sync the data subjects\n *\n * @param client - GraphQL client\n * @param options - Options\n */\nexport async function syncDataSubject(\n client: GraphQLClient,\n {\n dataSubject,\n dataSubjectId,\n skipPublish = false,\n }: {\n /** DataSubject update input */\n dataSubject: DataSubjectInput;\n /** Existing data subject Id */\n dataSubjectId: string;\n /** When true, skip publishing to privacy center */\n skipPublish?: boolean;\n },\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_DATA_SUBJECT, {\n input: {\n id: dataSubjectId,\n title: dataSubject.title,\n adminDashboardDefaultSilentMode:\n dataSubject.adminDashboardDefaultSilentMode,\n actions: dataSubject.actions,\n skipPublish: skipPublish && typeof dataSubject.active === 'undefined',\n },\n });\n\n if (typeof dataSubject.active === 'boolean') {\n await makeGraphQLRequest(client, TOGGLE_DATA_SUBJECT, {\n input: {\n id: dataSubjectId,\n active: dataSubject.active,\n skipPublish,\n },\n });\n }\n}\n","import { IdentifierInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { UPDATE_IDENTIFIER } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport type { DataSubject } from './fetchDataSubjects';\n\n/**\n * Sync the consent manager\n *\n * @param client - GraphQL client\n * @param options - Options\n */\nexport async function syncIdentifier(\n client: GraphQLClient,\n {\n identifier,\n dataSubjectsByName,\n identifierId,\n skipPublish = false,\n }: {\n /** Identifier update input */\n identifier: IdentifierInput;\n /** Data subject lookup by name */\n dataSubjectsByName: { [k in string]: DataSubject };\n /** Existing identifier Id */\n identifierId: string;\n /** When true, skip publishing to privacy center */\n skipPublish?: boolean;\n },\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_IDENTIFIER, {\n input: {\n id: identifierId,\n selectOptions: identifier.selectOptions,\n isRequiredInForm: identifier.isRequiredInForm,\n regex: identifier.regex,\n placeholder: identifier.placeholder,\n displayTitle: identifier.displayTitle,\n displayDescription: identifier.displayDescription,\n displayOrder: identifier.displayOrder,\n isUniqueOnPreferenceStore: identifier.isUniqueOnPreferenceStore,\n privacyCenterVisibility: identifier.privacyCenterVisibility,\n dataSubjectIds: identifier.dataSubjects\n ? identifier.dataSubjects.map((type) => dataSubjectsByName[type].id)\n : undefined,\n skipPublish,\n },\n });\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { logger } from '../../logger';\nimport { IntlMessageInput } from '../../codecs';\nimport colors from 'colors';\nimport { UPDATE_INTL_MESSAGES } from './gqls';\nimport { chunk } from 'lodash-es';\nimport { mapSeries } from '../bluebird';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nconst MAX_PAGE_SIZE = 100;\n\n/**\n * Update or create intl messages\n *\n * @param client - GraphQL client\n * @param messageInputs - List of message inputs\n */\nexport async function updateIntlMessages(\n client: GraphQLClient,\n messageInputs: IntlMessageInput[],\n): Promise<void> {\n // Batch update messages\n await mapSeries(chunk(messageInputs, MAX_PAGE_SIZE), async (page) => {\n await makeGraphQLRequest(client, UPDATE_INTL_MESSAGES, {\n messages: page.map((message) => ({\n ...(message.id.includes('.') ? {} : { id: message.id }),\n defaultMessage: message.defaultMessage,\n targetReactIntlId: message.targetReactIntlId,\n translations: !message.translations\n ? undefined\n : Object.entries(message.translations).map(([locale, value]) => ({\n locale,\n value,\n })),\n })),\n });\n });\n}\n\n/**\n * Sync the set of messages from the YML interface into the product\n *\n * @param client - GraphQL client\n * @param messages - messages to sync\n * @returns True upon success, false upon failure\n */\nexport async function syncIntlMessages(\n client: GraphQLClient,\n messages: IntlMessageInput[],\n): Promise<boolean> {\n let encounteredError = false;\n logger.info(colors.magenta(`Syncing \"${messages.length}\" messages...`));\n\n // Ensure no duplicates are being uploaded\n const notUnique = messages.filter(\n (message) => messages.filter((pol) => message.id === pol.id).length > 1,\n );\n if (notUnique.length > 0) {\n throw new Error(\n `Failed to upload messages as there were non-unique entries found: ${notUnique\n .map(({ id }) => id)\n .join(',')}`,\n );\n }\n\n try {\n logger.info(\n colors.magenta(`Upserting \"${messages.length}\" new messages...`),\n );\n await updateIntlMessages(client, messages);\n logger.info(\n colors.green(`Successfully synced ${messages.length} messages!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create messages! - ${err.message}`));\n }\n\n return !encounteredError;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { logger } from '../../logger';\nimport { PolicyInput } from '../../codecs';\nimport colors from 'colors';\nimport { UPDATE_POLICIES } from './gqls';\nimport { chunk, keyBy } from 'lodash-es';\nimport { mapSeries } from '../bluebird';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { fetchPrivacyCenterId } from './fetchPrivacyCenterId';\nimport { fetchAllPolicies } from './fetchAllPolicies';\n\nconst MAX_PAGE_SIZE = 100;\n\n/**\n * Update or create policies\n *\n * @param client - GraphQL client\n * @param policyInputs - List of policy input\n */\nexport async function updatePolicies(\n client: GraphQLClient,\n policyInputs: [PolicyInput, string | undefined][],\n): Promise<void> {\n const privacyCenterId = await fetchPrivacyCenterId(client);\n\n // Batch update policies\n await mapSeries(chunk(policyInputs, MAX_PAGE_SIZE), async (page) => {\n await makeGraphQLRequest(client, UPDATE_POLICIES, {\n privacyCenterId,\n policies: page.map(([policy, policyId]) => ({\n id: policyId,\n title: policy.title,\n disableEffectiveOn: policy.disableEffectiveOn,\n disabledLocales: policy.disabledLocales,\n ...(policy.effectiveOn || policy.content\n ? {\n version: {\n ...(policy.effectiveOn\n ? { effectiveOn: policy.effectiveOn }\n : {}),\n ...(policy.content\n ? {\n content: {\n defaultMessage: policy.content,\n },\n }\n : {}),\n },\n }\n : {}),\n })),\n });\n });\n}\n\n/**\n * Sync the set of policies from the YML interface into the product\n *\n * @param client - GraphQL client\n * @param policies - policies to sync\n * @returns True upon success, false upon failure\n */\nexport async function syncPolicies(\n client: GraphQLClient,\n policies: PolicyInput[],\n): Promise<boolean> {\n let encounteredError = false;\n logger.info(colors.magenta(`Syncing \"${policies.length}\" policies...`));\n\n // Ensure no duplicates are being uploaded\n const notUnique = policies.filter(\n (policy) => policies.filter((pol) => policy.title === pol.title).length > 1,\n );\n if (notUnique.length > 0) {\n throw new Error(\n `Failed to upload policies as there were non-unique entries found: ${notUnique\n .map(({ title }) => title)\n .join(',')}`,\n );\n }\n\n // Grab existing policies\n const existingPolicies = await fetchAllPolicies(client);\n const policiesById = keyBy(\n existingPolicies,\n ({ title }) => title.defaultMessage,\n );\n\n try {\n logger.info(\n colors.magenta(`Upserting \"${policies.length}\" new policies...`),\n );\n await updatePolicies(\n client,\n policies.map((policy) => [policy, policiesById[policy.title]?.id]),\n );\n logger.info(\n colors.green(`Successfully synced ${policies.length} policies!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create policies! - ${err.message}`));\n }\n\n return !encounteredError;\n}\n","import { PrivacyCenterInput } from '../../codecs';\nimport { logger } from '../../logger';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { UPDATE_PRIVACY_CENTER } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { fetchPrivacyCenterId } from './fetchPrivacyCenterId';\n\n/**\n * Sync the privacy center\n *\n * @param client - GraphQL client\n * @param privacyCenter - The privacy center input\n * @returns Whether the privacy center was synced successfully\n */\nexport async function syncPrivacyCenter(\n client: GraphQLClient,\n privacyCenter: PrivacyCenterInput,\n): Promise<boolean> {\n let encounteredError = false;\n logger.info(colors.magenta('Syncing privacy center...'));\n\n // Grab the privacy center ID\n const privacyCenterId = await fetchPrivacyCenterId(client);\n\n try {\n await makeGraphQLRequest(client, UPDATE_PRIVACY_CENTER, {\n input: {\n privacyCenterId,\n transformAccessReportJsonToCsv:\n privacyCenter.transformAccessReportJsonToCsv,\n useCustomEmailDomain: privacyCenter.useCustomEmailDomain,\n useNoReplyEmailAddress: privacyCenter.useNoReplyEmailAddress,\n replyToEmail: privacyCenter.replyToEmail,\n supportEmail: privacyCenter.supportEmail,\n preferBrowserDefaultLocale: privacyCenter.preferBrowserDefaultLocale,\n defaultLocale: privacyCenter.defaultLocale,\n locales: privacyCenter.locales,\n showMarketingPreferences: privacyCenter.showMarketingPreferences,\n showManageYourPrivacy: privacyCenter.showManageYourPrivacy,\n showPolicies: privacyCenter.showPolicies,\n showConsentManager: privacyCenter.showConsentManager,\n showDataFlows: privacyCenter.showDataFlows,\n showCookies: privacyCenter.showCookies,\n showTrackingTechnologies: privacyCenter.showTrackingTechnologies,\n showPrivacyRequestButton: privacyCenter.showPrivacyRequestButton,\n isDisabled: privacyCenter.isDisabled,\n ...(privacyCenter.theme\n ? {\n colorPalette: privacyCenter.theme.colors,\n componentStyles: privacyCenter.theme.componentStyles,\n textStyles: privacyCenter.theme.textStyles,\n }\n : {}),\n },\n });\n logger.info(colors.green('Successfully synced privacy center!'));\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to create privacy center! - ${err.message}`),\n );\n }\n\n return !encounteredError;\n}\n","import { ProcessingActivityInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport {\n UPDATE_PROCESSING_ACTIVITIES,\n CREATE_PROCESSING_ACTIVITY,\n} from './gqls';\nimport { logger } from '../../logger';\nimport { keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport colors from 'colors';\nimport {\n fetchAllProcessingActivities,\n ProcessingActivity,\n} from './fetchAllProcessingActivities';\n\n/**\n * Create a new processing activity, setting only title and description\n *\n * @param client - GraphQL client\n * @param processingActivity - Input\n * @returns Created processingActivity\n */\nasync function createProcessingActivity(\n client: GraphQLClient,\n processingActivity: ProcessingActivityInput,\n): Promise<Pick<ProcessingActivity, 'id' | 'title'>> {\n const input = {\n title: processingActivity.title,\n description: processingActivity.description,\n };\n\n const { createProcessingActivity } = await makeGraphQLRequest<{\n /** Create processingActivity mutation */\n createProcessingActivity: {\n /** Created processingActivity */\n processingActivity: ProcessingActivity;\n };\n }>(client, CREATE_PROCESSING_ACTIVITY, {\n input,\n });\n return createProcessingActivity.processingActivity;\n}\n\n/**\n * Update a list of processing activities.\n *\n * @param client - GraphQL client\n * @param processingActivityIdPairs - [ProcessingActivityInput, processingActivityId] list\n */\nasync function updateProcessingActivities(\n client: GraphQLClient,\n processingActivityIdPairs: [ProcessingActivityInput, string][],\n): Promise<void> {\n const invalidProcessingActivityTitles = processingActivityIdPairs\n .filter(([, id]) => id === undefined)\n .map(([{ title }]) => title);\n if (invalidProcessingActivityTitles.length > 0) {\n // We always attempt to create processing activities before updating them, but if creation failed\n // (for example, due to insufficient scope), this provides a better error message\n throw new Error(\n `The following ${\n invalidProcessingActivityTitles.length\n } processing activities do not exist and thus can't be updated: \"${invalidProcessingActivityTitles.join(\n '\", \"',\n )}\"`,\n );\n }\n await makeGraphQLRequest(client, UPDATE_PROCESSING_ACTIVITIES, {\n input: {\n processingActivities: processingActivityIdPairs.map(\n ([\n {\n processingSubPurposes,\n dataSubCategories,\n saaSCategories,\n ...processingActivity\n },\n id,\n ]) => ({\n dataSubCategoryInputs: dataSubCategories?.map(\n ({ category, name }) => ({ category, name: name ?? '' }),\n ),\n processingPurposeSubCategoryInputs: processingSubPurposes?.map(\n ({ purpose, name }) => ({ purpose, name: name ?? 'Other' }),\n ),\n saaSCategoryTitles: saaSCategories,\n ...processingActivity,\n id,\n }),\n ),\n },\n });\n}\n\n/**\n * Sync the data inventory processing activities\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncProcessingActivities(\n client: GraphQLClient,\n inputs: ProcessingActivityInput[],\n): Promise<boolean> {\n let encounteredError = false;\n\n // Fetch existing\n logger.info(\n colors.magenta(`Syncing \"${inputs.length}\" processing activities...`),\n );\n const existingProcessingActivities = await fetchAllProcessingActivities(\n client,\n );\n\n // Look up by title\n const processingActivityByTitle: Record<\n string,\n Pick<ProcessingActivity, 'id' | 'title'>\n > = keyBy(existingProcessingActivities, 'title');\n\n // Create new processingActivities\n const newProcessingActivities = inputs.filter(\n (input) => !processingActivityByTitle[input.title],\n );\n if (newProcessingActivities.length > 0) {\n logger.info(\n colors.magenta(\n `Creating \"${newProcessingActivities.length}\" new processing activities...`,\n ),\n );\n }\n await mapSeries(newProcessingActivities, async (processingActivity) => {\n try {\n const newProcessingActivity = await createProcessingActivity(\n client,\n processingActivity,\n );\n // Augment processingActivityByTitle with newly-created processing activity\n processingActivityByTitle[newProcessingActivity.title] =\n newProcessingActivity;\n logger.info(\n colors.green(\n `Successfully created processing activity \"${processingActivity.title}\"!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to create processing activity \"${processingActivity.title}\"! - ${err.message}`,\n ),\n );\n }\n });\n\n // Update all processing activities\n try {\n logger.info(\n colors.magenta(`Updating \"${inputs.length}\" processing activities!`),\n );\n await updateProcessingActivities(\n client,\n inputs.map((input) => [\n input,\n // This processing activity might not exist if the `create` step failed\n processingActivityByTitle[input.title]?.id,\n ]),\n );\n logger.info(\n colors.green(\n `Successfully synced \"${inputs.length}\" processingActivities!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync \"${inputs.length}\" processingActivities! - ${err.message}`,\n ),\n );\n }\n\n return !encounteredError;\n}\n","import { ProcessingPurposeInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport {\n UPDATE_PROCESSING_PURPOSE_SUB_CATEGORIES,\n CREATE_PROCESSING_PURPOSE_SUB_CATEGORY,\n} from './gqls';\nimport { logger } from '../../logger';\nimport { keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport colors from 'colors';\nimport {\n fetchAllProcessingPurposes,\n ProcessingPurposeSubCategory,\n} from './fetchAllProcessingPurposes';\n\n/**\n * Input to create a new processing purpose\n *\n * @param client - GraphQL client\n * @param processingPurpose - Input\n * @returns Created processing purpose\n */\nexport async function createProcessingPurpose(\n client: GraphQLClient,\n processingPurpose: ProcessingPurposeInput,\n): Promise<Pick<ProcessingPurposeSubCategory, 'id' | 'name' | 'purpose'>> {\n const input = {\n name: processingPurpose.name,\n purpose: processingPurpose.purpose,\n description: processingPurpose.description,\n // TODO: https://transcend.height.app/T-31994 - add attributes, teams, owners\n };\n\n const { createProcessingPurposeSubCategory } = await makeGraphQLRequest<{\n /** Create processing purpose mutation */\n createProcessingPurposeSubCategory: {\n /** Created processing purpose */\n processingPurposeSubCategory: ProcessingPurposeSubCategory;\n };\n }>(client, CREATE_PROCESSING_PURPOSE_SUB_CATEGORY, {\n input,\n });\n return createProcessingPurposeSubCategory.processingPurposeSubCategory;\n}\n\n/**\n * Input to update processing purposes\n *\n * @param client - GraphQL client\n * @param processingPurposeIdPairs - [ProcessingPurposeInput, processingPurposeId] list\n */\nexport async function updateProcessingPurposes(\n client: GraphQLClient,\n processingPurposeIdPairs: [ProcessingPurposeInput, string][],\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_PROCESSING_PURPOSE_SUB_CATEGORIES, {\n input: {\n processingPurposeSubCategories: processingPurposeIdPairs.map(\n ([processingPurpose, id]) => ({\n id,\n description: processingPurpose.description,\n // TODO: https://transcend.height.app/T-31994 - add teams, owners\n attributes: processingPurpose.attributes,\n }),\n ),\n },\n });\n}\n\n/**\n * Sync the data inventory processing purposes\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncProcessingPurposes(\n client: GraphQLClient,\n inputs: ProcessingPurposeInput[],\n): Promise<boolean> {\n // Fetch existing\n logger.info(\n colors.magenta(`Syncing \"${inputs.length}\" processing purposes...`),\n );\n\n let encounteredError = false;\n\n // Fetch existing\n const existingProcessingPurposes = await fetchAllProcessingPurposes(client);\n\n // Look up by name\n const processingPurposeByName: {\n [k in string]: Pick<ProcessingPurposeSubCategory, 'id' | 'name'>;\n } = keyBy(\n existingProcessingPurposes,\n ({ name, purpose }) => `${name}:${purpose}`,\n );\n\n // Create new processing purposes\n const newProcessingPurposes = inputs.filter(\n (input) => !processingPurposeByName[`${input.name}:${input.purpose}`],\n );\n\n // Create new processing purposes\n await mapSeries(newProcessingPurposes, async (processingPurpose) => {\n try {\n const newProcessingPurpose = await createProcessingPurpose(\n client,\n processingPurpose,\n );\n processingPurposeByName[\n `${newProcessingPurpose.name}:${newProcessingPurpose.purpose}`\n ] = newProcessingPurpose;\n logger.info(\n colors.green(\n `Successfully synced processing purpose \"${processingPurpose.name}\"!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync processing purpose \"${processingPurpose.name}\"! - ${err.message}`,\n ),\n );\n }\n });\n\n // Update all processing purposes\n try {\n logger.info(\n colors.magenta(`Updating \"${inputs.length}\" processing purposes!`),\n );\n await updateProcessingPurposes(\n client,\n inputs.map((input) => [\n input,\n processingPurposeByName[`${input.name}:${input.purpose}`].id,\n ]),\n );\n logger.info(\n colors.green(\n `Successfully synced \"${inputs.length}\" processing purposes!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync \"${inputs.length}\" processing purposes ! - ${err.message}`,\n ),\n );\n }\n\n return !encounteredError;\n}\n","import { PromptInput } from '../../codecs';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { UPDATE_PROMPTS, CREATE_PROMPT } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { map } from '../bluebird';\nimport { fetchAllPrompts } from './fetchPrompts';\nimport { keyBy } from 'lodash-es';\nimport { logger } from '../../logger';\n\n/**\n * Create a new prompt\n *\n * @param client - GraphQL client\n * @param input - Prompt input\n * @returns Prompt ID\n */\nexport async function createPrompt(\n client: GraphQLClient,\n input: {\n /** Title of prompt */\n title: string;\n /** Prompt content */\n content: string;\n },\n): Promise<string> {\n const {\n createPrompt: { prompt },\n } = await makeGraphQLRequest<{\n /** createPrompt mutation */\n createPrompt: {\n /** Prompt */\n prompt: {\n /** ID */\n id: string;\n };\n };\n }>(client, CREATE_PROMPT, {\n // TODO: https://transcend.height.app/T-31994 - include models and groups, teams, users\n input,\n });\n logger.info(colors.green(`Successfully created prompt \"${input.title}\"!`));\n return prompt.id;\n}\n\n/**\n * Update a set of existing prompts\n *\n * @param client - GraphQL client\n * @param input - Prompt input\n */\nexport async function updatePrompts(\n client: GraphQLClient,\n input: [PromptInput, string][],\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_PROMPTS, {\n input: {\n prompts: input.map(([input, id]) => ({\n ...input,\n id,\n })),\n },\n });\n logger.info(colors.green(`Successfully updated ${input.length} prompts!`));\n}\n\n/**\n * Sync the prompts\n *\n * @param client - GraphQL client\n * @param prompts - Prompts\n * @param concurrency - Concurrency\n * @returns True if synced successfully\n */\nexport async function syncPrompts(\n client: GraphQLClient,\n prompts: PromptInput[],\n concurrency = 20,\n): Promise<boolean> {\n let encounteredError = false;\n logger.info(colors.magenta(`Syncing \"${prompts.length}\" prompts...`));\n\n // Index existing prompts\n const existing = await fetchAllPrompts(client);\n const promptByTitle = keyBy(existing, 'title');\n\n // Determine which prompts are new vs existing\n const mapPromptsToExisting = prompts.map((promptInput) => [\n promptInput,\n promptByTitle[promptInput.title]?.id,\n ]);\n\n // Create the new prompts\n const newPrompts = mapPromptsToExisting\n .filter(([, existing]) => !existing)\n .map(([promptInput]) => promptInput as PromptInput);\n try {\n logger.info(\n colors.magenta(`Creating \"${newPrompts.length}\" new prompts...`),\n );\n await map(\n newPrompts,\n async (prompt) => {\n await createPrompt(client, prompt);\n },\n {\n concurrency,\n },\n );\n logger.info(\n colors.green(`Successfully synced ${newPrompts.length} prompts!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create prompts! - ${err.message}`));\n }\n\n // Update existing prompts\n const existingPrompts = mapPromptsToExisting.filter(\n (x): x is [PromptInput, string] => !!x[1],\n );\n try {\n logger.info(\n colors.magenta(`Updating \"${existingPrompts.length}\" prompts...`),\n );\n await updatePrompts(client, existingPrompts);\n logger.info(\n colors.green(`Successfully updated \"${existingPrompts.length}\" prompts!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create prompts! - ${err.message}`));\n }\n\n logger.info(colors.green(`Synced \"${prompts.length}\" prompts!`));\n\n // Return true upon success\n return !encounteredError;\n}\n","import { VendorInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport { UPDATE_VENDORS, CREATE_VENDOR } from './gqls';\nimport { logger } from '../../logger';\nimport { keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport colors from 'colors';\nimport { fetchAllVendors, Vendor } from './fetchAllVendors';\n\n/**\n * Input to create a new vendor\n *\n * @param client - GraphQL client\n * @param vendor - Input\n * @returns Created vendor\n */\nexport async function createVendor(\n client: GraphQLClient,\n vendor: VendorInput,\n): Promise<Pick<Vendor, 'id' | 'title'>> {\n const input = {\n title: vendor.title,\n description: vendor.description,\n address: vendor.address,\n headquarterCountry: vendor.headquarterCountry,\n headquarterSubDivision: vendor.headquarterSubDivision,\n dataProcessingAgreementLink: vendor.dataProcessingAgreementLink,\n contactName: vendor.contactName,\n contactPhone: vendor.contactPhone,\n websiteUrl: vendor.websiteUrl,\n // TODO: https://transcend.height.app/T-31994 - add attributes, teams, owners\n };\n\n const { createVendor } = await makeGraphQLRequest<{\n /** Create vendor mutation */\n createVendor: {\n /** Created vendor */\n vendor: Vendor;\n };\n }>(client, CREATE_VENDOR, {\n input,\n });\n return createVendor.vendor;\n}\n\n/**\n * Input to update vendors\n *\n * @param client - GraphQL client\n * @param vendorIdParis - [VendorInput, vendorId] list\n */\nexport async function updateVendors(\n client: GraphQLClient,\n vendorIdParis: [VendorInput, string][],\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_VENDORS, {\n input: {\n vendors: vendorIdParis.map(([vendor, id]) => ({\n id,\n title: vendor.title,\n description: vendor.description,\n address: vendor.address,\n headquarterCountry: vendor.headquarterCountry,\n headquarterSubDivision: vendor.headquarterSubDivision,\n dataProcessingAgreementLink: vendor.dataProcessingAgreementLink,\n contactName: vendor.contactName,\n contactPhone: vendor.contactPhone,\n websiteUrl: vendor.websiteUrl,\n // TODO: https://transcend.height.app/T-31994 - add teams, owners\n attributes: vendor.attributes,\n })),\n },\n });\n}\n\n/**\n * Sync the data inventory vendors\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncVendors(\n client: GraphQLClient,\n inputs: VendorInput[],\n): Promise<boolean> {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${inputs.length}\" vendors...`));\n\n let encounteredError = false;\n\n // Fetch existing\n const existingVendors = await fetchAllVendors(client);\n\n // Look up by title\n const vendorByTitle: { [k in string]: Pick<Vendor, 'id' | 'title'> } = keyBy(\n existingVendors,\n 'title',\n );\n\n // Create new vendors\n const newVendors = inputs.filter((input) => !vendorByTitle[input.title]);\n\n // Create new vendors\n await mapSeries(newVendors, async (vendor) => {\n try {\n const newVendor = await createVendor(client, vendor);\n vendorByTitle[newVendor.title] = newVendor;\n logger.info(\n colors.green(`Successfully synced vendor \"${vendor.title}\"!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to sync vendor \"${vendor.title}\"! - ${err.message}`),\n );\n }\n });\n\n // Update all vendors\n try {\n logger.info(colors.magenta(`Updating \"${inputs.length}\" vendors!`));\n await updateVendors(\n client,\n inputs.map((input) => [input, vendorByTitle[input.title].id]),\n );\n logger.info(\n colors.green(`Successfully synced \"${inputs.length}\" vendors!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync \"${inputs.length}\" vendors ! - ${err.message}`,\n ),\n );\n }\n\n return !encounteredError;\n}\n","import { chunk } from 'lodash-es';\nimport { mapSeries } from '../bluebird';\nimport { ADD_SILO_DISCOVERY_RESULTS } from './gqls';\nimport { GraphQLClient } from 'graphql-request';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { SiloDiscoveryRawResults } from '../code-scanning/findFilesToScan';\n\nconst CHUNK_SIZE = 1000;\n\n/**\n * Uploads silo discovery results for Transcend to classify\n *\n * @param client - GraphQL Client\n * @param pluginId - pluginID to associate with the results\n * @param results - The results\n */\nexport async function uploadSiloDiscoveryResults(\n client: GraphQLClient,\n pluginId: string,\n results: SiloDiscoveryRawResults[],\n): Promise<void> {\n const chunks = chunk(results, CHUNK_SIZE);\n\n await mapSeries(chunks, async (rawResults) => {\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, ADD_SILO_DISCOVERY_RESULTS, {\n pluginId,\n rawResults,\n });\n });\n}\n","import { map } from '../bluebird';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport {\n UPDATE_PRIVACY_REQUEST,\n fetchAllRequests,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Mark a set of privacy requests to be in silent mode\n *\n * @param options - Options\n * @returns The number of requests marked silent\n */\nexport async function markSilentPrivacyRequests({\n requestActions,\n auth,\n requestIds,\n statuses = [\n RequestStatus.Compiling,\n RequestStatus.RequestMade,\n RequestStatus.Delayed,\n RequestStatus.Approving,\n RequestStatus.Secondary,\n RequestStatus.Enriching,\n RequestStatus.Waiting,\n RequestStatus.SecondaryApproving,\n ],\n createdAtAfter,\n createdAtBefore,\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** Transcend API key authentication */\n auth: string;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** The request statuses to mark silent */\n statuses?: RequestStatus[];\n /** The set of privacy requests to mark silent */\n requestIds?: string[];\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** 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 // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses,\n createdAtBefore,\n createdAtAfter,\n isSilent: false,\n requestIds,\n });\n\n // Notify Transcend\n logger.info(\n colors.magenta(`Marking \"${allRequests.length}\" as silent mode.`),\n );\n\n let total = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToMarkSilent) => {\n await makeGraphQLRequest(client, UPDATE_PRIVACY_REQUEST, {\n input: {\n id: requestToMarkSilent.id,\n isSilent: true,\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 marked ${total} requests as silent mode in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n return allRequests.length;\n}\n","import { getValues, getEntries } from '@transcend-io/type-utils';\nimport type { PersistedState } from '@transcend-io/persisted-state';\nimport inquirer from 'inquirer';\nimport { startCase } from 'lodash-es';\nimport {\n ColumnName,\n CachedFileState,\n IS_REQUIRED,\n CAN_APPLY_IN_BULK,\n} from './constants';\nimport { fuzzyMatchColumns } from './fuzzyMatchColumns';\n\n/**\n * Mapping from column name to request input parameter\n */\nexport type ColumnNameMap = {\n [k in ColumnName]?: string;\n};\n\n/**\n * Determine the mapping between columns in CSV\n *\n * @param columnNames - The set of column names\n * @param state - The cached file state used to map DSR inputs\n * @returns The column name mapping\n */\nexport async function mapCsvColumnsToApi(\n columnNames: string[],\n state: PersistedState<typeof CachedFileState>,\n): Promise<ColumnNameMap> {\n // Determine the columns that should be mapped\n const columnQuestions = getValues(ColumnName).filter(\n (name) => !state.getValue('columnNames', name),\n );\n\n // Skip mapping when everything is mapped\n const columnNameMap =\n columnQuestions.length === 0\n ? {}\n : // prompt questions to map columns\n await inquirer.prompt<{\n [k in ColumnName]?: string;\n }>(\n columnQuestions.map((name) => {\n const field = startCase(name.replace('ColumnName', ''));\n const matches = fuzzyMatchColumns(\n columnNames,\n field,\n IS_REQUIRED[name],\n !!CAN_APPLY_IN_BULK[name],\n );\n return {\n name,\n message: `Choose the column that will be used to map in the field: ${field}`,\n type: 'list',\n default: matches[0],\n choices: matches,\n };\n }),\n );\n\n await Promise.all(\n getEntries(columnNameMap).map(([k, v]) =>\n state.setValue(v, 'columnNames', k),\n ),\n );\n return columnNameMap;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport colors from 'colors';\nimport type { PersistedState } from '@transcend-io/persisted-state';\nimport {\n CompletedRequestStatus,\n RequestAction,\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\nimport {\n LOCALE_KEY,\n type LocaleValue,\n} from '@transcend-io/internationalization';\nimport { ObjByString } from '@transcend-io/type-utils';\nimport { logger } from '../../logger';\nimport { makeGraphQLRequest, DataSubject, DATA_SUBJECTS } from '../graphql';\nimport { CachedFileState, NONE, ColumnName } from './constants';\nimport { mapEnumValues } from './mapEnumValues';\nimport { ColumnNameMap } from './mapCsvColumnsToApi';\nimport { getUniqueValuesForColumn } from './getUniqueValuesForColumn';\n\n/**\n * Map the values in a CSV to the enum values in Transcend\n *\n * @param client - GraphQL client\n * @param requests - Set of privacy requests\n * @param options - Options\n */\nexport async function mapRequestEnumValues(\n client: GraphQLClient,\n requests: ObjByString[],\n {\n state,\n columnNameMap,\n }: {\n /** State value to write cache to */\n state: PersistedState<typeof CachedFileState>;\n /** Mapping of column names */\n columnNameMap: ColumnNameMap;\n },\n): Promise<void> {\n // Get mapped value\n const getMappedName = (attribute: ColumnName): string =>\n state.getValue('columnNames', attribute) || columnNameMap[attribute]!;\n\n // Fetch all data subjects in the organization\n const { internalSubjects } = await makeGraphQLRequest<{\n /** Query response */\n internalSubjects: DataSubject[];\n }>(client, DATA_SUBJECTS);\n\n // Map RequestAction\n logger.info(\n colors.magenta('Determining mapping of columns for request action'),\n );\n const requestTypeToRequestAction: { [k in string]: RequestAction } =\n await mapEnumValues(\n getUniqueValuesForColumn(requests, getMappedName(ColumnName.RequestType)),\n Object.values(RequestAction),\n state.getValue('requestTypeToRequestAction'),\n );\n await state.setValue(\n requestTypeToRequestAction,\n 'requestTypeToRequestAction',\n );\n\n // Map data subject type\n logger.info(colors.magenta('Determining mapping of columns for subject'));\n const subjectTypeToSubjectName: { [k in string]: string } =\n await mapEnumValues(\n getUniqueValuesForColumn(requests, getMappedName(ColumnName.SubjectType)),\n internalSubjects.map(({ type }) => type),\n state.getValue('subjectTypeToSubjectName'),\n );\n await state.setValue(subjectTypeToSubjectName, 'subjectTypeToSubjectName');\n\n // Map locale\n logger.info(colors.magenta('Determining mapping of columns for locale'));\n const languageToLocale: { [k in string]: LocaleValue } = await mapEnumValues(\n getUniqueValuesForColumn(requests, getMappedName(ColumnName.Locale)),\n Object.values(LOCALE_KEY),\n state.getValue('languageToLocale'),\n );\n await state.setValue(languageToLocale, 'languageToLocale');\n logger.info(\n colors.magenta('Determining mapping of columns for request status'),\n );\n\n // Map request status\n logger.info(\n colors.magenta('Determining mapping of columns for request status'),\n );\n const requestStatusColumn = getMappedName(ColumnName.RequestStatus);\n const statusToRequestStatus: {\n [k in string]: CompletedRequestStatus | typeof NONE;\n } =\n requestStatusColumn === NONE\n ? {}\n : await mapEnumValues(\n getUniqueValuesForColumn(requests, requestStatusColumn),\n [...Object.values(CompletedRequestStatus), NONE],\n state.getValue('statusToRequestStatus'),\n );\n await state.setValue(statusToRequestStatus, 'statusToRequestStatus');\n\n // Map country\n logger.info(colors.magenta('Determining mapping of columns for country'));\n const countryColumn = getMappedName(ColumnName.Country);\n const regionToCountry: {\n [k in string]: IsoCountryCode | typeof NONE;\n } =\n countryColumn === NONE\n ? {}\n : await mapEnumValues(\n getUniqueValuesForColumn(requests, countryColumn),\n [...Object.values(IsoCountryCode), NONE],\n state.getValue('regionToCountry'),\n );\n await state.setValue(regionToCountry, 'regionToCountry');\n\n // Map country sub division\n logger.info(\n colors.magenta('Determining mapping of columns for country sub division'),\n );\n const countrySubDivisionColumn = getMappedName(ColumnName.CountrySubDivision);\n const regionToCountrySubDivision: {\n [k in string]: IsoCountrySubdivisionCode | typeof NONE;\n } =\n countrySubDivisionColumn === NONE\n ? {}\n : await mapEnumValues(\n getUniqueValuesForColumn(requests, countrySubDivisionColumn),\n [...Object.values(IsoCountrySubdivisionCode), NONE],\n state.getValue('regionToCountrySubDivision'),\n );\n await state.setValue(\n regionToCountrySubDivision,\n 'regionToCountrySubDivision',\n );\n}\n","import { LOCALE_KEY } from '@transcend-io/internationalization';\nimport { DateFromISOString } from 'io-ts-types';\n\nimport * as t from 'io-ts';\nimport type { PersistedState } from '@transcend-io/persisted-state';\nimport {\n NORMALIZE_PHONE_NUMBER,\n CompletedRequestStatus,\n RequestAction,\n IdentifierType,\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\nimport { ObjByString, valuesOf } from '@transcend-io/type-utils';\n\nimport {\n CachedFileState,\n BLANK,\n BULK_APPLY,\n ColumnName,\n NONE,\n} from './constants';\nimport { AttributeKey } from '../graphql';\nimport { ColumnNameMap } from './mapCsvColumnsToApi';\nimport { splitCsvToList } from './splitCsvToList';\nimport { ParsedAttributeInput } from './parseAttributesFromString';\nimport { AttributeNameMap } from './mapColumnsToAttributes';\nimport { IdentifierNameMap } from './mapColumnsToIdentifiers';\n\n/**\n * Shape of additional identifiers\n *\n * key of object is IdentifierType\n */\nexport const AttestedExtraIdentifiers = t.record(\n t.string,\n t.array(\n t.intersection([\n t.type({\n /** Value of identifier */\n value: t.string,\n }),\n t.partial({\n /** Name of identifier - option for non-custom identifier types */\n name: t.string,\n }),\n ]),\n ),\n);\n\n/** Type override */\nexport type AttestedExtraIdentifiers = t.TypeOf<\n typeof AttestedExtraIdentifiers\n>;\n\nexport const PrivacyRequestInput = t.intersection([\n t.type({\n /** Email of user */\n email: t.string,\n /** Extra identifiers */\n attestedExtraIdentifiers: AttestedExtraIdentifiers,\n /** Core identifier for user */\n coreIdentifier: t.string,\n /** Action type being submitted */\n requestType: valuesOf(RequestAction),\n /** Type of data subject */\n subjectType: t.string,\n }),\n t.partial({\n /** Country */\n country: valuesOf(IsoCountryCode),\n /** Country sub division */\n countrySubDivision: valuesOf(IsoCountrySubdivisionCode),\n /** Attribute inputs */\n attributes: t.array(ParsedAttributeInput),\n /** The status that the request should be created as */\n status: valuesOf(CompletedRequestStatus),\n /** The time that the request was created */\n createdAt: DateFromISOString,\n /** Data silo IDs to submit for */\n dataSiloIds: t.array(t.string),\n /** Language key to map to */\n locale: valuesOf(LOCALE_KEY),\n }),\n]);\n\n/** Type override */\nexport type PrivacyRequestInput = t.TypeOf<typeof PrivacyRequestInput>;\n\n/**\n * Transform the identifier value based on type\n *\n * @param identifierValue - Value of identifier\n * @param identifierType - Type of identifier\n * @param defaultPhoneCountryCode - Default country code for phone numbers\n * @returns Post-processed identifier\n */\nexport function normalizeIdentifierValue(\n identifierValue: string,\n identifierType: IdentifierType,\n defaultPhoneCountryCode: string,\n): string {\n // Lowercase email\n if (identifierType === IdentifierType.Email) {\n return identifierValue.toLowerCase();\n }\n\n // Normalize phone number\n if (identifierType === IdentifierType.Phone) {\n const normalized = identifierValue\n .replace(NORMALIZE_PHONE_NUMBER, '')\n .replace(/[()]/g, '')\n .replace(/[–]/g, '')\n .replace(/[:]/g, '')\n .replace(/[]/g, '')\n .replace(/[A-Za-z]/g, '');\n return !normalized\n ? ''\n : normalized.startsWith('+')\n ? normalized\n : `+${defaultPhoneCountryCode}${normalized}`;\n }\n return identifierValue;\n}\n\n/**\n * Take the raw rows in a CSV upload, and map those rows to the request\n * input shape that can be passed to the Transcend API to submit a privacy\n * request.\n *\n * @param requestInputs - CSV of requests to be uploaded\n * @param state - The cached set of mapping values\n * @param options - Options\n * @returns [raw input, request input] list\n */\nexport function mapCsvRowsToRequestInputs(\n requestInputs: ObjByString[],\n state: PersistedState<typeof CachedFileState>,\n {\n columnNameMap,\n identifierNameMap,\n attributeNameMap,\n requestAttributeKeys,\n defaultPhoneCountryCode = '1', // US\n }: {\n /** Default country code */\n defaultPhoneCountryCode?: string;\n /** Mapping of column names */\n columnNameMap: ColumnNameMap;\n /** Mapping of identifier names */\n identifierNameMap: IdentifierNameMap;\n /** Mapping of attribute names */\n attributeNameMap: AttributeNameMap;\n /** Request attribute keys */\n requestAttributeKeys: AttributeKey[];\n },\n): [Record<string, string>, PrivacyRequestInput][] {\n // map the CSV to request input\n const getMappedName = (attribute: ColumnName): string =>\n state.getValue('columnNames', attribute) || columnNameMap[attribute]!;\n return requestInputs.map(\n (input): [Record<string, string>, PrivacyRequestInput] => {\n // The extra identifiers to upload for this request\n const attestedExtraIdentifiers: AttestedExtraIdentifiers = {};\n Object.entries(identifierNameMap)\n // filter out skipped identifiers\n .filter(([, columnName]) => columnName !== NONE)\n .forEach(([identifierName, columnName]) => {\n // Determine the identifier type being specified\n const identifierType = Object.values(IdentifierType).includes(\n identifierName as any, // eslint-disable-line @typescript-eslint/no-explicit-any\n )\n ? (identifierName as IdentifierType)\n : IdentifierType.Custom;\n\n // Only add the identifier if the value exists\n const identifierValue = input[columnName];\n if (identifierValue) {\n const normalized = normalizeIdentifierValue(\n identifierValue,\n identifierType,\n defaultPhoneCountryCode,\n );\n if (normalized) {\n // Initialize\n if (!attestedExtraIdentifiers[identifierType]) {\n attestedExtraIdentifiers[identifierType] = [];\n }\n\n // Add the identifier\n attestedExtraIdentifiers[identifierType]!.push({\n value: normalized,\n name: identifierName,\n });\n }\n }\n });\n\n // The extra attributes to upload for this request\n const attributes: ParsedAttributeInput[] = [];\n Object.entries(attributeNameMap)\n // filter out skipped attributes\n .filter(([, columnName]) => columnName !== NONE)\n .forEach(([attributeName, columnName]) => {\n // Only add the identifier if the value exists\n const attributeValueString = input[columnName];\n if (attributeValueString) {\n // Add the attribute\n const isMulti =\n requestAttributeKeys.find((attr) => attr.name === attributeName)\n ?.type === 'MULTI_SELECT';\n attributes.push({\n values: isMulti\n ? splitCsvToList(attributeValueString)\n : attributeValueString,\n key: attributeName,\n });\n }\n });\n\n const requestTypeColumn = getMappedName(ColumnName.RequestType);\n const dataSubjectTypeColumn = getMappedName(ColumnName.SubjectType);\n return [\n input,\n {\n email: input[getMappedName(ColumnName.Email)],\n attestedExtraIdentifiers,\n attributes,\n coreIdentifier: input[getMappedName(ColumnName.CoreIdentifier)],\n requestType:\n requestTypeColumn === BULK_APPLY\n ? state.getValue('requestTypeToRequestAction', BLANK)\n : state.getValue(\n 'requestTypeToRequestAction',\n input[requestTypeColumn],\n ),\n subjectType:\n dataSubjectTypeColumn === BULK_APPLY\n ? state.getValue('subjectTypeToSubjectName', BLANK)\n : state.getValue(\n 'subjectTypeToSubjectName',\n input[dataSubjectTypeColumn],\n ),\n ...(getMappedName(ColumnName.Locale) !== NONE &&\n input[getMappedName(ColumnName.Locale)]\n ? {\n locale: state.getValue(\n 'languageToLocale',\n input[getMappedName(ColumnName.Locale)],\n ),\n }\n : {}),\n ...(getMappedName(ColumnName.Country) !== NONE &&\n input[getMappedName(ColumnName.Country)]\n ? {\n country: state.getValue(\n 'regionToCountry',\n input[getMappedName(ColumnName.Country)],\n ) as IsoCountryCode,\n }\n : {}),\n ...(getMappedName(ColumnName.CountrySubDivision) !== NONE &&\n input[getMappedName(ColumnName.CountrySubDivision)]\n ? {\n countrySubDivision: state.getValue(\n 'regionToCountrySubDivision',\n input[getMappedName(ColumnName.CountrySubDivision)],\n ) as IsoCountrySubdivisionCode,\n }\n : {}),\n ...(getMappedName(ColumnName.RequestStatus) !== NONE &&\n state.getValue(\n 'statusToRequestStatus',\n input[getMappedName(ColumnName.RequestStatus)],\n ) !== NONE &&\n input[getMappedName(ColumnName.RequestStatus)]\n ? {\n status: state.getValue(\n 'statusToRequestStatus',\n input[getMappedName(ColumnName.RequestStatus)],\n ) as CompletedRequestStatus,\n }\n : {}),\n ...(getMappedName(ColumnName.CreatedAt) !== NONE &&\n input[getMappedName(ColumnName.CreatedAt)]\n ? {\n createdAt: new Date(input[getMappedName(ColumnName.CreatedAt)]),\n }\n : {}),\n ...(getMappedName(ColumnName.DataSiloIds) !== NONE &&\n input[getMappedName(ColumnName.DataSiloIds)]\n ? {\n dataSiloIds: splitCsvToList(\n input[getMappedName(ColumnName.DataSiloIds)],\n ),\n }\n : {}),\n },\n ];\n },\n );\n}\n","import { map } from '../bluebird';\nimport colors from 'colors';\nimport cliProgress from 'cli-progress';\n\nimport { PrivacyRequest } from '../graphql';\nimport * as t from 'io-ts';\nimport type { Got } from 'got';\nimport { decodeCodec, valuesOf } from '@transcend-io/type-utils';\nimport { logger } from '../../logger';\nimport { TableEncryptionType } from '@transcend-io/privacy-types';\n\nexport const IntlMessage = t.type({\n /** The message key */\n defaultMessage: t.string,\n /** ID */\n id: t.string,\n});\n\n/** Type */\nexport type IntlMessage = t.TypeOf<typeof IntlMessage>;\n\nexport const RequestFileMetadata = t.type({\n /** The key to pass to download the file contents */\n downloadKey: t.string,\n /** Error message related to file */\n error: t.union([t.null, t.string]),\n /** Mimetype of file */\n mimetype: t.string,\n /** Size of file, stored as string as this can be a BigInt */\n size: t.string,\n /** Name of file based on datapoint names in Transcend */\n fileName: t.string,\n /** The metadata on the datapoint */\n dataPoint: t.type({\n /** ID of datapoint */\n id: t.string,\n /** The title of datapoint */\n title: t.union([IntlMessage, t.null]),\n /** Description of datapoint */\n description: t.union([IntlMessage, t.null]),\n /** Name of datapoint */\n name: t.string,\n /** Slug of datapoint */\n slug: t.string,\n /** Table level encryption information */\n encryption: t.union([valuesOf(TableEncryptionType), t.null]),\n /** The name of the data silo */\n dataSilo: t.type({\n /** ID of the data silo */\n id: t.string,\n /** The title of the data silo */\n title: t.string,\n /** The description of the data silo */\n description: t.string,\n /** The type of the data silo */\n type: t.string,\n /** The outer type of the data silo */\n outerType: t.union([t.string, t.null]),\n }),\n /** The path to the datapoint if a database (e.g. name of schema) */\n path: t.array(t.string),\n }),\n});\n\n/** Type override */\nexport type RequestFileMetadata = t.TypeOf<typeof RequestFileMetadata>;\n\nexport const RequestFileMetadataResponse = t.type({\n /** The list of file metadata */\n nodes: t.array(RequestFileMetadata),\n /** The total number of file metadata */\n totalCount: t.number,\n /** Links to next pages */\n _links: t.partial({\n /** The link to the next page of file metadata */\n next: t.union([t.string, t.null]),\n /** The link to the previous page of file metadata */\n previous: t.union([t.string, t.null]),\n }),\n});\n\n/** Type override */\nexport type RequestFileMetadataResponse = t.TypeOf<\n typeof RequestFileMetadataResponse\n>;\n\n/**\n * Given a list of privacy requests, download the file metadata\n * for these requests - this is useful to prepare the files in a\n * data access request for download.\n *\n * @param requests - The list of privacy requests to download files for\n * @param options - Options\n * @returns The number of requests canceled\n */\nexport async function getFileMetadataForPrivacyRequests(\n requests: Pick<PrivacyRequest, 'id' | 'status'>[],\n {\n sombra,\n concurrency = 5,\n limit = 100,\n }: {\n /** Sombra instance */\n sombra: Got;\n /** Number of files to pull at once */\n limit?: number;\n /** Concurrency limit for approving */\n concurrency?: number;\n },\n): Promise<[Pick<PrivacyRequest, 'id' | 'status'>, RequestFileMetadata[]][]> {\n logger.info(\n colors.magenta(`Pulling file metadata for ${requests.length} requests`),\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 // Start timer\n let total = 0;\n progressBar.start(requests.length, 0);\n\n // Loop over the requests\n const results = await map(\n requests,\n async (\n requestToDownload,\n ): Promise<\n [Pick<PrivacyRequest, 'id' | 'status'>, RequestFileMetadata[]]\n > => {\n const localResults: RequestFileMetadata[] = [];\n\n // Paginate over the file metadata for this request\n let shouldContinue = true;\n let offset = 0;\n while (shouldContinue) {\n let response: RequestFileMetadataResponse;\n try {\n // Grab the file metadata for this request\n\n const rawResponse = await sombra\n .get(\n `v1/data-subject-request/${requestToDownload.id}/download-keys`,\n {\n searchParams: {\n limit,\n offset,\n },\n },\n )\n .json();\n response = decodeCodec(RequestFileMetadataResponse, rawResponse);\n localResults.push(...response.nodes);\n\n // Increase offset and break if no more pages\n offset += limit;\n shouldContinue =\n // eslint-disable-next-line no-underscore-dangle\n !!response._links.next && response.nodes.length === limit;\n } catch (err) {\n throw new Error(\n `Received an error from server: ${\n err?.response?.body || err?.message\n }`,\n );\n }\n }\n\n total += 1;\n progressBar.update(total);\n return [requestToDownload, localResults];\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 downloaded file metadata ${requests.length} requests in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n\n return results;\n}\n","import { map } from '../bluebird';\nimport colors from 'colors';\nimport { RequestFileMetadata } from './getFileMetadataForPrivacyRequests';\nimport type { Got } from 'got';\nimport { logger } from '../../logger';\n\n/**\n * This function will take in a set of file metadata for privacy requests\n * call the Transcend API to stream the file metadata for these requests\n * and pass that through a callback function\n *\n * @param fileMetadata - Metadata to download\n * @param options - Options for the request\n */\nexport async function streamPrivacyRequestFiles(\n fileMetadata: RequestFileMetadata[],\n {\n requestId,\n sombra,\n onFileDownloaded,\n concurrency = 20,\n }: {\n /** Request ID for logging */\n requestId: string;\n /** Sombra got instance */\n sombra: Got;\n /** Handler on each file */\n onFileDownloaded: (metadata: RequestFileMetadata, stream: Buffer) => void;\n /** Concurrent downloads at once */\n concurrency?: number;\n },\n): Promise<void> {\n // Loop over each file\n await map(\n fileMetadata,\n async (metadata) => {\n try {\n // Construct the stream\n await sombra\n .get('v1/files', {\n searchParams: {\n downloadKey: metadata.downloadKey,\n },\n })\n .buffer()\n .then((fileResponse) => onFileDownloaded(metadata, fileResponse));\n } catch (err) {\n if (err?.response?.body?.includes('fileMetadata#verify')) {\n logger.error(\n colors.red(\n `Failed to pull file for: ${metadata.fileName} (request:${requestId}) - JWT expired. ` +\n 'This likely means that the file is no longer available. ' +\n 'Try restarting the request from scratch in Transcend Admin Dashboard. ' +\n 'Skipping the download of this file.',\n ),\n );\n return;\n }\n throw new Error(\n `Received an error from server: ${\n err?.response?.body || err?.message\n }`,\n );\n }\n },\n {\n concurrency,\n },\n );\n}\n","import { map } from '../bluebird';\nimport { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport {\n fetchAllRequests,\n buildTranscendGraphQLClient,\n createSombraGotInstance,\n makeGraphQLRequest,\n APPROVE_PRIVACY_REQUEST,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\nimport { getFileMetadataForPrivacyRequests } from './getFileMetadataForPrivacyRequests';\nimport { streamPrivacyRequestFiles } from './streamPrivacyRequestFiles';\n\n/**\n * Download a set of privacy requests to disk\n *\n * @param options - Options\n * @returns The number of requests canceled\n */\nexport async function downloadPrivacyRequestFiles({\n auth,\n folderPath,\n requestIds,\n createdAtBefore,\n sombraAuth,\n createdAtAfter,\n statuses = [RequestStatus.Approving, RequestStatus.Downloadable],\n concurrency = 5,\n transcendUrl = DEFAULT_TRANSCEND_API,\n approveAfterDownload = false,\n}: {\n /** The folder path to download the files to */\n folderPath: string;\n /** Transcend API key authentication */\n auth: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** The request statuses to cancel */\n statuses?: RequestStatus[];\n /** The set of privacy requests to cancel */\n requestIds?: string[];\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** When true, approve any requests in Transcend that are in status=APPROVING */\n approveAfterDownload?: boolean;\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 // Create sombra instance to communicate with\n const sombra = await createSombraGotInstance(transcendUrl, auth, sombraAuth);\n\n // Create the folder if it does not exist\n if (!existsSync(folderPath)) {\n mkdirSync(folderPath);\n }\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: [RequestAction.Access],\n createdAtBefore,\n createdAtAfter,\n statuses,\n requestIds,\n });\n\n // Download the file metadata for each request\n const requestFileMetadata = await getFileMetadataForPrivacyRequests(\n allRequests,\n {\n sombra,\n concurrency,\n },\n );\n\n // Start timer for download process\n const t0 = new Date().getTime();\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n let total = 0;\n let totalApproved = 0;\n progressBar.start(allRequests.length, 0);\n\n // Download the files for each request\n await map(\n requestFileMetadata,\n async ([request, metadata]) => {\n // Create a new folder to store request files\n const requestFolder = join(folderPath, request.id);\n if (!existsSync(requestFolder)) {\n mkdirSync(requestFolder);\n }\n\n // Stream each file to disk\n await streamPrivacyRequestFiles(metadata, {\n sombra,\n requestId: request.id,\n onFileDownloaded: (fil, stream) => {\n // Ensure a folder exists for the file\n // filename looks like Health/heartbeat.csv\n const filePath = join(requestFolder, fil.fileName);\n const folder = dirname(filePath);\n if (!existsSync(folder)) {\n mkdirSync(folder, { recursive: true });\n }\n\n // Write to disk\n writeFileSync(filePath, stream);\n },\n });\n\n // Approve the request if requested\n if (approveAfterDownload && request.status === RequestStatus.Approving) {\n await makeGraphQLRequest(client, APPROVE_PRIVACY_REQUEST, {\n input: { requestId: request.id },\n });\n totalApproved += 1;\n }\n\n // Increment the progress bar\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 downloaded ${total} requests in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n if (totalApproved > 0) {\n logger.info(\n colors.green(`Approved ${totalApproved} requests in Transcend.`),\n );\n }\n return allRequests.length;\n}\n","import * as t from 'io-ts';\nimport { uniq } from 'lodash-es';\nimport { valuesOf, decodeCodec } from '@transcend-io/type-utils';\nimport {\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n RequestAction,\n RequestStatus,\n} from '@transcend-io/privacy-types';\nimport type { Got } from 'got';\nimport { PrivacyRequestInput } from './mapCsvRowsToRequestInputs';\nimport { ParsedAttributeInput } from './parseAttributesFromString';\n\nexport const PrivacyRequestResponse = t.type({\n id: t.string,\n link: t.string,\n status: valuesOf(RequestStatus),\n type: valuesOf(RequestAction),\n subjectType: t.string,\n email: t.union([t.null, t.string]),\n coreIdentifier: t.string,\n isSilent: t.boolean,\n isTest: t.boolean,\n country: t.union([t.null, valuesOf(IsoCountryCode)]),\n countrySubDivision: t.union([t.null, valuesOf(IsoCountrySubdivisionCode)]),\n attributeValues: t.array(\n t.type({\n attributeKey: t.type({ name: t.string }),\n name: t.string,\n }),\n ),\n});\n\n/** Type override */\nexport type PrivacyRequestResponse = t.TypeOf<typeof PrivacyRequestResponse>;\n\n/**\n * Submit a privacy request to the Transcend API\n *\n * @param sombra - Sombra instance configured to make requests\n * @param input - Request input\n * @param options - Additional options\n * @returns Successfully submitted request\n */\nexport async function submitPrivacyRequest(\n sombra: Got,\n input: PrivacyRequestInput,\n {\n details = '',\n isTest = false,\n emailIsVerified = true,\n skipSendingReceipt = false,\n isSilent = true,\n additionalAttributes = [],\n }: {\n /** Whether or not the request is a test request */\n isTest?: boolean;\n /** Whether or not the request is in silent mode */\n isSilent?: boolean;\n /** Whether the email is verified up front */\n emailIsVerified?: boolean;\n /** When true, skip sending of the email receipt */\n skipSendingReceipt?: boolean;\n /** Request details */\n details?: string;\n /** Additional attributes to tag the requests with */\n additionalAttributes?: ParsedAttributeInput[];\n } = {},\n): Promise<PrivacyRequestResponse> {\n // Merge the per-request attributes with the\n // global attributes\n const mergedAttributes = [...additionalAttributes];\n (input.attributes || []).forEach((attribute) => {\n const existing = mergedAttributes.find(\n (attr) => attr.key === attribute.key,\n );\n if (existing) {\n existing.values.push(...attribute.values);\n existing.values = uniq(existing.values);\n } else {\n mergedAttributes.push(attribute);\n }\n });\n\n // Make the GraphQL request\n let response: unknown;\n try {\n response = await sombra\n .post('v1/data-subject-request', {\n json: {\n type: input.requestType,\n subject: {\n coreIdentifier: input.coreIdentifier,\n email: input.email,\n emailIsVerified,\n attestedExtraIdentifiers: input.attestedExtraIdentifiers,\n },\n subjectType: input.subjectType,\n isSilent,\n isTest,\n skipSendingReceipt,\n ...(input.locale ? { locale: input.locale } : {}),\n details,\n attributes: mergedAttributes,\n ...(input.country || input.countrySubDivision\n ? {\n region: {\n ...(input.country\n ? {\n country: input.country,\n }\n : input.countrySubDivision\n ? { country: input.countrySubDivision.split('-')[0] }\n : {}),\n ...(input.countrySubDivision\n ? { countrySubDivision: input.countrySubDivision }\n : {}),\n },\n }\n : {}),\n ...(input.createdAt ? { createdAt: input.createdAt } : {}),\n ...(input.dataSiloIds ? { dataSiloIds: input.dataSiloIds } : {}),\n ...(input.status ? { completedRequestStatus: input.status } : {}),\n },\n })\n .json();\n } catch (err) {\n throw new Error(\n `Received an error from server: ${err?.response?.body || err?.message}`,\n );\n }\n\n const { request: requestResponse } = decodeCodec(\n t.type({\n request: PrivacyRequestResponse,\n }),\n response,\n );\n return requestResponse;\n}\n","import { map } from '../bluebird';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport {\n RequestAction,\n RequestOrigin,\n RequestStatus,\n} from '@transcend-io/privacy-types';\nimport {\n UPDATE_PRIVACY_REQUEST,\n fetchAllRequests,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n APPROVE_PRIVACY_REQUEST,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Approve a set of privacy requests\n *\n * @param options - Options\n * @returns The number of requests approved\n */\nexport async function approvePrivacyRequests({\n requestActions,\n requestOrigins,\n auth,\n silentModeBefore,\n createdAtAfter,\n createdAtBefore,\n concurrency = 50,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** The request origins that should be restarted */\n requestOrigins?: RequestOrigin[];\n /** Transcend API key authentication */\n auth: string;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** Mark these requests as silent mode if they were created before this date */\n silentModeBefore?: Date;\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses: [RequestStatus.Approving],\n createdAtAfter,\n origins: requestOrigins,\n createdAtBefore,\n });\n\n // Notify Transcend\n logger.info(colors.magenta(`Approving \"${allRequests.length}\" requests.`));\n\n let total = 0;\n let skipped = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToApprove) => {\n // update request to silent mode if silentModeBefore is defined\n // and the request was created before silentModeBefore\n if (\n silentModeBefore &&\n new Date(silentModeBefore) > new Date(requestToApprove.createdAt)\n ) {\n await makeGraphQLRequest(client, UPDATE_PRIVACY_REQUEST, {\n input: {\n id: requestToApprove.id,\n isSilent: true,\n },\n });\n }\n\n try {\n // approve the request\n await makeGraphQLRequest(client, APPROVE_PRIVACY_REQUEST, {\n input: { requestId: requestToApprove.id },\n });\n } catch (err) {\n if (err.message.includes('Request must be in an approving state,')) {\n skipped += 1;\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 if (skipped > 0) {\n logger.info(colors.yellow(`${skipped} requests were skipped.`));\n }\n logger.info(\n colors.green(\n `Successfully approved ${total} requests in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n return allRequests.length;\n}\n","import { map } from '../bluebird';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport { RequestAction } from '@transcend-io/privacy-types';\nimport {\n NOTIFY_ADDITIONAL_TIME,\n fetchAllRequests,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n fetchAllTemplates,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Mark a set of privacy requests to be in silent mode.\n * Note requests in silent mode are ignored\n *\n * @param options - Options\n * @returns The number of requests marked silent\n */\nexport async function notifyPrivacyRequestsAdditionalTime({\n requestActions = Object.values(RequestAction),\n auth,\n requestIds,\n createdAtBefore,\n days = 45,\n daysLeft = 10,\n createdAtAfter,\n emailTemplate = 'Additional Time Needed',\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions?: RequestAction[];\n /** Filter for requests created before this date */\n createdAtBefore: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Email template */\n emailTemplate?: string;\n /** Transcend API key authentication */\n auth: string;\n /** Number of days to extend request by */\n days?: number;\n /**\n * Only notify requests that have less than this number of days until they are considered expired.\n * This allows for re-running the command without notifying the same users multiple times\n */\n daysLeft?: number;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** The set of privacy requests to notify */\n requestIds?: string[];\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Grab the template with that title\n const matchingTemplates = await fetchAllTemplates(client, emailTemplate);\n const exactTemplateMatch = matchingTemplates.find(\n (template) => template.title === emailTemplate,\n );\n if (!exactTemplateMatch) {\n throw new Error(`Failed to find a template with title: \"${emailTemplate}\"`);\n }\n\n // Pull in the requests\n let allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n createdAtBefore,\n createdAtAfter,\n isSilent: false,\n isClosed: false,\n requestIds,\n });\n\n // Filter requests by daysLeft\n allRequests = allRequests.filter(\n (request) =>\n typeof request.daysRemaining === 'number' &&\n request.daysRemaining < daysLeft,\n );\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Notifying \"${allRequests.length}\" that more time is needed.`,\n ),\n );\n\n let total = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToNotify) => {\n await makeGraphQLRequest(client, NOTIFY_ADDITIONAL_TIME, {\n input: {\n requestId: requestToNotify.id,\n template: exactTemplateMatch.template.defaultMessage,\n subject: exactTemplateMatch.subject.defaultMessage,\n additionalTime: days,\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 marked ${total} requests as silent mode in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n return allRequests.length;\n}\n","import type { GraphQLClient } from 'graphql-request';\nimport inquirer from 'inquirer';\nimport { INITIALIZER, makeGraphQLRequest, Initializer } from '../graphql';\nimport { CachedFileState, IDENTIFIER_BLOCK_LIST } from './constants';\nimport { fuzzyMatchColumns } from './fuzzyMatchColumns';\nimport type { PersistedState } from '@transcend-io/persisted-state';\n\n/**\n * Mapping from identifier name to request input parameter\n */\nexport type IdentifierNameMap = {\n [k in string]: string;\n};\n\n/**\n * Create a mapping from the identifier names that can be included\n * at request submission, to the names of the columns that map to those\n * identifiers.\n *\n * @param client - GraphQL client\n * @param columnNames - The set of all column names\n * @param state - Cached state of this mapping\n * @returns Mapping from identifier name to column name\n */\nexport async function mapColumnsToIdentifiers(\n client: GraphQLClient,\n columnNames: string[],\n state: PersistedState<typeof CachedFileState>,\n): Promise<IdentifierNameMap> {\n // Grab the initializer\n const { initializer } = await makeGraphQLRequest<{\n /** Query response */\n initializer: Initializer;\n }>(client, INITIALIZER);\n\n // Determine the columns that should be mapped\n const columnQuestions = initializer.identifiers.filter(\n ({ name }) =>\n !state.getValue('identifierNames', name) &&\n !IDENTIFIER_BLOCK_LIST.includes(name),\n );\n\n // Skip mapping when everything is mapped\n const identifierNameMap =\n columnQuestions.length === 0\n ? {}\n : // prompt questions to map columns\n await inquirer.prompt<{\n [k in string]: string;\n }>(\n columnQuestions.map(({ name }) => {\n const matches = fuzzyMatchColumns(columnNames, name, false);\n return {\n name,\n message: `Choose the column that will be used to map in the identifier: ${name}`,\n type: 'list',\n default: matches[0],\n choices: matches,\n };\n }),\n );\n await Promise.all(\n Object.entries(identifierNameMap).map(([k, v]) =>\n state.setValue(v, 'identifierNames', k),\n ),\n );\n\n return {\n ...state.getValue('identifierNames'),\n ...identifierNameMap,\n };\n}\n","import { map } from '../bluebird';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport {\n UPDATE_PRIVACY_REQUEST,\n fetchAllRequests,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n CANCEL_PRIVACY_REQUEST,\n fetchAllTemplates,\n Template,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Cancel a set of privacy requests\n *\n * @param options - Options\n * @returns The number of requests canceled\n */\nexport async function cancelPrivacyRequests({\n requestActions,\n cancellationTitle,\n auth,\n requestIds,\n silentModeBefore,\n createdAtBefore,\n createdAtAfter,\n statuses = [\n RequestStatus.Compiling,\n RequestStatus.RequestMade,\n RequestStatus.Delayed,\n RequestStatus.Approving,\n RequestStatus.Secondary,\n RequestStatus.Enriching,\n RequestStatus.Waiting,\n RequestStatus.SecondaryApproving,\n ],\n concurrency = 50,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** Transcend API key authentication */\n auth: string;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** The request statuses to cancel */\n statuses?: RequestStatus[];\n /** The set of privacy requests to cancel */\n requestIds?: string[];\n /** Mark these requests as silent mode if they were created before this date */\n silentModeBefore?: Date;\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** The email template to use when canceling the requests */\n cancellationTitle?: 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 // Grab the template with that title\n let cancelationTemplate: Template | undefined;\n if (cancellationTitle) {\n const matchingTemplates = await fetchAllTemplates(\n client,\n cancellationTitle,\n );\n const exactTitleMatch = matchingTemplates.find(\n (template) => template.title === cancellationTitle,\n );\n if (!exactTitleMatch) {\n throw new Error(\n `Failed to find a template with title: \"${cancellationTitle}\"`,\n );\n }\n cancelationTemplate = exactTitleMatch;\n }\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n createdAtBefore,\n createdAtAfter,\n statuses,\n requestIds,\n });\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Canceling \"${allRequests.length}\" requests${\n cancelationTemplate\n ? ` Using template: ${cancelationTemplate.title}`\n : ''\n }.`,\n ),\n );\n\n let total = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToCancel) => {\n // update request to silent mode if silentModeBefore is defined\n // and the request was created before silentModeBefore\n if (\n silentModeBefore &&\n new Date(silentModeBefore) > new Date(requestToCancel.createdAt)\n ) {\n await makeGraphQLRequest(client, UPDATE_PRIVACY_REQUEST, {\n input: {\n id: requestToCancel.id,\n isSilent: true,\n },\n });\n }\n\n // cancel the request\n await makeGraphQLRequest(client, CANCEL_PRIVACY_REQUEST, {\n input: {\n requestId: requestToCancel.id,\n ...(cancelationTemplate\n ? {\n subject: `Re: ${cancelationTemplate.subject.defaultMessage}`,\n template: cancelationTemplate.template.defaultMessage,\n }\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 canceled ${total} requests in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n return allRequests.length;\n}\n","import type { GraphQLClient } from 'graphql-request';\nimport inquirer from 'inquirer';\nimport { AttributeKey } from '../graphql';\nimport { CachedFileState } from './constants';\nimport { fuzzyMatchColumns } from './fuzzyMatchColumns';\nimport type { PersistedState } from '@transcend-io/persisted-state';\n\n/**\n * Mapping from attribute name to request input parameter\n */\nexport type AttributeNameMap = {\n [k in string]: string;\n};\n\n/**\n * Create a mapping from the attributes names that can be included\n * at request submission, to the names of the columns that map to those\n * attributes.\n *\n * @param client - GraphQL client\n * @param columnNames - The set of all column names\n * @param state - Cached state of this mapping\n * @param requestAttributeKeys - Attribute keys to map\n * @returns Mapping from attributes name to column name\n */\nexport async function mapColumnsToAttributes(\n client: GraphQLClient,\n columnNames: string[],\n state: PersistedState<typeof CachedFileState>,\n requestAttributeKeys: AttributeKey[],\n): Promise<AttributeNameMap> {\n // Determine the columns that should be mapped\n const columnQuestions = requestAttributeKeys.filter(\n ({ name }) => !state.getValue('attributeNames', name),\n );\n\n // Skip mapping when everything is mapped\n const attributeNameMap =\n columnQuestions.length === 0\n ? {}\n : // prompt questions to map columns\n await inquirer.prompt<{\n [k in string]: string;\n }>(\n columnQuestions.map(({ name }) => {\n const matches = fuzzyMatchColumns(columnNames, name, false);\n return {\n name,\n message: `Choose the column that will be used to map in the attribute: ${name}`,\n type: 'list',\n default: matches[0],\n choices: matches,\n };\n }),\n );\n await Promise.all(\n Object.entries(attributeNameMap).map(([k, v]) =>\n state.setValue(v, 'attributeNames', k),\n ),\n );\n\n return {\n ...state.getValue('attributeNames'),\n ...attributeNameMap,\n };\n}\n","const CLIENT_ERROR = /{\\\\\"message\\\\\":\\\\\"(.+?)\\\\\",/;\n\n/**\n * Extract a client error from the request\n *\n * @param err - Error message\n * @returns Client error or null\n */\nexport function extractClientError(err: string): string | null {\n return CLIENT_ERROR.test(err) ? CLIENT_ERROR.exec(err)![1] : null;\n}\n","/* eslint-disable max-lines */\nimport colors from 'colors';\nimport { map } from '../bluebird';\nimport * as t from 'io-ts';\nimport { uniq } from 'lodash-es';\nimport cliProgress from 'cli-progress';\nimport { join } from 'node:path';\nimport { PersistedState } from '@transcend-io/persisted-state';\nimport { logger } from '../../logger';\nimport {\n createSombraGotInstance,\n buildTranscendGraphQLClient,\n fetchAllRequestAttributeKeys,\n} from '../graphql';\nimport { mapRequestEnumValues } from './mapRequestEnumValues';\nimport { CachedRequestState, CachedFileState } from './constants';\nimport { mapCsvColumnsToApi } from './mapCsvColumnsToApi';\nimport { parseAttributesFromString } from './parseAttributesFromString';\nimport { readCsv } from './readCsv';\nimport { submitPrivacyRequest } from './submitPrivacyRequest';\nimport { mapColumnsToAttributes } from './mapColumnsToAttributes';\nimport { mapColumnsToIdentifiers } from './mapColumnsToIdentifiers';\nimport { mapCsvRowsToRequestInputs } from './mapCsvRowsToRequestInputs';\nimport { filterRows } from './filterRows';\nimport { extractClientError } from './extractClientError';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Upload a set of privacy requests from CSV\n *\n * @param options - Options\n */\nexport async function uploadPrivacyRequestsFromCsv({\n cacheFilepath,\n requestReceiptFolder,\n file,\n auth,\n sombraAuth,\n concurrency = 100,\n defaultPhoneCountryCode = '1', // USA\n transcendUrl = DEFAULT_TRANSCEND_API,\n attributes = [],\n emailIsVerified = true,\n skipFilterStep = false,\n skipSendingReceipt = true,\n isTest = false,\n isSilent = true,\n debug = false,\n dryRun = false,\n}: {\n /** File to cache metadata about mapping of CSV shape to script */\n cacheFilepath: string;\n /** File where request receipts are stored */\n requestReceiptFolder: string;\n /** CSV file path */\n file: string;\n /** Transcend API key authentication */\n auth: string;\n /** Default country code for phone numbers */\n defaultPhoneCountryCode?: string;\n /** Concurrency to upload in */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** Include debug logs */\n debug?: boolean;\n /** Skip the step where requests are filtered */\n skipFilterStep?: boolean;\n /** Whether test requests are being uploaded */\n isTest?: boolean;\n /** Whether requests are uploaded in silent mode */\n isSilent?: boolean;\n /** Whether to send the email receipt */\n skipSendingReceipt?: boolean;\n /** Whether the email was verified up front */\n emailIsVerified?: boolean;\n /** Attributes string pre-parse */\n attributes?: string[];\n /** Whether a dry run is happening */\n dryRun?: boolean;\n}): Promise<void> {\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Parse out the extra attributes to apply to all requests uploaded\n const parsedAttributes = parseAttributesFromString(attributes);\n\n // Create a new state to persist the metadata that\n // maps the request inputs to the Transcend API shape\n const state = new PersistedState(cacheFilepath, CachedFileState, {\n columnNames: {},\n requestTypeToRequestAction: {},\n subjectTypeToSubjectName: {},\n languageToLocale: {},\n statusToRequestStatus: {},\n identifierNames: {},\n attributeNames: {},\n regionToCountrySubDivision: {},\n regionToCountry: {},\n });\n\n // Create a new state file to store the requests from this run\n const requestCacheFile = join(\n requestReceiptFolder,\n `tr-request-upload-${new Date().toISOString()}-${file\n .split('/')\n .pop()}`.replace('.csv', '.json'),\n );\n const requestState = new PersistedState(\n requestCacheFile,\n CachedRequestState,\n {\n successfulRequests: [],\n duplicateRequests: [],\n failingRequests: [],\n },\n );\n\n // Create sombra instance to communicate with\n const sombra = await createSombraGotInstance(transcendUrl, auth, sombraAuth);\n\n // Read in the list of integration requests\n const requestsList = readCsv(file, t.record(t.string, t.string));\n const columnNames = uniq(requestsList.map((x) => Object.keys(x)).flat());\n\n // Log out an example request\n if (requestsList.length === 0) {\n throw new Error(\n 'No Requests found in list! Ensure the first row of the CSV is a header and the rest are requests.',\n );\n }\n if (debug) {\n const firstRequest = requestsList[0];\n logger.info(\n colors.magenta(`First request: ${JSON.stringify(firstRequest, null, 2)}`),\n );\n }\n // Determine what rows in the CSV should be imported\n // Choose columns that contain metadata to filter the requests\n const filteredRequestList = skipFilterStep\n ? requestsList\n : await filterRows(requestsList);\n\n // Build a GraphQL client\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n // Grab the request attributes\n const requestAttributeKeys = await fetchAllRequestAttributeKeys(client);\n // Determine the columns that should be mapped\n const columnNameMap = await mapCsvColumnsToApi(columnNames, state);\n const identifierNameMap = await mapColumnsToIdentifiers(\n client,\n columnNames,\n state,\n );\n const attributeNameMap = await mapColumnsToAttributes(\n client,\n columnNames,\n state,\n requestAttributeKeys,\n );\n await mapRequestEnumValues(client, filteredRequestList, {\n state,\n columnNameMap,\n });\n\n // map the CSV to request input\n const requestInputs = mapCsvRowsToRequestInputs(filteredRequestList, state, {\n defaultPhoneCountryCode,\n columnNameMap,\n identifierNameMap,\n attributeNameMap,\n requestAttributeKeys,\n });\n\n // start the progress bar with a total value of 200 and start value of 0\n if (!debug) {\n progressBar.start(requestInputs.length, 0);\n }\n let total = 0;\n // Submit each request\n await map(\n requestInputs,\n async ([rawRow, requestInput], ind) => {\n // The identifier to log, only include personal data if debug mode is on\n const requestLogId = debug\n ? `email:${requestInput.email} | coreIdentifier:${requestInput.coreIdentifier}`\n : `row:${ind.toString()}`;\n\n if (debug) {\n logger.info(\n colors.magenta(\n `[${ind + 1}/${requestInputs.length}] Importing: ${JSON.stringify(\n requestInput,\n null,\n 2,\n )}`,\n ),\n );\n }\n\n // Skip on dry run\n if (dryRun) {\n logger.info(\n colors.magenta('Bailing out on dry run because dryRun is set'),\n );\n return;\n }\n\n try {\n // Make the GraphQL request to submit the privacy request\n const requestResponse = await submitPrivacyRequest(\n sombra,\n requestInput,\n {\n details: `Uploaded by Transcend Cli: \"tr-request-upload\" : ${JSON.stringify(\n rawRow,\n null,\n 2,\n )}`,\n isTest,\n emailIsVerified,\n skipSendingReceipt,\n isSilent,\n additionalAttributes: parsedAttributes,\n },\n );\n\n // Log success\n if (debug) {\n logger.info(\n colors.green(\n `[${ind + 1}/${\n requestInputs.length\n }] Successfully submitted the test data subject request: \"${requestLogId}\"`,\n ),\n );\n logger.info(\n colors.green(\n `[${ind + 1}/${requestInputs.length}] View it at: \"${\n requestResponse.link\n }\"`,\n ),\n );\n }\n\n // Cache successful upload\n const successfulRequests = requestState.getValue('successfulRequests');\n successfulRequests.push({\n id: requestResponse.id,\n link: requestResponse.link,\n rowIndex: ind,\n coreIdentifier: requestResponse.coreIdentifier,\n attemptedAt: new Date().toISOString(),\n });\n await requestState.setValue(successfulRequests, 'successfulRequests');\n } catch (err) {\n const msg = `${err.message} - ${JSON.stringify(\n err.response?.body,\n null,\n 2,\n )}`;\n const clientError = extractClientError(msg);\n\n if (\n clientError === 'Client error: You have already made this request.'\n ) {\n if (debug) {\n logger.info(\n colors.yellow(\n `[${ind + 1}/${\n requestInputs.length\n }] Skipping request as it is a duplicate`,\n ),\n );\n }\n const duplicateRequests = requestState.getValue('duplicateRequests');\n duplicateRequests.push({\n coreIdentifier: requestInput.coreIdentifier,\n rowIndex: ind,\n attemptedAt: new Date().toISOString(),\n });\n await requestState.setValue(duplicateRequests, 'duplicateRequests');\n } else {\n const failingRequests = requestState.getValue('failingRequests');\n failingRequests.push({\n ...requestInput,\n rowIndex: ind,\n error: clientError || msg,\n attemptedAt: new Date().toISOString(),\n });\n await requestState.setValue(failingRequests, 'failingRequests');\n if (debug) {\n logger.error(colors.red(clientError || msg));\n logger.error(\n colors.red(\n `[${ind + 1}/${\n requestInputs.length\n }] Failed to submit request for: \"${requestLogId}\"`,\n ),\n );\n }\n }\n }\n\n total += 1;\n if (!debug) {\n progressBar.update(total);\n }\n },\n {\n concurrency,\n },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n // Log completion time\n logger.info(\n colors.green(`Completed upload in \"${totalTime / 1000}\" seconds.`),\n );\n\n // Log duplicates\n if (requestState.getValue('duplicateRequests').length > 0) {\n logger.info(\n colors.yellow(\n `Encountered \"${\n requestState.getValue('duplicateRequests').length\n }\" duplicate requests. ` +\n `See \"${requestCacheFile}\" to review the core identifiers for these requests.`,\n ),\n );\n }\n\n // Log errors\n if (requestState.getValue('failingRequests').length > 0) {\n logger.error(\n colors.red(\n `Encountered \"${\n requestState.getValue('failingRequests').length\n }\" errors. ` +\n `See \"${requestCacheFile}\" to review the error messages and inputs.`,\n ),\n );\n process.exit(1);\n }\n}\n/* eslint-enable max-lines */\n","import * as t from 'io-ts';\nimport { groupBy } from 'lodash-es';\nimport { apply, decodeCodec } from '@transcend-io/type-utils';\nimport { IdentifierType } from '@transcend-io/privacy-types';\nimport type { Got } from 'got';\nimport { PrivacyRequest, RequestIdentifier } from '../graphql';\nimport { IDENTIFIER_BLOCK_LIST } from './constants';\nimport { PrivacyRequestResponse } from './submitPrivacyRequest';\n\n/**\n * Restart a privacy request to the Transcend API\n *\n * @param sombra - Sombra instance configured to make requests\n * @param request - Request to restart\n * @param input - Request input\n * @returns Successfully submitted request\n */\nexport async function restartPrivacyRequest(\n sombra: Got,\n request: PrivacyRequest,\n {\n sendEmailReceipt = false,\n skipWaitingPeriod = false,\n emailIsVerified = true,\n requestIdentifiers = [],\n }: {\n /** List of request identifiers to include */\n requestIdentifiers?: RequestIdentifier[];\n /** When true, send an email receipt to data subject */\n sendEmailReceipt?: boolean;\n /** Whether the email is verified */\n emailIsVerified?: boolean;\n /** Whether to skip waiting period */\n skipWaitingPeriod?: boolean;\n } = {},\n): Promise<PrivacyRequestResponse> {\n // Make the GraphQL request\n const response = await sombra\n .post('v1/data-subject-request', {\n json: {\n type: request.type,\n subject: {\n coreIdentifier: request.coreIdentifier,\n email: request.email,\n emailIsVerified,\n ...(requestIdentifiers.length > 0\n ? {\n attestedExtraIdentifiers: apply(\n groupBy(\n requestIdentifiers\n .filter(\n (ri) =>\n // these are already submitted above\n !(\n ri.name === 'email' && ri.value === request.email\n ) && !IDENTIFIER_BLOCK_LIST.includes(ri.name),\n )\n .map((ri) => ({\n ...ri,\n type: Object.values(IdentifierType).includes(\n ri.name as any, // eslint-disable-line @typescript-eslint/no-explicit-any\n )\n ? ri.name\n : IdentifierType.Custom,\n })),\n 'type',\n ),\n (values, type) =>\n values.map(({ name, value }) => ({\n ...(type === IdentifierType.Custom ? { name } : {}),\n value,\n })),\n ),\n }\n : {}),\n },\n requestId: request.id,\n subjectType: request.subjectType,\n isSilent: request.isSilent,\n isTest: request.isTest,\n locale: request.locale,\n skipWaitingPeriod,\n createdAt: request.createdAt,\n details: `Restarted by Transcend cli: \"tr-request-restart\" - ${request.details}`,\n skipSendingReceipt: !sendEmailReceipt,\n },\n })\n .json();\n\n const { request: requestResponse } = decodeCodec(\n t.type({\n request: PrivacyRequestResponse,\n }),\n response,\n );\n return requestResponse;\n}\n","import { PersistedState } from '@transcend-io/persisted-state';\nimport { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport { map } from '../bluebird';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\nimport * as t from 'io-ts';\nimport { difference } from 'lodash-es';\nimport { join, resolve } from 'node:path';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\nimport {\n buildTranscendGraphQLClient,\n createSombraGotInstance,\n fetchAllRequestIdentifiers,\n fetchAllRequests,\n} from '../graphql';\nimport { logger } from '../../logger';\nimport { SuccessfulRequest } from './constants';\nimport { extractClientError } from './extractClientError';\nimport { restartPrivacyRequest } from './restartPrivacyRequest';\n\n/** Minimal state we need to keep a list of requests */\nconst ErrorRequest = t.intersection([\n SuccessfulRequest,\n t.type({\n error: t.string,\n }),\n]);\n\n/** Type override */\ntype ErrorRequest = t.TypeOf<typeof ErrorRequest>;\n\n/** Persist this data between runs of the script */\nconst CachedRequestState = t.type({\n restartedRequests: t.array(SuccessfulRequest),\n failingRequests: t.array(ErrorRequest),\n});\n\n/**\n * Upload a set of privacy requests from CSV\n *\n * @param options - Options\n */\nexport async function bulkRestartRequests({\n requestReceiptFolder,\n auth,\n sombraAuth,\n requestActions,\n requestStatuses,\n createdAtBefore,\n createdAtAfter,\n transcendUrl = DEFAULT_TRANSCEND_API,\n requestIds = [],\n createdAt = new Date(),\n silentModeBefore,\n sendEmailReceipt = false,\n emailIsVerified = true,\n copyIdentifiers = false,\n skipWaitingPeriod = false,\n concurrency = 20,\n}: {\n /** Actions to filter for */\n requestActions: RequestAction[];\n /** Statues to filter for */\n requestStatuses: RequestStatus[];\n /** File where request receipts are stored */\n requestReceiptFolder: string;\n /** Transcend API key authentication */\n auth: string;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** Request IDs to filter for */\n requestIds?: string[];\n /** Whether to re-verify the email when restarting the request */\n emailIsVerified?: boolean;\n /** Filter for requests that were submitted before this date */\n createdAt?: Date;\n /** Requests that have been open for this length of time should be marked as silent mode */\n silentModeBefore?: Date;\n /** Send an email receipt to the restarted requests */\n sendEmailReceipt?: boolean;\n /** Copy over all identifiers rather than restarting the request only with the core identifier */\n copyIdentifiers?: boolean;\n /** Skip the waiting period when restarting requests */\n skipWaitingPeriod?: boolean;\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Concurrency to upload requests at */\n concurrency?: number;\n}): Promise<void> {\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Create a new state file to store the requests from this run\n const cacheFile = join(\n requestReceiptFolder,\n `tr-request-restart-${new Date().toISOString()}.json`,\n );\n const state = new PersistedState(cacheFile, CachedRequestState, {\n restartedRequests: [],\n failingRequests: [],\n });\n\n // Create sombra instance to communicate with\n const sombra = await createSombraGotInstance(transcendUrl, auth, sombraAuth);\n\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n const allRequests = await fetchAllRequests(client, {\n requestIds,\n actions: requestActions,\n statuses: requestStatuses,\n createdAtBefore,\n createdAtAfter,\n });\n const requests = allRequests.filter(\n (request) => new Date(request.createdAt) < createdAt,\n );\n logger.info(`Found ${requests.length} requests to restart`);\n\n if (copyIdentifiers) {\n logger.info('copyIdentifiers detected - All Identifiers will be copied.');\n }\n if (sendEmailReceipt) {\n logger.info('sendEmailReceipt detected - Email receipts will be sent.');\n }\n if (skipWaitingPeriod) {\n logger.info('skipWaitingPeriod detected - Waiting period will be skipped.');\n }\n\n // Validate request IDs\n if (requestIds.length > 0 && requestIds.length !== requests.length) {\n const missingRequests = difference(\n requestIds,\n requests.map(({ id }) => id),\n );\n if (missingRequests.length > 0) {\n logger.error(\n colors.red(\n `Failed to find the following requests by ID: ${missingRequests.join(\n ',',\n )}.`,\n ),\n );\n process.exit(1);\n }\n }\n\n // Map over the requests\n let total = 0;\n progressBar.start(requests.length, 0);\n await map(\n requests,\n async (request, ind) => {\n try {\n // Pull the request identifiers\n const requestIdentifiers = copyIdentifiers\n ? await fetchAllRequestIdentifiers(client, sombra, {\n requestId: request.id,\n })\n : [];\n\n // Make the GraphQL request to restart the request\n const requestResponse = await restartPrivacyRequest(\n sombra,\n {\n ...request,\n // override silent mode\n isSilent:\n !!silentModeBefore &&\n new Date(request.createdAt) < silentModeBefore\n ? true\n : request.isSilent,\n },\n {\n requestIdentifiers,\n skipWaitingPeriod,\n sendEmailReceipt,\n emailIsVerified,\n },\n );\n\n // Cache successful upload\n const restartedRequests = state.getValue('restartedRequests');\n restartedRequests.push({\n id: requestResponse.id,\n link: requestResponse.link,\n rowIndex: ind,\n coreIdentifier: requestResponse.coreIdentifier,\n attemptedAt: new Date().toISOString(),\n });\n await state.setValue(restartedRequests, 'restartedRequests');\n } catch (err) {\n const msg = `${err.message} - ${JSON.stringify(\n err.response?.body,\n null,\n 2,\n )}`;\n const clientError = extractClientError(msg);\n\n const failingRequests = state.getValue('failingRequests');\n failingRequests.push({\n id: request.id,\n link: request.link,\n rowIndex: ind,\n coreIdentifier: request.coreIdentifier,\n attemptedAt: new Date().toISOString(),\n error: clientError || msg,\n });\n await state.setValue(failingRequests, 'failingRequests');\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 // Log completion time\n logger.info(\n colors.green(\n `Completed restarting of requests in \"${totalTime / 1000}\" seconds.`,\n ),\n );\n\n // Log errors\n if (state.getValue('failingRequests').length > 0) {\n logger.error(\n colors.red(\n `Encountered \"${state.getValue('failingRequests').length}\" errors. ` +\n `See \"${resolve(\n cacheFile,\n )}\" to review the error messages and inputs.`,\n ),\n );\n process.exit(1);\n }\n}\n","import { mapSeries, map } from '../bluebird';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport {\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n fetchAllRequestEnrichers,\n fetchAllRequests,\n SKIP_REQUEST_ENRICHER,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport {\n RequestEnricherStatus,\n RequestStatus,\n} from '@transcend-io/privacy-types';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Given an enricher ID, mark all open request enrichers as skipped\n *\n * @param options - Options\n * @returns Number of items skipped\n */\nexport async function skipPreflightJobs({\n enricherIds,\n auth,\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** Transcend API key authentication */\n auth: string;\n /** Enricher IDs to pull down jobs for */\n enricherIds: string[];\n /** Upload concurrency */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Request statuses to mark as completed */\n requestStatuses?: RequestStatus[];\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n\n // fetch all RequestDataSilos that are open\n const requests = await fetchAllRequests(client, {\n statuses: [RequestStatus.Enriching],\n });\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Processing enricher: \"${enricherIds.join(',')}\" fetched \"${\n requests.length\n }\" in enriching status.`,\n ),\n );\n\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n let total = 0;\n progressBar.start(requests.length, 0);\n let totalSkipped = 0;\n await map(\n requests,\n async (request) => {\n // TODO dont pull all in\n const requestEnrichers = await fetchAllRequestEnrichers(client, {\n requestId: request.id,\n });\n const requestEnrichersFiltered = requestEnrichers.filter(\n (enricher) =>\n enricherIds.includes(enricher.enricher.id) &&\n ![\n RequestEnricherStatus.Resolved,\n RequestEnricherStatus.Skipped,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ].includes(enricher.status as any),\n );\n\n // TODO\n if (requestEnrichersFiltered.length > 0) {\n await mapSeries(requestEnrichersFiltered, async (requestEnricher) => {\n try {\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, SKIP_REQUEST_ENRICHER, {\n requestEnricherId: requestEnricher.id,\n });\n totalSkipped += 1;\n } catch (err) {\n if (\n !err.message.includes(\n 'Client error: Cannot skip Request enricher because it has already completed',\n )\n ) {\n throw err;\n }\n }\n });\n }\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully skipped \"${totalSkipped}\" for \"${\n requests.length\n }\" requests in \"${totalTime / 1000}\" seconds!`,\n ),\n );\n return requests.length;\n}\n","import {\n RequestAction,\n RequestEnricherStatus,\n RequestStatus,\n} from '@transcend-io/privacy-types';\nimport { map } from '../bluebird';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\nimport { difference } from 'lodash-es';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\nimport {\n buildTranscendGraphQLClient,\n fetchAllRequestEnrichers,\n fetchAllRequests,\n retryRequestEnricher,\n} from '../graphql';\nimport { logger } from '../../logger';\n\n/**\n * Restart a bunch of request enrichers\n *\n * @param options - Options\n */\nexport async function bulkRetryEnrichers({\n auth,\n requestActions = [],\n createdAtBefore,\n createdAtAfter,\n transcendUrl = DEFAULT_TRANSCEND_API,\n requestEnricherStatuses = Object.values(RequestEnricherStatus),\n requestIds = [],\n enricherId,\n concurrency = 20,\n}: {\n /** Actions to filter for */\n requestActions?: RequestAction[];\n /** Request enricher statuses to restart - defaults to all statuses */\n requestEnricherStatuses?: RequestEnricherStatus[];\n /** Transcend API key authentication */\n auth: string;\n /** The ID of the enricher to restart */\n enricherId: string;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Request IDs to filter for */\n requestIds?: string[];\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Concurrency to upload requests at */\n concurrency?: number;\n}): Promise<void> {\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n logger.info(colors.magenta('Fetching requests to restart...'));\n\n const requests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses: [RequestStatus.Enriching],\n createdAtBefore,\n createdAtAfter,\n requestIds,\n });\n\n let totalRestarted = 0;\n\n // Validate request IDs\n if (requestIds.length > 0 && requestIds.length !== requests.length) {\n const missingRequests = difference(\n requestIds,\n requests.map(({ id }) => id),\n );\n if (missingRequests.length > 0) {\n logger.error(\n colors.red(\n `Failed to find the following requests by ID: ${missingRequests.join(\n ',',\n )}.`,\n ),\n );\n process.exit(1);\n }\n }\n\n // Map over the requests\n let total = 0;\n progressBar.start(requests.length, 0);\n await map(\n requests,\n async (request) => {\n // Pull the request identifiers\n const requestEnrichers = await fetchAllRequestEnrichers(client, {\n requestId: request.id,\n });\n const requestEnrichersToRestart = requestEnrichers.filter(\n (requestEnricher) =>\n requestEnricher.enricher.id === enricherId &&\n requestEnricherStatuses.includes(requestEnricher.status),\n );\n await map(requestEnrichersToRestart, async (requestEnricher) => {\n await retryRequestEnricher(client, requestEnricher.id);\n totalRestarted += 1;\n });\n\n // Cache successful upload\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 // Log completion time\n logger.info(\n colors.green(\n `Completed restarting of ${\n requests.length\n } requests and ${totalRestarted} enrichers in \"${\n totalTime / 1000\n }\" seconds.`,\n ),\n );\n}\n","import { map } from '../bluebird';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport {\n RETRY_REQUEST_DATA_SILO,\n fetchRequestDataSilo,\n fetchAllRequests,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Retry a set of RequestDataSilos\n *\n * @param options - Options\n * @returns Number of items marked as completed\n */\nexport async function retryRequestDataSilos({\n requestActions,\n dataSiloId,\n auth,\n concurrency = 20,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** Transcend API key authentication */\n auth: string;\n /** Data Silo ID to pull down jobs for */\n dataSiloId: string;\n /** Concurrency to upload requests in parallel */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses: [RequestStatus.Compiling, RequestStatus.Approving],\n });\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Retrying requests for Data Silo: \"${dataSiloId}\", restarting \"${allRequests.length}\" requests.`,\n ),\n );\n\n let total = 0;\n let skipped = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToRestart) => {\n try {\n const requestDataSilo = await fetchRequestDataSilo(client, {\n requestId: requestToRestart.id,\n dataSiloId,\n });\n\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, RETRY_REQUEST_DATA_SILO, {\n requestDataSiloId: requestDataSilo.id,\n });\n } catch (err) {\n // some requests may not have this data silo connected\n if (!err.message.includes('Failed to find RequestDataSilo')) {\n throw err;\n }\n skipped += 1;\n }\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully notified Transcend in \"${\n totalTime / 1000\n }\" seconds for ${total} requests, ${skipped} requests were skipped because data silo was not attached to the request!`,\n ),\n );\n return allRequests.length;\n}\n","import { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport { map } from '../bluebird';\nimport colors from 'colors';\nimport { groupBy } from 'lodash-es';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\nimport {\n PrivacyRequest,\n RequestIdentifier,\n buildTranscendGraphQLClient,\n createSombraGotInstance,\n fetchAllRequestIdentifiers,\n fetchAllRequests,\n} from '../graphql';\nimport { logger } from '../../logger';\n\nexport interface ExportedPrivacyRequest extends PrivacyRequest {\n /** Request identifiers */\n requestIdentifiers: RequestIdentifier[];\n}\n\n/**\n * Pull down a list of privacy requests\n *\n * @param options - Options\n * @returns The requests with request identifiers and requests formatted for CSV\n */\nexport async function pullPrivacyRequests({\n auth,\n sombraAuth,\n actions = [],\n statuses = [],\n identifierSearch,\n pageLimit = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n createdAtBefore,\n skipRequestIdentifiers = false,\n createdAtAfter,\n isTest,\n}: {\n /** Transcend API key authentication */\n auth: string;\n /** Search for a specific identifier */\n identifierSearch?: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Statuses to filter on */\n statuses?: RequestStatus[];\n /** The request action to fetch */\n actions?: RequestAction[];\n /** Page limit when fetching requests */\n pageLimit?: number;\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Return test requests */\n isTest?: boolean;\n /** Skip fetching request identifier */\n skipRequestIdentifiers?: boolean;\n}): Promise<{\n /** All request information with attached identifiers */\n requestsWithRequestIdentifiers: ExportedPrivacyRequest[];\n /** Requests that are formatted for CSV */\n requestsFormattedForCsv: {\n [k in string]: string | null | number | boolean;\n }[];\n}> {\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 // Log date range\n let dateRange = '';\n if (createdAtBefore) {\n dateRange += ` before ${createdAtBefore.toISOString()}`;\n }\n if (createdAtAfter) {\n dateRange += `${\n dateRange ? ', and' : ''\n } after ${createdAtAfter.toISOString()}`;\n }\n\n // Log out\n logger.info(\n colors.magenta(\n `${\n actions.length > 0\n ? `Pulling requests of type \"${actions.join('\" , \"')}\"`\n : 'Pulling all requests'\n }${dateRange}`,\n ),\n );\n\n // fetch the requests\n const requests = await fetchAllRequests(client, {\n actions,\n text: identifierSearch,\n statuses,\n createdAtBefore,\n createdAtAfter,\n isTest,\n });\n\n // Fetch the request identifiers for those requests\n const requestsWithRequestIdentifiers = skipRequestIdentifiers\n ? requests.map((request) => ({\n ...request,\n requestIdentifiers: [],\n }))\n : await map(\n requests,\n async (request) => {\n const requestIdentifiers = await fetchAllRequestIdentifiers(\n client,\n sombra,\n {\n requestId: request.id,\n },\n );\n return {\n ...request,\n requestIdentifiers,\n };\n },\n {\n concurrency: pageLimit,\n },\n );\n\n logger.info(\n colors.magenta(`Pulled ${requestsWithRequestIdentifiers.length} requests`),\n );\n\n // Write out to CSV\n const data = requestsWithRequestIdentifiers.map(\n ({\n attributeValues,\n requestIdentifiers,\n id,\n email,\n type,\n status,\n subjectType,\n details,\n createdAt,\n country,\n locale,\n origin,\n countrySubDivision,\n isSilent,\n isTest,\n coreIdentifier,\n purpose,\n ...request\n }) => ({\n 'Request ID': id,\n 'Created At': createdAt,\n Email: email,\n 'Core Identifier': coreIdentifier,\n 'Request Type': type,\n 'Data Subject Type': subjectType,\n Status: status,\n Country: country,\n 'Country Sub Division': countrySubDivision,\n Details: details,\n Origin: origin,\n 'Silent Mode': isSilent,\n 'Is Test Request': isTest,\n Language: locale,\n 'Purpose Trigger Name': purpose?.title || purpose?.name || '',\n 'Purpose Trigger Value': purpose?.consent?.toString() || '',\n ...(purpose?.enrichedPreferences || []).reduce((acc, p) => {\n const title = p.preferenceTopic?.title.defaultMessage || p.name;\n return title\n ? {\n ...acc,\n [title]: p.selectValues\n ? p.selectValues.map((x) => x.name).join(';')\n : p.selectValue?.name || p.booleanValue,\n }\n : acc;\n }, {}),\n ...request,\n ...Object.entries(groupBy(attributeValues, 'attributeKey.name')).reduce(\n (acc, [name, values]) =>\n Object.assign(acc, {\n [name]: values.map(({ name }) => name).join(','),\n }),\n {},\n ),\n ...Object.entries(groupBy(requestIdentifiers, 'name')).reduce(\n (acc, [name, values]) =>\n Object.assign(acc, {\n [name]: values.map(({ value }) => value).join(','),\n }),\n {},\n ),\n }),\n );\n\n return { requestsWithRequestIdentifiers, requestsFormattedForCsv: data };\n}\n","import { map } from '../bluebird';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport {\n CHANGE_REQUEST_DATA_SILO_STATUS,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n fetchRequestDataSilos,\n fetchRequestDataSilosCount,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { RequestStatus } from '@transcend-io/privacy-types';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Given a data silo ID, mark all open request data silos as skipped\n *\n * @param options - Options\n * @returns Number of items skipped\n */\nexport async function skipRequestDataSilos({\n dataSiloId,\n auth,\n concurrency = 50,\n maxUploadPerChunk = 50000,\n status = 'SKIPPED',\n transcendUrl = DEFAULT_TRANSCEND_API,\n requestStatuses = [RequestStatus.Compiling, RequestStatus.Secondary],\n}: {\n /** Transcend API key authentication */\n auth: string;\n /** Data Silo ID to pull down jobs for */\n dataSiloId: string;\n /** Status to set */\n status?: 'SKIPPED' | 'RESOLVED';\n /** Upload concurrency */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Request statuses to mark as completed */\n requestStatuses?: RequestStatus[];\n /** Maximum number of items to mark skipped per go */\n maxUploadPerChunk?: number;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n\n // Determine total number of request data silos\n const requestDataSiloCount = await fetchRequestDataSilosCount(client, {\n dataSiloId,\n requestStatuses,\n });\n\n logger.info(\n colors.magenta(\n `Marking ${requestDataSiloCount} request data silos as completed`,\n ),\n );\n\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 total = 0;\n progressBar.start(requestDataSiloCount, 0);\n\n // fetch all RequestDataSilos that are open\n while (total < requestDataSiloCount) {\n const requestDataSilos = await fetchRequestDataSilos(client, {\n dataSiloId,\n requestStatuses,\n limit: maxUploadPerChunk,\n // eslint-disable-next-line no-loop-func\n onProgress: (numUpdated) => {\n total += numUpdated / 2;\n progressBar.update(total);\n },\n });\n\n await map(\n requestDataSilos,\n // eslint-disable-next-line no-loop-func\n async (requestDataSilo) => {\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 += 0.5;\n progressBar.update(total);\n },\n { concurrency },\n );\n }\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully skipped \"${requestDataSiloCount}\" requests in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n return requestDataSiloCount;\n}\n","import { map } from '../bluebird';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport {\n REMOVE_REQUEST_IDENTIFIERS,\n fetchAllRequests,\n fetchAllRequestIdentifierMetadata,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Remove a set of unverified request identifier\n *\n * @param options - Options\n * @returns Number of items marked as completed\n */\nexport async function removeUnverifiedRequestIdentifiers({\n requestActions,\n identifierNames,\n auth,\n concurrency = 20,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** Transcend API key authentication */\n auth: string;\n /** The set of identifier names to remove */\n identifierNames: string[];\n /** Concurrency to upload requests in parallel */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses: [RequestStatus.Enriching],\n });\n\n // Notify Transcend\n logger.info(colors.magenta('Fetched requests in preflight/enriching state.'));\n\n let total = 0;\n let processed = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToRestart) => {\n const requestIdentifiers = await fetchAllRequestIdentifierMetadata(\n client,\n { requestId: requestToRestart.id },\n );\n const clearOut = requestIdentifiers\n .filter(\n ({ isVerifiedAtLeastOnce, name }) =>\n isVerifiedAtLeastOnce === false && identifierNames.includes(name),\n )\n .map(({ id }) => id);\n\n if (clearOut.length > 0) {\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, REMOVE_REQUEST_IDENTIFIERS, {\n input: {\n requestId: requestToRestart.id,\n requestIdentifierIds: clearOut,\n },\n });\n processed += clearOut.length;\n }\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully cleared out unverified identifiers \"${\n totalTime / 1000\n }\" seconds for ${total} requests, ${processed} identifiers were cleared out!`,\n ),\n );\n return allRequests.length;\n}\n","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","/**\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","/**\n * Extract an HTTP status code from a thrown error (got compatible).\n *\n * @param err - Unknown error thrown by network call\n * @returns HTTP status code, if present\n */\nexport function getErrorStatus(err: unknown): number | undefined {\n // Swallow unknowns carefully—never throw from an error handler.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const anyErr = err as any;\n return anyErr?.response?.statusCode ?? anyErr?.response?.status;\n}\n","/**\n * Extract a human-readable error message from a thrown error.\n *\n * Tries to parse JSON bodies that follow common REST/GraphQL error patterns:\n * { error: { message: string } }\n * { errors: [{ message: string }, ...] }\n *\n * Falls back to `err.message` or 'Unknown error'.\n *\n * @param err - Unknown error thrown by network call\n * @returns A concise error string safe to log/show\n */\nexport function extractErrorMessage(err: unknown): string {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const anyErr = err as any;\n let errorMsg = anyErr?.response?.body || anyErr?.message || 'Unknown error';\n\n // Try to parse as JSON; if not parsable, leave as-is.\n try {\n const parsed = JSON.parse(errorMsg);\n // Typical shapes: errors[], error.errors[], error.message\n const candidates = parsed.errors ||\n parsed.error?.errors || [parsed.error?.message || parsed.error];\n\n const msgs = Array.isArray(candidates) ? candidates : [candidates];\n errorMsg = msgs.filter(Boolean).join(', ');\n } catch {\n // not JSON, ignore\n }\n return errorMsg;\n}\n","/**\n * Sleep in a promise\n *\n * @param sleepTime - The time to sleep in milliseconds.\n * @returns Resolves promise\n */\nexport function sleepPromise(sleepTime: number): Promise<number> {\n return new Promise((resolve) => {\n setTimeout(() => resolve(sleepTime), sleepTime);\n });\n}\n","/**\n * Split an array roughly in half. Stable for even/odd lengths.\n *\n * @param entries - Items to split\n * @returns A tuple [left, right] halves\n */\nexport function splitInHalf<T>(entries: T[]): [T[], T[]] {\n const mid = Math.floor(entries.length / 2);\n return [entries.slice(0, mid), entries.slice(mid)];\n}\n","import { sleepPromise } from './sleepPromise';\nimport { getErrorStatus } from './getErrorStatus';\nimport { extractErrorMessage } from './extractErrorMessage';\n\nexport interface RetryPolicy {\n /** Maximum retry attempts (not counting the initial try) */\n maxAttempts: number;\n /** Fixed delay between attempts in milliseconds */\n delayMs: number;\n /**\n * Decide whether a given error should be retried.\n *\n * @param status - HTTP status code (if known)\n * @param message - Extracted error message (if known)\n */\n shouldRetry(status?: number, message?: string): boolean;\n}\n\n/**\n * Retry a single async operation according to the provided policy.\n * The operation is executed once initially, then up to `maxAttempts` retries.\n *\n * @param op - Operation to run\n * @param policy - Retry policy\n * @param onBackoff - Observer called before each retry (for logging/metrics)\n * @returns Result of the operation if it eventually succeeds\n * @throws The last error encountered if all retries fail\n */\nexport async function retrySamePromise<T>(\n op: () => Promise<T>,\n policy: RetryPolicy,\n onBackoff: (note: string) => void,\n): Promise<T> {\n let attempt = 0;\n\n // eslint-disable-next-line no-constant-condition\n while (true) {\n try {\n // First pass and any subsequent retries run the same op.\n return await op();\n } catch (err) {\n attempt += 1;\n\n // Use shared helpers for status + human-readable message extraction\n const status = getErrorStatus(err);\n const msg = extractErrorMessage(err);\n\n const canRetry =\n attempt <= policy.maxAttempts && policy.shouldRetry(status, msg);\n\n if (!canRetry) {\n // Surface the final error to the caller, which may then split/fail.\n throw err;\n }\n\n onBackoff(\n `Retrying after status=${status} attempt=${attempt}/${policy.maxAttempts} — ${msg}`,\n );\n await sleepPromise(policy.delayMs);\n // Loop to retry\n }\n }\n}\n","/**\n * Limits the number of records in the returned object to a maximum.\n * For entries beyond the max, sets their value to `true`.\n *\n * @param obj - Object\n * @param max - Maximum number of entries to retain original value.\n * @returns Object with keys mapped to their value or `true` if over the limit.\n */\nexport function limitRecords<T>(\n obj: Record<string, T>,\n max: number,\n): Record<string, T | true> {\n return Object.entries(obj).reduce((acc, [userId, value], i) => {\n acc[userId] = i < max ? value : true;\n return acc;\n }, {} as Record<string, T | true>);\n}\n","/**\n * Tracks counts over time and calculates rates within a specified time window.\n *\n * This class maintains a rolling window of count \"buckets\" (timestamped values)\n * and provides methods to add new counts and compute the rate of events over a\n * configurable time window.\n *\n * Example usage:\n * ```typescript\n * const counter = new RateCounter();\n * counter.add(5); // Add 5 events\n * const rate = counter.rate(60_000); // Get rate over last 60 seconds\n * ```\n */\nexport class RateCounter {\n private buckets: Array<{\n /** Timestamp of the bucket */\n t: number;\n /** Number of events in the bucket */\n n: number;\n }> = [];\n\n /**\n * Adds a new count to the counter.\n *\n * @param n - The number of events to add to the counter.\n */\n add(n: number): void {\n const now = Date.now();\n this.buckets.push({ t: now, n });\n // keep last 2 minutes of buckets\n const cutoff = now - 120_000;\n while (this.buckets.length && this.buckets[0].t < cutoff) {\n this.buckets.shift();\n }\n }\n\n /**\n * rate over the last `windowMs` milliseconds\n *\n * @param windowMs - The time window in milliseconds to calculate the rate over.\n * @returns The average rate of events per second over the specified time window.\n */\n rate(windowMs: number): number {\n const now = Date.now();\n const cutoff = now - windowMs;\n let sum = 0;\n for (let i = this.buckets.length - 1; i >= 0; i -= 1) {\n const b = this.buckets[i];\n if (b.t < cutoff) break;\n sum += b.n;\n }\n return sum / (windowMs / 1000);\n }\n}\n","import { readFileSync } from 'node:fs';\n\n/**\n * Safely reads the contents of a file as a UTF-8 string.\n * Returns an empty string if the path is not provided or if reading fails.\n *\n * @param p - The path to the file to read.\n * @returns The file contents as a string, or an empty string on error.\n */\nexport function readSafe(p?: string): string {\n try {\n return p ? readFileSync(p, 'utf8') : '';\n } catch {\n return '';\n }\n}\n","import { join } from 'node:path';\nimport { readdirSync, statSync } from 'node:fs';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport type { LocalContext } from '../../context';\n\n/**\n * Validate flags and collect Parquet file paths from a directory.\n * On validation error, the provided `exit` function is called.\n *\n * @param directory - the directory containing Parquet files\n * @param localContext - the context of the command, used for logging and exit\n * @returns an array of valid Parquet file paths\n */\nexport function collectParquetFilesOrExit(\n directory: string | undefined,\n localContext: LocalContext,\n): string[] {\n if (!directory) {\n logger.error(colors.red('A --directory must be provided.'));\n localContext.process.exit(1);\n }\n\n let files: string[] = [];\n try {\n const entries = readdirSync(directory);\n files = entries\n .filter((f) => f.endsWith('.parquet'))\n .map((f) => join(directory, f))\n .filter((p) => {\n try {\n return statSync(p).isFile();\n } catch {\n return false;\n }\n });\n } catch (err) {\n logger.error(colors.red(`Failed to read directory: ${directory}`));\n logger.error(colors.red((err as Error).message));\n localContext.process.exit(1);\n }\n\n if (files.length === 0) {\n logger.error(\n colors.red(`No Parquet files found in directory: ${directory}`),\n );\n localContext.process.exit(1);\n }\n logger.info(colors.green(`Found: ${files.join(', ')} parquet files`));\n return files;\n}\n","import { mkdirSync, rmSync, existsSync } from 'node:fs';\nimport { dirname, join, parse } from 'node:path';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport type { DuckDBConnection, DuckDBInstance } from '@duckdb/node-api';\n\n/** Progress callback used by the parent runner to surface progress to the UI. */\ntype OnProgress = (processed: number, total?: number) => void;\n\n/**\n * Options for converting a single Parquet file into a single CSV file.\n */\nexport type ParquetToCsvOneFileOptions = {\n /** Absolute or relative path to the input `.parquet` file. */\n filePath: string;\n /**\n * Directory where the output CSV will be written.\n * If omitted, the CSV is written next to the input file.\n */\n outputDir?: string;\n /**\n * When true, removes a pre-existing output file with the same name before writing.\n * Useful for re-runs; ignored if the file does not exist.\n */\n clearOutputDir: boolean;\n /**\n * Optional progress hook. Called with the number of processed records.\n * `total` is not computed here; it will be `undefined`.\n */\n onProgress?: OnProgress;\n};\n\n/**\n * Convert a single Parquet file to a single CSV file (1:1) using DuckDB.\n *\n * Output naming: `${basename}.csv` in `outputDir ?? dirname(filePath)`.\n *\n * Errors:\n * - Throws on I/O failures or DuckDB execution errors.\n *\n * Why DuckDB?\n * - Robust reader for many Parquet dialects (e.g., Spark output, nested types, timestamps).\n * - Streaming COPY handles large files without loading everything into JS memory.\n *\n * What this does:\n * - Opens an in-memory DuckDB database (no `.db` file created).\n * - Optionally disables temp spilling to disk (so only your CSV is written).\n * - Executes a single `COPY (SELECT * FROM read_parquet(...)) TO ...` statement.\n * - Produces exactly one CSV per input Parquet (no chunking or rotation).\n *\n * Notes & defaults:\n * - DuckDBInstance: `:memory:` (ephemeral). No persistent DB file is created.\n * - Temp files: disabled via `PRAGMA temp_directory=''` (best-effort; ignored if unsupported).\n * - CSV format: header row, comma delimiter, double-quote quoting, empty string for NULL.\n * - Progress: DuckDB COPY doesn't expose row-level progress via the JS API; we emit a\n * best-effort final callback.\n *\n * Requirements:\n * - `@duckdb/node-api` npm package installed and available at runtime.\n * - Supported platform binary (mac arm64/x64, linux x64, windows x64).\n *\n * @param opts - Conversion options\n * @param DuckDb - DuckDB instance to use\n * @returns Promise<void> when the CSV has been written\n */\nexport async function parquetToCsvOneFile(\n opts: ParquetToCsvOneFileOptions,\n DuckDb: typeof DuckDBInstance,\n): Promise<void> {\n const { filePath, outputDir, clearOutputDir, onProgress } = opts;\n\n const baseDir = outputDir || dirname(filePath);\n const { name: baseName } = parse(filePath);\n const outPath = join(baseDir, `${baseName}.csv`);\n\n // Ensure output directory exists\n mkdirSync(baseDir, { recursive: true });\n\n // Remove any pre-existing output file if requested\n if (clearOutputDir && existsSync(outPath)) {\n try {\n rmSync(outPath, { force: true });\n } catch (err) {\n logger.warn(\n colors.yellow(\n `Could not remove existing output file ${outPath}: ${\n (err as Error).message\n }`,\n ),\n );\n }\n }\n\n // In-memory DB: no .db file created on disk\n const db = await DuckDb.create(':memory:');\n const conn = await db.connect();\n\n try {\n // Optional: prevent DuckDB from creating temp files on disk (best-effort).\n // Some versions may ignore or error; we ignore such errors safely.\n await runIgnoreError(conn, \"PRAGMA temp_directory='';\");\n\n // Optionally: cap memory to encourage in-memory execution or fail-fast\n // (commented out by default; uncomment to enforce a limit)\n // await runIgnoreError(conn, \"PRAGMA memory_limit='4GB';\");\n\n // Ensure stable CSV settings: header, comma delimiter, double quotes, empty string for NULLs.\n // Escape single quotes for SQL string literals\n const q = (p: string): string => `'${p.replace(/'/g, \"''\")}'`;\n\n // Use COPY with a subquery so DuckDB streams Parquet -> CSV efficiently.\n const sql = `\n COPY (SELECT * FROM read_parquet(${q(filePath)}))\n TO ${q(outPath)}\n (HEADER, DELIMITER ',', QUOTE '\"', ESCAPE '\"', NULL '');\n `;\n\n await run(conn, sql);\n\n // Best-effort progress notification (DuckDB JS API doesn't expose progress for COPY)\n onProgress?.(0, undefined);\n\n logger.info(colors.green(`Wrote CSV → ${outPath}`));\n } finally {\n // Close connection + db handles gracefully\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await disposeSafe(conn as any);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await disposeSafe(db as any);\n }\n}\n\n/* =============================================================================\n * DuckDB helpers\n * =============================================================================\n */\n\n/**\n * Execute a SQL statement on a DuckDB connection and dispose the result.\n *\n * @param conn - DuckDB connection\n * @param sql - SQL string to run\n * @returns Promise<void>\n */\nasync function run(conn: DuckDBConnection, sql: string): Promise<void> {\n const result = await conn.run(sql);\n // The high-level API returns a Result; ensure we dispose it to free buffers.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await disposeSafe(result as any);\n}\n\n/**\n * Execute a SQL statement but ignore any error that occurs.\n * Useful for best-effort PRAGMAs that may not be supported across versions.\n *\n * @param conn - DuckDB connection\n * @param sql - SQL string to run\n * @returns Promise<void>\n */\nasync function runIgnoreError(\n conn: DuckDBConnection,\n sql: string,\n): Promise<void> {\n try {\n await run(conn, sql);\n } catch {\n // ignore\n }\n}\n\n/**\n * Dispose a DuckDB resource (connection or instance) if present.\n *\n * @param handle - Object exposing an async `dispose()` method\n * @returns Promise<void>\n */\nasync function disposeSafe(\n handle:\n | {\n /** Dispose handler */\n dispose: () => Promise<void>;\n }\n | null\n | undefined,\n): Promise<void> {\n if (!handle || typeof handle.dispose !== 'function') return;\n try {\n await handle.dispose();\n } catch {\n // ignore\n }\n}\n","export const DAY_MS = 24 * 60 * 60 * 1000;\nexport const HOUR_MS = 60 * 60 * 1000;\nexport const FIVE_MIN_MS = 5 * 60 * 1000;\n\n/**\n * Clamp 1..50 per API spec\n *\n * @param n - Number\n * @returns Clamped number\n */\nexport const clampPageSize = (n?: number): number =>\n Math.max(1, Math.min(50, n ?? 50));\n\n/**\n * TRUE UTC day start (00:00:00Z)\n *\n * @param d - Date\n * @returns Day start\n */\nexport const startOfUtcDay = (d: Date): Date =>\n new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()));\n\n/**\n * TRUE UTC hour start (HH:00:00Z)\n *\n * @param d - Date\n * @returns Hour start\n */\nexport const startOfHour = (d: Date): Date =>\n new Date(\n Date.UTC(\n d.getUTCFullYear(),\n d.getUTCMonth(),\n d.getUTCDate(),\n d.getUTCHours(),\n ),\n );\n\n/**\n * Add ms safely\n *\n * @param d - Date\n * @param ms - Milliseconds to add\n * @returns New date\n */\nexport const addMs = (d: Date, ms: number): Date => new Date(d.getTime() + ms);\n\n/**\n * Add whole UTC days (exclusive bound helper)\n *\n * @param d - Date\n * @param n - Number of days to add\n * @returns New date\n */\nexport const addDaysUtc = (d: Date, n: number): Date =>\n new Date(d.getTime() + n * DAY_MS);\n","import * as fastcsv from 'fast-csv';\nimport { createWriteStream, writeFileSync, appendFileSync } from 'node:fs';\n\nimport { ObjByString } from '@transcend-io/type-utils';\n\n/**\n * Escape a CSV value\n *\n * @param value - Value to escape\n * @returns Escaped value\n */\nfunction escapeCsvValue(value: string): string {\n if (value.includes('\"') || value.includes(',') || value.includes('\\n')) {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n }\n return value;\n}\n\n/**\n * Write a csv to file synchronously, overwriting any existing content\n *\n * @param filePath - File to write out to\n * @param data - Data to write\n * @param headers - Headers. If true, use object keys as headers. If array, use provided headers.\n */\nexport function writeCsvSync(\n filePath: string,\n data: ObjByString[],\n headers: string[],\n): void {\n const rows: string[][] = [];\n\n rows.push(headers);\n rows.push(...data.map((row) => Object.values(row)));\n\n // Build CSV content with proper escaping\n const csvContent = rows\n .map((row) => row.map(escapeCsvValue).join(','))\n .join('\\n');\n\n // Write to file, overwriting existing content\n writeFileSync(filePath, csvContent);\n}\n\n/**\n * Initialize a CSV file by writing only the header row (or an empty file if no headers).\n *\n * @param filePath - CSV path\n * @param headers - Ordered list of column names; if empty, creates/empties the file\n */\nexport function initCsvFile(filePath: string, headers: string[]): void {\n if (!headers || headers.length === 0) {\n writeFileSync(filePath, '');\n return;\n }\n const headerLine = headers.map(escapeCsvValue).join(',');\n writeFileSync(filePath, `${headerLine}\\n`);\n}\n\n/**\n * Append rows to CSV using an explicit header order (no header line).\n * Values are written in the order of `headerOrder`.\n *\n * @param filePath - CSV path\n * @param data - Row objects\n * @param headerOrder - Column order to apply\n */\nexport function appendCsvRowsOrdered(\n filePath: string,\n data: ObjByString[],\n headerOrder: string[],\n): void {\n if (!data.length) return;\n\n const lines = data.map((row) => {\n const vals = headerOrder.map((key) => {\n const v = row[key];\n return v == null ? '' : String(v);\n });\n return vals.map(escapeCsvValue).join(',');\n });\n\n appendFileSync(filePath, `${lines.join('\\n')}\\n`);\n}\n\n/**\n * Append data to an existing csv file synchronously (legacy, uses Object.values order).\n * Prefer appendCsvRowsOrdered for deterministic column order.\n *\n * @param filePath - File to append to\n * @param data - Data to append\n */\nexport function appendCsvSync(filePath: string, data: ObjByString[]): void {\n // Convert data to CSV rows\n const rows = data.map((row) => Object.values(row));\n\n // Build CSV content with proper escaping\n const csvContent = rows\n .map((row) => row.map(escapeCsvValue).join(','))\n .join('\\n');\n\n // Append to file with leading newline\n appendFileSync(filePath, `\\n${csvContent}`);\n}\n\n/**\n * Write a csv to file asynchronously\n *\n * @param filePath - File to write out to\n * @param data - Data to write\n * @param headers - Headers\n */\nexport async function writeCsv(\n filePath: string,\n data: ObjByString[],\n headers: boolean | string[] = true,\n): Promise<void> {\n const ws = createWriteStream(filePath);\n await new Promise<void>((resolve, reject) => {\n try {\n const stream = fastcsv\n .write(data, { headers, objectMode: true })\n .on('error', reject);\n\n ws.on('error', reject);\n ws.on('finish', () => resolve());\n\n stream.pipe(ws);\n } catch (err) {\n reject(err);\n }\n });\n}\n\n/**\n * Parse a file path into a base name and extension\n *\n * @param filePath - File path to parse\n * @returns Base name and extension\n */\nexport function parseFilePath(filePath: string): {\n /** Base name of the file */\n baseName: string;\n /** Extension of the file */\n extension: string;\n} {\n const lastDotIndex = filePath.lastIndexOf('.');\n return {\n baseName:\n lastDotIndex !== -1 ? filePath.substring(0, lastDotIndex) : filePath,\n extension: lastDotIndex !== -1 ? filePath.substring(lastDotIndex) : '.csv',\n };\n}\n\n/**\n * Convert an object row into values aligned to header order\n *\n * @param row - Row object\n * @param headerOrder - Header order\n * @returns Aligned row object\n */\nfunction rowToValues(\n row: ObjByString,\n headerOrder: string[],\n): Record<string, unknown> {\n // fast-csv with objectMode expects objects; we ensure consistent key ordering\n // by building a new object with keys in headerOrder.\n const ordered: Record<string, unknown> = {};\n for (const key of headerOrder) {\n // Preserve undefined -> becomes empty cell in CSV\n ordered[key] = row[key];\n }\n return ordered;\n}\n\n/**\n * Await the 'drain' event when backpressure indicates buffering\n *\n * @param stream - Writable stream\n * @returns Promise that resolves on 'drain'\n */\nfunction waitForDrain(stream: NodeJS.WritableStream): Promise<void> {\n return new Promise((resolve) => {\n stream.once('drain', resolve);\n });\n}\n\n/**\n * Stream a large CSV dataset to a single file with proper backpressure handling.\n * (Kept for completeness; not used by the incremental write path.)\n *\n * @param filePath - File to write out to\n * @param data - Data to write (iterated without buffering the entire file content)\n * @param headers - If true, infer from first row; if string[], use provided; if false, omit header row\n * @returns Array with a single written file path\n */\nexport async function writeLargeCsv(\n filePath: string,\n data: ObjByString[],\n headers: boolean | string[] = true,\n): Promise<string[]> {\n // Determine header order\n let headerOrder: string[] | false;\n if (Array.isArray(headers)) {\n headerOrder = headers;\n } else if (headers === true) {\n headerOrder = data.length > 0 ? Object.keys(data[0]) : [];\n } else {\n headerOrder = false;\n }\n\n const ws = createWriteStream(filePath);\n const csvStream = fastcsv.format<ObjByString, ObjByString>({\n headers: headerOrder || undefined,\n objectMode: true,\n });\n\n // Pipe CSV stream into file write stream\n const piping = csvStream.pipe(ws);\n\n const completion = new Promise<void>((resolve, reject) => {\n piping.on('finish', () => resolve());\n piping.on('error', reject);\n csvStream.on('error', reject);\n ws.on('error', reject);\n });\n\n // Stream rows with backpressure handling\n for (const row of data) {\n const toWrite = headerOrder ? rowToValues(row, headerOrder) : row;\n const ok = csvStream.write(toWrite);\n if (!ok) {\n // Respect backpressure: wait until the internal buffer drains\n await waitForDrain(csvStream);\n }\n }\n\n // Signal end of input and wait for finish\n csvStream.end();\n await completion;\n\n return [filePath];\n}\n","import type {\n GraphQLClient,\n RequestDocument,\n Variables,\n} from 'graphql-request';\nimport { logger } from '../../logger';\nimport colors from 'colors';\nimport { sleepPromise } from '../helpers';\n\nconst MAX_RETRIES = 4;\n\nconst KNOWN_ERRORS = [\n 'syntax error',\n 'got invalid value',\n 'Client error',\n 'cannot affect row a second time',\n 'GRAPHQL_VALIDATION_FAILED',\n];\n\n/**\n * Make a GraphQL request with retries\n *\n * @param client - GraphQL client\n * @param document - document\n * @param variables - Variable\n * @param requestHeaders - Headers\n * @param maxRequests - Max number of requests\n * @returns Response\n */\nexport async function makeGraphQLRequest<T, V extends Variables = Variables>(\n client: GraphQLClient,\n document: RequestDocument,\n variables?: V,\n requestHeaders?: Record<string, string> | string[][] | Headers,\n maxRequests = MAX_RETRIES,\n): Promise<T> {\n let retryCount = 0;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n try {\n const result = await client.request(document, variables, requestHeaders);\n return result as T;\n } catch (err) {\n if (err.message.includes('API key is invalid')) {\n logger.error(\n colors.red(\n 'API key is invalid. ' +\n 'Please ensure that the key provided to `transcendAuth` has the proper scope and is not expired, ' +\n 'and that `transcendUrl` corresponds to the correct backend for your organization.',\n ),\n );\n process.exit(1);\n }\n\n if (KNOWN_ERRORS.some((msg) => err.message.includes(msg))) {\n throw err;\n }\n\n // wait for rate limit to resolve\n if (err.message.startsWith('Client error: Too many requests')) {\n const rateLimitResetAt = err.response.headers?.get('x-ratelimit-reset');\n const sleepTime = rateLimitResetAt\n ? new Date(rateLimitResetAt).getTime() - new Date().getTime() + 100\n : 1000 * 10;\n logger.log(\n colors.yellow(\n `DETECTED RATE LIMIT: ${err.message}. Sleeping for ${sleepTime}ms`,\n ),\n );\n\n await sleepPromise(sleepTime);\n }\n\n if (retryCount >= maxRequests) {\n throw err;\n }\n retryCount += 1;\n logger.log(\n colors.yellow(\n `Retrying failed request (${retryCount} / ${maxRequests}): ${err.message}`,\n ),\n );\n }\n }\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { IdentifierType, RequestAction } from '@transcend-io/privacy-types';\nimport { CREATE_IDENTIFIER, IDENTIFIERS, NEW_IDENTIFIER_TYPES } from './gqls';\nimport { keyBy, uniq, flatten, difference } from 'lodash-es';\nimport { TranscendInput } from '../../codecs';\nimport { logger } from '../../logger';\nimport colors from 'colors';\nimport { mapSeries } from '../bluebird';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface Identifier {\n /** ID of identifier */\n id: string;\n /** Name of identifier */\n name: string;\n /** The type of identifier */\n type: IdentifierType;\n /** Regular expression to */\n regex: string;\n /** The set of options that the identifier */\n selectOptions: string[];\n /** Whether identifier is enabled on privacy center */\n privacyCenterVisibility: RequestAction[];\n /** Enabled data subjects that are exposed this identifier on the privacy center */\n dataSubjects: {\n /** type of data subjects */\n type: string;\n }[];\n /** Whether identifier is a required field in privacy center form */\n isRequiredInForm: boolean;\n /** Identifier placeholder text */\n placeholder: string;\n /** Display title for identifier */\n displayTitle: {\n /** Default message */\n defaultMessage: string;\n };\n /** Display description for identifier */\n displayDescription: {\n /** Default */\n defaultMessage: string;\n };\n /** Display order */\n displayOrder: number;\n /** does this identifier uniquely identify a consent record */\n isUniqueOnPreferenceStore: boolean;\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all identifiers in the organization\n *\n * @param client - GraphQL client\n * @returns All identifiers in the organization\n */\nexport async function fetchAllIdentifiers(\n client: GraphQLClient,\n): Promise<Identifier[]> {\n const identifiers: Identifier[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n identifiers: { nodes },\n } = await makeGraphQLRequest<{\n /** Identifiers */\n identifiers: {\n /** List */\n nodes: Identifier[];\n };\n }>(client, IDENTIFIERS, {\n first: PAGE_SIZE,\n offset,\n });\n identifiers.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return identifiers.sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/**\n * Fetch all identifiers and if any are found in the config that are\n * missing, create those identifiers.\n *\n * @param input - Transcend input\n * @param client - GraphQL client\n * @param skipPublish - When true, skip publishing to privacy center\n * @returns A map from identifier name to Identifier\n */\nexport async function fetchIdentifiersAndCreateMissing(\n {\n enrichers = [],\n 'data-silos': dataSilos = [],\n identifiers = [],\n }: TranscendInput,\n client: GraphQLClient,\n skipPublish = false,\n): Promise<{ [k in string]: Identifier }> {\n // Grab all existing identifiers\n const allIdentifiers = await fetchAllIdentifiers(client);\n\n // Create a map\n const identifiersByName = keyBy(allIdentifiers, 'name');\n\n // Determine expected set of identifiers\n const expectedIdentifiers = uniq([\n ...flatten(\n enrichers.map((enricher) => [\n enricher['input-identifier'],\n ...enricher['output-identifiers'],\n ]),\n ),\n ...flatten(dataSilos.map((dataSilo) => dataSilo['identity-keys'])),\n ...identifiers.map(({ name }) => name),\n ]).filter((x) => !!x);\n const missingIdentifiers = difference(\n expectedIdentifiers,\n allIdentifiers.map(({ name }) => name),\n );\n\n // If there are missing identifiers, create new ones\n if (missingIdentifiers.length > 0) {\n logger.info(\n colors.magenta(\n `Creating ${missingIdentifiers.length} new identifiers...`,\n ),\n );\n const { newIdentifierTypes } = await makeGraphQLRequest<{\n /** Query response */\n newIdentifierTypes: {\n /** Name of identifier type remaining */\n name: string;\n }[];\n }>(client, NEW_IDENTIFIER_TYPES);\n const nativeTypesRemaining = newIdentifierTypes.map(({ name }) => name);\n await mapSeries(missingIdentifiers, async (identifier) => {\n logger.info(colors.magenta(`Creating identifier ${identifier}...`));\n const { createIdentifier } = await makeGraphQLRequest<{\n /** createIdentifier Response */\n createIdentifier: {\n /** Created identifier */\n identifier: Identifier;\n };\n }>(client, CREATE_IDENTIFIER, {\n input: {\n name: identifier,\n type: nativeTypesRemaining.includes(identifier!)\n ? identifier\n : 'custom',\n skipPublish,\n },\n });\n logger.info(colors.green(`Created identifier ${identifier}!`));\n\n identifiersByName[identifier!] = createIdentifier.identifier;\n });\n }\n return identifiersByName;\n}\n","import { TeamInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport { UPDATE_TEAM, CREATE_TEAM } from './gqls';\nimport { logger } from '../../logger';\nimport { keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport colors from 'colors';\nimport { fetchAllTeams, Team } from './fetchAllTeams';\n\n/**\n * Input to create a new team\n *\n * @param client - GraphQL client\n * @param team - Input\n * @returns Created team\n */\nexport async function createTeam(\n client: GraphQLClient,\n team: TeamInput,\n): Promise<Pick<Team, 'id' | 'name'>> {\n const input = {\n name: team.name,\n description: team.description,\n ssoTitle: team['sso-title'],\n ssoDepartment: team['sso-department'],\n ssoGroup: team['sso-group'],\n scopes: team.scopes,\n userEmails: team.users,\n };\n\n const { createTeam } = await makeGraphQLRequest<{\n /** Create team mutation */\n createTeam: {\n /** Created team */\n team: Team;\n };\n }>(client, CREATE_TEAM, {\n input,\n });\n return createTeam.team;\n}\n\n/**\n * Input to update teams\n *\n * @param client - GraphQL client\n * @param input - Team input to update\n * @param teamId - ID of team\n * @returns Updated team\n */\nexport async function updateTeam(\n client: GraphQLClient,\n input: TeamInput,\n teamId: string,\n): Promise<Pick<Team, 'id' | 'name'>> {\n const { updateTeam } = await makeGraphQLRequest<{\n /** Update team mutation */\n updateTeam: {\n /** Updated team */\n team: Team;\n };\n }>(client, UPDATE_TEAM, {\n input: {\n id: teamId,\n name: input.name,\n description: input.description,\n ssoTitle: input['sso-title'],\n ssoDepartment: input['sso-department'],\n ssoGroup: input['sso-group'],\n scopes: input.scopes,\n userEmails: input.users,\n },\n });\n return updateTeam.team;\n}\n\n/**\n * Sync the teams\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncTeams(\n client: GraphQLClient,\n inputs: TeamInput[],\n): Promise<boolean> {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${inputs.length}\" teams...`));\n\n let encounteredError = false;\n\n // Fetch existing\n const existingTeams = await fetchAllTeams(client);\n\n // Look up by name\n const teamsByName: { [k in string]: Pick<Team, 'id' | 'name'> } = keyBy(\n existingTeams,\n 'name',\n );\n\n // Create new teams\n const newTeams = inputs.filter((input) => !teamsByName[input.name]);\n const updatedTeams = inputs.filter((input) => !!teamsByName[input.name]);\n\n // Create new teams\n await mapSeries(newTeams, async (team) => {\n try {\n const newTeam = await createTeam(client, team);\n teamsByName[newTeam.name] = newTeam;\n logger.info(colors.green(`Successfully created team \"${team.name}\"!`));\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to sync team \"${team.name}\"! - ${err.message}`),\n );\n }\n });\n\n // Update all teams\n await mapSeries(updatedTeams, async (input) => {\n try {\n const newTeam = await updateTeam(\n client,\n input,\n teamsByName[input.name].id,\n );\n teamsByName[newTeam.name] = newTeam;\n logger.info(colors.green(`Successfully updated team \"${input.name}\"!`));\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to sync team \"${input.name}\"! - ${err.message}`),\n );\n }\n });\n\n return !encounteredError;\n}\n","import { PromptPartialInput } from '../../codecs';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { UPDATE_PROMPT_PARTIALS, CREATE_PROMPT_PARTIAL } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { map } from '../bluebird';\nimport { fetchAllPromptPartials } from './fetchPromptPartials';\nimport { keyBy } from 'lodash-es';\nimport { logger } from '../../logger';\n\n/**\n * Create a new prompt partial\n *\n * @param client - GraphQL client\n * @param input - Prompt input\n * @returns Prompt partial ID\n */\nexport async function createPromptPartial(\n client: GraphQLClient,\n input: {\n /** Title of prompt partial */\n title: string;\n /** Prompt content */\n content: string;\n },\n): Promise<string> {\n const {\n createPromptPartial: { promptPartial },\n } = await makeGraphQLRequest<{\n /** createPromptPartial mutation */\n createPromptPartial: {\n /** Prompt partial */\n promptPartial: {\n /** ID */\n id: string;\n };\n };\n }>(client, CREATE_PROMPT_PARTIAL, {\n input,\n });\n logger.info(\n colors.green(`Successfully created prompt partial \"${input.title}\"!`),\n );\n return promptPartial.id;\n}\n\n/**\n * Update a set of existing prompt partials\n *\n * @param client - GraphQL client\n * @param input - Prompt input\n */\nexport async function updatePromptPartials(\n client: GraphQLClient,\n input: [PromptPartialInput, string][],\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_PROMPT_PARTIALS, {\n input: {\n promptPartials: input.map(([input, id]) => ({\n ...input,\n id,\n })),\n },\n });\n logger.info(\n colors.green(`Successfully updated ${input.length} prompt partials!`),\n );\n}\n\n/**\n * Sync the prompt partials\n *\n * @param client - GraphQL client\n * @param promptPartials - PromptPartials\n * @param concurrency - Concurrency\n * @returns True if synced successfully\n */\nexport async function syncPromptPartials(\n client: GraphQLClient,\n promptPartials: PromptPartialInput[],\n concurrency = 20,\n): Promise<boolean> {\n let encounteredError = false;\n logger.info(\n colors.magenta(`Syncing \"${promptPartials.length}\" prompt partials...`),\n );\n\n // Index existing prompt partials\n const existing = await fetchAllPromptPartials(client);\n const promptPartialByTitle = keyBy(existing, 'title');\n\n // Determine which promptPartials are new vs existing\n const mapPromptPartialsToExisting = promptPartials.map((promptInput) => [\n promptInput,\n promptPartialByTitle[promptInput.title]?.id,\n ]);\n\n // Create the new promptPartials\n const newPromptPartials = mapPromptPartialsToExisting\n .filter(([, existing]) => !existing)\n .map(([promptInput]) => promptInput as PromptPartialInput);\n try {\n logger.info(\n colors.magenta(\n `Creating \"${newPromptPartials.length}\" new prompt partials...`,\n ),\n );\n await map(\n newPromptPartials,\n async (prompt) => {\n await createPromptPartial(client, prompt);\n },\n {\n concurrency,\n },\n );\n logger.info(\n colors.green(\n `Successfully synced ${newPromptPartials.length} prompt partials!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to create prompt partials! - ${err.message}`),\n );\n }\n\n // Update existing promptPartials\n const existingPromptPartials = mapPromptPartialsToExisting.filter(\n (x): x is [PromptPartialInput, string] => !!x[1],\n );\n try {\n logger.info(\n colors.magenta(\n `Updating \"${existingPromptPartials.length}\" prompt partials...`,\n ),\n );\n await updatePromptPartials(client, existingPromptPartials);\n logger.info(\n colors.green(\n `Successfully updated \"${existingPromptPartials.length}\" prompt partials!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to create prompt partials! - ${err.message}`),\n );\n }\n\n logger.info(\n colors.green(`Synced \"${promptPartials.length}\" prompt partials!`),\n );\n\n // Return true upon success\n return !encounteredError;\n}\n","import { PromptGroupInput } from '../../codecs';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { UPDATE_PROMPT_GROUPS, CREATE_PROMPT_GROUP } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { map } from '../bluebird';\nimport { fetchAllPromptGroups } from './fetchPromptGroups';\nimport { keyBy } from 'lodash-es';\nimport { logger } from '../../logger';\nimport { fetchAllPrompts } from './fetchPrompts';\n\nexport interface EditPromptGroupInput {\n /** Title of prompt group */\n title: string;\n /** Prompt group description */\n description: string;\n /** Prompt IDs */\n promptIds: string[];\n}\n\n/**\n * Create a new prompt group\n *\n * @param client - GraphQL client\n * @param input - Prompt input\n * @returns Prompt group ID\n */\nexport async function createPromptGroup(\n client: GraphQLClient,\n input: EditPromptGroupInput,\n): Promise<string> {\n const {\n createPromptGroup: { promptGroup },\n } = await makeGraphQLRequest<{\n /** createPromptGroup mutation */\n createPromptGroup: {\n /** Prompt group */\n promptGroup: {\n /** ID */\n id: string;\n };\n };\n }>(client, CREATE_PROMPT_GROUP, {\n input,\n });\n logger.info(\n colors.green(`Successfully created prompt group \"${input.title}\"!`),\n );\n return promptGroup.id;\n}\n\n/**\n * Update a set of existing prompt groups\n *\n * @param client - GraphQL client\n * @param input - Prompt input\n */\nexport async function updatePromptGroups(\n client: GraphQLClient,\n input: [EditPromptGroupInput, string][],\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_PROMPT_GROUPS, {\n input: {\n promptGroups: input.map(([input, id]) => ({\n ...input,\n id,\n })),\n },\n });\n logger.info(\n colors.green(`Successfully updated ${input.length} prompt groups!`),\n );\n}\n\n/**\n * Sync the prompt groups\n *\n * @param client - GraphQL client\n * @param promptGroups - PromptGroups\n * @param concurrency - Concurrency\n * @returns True if synced successfully\n */\nexport async function syncPromptGroups(\n client: GraphQLClient,\n promptGroups: PromptGroupInput[],\n concurrency = 20,\n): Promise<boolean> {\n let encounteredError = false;\n logger.info(\n colors.magenta(`Syncing \"${promptGroups.length}\" prompt groups...`),\n );\n\n // Index existing prompt groups\n const existing = await fetchAllPromptGroups(client);\n const existingPrompts = await fetchAllPrompts(client);\n const promptByTitle = keyBy(existingPrompts, 'title');\n const promptGroupByTitle = keyBy(existing, 'title');\n\n // Determine which promptGroups are new vs existing\n const mapPromptGroupsToExisting = promptGroups.map((promptInput) => [\n promptInput,\n promptGroupByTitle[promptInput.title]?.id,\n ]);\n\n // Create the new promptGroups\n const newPromptGroups = mapPromptGroupsToExisting\n .filter(([, existing]) => !existing)\n .map(([promptInput]) => promptInput as PromptGroupInput);\n try {\n logger.info(\n colors.magenta(\n `Creating \"${newPromptGroups.length}\" new prompt groups...`,\n ),\n );\n await map(\n newPromptGroups,\n async (prompt) => {\n await createPromptGroup(client, {\n ...prompt,\n promptIds: prompt.prompts.map((title) => {\n const prompt = promptByTitle[title];\n if (!prompt) {\n throw new Error(`Failed to find prompt with title: \"${title}\"`);\n }\n return prompt.id;\n }),\n });\n },\n {\n concurrency,\n },\n );\n logger.info(\n colors.green(\n `Successfully synced ${newPromptGroups.length} prompt groups!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create prompt groups! - ${err.message}`));\n }\n\n // Update existing promptGroups\n const existingPromptGroups = mapPromptGroupsToExisting.filter(\n (x): x is [PromptGroupInput, string] => !!x[1],\n );\n try {\n logger.info(\n colors.magenta(\n `Updating \"${existingPromptGroups.length}\" prompt groups...`,\n ),\n );\n await updatePromptGroups(\n client,\n existingPromptGroups.map(([{ prompts, ...input }, id]) => [\n {\n ...input,\n promptIds: prompts.map((title) => {\n const prompt = promptByTitle[title];\n if (!prompt) {\n throw new Error(`Failed to find prompt with title: \"${title}\"`);\n }\n return prompt.id;\n }),\n },\n id,\n ]),\n );\n logger.info(\n colors.green(\n `Successfully updated \"${existingPromptGroups.length}\" prompt groups!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create prompt groups! - ${err.message}`));\n }\n\n logger.info(colors.green(`Synced \"${promptGroups.length}\" prompt groups!`));\n\n // Return true upon success\n return !encounteredError;\n}\n","/* eslint-disable max-lines */\nimport { TranscendInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { logger } from '../../logger';\nimport colors from 'colors';\nimport { map } from '../bluebird';\nimport {\n fetchIdentifiersAndCreateMissing,\n Identifier,\n} from './fetchIdentifiers';\nimport { syncIdentifier } from './syncIdentifier';\nimport { syncEnricher } from './syncEnrichers';\nimport { syncAttribute } from './syncAttribute';\nimport { syncDataSiloDependencies, syncDataSilos } from './syncDataSilos';\nimport { syncCookies } from './syncCookies';\nimport {\n fetchAllDataSubjects,\n ensureAllDataSubjectsExist,\n} from './fetchDataSubjects';\nimport { syncTeams } from './syncTeams';\nimport { syncDataSubject } from './syncDataSubject';\nimport { fetchApiKeys } from './fetchApiKeys';\nimport { syncPrompts } from './syncPrompts';\nimport { syncPolicies } from './syncPolicies';\nimport { syncIntlMessages } from './syncIntlMessages';\nimport { syncPrivacyCenter } from './syncPrivacyCenter';\nimport { syncConsentManager } from './syncConsentManager';\nimport { fetchAllAttributes } from './fetchAllAttributes';\nimport { syncBusinessEntities } from './syncBusinessEntities';\nimport { syncDataFlows } from './syncDataFlows';\nimport { syncAction } from './syncAction';\nimport { syncTemplate } from './syncTemplates';\nimport { fetchAllActions } from './fetchAllActions';\nimport { syncPromptPartials } from './syncPromptPartials';\nimport { syncPromptGroups } from './syncPromptGroups';\nimport { syncAgents } from './syncAgents';\nimport { syncActionItemCollections } from './syncActionItemCollections';\nimport { syncActionItems } from './syncActionItems';\nimport { syncAgentFunctions } from './syncAgentFunctions';\nimport { syncAgentFiles } from './syncAgentFiles';\nimport { syncVendors } from './syncVendors';\nimport { syncDataCategories } from './syncDataCategories';\nimport { syncProcessingPurposes } from './syncProcessingPurposes';\nimport { syncProcessingActivities } from './syncProcessingActivities';\nimport { syncPartitions } from './syncPartitions';\n\nconst CONCURRENCY = 10;\n\n/**\n * Sync the yaml input back to Transcend using the GraphQL APIs\n *\n * @param input - The yml input\n * @param client - GraphQL client\n * @param pageSize - Page size\n * @returns True if an error was encountered\n */\nexport async function syncConfigurationToTranscend(\n input: TranscendInput,\n client: GraphQLClient,\n {\n pageSize = 50,\n // TODO: https://transcend.height.app/T-23779\n publishToPrivacyCenter = true,\n classifyService = false,\n deleteExtraAttributeValues = false,\n }: {\n /** Page size */\n pageSize?: number;\n /** When true, skip publishing to privacy center */\n publishToPrivacyCenter?: boolean;\n /** When true, delete any attributes being synced up */\n deleteExtraAttributeValues?: boolean;\n /** classify data flow service if missing */\n classifyService?: boolean;\n },\n): Promise<boolean> {\n let encounteredError = false;\n\n logger.info(colors.magenta(`Fetching data with page size ${pageSize}...`));\n\n const {\n templates,\n attributes,\n actions,\n identifiers,\n 'data-subjects': dataSubjects,\n 'business-entities': businessEntities,\n enrichers,\n cookies,\n 'consent-manager': consentManager,\n 'data-silos': dataSilos,\n 'data-flows': dataFlows,\n prompts,\n 'prompt-groups': promptGroups,\n 'prompt-partials': promptPartials,\n agents,\n 'agent-functions': agentFunctions,\n 'agent-files': agentFiles,\n vendors,\n 'data-categories': dataCategories,\n 'processing-activities': processingActivities,\n 'processing-purposes': processingPurposes,\n 'action-items': actionItems,\n 'action-item-collections': actionItemCollections,\n teams,\n 'privacy-center': privacyCenter,\n messages,\n policies,\n partitions,\n } = input;\n\n const [identifierByName, dataSubjectsByName, apiKeyTitleMap] =\n await Promise.all([\n // Ensure all identifiers are created and create a map from name -> identifier.id\n enrichers || identifiers\n ? fetchIdentifiersAndCreateMissing(\n input,\n client,\n !publishToPrivacyCenter,\n )\n : ({} as { [k in string]: Identifier }),\n // Grab all data subjects in the organization\n dataSilos || dataSubjects || enrichers || processingActivities\n ? ensureAllDataSubjectsExist(input, client)\n : {},\n // Grab API keys\n dataSilos &&\n dataSilos\n .map((dataSilo) => dataSilo['api-key-title'] || [])\n .reduce((acc, lst) => acc + lst.length, 0) > 0\n ? fetchApiKeys(input, client)\n : {},\n ]);\n\n // Sync consent manager\n if (consentManager) {\n logger.info(colors.magenta('Syncing consent manager...'));\n try {\n await syncConsentManager(client, consentManager);\n logger.info(colors.green('Successfully synced consent manager!'));\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to sync consent manager! - ${err.message}`),\n );\n }\n }\n\n // Sync prompts\n if (prompts) {\n const promptsSuccess = await syncPrompts(client, prompts);\n encounteredError = encounteredError || !promptsSuccess;\n }\n if (promptPartials) {\n const promptsSuccess = await syncPromptPartials(client, promptPartials);\n encounteredError = encounteredError || !promptsSuccess;\n }\n if (promptGroups) {\n const promptsSuccess = await syncPromptGroups(client, promptGroups);\n encounteredError = encounteredError || !promptsSuccess;\n }\n\n if (teams) {\n const teamsSuccess = await syncTeams(client, teams);\n encounteredError = encounteredError || !teamsSuccess;\n }\n\n // Sync email templates\n if (templates) {\n logger.info(\n colors.magenta(`Syncing \"${templates.length}\" email templates...`),\n );\n await map(\n templates,\n async (template) => {\n logger.info(colors.magenta(`Syncing template \"${template.title}\"...`));\n try {\n await syncTemplate(template, client);\n logger.info(\n colors.green(`Successfully synced template \"${template.title}\"!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync template \"${template.title}\"! - ${err.message}`,\n ),\n );\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${templates.length}\" email templates!`));\n }\n\n // Sync business entities\n if (businessEntities) {\n const businessEntitySuccess = await syncBusinessEntities(\n client,\n businessEntities,\n );\n encounteredError = encounteredError || !businessEntitySuccess;\n }\n\n // Sync vendors\n if (vendors) {\n const vendorsSuccess = await syncVendors(client, vendors);\n encounteredError = encounteredError || !vendorsSuccess;\n }\n\n // Sync data categories\n if (dataCategories) {\n const dataCategoriesSuccess = await syncDataCategories(\n client,\n dataCategories,\n );\n encounteredError = encounteredError || !dataCategoriesSuccess;\n }\n\n // Sync processing purposes\n if (processingPurposes) {\n const processingPurposesSuccess = await syncProcessingPurposes(\n client,\n processingPurposes,\n );\n encounteredError = encounteredError || !processingPurposesSuccess;\n }\n\n // Sync partitions\n if (partitions) {\n const partitionsSuccess = await syncPartitions(client, partitions);\n encounteredError = encounteredError || !partitionsSuccess;\n }\n\n // Sync agents\n if (agents) {\n const agentsSuccess = await syncAgents(client, agents);\n encounteredError = encounteredError || !agentsSuccess;\n }\n\n // Sync agent functions\n if (agentFunctions) {\n const agentFunctionsSuccess = await syncAgentFunctions(\n client,\n agentFunctions,\n );\n encounteredError = encounteredError || !agentFunctionsSuccess;\n }\n\n // Sync agent files\n if (agentFiles) {\n const agentFilesSuccess = await syncAgentFiles(client, agentFiles);\n encounteredError = encounteredError || !agentFilesSuccess;\n }\n\n // Sync cookies\n if (cookies) {\n const cookiesSuccess = await syncCookies(client, cookies);\n encounteredError = encounteredError || !cookiesSuccess;\n }\n\n // Sync action item collections\n if (actionItemCollections) {\n const actionItemCollectionsSuccess = await syncActionItemCollections(\n client,\n actionItemCollections,\n );\n encounteredError = encounteredError || !actionItemCollectionsSuccess;\n }\n\n // Sync attributes\n if (attributes) {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${attributes.length}\" attributes...`));\n const existingAttributes = await fetchAllAttributes(client);\n await map(\n attributes,\n async (attribute) => {\n const existing = existingAttributes.find(\n (attr) => attr.name === attribute.name,\n );\n\n logger.info(colors.magenta(`Syncing attribute \"${attribute.name}\"...`));\n try {\n await syncAttribute(client, attribute, {\n existingAttribute: existing,\n deleteExtraAttributeValues,\n });\n logger.info(\n colors.green(`Successfully synced attribute \"${attribute.name}\"!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync attribute \"${attribute.name}\"! - ${err.message}`,\n ),\n );\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${attributes.length}\" attributes!`));\n }\n\n // Sync action items\n if (actionItems) {\n const actionItemsSuccess = await syncActionItems(client, actionItems);\n encounteredError = encounteredError || !actionItemsSuccess;\n }\n\n // Sync enrichers\n if (enrichers) {\n logger.info(colors.magenta(`Syncing \"${enrichers.length}\" enrichers...`));\n await map(\n enrichers,\n async (enricher) => {\n logger.info(colors.magenta(`Syncing enricher \"${enricher.title}\"...`));\n try {\n await syncEnricher(client, {\n enricher,\n identifierByName,\n dataSubjectsByName,\n });\n logger.info(\n colors.green(`Successfully synced enricher \"${enricher.title}\"!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync enricher \"${enricher.title}\"! - ${err.message}`,\n ),\n );\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${enrichers.length}\" enrichers!`));\n }\n\n // Sync identifiers\n if (identifiers) {\n // Fetch existing\n logger.info(\n colors.magenta(`Syncing \"${identifiers.length}\" identifiers...`),\n );\n await map(\n identifiers,\n async (identifier) => {\n const existing = identifierByName[identifier.name];\n if (!existing) {\n throw new Error(\n `Failed to find identifier with name: ${identifier.type}. Should have been auto-created by cli.`,\n );\n }\n\n logger.info(\n colors.magenta(`Syncing identifier \"${identifier.type}\"...`),\n );\n try {\n await syncIdentifier(client, {\n identifier,\n dataSubjectsByName,\n identifierId: existing.id,\n skipPublish: !publishToPrivacyCenter,\n });\n logger.info(\n colors.green(\n `Successfully synced identifier \"${identifier.type}\"!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync identifier \"${identifier.type}\"! - ${err.message}`,\n ),\n );\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${identifiers.length}\" identifiers!`));\n }\n\n // Sync actions\n if (actions) {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${actions.length}\" actions...`));\n const existingActions = await fetchAllActions(client);\n await map(\n actions,\n async (action) => {\n const existing = existingActions.find(\n (act) => act.type === action.type,\n );\n if (!existing) {\n throw new Error(\n `Failed to find action with type: ${action.type}. Should have already existing in the organization.`,\n );\n }\n\n logger.info(colors.magenta(`Syncing action \"${action.type}\"...`));\n try {\n await syncAction(client, {\n action,\n actionId: existing.id,\n skipPublish: !publishToPrivacyCenter,\n });\n logger.info(\n colors.green(`Successfully synced action \"${action.type}\"!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync action \"${action.type}\"! - ${err.message}`,\n ),\n );\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${actions.length}\" actions!`));\n }\n\n // Sync data subjects\n if (dataSubjects) {\n // Fetch existing\n logger.info(\n colors.magenta(`Syncing \"${dataSubjects.length}\" data subjects...`),\n );\n const existingDataSubjects = await fetchAllDataSubjects(client);\n await map(\n dataSubjects,\n async (dataSubject) => {\n const existing = existingDataSubjects.find(\n (subj) => subj.type === dataSubject.type,\n );\n if (!existing) {\n throw new Error(\n `Failed to find data subject with type: ${dataSubject.type}. Should have already existing in the organization.`,\n );\n }\n\n logger.info(\n colors.magenta(`Syncing data subject \"${dataSubject.type}\"...`),\n );\n try {\n await syncDataSubject(client, {\n dataSubject,\n dataSubjectId: existing.id,\n skipPublish: !publishToPrivacyCenter,\n });\n logger.info(\n colors.green(\n `Successfully synced data subject \"${dataSubject.type}\"!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync data subject \"${dataSubject.type}\"! - ${err.message}`,\n ),\n );\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${dataSubjects.length}\" data subjects!`));\n }\n\n // Sync data flows\n if (dataFlows) {\n const syncedDataFlows = await syncDataFlows(\n client,\n dataFlows,\n classifyService,\n );\n encounteredError = encounteredError || !syncedDataFlows;\n }\n\n // Sync privacy center\n if (privacyCenter) {\n const privacyCenterSuccess = await syncPrivacyCenter(client, privacyCenter);\n encounteredError = encounteredError || !privacyCenterSuccess;\n }\n\n // Sync messages\n if (messages) {\n const messagesSuccess = await syncIntlMessages(client, messages);\n encounteredError = encounteredError || !messagesSuccess;\n }\n\n // Sync policies\n if (policies) {\n const policiesSuccess = await syncPolicies(client, policies);\n encounteredError = encounteredError || !policiesSuccess;\n }\n\n // Store dependency updates\n const dependencyUpdates: [string, string[]][] = [];\n // Sync data silos\n if (dataSilos) {\n const { success, dataSiloTitleToId } = await syncDataSilos(\n dataSilos,\n client,\n {\n dataSubjectsByName,\n apiKeysByTitle: apiKeyTitleMap,\n pageSize,\n },\n );\n dataSilos?.forEach((dataSilo) => {\n // Queue up dependency update\n if (dataSilo['deletion-dependencies']) {\n dependencyUpdates.push([\n dataSiloTitleToId[dataSilo.title],\n dataSilo['deletion-dependencies'],\n ]);\n }\n });\n encounteredError = encounteredError || !success;\n }\n\n // Dependencies updated at the end after all data silos are created\n if (dependencyUpdates.length > 0) {\n await syncDataSiloDependencies(client, dependencyUpdates);\n }\n\n // Update processing activities\n if (processingActivities) {\n const processingActivitySuccess = await syncProcessingActivities(\n client,\n processingActivities,\n );\n encounteredError = encounteredError || !processingActivitySuccess;\n }\n\n if (publishToPrivacyCenter) {\n // TODO: https://transcend.height.app/T-23779\n }\n\n return encounteredError;\n}\n/* eslint-enable max-lines */\n"],"x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56],"mappings":"izBACA,IAAI,EAAe,KAUnB,SAAS,EAAgB,EAAQ,CAG/B,IAFA,IAAI,EAAQ,EAAO,OAEZ,KAAW,EAAa,KAAK,EAAO,OAAO,EAAM,CAAC,GACzD,OAAO,EAGT,IAAA,EAAe,ECfX,EAAc,OASlB,SAAS,EAAS,EAAQ,CACxB,OAAO,GACH,EAAO,MAAM,EAAGA,EAAgB,EAAO,CAAG,EAAE,CAAC,QAAQ,EAAa,GAAG,CAI3E,IAAA,EAAe,ECbX,EAAM,IAGN,EAAa,qBAGb,EAAa,aAGb,EAAY,cAGZ,EAAe,SAyBnB,SAAS,EAAS,EAAO,CACvB,GAAI,OAAO,GAAS,SAClB,OAAO,EAET,GAAIC,EAAAA,EAAS,EAAM,CACjB,OAAO,EAET,GAAIC,EAAAA,EAAS,EAAM,CAAE,CACnB,IAAI,EAAQ,OAAO,EAAM,SAAW,WAAa,EAAM,SAAS,CAAG,EACnE,EAAQA,EAAAA,EAAS,EAAM,CAAI,EAAQ,GAAM,EAE3C,GAAI,OAAO,GAAS,SAClB,OAAO,IAAU,EAAI,EAAQ,CAAC,EAEhC,EAAQC,EAAS,EAAM,CACvB,IAAI,EAAW,EAAW,KAAK,EAAM,CACrC,OAAQ,GAAY,EAAU,KAAK,EAAM,CACrC,EAAa,EAAM,MAAM,EAAE,CAAE,EAAW,EAAI,EAAE,CAC7C,EAAW,KAAK,EAAM,CAAG,EAAM,CAAC,EAGvC,IAAA,EAAe,EC5DX,EAAW,IACX,GAAc,sBAyBlB,SAAS,EAAS,EAAO,CASvB,OARK,GAGL,EAAQC,EAAS,EAAM,CACnB,IAAU,GAAY,IAAU,CAAC,GACvB,EAAQ,EAAI,GAAK,GACf,GAET,IAAU,EAAQ,EAAQ,GAPxB,IAAU,EAAI,EAAQ,EAUjC,IAAA,GAAe,ECbf,SAAS,EAAU,EAAO,CACxB,IAAI,EAASC,GAAS,EAAM,CACxB,EAAY,EAAS,EAEzB,OAAO,IAAW,EAAU,EAAY,EAAS,EAAY,EAAU,EAGzE,IAAA,GAAe,ECzBf,SAASC,GAAM,EAAM,EAAS,EAAM,CAClC,OAAQ,EAAK,OAAb,CACE,IAAK,GAAG,OAAO,EAAK,KAAK,EAAQ,CACjC,IAAK,GAAG,OAAO,EAAK,KAAK,EAAS,EAAK,GAAG,CAC1C,IAAK,GAAG,OAAO,EAAK,KAAK,EAAS,EAAK,GAAI,EAAK,GAAG,CACnD,IAAK,GAAG,OAAO,EAAK,KAAK,EAAS,EAAK,GAAI,EAAK,GAAI,EAAK,GAAG,CAE9D,OAAO,EAAK,MAAM,EAAS,EAAK,CAGlC,IAAA,GAAeA,GCRf,SAAS,IAAO,EAIhB,IAAA,GAAe,GCfX,GAAY,IACZ,GAAW,GAGX,GAAY,KAAK,IAWrB,SAAS,GAAS,EAAM,CACtB,IAAI,EAAQ,EACR,EAAa,EAEjB,OAAO,UAAW,CAChB,IAAI,EAAQ,IAAW,CACnB,EAAY,IAAY,EAAQ,GAGpC,GADA,EAAa,EACT,EAAY,MACV,EAAE,GAAS,GACb,OAAO,UAAU,QAGnB,EAAQ,EAEV,OAAO,EAAK,MAAM,IAAA,GAAW,UAAU,EAI3C,IAAA,EAAe,GCjBf,SAAS,GAAS,EAAO,CACvB,OAAO,UAAW,CAChB,OAAO,GAIX,IAAA,GAAe,GCbX,GAAmBC,EAAAA,EAA4B,SAAS,EAAM,EAAQ,CACxE,OAAOA,EAAAA,EAAe,EAAM,WAAY,CACtC,aAAgB,GAChB,WAAc,GACd,MAASE,GAAS,EAAO,CACzB,SAAY,GACb,CAAC,EANoCD,EAAAA,EASxC,GAAe,GCVX,GAAcE,EAASC,GAAgB,CAE3C,GAAe,GCFf,SAAS,GAAc,EAAO,EAAW,EAAW,EAAW,CAI7D,IAHA,IAAI,EAAS,EAAM,OACf,EAAQ,GAAa,EAAY,EAAI,IAEjC,EAAY,IAAU,EAAE,EAAQ,GACtC,GAAI,EAAU,EAAM,GAAQ,EAAO,EAAM,CACvC,OAAO,EAGX,MAAO,GAGT,IAAA,GAAe,GChBf,SAAS,GAAU,EAAO,CACxB,OAAO,IAAU,EAGnB,IAAA,GAAe,GCDf,SAAS,GAAc,EAAO,EAAO,EAAW,CAI9C,IAHA,IAAI,EAAQ,EAAY,EACpB,EAAS,EAAM,OAEZ,EAAE,EAAQ,GACf,GAAI,EAAM,KAAW,EACnB,OAAO,EAGX,MAAO,GAGT,IAAA,GAAe,GCTf,SAAS,GAAY,EAAO,EAAO,EAAW,CAC5C,OAAO,IAAU,EACbC,GAAc,EAAO,EAAO,EAAU,CACtCC,GAAc,EAAOC,GAAW,EAAU,CAGhD,IAAA,GAAe,GCRf,SAAS,GAAc,EAAO,EAAO,CAEnC,MAAO,CAAC,EADK,GAAS,MAAW,EAAM,SACpBC,GAAY,EAAO,EAAO,EAAE,CAAG,GAGpD,IAAA,GAAe,GCbXC,GAAY,KAAK,IAWrB,SAAS,GAAS,EAAM,EAAO,EAAW,CAExC,MADA,GAAQA,GAAU,IAAU,IAAA,GAAa,EAAK,OAAS,EAAK,EAAO,EAAE,CAC9D,UAAW,CAMhB,IALA,IAAI,EAAO,UACP,EAAQ,GACR,EAASA,GAAU,EAAK,OAAS,EAAO,EAAE,CAC1C,EAAQ,MAAM,EAAO,CAElB,EAAE,EAAQ,GACf,EAAM,GAAS,EAAK,EAAQ,GAE9B,EAAQ,GAER,IADA,IAAI,EAAY,MAAM,EAAQ,EAAE,CACzB,EAAE,EAAQ,GACf,EAAU,GAAS,EAAK,GAG1B,MADA,GAAU,GAAS,EAAU,EAAM,CAC5BC,GAAM,EAAM,KAAM,EAAU,EAIvC,IAAA,GAAe,GCvBf,SAAS,GAAS,EAAM,EAAO,CAC7B,OAAOC,GAAYC,GAAS,EAAM,EAAOC,EAAAA,EAAS,CAAE,EAAO,GAAG,CAGhE,IAAA,GAAe,GCDf,SAAS,GAAe,EAAO,EAAO,EAAQ,CAC5C,GAAI,CAACC,EAAAA,EAAS,EAAO,CACnB,MAAO,GAET,IAAI,EAAO,OAAO,EAOlB,OANI,GAAQ,SACHC,EAAAA,EAAY,EAAO,EAAIC,EAAAA,EAAQ,EAAO,EAAO,OAAO,CACpD,GAAQ,UAAY,KAAS,GAE7BC,EAAAA,EAAG,EAAO,GAAQ,EAAM,CAE1B,GAGT,IAAA,GAAe,GCxBX,GAAmBC,EAAAA,EAASA,EAAAA,EAAO,mBAAqB,IAAA,GAS5D,SAAS,GAAc,EAAO,CAC5B,OAAOC,EAAAA,EAAQ,EAAM,EAAIC,EAAAA,EAAY,EAAM,EACzC,CAAC,EAAE,IAAoB,GAAS,EAAM,KAG1C,IAAA,GAAe,GCLf,SAAS,GAAY,EAAO,EAAO,EAAW,EAAU,EAAQ,CAC9D,IAAI,EAAQ,GACR,EAAS,EAAM,OAKnB,IAHA,AAAc,IAAYC,GAC1B,AAAW,IAAS,EAAE,CAEf,EAAE,EAAQ,GAAQ,CACvB,IAAI,EAAQ,EAAM,GACd,EAAQ,GAAK,EAAU,EAAM,CAC3B,EAAQ,EAEV,GAAY,EAAO,EAAQ,EAAG,EAAW,EAAU,EAAO,CAE1D,EAAA,EAAU,EAAQ,EAAM,CAEhB,IACV,EAAO,EAAO,QAAU,GAG5B,OAAO,EAGT,IAAA,GAAe,GCrBf,SAAS,GAAQ,EAAO,CAEtB,OADa,GAAS,MAAW,EAAM,OACvBC,GAAY,EAAO,EAAE,CAAG,EAAE,CAG5C,IAAA,GAAe,GCZf,SAAS,GAAU,EAAO,EAAO,EAAK,CACpC,IAAI,EAAQ,GACR,EAAS,EAAM,OAEf,EAAQ,IACV,EAAQ,CAAC,EAAQ,EAAS,EAAK,EAAS,GAE1C,EAAM,EAAM,EAAS,EAAS,EAC1B,EAAM,IACR,GAAO,GAET,EAAS,EAAQ,EAAM,EAAM,EAAM,IAAW,EAC9C,KAAW,EAGX,IADA,IAAI,EAAS,MAAM,EAAO,CACnB,EAAE,EAAQ,GACf,EAAO,GAAS,EAAM,EAAQ,GAEhC,OAAO,EAGT,IAAA,GAAe,GCnBf,SAAS,GAAU,EAAO,EAAO,EAAK,CACpC,IAAI,EAAS,EAAM,OAEnB,MADA,GAAM,IAAQ,IAAA,GAAY,EAAS,EAC3B,CAAC,GAAS,GAAO,EAAU,EAAQC,GAAU,EAAO,EAAO,EAAI,CAGzE,IAAA,GAAe,GCLX,GAAe,OAAO,sFAA+D,CASzF,SAAS,GAAW,EAAQ,CAC1B,OAAO,GAAa,KAAK,EAAO,CAGlC,IAAA,GAAe,GClBf,SAAS,GAAa,EAAQ,CAC5B,OAAO,EAAO,MAAM,GAAG,CAGzB,IAAA,GAAe,GCVXC,GAAgB,kBAIhBC,GAAe,gDACfC,GAAa,iBAGb,GAAW,IAAMF,GAAgB,IACjCG,GAAU,IAAMF,GAAe,IAC/B,GAAS,2BACTG,GAAa,MAAQD,GAAU,IAAM,GAAS,IAC9CE,GAAc,KAAOL,GAAgB,IACrCM,GAAa,kCACbC,GAAa,qCACbC,GAAQ,UAGRC,GAAWL,GAAa,IACxBM,GAAW,IAAMR,GAAa,KAC9BS,GAAY,MAAQH,GAAQ,MAAQ,CAACH,GAAaC,GAAYC,GAAW,CAAC,KAAK,IAAI,CAAG,IAAMG,GAAWD,GAAW,KAClHG,GAAQF,GAAWD,GAAWE,GAC9B,GAAW,MAAQ,CAACN,GAAcF,GAAU,IAAKA,GAASG,GAAYC,GAAY,GAAS,CAAC,KAAK,IAAI,CAAG,IAGxG,GAAY,OAAO,GAAS,MAAQ,GAAS,KAAO,GAAWK,GAAO,IAAI,CAS9E,SAAS,GAAe,EAAQ,CAC9B,OAAO,EAAO,MAAM,GAAU,EAAI,EAAE,CAGtC,IAAA,GAAe,GC5Bf,SAAS,GAAc,EAAQ,CAC7B,OAAOC,GAAW,EAAO,CACrBC,GAAe,EAAO,CACtBC,GAAa,EAAO,CAG1B,IAAA,GAAe,GCLf,SAAS,GAAgB,EAAY,CACnC,OAAO,SAAS,EAAQ,CACtB,EAASC,EAAAA,EAAS,EAAO,CAEzB,IAAI,EAAaC,GAAW,EAAO,CAC/BC,GAAc,EAAO,CACrB,IAAA,GAEA,EAAM,EACN,EAAW,GACX,EAAO,OAAO,EAAE,CAEhB,EAAW,EACXC,GAAU,EAAY,EAAE,CAAC,KAAK,GAAG,CACjC,EAAO,MAAM,EAAE,CAEnB,OAAO,EAAI,IAAa,CAAG,GAI/B,IAAA,GAAe,GCbX,GAAaC,GAAgB,cAAc,CAE/C,GAAe,GCTf,SAAS,GAAY,EAAO,EAAU,EAAa,EAAW,CAC5D,IAAI,EAAQ,GACR,EAAS,GAAS,KAAO,EAAI,EAAM,OAKvC,IAHI,GAAa,IACf,EAAc,EAAM,EAAE,IAEjB,EAAE,EAAQ,GACf,EAAc,EAAS,EAAa,EAAM,GAAQ,EAAO,EAAM,CAEjE,OAAO,EAGT,IAAA,GAAe,GClBf,SAAS,GAAe,EAAQ,CAC9B,OAAO,SAAS,EAAK,CACnB,OAAO,IAAoC,IAI/C,IAAA,GAAe,GCuDX,GAAeC,GAjEG,CAEpB,EAAQ,IAAM,EAAQ,IAAK,EAAQ,IAAK,EAAQ,IAAK,EAAQ,IAAK,EAAQ,IAC1E,EAAQ,IAAM,EAAQ,IAAK,EAAQ,IAAK,EAAQ,IAAK,EAAQ,IAAK,EAAQ,IAC1E,EAAQ,IAAM,EAAQ,IACtB,EAAQ,IAAM,EAAQ,IACtB,EAAQ,IAAM,EAAQ,IAAK,EAAQ,IAAK,EAAQ,IAChD,EAAQ,IAAM,EAAQ,IAAK,EAAQ,IAAK,EAAQ,IAChD,EAAQ,IAAM,EAAQ,IAAK,EAAQ,IAAK,EAAQ,IAChD,EAAQ,IAAM,EAAQ,IAAK,EAAQ,IAAK,EAAQ,IAChD,EAAQ,IAAM,EAAQ,IACtB,EAAQ,IAAM,EAAQ,IAAK,EAAQ,IAAK,EAAQ,IAAK,EAAQ,IAAK,EAAQ,IAC1E,EAAQ,IAAM,EAAQ,IAAK,EAAQ,IAAK,EAAQ,IAAK,EAAQ,IAAK,EAAQ,IAC1E,EAAQ,IAAM,EAAQ,IAAK,EAAQ,IAAK,EAAQ,IAChD,EAAQ,IAAM,EAAQ,IAAK,EAAQ,IAAK,EAAQ,IAChD,EAAQ,IAAM,EAAQ,IAAK,EAAQ,IACnC,EAAQ,KAAM,EAAQ,KACtB,EAAQ,KAAM,EAAQ,KACtB,EAAQ,KAER,EAAU,IAAM,EAAU,IAAK,EAAU,IACzC,EAAU,IAAM,EAAU,IAAK,EAAU,IACzC,EAAU,IAAM,EAAU,IAAK,EAAU,IAAK,EAAU,IACxD,EAAU,IAAM,EAAU,IAAK,EAAU,IAAK,EAAU,IACxD,EAAU,IAAM,EAAU,IAAK,EAAU,IAAK,EAAU,IACxD,EAAU,IAAM,EAAU,IAAK,EAAU,IAAK,EAAU,IAAK,EAAU,IACvE,EAAU,IAAM,EAAU,IAAK,EAAU,IAAK,EAAU,IAAK,EAAU,IACvE,EAAU,IAAM,EAAU,IAAK,EAAU,IAAK,EAAU,IACxD,EAAU,IAAM,EAAU,IAAK,EAAU,IAAK,EAAU,IACxD,EAAU,IAAM,EAAU,IAAK,EAAU,IAAK,EAAU,IACxD,EAAU,IAAM,EAAU,IAAK,EAAU,IAAK,EAAU,IAAK,EAAU,IACvE,EAAU,IAAM,EAAU,IAAK,EAAU,IAAK,EAAU,IAAK,EAAU,IACvE,EAAU,IAAM,EAAU,IAC1B,EAAU,IAAM,EAAU,IAAK,EAAU,IACzC,EAAU,IAAM,EAAU,IAAK,EAAU,IAAK,EAAU,IAAK,EAAU,IACvE,EAAU,IAAM,EAAU,IAAK,EAAU,IAAK,EAAU,IAAK,EAAU,IACvE,EAAU,IAAM,EAAU,IAAK,EAAU,IAAK,EAAU,IACxD,EAAU,IAAM,EAAU,IAAK,EAAU,IAAK,EAAU,IACxD,EAAU,IAAM,EAAU,IAAK,EAAU,IACzC,EAAU,IAAM,EAAU,IAAK,EAAU,IACzC,EAAU,IAAM,EAAU,IAAK,EAAU,IACzC,EAAU,IAAM,EAAU,IAAK,EAAU,IACzC,EAAU,IAAM,EAAU,IAAK,EAAU,IAAK,EAAU,IACxD,EAAU,IAAM,EAAU,IAAK,EAAU,IAAK,EAAU,IACxD,EAAU,IAAM,EAAU,IAAK,EAAU,IACzC,EAAU,IAAM,EAAU,IAAK,EAAU,IACzC,EAAU,IAAM,EAAU,IAAK,EAAU,IAAK,EAAU,IAAK,EAAU,IAAK,EAAU,IACtF,EAAU,IAAM,EAAU,IAAK,EAAU,IAAK,EAAU,IAAK,EAAU,IAAK,EAAU,IACtF,EAAU,IAAM,EAAU,IAC1B,EAAU,IAAM,EAAU,IAAK,EAAU,IACzC,EAAU,IAAM,EAAU,IAAK,EAAU,IACzC,EAAU,IAAM,EAAU,IAAK,EAAU,IACzC,EAAU,KAAM,EAAU,KAC1B,EAAU,KAAM,EAAU,KAC1B,EAAU,KAAM,EAAU,IAC3B,CAUiD,CAElD,GAAe,GClEX,GAAU,8CAeV,GAAc,OANJ,kDAMoB,IAAI,CAoBtC,SAAS,GAAO,EAAQ,CAEtB,MADA,GAASC,EAAAA,EAAS,EAAO,CAClB,GAAU,EAAO,QAAQ,GAASC,GAAa,CAAC,QAAQ,GAAa,GAAG,CAGjF,IAAA,GAAe,GC3CX,GAAc,4CASlB,SAAS,GAAW,EAAQ,CAC1B,OAAO,EAAO,MAAM,GAAY,EAAI,EAAE,CAGxC,IAAA,GAAe,GCbX,GAAmB,qEASvB,SAAS,GAAe,EAAQ,CAC9B,OAAO,GAAiB,KAAK,EAAO,CAGtC,IAAA,GAAe,GCbX,GAAgB,kBAIhB,GAAe,gDACf,GAAiB,kBACjB,GAAe,4BACf,GAAgB,uBAChB,GAAiB,+CACjB,GAAqB,kBACrB,GAAe,+JACf,GAAe,4BACf,GAAa,iBACb,GAAe,GAAgB,GAAiB,GAAqB,GAGrE,GAAS,OACT,GAAU,IAAM,GAAe,IAC/B,GAAU,IAAM,GAAe,IAC/B,GAAW,OACX,GAAY,IAAM,GAAiB,IACnC,GAAU,IAAM,GAAe,IAC/B,GAAS,KAAO,GAAgB,GAAe,GAAW,GAAiB,GAAe,GAAe,IAEzG,GAAa,MAAQ,GAAA,6BACrB,GAAc,KAAO,GAAgB,IACrC,GAAa,kCACb,GAAa,qCACb,GAAU,IAAM,GAAe,IAC/B,GAAQ,UAGR,GAAc,MAAQ,GAAU,IAAM,GAAS,IAC/C,GAAc,MAAQ,GAAU,IAAM,GAAS,IAC/C,GAAkB,MAAQ,GAAS,yBACnC,GAAkB,MAAQ,GAAS,yBACnC,GAAW,GAAa,IACxB,GAAW,IAAM,GAAa,KAC9B,GAAY,MAAQ,GAAQ,MAAQ,CAAC,GAAa,GAAY,GAAW,CAAC,KAAK,IAAI,CAAG,IAAM,GAAW,GAAW,KAClH,GAAa,mDACb,GAAa,mDACb,GAAQ,GAAW,GAAW,GAC9B,GAAU,MAAQ,CAAC,GAAW,GAAY,GAAW,CAAC,KAAK,IAAI,CAAG,IAAM,GAGxE,GAAgB,OAAO,CACzB,GAAU,IAAM,GAAU,IAAM,GAAkB,MAAQ,CAAC,GAAS,GAAS,IAAI,CAAC,KAAK,IAAI,CAAG,IAC9F,GAAc,IAAM,GAAkB,MAAQ,CAAC,GAAS,GAAU,GAAa,IAAI,CAAC,KAAK,IAAI,CAAG,IAChG,GAAU,IAAM,GAAc,IAAM,GACpC,GAAU,IAAM,GAChB,GACA,GACA,GACA,GACD,CAAC,KAAK,IAAI,CAAE,IAAI,CASjB,SAAS,GAAa,EAAQ,CAC5B,OAAO,EAAO,MAAM,GAAc,EAAI,EAAE,CAG1C,IAAA,GAAe,GC5Cf,SAAS,GAAM,EAAQ,EAAS,EAAO,CAOrC,MANA,GAASC,EAAAA,EAAS,EAAO,CACzB,EAAU,EAAQ,IAAA,GAAY,EAE1B,IAAY,IAAA,GACPC,GAAe,EAAO,CAAGC,GAAa,EAAO,CAAGC,GAAW,EAAO,CAEpE,EAAO,MAAM,EAAQ,EAAI,EAAE,CAGpC,IAAA,GAAe,GC1BX,GAAS,OAHA,OAGe,IAAI,CAShC,SAAS,GAAiB,EAAU,CAClC,OAAO,SAAS,EAAQ,CACtB,OAAOC,GAAYC,GAAMC,GAAO,EAAO,CAAC,QAAQ,GAAQ,GAAG,CAAC,CAAE,EAAU,GAAG,EAI/E,IAAA,GAAe,GClBX,GAAa,KAAK,KAClB,GAAY,KAAK,IAuBrB,SAAS,GAAM,EAAO,EAAM,EAAO,CACjC,AAGE,GAHG,EAAQC,GAAe,EAAO,EAAM,EAAM,CAAG,IAAS,IAAA,IAClD,EAEA,GAAUC,GAAU,EAAK,CAAE,EAAE,CAEtC,IAAI,EAAS,GAAS,KAAO,EAAI,EAAM,OACvC,GAAI,CAAC,GAAU,EAAO,EACpB,MAAO,EAAE,CAMX,IAJA,IAAI,EAAQ,EACR,EAAW,EACX,EAAS,MAAM,GAAW,EAAS,EAAK,CAAC,CAEtC,EAAQ,GACb,EAAO,KAAcC,GAAU,EAAO,EAAQ,GAAS,EAAM,CAE/D,OAAO,EAGT,IAAA,EAAe,GCrBf,SAAS,GAAkB,EAAO,CAChC,OAAOC,EAAAA,EAAa,EAAM,EAAIC,EAAAA,EAAY,EAAM,CAGlD,IAAA,GAAe,GCvBf,SAAS,GAAkB,EAAO,EAAO,EAAY,CAInD,IAHA,IAAI,EAAQ,GACR,EAAS,GAAS,KAAO,EAAI,EAAM,OAEhC,EAAE,EAAQ,GACf,GAAI,EAAW,EAAO,EAAM,GAAO,CACjC,MAAO,GAGX,MAAO,GAGT,IAAA,GAAe,GCbXC,GAAmB,IAavB,SAAS,GAAe,EAAO,EAAQ,EAAU,EAAY,CAC3D,IAAI,EAAQ,GACR,EAAWC,GACX,EAAW,GACX,EAAS,EAAM,OACf,EAAS,EAAE,CACX,EAAe,EAAO,OAE1B,GAAI,CAAC,EACH,OAAO,EAEL,IACF,EAASC,EAAAA,EAAS,EAAQC,EAAAA,EAAU,EAAS,CAAC,EAE5C,GACF,EAAWC,GACX,EAAW,IAEJ,EAAO,QAAUJ,KACxB,EAAWK,EAAAA,EACX,EAAW,GACX,EAAS,IAAIC,EAAAA,EAAS,EAAO,EAE/B,MACA,KAAO,EAAE,EAAQ,GAAQ,CACvB,IAAI,EAAQ,EAAM,GACd,EAAW,GAAY,KAAO,EAAQ,EAAS,EAAM,CAGzD,GADA,EAAS,GAAc,IAAU,EAAK,EAAQ,EAC1C,GAAY,IAAa,EAAU,CAErC,IADA,IAAI,EAAc,EACX,KACL,GAAI,EAAO,KAAiB,EAC1B,SAAS,MAGb,EAAO,KAAK,EAAM,MAEV,EAAS,EAAQ,EAAU,EAAW,EAC9C,EAAO,KAAK,EAAM,CAGtB,OAAO,EAGT,IAAA,GAAe,GCxCX,GAAaC,GAAS,SAAS,EAAO,EAAQ,CAChD,OAAOC,GAAkB,EAAM,CAC3BC,GAAe,EAAOC,GAAY,EAAQ,EAAGF,GAAmB,GAAK,CAAC,CACtE,EAAE,EACN,CAEF,EAAe,GCrBf,SAAS,GAAQ,EAAY,EAAU,CACrC,IAAI,EAAQ,GACR,EAASG,EAAAA,EAAY,EAAW,CAAG,MAAM,EAAW,OAAO,CAAG,EAAE,CAKpE,OAHA,EAAA,EAAS,EAAY,SAAS,EAAO,EAAK,EAAY,CACpD,EAAO,EAAE,GAAS,EAAS,EAAO,EAAKC,EAAW,EAClD,CACK,EAGT,IAAA,GAAe,GCdX,GAHc,OAAO,UAGQ,eAyB7B,GAAUC,EAAAA,EAAiB,SAAS,EAAQ,EAAO,EAAK,CACtD,GAAe,KAAK,EAAQ,EAAI,CAClC,EAAO,GAAK,KAAK,EAAM,CAEvB,EAAA,EAAgB,EAAQ,EAAK,CAAC,EAAM,CAAC,EAEvC,CAEF,GAAe,GCRf,SAAS,GAAU,EAAQ,EAAU,CACnC,IAAI,EAAS,EAAE,CAMf,MALA,GAAWC,EAAAA,EAAa,EAAU,EAAE,CAEpC,EAAA,EAAW,EAAQ,SAAS,EAAO,EAAK,EAAQ,CAC9C,EAAA,EAAgB,EAAQ,EAAK,EAAS,EAAO,EAAKC,EAAO,CAAC,EAC1D,CACK,EAGT,IAAA,GAAe,GChCf,SAAS,GAAW,EAAO,EAAU,CACnC,IAAI,EAAS,EAAM,OAGnB,IADA,EAAM,KAAK,EAAS,CACb,KACL,EAAM,GAAU,EAAM,GAAQ,MAEhC,OAAO,EAGT,IAAA,GAAe,GCVf,SAAS,GAAiB,EAAO,EAAO,CACtC,GAAI,IAAU,EAAO,CACnB,IAAI,EAAe,IAAU,IAAA,GACzB,EAAY,IAAU,KACtB,EAAiB,IAAU,EAC3B,EAAcC,EAAAA,EAAS,EAAM,CAE7B,EAAe,IAAU,IAAA,GACzB,EAAY,IAAU,KACtB,EAAiB,IAAU,EAC3B,EAAcA,EAAAA,EAAS,EAAM,CAEjC,GAAK,CAAC,GAAa,CAAC,GAAe,CAAC,GAAe,EAAQ,GACtD,GAAe,GAAgB,GAAkB,CAAC,GAAa,CAAC,GAChE,GAAa,GAAgB,GAC7B,CAAC,GAAgB,GAClB,CAAC,EACH,MAAO,GAET,GAAK,CAAC,GAAa,CAAC,GAAe,CAAC,GAAe,EAAQ,GACtD,GAAe,GAAgB,GAAkB,CAAC,GAAa,CAAC,GAChE,GAAa,GAAgB,GAC7B,CAAC,GAAgB,GAClB,CAAC,EACH,MAAO,GAGX,MAAO,GAGT,IAAA,GAAe,GCxBf,SAAS,GAAgB,EAAQ,EAAO,EAAQ,CAO9C,IANA,IAAI,EAAQ,GACR,EAAc,EAAO,SACrB,EAAc,EAAM,SACpB,EAAS,EAAY,OACrB,EAAe,EAAO,OAEnB,EAAE,EAAQ,GAAQ,CACvB,IAAI,EAASC,GAAiB,EAAY,GAAQ,EAAY,GAAO,CACrE,GAAI,EAKF,OAJI,GAAS,EACJ,EAGF,GADK,EAAO,IACO,OAAS,GAAK,GAU5C,OAAO,EAAO,MAAQ,EAAM,MAG9B,IAAA,GAAe,GCxBf,SAAS,GAAY,EAAY,EAAW,EAAQ,CAClD,AAUE,EAVE,EAAU,OACAC,EAAAA,EAAS,EAAW,SAAS,EAAU,CAMjD,OALIC,EAAAA,EAAQ,EAAS,CACZ,SAAS,EAAO,CACrB,OAAOC,EAAAA,EAAQ,EAAO,EAAS,SAAW,EAAI,EAAS,GAAK,EAAS,EAGlE,GACP,CAEU,CAACC,EAAAA,EAAS,CAGxB,IAAI,EAAQ,GAUZ,MATA,GAAYH,EAAAA,EAAS,EAAWI,EAAAA,EAAUC,EAAAA,EAAa,CAAC,CASjDC,GAPMC,GAAQ,EAAY,SAAS,EAAO,EAAK,EAAY,CAIhE,MAAO,CAAE,SAHMP,EAAAA,EAAS,EAAW,SAAS,EAAU,CACpD,OAAO,EAAS,EAAM,EACtB,CAC6B,MAAS,EAAE,EAAO,MAAS,EAAO,EACjE,CAEwB,SAAS,EAAQ,EAAO,CAChD,OAAOQ,GAAgB,EAAQ,EAAO,EAAO,EAC7C,CAGJ,IAAA,GAAe,GCdX,GAASC,GAAS,SAAS,EAAY,EAAW,CACpD,GAAI,GAAc,KAChB,MAAO,EAAE,CAEX,IAAI,EAAS,EAAU,OAMvB,OALI,EAAS,GAAKC,GAAe,EAAY,EAAU,GAAI,EAAU,GAAG,CACtE,EAAY,EAAE,CACL,EAAS,GAAKA,GAAe,EAAU,GAAI,EAAU,GAAI,EAAU,GAAG,GAC/E,EAAY,CAAC,EAAU,GAAG,EAErBC,GAAY,EAAYC,GAAY,EAAW,EAAE,CAAE,EAAE,CAAC,EAC7D,CAEF,GAAe,GCvBX,GAAYC,GAAiB,SAAS,EAAQ,EAAM,EAAO,CAC7D,OAAO,GAAU,EAAQ,IAAM,IAAMC,GAAW,EAAK,EACrD,CAEF,GAAe,GCdX,GAAcC,EAAAA,GAAQ,EAAIC,EAAAA,EAAW,IAAID,EAAAA,EAAI,EAAE,GAAG,CAAC,CAAC,CAAC,IAT1C,IASoE,SAAS,EAAQ,CAClG,OAAO,IAAIA,EAAAA,EAAI,EAAO,EADoDE,GAI5E,GAAe,GCVX,GAAmB,IAWvB,SAAS,GAAS,EAAO,EAAU,EAAY,CAC7C,IAAI,EAAQ,GACR,EAAWC,GACX,EAAS,EAAM,OACf,EAAW,GACX,EAAS,EAAE,CACX,EAAO,EAEX,GAAI,EACF,EAAW,GACX,EAAWC,WAEJ,GAAU,GAAkB,CACnC,IAAI,EAAM,EAAW,KAAOC,GAAU,EAAM,CAC5C,GAAI,EACF,OAAOC,EAAAA,EAAW,EAAI,CAExB,EAAW,GACX,EAAWC,EAAAA,EACX,EAAO,IAAIC,EAAAA,OAGX,EAAO,EAAW,EAAE,CAAG,EAEzB,MACA,KAAO,EAAE,EAAQ,GAAQ,CACvB,IAAI,EAAQ,EAAM,GACd,EAAW,EAAW,EAAS,EAAM,CAAG,EAG5C,GADA,EAAS,GAAc,IAAU,EAAK,EAAQ,EAC1C,GAAY,IAAa,EAAU,CAErC,IADA,IAAI,EAAY,EAAK,OACd,KACL,GAAI,EAAK,KAAe,EACtB,SAAS,MAGT,GACF,EAAK,KAAK,EAAS,CAErB,EAAO,KAAK,EAAM,MAEV,EAAS,EAAM,EAAU,EAAW,GACxC,IAAS,GACX,EAAK,KAAK,EAAS,CAErB,EAAO,KAAK,EAAM,EAGtB,OAAO,EAGT,IAAA,GAAe,GCnDf,SAAS,GAAK,EAAO,CACnB,OAAQ,GAAS,EAAM,OAAUC,GAAS,EAAM,CAAG,EAAE,CAGvD,IAAA,EAAe,GCEf,SAAS,GAAO,EAAO,EAAU,CAC/B,OAAQ,GAAS,EAAM,OAAUC,GAAS,EAAOC,EAAAA,EAAa,EAAU,EAAE,CAAC,CAAG,EAAE,CAGlF,IAAA,GAAe,GC5Bf,KAAM,CAAE,MAAK,aAAcC,EAAAA,QCEd,GAAc,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqDjB,GAAmB,EAAA,GAAG;;;;;;EAUtB,GAAkB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqCrB,GAAwB,EAAA,GAAG;;;;;;EAQ3B,GAA+B,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8ClC,GAA8B,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyCjC,GAAmB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;ECrMtB,GAAc,EAAA,GAAG;;;;;;;;;;;ECEjB,GAAa,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BhB,GAAmB,EAAA,GAAG;;;;;;;;;;;;EAgBtB,GAAsB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyEzB,GAAoB,EAAA,GAAG;;;;;;;;;;EAYvB,GAAoB,EAAA,GAAG;;;;;;;;;ECpIvB,GAAY,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgDf,GAAc,EAAA,GAAG;;;;;;;;;EAWjB,GAAkB,EAAA,GAAG;;;;;;EAQrB,GAAkB,EAAA,GAAG;;;;;;EClErB,GAAW,EAAA,GAAG;;;;;;;;;;ECDd,GAAc,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoCjB,GAAuB,EAAA,GAAG;;;;;;EAQ1B,GAAoB,EAAA,GAAG;;;;;;;;;EAWvB,GAAoB,EAAA,GAAG;;;;;;ECzDvB,GAAgB,EAAA,GAAG;;;;;;;;;;;;;;;EAiBnB,GAAsB,EAAA,GAAG;;;;;;;;;EAWzB,GAAsB,EAAA,GAAG;;;;;;EAQzB,GAAsB,EAAA,GAAG;;;;;;ECjCzB,GAAe,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiClB,GAAsB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;EAqBzB,GAAoB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;ECvDvB,GAAW,EAAA,GAAG;;;;;;;;;;;;;;;;;;EAoBd,GAAiB,EAAA,GAAG;;;;;;;;;;EAYpB,GAAiB,EAAA,GAAG;;;;;;EClCpB,GAAkC,EAAA,GAAG;;;;;;;;;;ECArC,GAA6B,EAAA,GAAG;;;;;;;;;;;EAahC,GAAkB,EAAA,GAAG;;;;;;;;;;;;ECVrB,GAAY,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;EAsBf,GAAkB,EAAA,GAAG;;;;;;ECzBrB,GAAe,EAAA,GAAG;;;;;;;;ECGlB,GAA0B,EAAA,GAAG;;;;;;;;;;;;;;;ECA7B,GAA4B,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmC/B,GAAmC,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;EA0BtC,GAAkC,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;EC7DrC,GAAgB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2CnB,GAAuB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgC1B,GAAsB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EC9EzB,GAAiB,EAAA,GAAG;;;;;;;;;;;;;;;;;ECApB,GAAW,EAAA,GAAG;;;;;;;;;;;;;;;;;EAmBd,GAAkB,EAAA,GAAG;;;;;;;;;;;;;;;ECjBrB,GAAW,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoFd,GAA0B,EAAA,GAAG;;;;;;;;EAS7B,GAAyB,EAAA,GAAG;;;;;;;;EAU5B,GAAyB,EAAA,GAAG;;;;;;;;EAU5B,GAAyB,EAAA,GAAG;;;;;;ECnH5B,GAAW,EAAA,GAAG;;;;;;;;;;;;;EAed,GAAuB,EAAA,GAAG;;;;;;ECb1B,GAAoB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8BvB,GAAyB,EAAA,GAAG;;;;;;;;EAU5B,GAAwB,EAAA,GAAG;;;;;;;;EC1C3B,GAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0I5B,GAAc,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YA4DlB,GAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsFzB,GAAoC,EAAA,GAAG;;;;;;;;;;;ECrRvC,GAAW,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECAd,GAAoB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECCvB,GAAuB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAmD3B,GAA0B;;;;;ECxDzB,GAAU,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;EA8Bb,GAAkB,EAAA,GAAG;;;;;;;;;;EAiBrB,GAAgB,EAAA,GAAG;;;;;;;;;;;;;;;;;EAmBnB,GAAyB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8B5B,GAAiB,EAAA,GAAG;;;;;;EAQpB,GAAgB,EAAA,GAAG;;;;;;;;;EAWnB,GAAyB,EAAA,GAAG;;;;;;;;EAU5B,GAAwB,EAAA,GAAG;;;;;;;;;EAW3B,GAAuB,EAAA,GAAG;;;;;;EAQ1B,GAAsB,EAAA,GAAG;;;;;;;;;ECjJzB,GAAqB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;EAwBxB,GAAkC,EAAA,GAAG;;;;;;;;;;;;;EAerC,GAA0B,EAAA,GAAG;;;;;;;;EAiB7B,GAAuC,EAAA,GAAG;;;;;;;;ECvD1C,GAAQ,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqCX,GAAc,EAAA,GAAG;;;;;;;;;EAWjB,GAAc,EAAA,GAAG;;;;;;;;;ECnDjB,GAA6B,EAAA,GAAG;;;;;;;;EAYhC,GAAsB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;ECTzB,GAAQ,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;ECAX,GAAgB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;EAuBnB,GAAqB,EAAA,GAAG;;;;;;;;;;;;;;;;;EC1BxB,GAAoB,EAAA,GAAG;;;;;;;;;EAWvB,GAA6B,EAAA,GAAG;;;;;;;;;;;ECLhC,GAAiC,EAAA,GAAG;;;;;;;;;;;;;;EAgBpC,GAAgC,EAAA,GAAG;;;;;;;;;;;EAanC,GAAgC,EAAA,GAAG;;;;;;;;EChCnC,GAAa,EAAA,GAAG;;;;;;;;;;;;;EAehB,GAA0B,EAAA,GAAG;;;;;;;;EAU7B,GAA0B,EAAA,GAAG;;;;;;;;EAU7B,GAAyB,EAAA,GAAG;;;;;;EAW5B,GAAmB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;EAsBtB,GAAmB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;EAuBtB,GAAmB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;EAqBtB,GAA0B,EAAA,GAAG;;;;;;;;EC/G7B,GAAc,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmCjB,GAAqB,EAAA,GAAG;;;;;;;;;;EAYxB,GAAoB,EAAA,GAAG;;;;;;;;;;;;;;;;;;EAoBvB,GAAoB,EAAA,GAAG;;;;;;;;;;;;;;;;;;EAoBvB,GAA2B,EAAA,GAAG;;;;;;;;;;;EAe9B,GAAa,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiDhB,GAAU,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8Cb,GAA2B,EAAA,GAAG;;;;;;;;EAU9B,GAAwB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;EA0B3B,GAA8B,EAAA,GAAG;;;;;;;;;;;EAajC,GAAyB,EAAA,GAAG;;;;;;;;EAU5B,GAAiC,EAAA,GAAG;;;;;;;;;EAWpC,GAAmC,EAAA,GAAG;;;;;;;;;;;;EActC,GAAyB,EAAA,GAAG;;;;;;;;;;;;EAc5B,GAAiC,EAAA,GAAG;;;;;;;;;;;EAapC,GAAmC,EAAA,GAAG;;;;;;;;;;;EAatC,GAAsB,EAAA,GAAG;;;;;;EAQzB,GAAgC,EAAA,GAAG;;;;;;;;EAUnC,GAA+B,EAAA,GAAG;;;;;;;;EAUlC,GAAsC,EAAA,GAAG;;;;;;;;EAUzC,GAA4B,EAAA,GAAG;;;;;;;;EAU/B,GAA+B,EAAA,GAAG;;;;;;;;EAUlC,GAA4B,EAAA,GAAG;;;;;;EAQ/B,GAA4B,EAAA,GAAG;;;;;;EAQ/B,GAA2B,EAAA,GAAG;;;;;;;;EC/Y9B,GAAiC,EAAA,GAAG;;;;;;;;;;;;ECEpC,GAAoB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BvB,GAAyB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;EAyB5B,GAA2B,EAAA,GAAG;;;;;;;;ECvD9B,GAAU,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;EAsBb,GAAgB,EAAA,GAAG;;;;;;EClBnB,GAAsB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiDzB,GAAsB,EAAA,GAAG;;;;;;EAQzB,GAAsB,EAAA,GAAG;;;;;;EChEzB,GAA0B,EAAA,GAAG;;;;;;EAQ7B,GAA8B,EAAA,GAAG;;;;;;EAQjC,GAAiB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;EA2BpB,GAAwB,EAAA,GAAG;;;;;;EC3C3B,GAAyB,EAAA,GAAG;;;;;;;;;EAW5B,GAAQ,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;EAyBX,GAAc,EAAA,GAAG;;;;;;ECjCjB,GAAwB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;ECA3B,GAAS,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+CZ,GAAe,EAAA,GAAG;;;;;;;;;;EAYlB,GAAgB,EAAA,GAAG;;;;;;EC3DnB,GAAc,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BjB,GAAoB,EAAA,GAAG;;;;;;;;;;;EAavB,GAAqB,EAAA,GAAG;;;;;;ECzCxB,GAAkB,EAAA,GAAG;;;;;;;;;;;;;;;;;;EAoBrB,GAAwB,EAAA,GAAG;;;;;;;;;EAW3B,GAAyB,EAAA,GAAG;;;;;;;;EClC5B,GAAU,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4Cb,GAAgB,EAAA,GAAG;;;;;;;;;EAWnB,GAAiB,EAAA,GAAG;;;;;;EClDpB,GAAsB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BzB,GAA2B,EAAA,GAAG;;;;;;;;;;;;EAc9B,GAA6B,EAAA,GAAG;;;;;;;;EC7ChC,GAAoC,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiCvC,GAAyC,EAAA,GAAG;;;;;;;;;;;;EAc5C,GAA2C,EAAA,GAAG;;;;;;;;ECpD9C,GAAwB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuD3B,GAA6B,EAAA,GAAG;;;;;;;;;;;EAahC,GAA+B,EAAA,GAAG;;;;;;;;ECpElC,GAAiB,EAAA,GAAG;;;;;;;;ECApB,GAAyB,EAAA,GAAG;;;;;;;;;;;;;;;;;;;;;;ECQ5B,EAAO,SACP,GAAa,4BACb,GAAQ,UAGR,GAAwB,CAAC,QAAS,iBAAiB,CAKhE,IAAY,EAAA,SAAA,EAAL,OAEL,GAAA,MAAA,QAEA,EAAA,eAAA,iBAEA,EAAA,YAAA,cAEA,EAAA,YAAA,cAEA,EAAA,OAAA,SAEA,EAAA,QAAA,UAEA,EAAA,mBAAA,qBAEA,EAAA,cAAA,gBAEA,EAAA,UAAA,YAEA,EAAA,YAAA,qBAIF,MAAa,GAA8C,EACxD,EAAW,OAAQ,IACnB,EAAW,gBAAiB,IAC5B,EAAW,aAAc,IACzB,EAAW,aAAc,IACzB,EAAW,eAAgB,IAC3B,EAAW,WAAY,IACvB,EAAW,aAAc,IACzB,EAAW,QAAS,IACpB,EAAW,SAAU,IACrB,EAAW,oBAAqB,GAClC,CAGY,GAAqD,EAC/D,EAAW,aAAc,IACzB,EAAW,aAAc,GAC3B,CAGY,GAAkBC,EAAE,KAAK,CAEpC,YAAaA,EAAE,SAAA,EAAA,EAAA,WAAkB,MAAkBA,EAAE,OAAO,CAAC,CAE7D,gBAAiBA,EAAE,OAAOA,EAAE,OAAQA,EAAE,OAAO,CAE7C,eAAgBA,EAAE,OAAOA,EAAE,OAAQA,EAAE,OAAO,CAE5C,2BAA4BA,EAAE,OAAOA,EAAE,QAAA,EAAA,EAAA,UAAiBC,EAAAA,cAAc,CAAC,CAEvE,yBAA0BD,EAAE,OAAOA,EAAE,OAAQA,EAAE,OAAO,CAEtD,iBAAkBA,EAAE,OAAOA,EAAE,QAAA,EAAA,EAAA,UAAiBE,EAAAA,WAAW,CAAC,CAE1D,gBAAiBF,EAAE,OACjBA,EAAE,QAAA,EAAA,EAAA,UACO,CAAE,GAAGG,EAAAA,gBAAiB,GAAO,EAAM,CAAC,CAC9C,CAED,2BAA4BH,EAAE,OAC5BA,EAAE,QAAA,EAAA,EAAA,UACO,CAAE,GAAGI,EAAAA,2BAA4B,GAAO,EAAM,CAAC,CACzD,CAED,sBAAuBJ,EAAE,OACvBA,EAAE,QAAA,EAAA,EAAA,UACO,CAAE,GAAGK,EAAAA,wBAAyB,GAAO,EAAM,CAAC,CACtD,CACF,CAAC,CAQW,GAAoBL,EAAE,KAAK,CACtC,GAAIA,EAAE,OACN,KAAMA,EAAE,OACR,SAAUA,EAAE,OACZ,eAAgBA,EAAE,OAClB,YAAaA,EAAE,OAChB,CAAC,CAMWM,GAAqBN,EAAE,KAAK,CAEvC,gBAAiBA,EAAE,MAAMA,EAAE,OAAOA,EAAE,OAAQA,EAAE,IAAI,CAAC,CAEnD,mBAAoBA,EAAE,MAAM,GAAkB,CAE9C,kBAAmBA,EAAE,MACnBA,EAAE,KAAK,CACL,SAAUA,EAAE,OACZ,eAAgBA,EAAE,OAClB,YAAaA,EAAE,OAChB,CAAC,CACH,CACF,CAAC,CChHF,SAAgB,GAAY,EAAe,EAAwB,CACjE,OAAA,EAAA,EAAA,SACc,EAAM,aAAa,CAAE,EAAM,aAAa,CAAC,GAAA,EAAA,EAAA,SACzC,EAAM,aAAa,CAAE,EAAM,aAAa,CAAC,CAazD,SAAgB,GACd,EACA,EACA,EACA,EACsD,CACtD,IAAM,EAAsB,EAAe,OAAQ,GACjD,GAAY,EAAa,aAAa,CAAE,EAAE,aAAa,CAAC,CACzD,CACD,MAAO,CACL,GAAG,EACH,IAAI,EAAA,QAAS,UACb,GAAI,EAAa,EAAE,CAAG,CAAC,EAAK,CAC5B,GAAI,EAAc,CAAC,GAAW,CAAG,EAAE,CACnC,GAAG,EAAe,OAAQ,GAAM,CAAC,EAAoB,SAAS,EAAE,CAAC,CAClE,CC/BH,eAAsB,EACpB,EACA,EACA,EACoC,CACpC,EAAA,QAAS,eAAe,eAAgBO,EAAAA,QAAmB,CAE3D,IAAM,EAAS,EACZ,IAAK,GAAS,GAAQ,UAAU,CAChC,OAAQ,GAAU,CAAC,EAAM,GAAO,CACnC,GAAI,EAAO,SAAW,EACpB,OAAO,EAET,IAAM,EAAS,MAAM,EAAA,QAAS,OAC5B,EAAO,IAAK,IAAW,CACrB,KAAM,EACN,QAAS,iBAAiB,IAC1B,KAAM,eACN,QAAS,EAAgB,KAAM,GAAM,GAAY,EAAO,EAAE,CAAC,CAC3D,QAAS,EAA2B,IACjC,EAEG,EAAgB,OACb,GAAM,OAAO,GAAM,UAAY,GAAY,EAAO,EAAE,CACtD,CAHD,EAIP,EAAE,CACJ,CACD,MAAO,CACL,GAAG,EACH,IAAA,EAAA,EAAA,OAAS,EAAS,GAChB,OAAO,GAAM,SAAY,EAAgB,OAAO,OAAO,EAAE,CAAC,GAC3D,CACF,CCnCH,SAAgB,GAAe,EAAyB,CACtD,OAAO,EACJ,MAAM,IAAI,CACV,IAAK,GAAM,EAAE,MAAM,CAAC,CACpB,OAAQ,GAAM,EAAE,CCVrB,MAAa,GAAuBC,EAAE,KAAK,CAEzC,IAAKA,EAAE,OAEP,OAAQA,EAAE,MAAMA,EAAE,OAAO,CAC1B,CAAC,CAWF,SAAgB,GACd,EACwB,CAExB,IAAM,EAAmB,EAAW,IAAK,GAAc,CACrD,GAAM,CAAC,EAAc,GAAsB,EAAU,MAAM,CAAC,MAAM,IAAI,CACtE,GAAI,CAAC,EACH,MAAU,MACR,8DACD,CAGH,MAAO,CACL,IAAK,EACL,OAHsB,EAAmB,MAAM,IAAI,CAIpD,EACD,CAGF,OAFA,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,uCAAuC,CAAC,CACnE,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,KAAK,UAAU,EAAkB,KAAM,EAAE,CAAC,CAAC,CAC/D,ECxBT,SAAgB,GACd,EACA,EACA,EAAmB,CAAE,QAAS,GAAM,CACrB,CAEf,IAAM,GAAA,EAAA,EAAA,QAAA,EAAA,EAAA,cAAiC,EAAY,QAAQ,CAAE,EAAQ,CAerE,OAAA,EAAA,EAAA,aAZyBC,EAAE,MAAM,EAAM,CAAE,EAAY,CAGjC,IAAK,GACvB,OAAO,QAAQ,EAAM,CAAC,QACnB,EAAK,CAAC,EAAK,KACV,OAAO,OAAO,EAAK,EAChB,EAAI,QAAQ,qBAAsB,GAAG,EAAG,EAC1C,CAAC,CACJ,EAAE,CACH,CACF,CCzBH,SAAgB,EACd,EACA,EACU,CACV,OAAOC,EAAK,EAAK,IAAK,GAAQ,EAAI,IAAe,GAAG,CAAC,MAAM,CAAC,CCC9D,eAAsB,GAAW,EAA6C,CAE5E,IAAM,EAAcC,EAAK,EAAK,IAAK,GAAM,OAAO,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAG5D,EAAe,EACf,EAAgB,GAGpB,KAAO,GAAe,CAGpB,GAAM,CAAE,oBAAqB,MAAM,EAAA,QAAS,OAGzC,CACD,CACE,KAAM,mBAEN,QAAS,mGAAmG,EAAa,OAAO,QAChI,KAAM,OACN,QAAS,EACT,QAAS,CAAC,EAAM,GAAG,EAAY,CAChC,CACF,CAAC,CAIF,GADA,EAAgB,IAAS,EACrB,EAAe,CACjB,IAAM,EAAU,EAAyB,EAAc,EAAiB,CAElE,CAAE,gBAAiB,MAAM,EAAA,QAAS,OAGrC,CACD,CACE,KAAM,eACN,QAAS,gCACT,KAAM,WACN,QAAS,EACT,QAAS,EACV,CACF,CAAC,CAEF,EAAe,EAAa,OAAQ,GAClC,EAAa,SAAS,EAAQ,GAAkB,CACjD,EAKL,OADA,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,aAAa,EAAa,OAAO,WAAW,CAAC,CACjE,ECtBT,eAAsB,GACpB,EACA,CAAE,cAAa,oBAAoB,EAAE,CAAE,GAAG,GACzB,CACjB,GAAM,CACJ,uBAAwB,CAAE,cACxB,MAAM,EASP,EAAQ,GAA4B,CACrC,MAAO,CACL,GAAG,EACH,GAAG,EACH,kBAAmB,EAAkB,KAAK,CAAE,UAAS,GAAGC,MAAY,CAClE,GAAGA,EACH,QAAS,EACV,EAAE,CACJ,CACF,CAAC,CACF,OAAO,EAAU,GC3DnB,SAAgB,GACd,EACA,EACe,CAEf,OAAO,IAAIC,EAAAA,cAAc,GAAG,EAAa,UAAW,CAClD,QAAS,CACP,GAAG,EACH,QAAA,EAAA,EACD,CACF,CAAC,CAUJ,SAAgB,EACd,EACA,EACe,CACf,OAAO,GAAmC,EAAc,CACtD,cAAe,UAAU,IAC1B,CAAC,CCpBJ,eAAsB,GACpB,EACA,EACA,EACc,CAId,GAAM,CAAE,gBAAiB,MAAM,EAFhB,EAA4B,EAAc,EAAgB,CAW9D,GAAa,CAElB,CAAE,eAAgB,EAAa,OAC/B,EAAc,QAAQ,IAAI,YAAc,EAG9C,GACE,CAAC,QAAQ,IAAI,YACb,CACE,6CACA,gDACD,CAAC,SAAS,EAAY,CAEvB,MAAU,MACR,qOAGD,CAKH,OAHA,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,iBAAiB,IAAc,CAAC,CAGlD,EAAA,QAAI,OAAO,CAChB,UAAW,EACX,QAAS,CACP,cAAe,UAAU,IACzB,GAAI,EACA,CACE,yBAA0B,UAAU,IACrC,CACD,EAAE,CACP,CACF,CAAC,CCxDJ,SAAgB,GAAkC,EAA2B,CAE3E,OAAO,EAAA,QAAI,OAAO,CAChB,UAAW,EACZ,CAAC,CCCJ,eAAsB,GACpB,EACA,CACE,KACA,cAOa,CACf,MAAM,EAAmB,EAAQ,GAAwB,CACvD,eAAgB,EAChB,aACD,CAAC,CASJ,eAAsB,GACpB,EACA,CACE,KACA,cAOa,CACf,MAAM,EAAmB,EAAQ,GAAkC,CACjE,eAAgB,EAChB,aACD,CAAC,CCrBJ,eAAsB,GACpB,EACA,EACiB,CAUjB,GAAM,CAAE,UAAS,eATA,MAAM,EACrB,EACA,GACA,CACE,aACA,KAAM,sBACP,CACF,EAEwC,QAOzC,OANI,IAAe,IACjB,EAAA,EAAO,MAAM,wDAAwD,CACrE,QAAQ,KAAK,EAAE,EAGF,EAAQ,GC6CzB,MAAMC,GAAY,GASlB,eAAsB,GACpB,EACA,EAWI,EAAE,CACiB,CACvB,IAAM,EAA4B,EAAE,CAChC,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,kBAAmB,CAAE,UACnB,MAAM,EAMP,EAAQ,GAAqB,CAC9B,MAAOA,GACP,SACA,SAAU,CACR,GAAG,EACH,GAAI,EAAS,aACT,CAAE,aAAc,EAAS,aAAa,aAAa,CAAE,CACrD,EAAE,CACN,GAAI,EAAS,WACT,CAAE,WAAY,EAAS,WAAW,aAAa,CAAE,CACjD,EAAE,CACP,CACF,CAAC,CACF,EAAY,KACV,GAAG,EAAM,IAAK,IAAU,CACtB,GAAG,EACH,GAAI,EAAK,IAAI,GACb,MAAO,EAAK,OAAO,GACnB,MAAO,EAAK,MAAM,GAClB,KAAM,EAAK,MAAM,GAClB,EAAE,CACJ,CACD,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,ECnIT,MAAMC,GAAY,GAQlB,eAAsB,GACpB,EACmB,CACnB,IAAM,EAAoB,EAAE,CACxB,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,QAAS,CAAE,UACT,MAAM,EAMP,EAAQ,GAAS,CAClB,MAAOA,GACP,SACD,CAAC,CACF,EAAQ,KAAK,GAAG,EAAM,CACtB,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAQ,MAAM,EAAG,IAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,CCzC7D,MAAMC,GAAY,GAkBlB,eAAsB,GACpB,EACA,EAA8B,EAAE,CACV,CACtB,IAAM,EAA0B,EAAE,CAC9B,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,WAAY,CAAE,UACZ,MAAM,EAMP,EAAQ,GAAa,CACtB,MAAOA,GACP,SACA,WACD,CAAC,CACF,EAAW,KAAK,GAAG,EAAM,CACzB,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAW,MAAM,EAAG,IAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,CC/ChE,MAAMC,GAAY,GAQlB,eAAsB,GACpB,EAC0B,CAC1B,IAAM,EAAkC,EAAE,CACtC,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,eAAgB,CAAE,UAChB,MAAM,EAMP,EAAQ,GAAiB,CAC1B,MAAOA,GACP,SACD,CAAC,CACF,EAAe,KACb,GAAG,EAAM,IAAK,IAAU,CACtB,GAAG,EACH,WAAY,KAAK,MAAM,EAAK,WAAW,CACxC,EAAE,CACJ,CACD,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAe,MAAM,EAAG,IAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,CCNpE,MAAMC,GAAY,GASlB,eAAsB,GACpB,EACA,EAKI,EAAE,CACY,CAClB,IAAM,EAAkB,EAAE,CACtB,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,OAAQ,CAAE,UACR,MAAM,EAMP,EAAQ,GAAQ,CACjB,MAAOA,GACP,SACA,WACD,CAAC,CACF,EAAO,KAAK,GAAG,EAAM,CACrB,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAO,MAAM,EAAG,IAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,CC8O5D,MAAMC,GAAY,GAQlB,eAAsB,GACpB,EACuB,CACvB,IAAM,EAA4B,EAAE,CAChC,EAAS,EAET,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,gBAAiB,CAAE,UACjB,MAAM,EAMP,EAAQ,GAAa,CACtB,MAAOA,GACP,SACD,CAAC,CACF,EAAY,KAAK,GAAG,EAAM,CAC1B,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAY,MAAM,EAAG,IAAM,EAAE,MAAM,cAAc,EAAE,MAAM,CAAC,CChUnE,MAAMC,GAAY,GAQlB,eAAsB,GACpB,EAC+B,CAC/B,IAAM,EAA4C,EAAE,CAChD,EAAS,EAET,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,wBAAyB,CAAE,UACzB,MAAM,EAMP,EAAQ,GAAsB,CAC/B,MAAOA,GACP,SACD,CAAC,CACF,EAAoB,KAAK,GAAG,EAAM,CAClC,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAoB,MAAM,EAAG,IAAM,EAAE,MAAM,cAAc,EAAE,MAAM,CAAC,CC5D3E,MAAM,GAAiB,GAUvB,eAAe,GACb,EACA,EACmB,CACnB,GAAM,CACJ,gCAAiC,CAAE,UACjC,MAAM,EASP,EAAQ,GAAiC,CAC1C,MAAO,CACL,UACD,CACF,CAAC,CACF,OAAO,EAAM,IAAK,GAAS,EAAK,MAAM,CAmBxC,eAAsB,GACpB,EACA,EACA,EACA,EAAc,GAQd,CACA,IAAI,EAAY,EACZ,GACF,EAAa,EAAE,CAEjB,IAAM,EAKA,EAAE,CAwBR,OArBA,MAAM,EACJC,EAAM,EAAS,GAAe,CAC9B,KAAO,IAAmB,CAMxB,IAAM,GALS,MAAM,GACnB,EAEA,EAAe,KAAK,CAAE,QAAO,GAAG,KAAW,EAAK,CACjD,EAC4B,KAAK,EAAO,KAAW,CAClD,MAAO,EAAe,GACtB,YAAa,EACd,EAAE,CACH,EAAQ,KAAK,GAAG,EAAc,CAC9B,GAAa,EAAe,OACxB,GACF,EAAa,EAAU,EAG3B,CAAE,cAAa,CAChB,CAEM,ECtGT,MAAMC,GAAY,GAQlB,eAAsB,GACpB,EACyB,CACzB,IAAM,EAAgC,EAAE,CACpC,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,cAAe,CAAE,UACf,MAAM,EAMP,EAAQ,GAAyB,CAClC,MAAOA,GACP,SACD,CAAC,CACF,EAAc,KAAK,GAAG,EAAM,CAC5B,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAc,MAAM,EAAG,IAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,CCRnE,MAAMC,GAAY,IASlB,eAAsB,GACpB,EACA,EAC2B,CAC3B,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,qCAAqC,EAAe,KAAK,CACzE,CACD,IAAM,EAAoC,EAAE,CACxC,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,gBAAiB,CAAE,UACjB,MAAM,EAMP,EAAQ,GAAkB,CAC3B,MAAOA,IACP,SACA,iBACD,CAAC,CACF,EAAgB,KAAK,GAAG,EAAM,CAC9B,GAAUA,IACV,EAAiB,EAAM,SAAWA,UAC3B,GAET,OAAO,EAAgB,MAAM,EAAG,IAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,CAGrE,MAAa,GAAuB,CAClCC,EAAAA,iBAAiB,YACjBA,EAAAA,iBAAiB,aAClB,CAQD,eAAsB,GACpB,EACsB,CACtB,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,6BAA6B,CAAC,CACzD,IAAM,EAA0B,EAAE,CAC9B,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,cAAe,CAAE,UACf,MAAM,EAMP,EAAQ,GAAY,CACrB,MAAOD,IACP,SACD,CAAC,CACF,EAAW,KACT,GAAI,MAAM,QAAQ,IAChB,EAAM,IAAI,KAAO,KAAU,CACzB,GAAG,EACH,OAAQ,GAAqB,SAAS,EAAK,KAAK,CAC5C,MAAM,GAAwB,EAAQ,EAAK,GAAG,CAC9C,EAAE,CACP,EAAE,CACJ,CACF,CACD,GAAUA,IACV,EAAiB,EAAM,SAAWA,UAC3B,GAET,OAAO,EAAW,MAAM,EAAG,IAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,CC5FhE,MAAME,GAAY,GAQlB,eAAsB,GACpB,EAC2B,CAC3B,IAAM,EAAqC,EAAE,CACzC,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,iBAAkB,CAAE,UAClB,MAAM,EAMP,EAAQ,GAAmB,CAC5B,MAAOA,GACP,SACD,CAAC,CACF,EAAiB,KAAK,GAAG,EAAM,CAC/B,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAiB,MAAM,EAAG,IAAM,EAAE,MAAM,cAAc,EAAE,MAAM,CAAC,CCLxE,eAAsB,GACpB,EACyB,CACzB,GAAM,CACJ,eAAgB,CAAE,mBAChB,MAAM,EAMP,EAAQ,GAAsB,CACjC,OAAO,EAUT,eAAsB,EACpB,EACA,EACiB,CACjB,GAAM,CACJ,eAAgB,CAAE,mBAChB,MAAM,EASP,EAAQ,GAA0B,EAAE,CAAE,EAAE,CAAE,EAAY,CACzD,OAAO,EAAe,GAGxB,MAAMC,GAAY,GAsDlB,eAAsB,GACpB,EAC8B,CAC9B,IAAM,EAAmC,EAAE,CACvC,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,YAAa,CAAE,UACb,MAAM,EAMP,EAAQ,GAAa,CACtB,MAAOA,GACP,SACD,CAAC,CACF,EAAY,KAAK,GAAG,EAAM,CAC1B,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAY,MAAM,EAAG,IAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,CAMjE,IAAY,GAAA,SAAA,EAAL,OACL,GAAA,OAAA,KACA,EAAA,MAAA,YAsBF,eAAsB,GACpB,EACA,EAmBiC,CACjC,GAAM,CACJ,cAAe,CAAE,WACf,MAAM,EAMP,EAAQ,GAAgC,CACzC,QACD,CAAC,CACF,OAAO,EAqBT,eAAsB,GACpB,EACA,EAC8B,CAC9B,GAAM,CACJ,oBAAqB,CAAE,UACrB,MAAM,EAMP,EAAQ,GAA6B,CACtC,iBACD,CAAC,CACF,OAAO,EC3OT,MAAMC,GAAY,GASlB,eAAsB,GACpB,EACA,EAASC,EAAAA,qBAAqB,KACX,CACnB,IAAM,EAAoB,EAAE,CACxB,EAAS,EAEP,EAAiB,MAAM,EAAsB,EAAO,CAGtD,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,QAAS,CAAE,UACT,MAAM,EAMP,EAAQ,GAAS,CAClB,MAAOD,GACP,SACA,iBACA,SACD,CAAC,CACF,EAAQ,KAAK,GAAG,EAAM,CACtB,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAQ,MAAM,EAAG,IAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,CCrD7D,MAAME,GAAY,GAQlB,eAAsB,GACpB,EAC4B,CAC5B,IAAM,EAAuC,EAAE,CAC3C,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,kBAAmB,CAAE,UACnB,MAAM,EAMP,EAAQ,GAAqB,CAC9B,MAAOA,GACP,SACD,CAAC,CACF,EAAkB,KAAK,GAAG,EAAM,CAChC,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAkB,MAAM,EAAG,IAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,CCpBvE,MAAMC,GAAY,GASlB,eAAsB,GACpB,EACA,EAASC,EAAAA,qBAAqB,KACT,CACrB,IAAM,EAAwB,EAAE,CAC5B,EAAS,EAEP,EAAiB,MAAM,EAAsB,EAAO,CAGtD,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,UAAW,CAAE,UACX,MAAM,EAMP,EAAQ,GAAY,CACrB,MAAOD,GACP,SACA,iBACA,SACA,GAAI,IAAWC,EAAAA,qBAAqB,YAChC,CAAE,iBAAkB,GAAM,CAC1B,EAAE,CACP,CAAC,CACF,EAAU,KAAK,GAAG,EAAM,CACxB,GAAUD,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAU,MAAM,EAAG,IAAM,EAAE,MAAM,cAAc,EAAE,MAAM,CAAC,CClEjE,eAAsB,GACpB,EACoB,CACpB,GAAM,CAAE,sBAAuB,MAAM,EAGlC,EAAQ,GAAU,EAAE,CAAC,CACxB,OAAO,EC1BT,eAAsB,GACpB,EACiB,CACjB,GAAM,CAAE,gBAAiB,MAAM,EAM5B,EAAQ,GAA4B,CACvC,OAAO,EAAa,yBAUtB,eAAsB,GACpB,EACA,EACiB,CACjB,IAAI,EAAW,EACf,AACE,IAAW,MAAM,GAAsB,EAAO,CAEhD,GAAM,CAAE,iBAAkB,MAAM,EAM7B,EAAQ,GAAyB,CAClC,IAAK,EACN,CAAC,CACF,OAAO,EAAc,GCfvB,eAAsB,GACpB,EACmB,CAEnB,GAAM,CAAE,yBAA0B,MAAM,EAGrC,EAAQ,GAAU,CACnB,IAL+B,MAAM,GAAsB,EAAO,CAMnE,CAAC,CAEF,OAAO,EAAsB,MAAM,EAAG,IACpC,EAAE,MAAM,eAAe,cAAc,EAAE,MAAM,eAAe,CAC7D,CC9BH,SAAgB,EACd,EACsB,CACtB,IAAM,EAAmC,EAAE,CAiB3C,OAfA,EAAK,IAAK,GAAQ,CAChB,IAAI,EAAW,EAAW,KAAM,GAAQ,EAAI,MAAQ,EAAI,aAAa,KAAK,CAW1E,OATI,IAAa,IAAA,IACf,EAAW,CACT,IAAK,EAAI,aAAa,KACtB,OAAQ,CAAC,EAAI,KAAK,CACnB,CACD,EAAW,KAAK,EAAS,EAEzB,EAAS,OAAO,KAAK,EAAI,KAAK,CAEzB,GACP,CAEK,ECcT,MAAME,GAAY,GAQlB,eAAsB,GACpB,EAC4B,CAC5B,IAAM,EAAsC,EAAE,CAC1C,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,iBAAkB,CAAE,UAClB,MAAM,EAMP,EAAQ,GAAmB,CAC5B,MAAOA,GACP,SACD,CAAC,CACF,EAAiB,KAAK,GAAG,EAAM,CAC/B,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAiB,MAAM,EAAG,IAC/B,GAAG,EAAE,KAAK,GAAG,EAAE,QAAQ,eAAe,cACpC,GAAG,EAAE,KAAK,GAAG,EAAE,QAAQ,eACxB,CACF,CC/BH,eAAsB,GACpB,EAC0B,CAE1B,GAAM,CACJ,cAAe,CAAE,WAAU,GAAG,IAC5B,MAAM,EAMP,EAAQ,GAAgB,CACzB,IAV+B,MAAM,GAAsB,EAAO,CAWnE,CAAC,CAEF,MAAO,CACL,CACE,GAAG,EACH,MAAO,KAAK,MAAM,EAAS,CAC5B,CACF,CCSH,MAAMC,GAAY,GAQlB,eAAsB,GACpB,EAC+B,CAC/B,IAAM,EAA6C,EAAE,CACjD,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,qBAAsB,CAAE,UACtB,MAAM,EAMP,EAAQ,GAAuB,CAChC,MAAOA,GACP,SACD,CAAC,CACF,EAAqB,KAAK,GAAG,EAAM,CACnC,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAqB,MAAM,EAAG,IAAM,EAAE,MAAM,cAAc,EAAE,MAAM,CAAC,CCpF5E,MAAMC,GAAY,GAQlB,eAAsB,GACpB,EACyC,CACzC,IAAM,EAAiE,EAAE,CACrE,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,+BAAgC,CAAE,UAChC,MAAM,EAMP,EAAQ,GAAmC,CAC5C,MAAOA,GACP,SACD,CAAC,CACF,EAA+B,KAAK,GAAG,EAAM,CAC7C,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAA+B,MAAM,EAAG,IAC7C,EAAE,KAAK,cAAc,EAAE,KAAK,CAC7B,CC9BH,MAAMC,GAAY,GASlB,eAAsB,GACpB,EACA,CACE,iBAAiB,IAIf,EAAE,CACc,CACpB,IAAM,EAAsB,EAAE,CAC1B,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,SAAU,CAAE,UACV,MAAM,EAMP,EAAQ,GAAU,CACnB,MAAOA,GACP,SACA,MAAO,CACL,iBACD,CACF,CAAC,CACF,EAAS,KAAK,GAAG,EAAM,CACvB,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAS,MAAM,EAAG,IAAM,EAAE,aAAa,cAAc,EAAE,aAAa,CAAC,CCpE9E,eAAsB,GACpB,EACmC,CACnC,GAAM,CAAC,EAAU,GAAU,MAAM,QAAQ,IAAI,CAC3C,GAAiB,EAAO,CACxB,GAAyB,EAAO,CACjC,CAAC,CAEF,OAAO,EAAS,IAAK,GAAY,CAC/B,IAAM,EAAgB,EAAO,OAC1B,GAAU,EAAM,QAAQ,eAAiB,EAAQ,aACnD,CACD,MAAO,CACL,GAAG,EACH,OAAQ,EACT,EACD,CCbJ,MAAMC,GAAY,GASlB,eAAsB,GACpB,EACA,CACE,aAK0B,CAC5B,IAAM,EAAsC,EAAE,CAC1C,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,iBAAkB,CAAE,UAClB,MAAM,EAMP,EAAQ,GAAmB,CAC5B,MAAOA,GACP,SACA,YACD,CAAC,CACF,EAAiB,KAAK,GAAG,EAAM,CAC/B,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EClDT,MAAMC,GAAY,GASlB,eAAsB,GACpB,EACA,CACE,aAKoC,CACtC,IAAM,EAAkD,EAAE,CACtD,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,mBAAoB,CAAE,UACpB,MAAM,EAMP,EAAQ,GAAqB,CAC9B,MAAOA,GACP,SACA,WAAY,CAAC,EAAU,CACxB,CAAC,CACF,EAAmB,KAAK,GAAG,EAAM,CACjC,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EC7CT,MAAM,GAAgC,UAEhC,GAAoBC,EAAE,KAAK,CAE/B,GAAIA,EAAE,OAEN,KAAMA,EAAE,OAER,MAAOA,EAAE,OAET,MAAA,EAAA,EAAA,UAAeC,EAAAA,eAAe,CAC/B,CAAC,CAKIC,GAAY,GAEL,GAA6BF,EAAE,KAAK,CAC/C,YAAaA,EAAE,MAAM,GAAkB,CACxC,CAAC,CAUF,eAAsB,GACpB,EACA,EACA,CACE,aAK4B,CAC9B,IAAM,EAA0C,EAAE,CAC9C,EAAS,EACT,EAAiB,GAGf,CACJ,aAAc,CACZ,OAAQ,CAAE,QAAA,KAEV,MAAM,EASP,EAAS,GAAe,CAE3B,GAAIG,GAAW,EAAA,QAAO,GAAGA,EAAS,GAA8B,CAC9D,MAAU,MACR,4BAA4B,GAA8B,kCAC3D,CAGH,EAAG,CACD,IAAI,EACJ,GAAI,CACF,EAAW,MAAM,EACd,KAGE,yBAA0B,CAC3B,KAAM,CACJ,MAAOD,GACP,SACA,YACD,CACF,CAAC,CACD,MAAM,OACF,EAAK,CACZ,MAAU,MACR,wCACE,GAAK,UAAU,MAAQ,GAAK,UAE/B,CAGH,GAAM,CAAE,YAAa,IAAA,EAAA,EAAA,aACnB,GACA,EACD,CAED,EAAmB,KAAK,GAAG,EAAM,CAEjC,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EC7FT,MAAa,GAAwBE,EAAE,KAAK,CAC1C,MAAOA,EAAE,OACT,KAAMA,EAAE,OACR,QAASA,EAAE,QACX,oBAAqBA,EAAE,MACrBA,EAAE,KAAK,CACL,MAAOA,EAAE,OACT,aAAcA,EAAE,MACdA,EAAE,KAAK,CACL,GAAIA,EAAE,OACN,KAAMA,EAAE,OACR,iBAAkBA,EAAE,KAAK,CACvB,GAAIA,EAAE,OACN,KAAMA,EAAE,OACR,MAAOA,EAAE,KAAK,CACZ,eAAgBA,EAAE,OACnB,CAAC,CACH,CAAC,CACH,CAAC,CACH,CACD,YAAaA,EAAE,KAAK,CAClB,GAAIA,EAAE,OACN,KAAMA,EAAE,OACT,CAAC,CACF,gBAAiBA,EAAE,KAAK,CACtB,MAAOA,EAAE,KAAK,CACZ,eAAgBA,EAAE,OACnB,CAAC,CACF,GAAIA,EAAE,OACN,KAAMA,EAAE,OACT,CAAC,CACF,KAAMA,EAAE,OACR,GAAIA,EAAE,OACN,aAAcA,EAAE,QACjB,CAAC,CACH,CACF,CAAC,CAKW,GAAiBA,EAAE,aAAa,CAC3CA,EAAE,KAAK,CAEL,GAAIA,EAAE,OAEN,UAAWA,EAAE,OAEb,MAAOA,EAAE,OAET,MAAA,EAAA,EAAA,UAAeC,EAAAA,cAAc,CAE7B,KAAMD,EAAE,OAER,SAAUA,EAAE,QAEZ,QAAA,EAAA,EAAA,UAAiBE,EAAAA,cAAc,CAE/B,OAAQF,EAAE,QAEV,eAAgBA,EAAE,OAElB,QAASA,EAAE,OAEX,QAAA,EAAA,EAAA,UAAiBG,EAAAA,WAAW,CAE5B,QAAA,EAAA,EAAA,UAAiBC,EAAAA,cAAc,CAE/B,YAAaJ,EAAE,OAEf,QAASA,EAAE,MAAM,CAACA,EAAE,MAAA,EAAA,EAAA,UAAeK,EAAAA,eAAe,CAAC,CAAC,CAEpD,mBAAoBL,EAAE,MAAM,CAACA,EAAE,MAAA,EAAA,EAAA,UAAeM,EAAAA,0BAA0B,CAAC,CAAC,CAE1E,gBAAiBN,EAAE,MACjBA,EAAE,KAAK,CACL,GAAIA,EAAE,OACN,aAAcA,EAAE,KAAK,CAAE,KAAMA,EAAE,OAAQ,GAAIA,EAAE,OAAQ,CAAC,CACtD,KAAMA,EAAE,OACT,CAAC,CACH,CACF,CAAC,CACFA,EAAE,QAAQ,CAER,cAAeA,EAAE,MAAM,CAACA,EAAE,KAAMA,EAAE,OAAO,CAAC,CAE1C,QAAS,GACV,CAAC,CACH,CAAC,CAKIO,GAAY,GASlB,eAAsB,EACpB,EACA,CACE,UAAU,EAAE,CACZ,WAAW,EAAE,CACb,UAAU,EAAE,CACZ,OACA,kBACA,iBACA,SACA,WACA,WACA,aAAa,EAAE,EAyBb,EAAE,CACqB,CAC3B,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,uBAAuB,CAAC,CAGnD,IAAM,EAAK,IAAI,MAAM,CAAC,SAAS,CACzB,EAAc,IAAIC,EAAAA,QAAY,UAClC,EAAE,CACFA,EAAAA,QAAY,QAAQ,eACrB,CAGK,EAA6B,EAAE,CACjC,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,SAAU,CAAE,QAAO,eACjB,MAAM,EAQP,EAAQ,GAAU,CACnB,MAAOD,GACP,SACA,SAAU,CACR,OACA,KAAM,EAAQ,OAAS,EAAI,EAAU,IAAA,GACrC,OAAQ,EAAS,OAAS,EAAI,EAAW,IAAA,GACzC,OAAQ,EAAQ,OAAS,EAAI,EAAU,IAAA,GACvC,SACA,WACA,WACA,gBAAiB,EACb,EAAgB,aAAa,CAC7B,IAAA,GACJ,eAAgB,EACZ,EAAe,aAAa,CAC5B,IAAA,GACL,CACF,CAAC,CACE,IAAW,GAAK,EAAaA,KAC/B,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,YAAY,EAAW,WAAW,CAAC,CAC9D,EAAY,MAAM,EAAY,EAAE,EAGlC,EAAS,KAAK,GAAG,EAAM,CACvB,GAAUA,GACV,EAAY,OAAO,EAAO,CAC1B,EAAiB,EAAM,SAAWA,SAC3B,GAET,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SAAS,CACR,EAGvB,EAAA,EAAO,KACL,EAAA,QAAO,MACL,yBAAyB,EAAS,OAAO,eACvC,EAAY,IACb,YACF,CACF,CAGD,IAAI,EAAc,EAYlB,OAXI,GAAc,EAAW,OAAS,IACpC,EAAc,EAAY,OAAQ,GAChC,EAAW,SAAS,EAAQ,GAAG,CAChC,CACD,EAAA,EAAO,KACL,EAAA,QAAO,MACL,oBAAoB,EAAY,OAAO,qBAAqB,EAAW,OAAO,gBAC/E,CACF,EAGI,EC1MT,MAAME,GAAY,GAQlB,eAAsB,GAAc,EAAwC,CAC1E,IAAM,EAAgB,EAAE,CACpB,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,MAAO,CAAE,UACP,MAAM,EAMP,EAAQ,GAAO,CAChB,MAAOA,GACP,SACD,CAAC,CACF,EAAM,KAAK,GAAG,EAAM,CACpB,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAM,MAAM,EAAG,IAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,CCzD3D,MAAMC,GAAY,GAQlB,eAAsB,GAAc,EAAwC,CAC1E,IAAM,EAAgB,EAAE,CACpB,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,MAAO,CAAE,UACP,MAAM,EAMP,EAAQ,GAAO,CAChB,MAAOA,GACP,SACD,CAAC,CACF,EAAM,KAAK,GAAG,EAAM,CACpB,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAM,MAAM,EAAG,IAAM,EAAE,MAAM,cAAc,EAAE,MAAM,CAAC,CCW7D,MAAMC,GAAY,GAQlB,eAAsB,GACpB,EACmB,CACnB,IAAM,EAAoB,EAAE,CACxB,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,QAAS,CAAE,UACT,MAAM,EAMP,EAAQ,GAAS,CAClB,MAAOA,GACP,SACD,CAAC,CACF,EAAQ,KAAK,GAAG,EAAM,CACtB,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAQ,MAAM,EAAG,IAAM,EAAE,MAAM,cAAc,EAAE,MAAM,CAAC,CC3E/D,MAAMC,GAAY,GAEZ,GAAa,mDASnB,eAAsB,GACpB,EACA,EACmB,CACnB,IAAM,EAAoB,EAAE,CACxB,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,QAAS,CAAE,UACT,MAAM,EAMP,EAAQ,GAAU,CACnB,MAAOA,GACP,SACA,SACD,CAAC,CACF,EAAQ,KAAK,GAAG,EAAM,CACtB,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GACT,OAAO,EAAQ,MAAM,EAAG,IAAM,EAAE,MAAM,cAAc,EAAE,MAAM,CAAC,CAY/D,eAAsB,GACpB,CACE,WAAY,EAAe,EAAE,CAC7B,aAAc,EAAY,EAAE,EAE9B,EACA,EAAW,GACyB,CACpC,EAAA,EAAO,KACL,EAAA,QAAO,QACL,YAAY,EAAW,MAAQ,EAAa,OAAO,cACpD,CACF,CACD,IAAM,EAAS,EAAa,KAAK,CAAE,WAAY,EAAM,CAC/C,EAAuBC,EAC3B,EACG,IAAK,GAAS,EAAK,iBAAiB,CACpC,OAAQ,GAAmB,CAAC,CAAC,EAAE,CACnC,CACK,EAAoB,CAAC,GAAG,EAAsB,GAAG,EAAO,CACxD,EAAU,MAAM,GACpB,EACA,EAAW,IAAA,GAAY,CAAC,GAAG,EAAsB,GAAG,EAAO,CAC5D,CAGK,EAAiBC,EAAAA,EAAM,EAAS,QAAQ,CAGxC,EAAiBC,EACrB,EACA,EAAQ,KAAK,CAAE,WAAY,EAAM,CAClC,CAaD,OAVI,EAAe,OAAS,IAC1B,EAAA,EAAO,KACL,EAAA,QAAO,IACL,4BAA4B,EAAe,KACzC,OACD,CAAC,8FACH,CACF,CACD,QAAQ,KAAK,EAAE,EAEV,ECjGT,MAAMC,GAAY,IAQlB,eAAsB,GACpB,EACoB,CACpB,IAAM,EAAsB,EAAE,CAC1B,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,SAAU,CAAE,UACV,MAAM,EAMP,EAAQ,GAAU,CACnB,MAAOA,IACP,SACD,CAAC,CACF,EAAS,KAAK,GAAG,EAAM,CACvB,GAAUA,IACV,EAAiB,EAAM,SAAWA,UAC3B,GACT,OAAO,EAAS,MAAM,EAAG,IACvB,EAAE,gBAAgB,cAAc,EAAE,gBAAgB,CACnD,CAgBH,eAAsB,GAAsB,EAK1C,CAEA,IAAM,EAAW,MAAM,GAAiB,EAAO,CAkB/C,MAAO,CACL,WACA,eAjBqB,EAAS,QAC7B,EAAK,IACJ,OAAO,OAAO,EAAK,EAAG,EAAQ,iBAAkB,EAAQ,MAAO,CAAC,CAClE,EAAE,CACH,CAcC,8BAXoC,EAAS,QAC5C,EAAK,IACJ,OAAO,OAAO,EAAK,EAChB,EAAQ,iBAAkB,EAAQ,oBACpC,CAAC,CACJ,EAAE,CACH,CAMA,CCxDH,eAAsB,GACpB,EACwB,CAExB,GAAM,CAAE,oBAAqB,MAAM,EAGhC,EAAQ,GAAc,CACzB,OAAO,EAWT,eAAsB,GACpB,CACE,aAAc,EAAY,EAAE,CAC5B,gBAAiB,EAAe,EAAE,CAClC,wBAAyB,EAAuB,EAAE,CAClD,YAAY,EAAE,EAEhB,EACA,EAAW,GACiC,CAE5C,IAAM,EAAuBC,EAAK,CAChC,GAAGC,GAAQ,EAAU,IAAK,GAAS,EAAK,kBAAoB,EAAE,CAAC,EAAI,EAAE,CAAC,CACtE,GAAGA,GACD,EAAqB,KAClB,CAAE,sBAAuB,GAAoB,EAAE,CACjD,EAAI,EAAE,CACR,CACD,GAAGA,GACD,EAAU,IAAK,GAAa,EAAS,kBAAoB,EAAE,CAAC,EAAI,EAAE,CACnE,CACD,GAAG,EAAa,IAAK,GAAY,EAAQ,KAAK,CAC/C,CAAC,CACF,GAAI,EAAqB,SAAW,GAAK,CAAC,EACxC,MAAO,EAAE,CAIX,IAAM,EAAmB,MAAM,GAAqB,EAAO,CACrD,EAAoBC,EAAAA,EAAM,EAAkB,OAAO,CAGnD,EAAsBC,EAC1B,EACA,EAAiB,KAAK,CAAE,UAAW,EAAK,CACzC,CA2BD,OAxBI,EAAoB,OAAS,IAC/B,EAAA,EAAO,KACL,EAAA,QAAO,QACL,YAAY,EAAoB,OAAO,uBACxC,CACF,CACD,MAAM,EAAU,EAAqB,KAAO,IAAgB,CAC1D,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,yBAAyB,EAAY,KAAK,CAAC,CACtE,GAAM,CAAE,iBAAkB,MAAM,EAM7B,EAAQ,GAAqB,CAC9B,KAAM,EACN,YAAa,GACd,CAAC,CACF,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,wBAAwB,EAAY,GAAG,CAAC,CAEjE,EAAkB,GAAe,EAAc,SAC/C,EAGG,EAUT,SAAgB,GACd,EACA,EACU,CAOV,OANA,EAAiB,QAAS,GAAS,CACjC,GAAI,CAAC,EAAgB,GACnB,MAAU,MAAM,6CAA6C,IAAO,EAEtE,CAEK,OAAO,OAAO,EAAgB,CAClC,OAAQ,GAAS,CAAC,EAAiB,SAAS,EAAK,KAAK,CAAC,CACvD,KAAK,CAAE,QAAS,EAAG,CAUxB,SAAgB,GACd,EACA,EACU,CAOV,OANA,EAAiB,QAAS,GAAS,CACjC,GAAI,CAAC,EAAgB,GACnB,MAAU,MAAM,6CAA6C,IAAO,EAEtE,CAEK,OAAO,OAAO,EAAgB,CAClC,OAAQ,GAAS,CAAC,EAAiB,SAAS,EAAK,KAAK,CAAC,CACvD,KAAK,CAAE,UAAW,EAAK,CChJ5B,MAAMC,GAAY,GAQlB,eAAsB,GACpB,EACwB,CACxB,IAAM,EAA8B,EAAE,CAClC,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,aAAc,CAAE,UACd,MAAM,EAMP,EAAQ,GAAe,CACxB,MAAOA,GACP,SACD,CAAC,CACF,EAAa,KAAK,GAAG,EAAM,CAC3B,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAa,MAAM,EAAG,IAAM,EAAE,MAAM,cAAc,EAAE,MAAM,CAAC,CCvCpE,MAAMC,GAAY,GAQlB,eAAsB,GACpB,EAC0B,CAC1B,IAAM,EAAkC,EAAE,CACtC,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,eAAgB,CAAE,UAChB,MAAM,EAMP,EAAQ,GAAiB,CAC1B,MAAOA,GACP,SACD,CAAC,CACF,EAAe,KAAK,GAAG,EAAM,CAC7B,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAe,MAAM,EAAG,IAAM,EAAE,MAAM,cAAc,EAAE,MAAM,CAAC,CCtBtE,MAAMC,GAAY,GASlB,eAAsB,GACpB,EACA,CACE,OACA,SAAS,EAAE,CACX,MAAM,EAAE,EAQN,EAAE,CACa,CACnB,IAAM,EAAoB,EAAE,CACxB,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,QAAS,CAAE,UACT,MAAM,EAMP,EAAQ,GAAS,CAClB,MAAOA,GACP,SACA,SAAU,CACR,GAAI,EAAO,CAAE,OAAM,CAAG,EAAE,CACxB,GAAI,EAAO,OAAS,EAAI,CAAE,MAAO,EAAQ,CAAG,EAAE,CAC9C,GAAI,EAAI,OAAS,EAAI,CAAE,GAAI,EAAK,CAAG,EAAE,CACtC,CACF,CAAC,CACF,EAAQ,KAAK,GAAG,EAAM,CACtB,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAQ,MAAM,EAAG,IAAM,EAAE,MAAM,cAAc,EAAE,MAAM,CAAC,CAgF/D,eAAsB,GACpB,EACA,CACE,eAAe,EAAE,CACjB,YAAY,EAAE,EAMZ,EAAE,CACiC,CACvC,GAAM,CAAE,wBAAyB,MAAM,EAGpC,EAAQ,GAAwB,CACjC,MAAO,CACL,GAAI,EAAa,OAAS,EAAI,CAAE,eAAc,CAAG,EAAE,CACnD,GAAI,EAAU,OAAS,EAAI,CAAE,YAAW,CAAG,EAAE,CAC9C,CACF,CAAC,CAEF,OAAO,EChKT,MAAMC,GAAY,GASlB,eAAsB,GACpB,EACA,EAMyB,CACzB,IAAM,EAAgC,EAAE,CACpC,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,cAAe,CAAE,UACf,MAAM,EAMP,EAAQ,GAAgB,CACzB,MAAOA,GACP,SACA,WACD,CAAC,CACF,EAAc,KAAK,GAAG,EAAM,CAC5B,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAc,MAAM,EAAG,IAAM,EAAE,SAAS,cAAc,EAAE,SAAS,CAAC,CC5B3E,eAAsB,GACpB,EACA,CAAE,YAAW,aAAY,kBAAiB,YACzB,CACjB,GAAM,CACJ,iBAAkB,CAAE,eAClB,MAAM,EAQP,EAAQ,GAAoB,CAC7B,MAAO,EACP,OAAQ,EACR,SAAU,CACR,aACA,YACA,OAAQ,EACR,cAAe,EAChB,CACF,CAAC,CAEF,OAAO,EAGT,MAAMC,GAAY,IASlB,eAAsB,GACpB,EACA,CACE,YACA,aACA,kBACA,WACA,QACA,cAiB0B,CAC5B,IAAM,EAAsC,EAAE,CAC1C,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,iBAAkB,CAAE,UAClB,MAAM,EAQP,EAAQ,GAAoB,CAC7B,MAAOA,IACP,SACA,SAAU,CACR,aACA,YACA,OAAQ,EACR,cAAe,EAChB,CACF,CAAC,CACF,EAAiB,KAAK,GAAG,EAAM,CAE/B,GAAUA,IACV,EAAiB,EAAM,SAAWA,IAClC,IAAa,EAAM,OAAO,OACnB,IAAmB,CAAC,GAAS,EAAS,IAE/C,OAAO,EAUT,eAAsB,GACpB,EACA,CACE,YACA,cAOwB,CAC1B,IAAM,EAAQ,MAAM,GAAsB,EAAQ,CAChD,YACA,aACD,CAAC,CACF,GAAI,EAAM,SAAW,EACnB,MAAU,MACR,iDAAiD,EAAU,cAAc,IAC1E,CAGH,OAAO,EAAM,GCtJf,eAAsB,GACpB,EACA,CACE,cAKe,CACjB,GAAM,CACJ,+BAAgC,CAAE,eAChC,MAAM,EAMP,EAAQ,GAAsC,CAC/C,MAAO,CACL,aACA,WAAY,GACb,CACF,CAAC,CAEF,OAAO,ECMT,eAAsB,GACpB,EAEA,EACA,EAMwB,CACxB,IAAM,EAA8B,EAAE,CAClC,EAAwB,KAGxB,EAAiB,GACrB,EAAG,CAaD,GAAM,CACJ,iBAAkB,CAAE,QAAO,aAZ3B,MAAM,EACJ,EACA,GACA,CACE,SAAU,CACR,GAAG,EACJ,CACD,MAAO,EACP,MAAO,GAAU,IAAA,GAClB,CACF,CAIH,EAAa,KAAK,GAAG,EAAM,CAC3B,EAAiB,EAAS,YAC1B,EAAS,EAAS,gBACX,GAET,OAAO,EAAa,MAAM,EAAG,IAAM,EAAE,SAAS,cAAc,EAAE,SAAS,CAAC,CCjD1E,eAAsB,GACpB,EACA,CACE,QACA,YAYD,CACD,GAAM,CACJ,qBAAsB,CAAE,gBACtB,MAAM,EAWP,EAAQ,GAAwB,CACjC,QACD,CAAC,CAEI,EAAM,MAAM,EAAO,WAStB,GAAO,CACR,QACA,WACA,UAAW,EAAY,gBACxB,CAAC,CACI,CACJ,MAAO,CAAE,SACP,EAAI,KAGF,EAAc,EAAI,QAAQ,IAAI,aAAa,CACjD,GAAI,CAAC,GAAe,CAAC,EAAY,SAAS,UAAU,CAClD,MAAU,MAAM,yCAAyC,CAG3D,MAAO,CACL,MAAO,EAAK,MACZ,cACD,CASH,eAAsB,GACpB,EACA,CACE,QACA,UAOa,CACf,GAAM,CACJ,qBAAsB,CAAE,gBACtB,MAAM,EAWP,EAAQ,GAAwB,CACjC,QACA,OAAQ,EACT,CAAC,CAEF,MAAM,EAAO,WAMV,GAAa,CACd,GAAI,EACJ,UAAW,EAAY,gBACxB,CAAC,CCrHJ,eAAsB,GACpB,EACA,EAMwB,CACxB,GAAM,CACJ,aAAc,CAAE,WACd,MAAM,EAMP,EAAQ,GAAgB,CAAE,QAAO,CAAC,CAErC,OAAO,EAST,eAAsB,GACpB,EACA,EACe,CACf,MAAM,EAAmB,EAAQ,GAAgB,CAAE,KAAI,CAAC,CC5C1D,MAAa,GAA6BC,EAAE,KAAK,CAC/C,6BAA8BA,EAAE,OAChC,mBAAoBA,EAAE,MAAM,CAC1BA,EAAE,QAAQC,EAAAA,mBAAmB,UAAU,CACvCD,EAAE,QAAQC,EAAAA,mBAAmB,aAAa,CAC1CD,EAAE,QAAQC,EAAAA,mBAAmB,QAAQ,CACrCD,EAAE,QAAQC,EAAAA,mBAAmB,WAAW,CACxCD,EAAE,QAAQC,EAAAA,mBAAmB,SAAS,CACvC,CAAC,CACF,mBAAoBD,EAAE,MAAMA,EAAE,OAAO,CACtC,CAAC,CAGW,GAAgCA,EAAE,KAAK,CAClD,6BAA8BA,EAAE,OAChC,mBAAoBA,EAAE,MAAM,CAC1BA,EAAE,QAAQC,EAAAA,mBAAmB,WAAW,CACxCD,EAAE,QAAQC,EAAAA,mBAAmB,QAAQ,CACtC,CAAC,CACH,CAAC,CAKW,GAAiBD,EAAE,MAAM,CACpC,GACA,GACD,CAAC,CAaW,GAETA,EAAE,UAAU,uBAAyB,GACvCA,EAAE,aAAa,CACbA,EAAE,KAAK,CAEL,eAAA,EAAA,EAAA,UAAwBE,EAAAA,cAAc,CACvC,CAAC,CACFF,EAAE,QAAQ,CAER,MAAOA,EAAE,MAAM,GAAe,CAE9B,YAAaA,EAAE,MAAM,EAAK,CAC3B,CAAC,CACH,CAAC,CACH,CAEY,GAAmBA,EAAE,QAAQ,CACxC,QAAA,EAAA,EAAA,UAAiBG,EAAAA,8BAA8B,CAC/C,KAAM,GACN,WAAY,GACb,CAAC,CAWF,SAAgB,GACd,EACkB,CAClB,OAAA,EAAA,EAAA,aAAmB,GAAkB,EAAa,CChFpD,MAAa,GAAsBC,EAAE,aAAa,CAChDA,EAAE,QAAQ,CACR,eAAgBA,EAAE,QAAQ,CACxB,YAAaA,EAAE,OACf,gBAAiBA,EAAE,OACnB,mBAAoBA,EAAE,OACvB,CAAC,CACH,CAAC,CACFA,EAAE,KAAK,CACL,mBAAoBA,EAAE,MAAMA,EAAE,OAAO,CACrC,oBAAA,EAAA,EAAA,UAA6BC,EAAAA,mBAAmB,CACjD,CAAC,CACH,CAAC,CAWF,SAAgB,GACd,EACqB,CACrB,OAAA,EAAA,EAAA,aAAmB,GAAqB,EAAU,CCsCpD,MAAM,GAAoB,GAS1B,eAAsB,GACpB,EACA,CACE,SACA,WACA,MAAM,EAAE,CACR,IAAA,EAAM,GACN,mBAAmB,EAAE,EAaD,CACtB,EAAA,EAAO,KACL,EAAA,QAAO,QACL,YAAY,EAAI,SAAW,EAAI,MAAQ,EAAI,OAAO,gBACnD,CACF,CAED,IAAM,EAAyB,EAAE,CAC7B,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,UAAW,CAAE,UACX,MAAM,EAMP,EAAQC,EAAK,CACd,SAAU,CACR,IAAK,EAAI,OAAS,EAAI,EAAM,IAAA,GAC5B,KAAM,EAAiB,OAAS,EAAI,EAAmB,IAAA,GACvD,SACD,CACD,MAAO,EACP,SACD,CAAC,CACF,EAAU,KAAK,GAAG,EAAM,CACxB,GAAU,EACV,EAAiB,EAAM,SAAW,QAC3B,GAaT,OAZA,EAAA,EAAO,KACL,EAAA,QAAO,MACL,oBAAoB,EAAU,OAAO,YACnC,EAAI,OAAS,EAAI,iBAAiB,EAAI,KAAK,IAAI,GAAK,GACrD,GACC,EAAiB,OAAS,EACtB,8BAA8B,EAAiB,KAAK,IAAI,GACxD,KAEP,CACF,CAEM,EAAU,MAAM,EAAG,IAAM,EAAE,MAAM,cAAc,EAAE,MAAM,CAAC,CAgHjE,eAAsB,GACpB,EACA,EACA,CACE,QACA,2BACA,YASuB,CACzB,IAAM,EAAgC,EAAE,CAEpC,EAAS,EAET,EAAiB,GACrB,EACE,IAAI,CACE,GACF,EAAA,EAAO,IACL,EAAA,QAAO,QAAQ,uCAAuC,IAAS,CAChE,CAEH,GAAM,CACJ,cAAe,CAAE,UACf,MAAM,EAOR,EACA,EACI,GACA,GACJ,CACE,MAAO,EACP,SAAU,CACR,WAAY,CAAC,EAAY,CAC1B,CACD,SACD,CACF,CAED,EAAc,KAAK,GAAG,EAAM,CAC5B,GAAU,EACV,EAAiB,EAAM,SAAW,EAE9B,GACF,EAAA,EAAO,IACL,EAAA,QAAO,MACL,sCAAsC,EAAO,mBAAmB,IACjE,CACF,OAEI,EAAK,CAMZ,MALA,EAAA,EAAO,MACL,EAAA,QAAO,IACL,8CAA8C,EAAO,mBAAmB,IACzE,CACF,CACK,QAED,GACT,OAAOC,GAAO,EAAe,OAAO,CAWtC,eAAsB,GACpB,EACA,EACA,CACE,QACA,WACA,oBACA,4BAWoC,CACtC,IAAM,EAA0C,EAAE,CAG9C,EAAS,EAGT,EAAiB,GACrB,EAAG,CACG,GACF,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,oCAAoC,IAAS,CAAC,CAG3E,GAAM,CACJ,WAAY,CAAE,UACZ,MAAM,EAMP,EAAQ,GAAa,CACtB,MAAO,EACP,SAAU,CACR,UAAW,CAAC,EAAW,CACxB,CACD,SACD,CAAC,CAEE,GACF,EAAA,EAAO,KACL,EAAA,QAAO,QACL,WAAW,EAAM,OAAO,yBAAyB,IAClD,CACF,CAGE,IACH,MAAM,EACJ,EAEA,KAAO,IAAS,CACd,GAAI,CACE,GACF,EAAA,EAAO,KACL,EAAA,QAAO,QACL,8BAA8B,EAAK,KAAK,wBAAwB,IACjE,CACF,CAGH,IAAM,EAAgB,MAAM,GAAsB,EAAQ,EAAK,GAAI,CACjE,SAAU,IACV,QACA,2BACD,CAAC,CACF,EAAW,KAAK,CACd,GAAG,EACH,cAAe,EAAc,MAAM,EAAG,IACpC,EAAE,KAAK,cAAc,EAAE,KAAK,CAC7B,CACF,CAAC,CAEE,GACF,EAAA,EAAO,KACL,EAAA,QAAO,MACL,0CAA0C,EAAK,OAChD,CACF,OAEI,EAAK,CAMZ,MALA,EAAA,EAAO,MACL,EAAA,QAAO,IACL,uCAAuC,EAAK,KAAK,oBAAoB,IACtE,CACF,CACK,IAIV,CACE,YAAa,EACd,CACF,CAEG,GACF,EAAA,EAAO,KACL,EAAA,QAAO,MACL,+DAA+D,IAChE,CACF,EAIL,GAAU,EACV,EAAiB,EAAM,SAAW,QAC3B,GACT,OAAO,EAAW,MAAM,EAAG,IAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,CA+GhE,eAAsB,GACpB,EACA,CACE,MACA,WACA,SACA,QACA,iBACA,oBACA,2BACA,oBAmB0D,CAC5D,IAAM,EAA+D,EAAE,CAGjE,EAAQ,MAAM,GAAoC,EAAQ,CAC9D,SACA,MACA,mBACA,WACA,IAAK,GACN,CAAC,CAsCF,OAnCK,GACH,MAAM,EAAU,EAAO,MAAO,EAAM,IAAU,CAC5C,EAAA,EAAO,KACL,EAAA,QAAO,QACL,IAAI,EAAQ,EAAE,GAAG,EAAM,OAAO,yBAAyB,EAAK,QAC7D,CACF,CAED,IAAM,EAAa,MAAM,GAAmB,EAAQ,EAAK,GAAI,CAC3D,QACA,WACA,oBACA,2BACD,CAAC,CAEE,GACF,EAAA,EAAO,KACL,EAAA,QAAO,MACL,IAAI,EAAQ,EAAE,GACZ,EAAM,OACP,yCAAyC,EAAK,QAChD,CACF,CAGH,EAAU,KAAK,CAAC,EAAM,EAAW,CAAC,EAClC,CAGJ,EAAA,EAAO,KACL,EAAA,QAAO,MACL,4BAA4B,EAAM,OAAO,2BAC1C,CACF,CAEM,EAWT,eAAsB,GACpB,EACA,EACA,CACE,WACA,qBACA,kBAcD,CACD,IAAI,EAAmB,GAGjB,EAAK,IAAI,MAAM,CAAC,SAAS,CAC/B,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,YAAY,EAAU,OAAO,iBAAiB,CAAC,CAS1E,IAAM,EAA0BC,EAAAA,EANN,MAAM,GAAkB,EAAQ,CACxD,OAAQ,EAAU,KAAK,CAAE,WAAY,EAAM,CAC3C,WACD,CAAC,CAKA,QACD,CAGK,EAAoB,EAAU,QACjC,CAAE,WAAY,CAAC,EAAwB,GACzC,CACG,EAAkB,OAAS,IAC7B,EAAA,EAAO,KACL,EAAA,QAAO,QACL,aAAa,EAAkB,OAAO,oCACvC,CACF,CAID,MAAM,EADUC,EAAM,EAAmB,GAAkB,CAClC,KAAO,IAA0B,CACxD,GAAM,CACJ,gBAAiB,CAAE,UAAA,IACjB,MAAM,EAMP,EAAQ,GAAmB,CAC5B,MAAO,EAAsB,IAAK,IAAW,CAC3C,KAAM,EAAM,eAAiB,EAAM,gBACnC,MAAO,EAAM,MACb,QAAS,EAAM,QACf,mBAAoB,EAAM,mBAC3B,EAAE,CACJ,CAAC,CAGF,EAAU,QAAS,GAAS,CAC1B,EAAwB,EAAK,OAAS,GACtC,EACF,CAEF,EAAA,EAAO,KACL,EAAA,QAAO,MACL,yBAAyB,EAAkB,OAAO,eACnD,CACF,EAIH,IAAM,EAAiBA,EAAM,EAAW,GAAkB,CAC1D,MAAM,EAAU,EAAgB,MAAO,EAAqB,IAAQ,CAClE,EAAA,EAAO,KACL,EAAA,QAAO,QACL,UAAU,EAAM,EAAE,GAAG,EAAe,OAAO,aACzC,EAAoB,OACrB,cACF,CACF,CACD,MAAM,EAMH,EAAQ,GAAmB,CAC5B,MAAO,CACL,UAAW,EAAoB,IAAK,IAAW,CAC7C,GAAI,EAAwB,EAAM,OAAO,GACzC,QAAS,EAAM,QACf,mBAAoB,EAAM,mBAC1B,IAAK,EAAM,IACX,QAAS,EAAM,QACf,YAAa,EAAM,YACnB,YAAa,EAAM,iBACnB,OAAQ,CAAC,EAAM,SACf,YAAa,EAAM,OACnB,UAAW,EAAM,MAGjB,yBAA0B,EAAM,yBAC5B,IAAA,GACA,EAAE,CACN,SAAU,EAAM,iBACZ,EAAe,EAAM,kBAAkB,GACvC,IAAA,GACJ,wBAAyB,EAAM,iBAC3B,GACE,EAAM,iBACN,EACD,CACD,IAAA,GACJ,WAAY,EAAM,WAClB,qBAAsB,EAAM,qBAE5B,mBAAoB,EAAM,oBAAoB,wBAC9C,gCACE,EAAM,oBAAoB,kBAC5B,2BAA4B,EAAM,oBAAoB,aACtD,+CACE,EAAM,oBAAoB,kCAC5B,qCACE,EAAM,oBAAoB,wBAC5B,yBACE,EAAM,oBAAoB,+BAC7B,EAAE,CACJ,CACF,CAAC,CACF,EAAA,EAAO,KACL,EAAA,QAAO,MACL,UAAU,EAAM,EAAE,GAAG,EAAe,OAAO,YACzC,EAAoB,OACrB,eACF,CACF,EACD,CAKF,IAAM,EAAc,IAAIC,EAAAA,QAAY,UAClC,EAAE,CACFA,EAAAA,QAAY,QAAQ,eACrB,CACK,EAA0B,EAAU,QACvC,CAAE,aAAa,EAAE,IAAO,EAAW,OAAS,EAC9C,CACK,EAAkB,EACrB,KAAK,CAAE,aAAa,EAAE,IAAO,EAAW,OAAO,CAC/C,QAAQ,EAAK,IAAU,EAAM,EAAO,EAAE,CACzC,EAAA,EAAO,KACL,EAAA,QAAO,QACL,YAAY,EAAgB,qBAAqB,EAAwB,OAAO,iBACjF,CACF,CACD,EAAY,MAAM,EAAiB,EAAE,CACrC,IAAI,EAAQ,EAEZ,MAAM,EACJ,EACA,MAAO,CAAE,aAAY,WAAY,CAC3B,GACF,MAAM,EAAU,EAAY,KAAO,IAAc,CAC/C,IAAM,EAAS,EAAU,OACrB,EAAU,OAAO,KACd,CACC,MACA,cACA,aACA,WACA,aACA,GAAG,MAGF,CACC,KAAM,EACN,cACA,WAAa,EAET,EAAW,IAAK,IAAc,CAC5B,GAAG,EACH,KAAM,EAAS,MAAQ,QACxB,EAAE,CAJH,IAAA,GAKJ,SAAW,EAEP,EAAS,IAAK,IAAa,CACzB,GAAG,EACH,KAAM,EAAQ,MAAQ,QACvB,EAAE,CAJH,IAAA,GAKJ,aACA,+BACE,EAAK,qCACP,+BACE,EAAK,qCACR,EACJ,CACD,IAAA,GAEE,EAAU,CACd,WAAY,EAAwB,GAAO,GAC3C,KAAM,EAAU,KAChB,KAAM,EAAU,IAChB,MAAO,EAAU,MACjB,YAAa,EAAU,YACvB,GAAI,EAAU,OACV,CACE,YAAa,EAAU,OACxB,CACD,EAAE,CACN,GAAI,EAAU,MACV,CACE,UAAW,EAAU,MACtB,CACD,EAAE,CACN,GAAI,EAAU,uBACV,CAAE,kBAAmB,EAAU,uBAAwB,CACvD,EAAE,CACN,iBAAmB,EAAU,0BAEzB,OAAO,QAAQ,EAAU,0BAA0B,CAAC,KACjD,CAAC,EAAK,MAAY,CACjB,YAAa,EACb,eAAgB,EACjB,EACF,CAND,IAAA,GAOJ,eAAgB,EAAU,oBAAsB,EAAE,CAClD,cAAe,EAChB,CAGK,GAAyB,EAAQ,eAAiB,EAAE,EAAE,KACzD,CAAE,UAAW,EACf,CACK,EAAsB,EAAsB,QAC/C,EAAM,IAAU,EAAsB,QAAQ,EAAK,GAAK,EAC1D,CACD,GAAI,EAAoB,OAAS,EAC/B,EAAA,EAAO,KACL,EAAA,QAAO,IACL,8BACE,EAAU,IACX,6DAA6D,EAAoB,KAChF;EACD,GACF,CACF,CACD,EAAmB,QAEnB,GAAI,CACF,MAAM,EACJ,EACA,GACA,EACD,OACM,EAAK,CACZ,EAAA,EAAO,KACL,EAAA,QAAO,IACL,iCAAiC,EAAU,IAAI,mBAAmB,EAAM,SAAS,EAAI,UACtF,CACF,CACD,EAAmB,GAGvB,GAAS,EACT,EAAY,OAAO,EAAM,EACzB,EAGN,CACE,YAAa,GACd,CACF,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SAAS,CACR,EAWvB,OATA,EAAA,EAAO,KACL,EAAA,QAAO,MACL,WACE,EAAU,OACX,oBAAoB,EAAgB,mBACnC,EAAY,IACb,YACF,CACF,CACM,CACL,QAAS,CAAC,EACV,mBAAA,EAAA,EAAA,OAAyB,GAA0B,CAAE,QAAS,EAAG,CAClE,CAUH,eAAsB,GACpB,EACA,EACkB,CAClB,IAAI,EAAmB,GAgDvB,OA/CA,EAAA,EAAO,KACL,EAAA,QAAO,QACL,YAAY,EAAkB,OAAO,6BACtC,CACF,CAID,MAAM,EADiBD,EAAM,EAAmB,GAAkB,CAClC,MAAO,EAAuB,IAAQ,CACpE,EAAA,EAAO,KACL,EAAA,QAAO,QACL,UAAU,EAAI,GAAG,EAAsB,OAAO,cAAc,EAAsB,OAAO,iBAC1F,CACF,CACD,GAAI,CACF,MAAM,EAMH,EAAQ,GAAmB,CAC5B,MAAO,CACL,UAAW,EAAsB,KAC9B,CAAC,EAAI,MAA+B,CACnC,KACA,2BACD,EACF,CACF,CACF,CAAC,CACF,EAAA,EAAO,KACL,EAAA,QAAO,MACL,UAAU,EAAM,EAAE,GAAG,EAAsB,OAAO,YACrC,EAAsB,OAAO,eAC3C,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,UAAU,EAAM,EAAE,GAAG,EAAsB,OAAO,sBAC3B,EAAsB,OAAO,aAAa,EAAI,UACtE,CACF,GAEH,CACK,CAAC,EC/7BV,MAAME,GAAY,GASlB,eAAsB,GACpB,EACA,EACqB,CACrB,IAAM,EAAwB,EAAE,CAC5B,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,UAAW,CAAE,UACX,MAAM,EAMP,EAAQ,GAAW,CACpB,MAAOA,GACP,SACA,QACD,CAAC,CACF,EAAU,KAAK,GAAG,EAAM,CACxB,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAU,MAAM,EAAG,IAAM,EAAE,MAAM,cAAc,EAAE,MAAM,CAAC,CASjE,eAAsB,GACpB,EACA,CACE,WACA,mBACA,sBASa,CAGf,IAAM,GADU,MAAM,GAAkB,EAAQ,EAAS,MAAM,EAC9B,MAC9B,CAAE,WAAY,IAAU,EAAS,MACnC,CAGK,EAAiB,EAAS,kBAAkB,IAAK,GAAY,CACjE,IAAM,EAAW,EAAmB,GACpC,GAAI,CAAC,EACH,MAAU,MAAM,4CAA4C,IAAU,CAExE,OAAO,EAAS,IAChB,CAGI,EAAkB,EAAS,oBAC3B,EACJ,EAAS,oBAAsB,OAAO,OAAOC,EAAAA,cAAc,CACzD,EACF,MAAM,EAAmB,EAAQ,GAAiB,CAChD,MAAO,CACL,GAAI,EAAiB,GACrB,MAAO,EAAS,MAChB,IAAK,EAAS,IACd,QAAS,EAAS,QAClB,UAAW,EAAS,UACpB,iBAAkB,EAAS,iBAC3B,mBACE,OAAO,EAAS,oBAAuB,SACnC,EAAS,mBAAmB,UAAU,CACtC,IAAA,GACN,wBAAyB,EAAS,wBAClC,aAAc,EAAS,aACvB,WAAY,EAAS,WACrB,iBACA,YAAa,EAAS,aAAe,GACrC,gBAAiB,EACb,EAAiB,GAAiB,GAClC,IAAA,GACJ,YAAa,EAAS,sBAAsB,IACzC,GAAO,EAAiB,GAAI,GAC9B,CACD,GAAI,EAAiB,OAASC,EAAAA,aAAa,OACvC,EAAE,CACF,CAAE,QAAS,EAAe,CAC/B,CACF,CAAC,CACO,GACT,MAAM,EAAmB,EAAQ,GAAiB,CAChD,MAAO,CACL,MAAO,EAAS,MAChB,IAAK,EAAS,IACd,KAAM,EAAS,MAAQA,EAAAA,aAAa,OACpC,QAAS,EAAS,QAClB,UAAW,EAAS,UACpB,iBAAkB,EAAS,iBAC3B,mBACE,OAAO,EAAS,oBAAuB,SACnC,EAAS,mBAAmB,UAAU,CACtC,IAAA,GACN,wBAAyB,EAAS,wBAClC,aAAc,EAAS,aACvB,iBACA,WAAY,EAAS,WACrB,YAAa,EAAS,aAAe,GACrC,gBAAiB,EAAiB,GAAiB,GACnD,YAAa,EAAS,sBAAsB,IACzC,GAAO,EAAiB,GAAI,GAC9B,CACD,QAAS,EACV,CACF,CAAC,CCvKN,MAAMC,GAAY,GASlB,eAAsB,GACpB,EACA,EACqB,CACrB,IAAM,EAAwB,EAAE,CAC5B,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,UAAW,CAAE,UACX,MAAM,EAMP,EAAQ,GAAW,CACpB,MAAOA,GACP,SACA,QACD,CAAC,CACF,EAAU,KAAK,GAAG,EAAM,CACxB,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAU,MAAM,EAAG,IAAM,EAAE,MAAM,cAAc,EAAE,MAAM,CAAC,CASjE,eAAsB,GACpB,EACA,EACe,EAEC,MAAM,GAAkB,EAAQ,EAAS,MAAM,EAC9B,MAC9B,CAAE,WAAY,IAAU,EAAS,MACnC,EAIC,MAAM,EAAmB,EAAQ,GAAiB,CAChD,MAAO,EAAS,MACjB,CAAC,CC9DN,SAAgB,GAAc,EAA+B,CAC3D,OAAO,EAAK,KAAK,CAAE,UAAS,yBAA0B,CACpD,UACA,GAAI,EAAqB,CAAE,qBAAoB,CAAG,EAAE,CACrD,EAAE,CCCL,eAAsB,GACpB,EACA,EAGI,EAAE,CAC2B,CACjC,GAAM,CACJ,4BAA6B,CAAE,UAC7B,MAAM,EAMP,EAAQ,GAAgC,CACzC,SAAU,CACR,GAAG,EACJ,CACF,CAAC,CACF,OAAO,ECnCT,MAAMC,GAAY,GAiBlB,eAAsB,GACpB,EAC+B,CAC/B,IAAM,EAAmC,EAAE,CACvC,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,kBAAmB,CAAE,UACnB,MAAM,EAMP,EAAQ,GAAoB,CAC7B,MAAOA,GACP,SACD,CAAC,CACF,EAAW,KAAK,GAAG,EAAM,CACzB,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAW,MAAM,EAAG,IAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,CAUhE,eAAsB,GACpB,EACA,EACkB,CAElB,IAAM,EAAiB,MAAM,EAAsB,EAAO,CACtD,EAAmB,GACjB,EAAa,MAAM,GAAgB,EAAO,CAyBhD,OApBA,MAAM,EAJoBC,EACxB,EAAgB,KAAK,CAAE,UAAW,EAAK,CACvC,EAAW,KAAK,CAAE,UAAW,EAAK,CACnC,CACkC,KAAO,IAAS,CACjD,GAAI,CACF,MAAM,EAAmB,EAAQ,GAA0B,CACzD,MAAO,CACL,GAAI,EACJ,OACD,CACF,CAAC,CACF,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,2CAA2C,EAAK,GAAG,CACjE,OACM,EAAK,CACZ,EAAA,EAAO,MACL,EAAA,QAAO,IACL,uCAAuC,EAAK,MAAM,EAAI,UACvD,CACF,CACD,EAAmB,KAErB,CACK,CAAC,ECzDV,MAAMC,GAAY,GAQlB,eAAsB,GACpB,EACgC,CAChC,IAAM,EAA8C,EAAE,CAClD,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,qBAAsB,CAAE,UACtB,MAAM,EAMP,EAAQ,GAAwB,CACjC,MAAOA,GACP,SACA,MAAO,EAAE,CACT,SAAU,EAAE,CACb,CAAC,CAEI,EAAc,EAAM,IAAK,GAC7B,EAAK,QAAU,MAAQ,EAAK,kBAAkB,MAC1C,CAAE,GAAG,EAAM,MAAO,EAAK,iBAAiB,MAAO,CAC/C,EACL,CAED,EAAqB,KAAK,GAAG,EAAY,CACzC,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,ECiBT,MAAa,GAAmC,CAC9CC,EAAAA,EAAsB,UACtBA,EAAAA,EAAsB,UACtBA,EAAAA,EAAsB,UACtBA,EAAAA,EAAsB,QACvB,CA8BD,eAAsB,GACpB,EACA,CACE,cACA,mBACA,QACA,YAAY,GACZ,WACA,iBACA,2BACA,oBACA,kBAAkB,OAAO,OAAOC,EAAAA,qBAAqB,EAE9B,CACzB,GAAI,EAAY,OAAS,GAAK,EAAiB,OAAS,EACtD,MAAU,MACR,4DACD,CAGH,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,gCAAgC,EAAS,KAAK,CAAC,CAG1E,GAAM,CACJ,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,GACA,EACA,GACA,EACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,IACE,MAAM,QAAQ,IAAI,CAEpB,EAAU,SAASD,EAAAA,EAAsB,UAAU,EACnD,EAAU,SAASA,EAAAA,EAAsB,aAAa,CAClD,GAAqB,EAAO,CAC5B,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,QAAQ,CAC7C,GAAa,EAAE,CAAE,EAAQ,GAAK,CAC9B,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,UAAU,CAC/C,GAAuB,EAAQ,CAC7B,IAAK,EACL,mBACA,WACA,QACA,2BACA,iBACA,oBACD,CAAC,CACF,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,UAAU,CAC/C,GAAkB,EAAO,CACzB,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,UAAU,CAC/C,CACE,GAAI,EAAgB,SAASC,EAAAA,qBAAqB,KAAK,CACnD,MAAM,GAAkB,EAAQA,EAAAA,qBAAqB,KAAK,CAC1D,EAAE,CACN,GAAI,EAAgB,SAASA,EAAAA,qBAAqB,YAAY,CAC1D,MAAM,GAAkB,EAAQA,EAAAA,qBAAqB,YAAY,CACjE,EAAE,CACP,CACD,EAAE,CAEN,EAAU,SAASD,EAAAA,EAAsB,QAAQ,CAC7C,CACE,GAAI,EAAgB,SAASC,EAAAA,qBAAqB,KAAK,CACnD,MAAM,GAAgB,EAAQA,EAAAA,qBAAqB,KAAK,CACxD,EAAE,CACN,GAAI,EAAgB,SAASA,EAAAA,qBAAqB,YAAY,CAC1D,MAAM,GAAgB,EAAQA,EAAAA,qBAAqB,YAAY,CAC/D,EAAE,CACP,CACD,EAAE,CAEN,EAAU,SAASD,EAAAA,EAAsB,WAAW,CAChD,GAAmB,EAAO,CAC1B,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,UAAU,CAC/C,GAAkB,EAAO,CACzB,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,YAAY,CACjD,GAAoB,EAAO,CAC3B,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,QAAQ,CAC7C,GAAgB,EAAO,CACvB,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,iBAAiB,CACtD,GAAyB,EAAO,CAChC,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,qBAAqB,CAC1D,GAA6B,EAAO,CACpC,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,eAAe,CACpD,GAAoB,EAAO,CAC3B,IAAA,GAEJ,EAAU,SAASA,EAAAA,EAAsB,eAAe,CACpD,GAA+B,EAAO,CACtC,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,QAAQ,CAC7C,GAAgB,EAAO,CACvB,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,eAAe,CACpD,GAAuB,EAAO,CAC9B,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,aAAa,CAClD,GAAqB,EAAO,CAC5B,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,OAAO,CAC5C,GAAe,EAAO,CACtB,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,eAAe,CACpD,GAAuB,EAAO,CAC9B,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,WAAW,CAChD,GAAmB,EAAO,CAC1B,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,QAAQ,CAC7C,GAAgB,EAAO,CACvB,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,eAAe,CACpD,GAAuB,EAAO,CAC9B,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,mBAAmB,CACxD,GAA2B,EAAO,CAClC,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,YAAY,CACjD,GAAoB,EAAQ,CAAE,KAAM,CAACE,EAAAA,eAAe,WAAW,CAAE,CAAC,CAClE,EAAE,CAEN,EAAU,SAASF,EAAAA,EAAsB,sBAAsB,CAC3D,GAA8B,EAAO,CACrC,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,MAAM,CAC3C,GAAc,EAAO,CACrB,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,SAAS,CAC9C,GAAiB,EAAO,CACxB,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,eAAe,CACpD,GAAuB,EAAO,CAC9B,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,SAAS,CAC9C,GAAiB,EAAO,CACxB,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,WAAW,CAChD,GAAgB,EAAO,CACvB,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,YAAY,CACjD,GAAoB,EAAO,CAC3B,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,oBAAoB,CACzD,GAA4B,EAAO,CACnC,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,SAAS,CAC9C,GAA+B,EAAO,CACtC,EAAE,CAEN,EAAU,SAASA,EAAAA,EAAsB,gBAAgB,CACrD,GAA6B,EAAO,CACpC,EAAE,CACP,CAAC,CAEI,GACJ,EAAU,SAASA,EAAAA,EAAsB,eAAe,EAAI,EACxD,MAAM,GAAyB,EAAQ,EAAe,GAAG,CACzD,IAAA,GAEA,EAAyB,EAAE,CAG3B,GAAeG,GACnB,EAAU,KAAK,CAAC,CAAE,cAAe,EAAQ,KAAK,CAAE,WAAY,EAAM,CAAC,CACpE,CACK,GAAkB,OAAO,OAAO,EAAe,CAAC,QAAQ,CAAE,WAC9D,EAAU,SAASH,EAAAA,EAAsB,QAAQ,CAC7C,GACA,GAAa,SAAS,EAAM,CACjC,CAyjBD,GAvjBE,GAAgB,OAAS,GACzB,EAAU,SAASA,EAAAA,EAAsB,QAAQ,GAEjD,EAAO,YAAc,GAAgB,KAClC,CAAE,YAA0B,CAC3B,QACD,EACF,EAKD,GAAW,OAAS,GACpB,EAAU,SAASA,EAAAA,EAAsB,WAAW,GAEpD,EAAO,WAAa,GAAW,KAAK,CAAE,OAAM,gBAAiB,CAC3D,OACA,YACD,EAAE,EAKH,GACA,EAAU,SAASA,EAAAA,EAAsB,eAAe,GAExD,EAAO,mBAAqB,CAC1B,WAAY,CACV,KAAM,EAAe,cACrB,WAAY,EAAe,UAC5B,CACD,QAAS,EAAe,cAAc,SAAW,IAAA,GACjD,UAAW,EAAe,cAAc,WAAa,IAAA,GACrD,kBACE,EAAe,cAAc,mBAAqB,IAAA,GACpD,qBACE,EAAe,cAAc,sBAAwB,IAAA,GACvD,oBACE,EAAe,cAAc,qBAAuB,IAAA,GACtD,aAAc,EAAe,cAAc,cAAgB,IAAA,GAC3D,sBACE,EAAe,cAAc,uBAAyB,IAAA,GACxD,mBACE,EAAe,cAAc,oBAAsB,IAAA,GAErD,WAAY,EAAe,cAAc,YAAc,IAAA,GACvD,MAAQ,GAEJ,CACE,aAAc,GAAoB,cAAgB,IAAA,GAClD,UAAW,GAAoB,WAAa,IAAA,GAC5C,cAAe,GAAoB,eAAiB,IAAA,GACpD,OAAQ,GAAoB,OAC7B,CAND,IAAA,GAOJ,YAAa,EAA0B,IAAK,IAAgB,CAC1D,KAAM,EAAW,KACjB,YAAa,EAAW,aAAe,IAAA,GACvC,QAAS,EAAW,QAAQ,IAAK,IAAY,CAC3C,mBAAoB,EAAO,oBAAsB,IAAA,GACjD,QAAS,EAAO,SAAW,IAAA,GAC5B,EAAE,CACH,gBAAiB,EAAW,gBAC5B,cAAe,EAAW,cAC1B,SAAU,EAAW,SACrB,gBAAiB,EAAW,gBAC5B,UAAW,EAAW,UACtB,SAAU,EAAW,SAAS,IAAK,IAAa,CAC9C,aAAc,EAAQ,aACvB,EAAE,CACH,iBAAkB,EAAW,iBAAiB,IAAK,IAAa,CAC9D,aAAc,EAAQ,aACvB,EAAE,CACH,iBAAkB,EAAW,iBAC7B,iBAAkB,EAAW,iBAC9B,EAAE,CACJ,EAKD,GAAY,OAAS,GACrB,EAAU,SAASA,EAAAA,EAAsB,YAAY,GAErD,EAAO,YAAc,GAAY,KAC9B,CACC,QACA,kBACA,WACA,UACA,cACA,SACA,YACA,oBACA,YACA,WACA,aACA,sBACA,UACA,YACA,aACA,cACA,aACA,aACA,kBACA,oBACA,kBACA,UAAA,EACA,iBACsB,CACtB,QACA,MAAO,EAAgB,MACvB,SAAU,EAAS,KAChB,CACC,MAAA,EACA,OAAA,EACA,YACA,UAAA,EACA,aACA,kBAAA,MAC6B,CAC7B,MAAA,EACA,OAAA,EACA,UAAW,EAAU,KAClB,CACC,MAAA,EACA,OACA,UACA,cACA,YAAA,EACA,aACA,cACA,eACA,YACA,iBACA,gBACA,gBACA,kBACA,mBACA,mBACA,YACA,aACA,eACA,wBACA,iCACoC,CACpC,IAAM,EAAqB,EACvB,GAA4B,EAAa,CACzC,IAAA,GACJ,MAAO,CACL,MAAA,EACA,OACA,WAAY,EACZ,cACA,YAAA,EACA,cAAe,EACf,eAAgB,EAChB,gBACE,GACA,OAAO,KAAK,EAAmB,CAAC,OAAS,EACrC,CACE,OAAQ,EAAmB,OAC3B,KAAM,EAAmB,KACrB,CACE,mCACE,EAAmB,KAChB,6BACL,sBACE,EAAmB,KAAK,mBAC1B,sBAEE,uBACA,EAAmB,KACf,EAAmB,KAAK,mBACxB,IAAA,GACP,CACD,IAAA,GACJ,cAAe,EAAmB,WAC9B,CACE,iBACE,EAAmB,WAAW,cAChC,OACE,EAAmB,WAAW,OAAS,EAAE,EACzC,IAAK,IAA0B,CAC/B,mCACE,EAAK,6BACP,sBACE,EAAK,mBACP,sBAEE,uBAAwB,EACpB,EAAK,mBACL,IAAA,GACP,EAAE,CACJ,CACD,IAAA,GACL,CACD,IAAA,GACN,aAAc,EAAU,IAAK,GAA0B,CACrD,IAAM,EAAS,GAAyB,EAAM,CAC9C,MAAO,CACL,aAAc,EAAO,gBAAgB,YACrC,sBAAuB,EAAO,mBAC9B,sBAAuB,EAAO,mBAC/B,EACD,CACF,kBAAmB,EAAe,KAAK,CAAE,MAAA,KAAYI,EAAM,CAC3D,iBAAkB,GAAe,MACjC,iBAAkB,EAAc,KAAK,CAAE,YAAa,CAClD,QACD,EAAE,CACH,mBAAoB,EAAgB,KAAK,CAAE,WAAY,EAAM,CAC7D,qBAAsB,EACtB,qBAAsB,EACtB,aAAc,GAAa,IAAA,GAC3B,cAAe,GAAc,IAAA,GAC7B,gBAAiB,GAAc,KAC/B,0BAA2B,EAC3B,iCAAkC,EACnC,EAEJ,CACD,UAAWC,EAAU,KAAK,CAAE,WAAY,EAAM,CAC9C,qBAAsBC,EAAkB,KAAK,CAAE,WAAY,EAAM,CACjE,cAAe,EAChB,EACF,CACD,QAAS,GAAS,MAClB,cACA,SACA,UAAW,EAAU,KAAK,CAAE,WAAY,EAAM,CAC9C,qBAAsB,EAAkB,KAAK,CAAE,WAAY,EAAM,CACjE,UAAW,EAAU,KAAK,CAAE,WAAY,EAAM,CAC9C,OAAQ,EACR,SAAU,EACV,SAAU,EACV,oBAAqB,EACrB,WAAY,GAAW,IAAA,GACvB,aAAc,GAAa,IAAA,GAC3B,cAAe,GAAc,IAAA,GAC7B,eAAgB,GAAe,IAAA,GAC/B,cAAe,GAAc,IAAA,GAC7B,cAAe,GAAc,IAAA,GAC7B,qBAAsB,EAClB,CACE,KAAM,EAAkB,KACxB,gBAAiB,EAAkB,aACnC,QAAS,EAAkB,UAC5B,CACD,IAAA,GACJ,WACE,IAAoB,IAAA,IAAa,EAAgB,OAAS,EACtD,EAAsB,EAAgB,CACtC,IAAA,GACN,UAAWC,EAAU,KAClB,CAAE,eAAc,MAAA,EAAO,OAAM,WAAU,OAAM,cAAe,CAC3D,KAAM,EACN,MAAO,EACH,GAAG,EAAS,KAAK,IACjB,EACA,GAAG,EAAQ,KAAK,IAChBH,GAAS,GAAQ,GAAQ,GAC9B,EACF,CACD,KAAM,EAAW,KACd,CAAE,eAAc,MAAA,EAAO,OAAM,WAAU,OAAM,cAAe,CAC3D,KAAM,EACN,MAAO,EACH,GAAG,EAAS,KAAK,IACjB,EACA,GAAG,EAAQ,KAAK,IAChBA,GAAS,GAAQ,GAAQ,GAC9B,EACF,CACF,EACF,EAKD,GAAoB,OAAS,GAC7B,EAAU,SAASJ,EAAAA,EAAsB,oBAAoB,GAE7D,EAAO,wBAA0B,GAAoB,KAClD,CACC,QACA,cACA,WACA,SACA,SACA,UACA,WACA,aACA,YACA,wBAC8B,CAC9B,QACA,cACA,SAAU,EAAS,KAChB,CAAE,MAAA,EAAO,gBAAyC,CACjD,MAAA,EACA,UAAW,EAAU,KAClB,CACC,MAAA,EACA,OACA,UACA,cACA,YAAA,EACA,aACA,cACA,eACA,YACA,iBACA,gBACA,gBACA,mBACA,mBACA,YACA,aACA,eACA,wBACA,iCACoC,CACpC,IAAM,EAAqB,EACvB,GAA4B,EAAa,CACzC,IAAA,GACJ,MAAO,CACL,MAAA,EACA,OACA,WAAY,EACZ,cACA,YAAA,EACA,cAAe,EACf,eAAgB,EAChB,gBACE,GACA,OAAO,KAAK,EAAmB,CAAC,OAAS,EACrC,CACE,OAAQ,EAAmB,OAC3B,KAAM,EAAmB,KACrB,CACE,mCACE,EAAmB,KAChB,6BACL,sBACE,EAAmB,KAAK,mBAC1B,sBAEE,uBACA,EAAmB,KACf,EAAmB,KAAK,mBACxB,IAAA,GACP,CACD,IAAA,GACJ,cAAe,EAAmB,WAC9B,CACE,iBACE,EAAmB,WAAW,cAChC,OACE,EAAmB,WAAW,OAAS,EAAE,EACzC,IAAK,IAA0B,CAC/B,mCACE,EAAK,6BACP,sBACE,EAAK,mBACP,sBAEE,uBAAwB,EACpB,EAAK,mBACL,IAAA,GACP,EAAE,CACJ,CACD,IAAA,GACL,CACD,IAAA,GACN,aAAc,EAAU,IAAK,GAA0B,CACrD,IAAM,EAAS,GAAyB,EAAM,CAC9C,MAAO,CACL,aAAc,EAAO,gBAAgB,YACrC,kBAAmB,EAAO,gBAAgB,gBAC1C,qBACE,EAAO,gBAAgB,mBACzB,sBAAuB,EAAO,mBAC9B,sBAAuB,EAAO,mBAC/B,EACD,CACF,kBAAmB,EAAe,KAAK,CAAE,MAAA,KAAYI,EAAM,CAC3D,iBAAkB,GAAe,MACjC,iBAAkB,EAAc,KAAK,CAAE,YAAa,CAClD,QACD,EAAE,CACH,qBAAsB,EACtB,qBAAsB,EACtB,aAAc,GAAa,IAAA,GAC3B,cAAe,GAAc,IAAA,GAC7B,gBAAiB,GAAc,KAC/B,0BAA2B,EAC3B,iCAAkC,EACnC,EAEJ,CACF,EACF,CACD,SACA,SACA,QAAS,GAAS,MAClB,OAAQ,EACR,SAAU,EACV,aAAc,GAAa,IAAA,GAC3B,qBAAsB,EAClB,CACE,KAAM,EAAkB,KACxB,gBAAiB,EAAkB,aACnC,QAAS,EAAkB,UAC5B,CACD,IAAA,GACL,EACF,EAKD,GAAqB,OAAS,GAC9B,EAAU,SAASJ,EAAAA,EAAsB,gBAAgB,GAEzD,EAAO,oBAAsB,GAAqB,KAC/C,CACC,QACA,aACA,iBAAkB,CAAE,MAAO,GAC3B,OAAQ,CACN,SAAU,CAAE,MAAO,IAErB,UACA,qBACA,mBACA,wBACA,aAC+B,CAC/B,QACA,aACA,iBAAkB,EAClB,OAAQ,EACR,QAAS,GAAW,IAAA,GACpB,mBAAoB,GAAsB,IAAA,GAC1C,mBACA,wBACA,SACD,EACF,EAIC,EAAQ,OAAS,GAAK,EAAU,SAASA,EAAAA,EAAsB,QAAQ,GACzE,EAAO,QAAU,EAAQ,KACtB,CAAE,QAAO,cAA4B,CACpC,QACA,UACD,EACF,EAKD,EAAe,OAAS,GACxB,EAAU,SAASA,EAAAA,EAAsB,eAAe,GAExD,EAAO,mBAAqB,EAAe,KACxC,CAAE,QAAO,cAAmC,CAC3C,QACA,UACD,EACF,EAKD,EAAa,OAAS,GACtB,EAAU,SAASA,EAAAA,EAAsB,aAAa,GAEtD,EAAO,iBAAmB,EAAa,KACpC,CAAE,QAAO,cAAa,QAAA,MAAiC,CACtD,QACA,cACA,QAASQ,EAAQ,KAAK,CAAE,MAAA,KAAYJ,EAAM,CAC3C,EACF,EAIC,EAAM,OAAS,GAAK,EAAU,SAASJ,EAAAA,EAAsB,MAAM,GACrE,EAAO,MAAQ,EAAM,KAClB,CACC,OACA,cACA,gBACA,WACA,WACA,QACA,aACgB,CAChB,OACA,cACA,iBAAkB,GAAiB,IAAA,GACnC,YAAa,GAAY,IAAA,GACzB,YAAa,GAAY,IAAA,GACzB,MAAO,EAAM,KAAK,CAAE,WAAY,EAAM,CACtC,OAAQ,EAAO,KAAK,CAAE,KAAA,KAAWS,EAAK,CACvC,EACF,EAKD,EAAa,OAAS,GACtB,EAAU,SAAST,EAAAA,EAAsB,aAAa,GAEtD,EAAO,iBAAmB,EAAa,KACpC,CACC,OACA,QACA,SACA,kCACA,QAAA,MACuB,CACvB,OACA,MAAO,GAAO,eACd,SACA,kCACA,QAASU,EAAQ,KAAK,CAAE,KAAA,KAAWC,EAAK,CACzC,EACF,EAIC,GAAS,OAAS,IACpB,EAAO,SAAW,GAAS,KACxB,CAAE,QAAO,WAAU,sBAAoC,CACtD,MAAO,GAAO,eACd,QAAS,IAAW,IAAI,SAAS,eACjC,kBACD,EACF,EAIC,GAAS,OAAS,IACpB,EAAO,SAAW,GAAS,KACxB,CACC,KACA,iBACA,oBACA,cACA,mBACuB,CACvB,KACA,iBACA,cACA,kBAAmB,GAAqB,IAAA,GACxC,aAAc,EAAa,QACxB,EAAK,CAAE,SAAQ,WAAY,OAAO,OAAO,EAAK,EAAG,GAAS,EAAO,CAAC,CACnE,EAAE,CACH,CACF,EACF,EAIC,GAAe,OAAS,EAAG,CAC7B,IAAM,EAAgB,GAAe,GACrC,EAAO,kBAAoB,CACzB,WAAY,EAAc,WAC1B,yBAA0B,EAAc,yBACxC,aAAc,EAAc,aAC5B,yBAA0B,EAAc,yBACxC,YAAa,EAAc,YAC3B,cAAe,EAAc,cAC7B,mBAAoB,EAAc,mBAClC,sBAAuB,EAAc,sBACrC,yBAA0B,EAAc,yBACxC,QAAS,EAAc,QACvB,cAAe,EAAc,cAC7B,2BAA4B,EAAc,2BAC1C,aAAc,EAAc,cAAgB,IAAA,GAC5C,aAAc,EAAc,cAAgB,IAAA,GAC5C,uBAAwB,EAAc,uBACtC,qBAAsB,EAAc,qBACpC,+BACE,EAAc,+BAChB,MAAO,EAAc,MACtB,CAknBH,GA7mBE,EAAiB,OAAS,GAC1B,EAAU,SAASX,EAAAA,EAAsB,iBAAiB,GAE1D,EAAO,qBAAuB,EAAiB,KAC5C,CACC,QACA,cACA,UACA,qBACA,yBACA,4BACA,6BACA,sBAC0B,CAC1B,QACA,YAAa,GAAe,IAAA,GAC5B,QAAS,GAAW,IAAA,GACpB,mBAAoB,GAAsB,IAAA,GAC1C,uBAAwB,GAA0B,IAAA,GAClD,0BAA2B,GAA6B,IAAA,GACxD,2BAA4B,GAA8B,IAAA,GAC1D,WACE,IAAoB,IAAA,IAAa,EAAgB,OAAS,EACtD,EAAsB,EAAgB,CACtC,IAAA,GACP,EACF,EAKD,EAAqB,OAAS,GAC9B,EAAU,SAASA,EAAAA,EAAsB,qBAAqB,GAE9D,EAAO,yBAA2B,EAAqB,KACpD,CACC,QACA,cACA,yBACA,kBACA,iBACA,kBACA,gBACA,kBACA,qCACA,uCACA,kBACA,UAAA,EACA,aAAA,EACA,MAAA,EACA,SACA,iCACA,oBACA,qBAC8B,CAC9B,QACA,cACA,uBAAwB,GAA0B,IAAA,GAClD,gBACE,EAAgB,OAAS,EAAI,EAAkB,IAAA,GACjD,eACE,EAAe,OAAS,EAAI,GAAc,EAAe,CAAG,IAAA,GAC9D,gBACE,EAAgB,OAAS,EACrB,GAAc,EAAgB,CAC9B,IAAA,GACN,gBACA,gBACE,IAAkBY,EAAAA,cAAc,aAC5B,EACA,IAAA,GACN,mCACE,GAAsC,IAAA,GACxC,uCACA,WACE,IAAoB,IAAA,IAAa,EAAgB,OAAS,EACtD,EAAsB,EAAgB,CACtC,IAAA,GACN,eACEC,EAAU,OAAS,EACfA,EAAU,KAAK,CAAE,MAAA,KAAYT,EAAM,CACnC,IAAA,GACN,iBACEU,EAAa,OAAS,EAClBA,EAAa,KAAK,CAAE,UAAW,EAAK,CACpC,IAAA,GACN,UAAWC,EAAM,OAAS,EAAIA,EAAM,KAAK,CAAE,UAAW,EAAK,CAAG,IAAA,GAC9D,YACE,EAAO,OAAS,EAAI,EAAO,KAAK,CAAE,WAAY,EAAM,CAAG,IAAA,GACzD,sBACE,EAA+B,OAAS,EACpC,EAA+B,KAAK,CAAE,OAAM,cAAe,CACzD,UACA,GAAI,EAAO,CAAE,OAAM,CAAG,EAAE,CACzB,EAAE,CACH,IAAA,GACN,kBACE,EAAkB,OAAS,EACvB,EAAkB,KAAK,CAAE,OAAM,eAAgB,CAC7C,WACA,GAAI,EAAO,CAAE,OAAM,CAAG,EAAE,CACzB,EAAE,CACH,IAAA,GACN,eACE,EAAe,OAAS,EACpB,EAAe,KAAK,CAAE,MAAA,KAAYX,EAAM,CACxC,IAAA,GACP,EACF,EAIC,EAAQ,OAAS,GAAK,EAAU,SAASJ,EAAAA,EAAsB,QAAQ,GACzE,EAAO,QAAU,EAAQ,KACtB,CACC,OACA,yBACA,uBACA,iBACA,aACA,wBACA,oBACkB,CAClB,OACA,GAAI,IAASgB,EAAAA,cAAc,QACvB,CACE,yBACA,uBACD,CACD,EAAE,CACN,iBACA,gBACA,wBACA,WAAY,EAAW,OAAS,EAAI,EAAa,IAAA,GAClD,EACF,EAKD,EAAY,OAAS,GACrB,EAAU,SAAShB,EAAAA,EAAsB,YAAY,GAErD,EAAO,YAAc,EAAY,KAC9B,CACC,OACA,OACA,QACA,gBACA,0BACA,mBACA,cACA,eACA,aAAA,EACA,qBACA,eACA,gCACsB,CACtB,OACA,OACA,QACA,cAAe,EAAc,OAAS,EAAI,EAAgB,IAAA,GAC1D,wBACE,EAAwB,OAAS,EAC7B,EACA,IAAA,GACN,mBACA,YAAa,GAAe,IAAA,GAC5B,aACEc,EAAa,OAAS,EAClBA,EAAa,KAAK,CAAE,KAAA,KAAWH,EAAK,CACpC,IAAA,GACN,aAAc,GAAc,eAC5B,mBAAoB,GAAoB,eACxC,eACA,4BACD,EACF,EAIC,EAAO,OAAS,GAAK,EAAU,SAASX,EAAAA,EAAsB,OAAO,GACvE,EAAO,OAAS,EAAO,KACpB,CACC,OACA,UACA,cACA,eACA,yBACA,mBACA,SACA,qBACA,MAAA,EACA,SACA,eAAA,EACA,WAAA,MACiB,CACjB,OACA,UACA,YAAa,GAAe,IAAA,GAC5B,eACA,yBACA,mBACA,OAAQ,GAAQ,MAChB,uBAAwB,CACtB,KAAM,EAAmB,KACzB,OAAQ,EAAmB,OAC5B,CACD,MACEe,GAASA,EAAM,OAAS,EAAIA,EAAM,KAAK,CAAE,KAAA,KAAWN,EAAK,CAAG,IAAA,GAC9D,OACE,GAAU,EAAO,OAAS,EACtB,EAAO,KAAK,CAAE,WAAY,EAAM,CAChC,IAAA,GACN,kBACEQ,GAAkBA,EAAe,OAAS,EACtCA,EAAe,KAAK,CAAE,KAAA,KAAWR,EAAK,CACtC,IAAA,GACN,cACES,GAAcA,EAAW,OAAS,EAC9BA,EAAW,KAAK,CAAE,KAAA,KAAWT,EAAK,CAClC,IAAA,GACP,EACF,EAKD,EAAY,OAAS,GACrB,EAAU,SAAST,EAAAA,EAAsB,YAAY,GAErD,EAAO,gBAAkB,EAAY,KAClC,CACC,MAAA,EACA,QACA,gCAAiC,CAAC,GAClC,UACA,WACA,WACA,cACA,QACA,OACA,QACA,OACA,sBACsB,CACtB,MAAOe,EAAM,KAAK,CAAE,UAAW,EAAK,CACpC,MAAO,EAAM,KAAK,CAAE,WAAY,EAAM,CACtC,QAAS,GAAW,IAAA,GACpB,QACA,QACA,iCACA,YAAa,EAAY,KAAK,CAAE,MAAA,KAAYX,EAAM,CAClD,OACA,SAAU,GAAY,IAAA,GACtB,WACA,OACA,WACE,IAAoB,IAAA,IAAa,EAAgB,OAAS,EACtD,EAAsB,EAAgB,CACtC,IAAA,GACP,EACF,EAKD,GAAsB,OAAS,GAC/B,EAAU,SAASJ,EAAAA,EAAsB,sBAAsB,GAE/D,EAAO,2BAA6B,GAAsB,KACvD,CACC,QACA,cACA,SACA,kBACgC,CAChC,QACA,YAAa,GAAe,IAAA,GAC5B,SACA,cACD,EACF,EAKD,EAAe,OAAS,GACxB,EAAU,SAASA,EAAAA,EAAsB,eAAe,GAExD,EAAO,mBAAqB,EAAe,KACxC,CAAE,OAAM,cAAa,iBAAsC,CAC1D,OACA,cACA,WAAY,KAAK,UAAU,EAAW,CACvC,EACF,EAKD,EAAW,OAAS,GACpB,EAAU,SAASA,EAAAA,EAAsB,WAAW,GAEpD,EAAO,eAAiB,EAAW,KAChC,CAAE,OAAM,cAAa,SAAQ,OAAM,cAA+B,CACjE,OACA,cACA,SACA,OACA,UACD,EACF,EAIC,EAAQ,OAAS,GAAK,EAAU,SAASA,EAAAA,EAAsB,QAAQ,GACzE,EAAO,QAAU,EAAQ,KACtB,CACC,QACA,cACA,8BACA,cACA,eACA,UACA,qBACA,yBACA,aACA,iBACA,MAAA,EACA,SACA,sBACkB,CAClB,QACA,YAAa,GAAe,IAAA,GAC5B,4BAA6B,GAA+B,IAAA,GAC5D,YAAa,GAAe,IAAA,GAC5B,aAAc,GAAgB,IAAA,GAC9B,QAAS,GAAW,IAAA,GACpB,mBAAoB,GAAsB,IAAA,GAC1C,uBAAwB,GAA0B,IAAA,GAClD,WAAY,GAAc,IAAA,GAC1B,eAAgB,GAAgB,MAChC,MACEe,GAASA,EAAM,OAAS,EAAIA,EAAM,KAAK,CAAE,UAAW,EAAK,CAAG,IAAA,GAC9D,OACE,GAAU,EAAO,OAAS,EACtB,EAAO,KAAK,CAAE,WAAY,EAAM,CAChC,IAAA,GACN,WACE,IAAoB,IAAA,IAAa,EAAgB,OAAS,EACtD,EAAsB,EAAgB,CACtC,IAAA,GACP,EACF,EAKD,EAAe,OAAS,GACxB,EAAU,SAASf,EAAAA,EAAsB,eAAe,GAExD,EAAO,mBAAqB,EAAe,KACxC,CACC,OACA,WACA,cACA,QACA,SACA,MAAA,EACA,sBACwB,CACxB,OACA,WACA,YAAa,GAAe,IAAA,GAC5B,MAAO,GAAS,IAAA,GAChB,OACE,GAAU,EAAO,OAAS,EACtB,EAAO,KAAK,CAAE,WAAY,EAAM,CAChC,IAAA,GACN,MACEe,GAASA,EAAM,OAAS,EAAIA,EAAM,KAAK,CAAE,KAAA,KAAWN,EAAK,CAAG,IAAA,GAC9D,WACE,IAAoB,IAAA,IAAa,EAAgB,OAAS,EACtD,EAAsB,EAAgB,CACtC,IAAA,GACP,EACF,EAKD,GAAmB,OAAS,GAC5B,EAAU,SAAST,EAAAA,EAAsB,mBAAmB,GAE5D,EAAO,uBAAyB,GAAmB,KAChD,CACC,OACA,UACA,cACA,SACA,MAAA,EACA,sBAC6B,CAC7B,OACA,UACA,YAAa,GAAe,IAAA,GAC5B,OACE,GAAU,EAAO,OAAS,EACtB,EAAO,KAAK,CAAE,WAAY,EAAM,CAChC,IAAA,GACN,MACEe,GAASA,EAAM,OAAS,EAAIA,EAAM,KAAK,CAAE,KAAA,KAAWN,EAAK,CAAG,IAAA,GAC9D,WACE,IAAoB,IAAA,IAAa,EAAgB,OAAS,EACtD,EAAsB,EAAgB,CACtC,IAAA,GACP,EACF,EAKD,EAAU,OAAS,GACnB,EAAU,SAAST,EAAAA,EAAsB,UAAU,GAEnD,EAAO,cAAgB,EAAU,KAC9B,CACC,QACA,OACA,cACA,eACA,UACA,SACA,SACA,MAAA,EACA,sBACoB,CACpB,QACA,OACA,YAAa,GAAe,IAAA,GAC5B,iBAAkB,EAClB,SACA,QAAS,GAAS,gBAClB,OAAQ,EAAO,KAAK,CAAE,WAAY,EAAM,CACxC,MAAOe,EAAM,KAAK,CAAE,UAAW,EAAK,CACpC,WACE,IAAoB,IAAA,IAAa,EAAgB,OAAS,EACtD,EAAsB,EAAgB,CACtC,IAAA,GACP,EACF,EAIC,EAAQ,OAAS,GAAK,EAAU,SAASf,EAAAA,EAAsB,QAAQ,GACzE,EAAO,QAAU,EAAQ,KACtB,CACC,OACA,UACA,cACA,mBACA,UACA,SACA,SACA,MAAA,EACA,sBACkB,CAClB,OACA,UACA,YAAa,GAAe,IAAA,GAC5B,mBACA,SACA,QAAS,GAAS,gBAClB,OAAQ,EAAO,KAAK,CAAE,WAAY,EAAM,CACxC,MAAOe,EAAM,KAAK,CAAE,KAAA,KAAWN,EAAK,CACpC,WACE,IAAoB,IAAA,IAAa,EAAgB,OAAS,EACtD,EAAsB,EAAgB,CACtC,IAAA,GACP,EACF,EAKD,EAAW,OAAS,GACpB,EAAU,SAAST,EAAAA,EAAsB,WAAW,GAEpD,EAAO,WAAa,EAAW,KAC5B,CACC,cACA,OACA,OACA,SACA,YAAY,EAAE,KACO,CACrB,YAAa,GAAe,IAAA,GAC5B,UAAW,EACX,OACA,OACA,OAAQ,EAAO,KAAK,CAAE,KAAA,EAAM,QAAO,YAAA,MAAmB,CACpD,KAAA,EACA,MAAO,GAAS,IAAA,GAChB,YAAA,EACD,EAAE,CACJ,EACF,EAIC,GAAS,OAAS,IACpB,EAAO,SAAW,GAAS,KACxB,CACC,OACA,cACA,eACA,iBACA,eACA,uBACA,WACA,eACA,gBACA,YACA,SACA,sBACA,YACqB,CACrB,OACA,QACA,YAAa,GAAe,IAAA,GAC5B,eACA,kBAAmB,EACnB,eACA,0BAA2B,EAC3B,yBAA0B,EAC1B,YAAa,EACb,gBAAiB,EACjB,kBAAmB,EAAc,OAAS,EAAI,EAAgB,IAAA,GAC9D,aAAc,GAAa,IAAA,GAC3B,oBAAqB,EAAO,KACzB,CACC,MAAA,EACA,OACA,qBACA,uBACA,oBAAA,EACA,6BACK,CACL,MAAOI,EAAM,eACb,OACA,YAAa,EAAmB,eAChC,wBAAyB,EACzB,yBAA0Be,EAC1B,GAAI,EAAuB,OAAS,EAChC,CACE,QAAS,EAAuB,KAAK,CAAE,MAAA,EAAO,WAAY,CACxD,MAAOf,EAAM,eACb,OACD,EAAE,CACJ,CACD,EAAE,CACP,EACF,CACF,EACF,EAKD,EAAY,SAAW,GACvB,EAAU,OAAS,GACnB,EAAU,SAASJ,EAAAA,EAAsB,UAAU,GAEnD,EAAO,UAAY,EAAU,KAAK,CAAE,YAAa,CAAE,QAAO,EAAE,EAK5D,EAAU,OAAS,GACnB,EAAU,SAASA,EAAAA,EAAsB,UAAU,GAEnD,EAAO,UAAY,EAAU,KAC1B,CACC,QACA,MACA,OACA,kBACA,YAAA,EACA,QAAA,EACA,YACA,aAAA,EACA,qBACA,mBACA,0BACA,eACA,iBACoB,CACpB,QACA,IAAK,GAAO,IAAA,GACZ,OACA,mBAAoB,GAAiB,KACrC,qBAAsBoB,EAAY,KAAK,CAAE,UAAW,EAAK,CACzD,kBACE,OAAO,OAAOJ,EAAAA,cAAc,CAAC,SAAWN,EAAQ,OAC5C,IAAA,GACAA,EACN,UAAW,GAAa,IAAA,GACxB,iBAAkB,GAAoB,IAAA,GACtC,mBAAoB,SAAS,EAAoB,GAAG,CACpD,wBAAyB,GAA2B,IAAA,GACpD,aACE,GAAgB,EAAa,OAAS,EAAI,EAAe,IAAA,GAC3D,WACE,GAAc,EAAW,OAAS,EAAI,EAAa,IAAA,GACrD,gBAAiBI,EAAa,KAAK,CAAE,KAAA,KAAWH,EAAK,CACtD,EACF,EAKD,EAAU,OAAS,GACnB,EAAU,SAASX,EAAAA,EAAsB,UAAU,CACnD,CACA,IAAM,EAAsBqB,EAAAA,EAAM,EAAc,OAAO,CACvD,EAAO,cAAgB,EAAU,KAC9B,CACC,CACE,QACA,cACA,MACA,OACA,YACA,UACA,qBACA,YAAA,EACA,qBACA,SACA,UACA,qBACA,MAAA,EACA,mBACA,SACA,kCACA,6BACA,iDACA,uCACA,2BACA,UACA,kBACA,eACA,iBAAA,GAEF,MACoB,CACpB,QACA,cACA,gBAAiB,EACjB,aAAc,GAAa,IAAA,GAC3B,IAAK,GAAO,IAAA,GACZ,gBAAiB,EAAQ,IAAI,MAC7B,gBAAiBD,EACd,QAAQ,CAAE,iBAAkB,EAAY,CACxC,KAAK,CAAE,UAAW,EAAK,CAC1B,GAAI,EAAmB,OAAS,EAC5B,CACE,wBAAyB,EAAmB,KACzC,CAAE,MAAA,KAAYhB,EAChB,CACF,CACD,EAAE,CACN,GAAI,EAAO,OAAS,EAChB,CAAE,OAAQ,EAAO,KAAK,CAAE,WAAY,EAAM,CAAE,CAC5C,EAAE,CACN,GAAIW,EAAM,OAAS,EAAI,CAAE,MAAOA,EAAM,KAAK,CAAE,UAAW,EAAK,CAAE,CAAG,EAAE,CACpE,GAAI,EAAa,OAAS,EACtB,CAAE,aAAc,EAAa,KAAK,CAAE,MAAA,KAAYX,EAAM,CAAE,CACxD,EAAE,CACN,GAAIkB,EAAiB,OAAS,EAC1B,CACE,iBAAkBA,EAAiB,KAAK,CAAE,MAAA,KAAYlB,EAAM,CAC7D,CACD,EAAE,CACN,QAAS,GAAW,IAAA,GACpB,mBAAoB,GAAsB,IAAA,GAC1C,SAAU,CAAC,EACX,gBACE,EAAiB,OAAS,EACtB,GACE,EAAiB,KAAK,CAAE,KAAA,KAAWO,EAAK,CACxC,EACD,CACD,IAAA,GACN,GAAI,EAAQ,oBACR,CACE,iBAAkB,CAChB,uBAAwB,GAAsB,IAAA,GAC9C,iBAAkB,EAClB,YAAa,EACb,iCACE,EACF,uBAAwB,EACxB,8BAA+B,EAChC,CACF,CACD,EAAE,CACN,WACE,IAAoB,IAAA,IAAa,EAAgB,OAAS,EACtD,EAAsB,EAAgB,CACtC,IAAA,GAEN,WAAY,EACT,IACE,IAA+B,CAC9B,IAAK,EAAU,KACf,MAAO,EAAU,OAAO,eACxB,YAAa,EAAU,aAAa,eACpC,OAAQ,EAAU,OAAO,KAAK,CAAE,WAAY,EAAM,CAClD,MAAO,EAAU,MAAM,KAAK,CAAE,UAAW,EAAK,CAC9C,GAAI,EAAU,KAAK,OAAS,EAAI,CAAE,KAAM,EAAU,KAAM,CAAG,EAAE,CAC7D,GAAI,EAAU,gBAAgB,MAC1B,CACE,sBACE,EAAU,eAAe,MAAM,eAClC,CACD,EAAE,CACN,GAAI,EAAU,qBAAqB,OAAS,EACxC,CACE,yBAA0BY,GACxBF,EAAAA,EAAM,EAAU,qBAAsB,cAAc,CACnD,GACC,EAAyB,gBACzB,EAAyB,OACzB,IAAA,GACH,CACF,CACD,EAAE,CACN,GAAI,EAAU,cAAc,OAAS,EACjC,CACE,OAAQ,EAAU,cACf,IACE,IAAuB,CACtB,IAAK,EAAM,KACX,YAAa,EAAM,YACnB,SAAU,EAAM,SAChB,WAAY,EAAM,WAClB,GAAI,GACJ,EAAM,uBACF,CACE,qBACE,EAAM,uBACH,OACE,GAAU,EAAM,SAAW,UAC7B,CACA,IAAK,IAAW,CACf,SAAU,CACR,KAAM,EAAM,SAAS,KACrB,SAAU,EAAM,SAAS,SAC1B,CACD,OAAQ,EAAM,OACd,WAAY,EAAM,WAClB,kBACE,EAAM,mBAAqB,IAAA,GAC9B,EAAE,CACR,CACD,EAAE,CACN,oCACE,EAAM,+BACR,oCACE,EAAM,+BACR,WACE,EAAM,kBAAoB,IAAA,IAC1B,EAAM,gBAAgB,OAAS,EAC3B,EAAsB,EAAM,gBAAgB,CAC5C,IAAA,GACP,EACF,CACA,MAAM,EAAG,IAAM,EAAE,IAAI,cAAc,EAAE,IAAI,CAAC,CAC9C,CACD,EAAE,CACN,kBAAmB,EAAU,eAC1B,QAAQ,CAAE,YAAa,EAAO,CAC9B,KAAK,CAAE,KAAA,KAAWV,EAAK,CAC3B,EACF,CACA,MAAM,EAAG,IACR,CAAC,GAAI,EAAE,MAAQ,EAAE,CAAG,EAAE,IAAI,CACvB,KAAK,IAAI,CACT,cAAc,CAAC,GAAI,EAAE,MAAQ,EAAE,CAAG,EAAE,IAAI,CAAC,KAAK,IAAI,CAAC,CACvD,CACJ,EACF,CAEH,OAAO,ECjpDT,eAAsB,GACpB,EACA,EACiB,CACjB,GAAM,CACJ,gBAAiB,CAAE,cACjB,MAAM,EASP,EAAQ,GAAmB,CAC5B,MAAO,CACL,GAAG,EACH,kBAAmB,EAAM,kBAAkB,KACxC,CAAE,UAAS,GAAG,MAAY,CACzB,GAAG,EACH,QAAS,EACV,EACF,CACF,CACF,CAAC,CACF,OAAO,EAAU,GC7FnB,eAAsB,GACpB,EACA,EACe,CACf,MAAM,EAAmB,EAAQ,GAAwB,CACvD,kBAAmB,EACpB,CAAC,CCQJ,eAAsB,GACpB,EACA,EACe,CACf,MAAM,EAAmB,EAAQ,GAAyB,CACxD,QACD,CAAC,CCpBJ,MAAM,GAAiC,CACrC,GAAG,OAAO,OAAOa,EAAAA,eAAe,CAChC,GAAG,OAAO,OAAOC,EAAAA,0BAA0B,CAC5C,CAQD,eAAsB,GACpB,EACA,CACE,SACA,WACA,cAAc,IASD,CACf,MAAM,EAAmB,EAAQ,GAAe,CAC9C,MAAO,CACL,GAAI,EACJ,uBAAwB,EAAO,uBAC/B,qBAAsB,EAAO,qBAC7B,eAAgB,EAAO,eACvB,cAAe,EAAO,cACtB,cACA,WAAY,EAAO,gBACfC,EAAW,GAAgC,EAAO,gBAAgB,CAClE,EAAO,WACX,sBAAuB,EAAO,sBAC/B,CACF,CAAC,CC1BJ,eAAsB,GACpB,EACA,EACqD,CAQrD,GAAM,CAAE,2BAAA,GAA+B,MAAM,EAM1C,EAAQ,GAA+B,CACxC,MAdY,CACZ,MAAO,EAAqB,MAC5B,YAAa,EAAqB,aAAe,GACjD,OAAQ,EAAqB,QAAU,GACvC,YAAa,EAAqB,YACnC,CAUA,CAAC,CACF,OAAOC,EAA2B,QAUpC,eAAsB,GACpB,EACA,EACA,EACe,CACf,MAAM,EAAmB,EAAQ,GAA+B,CAC9D,MAAO,CACL,GAAI,EACJ,MAAO,EAAM,MACb,YAAa,EAAM,YACnB,OAAQ,EAAM,OACd,YAAa,EAAM,YACpB,CACF,CAAC,CAUJ,eAAsB,GACpB,EACA,EACkB,CAClB,IAAI,EAAmB,GAEvB,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,YAAY,EAAO,OAAO,8BAA8B,CACxE,CAQD,IAAM,EAA6DC,EAAAA,EAL7B,MAAM,GAC1C,EACD,CAKC,QACD,CAgDD,OAxCA,MAAM,EALiB,EAAO,OAC3B,GAAU,CAAC,EAAkB,EAAM,OACrC,CAG+B,KAAO,IAAU,CAC/C,GAAI,CACF,MAAM,GAA2B,EAAQ,EAAM,CAC/C,EAAA,EAAO,KACL,EAAA,QAAO,MACL,gDAAgD,EAAM,MAAM,IAC7D,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,4CAA4C,EAAM,MAAM,OAAO,EAAI,UACpE,CACF,GAEH,CAMF,MAAM,EAHsB,EACzB,IAAK,GAAU,CAAC,EAAO,EAAkB,EAAM,QAAQ,GAAG,CAAC,CAC3D,OAAQ,GAAgD,CAAC,CAAC,EAAE,GAAG,CAC7B,MAAO,CAAC,EAAO,KAAkB,CACpE,GAAI,CACF,MAAM,GAA2B,EAAQ,EAAO,EAAa,CAC7D,EAAA,EAAO,KACL,EAAA,QAAO,MACL,+CAA+C,EAAM,MAAM,IAC5D,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,0CAA0C,EAAM,MAAM,OAAO,EAAI,UAClE,CACF,GAEH,CAEK,CAAC,ECxHV,eAAsB,GACpB,EACA,EACA,EAGA,EAAoD,EAAE,CACvC,CAUf,MAAM,EADUC,EAAM,EAAa,IAAI,CACd,KAAO,IAAkB,CAChD,MAAM,EAAmB,EAAQ,GAAqB,CACpD,MAAO,EAAc,IAAK,IAAgB,CACxC,MAAO,EAAW,MAClB,KAAM,EAAW,KACjB,iBAAkB,EAAW,SAC7B,QAAS,EAAW,QACpB,+BACE,EAAW,+BACb,SAAU,EAAW,SACrB,MAAO,EAAW,MAClB,KAAM,EAAW,KACjB,oBAAqB,EAAW,MAChC,mBAAoB,EAAW,MAC/B,IAAI,EAAW,WACX,EAMC,EAEL,cAAe,EAAW,YAAY,IACnC,GAAoB,EAA4B,GAAiB,GACnE,CACF,EAAE,CACJ,CAAC,EACF,CAWJ,eAAsB,GACpB,EACA,EACA,EACA,EAEI,EAAE,CACS,CACf,IAAM,EAAgB,GAAwB,CAC5C,IAAM,EAAW,EAAoB,GACrC,GAAI,CAAC,EACH,MAAU,MAAM,kBAAkB,EAAI,mBAAmB,CAE3D,OAAO,EAAS,IAElB,MAAM,EAAmB,EAAQ,GAAqB,CACpD,MAAO,CACL,IAAK,CAAC,EAAa,CACnB,MAAO,EAAM,MACb,iBAAkB,EAAM,SACxB,QAAS,EAAM,QACf,SAAU,EAAM,SAChB,+BAAgC,EAAM,+BACtC,MAAO,EAAM,MACb,KAAM,EAAM,KACZ,oBAAqB,EAAM,MAC3B,mBAAoB,EAAM,MAC1B,GAAI,EAAM,WACN,CACE,WAAY,EAAM,WAAW,KAAK,CAAE,MAAK,aAAc,CACrD,eAAgB,EAAa,EAAI,CACjC,oBAAqB,EACtB,EAAE,CACJ,CACD,EAAE,CACP,CACF,CAAC,CASJ,SAAS,GAAuB,CAC9B,QACA,eACoD,CACpD,MAAO,GAAG,EAAM,GAAG,EAChB,IAAK,GAAM,EAAE,MAAM,CACnB,MAAM,CACN,KAAK,IAAI,GASd,SAAS,GAA4B,CACnC,QACA,eACyD,CACzD,MAAO,GAAG,EAAM,GAAG,EAAY,MAAM,CAAC,KAAK,IAAI,GAUjD,eAAsB,GACpB,EACA,EACkB,CAClB,IAAI,EAAmB,GAEvB,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,YAAY,EAAO,OAAO,kBAAkB,CAAC,CAGxE,IAAM,EAAgB,EAAO,KAC1B,GAAU,EAAM,YAAc,EAAM,WAAW,OAAS,EAC1D,CAGK,CAAC,EAAqB,EAA+B,GACzD,MAAM,QAAQ,IAAI,CAChB,GAAoB,EAAO,CAC3B,GAA8B,EAAO,CACrC,EAAgB,GAAmB,EAAO,CAAG,EAAE,CAChD,CAAC,CAGE,EACJC,EAAAA,EAAM,EAA+B,QAAQ,CACzC,EAAmDA,EAAAA,EACvD,EACA,GACD,CACK,EAAsBA,EAAAA,EAAM,EAAe,OAAO,CAClD,EAAkDA,EAAAA,EACtD,EAAoB,OAAQ,GAAM,CAAC,CAAC,EAAE,gCAAgC,EACrE,CAAE,qCAAsC,EAAgC,GAC1E,CAGK,EAAqBC,EACzB,EAAO,IAAK,GAAU,EAAM,YAAY,CAAC,MAAM,CAChD,CAAC,OAAQ,GAAoB,CAAC,EAA4B,GAAiB,CAC5E,GAAI,EAAmB,OAAS,EAQ9B,OAPA,EAAA,EAAO,KACL,EAAA,QAAO,IACL,qCAAqC,EAAmB,KACtD,OACD,CAAC,+BACH,CACF,CACM,GAIT,IAAM,EAAiB,EAAO,OAC3B,GACC,CAAC,EAAkB,GAA4B,EAAM,GACrD,CAAC,EAAiB,EAAM,gCAC3B,CAGD,GAAI,EAAe,OAAS,EAC1B,GAAI,CACF,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,aAAa,EAAe,OAAO,kBAAkB,CACrE,CACD,MAAM,GACJ,EACA,EACA,EACA,EACD,CACD,EAAA,EAAO,KACL,EAAA,QAAO,MACL,yBAAyB,EAAe,OAAO,gBAChD,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IAAI,oCAAoC,EAAI,UAAU,CAC9D,CA4BL,OAhBA,MAAM,EAPsB,EACzB,IAAK,GAAU,CACd,EACA,EAAkB,GAA4B,EAAM,GAAG,IACrD,EAAiB,EAAM,iCAAkC,GAC5D,CAAC,CACD,OAAQ,GAAsC,CAAC,CAAC,EAAE,GAAG,CACnB,MAAO,CAAC,EAAO,KAAkB,CACpE,GAAI,CACF,MAAM,GAAiB,EAAQ,EAAO,EAAc,EAAoB,CACxE,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,oCAAoC,EAAM,MAAM,IAAI,CAClE,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,+BAA+B,EAAM,MAAM,OAAO,EAAI,UACvD,CACF,GAEH,CAEK,CAAC,EClPV,eAAsB,GACpB,EACA,EACoD,CAYpD,GAAM,CAAE,gBAAA,GAAoB,MAAM,EAM/B,EAAQ,GAAmB,CAC5B,MAlBY,CACZ,KAAM,EAAU,KAChB,YAAa,EAAU,YACvB,OAAQ,EAAU,OAClB,KAAM,EAAU,KAChB,QAAS,EAAU,QACnB,eAAgB,IAAI,KACpB,SAAU,EAAE,CAEb,CAUA,CAAC,CACF,OAAOC,EAAgB,UASzB,eAAsB,GACpB,EACA,EACe,CACf,MAAM,EAAmB,EAAQ,GAAoB,CACnD,MAAO,CACL,WAAY,EAAiB,KAAK,CAAC,EAAW,MAAS,CACrD,KACA,KAAM,EAAU,KAChB,YAAa,EAAU,YACvB,OAAQ,EAAU,OAClB,KAAM,EAAU,KAChB,QAAS,EAAU,QACpB,EAAE,CACJ,CACF,CAAC,CAUJ,eAAsB,GACpB,EACA,EACkB,CAElB,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,YAAY,EAAO,OAAO,kBAAkB,CAAC,CAExE,IAAI,EAAmB,GAMjB,EAEFC,EAAAA,EALuB,MAAM,GAAmB,EAAO,CAK7B,OAAO,CAMrC,MAAM,EAHgB,EAAO,OAAQ,GAAU,CAAC,EAAgB,EAAM,MAAM,CAG7C,KAAO,IAAc,CAClD,GAAI,CACF,IAAM,EAAe,MAAM,GAAgB,EAAQ,EAAU,CAC7D,EAAgB,EAAa,MAAQ,EACrC,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,mCAAmC,EAAU,KAAK,IAAI,CACpE,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,8BAA8B,EAAU,KAAK,OAAO,EAAI,UACzD,CACF,GAEH,CAGF,GAAI,CACF,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,aAAa,EAAO,OAAO,gBAAgB,CAAC,CACvE,MAAM,GACJ,EACA,EAAO,IAAK,GAAU,CAAC,EAAO,EAAgB,EAAM,MAAM,GAAG,CAAC,CAC/D,CACD,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,wBAAwB,EAAO,OAAO,gBAAgB,CACpE,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,mBAAmB,EAAO,OAAO,mBAAmB,EAAI,UACzD,CACF,CAGH,MAAO,CAAC,EChHV,eAAsB,GACpB,EACA,EAC6C,CAS7C,GAAM,CAAE,oBAAA,GAAwB,MAAM,EAMnC,EAAQ,GAAuB,CAChC,MAfY,CACZ,KAAM,EAAc,KACpB,YAAa,EAAc,YAC3B,WAAY,EAAc,WAC1B,SAAU,EAAE,CAEb,CAUA,CAAC,CACF,OAAOC,EAAoB,cAS7B,eAAsB,GACpB,EACA,EACe,CACf,MAAM,EAAmB,EAAQ,GAAwB,CACvD,MAAO,CACL,eAAgB,EAAqB,KAAK,CAAC,EAAe,MAAS,CACjE,KACA,KAAM,EAAc,KACpB,YAAa,EAAc,YAC3B,WAAY,EAAc,WAC3B,EAAE,CACJ,CACF,CAAC,CAUJ,eAAsB,GACpB,EACA,EACkB,CAElB,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,YAAY,EAAO,OAAO,sBAAsB,CAAC,CAE5E,IAAI,EAAmB,GAMjB,EAEFC,EAAAA,EAL2B,MAAM,GAAuB,EAAO,CAKjC,OAAO,CAQzC,MAAM,EALoB,EAAO,OAC9B,GAAU,CAAC,EAAoB,EAAM,MACvC,CAGkC,KAAO,IAAkB,CAC1D,GAAI,CACF,IAAM,EAAmB,MAAM,GAAoB,EAAQ,EAAc,CACzE,EAAoB,EAAiB,MAAQ,EAC7C,EAAA,EAAO,KACL,EAAA,QAAO,MACL,uCAAuC,EAAc,KAAK,IAC3D,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,kCAAkC,EAAc,KAAK,OAAO,EAAI,UACjE,CACF,GAEH,CAGF,GAAI,CACF,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,aAAa,EAAO,OAAO,oBAAoB,CAAC,CAC3E,MAAM,GACJ,EACA,EAAO,IAAK,GAAU,CAAC,EAAO,EAAoB,EAAM,MAAM,GAAG,CAAC,CACnE,CACD,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,wBAAwB,EAAO,OAAO,oBAAoB,CACxE,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,mBAAmB,EAAO,OAAO,uBAAuB,EAAI,UAC7D,CACF,CAGH,MAAO,CAAC,ECrHV,eAAsB,GACpB,EACA,EACiD,CAajD,GAAM,CAAE,YAAA,GAAgB,MAAM,EAM3B,EAAQ,GAAc,CACvB,MAnBY,CACZ,KAAM,EAAM,KACZ,YAAa,EAAM,YACnB,uBAAwB,EAAM,uBAC9B,iBAAkB,EAAM,iBACxB,YAAa,EAAM,OACnB,uBAAwB,EAAM,wBAAwB,KACtD,yBAA0B,EAAM,wBAAwB,OAGzD,CAUA,CAAC,CACF,OAAOC,EAAY,MASrB,eAAsB,GACpB,EACA,EACe,CACf,MAAM,EAAmB,EAAQ,GAAe,CAC9C,MAAO,CACL,OAAQ,EAAa,KAAK,CAAC,EAAO,MAAS,CACzC,KACA,KAAM,EAAM,KACZ,YAAa,EAAM,YACnB,uBAAwB,EAAM,uBAC9B,iBAAkB,EAAM,iBAEzB,EAAE,CACJ,CACF,CAAC,CAUJ,eAAsB,GACpB,EACA,EACkB,CAElB,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,YAAY,EAAO,OAAO,aAAa,CAAC,CAEnE,IAAI,EAAmB,GAMjB,EAEFC,EAAAA,EALmB,MAAM,GAAe,EAAO,CAKzB,OAAO,CAMjC,MAAM,EAHY,EAAO,OAAQ,GAAU,CAAC,EAAY,EAAM,MAAM,CAGzC,KAAO,IAAU,CAC1C,GAAI,CACF,IAAM,EAAW,MAAM,GAAY,EAAQ,EAAM,CACjD,EAAY,EAAS,MAAQ,EAC7B,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,8BAA8B,EAAM,KAAK,IAAI,CAAC,OAChE,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IAAI,yBAAyB,EAAM,KAAK,OAAO,EAAI,UAAU,CACrE,GAEH,CAGF,GAAI,CACF,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,aAAa,EAAO,OAAO,WAAW,CAAC,CAClE,MAAM,GACJ,EACA,EAAO,IAAK,GAAU,CAAC,EAAO,EAAY,EAAM,MAAM,GAAG,CAAC,CAC3D,CACD,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,wBAAwB,EAAO,OAAO,WAAW,CAAC,OACpE,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IAAI,mBAAmB,EAAO,OAAO,eAAe,EAAI,UAAU,CAC1E,CAGH,MAAO,CAAC,ECtGV,eAAsB,GACpB,EACA,EACA,CACE,oBACA,8BAOa,CAEf,IAAM,EAAQ,CACZ,KAAM,EAAU,KAChB,UAAW,EAAU,UACtB,CAGG,EACJ,GAAK,EAmBH,MAAM,EAAmB,EAAQ,GAAkB,CACjD,eAAgB,EAAkB,GAClC,YAAa,EAAkB,SAC3B,EAAU,YACV,IAAA,GACJ,GAAG,EACJ,CAAC,CACF,EAAiB,EAAkB,OA1Bb,CACtB,GAAM,CACJ,mBAAoB,CAAE,iBACpB,MAAM,EASP,EAAQ,GAAkB,CAC3B,KAAM,EAAU,KAChB,YAAa,EAAU,YACvB,GAAG,EACJ,CAAC,CACF,EAAiB,EAAa,GAahC,IAAM,EAAuBC,EAAAA,EAAM,GAAmB,QAAU,EAAE,CAAE,OAAO,CACrE,CAAE,iBAAiB,EAAE,CAAE,YAAY,EAAE,EAAKC,GAC9C,EAAU,QAAU,EAAE,CACrB,GACC,EAAqB,EAAM,MAAQ,iBAAmB,YACzD,CACK,EAAgBC,GACnB,GAAmB,QAAU,EAAE,EAAE,KAAK,CAAE,UAAW,EAAK,EACxD,EAAU,QAAU,EAAE,EAAE,KAAK,CAAE,UAAW,EAAK,CACjD,CAGG,EAAU,OAAS,IACrB,MAAM,EAAmB,EAAQ,GAAyB,CACxD,MAAO,EAAU,KAAK,CAAE,OAAM,GAAG,MAAY,CAC3C,OACA,iBACA,GAAG,EACJ,EAAE,CACJ,CAAC,CACF,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,WAAW,EAAU,OAAO,mBAAmB,CAAC,EAIvE,EAAe,OAAS,IAC1B,MAAM,EAAmB,EAAQ,GAAyB,CACxD,MAAO,EAAe,KAAK,CAAE,OAAM,GAAG,MAAY,CAChD,GAAI,EAAqB,GAAM,GAC/B,OACA,YAAa,EAAqB,GAAM,YACxC,MAAO,EAAqB,GAAM,MAClC,GAAG,EACH,iBACD,EAAE,CACJ,CAAC,CACF,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,WAAW,EAAe,OAAO,mBAAmB,CAClE,EAIC,EAAc,OAAS,GAAK,IAC9B,MAAM,EACJ,EACA,KAAO,IAAU,CACf,MAAM,EAAmB,EAAQ,GAAwB,CACvD,GAAI,EAAqB,GAAO,GACjC,CAAC,EAEJ,CACE,YAAa,GACd,CACF,CACD,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,WAAW,EAAc,OAAO,mBAAmB,CACjE,EC7GL,eAAsB,GACpB,EACA,EACyB,CAczB,GAAM,CAAE,qBAAA,GAAyB,MAAM,EAMpC,EAAQ,GAAwB,CACjC,MApBY,CACZ,MAAO,EAAe,MACtB,YAAa,EAAe,YAC5B,QAAS,EAAe,QACxB,mBAAoB,EAAe,mBACnC,uBAAwB,EAAe,uBACvC,0BAA2B,EAAe,0BAC1C,2BAA4B,EAAe,2BAC3C,WAAY,EAAe,WAC3B,UAAW,EAAe,MAC1B,YAAa,EAAe,OAC7B,CAUA,CAAC,CACF,OAAOC,EAAqB,eAS9B,eAAsB,GACpB,EACA,EACe,CAEf,MAAM,EADiBC,EAAM,EAAuB,IAAI,CACxB,KAAO,IAAY,CACjD,MAAM,EAAmB,EAAQ,GAA0B,CACzD,MAAO,EAAQ,KAAK,CAAC,EAAgB,MAAS,CAC5C,KACA,MAAO,EAAe,MACtB,YAAa,EAAe,YAC5B,QAAS,EAAe,QACxB,mBAAoB,EAAe,mBACnC,uBAAwB,EAAe,uBACvC,0BAA2B,EAAe,0BAC1C,2BAA4B,EAAe,2BAC3C,WAAY,EAAe,WAC3B,UAAW,EAAe,MAC1B,YAAa,EAAe,OAC7B,EAAE,CACJ,CAAC,EACF,CAUJ,eAAsB,GACpB,EACA,EACkB,CAElB,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,YAAY,EAAO,OAAO,wBAAwB,CAClE,CAED,IAAI,EAAmB,GAMjB,EAAwBC,EAAAA,EAHG,MAAM,GAAyB,EAAO,CAGT,QAAQ,CAQtE,MAAM,EALsB,EAAO,OAChC,GAAU,CAAC,EAAsB,EAAM,OACzC,CAGoC,KAAO,IAAmB,CAC7D,GAAI,CACF,IAAM,EAAoB,MAAM,GAC9B,EACA,EACD,CACD,EAAsB,EAAkB,OAAS,EACjD,EAAA,EAAO,KACL,EAAA,QAAO,MACL,wCAAwC,EAAe,MAAM,IAC9D,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,mCAAmC,EAAe,MAAM,OAAO,EAAI,UACpE,CACF,GAEH,CAGF,GAAI,CACF,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,aAAa,EAAO,OAAO,sBAAsB,CACjE,CACD,MAAM,GACJ,EACA,EAAO,IAAK,GAAU,CAAC,EAAO,EAAsB,EAAM,OAAO,GAAG,CAAC,CACtE,CACD,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,wBAAwB,EAAO,OAAO,sBAAsB,CAC1E,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,mBAAmB,EAAO,OAAO,0BAA0B,EAAI,UAChE,CACF,CAGH,MAAO,CAAC,ECxGV,MAAMC,GAAY,GAQlB,eAAsB,GACpB,EACwB,CACxB,IAAM,EAA8B,EAAE,CAClC,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,aAAc,CAAE,UACd,MAAM,EAMP,EAAQ,GAAe,CACxB,MAAOA,GACP,SACD,CAAC,CACF,EAAa,KAAK,GAAG,EAAM,CAC3B,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAa,MAAM,EAAG,IAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,CChDlE,MAAMC,GAAY,GAQlB,eAAsB,GACpB,EACmC,CACnC,IAAM,EAAoD,EAAE,CACxD,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,wBAAyB,CAAE,UACzB,MAAM,EAMP,EAAQ,GAA2B,CACpC,MAAOA,GACP,SACD,CAAC,CACF,EAAwB,KAAK,GAAG,EAAM,CACtC,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAwB,MAAM,EAAG,IAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,CCnD7E,MAAMC,GAAa,IASnB,eAAsB,GACpB,EACA,EA0BiC,CACjC,GAAM,CACJ,6BAA8B,CAAE,2BAC9B,MAAM,EAMP,EAAQ,GAAiC,CAC1C,QACD,CAAC,CAMF,OALA,EAAA,EAAO,KACL,EAAA,QAAO,MACL,kDAAkD,EAAM,KAAK,IAC9D,CACF,CACM,EAUT,eAAsB,GACpB,EACA,EA0BmC,CACnC,GAAM,CACJ,8BAA+B,CAAE,4BAC/B,MAAM,EAMP,EAAQ,GAAkC,CAC3C,MAAO,CACL,wBAAyB,EAC1B,CACF,CAAC,CAMF,OALA,EAAA,EAAO,KACL,EAAA,QAAO,MACL,wBAAwB,EAAO,OAAO,6BACvC,CACF,CACM,EAWT,eAAsB,GACpB,EACA,EACA,EAAc,GAMb,CACD,IAAI,EAAmB,GACjB,EAAiC,EAAE,CACzC,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,uCAAuC,CAAC,CAInE,IAAM,EAAgCC,EAAAA,EADrB,MAAM,GAAgC,EAAO,EAG3D,CAAE,OAAM,qBAAsB,KAAK,UAAU,CAAE,OAAM,kBAAiB,CAAC,CACzE,CAGK,EAAuC,EAAwB,IAClE,GAAa,CACZ,EACA,EACE,KAAK,UAAU,CACb,KAAM,EAAS,KACf,gBAAiB,EAAS,gBAC3B,CAAC,GACD,GACJ,CACF,CAGK,EAA6B,EAChC,QAAQ,EAAG,KAAc,CAAC,EAAS,CACnC,KAAK,CAAC,KAAc,EAAwC,CAC/D,GAAI,CACF,EAAA,EAAO,KACL,EAAA,QAAO,QACL,aAAa,EAA2B,OAAO,oCAChD,CACF,CACD,MAAM,EACJ,EACA,KAAO,IAAQ,CACb,IAAM,EAAS,MAAM,GAA6B,EAAQ,EAAI,CAC9D,EAAK,KAAK,EAAO,EAEnB,CACE,cACD,CACF,CACD,EAAA,EAAO,KACL,EAAA,QAAO,MACL,uBAAuB,EAA2B,OAAO,6BAC1D,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,iDAAiD,EAAI,UACtD,CACF,CAIH,IAAM,EACJ,EAAqC,OAClC,GAAkD,CAAC,CAAC,EAAE,GACxD,CACG,EAASC,EAAM,EAAiCF,IAAW,CAwCjE,OAvCA,EAAA,EAAO,KACL,EAAA,QAAO,QACL,aAAa,EAAgC,OAAO,gCACrD,CACF,CAED,MAAM,EAAU,EAAQ,KAAO,IAAU,CACvC,GAAI,CACF,IAAM,EAAc,MAAM,GACxB,EAEAE,EAAM,KAAK,CAAC,CAAE,kBAAiB,GAAG,GAAS,MAAS,CAClD,GAAG,EACH,KACD,EAAE,CACJ,CACD,EAAK,KAAK,GAAG,EAAY,CACzB,EAAA,EAAO,KACL,EAAA,QAAO,MACL,yBAAyB,EAAgC,OAAO,8BACjE,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,iDAAiD,EAAI,UACtD,CACF,CAGH,EAAA,EAAO,KACL,EAAA,QAAO,MACL,WAAW,EAAwB,OAAO,8BAC3C,CACF,EACD,CAGK,CACL,wBAAyB,EACzB,QAAS,CAAC,EACX,CClOH,MAAMC,GAAY,GAQlB,eAAsB,GACpB,EACuB,CACvB,IAAM,EAA6B,EAAE,CACjC,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,aAAc,CAAE,UACd,MAAM,EAMP,EAAQ,GAAc,CACvB,MAAOA,GACP,SACD,CAAC,CACF,EAAa,KAAK,GAAG,EAAM,CAC3B,GAAUA,GACV,EAAiB,EAAM,SAAWA,SAC3B,GAET,OAAO,EAAa,MAAM,EAAG,IAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,CCrDlE,MAAMC,GAAa,IASnB,eAAsB,GACpB,EACA,EAgBqB,CACrB,GAAM,CACJ,iBAAkB,CAAE,eAClB,MAAM,EAMP,EAAQ,GAAmB,CAC5B,QACD,CAAC,CAEF,OADA,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,oCAAoC,EAAM,KAAK,IAAI,CAAC,CACtE,EAUT,eAAsB,GACpB,EACA,EAkBuB,CACvB,GAAM,CACJ,mBAAoB,CAAE,iBACpB,MAAM,EAMP,EAAQ,GAAqB,CAC9B,MAAO,CACL,aAAc,EACf,CACF,CAAC,CAIF,OAHA,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,wBAAwB,EAAO,OAAO,gBAAgB,CACpE,CACM,EAWT,eAAsB,GACpB,EACA,EACA,EAAc,GAMb,CACD,IAAI,EAAmB,GACjB,EAAsB,EAAE,CAIxB,EAAmBC,EAAAA,EADR,MAAM,GAAqB,EAAO,CACV,OAAO,CAG1C,EAA4B,EAAa,IAAK,GAAc,CAChE,EACA,EAAiB,EAAU,OAAO,GACnC,CAAC,CAGI,EAAkB,EACrB,QAAQ,EAAG,KAAc,CAAC,EAAS,CACnC,KAAK,CAAC,KAAe,EAA6B,CACrD,GAAI,CACF,EAAA,EAAO,KACL,EAAA,QAAO,QACL,aAAa,EAAgB,OAAO,uBACrC,CACF,CACD,MAAM,EACJ,EACA,KAAO,IAAS,CACd,IAAM,EAAU,MAAM,GAAiB,EAAQ,EAAK,CACpD,EAAM,KAAK,EAAQ,EAErB,CACE,cACD,CACF,CACD,EAAA,EAAO,KACL,EAAA,QAAO,MACL,uBAAuB,EAAgB,OAAO,gBAC/C,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KAAK,EAAA,QAAO,IAAI,oCAAoC,EAAI,UAAU,CAAC,CAI5E,IAAM,EAAuB,EAA0B,OACpD,GAAsC,CAAC,CAAC,EAAE,GAC5C,CACK,EAASC,EAAM,EAAsBF,IAAW,CA+BtD,OA9BA,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,aAAa,EAAqB,OAAO,mBAAmB,CAC5E,CAED,MAAM,EAAU,EAAQ,KAAO,IAAU,CACvC,GAAI,CACF,IAAM,EAAe,MAAM,GACzB,EACAE,EAAM,KAAK,CAAC,EAAO,MAAS,CAC1B,GAAG,EACH,KACD,EAAE,CACJ,CACD,EAAM,KAAK,GAAG,EAAa,CAC3B,EAAA,EAAO,KACL,EAAA,QAAO,MACL,yBAAyB,EAAqB,OAAO,iBACtD,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IAAI,oCAAoC,EAAI,UAAU,CAC9D,CAGH,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,WAAW,EAAa,OAAO,iBAAiB,CAAC,EAC1E,CAGK,CACL,aAAc,EACd,QAAS,CAAC,EACX,CC1LH,MAAMC,GAAa,IAEb,GAAmB,OASzB,eAAsB,GACpB,EACA,EAwBsB,CACtB,GAAM,CACJ,kBAAmB,CAAE,gBACnB,MAAM,EAMP,EAAQ,GAAqB,CAC9B,QACD,CAAC,CAIF,OAHA,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,sCAAsC,EAAM,KAAK,IAAI,CACnE,CACM,EAUT,eAAsB,GACpB,EACA,EA0BwB,CACxB,GAAM,CACJ,mBAAoB,CAAE,iBACpB,MAAM,EAMP,EAAQ,GAAsB,CAC/B,MAAO,CACL,aAAc,EACf,CACF,CAAC,CAIF,OAHA,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,wBAAwB,EAAO,OAAO,iBAAiB,CACrE,CACM,EAWT,eAAsB,GACpB,EACA,EACA,EAAc,GACI,CAClB,IAAI,EAAmB,GACjB,CACJ,EACA,CAAE,wBAAyB,IACzB,MAAM,QAAQ,IAAI,CAEpB,GAAqB,EAAO,CAE5B,GACE,EACAC,GACE,EACG,KAAK,CAAE,OAAM,0BAA0B,EAAE,IACxC,EAAwB,KAAK,CAAE,WAAY,CACzC,OACA,gBAAiB,EAClB,EAAE,CACJ,CACA,MAAM,EACR,CAAE,OAAM,qBACP,GAAG,IAAO,KAAmB,IAChC,CACD,EACD,CAED,GACE,EACAA,GAAO,EAAc,iBAAiB,CAAC,KACpC,CAAE,qBACA,CACC,KAAM,EACN,IAAK,sBAAsB,IAC5B,EACJ,CACF,CACF,CAAC,CAEI,EAA+BC,EAAAA,EACnC,GACC,CAAE,OAAM,qBACP,GAAG,IAAO,KAAmB,IAChC,CACK,EAAqBA,EAAAA,EACzB,GACC,CAAE,OAAM,UAAW,GAAG,IAAO,KAAmB,IAClD,CAGK,EAA4B,EAAa,IAAK,GAAqB,CACvE,EACA,EACE,GAAG,EAAiB,OAAO,KAAmB,EAAiB,SAC9D,GACJ,CAAC,CAGI,EAAkB,EACrB,QAAQ,EAAG,KAAc,CAAC,EAAS,CACnC,KAAK,CAAC,KAAsB,EAAqC,CACpE,GAAI,CACF,EAAA,EAAO,KACL,EAAA,QAAO,QACL,aAAa,EAAgB,OAAO,wBACrC,CACF,CACD,MAAM,EACJ,EACA,MAAO,CAAE,0BAAyB,GAAG,KAAkB,CACrD,MAAM,GAAkB,EAAQ,CAC9B,GAAG,EACH,GAAI,EACA,CACE,0BAA2BC,EACzB,EAAwB,KAAK,CAAE,UAAW,CACxC,IAAM,EACJ,EACE,GAAG,IAAO,KAAmB,EAAY,QAE7C,GAAI,CAAC,EACH,MAAU,MACR,kCAAkC,EAAK,GACxC,CAEH,OAAO,EAAI,IACX,CACH,CACF,CACD,EAAE,CACP,CAAC,EAEJ,CACE,cACD,CACF,CACD,EAAA,EAAO,KACL,EAAA,QAAO,MACL,uBAAuB,EAAgB,OAAO,iBAC/C,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KAAK,EAAA,QAAO,IAAI,qCAAqC,EAAI,UAAU,CAAC,CAI7E,IAAM,EAA4B,EAA0B,OACzD,GAAuC,CAAC,CAAC,EAAE,GAC7C,CAkDD,OAjDA,EAAA,EAAO,KACL,EAAA,QAAO,QACL,aAAa,EAA0B,OAAO,oBAC/C,CACF,CAGD,MAAM,EAFSC,EAAM,EAA2BJ,IAAW,CAEnC,KAAO,IAAU,CACvC,GAAI,CACF,MAAM,GACJ,EACAI,EAAM,KAEH,CAAC,CAAE,0BAAyB,iBAAgB,GAAG,GAAS,MAAS,CAChE,GAAG,EACH,GAAI,EACA,CACE,0BAA2BD,EACzB,EAAwB,KAAK,CAAE,UAAW,CACxC,IAAM,EACJ,EACE,GAAG,IAAO,KAAmB,EAAM,QAEvC,GAAI,CAAC,EACH,MAAU,MACR,kCAAkC,EAAK,GACxC,CAEH,OAAO,EAAI,IACX,CACH,CACF,CACD,EAAE,CACN,KACD,EACF,CACF,CACD,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,yBAAyBC,EAAM,OAAO,kBAAkB,CACtE,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IAAI,qCAAqC,EAAI,UAAU,CAC/D,GAEH,CAEF,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,WAAW,EAAa,OAAO,kBAAkB,CAAC,CACpE,CAAC,ECjQV,MAAM,GACJ,yEAQF,eAAsB,GACpB,EACA,EACe,CAGf,IAAM,EAAmBC,EAAAA,EADG,MAAM,GAA+B,EAAO,CACpB,OAAO,CAIrD,EAAgBA,EAAAA,EADL,MAAM,GAAiB,EAAO,CACT,eAAe,CAGrD,MAAM,EACJ,EACA,MAAO,EAAK,IAAQ,CAElB,IAAM,EAAa,EAAI,UAAU,KAAK,EAAS,IAAS,CACtD,IAAM,EAAkB,EAAc,EAAQ,cAC9C,GAAI,CAAC,EACH,MAAU,MACR,uEAAuE,EAAI,aAAa,EAAK,KACxF,EAAQ,aAAa,+BAA+B,KAC1D,CAEH,OAAO,EAAgB,IACvB,CACI,EAAqB,EAAI,kBAAkB,KAAK,EAAS,IAAS,CACtE,IAAM,EAAkB,EAAc,EAAQ,cAC9C,GAAI,CAAC,EACH,MAAU,MACR,uEAAuE,EAAI,qBAAqB,EAAK,KAChG,EAAQ,aAAa,+BAA+B,KAC1D,CAEH,OAAO,EAAgB,IACvB,CAGI,EAAqB,EAAiB,EAAI,MAC5C,GACF,MAAM,EAAmB,EAAQ,GAA2B,CAC1D,MAAO,CACL,GAAI,EAAmB,GACvB,KAAM,EAAI,YACV,QAAS,EAAI,QACb,SAAU,EAAI,SACd,gBAAiB,EAAI,gBACrB,cAAe,EAAI,cACnB,gBACE,EAAI,kBAAoB,EAAmB,gBAEvC,IAAA,GADA,EAAI,gBAEV,UAAW,EAAI,UACf,SAAU,EACV,iBAAkB,EAClB,iBAAkB,EAAI,iBACtB,iBAAkB,EAAI,iBACvB,CACF,CAAC,CACF,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,2CAA2C,EAAI,KAAK,IAAI,CACtE,GAGD,MAAM,EAAmB,EAAQ,GAA2B,CAC1D,MAAO,CACL,KAAM,EAAI,KACV,YAAa,EAAI,YACjB,QAAS,EAAI,QACb,SAAU,EAAI,SACd,gBAAiB,EAAI,iBAAmBC,EAAAA,gBAAgB,OACxD,cAAe,EAAI,cACnB,gBAAiB,EAAI,gBACrB,UAAW,EAAI,WAAaC,EAAAA,iBAAiB,OAC7C,SAAU,GAAc,EAAE,CAC1B,iBAAkB,GAAsB,EAAE,CAC1C,iBAAkB,EAAI,iBACtB,iBAAkB,EAAI,iBACvB,CACF,CAAC,CACF,EAAA,EAAO,KACL,EAAA,QAAO,MACL,4CAA4C,EAAI,KAAK,IACtD,CACF,GAGL,CACE,YAAa,GACd,CACF,CASH,eAAsB,GACpB,EACA,EACe,CACf,IAAI,EAGJ,GAAI,CACF,EAAiB,MAAM,EAAsB,EAAQ,EAAE,OAChD,EAAK,CAEZ,GAAI,EAAI,QAAQ,SAAS,yBAAyB,CAAE,CAClD,IAAM,EAAkB,MAAM,GAAqB,EAAO,CAEpD,CAAE,wBAAyB,MAAM,EASpC,EAAQ,GAAwB,CACjC,QAAS,EAAe,QACxB,kBACD,CAAC,CACF,EAAiB,EAAqB,eAAe,QAErD,MAAM,EAaV,GARI,EAAe,SACjB,MAAM,EAAmB,EAAQ,GAAgC,CAC/D,QAAS,EAAe,QACxB,iBACD,CAAC,CAIA,EAAe,UAAW,CAE5B,IAAM,GADa,MAAM,GAAgB,EAAO,EACX,KAClC,GAAS,EAAK,OAAS,EAAe,UACxC,CACD,GAAI,CAAC,EACH,MAAU,MACR,cAAc,EAAe,UAAU,iDACxC,CAEH,MAAM,EAAmB,EAAQ,GAAkC,CACjE,YAAa,EAAkB,GAC/B,iBACD,CAAC,CAGA,EAAe,SACjB,MAAM,EAAmB,EAAQ,GAAgC,CAC/D,iBACA,QAAS,EAAe,QACzB,CAAC,CAIA,EAAe,oBACjB,MAAM,EAAmB,EAAQ,GAAqB,CACpD,MAAO,CACL,GAAI,EACJ,GAAI,EAAe,mBACf,CAAE,mBAAoB,EAAe,mBAAoB,CACzD,EAAE,CACP,CACF,CAAC,CAIA,EAAe,sBACjB,MAAM,EAAmB,EAAQ,GAA+B,CAC9D,MAAO,CACL,GAAI,EACJ,qBAAsB,EAAe,qBACtC,CACF,CAAC,CAIA,EAAe,sBACjB,MAAM,EAAmB,EAAQ,GAA8B,CAC7D,MAAO,CACL,GAAI,EACJ,oBAAqB,EAAe,oBACrC,CACF,CAAC,CAIA,EAAe,uBACjB,MAAM,EAAmB,EAAQ,GAAqC,CACpE,MAAO,CACL,GAAI,EACJ,SAAU,EAAe,sBAC1B,CACF,CAAC,CAIA,EAAe,mBACjB,MAAM,EAAmB,EAAQ,GAA2B,CAC1D,MAAO,CACL,GAAI,EACJ,kBAAmB,EAAe,kBACnC,CACF,CAAC,CAIA,EAAe,aACjB,MAAM,GAA8B,EAAQ,EAAe,YAAY,CAIrE,EAAe,OACjB,MAAM,EAAmB,EAAQ,GAA8B,CAC7D,MAAO,CACL,iBACA,GAAG,EAAe,MACnB,CACF,CAAC,CCvQN,MAAMC,GAAgB,IAQtB,eAAsB,GACpB,EACA,EACe,CACf,IAAM,EAAiB,MAAM,EAAsB,EAAO,CAM1D,MAAM,EAAUC,EAAM,EAAcD,IAAc,CAAE,KAAO,IAAS,CAClE,MAAM,EAAmB,EAAQ,GAA0B,CACzD,iBACA,QAAS,EAAK,IAAK,IAAY,CAC7B,KAAM,EAAO,KACb,iBACE,EAAO,kBAAoB,EAAO,iBAAiB,OAAS,EACxD,EAAO,iBACP,IAAA,GAON,YAAa,EAAO,YACpB,QAAS,EAAO,QAChB,OAAQ,EAAO,OACf,WAAY,EAAO,WACnB,QAAS,EAAO,QAIjB,EAAE,CACJ,CAAC,EACF,CAUJ,eAAsB,GACpB,EACA,EACkB,CAClB,IAAI,EAAmB,GACvB,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,YAAY,EAAQ,OAAO,cAAc,CAAC,CAGrE,IAAM,EAAY,EAAQ,OACvB,GACC,EAAQ,OACL,GAAS,EAAO,OAAS,EAAK,MAAQ,EAAO,UAAY,EAAK,QAChE,CAAC,OAAS,EACd,CACD,GAAI,EAAU,OAAS,EACrB,MAAU,MACR,oEAAoE,EACjE,KAAK,CAAE,UAAW,EAAK,CACvB,KAAK,IAAI,GACb,CAGH,GAAI,CACF,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,cAAc,EAAQ,OAAO,kBAAkB,CAAC,CAC3E,MAAM,GAAsB,EAAQ,EAAQ,CAC5C,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,uBAAuB,EAAQ,OAAO,WAAW,CAAC,OACpE,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KAAK,EAAA,QAAO,IAAI,+BAA+B,EAAI,UAAU,CAAC,CAGvE,MAAO,CAAC,EC3EV,eAAsB,GACpB,EACA,EAC4D,CAQ5D,GAAM,CAAE,mBAAA,GAAuB,MAAM,EAMlC,EAAQ,GAA0B,CACnC,MAdY,CACZ,KAAM,EAAa,KACnB,SAAU,EAAa,SACvB,YAAa,EAAa,YAE3B,CAUA,CAAC,CACF,OAAOE,EAAmB,aAS5B,eAAsB,GACpB,EACA,EACe,CACf,MAAM,EAAmB,EAAQ,GAA4B,CAC3D,MAAO,CACL,kBAAmB,EAAoB,KAAK,CAAC,EAAc,MAAS,CAClE,KACA,YAAa,EAAa,YAE1B,WAAY,EAAa,WAC1B,EAAE,CACJ,CACF,CAAC,CAUJ,eAAsB,GACpB,EACA,EACkB,CAElB,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,YAAY,EAAO,OAAO,sBAAsB,CAAC,CAE5E,IAAI,EAAmB,GAMjB,EAEFC,EAAAA,EAL2B,MAAM,GAAuB,EAAO,EAOhE,CAAE,OAAM,cAAe,GAAG,EAAK,GAAG,IACpC,CAQD,MAAM,EALoB,EAAO,OAC9B,GAAU,CAAC,EAAmB,GAAG,EAAM,KAAK,GAAG,EAAM,YACvD,CAGkC,KAAO,IAAiB,CACzD,GAAI,CACF,IAAM,EAAkB,MAAM,GAAmB,EAAQ,EAAa,CACtE,EACE,GAAG,EAAgB,KAAK,GAAG,EAAgB,YACzC,EACJ,EAAA,EAAO,KACL,EAAA,QAAO,MACL,sCAAsC,EAAa,KAAK,IACzD,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,iCAAiC,EAAa,KAAK,OAAO,EAAI,UAC/D,CACF,GAEH,CAGF,GAAI,CACF,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,aAAa,EAAO,OAAO,oBAAoB,CAAC,CAC3E,MAAM,GACJ,EACA,EAAO,IAAK,GAAU,CACpB,EACA,EAAmB,GAAG,EAAM,KAAK,GAAG,EAAM,YAAY,GACvD,CAAC,CACH,CACD,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,wBAAwB,EAAO,OAAO,oBAAoB,CACxE,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,mBAAmB,EAAO,OAAO,wBAAwB,EAAI,UAC9D,CACF,CAGH,MAAO,CAAC,ECjIV,MAAMC,GAAgB,IAStB,eAAsB,GACpB,EACA,EACA,EAAkB,GACH,CACf,IAAM,EAAiB,MAAM,EAAsB,EAAO,CAM1D,MAAM,EAAUC,EAAM,EAAgBD,IAAc,CAAE,KAAO,IAAS,CACpE,MAAM,EAAmB,EAAQ,GAAmB,CAClD,iBACA,UAAW,EAAK,KAAK,CAAC,EAAM,MAAS,CACnC,KACA,MAAO,EAAK,MACZ,KAAM,EAAK,KACX,aACE,EAAK,kBAAoB,EAAK,iBAAiB,OAAS,EACpD,EAAK,iBACL,IAAA,GAON,YAAa,EAAK,YAClB,QAAS,EAAK,QACd,OAAQ,EAAK,OACb,WAAY,EAAK,WAIlB,EAAE,CACH,kBACD,CAAC,EACF,CAUJ,eAAsB,GACpB,EACA,EACA,EAAkB,GACH,CACf,IAAM,EAAiB,MAAM,EAAsB,EAAO,CAI1D,MAAM,EAAUC,EAAM,EAAgBD,IAAc,CAAE,KAAO,IAAS,CACpE,MAAM,EAAmB,EAAQ,GAAmB,CAClD,iBACA,UAAW,EAAK,IAAK,IAAU,CAC7B,MAAO,EAAK,MACZ,KAAM,EAAK,KACX,aACE,EAAK,kBAAoB,EAAK,iBAAiB,OAAS,EACpD,EAAK,iBACL,IAAA,GAON,YAAa,EAAK,YAClB,QAAS,EAAK,QACd,OAAQ,EAAK,OACb,WAAY,EAAK,WAIlB,EAAE,CACH,8BAA+B,GAC/B,kBACD,CAAC,EACF,CAWJ,eAAsB,GACpB,EACA,EACA,EACkB,CAClB,IAAI,EAAmB,GACvB,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,YAAY,EAAU,OAAO,iBAAiB,CAAC,CAI1E,IAAM,EAAY,EAAU,OACzB,GACC,EAAU,OACP,GAAS,EAAS,QAAU,EAAK,OAAS,EAAS,OAAS,EAAK,KACnE,CAAC,OAAS,EACd,CAGD,GAAI,EAAU,OAAS,EACrB,MAAU,MACR,uEAAuE,EACpE,KAAK,CAAE,WAAY,EAAM,CACzB,KAAK,IAAI,GACb,CAKH,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,yBAAyB,CAAC,CACrD,GAAM,CAAC,EAAuB,GAA6B,MAAM,QAAQ,IAAI,CAC3E,GAAkB,EAAQE,EAAAA,qBAAqB,KAAK,CACpD,GAAkB,EAAQA,EAAAA,qBAAqB,YAAY,CAC5D,CAAC,CACI,EAAe,CAAC,GAAG,EAAuB,GAAG,EAA0B,CAGvE,EAAyB,EAAU,IAAK,GAAa,CACzD,EACA,EAAa,KACV,GAAS,EAAS,QAAU,EAAK,OAAS,EAAS,OAAS,EAAK,KACnE,EAAE,GACJ,CAAC,CAGI,EAAe,EAClB,QAAQ,EAAG,KAAc,CAAC,EAAS,CACnC,KAAK,CAAC,KAAU,EAAsB,CACzC,GAAI,CACF,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,aAAa,EAAa,OAAO,qBAAqB,CACtE,CACD,MAAM,GAAgB,EAAQ,EAAc,EAAgB,CAC5D,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,uBAAuB,EAAa,OAAO,cAAc,CACvE,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KAAK,EAAA,QAAO,IAAI,kCAAkC,EAAI,UAAU,CAAC,CAI1E,IAAM,EAAoB,EAAuB,OAC9C,GAAoC,CAAC,CAAC,EAAE,GAC1C,CACD,GAAI,CACF,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,aAAa,EAAkB,OAAO,iBAAiB,CACvE,CACD,MAAM,GAAgB,EAAQ,EAAmB,EAAgB,CACjE,EAAA,EAAO,KACL,EAAA,QAAO,MACL,yBAAyB,EAAkB,OAAO,eACnD,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KAAK,EAAA,QAAO,IAAI,kCAAkC,EAAI,UAAU,CAAC,CAM1E,OAHA,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,WAAW,EAAU,OAAO,eAAe,CAAC,CAG9D,CAAC,EC3LV,eAAsB,GACpB,EACA,CACE,cACA,gBACA,cAAc,IASD,CACf,MAAM,EAAmB,EAAQ,GAAqB,CACpD,MAAO,CACL,GAAI,EACJ,MAAO,EAAY,MACnB,gCACE,EAAY,gCACd,QAAS,EAAY,QACrB,YAAa,GAAsB,EAAY,SAAW,OAC3D,CACF,CAAC,CAEE,OAAO,EAAY,QAAW,WAChC,MAAM,EAAmB,EAAQ,GAAqB,CACpD,MAAO,CACL,GAAI,EACJ,OAAQ,EAAY,OACpB,cACD,CACF,CAAC,CChCN,eAAsB,GACpB,EACA,CACE,aACA,qBACA,eACA,cAAc,IAWD,CACf,MAAM,EAAmB,EAAQ,GAAmB,CAClD,MAAO,CACL,GAAI,EACJ,cAAe,EAAW,cAC1B,iBAAkB,EAAW,iBAC7B,MAAO,EAAW,MAClB,YAAa,EAAW,YACxB,aAAc,EAAW,aACzB,mBAAoB,EAAW,mBAC/B,aAAc,EAAW,aACzB,0BAA2B,EAAW,0BACtC,wBAAyB,EAAW,wBACpC,eAAgB,EAAW,aACvB,EAAW,aAAa,IAAK,GAAS,EAAmB,GAAM,GAAG,CAClE,IAAA,GACJ,cACD,CACF,CAAC,CCtCJ,MAAMC,GAAgB,IAQtB,eAAsB,GACpB,EACA,EACe,CAEf,MAAM,EAAUC,EAAM,EAAeD,IAAc,CAAE,KAAO,IAAS,CACnE,MAAM,EAAmB,EAAQ,GAAsB,CACrD,SAAU,EAAK,IAAK,IAAa,CAC/B,GAAI,EAAQ,GAAG,SAAS,IAAI,CAAG,EAAE,CAAG,CAAE,GAAI,EAAQ,GAAI,CACtD,eAAgB,EAAQ,eACxB,kBAAmB,EAAQ,kBAC3B,aAAe,EAAQ,aAEnB,OAAO,QAAQ,EAAQ,aAAa,CAAC,KAAK,CAAC,EAAQ,MAAY,CAC7D,SACA,QACD,EAAE,CAJH,IAAA,GAKL,EAAE,CACJ,CAAC,EACF,CAUJ,eAAsB,GACpB,EACA,EACkB,CAClB,IAAI,EAAmB,GACvB,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,YAAY,EAAS,OAAO,eAAe,CAAC,CAGvE,IAAM,EAAY,EAAS,OACxB,GAAY,EAAS,OAAQ,GAAQ,EAAQ,KAAO,EAAI,GAAG,CAAC,OAAS,EACvE,CACD,GAAI,EAAU,OAAS,EACrB,MAAU,MACR,qEAAqE,EAClE,KAAK,CAAE,QAAS,EAAG,CACnB,KAAK,IAAI,GACb,CAGH,GAAI,CACF,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,cAAc,EAAS,OAAO,mBAAmB,CACjE,CACD,MAAM,GAAmB,EAAQ,EAAS,CAC1C,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,uBAAuB,EAAS,OAAO,YAAY,CACjE,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KAAK,EAAA,QAAO,IAAI,gCAAgC,EAAI,UAAU,CAAC,CAGxE,MAAO,CAAC,ECnEV,MAAM,GAAgB,IAQtB,eAAsB,GACpB,EACA,EACe,CACf,IAAM,EAAkB,MAAM,GAAqB,EAAO,CAG1D,MAAM,EAAUE,EAAM,EAAc,IAAc,CAAE,KAAO,IAAS,CAClE,MAAM,EAAmB,EAAQ,GAAiB,CAChD,kBACA,SAAU,EAAK,KAAK,CAAC,EAAQ,MAAe,CAC1C,GAAI,EACJ,MAAO,EAAO,MACd,mBAAoB,EAAO,mBAC3B,gBAAiB,EAAO,gBACxB,GAAI,EAAO,aAAe,EAAO,QAC7B,CACE,QAAS,CACP,GAAI,EAAO,YACP,CAAE,YAAa,EAAO,YAAa,CACnC,EAAE,CACN,GAAI,EAAO,QACP,CACE,QAAS,CACP,eAAgB,EAAO,QACxB,CACF,CACD,EAAE,CACP,CACF,CACD,EAAE,CACP,EAAE,CACJ,CAAC,EACF,CAUJ,eAAsB,GACpB,EACA,EACkB,CAClB,IAAI,EAAmB,GACvB,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,YAAY,EAAS,OAAO,eAAe,CAAC,CAGvE,IAAM,EAAY,EAAS,OACxB,GAAW,EAAS,OAAQ,GAAQ,EAAO,QAAU,EAAI,MAAM,CAAC,OAAS,EAC3E,CACD,GAAI,EAAU,OAAS,EACrB,MAAU,MACR,qEAAqE,EAClE,KAAK,CAAE,WAAY,EAAM,CACzB,KAAK,IAAI,GACb,CAKH,IAAM,EAAeC,EAAAA,EADI,MAAM,GAAiB,EAAO,EAGpD,CAAE,WAAY,EAAM,eACtB,CAED,GAAI,CACF,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,cAAc,EAAS,OAAO,mBAAmB,CACjE,CACD,MAAM,GACJ,EACA,EAAS,IAAK,GAAW,CAAC,EAAQ,EAAa,EAAO,QAAQ,GAAG,CAAC,CACnE,CACD,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,uBAAuB,EAAS,OAAO,YAAY,CACjE,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KAAK,EAAA,QAAO,IAAI,gCAAgC,EAAI,UAAU,CAAC,CAGxE,MAAO,CAAC,ECzFV,eAAsB,GACpB,EACA,EACkB,CAClB,IAAI,EAAmB,GACvB,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,4BAA4B,CAAC,CAGxD,IAAM,EAAkB,MAAM,GAAqB,EAAO,CAE1D,GAAI,CACF,MAAM,EAAmB,EAAQ,GAAuB,CACtD,MAAO,CACL,kBACA,+BACE,EAAc,+BAChB,qBAAsB,EAAc,qBACpC,uBAAwB,EAAc,uBACtC,aAAc,EAAc,aAC5B,aAAc,EAAc,aAC5B,2BAA4B,EAAc,2BAC1C,cAAe,EAAc,cAC7B,QAAS,EAAc,QACvB,yBAA0B,EAAc,yBACxC,sBAAuB,EAAc,sBACrC,aAAc,EAAc,aAC5B,mBAAoB,EAAc,mBAClC,cAAe,EAAc,cAC7B,YAAa,EAAc,YAC3B,yBAA0B,EAAc,yBACxC,yBAA0B,EAAc,yBACxC,WAAY,EAAc,WAC1B,GAAI,EAAc,MACd,CACE,aAAc,EAAc,MAAM,OAClC,gBAAiB,EAAc,MAAM,gBACrC,WAAY,EAAc,MAAM,WACjC,CACD,EAAE,CACP,CACF,CAAC,CACF,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,sCAAsC,CAAC,OACzD,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IAAI,sCAAsC,EAAI,UAAU,CAChE,CAGH,MAAO,CAAC,ECzCV,eAAe,GACb,EACA,EACmD,CAMnD,GAAM,CAAE,yBAAA,GAA6B,MAAM,EAMxC,EAAQ,GAA4B,CACrC,MAZY,CACZ,MAAO,EAAmB,MAC1B,YAAa,EAAmB,YACjC,CAUA,CAAC,CACF,OAAOC,EAAyB,mBASlC,eAAe,GACb,EACA,EACe,CACf,IAAM,EAAkC,EACrC,QAAQ,EAAG,KAAQ,IAAO,IAAA,GAAU,CACpC,KAAK,CAAC,CAAE,YAAa,EAAM,CAC9B,GAAI,EAAgC,OAAS,EAG3C,MAAU,MACR,iBACE,EAAgC,OACjC,kEAAkE,EAAgC,KACjG,OACD,CAAC,GACH,CAEH,MAAM,EAAmB,EAAQ,GAA8B,CAC7D,MAAO,CACL,qBAAsB,EAA0B,KAC7C,CACC,CACE,wBACA,oBACA,iBACA,GAAG,GAEL,MACK,CACL,sBAAuB,GAAmB,KACvC,CAAE,WAAU,WAAY,CAAE,WAAU,KAAM,GAAQ,GAAI,EACxD,CACD,mCAAoC,GAAuB,KACxD,CAAE,UAAS,WAAY,CAAE,UAAS,KAAM,GAAQ,QAAS,EAC3D,CACD,mBAAoB,EACpB,GAAG,EACH,KACD,EACF,CACF,CACF,CAAC,CAUJ,eAAsB,GACpB,EACA,EACkB,CAClB,IAAI,EAAmB,GAGvB,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,YAAY,EAAO,OAAO,4BAA4B,CACtE,CAMD,IAAM,EAGFC,EAAAA,EARiC,MAAM,GACzC,EACD,CAMuC,QAAQ,CAG1C,EAA0B,EAAO,OACpC,GAAU,CAAC,EAA0B,EAAM,OAC7C,CACG,EAAwB,OAAS,GACnC,EAAA,EAAO,KACL,EAAA,QAAO,QACL,aAAa,EAAwB,OAAO,gCAC7C,CACF,CAEH,MAAM,EAAU,EAAyB,KAAO,IAAuB,CACrE,GAAI,CACF,IAAM,EAAwB,MAAM,GAClC,EACA,EACD,CAED,EAA0B,EAAsB,OAC9C,EACF,EAAA,EAAO,KACL,EAAA,QAAO,MACL,6CAA6C,EAAmB,MAAM,IACvE,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,yCAAyC,EAAmB,MAAM,OAAO,EAAI,UAC9E,CACF,GAEH,CAGF,GAAI,CACF,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,aAAa,EAAO,OAAO,0BAA0B,CACrE,CACD,MAAM,GACJ,EACA,EAAO,IAAK,GAAU,CACpB,EAEA,EAA0B,EAAM,QAAQ,GACzC,CAAC,CACH,CACD,EAAA,EAAO,KACL,EAAA,QAAO,MACL,wBAAwB,EAAO,OAAO,yBACvC,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,mBAAmB,EAAO,OAAO,4BAA4B,EAAI,UAClE,CACF,CAGH,MAAO,CAAC,ECjKV,eAAsB,GACpB,EACA,EACwE,CAQxE,GAAM,CAAE,sCAAuC,MAAM,EAMlD,EAAQ,GAAwC,CACjD,MAdY,CACZ,KAAM,EAAkB,KACxB,QAAS,EAAkB,QAC3B,YAAa,EAAkB,YAEhC,CAUA,CAAC,CACF,OAAO,EAAmC,6BAS5C,eAAsB,GACpB,EACA,EACe,CACf,MAAM,EAAmB,EAAQ,GAA0C,CACzE,MAAO,CACL,+BAAgC,EAAyB,KACtD,CAAC,EAAmB,MAAS,CAC5B,KACA,YAAa,EAAkB,YAE/B,WAAY,EAAkB,WAC/B,EACF,CACF,CACF,CAAC,CAUJ,eAAsB,GACpB,EACA,EACkB,CAElB,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,YAAY,EAAO,OAAO,0BAA0B,CACpE,CAED,IAAI,EAAmB,GAMjB,EAEFC,EAAAA,EAL+B,MAAM,GAA2B,EAAO,EAOxE,CAAE,OAAM,aAAc,GAAG,EAAK,GAAG,IACnC,CAQD,MAAM,EALwB,EAAO,OAClC,GAAU,CAAC,EAAwB,GAAG,EAAM,KAAK,GAAG,EAAM,WAC5D,CAGsC,KAAO,IAAsB,CAClE,GAAI,CACF,IAAM,EAAuB,MAAM,GACjC,EACA,EACD,CACD,EACE,GAAG,EAAqB,KAAK,GAAG,EAAqB,WACnD,EACJ,EAAA,EAAO,KACL,EAAA,QAAO,MACL,2CAA2C,EAAkB,KAAK,IACnE,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,sCAAsC,EAAkB,KAAK,OAAO,EAAI,UACzE,CACF,GAEH,CAGF,GAAI,CACF,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,aAAa,EAAO,OAAO,wBAAwB,CACnE,CACD,MAAM,GACJ,EACA,EAAO,IAAK,GAAU,CACpB,EACA,EAAwB,GAAG,EAAM,KAAK,GAAG,EAAM,WAAW,GAC3D,CAAC,CACH,CACD,EAAA,EAAO,KACL,EAAA,QAAO,MACL,wBAAwB,EAAO,OAAO,wBACvC,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,mBAAmB,EAAO,OAAO,4BAA4B,EAAI,UAClE,CACF,CAGH,MAAO,CAAC,EC1IV,eAAsB,GACpB,EACA,EAMiB,CACjB,GAAM,CACJ,aAAc,CAAE,WACd,MAAM,EASP,EAAQ,GAAe,CAExB,QACD,CAAC,CAEF,OADA,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,gCAAgC,EAAM,MAAM,IAAI,CAAC,CACnE,EAAO,GAShB,eAAsB,GACpB,EACA,EACe,CACf,MAAM,EAAmB,EAAQ,GAAgB,CAC/C,MAAO,CACL,QAAS,EAAM,KAAK,CAACC,EAAO,MAAS,CACnC,GAAGA,EACH,KACD,EAAE,CACJ,CACF,CAAC,CACF,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,wBAAwB,EAAM,OAAO,WAAW,CAAC,CAW5E,eAAsB,GACpB,EACA,EACA,EAAc,GACI,CAClB,IAAI,EAAmB,GACvB,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,YAAY,EAAQ,OAAO,cAAc,CAAC,CAIrE,IAAM,EAAgBC,EAAAA,EADL,MAAM,GAAgB,EAAO,CACR,QAAQ,CAGxC,EAAuB,EAAQ,IAAK,GAAgB,CACxD,EACA,EAAc,EAAY,QAAQ,GACnC,CAAC,CAGI,EAAa,EAChB,QAAQ,EAAG,KAAc,CAAC,EAAS,CACnC,KAAK,CAAC,KAAiB,EAA2B,CACrD,GAAI,CACF,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,aAAa,EAAW,OAAO,kBAAkB,CACjE,CACD,MAAM,EACJ,EACA,KAAO,IAAW,CAChB,MAAM,GAAa,EAAQ,EAAO,EAEpC,CACE,cACD,CACF,CACD,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,uBAAuB,EAAW,OAAO,WAAW,CAClE,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KAAK,EAAA,QAAO,IAAI,+BAA+B,EAAI,UAAU,CAAC,CAIvE,IAAM,EAAkB,EAAqB,OAC1C,GAAkC,CAAC,CAAC,EAAE,GACxC,CACD,GAAI,CACF,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,aAAa,EAAgB,OAAO,cAAc,CAClE,CACD,MAAM,GAAc,EAAQ,EAAgB,CAC5C,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,yBAAyB,EAAgB,OAAO,YAAY,CAC1E,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KAAK,EAAA,QAAO,IAAI,+BAA+B,EAAI,UAAU,CAAC,CAMvE,OAHA,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,WAAW,EAAQ,OAAO,YAAY,CAAC,CAGzD,CAAC,ECxHV,eAAsB,GACpB,EACA,EACuC,CAcvC,GAAM,CAAE,aAAA,GAAiB,MAAM,EAM5B,EAAQ,GAAe,CACxB,MApBY,CACZ,MAAO,EAAO,MACd,YAAa,EAAO,YACpB,QAAS,EAAO,QAChB,mBAAoB,EAAO,mBAC3B,uBAAwB,EAAO,uBAC/B,4BAA6B,EAAO,4BACpC,YAAa,EAAO,YACpB,aAAc,EAAO,aACrB,WAAY,EAAO,WAEpB,CAUA,CAAC,CACF,OAAOC,EAAa,OAStB,eAAsB,GACpB,EACA,EACe,CACf,MAAM,EAAmB,EAAQ,GAAgB,CAC/C,MAAO,CACL,QAAS,EAAc,KAAK,CAAC,EAAQ,MAAS,CAC5C,KACA,MAAO,EAAO,MACd,YAAa,EAAO,YACpB,QAAS,EAAO,QAChB,mBAAoB,EAAO,mBAC3B,uBAAwB,EAAO,uBAC/B,4BAA6B,EAAO,4BACpC,YAAa,EAAO,YACpB,aAAc,EAAO,aACrB,WAAY,EAAO,WAEnB,WAAY,EAAO,WACpB,EAAE,CACJ,CACF,CAAC,CAUJ,eAAsB,GACpB,EACA,EACkB,CAElB,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,YAAY,EAAO,OAAO,cAAc,CAAC,CAEpE,IAAI,EAAmB,GAMjB,EAAiEC,EAAAA,EAH/C,MAAM,GAAgB,EAAO,CAKnD,QACD,CAMD,MAAM,EAHa,EAAO,OAAQ,GAAU,CAAC,EAAc,EAAM,OAAO,CAG5C,KAAO,IAAW,CAC5C,GAAI,CACF,IAAM,EAAY,MAAM,GAAa,EAAQ,EAAO,CACpD,EAAc,EAAU,OAAS,EACjC,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,+BAA+B,EAAO,MAAM,IAAI,CAC9D,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IAAI,0BAA0B,EAAO,MAAM,OAAO,EAAI,UAAU,CACxE,GAEH,CAGF,GAAI,CACF,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,aAAa,EAAO,OAAO,YAAY,CAAC,CACnE,MAAM,GACJ,EACA,EAAO,IAAK,GAAU,CAAC,EAAO,EAAc,EAAM,OAAO,GAAG,CAAC,CAC9D,CACD,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,wBAAwB,EAAO,OAAO,YAAY,CAChE,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,mBAAmB,EAAO,OAAO,gBAAgB,EAAI,UACtD,CACF,CAGH,MAAO,CAAC,ECpIV,MAAM,GAAa,IASnB,eAAsB,GACpB,EACA,EACA,EACe,CAGf,MAAM,EAFSC,EAAM,EAAS,IAAW,CAEjB,KAAO,IAAe,CAC5C,MAAM,EAGH,EAAQ,GAA4B,CACrC,WACA,aACD,CAAC,EACF,CCZJ,eAAsB,GAA0B,CAC9C,iBACA,OACA,aACA,WAAW,CACTC,EAAAA,cAAc,UACdA,EAAAA,cAAc,YACdA,EAAAA,cAAc,QACdA,EAAAA,cAAc,UACdA,EAAAA,cAAc,UACdA,EAAAA,cAAc,UACdA,EAAAA,cAAc,QACdA,EAAAA,cAAc,mBACf,CACD,iBACA,kBACA,cAAc,IACd,eAAeC,EAAAA,GAkBG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAIC,EAAAA,QAAY,UAClC,EAAE,CACFA,EAAAA,QAAY,QAAQ,eACrB,CAGK,EAAc,MAAM,EAAiB,EAAQ,CACjD,QAAS,EACT,WACA,kBACA,iBACA,SAAU,GACV,aACD,CAAC,CAGF,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,YAAY,EAAY,OAAO,mBAAmB,CAClE,CAED,IAAI,EAAQ,EACZ,EAAY,MAAM,EAAY,OAAQ,EAAE,CACxC,MAAM,EACJ,EACA,KAAO,IAAwB,CAC7B,MAAM,EAAmB,EAAQ,GAAwB,CACvD,MAAO,CACL,GAAI,EAAoB,GACxB,SAAU,GACX,CACF,CAAC,CAEF,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SAAS,CACR,EASvB,OAPA,EAAA,EAAO,KACL,EAAA,QAAO,MACL,uBAAuB,EAAM,+BAC3B,EAAY,IACb,YACF,CACF,CACM,EAAY,OCpFrB,eAAsB,GACpB,EACA,EACwB,CAExB,IAAM,GAAA,EAAA,EAAA,WAA4B,EAAW,CAAC,OAC3C,GAAS,CAAC,EAAM,SAAS,cAAe,EAAK,CAC/C,CAGK,EACJ,EAAgB,SAAW,EACvB,EAAE,CAEF,MAAM,EAAA,QAAS,OAGb,EAAgB,IAAK,GAAS,CAC5B,IAAM,EAAQC,GAAU,EAAK,QAAQ,aAAc,GAAG,CAAC,CACjD,EAAU,GACd,EACA,EACA,GAAY,GACZ,CAAC,CAAC,GAAkB,GACrB,CACD,MAAO,CACL,OACA,QAAS,4DAA4D,IACrE,KAAM,OACN,QAAS,EAAQ,GACjB,QAAS,EACV,EACD,CACH,CAOP,OALA,MAAM,QAAQ,KAAA,EAAA,EAAA,YACD,EAAc,CAAC,KAAK,CAAC,EAAG,KACjC,EAAM,SAAS,EAAG,cAAe,EAAE,CACpC,CACF,CACM,ECtCT,eAAsB,GACpB,EACA,EACA,CACE,QACA,iBAOa,CAEf,IAAM,EAAiB,GACrB,EAAM,SAAS,cAAe,EAAU,EAAI,EAAc,GAGtD,CAAE,oBAAqB,MAAM,EAGhC,EAAQ,GAAc,CAGzB,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,oDAAoD,CACpE,CACD,IAAM,EACJ,MAAM,EACJ,EAAyB,EAAU,EAAc,EAAW,YAAY,CAAC,CACzE,OAAO,OAAOC,EAAAA,cAAc,CAC5B,EAAM,SAAS,6BAA6B,CAC7C,CACH,MAAM,EAAM,SACV,EACA,6BACD,CAGD,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,6CAA6C,CAAC,CACzE,IAAM,EACJ,MAAM,EACJ,EAAyB,EAAU,EAAc,EAAW,YAAY,CAAC,CACzE,EAAiB,KAAK,CAAE,UAAW,EAAK,CACxC,EAAM,SAAS,2BAA2B,CAC3C,CACH,MAAM,EAAM,SAAS,EAA0B,2BAA2B,CAG1E,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,4CAA4C,CAAC,CACxE,IAAM,EAAmD,MAAM,EAC7D,EAAyB,EAAU,EAAc,EAAW,OAAO,CAAC,CACpE,OAAO,OAAOC,EAAAA,WAAW,CACzB,EAAM,SAAS,mBAAmB,CACnC,CACD,MAAM,EAAM,SAAS,EAAkB,mBAAmB,CAC1D,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,oDAAoD,CACpE,CAGD,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,oDAAoD,CACpE,CACD,IAAM,EAAsB,EAAc,EAAW,cAAc,CAC7D,EAGJ,IAAwB,EACpB,EAAE,CACF,MAAM,EACJ,EAAyB,EAAU,EAAoB,CACvD,CAAC,GAAG,OAAO,OAAOC,EAAAA,uBAAuB,CAAE,EAAK,CAChD,EAAM,SAAS,wBAAwB,CACxC,CACP,MAAM,EAAM,SAAS,EAAuB,wBAAwB,CAGpE,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,6CAA6C,CAAC,CACzE,IAAM,EAAgB,EAAc,EAAW,QAAQ,CACjD,EAGJ,IAAkB,EACd,EAAE,CACF,MAAM,EACJ,EAAyB,EAAU,EAAc,CACjD,CAAC,GAAG,OAAO,OAAOC,EAAAA,eAAe,CAAE,EAAK,CACxC,EAAM,SAAS,kBAAkB,CAClC,CACP,MAAM,EAAM,SAAS,EAAiB,kBAAkB,CAGxD,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,0DAA0D,CAC1E,CACD,IAAM,EAA2B,EAAc,EAAW,mBAAmB,CACvE,EAGJ,IAA6B,EACzB,EAAE,CACF,MAAM,EACJ,EAAyB,EAAU,EAAyB,CAC5D,CAAC,GAAG,OAAO,OAAOC,EAAAA,0BAA0B,CAAE,EAAK,CACnD,EAAM,SAAS,6BAA6B,CAC7C,CACP,MAAM,EAAM,SACV,EACA,6BACD,CCxGH,MAAa,GAA2BC,EAAE,OACxCA,EAAE,OACFA,EAAE,MACAA,EAAE,aAAa,CACbA,EAAE,KAAK,CAEL,MAAOA,EAAE,OACV,CAAC,CACFA,EAAE,QAAQ,CAER,KAAMA,EAAE,OACT,CAAC,CACH,CAAC,CACH,CACF,CAOY,GAAsBA,EAAE,aAAa,CAChDA,EAAE,KAAK,CAEL,MAAOA,EAAE,OAET,yBAA0B,GAE1B,eAAgBA,EAAE,OAElB,aAAA,EAAA,EAAA,UAAsBC,EAAAA,cAAc,CAEpC,YAAaD,EAAE,OAChB,CAAC,CACFA,EAAE,QAAQ,CAER,SAAA,EAAA,EAAA,UAAkBE,EAAAA,eAAe,CAEjC,oBAAA,EAAA,EAAA,UAA6BC,EAAAA,0BAA0B,CAEvD,WAAYH,EAAE,MAAM,GAAqB,CAEzC,QAAA,EAAA,EAAA,UAAiBI,EAAAA,uBAAuB,CAExC,UAAWC,EAAAA,kBAEX,YAAaL,EAAE,MAAMA,EAAE,OAAO,CAE9B,QAAA,EAAA,EAAA,UAAiBM,EAAAA,WAAW,CAC7B,CAAC,CACH,CAAC,CAaF,SAAgB,GACd,EACA,EACA,EACQ,CAER,GAAI,IAAmBC,EAAAA,eAAe,MACpC,OAAO,EAAgB,aAAa,CAItC,GAAI,IAAmBA,EAAAA,eAAe,MAAO,CAC3C,IAAM,EAAa,EAChB,QAAQC,EAAAA,uBAAwB,GAAG,CACnC,QAAQ,QAAS,GAAG,CACpB,QAAQ,OAAQ,GAAG,CACnB,QAAQ,OAAQ,GAAG,CACnB,QAAQ,QAAS,GAAG,CACpB,QAAQ,YAAa,GAAG,CAC3B,OAAQ,EAEJ,EAAW,WAAW,IAAI,CAC1B,EACA,IAAI,IAA0B,IAH9B,GAKN,OAAO,EAaT,SAAgB,GACd,EACA,EACA,CACE,gBACA,oBACA,mBACA,uBACA,0BAA0B,KAaqB,CAEjD,IAAM,EAAiB,GACrB,EAAM,SAAS,cAAe,EAAU,EAAI,EAAc,GAC5D,OAAO,EAAc,IAClB,GAAyD,CAExD,IAAM,EAAqD,EAAE,CAC7D,OAAO,QAAQ,EAAkB,CAE9B,QAAQ,EAAG,KAAgB,IAAe,EAAK,CAC/C,SAAS,CAAC,EAAgB,KAAgB,CAEzC,IAAM,EAAiB,OAAO,OAAOD,EAAAA,eAAe,CAAC,SACnD,EACD,CACI,EACDA,EAAAA,eAAe,OAGb,EAAkB,EAAM,GAC9B,GAAI,EAAiB,CACnB,IAAM,EAAa,GACjB,EACA,EACA,EACD,CACG,IAEG,EAAyB,KAC5B,EAAyB,GAAkB,EAAE,EAI/C,EAAyB,GAAiB,KAAK,CAC7C,MAAO,EACP,KAAM,EACP,CAAC,IAGN,CAGJ,IAAM,EAAqC,EAAE,CAC7C,OAAO,QAAQ,EAAiB,CAE7B,QAAQ,EAAG,KAAgB,IAAe,EAAK,CAC/C,SAAS,CAAC,EAAe,KAAgB,CAExC,IAAM,EAAuB,EAAM,GACnC,GAAI,EAAsB,CAExB,IAAM,EACJ,EAAqB,KAAM,GAAS,EAAK,OAAS,EAAc,EAC5D,OAAS,eACf,EAAW,KAAK,CACd,OAAQ,EACJ,GAAe,EAAqB,CACpC,EACJ,IAAK,EACN,CAAC,GAEJ,CAEJ,IAAM,EAAoB,EAAc,EAAW,YAAY,CACzD,EAAwB,EAAc,EAAW,YAAY,CACnE,MAAO,CACL,EACA,CACE,MAAO,EAAM,EAAc,EAAW,MAAM,EAC5C,2BACA,aACA,eAAgB,EAAM,EAAc,EAAW,eAAe,EAC9D,YACE,IAAsB,GAClB,EAAM,SAAS,6BAA8B,GAAM,CACnD,EAAM,SACJ,6BACA,EAAM,GACP,CACP,YACE,IAA0B,GACtB,EAAM,SAAS,2BAA4B,GAAM,CACjD,EAAM,SACJ,2BACA,EAAM,GACP,CACP,GAAI,EAAc,EAAW,OAAO,GAAK,GACzC,EAAM,EAAc,EAAW,OAAO,EAClC,CACE,OAAQ,EAAM,SACZ,mBACA,EAAM,EAAc,EAAW,OAAO,EACvC,CACF,CACD,EAAE,CACN,GAAI,EAAc,EAAW,QAAQ,GAAK,GAC1C,EAAM,EAAc,EAAW,QAAQ,EACnC,CACE,QAAS,EAAM,SACb,kBACA,EAAM,EAAc,EAAW,QAAQ,EACxC,CACF,CACD,EAAE,CACN,GAAI,EAAc,EAAW,mBAAmB,GAAK,GACrD,EAAM,EAAc,EAAW,mBAAmB,EAC9C,CACE,mBAAoB,EAAM,SACxB,6BACA,EAAM,EAAc,EAAW,mBAAmB,EACnD,CACF,CACD,EAAE,CACN,GAAI,EAAc,EAAW,cAAc,GAAK,GAChD,EAAM,SACJ,wBACA,EAAM,EAAc,EAAW,cAAc,EAC9C,GAAK,GACN,EAAM,EAAc,EAAW,cAAc,EACzC,CACE,OAAQ,EAAM,SACZ,wBACA,EAAM,EAAc,EAAW,cAAc,EAC9C,CACF,CACD,EAAE,CACN,GAAI,EAAc,EAAW,UAAU,GAAK,GAC5C,EAAM,EAAc,EAAW,UAAU,EACrC,CACE,UAAW,IAAI,KAAK,EAAM,EAAc,EAAW,UAAU,EAAE,CAChE,CACD,EAAE,CACN,GAAI,EAAc,EAAW,YAAY,GAAK,GAC9C,EAAM,EAAc,EAAW,YAAY,EACvC,CACE,YAAa,GACX,EAAM,EAAc,EAAW,YAAY,EAC5C,CACF,CACD,EAAE,CACP,CACF,EAEJ,CCjSH,MAAa,GAAcE,EAAE,KAAK,CAEhC,eAAgBA,EAAE,OAElB,GAAIA,EAAE,OACP,CAAC,CAKW,GAAsBA,EAAE,KAAK,CAExC,YAAaA,EAAE,OAEf,MAAOA,EAAE,MAAM,CAACA,EAAE,KAAMA,EAAE,OAAO,CAAC,CAElC,SAAUA,EAAE,OAEZ,KAAMA,EAAE,OAER,SAAUA,EAAE,OAEZ,UAAWA,EAAE,KAAK,CAEhB,GAAIA,EAAE,OAEN,MAAOA,EAAE,MAAM,CAAC,GAAaA,EAAE,KAAK,CAAC,CAErC,YAAaA,EAAE,MAAM,CAAC,GAAaA,EAAE,KAAK,CAAC,CAE3C,KAAMA,EAAE,OAER,KAAMA,EAAE,OAER,WAAYA,EAAE,MAAM,EAAA,EAAA,EAAA,UAAUC,EAAAA,oBAAoB,CAAED,EAAE,KAAK,CAAC,CAE5D,SAAUA,EAAE,KAAK,CAEf,GAAIA,EAAE,OAEN,MAAOA,EAAE,OAET,YAAaA,EAAE,OAEf,KAAMA,EAAE,OAER,UAAWA,EAAE,MAAM,CAACA,EAAE,OAAQA,EAAE,KAAK,CAAC,CACvC,CAAC,CAEF,KAAMA,EAAE,MAAMA,EAAE,OAAO,CACxB,CAAC,CACH,CAAC,CAKW,GAA8BA,EAAE,KAAK,CAEhD,MAAOA,EAAE,MAAM,GAAoB,CAEnC,WAAYA,EAAE,OAEd,OAAQA,EAAE,QAAQ,CAEhB,KAAMA,EAAE,MAAM,CAACA,EAAE,OAAQA,EAAE,KAAK,CAAC,CAEjC,SAAUA,EAAE,MAAM,CAACA,EAAE,OAAQA,EAAE,KAAK,CAAC,CACtC,CAAC,CACH,CAAC,CAgBF,eAAsB,GACpB,EACA,CACE,SACA,cAAc,EACd,QAAQ,KASiE,CAC3E,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,6BAA6B,EAAS,OAAO,WAAW,CACxE,CAGD,IAAM,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAIE,EAAAA,QAAY,UAClC,EAAE,CACFA,EAAAA,QAAY,QAAQ,eACrB,CAGG,EAAQ,EACZ,EAAY,MAAM,EAAS,OAAQ,EAAE,CAGrC,IAAM,EAAU,MAAM,EACpB,EACA,KACE,IAGG,CACH,IAAM,EAAsC,EAAE,CAG1C,EAAiB,GACjB,EAAS,EACb,KAAO,GAAgB,CACrB,IAAI,EACJ,GAAI,CAcF,GAAA,EAAA,EAAA,aAAuB,GAXH,MAAM,EACvB,IACC,2BAA2B,EAAkB,GAAG,gBAChD,CACE,aAAc,CACZ,QACA,SACD,CACF,CACF,CACA,MAAM,CACuD,CAChE,EAAa,KAAK,GAAG,EAAS,MAAM,CAGpC,GAAU,EACV,EAEE,CAAC,CAAC,EAAS,OAAO,MAAQ,EAAS,MAAM,SAAW,QAC/C,EAAK,CACZ,MAAU,MACR,kCACE,GAAK,UAAU,MAAQ,GAAK,UAE/B,EAML,MAFA,IAAS,EACT,EAAY,OAAO,EAAM,CAClB,CAAC,EAAmB,EAAa,EAE1C,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SAAS,CACR,EAUvB,OARA,EAAA,EAAO,KACL,EAAA,QAAO,MACL,yCAAyC,EAAS,OAAO,gBACvD,EAAY,IACb,YACF,CACF,CAEM,ECjLT,eAAsB,GACpB,EACA,CACE,YACA,SACA,mBACA,cAAc,IAWD,CAEf,MAAM,EACJ,EACA,KAAO,IAAa,CAClB,GAAI,CAEF,MAAM,EACH,IAAI,WAAY,CACf,aAAc,CACZ,YAAa,EAAS,YACvB,CACF,CAAC,CACD,QAAQ,CACR,KAAM,GAAiB,EAAiB,EAAU,EAAa,CAAC,OAC5D,EAAK,CACZ,GAAI,GAAK,UAAU,MAAM,SAAS,sBAAsB,CAAE,CACxD,EAAA,EAAO,MACL,EAAA,QAAO,IACL,4BAA4B,EAAS,SAAS,YAAY,EAAU,oLAIrE,CACF,CACD,OAEF,MAAU,MACR,kCACE,GAAK,UAAU,MAAQ,GAAK,UAE/B,GAGL,CACE,cACD,CACF,CC5CH,eAAsB,GAA4B,CAChD,OACA,aACA,aACA,kBACA,aACA,iBACA,WAAW,CAACC,EAAAA,cAAc,UAAWA,EAAAA,cAAc,aAAa,CAChE,cAAc,EACd,eAAeC,EAAAA,EACf,uBAAuB,IAsBL,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAS,MAAM,GAAwB,EAAc,EAAM,EAAW,EAGxE,EAAA,EAAA,YAAY,EAAW,GACzB,EAAA,EAAA,WAAU,EAAW,CAIvB,IAAM,EAAc,MAAM,EAAiB,EAAQ,CACjD,QAAS,CAACC,EAAAA,cAAc,OAAO,CAC/B,kBACA,iBACA,WACA,aACD,CAAC,CAGI,EAAsB,MAAM,GAChC,EACA,CACE,SACA,cACD,CACF,CAGK,EAAK,IAAI,MAAM,CAAC,SAAS,CACzB,EAAc,IAAIC,EAAAA,QAAY,UAClC,EAAE,CACFA,EAAAA,QAAY,QAAQ,eACrB,CACG,EAAQ,EACR,EAAgB,EACpB,EAAY,MAAM,EAAY,OAAQ,EAAE,CAGxC,MAAM,EACJ,EACA,MAAO,CAAC,EAAS,KAAc,CAE7B,IAAM,GAAA,EAAA,EAAA,MAAqB,EAAY,EAAQ,GAAG,EAC9C,EAAA,EAAA,YAAY,EAAc,GAC5B,EAAA,EAAA,WAAU,EAAc,CAI1B,MAAM,GAA0B,EAAU,CACxC,SACA,UAAW,EAAQ,GACnB,kBAAmB,EAAK,IAAW,CAGjC,IAAM,GAAA,EAAA,EAAA,MAAgB,EAAe,EAAI,SAAS,CAC5C,GAAA,EAAA,EAAA,SAAiB,EAAS,EAC5B,EAAA,EAAA,YAAY,EAAO,GACrB,EAAA,EAAA,WAAU,EAAQ,CAAE,UAAW,GAAM,CAAC,EAIxC,EAAA,EAAA,eAAc,EAAU,EAAO,EAElC,CAAC,CAGE,GAAwB,EAAQ,SAAWH,EAAAA,cAAc,YAC3D,MAAM,EAAmB,EAAQ,GAAyB,CACxD,MAAO,CAAE,UAAW,EAAQ,GAAI,CACjC,CAAC,CACF,GAAiB,GAInB,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SAAS,CACR,EAcvB,OAZA,EAAA,EAAO,KACL,EAAA,QAAO,MACL,2BAA2B,EAAM,gBAC/B,EAAY,IACb,YACF,CACF,CACG,EAAgB,GAClB,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,YAAY,EAAc,yBAAyB,CACjE,CAEI,EAAY,OC9IrB,MAAa,GAAyBI,EAAE,KAAK,CAC3C,GAAIA,EAAE,OACN,KAAMA,EAAE,OACR,QAAA,EAAA,EAAA,UAAiBC,EAAAA,cAAc,CAC/B,MAAA,EAAA,EAAA,UAAeC,EAAAA,cAAc,CAC7B,YAAaF,EAAE,OACf,MAAOA,EAAE,MAAM,CAACA,EAAE,KAAMA,EAAE,OAAO,CAAC,CAClC,eAAgBA,EAAE,OAClB,SAAUA,EAAE,QACZ,OAAQA,EAAE,QACV,QAASA,EAAE,MAAM,CAACA,EAAE,MAAA,EAAA,EAAA,UAAeG,EAAAA,eAAe,CAAC,CAAC,CACpD,mBAAoBH,EAAE,MAAM,CAACA,EAAE,MAAA,EAAA,EAAA,UAAeI,EAAAA,0BAA0B,CAAC,CAAC,CAC1E,gBAAiBJ,EAAE,MACjBA,EAAE,KAAK,CACL,aAAcA,EAAE,KAAK,CAAE,KAAMA,EAAE,OAAQ,CAAC,CACxC,KAAMA,EAAE,OACT,CAAC,CACH,CACF,CAAC,CAaF,eAAsB,GACpB,EACA,EACA,CACE,UAAU,GACV,SAAS,GACT,kBAAkB,GAClB,qBAAqB,GACrB,WAAW,GACX,uBAAuB,EAAE,EAcvB,EAAE,CAC2B,CAGjC,IAAM,EAAmB,CAAC,GAAG,EAAqB,EACjD,EAAM,YAAc,EAAE,EAAE,QAAS,GAAc,CAC9C,IAAM,EAAW,EAAiB,KAC/B,GAAS,EAAK,MAAQ,EAAU,IAClC,CACG,GACF,EAAS,OAAO,KAAK,GAAG,EAAU,OAAO,CACzC,EAAS,OAASK,EAAK,EAAS,OAAO,EAEvC,EAAiB,KAAK,EAAU,EAElC,CAGF,IAAI,EACJ,GAAI,CACF,EAAW,MAAM,EACd,KAAK,0BAA2B,CAC/B,KAAM,CACJ,KAAM,EAAM,YACZ,QAAS,CACP,eAAgB,EAAM,eACtB,MAAO,EAAM,MACb,kBACA,yBAA0B,EAAM,yBACjC,CACD,YAAa,EAAM,YACnB,WACA,SACA,qBACA,GAAI,EAAM,OAAS,CAAE,OAAQ,EAAM,OAAQ,CAAG,EAAE,CAChD,UACA,WAAY,EACZ,GAAI,EAAM,SAAW,EAAM,mBACvB,CACE,OAAQ,CACN,GAAI,EAAM,QACN,CACE,QAAS,EAAM,QAChB,CACD,EAAM,mBACN,CAAE,QAAS,EAAM,mBAAmB,MAAM,IAAI,CAAC,GAAI,CACnD,EAAE,CACN,GAAI,EAAM,mBACN,CAAE,mBAAoB,EAAM,mBAAoB,CAChD,EAAE,CACP,CACF,CACD,EAAE,CACN,GAAI,EAAM,UAAY,CAAE,UAAW,EAAM,UAAW,CAAG,EAAE,CACzD,GAAI,EAAM,YAAc,CAAE,YAAa,EAAM,YAAa,CAAG,EAAE,CAC/D,GAAI,EAAM,OAAS,CAAE,uBAAwB,EAAM,OAAQ,CAAG,EAAE,CACjE,CACF,CAAC,CACD,MAAM,OACF,EAAK,CACZ,MAAU,MACR,kCAAkC,GAAK,UAAU,MAAQ,GAAK,UAC/D,CAGH,GAAM,CAAE,QAAS,IAAA,EAAA,EAAA,aACfL,EAAE,KAAK,CACL,QAAS,GACV,CAAC,CACF,EACD,CACD,OAAO,EClHT,eAAsB,GAAuB,CAC3C,iBACA,iBACA,OACA,mBACA,iBACA,kBACA,cAAc,GACd,eAAeM,EAAAA,GAkBG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAIC,EAAAA,QAAY,UAClC,EAAE,CACFA,EAAAA,QAAY,QAAQ,eACrB,CAGK,EAAc,MAAM,EAAiB,EAAQ,CACjD,QAAS,EACT,SAAU,CAACC,EAAAA,cAAc,UAAU,CACnC,iBACA,QAAS,EACT,kBACD,CAAC,CAGF,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,cAAc,EAAY,OAAO,aAAa,CAAC,CAE1E,IAAI,EAAQ,EACR,EAAU,EACd,EAAY,MAAM,EAAY,OAAQ,EAAE,CACxC,MAAM,EACJ,EACA,KAAO,IAAqB,CAIxB,GACA,IAAI,KAAK,EAAiB,CAAG,IAAI,KAAK,EAAiB,UAAU,EAEjE,MAAM,EAAmB,EAAQ,GAAwB,CACvD,MAAO,CACL,GAAI,EAAiB,GACrB,SAAU,GACX,CACF,CAAC,CAGJ,GAAI,CAEF,MAAM,EAAmB,EAAQ,GAAyB,CACxD,MAAO,CAAE,UAAW,EAAiB,GAAI,CAC1C,CAAC,OACK,EAAK,CACR,EAAI,QAAQ,SAAS,yCAAyC,GAChE,GAAW,GAIf,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SAAS,CACR,EAWvB,OAVI,EAAU,GACZ,EAAA,EAAO,KAAK,EAAA,QAAO,OAAO,GAAG,EAAQ,yBAAyB,CAAC,CAEjE,EAAA,EAAO,KACL,EAAA,QAAO,MACL,yBAAyB,EAAM,gBAC7B,EAAY,IACb,YACF,CACF,CACM,EAAY,OCvGrB,eAAsB,GAAoC,CACxD,iBAAiB,OAAO,OAAOC,EAAAA,cAAc,CAC7C,OACA,aACA,kBACA,OAAO,GACP,WAAW,GACX,iBACA,gBAAgB,yBAChB,cAAc,IACd,eAAeC,EAAAA,GAyBG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAIC,EAAAA,QAAY,UAClC,EAAE,CACFA,EAAAA,QAAY,QAAQ,eACrB,CAIK,GADoB,MAAM,GAAkB,EAAQ,EAAc,EAC3B,KAC1C,GAAa,EAAS,QAAU,EAClC,CACD,GAAI,CAAC,EACH,MAAU,MAAM,0CAA0C,EAAc,GAAG,CAI7E,IAAI,EAAc,MAAM,EAAiB,EAAQ,CAC/C,QAAS,EACT,kBACA,iBACA,SAAU,GACV,SAAU,GACV,aACD,CAAC,CAGF,EAAc,EAAY,OACvB,GACC,OAAO,EAAQ,eAAkB,UACjC,EAAQ,cAAgB,EAC3B,CAGD,EAAA,EAAO,KACL,EAAA,QAAO,QACL,cAAc,EAAY,OAAO,6BAClC,CACF,CAED,IAAI,EAAQ,EACZ,EAAY,MAAM,EAAY,OAAQ,EAAE,CACxC,MAAM,EACJ,EACA,KAAO,IAAoB,CACzB,MAAM,EAAmB,EAAQ,GAAwB,CACvD,MAAO,CACL,UAAW,EAAgB,GAC3B,SAAU,EAAmB,SAAS,eACtC,QAAS,EAAmB,QAAQ,eACpC,eAAgB,EACjB,CACF,CAAC,CAEF,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SAAS,CACR,EASvB,OAPA,EAAA,EAAO,KACL,EAAA,QAAO,MACL,uBAAuB,EAAM,+BAC3B,EAAY,IACb,YACF,CACF,CACM,EAAY,OC5GrB,eAAsB,GACpB,EACA,EACA,EAC4B,CAE5B,GAAM,CAAE,eAAgB,MAAM,EAG3B,EAAQ,GAAY,CAGjB,EAAkB,EAAY,YAAY,QAC7C,CAAE,UACD,CAAC,EAAM,SAAS,kBAAmB,EAAK,EACxC,CAAC,GAAsB,SAAS,EAAK,CACxC,CAGK,EACJ,EAAgB,SAAW,EACvB,EAAE,CAEF,MAAM,EAAA,QAAS,OAGb,EAAgB,KAAK,CAAE,UAAW,CAChC,IAAM,EAAU,GAAkB,EAAa,EAAM,GAAM,CAC3D,MAAO,CACL,OACA,QAAS,iEAAiE,IAC1E,KAAM,OACN,QAAS,EAAQ,GACjB,QAAS,EACV,EACD,CACH,CAOP,OANA,MAAM,QAAQ,IACZ,OAAO,QAAQ,EAAkB,CAAC,KAAK,CAAC,EAAG,KACzC,EAAM,SAAS,EAAG,kBAAmB,EAAE,CACxC,CACF,CAEM,CACL,GAAG,EAAM,SAAS,kBAAkB,CACpC,GAAG,EACJ,CChDH,eAAsB,GAAsB,CAC1C,iBACA,oBACA,OACA,aACA,mBACA,kBACA,iBACA,WAAW,CACTC,EAAAA,cAAc,UACdA,EAAAA,cAAc,YACdA,EAAAA,cAAc,QACdA,EAAAA,cAAc,UACdA,EAAAA,cAAc,UACdA,EAAAA,cAAc,UACdA,EAAAA,cAAc,QACdA,EAAAA,cAAc,mBACf,CACD,cAAc,GACd,eAAeC,EAAAA,GAsBG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAIC,EAAAA,QAAY,UAClC,EAAE,CACFA,EAAAA,QAAY,QAAQ,eACrB,CAGG,EACJ,GAAI,EAAmB,CAKrB,IAAM,GAJoB,MAAM,GAC9B,EACA,EACD,EACyC,KACvC,GAAa,EAAS,QAAU,EAClC,CACD,GAAI,CAAC,EACH,MAAU,MACR,0CAA0C,EAAkB,GAC7D,CAEH,EAAsB,EAIxB,IAAM,EAAc,MAAM,EAAiB,EAAQ,CACjD,QAAS,EACT,kBACA,iBACA,WACA,aACD,CAAC,CAGF,EAAA,EAAO,KACL,EAAA,QAAO,QACL,cAAc,EAAY,OAAO,YAC/B,EACI,oBAAoB,EAAoB,QACxC,GACL,GACF,CACF,CAED,IAAI,EAAQ,EACZ,EAAY,MAAM,EAAY,OAAQ,EAAE,CACxC,MAAM,EACJ,EACA,KAAO,IAAoB,CAIvB,GACA,IAAI,KAAK,EAAiB,CAAG,IAAI,KAAK,EAAgB,UAAU,EAEhE,MAAM,EAAmB,EAAQ,GAAwB,CACvD,MAAO,CACL,GAAI,EAAgB,GACpB,SAAU,GACX,CACF,CAAC,CAIJ,MAAM,EAAmB,EAAQ,GAAwB,CACvD,MAAO,CACL,UAAW,EAAgB,GAC3B,GAAI,EACA,CACE,QAAS,OAAO,EAAoB,QAAQ,iBAC5C,SAAU,EAAoB,SAAS,eACxC,CACD,EAAE,CACP,CACF,CAAC,CAEF,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SAAS,CACR,EASvB,OAPA,EAAA,EAAO,KACL,EAAA,QAAO,MACL,yBAAyB,EAAM,gBAC7B,EAAY,IACb,YACF,CACF,CACM,EAAY,OCzIrB,eAAsB,GACpB,EACA,EACA,EACA,EAC2B,CAE3B,IAAM,EAAkB,EAAqB,QAC1C,CAAE,UAAW,CAAC,EAAM,SAAS,iBAAkB,EAAK,CACtD,CAGK,EACJ,EAAgB,SAAW,EACvB,EAAE,CAEF,MAAM,EAAA,QAAS,OAGb,EAAgB,KAAK,CAAE,UAAW,CAChC,IAAM,EAAU,GAAkB,EAAa,EAAM,GAAM,CAC3D,MAAO,CACL,OACA,QAAS,gEAAgE,IACzE,KAAM,OACN,QAAS,EAAQ,GACjB,QAAS,EACV,EACD,CACH,CAOP,OANA,MAAM,QAAQ,IACZ,OAAO,QAAQ,EAAiB,CAAC,KAAK,CAAC,EAAG,KACxC,EAAM,SAAS,EAAG,iBAAkB,EAAE,CACvC,CACF,CAEM,CACL,GAAG,EAAM,SAAS,iBAAiB,CACnC,GAAG,EACJ,CChEH,MAAM,GAAe,8BAQrB,SAAgB,GAAmB,EAA4B,CAC7D,OAAO,GAAa,KAAK,EAAI,CAAG,GAAa,KAAK,EAAI,CAAE,GAAK,KCuB/D,eAAsB,GAA6B,CACjD,gBACA,uBACA,OACA,OACA,aACA,cAAc,IACd,0BAA0B,IAC1B,eAAeC,EAAAA,EACf,aAAa,EAAE,CACf,kBAAkB,GAClB,iBAAiB,GACjB,qBAAqB,GACrB,SAAS,GACT,WAAW,GACX,QAAQ,GACR,SAAS,IAkCO,CAEhB,IAAM,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAIC,EAAAA,QAAY,UAClC,EAAE,CACFA,EAAAA,QAAY,QAAQ,eACrB,CAGK,EAAmB,GAA0B,EAAW,CAIxD,EAAQ,IAAIC,EAAAA,eAAe,EAAe,GAAiB,CAC/D,YAAa,EAAE,CACf,2BAA4B,EAAE,CAC9B,yBAA0B,EAAE,CAC5B,iBAAkB,EAAE,CACpB,sBAAuB,EAAE,CACzB,gBAAiB,EAAE,CACnB,eAAgB,EAAE,CAClB,2BAA4B,EAAE,CAC9B,gBAAiB,EAAE,CACpB,CAAC,CAGI,GAAA,EAAA,EAAA,MACJ,EACA,qBAAqB,IAAI,MAAM,CAAC,aAAa,CAAC,GAAG,EAC9C,MAAM,IAAI,CACV,KAAK,GAAG,QAAQ,OAAQ,QAAQ,CACpC,CACK,EAAe,IAAIA,EAAAA,eACvB,EACAC,GACA,CACE,mBAAoB,EAAE,CACtB,kBAAmB,EAAE,CACrB,gBAAiB,EAAE,CACpB,CACF,CAGK,EAAS,MAAM,GAAwB,EAAc,EAAM,EAAW,CAGtE,EAAe,GAAQ,EAAMC,EAAE,OAAOA,EAAE,OAAQA,EAAE,OAAO,CAAC,CAC1D,EAAcC,EAAK,EAAa,IAAK,GAAM,OAAO,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAGxE,GAAI,EAAa,SAAW,EAC1B,MAAU,MACR,oGACD,CAEH,GAAI,EAAO,CACT,IAAM,EAAe,EAAa,GAClC,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,kBAAkB,KAAK,UAAU,EAAc,KAAM,EAAE,GAAG,CAC1E,CAIH,IAAM,EAAsB,EACxB,EACA,MAAM,GAAW,EAAa,CAG5B,EAAS,EAA4B,EAAc,EAAK,CAExD,EAAuB,MAAM,GAA6B,EAAO,CAEjE,EAAgB,MAAM,GAAmB,EAAa,EAAM,CAC5D,EAAoB,MAAM,GAC9B,EACA,EACA,EACD,CACK,GAAmB,MAAM,GAC7B,EACA,EACA,EACA,EACD,CACD,MAAM,GAAqB,EAAQ,EAAqB,CACtD,QACA,gBACD,CAAC,CAGF,IAAM,EAAgB,GAA0B,EAAqB,EAAO,CAC1E,0BACA,gBACA,oBACA,oBACA,uBACD,CAAC,CAGG,GACH,EAAY,MAAM,EAAc,OAAQ,EAAE,CAE5C,IAAI,GAAQ,EAEZ,MAAM,EACJ,EACA,MAAO,CAAC,EAAQ,GAAe,IAAQ,CAErC,IAAM,EAAe,EACjB,SAAS,EAAa,MAAM,oBAAoB,EAAa,iBAC7D,OAAO,EAAI,UAAU,GAezB,GAbI,GACF,EAAA,EAAO,KACL,EAAA,QAAO,QACL,IAAI,EAAM,EAAE,GAAG,EAAc,OAAO,eAAe,KAAK,UACtD,EACA,KACA,EACD,GACF,CACF,CAIC,EAAQ,CACV,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,+CAA+C,CAC/D,CACD,OAGF,GAAI,CAEF,IAAM,EAAkB,MAAM,GAC5B,EACA,EACA,CACE,QAAS,oDAAoD,KAAK,UAChE,EACA,KACA,EACD,GACD,SACA,kBACA,qBACA,WACA,qBAAsB,EACvB,CACF,CAGG,IACF,EAAA,EAAO,KACL,EAAA,QAAO,MACL,IAAI,EAAM,EAAE,GACV,EAAc,OACf,2DAA2D,EAAa,GAC1E,CACF,CACD,EAAA,EAAO,KACL,EAAA,QAAO,MACL,IAAI,EAAM,EAAE,GAAG,EAAc,OAAO,iBAClC,EAAgB,KACjB,GACF,CACF,EAIH,IAAM,EAAqB,EAAa,SAAS,qBAAqB,CACtE,EAAmB,KAAK,CACtB,GAAI,EAAgB,GACpB,KAAM,EAAgB,KACtB,SAAU,EACV,eAAgB,EAAgB,eAChC,YAAa,IAAI,MAAM,CAAC,aAAa,CACtC,CAAC,CACF,MAAM,EAAa,SAAS,EAAoB,qBAAqB,OAC9D,EAAK,CACZ,IAAM,EAAM,GAAG,EAAI,QAAQ,KAAK,KAAK,UACnC,EAAI,UAAU,KACd,KACA,EACD,GACK,EAAc,GAAmB,EAAI,CAE3C,GACE,IAAgB,oDAChB,CACI,GACF,EAAA,EAAO,KACL,EAAA,QAAO,OACL,IAAI,EAAM,EAAE,GACV,EAAc,OACf,yCACF,CACF,CAEH,IAAM,EAAoB,EAAa,SAAS,oBAAoB,CACpE,EAAkB,KAAK,CACrB,eAAgB,EAAa,eAC7B,SAAU,EACV,YAAa,IAAI,MAAM,CAAC,aAAa,CACtC,CAAC,CACF,MAAM,EAAa,SAAS,EAAmB,oBAAoB,KAC9D,CACL,IAAM,EAAkB,EAAa,SAAS,kBAAkB,CAChE,EAAgB,KAAK,CACnB,GAAG,EACH,SAAU,EACV,MAAO,GAAe,EACtB,YAAa,IAAI,MAAM,CAAC,aAAa,CACtC,CAAC,CACF,MAAM,EAAa,SAAS,EAAiB,kBAAkB,CAC3D,IACF,EAAA,EAAO,MAAM,EAAA,QAAO,IAAI,GAAe,EAAI,CAAC,CAC5C,EAAA,EAAO,MACL,EAAA,QAAO,IACL,IAAI,EAAM,EAAE,GACV,EAAc,OACf,mCAAmC,EAAa,GAClD,CACF,GAKP,IAAS,EACJ,GACH,EAAY,OAAO,GAAM,EAG7B,CACE,cACD,CACF,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SAAS,CACR,EAGvB,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,wBAAwB,EAAY,IAAK,YAAY,CACnE,CAGG,EAAa,SAAS,oBAAoB,CAAC,OAAS,GACtD,EAAA,EAAO,KACL,EAAA,QAAO,OACL,gBACE,EAAa,SAAS,oBAAoB,CAAC,OAC5C,6BACS,EAAiB,sDAC5B,CACF,CAIC,EAAa,SAAS,kBAAkB,CAAC,OAAS,IACpD,EAAA,EAAO,MACL,EAAA,QAAO,IACL,gBACE,EAAa,SAAS,kBAAkB,CAAC,OAC1C,iBACS,EAAiB,4CAC5B,CACF,CACD,QAAQ,KAAK,EAAE,EC/UnB,eAAsB,GACpB,EACA,EACA,CACE,mBAAmB,GACnB,oBAAoB,GACpB,kBAAkB,GAClB,qBAAqB,EAAE,EAUrB,EAAE,CAC2B,CAEjC,IAAM,EAAW,MAAM,EACpB,KAAK,0BAA2B,CAC/B,KAAM,CACJ,KAAM,EAAQ,KACd,QAAS,CACP,eAAgB,EAAQ,eACxB,MAAO,EAAQ,MACf,kBACA,GAAI,EAAmB,OAAS,EAC5B,CACE,0BAAA,EAAA,EAAA,OACEC,GACE,EACG,OACE,GAEC,EACE,EAAG,OAAS,SAAW,EAAG,QAAU,EAAQ,QACzC,CAAC,GAAsB,SAAS,EAAG,KAAK,CAChD,CACA,IAAK,IAAQ,CACZ,GAAG,EACH,KAAM,OAAO,OAAOC,EAAAA,eAAe,CAAC,SAClC,EAAG,KACJ,CACG,EAAG,KACHA,EAAAA,eAAe,OACpB,EAAE,CACL,OACD,EACA,EAAQ,IACP,EAAO,KAAK,CAAE,OAAM,YAAa,CAC/B,GAAI,IAASA,EAAAA,eAAe,OAAS,CAAE,OAAM,CAAG,EAAE,CAClD,QACD,EAAE,CACN,CACF,CACD,EAAE,CACP,CACD,UAAW,EAAQ,GACnB,YAAa,EAAQ,YACrB,SAAU,EAAQ,SAClB,OAAQ,EAAQ,OAChB,OAAQ,EAAQ,OAChB,oBACA,UAAW,EAAQ,UACnB,QAAS,sDAAsD,EAAQ,UACvE,mBAAoB,CAAC,EACtB,CACF,CAAC,CACD,MAAM,CAEH,CAAE,QAAS,IAAA,EAAA,EAAA,aACfC,EAAE,KAAK,CACL,QAAS,GACV,CAAC,CACF,EACD,CACD,OAAO,EC1ET,MAAM,GAAeC,EAAE,aAAa,CAClC,GACAA,EAAE,KAAK,CACL,MAAOA,EAAE,OACV,CAAC,CACH,CAAC,CAMI,GAAqBA,EAAE,KAAK,CAChC,kBAAmBA,EAAE,MAAM,GAAkB,CAC7C,gBAAiBA,EAAE,MAAM,GAAa,CACvC,CAAC,CAOF,eAAsB,GAAoB,CACxC,uBACA,OACA,aACA,iBACA,kBACA,kBACA,iBACA,eAAeC,EAAAA,EACf,aAAa,EAAE,CACf,YAAY,IAAI,KAChB,mBACA,mBAAmB,GACnB,kBAAkB,GAClB,kBAAkB,GAClB,oBAAoB,GACpB,cAAc,IAkCE,CAEhB,IAAM,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAIC,EAAAA,QAAY,UAClC,EAAE,CACFA,EAAAA,QAAY,QAAQ,eACrB,CAGK,GAAA,EAAA,EAAA,MACJ,EACA,sBAAsB,IAAI,MAAM,CAAC,aAAa,CAAC,OAChD,CACK,EAAQ,IAAIC,EAAAA,eAAe,EAAW,GAAoB,CAC9D,kBAAmB,EAAE,CACrB,gBAAiB,EAAE,CACpB,CAAC,CAGI,EAAS,MAAM,GAAwB,EAAc,EAAM,EAAW,CAGtE,EAAS,EAA4B,EAAc,EAAK,CAQxD,GAPc,MAAM,EAAiB,EAAQ,CACjD,aACA,QAAS,EACT,SAAU,EACV,kBACA,iBACD,CAAC,EAC2B,OAC1B,GAAY,IAAI,KAAK,EAAQ,UAAU,CAAG,EAC5C,CAcD,GAbA,EAAA,EAAO,KAAK,SAAS,EAAS,OAAO,sBAAsB,CAEvD,GACF,EAAA,EAAO,KAAK,6DAA6D,CAEvE,GACF,EAAA,EAAO,KAAK,2DAA2D,CAErE,GACF,EAAA,EAAO,KAAK,+DAA+D,CAIzE,EAAW,OAAS,GAAK,EAAW,SAAW,EAAS,OAAQ,CAClE,IAAM,EAAkBC,EACtB,EACA,EAAS,KAAK,CAAE,QAAS,EAAG,CAC7B,CACG,EAAgB,OAAS,IAC3B,EAAA,EAAO,MACL,EAAA,QAAO,IACL,gDAAgD,EAAgB,KAC9D,IACD,CAAC,GACH,CACF,CACD,QAAQ,KAAK,EAAE,EAKnB,IAAI,EAAQ,EACZ,EAAY,MAAM,EAAS,OAAQ,EAAE,CACrC,MAAM,EACJ,EACA,MAAO,EAAS,IAAQ,CACtB,GAAI,CAEF,IAAM,EAAqB,EACvB,MAAM,GAA2B,EAAQ,EAAQ,CAC/C,UAAW,EAAQ,GACpB,CAAC,CACF,EAAE,CAGA,EAAkB,MAAM,GAC5B,EACA,CACE,GAAG,EAEH,SACI,GACF,IAAI,KAAK,EAAQ,UAAU,CAAG,EAC1B,GACA,EAAQ,SACf,CACD,CACE,qBACA,oBACA,mBACA,kBACD,CACF,CAGK,EAAoB,EAAM,SAAS,oBAAoB,CAC7D,EAAkB,KAAK,CACrB,GAAI,EAAgB,GACpB,KAAM,EAAgB,KACtB,SAAU,EACV,eAAgB,EAAgB,eAChC,YAAa,IAAI,MAAM,CAAC,aAAa,CACtC,CAAC,CACF,MAAM,EAAM,SAAS,EAAmB,oBAAoB,OACrD,EAAK,CACZ,IAAM,EAAM,GAAG,EAAI,QAAQ,KAAK,KAAK,UACnC,EAAI,UAAU,KACd,KACA,EACD,GACK,EAAc,GAAmB,EAAI,CAErC,EAAkB,EAAM,SAAS,kBAAkB,CACzD,EAAgB,KAAK,CACnB,GAAI,EAAQ,GACZ,KAAM,EAAQ,KACd,SAAU,EACV,eAAgB,EAAQ,eACxB,YAAa,IAAI,MAAM,CAAC,aAAa,CACrC,MAAO,GAAe,EACvB,CAAC,CACF,MAAM,EAAM,SAAS,EAAiB,kBAAkB,CAE1D,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SAAS,CACR,EAGvB,EAAA,EAAO,KACL,EAAA,QAAO,MACL,wCAAwC,EAAY,IAAK,YAC1D,CACF,CAGG,EAAM,SAAS,kBAAkB,CAAC,OAAS,IAC7C,EAAA,EAAO,MACL,EAAA,QAAO,IACL,gBAAgB,EAAM,SAAS,kBAAkB,CAAC,OAAO,kBAAA,EAAA,EAAA,SAErD,EACD,CAAC,4CACL,CACF,CACD,QAAQ,KAAK,EAAE,EC/NnB,eAAsB,GAAkB,CACtC,cACA,OACA,cAAc,IACd,eAAeC,EAAAA,GAYG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAGzB,EAAW,MAAM,EAAiB,EAAQ,CAC9C,SAAU,CAACC,EAAAA,cAAc,UAAU,CACpC,CAAC,CAGF,EAAA,EAAO,KACL,EAAA,QAAO,QACL,yBAAyB,EAAY,KAAK,IAAI,CAAC,aAC7C,EAAS,OACV,wBACF,CACF,CAGD,IAAM,EAAc,IAAIC,EAAAA,QAAY,UAClC,EAAE,CACFA,EAAAA,QAAY,QAAQ,eACrB,CAEG,EAAQ,EACZ,EAAY,MAAM,EAAS,OAAQ,EAAE,CACrC,IAAI,EAAe,EACnB,MAAM,EACJ,EACA,KAAO,IAAY,CAKjB,IAAM,GAHmB,MAAM,GAAyB,EAAQ,CAC9D,UAAW,EAAQ,GACpB,CAAC,EACgD,OAC/C,GACC,EAAY,SAAS,EAAS,SAAS,GAAG,EAC1C,CAAC,CACCC,EAAAA,sBAAsB,SACtBA,EAAAA,sBAAsB,QAEvB,CAAC,SAAS,EAAS,OAAc,CACrC,CAGG,EAAyB,OAAS,GACpC,MAAM,EAAU,EAA0B,KAAO,IAAoB,CACnE,GAAI,CACF,MAAM,EAGH,EAAQ,GAAuB,CAChC,kBAAmB,EAAgB,GACpC,CAAC,CACF,GAAgB,QACT,EAAK,CACZ,GACE,CAAC,EAAI,QAAQ,SACX,8EACD,CAED,MAAM,IAGV,CAEJ,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SAAS,CACR,EASvB,OAPA,EAAA,EAAO,KACL,EAAA,QAAO,MACL,yBAAyB,EAAa,UACpC,EAAS,OACV,iBAAiB,EAAY,IAAK,YACpC,CACF,CACM,EAAS,OCtGlB,eAAsB,GAAmB,CACvC,OACA,iBAAiB,EAAE,CACnB,kBACA,iBACA,eAAeC,EAAAA,EACf,0BAA0B,OAAO,OAAOC,EAAAA,sBAAsB,CAC9D,aAAa,EAAE,CACf,aACA,cAAc,IAoBE,CAEhB,IAAM,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAIC,EAAAA,QAAY,UAClC,EAAE,CACFA,EAAAA,QAAY,QAAQ,eACrB,CAGK,EAAS,EAA4B,EAAc,EAAK,CAE9D,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,kCAAkC,CAAC,CAE9D,IAAM,EAAW,MAAM,EAAiB,EAAQ,CAC9C,QAAS,EACT,SAAU,CAACC,EAAAA,cAAc,UAAU,CACnC,kBACA,iBACA,aACD,CAAC,CAEE,EAAiB,EAGrB,GAAI,EAAW,OAAS,GAAK,EAAW,SAAW,EAAS,OAAQ,CAClE,IAAM,EAAkBC,EACtB,EACA,EAAS,KAAK,CAAE,QAAS,EAAG,CAC7B,CACG,EAAgB,OAAS,IAC3B,EAAA,EAAO,MACL,EAAA,QAAO,IACL,gDAAgD,EAAgB,KAC9D,IACD,CAAC,GACH,CACF,CACD,QAAQ,KAAK,EAAE,EAKnB,IAAI,EAAQ,EACZ,EAAY,MAAM,EAAS,OAAQ,EAAE,CACrC,MAAM,EACJ,EACA,KAAO,IAAY,CAUjB,MAAM,GARmB,MAAM,GAAyB,EAAQ,CAC9D,UAAW,EAAQ,GACpB,CAAC,EACiD,OAChD,GACC,EAAgB,SAAS,KAAO,GAChC,EAAwB,SAAS,EAAgB,OAAO,CAC3D,CACoC,KAAO,IAAoB,CAC9D,MAAM,GAAqB,EAAQ,EAAgB,GAAG,CACtD,GAAkB,GAClB,CAGF,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SAAS,CACR,EAGvB,EAAA,EAAO,KACL,EAAA,QAAO,MACL,2BACE,EAAS,OACV,gBAAgB,EAAe,iBAC9B,EAAY,IACb,YACF,CACF,CClHH,eAAsB,GAAsB,CAC1C,iBACA,aACA,OACA,cAAc,GACd,eAAeC,EAAAA,GAYG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAIC,EAAAA,QAAY,UAClC,EAAE,CACFA,EAAAA,QAAY,QAAQ,eACrB,CAGK,EAAc,MAAM,EAAiB,EAAQ,CACjD,QAAS,EACT,SAAU,CAACC,EAAAA,cAAc,UAAWA,EAAAA,cAAc,UAAU,CAC7D,CAAC,CAGF,EAAA,EAAO,KACL,EAAA,QAAO,QACL,qCAAqC,EAAW,iBAAiB,EAAY,OAAO,aACrF,CACF,CAED,IAAI,EAAQ,EACR,EAAU,EACd,EAAY,MAAM,EAAY,OAAQ,EAAE,CACxC,MAAM,EACJ,EACA,KAAO,IAAqB,CAC1B,GAAI,CAMF,MAAM,EAGH,EAAQ,GAAyB,CAClC,mBATsB,MAAM,GAAqB,EAAQ,CACzD,UAAW,EAAiB,GAC5B,aACD,CAAC,EAMmC,GACpC,CAAC,OACK,EAAK,CAEZ,GAAI,CAAC,EAAI,QAAQ,SAAS,iCAAiC,CACzD,MAAM,EAER,GAAW,EAGb,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SAAS,CACR,EASvB,OAPA,EAAA,EAAO,KACL,EAAA,QAAO,MACL,uCACE,EAAY,IACb,gBAAgB,EAAM,aAAa,EAAQ,2EAC7C,CACF,CACM,EAAY,OC9ErB,eAAsB,GAAoB,CACxC,OACA,aACA,UAAU,EAAE,CACZ,WAAW,EAAE,CACb,mBACA,YAAY,IACZ,eAAeC,EAAAA,EACf,kBACA,yBAAyB,GACzB,iBACA,UA+BC,CAED,IAAM,EAAS,EAA4B,EAAc,EAAK,CACxD,EAAS,MAAM,GAAwB,EAAc,EAAM,EAAW,CAGxE,EAAY,GACZ,IACF,GAAa,WAAW,EAAgB,aAAa,IAEnD,IACF,GAAa,GACX,EAAY,QAAU,GACvB,SAAS,EAAe,aAAa,IAIxC,EAAA,EAAO,KACL,EAAA,QAAO,QACL,GACE,EAAQ,OAAS,EACb,6BAA6B,EAAQ,KAAK,QAAQ,CAAC,GACnD,yBACH,IACJ,CACF,CAGD,IAAM,EAAW,MAAM,EAAiB,EAAQ,CAC9C,UACA,KAAM,EACN,WACA,kBACA,iBACA,SACD,CAAC,CAGI,EAAiC,EACnC,EAAS,IAAK,IAAa,CACzB,GAAG,EACH,mBAAoB,EAAE,CACvB,EAAE,CACH,MAAM,EACJ,EACA,KAAO,IAAY,CACjB,IAAM,EAAqB,MAAM,GAC/B,EACA,EACA,CACE,UAAW,EAAQ,GACpB,CACF,CACD,MAAO,CACL,GAAG,EACH,qBACD,EAEH,CACE,YAAa,EACd,CACF,CAyEL,OAvEA,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,UAAU,EAA+B,OAAO,WAAW,CAC3E,CAqEM,CAAE,iCAAgC,wBAlE5B,EAA+B,KACzC,CACC,kBACA,qBACA,KACA,QACA,OACA,SACA,cACA,UACA,YACA,UACA,SACA,SACA,qBACA,WACA,OAAA,EACA,iBACA,UACA,GAAG,MACE,CACL,aAAc,EACd,aAAc,EACd,MAAO,EACP,kBAAmB,EACnB,eAAgB,EAChB,oBAAqB,EACrB,OAAQ,EACR,QAAS,EACT,uBAAwB,EACxB,QAAS,EACT,OAAQ,EACR,cAAe,EACf,kBAAmBC,EACnB,SAAU,EACV,uBAAwB,GAAS,OAAS,GAAS,MAAQ,GAC3D,wBAAyB,GAAS,SAAS,UAAU,EAAI,GACzD,IAAI,GAAS,qBAAuB,EAAE,EAAE,QAAQ,EAAK,IAAM,CACzD,IAAM,EAAQ,EAAE,iBAAiB,MAAM,gBAAkB,EAAE,KAC3D,OAAO,EACH,CACE,GAAG,GACF,GAAQ,EAAE,aACP,EAAE,aAAa,IAAK,GAAM,EAAE,KAAK,CAAC,KAAK,IAAI,CAC3C,EAAE,aAAa,MAAQ,EAAE,aAC9B,CACD,GACH,EAAE,CAAC,CACN,GAAG,EACH,GAAG,OAAO,QAAQC,GAAQ,EAAiB,oBAAoB,CAAC,CAAC,QAC9D,EAAK,CAAC,EAAM,KACX,OAAO,OAAO,EAAK,EAChB,GAAO,EAAO,KAAK,CAAE,KAAA,KAAWC,EAAK,CAAC,KAAK,IAAI,CACjD,CAAC,CACJ,EAAE,CACH,CACD,GAAG,OAAO,QAAQD,GAAQ,EAAoB,OAAO,CAAC,CAAC,QACpD,EAAK,CAAC,EAAM,KACX,OAAO,OAAO,EAAK,EAChB,GAAO,EAAO,KAAK,CAAE,WAAY,EAAM,CAAC,KAAK,IAAI,CACnD,CAAC,CACJ,EAAE,CACH,CACF,EACF,CAEuE,CCvL1E,eAAsB,GAAqB,CACzC,aACA,OACA,cAAc,GACd,oBAAoB,IACpB,SAAS,UACT,eAAeE,EAAAA,EACf,kBAAkB,CAACC,EAAAA,cAAc,UAAWA,EAAAA,cAAc,UAAU,EAgBlD,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAGzB,EAAuB,MAAM,GAA2B,EAAQ,CACpE,aACA,kBACD,CAAC,CAEF,EAAA,EAAO,KACL,EAAA,QAAO,QACL,WAAW,EAAqB,kCACjC,CACF,CAGD,IAAM,EAAc,IAAIC,EAAAA,QAAY,UAClC,EAAE,CACFA,EAAAA,QAAY,QAAQ,eACrB,CAEG,EAAQ,EAIZ,IAHA,EAAY,MAAM,EAAsB,EAAE,CAGnC,EAAQ,GAYb,MAAM,EAXmB,MAAM,GAAsB,EAAQ,CAC3D,aACA,kBACA,MAAO,EAEP,WAAa,GAAe,CAC1B,GAAS,EAAa,EACtB,EAAY,OAAO,EAAM,EAE5B,CAAC,CAKA,KAAO,IAAoB,CACzB,GAAI,CACF,MAAM,EAGH,EAAQ,GAAiC,CAC1C,kBAAmB,EAAgB,GACnC,SACD,CAAC,OACK,EAAK,CACZ,GAAI,CAAC,EAAI,QAAQ,SAAS,wCAAwC,CAChE,MAAM,EAIV,GAAS,GACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAGH,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SAAS,CACR,EASvB,OAPA,EAAA,EAAO,KACL,EAAA,QAAO,MACL,0BAA0B,EAAqB,iBAC7C,EAAY,IACb,YACF,CACF,CACM,ECpGT,eAAsB,GAAmC,CACvD,iBACA,kBACA,OACA,cAAc,GACd,eAAeC,EAAAA,GAYG,CAElB,IAAM,EAAS,EAA4B,EAAc,EAAK,CAGxD,EAAK,IAAI,MAAM,CAAC,SAAS,CAEzB,EAAc,IAAIC,EAAAA,QAAY,UAClC,EAAE,CACFA,EAAAA,QAAY,QAAQ,eACrB,CAGK,EAAc,MAAM,EAAiB,EAAQ,CACjD,QAAS,EACT,SAAU,CAACC,EAAAA,cAAc,UAAU,CACpC,CAAC,CAGF,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,iDAAiD,CAAC,CAE7E,IAAI,EAAQ,EACR,EAAY,EAChB,EAAY,MAAM,EAAY,OAAQ,EAAE,CACxC,MAAM,EACJ,EACA,KAAO,IAAqB,CAK1B,IAAM,GAJqB,MAAM,GAC/B,EACA,CAAE,UAAW,EAAiB,GAAI,CACnC,EAEE,QACE,CAAE,wBAAuB,UACxB,IAA0B,IAAS,EAAgB,SAAS,EAAK,CACpE,CACA,KAAK,CAAE,QAAS,EAAG,CAElB,EAAS,OAAS,IACpB,MAAM,EAGH,EAAQ,GAA4B,CACrC,MAAO,CACL,UAAW,EAAiB,GAC5B,qBAAsB,EACvB,CACF,CAAC,CACF,GAAa,EAAS,QAGxB,GAAS,EACT,EAAY,OAAO,EAAM,EAE3B,CAAE,cAAa,CAChB,CAED,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SAAS,CACR,EASvB,OAPA,EAAA,EAAO,KACL,EAAA,QAAO,MACL,oDACE,EAAY,IACb,gBAAgB,EAAM,aAAa,EAAU,gCAC/C,CACF,CACM,EAAY,OC9FrB,eAAsB,GAAuB,CAC3C,WAImB,CACnB,GAAM,CAAE,YAAa,MAAM,EAAA,QAAS,OAGjC,CACD,CACE,KAAM,WACN,UACA,KAAM,UACP,CACF,CAAC,CACF,OAAO,EAST,eAAsB,GAAoB,CACxC,WAIkB,CAClB,GAAM,CAAE,YAAa,MAAM,EAAA,QAAS,OAGjC,CACD,CACE,KAAM,WACN,UACA,KAAM,OACN,SAAW,GAAM,EAAE,MAAM,CAAC,OAAS,EACpC,CACF,CAAC,CACF,OAAO,EAST,eAAsB,GAAqB,CACzC,eACA,SACA,WAQkB,CAClB,EAAA,QAAS,eAAe,eAAgBC,EAAAA,QAAmB,CAC3D,GAAM,CAAE,YAAa,MAAM,EAAA,QAAS,OAGjC,CACD,CACE,KAAM,WACN,UACA,KAAM,eACN,QAAS,EACT,QAAS,EAA2B,IACjC,EAEG,EAAO,OACJ,GAAM,OAAO,GAAM,UAAY,GAAY,EAAO,EAAE,CACtD,CAHD,EAIP,CACF,CAAC,CACF,OAAO,ECtFT,SAAgB,GAAyB,EAEvC,CAEA,IAAM,EAAY,EAAU,MAAM,IAAI,CAAC,OAAQ,GAAM,CAAC,CAAC,EAAE,CACnD,EAAkC,EAAE,CAU1C,OATA,EAAU,QAAS,GAAa,CAC9B,GAAM,CAAC,EAAG,GAAK,EAAS,MAAM,IAAI,CAClC,GAAI,CAAC,GAAK,CAAC,EACT,MAAU,MACR,qBAAqB,EAAS,8BAC/B,CAEH,EAAK,GAAK,GACV,CACK,ECfT,SAAgB,GAAe,EAAkC,CAG/D,IAAM,EAAS,EACf,OAAO,GAAQ,UAAU,YAAc,GAAQ,UAAU,OCE3D,SAAgB,GAAoB,EAAsB,CAExD,IAAM,EAAS,EACX,EAAW,GAAQ,UAAU,MAAQ,GAAQ,SAAW,gBAG5D,GAAI,CACF,IAAM,EAAS,KAAK,MAAM,EAAS,CAE7B,EAAa,EAAO,QACxB,EAAO,OAAO,QAAU,CAAC,EAAO,OAAO,SAAW,EAAO,MAAM,CAGjE,GADa,MAAM,QAAQ,EAAW,CAAG,EAAa,CAAC,EAAW,EAClD,OAAO,QAAQ,CAAC,KAAK,KAAK,MACpC,EAGR,OAAO,ECvBT,SAAgB,GAAa,EAAoC,CAC/D,OAAO,IAAI,QAAS,GAAY,CAC9B,eAAiBC,EAAQ,EAAU,CAAE,EAAU,EAC/C,CCHJ,SAAgB,GAAe,EAA0B,CACvD,IAAM,EAAM,KAAK,MAAM,EAAQ,OAAS,EAAE,CAC1C,MAAO,CAAC,EAAQ,MAAM,EAAG,EAAI,CAAE,EAAQ,MAAM,EAAI,CAAC,CCoBpD,eAAsB,GACpB,EACA,EACA,EACY,CACZ,IAAI,EAAU,EAGd,OACE,GAAI,CAEF,OAAO,MAAM,GAAI,OACV,EAAK,CACZ,GAAW,EAGX,IAAM,EAAS,GAAe,EAAI,CAC5B,EAAM,GAAoB,EAAI,CAKpC,GAAI,EAFF,GAAW,EAAO,aAAe,EAAO,YAAY,EAAQ,EAAI,EAIhE,MAAM,EAGR,EACE,yBAAyB,EAAO,WAAW,EAAQ,GAAG,EAAO,YAAY,KAAK,IAC/E,CACD,MAAM,GAAa,EAAO,QAAQ,EClDxC,SAAgB,GACd,EACA,EAC0B,CAC1B,OAAO,OAAO,QAAQ,EAAI,CAAC,QAAQ,EAAK,CAAC,EAAQ,GAAQ,KACvD,EAAI,GAAU,EAAI,EAAM,EAAQ,GACzB,GACN,EAAE,CAA6B,CCDpC,IAAa,GAAb,KAAyB,CACvB,QAKK,EAAE,CAOP,IAAI,EAAiB,CACnB,IAAM,EAAM,KAAK,KAAK,CACtB,KAAK,QAAQ,KAAK,CAAK,EAAK,IAAG,CAAC,CAEhC,IAAM,EAAS,EAAM,KACrB,KAAO,KAAK,QAAQ,QAAU,KAAK,QAAQ,GAAG,EAAI,GAChD,KAAK,QAAQ,OAAO,CAUxB,KAAK,EAA0B,CAE7B,IAAM,EADM,KAAK,KAAK,CACD,EACjB,EAAM,EACV,IAAK,IAAI,EAAI,KAAK,QAAQ,OAAS,EAAG,GAAK,EAAG,IAAQ,CACpD,IAAM,EAAI,KAAK,QAAQ,GACvB,GAAI,EAAE,EAAI,EAAQ,MAClB,GAAO,EAAE,EAEX,OAAO,GAAO,EAAW,OC3C7B,SAAgB,GAAS,EAAoB,CAC3C,GAAI,CACF,OAAO,GAAA,EAAA,EAAA,cAAiB,EAAG,OAAO,CAAG,QAC/B,CACN,MAAO,ICCX,SAAgB,GACd,EACA,EACU,CACL,IACH,EAAA,EAAO,MAAM,EAAA,QAAO,IAAI,kCAAkC,CAAC,CAC3D,EAAa,QAAQ,KAAK,EAAE,EAG9B,IAAI,EAAkB,EAAE,CACxB,GAAI,CAEF,GAAA,EAAA,EAAA,aAD4B,EAAU,CAEnC,OAAQ,GAAM,EAAE,SAAS,WAAW,CAAC,CACrC,IAAK,IAAA,EAAA,EAAA,MAAW,EAAW,EAAE,CAAC,CAC9B,OAAQ,GAAM,CACb,GAAI,CACF,OAAA,EAAA,EAAA,UAAgB,EAAE,CAAC,QAAQ,MACrB,CACN,MAAO,KAET,OACG,EAAK,CACZ,EAAA,EAAO,MAAM,EAAA,QAAO,IAAI,6BAA6B,IAAY,CAAC,CAClE,EAAA,EAAO,MAAM,EAAA,QAAO,IAAK,EAAc,QAAQ,CAAC,CAChD,EAAa,QAAQ,KAAK,EAAE,CAU9B,OAPI,EAAM,SAAW,IACnB,EAAA,EAAO,MACL,EAAA,QAAO,IAAI,wCAAwC,IAAY,CAChE,CACD,EAAa,QAAQ,KAAK,EAAE,EAE9B,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,UAAU,EAAM,KAAK,KAAK,CAAC,gBAAgB,CAAC,CAC9D,ECgBT,eAAsB,GACpB,EACA,EACe,CACf,GAAM,CAAE,WAAU,YAAW,iBAAgB,cAAe,EAEtD,EAAU,IAAA,EAAA,EAAA,SAAqB,EAAS,CACxC,CAAE,KAAM,IAAA,EAAA,EAAA,OAAmB,EAAS,CACpC,GAAA,EAAA,EAAA,MAAe,EAAS,GAAG,EAAS,MAAM,CAMhD,IAHA,EAAA,EAAA,WAAU,EAAS,CAAE,UAAW,GAAM,CAAC,CAGnC,IAAA,EAAA,EAAA,YAA6B,EAAQ,CACvC,GAAI,EACF,EAAA,EAAA,QAAO,EAAS,CAAE,MAAO,GAAM,CAAC,OACzB,EAAK,CACZ,EAAA,EAAO,KACL,EAAA,QAAO,OACL,yCAAyC,EAAQ,IAC9C,EAAc,UAElB,CACF,CAKL,IAAM,EAAK,MAAM,EAAO,OAAO,WAAW,CACpC,EAAO,MAAM,EAAG,SAAS,CAE/B,GAAI,CAGF,MAAM,GAAe,EAAM,4BAA4B,CAQvD,IAAM,EAAK,GAAsB,IAAI,EAAE,QAAQ,KAAM,KAAK,CAAC,GAS3D,MAAM,GAAI,EANE;yCACyB,EAAE,EAAS,CAAC;WAC1C,EAAE,EAAQ,CAAC;;MAIE,CAGpB,IAAa,EAAG,IAAA,GAAU,CAE1B,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,eAAe,IAAU,CAAC,QAC3C,CAGR,MAAM,GAAY,EAAY,CAE9B,MAAM,GAAY,EAAU,EAgBhC,eAAe,GAAI,EAAwB,EAA4B,CAIrE,MAAM,GAHS,MAAM,EAAK,IAAI,EAAI,CAGF,CAWlC,eAAe,GACb,EACA,EACe,CACf,GAAI,CACF,MAAM,GAAI,EAAM,EAAI,MACd,GAWV,eAAe,GACb,EAOe,CACX,MAAC,GAAU,OAAO,EAAO,SAAY,YACzC,GAAI,CACF,MAAM,EAAO,SAAS,MAChB,GC5LV,MAAa,GAAS,KAAU,GAAK,IACxB,GAAU,KAAU,IACpB,GAAc,IAAS,IAQvB,GAAiB,GAC5B,KAAK,IAAI,EAAG,KAAK,IAAI,GAAI,GAAK,GAAG,CAAC,CAQvB,GAAiB,GAC5B,IAAI,KAAK,KAAK,IAAI,EAAE,gBAAgB,CAAE,EAAE,aAAa,CAAE,EAAE,YAAY,CAAC,CAAC,CAQ5D,GAAe,GAC1B,IAAI,KACF,KAAK,IACH,EAAE,gBAAgB,CAClB,EAAE,aAAa,CACf,EAAE,YAAY,CACd,EAAE,aAAa,CAChB,CACF,CASU,IAAS,EAAS,IAAqB,IAAI,KAAK,EAAE,SAAS,CAAG,EAAG,CASjE,IAAc,EAAS,IAClC,IAAI,KAAK,EAAE,SAAS,CAAG,EAAI,GAAO,CC5CpC,SAAS,GAAe,EAAuB,CAI7C,OAHI,EAAM,SAAS,IAAI,EAAI,EAAM,SAAS,IAAI,EAAI,EAAM,SAAS;EAAK,CAC7D,IAAI,EAAM,QAAQ,KAAM,KAAK,CAAC,GAEhC,EAUT,SAAgB,GACd,EACA,EACA,EACM,CACN,IAAM,EAAmB,EAAE,CAE3B,EAAK,KAAK,EAAQ,CAClB,EAAK,KAAK,GAAG,EAAK,IAAK,GAAQ,OAAO,OAAO,EAAI,CAAC,CAAC,EAQnD,EAAA,EAAA,eAAc,EALK,EAChB,IAAK,GAAQ,EAAI,IAAI,GAAe,CAAC,KAAK,IAAI,CAAC,CAC/C,KAAK;EAAK,CAGsB,CASrC,SAAgB,GAAY,EAAkB,EAAyB,CACrE,GAAI,CAAC,GAAW,EAAQ,SAAW,EAAG,EACpC,EAAA,EAAA,eAAc,EAAU,GAAG,CAC3B,QAGF,EAAA,EAAA,eAAc,EAAU,GADL,EAAQ,IAAI,GAAe,CAAC,KAAK,IAAI,CAClB,IAAI,CAW5C,SAAgB,GACd,EACA,EACA,EACM,CACD,EAAK,SAUV,EAAA,EAAA,gBAAe,EAAU,GARX,EAAK,IAAK,GACT,EAAY,IAAK,GAAQ,CACpC,IAAM,EAAI,EAAI,GACd,OAAO,GAAK,KAAO,GAAK,OAAO,EAAE,EACjC,CACU,IAAI,GAAe,CAAC,KAAK,IAAI,CACzC,CAEgC,KAAK;EAAK,CAAC,IAAI,CAUnD,SAAgB,GAAc,EAAkB,EAA2B,EAUzE,EAAA,EAAA,gBAAe,EAAU,KARZ,EAAK,IAAK,GAAQ,OAAO,OAAO,EAAI,CAAC,CAI/C,IAAK,GAAQ,EAAI,IAAI,GAAe,CAAC,KAAK,IAAI,CAAC,CAC/C,KAAK;EAAK,GAG8B,CAU7C,eAAsB,GACpB,EACA,EACA,EAA8B,GACf,CACf,IAAM,GAAA,EAAA,EAAA,mBAAuB,EAAS,CACtC,MAAM,IAAI,SAAe,EAAS,IAAW,CAC3C,GAAI,CACF,IAAM,EAASC,EACZ,MAAM,EAAM,CAAE,UAAS,WAAY,GAAM,CAAC,CAC1C,GAAG,QAAS,EAAO,CAEtB,EAAG,GAAG,QAAS,EAAO,CACtB,EAAG,GAAG,aAAgBC,GAAS,CAAC,CAEhC,EAAO,KAAK,EAAG,OACR,EAAK,CACZ,EAAO,EAAI,GAEb,CASJ,SAAgB,GAAc,EAK5B,CACA,IAAM,EAAe,EAAS,YAAY,IAAI,CAC9C,MAAO,CACL,SACE,IAAiB,GAA2C,EAAtC,EAAS,UAAU,EAAG,EAAa,CAC3D,UAAW,IAAiB,GAAwC,OAAnC,EAAS,UAAU,EAAa,CAClE,CAUH,SAAS,GACP,EACA,EACyB,CAGzB,IAAM,EAAmC,EAAE,CAC3C,IAAK,IAAM,KAAO,EAEhB,EAAQ,GAAO,EAAI,GAErB,OAAO,EAST,SAAS,GAAa,EAA8C,CAClE,OAAO,IAAI,QAAS,GAAY,CAC9B,EAAO,KAAK,QAASA,EAAQ,EAC7B,CAYJ,eAAsB,GACpB,EACA,EACA,EAA8B,GACX,CAEnB,IAAI,EACJ,AAKE,EALE,MAAM,QAAQ,EAAQ,CACV,EACL,IAAY,GACP,EAAK,OAAS,EAAI,OAAO,KAAK,EAAK,GAAG,CAAG,EAAE,CAE3C,GAGhB,IAAM,GAAA,EAAA,EAAA,mBAAuB,EAAS,CAChC,EAAYD,EAAQ,OAAiC,CACzD,QAAS,GAAe,IAAA,GACxB,WAAY,GACb,CAAC,CAGI,EAAS,EAAU,KAAK,EAAG,CAE3B,EAAa,IAAI,SAAe,EAAS,IAAW,CACxD,EAAO,GAAG,aAAgBC,GAAS,CAAC,CACpC,EAAO,GAAG,QAAS,EAAO,CAC1B,EAAU,GAAG,QAAS,EAAO,CAC7B,EAAG,GAAG,QAAS,EAAO,EACtB,CAGF,IAAK,IAAM,KAAO,EAAM,CACtB,IAAM,EAAU,EAAc,GAAY,EAAK,EAAY,CAAG,EACnD,EAAU,MAAM,EAAQ,EAGjC,MAAM,GAAa,EAAU,CAQjC,OAHA,EAAU,KAAK,CACf,MAAM,EAEC,CAAC,EAAS,CCxOnB,MAAM,GAAc,EAEd,GAAe,CACnB,eACA,oBACA,eACA,kCACA,4BACD,CAYD,eAAsB,EACpB,EACA,EACA,EACA,EACA,EAAc,EACF,CACZ,IAAI,EAAa,EAEjB,OACE,GAAI,CAEF,OADe,MAAM,EAAO,QAAQ,EAAU,EAAW,EAAe,OAEjE,EAAK,CAYZ,GAXI,EAAI,QAAQ,SAAS,qBAAqB,GAC5C,EAAA,EAAO,MACL,EAAA,QAAO,IACL,wMAGD,CACF,CACD,QAAQ,KAAK,EAAE,EAGb,GAAa,KAAM,GAAQ,EAAI,QAAQ,SAAS,EAAI,CAAC,CACvD,MAAM,EAIR,GAAI,EAAI,QAAQ,WAAW,kCAAkC,CAAE,CAC7D,IAAM,EAAmB,EAAI,SAAS,SAAS,IAAI,oBAAoB,CACjE,EAAY,EACd,IAAI,KAAK,EAAiB,CAAC,SAAS,CAAG,IAAI,MAAM,CAAC,SAAS,CAAG,IAC9D,IAAO,GACX,EAAA,EAAO,IACL,EAAA,QAAO,OACL,wBAAwB,EAAI,QAAQ,iBAAiB,EAAU,IAChE,CACF,CAED,MAAM,GAAa,EAAU,CAG/B,GAAI,GAAc,EAChB,MAAM,EAER,GAAc,EACd,EAAA,EAAO,IACL,EAAA,QAAO,OACL,4BAA4B,EAAW,KAAK,EAAY,KAAK,EAAI,UAClE,CACF,ECjCP,MAAM,GAAY,GAQlB,eAAsB,GACpB,EACuB,CACvB,IAAM,EAA4B,EAAE,CAChC,EAAS,EAGT,EAAiB,GACrB,EAAG,CACD,GAAM,CACJ,YAAa,CAAE,UACb,MAAM,EAMP,EAAQ,GAAa,CACtB,MAAO,GACP,SACD,CAAC,CACF,EAAY,KAAK,GAAG,EAAM,CAC1B,GAAU,GACV,EAAiB,EAAM,SAAW,SAC3B,GAET,OAAO,EAAY,MAAM,EAAG,IAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,CAYjE,eAAsB,GACpB,CACE,YAAY,EAAE,CACd,aAAc,EAAY,EAAE,CAC5B,cAAc,EAAE,EAElB,EACA,EAAc,GAC0B,CAExC,IAAM,EAAiB,MAAM,GAAoB,EAAO,CAGlD,EAAoBC,EAAAA,EAAM,EAAgB,OAAO,CAajD,EAAqBC,EAVCC,EAAK,CAC/B,GAAGC,GACD,EAAU,IAAK,GAAa,CAC1B,EAAS,oBACT,GAAG,EAAS,sBACb,CAAC,CACH,CACD,GAAGA,GAAQ,EAAU,IAAK,GAAa,EAAS,iBAAiB,CAAC,CAClE,GAAG,EAAY,KAAK,CAAE,UAAW,EAAK,CACvC,CAAC,CAAC,OAAQ,GAAM,CAAC,CAAC,EAAE,CAGnB,EAAe,KAAK,CAAE,UAAW,EAAK,CACvC,CAGD,GAAI,EAAmB,OAAS,EAAG,CACjC,EAAA,EAAO,KACL,EAAA,QAAO,QACL,YAAY,EAAmB,OAAO,qBACvC,CACF,CACD,GAAM,CAAE,sBAAuB,MAAM,EAMlC,EAAQ,GAAqB,CAC1B,EAAuB,EAAmB,KAAK,CAAE,UAAW,EAAK,CACvE,MAAM,EAAU,EAAoB,KAAO,IAAe,CACxD,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,uBAAuB,EAAW,KAAK,CAAC,CACnE,GAAM,CAAE,oBAAqB,MAAM,EAMhC,EAAQ,GAAmB,CAC5B,MAAO,CACL,KAAM,EACN,KAAM,EAAqB,SAAS,EAAY,CAC5C,EACA,SACJ,cACD,CACF,CAAC,CACF,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,sBAAsB,EAAW,GAAG,CAAC,CAE9D,EAAkB,GAAe,EAAiB,YAClD,CAEJ,OAAO,ECjJT,eAAsB,GACpB,EACA,EACoC,CAWpC,GAAM,CAAE,WAAA,GAAe,MAAM,EAM1B,EAAQ,GAAa,CACtB,MAjBY,CACZ,KAAM,EAAK,KACX,YAAa,EAAK,YAClB,SAAU,EAAK,aACf,cAAe,EAAK,kBACpB,SAAU,EAAK,aACf,OAAQ,EAAK,OACb,WAAY,EAAK,MAClB,CAUA,CAAC,CACF,OAAOC,EAAW,KAWpB,eAAsB,GACpB,EACA,EACA,EACoC,CACpC,GAAM,CAAE,WAAA,GAAe,MAAM,EAM1B,EAAQ,GAAa,CACtB,MAAO,CACL,GAAI,EACJ,KAAM,EAAM,KACZ,YAAa,EAAM,YACnB,SAAU,EAAM,aAChB,cAAe,EAAM,kBACrB,SAAU,EAAM,aAChB,OAAQ,EAAM,OACd,WAAY,EAAM,MACnB,CACF,CAAC,CACF,OAAOC,EAAW,KAUpB,eAAsB,GACpB,EACA,EACkB,CAElB,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,YAAY,EAAO,OAAO,YAAY,CAAC,CAElE,IAAI,EAAmB,GAMjB,EAA4DC,EAAAA,EAH5C,MAAM,GAAc,EAAO,CAK/C,OACD,CAGK,EAAW,EAAO,OAAQ,GAAU,CAAC,EAAY,EAAM,MAAM,CAC7D,EAAe,EAAO,OAAQ,GAAU,CAAC,CAAC,EAAY,EAAM,MAAM,CAkCxE,OA/BA,MAAM,EAAU,EAAU,KAAO,IAAS,CACxC,GAAI,CACF,IAAM,EAAU,MAAM,GAAW,EAAQ,EAAK,CAC9C,EAAY,EAAQ,MAAQ,EAC5B,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,8BAA8B,EAAK,KAAK,IAAI,CAAC,OAC/D,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IAAI,wBAAwB,EAAK,KAAK,OAAO,EAAI,UAAU,CACnE,GAEH,CAGF,MAAM,EAAU,EAAc,KAAO,IAAU,CAC7C,GAAI,CACF,IAAM,EAAU,MAAM,GACpB,EACA,EACA,EAAY,EAAM,MAAM,GACzB,CACD,EAAY,EAAQ,MAAQ,EAC5B,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,8BAA8B,EAAM,KAAK,IAAI,CAAC,OAChE,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IAAI,wBAAwB,EAAM,KAAK,OAAO,EAAI,UAAU,CACpE,GAEH,CAEK,CAAC,ECzHV,eAAsB,GACpB,EACA,EAMiB,CACjB,GAAM,CACJ,oBAAqB,CAAE,kBACrB,MAAM,EASP,EAAQ,GAAuB,CAChC,QACD,CAAC,CAIF,OAHA,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,wCAAwC,EAAM,MAAM,IAAI,CACtE,CACM,EAAc,GASvB,eAAsB,GACpB,EACA,EACe,CACf,MAAM,EAAmB,EAAQ,GAAwB,CACvD,MAAO,CACL,eAAgB,EAAM,KAAK,CAACC,EAAO,MAAS,CAC1C,GAAGA,EACH,KACD,EAAE,CACJ,CACF,CAAC,CACF,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,wBAAwB,EAAM,OAAO,mBAAmB,CACtE,CAWH,eAAsB,GACpB,EACA,EACA,EAAc,GACI,CAClB,IAAI,EAAmB,GACvB,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,YAAY,EAAe,OAAO,sBAAsB,CACxE,CAID,IAAM,EAAuBC,EAAAA,EADZ,MAAM,GAAuB,EAAO,CACR,QAAQ,CAG/C,EAA8B,EAAe,IAAK,GAAgB,CACtE,EACA,EAAqB,EAAY,QAAQ,GAC1C,CAAC,CAGI,EAAoB,EACvB,QAAQ,EAAG,KAAc,CAAC,EAAS,CACnC,KAAK,CAAC,KAAiB,EAAkC,CAC5D,GAAI,CACF,EAAA,EAAO,KACL,EAAA,QAAO,QACL,aAAa,EAAkB,OAAO,0BACvC,CACF,CACD,MAAM,EACJ,EACA,KAAO,IAAW,CAChB,MAAM,GAAoB,EAAQ,EAAO,EAE3C,CACE,cACD,CACF,CACD,EAAA,EAAO,KACL,EAAA,QAAO,MACL,uBAAuB,EAAkB,OAAO,mBACjD,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IAAI,uCAAuC,EAAI,UAAU,CACjE,CAIH,IAAM,EAAyB,EAA4B,OACxD,GAAyC,CAAC,CAAC,EAAE,GAC/C,CACD,GAAI,CACF,EAAA,EAAO,KACL,EAAA,QAAO,QACL,aAAa,EAAuB,OAAO,sBAC5C,CACF,CACD,MAAM,GAAqB,EAAQ,EAAuB,CAC1D,EAAA,EAAO,KACL,EAAA,QAAO,MACL,yBAAyB,EAAuB,OAAO,oBACxD,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IAAI,uCAAuC,EAAI,UAAU,CACjE,CAQH,OALA,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,WAAW,EAAe,OAAO,oBAAoB,CACnE,CAGM,CAAC,ECjIV,eAAsB,GACpB,EACA,EACiB,CACjB,GAAM,CACJ,kBAAmB,CAAE,gBACnB,MAAM,EASP,EAAQ,GAAqB,CAC9B,QACD,CAAC,CAIF,OAHA,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,sCAAsC,EAAM,MAAM,IAAI,CACpE,CACM,EAAY,GASrB,eAAsB,GACpB,EACA,EACe,CACf,MAAM,EAAmB,EAAQ,GAAsB,CACrD,MAAO,CACL,aAAc,EAAM,KAAK,CAACC,EAAO,MAAS,CACxC,GAAGA,EACH,KACD,EAAE,CACJ,CACF,CAAC,CACF,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,wBAAwB,EAAM,OAAO,iBAAiB,CACpE,CAWH,eAAsB,GACpB,EACA,EACA,EAAc,GACI,CAClB,IAAI,EAAmB,GACvB,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,YAAY,EAAa,OAAO,oBAAoB,CACpE,CAGD,IAAM,EAAW,MAAM,GAAqB,EAAO,CAE7C,EAAgBC,EAAAA,EADE,MAAM,GAAgB,EAAO,CACR,QAAQ,CAC/C,EAAqBA,EAAAA,EAAM,EAAU,QAAQ,CAG7C,EAA4B,EAAa,IAAK,GAAgB,CAClE,EACA,EAAmB,EAAY,QAAQ,GACxC,CAAC,CAGI,EAAkB,EACrB,QAAQ,EAAGC,KAAc,CAACA,EAAS,CACnC,KAAK,CAAC,KAAiB,EAAgC,CAC1D,GAAI,CACF,EAAA,EAAO,KACL,EAAA,QAAO,QACL,aAAa,EAAgB,OAAO,wBACrC,CACF,CACD,MAAM,EACJ,EACA,KAAO,IAAW,CAChB,MAAM,GAAkB,EAAQ,CAC9B,GAAG,EACH,UAAW,EAAO,QAAQ,IAAK,GAAU,CACvC,IAAMC,EAAS,EAAc,GAC7B,GAAI,CAACA,EACH,MAAU,MAAM,sCAAsC,EAAM,GAAG,CAEjE,OAAOA,EAAO,IACd,CACH,CAAC,EAEJ,CACE,cACD,CACF,CACD,EAAA,EAAO,KACL,EAAA,QAAO,MACL,uBAAuB,EAAgB,OAAO,iBAC/C,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KAAK,EAAA,QAAO,IAAI,qCAAqC,EAAI,UAAU,CAAC,CAI7E,IAAM,EAAuB,EAA0B,OACpD,GAAuC,CAAC,CAAC,EAAE,GAC7C,CACD,GAAI,CACF,EAAA,EAAO,KACL,EAAA,QAAO,QACL,aAAa,EAAqB,OAAO,oBAC1C,CACF,CACD,MAAM,GACJ,EACA,EAAqB,KAAK,CAAC,CAAE,UAAS,GAAG,GAAS,KAAQ,CACxD,CACE,GAAG,EACH,UAAW,EAAQ,IAAK,GAAU,CAChC,IAAM,EAAS,EAAc,GAC7B,GAAI,CAAC,EACH,MAAU,MAAM,sCAAsC,EAAM,GAAG,CAEjE,OAAO,EAAO,IACd,CACH,CACD,EACD,CAAC,CACH,CACD,EAAA,EAAO,KACL,EAAA,QAAO,MACL,yBAAyB,EAAqB,OAAO,kBACtD,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KAAK,EAAA,QAAO,IAAI,qCAAqC,EAAI,UAAU,CAAC,CAM7E,OAHA,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,WAAW,EAAa,OAAO,kBAAkB,CAAC,CAGpE,CAAC,ECvIV,MAAM,GAAc,GAUpB,eAAsB,GACpB,EACA,EACA,CACE,WAAW,GAEX,yBAAyB,GACzB,kBAAkB,GAClB,6BAA6B,IAWb,CAClB,IAAI,EAAmB,GAEvB,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,gCAAgC,EAAS,KAAK,CAAC,CAE1E,GAAM,CACJ,YACA,aACA,UACA,cACA,gBAAiB,EACjB,oBAAqB,EACrB,YACA,UACA,kBAAmB,EACnB,aAAc,EACd,aAAc,EACd,UACA,gBAAiB,EACjB,kBAAmB,EACnB,SACA,kBAAmB,EACnB,cAAe,EACf,UACA,kBAAmB,EACnB,wBAAyB,EACzB,sBAAuB,EACvB,eAAgB,EAChB,0BAA2B,EAC3B,QACA,iBAAkB,EAClB,WACA,WACA,cACE,EAEE,CAAC,GAAkB,EAAoB,IAC3C,MAAM,QAAQ,IAAI,CAEhB,GAAa,EACT,GACE,EACA,EACA,CAAC,EACF,CACA,EAAE,CAEP,GAAa,GAAgB,GAAa,EACtC,GAA2B,EAAO,EAAO,CACzC,EAAE,CAEN,GACA,EACG,IAAK,GAAa,EAAS,kBAAoB,EAAE,CAAC,CAClD,QAAQ,EAAK,IAAQ,EAAM,EAAI,OAAQ,EAAE,CAAG,EAC3C,GAAa,EAAO,EAAO,CAC3B,EAAE,CACP,CAAC,CAGJ,GAAI,EAAgB,CAClB,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,6BAA6B,CAAC,CACzD,GAAI,CACF,MAAM,GAAmB,EAAQ,EAAe,CAChD,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,uCAAuC,CAAC,OAC1D,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IAAI,qCAAqC,EAAI,UAAU,CAC/D,EAKL,GAAI,EAAS,CACX,IAAM,EAAiB,MAAM,GAAY,EAAQ,EAAQ,CACzD,IAAuC,CAAC,EAE1C,GAAI,EAAgB,CAClB,IAAM,EAAiB,MAAM,GAAmB,EAAQ,EAAe,CACvE,IAAuC,CAAC,EAE1C,GAAI,EAAc,CAChB,IAAM,EAAiB,MAAM,GAAiB,EAAQ,EAAa,CACnE,IAAuC,CAAC,EAG1C,GAAI,EAAO,CACT,IAAM,EAAe,MAAM,GAAU,EAAQ,EAAM,CACnD,IAAuC,CAAC,EAkC1C,GA9BI,IACF,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,YAAY,EAAU,OAAO,sBAAsB,CACnE,CACD,MAAM,EACJ,EACA,KAAO,IAAa,CAClB,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,qBAAqB,EAAS,MAAM,MAAM,CAAC,CACtE,GAAI,CACF,MAAM,GAAa,EAAU,EAAO,CACpC,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,iCAAiC,EAAS,MAAM,IAAI,CAClE,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,4BAA4B,EAAS,MAAM,OAAO,EAAI,UACvD,CACF,GAGL,CACE,YAAa,GACd,CACF,CACD,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,WAAW,EAAU,OAAO,oBAAoB,CAAC,EAIxE,EAAkB,CACpB,IAAM,EAAwB,MAAM,GAClC,EACA,EACD,CACD,IAAuC,CAAC,EAI1C,GAAI,EAAS,CACX,IAAM,EAAiB,MAAM,GAAY,EAAQ,EAAQ,CACzD,IAAuC,CAAC,EAI1C,GAAI,EAAgB,CAClB,IAAM,EAAwB,MAAM,GAClC,EACA,EACD,CACD,IAAuC,CAAC,EAI1C,GAAI,EAAoB,CACtB,IAAM,EAA4B,MAAM,GACtC,EACA,EACD,CACD,IAAuC,CAAC,EAI1C,GAAI,EAAY,CACd,IAAM,EAAoB,MAAM,GAAe,EAAQ,EAAW,CAClE,IAAuC,CAAC,EAI1C,GAAI,EAAQ,CACV,IAAM,EAAgB,MAAM,GAAW,EAAQ,EAAO,CACtD,IAAuC,CAAC,EAI1C,GAAI,EAAgB,CAClB,IAAM,EAAwB,MAAM,GAClC,EACA,EACD,CACD,IAAuC,CAAC,EAI1C,GAAI,EAAY,CACd,IAAM,EAAoB,MAAM,GAAe,EAAQ,EAAW,CAClE,IAAuC,CAAC,EAI1C,GAAI,EAAS,CACX,IAAM,EAAiB,MAAM,GAAY,EAAQ,EAAQ,CACzD,IAAuC,CAAC,EAI1C,GAAI,EAAuB,CACzB,IAAM,EAA+B,MAAM,GACzC,EACA,EACD,CACD,IAAuC,CAAC,EAI1C,GAAI,EAAY,CAEd,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,YAAY,EAAW,OAAO,iBAAiB,CAAC,CAC3E,IAAM,EAAqB,MAAM,GAAmB,EAAO,CAC3D,MAAM,EACJ,EACA,KAAO,IAAc,CACnB,IAAM,EAAW,EAAmB,KACjC,GAAS,EAAK,OAAS,EAAU,KACnC,CAED,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,sBAAsB,EAAU,KAAK,MAAM,CAAC,CACvE,GAAI,CACF,MAAM,GAAc,EAAQ,EAAW,CACrC,kBAAmB,EACnB,6BACD,CAAC,CACF,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,kCAAkC,EAAU,KAAK,IAAI,CACnE,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,6BAA6B,EAAU,KAAK,OAAO,EAAI,UACxD,CACF,GAGL,CACE,YAAa,GACd,CACF,CACD,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,WAAW,EAAW,OAAO,eAAe,CAAC,CAIxE,GAAI,EAAa,CACf,IAAM,EAAqB,MAAM,GAAgB,EAAQ,EAAY,CACrE,IAAuC,CAAC,EAmF1C,GA/EI,IACF,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,YAAY,EAAU,OAAO,gBAAgB,CAAC,CACzE,MAAM,EACJ,EACA,KAAO,IAAa,CAClB,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,qBAAqB,EAAS,MAAM,MAAM,CAAC,CACtE,GAAI,CACF,MAAM,GAAa,EAAQ,CACzB,WACA,oBACA,qBACD,CAAC,CACF,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,iCAAiC,EAAS,MAAM,IAAI,CAClE,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,4BAA4B,EAAS,MAAM,OAAO,EAAI,UACvD,CACF,GAGL,CACE,YAAa,GACd,CACF,CACD,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,WAAW,EAAU,OAAO,cAAc,CAAC,EAIlE,IAEF,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,YAAY,EAAY,OAAO,kBAAkB,CACjE,CACD,MAAM,EACJ,EACA,KAAO,IAAe,CACpB,IAAM,EAAW,GAAiB,EAAW,MAC7C,GAAI,CAAC,EACH,MAAU,MACR,wCAAwC,EAAW,KAAK,yCACzD,CAGH,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,uBAAuB,EAAW,KAAK,MAAM,CAC7D,CACD,GAAI,CACF,MAAM,GAAe,EAAQ,CAC3B,aACA,qBACA,aAAc,EAAS,GACvB,YAAa,CAAC,EACf,CAAC,CACF,EAAA,EAAO,KACL,EAAA,QAAO,MACL,mCAAmC,EAAW,KAAK,IACpD,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,8BAA8B,EAAW,KAAK,OAAO,EAAI,UAC1D,CACF,GAGL,CACE,YAAa,GACd,CACF,CACD,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,WAAW,EAAY,OAAO,gBAAgB,CAAC,EAItE,EAAS,CAEX,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,YAAY,EAAQ,OAAO,cAAc,CAAC,CACrE,IAAM,EAAkB,MAAM,GAAgB,EAAO,CACrD,MAAM,EACJ,EACA,KAAO,IAAW,CAChB,IAAM,EAAW,EAAgB,KAC9B,GAAQ,EAAI,OAAS,EAAO,KAC9B,CACD,GAAI,CAAC,EACH,MAAU,MACR,oCAAoC,EAAO,KAAK,qDACjD,CAGH,EAAA,EAAO,KAAK,EAAA,QAAO,QAAQ,mBAAmB,EAAO,KAAK,MAAM,CAAC,CACjE,GAAI,CACF,MAAM,GAAW,EAAQ,CACvB,SACA,SAAU,EAAS,GACnB,YAAa,CAAC,EACf,CAAC,CACF,EAAA,EAAO,KACL,EAAA,QAAO,MAAM,+BAA+B,EAAO,KAAK,IAAI,CAC7D,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,0BAA0B,EAAO,KAAK,OAAO,EAAI,UAClD,CACF,GAGL,CACE,YAAa,GACd,CACF,CACD,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,WAAW,EAAQ,OAAO,YAAY,CAAC,CAIlE,GAAI,EAAc,CAEhB,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,YAAY,EAAa,OAAO,oBAAoB,CACpE,CACD,IAAM,EAAuB,MAAM,GAAqB,EAAO,CAC/D,MAAM,EACJ,EACA,KAAO,IAAgB,CACrB,IAAM,EAAW,EAAqB,KACnC,GAAS,EAAK,OAAS,EAAY,KACrC,CACD,GAAI,CAAC,EACH,MAAU,MACR,0CAA0C,EAAY,KAAK,qDAC5D,CAGH,EAAA,EAAO,KACL,EAAA,QAAO,QAAQ,yBAAyB,EAAY,KAAK,MAAM,CAChE,CACD,GAAI,CACF,MAAM,GAAgB,EAAQ,CAC5B,cACA,cAAe,EAAS,GACxB,YAAa,CAAC,EACf,CAAC,CACF,EAAA,EAAO,KACL,EAAA,QAAO,MACL,qCAAqC,EAAY,KAAK,IACvD,CACF,OACM,EAAK,CACZ,EAAmB,GACnB,EAAA,EAAO,KACL,EAAA,QAAO,IACL,gCAAgC,EAAY,KAAK,OAAO,EAAI,UAC7D,CACF,GAGL,CACE,YAAa,GACd,CACF,CACD,EAAA,EAAO,KAAK,EAAA,QAAO,MAAM,WAAW,EAAa,OAAO,kBAAkB,CAAC,CAI7E,GAAI,EAAW,CACb,IAAM,EAAkB,MAAM,GAC5B,EACA,EACA,EACD,CACD,IAAuC,CAAC,EAI1C,GAAI,EAAe,CACjB,IAAM,EAAuB,MAAM,GAAkB,EAAQ,EAAc,CAC3E,IAAuC,CAAC,EAI1C,GAAI,EAAU,CACZ,IAAM,EAAkB,MAAM,GAAiB,EAAQ,EAAS,CAChE,IAAuC,CAAC,EAI1C,GAAI,EAAU,CACZ,IAAM,EAAkB,MAAM,GAAa,EAAQ,EAAS,CAC5D,IAAuC,CAAC,EAI1C,IAAM,EAA0C,EAAE,CAElD,GAAI,EAAW,CACb,GAAM,CAAE,UAAS,qBAAsB,MAAM,GAC3C,EACA,EACA,CACE,qBACA,eAAgB,GAChB,WACD,CACF,CACD,GAAW,QAAS,GAAa,CAE3B,EAAS,0BACX,EAAkB,KAAK,CACrB,EAAkB,EAAS,OAC3B,EAAS,yBACV,CAAC,EAEJ,CACF,IAAuC,CAAC,EAS1C,GALI,EAAkB,OAAS,GAC7B,MAAM,GAAyB,EAAQ,EAAkB,CAIvD,EAAsB,CACxB,IAAM,EAA4B,MAAM,GACtC,EACA,EACD,CACD,IAAuC,CAAC,EAO1C,OAAO"}
|
|
1
|
+
{"version":3,"file":"syncConfigurationToTranscend-Bd0ZTIm1.cjs","names":["trimmedEndIndex","isSymbol","isObject","baseTrim","toNumber","toFinite","apply","defineProperty","identity","constant","shortOut","baseSetToString","strictIndexOf","baseFindIndex","baseIsNaN","baseIndexOf","nativeMax","apply","setToString","overRest","identity","isObject","isArrayLike","isIndex","eq","Symbol","isArray","isArguments","isFlattenable","baseFlatten","baseSlice","rsAstralRange","rsComboRange","rsVarRange","rsCombo","rsModifier","rsNonAstral","rsRegional","rsSurrPair","rsZWJ","reOptMod","rsOptVar","rsOptJoin","rsSeq","hasUnicode","unicodeToArray","asciiToArray","toString","hasUnicode","stringToArray","castSlice","createCaseFirst","basePropertyOf","toString","deburrLetter","toString","hasUnicodeWord","unicodeWords","asciiWords","arrayReduce","words","deburr","isIterateeCall","toInteger","baseSlice","isObjectLike","isArrayLike","LARGE_ARRAY_SIZE","arrayIncludes","arrayMap","baseUnary","arrayIncludesWith","cacheHas","SetCache","baseRest","isArrayLikeObject","baseDifference","baseFlatten","isArrayLike","collection","createAggregator","baseIteratee","object","isSymbol","compareAscending","arrayMap","isArray","baseGet","identity","baseUnary","baseIteratee","baseSortBy","baseMap","compareMultiple","baseRest","isIterateeCall","baseOrderBy","baseFlatten","createCompounder","upperFirst","Set","setToArray","noop","arrayIncludes","arrayIncludesWith","createSet","setToArray","cacheHas","SetCache","baseUniq","baseUniq","baseIteratee","Bluebird","t","RequestAction","LOCALE_KEY","IsoCountryCode","IsoCountrySubdivisionCode","CompletedRequestStatus","CachedRequestState","autoCompletePrompt","t","t","uniq","uniq","rest","GraphQLClient","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","chunk","PAGE_SIZE","PAGE_SIZE","AttributeKeyType","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","ConsentTrackerStatus","PAGE_SIZE","PAGE_SIZE","ConsentTrackerStatus","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","t","IdentifierType","PAGE_SIZE","version","t","RequestAction","RequestOrigin","LOCALE_KEY","RequestStatus","IsoCountryCode","IsoCountrySubdivisionCode","PAGE_SIZE","cliProgress","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","uniq","keyBy","difference","PAGE_SIZE","uniq","flatten","keyBy","difference","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","PAGE_SIZE","t","ComparisonOperator","LogicOperator","AssessmentsDisplayLogicAction","t","ComparisonOperator","gql","sortBy","keyBy","chunk","cliProgress","PAGE_SIZE","RequestAction","EnricherType","PAGE_SIZE","PAGE_SIZE","difference","PAGE_SIZE","TranscendPullResource","ConsentTrackerStatus","ActionItemCode","flatten","title","assignees","externalAssignees","resources","prompts","name","actions","type","RetentionType","dataSilos","dataSubjects","teams","RequestAction","agentFunctions","agentFiles","showInPrivacyCenter","identifiers","keyBy","businessEntities","mapValues","IsoCountryCode","IsoCountrySubdivisionCode","difference","createActionItemCollection","keyBy","chunk","keyBy","uniq","createAgentFile","keyBy","createAgentFunction","keyBy","createAgent","keyBy","keyBy","groupBy","difference","createBusinessEntity","chunk","keyBy","PAGE_SIZE","PAGE_SIZE","CHUNK_SIZE","keyBy","chunk","PAGE_SIZE","CHUNK_SIZE","keyBy","chunk","CHUNK_SIZE","uniqBy","keyBy","uniq","chunk","keyBy","OnConsentExpiry","InitialViewState","MAX_PAGE_SIZE","chunk","createDataCategory","keyBy","MAX_PAGE_SIZE","chunk","ConsentTrackerStatus","MAX_PAGE_SIZE","chunk","chunk","keyBy","createProcessingActivity","keyBy","keyBy","input","keyBy","createVendor","keyBy","chunk","RequestStatus","DEFAULT_TRANSCEND_API","cliProgress","startCase","RequestAction","LOCALE_KEY","CompletedRequestStatus","IsoCountryCode","IsoCountrySubdivisionCode","t","RequestAction","IsoCountryCode","IsoCountrySubdivisionCode","CompletedRequestStatus","DateFromISOString","LOCALE_KEY","IdentifierType","NORMALIZE_PHONE_NUMBER","t","TableEncryptionType","cliProgress","RequestStatus","DEFAULT_TRANSCEND_API","RequestAction","cliProgress","t","RequestStatus","RequestAction","IsoCountryCode","IsoCountrySubdivisionCode","uniq","DEFAULT_TRANSCEND_API","cliProgress","RequestStatus","RequestAction","DEFAULT_TRANSCEND_API","cliProgress","RequestStatus","DEFAULT_TRANSCEND_API","cliProgress","DEFAULT_TRANSCEND_API","cliProgress","PersistedState","CachedRequestState","t","uniq","groupBy","IdentifierType","t","t","DEFAULT_TRANSCEND_API","cliProgress","PersistedState","difference","DEFAULT_TRANSCEND_API","RequestStatus","cliProgress","RequestEnricherStatus","DEFAULT_TRANSCEND_API","RequestEnricherStatus","cliProgress","RequestStatus","difference","DEFAULT_TRANSCEND_API","cliProgress","RequestStatus","DEFAULT_TRANSCEND_API","isTest","groupBy","name","DEFAULT_TRANSCEND_API","RequestStatus","cliProgress","DEFAULT_TRANSCEND_API","cliProgress","RequestStatus","autoCompletePrompt","resolve","fastcsv","resolve","keyBy","difference","uniq","flatten","createTeam","updateTeam","keyBy","input","keyBy","input","keyBy","existing","prompt"],"sources":["../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_trimmedEndIndex.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseTrim.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/toNumber.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/toFinite.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/toInteger.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_apply.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/noop.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_shortOut.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/constant.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseSetToString.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_setToString.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseFindIndex.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseIsNaN.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_strictIndexOf.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseIndexOf.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_arrayIncludes.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_overRest.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseRest.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_isIterateeCall.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_isFlattenable.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseFlatten.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/flatten.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseSlice.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_castSlice.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_hasUnicode.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_asciiToArray.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_unicodeToArray.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_stringToArray.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_createCaseFirst.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/upperFirst.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_arrayReduce.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_basePropertyOf.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_deburrLetter.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/deburr.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_asciiWords.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_hasUnicodeWord.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_unicodeWords.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/words.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_createCompounder.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/chunk.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isArrayLikeObject.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_arrayIncludesWith.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseDifference.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/difference.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseMap.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/groupBy.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/mapValues.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseSortBy.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_compareAscending.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_compareMultiple.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseOrderBy.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/sortBy.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/startCase.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_createSet.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseUniq.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/uniq.js","../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/uniqBy.js","../src/lib/bluebird.ts","../src/lib/graphql/gqls/dataPoint.ts","../src/lib/graphql/gqls/entry.ts","../src/lib/graphql/gqls/dataSilo.ts","../src/lib/graphql/gqls/enricher.ts","../src/lib/graphql/gqls/catalog.ts","../src/lib/graphql/gqls/identifier.ts","../src/lib/graphql/gqls/dataSubject.ts","../src/lib/graphql/gqls/repository.ts","../src/lib/graphql/gqls/apiKey.ts","../src/lib/graphql/gqls/preferenceAccessTokens.ts","../src/lib/graphql/gqls/siloDiscovery.ts","../src/lib/graphql/gqls/template.ts","../src/lib/graphql/gqls/organization.ts","../src/lib/graphql/gqls/attributeKey.ts","../src/lib/graphql/gqls/softwareDevelopmentKit.ts","../src/lib/graphql/gqls/codePackage.ts","../src/lib/graphql/gqls/promptThread.ts","../src/lib/graphql/gqls/policy.ts","../src/lib/graphql/gqls/request.ts","../src/lib/graphql/gqls/message.ts","../src/lib/graphql/gqls/RequestEnricher.ts","../src/lib/graphql/gqls/assessment.ts","../src/lib/graphql/gqls/purpose.ts","../src/lib/graphql/gqls/preferenceTopic.ts","../src/lib/graphql/gqls/assessmentTemplate.ts","../src/lib/graphql/gqls/prompt.ts","../src/lib/graphql/gqls/RequestDataSilo.ts","../src/lib/graphql/gqls/team.ts","../src/lib/graphql/gqls/RequestIdentifier.ts","../src/lib/graphql/gqls/user.ts","../src/lib/graphql/gqls/requestFile.ts","../src/lib/graphql/gqls/promptRun.ts","../src/lib/graphql/gqls/actionItemCollection.ts","../src/lib/graphql/gqls/attribute.ts","../src/lib/graphql/gqls/consentManager.ts","../src/lib/graphql/gqls/consentManagerMetrics.ts","../src/lib/graphql/gqls/businessEntity.ts","../src/lib/graphql/gqls/action.ts","../src/lib/graphql/gqls/actionItem.ts","../src/lib/graphql/gqls/privacyCenter.ts","../src/lib/graphql/gqls/auth.ts","../src/lib/graphql/gqls/largeLanguageModel.ts","../src/lib/graphql/gqls/agent.ts","../src/lib/graphql/gqls/agentFile.ts","../src/lib/graphql/gqls/agentFunction.ts","../src/lib/graphql/gqls/vendor.ts","../src/lib/graphql/gqls/dataCategory.ts","../src/lib/graphql/gqls/processingPurpose.ts","../src/lib/graphql/gqls/processingActivity.ts","../src/lib/graphql/gqls/sombraVersion.ts","../src/lib/graphql/gqls/siloDiscoveryResult.ts","../src/lib/requests/constants.ts","../src/lib/requests/fuzzyMatchColumns.ts","../src/lib/requests/mapEnumValues.ts","../src/lib/requests/splitCsvToList.ts","../src/lib/requests/parseAttributesFromString.ts","../src/lib/requests/readCsv.ts","../src/lib/requests/getUniqueValuesForColumn.ts","../src/lib/requests/filterRows.ts","../src/lib/graphql/addMessagesToPromptRun.ts","../src/lib/graphql/buildTranscendGraphQLClient.ts","../src/lib/graphql/createSombraGotInstance.ts","../src/lib/graphql/createTranscendConsentGotInstance.ts","../src/lib/graphql/deployConsentManager.ts","../src/lib/graphql/fetchActiveSiloDiscoPlugin.ts","../src/lib/graphql/fetchAllActionItems.ts","../src/lib/graphql/fetchAllActions.ts","../src/lib/graphql/fetchAllAgentFiles.ts","../src/lib/graphql/fetchAllAgentFunctions.ts","../src/lib/graphql/fetchAllAgents.ts","../src/lib/graphql/fetchAllAssessments.ts","../src/lib/graphql/fetchAllAssessmentTemplates.ts","../src/lib/graphql/createPreferenceAccessTokens.ts","../src/lib/graphql/fetchAllAttributeKeys.ts","../src/lib/graphql/fetchAllAttributes.ts","../src/lib/graphql/fetchAllBusinessEntities.ts","../src/lib/graphql/fetchConsentManagerId.ts","../src/lib/graphql/fetchAllCookies.ts","../src/lib/graphql/fetchAllDataCategories.ts","../src/lib/graphql/fetchAllDataFlows.ts","../src/lib/graphql/fetchAllMessages.ts","../src/lib/graphql/fetchPrivacyCenterId.ts","../src/lib/graphql/fetchAllPolicies.ts","../src/lib/graphql/formatAttributeValues.ts","../src/lib/graphql/fetchAllPreferenceTopics.ts","../src/lib/graphql/fetchAllPrivacyCenters.ts","../src/lib/graphql/fetchAllProcessingActivities.ts","../src/lib/graphql/fetchAllProcessingPurposes.ts","../src/lib/graphql/fetchAllPurposes.ts","../src/lib/graphql/fetchAllPurposesAndPreferences.ts","../src/lib/graphql/fetchAllRequestEnrichers.ts","../src/lib/graphql/fetchAllRequestIdentifierMetadata.ts","../src/lib/graphql/fetchAllRequestIdentifiers.ts","../src/lib/graphql/fetchAllRequests.ts","../src/lib/graphql/fetchAllTeams.ts","../src/lib/graphql/fetchAllUsers.ts","../src/lib/graphql/fetchAllVendors.ts","../src/lib/graphql/fetchApiKeys.ts","../src/lib/graphql/fetchCatalogs.ts","../src/lib/graphql/fetchDataSubjects.ts","../src/lib/graphql/fetchPromptGroups.ts","../src/lib/graphql/fetchPromptPartials.ts","../src/lib/graphql/fetchPrompts.ts","../src/lib/graphql/fetchPromptThreads.ts","../src/lib/graphql/fetchRequestDataSilo.ts","../src/lib/graphql/fetchRequestDataSiloActiveCount.ts","../src/lib/graphql/fetchRequestFilesForRequest.ts","../src/lib/graphql/loginUser.ts","../src/lib/graphql/manageApiKeys.ts","../src/lib/graphql/parseAssessmentDisplayLogic.ts","../src/lib/graphql/parseAssessmentRiskLogic.ts","../src/lib/graphql/syncDataSilos.ts","../src/lib/graphql/syncEnrichers.ts","../src/lib/graphql/syncTemplates.ts","../src/lib/graphql/formatRegions.ts","../src/lib/graphql/fetchAllActionItemCollections.ts","../src/lib/graphql/syncPartitions.ts","../src/lib/graphql/fetchAllSiloDiscoveryResults.ts","../src/lib/graphql/pullTranscendConfiguration.ts","../src/lib/graphql/reportPromptRun.ts","../src/lib/graphql/retryRequestEnricher.ts","../src/lib/graphql/setResourceAttributes.ts","../src/lib/graphql/syncAction.ts","../src/lib/graphql/syncActionItemCollections.ts","../src/lib/graphql/syncActionItems.ts","../src/lib/graphql/syncAgentFiles.ts","../src/lib/graphql/syncAgentFunctions.ts","../src/lib/graphql/syncAgents.ts","../src/lib/graphql/syncAttribute.ts","../src/lib/graphql/syncBusinessEntities.ts","../src/lib/graphql/fetchAllCodePackages.ts","../src/lib/graphql/fetchAllSoftwareDevelopmentKits.ts","../src/lib/graphql/syncSoftwareDevelopmentKits.ts","../src/lib/graphql/fetchAllRepositories.ts","../src/lib/graphql/syncRepositories.ts","../src/lib/graphql/syncCodePackages.ts","../src/lib/graphql/syncConsentManager.ts","../src/lib/graphql/syncCookies.ts","../src/lib/graphql/syncDataCategories.ts","../src/lib/graphql/syncDataFlows.ts","../src/lib/graphql/syncDataSubject.ts","../src/lib/graphql/syncIdentifier.ts","../src/lib/graphql/syncIntlMessages.ts","../src/lib/graphql/syncPolicies.ts","../src/lib/graphql/syncPrivacyCenter.ts","../src/lib/graphql/syncProcessingActivities.ts","../src/lib/graphql/syncProcessingPurposes.ts","../src/lib/graphql/syncPrompts.ts","../src/lib/graphql/syncVendors.ts","../src/lib/graphql/uploadSiloDiscoveryResults.ts","../src/lib/requests/markSilentPrivacyRequests.ts","../src/lib/requests/mapCsvColumnsToApi.ts","../src/lib/requests/mapRequestEnumValues.ts","../src/lib/requests/mapCsvRowsToRequestInputs.ts","../src/lib/requests/getFileMetadataForPrivacyRequests.ts","../src/lib/requests/streamPrivacyRequestFiles.ts","../src/lib/requests/downloadPrivacyRequestFiles.ts","../src/lib/requests/submitPrivacyRequest.ts","../src/lib/requests/approvePrivacyRequests.ts","../src/lib/requests/notifyPrivacyRequestsAdditionalTime.ts","../src/lib/requests/mapColumnsToIdentifiers.ts","../src/lib/requests/cancelPrivacyRequests.ts","../src/lib/requests/mapColumnsToAttributes.ts","../src/lib/requests/extractClientError.ts","../src/lib/requests/uploadPrivacyRequestsFromCsv.ts","../src/lib/requests/restartPrivacyRequest.ts","../src/lib/requests/bulkRestartRequests.ts","../src/lib/requests/skipPreflightJobs.ts","../src/lib/requests/bulkRetryEnrichers.ts","../src/lib/requests/retryRequestDataSilos.ts","../src/lib/requests/pullPrivacyRequests.ts","../src/lib/requests/skipRequestDataSilos.ts","../src/lib/requests/removeUnverifiedRequestIdentifiers.ts","../src/lib/helpers/inquirer.ts","../src/lib/helpers/parseVariablesFromString.ts","../src/lib/helpers/getErrorStatus.ts","../src/lib/helpers/extractErrorMessage.ts","../src/lib/helpers/sleepPromise.ts","../src/lib/helpers/splitInHalf.ts","../src/lib/helpers/retrySamePromise.ts","../src/lib/helpers/limitRecords.ts","../src/lib/helpers/RateCounter.ts","../src/lib/helpers/readSafe.ts","../src/lib/helpers/collectParquetFilesOrExit.ts","../src/lib/helpers/parquetToCsvOneFile.ts","../src/lib/helpers/time.ts","../src/lib/helpers/writeCsv.ts","../src/lib/graphql/makeGraphQLRequest.ts","../src/lib/graphql/fetchIdentifiers.ts","../src/lib/graphql/syncTeams.ts","../src/lib/graphql/syncPromptPartials.ts","../src/lib/graphql/syncPromptGroups.ts","../src/lib/graphql/syncConfigurationToTranscend.ts"],"sourcesContent":["/** Used to match a single whitespace character. */\nvar reWhitespace = /\\s/;\n\n/**\n * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace\n * character of `string`.\n *\n * @private\n * @param {string} string The string to inspect.\n * @returns {number} Returns the index of the last non-whitespace character.\n */\nfunction trimmedEndIndex(string) {\n var index = string.length;\n\n while (index-- && reWhitespace.test(string.charAt(index))) {}\n return index;\n}\n\nexport default trimmedEndIndex;\n","import trimmedEndIndex from './_trimmedEndIndex.js';\n\n/** Used to match leading whitespace. */\nvar reTrimStart = /^\\s+/;\n\n/**\n * The base implementation of `_.trim`.\n *\n * @private\n * @param {string} string The string to trim.\n * @returns {string} Returns the trimmed string.\n */\nfunction baseTrim(string) {\n return string\n ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '')\n : string;\n}\n\nexport default baseTrim;\n","import baseTrim from './_baseTrim.js';\nimport isObject from './isObject.js';\nimport isSymbol from './isSymbol.js';\n\n/** Used as references for various `Number` constants. */\nvar NAN = 0 / 0;\n\n/** Used to detect bad signed hexadecimal string values. */\nvar reIsBadHex = /^[-+]0x[0-9a-f]+$/i;\n\n/** Used to detect binary string values. */\nvar reIsBinary = /^0b[01]+$/i;\n\n/** Used to detect octal string values. */\nvar reIsOctal = /^0o[0-7]+$/i;\n\n/** Built-in method references without a dependency on `root`. */\nvar freeParseInt = parseInt;\n\n/**\n * Converts `value` to a number.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to process.\n * @returns {number} Returns the number.\n * @example\n *\n * _.toNumber(3.2);\n * // => 3.2\n *\n * _.toNumber(Number.MIN_VALUE);\n * // => 5e-324\n *\n * _.toNumber(Infinity);\n * // => Infinity\n *\n * _.toNumber('3.2');\n * // => 3.2\n */\nfunction toNumber(value) {\n if (typeof value == 'number') {\n return value;\n }\n if (isSymbol(value)) {\n return NAN;\n }\n if (isObject(value)) {\n var other = typeof value.valueOf == 'function' ? value.valueOf() : value;\n value = isObject(other) ? (other + '') : other;\n }\n if (typeof value != 'string') {\n return value === 0 ? value : +value;\n }\n value = baseTrim(value);\n var isBinary = reIsBinary.test(value);\n return (isBinary || reIsOctal.test(value))\n ? freeParseInt(value.slice(2), isBinary ? 2 : 8)\n : (reIsBadHex.test(value) ? NAN : +value);\n}\n\nexport default toNumber;\n","import toNumber from './toNumber.js';\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0,\n MAX_INTEGER = 1.7976931348623157e+308;\n\n/**\n * Converts `value` to a finite number.\n *\n * @static\n * @memberOf _\n * @since 4.12.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {number} Returns the converted number.\n * @example\n *\n * _.toFinite(3.2);\n * // => 3.2\n *\n * _.toFinite(Number.MIN_VALUE);\n * // => 5e-324\n *\n * _.toFinite(Infinity);\n * // => 1.7976931348623157e+308\n *\n * _.toFinite('3.2');\n * // => 3.2\n */\nfunction toFinite(value) {\n if (!value) {\n return value === 0 ? value : 0;\n }\n value = toNumber(value);\n if (value === INFINITY || value === -INFINITY) {\n var sign = (value < 0 ? -1 : 1);\n return sign * MAX_INTEGER;\n }\n return value === value ? value : 0;\n}\n\nexport default toFinite;\n","import toFinite from './toFinite.js';\n\n/**\n * Converts `value` to an integer.\n *\n * **Note:** This method is loosely based on\n * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {number} Returns the converted integer.\n * @example\n *\n * _.toInteger(3.2);\n * // => 3\n *\n * _.toInteger(Number.MIN_VALUE);\n * // => 0\n *\n * _.toInteger(Infinity);\n * // => 1.7976931348623157e+308\n *\n * _.toInteger('3.2');\n * // => 3\n */\nfunction toInteger(value) {\n var result = toFinite(value),\n remainder = result % 1;\n\n return result === result ? (remainder ? result - remainder : result) : 0;\n}\n\nexport default toInteger;\n","/**\n * A faster alternative to `Function#apply`, this function invokes `func`\n * with the `this` binding of `thisArg` and the arguments of `args`.\n *\n * @private\n * @param {Function} func The function to invoke.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} args The arguments to invoke `func` with.\n * @returns {*} Returns the result of `func`.\n */\nfunction apply(func, thisArg, args) {\n switch (args.length) {\n case 0: return func.call(thisArg);\n case 1: return func.call(thisArg, args[0]);\n case 2: return func.call(thisArg, args[0], args[1]);\n case 3: return func.call(thisArg, args[0], args[1], args[2]);\n }\n return func.apply(thisArg, args);\n}\n\nexport default apply;\n","/**\n * This method returns `undefined`.\n *\n * @static\n * @memberOf _\n * @since 2.3.0\n * @category Util\n * @example\n *\n * _.times(2, _.noop);\n * // => [undefined, undefined]\n */\nfunction noop() {\n // No operation performed.\n}\n\nexport default noop;\n","/** Used to detect hot functions by number of calls within a span of milliseconds. */\nvar HOT_COUNT = 800,\n HOT_SPAN = 16;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeNow = Date.now;\n\n/**\n * Creates a function that'll short out and invoke `identity` instead\n * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`\n * milliseconds.\n *\n * @private\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new shortable function.\n */\nfunction shortOut(func) {\n var count = 0,\n lastCalled = 0;\n\n return function() {\n var stamp = nativeNow(),\n remaining = HOT_SPAN - (stamp - lastCalled);\n\n lastCalled = stamp;\n if (remaining > 0) {\n if (++count >= HOT_COUNT) {\n return arguments[0];\n }\n } else {\n count = 0;\n }\n return func.apply(undefined, arguments);\n };\n}\n\nexport default shortOut;\n","/**\n * Creates a function that returns `value`.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Util\n * @param {*} value The value to return from the new function.\n * @returns {Function} Returns the new constant function.\n * @example\n *\n * var objects = _.times(2, _.constant({ 'a': 1 }));\n *\n * console.log(objects);\n * // => [{ 'a': 1 }, { 'a': 1 }]\n *\n * console.log(objects[0] === objects[1]);\n * // => true\n */\nfunction constant(value) {\n return function() {\n return value;\n };\n}\n\nexport default constant;\n","import constant from './constant.js';\nimport defineProperty from './_defineProperty.js';\nimport identity from './identity.js';\n\n/**\n * The base implementation of `setToString` without support for hot loop shorting.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar baseSetToString = !defineProperty ? identity : function(func, string) {\n return defineProperty(func, 'toString', {\n 'configurable': true,\n 'enumerable': false,\n 'value': constant(string),\n 'writable': true\n });\n};\n\nexport default baseSetToString;\n","import baseSetToString from './_baseSetToString.js';\nimport shortOut from './_shortOut.js';\n\n/**\n * Sets the `toString` method of `func` to return `string`.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar setToString = shortOut(baseSetToString);\n\nexport default setToString;\n","/**\n * The base implementation of `_.findIndex` and `_.findLastIndex` without\n * support for iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Function} predicate The function invoked per iteration.\n * @param {number} fromIndex The index to search from.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction baseFindIndex(array, predicate, fromIndex, fromRight) {\n var length = array.length,\n index = fromIndex + (fromRight ? 1 : -1);\n\n while ((fromRight ? index-- : ++index < length)) {\n if (predicate(array[index], index, array)) {\n return index;\n }\n }\n return -1;\n}\n\nexport default baseFindIndex;\n","/**\n * The base implementation of `_.isNaN` without support for number objects.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.\n */\nfunction baseIsNaN(value) {\n return value !== value;\n}\n\nexport default baseIsNaN;\n","/**\n * A specialized version of `_.indexOf` which performs strict equality\n * comparisons of values, i.e. `===`.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction strictIndexOf(array, value, fromIndex) {\n var index = fromIndex - 1,\n length = array.length;\n\n while (++index < length) {\n if (array[index] === value) {\n return index;\n }\n }\n return -1;\n}\n\nexport default strictIndexOf;\n","import baseFindIndex from './_baseFindIndex.js';\nimport baseIsNaN from './_baseIsNaN.js';\nimport strictIndexOf from './_strictIndexOf.js';\n\n/**\n * The base implementation of `_.indexOf` without `fromIndex` bounds checks.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction baseIndexOf(array, value, fromIndex) {\n return value === value\n ? strictIndexOf(array, value, fromIndex)\n : baseFindIndex(array, baseIsNaN, fromIndex);\n}\n\nexport default baseIndexOf;\n","import baseIndexOf from './_baseIndexOf.js';\n\n/**\n * A specialized version of `_.includes` for arrays without support for\n * specifying an index to search from.\n *\n * @private\n * @param {Array} [array] The array to inspect.\n * @param {*} target The value to search for.\n * @returns {boolean} Returns `true` if `target` is found, else `false`.\n */\nfunction arrayIncludes(array, value) {\n var length = array == null ? 0 : array.length;\n return !!length && baseIndexOf(array, value, 0) > -1;\n}\n\nexport default arrayIncludes;\n","import apply from './_apply.js';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * A specialized version of `baseRest` which transforms the rest array.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @param {Function} transform The rest array transform.\n * @returns {Function} Returns the new function.\n */\nfunction overRest(func, start, transform) {\n start = nativeMax(start === undefined ? (func.length - 1) : start, 0);\n return function() {\n var args = arguments,\n index = -1,\n length = nativeMax(args.length - start, 0),\n array = Array(length);\n\n while (++index < length) {\n array[index] = args[start + index];\n }\n index = -1;\n var otherArgs = Array(start + 1);\n while (++index < start) {\n otherArgs[index] = args[index];\n }\n otherArgs[start] = transform(array);\n return apply(func, this, otherArgs);\n };\n}\n\nexport default overRest;\n","import identity from './identity.js';\nimport overRest from './_overRest.js';\nimport setToString from './_setToString.js';\n\n/**\n * The base implementation of `_.rest` which doesn't validate or coerce arguments.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @returns {Function} Returns the new function.\n */\nfunction baseRest(func, start) {\n return setToString(overRest(func, start, identity), func + '');\n}\n\nexport default baseRest;\n","import eq from './eq.js';\nimport isArrayLike from './isArrayLike.js';\nimport isIndex from './_isIndex.js';\nimport isObject from './isObject.js';\n\n/**\n * Checks if the given arguments are from an iteratee call.\n *\n * @private\n * @param {*} value The potential iteratee value argument.\n * @param {*} index The potential iteratee index or key argument.\n * @param {*} object The potential iteratee object argument.\n * @returns {boolean} Returns `true` if the arguments are from an iteratee call,\n * else `false`.\n */\nfunction isIterateeCall(value, index, object) {\n if (!isObject(object)) {\n return false;\n }\n var type = typeof index;\n if (type == 'number'\n ? (isArrayLike(object) && isIndex(index, object.length))\n : (type == 'string' && index in object)\n ) {\n return eq(object[index], value);\n }\n return false;\n}\n\nexport default isIterateeCall;\n","import Symbol from './_Symbol.js';\nimport isArguments from './isArguments.js';\nimport isArray from './isArray.js';\n\n/** Built-in value references. */\nvar spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined;\n\n/**\n * Checks if `value` is a flattenable `arguments` object or array.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.\n */\nfunction isFlattenable(value) {\n return isArray(value) || isArguments(value) ||\n !!(spreadableSymbol && value && value[spreadableSymbol]);\n}\n\nexport default isFlattenable;\n","import arrayPush from './_arrayPush.js';\nimport isFlattenable from './_isFlattenable.js';\n\n/**\n * The base implementation of `_.flatten` with support for restricting flattening.\n *\n * @private\n * @param {Array} array The array to flatten.\n * @param {number} depth The maximum recursion depth.\n * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.\n * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.\n * @param {Array} [result=[]] The initial result value.\n * @returns {Array} Returns the new flattened array.\n */\nfunction baseFlatten(array, depth, predicate, isStrict, result) {\n var index = -1,\n length = array.length;\n\n predicate || (predicate = isFlattenable);\n result || (result = []);\n\n while (++index < length) {\n var value = array[index];\n if (depth > 0 && predicate(value)) {\n if (depth > 1) {\n // Recursively flatten arrays (susceptible to call stack limits).\n baseFlatten(value, depth - 1, predicate, isStrict, result);\n } else {\n arrayPush(result, value);\n }\n } else if (!isStrict) {\n result[result.length] = value;\n }\n }\n return result;\n}\n\nexport default baseFlatten;\n","import baseFlatten from './_baseFlatten.js';\n\n/**\n * Flattens `array` a single level deep.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to flatten.\n * @returns {Array} Returns the new flattened array.\n * @example\n *\n * _.flatten([1, [2, [3, [4]], 5]]);\n * // => [1, 2, [3, [4]], 5]\n */\nfunction flatten(array) {\n var length = array == null ? 0 : array.length;\n return length ? baseFlatten(array, 1) : [];\n}\n\nexport default flatten;\n","/**\n * The base implementation of `_.slice` without an iteratee call guard.\n *\n * @private\n * @param {Array} array The array to slice.\n * @param {number} [start=0] The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns the slice of `array`.\n */\nfunction baseSlice(array, start, end) {\n var index = -1,\n length = array.length;\n\n if (start < 0) {\n start = -start > length ? 0 : (length + start);\n }\n end = end > length ? length : end;\n if (end < 0) {\n end += length;\n }\n length = start > end ? 0 : ((end - start) >>> 0);\n start >>>= 0;\n\n var result = Array(length);\n while (++index < length) {\n result[index] = array[index + start];\n }\n return result;\n}\n\nexport default baseSlice;\n","import baseSlice from './_baseSlice.js';\n\n/**\n * Casts `array` to a slice if it's needed.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {number} start The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns the cast slice.\n */\nfunction castSlice(array, start, end) {\n var length = array.length;\n end = end === undefined ? length : end;\n return (!start && end >= length) ? array : baseSlice(array, start, end);\n}\n\nexport default castSlice;\n","/** Used to compose unicode character classes. */\nvar rsAstralRange = '\\\\ud800-\\\\udfff',\n rsComboMarksRange = '\\\\u0300-\\\\u036f',\n reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,\n rsVarRange = '\\\\ufe0e\\\\ufe0f';\n\n/** Used to compose unicode capture groups. */\nvar rsZWJ = '\\\\u200d';\n\n/** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */\nvar reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');\n\n/**\n * Checks if `string` contains Unicode symbols.\n *\n * @private\n * @param {string} string The string to inspect.\n * @returns {boolean} Returns `true` if a symbol is found, else `false`.\n */\nfunction hasUnicode(string) {\n return reHasUnicode.test(string);\n}\n\nexport default hasUnicode;\n","/**\n * Converts an ASCII `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\nfunction asciiToArray(string) {\n return string.split('');\n}\n\nexport default asciiToArray;\n","/** Used to compose unicode character classes. */\nvar rsAstralRange = '\\\\ud800-\\\\udfff',\n rsComboMarksRange = '\\\\u0300-\\\\u036f',\n reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,\n rsVarRange = '\\\\ufe0e\\\\ufe0f';\n\n/** Used to compose unicode capture groups. */\nvar rsAstral = '[' + rsAstralRange + ']',\n rsCombo = '[' + rsComboRange + ']',\n rsFitz = '\\\\ud83c[\\\\udffb-\\\\udfff]',\n rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',\n rsNonAstral = '[^' + rsAstralRange + ']',\n rsRegional = '(?:\\\\ud83c[\\\\udde6-\\\\uddff]){2}',\n rsSurrPair = '[\\\\ud800-\\\\udbff][\\\\udc00-\\\\udfff]',\n rsZWJ = '\\\\u200d';\n\n/** Used to compose unicode regexes. */\nvar reOptMod = rsModifier + '?',\n rsOptVar = '[' + rsVarRange + ']?',\n rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',\n rsSeq = rsOptVar + reOptMod + rsOptJoin,\n rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';\n\n/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */\nvar reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');\n\n/**\n * Converts a Unicode `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\nfunction unicodeToArray(string) {\n return string.match(reUnicode) || [];\n}\n\nexport default unicodeToArray;\n","import asciiToArray from './_asciiToArray.js';\nimport hasUnicode from './_hasUnicode.js';\nimport unicodeToArray from './_unicodeToArray.js';\n\n/**\n * Converts `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\nfunction stringToArray(string) {\n return hasUnicode(string)\n ? unicodeToArray(string)\n : asciiToArray(string);\n}\n\nexport default stringToArray;\n","import castSlice from './_castSlice.js';\nimport hasUnicode from './_hasUnicode.js';\nimport stringToArray from './_stringToArray.js';\nimport toString from './toString.js';\n\n/**\n * Creates a function like `_.lowerFirst`.\n *\n * @private\n * @param {string} methodName The name of the `String` case method to use.\n * @returns {Function} Returns the new case function.\n */\nfunction createCaseFirst(methodName) {\n return function(string) {\n string = toString(string);\n\n var strSymbols = hasUnicode(string)\n ? stringToArray(string)\n : undefined;\n\n var chr = strSymbols\n ? strSymbols[0]\n : string.charAt(0);\n\n var trailing = strSymbols\n ? castSlice(strSymbols, 1).join('')\n : string.slice(1);\n\n return chr[methodName]() + trailing;\n };\n}\n\nexport default createCaseFirst;\n","import createCaseFirst from './_createCaseFirst.js';\n\n/**\n * Converts the first character of `string` to upper case.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the converted string.\n * @example\n *\n * _.upperFirst('fred');\n * // => 'Fred'\n *\n * _.upperFirst('FRED');\n * // => 'FRED'\n */\nvar upperFirst = createCaseFirst('toUpperCase');\n\nexport default upperFirst;\n","/**\n * A specialized version of `_.reduce` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {*} [accumulator] The initial value.\n * @param {boolean} [initAccum] Specify using the first element of `array` as\n * the initial value.\n * @returns {*} Returns the accumulated value.\n */\nfunction arrayReduce(array, iteratee, accumulator, initAccum) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n if (initAccum && length) {\n accumulator = array[++index];\n }\n while (++index < length) {\n accumulator = iteratee(accumulator, array[index], index, array);\n }\n return accumulator;\n}\n\nexport default arrayReduce;\n","/**\n * The base implementation of `_.propertyOf` without support for deep paths.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Function} Returns the new accessor function.\n */\nfunction basePropertyOf(object) {\n return function(key) {\n return object == null ? undefined : object[key];\n };\n}\n\nexport default basePropertyOf;\n","import basePropertyOf from './_basePropertyOf.js';\n\n/** Used to map Latin Unicode letters to basic Latin letters. */\nvar deburredLetters = {\n // Latin-1 Supplement block.\n '\\xc0': 'A', '\\xc1': 'A', '\\xc2': 'A', '\\xc3': 'A', '\\xc4': 'A', '\\xc5': 'A',\n '\\xe0': 'a', '\\xe1': 'a', '\\xe2': 'a', '\\xe3': 'a', '\\xe4': 'a', '\\xe5': 'a',\n '\\xc7': 'C', '\\xe7': 'c',\n '\\xd0': 'D', '\\xf0': 'd',\n '\\xc8': 'E', '\\xc9': 'E', '\\xca': 'E', '\\xcb': 'E',\n '\\xe8': 'e', '\\xe9': 'e', '\\xea': 'e', '\\xeb': 'e',\n '\\xcc': 'I', '\\xcd': 'I', '\\xce': 'I', '\\xcf': 'I',\n '\\xec': 'i', '\\xed': 'i', '\\xee': 'i', '\\xef': 'i',\n '\\xd1': 'N', '\\xf1': 'n',\n '\\xd2': 'O', '\\xd3': 'O', '\\xd4': 'O', '\\xd5': 'O', '\\xd6': 'O', '\\xd8': 'O',\n '\\xf2': 'o', '\\xf3': 'o', '\\xf4': 'o', '\\xf5': 'o', '\\xf6': 'o', '\\xf8': 'o',\n '\\xd9': 'U', '\\xda': 'U', '\\xdb': 'U', '\\xdc': 'U',\n '\\xf9': 'u', '\\xfa': 'u', '\\xfb': 'u', '\\xfc': 'u',\n '\\xdd': 'Y', '\\xfd': 'y', '\\xff': 'y',\n '\\xc6': 'Ae', '\\xe6': 'ae',\n '\\xde': 'Th', '\\xfe': 'th',\n '\\xdf': 'ss',\n // Latin Extended-A block.\n '\\u0100': 'A', '\\u0102': 'A', '\\u0104': 'A',\n '\\u0101': 'a', '\\u0103': 'a', '\\u0105': 'a',\n '\\u0106': 'C', '\\u0108': 'C', '\\u010a': 'C', '\\u010c': 'C',\n '\\u0107': 'c', '\\u0109': 'c', '\\u010b': 'c', '\\u010d': 'c',\n '\\u010e': 'D', '\\u0110': 'D', '\\u010f': 'd', '\\u0111': 'd',\n '\\u0112': 'E', '\\u0114': 'E', '\\u0116': 'E', '\\u0118': 'E', '\\u011a': 'E',\n '\\u0113': 'e', '\\u0115': 'e', '\\u0117': 'e', '\\u0119': 'e', '\\u011b': 'e',\n '\\u011c': 'G', '\\u011e': 'G', '\\u0120': 'G', '\\u0122': 'G',\n '\\u011d': 'g', '\\u011f': 'g', '\\u0121': 'g', '\\u0123': 'g',\n '\\u0124': 'H', '\\u0126': 'H', '\\u0125': 'h', '\\u0127': 'h',\n '\\u0128': 'I', '\\u012a': 'I', '\\u012c': 'I', '\\u012e': 'I', '\\u0130': 'I',\n '\\u0129': 'i', '\\u012b': 'i', '\\u012d': 'i', '\\u012f': 'i', '\\u0131': 'i',\n '\\u0134': 'J', '\\u0135': 'j',\n '\\u0136': 'K', '\\u0137': 'k', '\\u0138': 'k',\n '\\u0139': 'L', '\\u013b': 'L', '\\u013d': 'L', '\\u013f': 'L', '\\u0141': 'L',\n '\\u013a': 'l', '\\u013c': 'l', '\\u013e': 'l', '\\u0140': 'l', '\\u0142': 'l',\n '\\u0143': 'N', '\\u0145': 'N', '\\u0147': 'N', '\\u014a': 'N',\n '\\u0144': 'n', '\\u0146': 'n', '\\u0148': 'n', '\\u014b': 'n',\n '\\u014c': 'O', '\\u014e': 'O', '\\u0150': 'O',\n '\\u014d': 'o', '\\u014f': 'o', '\\u0151': 'o',\n '\\u0154': 'R', '\\u0156': 'R', '\\u0158': 'R',\n '\\u0155': 'r', '\\u0157': 'r', '\\u0159': 'r',\n '\\u015a': 'S', '\\u015c': 'S', '\\u015e': 'S', '\\u0160': 'S',\n '\\u015b': 's', '\\u015d': 's', '\\u015f': 's', '\\u0161': 's',\n '\\u0162': 'T', '\\u0164': 'T', '\\u0166': 'T',\n '\\u0163': 't', '\\u0165': 't', '\\u0167': 't',\n '\\u0168': 'U', '\\u016a': 'U', '\\u016c': 'U', '\\u016e': 'U', '\\u0170': 'U', '\\u0172': 'U',\n '\\u0169': 'u', '\\u016b': 'u', '\\u016d': 'u', '\\u016f': 'u', '\\u0171': 'u', '\\u0173': 'u',\n '\\u0174': 'W', '\\u0175': 'w',\n '\\u0176': 'Y', '\\u0177': 'y', '\\u0178': 'Y',\n '\\u0179': 'Z', '\\u017b': 'Z', '\\u017d': 'Z',\n '\\u017a': 'z', '\\u017c': 'z', '\\u017e': 'z',\n '\\u0132': 'IJ', '\\u0133': 'ij',\n '\\u0152': 'Oe', '\\u0153': 'oe',\n '\\u0149': \"'n\", '\\u017f': 's'\n};\n\n/**\n * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A\n * letters to basic Latin letters.\n *\n * @private\n * @param {string} letter The matched letter to deburr.\n * @returns {string} Returns the deburred letter.\n */\nvar deburrLetter = basePropertyOf(deburredLetters);\n\nexport default deburrLetter;\n","import deburrLetter from './_deburrLetter.js';\nimport toString from './toString.js';\n\n/** Used to match Latin Unicode letters (excluding mathematical operators). */\nvar reLatin = /[\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\xff\\u0100-\\u017f]/g;\n\n/** Used to compose unicode character classes. */\nvar rsComboMarksRange = '\\\\u0300-\\\\u036f',\n reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange;\n\n/** Used to compose unicode capture groups. */\nvar rsCombo = '[' + rsComboRange + ']';\n\n/**\n * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and\n * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).\n */\nvar reComboMark = RegExp(rsCombo, 'g');\n\n/**\n * Deburrs `string` by converting\n * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)\n * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)\n * letters to basic Latin letters and removing\n * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to deburr.\n * @returns {string} Returns the deburred string.\n * @example\n *\n * _.deburr('déjà vu');\n * // => 'deja vu'\n */\nfunction deburr(string) {\n string = toString(string);\n return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');\n}\n\nexport default deburr;\n","/** Used to match words composed of alphanumeric characters. */\nvar reAsciiWord = /[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\x7f]+/g;\n\n/**\n * Splits an ASCII `string` into an array of its words.\n *\n * @private\n * @param {string} The string to inspect.\n * @returns {Array} Returns the words of `string`.\n */\nfunction asciiWords(string) {\n return string.match(reAsciiWord) || [];\n}\n\nexport default asciiWords;\n","/** Used to detect strings that need a more robust regexp to match words. */\nvar reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;\n\n/**\n * Checks if `string` contains a word composed of Unicode symbols.\n *\n * @private\n * @param {string} string The string to inspect.\n * @returns {boolean} Returns `true` if a word is found, else `false`.\n */\nfunction hasUnicodeWord(string) {\n return reHasUnicodeWord.test(string);\n}\n\nexport default hasUnicodeWord;\n","/** Used to compose unicode character classes. */\nvar rsAstralRange = '\\\\ud800-\\\\udfff',\n rsComboMarksRange = '\\\\u0300-\\\\u036f',\n reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,\n rsDingbatRange = '\\\\u2700-\\\\u27bf',\n rsLowerRange = 'a-z\\\\xdf-\\\\xf6\\\\xf8-\\\\xff',\n rsMathOpRange = '\\\\xac\\\\xb1\\\\xd7\\\\xf7',\n rsNonCharRange = '\\\\x00-\\\\x2f\\\\x3a-\\\\x40\\\\x5b-\\\\x60\\\\x7b-\\\\xbf',\n rsPunctuationRange = '\\\\u2000-\\\\u206f',\n rsSpaceRange = ' \\\\t\\\\x0b\\\\f\\\\xa0\\\\ufeff\\\\n\\\\r\\\\u2028\\\\u2029\\\\u1680\\\\u180e\\\\u2000\\\\u2001\\\\u2002\\\\u2003\\\\u2004\\\\u2005\\\\u2006\\\\u2007\\\\u2008\\\\u2009\\\\u200a\\\\u202f\\\\u205f\\\\u3000',\n rsUpperRange = 'A-Z\\\\xc0-\\\\xd6\\\\xd8-\\\\xde',\n rsVarRange = '\\\\ufe0e\\\\ufe0f',\n rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;\n\n/** Used to compose unicode capture groups. */\nvar rsApos = \"['\\u2019]\",\n rsBreak = '[' + rsBreakRange + ']',\n rsCombo = '[' + rsComboRange + ']',\n rsDigits = '\\\\d+',\n rsDingbat = '[' + rsDingbatRange + ']',\n rsLower = '[' + rsLowerRange + ']',\n rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',\n rsFitz = '\\\\ud83c[\\\\udffb-\\\\udfff]',\n rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',\n rsNonAstral = '[^' + rsAstralRange + ']',\n rsRegional = '(?:\\\\ud83c[\\\\udde6-\\\\uddff]){2}',\n rsSurrPair = '[\\\\ud800-\\\\udbff][\\\\udc00-\\\\udfff]',\n rsUpper = '[' + rsUpperRange + ']',\n rsZWJ = '\\\\u200d';\n\n/** Used to compose unicode regexes. */\nvar rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')',\n rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')',\n rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',\n rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',\n reOptMod = rsModifier + '?',\n rsOptVar = '[' + rsVarRange + ']?',\n rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',\n rsOrdLower = '\\\\d*(?:1st|2nd|3rd|(?![123])\\\\dth)(?=\\\\b|[A-Z_])',\n rsOrdUpper = '\\\\d*(?:1ST|2ND|3RD|(?![123])\\\\dTH)(?=\\\\b|[a-z_])',\n rsSeq = rsOptVar + reOptMod + rsOptJoin,\n rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq;\n\n/** Used to match complex or compound words. */\nvar reUnicodeWord = RegExp([\n rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',\n rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')',\n rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower,\n rsUpper + '+' + rsOptContrUpper,\n rsOrdUpper,\n rsOrdLower,\n rsDigits,\n rsEmoji\n].join('|'), 'g');\n\n/**\n * Splits a Unicode `string` into an array of its words.\n *\n * @private\n * @param {string} The string to inspect.\n * @returns {Array} Returns the words of `string`.\n */\nfunction unicodeWords(string) {\n return string.match(reUnicodeWord) || [];\n}\n\nexport default unicodeWords;\n","import asciiWords from './_asciiWords.js';\nimport hasUnicodeWord from './_hasUnicodeWord.js';\nimport toString from './toString.js';\nimport unicodeWords from './_unicodeWords.js';\n\n/**\n * Splits `string` into an array of its words.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to inspect.\n * @param {RegExp|string} [pattern] The pattern to match words.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Array} Returns the words of `string`.\n * @example\n *\n * _.words('fred, barney, & pebbles');\n * // => ['fred', 'barney', 'pebbles']\n *\n * _.words('fred, barney, & pebbles', /[^, ]+/g);\n * // => ['fred', 'barney', '&', 'pebbles']\n */\nfunction words(string, pattern, guard) {\n string = toString(string);\n pattern = guard ? undefined : pattern;\n\n if (pattern === undefined) {\n return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);\n }\n return string.match(pattern) || [];\n}\n\nexport default words;\n","import arrayReduce from './_arrayReduce.js';\nimport deburr from './deburr.js';\nimport words from './words.js';\n\n/** Used to compose unicode capture groups. */\nvar rsApos = \"['\\u2019]\";\n\n/** Used to match apostrophes. */\nvar reApos = RegExp(rsApos, 'g');\n\n/**\n * Creates a function like `_.camelCase`.\n *\n * @private\n * @param {Function} callback The function to combine each word.\n * @returns {Function} Returns the new compounder function.\n */\nfunction createCompounder(callback) {\n return function(string) {\n return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');\n };\n}\n\nexport default createCompounder;\n","import baseSlice from './_baseSlice.js';\nimport isIterateeCall from './_isIterateeCall.js';\nimport toInteger from './toInteger.js';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeCeil = Math.ceil,\n nativeMax = Math.max;\n\n/**\n * Creates an array of elements split into groups the length of `size`.\n * If `array` can't be split evenly, the final chunk will be the remaining\n * elements.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to process.\n * @param {number} [size=1] The length of each chunk\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Array} Returns the new array of chunks.\n * @example\n *\n * _.chunk(['a', 'b', 'c', 'd'], 2);\n * // => [['a', 'b'], ['c', 'd']]\n *\n * _.chunk(['a', 'b', 'c', 'd'], 3);\n * // => [['a', 'b', 'c'], ['d']]\n */\nfunction chunk(array, size, guard) {\n if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) {\n size = 1;\n } else {\n size = nativeMax(toInteger(size), 0);\n }\n var length = array == null ? 0 : array.length;\n if (!length || size < 1) {\n return [];\n }\n var index = 0,\n resIndex = 0,\n result = Array(nativeCeil(length / size));\n\n while (index < length) {\n result[resIndex++] = baseSlice(array, index, (index += size));\n }\n return result;\n}\n\nexport default chunk;\n","import isArrayLike from './isArrayLike.js';\nimport isObjectLike from './isObjectLike.js';\n\n/**\n * This method is like `_.isArrayLike` except that it also checks if `value`\n * is an object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array-like object,\n * else `false`.\n * @example\n *\n * _.isArrayLikeObject([1, 2, 3]);\n * // => true\n *\n * _.isArrayLikeObject(document.body.children);\n * // => true\n *\n * _.isArrayLikeObject('abc');\n * // => false\n *\n * _.isArrayLikeObject(_.noop);\n * // => false\n */\nfunction isArrayLikeObject(value) {\n return isObjectLike(value) && isArrayLike(value);\n}\n\nexport default isArrayLikeObject;\n","/**\n * This function is like `arrayIncludes` except that it accepts a comparator.\n *\n * @private\n * @param {Array} [array] The array to inspect.\n * @param {*} target The value to search for.\n * @param {Function} comparator The comparator invoked per element.\n * @returns {boolean} Returns `true` if `target` is found, else `false`.\n */\nfunction arrayIncludesWith(array, value, comparator) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (comparator(value, array[index])) {\n return true;\n }\n }\n return false;\n}\n\nexport default arrayIncludesWith;\n","import SetCache from './_SetCache.js';\nimport arrayIncludes from './_arrayIncludes.js';\nimport arrayIncludesWith from './_arrayIncludesWith.js';\nimport arrayMap from './_arrayMap.js';\nimport baseUnary from './_baseUnary.js';\nimport cacheHas from './_cacheHas.js';\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/**\n * The base implementation of methods like `_.difference` without support\n * for excluding multiple arrays or iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Array} values The values to exclude.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of filtered values.\n */\nfunction baseDifference(array, values, iteratee, comparator) {\n var index = -1,\n includes = arrayIncludes,\n isCommon = true,\n length = array.length,\n result = [],\n valuesLength = values.length;\n\n if (!length) {\n return result;\n }\n if (iteratee) {\n values = arrayMap(values, baseUnary(iteratee));\n }\n if (comparator) {\n includes = arrayIncludesWith;\n isCommon = false;\n }\n else if (values.length >= LARGE_ARRAY_SIZE) {\n includes = cacheHas;\n isCommon = false;\n values = new SetCache(values);\n }\n outer:\n while (++index < length) {\n var value = array[index],\n computed = iteratee == null ? value : iteratee(value);\n\n value = (comparator || value !== 0) ? value : 0;\n if (isCommon && computed === computed) {\n var valuesIndex = valuesLength;\n while (valuesIndex--) {\n if (values[valuesIndex] === computed) {\n continue outer;\n }\n }\n result.push(value);\n }\n else if (!includes(values, computed, comparator)) {\n result.push(value);\n }\n }\n return result;\n}\n\nexport default baseDifference;\n","import baseDifference from './_baseDifference.js';\nimport baseFlatten from './_baseFlatten.js';\nimport baseRest from './_baseRest.js';\nimport isArrayLikeObject from './isArrayLikeObject.js';\n\n/**\n * Creates an array of `array` values not included in the other given arrays\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons. The order and references of result values are\n * determined by the first array.\n *\n * **Note:** Unlike `_.pullAll`, this method returns a new array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {...Array} [values] The values to exclude.\n * @returns {Array} Returns the new array of filtered values.\n * @see _.without, _.xor\n * @example\n *\n * _.difference([2, 1], [2, 3]);\n * // => [1]\n */\nvar difference = baseRest(function(array, values) {\n return isArrayLikeObject(array)\n ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))\n : [];\n});\n\nexport default difference;\n","import baseEach from './_baseEach.js';\nimport isArrayLike from './isArrayLike.js';\n\n/**\n * The base implementation of `_.map` without support for iteratee shorthands.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction baseMap(collection, iteratee) {\n var index = -1,\n result = isArrayLike(collection) ? Array(collection.length) : [];\n\n baseEach(collection, function(value, key, collection) {\n result[++index] = iteratee(value, key, collection);\n });\n return result;\n}\n\nexport default baseMap;\n","import baseAssignValue from './_baseAssignValue.js';\nimport createAggregator from './_createAggregator.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Creates an object composed of keys generated from the results of running\n * each element of `collection` thru `iteratee`. The order of grouped values\n * is determined by the order they occur in `collection`. The corresponding\n * value of each key is an array of elements responsible for generating the\n * key. The iteratee is invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The iteratee to transform keys.\n * @returns {Object} Returns the composed aggregate object.\n * @example\n *\n * _.groupBy([6.1, 4.2, 6.3], Math.floor);\n * // => { '4': [4.2], '6': [6.1, 6.3] }\n *\n * // The `_.property` iteratee shorthand.\n * _.groupBy(['one', 'two', 'three'], 'length');\n * // => { '3': ['one', 'two'], '5': ['three'] }\n */\nvar groupBy = createAggregator(function(result, value, key) {\n if (hasOwnProperty.call(result, key)) {\n result[key].push(value);\n } else {\n baseAssignValue(result, key, [value]);\n }\n});\n\nexport default groupBy;\n","import baseAssignValue from './_baseAssignValue.js';\nimport baseForOwn from './_baseForOwn.js';\nimport baseIteratee from './_baseIteratee.js';\n\n/**\n * Creates an object with the same keys as `object` and values generated\n * by running each own enumerable string keyed property of `object` thru\n * `iteratee`. The iteratee is invoked with three arguments:\n * (value, key, object).\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Object} Returns the new mapped object.\n * @see _.mapKeys\n * @example\n *\n * var users = {\n * 'fred': { 'user': 'fred', 'age': 40 },\n * 'pebbles': { 'user': 'pebbles', 'age': 1 }\n * };\n *\n * _.mapValues(users, function(o) { return o.age; });\n * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)\n *\n * // The `_.property` iteratee shorthand.\n * _.mapValues(users, 'age');\n * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)\n */\nfunction mapValues(object, iteratee) {\n var result = {};\n iteratee = baseIteratee(iteratee, 3);\n\n baseForOwn(object, function(value, key, object) {\n baseAssignValue(result, key, iteratee(value, key, object));\n });\n return result;\n}\n\nexport default mapValues;\n","/**\n * The base implementation of `_.sortBy` which uses `comparer` to define the\n * sort order of `array` and replaces criteria objects with their corresponding\n * values.\n *\n * @private\n * @param {Array} array The array to sort.\n * @param {Function} comparer The function to define sort order.\n * @returns {Array} Returns `array`.\n */\nfunction baseSortBy(array, comparer) {\n var length = array.length;\n\n array.sort(comparer);\n while (length--) {\n array[length] = array[length].value;\n }\n return array;\n}\n\nexport default baseSortBy;\n","import isSymbol from './isSymbol.js';\n\n/**\n * Compares values to sort them in ascending order.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {number} Returns the sort order indicator for `value`.\n */\nfunction compareAscending(value, other) {\n if (value !== other) {\n var valIsDefined = value !== undefined,\n valIsNull = value === null,\n valIsReflexive = value === value,\n valIsSymbol = isSymbol(value);\n\n var othIsDefined = other !== undefined,\n othIsNull = other === null,\n othIsReflexive = other === other,\n othIsSymbol = isSymbol(other);\n\n if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||\n (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||\n (valIsNull && othIsDefined && othIsReflexive) ||\n (!valIsDefined && othIsReflexive) ||\n !valIsReflexive) {\n return 1;\n }\n if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||\n (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||\n (othIsNull && valIsDefined && valIsReflexive) ||\n (!othIsDefined && valIsReflexive) ||\n !othIsReflexive) {\n return -1;\n }\n }\n return 0;\n}\n\nexport default compareAscending;\n","import compareAscending from './_compareAscending.js';\n\n/**\n * Used by `_.orderBy` to compare multiple properties of a value to another\n * and stable sort them.\n *\n * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,\n * specify an order of \"desc\" for descending or \"asc\" for ascending sort order\n * of corresponding values.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {boolean[]|string[]} orders The order to sort by for each property.\n * @returns {number} Returns the sort order indicator for `object`.\n */\nfunction compareMultiple(object, other, orders) {\n var index = -1,\n objCriteria = object.criteria,\n othCriteria = other.criteria,\n length = objCriteria.length,\n ordersLength = orders.length;\n\n while (++index < length) {\n var result = compareAscending(objCriteria[index], othCriteria[index]);\n if (result) {\n if (index >= ordersLength) {\n return result;\n }\n var order = orders[index];\n return result * (order == 'desc' ? -1 : 1);\n }\n }\n // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications\n // that causes it, under certain circumstances, to provide the same value for\n // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247\n // for more details.\n //\n // This also ensures a stable sort in V8 and other engines.\n // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.\n return object.index - other.index;\n}\n\nexport default compareMultiple;\n","import arrayMap from './_arrayMap.js';\nimport baseGet from './_baseGet.js';\nimport baseIteratee from './_baseIteratee.js';\nimport baseMap from './_baseMap.js';\nimport baseSortBy from './_baseSortBy.js';\nimport baseUnary from './_baseUnary.js';\nimport compareMultiple from './_compareMultiple.js';\nimport identity from './identity.js';\nimport isArray from './isArray.js';\n\n/**\n * The base implementation of `_.orderBy` without param guards.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.\n * @param {string[]} orders The sort orders of `iteratees`.\n * @returns {Array} Returns the new sorted array.\n */\nfunction baseOrderBy(collection, iteratees, orders) {\n if (iteratees.length) {\n iteratees = arrayMap(iteratees, function(iteratee) {\n if (isArray(iteratee)) {\n return function(value) {\n return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee);\n }\n }\n return iteratee;\n });\n } else {\n iteratees = [identity];\n }\n\n var index = -1;\n iteratees = arrayMap(iteratees, baseUnary(baseIteratee));\n\n var result = baseMap(collection, function(value, key, collection) {\n var criteria = arrayMap(iteratees, function(iteratee) {\n return iteratee(value);\n });\n return { 'criteria': criteria, 'index': ++index, 'value': value };\n });\n\n return baseSortBy(result, function(object, other) {\n return compareMultiple(object, other, orders);\n });\n}\n\nexport default baseOrderBy;\n","import baseFlatten from './_baseFlatten.js';\nimport baseOrderBy from './_baseOrderBy.js';\nimport baseRest from './_baseRest.js';\nimport isIterateeCall from './_isIterateeCall.js';\n\n/**\n * Creates an array of elements, sorted in ascending order by the results of\n * running each element in a collection thru each iteratee. This method\n * performs a stable sort, that is, it preserves the original sort order of\n * equal elements. The iteratees are invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {...(Function|Function[])} [iteratees=[_.identity]]\n * The iteratees to sort by.\n * @returns {Array} Returns the new sorted array.\n * @example\n *\n * var users = [\n * { 'user': 'fred', 'age': 48 },\n * { 'user': 'barney', 'age': 36 },\n * { 'user': 'fred', 'age': 30 },\n * { 'user': 'barney', 'age': 34 }\n * ];\n *\n * _.sortBy(users, [function(o) { return o.user; }]);\n * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 30]]\n *\n * _.sortBy(users, ['user', 'age']);\n * // => objects for [['barney', 34], ['barney', 36], ['fred', 30], ['fred', 48]]\n */\nvar sortBy = baseRest(function(collection, iteratees) {\n if (collection == null) {\n return [];\n }\n var length = iteratees.length;\n if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {\n iteratees = [];\n } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {\n iteratees = [iteratees[0]];\n }\n return baseOrderBy(collection, baseFlatten(iteratees, 1), []);\n});\n\nexport default sortBy;\n","import createCompounder from './_createCompounder.js';\nimport upperFirst from './upperFirst.js';\n\n/**\n * Converts `string` to\n * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).\n *\n * @static\n * @memberOf _\n * @since 3.1.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the start cased string.\n * @example\n *\n * _.startCase('--foo-bar--');\n * // => 'Foo Bar'\n *\n * _.startCase('fooBar');\n * // => 'Foo Bar'\n *\n * _.startCase('__FOO_BAR__');\n * // => 'FOO BAR'\n */\nvar startCase = createCompounder(function(result, word, index) {\n return result + (index ? ' ' : '') + upperFirst(word);\n});\n\nexport default startCase;\n","import Set from './_Set.js';\nimport noop from './noop.js';\nimport setToArray from './_setToArray.js';\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0;\n\n/**\n * Creates a set object of `values`.\n *\n * @private\n * @param {Array} values The values to add to the set.\n * @returns {Object} Returns the new set.\n */\nvar createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {\n return new Set(values);\n};\n\nexport default createSet;\n","import SetCache from './_SetCache.js';\nimport arrayIncludes from './_arrayIncludes.js';\nimport arrayIncludesWith from './_arrayIncludesWith.js';\nimport cacheHas from './_cacheHas.js';\nimport createSet from './_createSet.js';\nimport setToArray from './_setToArray.js';\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/**\n * The base implementation of `_.uniqBy` without support for iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n */\nfunction baseUniq(array, iteratee, comparator) {\n var index = -1,\n includes = arrayIncludes,\n length = array.length,\n isCommon = true,\n result = [],\n seen = result;\n\n if (comparator) {\n isCommon = false;\n includes = arrayIncludesWith;\n }\n else if (length >= LARGE_ARRAY_SIZE) {\n var set = iteratee ? null : createSet(array);\n if (set) {\n return setToArray(set);\n }\n isCommon = false;\n includes = cacheHas;\n seen = new SetCache;\n }\n else {\n seen = iteratee ? [] : result;\n }\n outer:\n while (++index < length) {\n var value = array[index],\n computed = iteratee ? iteratee(value) : value;\n\n value = (comparator || value !== 0) ? value : 0;\n if (isCommon && computed === computed) {\n var seenIndex = seen.length;\n while (seenIndex--) {\n if (seen[seenIndex] === computed) {\n continue outer;\n }\n }\n if (iteratee) {\n seen.push(computed);\n }\n result.push(value);\n }\n else if (!includes(seen, computed, comparator)) {\n if (seen !== result) {\n seen.push(computed);\n }\n result.push(value);\n }\n }\n return result;\n}\n\nexport default baseUniq;\n","import baseUniq from './_baseUniq.js';\n\n/**\n * Creates a duplicate-free version of an array, using\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons, in which only the first occurrence of each element\n * is kept. The order of result values is determined by the order they occur\n * in the array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @returns {Array} Returns the new duplicate free array.\n * @example\n *\n * _.uniq([2, 1, 2]);\n * // => [2, 1]\n */\nfunction uniq(array) {\n return (array && array.length) ? baseUniq(array) : [];\n}\n\nexport default uniq;\n","import baseIteratee from './_baseIteratee.js';\nimport baseUniq from './_baseUniq.js';\n\n/**\n * This method is like `_.uniq` except that it accepts `iteratee` which is\n * invoked for each element in `array` to generate the criterion by which\n * uniqueness is computed. The order of result values is determined by the\n * order they occur in the array. The iteratee is invoked with one argument:\n * (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n * @example\n *\n * _.uniqBy([2.1, 1.2, 2.3], Math.floor);\n * // => [2.1, 1.2]\n *\n * // The `_.property` iteratee shorthand.\n * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');\n * // => [{ 'x': 1 }, { 'x': 2 }]\n */\nfunction uniqBy(array, iteratee) {\n return (array && array.length) ? baseUniq(array, baseIteratee(iteratee, 2)) : [];\n}\n\nexport default uniqBy;\n","import Bluebird from 'bluebird';\n\nconst { map, mapSeries } = Bluebird;\n\nexport { map, mapSeries };\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const DATA_POINTS = gql`\n query TranscendCliDataPoints(\n $filterBy: DataPointFiltersInput\n $first: Int!\n $offset: Int!\n ) {\n dataPoints(\n filterBy: $filterBy\n first: $first\n offset: $offset\n useMaster: false\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n title {\n defaultMessage\n }\n description {\n defaultMessage\n }\n owners {\n email\n }\n teams {\n name\n }\n name\n path\n actionSettings {\n type\n active\n }\n dataCollection {\n title {\n defaultMessage\n }\n }\n dbIntegrationQueries {\n query\n suggestedQuery\n requestType\n }\n }\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const DATA_POINT_COUNT = gql`\n query TranscendCliDataPointCount($filterBy: DataPointFiltersInput) {\n dataPoints(filterBy: $filterBy, useMaster: false) {\n totalCount\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - add orderBy\n// isExportCsv: true\nexport const SUB_DATA_POINTS = gql`\n query TranscendCliSubDataPoints(\n $filterBy: SubDataPointFiltersInput\n $first: Int!\n $offset: Int!\n ) {\n subDataPoints(\n filterBy: $filterBy\n first: $first\n offset: $offset\n useMaster: false\n ) {\n nodes {\n id\n name\n description\n purposes {\n name\n purpose\n }\n categories {\n name\n category\n }\n accessRequestVisibilityEnabled\n erasureRequestRedactionEnabled\n attributeValues {\n attributeKey {\n name\n }\n name\n }\n }\n }\n }\n`;\n\nexport const SUB_DATA_POINTS_COUNT = gql`\n query TranscendCliSubDataPointsCount($filterBy: SubDataPointFiltersInput) {\n subDataPoints(filterBy: $filterBy, useMaster: false) {\n totalCount\n }\n }\n`;\n\nexport const SUB_DATA_POINTS_WITH_GUESSES = gql`\n query TranscendCliSubDataPointGuesses(\n $filterBy: SubDataPointFiltersInput\n $first: Int!\n $offset: Int!\n ) {\n subDataPoints(\n filterBy: $filterBy\n first: $first\n offset: $offset\n useMaster: false\n ) {\n nodes {\n id\n name\n description\n purposes {\n name\n purpose\n }\n categories {\n name\n category\n }\n pendingCategoryGuesses {\n category {\n name\n category\n }\n status\n confidence\n classifierVersion\n }\n accessRequestVisibilityEnabled\n erasureRequestRedactionEnabled\n attributeValues {\n attributeKey {\n name\n }\n name\n }\n }\n }\n }\n`;\n\nexport const UPDATE_OR_CREATE_DATA_POINT = gql`\n mutation TranscendCliUpdateOrCreateDataPoint(\n $dataSiloId: ID!\n $name: String!\n $path: [String!]\n $title: String\n $description: String\n $ownerIds: [ID!]\n $ownerEmails: [String!]\n $teamNames: [String!]\n $teamIds: [ID!]\n $dataCollectionTag: String\n $querySuggestions: [DbIntegrationQuerySuggestionInput!]\n $enabledActions: [RequestActionObjectResolver!]\n $subDataPoints: [DataPointSubDataPointInput!]\n ) {\n updateOrCreateDataPoint(\n input: {\n dataSiloId: $dataSiloId\n name: $name\n path: $path\n title: $title\n teamNames: $teamNames\n ownerEmails: $ownerEmails\n dataCollectionTag: $dataCollectionTag\n description: $description\n ownerIds: $ownerIds\n teamIds: $teamIds\n querySuggestions: $querySuggestions\n enabledActions: $enabledActions\n subDataPoints: $subDataPoints\n }\n ) {\n dataPoint {\n id\n name\n }\n }\n }\n`;\n\nexport const DATAPOINT_EXPORT = gql`\n query TranscendCliDataPointCsvExport(\n $filterBy: DataPointFiltersInput\n $first: Int!\n ) {\n dataPoints(filterBy: $filterBy, first: $first, useMaster: false) {\n nodes {\n id\n title {\n defaultMessage\n }\n description {\n defaultMessage\n }\n owners {\n email\n }\n teams {\n name\n }\n name\n path\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const ENTRY_COUNT = gql`\n query TranscendCliEntryCount(\n $filterBy: UnstructuredSubDataPointRecommendationsFilterInput\n ) {\n unstructuredSubDataPointRecommendations(\n filterBy: $filterBy\n useMaster: false\n ) {\n totalCount\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const DATA_SILOS = gql`\n query TranscendCliDataSilos(\n $filterBy: DataSiloFiltersInput!\n $first: Int!\n $offset: Int!\n ) {\n dataSilos(\n filterBy: $filterBy\n first: $first\n offset: $offset\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: title, direction: ASC }\n ]\n useMaster: false\n ) {\n nodes {\n id\n title\n link\n type\n catalog {\n hasAvcFunctionality\n }\n }\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const DATA_SILO_EXPORT = gql`\n query TranscendCliDataSiloExport(\n $filterBy: DataSiloFiltersInput!\n $first: Int!\n ) {\n dataSilos(filterBy: $filterBy, first: $first, useMaster: false) {\n nodes {\n id\n title\n }\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const DATA_SILOS_ENRICHED = gql`\n query TranscendCliDataSilosEnriched(\n $filterBy: DataSiloFiltersInput!\n $first: Int!\n $offset: Int!\n ) {\n dataSilos(\n filterBy: $filterBy\n first: $first\n offset: $offset\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: title, direction: ASC }\n ]\n useMaster: false\n ) {\n nodes {\n id\n title\n description\n type\n outerType\n link\n country\n countrySubDivision\n url\n notifyEmailAddress\n attributeValues {\n attributeKey {\n name\n }\n name\n }\n apiKeys {\n title\n }\n subjectBlocklist {\n type\n }\n identifiers {\n name\n isConnected\n }\n dependentDataSilos {\n title\n }\n owners {\n email\n }\n teams {\n id\n name\n }\n catalog {\n hasAvcFunctionality\n }\n isLive\n promptAVendorEmailSendFrequency\n promptAVendorEmailSendType\n promptAVendorEmailIncludeIdentifiersAttachment\n promptAVendorEmailCompletionLinkType\n manualWorkRetryFrequency\n discoveredBy {\n title\n }\n businessEntities {\n title\n }\n }\n }\n }\n`;\n\nexport const UPDATE_DATA_SILOS = gql`\n mutation TranscendCliUpdateDataSilo($input: UpdateDataSilosInput!) {\n updateDataSilos(input: $input) {\n clientMutationId\n dataSilos {\n id\n title\n }\n }\n }\n`;\n\nexport const CREATE_DATA_SILOS = gql`\n mutation TranscendCliCreateDataSilo($input: [CreateDataSilosInput!]!) {\n createDataSilos(input: $input) {\n dataSilos {\n id\n title\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const ENRICHERS = gql`\n query TranscendCliEnrichers($title: String, $first: Int!, $offset: Int!) {\n enrichers(\n filterBy: { text: $title }\n first: $first\n offset: $offset\n useMaster: false\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: title, direction: ASC }\n ]\n ) {\n nodes {\n id\n title\n url\n type\n expirationDuration\n lookerQueryTitle\n testRegex\n transitionRequestStatus\n phoneNumbers\n regionList\n inputIdentifier {\n name\n }\n identifiers {\n name\n }\n dataSubjects {\n type\n }\n actions\n }\n }\n }\n`;\n\nexport interface Initializer {\n /** ID of enricher */\n id: string;\n /** Identifiers */\n identifiers: {\n /** Name of identifier */\n name: string;\n }[];\n}\n\nexport const INITIALIZER = gql`\n query TranscendCliInitializer {\n initializer {\n id\n identifiers {\n name\n }\n }\n }\n`;\n\nexport const CREATE_ENRICHER = gql`\n mutation TranscendCliCreateEnricher($input: EnricherInput!) {\n createEnricher(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const UPDATE_ENRICHER = gql`\n mutation TranscendCliUpdateEnricher($input: UpdateEnricherInput!) {\n updateEnricher(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - order by createdAt\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const CATALOGS = gql`\n query TranscendCliCatalogs($first: Int!, $offset: Int!) {\n catalogs(first: $first, offset: $offset, filterBy: {}, useMaster: false) {\n nodes {\n integrationName\n title\n hasApiFunctionality\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const IDENTIFIERS = gql`\n query TranscendCliIdentifiers($first: Int!, $offset: Int!) {\n identifiers(\n first: $first\n offset: $offset\n useMaster: false\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n name\n type\n regex\n selectOptions\n privacyCenterVisibility\n dataSubjects {\n type\n }\n isRequiredInForm\n placeholder\n displayTitle {\n defaultMessage\n }\n displayDescription {\n defaultMessage\n }\n displayOrder\n isUniqueOnPreferenceStore\n }\n }\n }\n`;\n\nexport const NEW_IDENTIFIER_TYPES = gql`\n query TranscendCliNewIdentifierTypes {\n newIdentifierTypes {\n name\n }\n }\n`;\n\nexport const CREATE_IDENTIFIER = gql`\n mutation TranscendCliCreateIdentifier($input: IdentifierInput!) {\n createIdentifier(input: $input) {\n identifier {\n id\n name\n }\n }\n }\n`;\n\nexport const UPDATE_IDENTIFIER = gql`\n mutation TranscendCliUpdateIdentifier($input: UpdateIdentifierInput!) {\n updateIdentifier(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const DATA_SUBJECTS = gql`\n query TranscendCliDataSubjects {\n internalSubjects {\n id\n title {\n defaultMessage\n }\n active\n type\n adminDashboardDefaultSilentMode\n actions {\n type\n }\n }\n }\n`;\n\nexport const CREATE_DATA_SUBJECT = gql`\n mutation TranscendCliCreateDataSubject($type: String!) {\n createSubject(input: { type: $type, title: $type, subjectClass: OTHER }) {\n subject {\n id\n type\n }\n }\n }\n`;\n\nexport const UPDATE_DATA_SUBJECT = gql`\n mutation TranscendCliUpdateDataSubject($input: UpdateSubjectInput!) {\n updateSubject(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const TOGGLE_DATA_SUBJECT = gql`\n mutation TranscendCliToggleDataSubject($input: ToggleSubjectInput!) {\n toggleSubject(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const REPOSITORIES = gql`\n query TranscendCliRepositories(\n $first: Int!\n $offset: Int!\n $input: RepositoryFiltersInput\n ) {\n repositories(\n first: $first\n offset: $offset\n filterBy: $input\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n name\n description\n url\n teams {\n id\n name\n }\n owners {\n id\n email\n }\n }\n }\n }\n`;\n\nexport const UPDATE_REPOSITORIES = gql`\n mutation TranscendCliUpdateRepositories($input: UpdateRepositoriesInput!) {\n updateRepositories(input: $input) {\n clientMutationId\n repositories {\n id\n name\n url\n teams {\n id\n name\n }\n owners {\n id\n email\n }\n }\n }\n }\n`;\n\nexport const CREATE_REPOSITORY = gql`\n mutation TranscendCliCreateRepository($input: CreateRepositoryInput!) {\n createRepository(input: $input) {\n clientMutationId\n repository {\n id\n name\n url\n teams {\n id\n name\n }\n owners {\n id\n email\n }\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const API_KEYS = gql`\n query TranscendCliApiKeys($first: Int!, $offset: Int!, $titles: [String!]) {\n apiKeys(\n first: $first\n offset: $offset\n filterBy: { titles: $titles }\n useMaster: false\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: title, direction: ASC }\n ]\n ) {\n nodes {\n id\n title\n }\n }\n }\n`;\n\nexport const CREATE_API_KEY = gql`\n mutation TranscendCliCreateApiKey($input: ApiKeyInput!) {\n createApiKey(input: $input) {\n apiKey {\n id\n apiKey\n title\n }\n }\n }\n`;\n\nexport const DELETE_API_KEY = gql`\n mutation TranscendCliDeleteApiKey($id: ID!) {\n deleteApiKey(id: $id) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const CREATE_PREFERENCE_ACCESS_TOKENS = gql`\n mutation TranscendCliCreatePreferenceAccessTokens(\n $input: CreatePrivacyCenterAccessTokensInput!\n ) {\n createPrivacyCenterAccessTokens(input: $input) {\n nodes {\n token\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const ADD_SILO_DISCOVERY_RESULTS = gql`\n mutation AddSiloDiscoveryResults(\n $pluginId: ID!\n $rawResults: [SiloDiscoveryRawResultInput!]!\n ) {\n addSiloDiscoveryResults(\n input: { pluginId: $pluginId, rawResults: $rawResults }\n ) {\n success\n }\n }\n`;\n\nexport const ENABLED_PLUGINS = gql`\n query Plugins($dataSiloId: String!, $type: PluginType!) {\n plugins(filterBy: { dataSiloId: $dataSiloId, type: $type, enabled: true }) {\n plugins {\n id\n dataSilo {\n type\n }\n }\n totalCount\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - order by createdAt\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const TEMPLATES = gql`\n query TranscendCliTemplates($title: String, $first: Int!, $offset: Int!) {\n templates(\n filterBy: { text: $title }\n first: $first\n offset: $offset\n useMaster: false\n ) {\n nodes {\n id\n title\n subject {\n defaultMessage\n }\n template {\n defaultMessage\n }\n }\n }\n }\n`;\n\nexport const CREATE_TEMPLATE = gql`\n mutation TranscendCliCreateTemplate($title: String!) {\n createTemplate(input: { title: $title, template: \"\", subject: $title }) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const ORGANIZATION = gql`\n query TranscendCliOrganization {\n organization {\n sombra {\n customerUrl\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// TODO: https://transcend.height.app/T-27909 - order by createdAt\nexport const ATTRIBUTE_KEYS_REQUESTS = gql`\n query TranscendCliAttributeKeys($first: Int!, $offset: Int!) {\n attributeKeys(\n filterBy: { enabledOn: [request] }\n first: $first\n useMaster: false\n offset: $offset\n ) {\n nodes {\n id\n name\n type\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const SOFTWARE_DEVELOPMENT_KITS = gql`\n query TranscendCliSoftwareDevelopmentKits(\n $first: Int!\n $offset: Int!\n $input: SoftwareDevelopmentKitFiltersInput\n ) {\n softwareDevelopmentKits(\n first: $first\n offset: $offset\n filterBy: $input\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n name\n description\n codePackageType\n documentationLinks\n repositoryUrl\n teams {\n id\n name\n }\n owners {\n id\n email\n }\n }\n }\n }\n`;\n\nexport const UPDATE_SOFTWARE_DEVELOPMENT_KITS = gql`\n mutation TranscendCliUpdateSoftwareDevelopmentKits(\n $input: UpdateSoftwareDevelopmentKitsInput!\n ) {\n updateSoftwareDevelopmentKits(input: $input) {\n clientMutationId\n softwareDevelopmentKits {\n id\n name\n description\n codePackageType\n documentationLinks\n repositoryUrl\n teams {\n id\n name\n }\n owners {\n id\n email\n }\n }\n }\n }\n`;\n\nexport const CREATE_SOFTWARE_DEVELOPMENT_KIT = gql`\n mutation TranscendCliCreateSoftwareDevelopmentKit(\n $input: CreateSoftwareDevelopmentKitInput!\n ) {\n createSoftwareDevelopmentKit(input: $input) {\n clientMutationId\n softwareDevelopmentKit {\n id\n name\n description\n codePackageType\n documentationLinks\n repositoryUrl\n teams {\n id\n name\n }\n owners {\n id\n email\n }\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const CODE_PACKAGES = gql`\n query TranscendCliCodePackages(\n $first: Int!\n $offset: Int!\n $input: CodePackageFiltersInput\n ) {\n codePackages(\n first: $first\n offset: $offset\n filterBy: $input\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n name\n description\n type\n relativePath\n teams {\n id\n name\n }\n owners {\n id\n email\n }\n repository {\n id\n name\n }\n dataSilo {\n id\n title\n type\n }\n }\n }\n }\n`;\n\nexport const UPDATE_CODE_PACKAGES = gql`\n mutation TranscendCliUpdateCodePackages($input: UpdateCodePackagesInput!) {\n updateCodePackages(input: $input) {\n clientMutationId\n codePackages {\n id\n name\n description\n type\n relativePath\n teams {\n id\n name\n }\n owners {\n id\n email\n }\n repository {\n id\n name\n }\n dataSilo {\n id\n title\n type\n }\n }\n }\n }\n`;\n\nexport const CREATE_CODE_PACKAGE = gql`\n mutation TranscendCliCreateCodePackage($input: CreateCodePackageInput!) {\n createCodePackage(input: $input) {\n clientMutationId\n codePackage {\n id\n name\n description\n type\n relativePath\n teams {\n id\n name\n }\n owners {\n id\n email\n }\n repository {\n id\n name\n }\n dataSilo {\n id\n title\n type\n }\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const PROMPT_THREADS = gql`\n query TranscendCliPromptThreads(\n $first: Int!\n $offset: Int!\n $filterBy: PromptThreadFiltersInput!\n ) {\n promptThreads(first: $first, offset: $offset, filterBy: $filterBy) {\n nodes {\n id\n threadId\n slackMessageTs\n slackTeamId\n slackChannelId\n slackChannelName\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const POLICIES = gql`\n query TranscendCliFetchPolicies($url: String!) {\n privacyCenterPolicies(lookup: { url: $url }) {\n id\n title {\n defaultMessage\n }\n disableEffectiveOn\n disabledLocales\n versions {\n effectiveOn\n content {\n defaultMessage\n }\n }\n }\n }\n`;\n\nexport const UPDATE_POLICIES = gql`\n mutation TranscendCliUpdatePolicies(\n $policies: [PolicyInput!]!\n $privacyCenterId: ID!\n ) {\n updatePolicies(\n input: {\n privacyCenterId: $privacyCenterId\n policies: $policies\n skipPublish: true\n }\n ) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const REQUESTS = gql`\n query TranscendCliRequests(\n $first: Int!\n $offset: Int!\n $filterBy: RequestFiltersInput!\n ) {\n requests(\n filterBy: $filterBy\n first: $first\n offset: $offset\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: id, direction: ASC }\n ]\n useMaster: false\n ) {\n nodes {\n id\n createdAt\n email\n link\n status\n details\n isTest\n locale\n origin\n isSilent\n coreIdentifier\n daysRemaining\n type\n subjectType\n country\n countrySubDivision\n purpose {\n title\n name\n consent\n enrichedPreferences {\n topic\n selectValues {\n id\n name\n preferenceOption {\n id\n slug\n title {\n defaultMessage\n }\n }\n }\n selectValue {\n id\n name\n }\n selectValue {\n id\n name\n }\n preferenceTopic {\n title {\n defaultMessage\n }\n id\n slug\n }\n name\n id\n booleanValue\n }\n }\n attributeValues {\n id\n name\n attributeKey {\n id\n name\n }\n }\n }\n totalCount\n }\n }\n`;\n\nexport const APPROVE_PRIVACY_REQUEST = gql`\n mutation TranscendCliApprovePrivacyRequest($input: CommunicationInput!) {\n approveRequest(input: $input) {\n request {\n id\n }\n }\n }\n`;\nexport const CANCEL_PRIVACY_REQUEST = gql`\n mutation TranscendCliCancelPrivacyRequest($input: CommunicationInput!) {\n cancelRequest(input: $input) {\n request {\n id\n }\n }\n }\n`;\n\nexport const UPDATE_PRIVACY_REQUEST = gql`\n mutation TranscendCliUpdatePrivacyRequest($input: UpdateRequestInput!) {\n updateRequest(input: $input) {\n request {\n id\n }\n }\n }\n`;\n\nexport const NOTIFY_ADDITIONAL_TIME = gql`\n mutation TranscendCliNotifyAdditionalTime($input: AdditionalTimeInput!) {\n notifyAdditionalTime(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const MESSAGES = gql`\n query TranscendCliFetchMessage {\n translatedMessages {\n id\n defaultMessage\n description\n targetReactIntlId\n translations {\n locale\n value\n }\n }\n }\n`;\n\nexport const UPDATE_INTL_MESSAGES = gql`\n mutation TranscendCliUpdateIntlMessages($messages: [MessageInput!]!) {\n updateIntlMessages(input: { messages: $messages, skipPublish: true }) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const REQUEST_ENRICHERS = gql`\n query TranscendCliRequestEnrichers(\n $first: Int!\n $offset: Int!\n $requestId: ID!\n ) {\n requestEnrichers(\n input: { requestId: $requestId }\n first: $first\n offset: $offset\n useMaster: false\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: title, direction: ASC, model: enricher }\n ]\n ) {\n nodes {\n id\n status\n enricher {\n id\n type\n title\n }\n }\n totalCount\n }\n }\n`;\n\nexport const RETRY_REQUEST_ENRICHER = gql`\n mutation TranscendCliRetryRequestEnricher($requestEnricherId: ID!) {\n retryRequestEnricher(id: $requestEnricherId) {\n requestEnricher {\n id\n }\n }\n }\n`;\n\nexport const SKIP_REQUEST_ENRICHER = gql`\n mutation TranscendCliSkipRequestEnricher($requestEnricherId: ID!) {\n skipRequestEnricher(id: $requestEnricherId) {\n requestEnricher {\n id\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const ASSESSMENT_SECTION_FIELDS = `\n id\n title\n status\n index\n questions {\n id\n title\n index\n type\n subType\n placeholder\n description\n isRequired\n displayLogic\n riskLogic\n requireRiskEvaluation\n requireRiskMatrixEvaluation\n riskCategories {\n id\n title\n }\n riskFramework {\n id\n title\n description\n riskLevels {\n id\n title\n }\n riskCategories {\n id\n title\n }\n riskMatrixColumns {\n id\n title\n }\n riskMatrixRows {\n id\n title\n }\n riskMatrix {\n id\n title\n }\n creator {\n id\n email\n name\n }\n riskMatrixRowTitle\n riskMatrixColumnTitle\n }\n riskLevel {\n id\n title\n }\n reviewerRiskLevel {\n id\n title\n }\n riskLevelFromRiskMatrix {\n id\n title\n }\n answerOptions {\n id\n index\n value\n }\n selectedAnswers {\n ... on AssessmentAnswerInterface {\n id\n index\n value\n }\n }\n respondent {\n id\n email\n name\n }\n attributeKey {\n name\n }\n externalRespondentEmail\n comments {\n id\n content\n createdAt\n updatedAt\n author {\n id\n email\n name\n }\n }\n allowedMimeTypes\n updatedAt\n referenceId\n previousSubmissions {\n id\n updatedAt\n assessmentQuestionId\n answers {\n ... on AssessmentAnswerInterface {\n id\n index\n value\n }\n }\n }\n allowSelectOther\n syncModel\n syncColumn\n syncRowIds\n syncOverride\n }\n assignees {\n id\n email\n name\n }\n externalAssignees {\n id\n email\n }\n isReviewed\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\n// orderBy: [\n// { field: createdAt, direction: ASC }\n// { field: name, direction: ASC }\n// ]\nexport const ASSESSMENTS = gql`\n query TranscendCliAssessments(\n $first: Int!\n $offset: Int!\n $filterBy: AssessmentFormFiltersInput\n ) {\n assessmentForms(first: $first, offset: $offset, filterBy: $filterBy) {\n nodes {\n id\n creator {\n id\n email\n name\n }\n lastEditor {\n id\n email\n name\n }\n title\n description\n status\n assignees {\n id\n email\n name\n }\n externalAssignees {\n id\n email\n }\n reviewers {\n id\n email\n name\n }\n isLocked\n isArchived\n isExternallyCreated\n dueDate\n createdAt\n updatedAt\n assignedAt\n submittedAt\n approvedAt\n rejectedAt\n titleIsInternal\n retentionSchedule {\n id\n type\n durationDays\n operation\n }\n attributeValues {\n name\n attributeKey {\n name\n }\n }\n sections {\n ${ASSESSMENT_SECTION_FIELDS}\n }\n assessmentGroup {\n id\n title\n description\n }\n resources {\n resourceType\n ... on AttributeBusinessEntityResource {\n id\n title\n }\n ... on AttributeDataSiloResource {\n id\n title\n }\n ... on AttributeDataSubCategoryResource {\n id\n name\n category\n }\n ... on AttributeSubDataPointResource {\n id\n name\n }\n ... on AttributeProcessingPurposeSubCategoryResource {\n id\n name\n purpose\n }\n ... on AttributeRequestResource {\n id\n type\n }\n ... on AttributeVendorResource {\n id\n title\n }\n ... on AttributePromptResource {\n id\n title\n }\n ... on AttributePromptRunResource {\n id\n title\n }\n ... on AttributePromptGroupResource {\n id\n title\n }\n }\n syncedRows {\n resourceType\n ... on AttributeBusinessEntityResource {\n id\n title\n }\n ... on AttributeDataSiloResource {\n id\n title\n }\n ... on AttributeDataSubCategoryResource {\n id\n name\n category\n }\n ... on AttributeSubDataPointResource {\n id\n name\n }\n ... on AttributeProcessingPurposeSubCategoryResource {\n id\n name\n purpose\n }\n ... on AttributeVendorResource {\n id\n title\n }\n }\n }\n }\n }\n`;\n\nexport const IMPORT_ONE_TRUST_ASSESSMENT_FORMS = gql`\n mutation TranscendCliImportOneTrustAssessmentForms(\n $input: ImportOnetrustAssessmentsInput!\n ) {\n importOneTrustAssessmentForms(input: $input) {\n assessmentForms {\n id\n title\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\n// orderBy: [\n// { field: createdAt, direction: ASC }\n// { field: name, direction: ASC }\n// ]\nexport const PURPOSES = gql`\n query TranscendCliPurposes(\n $first: Int!\n $offset: Int!\n $filterBy: TrackingPurposeFiltersInput\n $input: TrackingPurposeInput!\n ) {\n purposes(\n first: $first\n offset: $offset\n filterBy: $filterBy\n input: $input\n ) {\n nodes {\n id\n name\n description\n defaultConsent\n trackingType\n configurable\n essential\n showInConsentManager\n isActive\n displayOrder\n optOutSignals\n deletedAt\n authLevel\n showInPrivacyCenter\n title\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\n// orderBy: [\n// { field: createdAt, direction: ASC }\n// { field: name, direction: ASC }\n// ]\nexport const PREFERENCE_TOPICS = gql`\n query TranscendCliPreferenceTopics(\n $first: Int!\n $offset: Int!\n $filterBy: PreferenceTopicFilterInput\n ) {\n preferenceTopics(first: $first, offset: $offset, filterBy: $filterBy) {\n nodes {\n id\n slug\n type\n title {\n id\n defaultMessage\n }\n showInPrivacyCenter\n displayDescription {\n id\n defaultMessage\n }\n defaultConfiguration\n preferenceOptionValues {\n slug\n title {\n id\n defaultMessage\n }\n }\n purpose {\n trackingType\n }\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\nimport { ASSESSMENT_SECTION_FIELDS } from './assessment';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\n// orderBy: [\n// { field: createdAt, direction: ASC }\n// { field: name, direction: ASC }\n// ]\nexport const ASSESSMENT_TEMPLATES = gql`\n query TranscendCliAssessmentTemplates(\n $first: Int!\n $offset: Int!\n $filterBy: AssessmentFormTemplateFiltersInput\n ) {\n assessmentFormTemplates(\n first: $first\n offset: $offset\n filterBy: $filterBy\n ) {\n nodes {\n id\n creator {\n id\n email\n name\n }\n lastEditor {\n id\n email\n name\n }\n title\n description\n status\n source\n parentId\n isLocked\n isArchived\n createdAt\n updatedAt\n retentionSchedule {\n id\n type\n durationDays\n operation\n createdAt\n updatedAt\n }\n assessmentEmailSet {\n id\n title\n description\n isDefault\n templates {\n id\n title\n }\n }\n sections {\n ${ASSESSMENT_SECTION_FIELDS}\n }\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const PROMPTS = gql`\n query TranscendCliPrompts(\n $first: Int!\n $offset: Int!\n $filterBy: PromptFiltersInput\n ) {\n prompts(\n first: $first\n orderBy: [{ field: title, direction: ASC }]\n offset: $offset\n filterBy: $filterBy\n ) {\n nodes {\n id\n title\n status\n content\n temperature\n topP\n maxTokensToSample\n }\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\n// TODO: https://transcend.height.app/T-27909 - order by createdAt\n// orderBy: [{ field: title, direction: ASC }]\nexport const PROMPT_PARTIALS = gql`\n query TranscendCliPromptPartials($first: Int!, $offset: Int!) {\n promptPartials(first: $first, offset: $offset) {\n nodes {\n id\n title\n content\n }\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\n// TODO: https://transcend.height.app/T-27909 - order by createdAt\n// orderBy: [{ field: title, direction: ASC }]\nexport const PROMPT_GROUPS = gql`\n query TranscendCliPromptGroups($first: Int!, $offset: Int!) {\n promptGroups(\n first: $first\n\n offset: $offset\n ) {\n nodes {\n id\n title\n description\n prompts {\n title\n }\n }\n }\n }\n`;\n\nexport const PROMPTS_WITH_VARIABLES = gql`\n query TranscendCliPromptsWithVariables($input: PromptsWithVariablesInput!) {\n promptsWithVariables(input: $input) {\n prompts {\n id\n title\n content\n status\n temperature\n topP\n maxTokensToSample\n responseFormat\n }\n promptPartials {\n id\n title\n content\n slug\n }\n calculatedVariables {\n data\n name\n }\n runtimeVariables {\n name\n }\n }\n }\n`;\n\nexport const UPDATE_PROMPTS = gql`\n mutation TranscendCliUpdatePrompts($input: UpdatePromptsInput!) {\n updatePrompts(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const CREATE_PROMPT = gql`\n mutation TranscendCliCreatePrompt($input: CreatePromptInput!) {\n createPrompt(input: $input) {\n clientMutationId\n prompt {\n id\n }\n }\n }\n`;\n\nexport const UPDATE_PROMPT_PARTIALS = gql`\n mutation TranscendCliUpdatePromptPartials(\n $input: UpdatePromptPartialsInput!\n ) {\n updatePromptPartials(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const CREATE_PROMPT_PARTIAL = gql`\n mutation TranscendCliCreatePromptPartial($input: CreatePromptPartialInput!) {\n createPromptPartial(input: $input) {\n clientMutationId\n promptPartial {\n id\n }\n }\n }\n`;\n\nexport const UPDATE_PROMPT_GROUPS = gql`\n mutation TranscendCliUpdatePromptGroups($input: UpdatePromptGroupsInput!) {\n updatePromptGroups(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const CREATE_PROMPT_GROUP = gql`\n mutation TranscendCliCreatePromptPartial($input: CreatePromptGroupInput!) {\n createPromptGroup(input: $input) {\n clientMutationId\n promptGroup {\n id\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const REQUEST_DATA_SILOS = gql`\n query TranscendCliRequestDataSilos(\n $first: Int!\n $offset: Int!\n $filterBy: RequestDataSiloFiltersInput!\n ) {\n requestDataSilos(\n filterBy: $filterBy\n first: $first\n offset: $offset\n useMaster: false\n orderBy: [\n { field: createdAt, direction: DESC }\n { field: title, direction: ASC, model: dataSilo }\n ]\n ) {\n nodes {\n id\n }\n totalCount\n }\n }\n`;\n\nexport const CHANGE_REQUEST_DATA_SILO_STATUS = gql`\n mutation TranscendCliMarkRequestDataSiloCompleted(\n $requestDataSiloId: ID!\n $status: UpdateRequestDataSiloStatus!\n ) {\n changeRequestDataSiloStatus(\n input: { id: $requestDataSiloId, status: $status }\n ) {\n requestDataSilo {\n id\n }\n }\n }\n`;\n\nexport const RETRY_REQUEST_DATA_SILO = gql`\n mutation TranscendCliRetryRequestDataSilo($requestDataSiloId: ID!) {\n retryRequestDataSilo(id: $requestDataSiloId) {\n requestDataSilo {\n id\n }\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\n// orderBy: [\n// { field: createdAt, direction: DESC }\n// { field: title, direction: ASC, model: dataSilo }\n// ]\nexport const REDUCED_REQUESTS_FOR_DATA_SILO_COUNT = gql`\n query TranscendCliListReducedRequestsForDataSiloCount(\n $input: BulkCompletionReducedRequestInput!\n ) {\n listReducedRequestsForDataSilo(input: $input) {\n totalCount\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const TEAMS = gql`\n query TranscendCliTeams(\n $first: Int!\n $offset: Int!\n $input: TeamFiltersInput\n ) {\n teams(\n first: $first\n offset: $offset\n filterBy: $input\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n name\n description\n ssoDepartment\n ssoGroup\n ssoTitle\n users {\n id\n email\n name\n }\n scopes {\n id\n name\n title\n }\n }\n }\n }\n`;\n\nexport const CREATE_TEAM = gql`\n mutation TranscendCliCreateTeam($input: TeamInput!) {\n createTeam(input: $input) {\n team {\n id\n name\n }\n }\n }\n`;\n\nexport const UPDATE_TEAM = gql`\n mutation TranscendCliUpdateTeam($input: UpdateTeamInput!) {\n updateTeam(input: $input) {\n team {\n id\n name\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const REMOVE_REQUEST_IDENTIFIERS = gql`\n mutation TranscendCliRemoveRequestIdentifiers(\n $input: RemoveRequestIdentifiersInput!\n ) {\n removeRequestIdentifiers(input: $input) {\n count\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const REQUEST_IDENTIFIERS = gql`\n query TranscendCliRequestIdentifiers(\n $first: Int!\n $offset: Int!\n $requestIds: [ID!]!\n ) {\n requestIdentifiers(\n input: { requestIds: $requestIds }\n first: $first\n offset: $offset\n useMaster: false\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n name\n isVerifiedAtLeastOnce\n }\n totalCount\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const USERS = gql`\n query TranscendCliUsers(\n $first: Int!\n $offset: Int!\n $input: UserFiltersInput\n ) {\n users(\n first: $first\n offset: $offset\n filterBy: $input\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n name\n email\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const REQUEST_FILES = gql`\n query TranscendCliRequestFiles(\n $first: Int!\n $offset: Int!\n $filterBy: RequestFileFiltersInput!\n ) {\n requestFiles(\n filterBy: $filterBy\n first: $first\n offset: $offset\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: id, direction: ASC }\n ]\n ) {\n nodes {\n remoteId\n fileName\n }\n }\n }\n`;\n\nexport const BULK_REQUEST_FILES = gql`\n query TranscendCliBulkRequestFiles(\n $filterBy: BulkRequestFilesFiltersInput!\n $first: Int!\n $after: String\n ) {\n bulkRequestFiles(filterBy: $filterBy, first: $first, after: $after) {\n nodes {\n remoteId\n fileName\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const REPORT_PROMPT_RUN = gql`\n mutation TranscendCliReportPromptRun($input: ReportPromptRunInput!) {\n reportPromptRun(input: $input) {\n clientMutationId\n promptRun {\n id\n }\n }\n }\n`;\n\nexport const ADD_MESSAGES_TO_PROMPT_RUN = gql`\n mutation TranscendCliAddMessagesToPromptRun(\n $input: AddMessagesToPromptRunInput!\n ) {\n addMessagesToPromptRun(input: $input) {\n clientMutationId\n promptRun {\n id\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\n// orderBy: [\n// { field: createdAt, direction: ASC }\n// { field: title, direction: ASC }\n// ]\nexport const GLOBAL_ACTION_ITEM_COLLECTIONS = gql`\n query TranscendCliGlobalActionItemCollectionss(\n $filterBy: GlobalActionItemCollectionFiltersInput!\n ) {\n globalActionItemCollections(filterBy: $filterBy) {\n nodes {\n id\n title\n description\n hidden\n productLine\n }\n }\n }\n`;\n\nexport const CREATE_ACTION_ITEM_COLLECTION = gql`\n mutation TranscendCliCreateActionItemCollection(\n $input: CreateActionItemCollectionInput!\n ) {\n createActionItemCollection(input: $input) {\n created {\n id\n title\n }\n }\n }\n`;\n\nexport const UPDATE_ACTION_ITEM_COLLECTION = gql`\n mutation TranscendCliUpdateActionItemCollection(\n $input: UpdateActionItemCollectionInput!\n ) {\n updateActionItemCollection(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - order by createdAt\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const ATTRIBUTES = gql`\n query TranscendCliAttributes($first: Int!, $offset: Int!) {\n attributeKeys(first: $first, offset: $offset, useMaster: false) {\n nodes {\n id\n isCustom\n description\n enabledOn\n name\n type\n }\n }\n }\n`;\n\nexport const CREATE_ATTRIBUTE_VALUES = gql`\n mutation TranscendCliCreateAttributeValues(\n $input: [CreateAttributeValuesInput!]!\n ) {\n createAttributeValues(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const UPDATE_ATTRIBUTE_VALUES = gql`\n mutation TranscendCliUpdateAttributeValues(\n $input: [UpdateAttributeValueInput!]!\n ) {\n updateAttributeValues(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const DELETE_ATTRIBUTE_VALUE = gql`\n mutation TranscendCliDeleteAttributeValue($id: ID!) {\n deleteAttributeValue(id: $id) {\n clientMutationId\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - order by createdAt\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const ATTRIBUTE_VALUES = gql`\n query TranscendCliAttributeValues(\n $first: Int!\n $offset: Int!\n $attributeKeyId: ID!\n ) {\n attributeValues(\n first: $first\n offset: $offset\n useMaster: false\n filterBy: { attributeKeys: [$attributeKeyId] }\n ) {\n nodes {\n id\n name\n description\n color\n }\n }\n }\n`;\n\nexport const CREATE_ATTRIBUTE = gql`\n mutation TranscendCliCreateAttribute(\n $name: String!\n $type: AttributeKeyType!\n $description: String\n $enabledOn: [AttributeSupportedResourceType!]\n ) {\n createAttributeKey(\n input: {\n name: $name\n type: $type\n description: $description\n enabledOn: $enabledOn\n }\n ) {\n clientMutationId\n attributeKey {\n id\n }\n }\n }\n`;\n\nexport const UPDATE_ATTRIBUTE = gql`\n mutation TranscendCliCreateAttribute(\n $attributeKeyId: ID!\n $description: String\n $enabledOn: [AttributeSupportedResourceType!]\n ) {\n updateAttributeKey(\n input: {\n id: $attributeKeyId\n description: $description\n enabledOn: $enabledOn\n }\n ) {\n clientMutationId\n attributeKey {\n id\n }\n }\n }\n`;\n\nexport const SET_RESOURCE_ATTRIBUTES = gql`\n mutation TranscendCliSetResourceAttributes(\n $input: SetResourceAttributesInput!\n ) {\n setResourceAttributes(input: $input) {\n clientMutationId\n }\n }\n`;\n","/* eslint-disable max-lines */\nimport { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - order by createdAt\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const EXPERIENCES = gql`\n query TranscendCliExperiences($first: Int!, $offset: Int!) {\n experiences(first: $first, offset: $offset, useMaster: false) {\n nodes {\n id\n name\n displayName\n regions {\n countrySubDivision\n country\n }\n operator\n displayPriority\n onConsentExpiry\n consentExpiry\n viewState\n purposes {\n name\n trackingType\n }\n optedOutPurposes {\n name\n trackingType\n }\n browserLanguages\n browserTimeZones\n }\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - order by createdAt\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// useMaster: false\n// isExportCsv: true\nexport const CONSENT_PARTITIONS = gql`\n query TranscendCliConsentPartitions($first: Int!, $offset: Int!) {\n consentPartitions(first: $first, offset: $offset) {\n nodes {\n id\n name\n partition\n }\n }\n }\n`;\n\nexport const CREATE_DATA_FLOWS = gql`\n mutation TranscendCliCreateDataFlows(\n $dataFlows: [DataFlowInput!]!\n $airgapBundleId: ID!\n $classifyService: Boolean\n ) {\n createDataFlows(\n input: {\n airgapBundleId: $airgapBundleId\n dataFlows: $dataFlows\n classifyService: $classifyService\n }\n ) {\n dataFlows {\n id\n }\n }\n }\n`;\n\nexport const UPDATE_DATA_FLOWS = gql`\n mutation TranscendCliUpdateDataFlows(\n $airgapBundleId: ID!\n $dataFlows: [UpdateDataFlowInput!]!\n $classifyService: Boolean\n ) {\n updateDataFlows(\n input: {\n airgapBundleId: $airgapBundleId\n dataFlows: $dataFlows\n classifyService: $classifyService\n }\n ) {\n dataFlows {\n id\n }\n }\n }\n`;\n\nexport const UPDATE_OR_CREATE_COOKIES = gql`\n mutation TranscendCliUpdateOrCreateCookies(\n $cookies: [UpdateOrCreateCookieInput!]!\n $airgapBundleId: ID!\n ) {\n updateOrCreateCookies(\n input: { airgapBundleId: $airgapBundleId, cookies: $cookies }\n ) {\n clientMutationId\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const DATA_FLOWS = gql`\n query TranscendCliDataFlows(\n $first: Int!\n $airgapBundleId: ID!\n $offset: Int!\n $status: ConsentTrackerStatus\n $showZeroActivity: Boolean\n ) {\n dataFlows(\n first: $first\n offset: $offset\n filterBy: { status: $status, showZeroActivity: $showZeroActivity }\n input: { airgapBundleId: $airgapBundleId }\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: value, direction: ASC }\n ]\n useMaster: false\n ) {\n nodes {\n id\n value\n type\n description\n trackingType\n service {\n integrationName\n }\n source\n status\n owners {\n email\n }\n teams {\n name\n }\n attributeValues {\n name\n attributeKey {\n name\n }\n }\n }\n }\n }\n`;\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const COOKIES = gql`\n query TranscendCliCookies(\n $first: Int!\n $offset: Int!\n $airgapBundleId: ID!\n $status: ConsentTrackerStatus\n ) {\n cookies(\n first: $first\n offset: $offset\n filterBy: { status: $status }\n input: { airgapBundleId: $airgapBundleId }\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n useMaster: false\n ) {\n nodes {\n id\n name\n isRegex\n description\n trackingPurposes\n service {\n integrationName\n }\n source\n status\n owners {\n email\n }\n teams {\n name\n }\n attributeValues {\n name\n attributeKey {\n name\n }\n }\n }\n }\n }\n`;\n\nexport const FETCH_CONSENT_MANAGER_ID = gql`\n query TranscendCliFetchConsentManagerId {\n consentManager {\n consentManager {\n id\n }\n }\n }\n`;\n\nexport const FETCH_CONSENT_MANAGER = gql`\n query TranscendCliFetchConsentManager {\n consentManager {\n consentManager {\n id\n bundleURL\n testBundleURL\n configuration {\n domains\n consentPrecedence\n unknownRequestPolicy\n unknownCookiePolicy\n syncEndpoint\n telemetryPartitioning\n signedIabAgreement\n syncGroups\n partition\n }\n partition {\n partition\n }\n }\n }\n }\n`;\n\nexport const FETCH_CONSENT_MANAGER_THEME = gql`\n query TranscendCliFetchConsentManagerTheme($airgapBundleId: ID!) {\n consentManagerTheme(input: { airgapBundleId: $airgapBundleId }) {\n theme {\n primaryColor\n fontColor\n privacyPolicy\n prompt\n }\n }\n }\n`;\n\nexport const CREATE_CONSENT_MANAGER = gql`\n mutation TranscendCliCreateConsentManager($privacyCenterId: ID!) {\n createConsentManager(input: { privacyCenterId: $privacyCenterId }) {\n consentManager {\n id\n }\n }\n }\n`;\n\nexport const UPDATE_CONSENT_MANAGER_VERSION = gql`\n mutation TranscendCliUpdateConsentManager(\n $airgapBundleId: ID!\n $version: String!\n ) {\n updateConsentManager(id: $airgapBundleId, input: { version: $version }) {\n clientMutationId\n }\n }\n`;\n\nexport const UPDATE_CONSENT_MANAGER_TO_LATEST = gql`\n mutation TranscendCliUpdateConsentManagerToLatest(\n $airgapBundleId: ID!\n $bundleType: ConsentBundleType!\n ) {\n updateConsentManagerToLatestVersion(\n id: $airgapBundleId\n input: { bundleType: $bundleType }\n ) {\n clientMutationId\n }\n }\n`;\n\nexport const DEPLOY_CONSENT_MANAGER = gql`\n mutation TranscendCliDeployConsentManager(\n $airgapBundleId: ID!\n $bundleType: ConsentBundleType!\n ) {\n deployConsentManagerBundle(\n id: $airgapBundleId\n input: { bundleType: $bundleType }\n ) {\n clientMutationId\n }\n }\n`;\n\nexport const UPDATE_CONSENT_MANAGER_DOMAINS = gql`\n mutation TranscendCliUpdateConsentManagerDomains(\n $airgapBundleId: ID!\n $domains: [String!]!\n ) {\n updateConsentManagerDomains(\n input: { id: $airgapBundleId, domains: $domains }\n ) {\n clientMutationId\n }\n }\n`;\n\nexport const UPDATE_CONSENT_MANAGER_PARTITION = gql`\n mutation TranscendCliUpdateConsentManagerPartition(\n $airgapBundleId: ID!\n $partitionId: ID!\n ) {\n updateConsentManagerPartition(\n input: { id: $airgapBundleId, partitionId: $partitionId }\n ) {\n clientMutationId\n }\n }\n`;\n\nexport const UPDATE_LOAD_OPTIONS = gql`\n mutation TranscendCliUpdateLoadOptions($input: UpdateLoadOptionsInput!) {\n updateLoadOptions(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const TOGGLE_UNKNOWN_REQUEST_POLICY = gql`\n mutation TranscendCliToggleUnknownRequestPolicy(\n $input: ToggleUnknownRequestPolicyInput!\n ) {\n toggleUnknownRequestPolicy(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const TOGGLE_UNKNOWN_COOKIE_POLICY = gql`\n mutation TranscendCliToggleUnknownCookiePolicy(\n $input: ToggleUnknownCookiePolicyInput!\n ) {\n toggleUnknownCookiePolicy(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const TOGGLE_TELEMETRY_PARTITION_STRATEGY = gql`\n mutation TranscendCliToggleTelemetryPartitionStrategy(\n $input: ToggleTelemetryPartitionStrategyInput!\n ) {\n toggleTelemetryPartitioning(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const TOGGLE_CONSENT_PRECEDENCE = gql`\n mutation TranscendCliToggleConsentPrecedence(\n $input: ToggleConsentPrecedenceInput!\n ) {\n toggleConsentPrecedence(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const UPDATE_CONSENT_MANAGER_THEME = gql`\n mutation TranscendCliUpdateConsentManagerTheme(\n $input: UpdateConsentManagerThemeInput!\n ) {\n updateConsentManagerTheme(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const UPDATE_CONSENT_EXPERIENCE = gql`\n mutation TranscendCliUpdateConsentExperience($input: UpdateExperienceInput!) {\n updateExperience(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const CREATE_CONSENT_EXPERIENCE = gql`\n mutation TranscendCliCreateConsentExperience($input: CreateExperienceInput!) {\n createExperience(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const CREATE_CONSENT_PARTITION = gql`\n mutation TranscendCliCreateConsentPartition(\n $input: CreateConsentPartitionInput!\n ) {\n createConsentPartition(input: $input) {\n clientMutationId\n }\n }\n`;\n/* eslint-enable max-lines */\n","import { gql } from 'graphql-request';\n\nexport const CONSENT_MANAGER_ANALYTICS_DATA = gql`\n query TranscendCliConsentManagerAnalyticsData($input: AnalyticsInput!) {\n analyticsData(input: $input) {\n series {\n name\n points {\n key\n value\n }\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\nexport const BUSINESS_ENTITIES = gql`\n query TranscendCliBusinessEntities($first: Int!, $offset: Int!) {\n businessEntities(\n first: $first\n offset: $offset\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: title, direction: ASC }\n ]\n useMaster: false\n ) {\n nodes {\n id\n title\n description\n dataProtectionOfficerName\n dataProtectionOfficerEmail\n address\n headquarterCountry\n headquarterSubDivision\n attributeValues {\n name\n attributeKey {\n name\n }\n }\n }\n }\n }\n`;\n\nexport const CREATE_BUSINESS_ENTITY = gql`\n mutation TranscendCliCreateBusinessEntity(\n $input: CreateBusinessEntityInput!\n ) {\n createBusinessEntity(input: $input) {\n businessEntity {\n id\n title\n description\n dataProtectionOfficerName\n dataProtectionOfficerEmail\n address\n headquarterCountry\n headquarterSubDivision\n attributeValues {\n name\n attributeKey {\n name\n }\n }\n }\n }\n }\n`;\n\nexport const UPDATE_BUSINESS_ENTITIES = gql`\n mutation TranscendCliUpdateBusinessEntities(\n $input: [UpdateBusinessEntityInput!]!\n ) {\n updateBusinessEntities(input: { businessEntities: $input }) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// TODO: https://transcend.height.app/T-27909 - order by createdAt\nexport const ACTIONS = gql`\n query TranscendCliActions($first: Int!, $offset: Int!) {\n actions(\n first: $first\n offset: $offset\n useMaster: false\n orderBy: [{ field: type, direction: ASC }]\n ) {\n nodes {\n id\n type\n skipSecondaryIfNoFiles\n skipDownloadableStep\n requiresReview\n regionList\n regionDetectionMethod\n waitingPeriod\n }\n }\n }\n`;\n\nexport const UPDATE_ACTION = gql`\n mutation TranscendCliUpdateAction($input: UpdateActionInput!) {\n updateAction(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\n// orderBy: [\n// { field: createdAt, direction: ASC }\n// { field: title, direction: ASC }\n// ]\nexport const GLOBAL_ACTION_ITEMS = gql`\n query TranscendCliGlobalActionItems(\n $first: Int!\n $offset: Int!\n $filterBy: GlobalActionItemFiltersInput!\n ) {\n globalActionItems(first: $first, offset: $offset, filterBy: $filterBy) {\n nodes {\n ids\n count\n teams {\n id\n name\n }\n customerExperienceActionItemIds\n users {\n id\n email\n }\n collections {\n title\n id\n }\n dueDate\n priority\n titles\n resolved\n notes\n links\n type\n additionalContexts {\n iconOverride\n requestId\n dataSiloId\n requestType\n latestAirgapVersion\n parentTitle\n }\n attributeValues {\n name\n attributeKey {\n name\n }\n }\n }\n }\n }\n`;\n\nexport const UPDATE_ACTION_ITEMS = gql`\n mutation TranscendCliUpdateActionItems($input: UpdateActionItemsInput!) {\n updateActionItems(input: $input) {\n clientMutationId\n }\n }\n`;\n\nexport const CREATE_ACTION_ITEMS = gql`\n mutation TranscendCliCreateActionItems($input: [CreateActionItemsInput!]!) {\n createActionItems(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const FETCH_PRIVACY_CENTER_ID = gql`\n query TranscendCliFetchPrivacyCenterId($url: String!) {\n privacyCenter(lookup: { url: $url }) {\n id\n }\n }\n`;\n\nexport const DEPLOYED_PRIVACY_CENTER_URL = gql`\n query TranscendCliDeployedPrivacyCenterUrl {\n organization {\n deployedPrivacyCenterUrl\n }\n }\n`;\n\nexport const PRIVACY_CENTER = gql`\n query TranscendCliFetchPrivacyCenters($url: String!) {\n privacyCenter(lookup: { url: $url }) {\n id\n url\n isDisabled\n showPrivacyRequestButton\n showPolicies\n showTrackingTechnologies\n showCookies\n showDataFlows\n showConsentManager\n showManageYourPrivacy\n showMarketingPreferences\n locales\n defaultLocale\n preferBrowserDefaultLocale\n supportEmail\n replyToEmail\n useNoReplyEmailAddress\n useCustomEmailDomain\n transformAccessReportJsonToCsv\n themeStr\n }\n }\n`;\n\nexport const UPDATE_PRIVACY_CENTER = gql`\n mutation TranscendCliUpdatePrivacyCenter($input: UpdatePrivacyCenterInput!) {\n updatePrivacyCenter(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const DETERMINE_LOGIN_METHOD = gql`\n mutation TranscendCliDetermineLoginMethod($email: String!) {\n determineLoginMethod(input: { email: $email }) {\n loginMethod {\n email\n sombraPublicKey\n }\n }\n }\n`;\n\nexport const LOGIN = gql`\n mutation TranscendCliLogin(\n $email: String!\n $password: String!\n $publicKey: String!\n ) {\n login(\n input: { email: $email, password: $password }\n publicKey: $publicKey\n ) {\n user {\n roles {\n id\n organization {\n name\n id\n uri\n parentOrganizationId\n }\n }\n }\n }\n }\n`;\n\nexport const ASSUME_ROLE = gql`\n mutation TranscendCliAssumeRole($id: ID!, $publicKey: String!) {\n assumeRole(id: $id, publicKey: $publicKey) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const LARGE_LANGUAGE_MODELS = gql`\n query TranscendCliLargeLanguageModels(\n $first: Int!\n $offset: Int!\n $filterBy: LargeLanguageModelFiltersInput\n ) {\n largeLanguageModels(\n first: $first\n orderBy: [\n { field: name, direction: ASC }\n { field: client, direction: ASC }\n { field: isTranscendHosted, direction: ASC }\n ]\n offset: $offset\n filterBy: $filterBy\n ) {\n nodes {\n id\n name\n client\n isTranscendHosted\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const AGENTS = gql`\n query TranscendCliAgents(\n $first: Int!\n $offset: Int!\n $filterBy: AgentFiltersInput\n ) {\n agents(\n first: $first\n offset: $offset\n filterBy: $filterBy\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n name\n agentId\n instructions\n description\n codeInterpreterEnabled\n retrievalEnabled\n prompt {\n title\n }\n largeLanguageModel {\n name\n client\n }\n teams {\n name\n }\n owners {\n email\n }\n agentFunctions {\n name\n }\n agentFiles {\n name\n }\n }\n }\n }\n`;\n\nexport const CREATE_AGENT = gql`\n mutation TranscendCliCreateAgent($input: CreateAgentInput!) {\n createAgent(input: $input) {\n agent {\n id\n name\n agentId\n }\n }\n }\n`;\n\nexport const UPDATE_AGENTS = gql`\n mutation TranscendCliUpdateAgents($input: UpdateAgentsInput!) {\n updateAgents(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const AGENT_FILES = gql`\n query TranscendCliAgentFiles(\n $first: Int!\n $offset: Int!\n $filterBy: AgentFileFiltersInput\n ) {\n agentFiles(\n first: $first\n offset: $offset\n filterBy: $filterBy\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n name\n description\n fileId\n size\n purpose\n initialFileName\n }\n }\n }\n`;\n\nexport const CREATE_AGENT_FILE = gql`\n mutation TranscendCliCreateAgentFile($input: CreateAgentFileInput!) {\n createAgentFile(input: $input) {\n agentFile {\n id\n name\n fileId\n initialFileName\n }\n }\n }\n`;\n\nexport const UPDATE_AGENT_FILES = gql`\n mutation TranscendCliUpdateAgentFiles($input: UpdateAgentFilesInput!) {\n updateAgentFiles(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// isExportCsv: true\n// useMaster: false\nexport const AGENT_FUNCTIONS = gql`\n query TranscendCliAgentFunctions($first: Int!, $offset: Int!) {\n agentFunctions(\n first: $first\n offset: $offset\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: name, direction: ASC }\n ]\n ) {\n nodes {\n id\n name\n description\n parameters\n }\n }\n }\n`;\n\nexport const CREATE_AGENT_FUNCTION = gql`\n mutation TranscendCliCreateAgentFunction($input: CreateAgentFunctionInput!) {\n createAgentFunction(input: $input) {\n agentFunction {\n id\n name\n }\n }\n }\n`;\n\nexport const UPDATE_AGENT_FUNCTIONS = gql`\n mutation TranscendCliUpdateAgentFunctions(\n $input: UpdateAgentFunctionsInput!\n ) {\n updateAgentFunctions(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const VENDORS = gql`\n query TranscendCliVendors($first: Int!, $offset: Int!) {\n vendors(\n first: $first\n offset: $offset\n useMaster: false\n isExportCsv: true\n orderBy: [\n { field: createdAt, direction: ASC }\n { field: title, direction: ASC }\n ]\n ) {\n nodes {\n id\n title\n description\n dataProcessingAgreementLink\n contactName\n contactEmail\n contactPhone\n address\n headquarterCountry\n headquarterSubDivision\n websiteUrl\n businessEntity {\n title\n }\n teams {\n name\n }\n owners {\n email\n }\n attributeValues {\n attributeKey {\n name\n }\n name\n }\n }\n }\n }\n`;\n\nexport const CREATE_VENDOR = gql`\n mutation TranscendCliCreateVendor($input: CreateVendorInput!) {\n createVendor(input: $input) {\n vendor {\n id\n title\n }\n }\n }\n`;\n\nexport const UPDATE_VENDORS = gql`\n mutation TranscendCliUpdateVendor($input: UpdateVendorsInput!) {\n updateVendors(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// orderBy: [\n// { field: createdAt, direction: ASC }\n// { field: name, direction: ASC }\n// ]\nexport const DATA_SUB_CATEGORIES = gql`\n query TranscendCliDataSubCategories($first: Int!, $offset: Int!) {\n dataSubCategories(\n first: $first\n offset: $offset\n isExportCsv: true\n useMaster: false\n ) {\n nodes {\n id\n name\n category\n description\n regex\n teams {\n name\n }\n owners {\n email\n }\n attributeValues {\n attributeKey {\n name\n }\n name\n }\n }\n }\n }\n`;\n\nexport const CREATE_DATA_SUB_CATEGORY = gql`\n mutation TranscendCliCreateDataSubCategory(\n $input: CreateDataInventorySubCategoryInput!\n ) {\n createDataSubCategory(input: $input) {\n dataSubCategory {\n id\n name\n category\n }\n }\n }\n`;\n\nexport const UPDATE_DATA_SUB_CATEGORIES = gql`\n mutation TranscendCliUpdateDataSubCategories(\n $input: UpdateDataSubCategoriesInput!\n ) {\n updateDataSubCategories(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\n// TODO: https://transcend.height.app/T-27909 - enable optimizations\n// orderBy: [\n// { field: createdAt, direction: ASC }\n// { field: name, direction: ASC }\n// ]\nexport const PROCESSING_PURPOSE_SUB_CATEGORIES = gql`\n query TranscendCliProcessingPurposeSubCategories(\n $first: Int!\n $offset: Int!\n ) {\n processingPurposeSubCategories(\n first: $first\n offset: $offset\n isExportCsv: true\n useMaster: false\n ) {\n nodes {\n id\n name\n purpose\n description\n teams {\n name\n }\n owners {\n email\n }\n attributeValues {\n attributeKey {\n name\n }\n name\n }\n }\n }\n }\n`;\n\nexport const CREATE_PROCESSING_PURPOSE_SUB_CATEGORY = gql`\n mutation TranscendCliCreateProcessingPurposeSubCategory(\n $input: CreateProcessingPurposeCategoryInput!\n ) {\n createProcessingPurposeSubCategory(input: $input) {\n processingPurposeSubCategory {\n id\n name\n purpose\n }\n }\n }\n`;\n\nexport const UPDATE_PROCESSING_PURPOSE_SUB_CATEGORIES = gql`\n mutation TranscendCliUpdateProcessingPurposeSubCategories(\n $input: UpdateProcessingPurposeSubCategoriesInput!\n ) {\n updateProcessingPurposeSubCategories(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const PROCESSING_ACTIVITIES = gql`\n query TranscendCliProcessingActivities($first: Int!, $offset: Int!) {\n processingActivities(first: $first, offset: $offset, useMaster: false) {\n nodes {\n id\n title\n description\n securityMeasureDetails\n controllerships\n storageRegions {\n countrySubDivision\n country\n }\n transferRegions {\n countrySubDivision\n country\n }\n retentionType\n retentionPeriod\n dataProtectionImpactAssessmentLink\n dataProtectionImpactAssessmentStatus\n attributeValues {\n name\n attributeKey {\n name\n }\n }\n dataSilos {\n title\n }\n dataSubjects {\n type\n }\n teams {\n name\n }\n owners {\n email\n }\n processingPurposeSubCategories {\n name\n purpose\n }\n dataSubCategories {\n name\n category\n }\n saaSCategories {\n title\n }\n }\n }\n }\n`;\n\nexport const CREATE_PROCESSING_ACTIVITY = gql`\n mutation TranscendCliCreateProcessingActivity(\n $input: CreateProcessingActivityInput!\n ) {\n createProcessingActivity(input: $input) {\n processingActivity {\n id\n title\n }\n }\n }\n`;\n\nexport const UPDATE_PROCESSING_ACTIVITIES = gql`\n mutation TranscendCliUpdateProcessingActivities(\n $input: UpdateProcessingActivitiesInput!\n ) {\n updateProcessingActivities(input: $input) {\n clientMutationId\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const SOMBRA_VERSION = gql`\n query TranscendSombraVersion {\n organization {\n sombra {\n version\n }\n }\n }\n`;\n","import { gql } from 'graphql-request';\n\nexport const SILO_DISCOVERY_RESULTS = gql`\n query TranscendCliSiloDiscoveryResults($first: Int!, $offset: Int!) {\n siloDiscoveryResults(first: $first, offset: $offset) {\n nodes {\n title\n resourceId\n country\n countrySubDivision\n plaintextContext\n status\n containsSensitiveData\n suggestedCatalog {\n title\n }\n plugin {\n dataSilo {\n title\n }\n }\n }\n }\n }\n`;\n","import { applyEnum, valuesOf } from '@transcend-io/type-utils';\nimport { LOCALE_KEY } from '@transcend-io/internationalization';\nimport {\n CompletedRequestStatus,\n RequestAction,\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\nimport * as t from 'io-ts';\n\nexport const NONE = '[NONE]' as const;\nexport const BULK_APPLY = '[APPLY VALUE TO ALL ROWS]' as const;\nexport const BLANK = '<blank>' as const;\n\n/** These are uploaded at the top level of the request */\nexport const IDENTIFIER_BLOCK_LIST = ['email', 'coreIdentifier'];\n\n/**\n * Column names to map\n */\nexport enum ColumnName {\n /** The title of the email column */\n Email = 'email',\n /** The title of the core identifier column */\n CoreIdentifier = 'coreIdentifier',\n /** The title of the requestType column */\n RequestType = 'requestType',\n /** The title of the subjectType column */\n SubjectType = 'subjectType',\n /** The title of the locale column */\n Locale = 'locale',\n /** The country */\n Country = 'country',\n /** The country sub division */\n CountrySubDivision = 'countrySubDivision',\n /** The title of the requestStatus column */\n RequestStatus = 'requestStatus',\n /** The title of the createdAt column */\n CreatedAt = 'createdAt',\n /** The title of the dataSiloIds column */\n DataSiloIds = 'dataSiloIds',\n}\n\n/** These parameters are required in the Transcend DSR API */\nexport const IS_REQUIRED: { [k in ColumnName]: boolean } = {\n [ColumnName.Email]: false,\n [ColumnName.CoreIdentifier]: true,\n [ColumnName.RequestType]: true,\n [ColumnName.SubjectType]: true,\n [ColumnName.RequestStatus]: false,\n [ColumnName.CreatedAt]: false,\n [ColumnName.DataSiloIds]: false,\n [ColumnName.Locale]: false,\n [ColumnName.Country]: false,\n [ColumnName.CountrySubDivision]: false,\n};\n\n/** These parameters can be specified for the entire CSV set if needed */\nexport const CAN_APPLY_IN_BULK: { [k in ColumnName]?: boolean } = {\n [ColumnName.RequestType]: true,\n [ColumnName.SubjectType]: true,\n};\n\n// Cache state\nexport const CachedFileState = t.type({\n /** Mapping between the default request input column names and the CSV column name for that input */\n columnNames: t.partial(applyEnum(ColumnName, () => t.string)),\n /** Mapping between the identifier names and the CSV column name for that input */\n identifierNames: t.record(t.string, t.string),\n /** Mapping between the request attribute inputs and the CSV column name for that input */\n attributeNames: t.record(t.string, t.string),\n /** Mapping between CSV request type and Transcend Request Action */\n requestTypeToRequestAction: t.record(t.string, valuesOf(RequestAction)),\n /** Mapping between CSV data subject type and the name of the data subject in Transcend */\n subjectTypeToSubjectName: t.record(t.string, t.string),\n /** Mapping between language imported and Transcend locale code */\n languageToLocale: t.record(t.string, valuesOf(LOCALE_KEY)),\n /** Mapping between region and country code */\n regionToCountry: t.record(\n t.string,\n valuesOf({ ...IsoCountryCode, [NONE]: NONE }),\n ),\n /** Mapping between region and country sub division code */\n regionToCountrySubDivision: t.record(\n t.string,\n valuesOf({ ...IsoCountrySubdivisionCode, [NONE]: NONE }),\n ),\n /** Mapping between request status in import to Transcend request status */\n statusToRequestStatus: t.record(\n t.string,\n valuesOf({ ...CompletedRequestStatus, [NONE]: NONE }),\n ),\n});\n\n/** Type override */\nexport type CachedFileState = t.TypeOf<typeof CachedFileState>;\n\n/**\n * Successfully processed request\n */\nexport const SuccessfulRequest = t.type({\n id: t.string,\n link: t.string,\n rowIndex: t.number,\n coreIdentifier: t.string,\n attemptedAt: t.string,\n});\n\n/** Type override */\nexport type SuccessfulRequest = t.TypeOf<typeof SuccessfulRequest>;\n\n// Cache state\nexport const CachedRequestState = t.type({\n /** Set of privacy requests that failed to upload */\n failingRequests: t.array(t.record(t.string, t.any)),\n /** Successfully uploaded requests */\n successfulRequests: t.array(SuccessfulRequest),\n /** Duplicate requests */\n duplicateRequests: t.array(\n t.type({\n rowIndex: t.number,\n coreIdentifier: t.string,\n attemptedAt: t.string,\n }),\n ),\n});\n\n/** Type override */\nexport type CachedRequestState = t.TypeOf<typeof CachedRequestState>;\n","import inquirer from 'inquirer';\nimport { NONE, BULK_APPLY } from './constants';\n\nimport fuzzysearch from 'fuzzysearch';\n\n/**\n * Check if word1 and word2 are a fuzzy match of each other.\n * Returns true if word1 is fuzzy match of word2 or vice versa.\n *\n * @param word1 - First word\n * @param word2 - Second word\n * @returns True if words are fuzzy match\n */\nexport function fuzzySearch(word1: string, word2: string): boolean {\n return (\n fuzzysearch(word1.toLowerCase(), word2.toLowerCase()) ||\n fuzzysearch(word2.toLowerCase(), word1.toLowerCase())\n );\n}\n\n/**\n * Fuzzy match column names for a particular field\n *\n * @param allColumnNames - List of all column names\n * @param fuzzyMapName - The name of field being mapped to\n * @param isRequired - When true, don't include \"NONE\" as an option\n * @param canApplyAll - When true, include an option to specify the value in bulk\n * @returns The list of suggestions for inquirer\n */\nexport function fuzzyMatchColumns(\n allColumnNames: string[],\n fuzzyMapName: string,\n isRequired: boolean,\n canApplyAll?: boolean,\n): (string | InstanceType<typeof inquirer.Separator>)[] {\n const matchingColumnNames = allColumnNames.filter((x) =>\n fuzzySearch(fuzzyMapName.toLowerCase(), x.toLowerCase()),\n );\n return [\n ...matchingColumnNames,\n new inquirer.Separator(),\n ...(isRequired ? [] : [NONE]),\n ...(canApplyAll ? [BULK_APPLY] : []),\n ...allColumnNames.filter((x) => !matchingColumnNames.includes(x)),\n ];\n}\n","import inquirer from 'inquirer';\nimport autoCompletePrompt from 'inquirer-autocomplete-prompt';\nimport { apply, ObjByString } from '@transcend-io/type-utils';\nimport { fuzzySearch } from './fuzzyMatchColumns';\n\n/**\n * Map a set of inputs to a set of outputs\n *\n * @param csvInputs - Input list\n * @param expectedOutputs - Output list\n * @param cache - Cache\n * @returns Mapping from row to enum value\n */\nexport async function mapEnumValues<TValue extends string>(\n csvInputs: string[],\n expectedOutputs: TValue[],\n cache: { [k in string]: TValue },\n): Promise<{ [k in string]: TValue }> {\n inquirer.registerPrompt('autocomplete', autoCompletePrompt);\n\n const inputs = csvInputs\n .map((item) => item || '<blank>')\n .filter((value) => !cache[value]);\n if (inputs.length === 0) {\n return cache;\n }\n const result = await inquirer.prompt<{ [k in string]: TValue }>(\n inputs.map((value) => ({\n name: value,\n message: `Map value of: ${value}`,\n type: 'autocomplete',\n default: expectedOutputs.find((x) => fuzzySearch(value, x)),\n source: (answersSoFar: ObjByString, input: string) =>\n !input\n ? expectedOutputs\n : expectedOutputs.filter(\n (x) => typeof x === 'string' && fuzzySearch(input, x),\n ),\n })),\n );\n return {\n ...cache,\n ...apply(result, (r) =>\n typeof r === 'string' ? (r as TValue) : (Object.values(r)[0] as TValue),\n ),\n };\n}\n","/**\n * Split string to CSV\n *\n * Filter out double commas and spaces like:\n * Dog, Cat -> ['Dog', 'Cat']\n * Dog,,Cat -> ['Dog', 'Cat']\n *\n * @param value - Value\n * @returns List of values\n */\nexport function splitCsvToList(value: string): string[] {\n return value\n .split(',')\n .map((x) => x.trim())\n .filter((x) => x);\n}\n","import colors from 'colors';\nimport * as t from 'io-ts';\nimport { logger } from '../../logger';\n\nexport const ParsedAttributeInput = t.type({\n /** Attribute key */\n key: t.string,\n /** Attribute values */\n values: t.array(t.string),\n});\n\n/** Type override */\nexport type ParsedAttributeInput = t.TypeOf<typeof ParsedAttributeInput>;\n\n/**\n * Parse out the extra attributes to apply to all requests uploaded\n *\n * @param attributes - input as string, e.g. ['key:value1;value2','key2:value3;value4']\n * @returns The parsed attributes\n */\nexport function parseAttributesFromString(\n attributes: string[],\n): ParsedAttributeInput[] {\n // Parse out the extra attributes to apply to all requests uploaded\n const parsedAttributes = attributes.map((attribute) => {\n const [attributeKey, attributeValuesRaw] = attribute.trim().split(':');\n if (!attributeValuesRaw) {\n throw new Error(\n 'Expected attributes in key:value1;value2,key2:value3;value4',\n );\n }\n const attributeValues = attributeValuesRaw.split(';');\n return {\n key: attributeKey,\n values: attributeValues,\n };\n });\n logger.info(colors.magenta('Attributes to apply to all requests:'));\n logger.info(colors.magenta(JSON.stringify(parsedAttributes, null, 2)));\n return parsedAttributes;\n}\n","import type { Options } from 'csv-parse';\nimport { parse } from 'csv-parse/sync';\nimport { readFileSync } from 'node:fs';\nimport * as t from 'io-ts';\n\nimport { decodeCodec } from '@transcend-io/type-utils';\n\n/**\n * Read in a CSV and validate its shape\n *\n * @param pathToFile - Path to file\n * @param codec - The codec to validate against. This is the codec for individual, non-header, rows\n * @param options - CSV parse options\n * @returns The JSON data\n */\nexport function readCsv<T extends t.Any>(\n pathToFile: string,\n codec: T,\n options: Options = { columns: true },\n): t.TypeOf<T>[] {\n // read file contents and parse\n const fileContent = parse(readFileSync(pathToFile, 'utf-8'), options);\n\n // validate codec\n const data = decodeCodec(t.array(codec), fileContent);\n\n // remove any special characters from object keys\n const parsed = data.map((datum) =>\n Object.entries(datum).reduce(\n (acc, [key, value]) =>\n Object.assign(acc, {\n [key.replace(/[^a-z_.+\\-A-Z -~]/g, '')]: value,\n }),\n {} as T,\n ),\n );\n return parsed;\n}\n","import { ObjByString } from '@transcend-io/type-utils';\nimport { uniq } from 'lodash-es';\n\n/**\n * Return the unique set of values for a column in a CSV\n *\n * @param rows - Rows to look up\n * @param columnName - Name of column to grab values for\n * @returns Unique set of values in that column\n */\nexport function getUniqueValuesForColumn(\n rows: ObjByString[],\n columnName: string,\n): string[] {\n return uniq(rows.map((row) => row[columnName] || '').flat());\n}\n","import inquirer from 'inquirer';\nimport { ObjByString } from '@transcend-io/type-utils';\nimport colors from 'colors';\nimport { uniq } from 'lodash-es';\nimport { logger } from '../../logger';\nimport { NONE } from './constants';\nimport { getUniqueValuesForColumn } from './getUniqueValuesForColumn';\n\n/**\n * Filter a list of CSV rows by column values\n * Choose columns that contain metadata to filter the requests\n *\n * @param rows - Rows to filter\n * @returns Filtered rows\n */\nexport async function filterRows(rows: ObjByString[]): Promise<ObjByString[]> {\n // Determine set of column names\n const columnNames = uniq(rows.map((x) => Object.keys(x)).flat());\n\n // update these variables recursively\n let filteredRows = rows;\n let keepFiltering = true;\n\n // loop over\n while (keepFiltering) {\n // Prompt user for column to filter on\n\n const { filterColumnName } = await inquirer.prompt<{\n /** Name of column to filter on */\n filterColumnName: string;\n }>([\n {\n name: 'filterColumnName',\n // eslint-disable-next-line max-len\n message: `If you need to filter the list of requests to import, choose the column to filter on. Currently ${filteredRows.length} rows.`,\n type: 'list',\n default: columnNames,\n choices: [NONE, ...columnNames],\n },\n ]);\n\n // Determine if filtering should continue, or loop should be exited\n keepFiltering = NONE !== filterColumnName;\n if (keepFiltering) {\n const options = getUniqueValuesForColumn(filteredRows, filterColumnName);\n\n const { valuesToKeep } = await inquirer.prompt<{\n /** Values to keep */\n valuesToKeep: string[];\n }>([\n {\n name: 'valuesToKeep',\n message: 'Keep rows matching this value',\n type: 'checkbox',\n default: columnNames,\n choices: options,\n },\n ]);\n\n filteredRows = filteredRows.filter((request) =>\n valuesToKeep.includes(request[filterColumnName]),\n );\n }\n }\n\n logger.info(colors.magenta(`Importing ${filteredRows.length} requests`));\n return filteredRows;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { ADD_MESSAGES_TO_PROMPT_RUN } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { QueueStatus, ChatCompletionRole } from '@transcend-io/privacy-types';\n\nexport interface AddMessagesToPromptRunInput {\n /** ID of run */\n promptRunId:\n | {\n /** Report by prompt run name */\n name: string;\n /** Don't report by ID */\n id?: undefined;\n }\n | {\n /** Don't report by name */\n name?: undefined;\n /** Report by prompt run ID */\n id: string;\n };\n /** Messages to report on */\n promptRunMessages?: {\n /** Message reported */\n content: string;\n /** Role of message */\n role: ChatCompletionRole;\n /** Template used if created from prompt */\n template?: string;\n }[];\n /** Error message (if one exists) */\n error?: string;\n /** The status of the run */\n status?: QueueStatus;\n /** Duration of time that it took to execute the prompt */\n duration?: number;\n}\n\n/**\n * Record a new prompt run\n *\n * @param client - GraphQL client\n * @param input - Prompt input\n * @returns Prompt ID\n */\nexport async function addMessagesToPromptRun(\n client: GraphQLClient,\n { promptRunId, promptRunMessages = [], ...rest }: AddMessagesToPromptRunInput,\n): Promise<string> {\n const {\n addMessagesToPromptRun: { promptRun },\n } = await makeGraphQLRequest<{\n /** addMessagesToPromptRun mutation */\n addMessagesToPromptRun: {\n /** Prompt */\n promptRun: {\n /** ID */\n id: string;\n };\n };\n }>(client, ADD_MESSAGES_TO_PROMPT_RUN, {\n input: {\n ...rest,\n ...promptRunId,\n promptRunMessages: promptRunMessages.map(({ content, ...rest }) => ({\n ...rest,\n message: content,\n })),\n },\n });\n return promptRun.id;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { version } from '../../../package.json';\n\n/**\n * Create a GraphQL client\n *\n * @param transcendUrl - Transcend API URL\n * @param headers - Request headers to include in each request\n * @returns GraphQL client\n */\nexport function buildTranscendGraphQLClientGeneric(\n transcendUrl: string,\n headers: Record<string, string>,\n): GraphQLClient {\n // Create a GraphQL client\n return new GraphQLClient(`${transcendUrl}/graphql`, {\n headers: {\n ...headers,\n version,\n },\n });\n}\n\n/**\n * Create a GraphQL client capable of submitting requests with an API key\n *\n * @param transcendUrl - Transcend API URL\n * @param auth - API key to authenticate to API\n * @returns GraphQL client\n */\nexport function buildTranscendGraphQLClient(\n transcendUrl: string,\n auth: string,\n): GraphQLClient {\n return buildTranscendGraphQLClientGeneric(transcendUrl, {\n Authorization: `Bearer ${auth}`,\n });\n}\n","import got, { Got } from 'got';\nimport colors from 'colors';\nimport { ORGANIZATION } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { buildTranscendGraphQLClient } from './buildTranscendGraphQLClient';\nimport { logger } from '../../logger';\n\n/**\n * Instantiate an instance of got that is capable of making requests\n * to a sombra gateway.\n *\n * @param transcendUrl - URL of Transcend API\n * @param transcendApiKey - Transcend API key\n * @param sombraApiKey - Sombra API key\n * @returns The instance of got that is capable of making requests to the customer ingress\n */\nexport async function createSombraGotInstance(\n transcendUrl: string,\n transcendApiKey: string,\n sombraApiKey?: string,\n): Promise<Got> {\n // Create GraphQL client to connect to Transcend backend\n const client = buildTranscendGraphQLClient(transcendUrl, transcendApiKey);\n // Grab metadata about organization's sombra from GraphQL endpoint\n const { organization } = await makeGraphQLRequest<{\n /** Requests */\n organization: {\n /** PrimarySombra related to organization */\n sombra: {\n /** URL of sombra */\n customerUrl: string;\n };\n };\n }>(client, ORGANIZATION);\n // Use SOMBRA_URL env var if provided, otherwise fall back to the primary sombra's customerUrl\n const { customerUrl } = organization.sombra;\n const sombraToUse = process.env.SOMBRA_URL || customerUrl;\n\n // Only validate the reverse tunnel URL if we're using the primary sombra (not SOMBRA_URL override)\n if (\n !process.env.SOMBRA_URL &&\n [\n 'https://sombra-reverse-tunnel.transcend.io',\n 'https://sombra-reverse-tunnel.us.transcend.io',\n ].includes(customerUrl)\n ) {\n throw new Error(\n 'It looks like your Sombra customer ingress URL has not been set up. ' +\n 'Please follow the instructions here to configure networking for Sombra: ' +\n 'https://docs.transcend.io/docs/articles/sombra/deploying/customizing-sombra/networking',\n );\n }\n logger.info(colors.green(`Using sombra: ${sombraToUse}`));\n\n // Create got instance with default values\n return got.extend({\n prefixUrl: sombraToUse,\n headers: {\n Authorization: `Bearer ${transcendApiKey}`,\n ...(sombraApiKey\n ? {\n 'X-Sombra-Authorization': `Bearer ${sombraApiKey}`,\n }\n : {}),\n },\n });\n}\n","import got, { Got } from 'got';\n\n/**\n * Instantiate an instance of got that is capable of making requests\n * to a sombra gateway.\n *\n * @param transcendUrl - URL of Transcend API\n * @returns The instance of got that is capable of making requests to the customer ingress\n */\nexport function createTranscendConsentGotInstance(transcendUrl: string): Got {\n // Create got instance with default values\n return got.extend({\n prefixUrl: transcendUrl,\n });\n}\n","import { ConsentBundleType } from '@transcend-io/privacy-types';\nimport { GraphQLClient } from 'graphql-request';\nimport {\n UPDATE_CONSENT_MANAGER_TO_LATEST,\n DEPLOY_CONSENT_MANAGER,\n} from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\n/**\n * Deploy the Consent Manager\n *\n * @param client - GraphQL client\n * @param options - Options\n */\nexport async function deployConsentManager(\n client: GraphQLClient,\n {\n id,\n bundleType,\n }: {\n /** ID of Consent Manager */\n id: string;\n /** Type of bundle */\n bundleType: ConsentBundleType;\n },\n): Promise<void> {\n await makeGraphQLRequest(client, DEPLOY_CONSENT_MANAGER, {\n airgapBundleId: id,\n bundleType,\n });\n}\n\n/**\n * Update the Consent Manager to the latest airgap.jz version\n *\n * @param client - GraphQL client\n * @param options - Options\n */\nexport async function updateConsentManagerToLatest(\n client: GraphQLClient,\n {\n id,\n bundleType,\n }: {\n /** ID of Consent Manager */\n id: string;\n /** Type of bundle */\n bundleType: ConsentBundleType;\n },\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_CONSENT_MANAGER_TO_LATEST, {\n airgapBundleId: id,\n bundleType,\n });\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { logger } from '../../logger';\nimport { ENABLED_PLUGINS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface Plugin {\n /** Associated data silo */\n dataSilo: {\n /** The type of plugin */\n type: string;\n };\n /** The ID of this plugin */\n id: string;\n}\n\nexport interface PluginResponse {\n /** The key object of the response */\n plugins: {\n /** The total count */\n totalCount: number;\n /** The list of plugins */\n plugins: Plugin[];\n };\n}\n\n/**\n * Fetch a data silo discovery plugin\n *\n * @param client - GraphQL client\n * @param dataSiloId - The data silo to look up plugins for\n * @returns An active data silo plugin (if multiple, returns the first)\n */\nexport async function fetchActiveSiloDiscoPlugin(\n client: GraphQLClient,\n dataSiloId: string,\n): Promise<Plugin> {\n const response = await makeGraphQLRequest<PluginResponse>(\n client,\n ENABLED_PLUGINS,\n {\n dataSiloId,\n type: 'DATA_SILO_DISCOVERY',\n },\n );\n\n const { plugins, totalCount } = response.plugins;\n if (totalCount === 0) {\n logger.error('No active data silo plugins found for this data silo.');\n process.exit(1);\n }\n\n const plugin = plugins[0];\n return plugin;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { GLOBAL_ACTION_ITEMS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n ActionItemCode,\n ActionItemPriorityOverride,\n} from '@transcend-io/privacy-types';\n\nexport interface ActionItemRaw {\n /** ID of action item */\n ids: string[];\n /** Count of action items */\n count: number;\n /** Teams assigned to action items */\n teams: {\n /** ID of team */\n id: string;\n /** Name of team */\n name: string;\n }[];\n /** Customer experience action item ID */\n customerExperienceActionItemIds: string[];\n /** Users assigned to the action item */\n users: {\n /** ID of user */\n id: string;\n /** User email */\n email: string;\n }[];\n /** Due date of action item */\n dueDate?: string;\n /** Priority of action item */\n priority?: ActionItemPriorityOverride;\n /** Titles of action items */\n titles: string[];\n /** Description of the action item */\n resolved: boolean;\n /** Notes */\n notes: string[];\n /** links */\n links: string[];\n /** Action item types */\n type: ActionItemCode;\n /** Custom fields */\n attributeValues: {\n /** Name of attribute value */\n name: string;\n /** Attribute key that the value represents */\n attributeKey: {\n /** Name of attribute team */\n name: string;\n };\n }[];\n /** Additional context related to action item */\n additionalContexts?: {\n /** Override of icon */\n iconOverride?: string;\n /** Request ID */\n requestId?: string;\n /** Data Silo ID */\n dataSiloId?: string;\n /** Request type */\n requestType?: string;\n /** Airgap version */\n latestAirgapVersion?: string;\n /** Parent title */\n parentTitle?: string;\n };\n /** Sections where action item is grouped under */\n collections: {\n /** ID of collection that action item belongs to */\n id: string;\n /** Title of collection */\n title: string;\n }[];\n}\n\nexport interface ActionItem\n extends Omit<ActionItemRaw, 'ids' | 'titles' | 'links' | 'notes'> {\n /** ID of action item */\n id: string;\n /** Title of action item */\n title: string;\n /** Notes */\n notes: string;\n /** Links */\n link: string;\n /** Sections where action item is grouped under */\n collections: {\n /** ID of collection that action item belongs to */\n id: string;\n /** Title of collection */\n title: string;\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all action items in the organization\n *\n * @param client - GraphQL client\n * @param filterBy - Filter by\n * @returns All action items in the organization\n */\nexport async function fetchAllActionItems(\n client: GraphQLClient,\n filterBy: {\n /** Names of the action items to filter for */\n priority?: ActionItemPriorityOverride[];\n /** Type of action item */\n type?: ActionItemCode[];\n /** Whether resolved or not */\n resolved?: boolean;\n /** Filter for action items due before this date */\n startDueDate?: Date;\n /** Filter for action items due after this date */\n endDueDate?: Date;\n } = {},\n): Promise<ActionItem[]> {\n const actionItems: ActionItem[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n globalActionItems: { nodes },\n } = await makeGraphQLRequest<{\n /** ActionItems */\n globalActionItems: {\n /** List */\n nodes: ActionItemRaw[];\n };\n }>(client, GLOBAL_ACTION_ITEMS, {\n first: PAGE_SIZE,\n offset,\n filterBy: {\n ...filterBy,\n ...(filterBy.startDueDate\n ? { startDueDate: filterBy.startDueDate.toISOString() }\n : {}),\n ...(filterBy.endDueDate\n ? { endDueDate: filterBy.endDueDate.toISOString() }\n : {}),\n },\n });\n actionItems.push(\n ...nodes.map((node) => ({\n ...node,\n id: node.ids[0],\n title: node.titles[0],\n notes: node.notes[0],\n link: node.links[0],\n })),\n );\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return actionItems;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport {\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n RegionDetectionMethod,\n RequestAction,\n} from '@transcend-io/privacy-types';\nimport { ACTIONS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface Action {\n /** ID of identifier */\n id: string;\n /** Type of action */\n type: RequestAction;\n /** Whether to skip secondary when no files exist */\n skipSecondaryIfNoFiles: boolean;\n /** Whether to skip downloadable step */\n skipDownloadableStep: boolean;\n /** Whether action requires review */\n requiresReview: boolean;\n /** Waiting period for action */\n waitingPeriod: number;\n /** Method in which the data subject's region is detected */\n regionDetectionMethod: RegionDetectionMethod;\n /** The list of regions to show in the form */\n regionList: (IsoCountryCode | IsoCountrySubdivisionCode)[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all actions in the organization\n *\n * @param client - GraphQL client\n * @returns All actions in the organization\n */\nexport async function fetchAllActions(\n client: GraphQLClient,\n): Promise<Action[]> {\n const actions: Action[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n actions: { nodes },\n } = await makeGraphQLRequest<{\n /** Actions */\n actions: {\n /** List */\n nodes: Action[];\n };\n }>(client, ACTIONS, {\n first: PAGE_SIZE,\n offset,\n });\n actions.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return actions.sort((a, b) => a.type.localeCompare(b.type));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { AGENT_FILES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { PromptFilePurpose } from '@transcend-io/privacy-types';\n\nexport interface AgentFile {\n /** ID of agentFile */\n id: string;\n /** Name of agentFile */\n name: string;\n /** Description of the agentFile */\n description: string;\n /** Initial file name, useful to track if a file was split into multiple chunks */\n initialFileName?: string;\n /** File ID */\n fileId: string;\n /** File size */\n size: number;\n /** File purpose */\n purpose: PromptFilePurpose;\n}\n\nconst PAGE_SIZE = 20;\n\nexport interface AgentFileFilterBy {\n /** Filter by remote file IDs */\n fileIds?: string[];\n /** Filter by file names */\n names?: string[];\n /** Filter by initial file names (when split into chunks) */\n initialFileNames?: string[];\n}\n\n/**\n * Fetch all agentFiles in the organization\n *\n * @param client - GraphQL client\n * @param filterBy - Filter by options\n * @returns All agentFiles in the organization\n */\nexport async function fetchAllAgentFiles(\n client: GraphQLClient,\n filterBy: AgentFileFilterBy = {},\n): Promise<AgentFile[]> {\n const agentFiles: AgentFile[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n agentFiles: { nodes },\n } = await makeGraphQLRequest<{\n /** AgentFiles */\n agentFiles: {\n /** List */\n nodes: AgentFile[];\n };\n }>(client, AGENT_FILES, {\n first: PAGE_SIZE,\n offset,\n filterBy,\n });\n agentFiles.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return agentFiles.sort((a, b) => a.name.localeCompare(b.name));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { AGENT_FUNCTIONS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport type { JSONSchema7 } from 'json-schema';\n\nexport interface AgentFunction {\n /** ID of agentFunction */\n id: string;\n /** Name of agentFunction */\n name: string;\n /** Description of the agentFunction */\n description: string;\n /** The JSON schema */\n parameters: JSONSchema7;\n}\n\ninterface AgentFunctionInput extends Omit<AgentFunction, 'parameters'> {\n /** Stringified parameters */\n parameters: string;\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all agentFunctions in the organization\n *\n * @param client - GraphQL client\n * @returns All agentFunctions in the organization\n */\nexport async function fetchAllAgentFunctions(\n client: GraphQLClient,\n): Promise<AgentFunction[]> {\n const agentFunctions: AgentFunction[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n agentFunctions: { nodes },\n } = await makeGraphQLRequest<{\n /** AgentFunctions */\n agentFunctions: {\n /** List */\n nodes: AgentFunctionInput[];\n };\n }>(client, AGENT_FUNCTIONS, {\n first: PAGE_SIZE,\n offset,\n });\n agentFunctions.push(\n ...nodes.map((node) => ({\n ...node,\n parameters: JSON.parse(node.parameters),\n })),\n );\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return agentFunctions.sort((a, b) => a.name.localeCompare(b.name));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { AGENTS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { LargeLanguageModelClient } from '@transcend-io/privacy-types';\n\nexport interface Agent {\n /** ID of agent */\n id: string;\n /** Name of agent */\n name: string;\n /** Agent instructions */\n instructions: string;\n /** The ID of the agent */\n agentId: string;\n /** Description of the agent */\n description: string;\n /** Whether the agent has code interpreter enabled */\n codeInterpreterEnabled: boolean;\n /** Whether the agent has retrieval enabled */\n retrievalEnabled: boolean;\n /** The prompt that the agent is based on */\n prompt?: {\n /** Title of the prompt */\n title: string;\n };\n /** Large language model that the agent is based on */\n largeLanguageModel: {\n /** Name of model */\n name: string;\n /** Client */\n client: LargeLanguageModelClient;\n };\n /** Teams assigned to the agent */\n teams: {\n /** Team name */\n name: string;\n }[];\n /** Users assigned to the agent */\n owners: {\n /** User email */\n email: string;\n }[];\n /** Functions that the agent has access to */\n agentFunctions: {\n /** Function name */\n name: string;\n }[];\n /** Files that the agent has access to */\n agentFiles: {\n /** File name */\n name: string;\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all agents in the organization\n *\n * @param client - GraphQL client\n * @param filterBy - Filter by\n * @returns All agents in the organization\n */\nexport async function fetchAllAgents(\n client: GraphQLClient,\n filterBy: {\n /** Names of the agents to filter for */\n names?: string[];\n /** IDs of agents */\n agentIds?: string[];\n } = {},\n): Promise<Agent[]> {\n const agents: Agent[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n agents: { nodes },\n } = await makeGraphQLRequest<{\n /** Agents */\n agents: {\n /** List */\n nodes: Agent[];\n };\n }>(client, AGENTS, {\n first: PAGE_SIZE,\n offset,\n filterBy,\n });\n agents.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return agents.sort((a, b) => a.name.localeCompare(b.name));\n}\n","/* eslint-disable max-lines */\nimport { GraphQLClient } from 'graphql-request';\nimport { ASSESSMENTS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n AssessmentFormStatus,\n AssessmentQuestionSubType,\n AssessmentQuestionType,\n AssessmentSyncColumn,\n AssessmentSyncModel,\n AttributeSupportedResourceType,\n DataCategoryType,\n ProcessingPurpose,\n RetentionScheduleOperation,\n RetentionScheduleType,\n} from '@transcend-io/privacy-types';\n\n/**\n * Represents an assessment with various properties and metadata.\n */\nexport interface Assessment {\n /** The ID of the assessment */\n id: string;\n /** The user who created the assessment */\n creator: UserPreview;\n /** The user who last edited the assessment */\n lastEditor: UserPreview;\n /** The title of the assessment */\n title: string;\n /** The description of the assessment */\n description: string;\n /** The current status of the assessment */\n status: AssessmentFormStatus;\n /** The users assigned to the assessment */\n assignees: UserPreview[];\n /** The external users assigned to the assessment */\n externalAssignees: ExternalUser[];\n /** The users who are reviewers of the assessment */\n reviewers: UserPreview[];\n /** Indicates if the assessment is locked */\n isLocked: boolean;\n /** Indicates if the assessment is archived */\n isArchived: boolean;\n /** Indicates if the assessment was created externally */\n isExternallyCreated: boolean;\n /** The due date of the assessment */\n dueDate: string;\n /** The date when the assessment was created */\n createdAt: string;\n /** The date when the assessment was last updated */\n updatedAt: string;\n /** The date when the assessment was assigned */\n assignedAt: string;\n /** The date when the assessment was submitted */\n submittedAt: string;\n /** The date when the assessment was approved */\n approvedAt: string;\n /** The date when the assessment was rejected */\n rejectedAt: string;\n /** Indicates if the title of the assessment is internal */\n titleIsInternal: boolean;\n /** The retention schedule of the assessment */\n retentionSchedule?: RetentionSchedule;\n /** The attribute values associated with the assessment */\n attributeValues: AttributeValue[];\n /** The sections of the assessment */\n sections: AssessmentSection[];\n /** The group to which the assessment belongs */\n assessmentGroup: AssessmentGroup;\n /** The resources associated with the assessment */\n resources: AssessmentResource[];\n /** The rows that are synced with the assessment */\n syncedRows: AssessmentResource[];\n}\n\nexport interface UserPreview {\n /** ID of user */\n id: string;\n /** Email of user */\n email: string;\n /** Name of user */\n name: string;\n}\n\nexport interface ExternalUser {\n /** ID of external user */\n id: string;\n /** Email of external user */\n email: string;\n}\n\nexport interface RetentionSchedule {\n /** ID of retention schedule */\n id: string;\n /** Type */\n type: RetentionScheduleType;\n /** Duration of retention schedule */\n durationDays: number;\n /** The operation to perform on the retention schedule */\n operation: RetentionScheduleOperation;\n}\n\ninterface AttributeValue {\n /** Name of attribute value */\n name: string;\n /** Key */\n attributeKey: {\n /** Name of key */\n name: string;\n };\n}\n\nexport interface AssessmentSection {\n /** ID of section */\n id: string;\n /** Title of section */\n title: string;\n /** Status of section */\n status: string;\n /** Index of section */\n index: number;\n /** Questions */\n questions: AssessmentQuestion[];\n /** Assignees */\n assignees: UserPreview[];\n /** External assignees */\n externalAssignees: ExternalUser[];\n /** Whether is reviewed */\n isReviewed: boolean;\n}\n\n/**\n * Represents a question in the assessment.\n */\nexport interface AssessmentQuestion {\n /**\n * Unique identifier for the question.\n */\n id: string;\n /** Title of the question */\n title: string;\n /** Index of the question in the assessment */\n index: number;\n /** Type of the question */\n type: AssessmentQuestionType;\n /** Subtype of the question */\n subType: AssessmentQuestionSubType;\n /** Placeholder text for the question */\n placeholder: string;\n /** Description of the question */\n description: string;\n /** Indicates if the question is required */\n isRequired: boolean;\n /** Logic for displaying the question */\n displayLogic: string;\n /** Logic for assessing risk related to the question */\n riskLogic: string[];\n /** Indicates if risk evaluation is required for the question */\n requireRiskEvaluation: boolean;\n /** Indicates if risk matrix evaluation is required for the question */\n requireRiskMatrixEvaluation: boolean;\n /** Categories of risk associated with the question */\n riskCategories: RiskCategory[];\n /** Framework used for risk assessment */\n riskFramework?: RiskFramework;\n /** Level of risk associated with the question */\n riskLevel?: RiskLevel;\n /** Risk level assigned by the reviewer */\n reviewerRiskLevel?: RiskLevel;\n /** Risk level derived from the risk matrix */\n riskLevelFromRiskMatrix?: RiskLevel;\n /** Options available for answering the question */\n answerOptions: AssessmentAnswerOption[];\n /** Answers selected for the question */\n selectedAnswers: AssessmentAnswer[];\n /** User who responded to the question */\n respondent: UserPreview;\n /** Key attribute associated with the question */\n attributeKey?: {\n /** Name of key */\n name: string;\n };\n /** Email of the external respondent */\n externalRespondentEmail?: string;\n /** Comments related to the question */\n comments: unknown[];\n /** Allowed MIME types for file uploads in the question */\n allowedMimeTypes: string[];\n /** Timestamp of the last update to the question */\n updatedAt: string;\n /** Reference identifier for the question */\n referenceId: string;\n /** Previous submissions related to the question */\n previousSubmissions: AssessmentPreviousSubmission[];\n /** Indicates if selecting \"Other\" is allowed for the question */\n allowSelectOther: boolean;\n /** Model used for synchronization */\n syncModel: AssessmentSyncModel;\n /** Column used for synchronization */\n syncColumn: AssessmentSyncColumn;\n /** Row IDs used for synchronization */\n syncRowIds: string[];\n /** Indicates if synchronization override is allowed */\n syncOverride: boolean;\n}\n\nexport interface RiskCategory {\n /** ID of category */\n id: string;\n /** Title of category */\n title: string;\n}\n\nexport interface RiskFramework {\n /** ID of framework */\n id: string;\n /** Title of framework */\n title: string;\n /** Description of framework */\n description: string;\n /** Risk levels */\n riskLevels: RiskLevel[];\n /** Risk categories */\n riskCategories: RiskCategory[];\n /** Risk matrix columns */\n riskMatrixColumns: RiskMatrixColumn[];\n /** Risk matrix rows */\n riskMatrixRows: RiskMatrixRow[];\n /** Risk matrix settings */\n riskMatrix: RiskMatrix[][];\n /** Creator of risk framework */\n creator?: UserPreview;\n /** Risk matrix row title */\n riskMatrixRowTitle: string;\n /** Risk matrix column title */\n riskMatrixColumnTitle: string;\n}\n\nexport interface RiskLevel {\n /** ID of risk level */\n id: string;\n /** Title of risk level */\n title: string;\n}\n\nexport interface RiskMatrix {\n /** ID of risk matrix */\n id: string;\n /** Title of risk matrix */\n title: string;\n}\n\nexport interface RiskMatrixColumn {\n /** ID of column */\n id: string;\n /** Title of column */\n title: string;\n}\n\nexport interface RiskMatrixRow {\n /** ID of row */\n id: string;\n /** Title of row */\n title: string;\n}\n\nexport interface AssessmentAnswerOption {\n /** ID of answer option */\n id: string;\n /** Index of answer option */\n index: number;\n /** Value of answer */\n value: string;\n}\n\nexport interface AssessmentAnswer {\n /** ID of answer */\n id: string;\n /** Index of answer */\n index: number;\n /** Value of answer */\n value: string;\n}\n\nexport interface AssessmentComment {\n /** ID of comment */\n id: string;\n /** Content of comment */\n content: string;\n /** Date comment made */\n createdAt: string;\n /** Date comment updated */\n updatedAt: string;\n /** Author of comment */\n author?: UserPreview;\n}\n\nexport interface AssessmentPreviousSubmission {\n /** Id of submission */\n id: string;\n /** Date updated */\n updatedAt: string;\n /** ID of question */\n assessmentQuestionId: string;\n /** Answers */\n answers: AssessmentAnswer[];\n}\n\nexport interface AssessmentGroup {\n /** ID of group */\n id: string;\n /** Title of group */\n title: string;\n /** Description of group */\n description: string;\n}\n\nexport interface AssessmentResource {\n /** Type of resource */\n resourceType: AttributeSupportedResourceType;\n /** ID of resource */\n id: string;\n /** Title of resource */\n title?: string;\n /** Name of resource */\n name?: string;\n /** Category of resource */\n category?: DataCategoryType;\n /** Purpose of resource */\n purpose?: ProcessingPurpose;\n /** Type of integration */\n type?: string;\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all assessments in the organization\n *\n * @param client - GraphQL client\n * @returns All assessments in the organization\n */\nexport async function fetchAllAssessments(\n client: GraphQLClient,\n): Promise<Assessment[]> {\n const assessments: Assessment[] = [];\n let offset = 0;\n\n let shouldContinue = false;\n do {\n const {\n assessmentForms: { nodes },\n } = await makeGraphQLRequest<{\n /** Forms */\n assessmentForms: {\n /** Nodes */\n nodes: Assessment[];\n };\n }>(client, ASSESSMENTS, {\n first: PAGE_SIZE,\n offset,\n });\n assessments.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return assessments.sort((a, b) => a.title.localeCompare(b.title));\n}\n/* eslint-enable max-lines */\n","import { GraphQLClient } from 'graphql-request';\nimport { ASSESSMENT_TEMPLATES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport type {\n AssessmentSection,\n RetentionSchedule,\n UserPreview,\n} from './fetchAllAssessments';\nimport {\n AssessmentFormTemplateSource,\n AssessmentFormTemplateStatus,\n} from '@transcend-io/privacy-types';\n\n/**\n * Represents an assessment template with various properties and metadata.\n */\nexport interface AssessmentTemplate {\n /** The ID of the assessment template */\n id: string;\n /** The user who created the assessment template */\n creator: UserPreview;\n /** The user who last edited the assessment template */\n lastEditor: UserPreview;\n /** The title of the assessment template */\n title: string;\n /** The description of the assessment template */\n description: string;\n /** The current status of the assessment template */\n status: AssessmentFormTemplateStatus;\n /** The source fo the form template */\n source: AssessmentFormTemplateSource;\n /** ID of parent template */\n parentId: string;\n /** Indicates if the assessment template is locked */\n isLocked: boolean;\n /** Indicates if the assessment template is archived */\n isArchived: boolean;\n /** The date when the assessment template was created */\n createdAt: string;\n /** The date when the assessment template was last updated */\n updatedAt: string;\n /** The retention schedule of the assessment template */\n retentionSchedule?: RetentionSchedule;\n /** The sections of the assessment template */\n sections: AssessmentSection[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all assessment templates in the organization\n *\n * @param client - GraphQL client\n * @returns All assessment templates in the organization\n */\nexport async function fetchAllAssessmentTemplates(\n client: GraphQLClient,\n): Promise<AssessmentTemplate[]> {\n const assessmentTemplates: AssessmentTemplate[] = [];\n let offset = 0;\n\n let shouldContinue = false;\n do {\n const {\n assessmentFormTemplates: { nodes },\n } = await makeGraphQLRequest<{\n /** Templates */\n assessmentFormTemplates: {\n /** Nodes */\n nodes: AssessmentTemplate[];\n };\n }>(client, ASSESSMENT_TEMPLATES, {\n first: PAGE_SIZE,\n offset,\n });\n assessmentTemplates.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return assessmentTemplates.sort((a, b) => a.title.localeCompare(b.title));\n}\n","import type { SombraStandardScope } from '@transcend-io/privacy-types';\nimport { CREATE_PREFERENCE_ACCESS_TOKENS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport type { GraphQLClient } from 'graphql-request';\nimport { chunk } from 'lodash-es';\nimport { map } from '../bluebird';\n\nexport interface PreferenceAccessTokenInput {\n /** Slug of data subject to authenticate as */\n subjectType: string;\n /** Scopes to grant */\n scopes: SombraStandardScope[];\n /** Expiration time in seconds */\n expiresIn?: number;\n /** Email address of user */\n email: string;\n /** Core identifier for the user */\n coreIdentifier?: string;\n}\n\nconst MAX_BATCH_SIZE = 50;\n\n/**\n * Create preference access tokens for the given identifiers.\n *\n * @see https://docs.transcend.io/docs/articles/preference-management/access-links\n * @param client - GraphQL\n * @param records - Inputs to sign\n * @returns list of access tokens\n */\nasync function createPreferenceAccessTokensPage(\n client: GraphQLClient,\n records: PreferenceAccessTokenInput[],\n): Promise<string[]> {\n const {\n createPrivacyCenterAccessTokens: { nodes },\n } = await makeGraphQLRequest<{\n /** createPrivacyCenterAccessTokens mutation */\n createPrivacyCenterAccessTokens: {\n /** Nodes */\n nodes: {\n /** Token */\n token: string;\n }[];\n };\n }>(client, CREATE_PREFERENCE_ACCESS_TOKENS, {\n input: {\n records,\n },\n });\n return nodes.map((node) => node.token);\n}\n\nexport interface PreferenceAccessTokenInputWithIndex\n extends PreferenceAccessTokenInput {\n /** Index of the input record */\n index?: number;\n}\n\n/**\n * Create preference access tokens for the given identifiers.\n *\n * @see https://docs.transcend.io/docs/articles/preference-management/access-links\n * @param client - GraphQL\n * @param records - Inputs to sign\n * @param emitProgress - Optional progress emitter\n * @param concurrency - Number of concurrent requests to make (default: 10)\n * @returns list of access tokens/input identifiers\n */\nexport async function createPreferenceAccessTokens(\n client: GraphQLClient,\n records: PreferenceAccessTokenInputWithIndex[],\n emitProgress?: (progress: number) => void,\n concurrency = 10,\n): Promise<\n {\n /** Identifier for the record */\n input: PreferenceAccessTokenInputWithIndex;\n /** Access token */\n accessToken: string;\n }[]\n> {\n let completed = 0;\n if (emitProgress) {\n emitProgress(0);\n }\n const results: {\n /** Identifier for the record */\n input: PreferenceAccessTokenInput;\n /** Access token */\n accessToken: string;\n }[] = [];\n\n // Then replace the selection with:\n await map(\n chunk(records, MAX_BATCH_SIZE),\n async (chunkedRecords) => {\n const tokens = await createPreferenceAccessTokensPage(\n client,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n chunkedRecords.map(({ index, ...rest }) => rest),\n );\n const mappedResults = tokens.map((token, index) => ({\n input: chunkedRecords[index],\n accessToken: token,\n }));\n results.push(...mappedResults);\n completed += chunkedRecords.length;\n if (emitProgress) {\n emitProgress(completed);\n }\n },\n { concurrency },\n );\n\n return results;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { ATTRIBUTE_KEYS_REQUESTS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface AttributeKey {\n /** ID of attribute key */\n id: string;\n /** Name of attribute key */\n name: string;\n /** Attribute key type */\n type: string;\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all attribute keys enabled for privacy requests\n *\n * @param client - GraphQL client\n * @returns All attribute keys in the organization\n */\nexport async function fetchAllRequestAttributeKeys(\n client: GraphQLClient,\n): Promise<AttributeKey[]> {\n const attributeKeys: AttributeKey[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n attributeKeys: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n attributeKeys: {\n /** List of matches */\n nodes: AttributeKey[];\n };\n }>(client, ATTRIBUTE_KEYS_REQUESTS, {\n first: PAGE_SIZE,\n offset,\n });\n attributeKeys.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return attributeKeys.sort((a, b) => a.name.localeCompare(b.name));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { ATTRIBUTES, ATTRIBUTE_VALUES } from './gqls';\n\nimport { logger } from '../../logger';\nimport colors from 'colors';\nimport {\n AttributeKeyType,\n AttributeSupportedResourceType,\n} from '@transcend-io/privacy-types';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface AttributeValue {\n /** Attribute ID */\n id: string;\n /** Attribute name */\n name: string;\n /** Attribute description */\n description: string;\n /** Color of attribute value */\n color: string;\n}\n\nexport interface Attribute {\n /** ID of attribute */\n id: string;\n /** Name of attribute */\n name: string;\n /** if custom attribute */\n isCustom: boolean;\n /** Description */\n description: string;\n /** Type of attribute */\n type: AttributeKeyType;\n /** Values */\n values: AttributeValue[];\n /** The different fields that the attribute is enabled on */\n enabledOn: AttributeSupportedResourceType[];\n}\n\nconst PAGE_SIZE = 100;\n\n/**\n * Fetch all attribute values for an attribute key\n *\n * @param client - GraphQL client\n * @param attributeKeyId - Attribute keyID\n * @returns A map from apiKey title to Identifier\n */\nexport async function fetchAllAttributeValues(\n client: GraphQLClient,\n attributeKeyId: string,\n): Promise<AttributeValue[]> {\n logger.info(\n colors.magenta(`Fetching all attribute values for ${attributeKeyId}...`),\n );\n const attributeValues: AttributeValue[] = [];\n let offset = 0;\n\n // Paginate\n let shouldContinue = false;\n do {\n const {\n attributeValues: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n attributeValues: {\n /** List of matches */\n nodes: AttributeValue[];\n };\n }>(client, ATTRIBUTE_VALUES, {\n first: PAGE_SIZE,\n offset,\n attributeKeyId,\n });\n attributeValues.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return attributeValues.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport const SYNC_ATTRIBUTE_TYPES = [\n AttributeKeyType.MultiSelect,\n AttributeKeyType.SingleSelect,\n];\n\n/**\n * Fetch all attributes in an organization\n *\n * @param client - GraphQL client\n * @returns A map from apiKey title to Identifier\n */\nexport async function fetchAllAttributes(\n client: GraphQLClient,\n): Promise<Attribute[]> {\n logger.info(colors.magenta('Fetching all attributes...'));\n const attributes: Attribute[] = [];\n let offset = 0;\n\n // Paginate\n let shouldContinue = false;\n do {\n const {\n attributeKeys: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n attributeKeys: {\n /** List of matches */\n nodes: Attribute[];\n };\n }>(client, ATTRIBUTES, {\n first: PAGE_SIZE,\n offset,\n });\n attributes.push(\n ...(await Promise.all(\n nodes.map(async (node) => ({\n ...node,\n values: SYNC_ATTRIBUTE_TYPES.includes(node.type)\n ? await fetchAllAttributeValues(client, node.id)\n : [],\n })),\n )),\n );\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return attributes.sort((a, b) => a.name.localeCompare(b.name));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { BUSINESS_ENTITIES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\n\nexport interface BusinessEntity {\n /** ID of business entity */\n id: string;\n /** Title of business entity */\n title: string;\n /** Description of business entity */\n description?: string;\n /** Data protection officer name */\n dataProtectionOfficerName?: string;\n /** Data protection officer email */\n dataProtectionOfficerEmail?: string;\n /** Address of business entity */\n address?: string;\n /** Headquarters of business entity */\n headquarterCountry?: IsoCountryCode;\n /** Subdivision of business entity */\n headquarterSubDivision?: IsoCountrySubdivisionCode;\n /** Attributes */\n attributeValues: {\n /** Name of attribute value */\n name: string;\n /** Attribute key */\n attributeKey: {\n /** Name of attribute key */\n name: string;\n };\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all businessEntities in the organization\n *\n * @param client - GraphQL client\n * @returns All businessEntities in the organization\n */\nexport async function fetchAllBusinessEntities(\n client: GraphQLClient,\n): Promise<BusinessEntity[]> {\n const businessEntities: BusinessEntity[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n businessEntities: { nodes },\n } = await makeGraphQLRequest<{\n /** Business entities */\n businessEntities: {\n /** List */\n nodes: BusinessEntity[];\n };\n }>(client, BUSINESS_ENTITIES, {\n first: PAGE_SIZE,\n offset,\n });\n businessEntities.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return businessEntities.sort((a, b) => a.title.localeCompare(b.title));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport {\n ConsentPrecedenceOption,\n UnknownRequestPolicy,\n TelemetryPartitionStrategy,\n RegionsOperator,\n IsoCountrySubdivisionCode,\n IsoCountryCode,\n BrowserTimeZone,\n SignedIabAgreementOption,\n} from '@transcend-io/privacy-types';\nimport {\n InitialViewState,\n BrowserLanguage,\n OnConsentExpiry,\n} from '@transcend-io/airgap.js-types';\nimport {\n FETCH_CONSENT_MANAGER_ID,\n FETCH_CONSENT_MANAGER,\n EXPERIENCES,\n CONSENT_MANAGER_ANALYTICS_DATA,\n FETCH_CONSENT_MANAGER_THEME,\n} from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface ConsentManager {\n /** ID of consent manager */\n id: string;\n /** Production bundle URL */\n bundleURL: string;\n /** Test bundle URL */\n testBundleURL: string;\n /** Configuration of consent manager */\n configuration: {\n /** Domain list */\n domains: string[];\n /** Consent precedence of user vs signal */\n consentPrecedence: ConsentPrecedenceOption;\n /** Unknown request policy */\n unknownRequestPolicy: UnknownRequestPolicy;\n /** Unknown cookie policy */\n unknownCookiePolicy: UnknownRequestPolicy;\n /** Sync endpoint */\n syncEndpoint: string;\n /** Telemetry partitioning */\n telemetryPartitioning: TelemetryPartitionStrategy;\n /** Signed IAB agreement */\n signedIabAgreement: SignedIabAgreementOption;\n /** Sync groups */\n syncGroups: string;\n /** Partition parameter */\n partition: string;\n };\n /** When using a custom partition, this is the partition value */\n partition?: {\n /** Partition value */\n partition: string;\n };\n}\n\n/**\n * Fetch consent manager\n *\n * @param client - GraphQL client\n * @returns Consent manager ID in organization\n */\nexport async function fetchConsentManager(\n client: GraphQLClient,\n): Promise<ConsentManager> {\n const {\n consentManager: { consentManager },\n } = await makeGraphQLRequest<{\n /** Consent manager query */\n consentManager: {\n /** Consent manager object */\n consentManager: ConsentManager;\n };\n }>(client, FETCH_CONSENT_MANAGER);\n return consentManager;\n}\n\n/**\n * Fetch consent manager ID\n *\n * @param client - GraphQL client\n * @param maxRequests - = Max number of requests to send\n * @returns Consent manager ID in organization\n */\nexport async function fetchConsentManagerId(\n client: GraphQLClient,\n maxRequests?: number,\n): Promise<string> {\n const {\n consentManager: { consentManager },\n } = await makeGraphQLRequest<{\n /** Consent manager query */\n consentManager: {\n /** Consent manager object */\n consentManager: {\n /** ID of bundle */\n id: string;\n };\n };\n }>(client, FETCH_CONSENT_MANAGER_ID, {}, {}, maxRequests);\n return consentManager.id;\n}\n\nconst PAGE_SIZE = 50;\n\nexport interface ConsentExperience {\n /** ID of experience */\n id: string;\n /** Name of experience */\n name: string;\n /** Experience display name */\n displayName?: string;\n /** Region that define this regional experience */\n regions: {\n /** Sub division */\n countrySubDivision?: IsoCountrySubdivisionCode;\n /** Country */\n country?: IsoCountryCode;\n }[];\n /** In vs not in operator */\n operator: RegionsOperator;\n /** Priority of experience */\n displayPriority: number;\n /** View state to prompt when auto prompting is enabled */\n viewState: InitialViewState;\n /** Consent expiry setting */\n onConsentExpiry: OnConsentExpiry;\n /** Consent expiry */\n consentExpiry: number;\n /** Purposes that can be opted out of in a particular experience */\n purposes: {\n /** Name of purpose */\n name: string;\n /** Purpose slug */\n trackingType: string;\n }[];\n /** Purposes that are opted out by default in a particular experience */\n optedOutPurposes: {\n /** Name of purpose */\n name: string;\n /** Purpose slug */\n trackingType: string;\n }[];\n /**\n * Browser languages that define this regional experience\n */\n browserLanguages: BrowserLanguage[];\n /** Browser time zones that define this regional experience */\n browserTimeZones: BrowserTimeZone[];\n}\n\n/**\n * Fetch consent manager experiences\n *\n * @param client - GraphQL client\n * @returns Consent manager experiences in the organization\n */\nexport async function fetchConsentManagerExperiences(\n client: GraphQLClient,\n): Promise<ConsentExperience[]> {\n const experiences: ConsentExperience[] = [];\n let offset = 0;\n\n // Fetch all experiences\n let shouldContinue = false;\n do {\n const {\n experiences: { nodes },\n } = await makeGraphQLRequest<{\n /** Consent experience */\n experiences: {\n /** List */\n nodes: ConsentExperience[];\n };\n }>(client, EXPERIENCES, {\n first: PAGE_SIZE,\n offset,\n });\n experiences.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return experiences.sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/**\n * The allowed bin sizes for pulling consent metrics\n */\nexport enum ConsentManagerMetricBin {\n Hourly = '1h',\n Daily = '1d',\n}\n\nexport interface ConsentManagerMetric {\n /** Name of metric */\n name: string;\n /** The metrics */\n points: {\n /** Key of metric */\n key: string;\n /** Value of metric */\n value: string;\n }[];\n}\n\n/**\n * Fetch consent manager analytics data\n *\n * @param client - GraphQL client\n * @param input - Input for fetching data\n * @returns Consent manager purposes in the organization\n */\nexport async function fetchConsentManagerAnalyticsData(\n client: GraphQLClient,\n input: {\n /** Data source */\n dataSource:\n | 'PRIVACY_SIGNAL_TIMESERIES'\n | 'CONSENT_CHANGES_TIMESERIES'\n | 'CONSENT_SESSIONS_BY_REGIME';\n /** Start date, in ISO string format */\n startDate: string;\n /** End date, in ISO string format */\n endDate: string;\n /** Force refetching */\n forceRefetch?: boolean;\n /** Airgap bundle ID */\n airgapBundleId: string;\n /** Bin interval */\n binInterval: ConsentManagerMetricBin;\n /** Whether or not to smooth the time series */\n smoothTimeseries: false;\n },\n): Promise<ConsentManagerMetric[]> {\n const {\n analyticsData: { series },\n } = await makeGraphQLRequest<{\n /** Analytics data response */\n analyticsData: {\n /** Consent manager metrics */\n series: ConsentManagerMetric[];\n };\n }>(client, CONSENT_MANAGER_ANALYTICS_DATA, {\n input,\n });\n return series;\n}\n\nexport interface ConsentManagerTheme {\n /** Primary color */\n primaryColor: string;\n /** Font color */\n fontColor: string;\n /** Privacy policy URL */\n privacyPolicy?: string;\n /** Auto-prompt setting */\n prompt: number;\n}\n\n/**\n * Fetch consent manager theme\n *\n * @param client - GraphQL client\n * @param airgapBundleId - Airgap bundle ID to fetch for\n * @returns Consent manager ID in organization\n */\nexport async function fetchConsentManagerTheme(\n client: GraphQLClient,\n airgapBundleId: string,\n): Promise<ConsentManagerTheme> {\n const {\n consentManagerTheme: { theme },\n } = await makeGraphQLRequest<{\n /** Consent manager query */\n consentManagerTheme: {\n /** Consent manager object */\n theme: ConsentManagerTheme;\n };\n }>(client, FETCH_CONSENT_MANAGER_THEME, {\n airgapBundleId,\n });\n return theme;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { COOKIES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { fetchConsentManagerId } from './fetchConsentManagerId';\nimport {\n ConsentTrackerSource,\n ConsentTrackerStatus,\n} from '@transcend-io/privacy-types';\n\nexport interface Cookie {\n /** ID of the cookie */\n id: string;\n /** Name of the cookie */\n name: string;\n /** Whether cookie is a regular express */\n isRegex: boolean;\n /** Description of cookie */\n description: string;\n /** Enabled tracking purposes for the cookie */\n trackingPurposes: string[];\n /** The consent service */\n service: {\n /** Integration name of service */\n integrationName: string;\n };\n /** Source of how tracker was added */\n source: ConsentTrackerSource;\n /** Status of cookie labeling */\n status: ConsentTrackerStatus;\n /** Owners of that cookie */\n owners: {\n /** Email address of owner */\n email: string;\n }[];\n /** Teams assigned to that cookie */\n teams: {\n /** Name of team */\n name: string;\n }[];\n /** Attributes assigned to that cookie */\n attributeValues: {\n /** Name of attribute value */\n name: string;\n /** Attribute key that the value represents */\n attributeKey: {\n /** Name of attribute team */\n name: string;\n };\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all Cookies in the organization\n *\n * @param client - GraphQL client\n * @param status - The status to fetch\n * @returns All Cookies in the organization\n */\nexport async function fetchAllCookies(\n client: GraphQLClient,\n status = ConsentTrackerStatus.Live,\n): Promise<Cookie[]> {\n const cookies: Cookie[] = [];\n let offset = 0;\n\n const airgapBundleId = await fetchConsentManagerId(client);\n\n // Try to fetch an Cookies with the same title\n let shouldContinue = false;\n do {\n const {\n cookies: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n cookies: {\n /** List of matches */\n nodes: Cookie[];\n };\n }>(client, COOKIES, {\n first: PAGE_SIZE,\n offset,\n airgapBundleId,\n status,\n });\n cookies.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return cookies.sort((a, b) => a.name.localeCompare(b.name));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { DATA_SUB_CATEGORIES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { DataCategoryType } from '@transcend-io/privacy-types';\n\nexport interface DataSubCategory {\n /** ID of data category */\n id: string;\n /** Name of data category */\n name: string;\n /** Type of data category */\n category: DataCategoryType;\n /** Description of data category */\n description?: string;\n /** Regex for data category */\n regex?: string;\n /** Assigned teams */\n teams: {\n /** Team name */\n name: string;\n }[];\n /** Assigned owners */\n owners: {\n /** Email */\n email: string;\n }[];\n /** Custom fields */\n attributeValues: {\n /** Name of attribute value */\n name: string;\n /** Attribute key that the value represents */\n attributeKey: {\n /** Name of attribute team */\n name: string;\n };\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all dataSubCategories in the organization\n *\n * @param client - GraphQL client\n * @returns All dataSubCategories in the organization\n */\nexport async function fetchAllDataCategories(\n client: GraphQLClient,\n): Promise<DataSubCategory[]> {\n const dataSubCategories: DataSubCategory[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n dataSubCategories: { nodes },\n } = await makeGraphQLRequest<{\n /** DataCategories */\n dataSubCategories: {\n /** List */\n nodes: DataSubCategory[];\n };\n }>(client, DATA_SUB_CATEGORIES, {\n first: PAGE_SIZE,\n offset,\n });\n dataSubCategories.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return dataSubCategories.sort((a, b) => a.name.localeCompare(b.name));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { DATA_FLOWS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { fetchConsentManagerId } from './fetchConsentManagerId';\nimport {\n DataFlowScope,\n ConsentTrackerSource,\n ConsentTrackerStatus,\n} from '@transcend-io/privacy-types';\n\nexport interface DataFlow {\n /** ID of data flow */\n id: string;\n /** Value of data flow */\n value: string;\n /** Type of data flow */\n type: DataFlowScope;\n /** Description of data flow */\n description: string;\n /** Enabled tracking purposes */\n trackingType: string[];\n /** The consent service */\n service: {\n /** Integration name of service */\n integrationName: string;\n };\n /** Source of how tracker was added */\n source: ConsentTrackerSource;\n /** Status of data flow labeling */\n status: ConsentTrackerStatus;\n /** Owners of that data flow */\n owners: {\n /** Email address of owner */\n email: string;\n }[];\n /** Teams assigned to that data flow */\n teams: {\n /** Name of team */\n name: string;\n }[];\n /** Attributes assigned to that data flow */\n attributeValues: {\n /** Name of attribute value */\n name: string;\n /** Attribute key that the value represents */\n attributeKey: {\n /** Name of attribute team */\n name: string;\n };\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all DataFlows in the organization\n *\n * @param client - GraphQL client\n * @param status - The status to fetch\n * @returns All DataFlows in the organization\n */\nexport async function fetchAllDataFlows(\n client: GraphQLClient,\n status = ConsentTrackerStatus.Live,\n): Promise<DataFlow[]> {\n const dataFlows: DataFlow[] = [];\n let offset = 0;\n\n const airgapBundleId = await fetchConsentManagerId(client);\n\n // Try to fetch an DataFlow with the same title\n let shouldContinue = false;\n do {\n const {\n dataFlows: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n dataFlows: {\n /** List of matches */\n nodes: DataFlow[];\n };\n }>(client, DATA_FLOWS, {\n first: PAGE_SIZE,\n offset,\n airgapBundleId,\n status,\n ...(status === ConsentTrackerStatus.NeedsReview\n ? { showZeroActivity: true }\n : {}),\n });\n dataFlows.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return dataFlows.sort((a, b) => a.value.localeCompare(b.value));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { MESSAGES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport type { LocaleValue } from '@transcend-io/internationalization';\n\nexport interface Message {\n /** ID of message */\n id: string;\n /** Default message */\n defaultMessage: string;\n /** Description */\n description: string;\n /** React Intl ID */\n targetReactIntlId: string | null;\n /** Disabled locales */\n translations: {\n /** Locale */\n locale: LocaleValue;\n /** Value */\n value: string;\n }[];\n}\n\n/**\n * Fetch all messages in the organization\n *\n * @param client - GraphQL client\n * @returns All messages in the organization\n */\nexport async function fetchAllMessages(\n client: GraphQLClient,\n): Promise<Message[]> {\n const { translatedMessages } = await makeGraphQLRequest<{\n /** Messages */\n translatedMessages: Message[];\n }>(client, MESSAGES, {});\n return translatedMessages;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { DEPLOYED_PRIVACY_CENTER_URL, FETCH_PRIVACY_CENTER_ID } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\n/**\n * Fetch default privacy center URL\n *\n * @param client - GraphQL client\n * @returns Privacy Center ID in organization\n */\nexport async function fetchPrivacyCenterUrl(\n client: GraphQLClient,\n): Promise<string> {\n const { organization } = await makeGraphQLRequest<{\n /** Organization */\n organization: {\n /** URL */\n deployedPrivacyCenterUrl: string;\n };\n }>(client, DEPLOYED_PRIVACY_CENTER_URL);\n return organization.deployedPrivacyCenterUrl;\n}\n\n/**\n * Fetch privacy center ID\n *\n * @param client - GraphQL client\n * @param url - URLto lookup\n * @returns Privacy Center ID in organization\n */\nexport async function fetchPrivacyCenterId(\n client: GraphQLClient,\n url?: string,\n): Promise<string> {\n let urlToUse = url;\n if (!urlToUse) {\n urlToUse = await fetchPrivacyCenterUrl(client);\n }\n const { privacyCenter } = await makeGraphQLRequest<{\n /** Privacy Center query */\n privacyCenter: {\n /** ID of bundle */\n id: string;\n };\n }>(client, FETCH_PRIVACY_CENTER_ID, {\n url: urlToUse,\n });\n return privacyCenter.id;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { POLICIES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport type { LocaleValue } from '@transcend-io/internationalization';\nimport { fetchPrivacyCenterUrl } from './fetchPrivacyCenterId';\n\nexport interface Policy {\n /** ID of policy */\n id: string;\n /** Title of policy */\n title: {\n /** Default message */\n defaultMessage: string;\n };\n /** Disabled locales */\n disabledLocales: LocaleValue[];\n /** Versions */\n versions: {\n /** Message content */\n content: {\n /** Default message */\n defaultMessage: string;\n };\n }[];\n}\n\n/**\n * Fetch all policies in the organization\n *\n * @param client - GraphQL client\n * @returns All policies in the organization\n */\nexport async function fetchAllPolicies(\n client: GraphQLClient,\n): Promise<Policy[]> {\n const deployedPrivacyCenterUrl = await fetchPrivacyCenterUrl(client);\n const { privacyCenterPolicies } = await makeGraphQLRequest<{\n /** Policies */\n privacyCenterPolicies: Policy[];\n }>(client, POLICIES, {\n url: deployedPrivacyCenterUrl,\n });\n\n return privacyCenterPolicies.sort((a, b) =>\n a.title.defaultMessage.localeCompare(b.title.defaultMessage),\n );\n}\n","import type { DataSiloAttributeValue } from './syncDataSilos';\n\nexport interface FormattedAttribute {\n /** Attribute key */\n key: string;\n /** Attribute values */\n values: string[];\n}\n\n/**\n * Format attribute value objects to key-pair values\n *\n * @param vals - Attribute values\n * @returns formatted attributes\n */\nexport function formatAttributeValues(\n vals: DataSiloAttributeValue[],\n): FormattedAttribute[] {\n const attributes: FormattedAttribute[] = [];\n\n vals.map((val) => {\n let foundKey = attributes.find((att) => att.key === val.attributeKey.name);\n\n if (foundKey === undefined) {\n foundKey = {\n key: val.attributeKey.name,\n values: [val.name],\n };\n attributes.push(foundKey);\n } else {\n foundKey.values.push(val.name);\n }\n return attributes;\n });\n\n return attributes;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { PREFERENCE_TOPICS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { PreferenceTopicType } from '@transcend-io/privacy-types';\n\nexport interface PreferenceTopic {\n /** ID of preference topic */\n id: string;\n /** Slug of preference topic */\n slug: string;\n /** Title of topic */\n title: {\n /** ID */\n id: string;\n /** Default message */\n defaultMessage: string;\n };\n /** Whether to show in privacy center */\n showInPrivacyCenter: boolean;\n /** Description to display in privacy center */\n displayDescription: {\n /** ID */\n id: string;\n /** Default message */\n defaultMessage: string;\n };\n /** Type of preference topic */\n type: PreferenceTopicType;\n /** Default configuration */\n defaultConfiguration: string;\n /** Option values */\n preferenceOptionValues: {\n /** Slug of value */\n slug: string;\n /** Title of value */\n title: {\n /** ID */\n id: string;\n /** Default message */\n defaultMessage: string;\n };\n }[];\n /** Related purpose */\n purpose: {\n /** Slug */\n trackingType: string;\n };\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all preference topics in the organization\n *\n * @param client - GraphQL client\n * @returns All preference topics in the organization\n */\nexport async function fetchAllPreferenceTopics(\n client: GraphQLClient,\n): Promise<PreferenceTopic[]> {\n const preferenceTopics: PreferenceTopic[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n preferenceTopics: { nodes },\n } = await makeGraphQLRequest<{\n /** Preference topics */\n preferenceTopics: {\n /** List */\n nodes: PreferenceTopic[];\n };\n }>(client, PREFERENCE_TOPICS, {\n first: PAGE_SIZE,\n offset,\n });\n preferenceTopics.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return preferenceTopics.sort((a, b) =>\n `${a.slug}:${a.purpose.trackingType}`.localeCompare(\n `${b.slug}:${b.purpose.trackingType}`,\n ),\n );\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { PRIVACY_CENTER } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport type { LocaleValue } from '@transcend-io/internationalization';\nimport { PrivacyCenterThemePartial } from '@transcend-io/privacy-types';\nimport { fetchPrivacyCenterUrl } from './fetchPrivacyCenterId';\n\nexport interface PrivacyCenter {\n /** ID of the privacy center */\n id: string;\n /** The URL of the privacy center */\n url: string;\n /** Whether or not the entire privacy center is enabled or disabled */\n isDisabled: boolean;\n /** Whether or not to show the privacy requests button */\n showPrivacyRequestButton: boolean;\n /** Whether or not to show the policies page */\n showPolicies: boolean;\n /** Whether or not to show the tracking technologies page */\n showTrackingTechnologies: boolean;\n /** Whether or not to show the cookies on the tracking technologies page */\n showCookies: boolean;\n /** Whether or not to show the data flows on the tracking technologies page */\n showDataFlows: boolean;\n /** Whether or not to show the consent manager opt out options on the tracking technologies page */\n showConsentManager: boolean;\n /** Whether or not to show the manage your privacy page */\n showManageYourPrivacy: boolean;\n /** Whether or not to show the marketing preferences page */\n showMarketingPreferences: boolean;\n /** What languages are supported for the privacy center */\n locales: LocaleValue[];\n /** The default locale for the privacy center */\n defaultLocale: LocaleValue;\n /** Whether or not to prefer the browser default locale */\n preferBrowserDefaultLocale: boolean;\n /** The email addresses of the employees within your company that are the go-to individuals for managing this privacy center */\n supportEmail: string;\n /** The email addresses of the employees within your company that are the go-to individuals for managing this privacy center */\n replyToEmail: string;\n /** Whether or not to send emails from a no reply email */\n useNoReplyEmailAddress: boolean;\n /** Whether or not to use a custom email domain */\n useCustomEmailDomain: boolean;\n /** Whether or not to transcend access requests from JSON to CSV */\n transformAccessReportJsonToCsv: boolean;\n /** The theme object of colors to display on the privacy center */\n theme: PrivacyCenterThemePartial;\n}\n\n/**\n * Fetch all privacy centers in the organization\n *\n * @param client - GraphQL client\n * @returns All privacy centers in the organization\n */\nexport async function fetchAllPrivacyCenters(\n client: GraphQLClient,\n): Promise<PrivacyCenter[]> {\n const deployedPrivacyCenterUrl = await fetchPrivacyCenterUrl(client);\n const {\n privacyCenter: { themeStr, ...rest },\n } = await makeGraphQLRequest<{\n /** Privacy centers */\n privacyCenter: Omit<PrivacyCenter, 'theme'> & {\n /** Theme string */\n themeStr: string;\n };\n }>(client, PRIVACY_CENTER, {\n url: deployedPrivacyCenterUrl,\n });\n\n return [\n {\n ...rest,\n theme: JSON.parse(themeStr),\n },\n ];\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { PROCESSING_ACTIVITIES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport type {\n ProcessingPurpose,\n DataCategoryType,\n DataProtectionImpactAssessmentStatus,\n Controllership,\n RetentionType,\n} from '@transcend-io/privacy-types';\nimport type { Region } from './formatRegions';\n\nexport interface ProcessingActivity {\n /** ID of processing activity */\n id: string;\n /** Title of processing activity */\n title: string;\n /** Description of processing activity */\n description: string;\n /** Security measure details */\n securityMeasureDetails?: string;\n /** Controllerships */\n controllerships: Controllership[];\n /** Storage regions */\n storageRegions: Region[];\n /** Transfer regions */\n transferRegions: Region[];\n /** Retention type */\n retentionType: RetentionType;\n /** Retention period in days */\n retentionPeriod?: number;\n /** Data protection impact assessment link */\n dataProtectionImpactAssessmentLink?: string;\n /** Data protection impact assessment status */\n dataProtectionImpactAssessmentStatus: DataProtectionImpactAssessmentStatus;\n /** Attribute values */\n attributeValues: {\n /** Name of attribute value */\n name: string;\n /** Attribute key */\n attributeKey: {\n /** Name of attribute key */\n name: string;\n };\n }[];\n /** Data silos */\n dataSilos: {\n /** Data silo title */\n title: string;\n }[];\n /** Data subjects */\n dataSubjects: {\n /** Data subject type */\n type: string;\n }[];\n /** Teams */\n teams: {\n /** Team name */\n name: string;\n }[];\n /** Owners */\n owners: {\n /** Owner email */\n email: string;\n }[];\n /** Processing purpose sub categories */\n processingPurposeSubCategories: {\n /** Processing purpose sub category name */\n name: string;\n /** Processing purpose */\n purpose: ProcessingPurpose;\n }[];\n /** Data sub categories */\n dataSubCategories: {\n /** Data sub category name */\n name: string;\n /** Data category */\n category: DataCategoryType;\n }[];\n /** SaaS categories */\n saaSCategories: {\n /** Title */\n title: string;\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all processingActivities in the organization\n *\n * @param client - GraphQL client\n * @returns All processingActivities in the organization\n */\nexport async function fetchAllProcessingActivities(\n client: GraphQLClient,\n): Promise<ProcessingActivity[]> {\n const processingActivities: ProcessingActivity[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n processingActivities: { nodes },\n } = await makeGraphQLRequest<{\n /** Processing activities */\n processingActivities: {\n /** List */\n nodes: ProcessingActivity[];\n };\n }>(client, PROCESSING_ACTIVITIES, {\n first: PAGE_SIZE,\n offset,\n });\n processingActivities.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return processingActivities.sort((a, b) => a.title.localeCompare(b.title));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { PROCESSING_PURPOSE_SUB_CATEGORIES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { ProcessingPurpose } from '@transcend-io/privacy-types';\n\nexport interface ProcessingPurposeSubCategory {\n /** ID of processing purpose */\n id: string;\n /** Name of processing purpose */\n name: string;\n /** Type of processing purpose */\n purpose: ProcessingPurpose;\n /** Description of processing purpose */\n description?: string;\n /** Assigned teams */\n teams: {\n /** Team name */\n name: string;\n }[];\n /** Assigned owners */\n owners: {\n /** Email */\n email: string;\n }[];\n /** Custom fields */\n attributeValues: {\n /** Name of attribute value */\n name: string;\n /** Attribute key that the value represents */\n attributeKey: {\n /** Name of attribute team */\n name: string;\n };\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all processingPurposeSubCategories in the organization\n *\n * @param client - GraphQL client\n * @returns All processingPurposeSubCategories in the organization\n */\nexport async function fetchAllProcessingPurposes(\n client: GraphQLClient,\n): Promise<ProcessingPurposeSubCategory[]> {\n const processingPurposeSubCategories: ProcessingPurposeSubCategory[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n processingPurposeSubCategories: { nodes },\n } = await makeGraphQLRequest<{\n /** DataCategories */\n processingPurposeSubCategories: {\n /** List */\n nodes: ProcessingPurposeSubCategory[];\n };\n }>(client, PROCESSING_PURPOSE_SUB_CATEGORIES, {\n first: PAGE_SIZE,\n offset,\n });\n processingPurposeSubCategories.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return processingPurposeSubCategories.sort((a, b) =>\n a.name.localeCompare(b.name),\n );\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { PURPOSES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n DefaultConsentOption,\n PreferenceStoreAuthLevel,\n} from '@transcend-io/privacy-types';\nimport { UserPrivacySignalEnum } from '@transcend-io/airgap.js-types';\n\nexport interface Purpose {\n /** ID of purpose */\n id: string;\n /** Name of purpose */\n name: string;\n /** Description of purpose */\n description: string;\n /** Default consent status */\n defaultConsent: DefaultConsentOption;\n /** Slug of purpose */\n trackingType: string;\n /** Whether the purpose is configurable */\n configurable: boolean;\n /** Whether the purpose is essential */\n essential: boolean;\n /** Whether to show the purpose in the consent manager */\n showInConsentManager: boolean;\n /** Whether the purpose is active */\n isActive: boolean;\n /** Display order of the purpose */\n displayOrder: number;\n /** Opt-out signals for the purpose */\n optOutSignals: UserPrivacySignalEnum[];\n /** Whether the purpose is deleted */\n deletedAt?: string;\n /** Authorization level required for the purpose */\n authLevel: PreferenceStoreAuthLevel;\n /** Whether to show the purpose in the privacy center */\n showInPrivacyCenter: boolean;\n /** Title of the purpose */\n title: string;\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all purposes in the organization\n *\n * @param client - GraphQL client\n * @param input - Input\n * @returns All purposes in the organization\n */\nexport async function fetchAllPurposes(\n client: GraphQLClient,\n {\n includeDeleted = false,\n }: {\n /** Whether to include deleted purposes */\n includeDeleted?: boolean;\n } = {},\n): Promise<Purpose[]> {\n const purposes: Purpose[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n purposes: { nodes },\n } = await makeGraphQLRequest<{\n /** Purposes */\n purposes: {\n /** List */\n nodes: Purpose[];\n };\n }>(client, PURPOSES, {\n first: PAGE_SIZE,\n offset,\n input: {\n includeDeleted,\n },\n });\n purposes.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return purposes.sort((a, b) => a.trackingType.localeCompare(b.trackingType));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { Purpose, fetchAllPurposes } from './fetchAllPurposes';\nimport {\n PreferenceTopic,\n fetchAllPreferenceTopics,\n} from './fetchAllPreferenceTopics';\n\nexport interface PurposeWithPreferences extends Purpose {\n /** Topics */\n topics: PreferenceTopic[];\n}\n\n/**\n * Fetch all purposes and preferences for a request]\n *\n * @param client - GraphQL client\n * @returns List of request enrichers\n */\nexport async function fetchAllPurposesAndPreferences(\n client: GraphQLClient,\n): Promise<PurposeWithPreferences[]> {\n const [purposes, topics] = await Promise.all([\n fetchAllPurposes(client),\n fetchAllPreferenceTopics(client),\n ]);\n\n return purposes.map((purpose) => {\n const purposeTopics = topics.filter(\n (topic) => topic.purpose.trackingType === purpose.trackingType,\n );\n return {\n ...purpose,\n topics: purposeTopics,\n };\n });\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { RequestEnricherStatus } from '@transcend-io/privacy-types';\nimport { REQUEST_ENRICHERS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface RequestEnricher {\n /** ID of request enricher */\n id: string;\n /** Name of identifier */\n enricher: {\n /** ID of enricher */\n id: string;\n /** Title of enricher */\n title: string;\n /** Typeof of enricher */\n type: string;\n };\n /** The status of the enricher */\n status: RequestEnricherStatus;\n}\n\nconst PAGE_SIZE = 50;\n\n/**\n * Fetch all request enrichers for a particular request\n *\n * @param client - GraphQL client\n * @param options - Filter options\n * @returns List of request enrichers\n */\nexport async function fetchAllRequestEnrichers(\n client: GraphQLClient,\n {\n requestId,\n }: {\n /** ID of request to filter on */\n requestId: string;\n },\n): Promise<RequestEnricher[]> {\n const requestEnrichers: RequestEnricher[] = [];\n let offset = 0;\n\n // Paginate\n let shouldContinue = false;\n do {\n const {\n requestEnrichers: { nodes },\n } = await makeGraphQLRequest<{\n /** Request Enrichers */\n requestEnrichers: {\n /** List */\n nodes: RequestEnricher[];\n };\n }>(client, REQUEST_ENRICHERS, {\n first: PAGE_SIZE,\n offset,\n requestId,\n });\n requestEnrichers.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return requestEnrichers;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { REQUEST_IDENTIFIERS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface RequestIdentifierMetadata {\n /** ID of request identifier */\n id: string;\n /** Name of identifier */\n name: string;\n /** Status of identifier */\n isVerifiedAtLeastOnce: boolean;\n}\n\nconst PAGE_SIZE = 50;\n\n/**\n * Fetch all request identifier metadata for a particular request\n *\n * @param client - GraphQL client\n * @param options - Filter options\n * @returns List of request identifiers\n */\nexport async function fetchAllRequestIdentifierMetadata(\n client: GraphQLClient,\n {\n requestId,\n }: {\n /** ID of request to filter on */\n requestId: string;\n },\n): Promise<RequestIdentifierMetadata[]> {\n const requestIdentifiers: RequestIdentifierMetadata[] = [];\n let offset = 0;\n\n // Paginate\n let shouldContinue = false;\n do {\n const {\n requestIdentifiers: { nodes },\n } = await makeGraphQLRequest<{\n /** Request Identifiers */\n requestIdentifiers: {\n /** List */\n nodes: RequestIdentifierMetadata[];\n };\n }>(client, REQUEST_IDENTIFIERS, {\n first: PAGE_SIZE,\n offset,\n requestIds: [requestId],\n });\n requestIdentifiers.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return requestIdentifiers;\n}\n","import { IdentifierType } from '@transcend-io/privacy-types';\nimport { decodeCodec, valuesOf } from '@transcend-io/type-utils';\nimport type { Got } from 'got';\nimport { GraphQLClient } from 'graphql-request';\nimport * as t from 'io-ts';\nimport semver from 'semver';\n\nimport { SOMBRA_VERSION } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nconst MIN_SOMBRA_VERSION_TO_DECRYPT = '7.180.0';\n\nconst RequestIdentifier = t.type({\n /** ID of request */\n id: t.string,\n /** Name of identifier */\n name: t.string,\n /** The underlying identifier value */\n value: t.string,\n /** Type of identifier */\n type: valuesOf(IdentifierType),\n});\n\n/** Type override */\nexport type RequestIdentifier = t.TypeOf<typeof RequestIdentifier>;\n\nconst PAGE_SIZE = 50;\n\nexport const RequestIdentifiersResponse = t.type({\n identifiers: t.array(RequestIdentifier),\n});\n\n/**\n * Fetch all request identifiers for a particular request\n *\n * @param client - GraphQL client\n * @param sombra - Sombra client\n * @param options - Options\n * @returns List of request identifiers\n */\nexport async function fetchAllRequestIdentifiers(\n client: GraphQLClient,\n sombra: Got,\n {\n requestId,\n }: {\n /** ID of request to filter on */\n requestId: string;\n },\n): Promise<RequestIdentifier[]> {\n const requestIdentifiers: RequestIdentifier[] = [];\n let offset = 0;\n let shouldContinue = false;\n\n // determine sombra version\n const {\n organization: {\n sombra: { version },\n },\n } = await makeGraphQLRequest<{\n /** The organization */\n organization: {\n /** Sombra */\n sombra: {\n /** Version string */\n version: string;\n };\n };\n }>(client!, SOMBRA_VERSION);\n\n if (version && semver.lt(version, MIN_SOMBRA_VERSION_TO_DECRYPT)) {\n throw new Error(\n `Please upgrade Sombra to ${MIN_SOMBRA_VERSION_TO_DECRYPT} or greater to use this command.`,\n );\n }\n\n do {\n let response: unknown;\n try {\n response = await sombra!\n .post<{\n /** Decrypted identifiers */\n identifiers: RequestIdentifier[];\n }>('v1/request-identifiers', {\n json: {\n first: PAGE_SIZE,\n offset,\n requestId,\n },\n })\n .json();\n } catch (err) {\n throw new Error(\n `Failed to fetch request identifiers: ${\n err?.response?.body || err?.message\n }`,\n );\n }\n\n const { identifiers: nodes } = decodeCodec(\n RequestIdentifiersResponse,\n response,\n );\n\n requestIdentifiers.push(...nodes);\n\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return requestIdentifiers;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport colors from 'colors';\nimport { REQUESTS } from './gqls';\nimport * as t from 'io-ts';\nimport cliProgress from 'cli-progress';\nimport { valuesOf } from '@transcend-io/type-utils';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n RequestAction,\n RequestOrigin,\n RequestStatus,\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\nimport { logger } from '../../logger';\nimport { LOCALE_KEY } from '@transcend-io/internationalization';\n\nexport const RequestPurposeTrigger = t.type({\n title: t.string,\n name: t.string,\n consent: t.boolean,\n enrichedPreferences: t.array(\n t.type({\n topic: t.string,\n selectValues: t.array(\n t.type({\n id: t.string,\n name: t.string,\n preferenceOption: t.type({\n id: t.string,\n slug: t.string,\n title: t.type({\n defaultMessage: t.string,\n }),\n }),\n }),\n ),\n selectValue: t.type({\n id: t.string,\n name: t.string,\n }),\n preferenceTopic: t.type({\n title: t.type({\n defaultMessage: t.string,\n }),\n id: t.string,\n slug: t.string,\n }),\n name: t.string,\n id: t.string,\n booleanValue: t.boolean,\n }),\n ),\n});\n\n/** Override type */\nexport type RequestPurposeTrigger = t.TypeOf<typeof RequestPurposeTrigger>;\n\nexport const PrivacyRequest = t.intersection([\n t.type({\n /** Request ID */\n id: t.string,\n /** Time request was made */\n createdAt: t.string,\n /** Email of request */\n email: t.string,\n /** The type of request */\n type: valuesOf(RequestAction),\n /** Link to request in Transcend dashboard */\n link: t.string,\n /** Whether request is in silent mode */\n isSilent: t.boolean,\n /** Where request was made */\n origin: valuesOf(RequestOrigin),\n /** Whether request is a test request */\n isTest: t.boolean,\n /** The core identifier of the request */\n coreIdentifier: t.string,\n /** Request details */\n details: t.string,\n /** Locale of request */\n locale: valuesOf(LOCALE_KEY),\n /** Status of request */\n status: valuesOf(RequestStatus),\n /** Type of data subject */\n subjectType: t.string,\n /** Country of request */\n country: t.union([t.null, valuesOf(IsoCountryCode)]),\n /** Subdivision of request */\n countrySubDivision: t.union([t.null, valuesOf(IsoCountrySubdivisionCode)]),\n /** Request attributes */\n attributeValues: t.array(\n t.type({\n id: t.string,\n attributeKey: t.type({ name: t.string, id: t.string }),\n name: t.string,\n }),\n ),\n }),\n t.partial({\n /** Days remaining until expired */\n daysRemaining: t.union([t.null, t.number]),\n /** Purpose */\n purpose: RequestPurposeTrigger,\n }),\n]);\n\n/** Type override */\nexport type PrivacyRequest = t.TypeOf<typeof PrivacyRequest>;\n\nconst PAGE_SIZE = 50;\n\n/**\n * Fetch all requests matching a set of filters\n *\n * @param client - GraphQL client\n * @param options - Filter options\n * @returns List of requests\n */\nexport async function fetchAllRequests(\n client: GraphQLClient,\n {\n actions = [],\n statuses = [],\n origins = [],\n text,\n createdAtBefore,\n createdAtAfter,\n isTest,\n isSilent,\n isClosed,\n requestIds = [],\n }: {\n /** Actions to filter on */\n actions?: RequestAction[];\n /** Origins to filter on */\n origins?: RequestOrigin[];\n /** Statuses to filter on */\n statuses?: RequestStatus[];\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Filter for requests with a specific identifier */\n text?: string;\n /** Return test requests */\n isTest?: boolean;\n /** Return silent mode requests */\n isSilent?: boolean;\n /** Filter by whether request is active */\n isClosed?: boolean;\n /**\n * Filter the list of requests for a set of IDs - these are applied\n * at runtime while other filters are applied at the GraphQL level.\n */\n requestIds?: string[];\n } = {},\n): Promise<PrivacyRequest[]> {\n logger.info(colors.magenta('Fetching requests...'));\n\n // create a new progress bar instance and use shades_classic theme\n const t0 = new Date().getTime();\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // read in requests\n const requests: PrivacyRequest[] = [];\n let offset = 0;\n\n // Paginate\n let shouldContinue = false;\n do {\n const {\n requests: { nodes, totalCount },\n } = await makeGraphQLRequest<{\n /** Requests */\n requests: {\n /** List */\n nodes: PrivacyRequest[];\n /** Total count */\n totalCount: number;\n };\n }>(client, REQUESTS, {\n first: PAGE_SIZE,\n offset,\n filterBy: {\n text,\n type: actions.length > 0 ? actions : undefined,\n status: statuses.length > 0 ? statuses : undefined,\n origin: origins.length > 0 ? origins : undefined,\n isTest,\n isSilent,\n isClosed,\n createdAtBefore: createdAtBefore\n ? createdAtBefore.toISOString()\n : undefined,\n createdAtAfter: createdAtAfter\n ? createdAtAfter.toISOString()\n : undefined,\n },\n });\n if (offset === 0 && totalCount > PAGE_SIZE) {\n logger.info(colors.magenta(`Fetching ${totalCount} requests`));\n progressBar.start(totalCount, 0);\n }\n\n requests.push(...nodes);\n offset += PAGE_SIZE;\n progressBar.update(offset);\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n // Log completion time\n logger.info(\n colors.green(\n `Completed fetching of ${requests.length} request in \"${\n totalTime / 1000\n }\" seconds.`,\n ),\n );\n\n // Filter down requests by request ID\n let allRequests = requests;\n if (requestIds && requestIds.length > 0) {\n allRequests = allRequests.filter((request) =>\n requestIds.includes(request.id),\n );\n logger.info(\n colors.green(\n `Filtered down to ${allRequests.length} requests based on ${requestIds.length} provided IDs.`,\n ),\n );\n }\n\n return allRequests;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { TEAMS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { ScopeName } from '@transcend-io/privacy-types';\n\nexport interface Team {\n /** ID of team */\n id: string;\n /** Name of team */\n name: string;\n /** Description of team */\n description: string;\n /** SSO department for automated provisioning */\n ssoDepartment?: string;\n /** SSO group name for automated provisioning */\n ssoGroup?: string;\n /** SSO title mapping for automated provisioning */\n ssoTitle?: string;\n /** List of users on the team */\n users: {\n /** ID of user */\n id: string;\n /** Email of user */\n email: string;\n /** Name of user */\n name: string;\n }[];\n /** List of scopes on the team */\n scopes: {\n /** ID of scope */\n id: string;\n /** Name of scope */\n name: ScopeName;\n /** Title of scope */\n title: string;\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all teams in the organization\n *\n * @param client - GraphQL client\n * @returns All teams in the organization\n */\nexport async function fetchAllTeams(client: GraphQLClient): Promise<Team[]> {\n const teams: Team[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n teams: { nodes },\n } = await makeGraphQLRequest<{\n /** Teams */\n teams: {\n /** List */\n nodes: Team[];\n };\n }>(client, TEAMS, {\n first: PAGE_SIZE,\n offset,\n });\n teams.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return teams.sort((a, b) => a.name.localeCompare(b.name));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { USERS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface User {\n /** ID of user */\n id: string;\n /** Name of user */\n name: string;\n /** Email of user */\n email: string;\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all users in the organization\n *\n * @param client - GraphQL client\n * @returns All users in the organization\n */\nexport async function fetchAllUsers(client: GraphQLClient): Promise<User[]> {\n const users: User[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n users: { nodes },\n } = await makeGraphQLRequest<{\n /** Users */\n users: {\n /** List */\n nodes: User[];\n };\n }>(client, USERS, {\n first: PAGE_SIZE,\n offset,\n });\n users.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return users.sort((a, b) => a.email.localeCompare(b.email));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { VENDORS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\n\nexport interface Vendor {\n /** ID of vendor */\n id: string;\n /** Title of vendor */\n title: string;\n /** Description of vendor */\n description: string;\n /** DPA link */\n dataProcessingAgreementLink?: string;\n /** Contract email */\n contactName?: string;\n /** Contract phone */\n contactPhone?: string;\n /** Address */\n address?: string;\n /** Headquarters country */\n headquarterCountry?: IsoCountryCode;\n /** Headquarters subdivision */\n headquarterSubDivision?: IsoCountrySubdivisionCode;\n /** Website URL */\n websiteUrl?: string;\n /** Business entity */\n businessEntity?: {\n /** Business entity title */\n title: string;\n };\n /** Assigned teams */\n teams: {\n /** Team name */\n name: string;\n }[];\n /** Assigned owners */\n owners: {\n /** Email */\n email: string;\n }[];\n /** Custom fields */\n attributeValues: {\n /** Name of attribute value */\n name: string;\n /** Attribute key that the value represents */\n attributeKey: {\n /** Name of attribute team */\n name: string;\n };\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all vendors in the organization\n *\n * @param client - GraphQL client\n * @returns All vendors in the organization\n */\nexport async function fetchAllVendors(\n client: GraphQLClient,\n): Promise<Vendor[]> {\n const vendors: Vendor[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n vendors: { nodes },\n } = await makeGraphQLRequest<{\n /** Vendors */\n vendors: {\n /** List */\n nodes: Vendor[];\n };\n }>(client, VENDORS, {\n first: PAGE_SIZE,\n offset,\n });\n vendors.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return vendors.sort((a, b) => a.title.localeCompare(b.title));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { API_KEYS } from './gqls';\nimport { keyBy, uniq, difference } from 'lodash-es';\nimport { logger } from '../../logger';\nimport colors from 'colors';\nimport { TranscendInput } from '../../codecs';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface ApiKey {\n /** ID of API key */\n id: string;\n /** Title of API key */\n title: string;\n}\n\nconst PAGE_SIZE = 20;\n\nconst ADMIN_LINK = 'https://app.transcend.io/infrastructure/api-keys';\n\n/**\n * Fetch all API keys in an organization\n *\n * @param client - Client\n * @param titles - Filter on titles\n * @returns API keys\n */\nexport async function fetchAllApiKeys(\n client: GraphQLClient,\n titles?: string[],\n): Promise<ApiKey[]> {\n const apiKeys: ApiKey[] = [];\n let offset = 0;\n\n // Paginate\n let shouldContinue = false;\n do {\n const {\n apiKeys: { nodes },\n } = await makeGraphQLRequest<{\n /** API keys */\n apiKeys: {\n /** List */\n nodes: ApiKey[];\n };\n }>(client, API_KEYS, {\n first: PAGE_SIZE,\n offset,\n titles,\n });\n apiKeys.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n return apiKeys.sort((a, b) => a.title.localeCompare(b.title));\n}\n\n/**\n * Fetch all apiKeys and if any are found in the config that are\n * missing, create those apiKeys.\n *\n * @param apiKeyInputs - API keys to fetch metadata on\n * @param client - GraphQL client\n * @param fetchAll - When true, fetch all API keys\n * @returns A map from apiKey title to Identifier\n */\nexport async function fetchApiKeys(\n {\n 'api-keys': apiKeyInputs = [],\n 'data-silos': dataSilos = [],\n }: TranscendInput,\n client: GraphQLClient,\n fetchAll = false,\n): Promise<{ [k in string]: ApiKey }> {\n logger.info(\n colors.magenta(\n `Fetching ${fetchAll ? 'all' : apiKeyInputs.length} API keys...`,\n ),\n );\n const titles = apiKeyInputs.map(({ title }) => title);\n const expectedApiKeyTitles = uniq(\n dataSilos\n .map((silo) => silo['api-key-title'])\n .filter((x): x is string => !!x),\n );\n const allTitlesExpected = [...expectedApiKeyTitles, ...titles];\n const apiKeys = await fetchAllApiKeys(\n client,\n fetchAll ? undefined : [...expectedApiKeyTitles, ...titles],\n );\n\n // Create a map\n const apiKeysByTitle = keyBy(apiKeys, 'title');\n\n // Determine expected set of apiKeys expected\n const missingApiKeys = difference(\n allTitlesExpected,\n apiKeys.map(({ title }) => title),\n );\n\n // If there are missing apiKeys, throw an error\n if (missingApiKeys.length > 0) {\n logger.info(\n colors.red(\n `Failed to find API keys \"${missingApiKeys.join(\n '\", \"',\n )}\"! Make sure these API keys are created at: ${ADMIN_LINK}`,\n ),\n );\n process.exit(1);\n }\n return apiKeysByTitle;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { CATALOGS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface Catalog {\n /** Integration name */\n integrationName: string;\n /** Title of Data Silo */\n title: string;\n /** Whether API is supported */\n hasApiFunctionality: boolean;\n}\n\nconst PAGE_SIZE = 100;\n\n/**\n * Fetch all integration catalogs in an organization\n *\n * @param client - Client\n * @returns Integration catalogs\n */\nexport async function fetchAllCatalogs(\n client: GraphQLClient,\n): Promise<Catalog[]> {\n const catalogs: Catalog[] = [];\n let offset = 0;\n\n // Paginate\n let shouldContinue = false;\n do {\n const {\n catalogs: { nodes },\n } = await makeGraphQLRequest<{\n /** integration catalogs */\n catalogs: {\n /** List */\n nodes: Catalog[];\n };\n }>(client, CATALOGS, {\n first: PAGE_SIZE,\n offset,\n });\n catalogs.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n return catalogs.sort((a, b) =>\n a.integrationName.localeCompare(b.integrationName),\n );\n}\n\nexport interface IndexedCatalogs {\n /** Mapping from service name to service title */\n serviceToTitle: { [k in string]: string };\n /** Mapping from service name to boolean indicate if service has API integration support */\n serviceToSupportedIntegration: { [k in string]: boolean };\n}\n\n/**\n * Fetch all integration catalogs and index them for usage in common utility manners\n *\n * @param client - Client\n * @returns Integration catalogs\n */\nexport async function fetchAndIndexCatalogs(client: GraphQLClient): Promise<\n {\n /** List of all catalogs */\n catalogs: Catalog[];\n } & IndexedCatalogs\n> {\n // Fetch all integrations in the catalog\n const catalogs = await fetchAllCatalogs(client);\n\n // Create mapping from service name to service title\n const serviceToTitle = catalogs.reduce(\n (acc, catalog) =>\n Object.assign(acc, { [catalog.integrationName]: catalog.title }),\n {} as { [k in string]: string },\n );\n\n // Create mapping from service name to boolean indicate if service has API integration support\n const serviceToSupportedIntegration = catalogs.reduce(\n (acc, catalog) =>\n Object.assign(acc, {\n [catalog.integrationName]: catalog.hasApiFunctionality,\n }),\n {} as { [k in string]: boolean },\n );\n\n return {\n catalogs,\n serviceToTitle,\n serviceToSupportedIntegration,\n };\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { CREATE_DATA_SUBJECT, DATA_SUBJECTS } from './gqls';\nimport { keyBy, flatten, uniq, difference } from 'lodash-es';\nimport { RequestActionObjectResolver } from '@transcend-io/privacy-types';\nimport { TranscendInput } from '../../codecs';\nimport { logger } from '../../logger';\nimport colors from 'colors';\nimport { mapSeries } from '../bluebird';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface DataSubject {\n /** ID of data subject */\n id: string;\n /** Type of data subject */\n type: string;\n /** Whether active */\n active: boolean;\n /** Title of data subject */\n title: {\n /** Default message */\n defaultMessage: string;\n };\n /** Whether silent mode is enabled by default */\n adminDashboardDefaultSilentMode: boolean;\n /** Enabled actions */\n actions: {\n /** Type of action */\n type: RequestActionObjectResolver;\n }[];\n}\n\n/**\n * Fetch all data subjects in an organization\n *\n * @param client - GraphQL client\n * @returns List of data subject configurations\n */\nexport async function fetchAllDataSubjects(\n client: GraphQLClient,\n): Promise<DataSubject[]> {\n // Fetch all data subjects in the organization\n const { internalSubjects } = await makeGraphQLRequest<{\n /** Query response */\n internalSubjects: DataSubject[];\n }>(client, DATA_SUBJECTS);\n return internalSubjects;\n}\n\n/**\n * Fetch all of the data subjects in the organization\n *\n * @param input - Input to fetch\n * @param client - GraphQL client\n * @param fetchAll - When true, always fetch all subjects\n * @returns The list of data subjects\n */\nexport async function ensureAllDataSubjectsExist(\n {\n 'data-silos': dataSilos = [],\n 'data-subjects': dataSubjects = [],\n 'processing-activities': processingActivities = [],\n enrichers = [],\n }: TranscendInput,\n client: GraphQLClient,\n fetchAll = false,\n): Promise<{ [type in string]: DataSubject }> {\n // Only need to fetch data subjects if specified in config\n const expectedDataSubjects = uniq([\n ...flatten(dataSilos.map((silo) => silo['data-subjects'] || []) || []),\n ...flatten(\n processingActivities.map(\n ({ dataSubjectTypes }) => dataSubjectTypes ?? [],\n ) ?? [],\n ),\n ...flatten(\n enrichers.map((enricher) => enricher['data-subjects'] || []) || [],\n ),\n ...dataSubjects.map((subject) => subject.type),\n ]);\n if (expectedDataSubjects.length === 0 && !fetchAll) {\n return {};\n }\n\n // Fetch all data subjects in the organization\n const internalSubjects = await fetchAllDataSubjects(client);\n const dataSubjectByName = keyBy(internalSubjects, 'type');\n\n // Determine expected set of data subjects to create\n const missingDataSubjects = difference(\n expectedDataSubjects,\n internalSubjects.map(({ type }) => type),\n );\n\n // If there are missing data subjects, create new ones\n if (missingDataSubjects.length > 0) {\n logger.info(\n colors.magenta(\n `Creating ${missingDataSubjects.length} new data subjects...`,\n ),\n );\n await mapSeries(missingDataSubjects, async (dataSubject) => {\n logger.info(colors.magenta(`Creating data subject ${dataSubject}...`));\n const { createSubject } = await makeGraphQLRequest<{\n /** Create Subject Response */\n createSubject: {\n /** Created Data Subject */\n subject: DataSubject;\n };\n }>(client, CREATE_DATA_SUBJECT, {\n type: dataSubject,\n skipPublish: true,\n });\n logger.info(colors.green(`Created data subject ${dataSubject}!`));\n\n dataSubjectByName[dataSubject] = createSubject.subject;\n });\n }\n\n return dataSubjectByName;\n}\n\n/**\n * Convert a list of data subject types into the block list of IDs to assign to the data silo\n *\n * @param dataSubjectTypes - The list of data subject types that the data silo should be for\n * @param allDataSubjects - All data subjects in the organization\n * @returns The block list of data subject ids to not process against this data silo\n */\nexport function convertToDataSubjectBlockList(\n dataSubjectTypes: string[],\n allDataSubjects: { [type in string]: DataSubject },\n): string[] {\n dataSubjectTypes.forEach((type) => {\n if (!allDataSubjects[type]) {\n throw new Error(`Expected to find data subject definition: ${type}`);\n }\n });\n\n return Object.values(allDataSubjects)\n .filter((silo) => !dataSubjectTypes.includes(silo.type))\n .map(({ id }) => id);\n}\n\n/**\n * Convert a list of data subject types into the allow list of types\n *\n * @param dataSubjectTypes - The list of data subject types that the data silo should be for\n * @param allDataSubjects - All data subjects in the organization\n * @returns The allow list of data subjects for that silo\n */\nexport function convertToDataSubjectAllowlist(\n dataSubjectTypes: string[],\n allDataSubjects: { [type in string]: DataSubject },\n): string[] {\n dataSubjectTypes.forEach((type) => {\n if (!allDataSubjects[type]) {\n throw new Error(`Expected to find data subject definition: ${type}`);\n }\n });\n\n return Object.values(allDataSubjects)\n .filter((silo) => !dataSubjectTypes.includes(silo.type))\n .map(({ type }) => type);\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { PROMPT_GROUPS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface PromptGroup {\n /** ID of prompts */\n id: string;\n /** The title of the prompt group. */\n title: string;\n /** The description of the prompt group. */\n description: string;\n /** Prompts in the group */\n prompts: {\n /** Title of prompt */\n title: string;\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all PromptGroups in the organization\n *\n * @param client - GraphQL client\n * @returns All PromptGroups in the organization\n */\nexport async function fetchAllPromptGroups(\n client: GraphQLClient,\n): Promise<PromptGroup[]> {\n const promptGroups: PromptGroup[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n promptGroups: { nodes },\n } = await makeGraphQLRequest<{\n /** PromptGroups */\n promptGroups: {\n /** List */\n nodes: PromptGroup[];\n };\n }>(client, PROMPT_GROUPS, {\n first: PAGE_SIZE,\n offset,\n });\n promptGroups.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return promptGroups.sort((a, b) => a.title.localeCompare(b.title));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { PROMPT_PARTIALS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface PromptPartial {\n /** ID of prompts */\n id: string;\n /** The title of the prompt partial. */\n title: string;\n /** The content of the prompt partial. */\n content: string;\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all PromptPartials in the organization\n *\n * @param client - GraphQL client\n * @returns All PromptPartials in the organization\n */\nexport async function fetchAllPromptPartials(\n client: GraphQLClient,\n): Promise<PromptPartial[]> {\n const promptPartials: PromptPartial[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n promptPartials: { nodes },\n } = await makeGraphQLRequest<{\n /** PromptPartials */\n promptPartials: {\n /** List */\n nodes: PromptPartial[];\n };\n }>(client, PROMPT_PARTIALS, {\n first: PAGE_SIZE,\n offset,\n });\n promptPartials.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return promptPartials.sort((a, b) => a.title.localeCompare(b.title));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { PROMPTS, PROMPTS_WITH_VARIABLES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n PromptStatus,\n PromptResponseFormat,\n} from '@transcend-io/privacy-types';\n\nexport interface Prompt {\n /** ID of prompt */\n id: string;\n /** The title of the prompt */\n title: string;\n /** The status of the prompt */\n status: PromptStatus;\n /** The content of the prompt */\n content: string;\n /** Temperature to use with prompt */\n temperature: number;\n /** Top P to use with prompt */\n topP: number;\n /** Max tokens to sample for prompt */\n maxTokensToSample: number;\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all Prompts in the organization\n *\n * @param client - GraphQL client\n * @param options - Options\n * @returns All Prompts in the organization\n */\nexport async function fetchAllPrompts(\n client: GraphQLClient,\n {\n text,\n titles = [],\n ids = [],\n }: {\n /** Filter by text */\n text?: string;\n /** Filter by ids */\n ids?: string[];\n /** Filter by titles */\n titles?: string[];\n } = {},\n): Promise<Prompt[]> {\n const prompts: Prompt[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n prompts: { nodes },\n } = await makeGraphQLRequest<{\n /** Prompts */\n prompts: {\n /** List */\n nodes: Prompt[];\n };\n }>(client, PROMPTS, {\n first: PAGE_SIZE,\n offset,\n filterBy: {\n ...(text ? { text } : {}),\n ...(titles.length > 0 ? { title: titles } : {}),\n ...(ids.length > 0 ? { id: ids } : {}),\n },\n });\n prompts.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return prompts.sort((a, b) => a.title.localeCompare(b.title));\n}\n\n/**\n * The basic metadata needed to use a prompt at runtime\n */\nexport type TranscendPromptTemplated = {\n /** ID of prompt */\n id: string;\n /** Title of prompt */\n title: string;\n /** Content of prompt */\n content: string;\n /** Status of prompt */\n status: PromptStatus;\n /** Temperature */\n temperature?: number;\n /** Top P */\n topP?: number;\n /** Max tokens to sample */\n maxTokensToSample?: number;\n /** Response format */\n responseFormat?: PromptResponseFormat;\n};\n\n/**\n * The basic metadata needed to use a prompt partial at runtime\n */\nexport type TranscendPromptPartialTemplated = {\n /** ID of prompt */\n id: string;\n /** Title of prompt */\n title: string;\n /** Slug of prompt */\n slug: string;\n /** Content of prompt */\n content: string;\n};\n\n/**\n * Calculated variables\n */\nexport type PromptCalculatedVariable = {\n /** JSON stringified data to template */\n data: string | null;\n /** Name of variable */\n name: string;\n};\n\n/**\n * Runtime variables\n */\nexport type PromptRuntimeVariable = {\n /** Type of variable */\n type: string;\n /** Name of variable */\n name: string;\n};\n\n/**\n * Metadata useful for filling variables within a prompt\n */\nexport type TranscendPromptsAndVariables = {\n /** Prompts ready to be templated */\n prompts: TranscendPromptTemplated[];\n /** Prompt partials */\n promptPartials: TranscendPromptPartialTemplated[];\n /** Calculated variables to be templated */\n calculatedVariables: PromptCalculatedVariable[];\n /** Runtime variables to be templated */\n runtimeVariables: PromptRuntimeVariable[];\n};\n\n/**\n * Fetch prompts with templated variables\n *\n * @param client - GraphQL client\n * @param options - Options\n * @returns Prompts and template variables\n */\nexport async function fetchPromptsWithVariables(\n client: GraphQLClient,\n {\n promptTitles = [],\n promptIds = [],\n }: {\n /** Filter by prompt ids */\n promptIds?: string[];\n /** Filter by prompt titles */\n promptTitles?: string[];\n } = {},\n): Promise<TranscendPromptsAndVariables> {\n const { promptsWithVariables } = await makeGraphQLRequest<{\n /** Prompts */\n promptsWithVariables: TranscendPromptsAndVariables;\n }>(client, PROMPTS_WITH_VARIABLES, {\n input: {\n ...(promptTitles.length > 0 ? { promptTitles } : {}),\n ...(promptIds.length > 0 ? { promptIds } : {}),\n },\n });\n\n return promptsWithVariables;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { PROMPT_THREADS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface PromptThread {\n /** ID of prompts */\n id: string;\n /** Thread ID from API */\n threadId: string;\n /** Related slack message TS */\n slackMessageTs?: string;\n /** Related slack message team ID */\n slackTeamId?: string;\n /** Related slack channel ID */\n slackChannelId?: string;\n /** Related slack channel name */\n slackChannelName?: string;\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all PromptThreads in the organization\n *\n * @param client - GraphQL client\n * @param filterBy - Filter options\n * @returns All PromptThreads in the organization\n */\nexport async function fetchAllPromptThreads(\n client: GraphQLClient,\n filterBy: {\n /** Thread IDs to filter on */\n threadIds?: string[];\n /** Slack message timestamps to filter on */\n slackMessageTs?: string[];\n },\n): Promise<PromptThread[]> {\n const promptThreads: PromptThread[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n promptThreads: { nodes },\n } = await makeGraphQLRequest<{\n /** PromptThreads */\n promptThreads: {\n /** List */\n nodes: PromptThread[];\n };\n }>(client, PROMPT_THREADS, {\n first: PAGE_SIZE,\n offset,\n filterBy,\n });\n promptThreads.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return promptThreads.sort((a, b) => a.threadId.localeCompare(b.threadId));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { REQUEST_DATA_SILOS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n RequestDataSiloStatus,\n RequestStatus,\n} from '@transcend-io/privacy-types';\n\nexport interface RequestDataSilo {\n /** ID of RequestDataSilo */\n id: string;\n}\n\nexport interface RequestDataSiloFilters {\n /** ID of request to filter on */\n requestId?: string;\n /** Data silo ID */\n dataSiloId?: string;\n /**\n * The statuses to filter on\n */\n statuses?: RequestDataSiloStatus[];\n /** The request statuses to filter on */\n requestStatuses?: RequestStatus[];\n}\n\n/**\n * Fetch a count of request data silos\n *\n * @param client - GraphQL client\n * @param options - Filter options\n * @returns List of request identifiers\n */\nexport async function fetchRequestDataSilosCount(\n client: GraphQLClient,\n { requestId, dataSiloId, requestStatuses, statuses }: RequestDataSiloFilters,\n): Promise<number> {\n const {\n requestDataSilos: { totalCount },\n } = await makeGraphQLRequest<{\n /** Request Data Silos */\n requestDataSilos: {\n /** List */\n nodes: RequestDataSilo[];\n /** Total count */\n totalCount: number;\n };\n }>(client, REQUEST_DATA_SILOS, {\n first: 1,\n offset: 0,\n filterBy: {\n dataSiloId,\n requestId,\n status: statuses,\n requestStatus: requestStatuses,\n },\n });\n\n return totalCount;\n}\n\nconst PAGE_SIZE = 100;\n\n/**\n * Fetch all request data silos by some filter criteria\n *\n * @param client - GraphQL client\n * @param options - Filter options\n * @returns List of request identifiers\n */\nexport async function fetchRequestDataSilos(\n client: GraphQLClient,\n {\n requestId,\n dataSiloId,\n requestStatuses,\n statuses,\n limit,\n onProgress,\n }: {\n /** ID of request to filter on */\n requestId?: string;\n /** Data silo ID */\n dataSiloId?: string;\n /**\n * The statuses to filter on\n */\n statuses?: RequestDataSiloStatus[];\n /** The request statuses to filter on */\n requestStatuses?: RequestStatus[];\n /** Limit on number of requests */\n limit?: number;\n /** Handle progress updates */\n onProgress?: (numUpdated: number) => void;\n },\n): Promise<RequestDataSilo[]> {\n const requestDataSilos: RequestDataSilo[] = [];\n let offset = 0;\n\n // Try to fetch an DataFlow with the same title\n let shouldContinue = false;\n do {\n const {\n requestDataSilos: { nodes },\n } = await makeGraphQLRequest<{\n /** Request Data Silos */\n requestDataSilos: {\n /** List */\n nodes: RequestDataSilo[];\n /** Total count */\n totalCount: number;\n };\n }>(client, REQUEST_DATA_SILOS, {\n first: PAGE_SIZE,\n offset,\n filterBy: {\n dataSiloId,\n requestId,\n status: statuses,\n requestStatus: requestStatuses,\n },\n });\n requestDataSilos.push(...nodes);\n\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n onProgress?.(nodes.length);\n } while (shouldContinue && (!limit || offset < limit));\n\n return requestDataSilos;\n}\n\n/**\n * Fetch all request identifiers for a particular request\n *\n * @param client - GraphQL client\n * @param options - Filter options\n * @returns List of request identifiers\n */\nexport async function fetchRequestDataSilo(\n client: GraphQLClient,\n {\n requestId,\n dataSiloId,\n }: {\n /** ID of request to filter on */\n requestId: string;\n /** Data silo ID */\n dataSiloId: string;\n },\n): Promise<RequestDataSilo> {\n const nodes = await fetchRequestDataSilos(client, {\n requestId,\n dataSiloId,\n });\n if (nodes.length !== 1) {\n throw new Error(\n `Failed to find RequestDataSilo with requestId:${requestId},dataSiloId:${dataSiloId}`,\n );\n }\n\n return nodes[0];\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { REDUCED_REQUESTS_FOR_DATA_SILO_COUNT } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\n/**\n * Get number of open requests for a data silo\n *\n * @param client - GraphQL client\n * @param options - Filter options\n * @returns List of request identifiers\n */\nexport async function fetchRequestDataSiloActiveCount(\n client: GraphQLClient,\n {\n dataSiloId,\n }: {\n /** Data silo ID */\n dataSiloId: string;\n },\n): Promise<number> {\n const {\n listReducedRequestsForDataSilo: { totalCount },\n } = await makeGraphQLRequest<{\n /** Requests */\n listReducedRequestsForDataSilo: {\n /** Total count */\n totalCount: number;\n };\n }>(client, REDUCED_REQUESTS_FOR_DATA_SILO_COUNT, {\n input: {\n dataSiloId,\n isResolved: false,\n },\n });\n\n return totalCount;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { BULK_REQUEST_FILES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface RequestFileCursor {\n /** The ID of the request file */\n id: string;\n /** The created at timestamp */\n createdAt: string;\n}\n\nexport interface RequestFile {\n /** The remote ID */\n remoteId: string;\n /** The file name */\n fileName: string;\n}\n\nexport interface RequestFileResponse {\n /** RequestFiles */\n bulkRequestFiles: {\n /** List */\n nodes: RequestFile[];\n /** The page info */\n pageInfo: {\n /** Whether there is a next page */\n hasNextPage: boolean;\n /** The end cursor */\n endCursor: string;\n };\n };\n}\n\n/**\n * Fetch all RequestFiles for a single request\n *\n * @param client - GraphQL client\n * @param pageSize - How many request files to fetch per API call\n * @param filterBy - Filter by\n * @returns All RequestFiles in the organization\n */\nexport async function fetchRequestFilesForRequest(\n client: GraphQLClient,\n /** How many request files to fetch per API call */\n pageSize: number,\n filterBy: {\n /** Filter by request IDs */\n requestIds: string[];\n /** Filter by data silo ID */\n dataSiloIds: string[];\n },\n): Promise<RequestFile[]> {\n const requestFiles: RequestFile[] = [];\n let cursor: string | null = null;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const response: RequestFileResponse =\n await makeGraphQLRequest<RequestFileResponse>(\n client,\n BULK_REQUEST_FILES,\n {\n filterBy: {\n ...filterBy,\n },\n first: pageSize,\n after: cursor ?? undefined,\n },\n );\n const {\n bulkRequestFiles: { nodes, pageInfo },\n } = response;\n requestFiles.push(...nodes);\n shouldContinue = pageInfo.hasNextPage;\n cursor = pageInfo.endCursor;\n } while (shouldContinue);\n\n return requestFiles.sort((a, b) => a.remoteId.localeCompare(b.remoteId));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { DETERMINE_LOGIN_METHOD, ASSUME_ROLE, LOGIN } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface OrganizationPreview {\n /** Name of organization */\n name: string;\n /** Id of organization */\n id: string;\n /** uri of organization */\n uri: string;\n /** ID of parent organization */\n parentOrganizationId?: string;\n}\n\nexport interface UserRole {\n /** ID of role */\n id: string;\n /** Related organization */\n organization: OrganizationPreview;\n}\n\n/**\n * Log in as a user\n *\n * @param client - GraphQL client\n * @param options - Email/password\n * @returns Cookie and roles\n */\nexport async function loginUser(\n client: GraphQLClient,\n {\n email,\n password,\n }: {\n /** Email of user */\n email: string;\n /** Password of user */\n password: string;\n },\n): Promise<{\n /** Cookie to be used to make subsequent requests */\n loginCookie: string;\n /** Roles of the user */\n roles: UserRole[];\n}> {\n const {\n determineLoginMethod: { loginMethod },\n } = await makeGraphQLRequest<{\n /** Determine login method */\n determineLoginMethod: {\n /** Login method info */\n loginMethod: {\n /** Email being logged in */\n email: string;\n /** Sombra public key */\n sombraPublicKey: string;\n };\n };\n }>(client, DETERMINE_LOGIN_METHOD, {\n email,\n });\n\n const res = await client.rawRequest<{\n /** Login */\n login: {\n /** User */\n user: {\n /** Roles of user */\n roles: UserRole[];\n };\n };\n }>(LOGIN, {\n email,\n password,\n publicKey: loginMethod.sombraPublicKey,\n });\n const {\n login: { user },\n } = res.data;\n\n // Get login cookie from response\n const loginCookie = res.headers.get('set-cookie');\n if (!loginCookie || !loginCookie.includes('laravel')) {\n throw new Error('Failed to get login cookie in response');\n }\n\n return {\n roles: user.roles,\n loginCookie,\n };\n}\n\n/**\n * Assume role for user into another organization\n *\n * @param client - GraphQL client\n * @param options - Email/password\n */\nexport async function assumeRole(\n client: GraphQLClient,\n {\n email,\n roleId,\n }: {\n /** Email of user */\n email: string;\n /** Role of user assuming into */\n roleId: string;\n },\n): Promise<void> {\n const {\n determineLoginMethod: { loginMethod },\n } = await makeGraphQLRequest<{\n /** Determine login method */\n determineLoginMethod: {\n /** Login method info */\n loginMethod: {\n /** Email being logged in */\n email: string;\n /** Sombra public key */\n sombraPublicKey: string;\n };\n };\n }>(client, DETERMINE_LOGIN_METHOD, {\n email,\n userId: roleId,\n });\n\n await client.rawRequest<{\n /** Assume role */\n assumeRole: {\n /** Mutation ID */\n clientMutationId: string;\n };\n }>(ASSUME_ROLE, {\n id: roleId,\n publicKey: loginMethod.sombraPublicKey,\n });\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { CREATE_API_KEY, DELETE_API_KEY } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { ScopeName } from '@transcend-io/privacy-types';\n\nexport interface CreatedApiKey {\n /** ID of API key */\n id: string;\n /** Actual API key */\n apiKey: string;\n /** Title of the API key */\n title: string;\n}\n\n/**\n * Create an API key\n *\n * @param client - GraphQL client\n * @param input - Input\n * @returns The API key\n */\nexport async function createApiKey(\n client: GraphQLClient,\n input: {\n /** Title of API key */\n title: string;\n /** Scopes for API key */\n scopes: ScopeName[];\n },\n): Promise<CreatedApiKey> {\n const {\n createApiKey: { apiKey },\n } = await makeGraphQLRequest<{\n /** Create API key */\n createApiKey: {\n /** API key */\n apiKey: CreatedApiKey;\n };\n }>(client, CREATE_API_KEY, { input });\n\n return apiKey;\n}\n\n/**\n * Delete an API key\n *\n * @param client - GraphQL client\n * @param id - API key Id\n */\nexport async function deleteApiKey(\n client: GraphQLClient,\n id: string,\n): Promise<void> {\n await makeGraphQLRequest(client, DELETE_API_KEY, { id });\n}\n","import {\n AssessmentsDisplayLogicAction,\n ComparisonOperator,\n LogicOperator,\n} from '@transcend-io/privacy-types';\nimport { decodeCodec, valuesOf } from '@transcend-io/type-utils';\nimport * as t from 'io-ts';\n\n// This codec is for rules that logically require a list of values to compare against.\nexport const AssessmentRuleWithOperands = t.type({\n dependsOnQuestionReferenceId: t.string,\n comparisonOperator: t.union([\n t.literal(ComparisonOperator.IsEqualTo),\n t.literal(ComparisonOperator.IsNotEqualTo),\n t.literal(ComparisonOperator.IsOneOf),\n t.literal(ComparisonOperator.IsNotOneOf),\n t.literal(ComparisonOperator.Contains),\n ]),\n comparisonOperands: t.array(t.string),\n});\n\n// This codec is for the specific rule that does NOT require comparison operands.\nexport const AssessmentRuleWithoutOperands = t.type({\n dependsOnQuestionReferenceId: t.string,\n comparisonOperator: t.union([\n t.literal(ComparisonOperator.IsNotShown),\n t.literal(ComparisonOperator.IsShown),\n ]),\n});\n\n/**\n * The final, flexible codec that accepts EITHER a rule with operands OR a rule without them.\n */\nexport const AssessmentRule = t.union([\n AssessmentRuleWithOperands,\n AssessmentRuleWithoutOperands,\n]);\n/** Type override */\nexport type AssessmentRule = t.TypeOf<typeof AssessmentRule>;\n\nexport interface AssessmentNestedRule {\n /** The operator to use when comparing the nested rules */\n logicOperator: LogicOperator;\n /** The rules to evaluate and be compared with to other using the LogicOperator */\n rules?: AssessmentRule[];\n /** The nested rules to add one more level of nesting to the rules. They are also compared to each other. */\n nestedRules?: AssessmentNestedRule[];\n}\n\nexport const AssessmentNestedRule: t.RecursiveType<\n t.Type<AssessmentNestedRule>\n> = t.recursion('AssessmentNestedRule', (self) =>\n t.intersection([\n t.type({\n /** The operator to use when comparing the nested rules */\n logicOperator: valuesOf(LogicOperator),\n }),\n t.partial({\n /** The rules to evaluate and be compared with to other using the LogicOperator */\n rules: t.array(AssessmentRule),\n /** The nested rules to add one more level of nesting to the rules. They are also compared to each other. */\n nestedRules: t.array(self),\n }),\n ]),\n);\n\nexport const AssessmentAction = t.partial({\n action: valuesOf(AssessmentsDisplayLogicAction),\n rule: AssessmentRule,\n nestedRule: AssessmentNestedRule,\n});\n\n/** Type override */\nexport type AssessmentAction = t.TypeOf<typeof AssessmentAction>;\n\n/**\n * Parse the assessment display logic\n *\n * @param displayLogic - Stringified rule\n * @returns The parsed assessment display logic\n */\nexport function parseAssessmentDisplayLogic(\n displayLogic: string,\n): AssessmentAction {\n return decodeCodec(AssessmentAction, displayLogic);\n}\n","import { ComparisonOperator } from '@transcend-io/privacy-types';\nimport { decodeCodec, valuesOf } from '@transcend-io/type-utils';\nimport * as t from 'io-ts';\n\nexport const AssessmentRiskLogic = t.intersection([\n t.partial({\n riskAssignment: t.partial({\n riskLevelId: t.string,\n riskMatrixRowId: t.string,\n riskMatrixColumnId: t.string,\n }),\n }),\n t.type({\n comparisonOperands: t.array(t.string),\n comparisonOperator: valuesOf(ComparisonOperator),\n }),\n]);\n\n/** Type override */\nexport type AssessmentRiskLogic = t.TypeOf<typeof AssessmentRiskLogic>;\n\n/**\n * Parse the assessment risk logic\n *\n * @param riskLogic - Stringified rule\n * @returns The parsed assessment risk logic\n */\nexport function parseAssessmentRiskLogic(\n riskLogic: string,\n): AssessmentRiskLogic {\n return decodeCodec(AssessmentRiskLogic, riskLogic);\n}\n","/* eslint-disable max-lines */\nimport cliProgress from 'cli-progress';\nimport {\n DataCategoryInput,\n DataSiloInput,\n ProcessingPurposeInput,\n} from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { logger } from '../../logger';\nimport colors from 'colors';\nimport { mapSeries, map } from '../bluebird';\nimport {\n DATA_SILOS,\n CREATE_DATA_SILOS,\n UPDATE_OR_CREATE_DATA_POINT,\n DATA_POINTS,\n SUB_DATA_POINTS,\n UPDATE_DATA_SILOS,\n DATA_SILOS_ENRICHED,\n SUB_DATA_POINTS_WITH_GUESSES,\n} from './gqls';\nimport {\n convertToDataSubjectBlockList,\n DataSubject,\n} from './fetchDataSubjects';\nimport { ApiKey } from './fetchApiKeys';\nimport {\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n PromptAVendorEmailCompletionLinkType,\n PromptAVendorEmailSendType,\n ConfidenceLabel,\n RequestActionObjectResolver,\n SubDataPointDataSubCategoryGuessStatus,\n} from '@transcend-io/privacy-types';\nimport { sortBy, chunk, keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { apply } from '@transcend-io/type-utils';\n\nexport interface DataSiloAttributeValue {\n /** Key associated to value */\n attributeKey: {\n /** Name of key */\n name: string;\n };\n /** Name of value */\n name: string;\n}\nexport interface DataSilo {\n /** ID of dataSilo */\n id: string;\n /** Title of dataSilo */\n title: string;\n /** Type of silo */\n type: string;\n /** The link to the data silo */\n link: string;\n /** Attribute labels */\n attributeValues: DataSiloAttributeValue[];\n /** description */\n description: string;\n /** Metadata for this data silo */\n catalog: {\n /** Whether the data silo supports automated vendor coordination */\n hasAvcFunctionality: boolean;\n };\n}\n\nconst BATCH_SILOS_LIMIT = 20;\n\n/**\n * Fetch all dataSilos in the organization\n *\n * @param client - GraphQL client\n * @param title - Filter by title\n * @returns All dataSilos in the organization\n */\nexport async function fetchAllDataSilos<TDataSilo extends DataSilo>(\n client: GraphQLClient,\n {\n titles,\n pageSize,\n ids = [],\n gql = DATA_SILOS,\n integrationNames = [],\n }: {\n /** Page size to fetch datapoints in */\n pageSize: number;\n /** Title */\n titles?: string[];\n /** IDs */\n ids?: string[];\n /** Set of integration names to fetch */\n integrationNames?: string[];\n /** GQL query for data silos */\n gql?: string;\n },\n): Promise<TDataSilo[]> {\n logger.info(\n colors.magenta(\n `Fetching ${ids.length === 0 ? 'all' : ids.length} Data Silos...`,\n ),\n );\n\n const dataSilos: TDataSilo[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n dataSilos: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n dataSilos: {\n /** List of matches */\n nodes: TDataSilo[];\n };\n }>(client, gql, {\n filterBy: {\n ids: ids.length > 0 ? ids : undefined,\n type: integrationNames.length > 0 ? integrationNames : undefined,\n titles,\n },\n first: pageSize,\n offset,\n });\n dataSilos.push(...nodes);\n offset += pageSize;\n shouldContinue = nodes.length === pageSize;\n } while (shouldContinue);\n logger.info(\n colors.green(\n `Found a total of ${dataSilos.length} data silo${\n ids.length > 0 ? ` matching IDs ${ids.join(',')}` : ''\n }s${\n integrationNames.length > 0\n ? ` matching integrationNames ${integrationNames.join(',')}`\n : ''\n }`,\n ),\n );\n\n return dataSilos.sort((a, b) => a.title.localeCompare(b.title));\n}\n\nexport interface SubDataPoint {\n /** Name (or key) of the subdatapoint */\n name: string;\n /** The description */\n description?: string;\n /** Personal data category */\n categories: DataCategoryInput[];\n /** The processing purpose for this sub datapoint */\n purposes: ProcessingPurposeInput[];\n /**\n * When true, this subdatapoint should be revealed in a data access request.\n * When false, this field should be redacted\n */\n accessRequestVisibilityEnabled: boolean;\n /**\n * When true, this subdatapoint should be redacted during an erasure request.\n * There normally is a choice of enabling hard deletion or redaction at the\n * datapoint level, but if redaction is enabled, this column can be used\n * to define which fields should be redacted.\n */\n erasureRequestRedactionEnabled: boolean;\n /** Attribute attached to subdatapoint */\n attributeValues: DataSiloAttributeValue[];\n /** Data category guesses that are output by the classifier */\n pendingCategoryGuesses?: {\n /** Data category being guessed */\n category: DataCategoryInput;\n /** Status of guess */\n status: SubDataPointDataSubCategoryGuessStatus;\n /** Confidence level of guess */\n confidence: number;\n /** Confidence label */\n confidenceLabel: ConfidenceLabel;\n /** classifier version that produced the guess */\n classifierVersion: number;\n }[];\n}\n\ninterface DataPoint {\n /** ID of dataPoint */\n id: string;\n /** Title of dataPoint */\n title: {\n /** Default message */\n defaultMessage: string;\n };\n /** The path to this data point */\n path: string[];\n /** Description */\n description: {\n /** Default message */\n defaultMessage: string;\n };\n /** Name */\n name: string;\n /** Global actions */\n actionSettings: {\n /** Action type */\n type: RequestActionObjectResolver;\n /** Is enabled */\n active: boolean;\n }[];\n /** Data collection tag for privacy request download zip labeling */\n dataCollection?: {\n /** Title of data collection */\n title: {\n /** Default message (since message can be translated) */\n defaultMessage: string;\n };\n };\n /** Metadata for this data silo */\n catalog: {\n /** Whether the data silo supports automated vendor coordination */\n hasAvcFunctionality: boolean;\n };\n /** Owners of the datapoint */\n owners: {\n /** Email address of the owner */\n email: string;\n }[];\n /** Teams that own the datapoint */\n teams: {\n /** Name of the team */\n name: string;\n }[];\n /** Database integration queries */\n dbIntegrationQueries: {\n /** Approved query */\n query: string | null;\n /** Suggested query */\n suggestedQuery: string | null;\n /** Request action */\n requestType: RequestActionObjectResolver;\n }[];\n}\n\ninterface DataPointWithSubDataPoint extends DataPoint {\n /** The associated subdatapoints */\n subDataPoints: SubDataPoint[];\n}\n\n/**\n * Helper to fetch all subdatapoints for a given datapoint\n *\n * @param client - The GraphQL client\n * @param dataPointId - The datapoint ID\n * @param options - Options\n * @returns The list of subdatapoints\n */\nexport async function fetchAllSubDataPoints(\n client: GraphQLClient,\n dataPointId: string,\n {\n debug,\n includeGuessedCategories,\n pageSize,\n }: {\n /** Debug logs */\n debug: boolean;\n /** Page size */\n pageSize: number;\n /** When true, metadata around guessed data categories should be included */\n includeGuessedCategories?: boolean;\n },\n): Promise<SubDataPoint[]> {\n const subDataPoints: SubDataPoint[] = [];\n\n let offset = 0;\n\n let shouldContinue = false;\n do {\n try {\n if (debug) {\n logger.log(\n colors.magenta(`Pulling in subdatapoints for offset ${offset}`),\n );\n }\n const {\n subDataPoints: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n subDataPoints: {\n /** List of matches */\n nodes: SubDataPoint[];\n };\n }>(\n client,\n includeGuessedCategories\n ? SUB_DATA_POINTS_WITH_GUESSES\n : SUB_DATA_POINTS,\n {\n first: pageSize,\n filterBy: {\n dataPoints: [dataPointId],\n },\n offset,\n },\n );\n\n subDataPoints.push(...nodes);\n offset += pageSize;\n shouldContinue = nodes.length === pageSize;\n\n if (debug) {\n logger.log(\n colors.green(\n `Pulled in subdatapoints for offset ${offset} for dataPointId=${dataPointId}`,\n ),\n );\n }\n } catch (err) {\n logger.error(\n colors.red(\n `An error fetching subdatapoints for offset ${offset} for dataPointId=${dataPointId}`,\n ),\n );\n throw err;\n }\n } while (shouldContinue);\n return sortBy(subDataPoints, 'name');\n}\n\n/**\n * Fetch all datapoints for a data silo\n *\n * @param client - GraphQL client\n * @param dataSiloId - Data silo ID\n * @param options - Options\n * @returns List of datapoints\n */\nexport async function fetchAllDataPoints(\n client: GraphQLClient,\n dataSiloId: string,\n {\n debug,\n pageSize,\n skipSubDatapoints,\n includeGuessedCategories,\n }: {\n /** Debug logs */\n debug: boolean;\n /** Page size */\n pageSize: number;\n /** Skip fetching of subdatapoints */\n skipSubDatapoints?: boolean;\n /** When true, metadata around guessed data categories should be included */\n includeGuessedCategories?: boolean;\n },\n): Promise<DataPointWithSubDataPoint[]> {\n const dataPoints: DataPointWithSubDataPoint[] = [];\n\n // TODO: https://transcend.height.app/T-40481 - add cursor pagination\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n if (debug) {\n logger.info(colors.magenta(`Fetching datapoints with offset: ${offset}`));\n }\n\n const {\n dataPoints: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n dataPoints: {\n /** List of matches */\n nodes: DataPoint[];\n };\n }>(client, DATA_POINTS, {\n first: pageSize,\n filterBy: {\n dataSilos: [dataSiloId],\n },\n offset,\n });\n\n if (debug) {\n logger.info(\n colors.magenta(\n `Fetched ${nodes.length} datapoints at offset: ${offset}`,\n ),\n );\n }\n\n if (!skipSubDatapoints) {\n await map(\n nodes,\n /* eslint-disable no-loop-func */\n async (node) => {\n try {\n if (debug) {\n logger.info(\n colors.magenta(\n `Fetching subdatapoints for ${node.name} for datapoint offset ${offset}`,\n ),\n );\n }\n\n const subDataPoints = await fetchAllSubDataPoints(client, node.id, {\n pageSize: 1000, // max page size\n debug,\n includeGuessedCategories,\n });\n dataPoints.push({\n ...node,\n subDataPoints: subDataPoints.sort((a, b) =>\n a.name.localeCompare(b.name),\n ),\n });\n\n if (debug) {\n logger.info(\n colors.green(\n `Successfully fetched subdatapoints for ${node.name}`,\n ),\n );\n }\n } catch (err) {\n logger.error(\n colors.red(\n `An error fetching subdatapoints for ${node.name} datapoint offset ${offset}`,\n ),\n );\n throw err;\n }\n },\n /* eslint-enable no-loop-func */\n {\n concurrency: 5,\n },\n );\n\n if (debug) {\n logger.info(\n colors.green(\n `Fetched all subdatapoints for page of datapoints at offset: ${offset}`,\n ),\n );\n }\n }\n\n offset += pageSize;\n shouldContinue = nodes.length === pageSize;\n } while (shouldContinue);\n return dataPoints.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport interface DataSiloEnriched {\n /** ID of dataSilo */\n id: string;\n /** Title of dataSilo */\n title: string;\n /** Type of silo */\n type: string;\n /** Link to silo */\n link: string;\n /** Outer type of silo */\n outerType: string;\n /** Description of data silo */\n description: string;\n /** Webhook URL */\n url?: string;\n /** Email address of user to notify for prompt a person use case */\n notifyEmailAddress?: string;\n /** Associated API keys */\n apiKeys: {\n /** Title */\n title: string;\n }[];\n /** Data subject block list */\n subjectBlocklist: {\n /** Type of data subject */\n type: string;\n }[];\n /** Identifiers */\n identifiers: {\n /** Name of identifier */\n name: string;\n /** True if identifier is wired */\n isConnected: boolean;\n }[];\n /** Dependent data silos */\n dependentDataSilos: {\n /** Title of silo */\n title: string;\n }[];\n /** Silo owners */\n owners: {\n /** Email owners */\n email: string;\n }[];\n /** The teams assigned to this data silo */\n teams: {\n /** Name of the team assigned to this data silo */\n name: string;\n }[];\n /** Metadata for this data silo */\n catalog: {\n /** Whether the data silo supports automated vendor coordination */\n hasAvcFunctionality: boolean;\n };\n /** Silo is live */\n isLive: boolean;\n /** Hosting country of data silo */\n country?: IsoCountryCode;\n /** Hosting subdivision data silo */\n countrySubDivision?: IsoCountrySubdivisionCode;\n /**\n * The frequency with which we should be sending emails for this data silo, in milliseconds.\n */\n promptAVendorEmailSendFrequency: number;\n /**\n * The type of emails to send for this data silo, i.e. send an email for each DSR, across all open DSRs,\n * or per profile in a DSR.\n */\n promptAVendorEmailSendType: PromptAVendorEmailSendType;\n /**\n * Indicates whether prompt-a-vendor emails should include a list of identifiers\n * in addition to a link to the bulk processing UI.\n */\n promptAVendorEmailIncludeIdentifiersAttachment: boolean;\n /**\n * Indicates what kind of link to generate as part of the emails sent out for this Prompt-a-Vendor silo.\n */\n promptAVendorEmailCompletionLinkType: PromptAVendorEmailCompletionLinkType;\n /**\n * The frequency with which we should retry sending emails for this data silo, in milliseconds.\n * Needs to be a string because the number can be larger than the MAX_INT\n */\n manualWorkRetryFrequency: string;\n /** Attribute values tagged to data silo */\n attributeValues: DataSiloAttributeValue[];\n /**\n * The data silos that discovered this particular data silo\n */\n discoveredBy: {\n /** Title of data silo */\n title: string;\n }[];\n /**\n * The business entities assigned directly to this data silo\n */\n businessEntities: {\n /** Title of business entity */\n title: string;\n }[];\n}\n\n/**\n * Fetch all dataSilos with additional metadata\n *\n * @param client - GraphQL client\n * @param options - Filter options\n * @returns All dataSilos in the organization\n */\nexport async function fetchEnrichedDataSilos(\n client: GraphQLClient,\n {\n ids,\n pageSize,\n titles,\n debug,\n skipDatapoints,\n skipSubDatapoints,\n includeGuessedCategories,\n integrationNames,\n }: {\n /** Page size */\n pageSize: number;\n /** Filter by IDs */\n ids?: string[];\n /** Enable debug logs */\n debug: boolean;\n /** Filter by title */\n titles?: string[];\n /** Integration names */\n integrationNames?: string[];\n /** Skip fetching of datapoints */\n skipDatapoints?: boolean;\n /** Skip fetching of subdatapoints */\n skipSubDatapoints?: boolean;\n /** When true, metadata around guessed data categories should be included */\n includeGuessedCategories?: boolean;\n },\n): Promise<[DataSiloEnriched, DataPointWithSubDataPoint[]][]> {\n const dataSilos: [DataSiloEnriched, DataPointWithSubDataPoint[]][] = [];\n\n // Grab silos\n const silos = await fetchAllDataSilos<DataSiloEnriched>(client, {\n titles,\n ids,\n integrationNames,\n pageSize,\n gql: DATA_SILOS_ENRICHED,\n });\n\n // Graph datapoints for each silo\n if (!skipDatapoints) {\n await mapSeries(silos, async (silo, index) => {\n logger.info(\n colors.magenta(\n `[${index + 1}/${silos.length}] Fetching data silo - ${silo.title}`,\n ),\n );\n\n const dataPoints = await fetchAllDataPoints(client, silo.id, {\n debug,\n pageSize,\n skipSubDatapoints,\n includeGuessedCategories,\n });\n\n if (debug) {\n logger.info(\n colors.green(\n `[${index + 1}/${\n silos.length\n }] Successfully fetched datapoint for - ${silo.title}`,\n ),\n );\n }\n\n dataSilos.push([silo, dataPoints]);\n });\n }\n\n logger.info(\n colors.green(\n `Successfully fetched all ${silos.length} data silo configurations`,\n ),\n );\n\n return dataSilos;\n}\n\n/**\n * Sync a data silo configuration\n *\n * @param dataSilos - Data silos to sync\n * @param client - GraphQL client\n * @param options - Options\n * @returns Data silo info\n */\nexport async function syncDataSilos(\n dataSilos: DataSiloInput[],\n client: GraphQLClient,\n {\n pageSize,\n dataSubjectsByName,\n apiKeysByTitle,\n }: {\n /** Page size */\n pageSize: number;\n /** The data subjects in the organization */\n dataSubjectsByName: { [type in string]: DataSubject };\n /** API key title to API key */\n apiKeysByTitle: { [title in string]: ApiKey };\n },\n): Promise<{\n /** Whether successfully updated */\n success: boolean;\n /** A mapping between data silo title to data silo ID */\n dataSiloTitleToId: { [k in string]: string };\n}> {\n let encounteredError = false;\n\n // Time duration\n const t0 = new Date().getTime();\n logger.info(colors.magenta(`Syncing \"${dataSilos.length}\" data silos...`));\n\n // Determine the set of data silos that already exist\n const existingDataSilos = await fetchAllDataSilos(client, {\n titles: dataSilos.map(({ title }) => title),\n pageSize,\n });\n\n // Create a mapping of title -> existing silo, if it exists\n const existingDataSiloByTitle = keyBy<Pick<DataSilo, 'id' | 'title'>>(\n existingDataSilos,\n 'title',\n );\n\n // Create new silos that do not exist\n const newDataSiloInputs = dataSilos.filter(\n ({ title }) => !existingDataSiloByTitle[title],\n );\n if (newDataSiloInputs.length > 0) {\n logger.info(\n colors.magenta(\n `Creating \"${newDataSiloInputs.length}\" data silos that did not exist...`,\n ),\n );\n\n // Batch the creation\n const chunked = chunk(newDataSiloInputs, BATCH_SILOS_LIMIT);\n await mapSeries(chunked, async (dependencyUpdateChunk) => {\n const {\n createDataSilos: { dataSilos },\n } = await makeGraphQLRequest<{\n /** Mutation result */\n createDataSilos: {\n /** New data silos */\n dataSilos: Pick<DataSilo, 'id' | 'title'>[];\n };\n }>(client, CREATE_DATA_SILOS, {\n input: dependencyUpdateChunk.map((input) => ({\n name: input['outer-type'] || input.integrationName,\n title: input.title,\n country: input.country,\n countrySubDivision: input.countrySubDivision,\n })),\n });\n\n // save mapping of title and id\n dataSilos.forEach((silo) => {\n existingDataSiloByTitle[silo.title] = silo;\n });\n });\n\n logger.info(\n colors.green(\n `Successfully created \"${newDataSiloInputs.length}\" data silos!`,\n ),\n );\n }\n\n // Batch the updates\n const chunkedUpdates = chunk(dataSilos, BATCH_SILOS_LIMIT);\n await mapSeries(chunkedUpdates, async (dataSiloUpdateChunk, ind) => {\n logger.info(\n colors.magenta(\n `[Batch ${ind + 1}/${chunkedUpdates.length}] Syncing \"${\n dataSiloUpdateChunk.length\n }\" data silos`,\n ),\n );\n await makeGraphQLRequest<{\n /** Mutation result */\n updateDataSilos: {\n /** New data silos */\n dataSilos: Pick<DataSilo, 'id' | 'title'>[];\n };\n }>(client, UPDATE_DATA_SILOS, {\n input: {\n dataSilos: dataSiloUpdateChunk.map((input) => ({\n id: existingDataSiloByTitle[input.title].id,\n country: input.country,\n countrySubDivision: input.countrySubDivision,\n url: input.url,\n headers: input.headers,\n description: input.description,\n identifiers: input['identity-keys'],\n isLive: !input.disabled,\n ownerEmails: input.owners,\n teamNames: input.teams,\n // clear out if not specified, otherwise the update needs to be applied after\n // all data silos are created\n dependedOnDataSiloTitles: input['deletion-dependencies']\n ? undefined\n : [],\n apiKeyId: input['api-key-title']\n ? apiKeysByTitle[input['api-key-title']].id\n : undefined,\n dataSubjectBlockListIds: input['data-subjects']\n ? convertToDataSubjectBlockList(\n input['data-subjects'],\n dataSubjectsByName,\n )\n : undefined,\n attributes: input.attributes,\n businessEntityTitles: input.businessEntityTitles,\n // AVC settings\n notifyEmailAddress: input['email-settings']?.['notify-email-address'],\n promptAVendorEmailSendFrequency:\n input['email-settings']?.['send-frequency'],\n promptAVendorEmailSendType: input['email-settings']?.['send-type'],\n promptAVendorEmailIncludeIdentifiersAttachment:\n input['email-settings']?.['include-identifiers-attachment'],\n promptAVendorEmailCompletionLinkType:\n input['email-settings']?.['completion-link-type'],\n manualWorkRetryFrequency:\n input['email-settings']?.['manual-work-retry-frequency'],\n })),\n },\n });\n logger.info(\n colors.green(\n `[Batch ${ind + 1}/${chunkedUpdates.length}] Synced \"${\n dataSiloUpdateChunk.length\n }\" data silos!`,\n ),\n );\n });\n\n // Sync datapoints\n\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n const dataSilosWithDataPoints = dataSilos.filter(\n ({ datapoints = [] }) => datapoints.length > 0,\n );\n const totalDataPoints = dataSilos\n .map(({ datapoints = [] }) => datapoints.length)\n .reduce((acc, count) => acc + count, 0);\n logger.info(\n colors.magenta(\n `Syncing \"${totalDataPoints}\" datapoints from \"${dataSilosWithDataPoints.length}\" data silos...`,\n ),\n );\n progressBar.start(totalDataPoints, 0);\n let total = 0;\n\n await map(\n dataSilosWithDataPoints,\n async ({ datapoints, title }) => {\n if (datapoints) {\n await mapSeries(datapoints, async (datapoint) => {\n const fields = datapoint.fields\n ? datapoint.fields.map(\n ({\n key,\n description,\n categories,\n purposes,\n attributes,\n ...rest\n }) =>\n // TODO: Support setting title separately from the 'key/name'\n ({\n name: key,\n description,\n categories: !categories\n ? undefined\n : categories.map((category) => ({\n ...category,\n name: category.name || 'Other',\n })),\n purposes: !purposes\n ? undefined\n : purposes.map((purpose) => ({\n ...purpose,\n name: purpose.name || 'Other',\n })),\n attributes,\n accessRequestVisibilityEnabled:\n rest['access-request-visibility-enabled'],\n erasureRequestRedactionEnabled:\n rest['erasure-request-redaction-enabled'],\n }),\n )\n : undefined;\n\n const payload = {\n dataSiloId: existingDataSiloByTitle[title].id,\n path: datapoint.path,\n name: datapoint.key,\n title: datapoint.title,\n description: datapoint.description,\n ...(datapoint.owners\n ? {\n ownerEmails: datapoint.owners,\n }\n : {}),\n ...(datapoint.teams\n ? {\n teamNames: datapoint.teams,\n }\n : {}),\n ...(datapoint['data-collection-tag']\n ? { dataCollectionTag: datapoint['data-collection-tag'] }\n : {}),\n querySuggestions: !datapoint['privacy-action-queries']\n ? undefined\n : Object.entries(datapoint['privacy-action-queries']).map(\n ([key, value]) => ({\n requestType: key,\n suggestedQuery: value,\n }),\n ),\n enabledActions: datapoint['privacy-actions'] || [], // clear out when not specified\n subDataPoints: fields,\n };\n\n // Ensure no duplicate sub-datapoints are provided\n const subDataPointsToUpdate = (payload.subDataPoints || []).map(\n ({ name }) => name,\n );\n const duplicateDataPoints = subDataPointsToUpdate.filter(\n (name, index) => subDataPointsToUpdate.indexOf(name) !== index,\n );\n if (duplicateDataPoints.length > 0) {\n logger.info(\n colors.red(\n `\\nCannot update datapoint \"${\n datapoint.key\n }\" as it has duplicate sub-datapoints with the same name: \\n${duplicateDataPoints.join(\n '\\n',\n )}`,\n ),\n );\n encounteredError = true;\n } else {\n try {\n await makeGraphQLRequest(\n client,\n UPDATE_OR_CREATE_DATA_POINT,\n payload,\n );\n } catch (err) {\n logger.info(\n colors.red(\n `\\nFailed to update datapoint \"${datapoint.key}\" for data silo \"${title}\"! - \\n${err.message}`,\n ),\n );\n encounteredError = true;\n }\n }\n total += 1;\n progressBar.update(total);\n });\n }\n },\n {\n concurrency: 10,\n },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Synced \"${\n dataSilos.length\n }\" data silos and \"${totalDataPoints}\" datapoints in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n return {\n success: !encounteredError,\n dataSiloTitleToId: apply(existingDataSiloByTitle, ({ id }) => id),\n };\n}\n\n/**\n * Sync data silo dependencies\n *\n * @param client - GraphQL client\n * @param dependencyUpdates - Mapping from [data silo ID, dependency titles]\n * @returns True upon success\n */\nexport async function syncDataSiloDependencies(\n client: GraphQLClient,\n dependencyUpdates: [string, string[]][],\n): Promise<boolean> {\n let encounteredError = false;\n logger.info(\n colors.magenta(\n `Syncing \"${dependencyUpdates.length}\" data silo dependencies...`,\n ),\n );\n\n // Batch the updates\n const chunkedUpdates = chunk(dependencyUpdates, BATCH_SILOS_LIMIT);\n await mapSeries(chunkedUpdates, async (dependencyUpdateChunk, ind) => {\n logger.info(\n colors.magenta(\n `[Batch ${ind}/${dependencyUpdateChunk.length}] Updating \"${dependencyUpdateChunk.length}\" data silos...`,\n ),\n );\n try {\n await makeGraphQLRequest<{\n /** Mutation result */\n updateDataSilos: {\n /** New data silos */\n dataSilos: Pick<DataSilo, 'id' | 'title'>[];\n };\n }>(client, UPDATE_DATA_SILOS, {\n input: {\n dataSilos: dependencyUpdateChunk.map(\n ([id, dependedOnDataSiloTitles]) => ({\n id,\n dependedOnDataSiloTitles,\n }),\n ),\n },\n });\n logger.info(\n colors.green(\n `[Batch ${ind + 1}/${dependencyUpdateChunk.length}] ` +\n `Synced \"${dependencyUpdateChunk.length}\" data silos!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `[Batch ${ind + 1}/${dependencyUpdateChunk.length}] ` +\n `Failed to update \"${dependencyUpdateChunk.length}\" silos! - ${err.message}`,\n ),\n );\n }\n });\n return !encounteredError;\n}\n/* eslint-enable max-lines */\n","import { EnricherInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { ENRICHERS, CREATE_ENRICHER, UPDATE_ENRICHER } from './gqls';\nimport {\n EnricherType,\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n PreflightRequestStatus,\n RequestAction,\n} from '@transcend-io/privacy-types';\nimport { Identifier } from './fetchIdentifiers';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { DataSubject } from './fetchDataSubjects';\n\nexport interface Enricher {\n /** ID of enricher */\n id: string;\n /** Title of enricher */\n title: string;\n /** URL of enricher */\n url: string;\n /** Server silo */\n type: EnricherType;\n /** Input identifier */\n inputIdentifier: {\n /** Identifier name */\n name: string;\n };\n /** The selected actions */\n actions: RequestAction[];\n /** Output identifiers */\n identifiers: {\n /** Identifier name */\n name: string;\n }[];\n /** Data subjects that the preflight check is configured for */\n dataSubjects: {\n /** Data subject type */\n type: string;\n }[];\n /** The duration (in ms) that the enricher should take to execute. - BigInt */\n expirationDuration: string;\n /** Looker query title */\n lookerQueryTitle?: string;\n /** A regular expression that can be used to match on for cancelation */\n testRegex?: string;\n /** The status that the enricher should transfer to when condition is met. */\n transitionRequestStatus?: PreflightRequestStatus;\n /** The twilio phone number to send from */\n phoneNumbers: string[];\n /**\n * The list of regions that should trigger the enrichment condition\n */\n regionList: (IsoCountryCode | IsoCountrySubdivisionCode)[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all enrichers in the organization\n *\n * @param client - GraphQL client\n * @param title - Filter by title\n * @returns All enrichers in the organization\n */\nexport async function fetchAllEnrichers(\n client: GraphQLClient,\n title?: string,\n): Promise<Enricher[]> {\n const enrichers: Enricher[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n enrichers: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n enrichers: {\n /** List of matches */\n nodes: Enricher[];\n };\n }>(client, ENRICHERS, {\n first: PAGE_SIZE,\n offset,\n title,\n });\n enrichers.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return enrichers.sort((a, b) => a.title.localeCompare(b.title));\n}\n\n/**\n * Sync an enricher configuration\n *\n * @param client - GraphQL client\n * @param options - Options\n */\nexport async function syncEnricher(\n client: GraphQLClient,\n {\n enricher,\n identifierByName,\n dataSubjectsByName,\n }: {\n /** The enricher input */\n enricher: EnricherInput;\n /** Index of identifiers in the organization */\n identifierByName: { [name in string]: Identifier };\n /** Lookup data subject by name */\n dataSubjectsByName: { [name in string]: DataSubject };\n },\n): Promise<void> {\n // Whether to continue looping\n const matches = await fetchAllEnrichers(client, enricher.title);\n const existingEnricher = matches.find(\n ({ title }) => title === enricher.title,\n );\n\n // Map to data subject Ids\n const dataSubjectIds = enricher['data-subjects']?.map((subject) => {\n const existing = dataSubjectsByName[subject];\n if (!existing) {\n throw new Error(`Failed to find a data subject with name: ${subject}`);\n }\n return existing.id;\n });\n\n // If enricher exists, update it, else create new\n const inputIdentifier = enricher['input-identifier'];\n const actionUpdates =\n enricher['privacy-actions'] || Object.values(RequestAction);\n if (existingEnricher) {\n await makeGraphQLRequest(client, UPDATE_ENRICHER, {\n input: {\n id: existingEnricher.id,\n title: enricher.title,\n url: enricher.url,\n headers: enricher.headers,\n testRegex: enricher.testRegex,\n lookerQueryTitle: enricher.lookerQueryTitle,\n expirationDuration:\n typeof enricher.expirationDuration === 'number'\n ? enricher.expirationDuration.toString()\n : undefined,\n transitionRequestStatus: enricher.transitionRequestStatus,\n phoneNumbers: enricher.phoneNumbers,\n regionList: enricher.regionList,\n dataSubjectIds,\n description: enricher.description || '',\n inputIdentifier: inputIdentifier\n ? identifierByName[inputIdentifier].id\n : undefined,\n identifiers: enricher['output-identifiers'].map(\n (id) => identifierByName[id].id,\n ),\n ...(existingEnricher.type === EnricherType.Sombra\n ? {}\n : { actions: actionUpdates }),\n },\n });\n } else if (inputIdentifier) {\n await makeGraphQLRequest(client, CREATE_ENRICHER, {\n input: {\n title: enricher.title,\n url: enricher.url,\n type: enricher.type || EnricherType.Server,\n headers: enricher.headers,\n testRegex: enricher.testRegex,\n lookerQueryTitle: enricher.lookerQueryTitle,\n expirationDuration:\n typeof enricher.expirationDuration === 'number'\n ? enricher.expirationDuration.toString()\n : undefined,\n transitionRequestStatus: enricher.transitionRequestStatus,\n phoneNumbers: enricher.phoneNumbers,\n dataSubjectIds,\n regionList: enricher.regionList,\n description: enricher.description || '',\n inputIdentifier: identifierByName[inputIdentifier].id,\n identifiers: enricher['output-identifiers'].map(\n (id) => identifierByName[id].id,\n ),\n actions: actionUpdates,\n },\n });\n }\n}\n","import { TemplateInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { TEMPLATES, CREATE_TEMPLATE } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface Template {\n /** ID of Template */\n id: string;\n /** Title of Template */\n title: string;\n /** Template subject (e.g. email subject) */\n subject: {\n /** Default message for template subject */\n defaultMessage: string;\n };\n /** Template body - rich text HTML */\n template: {\n /** Default message for template body */\n defaultMessage: string;\n };\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all Templates in the organization\n *\n * @param client - GraphQL client\n * @param title - Filter by title\n * @returns All Templates in the organization\n */\nexport async function fetchAllTemplates(\n client: GraphQLClient,\n title?: string,\n): Promise<Template[]> {\n const templates: Template[] = [];\n let offset = 0;\n\n // Try to fetch an Template with the same title\n let shouldContinue = false;\n do {\n const {\n templates: { nodes },\n } = await makeGraphQLRequest<{\n /** Query response */\n templates: {\n /** List of matches */\n nodes: Template[];\n };\n }>(client, TEMPLATES, {\n first: PAGE_SIZE,\n offset,\n title,\n });\n templates.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return templates.sort((a, b) => a.title.localeCompare(b.title));\n}\n\n/**\n * Sync an email template configuration\n *\n * @param template - The email template input\n * @param client - GraphQL client\n */\nexport async function syncTemplate(\n template: TemplateInput,\n client: GraphQLClient,\n): Promise<void> {\n // Try to fetch an Template with the same title\n const matches = await fetchAllTemplates(client, template.title);\n const existingTemplate = matches.find(\n ({ title }) => title === template.title,\n );\n\n // If Template exists, update it\n if (!existingTemplate) {\n await makeGraphQLRequest(client, CREATE_TEMPLATE, {\n title: template.title,\n });\n }\n}\n","import {\n IsoCountrySubdivisionCode,\n IsoCountryCode,\n} from '@transcend-io/privacy-types';\nimport type { RegionInput } from '../../codecs';\n\n// Country subdivision is nullable in DB\nexport interface Region {\n /** Country */\n country: IsoCountryCode;\n /** Sub division (may be null in DB) */\n countrySubDivision?: IsoCountrySubdivisionCode | null;\n}\n\n/**\n * Format regions list to remove null country subdivisions\n *\n * @param vals - Regions\n * @returns formatted regions\n */\nexport function formatRegions(vals: Region[]): RegionInput[] {\n return vals.map(({ country, countrySubDivision }) => ({\n country,\n ...(countrySubDivision ? { countrySubDivision } : {}),\n }));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { GLOBAL_ACTION_ITEM_COLLECTIONS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { TranscendProduct } from '@transcend-io/privacy-types';\n\nexport interface ActionItemCollection {\n /** ID of collection */\n id: string;\n /** Title of collection */\n title: string;\n /** Description of collection */\n description: string;\n /** Whether section is hidden */\n hidden: boolean;\n /** Which locations/products the action item shows up in */\n productLine: TranscendProduct;\n}\n\n/**\n * Fetch all action item collections in the organization\n *\n * @param client - GraphQL client\n * @param filterBy - Filter by\n * @returns All action item collections in the organization\n */\nexport async function fetchAllActionItemCollections(\n client: GraphQLClient,\n filterBy: {\n /** Filter on location */\n location?: TranscendProduct;\n } = {},\n): Promise<ActionItemCollection[]> {\n const {\n globalActionItemCollections: { nodes },\n } = await makeGraphQLRequest<{\n /** ActionItemCollections */\n globalActionItemCollections: {\n /** List */\n nodes: ActionItemCollection[];\n };\n }>(client, GLOBAL_ACTION_ITEM_COLLECTIONS, {\n filterBy: {\n ...filterBy,\n },\n });\n return nodes;\n}\n","import colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { CREATE_CONSENT_PARTITION, CONSENT_PARTITIONS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { mapSeries } from '../bluebird';\nimport { difference } from 'lodash-es';\nimport { logger } from '../../logger';\nimport { PartitionInput } from '../../codecs';\nimport { fetchConsentManagerId } from './fetchConsentManagerId';\n\nconst PAGE_SIZE = 50;\n\nexport interface TranscendPartition {\n /** ID of the partition */\n id: string;\n /** Name of partition */\n name: string;\n /** Partition value */\n partition: string;\n}\n\n/**\n * Fetch the list of partitions\n *\n * @param client - GraphQL client\n * @returns Partition list\n */\nexport async function fetchPartitions(\n client: GraphQLClient,\n): Promise<TranscendPartition[]> {\n const partitions: TranscendPartition[] = [];\n let offset = 0;\n\n // Fetch all partitions\n let shouldContinue = false;\n do {\n const {\n consentPartitions: { nodes },\n } = await makeGraphQLRequest<{\n /** Consent experience */\n consentPartitions: {\n /** List */\n nodes: TranscendPartition[];\n };\n }>(client, CONSENT_PARTITIONS, {\n first: PAGE_SIZE,\n offset,\n });\n partitions.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return partitions.sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/**\n * Sync the consent manager\n *\n * @param client - GraphQL client\n * @param partitionInputs - The partition input\n *@returns true on success\n */\nexport async function syncPartitions(\n client: GraphQLClient,\n partitionInputs: PartitionInput[],\n): Promise<boolean> {\n // Grab the bundleId associated with this API key\n const airgapBundleId = await fetchConsentManagerId(client);\n let encounteredError = false;\n const partitions = await fetchPartitions(client);\n const newPartitionNames = difference(\n partitionInputs.map(({ name }) => name),\n partitions.map(({ name }) => name),\n );\n await mapSeries(newPartitionNames, async (name) => {\n try {\n await makeGraphQLRequest(client, CREATE_CONSENT_PARTITION, {\n input: {\n id: airgapBundleId,\n name,\n },\n });\n logger.info(\n colors.green(`Successfully created consent partition: ${name}!`),\n );\n } catch (err) {\n logger.error(\n colors.red(\n `Failed to create consent partition: ${name}! - ${err.message}`,\n ),\n );\n encounteredError = true;\n }\n });\n return !encounteredError;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { SILO_DISCOVERY_RESULTS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport type {\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\n\nexport interface SiloDiscoveryResult {\n /** Title of silo discovery result */\n title?: string;\n /** Resource ID of silo discovery result */\n resourceId: string;\n /** Suggested catalog */\n suggestedCatalog: {\n /** Title for the suggested catalog */\n title: string;\n };\n /** The likelihood that data is sensitive for this results */\n containsSensitiveData: string;\n /** The status of silo discovery triage */\n status: string;\n /** Hosting country of data silo discovery result */\n country?: IsoCountryCode;\n /** Hosting subdivision data silo discovery result */\n countrySubDivision?: IsoCountrySubdivisionCode;\n /** Plaintext context data silo discovery result */\n plaintextContext: string;\n /** The plugin that found this result */\n plugin: {\n /** The data silo the plugin belongs to */\n dataSilo: {\n /** The internal display title */\n title: string;\n };\n };\n}\n\nconst PAGE_SIZE = 30;\n\n/**\n * Fetch all silo discovery results in the organization\n *\n * @param client - GraphQL client\n * @returns All silo discovery results in the organization\n */\nexport async function fetchAllSiloDiscoveryResults(\n client: GraphQLClient,\n): Promise<SiloDiscoveryResult[]> {\n const siloDiscoveryResults: SiloDiscoveryResult[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n siloDiscoveryResults: { nodes },\n } = await makeGraphQLRequest<{\n /** Discovery results */\n siloDiscoveryResults: {\n /** Nodes */\n nodes: SiloDiscoveryResult[];\n };\n }>(client, SILO_DISCOVERY_RESULTS, {\n first: PAGE_SIZE,\n offset,\n input: {},\n filterBy: {},\n });\n\n const titledNodes = nodes.map((node) =>\n node.title === null && node.suggestedCatalog?.title\n ? { ...node, title: node.suggestedCatalog.title }\n : node,\n );\n\n siloDiscoveryResults.push(...titledNodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return siloDiscoveryResults;\n}\n","/* eslint-disable max-lines */\nimport {\n TranscendInput,\n ApiKeyInput,\n DataSiloInput,\n AttributeInput,\n ActionInput,\n IdentifierInput,\n BusinessEntityInput,\n EnricherInput,\n PromptGroupInput,\n DataFlowInput,\n PromptPartialInput,\n DataSubjectInput,\n CookieInput,\n PromptInput,\n DatapointInput,\n FieldInput,\n ProcessingPurposeInput,\n ProcessingActivityInput,\n DataCategoryInput,\n VendorInput,\n AgentFileInput,\n AgentFunctionInput,\n AgentInput,\n PolicyInput,\n IntlMessageInput,\n ActionItemInput,\n TeamInput,\n ActionItemCollectionInput,\n AssessmentInput,\n AssessmentTemplateInput,\n AssessmentSectionInput,\n AssessmentSectionQuestionInput,\n RiskLogicInput,\n ConsentPurpose,\n type SiloDiscoveryResultInput,\n} from '../../codecs';\nimport {\n RequestAction,\n ConsentTrackerStatus,\n ActionItemCode,\n RetentionType,\n} from '@transcend-io/privacy-types';\nimport { GraphQLClient } from 'graphql-request';\nimport { flatten, keyBy, mapValues } from 'lodash-es';\nimport { fetchEnrichedDataSilos } from './syncDataSilos';\nimport {\n convertToDataSubjectAllowlist,\n fetchAllDataSubjects,\n} from './fetchDataSubjects';\nimport { fetchApiKeys } from './fetchApiKeys';\nimport {\n fetchConsentManager,\n fetchConsentManagerExperiences,\n fetchConsentManagerTheme,\n} from './fetchConsentManagerId';\nimport { fetchAllEnrichers } from './syncEnrichers';\nimport { fetchAllDataFlows } from './fetchAllDataFlows';\nimport { fetchAllBusinessEntities } from './fetchAllBusinessEntities';\nimport { fetchAllProcessingActivities } from './fetchAllProcessingActivities';\nimport { fetchAllActions } from './fetchAllActions';\nimport { fetchAllAgents } from './fetchAllAgents';\nimport { fetchAllAgentFunctions } from './fetchAllAgentFunctions';\nimport { fetchAllAgentFiles } from './fetchAllAgentFiles';\nimport { fetchAllVendors } from './fetchAllVendors';\nimport { fetchAllDataCategories } from './fetchAllDataCategories';\nimport { fetchAllProcessingPurposes } from './fetchAllProcessingPurposes';\nimport { fetchAllIdentifiers } from './fetchIdentifiers';\nimport { fetchAllPrompts } from './fetchPrompts';\nimport { fetchAllPromptPartials } from './fetchPromptPartials';\nimport { fetchAllPolicies } from './fetchAllPolicies';\nimport { fetchAllPrivacyCenters } from './fetchAllPrivacyCenters';\nimport { fetchAllMessages } from './fetchAllMessages';\nimport { fetchAllPromptGroups } from './fetchPromptGroups';\nimport { fetchAllCookies } from './fetchAllCookies';\nimport { fetchAllTemplates } from './syncTemplates';\nimport { fetchAllAttributes } from './fetchAllAttributes';\nimport { formatAttributeValues } from './formatAttributeValues';\nimport { formatRegions } from './formatRegions';\nimport { logger } from '../../logger';\nimport colors from 'colors';\nimport { TranscendPullResource } from '../../enums';\nimport { fetchAllActionItems } from './fetchAllActionItems';\nimport { fetchAllTeams } from './fetchAllTeams';\nimport { fetchAllActionItemCollections } from './fetchAllActionItemCollections';\nimport { LocaleValue } from '@transcend-io/internationalization';\nimport { fetchPartitions } from './syncPartitions';\nimport { fetchAllAssessments } from './fetchAllAssessments';\nimport { fetchAllAssessmentTemplates } from './fetchAllAssessmentTemplates';\nimport {\n parseAssessmentDisplayLogic,\n type AssessmentRule,\n} from './parseAssessmentDisplayLogic';\nimport { parseAssessmentRiskLogic } from './parseAssessmentRiskLogic';\nimport { fetchAllPurposesAndPreferences } from './fetchAllPurposesAndPreferences';\nimport { fetchAllSiloDiscoveryResults } from './fetchAllSiloDiscoveryResults';\n\nexport const DEFAULT_TRANSCEND_PULL_RESOURCES = [\n TranscendPullResource.DataSilos,\n TranscendPullResource.Enrichers,\n TranscendPullResource.Templates,\n TranscendPullResource.ApiKeys,\n];\n\nexport interface TranscendPullConfigurationInput {\n /** Page size */\n pageSize: number;\n /** Enable debug logs */\n debug: boolean;\n /** The data silo IDs to sync. If empty list, pull all. */\n dataSiloIds: string[];\n /** Resources to pull in */\n resources?: TranscendPullResource[];\n /** The data silo types to sync.If empty list, pull all. */\n integrationNames: string[];\n /** The tracker statuses to pull */\n trackerStatuses?: ConsentTrackerStatus[];\n /** Skip fetching of datapoints */\n skipDatapoints?: boolean;\n /** Skip fetching of subdatapoints */\n skipSubDatapoints?: boolean;\n /** When true, metadata around guessed data categories should be included */\n includeGuessedCategories?: boolean;\n}\n\n/**\n * Pull a yaml configuration from Transcend\n *\n * @param client - GraphQL client\n * @param dataSiloIds - The data silos to sync. If empty list, pull all.\n * @returns The configuration\n */\nexport async function pullTranscendConfiguration(\n client: GraphQLClient,\n {\n dataSiloIds,\n integrationNames,\n debug,\n resources = DEFAULT_TRANSCEND_PULL_RESOURCES,\n pageSize,\n skipDatapoints,\n includeGuessedCategories,\n skipSubDatapoints,\n trackerStatuses = Object.values(ConsentTrackerStatus),\n }: TranscendPullConfigurationInput,\n): Promise<TranscendInput> {\n if (dataSiloIds.length > 0 && integrationNames.length > 0) {\n throw new Error(\n 'Only 1 of integrationNames OR dataSiloIds can be provided',\n );\n }\n\n logger.info(colors.magenta(`Fetching data with page size ${pageSize}...`));\n\n // Fetch all data, but only conditional fetch data that is requested\n const [\n dataSubjects,\n apiKeyTitleMap,\n dataSilos,\n enrichers,\n dataFlows,\n cookies,\n attributes,\n templates,\n identifiers,\n actions,\n businessEntities,\n processingActivities,\n consentManager,\n consentManagerExperiences,\n prompts,\n promptPartials,\n promptGroups,\n agents,\n agentFunctions,\n agentFiles,\n vendors,\n dataCategories,\n processingPurposes,\n actionItems,\n actionItemCollections,\n teams,\n policies,\n privacyCenters,\n messages,\n partitions,\n assessments,\n assessmentTemplates,\n purposes,\n siloDiscoveryResults,\n ] = await Promise.all([\n // Grab all data subjects in the organization\n resources.includes(TranscendPullResource.DataSilos) ||\n resources.includes(TranscendPullResource.DataSubjects)\n ? fetchAllDataSubjects(client)\n : [],\n // Grab API keys\n resources.includes(TranscendPullResource.ApiKeys)\n ? fetchApiKeys({}, client, true)\n : [],\n // Fetch the data silos\n resources.includes(TranscendPullResource.DataSilos)\n ? fetchEnrichedDataSilos(client, {\n ids: dataSiloIds,\n integrationNames,\n pageSize,\n debug,\n includeGuessedCategories,\n skipDatapoints,\n skipSubDatapoints,\n })\n : [],\n // Fetch enrichers\n resources.includes(TranscendPullResource.Enrichers)\n ? fetchAllEnrichers(client)\n : [],\n // Fetch data flows\n resources.includes(TranscendPullResource.DataFlows)\n ? [\n ...(trackerStatuses.includes(ConsentTrackerStatus.Live)\n ? await fetchAllDataFlows(client, ConsentTrackerStatus.Live)\n : []),\n ...(trackerStatuses.includes(ConsentTrackerStatus.NeedsReview)\n ? await fetchAllDataFlows(client, ConsentTrackerStatus.NeedsReview)\n : []),\n ]\n : [],\n // Fetch data flows\n resources.includes(TranscendPullResource.Cookies)\n ? [\n ...(trackerStatuses.includes(ConsentTrackerStatus.Live)\n ? await fetchAllCookies(client, ConsentTrackerStatus.Live)\n : []),\n ...(trackerStatuses.includes(ConsentTrackerStatus.NeedsReview)\n ? await fetchAllCookies(client, ConsentTrackerStatus.NeedsReview)\n : []),\n ]\n : [],\n // Fetch attributes\n resources.includes(TranscendPullResource.Attributes)\n ? fetchAllAttributes(client)\n : [],\n // Fetch email templates\n resources.includes(TranscendPullResource.Templates)\n ? fetchAllTemplates(client)\n : [],\n // Fetch identifiers\n resources.includes(TranscendPullResource.Identifiers)\n ? fetchAllIdentifiers(client)\n : [],\n // Fetch actions\n resources.includes(TranscendPullResource.Actions)\n ? fetchAllActions(client)\n : [],\n // Fetch business entities\n resources.includes(TranscendPullResource.BusinessEntities)\n ? fetchAllBusinessEntities(client)\n : [],\n // Fetch processing activities\n resources.includes(TranscendPullResource.ProcessingActivities)\n ? fetchAllProcessingActivities(client)\n : [],\n // Fetch consent manager\n resources.includes(TranscendPullResource.ConsentManager)\n ? fetchConsentManager(client)\n : undefined,\n // Fetch consent manager experiences\n resources.includes(TranscendPullResource.ConsentManager)\n ? fetchConsentManagerExperiences(client)\n : [],\n // Fetch prompts\n resources.includes(TranscendPullResource.Prompts)\n ? fetchAllPrompts(client)\n : [],\n // Fetch promptPartials\n resources.includes(TranscendPullResource.PromptPartials)\n ? fetchAllPromptPartials(client)\n : [],\n // Fetch promptGroups\n resources.includes(TranscendPullResource.PromptGroups)\n ? fetchAllPromptGroups(client)\n : [],\n // Fetch agents\n resources.includes(TranscendPullResource.Agents)\n ? fetchAllAgents(client)\n : [],\n // Fetch agentFunctions\n resources.includes(TranscendPullResource.AgentFunctions)\n ? fetchAllAgentFunctions(client)\n : [],\n // Fetch agentFiles\n resources.includes(TranscendPullResource.AgentFiles)\n ? fetchAllAgentFiles(client)\n : [],\n // Fetch vendors\n resources.includes(TranscendPullResource.Vendors)\n ? fetchAllVendors(client)\n : [],\n // Fetch dataCategories\n resources.includes(TranscendPullResource.DataCategories)\n ? fetchAllDataCategories(client)\n : [],\n // Fetch dataCategories\n resources.includes(TranscendPullResource.ProcessingPurposes)\n ? fetchAllProcessingPurposes(client)\n : [],\n // Fetch actionItems\n resources.includes(TranscendPullResource.ActionItems)\n ? fetchAllActionItems(client, { type: [ActionItemCode.Onboarding] })\n : [],\n // Fetch actionItemCollections\n resources.includes(TranscendPullResource.ActionItemCollections)\n ? fetchAllActionItemCollections(client)\n : [],\n // Fetch teams\n resources.includes(TranscendPullResource.Teams)\n ? fetchAllTeams(client)\n : [],\n // Fetch policies\n resources.includes(TranscendPullResource.Policies)\n ? fetchAllPolicies(client)\n : [],\n // Fetch privacy centers\n resources.includes(TranscendPullResource.PrivacyCenters)\n ? fetchAllPrivacyCenters(client)\n : [],\n // Fetch messages\n resources.includes(TranscendPullResource.Messages)\n ? fetchAllMessages(client)\n : [],\n // Fetch partitions\n resources.includes(TranscendPullResource.Partitions)\n ? fetchPartitions(client)\n : [],\n // Fetch assessments\n resources.includes(TranscendPullResource.Assessments)\n ? fetchAllAssessments(client)\n : [],\n // Fetch assessmentTemplates\n resources.includes(TranscendPullResource.AssessmentTemplates)\n ? fetchAllAssessmentTemplates(client)\n : [],\n // Fetch purpose and preferences\n resources.includes(TranscendPullResource.Purposes)\n ? fetchAllPurposesAndPreferences(client)\n : [],\n // Fetch silo discovery results\n resources.includes(TranscendPullResource.SystemDiscovery)\n ? fetchAllSiloDiscoveryResults(client)\n : [],\n ]);\n\n const consentManagerTheme =\n resources.includes(TranscendPullResource.ConsentManager) && consentManager\n ? await fetchConsentManagerTheme(client, consentManager.id)\n : undefined;\n\n const result: TranscendInput = {};\n\n // Save API keys\n const apiKeyTitles = flatten(\n dataSilos.map(([{ apiKeys }]) => apiKeys.map(({ title }) => title)),\n );\n const relevantApiKeys = Object.values(apiKeyTitleMap).filter(({ title }) =>\n resources.includes(TranscendPullResource.ApiKeys)\n ? true\n : apiKeyTitles.includes(title),\n );\n if (\n relevantApiKeys.length > 0 &&\n resources.includes(TranscendPullResource.ApiKeys)\n ) {\n result['api-keys'] = relevantApiKeys.map(\n ({ title }): ApiKeyInput => ({\n title,\n }),\n );\n }\n\n // Save Partitions\n if (\n partitions.length > 0 &&\n resources.includes(TranscendPullResource.Partitions)\n ) {\n result.partitions = partitions.map(({ name, partition }) => ({\n name,\n partition,\n }));\n }\n\n // Save Consent Manager\n if (\n consentManager &&\n resources.includes(TranscendPullResource.ConsentManager)\n ) {\n result['consent-manager'] = {\n bundleUrls: {\n TEST: consentManager.testBundleURL,\n PRODUCTION: consentManager.bundleURL,\n },\n domains: consentManager.configuration.domains || undefined,\n partition: consentManager.configuration.partition || undefined,\n consentPrecedence:\n consentManager.configuration.consentPrecedence || undefined,\n unknownRequestPolicy:\n consentManager.configuration.unknownRequestPolicy || undefined,\n unknownCookiePolicy:\n consentManager.configuration.unknownCookiePolicy || undefined,\n syncEndpoint: consentManager.configuration.syncEndpoint || undefined,\n telemetryPartitioning:\n consentManager.configuration.telemetryPartitioning || undefined,\n signedIabAgreement:\n consentManager.configuration.signedIabAgreement || undefined,\n // TODO: https://transcend.height.app/T-23919 - reconsider simpler yml shape\n syncGroups: consentManager.configuration.syncGroups || undefined,\n theme: !consentManagerTheme\n ? undefined\n : {\n primaryColor: consentManagerTheme.primaryColor || undefined,\n fontColor: consentManagerTheme.fontColor || undefined,\n privacyPolicy: consentManagerTheme.privacyPolicy || undefined,\n prompt: consentManagerTheme.prompt,\n },\n experiences: consentManagerExperiences.map((experience) => ({\n name: experience.name,\n displayName: experience.displayName || undefined,\n regions: experience.regions.map((region) => ({\n countrySubDivision: region.countrySubDivision || undefined,\n country: region.country || undefined,\n })),\n onConsentExpiry: experience.onConsentExpiry,\n consentExpiry: experience.consentExpiry,\n operator: experience.operator,\n displayPriority: experience.displayPriority,\n viewState: experience.viewState,\n purposes: experience.purposes.map((purpose) => ({\n trackingType: purpose.trackingType,\n })),\n optedOutPurposes: experience.optedOutPurposes.map((purpose) => ({\n trackingType: purpose.trackingType,\n })),\n browserLanguages: experience.browserLanguages,\n browserTimeZones: experience.browserTimeZones,\n })),\n };\n }\n\n // Save assessments\n if (\n assessments.length > 0 &&\n resources.includes(TranscendPullResource.Assessments)\n ) {\n result.assessments = assessments.map(\n ({\n title,\n assessmentGroup,\n sections,\n creator,\n description,\n status,\n assignees,\n externalAssignees,\n reviewers,\n isLocked,\n isArchived,\n isExternallyCreated,\n dueDate,\n createdAt,\n assignedAt,\n submittedAt,\n approvedAt,\n rejectedAt,\n titleIsInternal,\n retentionSchedule,\n attributeValues,\n resources,\n syncedRows,\n }): AssessmentInput => ({\n title,\n group: assessmentGroup.title,\n sections: sections.map(\n ({\n title,\n status,\n questions,\n assignees,\n isReviewed,\n externalAssignees,\n }): AssessmentSectionInput => ({\n title,\n status,\n questions: questions.map(\n ({\n title,\n type,\n subType,\n placeholder,\n description,\n isRequired,\n referenceId,\n displayLogic,\n riskLogic,\n riskCategories,\n riskFramework,\n answerOptions,\n selectedAnswers,\n allowedMimeTypes,\n allowSelectOther,\n syncModel,\n syncColumn,\n attributeKey,\n requireRiskEvaluation,\n requireRiskMatrixEvaluation,\n }): AssessmentSectionQuestionInput => {\n const displayLogicParsed = displayLogic\n ? parseAssessmentDisplayLogic(displayLogic)\n : undefined;\n return {\n title,\n type,\n 'sub-type': subType,\n placeholder,\n description,\n 'is-required': isRequired,\n 'reference-id': referenceId,\n 'display-logic':\n displayLogicParsed &&\n Object.keys(displayLogicParsed).length > 0\n ? {\n action: displayLogicParsed.action!,\n rule: displayLogicParsed.rule\n ? {\n 'depends-on-question-reference-id':\n displayLogicParsed.rule\n .dependsOnQuestionReferenceId,\n 'comparison-operator':\n displayLogicParsed.rule.comparisonOperator,\n 'comparison-operands':\n // Safely access property with a check\n 'comparisonOperands' in\n displayLogicParsed.rule\n ? displayLogicParsed.rule.comparisonOperands\n : undefined,\n }\n : undefined,\n 'nested-rule': displayLogicParsed.nestedRule\n ? {\n 'logic-operator':\n displayLogicParsed.nestedRule.logicOperator,\n rules: (\n displayLogicParsed.nestedRule.rules || []\n ).map((rule: AssessmentRule) => ({\n 'depends-on-question-reference-id':\n rule.dependsOnQuestionReferenceId,\n 'comparison-operator':\n rule.comparisonOperator,\n 'comparison-operands':\n // Safely access property on the nested rule\n 'comparisonOperands' in rule\n ? rule.comparisonOperands\n : undefined,\n })),\n }\n : undefined,\n }\n : undefined,\n 'risk-logic': riskLogic.map((logic): RiskLogicInput => {\n const parsed = parseAssessmentRiskLogic(logic);\n return {\n 'risk-level': parsed.riskAssignment?.riskLevelId,\n 'comparison-operands': parsed.comparisonOperands,\n 'comparison-operator': parsed.comparisonOperator,\n };\n }),\n 'risk-categories': riskCategories.map(({ title }) => title),\n 'risk-framework': riskFramework?.title,\n 'answer-options': answerOptions.map(({ value }) => ({\n value,\n })),\n 'selected-answers': selectedAnswers.map(({ value }) => value),\n 'allowed-mime-types': allowedMimeTypes,\n 'allow-select-other': allowSelectOther,\n 'sync-model': syncModel || undefined,\n 'sync-column': syncColumn || undefined,\n 'attribute-key': attributeKey?.name,\n 'require-risk-evaluation': requireRiskEvaluation,\n 'require-risk-matrix-evaluation': requireRiskMatrixEvaluation,\n };\n },\n ),\n assignees: assignees.map(({ email }) => email),\n 'external-assignees': externalAssignees.map(({ email }) => email),\n 'is-reviewed': isReviewed,\n }),\n ),\n creator: creator?.email,\n description,\n status,\n assignees: assignees.map(({ email }) => email),\n 'external-assignees': externalAssignees.map(({ email }) => email),\n reviewers: reviewers.map(({ email }) => email),\n locked: isLocked,\n archived: isArchived,\n external: isExternallyCreated,\n 'title-is-internal': titleIsInternal,\n 'due-date': dueDate || undefined,\n 'created-at': createdAt || undefined,\n 'assigned-at': assignedAt || undefined,\n 'submitted-at': submittedAt || undefined,\n 'approved-at': approvedAt || undefined,\n 'rejected-at': rejectedAt || undefined,\n 'retention-schedule': retentionSchedule\n ? {\n type: retentionSchedule.type,\n 'duration-days': retentionSchedule.durationDays,\n operand: retentionSchedule.operation,\n }\n : undefined,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n resources: resources.map(\n ({ resourceType, title, name, category, type, purpose }) => ({\n type: resourceType,\n title: category\n ? `${category} - ${name}`\n : purpose\n ? `${purpose} - ${name}`\n : title || name || type || '',\n }),\n ),\n rows: syncedRows.map(\n ({ resourceType, title, name, category, type, purpose }) => ({\n type: resourceType,\n title: category\n ? `${category} - ${name}`\n : purpose\n ? `${purpose} - ${name}`\n : title || name || type || '',\n }),\n ),\n }),\n );\n }\n\n // Save assessmentTemplates\n if (\n assessmentTemplates.length > 0 &&\n resources.includes(TranscendPullResource.AssessmentTemplates)\n ) {\n result['assessment-templates'] = assessmentTemplates.map(\n ({\n title,\n description,\n sections,\n status,\n source,\n creator,\n isLocked,\n isArchived,\n createdAt,\n retentionSchedule,\n }): AssessmentTemplateInput => ({\n title,\n description,\n sections: sections.map(\n ({ title, questions }): AssessmentSectionInput => ({\n title,\n questions: questions.map(\n ({\n title,\n type,\n subType,\n placeholder,\n description,\n isRequired,\n referenceId,\n displayLogic,\n riskLogic,\n riskCategories,\n riskFramework,\n answerOptions,\n allowedMimeTypes,\n allowSelectOther,\n syncModel,\n syncColumn,\n attributeKey,\n requireRiskEvaluation,\n requireRiskMatrixEvaluation,\n }): AssessmentSectionQuestionInput => {\n const displayLogicParsed = displayLogic\n ? parseAssessmentDisplayLogic(displayLogic)\n : undefined;\n return {\n title,\n type,\n 'sub-type': subType,\n placeholder,\n description,\n 'is-required': isRequired,\n 'reference-id': referenceId,\n 'display-logic':\n displayLogicParsed &&\n Object.keys(displayLogicParsed).length > 0\n ? {\n action: displayLogicParsed.action!,\n rule: displayLogicParsed.rule\n ? {\n 'depends-on-question-reference-id':\n displayLogicParsed.rule\n .dependsOnQuestionReferenceId,\n 'comparison-operator':\n displayLogicParsed.rule.comparisonOperator,\n 'comparison-operands':\n // Safely access property with a check\n 'comparisonOperands' in\n displayLogicParsed.rule\n ? displayLogicParsed.rule.comparisonOperands\n : undefined,\n }\n : undefined,\n 'nested-rule': displayLogicParsed.nestedRule\n ? {\n 'logic-operator':\n displayLogicParsed.nestedRule.logicOperator,\n rules: (\n displayLogicParsed.nestedRule.rules || []\n ).map((rule: AssessmentRule) => ({\n 'depends-on-question-reference-id':\n rule.dependsOnQuestionReferenceId,\n 'comparison-operator':\n rule.comparisonOperator,\n 'comparison-operands':\n // Safely access property on the nested rule\n 'comparisonOperands' in rule\n ? rule.comparisonOperands\n : undefined,\n })),\n }\n : undefined,\n }\n : undefined,\n 'risk-logic': riskLogic.map((logic): RiskLogicInput => {\n const parsed = parseAssessmentRiskLogic(logic);\n return {\n 'risk-level': parsed.riskAssignment?.riskLevelId,\n 'risk-matrix-row': parsed.riskAssignment?.riskMatrixRowId,\n 'risk-matrix-column':\n parsed.riskAssignment?.riskMatrixColumnId,\n 'comparison-operands': parsed.comparisonOperands,\n 'comparison-operator': parsed.comparisonOperator,\n };\n }),\n 'risk-categories': riskCategories.map(({ title }) => title),\n 'risk-framework': riskFramework?.title,\n 'answer-options': answerOptions.map(({ value }) => ({\n value,\n })),\n 'allowed-mime-types': allowedMimeTypes,\n 'allow-select-other': allowSelectOther,\n 'sync-model': syncModel || undefined,\n 'sync-column': syncColumn || undefined,\n 'attribute-key': attributeKey?.name,\n 'require-risk-evaluation': requireRiskEvaluation,\n 'require-risk-matrix-evaluation': requireRiskMatrixEvaluation,\n };\n },\n ),\n }),\n ),\n status,\n source,\n creator: creator?.email,\n locked: isLocked,\n archived: isArchived,\n 'created-at': createdAt || undefined,\n 'retention-schedule': retentionSchedule\n ? {\n type: retentionSchedule.type,\n 'duration-days': retentionSchedule.durationDays,\n operand: retentionSchedule.operation,\n }\n : undefined,\n }),\n );\n }\n\n // Save Silo Discovery Results\n if (\n siloDiscoveryResults.length > 0 &&\n resources.includes(TranscendPullResource.SystemDiscovery)\n ) {\n result['system-discovery'] = siloDiscoveryResults.map(\n ({\n title,\n resourceId,\n suggestedCatalog: { title: suggestedCatalogTitle },\n plugin: {\n dataSilo: { title: dataSiloTitle },\n },\n country,\n countrySubDivision,\n plaintextContext,\n containsSensitiveData,\n status,\n }): SiloDiscoveryResultInput => ({\n title,\n resourceId,\n suggestedCatalog: suggestedCatalogTitle,\n plugin: dataSiloTitle,\n country: country || undefined,\n countrySubDivision: countrySubDivision || undefined,\n plaintextContext,\n containsSensitiveData,\n status,\n }),\n );\n }\n\n // Save prompts\n if (prompts.length > 0 && resources.includes(TranscendPullResource.Prompts)) {\n result.prompts = prompts.map(\n ({ title, content }): PromptInput => ({\n title,\n content,\n }),\n );\n }\n\n // Save promptPartials\n if (\n promptPartials.length > 0 &&\n resources.includes(TranscendPullResource.PromptPartials)\n ) {\n result['prompt-partials'] = promptPartials.map(\n ({ title, content }): PromptPartialInput => ({\n title,\n content,\n }),\n );\n }\n\n // Save promptGroups\n if (\n promptGroups.length > 0 &&\n resources.includes(TranscendPullResource.PromptGroups)\n ) {\n result['prompt-groups'] = promptGroups.map(\n ({ title, description, prompts }): PromptGroupInput => ({\n title,\n description,\n prompts: prompts.map(({ title }) => title),\n }),\n );\n }\n\n // Save teams\n if (teams.length > 0 && resources.includes(TranscendPullResource.Teams)) {\n result.teams = teams.map(\n ({\n name,\n description,\n ssoDepartment,\n ssoGroup,\n ssoTitle,\n users,\n scopes,\n }): TeamInput => ({\n name,\n description,\n 'sso-department': ssoDepartment || undefined,\n 'sso-group': ssoGroup || undefined,\n 'sso-title': ssoTitle || undefined,\n users: users.map(({ email }) => email),\n scopes: scopes.map(({ name }) => name),\n }),\n );\n }\n\n // Save Data Subjects\n if (\n dataSubjects.length > 0 &&\n resources.includes(TranscendPullResource.DataSubjects)\n ) {\n result['data-subjects'] = dataSubjects.map(\n ({\n type,\n title,\n active,\n adminDashboardDefaultSilentMode,\n actions,\n }): DataSubjectInput => ({\n type,\n title: title?.defaultMessage,\n active,\n adminDashboardDefaultSilentMode,\n actions: actions.map(({ type }) => type),\n }),\n );\n }\n\n // Save privacy policies\n if (policies.length > 0) {\n result.policies = policies.map(\n ({ title, versions, disabledLocales }): PolicyInput => ({\n title: title?.defaultMessage,\n content: versions?.[0]?.content?.defaultMessage,\n disabledLocales,\n }),\n );\n }\n\n // Save messages\n if (messages.length > 0) {\n result.messages = messages.map(\n ({\n id,\n defaultMessage,\n targetReactIntlId,\n description,\n translations,\n }): IntlMessageInput => ({\n id,\n defaultMessage,\n description,\n targetReactIntlId: targetReactIntlId || undefined,\n translations: translations.reduce(\n (acc, { locale, value }) => Object.assign(acc, { [locale]: value }),\n {} as Record<LocaleValue, string>,\n ),\n }),\n );\n }\n\n // Save privacy center\n if (privacyCenters.length > 0) {\n const privacyCenter = privacyCenters[0];\n result['privacy-center'] = {\n isDisabled: privacyCenter.isDisabled,\n showPrivacyRequestButton: privacyCenter.showPrivacyRequestButton,\n showPolicies: privacyCenter.showPolicies,\n showTrackingTechnologies: privacyCenter.showTrackingTechnologies,\n showCookies: privacyCenter.showCookies,\n showDataFlows: privacyCenter.showDataFlows,\n showConsentManager: privacyCenter.showConsentManager,\n showManageYourPrivacy: privacyCenter.showManageYourPrivacy,\n showMarketingPreferences: privacyCenter.showMarketingPreferences,\n locales: privacyCenter.locales,\n defaultLocale: privacyCenter.defaultLocale,\n preferBrowserDefaultLocale: privacyCenter.preferBrowserDefaultLocale,\n supportEmail: privacyCenter.supportEmail || undefined,\n replyToEmail: privacyCenter.replyToEmail || undefined,\n useNoReplyEmailAddress: privacyCenter.useNoReplyEmailAddress,\n useCustomEmailDomain: privacyCenter.useCustomEmailDomain,\n transformAccessReportJsonToCsv:\n privacyCenter.transformAccessReportJsonToCsv,\n theme: privacyCenter.theme,\n };\n }\n\n // Save business entities\n if (\n businessEntities.length > 0 &&\n resources.includes(TranscendPullResource.BusinessEntities)\n ) {\n result['business-entities'] = businessEntities.map(\n ({\n title,\n description,\n address,\n headquarterCountry,\n headquarterSubDivision,\n dataProtectionOfficerName,\n dataProtectionOfficerEmail,\n attributeValues,\n }): BusinessEntityInput => ({\n title,\n description: description || undefined,\n address: address || undefined,\n headquarterCountry: headquarterCountry || undefined,\n headquarterSubDivision: headquarterSubDivision || undefined,\n dataProtectionOfficerName: dataProtectionOfficerName || undefined,\n dataProtectionOfficerEmail: dataProtectionOfficerEmail || undefined,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save processing activities\n if (\n processingActivities.length > 0 &&\n resources.includes(TranscendPullResource.ProcessingActivities)\n ) {\n result['processing-activities'] = processingActivities.map(\n ({\n title,\n description,\n securityMeasureDetails,\n controllerships,\n storageRegions,\n transferRegions,\n retentionType,\n retentionPeriod,\n dataProtectionImpactAssessmentLink,\n dataProtectionImpactAssessmentStatus,\n attributeValues,\n dataSilos,\n dataSubjects,\n teams,\n owners,\n processingPurposeSubCategories,\n dataSubCategories,\n saaSCategories,\n }): ProcessingActivityInput => ({\n title,\n description,\n securityMeasureDetails: securityMeasureDetails ?? undefined,\n controllerships:\n controllerships.length > 0 ? controllerships : undefined,\n storageRegions:\n storageRegions.length > 0 ? formatRegions(storageRegions) : undefined,\n transferRegions:\n transferRegions.length > 0\n ? formatRegions(transferRegions)\n : undefined,\n retentionType,\n retentionPeriod:\n retentionType === RetentionType.StatedPeriod\n ? retentionPeriod\n : undefined,\n dataProtectionImpactAssessmentLink:\n dataProtectionImpactAssessmentLink ?? undefined,\n dataProtectionImpactAssessmentStatus,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n dataSiloTitles:\n dataSilos.length > 0\n ? dataSilos.map(({ title }) => title)\n : undefined,\n dataSubjectTypes:\n dataSubjects.length > 0\n ? dataSubjects.map(({ type }) => type)\n : undefined,\n teamNames: teams.length > 0 ? teams.map(({ name }) => name) : undefined,\n ownerEmails:\n owners.length > 0 ? owners.map(({ email }) => email) : undefined,\n processingSubPurposes:\n processingPurposeSubCategories.length > 0\n ? processingPurposeSubCategories.map(({ name, purpose }) => ({\n purpose,\n ...(name ? { name } : {}),\n }))\n : undefined,\n dataSubCategories:\n dataSubCategories.length > 0\n ? dataSubCategories.map(({ name, category }) => ({\n category,\n ...(name ? { name } : {}),\n }))\n : undefined,\n saaSCategories:\n saaSCategories.length > 0\n ? saaSCategories.map(({ title }) => title)\n : undefined,\n }),\n );\n }\n\n // Save Actions\n if (actions.length > 0 && resources.includes(TranscendPullResource.Actions)) {\n result.actions = actions.map(\n ({\n type,\n skipSecondaryIfNoFiles,\n skipDownloadableStep,\n requiresReview,\n regionList,\n regionDetectionMethod,\n waitingPeriod,\n }): ActionInput => ({\n type,\n ...(type === RequestAction.Erasure\n ? {\n skipSecondaryIfNoFiles,\n skipDownloadableStep,\n }\n : {}),\n requiresReview,\n waitingPeriod,\n regionDetectionMethod,\n regionList: regionList.length > 0 ? regionList : undefined,\n }),\n );\n }\n\n // Save identifiers\n if (\n identifiers.length > 0 &&\n resources.includes(TranscendPullResource.Identifiers)\n ) {\n result.identifiers = identifiers.map(\n ({\n name,\n type,\n regex,\n selectOptions,\n privacyCenterVisibility,\n isRequiredInForm,\n placeholder,\n displayTitle,\n dataSubjects,\n displayDescription,\n displayOrder,\n isUniqueOnPreferenceStore,\n }): IdentifierInput => ({\n name,\n type,\n regex,\n selectOptions: selectOptions.length > 0 ? selectOptions : undefined,\n privacyCenterVisibility:\n privacyCenterVisibility.length > 0\n ? privacyCenterVisibility\n : undefined,\n isRequiredInForm,\n placeholder: placeholder || undefined,\n dataSubjects:\n dataSubjects.length > 0\n ? dataSubjects.map(({ type }) => type)\n : undefined,\n displayTitle: displayTitle?.defaultMessage,\n displayDescription: displayDescription?.defaultMessage,\n displayOrder,\n isUniqueOnPreferenceStore,\n }),\n );\n }\n\n // Save agents\n if (agents.length > 0 && resources.includes(TranscendPullResource.Agents)) {\n result.agents = agents.map(\n ({\n name,\n agentId,\n description,\n instructions,\n codeInterpreterEnabled,\n retrievalEnabled,\n prompt,\n largeLanguageModel,\n teams,\n owners,\n agentFunctions,\n agentFiles,\n }): AgentInput => ({\n name,\n agentId,\n description: description || undefined,\n instructions,\n codeInterpreterEnabled,\n retrievalEnabled,\n prompt: prompt?.title,\n 'large-language-model': {\n name: largeLanguageModel.name,\n client: largeLanguageModel.client,\n },\n teams:\n teams && teams.length > 0 ? teams.map(({ name }) => name) : undefined,\n owners:\n owners && owners.length > 0\n ? owners.map(({ email }) => email)\n : undefined,\n 'agent-functions':\n agentFunctions && agentFunctions.length > 0\n ? agentFunctions.map(({ name }) => name)\n : undefined,\n 'agent-files':\n agentFiles && agentFiles.length > 0\n ? agentFiles.map(({ name }) => name)\n : undefined,\n }),\n );\n }\n\n // Save action items\n if (\n actionItems.length > 0 &&\n resources.includes(TranscendPullResource.ActionItems)\n ) {\n result['action-items'] = actionItems.map(\n ({\n teams,\n users,\n customerExperienceActionItemIds: [customerExperienceActionItemId],\n dueDate,\n priority,\n resolved,\n collections,\n notes,\n link,\n title,\n type,\n attributeValues,\n }): ActionItemInput => ({\n teams: teams.map(({ name }) => name),\n users: users.map(({ email }) => email),\n dueDate: dueDate || undefined,\n title,\n notes,\n customerExperienceActionItemId,\n collections: collections.map(({ title }) => title),\n link,\n priority: priority || undefined,\n resolved,\n type,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save action item collections\n if (\n actionItemCollections.length > 0 &&\n resources.includes(TranscendPullResource.ActionItemCollections)\n ) {\n result['action-item-collections'] = actionItemCollections.map(\n ({\n title,\n description,\n hidden,\n productLine,\n }): ActionItemCollectionInput => ({\n title,\n description: description || undefined,\n hidden,\n productLine,\n }),\n );\n }\n\n // Save agent functions\n if (\n agentFunctions.length > 0 &&\n resources.includes(TranscendPullResource.AgentFunctions)\n ) {\n result['agent-functions'] = agentFunctions.map(\n ({ name, description, parameters }): AgentFunctionInput => ({\n name,\n description,\n parameters: JSON.stringify(parameters),\n }),\n );\n }\n\n // Save agent files\n if (\n agentFiles.length > 0 &&\n resources.includes(TranscendPullResource.AgentFiles)\n ) {\n result['agent-files'] = agentFiles.map(\n ({ name, description, fileId, size, purpose }): AgentFileInput => ({\n name,\n description,\n fileId,\n size,\n purpose,\n }),\n );\n }\n\n // Save vendors\n if (vendors.length > 0 && resources.includes(TranscendPullResource.Vendors)) {\n result.vendors = vendors.map(\n ({\n title,\n description,\n dataProcessingAgreementLink,\n contactName,\n contactPhone,\n address,\n headquarterCountry,\n headquarterSubDivision,\n websiteUrl,\n businessEntity,\n teams,\n owners,\n attributeValues,\n }): VendorInput => ({\n title,\n description: description || undefined,\n dataProcessingAgreementLink: dataProcessingAgreementLink || undefined,\n contactName: contactName || undefined,\n contactPhone: contactPhone || undefined,\n address: address || undefined,\n headquarterCountry: headquarterCountry || undefined,\n headquarterSubDivision: headquarterSubDivision || undefined,\n websiteUrl: websiteUrl || undefined,\n businessEntity: businessEntity?.title,\n teams:\n teams && teams.length > 0 ? teams.map(({ name }) => name) : undefined,\n owners:\n owners && owners.length > 0\n ? owners.map(({ email }) => email)\n : undefined,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save data categories\n if (\n dataCategories.length > 0 &&\n resources.includes(TranscendPullResource.DataCategories)\n ) {\n result['data-categories'] = dataCategories.map(\n ({\n name,\n category,\n description,\n regex,\n owners,\n teams,\n attributeValues,\n }): DataCategoryInput => ({\n name,\n category,\n description: description || undefined,\n regex: regex || undefined,\n owners:\n owners && owners.length > 0\n ? owners.map(({ email }) => email)\n : undefined,\n teams:\n teams && teams.length > 0 ? teams.map(({ name }) => name) : undefined,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save processing purposes\n if (\n processingPurposes.length > 0 &&\n resources.includes(TranscendPullResource.ProcessingPurposes)\n ) {\n result['processing-purposes'] = processingPurposes.map(\n ({\n name,\n purpose,\n description,\n owners,\n teams,\n attributeValues,\n }): ProcessingPurposeInput => ({\n name,\n purpose,\n description: description || undefined,\n owners:\n owners && owners.length > 0\n ? owners.map(({ email }) => email)\n : undefined,\n teams:\n teams && teams.length > 0 ? teams.map(({ name }) => name) : undefined,\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save data flows\n if (\n dataFlows.length > 0 &&\n resources.includes(TranscendPullResource.DataFlows)\n ) {\n result['data-flows'] = dataFlows.map(\n ({\n value,\n type,\n description,\n trackingType,\n service,\n status,\n owners,\n teams,\n attributeValues,\n }): DataFlowInput => ({\n value,\n type,\n description: description || undefined,\n trackingPurposes: trackingType,\n status,\n service: service?.integrationName,\n owners: owners.map(({ email }) => email),\n teams: teams.map(({ name }) => name),\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save cookies\n if (cookies.length > 0 && resources.includes(TranscendPullResource.Cookies)) {\n result.cookies = cookies.map(\n ({\n name,\n isRegex,\n description,\n trackingPurposes,\n service,\n status,\n owners,\n teams,\n attributeValues,\n }): CookieInput => ({\n name,\n isRegex,\n description: description || undefined,\n trackingPurposes,\n status,\n service: service?.integrationName,\n owners: owners.map(({ email }) => email),\n teams: teams.map(({ name }) => name),\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n }),\n );\n }\n\n // Save attributes\n if (\n attributes.length > 0 &&\n resources.includes(TranscendPullResource.Attributes)\n ) {\n result.attributes = attributes.map(\n ({\n description,\n name,\n type,\n values,\n enabledOn = [],\n }): AttributeInput => ({\n description: description || undefined,\n resources: enabledOn,\n name,\n type,\n values: values.map(({ name, color, description }) => ({\n name,\n color: color || undefined,\n description,\n })),\n }),\n );\n }\n\n // save purposes\n if (purposes.length > 0) {\n result.purposes = purposes.map(\n ({\n name,\n description,\n trackingType,\n defaultConsent,\n configurable,\n showInConsentManager,\n isActive,\n displayOrder,\n optOutSignals,\n authLevel,\n topics,\n showInPrivacyCenter,\n title,\n }): ConsentPurpose => ({\n name,\n title,\n description: description || undefined,\n trackingType,\n 'default-consent': defaultConsent,\n configurable,\n 'show-in-consent-manager': showInConsentManager,\n 'show-in-privacy-center': showInPrivacyCenter,\n 'is-active': isActive,\n 'display-order': displayOrder,\n 'opt-out-signals': optOutSignals.length > 0 ? optOutSignals : undefined,\n 'auth-level': authLevel || undefined,\n 'preference-topics': topics.map(\n ({\n title,\n type,\n displayDescription,\n defaultConfiguration,\n showInPrivacyCenter,\n preferenceOptionValues,\n }) => ({\n title: title.defaultMessage,\n type,\n description: displayDescription.defaultMessage,\n 'default-configuration': defaultConfiguration,\n 'show-in-privacy-center': showInPrivacyCenter,\n ...(preferenceOptionValues.length > 0\n ? {\n options: preferenceOptionValues.map(({ title, slug }) => ({\n title: title.defaultMessage,\n slug,\n })),\n }\n : {}),\n }),\n ),\n }),\n );\n }\n\n // save email templates\n if (\n dataSiloIds.length === 0 &&\n templates.length > 0 &&\n resources.includes(TranscendPullResource.Templates)\n ) {\n result.templates = templates.map(({ title }) => ({ title }));\n }\n\n // Save enrichers\n if (\n enrichers.length > 0 &&\n resources.includes(TranscendPullResource.Enrichers)\n ) {\n result.enrichers = enrichers.map(\n ({\n title,\n url,\n type,\n inputIdentifier,\n identifiers,\n actions,\n testRegex,\n dataSubjects,\n expirationDuration,\n lookerQueryTitle,\n transitionRequestStatus,\n phoneNumbers,\n regionList,\n }): EnricherInput => ({\n title,\n url: url || undefined,\n type,\n 'input-identifier': inputIdentifier?.name,\n 'output-identifiers': identifiers.map(({ name }) => name),\n 'privacy-actions':\n Object.values(RequestAction).length === actions.length\n ? undefined\n : actions,\n testRegex: testRegex || undefined,\n lookerQueryTitle: lookerQueryTitle || undefined,\n expirationDuration: parseInt(expirationDuration, 10),\n transitionRequestStatus: transitionRequestStatus || undefined,\n phoneNumbers:\n phoneNumbers && phoneNumbers.length > 0 ? phoneNumbers : undefined,\n regionList:\n regionList && regionList.length > 0 ? regionList : undefined,\n 'data-subjects': dataSubjects.map(({ type }) => type),\n }),\n );\n }\n\n // Save data silos\n if (\n dataSilos.length > 0 &&\n resources.includes(TranscendPullResource.DataSilos)\n ) {\n const indexedDataSubjects = keyBy(dataSubjects, 'type');\n result['data-silos'] = dataSilos.map(\n ([\n {\n title,\n description,\n url,\n type,\n outerType,\n apiKeys,\n notifyEmailAddress,\n identifiers,\n dependentDataSilos,\n owners,\n country,\n countrySubDivision,\n teams,\n subjectBlocklist,\n isLive,\n promptAVendorEmailSendFrequency,\n promptAVendorEmailSendType,\n promptAVendorEmailIncludeIdentifiersAttachment,\n promptAVendorEmailCompletionLinkType,\n manualWorkRetryFrequency,\n catalog,\n attributeValues,\n discoveredBy,\n businessEntities,\n },\n dataPoints,\n ]): DataSiloInput => ({\n title,\n description,\n integrationName: type,\n 'outer-type': outerType || undefined,\n url: url || undefined,\n 'api-key-title': apiKeys[0]?.title,\n 'identity-keys': identifiers\n .filter(({ isConnected }) => isConnected)\n .map(({ name }) => name),\n ...(dependentDataSilos.length > 0\n ? {\n 'deletion-dependencies': dependentDataSilos.map(\n ({ title }) => title,\n ),\n }\n : {}),\n ...(owners.length > 0\n ? { owners: owners.map(({ email }) => email) }\n : {}),\n ...(teams.length > 0 ? { teams: teams.map(({ name }) => name) } : {}),\n ...(discoveredBy.length > 0\n ? { discoveredBy: discoveredBy.map(({ title }) => title) }\n : {}),\n ...(businessEntities.length > 0\n ? {\n businessEntities: businessEntities.map(({ title }) => title),\n }\n : {}),\n country: country || undefined,\n countrySubDivision: countrySubDivision || undefined,\n disabled: !isLive,\n 'data-subjects':\n subjectBlocklist.length > 0\n ? convertToDataSubjectAllowlist(\n subjectBlocklist.map(({ type }) => type),\n indexedDataSubjects,\n )\n : undefined,\n ...(catalog.hasAvcFunctionality\n ? {\n 'email-settings': {\n 'notify-email-address': notifyEmailAddress || undefined,\n 'send-frequency': promptAVendorEmailSendFrequency,\n 'send-type': promptAVendorEmailSendType,\n 'include-identifiers-attachment':\n promptAVendorEmailIncludeIdentifiersAttachment,\n 'completion-link-type': promptAVendorEmailCompletionLinkType,\n 'manual-work-retry-frequency': manualWorkRetryFrequency,\n },\n }\n : {}),\n attributes:\n attributeValues !== undefined && attributeValues.length > 0\n ? formatAttributeValues(attributeValues)\n : undefined,\n\n datapoints: dataPoints\n .map(\n (dataPoint): DatapointInput => ({\n key: dataPoint.name,\n title: dataPoint.title?.defaultMessage,\n description: dataPoint.description?.defaultMessage,\n owners: dataPoint.owners.map(({ email }) => email),\n teams: dataPoint.teams.map(({ name }) => name),\n ...(dataPoint.path.length > 0 ? { path: dataPoint.path } : {}),\n ...(dataPoint.dataCollection?.title\n ? {\n 'data-collection-tag':\n dataPoint.dataCollection.title.defaultMessage,\n }\n : {}),\n ...(dataPoint.dbIntegrationQueries.length > 0\n ? {\n 'privacy-action-queries': mapValues(\n keyBy(dataPoint.dbIntegrationQueries, 'requestType'),\n (databaseIntegrationQuery) =>\n databaseIntegrationQuery.suggestedQuery ||\n databaseIntegrationQuery.query ||\n undefined,\n ),\n }\n : {}),\n ...(dataPoint.subDataPoints.length > 0\n ? {\n fields: dataPoint.subDataPoints\n .map(\n (field): FieldInput => ({\n key: field.name,\n description: field.description,\n purposes: field.purposes,\n categories: field.categories,\n ...(includeGuessedCategories &&\n field.pendingCategoryGuesses\n ? {\n 'guessed-categories':\n field.pendingCategoryGuesses\n .filter(\n (guess) => guess.status === 'PENDING',\n )\n .map((guess) => ({\n category: {\n name: guess.category.name,\n category: guess.category.category,\n },\n status: guess.status,\n confidence: guess.confidence,\n classifierVersion:\n guess.classifierVersion || undefined,\n })),\n }\n : {}),\n 'access-request-visibility-enabled':\n field.accessRequestVisibilityEnabled,\n 'erasure-request-redaction-enabled':\n field.erasureRequestRedactionEnabled,\n attributes:\n field.attributeValues !== undefined &&\n field.attributeValues.length > 0\n ? formatAttributeValues(field.attributeValues)\n : undefined,\n }),\n )\n .sort((a, b) => a.key.localeCompare(b.key)),\n }\n : {}),\n 'privacy-actions': dataPoint.actionSettings\n .filter(({ active }) => active)\n .map(({ type }) => type),\n }),\n )\n .sort((a, b) =>\n [...(a.path ?? []), a.key]\n .join('.')\n .localeCompare([...(b.path ?? []), b.key].join('.')),\n ),\n }),\n );\n }\n return result;\n}\n/* eslint-enable max-lines */\n","import { GraphQLClient } from 'graphql-request';\nimport { REPORT_PROMPT_RUN } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n QueueStatus,\n ChatCompletionRole,\n PromptRunProductArea,\n LargeLanguageModelClient,\n} from '@transcend-io/privacy-types';\n\nexport interface ReportPromptRunInput {\n /** Name of run */\n name: string;\n /** The related product area being uploaded to */\n productArea: PromptRunProductArea;\n /** Messages reported on */\n promptRunMessages: {\n /** Message reported */\n content: string;\n /** Role of message */\n role: ChatCompletionRole;\n /** Template used if created from prompt */\n template?: string;\n }[];\n /** ID of the Transcend prompt being reported */\n promptId?: string;\n /** Title of the prompt being reported on */\n promptTitle?: string;\n /** Error message (if one exists) */\n error?: string;\n /** The status of the run */\n status?: QueueStatus;\n /** Employee email that is executing the request */\n runByEmployeeEmail?: string;\n /** Duration of time that it took to execute the prompt */\n duration?: number;\n /** Temperature used when running prompt */\n temperature?: number;\n /** TopP parameter used when running prompt */\n topP?: number;\n /** Max tokens ot sample parameter used when running prompt */\n maxTokensToSample?: number;\n /** The ID of the prompt group being reported */\n promptGroupId?: string;\n /** The title of the prompt group being reported */\n promptGroupTitle?: string;\n /** The LLM Id being reported on */\n largeLanguageModelId?: string;\n /** The name of the large language model being reported on */\n largeLanguageModelName?: string;\n /** The name of the large language model client reported on */\n largeLanguageModelClient?: LargeLanguageModelClient;\n /** ID of the application calling pathfinder */\n applicationId?: string;\n /** Name of the application calling pathfinder */\n applicationName?: string;\n /** Name of the code package calling pathfinder */\n codePackageName?: string;\n /** Name of the repository calling pathfinder */\n repositoryName?: string;\n /** ID of the pathfinder applying policies */\n pathfinderId?: string;\n /** Name of the pathfinder applying policies */\n pathfinderName?: string;\n /** Core identifier of the application user being reported on */\n applicationUserCoreIdentifier?: string;\n /** Name of the application user being reported on */\n applicationUserName?: string;\n}\n\n/**\n * Record a new prompt run\n *\n * @param client - GraphQL client\n * @param input - Prompt input\n * @returns Prompt ID\n */\nexport async function reportPromptRun(\n client: GraphQLClient,\n input: ReportPromptRunInput,\n): Promise<string> {\n const {\n reportPromptRun: { promptRun },\n } = await makeGraphQLRequest<{\n /** reportPromptRun mutation */\n reportPromptRun: {\n /** Prompt */\n promptRun: {\n /** ID */\n id: string;\n };\n };\n }>(client, REPORT_PROMPT_RUN, {\n input: {\n ...input,\n promptRunMessages: input.promptRunMessages.map(\n ({ content, ...rest }) => ({\n ...rest,\n message: content,\n }),\n ),\n },\n });\n return promptRun.id;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { RETRY_REQUEST_ENRICHER } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\n/**\n * Retry a request enricher\n *\n * @param client - GraphQL client\n * @param id - The ID of the request enricher to restart\n */\nexport async function retryRequestEnricher(\n client: GraphQLClient,\n id: string,\n): Promise<void> {\n await makeGraphQLRequest(client, RETRY_REQUEST_ENRICHER, {\n requestEnricherId: id,\n });\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { SET_RESOURCE_ATTRIBUTES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { AttributeSupportedResourceType } from '@transcend-io/privacy-types';\n\ninterface SetResourceAttributesInput {\n /** ID of resource */\n resourceId: string;\n /** Type of resource */\n resourceType: AttributeSupportedResourceType;\n /** Attribute key ID */\n attributeKeyId: string;\n /** Attribute values by ID */\n attributeValueIds?: string[];\n /** Attribute values by name */\n attributeValueNames?: string[];\n}\n\n/**\n * Set attribute values on a particular resource\n *\n * @param client - GraphQL client\n * @param input - Input\n */\nexport async function setResourceAttributes(\n client: GraphQLClient,\n input: SetResourceAttributesInput,\n): Promise<void> {\n await makeGraphQLRequest(client, SET_RESOURCE_ATTRIBUTES, {\n input,\n });\n}\n","import { ActionInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { UPDATE_ACTION } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { difference } from 'lodash-es';\nimport {\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\n\nconst ALL_COUNTRIES_AND_SUBDIVISIONS = [\n ...Object.values(IsoCountryCode),\n ...Object.values(IsoCountrySubdivisionCode),\n];\n\n/**\n * Sync the consent manager\n *\n * @param client - GraphQL client\n * @param options - Options\n */\nexport async function syncAction(\n client: GraphQLClient,\n {\n action,\n actionId,\n skipPublish = false,\n }: {\n /** Action update input */\n action: ActionInput;\n /** Existing action Id */\n actionId: string;\n /** When true, skip publishing to privacy center */\n skipPublish?: boolean;\n },\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_ACTION, {\n input: {\n id: actionId,\n skipSecondaryIfNoFiles: action.skipSecondaryIfNoFiles,\n skipDownloadableStep: action.skipDownloadableStep,\n requiresReview: action.requiresReview,\n waitingPeriod: action.waitingPeriod,\n skipPublish,\n regionList: action.regionBlockList\n ? difference(ALL_COUNTRIES_AND_SUBDIVISIONS, action.regionBlockList)\n : action.regionList,\n regionDetectionMethod: action.regionDetectionMethod,\n },\n });\n}\n","import { ActionItemCollectionInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport {\n UPDATE_ACTION_ITEM_COLLECTION,\n CREATE_ACTION_ITEM_COLLECTION,\n} from './gqls';\nimport { logger } from '../../logger';\nimport { keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport colors from 'colors';\nimport {\n ActionItemCollection,\n fetchAllActionItemCollections,\n} from './fetchAllActionItemCollections';\n\n/**\n * Input to create a new action item collection\n *\n * @param client - GraphQL client\n * @param actionItemCollection - Input\n * @returns Created action item collection\n */\nexport async function createActionItemCollection(\n client: GraphQLClient,\n actionItemCollection: ActionItemCollectionInput,\n): Promise<Pick<ActionItemCollection, 'id' | 'title'>> {\n const input = {\n title: actionItemCollection.title,\n description: actionItemCollection.description || '',\n hidden: actionItemCollection.hidden || false,\n productLine: actionItemCollection.productLine,\n };\n\n const { createActionItemCollection } = await makeGraphQLRequest<{\n /** Create actionItemCollection mutation */\n createActionItemCollection: {\n /** Created actionItemCollection */\n created: ActionItemCollection;\n };\n }>(client, CREATE_ACTION_ITEM_COLLECTION, {\n input,\n });\n return createActionItemCollection.created;\n}\n\n/**\n * Input to update actionItem collection\n *\n * @param client - GraphQL client\n * @param input - Input to update\n * @param actionItemCollectionId - ID of action item collection to update\n */\nexport async function updateActionItemCollection(\n client: GraphQLClient,\n input: ActionItemCollectionInput,\n actionItemCollectionId: string,\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_ACTION_ITEM_COLLECTION, {\n input: {\n id: actionItemCollectionId,\n title: input.title,\n description: input.description,\n hidden: input.hidden,\n productLine: input.productLine,\n },\n });\n}\n\n/**\n * Sync the action item collections\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncActionItemCollections(\n client: GraphQLClient,\n inputs: ActionItemCollectionInput[],\n): Promise<boolean> {\n let encounteredError = false;\n // Fetch existing\n logger.info(\n colors.magenta(`Syncing \"${inputs.length}\" action item collections...`),\n );\n\n // Fetch existing\n const existingActionItemCollections = await fetchAllActionItemCollections(\n client,\n );\n\n // Look up by title\n const collectionByTitle: { [k in string]: ActionItemCollection } = keyBy(\n existingActionItemCollections,\n 'title',\n );\n\n // Create new actionItems\n const newCollections = inputs.filter(\n (input) => !collectionByTitle[input.title],\n );\n\n // Create new actionItem collections\n await mapSeries(newCollections, async (input) => {\n try {\n await createActionItemCollection(client, input);\n logger.info(\n colors.green(\n `Successfully created action item collection \"${input.title}\"!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to create action item collection \"${input.title}\"! - ${err.message}`,\n ),\n );\n }\n });\n\n // Update all actionItems\n const actionItemsToUpdate = inputs\n .map((input) => [input, collectionByTitle[input.title]?.id])\n .filter((x): x is [ActionItemCollectionInput, string] => !!x[1]);\n await mapSeries(actionItemsToUpdate, async ([input, actionItemId]) => {\n try {\n await updateActionItemCollection(client, input, actionItemId);\n logger.info(\n colors.green(\n `Successfully synced action item collection \"${input.title}\"!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync action item collection \"${input.title}\"! - ${err.message}`,\n ),\n );\n }\n });\n\n return !encounteredError;\n}\n","import { ActionItemInput } from '../../codecs';\nimport { uniq, keyBy, chunk } from 'lodash-es';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport { UPDATE_ACTION_ITEMS, CREATE_ACTION_ITEMS } from './gqls';\nimport { logger } from '../../logger';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport colors from 'colors';\nimport { fetchAllActionItems, ActionItem } from './fetchAllActionItems';\nimport {\n ActionItemCollection,\n fetchAllActionItemCollections,\n} from './fetchAllActionItemCollections';\nimport { Attribute, fetchAllAttributes } from './fetchAllAttributes';\n\n/**\n * Input to create a new actionItem\n *\n * @param client - GraphQL client\n * @param actionItems - Action item inputs\n * @param actionItemCollectionByTitle - Action item collections indexed by title\n * @param attributeKeysByName - Lookup attribute by name\n */\nexport async function createActionItems(\n client: GraphQLClient,\n actionItems: ActionItemInput[],\n actionItemCollectionByTitle: { [k in string]: ActionItemCollection },\n // TODO: https://transcend.height.app/T-38961 - insert attributes\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n attributeKeysByName: { [k in string]: Attribute } = {},\n): Promise<void> {\n // TODO: https://transcend.height.app/T-38961 - insert attributes\n // const getAttribute = (key: string): string => {\n // const existing = attributeKeysByName[key];\n // if (!existing) {\n // throw new Error(`Attribute key \"${key}\" does not exist!`);\n // }\n // return existing.id;\n // };\n const chunked = chunk(actionItems, 100);\n await mapSeries(chunked, async (chunkToUpload) => {\n await makeGraphQLRequest(client, CREATE_ACTION_ITEMS, {\n input: chunkToUpload.map((actionItem) => ({\n title: actionItem.title,\n type: actionItem.type,\n priorityOverride: actionItem.priority,\n dueDate: actionItem.dueDate,\n customerExperienceActionItemId:\n actionItem.customerExperienceActionItemId,\n resolved: actionItem.resolved,\n notes: actionItem.notes,\n link: actionItem.link,\n assigneesUserEmails: actionItem.users,\n assigneesTeamNames: actionItem.teams,\n ...(actionItem.attributes\n ? {\n // TODO: https://transcend.height.app/T-38961 - insert attributes\n // attributes: actionItem.attributes.map(({ key, values }) => ({\n // attributeKeyId: getAttribute(key),\n // attributeValueNames: values,\n // })),\n }\n : {}),\n collectionIds: actionItem.collections.map(\n (collectionTitle) => actionItemCollectionByTitle[collectionTitle].id,\n ),\n })),\n });\n });\n}\n\n/**\n * Input to update actionItems\n *\n * @param client - GraphQL client\n * @param input - Input to update\n * @param actionItemId - ID of action item to update\n * @param attributeKeysByName - Attribute keys by name\n */\nexport async function updateActionItem(\n client: GraphQLClient,\n input: ActionItemInput,\n actionItemId: string,\n attributeKeysByName: {\n [k in string]: Attribute;\n } = {},\n): Promise<void> {\n const getAttribute = (key: string): string => {\n const existing = attributeKeysByName[key];\n if (!existing) {\n throw new Error(`Attribute key \"${key}\" does not exist!`);\n }\n return existing.id;\n };\n await makeGraphQLRequest(client, UPDATE_ACTION_ITEMS, {\n input: {\n ids: [actionItemId],\n title: input.title,\n priorityOverride: input.priority,\n dueDate: input.dueDate,\n resolved: input.resolved,\n customerExperienceActionItemId: input.customerExperienceActionItemId,\n notes: input.notes,\n link: input.link,\n assigneesUserEmails: input.users,\n assigneesTeamNames: input.teams,\n ...(input.attributes\n ? {\n attributes: input.attributes.map(({ key, values }) => ({\n attributeKeyId: getAttribute(key),\n attributeValueNames: values,\n })),\n }\n : {}),\n },\n });\n}\n\n/**\n * Convert action item to a unique key\n *\n * @param actionItem - action item\n * @returns Unique key\n */\nfunction actionItemToUniqueCode({\n title,\n collections,\n}: Pick<ActionItem, 'title' | 'collections'>): string {\n return `${title}-${collections\n .map((c) => c.title)\n .sort()\n .join('-')}`;\n}\n\n/**\n * Convert action item to a unique key\n *\n * @param actionItem - action item\n * @returns Unique key\n */\nfunction actionItemInputToUniqueCode({\n title,\n collections,\n}: Pick<ActionItemInput, 'title' | 'collections'>): string {\n return `${title}-${collections.sort().join('-')}`;\n}\n\n/**\n * Sync the action item\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncActionItems(\n client: GraphQLClient,\n inputs: ActionItemInput[],\n): Promise<boolean> {\n let encounteredError = false;\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${inputs.length}\" actionItems...`));\n\n // Determine if attributes are syncing\n const hasAttributes = inputs.some(\n (input) => input.attributes && input.attributes.length > 0,\n );\n\n // Fetch existing\n const [existingActionItems, existingActionItemCollections, attributeKeys] =\n await Promise.all([\n fetchAllActionItems(client),\n fetchAllActionItemCollections(client),\n hasAttributes ? fetchAllAttributes(client) : [],\n ]);\n\n // Look up by title\n const actionItemCollectionByTitle: { [k in string]: ActionItemCollection } =\n keyBy(existingActionItemCollections, 'title');\n const actionItemByTitle: { [k in string]: ActionItem } = keyBy(\n existingActionItems,\n actionItemToUniqueCode,\n );\n const attributeKeysByName = keyBy(attributeKeys, 'name');\n const actionItemByCxId: { [k in string]: ActionItem } = keyBy(\n existingActionItems.filter((x) => !!x.customerExperienceActionItemIds),\n ({ customerExperienceActionItemIds }) => customerExperienceActionItemIds[0],\n );\n\n // Ensure all collections exist\n const missingCollections = uniq(\n inputs.map((input) => input.collections).flat(),\n ).filter((collectionTitle) => !actionItemCollectionByTitle[collectionTitle]);\n if (missingCollections.length > 0) {\n logger.info(\n colors.red(\n `Missing action item collections: \"${missingCollections.join(\n '\", \"',\n )}\" - please create them first!`,\n ),\n );\n return false;\n }\n\n // Create new actionItems\n const newActionItems = inputs.filter(\n (input) =>\n !actionItemByTitle[actionItemInputToUniqueCode(input)] &&\n !actionItemByCxId[input.customerExperienceActionItemId!],\n );\n\n // Create new actionItems\n if (newActionItems.length > 0) {\n try {\n logger.info(\n colors.magenta(`Creating \"${newActionItems.length}\" actionItems...`),\n );\n await createActionItems(\n client,\n newActionItems,\n actionItemCollectionByTitle,\n attributeKeysByName,\n );\n logger.info(\n colors.green(\n `Successfully created \"${newActionItems.length}\" actionItems!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to create action items! - ${err.message}`),\n );\n }\n }\n\n // Update all actionItems\n const actionItemsToUpdate = inputs\n .map((input) => [\n input,\n actionItemByTitle[actionItemInputToUniqueCode(input)]?.id ||\n actionItemByCxId[input.customerExperienceActionItemId!]?.id,\n ])\n .filter((x): x is [ActionItemInput, string] => !!x[1]);\n await mapSeries(actionItemsToUpdate, async ([input, actionItemId]) => {\n try {\n await updateActionItem(client, input, actionItemId, attributeKeysByName);\n logger.info(\n colors.green(`Successfully synced action item \"${input.title}\"!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync action item \"${input.title}\"! - ${err.message}`,\n ),\n );\n }\n });\n\n return !encounteredError;\n}\n","import { AgentFileInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport { UPDATE_AGENT_FILES, CREATE_AGENT_FILE } from './gqls';\nimport { logger } from '../../logger';\nimport { keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport colors from 'colors';\nimport { fetchAllAgentFiles, AgentFile } from './fetchAllAgentFiles';\n\n/**\n * Input to create a new agent file\n *\n * @param client - GraphQL client\n * @param agentFile - Input\n * @returns Created agent file\n */\nexport async function createAgentFile(\n client: GraphQLClient,\n agentFile: AgentFileInput,\n): Promise<Pick<AgentFile, 'id' | 'name' | 'fileId'>> {\n const input = {\n name: agentFile.name,\n description: agentFile.description,\n fileId: agentFile.fileId,\n size: agentFile.size,\n purpose: agentFile.purpose,\n fileUploadedAt: new Date(),\n agentIds: [],\n // TODO: https://transcend.height.app/T-31994 - sync agents\n };\n\n const { createAgentFile } = await makeGraphQLRequest<{\n /** Create agent file mutation */\n createAgentFile: {\n /** Created agent file */\n agentFile: AgentFile;\n };\n }>(client, CREATE_AGENT_FILE, {\n input,\n });\n return createAgentFile.agentFile;\n}\n\n/**\n * Input to update agent files\n *\n * @param client - GraphQL client\n * @param agentFileIdPairs - [AgentFileInput, agentFileId] list\n */\nexport async function updateAgentFiles(\n client: GraphQLClient,\n agentFileIdPairs: [AgentFileInput, string][],\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_AGENT_FILES, {\n input: {\n agentFiles: agentFileIdPairs.map(([agentFile, id]) => ({\n id,\n name: agentFile.name,\n description: agentFile.description,\n fileId: agentFile.fileId,\n size: agentFile.size,\n purpose: agentFile.purpose,\n })),\n },\n });\n}\n\n/**\n * Sync the data inventory agent files\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncAgentFiles(\n client: GraphQLClient,\n inputs: AgentFileInput[],\n): Promise<boolean> {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${inputs.length}\" agent files...`));\n\n let encounteredError = false;\n\n // Fetch existing\n const existingAgentFiles = await fetchAllAgentFiles(client);\n\n // Look up by name\n const agentFileByName: {\n [k in string]: Pick<AgentFile, 'id' | 'name' | 'fileId'>;\n } = keyBy(existingAgentFiles, 'name');\n\n // Create new agent files\n const newAgentFiles = inputs.filter((input) => !agentFileByName[input.name]);\n\n // Create new agent files\n await mapSeries(newAgentFiles, async (agentFile) => {\n try {\n const newAgentFile = await createAgentFile(client, agentFile);\n agentFileByName[newAgentFile.name] = newAgentFile;\n logger.info(\n colors.green(`Successfully synced agent file \"${agentFile.name}\"!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync agent file \"${agentFile.name}\"! - ${err.message}`,\n ),\n );\n }\n });\n\n // Update all agent files\n try {\n logger.info(colors.magenta(`Updating \"${inputs.length}\" agent files!`));\n await updateAgentFiles(\n client,\n inputs.map((input) => [input, agentFileByName[input.name].id]),\n );\n logger.info(\n colors.green(`Successfully synced \"${inputs.length}\" agent files!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync \"${inputs.length}\" agent files! - ${err.message}`,\n ),\n );\n }\n\n return !encounteredError;\n}\n","import { AgentFunctionInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport { UPDATE_AGENT_FUNCTIONS, CREATE_AGENT_FUNCTION } from './gqls';\nimport { logger } from '../../logger';\nimport { keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport colors from 'colors';\nimport {\n fetchAllAgentFunctions,\n AgentFunction,\n} from './fetchAllAgentFunctions';\n\n/**\n * Input to create a new agent function\n *\n * @param client - GraphQL client\n * @param agentFunction - Input\n * @returns Created agent function\n */\nexport async function createAgentFunction(\n client: GraphQLClient,\n agentFunction: AgentFunctionInput,\n): Promise<Pick<AgentFunction, 'id' | 'name'>> {\n const input = {\n name: agentFunction.name,\n description: agentFunction.description,\n parameters: agentFunction.parameters,\n agentIds: [],\n // TODO: https://transcend.height.app/T-31994 - sync agents\n };\n\n const { createAgentFunction } = await makeGraphQLRequest<{\n /** Create agent function mutation */\n createAgentFunction: {\n /** Created agent function */\n agentFunction: AgentFunction;\n };\n }>(client, CREATE_AGENT_FUNCTION, {\n input,\n });\n return createAgentFunction.agentFunction;\n}\n\n/**\n * Input to update agent functions\n *\n * @param client - GraphQL client\n * @param agentFunctionIdPairs - [AgentFunctionInput, agentFunctionId] list\n */\nexport async function updateAgentFunctions(\n client: GraphQLClient,\n agentFunctionIdPairs: [AgentFunctionInput, string][],\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_AGENT_FUNCTIONS, {\n input: {\n agentFunctions: agentFunctionIdPairs.map(([agentFunction, id]) => ({\n id,\n name: agentFunction.name,\n description: agentFunction.description,\n parameters: agentFunction.parameters,\n })),\n },\n });\n}\n\n/**\n * Sync the data inventory agent functions\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncAgentFunctions(\n client: GraphQLClient,\n inputs: AgentFunctionInput[],\n): Promise<boolean> {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${inputs.length}\" agent functions...`));\n\n let encounteredError = false;\n\n // Fetch existing\n const existingAgentFunctions = await fetchAllAgentFunctions(client);\n\n // Look up by name\n const agentFunctionByName: {\n [k in string]: Pick<AgentFunction, 'id' | 'name'>;\n } = keyBy(existingAgentFunctions, 'name');\n\n // Create new agent functions\n const newAgentFunctions = inputs.filter(\n (input) => !agentFunctionByName[input.name],\n );\n\n // Create new agent functions\n await mapSeries(newAgentFunctions, async (agentFunction) => {\n try {\n const newAgentFunction = await createAgentFunction(client, agentFunction);\n agentFunctionByName[newAgentFunction.name] = newAgentFunction;\n logger.info(\n colors.green(\n `Successfully synced agent function \"${agentFunction.name}\"!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync agent function \"${agentFunction.name}\"! - ${err.message}`,\n ),\n );\n }\n });\n\n // Update all agent functions\n try {\n logger.info(colors.magenta(`Updating \"${inputs.length}\" agent functions!`));\n await updateAgentFunctions(\n client,\n inputs.map((input) => [input, agentFunctionByName[input.name].id]),\n );\n logger.info(\n colors.green(`Successfully synced \"${inputs.length}\" agent functions!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync \"${inputs.length}\" agent functions! - ${err.message}`,\n ),\n );\n }\n\n return !encounteredError;\n}\n","import { AgentInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport { UPDATE_AGENTS, CREATE_AGENT } from './gqls';\nimport { logger } from '../../logger';\nimport { keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport colors from 'colors';\nimport { fetchAllAgents, Agent } from './fetchAllAgents';\n\n/**\n * Input to create a new agent\n *\n * @param client - GraphQL client\n * @param agent - Input\n * @returns Created agent\n */\nexport async function createAgent(\n client: GraphQLClient,\n agent: AgentInput,\n): Promise<Pick<Agent, 'id' | 'name' | 'agentId'>> {\n const input = {\n name: agent.name,\n description: agent.description,\n codeInterpreterEnabled: agent.codeInterpreterEnabled,\n retrievalEnabled: agent.retrievalEnabled,\n promptTitle: agent.prompt,\n largeLanguageModelName: agent['large-language-model'].name,\n largeLanguageModelClient: agent['large-language-model'].client,\n // TODO: https://transcend.height.app/T-32760 - agentFunction, agentFile\n // TODO: https://transcend.height.app/T-31994 - owners and teams\n };\n\n const { createAgent } = await makeGraphQLRequest<{\n /** Create agent mutation */\n createAgent: {\n /** Created agent */\n agent: Agent;\n };\n }>(client, CREATE_AGENT, {\n input,\n });\n return createAgent.agent;\n}\n\n/**\n * Input to update agents\n *\n * @param client - GraphQL client\n * @param agentIdParis - [AgentInput, agentId] list\n */\nexport async function updateAgents(\n client: GraphQLClient,\n agentIdParis: [AgentInput, string][],\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_AGENTS, {\n input: {\n agents: agentIdParis.map(([agent, id]) => ({\n id,\n name: agent.name,\n description: agent.description,\n codeInterpreterEnabled: agent.codeInterpreterEnabled,\n retrievalEnabled: agent.retrievalEnabled,\n // TODO: https://transcend.height.app/T-31995 - prompt, largeLanguageModel, agentFunction, agentFile\n })),\n },\n });\n}\n\n/**\n * Sync the data inventory agents\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncAgents(\n client: GraphQLClient,\n inputs: AgentInput[],\n): Promise<boolean> {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${inputs.length}\" agents...`));\n\n let encounteredError = false;\n\n // Fetch existing\n const existingAgents = await fetchAllAgents(client);\n\n // Look up by name\n const agentByName: {\n [k in string]: Pick<Agent, 'id' | 'name' | 'agentId'>;\n } = keyBy(existingAgents, 'name');\n\n // Create new agents\n const newAgents = inputs.filter((input) => !agentByName[input.name]);\n\n // Create new agents\n await mapSeries(newAgents, async (agent) => {\n try {\n const newAgent = await createAgent(client, agent);\n agentByName[newAgent.name] = newAgent;\n logger.info(colors.green(`Successfully synced agent \"${agent.name}\"!`));\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to sync agent \"${agent.name}\"! - ${err.message}`),\n );\n }\n });\n\n // Update all agents\n try {\n logger.info(colors.magenta(`Updating \"${inputs.length}\" agents!`));\n await updateAgents(\n client,\n inputs.map((input) => [input, agentByName[input.name].id]),\n );\n logger.info(colors.green(`Successfully synced \"${inputs.length}\" agents!`));\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to sync \"${inputs.length}\" agents ! - ${err.message}`),\n );\n }\n\n return !encounteredError;\n}\n","import { AttributeInput } from '../../codecs';\nimport colors from 'colors';\nimport { keyBy, difference, groupBy } from 'lodash-es';\nimport { GraphQLClient } from 'graphql-request';\nimport {\n CREATE_ATTRIBUTE,\n CREATE_ATTRIBUTE_VALUES,\n DELETE_ATTRIBUTE_VALUE,\n UPDATE_ATTRIBUTE,\n UPDATE_ATTRIBUTE_VALUES,\n} from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { Attribute } from './fetchAllAttributes';\nimport { map } from '../bluebird';\nimport { logger } from '../../logger';\n\n/**\n * Sync attribute\n *\n * @param client - GraphQL client\n * @param attribute - The attribute input\n * @param options - Options\n */\nexport async function syncAttribute(\n client: GraphQLClient,\n attribute: AttributeInput,\n {\n existingAttribute,\n deleteExtraAttributeValues,\n }: {\n /** The existing attribute configuration if it exists */\n existingAttribute?: Attribute;\n /** When true, delete extra attributes not specified in the list of values */\n deleteExtraAttributeValues?: boolean;\n },\n): Promise<void> {\n // attribute key input\n const input = {\n name: attribute.name,\n enabledOn: attribute.resources,\n };\n\n // create or update attribute key\n let attributeKeyId: string;\n if (!existingAttribute) {\n const {\n createAttributeKey: { attributeKey },\n } = await makeGraphQLRequest<{\n /** Create attribute key response */\n createAttributeKey: {\n /** Attribute key */\n attributeKey: {\n /** ID */\n id: string;\n };\n };\n }>(client, CREATE_ATTRIBUTE, {\n type: attribute.type,\n description: attribute.description,\n ...input,\n });\n attributeKeyId = attributeKey.id;\n } else {\n await makeGraphQLRequest(client, UPDATE_ATTRIBUTE, {\n attributeKeyId: existingAttribute.id,\n description: existingAttribute.isCustom\n ? attribute.description\n : undefined,\n ...input,\n });\n attributeKeyId = existingAttribute.id;\n }\n\n // upsert attribute values\n const existingAttributeMap = keyBy(existingAttribute?.values || [], 'name');\n const { existingValues = [], newValues = [] } = groupBy(\n attribute.values || [],\n (field) =>\n existingAttributeMap[field.name] ? 'existingValues' : 'newValues',\n );\n const removedValues = difference(\n (existingAttribute?.values || []).map(({ name }) => name),\n (attribute.values || []).map(({ name }) => name),\n );\n\n // Create new attribute values\n if (newValues.length > 0) {\n await makeGraphQLRequest(client, CREATE_ATTRIBUTE_VALUES, {\n input: newValues.map(({ name, ...rest }) => ({\n name,\n attributeKeyId,\n ...rest,\n })),\n });\n logger.info(colors.green(`Created ${newValues.length} attribute values`));\n }\n\n // Update existing attribute values\n if (existingValues.length > 0) {\n await makeGraphQLRequest(client, UPDATE_ATTRIBUTE_VALUES, {\n input: existingValues.map(({ name, ...rest }) => ({\n id: existingAttributeMap[name].id,\n name,\n description: existingAttributeMap[name].description,\n color: existingAttributeMap[name].color,\n ...rest,\n attributeKeyId,\n })),\n });\n logger.info(\n colors.green(`Updated ${existingValues.length} attribute values`),\n );\n }\n\n // Delete removed attribute values\n if (removedValues.length > 0 && deleteExtraAttributeValues) {\n await map(\n removedValues,\n async (value) => {\n await makeGraphQLRequest(client, DELETE_ATTRIBUTE_VALUE, {\n id: existingAttributeMap[value].id,\n });\n },\n {\n concurrency: 10,\n },\n );\n logger.info(\n colors.green(`Deleted ${removedValues.length} attribute values`),\n );\n }\n}\n","import { BusinessEntityInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport { UPDATE_BUSINESS_ENTITIES, CREATE_BUSINESS_ENTITY } from './gqls';\nimport { logger } from '../../logger';\nimport { keyBy, chunk } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n fetchAllBusinessEntities,\n BusinessEntity,\n} from './fetchAllBusinessEntities';\nimport colors from 'colors';\n\n/**\n * Input to create a new business entity\n *\n * @param client - GraphQL client\n * @param businessEntity - Input\n * @returns Created business entity\n */\nexport async function createBusinessEntity(\n client: GraphQLClient,\n businessEntity: BusinessEntityInput,\n): Promise<BusinessEntity> {\n const input = {\n title: businessEntity.title,\n description: businessEntity.description,\n address: businessEntity.address,\n headquarterCountry: businessEntity.headquarterCountry,\n headquarterSubDivision: businessEntity.headquarterSubDivision,\n dataProtectionOfficerName: businessEntity.dataProtectionOfficerName,\n dataProtectionOfficerEmail: businessEntity.dataProtectionOfficerEmail,\n attributes: businessEntity.attributes,\n teamNames: businessEntity.teams,\n ownerEmails: businessEntity.owners,\n };\n\n const { createBusinessEntity } = await makeGraphQLRequest<{\n /** Create business entity mutation */\n createBusinessEntity: {\n /** Created business entity */\n businessEntity: BusinessEntity;\n };\n }>(client, CREATE_BUSINESS_ENTITY, {\n input,\n });\n return createBusinessEntity.businessEntity;\n}\n\n/**\n * Input to update business entities\n *\n * @param client - GraphQL client\n * @param businessEntityIdParis - [BusinessEntityInput, businessEntityId] list\n */\nexport async function updateBusinessEntities(\n client: GraphQLClient,\n businessEntityIdParis: [BusinessEntityInput, string][],\n): Promise<void> {\n const chunkedUpdates = chunk(businessEntityIdParis, 100);\n await mapSeries(chunkedUpdates, async (chunked) => {\n await makeGraphQLRequest(client, UPDATE_BUSINESS_ENTITIES, {\n input: chunked.map(([businessEntity, id]) => ({\n id,\n title: businessEntity.title,\n description: businessEntity.description,\n address: businessEntity.address,\n headquarterCountry: businessEntity.headquarterCountry,\n headquarterSubDivision: businessEntity.headquarterSubDivision,\n dataProtectionOfficerName: businessEntity.dataProtectionOfficerName,\n dataProtectionOfficerEmail: businessEntity.dataProtectionOfficerEmail,\n attributes: businessEntity.attributes,\n teamNames: businessEntity.teams,\n ownerEmails: businessEntity.owners,\n })),\n });\n });\n}\n\n/**\n * Sync the data inventory business entities\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncBusinessEntities(\n client: GraphQLClient,\n inputs: BusinessEntityInput[],\n): Promise<boolean> {\n // Fetch existing\n logger.info(\n colors.magenta(`Syncing \"${inputs.length}\" business entities...`),\n );\n\n let encounteredError = false;\n\n // Fetch existing\n const existingBusinessEntities = await fetchAllBusinessEntities(client);\n\n // Look up by title\n const businessEntityByTitle = keyBy(existingBusinessEntities, 'title');\n\n // Create new business entities\n const newBusinessEntities = inputs.filter(\n (input) => !businessEntityByTitle[input.title],\n );\n\n // Create new business entities\n await mapSeries(newBusinessEntities, async (businessEntity) => {\n try {\n const newBusinessEntity = await createBusinessEntity(\n client,\n businessEntity,\n );\n businessEntityByTitle[newBusinessEntity.title] = newBusinessEntity;\n logger.info(\n colors.green(\n `Successfully synced business entity \"${businessEntity.title}\"!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync business entity \"${businessEntity.title}\"! - ${err.message}`,\n ),\n );\n }\n });\n\n // Update all business entities\n try {\n logger.info(\n colors.magenta(`Updating \"${inputs.length}\" business entities!`),\n );\n await updateBusinessEntities(\n client,\n inputs.map((input) => [input, businessEntityByTitle[input.title].id]),\n );\n logger.info(\n colors.green(`Successfully synced \"${inputs.length}\" business entities!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync \"${inputs.length}\" business entities ! - ${err.message}`,\n ),\n );\n }\n\n return !encounteredError;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { CODE_PACKAGES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { CodePackageType } from '@transcend-io/privacy-types';\n\nexport interface CodePackage {\n /** ID of code package */\n id: string;\n /** Name of code package */\n name: string;\n /** Description of code package */\n description: string;\n /** Type of code package */\n type: CodePackageType;\n /** Relative path to code package in repository */\n relativePath: string;\n /** The teams that manage the code package */\n teams: {\n /** ID of team */\n id: string;\n /** Name of team */\n name: string;\n }[];\n /** The users that manage the code package */\n owners: {\n /** ID of user */\n id: string;\n /** Email of user */\n email: string;\n }[];\n /** The repository where the code package belongs */\n repository: {\n /** ID of repository */\n id: string;\n /** Name of repository */\n name: string;\n };\n /** The data silo that the code package relates to */\n dataSilo?: {\n /** ID of repository */\n id: string;\n /** Title of repository */\n title: string;\n /** Type of data silo */\n type: string;\n };\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all code packages in the organization\n *\n * @param client - GraphQL client\n * @returns All code packages in the organization\n */\nexport async function fetchAllCodePackages(\n client: GraphQLClient,\n): Promise<CodePackage[]> {\n const codePackages: CodePackage[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n codePackages: { nodes },\n } = await makeGraphQLRequest<{\n /** Code packages */\n codePackages: {\n /** List */\n nodes: CodePackage[];\n };\n }>(client, CODE_PACKAGES, {\n first: PAGE_SIZE,\n offset,\n });\n codePackages.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return codePackages.sort((a, b) => a.name.localeCompare(b.name));\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { SOFTWARE_DEVELOPMENT_KITS } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { CodePackageType } from '@transcend-io/privacy-types';\n\nexport interface SoftwareDevelopmentKit {\n /** ID of software development kit */\n id: string;\n /** Name of software development kit */\n name: string;\n /** Description of software development kit */\n description: string;\n /** Type of software development kit */\n codePackageType: CodePackageType;\n /** Related documentation */\n documentationLinks: string[];\n /** Link to git repository */\n repositoryUrl?: string;\n /** The teams that manage the software development kit */\n teams: {\n /** ID of team */\n id: string;\n /** Name of team */\n name: string;\n }[];\n /** The users that manage the software development kit */\n owners: {\n /** ID of user */\n id: string;\n /** Email of user */\n email: string;\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all software development kits in the organization\n *\n * @param client - GraphQL client\n * @returns All software development kits in the organization\n */\nexport async function fetchAllSoftwareDevelopmentKits(\n client: GraphQLClient,\n): Promise<SoftwareDevelopmentKit[]> {\n const softwareDevelopmentKits: SoftwareDevelopmentKit[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n softwareDevelopmentKits: { nodes },\n } = await makeGraphQLRequest<{\n /** Software development kits */\n softwareDevelopmentKits: {\n /** List */\n nodes: SoftwareDevelopmentKit[];\n };\n }>(client, SOFTWARE_DEVELOPMENT_KITS, {\n first: PAGE_SIZE,\n offset,\n });\n softwareDevelopmentKits.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return softwareDevelopmentKits.sort((a, b) => a.name.localeCompare(b.name));\n}\n","import colors from 'colors';\nimport { chunk, keyBy } from 'lodash-es';\nimport { SoftwareDevelopmentKitInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport {\n UPDATE_SOFTWARE_DEVELOPMENT_KITS,\n CREATE_SOFTWARE_DEVELOPMENT_KIT,\n} from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { mapSeries, map } from '../bluebird';\nimport {\n fetchAllSoftwareDevelopmentKits,\n SoftwareDevelopmentKit,\n} from './fetchAllSoftwareDevelopmentKits';\nimport { logger } from '../../logger';\nimport { CodePackageType } from '@transcend-io/privacy-types';\n\nconst CHUNK_SIZE = 100;\n\n/**\n * Create a new software development kit\n *\n * @param client - GraphQL client\n * @param input - Software development kit input\n * @returns Created software development kit\n */\nexport async function createSoftwareDevelopmentKit(\n client: GraphQLClient,\n input: {\n /** Title of software development kit */\n name: string;\n /** Code package type */\n codePackageType: CodePackageType;\n /** Description of the SDK */\n description?: string;\n /** Github repository */\n repositoryUrl?: string;\n /** Integration name */\n catalogIntegrationName?: string;\n /** Doc links */\n documentationLinks?: string[];\n /** Code package IDs */\n codePackageIds?: string[];\n /** Code package names */\n codePackageNames?: string[];\n /** User IDs of owners */\n ownerIds?: string[];\n /** Emails of owners */\n ownerEmails?: string[];\n /** Team IDs */\n teamIds?: string[];\n /** Team names */\n teamNames?: string[];\n },\n): Promise<SoftwareDevelopmentKit> {\n const {\n createSoftwareDevelopmentKit: { softwareDevelopmentKit },\n } = await makeGraphQLRequest<{\n /** createSoftwareDevelopmentKit mutation */\n createSoftwareDevelopmentKit: {\n /** Software development kit */\n softwareDevelopmentKit: SoftwareDevelopmentKit;\n };\n }>(client, CREATE_SOFTWARE_DEVELOPMENT_KIT, {\n input,\n });\n logger.info(\n colors.green(\n `Successfully created software development kit \"${input.name}\"!`,\n ),\n );\n return softwareDevelopmentKit;\n}\n\n/**\n * Update an existing software development kit\n *\n * @param client - GraphQL client\n * @param inputs - Software development kit input\n * @returns Updated software development kits\n */\nexport async function updateSoftwareDevelopmentKits(\n client: GraphQLClient,\n inputs: {\n /** ID of software development kit */\n id: string;\n /** Title of software development kit */\n name?: string;\n /** Description of the SDK */\n description?: string;\n /** Github repository */\n repositoryUrl?: string;\n /** Integration name */\n catalogIntegrationName?: string;\n /** Doc links */\n documentationLinks?: string[];\n /** Code package IDs */\n codePackageIds?: string[];\n /** Code package names */\n codePackageNames?: string[];\n /** User IDs of owners */\n ownerIds?: string[];\n /** Emails of owners */\n ownerEmails?: string[];\n /** Team IDs */\n teamIds?: string[];\n /** Team names */\n teamNames?: string[];\n }[],\n): Promise<SoftwareDevelopmentKit[]> {\n const {\n updateSoftwareDevelopmentKits: { softwareDevelopmentKits },\n } = await makeGraphQLRequest<{\n /** updateSoftwareDevelopmentKits mutation */\n updateSoftwareDevelopmentKits: {\n /** Software development kit */\n softwareDevelopmentKits: SoftwareDevelopmentKit[];\n };\n }>(client, UPDATE_SOFTWARE_DEVELOPMENT_KITS, {\n input: {\n softwareDevelopmentKits: inputs,\n },\n });\n logger.info(\n colors.green(\n `Successfully updated ${inputs.length} software development kits!`,\n ),\n );\n return softwareDevelopmentKits;\n}\n\n/**\n * Sync the software development kits\n *\n * @param client - GraphQL client\n * @param softwareDevelopmentKits - Software development kits\n * @param concurrency - Concurrency\n * @returns The software development kits that were upserted and whether the sync was successful\n */\nexport async function syncSoftwareDevelopmentKits(\n client: GraphQLClient,\n softwareDevelopmentKits: SoftwareDevelopmentKitInput[],\n concurrency = 20,\n): Promise<{\n /** The SDKs that were upserted */\n softwareDevelopmentKits: SoftwareDevelopmentKit[];\n /** If successful */\n success: boolean;\n}> {\n let encounteredError = false;\n const sdks: SoftwareDevelopmentKit[] = [];\n logger.info(colors.magenta('Syncing software development kits...'));\n\n // Index existing software development kits\n const existing = await fetchAllSoftwareDevelopmentKits(client);\n const softwareDevelopmentKitByTitle = keyBy(\n existing,\n ({ name, codePackageType }) => JSON.stringify({ name, codePackageType }),\n );\n\n // Determine which software development kits are new vs existing\n const mapSoftwareDevelopmentKitsToExisting = softwareDevelopmentKits.map(\n (sdkInput) => [\n sdkInput,\n softwareDevelopmentKitByTitle[\n JSON.stringify({\n name: sdkInput.name,\n codePackageType: sdkInput.codePackageType,\n })\n ]?.id,\n ],\n );\n\n // Create the new software development kits\n const newSoftwareDevelopmentKits = mapSoftwareDevelopmentKitsToExisting\n .filter(([, existing]) => !existing)\n .map(([sdkInput]) => sdkInput as SoftwareDevelopmentKitInput);\n try {\n logger.info(\n colors.magenta(\n `Creating \"${newSoftwareDevelopmentKits.length}\" new software development kits...`,\n ),\n );\n await map(\n newSoftwareDevelopmentKits,\n async (sdk) => {\n const newSdk = await createSoftwareDevelopmentKit(client, sdk);\n sdks.push(newSdk);\n },\n {\n concurrency,\n },\n );\n logger.info(\n colors.green(\n `Successfully synced ${newSoftwareDevelopmentKits.length} software development kits!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to create software development kits! - ${err.message}`,\n ),\n );\n }\n\n // Update existing software development kits\n const existingSoftwareDevelopmentKits =\n mapSoftwareDevelopmentKitsToExisting.filter(\n (x): x is [SoftwareDevelopmentKitInput, string] => !!x[1],\n );\n const chunks = chunk(existingSoftwareDevelopmentKits, CHUNK_SIZE);\n logger.info(\n colors.magenta(\n `Updating \"${existingSoftwareDevelopmentKits.length}\" software development kits...`,\n ),\n );\n\n await mapSeries(chunks, async (chunk) => {\n try {\n const updatedSdks = await updateSoftwareDevelopmentKits(\n client,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n chunk.map(([{ codePackageType, ...input }, id]) => ({\n ...input,\n id,\n })),\n );\n sdks.push(...updatedSdks);\n logger.info(\n colors.green(\n `Successfully updated \"${existingSoftwareDevelopmentKits.length}\" software development kits!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to update software development kits! - ${err.message}`,\n ),\n );\n }\n\n logger.info(\n colors.green(\n `Synced \"${softwareDevelopmentKits.length}\" software development kits!`,\n ),\n );\n });\n\n // Return true upon success\n return {\n softwareDevelopmentKits: sdks,\n success: !encounteredError,\n };\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { REPOSITORIES } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface Repository {\n /** ID of repository */\n id: string;\n /** Name of repository */\n name: string;\n /** Description of repository */\n description: string;\n /** URL of repo */\n url: string;\n /** The teams that manage the repository */\n teams: {\n /** ID of team */\n id: string;\n /** Name of team */\n name: string;\n }[];\n /** The users that manage the repository */\n owners: {\n /** ID of user */\n id: string;\n /** Email of user */\n email: string;\n }[];\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all repositories in the organization\n *\n * @param client - GraphQL client\n * @returns All repositories in the organization\n */\nexport async function fetchAllRepositories(\n client: GraphQLClient,\n): Promise<Repository[]> {\n const repositories: Repository[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n repositories: { nodes },\n } = await makeGraphQLRequest<{\n /** Repositories */\n repositories: {\n /** List */\n nodes: Repository[];\n };\n }>(client, REPOSITORIES, {\n first: PAGE_SIZE,\n offset,\n });\n repositories.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return repositories.sort((a, b) => a.name.localeCompare(b.name));\n}\n","import colors from 'colors';\nimport { chunk, keyBy } from 'lodash-es';\nimport { RepositoryInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { UPDATE_REPOSITORIES, CREATE_REPOSITORY } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { mapSeries, map } from '../bluebird';\nimport { fetchAllRepositories, Repository } from './fetchAllRepositories';\nimport { logger } from '../../logger';\n\nconst CHUNK_SIZE = 100;\n\n/**\n * Create a new repository\n *\n * @param client - GraphQL client\n * @param input - Repository input\n * @returns Created repository\n */\nexport async function createRepository(\n client: GraphQLClient,\n input: {\n /** Title of repository */\n name: string;\n /** Description of the repository */\n description?: string;\n /** Github repository */\n url: string;\n /** User IDs of owners */\n ownerIds?: string[];\n /** Emails of owners */\n ownerEmails?: string[];\n /** Team IDs */\n teamIds?: string[];\n /** Team names */\n teamNames?: string[];\n },\n): Promise<Repository> {\n const {\n createRepository: { repository },\n } = await makeGraphQLRequest<{\n /** createRepository mutation */\n createRepository: {\n /** Software development kit */\n repository: Repository;\n };\n }>(client, CREATE_REPOSITORY, {\n input,\n });\n logger.info(colors.green(`Successfully created repository \"${input.name}\"!`));\n return repository;\n}\n\n/**\n * Update an existing repository\n *\n * @param client - GraphQL client\n * @param inputs - Repository input\n * @returns Updated repositories\n */\nexport async function updateRepositories(\n client: GraphQLClient,\n inputs: {\n /** ID of repository */\n id: string;\n /** Title of repository */\n name?: string;\n /** Description of the repository */\n description?: string;\n /** Github repository */\n url?: string;\n /** User IDs of owners */\n ownerIds?: string[];\n /** Emails of owners */\n ownerEmails?: string[];\n /** Team IDs */\n teamIds?: string[];\n /** Team names */\n teamNames?: string[];\n }[],\n): Promise<Repository[]> {\n const {\n updateRepositories: { repositories },\n } = await makeGraphQLRequest<{\n /** updateRepositories mutation */\n updateRepositories: {\n /** Software development kit */\n repositories: Repository[];\n };\n }>(client, UPDATE_REPOSITORIES, {\n input: {\n repositories: inputs,\n },\n });\n logger.info(\n colors.green(`Successfully updated ${inputs.length} repositories!`),\n );\n return repositories;\n}\n\n/**\n * Sync the repositories\n *\n * @param client - GraphQL client\n * @param repositories - Repositories\n * @param concurrency - Concurrency\n * @returns The repositories that were upserted and whether the sync was successful\n */\nexport async function syncRepositories(\n client: GraphQLClient,\n repositories: RepositoryInput[],\n concurrency = 20,\n): Promise<{\n /** The repositories that were upserted */\n repositories: Repository[];\n /** If successful */\n success: boolean;\n}> {\n let encounteredError = false;\n const repos: Repository[] = [];\n\n // Index existing repositories\n const existing = await fetchAllRepositories(client);\n const repositoryByName = keyBy(existing, 'name');\n\n // Determine which repositories are new vs existing\n const mapRepositoriesToExisting = repositories.map((repoInput) => [\n repoInput,\n repositoryByName[repoInput.name]?.id,\n ]);\n\n // Create the new repositories\n const newRepositories = mapRepositoriesToExisting\n .filter(([, existing]) => !existing)\n .map(([repoInput]) => repoInput as RepositoryInput);\n try {\n logger.info(\n colors.magenta(\n `Creating \"${newRepositories.length}\" new repositories...`,\n ),\n );\n await map(\n newRepositories,\n async (repo) => {\n const newRepo = await createRepository(client, repo);\n repos.push(newRepo);\n },\n {\n concurrency,\n },\n );\n logger.info(\n colors.green(\n `Successfully synced ${newRepositories.length} repositories!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create repositories! - ${err.message}`));\n }\n\n // Update existing repositories\n const existingRepositories = mapRepositoriesToExisting.filter(\n (x): x is [RepositoryInput, string] => !!x[1],\n );\n const chunks = chunk(existingRepositories, CHUNK_SIZE);\n logger.info(\n colors.magenta(`Updating \"${existingRepositories.length}\" repositories...`),\n );\n\n await mapSeries(chunks, async (chunk) => {\n try {\n const updatedRepos = await updateRepositories(\n client,\n chunk.map(([input, id]) => ({\n ...input,\n id,\n })),\n );\n repos.push(...updatedRepos);\n logger.info(\n colors.green(\n `Successfully updated \"${existingRepositories.length}\" repositories!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to update repositories! - ${err.message}`),\n );\n }\n\n logger.info(colors.green(`Synced \"${repositories.length}\" repositories!`));\n });\n\n // Return true upon success\n return {\n repositories: repos,\n success: !encounteredError,\n };\n}\n","import { chunk, uniq, keyBy, uniqBy } from 'lodash-es';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { CodePackage, fetchAllCodePackages } from './fetchAllCodePackages';\nimport { logger } from '../../logger';\nimport { syncSoftwareDevelopmentKits } from './syncSoftwareDevelopmentKits';\nimport { map, mapSeries } from '../bluebird';\nimport { CodePackageInput, RepositoryInput } from '../../codecs';\nimport { CodePackageType } from '@transcend-io/privacy-types';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { CREATE_CODE_PACKAGE, UPDATE_CODE_PACKAGES } from './gqls';\nimport { syncRepositories } from './syncRepositories';\n\nconst CHUNK_SIZE = 100;\n\nconst LOOKUP_SPLIT_KEY = '%%%%';\n\n/**\n * Create a new code package\n *\n * @param client - GraphQL client\n * @param input - Code package input\n * @returns Code package ID\n */\nexport async function createCodePackage(\n client: GraphQLClient,\n input: {\n /** Name of package */\n name: string;\n /** Description of package */\n description?: string;\n /** Type of package */\n type: CodePackageType;\n /** Relative path to package */\n relativePath: string;\n /** Repository ID */\n repositoryId?: string;\n /** Name of repository */\n repositoryName?: string;\n /** IDs of SDKs */\n softwareDevelopmentKitIds?: string[];\n /** IDs of owners */\n ownerIds?: string[];\n /** Emails of owners */\n ownerEmails?: string[];\n /** IDs of teams */\n teamIds?: string[];\n /** Names of teams */\n teamNames?: string[];\n },\n): Promise<CodePackage> {\n const {\n createCodePackage: { codePackage },\n } = await makeGraphQLRequest<{\n /** createCodePackage mutation */\n createCodePackage: {\n /** Code package */\n codePackage: CodePackage;\n };\n }>(client, CREATE_CODE_PACKAGE, {\n input,\n });\n logger.info(\n colors.green(`Successfully created code package \"${input.name}\"!`),\n );\n return codePackage;\n}\n\n/**\n * Update an existing code package\n *\n * @param client - GraphQL client\n * @param inputs - Code package input\n * @returns Code packages that were updated\n */\nexport async function updateCodePackages(\n client: GraphQLClient,\n inputs: {\n /** ID of code package */\n id: string;\n /** Name of package */\n name: string;\n /** Description of package */\n description?: string;\n /** Type of package */\n type: CodePackageType;\n /** Relative path to package */\n relativePath: string;\n /** Repository ID */\n repositoryId?: string;\n /** Name of repository */\n repositoryName?: string;\n /** IDs of SDKs */\n softwareDevelopmentKitIds?: string[];\n /** IDs of owners */\n ownerIds?: string[];\n /** Emails of owners */\n ownerEmails?: string[];\n /** IDs of teams */\n teamIds?: string[];\n /** Names of teams */\n teamNames?: string[];\n }[],\n): Promise<CodePackage[]> {\n const {\n updateCodePackages: { codePackages },\n } = await makeGraphQLRequest<{\n /** updateCodePackages mutation */\n updateCodePackages: {\n /** Code packages */\n codePackages: CodePackage[];\n };\n }>(client, UPDATE_CODE_PACKAGES, {\n input: {\n codePackages: inputs,\n },\n });\n logger.info(\n colors.green(`Successfully updated ${inputs.length} code packages!`),\n );\n return codePackages;\n}\n\n/**\n * Uploads silo discovery results for Transcend to classify\n *\n * @param client - GraphQL Client\n * @param codePackages - Packages to upload\n * @param concurrency - How many concurrent requests to make\n * @returns True if successful, false if any updates failed, or an error occurs\n */\nexport async function syncCodePackages(\n client: GraphQLClient,\n codePackages: CodePackageInput[],\n concurrency = 20,\n): Promise<boolean> {\n let encounteredError = false;\n const [\n existingCodePackages,\n { softwareDevelopmentKits: existingSoftwareDevelopmentKits },\n ] = await Promise.all([\n // fetch all code packages\n fetchAllCodePackages(client),\n // make sure all SDKs exist\n syncSoftwareDevelopmentKits(\n client,\n uniqBy(\n codePackages\n .map(({ type, softwareDevelopmentKits = [] }) =>\n softwareDevelopmentKits.map(({ name }) => ({\n name,\n codePackageType: type,\n })),\n )\n .flat(),\n ({ name, codePackageType }) =>\n `${name}${LOOKUP_SPLIT_KEY}${codePackageType}`,\n ),\n concurrency,\n ),\n // make sure all Repositories exist\n syncRepositories(\n client,\n uniqBy(codePackages, 'repositoryName').map(\n ({ repositoryName }) =>\n ({\n name: repositoryName,\n url: `https://github.com/${repositoryName}`,\n } as RepositoryInput),\n ),\n ),\n ]);\n\n const softwareDevelopmentKitLookup = keyBy(\n existingSoftwareDevelopmentKits,\n ({ name, codePackageType }) =>\n `${name}${LOOKUP_SPLIT_KEY}${codePackageType}`,\n );\n const codePackagesLookup = keyBy(\n existingCodePackages,\n ({ name, type }) => `${name}${LOOKUP_SPLIT_KEY}${type}`,\n );\n\n // Determine which codePackages are new vs existing\n const mapCodePackagesToExisting = codePackages.map((codePackageInput) => [\n codePackageInput,\n codePackagesLookup[\n `${codePackageInput.name}${LOOKUP_SPLIT_KEY}${codePackageInput.type}`\n ]?.id,\n ]);\n\n // Create the new codePackages\n const newCodePackages = mapCodePackagesToExisting\n .filter(([, existing]) => !existing)\n .map(([codePackageInput]) => codePackageInput as CodePackageInput);\n try {\n logger.info(\n colors.magenta(\n `Creating \"${newCodePackages.length}\" new code packages...`,\n ),\n );\n await map(\n newCodePackages,\n async ({ softwareDevelopmentKits, ...codePackage }) => {\n await createCodePackage(client, {\n ...codePackage,\n ...(softwareDevelopmentKits\n ? {\n softwareDevelopmentKitIds: uniq(\n softwareDevelopmentKits.map(({ name }) => {\n const sdk =\n softwareDevelopmentKitLookup[\n `${name}${LOOKUP_SPLIT_KEY}${codePackage.type}`\n ];\n if (!sdk) {\n throw new Error(\n `Failed to find SDK with name: \"${name}\"`,\n );\n }\n return sdk.id;\n }),\n ),\n }\n : {}),\n });\n },\n {\n concurrency,\n },\n );\n logger.info(\n colors.green(\n `Successfully synced ${newCodePackages.length} code packages!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create code packages! - ${err.message}`));\n }\n\n // Update existing codePackages\n const existingCodePackageInputs = mapCodePackagesToExisting.filter(\n (x): x is [CodePackageInput, string] => !!x[1],\n );\n logger.info(\n colors.magenta(\n `Updating \"${existingCodePackageInputs.length}\" code packages...`,\n ),\n );\n const chunks = chunk(existingCodePackageInputs, CHUNK_SIZE);\n\n await mapSeries(chunks, async (chunk) => {\n try {\n await updateCodePackages(\n client,\n chunk.map(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n ([{ softwareDevelopmentKits, repositoryName, ...input }, id]) => ({\n ...input,\n ...(softwareDevelopmentKits\n ? {\n softwareDevelopmentKitIds: uniq(\n softwareDevelopmentKits.map(({ name }) => {\n const sdk =\n softwareDevelopmentKitLookup[\n `${name}${LOOKUP_SPLIT_KEY}${input.type}`\n ];\n if (!sdk) {\n throw new Error(\n `Failed to find SDK with name: \"${name}\"`,\n );\n }\n return sdk.id;\n }),\n ),\n }\n : {}),\n id,\n }),\n ),\n );\n logger.info(\n colors.green(`Successfully updated \"${chunk.length}\" code packages!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to update code packages! - ${err.message}`),\n );\n }\n });\n\n logger.info(colors.green(`Synced \"${codePackages.length}\" code packages!`));\n return !encounteredError;\n}\n","import {\n ConsentManageExperienceInput,\n ConsentManagerInput,\n} from '../../codecs';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport {\n UPDATE_CONSENT_MANAGER_DOMAINS,\n CREATE_CONSENT_MANAGER,\n UPDATE_LOAD_OPTIONS,\n UPDATE_CONSENT_MANAGER_PARTITION,\n UPDATE_CONSENT_MANAGER_VERSION,\n TOGGLE_TELEMETRY_PARTITION_STRATEGY,\n TOGGLE_UNKNOWN_COOKIE_POLICY,\n TOGGLE_CONSENT_PRECEDENCE,\n TOGGLE_UNKNOWN_REQUEST_POLICY,\n UPDATE_CONSENT_EXPERIENCE,\n CREATE_CONSENT_EXPERIENCE,\n UPDATE_CONSENT_MANAGER_THEME,\n} from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport {\n fetchConsentManagerId,\n fetchConsentManagerExperiences,\n} from './fetchConsentManagerId';\nimport { keyBy } from 'lodash-es';\nimport { map } from '../bluebird';\nimport {\n InitialViewState,\n OnConsentExpiry,\n} from '@transcend-io/airgap.js-types';\nimport { logger } from '../../logger';\nimport { fetchPrivacyCenterId } from './fetchPrivacyCenterId';\nimport { fetchPartitions } from './syncPartitions';\nimport { fetchAllPurposes } from './fetchAllPurposes';\n\nconst PURPOSES_LINK =\n 'https://app.transcend.io/consent-manager/regional-experiences/purposes';\n\n/**\n * Sync consent manager experiences up to Transcend\n *\n * @param client - GraphQL client\n * @param experiences - The experience inputs\n */\nexport async function syncConsentManagerExperiences(\n client: GraphQLClient,\n experiences: ConsentManageExperienceInput[],\n): Promise<void> {\n // Fetch existing experiences and\n const existingExperiences = await fetchConsentManagerExperiences(client);\n const experienceLookup = keyBy(existingExperiences, 'name');\n\n // Fetch existing purposes\n const purposes = await fetchAllPurposes(client);\n const purposeLookup = keyBy(purposes, 'trackingType');\n\n // Bulk update or create experiences\n await map(\n experiences,\n async (exp, ind) => {\n // Purpose IDs\n const purposeIds = exp.purposes?.map((purpose, ind2) => {\n const existingPurpose = purposeLookup[purpose.trackingType];\n if (!existingPurpose) {\n throw new Error(\n `Invalid purpose trackingType provided at consentManager.experiences[${ind}].purposes[${ind2}]: ` +\n `${purpose.trackingType}. See list of valid purposes ${PURPOSES_LINK}`,\n );\n }\n return existingPurpose.id;\n });\n const optedOutPurposeIds = exp.optedOutPurposes?.map((purpose, ind2) => {\n const existingPurpose = purposeLookup[purpose.trackingType];\n if (!existingPurpose) {\n throw new Error(\n `Invalid purpose trackingType provided at consentManager.experiences[${ind}].optedOutPurposes[${ind2}]: ` +\n `${purpose.trackingType}. See list of valid purposes ${PURPOSES_LINK}`,\n );\n }\n return existingPurpose.id;\n });\n\n // update experience\n const existingExperience = experienceLookup[exp.name];\n if (existingExperience) {\n await makeGraphQLRequest(client, UPDATE_CONSENT_EXPERIENCE, {\n input: {\n id: existingExperience.id,\n name: exp.displayName,\n regions: exp.regions,\n operator: exp.operator,\n onConsentExpiry: exp.onConsentExpiry,\n consentExpiry: exp.consentExpiry,\n displayPriority:\n exp.displayPriority !== existingExperience.displayPriority\n ? exp.displayPriority\n : undefined,\n viewState: exp.viewState,\n purposes: purposeIds,\n optedOutPurposes: optedOutPurposeIds,\n browserLanguages: exp.browserLanguages,\n browserTimeZones: exp.browserTimeZones,\n },\n });\n logger.info(\n colors.green(`Successfully synced consent experience \"${exp.name}\"!`),\n );\n } else {\n // create new experience\n await makeGraphQLRequest(client, CREATE_CONSENT_EXPERIENCE, {\n input: {\n name: exp.name,\n displayName: exp.displayName,\n regions: exp.regions,\n operator: exp.operator,\n onConsentExpiry: exp.onConsentExpiry || OnConsentExpiry.Prompt,\n consentExpiry: exp.consentExpiry,\n displayPriority: exp.displayPriority,\n viewState: exp.viewState || InitialViewState.Hidden,\n purposes: purposeIds || [],\n optedOutPurposes: optedOutPurposeIds || [],\n browserLanguages: exp.browserLanguages,\n browserTimeZones: exp.browserTimeZones,\n },\n });\n logger.info(\n colors.green(\n `Successfully created consent experience \"${exp.name}\"!`,\n ),\n );\n }\n },\n {\n concurrency: 10,\n },\n );\n}\n\n/**\n * Sync the consent manager\n *\n * @param client - GraphQL client\n * @param consentManager - The consent manager input\n */\nexport async function syncConsentManager(\n client: GraphQLClient,\n consentManager: ConsentManagerInput,\n): Promise<void> {\n let airgapBundleId: string;\n\n // ensure the consent manager is created and deployed\n try {\n airgapBundleId = await fetchConsentManagerId(client, 1);\n } catch (err) {\n // TODO: https://transcend.height.app/T-23778\n if (err.message.includes('AirgapBundle not found')) {\n const privacyCenterId = await fetchPrivacyCenterId(client);\n\n const { createConsentManager } = await makeGraphQLRequest<{\n /** Create consent manager */\n createConsentManager: {\n /** Consent manager */\n consentManager: {\n /** ID */\n id: string;\n };\n };\n }>(client, CREATE_CONSENT_MANAGER, {\n domains: consentManager.domains,\n privacyCenterId,\n });\n airgapBundleId = createConsentManager.consentManager.id;\n } else {\n throw err;\n }\n }\n\n // sync domains\n if (consentManager.domains) {\n await makeGraphQLRequest(client, UPDATE_CONSENT_MANAGER_DOMAINS, {\n domains: consentManager.domains,\n airgapBundleId,\n });\n }\n\n // sync partition\n if (consentManager.partition) {\n const partitions = await fetchPartitions(client);\n const partitionToUpdate = partitions.find(\n (part) => part.name === consentManager.partition,\n );\n if (!partitionToUpdate) {\n throw new Error(\n `Partition \"${consentManager.partition}\" not found. Please create the partition first.`,\n );\n }\n await makeGraphQLRequest(client, UPDATE_CONSENT_MANAGER_PARTITION, {\n partitionId: partitionToUpdate.id,\n airgapBundleId,\n });\n }\n\n if (consentManager.version) {\n await makeGraphQLRequest(client, UPDATE_CONSENT_MANAGER_VERSION, {\n airgapBundleId,\n version: consentManager.version,\n });\n }\n\n // sync signed IAB agreement\n if (consentManager.signedIabAgreement) {\n await makeGraphQLRequest(client, UPDATE_LOAD_OPTIONS, {\n input: {\n id: airgapBundleId,\n ...(consentManager.signedIabAgreement\n ? { signedIabAgreement: consentManager.signedIabAgreement }\n : {}),\n },\n });\n }\n\n // sync default request policy\n if (consentManager.unknownRequestPolicy) {\n await makeGraphQLRequest(client, TOGGLE_UNKNOWN_REQUEST_POLICY, {\n input: {\n id: airgapBundleId,\n unknownRequestPolicy: consentManager.unknownRequestPolicy,\n },\n });\n }\n\n // sync default cookie policy\n if (consentManager.unknownRequestPolicy) {\n await makeGraphQLRequest(client, TOGGLE_UNKNOWN_COOKIE_POLICY, {\n input: {\n id: airgapBundleId,\n unknownCookiePolicy: consentManager.unknownCookiePolicy,\n },\n });\n }\n\n // sync telemetry partition strategy\n if (consentManager.telemetryPartitioning) {\n await makeGraphQLRequest(client, TOGGLE_TELEMETRY_PARTITION_STRATEGY, {\n input: {\n id: airgapBundleId,\n strategy: consentManager.telemetryPartitioning,\n },\n });\n }\n\n // sync telemetry partition strategy\n if (consentManager.consentPrecedence) {\n await makeGraphQLRequest(client, TOGGLE_CONSENT_PRECEDENCE, {\n input: {\n id: airgapBundleId,\n consentPrecedence: consentManager.consentPrecedence,\n },\n });\n }\n\n // Update experience configurations\n if (consentManager.experiences) {\n await syncConsentManagerExperiences(client, consentManager.experiences);\n }\n\n // update theme\n if (consentManager.theme) {\n await makeGraphQLRequest(client, UPDATE_CONSENT_MANAGER_THEME, {\n input: {\n airgapBundleId,\n ...consentManager.theme,\n },\n });\n }\n\n // TODO: https://transcend.height.app/T-23875\n // syncEndpoint: string;\n // TODO: https://transcend.height.app/T-23919\n // syncGroups: string;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { logger } from '../../logger';\nimport { CookieInput } from '../../codecs';\nimport colors from 'colors';\nimport { UPDATE_OR_CREATE_COOKIES } from './gqls';\nimport { chunk } from 'lodash-es';\nimport { fetchConsentManagerId } from './fetchConsentManagerId';\nimport { mapSeries } from '../bluebird';\n// import { keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nconst MAX_PAGE_SIZE = 100;\n\n/**\n * Update or create cookies that already existed\n *\n * @param client - GraphQL client\n * @param cookieInputs - List of cookie input\n */\nexport async function updateOrCreateCookies(\n client: GraphQLClient,\n cookieInputs: CookieInput[],\n): Promise<void> {\n const airgapBundleId = await fetchConsentManagerId(client);\n\n // TODO: https://transcend.height.app/T-19841 - add with custom purposes\n // const purposes = await fetchAllPurposes(client);\n // const purposeNameToId = keyBy(purposes, 'name');\n\n await mapSeries(chunk(cookieInputs, MAX_PAGE_SIZE), async (page) => {\n await makeGraphQLRequest(client, UPDATE_OR_CREATE_COOKIES, {\n airgapBundleId,\n cookies: page.map((cookie) => ({\n name: cookie.name,\n trackingPurposes:\n cookie.trackingPurposes && cookie.trackingPurposes.length > 0\n ? cookie.trackingPurposes\n : undefined,\n // TODO: https://transcend.height.app/T-19841 - add with custom purposes\n // purposeIds: cookie.trackingPurposes\n // ? cookie.trackingPurposes\n // .filter((purpose) => purpose !== 'Unknown')\n // .map((purpose) => purposeNameToId[purpose].id)\n // : undefined,\n description: cookie.description,\n service: cookie.service,\n status: cookie.status,\n attributes: cookie.attributes,\n isRegex: cookie.isRegex,\n // TODO: https://transcend.height.app/T-23718\n // owners,\n // teams,\n })),\n });\n });\n}\n\n/**\n * Sync the set of cookies from the YML interface into the product\n *\n * @param client - GraphQL client\n * @param cookies - Cookies to sync\n * @returns True upon success, false upon failure\n */\nexport async function syncCookies(\n client: GraphQLClient,\n cookies: CookieInput[],\n): Promise<boolean> {\n let encounteredError = false;\n logger.info(colors.magenta(`Syncing \"${cookies.length}\" cookies...`));\n\n // Ensure no duplicates are being uploaded\n const notUnique = cookies.filter(\n (cookie) =>\n cookies.filter(\n (cook) => cookie.name === cook.name && cookie.isRegex === cook.isRegex,\n ).length > 1,\n );\n if (notUnique.length > 0) {\n throw new Error(\n `Failed to upload cookies as there were non-unique entries found: ${notUnique\n .map(({ name }) => name)\n .join(',')}`,\n );\n }\n\n try {\n logger.info(colors.magenta(`Upserting \"${cookies.length}\" new cookies...`));\n await updateOrCreateCookies(client, cookies);\n logger.info(colors.green(`Successfully synced ${cookies.length} cookies!`));\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create cookies! - ${err.message}`));\n }\n\n return !encounteredError;\n}\n","import { DataCategoryInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport { UPDATE_DATA_SUB_CATEGORIES, CREATE_DATA_SUB_CATEGORY } from './gqls';\nimport { logger } from '../../logger';\nimport { keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport colors from 'colors';\nimport {\n fetchAllDataCategories,\n DataSubCategory,\n} from './fetchAllDataCategories';\n\n/**\n * Input to create a new data category\n *\n * @param client - GraphQL client\n * @param dataCategory - Input\n * @returns Created data category\n */\nexport async function createDataCategory(\n client: GraphQLClient,\n dataCategory: DataCategoryInput,\n): Promise<Pick<DataSubCategory, 'id' | 'name' | 'category'>> {\n const input = {\n name: dataCategory.name,\n category: dataCategory.category,\n description: dataCategory.description,\n // TODO: https://transcend.height.app/T-31994 - add attributes, teams, owners\n };\n\n const { createDataCategory } = await makeGraphQLRequest<{\n /** Create data category mutation */\n createDataCategory: {\n /** Created data category */\n dataCategory: DataSubCategory;\n };\n }>(client, CREATE_DATA_SUB_CATEGORY, {\n input,\n });\n return createDataCategory.dataCategory;\n}\n\n/**\n * Input to update data categories\n *\n * @param client - GraphQL client\n * @param dataCategoryIdPairs - [DataCategoryInput, dataCategoryId] list\n */\nexport async function updateDataCategories(\n client: GraphQLClient,\n dataCategoryIdPairs: [DataCategoryInput, string][],\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_DATA_SUB_CATEGORIES, {\n input: {\n dataSubCategories: dataCategoryIdPairs.map(([dataCategory, id]) => ({\n id,\n description: dataCategory.description,\n // TODO: https://transcend.height.app/T-31994 - add teams, owners\n attributes: dataCategory.attributes,\n })),\n },\n });\n}\n\n/**\n * Sync the data inventory data categories\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncDataCategories(\n client: GraphQLClient,\n inputs: DataCategoryInput[],\n): Promise<boolean> {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${inputs.length}\" data categories...`));\n\n let encounteredError = false;\n\n // Fetch existing\n const existingDataCategories = await fetchAllDataCategories(client);\n\n // Look up by name\n const dataCategoryByName: {\n [k in string]: Pick<DataSubCategory, 'id' | 'name' | 'category'>;\n } = keyBy(\n existingDataCategories,\n ({ name, category }) => `${name}:${category}`,\n );\n\n // Create new data categories\n const newDataCategories = inputs.filter(\n (input) => !dataCategoryByName[`${input.name}:${input.category}`],\n );\n\n // Create new data categories\n await mapSeries(newDataCategories, async (dataCategory) => {\n try {\n const newDataCategory = await createDataCategory(client, dataCategory);\n dataCategoryByName[\n `${newDataCategory.name}:${newDataCategory.category}`\n ] = newDataCategory;\n logger.info(\n colors.green(\n `Successfully synced data category \"${dataCategory.name}\"!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync data category \"${dataCategory.name}\"! - ${err.message}`,\n ),\n );\n }\n });\n\n // Update all data categories\n try {\n logger.info(colors.magenta(`Updating \"${inputs.length}\" data categories!`));\n await updateDataCategories(\n client,\n inputs.map((input) => [\n input,\n dataCategoryByName[`${input.name}:${input.category}`].id,\n ]),\n );\n logger.info(\n colors.green(`Successfully synced \"${inputs.length}\" data categories!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync \"${inputs.length}\" data categories ! - ${err.message}`,\n ),\n );\n }\n\n return !encounteredError;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { CREATE_DATA_FLOWS, UPDATE_DATA_FLOWS } from './gqls';\nimport { chunk } from 'lodash-es';\nimport { mapSeries } from '../bluebird';\nimport { DataFlowInput } from '../../codecs';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { fetchConsentManagerId } from './fetchConsentManagerId';\nimport { logger } from '../../logger';\nimport colors from 'colors';\nimport { fetchAllDataFlows } from './fetchAllDataFlows';\nimport { ConsentTrackerStatus } from '@transcend-io/privacy-types';\n\nconst MAX_PAGE_SIZE = 100;\n\n/**\n * Update data flows that already existed\n *\n * @param client - GraphQL client\n * @param dataFlowInputs - [DataFlowInput, Data Flow ID] mappings to update\n * @param classifyService - classify service if missing\n */\nexport async function updateDataFlows(\n client: GraphQLClient,\n dataFlowInputs: [DataFlowInput, string][],\n classifyService = false,\n): Promise<void> {\n const airgapBundleId = await fetchConsentManagerId(client);\n\n // TODO: https://transcend.height.app/T-19841 - add with custom purposes\n // const purposes = await fetchAllPurposes(client);\n // const purposeNameToId = keyBy(purposes, 'name');\n\n await mapSeries(chunk(dataFlowInputs, MAX_PAGE_SIZE), async (page) => {\n await makeGraphQLRequest(client, UPDATE_DATA_FLOWS, {\n airgapBundleId,\n dataFlows: page.map(([flow, id]) => ({\n id,\n value: flow.value,\n type: flow.type,\n trackingType:\n flow.trackingPurposes && flow.trackingPurposes.length > 0\n ? flow.trackingPurposes\n : undefined,\n // TODO: https://transcend.height.app/T-19841 - add with custom purposes\n // purposeIds: flow.trackingPurposes\n // ? flow.trackingPurposes\n // .filter((purpose) => purpose !== 'Unknown')\n // .map((purpose) => purposeNameToId[purpose].id)\n // : undefined,\n description: flow.description,\n service: flow.service,\n status: flow.status,\n attributes: flow.attributes,\n // TODO: https://transcend.height.app/T-23718\n // owners,\n // teams,\n })),\n classifyService,\n });\n });\n}\n\n/**\n * Create new data flows\n *\n * @param client - GraphQL client\n * @param dataFlowInputs - List of data flows to create\n * @param classifyService - classify service if missing\n */\nexport async function createDataFlows(\n client: GraphQLClient,\n dataFlowInputs: DataFlowInput[],\n classifyService = false,\n): Promise<void> {\n const airgapBundleId = await fetchConsentManagerId(client);\n // TODO: https://transcend.height.app/T-19841 - add with custom purposes\n // const purposes = await fetchAllPurposes(client);\n // const purposeNameToId = keyBy(purposes, 'name');\n await mapSeries(chunk(dataFlowInputs, MAX_PAGE_SIZE), async (page) => {\n await makeGraphQLRequest(client, CREATE_DATA_FLOWS, {\n airgapBundleId,\n dataFlows: page.map((flow) => ({\n value: flow.value,\n type: flow.type,\n trackingType:\n flow.trackingPurposes && flow.trackingPurposes.length > 0\n ? flow.trackingPurposes\n : undefined,\n // TODO: https://transcend.height.app/T-19841 - add with custom purposes\n // purposeIds: flow.trackingPurposes\n // ? flow.trackingPurposes\n // .filter((purpose) => purpose !== 'Unknown')\n // .map((purpose) => purposeNameToId[purpose].id)\n // : undefined,\n description: flow.description,\n service: flow.service,\n status: flow.status,\n attributes: flow.attributes,\n // TODO: https://transcend.height.app/T-23718\n // owners,\n // teams,\n })),\n dropMatchingDataFlowsInTriage: true,\n classifyService,\n });\n });\n}\n\n/**\n * Sync data flow configurations into Transcend\n *\n * @param client - GraphQL client\n * @param dataFlows - The data flows to upload\n * @param classifyService - When true, auto classify the service based on the data flow value\n * @returns True if the command ran successfully, returns false if an error occurred\n */\nexport async function syncDataFlows(\n client: GraphQLClient,\n dataFlows: DataFlowInput[],\n classifyService: boolean,\n): Promise<boolean> {\n let encounteredError = false;\n logger.info(colors.magenta(`Syncing \"${dataFlows.length}\" data flows...`));\n\n // Ensure no duplicates are being uploaded\n // De-dupe the data flows based on [value, type]\n const notUnique = dataFlows.filter(\n (dataFlow) =>\n dataFlows.filter(\n (flow) => dataFlow.value === flow.value && dataFlow.type === flow.type,\n ).length > 1,\n );\n\n // Throw error to prompt user to de-dupe before uploading\n if (notUnique.length > 0) {\n throw new Error(\n `Failed to upload data flows as there were non-unique entries found: ${notUnique\n .map(({ value }) => value)\n .join(',')}`,\n );\n }\n\n // Fetch existing data flows to determine whether we are creating a new data flow\n // or updating an existing data flow\n logger.info(colors.magenta('Fetching data flows...'));\n const [existingLiveDataFlows, existingInReviewDataFlows] = await Promise.all([\n fetchAllDataFlows(client, ConsentTrackerStatus.Live),\n fetchAllDataFlows(client, ConsentTrackerStatus.NeedsReview),\n ]);\n const allDataFlows = [...existingLiveDataFlows, ...existingInReviewDataFlows];\n\n // Determine which data flows are new vs existing\n const mapDataFlowsToExisting = dataFlows.map((dataFlow) => [\n dataFlow,\n allDataFlows.find(\n (flow) => dataFlow.value === flow.value && dataFlow.type === flow.type,\n )?.id,\n ]);\n\n // Create the new data flows\n const newDataFlows = mapDataFlowsToExisting\n .filter(([, existing]) => !existing)\n .map(([flow]) => flow as DataFlowInput);\n try {\n logger.info(\n colors.magenta(`Creating \"${newDataFlows.length}\" new data flows...`),\n );\n await createDataFlows(client, newDataFlows, classifyService);\n logger.info(\n colors.green(`Successfully synced ${newDataFlows.length} data flows!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create data flows! - ${err.message}`));\n }\n\n // Update existing data flows\n const existingDataFlows = mapDataFlowsToExisting.filter(\n (x): x is [DataFlowInput, string] => !!x[1],\n );\n try {\n logger.info(\n colors.magenta(`Updating \"${existingDataFlows.length}\" data flows...`),\n );\n await updateDataFlows(client, existingDataFlows, classifyService);\n logger.info(\n colors.green(\n `Successfully updated \"${existingDataFlows.length}\" data flows!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create data flows! - ${err.message}`));\n }\n\n logger.info(colors.green(`Synced \"${dataFlows.length}\" data flows!`));\n\n // Return true upon success\n return !encounteredError;\n}\n","import { DataSubjectInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { UPDATE_DATA_SUBJECT, TOGGLE_DATA_SUBJECT } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\n/**\n * Sync the data subjects\n *\n * @param client - GraphQL client\n * @param options - Options\n */\nexport async function syncDataSubject(\n client: GraphQLClient,\n {\n dataSubject,\n dataSubjectId,\n skipPublish = false,\n }: {\n /** DataSubject update input */\n dataSubject: DataSubjectInput;\n /** Existing data subject Id */\n dataSubjectId: string;\n /** When true, skip publishing to privacy center */\n skipPublish?: boolean;\n },\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_DATA_SUBJECT, {\n input: {\n id: dataSubjectId,\n title: dataSubject.title,\n adminDashboardDefaultSilentMode:\n dataSubject.adminDashboardDefaultSilentMode,\n actions: dataSubject.actions,\n skipPublish: skipPublish && typeof dataSubject.active === 'undefined',\n },\n });\n\n if (typeof dataSubject.active === 'boolean') {\n await makeGraphQLRequest(client, TOGGLE_DATA_SUBJECT, {\n input: {\n id: dataSubjectId,\n active: dataSubject.active,\n skipPublish,\n },\n });\n }\n}\n","import { IdentifierInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { UPDATE_IDENTIFIER } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport type { DataSubject } from './fetchDataSubjects';\n\n/**\n * Sync the consent manager\n *\n * @param client - GraphQL client\n * @param options - Options\n */\nexport async function syncIdentifier(\n client: GraphQLClient,\n {\n identifier,\n dataSubjectsByName,\n identifierId,\n skipPublish = false,\n }: {\n /** Identifier update input */\n identifier: IdentifierInput;\n /** Data subject lookup by name */\n dataSubjectsByName: { [k in string]: DataSubject };\n /** Existing identifier Id */\n identifierId: string;\n /** When true, skip publishing to privacy center */\n skipPublish?: boolean;\n },\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_IDENTIFIER, {\n input: {\n id: identifierId,\n selectOptions: identifier.selectOptions,\n isRequiredInForm: identifier.isRequiredInForm,\n regex: identifier.regex,\n placeholder: identifier.placeholder,\n displayTitle: identifier.displayTitle,\n displayDescription: identifier.displayDescription,\n displayOrder: identifier.displayOrder,\n isUniqueOnPreferenceStore: identifier.isUniqueOnPreferenceStore,\n privacyCenterVisibility: identifier.privacyCenterVisibility,\n dataSubjectIds: identifier.dataSubjects\n ? identifier.dataSubjects.map((type) => dataSubjectsByName[type].id)\n : undefined,\n skipPublish,\n },\n });\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { logger } from '../../logger';\nimport { IntlMessageInput } from '../../codecs';\nimport colors from 'colors';\nimport { UPDATE_INTL_MESSAGES } from './gqls';\nimport { chunk } from 'lodash-es';\nimport { mapSeries } from '../bluebird';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nconst MAX_PAGE_SIZE = 100;\n\n/**\n * Update or create intl messages\n *\n * @param client - GraphQL client\n * @param messageInputs - List of message inputs\n */\nexport async function updateIntlMessages(\n client: GraphQLClient,\n messageInputs: IntlMessageInput[],\n): Promise<void> {\n // Batch update messages\n await mapSeries(chunk(messageInputs, MAX_PAGE_SIZE), async (page) => {\n await makeGraphQLRequest(client, UPDATE_INTL_MESSAGES, {\n messages: page.map((message) => ({\n ...(message.id.includes('.') ? {} : { id: message.id }),\n defaultMessage: message.defaultMessage,\n targetReactIntlId: message.targetReactIntlId,\n translations: !message.translations\n ? undefined\n : Object.entries(message.translations).map(([locale, value]) => ({\n locale,\n value,\n })),\n })),\n });\n });\n}\n\n/**\n * Sync the set of messages from the YML interface into the product\n *\n * @param client - GraphQL client\n * @param messages - messages to sync\n * @returns True upon success, false upon failure\n */\nexport async function syncIntlMessages(\n client: GraphQLClient,\n messages: IntlMessageInput[],\n): Promise<boolean> {\n let encounteredError = false;\n logger.info(colors.magenta(`Syncing \"${messages.length}\" messages...`));\n\n // Ensure no duplicates are being uploaded\n const notUnique = messages.filter(\n (message) => messages.filter((pol) => message.id === pol.id).length > 1,\n );\n if (notUnique.length > 0) {\n throw new Error(\n `Failed to upload messages as there were non-unique entries found: ${notUnique\n .map(({ id }) => id)\n .join(',')}`,\n );\n }\n\n try {\n logger.info(\n colors.magenta(`Upserting \"${messages.length}\" new messages...`),\n );\n await updateIntlMessages(client, messages);\n logger.info(\n colors.green(`Successfully synced ${messages.length} messages!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create messages! - ${err.message}`));\n }\n\n return !encounteredError;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { logger } from '../../logger';\nimport { PolicyInput } from '../../codecs';\nimport colors from 'colors';\nimport { UPDATE_POLICIES } from './gqls';\nimport { chunk, keyBy } from 'lodash-es';\nimport { mapSeries } from '../bluebird';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { fetchPrivacyCenterId } from './fetchPrivacyCenterId';\nimport { fetchAllPolicies } from './fetchAllPolicies';\n\nconst MAX_PAGE_SIZE = 100;\n\n/**\n * Update or create policies\n *\n * @param client - GraphQL client\n * @param policyInputs - List of policy input\n */\nexport async function updatePolicies(\n client: GraphQLClient,\n policyInputs: [PolicyInput, string | undefined][],\n): Promise<void> {\n const privacyCenterId = await fetchPrivacyCenterId(client);\n\n // Batch update policies\n await mapSeries(chunk(policyInputs, MAX_PAGE_SIZE), async (page) => {\n await makeGraphQLRequest(client, UPDATE_POLICIES, {\n privacyCenterId,\n policies: page.map(([policy, policyId]) => ({\n id: policyId,\n title: policy.title,\n disableEffectiveOn: policy.disableEffectiveOn,\n disabledLocales: policy.disabledLocales,\n ...(policy.effectiveOn || policy.content\n ? {\n version: {\n ...(policy.effectiveOn\n ? { effectiveOn: policy.effectiveOn }\n : {}),\n ...(policy.content\n ? {\n content: {\n defaultMessage: policy.content,\n },\n }\n : {}),\n },\n }\n : {}),\n })),\n });\n });\n}\n\n/**\n * Sync the set of policies from the YML interface into the product\n *\n * @param client - GraphQL client\n * @param policies - policies to sync\n * @returns True upon success, false upon failure\n */\nexport async function syncPolicies(\n client: GraphQLClient,\n policies: PolicyInput[],\n): Promise<boolean> {\n let encounteredError = false;\n logger.info(colors.magenta(`Syncing \"${policies.length}\" policies...`));\n\n // Ensure no duplicates are being uploaded\n const notUnique = policies.filter(\n (policy) => policies.filter((pol) => policy.title === pol.title).length > 1,\n );\n if (notUnique.length > 0) {\n throw new Error(\n `Failed to upload policies as there were non-unique entries found: ${notUnique\n .map(({ title }) => title)\n .join(',')}`,\n );\n }\n\n // Grab existing policies\n const existingPolicies = await fetchAllPolicies(client);\n const policiesById = keyBy(\n existingPolicies,\n ({ title }) => title.defaultMessage,\n );\n\n try {\n logger.info(\n colors.magenta(`Upserting \"${policies.length}\" new policies...`),\n );\n await updatePolicies(\n client,\n policies.map((policy) => [policy, policiesById[policy.title]?.id]),\n );\n logger.info(\n colors.green(`Successfully synced ${policies.length} policies!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create policies! - ${err.message}`));\n }\n\n return !encounteredError;\n}\n","import { PrivacyCenterInput } from '../../codecs';\nimport { logger } from '../../logger';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { UPDATE_PRIVACY_CENTER } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { fetchPrivacyCenterId } from './fetchPrivacyCenterId';\n\n/**\n * Sync the privacy center\n *\n * @param client - GraphQL client\n * @param privacyCenter - The privacy center input\n * @returns Whether the privacy center was synced successfully\n */\nexport async function syncPrivacyCenter(\n client: GraphQLClient,\n privacyCenter: PrivacyCenterInput,\n): Promise<boolean> {\n let encounteredError = false;\n logger.info(colors.magenta('Syncing privacy center...'));\n\n // Grab the privacy center ID\n const privacyCenterId = await fetchPrivacyCenterId(client);\n\n try {\n await makeGraphQLRequest(client, UPDATE_PRIVACY_CENTER, {\n input: {\n privacyCenterId,\n transformAccessReportJsonToCsv:\n privacyCenter.transformAccessReportJsonToCsv,\n useCustomEmailDomain: privacyCenter.useCustomEmailDomain,\n useNoReplyEmailAddress: privacyCenter.useNoReplyEmailAddress,\n replyToEmail: privacyCenter.replyToEmail,\n supportEmail: privacyCenter.supportEmail,\n preferBrowserDefaultLocale: privacyCenter.preferBrowserDefaultLocale,\n defaultLocale: privacyCenter.defaultLocale,\n locales: privacyCenter.locales,\n showMarketingPreferences: privacyCenter.showMarketingPreferences,\n showManageYourPrivacy: privacyCenter.showManageYourPrivacy,\n showPolicies: privacyCenter.showPolicies,\n showConsentManager: privacyCenter.showConsentManager,\n showDataFlows: privacyCenter.showDataFlows,\n showCookies: privacyCenter.showCookies,\n showTrackingTechnologies: privacyCenter.showTrackingTechnologies,\n showPrivacyRequestButton: privacyCenter.showPrivacyRequestButton,\n isDisabled: privacyCenter.isDisabled,\n ...(privacyCenter.theme\n ? {\n colorPalette: privacyCenter.theme.colors,\n componentStyles: privacyCenter.theme.componentStyles,\n textStyles: privacyCenter.theme.textStyles,\n }\n : {}),\n },\n });\n logger.info(colors.green('Successfully synced privacy center!'));\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to create privacy center! - ${err.message}`),\n );\n }\n\n return !encounteredError;\n}\n","import { ProcessingActivityInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport {\n UPDATE_PROCESSING_ACTIVITIES,\n CREATE_PROCESSING_ACTIVITY,\n} from './gqls';\nimport { logger } from '../../logger';\nimport { keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport colors from 'colors';\nimport {\n fetchAllProcessingActivities,\n ProcessingActivity,\n} from './fetchAllProcessingActivities';\n\n/**\n * Create a new processing activity, setting only title and description\n *\n * @param client - GraphQL client\n * @param processingActivity - Input\n * @returns Created processingActivity\n */\nasync function createProcessingActivity(\n client: GraphQLClient,\n processingActivity: ProcessingActivityInput,\n): Promise<Pick<ProcessingActivity, 'id' | 'title'>> {\n const input = {\n title: processingActivity.title,\n description: processingActivity.description,\n };\n\n const { createProcessingActivity } = await makeGraphQLRequest<{\n /** Create processingActivity mutation */\n createProcessingActivity: {\n /** Created processingActivity */\n processingActivity: ProcessingActivity;\n };\n }>(client, CREATE_PROCESSING_ACTIVITY, {\n input,\n });\n return createProcessingActivity.processingActivity;\n}\n\n/**\n * Update a list of processing activities.\n *\n * @param client - GraphQL client\n * @param processingActivityIdPairs - [ProcessingActivityInput, processingActivityId] list\n */\nasync function updateProcessingActivities(\n client: GraphQLClient,\n processingActivityIdPairs: [ProcessingActivityInput, string][],\n): Promise<void> {\n const invalidProcessingActivityTitles = processingActivityIdPairs\n .filter(([, id]) => id === undefined)\n .map(([{ title }]) => title);\n if (invalidProcessingActivityTitles.length > 0) {\n // We always attempt to create processing activities before updating them, but if creation failed\n // (for example, due to insufficient scope), this provides a better error message\n throw new Error(\n `The following ${\n invalidProcessingActivityTitles.length\n } processing activities do not exist and thus can't be updated: \"${invalidProcessingActivityTitles.join(\n '\", \"',\n )}\"`,\n );\n }\n await makeGraphQLRequest(client, UPDATE_PROCESSING_ACTIVITIES, {\n input: {\n processingActivities: processingActivityIdPairs.map(\n ([\n {\n processingSubPurposes,\n dataSubCategories,\n saaSCategories,\n ...processingActivity\n },\n id,\n ]) => ({\n dataSubCategoryInputs: dataSubCategories?.map(\n ({ category, name }) => ({ category, name: name ?? '' }),\n ),\n processingPurposeSubCategoryInputs: processingSubPurposes?.map(\n ({ purpose, name }) => ({ purpose, name: name ?? 'Other' }),\n ),\n saaSCategoryTitles: saaSCategories,\n ...processingActivity,\n id,\n }),\n ),\n },\n });\n}\n\n/**\n * Sync the data inventory processing activities\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncProcessingActivities(\n client: GraphQLClient,\n inputs: ProcessingActivityInput[],\n): Promise<boolean> {\n let encounteredError = false;\n\n // Fetch existing\n logger.info(\n colors.magenta(`Syncing \"${inputs.length}\" processing activities...`),\n );\n const existingProcessingActivities = await fetchAllProcessingActivities(\n client,\n );\n\n // Look up by title\n const processingActivityByTitle: Record<\n string,\n Pick<ProcessingActivity, 'id' | 'title'>\n > = keyBy(existingProcessingActivities, 'title');\n\n // Create new processingActivities\n const newProcessingActivities = inputs.filter(\n (input) => !processingActivityByTitle[input.title],\n );\n if (newProcessingActivities.length > 0) {\n logger.info(\n colors.magenta(\n `Creating \"${newProcessingActivities.length}\" new processing activities...`,\n ),\n );\n }\n await mapSeries(newProcessingActivities, async (processingActivity) => {\n try {\n const newProcessingActivity = await createProcessingActivity(\n client,\n processingActivity,\n );\n // Augment processingActivityByTitle with newly-created processing activity\n processingActivityByTitle[newProcessingActivity.title] =\n newProcessingActivity;\n logger.info(\n colors.green(\n `Successfully created processing activity \"${processingActivity.title}\"!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to create processing activity \"${processingActivity.title}\"! - ${err.message}`,\n ),\n );\n }\n });\n\n // Update all processing activities\n try {\n logger.info(\n colors.magenta(`Updating \"${inputs.length}\" processing activities!`),\n );\n await updateProcessingActivities(\n client,\n inputs.map((input) => [\n input,\n // This processing activity might not exist if the `create` step failed\n processingActivityByTitle[input.title]?.id,\n ]),\n );\n logger.info(\n colors.green(\n `Successfully synced \"${inputs.length}\" processingActivities!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync \"${inputs.length}\" processingActivities! - ${err.message}`,\n ),\n );\n }\n\n return !encounteredError;\n}\n","import { ProcessingPurposeInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport {\n UPDATE_PROCESSING_PURPOSE_SUB_CATEGORIES,\n CREATE_PROCESSING_PURPOSE_SUB_CATEGORY,\n} from './gqls';\nimport { logger } from '../../logger';\nimport { keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport colors from 'colors';\nimport {\n fetchAllProcessingPurposes,\n ProcessingPurposeSubCategory,\n} from './fetchAllProcessingPurposes';\n\n/**\n * Input to create a new processing purpose\n *\n * @param client - GraphQL client\n * @param processingPurpose - Input\n * @returns Created processing purpose\n */\nexport async function createProcessingPurpose(\n client: GraphQLClient,\n processingPurpose: ProcessingPurposeInput,\n): Promise<Pick<ProcessingPurposeSubCategory, 'id' | 'name' | 'purpose'>> {\n const input = {\n name: processingPurpose.name,\n purpose: processingPurpose.purpose,\n description: processingPurpose.description,\n // TODO: https://transcend.height.app/T-31994 - add attributes, teams, owners\n };\n\n const { createProcessingPurposeSubCategory } = await makeGraphQLRequest<{\n /** Create processing purpose mutation */\n createProcessingPurposeSubCategory: {\n /** Created processing purpose */\n processingPurposeSubCategory: ProcessingPurposeSubCategory;\n };\n }>(client, CREATE_PROCESSING_PURPOSE_SUB_CATEGORY, {\n input,\n });\n return createProcessingPurposeSubCategory.processingPurposeSubCategory;\n}\n\n/**\n * Input to update processing purposes\n *\n * @param client - GraphQL client\n * @param processingPurposeIdPairs - [ProcessingPurposeInput, processingPurposeId] list\n */\nexport async function updateProcessingPurposes(\n client: GraphQLClient,\n processingPurposeIdPairs: [ProcessingPurposeInput, string][],\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_PROCESSING_PURPOSE_SUB_CATEGORIES, {\n input: {\n processingPurposeSubCategories: processingPurposeIdPairs.map(\n ([processingPurpose, id]) => ({\n id,\n description: processingPurpose.description,\n // TODO: https://transcend.height.app/T-31994 - add teams, owners\n attributes: processingPurpose.attributes,\n }),\n ),\n },\n });\n}\n\n/**\n * Sync the data inventory processing purposes\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncProcessingPurposes(\n client: GraphQLClient,\n inputs: ProcessingPurposeInput[],\n): Promise<boolean> {\n // Fetch existing\n logger.info(\n colors.magenta(`Syncing \"${inputs.length}\" processing purposes...`),\n );\n\n let encounteredError = false;\n\n // Fetch existing\n const existingProcessingPurposes = await fetchAllProcessingPurposes(client);\n\n // Look up by name\n const processingPurposeByName: {\n [k in string]: Pick<ProcessingPurposeSubCategory, 'id' | 'name'>;\n } = keyBy(\n existingProcessingPurposes,\n ({ name, purpose }) => `${name}:${purpose}`,\n );\n\n // Create new processing purposes\n const newProcessingPurposes = inputs.filter(\n (input) => !processingPurposeByName[`${input.name}:${input.purpose}`],\n );\n\n // Create new processing purposes\n await mapSeries(newProcessingPurposes, async (processingPurpose) => {\n try {\n const newProcessingPurpose = await createProcessingPurpose(\n client,\n processingPurpose,\n );\n processingPurposeByName[\n `${newProcessingPurpose.name}:${newProcessingPurpose.purpose}`\n ] = newProcessingPurpose;\n logger.info(\n colors.green(\n `Successfully synced processing purpose \"${processingPurpose.name}\"!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync processing purpose \"${processingPurpose.name}\"! - ${err.message}`,\n ),\n );\n }\n });\n\n // Update all processing purposes\n try {\n logger.info(\n colors.magenta(`Updating \"${inputs.length}\" processing purposes!`),\n );\n await updateProcessingPurposes(\n client,\n inputs.map((input) => [\n input,\n processingPurposeByName[`${input.name}:${input.purpose}`].id,\n ]),\n );\n logger.info(\n colors.green(\n `Successfully synced \"${inputs.length}\" processing purposes!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync \"${inputs.length}\" processing purposes ! - ${err.message}`,\n ),\n );\n }\n\n return !encounteredError;\n}\n","import { PromptInput } from '../../codecs';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { UPDATE_PROMPTS, CREATE_PROMPT } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { map } from '../bluebird';\nimport { fetchAllPrompts } from './fetchPrompts';\nimport { keyBy } from 'lodash-es';\nimport { logger } from '../../logger';\n\n/**\n * Create a new prompt\n *\n * @param client - GraphQL client\n * @param input - Prompt input\n * @returns Prompt ID\n */\nexport async function createPrompt(\n client: GraphQLClient,\n input: {\n /** Title of prompt */\n title: string;\n /** Prompt content */\n content: string;\n },\n): Promise<string> {\n const {\n createPrompt: { prompt },\n } = await makeGraphQLRequest<{\n /** createPrompt mutation */\n createPrompt: {\n /** Prompt */\n prompt: {\n /** ID */\n id: string;\n };\n };\n }>(client, CREATE_PROMPT, {\n // TODO: https://transcend.height.app/T-31994 - include models and groups, teams, users\n input,\n });\n logger.info(colors.green(`Successfully created prompt \"${input.title}\"!`));\n return prompt.id;\n}\n\n/**\n * Update a set of existing prompts\n *\n * @param client - GraphQL client\n * @param input - Prompt input\n */\nexport async function updatePrompts(\n client: GraphQLClient,\n input: [PromptInput, string][],\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_PROMPTS, {\n input: {\n prompts: input.map(([input, id]) => ({\n ...input,\n id,\n })),\n },\n });\n logger.info(colors.green(`Successfully updated ${input.length} prompts!`));\n}\n\n/**\n * Sync the prompts\n *\n * @param client - GraphQL client\n * @param prompts - Prompts\n * @param concurrency - Concurrency\n * @returns True if synced successfully\n */\nexport async function syncPrompts(\n client: GraphQLClient,\n prompts: PromptInput[],\n concurrency = 20,\n): Promise<boolean> {\n let encounteredError = false;\n logger.info(colors.magenta(`Syncing \"${prompts.length}\" prompts...`));\n\n // Index existing prompts\n const existing = await fetchAllPrompts(client);\n const promptByTitle = keyBy(existing, 'title');\n\n // Determine which prompts are new vs existing\n const mapPromptsToExisting = prompts.map((promptInput) => [\n promptInput,\n promptByTitle[promptInput.title]?.id,\n ]);\n\n // Create the new prompts\n const newPrompts = mapPromptsToExisting\n .filter(([, existing]) => !existing)\n .map(([promptInput]) => promptInput as PromptInput);\n try {\n logger.info(\n colors.magenta(`Creating \"${newPrompts.length}\" new prompts...`),\n );\n await map(\n newPrompts,\n async (prompt) => {\n await createPrompt(client, prompt);\n },\n {\n concurrency,\n },\n );\n logger.info(\n colors.green(`Successfully synced ${newPrompts.length} prompts!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create prompts! - ${err.message}`));\n }\n\n // Update existing prompts\n const existingPrompts = mapPromptsToExisting.filter(\n (x): x is [PromptInput, string] => !!x[1],\n );\n try {\n logger.info(\n colors.magenta(`Updating \"${existingPrompts.length}\" prompts...`),\n );\n await updatePrompts(client, existingPrompts);\n logger.info(\n colors.green(`Successfully updated \"${existingPrompts.length}\" prompts!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create prompts! - ${err.message}`));\n }\n\n logger.info(colors.green(`Synced \"${prompts.length}\" prompts!`));\n\n // Return true upon success\n return !encounteredError;\n}\n","import { VendorInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport { UPDATE_VENDORS, CREATE_VENDOR } from './gqls';\nimport { logger } from '../../logger';\nimport { keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport colors from 'colors';\nimport { fetchAllVendors, Vendor } from './fetchAllVendors';\n\n/**\n * Input to create a new vendor\n *\n * @param client - GraphQL client\n * @param vendor - Input\n * @returns Created vendor\n */\nexport async function createVendor(\n client: GraphQLClient,\n vendor: VendorInput,\n): Promise<Pick<Vendor, 'id' | 'title'>> {\n const input = {\n title: vendor.title,\n description: vendor.description,\n address: vendor.address,\n headquarterCountry: vendor.headquarterCountry,\n headquarterSubDivision: vendor.headquarterSubDivision,\n dataProcessingAgreementLink: vendor.dataProcessingAgreementLink,\n contactName: vendor.contactName,\n contactPhone: vendor.contactPhone,\n websiteUrl: vendor.websiteUrl,\n // TODO: https://transcend.height.app/T-31994 - add attributes, teams, owners\n };\n\n const { createVendor } = await makeGraphQLRequest<{\n /** Create vendor mutation */\n createVendor: {\n /** Created vendor */\n vendor: Vendor;\n };\n }>(client, CREATE_VENDOR, {\n input,\n });\n return createVendor.vendor;\n}\n\n/**\n * Input to update vendors\n *\n * @param client - GraphQL client\n * @param vendorIdParis - [VendorInput, vendorId] list\n */\nexport async function updateVendors(\n client: GraphQLClient,\n vendorIdParis: [VendorInput, string][],\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_VENDORS, {\n input: {\n vendors: vendorIdParis.map(([vendor, id]) => ({\n id,\n title: vendor.title,\n description: vendor.description,\n address: vendor.address,\n headquarterCountry: vendor.headquarterCountry,\n headquarterSubDivision: vendor.headquarterSubDivision,\n dataProcessingAgreementLink: vendor.dataProcessingAgreementLink,\n contactName: vendor.contactName,\n contactPhone: vendor.contactPhone,\n websiteUrl: vendor.websiteUrl,\n // TODO: https://transcend.height.app/T-31994 - add teams, owners\n attributes: vendor.attributes,\n })),\n },\n });\n}\n\n/**\n * Sync the data inventory vendors\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncVendors(\n client: GraphQLClient,\n inputs: VendorInput[],\n): Promise<boolean> {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${inputs.length}\" vendors...`));\n\n let encounteredError = false;\n\n // Fetch existing\n const existingVendors = await fetchAllVendors(client);\n\n // Look up by title\n const vendorByTitle: { [k in string]: Pick<Vendor, 'id' | 'title'> } = keyBy(\n existingVendors,\n 'title',\n );\n\n // Create new vendors\n const newVendors = inputs.filter((input) => !vendorByTitle[input.title]);\n\n // Create new vendors\n await mapSeries(newVendors, async (vendor) => {\n try {\n const newVendor = await createVendor(client, vendor);\n vendorByTitle[newVendor.title] = newVendor;\n logger.info(\n colors.green(`Successfully synced vendor \"${vendor.title}\"!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to sync vendor \"${vendor.title}\"! - ${err.message}`),\n );\n }\n });\n\n // Update all vendors\n try {\n logger.info(colors.magenta(`Updating \"${inputs.length}\" vendors!`));\n await updateVendors(\n client,\n inputs.map((input) => [input, vendorByTitle[input.title].id]),\n );\n logger.info(\n colors.green(`Successfully synced \"${inputs.length}\" vendors!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync \"${inputs.length}\" vendors ! - ${err.message}`,\n ),\n );\n }\n\n return !encounteredError;\n}\n","import { chunk } from 'lodash-es';\nimport { mapSeries } from '../bluebird';\nimport { ADD_SILO_DISCOVERY_RESULTS } from './gqls';\nimport { GraphQLClient } from 'graphql-request';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { SiloDiscoveryRawResults } from '../code-scanning/findFilesToScan';\n\nconst CHUNK_SIZE = 1000;\n\n/**\n * Uploads silo discovery results for Transcend to classify\n *\n * @param client - GraphQL Client\n * @param pluginId - pluginID to associate with the results\n * @param results - The results\n */\nexport async function uploadSiloDiscoveryResults(\n client: GraphQLClient,\n pluginId: string,\n results: SiloDiscoveryRawResults[],\n): Promise<void> {\n const chunks = chunk(results, CHUNK_SIZE);\n\n await mapSeries(chunks, async (rawResults) => {\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, ADD_SILO_DISCOVERY_RESULTS, {\n pluginId,\n rawResults,\n });\n });\n}\n","import { map } from '../bluebird';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport {\n UPDATE_PRIVACY_REQUEST,\n fetchAllRequests,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Mark a set of privacy requests to be in silent mode\n *\n * @param options - Options\n * @returns The number of requests marked silent\n */\nexport async function markSilentPrivacyRequests({\n requestActions,\n auth,\n requestIds,\n statuses = [\n RequestStatus.Compiling,\n RequestStatus.RequestMade,\n RequestStatus.Delayed,\n RequestStatus.Approving,\n RequestStatus.Secondary,\n RequestStatus.Enriching,\n RequestStatus.Waiting,\n RequestStatus.SecondaryApproving,\n ],\n createdAtAfter,\n createdAtBefore,\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** Transcend API key authentication */\n auth: string;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** The request statuses to mark silent */\n statuses?: RequestStatus[];\n /** The set of privacy requests to mark silent */\n requestIds?: string[];\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** 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 // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses,\n createdAtBefore,\n createdAtAfter,\n isSilent: false,\n requestIds,\n });\n\n // Notify Transcend\n logger.info(\n colors.magenta(`Marking \"${allRequests.length}\" as silent mode.`),\n );\n\n let total = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToMarkSilent) => {\n await makeGraphQLRequest(client, UPDATE_PRIVACY_REQUEST, {\n input: {\n id: requestToMarkSilent.id,\n isSilent: true,\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 marked ${total} requests as silent mode in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n return allRequests.length;\n}\n","import { getValues, getEntries } from '@transcend-io/type-utils';\nimport type { PersistedState } from '@transcend-io/persisted-state';\nimport inquirer from 'inquirer';\nimport { startCase } from 'lodash-es';\nimport {\n ColumnName,\n CachedFileState,\n IS_REQUIRED,\n CAN_APPLY_IN_BULK,\n} from './constants';\nimport { fuzzyMatchColumns } from './fuzzyMatchColumns';\n\n/**\n * Mapping from column name to request input parameter\n */\nexport type ColumnNameMap = {\n [k in ColumnName]?: string;\n};\n\n/**\n * Determine the mapping between columns in CSV\n *\n * @param columnNames - The set of column names\n * @param state - The cached file state used to map DSR inputs\n * @returns The column name mapping\n */\nexport async function mapCsvColumnsToApi(\n columnNames: string[],\n state: PersistedState<typeof CachedFileState>,\n): Promise<ColumnNameMap> {\n // Determine the columns that should be mapped\n const columnQuestions = getValues(ColumnName).filter(\n (name) => !state.getValue('columnNames', name),\n );\n\n // Skip mapping when everything is mapped\n const columnNameMap =\n columnQuestions.length === 0\n ? {}\n : // prompt questions to map columns\n await inquirer.prompt<{\n [k in ColumnName]?: string;\n }>(\n columnQuestions.map((name) => {\n const field = startCase(name.replace('ColumnName', ''));\n const matches = fuzzyMatchColumns(\n columnNames,\n field,\n IS_REQUIRED[name],\n !!CAN_APPLY_IN_BULK[name],\n );\n return {\n name,\n message: `Choose the column that will be used to map in the field: ${field}`,\n type: 'list',\n default: matches[0],\n choices: matches,\n };\n }),\n );\n\n await Promise.all(\n getEntries(columnNameMap).map(([k, v]) =>\n state.setValue(v, 'columnNames', k),\n ),\n );\n return columnNameMap;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport colors from 'colors';\nimport type { PersistedState } from '@transcend-io/persisted-state';\nimport {\n CompletedRequestStatus,\n RequestAction,\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\nimport {\n LOCALE_KEY,\n type LocaleValue,\n} from '@transcend-io/internationalization';\nimport { ObjByString } from '@transcend-io/type-utils';\nimport { logger } from '../../logger';\nimport { makeGraphQLRequest, DataSubject, DATA_SUBJECTS } from '../graphql';\nimport { CachedFileState, NONE, ColumnName } from './constants';\nimport { mapEnumValues } from './mapEnumValues';\nimport { ColumnNameMap } from './mapCsvColumnsToApi';\nimport { getUniqueValuesForColumn } from './getUniqueValuesForColumn';\n\n/**\n * Map the values in a CSV to the enum values in Transcend\n *\n * @param client - GraphQL client\n * @param requests - Set of privacy requests\n * @param options - Options\n */\nexport async function mapRequestEnumValues(\n client: GraphQLClient,\n requests: ObjByString[],\n {\n state,\n columnNameMap,\n }: {\n /** State value to write cache to */\n state: PersistedState<typeof CachedFileState>;\n /** Mapping of column names */\n columnNameMap: ColumnNameMap;\n },\n): Promise<void> {\n // Get mapped value\n const getMappedName = (attribute: ColumnName): string =>\n state.getValue('columnNames', attribute) || columnNameMap[attribute]!;\n\n // Fetch all data subjects in the organization\n const { internalSubjects } = await makeGraphQLRequest<{\n /** Query response */\n internalSubjects: DataSubject[];\n }>(client, DATA_SUBJECTS);\n\n // Map RequestAction\n logger.info(\n colors.magenta('Determining mapping of columns for request action'),\n );\n const requestTypeToRequestAction: { [k in string]: RequestAction } =\n await mapEnumValues(\n getUniqueValuesForColumn(requests, getMappedName(ColumnName.RequestType)),\n Object.values(RequestAction),\n state.getValue('requestTypeToRequestAction'),\n );\n await state.setValue(\n requestTypeToRequestAction,\n 'requestTypeToRequestAction',\n );\n\n // Map data subject type\n logger.info(colors.magenta('Determining mapping of columns for subject'));\n const subjectTypeToSubjectName: { [k in string]: string } =\n await mapEnumValues(\n getUniqueValuesForColumn(requests, getMappedName(ColumnName.SubjectType)),\n internalSubjects.map(({ type }) => type),\n state.getValue('subjectTypeToSubjectName'),\n );\n await state.setValue(subjectTypeToSubjectName, 'subjectTypeToSubjectName');\n\n // Map locale\n logger.info(colors.magenta('Determining mapping of columns for locale'));\n const languageToLocale: { [k in string]: LocaleValue } = await mapEnumValues(\n getUniqueValuesForColumn(requests, getMappedName(ColumnName.Locale)),\n Object.values(LOCALE_KEY),\n state.getValue('languageToLocale'),\n );\n await state.setValue(languageToLocale, 'languageToLocale');\n logger.info(\n colors.magenta('Determining mapping of columns for request status'),\n );\n\n // Map request status\n logger.info(\n colors.magenta('Determining mapping of columns for request status'),\n );\n const requestStatusColumn = getMappedName(ColumnName.RequestStatus);\n const statusToRequestStatus: {\n [k in string]: CompletedRequestStatus | typeof NONE;\n } =\n requestStatusColumn === NONE\n ? {}\n : await mapEnumValues(\n getUniqueValuesForColumn(requests, requestStatusColumn),\n [...Object.values(CompletedRequestStatus), NONE],\n state.getValue('statusToRequestStatus'),\n );\n await state.setValue(statusToRequestStatus, 'statusToRequestStatus');\n\n // Map country\n logger.info(colors.magenta('Determining mapping of columns for country'));\n const countryColumn = getMappedName(ColumnName.Country);\n const regionToCountry: {\n [k in string]: IsoCountryCode | typeof NONE;\n } =\n countryColumn === NONE\n ? {}\n : await mapEnumValues(\n getUniqueValuesForColumn(requests, countryColumn),\n [...Object.values(IsoCountryCode), NONE],\n state.getValue('regionToCountry'),\n );\n await state.setValue(regionToCountry, 'regionToCountry');\n\n // Map country sub division\n logger.info(\n colors.magenta('Determining mapping of columns for country sub division'),\n );\n const countrySubDivisionColumn = getMappedName(ColumnName.CountrySubDivision);\n const regionToCountrySubDivision: {\n [k in string]: IsoCountrySubdivisionCode | typeof NONE;\n } =\n countrySubDivisionColumn === NONE\n ? {}\n : await mapEnumValues(\n getUniqueValuesForColumn(requests, countrySubDivisionColumn),\n [...Object.values(IsoCountrySubdivisionCode), NONE],\n state.getValue('regionToCountrySubDivision'),\n );\n await state.setValue(\n regionToCountrySubDivision,\n 'regionToCountrySubDivision',\n );\n}\n","import { LOCALE_KEY } from '@transcend-io/internationalization';\nimport { DateFromISOString } from 'io-ts-types';\n\nimport * as t from 'io-ts';\nimport type { PersistedState } from '@transcend-io/persisted-state';\nimport {\n NORMALIZE_PHONE_NUMBER,\n CompletedRequestStatus,\n RequestAction,\n IdentifierType,\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\nimport { ObjByString, valuesOf } from '@transcend-io/type-utils';\n\nimport {\n CachedFileState,\n BLANK,\n BULK_APPLY,\n ColumnName,\n NONE,\n} from './constants';\nimport { AttributeKey } from '../graphql';\nimport { ColumnNameMap } from './mapCsvColumnsToApi';\nimport { splitCsvToList } from './splitCsvToList';\nimport { ParsedAttributeInput } from './parseAttributesFromString';\nimport { AttributeNameMap } from './mapColumnsToAttributes';\nimport { IdentifierNameMap } from './mapColumnsToIdentifiers';\n\n/**\n * Shape of additional identifiers\n *\n * key of object is IdentifierType\n */\nexport const AttestedExtraIdentifiers = t.record(\n t.string,\n t.array(\n t.intersection([\n t.type({\n /** Value of identifier */\n value: t.string,\n }),\n t.partial({\n /** Name of identifier - option for non-custom identifier types */\n name: t.string,\n }),\n ]),\n ),\n);\n\n/** Type override */\nexport type AttestedExtraIdentifiers = t.TypeOf<\n typeof AttestedExtraIdentifiers\n>;\n\nexport const PrivacyRequestInput = t.intersection([\n t.type({\n /** Email of user */\n email: t.string,\n /** Extra identifiers */\n attestedExtraIdentifiers: AttestedExtraIdentifiers,\n /** Core identifier for user */\n coreIdentifier: t.string,\n /** Action type being submitted */\n requestType: valuesOf(RequestAction),\n /** Type of data subject */\n subjectType: t.string,\n }),\n t.partial({\n /** Country */\n country: valuesOf(IsoCountryCode),\n /** Country sub division */\n countrySubDivision: valuesOf(IsoCountrySubdivisionCode),\n /** Attribute inputs */\n attributes: t.array(ParsedAttributeInput),\n /** The status that the request should be created as */\n status: valuesOf(CompletedRequestStatus),\n /** The time that the request was created */\n createdAt: DateFromISOString,\n /** Data silo IDs to submit for */\n dataSiloIds: t.array(t.string),\n /** Language key to map to */\n locale: valuesOf(LOCALE_KEY),\n }),\n]);\n\n/** Type override */\nexport type PrivacyRequestInput = t.TypeOf<typeof PrivacyRequestInput>;\n\n/**\n * Transform the identifier value based on type\n *\n * @param identifierValue - Value of identifier\n * @param identifierType - Type of identifier\n * @param defaultPhoneCountryCode - Default country code for phone numbers\n * @returns Post-processed identifier\n */\nexport function normalizeIdentifierValue(\n identifierValue: string,\n identifierType: IdentifierType,\n defaultPhoneCountryCode: string,\n): string {\n // Lowercase email\n if (identifierType === IdentifierType.Email) {\n return identifierValue.toLowerCase();\n }\n\n // Normalize phone number\n if (identifierType === IdentifierType.Phone) {\n const normalized = identifierValue\n .replace(NORMALIZE_PHONE_NUMBER, '')\n .replace(/[()]/g, '')\n .replace(/[–]/g, '')\n .replace(/[:]/g, '')\n .replace(/[]/g, '')\n .replace(/[A-Za-z]/g, '');\n return !normalized\n ? ''\n : normalized.startsWith('+')\n ? normalized\n : `+${defaultPhoneCountryCode}${normalized}`;\n }\n return identifierValue;\n}\n\n/**\n * Take the raw rows in a CSV upload, and map those rows to the request\n * input shape that can be passed to the Transcend API to submit a privacy\n * request.\n *\n * @param requestInputs - CSV of requests to be uploaded\n * @param state - The cached set of mapping values\n * @param options - Options\n * @returns [raw input, request input] list\n */\nexport function mapCsvRowsToRequestInputs(\n requestInputs: ObjByString[],\n state: PersistedState<typeof CachedFileState>,\n {\n columnNameMap,\n identifierNameMap,\n attributeNameMap,\n requestAttributeKeys,\n defaultPhoneCountryCode = '1', // US\n }: {\n /** Default country code */\n defaultPhoneCountryCode?: string;\n /** Mapping of column names */\n columnNameMap: ColumnNameMap;\n /** Mapping of identifier names */\n identifierNameMap: IdentifierNameMap;\n /** Mapping of attribute names */\n attributeNameMap: AttributeNameMap;\n /** Request attribute keys */\n requestAttributeKeys: AttributeKey[];\n },\n): [Record<string, string>, PrivacyRequestInput][] {\n // map the CSV to request input\n const getMappedName = (attribute: ColumnName): string =>\n state.getValue('columnNames', attribute) || columnNameMap[attribute]!;\n return requestInputs.map(\n (input): [Record<string, string>, PrivacyRequestInput] => {\n // The extra identifiers to upload for this request\n const attestedExtraIdentifiers: AttestedExtraIdentifiers = {};\n Object.entries(identifierNameMap)\n // filter out skipped identifiers\n .filter(([, columnName]) => columnName !== NONE)\n .forEach(([identifierName, columnName]) => {\n // Determine the identifier type being specified\n const identifierType = Object.values(IdentifierType).includes(\n identifierName as any, // eslint-disable-line @typescript-eslint/no-explicit-any\n )\n ? (identifierName as IdentifierType)\n : IdentifierType.Custom;\n\n // Only add the identifier if the value exists\n const identifierValue = input[columnName];\n if (identifierValue) {\n const normalized = normalizeIdentifierValue(\n identifierValue,\n identifierType,\n defaultPhoneCountryCode,\n );\n if (normalized) {\n // Initialize\n if (!attestedExtraIdentifiers[identifierType]) {\n attestedExtraIdentifiers[identifierType] = [];\n }\n\n // Add the identifier\n attestedExtraIdentifiers[identifierType]!.push({\n value: normalized,\n name: identifierName,\n });\n }\n }\n });\n\n // The extra attributes to upload for this request\n const attributes: ParsedAttributeInput[] = [];\n Object.entries(attributeNameMap)\n // filter out skipped attributes\n .filter(([, columnName]) => columnName !== NONE)\n .forEach(([attributeName, columnName]) => {\n // Only add the identifier if the value exists\n const attributeValueString = input[columnName];\n if (attributeValueString) {\n // Add the attribute\n const isMulti =\n requestAttributeKeys.find((attr) => attr.name === attributeName)\n ?.type === 'MULTI_SELECT';\n attributes.push({\n values: isMulti\n ? splitCsvToList(attributeValueString)\n : attributeValueString,\n key: attributeName,\n });\n }\n });\n\n const requestTypeColumn = getMappedName(ColumnName.RequestType);\n const dataSubjectTypeColumn = getMappedName(ColumnName.SubjectType);\n return [\n input,\n {\n email: input[getMappedName(ColumnName.Email)],\n attestedExtraIdentifiers,\n attributes,\n coreIdentifier: input[getMappedName(ColumnName.CoreIdentifier)],\n requestType:\n requestTypeColumn === BULK_APPLY\n ? state.getValue('requestTypeToRequestAction', BLANK)\n : state.getValue(\n 'requestTypeToRequestAction',\n input[requestTypeColumn],\n ),\n subjectType:\n dataSubjectTypeColumn === BULK_APPLY\n ? state.getValue('subjectTypeToSubjectName', BLANK)\n : state.getValue(\n 'subjectTypeToSubjectName',\n input[dataSubjectTypeColumn],\n ),\n ...(getMappedName(ColumnName.Locale) !== NONE &&\n input[getMappedName(ColumnName.Locale)]\n ? {\n locale: state.getValue(\n 'languageToLocale',\n input[getMappedName(ColumnName.Locale)],\n ),\n }\n : {}),\n ...(getMappedName(ColumnName.Country) !== NONE &&\n input[getMappedName(ColumnName.Country)]\n ? {\n country: state.getValue(\n 'regionToCountry',\n input[getMappedName(ColumnName.Country)],\n ) as IsoCountryCode,\n }\n : {}),\n ...(getMappedName(ColumnName.CountrySubDivision) !== NONE &&\n input[getMappedName(ColumnName.CountrySubDivision)]\n ? {\n countrySubDivision: state.getValue(\n 'regionToCountrySubDivision',\n input[getMappedName(ColumnName.CountrySubDivision)],\n ) as IsoCountrySubdivisionCode,\n }\n : {}),\n ...(getMappedName(ColumnName.RequestStatus) !== NONE &&\n state.getValue(\n 'statusToRequestStatus',\n input[getMappedName(ColumnName.RequestStatus)],\n ) !== NONE &&\n input[getMappedName(ColumnName.RequestStatus)]\n ? {\n status: state.getValue(\n 'statusToRequestStatus',\n input[getMappedName(ColumnName.RequestStatus)],\n ) as CompletedRequestStatus,\n }\n : {}),\n ...(getMappedName(ColumnName.CreatedAt) !== NONE &&\n input[getMappedName(ColumnName.CreatedAt)]\n ? {\n createdAt: new Date(input[getMappedName(ColumnName.CreatedAt)]),\n }\n : {}),\n ...(getMappedName(ColumnName.DataSiloIds) !== NONE &&\n input[getMappedName(ColumnName.DataSiloIds)]\n ? {\n dataSiloIds: splitCsvToList(\n input[getMappedName(ColumnName.DataSiloIds)],\n ),\n }\n : {}),\n },\n ];\n },\n );\n}\n","import { map } from '../bluebird';\nimport colors from 'colors';\nimport cliProgress from 'cli-progress';\n\nimport { PrivacyRequest } from '../graphql';\nimport * as t from 'io-ts';\nimport type { Got } from 'got';\nimport { decodeCodec, valuesOf } from '@transcend-io/type-utils';\nimport { logger } from '../../logger';\nimport { TableEncryptionType } from '@transcend-io/privacy-types';\n\nexport const IntlMessage = t.type({\n /** The message key */\n defaultMessage: t.string,\n /** ID */\n id: t.string,\n});\n\n/** Type */\nexport type IntlMessage = t.TypeOf<typeof IntlMessage>;\n\nexport const RequestFileMetadata = t.type({\n /** The key to pass to download the file contents */\n downloadKey: t.string,\n /** Error message related to file */\n error: t.union([t.null, t.string]),\n /** Mimetype of file */\n mimetype: t.string,\n /** Size of file, stored as string as this can be a BigInt */\n size: t.string,\n /** Name of file based on datapoint names in Transcend */\n fileName: t.string,\n /** The metadata on the datapoint */\n dataPoint: t.type({\n /** ID of datapoint */\n id: t.string,\n /** The title of datapoint */\n title: t.union([IntlMessage, t.null]),\n /** Description of datapoint */\n description: t.union([IntlMessage, t.null]),\n /** Name of datapoint */\n name: t.string,\n /** Slug of datapoint */\n slug: t.string,\n /** Table level encryption information */\n encryption: t.union([valuesOf(TableEncryptionType), t.null]),\n /** The name of the data silo */\n dataSilo: t.type({\n /** ID of the data silo */\n id: t.string,\n /** The title of the data silo */\n title: t.string,\n /** The description of the data silo */\n description: t.string,\n /** The type of the data silo */\n type: t.string,\n /** The outer type of the data silo */\n outerType: t.union([t.string, t.null]),\n }),\n /** The path to the datapoint if a database (e.g. name of schema) */\n path: t.array(t.string),\n }),\n});\n\n/** Type override */\nexport type RequestFileMetadata = t.TypeOf<typeof RequestFileMetadata>;\n\nexport const RequestFileMetadataResponse = t.type({\n /** The list of file metadata */\n nodes: t.array(RequestFileMetadata),\n /** The total number of file metadata */\n totalCount: t.number,\n /** Links to next pages */\n _links: t.partial({\n /** The link to the next page of file metadata */\n next: t.union([t.string, t.null]),\n /** The link to the previous page of file metadata */\n previous: t.union([t.string, t.null]),\n }),\n});\n\n/** Type override */\nexport type RequestFileMetadataResponse = t.TypeOf<\n typeof RequestFileMetadataResponse\n>;\n\n/**\n * Given a list of privacy requests, download the file metadata\n * for these requests - this is useful to prepare the files in a\n * data access request for download.\n *\n * @param requests - The list of privacy requests to download files for\n * @param options - Options\n * @returns The number of requests canceled\n */\nexport async function getFileMetadataForPrivacyRequests(\n requests: Pick<PrivacyRequest, 'id' | 'status'>[],\n {\n sombra,\n concurrency = 5,\n limit = 100,\n }: {\n /** Sombra instance */\n sombra: Got;\n /** Number of files to pull at once */\n limit?: number;\n /** Concurrency limit for approving */\n concurrency?: number;\n },\n): Promise<[Pick<PrivacyRequest, 'id' | 'status'>, RequestFileMetadata[]][]> {\n logger.info(\n colors.magenta(`Pulling file metadata for ${requests.length} requests`),\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 // Start timer\n let total = 0;\n progressBar.start(requests.length, 0);\n\n // Loop over the requests\n const results = await map(\n requests,\n async (\n requestToDownload,\n ): Promise<\n [Pick<PrivacyRequest, 'id' | 'status'>, RequestFileMetadata[]]\n > => {\n const localResults: RequestFileMetadata[] = [];\n\n // Paginate over the file metadata for this request\n let shouldContinue = true;\n let offset = 0;\n while (shouldContinue) {\n let response: RequestFileMetadataResponse;\n try {\n // Grab the file metadata for this request\n\n const rawResponse = await sombra\n .get(\n `v1/data-subject-request/${requestToDownload.id}/download-keys`,\n {\n searchParams: {\n limit,\n offset,\n },\n },\n )\n .json();\n response = decodeCodec(RequestFileMetadataResponse, rawResponse);\n localResults.push(...response.nodes);\n\n // Increase offset and break if no more pages\n offset += limit;\n shouldContinue =\n // eslint-disable-next-line no-underscore-dangle\n !!response._links.next && response.nodes.length === limit;\n } catch (err) {\n throw new Error(\n `Received an error from server: ${\n err?.response?.body || err?.message\n }`,\n );\n }\n }\n\n total += 1;\n progressBar.update(total);\n return [requestToDownload, localResults];\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 downloaded file metadata ${requests.length} requests in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n\n return results;\n}\n","import { map } from '../bluebird';\nimport colors from 'colors';\nimport { RequestFileMetadata } from './getFileMetadataForPrivacyRequests';\nimport type { Got } from 'got';\nimport { logger } from '../../logger';\n\n/**\n * This function will take in a set of file metadata for privacy requests\n * call the Transcend API to stream the file metadata for these requests\n * and pass that through a callback function\n *\n * @param fileMetadata - Metadata to download\n * @param options - Options for the request\n */\nexport async function streamPrivacyRequestFiles(\n fileMetadata: RequestFileMetadata[],\n {\n requestId,\n sombra,\n onFileDownloaded,\n concurrency = 20,\n }: {\n /** Request ID for logging */\n requestId: string;\n /** Sombra got instance */\n sombra: Got;\n /** Handler on each file */\n onFileDownloaded: (metadata: RequestFileMetadata, stream: Buffer) => void;\n /** Concurrent downloads at once */\n concurrency?: number;\n },\n): Promise<void> {\n // Loop over each file\n await map(\n fileMetadata,\n async (metadata) => {\n try {\n // Construct the stream\n await sombra\n .get('v1/files', {\n searchParams: {\n downloadKey: metadata.downloadKey,\n },\n })\n .buffer()\n .then((fileResponse) => onFileDownloaded(metadata, fileResponse));\n } catch (err) {\n if (err?.response?.body?.includes('fileMetadata#verify')) {\n logger.error(\n colors.red(\n `Failed to pull file for: ${metadata.fileName} (request:${requestId}) - JWT expired. ` +\n 'This likely means that the file is no longer available. ' +\n 'Try restarting the request from scratch in Transcend Admin Dashboard. ' +\n 'Skipping the download of this file.',\n ),\n );\n return;\n }\n throw new Error(\n `Received an error from server: ${\n err?.response?.body || err?.message\n }`,\n );\n }\n },\n {\n concurrency,\n },\n );\n}\n","import { map } from '../bluebird';\nimport { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport {\n fetchAllRequests,\n buildTranscendGraphQLClient,\n createSombraGotInstance,\n makeGraphQLRequest,\n APPROVE_PRIVACY_REQUEST,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\nimport { getFileMetadataForPrivacyRequests } from './getFileMetadataForPrivacyRequests';\nimport { streamPrivacyRequestFiles } from './streamPrivacyRequestFiles';\n\n/**\n * Download a set of privacy requests to disk\n *\n * @param options - Options\n * @returns The number of requests canceled\n */\nexport async function downloadPrivacyRequestFiles({\n auth,\n folderPath,\n requestIds,\n createdAtBefore,\n sombraAuth,\n createdAtAfter,\n statuses = [RequestStatus.Approving, RequestStatus.Downloadable],\n concurrency = 5,\n transcendUrl = DEFAULT_TRANSCEND_API,\n approveAfterDownload = false,\n}: {\n /** The folder path to download the files to */\n folderPath: string;\n /** Transcend API key authentication */\n auth: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** The request statuses to cancel */\n statuses?: RequestStatus[];\n /** The set of privacy requests to cancel */\n requestIds?: string[];\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** When true, approve any requests in Transcend that are in status=APPROVING */\n approveAfterDownload?: boolean;\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 // Create sombra instance to communicate with\n const sombra = await createSombraGotInstance(transcendUrl, auth, sombraAuth);\n\n // Create the folder if it does not exist\n if (!existsSync(folderPath)) {\n mkdirSync(folderPath);\n }\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: [RequestAction.Access],\n createdAtBefore,\n createdAtAfter,\n statuses,\n requestIds,\n });\n\n // Download the file metadata for each request\n const requestFileMetadata = await getFileMetadataForPrivacyRequests(\n allRequests,\n {\n sombra,\n concurrency,\n },\n );\n\n // Start timer for download process\n const t0 = new Date().getTime();\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n let total = 0;\n let totalApproved = 0;\n progressBar.start(allRequests.length, 0);\n\n // Download the files for each request\n await map(\n requestFileMetadata,\n async ([request, metadata]) => {\n // Create a new folder to store request files\n const requestFolder = join(folderPath, request.id);\n if (!existsSync(requestFolder)) {\n mkdirSync(requestFolder);\n }\n\n // Stream each file to disk\n await streamPrivacyRequestFiles(metadata, {\n sombra,\n requestId: request.id,\n onFileDownloaded: (fil, stream) => {\n // Ensure a folder exists for the file\n // filename looks like Health/heartbeat.csv\n const filePath = join(requestFolder, fil.fileName);\n const folder = dirname(filePath);\n if (!existsSync(folder)) {\n mkdirSync(folder, { recursive: true });\n }\n\n // Write to disk\n writeFileSync(filePath, stream);\n },\n });\n\n // Approve the request if requested\n if (approveAfterDownload && request.status === RequestStatus.Approving) {\n await makeGraphQLRequest(client, APPROVE_PRIVACY_REQUEST, {\n input: { requestId: request.id },\n });\n totalApproved += 1;\n }\n\n // Increment the progress bar\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 downloaded ${total} requests in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n if (totalApproved > 0) {\n logger.info(\n colors.green(`Approved ${totalApproved} requests in Transcend.`),\n );\n }\n return allRequests.length;\n}\n","import * as t from 'io-ts';\nimport { uniq } from 'lodash-es';\nimport { valuesOf, decodeCodec } from '@transcend-io/type-utils';\nimport {\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n RequestAction,\n RequestStatus,\n} from '@transcend-io/privacy-types';\nimport type { Got } from 'got';\nimport { PrivacyRequestInput } from './mapCsvRowsToRequestInputs';\nimport { ParsedAttributeInput } from './parseAttributesFromString';\n\nexport const PrivacyRequestResponse = t.type({\n id: t.string,\n link: t.string,\n status: valuesOf(RequestStatus),\n type: valuesOf(RequestAction),\n subjectType: t.string,\n email: t.union([t.null, t.string]),\n coreIdentifier: t.string,\n isSilent: t.boolean,\n isTest: t.boolean,\n country: t.union([t.null, valuesOf(IsoCountryCode)]),\n countrySubDivision: t.union([t.null, valuesOf(IsoCountrySubdivisionCode)]),\n attributeValues: t.array(\n t.type({\n attributeKey: t.type({ name: t.string }),\n name: t.string,\n }),\n ),\n});\n\n/** Type override */\nexport type PrivacyRequestResponse = t.TypeOf<typeof PrivacyRequestResponse>;\n\n/**\n * Submit a privacy request to the Transcend API\n *\n * @param sombra - Sombra instance configured to make requests\n * @param input - Request input\n * @param options - Additional options\n * @returns Successfully submitted request\n */\nexport async function submitPrivacyRequest(\n sombra: Got,\n input: PrivacyRequestInput,\n {\n details = '',\n isTest = false,\n emailIsVerified = true,\n skipSendingReceipt = false,\n isSilent = true,\n additionalAttributes = [],\n }: {\n /** Whether or not the request is a test request */\n isTest?: boolean;\n /** Whether or not the request is in silent mode */\n isSilent?: boolean;\n /** Whether the email is verified up front */\n emailIsVerified?: boolean;\n /** When true, skip sending of the email receipt */\n skipSendingReceipt?: boolean;\n /** Request details */\n details?: string;\n /** Additional attributes to tag the requests with */\n additionalAttributes?: ParsedAttributeInput[];\n } = {},\n): Promise<PrivacyRequestResponse> {\n // Merge the per-request attributes with the\n // global attributes\n const mergedAttributes = [...additionalAttributes];\n (input.attributes || []).forEach((attribute) => {\n const existing = mergedAttributes.find(\n (attr) => attr.key === attribute.key,\n );\n if (existing) {\n existing.values.push(...attribute.values);\n existing.values = uniq(existing.values);\n } else {\n mergedAttributes.push(attribute);\n }\n });\n\n // Make the GraphQL request\n let response: unknown;\n try {\n response = await sombra\n .post('v1/data-subject-request', {\n json: {\n type: input.requestType,\n subject: {\n coreIdentifier: input.coreIdentifier,\n email: input.email,\n emailIsVerified,\n attestedExtraIdentifiers: input.attestedExtraIdentifiers,\n },\n subjectType: input.subjectType,\n isSilent,\n isTest,\n skipSendingReceipt,\n ...(input.locale ? { locale: input.locale } : {}),\n details,\n attributes: mergedAttributes,\n ...(input.country || input.countrySubDivision\n ? {\n region: {\n ...(input.country\n ? {\n country: input.country,\n }\n : input.countrySubDivision\n ? { country: input.countrySubDivision.split('-')[0] }\n : {}),\n ...(input.countrySubDivision\n ? { countrySubDivision: input.countrySubDivision }\n : {}),\n },\n }\n : {}),\n ...(input.createdAt ? { createdAt: input.createdAt } : {}),\n ...(input.dataSiloIds ? { dataSiloIds: input.dataSiloIds } : {}),\n ...(input.status ? { completedRequestStatus: input.status } : {}),\n },\n })\n .json();\n } catch (err) {\n throw new Error(\n `Received an error from server: ${err?.response?.body || err?.message}`,\n );\n }\n\n const { request: requestResponse } = decodeCodec(\n t.type({\n request: PrivacyRequestResponse,\n }),\n response,\n );\n return requestResponse;\n}\n","import { map } from '../bluebird';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport {\n RequestAction,\n RequestOrigin,\n RequestStatus,\n} from '@transcend-io/privacy-types';\nimport {\n UPDATE_PRIVACY_REQUEST,\n fetchAllRequests,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n APPROVE_PRIVACY_REQUEST,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Approve a set of privacy requests\n *\n * @param options - Options\n * @returns The number of requests approved\n */\nexport async function approvePrivacyRequests({\n requestActions,\n requestOrigins,\n auth,\n silentModeBefore,\n createdAtAfter,\n createdAtBefore,\n concurrency = 50,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** The request origins that should be restarted */\n requestOrigins?: RequestOrigin[];\n /** Transcend API key authentication */\n auth: string;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** Mark these requests as silent mode if they were created before this date */\n silentModeBefore?: Date;\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses: [RequestStatus.Approving],\n createdAtAfter,\n origins: requestOrigins,\n createdAtBefore,\n });\n\n // Notify Transcend\n logger.info(colors.magenta(`Approving \"${allRequests.length}\" requests.`));\n\n let total = 0;\n let skipped = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToApprove) => {\n // update request to silent mode if silentModeBefore is defined\n // and the request was created before silentModeBefore\n if (\n silentModeBefore &&\n new Date(silentModeBefore) > new Date(requestToApprove.createdAt)\n ) {\n await makeGraphQLRequest(client, UPDATE_PRIVACY_REQUEST, {\n input: {\n id: requestToApprove.id,\n isSilent: true,\n },\n });\n }\n\n try {\n // approve the request\n await makeGraphQLRequest(client, APPROVE_PRIVACY_REQUEST, {\n input: { requestId: requestToApprove.id },\n });\n } catch (err) {\n if (err.message.includes('Request must be in an approving state,')) {\n skipped += 1;\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 if (skipped > 0) {\n logger.info(colors.yellow(`${skipped} requests were skipped.`));\n }\n logger.info(\n colors.green(\n `Successfully approved ${total} requests in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n return allRequests.length;\n}\n","import { map } from '../bluebird';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport { RequestAction } from '@transcend-io/privacy-types';\nimport {\n NOTIFY_ADDITIONAL_TIME,\n fetchAllRequests,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n fetchAllTemplates,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Mark a set of privacy requests to be in silent mode.\n * Note requests in silent mode are ignored\n *\n * @param options - Options\n * @returns The number of requests marked silent\n */\nexport async function notifyPrivacyRequestsAdditionalTime({\n requestActions = Object.values(RequestAction),\n auth,\n requestIds,\n createdAtBefore,\n days = 45,\n daysLeft = 10,\n createdAtAfter,\n emailTemplate = 'Additional Time Needed',\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions?: RequestAction[];\n /** Filter for requests created before this date */\n createdAtBefore: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Email template */\n emailTemplate?: string;\n /** Transcend API key authentication */\n auth: string;\n /** Number of days to extend request by */\n days?: number;\n /**\n * Only notify requests that have less than this number of days until they are considered expired.\n * This allows for re-running the command without notifying the same users multiple times\n */\n daysLeft?: number;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** The set of privacy requests to notify */\n requestIds?: string[];\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Grab the template with that title\n const matchingTemplates = await fetchAllTemplates(client, emailTemplate);\n const exactTemplateMatch = matchingTemplates.find(\n (template) => template.title === emailTemplate,\n );\n if (!exactTemplateMatch) {\n throw new Error(`Failed to find a template with title: \"${emailTemplate}\"`);\n }\n\n // Pull in the requests\n let allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n createdAtBefore,\n createdAtAfter,\n isSilent: false,\n isClosed: false,\n requestIds,\n });\n\n // Filter requests by daysLeft\n allRequests = allRequests.filter(\n (request) =>\n typeof request.daysRemaining === 'number' &&\n request.daysRemaining < daysLeft,\n );\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Notifying \"${allRequests.length}\" that more time is needed.`,\n ),\n );\n\n let total = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToNotify) => {\n await makeGraphQLRequest(client, NOTIFY_ADDITIONAL_TIME, {\n input: {\n requestId: requestToNotify.id,\n template: exactTemplateMatch.template.defaultMessage,\n subject: exactTemplateMatch.subject.defaultMessage,\n additionalTime: days,\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 marked ${total} requests as silent mode in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n return allRequests.length;\n}\n","import type { GraphQLClient } from 'graphql-request';\nimport inquirer from 'inquirer';\nimport { INITIALIZER, makeGraphQLRequest, Initializer } from '../graphql';\nimport { CachedFileState, IDENTIFIER_BLOCK_LIST } from './constants';\nimport { fuzzyMatchColumns } from './fuzzyMatchColumns';\nimport type { PersistedState } from '@transcend-io/persisted-state';\n\n/**\n * Mapping from identifier name to request input parameter\n */\nexport type IdentifierNameMap = {\n [k in string]: string;\n};\n\n/**\n * Create a mapping from the identifier names that can be included\n * at request submission, to the names of the columns that map to those\n * identifiers.\n *\n * @param client - GraphQL client\n * @param columnNames - The set of all column names\n * @param state - Cached state of this mapping\n * @returns Mapping from identifier name to column name\n */\nexport async function mapColumnsToIdentifiers(\n client: GraphQLClient,\n columnNames: string[],\n state: PersistedState<typeof CachedFileState>,\n): Promise<IdentifierNameMap> {\n // Grab the initializer\n const { initializer } = await makeGraphQLRequest<{\n /** Query response */\n initializer: Initializer;\n }>(client, INITIALIZER);\n\n // Determine the columns that should be mapped\n const columnQuestions = initializer.identifiers.filter(\n ({ name }) =>\n !state.getValue('identifierNames', name) &&\n !IDENTIFIER_BLOCK_LIST.includes(name),\n );\n\n // Skip mapping when everything is mapped\n const identifierNameMap =\n columnQuestions.length === 0\n ? {}\n : // prompt questions to map columns\n await inquirer.prompt<{\n [k in string]: string;\n }>(\n columnQuestions.map(({ name }) => {\n const matches = fuzzyMatchColumns(columnNames, name, false);\n return {\n name,\n message: `Choose the column that will be used to map in the identifier: ${name}`,\n type: 'list',\n default: matches[0],\n choices: matches,\n };\n }),\n );\n await Promise.all(\n Object.entries(identifierNameMap).map(([k, v]) =>\n state.setValue(v, 'identifierNames', k),\n ),\n );\n\n return {\n ...state.getValue('identifierNames'),\n ...identifierNameMap,\n };\n}\n","import { map } from '../bluebird';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport {\n UPDATE_PRIVACY_REQUEST,\n fetchAllRequests,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n CANCEL_PRIVACY_REQUEST,\n fetchAllTemplates,\n Template,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Cancel a set of privacy requests\n *\n * @param options - Options\n * @returns The number of requests canceled\n */\nexport async function cancelPrivacyRequests({\n requestActions,\n cancellationTitle,\n auth,\n requestIds,\n silentModeBefore,\n createdAtBefore,\n createdAtAfter,\n statuses = [\n RequestStatus.Compiling,\n RequestStatus.RequestMade,\n RequestStatus.Delayed,\n RequestStatus.Approving,\n RequestStatus.Secondary,\n RequestStatus.Enriching,\n RequestStatus.Waiting,\n RequestStatus.SecondaryApproving,\n ],\n concurrency = 50,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** Transcend API key authentication */\n auth: string;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** The request statuses to cancel */\n statuses?: RequestStatus[];\n /** The set of privacy requests to cancel */\n requestIds?: string[];\n /** Mark these requests as silent mode if they were created before this date */\n silentModeBefore?: Date;\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** The email template to use when canceling the requests */\n cancellationTitle?: 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 // Grab the template with that title\n let cancelationTemplate: Template | undefined;\n if (cancellationTitle) {\n const matchingTemplates = await fetchAllTemplates(\n client,\n cancellationTitle,\n );\n const exactTitleMatch = matchingTemplates.find(\n (template) => template.title === cancellationTitle,\n );\n if (!exactTitleMatch) {\n throw new Error(\n `Failed to find a template with title: \"${cancellationTitle}\"`,\n );\n }\n cancelationTemplate = exactTitleMatch;\n }\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n createdAtBefore,\n createdAtAfter,\n statuses,\n requestIds,\n });\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Canceling \"${allRequests.length}\" requests${\n cancelationTemplate\n ? ` Using template: ${cancelationTemplate.title}`\n : ''\n }.`,\n ),\n );\n\n let total = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToCancel) => {\n // update request to silent mode if silentModeBefore is defined\n // and the request was created before silentModeBefore\n if (\n silentModeBefore &&\n new Date(silentModeBefore) > new Date(requestToCancel.createdAt)\n ) {\n await makeGraphQLRequest(client, UPDATE_PRIVACY_REQUEST, {\n input: {\n id: requestToCancel.id,\n isSilent: true,\n },\n });\n }\n\n // cancel the request\n await makeGraphQLRequest(client, CANCEL_PRIVACY_REQUEST, {\n input: {\n requestId: requestToCancel.id,\n ...(cancelationTemplate\n ? {\n subject: `Re: ${cancelationTemplate.subject.defaultMessage}`,\n template: cancelationTemplate.template.defaultMessage,\n }\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 canceled ${total} requests in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n return allRequests.length;\n}\n","import type { GraphQLClient } from 'graphql-request';\nimport inquirer from 'inquirer';\nimport { AttributeKey } from '../graphql';\nimport { CachedFileState } from './constants';\nimport { fuzzyMatchColumns } from './fuzzyMatchColumns';\nimport type { PersistedState } from '@transcend-io/persisted-state';\n\n/**\n * Mapping from attribute name to request input parameter\n */\nexport type AttributeNameMap = {\n [k in string]: string;\n};\n\n/**\n * Create a mapping from the attributes names that can be included\n * at request submission, to the names of the columns that map to those\n * attributes.\n *\n * @param client - GraphQL client\n * @param columnNames - The set of all column names\n * @param state - Cached state of this mapping\n * @param requestAttributeKeys - Attribute keys to map\n * @returns Mapping from attributes name to column name\n */\nexport async function mapColumnsToAttributes(\n client: GraphQLClient,\n columnNames: string[],\n state: PersistedState<typeof CachedFileState>,\n requestAttributeKeys: AttributeKey[],\n): Promise<AttributeNameMap> {\n // Determine the columns that should be mapped\n const columnQuestions = requestAttributeKeys.filter(\n ({ name }) => !state.getValue('attributeNames', name),\n );\n\n // Skip mapping when everything is mapped\n const attributeNameMap =\n columnQuestions.length === 0\n ? {}\n : // prompt questions to map columns\n await inquirer.prompt<{\n [k in string]: string;\n }>(\n columnQuestions.map(({ name }) => {\n const matches = fuzzyMatchColumns(columnNames, name, false);\n return {\n name,\n message: `Choose the column that will be used to map in the attribute: ${name}`,\n type: 'list',\n default: matches[0],\n choices: matches,\n };\n }),\n );\n await Promise.all(\n Object.entries(attributeNameMap).map(([k, v]) =>\n state.setValue(v, 'attributeNames', k),\n ),\n );\n\n return {\n ...state.getValue('attributeNames'),\n ...attributeNameMap,\n };\n}\n","const CLIENT_ERROR = /{\\\\\"message\\\\\":\\\\\"(.+?)\\\\\",/;\n\n/**\n * Extract a client error from the request\n *\n * @param err - Error message\n * @returns Client error or null\n */\nexport function extractClientError(err: string): string | null {\n return CLIENT_ERROR.test(err) ? CLIENT_ERROR.exec(err)![1] : null;\n}\n","/* eslint-disable max-lines */\nimport colors from 'colors';\nimport { map } from '../bluebird';\nimport * as t from 'io-ts';\nimport { uniq } from 'lodash-es';\nimport cliProgress from 'cli-progress';\nimport { join } from 'node:path';\nimport { PersistedState } from '@transcend-io/persisted-state';\nimport { logger } from '../../logger';\nimport {\n createSombraGotInstance,\n buildTranscendGraphQLClient,\n fetchAllRequestAttributeKeys,\n} from '../graphql';\nimport { mapRequestEnumValues } from './mapRequestEnumValues';\nimport { CachedRequestState, CachedFileState } from './constants';\nimport { mapCsvColumnsToApi } from './mapCsvColumnsToApi';\nimport { parseAttributesFromString } from './parseAttributesFromString';\nimport { readCsv } from './readCsv';\nimport { submitPrivacyRequest } from './submitPrivacyRequest';\nimport { mapColumnsToAttributes } from './mapColumnsToAttributes';\nimport { mapColumnsToIdentifiers } from './mapColumnsToIdentifiers';\nimport { mapCsvRowsToRequestInputs } from './mapCsvRowsToRequestInputs';\nimport { filterRows } from './filterRows';\nimport { extractClientError } from './extractClientError';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Upload a set of privacy requests from CSV\n *\n * @param options - Options\n */\nexport async function uploadPrivacyRequestsFromCsv({\n cacheFilepath,\n requestReceiptFolder,\n file,\n auth,\n sombraAuth,\n concurrency = 100,\n defaultPhoneCountryCode = '1', // USA\n transcendUrl = DEFAULT_TRANSCEND_API,\n attributes = [],\n emailIsVerified = true,\n skipFilterStep = false,\n skipSendingReceipt = true,\n isTest = false,\n isSilent = true,\n debug = false,\n dryRun = false,\n}: {\n /** File to cache metadata about mapping of CSV shape to script */\n cacheFilepath: string;\n /** File where request receipts are stored */\n requestReceiptFolder: string;\n /** CSV file path */\n file: string;\n /** Transcend API key authentication */\n auth: string;\n /** Default country code for phone numbers */\n defaultPhoneCountryCode?: string;\n /** Concurrency to upload in */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** Include debug logs */\n debug?: boolean;\n /** Skip the step where requests are filtered */\n skipFilterStep?: boolean;\n /** Whether test requests are being uploaded */\n isTest?: boolean;\n /** Whether requests are uploaded in silent mode */\n isSilent?: boolean;\n /** Whether to send the email receipt */\n skipSendingReceipt?: boolean;\n /** Whether the email was verified up front */\n emailIsVerified?: boolean;\n /** Attributes string pre-parse */\n attributes?: string[];\n /** Whether a dry run is happening */\n dryRun?: boolean;\n}): Promise<void> {\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Parse out the extra attributes to apply to all requests uploaded\n const parsedAttributes = parseAttributesFromString(attributes);\n\n // Create a new state to persist the metadata that\n // maps the request inputs to the Transcend API shape\n const state = new PersistedState(cacheFilepath, CachedFileState, {\n columnNames: {},\n requestTypeToRequestAction: {},\n subjectTypeToSubjectName: {},\n languageToLocale: {},\n statusToRequestStatus: {},\n identifierNames: {},\n attributeNames: {},\n regionToCountrySubDivision: {},\n regionToCountry: {},\n });\n\n // Create a new state file to store the requests from this run\n const requestCacheFile = join(\n requestReceiptFolder,\n `tr-request-upload-${new Date().toISOString()}-${file\n .split('/')\n .pop()}`.replace('.csv', '.json'),\n );\n const requestState = new PersistedState(\n requestCacheFile,\n CachedRequestState,\n {\n successfulRequests: [],\n duplicateRequests: [],\n failingRequests: [],\n },\n );\n\n // Create sombra instance to communicate with\n const sombra = await createSombraGotInstance(transcendUrl, auth, sombraAuth);\n\n // Read in the list of integration requests\n const requestsList = readCsv(file, t.record(t.string, t.string));\n const columnNames = uniq(requestsList.map((x) => Object.keys(x)).flat());\n\n // Log out an example request\n if (requestsList.length === 0) {\n throw new Error(\n 'No Requests found in list! Ensure the first row of the CSV is a header and the rest are requests.',\n );\n }\n if (debug) {\n const firstRequest = requestsList[0];\n logger.info(\n colors.magenta(`First request: ${JSON.stringify(firstRequest, null, 2)}`),\n );\n }\n // Determine what rows in the CSV should be imported\n // Choose columns that contain metadata to filter the requests\n const filteredRequestList = skipFilterStep\n ? requestsList\n : await filterRows(requestsList);\n\n // Build a GraphQL client\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n // Grab the request attributes\n const requestAttributeKeys = await fetchAllRequestAttributeKeys(client);\n // Determine the columns that should be mapped\n const columnNameMap = await mapCsvColumnsToApi(columnNames, state);\n const identifierNameMap = await mapColumnsToIdentifiers(\n client,\n columnNames,\n state,\n );\n const attributeNameMap = await mapColumnsToAttributes(\n client,\n columnNames,\n state,\n requestAttributeKeys,\n );\n await mapRequestEnumValues(client, filteredRequestList, {\n state,\n columnNameMap,\n });\n\n // map the CSV to request input\n const requestInputs = mapCsvRowsToRequestInputs(filteredRequestList, state, {\n defaultPhoneCountryCode,\n columnNameMap,\n identifierNameMap,\n attributeNameMap,\n requestAttributeKeys,\n });\n\n // start the progress bar with a total value of 200 and start value of 0\n if (!debug) {\n progressBar.start(requestInputs.length, 0);\n }\n let total = 0;\n // Submit each request\n await map(\n requestInputs,\n async ([rawRow, requestInput], ind) => {\n // The identifier to log, only include personal data if debug mode is on\n const requestLogId = debug\n ? `email:${requestInput.email} | coreIdentifier:${requestInput.coreIdentifier}`\n : `row:${ind.toString()}`;\n\n if (debug) {\n logger.info(\n colors.magenta(\n `[${ind + 1}/${requestInputs.length}] Importing: ${JSON.stringify(\n requestInput,\n null,\n 2,\n )}`,\n ),\n );\n }\n\n // Skip on dry run\n if (dryRun) {\n logger.info(\n colors.magenta('Bailing out on dry run because dryRun is set'),\n );\n return;\n }\n\n try {\n // Make the GraphQL request to submit the privacy request\n const requestResponse = await submitPrivacyRequest(\n sombra,\n requestInput,\n {\n details: `Uploaded by Transcend Cli: \"tr-request-upload\" : ${JSON.stringify(\n rawRow,\n null,\n 2,\n )}`,\n isTest,\n emailIsVerified,\n skipSendingReceipt,\n isSilent,\n additionalAttributes: parsedAttributes,\n },\n );\n\n // Log success\n if (debug) {\n logger.info(\n colors.green(\n `[${ind + 1}/${\n requestInputs.length\n }] Successfully submitted the test data subject request: \"${requestLogId}\"`,\n ),\n );\n logger.info(\n colors.green(\n `[${ind + 1}/${requestInputs.length}] View it at: \"${\n requestResponse.link\n }\"`,\n ),\n );\n }\n\n // Cache successful upload\n const successfulRequests = requestState.getValue('successfulRequests');\n successfulRequests.push({\n id: requestResponse.id,\n link: requestResponse.link,\n rowIndex: ind,\n coreIdentifier: requestResponse.coreIdentifier,\n attemptedAt: new Date().toISOString(),\n });\n await requestState.setValue(successfulRequests, 'successfulRequests');\n } catch (err) {\n const msg = `${err.message} - ${JSON.stringify(\n err.response?.body,\n null,\n 2,\n )}`;\n const clientError = extractClientError(msg);\n\n if (\n clientError === 'Client error: You have already made this request.'\n ) {\n if (debug) {\n logger.info(\n colors.yellow(\n `[${ind + 1}/${\n requestInputs.length\n }] Skipping request as it is a duplicate`,\n ),\n );\n }\n const duplicateRequests = requestState.getValue('duplicateRequests');\n duplicateRequests.push({\n coreIdentifier: requestInput.coreIdentifier,\n rowIndex: ind,\n attemptedAt: new Date().toISOString(),\n });\n await requestState.setValue(duplicateRequests, 'duplicateRequests');\n } else {\n const failingRequests = requestState.getValue('failingRequests');\n failingRequests.push({\n ...requestInput,\n rowIndex: ind,\n error: clientError || msg,\n attemptedAt: new Date().toISOString(),\n });\n await requestState.setValue(failingRequests, 'failingRequests');\n if (debug) {\n logger.error(colors.red(clientError || msg));\n logger.error(\n colors.red(\n `[${ind + 1}/${\n requestInputs.length\n }] Failed to submit request for: \"${requestLogId}\"`,\n ),\n );\n }\n }\n }\n\n total += 1;\n if (!debug) {\n progressBar.update(total);\n }\n },\n {\n concurrency,\n },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n // Log completion time\n logger.info(\n colors.green(`Completed upload in \"${totalTime / 1000}\" seconds.`),\n );\n\n // Log duplicates\n if (requestState.getValue('duplicateRequests').length > 0) {\n logger.info(\n colors.yellow(\n `Encountered \"${\n requestState.getValue('duplicateRequests').length\n }\" duplicate requests. ` +\n `See \"${requestCacheFile}\" to review the core identifiers for these requests.`,\n ),\n );\n }\n\n // Log errors\n if (requestState.getValue('failingRequests').length > 0) {\n logger.error(\n colors.red(\n `Encountered \"${\n requestState.getValue('failingRequests').length\n }\" errors. ` +\n `See \"${requestCacheFile}\" to review the error messages and inputs.`,\n ),\n );\n process.exit(1);\n }\n}\n/* eslint-enable max-lines */\n","import * as t from 'io-ts';\nimport { groupBy } from 'lodash-es';\nimport { apply, decodeCodec } from '@transcend-io/type-utils';\nimport { IdentifierType } from '@transcend-io/privacy-types';\nimport type { Got } from 'got';\nimport { PrivacyRequest, RequestIdentifier } from '../graphql';\nimport { IDENTIFIER_BLOCK_LIST } from './constants';\nimport { PrivacyRequestResponse } from './submitPrivacyRequest';\n\n/**\n * Restart a privacy request to the Transcend API\n *\n * @param sombra - Sombra instance configured to make requests\n * @param request - Request to restart\n * @param input - Request input\n * @returns Successfully submitted request\n */\nexport async function restartPrivacyRequest(\n sombra: Got,\n request: PrivacyRequest,\n {\n sendEmailReceipt = false,\n skipWaitingPeriod = false,\n emailIsVerified = true,\n requestIdentifiers = [],\n }: {\n /** List of request identifiers to include */\n requestIdentifiers?: RequestIdentifier[];\n /** When true, send an email receipt to data subject */\n sendEmailReceipt?: boolean;\n /** Whether the email is verified */\n emailIsVerified?: boolean;\n /** Whether to skip waiting period */\n skipWaitingPeriod?: boolean;\n } = {},\n): Promise<PrivacyRequestResponse> {\n // Make the GraphQL request\n const response = await sombra\n .post('v1/data-subject-request', {\n json: {\n type: request.type,\n subject: {\n coreIdentifier: request.coreIdentifier,\n email: request.email,\n emailIsVerified,\n ...(requestIdentifiers.length > 0\n ? {\n attestedExtraIdentifiers: apply(\n groupBy(\n requestIdentifiers\n .filter(\n (ri) =>\n // these are already submitted above\n !(\n ri.name === 'email' && ri.value === request.email\n ) && !IDENTIFIER_BLOCK_LIST.includes(ri.name),\n )\n .map((ri) => ({\n ...ri,\n type: Object.values(IdentifierType).includes(\n ri.name as any, // eslint-disable-line @typescript-eslint/no-explicit-any\n )\n ? ri.name\n : IdentifierType.Custom,\n })),\n 'type',\n ),\n (values, type) =>\n values.map(({ name, value }) => ({\n ...(type === IdentifierType.Custom ? { name } : {}),\n value,\n })),\n ),\n }\n : {}),\n },\n requestId: request.id,\n subjectType: request.subjectType,\n isSilent: request.isSilent,\n isTest: request.isTest,\n locale: request.locale,\n skipWaitingPeriod,\n createdAt: request.createdAt,\n details: `Restarted by Transcend cli: \"tr-request-restart\" - ${request.details}`,\n skipSendingReceipt: !sendEmailReceipt,\n },\n })\n .json();\n\n const { request: requestResponse } = decodeCodec(\n t.type({\n request: PrivacyRequestResponse,\n }),\n response,\n );\n return requestResponse;\n}\n","import { PersistedState } from '@transcend-io/persisted-state';\nimport { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport { map } from '../bluebird';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\nimport * as t from 'io-ts';\nimport { difference } from 'lodash-es';\nimport { join, resolve } from 'node:path';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\nimport {\n buildTranscendGraphQLClient,\n createSombraGotInstance,\n fetchAllRequestIdentifiers,\n fetchAllRequests,\n} from '../graphql';\nimport { logger } from '../../logger';\nimport { SuccessfulRequest } from './constants';\nimport { extractClientError } from './extractClientError';\nimport { restartPrivacyRequest } from './restartPrivacyRequest';\n\n/** Minimal state we need to keep a list of requests */\nconst ErrorRequest = t.intersection([\n SuccessfulRequest,\n t.type({\n error: t.string,\n }),\n]);\n\n/** Type override */\ntype ErrorRequest = t.TypeOf<typeof ErrorRequest>;\n\n/** Persist this data between runs of the script */\nconst CachedRequestState = t.type({\n restartedRequests: t.array(SuccessfulRequest),\n failingRequests: t.array(ErrorRequest),\n});\n\n/**\n * Upload a set of privacy requests from CSV\n *\n * @param options - Options\n */\nexport async function bulkRestartRequests({\n requestReceiptFolder,\n auth,\n sombraAuth,\n requestActions,\n requestStatuses,\n createdAtBefore,\n createdAtAfter,\n transcendUrl = DEFAULT_TRANSCEND_API,\n requestIds = [],\n createdAt = new Date(),\n silentModeBefore,\n sendEmailReceipt = false,\n emailIsVerified = true,\n copyIdentifiers = false,\n skipWaitingPeriod = false,\n concurrency = 20,\n}: {\n /** Actions to filter for */\n requestActions: RequestAction[];\n /** Statues to filter for */\n requestStatuses: RequestStatus[];\n /** File where request receipts are stored */\n requestReceiptFolder: string;\n /** Transcend API key authentication */\n auth: string;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** Request IDs to filter for */\n requestIds?: string[];\n /** Whether to re-verify the email when restarting the request */\n emailIsVerified?: boolean;\n /** Filter for requests that were submitted before this date */\n createdAt?: Date;\n /** Requests that have been open for this length of time should be marked as silent mode */\n silentModeBefore?: Date;\n /** Send an email receipt to the restarted requests */\n sendEmailReceipt?: boolean;\n /** Copy over all identifiers rather than restarting the request only with the core identifier */\n copyIdentifiers?: boolean;\n /** Skip the waiting period when restarting requests */\n skipWaitingPeriod?: boolean;\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Concurrency to upload requests at */\n concurrency?: number;\n}): Promise<void> {\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Create a new state file to store the requests from this run\n const cacheFile = join(\n requestReceiptFolder,\n `tr-request-restart-${new Date().toISOString()}.json`,\n );\n const state = new PersistedState(cacheFile, CachedRequestState, {\n restartedRequests: [],\n failingRequests: [],\n });\n\n // Create sombra instance to communicate with\n const sombra = await createSombraGotInstance(transcendUrl, auth, sombraAuth);\n\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n const allRequests = await fetchAllRequests(client, {\n requestIds,\n actions: requestActions,\n statuses: requestStatuses,\n createdAtBefore,\n createdAtAfter,\n });\n const requests = allRequests.filter(\n (request) => new Date(request.createdAt) < createdAt,\n );\n logger.info(`Found ${requests.length} requests to restart`);\n\n if (copyIdentifiers) {\n logger.info('copyIdentifiers detected - All Identifiers will be copied.');\n }\n if (sendEmailReceipt) {\n logger.info('sendEmailReceipt detected - Email receipts will be sent.');\n }\n if (skipWaitingPeriod) {\n logger.info('skipWaitingPeriod detected - Waiting period will be skipped.');\n }\n\n // Validate request IDs\n if (requestIds.length > 0 && requestIds.length !== requests.length) {\n const missingRequests = difference(\n requestIds,\n requests.map(({ id }) => id),\n );\n if (missingRequests.length > 0) {\n logger.error(\n colors.red(\n `Failed to find the following requests by ID: ${missingRequests.join(\n ',',\n )}.`,\n ),\n );\n process.exit(1);\n }\n }\n\n // Map over the requests\n let total = 0;\n progressBar.start(requests.length, 0);\n await map(\n requests,\n async (request, ind) => {\n try {\n // Pull the request identifiers\n const requestIdentifiers = copyIdentifiers\n ? await fetchAllRequestIdentifiers(client, sombra, {\n requestId: request.id,\n })\n : [];\n\n // Make the GraphQL request to restart the request\n const requestResponse = await restartPrivacyRequest(\n sombra,\n {\n ...request,\n // override silent mode\n isSilent:\n !!silentModeBefore &&\n new Date(request.createdAt) < silentModeBefore\n ? true\n : request.isSilent,\n },\n {\n requestIdentifiers,\n skipWaitingPeriod,\n sendEmailReceipt,\n emailIsVerified,\n },\n );\n\n // Cache successful upload\n const restartedRequests = state.getValue('restartedRequests');\n restartedRequests.push({\n id: requestResponse.id,\n link: requestResponse.link,\n rowIndex: ind,\n coreIdentifier: requestResponse.coreIdentifier,\n attemptedAt: new Date().toISOString(),\n });\n await state.setValue(restartedRequests, 'restartedRequests');\n } catch (err) {\n const msg = `${err.message} - ${JSON.stringify(\n err.response?.body,\n null,\n 2,\n )}`;\n const clientError = extractClientError(msg);\n\n const failingRequests = state.getValue('failingRequests');\n failingRequests.push({\n id: request.id,\n link: request.link,\n rowIndex: ind,\n coreIdentifier: request.coreIdentifier,\n attemptedAt: new Date().toISOString(),\n error: clientError || msg,\n });\n await state.setValue(failingRequests, 'failingRequests');\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 // Log completion time\n logger.info(\n colors.green(\n `Completed restarting of requests in \"${totalTime / 1000}\" seconds.`,\n ),\n );\n\n // Log errors\n if (state.getValue('failingRequests').length > 0) {\n logger.error(\n colors.red(\n `Encountered \"${state.getValue('failingRequests').length}\" errors. ` +\n `See \"${resolve(\n cacheFile,\n )}\" to review the error messages and inputs.`,\n ),\n );\n process.exit(1);\n }\n}\n","import { mapSeries, map } from '../bluebird';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport {\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n fetchAllRequestEnrichers,\n fetchAllRequests,\n SKIP_REQUEST_ENRICHER,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport {\n RequestEnricherStatus,\n RequestStatus,\n} from '@transcend-io/privacy-types';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Given an enricher ID, mark all open request enrichers as skipped\n *\n * @param options - Options\n * @returns Number of items skipped\n */\nexport async function skipPreflightJobs({\n enricherIds,\n auth,\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** Transcend API key authentication */\n auth: string;\n /** Enricher IDs to pull down jobs for */\n enricherIds: string[];\n /** Upload concurrency */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Request statuses to mark as completed */\n requestStatuses?: RequestStatus[];\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n\n // fetch all RequestDataSilos that are open\n const requests = await fetchAllRequests(client, {\n statuses: [RequestStatus.Enriching],\n });\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Processing enricher: \"${enricherIds.join(',')}\" fetched \"${\n requests.length\n }\" in enriching status.`,\n ),\n );\n\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n let total = 0;\n progressBar.start(requests.length, 0);\n let totalSkipped = 0;\n await map(\n requests,\n async (request) => {\n // TODO dont pull all in\n const requestEnrichers = await fetchAllRequestEnrichers(client, {\n requestId: request.id,\n });\n const requestEnrichersFiltered = requestEnrichers.filter(\n (enricher) =>\n enricherIds.includes(enricher.enricher.id) &&\n ![\n RequestEnricherStatus.Resolved,\n RequestEnricherStatus.Skipped,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ].includes(enricher.status as any),\n );\n\n // TODO\n if (requestEnrichersFiltered.length > 0) {\n await mapSeries(requestEnrichersFiltered, async (requestEnricher) => {\n try {\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, SKIP_REQUEST_ENRICHER, {\n requestEnricherId: requestEnricher.id,\n });\n totalSkipped += 1;\n } catch (err) {\n if (\n !err.message.includes(\n 'Client error: Cannot skip Request enricher because it has already completed',\n )\n ) {\n throw err;\n }\n }\n });\n }\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully skipped \"${totalSkipped}\" for \"${\n requests.length\n }\" requests in \"${totalTime / 1000}\" seconds!`,\n ),\n );\n return requests.length;\n}\n","import {\n RequestAction,\n RequestEnricherStatus,\n RequestStatus,\n} from '@transcend-io/privacy-types';\nimport { map } from '../bluebird';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\nimport { difference } from 'lodash-es';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\nimport {\n buildTranscendGraphQLClient,\n fetchAllRequestEnrichers,\n fetchAllRequests,\n retryRequestEnricher,\n} from '../graphql';\nimport { logger } from '../../logger';\n\n/**\n * Restart a bunch of request enrichers\n *\n * @param options - Options\n */\nexport async function bulkRetryEnrichers({\n auth,\n requestActions = [],\n createdAtBefore,\n createdAtAfter,\n transcendUrl = DEFAULT_TRANSCEND_API,\n requestEnricherStatuses = Object.values(RequestEnricherStatus),\n requestIds = [],\n enricherId,\n concurrency = 20,\n}: {\n /** Actions to filter for */\n requestActions?: RequestAction[];\n /** Request enricher statuses to restart - defaults to all statuses */\n requestEnricherStatuses?: RequestEnricherStatus[];\n /** Transcend API key authentication */\n auth: string;\n /** The ID of the enricher to restart */\n enricherId: string;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Request IDs to filter for */\n requestIds?: string[];\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Concurrency to upload requests at */\n concurrency?: number;\n}): Promise<void> {\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n logger.info(colors.magenta('Fetching requests to restart...'));\n\n const requests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses: [RequestStatus.Enriching],\n createdAtBefore,\n createdAtAfter,\n requestIds,\n });\n\n let totalRestarted = 0;\n\n // Validate request IDs\n if (requestIds.length > 0 && requestIds.length !== requests.length) {\n const missingRequests = difference(\n requestIds,\n requests.map(({ id }) => id),\n );\n if (missingRequests.length > 0) {\n logger.error(\n colors.red(\n `Failed to find the following requests by ID: ${missingRequests.join(\n ',',\n )}.`,\n ),\n );\n process.exit(1);\n }\n }\n\n // Map over the requests\n let total = 0;\n progressBar.start(requests.length, 0);\n await map(\n requests,\n async (request) => {\n // Pull the request identifiers\n const requestEnrichers = await fetchAllRequestEnrichers(client, {\n requestId: request.id,\n });\n const requestEnrichersToRestart = requestEnrichers.filter(\n (requestEnricher) =>\n requestEnricher.enricher.id === enricherId &&\n requestEnricherStatuses.includes(requestEnricher.status),\n );\n await map(requestEnrichersToRestart, async (requestEnricher) => {\n await retryRequestEnricher(client, requestEnricher.id);\n totalRestarted += 1;\n });\n\n // Cache successful upload\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 // Log completion time\n logger.info(\n colors.green(\n `Completed restarting of ${\n requests.length\n } requests and ${totalRestarted} enrichers in \"${\n totalTime / 1000\n }\" seconds.`,\n ),\n );\n}\n","import { map } from '../bluebird';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport {\n RETRY_REQUEST_DATA_SILO,\n fetchRequestDataSilo,\n fetchAllRequests,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Retry a set of RequestDataSilos\n *\n * @param options - Options\n * @returns Number of items marked as completed\n */\nexport async function retryRequestDataSilos({\n requestActions,\n dataSiloId,\n auth,\n concurrency = 20,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** Transcend API key authentication */\n auth: string;\n /** Data Silo ID to pull down jobs for */\n dataSiloId: string;\n /** Concurrency to upload requests in parallel */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses: [RequestStatus.Compiling, RequestStatus.Approving],\n });\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Retrying requests for Data Silo: \"${dataSiloId}\", restarting \"${allRequests.length}\" requests.`,\n ),\n );\n\n let total = 0;\n let skipped = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToRestart) => {\n try {\n const requestDataSilo = await fetchRequestDataSilo(client, {\n requestId: requestToRestart.id,\n dataSiloId,\n });\n\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, RETRY_REQUEST_DATA_SILO, {\n requestDataSiloId: requestDataSilo.id,\n });\n } catch (err) {\n // some requests may not have this data silo connected\n if (!err.message.includes('Failed to find RequestDataSilo')) {\n throw err;\n }\n skipped += 1;\n }\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully notified Transcend in \"${\n totalTime / 1000\n }\" seconds for ${total} requests, ${skipped} requests were skipped because data silo was not attached to the request!`,\n ),\n );\n return allRequests.length;\n}\n","import { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport { map } from '../bluebird';\nimport colors from 'colors';\nimport { groupBy } from 'lodash-es';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\nimport {\n PrivacyRequest,\n RequestIdentifier,\n buildTranscendGraphQLClient,\n createSombraGotInstance,\n fetchAllRequestIdentifiers,\n fetchAllRequests,\n} from '../graphql';\nimport { logger } from '../../logger';\n\nexport interface ExportedPrivacyRequest extends PrivacyRequest {\n /** Request identifiers */\n requestIdentifiers: RequestIdentifier[];\n}\n\n/**\n * Pull down a list of privacy requests\n *\n * @param options - Options\n * @returns The requests with request identifiers and requests formatted for CSV\n */\nexport async function pullPrivacyRequests({\n auth,\n sombraAuth,\n actions = [],\n statuses = [],\n identifierSearch,\n pageLimit = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n createdAtBefore,\n skipRequestIdentifiers = false,\n createdAtAfter,\n isTest,\n}: {\n /** Transcend API key authentication */\n auth: string;\n /** Search for a specific identifier */\n identifierSearch?: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Statuses to filter on */\n statuses?: RequestStatus[];\n /** The request action to fetch */\n actions?: RequestAction[];\n /** Page limit when fetching requests */\n pageLimit?: number;\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Return test requests */\n isTest?: boolean;\n /** Skip fetching request identifier */\n skipRequestIdentifiers?: boolean;\n}): Promise<{\n /** All request information with attached identifiers */\n requestsWithRequestIdentifiers: ExportedPrivacyRequest[];\n /** Requests that are formatted for CSV */\n requestsFormattedForCsv: {\n [k in string]: string | null | number | boolean;\n }[];\n}> {\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 // Log date range\n let dateRange = '';\n if (createdAtBefore) {\n dateRange += ` before ${createdAtBefore.toISOString()}`;\n }\n if (createdAtAfter) {\n dateRange += `${\n dateRange ? ', and' : ''\n } after ${createdAtAfter.toISOString()}`;\n }\n\n // Log out\n logger.info(\n colors.magenta(\n `${\n actions.length > 0\n ? `Pulling requests of type \"${actions.join('\" , \"')}\"`\n : 'Pulling all requests'\n }${dateRange}`,\n ),\n );\n\n // fetch the requests\n const requests = await fetchAllRequests(client, {\n actions,\n text: identifierSearch,\n statuses,\n createdAtBefore,\n createdAtAfter,\n isTest,\n });\n\n // Fetch the request identifiers for those requests\n const requestsWithRequestIdentifiers = skipRequestIdentifiers\n ? requests.map((request) => ({\n ...request,\n requestIdentifiers: [],\n }))\n : await map(\n requests,\n async (request) => {\n const requestIdentifiers = await fetchAllRequestIdentifiers(\n client,\n sombra,\n {\n requestId: request.id,\n },\n );\n return {\n ...request,\n requestIdentifiers,\n };\n },\n {\n concurrency: pageLimit,\n },\n );\n\n logger.info(\n colors.magenta(`Pulled ${requestsWithRequestIdentifiers.length} requests`),\n );\n\n // Write out to CSV\n const data = requestsWithRequestIdentifiers.map(\n ({\n attributeValues,\n requestIdentifiers,\n id,\n email,\n type,\n status,\n subjectType,\n details,\n createdAt,\n country,\n locale,\n origin,\n countrySubDivision,\n isSilent,\n isTest,\n coreIdentifier,\n purpose,\n ...request\n }) => ({\n 'Request ID': id,\n 'Created At': createdAt,\n Email: email,\n 'Core Identifier': coreIdentifier,\n 'Request Type': type,\n 'Data Subject Type': subjectType,\n Status: status,\n Country: country,\n 'Country Sub Division': countrySubDivision,\n Details: details,\n Origin: origin,\n 'Silent Mode': isSilent,\n 'Is Test Request': isTest,\n Language: locale,\n 'Purpose Trigger Name': purpose?.title || purpose?.name || '',\n 'Purpose Trigger Value': purpose?.consent?.toString() || '',\n ...(purpose?.enrichedPreferences || []).reduce((acc, p) => {\n const title = p.preferenceTopic?.title.defaultMessage || p.name;\n return title\n ? {\n ...acc,\n [title]: p.selectValues\n ? p.selectValues.map((x) => x.name).join(';')\n : p.selectValue?.name || p.booleanValue,\n }\n : acc;\n }, {}),\n ...request,\n ...Object.entries(groupBy(attributeValues, 'attributeKey.name')).reduce(\n (acc, [name, values]) =>\n Object.assign(acc, {\n [name]: values.map(({ name }) => name).join(','),\n }),\n {},\n ),\n ...Object.entries(groupBy(requestIdentifiers, 'name')).reduce(\n (acc, [name, values]) =>\n Object.assign(acc, {\n [name]: values.map(({ value }) => value).join(','),\n }),\n {},\n ),\n }),\n );\n\n return { requestsWithRequestIdentifiers, requestsFormattedForCsv: data };\n}\n","import { map } from '../bluebird';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport {\n CHANGE_REQUEST_DATA_SILO_STATUS,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n fetchRequestDataSilos,\n fetchRequestDataSilosCount,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { RequestStatus } from '@transcend-io/privacy-types';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Given a data silo ID, mark all open request data silos as skipped\n *\n * @param options - Options\n * @returns Number of items skipped\n */\nexport async function skipRequestDataSilos({\n dataSiloId,\n auth,\n concurrency = 50,\n maxUploadPerChunk = 50000,\n status = 'SKIPPED',\n transcendUrl = DEFAULT_TRANSCEND_API,\n requestStatuses = [RequestStatus.Compiling, RequestStatus.Secondary],\n}: {\n /** Transcend API key authentication */\n auth: string;\n /** Data Silo ID to pull down jobs for */\n dataSiloId: string;\n /** Status to set */\n status?: 'SKIPPED' | 'RESOLVED';\n /** Upload concurrency */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Request statuses to mark as completed */\n requestStatuses?: RequestStatus[];\n /** Maximum number of items to mark skipped per go */\n maxUploadPerChunk?: number;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n\n // Determine total number of request data silos\n const requestDataSiloCount = await fetchRequestDataSilosCount(client, {\n dataSiloId,\n requestStatuses,\n });\n\n logger.info(\n colors.magenta(\n `Marking ${requestDataSiloCount} request data silos as completed`,\n ),\n );\n\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 total = 0;\n progressBar.start(requestDataSiloCount, 0);\n\n // fetch all RequestDataSilos that are open\n while (total < requestDataSiloCount) {\n const requestDataSilos = await fetchRequestDataSilos(client, {\n dataSiloId,\n requestStatuses,\n limit: maxUploadPerChunk,\n // eslint-disable-next-line no-loop-func\n onProgress: (numUpdated) => {\n total += numUpdated / 2;\n progressBar.update(total);\n },\n });\n\n await map(\n requestDataSilos,\n // eslint-disable-next-line no-loop-func\n async (requestDataSilo) => {\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 += 0.5;\n progressBar.update(total);\n },\n { concurrency },\n );\n }\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully skipped \"${requestDataSiloCount}\" requests in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n return requestDataSiloCount;\n}\n","import { map } from '../bluebird';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport {\n REMOVE_REQUEST_IDENTIFIERS,\n fetchAllRequests,\n fetchAllRequestIdentifierMetadata,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Remove a set of unverified request identifier\n *\n * @param options - Options\n * @returns Number of items marked as completed\n */\nexport async function removeUnverifiedRequestIdentifiers({\n requestActions,\n identifierNames,\n auth,\n concurrency = 20,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** Transcend API key authentication */\n auth: string;\n /** The set of identifier names to remove */\n identifierNames: string[];\n /** Concurrency to upload requests in parallel */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses: [RequestStatus.Enriching],\n });\n\n // Notify Transcend\n logger.info(colors.magenta('Fetched requests in preflight/enriching state.'));\n\n let total = 0;\n let processed = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToRestart) => {\n const requestIdentifiers = await fetchAllRequestIdentifierMetadata(\n client,\n { requestId: requestToRestart.id },\n );\n const clearOut = requestIdentifiers\n .filter(\n ({ isVerifiedAtLeastOnce, name }) =>\n isVerifiedAtLeastOnce === false && identifierNames.includes(name),\n )\n .map(({ id }) => id);\n\n if (clearOut.length > 0) {\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, REMOVE_REQUEST_IDENTIFIERS, {\n input: {\n requestId: requestToRestart.id,\n requestIdentifierIds: clearOut,\n },\n });\n processed += clearOut.length;\n }\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully cleared out unverified identifiers \"${\n totalTime / 1000\n }\" seconds for ${total} requests, ${processed} identifiers were cleared out!`,\n ),\n );\n return allRequests.length;\n}\n","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","/**\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","/**\n * Extract an HTTP status code from a thrown error (got compatible).\n *\n * @param err - Unknown error thrown by network call\n * @returns HTTP status code, if present\n */\nexport function getErrorStatus(err: unknown): number | undefined {\n // Swallow unknowns carefully—never throw from an error handler.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const anyErr = err as any;\n return anyErr?.response?.statusCode ?? anyErr?.response?.status;\n}\n","/**\n * Extract a human-readable error message from a thrown error.\n *\n * Tries to parse JSON bodies that follow common REST/GraphQL error patterns:\n * { error: { message: string } }\n * { errors: [{ message: string }, ...] }\n *\n * Falls back to `err.message` or 'Unknown error'.\n *\n * @param err - Unknown error thrown by network call\n * @returns A concise error string safe to log/show\n */\nexport function extractErrorMessage(err: unknown): string {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const anyErr = err as any;\n let errorMsg = anyErr?.response?.body || anyErr?.message || 'Unknown error';\n\n // Try to parse as JSON; if not parsable, leave as-is.\n try {\n const parsed = JSON.parse(errorMsg);\n // Typical shapes: errors[], error.errors[], error.message\n const candidates = parsed.errors ||\n parsed.error?.errors || [parsed.error?.message || parsed.error];\n\n const msgs = Array.isArray(candidates) ? candidates : [candidates];\n errorMsg = msgs.filter(Boolean).join(', ');\n } catch {\n // not JSON, ignore\n }\n return errorMsg;\n}\n","/**\n * Sleep in a promise\n *\n * @param sleepTime - The time to sleep in milliseconds.\n * @returns Resolves promise\n */\nexport function sleepPromise(sleepTime: number): Promise<number> {\n return new Promise((resolve) => {\n setTimeout(() => resolve(sleepTime), sleepTime);\n });\n}\n","/**\n * Split an array roughly in half. Stable for even/odd lengths.\n *\n * @param entries - Items to split\n * @returns A tuple [left, right] halves\n */\nexport function splitInHalf<T>(entries: T[]): [T[], T[]] {\n const mid = Math.floor(entries.length / 2);\n return [entries.slice(0, mid), entries.slice(mid)];\n}\n","import { sleepPromise } from './sleepPromise';\nimport { getErrorStatus } from './getErrorStatus';\nimport { extractErrorMessage } from './extractErrorMessage';\n\nexport interface RetryPolicy {\n /** Maximum retry attempts (not counting the initial try) */\n maxAttempts: number;\n /** Fixed delay between attempts in milliseconds */\n delayMs: number;\n /**\n * Decide whether a given error should be retried.\n *\n * @param status - HTTP status code (if known)\n * @param message - Extracted error message (if known)\n */\n shouldRetry(status?: number, message?: string): boolean;\n}\n\n/**\n * Retry a single async operation according to the provided policy.\n * The operation is executed once initially, then up to `maxAttempts` retries.\n *\n * @param op - Operation to run\n * @param policy - Retry policy\n * @param onBackoff - Observer called before each retry (for logging/metrics)\n * @returns Result of the operation if it eventually succeeds\n * @throws The last error encountered if all retries fail\n */\nexport async function retrySamePromise<T>(\n op: () => Promise<T>,\n policy: RetryPolicy,\n onBackoff: (note: string) => void,\n): Promise<T> {\n let attempt = 0;\n\n // eslint-disable-next-line no-constant-condition\n while (true) {\n try {\n // First pass and any subsequent retries run the same op.\n return await op();\n } catch (err) {\n attempt += 1;\n\n // Use shared helpers for status + human-readable message extraction\n const status = getErrorStatus(err);\n const msg = extractErrorMessage(err);\n\n const canRetry =\n attempt <= policy.maxAttempts && policy.shouldRetry(status, msg);\n\n if (!canRetry) {\n // Surface the final error to the caller, which may then split/fail.\n throw err;\n }\n\n onBackoff(\n `Retrying after status=${status} attempt=${attempt}/${policy.maxAttempts} — ${msg}`,\n );\n await sleepPromise(policy.delayMs);\n // Loop to retry\n }\n }\n}\n","/**\n * Limits the number of records in the returned object to a maximum.\n * For entries beyond the max, sets their value to `true`.\n *\n * @param obj - Object\n * @param max - Maximum number of entries to retain original value.\n * @returns Object with keys mapped to their value or `true` if over the limit.\n */\nexport function limitRecords<T>(\n obj: Record<string, T>,\n max: number,\n): Record<string, T | true> {\n return Object.entries(obj).reduce((acc, [userId, value], i) => {\n acc[userId] = i < max ? value : true;\n return acc;\n }, {} as Record<string, T | true>);\n}\n","/**\n * Tracks counts over time and calculates rates within a specified time window.\n *\n * This class maintains a rolling window of count \"buckets\" (timestamped values)\n * and provides methods to add new counts and compute the rate of events over a\n * configurable time window.\n *\n * Example usage:\n * ```typescript\n * const counter = new RateCounter();\n * counter.add(5); // Add 5 events\n * const rate = counter.rate(60_000); // Get rate over last 60 seconds\n * ```\n */\nexport class RateCounter {\n private buckets: Array<{\n /** Timestamp of the bucket */\n t: number;\n /** Number of events in the bucket */\n n: number;\n }> = [];\n\n /**\n * Adds a new count to the counter.\n *\n * @param n - The number of events to add to the counter.\n */\n add(n: number): void {\n const now = Date.now();\n this.buckets.push({ t: now, n });\n // keep last 2 minutes of buckets\n const cutoff = now - 120_000;\n while (this.buckets.length && this.buckets[0].t < cutoff) {\n this.buckets.shift();\n }\n }\n\n /**\n * rate over the last `windowMs` milliseconds\n *\n * @param windowMs - The time window in milliseconds to calculate the rate over.\n * @returns The average rate of events per second over the specified time window.\n */\n rate(windowMs: number): number {\n const now = Date.now();\n const cutoff = now - windowMs;\n let sum = 0;\n for (let i = this.buckets.length - 1; i >= 0; i -= 1) {\n const b = this.buckets[i];\n if (b.t < cutoff) break;\n sum += b.n;\n }\n return sum / (windowMs / 1000);\n }\n}\n","import { readFileSync } from 'node:fs';\n\n/**\n * Safely reads the contents of a file as a UTF-8 string.\n * Returns an empty string if the path is not provided or if reading fails.\n *\n * @param p - The path to the file to read.\n * @returns The file contents as a string, or an empty string on error.\n */\nexport function readSafe(p?: string): string {\n try {\n return p ? readFileSync(p, 'utf8') : '';\n } catch {\n return '';\n }\n}\n","import { join } from 'node:path';\nimport { readdirSync, statSync } from 'node:fs';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport type { LocalContext } from '../../context';\n\n/**\n * Validate flags and collect Parquet file paths from a directory.\n * On validation error, the provided `exit` function is called.\n *\n * @param directory - the directory containing Parquet files\n * @param localContext - the context of the command, used for logging and exit\n * @returns an array of valid Parquet file paths\n */\nexport function collectParquetFilesOrExit(\n directory: string | undefined,\n localContext: LocalContext,\n): string[] {\n if (!directory) {\n logger.error(colors.red('A --directory must be provided.'));\n localContext.process.exit(1);\n }\n\n let files: string[] = [];\n try {\n const entries = readdirSync(directory);\n files = entries\n .filter((f) => f.endsWith('.parquet'))\n .map((f) => join(directory, f))\n .filter((p) => {\n try {\n return statSync(p).isFile();\n } catch {\n return false;\n }\n });\n } catch (err) {\n logger.error(colors.red(`Failed to read directory: ${directory}`));\n logger.error(colors.red((err as Error).message));\n localContext.process.exit(1);\n }\n\n if (files.length === 0) {\n logger.error(\n colors.red(`No Parquet files found in directory: ${directory}`),\n );\n localContext.process.exit(1);\n }\n logger.info(colors.green(`Found: ${files.join(', ')} parquet files`));\n return files;\n}\n","import { mkdirSync, rmSync, existsSync } from 'node:fs';\nimport { dirname, join, parse } from 'node:path';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport type { DuckDBConnection, DuckDBInstance } from '@duckdb/node-api';\n\n/** Progress callback used by the parent runner to surface progress to the UI. */\ntype OnProgress = (processed: number, total?: number) => void;\n\n/**\n * Options for converting a single Parquet file into a single CSV file.\n */\nexport type ParquetToCsvOneFileOptions = {\n /** Absolute or relative path to the input `.parquet` file. */\n filePath: string;\n /**\n * Directory where the output CSV will be written.\n * If omitted, the CSV is written next to the input file.\n */\n outputDir?: string;\n /**\n * When true, removes a pre-existing output file with the same name before writing.\n * Useful for re-runs; ignored if the file does not exist.\n */\n clearOutputDir: boolean;\n /**\n * Optional progress hook. Called with the number of processed records.\n * `total` is not computed here; it will be `undefined`.\n */\n onProgress?: OnProgress;\n};\n\n/**\n * Convert a single Parquet file to a single CSV file (1:1) using DuckDB.\n *\n * Output naming: `${basename}.csv` in `outputDir ?? dirname(filePath)`.\n *\n * Errors:\n * - Throws on I/O failures or DuckDB execution errors.\n *\n * Why DuckDB?\n * - Robust reader for many Parquet dialects (e.g., Spark output, nested types, timestamps).\n * - Streaming COPY handles large files without loading everything into JS memory.\n *\n * What this does:\n * - Opens an in-memory DuckDB database (no `.db` file created).\n * - Optionally disables temp spilling to disk (so only your CSV is written).\n * - Executes a single `COPY (SELECT * FROM read_parquet(...)) TO ...` statement.\n * - Produces exactly one CSV per input Parquet (no chunking or rotation).\n *\n * Notes & defaults:\n * - DuckDBInstance: `:memory:` (ephemeral). No persistent DB file is created.\n * - Temp files: disabled via `PRAGMA temp_directory=''` (best-effort; ignored if unsupported).\n * - CSV format: header row, comma delimiter, double-quote quoting, empty string for NULL.\n * - Progress: DuckDB COPY doesn't expose row-level progress via the JS API; we emit a\n * best-effort final callback.\n *\n * Requirements:\n * - `@duckdb/node-api` npm package installed and available at runtime.\n * - Supported platform binary (mac arm64/x64, linux x64, windows x64).\n *\n * @param opts - Conversion options\n * @param DuckDb - DuckDB instance to use\n * @returns Promise<void> when the CSV has been written\n */\nexport async function parquetToCsvOneFile(\n opts: ParquetToCsvOneFileOptions,\n DuckDb: typeof DuckDBInstance,\n): Promise<void> {\n const { filePath, outputDir, clearOutputDir, onProgress } = opts;\n\n const baseDir = outputDir || dirname(filePath);\n const { name: baseName } = parse(filePath);\n const outPath = join(baseDir, `${baseName}.csv`);\n\n // Ensure output directory exists\n mkdirSync(baseDir, { recursive: true });\n\n // Remove any pre-existing output file if requested\n if (clearOutputDir && existsSync(outPath)) {\n try {\n rmSync(outPath, { force: true });\n } catch (err) {\n logger.warn(\n colors.yellow(\n `Could not remove existing output file ${outPath}: ${\n (err as Error).message\n }`,\n ),\n );\n }\n }\n\n // In-memory DB: no .db file created on disk\n const db = await DuckDb.create(':memory:');\n const conn = await db.connect();\n\n try {\n // Optional: prevent DuckDB from creating temp files on disk (best-effort).\n // Some versions may ignore or error; we ignore such errors safely.\n await runIgnoreError(conn, \"PRAGMA temp_directory='';\");\n\n // Optionally: cap memory to encourage in-memory execution or fail-fast\n // (commented out by default; uncomment to enforce a limit)\n // await runIgnoreError(conn, \"PRAGMA memory_limit='4GB';\");\n\n // Ensure stable CSV settings: header, comma delimiter, double quotes, empty string for NULLs.\n // Escape single quotes for SQL string literals\n const q = (p: string): string => `'${p.replace(/'/g, \"''\")}'`;\n\n // Use COPY with a subquery so DuckDB streams Parquet -> CSV efficiently.\n const sql = `\n COPY (SELECT * FROM read_parquet(${q(filePath)}))\n TO ${q(outPath)}\n (HEADER, DELIMITER ',', QUOTE '\"', ESCAPE '\"', NULL '');\n `;\n\n await run(conn, sql);\n\n // Best-effort progress notification (DuckDB JS API doesn't expose progress for COPY)\n onProgress?.(0, undefined);\n\n logger.info(colors.green(`Wrote CSV → ${outPath}`));\n } finally {\n // Close connection + db handles gracefully\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await disposeSafe(conn as any);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await disposeSafe(db as any);\n }\n}\n\n/* =============================================================================\n * DuckDB helpers\n * =============================================================================\n */\n\n/**\n * Execute a SQL statement on a DuckDB connection and dispose the result.\n *\n * @param conn - DuckDB connection\n * @param sql - SQL string to run\n * @returns Promise<void>\n */\nasync function run(conn: DuckDBConnection, sql: string): Promise<void> {\n const result = await conn.run(sql);\n // The high-level API returns a Result; ensure we dispose it to free buffers.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await disposeSafe(result as any);\n}\n\n/**\n * Execute a SQL statement but ignore any error that occurs.\n * Useful for best-effort PRAGMAs that may not be supported across versions.\n *\n * @param conn - DuckDB connection\n * @param sql - SQL string to run\n * @returns Promise<void>\n */\nasync function runIgnoreError(\n conn: DuckDBConnection,\n sql: string,\n): Promise<void> {\n try {\n await run(conn, sql);\n } catch {\n // ignore\n }\n}\n\n/**\n * Dispose a DuckDB resource (connection or instance) if present.\n *\n * @param handle - Object exposing an async `dispose()` method\n * @returns Promise<void>\n */\nasync function disposeSafe(\n handle:\n | {\n /** Dispose handler */\n dispose: () => Promise<void>;\n }\n | null\n | undefined,\n): Promise<void> {\n if (!handle || typeof handle.dispose !== 'function') return;\n try {\n await handle.dispose();\n } catch {\n // ignore\n }\n}\n","export const DAY_MS = 24 * 60 * 60 * 1000;\nexport const HOUR_MS = 60 * 60 * 1000;\nexport const FIVE_MIN_MS = 5 * 60 * 1000;\n\n/**\n * Clamp 1..50 per API spec\n *\n * @param n - Number\n * @returns Clamped number\n */\nexport const clampPageSize = (n?: number): number =>\n Math.max(1, Math.min(50, n ?? 50));\n\n/**\n * TRUE UTC day start (00:00:00Z)\n *\n * @param d - Date\n * @returns Day start\n */\nexport const startOfUtcDay = (d: Date): Date =>\n new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()));\n\n/**\n * TRUE UTC hour start (HH:00:00Z)\n *\n * @param d - Date\n * @returns Hour start\n */\nexport const startOfHour = (d: Date): Date =>\n new Date(\n Date.UTC(\n d.getUTCFullYear(),\n d.getUTCMonth(),\n d.getUTCDate(),\n d.getUTCHours(),\n ),\n );\n\n/**\n * Add ms safely\n *\n * @param d - Date\n * @param ms - Milliseconds to add\n * @returns New date\n */\nexport const addMs = (d: Date, ms: number): Date => new Date(d.getTime() + ms);\n\n/**\n * Add whole UTC days (exclusive bound helper)\n *\n * @param d - Date\n * @param n - Number of days to add\n * @returns New date\n */\nexport const addDaysUtc = (d: Date, n: number): Date =>\n new Date(d.getTime() + n * DAY_MS);\n","import * as fastcsv from 'fast-csv';\nimport { createWriteStream, writeFileSync, appendFileSync } from 'node:fs';\n\nimport { ObjByString } from '@transcend-io/type-utils';\n\n/**\n * Escape a CSV value\n *\n * @param value - Value to escape\n * @returns Escaped value\n */\nfunction escapeCsvValue(value: string): string {\n if (value.includes('\"') || value.includes(',') || value.includes('\\n')) {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n }\n return value;\n}\n\n/**\n * Write a csv to file synchronously, overwriting any existing content\n *\n * @param filePath - File to write out to\n * @param data - Data to write\n * @param headers - Headers. If true, use object keys as headers. If array, use provided headers.\n */\nexport function writeCsvSync(\n filePath: string,\n data: ObjByString[],\n headers: string[],\n): void {\n const rows: string[][] = [];\n\n rows.push(headers);\n rows.push(...data.map((row) => Object.values(row)));\n\n // Build CSV content with proper escaping\n const csvContent = rows\n .map((row) => row.map(escapeCsvValue).join(','))\n .join('\\n');\n\n // Write to file, overwriting existing content\n writeFileSync(filePath, csvContent);\n}\n\n/**\n * Initialize a CSV file by writing only the header row (or an empty file if no headers).\n *\n * @param filePath - CSV path\n * @param headers - Ordered list of column names; if empty, creates/empties the file\n */\nexport function initCsvFile(filePath: string, headers: string[]): void {\n if (!headers || headers.length === 0) {\n writeFileSync(filePath, '');\n return;\n }\n const headerLine = headers.map(escapeCsvValue).join(',');\n writeFileSync(filePath, `${headerLine}\\n`);\n}\n\n/**\n * Append rows to CSV using an explicit header order (no header line).\n * Values are written in the order of `headerOrder`.\n *\n * @param filePath - CSV path\n * @param data - Row objects\n * @param headerOrder - Column order to apply\n */\nexport function appendCsvRowsOrdered(\n filePath: string,\n data: ObjByString[],\n headerOrder: string[],\n): void {\n if (!data.length) return;\n\n const lines = data.map((row) => {\n const vals = headerOrder.map((key) => {\n const v = row[key];\n return v == null ? '' : String(v);\n });\n return vals.map(escapeCsvValue).join(',');\n });\n\n appendFileSync(filePath, `${lines.join('\\n')}\\n`);\n}\n\n/**\n * Append data to an existing csv file synchronously (legacy, uses Object.values order).\n * Prefer appendCsvRowsOrdered for deterministic column order.\n *\n * @param filePath - File to append to\n * @param data - Data to append\n */\nexport function appendCsvSync(filePath: string, data: ObjByString[]): void {\n // Convert data to CSV rows\n const rows = data.map((row) => Object.values(row));\n\n // Build CSV content with proper escaping\n const csvContent = rows\n .map((row) => row.map(escapeCsvValue).join(','))\n .join('\\n');\n\n // Append to file with leading newline\n appendFileSync(filePath, `\\n${csvContent}`);\n}\n\n/**\n * Write a csv to file asynchronously\n *\n * @param filePath - File to write out to\n * @param data - Data to write\n * @param headers - Headers\n */\nexport async function writeCsv(\n filePath: string,\n data: ObjByString[],\n headers: boolean | string[] = true,\n): Promise<void> {\n const ws = createWriteStream(filePath);\n await new Promise<void>((resolve, reject) => {\n try {\n const stream = fastcsv\n .write(data, { headers, objectMode: true })\n .on('error', reject);\n\n ws.on('error', reject);\n ws.on('finish', () => resolve());\n\n stream.pipe(ws);\n } catch (err) {\n reject(err);\n }\n });\n}\n\n/**\n * Parse a file path into a base name and extension\n *\n * @param filePath - File path to parse\n * @returns Base name and extension\n */\nexport function parseFilePath(filePath: string): {\n /** Base name of the file */\n baseName: string;\n /** Extension of the file */\n extension: string;\n} {\n const lastDotIndex = filePath.lastIndexOf('.');\n return {\n baseName:\n lastDotIndex !== -1 ? filePath.substring(0, lastDotIndex) : filePath,\n extension: lastDotIndex !== -1 ? filePath.substring(lastDotIndex) : '.csv',\n };\n}\n\n/**\n * Convert an object row into values aligned to header order\n *\n * @param row - Row object\n * @param headerOrder - Header order\n * @returns Aligned row object\n */\nfunction rowToValues(\n row: ObjByString,\n headerOrder: string[],\n): Record<string, unknown> {\n // fast-csv with objectMode expects objects; we ensure consistent key ordering\n // by building a new object with keys in headerOrder.\n const ordered: Record<string, unknown> = {};\n for (const key of headerOrder) {\n // Preserve undefined -> becomes empty cell in CSV\n ordered[key] = row[key];\n }\n return ordered;\n}\n\n/**\n * Await the 'drain' event when backpressure indicates buffering\n *\n * @param stream - Writable stream\n * @returns Promise that resolves on 'drain'\n */\nfunction waitForDrain(stream: NodeJS.WritableStream): Promise<void> {\n return new Promise((resolve) => {\n stream.once('drain', resolve);\n });\n}\n\n/**\n * Stream a large CSV dataset to a single file with proper backpressure handling.\n * (Kept for completeness; not used by the incremental write path.)\n *\n * @param filePath - File to write out to\n * @param data - Data to write (iterated without buffering the entire file content)\n * @param headers - If true, infer from first row; if string[], use provided; if false, omit header row\n * @returns Array with a single written file path\n */\nexport async function writeLargeCsv(\n filePath: string,\n data: ObjByString[],\n headers: boolean | string[] = true,\n): Promise<string[]> {\n // Determine header order\n let headerOrder: string[] | false;\n if (Array.isArray(headers)) {\n headerOrder = headers;\n } else if (headers === true) {\n headerOrder = data.length > 0 ? Object.keys(data[0]) : [];\n } else {\n headerOrder = false;\n }\n\n const ws = createWriteStream(filePath);\n const csvStream = fastcsv.format<ObjByString, ObjByString>({\n headers: headerOrder || undefined,\n objectMode: true,\n });\n\n // Pipe CSV stream into file write stream\n const piping = csvStream.pipe(ws);\n\n const completion = new Promise<void>((resolve, reject) => {\n piping.on('finish', () => resolve());\n piping.on('error', reject);\n csvStream.on('error', reject);\n ws.on('error', reject);\n });\n\n // Stream rows with backpressure handling\n for (const row of data) {\n const toWrite = headerOrder ? rowToValues(row, headerOrder) : row;\n const ok = csvStream.write(toWrite);\n if (!ok) {\n // Respect backpressure: wait until the internal buffer drains\n await waitForDrain(csvStream);\n }\n }\n\n // Signal end of input and wait for finish\n csvStream.end();\n await completion;\n\n return [filePath];\n}\n","import type {\n GraphQLClient,\n RequestDocument,\n Variables,\n} from 'graphql-request';\nimport { logger } from '../../logger';\nimport colors from 'colors';\nimport { sleepPromise } from '../helpers';\n\nconst MAX_RETRIES = 4;\n\nconst KNOWN_ERRORS = [\n 'syntax error',\n 'got invalid value',\n 'Client error',\n 'cannot affect row a second time',\n 'GRAPHQL_VALIDATION_FAILED',\n];\n\n/**\n * Make a GraphQL request with retries\n *\n * @param client - GraphQL client\n * @param document - document\n * @param variables - Variable\n * @param requestHeaders - Headers\n * @param maxRequests - Max number of requests\n * @returns Response\n */\nexport async function makeGraphQLRequest<T, V extends Variables = Variables>(\n client: GraphQLClient,\n document: RequestDocument,\n variables?: V,\n requestHeaders?: Record<string, string> | string[][] | Headers,\n maxRequests = MAX_RETRIES,\n): Promise<T> {\n let retryCount = 0;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n try {\n const result = await client.request(document, variables, requestHeaders);\n return result as T;\n } catch (err) {\n if (err.message.includes('API key is invalid')) {\n logger.error(\n colors.red(\n 'API key is invalid. ' +\n 'Please ensure that the key provided to `transcendAuth` has the proper scope and is not expired, ' +\n 'and that `transcendUrl` corresponds to the correct backend for your organization.',\n ),\n );\n process.exit(1);\n }\n\n if (KNOWN_ERRORS.some((msg) => err.message.includes(msg))) {\n throw err;\n }\n\n // wait for rate limit to resolve\n if (err.message.startsWith('Client error: Too many requests')) {\n const rateLimitResetAt = err.response.headers?.get('x-ratelimit-reset');\n const sleepTime = rateLimitResetAt\n ? new Date(rateLimitResetAt).getTime() - new Date().getTime() + 100\n : 1000 * 10;\n logger.log(\n colors.yellow(\n `DETECTED RATE LIMIT: ${err.message}. Sleeping for ${sleepTime}ms`,\n ),\n );\n\n await sleepPromise(sleepTime);\n }\n\n if (retryCount >= maxRequests) {\n throw err;\n }\n retryCount += 1;\n logger.log(\n colors.yellow(\n `Retrying failed request (${retryCount} / ${maxRequests}): ${err.message}`,\n ),\n );\n }\n }\n}\n","import { GraphQLClient } from 'graphql-request';\nimport { IdentifierType, RequestAction } from '@transcend-io/privacy-types';\nimport { CREATE_IDENTIFIER, IDENTIFIERS, NEW_IDENTIFIER_TYPES } from './gqls';\nimport { keyBy, uniq, flatten, difference } from 'lodash-es';\nimport { TranscendInput } from '../../codecs';\nimport { logger } from '../../logger';\nimport colors from 'colors';\nimport { mapSeries } from '../bluebird';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\n\nexport interface Identifier {\n /** ID of identifier */\n id: string;\n /** Name of identifier */\n name: string;\n /** The type of identifier */\n type: IdentifierType;\n /** Regular expression to */\n regex: string;\n /** The set of options that the identifier */\n selectOptions: string[];\n /** Whether identifier is enabled on privacy center */\n privacyCenterVisibility: RequestAction[];\n /** Enabled data subjects that are exposed this identifier on the privacy center */\n dataSubjects: {\n /** type of data subjects */\n type: string;\n }[];\n /** Whether identifier is a required field in privacy center form */\n isRequiredInForm: boolean;\n /** Identifier placeholder text */\n placeholder: string;\n /** Display title for identifier */\n displayTitle: {\n /** Default message */\n defaultMessage: string;\n };\n /** Display description for identifier */\n displayDescription: {\n /** Default */\n defaultMessage: string;\n };\n /** Display order */\n displayOrder: number;\n /** does this identifier uniquely identify a consent record */\n isUniqueOnPreferenceStore: boolean;\n}\n\nconst PAGE_SIZE = 20;\n\n/**\n * Fetch all identifiers in the organization\n *\n * @param client - GraphQL client\n * @returns All identifiers in the organization\n */\nexport async function fetchAllIdentifiers(\n client: GraphQLClient,\n): Promise<Identifier[]> {\n const identifiers: Identifier[] = [];\n let offset = 0;\n\n // Whether to continue looping\n let shouldContinue = false;\n do {\n const {\n identifiers: { nodes },\n } = await makeGraphQLRequest<{\n /** Identifiers */\n identifiers: {\n /** List */\n nodes: Identifier[];\n };\n }>(client, IDENTIFIERS, {\n first: PAGE_SIZE,\n offset,\n });\n identifiers.push(...nodes);\n offset += PAGE_SIZE;\n shouldContinue = nodes.length === PAGE_SIZE;\n } while (shouldContinue);\n\n return identifiers.sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/**\n * Fetch all identifiers and if any are found in the config that are\n * missing, create those identifiers.\n *\n * @param input - Transcend input\n * @param client - GraphQL client\n * @param skipPublish - When true, skip publishing to privacy center\n * @returns A map from identifier name to Identifier\n */\nexport async function fetchIdentifiersAndCreateMissing(\n {\n enrichers = [],\n 'data-silos': dataSilos = [],\n identifiers = [],\n }: TranscendInput,\n client: GraphQLClient,\n skipPublish = false,\n): Promise<{ [k in string]: Identifier }> {\n // Grab all existing identifiers\n const allIdentifiers = await fetchAllIdentifiers(client);\n\n // Create a map\n const identifiersByName = keyBy(allIdentifiers, 'name');\n\n // Determine expected set of identifiers\n const expectedIdentifiers = uniq([\n ...flatten(\n enrichers.map((enricher) => [\n enricher['input-identifier'],\n ...enricher['output-identifiers'],\n ]),\n ),\n ...flatten(dataSilos.map((dataSilo) => dataSilo['identity-keys'])),\n ...identifiers.map(({ name }) => name),\n ]).filter((x) => !!x);\n const missingIdentifiers = difference(\n expectedIdentifiers,\n allIdentifiers.map(({ name }) => name),\n );\n\n // If there are missing identifiers, create new ones\n if (missingIdentifiers.length > 0) {\n logger.info(\n colors.magenta(\n `Creating ${missingIdentifiers.length} new identifiers...`,\n ),\n );\n const { newIdentifierTypes } = await makeGraphQLRequest<{\n /** Query response */\n newIdentifierTypes: {\n /** Name of identifier type remaining */\n name: string;\n }[];\n }>(client, NEW_IDENTIFIER_TYPES);\n const nativeTypesRemaining = newIdentifierTypes.map(({ name }) => name);\n await mapSeries(missingIdentifiers, async (identifier) => {\n logger.info(colors.magenta(`Creating identifier ${identifier}...`));\n const { createIdentifier } = await makeGraphQLRequest<{\n /** createIdentifier Response */\n createIdentifier: {\n /** Created identifier */\n identifier: Identifier;\n };\n }>(client, CREATE_IDENTIFIER, {\n input: {\n name: identifier,\n type: nativeTypesRemaining.includes(identifier!)\n ? identifier\n : 'custom',\n skipPublish,\n },\n });\n logger.info(colors.green(`Created identifier ${identifier}!`));\n\n identifiersByName[identifier!] = createIdentifier.identifier;\n });\n }\n return identifiersByName;\n}\n","import { TeamInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { mapSeries } from '../bluebird';\nimport { UPDATE_TEAM, CREATE_TEAM } from './gqls';\nimport { logger } from '../../logger';\nimport { keyBy } from 'lodash-es';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport colors from 'colors';\nimport { fetchAllTeams, Team } from './fetchAllTeams';\n\n/**\n * Input to create a new team\n *\n * @param client - GraphQL client\n * @param team - Input\n * @returns Created team\n */\nexport async function createTeam(\n client: GraphQLClient,\n team: TeamInput,\n): Promise<Pick<Team, 'id' | 'name'>> {\n const input = {\n name: team.name,\n description: team.description,\n ssoTitle: team['sso-title'],\n ssoDepartment: team['sso-department'],\n ssoGroup: team['sso-group'],\n scopes: team.scopes,\n userEmails: team.users,\n };\n\n const { createTeam } = await makeGraphQLRequest<{\n /** Create team mutation */\n createTeam: {\n /** Created team */\n team: Team;\n };\n }>(client, CREATE_TEAM, {\n input,\n });\n return createTeam.team;\n}\n\n/**\n * Input to update teams\n *\n * @param client - GraphQL client\n * @param input - Team input to update\n * @param teamId - ID of team\n * @returns Updated team\n */\nexport async function updateTeam(\n client: GraphQLClient,\n input: TeamInput,\n teamId: string,\n): Promise<Pick<Team, 'id' | 'name'>> {\n const { updateTeam } = await makeGraphQLRequest<{\n /** Update team mutation */\n updateTeam: {\n /** Updated team */\n team: Team;\n };\n }>(client, UPDATE_TEAM, {\n input: {\n id: teamId,\n name: input.name,\n description: input.description,\n ssoTitle: input['sso-title'],\n ssoDepartment: input['sso-department'],\n ssoGroup: input['sso-group'],\n scopes: input.scopes,\n userEmails: input.users,\n },\n });\n return updateTeam.team;\n}\n\n/**\n * Sync the teams\n *\n * @param client - GraphQL client\n * @param inputs - Inputs to create\n * @returns True if run without error, returns false if an error occurred\n */\nexport async function syncTeams(\n client: GraphQLClient,\n inputs: TeamInput[],\n): Promise<boolean> {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${inputs.length}\" teams...`));\n\n let encounteredError = false;\n\n // Fetch existing\n const existingTeams = await fetchAllTeams(client);\n\n // Look up by name\n const teamsByName: { [k in string]: Pick<Team, 'id' | 'name'> } = keyBy(\n existingTeams,\n 'name',\n );\n\n // Create new teams\n const newTeams = inputs.filter((input) => !teamsByName[input.name]);\n const updatedTeams = inputs.filter((input) => !!teamsByName[input.name]);\n\n // Create new teams\n await mapSeries(newTeams, async (team) => {\n try {\n const newTeam = await createTeam(client, team);\n teamsByName[newTeam.name] = newTeam;\n logger.info(colors.green(`Successfully created team \"${team.name}\"!`));\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to sync team \"${team.name}\"! - ${err.message}`),\n );\n }\n });\n\n // Update all teams\n await mapSeries(updatedTeams, async (input) => {\n try {\n const newTeam = await updateTeam(\n client,\n input,\n teamsByName[input.name].id,\n );\n teamsByName[newTeam.name] = newTeam;\n logger.info(colors.green(`Successfully updated team \"${input.name}\"!`));\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to sync team \"${input.name}\"! - ${err.message}`),\n );\n }\n });\n\n return !encounteredError;\n}\n","import { PromptPartialInput } from '../../codecs';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { UPDATE_PROMPT_PARTIALS, CREATE_PROMPT_PARTIAL } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { map } from '../bluebird';\nimport { fetchAllPromptPartials } from './fetchPromptPartials';\nimport { keyBy } from 'lodash-es';\nimport { logger } from '../../logger';\n\n/**\n * Create a new prompt partial\n *\n * @param client - GraphQL client\n * @param input - Prompt input\n * @returns Prompt partial ID\n */\nexport async function createPromptPartial(\n client: GraphQLClient,\n input: {\n /** Title of prompt partial */\n title: string;\n /** Prompt content */\n content: string;\n },\n): Promise<string> {\n const {\n createPromptPartial: { promptPartial },\n } = await makeGraphQLRequest<{\n /** createPromptPartial mutation */\n createPromptPartial: {\n /** Prompt partial */\n promptPartial: {\n /** ID */\n id: string;\n };\n };\n }>(client, CREATE_PROMPT_PARTIAL, {\n input,\n });\n logger.info(\n colors.green(`Successfully created prompt partial \"${input.title}\"!`),\n );\n return promptPartial.id;\n}\n\n/**\n * Update a set of existing prompt partials\n *\n * @param client - GraphQL client\n * @param input - Prompt input\n */\nexport async function updatePromptPartials(\n client: GraphQLClient,\n input: [PromptPartialInput, string][],\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_PROMPT_PARTIALS, {\n input: {\n promptPartials: input.map(([input, id]) => ({\n ...input,\n id,\n })),\n },\n });\n logger.info(\n colors.green(`Successfully updated ${input.length} prompt partials!`),\n );\n}\n\n/**\n * Sync the prompt partials\n *\n * @param client - GraphQL client\n * @param promptPartials - PromptPartials\n * @param concurrency - Concurrency\n * @returns True if synced successfully\n */\nexport async function syncPromptPartials(\n client: GraphQLClient,\n promptPartials: PromptPartialInput[],\n concurrency = 20,\n): Promise<boolean> {\n let encounteredError = false;\n logger.info(\n colors.magenta(`Syncing \"${promptPartials.length}\" prompt partials...`),\n );\n\n // Index existing prompt partials\n const existing = await fetchAllPromptPartials(client);\n const promptPartialByTitle = keyBy(existing, 'title');\n\n // Determine which promptPartials are new vs existing\n const mapPromptPartialsToExisting = promptPartials.map((promptInput) => [\n promptInput,\n promptPartialByTitle[promptInput.title]?.id,\n ]);\n\n // Create the new promptPartials\n const newPromptPartials = mapPromptPartialsToExisting\n .filter(([, existing]) => !existing)\n .map(([promptInput]) => promptInput as PromptPartialInput);\n try {\n logger.info(\n colors.magenta(\n `Creating \"${newPromptPartials.length}\" new prompt partials...`,\n ),\n );\n await map(\n newPromptPartials,\n async (prompt) => {\n await createPromptPartial(client, prompt);\n },\n {\n concurrency,\n },\n );\n logger.info(\n colors.green(\n `Successfully synced ${newPromptPartials.length} prompt partials!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to create prompt partials! - ${err.message}`),\n );\n }\n\n // Update existing promptPartials\n const existingPromptPartials = mapPromptPartialsToExisting.filter(\n (x): x is [PromptPartialInput, string] => !!x[1],\n );\n try {\n logger.info(\n colors.magenta(\n `Updating \"${existingPromptPartials.length}\" prompt partials...`,\n ),\n );\n await updatePromptPartials(client, existingPromptPartials);\n logger.info(\n colors.green(\n `Successfully updated \"${existingPromptPartials.length}\" prompt partials!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to create prompt partials! - ${err.message}`),\n );\n }\n\n logger.info(\n colors.green(`Synced \"${promptPartials.length}\" prompt partials!`),\n );\n\n // Return true upon success\n return !encounteredError;\n}\n","import { PromptGroupInput } from '../../codecs';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport { UPDATE_PROMPT_GROUPS, CREATE_PROMPT_GROUP } from './gqls';\nimport { makeGraphQLRequest } from './makeGraphQLRequest';\nimport { map } from '../bluebird';\nimport { fetchAllPromptGroups } from './fetchPromptGroups';\nimport { keyBy } from 'lodash-es';\nimport { logger } from '../../logger';\nimport { fetchAllPrompts } from './fetchPrompts';\n\nexport interface EditPromptGroupInput {\n /** Title of prompt group */\n title: string;\n /** Prompt group description */\n description: string;\n /** Prompt IDs */\n promptIds: string[];\n}\n\n/**\n * Create a new prompt group\n *\n * @param client - GraphQL client\n * @param input - Prompt input\n * @returns Prompt group ID\n */\nexport async function createPromptGroup(\n client: GraphQLClient,\n input: EditPromptGroupInput,\n): Promise<string> {\n const {\n createPromptGroup: { promptGroup },\n } = await makeGraphQLRequest<{\n /** createPromptGroup mutation */\n createPromptGroup: {\n /** Prompt group */\n promptGroup: {\n /** ID */\n id: string;\n };\n };\n }>(client, CREATE_PROMPT_GROUP, {\n input,\n });\n logger.info(\n colors.green(`Successfully created prompt group \"${input.title}\"!`),\n );\n return promptGroup.id;\n}\n\n/**\n * Update a set of existing prompt groups\n *\n * @param client - GraphQL client\n * @param input - Prompt input\n */\nexport async function updatePromptGroups(\n client: GraphQLClient,\n input: [EditPromptGroupInput, string][],\n): Promise<void> {\n await makeGraphQLRequest(client, UPDATE_PROMPT_GROUPS, {\n input: {\n promptGroups: input.map(([input, id]) => ({\n ...input,\n id,\n })),\n },\n });\n logger.info(\n colors.green(`Successfully updated ${input.length} prompt groups!`),\n );\n}\n\n/**\n * Sync the prompt groups\n *\n * @param client - GraphQL client\n * @param promptGroups - PromptGroups\n * @param concurrency - Concurrency\n * @returns True if synced successfully\n */\nexport async function syncPromptGroups(\n client: GraphQLClient,\n promptGroups: PromptGroupInput[],\n concurrency = 20,\n): Promise<boolean> {\n let encounteredError = false;\n logger.info(\n colors.magenta(`Syncing \"${promptGroups.length}\" prompt groups...`),\n );\n\n // Index existing prompt groups\n const existing = await fetchAllPromptGroups(client);\n const existingPrompts = await fetchAllPrompts(client);\n const promptByTitle = keyBy(existingPrompts, 'title');\n const promptGroupByTitle = keyBy(existing, 'title');\n\n // Determine which promptGroups are new vs existing\n const mapPromptGroupsToExisting = promptGroups.map((promptInput) => [\n promptInput,\n promptGroupByTitle[promptInput.title]?.id,\n ]);\n\n // Create the new promptGroups\n const newPromptGroups = mapPromptGroupsToExisting\n .filter(([, existing]) => !existing)\n .map(([promptInput]) => promptInput as PromptGroupInput);\n try {\n logger.info(\n colors.magenta(\n `Creating \"${newPromptGroups.length}\" new prompt groups...`,\n ),\n );\n await map(\n newPromptGroups,\n async (prompt) => {\n await createPromptGroup(client, {\n ...prompt,\n promptIds: prompt.prompts.map((title) => {\n const prompt = promptByTitle[title];\n if (!prompt) {\n throw new Error(`Failed to find prompt with title: \"${title}\"`);\n }\n return prompt.id;\n }),\n });\n },\n {\n concurrency,\n },\n );\n logger.info(\n colors.green(\n `Successfully synced ${newPromptGroups.length} prompt groups!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create prompt groups! - ${err.message}`));\n }\n\n // Update existing promptGroups\n const existingPromptGroups = mapPromptGroupsToExisting.filter(\n (x): x is [PromptGroupInput, string] => !!x[1],\n );\n try {\n logger.info(\n colors.magenta(\n `Updating \"${existingPromptGroups.length}\" prompt groups...`,\n ),\n );\n await updatePromptGroups(\n client,\n existingPromptGroups.map(([{ prompts, ...input }, id]) => [\n {\n ...input,\n promptIds: prompts.map((title) => {\n const prompt = promptByTitle[title];\n if (!prompt) {\n throw new Error(`Failed to find prompt with title: \"${title}\"`);\n }\n return prompt.id;\n }),\n },\n id,\n ]),\n );\n logger.info(\n colors.green(\n `Successfully updated \"${existingPromptGroups.length}\" prompt groups!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(colors.red(`Failed to create prompt groups! - ${err.message}`));\n }\n\n logger.info(colors.green(`Synced \"${promptGroups.length}\" prompt groups!`));\n\n // Return true upon success\n return !encounteredError;\n}\n","/* eslint-disable max-lines */\nimport { TranscendInput } from '../../codecs';\nimport { GraphQLClient } from 'graphql-request';\nimport { logger } from '../../logger';\nimport colors from 'colors';\nimport { map } from '../bluebird';\nimport {\n fetchIdentifiersAndCreateMissing,\n Identifier,\n} from './fetchIdentifiers';\nimport { syncIdentifier } from './syncIdentifier';\nimport { syncEnricher } from './syncEnrichers';\nimport { syncAttribute } from './syncAttribute';\nimport { syncDataSiloDependencies, syncDataSilos } from './syncDataSilos';\nimport { syncCookies } from './syncCookies';\nimport {\n fetchAllDataSubjects,\n ensureAllDataSubjectsExist,\n} from './fetchDataSubjects';\nimport { syncTeams } from './syncTeams';\nimport { syncDataSubject } from './syncDataSubject';\nimport { fetchApiKeys } from './fetchApiKeys';\nimport { syncPrompts } from './syncPrompts';\nimport { syncPolicies } from './syncPolicies';\nimport { syncIntlMessages } from './syncIntlMessages';\nimport { syncPrivacyCenter } from './syncPrivacyCenter';\nimport { syncConsentManager } from './syncConsentManager';\nimport { fetchAllAttributes } from './fetchAllAttributes';\nimport { syncBusinessEntities } from './syncBusinessEntities';\nimport { syncDataFlows } from './syncDataFlows';\nimport { syncAction } from './syncAction';\nimport { syncTemplate } from './syncTemplates';\nimport { fetchAllActions } from './fetchAllActions';\nimport { syncPromptPartials } from './syncPromptPartials';\nimport { syncPromptGroups } from './syncPromptGroups';\nimport { syncAgents } from './syncAgents';\nimport { syncActionItemCollections } from './syncActionItemCollections';\nimport { syncActionItems } from './syncActionItems';\nimport { syncAgentFunctions } from './syncAgentFunctions';\nimport { syncAgentFiles } from './syncAgentFiles';\nimport { syncVendors } from './syncVendors';\nimport { syncDataCategories } from './syncDataCategories';\nimport { syncProcessingPurposes } from './syncProcessingPurposes';\nimport { syncProcessingActivities } from './syncProcessingActivities';\nimport { syncPartitions } from './syncPartitions';\n\nconst CONCURRENCY = 10;\n\n/**\n * Sync the yaml input back to Transcend using the GraphQL APIs\n *\n * @param input - The yml input\n * @param client - GraphQL client\n * @param pageSize - Page size\n * @returns True if an error was encountered\n */\nexport async function syncConfigurationToTranscend(\n input: TranscendInput,\n client: GraphQLClient,\n {\n pageSize = 50,\n // TODO: https://transcend.height.app/T-23779\n publishToPrivacyCenter = true,\n classifyService = false,\n deleteExtraAttributeValues = false,\n }: {\n /** Page size */\n pageSize?: number;\n /** When true, skip publishing to privacy center */\n publishToPrivacyCenter?: boolean;\n /** When true, delete any attributes being synced up */\n deleteExtraAttributeValues?: boolean;\n /** classify data flow service if missing */\n classifyService?: boolean;\n },\n): Promise<boolean> {\n let encounteredError = false;\n\n logger.info(colors.magenta(`Fetching data with page size ${pageSize}...`));\n\n const {\n templates,\n attributes,\n actions,\n identifiers,\n 'data-subjects': dataSubjects,\n 'business-entities': businessEntities,\n enrichers,\n cookies,\n 'consent-manager': consentManager,\n 'data-silos': dataSilos,\n 'data-flows': dataFlows,\n prompts,\n 'prompt-groups': promptGroups,\n 'prompt-partials': promptPartials,\n agents,\n 'agent-functions': agentFunctions,\n 'agent-files': agentFiles,\n vendors,\n 'data-categories': dataCategories,\n 'processing-activities': processingActivities,\n 'processing-purposes': processingPurposes,\n 'action-items': actionItems,\n 'action-item-collections': actionItemCollections,\n teams,\n 'privacy-center': privacyCenter,\n messages,\n policies,\n partitions,\n } = input;\n\n const [identifierByName, dataSubjectsByName, apiKeyTitleMap] =\n await Promise.all([\n // Ensure all identifiers are created and create a map from name -> identifier.id\n enrichers || identifiers\n ? fetchIdentifiersAndCreateMissing(\n input,\n client,\n !publishToPrivacyCenter,\n )\n : ({} as { [k in string]: Identifier }),\n // Grab all data subjects in the organization\n dataSilos || dataSubjects || enrichers || processingActivities\n ? ensureAllDataSubjectsExist(input, client)\n : {},\n // Grab API keys\n dataSilos &&\n dataSilos\n .map((dataSilo) => dataSilo['api-key-title'] || [])\n .reduce((acc, lst) => acc + lst.length, 0) > 0\n ? fetchApiKeys(input, client)\n : {},\n ]);\n\n // Sync consent manager\n if (consentManager) {\n logger.info(colors.magenta('Syncing consent manager...'));\n try {\n await syncConsentManager(client, consentManager);\n logger.info(colors.green('Successfully synced consent manager!'));\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(`Failed to sync consent manager! - ${err.message}`),\n );\n }\n }\n\n // Sync prompts\n if (prompts) {\n const promptsSuccess = await syncPrompts(client, prompts);\n encounteredError = encounteredError || !promptsSuccess;\n }\n if (promptPartials) {\n const promptsSuccess = await syncPromptPartials(client, promptPartials);\n encounteredError = encounteredError || !promptsSuccess;\n }\n if (promptGroups) {\n const promptsSuccess = await syncPromptGroups(client, promptGroups);\n encounteredError = encounteredError || !promptsSuccess;\n }\n\n if (teams) {\n const teamsSuccess = await syncTeams(client, teams);\n encounteredError = encounteredError || !teamsSuccess;\n }\n\n // Sync email templates\n if (templates) {\n logger.info(\n colors.magenta(`Syncing \"${templates.length}\" email templates...`),\n );\n await map(\n templates,\n async (template) => {\n logger.info(colors.magenta(`Syncing template \"${template.title}\"...`));\n try {\n await syncTemplate(template, client);\n logger.info(\n colors.green(`Successfully synced template \"${template.title}\"!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync template \"${template.title}\"! - ${err.message}`,\n ),\n );\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${templates.length}\" email templates!`));\n }\n\n // Sync business entities\n if (businessEntities) {\n const businessEntitySuccess = await syncBusinessEntities(\n client,\n businessEntities,\n );\n encounteredError = encounteredError || !businessEntitySuccess;\n }\n\n // Sync vendors\n if (vendors) {\n const vendorsSuccess = await syncVendors(client, vendors);\n encounteredError = encounteredError || !vendorsSuccess;\n }\n\n // Sync data categories\n if (dataCategories) {\n const dataCategoriesSuccess = await syncDataCategories(\n client,\n dataCategories,\n );\n encounteredError = encounteredError || !dataCategoriesSuccess;\n }\n\n // Sync processing purposes\n if (processingPurposes) {\n const processingPurposesSuccess = await syncProcessingPurposes(\n client,\n processingPurposes,\n );\n encounteredError = encounteredError || !processingPurposesSuccess;\n }\n\n // Sync partitions\n if (partitions) {\n const partitionsSuccess = await syncPartitions(client, partitions);\n encounteredError = encounteredError || !partitionsSuccess;\n }\n\n // Sync agents\n if (agents) {\n const agentsSuccess = await syncAgents(client, agents);\n encounteredError = encounteredError || !agentsSuccess;\n }\n\n // Sync agent functions\n if (agentFunctions) {\n const agentFunctionsSuccess = await syncAgentFunctions(\n client,\n agentFunctions,\n );\n encounteredError = encounteredError || !agentFunctionsSuccess;\n }\n\n // Sync agent files\n if (agentFiles) {\n const agentFilesSuccess = await syncAgentFiles(client, agentFiles);\n encounteredError = encounteredError || !agentFilesSuccess;\n }\n\n // Sync cookies\n if (cookies) {\n const cookiesSuccess = await syncCookies(client, cookies);\n encounteredError = encounteredError || !cookiesSuccess;\n }\n\n // Sync action item collections\n if (actionItemCollections) {\n const actionItemCollectionsSuccess = await syncActionItemCollections(\n client,\n actionItemCollections,\n );\n encounteredError = encounteredError || !actionItemCollectionsSuccess;\n }\n\n // Sync attributes\n if (attributes) {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${attributes.length}\" attributes...`));\n const existingAttributes = await fetchAllAttributes(client);\n await map(\n attributes,\n async (attribute) => {\n const existing = existingAttributes.find(\n (attr) => attr.name === attribute.name,\n );\n\n logger.info(colors.magenta(`Syncing attribute \"${attribute.name}\"...`));\n try {\n await syncAttribute(client, attribute, {\n existingAttribute: existing,\n deleteExtraAttributeValues,\n });\n logger.info(\n colors.green(`Successfully synced attribute \"${attribute.name}\"!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync attribute \"${attribute.name}\"! - ${err.message}`,\n ),\n );\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${attributes.length}\" attributes!`));\n }\n\n // Sync action items\n if (actionItems) {\n const actionItemsSuccess = await syncActionItems(client, actionItems);\n encounteredError = encounteredError || !actionItemsSuccess;\n }\n\n // Sync enrichers\n if (enrichers) {\n logger.info(colors.magenta(`Syncing \"${enrichers.length}\" enrichers...`));\n await map(\n enrichers,\n async (enricher) => {\n logger.info(colors.magenta(`Syncing enricher \"${enricher.title}\"...`));\n try {\n await syncEnricher(client, {\n enricher,\n identifierByName,\n dataSubjectsByName,\n });\n logger.info(\n colors.green(`Successfully synced enricher \"${enricher.title}\"!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync enricher \"${enricher.title}\"! - ${err.message}`,\n ),\n );\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${enrichers.length}\" enrichers!`));\n }\n\n // Sync identifiers\n if (identifiers) {\n // Fetch existing\n logger.info(\n colors.magenta(`Syncing \"${identifiers.length}\" identifiers...`),\n );\n await map(\n identifiers,\n async (identifier) => {\n const existing = identifierByName[identifier.name];\n if (!existing) {\n throw new Error(\n `Failed to find identifier with name: ${identifier.type}. Should have been auto-created by cli.`,\n );\n }\n\n logger.info(\n colors.magenta(`Syncing identifier \"${identifier.type}\"...`),\n );\n try {\n await syncIdentifier(client, {\n identifier,\n dataSubjectsByName,\n identifierId: existing.id,\n skipPublish: !publishToPrivacyCenter,\n });\n logger.info(\n colors.green(\n `Successfully synced identifier \"${identifier.type}\"!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync identifier \"${identifier.type}\"! - ${err.message}`,\n ),\n );\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${identifiers.length}\" identifiers!`));\n }\n\n // Sync actions\n if (actions) {\n // Fetch existing\n logger.info(colors.magenta(`Syncing \"${actions.length}\" actions...`));\n const existingActions = await fetchAllActions(client);\n await map(\n actions,\n async (action) => {\n const existing = existingActions.find(\n (act) => act.type === action.type,\n );\n if (!existing) {\n throw new Error(\n `Failed to find action with type: ${action.type}. Should have already existing in the organization.`,\n );\n }\n\n logger.info(colors.magenta(`Syncing action \"${action.type}\"...`));\n try {\n await syncAction(client, {\n action,\n actionId: existing.id,\n skipPublish: !publishToPrivacyCenter,\n });\n logger.info(\n colors.green(`Successfully synced action \"${action.type}\"!`),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync action \"${action.type}\"! - ${err.message}`,\n ),\n );\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${actions.length}\" actions!`));\n }\n\n // Sync data subjects\n if (dataSubjects) {\n // Fetch existing\n logger.info(\n colors.magenta(`Syncing \"${dataSubjects.length}\" data subjects...`),\n );\n const existingDataSubjects = await fetchAllDataSubjects(client);\n await map(\n dataSubjects,\n async (dataSubject) => {\n const existing = existingDataSubjects.find(\n (subj) => subj.type === dataSubject.type,\n );\n if (!existing) {\n throw new Error(\n `Failed to find data subject with type: ${dataSubject.type}. Should have already existing in the organization.`,\n );\n }\n\n logger.info(\n colors.magenta(`Syncing data subject \"${dataSubject.type}\"...`),\n );\n try {\n await syncDataSubject(client, {\n dataSubject,\n dataSubjectId: existing.id,\n skipPublish: !publishToPrivacyCenter,\n });\n logger.info(\n colors.green(\n `Successfully synced data subject \"${dataSubject.type}\"!`,\n ),\n );\n } catch (err) {\n encounteredError = true;\n logger.info(\n colors.red(\n `Failed to sync data subject \"${dataSubject.type}\"! - ${err.message}`,\n ),\n );\n }\n },\n {\n concurrency: CONCURRENCY,\n },\n );\n logger.info(colors.green(`Synced \"${dataSubjects.length}\" data subjects!`));\n }\n\n // Sync data flows\n if (dataFlows) {\n const syncedDataFlows = await syncDataFlows(\n client,\n dataFlows,\n classifyService,\n );\n encounteredError = encounteredError || !syncedDataFlows;\n }\n\n // Sync privacy center\n if (privacyCenter) {\n const privacyCenterSuccess = await syncPrivacyCenter(client, privacyCenter);\n encounteredError = encounteredError || !privacyCenterSuccess;\n }\n\n // Sync messages\n if (messages) {\n const messagesSuccess = await syncIntlMessages(client, messages);\n encounteredError = encounteredError || !messagesSuccess;\n }\n\n // Sync policies\n if (policies) {\n const policiesSuccess = await syncPolicies(client, policies);\n encounteredError = encounteredError || !policiesSuccess;\n }\n\n // Store dependency updates\n const dependencyUpdates: [string, string[]][] = [];\n // Sync data silos\n if (dataSilos) {\n const { success, dataSiloTitleToId } = await syncDataSilos(\n dataSilos,\n client,\n {\n dataSubjectsByName,\n apiKeysByTitle: apiKeyTitleMap,\n pageSize,\n },\n );\n dataSilos?.forEach((dataSilo) => {\n // Queue up dependency update\n if (dataSilo['deletion-dependencies']) {\n dependencyUpdates.push([\n dataSiloTitleToId[dataSilo.title],\n dataSilo['deletion-dependencies'],\n ]);\n }\n });\n encounteredError = encounteredError || !success;\n }\n\n // Dependencies updated at the end after all data silos are created\n if (dependencyUpdates.length > 0) {\n await syncDataSiloDependencies(client, dependencyUpdates);\n }\n\n // Update processing activities\n if (processingActivities) {\n const processingActivitySuccess = await syncProcessingActivities(\n client,\n processingActivities,\n );\n encounteredError = encounteredError || !processingActivitySuccess;\n }\n\n if (publishToPrivacyCenter) {\n // TODO: https://transcend.height.app/T-23779\n }\n\n return encounteredError;\n}\n/* eslint-enable max-lines */\n"],"x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56],"mappings":"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"}
|