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

Compare commits

...

9 Commits

Author SHA1 Message Date
Saad Jutt
adc5aca0f0 chore(release): 0.0.42 2022-03-23 22:49:29 +05:00
Muhammad Saad
71c6be6b84 Merge pull request #104 from sasjs/webout-raw
fix: execute api, webout as raw
2022-03-23 22:47:07 +05:00
Saad Jutt
9c751877d1 fix: execute api, webout as raw 2022-03-23 22:41:02 +05:00
Saad Jutt
2204d54cd6 chore(release): 0.0.41 2022-03-23 21:32:06 +05:00
Saad Jutt
f4eb75ff34 fix(scroll): closes #100 2022-03-23 21:31:54 +05:00
Saad Jutt
a3cde343b7 chore(release): 0.0.40 2022-03-23 20:17:15 +05:00
Saad Jutt
7a70d40dbf fix: macros available for SAS 2022-03-23 20:15:18 +05:00
Saad Jutt
d27e070fc8 fix: moved macros from codebase to drive
This reverts commit d2956fc641.
2022-03-23 19:38:29 +05:00
Saad Jutt
27e260e6a4 fix(deploy): validating empty file or service in filetree 2022-03-23 19:38:20 +05:00
14 changed files with 177 additions and 75 deletions

View File

