From 52275ba67d97d5cbdf6c5511c9bd789bd6ca6b4e Mon Sep 17 00:00:00 2001 From: Yury Shkoda Date: Tue, 5 Oct 2021 11:18:20 +0300 Subject: [PATCH] feat(executor): response with webout --- src/controllers/sas.ts | 66 ++++++++++++++++++++++++++++++++++-------- src/routes/index.ts | 35 +++++++++++++++++----- src/types/request.ts | 1 + src/types/sas.ts | 5 ++-- 4 files changed, 85 insertions(+), 22 deletions(-) diff --git a/src/controllers/sas.ts b/src/controllers/sas.ts index 0c29b2b..a63b5a6 100644 --- a/src/controllers/sas.ts +++ b/src/controllers/sas.ts @@ -29,29 +29,71 @@ export const processSas = async ( const sasFile: string = sasCodePath.split(path.sep).pop() || 'default' - const sasLogPath = path.join( - getTmpLogFolderPath(), - [sasFile.replace(/\.sas/g, ''), '-', generateTimestamp(), '.log'].join('') + const logArgs = [] + let sasLogPath + + if (query._debug) { + sasLogPath = path.join( + getTmpLogFolderPath(), + [sasFile.replace(/\.sas/g, ''), '-', generateTimestamp(), '.log'].join('') + ) + logArgs.push('-log') + logArgs.push(sasLogPath) + } + + const sasWeboutPath = path.join( + getTmpWeboutFolderPath(), + [sasFile.replace(/\.sas/g, ''), '-', generateTimestamp(), '.json'].join('') ) + let sasCode = await readFile(sasCodePath) + const originalSasCode = sasCode + + if (query.macroVars) { + const macroVars = query.macroVars.macroVars + + Object.keys(macroVars).forEach( + (key: string) => (sasCode = `%let ${key}=${macroVars[key]};\n${sasCode}`) + ) + } + + sasCode = `filename _webout "${sasWeboutPath}";\n${sasCode}` + + await createFile(sasCodePath, sasCode) + const { stdout, stderr } = await execFilePromise(configuration.sasPath, [ '-SYSIN', sasCodePath, - '-log', - sasLogPath, + ...logArgs, '-nosplash' ]) if (stderr) return Promise.reject(stderr) - if (await fileExists(sasLogPath)) { - return Promise.resolve({ - log: await readFile(sasLogPath), - logPath: sasLogPath - }) + if (await fileExists(sasWeboutPath)) { + const webout = await readFile(sasWeboutPath) + + try { + const weboutJson = JSON.parse(webout) + + if (sasLogPath && (await fileExists(sasLogPath))) { + return Promise.resolve({ + webout: weboutJson, + log: await readFile(sasLogPath), + logPath: sasLogPath + }) + } else { + return Promise.resolve({ + webout: weboutJson + }) + } + } catch (error) { + return Promise.reject(`Error while parsing Webout. Details: ${error}`) + } } else { - return Promise.reject(`Log file wasn't created.`) + return Promise.reject(`Webout wasn't created.`) } - // deleteFile(sasLogPath) + // await createFile(sasCodePath, originalSasCode) + // await deleteFile(sasLogPath) } diff --git a/src/routes/index.ts b/src/routes/index.ts index 48c525f..7dc647a 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -48,15 +48,34 @@ router.post('/deploy', async (req, res) => { }) }) -router.post('/execute', async (req, res) => { - if (req.body?._program) { - await processSas(req.body) +// TODO: respond with HTML page including file tree +router.get('/SASjsExecutor', async (req, res) => { + res.status(200).send({ status: 'success', tree: {} }) +}) + +// SAS: +// https://sas.analytium.co.uk:8343/SASStoredProcess/do?_action=form,properties,execute,noba[…]blic%2Fapp%2Fdata-combiner%2Fservices%2Fcommon%2Fappinit +// https://sas.analytium.co.uk:8343/SASStoredProcess/ +// https://sas.analytium.co.uk:8343/SASStoredProcess/do?&_program=%2FPublic%2Fapp%2Fdata-combiner%2Fservices%2Fcommon%2Fappinit&_DEBUG=131 +// https://sas.analytium.co.uk:8343/SASStoredProcess/do?_program=%2FPublic%2Fapp%2Fdata-comb[…]ction=update%2Cnewwindow%2Cnobanner&_updatekey=895432774 + +// SASjs: +// http://localhost:5000/SASjsExecutor?_program=%2FPublic%2Fapp%2Fdata-combiner%2Fservices%2Fcommon%2Fappinit +// http://localhost:5000/SASjsExecutor +// http://localhost:5000/SASjsExecutor?_program=%2FPublic%2Fapp%2Fdata-combiner%2Fservices%2Fcommon%2Fappinit&_DEBUG=131 + +router.get('/SASjsExecutor/do', async (req, res) => { + const queryEntries = Object.keys(req.query).map((entry: string) => + entry.toLowerCase() + ) + const isDebug = queryEntries.find((entry: string) => entry === '_debug') + ? true + : false + + if (isRequestQuery(req.query)) { + await processSas({ ...req.query, _debug: isDebug }) .then((result) => { - res.status(200).send({ - status: 'success', - message: 'Job has been sent for execution.', - ...result - }) + res.status(200).send(result) }) .catch((err) => { res.status(400).send({ diff --git a/src/types/request.ts b/src/types/request.ts index 876dc89..26c872f 100644 --- a/src/types/request.ts +++ b/src/types/request.ts @@ -2,6 +2,7 @@ import { MacroVars } from '@sasjs/utils' export interface ExecutionQuery { _program: string macroVars?: MacroVars + _debug?: boolean } export const isRequestQuery = (arg: any): arg is ExecutionQuery => diff --git a/src/types/sas.ts b/src/types/sas.ts index 26d49b5..1147687 100644 --- a/src/types/sas.ts +++ b/src/types/sas.ts @@ -1,4 +1,5 @@ export interface ExecutionResult { - log: string - logPath: string + webout: object + log?: string + logPath?: string }