jsforce2
Version:
Salesforce API Library for JavaScript
1,416 lines (1,270 loc) • 244 kB
JavaScript
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g=(g.jsforce||(g.jsforce = {}));g=(g.modules||(g.modules = {}));g=(g.api||(g.api = {}));g.Metadata = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
(function (process,Buffer){
/*global process, Buffer */
/**
* @file Manages Salesforce Metadata API
* @author Shinichi Tomita <shinichi.tomita@gmail.com>
*/
'use strict';
var inherits = window.jsforce.require('inherits'),
events = window.jsforce.require('events'),
stream = window.jsforce.require('readable-stream'),
_ = window.jsforce.require('lodash/core'),
jsforce = window.jsforce.require('./core'),
Promise = window.jsforce.require('./promise'),
SOAP = window.jsforce.require('./soap');
/*--------------------------------------------*/
/**
* Class for Salesforce Metadata API
*
* @class
* @param {Connection} conn - Connection object
*/
var Metadata = module.exports = function(conn) {
this._conn = conn;
};
/**
* Polling interval in milliseconds
* @type {Number}
*/
Metadata.prototype.pollInterval = 1000;
/**
* Polling timeout in milliseconds
* @type {Number}
*/
Metadata.prototype.pollTimeout = 10000;
/**
* Call Metadata API SOAP endpoint
*
* @private
*/
Metadata.prototype._invoke = function(method, message, callback) {
var soapEndpoint = new SOAP(this._conn, {
xmlns: "http://soap.sforce.com/2006/04/metadata",
endpointUrl: this._conn.instanceUrl + "/services/Soap/m/" + this._conn.version
});
return soapEndpoint.invoke(method, message).then(function(res) {
return res.result;
}).thenCall(callback);
};
/**
* @typedef {Object} Metadata~MetadataInfo
* @prop {String} fullName - The name of the component
*/
/**
* Asynchronously adds one or more new metadata components to the organization.
*
* @param {String} type - The type of metadata to create
* @param {Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>} metadata - Metadata to create
* @param {Callback.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>} [callback] - Callback function
* @returns {Metadata~AsyncResultLocator}
*/
Metadata.prototype.createAsync = function(type, metadata, callback) {
if (Number(this._conn.version) > 30) {
throw new Error("Async metadata CRUD calls are not supported on ver 31.0 or later.");
}
var convert = function(md) {
md["@xsi:type"] = type;
return md;
};
var isArray = _.isArray(metadata);
metadata = isArray ? _.map(metadata, convert) : convert(metadata);
var res = this._invoke("create", { metadata: metadata });
return new AsyncResultLocator(this, res, isArray).thenCall(callback);
};
/**
* @typedef {Object} Metadata~SaveResult
* @prop {Boolean} success - True if metadata is successfully saved
* @prop {String} fullName - Full name of metadata object
*/
/**
* @private
*/
function convertToSaveResult(result) {
var saveResult = _.clone(result);
saveResult.success = saveResult.success === 'true';
return saveResult;
}
/**
* @typedef {Object} Metadata~UpsertResult
* @prop {Boolean} success - True if metadata is successfully saved
* @prop {String} fullName - Full name of metadata object
* @prop {Boolean} created - True if metadata is newly created
*/
/**
* @private
*/
function convertToUpsertResult(result) {
var upsertResult = convertToSaveResult(result);
upsertResult.created = upsertResult.created === 'true';
return upsertResult;
}
/**
* Synonym of Metadata#create().
*
* @method Metadata#createSync
* @param {String} type - The type of metadata to create
* @param {Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>} metadata - Metadata to create
* @param {Callback.<Metadata~SaveResult|Array.<Metadata~SaveResult>>} [callback] - Callback function
* @returns {Promise.<Metadata~SaveResult|Array.<Metadata~SaveResult>>}
*/
/**
* Synchronously adds one or more new metadata components to the organization.
*
* @method Metadata#create
* @param {String} type - The type of metadata to create
* @param {Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>} metadata - Metadata to create
* @param {Callback.<Metadata~SaveResult|Array.<Metadata~SaveResult>>} [callback] - Callback function
* @returns {Promise.<Metadata~SaveResult|Array.<Metadata~SaveResult>>}
*/
Metadata.prototype.createSync =
Metadata.prototype.create = function(type, metadata, callback) {
var convert = function(md) {
md["@xsi:type"] = type;
return md;
};
var isArray = _.isArray(metadata);
metadata = isArray ? _.map(metadata, convert) : convert(metadata);
return this._invoke("createMetadata", { metadata: metadata }).then(function(results) {
return _.isArray(results) ? _.map(results, convertToSaveResult) : convertToSaveResult(results);
}).thenCall(callback);
};
/**
* @private
*/
function convertToMetadataInfo(rec) {
var metadataInfo = _.clone(rec);
delete metadataInfo.$;
return metadataInfo;
}
/**
* Synonym of Metadata#read()
*
* @method Metadata#readSync
* @param {String} type - The type of metadata to read
* @param {String|Array.<String>} fullNames - full name(s) of metadata objects to read
* @param {Callback.<Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>>} [callback] - Callback function
* @returns {Promise.<Array.<Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>>>}
*/
/**
* Synchronously read specified metadata components in the organization.
*
* @method Metadata#read
* @param {String} type - The type of metadata to read
* @param {String|Array.<String>} fullNames - full name(s) of metadata objects to read
* @param {Callback.<Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>>} [callback] - Callback function
* @returns {Promise.<Array.<Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>>>}
*/
Metadata.prototype.readSync =
Metadata.prototype.read = function(type, fullNames, callback) {
return this._invoke("readMetadata", { type: type, fullNames: fullNames }).then(function(res) {
return _.isArray(res.records) ? _.map(res.records, convertToMetadataInfo) : convertToMetadataInfo(res.records);
}).thenCall(callback);
};
/**
* @typedef {Object} Metadata~UpdateMetadataInfo
* @prop {String} currentName - The API name of the component or field before the update
* @prop {Metadata~MetadataInfo} metadata - Full specification of the component or field you wish to update
*/
/**
* Asynchronously updates one or more metadata components in the organization.
*
* @param {String} type - The type of metadata to update
* @param {Metadata~UpdateMetadataInfo|Array.<Metadata~UpdateMetadataInfo>} updateMetadata - Updating metadata
* @param {Callback.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>} [callback] - Callback function
* @returns {Metadata~AsyncResultLocator}
*/
Metadata.prototype.updateAsync = function(type, updateMetadata, callback) {
if (Number(this._conn.version) > 30) {
throw new Error("Async metadata CRUD calls are not supported on ver 31.0 or later.");
}
var convert = function(umd) {
umd.metadata["@xsi:type"] = type;
return umd;
};
var isArray = _.isArray(updateMetadata);
updateMetadata = isArray ? _.map(updateMetadata, convert) : convert(updateMetadata);
var res = this._invoke("update", { updateMetadata: updateMetadata });
return new AsyncResultLocator(this, res, isArray).thenCall(callback);
};
/**
* Synonym of Metadata#update().
*
* @method Metadata#updateSync
* @param {String} type - The type of metadata to update
* @param {Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>} updateMetadata - Updating metadata
* @param {Callback.<Metadata~SaveResult|Array.<Metadata~SaveResult>>} [callback] - Callback function
* @returns {Promise.<Metadata~SaveResult|Array.<Metadata~SaveResult>>}
*/
/**
* Synchronously updates one or more metadata components in the organization.
*
* @method Metadata#update
* @param {String} type - The type of metadata to update
* @param {Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>} updateMetadata - Updating metadata
* @param {Callback.<Metadata~SaveResult|Array.<Metadata~SaveResult>>} [callback] - Callback function
* @returns {Promise.<Metadata~SaveResult|Array.<Metadata~SaveResult>>}
*/
Metadata.prototype.updateSync =
Metadata.prototype.update = function(type, metadata, callback) {
var convert = function(md) {
md["@xsi:type"] = type;
return md;
};
var isArray = _.isArray(metadata);
metadata = isArray ? _.map(metadata, convert) : convert(metadata);
return this._invoke("updateMetadata", { metadata: metadata }).then(function(results) {
return _.isArray(results) ? _.map(results, convertToSaveResult) : convertToSaveResult(results);
}).thenCall(callback);
};
/**
* Synonym of Metadata#upsert().
*
* @method Metadata#upsertSync
* @param {String} type - The type of metadata to upsert
* @param {Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>} metadata - Upserting metadata
* @param {Callback.<Metadata~UpsertResult|Array.<Metadata~UpsertResult>>} [callback] - Callback function
* @returns {Promise.<Metadata~UpsertResult|Array.<Metadata~UpsertResult>>}
*/
/**
* Upserts one or more components in your organization's data.
*
* @method Metadata#upsert
* @param {String} type - The type of metadata to upsert
* @param {Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>} metadata - Upserting metadata
* @param {Callback.<Metadata~UpsertResult|Array.<Metadata~UpsertResult>>} [callback] - Callback function
* @returns {Promise.<Metadata~UpsertResult|Array.<Metadata~UpsertResult>>}
*/
Metadata.prototype.upsertSync =
Metadata.prototype.upsert = function(type, metadata, callback) {
var convert = function(md) {
md["@xsi:type"] = type;
return md;
};
var isArray = _.isArray(metadata);
metadata = isArray ? _.map(metadata, convert) : convert(metadata);
return this._invoke("upsertMetadata", { metadata: metadata }).then(function(results) {
return _.isArray(results) ? _.map(results, convertToUpsertResult) : convertToUpsertResult(results);
}).thenCall(callback);
};
/**
* Asynchronously deletes specified metadata components in the organization.
*
* @param {String} type - The type of metadata to delete
* @param {String|Metadata~MetadataInfo|Array.<String>|Array.<Metadata~MetadataInfo>} metadata - The fullName of metadata or metadata info to delete. If it is passed in fullName, the type parameter should not be empty.
* @param {Callback.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>} [callback] - Callback function
* @returns {Metadata~AsyncResultLocator}
*/
Metadata.prototype.deleteAsync = function(type, metadata, callback) {
if (Number(this._conn.version) > 30) {
throw new Error("Async metadata CRUD calls are not supported on ver 31.0 or later.");
}
var convert = function(md) {
if (_.isString(md)) {
md = { fullName : md };
}
md["@xsi:type"] = type;
return md;
};
var isArray = _.isArray(metadata);
metadata = isArray ? _.map(metadata, convert) : convert(metadata);
var res = this._invoke("delete", { metadata: metadata });
return new AsyncResultLocator(this, res, isArray).thenCall(callback);
};
/**
* Synonym of Metadata#delete().
*
* @deprecated
* @method Metadata#del
* @param {String} [type] - The type of metadata to delete
* @param {String|Metadata~MetadataInfo|Array.<String>|Array.<Metadata~MetadataInfo>} metadata - The fullName of metadata or metadata info to delete. If it is passed in fullName, the type parameter should not be empty.
* @param {Callback.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>} [callback] - Callback function
* @returns {Metadata~AsyncResultLocator}
*/
/**
* Synonym of Metadata#delete().
*
* @method Metadata#deleteSync
* @param {String} type - The type of metadata to delete
* @param {String|Array.<String>} fullNames - The fullName of metadata to delete.
* @param {Callback.<Metadata~SaveResult|Array.<Metadata~SaveResult>>} [callback] - Callback function
* @returns {Promise.<Metadata~SaveResult|Array.<Metadata~SaveResult>>}
*/
/**
* Synchronously deletes specified metadata components in the organization.
*
* @method Metadata#delete
* @param {String} type - The type of metadata to delete
* @param {String|Array.<String>} fullNames - The fullName of metadata to delete.
* @param {Callback.<Metadata~SaveResult|Array.<Metadata~SaveResult>>} [callback] - Callback function
* @returns {Promise.<Metadata~SaveResult|Array.<Metadata~SaveResult>>}
*/
Metadata.prototype.del =
Metadata.prototype.deleteSync =
Metadata.prototype["delete"] = function(type, fullNames, callback) {
return this._invoke("deleteMetadata", { type: type, fullNames: fullNames }).then(function(results) {
return _.isArray(results) ? _.map(results, convertToSaveResult) : convertToSaveResult(results);
}).thenCall(callback);
};
/**
* Rename fullname of a metadata component in the organization
*
* @param {String} type - The type of metadata to delete
* @param {String} oldFullName - The original fullName of metadata
* @param {String} newFullName - The new fullName of metadata
* @param {Callback.<Metadata~SaveResult>} [callback] - Callback function
* @returns {Promise.<Metadata~SaveResult>}
*/
Metadata.prototype.rename = function(type, oldFullName, newFullName, callback) {
return this._invoke("renameMetadata", { type: type, oldFullName: oldFullName, newFullName: newFullName }).then(function(result) {
return convertToSaveResult(result);
}).thenCall(callback);
};
/**
* Checks the status of asynchronous metadata calls
*
* @param {String|Array.<String>} ids - The asynchronous process ID(s)
* @param {Callback.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>} [callback] - Callback function
* @returns {Metadata~AsyncResultLocator}
*/
Metadata.prototype.checkStatus = function(ids, callback) {
var isArray = _.isArray(ids);
var res = this._invoke("checkStatus", { asyncProcessId: ids });
return new AsyncResultLocator(this, res, isArray).thenCall(callback);
};
/**
* @typedef {Object} Metadata~DescribeMetadataResult
* @prop {Array.<Object>} metadataObjects - One or more metadata components and their attributes
* @prop {Array.<String>} metadataObjects.childXmlNames - List of child sub-components for this component
* @prop {String} metadataObjects.directoryName - The name of the directory in the .zip file that contains this component
* @prop {Boolean} metadataObjects.inFolder - Indicates whether the component is in a folder or not
* @prop {Boolean} metadataObjects.metaFile - Indicates whether the component requires an accompanying metadata file
* @prop {String} metadataObjects.suffix - The file suffix for this component
* @prop {String} metadataObjects.xmlName - The name of the root element in the metadata file for this component
* @prop {String} organizationNamespace - The namespace of the organization
* @prop {Boolean} partialSaveAllowed - Indicates whether rollbackOnError is allowed or not
* @prop {Boolean} testRequired - Indicates whether tests are required or not
*/
/**
* Retrieves the metadata which describes your organization, including Apex classes and triggers,
* custom objects, custom fields on standard objects, tab sets that define an app,
* and many other components.
*
* @param {String} [version] - The API version for which you want metadata; for example, 29.0
* @param {Callback.<Metadata~DescribeMetadataResult>} [callback] - Callback function
* @returns {Promise.<Metadata~DescribeMetadataResult>}
*/
Metadata.prototype.describe = function(version, callback) {
if (!_.isString(version)) {
callback = version;
version = this._conn.version;
}
return this._invoke("describeMetadata", { asOfVersion: version }).then(function(res) {
res.metadataObjects = _.isArray(res.metadataObjects) ? res.metadataObjects : [ res.metadataObjects ];
res.metadataObjects = _.map(res.metadataObjects, function(mo) {
if (mo.childXmlNames) {
mo.childXmlNames = _.isArray(mo.childXmlNames) ? mo.childXmlNames: [ mo.childXmlNames ];
}
mo.inFolder = mo.inFolder === 'true';
mo.metaFile = mo.metaFile === 'true';
return mo;
});
res.partialSaveAllowed = res.partialSaveAllowed === 'true';
res.testRequired = res.testRequired === 'true';
return res;
}).thenCall(callback);
};
/**
* @typedef {Object} Metadata~ListMetadataQuery
* @prop {String} type - The metadata type, such as CustomObject, CustomField, or ApexClass
* @prop {String} [folder] - The folder associated with the component.
*/
/**
* @typedef {Object} Metadata~FileProperties
* @prop {String} type - The metadata type, such as CustomObject, CustomField, or ApexClass
* @prop {String} createdById - ID of the user who created the file
* @prop {String} createdByName - Name of the user who created the file
* @prop {String} createdDate - Date and time when the file was created
* @prop {String} fileName - Name of the file
* @prop {String} fullName - The file developer name used as a unique identifier for API access
* @prop {String} id - ID of the file
* @prop {String} lastModifiedById - ID of the user who last modified the file
* @prop {String} lastModifiedByName - Name of the user who last modified the file
* @prop {String} lastModifiedDate - Date and time that the file was last modified
* @prop {String} [manageableState] - Indicates the manageable state of the specified component if it is contained in a package
* @prop {String} [namespacePrefix] - The namespace prefix of the component
*/
/**
* Retrieves property information about metadata components in your organization
*
* @param {Metadata~ListMetadataQuery|Array.<Metadata~ListMetadataQuery>} queries - The criteria object(s) specifing metadata to list
* @param {String} [version] - The API version for which you want metadata; for example, 29.0
* @param {Callback.<Array.<Metadata~FileProperties>>} [callback] - Callback function
* @returns {Promise.<Array.<Metadata~FileProperties>>}
*/
Metadata.prototype.list = function(queries, version, callback) {
if (!_.isString(version)) {
callback = version;
version = this._conn.version;
}
if (!_.isArray(queries)) {
queries = [ queries ];
}
return this._invoke("listMetadata", { queries: queries, asOfVersion: version }, callback);
};
/**
* @typedef {Object} Metadata~RetrieveRequest
*/
/**
* Retrieves XML file representations of components in an organization
*
* @param {Metadata~RetrieveRequest} request - Options for determining which packages or files are retrieved
* @param {Callback.<Metadata~AsyncResult>} [callback] - Callback function
* @returns {Metadata~RetrieveResultLocator}
*/
Metadata.prototype.retrieve = function(request, callback) {
var res = this._invoke("retrieve", { request: request });
return new RetrieveResultLocator(this, res).thenCall(callback);
};
/**
* Checks the status of declarative metadata call retrieve() and returns the zip file contents
*
* @param {String} id - Async process id returned from previous retrieve request
* @param {Callback.<Metadata~RetrieveResult>} [callback] - Callback function
* @returns {Promise.<Metadata~RetrieveResult>}
*/
Metadata.prototype.checkRetrieveStatus = function(id, callback) {
return this._invoke("checkRetrieveStatus", { asyncProcessId: id }, callback);
};
/**
* Deploy components into an organization using zipped file representations
*
* @param {stream.Stream|Buffer|String} zipInput - Zipped file input source in readable stream, binary buffer or Base64-encoded string
* @param {Object} [options] - Options used in deployment
* @param {Boolean} [options.allowMissingFiles] - Specifies whether a deploy succeeds even if files that are specified in package.xml but are not in the .zip file or not.
* @param {Boolean} [options.autoUpdatePackage] - If a file is in the .zip file but not specified in package.xml, specifies whether the file should be automatically added to the package or not.
* @param {Boolean} [options.checkOnly] - Indicates whether Apex classes and triggers are saved to the organization as part of the deployment (false) or not (true).
* @param {Boolean} [options.ignoreWarnings] - Indicates whether a warning should allow a deployment to complete successfully (true) or not (false). Defaults to false.
* @param {Boolean} [options.performRetrieve] - Indicates whether a retrieve() call is performed immediately after the deployment (true) or not (false).
* @param {Boolean} [options.purgeOnDelete] - If true, the deleted components in the destructiveChanges.xml manifest file aren't stored in the Recycle Bin.
* @param {Boolean} [options.rollbackOnError] - Indicates whether any failure causes a complete rollback (true) or not (false).
* @param {Boolean} [options.runAllTests] - If true, all Apex tests defined in the organization are run.
* @param {Array.<String>} [options.runTests] - A list of Apex tests to be run during deployment.
* @param {Boolean} [options.singlePackage] - Indicates whether the specified .zip file points to a directory structure with a single package (true) or a set of packages (false).
* @param {Callback.<Metadata~AsyncResult>} [callback] - Callback function
* @returns {Metadata~DeployResultLocator}
*/
Metadata.prototype.deploy = function(zipInput, options, callback) {
if (!options || _.isFunction(options)) {
callback = options;
options = {};
}
var deferred = Promise.defer();
if (_.isObject(zipInput) && _.isFunction(zipInput.pipe)) {
var bufs = [];
zipInput.on('data', function(d) {
bufs.push(d);
});
zipInput.on('end', function() {
deferred.resolve(Buffer.concat(bufs).toString('base64'));
});
// zipInput.resume();
} else if (zipInput instanceof Buffer) {
deferred.resolve(zipInput.toString('base64'));
} else if (zipInput instanceof String || typeof zipInput === 'string') {
deferred.resolve(zipInput);
} else {
throw "Unexpected zipInput type";
}
var self = this;
var res = deferred.promise.then(function(zipContentB64) {
return self._invoke("deploy", {
ZipFile: zipContentB64,
DeployOptions: options
}, callback);
});
return new DeployResultLocator(this, res).thenCall(callback);
};
/**
* Checks the status of declarative metadata call deploy()
*
* @param {String} id - Async process id returned from previous deploy request
* @param {Boolean} [includeDetails] - Sets the DeployResult object to include details information (default: false)
* @param {Callback.<Metadata~DeployResult>} [callback] - Callback function
* @returns {Promise.<Metadata~DeployResult>}
*/
Metadata.prototype.checkDeployStatus = function(id, includeDetails, callback) {
if (_.isObject(includeDetails) || _.isBoolean(includeDetails)) {
includeDetails = !!includeDetails;
} else {
callback = includeDetails;
includeDetails = false;
}
return this._invoke("checkDeployStatus", {
asyncProcessId: id,
includeDetails : includeDetails
}).then(function(res) {
res.done = res.done === 'true';
res.success = res.success === 'true';
res.checkOnly = res.checkOnly === 'true';
res.runTestsEnabled = res.runTestsEnabled === 'true';
if (res.ignoreWarnings) {
res.ignoreWarnings = res.ignoreWarnings === 'true';
}
if (res.rollbackOnError) {
res.rollbackOnError = res.rollbackOnError === 'true';
}
res.numberComponentErrors = Number(res.numberComponentErrors);
res.numberComponentsDeployed = Number(res.numberComponentsDeployed);
res.numberComponentsTotal = Number(res.numberComponentsTotal);
res.numberTestErrors = Number(res.numberTestErrors);
res.numberTestsCompleted = Number(res.numberTestsCompleted);
res.numberTestsTotal = Number(res.numberTestsTotal);
return res;
}).thenCall(callback);
};
/*--------------------------------------------*/
/**
* @typedef {Object} Metadata~AsyncResult
* @prop {Boolean} done - Indicates whether the call has completed or not
* @prop {String} id - ID of the component being created, updated, deleted, deployed, or retrieved
* @prop {String} state - The state four possible values: Queued, InProgress, Completed, and Error.
* @prop {String} [statusCode] - If an error occurred during the create(), update(), or delete() call, a status code is returned
* @prop {String} [message] - Message corresponding to the statusCode field returned
*/
/**
* The locator class for Metadata API asynchronous call result
*
* @protected
* @class Metadata~AsyncResultLocator
* @extends events.EventEmitter
* @implements Promise.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>
* @param {Metadata} meta - Metadata API object
* @param {Promise.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>} results - Promise object for async result info
* @param {Boolean} [isArray] - Indicates whether the async request is given in array or single object
*/
var AsyncResultLocator = function(meta, results, isArray) {
this._meta = meta;
this._results = results;
this._isArray = isArray;
};
inherits(AsyncResultLocator, events.EventEmitter);
/**
* Promise/A+ interface
* http://promises-aplus.github.io/promises-spec/
*
* Delegate to deferred promise, return promise instance for batch result
*
* @method Metadata~AsyncResultLocator#then
*/
AsyncResultLocator.prototype.then = function(onResolve, onReject) {
var self = this;
return this._results.then(function(results) {
var convertType = function(res) {
if (res.$ && res.$["xsi:nil"] === 'true') {
return null;
}
res.done = res.done === 'true';
return res;
};
results = _.isArray(results) ? _.map(results, convertType) : convertType(results);
if (self._isArray && !_.isArray(results)) {
results = [ results ];
}
return onResolve(results);
}, onReject);
};
/**
* Promise/A+ extension
* Call "then" using given node-style callback function
*
* @method Metadata~AsyncResultLocator#thenCall
*/
AsyncResultLocator.prototype.thenCall = function(callback) {
return _.isFunction(callback) ? this.then(function(res) {
process.nextTick(function() {
callback(null, res);
});
}, function(err) {
process.nextTick(function() {
callback(err);
});
}) : this;
};
/**
* Check the status of async request
*
* @method Metadata~AsyncResultLocator#check
* @param {Callback.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>} [callback] - Callback function
* @returns {Promise.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>}
*/
AsyncResultLocator.prototype.check = function(callback) {
var self = this;
var meta = this._meta;
return this.then(function(results) {
var ids = _.isArray(results) ? _.map(results, function(res){ return res.id; }) : results.id;
self._ids = ids;
return meta.checkStatus(ids);
}).thenCall(callback);
};
/**
* Polling until async call status becomes complete or error
*
* @method Metadata~AsyncResultLocator#poll
* @param {Number} interval - Polling interval in milliseconds
* @param {Number} timeout - Polling timeout in milliseconds
*/
AsyncResultLocator.prototype.poll = function(interval, timeout) {
var self = this;
var startTime = new Date().getTime();
var poll = function() {
var now = new Date().getTime();
if (startTime + timeout < now) {
var errMsg = "Polling time out.";
if (self._ids) {
errMsg += " Process Id = " + self._ids;
}
self.emit('error', new Error(errMsg));
return;
}
self.check().then(function(results) {
var done = true;
var resultArr = _.isArray(results) ? results : [ results ];
for (var i=0, len=resultArr.length; i<len; i++) {
var result = resultArr[i];
if (result && !result.done) {
self.emit('progress', result);
done = false;
}
}
if (done) {
self.emit('complete', results);
} else {
setTimeout(poll, interval);
}
}, function(err) {
self.emit('error', err);
});
};
setTimeout(poll, interval);
};
/**
* Check and wait until the async requests become in completed status
*
* @method Metadata~AsyncResultLocator#complete
* @param {Callback.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>} [callback] - Callback function
* @returns {Promise.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>}
*/
AsyncResultLocator.prototype.complete = function(callback) {
var deferred = Promise.defer();
this.on('complete', function(results) {
deferred.resolve(results);
});
this.on('error', function(err) {
deferred.reject(err);
});
var meta = this._meta;
this.poll(meta.pollInterval, meta.pollTimeout);
return deferred.promise.thenCall(callback);
};
/*--------------------------------------------*/
/**
* The locator class to track retreive() Metadata API call result
*
* @protected
* @class Metadata~RetrieveResultLocator
* @extends Metadata~AsyncResultLocator
* @param {Metadata} meta - Metadata API object
* @param {Promise.<Metadata~AsyncResult>} result - Promise object for async result of retrieve call()
*/
var RetrieveResultLocator = function(meta, result) {
RetrieveResultLocator.super_.call(this, meta, result);
};
inherits(RetrieveResultLocator, AsyncResultLocator);
/**
* @typedef {Object} Metadata~RetrieveResult
* @prop {Array.<Metadata~FileProperties>} fileProperties - Contains information about the properties of each component in the .zip file, and the manifest file package.xml
* @prop {String} id - ID of the component being retrieved
* @prop {Array.<Object>} messages - Contains information about the success or failure of the retrieve() call
* @prop {String} zipFile - The zip file returned by the retrieve request. Base 64-encoded binary data
*/
/**
* Check and wait until the async request becomes in completed status,
* and retrieve the result data.
*
* @memthod Metadata~RetrieveResultLocator#complete
* @param {Callback.<Metadata~RetrieveResult>} [callback] - Callback function
* @returns {Promise.<Metadata~RetrieveResult>}
*/
RetrieveResultLocator.prototype.complete = function(callback) {
var meta = this._meta;
return RetrieveResultLocator.super_.prototype.complete.call(this).then(function(result) {
return meta.checkRetrieveStatus(result.id);
}).thenCall(callback);
};
/**
* Change the retrieved result to Node.js readable stream
*
* @method Metadata~RetrieveResultLocator#stream
* @returns {stream.Readable}
*/
RetrieveResultLocator.prototype.stream = function() {
var self = this;
var resultStream = new stream.Readable();
var reading = false;
resultStream._read = function() {
if (reading) { return; }
reading = true;
self.complete(function(err, result) {
if (err) {
resultStream.emit('error', err);
} else {
resultStream.push(Buffer.from(result.zipFile, 'base64'));
resultStream.push(null);
}
});
};
return resultStream;
};
/*--------------------------------------------*/
/**
* The locator class to track deploy() Metadata API call result
*
* @protected
* @class Metadata~DeployResultLocator
* @extends Metadata~AsyncResultLocator
* @param {Metadata} meta - Metadata API object
* @param {Promise.<Metadata~AsyncResult>} result - Promise object for async result of deploy() call
*/
var DeployResultLocator = function(meta, result) {
DeployResultLocator.super_.call(this, meta, result);
};
inherits(DeployResultLocator, AsyncResultLocator);
/**
* @typedef {Object} Metadata~DeployResult
* @prop {String} id - ID of the component being deployed
* @prop {Boolean} checkOnly - Indicates whether this deployment is being used to check the validity of the deployed files without making any changes in the organization or not
* @prop {String} completedDate - Timestamp for when the deployment process ended
* @prop {String} createdDate - Timestamp for when the deploy() call was received
* @prop {Array.<Object>} [details] - Provides the details of a deployment that is in-progress or ended, if includeDetails is set to true in checkDeployStatus() call
* @prop {Boolean} done - Indicates whether the server finished processing the deploy() call for the specified id
* @prop {String} [errorMessage] - Message corresponding to the values in the errorStatusCode field
* @prop {String} [errorStatusCode] - If an error occurred during the deploy() call, a status code is returned, and the message corresponding to the status code is returned in the errorMessagefield
* @prop {Boolean} [ignoreWarnings] - Specifies whether a deployment should continue even if the deployment generates warnings
* @prop {String} lastModifiedDate - Timestamp of the last update for the deployment process
* @prop {Number} numberComponentErrors - The number of components that generated errors during this deployment
* @prop {Number} numberComponentsDeployed - The number of components deployed in the deployment process
* @prop {Number} numberComponentsTotal - The total number of components in the deployment
* @prop {Number} numberTestErrors - The number of Apex tests that have generated errors during this deployment
* @prop {Number} numberTestsCompleted - The number of completedApex tests for this deployment
* @prop {Number} numberTestsTotal - The total number of Apex tests for this deployment
* @prop {Boolean} [rollbackOnError] - Indicates whether any failure causes a complete rollback or not. Default is true.
* @prop {String} startDate - Timestamp for when the deployment process began
* @prop {String} status - Indicates the current state of the deployment
* @prop {Boolean} success - Indicates whether the deployment was successful or not
*/
/**
* Check and wait until the async request becomes in completed status,
* and retrieve the result data.
*
* @method Metadata~DeployResultLocator#complete
* @param {Callback.<Metadata~DeployResult>} [callback] - Callback function
* @returns {Promise.<Metadata~DeployResult>}
*/
DeployResultLocator.prototype.complete = function(includeDetails, callback) {
if (_.isFunction(includeDetails)) {
callback = includeDetails;
includeDetails = false;
}
var meta = this._meta;
return DeployResultLocator.super_.prototype.complete.call(this).then(function(result) {
return meta.checkDeployStatus(result.id, includeDetails);
}).thenCall(callback);
};
/*--------------------------------------------*/
/*
* Register hook in connection instantiation for dynamically adding this API module features
*/
jsforce.on('connection:new', function(conn) {
conn.metadata = new Metadata(conn);
});
}).call(this,require('_process'),require("buffer").Buffer)
},{"_process":5,"buffer":3}],2:[function(require,module,exports){
'use strict'
exports.byteLength = byteLength
exports.toByteArray = toByteArray
exports.fromByteArray = fromByteArray
var lookup = []
var revLookup = []
var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
for (var i = 0, len = code.length; i < len; ++i) {
lookup[i] = code[i]
revLookup[code.charCodeAt(i)] = i
}
// Support decoding URL-safe base64 strings, as Node.js does.
// See: https://en.wikipedia.org/wiki/Base64#URL_applications
revLookup['-'.charCodeAt(0)] = 62
revLookup['_'.charCodeAt(0)] = 63
function getLens (b64) {
var len = b64.length
if (len % 4 > 0) {
throw new Error('Invalid string. Length must be a multiple of 4')
}
// Trim off extra bytes after placeholder bytes are found
// See: https://github.com/beatgammit/base64-js/issues/42
var validLen = b64.indexOf('=')
if (validLen === -1) validLen = len
var placeHoldersLen = validLen === len
? 0
: 4 - (validLen % 4)
return [validLen, placeHoldersLen]
}
// base64 is 4/3 + up to two characters of the original data
function byteLength (b64) {
var lens = getLens(b64)
var validLen = lens[0]
var placeHoldersLen = lens[1]
return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
}
function _byteLength (b64, validLen, placeHoldersLen) {
return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
}
function toByteArray (b64) {
var tmp
var lens = getLens(b64)
var validLen = lens[0]
var placeHoldersLen = lens[1]
var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))
var curByte = 0
// if there are placeholders, only get up to the last complete 4 chars
var len = placeHoldersLen > 0
? validLen - 4
: validLen
for (var i = 0; i < len; i += 4) {
tmp =
(revLookup[b64.charCodeAt(i)] << 18) |
(revLookup[b64.charCodeAt(i + 1)] << 12) |
(revLookup[b64.charCodeAt(i + 2)] << 6) |
revLookup[b64.charCodeAt(i + 3)]
arr[curByte++] = (tmp >> 16) & 0xFF
arr[curByte++] = (tmp >> 8) & 0xFF
arr[curByte++] = tmp & 0xFF
}
if (placeHoldersLen === 2) {
tmp =
(revLookup[b64.charCodeAt(i)] << 2) |
(revLookup[b64.charCodeAt(i + 1)] >> 4)
arr[curByte++] = tmp & 0xFF
}
if (placeHoldersLen === 1) {
tmp =
(revLookup[b64.charCodeAt(i)] << 10) |
(revLookup[b64.charCodeAt(i + 1)] << 4) |
(revLookup[b64.charCodeAt(i + 2)] >> 2)
arr[curByte++] = (tmp >> 8) & 0xFF
arr[curByte++] = tmp & 0xFF
}
return arr
}
function tripletToBase64 (num) {
return lookup[num >> 18 & 0x3F] +
lookup[num >> 12 & 0x3F] +
lookup[num >> 6 & 0x3F] +
lookup[num & 0x3F]
}
function encodeChunk (uint8, start, end) {
var tmp
var output = []
for (var i = start; i < end; i += 3) {
tmp =
((uint8[i] << 16) & 0xFF0000) +
((uint8[i + 1] << 8) & 0xFF00) +
(uint8[i + 2] & 0xFF)
output.push(tripletToBase64(tmp))
}
return output.join('')
}
function fromByteArray (uint8) {
var tmp
var len = uint8.length
var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
var parts = []
var maxChunkLength = 16383 // must be multiple of 3
// go through the array every three bytes, we'll deal with trailing stuff later
for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
parts.push(encodeChunk(
uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)
))
}
// pad the end with zeros, but make sure to not forget the extra bytes
if (extraBytes === 1) {
tmp = uint8[len - 1]
parts.push(
lookup[tmp >> 2] +
lookup[(tmp << 4) & 0x3F] +
'=='
)
} else if (extraBytes === 2) {
tmp = (uint8[len - 2] << 8) + uint8[len - 1]
parts.push(
lookup[tmp >> 10] +
lookup[(tmp >> 4) & 0x3F] +
lookup[(tmp << 2) & 0x3F] +
'='
)
}
return parts.join('')
}
},{}],3:[function(require,module,exports){
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*/
/* eslint-disable no-proto */
'use strict'
var base64 = require('base64-js')
var ieee754 = require('ieee754')
exports.Buffer = Buffer
exports.SlowBuffer = SlowBuffer
exports.INSPECT_MAX_BYTES = 50
var K_MAX_LENGTH = 0x7fffffff
exports.kMaxLength = K_MAX_LENGTH
/**
* If `Buffer.TYPED_ARRAY_SUPPORT`:
* === true Use Uint8Array implementation (fastest)
* === false Print warning and recommend using `buffer` v4.x which has an Object
* implementation (most compatible, even IE6)
*
* Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
* Opera 11.6+, iOS 4.2+.
*
* We report that the browser does not support typed arrays if the are not subclassable
* using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array`
* (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support
* for __proto__ and has a buggy typed array implementation.
*/
Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport()
if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' &&
typeof console.error === 'function') {
console.error(
'This browser lacks typed array (Uint8Array) support which is required by ' +
'`buffer` v5.x. Use `buffer` v4.x if you require old browser support.'
)
}
function typedArraySupport () {
// Can typed array instances can be augmented?
try {
var arr = new Uint8Array(1)
arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }}
return arr.foo() === 42
} catch (e) {
return false
}
}
Object.defineProperty(Buffer.prototype, 'parent', {
get: function () {
if (!(this instanceof Buffer)) {
return undefined
}
return this.buffer
}
})
Object.defineProperty(Buffer.prototype, 'offset', {
get: function () {
if (!(this instanceof Buffer)) {
return undefined
}
return this.byteOffset
}
})
function createBuffer (length) {
if (length > K_MAX_LENGTH) {
throw new RangeError('Invalid typed array length')
}
// Return an augmented `Uint8Array` instance
var buf = new Uint8Array(length)
buf.__proto__ = Buffer.prototype
return buf
}
/**
* The Buffer constructor returns instances of `Uint8Array` that have their
* prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
* `Uint8Array`, so the returned instances will have all the node `Buffer` methods
* and the `Uint8Array` methods. Square bracket notation works as expected -- it
* returns a single octet.
*
* The `Uint8Array` prototype remains unmodified.
*/
function Buffer (arg, encodingOrOffset, length) {
// Common case.
if (typeof arg === 'number') {
if (typeof encodingOrOffset === 'string') {
throw new Error(
'If encoding is specified then the first argument must be a string'
)
}
return allocUnsafe(arg)
}
return from(arg, encodingOrOffset, length)
}
// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
if (typeof Symbol !== 'undefined' && Symbol.species &&
Buffer[Symbol.species] === Buffer) {
Object.defineProperty(Buffer, Symbol.species, {
value: null,
configurable: true,
enumerable: false,
writable: false
})
}
Buffer.poolSize = 8192 // not used by this implementation
function from (value, encodingOrOffset, length) {
if (typeof value === 'number') {
throw new TypeError('"value" argument must not be a number')
}
if (isArrayBuffer(value) || (value && isArrayBuffer(value.buffer))) {
return fromArrayBuffer(value, encodingOrOffset, length)
}
if (typeof value === 'string') {
return fromString(value, encodingOrOffset)
}
return fromObject(value)
}
/**
* Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
* if value is a number.
* Buffer.from(str[, encoding])
* Buffer.from(array)
* Buffer.from(buffer)
* Buffer.from(arrayBuffer[, byteOffset[, length]])
**/
Buffer.from = function (value, encodingOrOffset, length) {
return from(value, encodingOrOffset, length)
}
// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug:
// https://github.com/feross/buffer/pull/148
Buffer.prototype.__proto__ = Uint8Array.prototype
Buffer.__proto__ = Uint8Array
function assertSize (size) {
if (typeof size !== 'number') {
throw new TypeError('"size" argument must be of type number')
} else if (size < 0) {
throw new RangeError('"size" argument must not be negative')
}
}
function alloc (size, fill, encoding) {
assertSize(size)
if (size <= 0) {
return createBuffer(size)
}
if (fill !== undefined) {
// Only pay attention to encoding if it's a string. This
// prevents accidentally sending in a number that would
// be interpretted as a start offset.
return typeof encoding === 'string'
? createBuffer(size).fill(fill, encoding)
: createBuffer(size).fill(fill)
}
return createBuffer(size)
}
/**
* Creates a new filled Buffer instance.
* alloc(size[, fill[, encoding]])
**/
Buffer.alloc = function (size, fill, encoding) {
return alloc(size, fill, encoding)
}
function allocUnsafe (size) {
assertSize(size)
return createBuffer(size < 0 ? 0 : checked(size) | 0)
}
/**
* Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
* */
Buffer.allocUnsafe = function (size) {
return allocUnsafe(size)
}
/**
* Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
*/
Buffer.allocUnsafeSlow = function (size) {
return allocUnsafe(size)
}
function fromString (string, encoding) {
if (typeof encoding !== 'string' || encoding === '') {
encoding = 'utf8'
}
if (!Buffer.isEncoding(encoding)) {
throw new TypeError('Unknown encoding: ' + encoding)
}
var length = byteLength(string, encoding) | 0
var buf = createBuffer(length)
var actual = buf.write(string, encoding)
if (actual !== length) {
// Writing a hex string, for example, that contains invalid characters will
// cause everything after the first invalid character to be ignored. (e.g.
// 'abxxcd' will be treated as 'ab')
buf = buf.slice(0, actual)
}
return buf
}
function fromArrayLike (array) {
var length = array.length < 0 ? 0 : checked(array.length) | 0
var buf = createBuffer(length)
for (var i = 0; i < length; i += 1) {
buf[i] = array[i] & 255
}
return buf
}
function fromArrayBuffer (array, byteOffset, length) {
if (byteOffset < 0 || array.byteLength < byteOffset) {
throw new RangeError('"offset" is outside of buffer bounds')
}
if (array.byteLength < byteOffset + (length || 0)) {
throw new RangeError('"length" is outside of buffer bounds')
}
var buf
if (byteOffset === undefined && length === undefined) {
buf = new Uint8Array(array)
} else if (length === undefined) {
buf = new Uint8Array(array, byteOffset)
} else {
buf = new Uint8Array(array, byteOffset, length)
}
// Return an augmented `Uint8Array` instance
buf.__proto__ = Buffer.prototype
return buf
}
function fromObject (obj) {
if (Buffer.isBuffer(obj)) {
var len = checked(obj.length) | 0
var buf = createBuffer(len)
if (buf.length === 0) {
return buf
}
obj.copy(buf, 0, 0, len)
return buf
}
if (obj) {
if (ArrayBuffer.isView(obj) || 'length' in obj) {
if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) {
return createBuffer(0)
}
return fromArrayLike(obj)
}
if (obj.type === 'Buffer' && Array.isArray(obj.data)) {
return fromArrayLike(obj.data)
}
}
throw new TypeError('The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object.')
}
function checked (length) {
// Note: cannot use `length < K_MAX_LENGTH` here because that fails when
// length is NaN (which is otherwise coerced to zero.)
if (length >= K_MAX_LENGTH) {
throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes')
}
return length | 0
}
function SlowBuffer (length) {
if (+length != length) { // eslint-disable-line eqeqeq
length = 0
}
return Buffer.alloc(+length)
}
Buffer.isBuffer = function isBuffer (b) {
return b != null && b._isBuffer === true
}
Buffer.compare = function compare (a, b) {
if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
throw new TypeError('Arguments must be Buffers')
}
if (a === b) return 0
var x = a.length
var y = b.length
for (var i = 0, len = Math.min(x, y); i < len; ++i) {
if (a[i] !== b[i]) {
x = a[i]
y = b[i]
break
}
}
if (x < y) return -1
if (y < x) return 1
return 0
}
Buffer.isEncoding = function isEncoding (encoding) {
switch (String(encoding).toLowerCase()) {
case 'hex':
case 'utf8':
case 'utf-8':
case 'ascii':
case 'latin1':
case 'binary':
case 'base64':
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return true
default:
return false
}
}
Buffer.concat = function concat (list, length) {
if (!Array.isArray(list)) {
throw new TypeError('"list" argument must be an Array of Buffers')
}
if (list.length === 0) {
return Buffer.alloc(0)
}
var i
if (length === undefined) {
length = 0
for (i = 0; i < list.length; ++i) {
length += list[i].length
}
}
var buffer = Buffer.allocUnsafe(length)
var pos = 0
for (i = 0; i < list.length; ++i) {
var buf = list[i]
if (ArrayBuffer.isView(buf)) {
buf = Buffer.from(buf)
}
if (!Buffer.isBuffer(buf)) {
throw new TypeError('"list" argument must be an Array of Buffers')
}
buf.copy(buffer, pos)
pos += buf.length
}
return buffer
}
function byteLength (string, encoding) {
if (Buffer.isBuffer(string)) {
return string.length
}
if (ArrayBuffer.isView(string) || isArrayBuffer(string)) {
return string.byteLength
}
if (typeof string !== 'string') {
string = '' + string
}
var len = string.length
if (len === 0) return 0
// Use a for loop to avoid recursion
var loweredCase = false
for (;;) {
switch (encoding) {
case 'ascii':
case 'latin1':
case 'binary':
return len
case 'utf8':
case 'utf-8':
case undefined:
return utf8ToBytes(string).len