refactor: migrate from Rollup to Bun for build configuration
feat: update adapter to use globalThis for origin resolution fix: remove unused ClientQuery export from query.ts chore: update tsconfig to include test files and set rootDir feat: add create-query functionality for dynamic API generation feat: implement QueryApi with enhanced type inference from JSON Schema test: add comprehensive API tests for QueryApi functionality test: create demo routes and schemas for testing purposes docs: add type inference demo for QueryApi usage
This commit is contained in:
8
bun.config.ts
Normal file
8
bun.config.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { buildWithBun } from '@kevisual/code-builder';
|
||||||
|
|
||||||
|
await buildWithBun({ naming: 'query-browser', entry: 'src/query-browser.ts', dts: true, target: 'browser' });
|
||||||
|
await buildWithBun({ naming: 'query', entry: 'src/query.ts', dts: true, target: 'browser' });
|
||||||
|
await buildWithBun({ naming: 'query-ws', entry: 'src/ws.ts', dts: true, target: 'browser' });
|
||||||
|
await buildWithBun({ naming: 'query-adapter', entry: 'src/adapter.ts', dts: true, target: 'browser' });
|
||||||
|
await buildWithBun({ naming: 'query-api', entry: 'src/query-api.ts', dts: true, target: 'browser' });
|
||||||
|
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
import { App } from '@kevisual/router';
|
import { App } from '@kevisual/router';
|
||||||
|
|
||||||
const app = new App({
|
const app = new App({});
|
||||||
io: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
app
|
app
|
||||||
.route({
|
.route({
|
||||||
@@ -17,8 +15,3 @@ app
|
|||||||
app.listen(4000, () => {
|
app.listen(4000, () => {
|
||||||
console.log('Server is running at http://localhost:4000');
|
console.log('Server is running at http://localhost:4000');
|
||||||
});
|
});
|
||||||
|
|
||||||
app.io.addListener('subscribe', async ({ data, end, ws }) => {
|
|
||||||
console.log('A user connected', data);
|
|
||||||
ws.send('Hello World');
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// console.log('Hello World');
|
// console.log('Hello World');
|
||||||
import { adapter, Query } from '@abearxiong/query';
|
import { adapter, Query } from '@kevisual/query';
|
||||||
import { QueryWs } from '@abearxiong/query/ws';
|
import { QueryWs } from '@kevisual/query/ws';
|
||||||
|
|
||||||
window.onload = async () => {
|
window.onload = async () => {
|
||||||
// const res = await adapter({
|
// const res = await adapter({
|
||||||
|
|||||||
67
demo/type-inference-demo.ts
Normal file
67
demo/type-inference-demo.ts
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import { QueryApi } from "../src/query-api";
|
||||||
|
|
||||||
|
const api = new QueryApi();
|
||||||
|
|
||||||
|
// 示例 1: args 的 value 是 string 类型
|
||||||
|
api.post(
|
||||||
|
{
|
||||||
|
path: "/users",
|
||||||
|
metadata: {
|
||||||
|
args: {
|
||||||
|
name: "John",
|
||||||
|
email: "john@example.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos: "someValue", // ✅ TypeScript 会推断 pos 应该是 string 类型
|
||||||
|
other: "data"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// 示例 2: args 的 value 是 number 类型
|
||||||
|
api.post(
|
||||||
|
{
|
||||||
|
path: "/products",
|
||||||
|
metadata: {
|
||||||
|
args: {
|
||||||
|
id: 123,
|
||||||
|
price: 99.99
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos: 456, // ✅ TypeScript 会推断 pos 应该是 number 类型
|
||||||
|
other: "data"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// 示例 3: args 的 value 是混合类型
|
||||||
|
api.post(
|
||||||
|
{
|
||||||
|
path: "/orders",
|
||||||
|
metadata: {
|
||||||
|
args: {
|
||||||
|
orderId: 123,
|
||||||
|
status: "pending",
|
||||||
|
total: 99.99
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos: "status", // ✅ TypeScript 会推断 pos 可以是 string 或 number
|
||||||
|
// pos: 999, // 这也是合法的
|
||||||
|
other: "data"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// 示例 4: 没有 metadata 或 args
|
||||||
|
api.post(
|
||||||
|
{
|
||||||
|
path: "/test"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos: undefined, // ✅ pos 类型为 never,只能是 undefined
|
||||||
|
other: "data"
|
||||||
|
}
|
||||||
|
);
|
||||||
36
package.json
36
package.json
@@ -1,12 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "@kevisual/query",
|
"name": "@kevisual/query",
|
||||||
"version": "0.0.40",
|
"version": "0.0.41",
|
||||||
"main": "dist/query-browser.js",
|
|
||||||
"private": false,
|
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "npm run clean && rollup -c",
|
"build": "npm run clean && bun run bun.config.ts",
|
||||||
"dev:lib": "rollup -c -w",
|
|
||||||
"clean": "rm -rf dist"
|
"clean": "rm -rf dist"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
@@ -21,11 +18,12 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"description": "",
|
"description": "",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-node-resolve": "^16.0.3",
|
"@kevisual/code-builder": "^0.0.6",
|
||||||
"@rollup/plugin-typescript": "^12.3.0",
|
"@kevisual/router": "^0.0.72",
|
||||||
"rollup": "^4.57.1",
|
"@types/node": "^25.2.3",
|
||||||
"rollup-plugin-dts": "^6.3.0",
|
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3",
|
||||||
|
"es-toolkit": "^1.44.0",
|
||||||
|
"zod": "^4.3.6",
|
||||||
"zustand": "^5.0.11"
|
"zustand": "^5.0.11"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
@@ -36,20 +34,10 @@
|
|||||||
"url": "git+ssh://git@github.com/abearxiong/kevisual-query.git"
|
"url": "git+ssh://git@github.com/abearxiong/kevisual-query.git"
|
||||||
},
|
},
|
||||||
"exports": {
|
"exports": {
|
||||||
".": {
|
".": "./dist/query-browser.js",
|
||||||
"import": "./dist/query-browser.js",
|
"./query": "./dist/query.js",
|
||||||
"require": "./dist/query-browser.js"
|
"./ws": "./dist/query-ws.js",
|
||||||
|
"./api": "./dist/query-api.js"
|
||||||
},
|
},
|
||||||
"./query": {
|
"dependencies": {}
|
||||||
"import": "./dist/query.js",
|
|
||||||
"require": "./dist/query.js"
|
|
||||||
},
|
|
||||||
"./ws": {
|
|
||||||
"import": "./dist/query-ws.js",
|
|
||||||
"require": "./dist/query-ws.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": "^2.8.1"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
497
pnpm-lock.yaml
generated
497
pnpm-lock.yaml
generated
@@ -8,288 +8,55 @@ importers:
|
|||||||
|
|
||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib:
|
es-toolkit:
|
||||||
specifier: ^2.8.1
|
specifier: ^1.44.0
|
||||||
version: 2.8.1
|
version: 1.44.0
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@rollup/plugin-node-resolve':
|
'@kevisual/code-builder':
|
||||||
specifier: ^16.0.3
|
specifier: ^0.0.6
|
||||||
version: 16.0.3(rollup@4.57.1)
|
version: 0.0.6
|
||||||
'@rollup/plugin-typescript':
|
'@kevisual/router':
|
||||||
specifier: ^12.3.0
|
specifier: ^0.0.72
|
||||||
version: 12.3.0(rollup@4.57.1)(tslib@2.8.1)(typescript@5.9.3)
|
version: 0.0.72
|
||||||
rollup:
|
'@types/node':
|
||||||
specifier: ^4.57.1
|
specifier: ^25.2.3
|
||||||
version: 4.57.1
|
version: 25.2.3
|
||||||
rollup-plugin-dts:
|
|
||||||
specifier: ^6.3.0
|
|
||||||
version: 6.3.0(rollup@4.57.1)(typescript@5.9.3)
|
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ^5.9.3
|
specifier: ^5.9.3
|
||||||
version: 5.9.3
|
version: 5.9.3
|
||||||
|
zod:
|
||||||
|
specifier: ^4.3.6
|
||||||
|
version: 4.3.6
|
||||||
zustand:
|
zustand:
|
||||||
specifier: ^5.0.11
|
specifier: ^5.0.11
|
||||||
version: 5.0.11
|
version: 5.0.11
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
'@babel/code-frame@7.28.6':
|
'@kevisual/code-builder@0.0.6':
|
||||||
resolution: {integrity: sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==}
|
resolution: {integrity: sha512-0aqATB31/yw4k4s5/xKnfr4DKbUnx8e3Z3BmKbiXTrc+CqWiWTdlGe9bKI9dZ2Df+xNp6g11W4xM2NICNyyCCw==}
|
||||||
engines: {node: '>=6.9.0'}
|
|
||||||
|
|
||||||
'@babel/helper-validator-identifier@7.28.5':
|
|
||||||
resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
|
|
||||||
engines: {node: '>=6.9.0'}
|
|
||||||
|
|
||||||
'@jridgewell/sourcemap-codec@1.5.5':
|
|
||||||
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
|
|
||||||
|
|
||||||
'@rollup/plugin-node-resolve@16.0.3':
|
|
||||||
resolution: {integrity: sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg==}
|
|
||||||
engines: {node: '>=14.0.0'}
|
|
||||||
peerDependencies:
|
|
||||||
rollup: ^2.78.0||^3.0.0||^4.0.0
|
|
||||||
peerDependenciesMeta:
|
|
||||||
rollup:
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/plugin-typescript@12.3.0':
|
|
||||||
resolution: {integrity: sha512-7DP0/p7y3t67+NabT9f8oTBFE6gGkto4SA6Np2oudYmZE/m1dt8RB0SjL1msMxFpLo631qjRCcBlAbq1ml/Big==}
|
|
||||||
engines: {node: '>=14.0.0'}
|
|
||||||
peerDependencies:
|
|
||||||
rollup: ^2.14.0||^3.0.0||^4.0.0
|
|
||||||
tslib: '*'
|
|
||||||
typescript: '>=3.7.0'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
rollup:
|
|
||||||
optional: true
|
|
||||||
tslib:
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/pluginutils@5.3.0':
|
|
||||||
resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==}
|
|
||||||
engines: {node: '>=14.0.0'}
|
|
||||||
peerDependencies:
|
|
||||||
rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
|
|
||||||
peerDependenciesMeta:
|
|
||||||
rollup:
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-android-arm-eabi@4.57.1':
|
|
||||||
resolution: {integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==}
|
|
||||||
cpu: [arm]
|
|
||||||
os: [android]
|
|
||||||
|
|
||||||
'@rollup/rollup-android-arm64@4.57.1':
|
|
||||||
resolution: {integrity: sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==}
|
|
||||||
cpu: [arm64]
|
|
||||||
os: [android]
|
|
||||||
|
|
||||||
'@rollup/rollup-darwin-arm64@4.57.1':
|
|
||||||
resolution: {integrity: sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==}
|
|
||||||
cpu: [arm64]
|
|
||||||
os: [darwin]
|
|
||||||
|
|
||||||
'@rollup/rollup-darwin-x64@4.57.1':
|
|
||||||
resolution: {integrity: sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==}
|
|
||||||
cpu: [x64]
|
|
||||||
os: [darwin]
|
|
||||||
|
|
||||||
'@rollup/rollup-freebsd-arm64@4.57.1':
|
|
||||||
resolution: {integrity: sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==}
|
|
||||||
cpu: [arm64]
|
|
||||||
os: [freebsd]
|
|
||||||
|
|
||||||
'@rollup/rollup-freebsd-x64@4.57.1':
|
|
||||||
resolution: {integrity: sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==}
|
|
||||||
cpu: [x64]
|
|
||||||
os: [freebsd]
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm-gnueabihf@4.57.1':
|
|
||||||
resolution: {integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==}
|
|
||||||
cpu: [arm]
|
|
||||||
os: [linux]
|
|
||||||
libc: [glibc]
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm-musleabihf@4.57.1':
|
|
||||||
resolution: {integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==}
|
|
||||||
cpu: [arm]
|
|
||||||
os: [linux]
|
|
||||||
libc: [musl]
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm64-gnu@4.57.1':
|
|
||||||
resolution: {integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==}
|
|
||||||
cpu: [arm64]
|
|
||||||
os: [linux]
|
|
||||||
libc: [glibc]
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm64-musl@4.57.1':
|
|
||||||
resolution: {integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==}
|
|
||||||
cpu: [arm64]
|
|
||||||
os: [linux]
|
|
||||||
libc: [musl]
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-loong64-gnu@4.57.1':
|
|
||||||
resolution: {integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==}
|
|
||||||
cpu: [loong64]
|
|
||||||
os: [linux]
|
|
||||||
libc: [glibc]
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-loong64-musl@4.57.1':
|
|
||||||
resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==}
|
|
||||||
cpu: [loong64]
|
|
||||||
os: [linux]
|
|
||||||
libc: [musl]
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-ppc64-gnu@4.57.1':
|
|
||||||
resolution: {integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==}
|
|
||||||
cpu: [ppc64]
|
|
||||||
os: [linux]
|
|
||||||
libc: [glibc]
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-ppc64-musl@4.57.1':
|
|
||||||
resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==}
|
|
||||||
cpu: [ppc64]
|
|
||||||
os: [linux]
|
|
||||||
libc: [musl]
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-riscv64-gnu@4.57.1':
|
|
||||||
resolution: {integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==}
|
|
||||||
cpu: [riscv64]
|
|
||||||
os: [linux]
|
|
||||||
libc: [glibc]
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-riscv64-musl@4.57.1':
|
|
||||||
resolution: {integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==}
|
|
||||||
cpu: [riscv64]
|
|
||||||
os: [linux]
|
|
||||||
libc: [musl]
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-s390x-gnu@4.57.1':
|
|
||||||
resolution: {integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==}
|
|
||||||
cpu: [s390x]
|
|
||||||
os: [linux]
|
|
||||||
libc: [glibc]
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-x64-gnu@4.57.1':
|
|
||||||
resolution: {integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==}
|
|
||||||
cpu: [x64]
|
|
||||||
os: [linux]
|
|
||||||
libc: [glibc]
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-x64-musl@4.57.1':
|
|
||||||
resolution: {integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==}
|
|
||||||
cpu: [x64]
|
|
||||||
os: [linux]
|
|
||||||
libc: [musl]
|
|
||||||
|
|
||||||
'@rollup/rollup-openbsd-x64@4.57.1':
|
|
||||||
resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==}
|
|
||||||
cpu: [x64]
|
|
||||||
os: [openbsd]
|
|
||||||
|
|
||||||
'@rollup/rollup-openharmony-arm64@4.57.1':
|
|
||||||
resolution: {integrity: sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==}
|
|
||||||
cpu: [arm64]
|
|
||||||
os: [openharmony]
|
|
||||||
|
|
||||||
'@rollup/rollup-win32-arm64-msvc@4.57.1':
|
|
||||||
resolution: {integrity: sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==}
|
|
||||||
cpu: [arm64]
|
|
||||||
os: [win32]
|
|
||||||
|
|
||||||
'@rollup/rollup-win32-ia32-msvc@4.57.1':
|
|
||||||
resolution: {integrity: sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==}
|
|
||||||
cpu: [ia32]
|
|
||||||
os: [win32]
|
|
||||||
|
|
||||||
'@rollup/rollup-win32-x64-gnu@4.57.1':
|
|
||||||
resolution: {integrity: sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==}
|
|
||||||
cpu: [x64]
|
|
||||||
os: [win32]
|
|
||||||
|
|
||||||
'@rollup/rollup-win32-x64-msvc@4.57.1':
|
|
||||||
resolution: {integrity: sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==}
|
|
||||||
cpu: [x64]
|
|
||||||
os: [win32]
|
|
||||||
|
|
||||||
'@types/estree@1.0.8':
|
|
||||||
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
|
|
||||||
|
|
||||||
'@types/resolve@1.20.2':
|
|
||||||
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
|
|
||||||
|
|
||||||
deepmerge@4.3.1:
|
|
||||||
resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
|
|
||||||
estree-walker@2.0.2:
|
|
||||||
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
|
||||||
|
|
||||||
fsevents@2.3.3:
|
|
||||||
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
|
|
||||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
|
||||||
os: [darwin]
|
|
||||||
|
|
||||||
function-bind@1.1.2:
|
|
||||||
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
|
|
||||||
|
|
||||||
hasown@2.0.2:
|
|
||||||
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
|
||||||
engines: {node: '>= 0.4'}
|
|
||||||
|
|
||||||
is-core-module@2.16.1:
|
|
||||||
resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
|
|
||||||
engines: {node: '>= 0.4'}
|
|
||||||
|
|
||||||
is-module@1.0.0:
|
|
||||||
resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==}
|
|
||||||
|
|
||||||
js-tokens@4.0.0:
|
|
||||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
|
||||||
|
|
||||||
magic-string@0.30.21:
|
|
||||||
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
|
|
||||||
|
|
||||||
path-parse@1.0.7:
|
|
||||||
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
|
|
||||||
|
|
||||||
picocolors@1.1.1:
|
|
||||||
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
|
||||||
|
|
||||||
picomatch@4.0.3:
|
|
||||||
resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
|
|
||||||
engines: {node: '>=12'}
|
|
||||||
|
|
||||||
resolve@1.22.11:
|
|
||||||
resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==}
|
|
||||||
engines: {node: '>= 0.4'}
|
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
rollup-plugin-dts@6.3.0:
|
'@kevisual/router@0.0.72':
|
||||||
resolution: {integrity: sha512-d0UrqxYd8KyZ6i3M2Nx7WOMy708qsV/7fTHMHxCMCBOAe3V/U7OMPu5GkX8hC+cmkHhzGnfeYongl1IgiooddA==}
|
resolution: {integrity: sha512-+HL4FINZsjnoRRa8Qs7xoPg+5/TcHR7jZQ7AHWHogo0BJzCAtnQwmidMQzeGL4z0WKNbbgVhXdz1wAYoxHJZTg==}
|
||||||
engines: {node: '>=16'}
|
|
||||||
peerDependencies:
|
|
||||||
rollup: ^3.29.4 || ^4
|
|
||||||
typescript: ^4.5 || ^5.0
|
|
||||||
|
|
||||||
rollup@4.57.1:
|
'@types/node@25.2.3':
|
||||||
resolution: {integrity: sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==}
|
resolution: {integrity: sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ==}
|
||||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
supports-preserve-symlinks-flag@1.0.0:
|
es-toolkit@1.44.0:
|
||||||
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
resolution: {integrity: sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==}
|
||||||
engines: {node: '>= 0.4'}
|
|
||||||
|
|
||||||
tslib@2.8.1:
|
|
||||||
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
|
||||||
|
|
||||||
typescript@5.9.3:
|
typescript@5.9.3:
|
||||||
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
|
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
|
||||||
engines: {node: '>=14.17'}
|
engines: {node: '>=14.17'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
undici-types@7.16.0:
|
||||||
|
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
|
||||||
|
|
||||||
|
zod@4.3.6:
|
||||||
|
resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==}
|
||||||
|
|
||||||
zustand@5.0.11:
|
zustand@5.0.11:
|
||||||
resolution: {integrity: sha512-fdZY+dk7zn/vbWNCYmzZULHRrss0jx5pPFiOuMZ/5HJN6Yv3u+1Wswy/4MpZEkEGhtNH+pwxZB8OKgUBPzYAGg==}
|
resolution: {integrity: sha512-fdZY+dk7zn/vbWNCYmzZULHRrss0jx5pPFiOuMZ/5HJN6Yv3u+1Wswy/4MpZEkEGhtNH+pwxZB8OKgUBPzYAGg==}
|
||||||
engines: {node: '>=12.20.0'}
|
engines: {node: '>=12.20.0'}
|
||||||
@@ -310,206 +77,22 @@ packages:
|
|||||||
|
|
||||||
snapshots:
|
snapshots:
|
||||||
|
|
||||||
'@babel/code-frame@7.28.6':
|
'@kevisual/code-builder@0.0.6': {}
|
||||||
|
|
||||||
|
'@kevisual/router@0.0.72':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/helper-validator-identifier': 7.28.5
|
es-toolkit: 1.44.0
|
||||||
js-tokens: 4.0.0
|
|
||||||
picocolors: 1.1.1
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@babel/helper-validator-identifier@7.28.5':
|
'@types/node@25.2.3':
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@jridgewell/sourcemap-codec@1.5.5': {}
|
|
||||||
|
|
||||||
'@rollup/plugin-node-resolve@16.0.3(rollup@4.57.1)':
|
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rollup/pluginutils': 5.3.0(rollup@4.57.1)
|
undici-types: 7.16.0
|
||||||
'@types/resolve': 1.20.2
|
|
||||||
deepmerge: 4.3.1
|
|
||||||
is-module: 1.0.0
|
|
||||||
resolve: 1.22.11
|
|
||||||
optionalDependencies:
|
|
||||||
rollup: 4.57.1
|
|
||||||
|
|
||||||
'@rollup/plugin-typescript@12.3.0(rollup@4.57.1)(tslib@2.8.1)(typescript@5.9.3)':
|
es-toolkit@1.44.0: {}
|
||||||
dependencies:
|
|
||||||
'@rollup/pluginutils': 5.3.0(rollup@4.57.1)
|
|
||||||
resolve: 1.22.11
|
|
||||||
typescript: 5.9.3
|
|
||||||
optionalDependencies:
|
|
||||||
rollup: 4.57.1
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@rollup/pluginutils@5.3.0(rollup@4.57.1)':
|
|
||||||
dependencies:
|
|
||||||
'@types/estree': 1.0.8
|
|
||||||
estree-walker: 2.0.2
|
|
||||||
picomatch: 4.0.3
|
|
||||||
optionalDependencies:
|
|
||||||
rollup: 4.57.1
|
|
||||||
|
|
||||||
'@rollup/rollup-android-arm-eabi@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-android-arm64@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-darwin-arm64@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-darwin-x64@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-freebsd-arm64@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-freebsd-x64@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm-gnueabihf@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm-musleabihf@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm64-gnu@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-arm64-musl@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-loong64-gnu@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-loong64-musl@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-ppc64-gnu@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-ppc64-musl@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-riscv64-gnu@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-riscv64-musl@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-s390x-gnu@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-x64-gnu@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-linux-x64-musl@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-openbsd-x64@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-openharmony-arm64@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-win32-arm64-msvc@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-win32-ia32-msvc@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-win32-x64-gnu@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@rollup/rollup-win32-x64-msvc@4.57.1':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@types/estree@1.0.8': {}
|
|
||||||
|
|
||||||
'@types/resolve@1.20.2': {}
|
|
||||||
|
|
||||||
deepmerge@4.3.1: {}
|
|
||||||
|
|
||||||
estree-walker@2.0.2: {}
|
|
||||||
|
|
||||||
fsevents@2.3.3:
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
function-bind@1.1.2: {}
|
|
||||||
|
|
||||||
hasown@2.0.2:
|
|
||||||
dependencies:
|
|
||||||
function-bind: 1.1.2
|
|
||||||
|
|
||||||
is-core-module@2.16.1:
|
|
||||||
dependencies:
|
|
||||||
hasown: 2.0.2
|
|
||||||
|
|
||||||
is-module@1.0.0: {}
|
|
||||||
|
|
||||||
js-tokens@4.0.0:
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
magic-string@0.30.21:
|
|
||||||
dependencies:
|
|
||||||
'@jridgewell/sourcemap-codec': 1.5.5
|
|
||||||
|
|
||||||
path-parse@1.0.7: {}
|
|
||||||
|
|
||||||
picocolors@1.1.1:
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
picomatch@4.0.3: {}
|
|
||||||
|
|
||||||
resolve@1.22.11:
|
|
||||||
dependencies:
|
|
||||||
is-core-module: 2.16.1
|
|
||||||
path-parse: 1.0.7
|
|
||||||
supports-preserve-symlinks-flag: 1.0.0
|
|
||||||
|
|
||||||
rollup-plugin-dts@6.3.0(rollup@4.57.1)(typescript@5.9.3):
|
|
||||||
dependencies:
|
|
||||||
magic-string: 0.30.21
|
|
||||||
rollup: 4.57.1
|
|
||||||
typescript: 5.9.3
|
|
||||||
optionalDependencies:
|
|
||||||
'@babel/code-frame': 7.28.6
|
|
||||||
|
|
||||||
rollup@4.57.1:
|
|
||||||
dependencies:
|
|
||||||
'@types/estree': 1.0.8
|
|
||||||
optionalDependencies:
|
|
||||||
'@rollup/rollup-android-arm-eabi': 4.57.1
|
|
||||||
'@rollup/rollup-android-arm64': 4.57.1
|
|
||||||
'@rollup/rollup-darwin-arm64': 4.57.1
|
|
||||||
'@rollup/rollup-darwin-x64': 4.57.1
|
|
||||||
'@rollup/rollup-freebsd-arm64': 4.57.1
|
|
||||||
'@rollup/rollup-freebsd-x64': 4.57.1
|
|
||||||
'@rollup/rollup-linux-arm-gnueabihf': 4.57.1
|
|
||||||
'@rollup/rollup-linux-arm-musleabihf': 4.57.1
|
|
||||||
'@rollup/rollup-linux-arm64-gnu': 4.57.1
|
|
||||||
'@rollup/rollup-linux-arm64-musl': 4.57.1
|
|
||||||
'@rollup/rollup-linux-loong64-gnu': 4.57.1
|
|
||||||
'@rollup/rollup-linux-loong64-musl': 4.57.1
|
|
||||||
'@rollup/rollup-linux-ppc64-gnu': 4.57.1
|
|
||||||
'@rollup/rollup-linux-ppc64-musl': 4.57.1
|
|
||||||
'@rollup/rollup-linux-riscv64-gnu': 4.57.1
|
|
||||||
'@rollup/rollup-linux-riscv64-musl': 4.57.1
|
|
||||||
'@rollup/rollup-linux-s390x-gnu': 4.57.1
|
|
||||||
'@rollup/rollup-linux-x64-gnu': 4.57.1
|
|
||||||
'@rollup/rollup-linux-x64-musl': 4.57.1
|
|
||||||
'@rollup/rollup-openbsd-x64': 4.57.1
|
|
||||||
'@rollup/rollup-openharmony-arm64': 4.57.1
|
|
||||||
'@rollup/rollup-win32-arm64-msvc': 4.57.1
|
|
||||||
'@rollup/rollup-win32-ia32-msvc': 4.57.1
|
|
||||||
'@rollup/rollup-win32-x64-gnu': 4.57.1
|
|
||||||
'@rollup/rollup-win32-x64-msvc': 4.57.1
|
|
||||||
fsevents: 2.3.3
|
|
||||||
|
|
||||||
supports-preserve-symlinks-flag@1.0.0: {}
|
|
||||||
|
|
||||||
tslib@2.8.1: {}
|
|
||||||
|
|
||||||
typescript@5.9.3: {}
|
typescript@5.9.3: {}
|
||||||
|
|
||||||
|
undici-types@7.16.0: {}
|
||||||
|
|
||||||
|
zod@4.3.6: {}
|
||||||
|
|
||||||
zustand@5.0.11: {}
|
zustand@5.0.11: {}
|
||||||
|
|||||||
@@ -1,81 +0,0 @@
|
|||||||
// rollup.config.js
|
|
||||||
|
|
||||||
import typescript from '@rollup/plugin-typescript';
|
|
||||||
import resolve from '@rollup/plugin-node-resolve';
|
|
||||||
import { dts } from 'rollup-plugin-dts';
|
|
||||||
/**
|
|
||||||
* @type {import('rollup').RollupOptions}
|
|
||||||
*/
|
|
||||||
export default [
|
|
||||||
{
|
|
||||||
input: 'src/index.ts', // TypeScript 入口文件
|
|
||||||
output: {
|
|
||||||
file: 'dist/query-browser.js', // 输出文件
|
|
||||||
format: 'es', // 输出格式设置为 ES 模块
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
resolve(), // 使用 @rollup/plugin-node-resolve 解析 node_modules 中的模块
|
|
||||||
typescript(), // 使用 @rollup/plugin-typescript 处理 TypeScript 文件
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: 'src/index.ts', // TypeScript 入口文件
|
|
||||||
output: {
|
|
||||||
file: 'dist/query-browser.d.ts', // 输出文件
|
|
||||||
format: 'es', // 输出格式设置为 ES 模块
|
|
||||||
},
|
|
||||||
plugins: [dts()],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: 'src/query.ts',
|
|
||||||
output: {
|
|
||||||
file: 'dist/query.js',
|
|
||||||
format: 'es',
|
|
||||||
},
|
|
||||||
plugins: [resolve(), typescript()],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: 'src/query.ts',
|
|
||||||
output: {
|
|
||||||
file: 'dist/query.d.ts',
|
|
||||||
format: 'es',
|
|
||||||
},
|
|
||||||
|
|
||||||
plugins: [dts()],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: 'src/ws.ts', // TypeScript 入口文件
|
|
||||||
output: {
|
|
||||||
file: 'dist/query-ws.js', // 输出文件
|
|
||||||
format: 'es', // 输出格式设置为 ES 模块
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
resolve(), // 使用 @rollup/plugin-node-resolve 解析 node_modules 中的模块
|
|
||||||
typescript(), // 使用 @rollup/plugin-typescript 处理 TypeScript 文件
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: 'src/ws.ts', // TypeScript 入口文件
|
|
||||||
output: {
|
|
||||||
file: 'dist/query-ws.d.ts', // 输出文件
|
|
||||||
format: 'es', // 输出格式设置为 ES 模块
|
|
||||||
},
|
|
||||||
plugins: [dts()],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: 'src/adapter.ts',
|
|
||||||
output: {
|
|
||||||
file: 'dist/query-adapter.js',
|
|
||||||
format: 'es',
|
|
||||||
},
|
|
||||||
plugins: [resolve(), typescript()],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: 'src/adapter.ts', // TypeScript 入口文件
|
|
||||||
output: {
|
|
||||||
file: 'dist/query-adapter.d.ts', // 输出文件
|
|
||||||
format: 'es', // 输出格式设置为 ES 模块
|
|
||||||
},
|
|
||||||
plugins: [dts()],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
@@ -60,7 +60,7 @@ export const adapter = async (opts: AdapterOpts = {}, overloadOpts?: RequestInit
|
|||||||
if (opts?.url?.startsWith('http')) {
|
if (opts?.url?.startsWith('http')) {
|
||||||
url = new URL(opts.url);
|
url = new URL(opts.url);
|
||||||
} else {
|
} else {
|
||||||
origin = window?.location?.origin || 'http://localhost:51515';
|
origin = globalThis?.location?.origin || 'http://localhost:51515';
|
||||||
url = new URL(opts?.url || '', origin);
|
url = new URL(opts?.url || '', origin);
|
||||||
}
|
}
|
||||||
const isGet = method === 'GET';
|
const isGet = method === 'GET';
|
||||||
|
|||||||
130
src/create-query/index.ts
Normal file
130
src/create-query/index.ts
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
|
||||||
|
type RouteInfo = {
|
||||||
|
path: string;
|
||||||
|
key: string;
|
||||||
|
id: string;
|
||||||
|
description?: string;
|
||||||
|
metadata?: {
|
||||||
|
summary?: string;
|
||||||
|
args?: Record<string, any>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export const createQueryByRoutes = (list: RouteInfo[]) => {
|
||||||
|
const obj: any = {};
|
||||||
|
for (const route of list) {
|
||||||
|
if (!obj[route.path]) {
|
||||||
|
obj[route.path] = {};
|
||||||
|
}
|
||||||
|
obj[route.path][route.key] = route;
|
||||||
|
}
|
||||||
|
const code = `
|
||||||
|
import { createQueryApi } from '@kevisual/query/api';
|
||||||
|
const api = ${generateApiCode(obj)} as const;
|
||||||
|
const queryApi = createQueryApi({ api });
|
||||||
|
export { queryApi };
|
||||||
|
`
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成带注释的对象字符串
|
||||||
|
function generateApiCode(obj: any): string {
|
||||||
|
let code = '{\n';
|
||||||
|
const paths = Object.keys(obj);
|
||||||
|
|
||||||
|
for (let i = 0; i < paths.length; i++) {
|
||||||
|
const path = paths[i];
|
||||||
|
const methods = obj[path];
|
||||||
|
|
||||||
|
code += ` "${path}": {\n`;
|
||||||
|
|
||||||
|
const keys = Object.keys(methods);
|
||||||
|
for (let j = 0; j < keys.length; j++) {
|
||||||
|
const key = keys[j];
|
||||||
|
const route = methods[key];
|
||||||
|
if (route?.id) {
|
||||||
|
if (route.id.startsWith('rand-')) {
|
||||||
|
delete route.id; // 删除随机生成的 ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const description = route?.metadata?.summary || route?.description || '';
|
||||||
|
const args = route?.metadata?.args || {};
|
||||||
|
|
||||||
|
// 添加 JSDoc 注释
|
||||||
|
if (description || Object.keys(args).length > 0) {
|
||||||
|
code += ` /**\n`;
|
||||||
|
|
||||||
|
// 添加主描述
|
||||||
|
if (description) {
|
||||||
|
// 转义描述中的特殊字符
|
||||||
|
const escapedDescription = description
|
||||||
|
.replace(/\\/g, '\\\\') // 转义反斜杠
|
||||||
|
.replace(/\*/g, '\\*') // 转义星号
|
||||||
|
.replace(/\n/g, '\n * '); // 处理多行描述
|
||||||
|
code += ` * ${escapedDescription}\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加参数描述
|
||||||
|
if (Object.keys(args).length > 0) {
|
||||||
|
if (description) {
|
||||||
|
code += ` *\n`; // 添加空行分隔
|
||||||
|
}
|
||||||
|
code += ` * @param data - Request parameters\n`;
|
||||||
|
|
||||||
|
for (const [argName, schema] of Object.entries(args)) {
|
||||||
|
const argSchema = schema as any;
|
||||||
|
const argType = argSchema.type || 'unknown';
|
||||||
|
const argDesc = argSchema.description || '';
|
||||||
|
|
||||||
|
// 构建类型信息
|
||||||
|
let typeInfo = argType;
|
||||||
|
if (argType === 'string' && argSchema.enum) {
|
||||||
|
typeInfo = argSchema.enum.map((v: any) => `"${v}"`).join(' | ');
|
||||||
|
} else if (argType === 'number' || argType === 'integer') {
|
||||||
|
const constraints = [];
|
||||||
|
if (argSchema.minimum !== undefined) constraints.push(`min: ${argSchema.minimum}`);
|
||||||
|
if (argSchema.maximum !== undefined) constraints.push(`max: ${argSchema.maximum}`);
|
||||||
|
if (argSchema.exclusiveMinimum !== undefined) constraints.push(`> ${argSchema.exclusiveMinimum}`);
|
||||||
|
if (argSchema.exclusiveMaximum !== undefined) constraints.push(`< ${argSchema.exclusiveMaximum}`);
|
||||||
|
if (constraints.length > 0) typeInfo += ` (${constraints.join(', ')})`;
|
||||||
|
} else if (argType === 'string') {
|
||||||
|
const constraints = [];
|
||||||
|
if (argSchema.minLength !== undefined) constraints.push(`minLength: ${argSchema.minLength}`);
|
||||||
|
if (argSchema.maxLength !== undefined) constraints.push(`maxLength: ${argSchema.maxLength}`);
|
||||||
|
if (argSchema.format) constraints.push(`format: ${argSchema.format}`);
|
||||||
|
if (constraints.length > 0) typeInfo += ` (${constraints.join(', ')})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转义参数描述
|
||||||
|
const escapedArgDesc = argDesc
|
||||||
|
.replace(/\\/g, '\\\\')
|
||||||
|
.replace(/\*/g, '\\*')
|
||||||
|
.replace(/\n/g, ' ');
|
||||||
|
|
||||||
|
code += ` * @param data.${argName} - {${typeInfo}}${escapedArgDesc ? ' ' + escapedArgDesc : ''}\n`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
code += ` */\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
code += ` "${key}": ${JSON.stringify(route, null, 2).split('\n').map((line, idx) =>
|
||||||
|
idx === 0 ? line : ' ' + line
|
||||||
|
).join('\n')}`;
|
||||||
|
|
||||||
|
if (j < keys.length - 1) {
|
||||||
|
code += ',';
|
||||||
|
}
|
||||||
|
code += '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
code += ` }`;
|
||||||
|
if (i < paths.length - 1) {
|
||||||
|
code += ',';
|
||||||
|
}
|
||||||
|
code += '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
code += '}';
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
136
src/query-api.ts
Normal file
136
src/query-api.ts
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
import { DataOpts, Query } from "./query.ts";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { createQueryByRoutes } from "./create-query/index.ts";
|
||||||
|
import { pick } from 'es-toolkit'
|
||||||
|
type Pos = {
|
||||||
|
path?: string;
|
||||||
|
key?: string;
|
||||||
|
id?: string;
|
||||||
|
metadata?: {
|
||||||
|
args?: Record<string, any>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON Schema 类型推断 - 使用更精确的类型匹配
|
||||||
|
type InferFromJSONSchema<T> =
|
||||||
|
T extends { type: "string"; enum: readonly (infer E)[] } ? E :
|
||||||
|
T extends { type: "string"; enum: (infer E)[] } ? E :
|
||||||
|
T extends { type: "string" } ? string :
|
||||||
|
T extends { type: "number" } ? number :
|
||||||
|
T extends { type: "integer" } ? number :
|
||||||
|
T extends { type: "boolean" } ? boolean :
|
||||||
|
T extends { type: "object"; properties: infer P }
|
||||||
|
? { [K in keyof P]: InferFromJSONSchema<P[K]> }
|
||||||
|
: T extends { type: "array"; items: infer I }
|
||||||
|
? Array<InferFromJSONSchema<I>>
|
||||||
|
: unknown;
|
||||||
|
|
||||||
|
// 统一类型推断:支持 Zod schema 和原始 JSON Schema
|
||||||
|
type InferType<T> =
|
||||||
|
T extends z.ZodType<infer U> ? U : // Zod schema
|
||||||
|
T extends { type: infer TType } ? InferFromJSONSchema<T> : // 任何包含 type 字段的 JSON Schema(忽略 $schema)
|
||||||
|
T;
|
||||||
|
|
||||||
|
// 提取 args 对象,将每个 Zod schema 或 JSON Schema 转换为实际类型
|
||||||
|
type ExtractArgsFromMetadata<T> = T extends { metadata?: { args?: infer A } }
|
||||||
|
? A extends Record<string, any>
|
||||||
|
? { [K in keyof A]: 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]>>,
|
||||||
|
opts?: DataOpts
|
||||||
|
) => ReturnType<Query['post']>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type QueryApiOpts<P extends { [path: string]: { [key: string]: Pos } } = {}> = {
|
||||||
|
query?: Query,
|
||||||
|
api?: P
|
||||||
|
}
|
||||||
|
export class QueryApi<P extends { [path: string]: { [key: string]: Pos } } = {}> {
|
||||||
|
query: Query;
|
||||||
|
|
||||||
|
constructor(opts?: QueryApiOpts<P>) {
|
||||||
|
this.query = opts?.query ?? new Query();
|
||||||
|
if (opts?.api) {
|
||||||
|
this.createApi(opts.api);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用泛型来推断类型
|
||||||
|
post<T extends Pos>(
|
||||||
|
pos: T,
|
||||||
|
data?: Partial<ExtractArgsFromMetadata<T>>,
|
||||||
|
opts?: DataOpts
|
||||||
|
) {
|
||||||
|
const _pos = pick(pos, ['path', 'key', 'id']);
|
||||||
|
return this.query.post({
|
||||||
|
..._pos,
|
||||||
|
payload: data
|
||||||
|
}, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
createApi(api: P): asserts this is this & ApiMethods<P> {
|
||||||
|
const that = this as any;
|
||||||
|
const apiEntries = Object.entries(api);
|
||||||
|
const keepPaths = ['createApi', 'query', 'post'];
|
||||||
|
|
||||||
|
for (const [path, methods] of apiEntries) {
|
||||||
|
if (keepPaths.includes(path)) continue;
|
||||||
|
|
||||||
|
// 为每个 path 创建命名空间对象
|
||||||
|
if (!that[path]) {
|
||||||
|
that[path] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [key, pos] of Object.entries(methods)) {
|
||||||
|
that[path][key] = (data?: Partial<ExtractArgsFromMetadata<typeof pos>>, opts?: DataOpts) => {
|
||||||
|
const _pos = pick(pos, ['path', 'key', 'id']);
|
||||||
|
return that.query.post({
|
||||||
|
..._pos,
|
||||||
|
payload: data
|
||||||
|
}, opts);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建工厂函数,提供更好的类型推断
|
||||||
|
export function createQueryApi<P extends { [path: string]: { [key: string]: Pos } }>(
|
||||||
|
opts?: QueryApiOpts<P>
|
||||||
|
): QueryApi<P> & ApiMethods<P> {
|
||||||
|
return new QueryApi(opts) as QueryApi<P> & ApiMethods<P>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { createQueryByRoutes };
|
||||||
|
// const demo = {
|
||||||
|
// "test_path": {
|
||||||
|
// "test_key": {
|
||||||
|
// "path": "demo",
|
||||||
|
// "key": "test",
|
||||||
|
// metadata: {
|
||||||
|
// args: {
|
||||||
|
// name: z.string(),
|
||||||
|
// age: z.number(),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } as const;
|
||||||
|
|
||||||
|
// // 方式1: 使用工厂函数创建(推荐)
|
||||||
|
// const queryApi = createQueryApi({ query: new Query(), api: demo });
|
||||||
|
|
||||||
|
// // 现在调用时会有完整的类型推断
|
||||||
|
// // data 参数会被推断为 { name?: string, age?: number }
|
||||||
|
// queryApi.test_path.test_key({ name: "test", age: 18 });
|
||||||
|
// // 也可以不传参数
|
||||||
|
// queryApi.test_path.test_key();
|
||||||
|
|
||||||
|
// // 或者只传递 opts
|
||||||
|
// queryApi.test_path.test_key(undefined, { timeout: 5000 });
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { adapter } from './adapter.ts';
|
import { adapter } from './adapter.ts';
|
||||||
import { QueryWs, QueryWsOpts } from './ws.ts';
|
import { QueryWs, QueryWsOpts } from './ws.ts';
|
||||||
import { Query, ClientQuery } from './query.ts';
|
import { Query } from './query.ts';
|
||||||
import { BaseQuery, QueryOptions, wrapperError } from './query.ts';
|
import { BaseQuery, QueryOptions, wrapperError } from './query.ts';
|
||||||
|
|
||||||
export { QueryOpts, QueryWs, ClientQuery, Query, QueryWsOpts, adapter, BaseQuery, wrapperError };
|
export { QueryOpts, QueryWs, Query, QueryWsOpts, adapter, BaseQuery, wrapperError };
|
||||||
export { QueryOptions }
|
export { QueryOptions }
|
||||||
export type { DataOpts, Result, Data } from './query.ts';
|
export type { DataOpts, Result, Data } from './query.ts';
|
||||||
|
|
||||||
|
|||||||
11
src/query.ts
11
src/query.ts
@@ -162,6 +162,7 @@ export class Query {
|
|||||||
*/
|
*/
|
||||||
async post<R = any, P = any>(body: Data & P, options?: DataOpts): Promise<Result<R>> {
|
async post<R = any, P = any>(body: Data & P, options?: DataOpts): Promise<Result<R>> {
|
||||||
const url = options?.url || this.url;
|
const url = options?.url || this.url;
|
||||||
|
console.log('query post', url, body, options);
|
||||||
const { headers, adapter, beforeRequest, afterResponse, timeout, ...rest } = options || {};
|
const { headers, adapter, beforeRequest, afterResponse, timeout, ...rest } = options || {};
|
||||||
const _headers = { ...this.headers, ...headers };
|
const _headers = { ...this.headers, ...headers };
|
||||||
const _adapter = adapter || this.adapter;
|
const _adapter = adapter || this.adapter;
|
||||||
@@ -301,13 +302,3 @@ export class BaseQuery<T extends Query = Query, R extends { queryChain?: any; qu
|
|||||||
return this.query.get(data, options);
|
return this.query.get(data, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
* 前端调用后端QueryRouter, 默认路径 /client/router
|
|
||||||
*/
|
|
||||||
export class ClientQuery extends Query {
|
|
||||||
constructor(opts?: QueryOpts) {
|
|
||||||
super({ ...opts, url: opts?.url || '/client/router' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
30
test/api.ts
Normal file
30
test/api.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { QueryApi } from '../src/query-api.ts';
|
||||||
|
|
||||||
|
export const queryApi = new QueryApi();
|
||||||
|
|
||||||
|
export const api = {
|
||||||
|
"test": {
|
||||||
|
"test": {
|
||||||
|
"path": "test",
|
||||||
|
"key": "test",
|
||||||
|
"id": "rWfTW4jLlwPWN_LdYXPBO",
|
||||||
|
"description": "test route",
|
||||||
|
"type": "route",
|
||||||
|
"middleware": [],
|
||||||
|
"metadata": {
|
||||||
|
"args": {
|
||||||
|
"a": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "string",
|
||||||
|
"description": "arg a"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Additional routes can be added here
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
const res = await queryApi.post(api.test.test, {
|
||||||
|
a: 'test'
|
||||||
|
});
|
||||||
26
test/common.ts
Normal file
26
test/common.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { app } from './router.ts';
|
||||||
|
import util from 'node:util';
|
||||||
|
import fs from 'node:fs'
|
||||||
|
import { createQueryByRoutes } from '../src/create-query/index.ts';
|
||||||
|
export const showMore = (data: any) => {
|
||||||
|
return util.inspect(data, { depth: null, colors: true });
|
||||||
|
}
|
||||||
|
const routes = await app.run({ path: 'router', key: 'list' })
|
||||||
|
// console.log('rourtes', showMore(routes.data.list));
|
||||||
|
const list = routes.data.list
|
||||||
|
|
||||||
|
const obj: any = {}
|
||||||
|
|
||||||
|
for (const route of list) {
|
||||||
|
if (!obj[route.path]) {
|
||||||
|
obj[route.path] = {};
|
||||||
|
}
|
||||||
|
obj[route.path][route.key] = route;
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log('obj', showMore(obj));
|
||||||
|
|
||||||
|
const code = createQueryByRoutes(list);
|
||||||
|
|
||||||
|
fs.writeFileSync('test/query.ts', code, 'utf-8');
|
||||||
|
|
||||||
472
test/query.ts
Normal file
472
test/query.ts
Normal file
@@ -0,0 +1,472 @@
|
|||||||
|
|
||||||
|
import { createQueryApi } from '@kevisual/query/api';
|
||||||
|
const api = {
|
||||||
|
"test": {
|
||||||
|
/**
|
||||||
|
* test route
|
||||||
|
*
|
||||||
|
* @param data - Request parameters
|
||||||
|
* @param data.a - {string} arg a
|
||||||
|
*/
|
||||||
|
"test": {
|
||||||
|
"path": "test",
|
||||||
|
"key": "test",
|
||||||
|
"description": "test route",
|
||||||
|
"type": "route",
|
||||||
|
"middleware": [],
|
||||||
|
"metadata": {
|
||||||
|
"args": {
|
||||||
|
"a": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"description": "arg a",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"demo": {
|
||||||
|
/**
|
||||||
|
* First demo route demonstrating string and number parameters
|
||||||
|
*
|
||||||
|
* @param data - Request parameters
|
||||||
|
* @param data.username - {string (minLength: 3, maxLength: 20)} The username to be validated, must be between 3 and 20 characters
|
||||||
|
* @param data.age - {number (min: 18, max: 100)} The age of the user, must be between 18 and 100
|
||||||
|
* @param data.email - {string (format: email)} The email address of the user for notification purposes
|
||||||
|
* @param data.count - {integer (max: 9007199254740991, > 0)} The number of items to process, must be a positive integer
|
||||||
|
* @param data.name - {string} The display name of the user
|
||||||
|
*/
|
||||||
|
"d1": {
|
||||||
|
"path": "demo",
|
||||||
|
"key": "d1",
|
||||||
|
"description": "First demo route demonstrating string and number parameters",
|
||||||
|
"type": "route",
|
||||||
|
"middleware": [],
|
||||||
|
"metadata": {
|
||||||
|
"args": {
|
||||||
|
"username": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 3,
|
||||||
|
"maxLength": 20,
|
||||||
|
"description": "The username to be validated, must be between 3 and 20 characters"
|
||||||
|
},
|
||||||
|
"age": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 18,
|
||||||
|
"maximum": 100,
|
||||||
|
"description": "The age of the user, must be between 18 and 100"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "string",
|
||||||
|
"format": "email",
|
||||||
|
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
|
||||||
|
"description": "The email address of the user for notification purposes"
|
||||||
|
},
|
||||||
|
"count": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "integer",
|
||||||
|
"exclusiveMinimum": 0,
|
||||||
|
"maximum": 9007199254740991,
|
||||||
|
"description": "The number of items to process, must be a positive integer"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "string",
|
||||||
|
"description": "The display name of the user"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Second demo route for boolean and enum parameters
|
||||||
|
*
|
||||||
|
* @param data - Request parameters
|
||||||
|
* @param data.isActive - {boolean} Whether the user account is currently active and accessible
|
||||||
|
* @param data.isAdmin - {boolean} Whether the user has administrative privileges
|
||||||
|
* @param data.notifications - {boolean} Whether to enable email and push notifications
|
||||||
|
* @param data.mode - {"read" | "write" | "execute"} The operation mode for the current session
|
||||||
|
* @param data.verified - {boolean} Whether the user email has been verified
|
||||||
|
*/
|
||||||
|
"d2": {
|
||||||
|
"path": "demo",
|
||||||
|
"key": "d2",
|
||||||
|
"description": "Second demo route for boolean and enum parameters",
|
||||||
|
"type": "route",
|
||||||
|
"middleware": [],
|
||||||
|
"metadata": {
|
||||||
|
"args": {
|
||||||
|
"isActive": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether the user account is currently active and accessible"
|
||||||
|
},
|
||||||
|
"isAdmin": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether the user has administrative privileges"
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to enable email and push notifications"
|
||||||
|
},
|
||||||
|
"mode": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"read",
|
||||||
|
"write",
|
||||||
|
"execute"
|
||||||
|
],
|
||||||
|
"description": "The operation mode for the current session"
|
||||||
|
},
|
||||||
|
"verified": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether the user email has been verified"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Third demo route handling array and optional parameters
|
||||||
|
*
|
||||||
|
* @param data - Request parameters
|
||||||
|
* @param data.tags - {array} List of tags associated with the content, between 1 and 10 tags
|
||||||
|
* @param data.categories - {array} List of category names for filtering and classification
|
||||||
|
* @param data.ids - {array} Array of numeric identifiers for the resources
|
||||||
|
* @param data.priority - {number (min: 1, max: 5)} Priority level from 1 to 5, defaults to 3 if not specified
|
||||||
|
* @param data.keywords - {array} Keywords for search optimization, up to 20 keywords
|
||||||
|
*/
|
||||||
|
"d3": {
|
||||||
|
"path": "demo",
|
||||||
|
"key": "d3",
|
||||||
|
"description": "Third demo route handling array and optional parameters",
|
||||||
|
"type": "route",
|
||||||
|
"middleware": [],
|
||||||
|
"metadata": {
|
||||||
|
"args": {
|
||||||
|
"tags": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": 10,
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "List of tags associated with the content, between 1 and 10 tags"
|
||||||
|
},
|
||||||
|
"categories": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "List of category names for filtering and classification"
|
||||||
|
},
|
||||||
|
"ids": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "integer",
|
||||||
|
"exclusiveMinimum": 0,
|
||||||
|
"maximum": 9007199254740991
|
||||||
|
},
|
||||||
|
"description": "Array of numeric identifiers for the resources"
|
||||||
|
},
|
||||||
|
"priority": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"description": "Priority level from 1 to 5, defaults to 3 if not specified",
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 1,
|
||||||
|
"maximum": 5
|
||||||
|
},
|
||||||
|
"keywords": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"maxItems": 20,
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "Keywords for search optimization, up to 20 keywords"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Fourth demo route with nested object parameters
|
||||||
|
*
|
||||||
|
* @param data - Request parameters
|
||||||
|
* @param data.user - {object} Complete user profile information
|
||||||
|
* @param data.settings - {object} User preference settings
|
||||||
|
* @param data.address - {object} Mailing address, optional field
|
||||||
|
*/
|
||||||
|
"d4": {
|
||||||
|
"path": "demo",
|
||||||
|
"key": "d4",
|
||||||
|
"description": "Fourth demo route with nested object parameters",
|
||||||
|
"type": "route",
|
||||||
|
"middleware": [],
|
||||||
|
"metadata": {
|
||||||
|
"args": {
|
||||||
|
"user": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "integer",
|
||||||
|
"exclusiveMinimum": 0,
|
||||||
|
"maximum": 9007199254740991,
|
||||||
|
"description": "Unique identifier for the user"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Full name of the user"
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"email": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "email",
|
||||||
|
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
|
||||||
|
"description": "Primary email address"
|
||||||
|
},
|
||||||
|
"phone": {
|
||||||
|
"description": "Phone number with country code",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"email"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "Contact information for the user"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"contact"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "Complete user profile information"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"theme": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"light",
|
||||||
|
"dark",
|
||||||
|
"auto"
|
||||||
|
],
|
||||||
|
"description": "UI theme preference"
|
||||||
|
},
|
||||||
|
"language": {
|
||||||
|
"default": "en",
|
||||||
|
"description": "Preferred language code",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"timezone": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Timezone identifier like America/New_York"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"theme",
|
||||||
|
"language",
|
||||||
|
"timezone"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "User preference settings"
|
||||||
|
},
|
||||||
|
"address": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"description": "Mailing address, optional field",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"street": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Street address line"
|
||||||
|
},
|
||||||
|
"city": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "City name"
|
||||||
|
},
|
||||||
|
"country": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Country code or name"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"street",
|
||||||
|
"city",
|
||||||
|
"country"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Fifth demo route with mixed complex parameters and validation
|
||||||
|
*
|
||||||
|
* @param data - Request parameters
|
||||||
|
* @param data.query - {string (minLength: 1)} Search query string, minimum 1 character required
|
||||||
|
* @param data.filters - {object} Advanced search filters configuration
|
||||||
|
* @param data.pagination - {object} Pagination settings for query results
|
||||||
|
* @param data.includeMetadata - {boolean} Whether to include metadata in response
|
||||||
|
* @param data.timeout - {number (min: 1000, max: 30000)} Request timeout in milliseconds, between 1s and 30s
|
||||||
|
* @param data.retry - {integer (min: 0, max: 5)} Number of retry attempts on failure
|
||||||
|
*/
|
||||||
|
"d5": {
|
||||||
|
"path": "demo",
|
||||||
|
"key": "d5",
|
||||||
|
"description": "Fifth demo route with mixed complex parameters and validation",
|
||||||
|
"type": "route",
|
||||||
|
"middleware": [],
|
||||||
|
"metadata": {
|
||||||
|
"args": {
|
||||||
|
"query": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
"description": "Search query string, minimum 1 character required"
|
||||||
|
},
|
||||||
|
"filters": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"all",
|
||||||
|
"image",
|
||||||
|
"video",
|
||||||
|
"audio",
|
||||||
|
"document"
|
||||||
|
],
|
||||||
|
"description": "Content type filter"
|
||||||
|
},
|
||||||
|
"dateRange": {
|
||||||
|
"description": "Date range filter, optional",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"start": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time",
|
||||||
|
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
|
||||||
|
"description": "Start date in ISO 8601 format"
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time",
|
||||||
|
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
|
||||||
|
"description": "End date in ISO 8601 format"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"start",
|
||||||
|
"end"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
"size": {
|
||||||
|
"description": "Size filter for media content",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"small",
|
||||||
|
"medium",
|
||||||
|
"large",
|
||||||
|
"extra-large"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "Advanced search filters configuration"
|
||||||
|
},
|
||||||
|
"pagination": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"page": {
|
||||||
|
"default": 1,
|
||||||
|
"description": "Page number starting from 1",
|
||||||
|
"type": "integer",
|
||||||
|
"exclusiveMinimum": 0,
|
||||||
|
"maximum": 9007199254740991
|
||||||
|
},
|
||||||
|
"limit": {
|
||||||
|
"default": 20,
|
||||||
|
"description": "Number of items per page, max 100",
|
||||||
|
"type": "integer",
|
||||||
|
"exclusiveMinimum": 0,
|
||||||
|
"maximum": 100
|
||||||
|
},
|
||||||
|
"sort": {
|
||||||
|
"default": "desc",
|
||||||
|
"description": "Sort order for results",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"asc",
|
||||||
|
"desc"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"page",
|
||||||
|
"limit",
|
||||||
|
"sort"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "Pagination settings for query results"
|
||||||
|
},
|
||||||
|
"includeMetadata": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"default": false,
|
||||||
|
"description": "Whether to include metadata in response",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"timeout": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"description": "Request timeout in milliseconds, between 1s and 30s",
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 1000,
|
||||||
|
"maximum": 30000
|
||||||
|
},
|
||||||
|
"retry": {
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"default": 3,
|
||||||
|
"description": "Number of retry attempts on failure",
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"router": {
|
||||||
|
/**
|
||||||
|
* 列出当前应用下的所有的路由信息
|
||||||
|
*/
|
||||||
|
"list": {
|
||||||
|
"path": "router",
|
||||||
|
"key": "list",
|
||||||
|
"description": "列出当前应用下的所有的路由信息",
|
||||||
|
"type": "route",
|
||||||
|
"middleware": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} as const;
|
||||||
|
const queryApi = createQueryApi({ api });
|
||||||
|
export { queryApi };
|
||||||
131
test/router.ts
Normal file
131
test/router.ts
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
import { App } from '@kevisual/router';
|
||||||
|
import { z } from 'zod';
|
||||||
|
export const app = new App({});
|
||||||
|
|
||||||
|
app
|
||||||
|
.route({
|
||||||
|
path: 'test',
|
||||||
|
key: 'test',
|
||||||
|
description: 'test route',
|
||||||
|
metadata: {
|
||||||
|
args: {
|
||||||
|
a: z.string().optional().describe('arg a'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.define(async (ctx) => {
|
||||||
|
ctx.body = 'test';
|
||||||
|
})
|
||||||
|
.addTo(app);
|
||||||
|
|
||||||
|
app.route({
|
||||||
|
path: 'demo',
|
||||||
|
key: 'd1',
|
||||||
|
description: 'First demo route demonstrating string and number parameters',
|
||||||
|
metadata: {
|
||||||
|
args: {
|
||||||
|
username: z.string().min(3).max(20).describe('The username to be validated, must be between 3 and 20 characters'),
|
||||||
|
age: z.number().min(18).max(100).describe('The age of the user, must be between 18 and 100'),
|
||||||
|
email: z.email().describe('The email address of the user for notification purposes'),
|
||||||
|
count: z.number().int().positive().describe('The number of items to process, must be a positive integer'),
|
||||||
|
name: z.string().describe('The display name of the user'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
ctx.body = 'demo1';
|
||||||
|
}).addTo(app);
|
||||||
|
|
||||||
|
app.route({
|
||||||
|
path: 'demo',
|
||||||
|
key: 'd2',
|
||||||
|
description: 'Second demo route for boolean and enum parameters',
|
||||||
|
metadata: {
|
||||||
|
args: {
|
||||||
|
isActive: z.boolean().describe('Whether the user account is currently active and accessible'),
|
||||||
|
isAdmin: z.boolean().describe('Whether the user has administrative privileges'),
|
||||||
|
notifications: z.boolean().describe('Whether to enable email and push notifications'),
|
||||||
|
mode: z.enum(['read', 'write', 'execute']).describe('The operation mode for the current session'),
|
||||||
|
verified: z.boolean().describe('Whether the user email has been verified'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
ctx.body = 'demo2';
|
||||||
|
}).addTo(app);
|
||||||
|
|
||||||
|
app.route({
|
||||||
|
path: 'demo',
|
||||||
|
key: 'd3',
|
||||||
|
description: 'Third demo route handling array and optional parameters',
|
||||||
|
metadata: {
|
||||||
|
args: {
|
||||||
|
tags: z.array(z.string()).min(1).max(10).describe('List of tags associated with the content, between 1 and 10 tags'),
|
||||||
|
categories: z.array(z.string()).describe('List of category names for filtering and classification'),
|
||||||
|
ids: z.array(z.number().int().positive()).describe('Array of numeric identifiers for the resources'),
|
||||||
|
priority: z.number().min(1).max(5).optional().describe('Priority level from 1 to 5, defaults to 3 if not specified'),
|
||||||
|
keywords: z.array(z.string()).max(20).describe('Keywords for search optimization, up to 20 keywords'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
ctx.body = 'demo3';
|
||||||
|
}).addTo(app);
|
||||||
|
|
||||||
|
app.route({
|
||||||
|
path: 'demo',
|
||||||
|
key: 'd4',
|
||||||
|
description: 'Fourth demo route with nested object parameters',
|
||||||
|
metadata: {
|
||||||
|
args: {
|
||||||
|
user: z.object({
|
||||||
|
id: z.number().int().positive().describe('Unique identifier for the user'),
|
||||||
|
name: z.string().describe('Full name of the user'),
|
||||||
|
contact: z.object({
|
||||||
|
email: z.email().describe('Primary email address'),
|
||||||
|
phone: z.string().optional().describe('Phone number with country code'),
|
||||||
|
}).describe('Contact information for the user'),
|
||||||
|
}).describe('Complete user profile information'),
|
||||||
|
settings: z.object({
|
||||||
|
theme: z.enum(['light', 'dark', 'auto']).describe('UI theme preference'),
|
||||||
|
language: z.string().default('en').describe('Preferred language code'),
|
||||||
|
timezone: z.string().describe('Timezone identifier like America/New_York'),
|
||||||
|
}).describe('User preference settings'),
|
||||||
|
address: z.object({
|
||||||
|
street: z.string().describe('Street address line'),
|
||||||
|
city: z.string().describe('City name'),
|
||||||
|
country: z.string().describe('Country code or name'),
|
||||||
|
}).optional().describe('Mailing address, optional field'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
ctx.body = 'demo4';
|
||||||
|
}).addTo(app);
|
||||||
|
|
||||||
|
app.route({
|
||||||
|
path: 'demo',
|
||||||
|
key: 'd5',
|
||||||
|
description: 'Fifth demo route with mixed complex parameters and validation',
|
||||||
|
metadata: {
|
||||||
|
args: {
|
||||||
|
query: z.string().min(1).describe('Search query string, minimum 1 character required'),
|
||||||
|
filters: z.object({
|
||||||
|
type: z.enum(['all', 'image', 'video', 'audio', 'document']).describe('Content type filter'),
|
||||||
|
dateRange: z.object({
|
||||||
|
start: z.iso.datetime().describe('Start date in ISO 8601 format'),
|
||||||
|
end: z.iso.datetime().describe('End date in ISO 8601 format'),
|
||||||
|
}).optional().describe('Date range filter, optional'),
|
||||||
|
size: z.enum(['small', 'medium', 'large', 'extra-large']).optional().describe('Size filter for media content'),
|
||||||
|
}).describe('Advanced search filters configuration'),
|
||||||
|
pagination: z.object({
|
||||||
|
page: z.number().int().positive().default(1).describe('Page number starting from 1'),
|
||||||
|
limit: z.number().int().positive().max(100).default(20).describe('Number of items per page, max 100'),
|
||||||
|
sort: z.enum(['asc', 'desc']).default('desc').describe('Sort order for results'),
|
||||||
|
}).describe('Pagination settings for query results'),
|
||||||
|
includeMetadata: z.boolean().default(false).describe('Whether to include metadata in response'),
|
||||||
|
timeout: z.number().min(1000).max(30000).optional().describe('Request timeout in milliseconds, between 1s and 30s'),
|
||||||
|
retry: z.number().int().min(0).max(5).default(3).describe('Number of retry attempts on failure'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
ctx.body = 'demo5';
|
||||||
|
}).addTo(app);
|
||||||
|
|
||||||
|
app.createRouteList()
|
||||||
43
test/schema.ts
Normal file
43
test/schema.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import z, { toJSONSchema } from "zod";
|
||||||
|
|
||||||
|
const schema = z.object({
|
||||||
|
name: z.string().describe("The name of the person"),
|
||||||
|
age: z.number().int().min(0).describe("The age of the person"),
|
||||||
|
email: z.string().optional().describe("The email address of the person"),
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("JSON Schema for the person object:");
|
||||||
|
console.log(
|
||||||
|
JSON.stringify(toJSONSchema(schema), null, 2)
|
||||||
|
);
|
||||||
|
const jsonSchema = toJSONSchema(schema);
|
||||||
|
|
||||||
|
const schema2 = z.fromJSONSchema(jsonSchema);
|
||||||
|
|
||||||
|
// schema2 的类型是 ZodSchema<any>,所以无法在编译时推断出具体类型
|
||||||
|
// 这是 fromJSONSchema 的限制 - JSON Schema 转换会丢失 TypeScript 类型信息
|
||||||
|
|
||||||
|
schema2.parse({
|
||||||
|
name: "John Doe",
|
||||||
|
age: 30, // 添加必需的 age 字段
|
||||||
|
email: "",
|
||||||
|
})
|
||||||
|
|
||||||
|
type Schema2Type = z.infer<typeof schema2>;
|
||||||
|
// Schema2Type 被推断为 any
|
||||||
|
|
||||||
|
// 对比:原始 schema 的类型推断是正常的
|
||||||
|
type OriginalSchemaType = z.infer<typeof schema>;
|
||||||
|
// OriginalSchemaType = { name: string; age: number; email?: string | undefined }
|
||||||
|
|
||||||
|
const v: Schema2Type = {
|
||||||
|
name: "John Doe",
|
||||||
|
email: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果使用原始 schema,类型推断会正常工作:
|
||||||
|
const v2: OriginalSchemaType = {
|
||||||
|
name: "John Doe",
|
||||||
|
age: 30,
|
||||||
|
// email 是可选的
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
"sourceMap": false,
|
"sourceMap": false,
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"newLine": "LF",
|
"newLine": "LF",
|
||||||
|
"rootDir": ".",
|
||||||
"baseUrl": "./",
|
"baseUrl": "./",
|
||||||
"declaration": false,
|
"declaration": false,
|
||||||
"typeRoots": [
|
"typeRoots": [
|
||||||
@@ -21,20 +22,17 @@
|
|||||||
"paths": {
|
"paths": {
|
||||||
"@/*": [
|
"@/*": [
|
||||||
"src/*"
|
"src/*"
|
||||||
],
|
|
||||||
"*": [
|
|
||||||
"types/*"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"typings.d.ts",
|
"typings.d.ts",
|
||||||
"src/**/*.ts"
|
"src/**/*.ts",
|
||||||
|
"test/**/*.ts"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules",
|
"node_modules",
|
||||||
"demo/simple/dist",
|
"demo/simple/dist",
|
||||||
"src/**/*.test.ts",
|
"src/**/*.test.ts",
|
||||||
"rollup.config.js",
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user