279 lines
7.8 KiB
JavaScript
279 lines
7.8 KiB
JavaScript
/* Xeslint-disable */
|
|
import store from "../store";
|
|
import router from "../router";
|
|
import auth from "./auth";
|
|
import errorHandler from "./errorhandler";
|
|
|
|
function stringifyPrimitive(v) {
|
|
switch (typeof v) {
|
|
case "string":
|
|
return v;
|
|
|
|
case "boolean":
|
|
return v ? "true" : "false";
|
|
|
|
case "number":
|
|
return isFinite(v) ? v : "";
|
|
|
|
default:
|
|
return "";
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
// Show unexpected errors during development
|
|
//
|
|
function devShowUnknownError(error) {
|
|
if (errorHandler.devMode) {
|
|
// eslint-disable-next-line
|
|
console.log("gzapi::devShowUnknownError, error is:");
|
|
// eslint-disable-next-line
|
|
console.log(error);
|
|
// eslint-disable-next-line
|
|
alert(
|
|
"DEV ERROR gzapi::devShowUnknownError - unexpected error during api operation see console "
|
|
);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////
|
|
// Try to handle an api error
|
|
// return true if handled or false if not
|
|
//
|
|
function handleError(action, error, route, reject) {
|
|
var errorMessage =
|
|
"API error: " + action + " route =" + route + ", message =" + error.message;
|
|
store.commit("logItem", errorMessage);
|
|
|
|
//BUGBUG?? What if the 401 is just a rights issue and not because they have no authentication at all??
|
|
//perhaps that would never happen
|
|
if (error.message && error.message.includes("NotAuthenticated")) {
|
|
store.commit("logItem", "User is not authorized, redirecting to login");
|
|
auth.logout();
|
|
router.push("/login");
|
|
return reject("[ErrorUserNotAuthenticated]");
|
|
}
|
|
//is it a network error?
|
|
//https://medium.com/@vinhlh/how-to-handle-networkerror-when-using-fetch-ff2663220435
|
|
if (error instanceof TypeError) {
|
|
if (
|
|
error.message.includes("Failed to fetch") ||
|
|
error.message.includes("NetworkError") ||
|
|
error.message.includes("Network request failed")
|
|
) {
|
|
store.commit("logItem", "Network error");
|
|
//note: using locale key in square brackets
|
|
return reject("[ErrorServerUnresponsive]");
|
|
//throw "Error: unable to contact server";
|
|
}
|
|
}
|
|
//Ideally this should never get called because any issue should be addressed above
|
|
devShowUnknownError(error);
|
|
}
|
|
|
|
export default {
|
|
status(response) {
|
|
//Handle expected api errors
|
|
if (response.status == 401) {
|
|
//must reject if not authorized
|
|
return Promise.reject(new Error("[ErrorUserNotAuthenticated]"));
|
|
}
|
|
|
|
if (response.status >= 200 && response.status < 300) {
|
|
return Promise.resolve(response);
|
|
} else {
|
|
//log unhandled api error
|
|
store.commit(
|
|
"logItem",
|
|
"API error: status=" +
|
|
response.status +
|
|
", statusText=" +
|
|
response.statusText +
|
|
", url=" +
|
|
response.url
|
|
);
|
|
//let it float up for dealing with by caller(s)
|
|
return Promise.resolve(response);
|
|
}
|
|
},
|
|
json(response) {
|
|
return response.json();
|
|
},
|
|
apiErrorToHumanString(apiError) {
|
|
//empty error object?
|
|
if (!apiError) {
|
|
return "apiErrorToHumanString():: Empty API eror, unknown";
|
|
}
|
|
//convert to readable string
|
|
return JSON.stringify(apiError);
|
|
},
|
|
patchAuthorizedHeaders() {
|
|
return {
|
|
//Accept: "application/json, text/plain, */*",
|
|
Accept: "application/json",
|
|
"Content-Type": "application/json-patch+json",
|
|
Authorization: "Bearer " + store.state.apiToken
|
|
};
|
|
},
|
|
postAuthorizedHeaders() {
|
|
return {
|
|
Accept: "application/json",
|
|
"Content-Type": "application/json",
|
|
Authorization: "Bearer " + store.state.apiToken
|
|
};
|
|
},
|
|
postUnAuthorizedHeaders() {
|
|
return {
|
|
Accept: "application/json",
|
|
"Content-Type": "application/json"
|
|
};
|
|
},
|
|
fetchPostNoAuthOptions(data) {
|
|
return {
|
|
method: "post",
|
|
mode: "cors",
|
|
headers: this.postUnAuthorizedHeaders(),
|
|
body: JSON.stringify(data)
|
|
};
|
|
},
|
|
fetchPostOptions(data) {
|
|
return {
|
|
method: "post",
|
|
mode: "cors",
|
|
headers: this.postAuthorizedHeaders(),
|
|
body: JSON.stringify(data)
|
|
};
|
|
},
|
|
fetchPutOptions(data) {
|
|
return {
|
|
method: "put",
|
|
mode: "cors",
|
|
headers: this.postAuthorizedHeaders(),
|
|
body: JSON.stringify(data)
|
|
};
|
|
},
|
|
fetchGetOptions() {
|
|
/* GET WITH AUTH */
|
|
return {
|
|
method: "get",
|
|
mode: "cors",
|
|
headers: this.postAuthorizedHeaders()
|
|
};
|
|
},
|
|
APIUrl(apiPath) {
|
|
if ("" == store.state.apiUrl) {
|
|
//construct the api url and store it
|
|
//development location?
|
|
if (
|
|
(window.location.hostname == "localhost" ||
|
|
window.location.hostname == "192.168.1.56") &&
|
|
window.location.port == "8080"
|
|
) {
|
|
store.commit("setAPIURL", "http://localhost:7575/api/v8.0/");
|
|
store.commit("setHelpURL", "http://localhost:7575/docs/");
|
|
store.commit(
|
|
"logItem",
|
|
"gzapi::APIUrl -> setting to dev. mode: " + store.state.apiUrl
|
|
);
|
|
} else {
|
|
//production location <protocol>//<hostname>:<port>/
|
|
store.commit(
|
|
"setHelpURL",
|
|
window.location.protocol + "//" + window.location.host + "/docs/"
|
|
);
|
|
store.commit(
|
|
"setAPIURL",
|
|
window.location.protocol + "//" + window.location.host + "/api/v8.0/"
|
|
);
|
|
store.commit(
|
|
"logItem",
|
|
"gzapi::APIUrl -> setting to: " + store.state.apiUrl
|
|
);
|
|
}
|
|
}
|
|
return store.state.apiUrl + apiPath;
|
|
},
|
|
/////////////////////////////
|
|
// ENCODE QUERY STRING
|
|
//
|
|
buildQuery(obj, sep, eq, name) {
|
|
sep = sep || "&";
|
|
eq = eq || "=";
|
|
if (obj === null) {
|
|
obj = undefined;
|
|
}
|
|
|
|
if (typeof obj === "object") {
|
|
return Object.keys(obj)
|
|
.map(function(k) {
|
|
var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
|
|
if (Array.isArray(obj[k])) {
|
|
return obj[k]
|
|
.map(function(v) {
|
|
return ks + encodeURIComponent(stringifyPrimitive(v));
|
|
})
|
|
.join(sep);
|
|
} else {
|
|
return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
|
|
}
|
|
})
|
|
.filter(Boolean)
|
|
.join(sep);
|
|
}
|
|
|
|
if (!name) return "";
|
|
return (
|
|
encodeURIComponent(stringifyPrimitive(name)) +
|
|
eq +
|
|
encodeURIComponent(stringifyPrimitive(obj))
|
|
);
|
|
},
|
|
///////////////////////////////////
|
|
// GET DATA FROM API SERVER
|
|
//
|
|
get(route) {
|
|
var that = this;
|
|
return new Promise(function getDataFromServer(resolve, reject) {
|
|
fetch(that.APIUrl(route), that.fetchGetOptions())
|
|
.then(that.status)
|
|
.then(that.json)
|
|
.then(response => {
|
|
resolve(response);
|
|
})
|
|
.catch(function handleGetError(error) {
|
|
//fundamental error, can't proceed with this call
|
|
handleError("GET", error, route, reject);
|
|
});
|
|
});
|
|
},
|
|
///////////////////////////////////
|
|
// POST / PUT DATA TO API SERVER
|
|
//
|
|
upsert(route, data) {
|
|
var that = this;
|
|
return new Promise(function upsertDataToServer(resolve, reject) {
|
|
//determine if this is a new or existing record
|
|
var fetchOptions = undefined;
|
|
if (data.concurrencyToken) {
|
|
fetchOptions = that.fetchPutOptions(data);
|
|
} else {
|
|
fetchOptions = that.fetchPostOptions(data);
|
|
}
|
|
fetch(that.APIUrl(route), fetchOptions)
|
|
.then(that.status)
|
|
.then(that.json)
|
|
.then(response => {
|
|
//Note: response.error indicates there is an error, however this is not an unusual condition
|
|
//it could be validation errors or other general error so we need to treat it here like it's normal
|
|
//and let the caller deal with it appropriately
|
|
resolve(response);
|
|
})
|
|
.catch(function handleUpsertError(error) {
|
|
handleError("UPSERT", error, route, reject);
|
|
});
|
|
});
|
|
}
|
|
|
|
//new functions above here
|
|
};
|