mirror of
https://github.com/sasjs/adapter.git
synced 2025-12-15 10:44:36 +00:00
Compare commits
7 Commits
redirected
...
debug-sasj
| Author | SHA1 | Date | |
|---|---|---|---|
| 2c6198ae25 | |||
| 73f50c0435 | |||
| 5ee57f3d07 | |||
| 146b0715bf | |||
| dfc1d567a5 | |||
| 779200f5fc | |||
| cf4c4cfca9 |
30314
sasjs-tests/package-lock.json
generated
30314
sasjs-tests/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,7 @@
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject",
|
||||
"update:adapter": "cd .. && npm run package:lib && cd sasjs-tests && npm i ../build/sasjs-adapter-5.0.0.tgz",
|
||||
"deploy:tests": "rsync -avhe ssh ./build/* --delete $SSH_ACCOUNT:$DEPLOY_PATH || npm run deploy:tests-win",
|
||||
"deploy:tests": "rsync -avhe ssh ./build/* --delete sabhas@sas.analytium.co.uk:/var/www/html/sabhas/sasjs-test || npm run deploy:tests-win",
|
||||
"deploy:tests-win": "scp %DEPLOY_PATH% ./build/*",
|
||||
"deploy": "npm run update:adapter && npm run build && npm run deploy:tests"
|
||||
},
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"userName": "",
|
||||
"password": "",
|
||||
"sasJsConfig": {
|
||||
"serverUrl": "",
|
||||
"serverUrl": "https://sas.analytium.co.uk/",
|
||||
"appLoc": "/Public/app",
|
||||
"serverType": "SASVIYA",
|
||||
"debug": false,
|
||||
|
||||
@@ -14,16 +14,16 @@ const App = (): ReactElement<{}> => {
|
||||
useEffect(() => {
|
||||
if (adapter) {
|
||||
const testSuites = [
|
||||
basicTests(adapter, config.userName, config.password),
|
||||
sendArrTests(adapter),
|
||||
sendObjTests(adapter),
|
||||
specialCaseTests(adapter),
|
||||
// basicTests(adapter, config.userName, config.password),
|
||||
// sendArrTests(adapter),
|
||||
// sendObjTests(adapter),
|
||||
// specialCaseTests(adapter),
|
||||
sasjsRequestTests(adapter)
|
||||
]
|
||||
|
||||
if (adapter.getSasjsConfig().serverType === 'SASVIYA') {
|
||||
testSuites.push(computeTests(adapter))
|
||||
}
|
||||
// if (adapter.getSasjsConfig().serverType === 'SASVIYA') {
|
||||
// testSuites.push(computeTests(adapter))
|
||||
// }
|
||||
|
||||
setTestSuites(testSuites)
|
||||
}
|
||||
|
||||
@@ -64,7 +64,16 @@ export class FileUploader {
|
||||
// currently only web approach is supported for file upload
|
||||
// therefore log is part of response with debug enabled and must be parsed
|
||||
return this.requestClient
|
||||
.post(uploadUrl, formData, undefined, 'application/json', headers)
|
||||
.post(
|
||||
uploadUrl,
|
||||
formData,
|
||||
undefined,
|
||||
'application/json',
|
||||
headers,
|
||||
this.sasjsConfig.debug,
|
||||
true,
|
||||
sasJob
|
||||
)
|
||||
.then(async (res) => {
|
||||
if (
|
||||
this.sasjsConfig.serverType === ServerType.SasViya &&
|
||||
|
||||
@@ -782,12 +782,24 @@ export class SASViyaApiClient {
|
||||
jobResult = await this.requestClient.get<any>(
|
||||
`${this.serverUrl}${resultLink}/content`,
|
||||
access_token,
|
||||
'text/plain'
|
||||
'text/plain',
|
||||
{},
|
||||
debug,
|
||||
true,
|
||||
sasJob
|
||||
)
|
||||
}
|
||||
if (debug && logLink) {
|
||||
log = await this.requestClient
|
||||
.get<any>(`${this.serverUrl}${logLink.href}/content`, access_token)
|
||||
.get<any>(
|
||||
`${this.serverUrl}${logLink.href}/content`,
|
||||
access_token,
|
||||
'application/json',
|
||||
{},
|
||||
debug,
|
||||
true,
|
||||
sasJob
|
||||
)
|
||||
.then((res: any) => res.result.items.map((i: any) => i.line).join('\n'))
|
||||
}
|
||||
if (jobStatus === 'failed') {
|
||||
|
||||
18
src/SASjs.ts
18
src/SASjs.ts
@@ -50,6 +50,7 @@ export default class SASjs {
|
||||
private sas9JobExecutor: JobExecutor | null = null
|
||||
|
||||
constructor(config?: any) {
|
||||
console.log('from SASjs constructor')
|
||||
this.sasjsConfig = {
|
||||
...defaultConfig,
|
||||
...config
|
||||
@@ -611,6 +612,7 @@ export default class SASjs {
|
||||
config.useComputeApi !== null
|
||||
) {
|
||||
if (config.useComputeApi) {
|
||||
console.log(615)
|
||||
return await this.computeJobExecutor!.execute(
|
||||
sasJob,
|
||||
data,
|
||||
@@ -878,20 +880,20 @@ 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()
|
||||
]
|
||||
console.log('from getSASRequests')
|
||||
const requests = this.requestClient!.getRequests()
|
||||
const sortedRequests = requests.sort(compareTimestamps)
|
||||
console.log('sortedRequests', sortedRequests)
|
||||
return sortedRequests
|
||||
}
|
||||
|
||||
public clearSasRequests() {
|
||||
this.webJobExecutor!.clearRequests()
|
||||
this.computeJobExecutor!.clearRequests()
|
||||
this.jesJobExecutor!.clearRequests()
|
||||
this.requestClient!.clearRequests()
|
||||
}
|
||||
|
||||
private setupConfiguration() {
|
||||
|
||||
@@ -239,7 +239,15 @@ export async function executeScript(
|
||||
const resultLink = `/compute/sessions/${executionSessionId}/filerefs/_webout/content`
|
||||
|
||||
jobResult = await requestClient
|
||||
.get<any>(resultLink, access_token, 'text/plain')
|
||||
.get<any>(
|
||||
resultLink,
|
||||
access_token,
|
||||
'text/plain',
|
||||
{},
|
||||
debug,
|
||||
true,
|
||||
jobPath
|
||||
)
|
||||
.catch(async (e) => {
|
||||
if (e instanceof NotFoundError) {
|
||||
if (logLink) {
|
||||
|
||||
@@ -35,14 +35,11 @@ export class ComputeJobExecutor extends BaseJobExecutor {
|
||||
expectWebout
|
||||
)
|
||||
.then((response) => {
|
||||
this.appendRequest(response, sasJob, config.debug)
|
||||
|
||||
console.log('then block of compute job executor')
|
||||
resolve(response.result)
|
||||
})
|
||||
.catch(async (e: Error) => {
|
||||
if (e instanceof ComputeJobExecutionError) {
|
||||
this.appendRequest(e, sasJob, config.debug)
|
||||
|
||||
reject(new ErrorResponse(e?.message, e))
|
||||
}
|
||||
|
||||
|
||||
@@ -27,8 +27,6 @@ export class JesJobExecutor extends BaseJobExecutor {
|
||||
this.sasViyaApiClient
|
||||
?.executeJob(sasJob, config.contextName, config.debug, data, authConfig)
|
||||
.then((response: any) => {
|
||||
this.appendRequest(response, sasJob, config.debug)
|
||||
|
||||
let responseObject = {}
|
||||
|
||||
if (extraResponseAttributes && extraResponseAttributes.length > 0) {
|
||||
@@ -49,8 +47,6 @@ export class JesJobExecutor extends BaseJobExecutor {
|
||||
})
|
||||
.catch(async (e: Error) => {
|
||||
if (e instanceof JobExecutionError) {
|
||||
this.appendRequest(e, sasJob, config.debug)
|
||||
|
||||
reject(new ErrorResponse(e?.message, e))
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,6 @@ export interface JobExecutor {
|
||||
extraResponseAttributes?: ExtraResponseAttributes[]
|
||||
) => Promise<any>
|
||||
resendWaitingRequests: () => Promise<void>
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +111,16 @@ export class WebJobExecutor extends BaseJobExecutor {
|
||||
}
|
||||
|
||||
const requestPromise = new Promise((resolve, reject) => {
|
||||
this.requestClient!.post(apiUrl, formData, undefined)
|
||||
this.requestClient!.post(
|
||||
apiUrl,
|
||||
formData,
|
||||
undefined,
|
||||
'application/json',
|
||||
{},
|
||||
config.debug,
|
||||
true,
|
||||
sasJob
|
||||
)
|
||||
.then(async (res: any) => {
|
||||
if (this.serverType === ServerType.SasViya && config.debug) {
|
||||
const jsonResponse = await parseSasViyaDebugResponse(
|
||||
@@ -119,7 +128,6 @@ export class WebJobExecutor extends BaseJobExecutor {
|
||||
this.requestClient,
|
||||
this.serverUrl
|
||||
)
|
||||
this.appendRequest(res, sasJob, config.debug)
|
||||
resolve(jsonResponse)
|
||||
}
|
||||
if (this.serverType === ServerType.Sas9 && config.debug) {
|
||||
@@ -128,17 +136,13 @@ export class WebJobExecutor extends BaseJobExecutor {
|
||||
jsonResponse = parseWeboutResponse(res.result, apiUrl)
|
||||
|
||||
getValidJson(jsonResponse)
|
||||
this.appendRequest(res, sasJob, config.debug)
|
||||
resolve(res.result)
|
||||
}
|
||||
this.appendRequest(res, sasJob, config.debug)
|
||||
getValidJson(res.result as string)
|
||||
resolve(res.result)
|
||||
})
|
||||
.catch(async (e: Error) => {
|
||||
if (e instanceof JobExecutionError) {
|
||||
this.appendRequest(e, sasJob, config.debug)
|
||||
|
||||
reject(new ErrorResponse(e?.message, e))
|
||||
}
|
||||
|
||||
|
||||
@@ -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<T>(
|
||||
@@ -47,6 +48,8 @@ export interface HttpClient {
|
||||
}
|
||||
|
||||
export class RequestClient implements HttpClient {
|
||||
private requests: SASjsRequest[] = []
|
||||
|
||||
protected csrfToken: CsrfToken = { headerName: '', value: '' }
|
||||
protected fileUploadCsrfToken: CsrfToken | undefined
|
||||
protected httpClient: AxiosInstance
|
||||
@@ -83,12 +86,75 @@ 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) => {
|
||||
console.log('from appendRequest')
|
||||
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<T>(
|
||||
url: string,
|
||||
accessToken: string | undefined,
|
||||
contentType: string = 'application/json',
|
||||
overrideHeaders: { [key: string]: string | number } = {},
|
||||
debug: boolean = false
|
||||
debug: boolean = false,
|
||||
captureRequest: boolean = false,
|
||||
sasJob: string = ''
|
||||
): Promise<{ result: T; etag: string; status: number }> {
|
||||
const headers = {
|
||||
...this.getHeaders(accessToken, contentType),
|
||||
@@ -108,8 +174,11 @@ export class RequestClient implements HttpClient {
|
||||
.get<T>(url, requestConfig)
|
||||
.then((response) => {
|
||||
throwIfError(response)
|
||||
|
||||
return this.parseResponse<T>(response)
|
||||
const responseToReturn = this.parseResponse<T>(response)
|
||||
if (captureRequest) {
|
||||
this.appendRequest(responseToReturn, sasJob, debug)
|
||||
}
|
||||
return responseToReturn
|
||||
})
|
||||
.catch(async (e) => {
|
||||
return await this.handleError(
|
||||
@@ -135,7 +204,10 @@ export class RequestClient implements HttpClient {
|
||||
data: any,
|
||||
accessToken: string | undefined,
|
||||
contentType = 'application/json',
|
||||
overrideHeaders: { [key: string]: string | number } = {}
|
||||
overrideHeaders: { [key: string]: string | number } = {},
|
||||
debug: boolean = false,
|
||||
captureRequest: boolean = false,
|
||||
sasJob: string = ''
|
||||
): Promise<{ result: T; etag: string }> {
|
||||
const headers = {
|
||||
...this.getHeaders(accessToken, contentType),
|
||||
@@ -146,7 +218,11 @@ export class RequestClient implements HttpClient {
|
||||
.post<T>(url, data, { headers, withCredentials: true })
|
||||
.then((response) => {
|
||||
throwIfError(response)
|
||||
return this.parseResponse<T>(response)
|
||||
const responseToReturn = this.parseResponse<T>(response)
|
||||
if (captureRequest) {
|
||||
this.appendRequest(responseToReturn, sasJob, debug)
|
||||
}
|
||||
return responseToReturn
|
||||
})
|
||||
.catch(async (e) => {
|
||||
return await this.handleError(e, () =>
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user