@transcend-io/cli 7.0.0-alpha.12 → 7.0.0-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/bash-complete.js +4 -0
- package/dist/bin/bash-complete.js.map +1 -0
- package/dist/bin/cli.js +3 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/bin/deprecated-command.js +7 -0
- package/dist/bin/deprecated-command.js.map +1 -0
- package/dist/chunk-24SSWBXM.js +4 -0
- package/dist/chunk-24SSWBXM.js.map +1 -0
- package/dist/chunk-347UQP43.js +2 -0
- package/dist/chunk-347UQP43.js.map +1 -0
- package/dist/chunk-43JWXG77.js +2 -0
- package/dist/chunk-43JWXG77.js.map +1 -0
- package/dist/chunk-4GLITB3Y.js +2 -0
- package/dist/chunk-4GLITB3Y.js.map +1 -0
- package/dist/chunk-6P4FW6XR.js +3 -0
- package/dist/chunk-6P4FW6XR.js.map +1 -0
- package/dist/chunk-72U6ETHG.js +2 -0
- package/dist/chunk-72U6ETHG.js.map +1 -0
- package/dist/chunk-7QHA6ZIV.js +2 -0
- package/dist/chunk-7QHA6ZIV.js.map +1 -0
- package/dist/chunk-ARVEJERC.js +2 -0
- package/dist/chunk-ARVEJERC.js.map +1 -0
- package/dist/chunk-CBAHSBSW.js +2 -0
- package/dist/chunk-CBAHSBSW.js.map +1 -0
- package/dist/chunk-HH2PQ3PQ.js +2 -0
- package/dist/chunk-HH2PQ3PQ.js.map +1 -0
- package/dist/chunk-INLBXSQE.js +9 -0
- package/dist/chunk-INLBXSQE.js.map +1 -0
- package/dist/chunk-KRN6Q433.js +75 -0
- package/dist/chunk-KRN6Q433.js.map +1 -0
- package/dist/chunk-L5ULN3IT.js +2 -0
- package/dist/chunk-L5ULN3IT.js.map +1 -0
- package/dist/chunk-L7ZIX4SU.js +2 -0
- package/dist/chunk-L7ZIX4SU.js.map +1 -0
- package/dist/chunk-LAYHULHH.js +2 -0
- package/dist/chunk-LAYHULHH.js.map +1 -0
- package/dist/chunk-MA4JWWRO.js +6 -0
- package/dist/chunk-MA4JWWRO.js.map +1 -0
- package/dist/chunk-MVDOKJ6J.js +2 -0
- package/dist/chunk-MVDOKJ6J.js.map +1 -0
- package/dist/chunk-OEB7WG3G.js +4 -0
- package/dist/chunk-OEB7WG3G.js.map +1 -0
- package/dist/chunk-SF46ZLPT.js +2 -0
- package/dist/chunk-SF46ZLPT.js.map +1 -0
- package/dist/chunk-TDBKATQK.js +2831 -0
- package/dist/chunk-TDBKATQK.js.map +1 -0
- package/dist/chunk-WSDWILYI.js +2 -0
- package/dist/chunk-WSDWILYI.js.map +1 -0
- package/dist/chunk-XNR74SBS.js +12 -0
- package/dist/chunk-XNR74SBS.js.map +1 -0
- package/dist/chunk-ZLRUIEVQ.js +94 -0
- package/dist/chunk-ZLRUIEVQ.js.map +1 -0
- package/dist/chunk-ZTD7APNF.js +2 -0
- package/dist/chunk-ZTD7APNF.js.map +1 -0
- package/dist/impl-25VWUB6L.js +2 -0
- package/dist/impl-25VWUB6L.js.map +1 -0
- package/dist/impl-3M5R6G5M.js +6 -0
- package/dist/impl-3M5R6G5M.js.map +1 -0
- package/dist/impl-5OEPVWPL.js +2 -0
- package/dist/impl-5OEPVWPL.js.map +1 -0
- package/dist/impl-5YV7K446.js +2 -0
- package/dist/impl-5YV7K446.js.map +1 -0
- package/dist/impl-AFRHPZGF.js +2 -0
- package/dist/impl-AFRHPZGF.js.map +1 -0
- package/dist/impl-CCUCFOCW.js +6 -0
- package/dist/impl-CCUCFOCW.js.map +1 -0
- package/dist/impl-E36SWF4Z.js +2 -0
- package/dist/impl-E36SWF4Z.js.map +1 -0
- package/dist/impl-E5WXNV47.js +2 -0
- package/dist/impl-E5WXNV47.js.map +1 -0
- package/dist/impl-EVICJMI3.js +2 -0
- package/dist/impl-EVICJMI3.js.map +1 -0
- package/dist/impl-G5TGSB4H.js +2 -0
- package/dist/impl-G5TGSB4H.js.map +1 -0
- package/dist/impl-GNG2DOKG.js +2 -0
- package/dist/impl-GNG2DOKG.js.map +1 -0
- package/dist/impl-GNSHZ3OL.js +2 -0
- package/dist/impl-GNSHZ3OL.js.map +1 -0
- package/dist/impl-GPCURY4M.js +7 -0
- package/dist/impl-GPCURY4M.js.map +1 -0
- package/dist/impl-GZRQOFY6.js +2 -0
- package/dist/impl-GZRQOFY6.js.map +1 -0
- package/dist/impl-HEC3SVYP.js +2 -0
- package/dist/impl-HEC3SVYP.js.map +1 -0
- package/dist/impl-HH24GIMG.js +2 -0
- package/dist/impl-HH24GIMG.js.map +1 -0
- package/dist/impl-I24OLEN5.js +2 -0
- package/dist/impl-I24OLEN5.js.map +1 -0
- package/dist/impl-IAXNYDJT.js +2 -0
- package/dist/impl-IAXNYDJT.js.map +1 -0
- package/dist/impl-J33PI3PK.js +2 -0
- package/dist/impl-J33PI3PK.js.map +1 -0
- package/dist/impl-JZDUGI7W.js +2 -0
- package/dist/impl-JZDUGI7W.js.map +1 -0
- package/dist/impl-LZ3HI26W.js +4 -0
- package/dist/impl-LZ3HI26W.js.map +1 -0
- package/dist/impl-MEDPDKAE.js +2 -0
- package/dist/impl-MEDPDKAE.js.map +1 -0
- package/dist/impl-MLS6TI7N.js +2 -0
- package/dist/impl-MLS6TI7N.js.map +1 -0
- package/dist/impl-NI7KSBSS.js +2 -0
- package/dist/impl-NI7KSBSS.js.map +1 -0
- package/dist/impl-OM6EKANE.js +9 -0
- package/dist/impl-OM6EKANE.js.map +1 -0
- package/dist/impl-T4WDJSWZ.js +2 -0
- package/dist/impl-T4WDJSWZ.js.map +1 -0
- package/dist/impl-U37YTCPW.js +2 -0
- package/dist/impl-U37YTCPW.js.map +1 -0
- package/dist/impl-U5555HGJ.js +12 -0
- package/dist/impl-U5555HGJ.js.map +1 -0
- package/dist/impl-UHFSVVIS.js +6 -0
- package/dist/impl-UHFSVVIS.js.map +1 -0
- package/dist/impl-UIVTSO57.js +2 -0
- package/dist/impl-UIVTSO57.js.map +1 -0
- package/dist/impl-UQYL5PXR.js +2 -0
- package/dist/impl-UQYL5PXR.js.map +1 -0
- package/dist/impl-V5QTKTU4.js +2 -0
- package/dist/impl-V5QTKTU4.js.map +1 -0
- package/dist/impl-WDPWOOFV.js +2 -0
- package/dist/impl-WDPWOOFV.js.map +1 -0
- package/dist/impl-WZAF2LD3.js +2 -0
- package/dist/impl-WZAF2LD3.js.map +1 -0
- package/dist/impl-XF26H3HG.js +2 -0
- package/dist/impl-XF26H3HG.js.map +1 -0
- package/dist/impl-XQY2Q5R6.js +2 -0
- package/dist/impl-XQY2Q5R6.js.map +1 -0
- package/dist/impl-YB2LON7S.js +2 -0
- package/dist/impl-YB2LON7S.js.map +1 -0
- package/dist/impl-YNGQIWW7.js +2 -0
- package/dist/impl-YNGQIWW7.js.map +1 -0
- package/dist/impl-ZA3PKNQN.js +2 -0
- package/dist/impl-ZA3PKNQN.js.map +1 -0
- package/dist/{index.d.cts → index.d.ts} +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/package.json +45 -46
- package/dist/bin/bash-complete.cjs +0 -4
- package/dist/bin/bash-complete.cjs.map +0 -1
- package/dist/bin/cli.cjs +0 -3
- package/dist/bin/cli.cjs.map +0 -1
- package/dist/bin/deprecated-command.cjs +0 -7
- package/dist/bin/deprecated-command.cjs.map +0 -1
- package/dist/chunk-BRVWR44K.cjs +0 -2
- package/dist/chunk-BRVWR44K.cjs.map +0 -1
- package/dist/chunk-BY7W4UQF.cjs +0 -2
- package/dist/chunk-BY7W4UQF.cjs.map +0 -1
- package/dist/chunk-CX2GRUPB.cjs +0 -2
- package/dist/chunk-CX2GRUPB.cjs.map +0 -1
- package/dist/chunk-DQHCGJTR.cjs +0 -2
- package/dist/chunk-DQHCGJTR.cjs.map +0 -1
- package/dist/chunk-EG4L6YAJ.cjs +0 -2
- package/dist/chunk-EG4L6YAJ.cjs.map +0 -1
- package/dist/chunk-IBTP5OXE.cjs +0 -2
- package/dist/chunk-IBTP5OXE.cjs.map +0 -1
- package/dist/chunk-JC7VDPVP.cjs +0 -2831
- package/dist/chunk-JC7VDPVP.cjs.map +0 -1
- package/dist/chunk-KAE73AXX.cjs +0 -2
- package/dist/chunk-KAE73AXX.cjs.map +0 -1
- package/dist/chunk-KEXUFX2J.cjs +0 -12
- package/dist/chunk-KEXUFX2J.cjs.map +0 -1
- package/dist/chunk-KOV2SQO2.cjs +0 -4
- package/dist/chunk-KOV2SQO2.cjs.map +0 -1
- package/dist/chunk-LOOIAAAW.cjs +0 -9
- package/dist/chunk-LOOIAAAW.cjs.map +0 -1
- package/dist/chunk-OKOJP5XU.cjs +0 -94
- package/dist/chunk-OKOJP5XU.cjs.map +0 -1
- package/dist/chunk-ORNBWSZL.cjs +0 -2
- package/dist/chunk-ORNBWSZL.cjs.map +0 -1
- package/dist/chunk-QJYHSHFA.cjs +0 -2
- package/dist/chunk-QJYHSHFA.cjs.map +0 -1
- package/dist/chunk-SAEKBZGF.cjs +0 -2
- package/dist/chunk-SAEKBZGF.cjs.map +0 -1
- package/dist/chunk-T462ONFX.cjs +0 -2
- package/dist/chunk-T462ONFX.cjs.map +0 -1
- package/dist/chunk-TD7ADMVO.cjs +0 -2
- package/dist/chunk-TD7ADMVO.cjs.map +0 -1
- package/dist/chunk-UEGX6GZ2.cjs +0 -2
- package/dist/chunk-UEGX6GZ2.cjs.map +0 -1
- package/dist/chunk-URT6VVOK.cjs +0 -3
- package/dist/chunk-URT6VVOK.cjs.map +0 -1
- package/dist/chunk-UYYOVK3W.cjs +0 -2
- package/dist/chunk-UYYOVK3W.cjs.map +0 -1
- package/dist/chunk-X4YTPQVY.cjs +0 -4
- package/dist/chunk-X4YTPQVY.cjs.map +0 -1
- package/dist/chunk-ZJDLK7C3.cjs +0 -75
- package/dist/chunk-ZJDLK7C3.cjs.map +0 -1
- package/dist/chunk-ZUNVPK23.cjs +0 -2
- package/dist/chunk-ZUNVPK23.cjs.map +0 -1
- package/dist/chunk-ZVK4HIDF.cjs +0 -6
- package/dist/chunk-ZVK4HIDF.cjs.map +0 -1
- package/dist/impl-2DZ5OV74.cjs +0 -2
- package/dist/impl-2DZ5OV74.cjs.map +0 -1
- package/dist/impl-2ILRPUCC.cjs +0 -9
- package/dist/impl-2ILRPUCC.cjs.map +0 -1
- package/dist/impl-2LBSGBBL.cjs +0 -2
- package/dist/impl-2LBSGBBL.cjs.map +0 -1
- package/dist/impl-3NMEM4QJ.cjs +0 -2
- package/dist/impl-3NMEM4QJ.cjs.map +0 -1
- package/dist/impl-3QGL5KFO.cjs +0 -2
- package/dist/impl-3QGL5KFO.cjs.map +0 -1
- package/dist/impl-56MNYVA5.cjs +0 -2
- package/dist/impl-56MNYVA5.cjs.map +0 -1
- package/dist/impl-6PKXIPAW.cjs +0 -2
- package/dist/impl-6PKXIPAW.cjs.map +0 -1
- package/dist/impl-73JOMLRW.cjs +0 -2
- package/dist/impl-73JOMLRW.cjs.map +0 -1
- package/dist/impl-ADTYWN4O.cjs +0 -2
- package/dist/impl-ADTYWN4O.cjs.map +0 -1
- package/dist/impl-BOLY4EOP.cjs +0 -7
- package/dist/impl-BOLY4EOP.cjs.map +0 -1
- package/dist/impl-DUSKH5V5.cjs +0 -2
- package/dist/impl-DUSKH5V5.cjs.map +0 -1
- package/dist/impl-F6IWO7FD.cjs +0 -2
- package/dist/impl-F6IWO7FD.cjs.map +0 -1
- package/dist/impl-GHDROQMO.cjs +0 -2
- package/dist/impl-GHDROQMO.cjs.map +0 -1
- package/dist/impl-HEJP2URY.cjs +0 -2
- package/dist/impl-HEJP2URY.cjs.map +0 -1
- package/dist/impl-IQ7A5Z4D.cjs +0 -6
- package/dist/impl-IQ7A5Z4D.cjs.map +0 -1
- package/dist/impl-JAJVO3ZW.cjs +0 -2
- package/dist/impl-JAJVO3ZW.cjs.map +0 -1
- package/dist/impl-JF27LEV3.cjs +0 -2
- package/dist/impl-JF27LEV3.cjs.map +0 -1
- package/dist/impl-JODNLRWN.cjs +0 -6
- package/dist/impl-JODNLRWN.cjs.map +0 -1
- package/dist/impl-KJUS5YHL.cjs +0 -6
- package/dist/impl-KJUS5YHL.cjs.map +0 -1
- package/dist/impl-KOKG6ZNB.cjs +0 -2
- package/dist/impl-KOKG6ZNB.cjs.map +0 -1
- package/dist/impl-KWJ7DKLD.cjs +0 -2
- package/dist/impl-KWJ7DKLD.cjs.map +0 -1
- package/dist/impl-LNCNTGHP.cjs +0 -2
- package/dist/impl-LNCNTGHP.cjs.map +0 -1
- package/dist/impl-MHS2Q5XQ.cjs +0 -2
- package/dist/impl-MHS2Q5XQ.cjs.map +0 -1
- package/dist/impl-MUMMGTPH.cjs +0 -2
- package/dist/impl-MUMMGTPH.cjs.map +0 -1
- package/dist/impl-NJ7B53DT.cjs +0 -2
- package/dist/impl-NJ7B53DT.cjs.map +0 -1
- package/dist/impl-OKINLHAG.cjs +0 -2
- package/dist/impl-OKINLHAG.cjs.map +0 -1
- package/dist/impl-PAGIGWUU.cjs +0 -2
- package/dist/impl-PAGIGWUU.cjs.map +0 -1
- package/dist/impl-PKVWUYYX.cjs +0 -2
- package/dist/impl-PKVWUYYX.cjs.map +0 -1
- package/dist/impl-QBPIYO6K.cjs +0 -2
- package/dist/impl-QBPIYO6K.cjs.map +0 -1
- package/dist/impl-QUC5AKPQ.cjs +0 -2
- package/dist/impl-QUC5AKPQ.cjs.map +0 -1
- package/dist/impl-RMVV72AB.cjs +0 -2
- package/dist/impl-RMVV72AB.cjs.map +0 -1
- package/dist/impl-S5EXF3MB.cjs +0 -2
- package/dist/impl-S5EXF3MB.cjs.map +0 -1
- package/dist/impl-SJGNXCXR.cjs +0 -4
- package/dist/impl-SJGNXCXR.cjs.map +0 -1
- package/dist/impl-SYM6RYJP.cjs +0 -2
- package/dist/impl-SYM6RYJP.cjs.map +0 -1
- package/dist/impl-UTZGKHAD.cjs +0 -2
- package/dist/impl-UTZGKHAD.cjs.map +0 -1
- package/dist/impl-VI3JMHFN.cjs +0 -2
- package/dist/impl-VI3JMHFN.cjs.map +0 -1
- package/dist/impl-VIX7AWHA.cjs +0 -2
- package/dist/impl-VIX7AWHA.cjs.map +0 -1
- package/dist/impl-W42Y6L6N.cjs +0 -2
- package/dist/impl-W42Y6L6N.cjs.map +0 -1
- package/dist/impl-XE5EV5SW.cjs +0 -12
- package/dist/impl-XE5EV5SW.cjs.map +0 -1
- package/dist/index.cjs +0 -5
- package/dist/index.cjs.map +0 -1
- /package/dist/bin/{bash-complete.d.cts → bash-complete.d.ts} +0 -0
- /package/dist/bin/{cli.d.cts → cli.d.ts} +0 -0
- /package/dist/bin/{deprecated-command.d.cts → deprecated-command.d.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/requests/constants.ts","../src/lib/requests/fuzzyMatchColumns.ts","../src/lib/requests/mapEnumValues.ts","../src/lib/requests/splitCsvToList.ts","../src/lib/requests/parseAttributesFromString.ts","../src/lib/requests/readCsv.ts","../src/lib/requests/getUniqueValuesForColumn.ts","../src/lib/requests/filterRows.ts","../src/lib/requests/markSilentPrivacyRequests.ts","../src/lib/requests/mapCsvColumnsToApi.ts","../src/lib/requests/mapRequestEnumValues.ts","../src/lib/requests/mapCsvRowsToRequestInputs.ts","../src/lib/requests/getFileMetadataForPrivacyRequests.ts","../src/lib/requests/streamPrivacyRequestFiles.ts","../src/lib/requests/downloadPrivacyRequestFiles.ts","../src/lib/requests/submitPrivacyRequest.ts","../src/lib/requests/approvePrivacyRequests.ts","../src/lib/requests/notifyPrivacyRequestsAdditionalTime.ts","../src/lib/requests/mapColumnsToIdentifiers.ts","../src/lib/requests/cancelPrivacyRequests.ts","../src/lib/requests/mapColumnsToAttributes.ts","../src/lib/requests/extractClientError.ts","../src/lib/requests/uploadPrivacyRequestsFromCsv.ts","../src/lib/requests/restartPrivacyRequest.ts","../src/lib/requests/bulkRestartRequests.ts","../src/lib/requests/skipPreflightJobs.ts","../src/lib/requests/bulkRetryEnrichers.ts","../src/lib/requests/retryRequestDataSilos.ts","../src/lib/requests/pullPrivacyRequests.ts","../src/lib/requests/skipRequestDataSilos.ts","../src/lib/requests/removeUnverifiedRequestIdentifiers.ts"],"sourcesContent":["import { applyEnum, valuesOf } from '@transcend-io/type-utils';\nimport { LanguageKey } 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(LanguageKey)),\n /** Mapping between region and country code */\n regionToCountry: t.record(\n t.string,\n valuesOf({ ...IsoCountryCode, [NONE]: NONE }),\n ),\n /** Mapping between region and country sub division code */\n regionToCountrySubDivision: t.record(\n t.string,\n valuesOf({ ...IsoCountrySubdivisionCode, [NONE]: NONE }),\n ),\n /** Mapping between request status in import to Transcend request status */\n statusToRequestStatus: t.record(\n t.string,\n valuesOf({ ...CompletedRequestStatus, [NONE]: NONE }),\n ),\n});\n\n/** Type override */\nexport type CachedFileState = t.TypeOf<typeof CachedFileState>;\n\n/**\n * Successfully processed request\n */\nexport const SuccessfulRequest = t.type({\n id: t.string,\n link: t.string,\n rowIndex: t.number,\n coreIdentifier: t.string,\n attemptedAt: t.string,\n});\n\n/** Type override */\nexport type SuccessfulRequest = t.TypeOf<typeof SuccessfulRequest>;\n\n// Cache state\nexport const CachedRequestState = t.type({\n /** Set of privacy requests that failed to upload */\n failingRequests: t.array(t.record(t.string, t.any)),\n /** Successfully uploaded requests */\n successfulRequests: t.array(SuccessfulRequest),\n /** Duplicate requests */\n duplicateRequests: t.array(\n t.type({\n rowIndex: t.number,\n coreIdentifier: t.string,\n attemptedAt: t.string,\n }),\n ),\n});\n\n/** Type override */\nexport type CachedRequestState = t.TypeOf<typeof CachedRequestState>;\n","import inquirer from 'inquirer';\nimport { NONE, BULK_APPLY } from './constants';\n\nimport fuzzysearch from 'fuzzysearch';\n\n/**\n * Check if word1 and word2 are a fuzzy match of each other.\n * Returns true if word1 is fuzzy match of word2 or vice versa.\n *\n * @param word1 - First word\n * @param word2 - Second word\n * @returns True if words are fuzzy match\n */\nexport function fuzzySearch(word1: string, word2: string): boolean {\n return (\n fuzzysearch(word1.toLowerCase(), word2.toLowerCase()) ||\n fuzzysearch(word2.toLowerCase(), word1.toLowerCase())\n );\n}\n\n/**\n * Fuzzy match column names for a particular field\n *\n * @param allColumnNames - List of all column names\n * @param fuzzyMapName - The name of field being mapped to\n * @param isRequired - When true, don't include \"NONE\" as an option\n * @param canApplyAll - When true, include an option to specify the value in bulk\n * @returns The list of suggestions for inquirer\n */\nexport function fuzzyMatchColumns(\n allColumnNames: string[],\n fuzzyMapName: string,\n isRequired: boolean,\n canApplyAll?: boolean,\n): (string | InstanceType<typeof inquirer.Separator>)[] {\n const matchingColumnNames = allColumnNames.filter((x) =>\n fuzzySearch(fuzzyMapName.toLowerCase(), x.toLowerCase()),\n );\n return [\n ...matchingColumnNames,\n new inquirer.Separator(),\n ...(isRequired ? [] : [NONE]),\n ...(canApplyAll ? [BULK_APPLY] : []),\n ...allColumnNames.filter((x) => !matchingColumnNames.includes(x)),\n ];\n}\n","import inquirer from 'inquirer';\nimport autoCompletePrompt from 'inquirer-autocomplete-prompt';\nimport { apply, ObjByString } from '@transcend-io/type-utils';\nimport { fuzzySearch } from './fuzzyMatchColumns';\n\n/**\n * Map a set of inputs to a set of outputs\n *\n * @param csvInputs - Input list\n * @param expectedOutputs - Output list\n * @param cache - Cache\n * @returns Mapping from row to enum value\n */\nexport async function mapEnumValues<TValue extends string>(\n csvInputs: string[],\n expectedOutputs: TValue[],\n cache: { [k in string]: TValue },\n): Promise<{ [k in string]: TValue }> {\n inquirer.registerPrompt('autocomplete', autoCompletePrompt);\n\n const inputs = csvInputs\n .map((item) => item || '<blank>')\n .filter((value) => !cache[value]);\n if (inputs.length === 0) {\n return cache;\n }\n const result = await inquirer.prompt<{ [k in string]: TValue }>(\n inputs.map((value) => ({\n name: value,\n message: `Map value of: ${value}`,\n type: 'autocomplete',\n default: expectedOutputs.find((x) => fuzzySearch(value, x)),\n source: (answersSoFar: ObjByString, input: string) =>\n !input\n ? expectedOutputs\n : expectedOutputs.filter(\n (x) => typeof x === 'string' && fuzzySearch(input, x),\n ),\n })),\n );\n return {\n ...cache,\n ...apply(result, (r) =>\n typeof r === 'string' ? (r as TValue) : (Object.values(r)[0] as TValue),\n ),\n };\n}\n","/**\n * Split string to CSV\n *\n * Filter out double commas and spaces like:\n * Dog, Cat -> ['Dog', 'Cat']\n * Dog,,Cat -> ['Dog', 'Cat']\n *\n * @param value - Value\n * @returns List of values\n */\nexport function splitCsvToList(value: string): string[] {\n return value\n .split(',')\n .map((x) => x.trim())\n .filter((x) => x);\n}\n","import colors from 'colors';\nimport * as t from 'io-ts';\nimport { logger } from '../../logger';\n\nexport const ParsedAttributeInput = t.type({\n /** Attribute key */\n key: t.string,\n /** Attribute values */\n values: t.array(t.string),\n});\n\n/** Type override */\nexport type ParsedAttributeInput = t.TypeOf<typeof ParsedAttributeInput>;\n\n/**\n * Parse out the extra attributes to apply to all requests uploaded\n *\n * @param attributes - input as string, e.g. ['key:value1;value2','key2:value3;value4']\n * @returns The parsed attributes\n */\nexport function parseAttributesFromString(\n attributes: string[],\n): ParsedAttributeInput[] {\n // Parse out the extra attributes to apply to all requests uploaded\n const parsedAttributes = attributes.map((attribute) => {\n const [attributeKey, attributeValuesRaw] = attribute.trim().split(':');\n if (!attributeValuesRaw) {\n throw new Error(\n 'Expected attributes in key:value1;value2,key2:value3;value4',\n );\n }\n const attributeValues = attributeValuesRaw.split(';');\n return {\n key: attributeKey,\n values: attributeValues,\n };\n });\n logger.info(colors.magenta('Attributes to apply to all requests:'));\n logger.info(colors.magenta(JSON.stringify(parsedAttributes, null, 2)));\n return parsedAttributes;\n}\n","import type { Options } from 'csv-parse';\nimport { parse } from 'csv-parse/sync';\nimport { readFileSync } from 'fs';\nimport * as t from 'io-ts';\n\nimport { decodeCodec } from '@transcend-io/type-utils';\n\n/**\n * Read in a CSV and validate its shape\n *\n * @param pathToFile - Path to file\n * @param codec - The codec to validate against. This is the codec for individual, non-header, rows\n * @param options - CSV parse options\n * @returns The JSON data\n */\nexport function readCsv<T extends t.Any>(\n pathToFile: string,\n codec: T,\n options: Options = { columns: true },\n): t.TypeOf<T>[] {\n // read file contents and parse\n const fileContent = parse(readFileSync(pathToFile, 'utf-8'), options);\n\n // validate codec\n const data = decodeCodec(t.array(codec), fileContent);\n\n // remove any special characters from object keys\n const parsed = data.map((datum) =>\n Object.entries(datum).reduce(\n (acc, [key, value]) =>\n Object.assign(acc, {\n [key.replace(/[^a-z_.+\\-A-Z -~]/g, '')]: value,\n }),\n {} as T,\n ),\n );\n return parsed;\n}\n","import { ObjByString } from '@transcend-io/type-utils';\nimport { uniq } from 'lodash-es';\n\n/**\n * Return the unique set of values for a column in a CSV\n *\n * @param rows - Rows to look up\n * @param columnName - Name of column to grab values for\n * @returns Unique set of values in that column\n */\nexport function getUniqueValuesForColumn(\n rows: ObjByString[],\n columnName: string,\n): string[] {\n return uniq(rows.map((row) => row[columnName] || '').flat());\n}\n","import inquirer from 'inquirer';\nimport { ObjByString } from '@transcend-io/type-utils';\nimport colors from 'colors';\nimport { uniq } from 'lodash-es';\nimport { logger } from '../../logger';\nimport { NONE } from './constants';\nimport { getUniqueValuesForColumn } from './getUniqueValuesForColumn';\n\n/**\n * Filter a list of CSV rows by column values\n * Choose columns that contain metadata to filter the requests\n *\n * @param rows - Rows to filter\n * @returns Filtered rows\n */\nexport async function filterRows(rows: ObjByString[]): Promise<ObjByString[]> {\n // Determine set of column names\n const columnNames = uniq(rows.map((x) => Object.keys(x)).flat());\n\n // update these variables recursively\n let filteredRows = rows;\n let keepFiltering = true;\n\n // loop over\n while (keepFiltering) {\n // Prompt user for column to filter on\n\n const { filterColumnName } = await inquirer.prompt<{\n /** Name of column to filter on */\n filterColumnName: string;\n }>([\n {\n name: 'filterColumnName',\n // eslint-disable-next-line max-len\n message: `If you need to filter the list of requests to import, choose the column to filter on. Currently ${filteredRows.length} rows.`,\n type: 'list',\n default: columnNames,\n choices: [NONE, ...columnNames],\n },\n ]);\n\n // Determine if filtering should continue, or loop should be exited\n keepFiltering = NONE !== filterColumnName;\n if (keepFiltering) {\n const options = getUniqueValuesForColumn(filteredRows, filterColumnName);\n\n const { valuesToKeep } = await inquirer.prompt<{\n /** Values to keep */\n valuesToKeep: string[];\n }>([\n {\n name: 'valuesToKeep',\n message: 'Keep rows matching this value',\n type: 'checkbox',\n default: columnNames,\n choices: options,\n },\n ]);\n\n filteredRows = filteredRows.filter((request) =>\n valuesToKeep.includes(request[filterColumnName]),\n );\n }\n }\n\n logger.info(colors.magenta(`Importing ${filteredRows.length} requests`));\n return filteredRows;\n}\n","import { map } from '@/lib/bluebird-replace';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport {\n UPDATE_PRIVACY_REQUEST,\n fetchAllRequests,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Mark a set of privacy requests to be in silent mode\n *\n * @param options - Options\n * @returns The number of requests marked silent\n */\nexport async function markSilentPrivacyRequests({\n requestActions,\n auth,\n requestIds,\n statuses = [\n RequestStatus.Compiling,\n RequestStatus.RequestMade,\n RequestStatus.Delayed,\n RequestStatus.Approving,\n RequestStatus.Secondary,\n RequestStatus.Enriching,\n RequestStatus.Waiting,\n RequestStatus.SecondaryApproving,\n ],\n createdAtAfter,\n createdAtBefore,\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** Transcend API key authentication */\n auth: string;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** The request statuses to mark silent */\n statuses?: RequestStatus[];\n /** The set of privacy requests to mark silent */\n requestIds?: string[];\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses,\n createdAtBefore,\n createdAtAfter,\n isSilent: false,\n requestIds,\n });\n\n // Notify Transcend\n logger.info(\n colors.magenta(`Marking \"${allRequests.length}\" as silent mode.`),\n );\n\n let total = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToMarkSilent) => {\n await makeGraphQLRequest(client, UPDATE_PRIVACY_REQUEST, {\n input: {\n id: requestToMarkSilent.id,\n isSilent: true,\n },\n });\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully marked ${total} requests as silent mode in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n return allRequests.length;\n}\n","import { getValues, getEntries } from '@transcend-io/type-utils';\nimport type { PersistedState } from '@transcend-io/persisted-state';\nimport inquirer from 'inquirer';\nimport { startCase } from 'lodash-es';\nimport {\n ColumnName,\n CachedFileState,\n IS_REQUIRED,\n CAN_APPLY_IN_BULK,\n} from './constants';\nimport { fuzzyMatchColumns } from './fuzzyMatchColumns';\n\n/**\n * Mapping from column name to request input parameter\n */\nexport type ColumnNameMap = {\n [k in ColumnName]?: string;\n};\n\n/**\n * Determine the mapping between columns in CSV\n *\n * @param columnNames - The set of column names\n * @param state - The cached file state used to map DSR inputs\n * @returns The column name mapping\n */\nexport async function mapCsvColumnsToApi(\n columnNames: string[],\n state: PersistedState<typeof CachedFileState>,\n): Promise<ColumnNameMap> {\n // Determine the columns that should be mapped\n const columnQuestions = getValues(ColumnName).filter(\n (name) => !state.getValue('columnNames', name),\n );\n\n // Skip mapping when everything is mapped\n const columnNameMap =\n columnQuestions.length === 0\n ? {}\n : // prompt questions to map columns\n await inquirer.prompt<{\n [k in ColumnName]?: string;\n }>(\n columnQuestions.map((name) => {\n const field = startCase(name.replace('ColumnName', ''));\n const matches = fuzzyMatchColumns(\n columnNames,\n field,\n IS_REQUIRED[name],\n !!CAN_APPLY_IN_BULK[name],\n );\n return {\n name,\n message: `Choose the column that will be used to map in the field: ${field}`,\n type: 'list',\n default: matches[0],\n choices: matches,\n };\n }),\n );\n\n await Promise.all(\n getEntries(columnNameMap).map(([k, v]) =>\n state.setValue(v, 'columnNames', k),\n ),\n );\n return columnNameMap;\n}\n","import { GraphQLClient } from 'graphql-request';\nimport colors from 'colors';\nimport type { PersistedState } from '@transcend-io/persisted-state';\nimport {\n CompletedRequestStatus,\n RequestAction,\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\nimport { LanguageKey } from '@transcend-io/internationalization';\nimport { ObjByString } from '@transcend-io/type-utils';\nimport { logger } from '../../logger';\nimport { makeGraphQLRequest, DataSubject, DATA_SUBJECTS } from '../graphql';\nimport { CachedFileState, NONE, ColumnName } from './constants';\nimport { mapEnumValues } from './mapEnumValues';\nimport { ColumnNameMap } from './mapCsvColumnsToApi';\nimport { getUniqueValuesForColumn } from './getUniqueValuesForColumn';\n\n/**\n * Map the values in a CSV to the enum values in Transcend\n *\n * @param client - GraphQL client\n * @param requests - Set of privacy requests\n * @param options - Options\n */\nexport async function mapRequestEnumValues(\n client: GraphQLClient,\n requests: ObjByString[],\n {\n state,\n columnNameMap,\n }: {\n /** State value to write cache to */\n state: PersistedState<typeof CachedFileState>;\n /** Mapping of column names */\n columnNameMap: ColumnNameMap;\n },\n): Promise<void> {\n // Get mapped value\n const getMappedName = (attribute: ColumnName): string =>\n state.getValue('columnNames', attribute) || columnNameMap[attribute]!;\n\n // Fetch all data subjects in the organization\n const { internalSubjects } = await makeGraphQLRequest<{\n /** Query response */\n internalSubjects: DataSubject[];\n }>(client, DATA_SUBJECTS);\n\n // Map RequestAction\n logger.info(\n colors.magenta('Determining mapping of columns for request action'),\n );\n const requestTypeToRequestAction: { [k in string]: RequestAction } =\n await mapEnumValues(\n getUniqueValuesForColumn(requests, getMappedName(ColumnName.RequestType)),\n Object.values(RequestAction),\n state.getValue('requestTypeToRequestAction'),\n );\n await state.setValue(\n requestTypeToRequestAction,\n 'requestTypeToRequestAction',\n );\n\n // Map data subject type\n logger.info(colors.magenta('Determining mapping of columns for subject'));\n const subjectTypeToSubjectName: { [k in string]: string } =\n await mapEnumValues(\n getUniqueValuesForColumn(requests, getMappedName(ColumnName.SubjectType)),\n internalSubjects.map(({ type }) => type),\n state.getValue('subjectTypeToSubjectName'),\n );\n await state.setValue(subjectTypeToSubjectName, 'subjectTypeToSubjectName');\n\n // Map locale\n logger.info(colors.magenta('Determining mapping of columns for locale'));\n const languageToLocale: { [k in string]: LanguageKey } = await mapEnumValues(\n getUniqueValuesForColumn(requests, getMappedName(ColumnName.Locale)),\n Object.values(LanguageKey),\n state.getValue('languageToLocale'),\n );\n await state.setValue(languageToLocale, 'languageToLocale');\n logger.info(\n colors.magenta('Determining mapping of columns for request status'),\n );\n\n // Map request status\n logger.info(\n colors.magenta('Determining mapping of columns for request status'),\n );\n const requestStatusColumn = getMappedName(ColumnName.RequestStatus);\n const statusToRequestStatus: {\n [k in string]: CompletedRequestStatus | typeof NONE;\n } =\n requestStatusColumn === NONE\n ? {}\n : await mapEnumValues(\n getUniqueValuesForColumn(requests, requestStatusColumn),\n [...Object.values(CompletedRequestStatus), NONE],\n state.getValue('statusToRequestStatus'),\n );\n await state.setValue(statusToRequestStatus, 'statusToRequestStatus');\n\n // Map country\n logger.info(colors.magenta('Determining mapping of columns for country'));\n const countryColumn = getMappedName(ColumnName.Country);\n const regionToCountry: {\n [k in string]: IsoCountryCode | typeof NONE;\n } =\n countryColumn === NONE\n ? {}\n : await mapEnumValues(\n getUniqueValuesForColumn(requests, countryColumn),\n [...Object.values(IsoCountryCode), NONE],\n state.getValue('regionToCountry'),\n );\n await state.setValue(regionToCountry, 'regionToCountry');\n\n // Map country sub division\n logger.info(\n colors.magenta('Determining mapping of columns for country sub division'),\n );\n const countrySubDivisionColumn = getMappedName(ColumnName.CountrySubDivision);\n const regionToCountrySubDivision: {\n [k in string]: IsoCountrySubdivisionCode | typeof NONE;\n } =\n countrySubDivisionColumn === NONE\n ? {}\n : await mapEnumValues(\n getUniqueValuesForColumn(requests, countrySubDivisionColumn),\n [...Object.values(IsoCountrySubdivisionCode), NONE],\n state.getValue('regionToCountrySubDivision'),\n );\n await state.setValue(\n regionToCountrySubDivision,\n 'regionToCountrySubDivision',\n );\n}\n","import { LanguageKey } from '@transcend-io/internationalization';\nimport { DateFromISOString } from 'io-ts-types';\n\nimport * as t from 'io-ts';\nimport type { PersistedState } from '@transcend-io/persisted-state';\nimport {\n NORMALIZE_PHONE_NUMBER,\n CompletedRequestStatus,\n RequestAction,\n IdentifierType,\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\nimport { ObjByString, valuesOf } from '@transcend-io/type-utils';\n\nimport {\n CachedFileState,\n BLANK,\n BULK_APPLY,\n ColumnName,\n NONE,\n} from './constants';\nimport { AttributeKey } from '../graphql';\nimport { ColumnNameMap } from './mapCsvColumnsToApi';\nimport { splitCsvToList } from './splitCsvToList';\nimport { ParsedAttributeInput } from './parseAttributesFromString';\nimport { AttributeNameMap } from './mapColumnsToAttributes';\nimport { IdentifierNameMap } from './mapColumnsToIdentifiers';\n\n/**\n * Shape of additional identifiers\n *\n * key of object is IdentifierType\n */\nexport const AttestedExtraIdentifiers = t.record(\n t.string,\n t.array(\n t.intersection([\n t.type({\n /** Value of identifier */\n value: t.string,\n }),\n t.partial({\n /** Name of identifier - option for non-custom identifier types */\n name: t.string,\n }),\n ]),\n ),\n);\n\n/** Type override */\nexport type AttestedExtraIdentifiers = t.TypeOf<\n typeof AttestedExtraIdentifiers\n>;\n\nexport const PrivacyRequestInput = t.intersection([\n t.type({\n /** Email of user */\n email: t.string,\n /** Extra identifiers */\n attestedExtraIdentifiers: AttestedExtraIdentifiers,\n /** Core identifier for user */\n coreIdentifier: t.string,\n /** Action type being submitted */\n requestType: valuesOf(RequestAction),\n /** Type of data subject */\n subjectType: t.string,\n }),\n t.partial({\n /** Country */\n country: valuesOf(IsoCountryCode),\n /** Country sub division */\n countrySubDivision: valuesOf(IsoCountrySubdivisionCode),\n /** Attribute inputs */\n attributes: t.array(ParsedAttributeInput),\n /** The status that the request should be created as */\n status: valuesOf(CompletedRequestStatus),\n /** The time that the request was created */\n createdAt: DateFromISOString,\n /** Data silo IDs to submit for */\n dataSiloIds: t.array(t.string),\n /** Language key to map to */\n locale: valuesOf(LanguageKey),\n }),\n]);\n\n/** Type override */\nexport type PrivacyRequestInput = t.TypeOf<typeof PrivacyRequestInput>;\n\n/**\n * Transform the identifier value based on type\n *\n * @param identifierValue - Value of identifier\n * @param identifierType - Type of identifier\n * @param defaultPhoneCountryCode - Default country code for phone numbers\n * @returns Post-processed identifier\n */\nexport function normalizeIdentifierValue(\n identifierValue: string,\n identifierType: IdentifierType,\n defaultPhoneCountryCode: string,\n): string {\n // Lowercase email\n if (identifierType === IdentifierType.Email) {\n return identifierValue.toLowerCase();\n }\n\n // Normalize phone number\n if (identifierType === IdentifierType.Phone) {\n const normalized = identifierValue\n .replace(NORMALIZE_PHONE_NUMBER, '')\n .replace(/[()]/g, '')\n .replace(/[–]/g, '')\n .replace(/[:]/g, '')\n .replace(/[]/g, '')\n .replace(/[A-Za-z]/g, '');\n return !normalized\n ? ''\n : normalized.startsWith('+')\n ? normalized\n : `+${defaultPhoneCountryCode}${normalized}`;\n }\n return identifierValue;\n}\n\n/**\n * Take the raw rows in a CSV upload, and map those rows to the request\n * input shape that can be passed to the Transcend API to submit a privacy\n * request.\n *\n * @param requestInputs - CSV of requests to be uploaded\n * @param state - The cached set of mapping values\n * @param options - Options\n * @returns [raw input, request input] list\n */\nexport function mapCsvRowsToRequestInputs(\n requestInputs: ObjByString[],\n state: PersistedState<typeof CachedFileState>,\n {\n columnNameMap,\n identifierNameMap,\n attributeNameMap,\n requestAttributeKeys,\n defaultPhoneCountryCode = '1', // US\n }: {\n /** Default country code */\n defaultPhoneCountryCode?: string;\n /** Mapping of column names */\n columnNameMap: ColumnNameMap;\n /** Mapping of identifier names */\n identifierNameMap: IdentifierNameMap;\n /** Mapping of attribute names */\n attributeNameMap: AttributeNameMap;\n /** Request attribute keys */\n requestAttributeKeys: AttributeKey[];\n },\n): [Record<string, string>, PrivacyRequestInput][] {\n // map the CSV to request input\n const getMappedName = (attribute: ColumnName): string =>\n state.getValue('columnNames', attribute) || columnNameMap[attribute]!;\n return requestInputs.map(\n (input): [Record<string, string>, PrivacyRequestInput] => {\n // The extra identifiers to upload for this request\n const attestedExtraIdentifiers: AttestedExtraIdentifiers = {};\n Object.entries(identifierNameMap)\n // filter out skipped identifiers\n .filter(([, columnName]) => columnName !== NONE)\n .forEach(([identifierName, columnName]) => {\n // Determine the identifier type being specified\n const identifierType = Object.values(IdentifierType).includes(\n identifierName as any, // eslint-disable-line @typescript-eslint/no-explicit-any\n )\n ? (identifierName as IdentifierType)\n : IdentifierType.Custom;\n\n // Only add the identifier if the value exists\n const identifierValue = input[columnName];\n if (identifierValue) {\n const normalized = normalizeIdentifierValue(\n identifierValue,\n identifierType,\n defaultPhoneCountryCode,\n );\n if (normalized) {\n // Initialize\n if (!attestedExtraIdentifiers[identifierType]) {\n attestedExtraIdentifiers[identifierType] = [];\n }\n\n // Add the identifier\n attestedExtraIdentifiers[identifierType]!.push({\n value: normalized,\n name: identifierName,\n });\n }\n }\n });\n\n // The extra attributes to upload for this request\n const attributes: ParsedAttributeInput[] = [];\n Object.entries(attributeNameMap)\n // filter out skipped attributes\n .filter(([, columnName]) => columnName !== NONE)\n .forEach(([attributeName, columnName]) => {\n // Only add the identifier if the value exists\n const attributeValueString = input[columnName];\n if (attributeValueString) {\n // Add the attribute\n const isMulti =\n requestAttributeKeys.find((attr) => attr.name === attributeName)\n ?.type === 'MULTI_SELECT';\n attributes.push({\n values: isMulti\n ? splitCsvToList(attributeValueString)\n : attributeValueString,\n key: attributeName,\n });\n }\n });\n\n const requestTypeColumn = getMappedName(ColumnName.RequestType);\n const dataSubjectTypeColumn = getMappedName(ColumnName.SubjectType);\n return [\n input,\n {\n email: input[getMappedName(ColumnName.Email)],\n attestedExtraIdentifiers,\n attributes,\n coreIdentifier: input[getMappedName(ColumnName.CoreIdentifier)],\n requestType:\n requestTypeColumn === BULK_APPLY\n ? state.getValue('requestTypeToRequestAction', BLANK)\n : state.getValue(\n 'requestTypeToRequestAction',\n input[requestTypeColumn],\n ),\n subjectType:\n dataSubjectTypeColumn === BULK_APPLY\n ? state.getValue('subjectTypeToSubjectName', BLANK)\n : state.getValue(\n 'subjectTypeToSubjectName',\n input[dataSubjectTypeColumn],\n ),\n ...(getMappedName(ColumnName.Locale) !== NONE &&\n input[getMappedName(ColumnName.Locale)]\n ? {\n locale: state.getValue(\n 'languageToLocale',\n input[getMappedName(ColumnName.Locale)],\n ),\n }\n : {}),\n ...(getMappedName(ColumnName.Country) !== NONE &&\n input[getMappedName(ColumnName.Country)]\n ? {\n country: state.getValue(\n 'regionToCountry',\n input[getMappedName(ColumnName.Country)],\n ) as IsoCountryCode,\n }\n : {}),\n ...(getMappedName(ColumnName.CountrySubDivision) !== NONE &&\n input[getMappedName(ColumnName.CountrySubDivision)]\n ? {\n countrySubDivision: state.getValue(\n 'regionToCountrySubDivision',\n input[getMappedName(ColumnName.CountrySubDivision)],\n ) as IsoCountrySubdivisionCode,\n }\n : {}),\n ...(getMappedName(ColumnName.RequestStatus) !== NONE &&\n state.getValue(\n 'statusToRequestStatus',\n input[getMappedName(ColumnName.RequestStatus)],\n ) !== NONE &&\n input[getMappedName(ColumnName.RequestStatus)]\n ? {\n status: state.getValue(\n 'statusToRequestStatus',\n input[getMappedName(ColumnName.RequestStatus)],\n ) as CompletedRequestStatus,\n }\n : {}),\n ...(getMappedName(ColumnName.CreatedAt) !== NONE &&\n input[getMappedName(ColumnName.CreatedAt)]\n ? {\n createdAt: new Date(input[getMappedName(ColumnName.CreatedAt)]),\n }\n : {}),\n ...(getMappedName(ColumnName.DataSiloIds) !== NONE &&\n input[getMappedName(ColumnName.DataSiloIds)]\n ? {\n dataSiloIds: splitCsvToList(\n input[getMappedName(ColumnName.DataSiloIds)],\n ),\n }\n : {}),\n },\n ];\n },\n );\n}\n","import { map } from '@/lib/bluebird-replace';\nimport colors from 'colors';\nimport cliProgress from 'cli-progress';\n\nimport { PrivacyRequest } from '../graphql';\nimport * as t from 'io-ts';\nimport type { Got } from 'got';\nimport { decodeCodec, valuesOf } from '@transcend-io/type-utils';\nimport { logger } from '../../logger';\nimport { TableEncryptionType } from '@transcend-io/privacy-types';\n\nexport const IntlMessage = t.type({\n /** The message key */\n defaultMessage: t.string,\n /** ID */\n id: t.string,\n});\n\n/** Type */\nexport type IntlMessage = t.TypeOf<typeof IntlMessage>;\n\nexport const RequestFileMetadata = t.type({\n /** The key to pass to download the file contents */\n downloadKey: t.string,\n /** Error message related to file */\n error: t.union([t.null, t.string]),\n /** Mimetype of file */\n mimetype: t.string,\n /** Size of file, stored as string as this can be a BigInt */\n size: t.string,\n /** Name of file based on datapoint names in Transcend */\n fileName: t.string,\n /** The metadata on the datapoint */\n dataPoint: t.type({\n /** ID of datapoint */\n id: t.string,\n /** The title of datapoint */\n title: t.union([IntlMessage, t.null]),\n /** Description of datapoint */\n description: t.union([IntlMessage, t.null]),\n /** Name of datapoint */\n name: t.string,\n /** Slug of datapoint */\n slug: t.string,\n /** Table level encryption information */\n encryption: t.union([valuesOf(TableEncryptionType), t.null]),\n /** The name of the data silo */\n dataSilo: t.type({\n /** ID of the data silo */\n id: t.string,\n /** The title of the data silo */\n title: t.string,\n /** The description of the data silo */\n description: t.string,\n /** The type of the data silo */\n type: t.string,\n /** The outer type of the data silo */\n outerType: t.union([t.string, t.null]),\n }),\n /** The path to the datapoint if a database (e.g. name of schema) */\n path: t.array(t.string),\n }),\n});\n\n/** Type override */\nexport type RequestFileMetadata = t.TypeOf<typeof RequestFileMetadata>;\n\nexport const RequestFileMetadataResponse = t.type({\n /** The list of file metadata */\n nodes: t.array(RequestFileMetadata),\n /** The total number of file metadata */\n totalCount: t.number,\n /** Links to next pages */\n _links: t.partial({\n /** The link to the next page of file metadata */\n next: t.union([t.string, t.null]),\n /** The link to the previous page of file metadata */\n previous: t.union([t.string, t.null]),\n }),\n});\n\n/** Type override */\nexport type RequestFileMetadataResponse = t.TypeOf<\n typeof RequestFileMetadataResponse\n>;\n\n/**\n * Given a list of privacy requests, download the file metadata\n * for these requests - this is useful to prepare the files in a\n * data access request for download.\n *\n * @param requests - The list of privacy requests to download files for\n * @param options - Options\n * @returns The number of requests canceled\n */\nexport async function getFileMetadataForPrivacyRequests(\n requests: Pick<PrivacyRequest, 'id' | 'status'>[],\n {\n sombra,\n concurrency = 5,\n limit = 100,\n }: {\n /** Sombra instance */\n sombra: Got;\n /** Number of files to pull at once */\n limit?: number;\n /** Concurrency limit for approving */\n concurrency?: number;\n },\n): Promise<[Pick<PrivacyRequest, 'id' | 'status'>, RequestFileMetadata[]][]> {\n logger.info(\n colors.magenta(`Pulling file metadata for ${requests.length} requests`),\n );\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Start timer\n let total = 0;\n progressBar.start(requests.length, 0);\n\n // Loop over the requests\n const results = await map(\n requests,\n async (\n requestToDownload,\n ): Promise<\n [Pick<PrivacyRequest, 'id' | 'status'>, RequestFileMetadata[]]\n > => {\n const localResults: RequestFileMetadata[] = [];\n\n // Paginate over the file metadata for this request\n let shouldContinue = true;\n let offset = 0;\n while (shouldContinue) {\n let response: RequestFileMetadataResponse;\n try {\n // Grab the file metadata for this request\n\n const rawResponse = await sombra\n .get(\n `v1/data-subject-request/${requestToDownload.id}/download-keys`,\n {\n searchParams: {\n limit,\n offset,\n },\n },\n )\n .json();\n response = decodeCodec(RequestFileMetadataResponse, rawResponse);\n localResults.push(...response.nodes);\n\n // Increase offset and break if no more pages\n offset += limit;\n shouldContinue =\n // eslint-disable-next-line no-underscore-dangle\n !!response._links.next && response.nodes.length === limit;\n } catch (err) {\n throw new Error(\n `Received an error from server: ${\n err?.response?.body || err?.message\n }`,\n );\n }\n }\n\n total += 1;\n progressBar.update(total);\n return [requestToDownload, localResults];\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully downloaded file metadata ${requests.length} requests in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n\n return results;\n}\n","import { map } from '@/lib/bluebird-replace';\nimport colors from 'colors';\nimport { RequestFileMetadata } from './getFileMetadataForPrivacyRequests';\nimport type { Got } from 'got';\nimport { logger } from '../../logger';\n\n/**\n * This function will take in a set of file metadata for privacy requests\n * call the Transcend API to stream the file metadata for these requests\n * and pass that through a callback function\n *\n * @param fileMetadata - Metadata to download\n * @param options - Options for the request\n */\nexport async function streamPrivacyRequestFiles(\n fileMetadata: RequestFileMetadata[],\n {\n requestId,\n sombra,\n onFileDownloaded,\n concurrency = 20,\n }: {\n /** Request ID for logging */\n requestId: string;\n /** Sombra got instance */\n sombra: Got;\n /** Handler on each file */\n onFileDownloaded: (metadata: RequestFileMetadata, stream: Buffer) => void;\n /** Concurrent downloads at once */\n concurrency?: number;\n },\n): Promise<void> {\n // Loop over each file\n await map(\n fileMetadata,\n async (metadata) => {\n try {\n // Construct the stream\n await sombra\n .get('v1/files', {\n searchParams: {\n downloadKey: metadata.downloadKey,\n },\n })\n .buffer()\n .then((fileResponse) => onFileDownloaded(metadata, fileResponse));\n } catch (err) {\n if (err?.response?.body?.includes('fileMetadata#verify')) {\n logger.error(\n colors.red(\n `Failed to pull file for: ${metadata.fileName} (request:${requestId}) - JWT expired. ` +\n 'This likely means that the file is no longer available. ' +\n 'Try restarting the request from scratch in Transcend Admin Dashboard. ' +\n 'Skipping the download of this file.',\n ),\n );\n return;\n }\n throw new Error(\n `Received an error from server: ${\n err?.response?.body || err?.message\n }`,\n );\n }\n },\n {\n concurrency,\n },\n );\n}\n","import { map } from '@/lib/bluebird-replace';\nimport { existsSync, mkdirSync, writeFileSync } from 'fs';\nimport { dirname, join } from 'path';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport {\n fetchAllRequests,\n buildTranscendGraphQLClient,\n createSombraGotInstance,\n makeGraphQLRequest,\n APPROVE_PRIVACY_REQUEST,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\nimport { getFileMetadataForPrivacyRequests } from './getFileMetadataForPrivacyRequests';\nimport { streamPrivacyRequestFiles } from './streamPrivacyRequestFiles';\n\n/**\n * Download a set of privacy requests to disk\n *\n * @param options - Options\n * @returns The number of requests canceled\n */\nexport async function downloadPrivacyRequestFiles({\n auth,\n folderPath,\n requestIds,\n createdAtBefore,\n sombraAuth,\n createdAtAfter,\n statuses = [RequestStatus.Approving, RequestStatus.Downloadable],\n concurrency = 5,\n transcendUrl = DEFAULT_TRANSCEND_API,\n approveAfterDownload = false,\n}: {\n /** The folder path to download the files to */\n folderPath: string;\n /** Transcend API key authentication */\n auth: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** The request statuses to cancel */\n statuses?: RequestStatus[];\n /** The set of privacy requests to cancel */\n requestIds?: string[];\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** When true, approve any requests in Transcend that are in status=APPROVING */\n approveAfterDownload?: boolean;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Create sombra instance to communicate with\n const sombra = await createSombraGotInstance(transcendUrl, auth, sombraAuth);\n\n // Create the folder if it does not exist\n if (!existsSync(folderPath)) {\n mkdirSync(folderPath);\n }\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: [RequestAction.Access],\n createdAtBefore,\n createdAtAfter,\n statuses,\n requestIds,\n });\n\n // Download the file metadata for each request\n const requestFileMetadata = await getFileMetadataForPrivacyRequests(\n allRequests,\n {\n sombra,\n concurrency,\n },\n );\n\n // Start timer for download process\n const t0 = new Date().getTime();\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n let total = 0;\n let totalApproved = 0;\n progressBar.start(allRequests.length, 0);\n\n // Download the files for each request\n await map(\n requestFileMetadata,\n async ([request, metadata]) => {\n // Create a new folder to store request files\n const requestFolder = join(folderPath, request.id);\n if (!existsSync(requestFolder)) {\n mkdirSync(requestFolder);\n }\n\n // Stream each file to disk\n await streamPrivacyRequestFiles(metadata, {\n sombra,\n requestId: request.id,\n onFileDownloaded: (fil, stream) => {\n // Ensure a folder exists for the file\n // filename looks like Health/heartbeat.csv\n const filePath = join(requestFolder, fil.fileName);\n const folder = dirname(filePath);\n if (!existsSync(folder)) {\n mkdirSync(folder, { recursive: true });\n }\n\n // Write to disk\n writeFileSync(filePath, stream);\n },\n });\n\n // Approve the request if requested\n if (approveAfterDownload && request.status === RequestStatus.Approving) {\n await makeGraphQLRequest(client, APPROVE_PRIVACY_REQUEST, {\n input: { requestId: request.id },\n });\n totalApproved += 1;\n }\n\n // Increment the progress bar\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully downloaded ${total} requests in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n if (totalApproved > 0) {\n logger.info(\n colors.green(`Approved ${totalApproved} requests in Transcend.`),\n );\n }\n return allRequests.length;\n}\n","import * as t from 'io-ts';\nimport { uniq } from 'lodash-es';\nimport { valuesOf, decodeCodec } from '@transcend-io/type-utils';\nimport {\n IsoCountryCode,\n IsoCountrySubdivisionCode,\n RequestAction,\n RequestStatus,\n} from '@transcend-io/privacy-types';\nimport type { Got } from 'got';\nimport { PrivacyRequestInput } from './mapCsvRowsToRequestInputs';\nimport { ParsedAttributeInput } from './parseAttributesFromString';\n\nexport const PrivacyRequestResponse = t.type({\n id: t.string,\n link: t.string,\n status: valuesOf(RequestStatus),\n type: valuesOf(RequestAction),\n subjectType: t.string,\n email: t.union([t.null, t.string]),\n coreIdentifier: t.string,\n isSilent: t.boolean,\n isTest: t.boolean,\n country: t.union([t.null, valuesOf(IsoCountryCode)]),\n countrySubDivision: t.union([t.null, valuesOf(IsoCountrySubdivisionCode)]),\n attributeValues: t.array(\n t.type({\n attributeKey: t.type({ name: t.string }),\n name: t.string,\n }),\n ),\n});\n\n/** Type override */\nexport type PrivacyRequestResponse = t.TypeOf<typeof PrivacyRequestResponse>;\n\n/**\n * Submit a privacy request to the Transcend API\n *\n * @param sombra - Sombra instance configured to make requests\n * @param input - Request input\n * @param options - Additional options\n * @returns Successfully submitted request\n */\nexport async function submitPrivacyRequest(\n sombra: Got,\n input: PrivacyRequestInput,\n {\n details = '',\n isTest = false,\n emailIsVerified = true,\n skipSendingReceipt = false,\n isSilent = true,\n additionalAttributes = [],\n }: {\n /** Whether or not the request is a test request */\n isTest?: boolean;\n /** Whether or not the request is in silent mode */\n isSilent?: boolean;\n /** Whether the email is verified up front */\n emailIsVerified?: boolean;\n /** When true, skip sending of the email receipt */\n skipSendingReceipt?: boolean;\n /** Request details */\n details?: string;\n /** Additional attributes to tag the requests with */\n additionalAttributes?: ParsedAttributeInput[];\n } = {},\n): Promise<PrivacyRequestResponse> {\n // Merge the per-request attributes with the\n // global attributes\n const mergedAttributes = [...additionalAttributes];\n (input.attributes || []).forEach((attribute) => {\n const existing = mergedAttributes.find(\n (attr) => attr.key === attribute.key,\n );\n if (existing) {\n existing.values.push(...attribute.values);\n existing.values = uniq(existing.values);\n } else {\n mergedAttributes.push(attribute);\n }\n });\n\n // Make the GraphQL request\n let response: unknown;\n try {\n response = await sombra\n .post('v1/data-subject-request', {\n json: {\n type: input.requestType,\n subject: {\n coreIdentifier: input.coreIdentifier,\n email: input.email,\n emailIsVerified,\n attestedExtraIdentifiers: input.attestedExtraIdentifiers,\n },\n subjectType: input.subjectType,\n isSilent,\n isTest,\n skipSendingReceipt,\n ...(input.locale ? { locale: input.locale } : {}),\n details,\n attributes: mergedAttributes,\n ...(input.country || input.countrySubDivision\n ? {\n region: {\n ...(input.country\n ? {\n country: input.country,\n }\n : input.countrySubDivision\n ? { country: input.countrySubDivision.split('-')[0] }\n : {}),\n ...(input.countrySubDivision\n ? { countrySubDivision: input.countrySubDivision }\n : {}),\n },\n }\n : {}),\n ...(input.createdAt ? { createdAt: input.createdAt } : {}),\n ...(input.dataSiloIds ? { dataSiloIds: input.dataSiloIds } : {}),\n ...(input.status ? { completedRequestStatus: input.status } : {}),\n },\n })\n .json();\n } catch (err) {\n throw new Error(\n `Received an error from server: ${err?.response?.body || err?.message}`,\n );\n }\n\n const { request: requestResponse } = decodeCodec(\n t.type({\n request: PrivacyRequestResponse,\n }),\n response,\n );\n return requestResponse;\n}\n","import { map } from '@/lib/bluebird-replace';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport {\n RequestAction,\n RequestOrigin,\n RequestStatus,\n} from '@transcend-io/privacy-types';\nimport {\n UPDATE_PRIVACY_REQUEST,\n fetchAllRequests,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n APPROVE_PRIVACY_REQUEST,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Approve a set of privacy requests\n *\n * @param options - Options\n * @returns The number of requests approved\n */\nexport async function approvePrivacyRequests({\n requestActions,\n requestOrigins,\n auth,\n silentModeBefore,\n createdAtAfter,\n createdAtBefore,\n concurrency = 50,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** The request origins that should be restarted */\n requestOrigins?: RequestOrigin[];\n /** Transcend API key authentication */\n auth: string;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** Mark these requests as silent mode if they were created before this date */\n silentModeBefore?: Date;\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses: [RequestStatus.Approving],\n createdAtAfter,\n origins: requestOrigins,\n createdAtBefore,\n });\n\n // Notify Transcend\n logger.info(colors.magenta(`Approving \"${allRequests.length}\" requests.`));\n\n let total = 0;\n let skipped = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToApprove) => {\n // update request to silent mode if silentModeBefore is defined\n // and the request was created before silentModeBefore\n if (\n silentModeBefore &&\n new Date(silentModeBefore) > new Date(requestToApprove.createdAt)\n ) {\n await makeGraphQLRequest(client, UPDATE_PRIVACY_REQUEST, {\n input: {\n id: requestToApprove.id,\n isSilent: true,\n },\n });\n }\n\n try {\n // approve the request\n await makeGraphQLRequest(client, APPROVE_PRIVACY_REQUEST, {\n input: { requestId: requestToApprove.id },\n });\n } catch (err) {\n if (err.message.includes('Request must be in an approving state,')) {\n skipped += 1;\n }\n }\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n if (skipped > 0) {\n logger.info(colors.yellow(`${skipped} requests were skipped.`));\n }\n logger.info(\n colors.green(\n `Successfully approved ${total} requests in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n return allRequests.length;\n}\n","import { map } from '@/lib/bluebird-replace';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport { RequestAction } from '@transcend-io/privacy-types';\nimport {\n NOTIFY_ADDITIONAL_TIME,\n fetchAllRequests,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n fetchAllTemplates,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Mark a set of privacy requests to be in silent mode.\n * Note requests in silent mode are ignored\n *\n * @param options - Options\n * @returns The number of requests marked silent\n */\nexport async function notifyPrivacyRequestsAdditionalTime({\n requestActions = Object.values(RequestAction),\n auth,\n requestIds,\n createdAtBefore,\n days = 45,\n daysLeft = 10,\n createdAtAfter,\n emailTemplate = 'Additional Time Needed',\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions?: RequestAction[];\n /** Filter for requests created before this date */\n createdAtBefore: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Email template */\n emailTemplate?: string;\n /** Transcend API key authentication */\n auth: string;\n /** Number of days to extend request by */\n days?: number;\n /**\n * Only notify requests that have less than this number of days until they are considered expired.\n * This allows for re-running the command without notifying the same users multiple times\n */\n daysLeft?: number;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** The set of privacy requests to notify */\n requestIds?: string[];\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Grab the template with that title\n const matchingTemplates = await fetchAllTemplates(client, emailTemplate);\n const exactTemplateMatch = matchingTemplates.find(\n (template) => template.title === emailTemplate,\n );\n if (!exactTemplateMatch) {\n throw new Error(`Failed to find a template with title: \"${emailTemplate}\"`);\n }\n\n // Pull in the requests\n let allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n createdAtBefore,\n createdAtAfter,\n isSilent: false,\n isClosed: false,\n requestIds,\n });\n\n // Filter requests by daysLeft\n allRequests = allRequests.filter(\n (request) =>\n typeof request.daysRemaining === 'number' &&\n request.daysRemaining < daysLeft,\n );\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Notifying \"${allRequests.length}\" that more time is needed.`,\n ),\n );\n\n let total = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToNotify) => {\n await makeGraphQLRequest(client, NOTIFY_ADDITIONAL_TIME, {\n input: {\n requestId: requestToNotify.id,\n template: exactTemplateMatch.template.defaultMessage,\n subject: exactTemplateMatch.subject.defaultMessage,\n additionalTime: days,\n },\n });\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully marked ${total} requests as silent mode in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n return allRequests.length;\n}\n","import type { GraphQLClient } from 'graphql-request';\nimport inquirer from 'inquirer';\nimport { INITIALIZER, makeGraphQLRequest, Initializer } from '../graphql';\nimport { CachedFileState, IDENTIFIER_BLOCK_LIST } from './constants';\nimport { fuzzyMatchColumns } from './fuzzyMatchColumns';\nimport type { PersistedState } from '@transcend-io/persisted-state';\n\n/**\n * Mapping from identifier name to request input parameter\n */\nexport type IdentifierNameMap = {\n [k in string]: string;\n};\n\n/**\n * Create a mapping from the identifier names that can be included\n * at request submission, to the names of the columns that map to those\n * identifiers.\n *\n * @param client - GraphQL client\n * @param columnNames - The set of all column names\n * @param state - Cached state of this mapping\n * @returns Mapping from identifier name to column name\n */\nexport async function mapColumnsToIdentifiers(\n client: GraphQLClient,\n columnNames: string[],\n state: PersistedState<typeof CachedFileState>,\n): Promise<IdentifierNameMap> {\n // Grab the initializer\n const { initializer } = await makeGraphQLRequest<{\n /** Query response */\n initializer: Initializer;\n }>(client, INITIALIZER);\n\n // Determine the columns that should be mapped\n const columnQuestions = initializer.identifiers.filter(\n ({ name }) =>\n !state.getValue('identifierNames', name) &&\n !IDENTIFIER_BLOCK_LIST.includes(name),\n );\n\n // Skip mapping when everything is mapped\n const identifierNameMap =\n columnQuestions.length === 0\n ? {}\n : // prompt questions to map columns\n await inquirer.prompt<{\n [k in string]: string;\n }>(\n columnQuestions.map(({ name }) => {\n const matches = fuzzyMatchColumns(columnNames, name, false);\n return {\n name,\n message: `Choose the column that will be used to map in the identifier: ${name}`,\n type: 'list',\n default: matches[0],\n choices: matches,\n };\n }),\n );\n await Promise.all(\n Object.entries(identifierNameMap).map(([k, v]) =>\n state.setValue(v, 'identifierNames', k),\n ),\n );\n\n return {\n ...state.getValue('identifierNames'),\n ...identifierNameMap,\n };\n}\n","import { map } from '@/lib/bluebird-replace';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport {\n UPDATE_PRIVACY_REQUEST,\n fetchAllRequests,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n CANCEL_PRIVACY_REQUEST,\n fetchAllTemplates,\n Template,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Cancel a set of privacy requests\n *\n * @param options - Options\n * @returns The number of requests canceled\n */\nexport async function cancelPrivacyRequests({\n requestActions,\n cancellationTitle,\n auth,\n requestIds,\n silentModeBefore,\n createdAtBefore,\n createdAtAfter,\n statuses = [\n RequestStatus.Compiling,\n RequestStatus.RequestMade,\n RequestStatus.Delayed,\n RequestStatus.Approving,\n RequestStatus.Secondary,\n RequestStatus.Enriching,\n RequestStatus.Waiting,\n RequestStatus.SecondaryApproving,\n ],\n concurrency = 50,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** Transcend API key authentication */\n auth: string;\n /** Concurrency limit for approving */\n concurrency?: number;\n /** The request statuses to cancel */\n statuses?: RequestStatus[];\n /** The set of privacy requests to cancel */\n requestIds?: string[];\n /** Mark these requests as silent mode if they were created before this date */\n silentModeBefore?: Date;\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** The email template to use when canceling the requests */\n cancellationTitle?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Grab the template with that title\n let cancelationTemplate: Template | undefined;\n if (cancellationTitle) {\n const matchingTemplates = await fetchAllTemplates(\n client,\n cancellationTitle,\n );\n const exactTitleMatch = matchingTemplates.find(\n (template) => template.title === cancellationTitle,\n );\n if (!exactTitleMatch) {\n throw new Error(\n `Failed to find a template with title: \"${cancellationTitle}\"`,\n );\n }\n cancelationTemplate = exactTitleMatch;\n }\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n createdAtBefore,\n createdAtAfter,\n statuses,\n requestIds,\n });\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Canceling \"${allRequests.length}\" requests${\n cancelationTemplate\n ? ` Using template: ${cancelationTemplate.title}`\n : ''\n }.`,\n ),\n );\n\n let total = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToCancel) => {\n // update request to silent mode if silentModeBefore is defined\n // and the request was created before silentModeBefore\n if (\n silentModeBefore &&\n new Date(silentModeBefore) > new Date(requestToCancel.createdAt)\n ) {\n await makeGraphQLRequest(client, UPDATE_PRIVACY_REQUEST, {\n input: {\n id: requestToCancel.id,\n isSilent: true,\n },\n });\n }\n\n // cancel the request\n await makeGraphQLRequest(client, CANCEL_PRIVACY_REQUEST, {\n input: {\n requestId: requestToCancel.id,\n ...(cancelationTemplate\n ? {\n subject: `Re: ${cancelationTemplate.subject.defaultMessage}`,\n template: cancelationTemplate.template.defaultMessage,\n }\n : {}),\n },\n });\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully canceled ${total} requests in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n return allRequests.length;\n}\n","import type { GraphQLClient } from 'graphql-request';\nimport inquirer from 'inquirer';\nimport { AttributeKey } from '../graphql';\nimport { CachedFileState } from './constants';\nimport { fuzzyMatchColumns } from './fuzzyMatchColumns';\nimport type { PersistedState } from '@transcend-io/persisted-state';\n\n/**\n * Mapping from attribute name to request input parameter\n */\nexport type AttributeNameMap = {\n [k in string]: string;\n};\n\n/**\n * Create a mapping from the attributes names that can be included\n * at request submission, to the names of the columns that map to those\n * attributes.\n *\n * @param client - GraphQL client\n * @param columnNames - The set of all column names\n * @param state - Cached state of this mapping\n * @param requestAttributeKeys - Attribute keys to map\n * @returns Mapping from attributes name to column name\n */\nexport async function mapColumnsToAttributes(\n client: GraphQLClient,\n columnNames: string[],\n state: PersistedState<typeof CachedFileState>,\n requestAttributeKeys: AttributeKey[],\n): Promise<AttributeNameMap> {\n // Determine the columns that should be mapped\n const columnQuestions = requestAttributeKeys.filter(\n ({ name }) => !state.getValue('attributeNames', name),\n );\n\n // Skip mapping when everything is mapped\n const attributeNameMap =\n columnQuestions.length === 0\n ? {}\n : // prompt questions to map columns\n await inquirer.prompt<{\n [k in string]: string;\n }>(\n columnQuestions.map(({ name }) => {\n const matches = fuzzyMatchColumns(columnNames, name, false);\n return {\n name,\n message: `Choose the column that will be used to map in the attribute: ${name}`,\n type: 'list',\n default: matches[0],\n choices: matches,\n };\n }),\n );\n await Promise.all(\n Object.entries(attributeNameMap).map(([k, v]) =>\n state.setValue(v, 'attributeNames', k),\n ),\n );\n\n return {\n ...state.getValue('attributeNames'),\n ...attributeNameMap,\n };\n}\n","const CLIENT_ERROR = /{\\\\\"message\\\\\":\\\\\"(.+?)\\\\\",/;\n\n/**\n * Extract a client error from the request\n *\n * @param err - Error message\n * @returns Client error or null\n */\nexport function extractClientError(err: string): string | null {\n return CLIENT_ERROR.test(err) ? CLIENT_ERROR.exec(err)![1] : null;\n}\n","/* eslint-disable max-lines */\nimport colors from 'colors';\nimport { map } from '@/lib/bluebird-replace';\nimport * as t from 'io-ts';\nimport { uniq } from 'lodash-es';\nimport cliProgress from 'cli-progress';\nimport { join } from 'path';\nimport { PersistedState } from '@transcend-io/persisted-state';\nimport { logger } from '../../logger';\nimport {\n createSombraGotInstance,\n buildTranscendGraphQLClient,\n fetchAllRequestAttributeKeys,\n} from '../graphql';\nimport { mapRequestEnumValues } from './mapRequestEnumValues';\nimport { CachedRequestState, CachedFileState } from './constants';\nimport { mapCsvColumnsToApi } from './mapCsvColumnsToApi';\nimport { parseAttributesFromString } from './parseAttributesFromString';\nimport { readCsv } from './readCsv';\nimport { submitPrivacyRequest } from './submitPrivacyRequest';\nimport { mapColumnsToAttributes } from './mapColumnsToAttributes';\nimport { mapColumnsToIdentifiers } from './mapColumnsToIdentifiers';\nimport { mapCsvRowsToRequestInputs } from './mapCsvRowsToRequestInputs';\nimport { filterRows } from './filterRows';\nimport { extractClientError } from './extractClientError';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Upload a set of privacy requests from CSV\n *\n * @param options - Options\n */\nexport async function uploadPrivacyRequestsFromCsv({\n cacheFilepath,\n requestReceiptFolder,\n file,\n auth,\n sombraAuth,\n concurrency = 100,\n defaultPhoneCountryCode = '1', // USA\n transcendUrl = DEFAULT_TRANSCEND_API,\n attributes = [],\n emailIsVerified = true,\n skipFilterStep = false,\n skipSendingReceipt = true,\n isTest = false,\n isSilent = true,\n debug = false,\n dryRun = false,\n}: {\n /** File to cache metadata about mapping of CSV shape to script */\n cacheFilepath: string;\n /** File where request receipts are stored */\n requestReceiptFolder: string;\n /** CSV file path */\n file: string;\n /** Transcend API key authentication */\n auth: string;\n /** Default country code for phone numbers */\n defaultPhoneCountryCode?: string;\n /** Concurrency to upload in */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** Include debug logs */\n debug?: boolean;\n /** Skip the step where requests are filtered */\n skipFilterStep?: boolean;\n /** Whether test requests are being uploaded */\n isTest?: boolean;\n /** Whether requests are uploaded in silent mode */\n isSilent?: boolean;\n /** Whether to send the email receipt */\n skipSendingReceipt?: boolean;\n /** Whether the email was verified up front */\n emailIsVerified?: boolean;\n /** Attributes string pre-parse */\n attributes?: string[];\n /** Whether a dry run is happening */\n dryRun?: boolean;\n}): Promise<void> {\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Parse out the extra attributes to apply to all requests uploaded\n const parsedAttributes = parseAttributesFromString(attributes);\n\n // Create a new state to persist the metadata that\n // maps the request inputs to the Transcend API shape\n const state = new PersistedState(cacheFilepath, CachedFileState, {\n columnNames: {},\n requestTypeToRequestAction: {},\n subjectTypeToSubjectName: {},\n languageToLocale: {},\n statusToRequestStatus: {},\n identifierNames: {},\n attributeNames: {},\n regionToCountrySubDivision: {},\n regionToCountry: {},\n });\n\n // Create a new state file to store the requests from this run\n const requestCacheFile = join(\n requestReceiptFolder,\n `tr-request-upload-${new Date().toISOString()}-${file\n .split('/')\n .pop()}`.replace('.csv', '.json'),\n );\n const requestState = new PersistedState(\n requestCacheFile,\n CachedRequestState,\n {\n successfulRequests: [],\n duplicateRequests: [],\n failingRequests: [],\n },\n );\n\n // Create sombra instance to communicate with\n const sombra = await createSombraGotInstance(transcendUrl, auth, sombraAuth);\n\n // Read in the list of integration requests\n const requestsList = readCsv(file, t.record(t.string, t.string));\n const columnNames = uniq(requestsList.map((x) => Object.keys(x)).flat());\n\n // Log out an example request\n if (requestsList.length === 0) {\n throw new Error(\n 'No Requests found in list! Ensure the first row of the CSV is a header and the rest are requests.',\n );\n }\n if (debug) {\n const firstRequest = requestsList[0];\n logger.info(\n colors.magenta(`First request: ${JSON.stringify(firstRequest, null, 2)}`),\n );\n }\n // Determine what rows in the CSV should be imported\n // Choose columns that contain metadata to filter the requests\n const filteredRequestList = skipFilterStep\n ? requestsList\n : await filterRows(requestsList);\n\n // Build a GraphQL client\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n // Grab the request attributes\n const requestAttributeKeys = await fetchAllRequestAttributeKeys(client);\n // Determine the columns that should be mapped\n const columnNameMap = await mapCsvColumnsToApi(columnNames, state);\n const identifierNameMap = await mapColumnsToIdentifiers(\n client,\n columnNames,\n state,\n );\n const attributeNameMap = await mapColumnsToAttributes(\n client,\n columnNames,\n state,\n requestAttributeKeys,\n );\n await mapRequestEnumValues(client, filteredRequestList, {\n state,\n columnNameMap,\n });\n\n // map the CSV to request input\n const requestInputs = mapCsvRowsToRequestInputs(filteredRequestList, state, {\n defaultPhoneCountryCode,\n columnNameMap,\n identifierNameMap,\n attributeNameMap,\n requestAttributeKeys,\n });\n\n // start the progress bar with a total value of 200 and start value of 0\n if (!debug) {\n progressBar.start(requestInputs.length, 0);\n }\n let total = 0;\n // Submit each request\n await map(\n requestInputs,\n async ([rawRow, requestInput], ind) => {\n // The identifier to log, only include personal data if debug mode is on\n const requestLogId = debug\n ? `email:${requestInput.email} | coreIdentifier:${requestInput.coreIdentifier}`\n : `row:${ind.toString()}`;\n\n if (debug) {\n logger.info(\n colors.magenta(\n `[${ind + 1}/${requestInputs.length}] Importing: ${JSON.stringify(\n requestInput,\n null,\n 2,\n )}`,\n ),\n );\n }\n\n // Skip on dry run\n if (dryRun) {\n logger.info(\n colors.magenta('Bailing out on dry run because dryRun is set'),\n );\n return;\n }\n\n try {\n // Make the GraphQL request to submit the privacy request\n const requestResponse = await submitPrivacyRequest(\n sombra,\n requestInput,\n {\n details: `Uploaded by Transcend Cli: \"tr-request-upload\" : ${JSON.stringify(\n rawRow,\n null,\n 2,\n )}`,\n isTest,\n emailIsVerified,\n skipSendingReceipt,\n isSilent,\n additionalAttributes: parsedAttributes,\n },\n );\n\n // Log success\n if (debug) {\n logger.info(\n colors.green(\n `[${ind + 1}/${\n requestInputs.length\n }] Successfully submitted the test data subject request: \"${requestLogId}\"`,\n ),\n );\n logger.info(\n colors.green(\n `[${ind + 1}/${requestInputs.length}] View it at: \"${\n requestResponse.link\n }\"`,\n ),\n );\n }\n\n // Cache successful upload\n const successfulRequests = requestState.getValue('successfulRequests');\n successfulRequests.push({\n id: requestResponse.id,\n link: requestResponse.link,\n rowIndex: ind,\n coreIdentifier: requestResponse.coreIdentifier,\n attemptedAt: new Date().toISOString(),\n });\n await requestState.setValue(successfulRequests, 'successfulRequests');\n } catch (err) {\n const msg = `${err.message} - ${JSON.stringify(\n err.response?.body,\n null,\n 2,\n )}`;\n const clientError = extractClientError(msg);\n\n if (\n clientError === 'Client error: You have already made this request.'\n ) {\n if (debug) {\n logger.info(\n colors.yellow(\n `[${ind + 1}/${\n requestInputs.length\n }] Skipping request as it is a duplicate`,\n ),\n );\n }\n const duplicateRequests = requestState.getValue('duplicateRequests');\n duplicateRequests.push({\n coreIdentifier: requestInput.coreIdentifier,\n rowIndex: ind,\n attemptedAt: new Date().toISOString(),\n });\n await requestState.setValue(duplicateRequests, 'duplicateRequests');\n } else {\n const failingRequests = requestState.getValue('failingRequests');\n failingRequests.push({\n ...requestInput,\n rowIndex: ind,\n error: clientError || msg,\n attemptedAt: new Date().toISOString(),\n });\n await requestState.setValue(failingRequests, 'failingRequests');\n if (debug) {\n logger.error(colors.red(clientError || msg));\n logger.error(\n colors.red(\n `[${ind + 1}/${\n requestInputs.length\n }] Failed to submit request for: \"${requestLogId}\"`,\n ),\n );\n }\n }\n }\n\n total += 1;\n if (!debug) {\n progressBar.update(total);\n }\n },\n {\n concurrency,\n },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n // Log completion time\n logger.info(\n colors.green(`Completed upload in \"${totalTime / 1000}\" seconds.`),\n );\n\n // Log duplicates\n if (requestState.getValue('duplicateRequests').length > 0) {\n logger.info(\n colors.yellow(\n `Encountered \"${\n requestState.getValue('duplicateRequests').length\n }\" duplicate requests. ` +\n `See \"${requestCacheFile}\" to review the core identifiers for these requests.`,\n ),\n );\n }\n\n // Log errors\n if (requestState.getValue('failingRequests').length > 0) {\n logger.error(\n colors.red(\n `Encountered \"${\n requestState.getValue('failingRequests').length\n }\" errors. ` +\n `See \"${requestCacheFile}\" to review the error messages and inputs.`,\n ),\n );\n process.exit(1);\n }\n}\n/* eslint-enable max-lines */\n","import * as t from 'io-ts';\nimport { groupBy } from 'lodash-es';\nimport { apply, decodeCodec } from '@transcend-io/type-utils';\nimport { IdentifierType } from '@transcend-io/privacy-types';\nimport type { Got } from 'got';\nimport { PrivacyRequest, RequestIdentifier } from '../graphql';\nimport { IDENTIFIER_BLOCK_LIST } from './constants';\nimport { PrivacyRequestResponse } from './submitPrivacyRequest';\n\n/**\n * Restart a privacy request to the Transcend API\n *\n * @param sombra - Sombra instance configured to make requests\n * @param request - Request to restart\n * @param input - Request input\n * @returns Successfully submitted request\n */\nexport async function restartPrivacyRequest(\n sombra: Got,\n request: PrivacyRequest,\n {\n sendEmailReceipt = false,\n skipWaitingPeriod = false,\n emailIsVerified = true,\n requestIdentifiers = [],\n }: {\n /** List of request identifiers to include */\n requestIdentifiers?: RequestIdentifier[];\n /** When true, send an email receipt to data subject */\n sendEmailReceipt?: boolean;\n /** Whether the email is verified */\n emailIsVerified?: boolean;\n /** Whether to skip waiting period */\n skipWaitingPeriod?: boolean;\n } = {},\n): Promise<PrivacyRequestResponse> {\n // Make the GraphQL request\n const response = await sombra\n .post('v1/data-subject-request', {\n json: {\n type: request.type,\n subject: {\n coreIdentifier: request.coreIdentifier,\n email: request.email,\n emailIsVerified,\n ...(requestIdentifiers.length > 0\n ? {\n attestedExtraIdentifiers: apply(\n groupBy(\n requestIdentifiers\n .filter(\n (ri) =>\n // these are already submitted above\n !(\n ri.name === 'email' && ri.value === request.email\n ) && !IDENTIFIER_BLOCK_LIST.includes(ri.name),\n )\n .map((ri) => ({\n ...ri,\n type: Object.values(IdentifierType).includes(\n ri.name as any, // eslint-disable-line @typescript-eslint/no-explicit-any\n )\n ? ri.name\n : IdentifierType.Custom,\n })),\n 'type',\n ),\n (values, type) =>\n values.map(({ name, value }) => ({\n ...(type === IdentifierType.Custom ? { name } : {}),\n value,\n })),\n ),\n }\n : {}),\n },\n requestId: request.id,\n subjectType: request.subjectType,\n isSilent: request.isSilent,\n isTest: request.isTest,\n locale: request.locale,\n skipWaitingPeriod,\n createdAt: request.createdAt,\n details: `Restarted by Transcend cli: \"tr-request-restart\" - ${request.details}`,\n skipSendingReceipt: !sendEmailReceipt,\n },\n })\n .json();\n\n const { request: requestResponse } = decodeCodec(\n t.type({\n request: PrivacyRequestResponse,\n }),\n response,\n );\n return requestResponse;\n}\n","import { PersistedState } from '@transcend-io/persisted-state';\nimport { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport { map } from '@/lib/bluebird-replace';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\nimport * as t from 'io-ts';\nimport { difference } from 'lodash-es';\nimport { join } from 'path';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\nimport {\n buildTranscendGraphQLClient,\n createSombraGotInstance,\n fetchAllRequestIdentifiers,\n fetchAllRequests,\n} from '../graphql';\nimport { logger } from '../../logger';\nimport { SuccessfulRequest } from './constants';\nimport { extractClientError } from './extractClientError';\nimport { restartPrivacyRequest } from './restartPrivacyRequest';\n\n/** Minimal state we need to keep a list of requests */\nconst ErrorRequest = t.intersection([\n SuccessfulRequest,\n t.type({\n error: t.string,\n }),\n]);\n\n/** Type override */\ntype ErrorRequest = t.TypeOf<typeof ErrorRequest>;\n\n/** Persist this data between runs of the script */\nconst CachedRequestState = t.type({\n restartedRequests: t.array(SuccessfulRequest),\n failingRequests: t.array(ErrorRequest),\n});\n\n/**\n * Upload a set of privacy requests from CSV\n *\n * @param options - Options\n */\nexport async function bulkRestartRequests({\n requestReceiptFolder,\n auth,\n sombraAuth,\n requestActions,\n requestStatuses,\n createdAtBefore,\n createdAtAfter,\n transcendUrl = DEFAULT_TRANSCEND_API,\n requestIds = [],\n createdAt = new Date(),\n silentModeBefore,\n sendEmailReceipt = false,\n emailIsVerified = true,\n copyIdentifiers = false,\n skipWaitingPeriod = false,\n concurrency = 20,\n}: {\n /** Actions to filter for */\n requestActions: RequestAction[];\n /** Statues to filter for */\n requestStatuses: RequestStatus[];\n /** File where request receipts are stored */\n requestReceiptFolder: string;\n /** Transcend API key authentication */\n auth: string;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** Request IDs to filter for */\n requestIds?: string[];\n /** Whether to re-verify the email when restarting the request */\n emailIsVerified?: boolean;\n /** Filter for requests that were submitted before this date */\n createdAt?: Date;\n /** Requests that have been open for this length of time should be marked as silent mode */\n silentModeBefore?: Date;\n /** Send an email receipt to the restarted requests */\n sendEmailReceipt?: boolean;\n /** Copy over all identifiers rather than restarting the request only with the core identifier */\n copyIdentifiers?: boolean;\n /** Skip the waiting period when restarting requests */\n skipWaitingPeriod?: boolean;\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Concurrency to upload requests at */\n concurrency?: number;\n}): Promise<void> {\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Create a new state file to store the requests from this run\n const cacheFile = join(\n requestReceiptFolder,\n `tr-request-restart-${new Date().toISOString()}`,\n );\n const state = new PersistedState(cacheFile, CachedRequestState, {\n restartedRequests: [],\n failingRequests: [],\n });\n\n // Create sombra instance to communicate with\n const sombra = await createSombraGotInstance(transcendUrl, auth, sombraAuth);\n\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses: requestStatuses,\n createdAtBefore,\n createdAtAfter,\n });\n const requests = allRequests.filter(\n (request) => new Date(request.createdAt) < createdAt,\n );\n logger.info(`Found ${requests.length} requests to process`);\n\n if (copyIdentifiers) {\n logger.info('copyIdentifiers detected - All Identifiers will be copied.');\n }\n if (sendEmailReceipt) {\n logger.info('sendEmailReceipt detected - Email receipts will be sent.');\n }\n if (skipWaitingPeriod) {\n logger.info('skipWaitingPeriod detected - Waiting period will be skipped.');\n }\n\n // Validate request IDs\n if (requestIds.length > 0 && requestIds.length !== requests.length) {\n const missingRequests = difference(\n requestIds,\n requests.map(({ id }) => id),\n );\n if (missingRequests.length > 0) {\n logger.error(\n colors.red(\n `Failed to find the following requests by ID: ${missingRequests.join(\n ',',\n )}.`,\n ),\n );\n process.exit(1);\n }\n }\n\n // Map over the requests\n let total = 0;\n progressBar.start(requests.length, 0);\n await map(\n requests,\n async (request, ind) => {\n try {\n // Pull the request identifiers\n const requestIdentifiers = copyIdentifiers\n ? await fetchAllRequestIdentifiers(client, sombra, {\n requestId: request.id,\n })\n : [];\n\n // Make the GraphQL request to restart the request\n const requestResponse = await restartPrivacyRequest(\n sombra,\n {\n ...request,\n // override silent mode\n isSilent:\n !!silentModeBefore &&\n new Date(request.createdAt) < silentModeBefore\n ? true\n : request.isSilent,\n },\n {\n requestIdentifiers,\n skipWaitingPeriod,\n sendEmailReceipt,\n emailIsVerified,\n },\n );\n\n // Cache successful upload\n const restartedRequests = state.getValue('restartedRequests');\n restartedRequests.push({\n id: requestResponse.id,\n link: requestResponse.link,\n rowIndex: ind,\n coreIdentifier: requestResponse.coreIdentifier,\n attemptedAt: new Date().toISOString(),\n });\n await state.setValue(restartedRequests, 'restartedRequests');\n } catch (err) {\n const msg = `${err.message} - ${JSON.stringify(\n err.response?.body,\n null,\n 2,\n )}`;\n const clientError = extractClientError(msg);\n\n const failingRequests = state.getValue('failingRequests');\n failingRequests.push({\n id: request.id,\n link: request.link,\n rowIndex: ind,\n coreIdentifier: request.coreIdentifier,\n attemptedAt: new Date().toISOString(),\n error: clientError || msg,\n });\n await state.setValue(failingRequests, 'failingRequests');\n }\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n // Log completion time\n logger.info(\n colors.green(\n `Completed restarting of requests in \"${totalTime / 1000}\" seconds.`,\n ),\n );\n\n // Log errors\n if (state.getValue('failingRequests').length > 0) {\n logger.error(\n colors.red(\n `Encountered \"${state.getValue('failingRequests').length}\" errors. ` +\n `See \"${cacheFile}\" to review the error messages and inputs.`,\n ),\n );\n process.exit(1);\n }\n}\n","import { mapSeries, map } from '@/lib/bluebird-replace';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport {\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n fetchAllRequestEnrichers,\n fetchAllRequests,\n SKIP_REQUEST_ENRICHER,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport {\n RequestEnricherStatus,\n RequestStatus,\n} from '@transcend-io/privacy-types';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Given an enricher ID, mark all open request enrichers as skipped\n *\n * @param options - Options\n * @returns Number of items skipped\n */\nexport async function skipPreflightJobs({\n enricherIds,\n auth,\n concurrency = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** Transcend API key authentication */\n auth: string;\n /** Enricher IDs to pull down jobs for */\n enricherIds: string[];\n /** Upload concurrency */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Request statuses to mark as completed */\n requestStatuses?: RequestStatus[];\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n\n // fetch all RequestDataSilos that are open\n const requests = await fetchAllRequests(client, {\n statuses: [RequestStatus.Enriching],\n });\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Processing enricher: \"${enricherIds.join(',')}\" fetched \"${\n requests.length\n }\" in enriching status.`,\n ),\n );\n\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n let total = 0;\n progressBar.start(requests.length, 0);\n let totalSkipped = 0;\n await map(\n requests,\n async (request) => {\n // FIXME dont pull all in\n const requestEnrichers = await fetchAllRequestEnrichers(client, {\n requestId: request.id,\n });\n const requestEnrichersFiltered = requestEnrichers.filter(\n (enricher) =>\n enricherIds.includes(enricher.enricher.id) &&\n ![\n RequestEnricherStatus.Resolved,\n RequestEnricherStatus.Skipped,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ].includes(enricher.status as any),\n );\n\n // FIXME\n if (requestEnrichersFiltered.length > 0) {\n await mapSeries(requestEnrichersFiltered, async (requestEnricher) => {\n try {\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, SKIP_REQUEST_ENRICHER, {\n requestEnricherId: requestEnricher.id,\n });\n totalSkipped += 1;\n } catch (err) {\n if (\n !err.message.includes(\n 'Client error: Cannot skip Request enricher because it has already completed',\n )\n ) {\n throw err;\n }\n }\n });\n }\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully skipped \"${totalSkipped}\" for \"${\n requests.length\n }\" requests in \"${totalTime / 1000}\" seconds!`,\n ),\n );\n return requests.length;\n}\n","import {\n RequestAction,\n RequestEnricherStatus,\n RequestStatus,\n} from '@transcend-io/privacy-types';\nimport { map } from '@/lib/bluebird-replace';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\nimport { difference } from 'lodash-es';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\nimport {\n buildTranscendGraphQLClient,\n fetchAllRequestEnrichers,\n fetchAllRequests,\n retryRequestEnricher,\n} from '../graphql';\nimport { logger } from '../../logger';\n\n/**\n * Restart a bunch of request enrichers\n *\n * @param options - Options\n */\nexport async function bulkRetryEnrichers({\n auth,\n requestActions = [],\n createdAtBefore,\n createdAtAfter,\n transcendUrl = DEFAULT_TRANSCEND_API,\n requestEnricherStatuses = Object.values(RequestEnricherStatus),\n requestIds = [],\n enricherId,\n concurrency = 20,\n}: {\n /** Actions to filter for */\n requestActions?: RequestAction[];\n /** Request enricher statuses to restart - defaults to all statuses */\n requestEnricherStatuses?: RequestEnricherStatus[];\n /** Transcend API key authentication */\n auth: string;\n /** The ID of the enricher to restart */\n enricherId: string;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Request IDs to filter for */\n requestIds?: string[];\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Concurrency to upload requests at */\n concurrency?: number;\n}): Promise<void> {\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n logger.info(colors.magenta('Fetching requests to restart...'));\n\n const requests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses: [RequestStatus.Enriching],\n createdAtBefore,\n createdAtAfter,\n requestIds,\n });\n\n let totalRestarted = 0;\n\n // Validate request IDs\n if (requestIds.length > 0 && requestIds.length !== requests.length) {\n const missingRequests = difference(\n requestIds,\n requests.map(({ id }) => id),\n );\n if (missingRequests.length > 0) {\n logger.error(\n colors.red(\n `Failed to find the following requests by ID: ${missingRequests.join(\n ',',\n )}.`,\n ),\n );\n process.exit(1);\n }\n }\n\n // Map over the requests\n let total = 0;\n progressBar.start(requests.length, 0);\n await map(\n requests,\n async (request) => {\n // Pull the request identifiers\n const requestEnrichers = await fetchAllRequestEnrichers(client, {\n requestId: request.id,\n });\n const requestEnrichersToRestart = requestEnrichers.filter(\n (requestEnricher) =>\n requestEnricher.enricher.id === enricherId &&\n requestEnricherStatuses.includes(requestEnricher.status),\n );\n await map(requestEnrichersToRestart, async (requestEnricher) => {\n await retryRequestEnricher(client, requestEnricher.id);\n totalRestarted += 1;\n });\n\n // Cache successful upload\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n // Log completion time\n logger.info(\n colors.green(\n `Completed restarting of ${\n requests.length\n } requests and ${totalRestarted} enrichers in \"${\n totalTime / 1000\n }\" seconds.`,\n ),\n );\n}\n","import { map } from '@/lib/bluebird-replace';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport {\n RETRY_REQUEST_DATA_SILO,\n fetchRequestDataSilo,\n fetchAllRequests,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Retry a set of RequestDataSilos\n *\n * @param options - Options\n * @returns Number of items marked as completed\n */\nexport async function retryRequestDataSilos({\n requestActions,\n dataSiloId,\n auth,\n concurrency = 20,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** Transcend API key authentication */\n auth: string;\n /** Data Silo ID to pull down jobs for */\n dataSiloId: string;\n /** Concurrency to upload requests in parallel */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses: [RequestStatus.Compiling, RequestStatus.Approving],\n });\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Retrying requests for Data Silo: \"${dataSiloId}\", restarting \"${allRequests.length}\" requests.`,\n ),\n );\n\n let total = 0;\n let skipped = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToRestart) => {\n try {\n const requestDataSilo = await fetchRequestDataSilo(client, {\n requestId: requestToRestart.id,\n dataSiloId,\n });\n\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, RETRY_REQUEST_DATA_SILO, {\n requestDataSiloId: requestDataSilo.id,\n });\n } catch (err) {\n // some requests may not have this data silo connected\n if (!err.message.includes('Failed to find RequestDataSilo')) {\n throw err;\n }\n skipped += 1;\n }\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully notified Transcend in \"${\n totalTime / 1000\n }\" seconds for ${total} requests, ${skipped} requests were skipped because data silo was not attached to the request!`,\n ),\n );\n return allRequests.length;\n}\n","import { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport { map } from '@/lib/bluebird-replace';\nimport colors from 'colors';\nimport { groupBy } from 'lodash-es';\n\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\nimport {\n PrivacyRequest,\n RequestIdentifier,\n buildTranscendGraphQLClient,\n createSombraGotInstance,\n fetchAllRequestIdentifiers,\n fetchAllRequests,\n} from '../graphql';\nimport { logger } from '../../logger';\n\nexport interface ExportedPrivacyRequest extends PrivacyRequest {\n /** Request identifiers */\n requestIdentifiers: RequestIdentifier[];\n}\n\n/**\n * Pull down a list of privacy requests\n *\n * @param options - Options\n */\nexport async function pullPrivacyRequests({\n auth,\n sombraAuth,\n actions = [],\n statuses = [],\n identifierSearch,\n pageLimit = 100,\n transcendUrl = DEFAULT_TRANSCEND_API,\n createdAtBefore,\n createdAtAfter,\n isTest,\n}: {\n /** Transcend API key authentication */\n auth: string;\n /** Search for a specific identifier */\n identifierSearch?: string;\n /** Sombra API key authentication */\n sombraAuth?: string;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Statuses to filter on */\n statuses?: RequestStatus[];\n /** The request action to fetch */\n actions?: RequestAction[];\n /** Page limit when fetching requests */\n pageLimit?: number;\n /** Filter for requests created before this date */\n createdAtBefore?: Date;\n /** Filter for requests created after this date */\n createdAtAfter?: Date;\n /** Return test requests */\n isTest?: boolean;\n}): Promise<{\n /** All request information with attached identifiers */\n requestsWithRequestIdentifiers: ExportedPrivacyRequest[];\n /** Requests that are formatted for CSV */\n requestsFormattedForCsv: {\n [k in string]: string | null | number | boolean;\n }[];\n}> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n const sombra = await createSombraGotInstance(transcendUrl, auth, sombraAuth);\n\n // Log date range\n let dateRange = '';\n if (createdAtBefore) {\n dateRange += ` before ${createdAtBefore.toISOString()}`;\n }\n if (createdAtAfter) {\n dateRange += `${\n dateRange ? ', and' : ''\n } after ${createdAtAfter.toISOString()}`;\n }\n\n // Log out\n logger.info(\n colors.magenta(\n `${\n actions.length > 0\n ? `Pulling requests of type \"${actions.join('\" , \"')}\"`\n : 'Pulling all requests'\n }${dateRange}`,\n ),\n );\n\n // fetch the requests\n const requests = await fetchAllRequests(client, {\n actions,\n text: identifierSearch,\n statuses,\n createdAtBefore,\n createdAtAfter,\n isTest,\n });\n\n // Fetch the request identifiers for those requests\n const requestsWithRequestIdentifiers = await map(\n requests,\n async (request) => {\n const requestIdentifiers = await fetchAllRequestIdentifiers(\n client,\n sombra,\n {\n requestId: request.id,\n },\n );\n return {\n ...request,\n requestIdentifiers,\n };\n },\n {\n concurrency: pageLimit,\n },\n );\n\n logger.info(\n colors.magenta(`Pulled ${requestsWithRequestIdentifiers.length} requests`),\n );\n\n // Write out to CSV\n const data = requestsWithRequestIdentifiers.map(\n ({\n attributeValues,\n requestIdentifiers,\n id,\n email,\n type,\n status,\n subjectType,\n details,\n createdAt,\n country,\n locale,\n origin,\n countrySubDivision,\n isSilent,\n isTest,\n coreIdentifier,\n ...request\n }) => ({\n 'Request ID': id,\n 'Created At': createdAt,\n Email: email,\n 'Core Identifier': coreIdentifier,\n 'Request Type': type,\n 'Data Subject Type': subjectType,\n Status: status,\n Country: country,\n 'Country Sub Division': countrySubDivision,\n Details: details,\n Origin: origin,\n 'Silent Mode': isSilent,\n 'Is Test Request': isTest,\n Language: locale,\n ...request,\n ...Object.entries(groupBy(attributeValues, 'attributeKey.name')).reduce(\n (acc, [name, values]) =>\n Object.assign(acc, {\n [name]: values.map(({ name }) => name).join(','),\n }),\n {},\n ),\n ...Object.entries(groupBy(requestIdentifiers, 'name')).reduce(\n (acc, [name, values]) =>\n Object.assign(acc, {\n [name]: values.map(({ value }) => value).join(','),\n }),\n {},\n ),\n }),\n );\n\n return { requestsWithRequestIdentifiers, requestsFormattedForCsv: data };\n}\n","import { map } from '@/lib/bluebird-replace';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport {\n CHANGE_REQUEST_DATA_SILO_STATUS,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n fetchRequestDataSilos,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { RequestStatus } from '@transcend-io/privacy-types';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Given a data silo ID, mark all open request data silos as skipped\n *\n * @param options - Options\n * @returns Number of items skipped\n */\nexport async function skipRequestDataSilos({\n dataSiloId,\n auth,\n concurrency = 100,\n status = 'SKIPPED',\n transcendUrl = DEFAULT_TRANSCEND_API,\n requestStatuses = [RequestStatus.Compiling, RequestStatus.Secondary],\n}: {\n /** Transcend API key authentication */\n auth: string;\n /** Data Silo ID to pull down jobs for */\n dataSiloId: string;\n /** Status to set */\n status?: 'SKIPPED' | 'RESOLVED';\n /** Upload concurrency */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n /** Request statuses to mark as completed */\n requestStatuses?: RequestStatus[];\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n\n // fetch all RequestDataSilos that are open\n const requestDataSilos = await fetchRequestDataSilos(client, {\n dataSiloId,\n requestStatuses,\n });\n\n // Notify Transcend\n logger.info(\n colors.magenta(\n `Processing data silo: \"${dataSiloId}\" marking \"${requestDataSilos.length}\" requests as skipped.`,\n ),\n );\n\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n let total = 0;\n progressBar.start(requestDataSilos.length, 0);\n await map(\n requestDataSilos,\n async (requestDataSilo) => {\n try {\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, CHANGE_REQUEST_DATA_SILO_STATUS, {\n requestDataSiloId: requestDataSilo.id,\n status,\n });\n } catch (err) {\n if (!err.message.includes('Client error: Request must be active:')) {\n throw err;\n }\n }\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully skipped \"${requestDataSilos.length}\" requests in \"${\n totalTime / 1000\n }\" seconds!`,\n ),\n );\n return requestDataSilos.length;\n}\n","import { map } from '@/lib/bluebird-replace';\nimport colors from 'colors';\nimport { logger } from '../../logger';\nimport { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\nimport {\n REMOVE_REQUEST_IDENTIFIERS,\n fetchAllRequests,\n fetchAllRequestIdentifierMetadata,\n makeGraphQLRequest,\n buildTranscendGraphQLClient,\n} from '../graphql';\nimport cliProgress from 'cli-progress';\nimport { DEFAULT_TRANSCEND_API } from '../../constants';\n\n/**\n * Remove a set of unverified request identifier\n *\n * @param options - Options\n * @returns Number of items marked as completed\n */\nexport async function removeUnverifiedRequestIdentifiers({\n requestActions,\n identifierNames,\n auth,\n concurrency = 20,\n transcendUrl = DEFAULT_TRANSCEND_API,\n}: {\n /** The request actions that should be restarted */\n requestActions: RequestAction[];\n /** Transcend API key authentication */\n auth: string;\n /** The set of identifier names to remove */\n identifierNames: string[];\n /** Concurrency to upload requests in parallel */\n concurrency?: number;\n /** API URL for Transcend backend */\n transcendUrl?: string;\n}): Promise<number> {\n // Find all requests made before createdAt that are in a removing data state\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Time duration\n const t0 = new Date().getTime();\n // create a new progress bar instance and use shades_classic theme\n const progressBar = new cliProgress.SingleBar(\n {},\n cliProgress.Presets.shades_classic,\n );\n\n // Pull in the requests\n const allRequests = await fetchAllRequests(client, {\n actions: requestActions,\n statuses: [RequestStatus.Enriching],\n });\n\n // Notify Transcend\n logger.info(colors.magenta('Fetched requests in preflight/enriching state.'));\n\n let total = 0;\n let processed = 0;\n progressBar.start(allRequests.length, 0);\n await map(\n allRequests,\n async (requestToRestart) => {\n const requestIdentifiers = await fetchAllRequestIdentifierMetadata(\n client,\n { requestId: requestToRestart.id },\n );\n const clearOut = requestIdentifiers\n .filter(\n ({ isVerifiedAtLeastOnce, name }) =>\n isVerifiedAtLeastOnce === false && identifierNames.includes(name),\n )\n .map(({ id }) => id);\n\n if (clearOut.length > 0) {\n await makeGraphQLRequest<{\n /** Whether we successfully uploaded the results */\n success: boolean;\n }>(client, REMOVE_REQUEST_IDENTIFIERS, {\n input: {\n requestId: requestToRestart.id,\n requestIdentifierIds: clearOut,\n },\n });\n processed += clearOut.length;\n }\n\n total += 1;\n progressBar.update(total);\n },\n { concurrency },\n );\n\n progressBar.stop();\n const t1 = new Date().getTime();\n const totalTime = t1 - t0;\n\n logger.info(\n colors.green(\n `Successfully cleared out unverified identifiers \"${\n totalTime / 1000\n }\" seconds for ${total} requests, ${processed} identifiers were cleared out!`,\n ),\n );\n return allRequests.length;\n}\n"],"mappings":"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","names":["applyEnum","valuesOf","LanguageKey","CompletedRequestStatus","RequestAction","IsoCountryCode","IsoCountrySubdivisionCode","t","NONE","BULK_APPLY","BLANK","IDENTIFIER_BLOCK_LIST","ColumnName","IS_REQUIRED","CAN_APPLY_IN_BULK","CachedFileState","SuccessfulRequest","CachedRequestState","inquirer","fuzzysearch","fuzzySearch","word1","word2","fuzzyMatchColumns","allColumnNames","fuzzyMapName","isRequired","canApplyAll","matchingColumnNames","x","inquirer","NONE","BULK_APPLY","inquirer","autoCompletePrompt","apply","mapEnumValues","csvInputs","expectedOutputs","cache","inquirer","autoCompletePrompt","inputs","item","value","result","x","fuzzySearch","answersSoFar","input","apply","r","splitCsvToList","value","x","colors","t","ParsedAttributeInput","parseAttributesFromString","attributes","parsedAttributes","attribute","attributeKey","attributeValuesRaw","attributeValues","logger","colors","parse","readFileSync","t","decodeCodec","readCsv","pathToFile","codec","options","fileContent","datum","acc","key","value","uniq","getUniqueValuesForColumn","rows","columnName","row","inquirer","colors","uniq","filterRows","rows","columnNames","uniq","x","filteredRows","keepFiltering","filterColumnName","inquirer","NONE","options","getUniqueValuesForColumn","valuesToKeep","request","logger","colors","colors","RequestStatus","cliProgress","markSilentPrivacyRequests","requestActions","auth","requestIds","statuses","RequestStatus","createdAtAfter","createdAtBefore","concurrency","transcendUrl","DEFAULT_TRANSCEND_API","client","buildTranscendGraphQLClient","t0","progressBar","cliProgress","allRequests","fetchAllRequests","logger","colors","total","map","requestToMarkSilent","makeGraphQLRequest","UPDATE_PRIVACY_REQUEST","totalTime","getValues","getEntries","inquirer","startCase","mapCsvColumnsToApi","columnNames","state","columnQuestions","getValues","ColumnName","name","columnNameMap","inquirer","field","startCase","matches","fuzzyMatchColumns","IS_REQUIRED","CAN_APPLY_IN_BULK","getEntries","k","v","colors","CompletedRequestStatus","RequestAction","IsoCountryCode","IsoCountrySubdivisionCode","LanguageKey","mapRequestEnumValues","client","requests","state","columnNameMap","getMappedName","attribute","internalSubjects","makeGraphQLRequest","DATA_SUBJECTS","logger","colors","requestTypeToRequestAction","mapEnumValues","getUniqueValuesForColumn","RequestAction","subjectTypeToSubjectName","type","languageToLocale","LanguageKey","requestStatusColumn","statusToRequestStatus","NONE","CompletedRequestStatus","countryColumn","regionToCountry","IsoCountryCode","countrySubDivisionColumn","regionToCountrySubDivision","IsoCountrySubdivisionCode","LanguageKey","DateFromISOString","t","NORMALIZE_PHONE_NUMBER","CompletedRequestStatus","RequestAction","IdentifierType","IsoCountryCode","IsoCountrySubdivisionCode","valuesOf","AttestedExtraIdentifiers","PrivacyRequestInput","valuesOf","RequestAction","IsoCountryCode","IsoCountrySubdivisionCode","ParsedAttributeInput","CompletedRequestStatus","DateFromISOString","LanguageKey","normalizeIdentifierValue","identifierValue","identifierType","defaultPhoneCountryCode","IdentifierType","normalized","NORMALIZE_PHONE_NUMBER","mapCsvRowsToRequestInputs","requestInputs","state","columnNameMap","identifierNameMap","attributeNameMap","requestAttributeKeys","getMappedName","attribute","input","attestedExtraIdentifiers","columnName","NONE","identifierName","attributes","attributeName","attributeValueString","isMulti","attr","splitCsvToList","requestTypeColumn","dataSubjectTypeColumn","BULK_APPLY","BLANK","colors","cliProgress","t","decodeCodec","valuesOf","TableEncryptionType","IntlMessage","RequestFileMetadata","valuesOf","RequestFileMetadataResponse","getFileMetadataForPrivacyRequests","requests","sombra","concurrency","limit","logger","colors","t0","progressBar","cliProgress","total","results","map","requestToDownload","localResults","shouldContinue","offset","response","rawResponse","decodeCodec","err","totalTime","colors","streamPrivacyRequestFiles","fileMetadata","requestId","sombra","onFileDownloaded","concurrency","map","metadata","fileResponse","err","logger","colors","existsSync","mkdirSync","writeFileSync","dirname","join","colors","RequestAction","RequestStatus","cliProgress","downloadPrivacyRequestFiles","auth","folderPath","requestIds","createdAtBefore","sombraAuth","createdAtAfter","statuses","RequestStatus","concurrency","transcendUrl","DEFAULT_TRANSCEND_API","approveAfterDownload","client","buildTranscendGraphQLClient","sombra","createSombraGotInstance","existsSync","mkdirSync","allRequests","fetchAllRequests","RequestAction","requestFileMetadata","getFileMetadataForPrivacyRequests","t0","progressBar","cliProgress","total","totalApproved","map","request","metadata","requestFolder","join","streamPrivacyRequestFiles","fil","stream","filePath","folder","dirname","writeFileSync","makeGraphQLRequest","APPROVE_PRIVACY_REQUEST","totalTime","logger","colors","t","uniq","valuesOf","decodeCodec","IsoCountryCode","IsoCountrySubdivisionCode","RequestAction","RequestStatus","PrivacyRequestResponse","submitPrivacyRequest","sombra","input","details","isTest","emailIsVerified","skipSendingReceipt","isSilent","additionalAttributes","mergedAttributes","attribute","existing","attr","response","err","requestResponse","colors","RequestStatus","cliProgress","approvePrivacyRequests","requestActions","requestOrigins","auth","silentModeBefore","createdAtAfter","createdAtBefore","concurrency","transcendUrl","DEFAULT_TRANSCEND_API","client","buildTranscendGraphQLClient","t0","progressBar","cliProgress","allRequests","fetchAllRequests","RequestStatus","logger","colors","total","skipped","map","requestToApprove","makeGraphQLRequest","UPDATE_PRIVACY_REQUEST","APPROVE_PRIVACY_REQUEST","err","totalTime","colors","RequestAction","cliProgress","notifyPrivacyRequestsAdditionalTime","requestActions","RequestAction","auth","requestIds","createdAtBefore","days","daysLeft","createdAtAfter","emailTemplate","concurrency","transcendUrl","DEFAULT_TRANSCEND_API","client","buildTranscendGraphQLClient","t0","progressBar","cliProgress","exactTemplateMatch","fetchAllTemplates","template","allRequests","fetchAllRequests","request","logger","colors","total","map","requestToNotify","makeGraphQLRequest","NOTIFY_ADDITIONAL_TIME","totalTime","inquirer","mapColumnsToIdentifiers","client","columnNames","state","initializer","makeGraphQLRequest","INITIALIZER","columnQuestions","name","IDENTIFIER_BLOCK_LIST","identifierNameMap","inquirer","matches","fuzzyMatchColumns","k","v","colors","RequestStatus","cliProgress","cancelPrivacyRequests","requestActions","cancellationTitle","auth","requestIds","silentModeBefore","createdAtBefore","createdAtAfter","statuses","RequestStatus","concurrency","transcendUrl","DEFAULT_TRANSCEND_API","client","buildTranscendGraphQLClient","t0","progressBar","cliProgress","cancelationTemplate","exactTitleMatch","fetchAllTemplates","template","allRequests","fetchAllRequests","logger","colors","total","map","requestToCancel","makeGraphQLRequest","UPDATE_PRIVACY_REQUEST","CANCEL_PRIVACY_REQUEST","totalTime","inquirer","mapColumnsToAttributes","client","columnNames","state","requestAttributeKeys","columnQuestions","name","attributeNameMap","inquirer","matches","fuzzyMatchColumns","k","v","CLIENT_ERROR","extractClientError","err","colors","t","uniq","cliProgress","join","PersistedState","uploadPrivacyRequestsFromCsv","cacheFilepath","requestReceiptFolder","file","auth","sombraAuth","concurrency","defaultPhoneCountryCode","transcendUrl","DEFAULT_TRANSCEND_API","attributes","emailIsVerified","skipFilterStep","skipSendingReceipt","isTest","isSilent","debug","dryRun","t0","progressBar","cliProgress","parsedAttributes","parseAttributesFromString","state","PersistedState","CachedFileState","requestCacheFile","join","requestState","CachedRequestState","sombra","createSombraGotInstance","requestsList","readCsv","columnNames","uniq","x","firstRequest","logger","colors","filteredRequestList","filterRows","client","buildTranscendGraphQLClient","requestAttributeKeys","fetchAllRequestAttributeKeys","columnNameMap","mapCsvColumnsToApi","identifierNameMap","mapColumnsToIdentifiers","attributeNameMap","mapColumnsToAttributes","mapRequestEnumValues","requestInputs","mapCsvRowsToRequestInputs","total","map","rawRow","requestInput","ind","requestLogId","requestResponse","submitPrivacyRequest","successfulRequests","err","msg","clientError","extractClientError","duplicateRequests","failingRequests","totalTime","t","groupBy","apply","decodeCodec","IdentifierType","restartPrivacyRequest","sombra","request","sendEmailReceipt","skipWaitingPeriod","emailIsVerified","requestIdentifiers","response","apply","groupBy","ri","IDENTIFIER_BLOCK_LIST","IdentifierType","values","type","name","value","requestResponse","decodeCodec","PrivacyRequestResponse","PersistedState","cliProgress","colors","t","difference","join","ErrorRequest","SuccessfulRequest","CachedRequestState","bulkRestartRequests","requestReceiptFolder","auth","sombraAuth","requestActions","requestStatuses","createdAtBefore","createdAtAfter","transcendUrl","DEFAULT_TRANSCEND_API","requestIds","createdAt","silentModeBefore","sendEmailReceipt","emailIsVerified","copyIdentifiers","skipWaitingPeriod","concurrency","t0","progressBar","cliProgress","cacheFile","join","state","PersistedState","sombra","createSombraGotInstance","client","buildTranscendGraphQLClient","requests","fetchAllRequests","request","logger","missingRequests","difference","id","colors","total","map","ind","requestIdentifiers","fetchAllRequestIdentifiers","requestResponse","restartPrivacyRequest","restartedRequests","err","msg","clientError","extractClientError","failingRequests","totalTime","colors","cliProgress","RequestEnricherStatus","RequestStatus","skipPreflightJobs","enricherIds","auth","concurrency","transcendUrl","DEFAULT_TRANSCEND_API","client","buildTranscendGraphQLClient","t0","requests","fetchAllRequests","RequestStatus","logger","colors","progressBar","cliProgress","total","totalSkipped","map","request","requestEnrichersFiltered","fetchAllRequestEnrichers","enricher","RequestEnricherStatus","mapSeries","requestEnricher","makeGraphQLRequest","SKIP_REQUEST_ENRICHER","err","totalTime","RequestEnricherStatus","RequestStatus","cliProgress","colors","difference","bulkRetryEnrichers","auth","requestActions","createdAtBefore","createdAtAfter","transcendUrl","DEFAULT_TRANSCEND_API","requestEnricherStatuses","RequestEnricherStatus","requestIds","enricherId","concurrency","t0","progressBar","cliProgress","client","buildTranscendGraphQLClient","logger","colors","requests","fetchAllRequests","RequestStatus","totalRestarted","missingRequests","difference","id","total","map","request","requestEnrichersToRestart","fetchAllRequestEnrichers","requestEnricher","retryRequestEnricher","totalTime","colors","RequestStatus","cliProgress","retryRequestDataSilos","requestActions","dataSiloId","auth","concurrency","transcendUrl","DEFAULT_TRANSCEND_API","client","buildTranscendGraphQLClient","t0","progressBar","cliProgress","allRequests","fetchAllRequests","RequestStatus","logger","colors","total","skipped","map","requestToRestart","requestDataSilo","fetchRequestDataSilo","makeGraphQLRequest","RETRY_REQUEST_DATA_SILO","err","totalTime","colors","groupBy","pullPrivacyRequests","auth","sombraAuth","actions","statuses","identifierSearch","pageLimit","transcendUrl","DEFAULT_TRANSCEND_API","createdAtBefore","createdAtAfter","isTest","client","buildTranscendGraphQLClient","sombra","createSombraGotInstance","dateRange","logger","colors","requests","fetchAllRequests","requestsWithRequestIdentifiers","map","request","requestIdentifiers","fetchAllRequestIdentifiers","data","attributeValues","id","email","type","status","subjectType","details","createdAt","country","locale","origin","countrySubDivision","isSilent","coreIdentifier","groupBy","acc","name","values","value","colors","cliProgress","RequestStatus","skipRequestDataSilos","dataSiloId","auth","concurrency","status","transcendUrl","DEFAULT_TRANSCEND_API","requestStatuses","RequestStatus","client","buildTranscendGraphQLClient","t0","requestDataSilos","fetchRequestDataSilos","logger","colors","progressBar","cliProgress","total","map","requestDataSilo","makeGraphQLRequest","CHANGE_REQUEST_DATA_SILO_STATUS","err","totalTime","colors","RequestStatus","cliProgress","removeUnverifiedRequestIdentifiers","requestActions","identifierNames","auth","concurrency","transcendUrl","DEFAULT_TRANSCEND_API","client","buildTranscendGraphQLClient","t0","progressBar","cliProgress","allRequests","fetchAllRequests","RequestStatus","logger","colors","total","processed","map","requestToRestart","clearOut","fetchAllRequestIdentifierMetadata","isVerifiedAtLeastOnce","name","id","makeGraphQLRequest","REMOVE_REQUEST_IDENTIFIERS","totalTime"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{b as a}from"./chunk-XNR74SBS.js";import"./chunk-WSDWILYI.js";import"./chunk-ZTD7APNF.js";import"./chunk-LAYHULHH.js";import"./chunk-347UQP43.js";import"./chunk-TDBKATQK.js";import"./chunk-43JWXG77.js";import"./chunk-L5ULN3IT.js";import"./chunk-SF46ZLPT.js";import"./chunk-ARVEJERC.js";async function n({auth:o,trackerStatus:t,file:r,classifyService:s,transcendUrl:e}){await a({auth:o,trackerStatus:t,file:r,classifyService:s,transcendUrl:e})}export{n as uploadDataFlowsFromCsv};
|
|
2
|
+
//# sourceMappingURL=impl-25VWUB6L.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/consent/upload-data-flows-from-csv/impl.ts"],"sourcesContent":["import type { LocalContext } from '@/context';\nimport { uploadDataFlowsFromCsv as uploadDataFlowsFromCsvHelper } from '@/lib/consent-manager';\nimport { ConsentTrackerStatus } from '@transcend-io/privacy-types';\n\ninterface UploadDataFlowsFromCsvCommandFlags {\n auth: string;\n trackerStatus: ConsentTrackerStatus;\n file: string;\n classifyService: boolean;\n transcendUrl: string;\n}\n\nexport async function uploadDataFlowsFromCsv(\n this: LocalContext,\n {\n auth,\n trackerStatus,\n file,\n classifyService,\n transcendUrl,\n }: UploadDataFlowsFromCsvCommandFlags,\n): Promise<void> {\n await uploadDataFlowsFromCsvHelper({\n auth,\n trackerStatus,\n file,\n classifyService,\n transcendUrl,\n });\n}\n"],"mappings":"oSAYA,eAAsBA,EAEpB,CACE,KAAAC,EACA,cAAAC,EACA,KAAAC,EACA,gBAAAC,EACA,aAAAC,CACF,EACe,CACf,MAAML,EAA6B,CACjC,KAAAC,EACA,cAAAC,EACA,KAAAC,EACA,gBAAAC,EACA,aAAAC,CACF,CAAC,CACH","names":["uploadDataFlowsFromCsv","auth","trackerStatus","file","classifyService","transcendUrl"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{e as l}from"./chunk-OEB7WG3G.js";import{h as R,i as b}from"./chunk-INLBXSQE.js";import{b as N}from"./chunk-MVDOKJ6J.js";import"./chunk-LAYHULHH.js";import"./chunk-347UQP43.js";import{a as P,be as m,pe as u}from"./chunk-TDBKATQK.js";import{a as o}from"./chunk-43JWXG77.js";import{c as f}from"./chunk-L5ULN3IT.js";import"./chunk-SF46ZLPT.js";import{d as E}from"./chunk-ARVEJERC.js";import n from"colors";import{join as k}from"path";import D from"fs";async function M({auth:x,resources:g=R,file:t,transcendUrl:p,dataSiloIds:d=[],integrationNames:T=[],trackerStatuses:y=b,pageSize:S,skipDatapoints:h,skipSubDatapoints:$,includeGuessedCategories:A,debug:a}){let i=await N(x),C=g.includes("all")?Object.values(E):g;if(typeof i=="string"){try{let r=u(p,i),e=await m(r,{dataSiloIds:d,integrationNames:T,resources:C,pageSize:S,debug:a,skipDatapoints:h,skipSubDatapoints:$,includeGuessedCategories:A,trackerStatuses:y});o.info(n.magenta(`Writing configuration to file "${t}"...`)),l(t,e)}catch(r){o.error(n.red(`An error occurred syncing the schema: ${a?r.stack:r.message}`)),process.exit(1)}o.info(n.green(`Successfully synced yaml file to disk at ${t}! View at ${f}`))}else{if(!D.lstatSync(t).isDirectory())throw new Error("File is expected to be a folder when passing in a list of API keys to pull from. e.g. --file=./working/");let r=[];await P(i,async(e,L)=>{let s=`[${L+1}/${i.length}][${e.organizationName}] `;o.info(n.magenta(`~~~
|
|
2
|
+
|
|
3
|
+
${s}Attempting to pull configuration...
|
|
4
|
+
|
|
5
|
+
~~~`));let _=u(p,e.apiKey);try{let c=await m(_,{dataSiloIds:d,integrationNames:T,resources:C,pageSize:S,debug:a,skipDatapoints:h,skipSubDatapoints:$,includeGuessedCategories:A,trackerStatuses:y}),w=k(t,`${e.organizationName}.yml`);o.info(n.magenta(`Writing configuration to file "${w}"...`)),l(w,c),o.info(n.green(`${s}Successfully pulled configuration!`))}catch(c){o.error(n.red(`${s}Failed to sync configuration. - ${c.message}`)),r.push(e.organizationName)}}),r.length>0&&(o.info(n.red(`Sync encountered errors for "${r.join(",")}". View output above for more information, or check out ${f}`)),process.exit(1))}}export{M as pull};
|
|
6
|
+
//# sourceMappingURL=impl-3M5R6G5M.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/inventory/pull/impl.ts"],"sourcesContent":["import { ConsentTrackerStatus } from '@transcend-io/privacy-types';\nimport type { LocalContext } from '@/context';\nimport { TranscendPullResource } from '@/enums';\nimport {\n DEFAULT_CONSENT_TRACKER_STATUSES,\n DEFAULT_TRANSCEND_PULL_RESOURCES,\n} from './command';\n\nimport { logger } from '@/logger';\nimport colors from 'colors';\nimport { mapSeries } from '@/lib/bluebird-replace';\nimport { join } from 'path';\nimport fs from 'fs';\nimport {\n buildTranscendGraphQLClient,\n pullTranscendConfiguration,\n} from '@/lib/graphql';\n\nimport { writeTranscendYaml } from '@/lib/readTranscendYaml';\nimport { ADMIN_DASH_INTEGRATIONS } from '@/constants';\nimport { validateTranscendAuth } from '@/lib/api-keys';\n\ninterface PullCommandFlags {\n auth: string;\n resources?: (TranscendPullResource | 'all')[];\n file: string;\n transcendUrl: string;\n dataSiloIds?: string[];\n integrationNames?: string[];\n trackerStatuses?: ConsentTrackerStatus[];\n pageSize: number;\n skipDatapoints: boolean;\n skipSubDatapoints: boolean;\n includeGuessedCategories: boolean;\n debug: boolean;\n}\n\nexport async function pull(\n this: LocalContext,\n {\n auth,\n resources = DEFAULT_TRANSCEND_PULL_RESOURCES,\n file,\n transcendUrl,\n dataSiloIds = [],\n integrationNames = [],\n trackerStatuses = DEFAULT_CONSENT_TRACKER_STATUSES,\n pageSize,\n skipDatapoints,\n skipSubDatapoints,\n includeGuessedCategories,\n debug,\n }: PullCommandFlags,\n): Promise<void> {\n // Parse authentication as API key or path to list of API keys\n const apiKeyOrList = await validateTranscendAuth(auth);\n\n const resourcesToPull: TranscendPullResource[] = resources.includes('all')\n ? Object.values(TranscendPullResource)\n : (resources as TranscendPullResource[]);\n\n // Sync to Disk\n if (typeof apiKeyOrList === 'string') {\n try {\n // Create a GraphQL client\n const client = buildTranscendGraphQLClient(transcendUrl, apiKeyOrList);\n\n const configuration = await pullTranscendConfiguration(client, {\n dataSiloIds,\n integrationNames,\n resources: resourcesToPull,\n pageSize,\n debug,\n skipDatapoints,\n skipSubDatapoints,\n includeGuessedCategories,\n trackerStatuses,\n });\n\n logger.info(colors.magenta(`Writing configuration to file \"${file}\"...`));\n writeTranscendYaml(file, configuration);\n } catch (err) {\n logger.error(\n colors.red(\n `An error occurred syncing the schema: ${\n debug ? err.stack : err.message\n }`,\n ),\n );\n process.exit(1);\n }\n\n // Indicate success\n logger.info(\n colors.green(\n `Successfully synced yaml file to disk at ${file}! View at ${ADMIN_DASH_INTEGRATIONS}`,\n ),\n );\n } else {\n if (!fs.lstatSync(file).isDirectory()) {\n throw new Error(\n 'File is expected to be a folder when passing in a list of API keys to pull from. e.g. --file=./working/',\n );\n }\n\n const encounteredErrors: string[] = [];\n await mapSeries(apiKeyOrList, async (apiKey, ind) => {\n const prefix = `[${ind + 1}/${apiKeyOrList.length}][${\n apiKey.organizationName\n }] `;\n logger.info(\n colors.magenta(\n `~~~\\n\\n${prefix}Attempting to pull configuration...\\n\\n~~~`,\n ),\n );\n\n // Create a GraphQL client\n const client = buildTranscendGraphQLClient(transcendUrl, apiKey.apiKey);\n\n try {\n const configuration = await pullTranscendConfiguration(client, {\n dataSiloIds,\n integrationNames,\n resources: resourcesToPull,\n pageSize,\n debug,\n skipDatapoints,\n skipSubDatapoints,\n includeGuessedCategories,\n trackerStatuses,\n });\n\n const filePath = join(file, `${apiKey.organizationName}.yml`);\n logger.info(\n colors.magenta(`Writing configuration to file \"${filePath}\"...`),\n );\n writeTranscendYaml(filePath, configuration);\n\n logger.info(\n colors.green(`${prefix}Successfully pulled configuration!`),\n );\n } catch (err) {\n logger.error(\n colors.red(`${prefix}Failed to sync configuration. - ${err.message}`),\n );\n encounteredErrors.push(apiKey.organizationName);\n }\n });\n\n if (encounteredErrors.length > 0) {\n logger.info(\n colors.red(\n `Sync encountered errors for \"${encounteredErrors.join(\n ',',\n )}\". View output above for more information, or check out ${ADMIN_DASH_INTEGRATIONS}`,\n ),\n );\n\n process.exit(1);\n }\n }\n}\n"],"mappings":"mYASA,OAAOA,MAAY,SAEnB,OAAS,QAAAC,MAAY,OACrB,OAAOC,MAAQ,KAyBf,eAAsBC,EAEpB,CACE,KAAAC,EACA,UAAAC,EAAYC,EACZ,KAAAC,EACA,aAAAC,EACA,YAAAC,EAAc,CAAC,EACf,iBAAAC,EAAmB,CAAC,EACpB,gBAAAC,EAAkBC,EAClB,SAAAC,EACA,eAAAC,EACA,kBAAAC,EACA,yBAAAC,EACA,MAAAC,CACF,EACe,CAEf,IAAMC,EAAe,MAAMC,EAAsBf,CAAI,EAE/CgB,EAA2Cf,EAAU,SAAS,KAAK,EACrE,OAAO,OAAOgB,CAAqB,EAClChB,EAGL,GAAI,OAAOa,GAAiB,SAAU,CACpC,GAAI,CAEF,IAAMI,EAASC,EAA4Bf,EAAcU,CAAY,EAE/DM,EAAgB,MAAMC,EAA2BH,EAAQ,CAC7D,YAAAb,EACA,iBAAAC,EACA,UAAWU,EACX,SAAAP,EACA,MAAAI,EACA,eAAAH,EACA,kBAAAC,EACA,yBAAAC,EACA,gBAAAL,CACF,CAAC,EAEDe,EAAO,KAAKC,EAAO,QAAQ,kCAAkCpB,CAAI,MAAM,CAAC,EACxEqB,EAAmBrB,EAAMiB,CAAa,CACxC,OAASK,EAAK,CACZH,EAAO,MACLC,EAAO,IACL,yCACEV,EAAQY,EAAI,MAAQA,EAAI,OAC1B,EACF,CACF,EACA,QAAQ,KAAK,CAAC,CAChB,CAGAH,EAAO,KACLC,EAAO,MACL,4CAA4CpB,CAAI,aAAauB,CAAuB,EACtF,CACF,CACF,KAAO,CACL,GAAI,CAACC,EAAG,UAAUxB,CAAI,EAAE,YAAY,EAClC,MAAM,IAAI,MACR,yGACF,EAGF,IAAMyB,EAA8B,CAAC,EACrC,MAAMC,EAAUf,EAAc,MAAOgB,EAAQC,IAAQ,CACnD,IAAMC,EAAS,IAAID,EAAM,CAAC,IAAIjB,EAAa,MAAM,KAC/CgB,EAAO,gBACT,KACAR,EAAO,KACLC,EAAO,QACL;AAAA;AAAA,EAAUS,CAAM;AAAA;AAAA,IAClB,CACF,EAGA,IAAMd,EAASC,EAA4Bf,EAAc0B,EAAO,MAAM,EAEtE,GAAI,CACF,IAAMV,EAAgB,MAAMC,EAA2BH,EAAQ,CAC7D,YAAAb,EACA,iBAAAC,EACA,UAAWU,EACX,SAAAP,EACA,MAAAI,EACA,eAAAH,EACA,kBAAAC,EACA,yBAAAC,EACA,gBAAAL,CACF,CAAC,EAEK0B,EAAWC,EAAK/B,EAAM,GAAG2B,EAAO,gBAAgB,MAAM,EAC5DR,EAAO,KACLC,EAAO,QAAQ,kCAAkCU,CAAQ,MAAM,CACjE,EACAT,EAAmBS,EAAUb,CAAa,EAE1CE,EAAO,KACLC,EAAO,MAAM,GAAGS,CAAM,oCAAoC,CAC5D,CACF,OAASP,EAAK,CACZH,EAAO,MACLC,EAAO,IAAI,GAAGS,CAAM,mCAAmCP,EAAI,OAAO,EAAE,CACtE,EACAG,EAAkB,KAAKE,EAAO,gBAAgB,CAChD,CACF,CAAC,EAEGF,EAAkB,OAAS,IAC7BN,EAAO,KACLC,EAAO,IACL,gCAAgCK,EAAkB,KAChD,GACF,CAAC,2DAA2DF,CAAuB,EACrF,CACF,EAEA,QAAQ,KAAK,CAAC,EAElB,CACF","names":["colors","join","fs","pull","auth","resources","DEFAULT_TRANSCEND_PULL_RESOURCES","file","transcendUrl","dataSiloIds","integrationNames","trackerStatuses","DEFAULT_CONSENT_TRACKER_STATUSES","pageSize","skipDatapoints","skipSubDatapoints","includeGuessedCategories","debug","apiKeyOrList","validateTranscendAuth","resourcesToPull","TranscendPullResource","client","buildTranscendGraphQLClient","configuration","pullTranscendConfiguration","logger","colors","writeTranscendYaml","err","ADMIN_DASH_INTEGRATIONS","fs","encounteredErrors","mapSeries","apiKey","ind","prefix","filePath","join"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{e as t}from"./chunk-7QHA6ZIV.js";import"./chunk-MA4JWWRO.js";import"./chunk-ZTD7APNF.js";import"./chunk-TDBKATQK.js";import"./chunk-43JWXG77.js";import"./chunk-L5ULN3IT.js";import"./chunk-SF46ZLPT.js";import"./chunk-ARVEJERC.js";async function s({file:e,transcendUrl:r,auth:i,sombraAuth:o,dataSiloId:n}){await t({file:e,transcendUrl:r,auth:i,sombraAuth:o,dataSiloId:n})}export{s as markIdentifiersCompleted};
|
|
2
|
+
//# sourceMappingURL=impl-5OEPVWPL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/request/cron/mark-identifiers-completed/impl.ts"],"sourcesContent":["import type { LocalContext } from '@/context';\nimport { pushCronIdentifiersFromCsv } from '@/lib/cron';\n\ninterface MarkIdentifiersCompletedCommandFlags {\n file: string;\n transcendUrl: string;\n auth: string;\n sombraAuth?: string;\n dataSiloId: string;\n}\n\nexport async function markIdentifiersCompleted(\n this: LocalContext,\n {\n file,\n transcendUrl,\n auth,\n sombraAuth,\n dataSiloId,\n }: MarkIdentifiersCompletedCommandFlags,\n): Promise<void> {\n await pushCronIdentifiersFromCsv({\n file,\n transcendUrl,\n auth,\n sombraAuth,\n dataSiloId,\n });\n}\n"],"mappings":"4OAWA,eAAsBA,EAEpB,CACE,KAAAC,EACA,aAAAC,EACA,KAAAC,EACA,WAAAC,EACA,WAAAC,CACF,EACe,CACf,MAAMC,EAA2B,CAC/B,KAAAL,EACA,aAAAC,EACA,KAAAC,EACA,WAAAC,EACA,WAAAC,CACF,CAAC,CACH","names":["markIdentifiersCompleted","file","transcendUrl","auth","sombraAuth","dataSiloId","pushCronIdentifiersFromCsv"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{e as c}from"./chunk-OEB7WG3G.js";import{ia as i}from"./chunk-LAYHULHH.js";import"./chunk-347UQP43.js";import{a}from"./chunk-43JWXG77.js";import"./chunk-ARVEJERC.js";import*as p from"io-ts";import m from"colors";import{existsSync as u,readFileSync as g}from"fs";import{decodeCodec as d}from"@transcend-io/type-utils";import{ConsentTrackerStatus as l,DataFlowScope as C}from"@transcend-io/privacy-types";function P({file:e,output:n}){u(e)||(a.error(m.red(`File does not exist: --file="${e}"`)),process.exit(1));let f=d(p.array(i),g(e,"utf-8")),t=[],r=[];f.forEach(s=>{s.dataFlows.filter(({type:o})=>o!==C.CSP).forEach(o=>{t.push({value:o.value,type:o.type,status:l.Live,trackingPurposes:o.trackingPurposes})}),s.cookies.forEach(o=>{r.push({name:o.name,status:l.Live,trackingPurposes:o.trackingPurposes})})}),c(n,{"data-flows":t,cookies:r}),a.info(m.green(`Successfully wrote ${t.length} data flows and ${r.length} cookies to file "${n}"`))}export{P as consentManagerServiceJsonToYml};
|
|
2
|
+
//# sourceMappingURL=impl-5YV7K446.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/inventory/consent-manager-service-json-to-yml/impl.ts"],"sourcesContent":["import type { LocalContext } from '@/context';\nimport * as t from 'io-ts';\nimport { writeTranscendYaml } from '@/lib/readTranscendYaml';\nimport colors from 'colors';\nimport { logger } from '@/logger';\nimport { existsSync, readFileSync } from 'fs';\nimport { decodeCodec } from '@transcend-io/type-utils';\nimport {\n ConsentManagerServiceMetadata,\n CookieInput,\n DataFlowInput,\n} from '@/codecs';\nimport {\n ConsentTrackerStatus,\n DataFlowScope,\n} from '@transcend-io/privacy-types';\n\ninterface ConsentManagerServiceJsonToYmlCommandFlags {\n file: string;\n output: string;\n}\n\nexport function consentManagerServiceJsonToYml(\n this: LocalContext,\n { file, output }: ConsentManagerServiceJsonToYmlCommandFlags,\n): void {\n // Ensure files exist\n if (!existsSync(file)) {\n logger.error(colors.red(`File does not exist: --file=\"${file}\"`));\n process.exit(1);\n }\n\n // Read in each consent manager configuration\n const services = decodeCodec(\n t.array(ConsentManagerServiceMetadata),\n readFileSync(file, 'utf-8'),\n );\n\n // Create data flows and cookie configurations\n const dataFlows: DataFlowInput[] = [];\n const cookies: CookieInput[] = [];\n services.forEach((service) => {\n service.dataFlows\n .filter(({ type }) => type !== DataFlowScope.CSP)\n .forEach((dataFlow) => {\n dataFlows.push({\n value: dataFlow.value,\n type: dataFlow.type,\n status: ConsentTrackerStatus.Live,\n trackingPurposes: dataFlow.trackingPurposes,\n });\n });\n\n service.cookies.forEach((cookie) => {\n cookies.push({\n name: cookie.name,\n status: ConsentTrackerStatus.Live,\n trackingPurposes: cookie.trackingPurposes,\n });\n });\n });\n\n // write to disk\n writeTranscendYaml(output, {\n 'data-flows': dataFlows,\n cookies,\n });\n\n logger.info(\n colors.green(\n `Successfully wrote ${dataFlows.length} data flows and ${cookies.length} cookies to file \"${output}\"`,\n ),\n );\n}\n"],"mappings":"4KACA,UAAYA,MAAO,QAEnB,OAAOC,MAAY,SAEnB,OAAS,cAAAC,EAAY,gBAAAC,MAAoB,KACzC,OAAS,eAAAC,MAAmB,2BAM5B,OACE,wBAAAC,EACA,iBAAAC,MACK,8BAOA,SAASC,EAEd,CAAE,KAAAC,EAAM,OAAAC,CAAO,EACT,CAEDC,EAAWF,CAAI,IAClBG,EAAO,MAAMC,EAAO,IAAI,gCAAgCJ,CAAI,GAAG,CAAC,EAChE,QAAQ,KAAK,CAAC,GAIhB,IAAMK,EAAWC,EACb,QAAMC,CAA6B,EACrCC,EAAaR,EAAM,OAAO,CAC5B,EAGMS,EAA6B,CAAC,EAC9BC,EAAyB,CAAC,EAChCL,EAAS,QAASM,GAAY,CAC5BA,EAAQ,UACL,OAAO,CAAC,CAAE,KAAAC,CAAK,IAAMA,IAASd,EAAc,GAAG,EAC/C,QAASe,GAAa,CACrBJ,EAAU,KAAK,CACb,MAAOI,EAAS,MAChB,KAAMA,EAAS,KACf,OAAQhB,EAAqB,KAC7B,iBAAkBgB,EAAS,gBAC7B,CAAC,CACH,CAAC,EAEHF,EAAQ,QAAQ,QAASG,GAAW,CAClCJ,EAAQ,KAAK,CACX,KAAMI,EAAO,KACb,OAAQjB,EAAqB,KAC7B,iBAAkBiB,EAAO,gBAC3B,CAAC,CACH,CAAC,CACH,CAAC,EAGDC,EAAmBd,EAAQ,CACzB,aAAcQ,EACd,QAAAC,CACF,CAAC,EAEDP,EAAO,KACLC,EAAO,MACL,sBAAsBK,EAAU,MAAM,mBAAmBC,EAAQ,MAAM,qBAAqBT,CAAM,GACpG,CACF,CACF","names":["t","colors","existsSync","readFileSync","decodeCodec","ConsentTrackerStatus","DataFlowScope","consentManagerServiceJsonToYml","file","output","existsSync","logger","colors","services","decodeCodec","ConsentManagerServiceMetadata","readFileSync","dataFlows","cookies","service","type","dataFlow","cookie","writeTranscendYaml"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{g as w}from"./chunk-7QHA6ZIV.js";import{c as d,d as c}from"./chunk-MA4JWWRO.js";import"./chunk-ZTD7APNF.js";import{Ke as v,b as h,pe as q}from"./chunk-TDBKATQK.js";import{a as t}from"./chunk-43JWXG77.js";import"./chunk-L5ULN3IT.js";import"./chunk-SF46ZLPT.js";import"./chunk-ARVEJERC.js";import i from"colors";import{uniq as u}from"lodash-es";async function W({file:n,fileTarget:a,transcendUrl:m,auth:p,sombraAuth:P,cronDataSiloId:S,targetDataSiloId:F,actions:x,skipRequestCount:g,pageLimit:l,chunkSize:s}){g&&t.info(i.yellow("Skipping request count as requested. This may help speed up the call.")),(Number.isNaN(s)||s<=0||s%l!==0)&&(t.error(i.red(`Invalid chunk size: "${s}". Must be a positive integer that is a multiple of ${l}.`)),process.exit(1));let N=q(m,p),{baseName:R,extension:T}=c(n),{baseName:j,extension:O}=c(a),$=0,b=0,f=0;await w({dataSiloId:S,auth:p,sombraAuth:P,actions:x,apiPageSize:l,savePageSize:s,onSave:async o=>{$+=o.length;let A=o.map(e=>e.requestId),D=u(A),y=await h(D,async e=>(await v(N,{requestId:e,dataSiloId:F})).map(({fileName:C,remoteId:I})=>{if(!I)throw new Error(`Failed to find remoteId for ${C} request: ${e}`);return{RecordId:I,Object:C.replace(".json","").split("/").pop()?.replace(" Information",""),Comment:"Customer data deletion request submitted via transcend.io"}}),{concurrency:10});b+=y.flat().length;let L=u(o.map(e=>Object.keys(e)).flat()),E=`${R}-${f}${T}`,G=`${j}-${f}${O}`;d(E,o,L),t.info(i.green(`Successfully wrote ${o.length} identifiers to file "${n}"`));let r=y.flat(),M=u(r.map(e=>Object.keys(e)).flat());d(G,r,M),t.info(i.green(`Successfully wrote ${r.length} identifiers to file "${a}"`)),t.info(i.blue(`Processed chunk of ${o.length} identifiers, found ${r.length} target identifiers`)),f+=1},transcendUrl:m,skipRequestCount:g}),t.info(i.green(`Successfully wrote ${$} identifiers to file "${n}"`)),t.info(i.green(`Successfully wrote ${b} identifiers to file "${a}"`))}export{W as pullProfiles};
|
|
2
|
+
//# sourceMappingURL=impl-AFRHPZGF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/request/cron/pull-profiles/impl.ts"],"sourcesContent":["import type { RequestAction } from '@transcend-io/privacy-types';\nimport { logger } from '@/logger';\nimport colors from 'colors';\nimport { uniq } from 'lodash-es';\nimport { map } from '@/lib/bluebird-replace';\nimport {\n buildTranscendGraphQLClient,\n fetchRequestFilesForRequest,\n} from '@/lib/graphql';\nimport type { LocalContext } from '@/context';\nimport {\n parseFilePath,\n pullChunkedCustomSiloOutstandingIdentifiers,\n writeCsv,\n type CsvFormattedIdentifier,\n} from '@/lib/cron';\n\ninterface PullProfilesCommandFlags {\n file: string;\n fileTarget: string;\n transcendUrl: string;\n auth: string;\n sombraAuth?: string;\n cronDataSiloId: string;\n targetDataSiloId: string;\n actions: RequestAction[];\n skipRequestCount: boolean;\n pageLimit: number;\n chunkSize: number;\n}\n\nexport async function pullProfiles(\n this: LocalContext,\n {\n file,\n fileTarget,\n transcendUrl,\n auth,\n sombraAuth,\n cronDataSiloId,\n targetDataSiloId,\n actions,\n skipRequestCount,\n pageLimit,\n chunkSize,\n }: PullProfilesCommandFlags,\n): Promise<void> {\n if (skipRequestCount) {\n logger.info(\n colors.yellow(\n 'Skipping request count as requested. This may help speed up the call.',\n ),\n );\n }\n\n if (\n Number.isNaN(chunkSize) ||\n chunkSize <= 0 ||\n chunkSize % pageLimit !== 0\n ) {\n logger.error(\n colors.red(\n `Invalid chunk size: \"${chunkSize}\". Must be a positive integer that is a multiple of ${pageLimit}.`,\n ),\n );\n process.exit(1);\n }\n\n // Create GraphQL client to connect to Transcend backend\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n const { baseName, extension } = parseFilePath(file);\n const { baseName: baseNameTarget, extension: extensionTarget } =\n parseFilePath(fileTarget);\n\n let allIdentifiersCount = 0;\n let allTargetIdentifiersCount = 0;\n let fileCount = 0;\n // Create onSave callback to handle chunked processing\n const onSave = async (chunk: CsvFormattedIdentifier[]): Promise<void> => {\n // Add to all identifiers\n allIdentifiersCount += chunk.length;\n\n // Get unique request IDs from this chunk\n const requestIds = chunk.map((d) => d.requestId as string);\n const uniqueRequestIds = uniq(requestIds);\n\n // Pull down target identifiers for this chunk\n const results = await map(\n uniqueRequestIds,\n async (requestId) => {\n const results = await fetchRequestFilesForRequest(client, {\n requestId,\n dataSiloId: targetDataSiloId,\n });\n return results.map(({ fileName, remoteId }) => {\n if (!remoteId) {\n throw new Error(\n `Failed to find remoteId for ${fileName} request: ${requestId}`,\n );\n }\n return {\n RecordId: remoteId,\n Object: fileName\n .replace('.json', '')\n .split('/')\n .pop()\n ?.replace(' Information', ''),\n Comment:\n 'Customer data deletion request submitted via transcend.io',\n };\n });\n },\n {\n concurrency: 10,\n },\n );\n\n allTargetIdentifiersCount += results.flat().length;\n\n // Write the identifiers and target identifiers to CSV\n const headers = uniq(chunk.map((d) => Object.keys(d)).flat());\n const numberedFileName = `${baseName}-${fileCount}${extension}`;\n const numberedFileNameTarget = `${baseNameTarget}-${fileCount}${extensionTarget}`;\n writeCsv(numberedFileName, chunk, headers);\n logger.info(\n colors.green(\n `Successfully wrote ${chunk.length} identifiers to file \"${file}\"`,\n ),\n );\n\n const targetIdentifiers = results.flat();\n const headers2 = uniq(targetIdentifiers.map((d) => Object.keys(d)).flat());\n writeCsv(numberedFileNameTarget, targetIdentifiers, headers2);\n logger.info(\n colors.green(\n `Successfully wrote ${targetIdentifiers.length} identifiers to file \"${fileTarget}\"`,\n ),\n );\n\n logger.info(\n colors.blue(\n `Processed chunk of ${chunk.length} identifiers, found ${targetIdentifiers.length} target identifiers`,\n ),\n );\n fileCount += 1;\n };\n\n // Pull down outstanding identifiers using the new chunked function\n await pullChunkedCustomSiloOutstandingIdentifiers({\n dataSiloId: cronDataSiloId,\n auth,\n sombraAuth,\n actions,\n apiPageSize: pageLimit,\n savePageSize: chunkSize,\n onSave,\n transcendUrl,\n skipRequestCount,\n });\n\n logger.info(\n colors.green(\n `Successfully wrote ${allIdentifiersCount} identifiers to file \"${file}\"`,\n ),\n );\n logger.info(\n colors.green(\n `Successfully wrote ${allTargetIdentifiersCount} identifiers to file \"${fileTarget}\"`,\n ),\n );\n}\n"],"mappings":"uSAEA,OAAOA,MAAY,SACnB,OAAS,QAAAC,MAAY,YA4BrB,eAAsBC,EAEpB,CACE,KAAAC,EACA,WAAAC,EACA,aAAAC,EACA,KAAAC,EACA,WAAAC,EACA,eAAAC,EACA,iBAAAC,EACA,QAAAC,EACA,iBAAAC,EACA,UAAAC,EACA,UAAAC,CACF,EACe,CACXF,GACFG,EAAO,KACLC,EAAO,OACL,uEACF,CACF,GAIA,OAAO,MAAMF,CAAS,GACtBA,GAAa,GACbA,EAAYD,IAAc,KAE1BE,EAAO,MACLC,EAAO,IACL,wBAAwBF,CAAS,uDAAuDD,CAAS,GACnG,CACF,EACA,QAAQ,KAAK,CAAC,GAIhB,IAAMI,EAASC,EAA4BZ,EAAcC,CAAI,EACvD,CAAE,SAAAY,EAAU,UAAAC,CAAU,EAAIC,EAAcjB,CAAI,EAC5C,CAAE,SAAUkB,EAAgB,UAAWC,CAAgB,EAC3DF,EAAchB,CAAU,EAEtBmB,EAAsB,EACtBC,EAA4B,EAC5BC,EAAY,EAwEhB,MAAMC,EAA4C,CAChD,WAAYlB,EACZ,KAAAF,EACA,WAAAC,EACA,QAAAG,EACA,YAAaE,EACb,aAAcC,EACd,OA7Ea,MAAOc,GAAmD,CAEvEJ,GAAuBI,EAAM,OAG7B,IAAMC,EAAaD,EAAM,IAAKE,GAAMA,EAAE,SAAmB,EACnDC,EAAmBC,EAAKH,CAAU,EAGlCI,EAAU,MAAMC,EACpBH,EACA,MAAOI,IACW,MAAMC,EAA4BnB,EAAQ,CACxD,UAAAkB,EACA,WAAYzB,CACd,CAAC,GACc,IAAI,CAAC,CAAE,SAAA2B,EAAU,SAAAC,CAAS,IAAM,CAC7C,GAAI,CAACA,EACH,MAAM,IAAI,MACR,+BAA+BD,CAAQ,aAAaF,CAAS,EAC/D,EAEF,MAAO,CACL,SAAUG,EACV,OAAQD,EACL,QAAQ,QAAS,EAAE,EACnB,MAAM,GAAG,EACT,IAAI,GACH,QAAQ,eAAgB,EAAE,EAC9B,QACE,2DACJ,CACF,CAAC,EAEH,CACE,YAAa,EACf,CACF,EAEAZ,GAA6BQ,EAAQ,KAAK,EAAE,OAG5C,IAAMM,EAAUP,EAAKJ,EAAM,IAAKE,GAAM,OAAO,KAAKA,CAAC,CAAC,EAAE,KAAK,CAAC,EACtDU,EAAmB,GAAGrB,CAAQ,IAAIO,CAAS,GAAGN,CAAS,GACvDqB,EAAyB,GAAGnB,CAAc,IAAII,CAAS,GAAGH,CAAe,GAC/EmB,EAASF,EAAkBZ,EAAOW,CAAO,EACzCxB,EAAO,KACLC,EAAO,MACL,sBAAsBY,EAAM,MAAM,yBAAyBxB,CAAI,GACjE,CACF,EAEA,IAAMuC,EAAoBV,EAAQ,KAAK,EACjCW,EAAWZ,EAAKW,EAAkB,IAAKb,GAAM,OAAO,KAAKA,CAAC,CAAC,EAAE,KAAK,CAAC,EACzEY,EAASD,EAAwBE,EAAmBC,CAAQ,EAC5D7B,EAAO,KACLC,EAAO,MACL,sBAAsB2B,EAAkB,MAAM,yBAAyBtC,CAAU,GACnF,CACF,EAEAU,EAAO,KACLC,EAAO,KACL,sBAAsBY,EAAM,MAAM,uBAAuBe,EAAkB,MAAM,qBACnF,CACF,EACAjB,GAAa,CACf,EAWE,aAAApB,EACA,iBAAAM,CACF,CAAC,EAEDG,EAAO,KACLC,EAAO,MACL,sBAAsBQ,CAAmB,yBAAyBpB,CAAI,GACxE,CACF,EACAW,EAAO,KACLC,EAAO,MACL,sBAAsBS,CAAyB,yBAAyBpB,CAAU,GACpF,CACF,CACF","names":["colors","uniq","pullProfiles","file","fileTarget","transcendUrl","auth","sombraAuth","cronDataSiloId","targetDataSiloId","actions","skipRequestCount","pageLimit","chunkSize","logger","colors","client","buildTranscendGraphQLClient","baseName","extension","parseFilePath","baseNameTarget","extensionTarget","allIdentifiersCount","allTargetIdentifiersCount","fileCount","pullChunkedCustomSiloOutstandingIdentifiers","chunk","requestIds","d","uniqueRequestIds","uniq","results","map","requestId","fetchRequestFilesForRequest","fileName","remoteId","headers","numberedFileName","numberedFileNameTarget","writeCsv","targetIdentifiers","headers2"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{a}from"./chunk-MVDOKJ6J.js";import"./chunk-LAYHULHH.js";import"./chunk-347UQP43.js";import"./chunk-TDBKATQK.js";import{a as n}from"./chunk-43JWXG77.js";import"./chunk-L5ULN3IT.js";import"./chunk-SF46ZLPT.js";import"./chunk-ARVEJERC.js";import x from"colors";import{writeFileSync as A}from"fs";import{TRANSCEND_SCOPES as E}from"@transcend-io/privacy-types";import{keyBy as K}from"lodash-es";var i=K(Object.entries(E).map(([t,o])=>({...o,name:t})),"title"),N=Object.keys(i);async function P({email:t,password:o,apiKeyTitle:p,file:c,scopes:m,deleteExistingApiKey:l,createNewApiKey:g,parentOrganizationId:f,transcendUrl:y}){let r=m.map(e=>e.trim()),s=r.filter(e=>!i[e]);s.length>0&&(n.error(x.red(`Failed to parse scopes:"${s.join(",")}".
|
|
2
|
+
Expected one of:
|
|
3
|
+
${N.join(`
|
|
4
|
+
`)}`)),process.exit(1));let S=r.map(e=>i[e].name),{errors:d,apiKeys:C}=await a({transcendUrl:y,password:o,email:t,parentOrganizationId:f,deleteExistingApiKey:l,createNewApiKey:g,apiKeyTitle:p,scopes:S});A(c,`${JSON.stringify(C,null,2)}
|
|
5
|
+
`),d.length>0&&process.exit(1)}export{P as generateApiKeys};
|
|
6
|
+
//# sourceMappingURL=impl-CCUCFOCW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/admin/generate-api-keys/impl.ts"],"sourcesContent":["import type { LocalContext } from '@/context';\nimport colors from 'colors';\nimport { writeFileSync } from 'fs';\n\nimport { ScopeName, TRANSCEND_SCOPES } from '@transcend-io/privacy-types';\n\nimport { logger } from '@/logger';\nimport { generateCrossAccountApiKeys } from '@/lib/api-keys';\nimport { keyBy } from 'lodash-es';\n\nconst SCOPES_BY_TITLE = keyBy(\n Object.entries(TRANSCEND_SCOPES).map(([name, value]) => ({\n ...value,\n name,\n })),\n 'title',\n);\nconst SCOPE_TITLES = Object.keys(SCOPES_BY_TITLE);\n\n// Command flag interface\ninterface GenerateApiKeysCommandFlags {\n email: string;\n password: string;\n apiKeyTitle: string;\n file: string;\n scopes: string[];\n deleteExistingApiKey: boolean;\n createNewApiKey: boolean;\n parentOrganizationId?: string;\n transcendUrl: string;\n}\n\n// Command implementation\nexport async function generateApiKeys(\n this: LocalContext,\n {\n email,\n password,\n apiKeyTitle,\n file,\n scopes,\n deleteExistingApiKey,\n createNewApiKey,\n parentOrganizationId,\n transcendUrl,\n }: GenerateApiKeysCommandFlags,\n): Promise<void> {\n // Validate scopes\n const splitScopes = scopes.map((x) => x.trim());\n const invalidScopes = splitScopes.filter(\n (scopeTitle) => !SCOPES_BY_TITLE[scopeTitle],\n );\n if (invalidScopes.length > 0) {\n logger.error(\n colors.red(\n `Failed to parse scopes:\"${invalidScopes.join(',')}\".\\n` +\n `Expected one of: \\n${SCOPE_TITLES.join('\\n')}`,\n ),\n );\n process.exit(1);\n }\n\n const scopeNames = splitScopes.map(\n (scopeTitle) => SCOPES_BY_TITLE[scopeTitle].name as ScopeName,\n );\n\n // Upload privacy requests\n const { errors, apiKeys } = await generateCrossAccountApiKeys({\n transcendUrl,\n password,\n email,\n parentOrganizationId,\n deleteExistingApiKey,\n createNewApiKey,\n apiKeyTitle,\n scopes: scopeNames,\n });\n\n // Write to disk\n writeFileSync(file, `${JSON.stringify(apiKeys, null, 2)}\\n`);\n if (errors.length > 0) {\n process.exit(1);\n }\n}\n"],"mappings":"mPACA,OAAOA,MAAY,SACnB,OAAS,iBAAAC,MAAqB,KAE9B,OAAoB,oBAAAC,MAAwB,8BAI5C,OAAS,SAAAC,MAAa,YAEtB,IAAMC,EAAkBD,EACtB,OAAO,QAAQE,CAAgB,EAAE,IAAI,CAAC,CAACC,EAAMC,CAAK,KAAO,CACvD,GAAGA,EACH,KAAAD,CACF,EAAE,EACF,OACF,EACME,EAAe,OAAO,KAAKJ,CAAe,EAgBhD,eAAsBK,EAEpB,CACE,MAAAC,EACA,SAAAC,EACA,YAAAC,EACA,KAAAC,EACA,OAAAC,EACA,qBAAAC,EACA,gBAAAC,EACA,qBAAAC,EACA,aAAAC,CACF,EACe,CAEf,IAAMC,EAAcL,EAAO,IAAKM,GAAMA,EAAE,KAAK,CAAC,EACxCC,EAAgBF,EAAY,OAC/BG,GAAe,CAAClB,EAAgBkB,CAAU,CAC7C,EACID,EAAc,OAAS,IACzBE,EAAO,MACLC,EAAO,IACL,2BAA2BH,EAAc,KAAK,GAAG,CAAC;AAAA;AAAA,EAC1Bb,EAAa,KAAK;AAAA,CAAI,CAAC,EACjD,CACF,EACA,QAAQ,KAAK,CAAC,GAGhB,IAAMiB,EAAaN,EAAY,IAC5BG,GAAelB,EAAgBkB,CAAU,EAAE,IAC9C,EAGM,CAAE,OAAAI,EAAQ,QAAAC,CAAQ,EAAI,MAAMC,EAA4B,CAC5D,aAAAV,EACA,SAAAP,EACA,MAAAD,EACA,qBAAAO,EACA,qBAAAF,EACA,gBAAAC,EACA,YAAAJ,EACA,OAAQa,CACV,CAAC,EAGDI,EAAchB,EAAM,GAAG,KAAK,UAAUc,EAAS,KAAM,CAAC,CAAC;AAAA,CAAI,EACvDD,EAAO,OAAS,GAClB,QAAQ,KAAK,CAAC,CAElB","names":["colors","writeFileSync","TRANSCEND_SCOPES","keyBy","SCOPES_BY_TITLE","TRANSCEND_SCOPES","name","value","SCOPE_TITLES","generateApiKeys","email","password","apiKeyTitle","file","scopes","deleteExistingApiKey","createNewApiKey","parentOrganizationId","transcendUrl","splitScopes","x","invalidScopes","scopeTitle","logger","colors","scopeNames","errors","apiKeys","generateCrossAccountApiKeys","writeFileSync"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as p}from"./chunk-CBAHSBSW.js";import{d as c,e as l}from"./chunk-OEB7WG3G.js";import{c as d}from"./chunk-MVDOKJ6J.js";import"./chunk-LAYHULHH.js";import"./chunk-347UQP43.js";import{ne as m,pe as g}from"./chunk-TDBKATQK.js";import{a as o}from"./chunk-43JWXG77.js";import"./chunk-L5ULN3IT.js";import"./chunk-SF46ZLPT.js";import"./chunk-ARVEJERC.js";import{join as f}from"path";import e from"colors";import{existsSync as D,lstatSync as h}from"fs";async function M({auth:x,dataFlowsYmlFolder:r,dataSilosYmlFolder:t,ignoreYmls:S=[],transcendUrl:T}){r||(o.error(e.red("Missing required arg: --dataFlowsYmlFolder=./working/data-flows/")),process.exit(1)),(!D(r)||!h(r).isDirectory())&&(o.error(e.red(`Folder does not exist: "${r}"`)),process.exit(1)),t||(o.error(e.red("Missing required arg: --dataSilosYmlFolder=./working/data-silos/")),process.exit(1)),(!D(t)||!h(t).isDirectory())&&(o.error(e.red(`Folder does not exist: "${t}"`)),process.exit(1));let w=g(T,x),{serviceToTitle:u,serviceToSupportedIntegration:v}=await m(w);d(r).forEach(i=>{let{"data-flows":F=[]}=c(f(r,i)),{adTechDataSilos:s,siteTechDataSilos:a}=p(F,{serviceToSupportedIntegration:v,serviceToTitle:u}),n=[...s,...a];o.log(`Total Services: ${n.length}`),o.log(`Ad Tech Services: ${s.length}`),o.log(`Site Tech Services: ${a.length}`),l(f(t,i),{"data-silos":S.includes(i)?[]:n})})}export{M as deriveDataSilosFromDataFlows};
|
|
2
|
+
//# sourceMappingURL=impl-E36SWF4Z.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/inventory/derive-data-silos-from-data-flows/impl.ts"],"sourcesContent":["import type { LocalContext } from '@/context';\nimport {\n fetchAndIndexCatalogs,\n buildTranscendGraphQLClient,\n} from '@/lib/graphql';\nimport { join } from 'path';\nimport colors from 'colors';\nimport { logger } from '@/logger';\nimport { dataFlowsToDataSilos } from '@/lib/consent-manager/dataFlowsToDataSilos';\nimport { DataFlowInput } from '@/codecs';\nimport { existsSync, lstatSync } from 'fs';\nimport { listFiles } from '@/lib/api-keys';\nimport { readTranscendYaml, writeTranscendYaml } from '@/lib/readTranscendYaml';\n\ninterface DeriveDataSilosFromDataFlowsCommandFlags {\n auth: string;\n dataFlowsYmlFolder: string;\n dataSilosYmlFolder: string;\n ignoreYmls?: string[];\n transcendUrl: string;\n}\n\nexport async function deriveDataSilosFromDataFlows(\n this: LocalContext,\n {\n auth,\n dataFlowsYmlFolder,\n dataSilosYmlFolder,\n ignoreYmls = [],\n transcendUrl,\n }: DeriveDataSilosFromDataFlowsCommandFlags,\n): Promise<void> {\n // Ensure folder is passed to dataFlowsYmlFolder\n if (!dataFlowsYmlFolder) {\n logger.error(\n colors.red(\n 'Missing required arg: --dataFlowsYmlFolder=./working/data-flows/',\n ),\n );\n process.exit(1);\n }\n\n // Ensure folder is passed\n if (\n !existsSync(dataFlowsYmlFolder) ||\n !lstatSync(dataFlowsYmlFolder).isDirectory()\n ) {\n logger.error(colors.red(`Folder does not exist: \"${dataFlowsYmlFolder}\"`));\n process.exit(1);\n }\n\n // Ensure folder is passed to dataSilosYmlFolder\n if (!dataSilosYmlFolder) {\n logger.error(\n colors.red(\n 'Missing required arg: --dataSilosYmlFolder=./working/data-silos/',\n ),\n );\n process.exit(1);\n }\n\n // Ensure folder is passed\n if (\n !existsSync(dataSilosYmlFolder) ||\n !lstatSync(dataSilosYmlFolder).isDirectory()\n ) {\n logger.error(colors.red(`Folder does not exist: \"${dataSilosYmlFolder}\"`));\n process.exit(1);\n }\n\n // Fetch all integrations in the catalog\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n const { serviceToTitle, serviceToSupportedIntegration } =\n await fetchAndIndexCatalogs(client);\n\n // List of each data flow yml file\n listFiles(dataFlowsYmlFolder).forEach((directory) => {\n // read in the data flows for a specific instance\n const { 'data-flows': dataFlows = [] } = readTranscendYaml(\n join(dataFlowsYmlFolder, directory),\n );\n\n // map the data flows to data silos\n const { adTechDataSilos, siteTechDataSilos } = dataFlowsToDataSilos(\n dataFlows as DataFlowInput[],\n {\n serviceToSupportedIntegration,\n serviceToTitle,\n },\n );\n\n // combine and write to yml file\n const dataSilos = [...adTechDataSilos, ...siteTechDataSilos];\n logger.log(`Total Services: ${dataSilos.length}`);\n logger.log(`Ad Tech Services: ${adTechDataSilos.length}`);\n logger.log(`Site Tech Services: ${siteTechDataSilos.length}`);\n writeTranscendYaml(join(dataSilosYmlFolder, directory), {\n 'data-silos': ignoreYmls.includes(directory) ? [] : dataSilos,\n });\n });\n}\n"],"mappings":"oWAKA,OAAS,QAAAA,MAAY,OACrB,OAAOC,MAAY,SAInB,OAAS,cAAAC,EAAY,aAAAC,MAAiB,KAYtC,eAAsBC,EAEpB,CACE,KAAAC,EACA,mBAAAC,EACA,mBAAAC,EACA,WAAAC,EAAa,CAAC,EACd,aAAAC,CACF,EACe,CAEVH,IACHI,EAAO,MACLC,EAAO,IACL,kEACF,CACF,EACA,QAAQ,KAAK,CAAC,IAKd,CAACC,EAAWN,CAAkB,GAC9B,CAACO,EAAUP,CAAkB,EAAE,YAAY,KAE3CI,EAAO,MAAMC,EAAO,IAAI,2BAA2BL,CAAkB,GAAG,CAAC,EACzE,QAAQ,KAAK,CAAC,GAIXC,IACHG,EAAO,MACLC,EAAO,IACL,kEACF,CACF,EACA,QAAQ,KAAK,CAAC,IAKd,CAACC,EAAWL,CAAkB,GAC9B,CAACM,EAAUN,CAAkB,EAAE,YAAY,KAE3CG,EAAO,MAAMC,EAAO,IAAI,2BAA2BJ,CAAkB,GAAG,CAAC,EACzE,QAAQ,KAAK,CAAC,GAIhB,IAAMO,EAASC,EAA4BN,EAAcJ,CAAI,EACvD,CAAE,eAAAW,EAAgB,8BAAAC,CAA8B,EACpD,MAAMC,EAAsBJ,CAAM,EAGpCK,EAAUb,CAAkB,EAAE,QAASc,GAAc,CAEnD,GAAM,CAAE,aAAcC,EAAY,CAAC,CAAE,EAAIC,EACvCC,EAAKjB,EAAoBc,CAAS,CACpC,EAGM,CAAE,gBAAAI,EAAiB,kBAAAC,CAAkB,EAAIC,EAC7CL,EACA,CACE,8BAAAJ,EACA,eAAAD,CACF,CACF,EAGMW,EAAY,CAAC,GAAGH,EAAiB,GAAGC,CAAiB,EAC3Df,EAAO,IAAI,mBAAmBiB,EAAU,MAAM,EAAE,EAChDjB,EAAO,IAAI,qBAAqBc,EAAgB,MAAM,EAAE,EACxDd,EAAO,IAAI,uBAAuBe,EAAkB,MAAM,EAAE,EAC5DG,EAAmBL,EAAKhB,EAAoBa,CAAS,EAAG,CACtD,aAAcZ,EAAW,SAASY,CAAS,EAAI,CAAC,EAAIO,CACtD,CAAC,CACH,CAAC,CACH","names":["join","colors","existsSync","lstatSync","deriveDataSilosFromDataFlows","auth","dataFlowsYmlFolder","dataSilosYmlFolder","ignoreYmls","transcendUrl","logger","colors","existsSync","lstatSync","client","buildTranscendGraphQLClient","serviceToTitle","serviceToSupportedIntegration","fetchAndIndexCatalogs","listFiles","directory","dataFlows","readTranscendYaml","join","adTechDataSilos","siteTechDataSilos","dataFlowsToDataSilos","dataSilos","writeTranscendYaml"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{t}from"./chunk-ZTD7APNF.js";import"./chunk-TDBKATQK.js";import"./chunk-43JWXG77.js";import"./chunk-L5ULN3IT.js";import"./chunk-SF46ZLPT.js";import"./chunk-ARVEJERC.js";async function u({auth:e,transcendUrl:r,actions:a,statuses:n,requestIds:s,createdAtBefore:o,createdAtAfter:i,concurrency:c}){await t({transcendUrl:r,requestActions:a,auth:e,requestIds:s,statuses:n,concurrency:c,createdAtBefore:o,createdAtAfter:i})}export{u as markSilent};
|
|
2
|
+
//# sourceMappingURL=impl-E5WXNV47.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/request/mark-silent/impl.ts"],"sourcesContent":["import type { LocalContext } from '@/context';\nimport { markSilentPrivacyRequests } from '@/lib/requests';\nimport type { RequestAction, RequestStatus } from '@transcend-io/privacy-types';\n\ninterface MarkSilentCommandFlags {\n auth: string;\n actions: RequestAction[];\n statuses?: RequestStatus[];\n requestIds?: string[];\n createdAtBefore?: Date;\n createdAtAfter?: Date;\n transcendUrl: string;\n concurrency: number;\n}\n\nexport async function markSilent(\n this: LocalContext,\n {\n auth,\n transcendUrl,\n actions,\n statuses,\n requestIds,\n createdAtBefore,\n createdAtAfter,\n concurrency,\n }: MarkSilentCommandFlags,\n): Promise<void> {\n await markSilentPrivacyRequests({\n transcendUrl,\n requestActions: actions,\n auth,\n requestIds,\n statuses,\n concurrency,\n createdAtBefore,\n createdAtAfter,\n });\n}\n"],"mappings":"+KAeA,eAAsBA,EAEpB,CACE,KAAAC,EACA,aAAAC,EACA,QAAAC,EACA,SAAAC,EACA,WAAAC,EACA,gBAAAC,EACA,eAAAC,EACA,YAAAC,CACF,EACe,CACf,MAAMC,EAA0B,CAC9B,aAAAP,EACA,eAAgBC,EAChB,KAAAF,EACA,WAAAI,EACA,SAAAD,EACA,YAAAI,EACA,gBAAAF,EACA,eAAAC,CACF,CAAC,CACH","names":["markSilent","auth","transcendUrl","actions","statuses","requestIds","createdAtBefore","createdAtAfter","concurrency","markSilentPrivacyRequests"]}
|