jsforce2 1.11.1

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.
Files changed (80) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +74 -0
  3. package/bin/jsforce +3 -0
  4. package/bower.json +30 -0
  5. package/build/jsforce-api-analytics.js +393 -0
  6. package/build/jsforce-api-analytics.min.js +2 -0
  7. package/build/jsforce-api-analytics.min.js.map +1 -0
  8. package/build/jsforce-api-apex.js +183 -0
  9. package/build/jsforce-api-apex.min.js +2 -0
  10. package/build/jsforce-api-apex.min.js.map +1 -0
  11. package/build/jsforce-api-bulk.js +1054 -0
  12. package/build/jsforce-api-bulk.min.js +2 -0
  13. package/build/jsforce-api-bulk.min.js.map +1 -0
  14. package/build/jsforce-api-chatter.js +320 -0
  15. package/build/jsforce-api-chatter.min.js +2 -0
  16. package/build/jsforce-api-chatter.min.js.map +1 -0
  17. package/build/jsforce-api-metadata.js +3020 -0
  18. package/build/jsforce-api-metadata.min.js +2 -0
  19. package/build/jsforce-api-metadata.min.js.map +1 -0
  20. package/build/jsforce-api-soap.js +403 -0
  21. package/build/jsforce-api-soap.min.js +2 -0
  22. package/build/jsforce-api-soap.min.js.map +1 -0
  23. package/build/jsforce-api-streaming.js +3479 -0
  24. package/build/jsforce-api-streaming.min.js +2 -0
  25. package/build/jsforce-api-streaming.min.js.map +1 -0
  26. package/build/jsforce-api-tooling.js +319 -0
  27. package/build/jsforce-api-tooling.min.js +2 -0
  28. package/build/jsforce-api-tooling.min.js.map +1 -0
  29. package/build/jsforce-core.js +25250 -0
  30. package/build/jsforce-core.min.js +2 -0
  31. package/build/jsforce-core.min.js.map +1 -0
  32. package/build/jsforce.js +31637 -0
  33. package/build/jsforce.min.js +2 -0
  34. package/build/jsforce.min.js.map +1 -0
  35. package/core.js +1 -0
  36. package/index.js +1 -0
  37. package/lib/VERSION.js +2 -0
  38. package/lib/_required.js +29 -0
  39. package/lib/api/analytics.js +387 -0
  40. package/lib/api/apex.js +177 -0
  41. package/lib/api/bulk.js +862 -0
  42. package/lib/api/chatter.js +314 -0
  43. package/lib/api/index.js +8 -0
  44. package/lib/api/metadata.js +848 -0
  45. package/lib/api/soap.js +397 -0
  46. package/lib/api/streaming-extension.js +136 -0
  47. package/lib/api/streaming.js +270 -0
  48. package/lib/api/tooling.js +313 -0
  49. package/lib/browser/canvas.js +90 -0
  50. package/lib/browser/client.js +241 -0
  51. package/lib/browser/core.js +5 -0
  52. package/lib/browser/jsforce.js +6 -0
  53. package/lib/browser/jsonp.js +52 -0
  54. package/lib/browser/request.js +70 -0
  55. package/lib/cache.js +252 -0
  56. package/lib/cli/cli.js +431 -0
  57. package/lib/cli/repl.js +337 -0
  58. package/lib/connection.js +1881 -0
  59. package/lib/core.js +16 -0
  60. package/lib/csv.js +50 -0
  61. package/lib/date.js +163 -0
  62. package/lib/http-api.js +300 -0
  63. package/lib/jsforce.js +10 -0
  64. package/lib/logger.js +52 -0
  65. package/lib/oauth2.js +206 -0
  66. package/lib/process.js +275 -0
  67. package/lib/promise.js +164 -0
  68. package/lib/query.js +881 -0
  69. package/lib/quick-action.js +90 -0
  70. package/lib/record-stream.js +305 -0
  71. package/lib/record.js +107 -0
  72. package/lib/registry/file-registry.js +48 -0
  73. package/lib/registry/index.js +3 -0
  74. package/lib/registry/registry.js +111 -0
  75. package/lib/require.js +14 -0
  76. package/lib/soap.js +207 -0
  77. package/lib/sobject.js +558 -0
  78. package/lib/soql-builder.js +236 -0
  79. package/lib/transport.js +233 -0
  80. package/package.json +110 -0
