From 92504b0c168c342bf588225232278a4613f4c471 Mon Sep 17 00:00:00 2001 From: Krishna Acondy Date: Mon, 13 Jul 2020 18:38:30 +0100 Subject: [PATCH 01/20] feat(jes-api): implement job execution via API to JES --- sasjs-tests/public/config.json | 2 +- src/SASViyaApiClient.ts | 132 +++++---- src/SASjs.ts | 504 ++++++++++++++++++--------------- src/types/Job.ts | 1 + 4 files changed, 356 insertions(+), 283 deletions(-) diff --git a/sasjs-tests/public/config.json b/sasjs-tests/public/config.json index 33c1200..1bd77e0 100644 --- a/sasjs-tests/public/config.json +++ b/sasjs-tests/public/config.json @@ -6,6 +6,6 @@ "appLoc": "/Public/app", "serverType": "SASVIYA", "debug": false, - "contextName": null + "contextName": "SAS Job Execution compute context" } } diff --git a/src/SASViyaApiClient.ts b/src/SASViyaApiClient.ts index 535fb04..c10b389 100644 --- a/src/SASViyaApiClient.ts +++ b/src/SASViyaApiClient.ts @@ -6,7 +6,7 @@ import { } from "./utils"; import * as NodeFormData from "form-data"; import * as path from "path"; -import { Job, Session, Context, Folder } from "./types"; +import { Job, Session, Context, Folder, CsrfToken } from "./types"; /** * A client for interfacing with the SAS Viya REST API @@ -32,7 +32,7 @@ export class SASViyaApiClient { if (this.rootFolderMap.size) { return this.rootFolderMap; } - + this.populateRootFolderMap(); return this.rootFolderMap; } @@ -276,12 +276,12 @@ export class SASViyaApiClient { } /** - * Creates a folder in the specified location. Either parentFolderPath or - * parentFolderUri must be provided. + * Creates a folder in the specified location. Either parentFolderPath or + * parentFolderUri must be provided. * @param folderName - the name of the new folder. - * @param parentFolderPath - the full path to the parent folder. If not + * @param parentFolderPath - the full path to the parent folder. If not * provided, the parentFolderUri must be provided. - * @param parentFolderUri - the URI (eg /folders/folders/UUID) of the parent + * @param parentFolderUri - the URI (eg /folders/folders/UUID) of the parent * folder. If not provided, the parentFolderPath must be provided. */ public async createFolder( @@ -296,17 +296,27 @@ export class SASViyaApiClient { if (!parentFolderUri && parentFolderPath) { parentFolderUri = await this.getFolderUri(parentFolderPath, accessToken); - if (!parentFolderUri){ + if (!parentFolderUri) { console.log(`Parent folder is not present: ${parentFolderPath}`); - const newParentFolderPath = parentFolderPath.substring(0, parentFolderPath.lastIndexOf("/")); + const newParentFolderPath = parentFolderPath.substring( + 0, + parentFolderPath.lastIndexOf("/") + ); const newFolderName = `${parentFolderPath.split("/").pop()}`; - if (newParentFolderPath === ""){ + if (newParentFolderPath === "") { throw new Error("Root Folder should have been present on server"); } - console.log(`Creating Parent Folder:\n${newFolderName} in ${newParentFolderPath}`) - const parentFolder = await this.createFolder(newFolderName, newParentFolderPath, undefined, accessToken) - console.log(`Parent Folder "${newFolderName}" successfully created.`) + console.log( + `Creating Parent Folder:\n${newFolderName} in ${newParentFolderPath}` + ); + const parentFolder = await this.createFolder( + newFolderName, + newParentFolderPath, + undefined, + accessToken + ); + console.log(`Parent Folder "${newFolderName}" successfully created.`); parentFolderUri = `/folders/folders/${parentFolder.id}`; } } @@ -350,7 +360,9 @@ export class SASViyaApiClient { accessToken?: string ) { if (!parentFolderPath && !parentFolderUri) { - throw new Error('Either parentFolderPath or parentFolderUri must be provided'); + throw new Error( + "Either parentFolderPath or parentFolderUri must be provided" + ); } if (!parentFolderUri && parentFolderPath) { @@ -365,12 +377,12 @@ export class SASViyaApiClient { }, body: JSON.stringify({ name: jobName, - parameters:[ + parameters: [ { - "name":"_addjesbeginendmacros", - "type":"CHARACTER", - "defaultValue":"false" - } + name: "_addjesbeginendmacros", + type: "CHARACTER", + defaultValue: "false", + }, ], type: "Compute", code, @@ -578,6 +590,7 @@ export class SASViyaApiClient { let files: any[] = []; if (data && Object.keys(data).length) { files = await this.uploadTables(data, accessToken); + console.log("Uploaded table files: ", files); } const jobName = path.basename(sasJob); const jobFolder = sasJob.replace(`/${jobName}`, ""); @@ -612,15 +625,15 @@ export class SASViyaApiClient { }; if (debug) { - jobArguments["_omittextlog"] = "false"; - jobArguments["_omitsessionresults"] = "false"; - jobArguments["_debug"] = 131; + jobArguments["_OMITTEXTLOG"] = "false"; + jobArguments["_OMITSESSIONRESULTS"] = "false"; + jobArguments["_DEBUG"] = 131; } files.forEach((fileInfo, index) => { jobArguments[ `_webin_fileuri${index + 1}` - ] = `/files/files/${fileInfo.id}`; + ] = `/files/files/${fileInfo.file.id}`; jobArguments[`_webin_name${index + 1}`] = fileInfo.tableName; }); @@ -643,16 +656,29 @@ export class SASViyaApiClient { `${this.serverUrl}/jobExecution/jobs/${postedJob.id}`, { headers } ); - const resultLink = currentJob.results["_webout.json"]; - if (resultLink) { - const result = await this.request( - `${this.serverUrl}${resultLink}/content`, - { headers } - ); - return result; - } - return postedJob; + let result, log; + if (jobStatus === "failed") { + return Promise.reject(currentJob.error); + } + const resultLink = currentJob.results["_webout.json"]; + const logLink = currentJob.links.find((l) => l.rel === "log"); + if (resultLink) { + result = await this.request( + `${this.serverUrl}${resultLink}/content`, + { headers }, + "text" + ); + } + if (debug && logLink) { + log = await this.request( + `${this.serverUrl}${logLink.href}/content`, + { + headers, + } + ).then((res: any) => res.items.map((i: any) => i.line).join("\n")); + } + return { result, log }; } else { throw new Error( `The job ${sasJob} was not found at the location ${this.rootFolderName}` @@ -673,7 +699,7 @@ export class SASViyaApiClient { `${this.serverUrl}${url}`, requestInfo ); - if (!folder){ + if (!folder) { throw new Error("Cannot populate RootFolderMap unless rootFolder exists"); } const members = await this.request<{ items: any[] }>( @@ -734,6 +760,8 @@ export class SASViyaApiClient { accessToken?: string, silent = false ) { + const MAX_POLL_COUNT = 1000; + const POLL_INTERVAL = 300; let postedJobState = ""; let pollCount = 0; const headers: any = { @@ -767,7 +795,7 @@ export class SASViyaApiClient { console.log(`Current state: ${postedJobState}\n`); } pollCount++; - if (pollCount >= 100) { + if (pollCount >= MAX_POLL_COUNT) { resolve(postedJobState); } } @@ -775,7 +803,7 @@ export class SASViyaApiClient { clearInterval(interval); resolve(postedJobState); } - }, 100); + }, POLL_INTERVAL); }); } @@ -814,21 +842,24 @@ export class SASViyaApiClient { private async getFolderUri(folderPath: string, accessToken?: string) { const url = "/folders/folders/@item?path=" + folderPath; - const requestInfo: any = { - method: "GET", - }; - if (accessToken) { - requestInfo.headers = { Authorization: `Bearer ${accessToken}` }; - } - const folder = await this.request( - `${this.serverUrl}${url}`, - requestInfo - ); - if (!folder) - return undefined; - return `/folders/folders/${folder.id}`; + const requestInfo: any = { + method: "GET", + }; + if (accessToken) { + requestInfo.headers = { Authorization: `Bearer ${accessToken}` }; + } + const folder = await this.request( + `${this.serverUrl}${url}`, + requestInfo + ); + if (!folder) return undefined; + return `/folders/folders/${folder.id}`; } + setCsrfToken = (csrfToken: CsrfToken) => { + this.csrfToken = csrfToken; + }; + private async request( url: string, options: RequestInit, @@ -840,11 +871,6 @@ export class SASViyaApiClient { [this.csrfToken.headerName]: this.csrfToken.value, }; } - return await makeRequest( - url, - options, - (csrfToken) => (this.csrfToken = csrfToken), - contentType - ); + return await makeRequest(url, options, this.setCsrfToken, contentType); } } diff --git a/src/SASjs.ts b/src/SASjs.ts index ca1318b..707ff05 100644 --- a/src/SASjs.ts +++ b/src/SASjs.ts @@ -386,257 +386,244 @@ export default class SASjs { loginRequiredCallback?: any, accessToken?: string ) { - const sasjsWaitingRequest: SASjsWaitingRequest = { - requestPromise: { - promise: null, - resolve: null, - reject: null, - }, - SASjob: sasJob, - data, - params, - }; + if ( + this.sasjsConfig.serverType === ServerType.SASViya && + this.sasjsConfig.contextName + ) { + return await this.executeViaJesApi( + sasJob, + data, + params, + loginRequiredCallback, + accessToken + ); + } else { + const sasjsWaitingRequest: SASjsWaitingRequest = { + requestPromise: { + promise: null, + resolve: null, + reject: null, + }, + SASjob: sasJob, + data, + params, + }; + const program = this.sasjsConfig.appLoc + ? this.sasjsConfig.appLoc.replace(/\/?$/, "/") + + sasJob.replace(/^\//, "") + : sasJob; + const jobUri = + this.sasjsConfig.serverType === "SASVIYA" + ? await this.getJobUri(sasJob) + : ""; + const apiUrl = `${this.sasjsConfig.serverUrl}${this.jobsPath}/?${ + jobUri.length > 0 + ? "__program=" + program + "&_job=" + jobUri + : "_program=" + program + }`; - // if ( - // this.sasjsConfig.serverType === ServerType.SASViya && - // this.sasjsConfig.contextName - // ) { - // sasjsWaitingRequest.requestPromise.promise = new Promise( - // async (resolve, reject) => { - // const session = await this.checkSession(); + const inputParams = params ? params : {}; + const requestParams = { + ...inputParams, + ...this.getRequestParams(), + }; - // if (!session.isLoggedIn) { - // if (loginRequiredCallback) loginRequiredCallback(true); - // logInRequired = true; - // sasjsWaitingRequest.requestPromise.resolve = resolve; - // sasjsWaitingRequest.requestPromise.reject = reject; - // this.sasjsWaitingRequests.push(sasjsWaitingRequest); - // } else { - // resolve( - // await this.sasViyaApiClient?.executeJob( - // sasJob, - // this.sasjsConfig.contextName, - // this.sasjsConfig.debug, - // data, - // accessToken - // ) - // ); - // } - // } - // ); - // return sasjsWaitingRequest.requestPromise.promise; - // } else { - const program = this.sasjsConfig.appLoc - ? this.sasjsConfig.appLoc.replace(/\/?$/, "/") + sasJob.replace(/^\//, "") - : sasJob; - const jobUri = - this.sasjsConfig.serverType === "SASVIYA" - ? await this.getJobUri(sasJob) - : ""; - const apiUrl = `${this.sasjsConfig.serverUrl}${this.jobsPath}/?${ - jobUri.length > 0 - ? "__program=" + program + "&_job=" + jobUri - : "_program=" + program - }`; + const formData = new FormData(); - const inputParams = params ? params : {}; - const requestParams = { - ...inputParams, - ...this.getRequestParams(), - }; + let isError = false; + let errorMsg = ""; - const formData = new FormData(); + if (data) { + console.log("Input data", data); + const stringifiedData = JSON.stringify(data); + if ( + this.sasjsConfig.serverType === ServerType.SAS9 || + stringifiedData.length > 500000 || + stringifiedData.includes(";") + ) { + // file upload approach + for (const tableName in data) { + console.log("TableName: ", tableName); + if (isError) { + return; + } + const name = tableName; + const csv = convertToCSV(data[tableName]); + console.log("Converted CSV", csv); + if (csv === "ERROR: LARGE STRING LENGTH") { + console.log("String too long"); + isError = true; + errorMsg = + "The max length of a string value in SASjs is 32765 characters."; + } - let isError = false; - let errorMsg = ""; - - if (data) { - console.log("Input data", data); - const stringifiedData = JSON.stringify(data); - if ( - this.sasjsConfig.serverType === ServerType.SAS9 || - stringifiedData.length > 500000 || - stringifiedData.includes(";") - ) { - // file upload approach - for (const tableName in data) { - console.log("TableName: ", tableName); - if (isError) { - return; - } - const name = tableName; - const csv = convertToCSV(data[tableName]); - console.log("Converted CSV", csv); - if (csv === "ERROR: LARGE STRING LENGTH") { - console.log("String too long"); - isError = true; - errorMsg = - "The max length of a string value in SASjs is 32765 characters."; - } - - const file = new Blob([csv], { type: "application/csv" }); - console.log("File", file); - - formData.append(name, file, `${name}.csv`); - } - } else { - // param based approach - const sasjsTables = []; - let tableCounter = 0; - for (const tableName in data) { - if (isError) { - return; - } - tableCounter++; - sasjsTables.push(tableName); - const csv = convertToCSV(data[tableName]); - if (csv === "ERROR: LARGE STRING LENGTH") { - isError = true; - errorMsg = - "The max length of a string value in SASjs is 32765 characters."; - } - // if csv has length more then 16k, send in chunks - if (csv.length > 16000) { - const csvChunks = splitChunks(csv); - // append chunks to form data with same key - csvChunks.map((chunk) => { - formData.append(`sasjs${tableCounter}data`, chunk); + const file = new Blob([csv], { + type: "application/csv", }); - } else { - requestParams[`sasjs${tableCounter}data`] = csv; + console.log("File", file); + + formData.append(name, file, `${name}.csv`); } + } else { + // param based approach + const sasjsTables = []; + let tableCounter = 0; + for (const tableName in data) { + if (isError) { + return; + } + tableCounter++; + sasjsTables.push(tableName); + const csv = convertToCSV(data[tableName]); + if (csv === "ERROR: LARGE STRING LENGTH") { + isError = true; + errorMsg = + "The max length of a string value in SASjs is 32765 characters."; + } + // if csv has length more then 16k, send in chunks + if (csv.length > 16000) { + const csvChunks = splitChunks(csv); + // append chunks to form data with same key + csvChunks.map((chunk) => { + formData.append(`sasjs${tableCounter}data`, chunk); + }); + } else { + requestParams[`sasjs${tableCounter}data`] = csv; + } + } + requestParams["sasjs_tables"] = sasjsTables.join(" "); } - requestParams["sasjs_tables"] = sasjsTables.join(" "); } - } - for (const key in requestParams) { - if (requestParams.hasOwnProperty(key)) { - formData.append(key, requestParams[key]); + for (const key in requestParams) { + if (requestParams.hasOwnProperty(key)) { + formData.append(key, requestParams[key]); + } } - } - console.log("Form data", formData); + console.log("Form data", formData); - let isRedirected = false; + let isRedirected = false; - sasjsWaitingRequest.requestPromise.promise = new Promise( - (resolve, reject) => { - if (isError) { - reject({ MESSAGE: errorMsg }); - } - const headers: any = {}; - if (this._csrfHeader && this._csrf) { - headers[this._csrfHeader] = this._csrf; - } - fetch(apiUrl, { - method: "POST", - body: formData, - referrerPolicy: "same-origin", - headers, - }) - .then(async (response) => { - if (!response.ok) { - if (response.status === 403) { - const tokenHeader = response.headers.get("X-CSRF-HEADER"); + sasjsWaitingRequest.requestPromise.promise = new Promise( + (resolve, reject) => { + if (isError) { + reject({ MESSAGE: errorMsg }); + } + const headers: any = {}; + if (this._csrfHeader && this._csrf) { + headers[this._csrfHeader] = this._csrf; + } + fetch(apiUrl, { + method: "POST", + body: formData, + referrerPolicy: "same-origin", + headers, + }) + .then(async (response) => { + if (!response.ok) { + if (response.status === 403) { + const tokenHeader = response.headers.get("X-CSRF-HEADER"); - if (tokenHeader) { - const token = response.headers.get(tokenHeader); - this._csrfHeader = tokenHeader; - this._csrf = token; + if (tokenHeader) { + const token = response.headers.get(tokenHeader); + this._csrfHeader = tokenHeader; + this._csrf = token; + } } } - } - if ( - response.redirected && - this.sasjsConfig.serverType === ServerType.SAS9 - ) { - isRedirected = true; - } + if ( + response.redirected && + this.sasjsConfig.serverType === ServerType.SAS9 + ) { + isRedirected = true; + } - return response.text(); - }) - .then((responseText) => { - if ( - (needsRetry(responseText) || isRedirected) && - !isLogInRequired(responseText) - ) { - if (this.retryCount < requestRetryLimit) { - this.retryCount++; - this.request(sasJob, data, params).then( - (res: any) => resolve(res), - (err: any) => reject(err) - ); + return response.text(); + }) + .then((responseText) => { + if ( + (needsRetry(responseText) || isRedirected) && + !isLogInRequired(responseText) + ) { + if (this.retryCount < requestRetryLimit) { + this.retryCount++; + this.request(sasJob, data, params).then( + (res: any) => resolve(res), + (err: any) => reject(err) + ); + } else { + this.retryCount = 0; + reject(responseText); + } } else { this.retryCount = 0; - reject(responseText); - } - } else { - this.retryCount = 0; - this.parseLogFromResponse(responseText, program); + this.parseLogFromResponse(responseText, program); - if (isLogInRequired(responseText)) { - if (loginRequiredCallback) loginRequiredCallback(true); - sasjsWaitingRequest.requestPromise.resolve = resolve; - sasjsWaitingRequest.requestPromise.reject = reject; - this.sasjsWaitingRequests.push(sasjsWaitingRequest); - } else { - if ( - this.sasjsConfig.serverType === ServerType.SAS9 && - this.sasjsConfig.debug - ) { - this.updateUsername(responseText); - const jsonResponseText = this.parseSAS9Response(responseText); - - if (jsonResponseText !== "") { - resolve(JSON.parse(jsonResponseText)); - } else { - reject({ - MESSAGE: this.parseSAS9ErrorResponse(responseText), - }); - } - } else if ( - this.sasjsConfig.serverType === ServerType.SASViya && - this.sasjsConfig.debug - ) { - try { - this.parseSASVIYADebugResponse(responseText).then( - (resText: any) => { - this.updateUsername(resText); - try { - resolve(JSON.parse(resText)); - } catch (e) { - reject({ MESSAGE: resText }); - } - }, - (err: any) => { - reject({ MESSAGE: err }); - } - ); - } catch (e) { - reject({ MESSAGE: responseText }); - } + if (isLogInRequired(responseText)) { + if (loginRequiredCallback) loginRequiredCallback(true); + sasjsWaitingRequest.requestPromise.resolve = resolve; + sasjsWaitingRequest.requestPromise.reject = reject; + this.sasjsWaitingRequests.push(sasjsWaitingRequest); } else { - this.updateUsername(responseText); - try { - const parsedJson = JSON.parse(responseText); - resolve(parsedJson); - } catch (e) { - reject({ MESSAGE: responseText }); + if ( + this.sasjsConfig.serverType === ServerType.SAS9 && + this.sasjsConfig.debug + ) { + this.updateUsername(responseText); + const jsonResponseText = this.parseSAS9Response( + responseText + ); + + if (jsonResponseText !== "") { + resolve(JSON.parse(jsonResponseText)); + } else { + reject({ + MESSAGE: this.parseSAS9ErrorResponse(responseText), + }); + } + } else if ( + this.sasjsConfig.serverType === ServerType.SASViya && + this.sasjsConfig.debug + ) { + try { + this.parseSASVIYADebugResponse(responseText).then( + (resText: any) => { + this.updateUsername(resText); + try { + resolve(JSON.parse(resText)); + } catch (e) { + reject({ MESSAGE: resText }); + } + }, + (err: any) => { + reject({ MESSAGE: err }); + } + ); + } catch (e) { + reject({ MESSAGE: responseText }); + } + } else { + this.updateUsername(responseText); + try { + const parsedJson = JSON.parse(responseText); + resolve(parsedJson); + } catch (e) { + reject({ MESSAGE: responseText }); + } } } } - } - }) - .catch((e: Error) => { - reject(e); - }); - } - ); + }) + .catch((e: Error) => { + reject(e); + }); + } + ); - return sasjsWaitingRequest.requestPromise.promise; - // } + return sasjsWaitingRequest.requestPromise.promise; + } } /** @@ -695,6 +682,59 @@ export default class SASjs { ); } + private async executeViaJesApi( + sasJob: string, + data: any, + params?: any, + loginRequiredCallback?: any, + accessToken?: string + ) { + const sasjsWaitingRequest: SASjsWaitingRequest = { + requestPromise: { + promise: null, + resolve: null, + reject: null, + }, + SASjob: sasJob, + data, + params, + }; + + sasjsWaitingRequest.requestPromise.promise = new Promise( + async (resolve, reject) => { + const session = await this.checkSession(); + + if (!session.isLoggedIn) { + if (loginRequiredCallback) loginRequiredCallback(true); + sasjsWaitingRequest.requestPromise.resolve = resolve; + sasjsWaitingRequest.requestPromise.reject = reject; + this.sasjsWaitingRequests.push(sasjsWaitingRequest); + } else { + resolve( + await this.sasViyaApiClient + ?.executeJob( + sasJob, + this.sasjsConfig.contextName, + this.sasjsConfig.debug, + data, + accessToken + ) + .then((response) => { + if (!this.sasjsConfig.debug) { + this.appendSasjsRequest(null, sasJob, null); + } else { + this.appendSasjsRequest(response, sasJob, null); + } + return JSON.parse(response.result); + }) + .catch((e) => reject({ MESSAGE: e.message })) + ); + } + } + ); + return sasjsWaitingRequest.requestPromise.promise; + } + private async resendWaitingRequests() { for (const sasjsWaitingRequest of this.sasjsWaitingRequests) { this.request( @@ -856,14 +896,20 @@ export default class SASjs { let generatedCode = ""; let sasWork = null; - if (response) { - sourceCode = parseSourceCode(response); - generatedCode = parseGeneratedCode(response); - sasWork = await this.parseSasWork(response); + if (response && response.result && response.log) { + sourceCode = parseSourceCode(response.log); + generatedCode = parseGeneratedCode(response.log); + sasWork = JSON.parse(response.result).WORK; + } else { + if (response) { + sourceCode = parseSourceCode(response); + generatedCode = parseGeneratedCode(response); + sasWork = await this.parseSasWork(response); + } } this.sasjsRequests.push({ - logFile: response, + logFile: (response && response.log) || response, serviceLink: program, timestamp: new Date(), sourceCode, diff --git a/src/types/Job.ts b/src/types/Job.ts index f6b93d9..ccd8314 100644 --- a/src/types/Job.ts +++ b/src/types/Job.ts @@ -8,4 +8,5 @@ export interface Job { createdBy: string; links: Link[]; results: JobResult; + error?: any; } From 7d84033ad426ec20358290305a7e8471ffd4ba41 Mon Sep 17 00:00:00 2001 From: Krishna Acondy Date: Thu, 16 Jul 2020 09:06:24 +0100 Subject: [PATCH 02/20] feat(compute-api): implement job execution via compute API --- sasjs-tests/public/config.json | 3 +- sasjs-tests/src/Login.tsx | 2 +- sasjs-tests/src/testSuites/Basic.ts | 1 + sasjs-tests/src/testSuites/RequestData.ts | 5 +- src/SASViyaApiClient.ts | 259 +++++++++-- src/SASjs.ts | 542 ++++++++++++---------- src/types/JobDefinition.ts | 3 + src/types/SASjsConfig.ts | 1 + src/types/Session.ts | 4 + src/utils/formatDataForRequest.ts | 33 ++ src/utils/makeRequest.ts | 11 +- 11 files changed, 584 insertions(+), 280 deletions(-) create mode 100644 src/types/JobDefinition.ts create mode 100644 src/utils/formatDataForRequest.ts diff --git a/sasjs-tests/public/config.json b/sasjs-tests/public/config.json index 1bd77e0..070b6ac 100644 --- a/sasjs-tests/public/config.json +++ b/sasjs-tests/public/config.json @@ -6,6 +6,7 @@ "appLoc": "/Public/app", "serverType": "SASVIYA", "debug": false, - "contextName": "SAS Job Execution compute context" + "contextName": "SharedCompute", + "useComputeApi": true } } diff --git a/sasjs-tests/src/Login.tsx b/sasjs-tests/src/Login.tsx index 158f908..38f05f2 100644 --- a/sasjs-tests/src/Login.tsx +++ b/sasjs-tests/src/Login.tsx @@ -11,7 +11,7 @@ const Login = (): ReactElement<{}> => { const handleSubmit = useCallback( (e) => { e.preventDefault(); - appContext.adapter.logIn(username, password).then(() => { + appContext.adapter.logIn(username, password).then((res) => { appContext.setIsLoggedIn(true); }); }, diff --git a/sasjs-tests/src/testSuites/Basic.ts b/sasjs-tests/src/testSuites/Basic.ts index 4dbf4fe..ee0be3d 100644 --- a/sasjs-tests/src/testSuites/Basic.ts +++ b/sasjs-tests/src/testSuites/Basic.ts @@ -9,6 +9,7 @@ const defaultConfig: SASjsConfig = { serverType: ServerType.SASViya, debug: true, contextName: "SAS Job Execution compute context", + useComputeApi: false, }; const customConfig = { diff --git a/sasjs-tests/src/testSuites/RequestData.ts b/sasjs-tests/src/testSuites/RequestData.ts index f31a1b2..2ed3672 100644 --- a/sasjs-tests/src/testSuites/RequestData.ts +++ b/sasjs-tests/src/testSuites/RequestData.ts @@ -74,9 +74,8 @@ export const sendArrTests = (adapter: SASjs): TestSuite => ({ description: "Should error out with long string values over 32765 characters", test: () => { - return adapter - .request("common/sendArr", getLongStringData(32767)) - .catch((e) => e); + const data = getLongStringData(32767); + return adapter.request("common/sendArr", data).catch((e) => e); }, assertion: (error: any) => { return !!error && !!error.MESSAGE; diff --git a/src/SASViyaApiClient.ts b/src/SASViyaApiClient.ts index c10b389..06b503c 100644 --- a/src/SASViyaApiClient.ts +++ b/src/SASViyaApiClient.ts @@ -7,6 +7,8 @@ import { import * as NodeFormData from "form-data"; import * as path from "path"; import { Job, Session, Context, Folder, CsrfToken } from "./types"; +import { JobDefinition } from "./types/JobDefinition"; +import { formatDataForRequest } from "./utils/formatDataForRequest"; /** * A client for interfacing with the SAS Viya REST API @@ -68,7 +70,7 @@ export class SASViyaApiClient { if (accessToken) { headers.Authorization = `Bearer ${accessToken}`; } - const contexts = await this.request<{ items: Context[] }>( + const { result: contexts } = await this.request<{ items: Context[] }>( `${this.serverUrl}/compute/contexts`, { headers } ); @@ -93,7 +95,7 @@ export class SASViyaApiClient { if (accessToken) { headers.Authorization = `Bearer ${accessToken}`; } - const contexts = await this.request<{ items: Context[] }>( + const { result: contexts } = await this.request<{ items: Context[] }>( `${this.serverUrl}/compute/contexts`, { headers } ); @@ -153,7 +155,7 @@ export class SASViyaApiClient { headers.Authorization = `Bearer ${accessToken}`; } - const contexts = await this.request<{ items: Context[] }>( + const { result: contexts } = await this.request<{ items: Context[] }>( `${this.serverUrl}/compute/contexts`, { headers } ); @@ -172,7 +174,7 @@ export class SASViyaApiClient { "Content-Type": "application/json", }, }; - const createdSession = this.request( + const { result: createdSession } = await this.request( `${this.serverUrl}/compute/contexts/${executionContext.id}/sessions`, createSessionRequest ); @@ -190,12 +192,14 @@ export class SASViyaApiClient { * @param silent - optional flag to turn of logging. */ public async executeScript( - fileName: string, + jobName: string, linesOfCode: string[], contextName: string, accessToken?: string, sessionId = "", - silent = false + silent = false, + data = null, + debug = false ) { const headers: any = { "Content-Type": "application/json", @@ -206,7 +210,7 @@ export class SASViyaApiClient { if (this.csrfToken) { headers[this.csrfToken.headerName] = this.csrfToken.value; } - const contexts = await this.request<{ items: Context[] }>( + const { result: contexts } = await this.request<{ items: Context[] }>( `${this.serverUrl}/compute/contexts`, { headers } ); @@ -225,13 +229,52 @@ export class SASViyaApiClient { method: "POST", headers, }; - const createdSession = await this.request( + const { result: createdSession, etag } = await this.request( `${this.serverUrl}/compute/contexts/${executionContext.id}/sessions`, createSessionRequest ); + await this.waitForSession(createdSession, etag); + executionSessionId = createdSession.id; } + + let jobArguments: { [key: string]: any } = { + _contextName: contextName, + _OMITJSONLISTING: true, + _OMITJSONLOG: true, + _OMITSESSIONRESULTS: true, + _OMITTEXTLISTING: true, + _OMITTEXTLOG: true, + }; + + if (debug) { + jobArguments["_OMITTEXTLOG"] = false; + jobArguments["_OMITSESSIONRESULTS"] = false; + jobArguments["_DEBUG"] = 131; + } + + const fileName = `exec-${ + jobName.includes("/") ? jobName.split("/")[1] : jobName + }`; + + let jobVariables: any = { SYS_JES_JOB_URI: "", _program: jobName }; + let files: any[] = []; + if (data) { + if (JSON.stringify(data).includes(";")) { + files = await this.uploadTables(data, accessToken); + jobVariables["_webin_file_count"] = files.length; + files.forEach((fileInfo, index) => { + jobVariables[ + `_webin_fileuri${index + 1}` + ] = `/files/files/${fileInfo.file.id}`; + jobVariables[`_webin_name${index + 1}`] = fileInfo.tableName; + }); + } else { + jobVariables = { ...jobVariables, ...formatDataForRequest(data) }; + } + } + // Execute job in session const postJobRequest = { method: "POST", @@ -240,9 +283,11 @@ export class SASViyaApiClient { name: fileName, description: "Powered by SASjs", code: linesOfCode, + variables: jobVariables, + arguments: jobArguments, }), }; - const postedJob = await this.request( + const { result: postedJob, etag } = await this.request( `${this.serverUrl}/compute/sessions/${executionSessionId}/jobs`, postJobRequest ); @@ -255,18 +300,42 @@ export class SASViyaApiClient { ); } - const jobStatus = await this.pollJobState(postedJob, accessToken, silent); - const logLink = postedJob.links.find((l: any) => l.rel === "log"); - if (logLink) { - const log = await this.request( - `${this.serverUrl}${logLink.href}?limit=100000`, + const jobStatus = await this.pollJobState( + postedJob, + etag, + accessToken, + silent + ); + const { result: currentJob } = await this.request( + `${this.serverUrl}/compute/sessions/${executionSessionId}/jobs/${postedJob.id}`, + { headers } + ); + + let jobResult, log; + if (jobStatus === "failed" || jobStatus === "error") { + return Promise.reject(currentJob.error); + } + const resultLink = `/compute/sessions/${executionSessionId}/filerefs/_webout/content`; + const logLink = currentJob.links.find((l) => l.rel === "log"); + if (resultLink) { + jobResult = await this.request( + `${this.serverUrl}${resultLink}`, + { headers }, + "text" + ); + } + + if (true && logLink) { + log = await this.request( + `${this.serverUrl}${logLink.href}/content`, { headers, } + ).then((res: any) => + res.result.items.map((i: any) => i.line).join("\n") ); - - return { jobStatus, log }; } + return { result: jobResult?.result, log }; } else { console.error( `Unable to find execution context ${contextName}.\nPlease check the contextName in the tgtDeployVars and try again.` @@ -334,7 +403,7 @@ export class SASViyaApiClient { createFolderRequest.headers.Authorization = `Bearer ${accessToken}`; } - const createFolderResponse = await this.request( + const { result: createFolderResponse } = await this.request( `${this.serverUrl}/folders/folders?parentFolderUri=${parentFolderUri}`, createFolderRequest ); @@ -556,6 +625,71 @@ export class SASViyaApiClient { return deleteResponse; } + /** + * Executes a job via the SAS Viya Compute API + * @param sasJob - the relative path to the job. + * @param contextName - the name of the context where the job is to be executed. + * @param debug - sets the _debug flag in the job arguments. + * @param data - any data to be passed in as input to the job. + * @param accessToken - an optional access token for an authorized user. + */ + public async executeComputeJob( + sasJob: string, + contextName: string, + debug: boolean, + data?: any, + accessToken?: string + ) { + if (!this.rootFolder) { + await this.populateRootFolder(accessToken); + } + + if (!this.rootFolder) { + throw new Error("Root folder was not found"); + } + if (!this.rootFolderMap.size) { + await this.populateRootFolderMap(accessToken); + } + if (!this.rootFolderMap.size) { + throw new Error( + `The job ${sasJob} was not found in ${this.rootFolderName}` + ); + } + + const headers: any = { "Content-Type": "application/json" }; + if (!!accessToken) { + headers.Authorization = `Bearer ${accessToken}`; + } + + const folderName = sasJob.split("/")[0]; + const jobName = sasJob.split("/")[1]; + const jobFolder = this.rootFolderMap.get(folderName); + const jobToExecute = jobFolder?.find((item) => item.name === jobName); + const jobDefinitionLink = jobToExecute?.links.find( + (l) => l.rel === "getResource" + ); + if (!jobDefinitionLink) { + throw new Error("Job definition URI was not found."); + } + const { result: jobDefinition } = await this.request( + `${this.serverUrl}${jobDefinitionLink.href}`, + headers + ); + const linesToExecute = jobDefinition.code + .replace(/\r\n/g, "\n") + .split("\n"); + return await this.executeScript( + sasJob, + linesToExecute, + contextName, + accessToken, + "", + false, + data, + debug + ); + } + /** * Executes a job via the SAS Viya Job Execution API * @param sasJob - the relative path to the job. @@ -590,7 +724,6 @@ export class SASViyaApiClient { let files: any[] = []; if (data && Object.keys(data).length) { files = await this.uploadTables(data, accessToken); - console.log("Uploaded table files: ", files); } const jobName = path.basename(sasJob); const jobFolder = sasJob.replace(`/${jobName}`, ""); @@ -608,7 +741,7 @@ export class SASViyaApiClient { headers.Authorization = `Bearer ${accessToken}`; } requestInfo.headers = headers; - const jobDefinition = await this.request( + const { result: jobDefinition } = await this.request( `${this.serverUrl}${jobDefinitionLink}`, requestInfo ); @@ -647,24 +780,29 @@ export class SASViyaApiClient { arguments: jobArguments, }), }; - const postedJob = await this.request( + const { result: postedJob, etag } = await this.request( `${this.serverUrl}/jobExecution/jobs?_action=wait`, postJobRequest ); - const jobStatus = await this.pollJobState(postedJob, accessToken, true); - const currentJob = await this.request( + const jobStatus = await this.pollJobState( + postedJob, + etag, + accessToken, + true + ); + const { result: currentJob } = await this.request( `${this.serverUrl}/jobExecution/jobs/${postedJob.id}`, { headers } ); - let result, log; + let jobResult, log; if (jobStatus === "failed") { return Promise.reject(currentJob.error); } const resultLink = currentJob.results["_webout.json"]; const logLink = currentJob.links.find((l) => l.rel === "log"); if (resultLink) { - result = await this.request( + jobResult = await this.request( `${this.serverUrl}${resultLink}/content`, { headers }, "text" @@ -676,9 +814,11 @@ export class SASViyaApiClient { { headers, } - ).then((res: any) => res.items.map((i: any) => i.line).join("\n")); + ).then((res: any) => + res.result.items.map((i: any) => i.line).join("\n") + ); } - return { result, log }; + return { result: jobResult?.result, log }; } else { throw new Error( `The job ${sasJob} was not found at the location ${this.rootFolderName}` @@ -695,14 +835,14 @@ export class SASViyaApiClient { if (accessToken) { requestInfo.headers = { Authorization: `Bearer ${accessToken}` }; } - const folder = await this.request( + const { result: folder } = await this.request( `${this.serverUrl}${url}`, requestInfo ); if (!folder) { throw new Error("Cannot populate RootFolderMap unless rootFolder exists"); } - const members = await this.request<{ items: any[] }>( + const { result: members } = await this.request<{ items: any[] }>( `${this.serverUrl}/folders/folders/${folder.id}/members`, requestInfo ); @@ -717,7 +857,7 @@ export class SASViyaApiClient { this.rootFolderName + "/" + member.name; - const memberDetail = await this.request( + const { result: memberDetail } = await this.request( `${this.serverUrl}${subFolderUrl}`, requestInfo ); @@ -726,7 +866,7 @@ export class SASViyaApiClient { (l: any) => l.rel === "members" ); - const memberContents = await this.request<{ items: any[] }>( + const { result: memberContents } = await this.request<{ items: any[] }>( `${this.serverUrl}${membersLink!.href}`, requestInfo ); @@ -752,26 +892,28 @@ export class SASViyaApiClient { requestInfo ).catch(() => null); - this.rootFolder = rootFolder; + this.rootFolder = rootFolder?.result || null; } private async pollJobState( postedJob: any, + etag: string | null, accessToken?: string, silent = false ) { const MAX_POLL_COUNT = 1000; - const POLL_INTERVAL = 300; + const POLL_INTERVAL = 100; let postedJobState = ""; let pollCount = 0; const headers: any = { "Content-Type": "application/json", + "If-None-Match": etag, }; if (accessToken) { headers.Authorization = `Bearer ${accessToken}`; } const stateLink = postedJob.links.find((l: any) => l.rel === "state"); - return new Promise((resolve, _) => { + return new Promise(async (resolve, _) => { const interval = setInterval(async () => { if ( postedJobState === "running" || @@ -782,8 +924,8 @@ export class SASViyaApiClient { if (!silent) { console.log("Polling job status... \n"); } - const jobState = await this.request( - `${this.serverUrl}${stateLink.href}?wait=30`, + const { result: jobState } = await this.request( + `${this.serverUrl}${stateLink.href}?_action=wait&wait=30`, { headers, }, @@ -807,6 +949,49 @@ export class SASViyaApiClient { }); } + private async waitForSession( + session: Session, + etag: string | null, + accessToken?: string, + silent = false + ) { + let sessionState = session.state; + let pollCount = 0; + const headers: any = { + "Content-Type": "application/json", + "If-None-Match": etag, + }; + if (accessToken) { + headers.Authorization = `Bearer ${accessToken}`; + } + const stateLink = session.links.find((l: any) => l.rel === "state"); + return new Promise(async (resolve, _) => { + if (sessionState === "pending") { + if (stateLink) { + if (!silent) { + console.log("Polling session status... \n"); + } + const { result: state } = await this.request( + `${this.serverUrl}${stateLink.href}?wait=30`, + { + headers, + }, + "text" + ); + + sessionState = state.trim(); + if (!silent) { + console.log(`Current state: ${sessionState}\n`); + } + pollCount++; + resolve(sessionState); + } + } else { + resolve(sessionState); + } + }); + } + private async uploadTables(data: any, accessToken?: string) { const uploadedFiles = []; const headers: any = { @@ -830,7 +1015,7 @@ export class SASViyaApiClient { headers, }; - const file = await this.request( + const { result: file } = await this.request( `${this.serverUrl}/files/files#rawUpload`, createFileRequest ); @@ -848,7 +1033,7 @@ export class SASViyaApiClient { if (accessToken) { requestInfo.headers = { Authorization: `Bearer ${accessToken}` }; } - const folder = await this.request( + const { result: folder } = await this.request( `${this.serverUrl}${url}`, requestInfo ); diff --git a/src/SASjs.ts b/src/SASjs.ts index 707ff05..2434b98 100644 --- a/src/SASjs.ts +++ b/src/SASjs.ts @@ -32,6 +32,7 @@ const defaultConfig: SASjsConfig = { serverType: ServerType.SASViya, debug: true, contextName: "SAS Job Execution compute context", + useComputeApi: false, }; const requestRetryLimit = 5; @@ -390,239 +391,30 @@ export default class SASjs { this.sasjsConfig.serverType === ServerType.SASViya && this.sasjsConfig.contextName ) { - return await this.executeViaJesApi( + if (this.sasjsConfig.useComputeApi) { + return await this.executeJobViaComputeApi( + sasJob, + data, + params, + loginRequiredCallback, + accessToken + ); + } else { + return await this.executeJobViaJesApi( + sasJob, + data, + params, + loginRequiredCallback, + accessToken + ); + } + } else { + return await this.executeJobViaJes( sasJob, data, params, - loginRequiredCallback, - accessToken + loginRequiredCallback ); - } else { - const sasjsWaitingRequest: SASjsWaitingRequest = { - requestPromise: { - promise: null, - resolve: null, - reject: null, - }, - SASjob: sasJob, - data, - params, - }; - const program = this.sasjsConfig.appLoc - ? this.sasjsConfig.appLoc.replace(/\/?$/, "/") + - sasJob.replace(/^\//, "") - : sasJob; - const jobUri = - this.sasjsConfig.serverType === "SASVIYA" - ? await this.getJobUri(sasJob) - : ""; - const apiUrl = `${this.sasjsConfig.serverUrl}${this.jobsPath}/?${ - jobUri.length > 0 - ? "__program=" + program + "&_job=" + jobUri - : "_program=" + program - }`; - - const inputParams = params ? params : {}; - const requestParams = { - ...inputParams, - ...this.getRequestParams(), - }; - - const formData = new FormData(); - - let isError = false; - let errorMsg = ""; - - if (data) { - console.log("Input data", data); - const stringifiedData = JSON.stringify(data); - if ( - this.sasjsConfig.serverType === ServerType.SAS9 || - stringifiedData.length > 500000 || - stringifiedData.includes(";") - ) { - // file upload approach - for (const tableName in data) { - console.log("TableName: ", tableName); - if (isError) { - return; - } - const name = tableName; - const csv = convertToCSV(data[tableName]); - console.log("Converted CSV", csv); - if (csv === "ERROR: LARGE STRING LENGTH") { - console.log("String too long"); - isError = true; - errorMsg = - "The max length of a string value in SASjs is 32765 characters."; - } - - const file = new Blob([csv], { - type: "application/csv", - }); - console.log("File", file); - - formData.append(name, file, `${name}.csv`); - } - } else { - // param based approach - const sasjsTables = []; - let tableCounter = 0; - for (const tableName in data) { - if (isError) { - return; - } - tableCounter++; - sasjsTables.push(tableName); - const csv = convertToCSV(data[tableName]); - if (csv === "ERROR: LARGE STRING LENGTH") { - isError = true; - errorMsg = - "The max length of a string value in SASjs is 32765 characters."; - } - // if csv has length more then 16k, send in chunks - if (csv.length > 16000) { - const csvChunks = splitChunks(csv); - // append chunks to form data with same key - csvChunks.map((chunk) => { - formData.append(`sasjs${tableCounter}data`, chunk); - }); - } else { - requestParams[`sasjs${tableCounter}data`] = csv; - } - } - requestParams["sasjs_tables"] = sasjsTables.join(" "); - } - } - - for (const key in requestParams) { - if (requestParams.hasOwnProperty(key)) { - formData.append(key, requestParams[key]); - } - } - - console.log("Form data", formData); - - let isRedirected = false; - - sasjsWaitingRequest.requestPromise.promise = new Promise( - (resolve, reject) => { - if (isError) { - reject({ MESSAGE: errorMsg }); - } - const headers: any = {}; - if (this._csrfHeader && this._csrf) { - headers[this._csrfHeader] = this._csrf; - } - fetch(apiUrl, { - method: "POST", - body: formData, - referrerPolicy: "same-origin", - headers, - }) - .then(async (response) => { - if (!response.ok) { - if (response.status === 403) { - const tokenHeader = response.headers.get("X-CSRF-HEADER"); - - if (tokenHeader) { - const token = response.headers.get(tokenHeader); - this._csrfHeader = tokenHeader; - this._csrf = token; - } - } - } - - if ( - response.redirected && - this.sasjsConfig.serverType === ServerType.SAS9 - ) { - isRedirected = true; - } - - return response.text(); - }) - .then((responseText) => { - if ( - (needsRetry(responseText) || isRedirected) && - !isLogInRequired(responseText) - ) { - if (this.retryCount < requestRetryLimit) { - this.retryCount++; - this.request(sasJob, data, params).then( - (res: any) => resolve(res), - (err: any) => reject(err) - ); - } else { - this.retryCount = 0; - reject(responseText); - } - } else { - this.retryCount = 0; - this.parseLogFromResponse(responseText, program); - - if (isLogInRequired(responseText)) { - if (loginRequiredCallback) loginRequiredCallback(true); - sasjsWaitingRequest.requestPromise.resolve = resolve; - sasjsWaitingRequest.requestPromise.reject = reject; - this.sasjsWaitingRequests.push(sasjsWaitingRequest); - } else { - if ( - this.sasjsConfig.serverType === ServerType.SAS9 && - this.sasjsConfig.debug - ) { - this.updateUsername(responseText); - const jsonResponseText = this.parseSAS9Response( - responseText - ); - - if (jsonResponseText !== "") { - resolve(JSON.parse(jsonResponseText)); - } else { - reject({ - MESSAGE: this.parseSAS9ErrorResponse(responseText), - }); - } - } else if ( - this.sasjsConfig.serverType === ServerType.SASViya && - this.sasjsConfig.debug - ) { - try { - this.parseSASVIYADebugResponse(responseText).then( - (resText: any) => { - this.updateUsername(resText); - try { - resolve(JSON.parse(resText)); - } catch (e) { - reject({ MESSAGE: resText }); - } - }, - (err: any) => { - reject({ MESSAGE: err }); - } - ); - } catch (e) { - reject({ MESSAGE: responseText }); - } - } else { - this.updateUsername(responseText); - try { - const parsedJson = JSON.parse(responseText); - resolve(parsedJson); - } catch (e) { - reject({ MESSAGE: responseText }); - } - } - } - } - }) - .catch((e: Error) => { - reject(e); - }); - } - ); - - return sasjsWaitingRequest.requestPromise.promise; } } @@ -682,7 +474,62 @@ export default class SASjs { ); } - private async executeViaJesApi( + private async executeJobViaComputeApi( + sasJob: string, + data: any, + params?: any, + loginRequiredCallback?: any, + accessToken?: string + ) { + const sasjsWaitingRequest: SASjsWaitingRequest = { + requestPromise: { + promise: null, + resolve: null, + reject: null, + }, + SASjob: sasJob, + data, + params, + }; + + sasjsWaitingRequest.requestPromise.promise = new Promise( + async (resolve, reject) => { + const session = await this.checkSession(); + + if (!session.isLoggedIn) { + if (loginRequiredCallback) loginRequiredCallback(true); + sasjsWaitingRequest.requestPromise.resolve = resolve; + sasjsWaitingRequest.requestPromise.reject = reject; + this.sasjsWaitingRequests.push(sasjsWaitingRequest); + } else { + resolve( + await this.sasViyaApiClient + ?.executeComputeJob( + sasJob, + this.sasjsConfig.contextName, + this.sasjsConfig.debug, + data, + accessToken + ) + .then((response) => { + if (!this.sasjsConfig.debug) { + this.appendSasjsRequest(null, sasJob, null); + } else { + this.appendSasjsRequest(response, sasJob, null); + } + return JSON.parse(response!.result); + }) + .catch((e) => + reject({ MESSAGE: (e && e.message) || "Job execution failed" }) + ) + ); + } + } + ); + return sasjsWaitingRequest.requestPromise.promise; + } + + private async executeJobViaJesApi( sasJob: string, data: any, params?: any, @@ -725,9 +572,11 @@ export default class SASjs { } else { this.appendSasjsRequest(response, sasJob, null); } - return JSON.parse(response.result); + return JSON.parse(response!.result); }) - .catch((e) => reject({ MESSAGE: e.message })) + .catch((e) => + reject({ MESSAGE: (e && e.message) || "Job execution failed" }) + ) ); } } @@ -735,6 +584,229 @@ export default class SASjs { return sasjsWaitingRequest.requestPromise.promise; } + private async executeJobViaJes( + sasJob: string, + data: any, + params?: any, + loginRequiredCallback?: any + ) { + const sasjsWaitingRequest: SASjsWaitingRequest = { + requestPromise: { + promise: null, + resolve: null, + reject: null, + }, + SASjob: sasJob, + data, + params, + }; + const program = this.sasjsConfig.appLoc + ? this.sasjsConfig.appLoc.replace(/\/?$/, "/") + sasJob.replace(/^\//, "") + : sasJob; + const jobUri = + this.sasjsConfig.serverType === "SASVIYA" + ? await this.getJobUri(sasJob) + : ""; + const apiUrl = `${this.sasjsConfig.serverUrl}${this.jobsPath}/?${ + jobUri.length > 0 + ? "__program=" + program + "&_job=" + jobUri + : "_program=" + program + }`; + + const inputParams = params ? params : {}; + const requestParams = { + ...inputParams, + ...this.getRequestParams(), + }; + + const formData = new FormData(); + + let isError = false; + let errorMsg = ""; + + if (data) { + const stringifiedData = JSON.stringify(data); + if ( + this.sasjsConfig.serverType === ServerType.SAS9 || + stringifiedData.length > 500000 || + stringifiedData.includes(";") + ) { + // file upload approach + for (const tableName in data) { + if (isError) { + return; + } + const name = tableName; + const csv = convertToCSV(data[tableName]); + if (csv === "ERROR: LARGE STRING LENGTH") { + isError = true; + errorMsg = + "The max length of a string value in SASjs is 32765 characters."; + } + + const file = new Blob([csv], { + type: "application/csv", + }); + + formData.append(name, file, `${name}.csv`); + } + } else { + // param based approach + const sasjsTables = []; + let tableCounter = 0; + for (const tableName in data) { + if (isError) { + return; + } + tableCounter++; + sasjsTables.push(tableName); + const csv = convertToCSV(data[tableName]); + if (csv === "ERROR: LARGE STRING LENGTH") { + isError = true; + errorMsg = + "The max length of a string value in SASjs is 32765 characters."; + } + // if csv has length more then 16k, send in chunks + if (csv.length > 16000) { + const csvChunks = splitChunks(csv); + // append chunks to form data with same key + csvChunks.map((chunk) => { + formData.append(`sasjs${tableCounter}data`, chunk); + }); + } else { + requestParams[`sasjs${tableCounter}data`] = csv; + } + } + requestParams["sasjs_tables"] = sasjsTables.join(" "); + } + } + + for (const key in requestParams) { + if (requestParams.hasOwnProperty(key)) { + formData.append(key, requestParams[key]); + } + } + + let isRedirected = false; + + sasjsWaitingRequest.requestPromise.promise = new Promise( + (resolve, reject) => { + if (isError) { + reject({ MESSAGE: errorMsg }); + } + const headers: any = {}; + if (this._csrfHeader && this._csrf) { + headers[this._csrfHeader] = this._csrf; + } + fetch(apiUrl, { + method: "POST", + body: formData, + referrerPolicy: "same-origin", + headers, + }) + .then(async (response) => { + if (!response.ok) { + if (response.status === 403) { + const tokenHeader = response.headers.get("X-CSRF-HEADER"); + + if (tokenHeader) { + const token = response.headers.get(tokenHeader); + this._csrfHeader = tokenHeader; + this._csrf = token; + } + } + } + + if ( + response.redirected && + this.sasjsConfig.serverType === ServerType.SAS9 + ) { + isRedirected = true; + } + + return response.text(); + }) + .then((responseText) => { + if ( + (needsRetry(responseText) || isRedirected) && + !isLogInRequired(responseText) + ) { + if (this.retryCount < requestRetryLimit) { + this.retryCount++; + this.request(sasJob, data, params).then( + (res: any) => resolve(res), + (err: any) => reject(err) + ); + } else { + this.retryCount = 0; + reject(responseText); + } + } else { + this.retryCount = 0; + this.parseLogFromResponse(responseText, program); + + if (isLogInRequired(responseText)) { + if (loginRequiredCallback) loginRequiredCallback(true); + sasjsWaitingRequest.requestPromise.resolve = resolve; + sasjsWaitingRequest.requestPromise.reject = reject; + this.sasjsWaitingRequests.push(sasjsWaitingRequest); + } else { + if ( + this.sasjsConfig.serverType === ServerType.SAS9 && + this.sasjsConfig.debug + ) { + this.updateUsername(responseText); + const jsonResponseText = this.parseSAS9Response(responseText); + + if (jsonResponseText !== "") { + resolve(JSON.parse(jsonResponseText)); + } else { + reject({ + MESSAGE: this.parseSAS9ErrorResponse(responseText), + }); + } + } else if ( + this.sasjsConfig.serverType === ServerType.SASViya && + this.sasjsConfig.debug + ) { + try { + this.parseSASVIYADebugResponse(responseText).then( + (resText: any) => { + this.updateUsername(resText); + try { + resolve(JSON.parse(resText)); + } catch (e) { + reject({ MESSAGE: resText }); + } + }, + (err: any) => { + reject({ MESSAGE: err }); + } + ); + } catch (e) { + reject({ MESSAGE: responseText }); + } + } else { + this.updateUsername(responseText); + try { + const parsedJson = JSON.parse(responseText); + resolve(parsedJson); + } catch (e) { + reject({ MESSAGE: responseText }); + } + } + } + } + }) + .catch((e: Error) => { + reject(e); + }); + } + ); + + return sasjsWaitingRequest.requestPromise.promise; + } + private async resendWaitingRequests() { for (const sasjsWaitingRequest of this.sasjsWaitingRequests) { this.request( @@ -930,7 +1002,7 @@ export default class SASjs { try { jsonResponse = JSON.parse(this.parseSAS9Response(response)); } catch (e) { - console.log(e); + console.error(e); } } else { await this.parseSASVIYADebugResponse(response).then( @@ -938,11 +1010,11 @@ export default class SASjs { try { jsonResponse = JSON.parse(resText); } catch (e) { - console.log(e); + console.error(e); } }, (err: any) => { - console.log(err); + console.error(err); } ); } diff --git a/src/types/JobDefinition.ts b/src/types/JobDefinition.ts new file mode 100644 index 0000000..fc8fb59 --- /dev/null +++ b/src/types/JobDefinition.ts @@ -0,0 +1,3 @@ +export interface JobDefinition { + code: string; +} diff --git a/src/types/SASjsConfig.ts b/src/types/SASjsConfig.ts index ee40745..9c434b4 100644 --- a/src/types/SASjsConfig.ts +++ b/src/types/SASjsConfig.ts @@ -27,4 +27,5 @@ export class SASjsConfig { */ debug: boolean = true; contextName: string = ""; + useComputeApi = false; } diff --git a/src/types/Session.ts b/src/types/Session.ts index 8734fdf..b05e7da 100644 --- a/src/types/Session.ts +++ b/src/types/Session.ts @@ -1,3 +1,7 @@ +import { Link } from "./Link"; + export interface Session { id: string; + state: string; + links: Link[]; } diff --git a/src/utils/formatDataForRequest.ts b/src/utils/formatDataForRequest.ts new file mode 100644 index 0000000..4f62737 --- /dev/null +++ b/src/utils/formatDataForRequest.ts @@ -0,0 +1,33 @@ +import { convertToCSV } from "./convertToCsv"; +import { splitChunks } from "./splitChunks"; + +export const formatDataForRequest = (data: any) => { + const sasjsTables = []; + let tableCounter = 0; + const result: any = {}; + + for (const tableName in data) { + tableCounter++; + sasjsTables.push(tableName); + const csv = convertToCSV(data[tableName]); + if (csv === "ERROR: LARGE STRING LENGTH") { + throw new Error( + "The max length of a string value in SASjs is 32765 characters." + ); + } + // if csv has length more then 16k, send in chunks + if (csv.length > 16000) { + const csvChunks = splitChunks(csv); + // append chunks to form data with same key + result[`sasjs${tableCounter}data0`] = csvChunks.length; + csvChunks.forEach((chunk, index) => { + result[`sasjs${tableCounter}data${index + 1}`] = chunk; + }); + } else { + result[`sasjs${tableCounter}data`] = csv; + } + } + result["sasjs_tables"] = sasjsTables.join(" "); + + return result; +}; diff --git a/src/utils/makeRequest.ts b/src/utils/makeRequest.ts index 1d28c23..8b2b411 100644 --- a/src/utils/makeRequest.ts +++ b/src/utils/makeRequest.ts @@ -5,11 +5,12 @@ export async function makeRequest( request: RequestInit, callback: (value: CsrfToken) => any, contentType: "text" | "json" = "json" -): Promise { +): Promise<{ result: T; etag: string | null }> { const responseTransform = contentType === "json" ? (res: Response) => res.json() : (res: Response) => res.text(); + let etag = null; const result = await fetch(url, request).then((response) => { if (!response.ok) { if (response.status === 403) { @@ -26,12 +27,16 @@ export async function makeRequest( ...request, headers: { ...request.headers, [tokenHeader]: token }, }; - return fetch(url, retryRequest).then(responseTransform); + return fetch(url, retryRequest).then((res) => { + etag = res.headers.get("ETag"); + return responseTransform(res); + }); } } } else { + etag = response.headers.get("ETag"); return responseTransform(response); } }); - return result; + return { result, etag }; } From 2ecd57169f89617e9f83f0df7ce001c652ada9fd Mon Sep 17 00:00:00 2001 From: Krishna Acondy Date: Thu, 16 Jul 2020 17:27:28 +0100 Subject: [PATCH 03/20] fix(context): cache contexts after first request --- src/SASViyaApiClient.ts | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/SASViyaApiClient.ts b/src/SASViyaApiClient.ts index 06b503c..7fa8f09 100644 --- a/src/SASViyaApiClient.ts +++ b/src/SASViyaApiClient.ts @@ -26,6 +26,7 @@ export class SASViyaApiClient { } private csrfToken: { headerName: string; value: string } | null = null; private rootFolder: Folder | null = null; + private contexts: Context[] = []; /** * Returns a map containing the directory structure in the currently set root folder. @@ -95,14 +96,18 @@ export class SASViyaApiClient { if (accessToken) { headers.Authorization = `Bearer ${accessToken}`; } - const { result: contexts } = await this.request<{ items: Context[] }>( - `${this.serverUrl}/compute/contexts`, - { headers } - ); - const contextsList = contexts && contexts.items ? contexts.items : []; + + if (!this.contexts.length) { + const { result: contexts } = await this.request<{ items: Context[] }>( + `${this.serverUrl}/compute/contexts`, + { headers } + ); + + this.contexts = contexts && contexts.items ? contexts.items : []; + } const executableContexts: any[] = []; - const promises = contextsList.map((context: any) => { + const promises = this.contexts.map((context: any) => { const linesOfCode = ["%put &=sysuserid;"]; return this.executeScript( `test-${context.name}`, @@ -127,10 +132,10 @@ export class SASViyaApiClient { } executableContexts.push({ - createdBy: contextsList[index].createdBy, - id: contextsList[index].id, - name: contextsList[index].name, - version: contextsList[index].version, + createdBy: this.contexts[index].createdBy, + id: this.contexts[index].id, + name: this.contexts[index].name, + version: this.contexts[index].version, attributes: { sysUserId, }, From a579f481c5b69396065ee6b49945320735ed3be8 Mon Sep 17 00:00:00 2001 From: Krishna Acondy Date: Thu, 16 Jul 2020 17:31:03 +0100 Subject: [PATCH 04/20] fix(context): cache contexts after first request --- src/SASViyaApiClient.ts | 45 ++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/SASViyaApiClient.ts b/src/SASViyaApiClient.ts index 7fa8f09..07d5ad6 100644 --- a/src/SASViyaApiClient.ts +++ b/src/SASViyaApiClient.ts @@ -97,17 +97,14 @@ export class SASViyaApiClient { headers.Authorization = `Bearer ${accessToken}`; } - if (!this.contexts.length) { - const { result: contexts } = await this.request<{ items: Context[] }>( - `${this.serverUrl}/compute/contexts`, - { headers } - ); - - this.contexts = contexts && contexts.items ? contexts.items : []; - } + const { result: contexts } = await this.request<{ items: Context[] }>( + `${this.serverUrl}/compute/contexts`, + { headers } + ); + const contextsList = contexts && contexts.items ? contexts.items : []; const executableContexts: any[] = []; - const promises = this.contexts.map((context: any) => { + const promises = contextsList.map((context: any) => { const linesOfCode = ["%put &=sysuserid;"]; return this.executeScript( `test-${context.name}`, @@ -132,10 +129,10 @@ export class SASViyaApiClient { } executableContexts.push({ - createdBy: this.contexts[index].createdBy, - id: this.contexts[index].id, - name: this.contexts[index].name, - version: this.contexts[index].version, + createdBy: contextsList[index].createdBy, + id: contextsList[index].id, + name: contextsList[index].name, + version: contextsList[index].version, attributes: { sysUserId, }, @@ -215,14 +212,20 @@ export class SASViyaApiClient { if (this.csrfToken) { headers[this.csrfToken.headerName] = this.csrfToken.value; } - const { result: contexts } = await this.request<{ items: Context[] }>( - `${this.serverUrl}/compute/contexts`, - { headers } + if (!this.contexts.length) { + const { result: contexts } = await this.request<{ items: Context[] }>( + `${this.serverUrl}/compute/contexts`, + { headers } + ); + + this.contexts = + contexts && contexts.items && contexts.items.length + ? contexts.items + : []; + } + const executionContext = this.contexts.find( + (c: any) => c.name === contextName ); - const executionContext = - contexts.items && contexts.items.length - ? contexts.items.find((c: any) => c.name === contextName) - : null; if (executionContext) { // Request new session in context or use the ID passed in @@ -345,7 +348,7 @@ export class SASViyaApiClient { console.error( `Unable to find execution context ${contextName}.\nPlease check the contextName in the tgtDeployVars and try again.` ); - console.error("Response from server: ", JSON.stringify(contexts)); + console.error("Response from server: ", JSON.stringify(this.contexts)); } } From a12244cf7871dfa9caaed7783b9fcccf852c169e Mon Sep 17 00:00:00 2001 From: Krishna Acondy Date: Fri, 17 Jul 2020 08:31:27 +0100 Subject: [PATCH 05/20] feat(session-manager): Manage a pool of sessions for job execution --- src/SASViyaApiClient.ts | 245 ++++++++++++++++++---------------------- src/SASjs.ts | 9 +- src/SessionManager.ts | 138 ++++++++++++++++++++++ 3 files changed, 252 insertions(+), 140 deletions(-) create mode 100644 src/SessionManager.ts diff --git a/src/SASViyaApiClient.ts b/src/SASViyaApiClient.ts index 07d5ad6..a56a17c 100644 --- a/src/SASViyaApiClient.ts +++ b/src/SASViyaApiClient.ts @@ -9,6 +9,7 @@ import * as path from "path"; import { Job, Session, Context, Folder, CsrfToken } from "./types"; import { JobDefinition } from "./types/JobDefinition"; import { formatDataForRequest } from "./utils/formatDataForRequest"; +import { SessionManager } from "./SessionManager"; /** * A client for interfacing with the SAS Viya REST API @@ -18,15 +19,16 @@ export class SASViyaApiClient { constructor( private serverUrl: string, private rootFolderName: string, + private contextName: string, private rootFolderMap = new Map() ) { if (!rootFolderName) { throw new Error("Root folder must be provided."); } } - private csrfToken: { headerName: string; value: string } | null = null; + private csrfToken: CsrfToken | null = null; private rootFolder: Folder | null = null; - private contexts: Context[] = []; + private sessionManager = new SessionManager(this.serverUrl, this.contextName); /** * Returns a map containing the directory structure in the currently set root folder. @@ -209,147 +211,114 @@ export class SASViyaApiClient { if (accessToken) { headers.Authorization = `Bearer ${accessToken}`; } - if (this.csrfToken) { - headers[this.csrfToken.headerName] = this.csrfToken.value; - } - if (!this.contexts.length) { - const { result: contexts } = await this.request<{ items: Context[] }>( - `${this.serverUrl}/compute/contexts`, - { headers } - ); + let executionSessionId: string; + const session = await this.sessionManager.getSession(accessToken); + executionSessionId = session!.id; - this.contexts = - contexts && contexts.items && contexts.items.length - ? contexts.items - : []; + const jobArguments: { [key: string]: any } = { + _contextName: contextName, + _OMITJSONLISTING: true, + _OMITJSONLOG: true, + _OMITSESSIONRESULTS: true, + _OMITTEXTLISTING: true, + _OMITTEXTLOG: true, + }; + + if (debug) { + jobArguments["_OMITTEXTLOG"] = false; + jobArguments["_OMITSESSIONRESULTS"] = false; + jobArguments["_DEBUG"] = 131; } - const executionContext = this.contexts.find( - (c: any) => c.name === contextName + + const fileName = `exec-${ + jobName.includes("/") ? jobName.split("/")[1] : jobName + }`; + + let jobVariables: any = { + SYS_JES_JOB_URI: "", + _program: this.rootFolderName + "/" + jobName, + }; + let files: any[] = []; + if (data) { + if (JSON.stringify(data).includes(";")) { + files = await this.uploadTables(data, accessToken); + jobVariables["_webin_file_count"] = files.length; + files.forEach((fileInfo, index) => { + jobVariables[ + `_webin_fileuri${index + 1}` + ] = `/files/files/${fileInfo.file.id}`; + jobVariables[`_webin_name${index + 1}`] = fileInfo.tableName; + }); + } else { + jobVariables = { ...jobVariables, ...formatDataForRequest(data) }; + } + } + + // Execute job in session + const postJobRequest = { + method: "POST", + headers, + body: JSON.stringify({ + name: fileName, + description: "Powered by SASjs", + code: linesOfCode, + variables: jobVariables, + arguments: jobArguments, + }), + }; + const { result: postedJob, etag } = await this.request( + `${this.serverUrl}/compute/sessions/${executionSessionId}/jobs`, + postJobRequest + ); + if (!silent) { + console.log(`Job has been submitted for ${fileName}`); + console.log( + `You can monitor the job progress at ${this.serverUrl}${ + postedJob.links.find((l: any) => l.rel === "state")!.href + }` + ); + } + + const jobStatus = await this.pollJobState( + postedJob, + etag, + accessToken, + silent + ); + const { result: currentJob } = await this.request( + `${this.serverUrl}/compute/sessions/${executionSessionId}/jobs/${postedJob.id}`, + { headers } ); - if (executionContext) { - // Request new session in context or use the ID passed in - let executionSessionId: string; - if (sessionId) { - executionSessionId = sessionId; - } else { - const createSessionRequest = { - method: "POST", - headers, - }; - const { result: createdSession, etag } = await this.request( - `${this.serverUrl}/compute/contexts/${executionContext.id}/sessions`, - createSessionRequest - ); - - await this.waitForSession(createdSession, etag); - - executionSessionId = createdSession.id; - } - - let jobArguments: { [key: string]: any } = { - _contextName: contextName, - _OMITJSONLISTING: true, - _OMITJSONLOG: true, - _OMITSESSIONRESULTS: true, - _OMITTEXTLISTING: true, - _OMITTEXTLOG: true, - }; - - if (debug) { - jobArguments["_OMITTEXTLOG"] = false; - jobArguments["_OMITSESSIONRESULTS"] = false; - jobArguments["_DEBUG"] = 131; - } - - const fileName = `exec-${ - jobName.includes("/") ? jobName.split("/")[1] : jobName - }`; - - let jobVariables: any = { SYS_JES_JOB_URI: "", _program: jobName }; - let files: any[] = []; - if (data) { - if (JSON.stringify(data).includes(";")) { - files = await this.uploadTables(data, accessToken); - jobVariables["_webin_file_count"] = files.length; - files.forEach((fileInfo, index) => { - jobVariables[ - `_webin_fileuri${index + 1}` - ] = `/files/files/${fileInfo.file.id}`; - jobVariables[`_webin_name${index + 1}`] = fileInfo.tableName; - }); - } else { - jobVariables = { ...jobVariables, ...formatDataForRequest(data) }; - } - } - - // Execute job in session - const postJobRequest = { - method: "POST", - headers, - body: JSON.stringify({ - name: fileName, - description: "Powered by SASjs", - code: linesOfCode, - variables: jobVariables, - arguments: jobArguments, - }), - }; - const { result: postedJob, etag } = await this.request( - `${this.serverUrl}/compute/sessions/${executionSessionId}/jobs`, - postJobRequest - ); - if (!silent) { - console.log(`Job has been submitted for ${fileName}`); - console.log( - `You can monitor the job progress at ${this.serverUrl}${ - postedJob.links.find((l: any) => l.rel === "state")!.href - }` - ); - } - - const jobStatus = await this.pollJobState( - postedJob, - etag, - accessToken, - silent - ); - const { result: currentJob } = await this.request( - `${this.serverUrl}/compute/sessions/${executionSessionId}/jobs/${postedJob.id}`, - { headers } - ); - - let jobResult, log; - if (jobStatus === "failed" || jobStatus === "error") { - return Promise.reject(currentJob.error); - } - const resultLink = `/compute/sessions/${executionSessionId}/filerefs/_webout/content`; - const logLink = currentJob.links.find((l) => l.rel === "log"); - if (resultLink) { - jobResult = await this.request( - `${this.serverUrl}${resultLink}`, - { headers }, - "text" - ); - } - - if (true && logLink) { - log = await this.request( - `${this.serverUrl}${logLink.href}/content`, - { - headers, - } - ).then((res: any) => - res.result.items.map((i: any) => i.line).join("\n") - ); - } - return { result: jobResult?.result, log }; - } else { - console.error( - `Unable to find execution context ${contextName}.\nPlease check the contextName in the tgtDeployVars and try again.` - ); - console.error("Response from server: ", JSON.stringify(this.contexts)); + let jobResult, log; + if (jobStatus === "failed" || jobStatus === "error") { + return Promise.reject(currentJob.error); } + const resultLink = `/compute/sessions/${executionSessionId}/filerefs/_webout/content`; + const logLink = currentJob.links.find((l) => l.rel === "log"); + if (resultLink) { + jobResult = await this.request( + `${this.serverUrl}${resultLink}`, + { headers }, + "text" + ); + } + + if (true && logLink) { + log = await this.request( + `${this.serverUrl}${logLink.href}/content`, + { + headers, + } + ).then((res: any) => res.result.items.map((i: any) => i.line).join("\n")); + } + return { result: jobResult?.result, log }; + // } else { + // console.error( + // `Unable to find execution context ${contextName}.\nPlease check the contextName in the tgtDeployVars and try again.` + // ); + // console.error("Response from server: ", JSON.stringify(this.contexts)); + // } } /** diff --git a/src/SASjs.ts b/src/SASjs.ts index 2434b98..5d3d911 100644 --- a/src/SASjs.ts +++ b/src/SASjs.ts @@ -448,7 +448,11 @@ export default class SASjs { appLoc = this.sasjsConfig.appLoc; } if (this.sasjsConfig.serverType === ServerType.SASViya) { - sasApiClient = new SASViyaApiClient(serverUrl, appLoc); + sasApiClient = new SASViyaApiClient( + serverUrl, + appLoc, + this.sasjsConfig.contextName + ); } else if (this.sasjsConfig.serverType === ServerType.SAS9) { sasApiClient = new SAS9ApiClient(serverUrl); } @@ -1066,7 +1070,8 @@ export default class SASjs { else this.sasViyaApiClient = new SASViyaApiClient( this.sasjsConfig.serverUrl, - this.sasjsConfig.appLoc + this.sasjsConfig.appLoc, + this.sasjsConfig.contextName ); } if (this.sasjsConfig.serverType === ServerType.SAS9) { diff --git a/src/SessionManager.ts b/src/SessionManager.ts new file mode 100644 index 0000000..cda6018 --- /dev/null +++ b/src/SessionManager.ts @@ -0,0 +1,138 @@ +import { Session, Context, CsrfToken } from "./types"; +import { asyncForEach, makeRequest } from "./utils"; + +const MAX_SESSION_COUNT = 1; + +export class SessionManager { + constructor(private serverUrl: string, private contextName: string) {} + private sessions: Session[] = []; + private currentContext: Context | null = null; + private csrfToken: CsrfToken | null = null; + + async getSession(accessToken?: string) { + await this.createSessions(accessToken); + this.createAndWaitForSession(accessToken); + return this.sessions.pop(); + } + + private async createSessions(accessToken?: string) { + if (!this.sessions.length) { + if (!this.currentContext) { + await this.setCurrentContext(accessToken); + } + await asyncForEach(new Array(MAX_SESSION_COUNT), async () => { + const createdSession = await this.createAndWaitForSession(accessToken); + this.sessions.push(createdSession); + }); + } + } + + private async createAndWaitForSession(accessToken?: string) { + const createSessionRequest = { + method: "POST", + headers: this.getHeaders(accessToken), + }; + const { result: createdSession, etag } = await this.request( + `${this.serverUrl}/compute/contexts/${this.currentContext!.id}/sessions`, + createSessionRequest + ); + + await this.waitForSession(createdSession, etag); + return createdSession; + } + + private async setCurrentContext(accessToken?: string) { + if (!this.currentContext) { + const { result: contexts } = await this.request<{ + items: Context[]; + }>(`${this.serverUrl}/compute/contexts`, { + headers: this.getHeaders(accessToken), + }); + + const contextsList = + contexts && contexts.items && contexts.items.length + ? contexts.items + : []; + + const currentContext = contextsList.find( + (c: any) => c.name === this.contextName + ); + + if (!currentContext) { + throw new Error( + `The context ${this.contextName} was not found on the server ${this.serverUrl}` + ); + } + + this.currentContext = currentContext; + } + } + + private getHeaders(accessToken?: string) { + const headers: any = { + "Content-Type": "application/json", + }; + if (accessToken) { + headers.Authorization = `Bearer ${accessToken}`; + } + + return headers; + } + + private async waitForSession( + session: Session, + etag: string | null, + accessToken?: string, + silent = false + ) { + let sessionState = session.state; + const headers: any = { + ...this.getHeaders(accessToken), + "If-None-Match": etag, + }; + const stateLink = session.links.find((l: any) => l.rel === "state"); + return new Promise(async (resolve, _) => { + if (sessionState === "pending") { + if (stateLink) { + if (!silent) { + console.log("Polling session status... \n"); + } + const { result: state } = await this.request( + `${this.serverUrl}${stateLink.href}?wait=30`, + { + headers, + }, + "text" + ); + + sessionState = state.trim(); + if (!silent) { + console.log(`Current state: ${sessionState}\n`); + } + resolve(sessionState); + } + } else { + resolve(sessionState); + } + }); + } + + private async request( + url: string, + options: RequestInit, + contentType: "text" | "json" = "json" + ) { + if (this.csrfToken) { + options.headers = { + ...options.headers, + [this.csrfToken.headerName]: this.csrfToken.value, + }; + } + return await makeRequest( + url, + options, + (token) => (this.csrfToken = token), + contentType + ); + } +} From 8bf74d17e9c41b26f302d211a16e3bdf1ef267c0 Mon Sep 17 00:00:00 2001 From: Krishna Acondy Date: Sat, 18 Jul 2020 15:08:40 +0100 Subject: [PATCH 06/20] fix(*): handle login required state, fix session creation logic --- src/SASViyaApiClient.ts | 11 ++++++-- src/SASjs.ts | 59 ++++++++++++++++++++-------------------- src/SessionManager.ts | 1 + src/utils/makeRequest.ts | 9 +++++- 4 files changed, 47 insertions(+), 33 deletions(-) diff --git a/src/SASViyaApiClient.ts b/src/SASViyaApiClient.ts index a56a17c..d45db0c 100644 --- a/src/SASViyaApiClient.ts +++ b/src/SASViyaApiClient.ts @@ -661,7 +661,7 @@ export class SASViyaApiClient { contextName, accessToken, "", - false, + true, data, debug ); @@ -864,12 +864,19 @@ export class SASViyaApiClient { if (accessToken) { requestInfo.headers = { Authorization: `Bearer ${accessToken}` }; } + let error; const rootFolder = await this.request( `${this.serverUrl}${url}`, requestInfo - ).catch(() => null); + ).catch((e) => { + error = e; + return null; + }); this.rootFolder = rootFolder?.result || null; + if (error) { + throw new Error(JSON.stringify(error)); + } } private async pollJobState( diff --git a/src/SASjs.ts b/src/SASjs.ts index 5d3d911..dc808c0 100644 --- a/src/SASjs.ts +++ b/src/SASjs.ts @@ -387,6 +387,7 @@ export default class SASjs { loginRequiredCallback?: any, accessToken?: string ) { + sasJob = sasJob.startsWith("/") ? sasJob.replace("/", "") : sasJob; if ( this.sasjsConfig.serverType === ServerType.SASViya && this.sasjsConfig.contextName @@ -498,36 +499,34 @@ export default class SASjs { sasjsWaitingRequest.requestPromise.promise = new Promise( async (resolve, reject) => { - const session = await this.checkSession(); - - if (!session.isLoggedIn) { - if (loginRequiredCallback) loginRequiredCallback(true); - sasjsWaitingRequest.requestPromise.resolve = resolve; - sasjsWaitingRequest.requestPromise.reject = reject; - this.sasjsWaitingRequests.push(sasjsWaitingRequest); - } else { - resolve( - await this.sasViyaApiClient - ?.executeComputeJob( - sasJob, - this.sasjsConfig.contextName, - this.sasjsConfig.debug, - data, - accessToken - ) - .then((response) => { - if (!this.sasjsConfig.debug) { - this.appendSasjsRequest(null, sasJob, null); - } else { - this.appendSasjsRequest(response, sasJob, null); - } - return JSON.parse(response!.result); - }) - .catch((e) => - reject({ MESSAGE: (e && e.message) || "Job execution failed" }) - ) - ); - } + resolve( + await this.sasViyaApiClient + ?.executeComputeJob( + sasJob, + this.sasjsConfig.contextName, + this.sasjsConfig.debug, + data, + accessToken + ) + .then((response) => { + if (!this.sasjsConfig.debug) { + this.appendSasjsRequest(null, sasJob, null); + } else { + this.appendSasjsRequest(response, sasJob, null); + } + return JSON.parse(response!.result); + }) + .catch((e) => { + if (e && e.includes(401)) { + if (loginRequiredCallback) loginRequiredCallback(true); + sasjsWaitingRequest.requestPromise.resolve = resolve; + sasjsWaitingRequest.requestPromise.reject = reject; + this.sasjsWaitingRequests.push(sasjsWaitingRequest); + } else { + reject({ MESSAGE: e || "Job execution failed" }); + } + }) + ); } ); return sasjsWaitingRequest.requestPromise.promise; diff --git a/src/SessionManager.ts b/src/SessionManager.ts index cda6018..a11d609 100644 --- a/src/SessionManager.ts +++ b/src/SessionManager.ts @@ -38,6 +38,7 @@ export class SessionManager { ); await this.waitForSession(createdSession, etag); + this.sessions.push(createdSession); return createdSession; } diff --git a/src/utils/makeRequest.ts b/src/utils/makeRequest.ts index 8b2b411..c92d1b1 100644 --- a/src/utils/makeRequest.ts +++ b/src/utils/makeRequest.ts @@ -11,7 +11,7 @@ export async function makeRequest( ? (res: Response) => res.json() : (res: Response) => res.text(); let etag = null; - const result = await fetch(url, request).then((response) => { + const result = await fetch(url, request).then(async (response) => { if (!response.ok) { if (response.status === 403) { const tokenHeader = response.headers.get("X-CSRF-HEADER"); @@ -32,8 +32,15 @@ export async function makeRequest( return responseTransform(res); }); } + } else { + const body = await response.text(); + return Promise.reject({ status: response.status, body }); } } else { + if (response.redirected && response.url.includes("SASLogon/login")) { + const body = await response.text(); + return Promise.reject({ status: 401, body }); + } etag = response.headers.get("ETag"); return responseTransform(response); } From c7d6c66093475c7d9c9a440479f6910bd49d707d Mon Sep 17 00:00:00 2001 From: Mihajlo Medjedovic Date: Sun, 19 Jul 2020 16:10:56 +0200 Subject: [PATCH 07/20] feat: request config override --- src/SASjs.ts | 54 ++++++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/src/SASjs.ts b/src/SASjs.ts index dc808c0..d4fc4c8 100644 --- a/src/SASjs.ts +++ b/src/SASjs.ts @@ -42,7 +42,8 @@ const requestRetryLimit = 5; * */ export default class SASjs { - private sasjsConfig = new SASjsConfig(); + private globalSasjsConfig: SASjsConfig = new SASjsConfig(); + private sasjsConfig: SASjsConfig = new SASjsConfig(); private jobsPath: string = ""; private logoutUrl: string = ""; private loginUrl: string = ""; @@ -60,8 +61,9 @@ export default class SASjs { ...defaultConfig, ...config, }; - + this.setupConfiguration(); + this.globalSasjsConfig = { ...this.sasjsConfig }; } public async executeScriptSAS9( @@ -383,40 +385,51 @@ export default class SASjs { public async request( sasJob: string, data: any, - params?: any, + config?: SASjsConfig, loginRequiredCallback?: any, accessToken?: string ) { + let requestResponse; + + if (config) { + this.sasjsConfig = { + ...this.globalSasjsConfig, + ...config + }; + } + sasJob = sasJob.startsWith("/") ? sasJob.replace("/", "") : sasJob; + if ( this.sasjsConfig.serverType === ServerType.SASViya && this.sasjsConfig.contextName ) { if (this.sasjsConfig.useComputeApi) { - return await this.executeJobViaComputeApi( + requestResponse = await this.executeJobViaComputeApi( sasJob, data, - params, loginRequiredCallback, accessToken ); } else { - return await this.executeJobViaJesApi( + requestResponse = await this.executeJobViaJesApi( sasJob, data, - params, loginRequiredCallback, accessToken ); } } else { - return await this.executeJobViaJes( + requestResponse = await this.executeJobViaWeb( sasJob, data, - params, loginRequiredCallback ); } + + this.sasjsConfig = this.globalSasjsConfig; + + return requestResponse; } /** @@ -482,7 +495,6 @@ export default class SASjs { private async executeJobViaComputeApi( sasJob: string, data: any, - params?: any, loginRequiredCallback?: any, accessToken?: string ) { @@ -493,8 +505,7 @@ export default class SASjs { reject: null, }, SASjob: sasJob, - data, - params, + data }; sasjsWaitingRequest.requestPromise.promise = new Promise( @@ -535,7 +546,6 @@ export default class SASjs { private async executeJobViaJesApi( sasJob: string, data: any, - params?: any, loginRequiredCallback?: any, accessToken?: string ) { @@ -546,8 +556,7 @@ export default class SASjs { reject: null, }, SASjob: sasJob, - data, - params, + data }; sasjsWaitingRequest.requestPromise.promise = new Promise( @@ -587,10 +596,9 @@ export default class SASjs { return sasjsWaitingRequest.requestPromise.promise; } - private async executeJobViaJes( + private async executeJobViaWeb( sasJob: string, data: any, - params?: any, loginRequiredCallback?: any ) { const sasjsWaitingRequest: SASjsWaitingRequest = { @@ -600,8 +608,7 @@ export default class SASjs { reject: null, }, SASjob: sasJob, - data, - params, + data }; const program = this.sasjsConfig.appLoc ? this.sasjsConfig.appLoc.replace(/\/?$/, "/") + sasJob.replace(/^\//, "") @@ -615,10 +622,8 @@ export default class SASjs { ? "__program=" + program + "&_job=" + jobUri : "_program=" + program }`; - - const inputParams = params ? params : {}; + const requestParams = { - ...inputParams, ...this.getRequestParams(), }; @@ -736,7 +741,7 @@ export default class SASjs { ) { if (this.retryCount < requestRetryLimit) { this.retryCount++; - this.request(sasJob, data, params).then( + this.request(sasJob, data).then( (res: any) => resolve(res), (err: any) => reject(err) ); @@ -814,8 +819,7 @@ export default class SASjs { for (const sasjsWaitingRequest of this.sasjsWaitingRequests) { this.request( sasjsWaitingRequest.SASjob, - sasjsWaitingRequest.data, - sasjsWaitingRequest.params + sasjsWaitingRequest.data ).then( (res: any) => { sasjsWaitingRequest.requestPromise.resolve(res); From 405a19f0cf032065a567e7f16ccc4a8c17793111 Mon Sep 17 00:00:00 2001 From: Mihajlo Medjedovic Date: Sun, 19 Jul 2020 17:44:29 +0200 Subject: [PATCH 08/20] fix: local config --- src/SASjs.ts | 58 ++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/SASjs.ts b/src/SASjs.ts index d4fc4c8..00f2708 100644 --- a/src/SASjs.ts +++ b/src/SASjs.ts @@ -42,7 +42,6 @@ const requestRetryLimit = 5; * */ export default class SASjs { - private globalSasjsConfig: SASjsConfig = new SASjsConfig(); private sasjsConfig: SASjsConfig = new SASjsConfig(); private jobsPath: string = ""; private logoutUrl: string = ""; @@ -63,7 +62,6 @@ export default class SASjs { }; this.setupConfiguration(); - this.globalSasjsConfig = { ...this.sasjsConfig }; } public async executeScriptSAS9( @@ -385,29 +383,28 @@ export default class SASjs { public async request( sasJob: string, data: any, - config?: SASjsConfig, + config: any = {}, loginRequiredCallback?: any, accessToken?: string ) { let requestResponse; - if (config) { - this.sasjsConfig = { - ...this.globalSasjsConfig, - ...config - }; + config = { + ...this.sasjsConfig, + ...config } sasJob = sasJob.startsWith("/") ? sasJob.replace("/", "") : sasJob; if ( - this.sasjsConfig.serverType === ServerType.SASViya && - this.sasjsConfig.contextName + config.serverType === ServerType.SASViya && + config.contextName ) { - if (this.sasjsConfig.useComputeApi) { + if (config.useComputeApi) { requestResponse = await this.executeJobViaComputeApi( sasJob, data, + config, loginRequiredCallback, accessToken ); @@ -415,6 +412,7 @@ export default class SASjs { requestResponse = await this.executeJobViaJesApi( sasJob, data, + config, loginRequiredCallback, accessToken ); @@ -423,12 +421,11 @@ export default class SASjs { requestResponse = await this.executeJobViaWeb( sasJob, data, + config, loginRequiredCallback ); } - this.sasjsConfig = this.globalSasjsConfig; - return requestResponse; } @@ -495,6 +492,7 @@ export default class SASjs { private async executeJobViaComputeApi( sasJob: string, data: any, + config: any, loginRequiredCallback?: any, accessToken?: string ) { @@ -514,13 +512,13 @@ export default class SASjs { await this.sasViyaApiClient ?.executeComputeJob( sasJob, - this.sasjsConfig.contextName, - this.sasjsConfig.debug, + config.contextName, + config.debug, data, accessToken ) .then((response) => { - if (!this.sasjsConfig.debug) { + if (!config.debug) { this.appendSasjsRequest(null, sasJob, null); } else { this.appendSasjsRequest(response, sasJob, null); @@ -546,6 +544,7 @@ export default class SASjs { private async executeJobViaJesApi( sasJob: string, data: any, + config: any, loginRequiredCallback?: any, accessToken?: string ) { @@ -573,13 +572,13 @@ export default class SASjs { await this.sasViyaApiClient ?.executeJob( sasJob, - this.sasjsConfig.contextName, - this.sasjsConfig.debug, + config.contextName, + config.debug, data, accessToken ) .then((response) => { - if (!this.sasjsConfig.debug) { + if (!config.debug) { this.appendSasjsRequest(null, sasJob, null); } else { this.appendSasjsRequest(response, sasJob, null); @@ -599,6 +598,7 @@ export default class SASjs { private async executeJobViaWeb( sasJob: string, data: any, + config: any, loginRequiredCallback?: any ) { const sasjsWaitingRequest: SASjsWaitingRequest = { @@ -610,14 +610,14 @@ export default class SASjs { SASjob: sasJob, data }; - const program = this.sasjsConfig.appLoc - ? this.sasjsConfig.appLoc.replace(/\/?$/, "/") + sasJob.replace(/^\//, "") + const program = config.appLoc + ? config.appLoc.replace(/\/?$/, "/") + sasJob.replace(/^\//, "") : sasJob; const jobUri = - this.sasjsConfig.serverType === "SASVIYA" + config.serverType === "SASVIYA" ? await this.getJobUri(sasJob) : ""; - const apiUrl = `${this.sasjsConfig.serverUrl}${this.jobsPath}/?${ + const apiUrl = `${config.serverUrl}${this.jobsPath}/?${ jobUri.length > 0 ? "__program=" + program + "&_job=" + jobUri : "_program=" + program @@ -635,7 +635,7 @@ export default class SASjs { if (data) { const stringifiedData = JSON.stringify(data); if ( - this.sasjsConfig.serverType === ServerType.SAS9 || + config.serverType === ServerType.SAS9 || stringifiedData.length > 500000 || stringifiedData.includes(";") ) { @@ -727,7 +727,7 @@ export default class SASjs { if ( response.redirected && - this.sasjsConfig.serverType === ServerType.SAS9 + config.serverType === ServerType.SAS9 ) { isRedirected = true; } @@ -760,8 +760,8 @@ export default class SASjs { this.sasjsWaitingRequests.push(sasjsWaitingRequest); } else { if ( - this.sasjsConfig.serverType === ServerType.SAS9 && - this.sasjsConfig.debug + config.serverType === ServerType.SAS9 && + config.debug ) { this.updateUsername(responseText); const jsonResponseText = this.parseSAS9Response(responseText); @@ -774,8 +774,8 @@ export default class SASjs { }); } } else if ( - this.sasjsConfig.serverType === ServerType.SASViya && - this.sasjsConfig.debug + config.serverType === ServerType.SASViya && + config.debug ) { try { this.parseSASVIYADebugResponse(responseText).then( From ee024c67ab5984a73ff673f2fb6367ecf84262f1 Mon Sep 17 00:00:00 2001 From: Mihajlo Medjedovic Date: Mon, 20 Jul 2020 20:34:12 +0200 Subject: [PATCH 09/20] feat: csrf token main file sync --- src/SASViyaApiClient.ts | 8 +++++--- src/SASjs.ts | 32 ++++++++++++++++++++------------ src/SessionManager.ts | 11 +++++++++-- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/SASViyaApiClient.ts b/src/SASViyaApiClient.ts index d45db0c..de4acab 100644 --- a/src/SASViyaApiClient.ts +++ b/src/SASViyaApiClient.ts @@ -20,6 +20,7 @@ export class SASViyaApiClient { private serverUrl: string, private rootFolderName: string, private contextName: string, + private setCsrfToken: (csrfToken: CsrfToken) => void, private rootFolderMap = new Map() ) { if (!rootFolderName) { @@ -28,7 +29,7 @@ export class SASViyaApiClient { } private csrfToken: CsrfToken | null = null; private rootFolder: Folder | null = null; - private sessionManager = new SessionManager(this.serverUrl, this.contextName); + private sessionManager = new SessionManager(this.serverUrl, this.contextName, this.setCsrfToken); /** * Returns a map containing the directory structure in the currently set root folder. @@ -1025,8 +1026,9 @@ export class SASViyaApiClient { return `/folders/folders/${folder.id}`; } - setCsrfToken = (csrfToken: CsrfToken) => { + setCsrfTokenLocal = (csrfToken: CsrfToken) => { this.csrfToken = csrfToken; + this.setCsrfToken(csrfToken); }; private async request( @@ -1040,6 +1042,6 @@ export class SASViyaApiClient { [this.csrfToken.headerName]: this.csrfToken.value, }; } - return await makeRequest(url, options, this.setCsrfToken, contentType); + return await makeRequest(url, options, this.setCsrfTokenLocal, contentType); } } diff --git a/src/SASjs.ts b/src/SASjs.ts index dc808c0..a48f55b 100644 --- a/src/SASjs.ts +++ b/src/SASjs.ts @@ -20,6 +20,7 @@ import { SASjsRequest, SASjsWaitingRequest, ServerType, + CsrfToken, } from "./types"; import { SASViyaApiClient } from "./SASViyaApiClient"; import { SAS9ApiClient } from "./SAS9ApiClient"; @@ -46,8 +47,7 @@ export default class SASjs { private jobsPath: string = ""; private logoutUrl: string = ""; private loginUrl: string = ""; - private _csrf: string | null = null; - private _csrfHeader: string | null = null; + private csrfToken: CsrfToken | null = null; private retryCount: number = 0; private sasjsRequests: SASjsRequest[] = []; private sasjsWaitingRequests: SASjsWaitingRequest[] = []; @@ -239,7 +239,7 @@ export default class SASjs { * */ public getCsrf() { - return this._csrf; + return this.csrfToken?.value; } /** @@ -452,7 +452,8 @@ export default class SASjs { sasApiClient = new SASViyaApiClient( serverUrl, appLoc, - this.sasjsConfig.contextName + this.sasjsConfig.contextName, + this.setCsrfToken ); } else if (this.sasjsConfig.serverType === ServerType.SAS9) { sasApiClient = new SAS9ApiClient(serverUrl); @@ -517,7 +518,7 @@ export default class SASjs { return JSON.parse(response!.result); }) .catch((e) => { - if (e && e.includes(401)) { + if (e && e.status === 401) { if (loginRequiredCallback) loginRequiredCallback(true); sasjsWaitingRequest.requestPromise.resolve = resolve; sasjsWaitingRequest.requestPromise.reject = reject; @@ -698,8 +699,8 @@ export default class SASjs { reject({ MESSAGE: errorMsg }); } const headers: any = {}; - if (this._csrfHeader && this._csrf) { - headers[this._csrfHeader] = this._csrf; + if (this.csrfToken) { + headers[this.csrfToken.headerName] = this.csrfToken.value; } fetch(apiUrl, { method: "POST", @@ -714,8 +715,10 @@ export default class SASjs { if (tokenHeader) { const token = response.headers.get(tokenHeader); - this._csrfHeader = tokenHeader; - this._csrf = token; + this.csrfToken = { + headerName: tokenHeader, + value: token || '' + } } } } @@ -810,6 +813,10 @@ export default class SASjs { return sasjsWaitingRequest.requestPromise.promise; } + private setCsrfToken = (csrfToken: CsrfToken) => { + this.csrfToken = csrfToken; + }; + private async resendWaitingRequests() { for (const sasjsWaitingRequest of this.sasjsWaitingRequests) { this.request( @@ -832,8 +839,8 @@ export default class SASjs { private getRequestParams(): any { const requestParams: any = {}; - if (this._csrf) { - requestParams["_csrf"] = this._csrf; + if (this.csrfToken) { + requestParams["_csrf"] = this.csrfToken.value; } if (this.sasjsConfig.debug) { @@ -1070,7 +1077,8 @@ export default class SASjs { this.sasViyaApiClient = new SASViyaApiClient( this.sasjsConfig.serverUrl, this.sasjsConfig.appLoc, - this.sasjsConfig.contextName + this.sasjsConfig.contextName, + this.setCsrfToken ); } if (this.sasjsConfig.serverType === ServerType.SAS9) { diff --git a/src/SessionManager.ts b/src/SessionManager.ts index a11d609..1a20b96 100644 --- a/src/SessionManager.ts +++ b/src/SessionManager.ts @@ -4,7 +4,11 @@ import { asyncForEach, makeRequest } from "./utils"; const MAX_SESSION_COUNT = 1; export class SessionManager { - constructor(private serverUrl: string, private contextName: string) {} + constructor( + private serverUrl: string, + private contextName: string, + private setCsrfToken: (csrfToken: CsrfToken) => void + ) {} private sessions: Session[] = []; private currentContext: Context | null = null; private csrfToken: CsrfToken | null = null; @@ -132,7 +136,10 @@ export class SessionManager { return await makeRequest( url, options, - (token) => (this.csrfToken = token), + (token) => { + this.csrfToken = token; + this.setCsrfToken(token); + }, contentType ); } From 1c1e6b8efd0e79c48cd079c008aaec19c7f0ce5c Mon Sep 17 00:00:00 2001 From: Mihajlo Medjedovic Date: Mon, 20 Jul 2020 20:44:30 +0200 Subject: [PATCH 10/20] fix: waiting requests passing config --- src/SASjs.ts | 3 +++ src/types/SASjsWaitingRequest.ts | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/SASjs.ts b/src/SASjs.ts index 00f2708..93053fa 100644 --- a/src/SASjs.ts +++ b/src/SASjs.ts @@ -530,6 +530,7 @@ export default class SASjs { if (loginRequiredCallback) loginRequiredCallback(true); sasjsWaitingRequest.requestPromise.resolve = resolve; sasjsWaitingRequest.requestPromise.reject = reject; + sasjsWaitingRequest.config = config; this.sasjsWaitingRequests.push(sasjsWaitingRequest); } else { reject({ MESSAGE: e || "Job execution failed" }); @@ -566,6 +567,7 @@ export default class SASjs { if (loginRequiredCallback) loginRequiredCallback(true); sasjsWaitingRequest.requestPromise.resolve = resolve; sasjsWaitingRequest.requestPromise.reject = reject; + sasjsWaitingRequest.config = config; this.sasjsWaitingRequests.push(sasjsWaitingRequest); } else { resolve( @@ -757,6 +759,7 @@ export default class SASjs { if (loginRequiredCallback) loginRequiredCallback(true); sasjsWaitingRequest.requestPromise.resolve = resolve; sasjsWaitingRequest.requestPromise.reject = reject; + sasjsWaitingRequest.config = config; this.sasjsWaitingRequests.push(sasjsWaitingRequest); } else { if ( diff --git a/src/types/SASjsWaitingRequest.ts b/src/types/SASjsWaitingRequest.ts index f3c289d..f47c832 100644 --- a/src/types/SASjsWaitingRequest.ts +++ b/src/types/SASjsWaitingRequest.ts @@ -10,5 +10,5 @@ export interface SASjsWaitingRequest { }; SASjob: string; data: any; - params?: any; + config?: any; } From 2b04fe0c3ea669670ca11f29b7e7ea9ff807909a Mon Sep 17 00:00:00 2001 From: Mihajlo Medjedovic Date: Mon, 20 Jul 2020 21:31:54 +0200 Subject: [PATCH 11/20] docs: update --- docs/assets/js/search.json | 2 +- ...ection-560.reflection-1.sas9apiclient.html | 294 ++++++ .../reflection-560.reflection-1.sasjs.html | 929 ++++++++++++++++++ ...ion-560.reflection-1.sasviyaapiclient.html | 892 +++++++++++++++++ ...ction-560.reflection-1.sessionmanager.html | 206 ++++ docs/classes/types.sasjsconfig.html | 34 +- docs/enums/types.servertype.html | 8 +- docs/globals.html | 4 +- docs/index.html | 342 +++---- docs/interfaces/types.context.html | 5 +- docs/interfaces/types.csrftoken.html | 5 +- docs/interfaces/types.folder.html | 5 +- docs/interfaces/types.job.html | 19 +- docs/interfaces/types.jobdefinition.html | 176 ++++ docs/interfaces/types.jobresult.html | 5 +- docs/interfaces/types.link.html | 5 +- docs/interfaces/types.sasjsrequest.html | 8 +- .../interfaces/types.sasjswaitingrequest.html | 34 +- docs/interfaces/types.session.html | 35 +- docs/modules/reflection-560.html | 107 ++ docs/modules/reflection-560.reflection-1.html | 125 +++ docs/modules/types.html | 6 +- docs/modules/utils.html | 42 +- 23 files changed, 3020 insertions(+), 268 deletions(-) create mode 100644 docs/classes/reflection-560.reflection-1.sas9apiclient.html create mode 100644 docs/classes/reflection-560.reflection-1.sasjs.html create mode 100644 docs/classes/reflection-560.reflection-1.sasviyaapiclient.html create mode 100644 docs/classes/reflection-560.reflection-1.sessionmanager.html create mode 100644 docs/interfaces/types.jobdefinition.html create mode 100644 docs/modules/reflection-560.html create mode 100644 docs/modules/reflection-560.reflection-1.html diff --git a/docs/assets/js/search.json b/docs/assets/js/search.json index afd9d94..34a11bb 100644 --- a/docs/assets/js/search.json +++ b/docs/assets/js/search.json @@ -1 +1 @@ -{"kinds":{"1":"Module","4":"Enumeration","16":"Enumeration member","32":"Variable","64":"Function","128":"Class","256":"Interface","512":"Constructor","1024":"Property","2048":"Method","65536":"Type literal"},"rows":[{"id":0,"kind":128,"name":"SAS9ApiClient","url":"classes/reflection-445.reflection-1.sas9apiclient.html","classes":"tsd-kind-class tsd-parent-kind-module","parent":"."},{"id":1,"kind":512,"name":"constructor","url":"classes/reflection-445.reflection-1.sas9apiclient.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"..SAS9ApiClient"},{"id":2,"kind":2048,"name":"getConfig","url":"classes/reflection-445.reflection-1.sas9apiclient.html#getconfig","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SAS9ApiClient"},{"id":3,"kind":2048,"name":"setConfig","url":"classes/reflection-445.reflection-1.sas9apiclient.html#setconfig","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SAS9ApiClient"},{"id":4,"kind":2048,"name":"executeScript","url":"classes/reflection-445.reflection-1.sas9apiclient.html#executescript","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SAS9ApiClient"},{"id":5,"kind":1,"name":"utils","url":"modules/utils.html","classes":"tsd-kind-module"},{"id":6,"kind":64,"name":"asyncForEach","url":"modules/utils.html#asyncforeach","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":7,"kind":1,"name":"types","url":"modules/types.html","classes":"tsd-kind-module"},{"id":8,"kind":256,"name":"SASjsRequest","url":"interfaces/types.sasjsrequest.html","classes":"tsd-kind-interface tsd-parent-kind-module","parent":"types"},{"id":9,"kind":1024,"name":"serviceLink","url":"interfaces/types.sasjsrequest.html#servicelink","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.SASjsRequest"},{"id":10,"kind":1024,"name":"timestamp","url":"interfaces/types.sasjsrequest.html#timestamp","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.SASjsRequest"},{"id":11,"kind":1024,"name":"sourceCode","url":"interfaces/types.sasjsrequest.html#sourcecode","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.SASjsRequest"},{"id":12,"kind":1024,"name":"generatedCode","url":"interfaces/types.sasjsrequest.html#generatedcode","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.SASjsRequest"},{"id":13,"kind":1024,"name":"logFile","url":"interfaces/types.sasjsrequest.html#logfile","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.SASjsRequest"},{"id":14,"kind":1024,"name":"SASWORK","url":"interfaces/types.sasjsrequest.html#saswork","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.SASjsRequest"},{"id":15,"kind":64,"name":"compareTimestamps","url":"modules/utils.html#comparetimestamps","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":16,"kind":64,"name":"convertToCSV","url":"modules/utils.html#converttocsv","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":17,"kind":64,"name":"isAuthorizeFormRequired","url":"modules/utils.html#isauthorizeformrequired","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":18,"kind":64,"name":"isLogInRequired","url":"modules/utils.html#isloginrequired","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":19,"kind":64,"name":"isLogInSuccess","url":"modules/utils.html#isloginsuccess","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":20,"kind":256,"name":"Context","url":"interfaces/types.context.html","classes":"tsd-kind-interface tsd-parent-kind-module","parent":"types"},{"id":21,"kind":1024,"name":"name","url":"interfaces/types.context.html#name","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Context"},{"id":22,"kind":1024,"name":"id","url":"interfaces/types.context.html#id","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Context"},{"id":23,"kind":1024,"name":"createdBy","url":"interfaces/types.context.html#createdby","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Context"},{"id":24,"kind":1024,"name":"version","url":"interfaces/types.context.html#version","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Context"},{"id":25,"kind":256,"name":"CsrfToken","url":"interfaces/types.csrftoken.html","classes":"tsd-kind-interface tsd-parent-kind-module","parent":"types"},{"id":26,"kind":1024,"name":"headerName","url":"interfaces/types.csrftoken.html#headername","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.CsrfToken"},{"id":27,"kind":1024,"name":"value","url":"interfaces/types.csrftoken.html#value","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.CsrfToken"},{"id":28,"kind":256,"name":"Link","url":"interfaces/types.link.html","classes":"tsd-kind-interface tsd-parent-kind-module","parent":"types"},{"id":29,"kind":1024,"name":"method","url":"interfaces/types.link.html#method","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Link"},{"id":30,"kind":1024,"name":"rel","url":"interfaces/types.link.html#rel","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Link"},{"id":31,"kind":1024,"name":"href","url":"interfaces/types.link.html#href","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Link"},{"id":32,"kind":1024,"name":"uri","url":"interfaces/types.link.html#uri","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Link"},{"id":33,"kind":1024,"name":"type","url":"interfaces/types.link.html#type","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Link"},{"id":34,"kind":256,"name":"Folder","url":"interfaces/types.folder.html","classes":"tsd-kind-interface tsd-parent-kind-module","parent":"types"},{"id":35,"kind":1024,"name":"id","url":"interfaces/types.folder.html#id","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Folder"},{"id":36,"kind":1024,"name":"uri","url":"interfaces/types.folder.html#uri","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Folder"},{"id":37,"kind":1024,"name":"links","url":"interfaces/types.folder.html#links","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Folder"},{"id":38,"kind":256,"name":"JobResult","url":"interfaces/types.jobresult.html","classes":"tsd-kind-interface tsd-parent-kind-module","parent":"types"},{"id":39,"kind":1024,"name":"_webout.json","url":"interfaces/types.jobresult.html#_webout_json","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.JobResult"},{"id":40,"kind":256,"name":"Job","url":"interfaces/types.job.html","classes":"tsd-kind-interface tsd-parent-kind-module","parent":"types"},{"id":41,"kind":1024,"name":"id","url":"interfaces/types.job.html#id","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Job"},{"id":42,"kind":1024,"name":"name","url":"interfaces/types.job.html#name","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Job"},{"id":43,"kind":1024,"name":"uri","url":"interfaces/types.job.html#uri","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Job"},{"id":44,"kind":1024,"name":"createdBy","url":"interfaces/types.job.html#createdby","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Job"},{"id":45,"kind":1024,"name":"links","url":"interfaces/types.job.html#links","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Job"},{"id":46,"kind":1024,"name":"results","url":"interfaces/types.job.html#results","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Job"},{"id":47,"kind":4,"name":"ServerType","url":"enums/types.servertype.html","classes":"tsd-kind-enum tsd-parent-kind-module","parent":"types"},{"id":48,"kind":16,"name":"SASViya","url":"enums/types.servertype.html#sasviya","classes":"tsd-kind-enum-member tsd-parent-kind-enum","parent":"types.ServerType"},{"id":49,"kind":16,"name":"SAS9","url":"enums/types.servertype.html#sas9","classes":"tsd-kind-enum-member tsd-parent-kind-enum","parent":"types.ServerType"},{"id":50,"kind":128,"name":"SASjsConfig","url":"classes/types.sasjsconfig.html","classes":"tsd-kind-class tsd-parent-kind-module","parent":"types"},{"id":51,"kind":1024,"name":"serverUrl","url":"classes/types.sasjsconfig.html#serverurl","classes":"tsd-kind-property tsd-parent-kind-class","parent":"types.SASjsConfig"},{"id":52,"kind":1024,"name":"pathSAS9","url":"classes/types.sasjsconfig.html#pathsas9","classes":"tsd-kind-property tsd-parent-kind-class","parent":"types.SASjsConfig"},{"id":53,"kind":1024,"name":"pathSASViya","url":"classes/types.sasjsconfig.html#pathsasviya","classes":"tsd-kind-property tsd-parent-kind-class","parent":"types.SASjsConfig"},{"id":54,"kind":1024,"name":"appLoc","url":"classes/types.sasjsconfig.html#apploc","classes":"tsd-kind-property tsd-parent-kind-class","parent":"types.SASjsConfig"},{"id":55,"kind":1024,"name":"serverType","url":"classes/types.sasjsconfig.html#servertype","classes":"tsd-kind-property tsd-parent-kind-class","parent":"types.SASjsConfig"},{"id":56,"kind":1024,"name":"debug","url":"classes/types.sasjsconfig.html#debug","classes":"tsd-kind-property tsd-parent-kind-class","parent":"types.SASjsConfig"},{"id":57,"kind":1024,"name":"contextName","url":"classes/types.sasjsconfig.html#contextname","classes":"tsd-kind-property tsd-parent-kind-class","parent":"types.SASjsConfig"},{"id":58,"kind":256,"name":"SASjsWaitingRequest","url":"interfaces/types.sasjswaitingrequest.html","classes":"tsd-kind-interface tsd-parent-kind-module","parent":"types"},{"id":59,"kind":1024,"name":"requestPromise","url":"interfaces/types.sasjswaitingrequest.html#requestpromise","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.SASjsWaitingRequest"},{"id":60,"kind":65536,"name":"__type","url":"interfaces/types.sasjswaitingrequest.html#requestpromise.__type","classes":"tsd-kind-type-literal tsd-parent-kind-property","parent":"types.SASjsWaitingRequest.requestPromise"},{"id":61,"kind":32,"name":"promise","url":"interfaces/types.sasjswaitingrequest.html#requestpromise.__type.promise","classes":"tsd-kind-variable tsd-parent-kind-type-literal","parent":"types.SASjsWaitingRequest.requestPromise.__type"},{"id":62,"kind":32,"name":"resolve","url":"interfaces/types.sasjswaitingrequest.html#requestpromise.__type.resolve","classes":"tsd-kind-variable tsd-parent-kind-type-literal","parent":"types.SASjsWaitingRequest.requestPromise.__type"},{"id":63,"kind":32,"name":"reject","url":"interfaces/types.sasjswaitingrequest.html#requestpromise.__type.reject","classes":"tsd-kind-variable tsd-parent-kind-type-literal","parent":"types.SASjsWaitingRequest.requestPromise.__type"},{"id":64,"kind":1024,"name":"SASjob","url":"interfaces/types.sasjswaitingrequest.html#sasjob","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.SASjsWaitingRequest"},{"id":65,"kind":1024,"name":"data","url":"interfaces/types.sasjswaitingrequest.html#data","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.SASjsWaitingRequest"},{"id":66,"kind":1024,"name":"params","url":"interfaces/types.sasjswaitingrequest.html#params","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.SASjsWaitingRequest"},{"id":67,"kind":256,"name":"Session","url":"interfaces/types.session.html","classes":"tsd-kind-interface tsd-parent-kind-module","parent":"types"},{"id":68,"kind":1024,"name":"id","url":"interfaces/types.session.html#id","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Session"},{"id":69,"kind":64,"name":"makeRequest","url":"modules/utils.html#makerequest","classes":"tsd-kind-function tsd-parent-kind-module tsd-has-type-parameter","parent":"utils"},{"id":70,"kind":64,"name":"needsRetry","url":"modules/utils.html#needsretry","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":71,"kind":64,"name":"parseAndSubmitAuthorizeForm","url":"modules/utils.html#parseandsubmitauthorizeform","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":72,"kind":64,"name":"parseGeneratedCode","url":"modules/utils.html#parsegeneratedcode","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":73,"kind":64,"name":"parseSourceCode","url":"modules/utils.html#parsesourcecode","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":74,"kind":64,"name":"parseSasViyaLog","url":"modules/utils.html#parsesasviyalog","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":75,"kind":64,"name":"serialize","url":"modules/utils.html#serialize","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":76,"kind":64,"name":"splitChunks","url":"modules/utils.html#splitchunks","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":77,"kind":128,"name":"SASViyaApiClient","url":"classes/reflection-445.reflection-1.sasviyaapiclient.html","classes":"tsd-kind-class tsd-parent-kind-module","parent":"."},{"id":78,"kind":512,"name":"constructor","url":"classes/reflection-445.reflection-1.sasviyaapiclient.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":79,"kind":2048,"name":"getAppLocMap","url":"classes/reflection-445.reflection-1.sasviyaapiclient.html#getapplocmap","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":80,"kind":2048,"name":"getConfig","url":"classes/reflection-445.reflection-1.sasviyaapiclient.html#getconfig","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":81,"kind":2048,"name":"setConfig","url":"classes/reflection-445.reflection-1.sasviyaapiclient.html#setconfig","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":82,"kind":2048,"name":"getAllContexts","url":"classes/reflection-445.reflection-1.sasviyaapiclient.html#getallcontexts","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":83,"kind":2048,"name":"getExecutableContexts","url":"classes/reflection-445.reflection-1.sasviyaapiclient.html#getexecutablecontexts","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":84,"kind":2048,"name":"createSession","url":"classes/reflection-445.reflection-1.sasviyaapiclient.html#createsession","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":85,"kind":2048,"name":"executeScript","url":"classes/reflection-445.reflection-1.sasviyaapiclient.html#executescript","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":86,"kind":2048,"name":"createFolder","url":"classes/reflection-445.reflection-1.sasviyaapiclient.html#createfolder","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":87,"kind":2048,"name":"createJobDefinition","url":"classes/reflection-445.reflection-1.sasviyaapiclient.html#createjobdefinition","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":88,"kind":2048,"name":"getAuthCode","url":"classes/reflection-445.reflection-1.sasviyaapiclient.html#getauthcode","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":89,"kind":2048,"name":"getAccessToken","url":"classes/reflection-445.reflection-1.sasviyaapiclient.html#getaccesstoken","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":90,"kind":2048,"name":"refreshTokens","url":"classes/reflection-445.reflection-1.sasviyaapiclient.html#refreshtokens","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":91,"kind":2048,"name":"deleteClient","url":"classes/reflection-445.reflection-1.sasviyaapiclient.html#deleteclient","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":92,"kind":2048,"name":"executeJob","url":"classes/reflection-445.reflection-1.sasviyaapiclient.html#executejob","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":93,"kind":128,"name":"SASjs","url":"classes/reflection-445.reflection-1.sasjs.html","classes":"tsd-kind-class tsd-parent-kind-module","parent":"."},{"id":94,"kind":512,"name":"constructor","url":"classes/reflection-445.reflection-1.sasjs.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"..SASjs"},{"id":95,"kind":2048,"name":"executeScriptSAS9","url":"classes/reflection-445.reflection-1.sasjs.html#executescriptsas9","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":96,"kind":2048,"name":"getAllContexts","url":"classes/reflection-445.reflection-1.sasjs.html#getallcontexts","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":97,"kind":2048,"name":"getExecutableContexts","url":"classes/reflection-445.reflection-1.sasjs.html#getexecutablecontexts","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":98,"kind":2048,"name":"createSession","url":"classes/reflection-445.reflection-1.sasjs.html#createsession","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":99,"kind":2048,"name":"executeScriptSASViya","url":"classes/reflection-445.reflection-1.sasjs.html#executescriptsasviya","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":100,"kind":2048,"name":"createFolder","url":"classes/reflection-445.reflection-1.sasjs.html#createfolder","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":101,"kind":2048,"name":"createJobDefinition","url":"classes/reflection-445.reflection-1.sasjs.html#createjobdefinition","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":102,"kind":2048,"name":"getAuthCode","url":"classes/reflection-445.reflection-1.sasjs.html#getauthcode","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":103,"kind":2048,"name":"getAccessToken","url":"classes/reflection-445.reflection-1.sasjs.html#getaccesstoken","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":104,"kind":2048,"name":"refreshTokens","url":"classes/reflection-445.reflection-1.sasjs.html#refreshtokens","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":105,"kind":2048,"name":"deleteClient","url":"classes/reflection-445.reflection-1.sasjs.html#deleteclient","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":106,"kind":2048,"name":"getSasjsConfig","url":"classes/reflection-445.reflection-1.sasjs.html#getsasjsconfig","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":107,"kind":2048,"name":"getUserName","url":"classes/reflection-445.reflection-1.sasjs.html#getusername","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":108,"kind":2048,"name":"getCsrf","url":"classes/reflection-445.reflection-1.sasjs.html#getcsrf","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":109,"kind":2048,"name":"setSASjsConfig","url":"classes/reflection-445.reflection-1.sasjs.html#setsasjsconfig","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":110,"kind":2048,"name":"setDebugState","url":"classes/reflection-445.reflection-1.sasjs.html#setdebugstate","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":111,"kind":2048,"name":"checkSession","url":"classes/reflection-445.reflection-1.sasjs.html#checksession","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":112,"kind":2048,"name":"logIn","url":"classes/reflection-445.reflection-1.sasjs.html#login","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":113,"kind":2048,"name":"logOut","url":"classes/reflection-445.reflection-1.sasjs.html#logout","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":114,"kind":2048,"name":"request","url":"classes/reflection-445.reflection-1.sasjs.html#request","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":115,"kind":2048,"name":"deployServicePack","url":"classes/reflection-445.reflection-1.sasjs.html#deployservicepack","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":116,"kind":2048,"name":"getSasRequests","url":"classes/reflection-445.reflection-1.sasjs.html#getsasrequests","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"}],"index":{"version":"2.3.8","fields":["name","parent"],"fieldVectors":[["name/0",[0,30.659]],["parent/0",[1,3.493]],["name/1",[2,35.179]],["parent/1",[0,3.044]],["name/2",[3,38.544]],["parent/2",[0,3.044]],["name/3",[4,38.544]],["parent/3",[0,3.044]],["name/4",[5,38.544]],["parent/4",[0,3.044]],["name/5",[6,20.298]],["parent/5",[]],["name/6",[7,43.652]],["parent/6",[6,2.016]],["name/7",[8,22.45]],["parent/7",[]],["name/8",[9,43.652]],["parent/8",[8,2.229]],["name/9",[10,43.652]],["parent/9",[11,2.878]],["name/10",[12,43.652]],["parent/10",[11,2.878]],["name/11",[13,43.652]],["parent/11",[11,2.878]],["name/12",[14,43.652]],["parent/12",[11,2.878]],["name/13",[15,43.652]],["parent/13",[11,2.878]],["name/14",[16,43.652]],["parent/14",[11,2.878]],["name/15",[17,43.652]],["parent/15",[6,2.016]],["name/16",[18,43.652]],["parent/16",[6,2.016]],["name/17",[19,43.652]],["parent/17",[6,2.016]],["name/18",[20,43.652]],["parent/18",[6,2.016]],["name/19",[21,43.652]],["parent/19",[6,2.016]],["name/20",[22,43.652]],["parent/20",[8,2.229]],["name/21",[23,38.544]],["parent/21",[24,3.244]],["name/22",[25,32.666]],["parent/22",[24,3.244]],["name/23",[26,38.544]],["parent/23",[24,3.244]],["name/24",[27,43.652]],["parent/24",[24,3.244]],["name/25",[28,43.652]],["parent/25",[8,2.229]],["name/26",[29,43.652]],["parent/26",[30,3.827]],["name/27",[31,43.652]],["parent/27",[30,3.827]],["name/28",[32,43.652]],["parent/28",[8,2.229]],["name/29",[33,43.652]],["parent/29",[34,3.044]],["name/30",[35,43.652]],["parent/30",[34,3.044]],["name/31",[36,43.652]],["parent/31",[34,3.044]],["name/32",[37,35.179]],["parent/32",[34,3.044]],["name/33",[38,43.652]],["parent/33",[34,3.044]],["name/34",[39,43.652]],["parent/34",[8,2.229]],["name/35",[25,32.666]],["parent/35",[40,3.493]],["name/36",[37,35.179]],["parent/36",[40,3.493]],["name/37",[41,38.544]],["parent/37",[40,3.493]],["name/38",[42,43.652]],["parent/38",[8,2.229]],["name/39",[43,43.652]],["parent/39",[44,4.334]],["name/40",[45,43.652]],["parent/40",[8,2.229]],["name/41",[25,32.666]],["parent/41",[46,2.878]],["name/42",[23,38.544]],["parent/42",[46,2.878]],["name/43",[37,35.179]],["parent/43",[46,2.878]],["name/44",[26,38.544]],["parent/44",[46,2.878]],["name/45",[41,38.544]],["parent/45",[46,2.878]],["name/46",[47,43.652]],["parent/46",[46,2.878]],["name/47",[48,38.544]],["parent/47",[8,2.229]],["name/48",[49,43.652]],["parent/48",[50,3.827]],["name/49",[51,43.652]],["parent/49",[50,3.827]],["name/50",[52,43.652]],["parent/50",[8,2.229]],["name/51",[53,43.652]],["parent/51",[54,2.736]],["name/52",[55,43.652]],["parent/52",[54,2.736]],["name/53",[56,43.652]],["parent/53",[54,2.736]],["name/54",[57,43.652]],["parent/54",[54,2.736]],["name/55",[48,38.544]],["parent/55",[54,2.736]],["name/56",[58,43.652]],["parent/56",[54,2.736]],["name/57",[59,43.652]],["parent/57",[54,2.736]],["name/58",[60,43.652]],["parent/58",[8,2.229]],["name/59",[61,43.652]],["parent/59",[62,3.244]],["name/60",[63,43.652]],["parent/60",[64,4.334]],["name/61",[65,43.652]],["parent/61",[66,3.493]],["name/62",[67,43.652]],["parent/62",[66,3.493]],["name/63",[68,43.652]],["parent/63",[66,3.493]],["name/64",[69,43.652]],["parent/64",[62,3.244]],["name/65",[70,43.652]],["parent/65",[62,3.244]],["name/66",[71,43.652]],["parent/66",[62,3.244]],["name/67",[72,43.652]],["parent/67",[8,2.229]],["name/68",[25,32.666]],["parent/68",[73,4.334]],["name/69",[74,43.652]],["parent/69",[6,2.016]],["name/70",[75,43.652]],["parent/70",[6,2.016]],["name/71",[76,43.652]],["parent/71",[6,2.016]],["name/72",[77,43.652]],["parent/72",[6,2.016]],["name/73",[78,43.652]],["parent/73",[6,2.016]],["name/74",[79,43.652]],["parent/74",[6,2.016]],["name/75",[80,43.652]],["parent/75",[6,2.016]],["name/76",[81,43.652]],["parent/76",[6,2.016]],["name/77",[82,19.673]],["parent/77",[1,3.493]],["name/78",[2,35.179]],["parent/78",[82,1.953]],["name/79",[83,43.652]],["parent/79",[82,1.953]],["name/80",[3,38.544]],["parent/80",[82,1.953]],["name/81",[4,38.544]],["parent/81",[82,1.953]],["name/82",[84,38.544]],["parent/82",[82,1.953]],["name/83",[85,38.544]],["parent/83",[82,1.953]],["name/84",[86,38.544]],["parent/84",[82,1.953]],["name/85",[5,38.544]],["parent/85",[82,1.953]],["name/86",[87,38.544]],["parent/86",[82,1.953]],["name/87",[88,38.544]],["parent/87",[82,1.953]],["name/88",[89,38.544]],["parent/88",[82,1.953]],["name/89",[90,38.544]],["parent/89",[82,1.953]],["name/90",[91,38.544]],["parent/90",[82,1.953]],["name/91",[92,38.544]],["parent/91",[82,1.953]],["name/92",[93,43.652]],["parent/92",[82,1.953]],["name/93",[94,15.72]],["parent/93",[1,3.493]],["name/94",[2,35.179]],["parent/94",[94,1.561]],["name/95",[95,43.652]],["parent/95",[94,1.561]],["name/96",[84,38.544]],["parent/96",[94,1.561]],["name/97",[85,38.544]],["parent/97",[94,1.561]],["name/98",[86,38.544]],["parent/98",[94,1.561]],["name/99",[96,43.652]],["parent/99",[94,1.561]],["name/100",[87,38.544]],["parent/100",[94,1.561]],["name/101",[88,38.544]],["parent/101",[94,1.561]],["name/102",[89,38.544]],["parent/102",[94,1.561]],["name/103",[90,38.544]],["parent/103",[94,1.561]],["name/104",[91,38.544]],["parent/104",[94,1.561]],["name/105",[92,38.544]],["parent/105",[94,1.561]],["name/106",[97,43.652]],["parent/106",[94,1.561]],["name/107",[98,43.652]],["parent/107",[94,1.561]],["name/108",[99,43.652]],["parent/108",[94,1.561]],["name/109",[100,43.652]],["parent/109",[94,1.561]],["name/110",[101,43.652]],["parent/110",[94,1.561]],["name/111",[102,43.652]],["parent/111",[94,1.561]],["name/112",[103,43.652]],["parent/112",[94,1.561]],["name/113",[104,43.652]],["parent/113",[94,1.561]],["name/114",[105,43.652]],["parent/114",[94,1.561]],["name/115",[106,43.652]],["parent/115",[94,1.561]],["name/116",[107,43.652]],["parent/116",[94,1.561]]],"invertedIndex":[["",{"_index":1,"name":{},"parent":{"0":{},"77":{},"93":{}}}],["__type",{"_index":63,"name":{"60":{}},"parent":{}}],["_webout.json",{"_index":43,"name":{"39":{}},"parent":{}}],["apploc",{"_index":57,"name":{"54":{}},"parent":{}}],["asyncforeach",{"_index":7,"name":{"6":{}},"parent":{}}],["checksession",{"_index":102,"name":{"111":{}},"parent":{}}],["comparetimestamps",{"_index":17,"name":{"15":{}},"parent":{}}],["constructor",{"_index":2,"name":{"1":{},"78":{},"94":{}},"parent":{}}],["context",{"_index":22,"name":{"20":{}},"parent":{}}],["contextname",{"_index":59,"name":{"57":{}},"parent":{}}],["converttocsv",{"_index":18,"name":{"16":{}},"parent":{}}],["createdby",{"_index":26,"name":{"23":{},"44":{}},"parent":{}}],["createfolder",{"_index":87,"name":{"86":{},"100":{}},"parent":{}}],["createjobdefinition",{"_index":88,"name":{"87":{},"101":{}},"parent":{}}],["createsession",{"_index":86,"name":{"84":{},"98":{}},"parent":{}}],["csrftoken",{"_index":28,"name":{"25":{}},"parent":{}}],["data",{"_index":70,"name":{"65":{}},"parent":{}}],["debug",{"_index":58,"name":{"56":{}},"parent":{}}],["deleteclient",{"_index":92,"name":{"91":{},"105":{}},"parent":{}}],["deployservicepack",{"_index":106,"name":{"115":{}},"parent":{}}],["executejob",{"_index":93,"name":{"92":{}},"parent":{}}],["executescript",{"_index":5,"name":{"4":{},"85":{}},"parent":{}}],["executescriptsas9",{"_index":95,"name":{"95":{}},"parent":{}}],["executescriptsasviya",{"_index":96,"name":{"99":{}},"parent":{}}],["folder",{"_index":39,"name":{"34":{}},"parent":{}}],["generatedcode",{"_index":14,"name":{"12":{}},"parent":{}}],["getaccesstoken",{"_index":90,"name":{"89":{},"103":{}},"parent":{}}],["getallcontexts",{"_index":84,"name":{"82":{},"96":{}},"parent":{}}],["getapplocmap",{"_index":83,"name":{"79":{}},"parent":{}}],["getauthcode",{"_index":89,"name":{"88":{},"102":{}},"parent":{}}],["getconfig",{"_index":3,"name":{"2":{},"80":{}},"parent":{}}],["getcsrf",{"_index":99,"name":{"108":{}},"parent":{}}],["getexecutablecontexts",{"_index":85,"name":{"83":{},"97":{}},"parent":{}}],["getsasjsconfig",{"_index":97,"name":{"106":{}},"parent":{}}],["getsasrequests",{"_index":107,"name":{"116":{}},"parent":{}}],["getusername",{"_index":98,"name":{"107":{}},"parent":{}}],["headername",{"_index":29,"name":{"26":{}},"parent":{}}],["href",{"_index":36,"name":{"31":{}},"parent":{}}],["id",{"_index":25,"name":{"22":{},"35":{},"41":{},"68":{}},"parent":{}}],["isauthorizeformrequired",{"_index":19,"name":{"17":{}},"parent":{}}],["isloginrequired",{"_index":20,"name":{"18":{}},"parent":{}}],["isloginsuccess",{"_index":21,"name":{"19":{}},"parent":{}}],["job",{"_index":45,"name":{"40":{}},"parent":{}}],["jobresult",{"_index":42,"name":{"38":{}},"parent":{}}],["link",{"_index":32,"name":{"28":{}},"parent":{}}],["links",{"_index":41,"name":{"37":{},"45":{}},"parent":{}}],["logfile",{"_index":15,"name":{"13":{}},"parent":{}}],["login",{"_index":103,"name":{"112":{}},"parent":{}}],["logout",{"_index":104,"name":{"113":{}},"parent":{}}],["makerequest",{"_index":74,"name":{"69":{}},"parent":{}}],["method",{"_index":33,"name":{"29":{}},"parent":{}}],["name",{"_index":23,"name":{"21":{},"42":{}},"parent":{}}],["needsretry",{"_index":75,"name":{"70":{}},"parent":{}}],["params",{"_index":71,"name":{"66":{}},"parent":{}}],["parseandsubmitauthorizeform",{"_index":76,"name":{"71":{}},"parent":{}}],["parsegeneratedcode",{"_index":77,"name":{"72":{}},"parent":{}}],["parsesasviyalog",{"_index":79,"name":{"74":{}},"parent":{}}],["parsesourcecode",{"_index":78,"name":{"73":{}},"parent":{}}],["pathsas9",{"_index":55,"name":{"52":{}},"parent":{}}],["pathsasviya",{"_index":56,"name":{"53":{}},"parent":{}}],["promise",{"_index":65,"name":{"61":{}},"parent":{}}],["refreshtokens",{"_index":91,"name":{"90":{},"104":{}},"parent":{}}],["reject",{"_index":68,"name":{"63":{}},"parent":{}}],["rel",{"_index":35,"name":{"30":{}},"parent":{}}],["request",{"_index":105,"name":{"114":{}},"parent":{}}],["requestpromise",{"_index":61,"name":{"59":{}},"parent":{}}],["resolve",{"_index":67,"name":{"62":{}},"parent":{}}],["results",{"_index":47,"name":{"46":{}},"parent":{}}],["sas9",{"_index":51,"name":{"49":{}},"parent":{}}],["sas9apiclient",{"_index":0,"name":{"0":{}},"parent":{"1":{},"2":{},"3":{},"4":{}}}],["sasjob",{"_index":69,"name":{"64":{}},"parent":{}}],["sasjs",{"_index":94,"name":{"93":{}},"parent":{"94":{},"95":{},"96":{},"97":{},"98":{},"99":{},"100":{},"101":{},"102":{},"103":{},"104":{},"105":{},"106":{},"107":{},"108":{},"109":{},"110":{},"111":{},"112":{},"113":{},"114":{},"115":{},"116":{}}}],["sasjsconfig",{"_index":52,"name":{"50":{}},"parent":{}}],["sasjsrequest",{"_index":9,"name":{"8":{}},"parent":{}}],["sasjswaitingrequest",{"_index":60,"name":{"58":{}},"parent":{}}],["sasviya",{"_index":49,"name":{"48":{}},"parent":{}}],["sasviyaapiclient",{"_index":82,"name":{"77":{}},"parent":{"78":{},"79":{},"80":{},"81":{},"82":{},"83":{},"84":{},"85":{},"86":{},"87":{},"88":{},"89":{},"90":{},"91":{},"92":{}}}],["saswork",{"_index":16,"name":{"14":{}},"parent":{}}],["serialize",{"_index":80,"name":{"75":{}},"parent":{}}],["servertype",{"_index":48,"name":{"47":{},"55":{}},"parent":{}}],["serverurl",{"_index":53,"name":{"51":{}},"parent":{}}],["servicelink",{"_index":10,"name":{"9":{}},"parent":{}}],["session",{"_index":72,"name":{"67":{}},"parent":{}}],["setconfig",{"_index":4,"name":{"3":{},"81":{}},"parent":{}}],["setdebugstate",{"_index":101,"name":{"110":{}},"parent":{}}],["setsasjsconfig",{"_index":100,"name":{"109":{}},"parent":{}}],["sourcecode",{"_index":13,"name":{"11":{}},"parent":{}}],["splitchunks",{"_index":81,"name":{"76":{}},"parent":{}}],["timestamp",{"_index":12,"name":{"10":{}},"parent":{}}],["type",{"_index":38,"name":{"33":{}},"parent":{}}],["types",{"_index":8,"name":{"7":{}},"parent":{"8":{},"20":{},"25":{},"28":{},"34":{},"38":{},"40":{},"47":{},"50":{},"58":{},"67":{}}}],["types.context",{"_index":24,"name":{},"parent":{"21":{},"22":{},"23":{},"24":{}}}],["types.csrftoken",{"_index":30,"name":{},"parent":{"26":{},"27":{}}}],["types.folder",{"_index":40,"name":{},"parent":{"35":{},"36":{},"37":{}}}],["types.job",{"_index":46,"name":{},"parent":{"41":{},"42":{},"43":{},"44":{},"45":{},"46":{}}}],["types.jobresult",{"_index":44,"name":{},"parent":{"39":{}}}],["types.link",{"_index":34,"name":{},"parent":{"29":{},"30":{},"31":{},"32":{},"33":{}}}],["types.sasjsconfig",{"_index":54,"name":{},"parent":{"51":{},"52":{},"53":{},"54":{},"55":{},"56":{},"57":{}}}],["types.sasjsrequest",{"_index":11,"name":{},"parent":{"9":{},"10":{},"11":{},"12":{},"13":{},"14":{}}}],["types.sasjswaitingrequest",{"_index":62,"name":{},"parent":{"59":{},"64":{},"65":{},"66":{}}}],["types.sasjswaitingrequest.requestpromise",{"_index":64,"name":{},"parent":{"60":{}}}],["types.sasjswaitingrequest.requestpromise.__type",{"_index":66,"name":{},"parent":{"61":{},"62":{},"63":{}}}],["types.servertype",{"_index":50,"name":{},"parent":{"48":{},"49":{}}}],["types.session",{"_index":73,"name":{},"parent":{"68":{}}}],["uri",{"_index":37,"name":{"32":{},"36":{},"43":{}},"parent":{}}],["utils",{"_index":6,"name":{"5":{}},"parent":{"6":{},"15":{},"16":{},"17":{},"18":{},"19":{},"69":{},"70":{},"71":{},"72":{},"73":{},"74":{},"75":{},"76":{}}}],["value",{"_index":31,"name":{"27":{}},"parent":{}}],["version",{"_index":27,"name":{"24":{}},"parent":{}}]],"pipeline":[]}} \ No newline at end of file +{"kinds":{"1":"Module","4":"Enumeration","16":"Enumeration member","32":"Variable","64":"Function","128":"Class","256":"Interface","512":"Constructor","1024":"Property","2048":"Method","65536":"Type literal"},"rows":[{"id":0,"kind":128,"name":"SAS9ApiClient","url":"classes/reflection-560.reflection-1.sas9apiclient.html","classes":"tsd-kind-class tsd-parent-kind-module","parent":"."},{"id":1,"kind":512,"name":"constructor","url":"classes/reflection-560.reflection-1.sas9apiclient.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"..SAS9ApiClient"},{"id":2,"kind":2048,"name":"getConfig","url":"classes/reflection-560.reflection-1.sas9apiclient.html#getconfig","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SAS9ApiClient"},{"id":3,"kind":2048,"name":"setConfig","url":"classes/reflection-560.reflection-1.sas9apiclient.html#setconfig","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SAS9ApiClient"},{"id":4,"kind":2048,"name":"executeScript","url":"classes/reflection-560.reflection-1.sas9apiclient.html#executescript","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SAS9ApiClient"},{"id":5,"kind":1,"name":"utils","url":"modules/utils.html","classes":"tsd-kind-module"},{"id":6,"kind":64,"name":"asyncForEach","url":"modules/utils.html#asyncforeach","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":7,"kind":1,"name":"types","url":"modules/types.html","classes":"tsd-kind-module"},{"id":8,"kind":256,"name":"SASjsRequest","url":"interfaces/types.sasjsrequest.html","classes":"tsd-kind-interface tsd-parent-kind-module","parent":"types"},{"id":9,"kind":1024,"name":"serviceLink","url":"interfaces/types.sasjsrequest.html#servicelink","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.SASjsRequest"},{"id":10,"kind":1024,"name":"timestamp","url":"interfaces/types.sasjsrequest.html#timestamp","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.SASjsRequest"},{"id":11,"kind":1024,"name":"sourceCode","url":"interfaces/types.sasjsrequest.html#sourcecode","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.SASjsRequest"},{"id":12,"kind":1024,"name":"generatedCode","url":"interfaces/types.sasjsrequest.html#generatedcode","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.SASjsRequest"},{"id":13,"kind":1024,"name":"logFile","url":"interfaces/types.sasjsrequest.html#logfile","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.SASjsRequest"},{"id":14,"kind":1024,"name":"SASWORK","url":"interfaces/types.sasjsrequest.html#saswork","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.SASjsRequest"},{"id":15,"kind":64,"name":"compareTimestamps","url":"modules/utils.html#comparetimestamps","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":16,"kind":64,"name":"convertToCSV","url":"modules/utils.html#converttocsv","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":17,"kind":64,"name":"isAuthorizeFormRequired","url":"modules/utils.html#isauthorizeformrequired","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":18,"kind":64,"name":"isLogInRequired","url":"modules/utils.html#isloginrequired","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":19,"kind":64,"name":"isLogInSuccess","url":"modules/utils.html#isloginsuccess","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":20,"kind":256,"name":"Context","url":"interfaces/types.context.html","classes":"tsd-kind-interface tsd-parent-kind-module","parent":"types"},{"id":21,"kind":1024,"name":"name","url":"interfaces/types.context.html#name","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Context"},{"id":22,"kind":1024,"name":"id","url":"interfaces/types.context.html#id","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Context"},{"id":23,"kind":1024,"name":"createdBy","url":"interfaces/types.context.html#createdby","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Context"},{"id":24,"kind":1024,"name":"version","url":"interfaces/types.context.html#version","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Context"},{"id":25,"kind":256,"name":"CsrfToken","url":"interfaces/types.csrftoken.html","classes":"tsd-kind-interface tsd-parent-kind-module","parent":"types"},{"id":26,"kind":1024,"name":"headerName","url":"interfaces/types.csrftoken.html#headername","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.CsrfToken"},{"id":27,"kind":1024,"name":"value","url":"interfaces/types.csrftoken.html#value","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.CsrfToken"},{"id":28,"kind":256,"name":"Link","url":"interfaces/types.link.html","classes":"tsd-kind-interface tsd-parent-kind-module","parent":"types"},{"id":29,"kind":1024,"name":"method","url":"interfaces/types.link.html#method","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Link"},{"id":30,"kind":1024,"name":"rel","url":"interfaces/types.link.html#rel","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Link"},{"id":31,"kind":1024,"name":"href","url":"interfaces/types.link.html#href","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Link"},{"id":32,"kind":1024,"name":"uri","url":"interfaces/types.link.html#uri","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Link"},{"id":33,"kind":1024,"name":"type","url":"interfaces/types.link.html#type","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Link"},{"id":34,"kind":256,"name":"Folder","url":"interfaces/types.folder.html","classes":"tsd-kind-interface tsd-parent-kind-module","parent":"types"},{"id":35,"kind":1024,"name":"id","url":"interfaces/types.folder.html#id","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Folder"},{"id":36,"kind":1024,"name":"uri","url":"interfaces/types.folder.html#uri","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Folder"},{"id":37,"kind":1024,"name":"links","url":"interfaces/types.folder.html#links","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Folder"},{"id":38,"kind":256,"name":"JobResult","url":"interfaces/types.jobresult.html","classes":"tsd-kind-interface tsd-parent-kind-module","parent":"types"},{"id":39,"kind":1024,"name":"_webout.json","url":"interfaces/types.jobresult.html#_webout_json","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.JobResult"},{"id":40,"kind":256,"name":"Job","url":"interfaces/types.job.html","classes":"tsd-kind-interface tsd-parent-kind-module","parent":"types"},{"id":41,"kind":1024,"name":"id","url":"interfaces/types.job.html#id","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Job"},{"id":42,"kind":1024,"name":"name","url":"interfaces/types.job.html#name","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Job"},{"id":43,"kind":1024,"name":"uri","url":"interfaces/types.job.html#uri","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Job"},{"id":44,"kind":1024,"name":"createdBy","url":"interfaces/types.job.html#createdby","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Job"},{"id":45,"kind":1024,"name":"links","url":"interfaces/types.job.html#links","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Job"},{"id":46,"kind":1024,"name":"results","url":"interfaces/types.job.html#results","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Job"},{"id":47,"kind":1024,"name":"error","url":"interfaces/types.job.html#error","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Job"},{"id":48,"kind":4,"name":"ServerType","url":"enums/types.servertype.html","classes":"tsd-kind-enum tsd-parent-kind-module","parent":"types"},{"id":49,"kind":16,"name":"SASViya","url":"enums/types.servertype.html#sasviya","classes":"tsd-kind-enum-member tsd-parent-kind-enum","parent":"types.ServerType"},{"id":50,"kind":16,"name":"SAS9","url":"enums/types.servertype.html#sas9","classes":"tsd-kind-enum-member tsd-parent-kind-enum","parent":"types.ServerType"},{"id":51,"kind":128,"name":"SASjsConfig","url":"classes/types.sasjsconfig.html","classes":"tsd-kind-class tsd-parent-kind-module","parent":"types"},{"id":52,"kind":1024,"name":"serverUrl","url":"classes/types.sasjsconfig.html#serverurl","classes":"tsd-kind-property tsd-parent-kind-class","parent":"types.SASjsConfig"},{"id":53,"kind":1024,"name":"pathSAS9","url":"classes/types.sasjsconfig.html#pathsas9","classes":"tsd-kind-property tsd-parent-kind-class","parent":"types.SASjsConfig"},{"id":54,"kind":1024,"name":"pathSASViya","url":"classes/types.sasjsconfig.html#pathsasviya","classes":"tsd-kind-property tsd-parent-kind-class","parent":"types.SASjsConfig"},{"id":55,"kind":1024,"name":"appLoc","url":"classes/types.sasjsconfig.html#apploc","classes":"tsd-kind-property tsd-parent-kind-class","parent":"types.SASjsConfig"},{"id":56,"kind":1024,"name":"serverType","url":"classes/types.sasjsconfig.html#servertype","classes":"tsd-kind-property tsd-parent-kind-class","parent":"types.SASjsConfig"},{"id":57,"kind":1024,"name":"debug","url":"classes/types.sasjsconfig.html#debug","classes":"tsd-kind-property tsd-parent-kind-class","parent":"types.SASjsConfig"},{"id":58,"kind":1024,"name":"contextName","url":"classes/types.sasjsconfig.html#contextname","classes":"tsd-kind-property tsd-parent-kind-class","parent":"types.SASjsConfig"},{"id":59,"kind":1024,"name":"useComputeApi","url":"classes/types.sasjsconfig.html#usecomputeapi","classes":"tsd-kind-property tsd-parent-kind-class","parent":"types.SASjsConfig"},{"id":60,"kind":256,"name":"SASjsWaitingRequest","url":"interfaces/types.sasjswaitingrequest.html","classes":"tsd-kind-interface tsd-parent-kind-module","parent":"types"},{"id":61,"kind":1024,"name":"requestPromise","url":"interfaces/types.sasjswaitingrequest.html#requestpromise","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.SASjsWaitingRequest"},{"id":62,"kind":65536,"name":"__type","url":"interfaces/types.sasjswaitingrequest.html#requestpromise.__type","classes":"tsd-kind-type-literal tsd-parent-kind-property","parent":"types.SASjsWaitingRequest.requestPromise"},{"id":63,"kind":32,"name":"promise","url":"interfaces/types.sasjswaitingrequest.html#requestpromise.__type.promise","classes":"tsd-kind-variable tsd-parent-kind-type-literal","parent":"types.SASjsWaitingRequest.requestPromise.__type"},{"id":64,"kind":32,"name":"resolve","url":"interfaces/types.sasjswaitingrequest.html#requestpromise.__type.resolve","classes":"tsd-kind-variable tsd-parent-kind-type-literal","parent":"types.SASjsWaitingRequest.requestPromise.__type"},{"id":65,"kind":32,"name":"reject","url":"interfaces/types.sasjswaitingrequest.html#requestpromise.__type.reject","classes":"tsd-kind-variable tsd-parent-kind-type-literal","parent":"types.SASjsWaitingRequest.requestPromise.__type"},{"id":66,"kind":1024,"name":"SASjob","url":"interfaces/types.sasjswaitingrequest.html#sasjob","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.SASjsWaitingRequest"},{"id":67,"kind":1024,"name":"data","url":"interfaces/types.sasjswaitingrequest.html#data","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.SASjsWaitingRequest"},{"id":68,"kind":1024,"name":"config","url":"interfaces/types.sasjswaitingrequest.html#config","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.SASjsWaitingRequest"},{"id":69,"kind":256,"name":"Session","url":"interfaces/types.session.html","classes":"tsd-kind-interface tsd-parent-kind-module","parent":"types"},{"id":70,"kind":1024,"name":"id","url":"interfaces/types.session.html#id","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Session"},{"id":71,"kind":1024,"name":"state","url":"interfaces/types.session.html#state","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Session"},{"id":72,"kind":1024,"name":"links","url":"interfaces/types.session.html#links","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.Session"},{"id":73,"kind":64,"name":"makeRequest","url":"modules/utils.html#makerequest","classes":"tsd-kind-function tsd-parent-kind-module tsd-has-type-parameter","parent":"utils"},{"id":74,"kind":64,"name":"needsRetry","url":"modules/utils.html#needsretry","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":75,"kind":64,"name":"parseAndSubmitAuthorizeForm","url":"modules/utils.html#parseandsubmitauthorizeform","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":76,"kind":64,"name":"parseGeneratedCode","url":"modules/utils.html#parsegeneratedcode","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":77,"kind":64,"name":"parseSourceCode","url":"modules/utils.html#parsesourcecode","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":78,"kind":64,"name":"parseSasViyaLog","url":"modules/utils.html#parsesasviyalog","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":79,"kind":64,"name":"serialize","url":"modules/utils.html#serialize","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":80,"kind":64,"name":"splitChunks","url":"modules/utils.html#splitchunks","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":81,"kind":256,"name":"JobDefinition","url":"interfaces/types.jobdefinition.html","classes":"tsd-kind-interface tsd-parent-kind-module","parent":"types"},{"id":82,"kind":1024,"name":"code","url":"interfaces/types.jobdefinition.html#code","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"types.JobDefinition"},{"id":83,"kind":64,"name":"formatDataForRequest","url":"modules/utils.html#formatdataforrequest","classes":"tsd-kind-function tsd-parent-kind-module","parent":"utils"},{"id":84,"kind":128,"name":"SessionManager","url":"classes/reflection-560.reflection-1.sessionmanager.html","classes":"tsd-kind-class tsd-parent-kind-module","parent":"."},{"id":85,"kind":512,"name":"constructor","url":"classes/reflection-560.reflection-1.sessionmanager.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"..SessionManager"},{"id":86,"kind":2048,"name":"getSession","url":"classes/reflection-560.reflection-1.sessionmanager.html#getsession","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SessionManager"},{"id":87,"kind":128,"name":"SASViyaApiClient","url":"classes/reflection-560.reflection-1.sasviyaapiclient.html","classes":"tsd-kind-class tsd-parent-kind-module","parent":"."},{"id":88,"kind":512,"name":"constructor","url":"classes/reflection-560.reflection-1.sasviyaapiclient.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":89,"kind":2048,"name":"getAppLocMap","url":"classes/reflection-560.reflection-1.sasviyaapiclient.html#getapplocmap","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":90,"kind":2048,"name":"getConfig","url":"classes/reflection-560.reflection-1.sasviyaapiclient.html#getconfig","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":91,"kind":2048,"name":"setConfig","url":"classes/reflection-560.reflection-1.sasviyaapiclient.html#setconfig","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":92,"kind":2048,"name":"getAllContexts","url":"classes/reflection-560.reflection-1.sasviyaapiclient.html#getallcontexts","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":93,"kind":2048,"name":"getExecutableContexts","url":"classes/reflection-560.reflection-1.sasviyaapiclient.html#getexecutablecontexts","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":94,"kind":2048,"name":"createSession","url":"classes/reflection-560.reflection-1.sasviyaapiclient.html#createsession","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":95,"kind":2048,"name":"executeScript","url":"classes/reflection-560.reflection-1.sasviyaapiclient.html#executescript","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":96,"kind":2048,"name":"createFolder","url":"classes/reflection-560.reflection-1.sasviyaapiclient.html#createfolder","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":97,"kind":2048,"name":"createJobDefinition","url":"classes/reflection-560.reflection-1.sasviyaapiclient.html#createjobdefinition","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":98,"kind":2048,"name":"getAuthCode","url":"classes/reflection-560.reflection-1.sasviyaapiclient.html#getauthcode","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":99,"kind":2048,"name":"getAccessToken","url":"classes/reflection-560.reflection-1.sasviyaapiclient.html#getaccesstoken","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":100,"kind":2048,"name":"refreshTokens","url":"classes/reflection-560.reflection-1.sasviyaapiclient.html#refreshtokens","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":101,"kind":2048,"name":"deleteClient","url":"classes/reflection-560.reflection-1.sasviyaapiclient.html#deleteclient","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":102,"kind":2048,"name":"executeComputeJob","url":"classes/reflection-560.reflection-1.sasviyaapiclient.html#executecomputejob","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":103,"kind":2048,"name":"executeJob","url":"classes/reflection-560.reflection-1.sasviyaapiclient.html#executejob","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":104,"kind":2048,"name":"setCsrfToken","url":"classes/reflection-560.reflection-1.sasviyaapiclient.html#setcsrftoken","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASViyaApiClient"},{"id":105,"kind":128,"name":"SASjs","url":"classes/reflection-560.reflection-1.sasjs.html","classes":"tsd-kind-class tsd-parent-kind-module","parent":"."},{"id":106,"kind":512,"name":"constructor","url":"classes/reflection-560.reflection-1.sasjs.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"..SASjs"},{"id":107,"kind":2048,"name":"executeScriptSAS9","url":"classes/reflection-560.reflection-1.sasjs.html#executescriptsas9","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":108,"kind":2048,"name":"getAllContexts","url":"classes/reflection-560.reflection-1.sasjs.html#getallcontexts","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":109,"kind":2048,"name":"getExecutableContexts","url":"classes/reflection-560.reflection-1.sasjs.html#getexecutablecontexts","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":110,"kind":2048,"name":"createSession","url":"classes/reflection-560.reflection-1.sasjs.html#createsession","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":111,"kind":2048,"name":"executeScriptSASViya","url":"classes/reflection-560.reflection-1.sasjs.html#executescriptsasviya","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":112,"kind":2048,"name":"createFolder","url":"classes/reflection-560.reflection-1.sasjs.html#createfolder","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":113,"kind":2048,"name":"createJobDefinition","url":"classes/reflection-560.reflection-1.sasjs.html#createjobdefinition","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":114,"kind":2048,"name":"getAuthCode","url":"classes/reflection-560.reflection-1.sasjs.html#getauthcode","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":115,"kind":2048,"name":"getAccessToken","url":"classes/reflection-560.reflection-1.sasjs.html#getaccesstoken","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":116,"kind":2048,"name":"refreshTokens","url":"classes/reflection-560.reflection-1.sasjs.html#refreshtokens","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":117,"kind":2048,"name":"deleteClient","url":"classes/reflection-560.reflection-1.sasjs.html#deleteclient","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":118,"kind":2048,"name":"getSasjsConfig","url":"classes/reflection-560.reflection-1.sasjs.html#getsasjsconfig","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":119,"kind":2048,"name":"getUserName","url":"classes/reflection-560.reflection-1.sasjs.html#getusername","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":120,"kind":2048,"name":"getCsrf","url":"classes/reflection-560.reflection-1.sasjs.html#getcsrf","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":121,"kind":2048,"name":"setSASjsConfig","url":"classes/reflection-560.reflection-1.sasjs.html#setsasjsconfig","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":122,"kind":2048,"name":"setDebugState","url":"classes/reflection-560.reflection-1.sasjs.html#setdebugstate","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":123,"kind":2048,"name":"checkSession","url":"classes/reflection-560.reflection-1.sasjs.html#checksession","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":124,"kind":2048,"name":"logIn","url":"classes/reflection-560.reflection-1.sasjs.html#login","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":125,"kind":2048,"name":"logOut","url":"classes/reflection-560.reflection-1.sasjs.html#logout","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":126,"kind":2048,"name":"request","url":"classes/reflection-560.reflection-1.sasjs.html#request","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":127,"kind":2048,"name":"deployServicePack","url":"classes/reflection-560.reflection-1.sasjs.html#deployservicepack","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"},{"id":128,"kind":2048,"name":"getSasRequests","url":"classes/reflection-560.reflection-1.sasjs.html#getsasrequests","classes":"tsd-kind-method tsd-parent-kind-class","parent":"..SASjs"}],"index":{"version":"2.3.8","fields":["name","parent"],"fieldVectors":[["name/0",[0,31.628]],["parent/0",[1,3.342]],["name/1",[2,33.635]],["parent/1",[0,3.143]],["name/2",[3,39.512]],["parent/2",[0,3.143]],["name/3",[4,39.512]],["parent/3",[0,3.143]],["name/4",[5,39.512]],["parent/4",[0,3.143]],["name/5",[6,20.642]],["parent/5",[]],["name/6",[7,44.621]],["parent/6",[6,2.051]],["name/7",[8,22.648]],["parent/7",[]],["name/8",[9,44.621]],["parent/8",[8,2.25]],["name/9",[10,44.621]],["parent/9",[11,2.977]],["name/10",[12,44.621]],["parent/10",[11,2.977]],["name/11",[13,44.621]],["parent/11",[11,2.977]],["name/12",[14,44.621]],["parent/12",[11,2.977]],["name/13",[15,44.621]],["parent/13",[11,2.977]],["name/14",[16,44.621]],["parent/14",[11,2.977]],["name/15",[17,44.621]],["parent/15",[6,2.051]],["name/16",[18,44.621]],["parent/16",[6,2.051]],["name/17",[19,44.621]],["parent/17",[6,2.051]],["name/18",[20,44.621]],["parent/18",[6,2.051]],["name/19",[21,44.621]],["parent/19",[6,2.051]],["name/20",[22,44.621]],["parent/20",[8,2.25]],["name/21",[23,39.512]],["parent/21",[24,3.342]],["name/22",[25,33.635]],["parent/22",[24,3.342]],["name/23",[26,39.512]],["parent/23",[24,3.342]],["name/24",[27,44.621]],["parent/24",[24,3.342]],["name/25",[28,44.621]],["parent/25",[8,2.25]],["name/26",[29,44.621]],["parent/26",[30,3.926]],["name/27",[31,44.621]],["parent/27",[30,3.926]],["name/28",[32,44.621]],["parent/28",[8,2.25]],["name/29",[33,44.621]],["parent/29",[34,3.143]],["name/30",[35,44.621]],["parent/30",[34,3.143]],["name/31",[36,44.621]],["parent/31",[34,3.143]],["name/32",[37,36.148]],["parent/32",[34,3.143]],["name/33",[38,44.621]],["parent/33",[34,3.143]],["name/34",[39,44.621]],["parent/34",[8,2.25]],["name/35",[25,33.635]],["parent/35",[40,3.592]],["name/36",[37,36.148]],["parent/36",[40,3.592]],["name/37",[41,36.148]],["parent/37",[40,3.592]],["name/38",[42,44.621]],["parent/38",[8,2.25]],["name/39",[43,44.621]],["parent/39",[44,4.434]],["name/40",[45,44.621]],["parent/40",[8,2.25]],["name/41",[25,33.635]],["parent/41",[46,2.834]],["name/42",[23,39.512]],["parent/42",[46,2.834]],["name/43",[37,36.148]],["parent/43",[46,2.834]],["name/44",[26,39.512]],["parent/44",[46,2.834]],["name/45",[41,36.148]],["parent/45",[46,2.834]],["name/46",[47,44.621]],["parent/46",[46,2.834]],["name/47",[48,44.621]],["parent/47",[46,2.834]],["name/48",[49,39.512]],["parent/48",[8,2.25]],["name/49",[50,44.621]],["parent/49",[51,3.926]],["name/50",[52,44.621]],["parent/50",[51,3.926]],["name/51",[53,44.621]],["parent/51",[8,2.25]],["name/52",[54,44.621]],["parent/52",[55,2.71]],["name/53",[56,44.621]],["parent/53",[55,2.71]],["name/54",[57,44.621]],["parent/54",[55,2.71]],["name/55",[58,44.621]],["parent/55",[55,2.71]],["name/56",[49,39.512]],["parent/56",[55,2.71]],["name/57",[59,44.621]],["parent/57",[55,2.71]],["name/58",[60,44.621]],["parent/58",[55,2.71]],["name/59",[61,44.621]],["parent/59",[55,2.71]],["name/60",[62,44.621]],["parent/60",[8,2.25]],["name/61",[63,44.621]],["parent/61",[64,3.342]],["name/62",[65,44.621]],["parent/62",[66,4.434]],["name/63",[67,44.621]],["parent/63",[68,3.592]],["name/64",[69,44.621]],["parent/64",[68,3.592]],["name/65",[70,44.621]],["parent/65",[68,3.592]],["name/66",[71,44.621]],["parent/66",[64,3.342]],["name/67",[72,44.621]],["parent/67",[64,3.342]],["name/68",[73,44.621]],["parent/68",[64,3.342]],["name/69",[74,44.621]],["parent/69",[8,2.25]],["name/70",[25,33.635]],["parent/70",[75,3.592]],["name/71",[76,44.621]],["parent/71",[75,3.592]],["name/72",[41,36.148]],["parent/72",[75,3.592]],["name/73",[77,44.621]],["parent/73",[6,2.051]],["name/74",[78,44.621]],["parent/74",[6,2.051]],["name/75",[79,44.621]],["parent/75",[6,2.051]],["name/76",[80,44.621]],["parent/76",[6,2.051]],["name/77",[81,44.621]],["parent/77",[6,2.051]],["name/78",[82,44.621]],["parent/78",[6,2.051]],["name/79",[83,44.621]],["parent/79",[6,2.051]],["name/80",[84,44.621]],["parent/80",[6,2.051]],["name/81",[85,44.621]],["parent/81",[8,2.25]],["name/82",[86,44.621]],["parent/82",[87,4.434]],["name/83",[88,44.621]],["parent/83",[6,2.051]],["name/84",[89,36.148]],["parent/84",[1,3.342]],["name/85",[2,33.635]],["parent/85",[89,3.592]],["name/86",[90,44.621]],["parent/86",[89,3.592]],["name/87",[91,19.498]],["parent/87",[1,3.342]],["name/88",[2,33.635]],["parent/88",[91,1.937]],["name/89",[92,44.621]],["parent/89",[91,1.937]],["name/90",[3,39.512]],["parent/90",[91,1.937]],["name/91",[4,39.512]],["parent/91",[91,1.937]],["name/92",[93,39.512]],["parent/92",[91,1.937]],["name/93",[94,39.512]],["parent/93",[91,1.937]],["name/94",[95,39.512]],["parent/94",[91,1.937]],["name/95",[5,39.512]],["parent/95",[91,1.937]],["name/96",[96,39.512]],["parent/96",[91,1.937]],["name/97",[97,39.512]],["parent/97",[91,1.937]],["name/98",[98,39.512]],["parent/98",[91,1.937]],["name/99",[99,39.512]],["parent/99",[91,1.937]],["name/100",[100,39.512]],["parent/100",[91,1.937]],["name/101",[101,39.512]],["parent/101",[91,1.937]],["name/102",[102,44.621]],["parent/102",[91,1.937]],["name/103",[103,44.621]],["parent/103",[91,1.937]],["name/104",[104,44.621]],["parent/104",[91,1.937]],["name/105",[105,16.689]],["parent/105",[1,3.342]],["name/106",[2,33.635]],["parent/106",[105,1.658]],["name/107",[106,44.621]],["parent/107",[105,1.658]],["name/108",[93,39.512]],["parent/108",[105,1.658]],["name/109",[94,39.512]],["parent/109",[105,1.658]],["name/110",[95,39.512]],["parent/110",[105,1.658]],["name/111",[107,44.621]],["parent/111",[105,1.658]],["name/112",[96,39.512]],["parent/112",[105,1.658]],["name/113",[97,39.512]],["parent/113",[105,1.658]],["name/114",[98,39.512]],["parent/114",[105,1.658]],["name/115",[99,39.512]],["parent/115",[105,1.658]],["name/116",[100,39.512]],["parent/116",[105,1.658]],["name/117",[101,39.512]],["parent/117",[105,1.658]],["name/118",[108,44.621]],["parent/118",[105,1.658]],["name/119",[109,44.621]],["parent/119",[105,1.658]],["name/120",[110,44.621]],["parent/120",[105,1.658]],["name/121",[111,44.621]],["parent/121",[105,1.658]],["name/122",[112,44.621]],["parent/122",[105,1.658]],["name/123",[113,44.621]],["parent/123",[105,1.658]],["name/124",[114,44.621]],["parent/124",[105,1.658]],["name/125",[115,44.621]],["parent/125",[105,1.658]],["name/126",[116,44.621]],["parent/126",[105,1.658]],["name/127",[117,44.621]],["parent/127",[105,1.658]],["name/128",[118,44.621]],["parent/128",[105,1.658]]],"invertedIndex":[["",{"_index":1,"name":{},"parent":{"0":{},"84":{},"87":{},"105":{}}}],["__type",{"_index":65,"name":{"62":{}},"parent":{}}],["_webout.json",{"_index":43,"name":{"39":{}},"parent":{}}],["apploc",{"_index":58,"name":{"55":{}},"parent":{}}],["asyncforeach",{"_index":7,"name":{"6":{}},"parent":{}}],["checksession",{"_index":113,"name":{"123":{}},"parent":{}}],["code",{"_index":86,"name":{"82":{}},"parent":{}}],["comparetimestamps",{"_index":17,"name":{"15":{}},"parent":{}}],["config",{"_index":73,"name":{"68":{}},"parent":{}}],["constructor",{"_index":2,"name":{"1":{},"85":{},"88":{},"106":{}},"parent":{}}],["context",{"_index":22,"name":{"20":{}},"parent":{}}],["contextname",{"_index":60,"name":{"58":{}},"parent":{}}],["converttocsv",{"_index":18,"name":{"16":{}},"parent":{}}],["createdby",{"_index":26,"name":{"23":{},"44":{}},"parent":{}}],["createfolder",{"_index":96,"name":{"96":{},"112":{}},"parent":{}}],["createjobdefinition",{"_index":97,"name":{"97":{},"113":{}},"parent":{}}],["createsession",{"_index":95,"name":{"94":{},"110":{}},"parent":{}}],["csrftoken",{"_index":28,"name":{"25":{}},"parent":{}}],["data",{"_index":72,"name":{"67":{}},"parent":{}}],["debug",{"_index":59,"name":{"57":{}},"parent":{}}],["deleteclient",{"_index":101,"name":{"101":{},"117":{}},"parent":{}}],["deployservicepack",{"_index":117,"name":{"127":{}},"parent":{}}],["error",{"_index":48,"name":{"47":{}},"parent":{}}],["executecomputejob",{"_index":102,"name":{"102":{}},"parent":{}}],["executejob",{"_index":103,"name":{"103":{}},"parent":{}}],["executescript",{"_index":5,"name":{"4":{},"95":{}},"parent":{}}],["executescriptsas9",{"_index":106,"name":{"107":{}},"parent":{}}],["executescriptsasviya",{"_index":107,"name":{"111":{}},"parent":{}}],["folder",{"_index":39,"name":{"34":{}},"parent":{}}],["formatdataforrequest",{"_index":88,"name":{"83":{}},"parent":{}}],["generatedcode",{"_index":14,"name":{"12":{}},"parent":{}}],["getaccesstoken",{"_index":99,"name":{"99":{},"115":{}},"parent":{}}],["getallcontexts",{"_index":93,"name":{"92":{},"108":{}},"parent":{}}],["getapplocmap",{"_index":92,"name":{"89":{}},"parent":{}}],["getauthcode",{"_index":98,"name":{"98":{},"114":{}},"parent":{}}],["getconfig",{"_index":3,"name":{"2":{},"90":{}},"parent":{}}],["getcsrf",{"_index":110,"name":{"120":{}},"parent":{}}],["getexecutablecontexts",{"_index":94,"name":{"93":{},"109":{}},"parent":{}}],["getsasjsconfig",{"_index":108,"name":{"118":{}},"parent":{}}],["getsasrequests",{"_index":118,"name":{"128":{}},"parent":{}}],["getsession",{"_index":90,"name":{"86":{}},"parent":{}}],["getusername",{"_index":109,"name":{"119":{}},"parent":{}}],["headername",{"_index":29,"name":{"26":{}},"parent":{}}],["href",{"_index":36,"name":{"31":{}},"parent":{}}],["id",{"_index":25,"name":{"22":{},"35":{},"41":{},"70":{}},"parent":{}}],["isauthorizeformrequired",{"_index":19,"name":{"17":{}},"parent":{}}],["isloginrequired",{"_index":20,"name":{"18":{}},"parent":{}}],["isloginsuccess",{"_index":21,"name":{"19":{}},"parent":{}}],["job",{"_index":45,"name":{"40":{}},"parent":{}}],["jobdefinition",{"_index":85,"name":{"81":{}},"parent":{}}],["jobresult",{"_index":42,"name":{"38":{}},"parent":{}}],["link",{"_index":32,"name":{"28":{}},"parent":{}}],["links",{"_index":41,"name":{"37":{},"45":{},"72":{}},"parent":{}}],["logfile",{"_index":15,"name":{"13":{}},"parent":{}}],["login",{"_index":114,"name":{"124":{}},"parent":{}}],["logout",{"_index":115,"name":{"125":{}},"parent":{}}],["makerequest",{"_index":77,"name":{"73":{}},"parent":{}}],["method",{"_index":33,"name":{"29":{}},"parent":{}}],["name",{"_index":23,"name":{"21":{},"42":{}},"parent":{}}],["needsretry",{"_index":78,"name":{"74":{}},"parent":{}}],["parseandsubmitauthorizeform",{"_index":79,"name":{"75":{}},"parent":{}}],["parsegeneratedcode",{"_index":80,"name":{"76":{}},"parent":{}}],["parsesasviyalog",{"_index":82,"name":{"78":{}},"parent":{}}],["parsesourcecode",{"_index":81,"name":{"77":{}},"parent":{}}],["pathsas9",{"_index":56,"name":{"53":{}},"parent":{}}],["pathsasviya",{"_index":57,"name":{"54":{}},"parent":{}}],["promise",{"_index":67,"name":{"63":{}},"parent":{}}],["refreshtokens",{"_index":100,"name":{"100":{},"116":{}},"parent":{}}],["reject",{"_index":70,"name":{"65":{}},"parent":{}}],["rel",{"_index":35,"name":{"30":{}},"parent":{}}],["request",{"_index":116,"name":{"126":{}},"parent":{}}],["requestpromise",{"_index":63,"name":{"61":{}},"parent":{}}],["resolve",{"_index":69,"name":{"64":{}},"parent":{}}],["results",{"_index":47,"name":{"46":{}},"parent":{}}],["sas9",{"_index":52,"name":{"50":{}},"parent":{}}],["sas9apiclient",{"_index":0,"name":{"0":{}},"parent":{"1":{},"2":{},"3":{},"4":{}}}],["sasjob",{"_index":71,"name":{"66":{}},"parent":{}}],["sasjs",{"_index":105,"name":{"105":{}},"parent":{"106":{},"107":{},"108":{},"109":{},"110":{},"111":{},"112":{},"113":{},"114":{},"115":{},"116":{},"117":{},"118":{},"119":{},"120":{},"121":{},"122":{},"123":{},"124":{},"125":{},"126":{},"127":{},"128":{}}}],["sasjsconfig",{"_index":53,"name":{"51":{}},"parent":{}}],["sasjsrequest",{"_index":9,"name":{"8":{}},"parent":{}}],["sasjswaitingrequest",{"_index":62,"name":{"60":{}},"parent":{}}],["sasviya",{"_index":50,"name":{"49":{}},"parent":{}}],["sasviyaapiclient",{"_index":91,"name":{"87":{}},"parent":{"88":{},"89":{},"90":{},"91":{},"92":{},"93":{},"94":{},"95":{},"96":{},"97":{},"98":{},"99":{},"100":{},"101":{},"102":{},"103":{},"104":{}}}],["saswork",{"_index":16,"name":{"14":{}},"parent":{}}],["serialize",{"_index":83,"name":{"79":{}},"parent":{}}],["servertype",{"_index":49,"name":{"48":{},"56":{}},"parent":{}}],["serverurl",{"_index":54,"name":{"52":{}},"parent":{}}],["servicelink",{"_index":10,"name":{"9":{}},"parent":{}}],["session",{"_index":74,"name":{"69":{}},"parent":{}}],["sessionmanager",{"_index":89,"name":{"84":{}},"parent":{"85":{},"86":{}}}],["setconfig",{"_index":4,"name":{"3":{},"91":{}},"parent":{}}],["setcsrftoken",{"_index":104,"name":{"104":{}},"parent":{}}],["setdebugstate",{"_index":112,"name":{"122":{}},"parent":{}}],["setsasjsconfig",{"_index":111,"name":{"121":{}},"parent":{}}],["sourcecode",{"_index":13,"name":{"11":{}},"parent":{}}],["splitchunks",{"_index":84,"name":{"80":{}},"parent":{}}],["state",{"_index":76,"name":{"71":{}},"parent":{}}],["timestamp",{"_index":12,"name":{"10":{}},"parent":{}}],["type",{"_index":38,"name":{"33":{}},"parent":{}}],["types",{"_index":8,"name":{"7":{}},"parent":{"8":{},"20":{},"25":{},"28":{},"34":{},"38":{},"40":{},"48":{},"51":{},"60":{},"69":{},"81":{}}}],["types.context",{"_index":24,"name":{},"parent":{"21":{},"22":{},"23":{},"24":{}}}],["types.csrftoken",{"_index":30,"name":{},"parent":{"26":{},"27":{}}}],["types.folder",{"_index":40,"name":{},"parent":{"35":{},"36":{},"37":{}}}],["types.job",{"_index":46,"name":{},"parent":{"41":{},"42":{},"43":{},"44":{},"45":{},"46":{},"47":{}}}],["types.jobdefinition",{"_index":87,"name":{},"parent":{"82":{}}}],["types.jobresult",{"_index":44,"name":{},"parent":{"39":{}}}],["types.link",{"_index":34,"name":{},"parent":{"29":{},"30":{},"31":{},"32":{},"33":{}}}],["types.sasjsconfig",{"_index":55,"name":{},"parent":{"52":{},"53":{},"54":{},"55":{},"56":{},"57":{},"58":{},"59":{}}}],["types.sasjsrequest",{"_index":11,"name":{},"parent":{"9":{},"10":{},"11":{},"12":{},"13":{},"14":{}}}],["types.sasjswaitingrequest",{"_index":64,"name":{},"parent":{"61":{},"66":{},"67":{},"68":{}}}],["types.sasjswaitingrequest.requestpromise",{"_index":66,"name":{},"parent":{"62":{}}}],["types.sasjswaitingrequest.requestpromise.__type",{"_index":68,"name":{},"parent":{"63":{},"64":{},"65":{}}}],["types.servertype",{"_index":51,"name":{},"parent":{"49":{},"50":{}}}],["types.session",{"_index":75,"name":{},"parent":{"70":{},"71":{},"72":{}}}],["uri",{"_index":37,"name":{"32":{},"36":{},"43":{}},"parent":{}}],["usecomputeapi",{"_index":61,"name":{"59":{}},"parent":{}}],["utils",{"_index":6,"name":{"5":{}},"parent":{"6":{},"15":{},"16":{},"17":{},"18":{},"19":{},"73":{},"74":{},"75":{},"76":{},"77":{},"78":{},"79":{},"80":{},"83":{}}}],["value",{"_index":31,"name":{"27":{}},"parent":{}}],["version",{"_index":27,"name":{"24":{}},"parent":{}}]],"pipeline":[]}} \ No newline at end of file diff --git a/docs/classes/reflection-560.reflection-1.sas9apiclient.html b/docs/classes/reflection-560.reflection-1.sas9apiclient.html new file mode 100644 index 0000000..263ae4d --- /dev/null +++ b/docs/classes/reflection-560.reflection-1.sas9apiclient.html @@ -0,0 +1,294 @@ + + + + + + SAS9ApiClient | @sasjs/adapter + + + + + +
+
+
+
+ +
+
+ Options +
+
+ All +
    +
  • Public
  • +
  • Public/Protected
  • +
  • All
  • +
+
+ + +
+
+ Menu +
+
+
+
+
+
+ +
+
+
+
+
+ +
+

Class SAS9ApiClient

+
+
+

A client for interfacing with the SAS9 REST API

+
+
+
+

Hierarchy

+
    +
  • + SAS9ApiClient +
  • +
+
+
+
+
+
+

Constructors

+ +
+
+

Methods

+ +
+
+
+
+
+

Constructors

+
+ +

constructor

+ +
    +
  • + +

    Parameters

    +
      +
    • +
      serverUrl: string
      +
    • +
    +

    Returns SAS9ApiClient

    +
  • +
+
+
+
+

Methods

+
+ +

executeScript

+
    +
  • executeScript(linesOfCode: string[], serverName: string, repositoryName: string): Promise<string>
  • +
+
    +
  • + +
    +
    +

    Executes code on a SAS9 server.

    +
    +
    +

    Parameters

    +
      +
    • +
      linesOfCode: string[]
      +
      +

      an array of lines of code to execute

      +
      +
    • +
    • +
      serverName: string
      +
      +

      the server to execute the code on

      +
      +
    • +
    • +
      repositoryName: string
      +
      +

      the repository to execute the code on

      +
      +
    • +
    +

    Returns Promise<string>

    +
  • +
+
+
+ +

getConfig

+
    +
  • getConfig(): object
  • +
+
    +
  • + +
    +
    +

    returns on object containing the server URL

    +
    +
    +

    Returns object

    +
      +
    • +
      serverUrl: string
      +
    • +
    +
  • +
+
+
+ +

setConfig

+
    +
  • setConfig(serverUrl: string): void
  • +
+
    +
  • + +
    +
    +

    Updates serverurl which is not null

    +
    +
    +

    Parameters

    +
      +
    • +
      serverUrl: string
      +
      +

      the URL of the server.

      +
      +
    • +
    +

    Returns void

    +
  • +
+
+
+ +
+
+ +
+
+
+
+
+
+

Generated using TypeDoc

+
+
+ + + + \ No newline at end of file diff --git a/docs/classes/reflection-560.reflection-1.sasjs.html b/docs/classes/reflection-560.reflection-1.sasjs.html new file mode 100644 index 0000000..7791c3e --- /dev/null +++ b/docs/classes/reflection-560.reflection-1.sasjs.html @@ -0,0 +1,929 @@ + + + + + + SASjs | @sasjs/adapter + + + + + +
+
+
+
+ +
+
+ Options +
+
+ All +
    +
  • Public
  • +
  • Public/Protected
  • +
  • All
  • +
+
+ + +
+
+ Menu +
+
+
+
+
+
+
    +
  • + +
  • +
  • + +
  • +
  • + SASjs +
  • +
+
+
+
+
+
+ +
+

Class SASjs

+
+
+

SASjs is a JavaScript adapter for SAS.

+
+
+
+

Hierarchy

+
    +
  • + SASjs +
  • +
+
+
+
+ +
+
+
+

Constructors

+
+ +

constructor

+
    +
  • new SASjs(config?: any): SASjs
  • +
+
    +
  • + +

    Parameters

    +
      +
    • +
      Optional config: any
      +
    • +
    +

    Returns SASjs

    +
  • +
+
+
+
+

Methods

+
+ +

checkSession

+
    +
  • checkSession(): Promise<object>
  • +
+
    +
  • + +
    +
    +

    Checks whether a session is active, or login is required

    +
    +
    +

    Returns Promise<object>

    +

    a promise which resolves with an object containing two values - a boolean isLoggedIn, and a string userName

    +
  • +
+
+
+ +

createFolder

+
    +
  • createFolder(folderName: string, parentFolderPath: string, parentFolderUri?: undefined | string, accessToken?: undefined | string, sasApiClient?: SASViyaApiClient): Promise<Folder>
  • +
+
    +
  • + +

    Parameters

    +
      +
    • +
      folderName: string
      +
    • +
    • +
      parentFolderPath: string
      +
    • +
    • +
      Optional parentFolderUri: undefined | string
      +
    • +
    • +
      Optional accessToken: undefined | string
      +
    • +
    • +
      Optional sasApiClient: SASViyaApiClient
      +
    • +
    +

    Returns Promise<Folder>

    +
  • +
+
+
+ +

createJobDefinition

+
    +
  • createJobDefinition(jobName: string, code: string, parentFolderPath?: undefined | string, parentFolderUri?: undefined | string, accessToken?: undefined | string, sasApiClient?: SASViyaApiClient): Promise<object>
  • +
+
    +
  • + +

    Parameters

    +
      +
    • +
      jobName: string
      +
    • +
    • +
      code: string
      +
    • +
    • +
      Optional parentFolderPath: undefined | string
      +
    • +
    • +
      Optional parentFolderUri: undefined | string
      +
    • +
    • +
      Optional accessToken: undefined | string
      +
    • +
    • +
      Optional sasApiClient: SASViyaApiClient
      +
    • +
    +

    Returns Promise<object>

    +
  • +
+
+
+ +

createSession

+
    +
  • createSession(contextName: string, accessToken: string): Promise<Session>
  • +
+
    +
  • + +

    Parameters

    +
      +
    • +
      contextName: string
      +
    • +
    • +
      accessToken: string
      +
    • +
    +

    Returns Promise<Session>

    +
  • +
+
+
+ +

deleteClient

+
    +
  • deleteClient(clientId: string, accessToken: string): Promise<object>
  • +
+
    +
  • + +

    Parameters

    +
      +
    • +
      clientId: string
      +
    • +
    • +
      accessToken: string
      +
    • +
    +

    Returns Promise<object>

    +
  • +
+
+
+ +

deployServicePack

+
    +
  • deployServicePack(serviceJson: any, appLoc?: undefined | string, serverUrl?: undefined | string, accessToken?: undefined | string): Promise<void>
  • +
+
    +
  • + +
    +
    +

    Creates the folders and services in the provided JSON on the given location + (appLoc) on the given server (serverUrl).

    +
    +
    +

    Parameters

    +
      +
    • +
      serviceJson: any
      +
      +

      the JSON specifying the folders and services to be created.

      +
      +
    • +
    • +
      Optional appLoc: undefined | string
      +
      +

      the base folder in which to create the new folders and + services. If not provided, is taken from SASjsConfig.

      +
      +
    • +
    • +
      Optional serverUrl: undefined | string
      +
      +

      the server on which to deploy the folders and services. + If not provided, is taken from SASjsConfig.

      +
      +
    • +
    • +
      Optional accessToken: undefined | string
      +
      +

      an optional access token to be passed in when + using this function from the command line.

      +
      +
    • +
    +

    Returns Promise<void>

    +
  • +
+
+
+ +

executeScriptSAS9

+
    +
  • executeScriptSAS9(linesOfCode: string[], serverName: string, repositoryName: string): Promise<undefined | string>
  • +
+
    +
  • + +

    Parameters

    +
      +
    • +
      linesOfCode: string[]
      +
    • +
    • +
      serverName: string
      +
    • +
    • +
      repositoryName: string
      +
    • +
    +

    Returns Promise<undefined | string>

    +
  • +
+
+
+ +

executeScriptSASViya

+
    +
  • executeScriptSASViya(fileName: string, linesOfCode: string[], contextName: string, accessToken?: undefined | string, sessionId?: string, silent?: boolean): Promise<object>
  • +
+
    +
  • + +

    Parameters

    +
      +
    • +
      fileName: string
      +
    • +
    • +
      linesOfCode: string[]
      +
    • +
    • +
      contextName: string
      +
    • +
    • +
      Optional accessToken: undefined | string
      +
    • +
    • +
      Default value sessionId: string = ""
      +
    • +
    • +
      Default value silent: boolean = false
      +
    • +
    +

    Returns Promise<object>

    +
  • +
+
+
+ +

getAccessToken

+
    +
  • getAccessToken(clientId: string, clientSecret: string, authCode: string): Promise<any>
  • +
+
    +
  • + +

    Parameters

    +
      +
    • +
      clientId: string
      +
    • +
    • +
      clientSecret: string
      +
    • +
    • +
      authCode: string
      +
    • +
    +

    Returns Promise<any>

    +
  • +
+
+
+ +

getAllContexts

+
    +
  • getAllContexts(accessToken: string): Promise<object[]>
  • +
+
    +
  • + +

    Parameters

    +
      +
    • +
      accessToken: string
      +
    • +
    +

    Returns Promise<object[]>

    +
  • +
+
+
+ +

getAuthCode

+
    +
  • getAuthCode(clientId: string): Promise<null | string>
  • +
+
    +
  • + +

    Parameters

    +
      +
    • +
      clientId: string
      +
    • +
    +

    Returns Promise<null | string>

    +
  • +
+
+
+ +

getCsrf

+
    +
  • getCsrf(): null | string
  • +
+
    +
  • + +
    +
    +

    Returns the _csrf token of the current session.

    +
    +
    +

    Returns null + | + string +

    +
  • +
+
+
+ +

getExecutableContexts

+
    +
  • getExecutableContexts(accessToken: string): Promise<any[]>
  • +
+
    +
  • + +

    Parameters

    +
      +
    • +
      accessToken: string
      +
    • +
    +

    Returns Promise<any[]>

    +
  • +
+
+
+ +

getSasRequests

+ +
    +
  • + +

    Returns SASjsRequest[]

    +
  • +
+
+
+ +

getSasjsConfig

+ +
    +
  • + +
    +
    +

    Returns the current SASjs configuration.

    +
    +
    +

    Returns SASjsConfig

    +
  • +
+
+
+ +

getUserName

+
    +
  • getUserName(): string
  • +
+
    +
  • + +
    +
    +

    Returns the username of the user currently logged in.

    +
    +
    +

    Returns string

    +
  • +
+
+
+ +

logIn

+
    +
  • logIn(username: string, password: string): Promise<object>
  • +
+
    +
  • + +
    +
    +

    Logs into the SAS server with the supplied credentials

    +
    +
    +

    Parameters

    +
      +
    • +
      username: string
      +
      +

      a string representing the username

      +
      +
    • +
    • +
      password: string
      +
      +

      a string representing the password

      +
      +
    • +
    +

    Returns Promise<object>

    +
  • +
+
+
+ +

logOut

+
    +
  • logOut(): Promise<unknown>
  • +
+
    +
  • + +
    +
    +

    Logs out of the configured SAS server

    +
    +
    +

    Returns Promise<unknown>

    +
  • +
+
+
+ +

refreshTokens

+
    +
  • refreshTokens(clientId: string, clientSecret: string, refreshToken: string): Promise<any>
  • +
+
    +
  • + +

    Parameters

    +
      +
    • +
      clientId: string
      +
    • +
    • +
      clientSecret: string
      +
    • +
    • +
      refreshToken: string
      +
    • +
    +

    Returns Promise<any>

    +
  • +
+
+
+ +

request

+
    +
  • request(sasJob: string, data: any, config?: any, loginRequiredCallback?: any, accessToken?: undefined | string): Promise<any>
  • +
+
    +
  • + +
    +
    +

    Makes a request to the SAS Service specified in SASjob. The response + object will always contain table names in lowercase, and column names in + uppercase. Values are returned formatted by default, unformatted + values can be configured as an option in the %webout macro.

    +
    +
    +

    Parameters

    +
      +
    • +
      sasJob: string
      +
      +

      The path to the SAS program (ultimately resolves to + the SAS _program parameter to run a Job Definition or SAS 9 Stored + Process.) Is prepended at runtime with the value of appLoc.

      +
      +
    • +
    • +
      data: any
      +
      +

      A JSON object containing one or more tables to be sent to + SAS. Can be null if no inputs required.

      +
      +
    • +
    • +
      Default value config: any = {}
      +
    • +
    • +
      Optional loginRequiredCallback: any
      +
      +

      provide a function here to be called if the + user is not logged in (eg to display a login form). The request will be + resubmitted after logon.

      +
      +
    • +
    • +
      Optional accessToken: undefined | string
      +
    • +
    +

    Returns Promise<any>

    +
  • +
+
+
+ +

setDebugState

+
    +
  • setDebugState(value: boolean): void
  • +
+
    +
  • + +
    +
    +

    Sets the debug state. Turning this on will enable additional logging to + be returned to the adapter.

    +
    +
    +

    Parameters

    +
      +
    • +
      value: boolean
      +
      +

      Boolean indicating debug state

      +
      +
    • +
    +

    Returns void

    +
  • +
+
+
+ +

setSASjsConfig

+
    +
  • setSASjsConfig(config: SASjsConfig): Promise<void>
  • +
+
    +
  • + +
    +
    +

    Sets the SASjs configuration.

    +
    +
    +

    Parameters

    +
      +
    • +
      config: SASjsConfig
      +
      +

      SASjsConfig indicating SASjs Configuration

      +
      +
    • +
    +

    Returns Promise<void>

    +
  • +
+
+
+ +
+ +
+
+
+
+
+

Generated using TypeDoc

+
+
+ + + + \ No newline at end of file diff --git a/docs/classes/reflection-560.reflection-1.sasviyaapiclient.html b/docs/classes/reflection-560.reflection-1.sasviyaapiclient.html new file mode 100644 index 0000000..6d014d3 --- /dev/null +++ b/docs/classes/reflection-560.reflection-1.sasviyaapiclient.html @@ -0,0 +1,892 @@ + + + + + + SASViyaApiClient | @sasjs/adapter + + + + + +
+
+
+
+ +
+
+ Options +
+
+ All +
    +
  • Public
  • +
  • Public/Protected
  • +
  • All
  • +
+
+ + +
+
+ Menu +
+
+
+
+
+
+ +
+
+
+
+
+ +
+

Class SASViyaApiClient

+
+
+

A client for interfacing with the SAS Viya REST API

+
+
+
+

Hierarchy

+
    +
  • + SASViyaApiClient +
  • +
+
+
+
+ +
+
+
+

Constructors

+
+ +

constructor

+
    +
  • new SASViyaApiClient(serverUrl: string, rootFolderName: string, contextName: string, rootFolderMap?: Map<string, Job[]>): SASViyaApiClient
  • +
+
    +
  • + +

    Parameters

    +
      +
    • +
      serverUrl: string
      +
    • +
    • +
      rootFolderName: string
      +
    • +
    • +
      contextName: string
      +
    • +
    • +
      Default value rootFolderMap: Map<string, Job[]> = new Map<string, Job[]>()
      +
    • +
    +

    Returns SASViyaApiClient

    +
  • +
+
+
+
+

Methods

+
+ +

createFolder

+
    +
  • createFolder(folderName: string, parentFolderPath?: undefined | string, parentFolderUri?: undefined | string, accessToken?: undefined | string): Promise<Folder>
  • +
+
    +
  • + +
    +
    +

    Creates a folder in the specified location. Either parentFolderPath or + parentFolderUri must be provided.

    +
    +
    +

    Parameters

    +
      +
    • +
      folderName: string
      +
      +

      the name of the new folder.

      +
      +
    • +
    • +
      Optional parentFolderPath: undefined | string
      +
      +

      the full path to the parent folder. If not + provided, the parentFolderUri must be provided.

      +
      +
    • +
    • +
      Optional parentFolderUri: undefined | string
      +
      +

      the URI (eg /folders/folders/UUID) of the parent + folder. If not provided, the parentFolderPath must be provided.

      +
      +
    • +
    • +
      Optional accessToken: undefined | string
      +
    • +
    +

    Returns Promise<Folder>

    +
  • +
+
+
+ +

createJobDefinition

+
    +
  • createJobDefinition(jobName: string, code: string, parentFolderPath?: undefined | string, parentFolderUri?: undefined | string, accessToken?: undefined | string): Promise<object>
  • +
+
    +
  • + +
    +
    +

    Creates a Job in the specified folder (or folder uri).

    +
    +
    +

    Parameters

    +
      +
    • +
      jobName: string
      +
      +

      the name of the new job to be created.

      +
      +
    • +
    • +
      code: string
      +
      +

      the SAS code for the new job.

      +
      +
    • +
    • +
      Optional parentFolderPath: undefined | string
      +
      +

      the location of the new job.

      +
      +
    • +
    • +
      Optional parentFolderUri: undefined | string
      +
      +

      the URI location of the new job. The function is a + little faster if the folder URI is supplied instead of the path.

      +
      +
    • +
    • +
      Optional accessToken: undefined | string
      +
    • +
    +

    Returns Promise<object>

    +
  • +
+
+
+ +

createSession

+
    +
  • createSession(contextName: string, accessToken?: undefined | string): Promise<Session>
  • +
+
    +
  • + +
    +
    +

    Creates a session on the given context.

    +
    +
    +

    Parameters

    +
      +
    • +
      contextName: string
      +
      +

      the name of the context to create a session on.

      +
      +
    • +
    • +
      Optional accessToken: undefined | string
      +
      +

      an access token for an authorized user.

      +
      +
    • +
    +

    Returns Promise<Session>

    +
  • +
+
+
+ +

deleteClient

+
    +
  • deleteClient(clientId: string, accessToken?: undefined | string): Promise<object>
  • +
+
    +
  • + +
    +
    +

    Deletes the client representing the supplied ID.

    +
    +
    +

    Parameters

    +
      +
    • +
      clientId: string
      +
      +

      the client ID to authenticate with.

      +
      +
    • +
    • +
      Optional accessToken: undefined | string
      +
      +

      an access token for an authorized user.

      +
      +
    • +
    +

    Returns Promise<object>

    +
  • +
+
+
+ +

executeComputeJob

+
    +
  • executeComputeJob(sasJob: string, contextName: string, debug: boolean, data?: any, accessToken?: undefined | string): Promise<object>
  • +
+
    +
  • + +
    +
    +

    Executes a job via the SAS Viya Compute API

    +
    +
    +

    Parameters

    +
      +
    • +
      sasJob: string
      +
      +

      the relative path to the job.

      +
      +
    • +
    • +
      contextName: string
      +
      +

      the name of the context where the job is to be executed.

      +
      +
    • +
    • +
      debug: boolean
      +
      +

      sets the _debug flag in the job arguments.

      +
      +
    • +
    • +
      Optional data: any
      +
      +

      any data to be passed in as input to the job.

      +
      +
    • +
    • +
      Optional accessToken: undefined | string
      +
      +

      an optional access token for an authorized user.

      +
      +
    • +
    +

    Returns Promise<object>

    +
  • +
+
+
+ +

executeJob

+
    +
  • executeJob(sasJob: string, contextName: string, debug: boolean, data?: any, accessToken?: undefined | string): Promise<object>
  • +
+
    +
  • + +
    +
    +

    Executes a job via the SAS Viya Job Execution API

    +
    +
    +

    Parameters

    +
      +
    • +
      sasJob: string
      +
      +

      the relative path to the job.

      +
      +
    • +
    • +
      contextName: string
      +
      +

      the name of the context where the job is to be executed.

      +
      +
    • +
    • +
      debug: boolean
      +
      +

      sets the _debug flag in the job arguments.

      +
      +
    • +
    • +
      Optional data: any
      +
      +

      any data to be passed in as input to the job.

      +
      +
    • +
    • +
      Optional accessToken: undefined | string
      +
      +

      an optional access token for an authorized user.

      +
      +
    • +
    +

    Returns Promise<object>

    +
  • +
+
+
+ +

executeScript

+
    +
  • executeScript(jobName: string, linesOfCode: string[], contextName: string, accessToken?: undefined | string, sessionId?: string, silent?: boolean, data?: null, debug?: boolean): Promise<object>
  • +
+
    +
  • + +
    +
    +

    Executes code on the current SAS Viya server.

    +
    +
    +

    Parameters

    +
      +
    • +
      jobName: string
      +
    • +
    • +
      linesOfCode: string[]
      +
      +

      an array of lines of code to execute.

      +
      +
    • +
    • +
      contextName: string
      +
      +

      the context to execute the code in.

      +
      +
    • +
    • +
      Optional accessToken: undefined | string
      +
      +

      an access token for an authorized user.

      +
      +
    • +
    • +
      Default value sessionId: string = ""
      +
      +

      optional session ID to reuse.

      +
      +
    • +
    • +
      Default value silent: boolean = false
      +
      +

      optional flag to turn of logging.

      +
      +
    • +
    • +
      Default value data: null = null
      +
    • +
    • +
      Default value debug: boolean = false
      +
    • +
    +

    Returns Promise<object>

    +
  • +
+
+
+ +

getAccessToken

+
    +
  • getAccessToken(clientId: string, clientSecret: string, authCode: string): Promise<any>
  • +
+
    +
  • + +
    +
    +

    Exchanges the auth code for an access token for the given client.

    +
    +
    +

    Parameters

    +
      +
    • +
      clientId: string
      +
      +

      the client ID to authenticate with.

      +
      +
    • +
    • +
      clientSecret: string
      +
      +

      the client secret to authenticate with.

      +
      +
    • +
    • +
      authCode: string
      +
      +

      the auth code received from the server.

      +
      +
    • +
    +

    Returns Promise<any>

    +
  • +
+
+
+ +

getAllContexts

+
    +
  • getAllContexts(accessToken?: undefined | string): Promise<object[]>
  • +
+
    +
  • + +
    +
    +

    Returns all available compute contexts on this server.

    +
    +
    +

    Parameters

    +
      +
    • +
      Optional accessToken: undefined | string
      +
      +

      an access token for an authorized user.

      +
      +
    • +
    +

    Returns Promise<object[]>

    +
  • +
+
+
+ +

getAppLocMap

+
    +
  • getAppLocMap(): Promise<Map<string, Job[]>>
  • +
+
    +
  • + +
    +
    +

    Returns a map containing the directory structure in the currently set root folder.

    +
    +
    +

    Returns Promise<Map<string, Job[]>>

    +
  • +
+
+
+ +

getAuthCode

+
    +
  • getAuthCode(clientId: string): Promise<null | string>
  • +
+
    +
  • + +
    +
    +

    Performs a login redirect and returns an auth code for the given client

    +
    +
    +

    Parameters

    +
      +
    • +
      clientId: string
      +
      +

      the client ID to authenticate with.

      +
      +
    • +
    +

    Returns Promise<null | string>

    +
  • +
+
+
+ +

getConfig

+
    +
  • getConfig(): object
  • +
+
    +
  • + +
    +
    +

    returns an object containing the Server URL and root folder name

    +
    +
    +

    Returns object

    +
      +
    • +
      rootFolderName: string
      +
    • +
    • +
      serverUrl: string
      +
    • +
    +
  • +
+
+
+ +

getExecutableContexts

+
    +
  • getExecutableContexts(accessToken?: undefined | string): Promise<any[]>
  • +
+
    +
  • + +
    +
    +

    Returns all compute contexts on this server that the user has access to.

    +
    +
    +

    Parameters

    +
      +
    • +
      Optional accessToken: undefined | string
      +
      +

      an access token for an authorized user.

      +
      +
    • +
    +

    Returns Promise<any[]>

    +
  • +
+
+
+ +

refreshTokens

+
    +
  • refreshTokens(clientId: string, clientSecret: string, refreshToken: string): Promise<any>
  • +
+
    +
  • + +
    +
    +

    Exchanges the refresh token for an access token for the given client.

    +
    +
    +

    Parameters

    +
      +
    • +
      clientId: string
      +
      +

      the client ID to authenticate with.

      +
      +
    • +
    • +
      clientSecret: string
      +
      +

      the client secret to authenticate with.

      +
      +
    • +
    • +
      refreshToken: string
      +
    • +
    +

    Returns Promise<any>

    +
  • +
+
+
+ +

setConfig

+
    +
  • setConfig(serverUrl: string, rootFolderName: string): void
  • +
+
    +
  • + +
    +
    +

    Updates server URL or root folder name when not null

    +
    +
    +

    Parameters

    +
      +
    • +
      serverUrl: string
      +
      +

      the URL of the server.

      +
      +
    • +
    • +
      rootFolderName: string
      +
      +

      the name for rootFolderName.

      +
      +
    • +
    +

    Returns void

    +
  • +
+
+
+ +

setCsrfToken

+
    +
  • setCsrfToken(csrfToken: CsrfToken): void
  • +
+
    +
  • + +

    Parameters

    + +

    Returns void

    +
  • +
+
+
+ +
+ +
+
+
+
+
+

Generated using TypeDoc

+
+
+ + + + \ No newline at end of file diff --git a/docs/classes/reflection-560.reflection-1.sessionmanager.html b/docs/classes/reflection-560.reflection-1.sessionmanager.html new file mode 100644 index 0000000..5d244f8 --- /dev/null +++ b/docs/classes/reflection-560.reflection-1.sessionmanager.html @@ -0,0 +1,206 @@ + + + + + + SessionManager | @sasjs/adapter + + + + + +
+
+
+
+ +
+
+ Options +
+
+ All +
    +
  • Public
  • +
  • Public/Protected
  • +
  • All
  • +
+
+ + +
+
+ Menu +
+
+
+
+
+
+ +
+
+
+
+
+ +
+

Class SessionManager

+
+

Hierarchy

+
    +
  • + SessionManager +
  • +
+
+
+
+
+
+

Constructors

+ +
+
+

Methods

+ +
+
+
+
+
+

Constructors

+
+ +

constructor

+
    +
  • new SessionManager(serverUrl: string, contextName: string): SessionManager
  • +
+
    +
  • + +

    Parameters

    +
      +
    • +
      serverUrl: string
      +
    • +
    • +
      contextName: string
      +
    • +
    +

    Returns SessionManager

    +
  • +
+
+
+
+

Methods

+
+ +

getSession

+
    +
  • getSession(accessToken?: undefined | string): Promise<undefined | Session>
  • +
+
    +
  • + +

    Parameters

    +
      +
    • +
      Optional accessToken: undefined | string
      +
    • +
    +

    Returns Promise<undefined | Session>

    +
  • +
+
+
+ +
+
+ +
+
+
+
+
+
+

Generated using TypeDoc

+
+
+ + + + \ No newline at end of file diff --git a/docs/classes/types.sasjsconfig.html b/docs/classes/types.sasjsconfig.html index 879299a..878f1a0 100644 --- a/docs/classes/types.sasjsconfig.html +++ b/docs/classes/types.sasjsconfig.html @@ -79,7 +79,8 @@

Specifies the configuration for the SASjs instance.

-
+ +

Hierarchy

@@ -121,7 +123,8 @@

The appLoc is the parent folder under which the SAS services (STPs or Job Execution Services) are stored.

-
+ +
@@ -145,7 +148,8 @@

Set to true to enable additional debugging.

-
+ +
@@ -179,7 +183,8 @@

Can be SAS9 or SASVIYA

-
+ +
@@ -195,10 +200,21 @@

The location (including http protocol and port) of the SAS Server. Can be omitted, eg if serving directly from the SAS Web Server or being streamed.

- + + +
+
+ +

useComputeApi

+
useComputeApi: boolean = false
+
- +
+
@@ -116,7 +117,7 @@
- +
- +
+

Hierarchy

    @@ -168,7 +169,7 @@
- +
+

Hierarchy

@@ -115,6 +116,16 @@ +
+ +

Optional config

+
config: any
+ +

data

@@ -125,16 +136,6 @@
-
- -

Optional params

-
params: any
- -

requestPromise

@@ -160,7 +161,7 @@
- +
@@ -104,12 +106,32 @@
id: string
+ +
+ +

links

+
links: Link[]
+ +
+
+ +

state

+
state: string
+
- +
- +
+

Parameters

  • @@ -172,7 +174,8 @@

    Converts the given JSON object to a CSV string.

    -
    + +

    Parameters

    • @@ -180,13 +183,37 @@

      the JSON object to convert.

      -
      + +

    Returns string

+
+ +

Const formatDataForRequest

+
    +
  • formatDataForRequest(data: any): any
  • +
+
    +
  • + +

    Parameters

    +
      +
    • +
      data: any
      +
    • +
    +

    Returns any

    +
  • +
+

Const isAuthorizeFormRequired

@@ -260,7 +287,7 @@

makeRequest

    -
  • makeRequest<T>(url: string, request: RequestInit, callback: function, contentType?: "text" | "json"): Promise<T>
  • +
  • makeRequest<T>(url: string, request: RequestInit, callback: function, contentType?: "text" | "json"): Promise<object>
  • @@ -308,7 +335,7 @@
    Default value contentType: "text" | "json" = "json"
-

Returns Promise<T>

+

Returns Promise<object>

@@ -485,7 +512,7 @@ - +
+

Hierarchy

@@ -121,7 +123,8 @@

The appLoc is the parent folder under which the SAS services (STPs or Job Execution Services) are stored.

-
+ +
@@ -145,7 +148,8 @@

Set to true to enable additional debugging.

-
+ +
@@ -179,7 +183,8 @@

Can be SAS9 or SASVIYA

-
+ +
@@ -195,10 +200,21 @@

The location (including http protocol and port) of the SAS Server. Can be omitted, eg if serving directly from the SAS Web Server or being streamed.

- + + +
+
+ +

useComputeApi

+
useComputeApi: boolean = false
+
- +
+
@@ -116,7 +117,7 @@
- +
- +
+

Hierarchy

    @@ -168,7 +169,7 @@
- +
+

Hierarchy

    @@ -160,7 +161,7 @@
- +
@@ -104,12 +106,32 @@
id: string
+ +
+ +

links

+
links: Link[]
+ +
+
+ +

state

+
state: string
+
- +
- +
+

Parameters

  • @@ -172,7 +174,8 @@

    Converts the given JSON object to a CSV string.

    -
    + +

    Parameters

    • @@ -180,13 +183,37 @@

      the JSON object to convert.

      -
      + +

    Returns string

+
+ +

Const formatDataForRequest

+
    +
  • formatDataForRequest(data: any): any
  • +
+
    +
  • + +

    Parameters

    +
      +
    • +
      data: any
      +
    • +
    +

    Returns any

    +
  • +
+

Const isAuthorizeFormRequired

@@ -260,7 +287,7 @@

makeRequest

    -
  • makeRequest<T>(url: string, request: RequestInit, callback: function, contentType?: "text" | "json"): Promise<T>
  • +
  • makeRequest<T>(url: string, request: RequestInit, callback: function, contentType?: "text" | "json"): Promise<object>
  • @@ -308,7 +335,7 @@
    Default value contentType: "text" | "json" = "json"
-

Returns Promise<T>

+

Returns Promise<object>

@@ -485,7 +512,7 @@ - +
diff --git a/docs/enums/types.servertype.html b/docs/enums/types.servertype.html index 57c2294..39407c3 100644 --- a/docs/enums/types.servertype.html +++ b/docs/enums/types.servertype.html @@ -117,7 +117,7 @@ - +
diff --git a/docs/globals.html b/docs/globals.html index 4241e98..83d95d8 100644 --- a/docs/globals.html +++ b/docs/globals.html @@ -76,7 +76,7 @@

Modules

@@ -84,7 +84,7 @@
- +
- +
diff --git a/docs/interfaces/types.csrftoken.html b/docs/interfaces/types.csrftoken.html index fb864bf..0a30e4b 100644 --- a/docs/interfaces/types.csrftoken.html +++ b/docs/interfaces/types.csrftoken.html @@ -120,7 +120,7 @@ - +
diff --git a/docs/interfaces/types.folder.html b/docs/interfaces/types.folder.html index 69994a0..0320d0e 100644 --- a/docs/interfaces/types.folder.html +++ b/docs/interfaces/types.folder.html @@ -131,7 +131,7 @@ - +
diff --git a/docs/interfaces/types.job.html b/docs/interfaces/types.job.html index bc6a5ff..d83aefd 100644 --- a/docs/interfaces/types.job.html +++ b/docs/interfaces/types.job.html @@ -175,7 +175,7 @@ - +
diff --git a/docs/interfaces/types.jobdefinition.html b/docs/interfaces/types.jobdefinition.html index 0025c7c..34da1c2 100644 --- a/docs/interfaces/types.jobdefinition.html +++ b/docs/interfaces/types.jobdefinition.html @@ -109,7 +109,7 @@ - +
diff --git a/docs/interfaces/types.jobresult.html b/docs/interfaces/types.jobresult.html index b7dadbb..249b5d3 100644 --- a/docs/interfaces/types.jobresult.html +++ b/docs/interfaces/types.jobresult.html @@ -109,7 +109,7 @@ - +
diff --git a/docs/interfaces/types.link.html b/docs/interfaces/types.link.html index a9bd632..48c21ec 100644 --- a/docs/interfaces/types.link.html +++ b/docs/interfaces/types.link.html @@ -153,7 +153,7 @@ - +
diff --git a/docs/interfaces/types.sasjsrequest.html b/docs/interfaces/types.sasjsrequest.html index 8374407..2757372 100644 --- a/docs/interfaces/types.sasjsrequest.html +++ b/docs/interfaces/types.sasjsrequest.html @@ -169,7 +169,7 @@ - +
diff --git a/docs/interfaces/types.sasjswaitingrequest.html b/docs/interfaces/types.sasjswaitingrequest.html index db3f327..3f6b612 100644 --- a/docs/interfaces/types.sasjswaitingrequest.html +++ b/docs/interfaces/types.sasjswaitingrequest.html @@ -161,7 +161,7 @@ - +
diff --git a/docs/interfaces/types.session.html b/docs/interfaces/types.session.html index bb68c1f..a90b0fc 100644 --- a/docs/interfaces/types.session.html +++ b/docs/interfaces/types.session.html @@ -131,7 +131,7 @@ - +
diff --git a/docs/interfaces/types.uploadfile.html b/docs/interfaces/types.uploadfile.html new file mode 100644 index 0000000..ae7aeb6 --- /dev/null +++ b/docs/interfaces/types.uploadfile.html @@ -0,0 +1,198 @@ + + + + + + UploadFile | @sasjs/adapter + + + + + +
+
+
+
+ +
+
+ Options +
+
+ All +
    +
  • Public
  • +
  • Public/Protected
  • +
  • All
  • +
+
+ + +
+
+ Menu +
+
+
+
+
+
+ +
+
+
+
+
+ +
+

Interface UploadFile

+
+
+

Represents a object that is passed to file uploader

+
+
+
+

Hierarchy

+
    +
  • + UploadFile +
  • +
+
+
+
+
+
+

Properties

+ +
+
+
+
+
+

Properties

+
+ +

file

+
file: File
+ +
+
+ +

fileName

+
fileName: string
+ +
+
+ +
+
+ +
+
+
+
+
+
+

Generated using TypeDoc

+
+
+ + + + \ No newline at end of file diff --git a/docs/modules/reflection-610.html b/docs/modules/reflection-610.html new file mode 100644 index 0000000..476c0f9 --- /dev/null +++ b/docs/modules/reflection-610.html @@ -0,0 +1,107 @@ + + + + + + | @sasjs/adapter + + + + + +
+
+
+
+ +
+
+ Options +
+
+ All +
    +
  • Public
  • +
  • Public/Protected
  • +
  • All
  • +
+
+ + +
+
+ Menu +
+
+
+
+
+
+
    +
  • + +
  • +
+
+
+
+
+
+ +
+

Module

+
+
+
+
+

Modules

+ +
+
+
+
+ +
+
+ +
+
+
+
+
+
+

Generated using TypeDoc

+
+
+ + + + \ No newline at end of file diff --git a/docs/modules/reflection-610.reflection-149.html b/docs/modules/reflection-610.reflection-149.html new file mode 100644 index 0000000..22545b3 --- /dev/null +++ b/docs/modules/reflection-610.reflection-149.html @@ -0,0 +1,129 @@ + + + + + + | @sasjs/adapter + + + + + +
+
+
+
+ +
+
+ Options +
+
+ All +
    +
  • Public
  • +
  • Public/Protected
  • +
  • All
  • +
+
+ + +
+
+ Menu +
+
+
+
+
+
+
    +
  • + +
  • +
  • + +
  • +
+
+
+
+
+
+ +
+

Module

+
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+

Generated using TypeDoc

+
+
+ + + + \ No newline at end of file diff --git a/docs/modules/types.html b/docs/modules/types.html index 36bcbd0..fe98425 100644 --- a/docs/modules/types.html +++ b/docs/modules/types.html @@ -101,12 +101,13 @@
  • SASjsRequest
  • SASjsWaitingRequest
  • Session
  • +
  • UploadFile
  • - +
    diff --git a/docs/modules/utils.html b/docs/modules/utils.html index 268eeb9..0447ce0 100644 --- a/docs/modules/utils.html +++ b/docs/modules/utils.html @@ -512,7 +512,7 @@ - +