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

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 (156) hide show
  1. package/README.md +0 -4
  2. package/dist/airsync-sdk.d.ts +1802 -0
  3. package/dist/attachments-streaming/attachments-streaming-pool.d.ts.map +1 -1
  4. package/dist/attachments-streaming/attachments-streaming-pool.js +13 -2
  5. package/dist/attachments-streaming/attachments-streaming-pool.test.js +201 -6
  6. package/dist/common/constants.d.ts +16 -5
  7. package/dist/common/constants.d.ts.map +1 -1
  8. package/dist/common/constants.js +20 -6
  9. package/dist/common/control-protocol.d.ts +2 -2
  10. package/dist/common/control-protocol.d.ts.map +1 -1
  11. package/dist/common/control-protocol.js +1 -5
  12. package/dist/common/helpers.d.ts +8 -0
  13. package/dist/common/helpers.d.ts.map +1 -1
  14. package/dist/common/helpers.js +15 -0
  15. package/dist/common/install-initial-domain-mapping.d.ts +2 -2
  16. package/dist/common/install-initial-domain-mapping.test.js +5 -2
  17. package/dist/common/test-utils.d.ts +19 -0
  18. package/dist/common/test-utils.d.ts.map +1 -0
  19. package/dist/common/test-utils.js +101 -0
  20. package/dist/common/time-value-resolver.d.ts +47 -0
  21. package/dist/common/time-value-resolver.d.ts.map +1 -0
  22. package/dist/common/time-value-resolver.js +141 -0
  23. package/dist/common/time-value-resolver.test.d.ts +2 -0
  24. package/dist/common/time-value-resolver.test.d.ts.map +1 -0
  25. package/dist/common/time-value-resolver.test.js +268 -0
  26. package/dist/http/axios-client-internal.d.ts.map +1 -1
  27. package/dist/http/axios-client-internal.js +7 -0
  28. package/dist/http/axios-client-internal.test.js +21 -0
  29. package/dist/http/axios-client.d.ts.map +1 -1
  30. package/dist/http/axios-client.js +6 -3
  31. package/dist/http/index.d.ts +0 -1
  32. package/dist/http/index.d.ts.map +1 -1
  33. package/dist/http/index.js +0 -1
  34. package/dist/index.d.ts +9 -8
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +12 -10
  37. package/dist/logger/logger.d.ts +1 -17
  38. package/dist/logger/logger.d.ts.map +1 -1
  39. package/dist/logger/logger.interfaces.d.ts +2 -2
  40. package/dist/logger/logger.js +35 -27
  41. package/dist/logger/logger.test.js +66 -19
  42. package/dist/mappers/mappers.interface.d.ts +5 -5
  43. package/dist/mappers/mappers.interface.js +3 -3
  44. package/dist/mappers/mappers.test.js +8 -10
  45. package/dist/mock-server/mock-server.d.ts +47 -0
  46. package/dist/mock-server/mock-server.d.ts.map +1 -0
  47. package/dist/mock-server/mock-server.interfaces.d.ts +73 -0
  48. package/dist/mock-server/mock-server.interfaces.d.ts.map +1 -0
  49. package/dist/mock-server/mock-server.interfaces.js +4 -0
  50. package/dist/mock-server/mock-server.js +278 -0
  51. package/dist/multithreading/create-worker.test.js +36 -17
  52. package/dist/multithreading/process-task.d.ts.map +1 -1
  53. package/dist/multithreading/process-task.js +15 -48
  54. package/dist/multithreading/process-task.test.d.ts +2 -0
  55. package/dist/multithreading/process-task.test.d.ts.map +1 -0
  56. package/dist/multithreading/process-task.test.js +146 -0
  57. package/dist/multithreading/spawn/spawn.d.ts +3 -3
  58. package/dist/multithreading/spawn/spawn.d.ts.map +1 -1
  59. package/dist/multithreading/spawn/spawn.helpers.d.ts.map +1 -1
  60. package/dist/multithreading/spawn/spawn.helpers.js +6 -14
  61. package/dist/multithreading/spawn/spawn.helpers.test.js +8 -8
  62. package/dist/multithreading/spawn/spawn.js +20 -25
  63. package/dist/multithreading/spawn/spawn.test.d.ts +2 -0
  64. package/dist/multithreading/spawn/spawn.test.d.ts.map +1 -0
  65. package/dist/multithreading/spawn/spawn.test.js +232 -0
  66. package/dist/multithreading/worker-adapter/worker-adapter.artifacts.test.js +49 -1
  67. package/dist/multithreading/worker-adapter/worker-adapter.d.ts +11 -5
  68. package/dist/multithreading/worker-adapter/worker-adapter.d.ts.map +1 -1
  69. package/dist/multithreading/worker-adapter/worker-adapter.emit.test.d.ts +2 -0
  70. package/dist/multithreading/worker-adapter/worker-adapter.emit.test.d.ts.map +1 -0
  71. package/dist/multithreading/worker-adapter/worker-adapter.emit.test.js +390 -0
  72. package/dist/multithreading/worker-adapter/worker-adapter.extraction.test.d.ts +2 -0
  73. package/dist/multithreading/worker-adapter/worker-adapter.extraction.test.d.ts.map +1 -0
  74. package/dist/multithreading/worker-adapter/worker-adapter.extraction.test.js +799 -0
  75. package/dist/multithreading/worker-adapter/worker-adapter.js +232 -131
  76. package/dist/multithreading/worker-adapter/worker-adapter.loading.test.d.ts +2 -0
  77. package/dist/multithreading/worker-adapter/worker-adapter.loading.test.d.ts.map +1 -0
  78. package/dist/multithreading/worker-adapter/worker-adapter.loading.test.js +596 -0
  79. package/dist/multithreading/worker-adapter/worker-adapter.serialization.test.d.ts +2 -0
  80. package/dist/multithreading/worker-adapter/worker-adapter.serialization.test.d.ts.map +1 -0
  81. package/dist/multithreading/worker-adapter/worker-adapter.serialization.test.js +71 -0
  82. package/dist/repo/repo.d.ts.map +1 -1
  83. package/dist/repo/repo.interfaces.d.ts +4 -2
  84. package/dist/repo/repo.interfaces.d.ts.map +1 -1
  85. package/dist/repo/repo.js +4 -3
  86. package/dist/repo/repo.test.js +60 -7
  87. package/dist/state/state.d.ts +7 -1
  88. package/dist/state/state.d.ts.map +1 -1
  89. package/dist/state/state.extract-window.test.d.ts +2 -0
  90. package/dist/state/state.extract-window.test.d.ts.map +1 -0
  91. package/dist/state/state.extract-window.test.js +163 -0
  92. package/dist/state/state.interfaces.d.ts +17 -7
  93. package/dist/state/state.interfaces.d.ts.map +1 -1
  94. package/dist/state/state.interfaces.js +4 -2
  95. package/dist/state/state.js +111 -12
  96. package/dist/state/state.pending-boundaries.test.d.ts +2 -0
  97. package/dist/state/state.pending-boundaries.test.d.ts.map +1 -0
  98. package/dist/state/state.pending-boundaries.test.js +189 -0
  99. package/dist/state/state.post-state.test.d.ts +2 -0
  100. package/dist/state/state.post-state.test.d.ts.map +1 -0
  101. package/dist/state/state.post-state.test.js +77 -0
  102. package/dist/state/state.test.js +117 -73
  103. package/dist/state/state.time-value-resolution.test.d.ts +2 -0
  104. package/dist/state/state.time-value-resolution.test.d.ts.map +1 -0
  105. package/dist/state/state.time-value-resolution.test.js +175 -0
  106. package/dist/tsdoc-metadata.json +11 -0
  107. package/dist/types/common.d.ts +0 -25
  108. package/dist/types/common.d.ts.map +1 -1
  109. package/dist/types/common.js +1 -11
  110. package/dist/types/external-domain-metadata.d.ts +20 -1
  111. package/dist/types/external-domain-metadata.d.ts.map +1 -1
  112. package/dist/types/extraction.d.ts +89 -218
  113. package/dist/types/extraction.d.ts.map +1 -1
  114. package/dist/types/extraction.js +56 -124
  115. package/dist/types/extraction.test.js +69 -43
  116. package/dist/types/index.d.ts +3 -2
  117. package/dist/types/index.d.ts.map +1 -1
  118. package/dist/types/index.js +6 -3
  119. package/dist/types/loading.d.ts +4 -24
  120. package/dist/types/loading.d.ts.map +1 -1
  121. package/dist/types/loading.js +1 -22
  122. package/dist/types/workers.d.ts +31 -14
  123. package/dist/types/workers.d.ts.map +1 -1
  124. package/dist/types/workers.js +1 -0
  125. package/dist/uploader/uploader.d.ts +1 -0
  126. package/dist/uploader/uploader.d.ts.map +1 -1
  127. package/dist/uploader/uploader.helpers.test.js +0 -11
  128. package/dist/uploader/uploader.interfaces.d.ts +3 -3
  129. package/dist/uploader/uploader.js +53 -20
  130. package/dist/uploader/uploader.test.js +22 -10
  131. package/package.json +10 -13
  132. package/dist/common/event-type-translation.d.ts +0 -24
  133. package/dist/common/event-type-translation.d.ts.map +0 -1
  134. package/dist/common/event-type-translation.js +0 -117
  135. package/dist/deprecated/adapter/index.d.ts +0 -62
  136. package/dist/deprecated/adapter/index.d.ts.map +0 -1
  137. package/dist/deprecated/adapter/index.js +0 -151
  138. package/dist/deprecated/common/helpers.d.ts +0 -7
  139. package/dist/deprecated/common/helpers.d.ts.map +0 -1
  140. package/dist/deprecated/common/helpers.js +0 -47
  141. package/dist/deprecated/demo-extractor/external_domain_metadata.json +0 -38
  142. package/dist/deprecated/demo-extractor/index.d.ts +0 -18
  143. package/dist/deprecated/demo-extractor/index.d.ts.map +0 -1
  144. package/dist/deprecated/demo-extractor/index.js +0 -161
  145. package/dist/deprecated/http/client.d.ts +0 -22
  146. package/dist/deprecated/http/client.d.ts.map +0 -1
  147. package/dist/deprecated/http/client.js +0 -161
  148. package/dist/deprecated/uploader/index.d.ts +0 -35
  149. package/dist/deprecated/uploader/index.d.ts.map +0 -1
  150. package/dist/deprecated/uploader/index.js +0 -161
  151. package/dist/http/types.d.ts +0 -17
  152. package/dist/http/types.d.ts.map +0 -1
  153. package/dist/http/types.js +0 -2
  154. package/dist/multithreading/worker-adapter/worker-adapter.test.d.ts +0 -2
  155. package/dist/multithreading/worker-adapter/worker-adapter.test.d.ts.map +0 -1
  156. package/dist/multithreading/worker-adapter/worker-adapter.test.js +0 -483
