UNPKG

8.02 kBJavaScriptView Raw
1"use strict";
2/*
3 * Copyright (c) 2018, salesforce.com, inc.
4 * All rights reserved.
5 * SPDX-License-Identifier: BSD-3-Clause
6 * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
7 */
8Object.defineProperty(exports, "__esModule", { value: true });
9const kit_1 = require("@salesforce/kit");
10const ts_types_1 = require("@salesforce/ts-types");
11const jsforce_1 = require("jsforce");
12const jsforce_2 = require("jsforce");
13const configAggregator_1 = require("./config/configAggregator");
14const logger_1 = require("./logger");
15const sfdxError_1 = require("./sfdxError");
16const sfdc_1 = require("./util/sfdc");
17/**
18 * The 'async' in our request override replaces the jsforce promise with the node promise, then returns it back to
19 * jsforce which expects .thenCall. Add .thenCall to the node promise to prevent breakage.
20 */
21// @ts-ignore
22Promise.prototype.thenCall = jsforce_2.Promise.prototype.thenCall;
23const clientId = `sfdx toolbelt:${process.env.SFDX_SET_CLIENT_IDS || ''}`;
24exports.SFDX_HTTP_HEADERS = {
25 'content-type': 'application/json',
26 'user-agent': clientId
27};
28/**
29 * Handles connections and requests to Salesforce Orgs.
30 *
31 * ```
32 * // Uses latest API version
33 * const connection = await Connection.create({
34 * authInfo: await AuthInfo.create({ username: 'myAdminUsername' })
35 * });
36 * connection.query('SELECT Name from Account');
37 *
38 * // Use different API version
39 * connection.setApiVersion("42.0");
40 * connection.query('SELECT Name from Account');
41 * ```
42 */
43class Connection extends jsforce_1.Connection {
44 /**
45 * Creates an instance of a Connection. Performs additional async initializations.
46 * @param options Constructor options.
47 */
48 static async create(options) {
49 const _aggregator = options.configAggregator || (await configAggregator_1.ConfigAggregator.create());
50 const versionFromConfig = ts_types_1.asString(_aggregator.getInfo('apiVersion').value);
51 const baseOptions = {
52 // Set the API version obtained from the config aggregator.
53 // Will use jsforce default if undefined.
54 version: versionFromConfig,
55 callOptions: {
56 client: clientId
57 }
58 };
59 // Get connection options from auth info and create a new jsForce connection
60 options.connectionOptions = Object.assign(baseOptions, options.authInfo.getConnectionOptions());
61 const conn = new this(options);
62 await conn.init();
63 if (!versionFromConfig) {
64 await conn.useLatestApiVersion();
65 }
66 return conn;
67 }
68 /**
69 * Constructor
70 * **Do not directly construct instances of this class -- use {@link Connection.create} instead.**
71 * @param options The options for the class instance.
72 * @ignore
73 */
74 constructor(options) {
75 super(options.connectionOptions || {});
76 this.tooling.autoFetchQuery = Connection.prototype.autoFetchQuery;
77 this.options = options;
78 }
79 /**
80 * Async initializer.
81 */
82 async init() {
83 this.logger = this._logger = this.tooling._logger = await logger_1.Logger.child('connection');
84 }
85 /**
86 * Send REST API request with given HTTP request info, with connected session information
87 * and SFDX headers.
88 *
89 * @param request HTTP request object or URL to GET request.
90 * @param options HTTP API request options.
91 */
92 async request(request, options) {
93 const _request = ts_types_1.isString(request) ? { method: 'GET', url: request } : request;
94 _request.headers = Object.assign({}, exports.SFDX_HTTP_HEADERS, _request.headers);
95 this.logger.debug(`request: ${JSON.stringify(_request)}`);
96 // The "as" is a workaround for the jsforce typings.
97 return super.request(_request, options);
98 }
99 /**
100 * Send REST API request with given HTTP request info, with connected session information
101 * and SFDX headers. This method returns a raw http response which includes a response body and statusCode.
102 *
103 * @param request HTTP request object or URL to GET request.
104 */
105 async requestRaw(request) {
106 const _headers = this.accessToken ? { Authorization: `Bearer ${this.accessToken}` } : {};
107 kit_1.merge(_headers, exports.SFDX_HTTP_HEADERS, request.headers);
108 return this._transport.httpRequest({
109 method: request.method,
110 url: request.url,
111 headers: _headers,
112 body: request.body
113 });
114 }
115 /**
116 * The Force API base url for the instance.
117 */
118 baseUrl() {
119 // essentially the same as pathJoin(super.instanceUrl, 'services', 'data', `v${super.version}`);
120 return super._baseUrl();
121 }
122 /**
123 * Retrieves the highest api version that is supported by the target server instance.
124 */
125 async retrieveMaxApiVersion() {
126 const versions = (await this.request(`${this.instanceUrl}/services/data`));
127 this.logger.debug(`response for org versions: ${versions}`);
128 const max = ts_types_1.ensure(kit_1.maxBy(versions, (version) => version.version));
129 return max.version;
130 }
131 /**
132 * Use the latest API version available on `this.instanceUrl`.
133 */
134 async useLatestApiVersion() {
135 try {
136 this.setApiVersion(await this.retrieveMaxApiVersion());
137 }
138 catch (err) {
139 // Don't fail if we can't use the latest, just use the default
140 this.logger.warn('Failed to set the latest API version:', err);
141 }
142 }
143 /**
144 * Get the API version used for all connection requests.
145 */
146 getApiVersion() {
147 return this.version;
148 }
149 /**
150 * Set the API version for all connection requests.
151 *
152 * **Throws** *{@link SfdxError}{ name: 'IncorrectAPIVersion' }* Incorrect API version.
153 * @param version The API version.
154 */
155 setApiVersion(version) {
156 if (!sfdc_1.sfdc.validateApiVersion(version)) {
157 throw new sfdxError_1.SfdxError(`Invalid API version ${version}. Expecting format "[1-9][0-9].0", i.e. 42.0`, 'IncorrectAPIVersion');
158 }
159 this.version = version;
160 }
161 /**
162 * Getter for the AuthInfo.
163 */
164 getAuthInfoFields() {
165 return this.options.authInfo.getFields();
166 }
167 /**
168 * Getter for the auth fields.
169 */
170 getConnectionOptions() {
171 return this.options.authInfo.getConnectionOptions();
172 }
173 /**
174 * Getter for the username of the Salesforce Org.
175 */
176 getUsername() {
177 return this.getAuthInfoFields().username;
178 }
179 /**
180 * Returns true if this connection is using access token auth.
181 */
182 isUsingAccessToken() {
183 return this.options.authInfo.isUsingAccessToken();
184 }
185 /**
186 * Normalize a Salesforce url to include a instance information.
187 * @param url Partial url.
188 */
189 normalizeUrl(url) {
190 return this._normalizeUrl(url);
191 }
192 /**
193 * Executes a query and auto-fetches (i.e., "queryMore") all results. This is especially
194 * useful with large query result sizes, such as over 2000 records. The default maximum
195 * fetch size is 10,000 records. Modify this via the options argument.
196 * @param soql The SOQL string.
197 * @param options The query options. NOTE: the autoFetch option will always be true.
198 */
199 async autoFetchQuery(soql, options = {}) {
200 const _options = Object.assign(options, {
201 autoFetch: true
202 });
203 const records = [];
204 this._logger.debug(`Auto-fetching query: ${soql}`);
205 return new Promise((resolve, reject) => this.query(soql, _options)
206 .on('record', rec => records.push(rec))
207 .on('error', err => reject(err))
208 .on('end', () => resolve({
209 done: true,
210 totalSize: records.length,
211 records
212 })));
213 }
214}
215exports.Connection = Connection;
216//# sourceMappingURL=connection.js.map
\No newline at end of file