@devrev/ts-adaas 0.0.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +182 -116
  2. package/dist/common/constants.d.ts +10 -0
  3. package/dist/common/constants.js +27 -0
  4. package/dist/common/control-protocol.d.ts +7 -0
  5. package/dist/common/control-protocol.js +41 -0
  6. package/dist/common/helpers.d.ts +4 -0
  7. package/dist/common/helpers.js +38 -0
  8. package/dist/common/install-initial-domain-mapping.d.ts +3 -0
  9. package/dist/common/install-initial-domain-mapping.js +87 -0
  10. package/dist/{src → deprecated}/adapter/index.d.ts +10 -7
  11. package/dist/{src → deprecated}/adapter/index.js +13 -10
  12. package/dist/{src → deprecated}/common/helpers.d.ts +1 -2
  13. package/dist/deprecated/common/helpers.js +47 -0
  14. package/dist/deprecated/demo-extractor/index.d.ts +17 -0
  15. package/dist/{src → deprecated}/demo-extractor/index.js +28 -22
  16. package/dist/{src → deprecated}/uploader/index.d.ts +1 -1
  17. package/dist/{src → deprecated}/uploader/index.js +3 -1
  18. package/dist/{src/http → http}/client.d.ts +2 -1
  19. package/dist/index.d.ts +10 -0
  20. package/dist/{src/index.js → index.js} +11 -3
  21. package/dist/logger/logger.d.ts +14 -0
  22. package/dist/logger/logger.interfaces.d.ts +14 -0
  23. package/dist/logger/logger.interfaces.js +9 -0
  24. package/dist/logger/logger.js +91 -0
  25. package/dist/logger/logger.test.js +49 -0
  26. package/dist/repo/repo.d.ts +14 -0
  27. package/dist/repo/repo.interfaces.d.ts +43 -0
  28. package/dist/repo/repo.interfaces.js +2 -0
  29. package/dist/repo/repo.js +68 -0
  30. package/dist/repo/repo.test.js +74 -0
  31. package/dist/state/state.d.ts +24 -0
  32. package/dist/state/state.interfaces.d.ts +24 -0
  33. package/dist/state/state.interfaces.js +2 -0
  34. package/dist/state/state.js +115 -0
  35. package/dist/tests/test-helpers.d.ts +9 -0
  36. package/dist/tests/test-helpers.interfaces.d.ts +11 -0
  37. package/dist/tests/test-helpers.interfaces.js +2 -0
  38. package/dist/tests/test-helpers.js +88 -0
  39. package/dist/tests/test-worker.js +16 -0
  40. package/dist/types/common.d.ts +39 -0
  41. package/dist/{src/types → types}/common.js +4 -0
  42. package/dist/{src/types → types}/extraction.d.ts +56 -12
  43. package/dist/{src/types → types}/extraction.js +12 -29
  44. package/dist/types/index.d.ts +5 -0
  45. package/dist/types/index.js +11 -0
  46. package/dist/types/workers.d.ts +142 -0
  47. package/dist/types/workers.js +23 -0
  48. package/dist/uploader/uploader.d.ts +38 -0
  49. package/dist/uploader/uploader.interfaces.d.ts +63 -0
  50. package/dist/uploader/uploader.interfaces.js +2 -0
  51. package/dist/uploader/uploader.js +351 -0
  52. package/dist/{tests → uploader}/uploader.test.js +7 -5
  53. package/dist/workers/create-worker.d.ts +4 -0
  54. package/dist/workers/create-worker.js +30 -0
  55. package/dist/workers/create-worker.test.js +25 -0
  56. package/dist/workers/default-workers/attachments-deletion.d.ts +1 -0
  57. package/dist/workers/default-workers/attachments-deletion.js +13 -0
  58. package/dist/workers/default-workers/attachments-extraction.d.ts +1 -0
  59. package/dist/workers/default-workers/attachments-extraction.js +49 -0
  60. package/dist/workers/default-workers/data-deletion.d.ts +1 -0
  61. package/dist/workers/default-workers/data-deletion.js +15 -0
  62. package/dist/workers/default-workers/data-extraction.d.ts +1 -0
  63. package/dist/workers/default-workers/data-extraction.js +101 -0
  64. package/dist/workers/default-workers/external-sync-units-extraction.d.ts +1 -0
  65. package/dist/workers/default-workers/external-sync-units-extraction.js +27 -0
  66. package/dist/workers/default-workers/metadata-extraction.d.ts +1 -0
  67. package/dist/workers/default-workers/metadata-extraction.js +26 -0
  68. package/dist/workers/dummy-extractor/data-normalization.d.ts +4 -0
  69. package/dist/workers/dummy-extractor/data-normalization.js +41 -0
  70. package/dist/workers/dummy-extractor/external_domain_metadata.json +58 -0
  71. package/dist/workers/process-task.d.ts +2 -0
  72. package/dist/workers/process-task.js +44 -0
  73. package/dist/workers/spawn.d.ts +25 -0
  74. package/dist/workers/spawn.js +163 -0
  75. package/dist/workers/worker-adapter.d.ts +48 -0
  76. package/dist/workers/worker-adapter.js +138 -0
  77. package/dist/workers/worker.d.ts +1 -0
  78. package/dist/workers/worker.js +6 -0
  79. package/package.json +9 -5
  80. package/dist/src/common/constants.d.ts +0 -2
  81. package/dist/src/common/constants.js +0 -10
  82. package/dist/src/common/helpers.js +0 -59
  83. package/dist/src/common/install-initial-domain-mapping.d.ts +0 -3
  84. package/dist/src/common/install-initial-domain-mapping.js +0 -60
  85. package/dist/src/demo-extractor/index.d.ts +0 -11
  86. package/dist/src/index.d.ts +0 -6
  87. package/dist/src/logging/index.d.ts +0 -18
  88. package/dist/src/logging/index.js +0 -39
  89. package/dist/src/state/index.d.ts +0 -23
  90. package/dist/src/state/index.js +0 -111
  91. package/dist/src/types/common.d.ts +0 -37
  92. package/dist/src/types/index.d.ts +0 -2
  93. package/dist/src/types/index.js +0 -18
  94. package/dist/tests/adapter.helpers.test.js +0 -60
  95. package/dist/tests/adapter.test.js +0 -123
  96. package/dist/tests/demo-extractor.test.js +0 -61
  97. package/dist/tests/state.test.js +0 -101
  98. /package/dist/{src → deprecated}/demo-extractor/external_domain_metadata.json +0 -0
  99. /package/dist/{src/http → http}/client.js +0 -0
  100. /package/dist/{src/http → http}/constants.d.ts +0 -0
  101. /package/dist/{src/http → http}/constants.js +0 -0
  102. /package/dist/{src/http → http}/index.d.ts +0 -0
  103. /package/dist/{src/http → http}/index.js +0 -0
  104. /package/dist/{src/http → http}/types.d.ts +0 -0
  105. /package/dist/{src/http → http}/types.js +0 -0
  106. /package/dist/{tests/adapter.helpers.test.d.ts → logger/logger.test.d.ts} +0 -0
  107. /package/dist/{tests/adapter.test.d.ts → repo/repo.test.d.ts} +0 -0
  108. /package/dist/tests/{demo-extractor.test.d.ts → test-worker.d.ts} +0 -0
  109. /package/dist/{tests → uploader}/uploader.test.d.ts +0 -0
  110. /package/dist/{tests/state.test.d.ts → workers/create-worker.test.d.ts} +0 -0
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ExtractionMode = exports.ExtractorEventType = exports.EventType = exports.ErrorLevel = void 0;
4
+ // Common
5
+ var common_1 = require("./common");
6
+ Object.defineProperty(exports, "ErrorLevel", { enumerable: true, get: function () { return common_1.ErrorLevel; } });
7
+ // Extraction
8
+ var extraction_1 = require("./extraction");
9
+ Object.defineProperty(exports, "EventType", { enumerable: true, get: function () { return extraction_1.EventType; } });
10
+ Object.defineProperty(exports, "ExtractorEventType", { enumerable: true, get: function () { return extraction_1.ExtractorEventType; } });
11
+ Object.defineProperty(exports, "ExtractionMode", { enumerable: true, get: function () { return extraction_1.ExtractionMode; } });
@@ -0,0 +1,142 @@
1
+ import { Worker } from 'worker_threads';
2
+ import { MessagePort } from 'node:worker_threads';
3
+ import { State } from '../state/state';
4
+ import { WorkerAdapter } from '../workers/worker-adapter';
5
+ import { ExtractorEventType, AirdropEvent } from './extraction';
6
+ /**
7
+ * WorkerAdapterInterface is an interface for WorkerAdapter class.
8
+ * @interface WorkerAdapterInterface
9
+ * @constructor
10
+ * @param {AirdropEvent} event - The event object received from the platform
11
+ * @param {object=} initialState - The initial state of the adapter
12
+ * @param {MessagePort} parentPort - The parent port of the worker thread
13
+ * @param {WorkerAdapterInterface} options - The options to create a new instance of WorkerAdapter class
14
+ */
15
+ export interface WorkerAdapterInterface<ConnectorState> {
16
+ event: AirdropEvent;
17
+ adapterState: State<ConnectorState>;
18
+ parentPort: MessagePort;
19
+ options: WorkerAdapterOptions;
20
+ }
21
+ /**
22
+ * WorkerAdapterOptions represents the options for WorkerAdapter class.
23
+ * @interface WorkerAdapterOptions
24
+ * @constructor
25
+ * @param {boolean=} isLocalDevelopment - A flag to indicate if the adapter is being used in local development
26
+ * @param {number=} timeout - The timeout for the worker thread
27
+ */
28
+ export interface WorkerAdapterOptions {
29
+ isLocalDevelopment?: boolean;
30
+ timeout?: number;
31
+ }
32
+ export type SpawnResolve = (value: boolean | PromiseLike<boolean>) => void;
33
+ /**
34
+ * SpawnInterface is an interface for Spawn class.
35
+ * @interface SpawnInterface
36
+ * @constructor
37
+ * @param {AirdropEvent} event - The event object received from the platform
38
+ * @param {Worker} worker - The worker thread
39
+ */
40
+ export interface SpawnInterface {
41
+ event: AirdropEvent;
42
+ worker: Worker;
43
+ options: WorkerAdapterOptions | null;
44
+ resolve: SpawnResolve;
45
+ }
46
+ /**
47
+ * SpawnFactoryInterface is an interface for Spawn class factory.
48
+ * Spawn class is responsible for spawning a new worker thread and managing the lifecycle of the worker.
49
+ * The class provides utilities to emit control events to the platform and exit the worker gracefully.
50
+ * In case of lambda timeout, the class emits a lambda timeout event to the platform.
51
+ * @interface SpawnFactoryInterface
52
+ * @constructor
53
+ * @param {AirdropEvent} event - The event object received from the platform
54
+ * @param {object=} initialState - The initial state of the adapter
55
+ * @param {string} workerPath - The path to the worker file
56
+ * @param {WorkerAdapterOptions} options - The options to create a new instance of Spawn class
57
+ */
58
+ export interface SpawnFactoryInterface<ConnectorState> {
59
+ event: AirdropEvent;
60
+ initialState: ConnectorState;
61
+ workerPath?: string;
62
+ options?: WorkerAdapterOptions;
63
+ }
64
+ /**
65
+ * TaskAdapterInterface is an interface for TaskAdapter class.
66
+ * @interface TaskAdapterInterface
67
+ * @constructor
68
+ * @param {WorkerAdapter} adapter - The adapter object
69
+ */
70
+ export interface TaskAdapterInterface<ConnectorState> {
71
+ adapter: WorkerAdapter<ConnectorState>;
72
+ }
73
+ /**
74
+ * ProcessTaskInterface is an interface for ProcessTask class.
75
+ * @interface ProcessTaskInterface
76
+ * @constructor
77
+ * @param {function} task - The task to be executed, returns exit code
78
+ * @param {function} onTimeout - The task to be executed on timeout, returns exit code
79
+ */
80
+ export interface ProcessTaskInterface<ConnectorState> {
81
+ task: (params: TaskAdapterInterface<ConnectorState>) => void;
82
+ onTimeout: (params: TaskAdapterInterface<ConnectorState>) => void;
83
+ }
84
+ /**
85
+ * WorkerEvent represents the standard worker events.
86
+ */
87
+ export declare enum WorkerEvent {
88
+ WorkerMessage = "message",
89
+ WorkerOnline = "online",
90
+ WorkerError = "error",
91
+ WorkerExit = "exit"
92
+ }
93
+ /**
94
+ * WorkerMessageSubject represents the handled worker message subjects.
95
+ */
96
+ export declare enum WorkerMessageSubject {
97
+ WorkerMessageEmitted = "emit",
98
+ WorkerMessageDone = "done",
99
+ WorkerMessageExit = "exit",
100
+ WorkerMessageLog = "log"
101
+ }
102
+ /**
103
+ * WorkerMessageEmitted interface represents the structure of the emitted worker message.
104
+ */
105
+ export interface WorkerMessageEmitted {
106
+ subject: WorkerMessageSubject.WorkerMessageEmitted;
107
+ payload: {
108
+ eventType: ExtractorEventType;
109
+ };
110
+ }
111
+ /**
112
+ * WorkerMessageDone interface represents the structure of the done worker message.
113
+ */
114
+ export interface WorkerMessageDone {
115
+ subject: WorkerMessageSubject.WorkerMessageDone;
116
+ }
117
+ /**
118
+ * WorkerMessageExit interface represents the structure of the exit worker message.
119
+ */
120
+ export interface WorkerMessageExit {
121
+ subject: WorkerMessageSubject.WorkerMessageExit;
122
+ }
123
+ /**
124
+ * WorkerMessage represents the structure of the worker message.
125
+ */
126
+ export type WorkerMessage = WorkerMessageDone | WorkerMessageEmitted | WorkerMessageExit;
127
+ /**
128
+ * WorkerData represents the structure of the worker data object.
129
+ */
130
+ export interface WorkerData<ConnectorState> {
131
+ event: AirdropEvent;
132
+ initialState: ConnectorState;
133
+ workerPath: string;
134
+ options?: WorkerAdapterOptions;
135
+ }
136
+ /**
137
+ * GetWorkerPathInterface is an interface for getting the worker path.
138
+ */
139
+ export interface GetWorkerPathInterface {
140
+ event: AirdropEvent;
141
+ connectorWorkerPath?: string | null;
142
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WorkerMessageSubject = exports.WorkerEvent = void 0;
4
+ /**
5
+ * WorkerEvent represents the standard worker events.
6
+ */
7
+ var WorkerEvent;
8
+ (function (WorkerEvent) {
9
+ WorkerEvent["WorkerMessage"] = "message";
10
+ WorkerEvent["WorkerOnline"] = "online";
11
+ WorkerEvent["WorkerError"] = "error";
12
+ WorkerEvent["WorkerExit"] = "exit";
13
+ })(WorkerEvent || (exports.WorkerEvent = WorkerEvent = {}));
14
+ /**
15
+ * WorkerMessageSubject represents the handled worker message subjects.
16
+ */
17
+ var WorkerMessageSubject;
18
+ (function (WorkerMessageSubject) {
19
+ WorkerMessageSubject["WorkerMessageEmitted"] = "emit";
20
+ WorkerMessageSubject["WorkerMessageDone"] = "done";
21
+ WorkerMessageSubject["WorkerMessageExit"] = "exit";
22
+ WorkerMessageSubject["WorkerMessageLog"] = "log";
23
+ })(WorkerMessageSubject || (exports.WorkerMessageSubject = WorkerMessageSubject = {}));
@@ -0,0 +1,38 @@
1
+ import { UploadResponse, StreamAttachmentsResponse, UploaderFactoryInterface } from './uploader.interfaces';
2
+ export declare class Uploader {
3
+ private event;
4
+ private betaDevrevSdk;
5
+ private isLocalDevelopment?;
6
+ constructor({ event, options }: UploaderFactoryInterface);
7
+ /**
8
+ * Uploads the fetched objects to the DevRev platform.
9
+ * The fetched objects are uploaded to the platform and the artifact information is returned.
10
+ * @param {string} filename - The name of the file to be uploaded
11
+ * @param {string} itemType - The type of the item to be uploaded
12
+ * @param {object[] | object} fetchedObjects - The fetched objects to be uploaded
13
+ * @returns {Promise<UploadResponse>} - The response object containing the artifact information
14
+ * or error information if there was an error
15
+ */
16
+ upload(itemType: string, fetchedObjects: object[] | object): Promise<UploadResponse>;
17
+ private prepareArtifact;
18
+ private uploadToArtifact;
19
+ private streamToArtifact;
20
+ /**
21
+ * Streams the attachments to the DevRev platform.
22
+ * The attachments are streamed to the platform and the artifact information is returned.
23
+ * @param {string} attachmentsMetadataArtifactId - The artifact ID of the attachments metadata
24
+ * @returns {Promise<UploadResponse>} - The response object containing the ssoAttachment artifact information
25
+ * or error information if there was an error
26
+ */
27
+ streamAttachments({ attachmentsMetadataArtifactId, }: {
28
+ attachmentsMetadataArtifactId: string;
29
+ }): Promise<StreamAttachmentsResponse>;
30
+ private getArtifactDownloadUrl;
31
+ private downloadArtifact;
32
+ private compressGzip;
33
+ private decompressGzip;
34
+ private parseJsonl;
35
+ private stream;
36
+ private getFileStreamResponse;
37
+ private downloadToLocal;
38
+ }
@@ -0,0 +1,63 @@
1
+ import { AirdropEvent } from '../types/extraction';
2
+ import { WorkerAdapterOptions } from '../types/workers';
3
+ import { ErrorRecord } from '../types/common';
4
+ export interface UploaderFactoryInterface {
5
+ event: AirdropEvent;
6
+ options?: WorkerAdapterOptions;
7
+ }
8
+ /**
9
+ * Artifact is an interface that defines the structure of an artifact. Artifact is a file that is generated by the extractor and uploaded to ADaaS.
10
+ */
11
+ export interface Artifact {
12
+ id: string;
13
+ item_type: string;
14
+ item_count: number;
15
+ }
16
+ /**
17
+ * ArtifactsPrepareResponse is an interface that defines the structure of the response from the prepare artifacts endpoint.
18
+ * @deprecated
19
+ */
20
+ export interface ArtifactsPrepareResponse {
21
+ url: string;
22
+ id: string;
23
+ form_data: {
24
+ key: string;
25
+ value: string;
26
+ }[];
27
+ }
28
+ /**
29
+ * UploadResponse is an interface that defines the structure of the response from upload through Uploader.
30
+ */
31
+ export interface UploadResponse {
32
+ artifact?: Artifact;
33
+ error?: ErrorRecord;
34
+ }
35
+ /**
36
+ * StreamAttachmentsResponse is an interface that defines the structure of the response from the stream attachments through Uploader.
37
+ */
38
+ export interface StreamAttachmentsResponse {
39
+ ssorAttachments?: SsorAttachment[];
40
+ error?: ErrorRecord;
41
+ }
42
+ /**
43
+ * StreamResponse is an interface that defines the structure of the response from the stream of single attachment through Uploader.
44
+ */
45
+ export interface StreamResponse {
46
+ ssorAttachment?: SsorAttachment;
47
+ error?: ErrorRecord;
48
+ }
49
+ /**
50
+ * SsorAttachment is an interface that defines the structure of the SSOR attachment.
51
+ */
52
+ export interface SsorAttachment {
53
+ id: {
54
+ devrev: string;
55
+ external: string;
56
+ };
57
+ parent_id: {
58
+ external: string;
59
+ };
60
+ actor_id: {
61
+ external: string;
62
+ };
63
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,351 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.Uploader = void 0;
30
+ const axios_1 = __importDefault(require("axios"));
31
+ const fs_1 = __importStar(require("fs"));
32
+ const zlib_1 = __importDefault(require("zlib"));
33
+ const js_jsonl_1 = require("js-jsonl");
34
+ const form_data_1 = __importDefault(require("form-data"));
35
+ const typescript_sdk_1 = require("@devrev/typescript-sdk");
36
+ const constants_1 = require("../common/constants");
37
+ const logger_1 = require("../logger/logger");
38
+ class Uploader {
39
+ constructor({ event, options }) {
40
+ this.event = event;
41
+ this.betaDevrevSdk = typescript_sdk_1.client.setupBeta({
42
+ endpoint: event.execution_metadata.devrev_endpoint,
43
+ token: event.context.secrets.service_account_token,
44
+ });
45
+ this.isLocalDevelopment = options === null || options === void 0 ? void 0 : options.isLocalDevelopment;
46
+ }
47
+ /**
48
+ * Uploads the fetched objects to the DevRev platform.
49
+ * The fetched objects are uploaded to the platform and the artifact information is returned.
50
+ * @param {string} filename - The name of the file to be uploaded
51
+ * @param {string} itemType - The type of the item to be uploaded
52
+ * @param {object[] | object} fetchedObjects - The fetched objects to be uploaded
53
+ * @returns {Promise<UploadResponse>} - The response object containing the artifact information
54
+ * or error information if there was an error
55
+ */
56
+ async upload(itemType, fetchedObjects) {
57
+ if (this.isLocalDevelopment) {
58
+ this.downloadToLocal(itemType, fetchedObjects);
59
+ }
60
+ // 1. Compress the fetched objects to a gzipped jsonl object
61
+ const file = await this.compressGzip(js_jsonl_1.jsonl.stringify(fetchedObjects));
62
+ if (!file) {
63
+ return {
64
+ error: { message: 'Error while compressing jsonl object.' },
65
+ };
66
+ }
67
+ const filename = itemType + '.jsonl.gz';
68
+ const fileType = 'application/x-gzip';
69
+ // 2. Prepare the artifact for uploading
70
+ const preparedArtifact = await this.prepareArtifact(filename, fileType);
71
+ if (!preparedArtifact) {
72
+ return {
73
+ error: { message: 'Error while preparing artifact.' },
74
+ };
75
+ }
76
+ // 3. Upload the file to the prepared artifact
77
+ const uploadedArtifact = await this.uploadToArtifact(preparedArtifact, file);
78
+ if (!uploadedArtifact) {
79
+ return {
80
+ error: { message: 'Error while uploading artifact.' },
81
+ };
82
+ }
83
+ // 4. Return the artifact information to the platform
84
+ const artifact = {
85
+ id: preparedArtifact.id,
86
+ item_type: itemType,
87
+ item_count: Array.isArray(fetchedObjects) ? fetchedObjects.length : 1,
88
+ };
89
+ console.log('Successful upload of artifact: ', artifact);
90
+ return { artifact };
91
+ }
92
+ async prepareArtifact(filename, fileType) {
93
+ try {
94
+ const response = await this.betaDevrevSdk.artifactsPrepare({
95
+ file_name: filename,
96
+ file_type: fileType,
97
+ });
98
+ return response.data;
99
+ }
100
+ catch (error) {
101
+ if (axios_1.default.isAxiosError(error)) {
102
+ console.error('Error while preparing artifact.', (0, logger_1.formatAxiosError)(error));
103
+ }
104
+ else {
105
+ console.error('Error while preparing artifact.', error);
106
+ }
107
+ }
108
+ }
109
+ async uploadToArtifact(preparedArtifact, file
110
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
111
+ ) {
112
+ const formData = new form_data_1.default();
113
+ for (const field of preparedArtifact.form_data) {
114
+ formData.append(field.key, field.value);
115
+ }
116
+ formData.append('file', file);
117
+ try {
118
+ const response = await axios_1.default.post(preparedArtifact.url, formData, {
119
+ headers: Object.assign({}, formData.getHeaders()),
120
+ });
121
+ return response;
122
+ }
123
+ catch (error) {
124
+ if (axios_1.default.isAxiosError(error)) {
125
+ console.error('Error while uploading artifact.', (0, logger_1.formatAxiosError)(error));
126
+ }
127
+ else {
128
+ console.error('Error while uploading artifact.', error);
129
+ }
130
+ }
131
+ }
132
+ async streamToArtifact(preparedArtifact,
133
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
134
+ fileStreamResponse) {
135
+ const formData = new form_data_1.default();
136
+ for (const field of preparedArtifact.form_data) {
137
+ formData.append(field.key, field.value);
138
+ }
139
+ formData.append('file', fileStreamResponse.data);
140
+ try {
141
+ const response = await axios_1.default.post(preparedArtifact.url, formData, {
142
+ headers: Object.assign(Object.assign({}, formData.getHeaders()), (!fileStreamResponse.headers['content-length'] && {
143
+ 'Content-Length': constants_1.MAX_DEVREV_ARTIFACT_SIZE,
144
+ })),
145
+ });
146
+ return response;
147
+ }
148
+ catch (error) {
149
+ if (axios_1.default.isAxiosError(error)) {
150
+ console.error('Error while streaming artifact.', (0, logger_1.formatAxiosError)(error));
151
+ }
152
+ else {
153
+ console.error('Error while streaming artifact.', error);
154
+ }
155
+ return;
156
+ }
157
+ }
158
+ /**
159
+ * Streams the attachments to the DevRev platform.
160
+ * The attachments are streamed to the platform and the artifact information is returned.
161
+ * @param {string} attachmentsMetadataArtifactId - The artifact ID of the attachments metadata
162
+ * @returns {Promise<UploadResponse>} - The response object containing the ssoAttachment artifact information
163
+ * or error information if there was an error
164
+ */
165
+ async streamAttachments({ attachmentsMetadataArtifactId, }) {
166
+ console.log('Started streaming attachments to the platform.');
167
+ // 1. Get the URL of the attachments metadata artifact
168
+ const artifactUrl = await this.getArtifactDownloadUrl(attachmentsMetadataArtifactId);
169
+ if (!artifactUrl) {
170
+ return {
171
+ error: { message: 'Error while getting artifact download URL.' },
172
+ };
173
+ }
174
+ // 2. Download artifact from the URL
175
+ const gzippedJsonlObject = await this.downloadArtifact(artifactUrl);
176
+ if (!gzippedJsonlObject) {
177
+ return {
178
+ error: { message: 'Error while downloading gzipped jsonl object.' },
179
+ };
180
+ }
181
+ // 3. Decompress the gzipped jsonl object
182
+ const jsonlObject = await this.decompressGzip(gzippedJsonlObject);
183
+ if (!jsonlObject) {
184
+ return {
185
+ error: { message: 'Error while decompressing gzipped jsonl object.' },
186
+ };
187
+ }
188
+ // 4. Parse the jsonl object to get the attachment metadata
189
+ const jsonObject = (await this.parseJsonl(jsonlObject));
190
+ if (!jsonObject) {
191
+ return {
192
+ error: { message: 'Error while parsing jsonl object.' },
193
+ };
194
+ }
195
+ // 5. Stream each attachment to the platform, and push the ssorAttachment to the ssorAttachments array
196
+ const ssorAttachments = [];
197
+ for (const attachmentMetadata of jsonObject) {
198
+ const { ssorAttachment, error } = await this.stream(attachmentMetadata);
199
+ if (error || !ssorAttachment) {
200
+ console.warn('Error while streaming attachment', error);
201
+ continue;
202
+ }
203
+ ssorAttachments.push(ssorAttachment);
204
+ }
205
+ if (!ssorAttachments.length) {
206
+ console.warn('No attachments were streamed to the platform.');
207
+ return {
208
+ error: { message: 'No attachments were streamed to the platform.' },
209
+ };
210
+ }
211
+ return { ssorAttachments };
212
+ }
213
+ async getArtifactDownloadUrl(artifactId) {
214
+ try {
215
+ const response = await this.betaDevrevSdk.artifactsLocate({
216
+ id: artifactId,
217
+ });
218
+ return response.data.url;
219
+ }
220
+ catch (error) {
221
+ console.error('Error while getting artifact download URL.', error);
222
+ }
223
+ }
224
+ async downloadArtifact(artifactUrl) {
225
+ try {
226
+ const response = await axios_1.default.get(artifactUrl, {
227
+ responseType: 'arraybuffer',
228
+ });
229
+ return response.data;
230
+ }
231
+ catch (error) {
232
+ if (axios_1.default.isAxiosError(error)) {
233
+ console.error('Error while downloading artifact from URL.', (0, logger_1.formatAxiosError)(error));
234
+ }
235
+ else {
236
+ console.error('Error while downloading artifact from URL.', error);
237
+ }
238
+ }
239
+ }
240
+ async compressGzip(jsonlObject) {
241
+ try {
242
+ return zlib_1.default.gzipSync(jsonlObject);
243
+ }
244
+ catch (error) {
245
+ console.error('Error while compressing jsonl object.', error);
246
+ }
247
+ }
248
+ async decompressGzip(gzippedJsonlObject) {
249
+ try {
250
+ const jsonlObject = await zlib_1.default.gunzipSync(gzippedJsonlObject);
251
+ return jsonlObject.toString();
252
+ }
253
+ catch (error) {
254
+ console.error('Error while decompressing gzipped jsonl object.', error);
255
+ }
256
+ }
257
+ async parseJsonl(jsonlObject) {
258
+ try {
259
+ return js_jsonl_1.jsonl.parse(jsonlObject);
260
+ }
261
+ catch (error) {
262
+ console.error('Error while parsing jsonl object.', error);
263
+ }
264
+ }
265
+ async stream(attachmentMetadata) {
266
+ var _a;
267
+ const { id: externalId, file_name: filename, url, parent_id: parentId, author_id: actorId, } = attachmentMetadata;
268
+ const fileStreamResponse = await this.getFileStreamResponse(url);
269
+ if (!fileStreamResponse) {
270
+ return {
271
+ error: { message: 'Error while fetching attachment from URL' },
272
+ };
273
+ }
274
+ const fileType = ((_a = fileStreamResponse.headers) === null || _a === void 0 ? void 0 : _a['content-type']) ||
275
+ 'application/octet-stream';
276
+ const preparedArtifact = await this.prepareArtifact(filename, fileType);
277
+ if (!preparedArtifact) {
278
+ return {
279
+ error: { message: 'Error while preparing artifact.' },
280
+ };
281
+ }
282
+ const uploadedArtifact = await this.streamToArtifact(preparedArtifact, fileStreamResponse);
283
+ if (!uploadedArtifact) {
284
+ return {
285
+ error: { message: 'Error while streaming artifact.' },
286
+ };
287
+ }
288
+ const ssorAttachment = {
289
+ id: {
290
+ devrev: preparedArtifact.id,
291
+ external: externalId,
292
+ },
293
+ parent_id: {
294
+ external: parentId,
295
+ },
296
+ actor_id: {
297
+ external: actorId,
298
+ },
299
+ };
300
+ console.log('Successful stream of attachment: ', ssorAttachment);
301
+ return { ssorAttachment };
302
+ }
303
+ async getFileStreamResponse(url) {
304
+ try {
305
+ const fileStreamResponse = await axios_1.default.get(url, {
306
+ responseType: 'stream',
307
+ headers: {
308
+ Authorization: this.event.payload.connection_data.key,
309
+ },
310
+ });
311
+ return fileStreamResponse;
312
+ }
313
+ catch (error) {
314
+ if (axios_1.default.isAxiosError(error)) {
315
+ console.error('Error while fetching attachment from URL.', (0, logger_1.formatAxiosError)(error));
316
+ }
317
+ else {
318
+ console.error('Error while fetching attachment from URL.', error);
319
+ }
320
+ }
321
+ }
322
+ async downloadToLocal(itemType, fetchedObjects) {
323
+ console.log(`Downloading ${itemType} to local file system.`);
324
+ try {
325
+ if (!fs_1.default.existsSync('extracted_files')) {
326
+ fs_1.default.mkdirSync('extracted_files');
327
+ }
328
+ const timestamp = new Date().getTime();
329
+ const filePath = `extracted_files/extractor_${itemType}_${timestamp}.${itemType === 'external_domain_metadata' ? 'json' : 'jsonl'}`;
330
+ const fileHandle = await fs_1.promises.open(filePath, 'w');
331
+ let objArray = [];
332
+ if (!Array.isArray(fetchedObjects)) {
333
+ objArray.push(fetchedObjects);
334
+ }
335
+ else {
336
+ objArray = fetchedObjects;
337
+ }
338
+ for (const jsonObject of objArray) {
339
+ const jsonLine = JSON.stringify(jsonObject) + '\n';
340
+ await fileHandle.write(jsonLine);
341
+ }
342
+ await fileHandle.close();
343
+ console.log('Data successfully written to', filePath);
344
+ }
345
+ catch (error) {
346
+ console.error('Error writing data to file.', error);
347
+ return Promise.reject(error);
348
+ }
349
+ }
350
+ }
351
+ exports.Uploader = Uploader;
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const uploader_1 = require("../src/uploader");
3
+ const test_helpers_1 = require("../tests/test-helpers");
4
+ const types_1 = require("../types");
5
+ const uploader_1 = require("./uploader");
4
6
  // mock uploader.upload method
5
- jest.mock('../src/uploader', () => {
7
+ jest.mock('./uploader', () => {
6
8
  return {
7
9
  Uploader: jest.fn().mockImplementation(() => {
8
10
  return {
@@ -15,12 +17,12 @@ jest.mock('../src/uploader', () => {
15
17
  };
16
18
  });
17
19
  describe('uploader.ts', () => {
18
- const uploader = new uploader_1.Uploader('https://example.com', 'test-token', false);
20
+ const mockEvent = (0, test_helpers_1.createEvent)({ eventType: types_1.EventType.ExtractionDataStart });
21
+ const uploader = new uploader_1.Uploader({ event: mockEvent });
19
22
  it('should upload the file to the DevRev platform and return the artifact information', async () => {
20
- const filename = 'filename';
21
23
  const entity = 'entity';
22
24
  const fetchedObjects = [{ key: 'value' }];
23
- const uploadResponse = await uploader.upload(filename, entity, fetchedObjects);
25
+ const uploadResponse = await uploader.upload(entity, fetchedObjects);
24
26
  expect(uploadResponse).toEqual({
25
27
  artifact: { key: 'value' },
26
28
  error: undefined,
@@ -0,0 +1,4 @@
1
+ import { Worker } from 'node:worker_threads';
2
+ import { WorkerData } from '../types/workers';
3
+ declare function createWorker<ConnectorState>(workerData: WorkerData<ConnectorState>): Promise<Worker>;
4
+ export { createWorker };