@@ -0,0 +1,390 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const constants_1 = require("../../common/constants");
4
+ const state_1 = require("../../state/state");
5
+ const jest_setup_1 = require("../../tests/jest.setup");
6
+ const test_utils_1 = require("../../common/test-utils");
7
+ const types_1 = require("../../types");
8
+ const loading_1 = require("../../types/loading");
9
+ const worker_adapter_1 = require("./worker-adapter");
10
+ /* eslint-disable @typescript-eslint/no-require-imports */
11
+ jest.mock('../../common/control-protocol', () => ({
12
+ emit: jest.fn().mockResolvedValue({}),
13
+ }));
14
+ jest.mock('../../mappers/mappers');
15
+ jest.mock('../../uploader/uploader');
16
+ jest.mock('../../repo/repo');
17
+ jest.mock('node:worker_threads', () => ({
18
+ parentPort: { postMessage: jest.fn() },
19
+ }));
20
+ jest.mock('../../attachments-streaming/attachments-streaming-pool', () => ({
21
+ AttachmentsStreamingPool: jest.fn().mockImplementation(() => ({
22
+ streamAll: jest.fn().mockResolvedValue(undefined),
23
+ })),
24
+ }));
25
+ function makeAdapter(eventType = types_1.EventType.StartExtractingData) {
26
+ const event = (0, test_utils_1.createMockEvent)(jest_setup_1.mockServer.baseUrl, {
27
+ payload: { event_type: eventType },
28
+ });
29
+ const initialState = {
30
+ attachments: { completed: false },
31
+ snapInVersionId: '',
32
+ toDevRev: {
33
+ attachmentsMetadata: {
34
+ artifactIds: [],
35
+ lastProcessed: 0,
36
+ lastProcessedAttachmentsIdsList: [],
37
+ },
38
+ },
39
+ };
40
+ const adapterState = new state_1.State({ event, initialState });
41
+ const adapter = new worker_adapter_1.WorkerAdapter({ event, adapterState });
42
+ return { adapter, event, adapterState };
43
+ }
44
+ describe(`${worker_adapter_1.WorkerAdapter.name}.emit`, () => {
45
+ let adapter;
46
+ let mockPostMessage;
47
+ beforeEach(() => {
48
+ jest.clearAllMocks();
49
+ ({ adapter } = makeAdapter());
50
+ const workerThreads = require('node:worker_threads');
51
+ mockPostMessage = jest.fn();
52
+ if (workerThreads.parentPort) {
53
+ jest
54
+ .spyOn(workerThreads.parentPort, 'postMessage')
55
+ .mockImplementation(mockPostMessage);
56
+ }
57
+ else {
58
+ workerThreads.parentPort = { postMessage: mockPostMessage };
59
+ }
60
+ });
61
+ afterEach(() => {
62
+ jest.restoreAllMocks();
63
+ });
64
+ it('should emit only one event when multiple events of same type are sent', async () => {
65
+ // Arrange
66
+ adapter['adapterState'].postState = jest.fn().mockResolvedValue(undefined);
67
+ adapter.uploadAllRepos = jest.fn().mockResolvedValue(undefined);
68
+ // Act
69
+ await adapter.emit(types_1.ExtractorEventType.MetadataExtractionError, {
70
+ reports: [],
71
+ processed_files: [],
72
+ });
73
+ await adapter.emit(types_1.ExtractorEventType.MetadataExtractionError, {
74
+ reports: [],
75
+ processed_files: [],
76
+ });
77
+ // Assert
78
+ expect(mockPostMessage).toHaveBeenCalledTimes(1);
79
+ });
80
+ it('should emit only once even when a different event type follows', async () => {
81
+ // Arrange
82
+ adapter['adapterState'].postState = jest.fn().mockResolvedValue(undefined);
83
+ adapter.uploadAllRepos = jest.fn().mockResolvedValue(undefined);
84
+ // Act
85
+ await adapter.emit(types_1.ExtractorEventType.MetadataExtractionError, {
86
+ reports: [],
87
+ processed_files: [],
88
+ });
89
+ await adapter.emit(types_1.ExtractorEventType.DataExtractionError, {
90
+ reports: [],
91
+ processed_files: [],
92
+ });
93
+ await adapter.emit(types_1.ExtractorEventType.AttachmentExtractionError, {
94
+ reports: [],
95
+ processed_files: [],
96
+ });
97
+ // Assert
98
+ expect(mockPostMessage).toHaveBeenCalledTimes(1);
99
+ });
100
+ it('should correctly emit one event even if postState errors', async () => {
101
+ // Arrange
102
+ adapter['adapterState'].postState = jest
103
+ .fn()
104
+ .mockRejectedValue(new Error('postState error'));
105
+ adapter.uploadAllRepos = jest.fn().mockResolvedValue(undefined);
106
+ // Act
107
+ await adapter.emit(types_1.ExtractorEventType.MetadataExtractionError, {
108
+ reports: [],
109
+ processed_files: [],
110
+ });
111
+ // Assert
112
+ expect(mockPostMessage).toHaveBeenCalledTimes(1);
113
+ });
114
+ it('should correctly emit one event even if uploadAllRepos errors', async () => {
115
+ // Arrange
116
+ adapter['adapterState'].postState = jest.fn().mockResolvedValue(undefined);
117
+ adapter.uploadAllRepos = jest
118
+ .fn()
119
+ .mockRejectedValue(new Error('uploadAllRepos error'));
120
+ // Act
121
+ await adapter.emit(types_1.ExtractorEventType.MetadataExtractionError, {
122
+ reports: [],
123
+ processed_files: [],
124
+ });
125
+ // Assert
126
+ expect(mockPostMessage).toHaveBeenCalledTimes(1);
127
+ });
128
+ it('should include artifacts in data for extraction events', async () => {
129
+ // Arrange
130
+ const { emit: mockEmit } = require('../../common/control-protocol');
131
+ adapter['adapterState'].postState = jest.fn().mockResolvedValue(undefined);
132
+ adapter.uploadAllRepos = jest.fn().mockResolvedValue(undefined);
133
+ adapter['_artifacts'] = [
134
+ { id: 'art-1', item_count: 10, item_type: 'issues' },
135
+ ];
136
+ // Act
137
+ await adapter.emit(types_1.ExtractorEventType.DataExtractionDone);
138
+ // Assert
139
+ expect(mockEmit).toHaveBeenCalledWith(expect.objectContaining({
140
+ data: expect.objectContaining({
141
+ artifacts: expect.arrayContaining([
142
+ expect.objectContaining({ id: 'art-1' }),
143
+ ]),
144
+ }),
145
+ }));
146
+ const callData = mockEmit.mock.calls[0][0].data;
147
+ expect(callData).not.toHaveProperty('reports');
148
+ expect(callData).not.toHaveProperty('processed_files');
149
+ });
150
+ it('should include reports and processed_files in data for loader events', async () => {
151
+ // Arrange
152
+ 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'] = [
156
+ { item_type: 'tasks', [loading_1.ActionType.CREATED]: 5 },
157
+ ];
158
+ adapter['_processedFiles'] = ['file-1', 'file-2'];
159
+ // Act
160
+ await adapter.emit(types_1.LoaderEventType.DataLoadingDone);
161
+ // Assert
162
+ expect(mockEmit).toHaveBeenCalledWith(expect.objectContaining({
163
+ data: expect.objectContaining({
164
+ reports: expect.arrayContaining([
165
+ expect.objectContaining({ item_type: 'tasks' }),
166
+ ]),
167
+ processed_files: ['file-1', 'file-2'],
168
+ }),
169
+ }));
170
+ const callData = mockEmit.mock.calls[0][0].data;
171
+ expect(callData).not.toHaveProperty('artifacts');
172
+ });
173
+ it('should not include artifacts, reports, or processed_files for unknown event types', async () => {
174
+ // Arrange
175
+ const { emit: mockEmit } = require('../../common/control-protocol');
176
+ adapter['adapterState'].postState = jest.fn().mockResolvedValue(undefined);
177
+ adapter.uploadAllRepos = jest.fn().mockResolvedValue(undefined);
178
+ adapter['_artifacts'] = [
179
+ { id: 'art-1', item_count: 10, item_type: 'issues' },
180
+ ];
181
+ adapter['loaderReports'] = [
182
+ { item_type: 'tasks', [loading_1.ActionType.CREATED]: 5 },
183
+ ];
184
+ adapter['_processedFiles'] = ['file-1'];
185
+ // Act
186
+ await adapter.emit('SOME_UNKNOWN_EVENT');
187
+ // Assert
188
+ const callData = mockEmit.mock.calls[0][0].data;
189
+ expect(callData).not.toHaveProperty('artifacts');
190
+ expect(callData).not.toHaveProperty('reports');
191
+ expect(callData).not.toHaveProperty('processed_files');
192
+ });
193
+ it('should include artifacts for all ExtractorEventType values', async () => {
194
+ var _a, _b;
195
+ // Arrange
196
+ const { emit: mockEmit } = require('../../common/control-protocol');
197
+ const extractorEvents = [
198
+ types_1.ExtractorEventType.DataExtractionDone,
199
+ types_1.ExtractorEventType.DataExtractionProgress,
200
+ types_1.ExtractorEventType.DataExtractionError,
201
+ types_1.ExtractorEventType.AttachmentExtractionDone,
202
+ types_1.ExtractorEventType.AttachmentExtractionProgress,
203
+ ];
204
+ for (const eventType of extractorEvents) {
205
+ jest.clearAllMocks();
206
+ adapter.hasWorkerEmitted = false;
207
+ adapter['adapterState'].postState = jest
208
+ .fn()
209
+ .mockResolvedValue(undefined);
210
+ adapter.uploadAllRepos = jest.fn().mockResolvedValue(undefined);
211
+ // Act
212
+ await adapter.emit(eventType);
213
+ // Assert
214
+ const callData = (_b = (_a = mockEmit.mock.calls[0]) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.data;
215
+ expect(callData).toHaveProperty('artifacts');
216
+ expect(callData).not.toHaveProperty('reports');
217
+ }
218
+ });
219
+ it('should include reports and processed_files for all LoaderEventType values', async () => {
220
+ var _a, _b;
221
+ // Arrange
222
+ const { emit: mockEmit } = require('../../common/control-protocol');
223
+ const loaderEvents = [
224
+ types_1.LoaderEventType.DataLoadingDone,
225
+ types_1.LoaderEventType.DataLoadingProgress,
226
+ types_1.LoaderEventType.DataLoadingError,
227
+ types_1.LoaderEventType.AttachmentLoadingDone,
228
+ types_1.LoaderEventType.AttachmentLoadingProgress,
229
+ ];
230
+ for (const eventType of loaderEvents) {
231
+ jest.clearAllMocks();
232
+ adapter.hasWorkerEmitted = false;
233
+ adapter['adapterState'].postState = jest
234
+ .fn()
235
+ .mockResolvedValue(undefined);
236
+ adapter.uploadAllRepos = jest.fn().mockResolvedValue(undefined);
237
+ // Act
238
+ await adapter.emit(eventType);
239
+ // Assert
240
+ 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
+ expect(callData).toHaveProperty('reports');
242
+ expect(callData).toHaveProperty('processed_files');
243
+ expect(callData).not.toHaveProperty('artifacts');
244
+ }
245
+ });
246
+ it('should truncate a long error message, preserving the original prefix', async () => {
247
+ var _a, _b;
248
+ // Arrange
249
+ adapter['adapterState'].postState = jest.fn().mockResolvedValue(undefined);
250
+ adapter.uploadAllRepos = jest.fn().mockResolvedValue(undefined);
251
+ const longMessage = 'E'.repeat(20000);
252
+ // Act
253
+ await adapter.emit(types_1.ExtractorEventType.DataExtractionError, {
254
+ error: { message: longMessage },
255
+ });
256
+ // Assert
257
+ const { emit: mockEmit } = require('../../common/control-protocol');
258
+ const emittedMessage = (_b = (_a = mockEmit.mock.calls[0][0].data) === null || _a === void 0 ? void 0 : _a.error) === null || _b === void 0 ? void 0 : _b.message;
259
+ expect(emittedMessage.length).toBeLessThan(longMessage.length);
260
+ expect(emittedMessage.startsWith('E'.repeat(100))).toBe(true);
261
+ });
262
+ });
263
+ describe('WorkerAdapter — workersOldest / workersNewest boundary updates', () => {
264
+ let adapter;
265
+ let mockPostMessage;
266
+ beforeEach(() => {
267
+ jest.clearAllMocks();
268
+ ({ adapter } = makeAdapter());
269
+ const workerThreads = require('node:worker_threads');
270
+ mockPostMessage = jest.fn();
271
+ if (workerThreads.parentPort) {
272
+ jest
273
+ .spyOn(workerThreads.parentPort, 'postMessage')
274
+ .mockImplementation(mockPostMessage);
275
+ }
276
+ else {
277
+ workerThreads.parentPort = { postMessage: mockPostMessage };
278
+ }
279
+ adapter['adapterState'].postState = jest.fn().mockResolvedValue(undefined);
280
+ adapter.uploadAllRepos = jest.fn().mockResolvedValue(undefined);
281
+ });
282
+ afterEach(() => {
283
+ jest.restoreAllMocks();
284
+ });
285
+ async function emitDone(adapterInstance, extractionStart, extractionEnd) {
286
+ adapterInstance.event.payload.event_context.extract_from = extractionStart;
287
+ adapterInstance.event.payload.event_context.extract_to = extractionEnd;
288
+ // Reset the emit guard so we can emit multiple times within one test.
289
+ adapterInstance['hasWorkerEmitted'] = false;
290
+ await adapterInstance.emit(types_1.ExtractorEventType.AttachmentExtractionDone, {
291
+ reports: [],
292
+ processed_files: [],
293
+ });
294
+ }
295
+ describe('initial import with UNBOUNDED start', () => {
296
+ it('should set workersOldest to UNBOUNDED_DATE_TIME_VALUE and workersNewest to extraction end', async () => {
297
+ 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');
300
+ });
301
+ });
302
+ describe('reconciliation after UNBOUNDED initial import', () => {
303
+ it('should NOT overwrite workersOldest when reconciliation start is later than sentinel', async () => {
304
+ await emitDone(adapter, constants_1.UNBOUNDED_DATE_TIME_VALUE, '2025-06-01T00:00:00.000Z');
305
+ 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');
308
+ });
309
+ it('should NOT overwrite workersOldest even when reconciliation start is very early', async () => {
310
+ await emitDone(adapter, constants_1.UNBOUNDED_DATE_TIME_VALUE, '2025-06-01T00:00:00.000Z');
311
+ 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');
314
+ });
315
+ });
316
+ describe('forward sync after UNBOUNDED initial import', () => {
317
+ it('should expand workersNewest forward while preserving workersOldest', async () => {
318
+ await emitDone(adapter, constants_1.UNBOUNDED_DATE_TIME_VALUE, '2025-06-01T00:00:00.000Z');
319
+ 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');
322
+ });
323
+ });
324
+ describe('reconciliation with end beyond current newest', () => {
325
+ it('should expand workersNewest when reconciliation end is later', async () => {
326
+ await emitDone(adapter, constants_1.UNBOUNDED_DATE_TIME_VALUE, '2025-06-01T00:00:00.000Z');
327
+ 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');
330
+ });
331
+ });
332
+ describe('first sync with absolute dates (no UNBOUNDED)', () => {
333
+ it('should set both boundaries from the extraction range', async () => {
334
+ 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');
337
+ });
338
+ });
339
+ describe('reconciliation after absolute initial sync', () => {
340
+ it('should expand workersOldest backward when reconciliation start is earlier', async () => {
341
+ await emitDone(adapter, '2025-01-01T00:00:00.000Z', '2025-03-01T00:00:00.000Z');
342
+ 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');
345
+ });
346
+ it('should NOT change boundaries when reconciliation is within existing range', async () => {
347
+ await emitDone(adapter, '2025-01-01T00:00:00.000Z', '2025-03-01T00:00:00.000Z');
348
+ 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');
351
+ });
352
+ it('should expand both boundaries when reconciliation exceeds both', async () => {
353
+ await emitDone(adapter, '2025-01-01T00:00:00.000Z', '2025-03-01T00:00:00.000Z');
354
+ 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');
357
+ });
358
+ });
359
+ describe('multiple forward syncs', () => {
360
+ it('should progressively expand workersNewest while preserving workersOldest', async () => {
361
+ await emitDone(adapter, constants_1.UNBOUNDED_DATE_TIME_VALUE, '2025-06-01T00:00:00.000Z');
362
+ 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');
364
+ 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);
367
+ });
368
+ });
369
+ describe('non-AttachmentExtractionDone events should NOT update boundaries', () => {
370
+ it.each([
371
+ types_1.ExtractorEventType.DataExtractionDone,
372
+ types_1.ExtractorEventType.DataExtractionProgress,
373
+ types_1.ExtractorEventType.MetadataExtractionError,
374
+ types_1.ExtractorEventType.AttachmentExtractionError,
375
+ ])('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';
378
+ adapter.event.payload.event_context.extract_from =
379
+ '2024-01-01T00:00:00.000Z';
380
+ adapter.event.payload.event_context.extract_to =
381
+ '2025-12-01T00:00:00.000Z';
382
+ await adapter.emit(eventType, {
383
+ reports: [],
384
+ processed_files: [],
385
+ });
386
+ expect(adapter.state.workersOldest).toBe('2025-01-01T00:00:00.000Z');
387
+ expect(adapter.state.workersNewest).toBe('2025-03-01T00:00:00.000Z');
388
+ });
389
+ });
390
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=worker-adapter.extraction.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-adapter.extraction.test.d.ts","sourceRoot":"","sources":["../../../src/multithreading/worker-adapter/worker-adapter.extraction.test.ts"],"names":[],"mappings":""}