@@ -0,0 +1,848 @@
1
+ /*global process, Buffer */
2
+ /**
3
+ * @file Manages Salesforce Metadata API
4
+ * @author Shinichi Tomita <shinichi.tomita@gmail.com>
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ var inherits = require('inherits'),
10
+ events = require('events'),
11
+ stream = require('readable-stream'),
12
+ _ = require('lodash/core'),
13
+ jsforce = require('../core'),
14
+ Promise = require('../promise'),
15
+ SOAP = require('../soap');
16
+
17
+ /*--------------------------------------------*/
18
+ /**
19
+ * Class for Salesforce Metadata API
20
+ *
21
+ * @class
22
+ * @param {Connection} conn - Connection object
23
+ */
24
+ var Metadata = module.exports = function(conn) {
25
+ this._conn = conn;
26
+ };
27
+
28
+
29
+ /**
30
+ * Polling interval in milliseconds
31
+ * @type {Number}
32
+ */
33
+ Metadata.prototype.pollInterval = 1000;
34
+
35
+ /**
36
+ * Polling timeout in milliseconds
37
+ * @type {Number}
38
+ */
39
+ Metadata.prototype.pollTimeout = 10000;
40
+
41
+
42
+ /**
43
+ * Call Metadata API SOAP endpoint
44
+ *
45
+ * @private
46
+ */
47
+ Metadata.prototype._invoke = function(method, message, callback) {
48
+ var soapEndpoint = new SOAP(this._conn, {
49
+ xmlns: "http://soap.sforce.com/2006/04/metadata",
50
+ endpointUrl: this._conn.instanceUrl + "/services/Soap/m/" + this._conn.version
51
+ });
52
+ return soapEndpoint.invoke(method, message).then(function(res) {
53
+ return res.result;
54
+ }).thenCall(callback);
55
+ };
56
+
57
+
58
+ /**
59
+ * @typedef {Object} Metadata~MetadataInfo
60
+ * @prop {String} fullName - The name of the component
61
+ */
62
+
63
+ /**
64
+ * Asynchronously adds one or more new metadata components to the organization.
65
+ *
66
+ * @param {String} type - The type of metadata to create
67
+ * @param {Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>} metadata - Metadata to create
68
+ * @param {Callback.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>} [callback] - Callback function
69
+ * @returns {Metadata~AsyncResultLocator}
70
+ */
71
+ Metadata.prototype.createAsync = function(type, metadata, callback) {
72
+ if (Number(this._conn.version) > 30) {
73
+ throw new Error("Async metadata CRUD calls are not supported on ver 31.0 or later.");
74
+ }
75
+ var convert = function(md) {
76
+ md["@xsi:type"] = type;
77
+ return md;
78
+ };
79
+ var isArray = _.isArray(metadata);
80
+ metadata = isArray ? _.map(metadata, convert) : convert(metadata);
81
+ var res = this._invoke("create", { metadata: metadata });
82
+ return new AsyncResultLocator(this, res, isArray).thenCall(callback);
83
+ };
84
+
85
+ /**
86
+ * @typedef {Object} Metadata~SaveResult
87
+ * @prop {Boolean} success - True if metadata is successfully saved
88
+ * @prop {String} fullName - Full name of metadata object
89
+ */
90
+
91
+ /**
92
+ * @private
93
+ */
94
+ function convertToSaveResult(result) {
95
+ var saveResult = _.clone(result);
96
+ saveResult.success = saveResult.success === 'true';
97
+ return saveResult;
98
+ }
99
+
100
+ /**
101
+ * @typedef {Object} Metadata~UpsertResult
102
+ * @prop {Boolean} success - True if metadata is successfully saved
103
+ * @prop {String} fullName - Full name of metadata object
104
+ * @prop {Boolean} created - True if metadata is newly created
105
+ */
106
+
107
+ /**
108
+ * @private
109
+ */
110
+ function convertToUpsertResult(result) {
111
+ var upsertResult = convertToSaveResult(result);
112
+ upsertResult.created = upsertResult.created === 'true';
113
+ return upsertResult;
114
+ }
115
+
116
+ /**
117
+ * Synonym of Metadata#create().
118
+ *
119
+ * @method Metadata#createSync
120
+ * @param {String} type - The type of metadata to create
121
+ * @param {Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>} metadata - Metadata to create
122
+ * @param {Callback.<Metadata~SaveResult|Array.<Metadata~SaveResult>>} [callback] - Callback function
123
+ * @returns {Promise.<Metadata~SaveResult|Array.<Metadata~SaveResult>>}
124
+ */
125
+ /**
126
+ * Synchronously adds one or more new metadata components to the organization.
127
+ *
128
+ * @method Metadata#create
129
+ * @param {String} type - The type of metadata to create
130
+ * @param {Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>} metadata - Metadata to create
131
+ * @param {Callback.<Metadata~SaveResult|Array.<Metadata~SaveResult>>} [callback] - Callback function
132
+ * @returns {Promise.<Metadata~SaveResult|Array.<Metadata~SaveResult>>}
133
+ */
134
+ Metadata.prototype.createSync =
135
+ Metadata.prototype.create = function(type, metadata, callback) {
136
+ var convert = function(md) {
137
+ md["@xsi:type"] = type;
138
+ return md;
139
+ };
140
+ var isArray = _.isArray(metadata);
141
+ metadata = isArray ? _.map(metadata, convert) : convert(metadata);
142
+ return this._invoke("createMetadata", { metadata: metadata }).then(function(results) {
143
+ return _.isArray(results) ? _.map(results, convertToSaveResult) : convertToSaveResult(results);
144
+ }).thenCall(callback);
145
+ };
146
+
147
+ /**
148
+ * @private
149
+ */
150
+ function convertToMetadataInfo(rec) {
151
+ var metadataInfo = _.clone(rec);
152
+ delete metadataInfo.$;
153
+ return metadataInfo;
154
+ }
155
+
156
+ /**
157
+ * Synonym of Metadata#read()
158
+ *
159
+ * @method Metadata#readSync
160
+ * @param {String} type - The type of metadata to read
161
+ * @param {String|Array.<String>} fullNames - full name(s) of metadata objects to read
162
+ * @param {Callback.<Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>>} [callback] - Callback function
163
+ * @returns {Promise.<Array.<Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>>>}
164
+ */
165
+ /**
166
+ * Synchronously read specified metadata components in the organization.
167
+ *
168
+ * @method Metadata#read
169
+ * @param {String} type - The type of metadata to read
170
+ * @param {String|Array.<String>} fullNames - full name(s) of metadata objects to read
171
+ * @param {Callback.<Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>>} [callback] - Callback function
172
+ * @returns {Promise.<Array.<Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>>>}
173
+ */
174
+ Metadata.prototype.readSync =
175
+ Metadata.prototype.read = function(type, fullNames, callback) {
176
+ return this._invoke("readMetadata", { type: type, fullNames: fullNames }).then(function(res) {
177
+ return _.isArray(res.records) ? _.map(res.records, convertToMetadataInfo) : convertToMetadataInfo(res.records);
178
+ }).thenCall(callback);
179
+ };
180
+
181
+ /**
182
+ * @typedef {Object} Metadata~UpdateMetadataInfo
183
+ * @prop {String} currentName - The API name of the component or field before the update
184
+ * @prop {Metadata~MetadataInfo} metadata - Full specification of the component or field you wish to update
185
+ */
186
+
187
+ /**
188
+ * Asynchronously updates one or more metadata components in the organization.
189
+ *
190
+ * @param {String} type - The type of metadata to update
191
+ * @param {Metadata~UpdateMetadataInfo|Array.<Metadata~UpdateMetadataInfo>} updateMetadata - Updating metadata
192
+ * @param {Callback.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>} [callback] - Callback function
193
+ * @returns {Metadata~AsyncResultLocator}
194
+ */
195
+ Metadata.prototype.updateAsync = function(type, updateMetadata, callback) {
196
+ if (Number(this._conn.version) > 30) {
197
+ throw new Error("Async metadata CRUD calls are not supported on ver 31.0 or later.");
198
+ }
199
+ var convert = function(umd) {
200
+ umd.metadata["@xsi:type"] = type;
201
+ return umd;
202
+ };
203
+ var isArray = _.isArray(updateMetadata);
204
+ updateMetadata = isArray ? _.map(updateMetadata, convert) : convert(updateMetadata);
205
+ var res = this._invoke("update", { updateMetadata: updateMetadata });
206
+ return new AsyncResultLocator(this, res, isArray).thenCall(callback);
207
+ };
208
+
209
+ /**
210
+ * Synonym of Metadata#update().
211
+ *
212
+ * @method Metadata#updateSync
213
+ * @param {String} type - The type of metadata to update
214
+ * @param {Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>} updateMetadata - Updating metadata
215
+ * @param {Callback.<Metadata~SaveResult|Array.<Metadata~SaveResult>>} [callback] - Callback function
216
+ * @returns {Promise.<Metadata~SaveResult|Array.<Metadata~SaveResult>>}
217
+ */
218
+ /**
219
+ * Synchronously updates one or more metadata components in the organization.
220
+ *
221
+ * @method Metadata#update
222
+ * @param {String} type - The type of metadata to update
223
+ * @param {Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>} updateMetadata - Updating metadata
224
+ * @param {Callback.<Metadata~SaveResult|Array.<Metadata~SaveResult>>} [callback] - Callback function
225
+ * @returns {Promise.<Metadata~SaveResult|Array.<Metadata~SaveResult>>}
226
+ */
227
+ Metadata.prototype.updateSync =
228
+ Metadata.prototype.update = function(type, metadata, callback) {
229
+ var convert = function(md) {
230
+ md["@xsi:type"] = type;
231
+ return md;
232
+ };
233
+ var isArray = _.isArray(metadata);
234
+ metadata = isArray ? _.map(metadata, convert) : convert(metadata);
235
+ return this._invoke("updateMetadata", { metadata: metadata }).then(function(results) {
236
+ return _.isArray(results) ? _.map(results, convertToSaveResult) : convertToSaveResult(results);
237
+ }).thenCall(callback);
238
+ };
239
+
240
+ /**
241
+ * Synonym of Metadata#upsert().
242
+ *
243
+ * @method Metadata#upsertSync
244
+ * @param {String} type - The type of metadata to upsert
245
+ * @param {Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>} metadata - Upserting metadata
246
+ * @param {Callback.<Metadata~UpsertResult|Array.<Metadata~UpsertResult>>} [callback] - Callback function
247
+ * @returns {Promise.<Metadata~UpsertResult|Array.<Metadata~UpsertResult>>}
248
+ */
249
+ /**
250
+ * Upserts one or more components in your organization's data.
251
+ *
252
+ * @method Metadata#upsert
253
+ * @param {String} type - The type of metadata to upsert
254
+ * @param {Metadata~MetadataInfo|Array.<Metadata~MetadataInfo>} metadata - Upserting metadata
255
+ * @param {Callback.<Metadata~UpsertResult|Array.<Metadata~UpsertResult>>} [callback] - Callback function
256
+ * @returns {Promise.<Metadata~UpsertResult|Array.<Metadata~UpsertResult>>}
257
+ */
258
+ Metadata.prototype.upsertSync =
259
+ Metadata.prototype.upsert = function(type, metadata, callback) {
260
+ var convert = function(md) {
261
+ md["@xsi:type"] = type;
262
+ return md;
263
+ };
264
+ var isArray = _.isArray(metadata);
265
+ metadata = isArray ? _.map(metadata, convert) : convert(metadata);
266
+ return this._invoke("upsertMetadata", { metadata: metadata }).then(function(results) {
267
+ return _.isArray(results) ? _.map(results, convertToUpsertResult) : convertToUpsertResult(results);
268
+ }).thenCall(callback);
269
+ };
270
+
271
+ /**
272
+ * Asynchronously deletes specified metadata components in the organization.
273
+ *
274
+ * @param {String} type - The type of metadata to delete
275
+ * @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.
276
+ * @param {Callback.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>} [callback] - Callback function
277
+ * @returns {Metadata~AsyncResultLocator}
278
+ */
279
+ Metadata.prototype.deleteAsync = function(type, metadata, callback) {
280
+ if (Number(this._conn.version) > 30) {
281
+ throw new Error("Async metadata CRUD calls are not supported on ver 31.0 or later.");
282
+ }
283
+ var convert = function(md) {
284
+ if (_.isString(md)) {
285
+ md = { fullName : md };
286
+ }
287
+ md["@xsi:type"] = type;
288
+ return md;
289
+ };
290
+ var isArray = _.isArray(metadata);
291
+ metadata = isArray ? _.map(metadata, convert) : convert(metadata);
292
+ var res = this._invoke("delete", { metadata: metadata });
293
+ return new AsyncResultLocator(this, res, isArray).thenCall(callback);
294
+ };
295
+
296
+ /**
297
+ * Synonym of Metadata#delete().
298
+ *
299
+ * @deprecated
300
+ * @method Metadata#del
301
+ * @param {String} [type] - The type of metadata to delete
302
+ * @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.
303
+ * @param {Callback.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>} [callback] - Callback function
304
+ * @returns {Metadata~AsyncResultLocator}
305
+ */
306
+ /**
307
+ * Synonym of Metadata#delete().
308
+ *
309
+ * @method Metadata#deleteSync
310
+ * @param {String} type - The type of metadata to delete
311
+ * @param {String|Array.<String>} fullNames - The fullName of metadata to delete.
312
+ * @param {Callback.<Metadata~SaveResult|Array.<Metadata~SaveResult>>} [callback] - Callback function
313
+ * @returns {Promise.<Metadata~SaveResult|Array.<Metadata~SaveResult>>}
314
+ */
315
+
316
+ /**
317
+ * Synchronously deletes specified metadata components in the organization.
318
+ *
319
+ * @method Metadata#delete
320
+ * @param {String} type - The type of metadata to delete
321
+ * @param {String|Array.<String>} fullNames - The fullName of metadata to delete.
322
+ * @param {Callback.<Metadata~SaveResult|Array.<Metadata~SaveResult>>} [callback] - Callback function
323
+ * @returns {Promise.<Metadata~SaveResult|Array.<Metadata~SaveResult>>}
324
+ */
325
+ Metadata.prototype.del =
326
+ Metadata.prototype.deleteSync =
327
+ Metadata.prototype["delete"] = function(type, fullNames, callback) {
328
+ return this._invoke("deleteMetadata", { type: type, fullNames: fullNames }).then(function(results) {
329
+ return _.isArray(results) ? _.map(results, convertToSaveResult) : convertToSaveResult(results);
330
+ }).thenCall(callback);
331
+ };
332
+
333
+ /**
334
+ * Rename fullname of a metadata component in the organization
335
+ *
336
+ * @param {String} type - The type of metadata to delete
337
+ * @param {String} oldFullName - The original fullName of metadata
338
+ * @param {String} newFullName - The new fullName of metadata
339
+ * @param {Callback.<Metadata~SaveResult>} [callback] - Callback function
340
+ * @returns {Promise.<Metadata~SaveResult>}
341
+ */
342
+ Metadata.prototype.rename = function(type, oldFullName, newFullName, callback) {
343
+ return this._invoke("renameMetadata", { type: type, oldFullName: oldFullName, newFullName: newFullName }).then(function(result) {
344
+ return convertToSaveResult(result);
345
+ }).thenCall(callback);
346
+ };
347
+
348
+ /**
349
+ * Checks the status of asynchronous metadata calls
350
+ *
351
+ * @param {String|Array.<String>} ids - The asynchronous process ID(s)
352
+ * @param {Callback.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>} [callback] - Callback function
353
+ * @returns {Metadata~AsyncResultLocator}
354
+ */
355
+ Metadata.prototype.checkStatus = function(ids, callback) {
356
+ var isArray = _.isArray(ids);
357
+ var res = this._invoke("checkStatus", { asyncProcessId: ids });
358
+ return new AsyncResultLocator(this, res, isArray).thenCall(callback);
359
+ };
360
+
361
+ /**
362
+ * @typedef {Object} Metadata~DescribeMetadataResult
363
+ * @prop {Array.<Object>} metadataObjects - One or more metadata components and their attributes
364
+ * @prop {Array.<String>} metadataObjects.childXmlNames - List of child sub-components for this component
365
+ * @prop {String} metadataObjects.directoryName - The name of the directory in the .zip file that contains this component
366
+ * @prop {Boolean} metadataObjects.inFolder - Indicates whether the component is in a folder or not
367
+ * @prop {Boolean} metadataObjects.metaFile - Indicates whether the component requires an accompanying metadata file
368
+ * @prop {String} metadataObjects.suffix - The file suffix for this component
369
+ * @prop {String} metadataObjects.xmlName - The name of the root element in the metadata file for this component
370
+ * @prop {String} organizationNamespace - The namespace of the organization
371
+ * @prop {Boolean} partialSaveAllowed - Indicates whether rollbackOnError is allowed or not
372
+ * @prop {Boolean} testRequired - Indicates whether tests are required or not
373
+ */
374
+
375
+ /**
376
+ * Retrieves the metadata which describes your organization, including Apex classes and triggers,
377
+ * custom objects, custom fields on standard objects, tab sets that define an app,
378
+ * and many other components.
379
+ *
380
+ * @param {String} [version] - The API version for which you want metadata; for example, 29.0
381
+ * @param {Callback.<Metadata~DescribeMetadataResult>} [callback] - Callback function
382
+ * @returns {Promise.<Metadata~DescribeMetadataResult>}
383
+ */
384
+ Metadata.prototype.describe = function(version, callback) {
385
+ if (!_.isString(version)) {
386
+ callback = version;
387
+ version = this._conn.version;
388
+ }
389
+ return this._invoke("describeMetadata", { asOfVersion: version }).then(function(res) {
390
+ res.metadataObjects = _.isArray(res.metadataObjects) ? res.metadataObjects : [ res.metadataObjects ];
391
+ res.metadataObjects = _.map(res.metadataObjects, function(mo) {
392
+ if (mo.childXmlNames) {
393
+ mo.childXmlNames = _.isArray(mo.childXmlNames) ? mo.childXmlNames: [ mo.childXmlNames ];
394
+ }
395
+ mo.inFolder = mo.inFolder === 'true';
396
+ mo.metaFile = mo.metaFile === 'true';
397
+ return mo;
398
+ });
399
+ res.partialSaveAllowed = res.partialSaveAllowed === 'true';
400
+ res.testRequired = res.testRequired === 'true';
401
+ return res;
402
+ }).thenCall(callback);
403
+ };
404
+
405
+ /**
406
+ * @typedef {Object} Metadata~ListMetadataQuery
407
+ * @prop {String} type - The metadata type, such as CustomObject, CustomField, or ApexClass
408
+ * @prop {String} [folder] - The folder associated with the component.
409
+ */
410
+
411
+ /**
412
+ * @typedef {Object} Metadata~FileProperties
413
+ * @prop {String} type - The metadata type, such as CustomObject, CustomField, or ApexClass
414
+ * @prop {String} createdById - ID of the user who created the file
415
+ * @prop {String} createdByName - Name of the user who created the file
416
+ * @prop {String} createdDate - Date and time when the file was created
417
+ * @prop {String} fileName - Name of the file
418
+ * @prop {String} fullName - The file developer name used as a unique identifier for API access
419
+ * @prop {String} id - ID of the file
420
+ * @prop {String} lastModifiedById - ID of the user who last modified the file
421
+ * @prop {String} lastModifiedByName - Name of the user who last modified the file
422
+ * @prop {String} lastModifiedDate - Date and time that the file was last modified
423
+ * @prop {String} [manageableState] - Indicates the manageable state of the specified component if it is contained in a package
424
+ * @prop {String} [namespacePrefix] - The namespace prefix of the component
425
+ */
426
+
427
+ /**
428
+ * Retrieves property information about metadata components in your organization
429
+ *
430
+ * @param {Metadata~ListMetadataQuery|Array.<Metadata~ListMetadataQuery>} queries - The criteria object(s) specifing metadata to list
431
+ * @param {String} [version] - The API version for which you want metadata; for example, 29.0
432
+ * @param {Callback.<Array.<Metadata~FileProperties>>} [callback] - Callback function
433
+ * @returns {Promise.<Array.<Metadata~FileProperties>>}
434
+ */
435
+ Metadata.prototype.list = function(queries, version, callback) {
436
+ if (!_.isString(version)) {
437
+ callback = version;
438
+ version = this._conn.version;
439
+ }
440
+ if (!_.isArray(queries)) {
441
+ queries = [ queries ];
442
+ }
443
+ return this._invoke("listMetadata", { queries: queries, asOfVersion: version }, callback);
444
+ };
445
+
446
+ /**
447
+ * @typedef {Object} Metadata~RetrieveRequest
448
+ */
449
+
450
+ /**
451
+ * Retrieves XML file representations of components in an organization
452
+ *
453
+ * @param {Metadata~RetrieveRequest} request - Options for determining which packages or files are retrieved
454
+ * @param {Callback.<Metadata~AsyncResult>} [callback] - Callback function
455
+ * @returns {Metadata~RetrieveResultLocator}
456
+ */
457
+ Metadata.prototype.retrieve = function(request, callback) {
458
+ var res = this._invoke("retrieve", { request: request });
459
+ return new RetrieveResultLocator(this, res).thenCall(callback);
460
+ };
461
+
462
+ /**
463
+ * Checks the status of declarative metadata call retrieve() and returns the zip file contents
464
+ *
465
+ * @param {String} id - Async process id returned from previous retrieve request
466
+ * @param {Callback.<Metadata~RetrieveResult>} [callback] - Callback function
467
+ * @returns {Promise.<Metadata~RetrieveResult>}
468
+ */
469
+ Metadata.prototype.checkRetrieveStatus = function(id, callback) {
470
+ return this._invoke("checkRetrieveStatus", { asyncProcessId: id }, callback);
471
+ };
472
+
473
+ /**
474
+ * Deploy components into an organization using zipped file representations
475
+ *
476
+ * @param {stream.Stream|Buffer|String} zipInput - Zipped file input source in readable stream, binary buffer or Base64-encoded string
477
+ * @param {Object} [options] - Options used in deployment
478
+ * @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.
479
+ * @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.
480
+ * @param {Boolean} [options.checkOnly] - Indicates whether Apex classes and triggers are saved to the organization as part of the deployment (false) or not (true).
481
+ * @param {Boolean} [options.ignoreWarnings] - Indicates whether a warning should allow a deployment to complete successfully (true) or not (false). Defaults to false.
482
+ * @param {Boolean} [options.performRetrieve] - Indicates whether a retrieve() call is performed immediately after the deployment (true) or not (false).
483
+ * @param {Boolean} [options.purgeOnDelete] - If true, the deleted components in the destructiveChanges.xml manifest file aren't stored in the Recycle Bin.
484
+ * @param {Boolean} [options.rollbackOnError] - Indicates whether any failure causes a complete rollback (true) or not (false).
485
+ * @param {Boolean} [options.runAllTests] - If true, all Apex tests defined in the organization are run.
486
+ * @param {Array.<String>} [options.runTests] - A list of Apex tests to be run during deployment.
487
+ * @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).
488
+ * @param {Callback.<Metadata~AsyncResult>} [callback] - Callback function
489
+ * @returns {Metadata~DeployResultLocator}
490
+ */
491
+ Metadata.prototype.deploy = function(zipInput, options, callback) {
492
+ if (!options || _.isFunction(options)) {
493
+ callback = options;
494
+ options = {};
495
+ }
496
+ var deferred = Promise.defer();
497
+ if (_.isObject(zipInput) && _.isFunction(zipInput.pipe)) {
498
+ var bufs = [];
499
+ zipInput.on('data', function(d) {
500
+ bufs.push(d);
501
+ });
502
+ zipInput.on('end', function() {
503
+ deferred.resolve(Buffer.concat(bufs).toString('base64'));
504
+ });
505
+ // zipInput.resume();
506
+ } else if (zipInput instanceof Buffer) {
507
+ deferred.resolve(zipInput.toString('base64'));
508
+ } else if (zipInput instanceof String || typeof zipInput === 'string') {
509
+ deferred.resolve(zipInput);
510
+ } else {
511
+ throw "Unexpected zipInput type";
512
+ }
513
+
514
+ var self = this;
515
+ var res = deferred.promise.then(function(zipContentB64) {
516
+ return self._invoke("deploy", {
517
+ ZipFile: zipContentB64,
518
+ DeployOptions: options
519
+ }, callback);
520
+ });
521
+ return new DeployResultLocator(this, res).thenCall(callback);
522
+ };
523
+
524
+ /**
525
+ * Checks the status of declarative metadata call deploy()
526
+ *
527
+ * @param {String} id - Async process id returned from previous deploy request
528
+ * @param {Boolean} [includeDetails] - Sets the DeployResult object to include details information (default: false)
529
+ * @param {Callback.<Metadata~DeployResult>} [callback] - Callback function
530
+ * @returns {Promise.<Metadata~DeployResult>}
531
+ */
532
+ Metadata.prototype.checkDeployStatus = function(id, includeDetails, callback) {
533
+ if (_.isObject(includeDetails) || _.isBoolean(includeDetails)) {
534
+ includeDetails = !!includeDetails;
535
+ } else {
536
+ callback = includeDetails;
537
+ includeDetails = false;
538
+ }
539
+ return this._invoke("checkDeployStatus", {
540
+ asyncProcessId: id,
541
+ includeDetails : includeDetails
542
+ }).then(function(res) {
543
+ res.done = res.done === 'true';
544
+ res.success = res.success === 'true';
545
+ res.checkOnly = res.checkOnly === 'true';
546
+ res.runTestsEnabled = res.runTestsEnabled === 'true';
547
+ if (res.ignoreWarnings) {
548
+ res.ignoreWarnings = res.ignoreWarnings === 'true';
549
+ }
550
+ if (res.rollbackOnError) {
551
+ res.rollbackOnError = res.rollbackOnError === 'true';
552
+ }
553
+ res.numberComponentErrors = Number(res.numberComponentErrors);
554
+ res.numberComponentsDeployed = Number(res.numberComponentsDeployed);
555
+ res.numberComponentsTotal = Number(res.numberComponentsTotal);
556
+ res.numberTestErrors = Number(res.numberTestErrors);
557
+ res.numberTestsCompleted = Number(res.numberTestsCompleted);
558
+ res.numberTestsTotal = Number(res.numberTestsTotal);
559
+
560
+ return res;
561
+ }).thenCall(callback);
562
+ };
563
+
564
+
565
+ /*--------------------------------------------*/
566
+
567
+ /**
568
+ * @typedef {Object} Metadata~AsyncResult
569
+ * @prop {Boolean} done - Indicates whether the call has completed or not
570
+ * @prop {String} id - ID of the component being created, updated, deleted, deployed, or retrieved
571
+ * @prop {String} state - The state four possible values: Queued, InProgress, Completed, and Error.
572
+ * @prop {String} [statusCode] - If an error occurred during the create(), update(), or delete() call, a status code is returned
573
+ * @prop {String} [message] - Message corresponding to the statusCode field returned
574
+ */
575
+
576
+ /**
577
+ * The locator class for Metadata API asynchronous call result
578
+ *
579
+ * @protected
580
+ * @class Metadata~AsyncResultLocator
581
+ * @extends events.EventEmitter
582
+ * @implements Promise.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>
583
+ * @param {Metadata} meta - Metadata API object
584
+ * @param {Promise.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>} results - Promise object for async result info
585
+ * @param {Boolean} [isArray] - Indicates whether the async request is given in array or single object
586
+ */
587
+ var AsyncResultLocator = function(meta, results, isArray) {
588
+ this._meta = meta;
589
+ this._results = results;
590
+ this._isArray = isArray;
591
+ };
592
+
593
+ inherits(AsyncResultLocator, events.EventEmitter);
594
+
595
+ /**
596
+ * Promise/A+ interface
597
+ * http://promises-aplus.github.io/promises-spec/
598
+ *
599
+ * Delegate to deferred promise, return promise instance for batch result
600
+ *
601
+ * @method Metadata~AsyncResultLocator#then
602
+ */
603
+ AsyncResultLocator.prototype.then = function(onResolve, onReject) {
604
+ var self = this;
605
+ return this._results.then(function(results) {
606
+ var convertType = function(res) {
607
+ if (res.$ && res.$["xsi:nil"] === 'true') {
608
+ return null;
609
+ }
610
+ res.done = res.done === 'true';
611
+ return res;
612
+ };
613
+ results = _.isArray(results) ? _.map(results, convertType) : convertType(results);
614
+ if (self._isArray && !_.isArray(results)) {
615
+ results = [ results ];
616
+ }
617
+ return onResolve(results);
618
+ }, onReject);
619
+ };
620
+
621
+ /**
622
+ * Promise/A+ extension
623
+ * Call "then" using given node-style callback function
624
+ *
625
+ * @method Metadata~AsyncResultLocator#thenCall
626
+ */
627
+ AsyncResultLocator.prototype.thenCall = function(callback) {
628
+ return _.isFunction(callback) ? this.then(function(res) {
629
+ process.nextTick(function() {
630
+ callback(null, res);
631
+ });
632
+ }, function(err) {
633
+ process.nextTick(function() {
634
+ callback(err);
635
+ });
636
+ }) : this;
637
+ };
638
+
639
+ /**
640
+ * Check the status of async request
641
+ *
642
+ * @method Metadata~AsyncResultLocator#check
643
+ * @param {Callback.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>} [callback] - Callback function
644
+ * @returns {Promise.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>}
645
+ */
646
+ AsyncResultLocator.prototype.check = function(callback) {
647
+ var self = this;
648
+ var meta = this._meta;
649
+ return this.then(function(results) {
650
+ var ids = _.isArray(results) ? _.map(results, function(res){ return res.id; }) : results.id;
651
+ self._ids = ids;
652
+ return meta.checkStatus(ids);
653
+ }).thenCall(callback);
654
+ };
655
+
656
+ /**
657
+ * Polling until async call status becomes complete or error
658
+ *
659
+ * @method Metadata~AsyncResultLocator#poll
660
+ * @param {Number} interval - Polling interval in milliseconds
661
+ * @param {Number} timeout - Polling timeout in milliseconds
662
+ */
663
+ AsyncResultLocator.prototype.poll = function(interval, timeout) {
664
+ var self = this;
665
+ var startTime = new Date().getTime();
666
+ var poll = function() {
667
+ var now = new Date().getTime();
668
+ if (startTime + timeout < now) {
669
+ var errMsg = "Polling time out.";
670
+ if (self._ids) {
671
+ errMsg += " Process Id = " + self._ids;
672
+ }
673
+ self.emit('error', new Error(errMsg));
674
+ return;
675
+ }
676
+ self.check().then(function(results) {
677
+ var done = true;
678
+ var resultArr = _.isArray(results) ? results : [ results ];
679
+ for (var i=0, len=resultArr.length; i<len; i++) {
680
+ var result = resultArr[i];
681
+ if (result && !result.done) {
682
+ self.emit('progress', result);
683
+ done = false;
684
+ }
685
+ }
686
+ if (done) {
687
+ self.emit('complete', results);
688
+ } else {
689
+ setTimeout(poll, interval);
690
+ }
691
+ }, function(err) {
692
+ self.emit('error', err);
693
+ });
694
+ };
695
+ setTimeout(poll, interval);
696
+ };
697
+
698
+ /**
699
+ * Check and wait until the async requests become in completed status
700
+ *
701
+ * @method Metadata~AsyncResultLocator#complete
702
+ * @param {Callback.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>} [callback] - Callback function
703
+ * @returns {Promise.<Metadata~AsyncResult|Array.<Metadata~AsyncResult>>}
704
+ */
705
+ AsyncResultLocator.prototype.complete = function(callback) {
706
+ var deferred = Promise.defer();
707
+ this.on('complete', function(results) {
708
+ deferred.resolve(results);
709
+ });
710
+ this.on('error', function(err) {
711
+ deferred.reject(err);
712
+ });
713
+ var meta = this._meta;
714
+ this.poll(meta.pollInterval, meta.pollTimeout);
715
+ return deferred.promise.thenCall(callback);
716
+ };
717
+
718
+ /*--------------------------------------------*/
719
+ /**
720
+ * The locator class to track retreive() Metadata API call result
721
+ *
722
+ * @protected
723
+ * @class Metadata~RetrieveResultLocator
724
+ * @extends Metadata~AsyncResultLocator
725
+ * @param {Metadata} meta - Metadata API object
726
+ * @param {Promise.<Metadata~AsyncResult>} result - Promise object for async result of retrieve call()
727
+ */
728
+ var RetrieveResultLocator = function(meta, result) {
729
+ RetrieveResultLocator.super_.call(this, meta, result);
730
+ };
731
+
732
+ inherits(RetrieveResultLocator, AsyncResultLocator);
733
+
734
+ /**
735
+ * @typedef {Object} Metadata~RetrieveResult
736
+ * @prop {Array.<Metadata~FileProperties>} fileProperties - Contains information about the properties of each component in the .zip file, and the manifest file package.xml
737
+ * @prop {String} id - ID of the component being retrieved
738
+ * @prop {Array.<Object>} messages - Contains information about the success or failure of the retrieve() call
739
+ * @prop {String} zipFile - The zip file returned by the retrieve request. Base 64-encoded binary data
740
+ */
741
+
742
+ /**
743
+ * Check and wait until the async request becomes in completed status,
744
+ * and retrieve the result data.
745
+ *
746
+ * @memthod Metadata~RetrieveResultLocator#complete
747
+ * @param {Callback.<Metadata~RetrieveResult>} [callback] - Callback function
748
+ * @returns {Promise.<Metadata~RetrieveResult>}
749
+ */
750
+ RetrieveResultLocator.prototype.complete = function(callback) {
751
+ var meta = this._meta;
752
+ return RetrieveResultLocator.super_.prototype.complete.call(this).then(function(result) {
753
+ return meta.checkRetrieveStatus(result.id);
754
+ }).thenCall(callback);
755
+ };
756
+
757
+ /**
758
+ * Change the retrieved result to Node.js readable stream
759
+ *
760
+ * @method Metadata~RetrieveResultLocator#stream
761
+ * @returns {stream.Readable}
762
+ */
763
+ RetrieveResultLocator.prototype.stream = function() {
764
+ var self = this;
765
+ var resultStream = new stream.Readable();
766
+ var reading = false;
767
+ resultStream._read = function() {
768
+ if (reading) { return; }
769
+ reading = true;
770
+ self.complete(function(err, result) {
771
+ if (err) {
772
+ resultStream.emit('error', err);
773
+ } else {
774
+ resultStream.push(Buffer.from(result.zipFile, 'base64'));
775
+ resultStream.push(null);
776
+ }
777
+ });
778
+ };
779
+ return resultStream;
780
+ };
781
+
782
+ /*--------------------------------------------*/
783
+ /**
784
+ * The locator class to track deploy() Metadata API call result
785
+ *
786
+ * @protected
787
+ * @class Metadata~DeployResultLocator
788
+ * @extends Metadata~AsyncResultLocator
789
+ * @param {Metadata} meta - Metadata API object
790
+ * @param {Promise.<Metadata~AsyncResult>} result - Promise object for async result of deploy() call
791
+ */
792
+ var DeployResultLocator = function(meta, result) {
793
+ DeployResultLocator.super_.call(this, meta, result);
794
+ };
795
+
796
+ inherits(DeployResultLocator, AsyncResultLocator);
797
+
798
+ /**
799
+ * @typedef {Object} Metadata~DeployResult
800
+ * @prop {String} id - ID of the component being deployed
801
+ * @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
802
+ * @prop {String} completedDate - Timestamp for when the deployment process ended
803
+ * @prop {String} createdDate - Timestamp for when the deploy() call was received
804
+ * @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
805
+ * @prop {Boolean} done - Indicates whether the server finished processing the deploy() call for the specified id
806
+ * @prop {String} [errorMessage] - Message corresponding to the values in the errorStatusCode field
807
+ * @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
808
+ * @prop {Boolean} [ignoreWarnings] - Specifies whether a deployment should continue even if the deployment generates warnings
809
+ * @prop {String} lastModifiedDate - Timestamp of the last update for the deployment process
810
+ * @prop {Number} numberComponentErrors - The number of components that generated errors during this deployment
811
+ * @prop {Number} numberComponentsDeployed - The number of components deployed in the deployment process
812
+ * @prop {Number} numberComponentsTotal - The total number of components in the deployment
813
+ * @prop {Number} numberTestErrors - The number of Apex tests that have generated errors during this deployment
814
+ * @prop {Number} numberTestsCompleted - The number of completedApex tests for this deployment
815
+ * @prop {Number} numberTestsTotal - The total number of Apex tests for this deployment
816
+ * @prop {Boolean} [rollbackOnError] - Indicates whether any failure causes a complete rollback or not. Default is true.
817
+ * @prop {String} startDate - Timestamp for when the deployment process began
818
+ * @prop {String} status - Indicates the current state of the deployment
819
+ * @prop {Boolean} success - Indicates whether the deployment was successful or not
820
+ */
821
+
822
+ /**
823
+ * Check and wait until the async request becomes in completed status,
824
+ * and retrieve the result data.
825
+ *
826
+ * @method Metadata~DeployResultLocator#complete
827
+ * @param {Callback.<Metadata~DeployResult>} [callback] - Callback function
828
+ * @returns {Promise.<Metadata~DeployResult>}
829
+ */
830
+ DeployResultLocator.prototype.complete = function(includeDetails, callback) {
831
+ if (_.isFunction(includeDetails)) {
832
+ callback = includeDetails;
833
+ includeDetails = false;
834
+ }
835
+ var meta = this._meta;
836
+ return DeployResultLocator.super_.prototype.complete.call(this).then(function(result) {
837
+ return meta.checkDeployStatus(result.id, includeDetails);
838
+ }).thenCall(callback);
839
+ };
840
+
841
+
842
+ /*--------------------------------------------*/
843
+ /*
844
+ * Register hook in connection instantiation for dynamically adding this API module features
845
+ */
846
+ jsforce.on('connection:new', function(conn) {
847
+ conn.metadata = new Metadata(conn);
848
+ });