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

Compare commits

...

13 Commits

Author SHA1 Message Date
Saad Jutt
122faad55f chore(release): 0.0.48 2022-04-02 07:06:18 +05:00
Saad Jutt
3ff6f5e865 fix(stp): return log+webout for debug on 2022-04-02 07:06:09 +05:00
Muhammad Saad
7d5128c0d6 Merge pull request #115 from sasjs/issue109
feat(deploy): new route added for deploy with build.json
2022-04-02 06:45:28 +05:00
Saad Jutt
e1ebbfd087 chore: increased file upload size to 100mb 2022-04-02 06:04:34 +05:00
Saad Jutt
e430bdb0d4 test(upload): spec updated for file upload exceeding limit 2022-04-02 05:51:24 +05:00
Saad Jutt
9d9769eef3 chore: increased file upload size to 100mb 2022-04-02 05:36:53 +05:00
Saad Jutt
9d167abe2a fix: remove uploaded build.json from temp folder in all cases 2022-04-02 05:29:34 +05:00
Saad Jutt
18d0604bdd feat(deploy): new route added for deploy with build.json 2022-04-02 05:23:25 +05:00
Saad Jutt
7b7bc6b778 chore: fix vulnerabilities 2022-03-31 01:54:40 +05:00
Saad Jutt
fb4f3442d5 chore(release): 0.0.47 2022-03-30 01:04:45 +05:00
Muhammad Saad
09d1b7d5d4 Merge pull request #114 from sasjs/show-contents-as-api-responded
fix: show contents as api responded
2022-03-30 01:04:29 +05:00
Saad Jutt
99839ae62f chore: fix vulnerabilities 2022-03-30 00:55:59 +05:00
Saad Jutt
f700561e1a fix(web): updated STUDIO log and webout 2022-03-30 00:55:38 +05:00
19 changed files with 211 additions and 152 deletions

View File

