diff --git a/server/.env b/server/.env index bc928e7eaf..20dc93c7b5 100644 --- a/server/.env +++ b/server/.env @@ -21,4 +21,7 @@ CASDOOR_ORG_NAME=laf CASDOOR_APP_NAME=laf CASDOOR_CLIENT_ID=a71f65e93723c436027e CASDOOR_CLIENT_SECRET=0d7e157be08055867b81456df3c222ea7c68a097 -CASDOOR_REDIRECT_URI=http://localhost:3001/login_callback \ No newline at end of file +CASDOOR_REDIRECT_URI=http://localhost:3001/login_callback + + +NODE_RUNTIME_BUILTIN_DEPENDENCIES=@aws-sdk/client-s3@3.72.0,@aws-sdk/client-sts@3.72.0,@aws-sdk/s3-request-presigner@3.72.0,@kubernetes/client-node@0.17.1,alipay-sdk@3.1.7,axios@0.21.1,database-proxy@0.8.2,dayjs@1.10.7,dotenv@8.2.0,ejs@3.1.6,express@4.17.1,express-xml-bodyparser@0.3.0,fs-extra@9.1.0,jsonwebtoken@8.5.1,lodash@4.17.21,log4js@6.7.1,minio@7.0.28,mongodb@4.1.3,mongodb-uri@0.9.7,multer@1.4.5-lts.1,node-modules-utils@0.8.2,nodemailer@6.6.3,validator@13.7.0,ws@8.2.3 \ No newline at end of file diff --git a/server/package-lock.json b/server/package-lock.json index cb05295116..ee4e533ed4 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -35,6 +35,7 @@ "mongodb": "^4.12.1", "ms": "^2.1.3", "nanoid": "^3.3.4", + "npm-package-arg": "^10.1.0", "passport": "^0.6.0", "passport-jwt": "^4.0.0", "passport-local": "^1.0.0", @@ -52,6 +53,7 @@ "@types/express": "^4.17.13", "@types/jest": "28.1.8", "@types/node": "^16.0.0", + "@types/npm-package-arg": "^6.1.1", "@types/passport-jwt": "^3.0.7", "@types/passport-local": "^1.0.34", "@types/supertest": "^2.0.11", @@ -5694,6 +5696,12 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz", "integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==" }, + "node_modules/@types/npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@types/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-452/1Kp9IdM/oR10AyqAgZOxUt7eLbm+EMJ194L6oarMYdZNiFIFAOJ7IIr0OrZXTySgfHjJezh2oiyk2kc3ag==", + "dev": true + }, "node_modules/@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", @@ -7067,6 +7075,14 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, + "node_modules/builtins": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dependencies": { + "semver": "^7.0.0" + } + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -9629,6 +9645,25 @@ "node": ">=8" } }, + "node_modules/hosted-git-info": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", + "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", + "dependencies": { + "lru-cache": "^7.5.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", + "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", + "engines": { + "node": ">=12" + } + }, "node_modules/html-entities": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", @@ -12003,6 +12038,20 @@ "node": ">=0.10.0" } }, + "node_modules/npm-package-arg": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", + "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", + "dependencies": { + "hosted-git-info": "^6.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -12726,6 +12775,14 @@ "node": ">=14.17" } }, + "node_modules/proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -13362,7 +13419,6 @@ "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -14910,6 +14966,17 @@ "node": ">=10.12.0" } }, + "node_modules/validate-npm-package-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", + "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", + "dependencies": { + "builtins": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/validator": { "version": "13.7.0", "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", @@ -19695,6 +19762,12 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz", "integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==" }, + "@types/npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@types/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-452/1Kp9IdM/oR10AyqAgZOxUt7eLbm+EMJ194L6oarMYdZNiFIFAOJ7IIr0OrZXTySgfHjJezh2oiyk2kc3ag==", + "dev": true + }, "@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", @@ -20769,6 +20842,14 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, + "builtins": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "requires": { + "semver": "^7.0.0" + } + }, "busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -22727,6 +22808,21 @@ "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", "dev": true }, + "hosted-git-info": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", + "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", + "requires": { + "lru-cache": "^7.5.1" + }, + "dependencies": { + "lru-cache": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", + "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==" + } + } + }, "html-entities": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", @@ -24541,6 +24637,17 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, + "npm-package-arg": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", + "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", + "requires": { + "hosted-git-info": "^6.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + } + }, "npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -25056,6 +25163,11 @@ "@prisma/engines": "4.7.1" } }, + "proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==" + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -25533,7 +25645,6 @@ "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, "requires": { "lru-cache": "^6.0.0" } @@ -26693,6 +26804,14 @@ "convert-source-map": "^1.6.0" } }, + "validate-npm-package-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", + "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", + "requires": { + "builtins": "^5.0.0" + } + }, "validator": { "version": "13.7.0", "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", diff --git a/server/package.json b/server/package.json index b523f1ca74..a7c05152ea 100644 --- a/server/package.json +++ b/server/package.json @@ -2,7 +2,7 @@ "name": "laf-server", "version": "1.0.0-alpha.0", "description": "", - "author": "", + "author": "maslow(wangfugen@!26.com)", "private": true, "license": "UNLICENSED", "scripts": { @@ -10,6 +10,7 @@ "generate": "prisma generate", "build": "nest build", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", + "push-db": "prisma db push --skip-generate", "start": "nest start", "watch": "nest start --watch", "start:dev": "nest start --watch", @@ -49,6 +50,7 @@ "mongodb": "^4.12.1", "ms": "^2.1.3", "nanoid": "^3.3.4", + "npm-package-arg": "^10.1.0", "passport": "^0.6.0", "passport-jwt": "^4.0.0", "passport-local": "^1.0.0", @@ -66,6 +68,7 @@ "@types/express": "^4.17.13", "@types/jest": "28.1.8", "@types/node": "^16.0.0", + "@types/npm-package-arg": "^6.1.1", "@types/passport-jwt": "^3.0.7", "@types/passport-local": "^1.0.34", "@types/supertest": "^2.0.11", diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma index 54152a9225..a048db573f 100644 --- a/server/prisma/schema.prisma +++ b/server/prisma/schema.prisma @@ -2,7 +2,7 @@ // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { - provider = "prisma-client-js" + provider = "prisma-client-js" // previewFeatures = ["interactiveTransactions"] // binaryTargets = ["native", "linux-arm64-openssl-1.1.x"] binaryTargets = ["native"] @@ -93,18 +93,18 @@ enum ApplicationPhase { } model Application { - id String @id @default(auto()) @map("_id") @db.ObjectId + id String @id @default(auto()) @map("_id") @db.ObjectId name String - appid String @unique + appid String @unique regionName String bundleName String runtimeName String state ApplicationState phase ApplicationPhase tags String[] - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - createdBy String @db.ObjectId + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String @db.ObjectId region Region @relation(fields: [regionName], references: [name]) runtime Runtime @relation(fields: [runtimeName], references: [name]) @@ -121,8 +121,10 @@ model ApplicationConfiguration { id String @id @default(auto()) @map("_id") @db.ObjectId appid String @unique environments EnvironmentVariable[] - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + dependencies String[] @default([]) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt application Application @relation(fields: [appid], references: [appid]) } diff --git a/server/src/app.module.ts b/server/src/app.module.ts index 6dfcabb140..05a53c80b1 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -14,7 +14,8 @@ import { ScheduleModule } from '@nestjs/schedule' import { DatabaseModule } from './database/database.module' import { PrismaService } from './prisma.service' import { StorageModule } from './storage/storage.module' -import { LogModule } from './log/log.module'; +import { LogModule } from './log/log.module' +import { DependencyModule } from './dependency/dependency.module' @Module({ imports: [ @@ -34,6 +35,7 @@ import { LogModule } from './log/log.module'; DatabaseModule, StorageModule, LogModule, + DependencyModule, ], controllers: [AppController], providers: [AppService, PrismaService], diff --git a/server/src/application/application.service.ts b/server/src/application/application.service.ts index 839d34fd48..b12857d870 100644 --- a/server/src/application/application.service.ts +++ b/server/src/application/application.service.ts @@ -54,6 +54,7 @@ export class ApplicationService { configuration: { create: { environments: [appSecret], + dependencies: [], }, }, } diff --git a/server/src/dependency/dependency.controller.ts b/server/src/dependency/dependency.controller.ts new file mode 100644 index 0000000000..a98499e2f7 --- /dev/null +++ b/server/src/dependency/dependency.controller.ts @@ -0,0 +1,74 @@ +import { + Body, + Controller, + Delete, + Get, + Logger, + Param, + Post, + UseGuards, +} from '@nestjs/common' +import { + ApiBearerAuth, + ApiOperation, + ApiResponse, + ApiTags, +} from '@nestjs/swagger' +import { ApplicationAuthGuard } from '../auth/application.auth.guard' +import { JwtAuthGuard } from '../auth/jwt.auth.guard' +import { ResponseUtil } from '../utils/response' +import { DependencyService } from './dependency.service' +import { CreateDependencyDto } from './dto/create-dependency.dto' + +@ApiTags('Application') +@ApiBearerAuth('Authorization') +@Controller('apps/:appid/dependencies') +export class DependencyController { + private readonly logger = new Logger(DependencyController.name) + + constructor(private readonly depsService: DependencyService) {} + + /** + * Add a dependency to an app + * @param appid + * @param dto + * @returns + */ + @ApiResponse({ type: ResponseUtil }) + @ApiOperation({ summary: 'Add a dependency' }) + @UseGuards(JwtAuthGuard, ApplicationAuthGuard) + @Post() + async add(@Param('appid') appid: string, @Body() dto: CreateDependencyDto) { + const res = await this.depsService.add(appid, dto) + return ResponseUtil.ok(res) + } + + /** + * Get application dependencies + * @param appid + * @returns + */ + @ApiResponse({ type: ResponseUtil }) + @ApiOperation({ summary: 'Get application dependencies' }) + @UseGuards(JwtAuthGuard, ApplicationAuthGuard) + @Get() + async getDependencies(@Param('appid') appid: string) { + const res = await this.depsService.getMergedObjects(appid) + return ResponseUtil.ok(res) + } + + /** + * Remove a dependency + * @param appid + * @param name + * @returns + */ + @ApiResponse({ type: ResponseUtil }) + @ApiOperation({ summary: 'Remove a dependency' }) + @UseGuards(JwtAuthGuard, ApplicationAuthGuard) + @Delete(':name') + async remove(@Param('appid') appid: string, @Param('name') name: string) { + const res = await this.depsService.remove(appid, name) + return ResponseUtil.ok(res) + } +} diff --git a/server/src/dependency/dependency.module.ts b/server/src/dependency/dependency.module.ts new file mode 100644 index 0000000000..fe33a2875a --- /dev/null +++ b/server/src/dependency/dependency.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common' +import { ApplicationModule } from 'src/application/application.module' +import { PrismaService } from 'src/prisma.service' +import { DependencyController } from './dependency.controller' +import { DependencyService } from './dependency.service' + +@Module({ + imports: [ApplicationModule], + controllers: [DependencyController], + providers: [DependencyService, PrismaService], +}) +export class DependencyModule {} diff --git a/server/src/dependency/dependency.service.ts b/server/src/dependency/dependency.service.ts new file mode 100644 index 0000000000..4e95c8d4a2 --- /dev/null +++ b/server/src/dependency/dependency.service.ts @@ -0,0 +1,119 @@ +import { Injectable, Logger } from '@nestjs/common' +import { PrismaService } from 'src/prisma.service' +import { RUNTIME_BUILTIN_DEPENDENCIES } from 'src/runtime-builtin-deps' +import * as npa from 'npm-package-arg' +import { CreateDependencyDto } from './dto/create-dependency.dto' + +export class Dependency { + name: string + spec: string + type: string + builtin: boolean +} + +@Injectable() +export class DependencyService { + private readonly logger = new Logger(DependencyService.name) + + constructor(private readonly prisma: PrismaService) {} + + /** + * Get app merged dependencies in `Dependency` array + * @param appid + * @returns + */ + async getMergedObjects(appid: string): Promise { + const extra_arr = await this.getExtras(appid) + const builtin_arr = this.getBuiltins() + + const extras = extra_arr.map((dep) => { + const { name, fetchSpec, type } = npa(dep) + return { name, spec: fetchSpec, type, builtin: false } as Dependency + }) + + const builtins = builtin_arr.map((dep) => { + const { name, fetchSpec, type } = npa(dep) + return { name, spec: fetchSpec, type, builtin: true } as Dependency + }) + + const deps = extras.concat(builtins) + return Object.values(deps) + } + + async add(appid: string, dto: CreateDependencyDto) { + if (!this.validate(dto)) { + return false + } + + const extras = await this.getExtras(appid) + const builtins = this.getBuiltins() + const all = extras.concat(builtins) + + // check if the dependency name is already existed + const existed = all.find((dep) => { + const r = npa(dep) + return r.name === dto.name + }) + if (existed) return false + + const new_dep = `${dto.name}@${dto.spec}` + await this.prisma.applicationConfiguration.update({ + where: { appid }, + data: { + dependencies: { + push: new_dep, + }, + }, + }) + + return true + } + + async remove(appid: string, name: string) { + const deps = await this.getExtras(appid) + const filtered = deps.filter((dep) => { + const r = npa(dep) + return r.name !== name + }) + + if (filtered.length === deps.length) return false + + await this.prisma.applicationConfiguration.update({ + where: { appid }, + data: { dependencies: filtered }, + }) + return true + } + + /** + * Get the extra dependencies in string array + * @param appid + * @returns + */ + private async getExtras(appid: string) { + const conf = await this.prisma.applicationConfiguration.findUnique({ + where: { appid }, + }) + + const deps = conf?.dependencies ?? [] + return deps + } + + /** + * Get the built-in dependencies in string array + * @returns + */ + private getBuiltins() { + const obj = RUNTIME_BUILTIN_DEPENDENCIES + return Object.keys(obj).map((key) => `${key}@${obj[key]}`) + } + + private validate(dto: CreateDependencyDto) { + try { + npa.resolve(dto.name, dto.spec) + return true + } catch (error) { + return false + } + } +} diff --git a/server/src/dependency/dto/create-dependency.dto.ts b/server/src/dependency/dto/create-dependency.dto.ts new file mode 100644 index 0000000000..14ed3179ee --- /dev/null +++ b/server/src/dependency/dto/create-dependency.dto.ts @@ -0,0 +1,14 @@ +import { ApiProperty } from '@nestjs/swagger' +import { IsNotEmpty, Length } from 'class-validator' + +export class CreateDependencyDto { + @ApiProperty() + @IsNotEmpty() + @Length(1, 64) + name: string + + @ApiProperty() + @IsNotEmpty() + @Length(1, 64) + spec: string +} diff --git a/server/src/instance/instance.service.ts b/server/src/instance/instance.service.ts index 00bbe0559c..3330fcdb71 100644 --- a/server/src/instance/instance.service.ts +++ b/server/src/instance/instance.service.ts @@ -50,6 +50,8 @@ export class InstanceService { const requestMemory = app.bundle.requestMemory const requestCpu = app.bundle.requestCPU const max_old_space_size = ~~(limitMemory * 0.8) + const dependencies = app.configuration?.dependencies || [] + const dependencies_string = dependencies.join(' ') const env = [ { name: 'DB_URI', value: database.status?.connectionUri }, @@ -60,6 +62,7 @@ export class InstanceService { { name: 'OSS_EXTERNAL_ENDPOINT', value: ServerConfig.OSS_ENDPOINT }, { name: 'OSS_REGION', value: oss.status?.region }, { name: 'FLAGS', value: `--max_old_space_size=${max_old_space_size}` }, + { name: 'DEPENDENCIES', value: dependencies_string }, ] // merge env from app configuration, override if exists diff --git a/server/src/runtime-builtin-deps.ts b/server/src/runtime-builtin-deps.ts new file mode 100644 index 0000000000..437afd864a --- /dev/null +++ b/server/src/runtime-builtin-deps.ts @@ -0,0 +1,26 @@ +export const RUNTIME_BUILTIN_DEPENDENCIES = { + '@aws-sdk/client-s3': '^3.231.0', + '@aws-sdk/client-sts': '^3.231.0', + '@aws-sdk/s3-request-presigner': '^3.231.0', + '@kubernetes/client-node': '^0.18.0', + 'alipay-sdk': '^3.2.0', + axios: '^1.2.1', + 'database-proxy': '^0.8.2', + dayjs: '^1.11.7', + dotenv: '^8.2.0', + ejs: '^3.1.8', + express: '^4.18.2', + 'express-xml-bodyparser': '^0.3.0', + 'fs-extra': '^9.1.0', + jsonwebtoken: '^8.5.1', + lodash: '^4.17.21', + log4js: '^6.7.1', + minio: '^7.0.32', + mongodb: '^4.12.1', + 'mongodb-uri': '^0.9.7', + multer: '^1.4.5-lts.1', + 'node-modules-utils': '^0.8.2', + nodemailer: '^6.6.3', + validator: '^13.7.0', + ws: '^8.11.0', +}