From a54ba4d823c15022a42e3d79e50004c094ef12de Mon Sep 17 00:00:00 2001 From: abearxiong Date: Fri, 18 Apr 2025 03:22:29 +0800 Subject: [PATCH] test deno --- deno-router-demo/deno.json | 42 +++ deno-router-demo/package.json | 17 + deno-router-demo/pnpm-lock.yaml | 83 +++++ deno-router-demo/src/index.ts | 32 ++ deno-router-demo/src/web-ws.ts | 28 ++ deno-router-demo/tsconfig.json | 41 +++ deno-router/index.ts | 2 +- deno-router2/check-env.ts | 6 + deno-router2/deno.json | 48 +++ deno-router2/deno.lock | 62 ++++ deno-router2/index.ts | 34 ++ deno-router2/types/router.d.ts | 618 ++++++++++++++++++++++++++++++++ deno-router3/check-env.ts | 6 + deno-router3/deno.json | 49 +++ deno-router3/deno.lock | 78 ++++ deno-router3/gpu.ts | 15 + deno-router3/index.ts | 59 +++ deno-router3/listen.ts | 34 ++ deno-router3/types/router.d.ts | 618 ++++++++++++++++++++++++++++++++ deno-server/server.ts | 5 + deno-server/ws-server.ts | 30 ++ deno.json | 33 ++ deno.lock | 44 +++ package.json | 2 +- pnpm-lock.yaml | 28 +- 25 files changed, 1989 insertions(+), 25 deletions(-) create mode 100644 deno-router-demo/deno.json create mode 100644 deno-router-demo/package.json create mode 100644 deno-router-demo/pnpm-lock.yaml create mode 100644 deno-router-demo/src/index.ts create mode 100644 deno-router-demo/src/web-ws.ts create mode 100644 deno-router-demo/tsconfig.json create mode 100644 deno-router2/check-env.ts create mode 100644 deno-router2/deno.json create mode 100644 deno-router2/deno.lock create mode 100644 deno-router2/index.ts create mode 100644 deno-router2/types/router.d.ts create mode 100644 deno-router3/check-env.ts create mode 100644 deno-router3/deno.json create mode 100644 deno-router3/deno.lock create mode 100644 deno-router3/gpu.ts create mode 100644 deno-router3/index.ts create mode 100644 deno-router3/listen.ts create mode 100644 deno-router3/types/router.d.ts create mode 100644 deno-server/server.ts create mode 100644 deno-server/ws-server.ts create mode 100644 deno.json create mode 100644 deno.lock diff --git a/deno-router-demo/deno.json b/deno-router-demo/deno.json new file mode 100644 index 0000000..b6dd252 --- /dev/null +++ b/deno-router-demo/deno.json @@ -0,0 +1,42 @@ +{ + "tasks": { + "start": "deno run --allow-all index.ts" + }, + "imports": { + "@kevisual/router": "https://esm.xiongxiao.me/@kevisual/router/src/mod.ts" + }, + "compilerOptions": { + "types": [ + "./types", + "https://esm.xiongxiao.me/@kevisual/router@0.0.10/dist/router.d.ts" + ] + }, + "fmt": { + "files": { + + "include": ["src/"], + "exclude": [] + }, + "options": { + "lineWidth": 80, + "indentWidth": 2, + "useTabs": false, + "singleQuote": false, + "proseWrap": "preserve" + } + }, + "lint": { + "include": [ + "./src/**/*.ts", + "index.ts" + ], + "exclude": [ + "./types" + ], + "rules": { + "tags": ["recommended"], + "include": [], + "exclude": ["require-await"] + } + } +} \ No newline at end of file diff --git a/deno-router-demo/package.json b/deno-router-demo/package.json new file mode 100644 index 0000000..19c3f08 --- /dev/null +++ b/deno-router-demo/package.json @@ -0,0 +1,17 @@ +{ + "name": "deno-router-demo", + "version": "0.0.1", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "abearxiong (https://www.xiongxiao.me)", + "license": "MIT", + "packageManager": "pnpm@10.8.1", + "type": "module", + "dependencies": { + "@kevisual/router": "^0.0.11" + } +} diff --git a/deno-router-demo/pnpm-lock.yaml b/deno-router-demo/pnpm-lock.yaml new file mode 100644 index 0000000..f4a62b3 --- /dev/null +++ b/deno-router-demo/pnpm-lock.yaml @@ -0,0 +1,83 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@kevisual/router': + specifier: ^0.0.11 + version: 0.0.11 + +packages: + + '@kevisual/router@0.0.11': + resolution: {integrity: sha512-i/gVqIv3UpjdyS0zZHoDWYTBnL4YWGmj/8O8GQV7xxXZXJPRXLHjLC1ylRhwEGBdb6UxabKohplr7HKRuIJ2Ag==} + + '@types/node-forge@1.3.11': + resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} + + '@types/node@22.14.1': + resolution: {integrity: sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==} + + node-forge@1.3.1: + resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} + engines: {node: '>= 6.13.0'} + + path-to-regexp@8.2.0: + resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==} + engines: {node: '>=16'} + + selfsigned@2.4.1: + resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} + engines: {node: '>=10'} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + ws@8.18.1: + resolution: {integrity: sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + +snapshots: + + '@kevisual/router@0.0.11': + dependencies: + path-to-regexp: 8.2.0 + selfsigned: 2.4.1 + ws: 8.18.1 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@types/node-forge@1.3.11': + dependencies: + '@types/node': 22.14.1 + + '@types/node@22.14.1': + dependencies: + undici-types: 6.21.0 + + node-forge@1.3.1: {} + + path-to-regexp@8.2.0: {} + + selfsigned@2.4.1: + dependencies: + '@types/node-forge': 1.3.11 + node-forge: 1.3.1 + + undici-types@6.21.0: {} + + ws@8.18.1: {} diff --git a/deno-router-demo/src/index.ts b/deno-router-demo/src/index.ts new file mode 100644 index 0000000..009e12a --- /dev/null +++ b/deno-router-demo/src/index.ts @@ -0,0 +1,32 @@ +// import { App } from '@kevisual/router'; +import { App } from '@kevisual/router/mod.ts'; + +console.log('meta', import.meta.url); +// deno run --allow-all index.ts +// deno run --config ./deno.json --allow-all index.ts +console.log('hello world'); + +const app = new App({ + io: true, +}); + +app + .route({ + path: 'demo', + }) + .define(async (ctx) => { + ctx.body = 'hello world'; + }) + .addTo(app); + +app.listen(10004, () => { + console.log('Server is running on http://localhost:10004'); +}); + +app.io.addListener('goo', async ({ data, ws, end }) => { + console.log('goo', data); + end({ + code: 200, + message: 'hello world goo', + }); +}); diff --git a/deno-router-demo/src/web-ws.ts b/deno-router-demo/src/web-ws.ts new file mode 100644 index 0000000..03b095b --- /dev/null +++ b/deno-router-demo/src/web-ws.ts @@ -0,0 +1,28 @@ +const ws = new WebSocket('ws://localhost:10004/api/router'); + +ws.onopen = () => { + console.log('open'); +}; + +ws.onmessage = (event) => { + console.log('message', event.data); + const data = event.data; + if (data === 'connected') { + const data = { + type: 'router', + requestId: 'requestId', + data: { + path: 'demo', + }, + }; + ws.send(JSON.stringify(data)); + const data2= { + type: 'goo' + }; + ws.send(JSON.stringify(data2)); + } +}; + +ws.onerror = (event) => { + console.log('error', event); +}; diff --git a/deno-router-demo/tsconfig.json b/deno-router-demo/tsconfig.json new file mode 100644 index 0000000..cff196e --- /dev/null +++ b/deno-router-demo/tsconfig.json @@ -0,0 +1,41 @@ +{ + "compilerOptions": { + "module": "NodeNext", + "target": "esnext", + "noImplicitAny": false, + "outDir": "./dist", + "sourceMap": false, + "allowJs": true, + "newLine": "LF", + "baseUrl": "./", + "typeRoots": [ + "node_modules/@types", + "src/@types" + ], + "declaration": true, + "noEmit": false, + // "allowImportingTsExtensions": true, + "moduleResolution": "NodeNext", + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "esModuleInterop": true, + "paths": { + "@/*": [ + "src/*" + ], + "*": [ + "types/*" + ] + } + }, + "include": [ + "typings.d.ts", + "src/**/*.ts" + ], + "exclude": [ + "node_modules", + "dist", + "src/**/*.test.ts", + "webpack.config.cjs", + ], +} \ No newline at end of file diff --git a/deno-router/index.ts b/deno-router/index.ts index 2559e87..c6e50a9 100644 --- a/deno-router/index.ts +++ b/deno-router/index.ts @@ -1,5 +1,5 @@ +import { App } from '@kevisual/router/mod.ts'; // @ts-types="https://esm.xiongxiao.me/@kevisual/router/dist/router.d.ts?raw" -import { App } from '@kevisual/router'; console.log('meta', import.meta.url) // deno run --allow-all index.ts diff --git a/deno-router2/check-env.ts b/deno-router2/check-env.ts new file mode 100644 index 0000000..ef41317 --- /dev/null +++ b/deno-router2/check-env.ts @@ -0,0 +1,6 @@ +const isDeno = typeof Deno !== "undefined" && !!Deno.version; +const isNode = typeof process !== "undefined" && !!process.versions?.node; + +console.log('process', process.version); +console.log("isDeno", isDeno); +console.log("isNode", isNode); \ No newline at end of file diff --git a/deno-router2/deno.json b/deno-router2/deno.json new file mode 100644 index 0000000..76cbb67 --- /dev/null +++ b/deno-router2/deno.json @@ -0,0 +1,48 @@ +{ + "tasks": { + "start": "deno run --allow-all index.ts" + }, + "imports": { + "@kevisual/router/mod.ts": "https://esm.xiongxiao.me/@kevisual/router/src/mod.ts", + "ws": "npm:ws@8.13.0" + }, + "compilerOptions": { + "types": [ + "./types", + "https://esm.xiongxiao.me/@kevisual/router@0.0.10/dist/router.d.ts" + ] + }, + "fmt": { + "files": { + "include": [ + "src/" + ], + "exclude": [] + }, + "options": { + "lineWidth": 80, + "indentWidth": 2, + "useTabs": false, + "singleQuote": false, + "proseWrap": "preserve" + } + }, + "lint": { + "include": [ + "./src/**/*.ts", + "index.ts" + ], + "exclude": [ + "./types" + ], + "rules": { + "tags": [ + "recommended" + ], + "include": [], + "exclude": [ + "require-await" + ] + } + } +} \ No newline at end of file diff --git a/deno-router2/deno.lock b/deno-router2/deno.lock new file mode 100644 index 0000000..0ccc79f --- /dev/null +++ b/deno-router2/deno.lock @@ -0,0 +1,62 @@ +{ + "version": "4", + "specifiers": { + "npm:@types/node@*": "22.12.0", + "npm:ws@8.13.0": "8.13.0" + }, + "npm": { + "@types/node@22.12.0": { + "integrity": "sha512-Fll2FZ1riMjNmlmJOdAyY5pUbkftXslB5DgEzlIuNaiWhXd00FhWxVC/r4yV/4wBb9JfImTu+jiSvXTkJ7F/gA==", + "dependencies": [ + "undici-types" + ] + }, + "undici-types@6.20.0": { + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" + }, + "ws@8.13.0": { + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==" + } + }, + "redirects": { + "http://esm.xiongxiao.me/@types/ws@~8.18.1/index.d.mts": "http://esm.xiongxiao.me/@types/ws@8.18.1/index.d.mts", + "http://esm.xiongxiao.me/bufferutil@^4.0.1?target=denonext": "http://esm.xiongxiao.me/bufferutil@4.0.9?target=denonext", + "http://esm.xiongxiao.me/cookie?target=denonext": "http://esm.xiongxiao.me/cookie@1.0.2?target=denonext", + "http://esm.xiongxiao.me/lodash-es?target=denonext": "http://esm.xiongxiao.me/lodash-es@4.17.21?target=denonext", + "http://esm.xiongxiao.me/nanoid?target=denonext": "http://esm.xiongxiao.me/nanoid@5.1.5?target=denonext", + "http://esm.xiongxiao.me/node-gyp-build@^4.3.0?target=denonext": "http://esm.xiongxiao.me/node-gyp-build@4.8.4?target=denonext", + "http://esm.xiongxiao.me/utf-8-validate@%3E=5.0.2?target=denonext": "http://esm.xiongxiao.me/utf-8-validate@6.0.5?target=denonext", + "http://esm.xiongxiao.me/ws@^8.18.1?target=denonext": "http://esm.xiongxiao.me/ws@8.18.1?target=denonext", + "http://esm.xiongxiao.me/zod?target=denonext": "http://esm.xiongxiao.me/zod@3.24.3?target=denonext", + "https://esm.xiongxiao.me/@kevisual/router": "http://esm.xiongxiao.me/@kevisual/router@0.0.10", + "https://esm.xiongxiao.me/@kevisual/router/router": "http://esm.xiongxiao.me/@kevisual/router@0.0.10/router", + "https://esm.xiongxiao.me/@kevisual/router/src/mod.ts": "http://esm.xiongxiao.me/@kevisual/router@0.0.11/src/mod.ts" + }, + "remote": { + "http://esm.xiongxiao.me/@kevisual/router@0.0.10": "f7e3ea672cef9b532b62cc557f3369afbe7bdfd35001a62cd246033b303af048", + "http://esm.xiongxiao.me/@kevisual/router@0.0.10/denonext/router.mjs": "ee734dfbbe30415695d67e9d735e968e0e4554dc77b14368603a51273641a580", + "http://esm.xiongxiao.me/@kevisual/router@0.0.11/denonext/src/mod.ts.mjs": "f205c1fa864e6deaad100ab873c194b21e1005a0366699ec5b17391faf7abfec", + "http://esm.xiongxiao.me/@kevisual/router@0.0.11/src/mod.ts": "553715d1d0e8e9ba5b1ba7bbfc33362162e8f8f4840c09110951b67c877861ae", + "http://esm.xiongxiao.me/bufferutil@4.0.9/denonext/bufferutil.mjs": "13dca4d5bb2c68cbe119f880fa3bd785b9a81a8e02e0834dae604b4b85295cd8", + "http://esm.xiongxiao.me/bufferutil@4.0.9?target=denonext": "e32574569ab438facfcc3f412c659b0719bbf05477136ca176938c9a3ac45125", + "http://esm.xiongxiao.me/cookie@1.0.2/denonext/cookie.mjs": "6c4f976d4d933ff2d7afc1f6ee7af134108c9858f5a2aadc6189084bd5972275", + "http://esm.xiongxiao.me/cookie@1.0.2?target=denonext": "04dabbcad7a7a96d841d6b21f00cb20191fb29339781237088d8edabad52df66", + "http://esm.xiongxiao.me/lodash-es@4.17.21/denonext/lodash-es.mjs": "83b25b8f85872b2805e6b0273c90d6c96960c80a710c55e89a7b399107fc6fa8", + "http://esm.xiongxiao.me/lodash-es@4.17.21?target=denonext": "1252ccd86311d14f2dd05282cf3e40e1ff76bfa79c71ca49b903e902129944cb", + "http://esm.xiongxiao.me/nanoid@5.1.5/denonext/nanoid.mjs": "dc919f2d7339a244f732a0cf02e3962dd1289535668026f52fb26bd593e9358b", + "http://esm.xiongxiao.me/nanoid@5.1.5?target=denonext": "33ad5b17f1290cb850164cfcf30f642d9dad489ba19909bc3cfd9eb78369f451", + "http://esm.xiongxiao.me/node-gyp-build@4.8.4/denonext/node-gyp-build.mjs": "9a86f2d044fc77bd60aaa3d697c2ba1b818da5fb1b9aaeedec59a40b8e908803", + "http://esm.xiongxiao.me/node-gyp-build@4.8.4?target=denonext": "261a6cedf1fdbf159798141ba1e2311ac1510682c5c8b55dacc8cf5fdee4aa06", + "http://esm.xiongxiao.me/utf-8-validate@6.0.5/denonext/utf-8-validate.mjs": "66b8ea532a0c745068f5b96ddb1bae332c3036703243541d2e89e66331974d98", + "http://esm.xiongxiao.me/utf-8-validate@6.0.5?target=denonext": "071bc33ba1a58297e23a34d69dd589fd06df04b0f373b382ff5da544a623f271", + "http://esm.xiongxiao.me/ws@8.18.1/denonext/ws.mjs": "9c6726c262f19d2dbbd5b5224d9f118cdbeb793ea475ecd40de2b778886a5e16", + "http://esm.xiongxiao.me/ws@8.18.1?target=denonext": "e99b670fc49b38e15a7576ddcd5bb01e123fe9b3a017db7f97898127811b4e27", + "http://esm.xiongxiao.me/zod@3.24.3/denonext/zod.mjs": "46c4acb1f87caf349962b648f519cbf3999a8746fb40df0331ad2d3b62a197c0", + "http://esm.xiongxiao.me/zod@3.24.3?target=denonext": "8fb963869b1a83e910ff2fc4e64af7918e34b1350088455141b653233f274395" + }, + "workspace": { + "dependencies": [ + "npm:ws@8.13.0" + ] + } +} diff --git a/deno-router2/index.ts b/deno-router2/index.ts new file mode 100644 index 0000000..d59130f --- /dev/null +++ b/deno-router2/index.ts @@ -0,0 +1,34 @@ +// import { App } from '@kevisual/router'; +// @ts-types="https://esm.xiongxiao.me/@kevisual/router/dist/router.d.ts?raw" +import { App } from '@kevisual/router/mod.ts'; + +console.log('meta', import.meta.url); +// deno run --allow-all index.ts +// deno run --config ./deno.json --allow-all index.ts +console.log('hello world'); + +const app = new App({ + io: true, +}); + +app + .route({ + path: 'demo', + }) + .define(async (ctx) => { + ctx.body = 'hello world'; + }) + .addTo(app); + +app.listen(10004, () => { + console.log('Server is running on http://localhost:10004'); +}); + +app.io.addListener('goo', async ({ data, ws, end }) => { + console.log('goo', data); + end({ + code: 200, + message: 'hello world goo', + }); +}); + diff --git a/deno-router2/types/router.d.ts b/deno-router2/types/router.d.ts new file mode 100644 index 0000000..f032635 --- /dev/null +++ b/deno-router2/types/router.d.ts @@ -0,0 +1,618 @@ +import { Schema } from 'http://esm.xiongxiao.me/zod@3.24.3/index.d.ts'; +export { Schema } from 'http://esm.xiongxiao.me/zod@3.24.3/index.d.ts'; +import http, { IncomingMessage, ServerResponse } from 'node:http'; +import https from 'node:https'; +import http2 from 'node:http2'; +import * as cookie from 'http://esm.xiongxiao.me/cookie@1.0.2/dist/index.d.ts'; +import { WebSocketServer, WebSocket } from 'http://esm.xiongxiao.me/@types/ws@~8.18.1/index.d.mts'; + +type BaseRule = { + value?: any; + required?: boolean; + message?: string; +}; +type RuleString = { + type: 'string'; + minLength?: number; + maxLength?: number; + regex?: string; +} & BaseRule; +type RuleNumber = { + type: 'number'; + min?: number; + max?: number; +} & BaseRule; +type RuleBoolean = { + type: 'boolean'; +} & BaseRule; +type RuleArray = { + type: 'array'; + items: Rule; + minItems?: number; + maxItems?: number; +} & BaseRule; +type RuleObject = { + type: 'object'; + properties: { + [key: string]: Rule; + }; +} & BaseRule; +type RuleAny = { + type: 'any'; +} & BaseRule; +type Rule = RuleString | RuleNumber | RuleBoolean | RuleArray | RuleObject | RuleAny; +declare const createSchema: (rule: Rule) => Schema; + +type RouterContextT = { + code?: number; + [key: string]: any; +}; +type RouteContext = { + query?: { + [key: string]: any; + }; + /** return body */ + body?: number | string | Object; + /** return code */ + code?: number; + /** return msg */ + message?: string; + state?: S; + currentPath?: string; + currentKey?: string; + currentRoute?: Route; + progress?: [[string, string]][]; + nextQuery?: { + [key: string]: any; + }; + end?: boolean; + queryRouter?: QueryRouter; + error?: any; + /** 请求 route的返回结果,包函ctx */ + call?: (message: { + path: string; + key?: string; + payload?: any; + [key: string]: any; + } | { + id: string; + apyload?: any; + [key: string]: any; + }, ctx?: RouteContext & { + [key: string]: any; + }) => Promise; + /** 请求 route的返回结果,不包函ctx */ + queryRoute?: (message: { + path: string; + key?: string; + payload?: any; + }, ctx?: RouteContext & { + [key: string]: any; + }) => Promise; + index?: number; + throw?: (code?: number | string, message?: string, tips?: string) => void; + /** 是否需要序列化 */ + needSerialize?: boolean; +} & T; +type Run = (ctx: RouteContext) => Promise; +type NextRoute = Pick; +type RouteOpts = { + path?: string; + key?: string; + id?: string; + run?: Run; + nextRoute?: NextRoute; + description?: string; + metadata?: { + [key: string]: any; + }; + middleware?: Route[] | string[]; + type?: 'route' | 'middleware'; + /** + * validator: { + * packageName: { + * type: 'string', + * required: true, + * }, + * } + */ + validator?: { + [key: string]: Rule; + }; + schema?: { + [key: string]: Schema; + }; + isVerify?: boolean; + verify?: (ctx?: RouteContext, dev?: boolean) => boolean; + verifyKey?: (key: string, ctx?: RouteContext, dev?: boolean) => boolean; + /** + * $#$ will be used to split path and key + */ + idUsePath?: boolean; + isDebug?: boolean; +}; +type DefineRouteOpts = Omit; +declare const pickValue: readonly ["path", "key", "id", "description", "type", "validator", "middleware"]; +type RouteInfo = Pick; +declare class Route { + /** + * 一级路径 + */ + path?: string; + /** + * 二级路径 + */ + key?: string; + id?: string; + share?: boolean; + run?: Run; + nextRoute?: NextRoute; + description?: string; + metadata?: { + [key: string]: any; + }; + middleware?: (Route | string)[]; + type?: string; + private _validator?; + schema?: { + [key: string]: Schema; + }; + data?: any; + /** + * 是否需要验证 + */ + isVerify?: boolean; + /** + * 是否开启debug,开启后会打印错误信息 + */ + isDebug?: boolean; + constructor(path: string, key?: string, opts?: RouteOpts); + private createSchema; + /** + * set validator and create schema + * @param validator + */ + set validator(validator: { + [key: string]: Rule; + }); + get validator(): { + [key: string]: Rule; + }; + /** + * has code, body, message in ctx, return ctx if has error + * @param ctx + * @param dev + * @returns + */ + verify(ctx: RouteContext, dev?: boolean): void; + /** + * Need to manully call return ctx fn and configure body, code, message + * @param key + * @param ctx + * @param dev + * @returns + */ + verifyKey(key: string, ctx: RouteContext, dev?: boolean): { + message: string; + path: string; + key: string; + error: any; + } | { + message: string; + path: string; + key: string; + error?: undefined; + }; + setValidator(validator: { + [key: string]: Rule; + }): this; + define(opts: DefineRouteOpts): this; + define(fn: Run): this; + define(key: string, fn: Run): this; + define(path: string, key: string, fn: Run): this; + addTo(router: QueryRouter | { + add: (route: Route) => void; + [key: string]: any; + }): void; + setData(data: any): this; + throw(code?: number | string, message?: string, tips?: string): void; +} +declare class QueryRouter { + routes: Route[]; + maxNextRoute: number; + context?: RouteContext; + constructor(); + add(route: Route): void; + /** + * remove route by path and key + * @param route + */ + remove(route: Route | { + path: string; + key?: string; + }): void; + /** + * remove route by id + * @param uniqueId + */ + removeById(unique: string): void; + /** + * 执行route + * @param path + * @param key + * @param ctx + * @returns + */ + runRoute(path: string, key: string, ctx?: RouteContext): any; + /** + * 第一次执行 + * @param message + * @param ctx + * @returns + */ + parse(message: { + path: string; + key?: string; + payload?: any; + }, ctx?: RouteContext & { + [key: string]: any; + }): Promise; + /** + * 返回的数据包含所有的context的请求返回的内容,可做其他处理 + * @param message + * @param ctx + * @returns + */ + call(message: { + id?: string; + path?: string; + key?: string; + payload?: any; + }, ctx?: RouteContext & { + [key: string]: any; + }): Promise; + /** + * 请求 result 的数据 + * @param message + * @param ctx + * @returns + */ + queryRoute(message: { + path: string; + key?: string; + payload?: any; + }, ctx?: RouteContext & { + [key: string]: any; + }): Promise<{ + code: any; + data: any; + message: any; + }>; + setContext(ctx: RouteContext): Promise; + getList(): RouteInfo[]; + getHandle(router: QueryRouter, wrapperFn?: HandleFn, ctx?: RouteContext): (msg: { + path: string; + key?: string; + [key: string]: any; + }, handleContext?: RouteContext) => Promise<{ + [key: string]: any; + code: string; + data?: any; + message?: string; + } | { + code: any; + data: any; + message: any; + } | { + code: number; + message: any; + data?: undefined; + }>; + exportRoutes(): Route<{ + [key: string]: any; + }>[]; + importRoutes(routes: Route[]): void; + importRouter(router: QueryRouter): void; + throw(code?: number | string, message?: string, tips?: string): void; + hasRoute(path: string, key?: string): Route<{ + [key: string]: any; + }>; +} +type QueryRouterServerOpts = { + handleFn?: HandleFn; + context?: RouteContext; +}; +interface HandleFn { + (msg: { + path: string; + [key: string]: any; + }, ctx?: any): { + code: string; + data?: any; + message?: string; + [key: string]: any; + }; + (res: RouteContext): any; +} +/** + * QueryRouterServer + * @description 移除server相关的功能,只保留router相关的功能,和http.createServer不相关,独立 + */ +declare class QueryRouterServer extends QueryRouter { + handle: any; + constructor(opts?: QueryRouterServerOpts); + setHandle(wrapperFn?: HandleFn, ctx?: RouteContext): void; + use(path: string, fn: (ctx: any) => any, opts?: RouteOpts): void; + addRoute(route: Route): void; + Route: typeof Route; + route(opts: RouteOpts): Route>; + route(path: string, key?: string): Route>; + route(path: string, opts?: RouteOpts): Route>; + route(path: string, key?: string, opts?: RouteOpts): Route>; + /** + * 等于queryRoute,但是调用了handle + * @param param0 + * @returns + */ + run({ path, key, payload }: { + path: string; + key?: string; + payload?: any; + }): Promise; +} + +declare class Connect { + path: string; + key?: string; + _fn?: (ctx?: RouteContext) => Promise; + description?: string; + connects: { + path: string; + key?: string; + }[]; + share: boolean; + constructor(path: string); + use(path: string): void; + useList(paths: string[]): void; + useConnect(connect: Connect): void; + useConnectList(connects: Connect[]): void; + getPathList(): string[]; + set fn(fn: (ctx?: RouteContext) => Promise); + get fn(): (ctx?: RouteContext) => Promise; +} +declare class QueryConnect { + connects: Connect[]; + constructor(); + add(connect: Connect): void; + remove(connect: Connect): void; + getList(): { + path: string; + key: string; + }[]; +} + +type Listener = (...args: any[]) => void; +type CookieFn = (name: string, value: string, options?: cookie.SerializeOptions, end?: boolean) => void; +type HandleCtx = { + req: IncomingMessage & { + cookies: Record; + }; + res: ServerResponse & { + /** + * cookie 函数, end 参数用于设置是否立即设置到响应头,设置了后面的cookie再设置会覆盖前面的 + */ + cookie: CookieFn; + }; +}; +type Cors = { + /** + * @default '*'' + */ + origin?: string | undefined; +}; +type ServerOpts = { + /**path default `/api/router` */ + path?: string; + /**handle Fn */ + handle?: (msg?: { + path: string; + key?: string; + [key: string]: any; + }, ctx?: { + req: http.IncomingMessage; + res: http.ServerResponse; + }) => any; + cors?: Cors; + httpType?: 'http' | 'https' | 'http2'; + httpsKey?: string; + httpsCert?: string; +}; +declare class Server { + path: string; + private _server; + handle: ServerOpts['handle']; + private _callback; + private cors; + private hasOn; + private httpType; + private options; + constructor(opts?: ServerOpts); + listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void): void; + listen(port: number, hostname?: string, listeningListener?: () => void): void; + listen(port: number, backlog?: number, listeningListener?: () => void): void; + listen(port: number, listeningListener?: () => void): void; + listen(path: string, backlog?: number, listeningListener?: () => void): void; + listen(path: string, listeningListener?: () => void): void; + listen(handle: any, backlog?: number, listeningListener?: () => void): void; + listen(handle: any, listeningListener?: () => void): void; + createServer(): http.Server | https.Server | http2.Http2SecureServer; + setHandle(handle?: any): void; + /** + * get callback + * @returns + */ + createCallback(): (req: IncomingMessage, res: ServerResponse) => Promise; + get handleServer(): any; + set handleServer(fn: any); + /** + * 兜底监听,当除开 `/api/router` 之外的请求,框架只监听一个api,所以有其他的请求都执行其他的监听 + * @description 主要是为了兼容其他的监听 + * @param listener + */ + on(listener: Listener | Listener[]): void; + get callback(): any; + get server(): http.Server | https.Server | http2.Http2SecureServer; +} + +/** + * get params and body + * 优先原则 + * 1. 请求参数中的 payload 的token 优先 + * 2. 请求头中的 authorization 优先 + * 3. 请求头中的 cookie 优先 + * @param req + * @param res + * @returns + */ +declare const handleServer: (req: IncomingMessage, res: ServerResponse) => Promise<{ + cookies: Record; + token: string; +}>; + +/** 自定义错误 */ +declare class CustomError extends Error { + code?: number; + data?: any; + message: string; + tips?: string; + constructor(code?: number | string, message?: string, tips?: string); + static fromCode(code?: number): CustomError; + static fromErrorData(code?: number, data?: any): CustomError; + static parseError(e: CustomError): { + code: number; + data: any; + message: string; + tips: string; + }; + parse(e?: CustomError): { + code: number; + data: any; + message: string; + tips: string; + }; +} + +type WsServerBaseOpts = { + wss?: WebSocketServer; + path?: string; +}; +type ListenerFn = (message: { + data: Record; + ws: WebSocket; + end: (data: any) => any; +}) => Promise; +declare class WsServerBase { + wss: WebSocketServer; + path: string; + listeners: { + type: string; + listener: ListenerFn; + }[]; + listening: boolean; + constructor(opts: WsServerBaseOpts); + setPath(path: string): void; + listen(): void; + addListener(type: string, listener: ListenerFn): void; + removeListener(type: string): void; +} +declare class WsServer extends WsServerBase { + server: Server; + constructor(server: Server, opts?: any); + initListener(): void; + listen(): void; +} + +type RouterHandle = (msg: { + path: string; + [key: string]: any; +}) => { + code: string; + data?: any; + message?: string; + [key: string]: any; +}; +type AppOptions = { + router?: QueryRouter; + server?: Server; + /** handle msg 关联 */ + routerHandle?: RouterHandle; + routerContext?: RouteContext; + serverOptions?: ServerOpts; + io?: boolean; + ioOpts?: { + routerHandle?: RouterHandle; + routerContext?: RouteContext; + path?: string; + }; +}; +type AppReqRes = HandleCtx; +/** + * 封装了 Router 和 Server 的 App 模块,处理http的请求和响应,内置了 Cookie 和 Token 和 res 的处理 + */ +declare class App { + router: QueryRouter; + server: Server; + io: WsServer; + constructor(opts?: AppOptions); + listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void): void; + listen(port: number, hostname?: string, listeningListener?: () => void): void; + listen(port: number, backlog?: number, listeningListener?: () => void): void; + listen(port: number, listeningListener?: () => void): void; + listen(path: string, backlog?: number, listeningListener?: () => void): void; + listen(path: string, listeningListener?: () => void): void; + listen(handle: any, backlog?: number, listeningListener?: () => void): void; + listen(handle: any, listeningListener?: () => void): void; + use(path: string, fn: (ctx: any) => any, opts?: RouteOpts): void; + addRoute(route: Route): void; + add: (route: Route) => void; + Route: typeof Route; + route(opts: RouteOpts): Route; + route(path: string, key?: string): Route; + route(path: string, opts?: RouteOpts): Route; + route(path: string, key?: string, opts?: RouteOpts): Route; + call(message: { + path: string; + key?: string; + payload?: any; + }, ctx?: RouteContext & { + [key: string]: any; + }): Promise; + queryRoute(path: string, key?: string, payload?: any, ctx?: RouteContext & { + [key: string]: any; + }): Promise<{ + code: any; + data: any; + message: any; + }>; + exportRoutes(): Route<{ + [key: string]: any; + }>[]; + importRoutes(routes: any[]): void; + importApp(app: App): void; + throw(code?: number | string, message?: string, tips?: string): void; +} + +export { App, Connect, CustomError, QueryConnect, QueryRouter, QueryRouterServer, Route, Server, createSchema, handleServer }; +export type { RouteContext, RouteOpts, Rule, Run }; diff --git a/deno-router3/check-env.ts b/deno-router3/check-env.ts new file mode 100644 index 0000000..ef41317 --- /dev/null +++ b/deno-router3/check-env.ts @@ -0,0 +1,6 @@ +const isDeno = typeof Deno !== "undefined" && !!Deno.version; +const isNode = typeof process !== "undefined" && !!process.versions?.node; + +console.log('process', process.version); +console.log("isDeno", isDeno); +console.log("isNode", isNode); \ No newline at end of file diff --git a/deno-router3/deno.json b/deno-router3/deno.json new file mode 100644 index 0000000..2a1e7a3 --- /dev/null +++ b/deno-router3/deno.json @@ -0,0 +1,49 @@ +{ + "tasks": { + "start": "deno run --allow-all index.ts", + "listen": "deno run --allow-all listen.ts" + }, + "imports": { + "@kevisual/router/dist/router.js": "https://esm.sh/@kevisual/router@0.0.13/dist/router.js", + "@kevisual/router/router": "https://esm.sh/@kevisual/router@0.0.13/dist/router.js", + "@kevisual/router": "https://esm.sh/@kevisual/router@0.0.13/mod.ts?build=deno" + }, + "compilerOptions": { + "types": [ + "./types" + ] + }, + "fmt": { + "files": { + "include": [ + "src/" + ], + "exclude": [] + }, + "options": { + "lineWidth": 80, + "indentWidth": 2, + "useTabs": false, + "singleQuote": false, + "proseWrap": "preserve" + } + }, + "lint": { + "include": [ + "./src/**/*.ts", + "index.ts" + ], + "exclude": [ + "./types" + ], + "rules": { + "tags": [ + "recommended" + ], + "include": [], + "exclude": [ + "require-await" + ] + } + } +} \ No newline at end of file diff --git a/deno-router3/deno.lock b/deno-router3/deno.lock new file mode 100644 index 0000000..0bd4a8f --- /dev/null +++ b/deno-router3/deno.lock @@ -0,0 +1,78 @@ +{ + "version": "4", + "specifiers": { + "jsr:@std/webgpu@*": "0.224.8", + "npm:@types/node@*": "22.12.0" + }, + "jsr": { + "@std/webgpu@0.224.8": { + "integrity": "47c6bab2671dc7c36cb2505167cbf856bde1028be554f7be6463b30f51e4f8a3" + } + }, + "npm": { + "@types/node@22.12.0": { + "integrity": "sha512-Fll2FZ1riMjNmlmJOdAyY5pUbkftXslB5DgEzlIuNaiWhXd00FhWxVC/r4yV/4wBb9JfImTu+jiSvXTkJ7F/gA==", + "dependencies": [ + "undici-types" + ] + }, + "undici-types@6.20.0": { + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" + } + }, + "redirects": { + "https://esm.sh/@kevisual/router/mod.ts?build=deno": "https://esm.sh/@kevisual/router@0.0.13/mod.ts?build=deno", + "https://esm.sh/@kevisual/router/mod.ts?raw": "https://esm.sh/@kevisual/router@0.0.13/mod.ts?raw", + "https://esm.sh/@types/lodash-es@~4.17.12/index.d.ts": "https://esm.sh/@types/lodash-es@4.17.12/index.d.ts", + "https://esm.sh/@types/ws@~8.18.1/index.d.mts": "https://esm.sh/@types/ws@8.18.1/index.d.mts", + "https://esm.sh/@types/ws@~8.5.14/index.d.mts": "https://esm.sh/@types/ws@8.5.14/index.d.mts", + "https://esm.sh/bufferutil@^4.0.1?target=denonext": "https://esm.sh/bufferutil@4.0.9?target=denonext", + "https://esm.sh/cookie?target=denonext": "https://esm.sh/cookie@1.0.2?target=denonext", + "https://esm.sh/lodash-es?target=denonext": "https://esm.sh/lodash-es@4.17.21?target=denonext", + "https://esm.sh/nanoid?target=denonext": "https://esm.sh/nanoid@5.1.5?target=denonext", + "https://esm.sh/node-gyp-build@^4.3.0?target=denonext": "https://esm.sh/node-gyp-build@4.8.4?target=denonext", + "https://esm.sh/utf-8-validate@%3E=5.0.2?target=denonext": "https://esm.sh/utf-8-validate@6.0.5?target=denonext", + "https://esm.sh/ws?target=denonext": "https://esm.sh/ws@8.18.1?target=denonext", + "https://esm.sh/zod?target=denonext": "https://esm.sh/zod@3.24.3?target=denonext" + }, + "remote": { + "https://esm.sh/@kevisual/router/dist/router.js": "e21ea4aa25ffe1881f5d7f5fd693092e61373ec75f49e18cd6cc9eae2414aa87", + "https://esm.sh/@kevisual/router@0.0.12/es2022/router.mjs": "ab943944d6b5ac7a1094908eb3ce1bdd702421f6b87b5f593a010f8df286a3ca", + "https://esm.sh/@kevisual/router@0.0.13/denonext/mod.ts.mjs": "c410c788ebf66e21cc46f3388983d986efa6c34d7865261d93636bb6b9ef1215", + "https://esm.sh/@kevisual/router@0.0.13/denonext/router.mjs": "582f85d04bff25c875bf8c5b34a5cda63bfe6bdb2455b0fafaa8cc398b6ca43a", + "https://esm.sh/@kevisual/router@0.0.13/dist/router.js": "2428e75cd75f1ed2ab133b1e14d79d1bcb331e90630730d56bd658ae24c26032", + "https://esm.sh/@kevisual/router@0.0.13/mod.ts?build=deno": "a22a2c1b416e615e10da854a89d027314a6deb8392102a9eb7cc97e119736dcd", + "https://esm.sh/bufferutil@4.0.9/denonext/bufferutil.mjs": "13dca4d5bb2c68cbe119f880fa3bd785b9a81a8e02e0834dae604b4b85295cd8", + "https://esm.sh/bufferutil@4.0.9?target=denonext": "e32574569ab438facfcc3f412c659b0719bbf05477136ca176938c9a3ac45125", + "https://esm.sh/cookie@1.0.2/denonext/cookie.mjs": "6c4f976d4d933ff2d7afc1f6ee7af134108c9858f5a2aadc6189084bd5972275", + "https://esm.sh/cookie@1.0.2?target=denonext": "04dabbcad7a7a96d841d6b21f00cb20191fb29339781237088d8edabad52df66", + "https://esm.sh/lodash-es@4.17.21/denonext/lodash-es.mjs": "83b25b8f85872b2805e6b0273c90d6c96960c80a710c55e89a7b399107fc6fa8", + "https://esm.sh/lodash-es@4.17.21?target=denonext": "1252ccd86311d14f2dd05282cf3e40e1ff76bfa79c71ca49b903e902129944cb", + "https://esm.sh/nanoid@5.1.5/denonext/nanoid.mjs": "dc919f2d7339a244f732a0cf02e3962dd1289535668026f52fb26bd593e9358b", + "https://esm.sh/nanoid@5.1.5?target=denonext": "33ad5b17f1290cb850164cfcf30f642d9dad489ba19909bc3cfd9eb78369f451", + "https://esm.sh/node-gyp-build@4.8.4/denonext/node-gyp-build.mjs": "9a86f2d044fc77bd60aaa3d697c2ba1b818da5fb1b9aaeedec59a40b8e908803", + "https://esm.sh/node-gyp-build@4.8.4?target=denonext": "261a6cedf1fdbf159798141ba1e2311ac1510682c5c8b55dacc8cf5fdee4aa06", + "https://esm.sh/node/async_hooks.mjs": "d4a1534a095d1f582630fd1a553aa0a4a7a18430e218436852fcae9b1832cf8c", + "https://esm.sh/node/buffer.mjs": "43d7ffab85c67adc0575a7d7c463e84a61ee8efc455d95665c8eb8d4a31e17cd", + "https://esm.sh/node/chunk-2OF3LYRV.mjs": "d7de750c968c3ecde19048322afb56c171047475c042de0d183d636ec2261f5a", + "https://esm.sh/node/chunk-6GKFKS3A.mjs": "7902e4736377601004f9c88d66082a4ed0ab5615b4cd922011215527721916ab", + "https://esm.sh/node/chunk-AAUDITJX.mjs": "bc58a1ed4be556edd5788a17f933332b5722308b4b20245d92fd94b0e8af7459", + "https://esm.sh/node/chunk-KJ4M6W4Z.mjs": "e758c20e0173250999825c305e42e2005ead5aae78927ccbd310d236254f434e", + "https://esm.sh/node/chunk-WV3DHSZU.mjs": "69325e3b23d7ea15773f164a4995f2c0052808db8479bc1b6ec6a1df39c33c1b", + "https://esm.sh/node/events.mjs": "583424d07fdbb9a1248bf5090098ac4107aebcbe512763e6f509e5e7667f1014", + "https://esm.sh/node/http.mjs": "b29aedee4b801bd589a38d38103fd417c75af732511610ae5f28204b7e76b919", + "https://esm.sh/node/http2.mjs": "40fe45808ad7a0c70d80dd9f2758d1691bd76c02419617b2be6f27354c0ab670", + "https://esm.sh/node/https.mjs": "190895efe5bf1d7cd734c77b755eab0768556c667e04328ed6627c628025633b", + "https://esm.sh/node/net.mjs": "bdc14e7b53ad5d7be43ef36a425f2cfdf723f3b72a2da2c0ddb71cadeac8d786", + "https://esm.sh/node/path.mjs": "cae9540da52fce2321292b45936e839f523cb70fea4166feea75b764ddcff7e3", + "https://esm.sh/node/querystring.mjs": "dedbd6385b2cb7999b4a245cc446100e3263e155ecdc51de07dbfda12907547b", + "https://esm.sh/node/stream.mjs": "135b4483eb457de5fd856fa174d7efdedc55e26847a1bdbdafb19035719e79e9", + "https://esm.sh/node/url.mjs": "74e9759ff9b2603b1f74134f1ae6d3844928245999314d7a88aceb81ed18454b", + "https://esm.sh/utf-8-validate@6.0.5/denonext/utf-8-validate.mjs": "66b8ea532a0c745068f5b96ddb1bae332c3036703243541d2e89e66331974d98", + "https://esm.sh/utf-8-validate@6.0.5?target=denonext": "071bc33ba1a58297e23a34d69dd589fd06df04b0f373b382ff5da544a623f271", + "https://esm.sh/ws@8.18.1/denonext/ws.mjs": "732cae76ba0acb311a561003d2f7ef569293cb9159d67dd800ab346b84f80432", + "https://esm.sh/ws@8.18.1?target=denonext": "e99b670fc49b38e15a7576ddcd5bb01e123fe9b3a017db7f97898127811b4e27", + "https://esm.sh/zod@3.24.3/denonext/zod.mjs": "46c4acb1f87caf349962b648f519cbf3999a8746fb40df0331ad2d3b62a197c0", + "https://esm.sh/zod@3.24.3?target=denonext": "8fb963869b1a83e910ff2fc4e64af7918e34b1350088455141b653233f274395" + } +} diff --git a/deno-router3/gpu.ts b/deno-router3/gpu.ts new file mode 100644 index 0000000..0a54bc9 --- /dev/null +++ b/deno-router3/gpu.ts @@ -0,0 +1,15 @@ +import { createTextureWithData } from "jsr:@std/webgpu"; + +const adapter = await navigator.gpu.requestAdapter(); +const device = await adapter?.requestDevice()!; + +const texture = createTextureWithData(device, { + format: "bgra8unorm-srgb", + size: { + width: 3, + height: 2, + }, + usage: GPUTextureUsage.COPY_SRC, +}, new Uint8Array([1, 1, 1, 1, 1, 1, 1])); + +console.log(texture); \ No newline at end of file diff --git a/deno-router3/index.ts b/deno-router3/index.ts new file mode 100644 index 0000000..c482a4f --- /dev/null +++ b/deno-router3/index.ts @@ -0,0 +1,59 @@ +// import { App } from "@kevisual/router"; +import { App } from '@kevisual/router/router'; +import path from 'node:path'; +import fs from 'node:fs'; +import http, { Server } from 'node:http'; + +// https://esm.sh/@kevisual/router@0.0.12/dist/router.d.ts +// https://esm.sh/@kevisual/router@0.0.13/dist/router.d.ts +// https​://esm.sh/​@kevisual/router​@0.0.13/dist/router.d.ts +console.log('meta', import.meta.url); +// deno run --allow-all index.ts +// deno run --config ./deno.json --allow-all index.ts +console.log('hello world'); + +const app = new App({ + io: true, +}); + +app + .route({ + path: 'demo', + }) + .define(async (ctx) => { + ctx.body = 'hello world'; + }) + .addTo(app); + +const socketPath = path.resolve('/tmp/http-deno.sock'); +// const socketPath = path.resolve(Deno.cwd(), './http.sock'); +if (fs.existsSync(socketPath)) { + fs.unlinkSync(socketPath); +} +// app.listen(10004, () => { +// console.log('Server is running on http://localhost:10004'); +// }); +// process.umask(0); // 设置默认权限掩码 + +// app.listen(socketPath, () => { +// // console.log('Server is running on. \ncurl --unix-socket ./http-deno.sock http://localhost/api/router?path=demo'); +// console.log('Server is running on. \ncurl --unix-socket /tmp/http-deno.sock http://localhost/api/router?path=demo'); +// console.log(`Actual path: ${fs.realpathSync(socketPath)}`); +// }); + +const sv = app.server.server as Server; +sv.listen(socketPath, () => { + console.log('Server is running on. \ncurl --unix-socket /tmp/http-deno.sock http://localhost/api/router?path=demo'); + console.log(`Actual path: ${fs.realpathSync(socketPath)}`); +}); +app.server.server.on('error', (err) => { + console.error('error', err); +}); + +app.io.addListener('goo', async ({ data, ws, end }) => { + console.log('goo', data); + end({ + code: 200, + message: 'hello world goo', + }); +}); diff --git a/deno-router3/listen.ts b/deno-router3/listen.ts new file mode 100644 index 0000000..7c0a790 --- /dev/null +++ b/deno-router3/listen.ts @@ -0,0 +1,34 @@ +import { createServer } from 'node:http'; +import fs from 'node:fs'; + +const server = createServer((req, res) => { + res.end('Hello World'); +}); + +const socketPath = '/tmp/http-listen.sock'; +if (fs.existsSync(socketPath)) { + fs.unlinkSync(socketPath); +} + +server.listen( + { + path: socketPath, + transport: 'unix', // 指定传输方式为 Unix 套接字 + port: 10004, + }, + () => { + console.log('Server is running on. \ncurl --unix-socket /tmp/http-listen.sock http://localhost/api/router?path=demo'); + throw new Error('test'); + }, +); + +// Deno.serve( +// { +// path: socketPath, +// transport: 'unix', +// }, +// async (req) => { +// console.log(req.url); +// return new Response('Hello World2'); +// }, +// ); diff --git a/deno-router3/types/router.d.ts b/deno-router3/types/router.d.ts new file mode 100644 index 0000000..f032635 --- /dev/null +++ b/deno-router3/types/router.d.ts @@ -0,0 +1,618 @@ +import { Schema } from 'http://esm.xiongxiao.me/zod@3.24.3/index.d.ts'; +export { Schema } from 'http://esm.xiongxiao.me/zod@3.24.3/index.d.ts'; +import http, { IncomingMessage, ServerResponse } from 'node:http'; +import https from 'node:https'; +import http2 from 'node:http2'; +import * as cookie from 'http://esm.xiongxiao.me/cookie@1.0.2/dist/index.d.ts'; +import { WebSocketServer, WebSocket } from 'http://esm.xiongxiao.me/@types/ws@~8.18.1/index.d.mts'; + +type BaseRule = { + value?: any; + required?: boolean; + message?: string; +}; +type RuleString = { + type: 'string'; + minLength?: number; + maxLength?: number; + regex?: string; +} & BaseRule; +type RuleNumber = { + type: 'number'; + min?: number; + max?: number; +} & BaseRule; +type RuleBoolean = { + type: 'boolean'; +} & BaseRule; +type RuleArray = { + type: 'array'; + items: Rule; + minItems?: number; + maxItems?: number; +} & BaseRule; +type RuleObject = { + type: 'object'; + properties: { + [key: string]: Rule; + }; +} & BaseRule; +type RuleAny = { + type: 'any'; +} & BaseRule; +type Rule = RuleString | RuleNumber | RuleBoolean | RuleArray | RuleObject | RuleAny; +declare const createSchema: (rule: Rule) => Schema; + +type RouterContextT = { + code?: number; + [key: string]: any; +}; +type RouteContext = { + query?: { + [key: string]: any; + }; + /** return body */ + body?: number | string | Object; + /** return code */ + code?: number; + /** return msg */ + message?: string; + state?: S; + currentPath?: string; + currentKey?: string; + currentRoute?: Route; + progress?: [[string, string]][]; + nextQuery?: { + [key: string]: any; + }; + end?: boolean; + queryRouter?: QueryRouter; + error?: any; + /** 请求 route的返回结果,包函ctx */ + call?: (message: { + path: string; + key?: string; + payload?: any; + [key: string]: any; + } | { + id: string; + apyload?: any; + [key: string]: any; + }, ctx?: RouteContext & { + [key: string]: any; + }) => Promise; + /** 请求 route的返回结果,不包函ctx */ + queryRoute?: (message: { + path: string; + key?: string; + payload?: any; + }, ctx?: RouteContext & { + [key: string]: any; + }) => Promise; + index?: number; + throw?: (code?: number | string, message?: string, tips?: string) => void; + /** 是否需要序列化 */ + needSerialize?: boolean; +} & T; +type Run = (ctx: RouteContext) => Promise; +type NextRoute = Pick; +type RouteOpts = { + path?: string; + key?: string; + id?: string; + run?: Run; + nextRoute?: NextRoute; + description?: string; + metadata?: { + [key: string]: any; + }; + middleware?: Route[] | string[]; + type?: 'route' | 'middleware'; + /** + * validator: { + * packageName: { + * type: 'string', + * required: true, + * }, + * } + */ + validator?: { + [key: string]: Rule; + }; + schema?: { + [key: string]: Schema; + }; + isVerify?: boolean; + verify?: (ctx?: RouteContext, dev?: boolean) => boolean; + verifyKey?: (key: string, ctx?: RouteContext, dev?: boolean) => boolean; + /** + * $#$ will be used to split path and key + */ + idUsePath?: boolean; + isDebug?: boolean; +}; +type DefineRouteOpts = Omit; +declare const pickValue: readonly ["path", "key", "id", "description", "type", "validator", "middleware"]; +type RouteInfo = Pick; +declare class Route { + /** + * 一级路径 + */ + path?: string; + /** + * 二级路径 + */ + key?: string; + id?: string; + share?: boolean; + run?: Run; + nextRoute?: NextRoute; + description?: string; + metadata?: { + [key: string]: any; + }; + middleware?: (Route | string)[]; + type?: string; + private _validator?; + schema?: { + [key: string]: Schema; + }; + data?: any; + /** + * 是否需要验证 + */ + isVerify?: boolean; + /** + * 是否开启debug,开启后会打印错误信息 + */ + isDebug?: boolean; + constructor(path: string, key?: string, opts?: RouteOpts); + private createSchema; + /** + * set validator and create schema + * @param validator + */ + set validator(validator: { + [key: string]: Rule; + }); + get validator(): { + [key: string]: Rule; + }; + /** + * has code, body, message in ctx, return ctx if has error + * @param ctx + * @param dev + * @returns + */ + verify(ctx: RouteContext, dev?: boolean): void; + /** + * Need to manully call return ctx fn and configure body, code, message + * @param key + * @param ctx + * @param dev + * @returns + */ + verifyKey(key: string, ctx: RouteContext, dev?: boolean): { + message: string; + path: string; + key: string; + error: any; + } | { + message: string; + path: string; + key: string; + error?: undefined; + }; + setValidator(validator: { + [key: string]: Rule; + }): this; + define(opts: DefineRouteOpts): this; + define(fn: Run): this; + define(key: string, fn: Run): this; + define(path: string, key: string, fn: Run): this; + addTo(router: QueryRouter | { + add: (route: Route) => void; + [key: string]: any; + }): void; + setData(data: any): this; + throw(code?: number | string, message?: string, tips?: string): void; +} +declare class QueryRouter { + routes: Route[]; + maxNextRoute: number; + context?: RouteContext; + constructor(); + add(route: Route): void; + /** + * remove route by path and key + * @param route + */ + remove(route: Route | { + path: string; + key?: string; + }): void; + /** + * remove route by id + * @param uniqueId + */ + removeById(unique: string): void; + /** + * 执行route + * @param path + * @param key + * @param ctx + * @returns + */ + runRoute(path: string, key: string, ctx?: RouteContext): any; + /** + * 第一次执行 + * @param message + * @param ctx + * @returns + */ + parse(message: { + path: string; + key?: string; + payload?: any; + }, ctx?: RouteContext & { + [key: string]: any; + }): Promise; + /** + * 返回的数据包含所有的context的请求返回的内容,可做其他处理 + * @param message + * @param ctx + * @returns + */ + call(message: { + id?: string; + path?: string; + key?: string; + payload?: any; + }, ctx?: RouteContext & { + [key: string]: any; + }): Promise; + /** + * 请求 result 的数据 + * @param message + * @param ctx + * @returns + */ + queryRoute(message: { + path: string; + key?: string; + payload?: any; + }, ctx?: RouteContext & { + [key: string]: any; + }): Promise<{ + code: any; + data: any; + message: any; + }>; + setContext(ctx: RouteContext): Promise; + getList(): RouteInfo[]; + getHandle(router: QueryRouter, wrapperFn?: HandleFn, ctx?: RouteContext): (msg: { + path: string; + key?: string; + [key: string]: any; + }, handleContext?: RouteContext) => Promise<{ + [key: string]: any; + code: string; + data?: any; + message?: string; + } | { + code: any; + data: any; + message: any; + } | { + code: number; + message: any; + data?: undefined; + }>; + exportRoutes(): Route<{ + [key: string]: any; + }>[]; + importRoutes(routes: Route[]): void; + importRouter(router: QueryRouter): void; + throw(code?: number | string, message?: string, tips?: string): void; + hasRoute(path: string, key?: string): Route<{ + [key: string]: any; + }>; +} +type QueryRouterServerOpts = { + handleFn?: HandleFn; + context?: RouteContext; +}; +interface HandleFn { + (msg: { + path: string; + [key: string]: any; + }, ctx?: any): { + code: string; + data?: any; + message?: string; + [key: string]: any; + }; + (res: RouteContext): any; +} +/** + * QueryRouterServer + * @description 移除server相关的功能,只保留router相关的功能,和http.createServer不相关,独立 + */ +declare class QueryRouterServer extends QueryRouter { + handle: any; + constructor(opts?: QueryRouterServerOpts); + setHandle(wrapperFn?: HandleFn, ctx?: RouteContext): void; + use(path: string, fn: (ctx: any) => any, opts?: RouteOpts): void; + addRoute(route: Route): void; + Route: typeof Route; + route(opts: RouteOpts): Route>; + route(path: string, key?: string): Route>; + route(path: string, opts?: RouteOpts): Route>; + route(path: string, key?: string, opts?: RouteOpts): Route>; + /** + * 等于queryRoute,但是调用了handle + * @param param0 + * @returns + */ + run({ path, key, payload }: { + path: string; + key?: string; + payload?: any; + }): Promise; +} + +declare class Connect { + path: string; + key?: string; + _fn?: (ctx?: RouteContext) => Promise; + description?: string; + connects: { + path: string; + key?: string; + }[]; + share: boolean; + constructor(path: string); + use(path: string): void; + useList(paths: string[]): void; + useConnect(connect: Connect): void; + useConnectList(connects: Connect[]): void; + getPathList(): string[]; + set fn(fn: (ctx?: RouteContext) => Promise); + get fn(): (ctx?: RouteContext) => Promise; +} +declare class QueryConnect { + connects: Connect[]; + constructor(); + add(connect: Connect): void; + remove(connect: Connect): void; + getList(): { + path: string; + key: string; + }[]; +} + +type Listener = (...args: any[]) => void; +type CookieFn = (name: string, value: string, options?: cookie.SerializeOptions, end?: boolean) => void; +type HandleCtx = { + req: IncomingMessage & { + cookies: Record; + }; + res: ServerResponse & { + /** + * cookie 函数, end 参数用于设置是否立即设置到响应头,设置了后面的cookie再设置会覆盖前面的 + */ + cookie: CookieFn; + }; +}; +type Cors = { + /** + * @default '*'' + */ + origin?: string | undefined; +}; +type ServerOpts = { + /**path default `/api/router` */ + path?: string; + /**handle Fn */ + handle?: (msg?: { + path: string; + key?: string; + [key: string]: any; + }, ctx?: { + req: http.IncomingMessage; + res: http.ServerResponse; + }) => any; + cors?: Cors; + httpType?: 'http' | 'https' | 'http2'; + httpsKey?: string; + httpsCert?: string; +}; +declare class Server { + path: string; + private _server; + handle: ServerOpts['handle']; + private _callback; + private cors; + private hasOn; + private httpType; + private options; + constructor(opts?: ServerOpts); + listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void): void; + listen(port: number, hostname?: string, listeningListener?: () => void): void; + listen(port: number, backlog?: number, listeningListener?: () => void): void; + listen(port: number, listeningListener?: () => void): void; + listen(path: string, backlog?: number, listeningListener?: () => void): void; + listen(path: string, listeningListener?: () => void): void; + listen(handle: any, backlog?: number, listeningListener?: () => void): void; + listen(handle: any, listeningListener?: () => void): void; + createServer(): http.Server | https.Server | http2.Http2SecureServer; + setHandle(handle?: any): void; + /** + * get callback + * @returns + */ + createCallback(): (req: IncomingMessage, res: ServerResponse) => Promise; + get handleServer(): any; + set handleServer(fn: any); + /** + * 兜底监听,当除开 `/api/router` 之外的请求,框架只监听一个api,所以有其他的请求都执行其他的监听 + * @description 主要是为了兼容其他的监听 + * @param listener + */ + on(listener: Listener | Listener[]): void; + get callback(): any; + get server(): http.Server | https.Server | http2.Http2SecureServer; +} + +/** + * get params and body + * 优先原则 + * 1. 请求参数中的 payload 的token 优先 + * 2. 请求头中的 authorization 优先 + * 3. 请求头中的 cookie 优先 + * @param req + * @param res + * @returns + */ +declare const handleServer: (req: IncomingMessage, res: ServerResponse) => Promise<{ + cookies: Record; + token: string; +}>; + +/** 自定义错误 */ +declare class CustomError extends Error { + code?: number; + data?: any; + message: string; + tips?: string; + constructor(code?: number | string, message?: string, tips?: string); + static fromCode(code?: number): CustomError; + static fromErrorData(code?: number, data?: any): CustomError; + static parseError(e: CustomError): { + code: number; + data: any; + message: string; + tips: string; + }; + parse(e?: CustomError): { + code: number; + data: any; + message: string; + tips: string; + }; +} + +type WsServerBaseOpts = { + wss?: WebSocketServer; + path?: string; +}; +type ListenerFn = (message: { + data: Record; + ws: WebSocket; + end: (data: any) => any; +}) => Promise; +declare class WsServerBase { + wss: WebSocketServer; + path: string; + listeners: { + type: string; + listener: ListenerFn; + }[]; + listening: boolean; + constructor(opts: WsServerBaseOpts); + setPath(path: string): void; + listen(): void; + addListener(type: string, listener: ListenerFn): void; + removeListener(type: string): void; +} +declare class WsServer extends WsServerBase { + server: Server; + constructor(server: Server, opts?: any); + initListener(): void; + listen(): void; +} + +type RouterHandle = (msg: { + path: string; + [key: string]: any; +}) => { + code: string; + data?: any; + message?: string; + [key: string]: any; +}; +type AppOptions = { + router?: QueryRouter; + server?: Server; + /** handle msg 关联 */ + routerHandle?: RouterHandle; + routerContext?: RouteContext; + serverOptions?: ServerOpts; + io?: boolean; + ioOpts?: { + routerHandle?: RouterHandle; + routerContext?: RouteContext; + path?: string; + }; +}; +type AppReqRes = HandleCtx; +/** + * 封装了 Router 和 Server 的 App 模块,处理http的请求和响应,内置了 Cookie 和 Token 和 res 的处理 + */ +declare class App { + router: QueryRouter; + server: Server; + io: WsServer; + constructor(opts?: AppOptions); + listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void): void; + listen(port: number, hostname?: string, listeningListener?: () => void): void; + listen(port: number, backlog?: number, listeningListener?: () => void): void; + listen(port: number, listeningListener?: () => void): void; + listen(path: string, backlog?: number, listeningListener?: () => void): void; + listen(path: string, listeningListener?: () => void): void; + listen(handle: any, backlog?: number, listeningListener?: () => void): void; + listen(handle: any, listeningListener?: () => void): void; + use(path: string, fn: (ctx: any) => any, opts?: RouteOpts): void; + addRoute(route: Route): void; + add: (route: Route) => void; + Route: typeof Route; + route(opts: RouteOpts): Route; + route(path: string, key?: string): Route; + route(path: string, opts?: RouteOpts): Route; + route(path: string, key?: string, opts?: RouteOpts): Route; + call(message: { + path: string; + key?: string; + payload?: any; + }, ctx?: RouteContext & { + [key: string]: any; + }): Promise; + queryRoute(path: string, key?: string, payload?: any, ctx?: RouteContext & { + [key: string]: any; + }): Promise<{ + code: any; + data: any; + message: any; + }>; + exportRoutes(): Route<{ + [key: string]: any; + }>[]; + importRoutes(routes: any[]): void; + importApp(app: App): void; + throw(code?: number | string, message?: string, tips?: string): void; +} + +export { App, Connect, CustomError, QueryConnect, QueryRouter, QueryRouterServer, Route, Server, createSchema, handleServer }; +export type { RouteContext, RouteOpts, Rule, Run }; diff --git a/deno-server/server.ts b/deno-server/server.ts new file mode 100644 index 0000000..376ae51 --- /dev/null +++ b/deno-server/server.ts @@ -0,0 +1,5 @@ +const server = Deno.serve(async (req) => { + return new Response('Hello, World!'); +}); + +console.log(server); diff --git a/deno-server/ws-server.ts b/deno-server/ws-server.ts new file mode 100644 index 0000000..390fa64 --- /dev/null +++ b/deno-server/ws-server.ts @@ -0,0 +1,30 @@ +// 创建 HTTP 服务器 +const server = Deno.serve({ port: 8080 }, (req) => { + if (req.headers.get('upgrade') === 'websocket') { + const { socket, response } = Deno.upgradeWebSocket(req); + socket.addEventListener('open', () => { + console.log('a client connected!'); + }); + socket.addEventListener('message', (event) => { + if (event.data === 'ping') { + socket.send('pong'); + } + }); + return response; + } + return new Response('HTTP server running', { + status: 200, + }); +}); + +// 注释掉有问题的代码,使用上面的 Deno.serve API +// const server2 = Deno.listen({ port: 8080 }); +// +// for await (const conn of server2) { +// const httpConn = Deno.serveHttp(conn); +// for await (const requestEvent of httpConn) { +// console.log(requestEvent); +// } +// } + +console.log('WebSocket server running on http://localhost:8080'); diff --git a/deno.json b/deno.json new file mode 100644 index 0000000..1ac4fa9 --- /dev/null +++ b/deno.json @@ -0,0 +1,33 @@ +{ + "compilerOptions": { + "lib": [ + "deno.window" + ] + }, + "tasks": { + "start": "deno run --allow-net deno-server/server.ts" + }, + "imports": { + "http/": "https://deno.land/std@0.220.1/http/" + }, + "lint": { + "include": [ + "./src/**/*.ts", + "index.ts" + ], + "exclude": [ + "./types" + ], + "rules": { + "tags": [ + "recommended" + ], + "include": [], + "exclude": [ + "require-await", + "no-explicit-any", + "unused-vars" + ] + } + } +} \ No newline at end of file diff --git a/deno.lock b/deno.lock new file mode 100644 index 0000000..f172662 --- /dev/null +++ b/deno.lock @@ -0,0 +1,44 @@ +{ + "version": "4", + "remote": { + "https://deno.land/std@0.200.0/async/delay.ts": "a6142eb44cdd856b645086af2b811b1fcce08ec06bb7d50969e6a872ee9b8659", + "https://deno.land/std@0.200.0/http/server.ts": "1b2403b3c544c0624ad23e8ca4e05877e65380d9e0d75d04957432d65c3d5f41", + "https://deno.land/std@0.92.0/_util/assert.ts": "2f868145a042a11d5ad0a3c748dcf580add8a0dbc0e876eaa0026303a5488f58", + "https://deno.land/std@0.92.0/_util/has_own_property.ts": "f5edd94ed3f3c20c517d812045deb97977e18501c9b7105b5f5c11a31893d7a2", + "https://deno.land/std@0.92.0/async/deferred.ts": "624bef4b755b71394620508a0c234a93cb8020cbd1b04bfcdad41c174392cef6", + "https://deno.land/std@0.92.0/async/delay.ts": "9de1d8d07d1927767ab7f82434b883f3d8294fb19cad819691a2ad81a728cf3d", + "https://deno.land/std@0.92.0/async/mod.ts": "253b41c658d768613eacfb11caa0a9ca7148442f932018a45576f7f27554c853", + "https://deno.land/std@0.92.0/async/mux_async_iterator.ts": "b9091909db04cdb0af6f7807677372f64c1488de6c4bd86004511b064bf230d6", + "https://deno.land/std@0.92.0/async/pool.ts": "876f9e6815366cd017a3b4fbb9e9ae40310b1b6972f1bd541c94358bc11fb7e5", + "https://deno.land/std@0.92.0/bytes/mod.ts": "1ae1ccfe98c4b979f12b015982c7444f81fcb921bea7aa215bf37d84f46e1e13", + "https://deno.land/std@0.92.0/fmt/colors.ts": "db22b314a2ae9430ae7460ce005e0a7130e23ae1c999157e3bb77cf55800f7e4", + "https://deno.land/std@0.92.0/hash/sha1.ts": "1cca324b4b253885a47f121adafcfac55b4cc96113e22b338e1db26f37a730b8", + "https://deno.land/std@0.92.0/http/_io.ts": "bf1331dd3be8aace9120614c1fedc2bb2449edc4779e31b74c0181ea9173f702", + "https://deno.land/std@0.92.0/http/http_status.ts": "ebaa9bebfb8adc3d7b20c49e11037e4eefd79629ad80d81383933f4cdc91b3eb", + "https://deno.land/std@0.92.0/http/server.ts": "d4e17c2aa5a5c65a2d19b9f24483be5f6c2a3e03665996fdf973e53c43091b48", + "https://deno.land/std@0.92.0/io/buffer.ts": "2a92f02c1d8daaebaf13e5678ea5969c89f4fab533f687b9e7e86f49f11c3118", + "https://deno.land/std@0.92.0/io/bufio.ts": "4053ea5d978479be68ae4d73424045a59c6b7a6e8f66727e4bfde516baa07126", + "https://deno.land/std@0.92.0/io/ioutil.ts": "275fa440494df9b4b3aa656301ced2eeac533feec128b3a39b2b40f4cd957e42", + "https://deno.land/std@0.92.0/io/util.ts": "03ca10e063afce551c501505c607ec336a40b9cb72363f5508e2a9ac81096bbf", + "https://deno.land/std@0.92.0/node/_utils.ts": "33b06f2877d3ee80f17190ee81fdc436755ce74b9c2a9a4492c7cdfe2a03e4c6", + "https://deno.land/std@0.92.0/node/events.ts": "0feda0707e2229363f5df8b799fed41bb91de6ca7106f27c7a9f0a02ea11b9d4", + "https://deno.land/std@0.92.0/testing/_diff.ts": "961eaf6d9f5b0a8556c9d835bbc6fa74f5addd7d3b02728ba7936ff93364f7a3", + "https://deno.land/std@0.92.0/testing/asserts.ts": "83889f9a37bdab16cb68b023a15f9172ceb644f62c0e727c72d4870a666e53d6", + "https://deno.land/std@0.92.0/textproto/mod.ts": "1c89b39a079dd158893ab2e9ff79391c66049433d6ca82da7d64b32280570d51", + "https://deno.land/std@0.92.0/ws/mod.ts": "bc521b3066441eb115ac94e3507bcc73098542f81d8d3ce7aad8d837316ce990", + "https://deno.land/x/websocket@v0.1.4/deps.ts": "1299887e27e09209d2eedc5c3b6552090842fac9e08f00dd235de39219efbd42", + "https://deno.land/x/websocket@v0.1.4/lib/errors.ts": "efb2251dac1ac2036809b0bfb520d737aee70e362eba1e287c84d5299fb211e8", + "https://deno.land/x/websocket@v0.1.4/lib/websocket.ts": "3363e0a8f59284de5439f5f3bd8831b65a2cfba047113fbc72e32934ebec3208", + "https://deno.land/x/websocket@v0.1.4/mod.ts": "6b24e14dd1c5d64c1671dd678ca545cce9e2ebc91f67e8be864069808b948267" + }, + "workspace": { + "packageJson": { + "dependencies": [ + "npm:@kevisual/router@^0.0.10", + "npm:@kevisual/use-config@^1.0.10", + "npm:pino-pretty@13", + "npm:pino@^9.6.0" + ] + } + } +} diff --git a/package.json b/package.json index bb826e5..35f0ab2 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "packageManager": "pnpm@10.6.2", "type": "module", "devDependencies": { - "@kevisual/router": "^0.0.10", + "@kevisual/router": "^0.0.13", "@kevisual/use-config": "^1.0.10", "pino": "^9.6.0", "pino-pretty": "^13.0.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 93316a2..04d4939 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: devDependencies: '@kevisual/router': - specifier: ^0.0.10 - version: 0.0.10 + specifier: ^0.0.13 + version: 0.0.13 '@kevisual/use-config': specifier: ^1.0.10 version: 1.0.10(dotenv@16.5.0) @@ -26,8 +26,8 @@ packages: '@kevisual/load@0.0.4': resolution: {integrity: sha512-TJBieKsEoEPfP4+tDyhNZdMX2LMAGiDZ/IrAXPFWB4jeFP0Ywm1W5xDV52LhhHq4nwTmuhyTVmPxJYiEVYTHtA==} - '@kevisual/router@0.0.10': - resolution: {integrity: sha512-prQGiMIboQhDNN1Eubp8x7YDyRCmAsUqpHQwzfu9f7WvgisVWSLOWSaLbqjqNssV2xcc1DgVrHIKdLhbx8HCqQ==} + '@kevisual/router@0.0.13': + resolution: {integrity: sha512-raji8aKXr0jigmJVOKBXb5gpstiAuyoIDy9m6SyPf4lRjCU3pspVI1bpscOUCBlaPICo6TLzPQxXhyTvvvtdWw==} '@kevisual/use-config@1.0.10': resolution: {integrity: sha512-fH2B4BnR4+OjR3PzAegF8H9RJpyFZu6BnVDyfvSSZavZMurufkJ949jizoRde+bNAHff/PRcpa5EZg2imZNf1g==} @@ -153,32 +153,16 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - ws@8.18.1: - resolution: {integrity: sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - snapshots: '@kevisual/load@0.0.4': dependencies: eventemitter3: 5.0.1 - '@kevisual/router@0.0.10': + '@kevisual/router@0.0.13': dependencies: path-to-regexp: 8.2.0 selfsigned: 2.4.1 - ws: 8.18.1 - transitivePeerDependencies: - - bufferutil - - utf-8-validate '@kevisual/use-config@1.0.10(dotenv@16.5.0)': dependencies: @@ -300,5 +284,3 @@ snapshots: undici-types@6.21.0: {} wrappy@1.0.2: {} - - ws@8.18.1: {}