fsm-sdk
Version:
Node.JS sdk to interface with SAP Field Service Management APIs.
1,076 lines (1,044 loc) • 52.5 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.fsm = {}));
}(this, (function (exports) { 'use strict';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
function __generator(thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
}
// Unique ID creation requires a high quality random # generator. In the browser we therefore
// require the crypto API and do not support built-in fallback to lower quality random number
// generators (like Math.random()).
var getRandomValues;
var rnds8 = new Uint8Array(16);
function rng() {
// lazy load so that environments that need to polyfill have a chance to do so
if (!getRandomValues) {
// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. Also,
// find the complete implementation of crypto (msCrypto) on IE11.
getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || typeof msCrypto !== 'undefined' && typeof msCrypto.getRandomValues === 'function' && msCrypto.getRandomValues.bind(msCrypto);
if (!getRandomValues) {
throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
}
}
return getRandomValues(rnds8);
}
var REGEX = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;
function validate(uuid) {
return typeof uuid === 'string' && REGEX.test(uuid);
}
/**
* Convert array of 16 byte values to UUID string format of the form:
* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
*/
var byteToHex = [];
for (var i = 0; i < 256; ++i) {
byteToHex.push((i + 0x100).toString(16).substr(1));
}
function stringify(arr) {
var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
// Note: Be careful editing this code! It's been tuned for performance
// and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
var uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one
// of the following:
// - One or more input array values don't map to a hex octet (leading to
// "undefined" in the uuid)
// - Invalid input values for the RFC `version` or `variant` fields
if (!validate(uuid)) {
throw TypeError('Stringified UUID is invalid');
}
return uuid;
}
function v4(options, buf, offset) {
options = options || {};
var rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
rnds[6] = rnds[6] & 0x0f | 0x40;
rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided
if (buf) {
offset = offset || 0;
for (var i = 0; i < 16; ++i) {
buf[offset + i] = rnds[i];
}
return buf;
}
return stringify(rnds);
}
// note: to update run -> npm run tools:update-dto-versions
var ALL_DTO_VERSIONS = {
'Activity': 39,
'ActivityCode': 14,
'ActivityComposedCode': 12,
'ActivityFeedback': 12,
'ActivitySubType': 15,
'ActivityTemplate': 12,
'ActivityTopic': 15,
'Address': 21,
'Alert': 15,
'Approval': 14,
'Attachment': 18,
'Batch': 11,
'BatchQuantity': 12,
'BlanketOrder': 12,
'Branch': 13,
'BusinessPartner': 23,
'BusinessPartnerGroup': 15,
'BusinessProcessStepDefinition': 16,
'Category': 17,
'CheckIn': 11,
'ChecklistAssignment': 14,
'ChecklistCategory': 11,
'ChecklistInstance': 18,
'ChecklistInstanceElement': 17,
'ChecklistTag': 8,
'ChecklistTemplate': 19,
'ChecklistVariable': 8,
'Comment': 11,
'CompanyInfo': 16,
'CompanySettings': 14,
'Competitor': 14,
'CompetitorProduct': 10,
'Configuration': 10,
'Consent': 8,
'Contact': 17,
'Country': 12,
'County': 10,
'CreditNote': 13,
'CrowdExecutionRecord': 8,
'Currency': 12,
'CustomRule': 8,
'Defect': 11,
'DocumentDiscount': 11,
'DocumentDraft': 14,
'EmployeeBranch': 9,
'EmployeeDepartment': 9,
'EmployeePosition': 11,
'Enumeration': 12,
'Equipment': 23,
'EquipmentSubType': 11,
'ErpError': 15,
'Expense': 16,
'ExpenseType': 16,
'FieldConfiguration': 10,
'File': 11,
'FileRef': 11,
'FileRevision': 11,
'Filter': 13,
'Function': 8,
'GenericOrder': 12,
'Group': 14,
'Icon': 10,
'Incident': 12,
'Industry': 14,
'InformationSource': 14,
'Inventory': 11,
'Invoice': 15,
'Item': 23,
'ItemCategory': 15,
'ItemGroup': 11,
'ItemPriceListAssignment': 15,
'ItemProposal': 11,
'ItemReturnReason': 12,
'ItemType': 11,
'ItemWarehouseLevel': 15,
'LevelOfInterest': 14,
'LocationNumberSeries': 11,
'Material': 21,
'Mileage': 17,
'MileageType': 15,
'Notification': 8,
'NowKpi': 8,
'NowPlugin': 9,
'NowPluginInstance': 8,
'NowPluginInstanceSet': 11,
'NowPluginVersion': 8,
'NowShortUrl': 8,
'ObjectGroup': 15,
'ObjectRating': 15,
'PaymentTerm': 15,
'PaymentType': 16,
'Person': 24,
'PersonReservation': 19,
'PersonReservationType': 16,
'PersonWorkTimePattern': 9,
'PlanningScenario': 8,
'Plugin': 8,
'PriceList': 15,
'ProductionOrder': 14,
'ProfileObject': 22,
'Project': 12,
'ProjectMemberTimeFrame': 8,
'ProjectPhase': 12,
'ProjectShift': 8,
'PropertyMeta': 11,
'PurchaseOrder': 14,
'Reason': 14,
'Region': 9,
'ReportData': 15,
'ReportTemplate': 19,
'Requirement': 9,
'ReservedMaterial': 20,
'SalesOpportunity': 16,
'SalesOrder': 18,
'SalesQuotation': 17,
'SalesStage': 14,
'ScreenConfiguration': 12,
'Sequence': 11,
'SerialNumber': 8,
'ServiceAssignment': 28,
'ServiceAssignmentStatus': 15,
'ServiceAssignmentStatusDefinition': 20,
'ServiceCall': 26,
'ServiceCallOrigin': 15,
'ServiceCallProblemType': 15,
'ServiceCallStatus': 15,
'ServiceCallType': 15,
'ServiceCheckout': 15,
'ServiceContract': 13,
'ServiceContractEquipment': 12,
'ServiceErrorCode': 11,
'ServiceErrorCodeItem': 12,
'Shift': 9,
'ShiftTechnician': 9,
'ShippingType': 15,
'Signature': 14,
'Skill': 9,
'State': 10,
'StockTransfer': 15,
'SyncObjectChangelog': 10,
'Tag': 8,
'Tax': 10,
'Team': 13,
'TeamTimeFrame': 10,
'TimeEffort': 16,
'TimeProject': 15,
'TimeSubTask': 15,
'TimeTask': 18,
'ToolAssignment': 8,
'Translation': 11,
'TransportCost': 13,
'UdfMeta': 19,
'UdfMetaGroup': 11,
'UdoMeta': 8,
'UnifiedPerson': 12,
'Usage': 15,
'UsedTool': 8,
'UserSettings': 14,
'UserSyncConfirmation': 14,
'VisitorReport': 11,
'Warehouse': 16,
'Widget': 10,
'WorkTime': 16,
'WorkTimePattern': 9,
'WorkTimeTask': 16
};
var RequestOptionsFacory = /** @class */ (function () {
function RequestOptionsFacory() {
}
RequestOptionsFacory.getUUID = function () {
return v4().replace(/\-/g, '');
};
RequestOptionsFacory.stringify = function (o) {
return Object.keys(o).map(function (key) { return encodeURIComponent(key) + "=" + encodeURIComponent(o[key]); }).join('&');
};
RequestOptionsFacory.getDataApiUriFor = function (token, resourceName, resourceId, externalId) {
if (resourceId === void 0) { resourceId = null; }
if (externalId === void 0) { externalId = null; }
var identifier = [
(resourceId ? "/" + resourceId : '').trim(),
(externalId && !resourceId ? "/externalId/" + externalId : '').trim()
].join('').trim();
return token.cluster_url + "/api/data/v4/" + resourceName + identifier;
};
/**
* map of DTO objects and versions
* { ['<DTOName>']: number }
* Note: DTOName is case sensitiv
*/
RequestOptionsFacory.getAllDTOVersions = function () {
return ALL_DTO_VERSIONS;
};
RequestOptionsFacory.getDTOVersionsString = function (DTONames) {
return DTONames
.map(function (name) {
if (!ALL_DTO_VERSIONS[name]) {
throw new Error("no DTO version found for " + name);
}
return name + "." + ALL_DTO_VERSIONS[name];
}).join(';');
};
RequestOptionsFacory.getRequestXHeaders = function (config) {
var requestId = v4().replace(/\-/g, '');
return {
'X-Client-Id': config.clientIdentifier,
'X-Client-Version': config.clientVersion,
'X-Request-ID': requestId,
'X-B3-TraceId': requestId
};
};
RequestOptionsFacory.getRequestHeaders = function (token, config) {
return __assign({ 'Authorization': token.token_type + " " + token.access_token, 'Accept': 'application/json' }, RequestOptionsFacory.getRequestXHeaders(config));
};
RequestOptionsFacory.getRequestAccountQueryParams = function (token, config) {
if (!token.companies || !token.companies.length) {
throw new Error('no compnay found on given account');
}
var selectedCompany = token.companies[0];
return {
account: config.authAccountName,
user: config.authUserName,
company: config.authCompany
? config.authCompany
: selectedCompany.name,
};
};
return RequestOptionsFacory;
}());
if (typeof window === 'undefined') {
// node
require('isomorphic-fetch');
globalThis.URLSearchParams = require('url').URLSearchParams;
}
var fetch = globalThis.fetch;
var URLSearchParams = globalThis.URLSearchParams;
function toBase64(str) {
return !!globalThis.Buffer
? globalThis.Buffer.from(str).toString('base64')
: globalThis.btoa(unescape(encodeURIComponent(str)));
}
var AuthService = /** @class */ (function () {
function AuthService(_http, _logger) {
if (_logger === void 0) { _logger = console; }
this._http = _http;
this._logger = _logger;
}
AuthService.prototype._fetchAndSaveToken = function (config) {
return __awaiter(this, void 0, void 0, function () {
var body, response, fs, token;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
body = new URLSearchParams(__assign({ grant_type: config.authGrantType }, (config.authGrantType === 'password'
? {
username: config.authAccountName + "/" + config.authUserName,
password: config.authPassword
}
: {})));
return [4 /*yield*/, this._http.request(config.oauthEndpoint + "/token", {
method: 'POST',
headers: __assign({ 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json', 'Authorization': "Basic " + toBase64(config.clientIdentifier + ":" + config.clientSecret) }, RequestOptionsFacory.getRequestXHeaders(config)),
body: body.toString()
})];
case 1:
response = _a.sent();
if (config.debug && config.tokenCacheFilePath) {
try {
fs = require('fs');
fs.writeFileSync(config.tokenCacheFilePath, JSON.stringify(response));
}
catch (error) {
this._logger.error("ERROR: could not create " + config.tokenCacheFilePath, error);
}
}
token = typeof response === 'string' ? JSON.parse(response) : response;
return [2 /*return*/, token];
}
});
});
};
AuthService.prototype._readToken = function (config) {
return __awaiter(this, void 0, void 0, function () {
var error_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 5]);
return [4 /*yield*/, new Promise(function (resolve, fail) {
if (config.debug && config.tokenCacheFilePath) {
var path = require('path');
var token = require(path.resolve(config.tokenCacheFilePath));
return resolve(token);
}
fail({ code: 'MODULE_NOT_FOUND' });
})];
case 1: return [2 /*return*/, _a.sent()];
case 2:
error_1 = _a.sent();
if (!(error_1.code === 'MODULE_NOT_FOUND')) return [3 /*break*/, 4];
return [4 /*yield*/, this._fetchAndSaveToken(config)];
case 3: return [2 /*return*/, _a.sent()];
case 4: throw error_1;
case 5: return [2 /*return*/];
}
});
});
};
AuthService.prototype.ensureToken = function (config) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
return [2 /*return*/, this._token && this._tokenExpiration && (new Date() < this._tokenExpiration)
? Promise.resolve(this._token)
: this._readToken(config)
.then(function (token) { return _this.setToken(token).getToken(); })];
});
});
};
AuthService.prototype.getToken = function () {
return this._token;
};
AuthService.prototype.setToken = function (token) {
if (!token || !token.account) {
throw new Error('invalid token');
}
this._token = token;
this._tokenExpiration = new Date(new Date().getTime() + token.expires_in * 1000);
return this;
};
return AuthService;
}());
var HttpService = /** @class */ (function () {
function HttpService(_config, _logger) {
if (_logger === void 0) { _logger = console; }
this._config = _config;
this._logger = _logger;
}
HttpService.prototype.request = function (uri, options) {
var _this = this;
if (this._config.debug) {
this._logger.log("[httpRequest] outgoing " + uri + " options[" + JSON.stringify(options, null, 2) + "]");
}
return fetch(uri, options)
.then(function (response) { return __awaiter(_this, void 0, void 0, function () {
var contentType, isJson, content;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
contentType = response.headers.get('content-type');
isJson = contentType && contentType.includes('application/json');
return [4 /*yield*/, (!!response.json && !!response.text
? isJson
? response.json()
: response.text()
: Promise.resolve(null))];
case 1:
content = _a.sent();
if (!response.ok && [304, 302].indexOf(response.status || -1) === -1) {
throw {
statusCode: response.status,
message: response.statusText,
error: content,
response: response,
options: options
};
}
if (this._config.debug) {
this._logger.log("[httpRequest] incoming going options[" + JSON.stringify(options, null, 2) + "] response[" + JSON.stringify(content, null, 2) + "]");
}
return [2 /*return*/, content];
}
});
}); });
};
return HttpService;
}());
var BatchRequest = /** @class */ (function () {
function BatchRequest(_token, _config, _actions) {
this._token = _token;
this._config = _config;
this._actions = _actions;
}
BatchRequest.prototype.toString = function () {
var _this = this;
var body = this._actions.map(function (action, idx) {
var bodyPart = '';
bodyPart += '--======boundary======\n';
bodyPart += 'Content-Type: application/http\n';
bodyPart += 'Content-ID: req' + idx + '\n';
bodyPart += '\n';
bodyPart += [
action.method.toUpperCase(),
' ',
RequestOptionsFacory.getDataApiUriFor(_this._token, action.dtoName, (action.method !== 'POST' ? action.dtoData.id : undefined)),
'?',
RequestOptionsFacory.stringify(__assign({ clientIdentifier: _this._config.clientIdentifier }, RequestOptionsFacory.getRequestAccountQueryParams(_this._token, _this._config), (action.method !== 'DELETE' && { dtos: RequestOptionsFacory.getDTOVersionsString([action.dtoName]) }), (action.force && action.method !== 'DELETE' && { forceUpdate: 'true' }), (action.force && action.method === 'DELETE' && { forceDelete: 'true' }), (action.method === 'DELETE' && !!action.dtoData && !!action.dtoData.lastChanged && { lastChanged: action.dtoData.lastChanged }))),
' ',
'HTTP/1.1\n'
].join('');
bodyPart += 'Content-Type: application/json\n';
bodyPart += '\n';
bodyPart += JSON.stringify(action.dtoData);
bodyPart += '\n\n';
return bodyPart;
}).join('\n');
return body;
};
return BatchRequest;
}());
var BatchResponse = /** @class */ (function () {
function BatchResponse(body) {
this.body = body;
}
BatchResponse.prototype.parseResponseContentType = function (response) {
var matches = response.match(new RegExp('(content-type: )(.*)', 'ig'));
return !matches || !matches[1] // the first content-type is the type of the request
? undefined
: matches[1].toLowerCase().replace('content-type: ', '').trim();
};
BatchResponse.prototype.parseRequestURL = function (response) {
var matches = response.match(new RegExp('(http|https)://[a-z0-9\-_]+(\.[a-z0-9\-_]+)+([a-z0-9\-\.,@\?^=%&;:/~\+#]*[a-z0-9\-@\?^=%&;/~\+#])?', 'i'));
return !matches
? undefined
: matches[0];
};
BatchResponse.prototype.parseResponseStatusCode = function (response) {
var matches = response.match(new RegExp('(HTTP\/1.1 )([0-9]+)'));
return !matches || !matches[0]
? undefined
: parseInt(matches[0].replace('HTTP/1.1 ', '').trim(), 10);
};
BatchResponse.prototype.parseResponseBody = function (response) {
try {
var jsonString = response.split('\n')
.filter(function (line) { return line.trim().indexOf('{') === 0; })[0];
var result = typeof jsonString === 'undefined' || !jsonString || jsonString === 'undefined' ? '{}' : jsonString;
return JSON.parse(result);
}
catch (ex) {
throw new Error("Error (" + (ex instanceof Error && ex.message ? ex.message : ex) + ") parsing body of " + response);
}
};
BatchResponse.prototype.parseRequestContentId = function (response) {
var matches = response.match(new RegExp('(Content-ID: )(.*)'));
return !matches || !matches[0]
? undefined
: matches[0].replace('Content-ID: ', '').trim();
};
BatchResponse.prototype.parseChildResponse = function (response) {
return {
body: this.parseResponseBody(response),
statusCode: this.parseResponseStatusCode(response),
contentType: this.parseResponseContentType(response),
requestOptions: {
url: this.parseRequestURL(response),
contentId: this.parseRequestContentId(response)
}
};
};
BatchResponse.prototype.toJson = function () {
var _this = this;
return this.body.split('Content-ID')
.map(function (it) { return 'Content-ID' + it; })
.filter(function (it, idx) { return idx !== 0; })
.map(function (it) { return _this.parseChildResponse(it); });
};
return BatchResponse;
}());
var ClientService = /** @class */ (function () {
function ClientService(_config, _http, _auth) {
this._config = _config;
this._http = _http;
this._auth = _auth;
}
ClientService.prototype._requestDataApi = function (method, resourceName, resourceData, _a, additionalQs) {
var _b = _a === void 0 ? { resourceId: null, externalId: null } : _a, resourceId = _b.resourceId, externalId = _b.externalId;
if (additionalQs === void 0) { additionalQs = {}; }
return __awaiter(this, void 0, void 0, function () {
var token, queryParams, uri;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, this.login()];
case 1:
token = _c.sent();
queryParams = new URLSearchParams(Object.assign({}, RequestOptionsFacory.getRequestAccountQueryParams(token, this._config), method !== 'DELETE' ? { dtos: RequestOptionsFacory.getDTOVersionsString([resourceName]) } : undefined, additionalQs));
uri = RequestOptionsFacory.getDataApiUriFor(token, resourceName, resourceId, externalId) + "?" + queryParams;
return [4 /*yield*/, this._http.request(uri, {
method: method,
headers: RequestOptionsFacory.getRequestHeaders(token, this._config),
body: method != 'GET' ? JSON.stringify(resourceData) : undefined
})];
case 2: return [2 /*return*/, _c.sent()];
}
});
});
};
ClientService.prototype.login = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this._auth.ensureToken(this._config)];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
ClientService.prototype.query = function (coreSQL, dtoNames) {
return __awaiter(this, void 0, void 0, function () {
var token, queryParams;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.login()];
case 1:
token = _a.sent();
queryParams = new URLSearchParams(__assign({}, RequestOptionsFacory.getRequestAccountQueryParams(token, this._config), { dtos: RequestOptionsFacory.getDTOVersionsString(dtoNames) }));
return [4 /*yield*/, this._http.request(token.cluster_url + "/api/query/v1?" + queryParams, {
method: 'POST',
headers: Object.assign({ 'Content-Type': 'application/json' }, RequestOptionsFacory.getRequestHeaders(token, this._config)),
body: JSON.stringify({ query: coreSQL })
})];
case 2: return [2 /*return*/, _a.sent()];
}
});
});
};
ClientService.prototype.getResource = function (resourceName, id, queryParams) {
if (queryParams === void 0) { queryParams = undefined; }
return __awaiter(this, void 0, void 0, function () {
var response;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this._requestDataApi('GET', resourceName, null, id, queryParams)];
case 1:
response = _a.sent();
return [2 /*return*/, typeof response === 'string' ? JSON.parse(response) : response];
}
});
});
};
ClientService.prototype.deleteResource = function (resourceName, id, lastChanged) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this._requestDataApi('DELETE', resourceName, null, id, { lastChanged: lastChanged })];
});
});
};
ClientService.prototype.postResource = function (resourceName, resource, queryParams) {
if (queryParams === void 0) { queryParams = undefined; }
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this._requestDataApi('POST', resourceName, resource, undefined, queryParams)];
});
});
};
ClientService.prototype.putResource = function (resourceName, id, resource, queryParams) {
if (queryParams === void 0) { queryParams = undefined; }
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this._requestDataApi('PUT', resourceName, resource, id, queryParams)];
});
});
};
ClientService.prototype.patchResource = function (resourceName, id, resource, queryParams) {
if (queryParams === void 0) { queryParams = undefined; }
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this._requestDataApi('PATCH', resourceName, resource, id, queryParams)];
});
});
};
ClientService.prototype.batch = function (actions) {
return __awaiter(this, void 0, void 0, function () {
var token, body, queryParams, responseBody;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.login()];
case 1:
token = _a.sent();
body = new BatchRequest(token, this._config, actions).toString();
queryParams = new URLSearchParams(Object.assign(__assign({ clientIdentifier: this._config.clientIdentifier, dtos: RequestOptionsFacory.getDTOVersionsString(actions.map(function (it) { return it.dtoName; })) }, RequestOptionsFacory.getRequestAccountQueryParams(token, this._config))));
return [4 /*yield*/, this._http.request(token.cluster_url + "/api/data/batch/v1?" + queryParams, {
method: 'POST',
headers: __assign({ 'content-type': 'multipart/mixed;boundary="======boundary======"' }, RequestOptionsFacory.getRequestHeaders(token, this._config)),
body: body
})];
case 2:
responseBody = _a.sent();
return [2 /*return*/, responseBody !== null
? new BatchResponse(responseBody).toJson()
: []];
}
});
});
};
ClientService.prototype.getToken = function () {
return this._auth.getToken();
};
ClientService.prototype.setToken = function (token) {
this._auth.setToken(token);
return this;
};
return ClientService;
}());
var CoreAPIClient = /** @class */ (function () {
/**
* The CoreAPIClient
*
* ```typescript
*{
* // [mandatory] your client configuration
* clientIdentifier: '<your-clientIdentifier>',
* clientSecret: '<your-clientSecret>',
* clientVersion: '<your-clientVersion>',
*
* // [optional] oauth grant type, default=password
* authGrantType: 'password' | 'client_credentials' | undefined
*
* // [optional] | [mandatory] if oauth grant type password
* authAccountName: '<your-authAccountName>',
*
* // [optional] | [mandatory] if oauth grant type password
* authUserName: '<your-authUserName>',
*
* // [optional] | [mandatory] if oauth grant type password
* authPassword: '<your-authPassword>',
*
* // [optional] or default=FIRST
* authCompany: '<your-authCompany>',
*
* // [optional] provide verbose logs
* debug: false,
*
* // [optional] enable using custom oauth endpoints
* oauthEndpoint: 'https://ds.coresuite.com/api/oauth2/v1',
*
* // [optional] client will cache token (helpful for writing integration tests)
* tokenCacheFilePath: './.myToken.json'
*
*}
* ```
* @param _config ClientConfig
* @returns CoreAPIClient
*/
function CoreAPIClient(config) {
this._config_default = {
debug: false,
oauthEndpoint: 'https://ds.coresuite.com/api/oauth2/v1',
tokenCacheFilePath: undefined,
clientIdentifier: '<your-clientIdentifier>',
clientSecret: '<your-clientSecret>',
clientVersion: '<your-clientVersion>',
authGrantType: 'password',
authAccountName: undefined,
authUserName: undefined,
authPassword: undefined,
authCompany: undefined
};
var _config = Object.assign(this._config_default, config);
var _http = new HttpService(_config);
var _auth = new AuthService(_http);
this._client = new ClientService(_config, _http, _auth);
}
/**
* Creates UUID
* @returns a uuid that can be used as an FSM object id
*/
CoreAPIClient.createUUID = function () {
return RequestOptionsFacory.getUUID().toUpperCase();
};
/**
* Here, you can input and execute the CoreSQL query.
*
* related api docs:
* https://help.sap.com/viewer/fsm_query_api/Cloud/en-US/query-api-intro.html
*
* @param coreSQL valid CoreSQL
* @param dtoNames DTOName[]
* @returns Promise<{ data: DTO[] }>
*/
CoreAPIClient.prototype.query = function (coreSQL, dtoNames) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this._client.query(coreSQL, dtoNames)];
});
});
};
/**
* Retrieving Lists of Objects by Id
*
* related api docs:
* https://help.sap.com/viewer/fsm_data_api/Cloud/en-US
*
* @param resourceName DTOName
* @param resourceId uuid as string
* @returns Promise<ClientResponse<DTO>>
*/
CoreAPIClient.prototype.getById = function (resourceName, resourceId) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this._client.getResource(resourceName, { resourceId: resourceId })];
});
});
};
/**
* Retrieving Lists of Objects by ExternalId
*
* Note: [useExternalIds=true] option will be used
* referenced resources will not be a uid-string or null but of object or null
* containing id and externalId if present
* ```typescript
* [referenced-resource] : { id: string, externalId? : string } | null
* ```
*
* related api docs:
* https://help.sap.com/viewer/fsm_data_api/Cloud/en-US
*
* @param resourceName DTOName
* @param externalId externalId as string
* @returns Promise<ClientResponse<DTO>>
*/
CoreAPIClient.prototype.getByExternalId = function (resourceName, externalId) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this._client.getResource(resourceName, { externalId: externalId }, { useExternalIds: true })];
});
});
};
/**
* Deletes Existing Object by Id
* related api docs:
* https://help.sap.com/viewer/fsm_data_api/Cloud/en-US
*
* @param resourceName DTOName
* @param resource { id: string, lastChanged: number }
* @returns
*/
CoreAPIClient.prototype.deleteById = function (resourceName, resource) {
return __awaiter(this, void 0, void 0, function () {
var id, lastChanged;
return __generator(this, function (_a) {
id = resource.id, lastChanged = resource.lastChanged;
return [2 /*return*/, this._client.deleteResource(resourceName, { resourceId: id }, lastChanged)];
});
});
};
/**
* Deletes Existing Object by ExternalId
* related api docs:
* https://help.sap.com/viewer/fsm_data_api/Cloud/en-US
*
* @param resourceName DTOName
* @param resource { id: string, lastChanged: number }
* @returns
*/
CoreAPIClient.prototype.deleteByExternalId = function (resourceName, resource) {
return __awaiter(this, void 0, void 0, function () {
var externalId, lastChanged;
return __generator(this, function (_a) {
externalId = resource.externalId, lastChanged = resource.lastChanged;
return [2 /*return*/, this._client.deleteResource(resourceName, { externalId: externalId }, lastChanged)];
});
});
};
/**
* Creating Objects by Id
*
* related api docs:
* https://help.sap.com/viewer/fsm_data_api/Cloud/en-US
*
* @param resourceName DTOName
* @param resource should contain in the body the ENTIRE updated resource
* @returns Promise<ClientResponse<DTO>>
*/
CoreAPIClient.prototype.post = function (resourceName, resource) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this._client.postResource(resourceName, resource)];
});
});
};
/**
* Creating Objects by ExternalId
*
* Note: [useExternalIds=true] option will be used
* referenced resources will not be a uid-string or null but of object or null
* containing id and externalId if present
* ```typescript
* [referenced-resource] : { id: string, externalId? : string } | null
* ```
*
* related api docs:
* https://help.sap.com/viewer/fsm_data_api/Cloud/en-US
*
* @param resourceName DTOName
* @param resource should contain in the body the ENTIRE updated resource
* @returns Promise<ClientResponse<DTO>>
*/
CoreAPIClient.prototype.postByExternalId = function (resourceName, resource) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this._client.postResource(resourceName, resource, { useExternalIds: true })];
});
});
};
/**
* Updating Existing Objects by Id
*
* related api docs:
* https://help.sap.com/viewer/fsm_data_api/Cloud/en-US
*
* @param resourceName resourceName
* @param resource should contain in the body the ENTIRE updated resource
* @returns Promise<ClientResponse<DTO>>
*/
CoreAPIClient.prototype.put = function (resourceName, resource) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this._client.putResource(resourceName, { resourceId: resource.id }, resource)];
});
});
};
/**
* Updating Existing Objects by ExternalId
*
* Note: [useExternalIds=true] option will be used
* referenced resources will not be a uid-string or null but of object or null
* containing id and externalId if present
* ```typescript
* [referenced-resource] : { id: string, externalId? : string } | null
* ```
*
* related api docs:
* https://help.sap.com/viewer/fsm_data_api/Cloud/en-US
*
* @param resourceName resourceName
* @param resource should contain in the resource the ENTIRE updated resource
* @returns Promise<ClientResponse<DTO>>
*/
CoreAPIClient.prototype.putByExternalId = function (resourceName, resource) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this._client.putResource(resourceName, { externalId: resource.externalId }, resource, { useExternalIds: true })];
});
});
};
/**
* Updating Existing Objects by Id
* should contain [id] in the body the entire updated resource
*
* related api docs:
* https://help.sap.com/viewer/fsm_data_api/Cloud/en-US
*
* @param resourceName resourceName
* @param resource should contain in the body the [id] & [FIELDS THAT YOU WANT TO UPDATE]
* @returns Promise<ClientResponse<DTO>>
*/
CoreAPIClient.prototype.patch = function (resourceName, resource) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this._client.patchResource(resourceName, { resourceId: resource.id }, resource)];
});
});
};
/**
* Updating Existing Objects by ExternalId
* should contain [ExternalId] in the resource the entire updated resource
*
* Note: [useExternalIds=true] option will be used
* referenced resources will not be a uid-string or null but of object or null
* containing id and externalId if present
* ```typescript
* [referenced-resource] : { id: string, externalId? : string } | null
* ```
*
* related api docs:
* https://help.sap.com/viewer/fsm_data_api/Cloud/en-US
*
* @param resourceName resourceName
* @param resource should contain in the resource the [externalId] & [FIELDS THAT YOU WANT TO UPDATE]
* @returns Promise<ClientResponse<DTO>>
*/
CoreAPIClient.prototype.patchByExternalId = function (resourceName, resource) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this._client.patchResource(resourceName, { externalId: resource.externalId }, resource, { useExternalIds: true })];
});
});
};
/**
* Batch request with transational support
* requests will be executed in oder of the actions array.
*
* Example:
* ```typescript
* const actions = [
* new CreateAction('ServiceCall', { ... }),
* new UpdateAction('ServiceCall', { id, lastChanged ... }),
* new DeleteAction('ServiceCall', { id, lastChanged ... })
* ];
* await client.batch(actions)
* ```
*
* related api docs:
* https://help.sap.com/viewer/fsm_data_api/Cloud/en-US/batch-api-intro.html
*
* @param actions BatchAction | CreateAction | UpdateAction | DeleteAction
* @returns Promise<BatchResponseJson<T>[]>
*/
CoreAPIClient.prototype.batch = function (actions) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this._client.batch(actions)];
});
});
};
/**
* Will use provided ClientConfig and perform a Login.
*
* Note: that it is **not required** to explicitly call client.login()
* before each client action. The CoreAPIClient will login and **keep a internally token copy**
* and will use this **up to its expiration** and **will auto refresh** when needed.
* Calling client.login()