@@ -2,6 +2,26 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [0.0.48](https://github.com/sasjs/server/compare/v0.0.47...v0.0.48) (2022-04-02)
### Features
* **deploy:** new route added for deploy with build.json ([18d0604](https://github.com/sasjs/server/commit/18d0604bdd0b20ad468f9345474b4de034ee3a67))
### Bug Fixes
* remove uploaded build.json from temp folder in all cases ([9d167ab](https://github.com/sasjs/server/commit/9d167abe2adb743bca161862b4561bf573182c00))
* **stp:** return log+webout for debug on ([3ff6f5e](https://github.com/sasjs/server/commit/3ff6f5e86581cd2ac23bbe0b8e2c367fbea890ed))
### [0.0.47](https://github.com/sasjs/server/compare/v0.0.46...v0.0.47) (2022-03-29)
### Bug Fixes
* **web:** updated STUDIO log and webout ([f700561](https://github.com/sasjs/server/commit/f700561e1a8d06c18ca2bdbe4605d7ab34f7a761))
### [0.0.46](https://github.com/sasjs/server/compare/v0.0.45...v0.0.46) (2022-03-29) ### [0.0.46](https://github.com/sasjs/server/compare/v0.0.45...v0.0.46) (2022-03-29)

26
api/package-lock.json generated
View File

@@ -9,7 +9,7 @@
"version": "0.0.2", "version": "0.0.2",
"dependencies": { "dependencies": {
"@sasjs/core": "4.9.0", "@sasjs/core": "4.9.0",
"@sasjs/utils": "2.36.2", "@sasjs/utils": "2.42.1",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
"cors": "^2.8.5", "cors": "^2.8.5",
@@ -1384,9 +1384,9 @@
"integrity": "sha512-zc1Ey0ylHt/eRZAfK0mVG3EqNyq//wLxbiguiK0R6FhVqwYFEkprs3IiLGZ5M9ttKs2rHRIjOe/ckklHm+6HNQ==" "integrity": "sha512-zc1Ey0ylHt/eRZAfK0mVG3EqNyq//wLxbiguiK0R6FhVqwYFEkprs3IiLGZ5M9ttKs2rHRIjOe/ckklHm+6HNQ=="
}, },
"node_modules/@sasjs/utils": { "node_modules/@sasjs/utils": {
"version": "2.36.2", "version": "2.42.1",
"resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.36.2.tgz", "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.42.1.tgz",
"integrity": "sha512-r0O9vkNIK5+2peBiGbcKc3Ei62eAMDt+1SQl17U9Vv26LYqezxQBwIYYMUjnkZE8Q7XlTI/FUS+SIHTCZMr4Jg==", "integrity": "sha512-DzHNYjeoj2eUkwV7Sa4eHCKRoTrYaQ6eyv6c1U5qOYXwVdZpMoYA3HFsHj55UcMOn2U3CXI5nrR7PZlUmVwVbQ==",
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
"@types/fs-extra": "9.0.13", "@types/fs-extra": "9.0.13",
@@ -7107,9 +7107,9 @@
} }
}, },
"node_modules/minimist": { "node_modules/minimist": {
"version": "1.2.5", "version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
}, },
"node_modules/mkdirp": { "node_modules/mkdirp": {
"version": "1.0.4", "version": "1.0.4",
@@ -11132,9 +11132,9 @@
"integrity": "sha512-zc1Ey0ylHt/eRZAfK0mVG3EqNyq//wLxbiguiK0R6FhVqwYFEkprs3IiLGZ5M9ttKs2rHRIjOe/ckklHm+6HNQ==" "integrity": "sha512-zc1Ey0ylHt/eRZAfK0mVG3EqNyq//wLxbiguiK0R6FhVqwYFEkprs3IiLGZ5M9ttKs2rHRIjOe/ckklHm+6HNQ=="
}, },
"@sasjs/utils": { "@sasjs/utils": {
"version": "2.36.2", "version": "2.42.1",
"resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.36.2.tgz", "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.42.1.tgz",
"integrity": "sha512-r0O9vkNIK5+2peBiGbcKc3Ei62eAMDt+1SQl17U9Vv26LYqezxQBwIYYMUjnkZE8Q7XlTI/FUS+SIHTCZMr4Jg==", "integrity": "sha512-DzHNYjeoj2eUkwV7Sa4eHCKRoTrYaQ6eyv6c1U5qOYXwVdZpMoYA3HFsHj55UcMOn2U3CXI5nrR7PZlUmVwVbQ==",
"requires": { "requires": {
"@types/fs-extra": "9.0.13", "@types/fs-extra": "9.0.13",
"@types/prompts": "2.0.13", "@types/prompts": "2.0.13",
@@ -15624,9 +15624,9 @@
} }
}, },
"minimist": { "minimist": {
"version": "1.2.5", "version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
}, },
"mkdirp": { "mkdirp": {
"version": "1.0.4", "version": "1.0.4",

View File

@@ -47,7 +47,7 @@
"author": "4GL Ltd", "author": "4GL Ltd",
"dependencies": { "dependencies": {
"@sasjs/core": "4.9.0", "@sasjs/core": "4.9.0",
"@sasjs/utils": "2.36.2", "@sasjs/utils": "2.42.1",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
"cors": "^2.8.5", "cors": "^2.8.5",

View File

@@ -606,6 +606,56 @@ paths:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/DeployPayload' $ref: '#/components/schemas/DeployPayload'
/SASjsApi/drive/deploy/upload:
post:
operationId: DeployUpload
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/DeployResponse'
examples:
'Example 1':
value: {status: success, message: 'Files deployed successfully to @sasjs/server.'}
'400':
description: 'Invalid Format'
content:
application/json:
schema:
$ref: '#/components/schemas/DeployResponse'
examples:
'Example 1':
value: {status: failure, message: 'Provided not supported data format.'}
'500':
description: 'Execution Error'
content:
application/json:
schema:
$ref: '#/components/schemas/DeployResponse'
examples:
'Example 1':
value: {status: failure, message: 'Deployment failed!'}
summary: 'Creates/updates files within SASjs Drive using uploaded JSON file.'
tags:
- Drive
security:
-
bearerAuth: []
parameters: []
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
format: binary
required:
- file
/SASjsApi/drive/file: /SASjsApi/drive/file:
get: get:
operationId: GetFile operationId: GetFile

View File

@@ -1,5 +1,6 @@
import path from 'path' import path from 'path'
import { import {
CompileTree,
createFile, createFile,
loadDependenciesFile, loadDependenciesFile,
readFile, readFile,
@@ -18,7 +19,8 @@ const compiledSystemInit = async (systemInit: string) =>
macroFolders: [], macroFolders: [],
buildSourceFolder: '', buildSourceFolder: '',
binaryFolders: [], binaryFolders: [],
macroCorePath macroCorePath,
compileTree: new CompileTree('') // dummy compileTree
})) }))
const createSysInitFile = async () => { const createSysInitFile = async () => {

View File

@@ -14,7 +14,8 @@ import {
Patch, Patch,
UploadedFile, UploadedFile,
FormField, FormField,
Delete Delete,
Hidden
} from 'tsoa' } from 'tsoa'
import { import {
fileExists, fileExists,
@@ -22,14 +23,15 @@ import {
createFolder, createFolder,
deleteFile as deleteFileOnSystem, deleteFile as deleteFileOnSystem,
folderExists, folderExists,
listFilesAndSubFoldersInFolder,
listFilesInFolder, listFilesInFolder,
listSubFoldersInFolder, listSubFoldersInFolder,
isFolder isFolder,
FileTree,
isFileTree
} from '@sasjs/utils' } from '@sasjs/utils'
import { createFileTree, ExecutionController, getTreeExample } from './internal' import { createFileTree, ExecutionController, getTreeExample } from './internal'
import { FileTree, isFileTree, TreeNode } from '../types' import { TreeNode } from '../types'
import { getTmpFilesFolderPath } from '../utils' import { getTmpFilesFolderPath } from '../utils'
interface DeployPayload { interface DeployPayload {
@@ -93,6 +95,21 @@ export class DriveController {
return deploy(body) return deploy(body)
} }
/**
* @summary Creates/updates files within SASjs Drive using uploaded JSON file.
*
*/
@Example<DeployResponse>(successDeployResponse)
@Response<DeployResponse>(400, 'Invalid Format', invalidDeployFormatResponse)
@Response<DeployResponse>(500, 'Execution Error', execDeployErrorResponse)
@Post('/deploy/upload')
public async deployUpload(
@UploadedFile() file: Express.Multer.File, // passing here for API docs
@Query() @Hidden() body?: DeployPayload // Hidden decorator has be optional
): Promise<DeployResponse> {
return deploy(body!)
}
/** /**
* *
* @summary Get file from SASjs Drive * @summary Get file from SASjs Drive

View File

@@ -178,11 +178,10 @@ ${program}`
return { return {
httpHeaders, httpHeaders,
result: fileResponse result:
? webout isDebugOn(vars) || session.crashed
: isDebugOn(vars) || session.crashed ? `<html><body>${webout}<div style="text-align:left"><hr /><h2>SAS Log</h2><pre>${log}</pre></div></body></html>`
? `<html><body>${webout}<div style="text-align:left"><hr /><h2>SAS Log</h2><pre>${log}</pre></div></body></html>` : webout
: webout
} }
} }

View File

@@ -1,13 +1,15 @@
import path from 'path' import path from 'path'
import { getTmpFilesFolderPath } from '../../utils/file'
import { import {
MemberType, createFolder,
createFile,
asyncForEach,
FolderMember, FolderMember,
ServiceMember, ServiceMember,
FileTree, FileMember,
FileMember MemberType,
} from '../../types' FileTree
import { getTmpFilesFolderPath } from '../../utils/file' } from '@sasjs/utils'
import { createFolder, createFile, asyncForEach } from '@sasjs/utils'
// REFACTOR: export FileTreeCpntroller // REFACTOR: export FileTreeCpntroller
export const createFileTree = async ( export const createFileTree = async (

View File

@@ -4,7 +4,7 @@ import multer, { FileFilterCallback, Options } from 'multer'
import { blockFileRegex, getTmpUploadsPath } from '../utils' import { blockFileRegex, getTmpUploadsPath } from '../utils'
const fieldNameSize = 300 const fieldNameSize = 300
const fileSize = 10485760 // 10 MB const fileSize = 104857600 // 100 MB
const storage = multer.diskStorage({ const storage = multer.diskStorage({
destination: getTmpUploadsPath(), destination: getTmpUploadsPath(),

View File

@@ -1,5 +1,5 @@
import express from 'express' import express from 'express'
import { deleteFile } from '@sasjs/utils' import { deleteFile, readFile } from '@sasjs/utils'
import { publishAppStream } from '../appStream' import { publishAppStream } from '../appStream'
@@ -43,6 +43,54 @@ driveRouter.post('/deploy', async (req, res) => {
} }
}) })
driveRouter.post(
'/deploy/upload',
(...arg) => multerSingle('file', arg),
async (req, res) => {
if (!req.file) return res.status(400).send('"file" is not present.')
const fileContent = await readFile(req.file.path)
let jsonContent
try {
jsonContent = JSON.parse(fileContent)
} catch (err) {
deleteFile(req.file.path)
return res.status(400).send('File containing invalid JSON content.')
}
const { error, value: body } = deployValidation(jsonContent)
if (error) {
deleteFile(req.file.path)
return res.status(400).send(error.details[0].message)
}
try {
const response = await controller.deployUpload(req.file, body)
if (body.streamWebFolder) {
const { streamServiceName } = await publishAppStream(
body.appLoc,
body.streamWebFolder,
body.streamServiceName,
body.streamLogo
)
response.streamServiceName = streamServiceName
}
res.send(response)
} catch (err: any) {
const statusCode = err.code
delete err.code
res.status(statusCode).send(err)
} finally {
deleteFile(req.file.path)
}
}
)
driveRouter.get('/file', async (req, res) => { driveRouter.get('/file', async (req, res) => {
const { error: errQ, value: query } = fileParamValidation(req.query) const { error: errQ, value: query } = fileParamValidation(req.query)

View File

@@ -12,7 +12,9 @@ import {
generateTimestamp, generateTimestamp,
copy, copy,
createFolder, createFolder,
createFile createFile,
ServiceMember,
FolderMember
} from '@sasjs/utils' } from '@sasjs/utils'
import * as fileUtilModules from '../../../utils/file' import * as fileUtilModules from '../../../utils/file'
@@ -28,7 +30,6 @@ jest
import appPromise from '../../../app' import appPromise from '../../../app'
import { UserController } from '../../../controllers/' import { UserController } from '../../../controllers/'
import { getTreeExample } from '../../../controllers/internal' import { getTreeExample } from '../../../controllers/internal'
import { FolderMember, ServiceMember } from '../../../types'
import { generateAccessToken, saveTokensInDB } from '../../../utils/' import { generateAccessToken, saveTokensInDB } from '../../../utils/'
const { getTmpFilesFolderPath } = fileUtilModules const { getTmpFilesFolderPath } = fileUtilModules
@@ -424,7 +425,7 @@ describe('drive', () => {
it('should respond with Bad Request if attached file exceeds file limit', async () => { it('should respond with Bad Request if attached file exceeds file limit', async () => {
const pathToUpload = '/my/path/code.sas' const pathToUpload = '/my/path/code.sas'
const attachedFile = Buffer.from('.'.repeat(20 * 1024 * 1024)) const attachedFile = Buffer.from('.'.repeat(110 * 1024 * 1024)) // 110mb
const res = await request(app) const res = await request(app)
.post('/SASjsApi/drive/file') .post('/SASjsApi/drive/file')
@@ -434,7 +435,7 @@ describe('drive', () => {
.expect(400) .expect(400)
expect(res.text).toEqual( expect(res.text).toEqual(
'File size is over limit. File limit is: 10 MB' 'File size is over limit. File limit is: 100 MB'
) )
expect(res.body).toEqual({}) expect(res.body).toEqual({})
}) })
@@ -582,7 +583,7 @@ describe('drive', () => {
it('should respond with Bad Request if attached file exceeds file limit', async () => { it('should respond with Bad Request if attached file exceeds file limit', async () => {
const pathToUpload = '/my/path/code.sas' const pathToUpload = '/my/path/code.sas'
const attachedFile = Buffer.from('.'.repeat(20 * 1024 * 1024)) const attachedFile = Buffer.from('.'.repeat(110 * 1024 * 1024)) // 110mb
const res = await request(app) const res = await request(app)
.patch('/SASjsApi/drive/file') .patch('/SASjsApi/drive/file')
@@ -592,7 +593,7 @@ describe('drive', () => {
.expect(400) .expect(400)
expect(res.text).toEqual( expect(res.text).toEqual(
'File size is over limit. File limit is: 10 MB' 'File size is over limit. File limit is: 100 MB'
) )
expect(res.body).toEqual({}) expect(res.body).toEqual({})
}) })

View File

@@ -52,7 +52,7 @@ export const publishAppStream = async (
addEntryToFile addEntryToFile
) )
const sasJsPort = process.env.PORT ?? 5000 const sasJsPort = process.env.PORT || 5000
console.log( console.log(
'Serving Stream App: ', 'Serving Stream App: ',
`http://localhost:${sasJsPort}/AppStream/${streamServiceName}` `http://localhost:${sasJsPort}/AppStream/${streamServiceName}`

View File

@@ -4,8 +4,8 @@ import appPromise from './app'
import { getCertificates } from './utils' import { getCertificates } from './utils'
appPromise.then(async (app) => { appPromise.then(async (app) => {
const protocol = process.env.PROTOCOL ?? 'http' const protocol = process.env.PROTOCOL || 'http'
const sasJsPort = process.env.PORT ?? 5000 const sasJsPort = process.env.PORT || 5000
console.log('PROTOCOL: ', protocol) console.log('PROTOCOL: ', protocol)

View File

@@ -1,62 +0,0 @@
export enum MemberType {
service = 'service',
file = 'file',
folder = 'folder'
}
export interface ServiceMember {
name: string
type: MemberType.service
code: string
}
export interface FileMember {
name: string
type: MemberType.file
code: string
}
export interface FolderMember {
name: string
type: MemberType.folder
members: (FolderMember | ServiceMember | FileMember)[]
}
export interface FileTree {
members: (FolderMember | ServiceMember | FileMember)[]
}
export const isFileTree = (arg: any): arg is FileTree =>
arg &&
arg.members &&
Array.isArray(arg.members) &&
arg.members.filter(
(member: ServiceMember | FileMember | FolderMember) =>
!isServiceMember(member, '-') &&
!isFileMember(member, '-') &&
!isFolderMember(member, '-')
).length === 0
const isServiceMember = (arg: any, pre: string): arg is ServiceMember =>
arg &&
typeof arg.name === 'string' &&
arg.type === MemberType.service &&
typeof arg.code === 'string'
const isFileMember = (arg: any, pre: string): arg is ServiceMember =>
arg &&
typeof arg.name === 'string' &&
arg.type === MemberType.file &&
typeof arg.code === 'string'
const isFolderMember = (arg: any, pre: string): arg is FolderMember =>
arg &&
typeof arg.name === 'string' &&
arg.type === MemberType.folder &&
arg.members &&
Array.isArray(arg.members) &&
arg.members.filter(
(member: FolderMember | ServiceMember) =>
!isServiceMember(member, pre + '-') &&
!isFileMember(member, pre + '-') &&
!isFolderMember(member, pre + '-')
).length === 0

View File

@@ -1,7 +1,6 @@
// TODO: uppercase types // TODO: uppercase types
export * from './AppStreamConfig' export * from './AppStreamConfig'
export * from './Execution' export * from './Execution'
export * from './FileTree'
export * from './InfoJWT' export * from './InfoJWT'
export * from './PreProgramVars' export * from './PreProgramVars'
export * from './Request' export * from './Request'

16
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "server", "name": "server",
"version": "0.0.46", "version": "0.0.48",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "server", "name": "server",
"version": "0.0.46", "version": "0.0.48",
"devDependencies": { "devDependencies": {
"prettier": "^2.3.1", "prettier": "^2.3.1",
"standard-version": "^9.3.2" "standard-version": "^9.3.2"
@@ -1350,9 +1350,9 @@
} }
}, },
"node_modules/minimist": { "node_modules/minimist": {
"version": "1.2.5", "version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
"dev": true "dev": true
}, },
"node_modules/minimist-options": { "node_modules/minimist-options": {
@@ -3158,9 +3158,9 @@
} }
}, },
"minimist": { "minimist": {
"version": "1.2.5", "version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
"dev": true "dev": true
}, },
"minimist-options": { "minimist-options": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "server", "name": "server",
"version": "0.0.46", "version": "0.0.48",
"description": "NodeJS wrapper for calling the SAS binary executable", "description": "NodeJS wrapper for calling the SAS binary executable",
"repository": "https://github.com/sasjs/server", "repository": "https://github.com/sasjs/server",
"scripts": { "scripts": {

24
web/package-lock.json generated
View File

@@ -8472,9 +8472,9 @@
} }
}, },
"node_modules/minimist": { "node_modules/minimist": {
"version": "1.2.5", "version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
}, },
"node_modules/mkdirp": { "node_modules/mkdirp": {
"version": "0.5.5", "version": "0.5.5",
@@ -8581,9 +8581,9 @@
} }
}, },
"node_modules/node-forge": { "node_modules/node-forge": {
"version": "1.2.1", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.2.1.tgz", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.0.tgz",
"integrity": "sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w==", "integrity": "sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">= 6.13.0" "node": ">= 6.13.0"
@@ -17622,9 +17622,9 @@
} }
}, },
"minimist": { "minimist": {
"version": "1.2.5", "version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
}, },
"mkdirp": { "mkdirp": {
"version": "0.5.5", "version": "0.5.5",
@@ -17715,9 +17715,9 @@
} }
}, },
"node-forge": { "node-forge": {
"version": "1.2.1", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.2.1.tgz", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.0.tgz",
"integrity": "sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w==", "integrity": "sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA==",
"dev": true "dev": true
}, },
"node-releases": { "node-releases": {

View File

@@ -50,25 +50,9 @@ const Studio = () => {
.map((logLine: any) => logLine.line) .map((logLine: any) => logLine.line)
.join('\n') .join('\n')
setLog(`<div><h2>SAS Log</h2><pre>${parsedLog}</pre></div>`) setLog(parsedLog)
let weboutString: string setWebout(`${res.data?._webout}`)
try {
weboutString = res.data._webout
.split('>>weboutBEGIN<<')[1]
.split('>>weboutEND<<')[0]
} catch (_) {
weboutString = res?.data?._webout ?? ''
}
let webout: string
try {
webout = JSON.stringify(JSON.parse(weboutString), null, 4)
} catch (_) {
webout = weboutString
}
setWebout(`<pre><code>${webout}</code></pre>`)
setTab('2') setTab('2')
// Scroll to bottom of log // Scroll to bottom of log
@@ -100,6 +84,7 @@ const Studio = () => {
}, [location.search]) }, [location.search])
const classes = useStyles() const classes = useStyles()
return ( return (
<> <>
<br /> <br />
@@ -152,17 +137,15 @@ const Studio = () => {
</Stack> </Stack>
</TabPanel> </TabPanel>
<TabPanel value="2"> <TabPanel value="2">
<div <div style={{ marginTop: '50px' }}>
id="sas_log" <h2>SAS Log</h2>
style={{ marginTop: '50px' }} <pre>{log}</pre>
dangerouslySetInnerHTML={{ __html: log }} </div>
/>
</TabPanel> </TabPanel>
<TabPanel value="3"> <TabPanel value="3">
<div <div style={{ marginTop: '50px' }}>
style={{ marginTop: '50px' }} <pre>{webout}</pre>
dangerouslySetInnerHTML={{ __html: webout }} </div>
/>
</TabPanel> </TabPanel>
</TabContext> </TabContext>
</Box> </Box>