feat(container): add CRUD operations for container management

- Implemented routes for listing, retrieving, updating, and deleting containers.
- Added ContainerModel with necessary fields and methods for data handling.
- Created utility functions for fetching container data by ID.

feat(page): enhance page management with CRUD and publish functionality

- Developed routes for managing pages, including listing, updating, and deleting.
- Integrated caching and zip file generation for page exports.
- Added publish functionality to manage app versions and file uploads.

feat(prompts): implement prompt management with CRUD operations

- Created routes for listing, updating, and deleting prompts.
- Added pagination and search capabilities for prompt listing.

test: add common query utilities and prompt tests

- Implemented common query utilities for API interactions.
- Added tests for prompt listing functionality.
This commit is contained in:
2025-12-30 13:28:50 +08:00
parent 27e5fb5e82
commit 8731801b52
28 changed files with 411 additions and 103 deletions

View File

@@ -0,0 +1,89 @@
import { CustomError } from '@kevisual/router';
import { app } from '../../app.ts';
import { PageModel } from './models/index.ts';
import { AppListModel, AppModel } from '../../routes/app-manager/index.ts';
import { cachePage, getZip } from './module/cache-file.ts';
import { uniqBy } from 'lodash-es';
import semver from 'semver';
app
.route({
path: 'page',
key: 'publish',
middleware: ['auth'],
})
.define(async (ctx) => {
const tokenUser = ctx.state.tokenUser;
const { data, id, publish, ...rest } = ctx.query.data;
let needUpdate = { ...rest };
if (data) {
needUpdate = { ...needUpdate, data };
}
if (publish) {
needUpdate = { ...needUpdate, publish };
}
if (!id) {
throw new CustomError('id is required');
}
const page = await PageModel.findByPk(id);
if (!page) {
throw new CustomError('page not found');
}
await page.update(needUpdate);
const _publish = page.publish || {};
if (!_publish.key) {
throw new CustomError('publish key is required');
}
try {
const { key, description } = _publish;
const version = _publish.version || '0.0.0';
let app = await AppModel.findOne({ where: { key, uid: tokenUser.id } });
if (!app) {
app = await AppModel.create({ title: key, key, uid: tokenUser.id, description, user: tokenUser.username });
}
const _version = semver.inc(version, 'patch');
let appList = await AppListModel.findOne({ where: { key, version: _version, uid: tokenUser.id } });
if (!appList) {
appList = await AppListModel.create({ key, version: _version, uid: tokenUser.id, data: {} });
}
// 上传文件
const res = await cachePage(page, { tokenUser, key, version: _version });
const appFiles = appList?.data?.files || [];
const newFiles = uniqBy([...appFiles, ...res], 'name');
appList.data = {
...appList?.data,
files: newFiles,
};
await appList.save();
await page.update({ publish: { ..._publish, id: app.id, version: _version } });
ctx.body = page;
} catch (e) {
console.log('error', e);
throw new CustomError(e.message || 'publish error');
}
})
.addTo(app);
app
.route({
path: 'page',
key: 'download',
middleware: ['auth'],
})
.define(async (ctx) => {
const tokenUser = ctx.state.tokenUser;
const { id } = ctx.query;
const page = await PageModel.findByPk(id);
if (!page) {
throw new CustomError('page not found');
}
try {
const files = await getZip(page, { tokenUser });
ctx.body = files;
} catch (e) {
console.log('error', e);
throw new CustomError(e.message || 'download error');
}
})
.addTo(app);