@devrev/ts-adaas 1.10.0 → 1.10.1-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/dist/repo/repo.d.ts +2 -0
- package/dist/repo/repo.d.ts.map +1 -1
- package/dist/repo/repo.js +2 -0
- package/dist/uploader/uploader.d.ts +5 -0
- package/dist/uploader/uploader.d.ts.map +1 -1
- package/dist/uploader/uploader.js +22 -0
- package/dist/workers/default-workers/attachments-extraction.js +42 -1
- package/dist/workers/worker-adapter.artifacts.test.d.ts +2 -0
- package/dist/workers/worker-adapter.artifacts.test.d.ts.map +1 -0
- package/dist/workers/worker-adapter.artifacts.test.js +135 -0
- package/dist/workers/worker-adapter.d.ts +5 -0
- package/dist/workers/worker-adapter.d.ts.map +1 -1
- package/dist/workers/worker-adapter.js +22 -1
- package/package.json +4 -5
package/dist/repo/repo.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ErrorRecord } from '../types/common';
|
|
2
2
|
import { Item } from '../repo/repo.interfaces';
|
|
3
|
+
import { Artifact } from '../uploader/uploader.interfaces';
|
|
3
4
|
import { RepoFactoryInterface, NormalizedItem, NormalizedAttachment } from './repo.interfaces';
|
|
4
5
|
export declare class Repo {
|
|
5
6
|
readonly itemType: string;
|
|
@@ -8,6 +9,7 @@ export declare class Repo {
|
|
|
8
9
|
private uploader;
|
|
9
10
|
private onUpload;
|
|
10
11
|
private options?;
|
|
12
|
+
uploadedArtifacts: Artifact[];
|
|
11
13
|
constructor({ event, itemType, normalize, onUpload, options, }: RepoFactoryInterface);
|
|
12
14
|
getItems(): (NormalizedItem | NormalizedAttachment | Item)[];
|
|
13
15
|
upload(batch?: (NormalizedItem | NormalizedAttachment | Item)[]): Promise<void | ErrorRecord>;
|
package/dist/repo/repo.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repo.d.ts","sourceRoot":"","sources":["../../src/repo/repo.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"repo.d.ts","sourceRoot":"","sources":["../../src/repo/repo.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAE3D,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,oBAAoB,EACrB,MAAM,mBAAmB,CAAC;AAG3B,qBAAa,IAAI;IACf,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,KAAK,CAAmD;IAChE,OAAO,CAAC,SAAS,CAAC,CAAwD;IAC1E,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,OAAO,CAAC,CAAuB;IAChC,iBAAiB,EAAE,QAAQ,EAAE,CAAC;gBAEzB,EACV,KAAK,EACL,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,OAAO,GACR,EAAE,oBAAoB;IAUvB,QAAQ,IAAI,CAAC,cAAc,GAAG,oBAAoB,GAAG,IAAI,CAAC,EAAE;IAItD,MAAM,CACV,KAAK,CAAC,EAAE,CAAC,cAAc,GAAG,oBAAoB,GAAG,IAAI,CAAC,EAAE,GACvD,OAAO,CAAC,IAAI,GAAG,WAAW,CAAC;IAqCxB,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;CAuC5C"}
|
package/dist/repo/repo.js
CHANGED
|
@@ -11,6 +11,7 @@ class Repo {
|
|
|
11
11
|
this.onUpload = onUpload;
|
|
12
12
|
this.uploader = new uploader_1.Uploader({ event, options });
|
|
13
13
|
this.options = options;
|
|
14
|
+
this.uploadedArtifacts = [];
|
|
14
15
|
}
|
|
15
16
|
getItems() {
|
|
16
17
|
return this.items;
|
|
@@ -25,6 +26,7 @@ class Repo {
|
|
|
25
26
|
return error;
|
|
26
27
|
}
|
|
27
28
|
this.onUpload(artifact);
|
|
29
|
+
this.uploadedArtifacts.push(artifact);
|
|
28
30
|
// Clear the uploaded items from the main items array if no batch was specified
|
|
29
31
|
if (!batch) {
|
|
30
32
|
this.items = [];
|
|
@@ -23,6 +23,11 @@ export declare class Uploader {
|
|
|
23
23
|
uploadArtifact(artifact: ArtifactToUpload, file: Buffer): Promise<AxiosResponse | void>;
|
|
24
24
|
streamArtifact(artifact: ArtifactToUpload, fileStream: any): Promise<AxiosResponse | void>;
|
|
25
25
|
confirmArtifactUpload(artifactId: string): Promise<AxiosResponse | void>;
|
|
26
|
+
/**
|
|
27
|
+
* Destroys a stream to prevent resource leaks.
|
|
28
|
+
* @param {any} fileStream - The axios response stream to destroy
|
|
29
|
+
*/
|
|
30
|
+
private destroyStream;
|
|
26
31
|
getAttachmentsFromArtifactId({ artifact, }: {
|
|
27
32
|
artifact: string;
|
|
28
33
|
}): Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uploader.d.ts","sourceRoot":"","sources":["../../src/uploader/uploader.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAG/D,OAAO,EAEL,cAAc,EACd,wBAAwB,EACxB,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEtC,qBAAa,QAAQ;IACnB,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,kBAAkB,CAAC,CAAU;IACrC,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAyB;gBAEnC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,wBAAwB;IAWxD;;;;;;;;OAQG;IACG,MAAM,CACV,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EAAE,GAAG,MAAM,GAChC,OAAO,CAAC,cAAc,CAAC;IAwDpB,oBAAoB,CACxB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAuB7B,cAAc,CAClB,QAAQ,EAAE,gBAAgB,EAC1B,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAmB1B,cAAc,CAClB,QAAQ,EAAE,gBAAgB,EAC1B,UAAU,EAAE,GAAG,GACd,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"uploader.d.ts","sourceRoot":"","sources":["../../src/uploader/uploader.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAG/D,OAAO,EAEL,cAAc,EACd,wBAAwB,EACxB,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEtC,qBAAa,QAAQ;IACnB,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,kBAAkB,CAAC,CAAU;IACrC,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAyB;gBAEnC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,wBAAwB;IAWxD;;;;;;;;OAQG;IACG,MAAM,CACV,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EAAE,GAAG,MAAM,GAChC,OAAO,CAAC,cAAc,CAAC;IAwDpB,oBAAoB,CACxB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAuB7B,cAAc,CAClB,QAAQ,EAAE,gBAAgB,EAC1B,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAmB1B,cAAc,CAClB,QAAQ,EAAE,gBAAgB,EAC1B,UAAU,EAAE,GAAG,GACd,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAoC1B,qBAAqB,CACzB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAwBhC;;;OAGG;IACH,OAAO,CAAC,aAAa;IAef,4BAA4B,CAAC,EACjC,QAAQ,GACT,EAAE;QACD,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC;QACV,WAAW,CAAC,EAAE,oBAAoB,EAAE,CAAC;QACrC,KAAK,CAAC,EAAE;YAAE,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC;KAC7B,CAAC;YAqCY,sBAAsB;YAyBtB,gBAAgB;IAe9B,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,UAAU;IASZ,yBAAyB,CAAC,EAC9B,UAAU,EACV,SAAiB,GAClB,EAAE;QACD,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,OAAO,CAAC;KACrB,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAAC;YAyBvB,eAAe;CA8B9B"}
|
|
@@ -148,6 +148,7 @@ class Uploader {
|
|
|
148
148
|
formData.append('file', fileStream.data);
|
|
149
149
|
if (fileStream.headers['content-length'] > constants_1.MAX_DEVREV_ARTIFACT_SIZE) {
|
|
150
150
|
console.warn(`File size exceeds the maximum limit of ${constants_1.MAX_DEVREV_ARTIFACT_SIZE} bytes.`);
|
|
151
|
+
this.destroyStream(fileStream);
|
|
151
152
|
return;
|
|
152
153
|
}
|
|
153
154
|
try {
|
|
@@ -164,6 +165,7 @@ class Uploader {
|
|
|
164
165
|
}
|
|
165
166
|
catch (error) {
|
|
166
167
|
console.error('Error while streaming artifact.', (0, logger_1.serializeError)(error));
|
|
168
|
+
this.destroyStream(fileStream);
|
|
167
169
|
return;
|
|
168
170
|
}
|
|
169
171
|
}
|
|
@@ -182,6 +184,26 @@ class Uploader {
|
|
|
182
184
|
console.error('Error while confirming artifact upload.', (0, logger_1.serializeError)(error));
|
|
183
185
|
}
|
|
184
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* Destroys a stream to prevent resource leaks.
|
|
189
|
+
* @param {any} fileStream - The axios response stream to destroy
|
|
190
|
+
*/
|
|
191
|
+
destroyStream(fileStream) {
|
|
192
|
+
try {
|
|
193
|
+
if (fileStream && fileStream.data) {
|
|
194
|
+
// For axios response streams, the data property contains the actual stream
|
|
195
|
+
if (typeof fileStream.data.destroy === 'function') {
|
|
196
|
+
fileStream.data.destroy();
|
|
197
|
+
}
|
|
198
|
+
else if (typeof fileStream.data.close === 'function') {
|
|
199
|
+
fileStream.data.close();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
console.warn('Error while destroying stream:', (0, logger_1.serializeError)(error));
|
|
205
|
+
}
|
|
206
|
+
}
|
|
185
207
|
async getAttachmentsFromArtifactId({ artifact, }) {
|
|
186
208
|
// Get the URL of the attachments metadata artifact
|
|
187
209
|
const artifactUrl = await this.getArtifactDownloadUrl(artifact);
|
|
@@ -6,10 +6,28 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const axios_1 = __importDefault(require("axios"));
|
|
7
7
|
const index_1 = require("../../index");
|
|
8
8
|
const axios_client_internal_1 = require("../../http/axios-client-internal");
|
|
9
|
+
const constants_1 = require("../../common/constants");
|
|
9
10
|
const getAttachmentStream = async ({ item, }) => {
|
|
10
11
|
const { id, url } = item;
|
|
12
|
+
let fileStreamResponse = null;
|
|
11
13
|
try {
|
|
12
|
-
|
|
14
|
+
// First, check file size with HEAD request to avoid downloading large files
|
|
15
|
+
const headResponse = await axios_client_internal_1.axiosClient.head(url, {
|
|
16
|
+
headers: {
|
|
17
|
+
'Accept-Encoding': 'identity',
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
const contentLength = headResponse.headers['content-length'];
|
|
21
|
+
if (contentLength && parseInt(contentLength) > constants_1.MAX_DEVREV_ARTIFACT_SIZE) {
|
|
22
|
+
console.warn(`Attachment ${id} size (${contentLength} bytes) exceeds maximum limit of ${constants_1.MAX_DEVREV_ARTIFACT_SIZE} bytes. Skipping download.`);
|
|
23
|
+
return {
|
|
24
|
+
error: {
|
|
25
|
+
message: `File size exceeds maximum limit of ${constants_1.MAX_DEVREV_ARTIFACT_SIZE} bytes.`,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
// If size is acceptable, proceed with streaming
|
|
30
|
+
fileStreamResponse = await axios_client_internal_1.axiosClient.get(url, {
|
|
13
31
|
responseType: 'stream',
|
|
14
32
|
headers: {
|
|
15
33
|
'Accept-Encoding': 'identity',
|
|
@@ -18,6 +36,10 @@ const getAttachmentStream = async ({ item, }) => {
|
|
|
18
36
|
return { httpStream: fileStreamResponse };
|
|
19
37
|
}
|
|
20
38
|
catch (error) {
|
|
39
|
+
// If we created a stream but failed afterwards, destroy it
|
|
40
|
+
if (fileStreamResponse) {
|
|
41
|
+
destroyHttpStream(fileStreamResponse);
|
|
42
|
+
}
|
|
21
43
|
if (axios_1.default.isAxiosError(error)) {
|
|
22
44
|
console.warn(`Error while fetching attachment ${id} from URL.`, (0, index_1.serializeAxiosError)(error));
|
|
23
45
|
console.warn('Failed attachment metadata', item);
|
|
@@ -33,6 +55,25 @@ const getAttachmentStream = async ({ item, }) => {
|
|
|
33
55
|
};
|
|
34
56
|
}
|
|
35
57
|
};
|
|
58
|
+
/**
|
|
59
|
+
* Destroys a stream to prevent memory leaks.
|
|
60
|
+
* @param {any} httpStream - The axios response stream to destroy
|
|
61
|
+
*/
|
|
62
|
+
const destroyHttpStream = (httpStream) => {
|
|
63
|
+
try {
|
|
64
|
+
if (httpStream && httpStream.data) {
|
|
65
|
+
if (typeof httpStream.data.destroy === 'function') {
|
|
66
|
+
httpStream.data.destroy();
|
|
67
|
+
}
|
|
68
|
+
else if (typeof httpStream.data.close === 'function') {
|
|
69
|
+
httpStream.data.close();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
console.warn('Error while destroying HTTP stream:', error);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
36
77
|
(0, index_1.processTask)({
|
|
37
78
|
task: async ({ adapter }) => {
|
|
38
79
|
try {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-adapter.artifacts.test.d.ts","sourceRoot":"","sources":["../../src/workers/worker-adapter.artifacts.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const test_helpers_1 = require("../tests/test-helpers");
|
|
4
|
+
const worker_adapter_1 = require("./worker-adapter");
|
|
5
|
+
const state_1 = require("../state/state");
|
|
6
|
+
const types_1 = require("../types");
|
|
7
|
+
// 1. Create a mock function for the method you want to override.
|
|
8
|
+
const mockUpload = (itemType, objects) => {
|
|
9
|
+
return {
|
|
10
|
+
error: null,
|
|
11
|
+
artifact: {
|
|
12
|
+
id: `artifact-${itemType}-${Math.random().toString(36).substring(2, 15)}`,
|
|
13
|
+
item_type: itemType,
|
|
14
|
+
item_count: objects.length,
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
// 2. Mock the entire 'uploader' module.
|
|
19
|
+
// The factory function () => { ... } returns the mock implementation.
|
|
20
|
+
jest.mock('../uploader/uploader', () => {
|
|
21
|
+
return {
|
|
22
|
+
// The mocked Uploader class
|
|
23
|
+
Uploader: jest.fn().mockImplementation(() => {
|
|
24
|
+
// The constructor of the mocked Uploader returns an object
|
|
25
|
+
// with the methods you want to control.
|
|
26
|
+
return {
|
|
27
|
+
upload: mockUpload,
|
|
28
|
+
};
|
|
29
|
+
}),
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
function checkArtifactOrder(artifacts, expectedOrder) {
|
|
33
|
+
let outerIndex = 0;
|
|
34
|
+
for (const artifact of artifacts) {
|
|
35
|
+
try {
|
|
36
|
+
// Always increase outer index. If items are out of order, the array will overflow and exception will be thrown
|
|
37
|
+
while (artifact.item_type != expectedOrder[outerIndex].itemType) {
|
|
38
|
+
outerIndex++;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
console.error("Error finding artifact type in repos:", e);
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
describe("Artifact ordering when artifacts overflow batch sizes in repositories", () => {
|
|
49
|
+
let testAdapter;
|
|
50
|
+
beforeEach(() => {
|
|
51
|
+
// Create a fresh adapter instance for this test to avoid mocking conflicts
|
|
52
|
+
let mockEvent = (0, test_helpers_1.createEvent)({ eventType: types_1.EventType.ExtractionDataStart });
|
|
53
|
+
let mockAdapterState = new state_1.State({
|
|
54
|
+
event: mockEvent,
|
|
55
|
+
initialState: { attachments: { completed: false } },
|
|
56
|
+
});
|
|
57
|
+
testAdapter = new worker_adapter_1.WorkerAdapter({
|
|
58
|
+
event: mockEvent,
|
|
59
|
+
adapterState: mockAdapterState,
|
|
60
|
+
options: {
|
|
61
|
+
batchSize: 50
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
it('should maintain artifact ordering when repo ItemTypeA has items below batch size and repo ItemTypeB has items above batch size', async () => {
|
|
66
|
+
var _a, _b;
|
|
67
|
+
const repos = [
|
|
68
|
+
{ itemType: 'ItemTypeA' },
|
|
69
|
+
{ itemType: 'ItemTypeB' }
|
|
70
|
+
];
|
|
71
|
+
// Initialize repos
|
|
72
|
+
testAdapter.initializeRepos(repos);
|
|
73
|
+
await ((_a = testAdapter.getRepo('ItemTypeA')) === null || _a === void 0 ? void 0 : _a.push((0, test_helpers_1.createItems)(5)));
|
|
74
|
+
await ((_b = testAdapter.getRepo('ItemTypeB')) === null || _b === void 0 ? void 0 : _b.push((0, test_helpers_1.createItems)(105)));
|
|
75
|
+
await testAdapter.uploadAllRepos();
|
|
76
|
+
const artifacts = testAdapter.artifacts;
|
|
77
|
+
expect(artifacts.length).toBe(4);
|
|
78
|
+
expect(checkArtifactOrder(artifacts, repos)).toBe(true);
|
|
79
|
+
});
|
|
80
|
+
it('should work with more than 2 repos', async () => {
|
|
81
|
+
var _a, _b, _c, _d;
|
|
82
|
+
const repos = [
|
|
83
|
+
{ itemType: 'ItemTypeA' },
|
|
84
|
+
{ itemType: 'ItemTypeB' },
|
|
85
|
+
{ itemType: 'ItemTypeC' },
|
|
86
|
+
{ itemType: 'ItemTypeD' },
|
|
87
|
+
];
|
|
88
|
+
// Initialize repos
|
|
89
|
+
testAdapter.initializeRepos(repos);
|
|
90
|
+
await ((_a = testAdapter.getRepo('ItemTypeA')) === null || _a === void 0 ? void 0 : _a.push((0, test_helpers_1.createItems)(101)));
|
|
91
|
+
await ((_b = testAdapter.getRepo('ItemTypeB')) === null || _b === void 0 ? void 0 : _b.push((0, test_helpers_1.createItems)(102)));
|
|
92
|
+
await ((_c = testAdapter.getRepo('ItemTypeC')) === null || _c === void 0 ? void 0 : _c.push((0, test_helpers_1.createItems)(103)));
|
|
93
|
+
await ((_d = testAdapter.getRepo('ItemTypeD')) === null || _d === void 0 ? void 0 : _d.push((0, test_helpers_1.createItems)(104)));
|
|
94
|
+
await testAdapter.uploadAllRepos();
|
|
95
|
+
const artifacts = testAdapter.artifacts;
|
|
96
|
+
expect(artifacts.length).toBe(12);
|
|
97
|
+
expect(checkArtifactOrder(artifacts, repos)).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
it('should maintain order with multiple pushes and uploads', async () => {
|
|
100
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
101
|
+
const repos = [
|
|
102
|
+
{ itemType: 'ItemTypeA' },
|
|
103
|
+
{ itemType: 'ItemTypeB' },
|
|
104
|
+
];
|
|
105
|
+
// Initialize repos
|
|
106
|
+
testAdapter.initializeRepos(repos);
|
|
107
|
+
await ((_a = testAdapter.getRepo('ItemTypeA')) === null || _a === void 0 ? void 0 : _a.push((0, test_helpers_1.createItems)(101)));
|
|
108
|
+
await ((_b = testAdapter.getRepo('ItemTypeB')) === null || _b === void 0 ? void 0 : _b.push((0, test_helpers_1.createItems)(102)));
|
|
109
|
+
await ((_c = testAdapter.getRepo('ItemTypeA')) === null || _c === void 0 ? void 0 : _c.push((0, test_helpers_1.createItems)(101)));
|
|
110
|
+
await ((_d = testAdapter.getRepo('ItemTypeB')) === null || _d === void 0 ? void 0 : _d.push((0, test_helpers_1.createItems)(102)));
|
|
111
|
+
await ((_e = testAdapter.getRepo('ItemTypeA')) === null || _e === void 0 ? void 0 : _e.upload());
|
|
112
|
+
await ((_f = testAdapter.getRepo('ItemTypeB')) === null || _f === void 0 ? void 0 : _f.upload());
|
|
113
|
+
await ((_g = testAdapter.getRepo('ItemTypeA')) === null || _g === void 0 ? void 0 : _g.push((0, test_helpers_1.createItems)(101)));
|
|
114
|
+
await ((_h = testAdapter.getRepo('ItemTypeB')) === null || _h === void 0 ? void 0 : _h.push((0, test_helpers_1.createItems)(102)));
|
|
115
|
+
await ((_j = testAdapter.getRepo('ItemTypeA')) === null || _j === void 0 ? void 0 : _j.push((0, test_helpers_1.createItems)(101)));
|
|
116
|
+
await ((_k = testAdapter.getRepo('ItemTypeB')) === null || _k === void 0 ? void 0 : _k.push((0, test_helpers_1.createItems)(102)));
|
|
117
|
+
await testAdapter.uploadAllRepos();
|
|
118
|
+
const artifacts = testAdapter.artifacts;
|
|
119
|
+
expect(artifacts.length).toBe(20);
|
|
120
|
+
expect(checkArtifactOrder(artifacts, repos)).toBe(true);
|
|
121
|
+
});
|
|
122
|
+
it('should not count artifacts if 0 items are pushed to the repo', async () => {
|
|
123
|
+
var _a;
|
|
124
|
+
const repos = [
|
|
125
|
+
{ itemType: 'ItemTypeA' }
|
|
126
|
+
];
|
|
127
|
+
// Initialize repos
|
|
128
|
+
testAdapter.initializeRepos(repos);
|
|
129
|
+
await ((_a = testAdapter.getRepo('ItemTypeA')) === null || _a === void 0 ? void 0 : _a.push([]));
|
|
130
|
+
await testAdapter.uploadAllRepos();
|
|
131
|
+
const artifacts = testAdapter.artifacts;
|
|
132
|
+
expect(artifacts.length).toBe(0);
|
|
133
|
+
expect(checkArtifactOrder(artifacts, repos)).toBe(true);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
@@ -67,6 +67,11 @@ export declare class WorkerAdapter<ConnectorState> {
|
|
|
67
67
|
itemTypeToLoad: ItemTypeToLoad;
|
|
68
68
|
}): Promise<LoadItemResponse>;
|
|
69
69
|
processAttachment(attachment: NormalizedAttachment, stream: ExternalSystemAttachmentStreamingFunction): Promise<ProcessAttachmentReturnType>;
|
|
70
|
+
/**
|
|
71
|
+
* Destroys a stream to prevent memory leaks.
|
|
72
|
+
* @param {any} httpStream - The axios response stream to destroy
|
|
73
|
+
*/
|
|
74
|
+
private destroyHttpStream;
|
|
70
75
|
loadAttachment({ item, create, }: {
|
|
71
76
|
item: ExternalSystemAttachment;
|
|
72
77
|
create: ExternalSystemLoadingFunction<ExternalSystemAttachment>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-adapter.d.ts","sourceRoot":"","sources":["../../src/workers/worker-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,SAAS,EAET,yCAAyC,EACzC,kCAAkC,EAClC,2BAA2B,EAC3B,2BAA2B,EAC5B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAEL,wBAAwB,EACxB,6BAA6B,EAC7B,UAAU,EACV,eAAe,EAEhB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAkB,MAAM,iCAAiC,CAAC;AAO3E,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAIhF,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,qBAAqB,EACtB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAM7C,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,EAClD,KAAK,EACL,YAAY,EACZ,OAAO,GACR,EAAE,sBAAsB,CAAC,cAAc,CAAC,GAAG,aAAa,CAAC,cAAc,CAAC,CAMxE;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,aAAa,CAAC,cAAc;IACvC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,oBAAoB,CAAC;IACxC,SAAS,EAAE,OAAO,CAAC;IAEnB,OAAO,CAAC,YAAY,CAAwB;IAC5C,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,gBAAgB,CAAU;IAClC,OAAO,CAAC,KAAK,CAAc;IAG3B,OAAO,CAAC,aAAa,CAAiB;IACtC,OAAO,CAAC,eAAe,CAAW;IAClC,OAAO,CAAC,QAAQ,CAAU;IAC1B,OAAO,CAAC,QAAQ,CAAW;gBAEf,EACV,KAAK,EACL,YAAY,EACZ,OAAO,GACR,EAAE,sBAAsB,CAAC,cAAc,CAAC;IAqBzC,IAAI,KAAK,IAAI,YAAY,CAAC,cAAc,CAAC,CAExC;IAED,IAAI,KAAK,CAAC,KAAK,EAAE,YAAY,CAAC,cAAc,CAAC,EAI5C;IAED,IAAI,OAAO,IAAI,YAAY,EAAE,CAE5B;IAED,IAAI,cAAc,IAAI,MAAM,EAAE,CAE7B;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE;
|
|
1
|
+
{"version":3,"file":"worker-adapter.d.ts","sourceRoot":"","sources":["../../src/workers/worker-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -85,7 +85,6 @@ class WorkerAdapter {
|
|
|
85
85
|
repo.itemType !== constants_1.AIRDROP_DEFAULT_ITEM_TYPES.SSOR_ATTACHMENT;
|
|
86
86
|
return new repo_1.Repo(Object.assign(Object.assign({ event: this.event, itemType: repo.itemType }, (shouldNormalize && { normalize: repo.normalize })), { onUpload: (artifact) => {
|
|
87
87
|
var _a;
|
|
88
|
-
this.artifacts.push(artifact);
|
|
89
88
|
// We need to store artifacts ids in state for later use when streaming attachments
|
|
90
89
|
if (repo.itemType === constants_1.AIRDROP_DEFAULT_ITEM_TYPES.ATTACHMENTS) {
|
|
91
90
|
(_a = this.state.toDevRev) === null || _a === void 0 ? void 0 : _a.attachmentsMetadata.artifactIds.push(artifact.id);
|
|
@@ -180,6 +179,7 @@ class WorkerAdapter {
|
|
|
180
179
|
async uploadAllRepos() {
|
|
181
180
|
for (const repo of this.repos) {
|
|
182
181
|
const error = await repo.upload();
|
|
182
|
+
this.artifacts.push(...repo.uploadedArtifacts);
|
|
183
183
|
if (error) {
|
|
184
184
|
throw error;
|
|
185
185
|
}
|
|
@@ -514,9 +514,11 @@ class WorkerAdapter {
|
|
|
514
514
|
const preparedArtifact = await this.uploader.getArtifactUploadUrl(attachment.file_name, fileType);
|
|
515
515
|
if (!preparedArtifact) {
|
|
516
516
|
console.warn(`Error while preparing artifact for attachment ID ${attachment.id}. Skipping attachment.`);
|
|
517
|
+
this.destroyHttpStream(httpStream);
|
|
517
518
|
return;
|
|
518
519
|
}
|
|
519
520
|
if (this.isTimeout) {
|
|
521
|
+
this.destroyHttpStream(httpStream);
|
|
520
522
|
return;
|
|
521
523
|
}
|
|
522
524
|
// Stream attachment
|
|
@@ -557,6 +559,25 @@ class WorkerAdapter {
|
|
|
557
559
|
}
|
|
558
560
|
return;
|
|
559
561
|
}
|
|
562
|
+
/**
|
|
563
|
+
* Destroys a stream to prevent memory leaks.
|
|
564
|
+
* @param {any} httpStream - The axios response stream to destroy
|
|
565
|
+
*/
|
|
566
|
+
destroyHttpStream(httpStream) {
|
|
567
|
+
try {
|
|
568
|
+
if (httpStream && httpStream.data) {
|
|
569
|
+
if (typeof httpStream.data.destroy === 'function') {
|
|
570
|
+
httpStream.data.destroy();
|
|
571
|
+
}
|
|
572
|
+
else if (typeof httpStream.data.close === 'function') {
|
|
573
|
+
httpStream.data.close();
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
catch (error) {
|
|
578
|
+
console.warn('Error while destroying HTTP stream:', error);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
560
581
|
async loadAttachment({ item, create, }) {
|
|
561
582
|
// Create item
|
|
562
583
|
const { id, delay, error } = await create({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devrev/ts-adaas",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.1-beta.2",
|
|
4
4
|
"description": "Typescript library containing the ADaaS(AirDrop as a Service) control protocol.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -38,17 +38,16 @@
|
|
|
38
38
|
"eslint-config-prettier": "^10.1.5",
|
|
39
39
|
"eslint-plugin-prettier": "^5.1.3",
|
|
40
40
|
"jest": "^29.7.0",
|
|
41
|
-
"ts-jest": "^29.
|
|
41
|
+
"ts-jest": "^29.4.4",
|
|
42
|
+
"ts-node": "^10.9.2",
|
|
43
|
+
"typescript": "^5.3.3"
|
|
42
44
|
},
|
|
43
45
|
"dependencies": {
|
|
44
46
|
"@devrev/typescript-sdk": "^1.1.59",
|
|
45
47
|
"axios": "^1.12.1",
|
|
46
|
-
"@microsoft/api-extractor": "^7.52.11",
|
|
47
48
|
"axios-retry": "^4.5.0",
|
|
48
49
|
"form-data": "^4.0.4",
|
|
49
50
|
"js-jsonl": "^1.1.1",
|
|
50
|
-
"ts-node": "^10.9.2",
|
|
51
|
-
"typescript": "^5.3.3",
|
|
52
51
|
"yargs": "^17.7.2"
|
|
53
52
|
},
|
|
54
53
|
"files": [
|