1
0
mirror of https://github.com/sasjs/adapter.git synced 2025-12-25 15:01:20 +00:00

Compare commits

..

15 Commits

Author SHA1 Message Date
Allan Bowe
e1a5cc9e45 Merge pull request #504 from sasjs/extract-username-while-check-session
fix: while checking session extract username also
2021-09-06 16:22:04 +03:00
Saad Jutt
351a22cb3c fix: deriving username with full name 2021-09-06 12:52:40 +05:00
Saad Jutt
3ccd35a4e2 fix: if username is not present in SAS9, derive it with full name 2021-09-06 12:42:26 +05:00
Saad Jutt
e4956cc1d4 chore: test corrected for AuthManager 2021-09-05 12:06:27 +05:00
Saad Jutt
291ba51b07 fix(request): handled error case for sas9 server 2021-09-05 11:55:17 +05:00
Saad Jutt
867422f4cc fix: extraResponseAttributes for WebJobExecutor + sasjs-tests 2021-09-01 03:50:55 +05:00
Saad Jutt
2a6e29b5b8 fix: username returns from checkSession 2021-09-01 03:49:44 +05:00
Saad Jutt
e4d669f9b6 chore: typo fixed userName 2021-08-31 12:58:47 +05:00
Saad Jutt
5edf09e0a7 fix: usernames to lower case 2021-08-31 12:50:04 +05:00
Saad Jutt
5a695f495c chore: login returns username 2021-08-31 12:39:04 +05:00
ab8643a89a chore: merge master into extract-username-while-check-session 2021-08-27 14:17:20 +05:00
Saad Jutt
83353326fb test(AuthManager): fixed 2021-08-26 10:44:06 +05:00
Saad Jutt
db7a5d601e fix(login): code refactor + sasjs-tests updated 2021-08-26 10:33:00 +05:00
Saad Jutt
ee977f4fab chore(merge): Merge branch 'master' into extract-username-while-check-session 2021-08-26 09:02:40 +05:00
Saad Jutt
fc1c93957c fix: while checking session extract username also 2021-08-07 07:32:48 +05:00
22 changed files with 5311 additions and 3548 deletions

1
package-lock.json generated
View File

@@ -6351,6 +6351,7 @@
"rimraf": "^3.0.2",
"semver": "^7.3.5",
"ssri": "^8.0.1",
"tar": "^6.1.0",
"treeverse": "^1.0.4",
"walk-up-path": "^1.0.0"
}

File diff suppressed because it is too large Load Diff

View File

@@ -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 sabhas@sas.analytium.co.uk:/var/www/html/sabhas/sasjs-test || npm run deploy:tests-win",
"deploy:tests": "rsync -avhe ssh ./build/* --delete $SSH_ACCOUNT:$DEPLOY_PATH || npm run deploy:tests-win",
"deploy:tests-win": "scp %DEPLOY_PATH% ./build/*",
"deploy": "npm run update:adapter && npm run build && npm run deploy:tests"
},

View File

@@ -2,7 +2,7 @@
"userName": "",
"password": "",
"sasJsConfig": {
"serverUrl": "https://sas.analytium.co.uk/",
"serverUrl": "",
"appLoc": "/Public/app",
"serverType": "SASVIYA",
"debug": false,

View File

@@ -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)
}

View File

