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

feat(deploy): new route added for deploy with build.json

This commit is contained in:
Saad Jutt
2022-04-02 05:23:25 +05:00
parent 7b7bc6b778
commit 18d0604bdd
10 changed files with 138 additions and 85 deletions

14
api/package-lock.json generated
View File

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

View File

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

View File

@@ -606,6 +606,56 @@ paths:
application/json:
schema:
$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:
get:
operationId: GetFile

View File

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

View File

@@ -14,7 +14,8 @@ import {
Patch,
UploadedFile,
FormField,
Delete
Delete,
Hidden
} from 'tsoa'
import {
fileExists,
@@ -22,14 +23,15 @@ import {
createFolder,
deleteFile as deleteFileOnSystem,
folderExists,
listFilesAndSubFoldersInFolder,
listFilesInFolder,
listSubFoldersInFolder,
isFolder
isFolder,
FileTree,
isFileTree
} from '@sasjs/utils'
import { createFileTree, ExecutionController, getTreeExample } from './internal'
import { FileTree, isFileTree, TreeNode } from '../types'
import { TreeNode } from '../types'
import { getTmpFilesFolderPath } from '../utils'
interface DeployPayload {
@@ -93,6 +95,21 @@ export class DriveController {
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

View File

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

View File

@@ -1,5 +1,5 @@
import express from 'express'
import { deleteFile } from '@sasjs/utils'
import { deleteFile, readFile } from '@sasjs/utils'
import { publishAppStream } from '../appStream'
@@ -43,6 +43,50 @@ 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) {
return res.status(400).send('File containing invalid JSON content.')
}
const { error, value: body } = deployValidation(jsonContent)
if (error) 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 {
await deleteFile(req.file.path)
}
}
)
driveRouter.get('/file', async (req, res) => {
const { error: errQ, value: query } = fileParamValidation(req.query)

View File

@@ -12,7 +12,9 @@ import {
generateTimestamp,
copy,
createFolder,
createFile
createFile,
ServiceMember,
FolderMember
} from '@sasjs/utils'
import * as fileUtilModules from '../../../utils/file'
@@ -28,7 +30,6 @@ jest
import appPromise from '../../../app'
import { UserController } from '../../../controllers/'
import { getTreeExample } from '../../../controllers/internal'
import { FolderMember, ServiceMember } from '../../../types'
import { generateAccessToken, saveTokensInDB } from '../../../utils/'
const { getTmpFilesFolderPath } = fileUtilModules

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
export * from './AppStreamConfig'
export * from './Execution'
export * from './FileTree'
export * from './InfoJWT'
export * from './PreProgramVars'
export * from './Request'