@@ -2,6 +2,29 @@
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.42](https://github.com/sasjs/server/compare/v0.0.41...v0.0.42) (2022-03-23)
### Bug Fixes
* execute api, webout as raw ([9c75187](https://github.com/sasjs/server/commit/9c751877d1ed0d0677aff816169a1df7c34c6bf5))
### [0.0.41](https://github.com/sasjs/server/compare/v0.0.40...v0.0.41) (2022-03-23)
### Bug Fixes
* **scroll:** closes [#100](https://github.com/sasjs/server/issues/100) ([f4eb75f](https://github.com/sasjs/server/commit/f4eb75ff347e78ac334e55ee26fbdd247bb8eaa2))
### [0.0.40](https://github.com/sasjs/server/compare/v0.0.39...v0.0.40) (2022-03-23)
### Bug Fixes
* **deploy:** validating empty file or service in filetree ([27e260e](https://github.com/sasjs/server/commit/27e260e6a453e9978830db63ab669bd48c029897))
* macros available for SAS ([7a70d40](https://github.com/sasjs/server/commit/7a70d40dbf0cd91cb3af156755f10006b860f917))
* moved macros from codebase to drive ([d27e070](https://github.com/sasjs/server/commit/d27e070fc83894854278df22a8223b8016a1f5f7))
### [0.0.39](https://github.com/sasjs/server/compare/v0.0.38...v0.0.39) (2022-03-23) ### [0.0.39](https://github.com/sasjs/server/compare/v0.0.38...v0.0.39) (2022-03-23)

View File

@@ -92,7 +92,7 @@
}, },
"nodemonConfig": { "nodemonConfig": {
"ignore": [ "ignore": [
"tmp/appStreamConfig.json" "tmp/**/*"
] ]
} }
} }

View File

@@ -161,6 +161,8 @@ components:
$ref: '#/components/schemas/FolderMember' $ref: '#/components/schemas/FolderMember'
- -
$ref: '#/components/schemas/ServiceMember' $ref: '#/components/schemas/ServiceMember'
-
$ref: '#/components/schemas/FileMember'
type: array type: array
required: required:
- name - name
@@ -172,20 +174,30 @@ components:
enum: enum:
- service - service
type: string type: string
MemberType.file:
enum:
- file
type: string
ServiceMember: ServiceMember:
properties: properties:
name: name:
type: string type: string
type: type:
anyOf: $ref: '#/components/schemas/MemberType.service'
- code:
$ref: '#/components/schemas/MemberType.service' type: string
- required:
$ref: '#/components/schemas/MemberType.file' - name
- type
- code
type: object
additionalProperties: false
MemberType.file:
enum:
- file
type: string
FileMember:
properties:
name:
type: string
type:
$ref: '#/components/schemas/MemberType.file'
code: code:
type: string type: string
required: required:
@@ -203,6 +215,8 @@ components:
$ref: '#/components/schemas/FolderMember' $ref: '#/components/schemas/FolderMember'
- -
$ref: '#/components/schemas/ServiceMember' $ref: '#/components/schemas/ServiceMember'
-
$ref: '#/components/schemas/FileMember'
type: array type: array
required: required:
- members - members

View File

@@ -1,7 +1,14 @@
import path from 'path' import path from 'path'
import { asyncForEach, copy, createFolder, deleteFolder } from '@sasjs/utils' import {
asyncForEach,
copy,
createFile,
createFolder,
deleteFolder,
listFilesInFolder
} from '@sasjs/utils'
import { apiRoot, sasJSCoreMacros } from '../src/utils' import { apiRoot, sasJSCoreMacros, sasJSCoreMacrosInfo } from '../src/utils'
const macroCorePath = path.join(apiRoot, 'node_modules', '@sasjs', 'core') const macroCorePath = path.join(apiRoot, 'node_modules', '@sasjs', 'core')
@@ -16,6 +23,10 @@ export const copySASjsCore = async () => {
await copy(coreSubFolderPath, sasJSCoreMacros) await copy(coreSubFolderPath, sasJSCoreMacros)
}) })
const fileNames = await listFilesInFolder(sasJSCoreMacros)
await createFile(sasJSCoreMacrosInfo, fileNames.join('\n'))
} }
copySASjsCore() copySASjsCore()

View File

@@ -7,6 +7,7 @@ import cors from 'cors'
import { import {
connectDB, connectDB,
copySASjsCore,
getWebBuildFolderPath, getWebBuildFolderPath,
loadAppStreamConfig, loadAppStreamConfig,
sasJSCoreMacros, sasJSCoreMacros,
@@ -42,6 +43,8 @@ const onError: ErrorRequestHandler = (err, req, res, next) => {
} }
export default setProcessVariables().then(async () => { export default setProcessVariables().then(async () => {
await copySASjsCore()
// loading these modules after setting up variables due to // loading these modules after setting up variables due to
// multer's usage of process var process.driveLoc // multer's usage of process var process.driveLoc
const { setupRoutes } = await import('./routes/setupRoutes') const { setupRoutes } = await import('./routes/setupRoutes')
@@ -53,8 +56,6 @@ export default setProcessVariables().then(async () => {
// index.html needs to be injected with some js script. // index.html needs to be injected with some js script.
app.use(express.static(getWebBuildFolderPath())) app.use(express.static(getWebBuildFolderPath()))
console.log('sasJSCoreMacros', sasJSCoreMacros)
app.use(onError) app.use(onError)
await connectDB() await connectDB()

View File

@@ -13,9 +13,9 @@ import {
extractHeaders, extractHeaders,
generateFileUploadSasCode, generateFileUploadSasCode,
getTmpFilesFolderPath, getTmpFilesFolderPath,
getTmpMacrosPath,
HTTPHeaders, HTTPHeaders,
isDebugOn, isDebugOn
sasJSCoreMacros
} from '../../utils' } from '../../utils'
export interface ExecutionVars { export interface ExecutionVars {
@@ -106,7 +106,7 @@ export class ExecutionController {
` `
program = ` program = `
options insert=(SASAUTOS="${sasJSCoreMacros}"); options insert=(SASAUTOS="${getTmpMacrosPath()}");
/* runtime vars */ /* runtime vars */
${varStatments} ${varStatments}

View File

@@ -1,11 +1,17 @@
import path from 'path' import path from 'path'
import { MemberType, FolderMember, ServiceMember, FileTree } from '../../types' import {
MemberType,
FolderMember,
ServiceMember,
FileTree,
FileMember
} from '../../types'
import { getTmpFilesFolderPath } from '../../utils/file' import { getTmpFilesFolderPath } from '../../utils/file'
import { createFolder, createFile, asyncForEach } from '@sasjs/utils' import { createFolder, createFile, asyncForEach } from '@sasjs/utils'
// REFACTOR: export FileTreeCpntroller // REFACTOR: export FileTreeCpntroller
export const createFileTree = async ( export const createFileTree = async (
members: (FolderMember | ServiceMember)[], members: (FolderMember | ServiceMember | FileMember)[],
parentFolders: string[] = [] parentFolders: string[] = []
) => { ) => {
const destinationPath = path.join( const destinationPath = path.join(
@@ -13,29 +19,32 @@ export const createFileTree = async (
path.join(...parentFolders) path.join(...parentFolders)
) )
await asyncForEach(members, async (member: FolderMember | ServiceMember) => { await asyncForEach(
let name = member.name members,
async (member: FolderMember | ServiceMember | FileMember) => {
let name = member.name
if (member.type === MemberType.service) name += '.sas' if (member.type === MemberType.service) name += '.sas'
if (member.type === MemberType.folder) { if (member.type === MemberType.folder) {
await createFolder(path.join(destinationPath, name)).catch((err) => await createFolder(path.join(destinationPath, name)).catch((err) =>
Promise.reject({ error: err, failedToCreate: name }) Promise.reject({ error: err, failedToCreate: name })
) )
await createFileTree(member.members, [...parentFolders, name]).catch( await createFileTree(member.members, [...parentFolders, name]).catch(
(err) => Promise.reject({ error: err, failedToCreate: name }) (err) => Promise.reject({ error: err, failedToCreate: name })
) )
} else { } else {
const encoding = member.type === MemberType.file ? 'base64' : undefined const encoding = member.type === MemberType.file ? 'base64' : undefined
await createFile( await createFile(
path.join(destinationPath, name), path.join(destinationPath, name),
member.code, member.code,
encoding encoding
).catch((err) => Promise.reject({ error: err, failedToCreate: name })) ).catch((err) => Promise.reject({ error: err, failedToCreate: name }))
}
} }
}) )
return Promise.resolve() return Promise.resolve()
} }

View File

@@ -1,23 +1,28 @@
export interface FileTree { export enum MemberType {
members: (FolderMember | ServiceMember)[] service = 'service',
file = 'file',
folder = 'folder'
} }
export enum MemberType { export interface ServiceMember {
folder = 'folder', name: string
service = 'service', type: MemberType.service
file = 'file' code: string
}
export interface FileMember {
name: string
type: MemberType.file
code: string
} }
export interface FolderMember { export interface FolderMember {
name: string name: string
type: MemberType.folder type: MemberType.folder
members: (FolderMember | ServiceMember)[] members: (FolderMember | ServiceMember | FileMember)[]
} }
export interface FileTree {
export interface ServiceMember { members: (FolderMember | ServiceMember | FileMember)[]
name: string
type: MemberType.service | MemberType.file
code: string
} }
export const isFileTree = (arg: any): arg is FileTree => export const isFileTree = (arg: any): arg is FileTree =>
@@ -25,11 +30,25 @@ export const isFileTree = (arg: any): arg is FileTree =>
arg.members && arg.members &&
Array.isArray(arg.members) && Array.isArray(arg.members) &&
arg.members.filter( arg.members.filter(
(member: FolderMember | ServiceMember) => (member: ServiceMember | FileMember | FolderMember) =>
!isFolderMember(member) && !isServiceMember(member) !isServiceMember(member, '-') &&
!isFileMember(member, '-') &&
!isFolderMember(member, '-')
).length === 0 ).length === 0
const isFolderMember = (arg: any): arg is FolderMember => 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 && arg &&
typeof arg.name === 'string' && typeof arg.name === 'string' &&
arg.type === MemberType.folder && arg.type === MemberType.folder &&
@@ -37,21 +56,7 @@ const isFolderMember = (arg: any): arg is FolderMember =>
Array.isArray(arg.members) && Array.isArray(arg.members) &&
arg.members.filter( arg.members.filter(
(member: FolderMember | ServiceMember) => (member: FolderMember | ServiceMember) =>
!isFolderMember(member) && !isServiceMember(member, pre + '-') &&
!isServiceMember(member) && !isFileMember(member, pre + '-') &&
!isFileMember(member) !isFolderMember(member, pre + '-')
).length === 0 ).length === 0
const isServiceMember = (arg: any): arg is ServiceMember =>
arg &&
typeof arg.name === 'string' &&
arg.type === MemberType.service &&
arg.code &&
typeof arg.code === 'string'
const isFileMember = (arg: any): arg is ServiceMember =>
arg &&
typeof arg.name === 'string' &&
arg.type === MemberType.file &&
arg.code &&
typeof arg.code === 'string'

View File

@@ -0,0 +1,32 @@
import path from 'path'
import {
asyncForEach,
createFile,
createFolder,
deleteFolder,
readFile
} from '@sasjs/utils'
import { getTmpMacrosPath, sasJSCoreMacros, sasJSCoreMacrosInfo } from '.'
export const copySASjsCore = async () => {
console.log('Copying Macros from container to drive(tmp).')
const macrosDrivePath = getTmpMacrosPath()
await deleteFolder(macrosDrivePath)
await createFolder(macrosDrivePath)
const macros = await readFile(sasJSCoreMacrosInfo)
await asyncForEach(macros.split('\n'), async (macroName) => {
const macroFileSourcePath = path.join(sasJSCoreMacros, macroName)
const macroContent = await readFile(macroFileSourcePath)
const macroFileDestPath = path.join(macrosDrivePath, macroName)
await createFile(macroFileDestPath, macroContent)
})
console.log('Macros Drive Path:', macrosDrivePath)
}

View File

@@ -9,6 +9,7 @@ export const sysInitCompiledPath = path.join(
) )
export const sasJSCoreMacros = path.join(apiRoot, 'sasjscore') export const sasJSCoreMacros = path.join(apiRoot, 'sasjscore')
export const sasJSCoreMacrosInfo = path.join(apiRoot, 'sasjscore', '.macrolist')
export const getWebBuildFolderPath = () => export const getWebBuildFolderPath = () =>
path.join(codebaseRoot, 'web', 'build') path.join(codebaseRoot, 'web', 'build')
@@ -18,6 +19,8 @@ export const getTmpFolderPath = () => process.driveLoc
export const getTmpAppStreamConfigPath = () => export const getTmpAppStreamConfigPath = () =>
path.join(getTmpFolderPath(), 'appStreamConfig.json') path.join(getTmpFolderPath(), 'appStreamConfig.json')
export const getTmpMacrosPath = () => path.join(getTmpFolderPath(), 'sasjscore')
export const getTmpUploadsPath = () => path.join(getTmpFolderPath(), 'uploads') export const getTmpUploadsPath = () => path.join(getTmpFolderPath(), 'uploads')
export const getTmpFilesFolderPath = () => export const getTmpFilesFolderPath = () =>

View File

@@ -1,13 +1,14 @@
export * from './appStreamConfig' export * from './appStreamConfig'
export * from './connectDB' export * from './connectDB'
export * from './copySASjsCore'
export * from './extractHeaders' export * from './extractHeaders'
export * from './file' export * from './file'
export * from './generateAccessToken' export * from './generateAccessToken'
export * from './generateAuthCode' export * from './generateAuthCode'
export * from './generateRefreshToken' export * from './generateRefreshToken'
export * from './isDebugOn'
export * from './getCertificates' export * from './getCertificates'
export * from './getDesktopFields' export * from './getDesktopFields'
export * from './isDebugOn'
export * from './parseLogToArray' export * from './parseLogToArray'
export * from './removeTokensInDB' export * from './removeTokensInDB'
export * from './saveTokensInDB' export * from './saveTokensInDB'

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "server", "name": "server",
"version": "0.0.39", "version": "0.0.42",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "server", "name": "server",
"version": "0.0.39", "version": "0.0.42",
"devDependencies": { "devDependencies": {
"prettier": "^2.3.1", "prettier": "^2.3.1",
"standard-version": "^9.3.2" "standard-version": "^9.3.2"

View File

@@ -1,6 +1,6 @@
{ {
"name": "server", "name": "server",
"version": "0.0.39", "version": "0.0.42",
"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": {

View File

@@ -54,11 +54,11 @@ const Studio = () => {
let weboutString: string let weboutString: string
try { try {
weboutString = res.data.webout weboutString = res.data._webout
.split('>>weboutBEGIN<<')[1] .split('>>weboutBEGIN<<')[1]
.split('>>weboutEND<<')[0] .split('>>weboutEND<<')[0]
} catch (_) { } catch (_) {
weboutString = res?.data?.webout ?? '' weboutString = res?.data?._webout ?? ''
} }
let webout: string let webout: string
@@ -70,6 +70,9 @@ const Studio = () => {
setWebout(`<pre><code>${webout}</code></pre>`) setWebout(`<pre><code>${webout}</code></pre>`)
setTab('2') setTab('2')
// Scroll to bottom of log
window.scrollTo(0, document.body.scrollHeight)
}) })
.catch((err) => console.log(err)) .catch((err) => console.log(err))
} }