chore: bump @kevisual/router to version 0.0.80, update QueryApi to handle optional fields in metadata args, and enhance JSON Schema conversion

This commit is contained in:
2026-02-18 12:58:44 +08:00
parent 73a9868c19
commit 05dace0c79
10 changed files with 183 additions and 37 deletions

View File

@@ -1,4 +1,5 @@
import { toJSONSchema, fromJSONSchema } from '@kevisual/router/browser'
type RouteInfo = {
path: string;
key: string;
@@ -44,6 +45,14 @@ export const createQueryByRoutes = (list: RouteInfo[]) => {
if (!obj[route.path]) {
obj[route.path] = {};
}
if (route.metadata?.args) {
const args = route.metadata.args;
if (args?.$schema) {
// 将 args 转换为 JSON Schema
const jsonSchema = fromJSONSchema(args);
route.metadata.args = toJSONSchema(jsonSchema);
}
}
obj[route.path][route.key] = route;
}
const code = `

View File

@@ -64,18 +64,27 @@ type InferType<T> =
T extends { properties: infer P } ? InferFromJSONSchema<T> : // 处理没有 type 但有 properties 的对象
T;
// 检查是否标记为可选
type IsOptional<T> = T extends { optional: true } ? true : false;
// 提取 args 对象,将每个 Zod schema 或 JSON Schema 转换为实际类型
// 根据 optional 字段分离必需字段和可选字段
type ExtractArgsFromMetadata<T> = T extends { metadata?: { args?: infer A } }
? A extends Record<string, any>
? { [K in keyof A]: InferType<A[K]> }
: never
? (
// 必需字段(没有 optional: true
{ [K in keyof A as IsOptional<A[K]> extends true ? never : K]: InferType<A[K]> } &
// 可选字段(有 optional: true
{ [K in keyof A as IsOptional<A[K]> extends true ? K : never]?: InferType<A[K]> }
)
: never
: never;
// 类型映射:将 API 配置转换为方法签名
type ApiMethods<P extends { [path: string]: { [key: string]: Pos } }> = {
[Path in keyof P]: {
[Key in keyof P[Path]]: (
data?: Partial<ExtractArgsFromMetadata<P[Path][Key]>>,
data?: ExtractArgsFromMetadata<P[Path][Key]>,
opts?: DataOpts
) => ReturnType<Query['post']>
}
@@ -97,7 +106,7 @@ export class QueryApi<P extends { [path: string]: { [key: string]: Pos } } = {}>
// 使用泛型来推断类型
post<T extends Pos>(
pos: T,
data?: Partial<ExtractArgsFromMetadata<T>>,
data?: ExtractArgsFromMetadata<T>,
opts?: DataOpts
) {
const _pos = pick(pos, ['path', 'key', 'id']);
@@ -121,7 +130,7 @@ export class QueryApi<P extends { [path: string]: { [key: string]: Pos } } = {}>
}
for (const [key, pos] of Object.entries(methods)) {
that[path][key] = (data?: Partial<ExtractArgsFromMetadata<typeof pos>>, opts: DataOpts = {}) => {
that[path][key] = (data?: ExtractArgsFromMetadata<typeof pos>, opts: DataOpts = {}) => {
const _pos = pick(pos, ['path', 'key', 'id']);
if (pos.metadata?.viewItem?.api?.url && !opts.url) {
opts.url = pos.metadata.viewItem.api.url;