1
0
mirror of https://github.com/sasjs/server.git synced 2025-12-11 03:34:35 +00:00

Compare commits

..

20 Commits

Author SHA1 Message Date
semantic-release-bot
aa2a1cbe13 chore(release): 0.35.4 [skip ci]
## [0.35.4](https://github.com/sasjs/server/compare/v0.35.3...v0.35.4) (2024-01-15)

### Bug Fixes

* **api:** fixed env issue in MacOS executable ([73d965d](73d965daf5))
2024-01-15 13:21:15 +00:00
Yury Shkoda
6f2c53555c Merge pull request #372 from sasjs/issue-371
fix(api): fixed env issue in MacOS executable
2024-01-15 16:18:10 +03:00
Yury
73d965daf5 fix(api): fixed env issue in MacOS executable 2024-01-15 15:14:06 +03:00
semantic-release-bot
4f1763db67 chore(release): 0.35.3 [skip ci]
## [0.35.3](https://github.com/sasjs/server/compare/v0.35.2...v0.35.3) (2023-11-07)

### Bug Fixes

* enable embedded LFs in JS STP vars ([7e8cbbf](7e8cbbf377))
2023-11-07 20:48:28 +00:00
Allan Bowe
28222add04 Merge pull request #370 from sasjs/allanbowe-patch-1
fix: enable embedded LFs in JS STP vars
2023-11-07 20:43:16 +00:00
Allan
068edfd6a5 chore: lint fix 2023-11-07 20:39:05 +00:00
Allan Bowe
7e8cbbf377 fix: enable embedded LFs in JS STP vars 2023-11-07 15:51:32 +00:00
Allan Bowe
1fc1431442 chore: using GITHUB_TOKEN 2023-08-07 20:11:40 +01:00
semantic-release-bot
3387efbb9a chore(release): 0.35.2 [skip ci]
## [0.35.2](https://github.com/sasjs/server/compare/v0.35.1...v0.35.2) (2023-08-07)

### Bug Fixes

* add _debug as optional query param in swagger apis for GET stp/execute ([9586dbb](9586dbb2d0))
2023-08-07 18:53:12 +00:00
Allan Bowe
e2996b495f Merge pull request #365 from sasjs/swagger-fix
fix: add _debug as optional query param in swagger apis for  stp/execute
2023-08-07 19:48:28 +01:00
Allan
41c627f93a chore: lint fix 2023-08-07 19:39:02 +01:00
Allan Bowe
49f5dc7555 Update swagger.yaml 2023-08-07 19:32:29 +01:00
Allan Bowe
f6e77f99a4 Update swagger.yaml 2023-08-07 19:31:20 +01:00
Allan Bowe
b57dfa429b Update stp.ts 2023-08-07 19:30:09 +01:00
9586dbb2d0 fix: add _debug as optional query param in swagger apis for GET stp/execute 2023-08-07 22:01:52 +05:00
semantic-release-bot
a4f78ab48d chore(release): 0.35.1 [skip ci]
## [0.35.1](https://github.com/sasjs/server/compare/v0.35.0...v0.35.1) (2023-07-25)

### Bug Fixes

* **log-separator:** log separator should always wrap log ([8940f4d](8940f4dc47))
2023-07-25 06:05:23 +00:00
Yury Shkoda
2f47a2213b Merge pull request #364 from sasjs/log-separator
fix(log-separator): log separator should always wrap log
2023-07-25 09:01:36 +03:00
Yury Shkoda
0f91395fbb lint: fixed linting issues 2023-07-24 18:36:08 +03:00
Yury Shkoda
167b14fed0 docs(log-separator): left comment 2023-07-24 18:29:20 +03:00
Yury Shkoda
8940f4dc47 fix(log-separator): log separator should always wrap log 2023-07-24 18:27:21 +03:00
16 changed files with 129 additions and 46 deletions

View File

@@ -56,4 +56,4 @@ jobs:
- name: Release
run: |
GITHUB_TOKEN=${{ secrets.GH_TOKEN }} semantic-release
GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} semantic-release

