@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 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
- - Exported `axios` and `axiosClient` with exponential backoff retry mechanism for HTTP requests and omitting Authorization headers from Axios errors.
8
- - Resolved issues with circular structure logging.
9
- - Fixed attachments metadata normalization bug.
10
- - Improved repository logging.
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
- #### v1.1.2
22
+ ### v1.1.2
13
23
 
14
- - Unified incoming and outgoing event context.
15
- - Added `dev_oid` to logger tags.
24
+ - Unify incoming and outgoing event context.
25
+ - Add `dev_oid` to logger tags.
16
26
 
17
- #### v1.1.1
27
+ ### v1.1.1
18
28
 
19
- - Added default workers for loading deletion events.
29
+ - Add default workers for loading deletion events.
20
30
 
21
- #### v1.1.0
31
+ ### v1.1.0
22
32
 
23
- - Support for sync from DevRev to external system. Known limitations: no support for loading attachments.
33
+ - Support sync from DevRev to the external system. (Known limitations: no support for loading attachments.)
24
34
 
25
- #### v1.0.4
35
+ ### v1.0.4
26
36
 
27
37
  - Fix logging from worker threads.
28
38
 
29
- #### v1.0.3
39
+ ### v1.0.3
30
40
 
31
- - Added Release notes.
41
+ - Add release notes.
32
42
 
33
- #### v1.0.2
43
+ ### v1.0.2
34
44
 
35
- - Bug fixes and improvements in local development.
45
+ - Fix bugs and improve local development.
36
46
  - Expose `formatAxiosError` function for error handling.
37
47
 
38
- #### v1.0.1
48
+ ### v1.0.1
39
49
 
40
- - Bug fixes and improvements in logging.
50
+ - Fix bugs and improve logging.
41
51
 
42
- #### v1.0.0
52
+ ### v1.0.0
43
53
 
44
- - Allow extractions to use full lambda runtime and gracefully handle execution context timeout.
45
- - Simplified metadata and data normalization and uploading with repo implementation.
46
- - Default handling of attachment extraction phase in ADaaS SDK library.
47
- - Reduced file size, streamlined process by gzip compression.
48
- - Bug fixes and improvements in error handling.
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
- #### v0.0.3
60
+ ### v0.0.3
51
61
 
52
- - Support for new recipe management
62
+ - Support new recipe management.
53
63
 
54
- #### v0.0.2
64
+ ### v0.0.2
55
65
 
56
- - Support for the State API
57
- - HTTP client for API requests
58
- - Local development environment creates local artifact files
59
- - Improvements in logging
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
- #### v0.0.1
71
+ ### v0.0.1
62
72
 
63
- - Demo implementation of ADaaS snap-in
64
- - Adapter for ADaaS control protocol with helper functions
65
- - Uploader for uploading artifacts
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.formatAxiosError)(error));
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.formatAxiosError)(error));
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.formatAxiosError)(error));
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.formatAxiosError)(error));
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: 3,
13
+ retries: 5,
15
14
  retryDelay: (retryCount, error) => {
16
15
  var _a;
17
- console.log(`Retry attempt: ${retryCount} of ${(_a = error.config) === null || _a === void 0 ? void 0 : _a.url}.`);
18
- return axios_retry_1.default.exponentialDelay(retryCount, error, 1000);
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
@@ -9,3 +9,4 @@ export { processTask } from './workers/process-task';
9
9
  export { spawn } from './workers/spawn';
10
10
  export * from './types/workers';
11
11
  export { formatAxiosError } from './logger/logger';
12
+ export { serializeAxiosError } from './logger/logger';
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; } });
@@ -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
+ };
@@ -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
- var _a, _b, _c, _d;
90
- if (error.response) {
91
- return {
92
- status: error.response.status,
93
- data: error.response.data,
94
- method: (_a = error.config) === null || _a === void 0 ? void 0 : _a.method,
95
- baseURL: (_b = error.config) === null || _b === void 0 ? void 0 : _b.baseURL,
96
- url: (_c = error.config) === null || _c === void 0 ? void 0 : _c.url,
97
- payload: (_d = error.config) === null || _d === void 0 ? void 0 : _d.data,
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 error;
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('formatAxiosError should return formatted error', () => {
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.formatAxiosError)(error);
43
+ const formattedError = (0, logger_1.serializeAxiosError)(error);
44
44
  expect(formattedError).toEqual({
45
- status: 500,
46
- data: 'Internal server error',
47
- method: 'GET',
48
- baseURL: undefined,
49
- url: undefined,
50
- payload: undefined,
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
  });
@@ -36,6 +36,7 @@ export interface NormalizedAttachment {
36
36
  file_name: string;
37
37
  author_id: string;
38
38
  parent_id: string;
39
+ inline?: boolean;
39
40
  }
40
41
  /**
41
42
  * Item is an interface that defines the structure of an item.
@@ -1,3 +1,2 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- ;
@@ -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.formatAxiosError)(error));
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
+ }
@@ -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 { UploadResponse, StreamAttachmentsResponse, UploaderFactoryInterface } from './uploader.interfaces';
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
- private prepareArtifact;
20
+ prepareArtifact(filename: string, fileType: string): Promise<betaSDK.ArtifactsPrepareResponse | void>;
18
21
  private uploadToArtifact;
19
- private streamToArtifact;
20
- /**
21
- * Streams the attachments to the DevRev platform.
22
- * The attachments are streamed to the platform and the artifact information is returned.
23
- * @param {string} attachmentsMetadataArtifactId - The artifact ID of the attachments metadata
24
- * @returns {Promise<UploadResponse>} - The response object containing the ssoAttachment artifact information
25
- * or error information if there was an error
26
- */
27
- streamAttachments({ attachmentsMetadataArtifactId, }: {
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.formatAxiosError)(error));
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.formatAxiosError)(error));
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.formatAxiosError)(error));
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(attachmentsMetadataArtifactId);
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
- // 5. Stream each attachment to the platform, and push the ssorAttachment to the ssorAttachments array
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.formatAxiosError)(error));
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 uploader_1 = require("../../uploader/uploader");
5
- const repos = [
6
- {
7
- itemType: 'ssor_attachment',
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
- var _a, _b, _c, _d, _e;
13
- if (!((_a = adapter.state.toDevRev) === null || _a === void 0 ? void 0 : _a.attachmentsMetadata.artifactIds) ||
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
- for (const attachmentsMetadataArtifactId of (_b = adapter.state.toDevRev) === null || _b === void 0 ? void 0 : _b.attachmentsMetadata.artifactIds) {
25
- const { ssorAttachments, error } = await uploader.streamAttachments({
26
- attachmentsMetadataArtifactId,
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.formatAxiosError)(error));
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.formatAxiosError)(error));
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.formatAxiosError)(error));
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devrev/ts-adaas",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "description": "Typescript library containing the ADaaS(AirDrop as a Service) control protocol.",
5
5
  "type": "commonjs",
6
6
  "main": "./dist/index.js",