diff --git a/package.json b/package.json index a925a85..321386d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kevisual/query", - "version": "0.0.49", + "version": "0.0.50", "type": "module", "scripts": { "build": "npm run clean && bun run bun.config.ts", @@ -19,8 +19,8 @@ "description": "", "devDependencies": { "@kevisual/code-builder": "^0.0.6", - "@kevisual/router": "^0.0.80", - "@types/node": "^25.2.3", + "@kevisual/router": "^0.0.84", + "@types/node": "^25.3.0", "typescript": "^5.9.3", "es-toolkit": "^1.44.0", "zod": "^4.3.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..0b6f2e4 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,97 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@kevisual/code-builder': + specifier: ^0.0.6 + version: 0.0.6 + '@kevisual/router': + specifier: ^0.0.84 + version: 0.0.84 + '@types/node': + specifier: ^25.3.0 + version: 25.3.0 + es-toolkit: + specifier: ^1.44.0 + version: 1.44.0 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + zod: + specifier: ^4.3.6 + version: 4.3.6 + zustand: + specifier: ^5.0.11 + version: 5.0.11 + +packages: + + '@kevisual/code-builder@0.0.6': + resolution: {integrity: sha512-0aqATB31/yw4k4s5/xKnfr4DKbUnx8e3Z3BmKbiXTrc+CqWiWTdlGe9bKI9dZ2Df+xNp6g11W4xM2NICNyyCCw==} + hasBin: true + + '@kevisual/router@0.0.84': + resolution: {integrity: sha512-l/TUFuqTJegB/S3FZQRBMUoz0Spvg8EzV3C/kBi/VO9KKCzjqZDVvhZJJbTQh9879CBY6vUy1ajo9WcLYnwbNA==} + + '@types/node@25.3.0': + resolution: {integrity: sha512-4K3bqJpXpqfg2XKGK9bpDTc6xO/xoUP/RBWS7AtRMug6zZFaRekiLzjVtAoZMquxoAbzBvy5nxQ7veS5eYzf8A==} + + es-toolkit@1.44.0: + resolution: {integrity: sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + + zod@4.3.6: + resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} + + zustand@5.0.11: + resolution: {integrity: sha512-fdZY+dk7zn/vbWNCYmzZULHRrss0jx5pPFiOuMZ/5HJN6Yv3u+1Wswy/4MpZEkEGhtNH+pwxZB8OKgUBPzYAGg==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@types/react': '>=18.0.0' + immer: '>=9.0.6' + react: '>=18.0.0' + use-sync-external-store: '>=1.2.0' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + use-sync-external-store: + optional: true + +snapshots: + + '@kevisual/code-builder@0.0.6': {} + + '@kevisual/router@0.0.84': + dependencies: + es-toolkit: 1.44.0 + + '@types/node@25.3.0': + dependencies: + undici-types: 7.18.2 + + es-toolkit@1.44.0: {} + + typescript@5.9.3: {} + + undici-types@7.18.2: {} + + zod@4.3.6: {} + + zustand@5.0.11: {} diff --git a/src/create-query/index.ts b/src/create-query/index.ts index 12e30c4..0c6eb40 100644 --- a/src/create-query/index.ts +++ b/src/create-query/index.ts @@ -22,8 +22,14 @@ type RouteInfo = { } }; } -const removeViewItemFromRoutes = (list: RouteInfo[]) => { +const removeViewItemCotnextFromRoutes = (list: RouteInfo[], options?: CreateQueryOptions) => { for (const route of list) { + if (options?.removeViewItem) { + if (route.metadata?.viewItem) { + delete route.metadata.viewItem; + } + continue; + } if (route.metadata?.viewItem) { if (route.metadata.viewItem?.api?.query) { delete route.metadata.viewItem.api.query; @@ -38,9 +44,14 @@ const removeViewItemFromRoutes = (list: RouteInfo[]) => { } return list; } -export const createQueryByRoutes = (list: RouteInfo[]) => { +type CreateQueryOptions = { + removeViewItem?: boolean, + before?: string, + after?: string, +} +export const createQueryByRoutes = (list: RouteInfo[], options?: CreateQueryOptions) => { const obj: any = {}; - list = removeViewItemFromRoutes(list); + list = removeViewItemCotnextFromRoutes(list, options); for (const route of list) { if (!obj[route.path]) { obj[route.path] = {}; @@ -55,11 +66,12 @@ export const createQueryByRoutes = (list: RouteInfo[]) => { } obj[route.path][route.key] = route; } - const code = ` -import { createQueryApi } from '@kevisual/query/api'; + const before = options?.before || `import { createQueryApi } from '@kevisual/query/api';`; + const after = options?.after || `export { queryApi };`; + const code = `${before} const api = ${generateApiCode(obj)} as const; const queryApi = createQueryApi({ api }); -export { queryApi }; +${after} ` return code; } diff --git a/src/query-api.ts b/src/query-api.ts index b9d1c21..1258b7e 100644 --- a/src/query-api.ts +++ b/src/query-api.ts @@ -1,4 +1,4 @@ -import { DataOpts, Query } from "./query.ts"; +import { DataOpts, Query, Result } from "./query.ts"; import { z } from "zod"; import { createQueryByRoutes } from "./create-query/index.ts"; import { pick } from 'es-toolkit' @@ -71,22 +71,23 @@ type IsOptional = T extends { optional: true } ? true : false; // 根据 optional 字段分离必需字段和可选字段 type ExtractArgsFromMetadata = T extends { metadata?: { args?: infer A } } ? A extends Record - ? ( - // 必需字段(没有 optional: true) - { [K in keyof A as IsOptional extends true ? never : K]: InferType } & - // 可选字段(有 optional: true) - { [K in keyof A as IsOptional extends true ? K : never]?: InferType } - ) - : never + ? ( + // 必需字段(没有 optional: true) + { [K in keyof A as IsOptional extends true ? never : K]: InferType } & + // 可选字段(有 optional: true) + { [K in keyof A as IsOptional extends true ? K : never]?: InferType } + ) + : never : never; + // 类型映射:将 API 配置转换为方法签名 type ApiMethods

= { [Path in keyof P]: { - [Key in keyof P[Path]]: ( + [Key in keyof P[Path]]: ( data?: ExtractArgsFromMetadata, opts?: DataOpts - ) => ReturnType + ) => Promise> } } type QueryApiOpts

= { diff --git a/test/examples.ts b/test/examples.ts index a1a12ac..cf5bfca 100644 --- a/test/examples.ts +++ b/test/examples.ts @@ -45,9 +45,11 @@ const api = { const queryApi = createQueryApi({ api }); export { queryApi }; -queryApi.app_domain_manager.get({ +const result = await queryApi.app_domain_manager.get<{ id: number }>({ data: { id: '123', domain: 'example.com' } -}) \ No newline at end of file +}); + +result.data.id; // TypeScript 正确推断为 number \ No newline at end of file