Skip to content

Commit

Permalink
fix: deploy with REST working :)
Browse files Browse the repository at this point in the history
  • Loading branch information
WillieRuemmele committed Mar 25, 2021
1 parent 0b3947b commit ec36851
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 99 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
"@types/jsforce": "1.9.23",
"@types/mkdirp": "1.0.0",
"debug": "^3.1.0",
"form-data": "^4.0.0",
"graceful-fs": "^4.2.4",
"jsen": "0.6.6",
"jsforce": "^1.10.0",
Expand Down
127 changes: 53 additions & 74 deletions src/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* 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
*/
import * as fs from 'fs';
import * as os from 'os';
import { Stream } from 'stream';
import { URL } from 'url';
import { AsyncResult, DeployOptions, DeployResultLocator } from 'jsforce/api/metadata';
Expand All @@ -28,17 +30,18 @@ import {
QueryResult,
RequestInfo,
Tooling as JSForceTooling,
// Metadata as JSForceMetadata,
} from 'jsforce';
// Transport is not _really_ exported and there's no types
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
import * as Transport from 'jsforce/lib/transport';
import { AuthFields, AuthInfo } from './authInfo';
import { MyDomainResolver } from './status/myDomainResolver';

import { ConfigAggregator } from './config/configAggregator';
import { Logger } from './logger';
import { SfdxError } from './sfdxError';
import { sfdc } from './util/sfdc';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const FormData = require('form-data');

/**
* The 'async' in our request override replaces the jsforce promise with the node promise, then returns it back to
Expand Down Expand Up @@ -71,20 +74,6 @@ export interface Tooling extends JSForceTooling {
*/
autoFetchQuery<T>(soql: string, options?: ExecuteOptions): Promise<QueryResult<T>>;
}
//
// export interface Metadata extends JSForceMetadata {
// /**
// *
// * @param zipInput
// * @param options The query options. NOTE: the autoFetch option will always be true.
// * @param callback
// */
// deploy(
// zipInput: Stream | Buffer | string,
// options: deployOptions,
// callback?: Callback<AsyncResult>
// ): DeployResultLocator<AsyncResult>;
// }

/**
* Handles connections and requests to Salesforce Orgs.
Expand All @@ -107,7 +96,6 @@ export class Connection extends JSForceConnection {
* Tooling api reference.
*/
public tooling!: Tooling;
// public metadata!: Metadata;
// We want to use 1 logger for this class and the jsForce base classes so override
// the jsForce connection.tooling.logger and connection.logger.
private logger!: Logger;
Expand All @@ -127,10 +115,10 @@ export class Connection extends JSForceConnection {

// eslint-disable-next-line @typescript-eslint/unbound-method
this.tooling.autoFetchQuery = Connection.prototype.autoFetchQuery;
// this.metadata.deploy = Connection.prototype.deploy.bind(this);

this.options = options;
}

