@jsforce/jsforce-node 3.10.13 → 3.10.14

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/lib/VERSION.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- declare const _default: "3.10.13";
1
+ declare const _default: "3.10.14";
2
2
  export default _default;
package/lib/VERSION.js CHANGED
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = '3.10.13';
3
+ exports.default = '3.10.14';
@@ -163,8 +163,8 @@ export declare class AsyncResultLocator<S extends Schema, R extends {} = AsyncRe
163
163
  */
164
164
  export declare class RetrieveResultLocator<S extends Schema> extends AsyncResultLocator<S, RetrieveResult> {
165
165
  /**
166
- * Check and wait until the async request becomes in completed status,
167
- * and retrieve the result data.
166
+ * Poll checkRetrieveStatus() until the retrieve operation completes,
167
+ * then return the RetrieveResult.
168
168
  */
169
169
  complete(): Promise<RetrieveResult>;
170
170
  /**
@@ -183,8 +183,8 @@ export declare class RetrieveResultLocator<S extends Schema> extends AsyncResult
183
183
  */
184
184
  export declare class DeployResultLocator<S extends Schema> extends AsyncResultLocator<S, DeployResult> {
185
185
  /**
186
- * Check and wait until the async request becomes in completed status,
187
- * and retrieve the result data.
186
+ * Poll checkDeployStatus() until the deploy operation completes,
187
+ * then return the DeployResult.
188
188
  */
189
189
  complete(includeDetails?: boolean): Promise<DeployResult>;
190
190
  }
@@ -356,12 +356,43 @@ exports.AsyncResultLocator = AsyncResultLocator;
356
356
  */
357
357
  class RetrieveResultLocator extends AsyncResultLocator {
358
358
  /**
359
- * Check and wait until the async request becomes in completed status,
360
- * and retrieve the result data.
359
+ * Poll checkRetrieveStatus() until the retrieve operation completes,
360
+ * then return the RetrieveResult.
361
361
  */
362
362
  async complete() {
363
- const result = await super.complete();
364
- return this._meta.checkRetrieveStatus(result.id);
363
+ if (!this._id) {
364
+ const asyncResult = await this._promise;
365
+ this._id = asyncResult.id;
366
+ }
367
+ const id = this._id;
368
+ return new Promise((resolve, reject) => {
369
+ const startTime = new Date().getTime();
370
+ const poll = async () => {
371
+ try {
372
+ const now = new Date().getTime();
373
+ if (startTime + this._meta.pollTimeout < now) {
374
+ const err = new Error('Polling time out. Retrieve operation is not completed.');
375
+ this.emit('error', err);
376
+ reject(err);
377
+ return;
378
+ }
379
+ const result = await this._meta.checkRetrieveStatus(id);
380
+ if (result.done) {
381
+ this.emit('complete', result);
382
+ resolve(result);
383
+ }
384
+ else {
385
+ this.emit('progress', result);
386
+ setTimeout(poll, this._meta.pollInterval);
387
+ }
388
+ }
389
+ catch (err) {
390
+ this.emit('error', err);
391
+ reject(err);
392
+ }
393
+ };
394
+ setTimeout(poll, this._meta.pollInterval);
395
+ });
365
396
  }
366
397
  /**
367
398
  * Change the retrieved result to Node.js readable stream
@@ -399,12 +430,43 @@ exports.RetrieveResultLocator = RetrieveResultLocator;
399
430
  */
400
431
  class DeployResultLocator extends AsyncResultLocator {
401
432
  /**
402
- * Check and wait until the async request becomes in completed status,
403
- * and retrieve the result data.
433
+ * Poll checkDeployStatus() until the deploy operation completes,
434
+ * then return the DeployResult.
404
435
  */
405
436
  async complete(includeDetails) {
406
- const result = await super.complete();
407
- return this._meta.checkDeployStatus(result.id, includeDetails);
437
+ if (!this._id) {
438
+ const asyncResult = await this._promise;
439
+ this._id = asyncResult.id;
440
+ }
441
+ const id = this._id;
442
+ return new Promise((resolve, reject) => {
443
+ const startTime = new Date().getTime();
444
+ const poll = async () => {
445
+ try {
446
+ const now = new Date().getTime();
447
+ if (startTime + this._meta.pollTimeout < now) {
448
+ const err = new Error('Polling time out. Deploy operation is not completed.');
449
+ this.emit('error', err);
450
+ reject(err);
451
+ return;
452
+ }
453
+ const result = await this._meta.checkDeployStatus(id, includeDetails);
454
+ if (result.done) {
455
+ this.emit('complete', result);
456
+ resolve(result);
457
+ }
458
+ else {
459
+ this.emit('progress', result);
460
+ setTimeout(poll, this._meta.pollInterval);
461
+ }
462
+ }
463
+ catch (err) {
464
+ this.emit('error', err);
465
+ reject(err);
466
+ }
467
+ };
468
+ setTimeout(poll, this._meta.pollInterval);
469
+ });
408
470
  }
409
471
  }
410
472
  exports.DeployResultLocator = DeployResultLocator;
package/lib/http-api.js CHANGED
@@ -303,6 +303,11 @@ class HttpApi extends events_1.EventEmitter {
303
303
  this._logger.debug(`html response.body: ${response.body}`);
304
304
  return new HttpApiError(`HTTP response contains html content.
305
305
  Check that the org exists and can be reached.
306
+
307
+ HTTP status code: ${response.statusCode}.
308
+ REST API Status Codes and Error Responses:
309
+ https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/errorcodes.htm
310
+
306
311
  See \`error.data\` for the full html response.`, error.errorCode, error.message);
307
312
  }
308
313
  return error instanceof HttpApiError
package/lib/request.js CHANGED
@@ -54,6 +54,7 @@ async function startFetchRequest(request, options, input, output, emitter, count
54
54
  const { url, body, ...rrequest } = request;
55
55
  const controller = new AbortController();
56
56
  let retryCount = 0;
57
+ let retry420Count = 0;
57
58
  const retryOpts = {
58
59
  statusCodes: options.retry?.statusCodes ?? [420, 429, 500, 502, 503, 504],
59
60
  maxRetries: options.retry?.maxRetries ?? 5,
@@ -82,7 +83,14 @@ async function startFetchRequest(request, options, input, output, emitter, count
82
83
  if (!retryOpts.methods.includes(request.method))
83
84
  return false;
84
85
  if (resOrErr instanceof node_fetch_1.Response) {
85
- if (retryOpts.statusCodes.includes(resOrErr.status)) {
86
+ // REST API status codes: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/errorcodes.htm
87
+ //
88
+ // Deleted/expired scratch orgs return 420 and causes a long delay on all requests due to the retry with exponential backoff.
89
+ // We still want to retry on 420 (Metadata API requests sometimes return it) so here we'll limit to a maximum of 2 retries.
90
+ if (resOrErr.status === 420) {
91
+ return retry420Count < 2;
92
+ }
93
+ else if (retryOpts.statusCodes.includes(resOrErr.status)) {
86
94
  if (maxRetry === retryCount) {
87
95
  return false;
88
96
  }
@@ -132,6 +140,9 @@ async function startFetchRequest(request, options, input, output, emitter, count
132
140
  // jsforce may switch to node's fetch which doesn't emit this event on retries.
133
141
  emitter.emit('retry', retryCount);
134
142
  retryCount++;
143
+ if (res.status === 420) {
144
+ retry420Count++;
145
+ }
135
146
  return await fetchWithRetries(maxRetry);
136
147
  }
137
148
  // should we throw here if the maxRetry already happened and still got the same statusCode?
@@ -157,12 +168,7 @@ async function startFetchRequest(request, options, input, output, emitter, count
157
168
  return fetchWithRetries(maxRetry);
158
169
  }
159
170
  logger.debug('Skipping retry...');
160
- if (maxRetry === retryCount) {
161
- throw err;
162
- }
163
- else {
164
- throw err;
165
- }
171
+ throw err;
166
172
  }
167
173
  };
168
174
  let res;
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "database.com"
11
11
  ],
12
12
  "homepage": "http://github.com/jsforce/jsforce",
13
- "version": "3.10.13",
13
+ "version": "3.10.14",
14
14
  "repository": {
15
15
  "type": "git",
16
16
  "url": "git://github.com/jsforce/jsforce.git"