@salesforce/core 3.31.4 → 3.31.7
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/LICENSE.txt +11 -11
- package/README.md +222 -222
- package/lib/config/aliasesConfig.d.ts +12 -12
- package/lib/config/aliasesConfig.js +27 -27
- package/lib/config/authInfoConfig.d.ts +19 -19
- package/lib/config/authInfoConfig.js +34 -34
- package/lib/config/config.d.ts +311 -311
- package/lib/config/config.js +574 -574
- package/lib/config/configAggregator.d.ts +232 -232
- package/lib/config/configAggregator.js +379 -379
- package/lib/config/configFile.d.ts +199 -199
- package/lib/config/configFile.js +340 -340
- package/lib/config/configGroup.d.ts +141 -141
- package/lib/config/configGroup.js +224 -224
- package/lib/config/configStore.d.ts +241 -241
- package/lib/config/configStore.js +352 -352
- package/lib/config/envVars.d.ts +101 -101
- package/lib/config/envVars.js +456 -456
- package/lib/config/orgUsersConfig.d.ts +31 -31
- package/lib/config/orgUsersConfig.js +41 -41
- package/lib/config/sandboxOrgConfig.d.ts +37 -37
- package/lib/config/sandboxOrgConfig.js +50 -50
- package/lib/config/sandboxProcessCache.d.ts +16 -16
- package/lib/config/sandboxProcessCache.js +37 -37
- package/lib/config/tokensConfig.d.ts +10 -10
- package/lib/config/tokensConfig.js +28 -28
- package/lib/config/ttlConfig.d.ts +34 -34
- package/lib/config/ttlConfig.js +54 -54
- package/lib/crypto/crypto.d.ts +54 -54
- package/lib/crypto/crypto.js +220 -220
- package/lib/crypto/keyChain.d.ts +8 -8
- package/lib/crypto/keyChain.js +61 -61
- package/lib/crypto/keyChainImpl.d.ts +116 -116
- package/lib/crypto/keyChainImpl.js +486 -486
- package/lib/crypto/secureBuffer.d.ts +46 -46
- package/lib/crypto/secureBuffer.js +82 -82
- package/lib/deviceOauthService.d.ts +71 -71
- package/lib/deviceOauthService.js +191 -191
- package/lib/exported.d.ts +38 -38
- package/lib/exported.js +118 -118
- package/lib/global.d.ts +70 -70
- package/lib/global.js +109 -109
- package/lib/lifecycleEvents.d.ts +93 -93
- package/lib/lifecycleEvents.js +188 -188
- package/lib/logger.d.ts +381 -381
- package/lib/logger.js +734 -734
- package/lib/messages.d.ts +291 -291
- package/lib/messages.js +543 -543
- package/lib/org/authInfo.d.ts +344 -344
- package/lib/org/authInfo.js +892 -892
- package/lib/org/authRemover.d.ts +88 -88
- package/lib/org/authRemover.js +182 -182
- package/lib/org/connection.d.ts +197 -197
- package/lib/org/connection.js +395 -395
- package/lib/org/index.d.ts +6 -6
- package/lib/org/index.js +28 -28
- package/lib/org/org.d.ts +558 -558
- package/lib/org/org.js +1267 -1267
- package/lib/org/orgConfigProperties.d.ts +69 -69
- package/lib/org/orgConfigProperties.js +136 -136
- package/lib/org/permissionSetAssignment.d.ts +35 -35
- package/lib/org/permissionSetAssignment.js +125 -125
- package/lib/org/scratchOrgCache.d.ts +20 -20
- package/lib/org/scratchOrgCache.js +32 -32
- package/lib/org/scratchOrgCreate.d.ts +54 -54
- package/lib/org/scratchOrgCreate.js +216 -216
- package/lib/org/scratchOrgErrorCodes.d.ts +10 -10
- package/lib/org/scratchOrgErrorCodes.js +88 -88
- package/lib/org/scratchOrgFeatureDeprecation.d.ts +26 -26
- package/lib/org/scratchOrgFeatureDeprecation.js +109 -109
- package/lib/org/scratchOrgInfoApi.d.ts +68 -68
- package/lib/org/scratchOrgInfoApi.js +413 -413
- package/lib/org/scratchOrgInfoGenerator.d.ts +64 -64
- package/lib/org/scratchOrgInfoGenerator.js +241 -241
- package/lib/org/scratchOrgLifecycleEvents.d.ts +10 -10
- package/lib/org/scratchOrgLifecycleEvents.js +40 -40
- package/lib/org/scratchOrgSettingsGenerator.d.ts +78 -78
- package/lib/org/scratchOrgSettingsGenerator.js +276 -276
- package/lib/org/scratchOrgTypes.d.ts +43 -43
- package/lib/org/scratchOrgTypes.js +8 -8
- package/lib/org/user.d.ts +187 -187
- package/lib/org/user.js +448 -448
- package/lib/schema/printer.d.ts +79 -79
- package/lib/schema/printer.js +260 -260
- package/lib/schema/validator.d.ts +70 -70
- package/lib/schema/validator.js +169 -169
- package/lib/sfError.d.ts +73 -73
- package/lib/sfError.js +136 -136
- package/lib/sfProject.d.ts +357 -357
- package/lib/sfProject.js +671 -671
- package/lib/stateAggregator/accessors/aliasAccessor.d.ts +98 -98
- package/lib/stateAggregator/accessors/aliasAccessor.js +145 -145
- package/lib/stateAggregator/accessors/orgAccessor.d.ts +101 -101
- package/lib/stateAggregator/accessors/orgAccessor.js +240 -240
- package/lib/stateAggregator/accessors/sandboxAccessor.d.ts +8 -8
- package/lib/stateAggregator/accessors/sandboxAccessor.js +27 -27
- package/lib/stateAggregator/accessors/tokenAccessor.d.ts +63 -63
- package/lib/stateAggregator/accessors/tokenAccessor.js +79 -79
- package/lib/stateAggregator/index.d.ts +4 -4
- package/lib/stateAggregator/index.js +26 -26
- package/lib/stateAggregator/stateAggregator.d.ts +25 -25
- package/lib/stateAggregator/stateAggregator.js +45 -45
- package/lib/status/myDomainResolver.d.ts +66 -66
- package/lib/status/myDomainResolver.js +124 -124
- package/lib/status/pollingClient.d.ts +85 -85
- package/lib/status/pollingClient.js +115 -115
- package/lib/status/streamingClient.d.ts +244 -244
- package/lib/status/streamingClient.js +436 -436
- package/lib/status/types.d.ts +89 -89
- package/lib/status/types.js +17 -17
- package/lib/testSetup.d.ts +553 -553
- package/lib/testSetup.js +871 -871
- package/lib/util/cache.d.ts +11 -11
- package/lib/util/cache.js +69 -69
- package/lib/util/checkLightningDomain.d.ts +1 -1
- package/lib/util/checkLightningDomain.js +28 -28
- package/lib/util/directoryWriter.d.ts +12 -12
- package/lib/util/directoryWriter.js +53 -53
- package/lib/util/getJwtAudienceUrl.d.ts +4 -4
- package/lib/util/getJwtAudienceUrl.js +18 -18
- package/lib/util/internal.d.ts +58 -58
- package/lib/util/internal.js +118 -118
- package/lib/util/jsonXmlTools.d.ts +14 -14
- package/lib/util/jsonXmlTools.js +38 -38
- package/lib/util/mapKeys.d.ts +14 -14
- package/lib/util/mapKeys.js +51 -51
- package/lib/util/sfdc.d.ts +52 -52
- package/lib/util/sfdc.js +85 -85
- package/lib/util/sfdcUrl.d.ts +72 -72
- package/lib/util/sfdcUrl.js +215 -215
- package/lib/util/structuredWriter.d.ts +9 -9
- package/lib/util/structuredWriter.js +2 -2
- package/lib/util/zipWriter.d.ts +16 -16
- package/lib/util/zipWriter.js +67 -67
- package/lib/webOAuthServer.d.ts +156 -156
- package/lib/webOAuthServer.js +388 -388
- package/messages/auth.md +37 -37
- package/messages/config.md +156 -156
- package/messages/connection.md +30 -30
- package/messages/core.json +20 -20
- package/messages/core.md +67 -67
- package/messages/encryption.md +85 -85
- package/messages/envVars.md +303 -303
- package/messages/org.md +63 -63
- package/messages/permissionSetAssignment.md +31 -31
- package/messages/scratchOrgCreate.md +23 -23
- package/messages/scratchOrgErrorCodes.md +115 -115
- package/messages/scratchOrgFeatureDeprecation.md +11 -11
- package/messages/scratchOrgInfoApi.md +15 -15
- package/messages/scratchOrgInfoGenerator.md +23 -23
- package/messages/streaming.md +23 -23
- package/messages/user.md +35 -35
- package/package.json +97 -97
package/lib/org/connection.js
CHANGED
|
@@ -1,396 +1,396 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* Copyright (c) 2020, salesforce.com, inc.
|
|
4
|
-
* All rights reserved.
|
|
5
|
-
* Licensed under the BSD 3-Clause license.
|
|
6
|
-
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
7
|
-
*/
|
|
8
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.SingleRecordQueryErrors = exports.Connection = exports.DNS_ERROR_NAME = exports.SFDX_HTTP_HEADERS = void 0;
|
|
10
|
-
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
11
|
-
const url_1 = require("url");
|
|
12
|
-
const kit_1 = require("@salesforce/kit");
|
|
13
|
-
const ts_types_1 = require("@salesforce/ts-types");
|
|
14
|
-
const jsforce_1 = require("jsforce");
|
|
15
|
-
const tooling_1 = require("jsforce/lib/api/tooling");
|
|
16
|
-
const myDomainResolver_1 = require("../status/myDomainResolver");
|
|
17
|
-
const configAggregator_1 = require("../config/configAggregator");
|
|
18
|
-
const logger_1 = require("../logger");
|
|
19
|
-
const sfError_1 = require("../sfError");
|
|
20
|
-
const sfdc_1 = require("../util/sfdc");
|
|
21
|
-
const messages_1 = require("../messages");
|
|
22
|
-
const lifecycleEvents_1 = require("../lifecycleEvents");
|
|
23
|
-
const orgConfigProperties_1 = require("./orgConfigProperties");
|
|
24
|
-
messages_1.Messages.importMessagesDirectory(__dirname);
|
|
25
|
-
const messages = messages_1.Messages.load('@salesforce/core', 'connection', [
|
|
26
|
-
'incorrectAPIVersionError',
|
|
27
|
-
'domainNotFoundError',
|
|
28
|
-
'noInstanceUrlError',
|
|
29
|
-
'noApiVersionsError',
|
|
30
|
-
]);
|
|
31
|
-
const clientId = `sfdx toolbelt:${process.env.SFDX_SET_CLIENT_IDS ?? ''}`;
|
|
32
|
-
exports.SFDX_HTTP_HEADERS = {
|
|
33
|
-
'content-type': 'application/json',
|
|
34
|
-
'user-agent': clientId,
|
|
35
|
-
};
|
|
36
|
-
exports.DNS_ERROR_NAME = 'DomainNotFoundError';
|
|
37
|
-
/**
|
|
38
|
-
* Handles connections and requests to Salesforce Orgs.
|
|
39
|
-
*
|
|
40
|
-
* ```
|
|
41
|
-
* // Uses latest API version
|
|
42
|
-
* const connection = await Connection.create({
|
|
43
|
-
* authInfo: await AuthInfo.create({ username: 'myAdminUsername' })
|
|
44
|
-
* });
|
|
45
|
-
* connection.query('SELECT Name from Account');
|
|
46
|
-
*
|
|
47
|
-
* // Use different API version
|
|
48
|
-
* connection.setApiVersion("42.0");
|
|
49
|
-
* connection.query('SELECT Name from Account');
|
|
50
|
-
* ```
|
|
51
|
-
*/
|
|
52
|
-
class Connection extends jsforce_1.Connection {
|
|
53
|
-
/**
|
|
54
|
-
* Constructor
|
|
55
|
-
* **Do not directly construct instances of this class -- use {@link Connection.create} instead.**
|
|
56
|
-
*
|
|
57
|
-
* @param options The options for the class instance.
|
|
58
|
-
* @ignore
|
|
59
|
-
*/
|
|
60
|
-
constructor(options) {
|
|
61
|
-
super(options.connectionOptions ?? {});
|
|
62
|
-
this.options = options;
|
|
63
|
-
this.username = options.authInfo.getUsername();
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Tooling api reference.
|
|
67
|
-
*/
|
|
68
|
-
get tooling() {
|
|
69
|
-
return super.tooling;
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Creates an instance of a Connection. Performs additional async initializations.
|
|
73
|
-
*
|
|
74
|
-
* @param options Constructor options.
|
|
75
|
-
*/
|
|
76
|
-
static async create(options) {
|
|
77
|
-
const baseOptions = {
|
|
78
|
-
version: options.connectionOptions?.version,
|
|
79
|
-
callOptions: {
|
|
80
|
-
client: clientId,
|
|
81
|
-
},
|
|
82
|
-
};
|
|
83
|
-
if (!baseOptions.version) {
|
|
84
|
-
// Set the API version obtained from the config aggregator.
|
|
85
|
-
const configAggregator = options.configAggregator ?? (await configAggregator_1.ConfigAggregator.create());
|
|
86
|
-
baseOptions.version = (0, ts_types_1.asString)(configAggregator.getInfo('org-api-version').value);
|
|
87
|
-
}
|
|
88
|
-
const providedOptions = options.authInfo.getConnectionOptions();
|
|
89
|
-
// Get connection options from auth info and create a new jsForce connection
|
|
90
|
-
options.connectionOptions = Object.assign(baseOptions, providedOptions);
|
|
91
|
-
const conn = new this(options);
|
|
92
|
-
await conn.init();
|
|
93
|
-
try {
|
|
94
|
-
// No version passed in or in the config, so load one.
|
|
95
|
-
if (!baseOptions.version) {
|
|
96
|
-
const cachedVersion = await conn.loadInstanceApiVersion();
|
|
97
|
-
if (cachedVersion) {
|
|
98
|
-
conn.setApiVersion(cachedVersion);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
conn.logger.debug(`The org-api-version ${baseOptions.version} was found from ${options.connectionOptions?.version ? 'passed in options' : 'config'}`);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
catch (err) {
|
|
106
|
-
const e = err;
|
|
107
|
-
if (e.name === exports.DNS_ERROR_NAME) {
|
|
108
|
-
throw e;
|
|
109
|
-
}
|
|
110
|
-
conn.logger.debug(`Error trying to load the API version: ${e.name} - ${e.message}`);
|
|
111
|
-
}
|
|
112
|
-
conn.logger.debug(`Using apiVersion ${conn.getApiVersion()}`);
|
|
113
|
-
return conn;
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Async initializer.
|
|
117
|
-
*/
|
|
118
|
-
async init() {
|
|
119
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
120
|
-
this.logger = this.tooling._logger = await logger_1.Logger.child('connection');
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* deploy a zipped buffer from the SDRL with REST or SOAP
|
|
124
|
-
*
|
|
125
|
-
* @param zipInput data to deploy
|
|
126
|
-
* @param options JSForce deploy options + a boolean for rest
|
|
127
|
-
*/
|
|
128
|
-
async deploy(zipInput, options) {
|
|
129
|
-
const rest = options.rest;
|
|
130
|
-
// neither API expects this option
|
|
131
|
-
delete options.rest;
|
|
132
|
-
if (rest) {
|
|
133
|
-
this.logger.debug('deploy with REST');
|
|
134
|
-
await this.refreshAuth();
|
|
135
|
-
return this.metadata.deployRest(zipInput, options);
|
|
136
|
-
}
|
|
137
|
-
else {
|
|
138
|
-
this.logger.debug('deploy with SOAP');
|
|
139
|
-
return this.metadata.deploy(zipInput, options);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Send REST API request with given HTTP request info, with connected session information
|
|
144
|
-
* and SFDX headers.
|
|
145
|
-
*
|
|
146
|
-
* @param request HTTP request object or URL to GET request.
|
|
147
|
-
* @param options HTTP API request options.
|
|
148
|
-
*/
|
|
149
|
-
request(request, options) {
|
|
150
|
-
const httpRequest = (0, ts_types_1.isString)(request) ? { method: 'GET', url: request } : request;
|
|
151
|
-
httpRequest.headers = Object.assign({}, exports.SFDX_HTTP_HEADERS, httpRequest.headers);
|
|
152
|
-
this.logger.debug(`request: ${JSON.stringify(httpRequest)}`);
|
|
153
|
-
return super.request(httpRequest, options);
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* The Force API base url for the instance.
|
|
157
|
-
*/
|
|
158
|
-
baseUrl() {
|
|
159
|
-
// essentially the same as pathJoin(super.instanceUrl, 'services', 'data', `v${super.version}`);
|
|
160
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
161
|
-
return super._baseUrl();
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* Will deploy a recently validated deploy request - directly calling jsforce now that this is supported.
|
|
165
|
-
* WARNING: will always return a string from jsforce, the type is JsonCollection to support backwards compatibility
|
|
166
|
-
*
|
|
167
|
-
* @param options.id = the deploy ID that's been validated already from a previous checkOnly deploy request
|
|
168
|
-
* @param options.rest = a boolean whether or not to use the REST API
|
|
169
|
-
* @deprecated use {@link Connection.metadata#deployRecentValidation} instead - the jsforce implementation, instead of this wrapper
|
|
170
|
-
*/
|
|
171
|
-
async deployRecentValidation(options) {
|
|
172
|
-
// REST returns an object with an id property, SOAP returns the id as a string directly. That is now handled
|
|
173
|
-
// in jsforce, so we have to cast a string as unkown as JsonCollection to support backwards compatibility.
|
|
174
|
-
return (await this.metadata.deployRecentValidation(options));
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* Retrieves the highest api version that is supported by the target server instance.
|
|
178
|
-
*/
|
|
179
|
-
async retrieveMaxApiVersion() {
|
|
180
|
-
await this.isResolvable();
|
|
181
|
-
const versions = await this.request(`${this.instanceUrl}/services/data`);
|
|
182
|
-
// if the server doesn't return a list of versions, it's possibly a instanceUrl issue where the local file is out of date.
|
|
183
|
-
if (!Array.isArray(versions)) {
|
|
184
|
-
this.logger.debug(`server response for retrieveMaxApiVersion: ${versions}`);
|
|
185
|
-
throw messages.createError('noApiVersionsError');
|
|
186
|
-
}
|
|
187
|
-
this.logger.debug(`response for org versions: ${versions.map((item) => item.version).join(',')}`);
|
|
188
|
-
const max = (0, ts_types_1.ensure)((0, kit_1.maxBy)(versions, (version) => version.version));
|
|
189
|
-
return max.version;
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Use the latest API version available on `this.instanceUrl`.
|
|
193
|
-
*/
|
|
194
|
-
async useLatestApiVersion() {
|
|
195
|
-
try {
|
|
196
|
-
this.setApiVersion(await this.retrieveMaxApiVersion());
|
|
197
|
-
}
|
|
198
|
-
catch (err) {
|
|
199
|
-
const error = err;
|
|
200
|
-
if (error.name === exports.DNS_ERROR_NAME) {
|
|
201
|
-
throw error; // throws on DNS connection errors
|
|
202
|
-
}
|
|
203
|
-
// Don't fail if we can't use the latest, just use the default
|
|
204
|
-
this.logger.warn('Failed to set the latest API version:', error);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
/**
|
|
208
|
-
* Verify that instance has a reachable DNS entry, otherwise will throw error
|
|
209
|
-
*/
|
|
210
|
-
async isResolvable() {
|
|
211
|
-
if (!this.options.connectionOptions?.instanceUrl) {
|
|
212
|
-
throw messages.createError('noInstanceUrlError');
|
|
213
|
-
}
|
|
214
|
-
const resolver = await myDomainResolver_1.MyDomainResolver.create({
|
|
215
|
-
url: new url_1.URL(this.options.connectionOptions.instanceUrl),
|
|
216
|
-
});
|
|
217
|
-
try {
|
|
218
|
-
await resolver.resolve();
|
|
219
|
-
return true;
|
|
220
|
-
}
|
|
221
|
-
catch (e) {
|
|
222
|
-
throw messages.createError('domainNotFoundError', [], [], e);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
/**
|
|
226
|
-
* Get the API version used for all connection requests.
|
|
227
|
-
*/
|
|
228
|
-
getApiVersion() {
|
|
229
|
-
return this.version;
|
|
230
|
-
}
|
|
231
|
-
/**
|
|
232
|
-
* Set the API version for all connection requests.
|
|
233
|
-
*
|
|
234
|
-
* **Throws** *{@link SfError}{ name: 'IncorrectAPIVersionError' }* Incorrect API version.
|
|
235
|
-
*
|
|
236
|
-
* @param version The API version.
|
|
237
|
-
*/
|
|
238
|
-
setApiVersion(version) {
|
|
239
|
-
if (!sfdc_1.sfdc.validateApiVersion(version)) {
|
|
240
|
-
throw messages.createError('incorrectAPIVersionError', [version]);
|
|
241
|
-
}
|
|
242
|
-
this.version = version;
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* Getter for AuthInfo.
|
|
246
|
-
*/
|
|
247
|
-
getAuthInfo() {
|
|
248
|
-
return this.options.authInfo;
|
|
249
|
-
}
|
|
250
|
-
/**
|
|
251
|
-
* Getter for the AuthInfo fields.
|
|
252
|
-
*/
|
|
253
|
-
getAuthInfoFields() {
|
|
254
|
-
// If the StateAggregator.orgs.remove is called, the AuthFields are no longer accessible.
|
|
255
|
-
return this.options.authInfo.getFields() || {};
|
|
256
|
-
}
|
|
257
|
-
/**
|
|
258
|
-
* Getter for the auth fields.
|
|
259
|
-
*/
|
|
260
|
-
getConnectionOptions() {
|
|
261
|
-
return this.options.authInfo.getConnectionOptions();
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* Getter for the username of the Salesforce Org.
|
|
265
|
-
*/
|
|
266
|
-
getUsername() {
|
|
267
|
-
return this.username;
|
|
268
|
-
}
|
|
269
|
-
/**
|
|
270
|
-
* Returns true if this connection is using access token auth.
|
|
271
|
-
*/
|
|
272
|
-
isUsingAccessToken() {
|
|
273
|
-
return this.options.authInfo.isUsingAccessToken();
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* Normalize a Salesforce url to include a instance information.
|
|
277
|
-
*
|
|
278
|
-
* @param url Partial url.
|
|
279
|
-
*/
|
|
280
|
-
normalizeUrl(url) {
|
|
281
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
282
|
-
return this._normalizeUrl(url);
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* Executes a query and auto-fetches (i.e., "queryMore") all results. This is especially
|
|
286
|
-
* useful with large query result sizes, such as over 2000 records. The default maximum
|
|
287
|
-
* fetch size is 10,000 records. Modify this via the options argument.
|
|
288
|
-
*
|
|
289
|
-
* @param soql The SOQL string.
|
|
290
|
-
* @param queryOptions The query options. NOTE: the autoFetch option will always be true.
|
|
291
|
-
*/
|
|
292
|
-
async autoFetchQuery(soql, queryOptions = { tooling: false }) {
|
|
293
|
-
const config = await configAggregator_1.ConfigAggregator.create();
|
|
294
|
-
// take the limit from the calling function, then the config, then default 10,000
|
|
295
|
-
const maxFetch = (config.getInfo(orgConfigProperties_1.OrgConfigProperties.ORG_MAX_QUERY_LIMIT).value || queryOptions.maxFetch) ?? 10000;
|
|
296
|
-
const { tooling, ...queryOptionsWithoutTooling } = queryOptions;
|
|
297
|
-
const options = Object.assign(queryOptionsWithoutTooling, {
|
|
298
|
-
autoFetch: true,
|
|
299
|
-
maxFetch,
|
|
300
|
-
});
|
|
301
|
-
const query = tooling ? await this.tooling.query(soql, options) : await this.query(soql, options);
|
|
302
|
-
if (query.records.length && query.totalSize > query.records.length) {
|
|
303
|
-
void lifecycleEvents_1.Lifecycle.getInstance().emitWarning(`The query result is missing ${query.totalSize - query.records.length} records due to a ${maxFetch} record limit. Increase the number of records returned by setting the config value "maxQueryLimit" or the environment variable "SFDX_MAX_QUERY_LIMIT" to ${query.totalSize} or greater than ${maxFetch}.`);
|
|
304
|
-
}
|
|
305
|
-
return query;
|
|
306
|
-
}
|
|
307
|
-
/**
|
|
308
|
-
* Executes a query using either standard REST or Tooling API, returning a single record.
|
|
309
|
-
* Will throw if either zero records are found OR multiple records are found.
|
|
310
|
-
*
|
|
311
|
-
* @param soql The SOQL string.
|
|
312
|
-
* @param options The query options.
|
|
313
|
-
*/
|
|
314
|
-
async singleRecordQuery(soql, options = {
|
|
315
|
-
choiceField: 'Name',
|
|
316
|
-
}) {
|
|
317
|
-
const result = options.tooling ? await this.tooling.query(soql) : await this.query(soql);
|
|
318
|
-
if (result.totalSize === 0) {
|
|
319
|
-
throw new sfError_1.SfError(`No record found for ${soql}`, exports.SingleRecordQueryErrors.NoRecords);
|
|
320
|
-
}
|
|
321
|
-
if (result.totalSize > 1) {
|
|
322
|
-
throw new sfError_1.SfError(options.returnChoicesOnMultiple
|
|
323
|
-
? // eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
324
|
-
`Multiple records found. ${result.records.map((item) => item[options.choiceField]).join(',')}`
|
|
325
|
-
: 'The query returned more than 1 record', exports.SingleRecordQueryErrors.MultipleRecords);
|
|
326
|
-
}
|
|
327
|
-
return result.records[0];
|
|
328
|
-
}
|
|
329
|
-
/**
|
|
330
|
-
* Executes a get request on the baseUrl to force an auth refresh
|
|
331
|
-
* Useful for the raw methods (request, requestRaw) that use the accessToken directly and don't handle refreshes
|
|
332
|
-
*/
|
|
333
|
-
async refreshAuth() {
|
|
334
|
-
this.logger.debug('Refreshing auth for org.');
|
|
335
|
-
const requestInfo = {
|
|
336
|
-
url: this.baseUrl(),
|
|
337
|
-
method: 'GET',
|
|
338
|
-
};
|
|
339
|
-
await this.request(requestInfo);
|
|
340
|
-
}
|
|
341
|
-
async loadInstanceApiVersion() {
|
|
342
|
-
const authFileFields = this.options.authInfo.getFields();
|
|
343
|
-
const lastCheckedDateString = authFileFields.instanceApiVersionLastRetrieved;
|
|
344
|
-
let version = authFileFields.instanceApiVersion;
|
|
345
|
-
let lastChecked;
|
|
346
|
-
try {
|
|
347
|
-
if (lastCheckedDateString && (0, ts_types_1.isString)(lastCheckedDateString)) {
|
|
348
|
-
lastChecked = Date.parse(lastCheckedDateString);
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
catch (e) {
|
|
352
|
-
/* Do nothing, it will just request the version again */
|
|
353
|
-
}
|
|
354
|
-
// Grab the latest api version from the server and cache it in the auth file
|
|
355
|
-
const useLatest = async () => {
|
|
356
|
-
// verifies DNS
|
|
357
|
-
await this.useLatestApiVersion();
|
|
358
|
-
version = this.getApiVersion();
|
|
359
|
-
await this.options.authInfo.save({
|
|
360
|
-
instanceApiVersion: version,
|
|
361
|
-
// This will get messed up if the user changes their local time on their machine.
|
|
362
|
-
// Not a big deal since it will just get updated sooner/later.
|
|
363
|
-
instanceApiVersionLastRetrieved: new Date().toLocaleString(),
|
|
364
|
-
});
|
|
365
|
-
};
|
|
366
|
-
const ignoreCache = kit_1.env.getBoolean('SFDX_IGNORE_API_VERSION_CACHE', false);
|
|
367
|
-
if (lastChecked && !ignoreCache) {
|
|
368
|
-
const now = new Date();
|
|
369
|
-
const has24HoursPastSinceLastCheck = now.getTime() - lastChecked > kit_1.Duration.hours(24).milliseconds;
|
|
370
|
-
this.logger.debug(`Last checked on ${lastCheckedDateString} (now is ${now.toLocaleString()}) - ${has24HoursPastSinceLastCheck ? '' : 'not '}getting latest`);
|
|
371
|
-
if (has24HoursPastSinceLastCheck) {
|
|
372
|
-
await useLatest();
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
else {
|
|
376
|
-
this.logger.debug(`Using the latest because lastChecked=${lastChecked} and SFDX_IGNORE_API_VERSION_CACHE=${ignoreCache}`);
|
|
377
|
-
// No version found in the file (we never checked before)
|
|
378
|
-
// so get the latest.
|
|
379
|
-
await useLatest();
|
|
380
|
-
}
|
|
381
|
-
this.logger.debug(`Loaded latest org-api-version ${version}`);
|
|
382
|
-
return version;
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
exports.Connection = Connection;
|
|
386
|
-
exports.SingleRecordQueryErrors = {
|
|
387
|
-
NoRecords: 'SingleRecordQuery_NoRecords',
|
|
388
|
-
MultipleRecords: 'SingleRecordQuery_MultipleRecords',
|
|
389
|
-
};
|
|
390
|
-
// jsforce does some interesting proxy loading on lib classes.
|
|
391
|
-
// Setting this in the Connection.tooling getter will not work, it
|
|
392
|
-
// must be set on the prototype.
|
|
393
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
394
|
-
// @ts-ignore
|
|
395
|
-
tooling_1.Tooling.prototype.autoFetchQuery = Connection.prototype.autoFetchQuery; // eslint-disable-line @typescript-eslint/unbound-method
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2020, salesforce.com, inc.
|
|
4
|
+
* All rights reserved.
|
|
5
|
+
* Licensed under the BSD 3-Clause license.
|
|
6
|
+
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.SingleRecordQueryErrors = exports.Connection = exports.DNS_ERROR_NAME = exports.SFDX_HTTP_HEADERS = void 0;
|
|
10
|
+
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
11
|
+
const url_1 = require("url");
|
|
12
|
+
const kit_1 = require("@salesforce/kit");
|
|
13
|
+
const ts_types_1 = require("@salesforce/ts-types");
|
|
14
|
+
const jsforce_1 = require("jsforce");
|
|
15
|
+
const tooling_1 = require("jsforce/lib/api/tooling");
|
|
16
|
+
const myDomainResolver_1 = require("../status/myDomainResolver");
|
|
17
|
+
const configAggregator_1 = require("../config/configAggregator");
|
|
18
|
+
const logger_1 = require("../logger");
|
|
19
|
+
const sfError_1 = require("../sfError");
|
|
20
|
+
const sfdc_1 = require("../util/sfdc");
|
|
21
|
+
const messages_1 = require("../messages");
|
|
22
|
+
const lifecycleEvents_1 = require("../lifecycleEvents");
|
|
23
|
+
const orgConfigProperties_1 = require("./orgConfigProperties");
|
|
24
|
+
messages_1.Messages.importMessagesDirectory(__dirname);
|
|
25
|
+
const messages = messages_1.Messages.load('@salesforce/core', 'connection', [
|
|
26
|
+
'incorrectAPIVersionError',
|
|
27
|
+
'domainNotFoundError',
|
|
28
|
+
'noInstanceUrlError',
|
|
29
|
+
'noApiVersionsError',
|
|
30
|
+
]);
|
|
31
|
+
const clientId = `sfdx toolbelt:${process.env.SFDX_SET_CLIENT_IDS ?? ''}`;
|
|
32
|
+
exports.SFDX_HTTP_HEADERS = {
|
|
33
|
+
'content-type': 'application/json',
|
|
34
|
+
'user-agent': clientId,
|
|
35
|
+
};
|
|
36
|
+
exports.DNS_ERROR_NAME = 'DomainNotFoundError';
|
|
37
|
+
/**
|
|
38
|
+
* Handles connections and requests to Salesforce Orgs.
|
|
39
|
+
*
|
|
40
|
+
* ```
|
|
41
|
+
* // Uses latest API version
|
|
42
|
+
* const connection = await Connection.create({
|
|
43
|
+
* authInfo: await AuthInfo.create({ username: 'myAdminUsername' })
|
|
44
|
+
* });
|
|
45
|
+
* connection.query('SELECT Name from Account');
|
|
46
|
+
*
|
|
47
|
+
* // Use different API version
|
|
48
|
+
* connection.setApiVersion("42.0");
|
|
49
|
+
* connection.query('SELECT Name from Account');
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
class Connection extends jsforce_1.Connection {
|
|
53
|
+
/**
|
|
54
|
+
* Constructor
|
|
55
|
+
* **Do not directly construct instances of this class -- use {@link Connection.create} instead.**
|
|
56
|
+
*
|
|
57
|
+
* @param options The options for the class instance.
|
|
58
|
+
* @ignore
|
|
59
|
+
*/
|
|
60
|
+
constructor(options) {
|
|
61
|
+
super(options.connectionOptions ?? {});
|
|
62
|
+
this.options = options;
|
|
63
|
+
this.username = options.authInfo.getUsername();
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Tooling api reference.
|
|
67
|
+
*/
|
|
68
|
+
get tooling() {
|
|
69
|
+
return super.tooling;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Creates an instance of a Connection. Performs additional async initializations.
|
|
73
|
+
*
|
|
74
|
+
* @param options Constructor options.
|
|
75
|
+
*/
|
|
76
|
+
static async create(options) {
|
|
77
|
+
const baseOptions = {
|
|
78
|
+
version: options.connectionOptions?.version,
|
|
79
|
+
callOptions: {
|
|
80
|
+
client: clientId,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
if (!baseOptions.version) {
|
|
84
|
+
// Set the API version obtained from the config aggregator.
|
|
85
|
+
const configAggregator = options.configAggregator ?? (await configAggregator_1.ConfigAggregator.create());
|
|
86
|
+
baseOptions.version = (0, ts_types_1.asString)(configAggregator.getInfo('org-api-version').value);
|
|
87
|
+
}
|
|
88
|
+
const providedOptions = options.authInfo.getConnectionOptions();
|
|
89
|
+
// Get connection options from auth info and create a new jsForce connection
|
|
90
|
+
options.connectionOptions = Object.assign(baseOptions, providedOptions);
|
|
91
|
+
const conn = new this(options);
|
|
92
|
+
await conn.init();
|
|
93
|
+
try {
|
|
94
|
+
// No version passed in or in the config, so load one.
|
|
95
|
+
if (!baseOptions.version) {
|
|
96
|
+
const cachedVersion = await conn.loadInstanceApiVersion();
|
|
97
|
+
if (cachedVersion) {
|
|
98
|
+
conn.setApiVersion(cachedVersion);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
conn.logger.debug(`The org-api-version ${baseOptions.version} was found from ${options.connectionOptions?.version ? 'passed in options' : 'config'}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
const e = err;
|
|
107
|
+
if (e.name === exports.DNS_ERROR_NAME) {
|
|
108
|
+
throw e;
|
|
109
|
+
}
|
|
110
|
+
conn.logger.debug(`Error trying to load the API version: ${e.name} - ${e.message}`);
|
|
111
|
+
}
|
|
112
|
+
conn.logger.debug(`Using apiVersion ${conn.getApiVersion()}`);
|
|
113
|
+
return conn;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Async initializer.
|
|
117
|
+
*/
|
|
118
|
+
async init() {
|
|
119
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
120
|
+
this.logger = this.tooling._logger = await logger_1.Logger.child('connection');
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* deploy a zipped buffer from the SDRL with REST or SOAP
|
|
124
|
+
*
|
|
125
|
+
* @param zipInput data to deploy
|
|
126
|
+
* @param options JSForce deploy options + a boolean for rest
|
|
127
|
+
*/
|
|
128
|
+
async deploy(zipInput, options) {
|
|
129
|
+
const rest = options.rest;
|
|
130
|
+
// neither API expects this option
|
|
131
|
+
delete options.rest;
|
|
132
|
+
if (rest) {
|
|
133
|
+
this.logger.debug('deploy with REST');
|
|
134
|
+
await this.refreshAuth();
|
|
135
|
+
return this.metadata.deployRest(zipInput, options);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
this.logger.debug('deploy with SOAP');
|
|
139
|
+
return this.metadata.deploy(zipInput, options);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Send REST API request with given HTTP request info, with connected session information
|
|
144
|
+
* and SFDX headers.
|
|
145
|
+
*
|
|
146
|
+
* @param request HTTP request object or URL to GET request.
|
|
147
|
+
* @param options HTTP API request options.
|
|
148
|
+
*/
|
|
149
|
+
request(request, options) {
|
|
150
|
+
const httpRequest = (0, ts_types_1.isString)(request) ? { method: 'GET', url: request } : request;
|
|
151
|
+
httpRequest.headers = Object.assign({}, exports.SFDX_HTTP_HEADERS, httpRequest.headers);
|
|
152
|
+
this.logger.debug(`request: ${JSON.stringify(httpRequest)}`);
|
|
153
|
+
return super.request(httpRequest, options);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* The Force API base url for the instance.
|
|
157
|
+
*/
|
|
158
|
+
baseUrl() {
|
|
159
|
+
// essentially the same as pathJoin(super.instanceUrl, 'services', 'data', `v${super.version}`);
|
|
160
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
161
|
+
return super._baseUrl();
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Will deploy a recently validated deploy request - directly calling jsforce now that this is supported.
|
|
165
|
+
* WARNING: will always return a string from jsforce, the type is JsonCollection to support backwards compatibility
|
|
166
|
+
*
|
|
167
|
+
* @param options.id = the deploy ID that's been validated already from a previous checkOnly deploy request
|
|
168
|
+
* @param options.rest = a boolean whether or not to use the REST API
|
|
169
|
+
* @deprecated use {@link Connection.metadata#deployRecentValidation} instead - the jsforce implementation, instead of this wrapper
|
|
170
|
+
*/
|
|
171
|
+
async deployRecentValidation(options) {
|
|
172
|
+
// REST returns an object with an id property, SOAP returns the id as a string directly. That is now handled
|
|
173
|
+
// in jsforce, so we have to cast a string as unkown as JsonCollection to support backwards compatibility.
|
|
174
|
+
return (await this.metadata.deployRecentValidation(options));
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Retrieves the highest api version that is supported by the target server instance.
|
|
178
|
+
*/
|
|
179
|
+
async retrieveMaxApiVersion() {
|
|
180
|
+
await this.isResolvable();
|
|
181
|
+
const versions = await this.request(`${this.instanceUrl}/services/data`);
|
|
182
|
+
// if the server doesn't return a list of versions, it's possibly a instanceUrl issue where the local file is out of date.
|
|
183
|
+
if (!Array.isArray(versions)) {
|
|
184
|
+
this.logger.debug(`server response for retrieveMaxApiVersion: ${versions}`);
|
|
185
|
+
throw messages.createError('noApiVersionsError');
|
|
186
|
+
}
|
|
187
|
+
this.logger.debug(`response for org versions: ${versions.map((item) => item.version).join(',')}`);
|
|
188
|
+
const max = (0, ts_types_1.ensure)((0, kit_1.maxBy)(versions, (version) => version.version));
|
|
189
|
+
return max.version;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Use the latest API version available on `this.instanceUrl`.
|
|
193
|
+
*/
|
|
194
|
+
async useLatestApiVersion() {
|
|
195
|
+
try {
|
|
196
|
+
this.setApiVersion(await this.retrieveMaxApiVersion());
|
|
197
|
+
}
|
|
198
|
+
catch (err) {
|
|
199
|
+
const error = err;
|
|
200
|
+
if (error.name === exports.DNS_ERROR_NAME) {
|
|
201
|
+
throw error; // throws on DNS connection errors
|
|
202
|
+
}
|
|
203
|
+
// Don't fail if we can't use the latest, just use the default
|
|
204
|
+
this.logger.warn('Failed to set the latest API version:', error);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Verify that instance has a reachable DNS entry, otherwise will throw error
|
|
209
|
+
*/
|
|
210
|
+
async isResolvable() {
|
|
211
|
+
if (!this.options.connectionOptions?.instanceUrl) {
|
|
212
|
+
throw messages.createError('noInstanceUrlError');
|
|
213
|
+
}
|
|
214
|
+
const resolver = await myDomainResolver_1.MyDomainResolver.create({
|
|
215
|
+
url: new url_1.URL(this.options.connectionOptions.instanceUrl),
|
|
216
|
+
});
|
|
217
|
+
try {
|
|
218
|
+
await resolver.resolve();
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
catch (e) {
|
|
222
|
+
throw messages.createError('domainNotFoundError', [], [], e);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Get the API version used for all connection requests.
|
|
227
|
+
*/
|
|
228
|
+
getApiVersion() {
|
|
229
|
+
return this.version;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Set the API version for all connection requests.
|
|
233
|
+
*
|
|
234
|
+
* **Throws** *{@link SfError}{ name: 'IncorrectAPIVersionError' }* Incorrect API version.
|
|
235
|
+
*
|
|
236
|
+
* @param version The API version.
|
|
237
|
+
*/
|
|
238
|
+
setApiVersion(version) {
|
|
239
|
+
if (!sfdc_1.sfdc.validateApiVersion(version)) {
|
|
240
|
+
throw messages.createError('incorrectAPIVersionError', [version]);
|
|
241
|
+
}
|
|
242
|
+
this.version = version;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Getter for AuthInfo.
|
|
246
|
+
*/
|
|
247
|
+
getAuthInfo() {
|
|
248
|
+
return this.options.authInfo;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Getter for the AuthInfo fields.
|
|
252
|
+
*/
|
|
253
|
+
getAuthInfoFields() {
|
|
254
|
+
// If the StateAggregator.orgs.remove is called, the AuthFields are no longer accessible.
|
|
255
|
+
return this.options.authInfo.getFields() || {};
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Getter for the auth fields.
|
|
259
|
+
*/
|
|
260
|
+
getConnectionOptions() {
|
|
261
|
+
return this.options.authInfo.getConnectionOptions();
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Getter for the username of the Salesforce Org.
|
|
265
|
+
*/
|
|
266
|
+
getUsername() {
|
|
267
|
+
return this.username;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Returns true if this connection is using access token auth.
|
|
271
|
+
*/
|
|
272
|
+
isUsingAccessToken() {
|
|
273
|
+
return this.options.authInfo.isUsingAccessToken();
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Normalize a Salesforce url to include a instance information.
|
|
277
|
+
*
|
|
278
|
+
* @param url Partial url.
|
|
279
|
+
*/
|
|
280
|
+
normalizeUrl(url) {
|
|
281
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
282
|
+
return this._normalizeUrl(url);
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Executes a query and auto-fetches (i.e., "queryMore") all results. This is especially
|
|
286
|
+
* useful with large query result sizes, such as over 2000 records. The default maximum
|
|
287
|
+
* fetch size is 10,000 records. Modify this via the options argument.
|
|
288
|
+
*
|
|
289
|
+
* @param soql The SOQL string.
|
|
290
|
+
* @param queryOptions The query options. NOTE: the autoFetch option will always be true.
|
|
291
|
+
*/
|
|
292
|
+
async autoFetchQuery(soql, queryOptions = { tooling: false }) {
|
|
293
|
+
const config = await configAggregator_1.ConfigAggregator.create();
|
|
294
|
+
// take the limit from the calling function, then the config, then default 10,000
|
|
295
|
+
const maxFetch = (config.getInfo(orgConfigProperties_1.OrgConfigProperties.ORG_MAX_QUERY_LIMIT).value || queryOptions.maxFetch) ?? 10000;
|
|
296
|
+
const { tooling, ...queryOptionsWithoutTooling } = queryOptions;
|
|
297
|
+
const options = Object.assign(queryOptionsWithoutTooling, {
|
|
298
|
+
autoFetch: true,
|
|
299
|
+
maxFetch,
|
|
300
|
+
});
|
|
301
|
+
const query = tooling ? await this.tooling.query(soql, options) : await this.query(soql, options);
|
|
302
|
+
if (query.records.length && query.totalSize > query.records.length) {
|
|
303
|
+
void lifecycleEvents_1.Lifecycle.getInstance().emitWarning(`The query result is missing ${query.totalSize - query.records.length} records due to a ${maxFetch} record limit. Increase the number of records returned by setting the config value "maxQueryLimit" or the environment variable "SFDX_MAX_QUERY_LIMIT" to ${query.totalSize} or greater than ${maxFetch}.`);
|
|
304
|
+
}
|
|
305
|
+
return query;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Executes a query using either standard REST or Tooling API, returning a single record.
|
|
309
|
+
* Will throw if either zero records are found OR multiple records are found.
|
|
310
|
+
*
|
|
311
|
+
* @param soql The SOQL string.
|
|
312
|
+
* @param options The query options.
|
|
313
|
+
*/
|
|
314
|
+
async singleRecordQuery(soql, options = {
|
|
315
|
+
choiceField: 'Name',
|
|
316
|
+
}) {
|
|
317
|
+
const result = options.tooling ? await this.tooling.query(soql) : await this.query(soql);
|
|
318
|
+
if (result.totalSize === 0) {
|
|
319
|
+
throw new sfError_1.SfError(`No record found for ${soql}`, exports.SingleRecordQueryErrors.NoRecords);
|
|
320
|
+
}
|
|
321
|
+
if (result.totalSize > 1) {
|
|
322
|
+
throw new sfError_1.SfError(options.returnChoicesOnMultiple
|
|
323
|
+
? // eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
324
|
+
`Multiple records found. ${result.records.map((item) => item[options.choiceField]).join(',')}`
|
|
325
|
+
: 'The query returned more than 1 record', exports.SingleRecordQueryErrors.MultipleRecords);
|
|
326
|
+
}
|
|
327
|
+
return result.records[0];
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Executes a get request on the baseUrl to force an auth refresh
|
|
331
|
+
* Useful for the raw methods (request, requestRaw) that use the accessToken directly and don't handle refreshes
|
|
332
|
+
*/
|
|
333
|
+
async refreshAuth() {
|
|
334
|
+
this.logger.debug('Refreshing auth for org.');
|
|
335
|
+
const requestInfo = {
|
|
336
|
+
url: this.baseUrl(),
|
|
337
|
+
method: 'GET',
|
|
338
|
+
};
|
|
339
|
+
await this.request(requestInfo);
|
|
340
|
+
}
|
|
341
|
+
async loadInstanceApiVersion() {
|
|
342
|
+
const authFileFields = this.options.authInfo.getFields();
|
|
343
|
+
const lastCheckedDateString = authFileFields.instanceApiVersionLastRetrieved;
|
|
344
|
+
let version = authFileFields.instanceApiVersion;
|
|
345
|
+
let lastChecked;
|
|
346
|
+
try {
|
|
347
|
+
if (lastCheckedDateString && (0, ts_types_1.isString)(lastCheckedDateString)) {
|
|
348
|
+
lastChecked = Date.parse(lastCheckedDateString);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
catch (e) {
|
|
352
|
+
/* Do nothing, it will just request the version again */
|
|
353
|
+
}
|
|
354
|
+
// Grab the latest api version from the server and cache it in the auth file
|
|
355
|
+
const useLatest = async () => {
|
|
356
|
+
// verifies DNS
|
|
357
|
+
await this.useLatestApiVersion();
|
|
358
|
+
version = this.getApiVersion();
|
|
359
|
+
await this.options.authInfo.save({
|
|
360
|
+
instanceApiVersion: version,
|
|
361
|
+
// This will get messed up if the user changes their local time on their machine.
|
|
362
|
+
// Not a big deal since it will just get updated sooner/later.
|
|
363
|
+
instanceApiVersionLastRetrieved: new Date().toLocaleString(),
|
|
364
|
+
});
|
|
365
|
+
};
|
|
366
|
+
const ignoreCache = kit_1.env.getBoolean('SFDX_IGNORE_API_VERSION_CACHE', false);
|
|
367
|
+
if (lastChecked && !ignoreCache) {
|
|
368
|
+
const now = new Date();
|
|
369
|
+
const has24HoursPastSinceLastCheck = now.getTime() - lastChecked > kit_1.Duration.hours(24).milliseconds;
|
|
370
|
+
this.logger.debug(`Last checked on ${lastCheckedDateString} (now is ${now.toLocaleString()}) - ${has24HoursPastSinceLastCheck ? '' : 'not '}getting latest`);
|
|
371
|
+
if (has24HoursPastSinceLastCheck) {
|
|
372
|
+
await useLatest();
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
this.logger.debug(`Using the latest because lastChecked=${lastChecked} and SFDX_IGNORE_API_VERSION_CACHE=${ignoreCache}`);
|
|
377
|
+
// No version found in the file (we never checked before)
|
|
378
|
+
// so get the latest.
|
|
379
|
+
await useLatest();
|
|
380
|
+
}
|
|
381
|
+
this.logger.debug(`Loaded latest org-api-version ${version}`);
|
|
382
|
+
return version;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
exports.Connection = Connection;
|
|
386
|
+
exports.SingleRecordQueryErrors = {
|
|
387
|
+
NoRecords: 'SingleRecordQuery_NoRecords',
|
|
388
|
+
MultipleRecords: 'SingleRecordQuery_MultipleRecords',
|
|
389
|
+
};
|
|
390
|
+
// jsforce does some interesting proxy loading on lib classes.
|
|
391
|
+
// Setting this in the Connection.tooling getter will not work, it
|
|
392
|
+
// must be set on the prototype.
|
|
393
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
394
|
+
// @ts-ignore
|
|
395
|
+
tooling_1.Tooling.prototype.autoFetchQuery = Connection.prototype.autoFetchQuery; // eslint-disable-line @typescript-eslint/unbound-method
|
|
396
396
|
//# sourceMappingURL=connection.js.map
|