## 后端改动 - 添加 Project.envPresets 字段(JSON 格式) - 移除 Deployment.env 字段,统一使用 envVars - 更新部署 DTO,支持 envVars (Record<string, string>) - pipeline-runner 支持解析并注入 envVars 到环境 - 移除稀疏检出模板和相关环境变量 - 优化代码格式(Biome lint & format) ## 前端改动 - 新增 EnvPresetsEditor 组件(支持单选/多选/输入框类型) - 项目创建/编辑界面集成环境预设编辑器 - 部署界面基于预设动态生成环境变量表单 - 移除稀疏检出表单项 - 项目详情页添加环境变量预设配置 tab - 优化部署界面布局(基本参数 & 环境变量分区) ## 文档 - 添加完整文档目录结构(docs/) - 创建设计文档 design-0005(部署流程重构) - 添加 API 文档、架构设计文档等 ## 数据库 - 执行 prisma db push 同步 schema 变更
148 lines
3.2 KiB
TypeScript
148 lines
3.2 KiB
TypeScript
/**
|
||
* 路由元数据键
|
||
*/
|
||
export const ROUTE_METADATA_KEY = Symbol('route');
|
||
|
||
/**
|
||
* HTTP 方法类型
|
||
*/
|
||
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
||
|
||
/**
|
||
* 路由元数据接口
|
||
*/
|
||
export interface RouteMetadata {
|
||
method: HttpMethod;
|
||
path: string;
|
||
propertyKey: string;
|
||
}
|
||
|
||
/**
|
||
* 元数据存储(降级方案)
|
||
*/
|
||
const metadataStore = new WeakMap<any, Map<string | symbol, any>>();
|
||
|
||
/**
|
||
* 设置元数据(降级方案)
|
||
*/
|
||
function setMetadata<T = any>(
|
||
key: string | symbol,
|
||
value: T,
|
||
target: any,
|
||
): void {
|
||
if (!metadataStore.has(target)) {
|
||
metadataStore.set(target, new Map());
|
||
}
|
||
metadataStore.get(target)?.set(key, value);
|
||
}
|
||
|
||
/**
|
||
* 获取元数据(降级方案)
|
||
*/
|
||
function getMetadata<T = any>(
|
||
key: string | symbol,
|
||
target: any,
|
||
): T | undefined {
|
||
return metadataStore.get(target)?.get(key);
|
||
}
|
||
|
||
/**
|
||
* 创建HTTP方法装饰器的工厂函数(TC39标准)
|
||
*/
|
||
function createMethodDecorator(method: HttpMethod) {
|
||
return (path: string = '') =>
|
||
<This, Args extends any[], Return>(
|
||
target: (this: This, ...args: Args) => Return,
|
||
context: ClassMethodDecoratorContext<
|
||
This,
|
||
(this: This, ...args: Args) => Return
|
||
>,
|
||
) => {
|
||
// 在类初始化时执行
|
||
context.addInitializer(function () {
|
||
// 使用 this.constructor 时需要类型断言
|
||
const ctor = (this as any).constructor;
|
||
|
||
// 获取现有的路由元数据
|
||
const existingRoutes: RouteMetadata[] =
|
||
getMetadata(ROUTE_METADATA_KEY, ctor) || [];
|
||
|
||
// 添加新的路由元数据
|
||
const newRoute: RouteMetadata = {
|
||
method,
|
||
path,
|
||
propertyKey: String(context.name),
|
||
};
|
||
|
||
existingRoutes.push(newRoute);
|
||
|
||
// 保存路由元数据到类的构造函数上
|
||
setMetadata(ROUTE_METADATA_KEY, existingRoutes, ctor);
|
||
});
|
||
|
||
return target;
|
||
};
|
||
}
|
||
|
||
/**
|
||
* GET 请求装饰器(TC39标准)
|
||
* @param path 路由路径
|
||
*/
|
||
export const Get = createMethodDecorator('GET');
|
||
|
||
/**
|
||
* POST 请求装饰器(TC39标准)
|
||
* @param path 路由路径
|
||
*/
|
||
export const Post = createMethodDecorator('POST');
|
||
|
||
/**
|
||
* PUT 请求装饰器(TC39标准)
|
||
* @param path 路由路径
|
||
*/
|
||
export const Put = createMethodDecorator('PUT');
|
||
|
||
/**
|
||
* DELETE 请求装饰器(TC39标准)
|
||
* @param path 路由路径
|
||
*/
|
||
export const Delete = createMethodDecorator('DELETE');
|
||
|
||
/**
|
||
* PATCH 请求装饰器(TC39标准)
|
||
* @param path 路由路径
|
||
*/
|
||
export const Patch = createMethodDecorator('PATCH');
|
||
|
||
/**
|
||
* 控制器装饰器(TC39标准)
|
||
* @param prefix 路由前缀
|
||
*/
|
||
export function Controller(prefix: string = '') {
|
||
return <T extends abstract new (...args: any) => any>(
|
||
target: T,
|
||
context: ClassDecoratorContext<T>,
|
||
) => {
|
||
// 在类初始化时保存控制器前缀
|
||
context.addInitializer(function () {
|
||
setMetadata('prefix', prefix, this);
|
||
});
|
||
|
||
return target;
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 获取控制器的路由元数据
|
||
*/
|
||
export function getRouteMetadata(ctor: any): RouteMetadata[] {
|
||
return getMetadata(ROUTE_METADATA_KEY, ctor) || [];
|
||
}
|
||
|
||
/**
|
||
* 获取控制器的路由前缀
|
||
*/
|
||
export function getControllerPrefix(ctor: any): string {
|
||
return getMetadata('prefix', ctor) || '';
|
||
}
|