@devrev/airsync-sdk 2.0.0-beta.2 → 2.0.0-beta.3

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 (89) hide show
  1. package/dist/airsync-sdk.d.ts +414 -157
  2. package/dist/attachments-streaming/attachments-streaming-pool.d.ts +2 -1
  3. package/dist/attachments-streaming/attachments-streaming-pool.d.ts.map +1 -1
  4. package/dist/attachments-streaming/attachments-streaming-pool.interfaces.d.ts +8 -2
  5. package/dist/attachments-streaming/attachments-streaming-pool.interfaces.d.ts.map +1 -1
  6. package/dist/attachments-streaming/attachments-streaming-pool.js +14 -14
  7. package/dist/attachments-streaming/attachments-streaming-pool.test.js +47 -23
  8. package/dist/common/time-value-resolver.d.ts +2 -2
  9. package/dist/common/time-value-resolver.d.ts.map +1 -1
  10. package/dist/index.d.ts +3 -2
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +7 -4
  13. package/dist/multithreading/adapters/base-adapter.d.ts +56 -0
  14. package/dist/multithreading/adapters/base-adapter.d.ts.map +1 -0
  15. package/dist/multithreading/adapters/base-adapter.emit.test.d.ts +2 -0
  16. package/dist/multithreading/adapters/base-adapter.emit.test.d.ts.map +1 -0
  17. package/dist/multithreading/{worker-adapter/worker-adapter.emit.test.js → adapters/base-adapter.emit.test.js} +66 -53
  18. package/dist/multithreading/adapters/base-adapter.js +105 -0
  19. package/dist/multithreading/adapters/extraction-adapter.artifacts.test.d.ts +2 -0
  20. package/dist/multithreading/adapters/extraction-adapter.artifacts.test.d.ts.map +1 -0
  21. package/dist/multithreading/{worker-adapter/worker-adapter.artifacts.test.js → adapters/extraction-adapter.artifacts.test.js} +6 -6
  22. package/dist/multithreading/adapters/extraction-adapter.d.ts +58 -0
  23. package/dist/multithreading/adapters/extraction-adapter.d.ts.map +1 -0
  24. package/dist/multithreading/adapters/extraction-adapter.js +325 -0
  25. package/dist/multithreading/adapters/extraction-adapter.test.d.ts +2 -0
  26. package/dist/multithreading/adapters/extraction-adapter.test.d.ts.map +1 -0
  27. package/dist/multithreading/{worker-adapter/worker-adapter.extraction.test.js → adapters/extraction-adapter.test.js} +41 -51
  28. package/dist/multithreading/adapters/loading-adapter.d.ts +44 -0
  29. package/dist/multithreading/adapters/loading-adapter.d.ts.map +1 -0
  30. package/dist/multithreading/{worker-adapter/worker-adapter.helpers.d.ts → adapters/loading-adapter.helpers.d.ts} +1 -1
  31. package/dist/multithreading/adapters/loading-adapter.helpers.d.ts.map +1 -0
  32. package/dist/multithreading/adapters/loading-adapter.helpers.test.d.ts +2 -0
  33. package/dist/multithreading/adapters/loading-adapter.helpers.test.d.ts.map +1 -0
  34. package/dist/multithreading/{worker-adapter/worker-adapter.helpers.test.js → adapters/loading-adapter.helpers.test.js} +26 -26
  35. package/dist/multithreading/adapters/loading-adapter.js +461 -0
  36. package/dist/multithreading/adapters/loading-adapter.test.d.ts +2 -0
  37. package/dist/multithreading/adapters/loading-adapter.test.d.ts.map +1 -0
  38. package/dist/multithreading/{worker-adapter/worker-adapter.loading.test.js → adapters/loading-adapter.test.js} +19 -26
  39. package/dist/multithreading/adapters/serialization.test.d.ts +2 -0
  40. package/dist/multithreading/adapters/serialization.test.d.ts.map +1 -0
  41. package/dist/multithreading/process-task.d.ts +16 -1
  42. package/dist/multithreading/process-task.d.ts.map +1 -1
  43. package/dist/multithreading/process-task.js +97 -49
  44. package/dist/multithreading/process-task.test.js +15 -15
  45. package/dist/state/base-state.d.ts +75 -0
  46. package/dist/state/base-state.d.ts.map +1 -0
  47. package/dist/state/base-state.js +261 -0
  48. package/dist/state/extraction-state.d.ts +29 -0
  49. package/dist/state/extraction-state.d.ts.map +1 -0
  50. package/dist/state/extraction-state.js +122 -0
  51. package/dist/state/loading-state.d.ts +19 -0
  52. package/dist/state/loading-state.d.ts.map +1 -0
  53. package/dist/state/loading-state.js +40 -0
  54. package/dist/state/state.extract-window.test.js +7 -7
  55. package/dist/state/state.interfaces.d.ts +32 -25
  56. package/dist/state/state.interfaces.d.ts.map +1 -1
  57. package/dist/state/state.interfaces.js +15 -4
  58. package/dist/state/state.pending-boundaries.test.js +15 -15
  59. package/dist/state/state.post-state.test.js +9 -8
  60. package/dist/state/state.test.js +22 -19
  61. package/dist/state/state.time-value-resolution.test.js +8 -8
  62. package/dist/types/extraction.d.ts +3 -3
  63. package/dist/types/extraction.d.ts.map +1 -1
  64. package/dist/types/index.d.ts +0 -1
  65. package/dist/types/index.d.ts.map +1 -1
  66. package/dist/types/workers.d.ts +16 -15
  67. package/dist/types/workers.d.ts.map +1 -1
  68. package/package.json +1 -1
  69. package/dist/multithreading/worker-adapter/worker-adapter.artifacts.test.d.ts +0 -2
  70. package/dist/multithreading/worker-adapter/worker-adapter.artifacts.test.d.ts.map +0 -1
  71. package/dist/multithreading/worker-adapter/worker-adapter.d.ts +0 -97
  72. package/dist/multithreading/worker-adapter/worker-adapter.d.ts.map +0 -1
  73. package/dist/multithreading/worker-adapter/worker-adapter.emit.test.d.ts +0 -2
  74. package/dist/multithreading/worker-adapter/worker-adapter.emit.test.d.ts.map +0 -1
  75. package/dist/multithreading/worker-adapter/worker-adapter.extraction.test.d.ts +0 -2
  76. package/dist/multithreading/worker-adapter/worker-adapter.extraction.test.d.ts.map +0 -1
  77. package/dist/multithreading/worker-adapter/worker-adapter.helpers.d.ts.map +0 -1
  78. package/dist/multithreading/worker-adapter/worker-adapter.helpers.test.d.ts +0 -2
  79. package/dist/multithreading/worker-adapter/worker-adapter.helpers.test.d.ts.map +0 -1
  80. package/dist/multithreading/worker-adapter/worker-adapter.js +0 -846
  81. package/dist/multithreading/worker-adapter/worker-adapter.loading.test.d.ts +0 -2
  82. package/dist/multithreading/worker-adapter/worker-adapter.loading.test.d.ts.map +0 -1
  83. package/dist/multithreading/worker-adapter/worker-adapter.serialization.test.d.ts +0 -2
  84. package/dist/multithreading/worker-adapter/worker-adapter.serialization.test.d.ts.map +0 -1
  85. package/dist/state/state.d.ts +0 -36
  86. package/dist/state/state.d.ts.map +0 -1
  87. package/dist/state/state.js +0 -265
  88. /package/dist/multithreading/{worker-adapter/worker-adapter.helpers.js → adapters/loading-adapter.helpers.js} +0 -0
  89. /package/dist/multithreading/{worker-adapter/worker-adapter.serialization.test.js → adapters/serialization.test.js} +0 -0
