/* 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;
}