1
0
mirror of https://github.com/sasjs/adapter.git synced 2025-12-11 01:14:36 +00:00
Files
adapter/src/job-execution/FileUploader.ts
2022-06-20 19:36:12 +03:00

157 lines
4.6 KiB
TypeScript

import {
getValidJson,
parseSasViyaDebugResponse,
parseWeboutResponse
} from '../utils'
import { UploadFile } from '../types/UploadFile'
import {
ErrorResponse,
JobExecutionError,
LoginRequiredError
} from '../types/errors'
import { RequestClient } from '../request/RequestClient'
import { ServerType } from '@sasjs/utils/types'
import { BaseJobExecutor } from './JobExecutor'
interface dataFileUpload {
files: UploadFile[]
params: { [key: string]: any } | null
}
export class FileUploader extends BaseJobExecutor {
constructor(
serverUrl: string,
serverType: ServerType,
private jobsPath: string,
private requestClient: RequestClient
) {
super(serverUrl, serverType)
}
public async execute(
sasJob: string,
data: any,
config: any,
loginRequiredCallback?: any
) {
const { files, params }: dataFileUpload = data
const loginCallback = loginRequiredCallback || (() => Promise.resolve())
if (!files?.length)
throw new ErrorResponse('At least one file must be provided.')
if (!sasJob || sasJob === '')
throw new ErrorResponse('sasJob must be provided.')
let paramsString = ''
for (let param in params)
if (params.hasOwnProperty(param))
paramsString += `&${param}=${params[param]}`
const program = config.appLoc
? config.appLoc.replace(/\/?$/, '/') + sasJob.replace(/^\//, '')
: sasJob
const uploadUrl = `${this.jobsPath}/?${
'_program=' + program
}${paramsString}`
const formData = new FormData()
for (let file of files) {
formData.append('file', file.file, file.fileName)
}
const csrfToken = this.requestClient.getCsrfToken('file')
if (csrfToken) formData.append('_csrf', csrfToken.value)
if (config.debug) formData.append('_debug', '131')
if (config.serverType === ServerType.SasViya && config.contextName)
formData.append('_contextname', config.contextName)
const headers = {
'cache-control': 'no-cache',
Accept: '*/*',
'Content-Type': 'text/plain'
}
// currently only web approach is supported for file upload
// therefore log is part of response with debug enabled and must be parsed
const requestPromise = new Promise((resolve, reject) => {
this.requestClient
.post(uploadUrl, formData, undefined, 'application/json', headers)
.then(async (res: any) => {
this.requestClient.appendRequest(res, sasJob, config.debug)
let jsonResponse = res.result
if (config.debug) {
switch (this.serverType) {
case ServerType.SasViya:
jsonResponse = await parseSasViyaDebugResponse(
res.result,
this.requestClient,
config.serverUrl
)
break
case ServerType.Sas9:
jsonResponse =
typeof res.result === 'string'
? parseWeboutResponse(res.result, uploadUrl)
: res.result
break
case ServerType.Sasjs:
if (typeof res.result._webout === 'object') {
jsonResponse = res.result._webout
} else {
const webout = parseWeboutResponse(
res.result._webout,
uploadUrl
)
jsonResponse = getValidJson(webout)
}
break
}
} else if (this.serverType === ServerType.Sasjs) {
jsonResponse = getValidJson(res.result._webout)
} else {
jsonResponse =
typeof res.result === 'string'
? getValidJson(res.result)
: res.result
}
resolve(jsonResponse)
})
.catch(async (e: Error) => {
if (e instanceof JobExecutionError) {
this.requestClient!.appendRequest(e, sasJob, config.debug)
reject(new ErrorResponse(e?.message, e))
}
if (e instanceof LoginRequiredError) {
this.appendWaitingRequest(() => {
return this.execute(
sasJob,
data,
config,
loginRequiredCallback
).then(
(res: any) => {
resolve(res)
},
(err: any) => {
reject(err)
}
)
})
await loginCallback()
} else {
reject(new ErrorResponse('File upload request failed.', e))
}
})
})
return requestPromise
}
}