@devrev/airsync-sdk 2.0.0-beta.0 → 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.
- package/README.md +0 -4
- package/dist/airsync-sdk.d.ts +1802 -0
- package/dist/attachments-streaming/attachments-streaming-pool.d.ts +7 -0
- package/dist/attachments-streaming/attachments-streaming-pool.d.ts.map +1 -1
- package/dist/attachments-streaming/attachments-streaming-pool.js +44 -4
- package/dist/attachments-streaming/attachments-streaming-pool.test.js +259 -10
- package/dist/common/constants.d.ts +16 -5
- package/dist/common/constants.d.ts.map +1 -1
- package/dist/common/constants.js +20 -6
- package/dist/common/control-protocol.d.ts +2 -2
- package/dist/common/control-protocol.d.ts.map +1 -1
- package/dist/common/control-protocol.js +1 -5
- package/dist/common/helpers.d.ts +8 -0
- package/dist/common/helpers.d.ts.map +1 -1
- package/dist/common/helpers.js +15 -0
- package/dist/common/install-initial-domain-mapping.d.ts +2 -2
- package/dist/common/install-initial-domain-mapping.test.js +7 -3
- package/dist/common/test-utils.d.ts +19 -0
- package/dist/common/test-utils.d.ts.map +1 -0
- package/dist/common/test-utils.js +101 -0
- package/dist/common/time-value-resolver.d.ts +47 -0
- package/dist/common/time-value-resolver.d.ts.map +1 -0
- package/dist/common/time-value-resolver.js +141 -0
- package/dist/common/time-value-resolver.test.d.ts +2 -0
- package/dist/common/time-value-resolver.test.d.ts.map +1 -0
- package/dist/common/time-value-resolver.test.js +268 -0
- package/dist/http/axios-client-internal.d.ts.map +1 -1
- package/dist/http/axios-client-internal.js +7 -0
- package/dist/http/axios-client-internal.test.js +27 -6
- package/dist/http/axios-client.d.ts.map +1 -1
- package/dist/http/axios-client.js +6 -3
- package/dist/http/index.d.ts +0 -1
- package/dist/http/index.d.ts.map +1 -1
- package/dist/http/index.js +0 -1
- package/dist/index.d.ts +9 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -10
- package/dist/logger/logger.d.ts +1 -17
- package/dist/logger/logger.d.ts.map +1 -1
- package/dist/logger/logger.interfaces.d.ts +2 -2
- package/dist/logger/logger.js +35 -27
- package/dist/logger/logger.test.js +66 -19
- package/dist/mappers/mappers.interface.d.ts +5 -5
- package/dist/mappers/mappers.interface.js +3 -3
- package/dist/mappers/mappers.test.js +8 -10
- package/dist/mock-server/mock-server.d.ts +47 -0
- package/dist/mock-server/mock-server.d.ts.map +1 -0
- package/dist/mock-server/mock-server.interfaces.d.ts +73 -0
- package/dist/mock-server/mock-server.interfaces.d.ts.map +1 -0
- package/dist/mock-server/mock-server.interfaces.js +4 -0
- package/dist/mock-server/mock-server.js +278 -0
- package/dist/multithreading/create-worker.test.js +36 -17
- package/dist/multithreading/process-task.d.ts.map +1 -1
- package/dist/multithreading/process-task.js +46 -44
- package/dist/multithreading/process-task.test.d.ts +2 -0
- package/dist/multithreading/process-task.test.d.ts.map +1 -0
- package/dist/multithreading/process-task.test.js +146 -0
- package/dist/multithreading/spawn/spawn.d.ts +4 -3
- package/dist/multithreading/spawn/spawn.d.ts.map +1 -1
- package/dist/multithreading/spawn/spawn.helpers.d.ts.map +1 -1
- package/dist/multithreading/spawn/spawn.helpers.js +6 -14
- package/dist/multithreading/spawn/spawn.helpers.test.js +8 -8
- package/dist/multithreading/spawn/spawn.js +41 -31
- package/dist/multithreading/spawn/spawn.test.d.ts +2 -0
- package/dist/multithreading/spawn/spawn.test.d.ts.map +1 -0
- package/dist/multithreading/spawn/spawn.test.js +232 -0
- package/dist/multithreading/worker-adapter/worker-adapter.artifacts.test.js +49 -1
- package/dist/multithreading/worker-adapter/worker-adapter.d.ts +11 -5
- package/dist/multithreading/worker-adapter/worker-adapter.d.ts.map +1 -1
- package/dist/multithreading/worker-adapter/worker-adapter.emit.test.d.ts +2 -0
- package/dist/multithreading/worker-adapter/worker-adapter.emit.test.d.ts.map +1 -0
- package/dist/multithreading/worker-adapter/worker-adapter.emit.test.js +390 -0
- package/dist/multithreading/worker-adapter/worker-adapter.extraction.test.d.ts +2 -0
- package/dist/multithreading/worker-adapter/worker-adapter.extraction.test.d.ts.map +1 -0
- package/dist/multithreading/worker-adapter/worker-adapter.extraction.test.js +799 -0
- package/dist/multithreading/worker-adapter/worker-adapter.js +233 -134
- package/dist/multithreading/worker-adapter/worker-adapter.loading.test.d.ts +2 -0
- package/dist/multithreading/worker-adapter/worker-adapter.loading.test.d.ts.map +1 -0
- package/dist/multithreading/worker-adapter/worker-adapter.loading.test.js +596 -0
- package/dist/multithreading/worker-adapter/worker-adapter.serialization.test.d.ts +2 -0
- package/dist/multithreading/worker-adapter/worker-adapter.serialization.test.d.ts.map +1 -0
- package/dist/multithreading/worker-adapter/worker-adapter.serialization.test.js +71 -0
- package/dist/repo/repo.d.ts.map +1 -1
- package/dist/repo/repo.interfaces.d.ts +4 -2
- package/dist/repo/repo.interfaces.d.ts.map +1 -1
- package/dist/repo/repo.js +4 -3
- package/dist/repo/repo.test.js +60 -7
- package/dist/state/state.d.ts +7 -1
- package/dist/state/state.d.ts.map +1 -1
- package/dist/state/state.extract-window.test.d.ts +2 -0
- package/dist/state/state.extract-window.test.d.ts.map +1 -0
- package/dist/state/state.extract-window.test.js +163 -0
- package/dist/state/state.interfaces.d.ts +25 -8
- package/dist/state/state.interfaces.d.ts.map +1 -1
- package/dist/state/state.interfaces.js +4 -2
- package/dist/state/state.js +111 -12
- package/dist/state/state.pending-boundaries.test.d.ts +2 -0
- package/dist/state/state.pending-boundaries.test.d.ts.map +1 -0
- package/dist/state/state.pending-boundaries.test.js +189 -0
- package/dist/state/state.post-state.test.d.ts +2 -0
- package/dist/state/state.post-state.test.d.ts.map +1 -0
- package/dist/state/state.post-state.test.js +77 -0
- package/dist/state/state.test.js +117 -73
- package/dist/state/state.time-value-resolution.test.d.ts +2 -0
- package/dist/state/state.time-value-resolution.test.d.ts.map +1 -0
- package/dist/state/state.time-value-resolution.test.js +175 -0
- package/dist/tsdoc-metadata.json +11 -0
- package/dist/types/common.d.ts +0 -25
- package/dist/types/common.d.ts.map +1 -1
- package/dist/types/common.js +1 -11
- package/dist/types/external-domain-metadata.d.ts +338 -0
- package/dist/types/external-domain-metadata.d.ts.map +1 -0
- package/dist/types/extraction.d.ts +89 -218
- package/dist/types/extraction.d.ts.map +1 -1
- package/dist/types/extraction.js +56 -124
- package/dist/types/extraction.test.js +69 -43
- package/dist/types/index.d.ts +4 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +6 -3
- package/dist/types/loading.d.ts +4 -24
- package/dist/types/loading.d.ts.map +1 -1
- package/dist/types/loading.js +1 -22
- package/dist/types/workers.d.ts +31 -14
- package/dist/types/workers.d.ts.map +1 -1
- package/dist/types/workers.js +1 -0
- package/dist/uploader/uploader.d.ts +1 -0
- package/dist/uploader/uploader.d.ts.map +1 -1
- package/dist/uploader/uploader.helpers.test.js +0 -11
- package/dist/uploader/uploader.interfaces.d.ts +3 -3
- package/dist/uploader/uploader.js +53 -20
- package/dist/uploader/uploader.test.js +22 -10
- package/package.json +12 -11
- package/dist/common/event-type-translation.d.ts +0 -24
- package/dist/common/event-type-translation.d.ts.map +0 -1
- package/dist/common/event-type-translation.js +0 -117
- package/dist/deprecated/adapter/index.d.ts +0 -62
- package/dist/deprecated/adapter/index.d.ts.map +0 -1
- package/dist/deprecated/adapter/index.js +0 -151
- package/dist/deprecated/common/helpers.d.ts +0 -7
- package/dist/deprecated/common/helpers.d.ts.map +0 -1
- package/dist/deprecated/common/helpers.js +0 -47
- package/dist/deprecated/demo-extractor/external_domain_metadata.json +0 -38
- package/dist/deprecated/demo-extractor/index.d.ts +0 -18
- package/dist/deprecated/demo-extractor/index.d.ts.map +0 -1
- package/dist/deprecated/demo-extractor/index.js +0 -161
- package/dist/deprecated/http/client.d.ts +0 -22
- package/dist/deprecated/http/client.d.ts.map +0 -1
- package/dist/deprecated/http/client.js +0 -161
- package/dist/deprecated/uploader/index.d.ts +0 -35
- package/dist/deprecated/uploader/index.d.ts.map +0 -1
- package/dist/deprecated/uploader/index.js +0 -161
- package/dist/http/types.d.ts +0 -17
- package/dist/http/types.d.ts.map +0 -1
- package/dist/multithreading/worker-adapter/worker-adapter.test.d.ts +0 -2
- package/dist/multithreading/worker-adapter/worker-adapter.test.d.ts.map +0 -1
- package/dist/multithreading/worker-adapter/worker-adapter.test.js +0 -483
- /package/dist/{http/types.js → types/external-domain-metadata.js} +0 -0
|
@@ -10,6 +10,13 @@ export declare class AttachmentsStreamingPool<ConnectorState> {
|
|
|
10
10
|
private readonly PROGRESS_REPORT_INTERVAL;
|
|
11
11
|
constructor({ adapter, attachments, batchSize, stream, }: AttachmentsStreamingPoolParams<ConnectorState>);
|
|
12
12
|
private updateProgress;
|
|
13
|
+
/**
|
|
14
|
+
* Migrates processed attachments from the legacy string[] format to the new ProcessedAttachment[] format.
|
|
15
|
+
*
|
|
16
|
+
* @param attachments - The attachments list to migrate (either string[] or ProcessedAttachment[])
|
|
17
|
+
* @returns Migrated array of ProcessedAttachment objects, or empty array if input is invalid
|
|
18
|
+
*/
|
|
19
|
+
private migrateProcessedAttachments;
|
|
13
20
|
streamAll(): Promise<ProcessAttachmentReturnType>;
|
|
14
21
|
startPoolStreaming(): Promise<void>;
|
|
15
22
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachments-streaming-pool.d.ts","sourceRoot":"","sources":["../../src/attachments-streaming/attachments-streaming-pool.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"attachments-streaming-pool.d.ts","sourceRoot":"","sources":["../../src/attachments-streaming/attachments-streaming-pool.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,2BAA2B,EAC5B,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,8BAA8B,EAAE,MAAM,yCAAyC,CAAC;AAEzF,qBAAa,wBAAwB,CAAC,cAAc;IAClD,OAAO,CAAC,OAAO,CAAgC;IAC/C,OAAO,CAAC,WAAW,CAAyB;IAC5C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,MAAM,CAA4C;IAE1D,OAAO,CAAC,mBAAmB,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAM;gBAEnC,EACV,OAAO,EACP,WAAW,EACX,SAAc,EACd,MAAM,GACP,EAAE,8BAA8B,CAAC,cAAc,CAAC;YAQnC,cAAc;IAS5B;;;;;OAKG;IAEH,OAAO,CAAC,2BAA2B;IAsB7B,SAAS,IAAI,OAAO,CAAC,2BAA2B,CAAC;IA8CjD,kBAAkB;CA0FzB"}
|
|
@@ -20,6 +20,31 @@ class AttachmentsStreamingPool {
|
|
|
20
20
|
await (0, helpers_1.sleep)(100);
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Migrates processed attachments from the legacy string[] format to the new ProcessedAttachment[] format.
|
|
25
|
+
*
|
|
26
|
+
* @param attachments - The attachments list to migrate (either string[] or ProcessedAttachment[])
|
|
27
|
+
* @returns Migrated array of ProcessedAttachment objects, or empty array if input is invalid
|
|
28
|
+
*/
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
30
|
+
migrateProcessedAttachments(attachments) {
|
|
31
|
+
// Handle null/undefined
|
|
32
|
+
if (!attachments || !Array.isArray(attachments)) {
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
// If already migrated (first element is an object), return as-is
|
|
36
|
+
if (attachments.length > 0 && typeof attachments[0] === 'object') {
|
|
37
|
+
return attachments;
|
|
38
|
+
}
|
|
39
|
+
// Migrate old string[] format
|
|
40
|
+
if (attachments.length > 0 && typeof attachments[0] === 'string') {
|
|
41
|
+
return attachments.map((it) => ({
|
|
42
|
+
id: it,
|
|
43
|
+
parent_id: '',
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
23
48
|
async streamAll() {
|
|
24
49
|
console.log(`Starting download of ${this.attachments.length} attachments, streaming ${this.batchSize} at once.`);
|
|
25
50
|
if (!this.adapter.state.toDevRev) {
|
|
@@ -34,6 +59,10 @@ class AttachmentsStreamingPool {
|
|
|
34
59
|
this.adapter.state.toDevRev.attachmentsMetadata.lastProcessedAttachmentsIdsList =
|
|
35
60
|
[];
|
|
36
61
|
}
|
|
62
|
+
// Migrate old processed attachments to the new format.
|
|
63
|
+
this.adapter.state.toDevRev.attachmentsMetadata.lastProcessedAttachmentsIdsList =
|
|
64
|
+
this.migrateProcessedAttachments(this.adapter.state.toDevRev.attachmentsMetadata
|
|
65
|
+
.lastProcessedAttachmentsIdsList);
|
|
37
66
|
// Start initial batch of promises up to batchSize limit
|
|
38
67
|
const initialBatchSize = Math.min(this.batchSize, this.attachments.length);
|
|
39
68
|
const initialPromises = [];
|
|
@@ -66,7 +95,7 @@ class AttachmentsStreamingPool {
|
|
|
66
95
|
break; // Exit if no more attachments
|
|
67
96
|
}
|
|
68
97
|
if (this.adapter.state.toDevRev &&
|
|
69
|
-
((_a = this.adapter.state.toDevRev.attachmentsMetadata.lastProcessedAttachmentsIdsList) === null || _a === void 0 ? void 0 : _a.
|
|
98
|
+
((_a = this.adapter.state.toDevRev.attachmentsMetadata.lastProcessedAttachmentsIdsList) === null || _a === void 0 ? void 0 : _a.some((it) => it.id == attachment.id && it.parent_id == attachment.parent_id))) {
|
|
70
99
|
continue; // Skip if the attachment ID is already processed
|
|
71
100
|
}
|
|
72
101
|
try {
|
|
@@ -77,18 +106,29 @@ class AttachmentsStreamingPool {
|
|
|
77
106
|
return;
|
|
78
107
|
}
|
|
79
108
|
if (response === null || response === void 0 ? void 0 : response.error) {
|
|
80
|
-
|
|
109
|
+
const fileExtension = attachment.file_name.split('.').pop() || '';
|
|
110
|
+
const fileSizeInfo = response.error.fileSize
|
|
111
|
+
? `and size ${response.error.fileSize} bytes `
|
|
112
|
+
: '';
|
|
113
|
+
const contentTypeInfo = attachment.content_type
|
|
114
|
+
? `and content_type ${attachment.content_type} `
|
|
115
|
+
: '';
|
|
116
|
+
console.warn(`Skipping attachment with ID ${attachment.id} with extension ${fileExtension} ${fileSizeInfo}${contentTypeInfo}due to error returned by the stream function`, response.error.message);
|
|
81
117
|
await this.updateProgress();
|
|
82
118
|
continue;
|
|
83
119
|
}
|
|
84
120
|
// No rate limiting, process normally
|
|
85
121
|
if ((_c = (_b = this.adapter.state.toDevRev) === null || _b === void 0 ? void 0 : _b.attachmentsMetadata) === null || _c === void 0 ? void 0 : _c.lastProcessedAttachmentsIdsList) {
|
|
86
|
-
(_d = this.adapter.state.toDevRev) === null || _d === void 0 ? void 0 : _d.attachmentsMetadata.lastProcessedAttachmentsIdsList.push(attachment.id);
|
|
122
|
+
(_d = this.adapter.state.toDevRev) === null || _d === void 0 ? void 0 : _d.attachmentsMetadata.lastProcessedAttachmentsIdsList.push({ id: attachment.id, parent_id: attachment.parent_id });
|
|
87
123
|
}
|
|
88
124
|
await this.updateProgress();
|
|
89
125
|
}
|
|
90
126
|
catch (error) {
|
|
91
|
-
|
|
127
|
+
const fileExtension = attachment.file_name.split('.').pop() || '';
|
|
128
|
+
const contentTypeInfo = attachment.content_type
|
|
129
|
+
? ` and content_type ${attachment.content_type}`
|
|
130
|
+
: '';
|
|
131
|
+
console.warn(`Skipping attachment with ID ${attachment.id} with extension ${fileExtension}${contentTypeInfo} due to error in processAttachment function`, error);
|
|
92
132
|
await this.updateProgress();
|
|
93
133
|
}
|
|
94
134
|
}
|
|
@@ -44,10 +44,6 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
44
44
|
parent_id: 'parent-3',
|
|
45
45
|
},
|
|
46
46
|
];
|
|
47
|
-
// Mock console methods
|
|
48
|
-
jest.spyOn(console, 'log').mockImplementation();
|
|
49
|
-
jest.spyOn(console, 'error').mockImplementation();
|
|
50
|
-
jest.spyOn(console, 'warn').mockImplementation();
|
|
51
47
|
});
|
|
52
48
|
afterEach(() => {
|
|
53
49
|
jest.clearAllMocks();
|
|
@@ -60,7 +56,6 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
60
56
|
attachments: mockAttachments,
|
|
61
57
|
stream: mockStream,
|
|
62
58
|
});
|
|
63
|
-
expect(pool).toBeDefined();
|
|
64
59
|
expect(pool['adapter']).toBe(mockAdapter);
|
|
65
60
|
expect(pool['attachments']).toEqual(mockAttachments);
|
|
66
61
|
expect(pool['batchSize']).toBe(10);
|
|
@@ -135,11 +130,73 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
135
130
|
const result = await pool.streamAll();
|
|
136
131
|
expect(result).toEqual({ delay: 5000 });
|
|
137
132
|
});
|
|
133
|
+
it('should resume attachment extraction if it encounters old ids', async () => {
|
|
134
|
+
var _a;
|
|
135
|
+
// Test migration from old string[] format to new ProcessedAttachment[] format
|
|
136
|
+
// Using 'as any' because we're intentionally testing legacy data format
|
|
137
|
+
mockAdapter.state.toDevRev.attachmentsMetadata.lastProcessedAttachmentsIdsList =
|
|
138
|
+
['attachment-1', 'attachment-2'];
|
|
139
|
+
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
140
|
+
adapter: mockAdapter,
|
|
141
|
+
attachments: mockAttachments,
|
|
142
|
+
stream: mockStream,
|
|
143
|
+
});
|
|
144
|
+
const result = await pool.streamAll();
|
|
145
|
+
expect((_a = mockAdapter.state.toDevRev) === null || _a === void 0 ? void 0 : _a.attachmentsMetadata.lastProcessedAttachmentsIdsList).toEqual([
|
|
146
|
+
{ id: 'attachment-1', parent_id: '' },
|
|
147
|
+
{ id: 'attachment-2', parent_id: '' },
|
|
148
|
+
{ id: 'attachment-1', parent_id: 'parent-1' },
|
|
149
|
+
{ id: 'attachment-2', parent_id: 'parent-2' },
|
|
150
|
+
{ id: 'attachment-3', parent_id: 'parent-3' },
|
|
151
|
+
]);
|
|
152
|
+
expect(result).toEqual({});
|
|
153
|
+
});
|
|
154
|
+
it('should handle all attachments failing with different file types and sizes', async () => {
|
|
155
|
+
const largeAttachments = [
|
|
156
|
+
{
|
|
157
|
+
id: 'attachment-image',
|
|
158
|
+
url: 'https://example.com/photo.jpg',
|
|
159
|
+
file_name: 'photo.jpg',
|
|
160
|
+
parent_id: 'parent-1',
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
id: 'attachment-pdf',
|
|
164
|
+
url: 'https://example.com/document.pdf',
|
|
165
|
+
file_name: 'document.pdf',
|
|
166
|
+
parent_id: 'parent-2',
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
id: 'attachment-video',
|
|
170
|
+
url: 'https://example.com/video.mp4',
|
|
171
|
+
file_name: 'video.mp4',
|
|
172
|
+
parent_id: 'parent-3',
|
|
173
|
+
},
|
|
174
|
+
];
|
|
175
|
+
const imageError = new Error('Image upload failed: File too large');
|
|
176
|
+
const pdfError = new Error('PDF upload failed: Unsupported format');
|
|
177
|
+
const videoError = new Error('Video upload failed: Network error');
|
|
178
|
+
mockAdapter.processAttachment
|
|
179
|
+
.mockRejectedValueOnce(imageError)
|
|
180
|
+
.mockRejectedValueOnce(pdfError)
|
|
181
|
+
.mockRejectedValueOnce(videoError);
|
|
182
|
+
const warnSpy = jest.spyOn(console, 'warn');
|
|
183
|
+
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
184
|
+
adapter: mockAdapter,
|
|
185
|
+
attachments: largeAttachments,
|
|
186
|
+
stream: mockStream,
|
|
187
|
+
});
|
|
188
|
+
await pool.streamAll();
|
|
189
|
+
expect(mockAdapter.processAttachment).toHaveBeenCalledTimes(3);
|
|
190
|
+
// Since there are 3 parallel workers (one per attachment), each logs its own failed attachment
|
|
191
|
+
expect(warnSpy).toHaveBeenCalledTimes(3);
|
|
192
|
+
expect(mockAdapter.state.toDevRev.attachmentsMetadata
|
|
193
|
+
.lastProcessedAttachmentsIdsList).toEqual([]);
|
|
194
|
+
});
|
|
138
195
|
});
|
|
139
196
|
describe(attachments_streaming_pool_1.AttachmentsStreamingPool.prototype.startPoolStreaming.name, () => {
|
|
140
197
|
it('should skip already processed attachments', async () => {
|
|
141
198
|
mockAdapter.state.toDevRev.attachmentsMetadata.lastProcessedAttachmentsIdsList =
|
|
142
|
-
['attachment-1'];
|
|
199
|
+
[{ id: 'attachment-1', parent_id: 'parent-1' }];
|
|
143
200
|
mockAdapter.processAttachment.mockResolvedValue({});
|
|
144
201
|
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
145
202
|
adapter: mockAdapter,
|
|
@@ -158,9 +215,14 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
158
215
|
});
|
|
159
216
|
await pool.streamAll();
|
|
160
217
|
expect(mockAdapter.state.toDevRev.attachmentsMetadata
|
|
161
|
-
.lastProcessedAttachmentsIdsList).toEqual([
|
|
218
|
+
.lastProcessedAttachmentsIdsList).toEqual([
|
|
219
|
+
{ id: 'attachment-1', parent_id: 'parent-1' },
|
|
220
|
+
{ id: 'attachment-2', parent_id: 'parent-2' },
|
|
221
|
+
{ id: 'attachment-3', parent_id: 'parent-3' },
|
|
222
|
+
]);
|
|
162
223
|
});
|
|
163
224
|
it('should handle processing errors gracefully', async () => {
|
|
225
|
+
const warnSpy = jest.spyOn(console, 'warn').mockImplementation();
|
|
164
226
|
const error = new Error('Processing failed');
|
|
165
227
|
mockAdapter.processAttachment
|
|
166
228
|
.mockResolvedValueOnce({}) // First attachment succeeds
|
|
@@ -172,9 +234,18 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
172
234
|
stream: mockStream,
|
|
173
235
|
});
|
|
174
236
|
await pool.streamAll();
|
|
175
|
-
expect(
|
|
237
|
+
expect(warnSpy).toHaveBeenCalledWith('Skipping attachment with ID attachment-2 with extension jpg due to error in processAttachment function', error);
|
|
176
238
|
expect(mockAdapter.state.toDevRev.attachmentsMetadata
|
|
177
|
-
.lastProcessedAttachmentsIdsList).toEqual([
|
|
239
|
+
.lastProcessedAttachmentsIdsList).toEqual([
|
|
240
|
+
{
|
|
241
|
+
id: 'attachment-1',
|
|
242
|
+
parent_id: 'parent-1',
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
id: 'attachment-3',
|
|
246
|
+
parent_id: 'parent-3',
|
|
247
|
+
},
|
|
248
|
+
]);
|
|
178
249
|
});
|
|
179
250
|
it('should stop processing when rate limit delay is encountered', async () => {
|
|
180
251
|
mockAdapter.processAttachment
|
|
@@ -189,7 +260,10 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
189
260
|
await pool.streamAll();
|
|
190
261
|
expect(mockAdapter.processAttachment).toHaveBeenCalledTimes(3);
|
|
191
262
|
expect(mockAdapter.state.toDevRev.attachmentsMetadata
|
|
192
|
-
.lastProcessedAttachmentsIdsList).toEqual([
|
|
263
|
+
.lastProcessedAttachmentsIdsList).toEqual([
|
|
264
|
+
{ id: 'attachment-1', parent_id: 'parent-1' },
|
|
265
|
+
{ id: 'attachment-3', parent_id: 'parent-3' },
|
|
266
|
+
]);
|
|
193
267
|
});
|
|
194
268
|
it('should pass correct parameters to processAttachment', async () => {
|
|
195
269
|
mockAdapter.processAttachment.mockResolvedValue({});
|
|
@@ -224,6 +298,23 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
224
298
|
await pool.streamAll();
|
|
225
299
|
expect(mockAdapter.processAttachment).toHaveBeenCalledTimes(3);
|
|
226
300
|
});
|
|
301
|
+
it('[edge] should upload attachments with same id, but different parent_id', async () => {
|
|
302
|
+
mockAdapter.processAttachment.mockResolvedValue({});
|
|
303
|
+
mockAttachments.push({
|
|
304
|
+
id: 'attachment-1',
|
|
305
|
+
url: 'http://example.com/file5.jpg',
|
|
306
|
+
file_name: 'file5.jpg',
|
|
307
|
+
parent_id: 'parent-4',
|
|
308
|
+
});
|
|
309
|
+
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
310
|
+
adapter: mockAdapter,
|
|
311
|
+
attachments: mockAttachments,
|
|
312
|
+
batchSize: 1,
|
|
313
|
+
stream: mockStream,
|
|
314
|
+
});
|
|
315
|
+
await pool.streamAll();
|
|
316
|
+
expect(mockAdapter.processAttachment).toHaveBeenCalledTimes(4);
|
|
317
|
+
});
|
|
227
318
|
it('[edge] should handle batch size of 1', async () => {
|
|
228
319
|
mockAdapter.processAttachment.mockResolvedValue({});
|
|
229
320
|
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
@@ -235,6 +326,117 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
235
326
|
await pool.streamAll();
|
|
236
327
|
expect(mockAdapter.processAttachment).toHaveBeenCalledTimes(3);
|
|
237
328
|
});
|
|
329
|
+
describe('content_type handling', () => {
|
|
330
|
+
it('should pass attachment with content_type to processAttachment', async () => {
|
|
331
|
+
mockAdapter.processAttachment.mockResolvedValue({});
|
|
332
|
+
const attachmentWithContentType = {
|
|
333
|
+
id: 'attachment-ct',
|
|
334
|
+
url: 'https://example.com/report.pdf',
|
|
335
|
+
file_name: 'report.pdf',
|
|
336
|
+
parent_id: 'parent-ct',
|
|
337
|
+
content_type: 'application/pdf',
|
|
338
|
+
};
|
|
339
|
+
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
340
|
+
adapter: mockAdapter,
|
|
341
|
+
attachments: [attachmentWithContentType],
|
|
342
|
+
stream: mockStream,
|
|
343
|
+
});
|
|
344
|
+
await pool.streamAll();
|
|
345
|
+
expect(mockAdapter.processAttachment).toHaveBeenCalledWith(attachmentWithContentType, mockStream);
|
|
346
|
+
expect(mockAdapter.processAttachment.mock.calls[0][0].content_type).toBe('application/pdf');
|
|
347
|
+
});
|
|
348
|
+
it('should handle mixed attachments with and without content_type', async () => {
|
|
349
|
+
mockAdapter.processAttachment.mockResolvedValue({});
|
|
350
|
+
const mixedAttachments = [
|
|
351
|
+
{
|
|
352
|
+
id: 'att-with-ct',
|
|
353
|
+
url: 'https://example.com/image.png',
|
|
354
|
+
file_name: 'image.png',
|
|
355
|
+
parent_id: 'parent-1',
|
|
356
|
+
content_type: 'image/png',
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
id: 'att-without-ct',
|
|
360
|
+
url: 'https://example.com/file.bin',
|
|
361
|
+
file_name: 'file.bin',
|
|
362
|
+
parent_id: 'parent-2',
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
id: 'att-with-ct-2',
|
|
366
|
+
url: 'https://example.com/doc.pdf',
|
|
367
|
+
file_name: 'doc.pdf',
|
|
368
|
+
parent_id: 'parent-3',
|
|
369
|
+
content_type: 'application/pdf',
|
|
370
|
+
},
|
|
371
|
+
];
|
|
372
|
+
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
373
|
+
adapter: mockAdapter,
|
|
374
|
+
attachments: mixedAttachments,
|
|
375
|
+
batchSize: 1,
|
|
376
|
+
stream: mockStream,
|
|
377
|
+
});
|
|
378
|
+
await pool.streamAll();
|
|
379
|
+
expect(mockAdapter.processAttachment).toHaveBeenCalledTimes(3);
|
|
380
|
+
expect(mockAdapter.processAttachment.mock.calls[0][0].content_type).toBe('image/png');
|
|
381
|
+
expect(mockAdapter.processAttachment.mock.calls[1][0].content_type).toBeUndefined();
|
|
382
|
+
expect(mockAdapter.processAttachment.mock.calls[2][0].content_type).toBe('application/pdf');
|
|
383
|
+
});
|
|
384
|
+
it('should include content_type in error log when processAttachment returns error', async () => {
|
|
385
|
+
mockAdapter.processAttachment.mockResolvedValue({
|
|
386
|
+
error: { message: 'Upload failed' },
|
|
387
|
+
});
|
|
388
|
+
const warnSpy = jest.spyOn(console, 'warn');
|
|
389
|
+
const attachmentWithContentType = {
|
|
390
|
+
id: 'att-error-ct',
|
|
391
|
+
url: 'https://example.com/file.pdf',
|
|
392
|
+
file_name: 'file.pdf',
|
|
393
|
+
parent_id: 'parent-err',
|
|
394
|
+
content_type: 'application/pdf',
|
|
395
|
+
};
|
|
396
|
+
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
397
|
+
adapter: mockAdapter,
|
|
398
|
+
attachments: [attachmentWithContentType],
|
|
399
|
+
batchSize: 1,
|
|
400
|
+
stream: mockStream,
|
|
401
|
+
});
|
|
402
|
+
await pool.streamAll();
|
|
403
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('content_type application/pdf'), expect.any(String));
|
|
404
|
+
});
|
|
405
|
+
it('should include content_type in error log when processAttachment throws', async () => {
|
|
406
|
+
const error = new Error('Processing crashed');
|
|
407
|
+
mockAdapter.processAttachment.mockRejectedValue(error);
|
|
408
|
+
const warnSpy = jest.spyOn(console, 'warn');
|
|
409
|
+
const attachmentWithContentType = {
|
|
410
|
+
id: 'att-throw-ct',
|
|
411
|
+
url: 'https://example.com/file.png',
|
|
412
|
+
file_name: 'file.png',
|
|
413
|
+
parent_id: 'parent-throw',
|
|
414
|
+
content_type: 'image/png',
|
|
415
|
+
};
|
|
416
|
+
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
417
|
+
adapter: mockAdapter,
|
|
418
|
+
attachments: [attachmentWithContentType],
|
|
419
|
+
batchSize: 1,
|
|
420
|
+
stream: mockStream,
|
|
421
|
+
});
|
|
422
|
+
await pool.streamAll();
|
|
423
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('content_type image/png'), error);
|
|
424
|
+
});
|
|
425
|
+
it('should not include content_type in error log when content_type is not set', async () => {
|
|
426
|
+
mockAdapter.processAttachment.mockResolvedValue({
|
|
427
|
+
error: { message: 'Upload failed' },
|
|
428
|
+
});
|
|
429
|
+
const warnSpy = jest.spyOn(console, 'warn');
|
|
430
|
+
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
431
|
+
adapter: mockAdapter,
|
|
432
|
+
attachments: [mockAttachments[0]],
|
|
433
|
+
batchSize: 1,
|
|
434
|
+
stream: mockStream,
|
|
435
|
+
});
|
|
436
|
+
await pool.streamAll();
|
|
437
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.not.stringContaining('content_type'), expect.any(String));
|
|
438
|
+
});
|
|
439
|
+
});
|
|
238
440
|
describe('concurrency behavior', () => {
|
|
239
441
|
it('should process attachments concurrently within batch size', async () => {
|
|
240
442
|
let processCallCount = 0;
|
|
@@ -264,4 +466,51 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
264
466
|
expect(endTime - startTime).toBeLessThan(250);
|
|
265
467
|
});
|
|
266
468
|
});
|
|
469
|
+
describe('log context attribution', () => {
|
|
470
|
+
it('should emit SDK-generated logs from pool (Starting download message)', async () => {
|
|
471
|
+
const logSpy = jest.spyOn(console, 'log');
|
|
472
|
+
mockAdapter.processAttachment.mockResolvedValue({});
|
|
473
|
+
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
474
|
+
adapter: mockAdapter,
|
|
475
|
+
attachments: mockAttachments.slice(0, 1),
|
|
476
|
+
stream: mockStream,
|
|
477
|
+
});
|
|
478
|
+
// Call streamAll - it should log "Starting download of N attachments..."
|
|
479
|
+
await pool.streamAll();
|
|
480
|
+
// Verify the SDK-generated "Starting download" message was logged
|
|
481
|
+
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('Starting download of 1 attachments'));
|
|
482
|
+
});
|
|
483
|
+
it('should process user stream callback correctly while maintaining context isolation', async () => {
|
|
484
|
+
let userCallbackExecuted = false;
|
|
485
|
+
// Mock stream to capture context info
|
|
486
|
+
const mockStreamFn = jest
|
|
487
|
+
.fn()
|
|
488
|
+
.mockImplementation(async () => {
|
|
489
|
+
await Promise.resolve();
|
|
490
|
+
userCallbackExecuted = true;
|
|
491
|
+
// Record that the callback executed
|
|
492
|
+
return Promise.resolve({
|
|
493
|
+
httpStream: undefined,
|
|
494
|
+
error: undefined,
|
|
495
|
+
});
|
|
496
|
+
});
|
|
497
|
+
mockAdapter.processAttachment.mockImplementation(async (attachment, stream) => {
|
|
498
|
+
// processAttachment should be called with the user's stream function
|
|
499
|
+
const result = await stream({
|
|
500
|
+
item: attachment,
|
|
501
|
+
event: {},
|
|
502
|
+
});
|
|
503
|
+
return result;
|
|
504
|
+
});
|
|
505
|
+
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
506
|
+
adapter: mockAdapter,
|
|
507
|
+
attachments: mockAttachments.slice(0, 1),
|
|
508
|
+
stream: mockStreamFn,
|
|
509
|
+
});
|
|
510
|
+
await pool.streamAll();
|
|
511
|
+
// Verify the user callback was executed
|
|
512
|
+
expect(userCallbackExecuted).toBe(true);
|
|
513
|
+
expect(mockStreamFn).toHaveBeenCalled();
|
|
514
|
+
});
|
|
515
|
+
});
|
|
267
516
|
});
|
|
@@ -12,14 +12,25 @@ export declare const ARTIFACT_BATCH_SIZE = 2000;
|
|
|
12
12
|
export declare const MAX_DEVREV_ARTIFACT_SIZE: number;
|
|
13
13
|
export declare const MAX_DEVREV_FILENAME_LENGTH = 256;
|
|
14
14
|
export declare const MAX_DEVREV_FILENAME_EXTENSION_LENGTH = 20;
|
|
15
|
-
export declare const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
export declare const MAX_EVENT_SIZE_BYTES = 200000;
|
|
16
|
+
export declare const EVENT_SIZE_THRESHOLD_BYTES: number;
|
|
17
|
+
export declare const SSOR_ATTACHMENT: string;
|
|
18
|
+
export declare enum AirSyncDefaultItemTypes {
|
|
19
|
+
EXTERNAL_DOMAIN_METADATA = "external_domain_metadata",
|
|
20
|
+
ATTACHMENTS = "attachments",
|
|
21
|
+
EXTERNAL_SYNC_UNITS = "external_sync_units"
|
|
22
|
+
}
|
|
20
23
|
export declare const LIBRARY_VERSION: any;
|
|
21
24
|
export declare const DEFAULT_LAMBDA_TIMEOUT: number;
|
|
22
25
|
export declare const HARD_TIMEOUT_MULTIPLIER = 1.3;
|
|
23
26
|
export declare const MEMORY_LOG_INTERVAL: number;
|
|
24
27
|
export declare const DEFAULT_SLEEP_DELAY_MS: number;
|
|
28
|
+
/**
|
|
29
|
+
* Sentinel value representing an unbounded (no limit) extraction timestamp.
|
|
30
|
+
* Used as the resolved value for TimeValueType.UNBOUNDED, stored as workersOldest
|
|
31
|
+
* when the initial import has no lower time bound. The Unix epoch ensures that
|
|
32
|
+
* no real extraction timestamp can be earlier, preventing accidental overwrites
|
|
33
|
+
* of the boundary by subsequent syncs (e.g. reconciliation with absolute dates).
|
|
34
|
+
*/
|
|
35
|
+
export declare const UNBOUNDED_DATE_TIME_VALUE = "1970-01-01T00:00:00.000Z";
|
|
25
36
|
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/common/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD,eAAO,MAAM,8BAA8B,aAS1C,CAAC;AAEF,eAAO,MAAM,2BAA2B,aAKvC,CAAC;AAEF,eAAO,MAAM,mBAAmB,aAG/B,CAAC;AAEF,eAAO,MAAM,gCAAgC,aAI5C,CAAC;AAEF,eAAO,MAAM,6BAA6B,aAGzC,CAAC;AAEF,eAAO,MAAM,qBAAqB,aAGjC,CAAC;AAEF,eAAO,MAAM,+BAA+B,aAGzC,CAAC;AAEJ,eAAO,MAAM,4BAA4B,aAExC,CAAC;AAEF,eAAO,MAAM,oBAAoB,aAGhC,CAAC;AAEF,eAAO,MAAM,mBAAmB,OAAO,CAAC;AACxC,eAAO,MAAM,wBAAwB,QAAyB,CAAC;AAC/D,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAC9C,eAAO,MAAM,oCAAoC,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/common/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD,eAAO,MAAM,8BAA8B,aAS1C,CAAC;AAEF,eAAO,MAAM,2BAA2B,aAKvC,CAAC;AAEF,eAAO,MAAM,mBAAmB,aAG/B,CAAC;AAEF,eAAO,MAAM,gCAAgC,aAI5C,CAAC;AAEF,eAAO,MAAM,6BAA6B,aAGzC,CAAC;AAEF,eAAO,MAAM,qBAAqB,aAGjC,CAAC;AAEF,eAAO,MAAM,+BAA+B,aAGzC,CAAC;AAEJ,eAAO,MAAM,4BAA4B,aAExC,CAAC;AAEF,eAAO,MAAM,oBAAoB,aAGhC,CAAC;AAEF,eAAO,MAAM,mBAAmB,OAAO,CAAC;AACxC,eAAO,MAAM,wBAAwB,QAAyB,CAAC;AAC/D,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAC9C,eAAO,MAAM,oCAAoC,KAAK,CAAC;AAGvD,eAAO,MAAM,oBAAoB,SAAU,CAAC;AAE5C,eAAO,MAAM,0BAA0B,QAEtC,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,MAA0B,CAAC;AAEzD,oBAAY,uBAAuB;IACjC,wBAAwB,6BAA6B;IACrD,WAAW,gBAAgB;IAC3B,mBAAmB,wBAAwB;CAC5C;AAED,eAAO,MAAM,eAAe,KAAsB,CAAC;AAEnD,eAAO,MAAM,sBAAsB,QAAiB,CAAC;AACrD,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,eAAO,MAAM,mBAAmB,QAAY,CAAC;AAE7C,eAAO,MAAM,sBAAsB,QAAgB,CAAC;AAEpD;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,6BAA6B,CAAC"}
|
package/dist/common/constants.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DEFAULT_SLEEP_DELAY_MS = exports.MEMORY_LOG_INTERVAL = exports.HARD_TIMEOUT_MULTIPLIER = exports.DEFAULT_LAMBDA_TIMEOUT = exports.LIBRARY_VERSION = exports.
|
|
3
|
+
exports.UNBOUNDED_DATE_TIME_VALUE = exports.DEFAULT_SLEEP_DELAY_MS = exports.MEMORY_LOG_INTERVAL = exports.HARD_TIMEOUT_MULTIPLIER = exports.DEFAULT_LAMBDA_TIMEOUT = exports.LIBRARY_VERSION = exports.AirSyncDefaultItemTypes = exports.SSOR_ATTACHMENT = exports.EVENT_SIZE_THRESHOLD_BYTES = exports.MAX_EVENT_SIZE_BYTES = exports.MAX_DEVREV_FILENAME_EXTENSION_LENGTH = exports.MAX_DEVREV_FILENAME_LENGTH = exports.MAX_DEVREV_ARTIFACT_SIZE = exports.ARTIFACT_BATCH_SIZE = exports.STATEFUL_EVENT_TYPES = exports.STATEFUL_LOADING_EVENT_TYPES = exports.STATEFUL_EXTRACTION_EVENT_TYPES = exports.STATELESS_EVENT_TYPES = exports.STATELESS_LOADING_EVENT_TYPES = exports.STATELESS_EXTRACTION_EVENT_TYPES = exports.ALLOWED_EVENT_TYPES = exports.ALLOWED_LOADING_EVENT_TYPES = exports.ALLOWED_EXTRACTION_EVENT_TYPES = void 0;
|
|
4
4
|
const extraction_1 = require("../types/extraction");
|
|
5
5
|
const helpers_1 = require("./helpers");
|
|
6
6
|
exports.ALLOWED_EXTRACTION_EVENT_TYPES = [
|
|
@@ -46,13 +46,27 @@ exports.ARTIFACT_BATCH_SIZE = 2000;
|
|
|
46
46
|
exports.MAX_DEVREV_ARTIFACT_SIZE = 2 * 1024 * 1024 * 1024; // 2GB
|
|
47
47
|
exports.MAX_DEVREV_FILENAME_LENGTH = 256;
|
|
48
48
|
exports.MAX_DEVREV_FILENAME_EXTENSION_LENGTH = 20; // 20 characters for the file extension
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
// Max SQS message size is 250KB, we want to leave some room for the other data in the message
|
|
50
|
+
exports.MAX_EVENT_SIZE_BYTES = 200000;
|
|
51
|
+
// We want to leave some room for the other data in the message and process the rest of queued messages
|
|
52
|
+
exports.EVENT_SIZE_THRESHOLD_BYTES = Math.floor(exports.MAX_EVENT_SIZE_BYTES * 0.8);
|
|
53
|
+
exports.SSOR_ATTACHMENT = 'ssor_attachment';
|
|
54
|
+
var AirSyncDefaultItemTypes;
|
|
55
|
+
(function (AirSyncDefaultItemTypes) {
|
|
56
|
+
AirSyncDefaultItemTypes["EXTERNAL_DOMAIN_METADATA"] = "external_domain_metadata";
|
|
57
|
+
AirSyncDefaultItemTypes["ATTACHMENTS"] = "attachments";
|
|
58
|
+
AirSyncDefaultItemTypes["EXTERNAL_SYNC_UNITS"] = "external_sync_units";
|
|
59
|
+
})(AirSyncDefaultItemTypes || (exports.AirSyncDefaultItemTypes = AirSyncDefaultItemTypes = {}));
|
|
54
60
|
exports.LIBRARY_VERSION = (0, helpers_1.getLibraryVersion)();
|
|
55
61
|
exports.DEFAULT_LAMBDA_TIMEOUT = 10 * 60 * 1000; // 10 minutes
|
|
56
62
|
exports.HARD_TIMEOUT_MULTIPLIER = 1.3;
|
|
57
63
|
exports.MEMORY_LOG_INTERVAL = 30 * 1000; // 30 seconds
|
|
58
64
|
exports.DEFAULT_SLEEP_DELAY_MS = 3 * 60 * 1000; // 3 minutes
|
|
65
|
+
/**
|
|
66
|
+
* Sentinel value representing an unbounded (no limit) extraction timestamp.
|
|
67
|
+
* Used as the resolved value for TimeValueType.UNBOUNDED, stored as workersOldest
|
|
68
|
+
* when the initial import has no lower time bound. The Unix epoch ensures that
|
|
69
|
+
* no real extraction timestamp can be earlier, preventing accidental overwrites
|
|
70
|
+
* of the boundary by subsequent syncs (e.g. reconciliation with absolute dates).
|
|
71
|
+
*/
|
|
72
|
+
exports.UNBOUNDED_DATE_TIME_VALUE = '1970-01-01T00:00:00.000Z';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { AxiosResponse } from 'axios';
|
|
2
|
-
import {
|
|
2
|
+
import { AirSyncEvent, EventData, ExtractorEventType } from '../types/extraction';
|
|
3
3
|
import { LoaderEventType } from '../types/loading';
|
|
4
4
|
export interface EmitInterface {
|
|
5
|
-
event:
|
|
5
|
+
event: AirSyncEvent;
|
|
6
6
|
eventType: ExtractorEventType | LoaderEventType;
|
|
7
7
|
data?: EventData;
|
|
8
8
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-protocol.d.ts","sourceRoot":"","sources":["../../src/common/control-protocol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEtC,OAAO,EACL,YAAY,EACZ,SAAS,EAET,kBAAkB,EAEnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"control-protocol.d.ts","sourceRoot":"","sources":["../../src/common/control-protocol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEtC,OAAO,EACL,YAAY,EACZ,SAAS,EAET,kBAAkB,EAEnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGnD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,kBAAkB,GAAG,eAAe,CAAC;IAChD,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED,eAAO,MAAM,IAAI,GAAU,6BAIxB,aAAa,KAAG,OAAO,CAAC,aAAa,CA4BvC,CAAC"}
|
|
@@ -3,13 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.emit = void 0;
|
|
4
4
|
const axios_client_internal_1 = require("../http/axios-client-internal");
|
|
5
5
|
const constants_1 = require("./constants");
|
|
6
|
-
const event_type_translation_1 = require("./event-type-translation");
|
|
7
6
|
const emit = async ({ event, eventType, data, }) => {
|
|
8
|
-
// Translate outgoing event type to ensure we always send new event types
|
|
9
|
-
// TODO: Remove when the old types are completely phased out
|
|
10
|
-
const translatedEventType = (0, event_type_translation_1.translateOutgoingEventType)(eventType);
|
|
11
7
|
const newEvent = {
|
|
12
|
-
event_type:
|
|
8
|
+
event_type: eventType,
|
|
13
9
|
event_context: event.payload.event_context,
|
|
14
10
|
event_data: Object.assign({}, data),
|
|
15
11
|
worker_metadata: {
|
package/dist/common/helpers.d.ts
CHANGED
|
@@ -38,4 +38,12 @@ export interface MemoryInfo {
|
|
|
38
38
|
* @returns {MemoryInfo} The memory usage information
|
|
39
39
|
*/
|
|
40
40
|
export declare function getMemoryUsage(): MemoryInfo;
|
|
41
|
+
/**
|
|
42
|
+
* Truncates a message if it exceeds the maximum allowed length.
|
|
43
|
+
* Adds a suffix indicating how many characters were omitted.
|
|
44
|
+
*
|
|
45
|
+
* @param message - The message to truncate
|
|
46
|
+
* @returns Truncated message or original if within limits
|
|
47
|
+
*/
|
|
48
|
+
export declare function truncateMessage(message: string): string;
|
|
41
49
|
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/common/helpers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/common/helpers.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,wBAAgB,iBAAiB,QAiBhC;AAED;;;;GAIG;AACH,wBAAsB,KAAK,CAAC,EAAE,EAAE,MAAM,oBAGrC;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAmBzD;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,UAAU,CAmD3C;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOvD"}
|
package/dist/common/helpers.js
CHANGED
|
@@ -37,10 +37,12 @@ exports.getLibraryVersion = getLibraryVersion;
|
|
|
37
37
|
exports.sleep = sleep;
|
|
38
38
|
exports.truncateFilename = truncateFilename;
|
|
39
39
|
exports.getMemoryUsage = getMemoryUsage;
|
|
40
|
+
exports.truncateMessage = truncateMessage;
|
|
40
41
|
const fs_1 = require("fs");
|
|
41
42
|
const path = __importStar(require("path"));
|
|
42
43
|
const v8 = __importStar(require("v8"));
|
|
43
44
|
const constants_1 = require("./constants");
|
|
45
|
+
const logger_constants_1 = require("../logger/logger.constants");
|
|
44
46
|
/**
|
|
45
47
|
* Gets the library version from the package.json file.
|
|
46
48
|
* @returns {string} The library version
|
|
@@ -122,3 +124,16 @@ function getMemoryUsage() {
|
|
|
122
124
|
throw err;
|
|
123
125
|
}
|
|
124
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Truncates a message if it exceeds the maximum allowed length.
|
|
129
|
+
* Adds a suffix indicating how many characters were omitted.
|
|
130
|
+
*
|
|
131
|
+
* @param message - The message to truncate
|
|
132
|
+
* @returns Truncated message or original if within limits
|
|
133
|
+
*/
|
|
134
|
+
function truncateMessage(message) {
|
|
135
|
+
if (message.length > logger_constants_1.MAX_LOG_STRING_LENGTH) {
|
|
136
|
+
return `${message.substring(0, logger_constants_1.MAX_LOG_STRING_LENGTH)}... ${message.length - logger_constants_1.MAX_LOG_STRING_LENGTH} more characters`;
|
|
137
|
+
}
|
|
138
|
+
return message;
|
|
139
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AirSyncEvent } from '../types/extraction';
|
|
2
2
|
import { InitialDomainMapping } from '../types/common';
|
|
3
|
-
export declare function installInitialDomainMapping(event:
|
|
3
|
+
export declare function installInitialDomainMapping(event: AirSyncEvent, initialDomainMappingJson: InitialDomainMapping): Promise<void>;
|
|
4
4
|
//# sourceMappingURL=install-initial-domain-mapping.d.ts.map
|
|
@@ -5,7 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const axios_1 = __importDefault(require("axios"));
|
|
7
7
|
const axios_client_internal_1 = require("../http/axios-client-internal");
|
|
8
|
-
const
|
|
8
|
+
const jest_setup_1 = require("../tests/jest.setup");
|
|
9
|
+
const test_utils_1 = require("./test-utils");
|
|
9
10
|
const extraction_1 = require("../types/extraction");
|
|
10
11
|
const install_initial_domain_mapping_1 = require("./install-initial-domain-mapping");
|
|
11
12
|
// Mock dependencies
|
|
@@ -22,7 +23,9 @@ const mockAxiosClient = axios_client_internal_1.axiosClient;
|
|
|
22
23
|
const mockIsAxiosError = axios_1.default.isAxiosError;
|
|
23
24
|
describe(install_initial_domain_mapping_1.installInitialDomainMapping.name, () => {
|
|
24
25
|
// Create mock objects
|
|
25
|
-
const mockEvent = (0,
|
|
26
|
+
const mockEvent = (0, test_utils_1.createMockEvent)(jest_setup_1.mockServer.baseUrl, {
|
|
27
|
+
payload: { event_type: extraction_1.EventType.StartExtractingData },
|
|
28
|
+
});
|
|
26
29
|
const mockInitialDomainMapping = {
|
|
27
30
|
starting_recipe_blueprint: {
|
|
28
31
|
name: 'Test Recipe Blueprint',
|
|
@@ -40,7 +43,8 @@ describe(install_initial_domain_mapping_1.installInitialDomainMapping.name, () =
|
|
|
40
43
|
},
|
|
41
44
|
},
|
|
42
45
|
};
|
|
43
|
-
|
|
46
|
+
// Use the endpoint from the event to support dynamic ports in parallel tests
|
|
47
|
+
const mockEndpoint = mockEvent.execution_metadata.devrev_endpoint;
|
|
44
48
|
const mockToken = 'test_token';
|
|
45
49
|
// After each test, clear all mocks to prevent state from leaking.
|
|
46
50
|
afterEach(() => {
|