mirror of
https://github.com/sasjs/adapter.git
synced 2025-12-10 17:04:36 +00:00
138 lines
4.1 KiB
TypeScript
138 lines
4.1 KiB
TypeScript
import * as https from 'https'
|
|
import { ServerType } from '@sasjs/utils/types'
|
|
import NodeFormData from 'form-data'
|
|
import { ErrorResponse } from '../types/errors'
|
|
import { convertToCSV, isRelativePath } from '../utils'
|
|
import { BaseJobExecutor } from './JobExecutor'
|
|
import { Sas9RequestClient } from '../request/Sas9RequestClient'
|
|
import { RequestClient } from '../request/RequestClient'
|
|
|
|
/**
|
|
* Job executor for SAS9 servers for use in Node.js environments.
|
|
* Initiates login with the provided username and password from the config
|
|
* The cookies are stored in the request client and used in subsequent
|
|
* job execution requests.
|
|
*/
|
|
export class Sas9JobExecutor extends BaseJobExecutor {
|
|
private sas9RequestClient: Sas9RequestClient
|
|
constructor(
|
|
serverUrl: string,
|
|
serverType: ServerType,
|
|
private jobsPath: string,
|
|
private requestClient: RequestClient,
|
|
httpsAgentOptions?: https.AgentOptions
|
|
) {
|
|
super(serverUrl, serverType)
|
|
this.sas9RequestClient = new Sas9RequestClient(serverUrl, httpsAgentOptions)
|
|
}
|
|
|
|
async execute(sasJob: string, data: any, config: any) {
|
|
const program = isRelativePath(sasJob)
|
|
? config.appLoc
|
|
? config.appLoc.replace(/\/?$/, '/') + sasJob.replace(/^\//, '')
|
|
: sasJob
|
|
: sasJob
|
|
let apiUrl = `${config.serverUrl}${this.jobsPath}?${'_program=' + program}`
|
|
apiUrl = `${apiUrl}${
|
|
config.username && config.password
|
|
? '&_username=' + config.username + '&_password=' + config.password
|
|
: ''
|
|
}`
|
|
|
|
apiUrl = `${apiUrl}${config.debug ? '&_debug=131' : ''}`
|
|
|
|
let requestParams = {
|
|
...this.getRequestParams(config)
|
|
}
|
|
|
|
let formData = new NodeFormData()
|
|
|
|
if (data) {
|
|
try {
|
|
formData = generateFileUploadForm(formData, data)
|
|
} catch (e: any) {
|
|
return Promise.reject(new ErrorResponse(e?.message, e))
|
|
}
|
|
} else {
|
|
data = ''
|
|
}
|
|
|
|
for (const key in requestParams) {
|
|
if (requestParams.hasOwnProperty(key)) {
|
|
formData.append(key, requestParams[key])
|
|
}
|
|
}
|
|
|
|
await this.sas9RequestClient.login(
|
|
config.username,
|
|
config.password,
|
|
this.jobsPath
|
|
)
|
|
|
|
const contentType =
|
|
data && Object.keys(data).length
|
|
? 'multipart/form-data; boundary=' + (formData as any)._boundary
|
|
: 'text/plain'
|
|
|
|
const requestPromise = new Promise((resolve, reject) =>
|
|
this.sas9RequestClient!.post(apiUrl, formData, undefined, contentType, {
|
|
Accept: '*/*',
|
|
Connection: 'Keep-Alive'
|
|
})
|
|
.then((res: any) => {
|
|
// appending response to requests array that will be used for requests history reference
|
|
this.requestClient!.appendRequest(res, sasJob, config.debug)
|
|
resolve(res)
|
|
})
|
|
.catch((err: any) => {
|
|
// by default error string is equal to actual error object
|
|
let errString = err
|
|
|
|
// if error object contains non empty result attribute, set result to errString
|
|
if (err.result && err.result !== '') errString = err.result
|
|
// if there's no result but error message, set error message to errString
|
|
else if (err.message) errString = err.message
|
|
|
|
// appending error to requests array that will be used for requests history reference
|
|
this.requestClient!.appendRequest(errString, sasJob, config.debug)
|
|
reject(new ErrorResponse(err?.message, err))
|
|
})
|
|
)
|
|
|
|
return requestPromise
|
|
}
|
|
|
|
protected getRequestParams(config: any): any {
|
|
const requestParams: any = {}
|
|
|
|
if (config.debug) {
|
|
requestParams['_debug'] = 131
|
|
}
|
|
|
|
return requestParams
|
|
}
|
|
}
|
|
|
|
const generateFileUploadForm = (
|
|
formData: NodeFormData,
|
|
data: any
|
|
): NodeFormData => {
|
|
for (const tableName in data) {
|
|
const name = tableName
|
|
const csv = convertToCSV(data, tableName)
|
|
|
|
if (csv === 'ERROR: LARGE STRING LENGTH') {
|
|
throw new Error(
|
|
'The max length of a string value in SASjs is 32765 characters.'
|
|
)
|
|
}
|
|
|
|
formData.append(name, csv, {
|
|
filename: `${name}.csv`,
|
|
contentType: 'application/csv'
|
|
})
|
|
}
|
|
|
|
return formData
|
|
}
|