UNPKG

jsforce

Version:

Salesforce API Library for JavaScript

1,276 lines (1,265 loc) 150 kB
import _Reflect$construct from "@babel/runtime-corejs3/core-js-stable/reflect/construct"; import _Object$getOwnPropertySymbols from "@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols"; import _filterInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/filter"; import _Object$getOwnPropertyDescriptor from "@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor"; import _forEachInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/for-each"; import _Object$getOwnPropertyDescriptors from "@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors"; import _Object$defineProperties from "@babel/runtime-corejs3/core-js-stable/object/define-properties"; import _Object$defineProperty from "@babel/runtime-corejs3/core-js-stable/object/define-property"; import _sliceInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/slice"; import _Array$from from "@babel/runtime-corejs3/core-js-stable/array/from"; import _Symbol from "@babel/runtime-corejs3/core-js-stable/symbol"; import _getIteratorMethod from "@babel/runtime-corejs3/core-js/get-iterator-method"; import _slicedToArray from "@babel/runtime-corejs3/helpers/slicedToArray"; import _objectWithoutProperties from "@babel/runtime-corejs3/helpers/objectWithoutProperties"; import _asyncToGenerator from "@babel/runtime-corejs3/helpers/asyncToGenerator"; import _defineProperty from "@babel/runtime-corejs3/helpers/defineProperty"; import _typeof from "@babel/runtime-corejs3/helpers/typeof"; import _createClass from "@babel/runtime-corejs3/helpers/createClass"; import _classCallCheck from "@babel/runtime-corejs3/helpers/classCallCheck"; import _possibleConstructorReturn from "@babel/runtime-corejs3/helpers/possibleConstructorReturn"; import _getPrototypeOf from "@babel/runtime-corejs3/helpers/getPrototypeOf"; import _inherits from "@babel/runtime-corejs3/helpers/inherits"; import _wrapNativeSuper from "@babel/runtime-corejs3/helpers/wrapNativeSuper"; var _excluded = ["pollInterval", "pollTimeout", "input"], _excluded2 = ["Id", "type", "attributes"]; function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof _Symbol && _getIteratorMethod(r) || r["@@iterator"]; if (!t) { if (_Array$isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; } function _unsupportedIterableToArray(r, a) { if (r) { var _context29; if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = _sliceInstanceProperty(_context29 = {}.toString.call(r)).call(_context29, 8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? _Array$from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function ownKeys(e, r) { var t = _Object$keys2(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = _filterInstanceProperty(o).call(o, function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var _context27, _context28; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty(_context27 = ownKeys(Object(t), !0)).call(_context27, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : _forEachInstanceProperty(_context28 = ownKeys(Object(t))).call(_context28, function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; } import _regeneratorRuntime from "@babel/runtime-corejs3/regenerator"; import _Array$isArray from "@babel/runtime-corejs3/core-js-stable/array/is-array"; import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes"; import _JSON$stringify from "@babel/runtime-corejs3/core-js-stable/json/stringify"; import _Date$now from "@babel/runtime-corejs3/core-js-stable/date/now"; import _concatInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/concat"; import _URL from "@babel/runtime-corejs3/core-js-stable/url"; import _Promise from "@babel/runtime-corejs3/core-js-stable/promise"; import _Object$keys2 from "@babel/runtime-corejs3/core-js-stable/object/keys"; import _setTimeout from "@babel/runtime-corejs3/core-js-stable/set-timeout"; import "core-js/modules/es.error.cause.js"; import "core-js/modules/es.array.iterator.js"; import "core-js/modules/es.array.push.js"; import "core-js/modules/es.function.name.js"; import "core-js/modules/es.map.js"; import "core-js/modules/es.object.keys.js"; import "core-js/modules/es.object.to-string.js"; import "core-js/modules/es.regexp.exec.js"; import "core-js/modules/es.regexp.test.js"; import "core-js/modules/es.regexp.to-string.js"; import "core-js/modules/es.set.js"; import "core-js/modules/web.dom-exception.constructor.js"; import "core-js/modules/web.dom-exception.stack.js"; import "core-js/modules/web.dom-exception.to-string-tag.js"; import "core-js/modules/web.structured-clone.js"; function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? _Reflect$construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(_Reflect$construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } import { EventEmitter } from 'events'; import { Writable } from 'stream'; import { Serializable, Parsable } from '../record-stream'; import HttpApi from '../http-api'; import { registerModule } from '../jsforce'; import { getLogger } from '../util/logger'; import { concatStreamsAsDuplex } from '../util/stream'; import is from '@sindresorhus/is'; var JobPollingTimeoutError = /*#__PURE__*/function (_Error) { /** * */ function JobPollingTimeoutError(message, jobId) { var _this; _classCallCheck(this, JobPollingTimeoutError); _this = _callSuper(this, JobPollingTimeoutError, [message]); _this.name = 'JobPollingTimeout'; _this.jobId = jobId; return _this; } _inherits(JobPollingTimeoutError, _Error); return _createClass(JobPollingTimeoutError); }(/*#__PURE__*/_wrapNativeSuper(Error)); var BulkApiV2 = /*#__PURE__*/function (_HttpApi) { function BulkApiV2() { _classCallCheck(this, BulkApiV2); return _callSuper(this, BulkApiV2, arguments); } _inherits(BulkApiV2, _HttpApi); return _createClass(BulkApiV2, [{ key: "hasErrorInResponseBody", value: function hasErrorInResponseBody(body) { return _Array$isArray(body) && _typeof(body[0]) === 'object' && 'errorCode' in body[0]; } }, { key: "isSessionExpired", value: function isSessionExpired(response) { var _context; return response.statusCode === 401 && _includesInstanceProperty(_context = response.body).call(_context, 'INVALID_SESSION_ID'); } }, { key: "parseError", value: function parseError(body) { return { errorCode: body[0].errorCode, message: body[0].message }; } }]); }(HttpApi); export var BulkV2 = /*#__PURE__*/function () { function BulkV2(connection) { _classCallCheck(this, BulkV2); /** * Polling interval in milliseconds * * Default: 1000 (1 second) */ _defineProperty(this, "pollInterval", 1000); /** * Polling timeout in milliseconds * * Default: 30000 (30 seconds) */ _defineProperty(this, "pollTimeout", 30000); this.connection = connection; this.logger = this.connection._logLevel ? getLogger('bulk2').createInstance(this.connection._logLevel) : getLogger('bulk2'); } /** * Create an instance of an ingest job object. * * @params {NewIngestJobOptions} options object * @returns {IngestJobV2} An ingest job instance * @example * // Upsert records to the Account object. * * const job = connection.bulk2.createJob({ * operation: 'insert' * object: 'Account', * }); * * // create the job in the org * await job.open() * * // upload data * await job.uploadData(csvFile) * * // finished uploading data, mark it as ready for processing * await job.close() */ return _createClass(BulkV2, [{ key: "createJob", value: function createJob(options) { return new IngestJobV2(this.connection, { bodyParams: options, pollingOptions: this }); } /** * Get an ingest or query job instance specified by a given job ID * * @param options Options object with a job ID * @returns IngestJobV2 An ingest job */ }, { key: "job", value: function job() { var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'ingest'; var options = arguments.length > 1 ? arguments[1] : undefined; if (type === 'ingest') { return new IngestJobV2(this.connection, { id: options.id, pollingOptions: this }); } else { return new QueryJobV2(this.connection, { id: options.id, pollingOptions: this }); } } /** * Create, upload, and start bulkload job */ }, { key: "loadAndWaitForResults", value: (function () { var _loadAndWaitForResults = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(options) { var pollInterval, pollTimeout, input, createJobOpts, job, err; return _regeneratorRuntime.wrap(function _callee$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: if (!options.pollTimeout) options.pollTimeout = this.pollTimeout; if (!options.pollInterval) options.pollInterval = this.pollInterval; pollInterval = options.pollInterval, pollTimeout = options.pollTimeout, input = options.input, createJobOpts = _objectWithoutProperties(options, _excluded); job = this.createJob(createJobOpts); _context2.prev = 4; _context2.next = 7; return job.open(); case 7: _context2.next = 9; return job.uploadData(input); case 9: _context2.next = 11; return job.close(); case 11: _context2.next = 13; return job.poll(pollInterval, pollTimeout); case 13: _context2.next = 15; return job.getAllResults(); case 15: return _context2.abrupt("return", _context2.sent); case 18: _context2.prev = 18; _context2.t0 = _context2["catch"](4); err = _context2.t0; this.logger.error("bulk load failed due to: ".concat(err.message)); if (err.name !== 'JobPollingTimeoutError') { // fires off one last attempt to clean up and ignores the result | error job.delete().catch(function (ignored) { return ignored; }); } throw err; case 24: case "end": return _context2.stop(); } }, _callee, this, [[4, 18]]); })); function loadAndWaitForResults(_x) { return _loadAndWaitForResults.apply(this, arguments); } return loadAndWaitForResults; }() /** * Execute bulk query and get a record stream. * * Default timeout: 10000ms * * @param soql SOQL query * @param options * * @returns {RecordStream} - Record stream, convertible to a CSV data stream */ ) }, { key: "query", value: (function () { var _query = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(soql, options) { var queryJob, recordStream, dataStream, queryRecordsStream, err; return _regeneratorRuntime.wrap(function _callee2$(_context3) { while (1) switch (_context3.prev = _context3.next) { case 0: queryJob = new QueryJobV2(this.connection, { bodyParams: { query: soql, operation: options !== null && options !== void 0 && options.scanAll ? 'queryAll' : 'query', columnDelimiter: options === null || options === void 0 ? void 0 : options.columnDelimiter, lineEnding: options === null || options === void 0 ? void 0 : options.lineEnding }, pollingOptions: this }); recordStream = new Parsable(); dataStream = recordStream.stream('csv'); _context3.prev = 3; _context3.next = 6; return queryJob.open(); case 6: _context3.next = 8; return queryJob.poll(options === null || options === void 0 ? void 0 : options.pollInterval, options === null || options === void 0 ? void 0 : options.pollTimeout); case 8: _context3.next = 10; return queryJob.result().then(function (s) { return s.stream(); }); case 10: queryRecordsStream = _context3.sent; queryRecordsStream.pipe(dataStream); _context3.next = 20; break; case 14: _context3.prev = 14; _context3.t0 = _context3["catch"](3); err = _context3.t0; this.logger.error("bulk query failed due to: ".concat(err.message)); if (err.name !== 'JobPollingTimeoutError') { // fires off one last attempt to clean up and ignores the result | error queryJob.delete().catch(function (ignored) { return ignored; }); } throw err; case 20: return _context3.abrupt("return", recordStream); case 21: case "end": return _context3.stop(); } }, _callee2, this, [[3, 14]]); })); function query(_x2, _x3) { return _query.apply(this, arguments); } return query; }()) }]); }(); export var QueryJobV2 = /*#__PURE__*/function (_EventEmitter) { function QueryJobV2(conn, options) { var _this2; _classCallCheck(this, QueryJobV2); _this2 = _callSuper(this, QueryJobV2); _this2.connection = conn; _this2.logger = _this2.connection._logLevel ? getLogger('bulk2:QueryJobV2').createInstance(_this2.connection._logLevel) : getLogger('bulk2:QueryJobV2'); if ('id' in options) { _this2._id = options.id; } else { _this2.bodyParams = options.bodyParams; } _this2.pollingOptions = options.pollingOptions; // default error handler to keep the latest error _this2.on('error', function (error) { return _this2.error = error; }); return _this2; } /** * Get the query job ID. * * @returns {string} query job Id. */ _inherits(QueryJobV2, _EventEmitter); return _createClass(QueryJobV2, [{ key: "id", get: function get() { return this.jobInfo ? this.jobInfo.id : this._id; } /** * Get the query job info. * * @returns {Promise<QueryJobInfoV2>} query job information. */ }, { key: "getInfo", value: function getInfo() { if (this.jobInfo) { return this.jobInfo; } throw new Error('No internal job info. Make sure to call `await job.check`.'); } /** * Creates a query job * * @returns {Promise<QueryJobInfoV2>} job information. */ }, { key: "open", value: (function () { var _open = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3() { return _regeneratorRuntime.wrap(function _callee3$(_context4) { while (1) switch (_context4.prev = _context4.next) { case 0: if (this.bodyParams) { _context4.next = 2; break; } throw new Error('Missing required body params to open a new query job.'); case 2: _context4.prev = 2; _context4.next = 5; return this.createQueryRequest({ method: 'POST', body: _JSON$stringify(this.bodyParams), headers: { 'Content-Type': 'application/json; charset=utf-8' }, responseType: 'application/json' }); case 5: this.jobInfo = _context4.sent; this.logger.debug("Successfully created job ".concat(this.id)); this.emit('open', this.jobInfo); _context4.next = 14; break; case 10: _context4.prev = 10; _context4.t0 = _context4["catch"](2); this.emit('error', _context4.t0); throw _context4.t0; case 14: return _context4.abrupt("return", this.jobInfo); case 15: case "end": return _context4.stop(); } }, _callee3, this, [[2, 10]]); })); function open() { return _open.apply(this, arguments); } return open; }() /** * Abort the job * * The 'aborted' event is emitted when the job successfully aborts. * @returns {Promise<QueryJobInfoV2>} job information. */ ) }, { key: "abort", value: (function () { var _abort = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4() { var state; return _regeneratorRuntime.wrap(function _callee4$(_context5) { while (1) switch (_context5.prev = _context5.next) { case 0: _context5.prev = 0; state = 'Aborted'; _context5.next = 4; return this.createQueryRequest({ method: 'PATCH', path: "/".concat(this.id), body: _JSON$stringify({ state: state }), headers: { 'Content-Type': 'application/json; charset=utf-8' }, responseType: 'application/json' }); case 4: this.jobInfo = _context5.sent; this.logger.debug("Successfully aborted job ".concat(this.id)); return _context5.abrupt("return", this.jobInfo); case 9: _context5.prev = 9; _context5.t0 = _context5["catch"](0); this.emit('error', _context5.t0); throw _context5.t0; case 13: case "end": return _context5.stop(); } }, _callee4, this, [[0, 9]]); })); function abort() { return _abort.apply(this, arguments); } return abort; }() /** * Poll for the state of the processing for the job. * * @param interval Polling interval in milliseconds * @param timeout Polling timeout in milliseconds * @returns {Promise<Record[]>} A promise that resolves when the job finished being processed. */ ) }, { key: "poll", value: (function () { var _poll = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee5() { var _context6, _context7; var interval, timeout, jobId, startTime, endTime, res, timeoutError, _args5 = arguments; return _regeneratorRuntime.wrap(function _callee5$(_context8) { while (1) switch (_context8.prev = _context8.next) { case 0: interval = _args5.length > 0 && _args5[0] !== undefined ? _args5[0] : this.pollingOptions.pollInterval; timeout = _args5.length > 1 && _args5[1] !== undefined ? _args5[1] : this.pollingOptions.pollTimeout; jobId = this.id; startTime = _Date$now(); endTime = startTime + timeout; this.logger.debug('Start polling for job status'); this.logger.debug(_concatInstanceProperty(_context6 = "Polling options: timeout:".concat(timeout, "ms | interval: ")).call(_context6, interval, "ms.")); if (!(timeout === 0)) { _context8.next = 9; break; } throw new JobPollingTimeoutError("Skipping polling because of timeout = 0ms. Job Id = ".concat(jobId), jobId); case 9: if (!(endTime > _Date$now())) { _context8.next = 35; break; } _context8.prev = 10; _context8.next = 13; return this.check(); case 13: res = _context8.sent; _context8.t0 = res.state; _context8.next = _context8.t0 === 'Aborted' ? 17 : _context8.t0 === 'UploadComplete' ? 18 : _context8.t0 === 'InProgress' ? 18 : _context8.t0 === 'Failed' ? 22 : _context8.t0 === 'JobComplete' ? 24 : 27; break; case 17: throw new Error('Job has been aborted'); case 18: this.emit('inProgress', res); _context8.next = 21; return delay(interval); case 21: return _context8.abrupt("break", 27); case 22: // unlike ingest jobs, the API doesn't return an error msg: // https://developer.salesforce.com/docs/atlas.en-us.api_asynch.meta/api_asynch/query_get_one_job.htm this.logger.debug(res); throw new Error('Query job failed to complete'); case 24: this.logger.debug("Job ".concat(this.id, " was successfully processed.")); this.emit('jobComplete', res); return _context8.abrupt("return"); case 27: _context8.next = 33; break; case 29: _context8.prev = 29; _context8.t1 = _context8["catch"](10); this.emit('error', _context8.t1); throw _context8.t1; case 33: _context8.next = 9; break; case 35: timeoutError = new JobPollingTimeoutError(_concatInstanceProperty(_context7 = "Polling timed out after ".concat(timeout, "ms. Job Id = ")).call(_context7, jobId), jobId); this.emit('error', timeoutError); throw timeoutError; case 38: case "end": return _context8.stop(); } }, _callee5, this, [[10, 29]]); })); function poll() { return _poll.apply(this, arguments); } return poll; }() /** * Check the latest job status * * @returns {Promise<QueryJobInfoV2>} job information. */ ) }, { key: "check", value: (function () { var _check = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee6() { var jobInfo; return _regeneratorRuntime.wrap(function _callee6$(_context9) { while (1) switch (_context9.prev = _context9.next) { case 0: _context9.prev = 0; _context9.next = 3; return this.createQueryRequest({ method: 'GET', path: "/".concat(this.id), responseType: 'application/json' }); case 3: jobInfo = _context9.sent; this.jobInfo = jobInfo; return _context9.abrupt("return", jobInfo); case 8: _context9.prev = 8; _context9.t0 = _context9["catch"](0); this.emit('error', _context9.t0); throw _context9.t0; case 12: case "end": return _context9.stop(); } }, _callee6, this, [[0, 8]]); })); function check() { return _check.apply(this, arguments); } return check; }() /** * Get the results for a query job as a record stream * * This method assumes the job finished being processed * @returns {RecordStream} - Record stream, convertible to a CSV data stream */ ) }, { key: "result", value: (function () { var _result = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee7() { var resultStream, resultDataStream, resultsPath, _context10, resPromise; return _regeneratorRuntime.wrap(function _callee7$(_context11) { while (1) switch (_context11.prev = _context11.next) { case 0: resultStream = new Parsable(); resultDataStream = resultStream.stream('csv'); resultsPath = "/".concat(this.id, "/results"); case 3: if (!(this.locator !== 'null')) { _context11.next = 10; break; } resPromise = this.createQueryRequest({ method: 'GET', path: this.locator // resultsPath starts with '/' ? _concatInstanceProperty(_context10 = "".concat(resultsPath, "?locator=")).call(_context10, this.locator) : resultsPath, headers: { Accept: 'text/csv' } }); resPromise.stream().pipe(resultDataStream); _context11.next = 8; return resPromise; case 8: _context11.next = 3; break; case 10: return _context11.abrupt("return", resultStream); case 11: case "end": return _context11.stop(); } }, _callee7, this); })); function result() { return _result.apply(this, arguments); } return result; }() /** * Deletes a query job. */ ) }, { key: "delete", value: (function () { var _delete2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee8() { return _regeneratorRuntime.wrap(function _callee8$(_context12) { while (1) switch (_context12.prev = _context12.next) { case 0: return _context12.abrupt("return", this.createQueryRequest({ method: 'DELETE', path: "/".concat(this.id) })); case 1: case "end": return _context12.stop(); } }, _callee8, this); })); function _delete() { return _delete2.apply(this, arguments); } return _delete; }()) }, { key: "createQueryRequest", value: function createQueryRequest(request) { var _this3 = this; var path = request.path, responseType = request.responseType; var basePath = "services/data/v".concat(this.connection.version, "/jobs/query"); var url = new _URL(path ? basePath + path : basePath, this.connection.instanceUrl).toString(); var httpApi = new BulkApiV2(this.connection, { responseType: responseType }); httpApi.on('response', function (response) { _this3.locator = response.headers['sforce-locator']; _this3.logger.debug("sforce-locator: ".concat(_this3.locator)); }); return httpApi.request(_objectSpread(_objectSpread({}, request), {}, { url: url })); } }]); }(EventEmitter); /** * Class for Bulk API V2 Ingest Job */ export var IngestJobV2 = /*#__PURE__*/function (_EventEmitter2) { /** * */ function IngestJobV2(conn, options) { var _this4; _classCallCheck(this, IngestJobV2); _this4 = _callSuper(this, IngestJobV2); _this4.connection = conn; _this4.logger = _this4.connection._logLevel ? getLogger('bulk2:IngestJobV2').createInstance(_this4.connection._logLevel) : getLogger('bulk2:IngestJobV2'); _this4.pollingOptions = options.pollingOptions; if ('id' in options) { _this4._id = options.id; } else { _this4.bodyParams = options.bodyParams; } _this4.jobData = new JobDataV2({ createRequest: function createRequest(request) { return _this4.createIngestRequest(request); }, job: _this4 }); // default error handler to keep the latest error _this4.on('error', function (error) { return _this4.error = error; }); return _this4; } /** * Get the query job ID. * * @returns {string} query job Id. */ _inherits(IngestJobV2, _EventEmitter2); return _createClass(IngestJobV2, [{ key: "id", get: function get() { return this.jobInfo ? this.jobInfo.id : this._id; } /** * Get the query job info. * * @returns {Promise<QueryJobInfoV2>} ingest job information. */ }, { key: "getInfo", value: function getInfo() { if (this.jobInfo) { return this.jobInfo; } throw new Error('No internal job info. Make sure to call `await job.check`.'); } /** * Create a job representing a bulk operation in the org * * @returns {Promise<QueryJobInfoV2>} job information. */ }, { key: "open", value: (function () { var _open2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee9() { return _regeneratorRuntime.wrap(function _callee9$(_context13) { while (1) switch (_context13.prev = _context13.next) { case 0: if (this.bodyParams) { _context13.next = 2; break; } throw new Error('Missing required body params to open a new ingest job.'); case 2: _context13.prev = 2; _context13.next = 5; return this.createIngestRequest({ method: 'POST', body: _JSON$stringify(this.bodyParams), headers: { 'Content-Type': 'application/json; charset=utf-8' }, responseType: 'application/json' }); case 5: this.jobInfo = _context13.sent; this.logger.debug("Successfully created job ".concat(this.id)); this.emit('open'); _context13.next = 14; break; case 10: _context13.prev = 10; _context13.t0 = _context13["catch"](2); this.emit('error', _context13.t0); throw _context13.t0; case 14: return _context13.abrupt("return", this.jobInfo); case 15: case "end": return _context13.stop(); } }, _callee9, this, [[2, 10]]); })); function open() { return _open2.apply(this, arguments); } return open; }() /** Upload data for a job in CSV format * * @param input CSV as a string, or array of records or readable stream */ ) }, { key: "uploadData", value: (function () { var _uploadData = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee10(input) { return _regeneratorRuntime.wrap(function _callee10$(_context14) { while (1) switch (_context14.prev = _context14.next) { case 0: _context14.next = 2; return this.jobData.execute(input).result; case 2: this.logger.debug("Successfully uploaded data to job ".concat(this.id)); case 3: case "end": return _context14.stop(); } }, _callee10, this); })); function uploadData(_x4) { return _uploadData.apply(this, arguments); } return uploadData; }() /** * Close opened job * * This method will notify the org that the upload of job data is complete and is ready for processing. */ ) }, { key: "close", value: (function () { var _close = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee11() { var state; return _regeneratorRuntime.wrap(function _callee11$(_context15) { while (1) switch (_context15.prev = _context15.next) { case 0: _context15.prev = 0; state = 'UploadComplete'; _context15.next = 4; return this.createIngestRequest({ method: 'PATCH', path: "/".concat(this.id), body: _JSON$stringify({ state: state }), headers: { 'Content-Type': 'application/json; charset=utf-8' }, responseType: 'application/json' }); case 4: this.jobInfo = _context15.sent; this.logger.debug("Successfully closed job ".concat(this.id)); this.emit('close'); _context15.next = 13; break; case 9: _context15.prev = 9; _context15.t0 = _context15["catch"](0); this.emit('error', _context15.t0); throw _context15.t0; case 13: case "end": return _context15.stop(); } }, _callee11, this, [[0, 9]]); })); function close() { return _close.apply(this, arguments); } return close; }() /** * Set the status to abort */ ) }, { key: "abort", value: (function () { var _abort2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee12() { var state; return _regeneratorRuntime.wrap(function _callee12$(_context16) { while (1) switch (_context16.prev = _context16.next) { case 0: _context16.prev = 0; state = 'Aborted'; _context16.next = 4; return this.createIngestRequest({ method: 'PATCH', path: "/".concat(this.id), body: _JSON$stringify({ state: state }), headers: { 'Content-Type': 'application/json; charset=utf-8' }, responseType: 'application/json' }); case 4: this.jobInfo = _context16.sent; this.logger.debug("Successfully aborted job ".concat(this.id)); this.emit('aborted'); _context16.next = 13; break; case 9: _context16.prev = 9; _context16.t0 = _context16["catch"](0); this.emit('error', _context16.t0); throw _context16.t0; case 13: case "end": return _context16.stop(); } }, _callee12, this, [[0, 9]]); })); function abort() { return _abort2.apply(this, arguments); } return abort; }() /** * Poll for the state of the processing for the job. * * This method will only throw after a timeout. To capture a * job failure while polling you must set a listener for the * `failed` event before calling it: * * job.on('failed', (err) => console.error(err)) * await job.poll() * * @param interval Polling interval in milliseconds * @param timeout Polling timeout in milliseconds * @returns {Promise<void>} A promise that resolves when the job finishes successfully */ ) }, { key: "poll", value: (function () { var _poll2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee13() { var _context17, _context18; var interval, timeout, jobId, startTime, endTime, res, timeoutError, _args13 = arguments; return _regeneratorRuntime.wrap(function _callee13$(_context19) { while (1) switch (_context19.prev = _context19.next) { case 0: interval = _args13.length > 0 && _args13[0] !== undefined ? _args13[0] : this.pollingOptions.pollInterval; timeout = _args13.length > 1 && _args13[1] !== undefined ? _args13[1] : this.pollingOptions.pollTimeout; jobId = this.id; startTime = _Date$now(); endTime = startTime + timeout; if (!(timeout === 0)) { _context19.next = 7; break; } throw new JobPollingTimeoutError("Skipping polling because of timeout = 0ms. Job Id = ".concat(jobId), jobId); case 7: this.logger.debug('Start polling for job status'); this.logger.debug(_concatInstanceProperty(_context17 = "Polling options: timeout:".concat(timeout, "ms | interval: ")).call(_context17, interval, "ms.")); case 9: if (!(endTime > _Date$now())) { _context19.next = 36; break; } _context19.prev = 10; _context19.next = 13; return this.check(); case 13: res = _context19.sent; _context19.t0 = res.state; _context19.next = _context19.t0 === 'Open' ? 17 : _context19.t0 === 'Aborted' ? 18 : _context19.t0 === 'UploadComplete' ? 19 : _context19.t0 === 'InProgress' ? 19 : _context19.t0 === 'Failed' ? 23 : _context19.t0 === 'JobComplete' ? 25 : 28; break; case 17: throw new Error('Job is still open. Make sure close the job by `close` method on the job instance before polling.'); case 18: throw new Error('Job has been aborted'); case 19: this.emit('inProgress', res); _context19.next = 22; return delay(interval); case 22: return _context19.abrupt("break", 28); case 23: this.logger.debug(res); throw new Error("Ingest job failed to complete due to: ".concat(res.errorMessage)); case 25: this.logger.debug("Job ".concat(this.id, " was successfully processed.")); this.emit('jobComplete', res); return _context19.abrupt("return"); case 28: _context19.next = 34; break; case 30: _context19.prev = 30; _context19.t1 = _context19["catch"](10); this.emit('error', _context19.t1); throw _context19.t1; case 34: _context19.next = 9; break; case 36: timeoutError = new JobPollingTimeoutError(_concatInstanceProperty(_context18 = "Polling timed out after ".concat(timeout, "ms. Job Id = ")).call(_context18, jobId), jobId); this.emit('error', timeoutError); throw timeoutError; case 39: case "end": return _context19.stop(); } }, _callee13, this, [[10, 30]]); })); function poll() { return _poll2.apply(this, arguments); } return poll; }() /** * Check the latest batch status in server */ ) }, { key: "check", value: (function () { var _check2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee14() { var jobInfo; return _regeneratorRuntime.wrap(function _callee14$(_context20) { while (1) switch (_context20.prev = _context20.next) { case 0: _context20.prev = 0; _context20.next = 3; return this.createIngestRequest({ method: 'GET', path: "/".concat(this.id), responseType: 'application/json' }); case 3: jobInfo = _context20.sent; this.jobInfo = jobInfo; return _context20.abrupt("return", jobInfo); case 8: _context20.prev = 8; _context20.t0 = _context20["catch"](0); this.emit('error', _context20.t0); throw _context20.t0; case 12: case "end": return _context20.stop(); } }, _callee14, this, [[0, 8]]); })); function check() { return _check2.apply(this, arguments); } return check; }() /** Return all record results * * This method will return successful, failed and unprocessed records * * @returns Promise<IngestJobV2Results> */ ) }, { key: "getAllResults", value: (function () { var _getAllResults = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee15() { var _yield$Promise$all, _yield$Promise$all2, successfulResults, failedResults, unprocessedRecords; return _regeneratorRuntime.wrap(function _callee15$(_context21) { while (1) switch (_context21.prev = _context21.next) { case 0: _context21.next = 2; return _Promise.all([this.getSuccessfulResults(), this.getFailedResults(), this.getUnprocessedRecords()]); case 2: _yield$Promise$all = _context21.sent; _yield$Promise$all2 = _slicedToArray(_yield$Promise$all, 3); successfulResults = _yield$Promise$all2[0]; failedResults = _yield$Promise$all2[1]; unprocessedRecords = _yield$Promise$all2[2]; return _context21.abrupt("return", { successfulResults: successfulResults, failedResults: failedResults, unprocessedRecords: unprocessedRecords }); case 8: case "end": return _context21.stop(); } }, _callee15, this); })); function getAllResults() { return _getAllResults.apply(this, arguments); } return getAllResults; }() /** Return successful results * * The order of records returned is not guaranteed to match the ordering of the uploaded data. * * @param {boolean} raw Get results as a CSV string * @returns Promise<IngestJobV2SuccessfulResults> */ ) }, { key: "getSuccessfulResults", value: function () { var _getSuccessfulResults = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee16(raw) { var reqOpts, results; return _regeneratorRuntime.wrap(function _callee16$(_context22) { while (1) switch (_context22.prev = _context22.next) { case 0: reqOpts = { method: 'GET', path: "/".concat(this.id, "/successfulResults") }; if (!raw) { _context22.next = 3; break; } return _context22.abrupt("return", this.createIngestRequest(_objectSpread(_objectSpread({}, reqOpts), {}, { responseType: 'text/plain' }))); case 3: if (!this.bulkJobSuccessfulResults) { _context22.next = 5; break; } return _context22.abrupt("return", this.bulkJobSuccessfulResults); case 5: _context22.next = 7; return this.createIngestRequest({ method: 'GET', path: "/".concat(this.id, "/successfulResults"), responseType: 'text/csv' }); case 7: results = _context22.sent; this.bulkJobSuccessfulResults = results !== null && results !== void 0 ? results : []; return _context22.abrupt("return", this.bulkJobSuccessfulResults); case 10: case "end": return _context22.stop(); } }, _callee16, this); })); function getSuccessfulResults(_x5) { return _getSuccessfulResults.apply(this, arguments); } return getSuccessfulResults; }() /** Return failed results * * The order of records in the response is not guaranteed to match the ordering of records in the original job data. * * @param {boolean} raw Get results as a CSV string * @returns Promise<IngestJobV2SuccessfulResults> */ }, { key: "getFailedResults", value: function () { var _getFailedResults = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee17(raw) { var reqOpts, results; return _regeneratorRuntime.wrap(function _callee17$(_context23) { while (1) switch (_context23.prev = _context23.next) { case 0: reqOpts = { method: 'GET', path: "/".concat(this.id, "/failedResults") }; if (!raw) { _context23.next = 3; break; } return _context23.abrupt("return", this.createIngestRequest(_objectSpread(_objectSpread({}, reqOpts), {}, { responseType: 'text/plain' }))); case 3: if (!this.bulkJobFailedResults) { _context23.next = 5; break; } return _context23.abrupt("return", this.bulkJobFailedResults); case 5: _context23.next = 7; return this.createIngestRequest(_objectSpread(_objectSpread({}, reqOpts), {}, { responseType: 'text/csv' })); case 7: results = _context23.sent; this.bulkJobFailedResults = results !== null && results !== void 0 ? results : []; return _context23.abrupt("return", this.bulkJobFailedResults); case 10: case "end": return _context23.stop(); } }, _callee17, this); })); function getFailedResults(_x6) { return _getFailedResults.apply(this, arguments); } return getFailedResults; }() /** Return unprocessed results * * The unprocessed records endpoint returns records as a CSV. * If the request helper is able to parse it, you get the records * as an array of objects. * If unable to parse it (bad CSV), you get the raw response as a string. * * The order of records in the response is not guaranteed to match the ordering of records in the original job data. * * @param {boolean} raw Get results as a CSV string * @returns Promise<IngestJobV2UnprocessedRecords> */ }, { key: "getUnprocessedRecords", value: function () { var _getUnprocessedRecords = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee18(raw) { var reqOpts, results; return _regeneratorRuntime.wrap(function _callee18$(_context24) { while (1) switch (_context24.prev = _context24.next) { case 0: reqOpts = { method: 'GET', path: "/".concat(this.id, "/unprocessedrecords") }; if (!raw) { _context24.next = 3; break; } return _context24.abrupt("return", this.createIngestRequest(_objectSpread(_objectSpread({}, reqOpts), {}, { responseType: 'text/plain' }))); case 3: if (!this.bulkJobUnprocessedRecords) { _context24.next = 5; break; } return _context24.abrupt("return", this.bulkJobUnprocessedRecords); case 5: _context24.next = 7; return this.createIngestRequest(_objectSpread(_objectSpread({}, reqOpts), {}, { responseType: 'text/csv' })); case 7: results = _context24.sent; this.bulkJobUnprocessedRecords = results !== null && results !== void 0 ? results : []; return _context24.abrupt("return", this.bulkJobUnprocessedRecords); case 10: case "end": return _context24.stop(); } }, _callee18, this); })); function getUnprocessedRecords(_x7) { return _getUnprocessedRecords.apply(this, arguments); } return getUnprocessedRecords; }() /** * Deletes an ingest job. */ }, { key: "delete", value: (function () { var _delete3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee19() { return _regeneratorRuntime.wrap(function _callee19$(_context25) { while (1) switch (_context25.prev = _context25.next) { case 0: