@devrev/ts-adaas 0.0.2 → 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 (111) hide show
  1. package/README.md +186 -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/external_domain_metadata.json +38 -0
  15. package/dist/deprecated/demo-extractor/index.d.ts +17 -0
  16. package/dist/deprecated/demo-extractor/index.js +161 -0
  17. package/dist/{src → deprecated}/uploader/index.d.ts +1 -1
  18. package/dist/{src → deprecated}/uploader/index.js +3 -1
  19. package/dist/{src/http → http}/client.d.ts +2 -1
  20. package/dist/index.d.ts +10 -0
  21. package/dist/index.js +30 -0
  22. package/dist/logger/logger.d.ts +14 -0
  23. package/dist/logger/logger.interfaces.d.ts +14 -0
  24. package/dist/logger/logger.interfaces.js +9 -0
  25. package/dist/logger/logger.js +91 -0
  26. package/dist/logger/logger.test.js +49 -0
  27. package/dist/repo/repo.d.ts +14 -0
  28. package/dist/repo/repo.interfaces.d.ts +43 -0
  29. package/dist/repo/repo.interfaces.js +2 -0
  30. package/dist/repo/repo.js +68 -0
  31. package/dist/repo/repo.test.js +74 -0
  32. package/dist/state/state.d.ts +24 -0
  33. package/dist/state/state.interfaces.d.ts +24 -0
  34. package/dist/state/state.interfaces.js +2 -0
  35. package/dist/state/state.js +115 -0
  36. package/dist/tests/test-helpers.d.ts +9 -0
  37. package/dist/tests/test-helpers.interfaces.d.ts +11 -0
  38. package/dist/tests/test-helpers.interfaces.js +2 -0
  39. package/dist/tests/test-helpers.js +88 -0
  40. package/dist/tests/test-worker.js +16 -0
  41. package/dist/types/common.d.ts +39 -0
  42. package/dist/{src/types → types}/common.js +4 -0
  43. package/dist/{src/types → types}/extraction.d.ts +57 -12
  44. package/dist/{src/types → types}/extraction.js +12 -29
  45. package/dist/types/index.d.ts +5 -0
  46. package/dist/types/index.js +11 -0
  47. package/dist/types/workers.d.ts +142 -0
  48. package/dist/types/workers.js +23 -0
  49. package/dist/uploader/uploader.d.ts +38 -0
  50. package/dist/uploader/uploader.interfaces.d.ts +63 -0
  51. package/dist/uploader/uploader.interfaces.js +2 -0
  52. package/dist/uploader/uploader.js +351 -0
  53. package/dist/{tests → uploader}/uploader.test.js +7 -5
  54. package/dist/workers/create-worker.d.ts +4 -0
  55. package/dist/workers/create-worker.js +30 -0
  56. package/dist/workers/create-worker.test.js +25 -0
  57. package/dist/workers/default-workers/attachments-deletion.d.ts +1 -0
  58. package/dist/workers/default-workers/attachments-deletion.js +13 -0
  59. package/dist/workers/default-workers/attachments-extraction.d.ts +1 -0
  60. package/dist/workers/default-workers/attachments-extraction.js +49 -0
  61. package/dist/workers/default-workers/data-deletion.d.ts +1 -0
  62. package/dist/workers/default-workers/data-deletion.js +15 -0
  63. package/dist/workers/default-workers/data-extraction.d.ts +1 -0
  64. package/dist/workers/default-workers/data-extraction.js +101 -0
  65. package/dist/workers/default-workers/external-sync-units-extraction.d.ts +1 -0
  66. package/dist/workers/default-workers/external-sync-units-extraction.js +27 -0
  67. package/dist/workers/default-workers/metadata-extraction.d.ts +1 -0
  68. package/dist/workers/default-workers/metadata-extraction.js +26 -0
  69. package/dist/workers/dummy-extractor/data-normalization.d.ts +4 -0
  70. package/dist/workers/dummy-extractor/data-normalization.js +41 -0
  71. package/dist/workers/dummy-extractor/external_domain_metadata.json +58 -0
  72. package/dist/workers/process-task.d.ts +2 -0
  73. package/dist/workers/process-task.js +44 -0
  74. package/dist/workers/spawn.d.ts +25 -0
  75. package/dist/workers/spawn.js +163 -0
  76. package/dist/workers/worker-adapter.d.ts +48 -0
  77. package/dist/workers/worker-adapter.js +138 -0
  78. package/dist/workers/worker.d.ts +1 -0
  79. package/dist/workers/worker.js +6 -0
  80. package/package.json +9 -5
  81. package/dist/src/common/constants.d.ts +0 -2
  82. package/dist/src/common/constants.js +0 -10
  83. package/dist/src/common/helpers.js +0 -59
  84. package/dist/src/demo-extractor/index.d.ts +0 -11
  85. package/dist/src/demo-extractor/index.js +0 -157
  86. package/dist/src/demo-extractor/initial_domain_mapping.json +0 -107
  87. package/dist/src/index.d.ts +0 -5
  88. package/dist/src/index.js +0 -21
  89. package/dist/src/logging/index.d.ts +0 -18
  90. package/dist/src/logging/index.js +0 -39
  91. package/dist/src/state/index.d.ts +0 -23
  92. package/dist/src/state/index.js +0 -111
  93. package/dist/src/types/common.d.ts +0 -33
  94. package/dist/src/types/index.d.ts +0 -2
  95. package/dist/src/types/index.js +0 -18
  96. package/dist/tests/adapter.helpers.test.js +0 -60
  97. package/dist/tests/adapter.test.js +0 -122
  98. package/dist/tests/demo-extractor.test.js +0 -60
  99. package/dist/tests/state.test.js +0 -100
  100. /package/dist/{src/http → http}/client.js +0 -0
  101. /package/dist/{src/http → http}/constants.d.ts +0 -0
  102. /package/dist/{src/http → http}/constants.js +0 -0
  103. /package/dist/{src/http → http}/index.d.ts +0 -0
  104. /package/dist/{src/http → http}/index.js +0 -0
  105. /package/dist/{src/http → http}/types.d.ts +0 -0
  106. /package/dist/{src/http → http}/types.js +0 -0
  107. /package/dist/{tests/adapter.helpers.test.d.ts → logger/logger.test.d.ts} +0 -0
  108. /package/dist/{tests/adapter.test.d.ts → repo/repo.test.d.ts} +0 -0
  109. /package/dist/tests/{demo-extractor.test.d.ts → test-worker.d.ts} +0 -0
  110. /package/dist/{tests → uploader}/uploader.test.d.ts +0 -0
  111. /package/dist/{tests/state.test.d.ts → workers/create-worker.test.d.ts} +0 -0
