@transcend-io/cli 8.25.3 → 8.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/README.md +53 -13
  2. package/dist/bin/bash-complete.cjs +1 -1
  3. package/dist/bin/cli.cjs +1 -1
  4. package/dist/bin/deprecated-command.cjs +2 -2
  5. package/dist/{chunk-HPERBM2R.cjs → chunk-2MHJ5LZ7.cjs} +2 -2
  6. package/dist/{chunk-HPERBM2R.cjs.map → chunk-2MHJ5LZ7.cjs.map} +1 -1
  7. package/dist/{chunk-EDVVHIFK.cjs → chunk-5TKJLZA2.cjs} +2 -2
  8. package/dist/{chunk-EDVVHIFK.cjs.map → chunk-5TKJLZA2.cjs.map} +1 -1
  9. package/dist/{chunk-FIBHN6CY.cjs → chunk-AZ4GTUNR.cjs} +22 -22
  10. package/dist/chunk-AZ4GTUNR.cjs.map +1 -0
  11. package/dist/{chunk-HJTYLFGJ.cjs → chunk-FTXFBDFW.cjs} +2 -2
  12. package/dist/{chunk-HJTYLFGJ.cjs.map → chunk-FTXFBDFW.cjs.map} +1 -1
  13. package/dist/{chunk-GLXV5XPP.cjs → chunk-K65NYGJM.cjs} +165 -162
  14. package/dist/chunk-K65NYGJM.cjs.map +1 -0
  15. package/dist/{chunk-FGBTRT4J.cjs → chunk-KOXU6674.cjs} +2 -2
  16. package/dist/{chunk-FGBTRT4J.cjs.map → chunk-KOXU6674.cjs.map} +1 -1
  17. package/dist/{chunk-GDPRENOQ.cjs → chunk-L32BTN2M.cjs} +4 -4
  18. package/dist/{chunk-GDPRENOQ.cjs.map → chunk-L32BTN2M.cjs.map} +1 -1
  19. package/dist/{chunk-DV57HBVO.cjs → chunk-L5QUUSVB.cjs} +4 -4
  20. package/dist/{chunk-DV57HBVO.cjs.map → chunk-L5QUUSVB.cjs.map} +1 -1
  21. package/dist/{chunk-UMAN3VT7.cjs → chunk-QAKUAPPO.cjs} +2 -2
  22. package/dist/{chunk-UMAN3VT7.cjs.map → chunk-QAKUAPPO.cjs.map} +1 -1
  23. package/dist/chunk-SONNKP33.cjs +12 -0
  24. package/dist/chunk-SONNKP33.cjs.map +1 -0
  25. package/dist/{chunk-C3ZJMA3A.cjs → chunk-U2XRCT7A.cjs} +2 -2
  26. package/dist/{chunk-C3ZJMA3A.cjs.map → chunk-U2XRCT7A.cjs.map} +1 -1
  27. package/dist/{chunk-7YR2TG7U.cjs → chunk-VEU5LPA6.cjs} +2 -2
  28. package/dist/{chunk-7YR2TG7U.cjs.map → chunk-VEU5LPA6.cjs.map} +1 -1
  29. package/dist/{chunk-5MIDKBL7.cjs → chunk-WGCFVEJZ.cjs} +2 -2
  30. package/dist/{chunk-5MIDKBL7.cjs.map → chunk-WGCFVEJZ.cjs.map} +1 -1
  31. package/dist/{chunk-G6QNUBBK.cjs → chunk-XN6WUCF4.cjs} +2 -2
  32. package/dist/{chunk-G6QNUBBK.cjs.map → chunk-XN6WUCF4.cjs.map} +1 -1
  33. package/dist/{impl-GRQJMVJE.cjs → impl-2CF2PKFH.cjs} +2 -2
  34. package/dist/{impl-GRQJMVJE.cjs.map → impl-2CF2PKFH.cjs.map} +1 -1
  35. package/dist/{impl-DRHYZQSB.cjs → impl-2XEHL54N.cjs} +2 -2
  36. package/dist/{impl-DRHYZQSB.cjs.map → impl-2XEHL54N.cjs.map} +1 -1
  37. package/dist/{impl-FJO7BPTB.cjs → impl-35DXHKNE.cjs} +2 -2
  38. package/dist/{impl-FJO7BPTB.cjs.map → impl-35DXHKNE.cjs.map} +1 -1
  39. package/dist/{impl-QYNAMOYS.cjs → impl-3BLJB5VJ.cjs} +2 -2
  40. package/dist/{impl-QYNAMOYS.cjs.map → impl-3BLJB5VJ.cjs.map} +1 -1
  41. package/dist/impl-3TTJGFRK.cjs +2 -0
  42. package/dist/{impl-O742JPYW.cjs.map → impl-3TTJGFRK.cjs.map} +1 -1
  43. package/dist/impl-43MGE5WS.cjs +2 -0
  44. package/dist/{impl-C3XI35SQ.cjs.map → impl-43MGE5WS.cjs.map} +1 -1
  45. package/dist/{impl-T7EXOBCA.cjs → impl-4GZIUG3H.cjs} +3 -3
  46. package/dist/{impl-T7EXOBCA.cjs.map → impl-4GZIUG3H.cjs.map} +1 -1
  47. package/dist/{impl-4MW5YXMP.cjs → impl-4VNXB52F.cjs} +2 -2
  48. package/dist/{impl-4MW5YXMP.cjs.map → impl-4VNXB52F.cjs.map} +1 -1
  49. package/dist/{impl-5FBCF5HY.cjs → impl-5PPLTGRY.cjs} +2 -2
  50. package/dist/{impl-5FBCF5HY.cjs.map → impl-5PPLTGRY.cjs.map} +1 -1
  51. package/dist/{impl-BPFDJMJY.cjs → impl-7TIKA2O6.cjs} +2 -2
  52. package/dist/{impl-BPFDJMJY.cjs.map → impl-7TIKA2O6.cjs.map} +1 -1
  53. package/dist/{impl-X6RMXDJS.cjs → impl-BEVLBZ2F.cjs} +2 -2
  54. package/dist/{impl-X6RMXDJS.cjs.map → impl-BEVLBZ2F.cjs.map} +1 -1
  55. package/dist/{impl-QTTAMUHI.cjs → impl-CCY7BINI.cjs} +2 -2
  56. package/dist/{impl-QTTAMUHI.cjs.map → impl-CCY7BINI.cjs.map} +1 -1
  57. package/dist/{impl-22JGFXXK.cjs → impl-DEQW3OGQ.cjs} +2 -2
  58. package/dist/{impl-22JGFXXK.cjs.map → impl-DEQW3OGQ.cjs.map} +1 -1
  59. package/dist/{impl-IQVMZJD7.cjs → impl-F2UNSOIO.cjs} +2 -2
  60. package/dist/{impl-IQVMZJD7.cjs.map → impl-F2UNSOIO.cjs.map} +1 -1
  61. package/dist/{impl-M6JBOLVE.cjs → impl-H3J7N77A.cjs} +2 -2
  62. package/dist/{impl-M6JBOLVE.cjs.map → impl-H3J7N77A.cjs.map} +1 -1
  63. package/dist/{impl-YM2OKSJ4.cjs → impl-HZJIVXWT.cjs} +2 -2
  64. package/dist/{impl-YM2OKSJ4.cjs.map → impl-HZJIVXWT.cjs.map} +1 -1
  65. package/dist/{impl-DVNUPZK7.cjs → impl-IQCQDDW7.cjs} +2 -2
  66. package/dist/{impl-DVNUPZK7.cjs.map → impl-IQCQDDW7.cjs.map} +1 -1
  67. package/dist/{impl-I6NMF5QP.cjs → impl-J3FUD3MS.cjs} +5 -5
  68. package/dist/{impl-I6NMF5QP.cjs.map → impl-J3FUD3MS.cjs.map} +1 -1
  69. package/dist/{impl-KJQDZ5CD.cjs → impl-JHP4RJZ4.cjs} +2 -2
  70. package/dist/{impl-KJQDZ5CD.cjs.map → impl-JHP4RJZ4.cjs.map} +1 -1
  71. package/dist/{impl-XWVPG2AO.cjs → impl-JK3TTCKR.cjs} +2 -2
  72. package/dist/{impl-XWVPG2AO.cjs.map → impl-JK3TTCKR.cjs.map} +1 -1
  73. package/dist/{impl-XUBKDJNI.cjs → impl-JYAKR5RR.cjs} +2 -2
  74. package/dist/{impl-XUBKDJNI.cjs.map → impl-JYAKR5RR.cjs.map} +1 -1
  75. package/dist/{impl-JTLAUUYX.cjs → impl-K6MYBWAY.cjs} +2 -2
  76. package/dist/{impl-JTLAUUYX.cjs.map → impl-K6MYBWAY.cjs.map} +1 -1
  77. package/dist/{impl-VINV2XOZ.cjs → impl-KZZC7P5D.cjs} +2 -2
  78. package/dist/{impl-VINV2XOZ.cjs.map → impl-KZZC7P5D.cjs.map} +1 -1
  79. package/dist/{impl-PVIVOTA4.cjs → impl-L74WP6LX.cjs} +2 -2
  80. package/dist/{impl-PVIVOTA4.cjs.map → impl-L74WP6LX.cjs.map} +1 -1
  81. package/dist/{impl-2HC6MNNN.cjs → impl-LUKG7ED6.cjs} +2 -2
  82. package/dist/{impl-2HC6MNNN.cjs.map → impl-LUKG7ED6.cjs.map} +1 -1
  83. package/dist/{impl-52NIQWXG.cjs → impl-MENWC3FS.cjs} +2 -2
  84. package/dist/{impl-52NIQWXG.cjs.map → impl-MENWC3FS.cjs.map} +1 -1
  85. package/dist/{impl-BA6B2C6M.cjs → impl-PK3DXVLW.cjs} +2 -2
  86. package/dist/{impl-BA6B2C6M.cjs.map → impl-PK3DXVLW.cjs.map} +1 -1
  87. package/dist/impl-QVM227RD.cjs +2 -0
  88. package/dist/impl-QVM227RD.cjs.map +1 -0
  89. package/dist/{impl-4CRBCTLC.cjs → impl-S2UBMTKQ.cjs} +2 -2
  90. package/dist/{impl-4CRBCTLC.cjs.map → impl-S2UBMTKQ.cjs.map} +1 -1
  91. package/dist/{impl-PAKRFLP6.cjs → impl-S6GUFHKS.cjs} +2 -2
  92. package/dist/{impl-PAKRFLP6.cjs.map → impl-S6GUFHKS.cjs.map} +1 -1
  93. package/dist/{impl-BGBHVFXR.cjs → impl-SAWOUYGV.cjs} +2 -2
  94. package/dist/{impl-BGBHVFXR.cjs.map → impl-SAWOUYGV.cjs.map} +1 -1
  95. package/dist/{impl-IXVIQGXK.cjs → impl-SBIOFGRE.cjs} +2 -2
  96. package/dist/{impl-IXVIQGXK.cjs.map → impl-SBIOFGRE.cjs.map} +1 -1
  97. package/dist/{impl-M7XLIXX7.cjs → impl-UR7MDG5O.cjs} +2 -2
  98. package/dist/{impl-M7XLIXX7.cjs.map → impl-UR7MDG5O.cjs.map} +1 -1
  99. package/dist/{impl-MSDEMRBZ.cjs → impl-UTDGC4UZ.cjs} +2 -2
  100. package/dist/{impl-MSDEMRBZ.cjs.map → impl-UTDGC4UZ.cjs.map} +1 -1
  101. package/dist/{impl-UDUTUFUT.cjs → impl-UTJTENWY.cjs} +2 -2
  102. package/dist/{impl-UDUTUFUT.cjs.map → impl-UTJTENWY.cjs.map} +1 -1
  103. package/dist/{impl-2YWGSU4V.cjs → impl-VEW5WAK7.cjs} +3 -3
  104. package/dist/{impl-2YWGSU4V.cjs.map → impl-VEW5WAK7.cjs.map} +1 -1
  105. package/dist/{impl-RVJLQVKI.cjs → impl-W33BLTPN.cjs} +2 -2
  106. package/dist/{impl-RVJLQVKI.cjs.map → impl-W33BLTPN.cjs.map} +1 -1
  107. package/dist/{impl-6BPL3Z3G.cjs → impl-WLYI6G4A.cjs} +4 -4
  108. package/dist/{impl-6BPL3Z3G.cjs.map → impl-WLYI6G4A.cjs.map} +1 -1
  109. package/dist/{impl-5Z557CRG.cjs → impl-X5JUJPG5.cjs} +2 -2
  110. package/dist/{impl-5Z557CRG.cjs.map → impl-X5JUJPG5.cjs.map} +1 -1
  111. package/dist/{impl-XCXP4S3J.cjs → impl-XJX7GD3G.cjs} +2 -2
  112. package/dist/{impl-XCXP4S3J.cjs.map → impl-XJX7GD3G.cjs.map} +1 -1
  113. package/dist/{impl-5H7LSGMO.cjs → impl-YZ6LZ2LI.cjs} +2 -2
  114. package/dist/{impl-5H7LSGMO.cjs.map → impl-YZ6LZ2LI.cjs.map} +1 -1
  115. package/dist/index.cjs +3 -3
  116. package/dist/index.cjs.map +1 -1
  117. package/dist/index.d.cts +21 -4
  118. package/package.json +2 -1
  119. package/dist/chunk-FIBHN6CY.cjs.map +0 -1
  120. package/dist/chunk-GLXV5XPP.cjs.map +0 -1
  121. package/dist/chunk-WO3KAASS.cjs +0 -12
  122. package/dist/chunk-WO3KAASS.cjs.map +0 -1
  123. package/dist/impl-C3XI35SQ.cjs +0 -2
  124. package/dist/impl-LVGKFMBD.cjs +0 -2
  125. package/dist/impl-LVGKFMBD.cjs.map +0 -1
  126. package/dist/impl-O742JPYW.cjs +0 -2
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/home/runner/work/cli/cli/dist/chunk-GLXV5XPP.cjs","../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/requests/constants.ts","../src/lib/requests/fuzzyMatchColumns.ts","../src/lib/requests/mapEnumValues.ts","../src/lib/graphql/syncDataSilos.ts","../src/lib/graphql/syncEnrichers.ts","../src/lib/helpers/parquetToCsvOneFile.ts","../src/lib/helpers/writeCsv.ts","../src/lib/graphql/addMessagesToPromptRun.ts"],"names":["DATA_POINTS","gql","DATA_POINT_COUNT","SUB_DATA_POINTS","SUB_DATA_POINTS_COUNT","SUB_DATA_POINTS_WITH_GUESSES","UPDATE_OR_CREATE_DATA_POINT","DATAPOINT_EXPORT","ENTRY_COUNT","DATA_SILOS","DATA_SILO_EXPORT","DATA_SILOS_ENRICHED","UPDATE_DATA_SILOS","CREATE_DATA_SILOS","ENRICHERS","INITIALIZER","CREATE_ENRICHER","UPDATE_ENRICHER","CATALOGS","IDENTIFIERS","NEW_IDENTIFIER_TYPES","CREATE_IDENTIFIER","UPDATE_IDENTIFIER","DATA_SUBJECTS","CREATE_DATA_SUBJECT","UPDATE_DATA_SUBJECT","TOGGLE_DATA_SUBJECT","REPOSITORIES","UPDATE_REPOSITORIES","CREATE_REPOSITORY","API_KEYS","CREATE_API_KEY","DELETE_API_KEY","CREATE_PREFERENCE_ACCESS_TOKENS","ADD_SILO_DISCOVERY_RESULTS","ENABLED_PLUGINS","TEMPLATES","CREATE_TEMPLATE","ORGANIZATION","ATTRIBUTE_KEYS_REQUESTS","SOFTWARE_DEVELOPMENT_KITS","UPDATE_SOFTWARE_DEVELOPMENT_KITS","CREATE_SOFTWARE_DEVELOPMENT_KIT","CODE_PACKAGES","UPDATE_CODE_PACKAGES","CREATE_CODE_PACKAGE","PROMPT_THREADS","POLICIES","UPDATE_POLICIES","REQUESTS","APPROVE_PRIVACY_REQUEST","CANCEL_PRIVACY_REQUEST","UPDATE_PRIVACY_REQUEST","NOTIFY_ADDITIONAL_TIME","MESSAGES","UPDATE_INTL_MESSAGES","REQUEST_ENRICHERS","RETRY_REQUEST_ENRICHER","SKIP_REQUEST_ENRICHER","ASSESSMENT_SECTION_FIELDS","ASSESSMENTS","IMPORT_ONE_TRUST_ASSESSMENT_FORMS","PURPOSES","PREFERENCE_TOPICS","ASSESSMENT_TEMPLATES","PROMPTS","PROMPT_PARTIALS","PROMPT_GROUPS","PROMPTS_WITH_VARIABLES","UPDATE_PROMPTS","CREATE_PROMPT","UPDATE_PROMPT_PARTIALS","CREATE_PROMPT_PARTIAL","UPDATE_PROMPT_GROUPS","CREATE_PROMPT_GROUP","REQUEST_DATA_SILOS","CHANGE_REQUEST_DATA_SILO_STATUS","RETRY_REQUEST_DATA_SILO","REDUCED_REQUESTS_FOR_DATA_SILO_COUNT","TEAMS","CREATE_TEAM","UPDATE_TEAM","REMOVE_REQUEST_IDENTIFIERS","REQUEST_IDENTIFIERS","USERS","REQUEST_FILES","BULK_REQUEST_FILES","REPORT_PROMPT_RUN","ADD_MESSAGES_TO_PROMPT_RUN","GLOBAL_ACTION_ITEM_COLLECTIONS","CREATE_ACTION_ITEM_COLLECTION","UPDATE_ACTION_ITEM_COLLECTION","ATTRIBUTES","CREATE_ATTRIBUTE_VALUES","UPDATE_ATTRIBUTE_VALUES","DELETE_ATTRIBUTE_VALUE","ATTRIBUTE_VALUES","CREATE_ATTRIBUTE","UPDATE_ATTRIBUTE","SET_RESOURCE_ATTRIBUTES","EXPERIENCES","CONSENT_PARTITIONS","CREATE_DATA_FLOWS","UPDATE_DATA_FLOWS","UPDATE_OR_CREATE_COOKIES","DATA_FLOWS","COOKIES","FETCH_CONSENT_MANAGER_ID","FETCH_CONSENT_MANAGER","FETCH_CONSENT_MANAGER_THEME","CREATE_CONSENT_MANAGER","UPDATE_CONSENT_MANAGER_VERSION","UPDATE_CONSENT_MANAGER_TO_LATEST","DEPLOY_CONSENT_MANAGER","UPDATE_CONSENT_MANAGER_DOMAINS","UPDATE_CONSENT_MANAGER_PARTITION","UPDATE_LOAD_OPTIONS","TOGGLE_UNKNOWN_REQUEST_POLICY","TOGGLE_UNKNOWN_COOKIE_POLICY","TOGGLE_TELEMETRY_PARTITION_STRATEGY","TOGGLE_CONSENT_PRECEDENCE","UPDATE_CONSENT_MANAGER_THEME","UPDATE_CONSENT_EXPERIENCE","CREATE_CONSENT_EXPERIENCE","CREATE_CONSENT_PARTITION","CONSENT_MANAGER_ANALYTICS_DATA","BUSINESS_ENTITIES","CREATE_BUSINESS_ENTITY","UPDATE_BUSINESS_ENTITIES","ACTIONS","UPDATE_ACTION","GLOBAL_ACTION_ITEMS","UPDATE_ACTION_ITEMS","CREATE_ACTION_ITEMS","FETCH_PRIVACY_CENTER_ID","DEPLOYED_PRIVACY_CENTER_URL","PRIVACY_CENTER","UPDATE_PRIVACY_CENTER","DETERMINE_LOGIN_METHOD","LOGIN","ASSUME_ROLE","LARGE_LANGUAGE_MODELS","AGENTS","CREATE_AGENT","UPDATE_AGENTS","AGENT_FILES","CREATE_AGENT_FILE","UPDATE_AGENT_FILES","AGENT_FUNCTIONS","CREATE_AGENT_FUNCTION","UPDATE_AGENT_FUNCTIONS","VENDORS","CREATE_VENDOR","UPDATE_VENDORS","DATA_SUB_CATEGORIES","CREATE_DATA_SUB_CATEGORY","UPDATE_DATA_SUB_CATEGORIES","PROCESSING_PURPOSE_SUB_CATEGORIES","CREATE_PROCESSING_PURPOSE_SUB_CATEGORY","UPDATE_PROCESSING_PURPOSE_SUB_CATEGORIES","PROCESSING_ACTIVITIES","CREATE_PROCESSING_ACTIVITY","UPDATE_PROCESSING_ACTIVITIES","SOMBRA_VERSION","NONE","BULK_APPLY","BLANK","IDENTIFIER_BLOCK_LIST","ColumnName","IS_REQUIRED","CAN_APPLY_IN_BULK","CachedFileState","applyEnum","valuesOf","IsoCountryCode","IsoCountrySubdivisionCode","CompletedRequestStatus","SuccessfulRequest","CachedRequestState","fuzzySearch","word1","word2","fuzzysearch","fuzzyMatchColumns","allColumnNames","fuzzyMapName","isRequired","canApplyAll","matchingColumnNames","x","inquirer","mapEnumValues","csvInputs","expectedOutputs","cache","autoCompletePrompt","inputs","item","value","result","enricher"],"mappings":"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","file":"/home/runner/work/cli/cli/dist/chunk-GLXV5XPP.cjs","sourcesContent":[null,"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 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 { 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","/* 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 { mkdirSync, rmSync, existsSync } from 'node:fs';\nimport { dirname, join, parse } from 'node:path';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport { DuckDBInstance, type DuckDBConnection } 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 * @returns Promise<void> when the CSV has been written\n */\nexport async function parquetToCsvOneFile(\n opts: ParquetToCsvOneFileOptions,\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 DuckDBInstance.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","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 * Append data to an existing csv file synchronously\n * Assumes the data structure matches the existing file\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 *\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 { 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"]}
@@ -1,12 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _chunkGLXV5XPPcjs = require('./chunk-GLXV5XPP.cjs');var _chunkZUNVPK23cjs = require('./chunk-ZUNVPK23.cjs');var _chunkHJTYLFGJcjs = require('./chunk-HJTYLFGJ.cjs');var _colors = require('colors'); var _colors2 = _interopRequireDefault(_colors);var _bluebird = require('bluebird');var _cliprogress = require('cli-progress'); var _cliprogress2 = _interopRequireDefault(_cliprogress);var _persistedstate = require('@transcend-io/persisted-state');var _iots = require('io-ts'); var F = _interopRequireWildcard(_iots); var b = _interopRequireWildcard(_iots); var e = _interopRequireWildcard(_iots);var _typeutils = require('@transcend-io/type-utils');var Ie=["ENOTFOUND","ECONNRESET","ETIMEDOUT","504 Gateway Time-out","Task timed out after"];async function Q(f,{maxAttempts:a=3,baseDelayMs:y=250,isRetryable:m=(l,i)=>Ie.some(r=>i.includes(r)),onRetry:c}={}){let l=0;for(;;){l+=1;try{return await f()}catch(i){let r=_nullishCoalesce((i&&(_optionalChain([i, 'access', _2 => _2.response, 'optionalAccess', _3 => _3.body])||i.message)), () => (String(_nullishCoalesce(i, () => ("Unknown error")))));if(!(l<a&&m(i,r)))throw new Error(`Preference query failed after ${l} attempt(s): ${r}`);_optionalChain([c, 'optionalCall', _4 => _4(l,i,r)]);let o=y*2**(l-1),n=Math.floor(Math.random()*y),t=o+n;_chunkZUNVPK23cjs.a.warn(_colors2.default.yellow(`[retry] attempt ${l}/${a-1}; backing off ${t}ms: ${r}`)),await _chunkGLXV5XPPcjs.Xf.call(void 0, t)}}}var _privacytypes = require('@transcend-io/privacy-types');var D=b.intersection([b.type({nodes:b.array(_privacytypes.PreferenceQueryResponseItem)}),b.partial({cursor:b.string})]);async function me(f,{identifiers:a,partitionKey:y,skipLogging:m=!1,concurrency:c=40}){let l=[],i=_chunkHJTYLFGJcjs.b.call(void 0, a,100),r=new Date().getTime(),s=new _cliprogress2.default.SingleBar({},_cliprogress2.default.Presets.shades_classic);m||s.start(a.length,0);let o=0;await _bluebird.map.call(void 0, i,async p=>{let g=await Q(()=>f.post(`v1/preferences/${y}/query`,{json:{filter:{identifiers:p},limit:p.length}}).json(),{onRetry:(w,M,P)=>{_chunkZUNVPK23cjs.a.warn(_colors2.default.yellow(`[RETRY] group size=${p.length} partition=${y} attempt=${w}: ${P}`))}}),u=_typeutils.decodeCodec.call(void 0, D,g);l.push(...u.nodes),o+=p.length,s.update(o)},{concurrency:c}),s.stop();let t=new Date().getTime()-r;return m||_chunkZUNVPK23cjs.a.info(_colors2.default.green(`Completed download in "${t/1e3}" seconds.`)),l}function q({row:f,columnToPurposeName:a,purposeSlugs:y,preferenceTopics:m}){let c={};return Object.entries(a).forEach(([l,{purpose:i,preference:r,valueMapping:s}])=>{if(!y.includes(i))throw new Error(`Invalid purpose slug: ${i}, expected: ${y.join(", ")}`);let o=f[l];if(r){let n=m.find(t=>t.slug===r&&t.purpose.trackingType===i);if(!n){let t=m.filter(p=>p.purpose.trackingType===i).map(p=>p.slug);throw new Error(`Invalid preference slug: ${r} for purpose: ${i}. Allowed preference slugs for purpose are: ${t.join(",")}`)}switch(c[i]||(c[i]={preferences:[]}),c[i].preferences||(c[i].preferences=[]),n.type){case _privacytypes.PreferenceTopicType.Boolean:{let t=s[o];if(t===void 0&&o!=="")throw new Error(`No preference mapping found for value "${o}" in column "${l}" (purpose=${i}, preference=${r})`);if(t==null)return;if(typeof t!="boolean")throw new Error(`Invalid value for boolean preference: ${r}, expected boolean, got: ${o}`);c[i].preferences.push({topic:r,choice:{booleanValue:t}});break}case _privacytypes.PreferenceTopicType.Select:{let t=s[o];if(t===void 0&&o!=="")throw new Error(`No preference mapping found for value "${o}" in column "${l}" (purpose=${i}, preference=${r})`);if(t==null)return;if(typeof t!="string")throw new Error(`Invalid value for select preference: ${r}, expected string, got: ${o}`);let p=t.trim()||null;if(p&&!n.preferenceOptionValues.map(({slug:g})=>g).includes(p))throw new Error(`Invalid value for select preference: ${r}, expected one of: ${n.preferenceOptionValues.map(({slug:g})=>g).join(", ")}, got: ${o}`);c[i].preferences.push({topic:r,choice:{selectValue:p}});break}case _privacytypes.PreferenceTopicType.MultiSelect:{if(typeof o!="string")throw new Error(`Invalid value for multi select preference: ${r}, expected string, got: ${o}`);let t=_chunkGLXV5XPPcjs.oc.call(void 0, o).map(p=>{let g=s[p];if(g===void 0&&o!=="")throw new Error(`No preference mapping found for multi select token "${o}" in column "${l}" (purpose=${i}, preference=${r})`);if(g==null)return null;if(typeof g!="string")throw new Error(`Invalid value for multi select preference: ${r}, expected one of: ${n.preferenceOptionValues.map(({slug:u})=>u).join(", ")}, got: ${p}`);return g}).filter(p=>p!==null).sort((p,g)=>p.localeCompare(g));t.length>0&&c[i].preferences.push({topic:r,choice:{selectValues:t}});break}default:throw new Error(`Unknown preference type: ${n.type}`)}}else{let n=s[o];if(n===void 0&&o!=="")throw new Error(`No preference mapping found for value "${o}" in column "${l}" (purpose=${i}, preference=\u2205)`);if(n===null)return;c[i]?c[i].enabled=n===!0:c[i]={enabled:n===!0}}}),_typeutils.apply.call(void 0, c,(l,i)=>{if(typeof l.enabled!="boolean")throw new Error(`No mapping provided for purpose.enabled=true/false value: ${i}`);return{...l,enabled:l.enabled}})}var _inquirer = require('inquirer'); var _inquirer2 = _interopRequireDefault(_inquirer);var B="[NONE]";async function de(f,a){let y=_chunkHJTYLFGJcjs.j.call(void 0, f.map(c=>Object.keys(c)).flat()),m=_chunkHJTYLFGJcjs.c.call(void 0, y,[...a.identifierColumn?[a.identifierColumn]:[],...Object.keys(a.columnToPurposeName)]);if(!a.timestampColum){let{timestampName:c}=await _inquirer2.default.prompt([{name:"timestampName",message:"Choose the column that will be used as the timestamp of last preference update",type:"list",default:m.find(l=>l.toLowerCase().includes("date"))||m.find(l=>l.toLowerCase().includes("time"))||m[0],choices:[...m,B]}]);a.timestampColum=c}if(_chunkZUNVPK23cjs.a.info(_colors2.default.magenta(`Using timestamp column "${a.timestampColum}"`)),a.timestampColum!==B){let c=f.map((l,i)=>l[a.timestampColum]?null:[i]).filter(l=>!!l).flat();if(c.length>0)throw new Error(`The timestamp column "${a.timestampColum}" is missing a value for the following rows: ${c.join(`
2
- `)}`);_chunkZUNVPK23cjs.a.info(_colors2.default.magenta(`The timestamp column "${a.timestampColum}" is present for all row`))}return a}async function ge(f,a){let y=_chunkHJTYLFGJcjs.j.call(void 0, f.map(r=>Object.keys(r)).flat()),m=_chunkHJTYLFGJcjs.c.call(void 0, y,[...a.identifierColumn?[a.identifierColumn]:[],...Object.keys(a.columnToPurposeName)]);if(!a.identifierColumn){let{identifierName:r}=await _inquirer2.default.prompt([{name:"identifierName",message:"Choose the column that will be used as the identifier to upload consent preferences by",type:"list",default:m.find(s=>s.toLowerCase().includes("email"))||m[0],choices:m}]);a.identifierColumn=r}_chunkZUNVPK23cjs.a.info(_colors2.default.magenta(`Using identifier column "${a.identifierColumn}"`));let c=f.map((r,s)=>r[a.identifierColumn]?null:[s]).filter(r=>!!r).flat();if(c.length>0){let r=`The identifier column "${a.identifierColumn}" is missing a value for the following rows: ${c.join(", ")}`;if(_chunkZUNVPK23cjs.a.warn(_colors2.default.yellow(r)),!await _chunkGLXV5XPPcjs.Rf.call(void 0, {message:"Would you like to skip rows missing an identifier?"}))throw new Error(r);let o=f.length;f=f.filter(n=>n[a.identifierColumn]),_chunkZUNVPK23cjs.a.info(_colors2.default.yellow(`Skipped ${o-f.length} rows missing an identifier`))}_chunkZUNVPK23cjs.a.info(_colors2.default.magenta(`The identifier column "${a.identifierColumn}" is present for all rows`));let l=_chunkHJTYLFGJcjs.d.call(void 0, f,a.identifierColumn),i=Object.entries(l).filter(([,r])=>r.length>1);if(i.length>0){let r=`The identifier column "${a.identifierColumn}" has duplicate values for the following rows: ${i.slice(0,10).map(([o,n])=>`${o} (${n.length})`).join(`
3
- `)}`;if(_chunkZUNVPK23cjs.a.warn(_colors2.default.yellow(r)),!await _chunkGLXV5XPPcjs.Rf.call(void 0, {message:"Would you like to automatically take the latest update?"}))throw new Error(r);f=Object.entries(l).map(([,o])=>o.sort((t,p)=>new Date(p[a.timestampColum]).getTime()-new Date(t[a.timestampColum]).getTime())[0]).filter(o=>o)}return{currentState:a,preferences:f}}async function ye(f,a,{purposeSlugs:y,preferenceTopics:m,forceTriggerWorkflows:c}){let l=_chunkHJTYLFGJcjs.j.call(void 0, f.map(s=>Object.keys(s)).flat()),i=_chunkHJTYLFGJcjs.c.call(void 0, l,[...a.identifierColumn?[a.identifierColumn]:[],...a.timestampColum?[a.timestampColum]:[]]);if(i.length===0){if(c)return a;throw new Error("No other columns to process")}let r=[...y,...m.map(s=>`${s.purpose.trackingType}->${s.slug}`)];return await _bluebird.mapSeries.call(void 0, i,async s=>{let o=_chunkHJTYLFGJcjs.j.call(void 0, f.map(t=>t[s])),n=a.columnToPurposeName[s];if(n)_chunkZUNVPK23cjs.a.info(_colors2.default.magenta(`Column "${s}" is associated with purpose "${n.purpose}"`));else{let{purposeName:t}=await _inquirer2.default.prompt([{name:"purposeName",message:`Choose the purpose that column ${s} is associated with`,type:"list",default:r.find(u=>u.startsWith(y[0])),choices:r}]),[p,g]=t.split("->");n={purpose:p,preference:g||null,valueMapping:{}}}await _bluebird.mapSeries.call(void 0, o,async t=>{if(n.valueMapping[t]!==void 0){_chunkZUNVPK23cjs.a.info(_colors2.default.magenta(`Value "${t}" is associated with purpose value "${n.valueMapping[t]}"`));return}if(n.preference===null){let{purposeValue:p}=await _inquirer2.default.prompt([{name:"purposeValue",message:`Choose the purpose value for value "${t}" associated with purpose "${n.purpose}"`,type:"confirm",default:t!=="false"}]);n.valueMapping[t]=p}if(n.preference!==null){let p=m.find(u=>u.slug===n.preference);if(!p){_chunkZUNVPK23cjs.a.error(_colors2.default.red(`Preference topic "${n.preference}" not found`));return}let g=p.preferenceOptionValues.map(({slug:u})=>u);if(p.type===_privacytypes.PreferenceTopicType.Boolean){let{preferenceValue:u}=await _inquirer2.default.prompt([{name:"preferenceValue",message:`Choose the preference value for "${p.slug}" value "${t}" associated with purpose "${n.purpose}"`,type:"confirm",default:t!=="false"}]);n.valueMapping[t]=u;return}if(p.type===_privacytypes.PreferenceTopicType.Select){let{preferenceValue:u}=await _inquirer2.default.prompt([{name:"preferenceValue",message:`Choose the preference value for "${p.slug}" value "${t}" associated with purpose "${n.purpose}"`,type:"list",choices:g,default:g.find(w=>w===t)}]);n.valueMapping[t]=u;return}if(p.type===_privacytypes.PreferenceTopicType.MultiSelect){let u=_chunkGLXV5XPPcjs.oc.call(void 0, t);await _bluebird.mapSeries.call(void 0, u,async w=>{if(n.valueMapping[w]!==void 0)return;let{preferenceValue:M}=await _inquirer2.default.prompt([{name:"preferenceValue",message:`Choose the preference value for "${p.slug}" value "${w}" associated with purpose "${n.purpose}"`,type:"list",choices:g,default:g.find(P=>P===w)}]);n.valueMapping[w]=M});return}throw new Error(`Unknown preference topic type: ${p.type}`)}}),a.columnToPurposeName[s]=n}),a}function we({currentConsentRecord:f,pendingUpdates:a,preferenceTopics:y}){return Object.entries(a).every(([m,{preferences:c=[],enabled:l}])=>{let i=f.purposes.find(s=>s.purpose===m);return!!i&&i.enabled===l?c.every(({topic:s,choice:o})=>i.preferences&&i.preferences.find(n=>{if(n.topic!==s)return!1;let t=y.find(p=>p.slug===s&&p.purpose.trackingType===m);if(!t)throw new Error(`Could not find preference topic for ${s}`);switch(t.type){case _privacytypes.PreferenceTopicType.Boolean:return n.choice.booleanValue===o.booleanValue;case _privacytypes.PreferenceTopicType.Select:return n.choice.selectValue===o.selectValue;case _privacytypes.PreferenceTopicType.MultiSelect:let p=(n.choice.selectValues||[]).sort(),g=(o.selectValues||[]).sort();return p.length===g.length&&p.every((u,w)=>u===g[w]);default:throw new Error(`Unknown preference topic type: ${t.type}`)}})):!1})}function Pe({currentConsentRecord:f,pendingUpdates:a,preferenceTopics:y,log:m}){return!!Object.entries(a).find(([c,{preferences:l=[],enabled:i}])=>{let r=f.purposes.find(s=>s.purpose===c);return r?r.enabled!==i?(m&&_chunkZUNVPK23cjs.a.warn(`Purpose ${c} enabled value conflict for user ${f.userId}. Pending Value: ${i}, Current Value: ${r.enabled}`),!0):!!l.find(({topic:s,choice:o})=>{let n=(r.preferences||[]).find(u=>u.topic===s);if(!n)return m&&_chunkZUNVPK23cjs.a.warn(`No existing preference found for topic ${s} in purpose ${c} for user ${f.userId}.`),!1;let t=y.find(u=>u.slug===s&&u.purpose.trackingType===c);if(!t)throw new Error(`Could not find preference topic for ${s}`);let p,g;switch(t.type){case _privacytypes.PreferenceTopicType.Boolean:return p=n.choice.booleanValue!==o.booleanValue,m&&_chunkZUNVPK23cjs.a.warn(`Preference topic ${s} boolean value conflict for user ${f.userId}. Expected: ${o.booleanValue}, Found: ${n.choice.booleanValue}`),p;case _privacytypes.PreferenceTopicType.Select:return g=n.choice.selectValue!==o.selectValue,m&&_chunkZUNVPK23cjs.a.warn(`Preference topic ${s} select value conflict for user ${f.userId}. Expected: ${o.selectValue}, Found: ${n.choice.selectValue}`),g;case _privacytypes.PreferenceTopicType.MultiSelect:let u=(n.choice.selectValues||[]).sort(),w=(o.selectValues||[]).sort();return g=u.length!==w.length||!u.every((M,P)=>M===w[P]),m&&_chunkZUNVPK23cjs.a.warn(`Preference topic ${s} multi-select value conflict for user ${f.userId}. Expected: ${w.join(", ")}, Found: ${u.join(", ")}`),g;default:throw new Error(`Unknown preference topic type: ${t.type}`)}}):(m&&_chunkZUNVPK23cjs.a.warn(`No existing purpose found for ${c} in consent record for ${f.userId}.`),!1)})}async function $e({file:f,sombra:a,purposeSlugs:y,preferenceTopics:m,partitionKey:c,skipExistingRecordCheck:l,forceTriggerWorkflows:i},r){let s=new Date().getTime(),o=r.getValue("fileMetadata");_chunkZUNVPK23cjs.a.info(_colors2.default.magenta(`Reading in file: "${f}"`));let n=_chunkGLXV5XPPcjs.rc.call(void 0, f,F.record(F.string,F.string)),t={columnToPurposeName:{},pendingSafeUpdates:{},pendingConflictUpdates:{},skippedUpdates:{},...o[f]||{},lastFetchedAt:new Date().toISOString()};t=await de(n,t),o[f]=t,await r.setValue(o,"fileMetadata");let p=await ge(n,t);t=p.currentState,n=p.preferences,o[f]=t,await r.setValue(o,"fileMetadata"),t=await ye(n,t,{preferenceTopics:m,purposeSlugs:y,forceTriggerWorkflows:i}),o[f]=t,await r.setValue(o,"fileMetadata");let g=n.map(P=>P[t.identifierColumn]),u=l?[]:await me(a,{identifiers:g.map(P=>({value:P})),partitionKey:c}),w=_chunkHJTYLFGJcjs.e.call(void 0, u,"userId");t.pendingConflictUpdates={},t.pendingSafeUpdates={},t.skippedUpdates={},n.forEach(P=>{let R=P[t.identifierColumn],I=q({row:P,columnToPurposeName:t.columnToPurposeName,preferenceTopics:m,purposeSlugs:y}),C=w[R];if(i&&!C)throw new Error(`No existing consent record found for user with id: ${R}.
4
- When 'forceTriggerWorkflows' is set all the user identifiers should contain a consent record`);if(C&&we({currentConsentRecord:C,pendingUpdates:I,preferenceTopics:m})&&!i){t.skippedUpdates[R]=P;return}if(C&&Pe({currentConsentRecord:C,pendingUpdates:I,preferenceTopics:m})){t.pendingConflictUpdates[R]={row:P,record:C};return}t.pendingSafeUpdates[R]=P}),o[f]=t,await r.setValue(o,"fileMetadata");let M=new Date().getTime();_chunkZUNVPK23cjs.a.info(_colors2.default.green(`Successfully pre-processed file: "${f}" in ${(M-s)/1e3}s`))}var Ce=e.type({purpose:e.string,preference:e.union([e.string,e.null]),valueMapping:e.record(e.string,e.union([e.string,e.boolean,e.null,e.undefined]))}),Xt=e.record(e.string,Ce),Ne=e.type({name:e.string,isUniqueOnPreferenceStore:e.boolean}),Zt=e.record(e.string,Ne),Ae=e.intersection([e.type({columnToPurposeName:e.record(e.string,Ce),lastFetchedAt:e.string,pendingSafeUpdates:e.record(e.string,e.record(e.string,e.string)),pendingConflictUpdates:e.record(e.string,e.type({record:_privacytypes.PreferenceQueryResponseItem,row:e.record(e.string,e.string)})),skippedUpdates:e.record(e.string,e.record(e.string,e.string))}),e.partial({identifierColumn:e.string,timestampColum:e.string})]),er=e.record(e.string,e.union([e.boolean,_privacytypes.PreferenceUpdateItem])),tr=e.record(e.string,e.union([e.boolean,e.record(e.string,e.string)])),rr=e.record(e.string,e.type({uploadedAt:e.string,error:e.string,update:_privacytypes.PreferenceUpdateItem})),or=e.record(e.string,e.type({record:_privacytypes.PreferenceQueryResponseItem,row:e.record(e.string,e.string)})),nr=e.record(e.string,e.record(e.string,e.string)),Te=e.type({fileMetadata:e.record(e.string,Ae),failingUpdates:e.record(e.string,e.type({uploadedAt:e.string,error:e.string,update:_privacytypes.PreferenceUpdateItem})),pendingUpdates:e.record(e.string,_privacytypes.PreferenceUpdateItem)});async function br({auth:f,sombraAuth:a,receiptFilepath:y,file:m,partition:c,isSilent:l=!0,dryRun:i=!1,skipWorkflowTriggers:r=!1,skipConflictUpdates:s=!1,skipExistingRecordCheck:o=!1,attributes:n=[],transcendUrl:t,forceTriggerWorkflows:p=!1}){let g=_chunkGLXV5XPPcjs.qc.call(void 0, n),u=new (0, _persistedstate.PersistedState)(y,Te,{fileMetadata:{},failingUpdates:{},pendingUpdates:{}}),w=u.getValue("failingUpdates"),M=u.getValue("pendingUpdates"),P=u.getValue("fileMetadata");_chunkZUNVPK23cjs.a.info(_colors2.default.magenta(`Restored cache, there are:
5
- ${Object.values(w).length} failing requests to be retried
6
- ${Object.values(M).length} pending requests to be processed
7
- The following files are stored in cache and will be used:
8
- ${Object.keys(P).map(h=>h).join(`
9
- `)}
10
- The following file will be processed: ${m}
11
- `));let R=_chunkGLXV5XPPcjs.wc.call(void 0, t,f),[I,C,Z]=await Promise.all([_chunkGLXV5XPPcjs.xc.call(void 0, t,f,a),p?Promise.resolve([]):_chunkGLXV5XPPcjs.fd.call(void 0, R),p?Promise.resolve([]):_chunkGLXV5XPPcjs.bd.call(void 0, R)]);await $e({file:m,purposeSlugs:C.map(h=>h.trackingType),preferenceTopics:Z,sombra:I,partitionKey:c,skipExistingRecordCheck:o,forceTriggerWorkflows:p},u);let O={};P=u.getValue("fileMetadata");let k=P[m];if(_chunkZUNVPK23cjs.a.info(_colors2.default.magenta(`Found ${Object.entries(k.pendingSafeUpdates).length} safe updates in ${m}`)),_chunkZUNVPK23cjs.a.info(_colors2.default.magenta(`Found ${Object.entries(k.pendingConflictUpdates).length} conflict updates in ${m}`)),_chunkZUNVPK23cjs.a.info(_colors2.default.magenta(`Found ${Object.entries(k.skippedUpdates).length} skipped updates in ${m}`)),Object.entries({...k.pendingSafeUpdates,...s?{}:_typeutils.apply.call(void 0, k.pendingConflictUpdates,({row:h})=>h)}).forEach(([h,$])=>{let j=k.timestampColum===B?new Date:new Date($[k.timestampColum]),x=q({row:$,columnToPurposeName:k.columnToPurposeName,preferenceTopics:Z,purposeSlugs:C.map(S=>S.trackingType)});O[h]={userId:h,partition:c,timestamp:j.toISOString(),purposes:Object.entries(x).map(([S,Ue])=>({...Ue,purpose:S,workflowSettings:{attributes:g,isSilent:l,skipWorkflowTrigger:r}}))}}),await u.setValue(O,"pendingUpdates"),await u.setValue({},"failingUpdates"),i){_chunkZUNVPK23cjs.a.info(_colors2.default.green(`Dry run complete, exiting. ${Object.values(O).length} pending updates. Check file: ${y}`));return}_chunkZUNVPK23cjs.a.info(_colors2.default.magenta(`Uploading ${Object.values(O).length} preferences to partition: ${c}`));let Re=new Date().getTime(),G=new _cliprogress2.default.SingleBar({},_cliprogress2.default.Presets.shades_classic),ee=0,W=Object.entries(O),ke=_chunkHJTYLFGJcjs.b.call(void 0, W,r?100:10);G.start(W.length,0),await _bluebird.map.call(void 0, ke,async h=>{try{await I.put("v1/preferences",{json:{records:h.map(([,$])=>$),skipWorkflowTriggers:r,forceTriggerWorkflows:p}}).json()}catch($){try{let x=JSON.parse(_optionalChain([$, 'optionalAccess', _5 => _5.response, 'optionalAccess', _6 => _6.body])||"{}");x.error&&_chunkZUNVPK23cjs.a.error(_colors2.default.red(`Error: ${x.error}`))}catch (e2){}_chunkZUNVPK23cjs.a.error(_colors2.default.red(`Failed to upload ${h.length} user preferences to partition ${c}: ${_optionalChain([$, 'optionalAccess', _7 => _7.response, 'optionalAccess', _8 => _8.body])||_optionalChain([$, 'optionalAccess', _9 => _9.message])}`));let j=u.getValue("failingUpdates");h.forEach(([x,S])=>{j[x]={uploadedAt:new Date().toISOString(),update:S,error:_optionalChain([$, 'optionalAccess', _10 => _10.response, 'optionalAccess', _11 => _11.body])||_optionalChain([$, 'optionalAccess', _12 => _12.message])||"Unknown error"}}),await u.setValue(j,"failingUpdates")}ee+=h.length,G.update(ee)},{concurrency:40}),G.stop();let xe=new Date().getTime()-Re;_chunkZUNVPK23cjs.a.info(_colors2.default.green(`Successfully uploaded ${W.length} user preferences to partition ${c} in "${xe/1e3}" seconds!`))}function Tr({identifiers:f=[],purposes:a=[],metadata:y=[],consentManagement:m={},system:c={decryptionStatus:"DECRYPTED"},...l}){let i={...l,...c,...m};if(Array.isArray(f)){let r=new Map;for(let{name:s,value:o}of f)r.has(s)||r.set(s,new Set),o&&r.get(s).add(o);for(let[s,o]of r.entries())i[s]=Array.from(o).join(",")}if(Array.isArray(y)){let r=new Map;for(let{key:s,value:o}of y)r.has(s)||r.set(s,new Set),o&&r.get(s).add(o);for(let[s,o]of r.entries())i[`metadata_${s}`]=Array.from(o).join(",")}if(Array.isArray(a)){for(let{purpose:r,preferences:s,enabled:o}of a)if(i[r]=!!o,Array.isArray(s))for(let{topic:n,choice:t}of s){let p=`${r}_${n}`,g=null;Object.prototype.hasOwnProperty.call(t,"booleanValue")?g=!!t.booleanValue:Object.prototype.hasOwnProperty.call(t,"selectValue")?g=String(_nullishCoalesce(t.selectValue, () => (""))):Array.isArray(t.selectValues)?g=t.selectValues.map(w=>String(w)).filter(w=>w.length>0).join(","):g=null,i[p]=g}}return i}async function Or(f,{partition:a,filterBy:y={},limit:m=50}){let c=[],l,i=y&&(Object.keys(y).length>0||y.system&&Object.keys(y.system).length>0),r=Math.max(1,Math.min(50,_nullishCoalesce(m, () => (50))));for(;;){let s={limit:r};i&&(s.filter=y),l&&(s.cursor=l);let o=await Q(()=>f.post(`v1/preferences/${a}/query`,{json:s}).json(),{onRetry:(p,g,u)=>{_chunkZUNVPK23cjs.a.warn(_colors2.default.yellow(`Retry attempt ${p} for fetchConsentPreferences due to error: ${u}`))}}),{nodes:n,cursor:t}=_typeutils.decodeCodec.call(void 0, D,o);if(!n||n.length===0||(c.push(...n),!t))break;l=t}return c}exports.a = br; exports.b = Tr; exports.c = Or;
12
- //# sourceMappingURL=chunk-WO3KAASS.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/home/runner/work/cli/cli/dist/chunk-WO3KAASS.cjs","../src/lib/preference-management/uploadPreferenceManagementPreferencesInteractive.ts","../src/lib/preference-management/parsePreferenceManagementCsv.ts","../src/lib/preference-management/getPreferencesForIdentifiers.ts","../src/lib/preference-management/withPreferenceQueryRetry.ts","../src/lib/preference-management/parsePreferenceIdentifiersFromCsv.ts","../src/lib/preference-management/parsePreferenceAndPurposeValuesFromCsv.ts","../src/lib/preference-management/codecs.ts"],"names":["RETRY_PREFERENCE_MSGS","withPreferenceQueryRetry","fn","maxAttempts","baseDelayMs","isRetryable","_err","msg","m","onRetry","attempt","err","preferences","value"],"mappings":"AAAA,2lCAAgH,wDAAyC,wDAAuE,gFCQ7M,oCACC,qGAGI,+DAEO,qJCXZ,qDCES,ICGfA,EAAAA,CAAkC,CAC7C,WAAA,CACA,YAAA,CACA,WAAA,CACA,sBAAA,CACA,sBACF,CAAA,CAwBA,MAAA,SAAsBC,CAAAA,CACpBC,CAAAA,CACA,CACE,WAAA,CAAAC,CAAAA,CAAc,CAAA,CACd,WAAA,CAAAC,CAAAA,CAAc,GAAA,CACd,WAAA,CAAAC,CAAAA,CAAc,CAACC,CAAAA,CAAMC,CAAAA,CAAAA,EACnBP,EAAAA,CAAsB,IAAA,CAAMQ,CAAAA,EAAMD,CAAAA,CAAI,QAAA,CAASC,CAAC,CAAC,CAAA,CACnD,OAAA,CAAAC,CACF,CAAA,CAAkB,CAAC,CAAA,CACP,CACZ,IAAIC,CAAAA,CAAU,CAAA,CAEd,GAAA,CAAA,CAAA,CAAA,CAAa,CACXA,CAAAA,EAAW,CAAA,CACX,GAAI,CACF,OAAO,MAAMR,CAAAA,CAAG,CAElB,CAAA,KAAA,CAASS,CAAAA,CAAU,CACjB,IAAMJ,CAAAA,kBAAAA,CACHI,CAAAA,EAAAA,iBAAQA,CAAAA,qBAAI,QAAA,6BAAU,MAAA,EAAQA,CAAAA,CAAI,OAAA,CAAA,CAAA,SACnC,MAAA,kBAAOA,CAAAA,SAAO,iBAAe,GAAA,CAE/B,EAAA,CAAI,CAAA,CADcD,CAAAA,CAAUP,CAAAA,EAAeE,CAAAA,CAAYM,CAAAA,CAAKJ,CAAG,CAAA,CAAA,CAE7D,MAAM,IAAI,KAAA,CACR,CAAA,8BAAA,EAAiCG,CAAO,CAAA,aAAA,EAAgBH,CAAG,CAAA,CAAA;ACwBjEK;ACfU;ACuBV,oGAAA;ANJI;AAGA;AAAA;AAKQ;AAAK;AACgC,sCAAA;AAqF1CC","file":"/home/runner/work/cli/cli/dist/chunk-WO3KAASS.cjs","sourcesContent":[null,"import {\n buildTranscendGraphQLClient,\n createSombraGotInstance,\n fetchAllPurposes,\n fetchAllPreferenceTopics,\n PreferenceTopic,\n Purpose,\n} from '../graphql';\nimport colors from 'colors';\nimport { map } from 'bluebird';\nimport { chunk } from 'lodash-es';\nimport { logger } from '../../logger';\nimport cliProgress from 'cli-progress';\nimport { parseAttributesFromString } from '../requests';\nimport { PersistedState } from '@transcend-io/persisted-state';\nimport { parsePreferenceManagementCsvWithCache } from './parsePreferenceManagementCsv';\nimport { PreferenceState } from './codecs';\nimport { PreferenceUpdateItem } from '@transcend-io/privacy-types';\nimport { apply } from '@transcend-io/type-utils';\nimport { NONE_PREFERENCE_MAP } from './parsePreferenceTimestampsFromCsv';\nimport { getPreferenceUpdatesFromRow } from './getPreferenceUpdatesFromRow';\n\n/**\n * Upload a set of consent preferences\n *\n * @param options - Options\n */\nexport async function uploadPreferenceManagementPreferencesInteractive({\n auth,\n sombraAuth,\n receiptFilepath,\n file,\n partition,\n isSilent = true,\n dryRun = false,\n skipWorkflowTriggers = false,\n skipConflictUpdates = false,\n skipExistingRecordCheck = false,\n attributes = [],\n transcendUrl,\n forceTriggerWorkflows = false,\n}: {\n /** The Transcend API key */\n auth: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** Partition key */\n partition: string;\n /** File where to store receipt and continue from where left off */\n receiptFilepath: string;\n /** The file to process */\n file: string;\n /** API URL for Transcend backend */\n transcendUrl: string;\n /** Whether to do a dry run */\n dryRun?: boolean;\n /** Whether to upload as isSilent */\n isSilent?: boolean;\n /** Attributes string pre-parse. In format Key:Value */\n attributes?: string[];\n /** Skip workflow triggers */\n skipWorkflowTriggers?: boolean;\n /**\n * When true, only update preferences that do not conflict with existing\n * preferences. When false, update all preferences in CSV based on timestamp.\n */\n skipConflictUpdates?: boolean;\n /** Whether to skip the check for existing records. SHOULD ONLY BE USED FOR INITIAL UPLOAD */\n skipExistingRecordCheck?: boolean;\n /** Whether to force trigger workflows */\n forceTriggerWorkflows?: boolean;\n}): Promise<void> {\n // Parse out the extra attributes to apply to all requests uploaded\n const parsedAttributes = parseAttributesFromString(attributes);\n\n // Create a new state file to store the requests from this run\n const preferenceState = new PersistedState(receiptFilepath, PreferenceState, {\n fileMetadata: {},\n failingUpdates: {},\n pendingUpdates: {},\n });\n const failingRequests = preferenceState.getValue('failingUpdates');\n const pendingRequests = preferenceState.getValue('pendingUpdates');\n let fileMetadata = preferenceState.getValue('fileMetadata');\n\n logger.info(\n colors.magenta(\n 'Restored cache, there are: \\n' +\n `${\n Object.values(failingRequests).length\n } failing requests to be retried\\n` +\n `${\n Object.values(pendingRequests).length\n } pending requests to be processed\\n` +\n `The following files are stored in cache and will be used:\\n${Object.keys(\n fileMetadata,\n )\n .map((x) => x)\n .join('\\n')}\\n` +\n `The following file will be processed: ${file}\\n`,\n ),\n );\n\n // Create GraphQL client to connect to Transcend backend\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n const [sombra, purposes, preferenceTopics] = await Promise.all([\n // Create sombra instance to communicate with\n createSombraGotInstance(transcendUrl, auth, sombraAuth),\n // get all purposes and topics\n forceTriggerWorkflows\n ? Promise.resolve([] as Purpose[])\n : fetchAllPurposes(client),\n forceTriggerWorkflows\n ? Promise.resolve([] as PreferenceTopic[])\n : fetchAllPreferenceTopics(client),\n ]);\n\n // Process the file\n await parsePreferenceManagementCsvWithCache(\n {\n file,\n purposeSlugs: purposes.map((x) => x.trackingType),\n preferenceTopics,\n sombra,\n partitionKey: partition,\n skipExistingRecordCheck,\n forceTriggerWorkflows,\n },\n preferenceState,\n );\n\n // Construct the pending updates\n const pendingUpdates: Record<string, PreferenceUpdateItem> = {};\n fileMetadata = preferenceState.getValue('fileMetadata');\n const metadata = fileMetadata[file];\n\n logger.info(\n colors.magenta(\n `Found ${\n Object.entries(metadata.pendingSafeUpdates).length\n } safe updates in ${file}`,\n ),\n );\n logger.info(\n colors.magenta(\n `Found ${\n Object.entries(metadata.pendingConflictUpdates).length\n } conflict updates in ${file}`,\n ),\n );\n logger.info(\n colors.magenta(\n `Found ${\n Object.entries(metadata.skippedUpdates).length\n } skipped updates in ${file}`,\n ),\n );\n\n // Update either safe updates only or safe + conflict\n Object.entries({\n ...metadata.pendingSafeUpdates,\n ...(skipConflictUpdates\n ? {}\n : apply(metadata.pendingConflictUpdates, ({ row }) => row)),\n }).forEach(([userId, update]) => {\n // Determine timestamp\n const timestamp =\n metadata.timestampColum === NONE_PREFERENCE_MAP\n ? new Date()\n : new Date(update[metadata.timestampColum!]);\n\n // Determine updates\n const updates = getPreferenceUpdatesFromRow({\n row: update,\n columnToPurposeName: metadata.columnToPurposeName,\n preferenceTopics,\n purposeSlugs: purposes.map((x) => x.trackingType),\n });\n pendingUpdates[userId] = {\n userId,\n partition,\n timestamp: timestamp.toISOString(),\n purposes: Object.entries(updates).map(([purpose, value]) => ({\n ...value,\n purpose,\n workflowSettings: {\n attributes: parsedAttributes,\n isSilent,\n skipWorkflowTrigger: skipWorkflowTriggers,\n },\n })),\n };\n });\n await preferenceState.setValue(pendingUpdates, 'pendingUpdates');\n await preferenceState.setValue({}, 'failingUpdates');\n\n // Exist early if dry run\n if (dryRun) {\n logger.info(\n colors.green(\n `Dry run complete, exiting. ${\n Object.values(pendingUpdates).length\n } pending updates. Check file: ${receiptFilepath}`,\n ),\n );\n return;\n }\n\n logger.info(\n colors.magenta(\n `Uploading ${\n Object.values(pendingUpdates).length\n } preferences to partition: ${partition}`,\n ),\n );\n\n // Time duration\n const t0 = new Date().getTime();\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 // Build a GraphQL client\n let total = 0;\n const updatesToRun = Object.entries(pendingUpdates);\n const chunkedUpdates = chunk(updatesToRun, skipWorkflowTriggers ? 100 : 10);\n progressBar.start(updatesToRun.length, 0);\n await map(\n chunkedUpdates,\n async (currentChunk) => {\n // Make the request\n try {\n await sombra\n .put('v1/preferences', {\n json: {\n records: currentChunk.map(([, update]) => update),\n skipWorkflowTriggers,\n forceTriggerWorkflows,\n },\n })\n .json();\n } catch (err) {\n try {\n const parsed = JSON.parse(err?.response?.body || '{}');\n if (parsed.error) {\n logger.error(colors.red(`Error: ${parsed.error}`));\n }\n } catch (e) {\n // continue\n }\n logger.error(\n colors.red(\n `Failed to upload ${\n currentChunk.length\n } user preferences to partition ${partition}: ${\n err?.response?.body || err?.message\n }`,\n ),\n );\n const failingUpdates = preferenceState.getValue('failingUpdates');\n currentChunk.forEach(([userId, update]) => {\n failingUpdates[userId] = {\n uploadedAt: new Date().toISOString(),\n update,\n error: err?.response?.body || err?.message || 'Unknown error',\n };\n });\n await preferenceState.setValue(failingUpdates, 'failingUpdates');\n }\n\n total += currentChunk.length;\n progressBar.update(total);\n },\n {\n concurrency: 40,\n },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n logger.info(\n colors.green(\n `Successfully uploaded ${\n updatesToRun.length\n } user preferences to partition ${partition} in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n}\n","import { PersistedState } from '@transcend-io/persisted-state';\nimport type { Got } from 'got';\nimport { keyBy } from 'lodash-es';\nimport * as t from 'io-ts';\nimport colors from 'colors';\nimport { FileMetadataState, PreferenceState } from './codecs';\nimport { logger } from '../../logger';\nimport { readCsv } from '../requests';\nimport { getPreferencesForIdentifiers } from './getPreferencesForIdentifiers';\nimport { PreferenceTopic } from '../graphql';\nimport { getPreferenceUpdatesFromRow } from './getPreferenceUpdatesFromRow';\nimport { parsePreferenceTimestampsFromCsv } from './parsePreferenceTimestampsFromCsv';\nimport { parsePreferenceIdentifiersFromCsv } from './parsePreferenceIdentifiersFromCsv';\nimport { parsePreferenceAndPurposeValuesFromCsv } from './parsePreferenceAndPurposeValuesFromCsv';\nimport { checkIfPendingPreferenceUpdatesAreNoOp } from './checkIfPendingPreferenceUpdatesAreNoOp';\nimport { checkIfPendingPreferenceUpdatesCauseConflict } from './checkIfPendingPreferenceUpdatesCauseConflict';\n\n/**\n * Parse a file into the cache\n *\n *\n * @param options - Options\n * @param cache - The cache to store the parsed file in\n * @returns The cache with the parsed file\n */\nexport async function parsePreferenceManagementCsvWithCache(\n {\n file,\n sombra,\n purposeSlugs,\n preferenceTopics,\n partitionKey,\n skipExistingRecordCheck,\n forceTriggerWorkflows,\n }: {\n /** File to parse */\n file: string;\n /** The purpose slugs that are allowed to be updated */\n purposeSlugs: string[];\n /** The preference topics */\n preferenceTopics: PreferenceTopic[];\n /** Sombra got instance */\n sombra: Got;\n /** Partition key */\n partitionKey: string;\n /** Whether to skip the check for existing records. SHOULD ONLY BE USED FOR INITIAL UPLOAD */\n skipExistingRecordCheck: boolean;\n /** Wheather to force workflow triggers */\n forceTriggerWorkflows: boolean;\n },\n cache: PersistedState<typeof PreferenceState>,\n): Promise<void> {\n // Start the timer\n const t0 = new Date().getTime();\n\n // Get the current metadata\n const fileMetadata = cache.getValue('fileMetadata');\n\n // Read in the file\n logger.info(colors.magenta(`Reading in file: \"${file}\"`));\n let preferences = readCsv(file, t.record(t.string, t.string));\n\n // start building the cache, can use previous cache as well\n let currentState: FileMetadataState = {\n columnToPurposeName: {},\n pendingSafeUpdates: {},\n pendingConflictUpdates: {},\n skippedUpdates: {},\n // Load in the last fetched time\n ...((fileMetadata[file] || {}) as Partial<FileMetadataState>),\n lastFetchedAt: new Date().toISOString(),\n };\n\n // Validate that all timestamps are present in the file\n currentState = await parsePreferenceTimestampsFromCsv(\n preferences,\n currentState,\n );\n fileMetadata[file] = currentState;\n await cache.setValue(fileMetadata, 'fileMetadata');\n\n // Validate that all identifiers are present and unique\n const result = await parsePreferenceIdentifiersFromCsv(\n preferences,\n currentState,\n );\n currentState = result.currentState;\n preferences = result.preferences;\n fileMetadata[file] = currentState;\n await cache.setValue(fileMetadata, 'fileMetadata');\n\n // Ensure all other columns are mapped to purpose and preference\n // slug values\n currentState = await parsePreferenceAndPurposeValuesFromCsv(\n preferences,\n currentState,\n {\n preferenceTopics,\n purposeSlugs,\n forceTriggerWorkflows,\n },\n );\n fileMetadata[file] = currentState;\n await cache.setValue(fileMetadata, 'fileMetadata');\n\n // Grab existing preference store records\n const identifiers = preferences.map(\n (pref) => pref[currentState.identifierColumn!],\n );\n const existingConsentRecords = skipExistingRecordCheck\n ? []\n : await getPreferencesForIdentifiers(sombra, {\n identifiers: identifiers.map((x) => ({ value: x })),\n partitionKey,\n });\n const consentRecordByIdentifier = keyBy(existingConsentRecords, 'userId');\n\n // Clear out previous updates\n currentState.pendingConflictUpdates = {};\n currentState.pendingSafeUpdates = {};\n currentState.skippedUpdates = {};\n\n // Process each row\n preferences.forEach((pref) => {\n // Grab unique Id for the user\n const userId = pref[currentState.identifierColumn!];\n\n // determine updates for user\n const pendingUpdates = getPreferenceUpdatesFromRow({\n row: pref,\n columnToPurposeName: currentState.columnToPurposeName,\n preferenceTopics,\n purposeSlugs,\n });\n\n // Grab current state of the update\n const currentConsentRecord = consentRecordByIdentifier[userId];\n if (forceTriggerWorkflows && !currentConsentRecord) {\n throw new Error(\n `No existing consent record found for user with id: ${userId}. \n When 'forceTriggerWorkflows' is set all the user identifiers should contain a consent record`,\n );\n }\n // Check if the update can be skipped\n // this is the case if a record exists, and the purpose\n // and preference values are all in sync\n if (\n currentConsentRecord &&\n checkIfPendingPreferenceUpdatesAreNoOp({\n currentConsentRecord,\n pendingUpdates,\n preferenceTopics,\n }) &&\n !forceTriggerWorkflows\n ) {\n currentState.skippedUpdates[userId] = pref;\n return;\n }\n\n // Determine if there are any conflicts\n if (\n currentConsentRecord &&\n checkIfPendingPreferenceUpdatesCauseConflict({\n currentConsentRecord,\n pendingUpdates,\n preferenceTopics,\n })\n ) {\n currentState.pendingConflictUpdates[userId] = {\n row: pref,\n record: currentConsentRecord,\n };\n return;\n }\n\n // Add to pending updates\n currentState.pendingSafeUpdates[userId] = pref;\n });\n\n // Read in the file\n fileMetadata[file] = currentState;\n await cache.setValue(fileMetadata, 'fileMetadata');\n const t1 = new Date().getTime();\n logger.info(\n colors.green(\n `Successfully pre-processed file: \"${file}\" in ${(t1 - t0) / 1000}s`,\n ),\n );\n}\n","import { PreferenceQueryResponseItem } from '@transcend-io/privacy-types';\nimport type { Got } from 'got';\nimport colors from 'colors';\nimport cliProgress from 'cli-progress';\nimport { chunk } from 'lodash-es';\nimport { decodeCodec } from '@transcend-io/type-utils';\nimport { map } from 'bluebird';\nimport { logger } from '../../logger';\nimport { withPreferenceQueryRetry } from './withPreferenceQueryRetry';\nimport { ConsentPreferenceResponse } from './types';\n\n/**\n * Grab the current consent preference values for a list of identifiers\n *\n * @param sombra - Backend to make API call to\n * @param options - Options\n * @returns Plaintext context information\n */\nexport async function getPreferencesForIdentifiers(\n sombra: Got,\n {\n identifiers,\n partitionKey,\n skipLogging = false,\n concurrency = 40,\n }: {\n /** The list of identifiers to look up */\n identifiers: {\n /** The value of the identifier */\n value: string;\n }[];\n /** The partition key to look up */\n partitionKey: string;\n /** Whether to skip logging */\n skipLogging?: boolean;\n /** Concurrency for requests (default 40) */\n concurrency?: number;\n },\n): Promise<PreferenceQueryResponseItem[]> {\n const results: PreferenceQueryResponseItem[] = [];\n const groupedIdentifiers = chunk(identifiers, 100);\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 if (!skipLogging) {\n progressBar.start(identifiers.length, 0);\n }\n\n let total = 0;\n await map(\n groupedIdentifiers,\n async (group) => {\n const rawResult = await withPreferenceQueryRetry(\n () =>\n sombra\n .post(`v1/preferences/${partitionKey}/query`, {\n json: {\n filter: { identifiers: group },\n limit: group.length,\n },\n })\n .json(),\n {\n onRetry: (attempt, _err, msg) => {\n logger.warn(\n colors.yellow(\n `[RETRY] group size=${group.length} partition=${partitionKey} attempt=${attempt}: ${msg}`,\n ),\n );\n },\n },\n );\n\n const result = decodeCodec(ConsentPreferenceResponse, rawResult);\n results.push(...result.nodes);\n total += group.length;\n progressBar.update(total);\n },\n {\n concurrency,\n },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n if (!skipLogging) {\n // Log completion time\n logger.info(\n colors.green(`Completed download in \"${totalTime / 1000}\" seconds.`),\n );\n }\n\n return results;\n}\n","import colors from 'colors';\nimport { logger } from '../../logger';\nimport { sleepPromise } from '../helpers';\n\n/**\n * Transient network / platform errors that merit a retry.\n * Keep this list short and specific to avoid masking real failures.\n */\nexport const RETRY_PREFERENCE_MSGS: string[] = [\n 'ENOTFOUND',\n 'ECONNRESET',\n 'ETIMEDOUT',\n '504 Gateway Time-out',\n 'Task timed out after',\n];\n\n/**\n * Options for retrying preference queries.\n */\nexport type RetryOptions = {\n /** Max attempts including the first try (default 3) */\n maxAttempts?: number;\n /** Initial backoff in ms (default 250) */\n baseDelayMs?: number;\n /** Optional custom predicate to decide if an error is retryable */\n isRetryable?: (err: unknown, message: string) => boolean;\n /** Optional hook to log on each retry */\n onRetry?: (attempt: number, err: unknown, message: string) => void;\n};\n\n/**\n * Run an async function with standardized retry behavior for preference queries.\n * Exponential backoff with jitter; only retries on known-transient messages.\n *\n * @param fn - Function to run\n * @param options - Retry options\n * @returns Result of the function\n */\nexport async function withPreferenceQueryRetry<T>(\n fn: () => Promise<T>,\n {\n maxAttempts = 3,\n baseDelayMs = 250,\n isRetryable = (_err, msg) =>\n RETRY_PREFERENCE_MSGS.some((m) => msg.includes(m)),\n onRetry,\n }: RetryOptions = {},\n): Promise<T> {\n let attempt = 0;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n attempt += 1;\n try {\n return await fn();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (err: any) {\n const msg: string =\n (err && (err.response?.body || err.message)) ??\n String(err ?? 'Unknown error');\n const willRetry = attempt < maxAttempts && isRetryable(err, msg);\n if (!willRetry) {\n throw new Error(\n `Preference query failed after ${attempt} attempt(s): ${msg}`,\n );\n }\n onRetry?.(attempt, err, msg);\n\n const backoff = baseDelayMs * 2 ** (attempt - 1);\n const jitter = Math.floor(Math.random() * baseDelayMs);\n const delay = backoff + jitter;\n logger.warn(\n colors.yellow(\n `[retry] attempt ${attempt}/${\n maxAttempts - 1\n }; backing off ${delay}ms: ${msg}`,\n ),\n );\n await sleepPromise(delay);\n }\n }\n}\n","import { uniq, groupBy, difference } from 'lodash-es';\nimport colors from 'colors';\nimport inquirer from 'inquirer';\nimport { FileMetadataState } from './codecs';\nimport { logger } from '../../logger';\nimport { inquirerConfirmBoolean } from '../helpers';\n\n/* eslint-disable no-param-reassign */\n\n/**\n * Parse identifiers from a CSV list of preferences\n *\n * Ensures that all rows have a valid identifier\n * and that all identifiers are unique.\n *\n * @param preferences - List of preferences\n * @param currentState - The current file metadata state for parsing this list\n * @returns The updated file metadata state\n */\nexport async function parsePreferenceIdentifiersFromCsv(\n preferences: Record<string, string>[],\n currentState: FileMetadataState,\n): Promise<{\n /** The updated state */\n currentState: FileMetadataState;\n /** The updated preferences */\n preferences: Record<string, string>[];\n}> {\n // Determine columns to map\n const columnNames = uniq(preferences.map((x) => Object.keys(x)).flat());\n\n // Determine the columns that could potentially be used for identifier\n const remainingColumnsForIdentifier = difference(columnNames, [\n ...(currentState.identifierColumn ? [currentState.identifierColumn] : []),\n ...Object.keys(currentState.columnToPurposeName),\n ]);\n\n // Determine the identifier column to work off of\n if (!currentState.identifierColumn) {\n const { identifierName } = await inquirer.prompt<{\n /** Identifier name */\n identifierName: string;\n }>([\n {\n name: 'identifierName',\n message:\n 'Choose the column that will be used as the identifier to upload consent preferences by',\n type: 'list',\n default:\n remainingColumnsForIdentifier.find((col) =>\n col.toLowerCase().includes('email'),\n ) || remainingColumnsForIdentifier[0],\n choices: remainingColumnsForIdentifier,\n },\n ]);\n currentState.identifierColumn = identifierName;\n }\n logger.info(\n colors.magenta(\n `Using identifier column \"${currentState.identifierColumn}\"`,\n ),\n );\n\n // Validate that the identifier column is present for all rows and unique\n const identifierColumnsMissing = preferences\n .map((pref, ind) => (pref[currentState.identifierColumn!] ? null : [ind]))\n .filter((x): x is number[] => !!x)\n .flat();\n if (identifierColumnsMissing.length > 0) {\n const msg = `The identifier column \"${\n currentState.identifierColumn\n }\" is missing a value for the following rows: ${identifierColumnsMissing.join(\n ', ',\n )}`;\n logger.warn(colors.yellow(msg));\n\n // Ask user if they would like to skip rows missing an identifier\n const skip = await inquirerConfirmBoolean({\n message: 'Would you like to skip rows missing an identifier?',\n });\n if (!skip) {\n throw new Error(msg);\n }\n\n // Filter out rows missing an identifier\n const previous = preferences.length;\n preferences = preferences.filter(\n (pref) => pref[currentState.identifierColumn!],\n );\n logger.info(\n colors.yellow(\n `Skipped ${previous - preferences.length} rows missing an identifier`,\n ),\n );\n }\n logger.info(\n colors.magenta(\n `The identifier column \"${currentState.identifierColumn}\" is present for all rows`,\n ),\n );\n\n // Validate that all identifiers are unique\n const rowsByUserId = groupBy(preferences, currentState.identifierColumn);\n const duplicateIdentifiers = Object.entries(rowsByUserId).filter(\n ([, rows]) => rows.length > 1,\n );\n if (duplicateIdentifiers.length > 0) {\n const msg = `The identifier column \"${\n currentState.identifierColumn\n }\" has duplicate values for the following rows: ${duplicateIdentifiers\n .slice(0, 10)\n .map(([userId, rows]) => `${userId} (${rows.length})`)\n .join('\\n')}`;\n logger.warn(colors.yellow(msg));\n\n // Ask user if they would like to take the most recent update\n // for each duplicate identifier\n const skip = await inquirerConfirmBoolean({\n message: 'Would you like to automatically take the latest update?',\n });\n if (!skip) {\n throw new Error(msg);\n }\n preferences = Object.entries(rowsByUserId)\n .map(([, rows]) => {\n const sorted = rows.sort(\n (a, b) =>\n new Date(b[currentState.timestampColum!]).getTime() -\n new Date(a[currentState.timestampColum!]).getTime(),\n );\n return sorted[0];\n })\n .filter((x) => x);\n }\n\n return { currentState, preferences };\n}\n/* eslint-enable no-param-reassign */\n","import { uniq, difference } from 'lodash-es';\nimport colors from 'colors';\nimport inquirer from 'inquirer';\nimport { FileMetadataState } from './codecs';\nimport { logger } from '../../logger';\nimport { mapSeries } from 'bluebird';\nimport { PreferenceTopic } from '../graphql';\nimport { PreferenceTopicType } from '@transcend-io/privacy-types';\nimport { splitCsvToList } from '../requests';\n\n/* eslint-disable no-param-reassign */\n\n/**\n * Parse out the purpose.enabled and preference values from a CSV file\n *\n * @param preferences - List of preferences\n * @param currentState - The current file metadata state for parsing this list\n * @param options - Options\n * @returns The updated file metadata state\n */\nexport async function parsePreferenceAndPurposeValuesFromCsv(\n preferences: Record<string, string>[],\n currentState: FileMetadataState,\n {\n purposeSlugs,\n preferenceTopics,\n forceTriggerWorkflows,\n }: {\n /** The purpose slugs that are allowed to be updated */\n purposeSlugs: string[];\n /** The preference topics */\n preferenceTopics: PreferenceTopic[];\n /** Force workflow triggers */\n forceTriggerWorkflows: boolean;\n },\n): Promise<FileMetadataState> {\n // Determine columns to map\n const columnNames = uniq(preferences.map((x) => Object.keys(x)).flat());\n\n // Determine the columns that could potentially be used for identifier\n const otherColumns = difference(columnNames, [\n ...(currentState.identifierColumn ? [currentState.identifierColumn] : []),\n ...(currentState.timestampColum ? [currentState.timestampColum] : []),\n ]);\n if (otherColumns.length === 0) {\n if (forceTriggerWorkflows) {\n return currentState;\n }\n throw new Error('No other columns to process');\n }\n\n // The purpose and preferences to map to\n const purposeNames = [\n ...purposeSlugs,\n ...preferenceTopics.map((x) => `${x.purpose.trackingType}->${x.slug}`),\n ];\n\n // Ensure all columns are accounted for\n await mapSeries(otherColumns, async (col) => {\n // Determine the unique values to map in this column\n const uniqueValues = uniq(preferences.map((x) => x[col]));\n\n // Map the column to a purpose\n let purposeMapping = currentState.columnToPurposeName[col];\n if (purposeMapping) {\n logger.info(\n colors.magenta(\n `Column \"${col}\" is associated with purpose \"${purposeMapping.purpose}\"`,\n ),\n );\n } else {\n const { purposeName } = await inquirer.prompt<{\n /** purpose name */\n purposeName: string;\n }>([\n {\n name: 'purposeName',\n message: `Choose the purpose that column ${col} is associated with`,\n type: 'list',\n default: purposeNames.find((x) => x.startsWith(purposeSlugs[0])),\n choices: purposeNames,\n },\n ]);\n const [purposeSlug, preferenceSlug] = purposeName.split('->');\n purposeMapping = {\n purpose: purposeSlug,\n preference: preferenceSlug || null,\n valueMapping: {},\n };\n }\n\n // map each value to the purpose value\n await mapSeries(uniqueValues, async (value) => {\n if (purposeMapping.valueMapping[value] !== undefined) {\n logger.info(\n colors.magenta(\n `Value \"${value}\" is associated with purpose value \"${purposeMapping.valueMapping[value]}\"`,\n ),\n );\n return;\n }\n // if preference is null, this column is just for the purpose\n if (purposeMapping.preference === null) {\n const { purposeValue } = await inquirer.prompt<{\n /** purpose value */\n purposeValue: boolean;\n }>([\n {\n name: 'purposeValue',\n message: `Choose the purpose value for value \"${value}\" associated with purpose \"${purposeMapping.purpose}\"`,\n type: 'confirm',\n default: value !== 'false',\n },\n ]);\n purposeMapping.valueMapping[value] = purposeValue;\n }\n\n // if preference is not null, this column is for a specific preference\n if (purposeMapping.preference !== null) {\n const preferenceTopic = preferenceTopics.find(\n (x) => x.slug === purposeMapping.preference,\n );\n if (!preferenceTopic) {\n logger.error(\n colors.red(\n `Preference topic \"${purposeMapping.preference}\" not found`,\n ),\n );\n return;\n }\n const preferenceOptions = preferenceTopic.preferenceOptionValues.map(\n ({ slug }) => slug,\n );\n\n if (preferenceTopic.type === PreferenceTopicType.Boolean) {\n const { preferenceValue } = await inquirer.prompt<{\n /** purpose value */\n preferenceValue: boolean;\n }>([\n {\n name: 'preferenceValue',\n message:\n // eslint-disable-next-line max-len\n `Choose the preference value for \"${preferenceTopic.slug}\" value \"${value}\" associated with purpose \"${purposeMapping.purpose}\"`,\n type: 'confirm',\n default: value !== 'false',\n },\n ]);\n purposeMapping.valueMapping[value] = preferenceValue;\n return;\n }\n\n if (preferenceTopic.type === PreferenceTopicType.Select) {\n const { preferenceValue } = await inquirer.prompt<{\n /** purpose value */\n preferenceValue: boolean;\n }>([\n {\n name: 'preferenceValue',\n // eslint-disable-next-line max-len\n message: `Choose the preference value for \"${preferenceTopic.slug}\" value \"${value}\" associated with purpose \"${purposeMapping.purpose}\"`,\n type: 'list',\n choices: preferenceOptions,\n default: preferenceOptions.find((x) => x === value),\n },\n ]);\n purposeMapping.valueMapping[value] = preferenceValue;\n return;\n }\n\n if (preferenceTopic.type === PreferenceTopicType.MultiSelect) {\n const parsedValues = splitCsvToList(value);\n // need to do this serially\n await mapSeries(parsedValues, async (parsedValue) => {\n // if we already have a value, skip re-processing it again\n if (purposeMapping.valueMapping[parsedValue] !== undefined) {\n return;\n }\n const { preferenceValue } = await inquirer.prompt<{\n /** purpose value */\n preferenceValue: boolean;\n }>([\n {\n name: 'preferenceValue',\n // eslint-disable-next-line max-len\n message: `Choose the preference value for \"${preferenceTopic.slug}\" value \"${parsedValue}\" associated with purpose \"${purposeMapping.purpose}\"`,\n type: 'list',\n choices: preferenceOptions,\n default: preferenceOptions.find((x) => x === parsedValue),\n },\n ]);\n purposeMapping.valueMapping[parsedValue] = preferenceValue;\n });\n return;\n }\n\n throw new Error(\n `Unknown preference topic type: ${preferenceTopic.type}`,\n );\n }\n });\n\n currentState.columnToPurposeName[col] = purposeMapping;\n });\n\n return currentState;\n}\n/* eslint-enable no-param-reassign */\n","import {\n PreferenceQueryResponseItem,\n PreferenceUpdateItem,\n} from '@transcend-io/privacy-types';\nimport * as t from 'io-ts';\n\nexport const PurposeRowMapping = t.type({\n /**\n * The slug or trackingType of the purpose to map to\n *\n * e.g. `Marketing`\n */\n purpose: t.string,\n /**\n * If the column maps to a preference instead of a purpose\n * this is the slug of the purpose.\n *\n * null value indicates that this column maps to the true/false\n * value of the purpose\n */\n preference: t.union([t.string, t.null]),\n /**\n * The mapping between each row value and purpose/preference value.\n *\n * e.g. for a boolean preference or purpose\n * {\n * 'true': true,\n * 'false': false,\n * '': true,\n * }\n *\n * or for a single or multi select preference\n * {\n * '': true,\n * 'value1': 'Value1',\n * 'value2': 'Value2',\n * }\n */\n valueMapping: t.record(\n t.string,\n t.union([t.string, t.boolean, t.null, t.undefined]),\n ),\n});\n\n/** Override type */\nexport type PurposeRowMapping = t.TypeOf<typeof PurposeRowMapping>;\n\n/**\n * Mapping of column name to purpose row mapping.\n * This is used to map each column in the CSV to the relevant purpose and preference definitions in\n * transcend.\n */\nexport const ColumnPurposeMap = t.record(t.string, PurposeRowMapping);\n\n/** Override type */\nexport type ColumnPurposeMap = t.TypeOf<typeof ColumnPurposeMap>;\n\nexport const IdentifierMetadataForPreference = t.type({\n /** The identifier name */\n name: t.string,\n /** Is unique on preference store */\n isUniqueOnPreferenceStore: t.boolean,\n});\n\n/** Override type */\nexport type IdentifierMetadataForPreference = t.TypeOf<\n typeof IdentifierMetadataForPreference\n>;\n\n/**\n * Mapping of identifier name to the column name in the CSV file.\n * This is used to map each identifier name to the column in the CSV file.\n */\nexport const ColumnIdentifierMap = t.record(\n t.string,\n IdentifierMetadataForPreference,\n);\n\n/** Override type */\nexport type ColumnIdentifierMap = t.TypeOf<typeof ColumnIdentifierMap>;\n\nexport const FileMetadataState = t.intersection([\n t.type({\n /**\n * Definition of how to map each column in the CSV to\n * the relevant purpose and preference definitions in transcend\n */\n columnToPurposeName: t.record(t.string, PurposeRowMapping),\n /** Last time the file was last parsed at */\n lastFetchedAt: t.string,\n /**\n * Mapping of userId to the rows in the file that need to be uploaded\n * These uploads are overwriting non-existent preferences and are safe\n */\n pendingSafeUpdates: t.record(t.string, t.record(t.string, t.string)),\n /**\n * Mapping of userId to the rows in the file that need to be uploaded\n * these records have conflicts with existing consent preferences\n */\n pendingConflictUpdates: t.record(\n t.string,\n t.type({\n record: PreferenceQueryResponseItem,\n row: t.record(t.string, t.string),\n }),\n ),\n /**\n * Mapping of userId to the rows in the file that can be skipped because\n * their preferences are already in the store\n */\n skippedUpdates: t.record(t.string, t.record(t.string, t.string)),\n }),\n t.partial({\n /** Determine which column name in file maps to consent record identifier to upload on */\n identifierColumn: t.string,\n /** Determine which column name in file maps to the timestamp */\n timestampColum: t.string,\n }),\n]);\n\n/** Override type */\nexport type FileMetadataState = t.TypeOf<typeof FileMetadataState>;\n\n/**\n * This is the type of the receipts that are stored in the file\n * that is used to track the state of the upload process.\n * It is used to resume the upload process from where it left off.\n * It is used to persist the state of the upload process across multiple runs.\n */\nexport const PreferenceUpdateMap = t.record(\n t.string,\n // This can either be true to indicate the record is pending\n // or it can be an object showing the object\n // We only return a fixed number of results to avoid\n // making the JSON file too large\n t.union([t.boolean, PreferenceUpdateItem]),\n);\n\n/** Override type */\nexport type PreferenceUpdateMap = t.TypeOf<typeof PreferenceUpdateMap>;\n\n/**\n * This is the type of the pending updates that are safe to run without\n * conflicts with existing consent preferences.\n *\n * Key is primaryKey of the record in the file.\n * The value is the row in the file that is safe to upload.\n */\nexport const PendingSafePreferenceUpdates = t.record(\n t.string,\n // This can either be true to indicate the record is safe\n // or it can be an object showing the object\n // We only return a fixed number of results to avoid\n // making the JSON file too large\n t.union([t.boolean, t.record(t.string, t.string)]),\n);\n\n/** Override type */\nexport type PendingSafePreferenceUpdates = t.TypeOf<\n typeof PendingSafePreferenceUpdates\n>;\n\n/**\n * These are the updates that failed to be uploaded to the API.\n */\nexport const FailingPreferenceUpdates = t.record(\n t.string,\n t.type({\n /** Time upload ran at */\n uploadedAt: t.string,\n /** Attempts to upload that resulted in an error */\n error: t.string,\n /** The update body */\n update: PreferenceUpdateItem,\n }),\n);\n\n/** Override type */\nexport type FailingPreferenceUpdates = t.TypeOf<\n typeof FailingPreferenceUpdates\n>;\n\n/**\n * This is the type of the pending updates that are in conflict with existing consent preferences.\n *\n * Key is primaryKey of the record in the file.\n * The value is the row in the file that is pending upload.\n */\nexport const PendingWithConflictPreferenceUpdates = t.record(\n t.string,\n // We always return the conflicts for investigation\n t.type({\n /** Record to be inserted to transcend v1/preferences API */\n record: PreferenceQueryResponseItem,\n /** The row in the file that is pending upload */\n row: t.record(t.string, t.string),\n }),\n);\n\n/** Override type */\nexport type PendingWithConflictPreferenceUpdates = t.TypeOf<\n typeof PendingWithConflictPreferenceUpdates\n>;\n\n/**\n * The set of preference updates that are skipped\n * Key is primaryKey and value is the row in the CSV\n * that is skipped.\n *\n * This is usually because the preferences are already in the store\n * or there are duplicate rows in the CSV file that are identical.\n */\nexport const SkippedPreferenceUpdates = t.record(\n t.string,\n t.record(t.string, t.string),\n);\n\n/** Override type */\nexport type SkippedPreferenceUpdates = t.TypeOf<\n typeof SkippedPreferenceUpdates\n>;\n\n/** Persist this data between runs of the script */\nexport const PreferenceState = t.type({\n /**\n * Store a cache of previous files read in\n */\n fileMetadata: t.record(t.string, FileMetadataState),\n /**\n * The set of successful uploads to Transcend\n * Mapping from userId to the upload metadata\n */\n failingUpdates: t.record(\n t.string,\n t.type({\n /** Time upload ran at */\n uploadedAt: t.string,\n /** Attempts to upload that resulted in an error */\n error: t.string,\n /** The update body */\n update: PreferenceUpdateItem,\n }),\n ),\n /**\n * The set of pending uploads to Transcend\n * Mapping from userId to the upload metadata\n */\n pendingUpdates: t.record(t.string, PreferenceUpdateItem),\n});\n\n/** Override type */\nexport type PreferenceState = t.TypeOf<typeof PreferenceState>;\n"]}
@@ -1,2 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunk7YR2TG7Ucjs = require('./chunk-7YR2TG7U.cjs');var _chunkWKCTKYN4cjs = require('./chunk-WKCTKYN4.cjs');require('./chunk-GLXV5XPP.cjs');require('./chunk-LCDYXJN6.cjs');require('./chunk-ZUNVPK23.cjs');require('./chunk-HJTYLFGJ.cjs');require('./chunk-Q7I37FJV.cjs');async function u({auth:r,transcendUrl:i,file:e,enricherId:o,concurrency:s,markSilent:a,sombraAuth:m}){_chunkWKCTKYN4cjs.a.call(void 0, this.process.exit),await _chunk7YR2TG7Ucjs.d.call(void 0, {file:e,transcendUrl:i,enricherId:o,concurrency:s,markSilent:a,auth:r,sombraAuth:m})}exports.pushIdentifiers = u;
2
- //# sourceMappingURL=impl-C3XI35SQ.cjs.map