/**
* Creates an instance of a Connection. Performs additional async initializations.
*
Expand Down Expand Up @@ -183,6 +171,16 @@ export class Connection extends JSForceConnection {
return conn;
}

private static createReadStreamFromBuffer(buffer: Buffer) {
const t = os.tmpdir() + '/temp';
fs.mkdirSync(t);
const file = t + '/abc.zip';
fs.writeFileSync(file, buffer);
const f = fs.createReadStream(file);
fs.unlinkSync(file);
fs.rmdirSync(t);
return f;
}
/**
* Async initializer.
*/
Expand All @@ -197,65 +195,46 @@ export class Connection extends JSForceConnection {
callback?: Callback<AsyncResult>
): Promise<DeployResultLocator<AsyncResult>> {
if (options.rest) {
const headers: { Authorization: string; clientId: string; 'Sforce-Call-Options': string } = {
// the API is not expecting this
delete options.rest;
const headers = {
Authorization: this && `OAuth ${this.accessToken}`,
clientId: this.oauth2 && this.oauth2.clientId,
'Sforce-Call-Options': 'client=sfdx-core',
};
const url = `${this.instanceUrl.replace(
/\/$/,
''
)}/services/data/v${this.getApiVersion()}/metadata/deployRequest`;
const form = new FormData();
form.append('file', zipInput, { contentType: 'application/zip' });
form.append('entity_content', JSON.stringify({ deployOptions: options }), { contentType: 'application/json' });

return ((await this.request({
url,
headers,
method: 'POST',
body: form.toString(),
})) as unknown) as DeployResultLocator<AsyncResult>;

// return new Promise((resolve) => {
// form.submit(
// {
// headers,
// host: this.instanceUrl,
// path: `/services/data/v${this.getApiVersion()}/metadata/deployRequest`,
// },
// (error: Error | null, response: IncomingMessage) => {
// // eslint-disable-next-line no-console
// console.log('done', error, response);
// res = response;
// resolve((res as unknown) as DeployResultLocator<AsyncResult>);
// }
// );
// });

// const r = requestModule.post(url, { headers }, (err, httpResponse, body) => {
// try {
// body = JSON.parse(body);
// } catch (e) {c
// reject(SfdxError.wrap(body));
// }
// if (err || httpResponse.statusCode > 300) {
// reject(new Error(`${body[0].errorCode}: ${body[0].message}`));
// } else {
// resolve(body);
// }
// });
// const form = r.form();
//
// // Add the zip file
// form.append('file', zipInput, {
// contentType: 'application/zip',
// });
//
// // Add the deploy options
// form.append('entity_content', JSON.stringify({ deployOptions: options }), {
// contentType: 'application/json',
// });
const url = `${this.baseUrl()}/metadata/deployRequest`;
const req = Transport.prototype._getHttpRequestModule();

return await new Promise((resolve, reject) => {
const r = req.post(url, { headers }, (err: Error, httpResponse: { statusCode: number }, body: string) => {
let res;
try {
res = JSON.parse(body);
} catch (e) {
reject(SfdxError.wrap(body));
}
if (err || httpResponse.statusCode > 300) {
if (body) {
reject(new Error(`${res[0].errorCode}: ${res[0].message}`));
}
} else {
resolve(res);
}
});
const form = r.form();

const s = Connection.createReadStreamFromBuffer(zipInput as Buffer);

// Add the zip file
form.append('file', s, {
contentType: 'application/zip',
});

// Add the deploy options
form.append('entity_content', JSON.stringify({ deployOptions: options }), {
contentType: 'application/json',
});
});
} else {
return this.metadata.deploy(zipInput, options, callback);
}
Expand Down
39 changes: 15 additions & 24 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -580,9 +580,9 @@
integrity sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==

"@types/node@*":
version "14.14.35"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.35.tgz#42c953a4e2b18ab931f72477e7012172f4ffa313"
integrity sha512-Lt+wj8NVPx0zUmUwumiVXapmaLUcAk3yPuHCFVXras9k5VT9TdhJqKqGVUQCD60OTMCl0qxJ57OiTL0Mic3Iag==
version "14.14.36"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.36.tgz#5637905dbb15c30a33a3c65b9ef7c20e3c85ebad"
integrity sha512-kjivUwDJfIjngzbhooRnOLhGYz6oRFi+L+EpMjxroDYXwDw9lHrJJ43E+dJ6KAd3V3WxWAJ/qZE9XKYHhjPOFQ==

"@types/node@^12.12.6":
version "12.20.6"
Expand Down Expand Up @@ -1245,7 +1245,7 @@ colorette@^1.2.1:
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94"
integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==

combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
combined-stream@^1.0.6, combined-stream@~1.0.6:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
Expand Down Expand Up @@ -1651,9 +1651,9 @@ ecdsa-sig-formatter@1.0.11:
safe-buffer "^5.0.1"

electron-to-chromium@^1.3.649:
version "1.3.699"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.699.tgz#854eea9db8bc8109c409a4807bfdb200dd75a2c7"
integrity sha512-fjt43CPXdPYwD9ybmKbNeLwZBmCVdLY2J5fGZub7/eMPuiqQznOGNXv/wurnpXIlE7ScHnvG9Zi+H4/i6uMKmw==
version "1.3.700"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.700.tgz#a6999a954c698dc7da5e84c369d65432dbe895be"
integrity sha512-wQtaxVZzpOeCjW1CGuC5W3bYjE2jglvk076LcTautBOB9UtHztty7wNzjVsndiMcSsdUsdMy5w76w5J1U7OPTQ==

emoji-regex@^7.0.1:
version "7.0.3"
Expand Down Expand Up @@ -2213,15 +2213,6 @@ forever-agent@~0.6.1:
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=

form-data@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"

form-data@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
Expand Down Expand Up @@ -2486,7 +2477,7 @@ hard-rejection@^2.1.0:
resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883"
integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==

has-bigints@^1.0.0:
has-bigints@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113"
integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==
Expand Down Expand Up @@ -5314,14 +5305,14 @@ uglify-js@^3.1.4:
integrity sha512-SbMu4D2Vo95LMC/MetNaso1194M1htEA+JrqE9Hk+G2DhI+itfS9TRu9ZKeCahLDNa/J3n4MqUJ/fOHMzQpRWw==

unbox-primitive@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.0.tgz#eeacbc4affa28e9b3d36b5eaeccc50b3251b1d3f"
integrity sha512-P/51NX+JXyxK/aigg1/ZgyccdAxm5K1+n8+tvqSntjOivPt19gvm1VC49RWYetsiub8WViUchdxl/KWHHB0kzA==
version "1.0.1"
resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471"
integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==
dependencies:
function-bind "^1.1.1"
has-bigints "^1.0.0"
has-symbols "^1.0.0"
which-boxed-primitive "^1.0.1"
has-bigints "^1.0.1"
has-symbols "^1.0.2"
which-boxed-primitive "^1.0.2"

union-value@^1.0.0:
version "1.0.1"
Expand Down Expand Up @@ -5414,7 +5405,7 @@ websocket-extensions@>=0.1.1:
resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42"
integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==

which-boxed-primitive@^1.0.1:
which-boxed-primitive@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==
Expand Down

0 comments on commit ec36851

Please sign in to comment.