View File

@@ -1,3 +1,31 @@
## [0.35.4](https://github.com/sasjs/server/compare/v0.35.3...v0.35.4) (2024-01-15)
### Bug Fixes
* **api:** fixed env issue in MacOS executable ([73d965d](https://github.com/sasjs/server/commit/73d965daf54b16c0921e4b18d11a1e6f8650884d))
## [0.35.3](https://github.com/sasjs/server/compare/v0.35.2...v0.35.3) (2023-11-07)
### Bug Fixes
* enable embedded LFs in JS STP vars ([7e8cbbf](https://github.com/sasjs/server/commit/7e8cbbf377b27a7f5dd9af0bc6605c01f302f5d9))
## [0.35.2](https://github.com/sasjs/server/compare/v0.35.1...v0.35.2) (2023-08-07)
### Bug Fixes
* add _debug as optional query param in swagger apis for GET stp/execute ([9586dbb](https://github.com/sasjs/server/commit/9586dbb2d0d6611061c9efdfb84030144f62c2ee))
## [0.35.1](https://github.com/sasjs/server/compare/v0.35.0...v0.35.1) (2023-07-25)
### Bug Fixes
* **log-separator:** log separator should always wrap log ([8940f4d](https://github.com/sasjs/server/commit/8940f4dc47abae2036b4fcdeb772c31a0ca07cca))
# [0.35.0](https://github.com/sasjs/server/compare/v0.34.2...v0.35.0) (2023-05-03)

16
api/package-lock.json generated
View File

@@ -51,7 +51,7 @@
"adm-zip": "^0.5.9",
"axios": "0.27.2",
"csrf": "^3.1.0",
"dotenv": "^10.0.0",
"dotenv": "^16.0.1",
"http-headers-validation": "^0.0.1",
"jest": "^27.0.6",
"mongodb-memory-server": "8.11.4",
@@ -4788,12 +4788,12 @@
}
},
"node_modules/dotenv": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
"integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==",
"version": "16.0.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz",
"integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==",
"dev": true,
"engines": {
"node": ">=10"
"node": ">=12"
}
},
"node_modules/duplexer2": {
@@ -15217,9 +15217,9 @@
}
},
"dotenv": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
"integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==",
"version": "16.0.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz",
"integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==",
"dev": true
},
"duplexer2": {

View File

@@ -88,7 +88,7 @@
"adm-zip": "^0.5.9",
"axios": "0.27.2",
"csrf": "^3.1.0",
"dotenv": "^10.0.0",
"dotenv": "^16.0.1",
"http-headers-validation": "^0.0.1",
"jest": "^27.0.6",
"mongodb-memory-server": "8.11.4",

View File

@@ -792,7 +792,7 @@ paths:
- {type: string}
- {type: string, format: byte}
description: 'Execute Code on the Specified Runtime'
summary: 'Run Code and Return Webout Content and Log'
summary: "Run Code and Return Webout Content, Log and Print output\nThe order of returned parts of the payload is:\n1. Webout (if present)\n2. Logs UUID (used as separator)\n3. Log\n4. Logs UUID (used as separator)\n5. Print (if present and if the runtime is SAS)\nPlease see"
tags:
- Code
security:
@@ -1798,13 +1798,22 @@ paths:
bearerAuth: []
parameters:
-
description: 'Location of code in SASjs Drive'
description: 'Location of the Stored Program in SASjs Drive'
in: query
name: _program
required: true
schema:
type: string
example: /Projects/myApp/some/program
-
description: 'Optional query param for setting debug mode (returns the session log in the response body)'
in: query
name: _debug
required: false
schema:
format: double
type: number
example: 131
post:
operationId: ExecutePostRequest
responses:

View File

@@ -128,8 +128,10 @@ export class ExecutionController {
// INFO: webout can be a Buffer, that is why it's length should be checked to determine if it is empty
if (webout && webout.length !== 0) resultParts.push(webout)
// INFO: log separator wraps the log from the beginning and the end
resultParts.push(process.logsUUID)
resultParts.push(log)
resultParts.push(process.logsUUID)
if (includePrintOutput && runTime === RunTimeType.SAS) {
const printOutputPath = path.join(session.path, 'output.lst')
@@ -137,10 +139,7 @@ export class ExecutionController {
? await readFile(printOutputPath)
: ''
if (printOutput) {
resultParts.push(process.logsUUID)
resultParts.push(printOutput)
}
if (printOutput) resultParts.push(printOutput)
}
return {

View File

@@ -190,17 +190,20 @@ ${autoExecContent}`
}
private scheduleSessionDestroy(session: Session) {
setTimeout(async () => {
if (session.inUse) {
// adding 10 more minutes
const newDeathTimeStamp = parseInt(session.deathTimeStamp) + 10 * 1000
session.deathTimeStamp = newDeathTimeStamp.toString()
setTimeout(
async () => {
if (session.inUse) {
// adding 10 more minutes
const newDeathTimeStamp = parseInt(session.deathTimeStamp) + 10 * 1000
session.deathTimeStamp = newDeathTimeStamp.toString()
this.scheduleSessionDestroy(session)
} else {
await this.deleteSession(session)
}
}, parseInt(session.deathTimeStamp) - new Date().getTime() - 100)
this.scheduleSessionDestroy(session)
} else {
await this.deleteSession(session)
}
},
parseInt(session.deathTimeStamp) - new Date().getTime() - 100
)
}
}

View File

@@ -15,7 +15,7 @@ export const createJSProgram = async (
) => {
const varStatments = Object.keys(vars).reduce(
(computed: string, key: string) =>
`${computed}const ${key} = '${vars[key]}';\n`,
`${computed}const ${key} = \`${vars[key]}\`;\n`,
''
)

View File

@@ -7,6 +7,7 @@ import {
getRunTimeAndFilePath
} from '../utils'
import { MulterFile } from '../types/Upload'
import { debug } from 'console'
interface ExecutePostRequestPayload {
/**
@@ -23,20 +24,30 @@ export class STPController {
/**
* Trigger a Stored Program using the _program URL parameter.
*
* Accepts URL parameters and file uploads. For more details, see docs:
* Accepts additional URL parameters (converted to session variables)
* and file uploads. For more details, see docs:
*
* https://server.sasjs.io/storedprograms
*
* @summary Execute a Stored Program, returns _webout and (optionally) log.
* @param _program Location of code in SASjs Drive
* @param _debug Optional query param for setting debug mode, which will return the session log.
* @example _program "/Projects/myApp/some/program"
* @example _debug 131
*/
@Get('/execute')
public async executeGetRequest(
@Request() request: express.Request,
@Query() _program: string
@Query() _program: string,
@Query() _debug?: number
): Promise<string | Buffer> {
const vars = request.query as ExecutionVars
let vars = request.query as ExecutionVars
if (_debug) {
vars = {
...vars,
_debug
}
}
return execute(request, _program, vars)
}

View File

@@ -13,7 +13,11 @@ stpRouter.get('/execute', async (req, res) => {
if (error) return res.status(400).send(error.details[0].message)
try {
const response = await controller.executeGetRequest(req, query._program)
const response = await controller.executeGetRequest(
req,
query._program,
query._debug
)
if (response instanceof Buffer) {
res.writeHead(200, (req as any).sasHeaders)

View File

@@ -1,9 +1,31 @@
import path from 'path'
import { createFolder, getAbsolutePath, getRealPath } from '@sasjs/utils'
import {
createFolder,
getAbsolutePath,
getRealPath,
fileExists
} from '@sasjs/utils'
import dotenv from 'dotenv'
import { connectDB, getDesktopFields, ModeType, RunTimeType, SECRETS } from '.'
export const setProcessVariables = async () => {
const { execPath } = process
// Check if execPath ends with 'api-macos' to determine executable for MacOS.
// This is needed to fix picking .env file issue in MacOS executable.
if (execPath) {
const envPathSplitted = execPath.split(path.sep)
if (envPathSplitted.pop() === 'api-macos') {
const envPath = path.join(envPathSplitted.join(path.sep), '.env')
// Override environment variables from envPath if file exists
if (await fileExists(envPath)) {
dotenv.config({ path: envPath, override: true })
}
}
}
const { MODE, RUN_TIMES } = process.env
if (MODE === ModeType.Server) {
@@ -21,6 +43,7 @@ export const setProcessVariables = async () => {
if (process.env.NODE_ENV === 'test') {
process.sasjsRoot = path.join(process.cwd(), 'sasjs_root')
process.driveLoc = path.join(process.cwd(), 'sasjs_root', 'drive')
return
}
@@ -41,7 +64,9 @@ export const setProcessVariables = async () => {
const { SASJS_ROOT } = process.env
const absPath = getAbsolutePath(SASJS_ROOT ?? 'sasjs_root', process.cwd())
await createFolder(absPath)
process.sasjsRoot = getRealPath(absPath)
const { DRIVE_LOCATION } = process.env
@@ -49,6 +74,7 @@ export const setProcessVariables = async () => {
DRIVE_LOCATION ?? path.join(process.sasjsRoot, 'drive'),
process.cwd()
)
await createFolder(absDrivePath)
process.driveLoc = getRealPath(absDrivePath)
@@ -57,7 +83,9 @@ export const setProcessVariables = async () => {
LOG_LOCATION ?? path.join(process.sasjsRoot, 'logs'),
process.cwd()
)
await createFolder(absLogsPath)
process.logsLoc = getRealPath(absLogsPath)
process.logsUUID = 'SASJS_LOGS_SEPARATOR_163ee17b6ff24f028928972d80a26784'

View File

@@ -51,9 +51,8 @@ export const generateFileUploadSasCode = async (
let fileCount = 0
const uploadedFiles: UploadedFiles[] = []
const sasSessionFolderList: string[] = await listFilesInFolder(
sasSessionFolder
)
const sasSessionFolderList: string[] =
await listFilesInFolder(sasSessionFolder)
sasSessionFolderList.forEach((fileName) => {
let fileCountString = fileCount < 100 ? '0' + fileCount : fileCount
fileCountString = fileCount < 10 ? '00' + fileCount : fileCount

View File

@@ -180,7 +180,8 @@ export const runCodeValidation = (data: any): Joi.ValidationResult =>
export const executeProgramRawValidation = (data: any): Joi.ValidationResult =>
Joi.object({
_program: Joi.string().required()
_program: Joi.string().required(),
_debug: Joi.number()
})
.pattern(/^/, Joi.alternatives(Joi.string(), Joi.number()))
.validate(data)

View File

@@ -3,12 +3,11 @@ import Snackbar from '@mui/material/Snackbar'
import MuiAlert, { AlertProps } from '@mui/material/Alert'
import Slide, { SlideProps } from '@mui/material/Slide'
const Alert = React.forwardRef<HTMLDivElement, AlertProps>(function Alert(
props,
ref
) {
return <MuiAlert elevation={6} ref={ref} variant="filled" {...props} />
})
const Alert = React.forwardRef<HTMLDivElement, AlertProps>(
function Alert(props, ref) {
return <MuiAlert elevation={6} ref={ref} variant="filled" {...props} />
}
)
const Transition = (props: SlideProps) => {
return <Slide {...props} direction="up" />

View File

@@ -7,8 +7,10 @@
border: none;
outline: none;
transition: 0.4s;
box-shadow: rgba(0, 0, 0, 0.2) 0px 2px 1px -1px,
rgba(0, 0, 0, 0.14) 0px 1px 1px 0px, rgba(0, 0, 0, 0.12) 0px 1px 3px 0px;
box-shadow:
rgba(0, 0, 0, 0.2) 0px 2px 1px -1px,
rgba(0, 0, 0, 0.14) 0px 1px 1px 0px,
rgba(0, 0, 0, 0.12) 0px 1px 3px 0px;
}
.ChunkDetails {

View File

@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />