diff --git a/src/FileUploader.ts b/src/FileUploader.ts index 38d2f52..ec56983 100644 --- a/src/FileUploader.ts +++ b/src/FileUploader.ts @@ -66,6 +66,7 @@ export class FileUploader { return this.requestClient .post(uploadUrl, formData, undefined, 'application/json', headers) .then(async (res) => { + this.requestClient!.appendRequest(res, sasJob, this.sasjsConfig.debug) if ( this.sasjsConfig.serverType === ServerType.SasViya && this.sasjsConfig.debug diff --git a/src/SASViyaApiClient.ts b/src/SASViyaApiClient.ts index a8dbc9f..4cd6abe 100644 --- a/src/SASViyaApiClient.ts +++ b/src/SASViyaApiClient.ts @@ -51,6 +51,16 @@ export class SASViyaApiClient { ) private folderMap = new Map() + /** + * A helper method used to call appendRequest method of RequestClient + * @param response - response from sasjs request + * @param program - name of program + * @param debug - a boolean that indicates whether debug was enabled or not + */ + public appendRequest(response: any, program: string, debug: boolean) { + this.requestClient!.appendRequest(response, program, debug) + } + public get debug() { return this._debug } diff --git a/src/SASjs.ts b/src/SASjs.ts index a631014..45313b6 100644 --- a/src/SASjs.ts +++ b/src/SASjs.ts @@ -905,20 +905,18 @@ export default class SASjs { }) } + /** + * this method returns an array of SASjsRequest + * @returns SASjsRequest[] + */ public getSasRequests() { - const requests = [ - ...this.webJobExecutor!.getRequests(), - ...this.computeJobExecutor!.getRequests(), - ...this.jesJobExecutor!.getRequests() - ] + const requests = [...this.requestClient!.getRequests()] const sortedRequests = requests.sort(compareTimestamps) return sortedRequests } public clearSasRequests() { - this.webJobExecutor!.clearRequests() - this.computeJobExecutor!.clearRequests() - this.jesJobExecutor!.clearRequests() + this.requestClient!.clearRequests() } private setupConfiguration() { @@ -941,10 +939,17 @@ export default class SASjs { this.sasjsConfig.serverUrl = this.sasjsConfig.serverUrl.slice(0, -1) } - this.requestClient = new RequestClient( - this.sasjsConfig.serverUrl, - this.sasjsConfig.allowInsecureRequests - ) + if (!this.requestClient) { + this.requestClient = new RequestClient( + this.sasjsConfig.serverUrl, + this.sasjsConfig.allowInsecureRequests + ) + } else { + this.requestClient.setConfig( + this.sasjsConfig.serverUrl, + this.sasjsConfig.allowInsecureRequests + ) + } this.jobsPath = this.sasjsConfig.serverType === ServerType.SasViya diff --git a/src/job-execution/ComputeJobExecutor.ts b/src/job-execution/ComputeJobExecutor.ts index 46d84be..d0a6ba6 100644 --- a/src/job-execution/ComputeJobExecutor.ts +++ b/src/job-execution/ComputeJobExecutor.ts @@ -35,14 +35,12 @@ export class ComputeJobExecutor extends BaseJobExecutor { expectWebout ) .then((response) => { - this.appendRequest(response, sasJob, config.debug) - + this.sasViyaApiClient.appendRequest(response, sasJob, config.debug) resolve(response.result) }) .catch(async (e: Error) => { if (e instanceof ComputeJobExecutionError) { - this.appendRequest(e, sasJob, config.debug) - + this.sasViyaApiClient.appendRequest(e, sasJob, config.debug) reject(new ErrorResponse(e?.message, e)) } diff --git a/src/job-execution/JesJobExecutor.ts b/src/job-execution/JesJobExecutor.ts index 0834467..464c4b0 100644 --- a/src/job-execution/JesJobExecutor.ts +++ b/src/job-execution/JesJobExecutor.ts @@ -28,7 +28,7 @@ export class JesJobExecutor extends BaseJobExecutor { this.sasViyaApiClient ?.executeJob(sasJob, config.contextName, config.debug, data, authConfig) .then((response: any) => { - this.appendRequest(response, sasJob, config.debug) + this.sasViyaApiClient.appendRequest(response, sasJob, config.debug) const responseObject = appendExtraResponseAttributes( response, @@ -39,7 +39,7 @@ export class JesJobExecutor extends BaseJobExecutor { }) .catch(async (e: Error) => { if (e instanceof JobExecutionError) { - this.appendRequest(e, sasJob, config.debug) + this.sasViyaApiClient.appendRequest(e, sasJob, config.debug) reject(new ErrorResponse(e?.message, e)) } diff --git a/src/job-execution/JobExecutor.ts b/src/job-execution/JobExecutor.ts index ffcdace..426bf59 100644 --- a/src/job-execution/JobExecutor.ts +++ b/src/job-execution/JobExecutor.ts @@ -15,8 +15,6 @@ export interface JobExecutor { extraResponseAttributes?: ExtraResponseAttributes[] ) => Promise resendWaitingRequests: () => Promise - getRequests: () => SASjsRequest[] - clearRequests: () => void } export abstract class BaseJobExecutor implements JobExecutor { @@ -46,54 +44,7 @@ export abstract class BaseJobExecutor implements JobExecutor { return } - getRequests = () => this.requests - - clearRequests = () => { - this.requests = [] - } - protected appendWaitingRequest(request: ExecuteFunction) { this.waitingRequests.push(request) } - - protected appendRequest(response: any, program: string, debug: boolean) { - let sourceCode = '' - let generatedCode = '' - let sasWork = null - - if (debug) { - if (response?.log) { - sourceCode = parseSourceCode(response.log) - generatedCode = parseGeneratedCode(response.log) - - if (response?.result) { - sasWork = response.result.WORK - } else { - sasWork = response.log - } - } else if (response?.result) { - sourceCode = parseSourceCode(response.result) - generatedCode = parseGeneratedCode(response.result) - sasWork = response.result.WORK - } - } - - const stringifiedResult = - typeof response?.result === 'string' - ? response?.result - : JSON.stringify(response?.result, null, 2) - - this.requests.push({ - logFile: response?.log || stringifiedResult || response, - serviceLink: program, - timestamp: new Date(), - sourceCode, - generatedCode, - SASWORK: sasWork - }) - - if (this.requests.length > 20) { - this.requests.splice(0, 1) - } - } } diff --git a/src/job-execution/WebJobExecutor.ts b/src/job-execution/WebJobExecutor.ts index 31f19eb..c0e569b 100644 --- a/src/job-execution/WebJobExecutor.ts +++ b/src/job-execution/WebJobExecutor.ts @@ -115,6 +115,8 @@ export class WebJobExecutor extends BaseJobExecutor { const requestPromise = new Promise((resolve, reject) => { this.requestClient!.post(apiUrl, formData, undefined) .then(async (res: any) => { + this.requestClient!.appendRequest(res, sasJob, config.debug) + let jsonResponse = res.result if (config.debug) { @@ -135,8 +137,6 @@ export class WebJobExecutor extends BaseJobExecutor { } } - this.appendRequest(res, sasJob, config.debug) - const responseObject = appendExtraResponseAttributes( { result: jsonResponse }, extraResponseAttributes @@ -145,8 +145,7 @@ export class WebJobExecutor extends BaseJobExecutor { }) .catch(async (e: Error) => { if (e instanceof JobExecutionError) { - this.appendRequest(e, sasJob, config.debug) - + this.requestClient!.appendRequest(e, sasJob, config.debug) reject(new ErrorResponse(e?.message, e)) } diff --git a/src/request/RequestClient.ts b/src/request/RequestClient.ts index 04bea15..b6fc90a 100644 --- a/src/request/RequestClient.ts +++ b/src/request/RequestClient.ts @@ -8,10 +8,11 @@ import { InternalServerError, JobExecutionError } from '../types/errors' +import { SASjsRequest } from '../types' import { parseWeboutResponse } from '../utils/parseWeboutResponse' import { prefixMessage } from '@sasjs/utils/error' import { SAS9AuthError } from '../types/errors/SAS9AuthError' -import { getValidJson } from '../utils' +import { parseGeneratedCode, parseSourceCode } from '../utils' export interface HttpClient { get( @@ -47,27 +48,18 @@ export interface HttpClient { } export class RequestClient implements HttpClient { + private requests: SASjsRequest[] = [] + protected csrfToken: CsrfToken = { headerName: '', value: '' } protected fileUploadCsrfToken: CsrfToken | undefined - protected httpClient: AxiosInstance + protected httpClient!: AxiosInstance constructor(protected baseUrl: string, allowInsecure = false) { - const https = require('https') - if (allowInsecure && https.Agent) { - this.httpClient = axios.create({ - baseURL: baseUrl, - httpsAgent: new https.Agent({ - rejectUnauthorized: !allowInsecure - }) - }) - } else { - this.httpClient = axios.create({ - baseURL: baseUrl - }) - } + this.createHttpClient(baseUrl, allowInsecure) + } - this.httpClient.defaults.validateStatus = (status) => - status >= 200 && status < 305 + public setConfig(baseUrl: string, allowInsecure = false) { + this.createHttpClient(baseUrl, allowInsecure) } public getCsrfToken(type: 'general' | 'file' = 'general') { @@ -83,6 +75,66 @@ export class RequestClient implements HttpClient { return this.httpClient.defaults.baseURL || '' } + /** + * this method returns all requests, an array of SASjsRequest type + * @returns SASjsRequest[] + */ + public getRequests = () => this.requests + + /** + * this method clears the requests array, i.e set to empty + */ + public clearRequests = () => { + this.requests = [] + } + + /** + * this method appends the response from sasjs request to requests array + * @param response - response from sasjs request + * @param program - name of program + * @param debug - a boolean that indicates whether debug was enabled or not + */ + public appendRequest(response: any, program: string, debug: boolean) { + let sourceCode = '' + let generatedCode = '' + let sasWork = null + + if (debug) { + if (response?.log) { + sourceCode = parseSourceCode(response.log) + generatedCode = parseGeneratedCode(response.log) + + if (response?.result) { + sasWork = response.result.WORK + } else { + sasWork = response.log + } + } else if (response?.result) { + sourceCode = parseSourceCode(response.result) + generatedCode = parseGeneratedCode(response.result) + sasWork = response.result.WORK + } + } + + const stringifiedResult = + typeof response?.result === 'string' + ? response?.result + : JSON.stringify(response?.result, null, 2) + + this.requests.push({ + logFile: response?.log || stringifiedResult || response, + serviceLink: program, + timestamp: new Date(), + sourceCode, + generatedCode, + SASWORK: sasWork + }) + + if (this.requests.length > 20) { + this.requests.splice(0, 1) + } + } + public async get( url: string, accessToken: string | undefined, @@ -454,6 +506,25 @@ export class RequestClient implements HttpClient { return responseToReturn } + + private createHttpClient(baseUrl: string, allowInsecure = false) { + const https = require('https') + if (allowInsecure && https.Agent) { + this.httpClient = axios.create({ + baseURL: baseUrl, + httpsAgent: new https.Agent({ + rejectUnauthorized: !allowInsecure + }) + }) + } else { + this.httpClient = axios.create({ + baseURL: baseUrl + }) + } + + this.httpClient.defaults.validateStatus = (status) => + status >= 200 && status < 305 + } } export const throwIfError = (response: AxiosResponse) => { diff --git a/src/test/FileUploader.spec.ts b/src/test/FileUploader.spec.ts index 2222d04..5968ad2 100644 --- a/src/test/FileUploader.spec.ts +++ b/src/test/FileUploader.spec.ts @@ -34,7 +34,8 @@ const prepareFilesAndParams = () => { describe('FileUploader', () => { const config: SASjsConfig = { ...new SASjsConfig(), - appLoc: '/sample/apploc' + appLoc: '/sample/apploc', + debug: false } const fileUploader = new FileUploader( diff --git a/src/test/utils/getValidJson.spec.ts b/src/test/utils/getValidJson.spec.ts index a84eb04..1e1f922 100644 --- a/src/test/utils/getValidJson.spec.ts +++ b/src/test/utils/getValidJson.spec.ts @@ -33,4 +33,18 @@ describe('jsonValidator', () => { } expect(test).toThrow(JsonParseArrayError) }) + + it('should throw an error when null is passed', () => { + const test = () => { + getValidJson(null as any) + } + expect(test).toThrow(InvalidJsonError) + }) + + it('should throw an error when undefined is passed', () => { + const test = () => { + getValidJson(undefined as any) + } + expect(test).toThrow(InvalidJsonError) + }) }) diff --git a/src/utils/getValidJson.ts b/src/utils/getValidJson.ts index 17f9cbb..8d8670b 100644 --- a/src/utils/getValidJson.ts +++ b/src/utils/getValidJson.ts @@ -6,6 +6,8 @@ import { JsonParseArrayError, InvalidJsonError } from '../types/errors' */ export const getValidJson = (str: string | object) => { try { + if (str === null || str === undefined) throw new InvalidJsonError() + if (Array.isArray(str)) throw new JsonParseArrayError() if (typeof str === 'object') return str