@devrev/airsync-sdk 2.0.0-beta.10 → 2.0.0-beta.12

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
@@ -15,3 +15,4 @@ npm install @devrev/airsync-sdk
15
15
  - [Architecture](docs/ARCHITECTURE.md): how the SDK works and how it talks to the AirSync platform.
16
16
  - [Migration from v1](docs/MIGRATION.md): moving from `@devrev/ts-adaas` to `@devrev/airsync-sdk`.
17
17
  - [Contributing](docs/CONTRIBUTING.md): workflow, versioning and testing conventions.
18
+ - [Release strategy](docs/RELEASE_STRATEGY.md): branch model, workflow choices and release safeguards.
@@ -73,7 +73,7 @@ class AttachmentsStreamingPool {
73
73
  Promise.all(initialPromises),
74
74
  this.adapter.timeoutSignal,
75
75
  ]);
76
- if (this.delay) {
76
+ if (this.delay !== undefined) {
77
77
  return { status: 'delay', delaySeconds: this.delay };
78
78
  }
79
79
  return { status: 'success' };
@@ -81,7 +81,7 @@ class AttachmentsStreamingPool {
81
81
  async startPoolStreaming() {
82
82
  var _a;
83
83
  while (this.attachments.length > 0) {
84
- if (this.delay) {
84
+ if (this.delay !== undefined) {
85
85
  break;
86
86
  }
87
87
  if (this.adapter.isTimeout) {
@@ -1,3 +1,4 @@
1
- declare const axiosClient: import("axios").AxiosInstance;
1
+ import { AxiosInstance } from 'axios';
2
+ declare const axiosClient: Pick<AxiosInstance, 'get' | 'post'>;
2
3
  export { axiosClient };
3
4
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/http/client.ts"],"names":[],"mappings":"AAGA,QAAA,MAAM,WAAW,+BAEf,CAAC;AAmFH,OAAO,EAAE,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/http/client.ts"],"names":[],"mappings":"AAAA,OAAc,EAAc,aAAa,EAAE,MAAM,OAAO,CAAC;AAmGzD,QAAA,MAAM,WAAW,EAAE,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,MAAM,CAGpD,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,CAAC"}
@@ -6,64 +6,75 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.axiosClient = void 0;
7
7
  const axios_1 = __importDefault(require("axios"));
8
8
  const axios_retry_1 = __importDefault(require("axios-retry"));
9
- const axiosClient = axios_1.default.create({
10
- timeout: 30 * 1000,
11
- });
9
+ function createAxiosClient() {
10
+ const client = axios_1.default.create({
11
+ timeout: 30 * 1000,
12
+ });
13
+ (0, axios_retry_1.default)(client, {
14
+ retries: 5,
15
+ shouldResetTimeout: true,
16
+ retryDelay: (retryCount, error) => {
17
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
18
+ let delay;
19
+ if (((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 429) {
20
+ const retryAfter = ((_c = (_b = error.response) === null || _b === void 0 ? void 0 : _b.headers) === null || _c === void 0 ? void 0 : _c['retry-after']) ||
21
+ ((_e = (_d = error.response) === null || _d === void 0 ? void 0 : _d.headers) === null || _e === void 0 ? void 0 : _e['Retry-After']);
22
+ delay = parseInt(retryAfter, 10) * 1000;
23
+ }
24
+ else {
25
+ delay = axios_retry_1.default.exponentialDelay(retryCount, error, 1000);
26
+ }
27
+ const requestId = ((_g = (_f = error.config) === null || _f === void 0 ? void 0 : _f.headers) === null || _g === void 0 ? void 0 : _g['x-request-id']) ||
28
+ ((_j = (_h = error.config) === null || _h === void 0 ? void 0 : _h.headers) === null || _j === void 0 ? void 0 : _j['X-Request-ID']);
29
+ const delayInSeconds = Math.round(delay / 1000);
30
+ console.warn(`Retrying request to ${(_k = error.config) === null || _k === void 0 ? void 0 : _k.url} in ${delayInSeconds}s due to ${(_m = (_l = error.response) === null || _l === void 0 ? void 0 : _l.status) !== null && _m !== void 0 ? _m : 'unknown'} error.`, Object.assign(Object.assign({ method: (_o = error.config) === null || _o === void 0 ? void 0 : _o.method }, (retryCount && { retryCount })), (requestId && { requestId })));
31
+ return delay;
32
+ },
33
+ retryCondition: (error) => {
34
+ var _a, _b, _c, _d, _e, _f, _g;
35
+ const retryAfter = ((_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.headers) === null || _b === void 0 ? void 0 : _b['retry-after']) ||
36
+ ((_d = (_c = error.response) === null || _c === void 0 ? void 0 : _c.headers) === null || _d === void 0 ? void 0 : _d['Retry-After']);
37
+ if (((_e = error.response) === null || _e === void 0 ? void 0 : _e.status) && error.response.status >= 500) {
38
+ return true;
39
+ }
40
+ // 429 only when a valid non-negative Retry-After header is present
41
+ else if (((_f = error.response) === null || _f === void 0 ? void 0 : _f.status) &&
42
+ error.response.status === 429 &&
43
+ retryAfter &&
44
+ !isNaN(Number(retryAfter)) &&
45
+ Number(retryAfter) >= 0) {
46
+ return true;
47
+ }
48
+ // Network errors for idempotent requests; 429 already handled above
49
+ else if (axios_retry_1.default.isNetworkOrIdempotentRequestError(error) &&
50
+ ((_g = error.response) === null || _g === void 0 ? void 0 : _g.status) !== 429) {
51
+ return true;
52
+ }
53
+ // axios-retry excludes ECONNABORTED (client-side timeout only, never a
54
+ // server response) from isNetworkError, so handle it here separately.
55
+ else if (error.code === 'ECONNABORTED') {
56
+ return true;
57
+ }
58
+ else {
59
+ return false;
60
+ }
61
+ },
62
+ onMaxRetryTimesExceeded(error) {
63
+ var _a, _b, _c, _d, _e, _f;
64
+ (_b = (_a = error.config) === null || _a === void 0 ? void 0 : _a.headers) === null || _b === void 0 ? true : delete _b.authorization;
65
+ (_d = (_c = error.config) === null || _c === void 0 ? void 0 : _c.headers) === null || _d === void 0 ? true : delete _d.Authorization;
66
+ (_e = error.request) === null || _e === void 0 ? true : delete _e._header;
67
+ console.error(`Request to ${(_f = error.config) === null || _f === void 0 ? void 0 : _f.url} failed after max retries. Error`, error);
68
+ },
69
+ });
70
+ return client;
71
+ }
72
+ let instance;
73
+ const getInstance = () => (instance !== null && instance !== void 0 ? instance : (instance = createAxiosClient()));
74
+ // Created on first use so that loading the SDK never calls axios.create(),
75
+ // which breaks connector tests that mock axios.
76
+ const axiosClient = {
77
+ get: async (...args) => getInstance().get(...args),
78
+ post: async (...args) => getInstance().post(...args),
79
+ };
12
80
  exports.axiosClient = axiosClient;
13
- (0, axios_retry_1.default)(axiosClient, {
14
- retries: 5,
15
- shouldResetTimeout: true,
16
- retryDelay: (retryCount, error) => {
17
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
18
- let delay;
19
- if (((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 429) {
20
- const retryAfter = ((_c = (_b = error.response) === null || _b === void 0 ? void 0 : _b.headers) === null || _c === void 0 ? void 0 : _c['retry-after']) ||
21
- ((_e = (_d = error.response) === null || _d === void 0 ? void 0 : _d.headers) === null || _e === void 0 ? void 0 : _e['Retry-After']);
22
- delay = parseInt(retryAfter, 10) * 1000;
23
- }
24
- else {
25
- delay = axios_retry_1.default.exponentialDelay(retryCount, error, 1000);
26
- }
27
- const requestId = ((_g = (_f = error.config) === null || _f === void 0 ? void 0 : _f.headers) === null || _g === void 0 ? void 0 : _g['x-request-id']) ||
28
- ((_j = (_h = error.config) === null || _h === void 0 ? void 0 : _h.headers) === null || _j === void 0 ? void 0 : _j['X-Request-ID']);
29
- const delayInSeconds = Math.round(delay / 1000);
30
- console.warn(`Retrying request to ${(_k = error.config) === null || _k === void 0 ? void 0 : _k.url} in ${delayInSeconds}s due to ${(_m = (_l = error.response) === null || _l === void 0 ? void 0 : _l.status) !== null && _m !== void 0 ? _m : 'unknown'} error.`, Object.assign(Object.assign({ method: (_o = error.config) === null || _o === void 0 ? void 0 : _o.method }, (retryCount && { retryCount })), (requestId && { requestId })));
31
- return delay;
32
- },
33
- retryCondition: (error) => {
34
- var _a, _b, _c, _d, _e, _f, _g;
35
- const retryAfter = ((_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.headers) === null || _b === void 0 ? void 0 : _b['retry-after']) ||
36
- ((_d = (_c = error.response) === null || _c === void 0 ? void 0 : _c.headers) === null || _d === void 0 ? void 0 : _d['Retry-After']);
37
- if (((_e = error.response) === null || _e === void 0 ? void 0 : _e.status) && error.response.status >= 500) {
38
- return true;
39
- }
40
- // 429 only when a valid non-negative Retry-After header is present
41
- else if (((_f = error.response) === null || _f === void 0 ? void 0 : _f.status) &&
42
- error.response.status === 429 &&
43
- retryAfter &&
44
- !isNaN(Number(retryAfter)) &&
45
- Number(retryAfter) >= 0) {
46
- return true;
47
- }
48
- // Network errors for idempotent requests; 429 already handled above
49
- else if (axios_retry_1.default.isNetworkOrIdempotentRequestError(error) &&
50
- ((_g = error.response) === null || _g === void 0 ? void 0 : _g.status) !== 429) {
51
- return true;
52
- }
53
- // axios-retry excludes ECONNABORTED (client-side timeout only, never a
54
- // server response) from isNetworkError, so handle it here separately.
55
- else if (error.code === 'ECONNABORTED') {
56
- return true;
57
- }
58
- else {
59
- return false;
60
- }
61
- },
62
- onMaxRetryTimesExceeded(error) {
63
- var _a, _b, _c, _d, _e, _f;
64
- (_b = (_a = error.config) === null || _a === void 0 ? void 0 : _a.headers) === null || _b === void 0 ? true : delete _b.authorization;
65
- (_d = (_c = error.config) === null || _c === void 0 ? void 0 : _c.headers) === null || _d === void 0 ? true : delete _d.Authorization;
66
- (_e = error.request) === null || _e === void 0 ? true : delete _e._header;
67
- console.error(`Request to ${(_f = error.config) === null || _f === void 0 ? void 0 : _f.url} failed after max retries. Error`, error);
68
- },
69
- });
@@ -17,6 +17,7 @@ export declare class LoadingAdapter<ConnectorState> extends BaseAdapter<Connecto
17
17
  * an item type the connector can't load, which fails the phase.
18
18
  */
19
19
  private loadFiles;
20
+ private initializeFilesToLoad;
20
21
  private getLoaderBatches;
21
22
  private loadItem;
22
23
  /** Maps a non-success connector response to a delay or a failed report. */
@@ -1 +1 @@
1
- {"version":3,"file":"loading-adapter.d.ts","sourceRoot":"","sources":["../../../src/multithreading/adapters/loading-adapter.ts"],"names":[],"mappings":"AASA,OAAO,EAEL,wBAAwB,EAGxB,6BAA6B,EAE7B,qBAAqB,EAGrB,YAAY,EAGb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAkB,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAM7C,yFAAyF;AACzF,qBAAa,cAAc,CACzB,cAAc,CACd,SAAQ,WAAW,CAAC,cAAc,CAAC;IACnC,OAAO,CAAC,aAAa,CAAiB;IACtC,OAAO,CAAC,eAAe,CAAW;IAalC,IAAI,OAAO,IAAI,YAAY,EAAE,CAE5B;IAED,IAAI,cAAc,IAAI,MAAM,EAAE,CAE7B;IA2BK,aAAa,CAAC,EAClB,eAAe,GAChB,EAAE,qBAAqB,GAAG,OAAO,CAAC,UAAU,CAAC;IA8BxC,eAAe,CAAC,EACpB,MAAM,GACP,EAAE;QACD,MAAM,EAAE,6BAA6B,CAAC,wBAAwB,CAAC,CAAC;KACjE,GAAG,OAAO,CAAC,UAAU,CAAC;IAavB;;;;OAIG;YACW,SAAS;YAiFT,gBAAgB;YAuBhB,QAAQ;IA+HtB,2EAA2E;IAC3E,OAAO,CAAC,YAAY;YAwBN,cAAc;CA2C7B"}
1
+ {"version":3,"file":"loading-adapter.d.ts","sourceRoot":"","sources":["../../../src/multithreading/adapters/loading-adapter.ts"],"names":[],"mappings":"AASA,OAAO,EAEL,wBAAwB,EAGxB,6BAA6B,EAE7B,qBAAqB,EAGrB,YAAY,EAGb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAkB,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAM7C,yFAAyF;AACzF,qBAAa,cAAc,CACzB,cAAc,CACd,SAAQ,WAAW,CAAC,cAAc,CAAC;IACnC,OAAO,CAAC,aAAa,CAAiB;IACtC,OAAO,CAAC,eAAe,CAAW;IAalC,IAAI,OAAO,IAAI,YAAY,EAAE,CAE5B;IAED,IAAI,cAAc,IAAI,MAAM,EAAE,CAE7B;IA2BK,aAAa,CAAC,EAClB,eAAe,GAChB,EAAE,qBAAqB,GAAG,OAAO,CAAC,UAAU,CAAC;IA6BxC,eAAe,CAAC,EACpB,MAAM,GACP,EAAE;QACD,MAAM,EAAE,6BAA6B,CAAC,wBAAwB,CAAC,CAAC;KACjE,GAAG,OAAO,CAAC,UAAU,CAAC;IAYvB;;;;OAIG;YACW,SAAS;YAqFT,qBAAqB;YAarB,gBAAgB;YA+BhB,QAAQ;IA+HtB,2EAA2E;IAC3E,OAAO,CAAC,YAAY;YAwBN,cAAc;CAiD7B"}
@@ -46,9 +46,9 @@ class LoadingAdapter extends base_adapter_1.BaseAdapter {
46
46
  console.warn('No item types to load, returning.');
47
47
  return { status: 'success' };
48
48
  }
49
- this.adapterState.sdkState.fromDevRev = {
50
- filesToLoad: await this.getLoaderBatches(itemTypes),
51
- };
49
+ const failure = await this.initializeFilesToLoad(itemTypes);
50
+ if (failure)
51
+ return failure;
52
52
  }
53
53
  return this.loadFiles('data', (fileToLoad) => {
54
54
  const itemTypeToLoad = itemTypesToLoad.find((itemTypeToLoad) => itemTypeToLoad.itemType === fileToLoad.itemType);
@@ -60,9 +60,9 @@ class LoadingAdapter extends base_adapter_1.BaseAdapter {
60
60
  }
61
61
  async loadAttachments({ create, }) {
62
62
  if (this.event.payload.event_type === extraction_1.EventType.StartLoadingAttachments) {
63
- this.adapterState.sdkState.fromDevRev = {
64
- filesToLoad: await this.getLoaderBatches(['attachment']),
65
- };
63
+ const failure = await this.initializeFilesToLoad(['attachment']);
64
+ if (failure)
65
+ return failure;
66
66
  }
67
67
  return this.loadFiles('attachment', () => async (item) => this.loadAttachment({ item, create }));
68
68
  }
@@ -105,8 +105,11 @@ class LoadingAdapter extends base_adapter_1.BaseAdapter {
105
105
  console.log(`Timeout detected during ${kind} loading. Returning progress to allow continuation.`);
106
106
  return { status: 'progress' };
107
107
  }
108
- const { report, rateLimit } = await load(transformerFile[i]);
109
- if (rateLimit === null || rateLimit === void 0 ? void 0 : rateLimit.delay) {
108
+ const { report, rateLimit, error } = await load(transformerFile[i]);
109
+ if (error) {
110
+ return { status: 'error', error };
111
+ }
112
+ if (rateLimit) {
110
113
  return { status: 'delay', delaySeconds: rateLimit.delay };
111
114
  }
112
115
  if (report) {
@@ -132,6 +135,17 @@ class LoadingAdapter extends base_adapter_1.BaseAdapter {
132
135
  }
133
136
  return { status: 'success' };
134
137
  }
138
+ async initializeFilesToLoad(supportedItemTypes) {
139
+ try {
140
+ this.adapterState.sdkState.fromDevRev = {
141
+ filesToLoad: await this.getLoaderBatches(supportedItemTypes),
142
+ };
143
+ return undefined;
144
+ }
145
+ catch (error) {
146
+ return { status: 'error', error: { message: (0, logger_1.serializeError)(error) } };
147
+ }
148
+ }
135
149
  async getLoaderBatches(supportedItemTypes) {
136
150
  var _a;
137
151
  const statsFileArtifactId = (_a = this.event.payload.event_data) === null || _a === void 0 ? void 0 : _a.stats_file;
@@ -142,7 +156,10 @@ class LoadingAdapter extends base_adapter_1.BaseAdapter {
142
156
  artifactId: statsFileArtifactId,
143
157
  });
144
158
  const statsFile = response;
145
- if (statsFileError || statsFile.length === 0) {
159
+ if (statsFileError) {
160
+ throw new Error(`Failed to download loader stats file ${statsFileArtifactId}. ${(0, logger_1.serializeError)(statsFileError)}`);
161
+ }
162
+ if (statsFile.length === 0) {
146
163
  return [];
147
164
  }
148
165
  return (0, loading_adapter_helpers_1.getFilesToLoad)({ supportedItemTypes, statsFile });
@@ -267,6 +284,11 @@ class LoadingAdapter extends base_adapter_1.BaseAdapter {
267
284
  }
268
285
  catch (error) {
269
286
  console.warn('Failed to create sync mapper record.', (0, logger_1.serializeError)(error));
287
+ return {
288
+ error: {
289
+ message: 'Failed to create sync mapper record. ' + (0, logger_1.serializeError)(error),
290
+ },
291
+ };
270
292
  }
271
293
  return {
272
294
  report: {
@@ -39,8 +39,8 @@ export declare abstract class BaseState<ConnectorState> {
39
39
  init(initialState: ConnectorState): Promise<void>;
40
40
  /**
41
41
  * Normalizes fetched state into the `{ connectorState, sdkState }` envelope.
42
- * Versioned envelopes are read by `stateVersion`; unversioned ones (2.0.0
43
- * betas) by their keys; anything else is a flat v1 blob split by
42
+ * Envelopes are recognized by their keys and validate `stateVersion` when
43
+ * present; anything else is a flat v1 blob split by
44
44
  * `V1_SDK_STATE_KEYS`.
45
45
  */
46
46
  private normalizeFetchedState;
@@ -1 +1 @@
1
- {"version":3,"file":"base-state.d.ts","sourceRoot":"","sources":["../../src/state/base-state.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGnD,OAAO,EAEL,QAAQ,EAER,cAAc,EAEf,MAAM,oBAAoB,CAAC;AAE5B;;;;GAIG;AACH,8BAAsB,SAAS,CAAC,cAAc;IAC5C,SAAS,CAAC,eAAe,EAAE,cAAc,CAAC;IAC1C,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC;IAC9B,SAAS,CAAC,gBAAgB,EAAE,eAAe,CAAM;IACjD,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,QAAQ,CAAC;IAC7C,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IACvC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAS;gBAGxB,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,cAAc,CAAC,cAAc,CAAC,EACvD,eAAe,EAAE,QAAQ;IAY3B,2EAA2E;IAC3E,IAAI,KAAK,IAAI,cAAc,CAE1B;IAED,IAAI,KAAK,CAAC,KAAK,EAAE,cAAc,EAE9B;IAED,uEAAuE;IACvE,IAAI,QAAQ,IAAI,QAAQ,CAEvB;IAED,IAAI,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAE3B;IAED,IAAI,eAAe,IAAI,eAAe,CAErC;IAED;;;;OAIG;IACG,mCAAmC,CACvC,oBAAoB,CAAC,EAAE,oBAAoB,GAC1C,OAAO,CAAC,IAAI,CAAC;IAwChB;;;;OAIG;IACG,IAAI,CAAC,YAAY,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAuDvD;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IA2C7B,OAAO,CAAC,YAAY;IAepB;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IA0C1B,UAAU,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAqBjE"}
1
+ {"version":3,"file":"base-state.d.ts","sourceRoot":"","sources":["../../src/state/base-state.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGnD,OAAO,EAEL,QAAQ,EAER,cAAc,EAEf,MAAM,oBAAoB,CAAC;AAE5B;;;;GAIG;AACH,8BAAsB,SAAS,CAAC,cAAc;IAC5C,SAAS,CAAC,eAAe,EAAE,cAAc,CAAC;IAC1C,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC;IAC9B,SAAS,CAAC,gBAAgB,EAAE,eAAe,CAAM;IACjD,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,QAAQ,CAAC;IAC7C,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IACvC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAS;gBAGxB,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,cAAc,CAAC,cAAc,CAAC,EACvD,eAAe,EAAE,QAAQ;IAY3B,2EAA2E;IAC3E,IAAI,KAAK,IAAI,cAAc,CAE1B;IAED,IAAI,KAAK,CAAC,KAAK,EAAE,cAAc,EAE9B;IAED,uEAAuE;IACvE,IAAI,QAAQ,IAAI,QAAQ,CAEvB;IAED,IAAI,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAE3B;IAED,IAAI,eAAe,IAAI,eAAe,CAErC;IAED;;;;OAIG;IACG,mCAAmC,CACvC,oBAAoB,CAAC,EAAE,oBAAoB,GAC1C,OAAO,CAAC,IAAI,CAAC;IAwChB;;;;OAIG;IACG,IAAI,CAAC,YAAY,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAuDvD;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IAyC7B,OAAO,CAAC,YAAY;IAepB;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IA0C1B,UAAU,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAqBjE"}
@@ -137,8 +137,8 @@ class BaseState {
137
137
  }
138
138
  /**
139
139
  * Normalizes fetched state into the `{ connectorState, sdkState }` envelope.
140
- * Versioned envelopes are read by `stateVersion`; unversioned ones (2.0.0
141
- * betas) by their keys; anything else is a flat v1 blob split by
140
+ * Envelopes are recognized by their keys and validate `stateVersion` when
141
+ * present; anything else is a flat v1 blob split by
142
142
  * `V1_SDK_STATE_KEYS`.
143
143
  */
144
144
  normalizeFetchedState(parsed) {
@@ -146,16 +146,13 @@ class BaseState {
146
146
  throw new Error('Fetched state is not a JSON object.');
147
147
  }
148
148
  const record = parsed;
149
- if (record.stateVersion !== undefined) {
150
- if (record.stateVersion !== state_interfaces_1.STATE_VERSION) {
149
+ if ('connectorState' in record || 'sdkState' in record) {
150
+ if (record.stateVersion !== undefined &&
151
+ record.stateVersion !== state_interfaces_1.STATE_VERSION) {
151
152
  throw new Error(`Unsupported state version ${String(record.stateVersion)}; this SDK reads version ${state_interfaces_1.STATE_VERSION}.`);
152
153
  }
153
154
  return this.readEnvelope(record);
154
155
  }
155
- // Envelopes written by 2.0.0 betas carry no version marker.
156
- if ('connectorState' in record || 'sdkState' in record) {
157
- return this.readEnvelope(record);
158
- }
159
156
  // Legacy flat v1 blob: split known SDK keys out of the connector state.
160
157
  const connectorState = {};
161
158
  const sdkState = {};
@@ -1 +1 @@
1
- {"version":3,"file":"extraction-state.d.ts","sourceRoot":"","sources":["../../src/state/extraction-state.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAsB,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGxE,sGAAsG;AACtG,qBAAa,eAAe,CAAC,cAAc,CAAE,SAAQ,SAAS,CAAC,cAAc,CAAC;gBAChE,MAAM,EAAE,cAAc,CAAC,cAAc,CAAC;IAIlD;;;;OAIG;IACH,uBAAuB,IAAI,IAAI;CAyHhC;AAED,wBAAsB,qBAAqB,CAAC,cAAc,EAAE,EAC1D,KAAK,EACL,YAAY,EACZ,oBAAoB,EACpB,OAAO,GACR,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,CAkB3E"}
1
+ {"version":3,"file":"extraction-state.d.ts","sourceRoot":"","sources":["../../src/state/extraction-state.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAsB,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGxE,sGAAsG;AACtG,qBAAa,eAAe,CAAC,cAAc,CAAE,SAAQ,SAAS,CAAC,cAAc,CAAC;gBAChE,MAAM,EAAE,cAAc,CAAC,cAAc,CAAC;IAIlD;;;;OAIG;IACH,uBAAuB,IAAI,IAAI;CA4HhC;AAED,wBAAsB,qBAAqB,CAAC,cAAc,EAAE,EAC1D,KAAK,EACL,YAAY,EACZ,oBAAoB,EACpB,OAAO,GACR,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,CAkB3E"}
@@ -21,6 +21,7 @@ class ExtractionState extends base_state_1.BaseState {
21
21
  * all other events reuse those cached boundaries. Validates extract_from < extract_to.
22
22
  */
23
23
  resolveExtractionWindow() {
24
+ var _a, _b;
24
25
  const sdkState = this.sdkState;
25
26
  const eventContext = this.event.payload.event_context;
26
27
  const overrideExtractFrom = (value) => {
@@ -29,10 +30,15 @@ class ExtractionState extends base_state_1.BaseState {
29
30
  }
30
31
  eventContext.extract_from = value;
31
32
  };
32
- if (this.event.payload.event_type === extraction_1.EventType.StartExtractingData &&
33
- !sdkState.lastSyncStarted) {
34
- sdkState.lastSyncStarted = new Date().toISOString();
35
- console.log(`Setting lastSyncStarted to ${sdkState.lastSyncStarted}.`);
33
+ if (this.event.payload.event_type === extraction_1.EventType.StartExtractingData) {
34
+ if (!sdkState.lastSyncStarted) {
35
+ sdkState.lastSyncStarted = new Date().toISOString();
36
+ console.log(`Setting lastSyncStarted to ${sdkState.lastSyncStarted}.`);
37
+ }
38
+ // A sync that failed before attachments must not leak its SSOR records into this one.
39
+ if ((_b = (_a = sdkState.toDevRev) === null || _a === void 0 ? void 0 : _a.deferredSsorArtifacts) === null || _b === void 0 ? void 0 : _b.length) {
40
+ sdkState.toDevRev.deferredSsorArtifacts = [];
41
+ }
36
42
  }
37
43
  if (this.event.payload.event_type === extraction_1.EventType.StartExtractingMetadata) {
38
44
  const timeFields = [
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Error codes the platform reacts to (e.g. stopping periodic syncs). Set them
3
- * on `ErrorRecord.code`; the platform matches the code exactly, so the SDK
4
- * sends it as the whole wire message.
2
+ * Platform-recognized error codes (CommonError), mapped by the snap-in manager
3
+ * in `internal/common/errors_snapin.go`. Set them on `ErrorRecord.code`; the SDK
4
+ * sends exactly `ERROR_CODE=<code>` as the wire message.
5
5
  */
6
6
  export declare enum AirSyncErrorCode {
7
7
  EXTERNAL_SYNC_UNIT_DELETED = "EXTERNAL_SYNC_UNIT_DELETED",
@@ -5,9 +5,9 @@ exports.formatErrorCode = formatErrorCode;
5
5
  const ERROR_PREFIX = 'ERROR_CODE';
6
6
  const ERROR_DELIMITER = '=';
7
7
  /**
8
- * Error codes the platform reacts to (e.g. stopping periodic syncs). Set them
9
- * on `ErrorRecord.code`; the platform matches the code exactly, so the SDK
10
- * sends it as the whole wire message.
8
+ * Platform-recognized error codes (CommonError), mapped by the snap-in manager
9
+ * in `internal/common/errors_snapin.go`. Set them on `ErrorRecord.code`; the SDK
10
+ * sends exactly `ERROR_CODE=<code>` as the wire message.
11
11
  */
12
12
  var AirSyncErrorCode;
13
13
  (function (AirSyncErrorCode) {
@@ -109,10 +109,6 @@ export interface EventContext {
109
109
  mode: string;
110
110
  request_id: string;
111
111
  request_id_adaas: string;
112
- /** @deprecated Never read by the SDK; kept because connectors still branch on it. */
113
- reset_extraction?: boolean;
114
- /** @deprecated Use extraction_start_time/extraction_end_time (resolved into extract_from/extract_to). */
115
- reset_extract_from?: boolean;
116
112
  run_id: string;
117
113
  sequence_version: string;
118
114
  snap_in_slug: string;
@@ -1 +1 @@
1
- {"version":3,"file":"extraction.d.ts","sourceRoot":"","sources":["../../src/types/extraction.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"extraction.d.ts","sourceRoot":"","sources":["../../src/types/extraction.ts"],"names":[],"mappings":"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"}
package/docs/MIGRATION.md CHANGED
@@ -9,11 +9,14 @@ own:
9
9
  It ships in the package at `node_modules/@devrev/airsync-sdk/docs/MIGRATION.md`
10
10
  (read it from disk; the `exports` map only blocks `import`/`require`). Before
11
11
  v2 is installed, use
12
- `https://raw.githubusercontent.com/devrev/adaas-sdk/v2/docs/MIGRATION.md`.
12
+ `https://raw.githubusercontent.com/devrev/adaas-sdk/v2/docs/MIGRATION.md`
13
+ (use `main` after GA). The installed guide always takes precedence.
13
14
 
14
- **The wire protocol is unchanged.** Event payloads, routes, headers, the
15
- artifact flow and every event-type and `ERROR_CODE=…` string are identical to
16
- v1. Only the TypeScript API changed, all at once, with no compatibility shims.
15
+ **The modern wire protocol is unchanged.** Event names, routes, headers,
16
+ artifact formats and `ERROR_CODE=…` strings remain compatible with platforms
17
+ that send modern events. Legacy `EXTRACTION_*` event names are intentionally
18
+ unsupported. The public TypeScript API changes all at once, without deprecated
19
+ aliases; runtime differences are described below.
17
20
 
18
21
  ---
19
22
 
@@ -21,7 +24,8 @@ v1. Only the TypeScript API changed, all at once, with no compatibility shims.
21
24
 
22
25
  **Rules.** Work autonomously; when a rewrite is ambiguous, pick the option
23
26
  that preserves runtime behavior and note it in `MIGRATION_REVIEW.md`. Migrate
24
- source **and** tests. Never change a runtime string value. Don't add comments
27
+ source **and** tests. Preserve runtime string values except the documented
28
+ legacy event-string replacements in §3 and §11. Don't add comments
25
29
  about the migration; the `// v1` / `// v2` labels here are reading aids. Leave
26
30
  no compile errors or orphaned imports. A section with no hits is a no-op.
27
31
  Existing comments and commented-out code that describe v1 behavior (`emit`,
@@ -30,12 +34,17 @@ v2; templates are copied into new connectors, so stale comments spread.
30
34
 
31
35
  1. **Locate the package.** Find the `package.json` that depends on
32
36
  `@devrev/ts-adaas` (generated connectors keep it in `code/`). Run everything
33
- from there. If it already depends on `@devrev/airsync-sdk` only, report
34
- "already on v2" and stop.
37
+ from there. If it already depends on `@devrev/airsync-sdk`, inspect its
38
+ installed version and migration review. Early betas still need the
39
+ changes under **Rare cases** below; upgrade to the selected v2 version
40
+ and verify source, tests and local runners against this guide. Stop only
41
+ when the current-contract migration and verification are complete.
35
42
  2. **Start from green latest v1.** If behind the latest stable 1.x, upgrade and
36
43
  apply the release notes of every release in between that mentions a
37
44
  migration (the last ones were 1.16.0–1.18.0), then get tsc/lint/build/test
38
- green on v1. Record failures that remain as **Pre-existing**.
45
+ green on v1. If the upgrade alone breaks tsc with axios type mismatches,
46
+ bump the connector's `axios` to the version that SDK release depends on.
47
+ Record failures that remain as **Pre-existing**.
39
48
  3. **Install v2.**
40
49
  ```bash
41
50
  npm uninstall @devrev/ts-adaas
@@ -51,15 +60,19 @@ v2; templates are copied into new connectors, so stale comments spread.
51
60
  5. **Verify**: `npm install && npx tsc --noEmit && npm run lint && npm run build && npm test`.
52
61
  If tsconfig excludes folders the connector still runs (`test/`, a local
53
62
  runner), type-check them too: use the repo's `tsconfig.test.json` if it has
54
- one, otherwise a temporary tsconfig that extends `tsconfig.json` with
55
- `"include": ["src", "test"]` and `npx tsc --noEmit -p` it. Fix and rerun,
63
+ one, otherwise a temporary tsconfig that extends `tsconfig.json` and
64
+ overrides `"include": ["src", "test"]`, `"exclude": ["node_modules", "dist"]`,
65
+ `"rootDir": "."` and `"noEmit": true` (the base `exclude` and `rootDir` still
66
+ apply otherwise), then `npx tsc -p` it. Fix and rerun,
56
67
  at most 4 attempts; the migration must add no new failures compared to
57
68
  step 2.
58
69
  6. **Sweep.** This must return nothing except legitimate hits (an
59
70
  `EventEmitter.emit`, the connector's own `axiosClient` from §9,
60
- `@devrev/typescript-sdk` in `package.json` from §1, `git config --local`):
71
+ `@devrev/typescript-sdk` in `package.json` from §1, `git config --local`,
72
+ legacy event names in fields the SDK doesn't read, such as
73
+ `event_type_adaas`):
61
74
  ```bash
62
- grep -rnE "@devrev/ts-adaas|airsync-sdk/dist|\bprocessTask\b|WorkerAdapter|\.emit\(|hasWorkerEmitted|Airdrop(Event|Message)|axiosClient|(format|serialize)AxiosError|workerPath:|overridenOptions|skipConfirmation|isLocalDevelopment|--local|-- local\b|@devrev/typescript-sdk|(Extractor|Loader)EventType|ExtractionCommonError|ERROR_CODE=|sdkState|onUpload|uploadedArtifacts|currentEventDataLength|EXTRACTION_(DATA|METADATA|ATTACHMENTS|EXTERNAL_SYNC_UNITS)_" \
75
+ grep -rnE "@devrev/ts-adaas|airsync-sdk/dist|\bprocessTask\b|\bWorkerAdapter\b|\.emit\(|hasWorkerEmitted|\bAirdrop(Event|Message)\b|axiosClient|(format|serialize)AxiosError|workerPath:|overridenOptions|skipConfirmation|isLocalDevelopment|--local|-- local\b|@devrev/typescript-sdk|(Extractor|Loader)EventType|ExtractionCommonError|ERROR_CODE=|reset_(extraction|extract_from)|sdkState|onUpload|uploadedArtifacts|currentEventDataLength|EXTRACTION_(DATA|METADATA|ATTACHMENTS|EXTERNAL_SYNC_UNITS)_" \
63
76
  --include='*.ts' --include='*.js' --include='*.json' --include='*.yml' --include='*.yaml' --include='*.md' --include='*.mdc' --include='*.sh' . \
64
77
  | grep -vE 'node_modules|/dist/|/coverage/|package-lock.json|MIGRATION_REVIEW.md'
65
78
  ```
@@ -80,7 +93,7 @@ v2; templates are copied into new connectors, so stale comments spread.
80
93
  helpers (§4), paths that emitted nothing (§4), `onTimeout` bodies kept (§4),
81
94
  delay values that look like milliseconds or headers (§4), the cursor decision
82
95
  (§8), ESU repo rewrites (§7), mapper error handling (§10), and a v1 baseline
83
- upgrade.
96
+ upgrade. Record the exact installed versions.
84
97
  ```markdown
85
98
  # v2 Migration Review
86
99
  Migrated `@devrev/ts-adaas` 1.20.2 → `@devrev/airsync-sdk` 2.0.0.
@@ -134,7 +147,10 @@ The shapes are unchanged. `AirSyncEvent.context` now also declares `user_id`,
134
147
  `payload.event_context`). Delete a hand-rolled context type that added these
135
148
  (e.g. `interface CustomAirdropEvent extends AirdropEvent { context: CustomContext }`):
136
149
  a narrower `context` no longer satisfies `AirSyncEvent`. Keep only the fields
137
- the SDK type lacks.
150
+ the SDK type lacks. These fields are required, so typed mock events must set
151
+ them. `execution_metadata` is typed `{ devrev_endpoint }`; a custom type that
152
+ widened it with `@devrev/typescript-sdk` fields goes too, along with mock values
153
+ for fields nothing reads.
138
154
 
139
155
  Deprecated `EventContext` aliases are removed. Use the current names:
140
156
 
@@ -147,12 +163,18 @@ Deprecated `EventContext` aliases are removed. Use the current names:
147
163
  | `sync_run`, `sync_run_id` | `run_id` |
148
164
  | `uuid` | `request_id_adaas` |
149
165
 
150
- Rename these keys in fixture and test `event_context` objects too. Untyped
166
+ Rename these keys in fixture and test `event_context` objects too. When an
167
+ object already has the new key (or has two old keys for one new one, like
168
+ `dev_user` and `dev_user_id`), keep the existing new-name value, otherwise the
169
+ first old one, and drop the rest. Untyped
151
170
  JSON still compiles, but the SDK reads only the current names (e.g. state
152
171
  requests carry `request_id_adaas`).
153
172
 
154
- `reset_extraction` and `reset_extract_from` remain (the SDK never read them);
155
- leave connector logic that uses them alone.
173
+ `reset_extraction` and `reset_extract_from` are removed. Delete these keys
174
+ from fixtures and remove connector branches that read them. The SDK never
175
+ interpreted either flag. Configure backfills through the platform's
176
+ `extraction_start_time` / `extraction_end_time`; connectors read the
177
+ SDK-resolved `extract_from` / `extract_to` for the sync window (§8).
156
178
 
157
179
  ## 3. `spawn`
158
180
 
@@ -246,14 +268,14 @@ processExtractionTask({
246
268
  |----|----|
247
269
  | `emit(XxxDone)` | `return { status: 'success' }` |
248
270
  | `emit(XxxProgress, { progress })` | `return { status: 'progress' }` |
249
- | `emit(XxxDelayed, { delay })` | `return { status: 'delay', delaySeconds: delay }` — keep the same number; the platform always read it as seconds. If it is clearly milliseconds or a raw `Retry-After` header, keep the behavior (`Number(header)`) and flag it in the review |
271
+ | `emit(XxxDelayed, { delay })` | `return { status: 'delay', delaySeconds: delay }` — keep the same number; the platform always read it as seconds. A raw `Retry-After` header stays `Number(header)`. If it is clearly milliseconds (a `*_MS` constant, a value in the thousands, "ms" in the message), keep the number, flag it and list it under **Unresolved**: v1 waited that many seconds too, and fixing it changes behavior |
250
272
  | `emit(XxxDelayed)` with no `delay` | `delaySeconds` is required; use the connector's existing default retry constant, else `0` (what v1 effectively sent), and flag it |
251
273
  | `emit(XxxError, { error })` | `return { status: 'error', error }` — `error` is required; fall back to `{ message: '<phase> failed' }` |
252
274
  | `emit(XxxDone, { error })` (finished with warnings) | `return { status: 'success' }` and log the error. Returning `error` would fail the phase |
253
275
  | `emit(ExternalSyncUnitExtractionDone, { external_sync_units })` | push to a repo, then `success` (§7) |
254
276
  | `emit(MetadataExtractionDone, { pre_extraction_item_counts })` | `adapter.preExtractionItemCounts = counts`, then `success` |
255
277
  | a path that **emitted nothing** (a `catch` that only logs, a branch that falls through) | `{ status: 'error', error: { message } }`, or rethrow. In v1 the SDK reported these as a phase error ("Worker exited without emitting"); never turn them into `success` or `progress` |
256
- | any `emit(XxxDone)` after `loadItemTypes` / `loadAttachments` / `streamAttachments`, guarded (`!adapter.hasWorkerEmitted && !adapter.isTimeout`) or not | `return adapter.loadItemTypes(...)` (or the other call). Never discard their result and return `success`: v1 emitted their `delay` / `error` itself. Drop the guard and any module-level "already emitted" flags |
278
+ | any `emit(XxxDone)` after `loadItemTypes` / `loadAttachments` / `streamAttachments`, guarded (`!adapter.hasWorkerEmitted && !adapter.isTimeout`) or not | `return adapter.loadItemTypes(...)` (or the other call). Never discard their result and return `success`: v1 emitted their `delay` / `error` itself. Drop the guard and any module-level "already emitted" flags. If v1 did more work after the call and then emitted `Done` with an `error`, return the call's result and log that error |
257
279
 
258
280
  In non-resumable phases (external sync units, state deletion), `progress` and
259
281
  `delay` become `*Error`.
@@ -282,7 +304,16 @@ If a helper **emitted and then kept going** (no throw), the caller often
282
304
  emitted again later, e.g. `DataExtractionDone` after the loop, and v1 dropped
283
305
  every emit after the first. Record the first result the same way, stop the
284
306
  work that followed it (return out of the loop or extractor), and return it
285
- from the task. Unawaited emits inside loops count too.
307
+ from the task. Unawaited emits inside loops count too. When the emitting helper
308
+ is deep in the call stack, throw an error class that carries the `TaskResult`
309
+ instead (`class TaskResultError extends Error { constructor(readonly result: TaskResult) { super(); } }`),
310
+ stop the extractor, and return `e.result` from the task's outermost `catch`.
311
+ A free-function handler that must keep only the first result stores it per
312
+ adapter (`WeakMap<adapter, TaskResult>`) and the task reads it back.
313
+
314
+ A helper that returned `{ delay?, error? }` and emitted only when one was set
315
+ needs an explicit result when neither is set: `success` if the caller carried
316
+ on, otherwise `error`.
286
317
 
287
318
  If a helper (often the HTTP client's 429 handler) **emitted and then threw a
288
319
  sentinel error** that call sites rethrow, keep the throw, drop the emit, and map
@@ -321,6 +352,11 @@ helpers, assert on the return value.
321
352
  custom error. Make its body safe to run after a completed task. A custom
322
353
  "Lambda timeout" `onTimeout` on a task that emits on every path is
323
354
  deleted; v1 never ran it.
355
+ - `onTimeout` runs only after the task has returned, in v1 and v2, so
356
+ cleanup there (cancelling a rate limiter, aborting requests) never
357
+ interrupted a stuck task. Check the public `adapter.isTimeout` between
358
+ batches and perform any needed cancellation inside the task.
359
+ `timeoutSignal` is internal and unavailable to connector code.
324
360
  - Don't call `process.exit()` or `postState()` in `onTimeout`; the SDK saves
325
361
  state and exits.
326
362
 
@@ -331,10 +367,16 @@ now wrong**, and `Boolean(await repo.push(x))` or `if (!(await …push(x)))`
331
367
  compiles but is always falsy. Make wrappers `await repo.push(x)` and return
332
368
  `true` (or `void`). Keep a top-level `try/catch` that maps an error to `delay`
333
369
  (e.g. a thrown 429); otherwise it's only needed for a custom message.
370
+ Find every unawaited `repo.push()` / `repo.upload()`, including calls in
371
+ helpers and loops, and await it before advancing the cursor or returning.
372
+ An unhandled upload rejection can bypass the task's error handling.
334
373
  `loadItemTypes` and `loadAttachments` don't throw: a `create` / `update` that
335
374
  throws becomes their `error` result, so a 429 must be returned as
336
375
  `{ status: 'delay', delaySeconds }` from the callback (§6). A `catch` around
337
376
  them that checks `isAxiosError(e) && status === 429` is dead; delete it.
377
+ Failures fetching loader stats or reading/writing sync mapper records fail
378
+ the phase and retain the current cursor. A connector callback returning
379
+ `status: 'error'` still counts that item as failed and continues.
338
380
 
339
381
  `ProcessTaskInterface<T>` and `TaskAdapterInterface<T>` now take the
340
382
  **adapter** type: `ProcessTaskInterface<ExtractionAdapter<State>>`, not
@@ -355,7 +397,9 @@ async function extractList(adapter: ExtractionAdapter<State>) { ... }
355
397
  | `event`, `state`, `mappers`, `postState`, `uploadArtifact`, `downloadArtifact`, `isTimeout`, `extractionScope` | both |
356
398
 
357
399
  - The adapters and `Repo` are **type-only**: `new ExtractionAdapter(...)` and
358
- `class X extends LoadingAdapter<S>` don't compile; `interface X extends …`
400
+ `class X extends LoadingAdapter<S>` or `extends Repo` (test doubles that
401
+ subclassed `Repo` through `dist/`) don't compile; use a plain object with
402
+ the methods the code calls. `interface X extends …`
359
403
  does. SDK internals (`emit`, `sdkState`, `options`, constructors, …) aren't
360
404
  public. `isTimeout` and `artifacts` are read-only.
361
405
  - `adapter.mappers` works in extraction as in v1; keep those calls and only
@@ -423,7 +467,9 @@ return { status: 'success' }; // was a bare `return;`
423
467
  as `skip` are dropped; every `success` creates or updates a mapper record.
424
468
  - Shared helpers typed as these responses change too. Callers that read
425
469
  `result.delay` or interpolate `${result.error}` (now an object) switch on
426
- `result.status`.
470
+ `result.status`. A helper that only builds delays and errors returns the
471
+ narrowed type (`Extract<…, { status: 'delay' | 'error' }>`), so callers and
472
+ tests can read `delaySeconds` and `error` without a check.
427
473
  - An error `code` returned from the stream callback is only logged; the pool
428
474
  skips that attachment.
429
475
  - `httpStream` is typed `HttpStreamResponse` (`{ data, headers }`); an axios
@@ -439,6 +485,14 @@ its state fields and tests. Workarounds typically override the
439
485
  `ssor_attachment` repo's `onUpload`, splice `uploadedArtifacts`, adjust
440
486
  `currentEventDataLength`, or stash artifact refs in state.
441
487
 
488
+ - A worker whose only job was re-injecting those refs returns
489
+ `{ status: 'success' }` (or its remaining work); keep its phase wired.
490
+ - A connector's own `{ itemType: 'ssor_attachment' }` repo entry can stay.
491
+ - Tests that mocked the deep `Uploader` use adapter doubles instead:
492
+ `{ uploadArtifact: jest.fn(), downloadArtifact: jest.fn() }`.
493
+ - If the workaround stashed refs in connector state, syncs between data done and
494
+ attachments done lose them after the upgrade; drain them first.
495
+
442
496
  ## 7. External sync units go through a repo
443
497
 
444
498
  `EventData.external_sync_units` is removed. Push them to a repo:
@@ -466,9 +520,14 @@ the emit.
466
520
  - **Persisted state** becomes `{ stateVersion: 2, connectorState, sdkState }`.
467
521
  A v1 blob is migrated automatically on first read: known SDK keys move to
468
522
  `sdkState` and everything else becomes connector state. **Rolling back to v1
469
- after a v2 worker has run is not supported**; drain or reset syncs first. A
523
+ after a v2 worker has persisted state is not supported**. A drained sync
524
+ still has a v2 envelope: recovery needs a verified saved v1 state together
525
+ with the v1 connector, or an explicit reset/reinitialization and reimport.
526
+ Upgrade between runs, after v1 workers have finished. A
470
527
  v1 state with a top-level key named `connectorState` or `sdkState` is
471
- misread; rename it before upgrading.
528
+ misread. Rename it in a staged v1 deployment and migrate its persisted
529
+ value before upgrading, or explicitly reset/reimport. A top-level
530
+ connector-owned `stateVersion` in a flat v1 blob is preserved.
472
531
  - **Sync window**: read
473
532
  `adapter.event.payload.event_context.extract_from` / `extract_to`. The SDK
474
533
  resolves them from the platform's time values, or from the last successful
@@ -479,17 +538,34 @@ the emit.
479
538
  **`lastSyncStarted` / `lastSuccessfulSyncStarted`: rename or repoint.**
480
539
  Getting this wrong compiles but silently breaks incremental sync.
481
540
 
482
- - **Not in the connector's `State` interface** (it came from the SDK): delete
483
- writes, and repoint reads to `extract_from`.
541
+ These rules cover **top-level** state keys only; the v1 migration moves only
542
+ those. A cursor nested in the connector's own object (`state.extractor.lastSuccessfulSyncStarted`)
543
+ is connector-owned: leave it alone.
544
+
545
+ - **Not in the connector's `State` interface**, or declared but never written
546
+ by the connector (it came from the SDK): delete writes, and repoint reads to
547
+ `extract_from`.
484
548
  - **Declared and used as the connector's own cursor** (derived from data, or
485
549
  read alongside `extract_from`): **rename** it (e.g. →
486
- `lastSuccessfulWindowStart`) everywhere, including fixtures. Otherwise the v1
487
- auto-migration moves it into SDK state and the connector loses it.
550
+ `lastSuccessfulWindowStart`) everywhere, including fixtures. Before
551
+ deploying v2, use a staged v1 deployment to copy the persisted value into
552
+ the new connector key, retaining the legacy key for v1 SDK bookkeeping.
553
+ Alternatively, explicitly reset/reimport. A source-only rename does not
554
+ migrate persisted data: the v1 auto-migration moves the old key into SDK
555
+ state and leaves the new connector key unset.
488
556
  - **Declared but only mirrors the SDK**: its only writes are "now" when data
489
557
  extraction starts and a copy on finish. Treat it as not declared, **even if
490
558
  it is read next to `extract_from`**. Renaming would leave it empty after the
491
559
  upgrade, because the v1 value moves into SDK state.
492
560
 
561
+ After repointing, branches that chose between the two
562
+ (`reset_extract_from ? extract_from : lastSuccessfulSyncStarted`) read the same
563
+ value; collapse them and drop the `reset_extract_from` read. If the connector
564
+ already used `extract_from` for something else (e.g. a skip filter) and the
565
+ cursor for a second window (e.g. "re-emit and bump the floor"), repointing
566
+ merges the two, so code below the window may become dead. Flag that low
567
+ confidence.
568
+
493
569
  `extract_from` equals the last successful sync start only when the platform
494
570
  sends no time window. If a repointed read feeds logic beyond "skip items older
495
571
  than this" (e.g. distinguishing first syncs), flag it as low confidence; there
@@ -514,7 +590,7 @@ import axios from 'axios';
514
590
  import axiosRetry from 'axios-retry';
515
591
 
516
592
  export const axiosClient = axios.create();
517
- axiosRetry(axiosClient, {
593
+ axiosRetry(axiosClient as Parameters<typeof axiosRetry>[0], {
518
594
  retries: 5,
519
595
  retryDelay: (retryCount, error) => axiosRetry.exponentialDelay(retryCount, error, 1000),
520
596
  retryCondition: (error) =>
@@ -528,6 +604,9 @@ axiosRetry(axiosClient, {
528
604
  });
529
605
  ```
530
606
 
607
+ The cast is needed under ts-jest, which can resolve axios's `.d.ts` and
608
+ `.d.cts` to different types.
609
+
531
610
  A deep import of the SDK's internal client (`dist/http/axios-client-internal`)
532
611
  relied on more: a 30 s timeout, retries of 429s that send `Retry-After` (waiting
533
612
  that long) and of `ECONNABORTED`. Reproduce what the connector depends on with
@@ -623,8 +702,10 @@ in minor versions, so give `switch` statements over it a `default`.
623
702
 
624
703
  ## 12. Error codes
625
704
 
626
- `ExtractionCommonError` is now `AirSyncErrorCode`. Its values are bare codes,
627
- and you set them on `error.code`:
705
+ `ExtractionCommonError` is now `AirSyncErrorCode`. These remain the platform's
706
+ known common error codes (`CommonError`), mapped by the snap-in manager in
707
+ `internal/common/errors_snapin.go`. Their values are bare codes, and you set
708
+ them on `error.code`:
628
709
 
629
710
  ```ts
630
711
  // v1
@@ -636,9 +717,11 @@ return {
636
717
  };
637
718
  ```
638
719
 
639
- The platform only recognizes a code when the message is exactly
640
- `ERROR_CODE=<code>`, so the SDK sends just that and logs your `message`. Write
641
- a useful `message`. Raw `'ERROR_CODE=…'` strings and connector helpers that
720
+ `error.code` is an SDK input field. Before sending the callback, the SDK
721
+ converts it into `event_data.error.message = 'ERROR_CODE=<code>'` and omits
722
+ the `code` property. The backend continues reading the common error from
723
+ `error.message`; your human-readable `message` goes to the logs. Write a
724
+ useful `message`. Raw `'ERROR_CODE=…'` strings and connector helpers that
642
725
  return them (`HISTORICAL_DONE`, `authErrorCode(e)`) still work at runtime but
643
726
  are migrated too: make the helper return `AirSyncErrorCode | undefined`, set it
644
727
  as `code`, and update tests that pin the literal. The wire string doesn't
@@ -674,7 +757,9 @@ change.
674
757
  - For a deleted `onTimeout`, drop the tests of its body and assert it's
675
758
  `undefined`. A factory like `processExtractionTask: (_config) => jest.fn()`
676
759
  discards the config; use `processExtractionTask: jest.fn()` and read
677
- `mocked.mock.calls[0][0].onTimeout`. Tests of a deleted SSOR workaround go with it.
760
+ `mocked.mock.calls[0][0].onTimeout`. Capture it in a module-level `const`
761
+ right after importing the worker: `jest.clearAllMocks()` in a `beforeEach`
762
+ wipes the calls. Tests of a deleted SSOR workaround go with it.
678
763
 
679
764
  ## 14. Smaller changes
680
765
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devrev/airsync-sdk",
3
- "version": "2.0.0-beta.10",
3
+ "version": "2.0.0-beta.12",
4
4
  "description": "Typescript SDK for building AirSync snap-ins on the DevRev platform.",
5
5
  "type": "commonjs",
6
6
  "main": "./dist/index.js",
@@ -26,7 +26,7 @@
26
26
  },
27
27
  "repository": {
28
28
  "type": "git",
29
- "url": "git+https://github.com/devrev/adaas-sdk.git"
29
+ "url": "git+https://github.com/devrev/airsync-sdk.git"
30
30
  },
31
31
  "publishConfig": {
32
32
  "registry": "https://registry.npmjs.org"