@@ -1,12 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const constants_1 = require("../../common/constants");
4
- const state_1 = require("../../state/state");
4
+ const extraction_state_1 = require("../../state/extraction-state");
5
+ const loading_state_1 = require("../../state/loading-state");
5
6
  const jest_setup_1 = require("../../tests/jest.setup");
6
7
  const test_utils_1 = require("../../common/test-utils");
7
8
  const types_1 = require("../../types");
8
9
  const loading_1 = require("../../types/loading");
9
- const worker_adapter_1 = require("./worker-adapter");
10
+ const extraction_adapter_1 = require("./extraction-adapter");
11
+ const loading_adapter_1 = require("./loading-adapter");
10
12
  /* eslint-disable @typescript-eslint/no-require-imports */
11
13
  jest.mock('../../common/control-protocol', () => ({
12
14
  emit: jest.fn().mockResolvedValue({}),
@@ -28,20 +30,32 @@ function makeAdapter(eventType = types_1.EventType.StartExtractingData) {
28
30
  });
29
31
  const initialState = {
30
32
  attachments: { completed: false },
31
- snapInVersionId: '',
32
- toDevRev: {
33
- attachmentsMetadata: {
34
- artifactIds: [],
35
- lastProcessed: 0,
36
- lastProcessedAttachmentsIdsList: [],
37
- },
33
+ };
34
+ const adapterState = new extraction_state_1.ExtractionState({ event, initialState });
35
+ adapterState.sdkState.snapInVersionId = '';
36
+ adapterState.sdkState.toDevRev = {
37
+ attachmentsMetadata: {
38
+ artifactIds: [],
39
+ lastProcessed: 0,
40
+ lastProcessedAttachmentsIdsList: [],
38
41
  },
39
42
  };
40
- const adapterState = new state_1.State({ event, initialState });
41
- const adapter = new worker_adapter_1.WorkerAdapter({ event, adapterState });
43
+ const adapter = new extraction_adapter_1.ExtractionAdapter({ event, adapterState });
42
44
  return { adapter, event, adapterState };
43
45
  }
44
- describe(`${worker_adapter_1.WorkerAdapter.name}.emit`, () => {
46
+ function makeLoadingAdapter(eventType = types_1.EventType.StartLoadingData) {
47
+ const event = (0, test_utils_1.createMockEvent)(jest_setup_1.mockServer.baseUrl, {
48
+ payload: { event_type: eventType },
49
+ });
50
+ const initialState = {
51
+ attachments: { completed: false },
52
+ };
53
+ const adapterState = new loading_state_1.LoadingState({ event, initialState });
54
+ adapterState.sdkState.snapInVersionId = '';
55
+ const adapter = new loading_adapter_1.LoadingAdapter({ event, adapterState });
56
+ return { adapter, event, adapterState };
57
+ }
58
+ describe(`${extraction_adapter_1.ExtractionAdapter.name}.emit`, () => {
45
59
  let adapter;
46
60
  let mockPostMessage;
47
61
  beforeEach(() => {
@@ -150,14 +164,16 @@ describe(`${worker_adapter_1.WorkerAdapter.name}.emit`, () => {
150
164
  it('should include reports and processed_files in data for loader events', async () => {
151
165
  // Arrange
152
166
  const { emit: mockEmit } = require('../../common/control-protocol');
153
- adapter['adapterState'].postState = jest.fn().mockResolvedValue(undefined);
154
- adapter.uploadAllRepos = jest.fn().mockResolvedValue(undefined);
155
- adapter['loaderReports'] = [
167
+ const { adapter: loadingAdapter } = makeLoadingAdapter();
168
+ loadingAdapter['adapterState'].postState = jest
169
+ .fn()
170
+ .mockResolvedValue(undefined);
171
+ loadingAdapter['loaderReports'] = [
156
172
  { item_type: 'tasks', [loading_1.ActionType.CREATED]: 5 },
157
173
  ];
158
- adapter['_processedFiles'] = ['file-1', 'file-2'];
174
+ loadingAdapter['_processedFiles'] = ['file-1', 'file-2'];
159
175
  // Act
160
- await adapter.emit(types_1.LoaderEventType.DataLoadingDone);
176
+ await loadingAdapter.emit(types_1.LoaderEventType.DataLoadingDone);
161
177
  // Assert
162
178
  expect(mockEmit).toHaveBeenCalledWith(expect.objectContaining({
163
179
  data: expect.objectContaining({
@@ -178,10 +194,6 @@ describe(`${worker_adapter_1.WorkerAdapter.name}.emit`, () => {
178
194
  adapter['_artifacts'] = [
179
195
  { id: 'art-1', item_count: 10, item_type: 'issues' },
180
196
  ];
181
- adapter['loaderReports'] = [
182
- { item_type: 'tasks', [loading_1.ActionType.CREATED]: 5 },
183
- ];
184
- adapter['_processedFiles'] = ['file-1'];
185
197
  // Act
186
198
  await adapter.emit('SOME_UNKNOWN_EVENT');
187
199
  // Assert
@@ -227,15 +239,15 @@ describe(`${worker_adapter_1.WorkerAdapter.name}.emit`, () => {
227
239
  types_1.LoaderEventType.AttachmentLoadingDone,
228
240
  types_1.LoaderEventType.AttachmentLoadingProgress,
229
241
  ];
242
+ const { adapter: loadingAdapter } = makeLoadingAdapter();
243
+ loadingAdapter['adapterState'].postState = jest
244
+ .fn()
245
+ .mockResolvedValue(undefined);
230
246
  for (const eventType of loaderEvents) {
231
247
  jest.clearAllMocks();
232
- adapter.hasWorkerEmitted = false;
233
- adapter['adapterState'].postState = jest
234
- .fn()
235
- .mockResolvedValue(undefined);
236
- adapter.uploadAllRepos = jest.fn().mockResolvedValue(undefined);
248
+ loadingAdapter.hasWorkerEmitted = false;
237
249
  // Act
238
- await adapter.emit(eventType);
250
+ await loadingAdapter.emit(eventType);
239
251
  // Assert
240
252
  const callData = (_b = (_a = mockEmit.mock.calls[0]) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.data;
241
253
  expect(callData).toHaveProperty('reports');
@@ -262,10 +274,11 @@ describe(`${worker_adapter_1.WorkerAdapter.name}.emit`, () => {
262
274
  });
263
275
  describe('WorkerAdapter — workersOldest / workersNewest boundary updates', () => {
264
276
  let adapter;
277
+ let adapterState;
265
278
  let mockPostMessage;
266
279
  beforeEach(() => {
267
280
  jest.clearAllMocks();
268
- ({ adapter } = makeAdapter());
281
+ ({ adapter, adapterState } = makeAdapter());
269
282
  const workerThreads = require('node:worker_threads');
270
283
  mockPostMessage = jest.fn();
271
284
  if (workerThreads.parentPort) {
@@ -295,75 +308,75 @@ describe('WorkerAdapter — workersOldest / workersNewest boundary updates', ()
295
308
  describe('initial import with UNBOUNDED start', () => {
296
309
  it('should set workersOldest to UNBOUNDED_DATE_TIME_VALUE and workersNewest to extraction end', async () => {
297
310
  await emitDone(adapter, constants_1.UNBOUNDED_DATE_TIME_VALUE, '2025-06-01T00:00:00.000Z');
298
- expect(adapter.state.workersOldest).toBe(constants_1.UNBOUNDED_DATE_TIME_VALUE);
299
- expect(adapter.state.workersNewest).toBe('2025-06-01T00:00:00.000Z');
311
+ expect(adapterState.sdkState.workersOldest).toBe(constants_1.UNBOUNDED_DATE_TIME_VALUE);
312
+ expect(adapterState.sdkState.workersNewest).toBe('2025-06-01T00:00:00.000Z');
300
313
  });
301
314
  });
302
315
  describe('reconciliation after UNBOUNDED initial import', () => {
303
316
  it('should NOT overwrite workersOldest when reconciliation start is later than sentinel', async () => {
304
317
  await emitDone(adapter, constants_1.UNBOUNDED_DATE_TIME_VALUE, '2025-06-01T00:00:00.000Z');
305
318
  await emitDone(adapter, '2025-01-01T00:00:00.000Z', '2025-03-01T00:00:00.000Z');
306
- expect(adapter.state.workersOldest).toBe(constants_1.UNBOUNDED_DATE_TIME_VALUE);
307
- expect(adapter.state.workersNewest).toBe('2025-06-01T00:00:00.000Z');
319
+ expect(adapterState.sdkState.workersOldest).toBe(constants_1.UNBOUNDED_DATE_TIME_VALUE);
320
+ expect(adapterState.sdkState.workersNewest).toBe('2025-06-01T00:00:00.000Z');
308
321
  });
309
322
  it('should NOT overwrite workersOldest even when reconciliation start is very early', async () => {
310
323
  await emitDone(adapter, constants_1.UNBOUNDED_DATE_TIME_VALUE, '2025-06-01T00:00:00.000Z');
311
324
  await emitDone(adapter, '1980-01-01T00:00:00.000Z', '1990-01-01T00:00:00.000Z');
312
- expect(adapter.state.workersOldest).toBe(constants_1.UNBOUNDED_DATE_TIME_VALUE);
313
- expect(adapter.state.workersNewest).toBe('2025-06-01T00:00:00.000Z');
325
+ expect(adapterState.sdkState.workersOldest).toBe(constants_1.UNBOUNDED_DATE_TIME_VALUE);
326
+ expect(adapterState.sdkState.workersNewest).toBe('2025-06-01T00:00:00.000Z');
314
327
  });
315
328
  });
316
329
  describe('forward sync after UNBOUNDED initial import', () => {
317
330
  it('should expand workersNewest forward while preserving workersOldest', async () => {
318
331
  await emitDone(adapter, constants_1.UNBOUNDED_DATE_TIME_VALUE, '2025-06-01T00:00:00.000Z');
319
332
  await emitDone(adapter, '2025-06-01T00:00:00.000Z', '2025-07-01T00:00:00.000Z');
320
- expect(adapter.state.workersOldest).toBe(constants_1.UNBOUNDED_DATE_TIME_VALUE);
321
- expect(adapter.state.workersNewest).toBe('2025-07-01T00:00:00.000Z');
333
+ expect(adapterState.sdkState.workersOldest).toBe(constants_1.UNBOUNDED_DATE_TIME_VALUE);
334
+ expect(adapterState.sdkState.workersNewest).toBe('2025-07-01T00:00:00.000Z');
322
335
  });
323
336
  });
324
337
  describe('reconciliation with end beyond current newest', () => {
325
338
  it('should expand workersNewest when reconciliation end is later', async () => {
326
339
  await emitDone(adapter, constants_1.UNBOUNDED_DATE_TIME_VALUE, '2025-06-01T00:00:00.000Z');
327
340
  await emitDone(adapter, '2024-01-01T00:00:00.000Z', '2025-08-01T00:00:00.000Z');
328
- expect(adapter.state.workersOldest).toBe(constants_1.UNBOUNDED_DATE_TIME_VALUE);
329
- expect(adapter.state.workersNewest).toBe('2025-08-01T00:00:00.000Z');
341
+ expect(adapterState.sdkState.workersOldest).toBe(constants_1.UNBOUNDED_DATE_TIME_VALUE);
342
+ expect(adapterState.sdkState.workersNewest).toBe('2025-08-01T00:00:00.000Z');
330
343
  });
331
344
  });
332
345
  describe('first sync with absolute dates (no UNBOUNDED)', () => {
333
346
  it('should set both boundaries from the extraction range', async () => {
334
347
  await emitDone(adapter, '2025-01-01T00:00:00.000Z', '2025-03-01T00:00:00.000Z');
335
- expect(adapter.state.workersOldest).toBe('2025-01-01T00:00:00.000Z');
336
- expect(adapter.state.workersNewest).toBe('2025-03-01T00:00:00.000Z');
348
+ expect(adapterState.sdkState.workersOldest).toBe('2025-01-01T00:00:00.000Z');
349
+ expect(adapterState.sdkState.workersNewest).toBe('2025-03-01T00:00:00.000Z');
337
350
  });
338
351
  });
339
352
  describe('reconciliation after absolute initial sync', () => {
340
353
  it('should expand workersOldest backward when reconciliation start is earlier', async () => {
341
354
  await emitDone(adapter, '2025-01-01T00:00:00.000Z', '2025-03-01T00:00:00.000Z');
342
355
  await emitDone(adapter, '2024-06-01T00:00:00.000Z', '2025-02-01T00:00:00.000Z');
343
- expect(adapter.state.workersOldest).toBe('2024-06-01T00:00:00.000Z');
344
- expect(adapter.state.workersNewest).toBe('2025-03-01T00:00:00.000Z');
356
+ expect(adapterState.sdkState.workersOldest).toBe('2024-06-01T00:00:00.000Z');
357
+ expect(adapterState.sdkState.workersNewest).toBe('2025-03-01T00:00:00.000Z');
345
358
  });
346
359
  it('should NOT change boundaries when reconciliation is within existing range', async () => {
347
360
  await emitDone(adapter, '2025-01-01T00:00:00.000Z', '2025-03-01T00:00:00.000Z');
348
361
  await emitDone(adapter, '2025-01-15T00:00:00.000Z', '2025-02-15T00:00:00.000Z');
349
- expect(adapter.state.workersOldest).toBe('2025-01-01T00:00:00.000Z');
350
- expect(adapter.state.workersNewest).toBe('2025-03-01T00:00:00.000Z');
362
+ expect(adapterState.sdkState.workersOldest).toBe('2025-01-01T00:00:00.000Z');
363
+ expect(adapterState.sdkState.workersNewest).toBe('2025-03-01T00:00:00.000Z');
351
364
  });
352
365
  it('should expand both boundaries when reconciliation exceeds both', async () => {
353
366
  await emitDone(adapter, '2025-01-01T00:00:00.000Z', '2025-03-01T00:00:00.000Z');
354
367
  await emitDone(adapter, '2024-06-01T00:00:00.000Z', '2025-09-01T00:00:00.000Z');
355
- expect(adapter.state.workersOldest).toBe('2024-06-01T00:00:00.000Z');
356
- expect(adapter.state.workersNewest).toBe('2025-09-01T00:00:00.000Z');
368
+ expect(adapterState.sdkState.workersOldest).toBe('2024-06-01T00:00:00.000Z');
369
+ expect(adapterState.sdkState.workersNewest).toBe('2025-09-01T00:00:00.000Z');
357
370
  });
358
371
  });
359
372
  describe('multiple forward syncs', () => {
360
373
  it('should progressively expand workersNewest while preserving workersOldest', async () => {
361
374
  await emitDone(adapter, constants_1.UNBOUNDED_DATE_TIME_VALUE, '2025-06-01T00:00:00.000Z');
362
375
  await emitDone(adapter, '2025-06-01T00:00:00.000Z', '2025-07-01T00:00:00.000Z');
363
- expect(adapter.state.workersNewest).toBe('2025-07-01T00:00:00.000Z');
376
+ expect(adapterState.sdkState.workersNewest).toBe('2025-07-01T00:00:00.000Z');
364
377
  await emitDone(adapter, '2025-07-01T00:00:00.000Z', '2025-08-01T00:00:00.000Z');
365
- expect(adapter.state.workersNewest).toBe('2025-08-01T00:00:00.000Z');
366
- expect(adapter.state.workersOldest).toBe(constants_1.UNBOUNDED_DATE_TIME_VALUE);
378
+ expect(adapterState.sdkState.workersNewest).toBe('2025-08-01T00:00:00.000Z');
379
+ expect(adapterState.sdkState.workersOldest).toBe(constants_1.UNBOUNDED_DATE_TIME_VALUE);
367
380
  });
368
381
  });
369
382
  describe('non-AttachmentExtractionDone events should NOT update boundaries', () => {
@@ -373,8 +386,8 @@ describe('WorkerAdapter — workersOldest / workersNewest boundary updates', ()
373
386
  types_1.ExtractorEventType.MetadataExtractionError,
374
387
  types_1.ExtractorEventType.AttachmentExtractionError,
375
388
  ])('should not update boundaries on %s', async (eventType) => {
376
- adapter.state.workersOldest = '2025-01-01T00:00:00.000Z';
377
- adapter.state.workersNewest = '2025-03-01T00:00:00.000Z';
389
+ adapterState.sdkState.workersOldest = '2025-01-01T00:00:00.000Z';
390
+ adapterState.sdkState.workersNewest = '2025-03-01T00:00:00.000Z';
378
391
  adapter.event.payload.event_context.extract_from =
379
392
  '2024-01-01T00:00:00.000Z';
380
393
  adapter.event.payload.event_context.extract_to =
@@ -383,8 +396,8 @@ describe('WorkerAdapter — workersOldest / workersNewest boundary updates', ()
383
396
  reports: [],
384
397
  processed_files: [],
385
398
  });
386
- expect(adapter.state.workersOldest).toBe('2025-01-01T00:00:00.000Z');
387
- expect(adapter.state.workersNewest).toBe('2025-03-01T00:00:00.000Z');
399
+ expect(adapterState.sdkState.workersOldest).toBe('2025-01-01T00:00:00.000Z');
400
+ expect(adapterState.sdkState.workersNewest).toBe('2025-03-01T00:00:00.000Z');
388
401
  });
389
402
  });
390
403
  });
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BaseAdapter = void 0;
4
+ const node_worker_threads_1 = require("node:worker_threads");
5
+ const constants_1 = require("../../common/constants");
6
+ const control_protocol_1 = require("../../common/control-protocol");
7
+ const helpers_1 = require("../../common/helpers");
8
+ const logger_1 = require("../../logger/logger");
9
+ const logger_context_1 = require("../../logger/logger.context");
10
+ const workers_1 = require("../../types/workers");
11
+ const uploader_1 = require("../../uploader/uploader");
12
+ /**
13
+ * BaseAdapter holds the state and behavior shared by both sync modes and owns
14
+ * the `emit` control-protocol flow as a template method. Mode-specific adapters
15
+ * (`ExtractionAdapter`, `LoadingAdapter`) implement the abstract hooks to inject
16
+ * their own pre-emit work and event payload shaping.
17
+ *
18
+ * @typeParam ConnectorState - the connector-owned state shape
19
+ * @typeParam StateClass - the mode's `BaseState` subclass
20
+ */
21
+ class BaseAdapter {
22
+ constructor({ event, adapterState, options, }) {
23
+ this.event = event;
24
+ this.options = options;
25
+ this.adapterState = adapterState;
26
+ this.hasWorkerEmitted = false;
27
+ this.isTimeout = false;
28
+ this.uploader = new uploader_1.Uploader({
29
+ event,
30
+ options,
31
+ });
32
+ }
33
+ get state() {
34
+ return this.adapterState.state;
35
+ }
36
+ set state(value) {
37
+ this.adapterState.state = value;
38
+ }
39
+ async postState() {
40
+ return (0, logger_context_1.runWithSdkLogContext)(async () => {
41
+ await this.adapterState.postState();
42
+ });
43
+ }
44
+ /**
45
+ * Emits an event to the platform.
46
+ *
47
+ * @param newEventType - The event type to be emitted
48
+ * @param data - The data to be sent with the event
49
+ */
50
+ async emit(newEventType, data) {
51
+ return (0, logger_context_1.runWithSdkLogContext)(async () => {
52
+ var _a;
53
+ if (this.hasWorkerEmitted) {
54
+ console.warn(`Trying to emit event with event type: ${newEventType}. Ignoring emit request because it has already been emitted.`);
55
+ return;
56
+ }
57
+ try {
58
+ await this.beforeEmit(newEventType);
59
+ }
60
+ catch (error) {
61
+ console.error('Error while preparing to emit event', error);
62
+ node_worker_threads_1.parentPort === null || node_worker_threads_1.parentPort === void 0 ? void 0 : node_worker_threads_1.parentPort.postMessage(workers_1.WorkerMessageSubject.WorkerMessageExit);
63
+ this.hasWorkerEmitted = true;
64
+ return;
65
+ }
66
+ // We want to save the state every time we emit an event, except for the start and delete events
67
+ if (!constants_1.STATELESS_EVENT_TYPES.includes(this.event.payload.event_type)) {
68
+ console.log(`Saving state before emitting event with event type: ${newEventType}.`);
69
+ try {
70
+ await this.adapterState.postState();
71
+ }
72
+ catch (error) {
73
+ console.error('Error while posting state', error);
74
+ node_worker_threads_1.parentPort === null || node_worker_threads_1.parentPort === void 0 ? void 0 : node_worker_threads_1.parentPort.postMessage(workers_1.WorkerMessageSubject.WorkerMessageExit);
75
+ this.hasWorkerEmitted = true;
76
+ return;
77
+ }
78
+ }
79
+ try {
80
+ // Always prune error messages to make them shorter before emit
81
+ if ((_a = data === null || data === void 0 ? void 0 : data.error) === null || _a === void 0 ? void 0 : _a.message) {
82
+ data.error.message = (0, helpers_1.truncateMessage)(data.error.message);
83
+ }
84
+ await (0, control_protocol_1.emit)({
85
+ eventType: newEventType,
86
+ event: this.event,
87
+ data: Object.assign(Object.assign({}, data), this.buildEmitPayload(newEventType)),
88
+ });
89
+ const message = {
90
+ subject: workers_1.WorkerMessageSubject.WorkerMessageEmitted,
91
+ payload: { eventType: newEventType },
92
+ };
93
+ this.afterEmit(newEventType);
94
+ node_worker_threads_1.parentPort === null || node_worker_threads_1.parentPort === void 0 ? void 0 : node_worker_threads_1.parentPort.postMessage(message);
95
+ this.hasWorkerEmitted = true;
96
+ }
97
+ catch (error) {
98
+ console.error(`Error while emitting event with event type: ${newEventType}.`, (0, logger_1.serializeError)(error));
99
+ node_worker_threads_1.parentPort === null || node_worker_threads_1.parentPort === void 0 ? void 0 : node_worker_threads_1.parentPort.postMessage(workers_1.WorkerMessageSubject.WorkerMessageExit);
100
+ this.hasWorkerEmitted = true;
101
+ }
102
+ });
103
+ }
104
+ }
105
+ exports.BaseAdapter = BaseAdapter;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=extraction-adapter.artifacts.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extraction-adapter.artifacts.test.d.ts","sourceRoot":"","sources":["../../../src/multithreading/adapters/extraction-adapter.artifacts.test.ts"],"names":[],"mappings":""}
@@ -1,12 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const constants_1 = require("../../common/constants");
4
- const state_1 = require("../../state/state");
4
+ const extraction_state_1 = require("../../state/extraction-state");
5
5
  const jest_setup_1 = require("../../tests/jest.setup");
6
6
  const test_helpers_1 = require("../../tests/test-helpers");
7
7
  const test_utils_1 = require("../../common/test-utils");
8
8
  const types_1 = require("../../types");
9
- const worker_adapter_1 = require("./worker-adapter");
9
+ const extraction_adapter_1 = require("./extraction-adapter");
10
10
  // 1. Create a mock function for the method you want to override.
11
11
  const mockUpload = (itemType, objects) => {
12
12
  return {
@@ -55,11 +55,11 @@ describe('Artifact ordering when artifacts overflow batch sizes in repositories'
55
55
  const mockEvent = (0, test_utils_1.createMockEvent)(jest_setup_1.mockServer.baseUrl, {
56
56
  payload: { event_type: types_1.EventType.StartExtractingData },
57
57
  });
58
- const mockAdapterState = new state_1.State({
58
+ const mockAdapterState = new extraction_state_1.ExtractionState({
59
59
  event: mockEvent,
60
60
  initialState: { attachments: { completed: false } },
61
61
  });
62
- testAdapter = new worker_adapter_1.WorkerAdapter({
62
+ testAdapter = new extraction_adapter_1.ExtractionAdapter({
63
63
  event: mockEvent,
64
64
  adapterState: mockAdapterState,
65
65
  options: {
@@ -136,11 +136,11 @@ describe('External sync units splitting into artifacts', () => {
136
136
  const mockEvent = (0, test_utils_1.createMockEvent)(jest_setup_1.mockServer.baseUrl, {
137
137
  payload: { event_type: types_1.EventType.StartExtractingExternalSyncUnits },
138
138
  });
139
- const mockAdapterState = new state_1.State({
139
+ const mockAdapterState = new extraction_state_1.ExtractionState({
140
140
  event: mockEvent,
141
141
  initialState: {},
142
142
  });
143
- testAdapter = new worker_adapter_1.WorkerAdapter({
143
+ testAdapter = new extraction_adapter_1.ExtractionAdapter({
144
144
  event: mockEvent,
145
145
  adapterState: mockAdapterState,
146
146
  });
@@ -0,0 +1,58 @@
1
+ import { Repo } from '../../repo/repo';
2
+ import { NormalizedAttachment, RepoInterface } from '../../repo/repo.interfaces';
3
+ import { ExtractionState } from '../../state/extraction-state';
4
+ import { AirSyncEvent, ExternalSystemAttachmentProcessors, ExternalSystemAttachmentStreamingFunction, ExtractorEventType, EventData, ProcessAttachmentReturnType, StreamAttachmentsReturnType } from '../../types/extraction';
5
+ import { LoaderEventType } from '../../types/loading';
6
+ import { WorkerAdapterOptions } from '../../types/workers';
7
+ import { Artifact } from '../../uploader/uploader.interfaces';
8
+ import { BaseAdapter } from './base-adapter';
9
+ /**
10
+ * ExtractionAdapter is the adapter passed to extraction tasks. It exposes the
11
+ * extraction surface (repos, artifacts, attachment streaming) and updates the
12
+ * extraction boundaries before emitting.
13
+ *
14
+ * @public
15
+ */
16
+ export declare class ExtractionAdapter<ConnectorState> extends BaseAdapter<ConnectorState, ExtractionState<ConnectorState>> {
17
+ private _artifacts;
18
+ private repos;
19
+ private currentEventDataLength;
20
+ constructor(params: {
21
+ event: AirSyncEvent;
22
+ adapterState: ExtractionState<ConnectorState>;
23
+ options?: WorkerAdapterOptions;
24
+ });
25
+ get extractionScope(): import("../../types/workers").ExtractionScope;
26
+ /**
27
+ * Returns whether the given item type should be extracted.
28
+ * Defaults to true if the scope is empty or the item type is not listed.
29
+ */
30
+ shouldExtract(itemType: string): boolean;
31
+ initializeRepos(repos: RepoInterface[]): void;
32
+ getRepo(itemType: string): Repo | undefined;
33
+ get artifacts(): Artifact[];
34
+ set artifacts(artifacts: Artifact[]);
35
+ protected beforeEmit(newEventType: ExtractorEventType | LoaderEventType): Promise<void>;
36
+ protected buildEmitPayload(newEventType: ExtractorEventType | LoaderEventType): EventData;
37
+ protected afterEmit(): void;
38
+ uploadAllRepos(): Promise<void>;
39
+ processAttachment(attachment: NormalizedAttachment, stream: ExternalSystemAttachmentStreamingFunction): Promise<ProcessAttachmentReturnType>;
40
+ /**
41
+ * Destroys a stream to prevent memory leaks.
42
+ * @param httpStream - The axios response stream to destroy
43
+ */
44
+ private destroyHttpStream;
45
+ /**
46
+ * Streams the attachments to the DevRev platform.
47
+ * The attachments are streamed to the platform and the artifact information is returned.
48
+ * @param params - The parameters to stream the attachments
49
+ * @returns The response object containing the ssorAttachment artifact information
50
+ * or error information if there was an error
51
+ */
52
+ streamAttachments<NewBatch>({ stream, processors, batchSize, }: {
53
+ stream: ExternalSystemAttachmentStreamingFunction;
54
+ processors?: ExternalSystemAttachmentProcessors<ConnectorState, NormalizedAttachment[], NewBatch>;
55
+ batchSize?: number;
56
+ }): Promise<StreamAttachmentsReturnType>;
57
+ }
58
+ //# sourceMappingURL=extraction-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extraction-adapter.d.ts","sourceRoot":"","sources":["../../../src/multithreading/adapters/extraction-adapter.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EACL,oBAAoB,EACpB,aAAa,EACd,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EACL,YAAY,EACZ,kCAAkC,EAClC,yCAAyC,EACzC,kBAAkB,EAClB,SAAS,EACT,2BAA2B,EAC3B,2BAA2B,EAC5B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAkB,MAAM,oCAAoC,CAAC;AAE9E,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C;;;;;;GAMG;AACH,qBAAa,iBAAiB,CAAC,cAAc,CAAE,SAAQ,WAAW,CAChE,cAAc,EACd,eAAe,CAAC,cAAc,CAAC,CAChC;IACC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,sBAAsB,CAAa;gBAE/B,MAAM,EAAE;QAClB,KAAK,EAAE,YAAY,CAAC;QACpB,YAAY,EAAE,eAAe,CAAC,cAAc,CAAC,CAAC;QAC9C,OAAO,CAAC,EAAE,oBAAoB,CAAC;KAChC;IAKD,IAAI,eAAe,kDAElB;IAED;;;OAGG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAOxC,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE;IAuCtC,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAa3C,IAAI,SAAS,IAAI,QAAQ,EAAE,CAE1B;IAED,IAAI,SAAS,CAAC,SAAS,EAAE,QAAQ,EAAE,EAIlC;cAEe,UAAU,CACxB,YAAY,EAAE,kBAAkB,GAAG,eAAe,GACjD,OAAO,CAAC,IAAI,CAAC;IAyChB,SAAS,CAAC,gBAAgB,CACxB,YAAY,EAAE,kBAAkB,GAAG,eAAe,GACjD,SAAS;IAOZ,SAAS,CAAC,SAAS,IAAI,IAAI;IAIrB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAU/B,iBAAiB,CACrB,UAAU,EAAE,oBAAoB,EAChC,MAAM,EAAE,yCAAyC,GAChD,OAAO,CAAC,2BAA2B,CAAC;IA+GvC;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAczB;;;;;;OAMG;IACG,iBAAiB,CAAC,QAAQ,EAAE,EAChC,MAAM,EACN,UAAU,EACV,SAAa,GACd,EAAE;QACD,MAAM,EAAE,yCAAyC,CAAC;QAClD,UAAU,CAAC,EAAE,kCAAkC,CAC7C,cAAc,EACd,oBAAoB,EAAE,EACtB,QAAQ,CACT,CAAC;QACF,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,2BAA2B,CAAC;CAyIzC"}