diff --git a/src/routes/app-manager/list.ts b/src/routes/app-manager/list.ts index 6016da4..33c4c5b 100644 --- a/src/routes/app-manager/list.ts +++ b/src/routes/app-manager/list.ts @@ -1,8 +1,8 @@ import { App as AppType, AppList, AppData } from './module/app-drizzle.ts'; -import { app, db, schema } from '@/app.ts'; +import { app, db, oss, schema } from '@/app.ts'; import { uniqBy } from 'es-toolkit'; import { getUidByUsername, prefixFix } from './util.ts'; -import { deleteFiles, getMinioListAndSetToAppList } from '../file/index.ts'; +import { deleteFiles, getMinioList, getMinioListAndSetToAppList } from '../file/index.ts'; import { setExpire } from './revoke.ts'; import { User } from '@/models/user.ts'; import { callDetectAppVersion } from './export.ts'; @@ -47,6 +47,16 @@ app key: 'get', middleware: ['auth'], description: '获取应用详情,可以通过id,或者key+version来获取', + metadata: { + args: { + data: z.object({ + id: z.string().optional(), + version: z.string().optional(), + key: z.string().optional(), + create: z.boolean().optional().describe('如果应用版本不存在,是否创建应用版本记录,默认false'), + }) + } + } }) .define(async (ctx) => { console.log('get app manager called'); @@ -376,11 +386,88 @@ app }) .addTo(app); +app.route({ + path: 'app', + key: 'publishDirectory', + middleware: ['auth'], + description: '发布应用目录,将某个版本的应用目录设置为当前应用的版本', + metadata: { + args: { + data: z.object({ + key: z.string().describe('应用的唯一标识'), + version: z.string().describe('应用版本'), + directory: z.string().describe('应用目录'), + }) + } + } +}).define(async (ctx) => { + const tokenUser = ctx.state.tokenUser; + const { key, version, directory } = ctx.query.data; + if (!key || !version || !directory) { + ctx.throw('key, version and directory are required'); + } + const username = tokenUser.username; + const chunks = directory.split('/').filter((item) => item); + const [_username, appWay, ...rest] = chunks; + if (username !== _username) { + ctx.throw('没有权限'); + } + let newChunks = []; + if (appWay === 'resources') { + newChunks = [username, ...rest]; + } else if (appWay === 'ai') { + newChunks = [username, 'ai', '1.0.0', ...rest]; + } + const [_, originAppKey, originVersion] = newChunks.filter((item) => item); + if (!originAppKey || !originVersion) { + ctx.throw('目录不合法'); + } + const pub = async () => { + return await app.run({ + path: 'app', + key: 'publish', + payload: { + data: { + appKey: key, + version, + detect: true, + }, + token: ctx.query.token, + }, + }) + } + // 如果发布的版本和当前版本不一致,则将目录下的文件复制到新的目录下 + if (originAppKey !== key || originVersion !== version) { + const oldPrefix = newChunks.join('/') + '/'; + const newPrefix = `${username}/${key}/${version}/`; + const listSource = await getMinioList({ prefix: oldPrefix, recursive: true }); + for (const item of listSource) { + const newName = item.name.slice(oldPrefix.length); + await oss.copyObject(item.name, `${newPrefix}${newName}`); + } + } + const appRes = await app.run({ path: 'app', key: 'get', payload: { data: { key, version, create: true }, token: ctx.query.token } }); + if (appRes.code !== 200) { + ctx.throw(appRes.message || '获取应用信息失败'); + } + const res = await pub(); + ctx.forward(res); + +}).addTo(app); app .route({ path: 'app', key: 'getApp', description: '获取应用信息,可以通过id,或者key+version来获取, 参数在data中传入', + metadata: { + args: { + data: z.object({ + id: z.string().optional(), + key: z.string().optional(), + version: z.string().optional(), + }) + } + } }) .define(async (ctx) => { const { user, key, id } = ctx.query.data;