@devrev/ts-adaas 1.1.3 → 1.1.5
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 +45 -35
- package/dist/common/control-protocol.js +1 -1
- package/dist/common/install-initial-domain-mapping.js +3 -3
- package/dist/http/axios-client.js +4 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/dist/logger/logger.d.ts +20 -1
- package/dist/logger/logger.js +38 -12
- package/dist/logger/logger.test.js +15 -8
- package/dist/repo/repo.interfaces.d.ts +1 -0
- package/dist/state/state.interfaces.js +0 -1
- package/dist/state/state.js +1 -1
- package/dist/types/extraction.d.ts +18 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/uploader/uploader.d.ts +14 -15
- package/dist/uploader/uploader.js +8 -89
- package/dist/workers/create-worker.js +1 -1
- package/dist/workers/default-workers/attachments-extraction.js +33 -32
- package/dist/workers/worker-adapter.d.ts +25 -1
- package/dist/workers/worker-adapter.js +85 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,67 +2,77 @@
|
|
|
2
2
|
|
|
3
3
|
## Release Notes
|
|
4
4
|
|
|
5
|
+
### v1.1.5
|
|
6
|
+
|
|
7
|
+
- Increase `delayFactor` and number of retries for the exponential backoff retry mechanism for HTTP requests.
|
|
8
|
+
- Provide an inject function for streaming attachments.
|
|
9
|
+
- Fix the attachments streaming bug.
|
|
10
|
+
|
|
11
|
+
### v1.1.4
|
|
12
|
+
|
|
13
|
+
- Provide log lines and stack traces for runtime worker errors.
|
|
14
|
+
|
|
5
15
|
### v1.1.3
|
|
6
16
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
17
|
+
- Export `axios` and `axiosClient` with the exponential backoff retry mechanism for HTTP requests and omit Authorization headers from Axios errors.
|
|
18
|
+
- Resolve circular structure logging issues.
|
|
19
|
+
- Fix the attachments metadata normalization bug.
|
|
20
|
+
- Improve repository logging.
|
|
11
21
|
|
|
12
|
-
|
|
22
|
+
### v1.1.2
|
|
13
23
|
|
|
14
|
-
-
|
|
15
|
-
-
|
|
24
|
+
- Unify incoming and outgoing event context.
|
|
25
|
+
- Add `dev_oid` to logger tags.
|
|
16
26
|
|
|
17
|
-
|
|
27
|
+
### v1.1.1
|
|
18
28
|
|
|
19
|
-
-
|
|
29
|
+
- Add default workers for loading deletion events.
|
|
20
30
|
|
|
21
|
-
|
|
31
|
+
### v1.1.0
|
|
22
32
|
|
|
23
|
-
- Support
|
|
33
|
+
- Support sync from DevRev to the external system. (Known limitations: no support for loading attachments.)
|
|
24
34
|
|
|
25
|
-
|
|
35
|
+
### v1.0.4
|
|
26
36
|
|
|
27
37
|
- Fix logging from worker threads.
|
|
28
38
|
|
|
29
|
-
|
|
39
|
+
### v1.0.3
|
|
30
40
|
|
|
31
|
-
-
|
|
41
|
+
- Add release notes.
|
|
32
42
|
|
|
33
|
-
|
|
43
|
+
### v1.0.2
|
|
34
44
|
|
|
35
|
-
-
|
|
45
|
+
- Fix bugs and improve local development.
|
|
36
46
|
- Expose `formatAxiosError` function for error handling.
|
|
37
47
|
|
|
38
|
-
|
|
48
|
+
### v1.0.1
|
|
39
49
|
|
|
40
|
-
-
|
|
50
|
+
- Fix bugs and improve logging.
|
|
41
51
|
|
|
42
|
-
|
|
52
|
+
### v1.0.0
|
|
43
53
|
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
54
|
+
- Enable extractions to use the full lambda runtime and gracefully handle execution context timeout.
|
|
55
|
+
- Simplify metadata and data normalization and uploading with the repo implementation.
|
|
56
|
+
- Provide default handling of the attachment extraction phase in the ADaaS SDK library.
|
|
57
|
+
- Reduce file size and streamline processes with gzip compression.
|
|
58
|
+
- Fix bugs and improve error handling.
|
|
49
59
|
|
|
50
|
-
|
|
60
|
+
### v0.0.3
|
|
51
61
|
|
|
52
|
-
- Support
|
|
62
|
+
- Support new recipe management.
|
|
53
63
|
|
|
54
|
-
|
|
64
|
+
### v0.0.2
|
|
55
65
|
|
|
56
|
-
- Support
|
|
57
|
-
- HTTP client for API requests
|
|
58
|
-
-
|
|
59
|
-
-
|
|
66
|
+
- Support the State API.
|
|
67
|
+
- Provide an HTTP client for API requests.
|
|
68
|
+
- Create local artifact files in the local development environment.
|
|
69
|
+
- Improve logging.
|
|
60
70
|
|
|
61
|
-
|
|
71
|
+
### v0.0.1
|
|
62
72
|
|
|
63
|
-
-
|
|
64
|
-
-
|
|
65
|
-
-
|
|
73
|
+
- Implement a demo of the ADaaS snap-in.
|
|
74
|
+
- Add an adapter for the ADaaS control protocol with helper functions.
|
|
75
|
+
- Provide an uploader for uploading artifacts.
|
|
66
76
|
|
|
67
77
|
# Overview
|
|
68
78
|
|
|
@@ -23,7 +23,7 @@ const emit = async ({ event, eventType, data, }) => {
|
|
|
23
23
|
}
|
|
24
24
|
catch (error) {
|
|
25
25
|
if (axios_client_1.axios.isAxiosError(error)) {
|
|
26
|
-
console.error(`Failed to emit event with event type ${eventType}.`, (0, logger_1.
|
|
26
|
+
console.error(`Failed to emit event with event type ${eventType}.`, (0, logger_1.serializeAxiosError)(error));
|
|
27
27
|
}
|
|
28
28
|
else {
|
|
29
29
|
// TODO: Stop it through UI or think about retrying this request. Implement exponential retry mechanism.
|
|
@@ -42,7 +42,7 @@ async function installInitialDomainMapping(event, initialDomainMappingJson) {
|
|
|
42
42
|
}
|
|
43
43
|
catch (error) {
|
|
44
44
|
if (axios_client_1.axios.isAxiosError(error)) {
|
|
45
|
-
console.error('Error while creating recipe blueprint', (0, logger_1.
|
|
45
|
+
console.error('Error while creating recipe blueprint', (0, logger_1.serializeAxiosError)(error));
|
|
46
46
|
}
|
|
47
47
|
else {
|
|
48
48
|
console.error('Error while creating recipe blueprint', error);
|
|
@@ -64,7 +64,7 @@ async function installInitialDomainMapping(event, initialDomainMappingJson) {
|
|
|
64
64
|
}
|
|
65
65
|
catch (error) {
|
|
66
66
|
if (axios_client_1.axios.isAxiosError(error)) {
|
|
67
|
-
console.error('Error while installing initial domain mapping', (0, logger_1.
|
|
67
|
+
console.error('Error while installing initial domain mapping', (0, logger_1.serializeAxiosError)(error));
|
|
68
68
|
}
|
|
69
69
|
else {
|
|
70
70
|
console.error('Error while installing initial domain mapping', error);
|
|
@@ -74,7 +74,7 @@ async function installInitialDomainMapping(event, initialDomainMappingJson) {
|
|
|
74
74
|
}
|
|
75
75
|
catch (error) {
|
|
76
76
|
if (axios_client_1.axios.isAxiosError(error)) {
|
|
77
|
-
console.error('Error while fetching snap in', (0, logger_1.
|
|
77
|
+
console.error('Error while fetching snap in', (0, logger_1.serializeAxiosError)(error));
|
|
78
78
|
}
|
|
79
79
|
else {
|
|
80
80
|
console.error('Error while fetching snap in', error);
|
|
@@ -9,13 +9,13 @@ exports.axios = axios_1.default;
|
|
|
9
9
|
const axios_retry_1 = __importDefault(require("axios-retry"));
|
|
10
10
|
const axiosClient = axios_1.default.create();
|
|
11
11
|
exports.axiosClient = axiosClient;
|
|
12
|
-
// Exponential backoff algorithm: Retry 3 times and there will be a delay of more than 1 * no. of retries second + random number of milliseconds between each retry.
|
|
13
12
|
(0, axios_retry_1.default)(axiosClient, {
|
|
14
|
-
retries:
|
|
13
|
+
retries: 5,
|
|
15
14
|
retryDelay: (retryCount, error) => {
|
|
16
15
|
var _a;
|
|
17
|
-
console.
|
|
18
|
-
|
|
16
|
+
console.warn('Retry attempt: ' + retryCount + 'to url: ' + ((_a = error.config) === null || _a === void 0 ? void 0 : _a.url) + '.');
|
|
17
|
+
// Exponential backoff algorithm: 1 * 2 ^ retryCount * 5000ms
|
|
18
|
+
return axios_retry_1.default.exponentialDelay(retryCount, error, 5000);
|
|
19
19
|
},
|
|
20
20
|
retryCondition: (error) => {
|
|
21
21
|
var _a, _b, _c, _d;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.formatAxiosError = exports.spawn = exports.processTask = exports.WorkerAdapter = void 0;
|
|
17
|
+
exports.serializeAxiosError = exports.formatAxiosError = exports.spawn = exports.processTask = exports.WorkerAdapter = void 0;
|
|
18
18
|
__exportStar(require("./deprecated/adapter"), exports);
|
|
19
19
|
__exportStar(require("./deprecated/demo-extractor"), exports);
|
|
20
20
|
__exportStar(require("./deprecated/uploader"), exports);
|
|
@@ -30,3 +30,5 @@ Object.defineProperty(exports, "spawn", { enumerable: true, get: function () { r
|
|
|
30
30
|
__exportStar(require("./types/workers"), exports);
|
|
31
31
|
var logger_1 = require("./logger/logger");
|
|
32
32
|
Object.defineProperty(exports, "formatAxiosError", { enumerable: true, get: function () { return logger_1.formatAxiosError; } });
|
|
33
|
+
var logger_2 = require("./logger/logger");
|
|
34
|
+
Object.defineProperty(exports, "serializeAxiosError", { enumerable: true, get: function () { return logger_2.serializeAxiosError; } });
|
package/dist/logger/logger.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Console } from 'node:console';
|
|
2
2
|
import { LoggerFactoryInterface, LogLevel, PrintableState } from './logger.interfaces';
|
|
3
|
-
import { AxiosError } from 'axios';
|
|
3
|
+
import { AxiosError, RawAxiosResponseHeaders } from 'axios';
|
|
4
4
|
export declare class Logger extends Console {
|
|
5
5
|
private options?;
|
|
6
6
|
constructor({ event, options }: LoggerFactoryInterface);
|
|
@@ -11,4 +11,23 @@ export declare class Logger extends Console {
|
|
|
11
11
|
error(...args: unknown[]): void;
|
|
12
12
|
}
|
|
13
13
|
export declare function getPrintableState(state: Record<string, any>): PrintableState;
|
|
14
|
+
/**
|
|
15
|
+
* @deprecated
|
|
16
|
+
*/
|
|
14
17
|
export declare function formatAxiosError(error: AxiosError): object;
|
|
18
|
+
export declare const serializeError: (error: unknown) => Error;
|
|
19
|
+
export declare function serializeAxiosError(error: AxiosError): {
|
|
20
|
+
config: {
|
|
21
|
+
method: string | undefined;
|
|
22
|
+
params: any;
|
|
23
|
+
url: string | undefined;
|
|
24
|
+
};
|
|
25
|
+
isAxiosError: boolean;
|
|
26
|
+
isCorsOrNoNetworkError: boolean;
|
|
27
|
+
response: {
|
|
28
|
+
data: unknown;
|
|
29
|
+
headers: RawAxiosResponseHeaders;
|
|
30
|
+
status: number;
|
|
31
|
+
statusText: string;
|
|
32
|
+
} | null;
|
|
33
|
+
};
|
package/dist/logger/logger.js
CHANGED
|
@@ -3,9 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.Logger = void 0;
|
|
6
|
+
exports.serializeError = exports.Logger = void 0;
|
|
7
7
|
exports.getPrintableState = getPrintableState;
|
|
8
8
|
exports.formatAxiosError = formatAxiosError;
|
|
9
|
+
exports.serializeAxiosError = serializeAxiosError;
|
|
9
10
|
const lambda_log_1 = __importDefault(require("lambda-log"));
|
|
10
11
|
const node_console_1 = require("node:console");
|
|
11
12
|
const logger_interfaces_1 = require("./logger.interfaces");
|
|
@@ -85,17 +86,42 @@ function getPrintableState(state) {
|
|
|
85
86
|
// Process the state object directly since it's guaranteed to be an object
|
|
86
87
|
return processValue(state);
|
|
87
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* @deprecated
|
|
91
|
+
*/
|
|
88
92
|
function formatAxiosError(error) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
};
|
|
93
|
+
return serializeAxiosError(error);
|
|
94
|
+
}
|
|
95
|
+
const serializeError = (error) => {
|
|
96
|
+
let serializedError = error;
|
|
97
|
+
try {
|
|
98
|
+
serializedError = JSON.parse(JSON.stringify(error, Object.getOwnPropertyNames(error)));
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
console.error('Failed to serialize error object for logger', err);
|
|
99
102
|
}
|
|
100
|
-
return
|
|
103
|
+
return serializedError;
|
|
104
|
+
};
|
|
105
|
+
exports.serializeError = serializeError;
|
|
106
|
+
function serializeAxiosError(error) {
|
|
107
|
+
var _a, _b, _c;
|
|
108
|
+
const response = error.response
|
|
109
|
+
? {
|
|
110
|
+
data: error.response.data,
|
|
111
|
+
headers: error.response.headers,
|
|
112
|
+
status: error.response.status,
|
|
113
|
+
statusText: error.response.statusText,
|
|
114
|
+
}
|
|
115
|
+
: null;
|
|
116
|
+
const config = {
|
|
117
|
+
method: (_a = error.config) === null || _a === void 0 ? void 0 : _a.method,
|
|
118
|
+
params: (_b = error.config) === null || _b === void 0 ? void 0 : _b.params,
|
|
119
|
+
url: (_c = error.config) === null || _c === void 0 ? void 0 : _c.url,
|
|
120
|
+
};
|
|
121
|
+
return {
|
|
122
|
+
config,
|
|
123
|
+
isAxiosError: true,
|
|
124
|
+
isCorsOrNoNetworkError: !error.response,
|
|
125
|
+
response,
|
|
126
|
+
};
|
|
101
127
|
}
|
|
@@ -30,7 +30,7 @@ it('getPrintableState should return printable state', () => {
|
|
|
30
30
|
},
|
|
31
31
|
});
|
|
32
32
|
});
|
|
33
|
-
it('
|
|
33
|
+
it('serializeAxiosError should return formatted error', () => {
|
|
34
34
|
const error = {
|
|
35
35
|
response: {
|
|
36
36
|
status: 500,
|
|
@@ -40,13 +40,20 @@ it('formatAxiosError should return formatted error', () => {
|
|
|
40
40
|
method: 'GET',
|
|
41
41
|
},
|
|
42
42
|
};
|
|
43
|
-
const formattedError = (0, logger_1.
|
|
43
|
+
const formattedError = (0, logger_1.serializeAxiosError)(error);
|
|
44
44
|
expect(formattedError).toEqual({
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
config: {
|
|
46
|
+
method: 'GET',
|
|
47
|
+
params: undefined,
|
|
48
|
+
url: undefined,
|
|
49
|
+
},
|
|
50
|
+
isAxiosError: true,
|
|
51
|
+
isCorsOrNoNetworkError: false,
|
|
52
|
+
response: {
|
|
53
|
+
data: 'Internal server error',
|
|
54
|
+
headers: undefined,
|
|
55
|
+
status: 500,
|
|
56
|
+
statusText: undefined,
|
|
57
|
+
},
|
|
51
58
|
});
|
|
52
59
|
});
|
package/dist/state/state.js
CHANGED
|
@@ -72,7 +72,7 @@ class State {
|
|
|
72
72
|
}
|
|
73
73
|
catch (error) {
|
|
74
74
|
if (axios_client_1.axios.isAxiosError(error)) {
|
|
75
|
-
console.error('Failed to update state.', (0, logger_1.
|
|
75
|
+
console.error('Failed to update state.', (0, logger_1.serializeAxiosError)(error));
|
|
76
76
|
}
|
|
77
77
|
else {
|
|
78
78
|
console.error('Failed to update state.', error);
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { InputData } from '@devrev/typescript-sdk/dist/snap-ins';
|
|
2
2
|
import { Artifact } from '../uploader/uploader.interfaces';
|
|
3
3
|
import { ErrorRecord } from './common';
|
|
4
|
-
import { DonV2, LoaderReport } from './loading';
|
|
4
|
+
import { DonV2, LoaderReport, RateLimited } from './loading';
|
|
5
|
+
import { NormalizedAttachment } from 'repo/repo.interfaces';
|
|
6
|
+
import { AxiosResponse } from 'axios';
|
|
5
7
|
/**
|
|
6
8
|
* EventType is an enum that defines the different types of events that can be sent to the external extractor from ADaaS.
|
|
7
9
|
* The external extractor can use these events to know what to do next in the extraction process.
|
|
@@ -218,3 +220,18 @@ export interface LoaderEvent {
|
|
|
218
220
|
event_context: EventContext;
|
|
219
221
|
event_data?: EventData;
|
|
220
222
|
}
|
|
223
|
+
export type ExternalSystemAttachmentStreamingFunction = ({ item, event, }: ExternalSystemAttachmentStreamingParams) => Promise<ExternalSystemAttachmentStreamingResponse>;
|
|
224
|
+
export interface ExternalSystemAttachmentStreamingParams {
|
|
225
|
+
item: NormalizedAttachment;
|
|
226
|
+
event: AirdropEvent;
|
|
227
|
+
}
|
|
228
|
+
export interface ExternalSystemAttachmentStreamingResponse {
|
|
229
|
+
httpStream?: AxiosResponse;
|
|
230
|
+
error?: ErrorRecord;
|
|
231
|
+
delay?: number;
|
|
232
|
+
}
|
|
233
|
+
export interface StreamAttachmentsResponse {
|
|
234
|
+
error?: ErrorRecord;
|
|
235
|
+
report?: LoaderReport;
|
|
236
|
+
rateLimit?: RateLimited;
|
|
237
|
+
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { ErrorLevel, ErrorRecord, LogRecord, AdapterUpdateParams, InitialDomainMapping, } from './common';
|
|
2
|
-
export { EventType, ExtractorEventType, ExtractionMode, ExternalSyncUnit, EventContextIn, EventContextOut, ConnectionData, EventData, DomainObjectState, AirdropEvent, AirdropMessage, ExtractorEvent, SyncMode, } from './extraction';
|
|
2
|
+
export { EventType, ExtractorEventType, ExtractionMode, ExternalSyncUnit, EventContextIn, EventContextOut, ConnectionData, EventData, DomainObjectState, AirdropEvent, AirdropMessage, ExtractorEvent, SyncMode, ExternalSystemAttachmentStreamingParams, ExternalSystemAttachmentStreamingResponse, ExternalSystemAttachmentStreamingFunction, } from './extraction';
|
|
3
3
|
export { LoaderEventType, ExternalSystemItem, ExternalSystemItemLoadingResponse, ExternalSystemItemLoadingParams, } from './loading';
|
|
4
4
|
export { NormalizedItem, NormalizedAttachment, RepoInterface, } from '../repo/repo.interfaces';
|
|
5
5
|
export { AdapterState } from '../state/state.interfaces';
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AxiosResponse } from 'axios';
|
|
2
|
+
import { betaSDK } from '@devrev/typescript-sdk';
|
|
3
|
+
import { NormalizedAttachment } from '../repo/repo.interfaces';
|
|
4
|
+
import { UploadResponse, UploaderFactoryInterface } from './uploader.interfaces';
|
|
2
5
|
export declare class Uploader {
|
|
3
6
|
private event;
|
|
4
7
|
private betaDevrevSdk;
|
|
@@ -14,26 +17,22 @@ export declare class Uploader {
|
|
|
14
17
|
* or error information if there was an error
|
|
15
18
|
*/
|
|
16
19
|
upload(itemType: string, fetchedObjects: object[] | object): Promise<UploadResponse>;
|
|
17
|
-
|
|
20
|
+
prepareArtifact(filename: string, fileType: string): Promise<betaSDK.ArtifactsPrepareResponse | void>;
|
|
18
21
|
private uploadToArtifact;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
attachmentsMetadataArtifactId: string;
|
|
29
|
-
}): Promise<StreamAttachmentsResponse>;
|
|
22
|
+
streamToArtifact(preparedArtifact: betaSDK.ArtifactsPrepareResponse, fileStreamResponse: any): Promise<AxiosResponse | void>;
|
|
23
|
+
getAttachmentsFromArtifactId({ artifact, }: {
|
|
24
|
+
artifact: string;
|
|
25
|
+
}): Promise<{
|
|
26
|
+
attachments?: NormalizedAttachment[];
|
|
27
|
+
error?: {
|
|
28
|
+
message: string;
|
|
29
|
+
};
|
|
30
|
+
}>;
|
|
30
31
|
private getArtifactDownloadUrl;
|
|
31
32
|
private downloadArtifact;
|
|
32
33
|
private compressGzip;
|
|
33
34
|
private decompressGzip;
|
|
34
35
|
private parseJsonl;
|
|
35
|
-
private stream;
|
|
36
|
-
private getFileStreamResponse;
|
|
37
36
|
getJsonObjectByArtifactId({ artifactId, isGzipped, }: {
|
|
38
37
|
artifactId: string;
|
|
39
38
|
isGzipped?: boolean;
|
|
@@ -27,8 +27,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
29
|
exports.Uploader = void 0;
|
|
30
|
-
const axios_client_1 = require("../http/axios-client");
|
|
31
30
|
const fs_1 = __importStar(require("fs"));
|
|
31
|
+
const axios_client_1 = require("../http/axios-client");
|
|
32
32
|
const zlib_1 = __importDefault(require("zlib"));
|
|
33
33
|
const js_jsonl_1 = require("js-jsonl");
|
|
34
34
|
const form_data_1 = __importDefault(require("form-data"));
|
|
@@ -99,7 +99,7 @@ class Uploader {
|
|
|
99
99
|
}
|
|
100
100
|
catch (error) {
|
|
101
101
|
if (axios_client_1.axios.isAxiosError(error)) {
|
|
102
|
-
console.error('Error while preparing artifact.', (0, logger_1.
|
|
102
|
+
console.error('Error while preparing artifact.', (0, logger_1.serializeAxiosError)(error));
|
|
103
103
|
}
|
|
104
104
|
else {
|
|
105
105
|
console.error('Error while preparing artifact.', error);
|
|
@@ -122,7 +122,7 @@ class Uploader {
|
|
|
122
122
|
}
|
|
123
123
|
catch (error) {
|
|
124
124
|
if (axios_client_1.axios.isAxiosError(error)) {
|
|
125
|
-
console.error('Error while uploading artifact.', (0, logger_1.
|
|
125
|
+
console.error('Error while uploading artifact.', (0, logger_1.serializeAxiosError)(error));
|
|
126
126
|
}
|
|
127
127
|
else {
|
|
128
128
|
console.error('Error while uploading artifact.', error);
|
|
@@ -147,7 +147,7 @@ class Uploader {
|
|
|
147
147
|
}
|
|
148
148
|
catch (error) {
|
|
149
149
|
if (axios_client_1.axios.isAxiosError(error)) {
|
|
150
|
-
console.error('Error while streaming artifact.', (0, logger_1.
|
|
150
|
+
console.error('Error while streaming artifact.', (0, logger_1.serializeAxiosError)(error));
|
|
151
151
|
}
|
|
152
152
|
else {
|
|
153
153
|
console.error('Error while streaming artifact.', error);
|
|
@@ -155,17 +155,9 @@ class Uploader {
|
|
|
155
155
|
return;
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
|
-
|
|
159
|
-
* Streams the attachments to the DevRev platform.
|
|
160
|
-
* The attachments are streamed to the platform and the artifact information is returned.
|
|
161
|
-
* @param {string} attachmentsMetadataArtifactId - The artifact ID of the attachments metadata
|
|
162
|
-
* @returns {Promise<UploadResponse>} - The response object containing the ssoAttachment artifact information
|
|
163
|
-
* or error information if there was an error
|
|
164
|
-
*/
|
|
165
|
-
async streamAttachments({ attachmentsMetadataArtifactId, }) {
|
|
166
|
-
console.log('Started streaming attachments to the platform.');
|
|
158
|
+
async getAttachmentsFromArtifactId({ artifact, }) {
|
|
167
159
|
// 1. Get the URL of the attachments metadata artifact
|
|
168
|
-
const artifactUrl = await this.getArtifactDownloadUrl(
|
|
160
|
+
const artifactUrl = await this.getArtifactDownloadUrl(artifact);
|
|
169
161
|
if (!artifactUrl) {
|
|
170
162
|
return {
|
|
171
163
|
error: { message: 'Error while getting artifact download URL.' },
|
|
@@ -192,23 +184,7 @@ class Uploader {
|
|
|
192
184
|
error: { message: 'Error while parsing jsonl object.' },
|
|
193
185
|
};
|
|
194
186
|
}
|
|
195
|
-
|
|
196
|
-
const ssorAttachments = [];
|
|
197
|
-
for (const attachmentMetadata of jsonObject) {
|
|
198
|
-
const { ssorAttachment, error } = await this.stream(attachmentMetadata);
|
|
199
|
-
if (error || !ssorAttachment) {
|
|
200
|
-
console.warn('Error while streaming attachment', error);
|
|
201
|
-
continue;
|
|
202
|
-
}
|
|
203
|
-
ssorAttachments.push(ssorAttachment);
|
|
204
|
-
}
|
|
205
|
-
if (!ssorAttachments.length) {
|
|
206
|
-
console.warn('No attachments were streamed to the platform.');
|
|
207
|
-
return {
|
|
208
|
-
error: { message: 'No attachments were streamed to the platform.' },
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
return { ssorAttachments };
|
|
187
|
+
return { attachments: jsonObject };
|
|
212
188
|
}
|
|
213
189
|
async getArtifactDownloadUrl(artifactId) {
|
|
214
190
|
try {
|
|
@@ -230,7 +206,7 @@ class Uploader {
|
|
|
230
206
|
}
|
|
231
207
|
catch (error) {
|
|
232
208
|
if (axios_client_1.axios.isAxiosError(error)) {
|
|
233
|
-
console.error('Error while downloading artifact from URL.', (0, logger_1.
|
|
209
|
+
console.error('Error while downloading artifact from URL.', (0, logger_1.serializeAxiosError)(error));
|
|
234
210
|
}
|
|
235
211
|
else {
|
|
236
212
|
console.error('Error while downloading artifact from URL.', error);
|
|
@@ -262,63 +238,6 @@ class Uploader {
|
|
|
262
238
|
console.error('Error while parsing jsonl object.', error);
|
|
263
239
|
}
|
|
264
240
|
}
|
|
265
|
-
async stream(attachmentMetadata) {
|
|
266
|
-
var _a;
|
|
267
|
-
const { id: externalId, file_name: filename, url, parent_id: parentId, author_id: actorId, } = attachmentMetadata;
|
|
268
|
-
const fileStreamResponse = await this.getFileStreamResponse(url);
|
|
269
|
-
if (!fileStreamResponse) {
|
|
270
|
-
return {
|
|
271
|
-
error: { message: 'Error while fetching attachment from URL' },
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
const fileType = ((_a = fileStreamResponse.headers) === null || _a === void 0 ? void 0 : _a['content-type']) ||
|
|
275
|
-
'application/octet-stream';
|
|
276
|
-
const preparedArtifact = await this.prepareArtifact(filename, fileType);
|
|
277
|
-
if (!preparedArtifact) {
|
|
278
|
-
return {
|
|
279
|
-
error: { message: 'Error while preparing artifact.' },
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
const uploadedArtifact = await this.streamToArtifact(preparedArtifact, fileStreamResponse);
|
|
283
|
-
if (!uploadedArtifact) {
|
|
284
|
-
return {
|
|
285
|
-
error: { message: 'Error while streaming artifact.' },
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
const ssorAttachment = {
|
|
289
|
-
id: {
|
|
290
|
-
devrev: preparedArtifact.id,
|
|
291
|
-
external: externalId,
|
|
292
|
-
},
|
|
293
|
-
parent_id: {
|
|
294
|
-
external: parentId,
|
|
295
|
-
},
|
|
296
|
-
actor_id: {
|
|
297
|
-
external: actorId,
|
|
298
|
-
},
|
|
299
|
-
};
|
|
300
|
-
console.log('Successful stream of attachment: ', ssorAttachment);
|
|
301
|
-
return { ssorAttachment };
|
|
302
|
-
}
|
|
303
|
-
async getFileStreamResponse(url) {
|
|
304
|
-
try {
|
|
305
|
-
const fileStreamResponse = await axios_client_1.axiosClient.get(url, {
|
|
306
|
-
responseType: 'stream',
|
|
307
|
-
headers: {
|
|
308
|
-
Authorization: this.event.payload.connection_data.key,
|
|
309
|
-
},
|
|
310
|
-
});
|
|
311
|
-
return fileStreamResponse;
|
|
312
|
-
}
|
|
313
|
-
catch (error) {
|
|
314
|
-
if (axios_client_1.axios.isAxiosError(error)) {
|
|
315
|
-
console.error('Error while fetching attachment from URL.', (0, logger_1.formatAxiosError)(error));
|
|
316
|
-
}
|
|
317
|
-
else {
|
|
318
|
-
console.error('Error while fetching attachment from URL.', error);
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
241
|
async getJsonObjectByArtifactId({ artifactId, isGzipped = false, }) {
|
|
323
242
|
const artifactUrl = await this.getArtifactDownloadUrl(artifactId);
|
|
324
243
|
if (!artifactUrl) {
|
|
@@ -16,7 +16,7 @@ async function createWorker(workerData) {
|
|
|
16
16
|
workerData,
|
|
17
17
|
});
|
|
18
18
|
worker.on(workers_1.WorkerEvent.WorkerError, (error) => {
|
|
19
|
-
logger.error('Worker error', error);
|
|
19
|
+
logger.error('Worker error', (0, logger_1.serializeError)(error));
|
|
20
20
|
reject();
|
|
21
21
|
});
|
|
22
22
|
worker.on(workers_1.WorkerEvent.WorkerOnline, () => {
|
|
@@ -1,42 +1,43 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const index_1 = require("../../index");
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
{
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
const axios_client_1 = require("../../http/axios-client");
|
|
5
|
+
const getAttachmentStream = async ({ item, }) => {
|
|
6
|
+
const { id, url } = item;
|
|
7
|
+
try {
|
|
8
|
+
const fileStreamResponse = await axios_client_1.axiosClient.get(url, {
|
|
9
|
+
responseType: 'stream',
|
|
10
|
+
});
|
|
11
|
+
return { httpStream: fileStreamResponse };
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
if (axios_client_1.axios.isAxiosError(error)) {
|
|
15
|
+
console.error('Error while fetching attachment from URL.', (0, index_1.serializeAxiosError)(error));
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
console.error('Error while fetching attachment from URL.', error);
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
error: {
|
|
22
|
+
message: 'Error while fetching attachment ' + id + ' from URL.',
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
};
|
|
10
27
|
(0, index_1.processTask)({
|
|
11
28
|
task: async ({ adapter }) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
adapter.state.toDevRev.attachmentsMetadata.artifactIds.length === 0) {
|
|
15
|
-
console.log('No attachments to extract, skipping.');
|
|
16
|
-
await adapter.emit(index_1.ExtractorEventType.ExtractionAttachmentsDone);
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
adapter.initializeRepos(repos);
|
|
20
|
-
const uploader = new uploader_1.Uploader({
|
|
21
|
-
event: adapter.event,
|
|
22
|
-
options: adapter.options,
|
|
29
|
+
const { error, delay } = await adapter.streamAttachments({
|
|
30
|
+
stream: getAttachmentStream,
|
|
23
31
|
});
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
32
|
+
if (delay) {
|
|
33
|
+
await adapter.emit(index_1.ExtractorEventType.ExtractionAttachmentsDelay, {
|
|
34
|
+
delay,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
else if (error) {
|
|
38
|
+
await adapter.emit(index_1.ExtractorEventType.ExtractionAttachmentsError, {
|
|
39
|
+
error,
|
|
27
40
|
});
|
|
28
|
-
if (error || !ssorAttachments) {
|
|
29
|
-
await adapter.emit(index_1.ExtractorEventType.ExtractionAttachmentsError, {
|
|
30
|
-
error,
|
|
31
|
-
});
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
await ((_c = adapter.getRepo('ssor_attachment')) === null || _c === void 0 ? void 0 : _c.push(ssorAttachments));
|
|
35
|
-
(_d = adapter.state.toDevRev) === null || _d === void 0 ? void 0 : _d.attachmentsMetadata.artifactIds.shift();
|
|
36
|
-
adapter.state.toDevRev.attachmentsMetadata.lastProcessed = 0;
|
|
37
|
-
if (((_e = adapter.state.toDevRev) === null || _e === void 0 ? void 0 : _e.attachmentsMetadata.artifactIds.length) === 0) {
|
|
38
|
-
break;
|
|
39
|
-
}
|
|
40
41
|
}
|
|
41
42
|
await adapter.emit(index_1.ExtractorEventType.ExtractionAttachmentsDone);
|
|
42
43
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AirdropEvent, ExtractorEventType, EventData } from '../types/extraction';
|
|
1
|
+
import { AirdropEvent, ExtractorEventType, EventData, ExternalSystemAttachmentStreamingFunction } from '../types/extraction';
|
|
2
2
|
import { LoaderEventType } from '../types/loading';
|
|
3
3
|
import { AdapterState } from '../state/state.interfaces';
|
|
4
4
|
import { Artifact } from '../uploader/uploader.interfaces';
|
|
@@ -58,4 +58,28 @@ export declare class WorkerAdapter<ConnectorState> {
|
|
|
58
58
|
item: ExternalSystemItem;
|
|
59
59
|
itemTypeToLoad: ItemTypeToLoad;
|
|
60
60
|
}): Promise<LoadItemResponse>;
|
|
61
|
+
/**
|
|
62
|
+
* Streams the attachments to the DevRev platform.
|
|
63
|
+
* The attachments are streamed to the platform and the artifact information is returned.
|
|
64
|
+
* @param {string} attachmentsMetadataArtifactId - The artifact ID of the attachments metadata
|
|
65
|
+
* @returns {Promise<UploadResponse>} - The response object containing the ssoAttachment artifact information
|
|
66
|
+
* or error information if there was an error
|
|
67
|
+
*/
|
|
68
|
+
streamAttachments({ stream, }: {
|
|
69
|
+
stream: ExternalSystemAttachmentStreamingFunction;
|
|
70
|
+
}): Promise<{
|
|
71
|
+
report: {};
|
|
72
|
+
error?: undefined;
|
|
73
|
+
delay?: undefined;
|
|
74
|
+
} | {
|
|
75
|
+
error: {
|
|
76
|
+
message: string;
|
|
77
|
+
};
|
|
78
|
+
report?: undefined;
|
|
79
|
+
delay?: undefined;
|
|
80
|
+
} | {
|
|
81
|
+
delay: number;
|
|
82
|
+
report?: undefined;
|
|
83
|
+
error?: undefined;
|
|
84
|
+
}>;
|
|
61
85
|
}
|
|
@@ -341,7 +341,7 @@ class WorkerAdapter {
|
|
|
341
341
|
}
|
|
342
342
|
catch (error) {
|
|
343
343
|
if (axios_client_1.axios.isAxiosError(error)) {
|
|
344
|
-
console.error('Failed to update sync mapper record', (0, logger_1.
|
|
344
|
+
console.error('Failed to update sync mapper record', (0, logger_1.serializeAxiosError)(error));
|
|
345
345
|
return {
|
|
346
346
|
error: {
|
|
347
347
|
message: error.message,
|
|
@@ -412,7 +412,7 @@ class WorkerAdapter {
|
|
|
412
412
|
}
|
|
413
413
|
catch (error) {
|
|
414
414
|
if (axios_client_1.axios.isAxiosError(error)) {
|
|
415
|
-
console.error('Failed to create sync mapper record', (0, logger_1.
|
|
415
|
+
console.error('Failed to create sync mapper record', (0, logger_1.serializeAxiosError)(error));
|
|
416
416
|
return {
|
|
417
417
|
error: {
|
|
418
418
|
message: error.message,
|
|
@@ -445,7 +445,7 @@ class WorkerAdapter {
|
|
|
445
445
|
}
|
|
446
446
|
}
|
|
447
447
|
else {
|
|
448
|
-
console.error('Failed to get sync mapper record', (0, logger_1.
|
|
448
|
+
console.error('Failed to get sync mapper record', (0, logger_1.serializeAxiosError)(error));
|
|
449
449
|
return {
|
|
450
450
|
error: {
|
|
451
451
|
message: error.message,
|
|
@@ -461,5 +461,87 @@ class WorkerAdapter {
|
|
|
461
461
|
};
|
|
462
462
|
}
|
|
463
463
|
}
|
|
464
|
+
/**
|
|
465
|
+
* Streams the attachments to the DevRev platform.
|
|
466
|
+
* The attachments are streamed to the platform and the artifact information is returned.
|
|
467
|
+
* @param {string} attachmentsMetadataArtifactId - The artifact ID of the attachments metadata
|
|
468
|
+
* @returns {Promise<UploadResponse>} - The response object containing the ssoAttachment artifact information
|
|
469
|
+
* or error information if there was an error
|
|
470
|
+
*/
|
|
471
|
+
async streamAttachments({ stream, }) {
|
|
472
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
473
|
+
const repos = [
|
|
474
|
+
{
|
|
475
|
+
itemType: 'ssor_attachment',
|
|
476
|
+
},
|
|
477
|
+
];
|
|
478
|
+
this.initializeRepos(repos);
|
|
479
|
+
for (const attachmentsMetadataArtifactId of ((_a = this.state.toDevRev) === null || _a === void 0 ? void 0 : _a.attachmentsMetadata.artifactIds) || []) {
|
|
480
|
+
if (((_b = this.state.toDevRev) === null || _b === void 0 ? void 0 : _b.attachmentsMetadata.artifactIds.length) === 0) {
|
|
481
|
+
return { report: {} };
|
|
482
|
+
}
|
|
483
|
+
console.log('Started streaming attachments to the platform.');
|
|
484
|
+
const { attachments, error } = await this.uploader.getAttachmentsFromArtifactId({
|
|
485
|
+
artifact: attachmentsMetadataArtifactId,
|
|
486
|
+
});
|
|
487
|
+
if (error) {
|
|
488
|
+
return { error };
|
|
489
|
+
}
|
|
490
|
+
console.log('this.state.toDevRev?.attachmentsMetadata :>> ', (_c = this.state.toDevRev) === null || _c === void 0 ? void 0 : _c.attachmentsMetadata);
|
|
491
|
+
if (attachments) {
|
|
492
|
+
const attachmentsToProcess = attachments.slice((_e = (_d = this.state.toDevRev) === null || _d === void 0 ? void 0 : _d.attachmentsMetadata) === null || _e === void 0 ? void 0 : _e.lastProcessed, attachments.length);
|
|
493
|
+
for (const attachment of attachmentsToProcess) {
|
|
494
|
+
const { httpStream, delay, error } = await stream({
|
|
495
|
+
item: attachment,
|
|
496
|
+
event: this.event,
|
|
497
|
+
});
|
|
498
|
+
if (error) {
|
|
499
|
+
console.warn('Error while streaming attachment', error === null || error === void 0 ? void 0 : error.message);
|
|
500
|
+
continue;
|
|
501
|
+
}
|
|
502
|
+
else if (delay) {
|
|
503
|
+
return { delay };
|
|
504
|
+
}
|
|
505
|
+
if (httpStream) {
|
|
506
|
+
const fileType = ((_f = httpStream.headers) === null || _f === void 0 ? void 0 : _f['content-type']) ||
|
|
507
|
+
'application/octet-stream';
|
|
508
|
+
const preparedArtifact = await this.uploader.prepareArtifact(attachment.file_name, fileType);
|
|
509
|
+
if (!preparedArtifact) {
|
|
510
|
+
return {
|
|
511
|
+
error: { message: 'Error while preparing artifact.' },
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
const uploadedArtifact = await this.uploader.streamToArtifact(preparedArtifact, httpStream);
|
|
515
|
+
if (!uploadedArtifact) {
|
|
516
|
+
return {
|
|
517
|
+
error: { message: 'Error while streaming artifact.' },
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
const ssorAttachment = {
|
|
521
|
+
id: {
|
|
522
|
+
devrev: preparedArtifact.id,
|
|
523
|
+
external: attachment.id,
|
|
524
|
+
},
|
|
525
|
+
parent_id: {
|
|
526
|
+
external: attachment.parent_id,
|
|
527
|
+
},
|
|
528
|
+
actor_id: {
|
|
529
|
+
external: attachment.author_id,
|
|
530
|
+
},
|
|
531
|
+
};
|
|
532
|
+
await ((_g = this.getRepo('ssor_attachment')) === null || _g === void 0 ? void 0 : _g.push([ssorAttachment]));
|
|
533
|
+
if (this.state.toDevRev) {
|
|
534
|
+
this.state.toDevRev.attachmentsMetadata.lastProcessed++;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
if (this.state.toDevRev) {
|
|
540
|
+
this.state.toDevRev.attachmentsMetadata.artifactIds.shift();
|
|
541
|
+
this.state.toDevRev.attachmentsMetadata.lastProcessed = 0;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
return { report: {} };
|
|
545
|
+
}
|
|
464
546
|
}
|
|
465
547
|
exports.WorkerAdapter = WorkerAdapter;
|