@devrev/ts-adaas 1.8.1 → 1.9.0-beta.1
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/common/constants.d.ts +6 -1
- package/dist/common/constants.js +20 -9
- 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 +80 -66
- package/dist/state/state.test.d.ts +1 -0
- package/dist/state/state.test.js +223 -0
- package/dist/types/common.d.ts +11 -0
- package/dist/types/common.js +13 -1
- package/dist/types/extraction.d.ts +0 -9
- package/dist/types/extraction.js +1 -11
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.js +2 -2
- package/package.json +2 -2
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { EventType } from '../types/extraction';
|
|
2
|
-
export declare const STATELESS_EVENT_TYPES: EventType[];
|
|
3
2
|
export declare const ALLOWED_EXTRACTION_EVENT_TYPES: EventType[];
|
|
4
3
|
export declare const ALLOWED_LOADING_EVENT_TYPES: EventType[];
|
|
5
4
|
export declare const ALLOWED_EVENT_TYPES: EventType[];
|
|
5
|
+
export declare const STATELESS_EXTRACTION_EVENT_TYPES: EventType[];
|
|
6
|
+
export declare const STATELESS_LOADING_EVENT_TYPES: EventType[];
|
|
7
|
+
export declare const STATELESS_EVENT_TYPES: EventType[];
|
|
8
|
+
export declare const STATEFUL_EXTRACTION_EVENT_TYPES: EventType[];
|
|
9
|
+
export declare const STATEFUL_LOADING_EVENT_TYPES: EventType[];
|
|
10
|
+
export declare const STATEFUL_EVENT_TYPES: EventType[];
|
|
6
11
|
export declare const ARTIFACT_BATCH_SIZE = 2000;
|
|
7
12
|
export declare const MAX_DEVREV_ARTIFACT_SIZE = 262144000;
|
|
8
13
|
export declare const MAX_DEVREV_FILENAME_LENGTH = 256;
|
package/dist/common/constants.js
CHANGED
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DEFAULT_SLEEP_DELAY_MS = exports.HARD_TIMEOUT_MULTIPLIER = exports.DEFAULT_LAMBDA_TIMEOUT = exports.LIBRARY_VERSION = exports.AIRDROP_DEFAULT_ITEM_TYPES = exports.MAX_DEVREV_FILENAME_EXTENSION_LENGTH = exports.MAX_DEVREV_FILENAME_LENGTH = exports.MAX_DEVREV_ARTIFACT_SIZE = exports.ARTIFACT_BATCH_SIZE = exports.
|
|
3
|
+
exports.DEFAULT_SLEEP_DELAY_MS = exports.HARD_TIMEOUT_MULTIPLIER = exports.DEFAULT_LAMBDA_TIMEOUT = exports.LIBRARY_VERSION = exports.AIRDROP_DEFAULT_ITEM_TYPES = exports.MAX_DEVREV_FILENAME_EXTENSION_LENGTH = exports.MAX_DEVREV_FILENAME_LENGTH = exports.MAX_DEVREV_ARTIFACT_SIZE = exports.ARTIFACT_BATCH_SIZE = exports.STATEFUL_EVENT_TYPES = exports.STATEFUL_LOADING_EVENT_TYPES = exports.STATEFUL_EXTRACTION_EVENT_TYPES = exports.STATELESS_EVENT_TYPES = exports.STATELESS_LOADING_EVENT_TYPES = exports.STATELESS_EXTRACTION_EVENT_TYPES = exports.ALLOWED_EVENT_TYPES = exports.ALLOWED_LOADING_EVENT_TYPES = exports.ALLOWED_EXTRACTION_EVENT_TYPES = void 0;
|
|
4
4
|
const extraction_1 = require("../types/extraction");
|
|
5
5
|
const helpers_1 = require("./helpers");
|
|
6
|
-
exports.STATELESS_EVENT_TYPES = [
|
|
7
|
-
extraction_1.EventType.ExtractionExternalSyncUnitsStart,
|
|
8
|
-
extraction_1.EventType.ExtractionMetadataStart,
|
|
9
|
-
extraction_1.EventType.ExtractionDataDelete,
|
|
10
|
-
extraction_1.EventType.ExtractionAttachmentsDelete,
|
|
11
|
-
extraction_1.EventType.StartDeletingLoaderState,
|
|
12
|
-
extraction_1.EventType.StartDeletingLoaderAttachmentState,
|
|
13
|
-
];
|
|
14
6
|
exports.ALLOWED_EXTRACTION_EVENT_TYPES = [
|
|
15
7
|
extraction_1.EventType.ExtractionExternalSyncUnitsStart,
|
|
16
8
|
extraction_1.EventType.ExtractionMetadataStart,
|
|
@@ -31,6 +23,25 @@ exports.ALLOWED_EVENT_TYPES = [
|
|
|
31
23
|
...exports.ALLOWED_EXTRACTION_EVENT_TYPES,
|
|
32
24
|
...exports.ALLOWED_LOADING_EVENT_TYPES,
|
|
33
25
|
];
|
|
26
|
+
exports.STATELESS_EXTRACTION_EVENT_TYPES = [
|
|
27
|
+
extraction_1.EventType.ExtractionExternalSyncUnitsStart,
|
|
28
|
+
extraction_1.EventType.ExtractionDataDelete,
|
|
29
|
+
extraction_1.EventType.ExtractionAttachmentsDelete,
|
|
30
|
+
];
|
|
31
|
+
exports.STATELESS_LOADING_EVENT_TYPES = [
|
|
32
|
+
extraction_1.EventType.StartDeletingLoaderState,
|
|
33
|
+
extraction_1.EventType.StartDeletingLoaderAttachmentState,
|
|
34
|
+
];
|
|
35
|
+
exports.STATELESS_EVENT_TYPES = [
|
|
36
|
+
...exports.STATELESS_EXTRACTION_EVENT_TYPES,
|
|
37
|
+
...exports.STATELESS_LOADING_EVENT_TYPES,
|
|
38
|
+
];
|
|
39
|
+
exports.STATEFUL_EXTRACTION_EVENT_TYPES = exports.ALLOWED_EXTRACTION_EVENT_TYPES.filter((eventType) => !exports.STATELESS_EXTRACTION_EVENT_TYPES.includes(eventType));
|
|
40
|
+
exports.STATEFUL_LOADING_EVENT_TYPES = exports.ALLOWED_LOADING_EVENT_TYPES.filter((eventType) => !exports.STATELESS_LOADING_EVENT_TYPES.includes(eventType));
|
|
41
|
+
exports.STATEFUL_EVENT_TYPES = [
|
|
42
|
+
...exports.STATEFUL_EXTRACTION_EVENT_TYPES,
|
|
43
|
+
...exports.STATEFUL_LOADING_EVENT_TYPES,
|
|
44
|
+
];
|
|
34
45
|
exports.ARTIFACT_BATCH_SIZE = 2000;
|
|
35
46
|
exports.MAX_DEVREV_ARTIFACT_SIZE = 262144000; // 250MB
|
|
36
47
|
exports.MAX_DEVREV_FILENAME_LENGTH = 256;
|
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
|
+
};
|
package/dist/state/state.js
CHANGED
|
@@ -8,39 +8,44 @@ exports.createAdapterState = createAdapterState;
|
|
|
8
8
|
const axios_1 = __importDefault(require("axios"));
|
|
9
9
|
const axios_client_internal_1 = require("../http/axios-client-internal");
|
|
10
10
|
const extraction_1 = require("../types/extraction");
|
|
11
|
+
const common_1 = require("../types/common");
|
|
11
12
|
const constants_1 = require("../common/constants");
|
|
12
13
|
const logger_1 = require("../logger/logger");
|
|
13
14
|
const install_initial_domain_mapping_1 = require("../common/install-initial-domain-mapping");
|
|
14
15
|
const helpers_1 = require("../common/helpers");
|
|
16
|
+
const state_interfaces_1 = require("./state.interfaces");
|
|
15
17
|
async function createAdapterState({ event, initialState, initialDomainMapping, options, }) {
|
|
16
|
-
|
|
18
|
+
// Deep clone the initial state to avoid mutating the original state
|
|
19
|
+
const deepCloneInitialState = structuredClone(initialState);
|
|
17
20
|
const as = new State({
|
|
18
21
|
event,
|
|
19
|
-
initialState:
|
|
22
|
+
initialState: deepCloneInitialState,
|
|
20
23
|
initialDomainMapping,
|
|
21
24
|
options,
|
|
22
25
|
});
|
|
23
26
|
if (!constants_1.STATELESS_EVENT_TYPES.includes(event.payload.event_type)) {
|
|
24
|
-
await as.
|
|
27
|
+
await as.init(deepCloneInitialState);
|
|
25
28
|
// Check if IDM needs to be updated
|
|
26
29
|
const snapInVersionId = event.context.snap_in_version_id;
|
|
27
30
|
const hasSnapInVersionInState = 'snapInVersionId' in as.state;
|
|
28
31
|
const shouldUpdateIDM = !hasSnapInVersionInState || as.state.snapInVersionId !== snapInVersionId;
|
|
29
32
|
if (!shouldUpdateIDM) {
|
|
30
|
-
console.log(`Snap-in version in state matches the version in event context
|
|
33
|
+
console.log(`Snap-in version in state matches the version in event context "${snapInVersionId}". Skipping initial domain mapping installation.`);
|
|
31
34
|
}
|
|
32
35
|
else {
|
|
33
36
|
try {
|
|
37
|
+
console.log(`Snap-in version in state "${as.state.snapInVersionId}" does not match the version in event context "${snapInVersionId}". Installing initial domain mapping.`);
|
|
34
38
|
if (initialDomainMapping) {
|
|
35
39
|
await (0, install_initial_domain_mapping_1.installInitialDomainMapping)(event, initialDomainMapping);
|
|
36
40
|
as.state.snapInVersionId = snapInVersionId;
|
|
37
41
|
}
|
|
38
42
|
else {
|
|
39
|
-
|
|
43
|
+
throw new Error('No initial domain mapping was passed to spawn function. Skipping initial domain mapping installation.');
|
|
40
44
|
}
|
|
41
45
|
}
|
|
42
46
|
catch (error) {
|
|
43
47
|
console.error('Error while installing initial domain mapping.', (0, logger_1.serializeError)(error));
|
|
48
|
+
process.exit(1);
|
|
44
49
|
}
|
|
45
50
|
}
|
|
46
51
|
// Set lastSyncStarted if the event type is ExtractionDataStart
|
|
@@ -55,29 +60,14 @@ async function createAdapterState({ event, initialState, initialDomainMapping, o
|
|
|
55
60
|
class State {
|
|
56
61
|
constructor({ event, initialState }) {
|
|
57
62
|
this.initialSdkState =
|
|
58
|
-
(0, helpers_1.getSyncDirection)({ event }) ===
|
|
59
|
-
?
|
|
60
|
-
|
|
61
|
-
fromDevRev: {
|
|
62
|
-
filesToLoad: [],
|
|
63
|
-
},
|
|
64
|
-
}
|
|
65
|
-
: {
|
|
66
|
-
lastSyncStarted: '',
|
|
67
|
-
lastSuccessfulSyncStarted: '',
|
|
68
|
-
snapInVersionId: '',
|
|
69
|
-
toDevRev: {
|
|
70
|
-
attachmentsMetadata: {
|
|
71
|
-
artifactIds: [],
|
|
72
|
-
lastProcessed: 0,
|
|
73
|
-
lastProcessedAttachmentsIdsList: [],
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
};
|
|
63
|
+
(0, helpers_1.getSyncDirection)({ event }) === common_1.SyncMode.LOADING
|
|
64
|
+
? state_interfaces_1.loadingSdkState
|
|
65
|
+
: state_interfaces_1.extractionSdkState;
|
|
77
66
|
this._state = Object.assign(Object.assign({}, initialState), this.initialSdkState);
|
|
78
|
-
this.event = event;
|
|
79
67
|
this.workerUrl = event.payload.event_context.worker_data_url;
|
|
80
68
|
this.devrevToken = event.context.secrets.service_account_token;
|
|
69
|
+
this.syncUnitId = event.payload.event_context.sync_unit_id;
|
|
70
|
+
this.requestId = event.payload.event_context.request_id_adaas;
|
|
81
71
|
}
|
|
82
72
|
get state() {
|
|
83
73
|
return this._state;
|
|
@@ -86,24 +76,67 @@ class State {
|
|
|
86
76
|
this._state = value;
|
|
87
77
|
}
|
|
88
78
|
/**
|
|
89
|
-
*
|
|
90
|
-
*
|
|
79
|
+
* Initializes the state for this adapter instance by fetching from API
|
|
80
|
+
* or creating an initial state if none exists (404).
|
|
81
|
+
* @param initialState The initial connector state provided by the spawn function
|
|
82
|
+
*/
|
|
83
|
+
async init(initialState) {
|
|
84
|
+
var _a;
|
|
85
|
+
try {
|
|
86
|
+
const stringifiedState = await this.fetchState();
|
|
87
|
+
if (!stringifiedState) {
|
|
88
|
+
throw new Error('No state found in response.');
|
|
89
|
+
}
|
|
90
|
+
let parsedState;
|
|
91
|
+
try {
|
|
92
|
+
parsedState = JSON.parse(stringifiedState);
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
throw new Error('Failed to parse state.');
|
|
96
|
+
}
|
|
97
|
+
this.state = parsedState;
|
|
98
|
+
console.log('State fetched successfully. Current state', (0, logger_1.getPrintableState)(this.state));
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
if (axios_1.default.isAxiosError(error) && ((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 404) {
|
|
102
|
+
console.log('State not found. Initializing state with initial state.');
|
|
103
|
+
const initialAdapterState = Object.assign(Object.assign({}, initialState), this.initialSdkState);
|
|
104
|
+
this.state = initialAdapterState;
|
|
105
|
+
await this.postState(initialAdapterState);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
console.error('Failed to init state.', (0, logger_1.serializeError)(error));
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Updates the state of the adapter by posting to API.
|
|
91
115
|
* @param {object} state - The state to be updated
|
|
92
116
|
*/
|
|
93
117
|
async postState(state) {
|
|
118
|
+
const url = this.workerUrl + '.update';
|
|
119
|
+
this.state = state || this.state;
|
|
120
|
+
let stringifiedState;
|
|
94
121
|
try {
|
|
95
|
-
|
|
96
|
-
|
|
122
|
+
stringifiedState = JSON.stringify(this.state);
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
console.error('Failed to stringify state.', (0, logger_1.serializeError)(error));
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
await axios_client_internal_1.axiosClient.post(url, {
|
|
130
|
+
state: stringifiedState,
|
|
97
131
|
}, {
|
|
98
132
|
headers: {
|
|
99
133
|
Authorization: this.devrevToken,
|
|
100
134
|
},
|
|
101
135
|
params: {
|
|
102
|
-
sync_unit: this.
|
|
103
|
-
request_id: this.
|
|
136
|
+
sync_unit: this.syncUnitId,
|
|
137
|
+
request_id: this.requestId,
|
|
104
138
|
},
|
|
105
139
|
});
|
|
106
|
-
this.state = state || this.state;
|
|
107
140
|
console.log('State updated successfully to', (0, logger_1.getPrintableState)(this.state));
|
|
108
141
|
}
|
|
109
142
|
catch (error) {
|
|
@@ -112,42 +145,23 @@ class State {
|
|
|
112
145
|
}
|
|
113
146
|
}
|
|
114
147
|
/**
|
|
115
|
-
* Fetches the state of the adapter.
|
|
116
|
-
*
|
|
117
|
-
* @return The state of the adapter
|
|
148
|
+
* Fetches the state of the adapter from API.
|
|
149
|
+
* @return The raw state data from API
|
|
118
150
|
*/
|
|
119
|
-
async fetchState(
|
|
151
|
+
async fetchState() {
|
|
120
152
|
var _a;
|
|
121
|
-
console.log(
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
});
|
|
134
|
-
this.state = JSON.parse(response.data.state);
|
|
135
|
-
console.log('State fetched successfully. Current state', (0, logger_1.getPrintableState)(this.state));
|
|
136
|
-
return this.state;
|
|
137
|
-
}
|
|
138
|
-
catch (error) {
|
|
139
|
-
if (axios_1.default.isAxiosError(error) && ((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 404) {
|
|
140
|
-
const state = Object.assign(Object.assign({}, initialState), this.initialSdkState);
|
|
141
|
-
this.state = state;
|
|
142
|
-
console.log('State not found, returning initial state. Current state', (0, logger_1.getPrintableState)(this.state));
|
|
143
|
-
await this.postState(this.state);
|
|
144
|
-
return this.state;
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
console.error('Failed to fetch state.', error);
|
|
148
|
-
process.exit(1);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
153
|
+
console.log(`Fetching state with sync unit id ${this.syncUnitId} and request id ${this.requestId}.`);
|
|
154
|
+
const url = this.workerUrl + '.get';
|
|
155
|
+
const response = await axios_client_internal_1.axiosClient.get(url, {
|
|
156
|
+
headers: {
|
|
157
|
+
Authorization: this.devrevToken,
|
|
158
|
+
},
|
|
159
|
+
params: {
|
|
160
|
+
sync_unit: this.syncUnitId,
|
|
161
|
+
request_id: this.requestId,
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
return (_a = response.data) === null || _a === void 0 ? void 0 : _a.state;
|
|
151
165
|
}
|
|
152
166
|
}
|
|
153
167
|
exports.State = State;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const state_1 = require("./state");
|
|
4
|
+
const extraction_1 = require("../types/extraction");
|
|
5
|
+
const test_helpers_1 = require("../tests/test-helpers");
|
|
6
|
+
const constants_1 = require("../common/constants");
|
|
7
|
+
const state_interfaces_1 = require("./state.interfaces");
|
|
8
|
+
describe(state_1.State.name, () => {
|
|
9
|
+
let initSpy;
|
|
10
|
+
let postStateSpy;
|
|
11
|
+
let fetchStateSpy;
|
|
12
|
+
let installInitialDomainMappingSpy;
|
|
13
|
+
let processExitSpy;
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
jest.clearAllMocks();
|
|
16
|
+
jest.restoreAllMocks();
|
|
17
|
+
initSpy = jest.spyOn(state_1.State.prototype, 'init');
|
|
18
|
+
postStateSpy = jest.spyOn(state_1.State.prototype, 'postState');
|
|
19
|
+
fetchStateSpy = jest.spyOn(state_1.State.prototype, 'fetchState');
|
|
20
|
+
installInitialDomainMappingSpy = jest.spyOn(require('../common/install-initial-domain-mapping'), 'installInitialDomainMapping');
|
|
21
|
+
processExitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {
|
|
22
|
+
throw new Error('process.exit called');
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
it.each(constants_1.STATELESS_EVENT_TYPES)('should not init, fetch, post or install IDM for stateless event type %s', async (eventType) => {
|
|
26
|
+
// Arrange
|
|
27
|
+
const event = (0, test_helpers_1.createEvent)({
|
|
28
|
+
eventType: eventType,
|
|
29
|
+
});
|
|
30
|
+
// Act
|
|
31
|
+
await (0, state_1.createAdapterState)({
|
|
32
|
+
event,
|
|
33
|
+
initialState: {},
|
|
34
|
+
initialDomainMapping: {},
|
|
35
|
+
});
|
|
36
|
+
// Assert
|
|
37
|
+
expect(initSpy).not.toHaveBeenCalled();
|
|
38
|
+
expect(fetchStateSpy).not.toHaveBeenCalled();
|
|
39
|
+
expect(postStateSpy).not.toHaveBeenCalled();
|
|
40
|
+
expect(installInitialDomainMappingSpy).not.toHaveBeenCalled();
|
|
41
|
+
});
|
|
42
|
+
it.each(constants_1.STATEFUL_EVENT_TYPES)('should exit the process if fetching the state fails', async (eventType) => {
|
|
43
|
+
// Arrange
|
|
44
|
+
const event = (0, test_helpers_1.createEvent)({
|
|
45
|
+
eventType: eventType,
|
|
46
|
+
});
|
|
47
|
+
fetchStateSpy.mockRejectedValue({
|
|
48
|
+
isAxiosError: true,
|
|
49
|
+
response: { status: 500 },
|
|
50
|
+
});
|
|
51
|
+
jest.spyOn(console, 'error').mockImplementation(() => { });
|
|
52
|
+
// Act & Assert
|
|
53
|
+
await expect((0, state_1.createAdapterState)({
|
|
54
|
+
event,
|
|
55
|
+
initialState: {},
|
|
56
|
+
initialDomainMapping: {},
|
|
57
|
+
})).rejects.toThrow('process.exit called');
|
|
58
|
+
expect(processExitSpy).toHaveBeenCalledWith(1);
|
|
59
|
+
});
|
|
60
|
+
it.each(constants_1.STATEFUL_EVENT_TYPES)('should exit the process if parsing the state fails', async (eventType) => {
|
|
61
|
+
// Arrange
|
|
62
|
+
const event = (0, test_helpers_1.createEvent)({
|
|
63
|
+
eventType: eventType,
|
|
64
|
+
});
|
|
65
|
+
fetchStateSpy.mockResolvedValue('invalid-json');
|
|
66
|
+
jest.spyOn(console, 'error').mockImplementation(() => { });
|
|
67
|
+
// Act & Assert
|
|
68
|
+
await expect((0, state_1.createAdapterState)({
|
|
69
|
+
event,
|
|
70
|
+
initialState: {},
|
|
71
|
+
initialDomainMapping: {},
|
|
72
|
+
})).rejects.toThrow('process.exit called');
|
|
73
|
+
expect(processExitSpy).toHaveBeenCalledWith(1);
|
|
74
|
+
});
|
|
75
|
+
it.each(constants_1.STATEFUL_EVENT_TYPES)('should exit the process if fetching is successful but there is no state in the response', async (eventType) => {
|
|
76
|
+
// Arrange
|
|
77
|
+
const event = (0, test_helpers_1.createEvent)({
|
|
78
|
+
eventType: eventType,
|
|
79
|
+
});
|
|
80
|
+
fetchStateSpy.mockResolvedValue(null);
|
|
81
|
+
jest.spyOn(console, 'error').mockImplementation(() => { });
|
|
82
|
+
// Act & Assert
|
|
83
|
+
await expect((0, state_1.createAdapterState)({
|
|
84
|
+
event,
|
|
85
|
+
initialState: {},
|
|
86
|
+
initialDomainMapping: {},
|
|
87
|
+
})).rejects.toThrow('process.exit called');
|
|
88
|
+
expect(processExitSpy).toHaveBeenCalledWith(1);
|
|
89
|
+
});
|
|
90
|
+
it.each(constants_1.STATEFUL_EVENT_TYPES.filter((eventType) => eventType !== extraction_1.EventType.ExtractionDataStart))('should call post state with full adapter state if fetching returns 404 for event type %s', async (eventType) => {
|
|
91
|
+
// Arrange
|
|
92
|
+
const initialState = {
|
|
93
|
+
test: 'test',
|
|
94
|
+
};
|
|
95
|
+
const event = (0, test_helpers_1.createEvent)({
|
|
96
|
+
eventType: eventType,
|
|
97
|
+
contextOverrides: {
|
|
98
|
+
snap_in_version_id: '',
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
fetchStateSpy.mockRejectedValue({
|
|
102
|
+
isAxiosError: true,
|
|
103
|
+
response: { status: 404 },
|
|
104
|
+
});
|
|
105
|
+
installInitialDomainMappingSpy.mockResolvedValue({
|
|
106
|
+
success: true,
|
|
107
|
+
});
|
|
108
|
+
postStateSpy.mockResolvedValue({
|
|
109
|
+
success: true,
|
|
110
|
+
});
|
|
111
|
+
jest.spyOn(console, 'log').mockImplementation(() => { });
|
|
112
|
+
// Act
|
|
113
|
+
await (0, state_1.createAdapterState)({
|
|
114
|
+
event,
|
|
115
|
+
initialState,
|
|
116
|
+
initialDomainMapping: {},
|
|
117
|
+
});
|
|
118
|
+
const expectedState = Object.assign(Object.assign({}, initialState), state_interfaces_1.extractionSdkState);
|
|
119
|
+
expect(postStateSpy).toHaveBeenCalledWith(expectedState);
|
|
120
|
+
});
|
|
121
|
+
it(extraction_1.EventType.ExtractionDataStart, async () => {
|
|
122
|
+
// Arrange
|
|
123
|
+
const initialState = {
|
|
124
|
+
test: 'test',
|
|
125
|
+
};
|
|
126
|
+
const event = (0, test_helpers_1.createEvent)({
|
|
127
|
+
eventType: extraction_1.EventType.ExtractionDataStart,
|
|
128
|
+
contextOverrides: {
|
|
129
|
+
snap_in_version_id: '',
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
fetchStateSpy.mockRejectedValue({
|
|
133
|
+
isAxiosError: true,
|
|
134
|
+
response: { status: 404 },
|
|
135
|
+
});
|
|
136
|
+
installInitialDomainMappingSpy.mockResolvedValue({
|
|
137
|
+
success: true,
|
|
138
|
+
});
|
|
139
|
+
postStateSpy.mockResolvedValue({
|
|
140
|
+
success: true,
|
|
141
|
+
});
|
|
142
|
+
jest.spyOn(console, 'log').mockImplementation(() => { });
|
|
143
|
+
// Act
|
|
144
|
+
await (0, state_1.createAdapterState)({
|
|
145
|
+
event,
|
|
146
|
+
initialState,
|
|
147
|
+
initialDomainMapping: {},
|
|
148
|
+
});
|
|
149
|
+
// Assert
|
|
150
|
+
// Verify that post state is called with object that contains
|
|
151
|
+
// lastSyncStarted which is not empty string
|
|
152
|
+
expect(postStateSpy).toHaveBeenCalledWith(expect.objectContaining({
|
|
153
|
+
lastSyncStarted: expect.not.stringMatching(/^$/),
|
|
154
|
+
}));
|
|
155
|
+
});
|
|
156
|
+
it.each(constants_1.STATEFUL_EVENT_TYPES)('should exit the process if initialDomainMapping is not provided for event type %s', async (eventType) => {
|
|
157
|
+
// Arrange
|
|
158
|
+
const event = (0, test_helpers_1.createEvent)({
|
|
159
|
+
eventType: eventType,
|
|
160
|
+
});
|
|
161
|
+
fetchStateSpy.mockResolvedValue(JSON.stringify({
|
|
162
|
+
test: 'test',
|
|
163
|
+
}));
|
|
164
|
+
jest.spyOn(console, 'log').mockImplementation(() => { });
|
|
165
|
+
jest.spyOn(console, 'error').mockImplementation(() => { });
|
|
166
|
+
// Act & Assert
|
|
167
|
+
await expect((0, state_1.createAdapterState)({
|
|
168
|
+
event,
|
|
169
|
+
initialState: {},
|
|
170
|
+
initialDomainMapping: undefined,
|
|
171
|
+
})).rejects.toThrow('process.exit called');
|
|
172
|
+
expect(processExitSpy).toHaveBeenCalledWith(1);
|
|
173
|
+
});
|
|
174
|
+
it.each(constants_1.STATEFUL_EVENT_TYPES)('should not install IDM if version matches for event type %s', async (eventType) => {
|
|
175
|
+
// Arrange
|
|
176
|
+
const event = (0, test_helpers_1.createEvent)({
|
|
177
|
+
eventType: eventType,
|
|
178
|
+
contextOverrides: {
|
|
179
|
+
snap_in_version_id: '1.0.0',
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
const stringifiedState = JSON.stringify({
|
|
183
|
+
test: 'test',
|
|
184
|
+
snapInVersionId: '1.0.0',
|
|
185
|
+
});
|
|
186
|
+
fetchStateSpy.mockResolvedValue(stringifiedState);
|
|
187
|
+
jest.spyOn(console, 'log').mockImplementation(() => { });
|
|
188
|
+
// Act & Assert
|
|
189
|
+
await (0, state_1.createAdapterState)({
|
|
190
|
+
event,
|
|
191
|
+
initialState: {},
|
|
192
|
+
initialDomainMapping: {},
|
|
193
|
+
});
|
|
194
|
+
// Assert
|
|
195
|
+
expect(installInitialDomainMappingSpy).not.toHaveBeenCalled();
|
|
196
|
+
});
|
|
197
|
+
it.each(constants_1.STATEFUL_EVENT_TYPES)('should install IDM if version does not match for event type %s', async (eventType) => {
|
|
198
|
+
// Arrange
|
|
199
|
+
const event = (0, test_helpers_1.createEvent)({
|
|
200
|
+
eventType: eventType,
|
|
201
|
+
contextOverrides: {
|
|
202
|
+
snap_in_version_id: '2.0.0',
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
const stringifiedState = JSON.stringify({
|
|
206
|
+
test: 'test',
|
|
207
|
+
snapInVersionId: '1.0.0',
|
|
208
|
+
});
|
|
209
|
+
fetchStateSpy.mockResolvedValue(stringifiedState);
|
|
210
|
+
installInitialDomainMappingSpy.mockResolvedValue({
|
|
211
|
+
success: true,
|
|
212
|
+
});
|
|
213
|
+
jest.spyOn(console, 'log').mockImplementation(() => { });
|
|
214
|
+
// Act
|
|
215
|
+
await (0, state_1.createAdapterState)({
|
|
216
|
+
event,
|
|
217
|
+
initialState: {},
|
|
218
|
+
initialDomainMapping: {},
|
|
219
|
+
});
|
|
220
|
+
// Assert
|
|
221
|
+
expect(installInitialDomainMappingSpy).toHaveBeenCalled();
|
|
222
|
+
});
|
|
223
|
+
});
|
package/dist/types/common.d.ts
CHANGED
|
@@ -36,3 +36,14 @@ export interface InitialDomainMapping {
|
|
|
36
36
|
starting_recipe_blueprint?: object;
|
|
37
37
|
additional_mappings?: object;
|
|
38
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* SyncMode is an enum that defines the different modes of sync that can be used by the external extractor.
|
|
41
|
+
* It can be either INITIAL, INCREMENTAL or LOADING. INITIAL mode is used for
|
|
42
|
+
* the first/initial import, while INCREMENTAL mode is used for doing syncs. LOADING mode is used for
|
|
43
|
+
* loading data from DevRev to the external system.
|
|
44
|
+
*/
|
|
45
|
+
export declare enum SyncMode {
|
|
46
|
+
INITIAL = "INITIAL",
|
|
47
|
+
INCREMENTAL = "INCREMENTAL",
|
|
48
|
+
LOADING = "LOADING"
|
|
49
|
+
}
|
package/dist/types/common.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ErrorLevel = void 0;
|
|
3
|
+
exports.SyncMode = exports.ErrorLevel = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* ErrorLevel is an enum that represents the level of an error.
|
|
6
6
|
* @deprecated
|
|
@@ -11,3 +11,15 @@ var ErrorLevel;
|
|
|
11
11
|
ErrorLevel["Error"] = "ERROR";
|
|
12
12
|
ErrorLevel["Info"] = "INFO";
|
|
13
13
|
})(ErrorLevel || (exports.ErrorLevel = ErrorLevel = {}));
|
|
14
|
+
/**
|
|
15
|
+
* SyncMode is an enum that defines the different modes of sync that can be used by the external extractor.
|
|
16
|
+
* It can be either INITIAL, INCREMENTAL or LOADING. INITIAL mode is used for
|
|
17
|
+
* the first/initial import, while INCREMENTAL mode is used for doing syncs. LOADING mode is used for
|
|
18
|
+
* loading data from DevRev to the external system.
|
|
19
|
+
*/
|
|
20
|
+
var SyncMode;
|
|
21
|
+
(function (SyncMode) {
|
|
22
|
+
SyncMode["INITIAL"] = "INITIAL";
|
|
23
|
+
SyncMode["INCREMENTAL"] = "INCREMENTAL";
|
|
24
|
+
SyncMode["LOADING"] = "LOADING";
|
|
25
|
+
})(SyncMode || (exports.SyncMode = SyncMode = {}));
|
|
@@ -57,15 +57,6 @@ export declare enum ExtractionMode {
|
|
|
57
57
|
INITIAL = "INITIAL",
|
|
58
58
|
INCREMENTAL = "INCREMENTAL"
|
|
59
59
|
}
|
|
60
|
-
/**
|
|
61
|
-
* ExtractionMode is an enum that defines the different modes of extraction that can be used by the external extractor.
|
|
62
|
-
* It can be either INITIAL or INCREMENTAL. INITIAL mode is used for the first/initial import, while INCREMENTAL mode is used for doing syncs.
|
|
63
|
-
*/
|
|
64
|
-
export declare enum SyncMode {
|
|
65
|
-
INITIAL = "INITIAL",
|
|
66
|
-
INCREMENTAL = "INCREMENTAL",
|
|
67
|
-
LOADING = "LOADING"
|
|
68
|
-
}
|
|
69
60
|
/**
|
|
70
61
|
* ExternalSyncUnit is an interface that defines the structure of an external sync unit (repos, projects, ...) that can be extracted.
|
|
71
62
|
* It must contain an ID, a name, and a description. It can also contain the number of items in the external sync unit.
|
package/dist/types/extraction.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.InitialSyncScope = exports.
|
|
3
|
+
exports.InitialSyncScope = exports.ExtractionMode = exports.ExtractorEventType = exports.EventType = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* EventType is an enum that defines the different types of events that can be sent to the external extractor from ADaaS.
|
|
6
6
|
* The external extractor can use these events to know what to do next in the extraction process.
|
|
@@ -60,16 +60,6 @@ var ExtractionMode;
|
|
|
60
60
|
ExtractionMode["INITIAL"] = "INITIAL";
|
|
61
61
|
ExtractionMode["INCREMENTAL"] = "INCREMENTAL";
|
|
62
62
|
})(ExtractionMode || (exports.ExtractionMode = ExtractionMode = {}));
|
|
63
|
-
/**
|
|
64
|
-
* ExtractionMode is an enum that defines the different modes of extraction that can be used by the external extractor.
|
|
65
|
-
* It can be either INITIAL or INCREMENTAL. INITIAL mode is used for the first/initial import, while INCREMENTAL mode is used for doing syncs.
|
|
66
|
-
*/
|
|
67
|
-
var SyncMode;
|
|
68
|
-
(function (SyncMode) {
|
|
69
|
-
SyncMode["INITIAL"] = "INITIAL";
|
|
70
|
-
SyncMode["INCREMENTAL"] = "INCREMENTAL";
|
|
71
|
-
SyncMode["LOADING"] = "LOADING";
|
|
72
|
-
})(SyncMode || (exports.SyncMode = SyncMode = {}));
|
|
73
63
|
/**
|
|
74
64
|
* InitialSyncScope is an enum that defines the different scopes of initial sync that can be used by the external extractor.
|
|
75
65
|
*/
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { ErrorLevel, ErrorRecord, LogRecord, AdapterUpdateParams, InitialDomainMapping, } from './common';
|
|
2
|
-
export { EventType, ExtractorEventType, ExtractionMode, ExternalSyncUnit, EventContextIn, EventContextOut, ConnectionData, EventData, DomainObjectState, AirdropEvent, AirdropMessage, ExtractorEvent,
|
|
1
|
+
export { ErrorLevel, ErrorRecord, LogRecord, AdapterUpdateParams, InitialDomainMapping, SyncMode, } from './common';
|
|
2
|
+
export { EventType, ExtractorEventType, ExtractionMode, ExternalSyncUnit, EventContextIn, EventContextOut, ConnectionData, EventData, DomainObjectState, AirdropEvent, AirdropMessage, ExtractorEvent, ExternalSystemAttachmentStreamingParams, ExternalSystemAttachmentStreamingResponse, ExternalSystemAttachmentStreamingFunction, ExternalProcessAttachmentFunction, ExternalSystemAttachmentReducerFunction, ExternalSystemAttachmentIteratorFunction, ProcessAttachmentReturnType, } from './extraction';
|
|
3
3
|
export { LoaderEventType, ExternalSystemItem, ExternalSystemItemLoadingResponse, ExternalSystemItemLoadingParams, ExternalSystemAttachment, } from './loading';
|
|
4
4
|
export { NormalizedItem, NormalizedAttachment, RepoInterface, } from '../repo/repo.interfaces';
|
|
5
5
|
export { AdapterState } from '../state/state.interfaces';
|
package/dist/types/index.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LoaderEventType = exports.
|
|
3
|
+
exports.LoaderEventType = exports.ExtractionMode = exports.ExtractorEventType = exports.EventType = exports.SyncMode = exports.ErrorLevel = void 0;
|
|
4
4
|
// Common
|
|
5
5
|
var common_1 = require("./common");
|
|
6
6
|
Object.defineProperty(exports, "ErrorLevel", { enumerable: true, get: function () { return common_1.ErrorLevel; } });
|
|
7
|
+
Object.defineProperty(exports, "SyncMode", { enumerable: true, get: function () { return common_1.SyncMode; } });
|
|
7
8
|
// Extraction
|
|
8
9
|
var extraction_1 = require("./extraction");
|
|
9
10
|
Object.defineProperty(exports, "EventType", { enumerable: true, get: function () { return extraction_1.EventType; } });
|
|
10
11
|
Object.defineProperty(exports, "ExtractorEventType", { enumerable: true, get: function () { return extraction_1.ExtractorEventType; } });
|
|
11
12
|
Object.defineProperty(exports, "ExtractionMode", { enumerable: true, get: function () { return extraction_1.ExtractionMode; } });
|
|
12
|
-
Object.defineProperty(exports, "SyncMode", { enumerable: true, get: function () { return extraction_1.SyncMode; } });
|
|
13
13
|
// Loading
|
|
14
14
|
var loading_1 = require("./loading");
|
|
15
15
|
Object.defineProperty(exports, "LoaderEventType", { enumerable: true, get: function () { return loading_1.LoaderEventType; } });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devrev/ts-adaas",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0-beta.1",
|
|
4
4
|
"description": "Typescript library containing the ADaaS(AirDrop as a Service) control protocol.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"start": "ts-node src/index.ts",
|
|
12
12
|
"lint": "eslint .",
|
|
13
13
|
"lint:fix": "eslint . --fix",
|
|
14
|
-
"test": "jest --forceExit --coverage --runInBand
|
|
14
|
+
"test": "jest --forceExit --coverage --runInBand"
|
|
15
15
|
},
|
|
16
16
|
"repository": {
|
|
17
17
|
"type": "git",
|