/* Enums */ // Enumeration of sort direction // Values: asc, desc var advDirection = Object.freeze({ Asc: 'asc', Desc: 'desc' }); // Enumeration of datatypes available // Values: string,date,boolean,decimal,integer,uniqueidentifier var advDataType = Object.freeze({ String: 'string', Date: 'date', Boolean: 'boolean', Decimal: 'decimal', Integer: 'integer', UniqueIdentifier: 'uniqueidentifier' }); // Enumeration of comparison types // Values: equals, notequals, like, notlike, greaterthan, greaterorequals,lessthan,lessorequals, all var advCompare = Object.freeze({ Equals: 'equals', NotEquals: 'notequals', Like: 'like', NotLike: 'notlike', GreaterThan: 'greaterthan', GreaterOrEquals: 'greaterorequals', LessThan: 'lessthan', LessOrEquals: 'lessorequals', All: 'all' }); /*Types */ function AdvKeyValueCompare(key, value, dataType, comparison) { /// /// Object that holds the Index/Filter criteria when performing a data request. /// /// The name of the field/index. /// The value to use in comparison. /// the datatype of the 'value' passed (advDataType). /// The comparison to perform (advCompare). this.Key = key; this.Value = value; this.DataType = dataType; this.Comparison = comparison; } function AdvSort(fieldName, direction) { /// /// Object that holds the sort when performing a data request /// /// Name of the field. /// The direction to sort (advDirection). this.Direction = direction; this.FieldName = fieldName; } function isUUID(uuid) { /// /// Determines whether the specified value is a unique identifier. /// /// The value passed. /// true if the specified is a unique identifier, otherwise false. let s = "" + uuid; s = s.match('^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'); if (s === null) { return false; } return true; } function AdvContentRequest(apiName, language) { /// /// Object to fill when performing a data request for multiple records. When populated use as parameter with advGetContent function. /// You can optionally specify the following: /// Index: the index to use when retrieving data (AdvKeyValueCompare) /// Filter: Multiple filters can be specified using AddFilter (AdvKeyValueCompare). Works as iterative 'where clause' with 'and' /// SortList: Multiple sort orders can be specified with AddSort (AdvSort). /// FieldList: Reduce payload by specifying what fields to return populated with data by using AddField. /// /// Name of the API. /// The language abbreviation code used in Advantage CSP associated with the data. this.name = 'AdvContentRequest'; this.ApiName = apiName; this.MaxRecords = 0; this.SkipRecords = 0; this.Header = { 'Authorization': 'Basic' }; this.Host = ''; this.CrossDomain = true; this.Authenticate = false; this.Action = 'POST'; var _index = new AdvKeyValueCompare("", "", "string", advCompare.All); // private member var _filter = []; var _sort = []; var _fieldList = []; var _language = "default"; if (language !== undefined && language !== null) _language = language; Object.defineProperty(this, "Language", { get: function () { if (language === undefined && language === null) return 'default'; return _language; }, set: function (value) { _language = value; } }); var checkDirection = function (val) { if (['asc', 'desc'].indexOf(val.toLowerCase()) >= 0) return ''; return 'Direction type must be of the following values: Asc, Desc'; } var checkCompare = function (val) { if (['equals', 'notequals', 'like', 'notlike', 'greaterthan', 'greaterorequals', 'lessthan', 'lessorequals', 'all'].indexOf(val.toLowerCase()) >= 0) return ''; return 'Compare type must be of the following values: Equals, NotEquals, Like, NotLike, GreaterThan, GreaterOrEquals, LessThanLessOrEquals, All'; } var checkDataType = function (val) { if (['string', 'date', 'boolean', 'decimal', 'integer', 'uniqueidentifier'].indexOf(val.toLowerCase()) >= 0) return ''; return 'Data type must be of the following values: String, Date, Boolean, Decimal, Integer, UniqueIdentifier'; } Object.defineProperty(this, "Index", { get: function () { return _index; }, set: function (value) { if (value.constructor.name === "AdvKeyValueCompare") { var result = checkCompare(value.Comparison); if (result) throw result; result = checkDataType(value.DataType); if (result) throw result; _index = value; } else throw "Index property type error"; } }); this.set_Index = function (key, value, dataType, comparison) { var result = checkCompare(comparison); if (result) throw result; result = checkDataType(dataType); if (result) throw result; _index = new AdvKeyValueCompare(key, value, dataType, comparison); } Object.defineProperty(this, "Filter", { get: function () { return _filter; }, set: function (value) { var result = ''; if (Array.isArray(value)) { var arrayLength = value.length; for (var i = 0; i < arrayLength; i++) { if (value[i].constructor.name !== "AdvKeyValueCompare") throw "Filter property type error"; result = checkCompare(value.Comparison); if (result) throw result; result = checkDataType(value.DataType); if (result) throw result; } _filter = value; } else { throw "Filter property type error"; } } }); this.AddFilter = function (key, value, dataType, comparison) { var result = ''; result = checkCompare(comparison); if (result) throw result; result = checkDataType(dataType); if (result) throw result; if (result === '') { var tmp = new AdvKeyValueCompare(key, value, dataType, comparison); _filter.push(tmp); } }; Object.defineProperty(this, "SortList", { get: function () { return _sort; }, set: function (value) { var result = ''; if (Array.isArray(value)) { var arrayLength = value.length; for (var i = 0; i < arrayLength; i++) { if (value[i].constructor.name !== "AdvSort") throw "SortList property type error"; result = checkDirection(value.Direction); if (result) throw result; } _sort = value; } else { throw "SortList property type error"; } } }); this.AddSort = function (fieldName, direction) { var result = ''; result = checkDirection(direction); if (result) throw result; if (result === '') { var tmp = new AdvSort(fieldName, direction); _sort.push(tmp); } else throw "Sort property type error"; }; Object.defineProperty(this, "FieldList", { get: function () { return _fieldList; }, set: function (value) { var result = ''; if (Array.isArray(value)) { var arrayLength = value.length; for (var i = 0; i < arrayLength; i++) { if (value[i].constructor.name !== "String") throw "FieldList property type error"; } _fieldList = value; } else { throw "FieldList property type error"; } } }); this.AddField = function (fieldName) { if (fieldName.constructor.name !== "String") throw "FieldList property type error"; if (fieldName !== '') { _fieldList.push(fieldName); } else throw "Sort property type error"; }; } function AdvUpdateRequest(apiName, language) { /// /// Object to fill when performing a data update for one or multiple records. When populated use as parameter with advUpdateContent function. /// You can optionally specify the following: /// /// Name of the API. /// The language abbreviation code used in Advantage CSP associated with the data. /// The object/objects to be updated. this.name = 'AdvUpdateRequest'; this.ApiName = apiName; this.Header = { 'Authorization': 'Basic' }; this.Host = ''; this.CrossDomain = true; this.Authenticate = false; this.Action = 'PUT'; var _language = "default"; if (language !== undefined && language !== null) _language = language; Object.defineProperty(this, "Language", { get: function () { if (language === undefined && language === null) return 'default'; return _language; }, set: function (value) { _language = value; } }); // Internal variable to hold either a JSON object or an array var _data = null; Object.defineProperty(this, "Data", { get: function () { return _data; }, set: function (value) { if (value !== null && typeof value === "object") { _data = value; // Allows object `{}` or array `[]` } else { throw new Error("Data must be a JSON object or an array."); } } }); } function AdvContentRequestById(apiName, language, id) { /// /// Object to fill when performing a data request for a single record. When populated use as parameter with advGetContent function. /// You can optionally specify the following: /// Id: The masterId or seoName for the object requested /// /// Name of the API. /// The language abbreviation code used in Advantage CSP associated with the data. /// The masterId or seoName for the object requested this.name = 'AdvContentRequestById'; this.ApiName = apiName; this.Header = { 'Authorization': 'Basic' }; this.Host = '' this.CrossDomain = true; this.Authenticate = false; this.Action = 'POST'; var _id = ''; var _language = "default"; if (language !== undefined && language !== null) _language = language; if (id !== undefined && id !== null) _id = id; Object.defineProperty(this, "Language", { get: function () { if (language === undefined && language === null) return 'default'; return _language; }, set: function (value) { _language = value; } }); Object.defineProperty(this, "Id", { get: function () { return _id; }, set: function (value) { _id = value; } }); } function AdvSchemaRequest(apiName, language) { /// /// Object to fill when performing a data request for multiple records. When populated use as parameter with advGetSchema function. /// You can optionally specify the following: /// /// Name of the API. /// The language abbreviation code used in Advantage CSP associated with the data. this.name = 'AdvSchemaRequest'; this.ApiName = apiName; this.Header = { 'Authorization': 'Basic' }; this.Host = ''; this.CrossDomain = true; this.Authenticate = false; this.Action = 'POST'; var _language = "default"; if (language !== undefined && language !== null) _language = language; Object.defineProperty(this, "Language", { get: function () { if (language === undefined && language === null) return 'default'; return _language; }, set: function (value) { _language = value; } }); } /*Functions */ //* GET DATA BEGIN async function advGetContent(requestContent) { /// /// Makes a synchronous (using await) the rest service to retrieve the data based on the requestContent object. /// Usage: var result= await advGetContent(requestContent); /// /// Content of the request. advGetContent(requestContent, null, null); } function advGetContent(requestContent, successFunction, failureFunction) { let myHeaders = new Headers(); let requestUrl = requestContent.Authenticate ? '/advantageapi/secure/content/get/' : '/advantageapi/content/get/'; requestUrl += requestContent.ApiName; requestContent.Language = requestContent.Language || 'default'; requestUrl += '/' + requestContent.Language; if (requestContent.Host !== '') requestUrl = requestContent.Host + requestUrl; for (let key in requestContent.Header) { myHeaders.append(key, requestContent.Header[key]); } //Replace 'Content-Type' if it exists, otherwise set it myHeaders.set('Content-Type', 'application/json'); if (requestContent.name === "AdvContentRequest") { const theRequest = fetch(requestUrl, { method: requestContent.Action, body: JSON.stringify({ "Index": requestContent.Index, "Filter": requestContent.Filter, "SortList": requestContent.SortList, "FieldList": requestContent.FieldList, "MaxRecords": requestContent.MaxRecords, "SkipRecords": requestContent.SkipRecords }), headers: myHeaders, mode: getOriginType(requestUrl) }); return processRequest(theRequest, successFunction, failureFunction); } else if (requestContent.name === "AdvContentRequestById") { requestUrl += '/' + requestContent.Id; const theRequest = fetch(requestUrl, { method: requestContent.Action, headers: myHeaders, mode: getOriginType(requestUrl) }); return processRequest(theRequest, successFunction, failureFunction); } else { throw "Parameter must be of type AdvContentRequest or AdvContentRequestById"; } } //* GET DATA END async function advUpdateContent(updateRequest, successFunction, failureFunction) { /// /// Calls the rest service to retrieve the data based on the requestContent object. /// /// Content of the request. /// The success function. /// The failure function. if (failureFunction === undefined || failureFunction === null) failureFunction = successFunction; var myHeaders = new Headers(); var requestUrl = '/advantageapi/content/update/'; if (updateRequest.Authenticate) requestUrl = '/advantageapi/secure/content/update/'; requestUrl = requestUrl + updateRequest.ApiName; updateRequest.Language = updateRequest.Language || 'default'; requestUrl += '/' + updateRequest.Language; for (var key in updateRequest.Header) myHeaders.append(key, updateRequest.Header[key]); myHeaders.append('Content-Type', 'application/json'); if (updateRequest.name === "AdvUpdateRequest") { if (updateRequest.Host !== '') requestUrl = updateRequest.Host + requestUrl; var _data = updateRequest.Data; var _isArray = Array.isArray(updateRequest.Data.Data); if (_isArray) _data = updateRequest.Data.Data; const theRequest = fetch(requestUrl, { method: updateRequest.Action, body: JSON.stringify({ "Data": _data, "IsArray": _isArray, }), ContentType: 'application/json', headers: myHeaders, mode: getOriginType(requestUrl) }); return processRequest(theRequest, successFunction, failureFunction); } else { throw "Parameter must be of type AdvUpdateRequest "; } } async function advGetSchema(schemaRequest, successFunction, failureFunction) { /// /// Calls the rest service to retrieve the data based on the requestContent object. /// /// Content of the request. /// The success function. /// The failure function. var myHeaders = new Headers(); var requestUrl = '/advantageapi/content/schema/'; if (schemaRequest.Authenticate) requestUrl = '/advantageapi/secure/content/schema/'; requestUrl = requestUrl + schemaRequest.ApiName; schemaRequest.Language = schemaRequest.Language || 'default'; requestUrl += '/' + schemaRequest.Language; for (var key in schemaRequest.Header) myHeaders.append(key, schemaRequest.Header[key]); myHeaders.append('Content-Type', 'application/json'); if (schemaRequest.name === "AdvSchemaRequest") { if (schemaRequest.Host !== '') requestUrl = schemaRequest.Host + requestUrl; const theRequest = fetch(requestUrl, { method: schemaRequest.Action, ContentType: 'application/json', headers: myHeaders, mode: getOriginType(requestUrl) }); return processRequest(theRequest, successFunction, failureFunction); } else { throw "Parameter must be of type AdvSchemaRequest "; } } function processRequest(theRequest, successFunction, failureFunction) { if (failureFunction === undefined || failureFunction === null) failureFunction = successFunction; return theRequest .then(response => response.text().then(text => ({ status: response.status, body: text }))) .then(({ status, body }) => { return advParseRequest({ status, body }, false); }) .then(result => { if (!successFunction) { return result; } else { if (result.Error !== null) { return failureFunction(result); } else { return successFunction(result); } } }) .catch (err => failureFunction(advParseRequest({ 500: "An unexpected error occurred: " + (err.status || 500) + "-" + (err.message || "Unknown error") }, false))); } function getOriginType(apiUrl) { const currentOrigin = window.location.origin; // Get current page origin (protocol + host + port) let apiOrigin; // Try creating a URL object; if it works, it's an absolute URL // If it's a relative URL, resolve it against the current origin try {apiOrigin = new URL(apiUrl).origin;} catch (e) { apiOrigin = new URL(apiUrl, currentOrigin).origin;} // Compare the origins if (currentOrigin === apiOrigin) { return 'same-origin'; } else { return 'cors'; } } function advParseRequest(obj, singleResult) { try { if (!obj.status) obj.status = 500; if (obj.status === 200) { var json = {}; if (singleResult) json.Data = JSON.parse(obj.body); else json = JSON.parse(obj.body); json.ResponseCode = 200; json.Error = null; return json; } return advgetError(obj); } catch { return advgetError({ 500: "An unexpected error occurred" }) } } async function advgetError(obj) { var json = {}; json.ResponseCode = obj.status; const error = new Error(); error.status = obj.status; error.message = obj.body; // Default messages for known errors const defaultMessages = { 400: "Bad Request – The server could not understand the request.", 401: "Unauthorized – Authentication is required.", 403: "Forbidden – You do not have permission to access this resource.", 404: "API object is unavailable", // Always override 404 message 405: "Method Not Allowed – The request method is not supported.", 408: "Request Timeout – The server timed out waiting for the request.", 429: "Too Many Requests – You have exceeded the request limit.", 500: "Internal Server Error – An unexpected error occurred.", 502: "Bad Gateway – Received an invalid response from the upstream server.", 503: "Service Unavailable – The server is currently unavailable.", 504: "Gateway Timeout – The server took too long to respond." }; if (error.status === 404) error.message = "API object is unavailable"; // Always override for 404 else if (error.message === undefined || error.message == null || error.message === '') error.message = defaultMessages[error.status] || "An unknown error occurred."; json.Error = error; json.Data = null; return json; }