@transcend-io/cli 4.14.0 → 4.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -21,6 +21,9 @@
21
21
  - [tr-request-upload](#tr-request-upload)
22
22
  - [Authentication](#authentication-3)
23
23
  - [Usage](#usage-4)
24
+ - [tr-pull-cron-identifiers](#tr-pull-cron-identifiers)
25
+ - [Authentication](#authentication-4)
26
+ - [Usage](#usage-5)
24
27
 
25
28
  <!-- END doctoc generated TOC please keep comment here to allow auto update -->
26
29
 
@@ -43,6 +46,7 @@ yarn tr-pull --auth=xxx
43
46
  yarn tr-push --auth=xxx
44
47
  yarn tr-discover-silos --auth=xxx
45
48
  yarn tr-request-upload --auth=xxx
49
+ yarn tr-pull-cron-identifiers --auth=xxx
46
50
  ```
47
51
 
48
52
  or
@@ -56,6 +60,7 @@ tr-pull --auth=xxx
56
60
  tr-push --auth=xxx
57
61
  tr-discover-silos --auth=xxx
58
62
  tr-request-upload --auth=xxx
63
+ tr-pull-cron-identifiers --auth=xxx
59
64
  ```
60
65
 
61
66
  alternatively, you can install the cli globally on your machine:
@@ -191,38 +196,38 @@ _Note: The scopes for tr-push are comprehensive of the scopes for tr-pull_
191
196
 
192
197
  ```sh
193
198
  # Writes out file to ./transcend.yml
194
- tr-pull --auth=<api-key>
199
+ tr-pull --auth=$TRANSCEND_API_KEY
195
200
  ```
196
201
 
197
202
  An alternative file destination can be specified:
198
203
 
199
204
  ```sh
200
205
  # Writes out file to ./custom/location.yml
201
- tr-pull --auth=<api-key> --file=./custom/location.yml
206
+ tr-pull --auth=$TRANSCEND_API_KEY --file=./custom/location.yml
202
207
  ```
203
208
 
204
209
  Or a specific data silo(s) can be pulled in:
205
210
 
206
211
  ```sh
207
- tr-pull --auth=<api-key> --dataSiloIds=710fec3c-7bcc-4c9e-baff-bf39f9bec43e
212
+ tr-pull --auth=$TRANSCEND_API_KEY --dataSiloIds=710fec3c-7bcc-4c9e-baff-bf39f9bec43e
208
213
  ```
209
214
 
210
215
  Or a specific types of data silo(s) can be pulled in:
211
216
 
212
217
  ```sh
213
- tr-pull --auth=<api-key> --integrationNames=salesforce,snowflake
218
+ tr-pull --auth=$TRANSCEND_API_KEY --integrationNames=salesforce,snowflake
214
219
  ```
215
220
 
216
221
  Or with a specific page size (max 100)
217
222
 
218
223
  ```sh
219
- tr-pull --auth=<api-key> --integrationNames=salesforce,snowflake --pageSize=30
224
+ tr-pull --auth=$TRANSCEND_API_KEY --integrationNames=salesforce,snowflake --pageSize=30
220
225
  ```
221
226
 
222
227
  Or with debug logs
223
228
 
224
229
  ```sh
225
- tr-pull --auth=<api-key> --integrationNames=salesforce,snowflake --debug=true
230
+ tr-pull --auth=$TRANSCEND_API_KEY --integrationNames=salesforce,snowflake --debug=true
226
231
  ```
227
232
 
228
233
  Note: This command will overwrite the existing transcend.yml file that you have locally.
@@ -248,14 +253,14 @@ The API key needs the following scopes:
248
253
 
249
254
  ```sh
250
255
  # Looks for file at ./transcend.yml
251
- tr-push --auth=<api-key>
256
+ tr-push --auth=$TRANSCEND_API_KEY
252
257
  ```
253
258
 
254
259
  An alternative file destination can be specified:
255
260
 
256
261
  ```sh
257
262
  # Looks for file at custom location ./custom/location.yml
258
- tr-push --auth=<api-key> --file=./custom/location.yml
263
+ tr-push --auth=$TRANSCEND_API_KEY --file=./custom/location.yml
259
264
  ```
260
265
 
261
266
  Some things to note about this sync process:
@@ -315,7 +320,7 @@ If you are using this cli to sync your Data Map between multiple Transcend insta
315
320
  The `tr-push` command takes in a parameter `variables`. This is a CSV of `key:value` pairs.
316
321
 
317
322
  ```sh
318
- tr-push --auth=<api-key> --variables=domain:acme.com,stage:staging
323
+ tr-push --auth=$TRANSCEND_API_KEY --variables=domain:acme.com,stage:staging
319
324
  ```
320
325
 
321
326
  This command could fill out multiple parameters in a yaml file like [./examples/multi-instance.yml](./examples/multi-instance.yml), copied below:
@@ -415,74 +420,131 @@ The API key needs the following scopes:
415
420
  ### Usage
416
421
 
417
422
  ```sh
418
- yarn tr-request-upload --auth=<api-key> --file=/Users/michaelfarrell/Desktop/test.csv
423
+ yarn tr-request-upload --auth=$TRANSCEND_API_KEY --file=/Users/transcend/Desktop/test.csv
419
424
  ```
420
425
 
421
426
  For self-hosted sombras that use an internal key:
422
427
 
423
428
  ```sh
424
- yarn tr-request-upload --auth=<api-key> --sombraAuth=<sombra-internal-key> --file=/Users/michaelfarrell/Desktop/test.csv
429
+ yarn tr-request-upload --auth=$TRANSCEND_API_KEY --sombraAuth=$SOMBRA_INTERNAL_KEY --file=/Users/transcend/Desktop/test.csv
430
+ ```
431
+
432
+ Specifying the backend URL, needed for US hosted backend infrastructure.
433
+
434
+ ```sh
435
+ yarn tr-request-upload --auth=$TRANSCEND_API_KEY --sombraAuth=$SOMBRA_INTERNAL_KEY --file=/Users/transcend/Desktop/test.csv \
436
+ --transcendApiUrl=https://api.us.transcend.io
425
437
  ```
426
438
 
427
439
  Run without being prompted to filter requests
428
440
 
429
441
  ```sh
430
- yarn tr-request-upload --auth=<api-key> --file=/Users/michaelfarrell/Desktop/test.csv --skipFilterStep=true
442
+ yarn tr-request-upload --auth=$TRANSCEND_API_KEY --file=/Users/transcend/Desktop/test.csv --skipFilterStep=true
431
443
  ```
432
444
 
433
445
  Perform a dry run to see what will be uploaded, without calling the Transcend API to upload the request
434
446
 
435
447
  ```sh
436
- yarn tr-request-upload --auth=<api-key> --file=/Users/michaelfarrell/Desktop/test.csv --dryRun=true
448
+ yarn tr-request-upload --auth=$TRANSCEND_API_KEY --file=/Users/transcend/Desktop/test.csv --dryRun=true
437
449
  ```
438
450
 
439
451
  Mark the uploaded requests as test requests
440
452
 
441
453
  ```sh
442
- yarn tr-request-upload --auth=<api-key> --file=/Users/michaelfarrell/Desktop/test.csv --isTest=true
454
+ yarn tr-request-upload --auth=$TRANSCEND_API_KEY --file=/Users/transcend/Desktop/test.csv --isTest=true
443
455
  ```
444
456
 
445
457
  Send email communications to the users throughout the request lifecycle.
446
458
 
447
459
  ```sh
448
- yarn tr-request-upload --auth=<api-key> --file=/Users/michaelfarrell/Desktop/test.csv --isSilent=false
460
+ yarn tr-request-upload --auth=$TRANSCEND_API_KEY --file=/Users/transcend/Desktop/test.csv --isSilent=false
449
461
  ```
450
462
 
451
463
  Send email verification to user before request continues.
452
464
 
453
465
  ```sh
454
- yarn tr-request-upload --auth=<api-key> --file=/Users/michaelfarrell/Desktop/test.csv \
466
+ yarn tr-request-upload --auth=$TRANSCEND_API_KEY --file=/Users/transcend/Desktop/test.csv \
455
467
  --isSilent=false --emailIsVerified=false
456
468
  ```
457
469
 
458
470
  Increase the concurrency (defaults to 20)
459
471
 
460
472
  ```sh
461
- yarn tr-request-upload --auth=<api-key> --file=/Users/michaelfarrell/Desktop/test.csv --concurrency=20
473
+ yarn tr-request-upload --auth=$TRANSCEND_API_KEY --file=/Users/transcend/Desktop/test.csv --concurrency=20
462
474
  ```
463
475
 
464
476
  Tag all uploaded requests with an attribute
465
477
 
466
478
  ```sh
467
- yarn tr-request-upload --auth=<api-key> --file=/Users/michaelfarrell/Desktop/test.csv \
479
+ yarn tr-request-upload --auth=$TRANSCEND_API_KEY --file=/Users/transcend/Desktop/test.csv \
468
480
  --attributes=Tags:transcend-cli;my-customer-tag,Customer:acme-corp
469
481
  ```
470
482
 
471
483
  Clear out the cache of failed and successful requests
472
484
 
473
485
  ```sh
474
- yarn tr-request-upload --auth=<api-key> --file=/Users/michaelfarrell/Desktop/test.csv \
486
+ yarn tr-request-upload --auth=$TRANSCEND_API_KEY --file=/Users/transcend/Desktop/test.csv \
475
487
  --clearFailingRequests=true --clearSuccessfulRequests=true --clearDuplicateRequests=true
476
488
  ```
477
489
 
478
490
  Specify default country code for phone numbers
479
491
 
480
492
  ```sh
481
- yarn tr-request-upload --auth=<api-key> --file=/Users/michaelfarrell/Desktop/test.csv --defaultPhoneCountryCode=44
493
+ yarn tr-request-upload --auth=$TRANSCEND_API_KEY --file=/Users/transcend/Desktop/test.csv --defaultPhoneCountryCode=44
482
494
  ```
483
495
 
484
496
  Include debug logs - warning, this logs out personal data.
485
497
 
486
498
  ```sh
487
- yarn tr-request-upload --auth=<api-key> --file=/Users/michaelfarrell/Desktop/test.csv --debug=true
499
+ yarn tr-request-upload --auth=$TRANSCEND_API_KEY --file=/Users/transcend/Desktop/test.csv --debug=true
500
+ ```
501
+
502
+ ### tr-pull-cron-identifiers
503
+
504
+ If you are using the cron job integration, you can run this command to pull the outstanding identifiers
505
+ for the data silo to a CSV.
506
+
507
+ Read more at https://docs.transcend.io/docs/integrations/cron-job-integration.
508
+
509
+ https://user-images.githubusercontent.com/10264973/205483055-f4050645-bdf5-4ea2-8464-3183abd63074.mov
510
+
511
+ #### Authentication
512
+
513
+ In order to use this cli, you will first need to generate an API key on the Transcend Admin Dashboard (https://app.transcend.io/infrastructure/api-keys).
514
+
515
+ The API key must be associated to the ID of the integration/data silo that is being operated on.
516
+
517
+ ### Usage
518
+
519
+ ```sh
520
+ yarn tr-pull-cron-identifiers --auth=$TRANSCEND_API_KEY -dataSiloId=70810f2e-cf90-43f6-9776-901a5950599f \
521
+ --requestType=ERASURE
522
+ ```
523
+
524
+ Pull to a specific file location
525
+
526
+ ```sh
527
+ yarn tr-pull-cron-identifiers --auth=$TRANSCEND_API_KEY -dataSiloId=70810f2e-cf90-43f6-9776-901a5950599f --requestType=ERASURE \
528
+ --file=/Users/transcend/Desktop/test.csv
529
+ ```
530
+
531
+ For self-hosted sombras that use an internal key:
532
+
533
+ ```sh
534
+ yarn tr-pull-cron-identifiers --auth=$TRANSCEND_API_KEY -dataSiloId=70810f2e-cf90-43f6-9776-901a5950599f \
535
+ --requestType=ERASURE --sombraAuth=$SOMBRA_INTERNAL_KEY
536
+ ```
537
+
538
+ Specifying the backend URL, needed for US hosted backend infrastructure.
539
+
540
+ ```sh
541
+ yarn tr-pull-cron-identifiers --auth=$TRANSCEND_API_KEY --sombraAuth=$SOMBRA_INTERNAL_KEY --file=/Users/transcend/Desktop/test.csv \
542
+ --transcendApiUrl=https://api.us.transcend.io
543
+ ```
544
+
545
+ Specifying the page limit, defaults to 100.
546
+
547
+ ```sh
548
+ yarn tr-pull-cron-identifiers --auth=$TRANSCEND_API_KEY --sombraAuth=$SOMBRA_INTERNAL_KEY --file=/Users/transcend/Desktop/test.csv \
549
+ --pageLimit=300
488
550
  ```
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli-pull-cron-identifiers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-pull-cron-identifiers.d.ts","sourceRoot":"","sources":["../src/cli-pull-cron-identifiers.ts"],"names":[],"mappings":""}
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const yargs_parser_1 = __importDefault(require("yargs-parser"));
8
+ const colors_1 = __importDefault(require("colors"));
9
+ const logger_1 = require("./logger");
10
+ const cron_1 = require("./cron");
11
+ const privacy_types_1 = require("@transcend-io/privacy-types");
12
+ /**
13
+ * Pull the set of active identifiers for a cron job silo.
14
+ *
15
+ * Requires an API key with scope for the cron integration being checked on.
16
+ *
17
+ * Dev Usage:
18
+ * yarn ts-node ./src/cli-pull-cron-identifiers.ts --auth=asd123 \
19
+ * --dataSiloId=92636cda-b7c6-48c6-b1b1-2df574596cbc \
20
+ * --requestType=ERASURE \
21
+ * --file=/Users/michaelfarrell/Desktop/test.csv
22
+ *
23
+ * Standard usage:
24
+ * yarn tr-pull-cron-identifiers --auth=asd123 \
25
+ * --dataSiloId=92636cda-b7c6-48c6-b1b1-2df574596cbc \
26
+ * --requestType=ERASURE \
27
+ * --file=/Users/michaelfarrell/Desktop/test.csv
28
+ */
29
+ async function main() {
30
+ // Parse command line arguments
31
+ const { file = './cron-identifiers.csv', transcendApiUrl = 'https://api.transcend.io', auth, sombraAuth, dataSiloId, requestType, pageLimit = '100', } = (0, yargs_parser_1.default)(process.argv.slice(2));
32
+ // Ensure auth is passed
33
+ if (!auth) {
34
+ logger_1.logger.error(colors_1.default.red('A Transcend API key must be provided. You can specify using --auth=asd123'));
35
+ process.exit(1);
36
+ }
37
+ // Validate request type
38
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
39
+ if (!Object.values(privacy_types_1.RequestAction).includes(requestType)) {
40
+ logger_1.logger.error(colors_1.default.red(`Failed to parse requestType:"${requestType}".\n` +
41
+ `Expected one of: \n${Object.values(privacy_types_1.RequestAction).join('\n')}`));
42
+ process.exit(1);
43
+ }
44
+ // Upload privacy requests
45
+ await (0, cron_1.pullCronIdentifiersToCsv)({
46
+ file,
47
+ transcendApiUrl,
48
+ pageLimit: parseInt(pageLimit, 10),
49
+ requestType: requestType,
50
+ auth,
51
+ sombraAuth,
52
+ dataSiloId,
53
+ });
54
+ }
55
+ main();
56
+ //# sourceMappingURL=cli-pull-cron-identifiers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-pull-cron-identifiers.js","sourceRoot":"","sources":["../src/cli-pull-cron-identifiers.ts"],"names":[],"mappings":";;;;;;AAEA,gEAAiC;AACjC,oDAA4B;AAE5B,qCAAkC;AAClC,iCAAkD;AAClD,+DAA4D;AAE5D;;;;;;;;;;;;;;;;GAgBG;AACH,KAAK,UAAU,IAAI;IACjB,+BAA+B;IAC/B,MAAM,EACJ,IAAI,GAAG,wBAAwB,EAC/B,eAAe,GAAG,0BAA0B,EAC5C,IAAI,EACJ,UAAU,EACV,UAAU,EACV,WAAW,EACX,SAAS,GAAG,KAAK,GAClB,GAAG,IAAA,sBAAK,EAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAA8B,CAAC;IAE9D,wBAAwB;IACxB,IAAI,CAAC,IAAI,EAAE;QACT,eAAM,CAAC,KAAK,CACV,gBAAM,CAAC,GAAG,CACR,2EAA2E,CAC5E,CACF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;KACjB;IAED,wBAAwB;IACxB,8DAA8D;IAC9D,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,6BAAa,CAAC,CAAC,QAAQ,CAAC,WAAkB,CAAC,EAAE;QAC9D,eAAM,CAAC,KAAK,CACV,gBAAM,CAAC,GAAG,CACR,gCAAgC,WAAW,MAAM;YAC/C,sBAAsB,MAAM,CAAC,MAAM,CAAC,6BAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAClE,CACF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;KACjB;IAED,0BAA0B;IAC1B,MAAM,IAAA,+BAAwB,EAAC;QAC7B,IAAI;QACJ,eAAe;QACf,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC;QAClC,WAAW,EAAE,WAA4B;QACzC,IAAI;QACJ,UAAU;QACV,UAAU;KACX,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC"}
@@ -11,13 +11,10 @@ const requests_1 = require("./requests");
11
11
  /**
12
12
  * Upload a CSV of Privacy Requests.
13
13
  *
14
- * Requirements:
15
- *
16
- * 1. Create API key with follow scopes: https://app.transcend.io/infrastructure/api-keys
14
+ * Requires an API key with follow scopes: https://app.transcend.io/infrastructure/api-keys
17
15
  * - "Submit New Data Subject Request"
18
16
  * - "View Identity Verification Settings"
19
17
  * - "View Global Attributes"
20
- * 2. Invite a new user into the dashboard with no scopes but email/password login (needed for diffie hellman channel)
21
18
  *
22
19
  * Dev Usage:
23
20
  * yarn ts-node ./src/cli-request-upload.ts --auth=asd123 \
@@ -1 +1 @@
1
- {"version":3,"file":"cli-request-upload.js","sourceRoot":"","sources":["../src/cli-request-upload.ts"],"names":[],"mappings":";;;;;;AAEA,gEAAiC;AACjC,oDAA4B;AAE5B,qCAAkC;AAClC,yCAA0E;AAE1E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,KAAK,UAAU,IAAI;IACjB,+BAA+B;IAC/B,MAAM,EACJ,IAAI,GAAG,gBAAgB,EACvB,eAAe,GAAG,0BAA0B,EAC5C,aAAa,GAAG,yCAAyC,EACzD,IAAI,EACJ,UAAU,EACV,WAAW,GAAG,KAAK,EACnB,MAAM,GAAG,OAAO,EAChB,QAAQ,GAAG,MAAM,EACjB,uBAAuB,GAAG,GAAG,EAAE,MAAM;IACrC,eAAe,GAAG,MAAM,EACxB,sBAAsB,GAAG,OAAO,EAChC,uBAAuB,GAAG,OAAO,EACjC,oBAAoB,GAAG,OAAO,EAC9B,MAAM,GAAG,OAAO,EAChB,KAAK,GAAG,OAAO,EACf,cAAc,GAAG,OAAO,EACxB,UAAU,GAAG,oBAAoB,GAClC,GAAG,IAAA,sBAAK,EAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAA8B,CAAC;IAE9D,wBAAwB;IACxB,IAAI,CAAC,IAAI,EAAE;QACT,eAAM,CAAC,KAAK,CACV,gBAAM,CAAC,GAAG,CACR,2EAA2E,CAC5E,CACF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;KACjB;IAED,0BAA0B;IAC1B,MAAM,IAAA,uCAA4B,EAAC;QACjC,aAAa;QACb,IAAI;QACJ,IAAI;QACJ,UAAU;QACV,oBAAoB,EAAE,oBAAoB,KAAK,MAAM;QACrD,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC;QACtC,eAAe;QACf,uBAAuB;QACvB,UAAU,EAAE,IAAA,yBAAc,EAAC,UAAU,CAAC;QACtC,sBAAsB,EAAE,sBAAsB,KAAK,MAAM;QACzD,uBAAuB,EAAE,uBAAuB,KAAK,MAAM;QAC3D,KAAK,EAAE,KAAK,KAAK,MAAM;QACvB,cAAc,EAAE,cAAc,KAAK,MAAM;QACzC,QAAQ,EAAE,QAAQ,KAAK,MAAM;QAC7B,eAAe,EAAE,eAAe,KAAK,MAAM;QAC3C,MAAM,EAAE,MAAM,KAAK,MAAM;QACzB,MAAM,EAAE,MAAM,KAAK,MAAM;KAC1B,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC"}
1
+ {"version":3,"file":"cli-request-upload.js","sourceRoot":"","sources":["../src/cli-request-upload.ts"],"names":[],"mappings":";;;;;;AAEA,gEAAiC;AACjC,oDAA4B;AAE5B,qCAAkC;AAClC,yCAA0E;AAE1E;;;;;;;;;;;;;;;;;GAiBG;AACH,KAAK,UAAU,IAAI;IACjB,+BAA+B;IAC/B,MAAM,EACJ,IAAI,GAAG,gBAAgB,EACvB,eAAe,GAAG,0BAA0B,EAC5C,aAAa,GAAG,yCAAyC,EACzD,IAAI,EACJ,UAAU,EACV,WAAW,GAAG,KAAK,EACnB,MAAM,GAAG,OAAO,EAChB,QAAQ,GAAG,MAAM,EACjB,uBAAuB,GAAG,GAAG,EAAE,MAAM;IACrC,eAAe,GAAG,MAAM,EACxB,sBAAsB,GAAG,OAAO,EAChC,uBAAuB,GAAG,OAAO,EACjC,oBAAoB,GAAG,OAAO,EAC9B,MAAM,GAAG,OAAO,EAChB,KAAK,GAAG,OAAO,EACf,cAAc,GAAG,OAAO,EACxB,UAAU,GAAG,oBAAoB,GAClC,GAAG,IAAA,sBAAK,EAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAA8B,CAAC;IAE9D,wBAAwB;IACxB,IAAI,CAAC,IAAI,EAAE;QACT,eAAM,CAAC,KAAK,CACV,gBAAM,CAAC,GAAG,CACR,2EAA2E,CAC5E,CACF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;KACjB;IAED,0BAA0B;IAC1B,MAAM,IAAA,uCAA4B,EAAC;QACjC,aAAa;QACb,IAAI;QACJ,IAAI;QACJ,UAAU;QACV,oBAAoB,EAAE,oBAAoB,KAAK,MAAM;QACrD,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC;QACtC,eAAe;QACf,uBAAuB;QACvB,UAAU,EAAE,IAAA,yBAAc,EAAC,UAAU,CAAC;QACtC,sBAAsB,EAAE,sBAAsB,KAAK,MAAM;QACzD,uBAAuB,EAAE,uBAAuB,KAAK,MAAM;QAC3D,KAAK,EAAE,KAAK,KAAK,MAAM;QACvB,cAAc,EAAE,cAAc,KAAK,MAAM;QACzC,QAAQ,EAAE,QAAQ,KAAK,MAAM;QAC7B,eAAe,EAAE,eAAe,KAAK,MAAM;QAC3C,MAAM,EAAE,MAAM,KAAK,MAAM;QACzB,MAAM,EAAE,MAAM,KAAK,MAAM;KAC1B,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from './pullCronIdentifiersToCsv';
2
+ export * from './pullCronPageOfIdentifiers';
3
+ export * from './writeCsv';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cron/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,YAAY,CAAC"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ __exportStar(require("./pullCronIdentifiersToCsv"), exports);
14
+ __exportStar(require("./pullCronPageOfIdentifiers"), exports);
15
+ __exportStar(require("./writeCsv"), exports);
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cron/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6DAA2C;AAC3C,8DAA4C;AAC5C,6CAA2B"}
@@ -0,0 +1,24 @@
1
+ import { CronIdentifier } from './pullCronPageOfIdentifiers';
2
+ import { RequestAction } from '@transcend-io/privacy-types';
3
+ /**
4
+ * Pull the set of cron job identifiers to CSV
5
+ *
6
+ * @param options - Options
7
+ */
8
+ export declare function pullCronIdentifiersToCsv({ file, dataSiloId, auth, sombraAuth, requestType, pageLimit, transcendApiUrl, }: {
9
+ /** CSV file path */
10
+ file: string;
11
+ /** Transcend API key authentication */
12
+ auth: string;
13
+ /** Data Silo ID to pull down jobs for */
14
+ dataSiloId: string;
15
+ /** The request action to fetch */
16
+ requestType: RequestAction;
17
+ /** Page limit when fetching identifiers */
18
+ pageLimit?: number;
19
+ /** API URL for Transcend backend */
20
+ transcendApiUrl?: string;
21
+ /** Sombra API key authentication */
22
+ sombraAuth?: string;
23
+ }): Promise<CronIdentifier[]>;
24
+ //# sourceMappingURL=pullCronIdentifiersToCsv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pullCronIdentifiersToCsv.d.ts","sourceRoot":"","sources":["../../src/cron/pullCronIdentifiersToCsv.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,cAAc,EACf,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAI5D;;;;GAIG;AACH,wBAAsB,wBAAwB,CAAC,EAC7C,IAAI,EACJ,UAAU,EACV,IAAI,EACJ,UAAU,EACV,WAAW,EACX,SAAe,EACf,eAA4C,GAC7C,EAAE;IACD,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,WAAW,EAAE,aAAa,CAAC;IAC3B,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oCAAoC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAwD5B"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.pullCronIdentifiersToCsv = void 0;
7
+ const graphql_1 = require("../graphql");
8
+ const colors_1 = __importDefault(require("colors"));
9
+ const pullCronPageOfIdentifiers_1 = require("./pullCronPageOfIdentifiers");
10
+ const writeCsv_1 = require("./writeCsv");
11
+ const logger_1 = require("../logger");
12
+ /**
13
+ * Pull the set of cron job identifiers to CSV
14
+ *
15
+ * @param options - Options
16
+ */
17
+ async function pullCronIdentifiersToCsv({ file, dataSiloId, auth, sombraAuth, requestType, pageLimit = 100, transcendApiUrl = 'https://api.transcend.io', }) {
18
+ // Create sombra instance to communicate with
19
+ const sombra = await (0, graphql_1.createSombraGotInstance)(transcendApiUrl, auth, sombraAuth);
20
+ logger_1.logger.info(colors_1.default.magenta(`Pulling identifier for data silo: ${dataSiloId} of type ${requestType}`));
21
+ let offset = 0;
22
+ const identifiers = [];
23
+ let shouldContinue = true;
24
+ // Fetch a page of identifiers
25
+ while (shouldContinue) {
26
+ // eslint-disable-next-line no-await-in-loop
27
+ const pageIdentifiers = await (0, pullCronPageOfIdentifiers_1.pullCronPageOfIdentifiers)(sombra, {
28
+ dataSiloId,
29
+ limit: pageLimit,
30
+ offset,
31
+ requestType,
32
+ });
33
+ identifiers.push(...pageIdentifiers);
34
+ shouldContinue = pageIdentifiers.length === pageLimit;
35
+ offset += pageLimit;
36
+ }
37
+ logger_1.logger.info(colors_1.default.magenta(`Found: ${identifiers.length} outstanding identifiers to parse`));
38
+ // Write out to CSV
39
+ (0, writeCsv_1.writeCsv)(file, identifiers.map((identifier) => ({
40
+ ...identifier,
41
+ attributes: identifier.attributes
42
+ .map((attr) => `${attr.key}:${attr.values.join(';')}`)
43
+ .join(','),
44
+ })));
45
+ logger_1.logger.info(colors_1.default.green(`Successfully wrote ${identifiers.length} identifiers to file "${file}"`));
46
+ return identifiers;
47
+ }
48
+ exports.pullCronIdentifiersToCsv = pullCronIdentifiersToCsv;
49
+ //# sourceMappingURL=pullCronIdentifiersToCsv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pullCronIdentifiersToCsv.js","sourceRoot":"","sources":["../../src/cron/pullCronIdentifiersToCsv.ts"],"names":[],"mappings":";;;;;;AAAA,wCAAqD;AACrD,oDAA4B;AAC5B,2EAGqC;AAErC,yCAAsC;AACtC,sCAAmC;AAEnC;;;;GAIG;AACI,KAAK,UAAU,wBAAwB,CAAC,EAC7C,IAAI,EACJ,UAAU,EACV,IAAI,EACJ,UAAU,EACV,WAAW,EACX,SAAS,GAAG,GAAG,EACf,eAAe,GAAG,0BAA0B,GAgB7C;IACC,6CAA6C;IAC7C,MAAM,MAAM,GAAG,MAAM,IAAA,iCAAuB,EAC1C,eAAe,EACf,IAAI,EACJ,UAAU,CACX,CAAC;IAEF,eAAM,CAAC,IAAI,CACT,gBAAM,CAAC,OAAO,CACZ,qCAAqC,UAAU,YAAY,WAAW,EAAE,CACzE,CACF,CAAC;IAEF,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,MAAM,WAAW,GAAqB,EAAE,CAAC;IACzC,IAAI,cAAc,GAAG,IAAI,CAAC;IAE1B,8BAA8B;IAC9B,OAAO,cAAc,EAAE;QACrB,4CAA4C;QAC5C,MAAM,eAAe,GAAG,MAAM,IAAA,qDAAyB,EAAC,MAAM,EAAE;YAC9D,UAAU;YACV,KAAK,EAAE,SAAS;YAChB,MAAM;YACN,WAAW;SACZ,CAAC,CAAC;QACH,WAAW,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,CAAC;QACrC,cAAc,GAAG,eAAe,CAAC,MAAM,KAAK,SAAS,CAAC;QACtD,MAAM,IAAI,SAAS,CAAC;KACrB;IAED,eAAM,CAAC,IAAI,CACT,gBAAM,CAAC,OAAO,CACZ,UAAU,WAAW,CAAC,MAAM,mCAAmC,CAChE,CACF,CAAC;IAEF,mBAAmB;IACnB,IAAA,mBAAQ,EACN,IAAI,EACJ,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAC/B,GAAG,UAAU;QACb,UAAU,EAAE,UAAU,CAAC,UAAU;aAC9B,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;aACrD,IAAI,CAAC,GAAG,CAAC;KACb,CAAC,CAAC,CACJ,CAAC;IAEF,eAAM,CAAC,IAAI,CACT,gBAAM,CAAC,KAAK,CACV,sBAAsB,WAAW,CAAC,MAAM,yBAAyB,IAAI,GAAG,CACzE,CACF,CAAC;IAEF,OAAO,WAAW,CAAC;AACrB,CAAC;AA/ED,4DA+EC"}
@@ -0,0 +1,46 @@
1
+ import * as t from 'io-ts';
2
+ import { RequestAction } from '@transcend-io/privacy-types';
3
+ import type { Got } from 'got';
4
+ export declare const CronIdentifier: t.TypeC<{
5
+ /** The identifier value */
6
+ identifier: t.StringC;
7
+ /** The type of identifier */
8
+ type: t.StringC;
9
+ /** The core identifier of the request */
10
+ coreIdentifier: t.StringC;
11
+ /** The ID of the underlying data silo */
12
+ dataSiloId: t.StringC;
13
+ /** The ID of the underlying request */
14
+ requestId: t.StringC;
15
+ /** The request nonce */
16
+ nonce: t.StringC;
17
+ /** The time the request was created */
18
+ /** The number of days until the request is overdue */
19
+ daysUntilOverdue: t.NumberC;
20
+ /** Request attributes */
21
+ attributes: t.ArrayC<t.TypeC<{
22
+ key: t.StringC;
23
+ values: t.ArrayC<t.StringC>;
24
+ }>>;
25
+ }>;
26
+ /** Type override */
27
+ export declare type CronIdentifier = t.TypeOf<typeof CronIdentifier>;
28
+ /**
29
+ * Pull a offset of identifiers for a cron job
30
+ *
31
+ * @see https://docs.transcend.io/docs/api-reference/GET/v1/data-silo/(id)/pending-requests/(type)
32
+ * @param sombra - Sombra instance configured to make requests
33
+ * @param options - Additional options
34
+ * @returns Successfully submitted request
35
+ */
36
+ export declare function pullCronPageOfIdentifiers(sombra: Got, { dataSiloId, limit, offset, requestType, }: {
37
+ /** Data Silo ID */
38
+ dataSiloId: string;
39
+ /** Type of request */
40
+ requestType: RequestAction;
41
+ /** Number of identifiers to pull in */
42
+ limit?: number;
43
+ /** Page to pull in */
44
+ offset?: number;
45
+ }): Promise<CronIdentifier[]>;
46
+ //# sourceMappingURL=pullCronPageOfIdentifiers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pullCronPageOfIdentifiers.d.ts","sourceRoot":"","sources":["../../src/cron/pullCronPageOfIdentifiers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,OAAO,CAAC;AAE3B,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE/B,eAAO,MAAM,cAAc;IACzB,2BAA2B;;IAE3B,6BAA6B;;IAE7B,yCAAyC;;IAEzC,yCAAyC;;IAEzC,uCAAuC;;IAEvC,wBAAwB;;IAExB,uCAAuC;IAEvC,sDAAsD;;IAEtD,yBAAyB;;;;;EAOzB,CAAC;AAEH,oBAAoB;AACpB,oBAAY,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,cAAc,CAAC,CAAC;AAE7D;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,GAAG,EACX,EACE,UAAU,EACV,KAAW,EACX,MAAU,EACV,WAAW,GACZ,EAAE;IACD,mBAAmB;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB;IACtB,WAAW,EAAE,aAAa,CAAC;IAC3B,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GACA,OAAO,CAAC,cAAc,EAAE,CAAC,CAkB3B"}
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.pullCronPageOfIdentifiers = exports.CronIdentifier = void 0;
23
+ const t = __importStar(require("io-ts"));
24
+ const type_utils_1 = require("@transcend-io/type-utils");
25
+ exports.CronIdentifier = t.type({
26
+ /** The identifier value */
27
+ identifier: t.string,
28
+ /** The type of identifier */
29
+ type: t.string,
30
+ /** The core identifier of the request */
31
+ coreIdentifier: t.string,
32
+ /** The ID of the underlying data silo */
33
+ dataSiloId: t.string,
34
+ /** The ID of the underlying request */
35
+ requestId: t.string,
36
+ /** The request nonce */
37
+ nonce: t.string,
38
+ /** The time the request was created */
39
+ // requestCreatedAt: t.string, TODO
40
+ /** The number of days until the request is overdue */
41
+ daysUntilOverdue: t.number,
42
+ /** Request attributes */
43
+ attributes: t.array(t.type({
44
+ key: t.string,
45
+ values: t.array(t.string),
46
+ })),
47
+ });
48
+ /**
49
+ * Pull a offset of identifiers for a cron job
50
+ *
51
+ * @see https://docs.transcend.io/docs/api-reference/GET/v1/data-silo/(id)/pending-requests/(type)
52
+ * @param sombra - Sombra instance configured to make requests
53
+ * @param options - Additional options
54
+ * @returns Successfully submitted request
55
+ */
56
+ async function pullCronPageOfIdentifiers(sombra, { dataSiloId, limit = 100, offset = 0, requestType, }) {
57
+ // Make the GraphQL request
58
+ const response = await sombra
59
+ .get(`v1/data-silo/${dataSiloId}/pending-requests/${requestType}`, {
60
+ searchParams: {
61
+ offset,
62
+ limit,
63
+ },
64
+ })
65
+ .json();
66
+ const { items } = (0, type_utils_1.decodeCodec)(t.type({
67
+ items: t.array(exports.CronIdentifier),
68
+ }), response);
69
+ return items;
70
+ }
71
+ exports.pullCronPageOfIdentifiers = pullCronPageOfIdentifiers;
72
+ //# sourceMappingURL=pullCronPageOfIdentifiers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pullCronPageOfIdentifiers.js","sourceRoot":"","sources":["../../src/cron/pullCronPageOfIdentifiers.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,yCAA2B;AAC3B,yDAAuD;AAI1C,QAAA,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC;IACnC,2BAA2B;IAC3B,UAAU,EAAE,CAAC,CAAC,MAAM;IACpB,6BAA6B;IAC7B,IAAI,EAAE,CAAC,CAAC,MAAM;IACd,yCAAyC;IACzC,cAAc,EAAE,CAAC,CAAC,MAAM;IACxB,yCAAyC;IACzC,UAAU,EAAE,CAAC,CAAC,MAAM;IACpB,uCAAuC;IACvC,SAAS,EAAE,CAAC,CAAC,MAAM;IACnB,wBAAwB;IACxB,KAAK,EAAE,CAAC,CAAC,MAAM;IACf,uCAAuC;IACvC,mCAAmC;IACnC,sDAAsD;IACtD,gBAAgB,EAAE,CAAC,CAAC,MAAM;IAC1B,yBAAyB;IACzB,UAAU,EAAE,CAAC,CAAC,KAAK,CACjB,CAAC,CAAC,IAAI,CAAC;QACL,GAAG,EAAE,CAAC,CAAC,MAAM;QACb,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;KAC1B,CAAC,CACH;CACF,CAAC,CAAC;AAKH;;;;;;;GAOG;AACI,KAAK,UAAU,yBAAyB,CAC7C,MAAW,EACX,EACE,UAAU,EACV,KAAK,GAAG,GAAG,EACX,MAAM,GAAG,CAAC,EACV,WAAW,GAUZ;IAED,2BAA2B;IAC3B,MAAM,QAAQ,GAAG,MAAM,MAAM;SAC1B,GAAG,CAAC,gBAAgB,UAAU,qBAAqB,WAAW,EAAE,EAAE;QACjE,YAAY,EAAE;YACZ,MAAM;YACN,KAAK;SACN;KACF,CAAC;SACD,IAAI,EAAE,CAAC;IAEV,MAAM,EAAE,KAAK,EAAE,GAAG,IAAA,wBAAW,EAC3B,CAAC,CAAC,IAAI,CAAC;QACL,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,sBAAc,CAAC;KAC/B,CAAC,EACF,QAAQ,CACT,CAAC;IACF,OAAO,KAAK,CAAC;AACf,CAAC;AAnCD,8DAmCC"}
@@ -0,0 +1,9 @@
1
+ import { ObjByString } from '@transcend-io/type-utils';
2
+ /**
3
+ * Write a csv to file
4
+ *
5
+ * @param filePath - File to write out to
6
+ * @param data - Data to write
7
+ */
8
+ export declare function writeCsv(filePath: string, data: ObjByString[]): Promise<void>;
9
+ //# sourceMappingURL=writeCsv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writeCsv.d.ts","sourceRoot":"","sources":["../../src/cron/writeCsv.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD;;;;;GAKG;AACH,wBAAsB,QAAQ,CAC5B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,WAAW,EAAE,GAClB,OAAO,CAAC,IAAI,CAAC,CAaf"}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.writeCsv = void 0;
23
+ const fastcsv = __importStar(require("fast-csv"));
24
+ const fs_1 = require("fs");
25
+ /**
26
+ * Write a csv to file
27
+ *
28
+ * @param filePath - File to write out to
29
+ * @param data - Data to write
30
+ */
31
+ async function writeCsv(filePath, data) {
32
+ const ws = (0, fs_1.createWriteStream)(filePath);
33
+ await new Promise((resolve, reject) => {
34
+ try {
35
+ fastcsv
36
+ .write(data, { headers: true })
37
+ .pipe(ws)
38
+ .on('error', reject)
39
+ .on('end', () => resolve(true));
40
+ }
41
+ catch (err) {
42
+ reject(err);
43
+ }
44
+ });
45
+ }
46
+ exports.writeCsv = writeCsv;
47
+ //# sourceMappingURL=writeCsv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writeCsv.js","sourceRoot":"","sources":["../../src/cron/writeCsv.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,kDAAoC;AACpC,2BAAuC;AAIvC;;;;;GAKG;AACI,KAAK,UAAU,QAAQ,CAC5B,QAAgB,EAChB,IAAmB;IAEnB,MAAM,EAAE,GAAG,IAAA,sBAAiB,EAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACpC,IAAI;YACF,OAAO;iBACJ,KAAK,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;iBAC9B,IAAI,CAAC,EAAE,CAAC;iBACR,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;iBACnB,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;SACnC;QAAC,OAAO,GAAG,EAAE;YACZ,MAAM,CAAC,GAAG,CAAC,CAAC;SACb;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAhBD,4BAgBC"}