@@ -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 };
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createWorker = createWorker;
4
+ const node_worker_threads_1 = require("node:worker_threads");
5
+ const workers_1 = require("../types/workers");
6
+ const logger_1 = require("../logger/logger");
7
+ async function createWorker(workerData) {
8
+ return new Promise((resolve, reject) => {
9
+ if (node_worker_threads_1.isMainThread) {
10
+ const logger = new logger_1.Logger(workerData.event);
11
+ const workerFile = __dirname + '/worker.js';
12
+ const worker = new node_worker_threads_1.Worker(workerFile, {
13
+ workerData,
14
+ });
15
+ worker.on(workers_1.WorkerEvent.WorkerError, (error) => {
16
+ logger.error('Worker error', error);
17
+ reject(error);
18
+ });
19
+ worker.on(workers_1.WorkerEvent.WorkerOnline, () => {
20
+ resolve(worker);
21
+ logger.info('Worker is online. Started processing the task with event type: ' +
22
+ workerData.event.payload.event_type +
23
+ '.');
24
+ });
25
+ }
26
+ else {
27
+ reject(new Error('Worker threads can not start more worker threads.'));
28
+ }
29
+ });
30
+ }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const worker_threads_1 = require("worker_threads");
4
+ const test_helpers_1 = require("../tests/test-helpers");
5
+ const extraction_1 = require("../types/extraction");
6
+ const create_worker_1 = require("./create-worker");
7
+ describe('createWorker function', () => {
8
+ it('should return a Worker instance when a valid worker script is found', async () => {
9
+ const workerPath = __dirname + '../tests/dummy-worker.ts';
10
+ const worker = worker_threads_1.isMainThread
11
+ ? await (0, create_worker_1.createWorker)({
12
+ event: (0, test_helpers_1.createEvent)({
13
+ eventType: extraction_1.EventType.ExtractionExternalSyncUnitsStart,
14
+ }),
15
+ initialState: {},
16
+ workerPath,
17
+ })
18
+ : null;
19
+ expect(worker).not.toBeNull();
20
+ expect(worker).toBeInstanceOf(worker_threads_1.Worker);
21
+ if (worker) {
22
+ await worker.terminate();
23
+ }
24
+ });
25
+ });
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("../../index");
4
+ (0, index_1.processTask)({
5
+ task: async ({ adapter }) => {
6
+ await adapter.emit(index_1.ExtractorEventType.ExtractionAttachmentsDeleteDone);
7
+ },
8
+ onTimeout: async ({ adapter }) => {
9
+ await adapter.emit(index_1.ExtractorEventType.ExtractionAttachmentsDeleteError, {
10
+ error: { message: 'Failed to delete attachments. Lambda timeout.' },
11
+ });
12
+ },
13
+ });
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("../../index");
4
+ const uploader_1 = require("../../uploader/uploader");
5
+ const repos = [
6
+ {
7
+ itemType: 'ssor_attachment',
8
+ },
9
+ ];
10
+ (0, index_1.processTask)({
11
+ task: async ({ adapter }) => {
12
+ var _a, _b, _c, _d, _e;
13
+ if (!((_a = adapter.state.toDevRev) === null || _a === void 0 ? void 0 : _a.attachmentsMetadata.artifactIds) ||
14
+ adapter.state.toDevRev.attachmentsMetadata.artifactIds.length === 0) {
15
+ console.log('No attachments to extract, skipping.');
16
+ await adapter.emit(index_1.ExtractorEventType.ExtractionAttachmentsDone);
17
+ return;
18
+ }
19
+ adapter.initializeRepos(repos);
20
+ const uploader = new uploader_1.Uploader({
21
+ event: adapter.event,
22
+ options: adapter.options,
23
+ });
24
+ for (const attachmentsMetadataArtifactId of (_b = adapter.state.toDevRev) === null || _b === void 0 ? void 0 : _b.attachmentsMetadata.artifactIds) {
25
+ const { ssorAttachments, error } = await uploader.streamAttachments({
26
+ attachmentsMetadataArtifactId,
27
+ });
28
+ if (error || !ssorAttachments) {
29
+ await adapter.emit(index_1.ExtractorEventType.ExtractionAttachmentsError, {
30
+ error,
31
+ });
32
+ return;
33
+ }
34
+ await ((_c = adapter.getRepo('ssor_attachment')) === null || _c === void 0 ? void 0 : _c.push(ssorAttachments));
35
+ (_d = adapter.state.toDevRev) === null || _d === void 0 ? void 0 : _d.attachmentsMetadata.artifactIds.shift();
36
+ adapter.state.toDevRev.attachmentsMetadata.lastProcessed = 0;
37
+ if (((_e = adapter.state.toDevRev) === null || _e === void 0 ? void 0 : _e.attachmentsMetadata.artifactIds.length) === 0) {
38
+ break;
39
+ }
40
+ }
41
+ await adapter.emit(index_1.ExtractorEventType.ExtractionAttachmentsDone);
42
+ },
43
+ onTimeout: async ({ adapter }) => {
44
+ await adapter.postState();
45
+ await adapter.emit(index_1.ExtractorEventType.ExtractionAttachmentsProgress, {
46
+ progress: 50,
47
+ });
48
+ },
49
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("../../index");
4
+ (0, index_1.processTask)({
5
+ task: async ({ adapter }) => {
6
+ await adapter.emit(index_1.ExtractorEventType.ExtractionDataDeleteDone);
7
+ },
8
+ onTimeout: async ({ adapter }) => {
9
+ await adapter.emit(index_1.ExtractorEventType.ExtractionDataDeleteError, {
10
+ error: {
11
+ message: 'Failed to delete data. Lambda timeout.',
12
+ },
13
+ });
14
+ },
15
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("../../index");
4
+ const data_normalization_1 = require("../dummy-extractor/data-normalization");
5
+ // Dummy data that originally would be fetched from an external source
6
+ const issues = [
7
+ {
8
+ id: 'issue-1',
9
+ created_date: '1999-12-25T01:00:03+01:00',
10
+ modified_date: '1999-12-25T01:00:03+01:00',
11
+ body: '<p>This is issue 1</p>',
12
+ creator: 'user-1',
13
+ owner: 'user-1',
14
+ title: 'Issue 1',
15
+ },
16
+ {
17
+ id: 'issue-2',
18
+ created_date: '1999-12-27T15:31:34+01:00',
19
+ modified_date: '2002-04-09T01:55:31+02:00',
20
+ body: '<p>This is issue 2</p>',
21
+ creator: 'user-2',
22
+ owner: 'user-2',
23
+ title: 'Issue 2',
24
+ },
25
+ ];
26
+ const users = [
27
+ {
28
+ id: 'user-1',
29
+ created_date: '1999-12-25T01:00:03+01:00',
30
+ modified_date: '1999-12-25T01:00:03+01:00',
31
+ data: {
32
+ email: 'johndoe@test.com',
33
+ name: 'John Doe',
34
+ },
35
+ },
36
+ {
37
+ id: 'user-2',
38
+ created_date: '1999-12-27T15:31:34+01:00',
39
+ modified_date: '2002-04-09T01:55:31+02:00',
40
+ data: {
41
+ email: 'janedoe@test.com',
42
+ name: 'Jane Doe',
43
+ },
44
+ },
45
+ ];
46
+ const attachments = [
47
+ {
48
+ url: 'https://app.dev.devrev-eng.ai/favicon.ico',
49
+ id: 'attachment-1',
50
+ file_name: 'dummy.jpg',
51
+ author_id: 'user-1',
52
+ parent_id: 'issue-1',
53
+ },
54
+ {
55
+ url: 'https://app.dev.devrev-eng.ai/favicon.ico',
56
+ id: 'attachment-2',
57
+ file_name: 'dummy.ico',
58
+ author_id: 'user-2',
59
+ parent_id: 'issue-2',
60
+ },
61
+ ];
62
+ const repos = [
63
+ {
64
+ itemType: 'issues',
65
+ normalize: data_normalization_1.normalizeIssue,
66
+ },
67
+ {
68
+ itemType: 'users',
69
+ normalize: data_normalization_1.normalizeUser,
70
+ },
71
+ {
72
+ itemType: 'attachments',
73
+ normalize: data_normalization_1.normalizeAttachment,
74
+ },
75
+ ];
76
+ (0, index_1.processTask)({
77
+ task: async ({ adapter }) => {
78
+ var _a, _b, _c;
79
+ console.log('Logging something from worker thread', {});
80
+ adapter.initializeRepos(repos);
81
+ if (adapter.event.payload.event_type === index_1.EventType.ExtractionDataStart) {
82
+ await ((_a = adapter.getRepo('issues')) === null || _a === void 0 ? void 0 : _a.push(issues));
83
+ await adapter.emit(index_1.ExtractorEventType.ExtractionDataProgress, {
84
+ progress: 50,
85
+ });
86
+ }
87
+ else {
88
+ await ((_b = adapter.getRepo('users')) === null || _b === void 0 ? void 0 : _b.push(users));
89
+ await ((_c = adapter.getRepo('attachments')) === null || _c === void 0 ? void 0 : _c.push(attachments));
90
+ await adapter.emit(index_1.ExtractorEventType.ExtractionDataDone, {
91
+ progress: 100,
92
+ });
93
+ }
94
+ },
95
+ onTimeout: async ({ adapter }) => {
96
+ await adapter.postState();
97
+ await adapter.emit(index_1.ExtractorEventType.ExtractionDataProgress, {
98
+ progress: 50,
99
+ });
100
+ },
101
+ });
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("../../index");
4
+ // Dummy data that originally would be fetched from an external source
5
+ const externalSyncUnits = [
6
+ {
7
+ id: 'devrev',
8
+ name: 'devrev',
9
+ description: 'Demo external sync unit',
10
+ item_count: 2,
11
+ item_type: 'issues',
12
+ },
13
+ ];
14
+ (0, index_1.processTask)({
15
+ task: async ({ adapter }) => {
16
+ await adapter.emit(index_1.ExtractorEventType.ExtractionExternalSyncUnitsDone, {
17
+ external_sync_units: externalSyncUnits,
18
+ });
19
+ },
20
+ onTimeout: async ({ adapter }) => {
21
+ await adapter.emit(index_1.ExtractorEventType.ExtractionExternalSyncUnitsError, {
22
+ error: {
23
+ message: 'Failed to extract external sync units. Lambda timeout.',
24
+ },
25
+ });
26
+ },
27
+ });