@devrev/ts-adaas 1.13.3 → 1.13.4-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/attachments-streaming/attachments-streaming-pool.interfaces.d.ts +1 -1
  2. package/dist/attachments-streaming/attachments-streaming-pool.interfaces.d.ts.map +1 -1
  3. package/dist/common/helpers.d.ts +28 -21
  4. package/dist/common/helpers.d.ts.map +1 -1
  5. package/dist/common/helpers.js +18 -156
  6. package/dist/index.d.ts +3 -3
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +3 -3
  9. package/dist/multithreading/create-worker.d.ts.map +1 -0
  10. package/dist/multithreading/create-worker.test.d.ts.map +1 -0
  11. package/dist/multithreading/process-task.d.ts.map +1 -0
  12. package/dist/{workers → multithreading}/process-task.js +1 -1
  13. package/dist/{workers → multithreading/spawn}/spawn.d.ts +1 -1
  14. package/dist/multithreading/spawn/spawn.d.ts.map +1 -0
  15. package/dist/multithreading/spawn/spawn.helpers.d.ts +21 -0
  16. package/dist/multithreading/spawn/spawn.helpers.d.ts.map +1 -0
  17. package/dist/multithreading/spawn/spawn.helpers.js +114 -0
  18. package/dist/multithreading/spawn/spawn.helpers.test.d.ts +2 -0
  19. package/dist/multithreading/spawn/spawn.helpers.test.d.ts.map +1 -0
  20. package/dist/multithreading/spawn/spawn.helpers.test.js +293 -0
  21. package/dist/{workers → multithreading/spawn}/spawn.js +11 -10
  22. package/dist/multithreading/worker-adapter/worker-adapter.artifacts.test.d.ts.map +1 -0
  23. package/dist/{workers → multithreading/worker-adapter}/worker-adapter.artifacts.test.js +4 -4
  24. package/dist/{workers → multithreading/worker-adapter}/worker-adapter.d.ts +8 -8
  25. package/dist/multithreading/worker-adapter/worker-adapter.d.ts.map +1 -0
  26. package/dist/multithreading/worker-adapter/worker-adapter.helpers.d.ts +22 -0
  27. package/dist/multithreading/worker-adapter/worker-adapter.helpers.d.ts.map +1 -0
  28. package/dist/multithreading/worker-adapter/worker-adapter.helpers.js +64 -0
  29. package/dist/multithreading/worker-adapter/worker-adapter.helpers.test.d.ts +2 -0
  30. package/dist/multithreading/worker-adapter/worker-adapter.helpers.test.d.ts.map +1 -0
  31. package/dist/multithreading/worker-adapter/worker-adapter.helpers.test.js +514 -0
  32. package/dist/{workers → multithreading/worker-adapter}/worker-adapter.js +16 -16
  33. package/dist/multithreading/worker-adapter/worker-adapter.test.d.ts.map +1 -0
  34. package/dist/{workers → multithreading/worker-adapter}/worker-adapter.test.js +10 -10
  35. package/dist/{workers → multithreading}/worker.d.ts.map +1 -1
  36. package/dist/state/state.d.ts.map +1 -1
  37. package/dist/state/state.js +1 -2
  38. package/dist/types/extraction.d.ts +1 -1
  39. package/dist/types/extraction.d.ts.map +1 -1
  40. package/dist/types/workers.d.ts +1 -1
  41. package/dist/types/workers.d.ts.map +1 -1
  42. package/dist/uploader/uploader.d.ts +1 -26
  43. package/dist/uploader/uploader.d.ts.map +1 -1
  44. package/dist/uploader/uploader.helpers.d.ts +32 -0
  45. package/dist/uploader/uploader.helpers.d.ts.map +1 -0
  46. package/dist/uploader/uploader.helpers.js +140 -0
  47. package/dist/uploader/uploader.helpers.test.d.ts +2 -0
  48. package/dist/uploader/uploader.helpers.test.d.ts.map +1 -0
  49. package/dist/uploader/uploader.helpers.test.js +265 -0
  50. package/dist/uploader/uploader.js +7 -117
  51. package/dist/uploader/uploader.test.js +561 -72
  52. package/package.json +1 -1
  53. package/dist/common/helpers.test.d.ts +0 -2
  54. package/dist/common/helpers.test.d.ts.map +0 -1
  55. package/dist/common/helpers.test.js +0 -158
  56. package/dist/workers/create-worker.d.ts.map +0 -1
  57. package/dist/workers/create-worker.test.d.ts.map +0 -1
  58. package/dist/workers/process-task.d.ts.map +0 -1
  59. package/dist/workers/spawn.d.ts.map +0 -1
  60. package/dist/workers/worker-adapter.artifacts.test.d.ts.map +0 -1
  61. package/dist/workers/worker-adapter.d.ts.map +0 -1
  62. package/dist/workers/worker-adapter.test.d.ts.map +0 -1
  63. /package/dist/{workers → multithreading}/create-worker.d.ts +0 -0
  64. /package/dist/{workers → multithreading}/create-worker.js +0 -0
  65. /package/dist/{workers → multithreading}/create-worker.test.d.ts +0 -0
  66. /package/dist/{workers → multithreading}/create-worker.test.js +0 -0
  67. /package/dist/{workers → multithreading}/process-task.d.ts +0 -0
  68. /package/dist/{workers → multithreading/worker-adapter}/worker-adapter.artifacts.test.d.ts +0 -0
  69. /package/dist/{workers → multithreading/worker-adapter}/worker-adapter.test.d.ts +0 -0
  70. /package/dist/{workers → multithreading}/worker.d.ts +0 -0
  71. /package/dist/{workers → multithreading}/worker.js +0 -0
