@devrev/ts-adaas 1.9.0-beta.0 → 1.9.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.
- package/dist/attachments-streaming/attachments-streaming-pool.test.js +33 -40
- package/dist/common/constants.d.ts +6 -1
- package/dist/common/constants.js +20 -9
- package/dist/common/control-protocol.js +2 -2
- package/dist/common/helpers.test.js +29 -29
- package/dist/common/install-initial-domain-mapping.js +4 -4
- package/dist/common/install-initial-domain-mapping.test.js +17 -27
- package/dist/deprecated/uploader/index.js +2 -2
- package/dist/http/axios-client-internal.d.ts +2 -0
- package/dist/http/axios-client-internal.js +60 -0
- package/dist/http/axios-client-internal.test.d.ts +1 -0
- package/dist/http/axios-client-internal.test.js +189 -0
- package/dist/logger/logger.js +1 -1
- package/dist/logger/logger.test.js +12 -12
- package/dist/mappers/mappers.js +4 -4
- package/dist/repo/repo.test.js +51 -37
- package/dist/state/state.d.ts +12 -8
- package/dist/state/state.interfaces.d.ts +18 -0
- package/dist/state/state.interfaces.js +19 -0
- package/dist/state/state.js +85 -67
- package/dist/state/state.test.d.ts +1 -0
- package/dist/state/state.test.js +223 -0
- package/dist/tests/test-helpers.js +8 -0
- package/dist/tests/timeout-handling/timeout-1.test.js +1 -1
- package/dist/tests/timeout-handling/timeout-2.test.js +1 -1
- package/dist/tests/timeout-handling/timeout-3a.test.js +1 -1
- package/dist/tests/timeout-handling/timeout-3b.test.js +1 -1
- package/dist/types/common.d.ts +11 -0
- package/dist/types/common.js +13 -1
- package/dist/types/extraction.d.ts +32 -9
- package/dist/types/extraction.js +1 -11
- package/dist/types/extraction.test.js +51 -5
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.js +2 -2
- package/dist/uploader/uploader.js +7 -7
- package/dist/uploader/uploader.test.js +18 -21
- package/dist/workers/create-worker.test.js +64 -2
- package/dist/workers/default-workers/attachments-extraction.js +7 -3
- package/dist/workers/worker-adapter.js +10 -3
- package/dist/workers/worker-adapter.test.js +140 -71
- package/package.json +3 -2
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const axios_mock_adapter_1 = __importDefault(require("axios-mock-adapter"));
|
|
7
|
+
const axios_client_internal_1 = require("./axios-client-internal");
|
|
8
|
+
describe('Internal Axios Client', () => {
|
|
9
|
+
let mockAdapter;
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
jest.clearAllMocks();
|
|
12
|
+
jest.spyOn(console, 'warn').mockImplementation(() => { });
|
|
13
|
+
mockAdapter = new axios_mock_adapter_1.default(axios_client_internal_1.axiosClient);
|
|
14
|
+
});
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
jest.restoreAllMocks();
|
|
17
|
+
mockAdapter.restore();
|
|
18
|
+
});
|
|
19
|
+
it('should not retry on 200 response', async () => {
|
|
20
|
+
// Arrange
|
|
21
|
+
const testUrl = '/test-endpoint';
|
|
22
|
+
const responseData = { id: 1, title: 'test title' };
|
|
23
|
+
mockAdapter.onGet(testUrl).reply(200, responseData);
|
|
24
|
+
// Act
|
|
25
|
+
await axios_client_internal_1.axiosClient.get(testUrl);
|
|
26
|
+
// Assert
|
|
27
|
+
expect(mockAdapter.history.get).toHaveLength(1);
|
|
28
|
+
});
|
|
29
|
+
it('should not retry when response is 400', async () => {
|
|
30
|
+
// Arrange
|
|
31
|
+
const testUrl = '/test-endpoint';
|
|
32
|
+
const errorData = { error: 'Bad Request' };
|
|
33
|
+
mockAdapter.onGet(testUrl).reply(400, errorData);
|
|
34
|
+
// Act
|
|
35
|
+
await expect(axios_client_internal_1.axiosClient.get(testUrl)).rejects.toMatchObject({
|
|
36
|
+
response: { status: 400 },
|
|
37
|
+
});
|
|
38
|
+
// Assert
|
|
39
|
+
expect(mockAdapter.history.get).toHaveLength(1);
|
|
40
|
+
});
|
|
41
|
+
// TODO: This test is working as expected, but it takes too long to run. Not
|
|
42
|
+
// sure if it is good idea to have it.
|
|
43
|
+
// it('should retry on 500 response', async () => {
|
|
44
|
+
// // Arrange
|
|
45
|
+
// const testUrl = '/test-endpoint';
|
|
46
|
+
// mockAdapter.onGet(testUrl).reply(500);
|
|
47
|
+
// // Act & Assert
|
|
48
|
+
// await expect(axiosClient.get(testUrl)).rejects.toMatchObject({
|
|
49
|
+
// response: { status: 500 },
|
|
50
|
+
// });
|
|
51
|
+
// // Assert
|
|
52
|
+
// expect(mockAdapter.history.get).toHaveLength(6);
|
|
53
|
+
// }, 100000);
|
|
54
|
+
it('should retry 2 times when response is 500 and then succeed third time when response is 200', async () => {
|
|
55
|
+
// Arrange
|
|
56
|
+
const testUrl = '/test-endpoint';
|
|
57
|
+
const successData = { message: 'success after 2 retries' };
|
|
58
|
+
mockAdapter
|
|
59
|
+
.onGet(testUrl)
|
|
60
|
+
.replyOnce(500)
|
|
61
|
+
.onGet(testUrl)
|
|
62
|
+
.replyOnce(500)
|
|
63
|
+
.onGet(testUrl)
|
|
64
|
+
.reply(200, successData);
|
|
65
|
+
// Act
|
|
66
|
+
const response = await axios_client_internal_1.axiosClient.get(testUrl);
|
|
67
|
+
// Assert
|
|
68
|
+
expect(response.status).toBe(200);
|
|
69
|
+
expect(response.data).toEqual(successData);
|
|
70
|
+
expect(mockAdapter.history.get).toHaveLength(3); // 1 initial + 2 retries
|
|
71
|
+
}, 10000); // Allow time for 2 retries
|
|
72
|
+
it('should retry once after 2 seconds when response is 429 and Retry-After header is valid value', async () => {
|
|
73
|
+
// Arrange
|
|
74
|
+
const testUrl = '/test-endpoint';
|
|
75
|
+
const errorData = { error: 'Too Many Requests' };
|
|
76
|
+
const successData = { message: 'success after rate limit retry' };
|
|
77
|
+
mockAdapter
|
|
78
|
+
.onGet(testUrl)
|
|
79
|
+
.replyOnce(429, errorData, {
|
|
80
|
+
'Retry-After': '2',
|
|
81
|
+
})
|
|
82
|
+
.onGet(testUrl)
|
|
83
|
+
.reply(200, successData);
|
|
84
|
+
// Act
|
|
85
|
+
const response = await axios_client_internal_1.axiosClient.get(testUrl);
|
|
86
|
+
// Assert
|
|
87
|
+
expect(response.status).toBe(200);
|
|
88
|
+
expect(response.data).toEqual(successData);
|
|
89
|
+
expect(mockAdapter.history.get).toHaveLength(2); // 1 initial + 1 retry
|
|
90
|
+
});
|
|
91
|
+
it('should retry once after 2 seconds and measure time between retries when response is 429 and Retry-After header is valid value', async () => {
|
|
92
|
+
// Arrange
|
|
93
|
+
const testUrl = '/test-endpoint';
|
|
94
|
+
const errorData = { error: 'Too Many Requests' };
|
|
95
|
+
const successData = { message: 'success after rate limit retry' };
|
|
96
|
+
const retryAfterSeconds = 2;
|
|
97
|
+
mockAdapter
|
|
98
|
+
.onGet(testUrl)
|
|
99
|
+
.replyOnce(429, errorData, {
|
|
100
|
+
'Retry-After': retryAfterSeconds.toString(),
|
|
101
|
+
})
|
|
102
|
+
.onGet(testUrl)
|
|
103
|
+
.reply(200, successData);
|
|
104
|
+
// Act
|
|
105
|
+
const startTime = Date.now();
|
|
106
|
+
const response = await axios_client_internal_1.axiosClient.get(testUrl);
|
|
107
|
+
const endTime = Date.now();
|
|
108
|
+
const actualWaitTime = endTime - startTime;
|
|
109
|
+
// Assert
|
|
110
|
+
expect(response.status).toBe(200);
|
|
111
|
+
expect(response.data).toEqual(successData);
|
|
112
|
+
expect(mockAdapter.history.get).toHaveLength(2); // 1 initial + 1 retry
|
|
113
|
+
const expectedWaitTime = retryAfterSeconds * 1000;
|
|
114
|
+
expect(actualWaitTime).toBeGreaterThanOrEqual(expectedWaitTime - 100);
|
|
115
|
+
expect(actualWaitTime).toBeLessThan(expectedWaitTime + 1000); // Allow up to 1s extra for processing
|
|
116
|
+
});
|
|
117
|
+
it('should retry when response is 429 and Retry-After header is lowercase', async () => {
|
|
118
|
+
// Arrange
|
|
119
|
+
const testUrl = '/test-endpoint';
|
|
120
|
+
const errorData = { error: 'Too Many Requests' };
|
|
121
|
+
const successData = { message: 'success after rate limit retry' };
|
|
122
|
+
mockAdapter
|
|
123
|
+
.onGet(testUrl)
|
|
124
|
+
.replyOnce(429, errorData, { 'retry-after': '2' })
|
|
125
|
+
.onGet(testUrl)
|
|
126
|
+
.reply(200, successData);
|
|
127
|
+
// Act
|
|
128
|
+
const response = await axios_client_internal_1.axiosClient.get(testUrl);
|
|
129
|
+
// Assert
|
|
130
|
+
expect(response.status).toBe(200);
|
|
131
|
+
expect(response.data).toEqual(successData);
|
|
132
|
+
expect(mockAdapter.history.get).toHaveLength(2); // 1 initial + 1 retry
|
|
133
|
+
});
|
|
134
|
+
it('[edge] should not retry when response is 429 and there is no Retry-After header', async () => {
|
|
135
|
+
// Arrange
|
|
136
|
+
const testUrl = '/test-endpoint';
|
|
137
|
+
const errorData = { error: 'Too Many Requests' };
|
|
138
|
+
mockAdapter.onGet(testUrl).reply(429, errorData);
|
|
139
|
+
// Act
|
|
140
|
+
await expect(axios_client_internal_1.axiosClient.get(testUrl)).rejects.toMatchObject({
|
|
141
|
+
response: { status: 429 },
|
|
142
|
+
});
|
|
143
|
+
// Assert
|
|
144
|
+
expect(mockAdapter.history.get).toHaveLength(1);
|
|
145
|
+
});
|
|
146
|
+
it('[edge] should retry when response is 429 and Retry-After header is 0', async () => {
|
|
147
|
+
// Arrange
|
|
148
|
+
const testUrl = '/test-endpoint';
|
|
149
|
+
const errorData = { error: 'Too Many Requests' };
|
|
150
|
+
const successData = { message: 'success after rate limit retry' };
|
|
151
|
+
mockAdapter
|
|
152
|
+
.onGet(testUrl)
|
|
153
|
+
.replyOnce(429, errorData, { 'Retry-After': '0' })
|
|
154
|
+
.onGet(testUrl)
|
|
155
|
+
.reply(200, successData);
|
|
156
|
+
// Act
|
|
157
|
+
const response = await axios_client_internal_1.axiosClient.get(testUrl);
|
|
158
|
+
// Assert
|
|
159
|
+
expect(response.status).toBe(200);
|
|
160
|
+
expect(response.data).toEqual(successData);
|
|
161
|
+
expect(mockAdapter.history.get).toHaveLength(2); // 1 initial + 1 retry
|
|
162
|
+
});
|
|
163
|
+
it('[edge] should not retry when response is 429 and Retry-After header is negative', async () => {
|
|
164
|
+
// Arrange
|
|
165
|
+
const testUrl = '/test-endpoint';
|
|
166
|
+
const errorData = { error: 'Too Many Requests' };
|
|
167
|
+
mockAdapter.onGet(testUrl).reply(429, errorData, { 'Retry-After': '-1' });
|
|
168
|
+
// Act
|
|
169
|
+
await expect(axios_client_internal_1.axiosClient.get(testUrl)).rejects.toMatchObject({
|
|
170
|
+
response: { status: 429 },
|
|
171
|
+
});
|
|
172
|
+
// Assert
|
|
173
|
+
expect(mockAdapter.history.get).toHaveLength(1);
|
|
174
|
+
});
|
|
175
|
+
it('[edge] should not retry when response is 429 and Retry-After header is invalid value', async () => {
|
|
176
|
+
// Arrange
|
|
177
|
+
const testUrl = '/test-endpoint';
|
|
178
|
+
const errorData = { error: 'Too Many Requests' };
|
|
179
|
+
mockAdapter
|
|
180
|
+
.onGet(testUrl)
|
|
181
|
+
.reply(429, errorData, { 'Retry-After': 'invalid' });
|
|
182
|
+
// Act
|
|
183
|
+
await expect(axios_client_internal_1.axiosClient.get(testUrl)).rejects.toMatchObject({
|
|
184
|
+
response: { status: 429 },
|
|
185
|
+
});
|
|
186
|
+
// Assert
|
|
187
|
+
expect(mockAdapter.history.get).toHaveLength(1);
|
|
188
|
+
});
|
|
189
|
+
});
|
package/dist/logger/logger.js
CHANGED
|
@@ -14,7 +14,7 @@ class Logger extends node_console_1.Console {
|
|
|
14
14
|
constructor({ event, options }) {
|
|
15
15
|
super(process.stdout, process.stderr);
|
|
16
16
|
this.options = options;
|
|
17
|
-
this.tags = Object.assign(Object.assign({}, event.payload.event_context), { dev_oid: event.payload.event_context.
|
|
17
|
+
this.tags = Object.assign(Object.assign({}, event.payload.event_context), { dev_oid: event.payload.event_context.dev_oid });
|
|
18
18
|
}
|
|
19
19
|
valueToString(value) {
|
|
20
20
|
if (typeof value === 'string') {
|
|
@@ -14,7 +14,7 @@ jest.mock('node:worker_threads', () => ({
|
|
|
14
14
|
isMainThread: true,
|
|
15
15
|
parentPort: null,
|
|
16
16
|
}));
|
|
17
|
-
describe(
|
|
17
|
+
describe(logger_1.Logger.name, () => {
|
|
18
18
|
let mockEvent;
|
|
19
19
|
let mockOptions;
|
|
20
20
|
beforeEach(() => {
|
|
@@ -50,7 +50,7 @@ describe('Logger', () => {
|
|
|
50
50
|
const logger = new logger_1.Logger({ event: mockEvent, options: mockOptions });
|
|
51
51
|
// Access private property for testing
|
|
52
52
|
const tags = logger.tags;
|
|
53
|
-
expect(tags).toEqual(Object.assign(Object.assign({}, mockEvent.payload.event_context), { dev_oid: mockEvent.payload.event_context.
|
|
53
|
+
expect(tags).toEqual(Object.assign(Object.assign({}, mockEvent.payload.event_context), { dev_oid: mockEvent.payload.event_context.dev_oid }));
|
|
54
54
|
});
|
|
55
55
|
});
|
|
56
56
|
describe('production logging', () => {
|
|
@@ -62,7 +62,7 @@ describe('Logger', () => {
|
|
|
62
62
|
it('should log single string message without backslashes', () => {
|
|
63
63
|
const message = 'Worker is online. Started processing the task.';
|
|
64
64
|
logger.info(message);
|
|
65
|
-
expect(mockConsoleInfo).toHaveBeenCalledWith(JSON.stringify(Object.assign(Object.assign({ message }, mockEvent.payload.event_context), { dev_oid: mockEvent.payload.event_context.
|
|
65
|
+
expect(mockConsoleInfo).toHaveBeenCalledWith(JSON.stringify(Object.assign(Object.assign({ message }, mockEvent.payload.event_context), { dev_oid: mockEvent.payload.event_context.dev_oid })));
|
|
66
66
|
});
|
|
67
67
|
it('should log single object message with JSON stringify', () => {
|
|
68
68
|
const data = { id: 123, name: 'test' };
|
|
@@ -71,7 +71,7 @@ describe('Logger', () => {
|
|
|
71
71
|
compact: false,
|
|
72
72
|
depth: Infinity,
|
|
73
73
|
});
|
|
74
|
-
expect(mockConsoleInfo).toHaveBeenCalledWith(JSON.stringify(Object.assign(Object.assign({ message: expectedMessage }, mockEvent.payload.event_context), { dev_oid: mockEvent.payload.event_context.
|
|
74
|
+
expect(mockConsoleInfo).toHaveBeenCalledWith(JSON.stringify(Object.assign(Object.assign({ message: expectedMessage }, mockEvent.payload.event_context), { dev_oid: mockEvent.payload.event_context.dev_oid })));
|
|
75
75
|
});
|
|
76
76
|
it('should log multiple arguments joined with space', () => {
|
|
77
77
|
const text = 'Successfully fetched';
|
|
@@ -81,7 +81,7 @@ describe('Logger', () => {
|
|
|
81
81
|
compact: false,
|
|
82
82
|
depth: Infinity,
|
|
83
83
|
});
|
|
84
|
-
expect(mockConsoleInfo).toHaveBeenCalledWith(JSON.stringify(Object.assign(Object.assign({ message: `${text} ${expectedDataMessage}` }, mockEvent.payload.event_context), { dev_oid: mockEvent.payload.event_context.
|
|
84
|
+
expect(mockConsoleInfo).toHaveBeenCalledWith(JSON.stringify(Object.assign(Object.assign({ message: `${text} ${expectedDataMessage}` }, mockEvent.payload.event_context), { dev_oid: mockEvent.payload.event_context.dev_oid })));
|
|
85
85
|
});
|
|
86
86
|
it('should handle mixed string and object arguments', () => {
|
|
87
87
|
const text1 = 'Processing';
|
|
@@ -92,7 +92,7 @@ describe('Logger', () => {
|
|
|
92
92
|
compact: false,
|
|
93
93
|
depth: Infinity,
|
|
94
94
|
});
|
|
95
|
-
expect(mockConsoleInfo).toHaveBeenCalledWith(JSON.stringify(Object.assign(Object.assign({ message: `${text1} ${expectedDataMessage} ${text2}` }, mockEvent.payload.event_context), { dev_oid: mockEvent.payload.event_context.
|
|
95
|
+
expect(mockConsoleInfo).toHaveBeenCalledWith(JSON.stringify(Object.assign(Object.assign({ message: `${text1} ${expectedDataMessage} ${text2}` }, mockEvent.payload.event_context), { dev_oid: mockEvent.payload.event_context.dev_oid })));
|
|
96
96
|
});
|
|
97
97
|
});
|
|
98
98
|
describe('local development logging', () => {
|
|
@@ -137,25 +137,25 @@ describe('Logger', () => {
|
|
|
137
137
|
mockOptions.isLocalDevelopment = false;
|
|
138
138
|
logger = new logger_1.Logger({ event: mockEvent, options: mockOptions });
|
|
139
139
|
});
|
|
140
|
-
it('should handle empty string message', () => {
|
|
140
|
+
it('[edge] should handle empty string message', () => {
|
|
141
141
|
logger.info('');
|
|
142
142
|
expect(mockConsoleInfo).toHaveBeenCalledTimes(1);
|
|
143
143
|
const callArgs = mockConsoleInfo.mock.calls[0][0];
|
|
144
144
|
const logObject = JSON.parse(callArgs);
|
|
145
145
|
expect(logObject.message).toBe('');
|
|
146
|
-
expect(logObject.dev_oid).toBe(mockEvent.payload.event_context.
|
|
146
|
+
expect(logObject.dev_oid).toBe(mockEvent.payload.event_context.dev_oid);
|
|
147
147
|
expect(logObject.request_id).toBe(mockEvent.payload.event_context.request_id);
|
|
148
148
|
});
|
|
149
|
-
it('should handle null and undefined values', () => {
|
|
149
|
+
it('[edge] should handle null and undefined values', () => {
|
|
150
150
|
logger.info('test', null, undefined);
|
|
151
151
|
expect(mockConsoleInfo).toHaveBeenCalledTimes(1);
|
|
152
152
|
const callArgs = mockConsoleInfo.mock.calls[0][0];
|
|
153
153
|
const logObject = JSON.parse(callArgs);
|
|
154
154
|
// inspect shows 'null' and 'undefined' as strings
|
|
155
155
|
expect(logObject.message).toBe('test null undefined');
|
|
156
|
-
expect(logObject.dev_oid).toBe(mockEvent.payload.event_context.
|
|
156
|
+
expect(logObject.dev_oid).toBe(mockEvent.payload.event_context.dev_oid);
|
|
157
157
|
});
|
|
158
|
-
it('should handle complex nested objects', () => {
|
|
158
|
+
it('[edge] should handle complex nested objects', () => {
|
|
159
159
|
const complexObject = {
|
|
160
160
|
level1: {
|
|
161
161
|
level2: {
|
|
@@ -174,7 +174,7 @@ describe('Logger', () => {
|
|
|
174
174
|
depth: Infinity,
|
|
175
175
|
});
|
|
176
176
|
expect(logObject.message).toBe(expectedMessage);
|
|
177
|
-
expect(logObject.dev_oid).toBe(mockEvent.payload.event_context.
|
|
177
|
+
expect(logObject.dev_oid).toBe(mockEvent.payload.event_context.dev_oid);
|
|
178
178
|
expect(typeof logObject.callback_url).toBe('string');
|
|
179
179
|
});
|
|
180
180
|
});
|
package/dist/mappers/mappers.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Mappers = void 0;
|
|
4
|
-
const
|
|
4
|
+
const axios_client_internal_1 = require("../http/axios-client-internal");
|
|
5
5
|
class Mappers {
|
|
6
6
|
constructor({ event }) {
|
|
7
7
|
this.devrevApiEndpoint = event.execution_metadata.devrev_endpoint;
|
|
@@ -9,7 +9,7 @@ class Mappers {
|
|
|
9
9
|
}
|
|
10
10
|
async getByTargetId(params) {
|
|
11
11
|
const { sync_unit, target } = params;
|
|
12
|
-
return
|
|
12
|
+
return axios_client_internal_1.axiosClient.get(`${this.devrevApiEndpoint}/internal/airdrop.sync-mapper-record.get-by-target`, {
|
|
13
13
|
headers: {
|
|
14
14
|
Authorization: this.devrevApiToken,
|
|
15
15
|
},
|
|
@@ -17,14 +17,14 @@ class Mappers {
|
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
19
|
async create(params) {
|
|
20
|
-
return
|
|
20
|
+
return axios_client_internal_1.axiosClient.post(`${this.devrevApiEndpoint}/internal/airdrop.sync-mapper-record.create`, params, {
|
|
21
21
|
headers: {
|
|
22
22
|
Authorization: this.devrevApiToken,
|
|
23
23
|
},
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
26
|
async update(params) {
|
|
27
|
-
return
|
|
27
|
+
return axios_client_internal_1.axiosClient.post(`${this.devrevApiEndpoint}/internal/airdrop.sync-mapper-record.update`, params, {
|
|
28
28
|
headers: {
|
|
29
29
|
Authorization: this.devrevApiToken,
|
|
30
30
|
},
|
package/dist/repo/repo.test.js
CHANGED
|
@@ -5,7 +5,7 @@ const test_helpers_1 = require("../tests/test-helpers");
|
|
|
5
5
|
const types_1 = require("../types");
|
|
6
6
|
const repo_1 = require("./repo");
|
|
7
7
|
jest.mock('../tests/test-helpers', () => (Object.assign(Object.assign({}, jest.requireActual('../tests/test-helpers')), { normalizeItem: jest.fn() })));
|
|
8
|
-
describe(
|
|
8
|
+
describe(repo_1.Repo.name, () => {
|
|
9
9
|
let repo;
|
|
10
10
|
let normalize;
|
|
11
11
|
beforeEach(() => {
|
|
@@ -20,18 +20,14 @@ describe('Repo class push method', () => {
|
|
|
20
20
|
afterEach(() => {
|
|
21
21
|
jest.clearAllMocks();
|
|
22
22
|
});
|
|
23
|
-
it('should
|
|
24
|
-
await repo.push([]);
|
|
25
|
-
expect(repo.getItems()).toEqual([]);
|
|
26
|
-
});
|
|
27
|
-
it('should normalize and push 10 items if array is not empty', async () => {
|
|
23
|
+
it('should normalize and push items when array contains items', async () => {
|
|
28
24
|
const items = (0, test_helpers_1.createItems)(10);
|
|
29
25
|
await repo.push(items);
|
|
30
26
|
expect(normalize).toHaveBeenCalledTimes(10);
|
|
31
27
|
const normalizedItems = items.map((item) => (0, test_helpers_1.normalizeItem)(item));
|
|
32
28
|
expect(repo.getItems()).toEqual(normalizedItems);
|
|
33
29
|
});
|
|
34
|
-
it('should not normalize items
|
|
30
|
+
it('should not normalize items when normalize function is not provided', async () => {
|
|
35
31
|
repo = new repo_1.Repo({
|
|
36
32
|
event: (0, test_helpers_1.createEvent)({ eventType: types_1.EventType.ExtractionDataStart }),
|
|
37
33
|
itemType: 'test_item_type',
|
|
@@ -42,46 +38,56 @@ describe('Repo class push method', () => {
|
|
|
42
38
|
await repo.push(items);
|
|
43
39
|
expect(normalize).not.toHaveBeenCalled();
|
|
44
40
|
});
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
expect(normalize).not.toHaveBeenCalled();
|
|
41
|
+
it('[edge] should not push items when items array is empty', async () => {
|
|
42
|
+
await repo.push([]);
|
|
43
|
+
expect(repo.getItems()).toEqual([]);
|
|
44
|
+
});
|
|
45
|
+
it('should not normalize items when item type is external_domain_metadata', async () => {
|
|
46
|
+
repo = new repo_1.Repo({
|
|
47
|
+
event: (0, test_helpers_1.createEvent)({ eventType: types_1.EventType.ExtractionDataStart }),
|
|
48
|
+
itemType: constants_1.AIRDROP_DEFAULT_ITEM_TYPES.EXTERNAL_DOMAIN_METADATA,
|
|
49
|
+
normalize,
|
|
50
|
+
onUpload: jest.fn(),
|
|
51
|
+
options: {},
|
|
57
52
|
});
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
53
|
+
const items = (0, test_helpers_1.createItems)(10);
|
|
54
|
+
await repo.push(items);
|
|
55
|
+
expect(normalize).not.toHaveBeenCalled();
|
|
56
|
+
});
|
|
57
|
+
it('should not normalize items when item type is ssor_attachment', async () => {
|
|
58
|
+
repo = new repo_1.Repo({
|
|
59
|
+
event: (0, test_helpers_1.createEvent)({ eventType: types_1.EventType.ExtractionDataStart }),
|
|
60
|
+
itemType: constants_1.AIRDROP_DEFAULT_ITEM_TYPES.SSOR_ATTACHMENT,
|
|
61
|
+
normalize,
|
|
62
|
+
onUpload: jest.fn(),
|
|
63
|
+
options: {},
|
|
69
64
|
});
|
|
65
|
+
const items = (0, test_helpers_1.createItems)(10);
|
|
66
|
+
await repo.push(items);
|
|
67
|
+
expect(normalize).not.toHaveBeenCalled();
|
|
70
68
|
});
|
|
71
69
|
it('should leave 5 items in the items array after pushing 2005 items with batch size of 2000', async () => {
|
|
72
70
|
const items = (0, test_helpers_1.createItems)(2005);
|
|
73
71
|
await repo.push(items);
|
|
74
72
|
expect(repo.getItems().length).toBe(5);
|
|
75
73
|
});
|
|
76
|
-
it('should
|
|
77
|
-
const uploadSpy = jest.spyOn(repo, 'upload');
|
|
74
|
+
it('should normalize all items when pushing 4005 items with batch size of 2000', async () => {
|
|
78
75
|
const items = (0, test_helpers_1.createItems)(4005);
|
|
79
76
|
await repo.push(items);
|
|
80
77
|
expect(normalize).toHaveBeenCalledTimes(4005);
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
});
|
|
79
|
+
it('should upload 2 batches when pushing 4005 items with batch size of 2000', async () => {
|
|
80
|
+
const uploadSpy = jest.spyOn(repo, 'upload');
|
|
81
|
+
const items = (0, test_helpers_1.createItems)(4005);
|
|
82
|
+
await repo.push(items);
|
|
83
|
+
expect(uploadSpy).toHaveBeenCalledTimes(2);
|
|
83
84
|
uploadSpy.mockRestore();
|
|
84
85
|
});
|
|
86
|
+
it('should leave 5 items in array after pushing 4005 items with batch size of 2000', async () => {
|
|
87
|
+
const items = (0, test_helpers_1.createItems)(4005);
|
|
88
|
+
await repo.push(items);
|
|
89
|
+
expect(repo.getItems().length).toBe(5);
|
|
90
|
+
});
|
|
85
91
|
describe('should take batch size into account', () => {
|
|
86
92
|
beforeEach(() => {
|
|
87
93
|
repo = new repo_1.Repo({
|
|
@@ -104,14 +110,22 @@ describe('Repo class push method', () => {
|
|
|
104
110
|
await repo.push(items);
|
|
105
111
|
expect(repo.getItems().length).toBe(5);
|
|
106
112
|
});
|
|
107
|
-
it('should
|
|
108
|
-
const uploadSpy = jest.spyOn(repo, 'upload');
|
|
113
|
+
it('should normalize all items when pushing 205 items with batch size of 50', async () => {
|
|
109
114
|
const items = (0, test_helpers_1.createItems)(205);
|
|
110
115
|
await repo.push(items);
|
|
111
116
|
expect(normalize).toHaveBeenCalledTimes(205);
|
|
112
|
-
|
|
117
|
+
});
|
|
118
|
+
it('should upload 4 batches when pushing 205 items with batch size of 50', async () => {
|
|
119
|
+
const uploadSpy = jest.spyOn(repo, 'upload');
|
|
120
|
+
const items = (0, test_helpers_1.createItems)(205);
|
|
121
|
+
await repo.push(items);
|
|
113
122
|
expect(uploadSpy).toHaveBeenCalledTimes(4);
|
|
114
123
|
uploadSpy.mockRestore();
|
|
115
124
|
});
|
|
125
|
+
it('should leave 5 items in array after pushing 205 items with batch size of 50', async () => {
|
|
126
|
+
const items = (0, test_helpers_1.createItems)(205);
|
|
127
|
+
await repo.push(items);
|
|
128
|
+
expect(repo.getItems().length).toBe(5);
|
|
129
|
+
});
|
|
116
130
|
});
|
|
117
131
|
});
|
package/dist/state/state.d.ts
CHANGED
|
@@ -1,25 +1,29 @@
|
|
|
1
|
-
import { ErrorRecord } from '../types/common';
|
|
2
1
|
import { AdapterState, StateInterface } from './state.interfaces';
|
|
3
2
|
export declare function createAdapterState<ConnectorState>({ event, initialState, initialDomainMapping, options, }: StateInterface<ConnectorState>): Promise<State<ConnectorState>>;
|
|
4
3
|
export declare class State<ConnectorState> {
|
|
5
4
|
private _state;
|
|
6
5
|
private initialSdkState;
|
|
7
|
-
private event;
|
|
8
6
|
private workerUrl;
|
|
9
7
|
private devrevToken;
|
|
8
|
+
private syncUnitId;
|
|
9
|
+
private requestId;
|
|
10
10
|
constructor({ event, initialState }: StateInterface<ConnectorState>);
|
|
11
11
|
get state(): AdapterState<ConnectorState>;
|
|
12
12
|
set state(value: AdapterState<ConnectorState>);
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
14
|
+
* Initializes the state for this adapter instance by fetching from API
|
|
15
|
+
* or creating an initial state if none exists (404).
|
|
16
|
+
* @param initialState The initial connector state provided by the spawn function
|
|
17
|
+
*/
|
|
18
|
+
init(initialState: ConnectorState): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Updates the state of the adapter by posting to API.
|
|
16
21
|
* @param {object} state - The state to be updated
|
|
17
22
|
*/
|
|
18
23
|
postState(state?: AdapterState<ConnectorState>): Promise<void>;
|
|
19
24
|
/**
|
|
20
|
-
* Fetches the state of the adapter.
|
|
21
|
-
*
|
|
22
|
-
* @return The state of the adapter
|
|
25
|
+
* Fetches the state of the adapter from API.
|
|
26
|
+
* @return The raw state data from API
|
|
23
27
|
*/
|
|
24
|
-
fetchState(
|
|
28
|
+
fetchState(): Promise<string>;
|
|
25
29
|
}
|
|
@@ -30,3 +30,21 @@ export interface StateInterface<ConnectorState> {
|
|
|
30
30
|
initialDomainMapping?: InitialDomainMapping;
|
|
31
31
|
options?: WorkerAdapterOptions;
|
|
32
32
|
}
|
|
33
|
+
export declare const extractionSdkState: {
|
|
34
|
+
lastSyncStarted: string;
|
|
35
|
+
lastSuccessfulSyncStarted: string;
|
|
36
|
+
snapInVersionId: string;
|
|
37
|
+
toDevRev: {
|
|
38
|
+
attachmentsMetadata: {
|
|
39
|
+
artifactIds: never[];
|
|
40
|
+
lastProcessed: number;
|
|
41
|
+
lastProcessedAttachmentsIdsList: never[];
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
export declare const loadingSdkState: {
|
|
46
|
+
snapInVersionId: string;
|
|
47
|
+
fromDevRev: {
|
|
48
|
+
filesToLoad: never[];
|
|
49
|
+
};
|
|
50
|
+
};
|
|
@@ -1,2 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadingSdkState = exports.extractionSdkState = void 0;
|
|
4
|
+
exports.extractionSdkState = {
|
|
5
|
+
lastSyncStarted: '',
|
|
6
|
+
lastSuccessfulSyncStarted: '',
|
|
7
|
+
snapInVersionId: '',
|
|
8
|
+
toDevRev: {
|
|
9
|
+
attachmentsMetadata: {
|
|
10
|
+
artifactIds: [],
|
|
11
|
+
lastProcessed: 0,
|
|
12
|
+
lastProcessedAttachmentsIdsList: [],
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
exports.loadingSdkState = {
|
|
17
|
+
snapInVersionId: '',
|
|
18
|
+
fromDevRev: {
|
|
19
|
+
filesToLoad: [],
|
|
20
|
+
},
|
|
21
|
+
};
|