UNPKG

@plattar/plattar-api

Version:

Module for interfacing with the Plattar API (https://www.plattar.com)

491 lines (400 loc) 15.5 kB
const fetch = require("node-fetch"); class PlattarQuery { constructor(target, server) { if (!target) { throw new Error("PlattarQuery cannot be created as target object cannot be null"); } if (!server) { throw new Error("PlattarQuery cannot be created as server object cannot be null"); } this._target = target; this._server = server; this._params = []; this._getIncludeQuery = []; } get target() { return this._target; } get server() { return this._server; } getCookie(cname) { try { let name = cname + "="; let decodedCookie = decodeURIComponent(document.cookie); let ca = decodedCookie.split(';'); for (let i = 0; i < ca.length; i++) { let c = ca[i]; while (c.charAt(0) == ' ') { c = c.substring(1); } if (c.indexOf(name) == 0) { return c.substring(name.length, c.length); } } } catch (error) { /* silent */ } return ""; } _get(opt) { return new Promise((resolve, reject) => { const target = this.target; const server = this.server; // we cannot perform a GET request without an ID if (!target.id) { reject(new Error("PlattarQuery." + target.type() + ".get() - object id is missing")); return; } const options = opt || { cache: true }; // look in the cache only if its enabled if (options.cache === true) { // check global cache first const cached = PlattarQuery._GetGlobalCachedObject(target); if (cached) { resolve(cached); return; } } // otherwise, proceed with the fetching op const origin = server.originLocation.api_read; const auth = server.authToken; const headers = { 'cookie': 'laravel_session=' + this.getCookie('laravel_session') }; Object.assign(headers, auth); const reqopts = { method: "GET", headers: headers }; const includeQuery = this._IncludeQuery; const params = this._ParamFor("get"); let endpoint = origin + target.type() + "/" + target.id; if (includeQuery) { endpoint = endpoint + "?include=" + includeQuery; } if (params) { let appender = includeQuery ? "&" : "?"; params.forEach((param) => { endpoint = endpoint + appender + param.key + "=" + param.value; appender = "&"; }); } fetch(endpoint, reqopts) .then((res) => { if (res.ok) { try { return res.json(); } catch (err) { return new Error("PlattarQuery." + target.type() + ".get(" + target.id + ") - critical error occured, cannot proceed"); } } return new Error("PlattarQuery." + target.type() + ".get(" + target.id + ") - unexpected error occured, cannot proceed. error message is " + res.statusText); }) .then((json) => { if (json instanceof Error) { reject(json); } else { const PlattarUtil = require("../util/plattar-util.js"); PlattarUtil.reconstruct(target, json, options); resolve(target); } }); }); } _update() { return new Promise((resolve, reject) => { const target = this.target; const server = this.server; // we cannot perform a GET request without an ID if (!target.id) { reject(new Error("PlattarQuery." + target.type() + ".update() - object id is missing")); return; } // otherwise, proceed with the fetching op const origin = server.originLocation.api_write; const auth = server.authToken; const headers = { 'Accept': 'application/json', 'Content-Type': 'application/json', 'cookie': 'laravel_session=' + this.getCookie('laravel_session') }; Object.assign(headers, auth); const reqopts = { method: "PATCH", headers: headers, body: JSON.stringify( { data: { id: target.id, attributes: target.attributes }, meta: target.meta || {} } ) }; const params = this._ParamFor("update"); let endpoint = origin + target.type() + "/" + target.id; if (params) { let appender = "?"; params.forEach((param) => { endpoint = endpoint + appender + param.key + "=" + param.value; appender = "&"; }); } fetch(endpoint, reqopts) .then((res) => { if (res.ok) { try { return res.json(); } catch (err) { return new Error("PlattarQuery." + target.type() + ".update(" + target.id + ") - critical error occured, cannot proceed"); } } return new Error("PlattarQuery." + target.type() + ".update(" + target.id + ") - unexpected error occured, cannot proceed. error message is " + res.statusText); }) .then((json) => { if (json instanceof Error) { reject(json); } else { if (json.data) { const PlattarUtil = require("../util/plattar-util.js"); PlattarUtil.reconstruct(target, json, { cache: true }); } resolve(target); } }); }); } _create() { return new Promise((resolve, reject) => { const target = this.target; const server = this.server; // otherwise, proceed with the fetching op const origin = server.originLocation.api_write; const auth = server.authToken; const headers = { 'Accept': 'application/json', 'Content-Type': 'application/json', 'cookie': 'laravel_session=' + this.getCookie('laravel_session') }; Object.assign(headers, auth); const reqopts = { method: "POST", headers: headers, body: JSON.stringify( { data: { attributes: target.attributes }, meta: target.meta || {} } ) }; const params = this._ParamFor("create"); let endpoint = origin + target.type(); if (params) { let appender = "?"; params.forEach((param) => { endpoint = endpoint + appender + param.key + "=" + param.value; appender = "&"; }); } fetch(endpoint, reqopts) .then((res) => { if (res.ok) { try { return res.json(); } catch (err) { return new Error("PlattarQuery." + target.type() + ".create() - critical error occured, cannot proceed"); } } return new Error("PlattarQuery." + target.type() + ".create() - unexpected error occured, cannot proceed. error message is " + res.statusText); }) .then((json) => { if (json instanceof Error) { reject(json); } else { if (json.data) { target._id = json.data.id; const PlattarUtil = require("../util/plattar-util.js"); PlattarUtil.reconstruct(target, json, { cache: true }); } resolve(target); } }); }); } _delete() { return new Promise((resolve, reject) => { const target = this.target; const server = this.server; // we cannot perform a GET request without an ID if (!target.id) { reject(new Error("PlattarQuery." + target.type() + ".delete() - object id is missing")); return; } // otherwise, proceed with the fetching op const origin = server.originLocation.api_write; const auth = server.authToken; const headers = { 'Accept': 'application/json', 'Content-Type': 'application/json', 'cookie': 'laravel_session=' + this.getCookie('laravel_session') }; Object.assign(headers, auth); const reqopts = { method: "DELETE", headers: headers, body: JSON.stringify( { data: { id: target.id, attributes: target.attributes }, meta: target.meta || {} } ) }; const params = this._ParamFor("delete"); let endpoint = origin + target.type() + "/" + target.id; if (params) { let appender = "?"; params.forEach((param) => { endpoint = endpoint + appender + param.key + "=" + param.value; appender = "&"; }); } fetch(endpoint, reqopts) .then((res) => { if (res.ok) { try { return res.json(); } catch (err) { return new Error("PlattarQuery." + target.type() + ".delete() - critical error occured, cannot proceed"); } } return new Error("PlattarQuery." + target.type() + ".delete() - unexpected error occured, cannot proceed. error message is " + res.statusText); }) .then((json) => { if (json instanceof Error) { reject(json); } else { if (json.data) { target._id = json.data.id; const PlattarUtil = require("../util/plattar-util.js"); PlattarUtil.reconstruct(target, json, { cache: true }); } resolve(target); } }); }); } /** * Adds a specific request parameter */ _addParameter(key, value, type) { type = type || "all"; this._params.push({ key: key, value: value, type: type.toLowerCase() }); } /** * Includes this query with the next GET operation */ _include(args) { if (!args || args.length <= 0) { return this; } const PlattarUtil = require("../util/plattar-util.js"); args.forEach((obj) => { // object passed is of PlattarObject type if (Array.isArray(obj)) { obj.forEach((strObject) => { if (typeof strObject === "string" || strObject instanceof String) { this._getIncludeQuery.push(strObject); } else { throw new Error("PlattarQuery." + this.target.type() + ".include(...args) - argument of Array must only include Strings"); } }); } else if (PlattarUtil.isPlattarObject(obj)) { const type = obj.type(); if (Array.isArray(type)) { this._include(type); } else { this._getIncludeQuery.push(type); } } else { throw new Error("PlattarQuery." + this.target.type() + ".include(...args) - argument must be of type PlattarObject or Array but was type=" + (typeof obj) + " value=" + obj); } }); return this; } /** * Filters and returns all request parameters for a particular * request type */ _ParamFor(type) { type = type || "all"; const list = this._params.filter((objcheck) => { return objcheck.type === type || objcheck.type === "all"; }); if (list.length > 0) { return list; } return undefined; } /** * Performs a combination of all include queries */ get _IncludeQuery() { if (this._getIncludeQuery.length <= 0) { return undefined; } return `${this._getIncludeQuery.map((item) => `${item}`).join(",")}`; } } /** * Plattar uses GUID for all object ids. This means * that the GUID will not be shared between different * object instances. This allows us to create a global * static cache to optimise fetch operations for all * objects. * * WARNING: These are for internal uses only! */ PlattarQuery._GlobalObjectCache = {}; PlattarQuery._InvalidateGlobalCache = () => { PlattarQuery._GlobalObjectCache = {}; }; PlattarQuery._HasGlobalCachedObject = (obj) => { return PlattarQuery._GlobalObjectCache.hasOwnProperty(obj.id); }; PlattarQuery._GetGlobalCachedObject = (obj) => { return PlattarQuery._HasGlobalCachedObject(obj) ? PlattarQuery._GlobalObjectCache[obj.id] : undefined; }; PlattarQuery._SetGlobalCachedObject = (obj) => { // enable after extensive testing - too many bugs //PlattarQuery._GlobalObjectCache[obj.id] = obj; }; PlattarQuery._DeleteGlobalCachedObject = (obj) => { if (PlattarQuery._HasGlobalCachedObject(obj)) { delete PlattarQuery._GlobalObjectCache[obj.id]; } }; module.exports = PlattarQuery;