@jsforce/jsforce-node 3.0.0-next.1 → 3.0.0-next.2

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.
@@ -19,7 +19,8 @@ import QuickAction from './quick-action';
19
19
  import Process from './process';
20
20
  import Analytics from './api/analytics';
21
21
  import Apex from './api/apex';
22
- import { Bulk, BulkV2 } from './api/bulk';
22
+ import { Bulk } from './api/bulk';
23
+ import { BulkV2 } from './api/bulk2';
23
24
  import Chatter from './api/chatter';
24
25
  import Metadata from './api/metadata';
25
26
  import SoapApi from './api/soap';
package/lib/http-api.js CHANGED
@@ -13,6 +13,7 @@ const logger_1 = require("./util/logger");
13
13
  const promise_1 = require("./util/promise");
14
14
  const csv_1 = require("./csv");
15
15
  const stream_1 = require("./util/stream");
16
+ const get_body_size_1 = require("./util/get-body-size");
16
17
  /** @private */
17
18
  function parseJSON(str) {
18
19
  return JSON.parse(str);
@@ -103,6 +104,23 @@ class HttpApi extends events_1.EventEmitter {
103
104
  // when session refresh delegate is available
104
105
  if (this.isSessionExpired(response) && refreshDelegate) {
105
106
  await refreshDelegate.refresh(requestTime);
107
+ /* remove the `content-length` header after token refresh
108
+ *
109
+ * SOAP requests include the access token their the body,
110
+ * if the first req had an invalid token and jsforce successfully
111
+ * refreshed it we need to remove the `content-length` header
112
+ * so that it get's re-calculated again with the new body.
113
+ *
114
+ * REST request aren't affected by this because the access token
115
+ * is sent via HTTP headers
116
+ *
117
+ * `_message` is only present in SOAP requests
118
+ */
119
+ if ('_message' in request &&
120
+ request.headers &&
121
+ 'content-length' in request.headers) {
122
+ delete request.headers['content-length'];
123
+ }
106
124
  return this.request(request);
107
125
  }
108
126
  if (this.isErrorResponse(response)) {
@@ -137,6 +155,16 @@ class HttpApi extends events_1.EventEmitter {
137
155
  }
138
156
  headers['Sforce-Call-Options'] = callOptions.join(', ');
139
157
  }
158
+ const bodySize = (0, get_body_size_1.getBodySize)(request.body, headers);
159
+ const cannotHaveBody = ['GET', 'HEAD', 'OPTIONS'].includes(request.method);
160
+ if (!cannotHaveBody &&
161
+ !!request.body &&
162
+ !('transfer-encoding' in headers) &&
163
+ !('content-length' in headers) &&
164
+ !!bodySize) {
165
+ this._logger.debug(`missing 'content-length' header, setting it to: ${bodySize}`);
166
+ headers['content-length'] = String(bodySize);
167
+ }
140
168
  request.headers = headers;
141
169
  }
142
170
  /**
@@ -214,6 +242,10 @@ class HttpApi extends events_1.EventEmitter {
214
242
  */
215
243
  parseError(body) {
216
244
  const errors = body;
245
+ // XML response
246
+ if (errors.Errors) {
247
+ return errors.Errors.Error;
248
+ }
217
249
  return Array.isArray(errors) ? errors[0] : errors;
218
250
  }
219
251
  /**
@@ -237,6 +269,12 @@ class HttpApi extends events_1.EventEmitter {
237
269
  errorCode: `ERROR_HTTP_${response.statusCode}`,
238
270
  message: response.body,
239
271
  };
272
+ if (response.headers['content-type'] === 'text/html') {
273
+ this._logger.debug(`html response.body: ${response.body}`);
274
+ return new HttpApiError(`HTTP response contains html content.
275
+ Check that the org exists and can be reached.
276
+ See error.content for the full html response.`, error.errorCode, error.message);
277
+ }
240
278
  return new HttpApiError(error.message, error.errorCode);
241
279
  }
242
280
  }
package/lib/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import jsforce from './jsforce';
2
2
  import './api/analytics';
3
3
  import './api/apex';
4
4
  import './api/bulk';
5
+ import './api/bulk2';
5
6
  import './api/chatter';
6
7
  import './api/metadata';
7
8
  import './api/soap';
package/lib/index.js CHANGED
@@ -21,6 +21,7 @@ const jsforce_1 = __importDefault(require("./jsforce"));
21
21
  require("./api/analytics");
22
22
  require("./api/apex");
23
23
  require("./api/bulk");
24
+ require("./api/bulk2");
24
25
  require("./api/chatter");
25
26
  require("./api/metadata");
26
27
  require("./api/soap");
package/lib/soap.js CHANGED
@@ -10,6 +10,7 @@ exports.SOAP = exports.castTypeUsingSchema = void 0;
10
10
  */
11
11
  const http_api_1 = __importDefault(require("./http-api"));
12
12
  const function_1 = require("./util/function");
13
+ const get_body_size_1 = require("./util/get-body-size");
13
14
  /**
14
15
  *
15
16
  */
@@ -196,6 +197,16 @@ class SOAP extends http_api_1.default {
196
197
  /** @override */
197
198
  beforeSend(request) {
198
199
  request.body = this._createEnvelope(request._message);
200
+ const headers = request.headers || {};
201
+ const bodySize = (0, get_body_size_1.getBodySize)(request.body, request.headers);
202
+ if (request.method === 'POST' &&
203
+ !('transfer-encoding' in headers) &&
204
+ !('content-length' in headers) &&
205
+ !!bodySize) {
206
+ this._logger.debug(`missing 'content-length' header, setting it to: ${bodySize}`);
207
+ headers['content-length'] = String(bodySize);
208
+ }
209
+ request.headers = headers;
199
210
  }
200
211
  /** @override **/
201
212
  isSessionExpired(response) {
@@ -0,0 +1,4 @@
1
+ import { HttpBody } from '../types';
2
+ export declare function getBodySize(body: HttpBody | undefined, headers?: {
3
+ [name: string]: string;
4
+ }): number | undefined;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getBodySize = void 0;
7
+ const is_1 = __importDefault(require("@sindresorhus/is"));
8
+ function getBodySize(body, headers = {}) {
9
+ function isFormData(body) {
10
+ return is_1.default.nodeStream(body) && is_1.default.function_(body.getBoundary);
11
+ }
12
+ if (headers && 'content-length' in headers) {
13
+ return Number(headers['content-length']);
14
+ }
15
+ if (!body) {
16
+ return 0;
17
+ }
18
+ if (is_1.default.string(body)) {
19
+ return Buffer.byteLength(body);
20
+ }
21
+ if (is_1.default.urlSearchParams(body)) {
22
+ return Buffer.byteLength(body.toString());
23
+ }
24
+ if (is_1.default.buffer(body)) {
25
+ return body.length;
26
+ }
27
+ try {
28
+ // `getLengthSync` will throw if body has a stream:
29
+ // https://github.com/form-data/form-data#integer-getlengthsync
30
+ if (isFormData(body)) {
31
+ return body.getLengthSync();
32
+ }
33
+ }
34
+ catch {
35
+ return undefined;
36
+ }
37
+ return undefined;
38
+ }
39
+ exports.getBodySize = getBodySize;
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.0.0-next.1",
13
+ "version": "3.0.0-next.2",
14
14
  "repository": {
15
15
  "type": "git",
16
16
  "url": "git://github.com/jsforce/jsforce.git"
@@ -191,6 +191,7 @@
191
191
  "node": ">=18"
192
192
  },
193
193
  "dependencies": {
194
+ "@sindresorhus/is": "^4",
194
195
  "@types/node": "^18.15.3",
195
196
  "abort-controller": "^3.0.0",
196
197
  "base64url": "^3.0.1",
@@ -240,6 +241,7 @@
240
241
  "karma-jasmine-html-reporter": "^2.0.0",
241
242
  "karma-sourcemap-loader": "^0.4.0",
242
243
  "karma-webpack": "^5.0.0",
244
+ "nock": "^13.4.0",
243
245
  "path-browserify": "^1.0.1",
244
246
  "power-assert": "^1.6.1",
245
247
  "prettier": "^2.2.1",