@jsforce/jsforce-node 3.1.0 → 3.2.1
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 +12 -1
- package/lib/VERSION.d.ts +1 -1
- package/lib/VERSION.js +1 -1
- package/lib/api/bulk.d.ts +2 -1
- package/lib/api/bulk.js +5 -1
- package/lib/api/bulk2.d.ts +4 -6
- package/lib/api/bulk2.js +14 -12
- package/lib/api/chatter.js +2 -2
- package/lib/api/metadata.d.ts +3 -3
- package/lib/api/metadata.js +1 -1
- package/lib/api/soap.d.ts +4 -4
- package/lib/api/streaming/extension.js +1 -3
- package/lib/api/streaming.js +5 -5
- package/lib/api/wsdl/wsdl2schema.js +1 -1
- package/lib/browser/request.js +1 -1
- package/lib/cache.js +1 -1
- package/lib/connection.d.ts +2 -2
- package/lib/connection.js +31 -13
- package/lib/http-api.js +1 -0
- package/lib/oauth2.js +2 -3
- package/lib/query.d.ts +6 -10
- package/lib/query.js +2 -1
- package/lib/registry/base.js +7 -0
- package/lib/registry/sfdx.js +2 -0
- package/lib/registry/types.d.ts +2 -2
- package/lib/request.js +93 -25
- package/lib/soap.js +4 -4
- package/lib/soql-builder.js +1 -1
- package/lib/transport.js +1 -1
- package/lib/types/common.d.ts +3 -0
- package/lib/types/projection.d.ts +4 -4
- package/lib/types/schema.d.ts +4 -4
- package/lib/types/standard-schema.d.ts +950 -950
- package/lib/util/logger.d.ts +6 -6
- package/package.json +4 -1
package/lib/registry/sfdx.js
CHANGED
|
@@ -120,9 +120,11 @@ class SfdxRegistry {
|
|
|
120
120
|
async removeConnectionConfig(name) {
|
|
121
121
|
await this._execCommand('force:org:delete', { u: name });
|
|
122
122
|
}
|
|
123
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
123
124
|
async getClientConfig(_name) {
|
|
124
125
|
return null;
|
|
125
126
|
}
|
|
127
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
126
128
|
async getClientNames() {
|
|
127
129
|
return [];
|
|
128
130
|
}
|
package/lib/registry/types.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export type RegistryConfig = {
|
|
|
34
34
|
/**
|
|
35
35
|
*
|
|
36
36
|
*/
|
|
37
|
-
export
|
|
37
|
+
export type Registry = {
|
|
38
38
|
getConnectionNames(): Promise<string[]>;
|
|
39
39
|
getConnection<S extends Schema = Schema>(name?: string): Promise<Connection<S> | null>;
|
|
40
40
|
getConnectionConfig(name?: string): Promise<ConnectionConfig | null>;
|
|
@@ -44,4 +44,4 @@ export interface Registry {
|
|
|
44
44
|
getClientConfig(name: string): Promise<ClientConfig | null>;
|
|
45
45
|
getClientNames(): Promise<string[]>;
|
|
46
46
|
registerClientConfig(name: string, clientConfig: ClientConfig): Promise<void>;
|
|
47
|
-
}
|
|
47
|
+
};
|
package/lib/request.js
CHANGED
|
@@ -1,11 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
27
|
};
|
|
5
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
29
|
exports.setDefaults = void 0;
|
|
7
30
|
const stream_1 = require("stream");
|
|
8
|
-
const node_fetch_1 =
|
|
31
|
+
const node_fetch_1 = __importStar(require("node-fetch"));
|
|
9
32
|
const abort_controller_1 = __importDefault(require("abort-controller"));
|
|
10
33
|
const https_proxy_agent_1 = __importDefault(require("https-proxy-agent"));
|
|
11
34
|
const request_helper_1 = require("./request-helper");
|
|
@@ -33,7 +56,10 @@ async function startFetchRequest(request, options, input, output, emitter, count
|
|
|
33
56
|
const controller = new abort_controller_1.default();
|
|
34
57
|
let retryCount = 0;
|
|
35
58
|
const retryOpts = {
|
|
59
|
+
statusCodes: options.retry?.statusCodes ?? [429, 500, 502, 503, 504],
|
|
36
60
|
maxRetries: options.retry?.maxRetries ?? 5,
|
|
61
|
+
minTimeout: options.retry?.minTimeout ?? 500,
|
|
62
|
+
timeoutFactor: options.retry?.timeoutFactor ?? 2,
|
|
37
63
|
errorCodes: options.retry?.errorCodes ?? [
|
|
38
64
|
'ECONNRESET',
|
|
39
65
|
'ECONNREFUSED',
|
|
@@ -53,6 +79,40 @@ async function startFetchRequest(request, options, input, output, emitter, count
|
|
|
53
79
|
'DELETE',
|
|
54
80
|
],
|
|
55
81
|
};
|
|
82
|
+
const shouldRetryRequest = (maxRetry, resOrErr) => {
|
|
83
|
+
if (!retryOpts.methods.includes(request.method))
|
|
84
|
+
return false;
|
|
85
|
+
if (resOrErr instanceof node_fetch_1.Response) {
|
|
86
|
+
if (retryOpts.statusCodes.includes(resOrErr.status)) {
|
|
87
|
+
if (maxRetry === retryCount) {
|
|
88
|
+
const err = new Error('Request failed');
|
|
89
|
+
err.name = 'RequestRetryError';
|
|
90
|
+
throw err;
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
if (maxRetry === retryCount)
|
|
100
|
+
return false;
|
|
101
|
+
// only retry on operational errors
|
|
102
|
+
// https://github.com/node-fetch/node-fetch/blob/2.x/ERROR-HANDLING.md#error-handling-with-node-fetch
|
|
103
|
+
if (resOrErr.name != 'FetchError')
|
|
104
|
+
return false;
|
|
105
|
+
if (is_1.default.nodeStream(body) && stream_1.Readable.isDisturbed(body)) {
|
|
106
|
+
logger.debug('Body of type stream was read, unable to retry request.');
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
if ('code' in resOrErr &&
|
|
110
|
+
resOrErr.code &&
|
|
111
|
+
retryOpts?.errorCodes?.includes(resOrErr.code))
|
|
112
|
+
return true;
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
56
116
|
const fetchWithRetries = async (maxRetry = retryOpts?.maxRetries) => {
|
|
57
117
|
const fetchOpts = {
|
|
58
118
|
...rrequest,
|
|
@@ -60,48 +120,55 @@ async function startFetchRequest(request, options, input, output, emitter, count
|
|
|
60
120
|
? { body: input }
|
|
61
121
|
: {}),
|
|
62
122
|
redirect: 'manual',
|
|
123
|
+
// @ts-expect-error - differing types of signal? this started abruptly
|
|
63
124
|
signal: controller.signal,
|
|
64
125
|
agent,
|
|
65
126
|
};
|
|
66
127
|
try {
|
|
67
|
-
|
|
128
|
+
const res = await (0, node_fetch_1.default)(url, fetchOpts);
|
|
129
|
+
if (shouldRetryRequest(retryOpts.maxRetries, res)) {
|
|
130
|
+
logger.debug(`retrying for the ${retryCount + 1} time`);
|
|
131
|
+
logger.debug('reason: statusCode match');
|
|
132
|
+
await sleep(retryCount === 0
|
|
133
|
+
? retryOpts.minTimeout
|
|
134
|
+
: retryOpts.minTimeout * retryOpts.timeoutFactor ** retryCount);
|
|
135
|
+
// NOTE: this event is only used by tests and will be removed at any time.
|
|
136
|
+
// jsforce may switch to node's fetch which doesn't emit this event on retries.
|
|
137
|
+
emitter.emit('retry', retryCount);
|
|
138
|
+
retryCount++;
|
|
139
|
+
return await fetchWithRetries(maxRetry);
|
|
140
|
+
}
|
|
141
|
+
// should we throw here if the maxRetry already happened and still got the same statusCode?
|
|
142
|
+
return res;
|
|
68
143
|
}
|
|
69
144
|
catch (err) {
|
|
70
|
-
logger.debug(
|
|
145
|
+
logger.debug('Request failed');
|
|
71
146
|
const error = err;
|
|
72
147
|
// request was canceled by consumer (AbortController), skip retry and rethrow.
|
|
73
148
|
if (error.name === 'AbortError') {
|
|
74
149
|
throw error;
|
|
75
150
|
}
|
|
76
|
-
|
|
77
|
-
// only retry on operational errors
|
|
78
|
-
if (error.name != 'FetchError')
|
|
79
|
-
return false;
|
|
80
|
-
if (retryCount === maxRetry)
|
|
81
|
-
return false;
|
|
82
|
-
if (!retryOpts?.methods?.includes(request.method))
|
|
83
|
-
return false;
|
|
84
|
-
if (is_1.default.nodeStream(body) && stream_1.Readable.isDisturbed(body)) {
|
|
85
|
-
logger.debug('Body of type stream was read, unable to retry request.');
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
if ('code' in error &&
|
|
89
|
-
error.code &&
|
|
90
|
-
retryOpts?.errorCodes?.includes(error.code))
|
|
91
|
-
return true;
|
|
92
|
-
return false;
|
|
93
|
-
};
|
|
94
|
-
if (shouldRetry()) {
|
|
151
|
+
if (shouldRetryRequest(retryOpts.maxRetries, error)) {
|
|
95
152
|
logger.debug(`retrying for the ${retryCount + 1} time`);
|
|
96
|
-
logger.debug(`Error: ${
|
|
153
|
+
logger.debug(`Error: ${err.message}`);
|
|
154
|
+
await sleep(retryCount === 0
|
|
155
|
+
? retryOpts.minTimeout
|
|
156
|
+
: retryOpts.minTimeout * retryOpts.timeoutFactor ** retryCount);
|
|
97
157
|
// NOTE: this event is only used by tests and will be removed at any time.
|
|
98
158
|
// jsforce may switch to node's fetch which doesn't emit this event on retries.
|
|
99
159
|
emitter.emit('retry', retryCount);
|
|
100
160
|
retryCount++;
|
|
101
|
-
return
|
|
161
|
+
return fetchWithRetries(maxRetry);
|
|
102
162
|
}
|
|
103
163
|
logger.debug('Skipping retry...');
|
|
104
|
-
|
|
164
|
+
if (maxRetry === retryCount) {
|
|
165
|
+
const error = new Error('Request failed', { cause: err });
|
|
166
|
+
error.name = 'RequestRetryError';
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
throw err;
|
|
171
|
+
}
|
|
105
172
|
}
|
|
106
173
|
};
|
|
107
174
|
let res;
|
|
@@ -142,3 +209,4 @@ function request(req, options_ = {}) {
|
|
|
142
209
|
return stream;
|
|
143
210
|
}
|
|
144
211
|
exports.default = request;
|
|
212
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
package/lib/soap.js
CHANGED
|
@@ -59,7 +59,7 @@ function castTypeUsingSchema(value, schema, schemaDict = {}) {
|
|
|
59
59
|
const v = obj[k];
|
|
60
60
|
const nillable = (Array.isArray(s) && s.length === 2 && s[0] === '?') ||
|
|
61
61
|
((0, function_1.isMapObject)(s) && '?' in s) ||
|
|
62
|
-
(typeof s === 'string' && s
|
|
62
|
+
(typeof s === 'string' && s.startsWith('?'));
|
|
63
63
|
if (typeof v === 'undefined' && nillable) {
|
|
64
64
|
return o;
|
|
65
65
|
}
|
|
@@ -70,7 +70,7 @@ function castTypeUsingSchema(value, schema, schemaDict = {}) {
|
|
|
70
70
|
}, obj);
|
|
71
71
|
}
|
|
72
72
|
else {
|
|
73
|
-
const nillable = typeof schema === 'string' && schema
|
|
73
|
+
const nillable = typeof schema === 'string' && schema.startsWith('?');
|
|
74
74
|
const type = typeof schema === 'string'
|
|
75
75
|
? nillable
|
|
76
76
|
? schema.substring(1)
|
|
@@ -135,9 +135,9 @@ function toXML(name, value) {
|
|
|
135
135
|
if ((0, function_1.isMapObject)(value)) {
|
|
136
136
|
for (const k of Object.keys(value)) {
|
|
137
137
|
const v = value[k];
|
|
138
|
-
if (k
|
|
138
|
+
if (k.startsWith('@')) {
|
|
139
139
|
const kk = k.substring(1);
|
|
140
|
-
attrs.push(kk
|
|
140
|
+
attrs.push(`${kk}="${v}"`);
|
|
141
141
|
}
|
|
142
142
|
else {
|
|
143
143
|
elems.push(toXML(k, v));
|
package/lib/soql-builder.js
CHANGED
|
@@ -75,7 +75,7 @@ function createFieldExpression(field, value) {
|
|
|
75
75
|
else if (typeof value === 'object' && value !== null) {
|
|
76
76
|
// Otherwise, if an object was passed then process the supplied ops.
|
|
77
77
|
for (const k of Object.keys(value)) {
|
|
78
|
-
if (k
|
|
78
|
+
if (k.startsWith('$')) {
|
|
79
79
|
op = k;
|
|
80
80
|
_value = value[k];
|
|
81
81
|
break;
|
package/lib/transport.js
CHANGED
|
@@ -146,7 +146,7 @@ class XdProxyTransport extends Transport {
|
|
|
146
146
|
httpRequest(req, _options = {}) {
|
|
147
147
|
const xdProxyUrl = this._xdProxyUrl;
|
|
148
148
|
const { url, body, ...rreq } = req;
|
|
149
|
-
const canonicalUrl = url.
|
|
149
|
+
const canonicalUrl = url.startsWith('/') ? baseUrl + url : url;
|
|
150
150
|
const xdProxyReq = createXdProxyRequest({ ...rreq, url: canonicalUrl, body }, xdProxyUrl);
|
|
151
151
|
return super.httpRequest(xdProxyReq, {
|
|
152
152
|
followRedirect: (redirectUrl) => createXdProxyRequest({ ...rreq, method: 'GET', url: redirectUrl }, xdProxyUrl),
|
package/lib/types/common.d.ts
CHANGED
|
@@ -21,8 +21,11 @@ export type HttpRequest = {
|
|
|
21
21
|
export type HttpRequestOptions = {
|
|
22
22
|
retry?: {
|
|
23
23
|
maxRetries?: number;
|
|
24
|
+
minTimeout?: number;
|
|
25
|
+
timeoutFactor?: number;
|
|
24
26
|
errorCodes?: string[];
|
|
25
27
|
methods?: HttpMethods[];
|
|
28
|
+
statusCodes?: number[];
|
|
26
29
|
};
|
|
27
30
|
httpProxy?: string;
|
|
28
31
|
timeout?: number;
|
|
@@ -3,15 +3,15 @@ import { StringKeys } from './util';
|
|
|
3
3
|
/**
|
|
4
4
|
*
|
|
5
5
|
*/
|
|
6
|
-
type FieldPath_3<SO extends SObjectDefinition> = '*' | StringKeys<SO['Fields']
|
|
6
|
+
type FieldPath_3<SO extends SObjectDefinition> = '*' | Array<StringKeys<SO['Fields']>>;
|
|
7
7
|
type FieldPath_2<SO extends SObjectDefinition, PSOR extends SO['ParentReferences'] = SO['ParentReferences']> = '*' | StringKeys<SO['Fields']> | {
|
|
8
|
-
[K in StringKeys<PSOR>]?: '*' | FieldPath_3<Extract<PSOR[K], SObjectDefinition
|
|
8
|
+
[K in StringKeys<PSOR>]?: '*' | Array<FieldPath_3<Extract<PSOR[K], SObjectDefinition>>>;
|
|
9
9
|
};
|
|
10
10
|
type FieldPath_1<SO extends SObjectDefinition, PSOR extends SO['ParentReferences'] = SO['ParentReferences']> = '*' | StringKeys<SO['Fields']> | {
|
|
11
|
-
[K in StringKeys<PSOR>]?: '*' | FieldPath_2<Extract<PSOR[K], SObjectDefinition
|
|
11
|
+
[K in StringKeys<PSOR>]?: '*' | Array<FieldPath_2<Extract<PSOR[K], SObjectDefinition>>>;
|
|
12
12
|
};
|
|
13
13
|
type FieldPathSpecifier_<S extends Schema, N extends string, SO extends SObjectDefinition = S['SObjects'][N], PSOR extends SO['ParentReferences'] = SO['ParentReferences']> = '*' | StringKeys<SO['Fields']> | {
|
|
14
|
-
[K in StringKeys<PSOR>]?: '*' | FieldPath_1<Extract<PSOR[K], SObjectDefinition
|
|
14
|
+
[K in StringKeys<PSOR>]?: '*' | Array<FieldPath_1<Extract<PSOR[K], SObjectDefinition>>>;
|
|
15
15
|
};
|
|
16
16
|
export type FieldPathSpecifier<S extends Schema, N extends string> = FieldPathSpecifier_<S, N>;
|
|
17
17
|
export type FieldProjectionConfigObject = {
|
package/lib/types/schema.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export type Address = {
|
|
|
19
19
|
street: string | null;
|
|
20
20
|
};
|
|
21
21
|
export type SObjectFieldType = number | boolean | DateString | BlobString | string | Address;
|
|
22
|
-
export
|
|
22
|
+
export type SObjectDefinition<N extends string = string> = {
|
|
23
23
|
Name: N;
|
|
24
24
|
Fields: {
|
|
25
25
|
[name: string]: SObjectFieldType | null;
|
|
@@ -30,12 +30,12 @@ export interface SObjectDefinition<N extends string = string> {
|
|
|
30
30
|
ChildRelationships: {
|
|
31
31
|
[name: string]: SObjectDefinition;
|
|
32
32
|
};
|
|
33
|
-
}
|
|
34
|
-
export
|
|
33
|
+
};
|
|
34
|
+
export type Schema = {
|
|
35
35
|
SObjects: {
|
|
36
36
|
[name: string]: SObjectDefinition;
|
|
37
37
|
};
|
|
38
|
-
}
|
|
38
|
+
};
|
|
39
39
|
/**
|
|
40
40
|
*
|
|
41
41
|
*/
|