From 1e340ec2b35ff97e5d6c1572cb0fcbfc48b53130 Mon Sep 17 00:00:00 2001 From: xion Date: Thu, 22 May 2025 13:19:57 +0800 Subject: [PATCH] =?UTF-8?q?"feat:=20=E6=96=B0=E5=A2=9E=E8=BF=9C=E7=A8=8B?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E6=B5=8B=E8=AF=95=E8=84=9A=E6=9C=AC=EF=BC=8C?= =?UTF-8?q?=E5=8D=87=E7=BA=A7=20pm2=20=E4=BE=9D=E8=B5=96"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assistant/package.json | 2 + assistant/pnpm-lock.yaml | 416 +++++++----------- .../src/module/assistant/config/index.ts | 8 + .../module/assistant/remote-app/remote-app.ts | 138 ++++++ assistant/src/routes/index.ts | 29 ++ assistant/src/services/proxy/local-proxy.ts | 44 +- assistant/src/test/common.ts | 17 + assistant/src/test/remote-app.ts | 20 + 8 files changed, 415 insertions(+), 259 deletions(-) create mode 100644 assistant/src/module/assistant/remote-app/remote-app.ts create mode 100644 assistant/src/test/common.ts create mode 100644 assistant/src/test/remote-app.ts diff --git a/assistant/package.json b/assistant/package.json index 81c2a70..8941f99 100644 --- a/assistant/package.json +++ b/assistant/package.json @@ -21,6 +21,7 @@ "scripts": { "dev": "bun run src/run.ts ", "dev:server": "cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 bun --watch src/run-server.ts ", + "dev:share": "bun --watch src/test/remote-app.ts ", "build:lib": "bun run bun-lib.config.mjs", "postbuild:lib": "dts -i src/lib.ts -o assistant-lib.d.ts -d libs -t", "build": "rimraf dist && bun run bun.config.mjs", @@ -75,6 +76,7 @@ "access": "public" }, "dependencies": { + "eventemitter3": "^5.0.1", "pm2": "^6.0.6" } } \ No newline at end of file diff --git a/assistant/pnpm-lock.yaml b/assistant/pnpm-lock.yaml index 027e454..6599009 100644 --- a/assistant/pnpm-lock.yaml +++ b/assistant/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + eventemitter3: + specifier: ^5.0.1 + version: 5.0.1 pm2: specifier: ^6.0.6 version: 6.0.6(supports-color@10.0.0) @@ -98,7 +101,7 @@ importers: dependencies: pm2: specifier: ^6.0.5 - version: 6.0.5(supports-color@10.0.0) + version: 6.0.6 devDependencies: '@kevisual/assistant-cli': specifier: workspace:* @@ -123,7 +126,7 @@ importers: version: 16.5.0 inquirer: specifier: ^12.6.0 - version: 12.6.0(@types/node@22.15.18) + version: 12.6.1(@types/node@22.15.18) lodash-es: specifier: ^4.17.21 version: 4.17.21 @@ -141,15 +144,6 @@ packages: resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} - '@inquirer/checkbox@4.1.5': - resolution: {integrity: sha512-swPczVU+at65xa5uPfNP9u3qx/alNwiaykiI/ExpsmMSQW55trmZcwhYWzw/7fj+n6Q8z1eENvR7vFfq9oPSAQ==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/checkbox@4.1.6': resolution: {integrity: sha512-62u896rWCtKKE43soodq5e/QcRsA22I+7/4Ov7LESWnKRO6BVo2A1DFLDmXL9e28TB0CfHc3YtkbPm7iwajqkg==} engines: {node: '>=18'} @@ -168,24 +162,6 @@ packages: '@types/node': optional: true - '@inquirer/confirm@5.1.9': - resolution: {integrity: sha512-NgQCnHqFTjF7Ys2fsqK2WtnA8X1kHyInyG+nMIuHowVTIgIuS10T4AznI/PvbqSpJqjCUqNBlKGh1v3bwLFL4w==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - - '@inquirer/core@10.1.10': - resolution: {integrity: sha512-roDaKeY1PYY0aCqhRmXihrHjoSW2A00pV3Ke5fTpMCkzcGF64R8e0lw3dK+eLEHwS4vB5RnW1wuQmvzoRul8Mw==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/core@10.1.11': resolution: {integrity: sha512-BXwI/MCqdtAhzNQlBEFE7CEflhPkl/BqvAuV/aK6lW3DClIfYVDWPP/kXuXHtBWC7/EEbNqd/1BGq2BGBBnuxw==} engines: {node: '>=18'} @@ -195,15 +171,6 @@ packages: '@types/node': optional: true - '@inquirer/editor@4.2.10': - resolution: {integrity: sha512-5GVWJ+qeI6BzR6TIInLP9SXhWCEcvgFQYmcRG6d6RIlhFjM5TyG18paTGBgRYyEouvCmzeco47x9zX9tQEofkw==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/editor@4.2.11': resolution: {integrity: sha512-YoZr0lBnnLFPpfPSNsQ8IZyKxU47zPyVi9NLjCWtna52//M/xuL0PGPAxHxxYhdOhnvY2oBafoM+BI5w/JK7jw==} engines: {node: '>=18'} @@ -213,15 +180,6 @@ packages: '@types/node': optional: true - '@inquirer/expand@4.0.12': - resolution: {integrity: sha512-jV8QoZE1fC0vPe6TnsOfig+qwu7Iza1pkXoUJ3SroRagrt2hxiL+RbM432YAihNR7m7XnU0HWl/WQ35RIGmXHw==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/expand@4.0.13': resolution: {integrity: sha512-HgYNWuZLHX6q5y4hqKhwyytqAghmx35xikOGY3TcgNiElqXGPas24+UzNPOwGUZa5Dn32y25xJqVeUcGlTv+QQ==} engines: {node: '>=18'} @@ -244,24 +202,6 @@ packages: '@types/node': optional: true - '@inquirer/input@4.1.9': - resolution: {integrity: sha512-mshNG24Ij5KqsQtOZMgj5TwEjIf+F2HOESk6bjMwGWgcH5UBe8UoljwzNFHqdMbGYbgAf6v2wU/X9CAdKJzgOA==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - - '@inquirer/number@3.0.12': - resolution: {integrity: sha512-7HRFHxbPCA4e4jMxTQglHJwP+v/kpFsCf2szzfBHy98Wlc3L08HL76UDiA87TOdX5fwj2HMOLWqRWv9Pnn+Z5Q==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/number@3.0.13': resolution: {integrity: sha512-IrLezcg/GWKS8zpKDvnJ/YTflNJdG0qSFlUM/zNFsdi4UKW/CO+gaJpbMgQ20Q58vNKDJbEzC6IebdkprwL6ew==} engines: {node: '>=18'} @@ -271,15 +211,6 @@ packages: '@types/node': optional: true - '@inquirer/password@4.0.12': - resolution: {integrity: sha512-FlOB0zvuELPEbnBYiPaOdJIaDzb2PmJ7ghi/SVwIHDDSQ2K4opGBkF+5kXOg6ucrtSUQdLhVVY5tycH0j0l+0g==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/password@4.0.13': resolution: {integrity: sha512-NN0S/SmdhakqOTJhDwOpeBEEr8VdcYsjmZHDb0rblSh2FcbXQOr+2IApP7JG4WE3sxIdKytDn4ed3XYwtHxmJQ==} engines: {node: '>=18'} @@ -289,15 +220,6 @@ packages: '@types/node': optional: true - '@inquirer/prompts@7.5.0': - resolution: {integrity: sha512-tk8Bx7l5AX/CR0sVfGj3Xg6v7cYlFBkEahH+EgBB+cZib6Fc83dwerTbzj7f2+qKckjIUGsviWRI1d7lx6nqQA==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/prompts@7.5.1': resolution: {integrity: sha512-5AOrZPf2/GxZ+SDRZ5WFplCA2TAQgK3OYrXCYmJL5NaTu4ECcoWFlfUZuw7Es++6Njv7iu/8vpYJhuzxUH76Vg==} engines: {node: '>=18'} @@ -307,15 +229,6 @@ packages: '@types/node': optional: true - '@inquirer/rawlist@4.1.0': - resolution: {integrity: sha512-6ob45Oh9pXmfprKqUiEeMz/tjtVTFQTgDDz1xAMKMrIvyrYjAmRbQZjMJfsictlL4phgjLhdLu27IkHNnNjB7g==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/rawlist@4.1.1': resolution: {integrity: sha512-VBUC0jPN2oaOq8+krwpo/mf3n/UryDUkKog3zi+oIi8/e5hykvdntgHUB9nhDM78RubiyR1ldIOfm5ue+2DeaQ==} engines: {node: '>=18'} @@ -325,15 +238,6 @@ packages: '@types/node': optional: true - '@inquirer/search@3.0.12': - resolution: {integrity: sha512-H/kDJA3kNlnNIjB8YsaXoQI0Qccgf0Na14K1h8ExWhNmUg2E941dyFPrZeugihEa9AZNW5NdsD/NcvUME83OPQ==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/search@3.0.13': resolution: {integrity: sha512-9g89d2c5Izok/Gw/U7KPC3f9kfe5rA1AJ24xxNZG0st+vWekSk7tB9oE+dJv5JXd0ZSijomvW0KPMoBd8qbN4g==} engines: {node: '>=18'} @@ -343,15 +247,6 @@ packages: '@types/node': optional: true - '@inquirer/select@4.2.0': - resolution: {integrity: sha512-KkXQ4aSySWimpV4V/TUJWdB3tdfENZUU765GjOIZ0uPwdbGIG6jrxD4dDf1w68uP+DVtfNhr1A92B+0mbTZ8FA==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/select@4.2.1': resolution: {integrity: sha512-gt1Kd5XZm+/ddemcT3m23IP8aD8rC9drRckWoP/1f7OL46Yy2FGi8DSmNjEjQKtPl6SV96Kmjbl6p713KXJ/Jg==} engines: {node: '>=18'} @@ -1033,15 +928,6 @@ packages: ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - inquirer@12.6.0: - resolution: {integrity: sha512-3zmmccQd/8o65nPOZJZ+2wqt76Ghw3+LaMrmc6JE/IzcvQhJ1st+QLCOo/iLS85/tILU0myG31a2TAZX0ysAvg==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - inquirer@12.6.1: resolution: {integrity: sha512-MGFnzHVS3l3oM3cy+LWkyR7UUtVEn3D5U41CZbEY34szToWoJAvaVtCTz1mxsEzZFk/HXWyCArn0HDgloTXMDw==} engines: {node: '>=18'} @@ -1273,11 +1159,6 @@ packages: pm2-sysmonit@1.2.8: resolution: {integrity: sha512-ACOhlONEXdCTVwKieBIQLSi2tQZ8eKinhcr9JpZSUAL8Qy0ajIgRtsLxG/lwPOW3JEKqPyw/UaHmTWhUzpP4kA==} - pm2@6.0.5: - resolution: {integrity: sha512-+O43WPaEiwYbm6/XSpAOO1Rtya/Uof0n7x8hJZGfwIuepesNTIVArpZh4KqFfze0cvvqZMr0maTW3ifhvmyeMQ==} - engines: {node: '>=16.0.0'} - hasBin: true - pm2@6.0.6: resolution: {integrity: sha512-6t+I+Gc232dKe0OjwFYlU59JoY8MWBqsBmcZMSfKollByL4q8APUFwWOt7OtPH4lGO4Sb6GiFAqu7xT42QeRBA==} engines: {node: '>=16.0.0'} @@ -1536,16 +1417,6 @@ snapshots: '@babel/helper-validator-identifier@7.25.9': optional: true - '@inquirer/checkbox@4.1.5(@types/node@22.15.18)': - dependencies: - '@inquirer/core': 10.1.10(@types/node@22.15.18) - '@inquirer/figures': 1.0.11 - '@inquirer/type': 3.0.6(@types/node@22.15.18) - ansi-escapes: 4.3.2 - yoctocolors-cjs: 2.1.2 - optionalDependencies: - '@types/node': 22.15.18 - '@inquirer/checkbox@4.1.6(@types/node@22.15.18)': dependencies: '@inquirer/core': 10.1.11(@types/node@22.15.18) @@ -1563,26 +1434,6 @@ snapshots: optionalDependencies: '@types/node': 22.15.18 - '@inquirer/confirm@5.1.9(@types/node@22.15.18)': - dependencies: - '@inquirer/core': 10.1.10(@types/node@22.15.18) - '@inquirer/type': 3.0.6(@types/node@22.15.18) - optionalDependencies: - '@types/node': 22.15.18 - - '@inquirer/core@10.1.10(@types/node@22.15.18)': - dependencies: - '@inquirer/figures': 1.0.11 - '@inquirer/type': 3.0.6(@types/node@22.15.18) - ansi-escapes: 4.3.2 - cli-width: 4.1.0 - mute-stream: 2.0.0 - signal-exit: 4.1.0 - wrap-ansi: 6.2.0 - yoctocolors-cjs: 2.1.2 - optionalDependencies: - '@types/node': 22.15.18 - '@inquirer/core@10.1.11(@types/node@22.15.18)': dependencies: '@inquirer/figures': 1.0.11 @@ -1596,14 +1447,6 @@ snapshots: optionalDependencies: '@types/node': 22.15.18 - '@inquirer/editor@4.2.10(@types/node@22.15.18)': - dependencies: - '@inquirer/core': 10.1.10(@types/node@22.15.18) - '@inquirer/type': 3.0.6(@types/node@22.15.18) - external-editor: 3.1.0 - optionalDependencies: - '@types/node': 22.15.18 - '@inquirer/editor@4.2.11(@types/node@22.15.18)': dependencies: '@inquirer/core': 10.1.11(@types/node@22.15.18) @@ -1612,14 +1455,6 @@ snapshots: optionalDependencies: '@types/node': 22.15.18 - '@inquirer/expand@4.0.12(@types/node@22.15.18)': - dependencies: - '@inquirer/core': 10.1.10(@types/node@22.15.18) - '@inquirer/type': 3.0.6(@types/node@22.15.18) - yoctocolors-cjs: 2.1.2 - optionalDependencies: - '@types/node': 22.15.18 - '@inquirer/expand@4.0.13(@types/node@22.15.18)': dependencies: '@inquirer/core': 10.1.11(@types/node@22.15.18) @@ -1637,20 +1472,6 @@ snapshots: optionalDependencies: '@types/node': 22.15.18 - '@inquirer/input@4.1.9(@types/node@22.15.18)': - dependencies: - '@inquirer/core': 10.1.10(@types/node@22.15.18) - '@inquirer/type': 3.0.6(@types/node@22.15.18) - optionalDependencies: - '@types/node': 22.15.18 - - '@inquirer/number@3.0.12(@types/node@22.15.18)': - dependencies: - '@inquirer/core': 10.1.10(@types/node@22.15.18) - '@inquirer/type': 3.0.6(@types/node@22.15.18) - optionalDependencies: - '@types/node': 22.15.18 - '@inquirer/number@3.0.13(@types/node@22.15.18)': dependencies: '@inquirer/core': 10.1.11(@types/node@22.15.18) @@ -1658,14 +1479,6 @@ snapshots: optionalDependencies: '@types/node': 22.15.18 - '@inquirer/password@4.0.12(@types/node@22.15.18)': - dependencies: - '@inquirer/core': 10.1.10(@types/node@22.15.18) - '@inquirer/type': 3.0.6(@types/node@22.15.18) - ansi-escapes: 4.3.2 - optionalDependencies: - '@types/node': 22.15.18 - '@inquirer/password@4.0.13(@types/node@22.15.18)': dependencies: '@inquirer/core': 10.1.11(@types/node@22.15.18) @@ -1674,21 +1487,6 @@ snapshots: optionalDependencies: '@types/node': 22.15.18 - '@inquirer/prompts@7.5.0(@types/node@22.15.18)': - dependencies: - '@inquirer/checkbox': 4.1.5(@types/node@22.15.18) - '@inquirer/confirm': 5.1.9(@types/node@22.15.18) - '@inquirer/editor': 4.2.10(@types/node@22.15.18) - '@inquirer/expand': 4.0.12(@types/node@22.15.18) - '@inquirer/input': 4.1.9(@types/node@22.15.18) - '@inquirer/number': 3.0.12(@types/node@22.15.18) - '@inquirer/password': 4.0.12(@types/node@22.15.18) - '@inquirer/rawlist': 4.1.0(@types/node@22.15.18) - '@inquirer/search': 3.0.12(@types/node@22.15.18) - '@inquirer/select': 4.2.0(@types/node@22.15.18) - optionalDependencies: - '@types/node': 22.15.18 - '@inquirer/prompts@7.5.1(@types/node@22.15.18)': dependencies: '@inquirer/checkbox': 4.1.6(@types/node@22.15.18) @@ -1704,14 +1502,6 @@ snapshots: optionalDependencies: '@types/node': 22.15.18 - '@inquirer/rawlist@4.1.0(@types/node@22.15.18)': - dependencies: - '@inquirer/core': 10.1.10(@types/node@22.15.18) - '@inquirer/type': 3.0.6(@types/node@22.15.18) - yoctocolors-cjs: 2.1.2 - optionalDependencies: - '@types/node': 22.15.18 - '@inquirer/rawlist@4.1.1(@types/node@22.15.18)': dependencies: '@inquirer/core': 10.1.11(@types/node@22.15.18) @@ -1720,15 +1510,6 @@ snapshots: optionalDependencies: '@types/node': 22.15.18 - '@inquirer/search@3.0.12(@types/node@22.15.18)': - dependencies: - '@inquirer/core': 10.1.10(@types/node@22.15.18) - '@inquirer/figures': 1.0.11 - '@inquirer/type': 3.0.6(@types/node@22.15.18) - yoctocolors-cjs: 2.1.2 - optionalDependencies: - '@types/node': 22.15.18 - '@inquirer/search@3.0.13(@types/node@22.15.18)': dependencies: '@inquirer/core': 10.1.11(@types/node@22.15.18) @@ -1738,16 +1519,6 @@ snapshots: optionalDependencies: '@types/node': 22.15.18 - '@inquirer/select@4.2.0(@types/node@22.15.18)': - dependencies: - '@inquirer/core': 10.1.10(@types/node@22.15.18) - '@inquirer/figures': 1.0.11 - '@inquirer/type': 3.0.6(@types/node@22.15.18) - ansi-escapes: 4.3.2 - yoctocolors-cjs: 2.1.2 - optionalDependencies: - '@types/node': 22.15.18 - '@inquirer/select@4.2.1(@types/node@22.15.18)': dependencies: '@inquirer/core': 10.1.11(@types/node@22.15.18) @@ -1825,6 +1596,24 @@ snapshots: '@kevisual/ws@8.0.0': {} + '@pm2/agent@2.1.1': + dependencies: + async: 3.2.6 + chalk: 3.0.0 + dayjs: 1.8.36 + debug: 4.3.7 + eventemitter2: 5.0.1 + fast-json-patch: 3.1.1 + fclone: 1.0.11 + pm2-axon: 4.0.1 + pm2-axon-rpc: 0.7.1 + proxy-agent: 6.4.0 + semver: 7.5.4 + ws: 7.5.10 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + '@pm2/agent@2.1.1(supports-color@10.0.0)': dependencies: async: 3.2.6 @@ -1844,6 +1633,17 @@ snapshots: - supports-color - utf-8-validate + '@pm2/io@6.1.0': + dependencies: + async: 2.6.4 + debug: 4.3.7 + eventemitter2: 6.4.9 + require-in-the-middle: 5.2.0 + semver: 7.5.4 + shimmer: 1.2.1 + signal-exit: 3.0.7 + tslib: 1.9.3 + '@pm2/io@6.1.0(supports-color@10.0.0)': dependencies: async: 2.6.4 @@ -1857,6 +1657,17 @@ snapshots: transitivePeerDependencies: - supports-color + '@pm2/js-api@0.8.0': + dependencies: + async: 2.6.4 + debug: 4.3.7 + eventemitter2: 6.4.9 + extrareqp2: 1.0.0(debug@4.3.7) + ws: 7.5.10 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + '@pm2/js-api@0.8.0(supports-color@10.0.0)': dependencies: async: 2.6.4 @@ -1869,6 +1680,10 @@ snapshots: - supports-color - utf-8-validate + '@pm2/pm2-version-check@1.0.4': + dependencies: + debug: 4.4.0 + '@pm2/pm2-version-check@1.0.4(supports-color@10.0.0)': dependencies: debug: 4.4.0(supports-color@10.0.0) @@ -2155,18 +1970,30 @@ snapshots: dayjs@1.8.36: {} + debug@3.2.7: + dependencies: + ms: 2.1.3 + debug@3.2.7(supports-color@10.0.0): dependencies: ms: 2.1.3 optionalDependencies: supports-color: 10.0.0 + debug@4.3.7: + dependencies: + ms: 2.1.3 + debug@4.3.7(supports-color@10.0.0): dependencies: ms: 2.1.3 optionalDependencies: supports-color: 10.0.0 + debug@4.4.0: + dependencies: + ms: 2.1.3 + debug@4.4.0(supports-color@10.0.0): dependencies: ms: 2.1.3 @@ -2260,6 +2087,12 @@ snapshots: transitivePeerDependencies: - debug + extrareqp2@1.0.0(debug@4.3.7): + dependencies: + follow-redirects: 1.15.9(debug@4.3.7) + transitivePeerDependencies: + - debug + fast-json-patch@3.1.1: {} fclone@1.0.11: {} @@ -2276,6 +2109,10 @@ snapshots: optionalDependencies: debug: 4.3.7(supports-color@10.0.0) + follow-redirects@1.15.9(debug@4.3.7): + optionalDependencies: + debug: 4.3.7 + form-data-encoder@1.7.2: {} form-data@4.0.2: @@ -2317,6 +2154,12 @@ snapshots: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 + get-uri@6.0.4: + dependencies: + basic-ftp: 5.0.5 + data-uri-to-buffer: 6.0.2 + debug: 4.4.0 + get-uri@6.0.4(supports-color@10.0.0): dependencies: basic-ftp: 5.0.5 @@ -2357,6 +2200,11 @@ snapshots: statuses: 2.0.1 toidentifier: 1.0.1 + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.3 + debug: 4.4.0 + http-proxy-agent@7.0.2(supports-color@10.0.0): dependencies: agent-base: 7.1.3 @@ -2364,6 +2212,11 @@ snapshots: transitivePeerDependencies: - supports-color + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.3 + debug: 4.4.0 + https-proxy-agent@7.0.6(supports-color@10.0.0): dependencies: agent-base: 7.1.3 @@ -2385,18 +2238,6 @@ snapshots: ini@1.3.8: {} - inquirer@12.6.0(@types/node@22.15.18): - dependencies: - '@inquirer/core': 10.1.10(@types/node@22.15.18) - '@inquirer/prompts': 7.5.0(@types/node@22.15.18) - '@inquirer/type': 3.0.6(@types/node@22.15.18) - ansi-escapes: 4.3.2 - mute-stream: 2.0.0 - run-async: 3.0.0 - rxjs: 7.8.2 - optionalDependencies: - '@types/node': 22.15.18 - inquirer@12.6.1(@types/node@22.15.18): dependencies: '@inquirer/core': 10.1.11(@types/node@22.15.18) @@ -2499,6 +2340,12 @@ snapshots: nanoid@5.1.5: {} + needle@2.4.0: + dependencies: + debug: 3.2.7 + iconv-lite: 0.4.24 + sax: 1.4.1 + needle@2.4.0(supports-color@10.0.0): dependencies: debug: 3.2.7(supports-color@10.0.0) @@ -2539,6 +2386,17 @@ snapshots: os-tmpdir@1.0.2: {} + pac-proxy-agent@7.2.0: + dependencies: + '@tootallnate/quickjs-emscripten': 0.23.0 + agent-base: 7.1.3 + debug: 4.4.0 + get-uri: 6.0.4 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + pac-resolver: 7.0.1 + socks-proxy-agent: 8.0.5 + pac-proxy-agent@7.2.0(supports-color@10.0.0): dependencies: '@tootallnate/quickjs-emscripten': 0.23.0 @@ -2581,12 +2439,23 @@ snapshots: dependencies: safe-buffer: 5.2.1 + pm2-axon-rpc@0.7.1: + dependencies: + debug: 4.4.0 + pm2-axon-rpc@0.7.1(supports-color@10.0.0): dependencies: debug: 4.4.0(supports-color@10.0.0) transitivePeerDependencies: - supports-color + pm2-axon@4.0.1: + dependencies: + amp: 0.3.1 + amp-message: 0.1.2 + debug: 4.4.0 + escape-string-regexp: 4.0.0 + pm2-axon@4.0.1(supports-color@10.0.0): dependencies: amp: 0.3.1 @@ -2605,6 +2474,15 @@ snapshots: dependencies: charm: 0.1.2 + pm2-sysmonit@1.2.8: + dependencies: + async: 3.2.6 + debug: 4.4.0 + pidusage: 2.0.21 + systeminformation: 5.25.11 + tx2: 1.0.5 + optional: true + pm2-sysmonit@1.2.8(supports-color@10.0.0): dependencies: async: 3.2.6 @@ -2616,30 +2494,30 @@ snapshots: - supports-color optional: true - pm2@6.0.5(supports-color@10.0.0): + pm2@6.0.6: dependencies: - '@pm2/agent': 2.1.1(supports-color@10.0.0) - '@pm2/io': 6.1.0(supports-color@10.0.0) - '@pm2/js-api': 0.8.0(supports-color@10.0.0) - '@pm2/pm2-version-check': 1.0.4(supports-color@10.0.0) + '@pm2/agent': 2.1.1 + '@pm2/io': 6.1.0 + '@pm2/js-api': 0.8.0 + '@pm2/pm2-version-check': 1.0.4 + ansis: 4.0.0 async: 3.2.6 blessed: 0.1.81 - chalk: 3.0.0 chokidar: 3.6.0 cli-tableau: 2.0.1 commander: 2.15.1 croner: 4.1.97 dayjs: 1.11.13 - debug: 4.4.0(supports-color@10.0.0) + debug: 4.4.0 enquirer: 2.3.6 eventemitter2: 5.0.1 fclone: 1.0.11 js-yaml: 4.1.0 mkdirp: 1.0.4 - needle: 2.4.0(supports-color@10.0.0) + needle: 2.4.0 pidusage: 3.0.2 - pm2-axon: 4.0.1(supports-color@10.0.0) - pm2-axon-rpc: 0.7.1(supports-color@10.0.0) + pm2-axon: 4.0.1 + pm2-axon-rpc: 0.7.1 pm2-deploy: 1.0.2 pm2-multimeter: 0.1.2 promptly: 2.2.0 @@ -2648,10 +2526,9 @@ snapshots: sprintf-js: 1.1.2 vizion: 2.2.1 optionalDependencies: - pm2-sysmonit: 1.2.8(supports-color@10.0.0) + pm2-sysmonit: 1.2.8 transitivePeerDependencies: - bufferutil - - supports-color - utf-8-validate pm2@6.0.6(supports-color@10.0.0): @@ -2696,6 +2573,17 @@ snapshots: dependencies: read: 1.0.7 + proxy-agent@6.4.0: + dependencies: + agent-base: 7.1.3 + debug: 4.4.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + lru-cache: 7.18.3 + pac-proxy-agent: 7.2.0 + proxy-from-env: 1.1.0 + socks-proxy-agent: 8.0.5 + proxy-agent@6.4.0(supports-color@10.0.0): dependencies: agent-base: 7.1.3 @@ -2721,6 +2609,12 @@ snapshots: dependencies: picomatch: 2.3.1 + require-in-the-middle@5.2.0: + dependencies: + debug: 4.4.0 + module-details-from-path: 1.0.3 + resolve: 1.22.10 + require-in-the-middle@5.2.0(supports-color@10.0.0): dependencies: debug: 4.4.0(supports-color@10.0.0) @@ -2826,6 +2720,12 @@ snapshots: smart-buffer@4.2.0: {} + socks-proxy-agent@8.0.5: + dependencies: + agent-base: 7.1.3 + debug: 4.4.0 + socks: 2.8.4 + socks-proxy-agent@8.0.5(supports-color@10.0.0): dependencies: agent-base: 7.1.3 diff --git a/assistant/src/module/assistant/config/index.ts b/assistant/src/module/assistant/config/index.ts index fd720df..adfb148 100644 --- a/assistant/src/module/assistant/config/index.ts +++ b/assistant/src/module/assistant/config/index.ts @@ -77,6 +77,14 @@ export type AssistantConfigData = { path?: string; port?: number; }; + share?: { + url: string; + enabled?: boolean; // 是否启用远程应用 + name: string; + }; + watch?: { + enabled?: boolean; + }; /** * 首页 */ diff --git a/assistant/src/module/assistant/remote-app/remote-app.ts b/assistant/src/module/assistant/remote-app/remote-app.ts new file mode 100644 index 0000000..107f56b --- /dev/null +++ b/assistant/src/module/assistant/remote-app/remote-app.ts @@ -0,0 +1,138 @@ +import type { AssistantConfig } from '@/module/assistant/index.ts'; +import { WebSocket } from 'ws'; +import type { App } from '@kevisual/router'; +import { EventEmitter } from 'eventemitter3'; +import { logger } from '@/module/logger.ts'; +type RemoteAppOptions = { + app?: App; + assistantConfig?: AssistantConfig; + emitter?: EventEmitter; +}; +export class RemoteApp { + mainApp: App; + assistantConfig: AssistantConfig; + url: string; + name: string; + enabled: boolean; + emitter: EventEmitter; + isConnected: boolean; + ws: WebSocket; + constructor(opts?: RemoteAppOptions) { + this.mainApp = opts?.app; + this.assistantConfig = opts?.assistantConfig; + const share = this.assistantConfig?.getConfig()?.share; + this.emitter = opts?.emitter || new EventEmitter(); + if (share) { + const { url, name, enabled } = share; + this.url = url; + this.name = name; + this.enabled = enabled ?? false; + if (this.enabled) { + this.init(); + } + } + } + async isConnect(): Promise { + const that = this; + if (this.isConnected) { + return true; + } + if (!this.enabled) { + return false; + } + return new Promise((resolve) => { + const timeout = setTimeout(() => { + resolve(false); + that.emitter.off('open', listenOnce); + }, 5000); + const listenOnce = () => { + clearTimeout(timeout); + that.isConnected = true; + resolve(true); + }; + that.emitter.once('open', listenOnce); + }); + } + getWsURL(url: string) { + const { protocol } = new URL(url); + const wsProtocol = protocol === 'https:' ? 'wss:' : 'ws:'; + const wsURL = url.toString().replace(protocol, wsProtocol); + return wsURL; + } + async init() { + if (!this.url) { + throw new Error('No url provided for remote app'); + } + if (!this.name) { + throw new Error('No name provided for remote app'); + } + console.log('Connecting to remote app:', this.name, this.url, this.getWsURL(this.url)); + const ws = new WebSocket(this.getWsURL(this.url), { + rejectUnauthorized: true, + }); + const that = this; + ws.on('open', that.onOpen.bind(that)); + ws.on('close', that.onClose.bind(that)); + ws.on('message', that.onMessage.bind(that)); + ws.on('error', that.onError.bind(that)); + this.ws = ws; + } + onOpen() { + this.emitter.emit('open', this.name); + } + onClose() { + this.emitter.emit('close', this.name); + } + onMessage(data: any) { + this.emitter.emit('message', data); + } + onError(error: any) { + console.error('Error in remote app:', this.name, error); + this.emitter.emit('error', error); + } + on(event: 'open' | 'close' | 'message' | 'error', listener: (data: any) => void) { + this.emitter.on(event, listener); + return () => { + this.emitter.off(event, listener); + }; + } + + sendData(data: any) {} + json(data: any) { + this.ws.send(JSON.stringify(data)); + } + listenProxy() { + const remoteApp = this; + const app = this.mainApp; + const listenFn = async (event: any) => { + const data = event.toString(); + logger.debug('Received message:', data); + const body = JSON.parse(data); + const message = body.data || {}; + if (body?.type !== 'proxy') return; + if (!body.id) { + remoteApp.json({ + id: body.id, + data: { + code: 400, + message: 'id is required', + }, + }); + return; + } + const res = await app.call(message); + remoteApp.json({ + id: body.id, + data: { + code: res.code, + data: res.body, + message: res.message, + }, + }); + }; + remoteApp.emitter.on('message', listenFn); + return () => { + remoteApp.emitter.off('message', listenFn); + }; + } +} diff --git a/assistant/src/routes/index.ts b/assistant/src/routes/index.ts index b000db2..a0fd162 100644 --- a/assistant/src/routes/index.ts +++ b/assistant/src/routes/index.ts @@ -2,6 +2,7 @@ import { Query } from '@kevisual/query'; import { app, assistantConfig } from '../app.ts'; import './config/index.ts'; import './shop-install/index.ts'; +import os from 'node:os'; app .route({ @@ -49,3 +50,31 @@ app ctx.body = 'v1.0.0'; }) .addTo(app); + +app + .route({ + path: 'client', + key: 'time', + }) + .define(async (ctx) => { + ctx.body = { + time: new Date().getTime(), + date: new Date().toLocaleDateString(), + }; + }) + .addTo(app); + +app + .route({ + path: 'client', + key: 'system', + }) + .define(async (ctx) => { + const { platform, arch, release } = os; + ctx.body = { + platform: platform(), + arch: arch(), + release: release(), + }; + }) + .addTo(app); diff --git a/assistant/src/services/proxy/local-proxy.ts b/assistant/src/services/proxy/local-proxy.ts index 68b48e6..00667df 100644 --- a/assistant/src/services/proxy/local-proxy.ts +++ b/assistant/src/services/proxy/local-proxy.ts @@ -32,19 +32,28 @@ type ProxyType = { }; export type LocalProxyOpts = { assistantConfig?: AssistantConfig; // 前端应用路径 + // watch?: boolean; // 是否监听文件变化 }; export class LocalProxy { localProxyProxyList: ProxyType[] = []; assistantConfig?: AssistantConfig; + watch?: boolean; + watching?: boolean; + initing?: boolean; constructor(opts?: LocalProxyOpts) { this.assistantConfig = opts?.assistantConfig; if (this.assistantConfig) { + this.watch = !!this.assistantConfig.config?.watch.enabled; this.init(); } } init() { const frontAppDir = this.assistantConfig.configPath?.pagesDir; if (frontAppDir) { + if (this.initing) { + return; + } + this.initing = true; const userList = fs.readdirSync(frontAppDir); const localProxyProxyList: ProxyType[] = []; userList.forEach((user) => { @@ -72,12 +81,45 @@ export class LocalProxy { } }); this.localProxyProxyList = localProxyProxyList; + this.initing = false; } } + onWatch() { + // 监听文件变化 + const frontAppDir = this.assistantConfig.configPath?.pagesDir; + const that = this; + if (!this.watch && !frontAppDir) { + return; + } + if (this.watching) { + return; + } + that.watching = true; + let timer: NodeJS.Timeout; + const debounce = (fn: () => void, delay: number) => { + if (timer) { + clearTimeout(timer); + } + timer = setTimeout(() => { + fn(); + }, delay); + }; + fs.watch(frontAppDir, { recursive: true }, (eventType, filename) => { + if (eventType === 'change') { + const filePath = path.join(frontAppDir, filename); + try { + const stat = fs.statSync(filePath); + if (stat.isDirectory()) { + debounce(that.init, 5000); + } + } catch (error) {} + } + }); + } getLocalProxyList() { return this.localProxyProxyList; } reload() { - // 重新加载本地代理列表 + this.init(); } } diff --git a/assistant/src/test/common.ts b/assistant/src/test/common.ts new file mode 100644 index 0000000..6e43c71 --- /dev/null +++ b/assistant/src/test/common.ts @@ -0,0 +1,17 @@ +// import { assistantConfig } from '../app.ts'; +// import { RemoteApp } from '@/module/assistant/remote-app/remote-app.ts'; +console.log('assistantConfig'); +// console.log('assistantConfig', assistantConfig); +// const main = async () => { +// const app = new RemoteApp({ +// assistantConfig, +// }); +// const connect = await app.isConnect(); +// if (connect) { +// console.log('Connected to assistant'); +// } else { +// console.log('Not connected to assistant'); +// } +// }; + +// main(); diff --git a/assistant/src/test/remote-app.ts b/assistant/src/test/remote-app.ts new file mode 100644 index 0000000..576671b --- /dev/null +++ b/assistant/src/test/remote-app.ts @@ -0,0 +1,20 @@ +import { logger } from '@/module/logger.ts'; +import { assistantConfig, app } from '../app.ts'; +import '../routes/index.ts'; +import { RemoteApp } from '@/module/assistant/remote-app/remote-app.ts'; +const main = async () => { + assistantConfig.checkMounted(); + const remoteApp = new RemoteApp({ + assistantConfig, + app, + }); + const connect = await remoteApp.isConnect(); + if (connect) { + console.log('Connected to proxy server'); + remoteApp.listenProxy(); + } else { + console.log('Not connected to proxy server'); + } +}; + +main();