diff --git a/package.json b/package.json index f2f7876..cebee79 100644 --- a/package.json +++ b/package.json @@ -12,13 +12,16 @@ "keywords": [], "author": "abearxiong (https://www.xiongxiao.me)", "license": "MIT", - "packageManager": "pnpm@10.19.0", + "packageManager": "pnpm@10.28.2", "type": "module", "dependencies": { - "@kevisual/noco": "^0.0.1", - "@kevisual/router": "^0.0.30" + "@kevisual/noco": "^0.0.10", + "@kevisual/router": "^0.0.70", + "ws": "npm:@kevisual/ws" }, "devDependencies": { - "@types/node": "^24.10.0" + "@types/bun": "^1.3.8", + "@types/node": "^25.2.0", + "@types/ws": "^8.18.1" } } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 55cf77a..1e66c50 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,203 +9,81 @@ importers: .: dependencies: '@kevisual/noco': - specifier: ^0.0.1 - version: 0.0.1 + specifier: ^0.0.10 + version: 0.0.10 '@kevisual/router': - specifier: ^0.0.30 - version: 0.0.30 + specifier: ^0.0.70 + version: 0.0.70 + ws: + specifier: npm:@kevisual/ws + version: '@kevisual/ws@8.19.0' devDependencies: + '@types/bun': + specifier: ^1.3.8 + version: 1.3.8 '@types/node': - specifier: ^24.10.0 - version: 24.10.0 + specifier: ^25.2.0 + version: 25.2.0 + '@types/ws': + specifier: ^8.18.1 + version: 8.18.1 packages: - '@kevisual/noco@0.0.1': - resolution: {integrity: sha512-N0wYcxasxXe3S6jQtD5SSUwOOmaPaL+9S9Qe+iwA2oXYNUmheNXgz2vQJUmKa3SZHgOrwsKMMe3ZhAHftJizQg==, tarball: https://registry.npmjs.org/@kevisual/noco/-/noco-0.0.1.tgz} + '@kevisual/noco@0.0.10': + resolution: {integrity: sha512-VFdjFiRpTOnuedD+WHxxV1YOvzGHU3oS+C8pU3HRXCwpcd+8rYEpH7EEUF1mMfC1oPCOPwnr67Dailc3CY0QKg==} - '@kevisual/router@0.0.30': - resolution: {integrity: sha512-/mBo7aZFWjT4QfHkI5HPXfdgSwZzt3mAVei7dcNSBTPe9KQSoYKZ8BTq9VTUj3XE0sI6o1bZjlLYvinpVnZilw==} + '@kevisual/router@0.0.70': + resolution: {integrity: sha512-vXlIj9jRufhcIfeuPWemjSI+dxdzSmIBq5eRxQzqEfAJ7k+mBPhoI4KxH8vHnwyL30bqm8EdODL/p6Wg8uBw3g==} - '@types/node@24.10.0': - resolution: {integrity: sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==} + '@kevisual/ws@8.19.0': + resolution: {integrity: sha512-jLsL80wBBKkrJZrfk3SQpJ9JA/zREdlUROj7eCkmzqduAWKSI0wVcXuCKf+mLFCHB0Q0Tkh2rgzjSlurt3JQgw==} + engines: {node: '>=10.0.0'} - debug@4.4.3: - resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true + '@types/bun@1.3.8': + resolution: {integrity: sha512-3LvWJ2q5GerAXYxO2mffLTqOzEu5qnhEAlh48Vnu8WQfnmSwbgagjGZV6BoHKJztENYEDn6QmVd949W4uESRJA==} - depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} + '@types/node@25.2.0': + resolution: {integrity: sha512-DZ8VwRFUNzuqJ5khrvwMXHmvPe+zGayJhr2CDNiKB1WBE1ST8Djl00D0IC4vvNmHMdj6DlbYRIaFE7WHjlDl5w==} - ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} - encodeurl@2.0.0: - resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} - engines: {node: '>= 0.8'} + bun-types@1.3.8: + resolution: {integrity: sha512-fL99nxdOWvV4LqjmC+8Q9kW3M4QTtTR1eePs94v5ctGqU8OeceWrSUaRw3JYb7tU3FkMIAjkueehrHPPPGKi5Q==} - escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - - etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - - fresh@2.0.0: - resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} - engines: {node: '>= 0.8'} - - http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - mime-db@1.54.0: - resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} - engines: {node: '>= 0.6'} - - mime-types@3.0.1: - resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==} - engines: {node: '>= 0.6'} - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - node-forge@1.3.1: - resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} - engines: {node: '>= 6.13.0'} - - on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} - - path-to-regexp@8.3.0: - resolution: {integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==} - - range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - - selfsigned@3.0.1: - resolution: {integrity: sha512-6U6w6kSLrM9Zxo0D7mC7QdGS6ZZytMWBnj/vhF9p+dAHx6CwGezuRcO4VclTbrrI7mg7SD6zNiqXUuBHOVopNQ==} - engines: {node: '>=10'} - - send@1.2.0: - resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==} - engines: {node: '>= 18'} - - setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - - statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - - statuses@2.0.2: - resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} - engines: {node: '>= 0.8'} - - toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} + es-toolkit@1.44.0: + resolution: {integrity: sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==} undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} snapshots: - '@kevisual/noco@0.0.1': {} + '@kevisual/noco@0.0.10': {} - '@kevisual/router@0.0.30': + '@kevisual/router@0.0.70': dependencies: - path-to-regexp: 8.3.0 - selfsigned: 3.0.1 - send: 1.2.0 - transitivePeerDependencies: - - supports-color + es-toolkit: 1.44.0 - '@types/node@24.10.0': + '@kevisual/ws@8.19.0': {} + + '@types/bun@1.3.8': + dependencies: + bun-types: 1.3.8 + + '@types/node@25.2.0': dependencies: undici-types: 7.16.0 - debug@4.4.3: + '@types/ws@8.18.1': dependencies: - ms: 2.1.3 + '@types/node': 25.2.0 - depd@2.0.0: {} - - ee-first@1.1.1: {} - - encodeurl@2.0.0: {} - - escape-html@1.0.3: {} - - etag@1.8.1: {} - - fresh@2.0.0: {} - - http-errors@2.0.0: + bun-types@1.3.8: dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 + '@types/node': 25.2.0 - inherits@2.0.4: {} - - mime-db@1.54.0: {} - - mime-types@3.0.1: - dependencies: - mime-db: 1.54.0 - - ms@2.1.3: {} - - node-forge@1.3.1: {} - - on-finished@2.4.1: - dependencies: - ee-first: 1.1.1 - - path-to-regexp@8.3.0: {} - - range-parser@1.2.1: {} - - selfsigned@3.0.1: - dependencies: - node-forge: 1.3.1 - - send@1.2.0: - dependencies: - debug: 4.4.3 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 2.0.0 - http-errors: 2.0.0 - mime-types: 3.0.1 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.2 - transitivePeerDependencies: - - supports-color - - setprototypeof@1.2.0: {} - - statuses@2.0.1: {} - - statuses@2.0.2: {} - - toidentifier@1.0.1: {} + es-toolkit@1.44.0: {} undici-types@7.16.0: {} diff --git a/demo-origin.ts b/src/2025-10/demo-origin.ts similarity index 100% rename from demo-origin.ts rename to src/2025-10/demo-origin.ts diff --git a/demo-router.ts b/src/2025-10/demo-router.ts similarity index 100% rename from demo-router.ts rename to src/2025-10/demo-router.ts diff --git a/main.ts b/src/2025-10/main.ts similarity index 100% rename from main.ts rename to src/2025-10/main.ts diff --git a/sign.ts b/src/2025-10/sign.ts similarity index 100% rename from sign.ts rename to src/2025-10/sign.ts diff --git a/weather.ts b/src/2025-10/weather.ts similarity index 100% rename from weather.ts rename to src/2025-10/weather.ts diff --git a/src/ws.ts b/src/ws.ts new file mode 100644 index 0000000..737d305 --- /dev/null +++ b/src/ws.ts @@ -0,0 +1,76 @@ + +import { App, ListenProcessResponse } from '@kevisual/router' +import { ReconnectingWebSocket } from '@kevisual/router/ws' + +const app = new App(); + +app.route({ + path: 'livecode-status', + description: 'LiveCode 状态路由', + metadata: { + tags: ['livecode', 'status'], + }, +}).define(async (ctx) => { + ctx.body = { + status: 'LiveCode 模块运行正常', + timestamp: new Date().toISOString(), + }; +}).addTo(app) + +app.createRouteList(); +await new Promise((resolve) => setTimeout(resolve, 1000)); + +// 创建支持断开重连的 WebSocket 客户端 +const ws = new ReconnectingWebSocket('ws://localhost:51515/livecode/ws?id=test-live-app', { + maxRetries: Infinity, // 无限重试 + retryDelay: 1000, // 初始重试延迟 1 秒 + maxDelay: 30000, // 最大延迟 30 秒 + backoffMultiplier: 2, // 指数退避倍数 +}); +ws.onMessage(async (message) => { + console.log('收到消息:', message); + if (message.type === 'router' && message.id) { + console.log('收到路由响应:', message); + const data = message?.data as ListenProcessResponse; + if (!data) { + ws.send({ + type: 'router', + id: message.id, + data: { code: 500, message: 'No data received' } + }); + return; + } + const msg = data.message; + if (!msg) { + ws.send({ + type: 'router', + id: message.id, + data: { code: 500, message: 'No {message} received' } + }); + return; + } + const context = data.context || {}; + const res = await app.run(msg, context); + console.log('路由处理结果:', res); + ws.send({ + type: 'router', + id: message.id, + data: res + }); + } +}); + +ws.onOpen(() => { + console.log('连接已建立,可以开始通信'); +}); + +ws.onError((error) => { + console.error('连接错误:', error.message); +}); + +ws.onClose((code, reason) => { + console.log(`连接关闭: ${code} - ${reason.toString()}`); +}); + +// 启动连接 +ws.connect();