UNPKG

maximo-dev-tools

Version:

Tools used with the development of Maximo projects

1,426 lines (1,200 loc) 55.4 kB
/* eslint-disable indent */ /* eslint-disable no-redeclare */ import axios from "axios"; import https from "https"; import { CookieJar, Cookie } from "tough-cookie"; import semver from "semver"; import { InvalidApiKeyError, LoginFailedError, MaximoError, MxAccessError, MxAdminLogoutError, MxDuplicateTransactionError, PasswordExpiredError, PasswordResetFailedError, ResourceNotFoundError } from "./errors.js"; import { fileURLToPath } from "url"; import * as fs from "fs"; import * as path from "path"; import MaximoConfig from "./maximo-config.js"; import { TextDecoder } from "util"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); export default class MaximoClient { constructor(config) { if (!(config instanceof MaximoConfig)) { throw "config parameter must be an instance of MaximoConfig"; } this.maxVersion = "undefined"; // keep a reference to the config for later use. this.config = config; this.requiredScriptVersion = "1.45.0"; this.currentScriptVersion = "1.45.0"; this.scriptEndpoint = "mxscript"; if (config.ca) { https.globalAgent.options.ca = config.ca; } https.globalAgent.options.rejectUnauthorized = !config.allowUntrustedCerts; // This is the way it is supposed to be done, but in tested Axios seems to ignore the agent. // Allows untrusted certificates agent. // let httpsAgent = new https.Agent({ // rejectUnauthorized: !config.allowUntrustedCerts, // ca: config.ca // }); this.jar = new CookieJar(); this.client = axios.create({ withCredentials: true, // httpsAgent: httpsAgent, baseURL: config.baseURL, timeout: config.connectTimeout }); this.client.interceptors.request.use( function (request) { // If the requested URL is the login endpoint, the inject the auth headers. if (request.url === "login") { this._addAuthHeaders(request); if (this.config.apiKey) { if (request.params) { request.params["apikey"] = config.apiKey } else { request.params = { "apikey": config.apiKey }; } } if (request.params) { request.params["csrf"] = "1"; } else { request.params = { "csrf": "1" }; } request.maxRedirects = 0; request.validateStatus = function (status) { return status == 200 || status == 302; }; } else { // // Add the x-public-uri header to ensure Maximo response URI's are properly addressed for external access. // // https://www.ibm.com/docs/en/mema"s?topic=imam-downloading-work-orders-by-using-maximo-mxapiwodetail-api request.headers["x-public-uri"] = this.config.baseURL; if (this.config.apiKey) { if (typeof request.params !== "undefined") { let params = request.params; params.lean = this.config.lean ? "true" : "false"; params.apikey = this.config.apiKey; } else { request.params = { "lean": this.config.lean ? "true" : "false", "apikey": this.config.apiKey }; } } else { if (typeof request.params !== "undefined") { let params = request.params; params.lean = this.config.lean ? "true" : "false"; request.params = params; } else { request.params = { "lean": this.config.lean ? "true" : "false" }; } } } // @ts-ignore this.jar.getCookiesSync(request.url && request.url.startsWith("http") ? request.url : request.baseURL, function (err, cookies) { request.headers["cookie"] = cookies.join("; "); }); return request; }.bind(this) ); this.client.interceptors.response.use( function (response) { const cookies = response.headers["set-cookie"]; if (cookies) { let parsedCookies; if (cookies instanceof Array) { // @ts-ignore parsedCookies = cookies.map(Cookie.parse); } else { parsedCookies = [Cookie.parse(cookies)]; } parsedCookies.forEach((cookie) => { this.jar.setCookieSync(cookie, response.request.protocol + "//" + response.request.host); }); } if (response.headers["csrftoken"]) { this._csrfToken = response.headers["csrftoken"]; } return response; }.bind(this), this._processError.bind(this) ); // When the first created the state of the client is disconnected. this._isConnected = false; this._currentLogFile = undefined; this._isLogging = false; this._csrfToken = null; } get connected() { return this._isConnected; } async connect() { var response = await this.client.post("login"); var maxRedirects = 5; var redirectUri = response.headers["location"]; if (response.status == 302 && this._isOIDCAuthRedirectResponse(response)) { for (var i = 0; i < maxRedirects; i++) { if (redirectUri == null) { break; } response = await this.client.get(redirectUri, { maxRedirects: 0, withCredentials: true, auth: { "username": this.config.username, "password": this.config.password }, validateStatus: function (status) { return status == 200 || status == 302; } }); if (response.status == 302) { // get the redirect URL from the header redirectUri = response.headers["location"]; } else { break; } } } else if (response.status == 302 && this._isLTPAFormRedirect(response)) { for (var i = 0; i < maxRedirects; i++) { if (redirectUri == null) { break; } if (redirectUri.includes("login.jsp?")) { const headers = { "content-type": "application/x-www-form-urlencoded" }; const data = `j_username=${this.config.username}&j_password=${this.config.password}`; response = await this.client.post(this.config.formLoginURL, data, { maxRedirects: 0, headers: headers, withCredentials: true, validateStatus: function (status) { return status == 200 || status == 302; } }); await this.client.get(redirectUri); response = await this.client.post("login"); break; } else if (redirectUri.includes("loginerror.jsp")) { this._isConnected = false; throw new LoginFailedError("You cannot log in at this time. Contact the system administrator."); } else { response = await this.client.post(redirectUri, { maxRedirects: 0, withCredentials: true, validateStatus: function (status) { return status == 200 || status == 302; } }); if (response.status == 302) { // get the redirect URL from the header redirectUri = response.headers["location"]; } else { break; } } } } this._responseHandler(response); } _addAuthHeaders(request) { request.headers.common["maxauth"] = this.config.maxauth; if (!this.config.maxauthOnly) { request.auth = { "username": this.config.username, "password": this.config.password }; } request.withCredentials = true; } _isLTPAFormRedirect(response) { if (!response) { return false; } // Check whether this is a redirect response if (response.statusCode < 300 || response.statusCode >= 400) return false; const cookies = response.headers["set-cookie"]; if (cookies) { var parsedCookies; if (cookies instanceof Array) { // @ts-ignore parsedCookies = cookies.map(Cookie.parse); } else { parsedCookies = [Cookie.parse(cookies)]; } if (!parsedCookies || parsedCookies.length == 0) { return false; } // MAS8 sets matching cookies: WASOidcStateXXXXXX and WASReqURLOidcXXXXXX // This is from specific observation and may need review/revision var wasPostParamName = "WASPostParam"; var wasPostParamCookie = parsedCookies.filter((c) => c.key.toLowerCase().startsWith(wasPostParamName.toLowerCase())); return wasPostParamCookie || wasPostParamCookie.length > 0; } else { return false; } } _isOIDCAuthRedirectResponse(response) { if (!response) { return false; } // Check whether this is a redirect response if (response.statusCode < 300 || response.statusCode >= 400) return false; const cookies = response.headers["set-cookie"]; if (cookies) { var parsedCookies; if (cookies instanceof Array) { // @ts-ignore parsedCookies = cookies.map(Cookie.parse); } else { parsedCookies = [Cookie.parse(cookies)]; } if (!parsedCookies || parsedCookies.length == 0) { return false; } // MAS8 sets matching cookies: WASOidcStateXXXXXX and WASReqURLOidcXXXXXX // This is from specific observation and may need review/revision var oidcStateCookieNamePrefix = "WASOidcState"; var oidcStateCookie = parsedCookies.filter((c) => c.key.toLowerCase().startsWith(oidcStateCookieNamePrefix.toLowerCase())); if (!oidcStateCookie || oidcStateCookie.length == 0) return false; // determine the identifier for the corresponding req url cookie name. var stateIdentifier = oidcStateCookie[0].key.substring(oidcStateCookieNamePrefix.length); var oidcReqUrlCookieNamePrefix = "WASReqURLOidc"; var targetCookieName = oidcReqUrlCookieNamePrefix + stateIdentifier; // ensure we have a matching req url cookie return parsedCookies.filter((c) => c.key.toLowerCase() == targetCookieName.toLowerCase()).length > 0; } else { return false; } } _responseHandler(response) { if (response) { if (response.status == 200) { if (response.data && response.data.maxupg) { this.maxVersion = response.data.maxupg; } this._isConnected = true; } else if (response.status == 401) { this._isConnected = false; throw new LoginFailedError("You cannot log in at this time. Contact the system administrator."); } else { this._isConnected = false; } } } async disconnect() { // we don't care about the response status because if it fails there is nothing we can do about it. if (this._isConnected) { try { await this.client.post("logout", { withCredentials: true }); } catch (error) { console.error("Warning disconnecting: " + JSON.stringify(error)); } } // can't be logging if disconnected. this._isLogging = false; } async getScriptSource(script, fileName) { if (!this._isConnected) { await this.connect(); } let isPython = fileName.endsWith(".py") || fileName.endsWith(".jy"); const options = { url: "script/sharptree.autoscript.deploy/source/" + (isPython ? "/python" : ""), method: MaximoClient.Method.POST, headers: { "Content-Type": "text/plain", Accept: "application/json" }, data: script }; await new Promise((resolve) => setTimeout(resolve, 100)); // @ts-ignore const result = await this.client.request(options); return result.data; } async dbConfigRequired() { if (!this._isConnected) { await this.connect(); } const headers = new Map(); headers["Content-Type"] = "application/json"; const options = { url: "script/sharptree.autoscript.admin/configdbrequired", method: MaximoClient.Method.GET, headers: { common: headers } }; // @ts-ignore const response = await this.client.request(options); if (typeof response.data.status !== "undefined" && response.data.status === "ok") { if (typeof response.data.configDBRequired !== "undefined") { return response.data.configDBRequired; } else { return false; } } else { throw new MaximoError("Error checking if database configuration is required: " + response.data.error); } } async dbConfigRequiresAdminMode() { if (!this._isConnected) { await this.connect(); } const headers = new Map(); headers["Content-Type"] = "application/json"; const options = { url: "script/sharptree.autoscript.admin/configdbrequiresadminmode", method: MaximoClient.Method.GET, headers: { common: headers } }; // @ts-ignore const response = await this.client.request(options); if (typeof response.data.status !== "undefined" && response.data.status === "ok") { if (typeof response.data.configDBRequiresAdminMode !== "undefined") { return response.data.configDBRequiresAdminMode; } else { return false; } } else { throw new MaximoError("Error checking if database configuration requires admin mode: " + response.data.error); } } async setAdminModeOn() { if (!this._isConnected) { await this.connect(); } const headers = new Map(); headers["Content-Type"] = "application/json"; const options = { url: "script/sharptree.autoscript.admin/adminmodeon", method: MaximoClient.Method.POST, headers: { common: headers } }; // @ts-ignore const response = await this.client.request(options); if (typeof response.data.status !== "undefined" && response.data.status === "ok") { if (typeof response.data.configDBRequiresAdminMode !== "undefined") { return response.data.configDBRequiresAdminMode; } else { return false; } } else { throw new MaximoError("Error setting Admin Mode On: " + response.data.error); } } async setAdminModeOff() { if (!this._isConnected) { await this.connect(); } const headers = new Map(); headers["Content-Type"] = "application/json"; const options = { url: "script/sharptree.autoscript.admin/adminmodeoff", method: MaximoClient.Method.POST, headers: { common: headers } }; // @ts-ignore const response = await this.client.request(options); if (typeof response.data.status !== "undefined" && response.data.status === "ok") { if (typeof response.data.configDBRequiresAdminMode !== "undefined") { return response.data.configDBRequiresAdminMode; } else { return false; } } else { throw new MaximoError("Error setting Admin Mode Off: " + response.data.error); } } async isAdminModeOn() { if (!this._isConnected) { await this.connect(); } const headers = new Map(); headers["Content-Type"] = "application/json"; const options = { url: "script/sharptree.autoscript.admin/adminmodeon", method: MaximoClient.Method.GET, headers: { common: headers } }; // @ts-ignore const response = await this.client.request(options); if (typeof response.data.status !== "undefined" && response.data.status === "ok") { if (typeof response.data.adminModeOn !== "undefined") { return response.data.adminModeOn; } else { return false; } } else { throw new MaximoError("Error checking if admin mode is on: " + response.data.error); } } async dbConfigInProgress() { if (!this._isConnected) { await this.connect(); } const headers = new Map(); headers["Content-Type"] = "application/json"; const options = { url: "script/sharptree.autoscript.admin/configuring", method: MaximoClient.Method.GET, headers: { common: headers } }; // @ts-ignore const response = await this.client.request(options); if (typeof response.data.status !== "undefined" && response.data.status === "ok") { if (typeof response.data.configuring !== "undefined") { return response.data.configuring; } else { return false; } } else { throw new MaximoError("Error checking database configuration is in progress: " + response.data.error); } } async dbConfigMessages() { if (!this._isConnected) { await this.connect(); } const headers = new Map(); headers["Content-Type"] = "application/json"; const options = { url: "script/sharptree.autoscript.admin/configmessages", method: MaximoClient.Method.GET, headers: { common: headers } }; // @ts-ignore const response = await this.client.request(options); if (typeof response.data.status !== "undefined" && response.data.status === "ok") { return response.data.messages; } else { throw new MaximoError("Error checking database configuration is in progress: " + response.data.error); } } async applyDBConfig() { if (!this._isConnected) { await this.connect(); } const headers = new Map(); headers["Content-Type"] = "application/json"; const options = { url: "script/sharptree.autoscript.admin/applyconfigdb", method: MaximoClient.Method.POST, headers: { common: headers } }; // @ts-ignore const response = await this.client.request(options); if (typeof response.data.status !== "undefined" && response.data.status === "ok") { if (typeof response.data.configDBRequiresAdminMode !== "undefined") { return response.data.configDBRequiresAdminMode; } else { return false; } } else { throw new MaximoError("Error applying database configuration: " + response.data.error); } } async postConfig(json) { if (!this._isConnected) { await this.connect(); } const configOptions = { url: "script/sharptree.autoscript.deploy/config", method: MaximoClient.Method.POST, headers: { "Content-Type": "text/plain", Accept: "application/json" }, data: json }; // @ts-ignore await this.client.request(configOptions); } async postScript(script, fileName, deployScript) { if (!this._isConnected) { await this.connect(); } let isPython = fileName.endsWith(".py") || fileName.endsWith(".jy"); if (deployScript) { const deployOptions = { url: "script/sharptree.autoscript.deploy" + (isPython ? "/python" : ""), method: MaximoClient.Method.POST, headers: { "Content-Type": "text/plain", Accept: "application/json" }, data: deployScript }; // @ts-ignore await this.client.request(deployOptions); } const options = { url: "script/sharptree.autoscript.deploy" + (isPython ? "/python" : ""), method: MaximoClient.Method.POST, headers: { "Content-Type": "text/plain", Accept: "application/json" }, data: script }; const result = await this.client.request(options); if (result.data && result.data.status == "success" && typeof result.data.deployid !== "undefined") { console.log(`Waiting for ${fileName} post deploy configuration to complete.`); const checkOptions = { url: "script/sharptree.autoscript.deploy", method: MaximoClient.Method.GET, headers: { "Content-Type": "text/plain", Accept: "application/json" }, params: { "deployId": result.data.deployid }, data: script }; // @ts-ignore var checkResult = await this.client.request(checkOptions); var checkCount = 0; var progressMessages = []; while (checkResult.data.deploying) { checkCount++; await new Promise((resolve) => setTimeout(resolve, 5000)); // @ts-ignore checkResult = await this.client.request(checkOptions); if (checkCount * 5000 > this.config.configurationTimeout) { var minutes = this.config.configurationTimeout / 60000; throw new MaximoError( `The script deployed, but the configuration script exceed the time out of ${minutes} minute${ minutes > 1 ? "s" : "" }. The configuration script may continue to execute in the background.` ); }else{ if(typeof checkResult.data.progress !== 'undefined' && Array.isArray(checkResult.data.progress) && checkResult.data.progress.length > 0) {`` checkResult.data.progress.filter( progress => !progressMessages.includes(progress.message) ).forEach(progress => { progressMessages.push(progress.message); console.log(progress.message); }); } } } checkResult.data.scriptName = result.data.scriptName; return checkResult.data; }else{ return result.data; } } async postScreen(screen) { if (!this._isConnected) { await this.connect(); } const options = { url: "script/sharptree.autoscript.screens", params: { designmode: false }, method: MaximoClient.Method.POST, headers: { "Content-Type": "text/plain", Accept: "application/json" }, data: screen }; const result = await this.client.request(options); return result.data; } async postReport(report) { if (!this._isConnected) { await this.connect(); } const options = { url: "script/sharptree.autoscript.report", method: MaximoClient.Method.POST, headers: { "Content-Type": "text/plain", Accept: "application/json" }, data: report }; const result = await this.client.request(options); return result.data; } async postForm(form) { if (!this._isConnected) { await this.connect(); } const options = { url: "script/sharptree.autoscript.form", method: MaximoClient.Method.POST, headers: { "Content-Type": "text/plain", Accept: "application/json" }, data: JSON.stringify(form, null, 4) }; const result = await this.client.request(options); return result.data; } async installed() { if (!this._isConnected) { await this.connect(); } const headers = new Map(); headers["Content-Type"] = "application/json"; const options = { url: `os/${this.scriptEndpoint}?oslc.select=autoscript&oslc.where=autoscript="SHARPTREE.AUTOSCRIPT.DEPLOY"`, method: MaximoClient.Method.GET, headers: { common: headers } }; // @ts-ignore try { const response = await this.client.request(options); if (!response || response.headers["content-type"] !== "application/json") { throw new MaximoError("Received an unexpected response from the server. Content-Type header is not application/json."); } return response.data.member.length !== 0; } catch (e) { if (e.reasonCode && e.reasonCode === "BMXAA9301E") { this.scriptEndpoint = "mxapiautoscript"; return await this.installed(); } } } async upgradeRequired() { if (!this._isConnected) { await this.connect(); } const headers = new Map(); headers["Content-Type"] = "application/json"; const options = { url: "script/SHARPTREE.AUTOSCRIPT.DEPLOY/version", method: MaximoClient.Method.GET, headers: { common: headers } }; // @ts-ignore const response = await this.client.request(options); if (typeof response.data.version !== "undefined") { return semver.lt(response.data.version, this.requiredScriptVersion); } else if (typeof response.data.status !== "undefined" && response.data.status === "error") { throw new MaximoError(response.data.message); } else { return true; } } async javaVersion() { if (!this._isConnected) { await this.connect(); } const headers = new Map(); headers["Content-Type"] = "application/json"; var options = { url: "", method: MaximoClient.Method.GET, headers: { common: headers } }; // @ts-ignore var response = await this.client.request(options); if (response.data.thisserver) { options = { url: "members/thisserver/jvm", method: MaximoClient.Method.GET, headers: { common: headers } }; // @ts-ignore response = await this.client.request(options).catch((error) => { // if the user doesn't have access to check the Java version then just skip it. if (typeof error.reasonCode !== "undefined" && error.reasonCode === "BMXAA9051E") { return "no-permission"; } else { throw error; } }); // @ts-ignore if (response === "no-permission") { return response; } if (typeof response.data !== "undefined") { return response.data.specVersion; } else { return "unavailable"; } } else { return "unavailable"; } } async maximoVersion() { if (!this._isConnected) { await this.connect(); } if (typeof this.maxVersion !== "undefined" && this.maxVersion !== "unknown" && this.maxVersion !== "undefined") { return this.maxVersion; } else { const headers = new Map(); headers["Content-Type"] = "application/json"; const options = { url: "", method: MaximoClient.Method.GET, headers: { common: headers } }; // @ts-ignore const response = await this.client.request(options); this.maxVersion = response.data.maxupg; return this.maxVersion; } } async deleteScriptIfExists(script) { if (!this._isConnected) { await this.connect(); } const headers = new Map(); headers["Content-Type"] = "application/json"; let options = { url: `os/${this.scriptEndpoint}?oslc.select=autoscript&oslc.where=autoscript="${script}"&lean=1`, method: MaximoClient.Method.GET, headers: { common: headers } }; const result = await this.client.request(options); if (result.data && result.data.member && result.data.member.length === 1 && result.data.member[0].href) { let href = result.data.member[0].href; let id = href.substring(href.lastIndexOf("/") + 1); if (id) { headers["x-method-override"] = "PATCH"; headers["patchtype"] = "MERGE"; if (this._csrfToken) { headers["csrftoken"] = this._csrfToken; } options = { url: `os/${this.scriptEndpoint}/` + id, method: MaximoClient.Method.POST, headers: { common: headers }, data: { "_action": "Delete" } }; } if ((await this.client.request(options)).status == "error") { return false; } else { return true; } } return false; } async installOrUpgrade(bootstrap) { if (!this._isConnected) { throw new MaximoError("Maximo client is not connected."); } if (bootstrap) { var result = await this._bootstrap(); if (result.status === "error") { return result; } await new Promise((resolve) => setTimeout(resolve, 500)); } // eslint-disable-next-line no-undef let source = fs.readFileSync(path.resolve(__dirname, "../resources/sharptree.autoscript.store.js")).toString(); await this._installOrUpdateScript("sharptree.autoscript.store", "Sharptree Automation Script Storage Script", source); // eslint-disable-next-line no-undef source = fs.readFileSync(path.resolve(__dirname, "../resources/sharptree.autoscript.extract.js")).toString(); await this._installOrUpdateScript("sharptree.autoscript.extract", "Sharptree Automation Script Extract Script", source); // eslint-disable-next-line no-undef source = fs.readFileSync(path.resolve(__dirname, "../resources/sharptree.autoscript.logging.js")).toString(); await this._installOrUpdateScript("sharptree.autoscript.logging", "Sharptree Automation Script Log Streaming", source); // initialize the logging security. result = this._initLogStreamSecurity(); if (result.status == "error") { throw new MaximoError(result.message); } // eslint-disable-next-line no-undef source = fs.readFileSync(path.resolve(__dirname, "../resources/sharptree.autoscript.deploy.js")).toString(); await this._installOrUpdateScript("sharptree.autoscript.deploy", "Sharptree Automation Script Deploy Script", source); source = fs.readFileSync(path.resolve(__dirname, "../resources/sharptree.autoscript.screens.js")).toString(); await this._installOrUpdateScript("sharptree.autoscript.screens", "Sharptree Screens Script", source); // eslint-disable-next-line no-undef source = fs.readFileSync(path.resolve(__dirname, "../resources/sharptree.autoscript.form.js")).toString(); await this._installOrUpdateScript("sharptree.autoscript.form", "Sharptree Forms Script", source); // eslint-disable-next-line no-undef source = fs.readFileSync(path.resolve(__dirname, "../resources/sharptree.autoscript.library.js")).toString(); await this._installOrUpdateScript("sharptree.autoscript.library", "Sharptree Deployment Library Script", source); // eslint-disable-next-line no-undef source = fs.readFileSync(path.resolve(__dirname, "../resources/sharptree.autoscript.admin.js")).toString(); await this._installOrUpdateScript("sharptree.autoscript.admin", "Sharptree Admin Script", source); } // @ts-ignore async startLogging(timeout) { if (typeof timeout === "undefined") { timeout = 30; } this._isLogging = true; const headers = new Map(); headers["Content-Type"] = "application/json"; let options = { url: `script/sharptree.autoscript.logging?timeout=${timeout}`, method: MaximoClient.Method.GET, responseType: "stream", headers: { common: headers } }; let lkp = undefined; try { while (this._isLogging) { // @ts-ignore if (typeof lkp !== "undefined") { options.headers["log-lkp"] = lkp; } // @ts-ignore let response = await this.client.request(options); let contentType = response.headers["content-type"]; if (contentType === "application/json") { if (typeof response.data !== "undefined") { var internalError = await new Promise((resolve, reject) => { let completeData = ""; response.data.on("data", (data) => { if (!this._isLogging) { resolve(); } else { completeData += data; } }); response.data.on("end", () => { if (completeData) { try { resolve(JSON.parse(completeData)); } catch (error) { resolve(); } } else { resolve(); } }); response.data.on("error", () => { this.stopLogging(); reject(); }); }); if (internalError) { throw new MaximoError(internalError.message); } else { throw new MaximoError("An unexpected JSON response was returned by the server."); } } else { throw new MaximoError("An unexpected JSON response was returned by the server."); } } else if (contentType === "text/event-stream") { lkp = await new Promise((resolve, reject) => { let internalLKP = undefined; response.data.on("data", (data) => { if (!this._isLogging) { resolve(); } else { if (data && data instanceof Uint8Array) { let decoder = new TextDecoder("utf-8"); let sData = decoder.decode(data); if (sData.startsWith("log-lkp=")) { internalLKP = sData.substring(8); } else if (sData.indexOf("WARNING: Cannot set status. Response already committed.") > 0) { // do nothing. } else if (sData === "") { // do nothing on a blank line } else { process.stdout.write(sData); } } } }); response.data.on("end", () => { resolve(internalLKP); }); response.data.on("error", () => { this.stopLogging(); reject(); }); }); } else { throw new Error(`Unexpected Content-Type ${contentType} was returned by the server.`); } } } catch (error) { if (error instanceof MaximoError) { throw error.message; } var internalError = await new Promise((resolve, reject) => { let completeData = ""; error.response.data.on("data", (data) => { if (!this._isLogging) { resolve(); } else { completeData += data; } }); error.response.data.on("end", () => { if (completeData) { try { resolve(JSON.parse(completeData)); } catch (error) { resolve(); } } else { resolve(); } }); error.response.data.on("error", () => { this.stopLogging(); reject(); }); }); if (internalError) { throw internalError; } else { throw error; } } } async stopLogging() { this._isLogging = false; this.disconnect(); } async getAllScriptNames() { const headers = new Map(); headers["Content-Type"] = "application/json"; let options = { url: `os/${this.scriptEndpoint}?oslc.select=autoscript&oslc.pageSize=10`, method: MaximoClient.Method.GET, headers: { common: headers } }; var scriptNames = []; let hasMorePages = true; while (hasMorePages) { // @ts-ignore let response = await this.client.request(options); if (response.data.member.length !== 0) { response.data.member.forEach((member) => { if (!member.autoscript.startsWith("SHARPTREE.AUTOSCRIPT")) { scriptNames.push(member.autoscript.toLowerCase()); } }); } hasMorePages = typeof response.data.responseInfo.nextPage !== "undefined"; if (hasMorePages) { let pageNumber = response.data.responseInfo.pagenum + 1; options.url = `os/${this.scriptEndpoint}?oslc.select=autoscript&oslc.pageSize=10&pageno=${pageNumber}`; } } return scriptNames; } async getAllScreenNames() { const headers = new Map(); headers["Content-Type"] = "application/json"; let options = { url: "script/sharptree.autoscript.screens", method: MaximoClient.Method.GET, headers: { common: headers } }; // @ts-ignore let response = await this.client.request(options); if (response.data.status === "success") { return response.data.screenNames; } else { throw new Error(response.data.message); } } async getAllForms() { const headers = new Map(); headers["Content-Type"] = "application/json"; let options = { url: "script/sharptree.autoscript.form", method: MaximoClient.Method.GET, headers: { common: headers } }; // @ts-ignore let response = await this.client.request(options); if (response.data.status === "success") { return response.data.inspectionForms; } else { throw new Error(response.data.message); } } async getAllReports() { const headers = new Map(); headers["Content-Type"] = "application/json"; let options = { url: "script/sharptree.autoscript.report", method: MaximoClient.Method.GET, headers: { common: headers } }; // @ts-ignore let response = await this.client.request(options); if (response.data.status === "success") { return response.data.reports; } else { throw new Error(response.data.message); } } async getReport(reportId) { const headers = new Map(); headers["Content-Type"] = "application/json"; let options = { url: `script/sharptree.autoscript.report/${reportId}`, method: MaximoClient.Method.GET, headers: { common: headers } }; // @ts-ignore let response = await this.client.request(options); if (response.data.status === "success") { return response.data.report; } else { throw new Error(response.data.message); } } // @ts-ignore // eslint-disable-next-line no-unused-vars async getPageData(url) {} // @ts-ignore // eslint-disable-next-line no-unused-vars async extractScript(script) {} async getScript(scriptName) { const headers = new Map(); headers["Content-Type"] = "application/json"; let options = { url: `script/sharptree.autoscript.extract/${scriptName}`, method: MaximoClient.Method.GET, headers: { common: headers } }; // @ts-ignore let response = await this.client.request(options); if (response.data.status === "success") { return response.data; } else { throw new Error(response.data.message); } } async getScreen(screenName) { const headers = new Map(); headers["Content-Type"] = "application/json"; let options = { url: `script/sharptree.autoscript.screens/${screenName}`, method: MaximoClient.Method.GET, headers: { common: headers } }; // @ts-ignore let response = await this.client.request(options); if (response.data.status === "success") { return response.data; } else { throw new Error(response.data.message); } } async getForm(formId) { const headers = new Map(); headers["Content-Type"] = "application/json"; let options = { url: `script/sharptree.autoscript.form/${formId}`, method: MaximoClient.Method.GET, headers: { common: headers } }; // @ts-ignore let response = await this.client.request(options); if (response.data.status === "success") { return response.data.form; } else { throw new Error(response.data.message); } } async _initLogStreamSecurity() { let headers = new Map(); headers["Content-Type"] = "application/json"; let options = { url: "script/sharptree.autoscript.logging?initialize=true", method: MaximoClient.Method.GET, headers: { common: headers } }; // @ts-ignore let response = await this.client.request(options); return response.data.status == true; } async _installOrUpdateScript(script, description, source) { let scriptURI = await this._getScriptURI(script); let headers = new Map(); headers["Content-Type"] = "application/json"; // update if a script uri was found. if (scriptURI) { let deployScript = { "description": description, "status": "Active", "version": this.currentScriptVersion, "source": source }; headers["x-method-override"] = "PATCH"; if (this._csrfToken) { headers["csrftoken"] = this._csrfToken; } let options = { url: scriptURI, method: MaximoClient.Method.POST, headers: { common: headers }, data: deployScript }; await this.client.request(options); } else { const deployScript = { "autoscript": script, "description": description, "status": "Active", "version": this.currentScriptVersion, "scriptlanguage": "nashorn", "source": source }; const options = { url: `os/${this.scriptEndpoint}`, method: MaximoClient.Method.POST, headers: { common: headers }, data: deployScript }; await this.client.request(options); } } async _getScriptURI(script) { const headers = new Map(); headers["Content-Type"] = "application/json"; let options = { url: `os/${this.scriptEndpoint}?oslc.select=autoscript&oslc.where=autoscript="${script}"`, method: MaximoClient.Method.GET, headers: { common: headers } }; // @ts-ignore let response = await this.client.request(options); if (response.data.member.length !== 0) { return response.data.member[0].href; } else { return null; } } async _bootstrap() { if (!this._isConnected) { throw new MaximoError("Maximo client is not connected."); } let refUri; try { const headers = new Map(); headers["Content-Type"] = "application/json"; // eslint-disable-next-line no-undef let source = fs.readFileSync(path.resolve(__dirname, "../resources/sharptree.autoscript.install.js")).toString(); let options = { url: `os/${this.scriptEndpoint}?oslc.select=autoscript&oslc.where=autoscript="SHARPTREE.AUTOSCRIPT.INSTALL"`, method: MaximoClient.Method.GET, headers: { common: headers } }; // @ts-ignore let response = await this.client.request(options); let href; if (response.data.member.length === 1) { href = response.data.member[0].href; } if (href) { let deployScript = { "description": "Sharptree AutoScript Deploy Bootstrap", "status": "Active", "version": this.currentScriptVersion, "scriptlanguage": "nashorn", "source": source }; headers["x-method-override"] = "PATCH"; if (this._csrfToken) { headers["csrftoken"] = this._csrfToken; } options = { url: href, method: MaximoClient.Method.PO