UNPKG

salesforce-alm

Version:

This package contains tools, and APIs, for an improved salesforce.com developer experience.

217 lines (215 loc) 10.1 kB
"use strict"; /* * Copyright (c) 2020, salesforce.com, inc. * All rights reserved. * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ /* -------------------------------------------------------------------------------------------------------------------- * WARNING: This file has been deprecated and should now be considered locked against further changes. Its contents * have been partially or wholely superceded by functionality included in the @salesforce/core npm package, and exists * now to service prior uses in this repository only until they can be ported to use the new @salesforce/core library. * * If you need or want help deciding where to add new functionality or how to migrate to the new library, please * contact the CLI team at alm-cli@salesforce.com. * ----------------------------------------------------------------------------------------------------------------- */ // Thirdparty const jsforce = require("jsforce"); const optional = require("optional-js"); const requestModule = require("request"); // Local const configApi_1 = require("./configApi"); const logger = require("./logApi"); const core_1 = require("@salesforce/core"); const almError = require("./almError"); const messages = require("../messages"); const srcDevUtil = require("./srcDevUtil"); const core_2 = require("@salesforce/core"); const jsforceRequestMethod = jsforce.Connection.prototype.request; const callOptionsValue = { client: srcDevUtil.getSfdxCLIClientId(), }; // Get a @salesforce/core Connection, which extends jsforce.Connection. const getCoreConnection = async (username, options) => { const conn = await core_1.Connection.create({ authInfo: await core_1.AuthInfo.create({ username, oauth2Options: options }), }); return conn; }; const getCoreConnectionFromOrgApi = async (orgApi) => { const orgUserName = orgApi.getName(); const options = orgUserName ? null : orgApi.authConfig; return getCoreConnection(orgUserName, options); }; /** * Internally we want to override jsforce::connection so we can inject our own http headers for all requests. * JSforce has limited support for enabling HTTP headers, only certain apis support the http header option. * With this strategy all requests are supported. Also see status.js. StreamingApi is managed as well. */ jsforce.Connection.prototype.request = function (request, options, callback) { const _request = srcDevUtil.setSfdxRequestHeaders(request, options); return jsforceRequestMethod.apply(this, [_request, options, callback]); }; const Force = function (config) { this.config = optional.ofNullable(config).orElse(new configApi_1.Config()); this.logger = logger.child('force'); }; Force.prototype.debug = function (orgApi, msg) { if (this.logger.isDebugEnabled()) { if (orgApi && orgApi.getName) { this.logger.setConfig('org', orgApi.getName()); } this.logger.debug(msg); } }; Force.prototype.getConfig = function () { return this.config; }; Force.prototype.create = async function (orgApi, sobjectName, sobject) { this.debug(orgApi, `create: ${sobjectName}`, { sobject }); const connection = await getCoreConnectionFromOrgApi(orgApi); try { await connection.sobject(sobjectName).describe(); return connection.sobject(sobjectName).create(sobject); } catch (err) { if (err.errorCode === 'NOT_FOUND') { err['message'] = messages().getMessage('createOrgCommandUnauthorized', sobjectName); err['name'] = 'ACCESS_DENIED'; } throw err; } }; Force.prototype.update = async function (orgApi, sobjectName, sobject) { this.debug(orgApi, `update: ${sobjectName}, ${sobject}`); return (await getCoreConnectionFromOrgApi(orgApi)).sobject(sobjectName).update(sobject); }; Force.prototype.delete = async function (orgApi, sobjectName, id) { this.debug(orgApi, `delete: ${sobjectName}, ${id}`); return (await getCoreConnectionFromOrgApi(orgApi)).sobject(sobjectName).delete(id); }; Force.prototype.describe = async function (orgApi, sobjectName) { this.debug(orgApi, `describe: ${sobjectName}`); return (await getCoreConnectionFromOrgApi(orgApi)).sobject(sobjectName).describe(); }; Force.prototype.find = async function (orgApi, sobjectName, conditions, fields) { return (await getCoreConnectionFromOrgApi(orgApi)).sobject(sobjectName).find(conditions, fields); }; // NOTE: All queries will auto fetch results up to 10,000 records. Force.prototype.query = async function (orgApi, query) { this.debug(orgApi, `query: ${query}`); return (await getCoreConnectionFromOrgApi(orgApi)).autoFetchQuery(query); }; Force.prototype.retrieve = async function (orgApi, sobjectName, id) { this.debug(orgApi, `toolingRetrieve: ${sobjectName}, ${id}`); return (await getCoreConnectionFromOrgApi(orgApi)).tooling.sobject(sobjectName).retrieve(id); }; Force.prototype.getApiVersions = function (orgApi) { return orgApi.getConfig().then((orgConfig) => { const url = `${orgConfig.instanceUrl}/services/data`; return this.request(orgApi, 'GET', url, this.config); }); }; Force.prototype.toolingCreate = async function (orgApi, sobjectName, sobject) { this.debug(orgApi, `toolingCreate: ${sobjectName}`, { sobject }); return (await getCoreConnectionFromOrgApi(orgApi)).tooling.sobject(sobjectName).create(sobject); }; Force.prototype.toolingUpdate = async function (orgApi, sobjectName, sobjectRecord) { return (await getCoreConnectionFromOrgApi(orgApi)).tooling.sobject(sobjectName).update(sobjectRecord); }; Force.prototype.toolingFind = async function (orgApi, sobjectName, conditions, fields) { return (await getCoreConnectionFromOrgApi(orgApi)).tooling.sobject(sobjectName).find(conditions, fields); }; // NOTE: all tooling queries will auto fetch results up to 10,000 records. Force.prototype.toolingQuery = async function (orgApi, query) { this.debug(orgApi, `toolingQuery: ${query}`); const orgUserName = orgApi.getName(); const options = orgUserName ? null : orgApi.authConfig; const connection = await getCoreConnection(orgUserName, options); return connection.tooling.autoFetchQuery(query); }; Force.prototype.toolingRetrieve = async function (orgApi, sobjectName, id) { this.debug(orgApi, `toolingRetrieve: ${sobjectName}, ${id}`); return (await getCoreConnectionFromOrgApi(orgApi)).tooling.sobject(sobjectName).retrieve(id); }; // generic request to given URL w/ body and headers Force.prototype.request = async function (orgApi, method, url, headers, body) { this.debug(orgApi, `request: ${url}`); // ensure string body body = typeof body === 'string' ? body : JSON.stringify(body); if (!headers) { headers = {}; } const conn = await getCoreConnectionFromOrgApi(orgApi); if (conn.accessToken) { headers.Authorization = `Bearer ${conn.accessToken}`; } return conn.requestRaw({ method, url, headers, body }); }; Force.prototype.mdapiSoapDeploy = async function (orgApi, zipStream, options) { return (await getCoreConnectionFromOrgApi(orgApi)).metadata.deploy(zipStream, options !== null && options !== void 0 ? options : {}); }; Force.prototype.getRestHeaders = function (connection) { return { Authorization: connection && `OAuth ${connection.accessToken}`, clientId: connection.oauth2 && connection.oauth2.clientId, 'Sforce-Call-Options': `client=${callOptionsValue.client}`, }; }; Force.prototype.mdapiRestDeploy = async function (orgApi, zipStream, options) { const connection = await getCoreConnectionFromOrgApi(orgApi); const headers = this.getRestHeaders(connection); const url = `${connection.instanceUrl.replace(/\/$/, '')}/services/data/v${this.config.getApiVersion()}/metadata/deployRequest`; return new Promise((resolve, reject) => { const r = requestModule.post(url, { headers }, (err, httpResponse, body) => { try { body = JSON.parse(body); } catch (e) { reject(core_2.SfdxError.wrap(body)); } if (err || httpResponse.statusCode > 300) { let error; if (body[0].errorCode === 'API_DISABLED_FOR_ORG') { error = almError('mdDeployCommandCliNoRestDeploy'); } else { error = new Error(`${body[0].errorCode}: ${body[0].message}`); } reject(error); } else { resolve(body); } }); const form = r.form(); // Add the zip file form.append('file', zipStream, { contentType: 'application/zip', }); // Add the deploy options form.append('entity_content', JSON.stringify({ deployOptions: options }), { contentType: 'application/json', }); }); }; Force.prototype.mdapiCheckDeployStatus = async function (orgApi, jobId) { return (await getCoreConnectionFromOrgApi(orgApi)).metadata.checkDeployStatus(jobId, true); }; Force.prototype.mdapiCheckRetrieveStatus = async function (orgApi, jobId) { const result = await (await getCoreConnectionFromOrgApi(orgApi)).metadata.checkRetrieveStatus(jobId); // if you look at what @types/jsforce thinks checkRetrieveStatus returns, done and success are invalid properties. // but if we don't set them, the NUTs will fail. // someday this will all be moot and use SDR instead // @ts-ignore return { ...result, done: result.done === 'true', success: result.success === 'true' }; }; // metadata api retrieve; options contains what to retrieve Force.prototype.mdapiRetrieve = async function (orgApi, options) { return (await getCoreConnectionFromOrgApi(orgApi)).metadata.retrieve(options); }; Force.prototype.setCallOptions = function (key, value) { callOptionsValue[key] = value; }; module.exports = Force; //# sourceMappingURL=force.js.map