diff --git a/package-lock.json b/package-lock.json index a579024..255a302 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "hasInstallScript": true, "license": "ISC", "dependencies": { - "@sasjs/utils": "^2.42.1", + "@sasjs/utils": "2.44.0", "axios": "0.26.0", "axios-cookiejar-support": "1.0.1", "form-data": "4.0.0", @@ -1142,9 +1142,9 @@ } }, "node_modules/@sasjs/utils": { - "version": "2.42.1", - "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.42.1.tgz", - "integrity": "sha512-DzHNYjeoj2eUkwV7Sa4eHCKRoTrYaQ6eyv6c1U5qOYXwVdZpMoYA3HFsHj55UcMOn2U3CXI5nrR7PZlUmVwVbQ==", + "version": "2.44.0", + "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.44.0.tgz", + "integrity": "sha512-hpC4erHYA8Mcb38mzxFEP0cXehfa0iKeqSW2d9MmxZ9g2qpy0BU6xyZJohN9kOiafXo5H359ndNKsg4DOq5YgA==", "hasInstallScript": true, "dependencies": { "@types/fs-extra": "9.0.13", @@ -13870,9 +13870,9 @@ } }, "@sasjs/utils": { - "version": "2.42.1", - "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.42.1.tgz", - "integrity": "sha512-DzHNYjeoj2eUkwV7Sa4eHCKRoTrYaQ6eyv6c1U5qOYXwVdZpMoYA3HFsHj55UcMOn2U3CXI5nrR7PZlUmVwVbQ==", + "version": "2.44.0", + "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.44.0.tgz", + "integrity": "sha512-hpC4erHYA8Mcb38mzxFEP0cXehfa0iKeqSW2d9MmxZ9g2qpy0BU6xyZJohN9kOiafXo5H359ndNKsg4DOq5YgA==", "requires": { "@types/fs-extra": "9.0.13", "@types/prompts": "2.0.13", diff --git a/package.json b/package.json index 98e2d52..2be4b9a 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ }, "main": "index.js", "dependencies": { - "@sasjs/utils": "2.42.1", + "@sasjs/utils": "2.44.0", "axios": "0.26.0", "axios-cookiejar-support": "1.0.1", "form-data": "4.0.0", diff --git a/sasjs-tests/README.md b/sasjs-tests/README.md index a400a1e..a475b56 100644 --- a/sasjs-tests/README.md +++ b/sasjs-tests/README.md @@ -65,7 +65,7 @@ The below services need to be created on your SAS server, at the location specif ```sas filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas"; %inc mc; -filename ft15f001 temp; +filename ft15f001 temp lrecl=1000; parmcards4; %webout(FETCH) %webout(OPEN) @@ -113,7 +113,7 @@ data _null_; ```sas filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas"; %inc mc; -filename ft15f001 temp; +filename ft15f001 temp lrecl=1000; parmcards4; %webout(FETCH) %webout(OPEN) diff --git a/src/SASjs.ts b/src/SASjs.ts index ac83240..f554947 100644 --- a/src/SASjs.ts +++ b/src/SASjs.ts @@ -916,8 +916,8 @@ export default class SASjs { return await this.sasJSApiClient?.deploy(dataJson, appLoc, authConfig) } - public async executeJobSASjs(query: ExecutionQuery) { - return await this.sasJSApiClient?.executeJob(query) + public async executeJobSASjs(query: ExecutionQuery, authConfig?: AuthConfig) { + return await this.sasJSApiClient?.executeJob(query, authConfig) } /** diff --git a/src/SASjsApiClient.ts b/src/SASjsApiClient.ts index b152f5d..af17911 100644 --- a/src/SASjsApiClient.ts +++ b/src/SASjsApiClient.ts @@ -43,7 +43,9 @@ export class SASjsApiClient { return Promise.resolve(result) } - public async executeJob(query: ExecutionQuery) { + public async executeJob(query: ExecutionQuery, authConfig?: AuthConfig) { + const access_token = authConfig ? authConfig.access_token : undefined + const { result } = await this.requestClient.post<{ status: string message: string @@ -51,7 +53,7 @@ export class SASjsApiClient { logPath?: string error?: {} _webout?: string - }>('SASjsApi/stp/execute', query, undefined) + }>('SASjsApi/stp/execute', query, access_token) if (Object.keys(result).includes('_webout')) { result._webout = parseWeboutResponse(result._webout!) diff --git a/src/job-execution/WebJobExecutor.ts b/src/job-execution/WebJobExecutor.ts index f3c3031..a4bdbe8 100644 --- a/src/job-execution/WebJobExecutor.ts +++ b/src/job-execution/WebJobExecutor.ts @@ -21,6 +21,7 @@ import { } from '../utils' import { BaseJobExecutor } from './JobExecutor' import { parseWeboutResponse } from '../utils/parseWeboutResponse' +import { Server } from 'https' export interface WaitingRequstPromise { promise: Promise | null @@ -46,7 +47,7 @@ export class WebJobExecutor extends BaseJobExecutor { authConfig?: AuthConfig, extraResponseAttributes: ExtraResponseAttributes[] = [] ) { - const loginCallback = loginRequiredCallback || (() => Promise.resolve()) + const loginCallback = loginRequiredCallback const program = isRelativePath(sasJob) ? config.appLoc ? config.appLoc.replace(/\/?$/, '/') + sasJob.replace(/^\//, '') @@ -79,7 +80,7 @@ export class WebJobExecutor extends BaseJobExecutor { ) }) - await loginCallback() + if (loginCallback) await loginCallback() } else { reject(new ErrorResponse(e?.message, e)) } @@ -220,6 +221,15 @@ export class WebJobExecutor extends BaseJobExecutor { } if (e instanceof LoginRequiredError) { + if (!loginRequiredCallback) { + reject( + new ErrorResponse( + 'Request is not authenticated. Make sure .env file exists with valid credentials.', + e + ) + ) + } + this.appendWaitingRequest(() => { return this.execute( sasJob, @@ -238,7 +248,7 @@ export class WebJobExecutor extends BaseJobExecutor { ) }) - await loginCallback() + if (loginCallback) await loginCallback() } else { reject(new ErrorResponse(e?.message, e)) } diff --git a/src/test/utils/formatDataForRequest.spec.ts b/src/test/utils/formatDataForRequest.spec.ts index 9a74998..eee87a4 100644 --- a/src/test/utils/formatDataForRequest.spec.ts +++ b/src/test/utils/formatDataForRequest.spec.ts @@ -62,7 +62,7 @@ describe('formatDataForRequest', () => { expect(() => formatDataForRequest(tableWithMissingValues)).toThrow( new Error( - 'Special missing value can only be a single character from A to Z or _' + `A Special missing value can only be a single character from 'A' to 'Z', '_', '.[a-z]', '._'` ) ) }) diff --git a/src/utils/convertToCsv.ts b/src/utils/convertToCsv.ts index bab7788..2211cd8 100644 --- a/src/utils/convertToCsv.ts +++ b/src/utils/convertToCsv.ts @@ -1,3 +1,5 @@ +import { isSpecialMissing } from '@sasjs/utils' + /** * Converts the given JSON object array to a CSV string. * @param data - the array of JSON objects to convert. @@ -18,7 +20,6 @@ export const convertToCSV = ( let headers: string[] = [] let csvTest let invalidString = false - const specialMissingValueRegExp = /^[a-z_]{1}$/i if (formats) { headers = Object.keys(formats).map((key) => `${key}:${formats![key]}`) @@ -36,7 +37,7 @@ export const convertToCSV = ( hasNullOrNumber = true } else if ( typeof row[field] === 'string' && - specialMissingValueRegExp.test(row[field]) + isSpecialMissing(row[field]) ) { hasSpecialMissingString = true } @@ -130,10 +131,9 @@ export const convertToCSV = ( value = currentCell === null ? '' : currentCell if (formats && formats[fieldName] === 'best.') { - if (value && !specialMissingValueRegExp.test(value)) { - console.log(`🤖[value]🤖`, value) + if (value && !isSpecialMissing(value)) { throw new Error( - 'Special missing value can only be a single character from A to Z or _' + `A Special missing value can only be a single character from 'A' to 'Z', '_', '.[a-z]', '._'` ) }