feat: 更新安装应用逻辑,添加用户 ID 处理,优化应用路径检查

This commit is contained in:
xiongxiao
2026-03-27 00:22:19 +08:00
committed by cnb
parent 867dcce83d
commit bb1141aea4
4 changed files with 21 additions and 15 deletions

View File

@@ -4,6 +4,7 @@ import { manager } from './manager-app.ts';
import { selfRestart } from '@/modules/self-restart.ts'; import { selfRestart } from '@/modules/self-restart.ts';
import { AppList } from '../app-manager/module/index.ts'; import { AppList } from '../app-manager/module/index.ts';
import { eq, and } from 'drizzle-orm'; import { eq, and } from 'drizzle-orm';
import { UserId } from '../user/modules/user-id.ts';
// curl http://localhost:4002/api/router?path=micro-app&key=deploy // curl http://localhost:4002/api/router?path=micro-app&key=deploy
// 把对应的应用安装到系统的apps目录下并解压然后把配置项写入数据库配置 // 把对应的应用安装到系统的apps目录下并解压然后把配置项写入数据库配置
// key 是应用的唯一标识和package.json中的key一致绑定关系 // key 是应用的唯一标识和package.json中的key一致绑定关系
@@ -48,20 +49,21 @@ app
} }
} }
const { version } = microApp; const { version } = microApp;
const appKey = username + '/' + microApp.key; const userAppKey = username + '/' + microApp.key;
const check = await appPathCheck({ appKey }); const uid = await UserId.getUserIdByName(username);
const check = await appPathCheck({ appKey: userAppKey });
let appType: string; let appType: string;
if (check) { if (check) {
if (!force) { if (!force) {
ctx.throw(400, 'App already exists, please remove it first'); ctx.throw(400, 'App already exists, please remove it first');
} else { } else {
const app = manager.getAppShowInfo(appKey); const app = manager.getAppShowInfo(userAppKey);
appType = app?.type; appType = app?.type;
await manager.removeApp(appKey); await manager.removeApp(userAppKey);
} }
} }
const installAppData = await installApp({ appKey, version, needInstallDeps: !!install }); const installAppData = await installApp({ uid, username, appKey: microApp.key, version, needInstallDeps: !!install });
await manager.add(installAppData.showAppInfo); await manager.add(installAppData.showAppInfo);
ctx.body = installAppData; ctx.body = installAppData;
if (appType === 'system-app') { if (appType === 'system-app') {

View File

@@ -1,18 +1,21 @@
import { oss } from '@/app.ts'; import { oss } from '@/app.ts';
import { fileIsExist } from '@kevisual/use-config'; import { fileIsExist } from '@kevisual/use-config';
import { spawn, spawnSync } from 'child_process'; import { spawn, spawnSync } from 'child_process';
import { getFileStat, getMinioList, MinioFile } from '@/routes/file/index.ts'; import { getMinioList, MinioFile } from '@/routes/file/index.ts';
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import { appsPath } from '../lib/index.ts'; import { appsPath } from '../lib/index.ts';
import { installAppFromKey } from './manager.ts'; import { installAppFromKey } from './manager.ts';
import { Readable } from 'stream'; import { Readable } from 'stream';
import { CustomError } from '@kevisual/router';
export type InstallAppOpts = { export type InstallAppOpts = {
needInstallDeps?: boolean; needInstallDeps?: boolean;
// minio中 // minio中
appKey?: string; appKey?: string;
version?: string; version?: string;
uid?: string;
username?: string;
}; };
/** /**
* 检测路径是否存在 * 检测路径是否存在
@@ -28,12 +31,13 @@ export const appPathCheck = async (opts: InstallAppOpts) => {
return false; return false;
}; };
export const installApp = async (opts: InstallAppOpts) => { export const installApp = async (opts: InstallAppOpts) => {
const { needInstallDeps, appKey, version } = opts; const { needInstallDeps, appKey, version, uid, username } = opts;
const prefix = `${appKey}/${version}`; const userAppKey = `${username}/${appKey}`;
const prefix = `data/${uid}/${appKey}/${version}`;
const pkgPrefix = prefix + '/package.json'; const pkgPrefix = prefix + '/package.json';
const stat = await getFileStat(pkgPrefix); const stat = await oss.statObject(pkgPrefix);
if (!stat) { if (!stat) {
throw new Error('App not found'); throw new CustomError({ code: 400, message: 'App not found' });
} }
const fileList = await getMinioList({ const fileList = await getMinioList({
prefix, prefix,
@@ -41,7 +45,7 @@ export const installApp = async (opts: InstallAppOpts) => {
}); });
for (const file of fileList) { for (const file of fileList) {
const { name } = file as MinioFile; const { name } = file as MinioFile;
const outputPath = path.join(appsPath, appKey, name.replace(prefix, '')); const outputPath = path.join(appsPath, userAppKey, name.replace(prefix, ''));
const dir = path.dirname(outputPath); const dir = path.dirname(outputPath);
if (!fileIsExist(dir)) { if (!fileIsExist(dir)) {
fs.mkdirSync(dir, { recursive: true }); fs.mkdirSync(dir, { recursive: true });
@@ -55,7 +59,7 @@ export const installApp = async (opts: InstallAppOpts) => {
writeStream.on('error', reject); writeStream.on('error', reject);
}); });
} }
const directory = path.join(appsPath, appKey); const directory = path.join(appsPath, userAppKey);
if (!fileIsExist(directory)) { if (!fileIsExist(directory)) {
fs.mkdirSync(directory, { recursive: true }); fs.mkdirSync(directory, { recursive: true });
} }
@@ -66,7 +70,7 @@ export const installApp = async (opts: InstallAppOpts) => {
console.log('installDeps error, [need manual install deps]', e); console.log('installDeps error, [need manual install deps]', e);
} }
} }
return installAppFromKey(appKey); return installAppFromKey(userAppKey);
}; };
export const checkPnpm = () => { export const checkPnpm = () => {

View File

@@ -6,7 +6,7 @@ import { appsPath } from '../lib/index.ts';
export const installAppFromKey = async (key: string) => { export const installAppFromKey = async (key: string) => {
const directory = path.join(appsPath, key); const directory = path.join(appsPath, key);
if (!fileIsExist(directory)) { if (!fileIsExist(directory)) {
throw new Error('App not found'); throw new Error('FileIsNotExist: App not found');
} }
const pkgs = path.join(directory, 'package.json'); const pkgs = path.join(directory, 'package.json');
if (!fileIsExist(pkgs)) { if (!fileIsExist(pkgs)) {

View File

@@ -1,4 +1,4 @@
import { oss } from '@/modules/s3.ts' import { oss } from '@/modules/s3.ts'
const stat = await oss.statObject('root/codepod/0.0.3/index.html'); const stat = await oss.statObject('data/0e700dc8-90dd-41b7-91dd-336ea51de3d2/cnb/0.0.61/package.json');
console.log('Object Stat:', stat); console.log('Object Stat:', stat);