@@ -41,6 +41,19 @@ export const basicTests = (
assertion: (response: any) =>
response && response.isLoggedIn && response.userName === userName
},
{
title: 'Fetch username for already logged in user',
description: 'Should log the user in',
test: async () => {
await adapter.logIn(userName, password)
const newAdapterIns = new SASjs(adapter.getSasjsConfig())
return await newAdapterIns.checkSession()
},
assertion: (response: any) =>
response?.isLoggedIn && response?.userName === userName
},
{
title: 'Multiple Log in attempts',
description:
@@ -48,7 +61,7 @@ export const basicTests = (
test: async () => {
await adapter.logOut()
await adapter.logIn('invalid', 'invalid')
return adapter.logIn(userName, password)
return await adapter.logIn(userName, password)
},
assertion: (response: any) =>
response && response.isLoggedIn && response.userName === userName
@@ -151,7 +164,7 @@ export const basicTests = (
description:
'Should complete successful request with extra attributes present in response',
test: async () => {
const config = {
const config: Partial<SASjsConfig> = {
useComputeApi: false
}

View File

@@ -64,16 +64,7 @@ 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,
this.sasjsConfig.debug,
true,
sasJob
)
.post(uploadUrl, formData, undefined, 'application/json', headers)
.then(async (res) => {
if (
this.sasjsConfig.serverType === ServerType.SasViya &&

View File

@@ -782,24 +782,12 @@ export class SASViyaApiClient {
jobResult = await this.requestClient.get<any>(
`${this.serverUrl}${resultLink}/content`,
access_token,
'text/plain',
{},
debug,
true,
sasJob
'text/plain'
)
}
if (debug && logLink) {
log = await this.requestClient
.get<any>(
`${this.serverUrl}${logLink.href}/content`,
access_token,
'application/json',
{},
debug,
true,
sasJob
)
.get<any>(`${this.serverUrl}${logLink.href}/content`, access_token)
.then((res: any) => res.result.items.map((i: any) => i.line).join('\n'))
}
if (jobStatus === 'failed') {

View File

@@ -50,7 +50,6 @@ export default class SASjs {
private sas9JobExecutor: JobExecutor | null = null
constructor(config?: any) {
console.log('from SASjs constructor')
this.sasjsConfig = {
...defaultConfig,
...config
@@ -612,7 +611,6 @@ export default class SASjs {
config.useComputeApi !== null
) {
if (config.useComputeApi) {
console.log(615)
return await this.computeJobExecutor!.execute(
sasJob,
data,
@@ -880,20 +878,20 @@ export default class SASjs {
})
}
/**
* this method returns an array of SASjsRequest
* @returns SASjsRequest[]
*/
public getSasRequests() {
console.log('from getSASRequests')
const requests = this.requestClient!.getRequests()
const requests = [
...this.webJobExecutor!.getRequests(),
...this.computeJobExecutor!.getRequests(),
...this.jesJobExecutor!.getRequests()
]
const sortedRequests = requests.sort(compareTimestamps)
console.log('sortedRequests', sortedRequests)
return sortedRequests
}
public clearSasRequests() {
this.requestClient!.clearRequests()
this.webJobExecutor!.clearRequests()
this.computeJobExecutor!.clearRequests()
this.jesJobExecutor!.clearRequests()
}
private setupConfiguration() {

View File

@@ -239,15 +239,7 @@ export async function executeScript(
const resultLink = `/compute/sessions/${executionSessionId}/filerefs/_webout/content`
jobResult = await requestClient
.get<any>(
resultLink,
access_token,
'text/plain',
{},
debug,
true,
jobPath
)
.get<any>(resultLink, access_token, 'text/plain')
.catch(async (e) => {
if (e instanceof NotFoundError) {
if (logLink) {

View File

@@ -23,43 +23,61 @@ export class AuthManager {
* Logs into the SAS server with the supplied credentials.
* @param username - a string representing the username.
* @param password - a string representing the password.
* @returns - a boolean `isLoggedin` and a string `username`
*/
public async logIn(username: string, password: string) {
const loginParams: any = {
public async logIn(
username: string,
password: string
): Promise<{
isLoggedIn: boolean
userName: string
}> {
const loginParams = {
_service: 'default',
username,
password
}
this.userName = loginParams.username
let {
isLoggedIn: isLoggedInAlready,
loginForm,
userName: currentSessionUsername
} = await this.checkSession()
const { isLoggedIn, loginForm } = await this.checkSession()
if (isLoggedInAlready) {
if (currentSessionUsername === loginParams.username) {
await this.loginCallback()
if (isLoggedIn) {
await this.loginCallback()
return {
isLoggedIn,
userName: this.userName
this.userName = currentSessionUsername!
return {
isLoggedIn: true,
userName: this.userName
}
} else {
this.logOut()
}
}
} else this.userName = ''
let loginResponse = await this.sendLoginRequest(loginForm, loginParams)
let loggedIn = isLogInSuccess(loginResponse)
let isLoggedIn = isLogInSuccess(loginResponse)
if (!loggedIn) {
if (!isLoggedIn) {
if (isCredentialsVerifyError(loginResponse)) {
const newLoginForm = await this.getLoginForm(loginResponse)
loginResponse = await this.sendLoginRequest(newLoginForm, loginParams)
}
const currentSession = await this.checkSession()
loggedIn = currentSession.isLoggedIn
const res = await this.checkSession()
isLoggedIn = res.isLoggedIn
if (isLoggedIn) this.userName = res.userName!
} else {
this.userName = loginParams.username
}
if (loggedIn) {
if (isLoggedIn) {
if (this.serverType === ServerType.Sas9) {
const casAuthenticationUrl = `${this.serverUrl}/SASStoredProcess/j_spring_cas_security_check`
@@ -70,10 +88,10 @@ export class AuthManager {
}
this.loginCallback()
}
} else this.userName = ''
return {
isLoggedIn: !!loggedIn,
isLoggedIn,
userName: this.userName
}
}
@@ -103,14 +121,21 @@ export class AuthManager {
/**
* Checks whether a session is active, or login is required.
* @returns - a promise which resolves with an object containing two values - a boolean `isLoggedIn`, and a string `userName`.
* @returns - a promise which resolves with an object containing three values
* - a boolean `isLoggedIn`
* - a string `userName` and
* - a form `loginForm` if not loggedin.
*/
public async checkSession() {
public async checkSession(): Promise<{
isLoggedIn: boolean
userName?: string
loginForm?: any
}> {
//For VIYA we will send request on API endpoint. Which is faster then pinging SASJobExecution.
//For SAS9 we will send request on SASStoredProcess
const url =
this.serverType === 'SASVIYA'
? `${this.serverUrl}/identities`
? `${this.serverUrl}/identities/users/@currentUser`
: `${this.serverUrl}/SASStoredProcess`
const { result: loginResponse } = await this.requestClient
@@ -120,6 +145,10 @@ export class AuthManager {
})
const isLoggedIn = loginResponse !== 'authErr'
const userName = isLoggedIn
? this.extractUserName(loginResponse)
: undefined
let loginForm = null
if (!isLoggedIn) {
@@ -138,11 +167,29 @@ export class AuthManager {
return Promise.resolve({
isLoggedIn,
userName: this.userName,
userName: userName?.toLowerCase(),
loginForm
})
}
private extractUserName = (response: any): string => {
switch (this.serverType) {
case ServerType.SasViya:
return response?.id
case ServerType.Sas9:
const matched = response?.match(/"title":"Log Off [0-1a-zA-Z ]*"/)
const username = matched?.[0].slice(17, -1)
if (!username.includes(' ')) return username
return username
.split(' ')
.map((name: string) => name.slice(0, 3).toLowerCase())
.join('')
}
}
private getLoginForm(response: any) {
const pattern: RegExp = /<form.+action="(.*Logon[^"]*).*>/
const matches = pattern.exec(response)

View File

@@ -67,7 +67,7 @@ describe('AuthManager', () => {
jest.spyOn(authManager, 'checkSession').mockImplementation(() =>
Promise.resolve({
isLoggedIn: true,
userName: 'test',
userName,
loginForm: 'test'
})
)
@@ -89,7 +89,6 @@ describe('AuthManager', () => {
jest.spyOn(authManager, 'checkSession').mockImplementation(() =>
Promise.resolve({
isLoggedIn: false,
userName: 'test',
loginForm: { name: 'test' }
})
)
@@ -175,7 +174,7 @@ describe('AuthManager', () => {
expect(response.isLoggedIn).toBeTruthy()
expect(mockedAxios.get).toHaveBeenNthCalledWith(
1,
`http://test-server.com/identities`,
`http://test-server.com/identities/users/@currentUser`,
{
withCredentials: true,
responseType: 'text',

View File

@@ -35,11 +35,14 @@ export class ComputeJobExecutor extends BaseJobExecutor {
expectWebout
)
.then((response) => {
console.log('then block of compute job executor')
this.appendRequest(response, sasJob, config.debug)
resolve(response.result)
})
.catch(async (e: Error) => {
if (e instanceof ComputeJobExecutionError) {
this.appendRequest(e, sasJob, config.debug)
reject(new ErrorResponse(e?.message, e))
}

View File

@@ -7,6 +7,7 @@ import {
} from '../types/errors'
import { ExtraResponseAttributes } from '@sasjs/utils/types'
import { BaseJobExecutor } from './JobExecutor'
import { appendExtraResponseAttributes } from '../utils'
export class JesJobExecutor extends BaseJobExecutor {
constructor(serverUrl: string, private sasViyaApiClient: SASViyaApiClient) {
@@ -27,26 +28,19 @@ export class JesJobExecutor extends BaseJobExecutor {
this.sasViyaApiClient
?.executeJob(sasJob, config.contextName, config.debug, data, authConfig)
.then((response: any) => {
let responseObject = {}
this.appendRequest(response, sasJob, config.debug)
if (extraResponseAttributes && extraResponseAttributes.length > 0) {
const extraAttributes = extraResponseAttributes.reduce(
(map: any, obj: any) => ((map[obj] = response[obj]), map),
{}
)
responseObject = {
result: response.result,
...extraAttributes
}
} else {
responseObject = response.result
}
const responseObject = appendExtraResponseAttributes(
response,
extraResponseAttributes
)
resolve(responseObject)
})
.catch(async (e: Error) => {
if (e instanceof JobExecutionError) {
this.appendRequest(e, sasJob, config.debug)
reject(new ErrorResponse(e?.message, e))
}

View File

@@ -15,6 +15,8 @@ export interface JobExecutor {
extraResponseAttributes?: ExtraResponseAttributes[]
) => Promise<any>
resendWaitingRequests: () => Promise<void>
getRequests: () => SASjsRequest[]
clearRequests: () => void
}
export abstract class BaseJobExecutor implements JobExecutor {
@@ -44,7 +46,54 @@ 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)
}
}
}

View File

@@ -1,4 +1,8 @@
import { ServerType } from '@sasjs/utils/types'
import {
AuthConfig,
ExtraResponseAttributes,
ServerType
} from '@sasjs/utils/types'
import {
ErrorResponse,
JobExecutionError,
@@ -12,7 +16,8 @@ import { SASViyaApiClient } from '../SASViyaApiClient'
import {
isRelativePath,
getValidJson,
parseSasViyaDebugResponse
parseSasViyaDebugResponse,
appendExtraResponseAttributes
} from '../utils'
import { BaseJobExecutor } from './JobExecutor'
import { parseWeboutResponse } from '../utils/parseWeboutResponse'
@@ -37,7 +42,9 @@ export class WebJobExecutor extends BaseJobExecutor {
sasJob: string,
data: any,
config: any,
loginRequiredCallback?: any
loginRequiredCallback?: any,
authConfig?: AuthConfig,
extraResponseAttributes: ExtraResponseAttributes[] = []
) {
const loginCallback = loginRequiredCallback || (() => Promise.resolve())
const program = isRelativePath(sasJob)
@@ -111,38 +118,40 @@ export class WebJobExecutor extends BaseJobExecutor {
}
const requestPromise = new Promise((resolve, reject) => {
this.requestClient!.post(
apiUrl,
formData,
undefined,
'application/json',
{},
config.debug,
true,
sasJob
)
this.requestClient!.post(apiUrl, formData, undefined)
.then(async (res: any) => {
if (this.serverType === ServerType.SasViya && config.debug) {
const jsonResponse = await parseSasViyaDebugResponse(
res.result,
this.requestClient,
this.serverUrl
)
resolve(jsonResponse)
}
if (this.serverType === ServerType.Sas9 && config.debug) {
let jsonResponse = res.result
if (typeof res.result === 'string')
jsonResponse = parseWeboutResponse(res.result, apiUrl)
let jsonResponse = res.result
getValidJson(jsonResponse)
resolve(res.result)
if (config.debug) {
switch (this.serverType) {
case ServerType.SasViya:
jsonResponse = await parseSasViyaDebugResponse(
res.result,
this.requestClient,
this.serverUrl
)
break
case ServerType.Sas9:
jsonResponse =
typeof res.result === 'string'
? parseWeboutResponse(res.result, apiUrl)
: res.result
break
}
}
getValidJson(res.result as string)
resolve(res.result)
this.appendRequest(res, sasJob, config.debug)
const responseObject = appendExtraResponseAttributes(
{ result: jsonResponse },
extraResponseAttributes
)
resolve(responseObject)
})
.catch(async (e: Error) => {
if (e instanceof JobExecutionError) {
this.appendRequest(e, sasJob, config.debug)
reject(new ErrorResponse(e?.message, e))
}
@@ -154,7 +163,9 @@ export class WebJobExecutor extends BaseJobExecutor {
sasJob,
data,
config,
loginRequiredCallback
loginRequiredCallback,
authConfig,
extraResponseAttributes
).then(
(res: any) => {
resolve(res)

View File

@@ -8,11 +8,10 @@ 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 { parseGeneratedCode, parseSourceCode } from '../utils'
import { getValidJson } from '../utils'
export interface HttpClient {
get<T>(
@@ -48,8 +47,6 @@ export interface HttpClient {
}
export class RequestClient implements HttpClient {
private requests: SASjsRequest[] = []
protected csrfToken: CsrfToken = { headerName: '', value: '' }
protected fileUploadCsrfToken: CsrfToken | undefined
protected httpClient: AxiosInstance
@@ -86,75 +83,12 @@ 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,
captureRequest: boolean = false,
sasJob: string = ''
debug: boolean = false
): Promise<{ result: T; etag: string; status: number }> {
const headers = {
...this.getHeaders(accessToken, contentType),
@@ -174,11 +108,8 @@ export class RequestClient implements HttpClient {
.get<T>(url, requestConfig)
.then((response) => {
throwIfError(response)
const responseToReturn = this.parseResponse<T>(response)
if (captureRequest) {
this.appendRequest(responseToReturn, sasJob, debug)
}
return responseToReturn
return this.parseResponse<T>(response)
})
.catch(async (e) => {
return await this.handleError(
@@ -204,10 +135,7 @@ export class RequestClient implements HttpClient {
data: any,
accessToken: string | undefined,
contentType = 'application/json',
overrideHeaders: { [key: string]: string | number } = {},
debug: boolean = false,
captureRequest: boolean = false,
sasJob: string = ''
overrideHeaders: { [key: string]: string | number } = {}
): Promise<{ result: T; etag: string }> {
const headers = {
...this.getHeaders(accessToken, contentType),
@@ -218,11 +146,7 @@ export class RequestClient implements HttpClient {
.post<T>(url, data, { headers, withCredentials: true })
.then((response) => {
throwIfError(response)
const responseToReturn = this.parseResponse<T>(response)
if (captureRequest) {
this.appendRequest(responseToReturn, sasJob, debug)
}
return responseToReturn
return this.parseResponse<T>(response)
})
.catch(async (e) => {
return await this.handleError(e, () =>
@@ -575,46 +499,60 @@ export const throwIfError = (response: AxiosResponse) => {
}
const parseError = (data: string) => {
if (!data) return null
try {
const responseJson = JSON.parse(data?.replace(/[\n\r]/g, ' '))
return responseJson.errorCode && responseJson.message
? new JobExecutionError(
responseJson.errorCode,
responseJson.message,
data?.replace(/[\n\r]/g, ' ')
)
: null
} catch (_) {
try {
const hasError = data?.includes('{"errorCode')
if (hasError) {
const parts = data.split('{"errorCode')
if (parts.length > 1) {
const error = '{"errorCode' + parts[1].split('"}')[0] + '"}'
const errorJson = JSON.parse(error.replace(/[\n\r]/g, ' '))
return new JobExecutionError(
errorJson.errorCode,
errorJson.message,
data?.replace(/[\n\r]/g, '\n')
)
}
return null
}
try {
const hasError = !!data?.match(/stored process not found: /i)
if (hasError) {
const parts = data.split(/stored process not found: /i)
if (parts.length > 1) {
const storedProcessPath = parts[1].split('<i>')[1].split('</i>')[0]
const message = `Stored process not found: ${storedProcessPath}`
return new JobExecutionError(404, message, '')
}
}
} catch (_) {
return null
}
} catch (_) {
return null
if (responseJson.errorCode && responseJson.message) {
return new JobExecutionError(
responseJson.errorCode,
responseJson.message,
data?.replace(/[\n\r]/g, ' ')
)
}
}
} catch (_) {}
try {
const hasError = data?.includes('{"errorCode')
if (hasError) {
const parts = data.split('{"errorCode')
if (parts.length > 1) {
const error = '{"errorCode' + parts[1].split('"}')[0] + '"}'
const errorJson = JSON.parse(error.replace(/[\n\r]/g, ' '))
return new JobExecutionError(
errorJson.errorCode,
errorJson.message,
data?.replace(/[\n\r]/g, '\n')
)
}
}
} catch (_) {}
try {
const hasError = !!data?.match(/stored process not found: /i)
if (hasError) {
const parts = data.split(/stored process not found: /i)
if (parts.length > 1) {
const storedProcessPath = parts[1].split('<i>')[1].split('</i>')[0]
const message = `Stored process not found: ${storedProcessPath}`
return new JobExecutionError(404, message, '')
}
}
} catch (_) {}
try {
const hasError =
!!data?.match(/Stored Process Error/i) &&
!!data?.match(/This request completed with errors./i)
if (hasError) {
const parts = data.split('<h2>SAS Log</h2>')
if (parts.length > 1) {
const log = parts[1].split('<pre>')[1].split('</pre>')[0]
const message = `This request completed with errors.`
return new JobExecutionError(404, message, log)
}
}
} catch (_) {}
return null
}

View File

@@ -34,8 +34,7 @@ const prepareFilesAndParams = () => {
describe('FileUploader', () => {
const config: SASjsConfig = {
...new SASjsConfig(),
appLoc: '/sample/apploc',
debug: false
appLoc: '/sample/apploc'
}
const fileUploader = new FileUploader(

View File

@@ -33,18 +33,4 @@ 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)
})
})

View File

@@ -0,0 +1,22 @@
import { ExtraResponseAttributes } from '@sasjs/utils/types'
export async function appendExtraResponseAttributes(
response: any,
extraResponseAttributes: ExtraResponseAttributes[]
) {
let responseObject = {}
if (extraResponseAttributes?.length) {
const extraAttributes = extraResponseAttributes.reduce(
(map: any, obj: any) => ((map[obj] = response[obj]), map),
{}
)
responseObject = {
result: response.result,
...extraAttributes
}
} else responseObject = response.result
return responseObject
}

View File

@@ -6,8 +6,6 @@ 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

View File

@@ -15,3 +15,4 @@ export * from './parseWeboutResponse'
export * from './fetchLogByChunks'
export * from './getValidJson'
export * from './parseViyaDebugResponse'
export * from './appendExtraResponseAttributes'