@@ -1,34 +1,22 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ const form_data_1 = __importDefault(require("form-data"));
7
+ const js_jsonl_1 = require("js-jsonl");
8
+ const zlib_1 = __importDefault(require("zlib"));
3
9
  const axios_client_internal_1 = require("../http/axios-client-internal");
4
10
  const test_helpers_1 = require("../tests/test-helpers");
5
- const types_1 = require("../types");
11
+ const uploader_helpers_1 = require("./uploader.helpers");
6
12
  const uploader_1 = require("./uploader");
7
- jest.mock('../http/axios-client-internal', () => {
8
- const originalModule = jest.requireActual('../http/axios-client-internal');
9
- return Object.assign(Object.assign({}, originalModule), { axiosClient: {
10
- get: jest.fn(),
11
- post: jest.fn(),
12
- } });
13
- });
14
- const getSuccessResponse = () => ({
15
- data: {
16
- message: 'Success',
17
- },
18
- status: 200,
19
- statusText: 'OK',
20
- headers: {},
21
- config: {},
22
- });
23
- const getArtifactUploadUrlMockResponse = {
24
- data: {
25
- artifact_id: 'mockArtifactId',
26
- upload_url: 'mockUploadUrl',
27
- form_data: [],
28
- },
29
- };
13
+ jest.mock('../http/axios-client-internal');
14
+ jest.mock('./uploader.helpers', () => (Object.assign(Object.assign({}, jest.requireActual('./uploader.helpers')), { downloadToLocal: jest.fn(), compressGzip: jest.fn(jest.requireActual('./uploader.helpers').compressGzip) })));
15
+ const mockedAxiosClient = jest.mocked(axios_client_internal_1.axiosClient);
16
+ const mockedDownloadToLocal = jest.mocked(uploader_helpers_1.downloadToLocal);
17
+ const mockedCompressGzip = jest.mocked(uploader_helpers_1.compressGzip);
30
18
  describe(uploader_1.Uploader.name, () => {
31
- const mockEvent = (0, test_helpers_1.createEvent)({ eventType: types_1.EventType.ExtractionDataStart });
19
+ const mockEvent = (0, test_helpers_1.createEvent)();
32
20
  let uploader;
33
21
  beforeEach(() => {
34
22
  uploader = new uploader_1.Uploader({ event: mockEvent });
@@ -36,56 +24,557 @@ describe(uploader_1.Uploader.name, () => {
36
24
  afterEach(() => {
37
25
  jest.clearAllMocks();
38
26
  });
39
- it('should upload the file to the DevRev platform and return the artifact information', async () => {
40
- // Mock successful response from getArtifactUploadUrl
41
- axios_client_internal_1.axiosClient.get.mockResolvedValueOnce(getArtifactUploadUrlMockResponse);
42
- // Mock successful response from confirmArtifactUpload and uploadArtifact
43
- axios_client_internal_1.axiosClient.post.mockResolvedValue(getSuccessResponse());
44
- const entity = 'entity';
45
- const fetchedObjects = [{ key: 'value' }];
46
- const uploadResponse = await uploader.upload(entity, fetchedObjects);
47
- expect(uploadResponse).toEqual({
48
- artifact: {
49
- id: 'mockArtifactId',
50
- item_type: entity,
51
- item_count: fetchedObjects.length,
52
- },
27
+ describe(uploader_1.Uploader.prototype.upload.name, () => {
28
+ const mockArtifactUploadUrlResponse = {
29
+ data: (0, test_helpers_1.createArtifact)(),
30
+ };
31
+ it('should return artifact info when upload flow succeeds', async () => {
32
+ // Arrange
33
+ const itemType = 'tasks';
34
+ const fetchedObjects = [
35
+ { id: 1, name: 'Task 1' },
36
+ { id: 2, name: 'Task 2' },
37
+ ];
38
+ mockedAxiosClient.get.mockResolvedValueOnce(mockArtifactUploadUrlResponse);
39
+ mockedAxiosClient.post.mockResolvedValue((0, test_helpers_1.createAxiosResponse)());
40
+ // Act
41
+ const result = await uploader.upload(itemType, fetchedObjects);
42
+ // Assert
43
+ expect(result).toEqual({
44
+ artifact: {
45
+ id: 'art_123',
46
+ item_type: itemType,
47
+ item_count: 2,
48
+ },
49
+ });
50
+ expect(result.error).toBeUndefined();
51
+ });
52
+ it('should report item_count as 1 when uploading single object', async () => {
53
+ var _a;
54
+ // Arrange
55
+ const itemType = 'metadata';
56
+ const fetchedObject = { key: 'value' };
57
+ mockedAxiosClient.get.mockResolvedValueOnce(mockArtifactUploadUrlResponse);
58
+ mockedAxiosClient.post.mockResolvedValue((0, test_helpers_1.createAxiosResponse)());
59
+ // Act
60
+ const result = await uploader.upload(itemType, fetchedObject);
61
+ // Assert
62
+ expect((_a = result.artifact) === null || _a === void 0 ? void 0 : _a.item_count).toBe(1);
63
+ expect(result.error).toBeUndefined();
64
+ });
65
+ it('should call downloadToLocal when isLocalDevelopment is true', async () => {
66
+ // Arrange
67
+ const localUploader = new uploader_1.Uploader({
68
+ event: mockEvent,
69
+ options: { isLocalDevelopment: true },
70
+ });
71
+ const itemType = 'tasks';
72
+ const fetchedObjects = [{ id: 1 }];
73
+ mockedAxiosClient.get.mockResolvedValueOnce(mockArtifactUploadUrlResponse);
74
+ mockedAxiosClient.post.mockResolvedValue((0, test_helpers_1.createAxiosResponse)());
75
+ // Act
76
+ await localUploader.upload(itemType, fetchedObjects);
77
+ // Assert
78
+ expect(mockedDownloadToLocal).toHaveBeenCalledWith(itemType, fetchedObjects);
79
+ });
80
+ it('should return error when getArtifactUploadUrl fails', async () => {
81
+ // Arrange
82
+ const itemType = 'tasks';
83
+ const fetchedObjects = [{ id: 1 }];
84
+ mockedAxiosClient.get.mockRejectedValueOnce(new Error('Get artifact upload URL failed'));
85
+ // Act
86
+ const result = await uploader.upload(itemType, fetchedObjects);
87
+ // Assert
88
+ expect(result.error).toBeInstanceOf(Error);
89
+ expect(result.artifact).toBeUndefined();
90
+ });
91
+ it('should return error when uploadArtifact fails', async () => {
92
+ // Arrange
93
+ const itemType = 'tasks';
94
+ const fetchedObjects = [{ id: 1 }];
95
+ mockedAxiosClient.get.mockResolvedValueOnce(mockArtifactUploadUrlResponse);
96
+ mockedAxiosClient.post.mockRejectedValueOnce(new Error('Upload artifact failed'));
97
+ // Act
98
+ const result = await uploader.upload(itemType, fetchedObjects);
99
+ // Assert
100
+ expect(result.error).toBeInstanceOf(Error);
101
+ expect(result.artifact).toBeUndefined();
102
+ });
103
+ it('should return error when confirmArtifactUpload fails', async () => {
104
+ // Arrange
105
+ const itemType = 'tasks';
106
+ const fetchedObjects = [{ id: 1 }];
107
+ mockedAxiosClient.get.mockResolvedValueOnce(mockArtifactUploadUrlResponse);
108
+ mockedAxiosClient.post
109
+ .mockResolvedValueOnce((0, test_helpers_1.createAxiosResponse)())
110
+ .mockRejectedValueOnce(new Error('Confirm artifact upload failed'));
111
+ // Act
112
+ const result = await uploader.upload(itemType, fetchedObjects);
113
+ // Assert
114
+ expect(result.error).toBeInstanceOf(Error);
115
+ expect(result.artifact).toBeUndefined();
116
+ });
117
+ it('should return error when compression fails', async () => {
118
+ // Arrange
119
+ const itemType = 'tasks';
120
+ const fetchedObjects = [{ id: 1 }];
121
+ mockedCompressGzip.mockReturnValueOnce(undefined);
122
+ // Act
123
+ const result = await uploader.upload(itemType, fetchedObjects);
124
+ // Assert
125
+ expect(result.error).toBeInstanceOf(Error);
126
+ expect(result.artifact).toBeUndefined();
53
127
  });
54
128
  });
55
- it('[edge] should handle failure when getting artifact upload URL', async () => {
56
- var _a;
57
- // Mock unsuccessful response for getArtifactUploadUrl
58
- axios_client_internal_1.axiosClient.get.mockResolvedValueOnce(undefined);
59
- const entity = 'entity';
60
- const fetchedObjects = [{ key: 'value' }];
61
- const uploadResponse = await uploader.upload(entity, fetchedObjects);
62
- expect(uploadResponse.error).toBeInstanceOf(Error);
63
- expect((_a = uploadResponse.error) === null || _a === void 0 ? void 0 : _a.message).toBeDefined();
129
+ describe(uploader_1.Uploader.prototype.getArtifactUploadUrl.name, () => {
130
+ it('should return artifact upload info when API call succeeds', async () => {
131
+ // Arrange
132
+ const filename = 'test-file.jsonl.gz';
133
+ const fileType = 'application/x-gzip';
134
+ const fileSize = 1024;
135
+ const expectedArtifact = (0, test_helpers_1.createArtifact)();
136
+ mockedAxiosClient.get.mockResolvedValueOnce({
137
+ data: expectedArtifact,
138
+ });
139
+ // Act
140
+ const result = await uploader.getArtifactUploadUrl(filename, fileType, fileSize);
141
+ // Assert
142
+ expect(result).toEqual(expectedArtifact);
143
+ expect(mockedAxiosClient.get).toHaveBeenCalledWith(expect.stringContaining('/internal/airdrop.artifacts.upload-url'), expect.objectContaining({
144
+ params: expect.objectContaining({
145
+ file_type: fileType,
146
+ file_name: filename,
147
+ file_size: fileSize,
148
+ }),
149
+ }));
150
+ });
151
+ it('should return undefined when API call fails', async () => {
152
+ // Arrange
153
+ const filename = 'test-file.jsonl.gz';
154
+ const fileType = 'application/x-gzip';
155
+ mockedAxiosClient.get.mockRejectedValueOnce(new Error('Get artifact upload URL failed'));
156
+ // Act
157
+ const result = await uploader.getArtifactUploadUrl(filename, fileType);
158
+ // Assert
159
+ expect(result).toBeUndefined();
160
+ expect(mockedAxiosClient.get).toHaveBeenCalled();
161
+ });
64
162
  });
65
- it('[edge] should handle failure when uploading artifact', async () => {
66
- var _a;
67
- // Mock successful response for getArtifactUploadUrl
68
- axios_client_internal_1.axiosClient.get.mockResolvedValueOnce(getArtifactUploadUrlMockResponse);
69
- // Mock unsuccessful response for uploadArtifact
70
- axios_client_internal_1.axiosClient.post.mockResolvedValueOnce(undefined);
71
- const entity = 'entity';
72
- const fetchedObjects = [{ key: 'value' }];
73
- const uploadResponse = await uploader.upload(entity, fetchedObjects);
74
- expect(uploadResponse.error).toBeInstanceOf(Error);
75
- expect((_a = uploadResponse.error) === null || _a === void 0 ? void 0 : _a.message).toBeDefined();
163
+ describe(uploader_1.Uploader.prototype.uploadArtifact.name, () => {
164
+ it('should return response when posting file as multipart form data', async () => {
165
+ // Arrange
166
+ const artifact = (0, test_helpers_1.createArtifact)();
167
+ const file = (0, test_helpers_1.createFileBuffer)();
168
+ const mockResponse = (0, test_helpers_1.createAxiosResponse)();
169
+ mockedAxiosClient.post.mockResolvedValueOnce(mockResponse);
170
+ // Act
171
+ const result = await uploader.uploadArtifact(artifact, file);
172
+ // Assert
173
+ expect(result).toBe(mockResponse);
174
+ expect(mockedAxiosClient.post).toHaveBeenCalledWith(artifact.upload_url, expect.any(form_data_1.default), expect.objectContaining({
175
+ headers: expect.any(Object),
176
+ }));
177
+ });
178
+ it('should append form_data fields to the multipart form', async () => {
179
+ // Arrange
180
+ // form_data is typed as array but implementation iterates with for...in
181
+ const formDataFields = { key: 'test-key', 'x-amz-credential': 'cred123' };
182
+ const artifact = {
183
+ artifact_id: 'art_123',
184
+ upload_url: 'https://s3.example.com/upload',
185
+ form_data: formDataFields,
186
+ };
187
+ const file = (0, test_helpers_1.createFileBuffer)();
188
+ const appendSpy = jest.spyOn(form_data_1.default.prototype, 'append');
189
+ mockedAxiosClient.post.mockResolvedValueOnce({ status: 200 });
190
+ // Act
191
+ await uploader.uploadArtifact(artifact, file);
192
+ // Assert
193
+ expect(appendSpy).toHaveBeenCalledWith('key', 'test-key');
194
+ expect(appendSpy).toHaveBeenCalledWith('x-amz-credential', 'cred123');
195
+ expect(appendSpy).toHaveBeenCalledWith('file', file);
196
+ appendSpy.mockRestore();
197
+ });
198
+ it('should return undefined when upload fails', async () => {
199
+ // Arrange
200
+ const artifact = (0, test_helpers_1.createArtifact)();
201
+ const file = (0, test_helpers_1.createFileBuffer)();
202
+ mockedAxiosClient.post.mockRejectedValueOnce(new Error('Upload artifact failed'));
203
+ // Act
204
+ const result = await uploader.uploadArtifact(artifact, file);
205
+ // Assert
206
+ expect(result).toBeUndefined();
207
+ });
208
+ });
209
+ describe(uploader_1.Uploader.prototype.confirmArtifactUpload.name, () => {
210
+ it('should return response when confirming artifact upload', async () => {
211
+ // Arrange
212
+ const artifactId = 'art_123';
213
+ const mockResponse = (0, test_helpers_1.createAxiosResponse)();
214
+ mockedAxiosClient.post.mockResolvedValueOnce(mockResponse);
215
+ // Act
216
+ const result = await uploader.confirmArtifactUpload(artifactId);
217
+ // Assert
218
+ expect(result).toBe(mockResponse);
219
+ expect(mockedAxiosClient.post).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
220
+ artifact_id: artifactId,
221
+ }), expect.any(Object));
222
+ });
223
+ it('should return undefined when confirmation fails', async () => {
224
+ // Arrange
225
+ const artifactId = 'art_123';
226
+ mockedAxiosClient.post.mockRejectedValueOnce(new Error('Confirmation failed'));
227
+ // Act
228
+ const result = await uploader.confirmArtifactUpload(artifactId);
229
+ // Assert
230
+ expect(result).toBeUndefined();
231
+ });
76
232
  });
77
- it('[edge] should handle failure when confirming artifact upload', async () => {
78
- var _a;
79
- // Mock successful response for getArtifactUploadUrl
80
- axios_client_internal_1.axiosClient.get.mockResolvedValueOnce(getArtifactUploadUrlMockResponse);
81
- // Mock successful response from uploadArtifact
82
- axios_client_internal_1.axiosClient.post.mockResolvedValueOnce(getSuccessResponse());
83
- // Mock unsuccessful response from confirmArtifactUpload
84
- axios_client_internal_1.axiosClient.post.mockResolvedValueOnce(undefined);
85
- const entity = 'entity';
86
- const fetchedObjects = [{ key: 'value' }];
87
- const uploadResponse = await uploader.upload(entity, fetchedObjects);
88
- expect(uploadResponse.error).toBeInstanceOf(Error);
89
- expect((_a = uploadResponse.error) === null || _a === void 0 ? void 0 : _a.message).toBeDefined();
233
+ describe(uploader_1.Uploader.prototype.streamArtifact.name, () => {
234
+ it('should return response when streaming file to upload URL', async () => {
235
+ // Arrange
236
+ const artifact = (0, test_helpers_1.createArtifact)();
237
+ const destroyFn = jest.fn();
238
+ const fileStream = (0, test_helpers_1.createFileStream)({
239
+ contentLength: 1024,
240
+ destroyFn,
241
+ });
242
+ const mockResponse = (0, test_helpers_1.createAxiosResponse)();
243
+ mockedAxiosClient.post.mockResolvedValueOnce(mockResponse);
244
+ // Act
245
+ const result = await uploader.streamArtifact(artifact, fileStream);
246
+ // Assert
247
+ expect(result).toBe(mockResponse);
248
+ expect(axios_client_internal_1.axiosClient.post).toHaveBeenCalledWith(artifact.upload_url, expect.any(form_data_1.default), expect.objectContaining({
249
+ headers: expect.any(Object),
250
+ maxRedirects: 0,
251
+ validateStatus: expect.any(Function),
252
+ }));
253
+ expect(destroyFn).toHaveBeenCalled();
254
+ });
255
+ it('should append form_data fields to the multipart form', async () => {
256
+ // Arrange
257
+ const formDataFields = { key: 'test-key', 'x-amz-credential': 'cred123' };
258
+ const artifact = {
259
+ artifact_id: 'art_123',
260
+ upload_url: 'https://s3.example.com/upload',
261
+ form_data: formDataFields,
262
+ };
263
+ const fileStream = (0, test_helpers_1.createFileStream)({ contentLength: 1024 });
264
+ const appendSpy = jest.spyOn(form_data_1.default.prototype, 'append');
265
+ mockedAxiosClient.post.mockResolvedValueOnce({ status: 200 });
266
+ // Act
267
+ await uploader.streamArtifact(artifact, fileStream);
268
+ // Assert
269
+ expect(appendSpy).toHaveBeenCalledWith('key', 'test-key');
270
+ expect(appendSpy).toHaveBeenCalledWith('x-amz-credential', 'cred123');
271
+ appendSpy.mockRestore();
272
+ });
273
+ it('should use validateStatus that accepts 2xx and 3xx status codes', async () => {
274
+ // Arrange
275
+ const artifact = (0, test_helpers_1.createArtifact)();
276
+ const fileStream = (0, test_helpers_1.createFileStream)({ contentLength: 1024 });
277
+ mockedAxiosClient.post.mockResolvedValueOnce((0, test_helpers_1.createAxiosResponse)());
278
+ // Act
279
+ await uploader.streamArtifact(artifact, fileStream);
280
+ // Assert
281
+ const callArgs = mockedAxiosClient.post.mock.calls[0];
282
+ const config = callArgs[2];
283
+ const validateStatus = config === null || config === void 0 ? void 0 : config.validateStatus;
284
+ expect(validateStatus === null || validateStatus === void 0 ? void 0 : validateStatus(200)).toBe(true);
285
+ expect(validateStatus === null || validateStatus === void 0 ? void 0 : validateStatus(201)).toBe(true);
286
+ expect(validateStatus === null || validateStatus === void 0 ? void 0 : validateStatus(299)).toBe(true);
287
+ expect(validateStatus === null || validateStatus === void 0 ? void 0 : validateStatus(300)).toBe(true);
288
+ expect(validateStatus === null || validateStatus === void 0 ? void 0 : validateStatus(301)).toBe(true);
289
+ expect(validateStatus === null || validateStatus === void 0 ? void 0 : validateStatus(399)).toBe(true);
290
+ expect(validateStatus === null || validateStatus === void 0 ? void 0 : validateStatus(400)).toBe(false);
291
+ expect(validateStatus === null || validateStatus === void 0 ? void 0 : validateStatus(404)).toBe(false);
292
+ expect(validateStatus === null || validateStatus === void 0 ? void 0 : validateStatus(500)).toBe(false);
293
+ expect(validateStatus === null || validateStatus === void 0 ? void 0 : validateStatus(199)).toBe(false);
294
+ });
295
+ it('should set Content-Length header when missing from file stream', async () => {
296
+ // Arrange
297
+ const artifact = (0, test_helpers_1.createArtifact)();
298
+ const fileStream = (0, test_helpers_1.createFileStream)({ includeContentLength: false });
299
+ mockedAxiosClient.post.mockResolvedValueOnce((0, test_helpers_1.createAxiosResponse)());
300
+ // Act
301
+ await uploader.streamArtifact(artifact, fileStream);
302
+ // Assert
303
+ expect(mockedAxiosClient.post).toHaveBeenCalledWith(artifact.upload_url, expect.any(form_data_1.default), expect.objectContaining({
304
+ headers: expect.objectContaining({
305
+ 'Content-Length': expect.any(Number),
306
+ }),
307
+ }));
308
+ });
309
+ it('should destroy stream and return undefined when streaming fails', async () => {
310
+ // Arrange
311
+ const artifact = (0, test_helpers_1.createArtifact)();
312
+ const destroyFn = jest.fn();
313
+ const fileStream = (0, test_helpers_1.createFileStream)({ destroyFn });
314
+ mockedAxiosClient.post.mockRejectedValueOnce(new Error('Streaming failed'));
315
+ // Act
316
+ const result = await uploader.streamArtifact(artifact, fileStream);
317
+ // Assert
318
+ expect(result).toBeUndefined();
319
+ expect(destroyFn).toHaveBeenCalled();
320
+ });
321
+ });
322
+ describe('Uploader.destroyStream', () => {
323
+ it('should call destroy when stream has destroy method', () => {
324
+ // Arrange
325
+ const destroyStream = (0, test_helpers_1.callPrivateMethod)()(uploader, 'destroyStream');
326
+ const destroyFn = jest.fn();
327
+ const fileStream = {
328
+ data: { destroy: destroyFn },
329
+ };
330
+ // Act
331
+ destroyStream(fileStream);
332
+ // Assert
333
+ expect(destroyFn).toHaveBeenCalled();
334
+ });
335
+ it('should call close when stream has close but no destroy method', () => {
336
+ // Arrange
337
+ const destroyStream = (0, test_helpers_1.callPrivateMethod)()(uploader, 'destroyStream');
338
+ const closeFn = jest.fn();
339
+ const fileStream = {
340
+ data: { close: closeFn },
341
+ };
342
+ // Act
343
+ destroyStream(fileStream);
344
+ // Assert
345
+ expect(closeFn).toHaveBeenCalled();
346
+ });
347
+ it('should prefer destroy over close when both are available', () => {
348
+ // Arrange
349
+ const destroyStream = (0, test_helpers_1.callPrivateMethod)()(uploader, 'destroyStream');
350
+ const destroyFn = jest.fn();
351
+ const closeFn = jest.fn();
352
+ const fileStream = {
353
+ data: { destroy: destroyFn, close: closeFn },
354
+ };
355
+ // Act
356
+ destroyStream(fileStream);
357
+ // Assert
358
+ expect(destroyFn).toHaveBeenCalled();
359
+ expect(closeFn).not.toHaveBeenCalled();
360
+ });
361
+ it('[edge] should handle stream with no destroy or close methods', () => {
362
+ // Arrange
363
+ const destroyStream = (0, test_helpers_1.callPrivateMethod)()(uploader, 'destroyStream');
364
+ const fileStream = {
365
+ data: {},
366
+ };
367
+ // Act & Assert - should not throw
368
+ expect(() => destroyStream(fileStream)).not.toThrow();
369
+ });
370
+ it('[edge] should handle null/undefined data gracefully', () => {
371
+ // Arrange
372
+ const destroyStream = (0, test_helpers_1.callPrivateMethod)()(uploader, 'destroyStream');
373
+ const fileStreamNullData = {
374
+ data: null,
375
+ };
376
+ const fileStreamUndefinedData = {
377
+ data: undefined,
378
+ };
379
+ // Act & Assert - should not throw
380
+ expect(() => destroyStream(fileStreamNullData)).not.toThrow();
381
+ expect(() => destroyStream(fileStreamUndefinedData)).not.toThrow();
382
+ });
383
+ it('[edge] should warn when destroy throws an error', () => {
384
+ // Arrange
385
+ const destroyStream = (0, test_helpers_1.callPrivateMethod)()(uploader, 'destroyStream');
386
+ const destroyFn = jest.fn().mockImplementation(() => {
387
+ throw new Error('Destroy failed');
388
+ });
389
+ const fileStream = {
390
+ data: { destroy: destroyFn },
391
+ };
392
+ // Act & Assert - should not throw
393
+ expect(() => destroyStream(fileStream)).not.toThrow();
394
+ });
395
+ });
396
+ describe('Uploader.getArtifactDownloadUrl', () => {
397
+ it('should return download URL when API call succeeds', async () => {
398
+ // Arrange
399
+ const getArtifactDownloadUrl = (0, test_helpers_1.callPrivateMethod)()(uploader, 'getArtifactDownloadUrl');
400
+ const artifactId = 'art_123';
401
+ const expectedDownloadUrl = 'https://s3.example.com/download/art_123';
402
+ mockedAxiosClient.get.mockResolvedValueOnce({
403
+ data: { download_url: expectedDownloadUrl },
404
+ });
405
+ // Act
406
+ const result = await getArtifactDownloadUrl(artifactId);
407
+ // Assert
408
+ expect(result).toBe(expectedDownloadUrl);
409
+ expect(mockedAxiosClient.get).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
410
+ params: expect.objectContaining({
411
+ artifact_id: artifactId,
412
+ }),
413
+ }));
414
+ });
415
+ it('should return undefined when API call fails', async () => {
416
+ // Arrange
417
+ const getArtifactDownloadUrl = (0, test_helpers_1.callPrivateMethod)()(uploader, 'getArtifactDownloadUrl');
418
+ const artifactId = 'art_123';
419
+ mockedAxiosClient.get.mockRejectedValueOnce(new Error('API error'));
420
+ // Act
421
+ const result = await getArtifactDownloadUrl(artifactId);
422
+ // Assert
423
+ expect(result).toBeUndefined();
424
+ });
425
+ });
426
+ describe(uploader_1.Uploader.prototype.getAttachmentsFromArtifactId.name, () => {
427
+ it('should return attachments when download and parse succeeds', async () => {
428
+ // Arrange
429
+ const artifactId = 'art_123';
430
+ const mockAttachments = [
431
+ { id: '1', url: 'https://example.com/1', file_name: 'file1.txt' },
432
+ { id: '2', url: 'https://example.com/2', file_name: 'file2.txt' },
433
+ ];
434
+ const gzippedData = zlib_1.default.gzipSync(js_jsonl_1.jsonl.stringify(mockAttachments));
435
+ mockedAxiosClient.get.mockResolvedValueOnce((0, test_helpers_1.createDownloadUrlResponse)());
436
+ mockedAxiosClient.get.mockResolvedValueOnce({
437
+ data: gzippedData,
438
+ });
439
+ // Act
440
+ const result = await uploader.getAttachmentsFromArtifactId({
441
+ artifact: artifactId,
442
+ });
443
+ // Assert
444
+ expect(result.attachments).toEqual(mockAttachments);
445
+ expect(result.error).toBeUndefined();
446
+ });
447
+ it('should return error when getArtifactDownloadUrl fails', async () => {
448
+ // Arrange
449
+ const artifactId = 'art_123';
450
+ (0, test_helpers_1.spyOnPrivateMethod)(uploader, 'getArtifactDownloadUrl').mockResolvedValueOnce(undefined);
451
+ // Act
452
+ const result = await uploader.getAttachmentsFromArtifactId({
453
+ artifact: artifactId,
454
+ });
455
+ // Assert
456
+ expect(result.error).toBeInstanceOf(Error);
457
+ expect(result.attachments).toBeUndefined();
458
+ });
459
+ it('should return error when downloadArtifact fails', async () => {
460
+ // Arrange
461
+ const artifactId = 'art_123';
462
+ mockedAxiosClient.get.mockResolvedValueOnce((0, test_helpers_1.createDownloadUrlResponse)());
463
+ mockedAxiosClient.get.mockRejectedValueOnce(new Error('Download error'));
464
+ // Act
465
+ const result = await uploader.getAttachmentsFromArtifactId({
466
+ artifact: artifactId,
467
+ });
468
+ // Assert
469
+ expect(result.error).toBeInstanceOf(Error);
470
+ expect(result.attachments).toBeUndefined();
471
+ });
472
+ it('should return error when decompression fails', async () => {
473
+ // Arrange
474
+ const artifactId = 'art_123';
475
+ mockedAxiosClient.get.mockResolvedValueOnce((0, test_helpers_1.createDownloadUrlResponse)());
476
+ mockedAxiosClient.get.mockResolvedValueOnce({
477
+ data: Buffer.from('not valid gzip data'),
478
+ });
479
+ // Act
480
+ const result = await uploader.getAttachmentsFromArtifactId({
481
+ artifact: artifactId,
482
+ });
483
+ // Assert
484
+ expect(result.error).toBeInstanceOf(Error);
485
+ expect(result.attachments).toBeUndefined();
486
+ });
487
+ it('should return error when JSONL parsing fails', async () => {
488
+ // Arrange
489
+ const artifactId = 'art_123';
490
+ const gzippedInvalidJsonl = zlib_1.default.gzipSync('not valid jsonl {{{');
491
+ mockedAxiosClient.get.mockResolvedValueOnce((0, test_helpers_1.createDownloadUrlResponse)());
492
+ mockedAxiosClient.get.mockResolvedValueOnce({
493
+ data: gzippedInvalidJsonl,
494
+ });
495
+ // Act
496
+ const result = await uploader.getAttachmentsFromArtifactId({
497
+ artifact: artifactId,
498
+ });
499
+ // Assert
500
+ expect(result.error).toBeInstanceOf(Error);
501
+ expect(result.attachments).toBeUndefined();
502
+ });
503
+ });
504
+ describe(uploader_1.Uploader.prototype.getJsonObjectByArtifactId.name, () => {
505
+ it('should return parsed data when downloading non-gzipped artifact', async () => {
506
+ // Arrange
507
+ const artifactId = 'art_123';
508
+ const mockData = [
509
+ { id: 1, name: 'Item 1' },
510
+ { id: 2, name: 'Item 2' },
511
+ ];
512
+ const jsonlData = js_jsonl_1.jsonl.stringify(mockData);
513
+ mockedAxiosClient.get.mockResolvedValueOnce((0, test_helpers_1.createDownloadUrlResponse)());
514
+ mockedAxiosClient.get.mockResolvedValueOnce({
515
+ data: Buffer.from(jsonlData),
516
+ });
517
+ // Act
518
+ const result = await uploader.getJsonObjectByArtifactId({
519
+ artifactId,
520
+ isGzipped: false,
521
+ });
522
+ // Assert
523
+ expect(result).toEqual(mockData);
524
+ });
525
+ it('should return parsed data when downloading gzipped artifact', async () => {
526
+ // Arrange
527
+ const artifactId = 'art_123';
528
+ const mockData = [
529
+ { id: 1, name: 'Item 1' },
530
+ { id: 2, name: 'Item 2' },
531
+ ];
532
+ const gzippedData = zlib_1.default.gzipSync(js_jsonl_1.jsonl.stringify(mockData));
533
+ mockedAxiosClient.get.mockResolvedValueOnce((0, test_helpers_1.createDownloadUrlResponse)());
534
+ mockedAxiosClient.get.mockResolvedValueOnce({
535
+ data: gzippedData,
536
+ });
537
+ // Act
538
+ const result = await uploader.getJsonObjectByArtifactId({
539
+ artifactId,
540
+ isGzipped: true,
541
+ });
542
+ // Assert
543
+ expect(result).toEqual(mockData);
544
+ });
545
+ it('[edge] should return undefined when getArtifactDownloadUrl fails', async () => {
546
+ // Arrange
547
+ const artifactId = 'art_123';
548
+ (0, test_helpers_1.spyOnPrivateMethod)(uploader, 'getArtifactDownloadUrl').mockResolvedValueOnce(undefined);
549
+ // Act
550
+ const result = await uploader.getJsonObjectByArtifactId({ artifactId });
551
+ // Assert
552
+ expect(result).toBeUndefined();
553
+ });
554
+ it('[edge] should return undefined when downloadArtifact fails', async () => {
555
+ // Arrange
556
+ const artifactId = 'art_123';
557
+ mockedAxiosClient.get.mockResolvedValueOnce((0, test_helpers_1.createDownloadUrlResponse)());
558
+ mockedAxiosClient.get.mockRejectedValueOnce(new Error('Download error'));
559
+ // Act
560
+ const result = await uploader.getJsonObjectByArtifactId({ artifactId });
561
+ // Assert
562
+ expect(result).toBeUndefined();
563
+ });
564
+ it('[edge] should return undefined when decompression fails for gzipped artifact', async () => {
565
+ // Arrange
566
+ const artifactId = 'art_123';
567
+ mockedAxiosClient.get.mockResolvedValueOnce((0, test_helpers_1.createDownloadUrlResponse)());
568
+ mockedAxiosClient.get.mockResolvedValueOnce({
569
+ data: Buffer.from('not valid gzip'),
570
+ });
571
+ // Act
572
+ const result = await uploader.getJsonObjectByArtifactId({
573
+ artifactId,
574
+ isGzipped: true,
575
+ });
576
+ // Assert
577
+ expect(result).toBeUndefined();
578
+ });
90
579
  });
91
580
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devrev/ts-adaas",
3
- "version": "1.13.3",
3
+ "version": "1.13.4-beta.0",
4
4
  "description": "Typescript library containing the ADaaS(AirDrop as a Service) control protocol.",
5
5
  "type": "commonjs",
6
6
  "main": "./dist/index.js",
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=helpers.test.d.ts.map