@devrev/ts-adaas 1.2.5 → 1.3.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/README.md +246 -84
- package/dist/common/install-initial-domain-mapping.d.ts +2 -2
- package/dist/http/axios-client.d.ts +23 -0
- package/dist/http/axios-client.js +27 -3
- package/dist/state/state.d.ts +1 -1
- package/dist/state/state.interfaces.d.ts +5 -1
- package/dist/state/state.js +24 -2
- package/dist/tests/test-helpers.js +1 -1
- package/dist/types/extraction.d.ts +1 -0
- package/dist/types/workers.d.ts +4 -0
- package/dist/workers/process-task.js +2 -0
- package/dist/workers/spawn.d.ts +1 -1
- package/dist/workers/spawn.js +2 -1
- package/dist/workers/worker-adapter.d.ts +1 -1
- package/dist/workers/worker-adapter.js +29 -17
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,135 +1,297 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Airdrop SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://coveralls.io/github/devrev/adaas-sdk?branch=main)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Overview
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
- Remove unneccessary postState from default workers.
|
|
10
|
-
- Fix bugs related to attachment streaming.
|
|
7
|
+
The Airdrop SDK for TypeScript helps developers build snap-ins that integrate with DevRev’s Airdrop platform.
|
|
8
|
+
This SDK simplifies the workflow for handling data extraction and loading, event-driven actions, state management, and artifact handling.
|
|
11
9
|
|
|
12
|
-
|
|
10
|
+
It provides features such as:
|
|
13
11
|
|
|
14
|
-
-
|
|
12
|
+
- Type Definitions: Structured types for Airdrop control protocol
|
|
13
|
+
- Event Management: Easily emit events for different extraction or loading phases
|
|
14
|
+
- State Handling: Update and access state in real-time within tasks
|
|
15
|
+
- Artifact Management: Supports batched storage of artifacts
|
|
16
|
+
- Error & Timeout Support: Error handling and timeout management for long-running tasks
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
## Installation
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
- Fix bugs related to event handling, error logging.
|
|
20
|
+
```bash
|
|
21
|
+
npm install @devrev/ts-adaas
|
|
22
|
+
```
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
## Reference
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
- Improve axios client and adapter logging.
|
|
27
|
-
- Fix bugs related to state handling.
|
|
26
|
+
### `spawn` function
|
|
28
27
|
|
|
29
|
-
|
|
28
|
+
This function initializes a new worker thread and oversees its lifecycle.
|
|
29
|
+
It should be invoked when the snap-in receives a message from the Airdrop platform.
|
|
30
|
+
The worker script provided then handles the event accordingly.
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
- Correct the setting of the `lastSyncStarted` timestamp.
|
|
33
|
-
- Improve logging for attachment extraction and loading.
|
|
34
|
-
- Fix several bugs related to the control protocol.
|
|
32
|
+
#### Usage
|
|
35
33
|
|
|
36
|
-
|
|
34
|
+
```typescript
|
|
35
|
+
spawn({ event, initialState, workerPath, options })
|
|
36
|
+
```
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
#### Parameters
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
* _event_
|
|
41
|
+
|
|
42
|
+
Required. An object of type __AirdropEvent__ that is received from the Airdrop platform.
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
- Gracefully handle failure to upload extracted attachments.
|
|
44
|
+
* _initialState_
|
|
44
45
|
|
|
45
|
-
|
|
46
|
+
Required. Object of __any__ type that represents the initial state of the snap-in.
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
- Provide an inject function for streaming attachments.
|
|
49
|
-
- Fix the attachments streaming bug.
|
|
48
|
+
* _workerPath_
|
|
50
49
|
|
|
51
|
-
|
|
50
|
+
Required. A __string__ that represents the path to the worker file.
|
|
52
51
|
|
|
53
|
-
|
|
52
|
+
* _options_
|
|
54
53
|
|
|
55
|
-
|
|
54
|
+
Optional. An object of type **WorkerAdapterOptions**, which will be passed to the newly created worker. This worker will then initialize a `WorkerAdapter` by invoking the `processTask` function. The options include:
|
|
55
|
+
|
|
56
|
+
* `isLocalDevelopment`
|
|
57
|
+
|
|
58
|
+
A __boolean__ flag. If set to `true`, intermediary files containing extracted data will be stored on the local machine, which is useful during development. The default value is `false`.
|
|
56
59
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
* `timeout`
|
|
61
|
+
|
|
62
|
+
A __number__ that specifies the timeout duration for the lambda function, in milliseconds. The default is 10 minutes (10 * 60 * 1000 milliseconds), with a maximum allowable duration of 13 minutes (13 * 60 * 1000 milliseconds).
|
|
63
|
+
|
|
64
|
+
* `batchSize`
|
|
61
65
|
|
|
62
|
-
|
|
66
|
+
A __number__ that determines the maximum number of items to be processed and saved to an intermediary file before being sent to the Airdrop platform. The default batch size is 2,000.
|
|
63
67
|
|
|
64
|
-
|
|
65
|
-
- Add `dev_oid` to logger tags.
|
|
68
|
+
#### Return value
|
|
66
69
|
|
|
67
|
-
|
|
70
|
+
A __promise__ that resolves once the worker has completed processing.
|
|
68
71
|
|
|
69
|
-
|
|
72
|
+
#### Example
|
|
70
73
|
|
|
71
|
-
|
|
74
|
+
```typescript
|
|
75
|
+
const run = async (events: AirdropEvent[]) => {
|
|
76
|
+
for (const event of events) {
|
|
77
|
+
const file = getWorkerPerExtractionPhase(event);
|
|
78
|
+
await spawn<ExtractorState>({
|
|
79
|
+
event,
|
|
80
|
+
initialState,
|
|
81
|
+
workerPath: file,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
```
|
|
72
86
|
|
|
73
|
-
|
|
87
|
+
### `processTask` function
|
|
74
88
|
|
|
75
|
-
|
|
89
|
+
The `processTask` function retrieves the current state from the Airdrop platform and initializes a new `WorkerAdapter`.
|
|
90
|
+
It executes the code specified in the `task` parameter, which contains the worker's functionality.
|
|
91
|
+
If a timeout occurs, the function handles it by executing the `onTimeout` callback, ensuring the worker exits gracefully.
|
|
92
|
+
Both functions receive an `adapter` parameter, representing the initialized `WorkerAdapter` object.
|
|
76
93
|
|
|
77
|
-
- Fix logging from worker threads.
|
|
78
94
|
|
|
79
|
-
|
|
95
|
+
#### Usage
|
|
96
|
+
```typescript
|
|
97
|
+
processTask({ task, onTimeout })
|
|
98
|
+
```
|
|
80
99
|
|
|
81
|
-
|
|
100
|
+
#### Parameters
|
|
82
101
|
|
|
83
|
-
|
|
102
|
+
* _task_
|
|
103
|
+
|
|
104
|
+
Required. A __function__ that defines the logic associated with the given event type.
|
|
84
105
|
|
|
85
|
-
|
|
86
|
-
|
|
106
|
+
* _onTimeout_
|
|
107
|
+
|
|
108
|
+
Required. A __function__ managing the timeout of the lambda invocation, including saving any necessary progress at the time of timeout.
|
|
87
109
|
|
|
88
|
-
|
|
110
|
+
#### Example
|
|
89
111
|
|
|
90
|
-
|
|
112
|
+
````typescript
|
|
113
|
+
// External sync units extraction
|
|
114
|
+
processTask({
|
|
115
|
+
task: async ({ adapter }) => {
|
|
116
|
+
const httpClient = new HttpClient(adapter.event);
|
|
91
117
|
|
|
92
|
-
|
|
118
|
+
const todoLists = await httpClient.getTodoLists();
|
|
93
119
|
|
|
94
|
-
|
|
95
|
-
- Simplify metadata and data normalization and uploading with the repo implementation.
|
|
96
|
-
- Provide default handling of the attachment extraction phase in the ADaaS SDK library.
|
|
97
|
-
- Reduce file size and streamline processes with gzip compression.
|
|
98
|
-
- Fix bugs and improve error handling.
|
|
120
|
+
const externalSyncUnits: ExternalSyncUnit[] = todoLists.map((todoList) => normalizeTodoList(todoList));
|
|
99
121
|
|
|
100
|
-
|
|
122
|
+
await adapter.emit(ExtractorEventType.ExtractionExternalSyncUnitsDone, {
|
|
123
|
+
external_sync_units: externalSyncUnits,
|
|
124
|
+
});
|
|
125
|
+
},
|
|
126
|
+
onTimeout: async ({ adapter }) => {
|
|
127
|
+
await adapter.emit(ExtractorEventType.ExtractionExternalSyncUnitsError, {
|
|
128
|
+
error: {
|
|
129
|
+
message: 'Failed to extract external sync units. Lambda timeout.',
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
````
|
|
101
135
|
|
|
102
|
-
|
|
136
|
+
### `WorkerAdapter` class
|
|
103
137
|
|
|
104
|
-
|
|
138
|
+
Used to interact with Airdrop platform.
|
|
139
|
+
Provides utilities to emit events to the Airdrop platform, update the state of the snap-in and upload artifacts (files with data) to the platform.
|
|
105
140
|
|
|
106
|
-
|
|
107
|
-
- Provide an HTTP client for API requests.
|
|
108
|
-
- Create local artifact files in the local development environment.
|
|
109
|
-
- Improve logging.
|
|
141
|
+
### Usage
|
|
110
142
|
|
|
111
|
-
|
|
143
|
+
```typescript
|
|
144
|
+
new WorkerAdapter({
|
|
145
|
+
event,
|
|
146
|
+
adapterState,
|
|
147
|
+
options,
|
|
148
|
+
});
|
|
149
|
+
```
|
|
112
150
|
|
|
113
|
-
|
|
114
|
-
- Add an adapter for the ADaaS control protocol with helper functions.
|
|
115
|
-
- Provide an uploader for uploading artifacts.
|
|
151
|
+
#### Parameters
|
|
116
152
|
|
|
117
|
-
|
|
153
|
+
* _event_
|
|
154
|
+
|
|
155
|
+
Required. An object of type __AirdropEvent__ that is received from the Airdrop platform.
|
|
118
156
|
|
|
119
|
-
|
|
157
|
+
* _adapterState_
|
|
158
|
+
|
|
159
|
+
Required. An object of type __State__, which represents the initial state of the adapter.
|
|
120
160
|
|
|
121
|
-
|
|
161
|
+
* _options_
|
|
162
|
+
|
|
163
|
+
Optional. An object of type __WorkerAdapterOptions__ that specifies additional configuration options for the `WorkerAdapter`. This object is passed via the `spawn` function.
|
|
122
164
|
|
|
123
|
-
|
|
165
|
+
#### Example
|
|
124
166
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
167
|
+
```typescript
|
|
168
|
+
const adapter = new WorkerAdapter<ConnectorState>({
|
|
169
|
+
event,
|
|
170
|
+
adapterState,
|
|
171
|
+
options,
|
|
172
|
+
});
|
|
173
|
+
```
|
|
130
174
|
|
|
131
|
-
|
|
175
|
+
### `WorkerAdapter.state` property
|
|
132
176
|
|
|
133
|
-
|
|
134
|
-
|
|
177
|
+
Getter and setter methods for working with the adapter state.
|
|
178
|
+
|
|
179
|
+
### Usage
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
// get state
|
|
183
|
+
const adapterState = adapter.state;
|
|
184
|
+
|
|
185
|
+
// set state
|
|
186
|
+
adapter.state = newAdapterState;
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
#### Example
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
export const initialState: ExtractorState = {
|
|
193
|
+
users: { completed: false },
|
|
194
|
+
tasks: { completed: false },
|
|
195
|
+
attachments: { completed: false },
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
adapter.state = initialState;
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### `WorkerAdapter.initializeRepos` method
|
|
202
|
+
|
|
203
|
+
Initializes a `Repo` object for each item provided.
|
|
204
|
+
|
|
205
|
+
### Usage
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
adapter.initializeRepos(repos);
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### Parameters
|
|
212
|
+
|
|
213
|
+
* _repos_
|
|
214
|
+
|
|
215
|
+
Required. An array of objects of type `RepoInterface`.
|
|
216
|
+
|
|
217
|
+
#### Example
|
|
218
|
+
|
|
219
|
+
This should typically be called within the function passed as a parameter to the `processTask` function in the data extraction phase.
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
const repos = [
|
|
223
|
+
{
|
|
224
|
+
itemType: 'tasks',
|
|
225
|
+
normalize: normalizeTask,
|
|
226
|
+
}
|
|
227
|
+
];
|
|
228
|
+
|
|
229
|
+
adapter.initializeRepos(repos);
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### `WorkerAdapter.getRepo` method
|
|
233
|
+
|
|
234
|
+
Finds a Repo from the initialized repos.
|
|
235
|
+
|
|
236
|
+
### Usage
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
adapter.getRepo(itemType);
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
#### Parameters
|
|
243
|
+
|
|
244
|
+
* _itemType_
|
|
245
|
+
|
|
246
|
+
Required. A __string__ that represents the itemType property for the searched repo.
|
|
247
|
+
|
|
248
|
+
#### Return value
|
|
249
|
+
|
|
250
|
+
An object of type __Repo__ if the repo is found, otherwise __undefined__.
|
|
251
|
+
|
|
252
|
+
#### Example
|
|
253
|
+
|
|
254
|
+
This should typically be called within the function passed as a parameter to the `processTask` function.
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
// Push users to the repository designated for 'users' data.
|
|
258
|
+
await adapter.getRepo('users')?.push(users);
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### `WorkerAdapter.emit` method
|
|
262
|
+
|
|
263
|
+
Emits an event to the Airdrop platform.
|
|
264
|
+
|
|
265
|
+
### Usage
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
adapter.emit( newEventType, data ):
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
#### Parameters
|
|
272
|
+
|
|
273
|
+
* _newEventType_
|
|
274
|
+
|
|
275
|
+
Required. The event type to be emitted, of type __ExtractorEventType__ or __LoaderEventType__.
|
|
276
|
+
|
|
277
|
+
* _data_
|
|
278
|
+
|
|
279
|
+
Optional. An object of type __EventData__ which represents the data to be sent with the event.
|
|
280
|
+
|
|
281
|
+
#### Return value
|
|
282
|
+
|
|
283
|
+
A __promise__, which resolves to undefined after the emit function completes its execution or rejects with an error.
|
|
284
|
+
|
|
285
|
+
#### Example
|
|
286
|
+
|
|
287
|
+
This should typically be called within the function passed as a parameter to the `processTask` function.
|
|
288
|
+
|
|
289
|
+
```typescript
|
|
290
|
+
// Emitting successfully finished data extraction.
|
|
291
|
+
await adapter.emit(ExtractorEventType.ExtractionDataDone);
|
|
292
|
+
|
|
293
|
+
// Emitting a delay in attachments extraction phase.
|
|
294
|
+
await adapter.emit(ExtractorEventType.ExtractionAttachmentsDelay, {
|
|
295
|
+
delay: 10,
|
|
296
|
+
});
|
|
135
297
|
```
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AirdropEvent } from '../types/extraction';
|
|
2
2
|
import { InitialDomainMapping } from '../types/common';
|
|
3
|
-
export declare function installInitialDomainMapping(event:
|
|
3
|
+
export declare function installInitialDomainMapping(event: AirdropEvent, initialDomainMappingJson: InitialDomainMapping): Promise<void>;
|
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Axios client setup with retry capabilities using axios-retry.
|
|
3
|
+
*
|
|
4
|
+
* This module exports an Axios client instance (`axiosClient`) that is configured to automatically retry
|
|
5
|
+
* failed requests under certain conditions.
|
|
6
|
+
*
|
|
7
|
+
* Retry Conditions:
|
|
8
|
+
* 1. Network errors (where no response is received).
|
|
9
|
+
* 2. Idempotent requests (defaults include GET, HEAD, OPTIONS, PUT).
|
|
10
|
+
* 3. All 5xx server errors.
|
|
11
|
+
*
|
|
12
|
+
* Retry Strategy:
|
|
13
|
+
* - A maximum of 5 retries are attempted.
|
|
14
|
+
* - Exponential backoff delay is applied between retries, increasing with each retry attempt.
|
|
15
|
+
*
|
|
16
|
+
* Additional Features:
|
|
17
|
+
* - When the maximum number of retry attempts is reached, sensitive headers (like authorization)
|
|
18
|
+
* are removed from error logs for security reasons.
|
|
19
|
+
*
|
|
20
|
+
* Exported:
|
|
21
|
+
* - `axios`: Original axios instance for additional customizations or direct use.
|
|
22
|
+
* - `axiosClient`: Configured axios instance with retry logic.
|
|
23
|
+
*/
|
|
1
24
|
import axios from 'axios';
|
|
2
25
|
declare const axiosClient: import("axios").AxiosInstance;
|
|
3
26
|
export { axios, axiosClient };
|
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Axios client setup with retry capabilities using axios-retry.
|
|
4
|
+
*
|
|
5
|
+
* This module exports an Axios client instance (`axiosClient`) that is configured to automatically retry
|
|
6
|
+
* failed requests under certain conditions.
|
|
7
|
+
*
|
|
8
|
+
* Retry Conditions:
|
|
9
|
+
* 1. Network errors (where no response is received).
|
|
10
|
+
* 2. Idempotent requests (defaults include GET, HEAD, OPTIONS, PUT).
|
|
11
|
+
* 3. All 5xx server errors.
|
|
12
|
+
*
|
|
13
|
+
* Retry Strategy:
|
|
14
|
+
* - A maximum of 5 retries are attempted.
|
|
15
|
+
* - Exponential backoff delay is applied between retries, increasing with each retry attempt.
|
|
16
|
+
*
|
|
17
|
+
* Additional Features:
|
|
18
|
+
* - When the maximum number of retry attempts is reached, sensitive headers (like authorization)
|
|
19
|
+
* are removed from error logs for security reasons.
|
|
20
|
+
*
|
|
21
|
+
* Exported:
|
|
22
|
+
* - `axios`: Original axios instance for additional customizations or direct use.
|
|
23
|
+
* - `axiosClient`: Configured axios instance with retry logic.
|
|
24
|
+
*/
|
|
2
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
27
|
};
|
|
@@ -19,9 +42,10 @@ exports.axiosClient = axiosClient;
|
|
|
19
42
|
return delay;
|
|
20
43
|
},
|
|
21
44
|
retryCondition: (error) => {
|
|
22
|
-
var _a;
|
|
23
|
-
return (axios_retry_1.default.isNetworkOrIdempotentRequestError(error) &&
|
|
24
|
-
((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) !== 429)
|
|
45
|
+
var _a, _b, _c;
|
|
46
|
+
return ((axios_retry_1.default.isNetworkOrIdempotentRequestError(error) &&
|
|
47
|
+
((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) !== 429) ||
|
|
48
|
+
((_c = (_b = error.response) === null || _b === void 0 ? void 0 : _b.status) !== null && _c !== void 0 ? _c : 0) >= 500);
|
|
25
49
|
},
|
|
26
50
|
onMaxRetryTimesExceeded(error) {
|
|
27
51
|
var _a, _b, _c, _d;
|
package/dist/state/state.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ErrorRecord } from '../types/common';
|
|
2
2
|
import { AdapterState, StateInterface } from './state.interfaces';
|
|
3
|
-
export declare function createAdapterState<ConnectorState>({ event, initialState, options, }: StateInterface<ConnectorState>): Promise<State<ConnectorState>>;
|
|
3
|
+
export declare function createAdapterState<ConnectorState>({ event, initialState, initialDomainMapping, options, }: StateInterface<ConnectorState>): Promise<State<ConnectorState>>;
|
|
4
4
|
export declare class State<ConnectorState> {
|
|
5
5
|
private _state;
|
|
6
6
|
private initialSdkState;
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { AirdropEvent } from '../types/extraction';
|
|
2
2
|
import { FileToLoad } from '../types/loading';
|
|
3
3
|
import { WorkerAdapterOptions } from '../types/workers';
|
|
4
|
+
import { InitialDomainMapping } from '../types/common';
|
|
4
5
|
export interface SdkState {
|
|
5
6
|
lastSyncStarted?: string;
|
|
6
7
|
lastSuccessfulSyncStarted?: string;
|
|
7
8
|
toDevRev?: ToDevRev;
|
|
8
9
|
fromDevRev?: FromDevRev;
|
|
10
|
+
snapInVersionId?: string;
|
|
9
11
|
}
|
|
10
12
|
/**
|
|
11
|
-
* AdapterState is an interface that defines the structure of the adapter state that is used by the external extractor.
|
|
13
|
+
* AdapterState is an interface that defines the structure of the adapter state that is used by the external extractor.
|
|
14
|
+
* It extends the connector state with additional fields: lastSyncStarted, lastSuccessfulSyncStarted, snapInVersionId and attachmentsMetadata.
|
|
12
15
|
*/
|
|
13
16
|
export type AdapterState<ConnectorState> = ConnectorState & SdkState;
|
|
14
17
|
export interface ToDevRev {
|
|
@@ -23,5 +26,6 @@ export interface FromDevRev {
|
|
|
23
26
|
export interface StateInterface<ConnectorState> {
|
|
24
27
|
event: AirdropEvent;
|
|
25
28
|
initialState: ConnectorState;
|
|
29
|
+
initialDomainMapping?: InitialDomainMapping;
|
|
26
30
|
options?: WorkerAdapterOptions;
|
|
27
31
|
}
|
package/dist/state/state.js
CHANGED
|
@@ -6,16 +6,36 @@ const axios_client_1 = require("../http/axios-client");
|
|
|
6
6
|
const extraction_1 = require("../types/extraction");
|
|
7
7
|
const constants_1 = require("../common/constants");
|
|
8
8
|
const logger_1 = require("../logger/logger");
|
|
9
|
+
const install_initial_domain_mapping_1 = require("../common/install-initial-domain-mapping");
|
|
9
10
|
const helpers_1 = require("../common/helpers");
|
|
10
|
-
async function createAdapterState({ event, initialState, options, }) {
|
|
11
|
+
async function createAdapterState({ event, initialState, initialDomainMapping, options, }) {
|
|
12
|
+
var _a;
|
|
11
13
|
const newInitialState = structuredClone(initialState);
|
|
12
14
|
const as = new State({
|
|
13
15
|
event,
|
|
14
16
|
initialState: newInitialState,
|
|
17
|
+
initialDomainMapping,
|
|
15
18
|
options,
|
|
16
19
|
});
|
|
17
20
|
if (!constants_1.STATELESS_EVENT_TYPES.includes(event.payload.event_type)) {
|
|
18
21
|
await as.fetchState(newInitialState);
|
|
22
|
+
const snapInVersionId = event.context.snap_in_version_id;
|
|
23
|
+
const hasSnapInVersionInState = 'snapInVersionId' in as.state;
|
|
24
|
+
const shouldUpdateIDM = !hasSnapInVersionInState || as.state.snapInVersionId !== snapInVersionId;
|
|
25
|
+
if (shouldUpdateIDM) {
|
|
26
|
+
console.log(`Snap-in version in state (${(_a = as.state) === null || _a === void 0 ? void 0 : _a.snapInVersionId}) differs from the version in event context (${snapInVersionId}) - initial domain mapping needs to be updated.`);
|
|
27
|
+
if (initialDomainMapping) {
|
|
28
|
+
await (0, install_initial_domain_mapping_1.installInitialDomainMapping)(event, initialDomainMapping);
|
|
29
|
+
as.state.snapInVersionId = snapInVersionId;
|
|
30
|
+
console.log('Successfully installed new initial domain mapping.');
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
console.warn('No initial domain mapping was passed to spawn function. Skipping initial domain mapping installation.');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
console.log(`Snap-in version in state matches the version in event context (${snapInVersionId}). Skipping initial domain mapping installation.`);
|
|
38
|
+
}
|
|
19
39
|
if (event.payload.event_type === extraction_1.EventType.ExtractionDataStart &&
|
|
20
40
|
!as.state.lastSyncStarted) {
|
|
21
41
|
as.state.lastSyncStarted = new Date().toISOString();
|
|
@@ -29,6 +49,7 @@ class State {
|
|
|
29
49
|
this.initialSdkState =
|
|
30
50
|
(0, helpers_1.getSyncDirection)({ event }) === extraction_1.SyncMode.LOADING
|
|
31
51
|
? {
|
|
52
|
+
snapInVersionId: '',
|
|
32
53
|
fromDevRev: {
|
|
33
54
|
filesToLoad: [],
|
|
34
55
|
},
|
|
@@ -36,6 +57,7 @@ class State {
|
|
|
36
57
|
: {
|
|
37
58
|
lastSyncStarted: '',
|
|
38
59
|
lastSuccessfulSyncStarted: '',
|
|
60
|
+
snapInVersionId: '',
|
|
39
61
|
toDevRev: {
|
|
40
62
|
attachmentsMetadata: {
|
|
41
63
|
artifactIds: [],
|
|
@@ -96,7 +118,7 @@ class State {
|
|
|
96
118
|
this.event.payload.event_context.sync_unit_id +
|
|
97
119
|
'.');
|
|
98
120
|
try {
|
|
99
|
-
const response = await axios_client_1.axiosClient.
|
|
121
|
+
const response = await axios_client_1.axiosClient.get(this.workerUrl + '.get', {
|
|
100
122
|
headers: {
|
|
101
123
|
Authorization: this.devrevToken,
|
|
102
124
|
},
|
|
@@ -10,7 +10,7 @@ function createEvent({ eventType, externalSyncUnits = [], progress, error, delay
|
|
|
10
10
|
return {
|
|
11
11
|
context: Object.assign({ secrets: {
|
|
12
12
|
service_account_token: 'test_token',
|
|
13
|
-
}, snap_in_version_id: 'test_snap_in_version_id' }, contextOverrides),
|
|
13
|
+
}, snap_in_version_id: 'test_snap_in_version_id', snap_in_id: 'test_snap_in_id' }, contextOverrides),
|
|
14
14
|
payload: Object.assign({ connection_data: {
|
|
15
15
|
org_id: 'test_org_id',
|
|
16
16
|
org_name: 'test_org_name',
|
package/dist/types/workers.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { State } from '../state/state';
|
|
|
3
3
|
import { WorkerAdapter } from '../workers/worker-adapter';
|
|
4
4
|
import { ExtractorEventType, AirdropEvent } from './extraction';
|
|
5
5
|
import { LoaderEventType } from './loading';
|
|
6
|
+
import { InitialDomainMapping } from './common';
|
|
6
7
|
/**
|
|
7
8
|
* WorkerAdapterInterface is an interface for WorkerAdapter class.
|
|
8
9
|
* @interface WorkerAdapterInterface
|
|
@@ -52,6 +53,7 @@ export interface SpawnInterface {
|
|
|
52
53
|
* @param {AirdropEvent} event - The event object received from the platform
|
|
53
54
|
* @param {object=} initialState - The initial state of the adapter
|
|
54
55
|
* @param {string} workerPath - The path to the worker file
|
|
56
|
+
* @param {string} initialDomainMapping - The initial domain mapping
|
|
55
57
|
* @param {WorkerAdapterOptions} options - The options to create a new instance of Spawn class
|
|
56
58
|
*/
|
|
57
59
|
export interface SpawnFactoryInterface<ConnectorState> {
|
|
@@ -59,6 +61,7 @@ export interface SpawnFactoryInterface<ConnectorState> {
|
|
|
59
61
|
initialState: ConnectorState;
|
|
60
62
|
workerPath?: string;
|
|
61
63
|
options?: WorkerAdapterOptions;
|
|
64
|
+
initialDomainMapping?: InitialDomainMapping;
|
|
62
65
|
}
|
|
63
66
|
/**
|
|
64
67
|
* TaskAdapterInterface is an interface for TaskAdapter class.
|
|
@@ -130,6 +133,7 @@ export interface WorkerData<ConnectorState> {
|
|
|
130
133
|
event: AirdropEvent;
|
|
131
134
|
initialState: ConnectorState;
|
|
132
135
|
workerPath: string;
|
|
136
|
+
initialDomainMapping?: InitialDomainMapping;
|
|
133
137
|
options?: WorkerAdapterOptions;
|
|
134
138
|
}
|
|
135
139
|
/**
|
|
@@ -11,11 +11,13 @@ function processTask({ task, onTimeout, }) {
|
|
|
11
11
|
void (async () => {
|
|
12
12
|
const event = node_worker_threads_1.workerData.event;
|
|
13
13
|
const initialState = node_worker_threads_1.workerData.initialState;
|
|
14
|
+
const initialDomainMapping = node_worker_threads_1.workerData.initialDomainMapping;
|
|
14
15
|
const options = node_worker_threads_1.workerData.options;
|
|
15
16
|
console = new logger_1.Logger({ event, options });
|
|
16
17
|
const adapterState = await (0, state_1.createAdapterState)({
|
|
17
18
|
event,
|
|
18
19
|
initialState,
|
|
20
|
+
initialDomainMapping,
|
|
19
21
|
options,
|
|
20
22
|
});
|
|
21
23
|
if (node_worker_threads_1.parentPort && node_worker_threads_1.workerData.event) {
|
package/dist/workers/spawn.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { SpawnFactoryInterface, SpawnInterface } from '../types/workers';
|
|
|
10
10
|
* @param {string} workerPath - The path to the worker file
|
|
11
11
|
* @returns {Promise<Spawn>} - A new instance of Spawn class
|
|
12
12
|
*/
|
|
13
|
-
export declare function spawn<ConnectorState>({ event, initialState, workerPath, options, }: SpawnFactoryInterface<ConnectorState>): Promise<void>;
|
|
13
|
+
export declare function spawn<ConnectorState>({ event, initialState, workerPath, initialDomainMapping, options, }: SpawnFactoryInterface<ConnectorState>): Promise<void>;
|
|
14
14
|
export declare class Spawn {
|
|
15
15
|
private event;
|
|
16
16
|
private alreadyEmitted;
|
package/dist/workers/spawn.js
CHANGED
|
@@ -71,7 +71,7 @@ function getWorkerPath({ event, connectorWorkerPath, }) {
|
|
|
71
71
|
* @param {string} workerPath - The path to the worker file
|
|
72
72
|
* @returns {Promise<Spawn>} - A new instance of Spawn class
|
|
73
73
|
*/
|
|
74
|
-
async function spawn({ event, initialState, workerPath, options, }) {
|
|
74
|
+
async function spawn({ event, initialState, workerPath, initialDomainMapping, options, }) {
|
|
75
75
|
const logger = new logger_1.Logger({ event, options });
|
|
76
76
|
const script = getWorkerPath({
|
|
77
77
|
event,
|
|
@@ -91,6 +91,7 @@ async function spawn({ event, initialState, workerPath, options, }) {
|
|
|
91
91
|
event,
|
|
92
92
|
initialState,
|
|
93
93
|
workerPath: script,
|
|
94
|
+
initialDomainMapping,
|
|
94
95
|
options,
|
|
95
96
|
});
|
|
96
97
|
return new Promise((resolve) => {
|
|
@@ -72,7 +72,7 @@ export declare class WorkerAdapter<ConnectorState> {
|
|
|
72
72
|
* Streams the attachments to the DevRev platform.
|
|
73
73
|
* The attachments are streamed to the platform and the artifact information is returned.
|
|
74
74
|
* @param {{ stream, processors }: { stream: ExternalSystemAttachmentStreamingFunction, processors?: ExternalSystemAttachmentProcessors }} Params - The parameters to stream the attachments
|
|
75
|
-
* @returns {Promise<StreamAttachmentsReturnType>} - The response object containing the
|
|
75
|
+
* @returns {Promise<StreamAttachmentsReturnType>} - The response object containing the ssorAttachment artifact information
|
|
76
76
|
* or error information if there was an error
|
|
77
77
|
*/
|
|
78
78
|
streamAttachments<NewBatch>({ stream, processors, }: {
|
|
@@ -117,7 +117,14 @@ class WorkerAdapter {
|
|
|
117
117
|
}
|
|
118
118
|
// We want to upload all the repos before emitting the event, except for the external sync units done event
|
|
119
119
|
if (newEventType !== extraction_1.ExtractorEventType.ExtractionExternalSyncUnitsDone) {
|
|
120
|
-
|
|
120
|
+
try {
|
|
121
|
+
await this.uploadAllRepos();
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
console.error('Error while uploading repos', error);
|
|
125
|
+
node_worker_threads_1.parentPort === null || node_worker_threads_1.parentPort === void 0 ? void 0 : node_worker_threads_1.parentPort.postMessage(workers_1.WorkerMessageSubject.WorkerMessageExit);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
121
128
|
}
|
|
122
129
|
// If the extraction is done, we want to save the timestamp of the last successful sync
|
|
123
130
|
if (newEventType === extraction_1.ExtractorEventType.ExtractionAttachmentsDone) {
|
|
@@ -164,7 +171,10 @@ class WorkerAdapter {
|
|
|
164
171
|
}
|
|
165
172
|
async uploadAllRepos() {
|
|
166
173
|
for (const repo of this.repos) {
|
|
167
|
-
await repo.upload();
|
|
174
|
+
const error = await repo.upload();
|
|
175
|
+
if (error) {
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
168
178
|
}
|
|
169
179
|
}
|
|
170
180
|
handleTimeout() {
|
|
@@ -501,7 +511,7 @@ class WorkerAdapter {
|
|
|
501
511
|
event: this.event,
|
|
502
512
|
});
|
|
503
513
|
if (error) {
|
|
504
|
-
console.warn('Error while streaming attachment', error
|
|
514
|
+
console.warn('Error while streaming attachment', error);
|
|
505
515
|
return { error };
|
|
506
516
|
}
|
|
507
517
|
else if (delay) {
|
|
@@ -573,27 +583,27 @@ class WorkerAdapter {
|
|
|
573
583
|
* Streams the attachments to the DevRev platform.
|
|
574
584
|
* The attachments are streamed to the platform and the artifact information is returned.
|
|
575
585
|
* @param {{ stream, processors }: { stream: ExternalSystemAttachmentStreamingFunction, processors?: ExternalSystemAttachmentProcessors }} Params - The parameters to stream the attachments
|
|
576
|
-
* @returns {Promise<StreamAttachmentsReturnType>} - The response object containing the
|
|
586
|
+
* @returns {Promise<StreamAttachmentsReturnType>} - The response object containing the ssorAttachment artifact information
|
|
577
587
|
* or error information if there was an error
|
|
578
588
|
*/
|
|
579
589
|
async streamAttachments({ stream, processors, }) {
|
|
580
|
-
var _a, _b
|
|
590
|
+
var _a, _b;
|
|
581
591
|
const repos = [
|
|
582
592
|
{
|
|
583
593
|
itemType: 'ssor_attachment',
|
|
584
594
|
},
|
|
585
595
|
];
|
|
586
596
|
this.initializeRepos(repos);
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
attachmentsMetadataArtifactIds.length === 0) {
|
|
597
|
+
if (!((_b = (_a = this.state.toDevRev) === null || _a === void 0 ? void 0 : _a.attachmentsMetadata) === null || _b === void 0 ? void 0 : _b.artifactIds) ||
|
|
598
|
+
this.state.toDevRev.attachmentsMetadata.artifactIds.length === 0) {
|
|
590
599
|
console.log(`No attachments metadata artifact IDs found in state.`);
|
|
591
600
|
return;
|
|
592
601
|
}
|
|
593
602
|
else {
|
|
594
|
-
console.log(`Found ${
|
|
603
|
+
console.log(`Found ${this.state.toDevRev.attachmentsMetadata.artifactIds.length} attachments metadata artifact IDs in state.`);
|
|
595
604
|
}
|
|
596
|
-
|
|
605
|
+
while (this.state.toDevRev.attachmentsMetadata.artifactIds.length > 0) {
|
|
606
|
+
const attachmentsMetadataArtifactId = this.state.toDevRev.attachmentsMetadata.artifactIds[0];
|
|
597
607
|
console.log(`Started processing attachments for attachments metadata artifact ID: ${attachmentsMetadataArtifactId}.`);
|
|
598
608
|
const { attachments, error } = await this.uploader.getAttachmentsFromArtifactId({
|
|
599
609
|
artifact: attachmentsMetadataArtifactId,
|
|
@@ -604,6 +614,9 @@ class WorkerAdapter {
|
|
|
604
614
|
}
|
|
605
615
|
if (!attachments || attachments.length === 0) {
|
|
606
616
|
console.warn(`No attachments found for artifact ID: ${attachmentsMetadataArtifactId}.`);
|
|
617
|
+
// Remove empty artifact and reset lastProcessed
|
|
618
|
+
this.state.toDevRev.attachmentsMetadata.artifactIds.shift();
|
|
619
|
+
this.state.toDevRev.attachmentsMetadata.lastProcessed = 0;
|
|
607
620
|
continue;
|
|
608
621
|
}
|
|
609
622
|
console.log(`Found ${attachments.length} attachments for artifact ID: ${attachmentsMetadataArtifactId}.`);
|
|
@@ -622,25 +635,24 @@ class WorkerAdapter {
|
|
|
622
635
|
}
|
|
623
636
|
else {
|
|
624
637
|
console.log(`Using default processors for attachments.`);
|
|
625
|
-
const
|
|
638
|
+
const startIndex = this.state.toDevRev.attachmentsMetadata.lastProcessed || 0;
|
|
639
|
+
const attachmentsToProcess = attachments.slice(startIndex);
|
|
626
640
|
for (const attachment of attachmentsToProcess) {
|
|
627
641
|
const response = await this.processAttachment(attachment, stream);
|
|
628
642
|
if (response === null || response === void 0 ? void 0 : response.delay) {
|
|
629
643
|
return response;
|
|
630
644
|
}
|
|
631
645
|
else if (response === null || response === void 0 ? void 0 : response.error) {
|
|
632
|
-
console.warn(
|
|
646
|
+
console.warn('Skipping attachment due to an error while processing', attachment);
|
|
633
647
|
}
|
|
634
648
|
if (this.state.toDevRev) {
|
|
635
649
|
this.state.toDevRev.attachmentsMetadata.lastProcessed += 1;
|
|
636
650
|
}
|
|
637
651
|
}
|
|
638
652
|
}
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
this.state.toDevRev.attachmentsMetadata.lastProcessed = 0;
|
|
643
|
-
}
|
|
653
|
+
console.log(`Finished processing all attachments for artifact ID: ${attachmentsMetadataArtifactId}.`);
|
|
654
|
+
this.state.toDevRev.attachmentsMetadata.artifactIds.shift();
|
|
655
|
+
this.state.toDevRev.attachmentsMetadata.lastProcessed = 0;
|
|
644
656
|
}
|
|
645
657
|
return;
|
|
646
658
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devrev/ts-adaas",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "DevRev ADaaS (AirDrop-as-a-Service) Typescript SDK.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"typescript": "^5.3.3"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@devrev/typescript-sdk": "^1.1.
|
|
40
|
+
"@devrev/typescript-sdk": "^1.1.54",
|
|
41
41
|
"axios": "^1.7.9",
|
|
42
42
|
"axios-retry": "^4.5.0",
|
|
43
43
|
"form-data": "^4.0.1",
|