@thangnm.nip/arouter 0.1.11 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +7 -6
  3. package/.next/standalone/.next/build-manifest.json +4 -4
  4. package/.next/standalone/.next/prerender-manifest.json +3 -3
  5. package/.next/standalone/.next/required-server-files.json +4 -4
  6. package/.next/standalone/.next/routes-manifest.json +6 -0
  7. package/.next/standalone/.next/server/app/(dashboard)/mitm/page.js +2 -2
  8. package/.next/standalone/.next/server/app/(dashboard)/mitm/page.js.nft.json +1 -1
  9. package/.next/standalone/.next/server/app/(dashboard)/mitm/page_client-reference-manifest.js +1 -1
  10. package/.next/standalone/.next/server/app/(dashboard)/page.js +2 -2
  11. package/.next/standalone/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  12. package/.next/standalone/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  13. package/.next/standalone/.next/server/app/_global-error/page.js +3 -3
  14. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  15. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  16. package/.next/standalone/.next/server/app/_global-error.html +2 -2
  17. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  18. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  19. package/.next/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  20. package/.next/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  21. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  22. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  23. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  24. package/.next/standalone/.next/server/app/_not-found/page.js +2 -2
  25. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  26. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  27. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  28. package/.next/standalone/.next/server/app/_not-found.rsc +3 -3
  29. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  30. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  31. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  32. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  33. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  34. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  35. package/.next/standalone/.next/server/app/api/cli-tools/antigravity-mitm/alias/route.js +2 -2
  36. package/.next/standalone/.next/server/app/api/cli-tools/antigravity-mitm/alias/route_client-reference-manifest.js +1 -1
  37. package/.next/standalone/.next/server/app/api/cli-tools/antigravity-mitm/console-logs/route.js +2 -2
  38. package/.next/standalone/.next/server/app/api/cli-tools/antigravity-mitm/console-logs/route_client-reference-manifest.js +1 -1
  39. package/.next/standalone/.next/server/app/api/cli-tools/antigravity-mitm/logs/route.js +8 -0
  40. package/.next/standalone/.next/server/app/api/cli-tools/antigravity-mitm/logs/route.js.nft.json +1 -0
  41. package/.next/standalone/.next/server/app/api/cli-tools/antigravity-mitm/logs/route_client-reference-manifest.js +1 -0
  42. package/.next/standalone/.next/server/app/api/cli-tools/antigravity-mitm/route.js +1 -1
  43. package/.next/standalone/.next/server/app/api/cli-tools/antigravity-mitm/route_client-reference-manifest.js +1 -1
  44. package/.next/standalone/.next/server/app/api/cli-tools/antigravity-mitm/settings/route.js +2 -2
  45. package/.next/standalone/.next/server/app/api/cli-tools/antigravity-mitm/settings/route_client-reference-manifest.js +1 -1
  46. package/.next/standalone/.next/server/app/api/cli-tools/claude-settings/route.js +2 -2
  47. package/.next/standalone/.next/server/app/api/cli-tools/claude-settings/route_client-reference-manifest.js +1 -1
  48. package/.next/standalone/.next/server/app/api/cli-tools/codex-settings/route.js +3 -3
  49. package/.next/standalone/.next/server/app/api/cli-tools/codex-settings/route_client-reference-manifest.js +1 -1
  50. package/.next/standalone/.next/server/app/api/cli-tools/copilot-settings/route.js +2 -2
  51. package/.next/standalone/.next/server/app/api/cli-tools/copilot-settings/route_client-reference-manifest.js +1 -1
  52. package/.next/standalone/.next/server/app/api/cli-tools/droid-settings/route.js +1 -1
  53. package/.next/standalone/.next/server/app/api/cli-tools/droid-settings/route_client-reference-manifest.js +1 -1
  54. package/.next/standalone/.next/server/app/api/cli-tools/openclaw-settings/route.js +2 -2
  55. package/.next/standalone/.next/server/app/api/cli-tools/openclaw-settings/route_client-reference-manifest.js +1 -1
  56. package/.next/standalone/.next/server/app/api/cli-tools/opencode-settings/route.js +2 -2
  57. package/.next/standalone/.next/server/app/api/cli-tools/opencode-settings/route_client-reference-manifest.js +1 -1
  58. package/.next/standalone/.next/server/app/api/keys/[id]/route.js +1 -1
  59. package/.next/standalone/.next/server/app/api/keys/[id]/route_client-reference-manifest.js +1 -1
  60. package/.next/standalone/.next/server/app/api/keys/route.js +1 -1
  61. package/.next/standalone/.next/server/app/api/keys/route_client-reference-manifest.js +1 -1
  62. package/.next/standalone/.next/server/app/api/locale/route.js +2 -2
  63. package/.next/standalone/.next/server/app/api/locale/route_client-reference-manifest.js +1 -1
  64. package/.next/standalone/.next/server/app/api/models/alias/route.js +1 -1
  65. package/.next/standalone/.next/server/app/api/models/alias/route_client-reference-manifest.js +1 -1
  66. package/.next/standalone/.next/server/app/api/models/route.js +1 -1
  67. package/.next/standalone/.next/server/app/api/models/route_client-reference-manifest.js +1 -1
  68. package/.next/standalone/.next/server/app/api/providers/route.js +1 -1
  69. package/.next/standalone/.next/server/app/api/providers/route_client-reference-manifest.js +1 -1
  70. package/.next/standalone/.next/server/app/api/settings/route.js +1 -1
  71. package/.next/standalone/.next/server/app/api/settings/route_client-reference-manifest.js +1 -1
  72. package/.next/standalone/.next/server/app/api/version/route.js +1 -1
  73. package/.next/standalone/.next/server/app/api/version/route_client-reference-manifest.js +1 -1
  74. package/.next/standalone/.next/server/app/index.html +1 -1
  75. package/.next/standalone/.next/server/app/index.rsc +4 -4
  76. package/.next/standalone/.next/server/app/index.segments/!KGRhc2hib2FyZCk/__PAGE__.segment.rsc +1 -1
  77. package/.next/standalone/.next/server/app/index.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  78. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  79. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  80. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  81. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  82. package/.next/standalone/.next/server/app/mitm.html +1 -1
  83. package/.next/standalone/.next/server/app/mitm.rsc +5 -5
  84. package/.next/standalone/.next/server/app/mitm.segments/!KGRhc2hib2FyZCk/mitm/__PAGE__.segment.rsc +2 -2
  85. package/.next/standalone/.next/server/app/mitm.segments/!KGRhc2hib2FyZCk/mitm.segment.rsc +1 -1
  86. package/.next/standalone/.next/server/app/mitm.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  87. package/.next/standalone/.next/server/app/mitm.segments/_full.segment.rsc +5 -5
  88. package/.next/standalone/.next/server/app/mitm.segments/_head.segment.rsc +1 -1
  89. package/.next/standalone/.next/server/app/mitm.segments/_index.segment.rsc +3 -3
  90. package/.next/standalone/.next/server/app/mitm.segments/_tree.segment.rsc +1 -1
  91. package/.next/standalone/.next/server/app-paths-manifest.json +7 -6
  92. package/.next/standalone/.next/server/chunks/138.js +1 -1
  93. package/.next/standalone/.next/server/chunks/182.js +9 -2
  94. package/.next/standalone/.next/server/chunks/219.js +1 -0
  95. package/.next/standalone/.next/server/chunks/471.js +13 -0
  96. package/.next/standalone/.next/server/chunks/741.js +2 -2
  97. package/.next/standalone/.next/server/chunks/900.js +7 -0
  98. package/.next/standalone/.next/server/middleware-build-manifest.js +1 -1
  99. package/.next/standalone/.next/server/middleware.js +2 -2
  100. package/.next/standalone/.next/server/next-font-manifest.js +1 -1
  101. package/.next/standalone/.next/server/next-font-manifest.json +1 -1
  102. package/.next/standalone/.next/server/pages/404.html +1 -1
  103. package/.next/standalone/.next/server/pages/500.html +2 -2
  104. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  105. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  106. package/.next/standalone/.next/static/chunks/{702-8f4a71e9289e360c.js → 702-c4610efa55dfb155.js} +1 -1
  107. package/.next/standalone/.next/static/chunks/{794-e4409998c8ba5c29.js → 794-37dad9bbc14b04b8.js} +1 -1
  108. package/.next/standalone/.next/static/chunks/{852-6b2b2eefb2d99b28.js → 852-d8cad4b0d71288a2.js} +3 -3
  109. package/.next/standalone/.next/static/chunks/app/(dashboard)/layout-579c25ca675b41ac.js +1 -0
  110. package/.next/standalone/.next/static/chunks/app/(dashboard)/mitm/page-d25cf1803f6924ee.js +7 -0
  111. package/.next/standalone/.next/static/chunks/app/(dashboard)/{page-a4e7c4e324778903.js → page-5c09ac097fc0cc9b.js} +1 -1
  112. package/.next/standalone/.next/static/chunks/app/_global-error/{page-a4e7c4e324778903.js → page-5c09ac097fc0cc9b.js} +1 -1
  113. package/.next/standalone/.next/static/chunks/app/_not-found/{page-f6a07fd1289f84a5.js → page-038730efde50428c.js} +1 -1
  114. package/.next/standalone/.next/static/chunks/app/api/cli-tools/antigravity-mitm/alias/{route-a4e7c4e324778903.js → route-5c09ac097fc0cc9b.js} +1 -1
  115. package/.next/standalone/.next/static/chunks/app/api/cli-tools/antigravity-mitm/console-logs/{route-a4e7c4e324778903.js → route-5c09ac097fc0cc9b.js} +1 -1
  116. package/.next/standalone/.next/static/chunks/app/api/cli-tools/antigravity-mitm/logs/route-5c09ac097fc0cc9b.js +1 -0
  117. package/.next/standalone/.next/static/chunks/app/api/cli-tools/antigravity-mitm/route-5c09ac097fc0cc9b.js +1 -0
  118. package/.next/standalone/.next/static/chunks/app/api/cli-tools/antigravity-mitm/settings/route-5c09ac097fc0cc9b.js +1 -0
  119. package/.next/standalone/.next/static/chunks/app/api/cli-tools/claude-settings/route-5c09ac097fc0cc9b.js +1 -0
  120. package/.next/standalone/.next/static/chunks/app/api/cli-tools/codex-settings/route-5c09ac097fc0cc9b.js +1 -0
  121. package/.next/standalone/.next/static/chunks/app/api/cli-tools/copilot-settings/route-5c09ac097fc0cc9b.js +1 -0
  122. package/.next/standalone/.next/static/chunks/app/api/cli-tools/droid-settings/route-5c09ac097fc0cc9b.js +1 -0
  123. package/.next/standalone/.next/static/chunks/app/api/cli-tools/openclaw-settings/route-5c09ac097fc0cc9b.js +1 -0
  124. package/.next/standalone/.next/static/chunks/app/api/cli-tools/opencode-settings/route-5c09ac097fc0cc9b.js +1 -0
  125. package/.next/standalone/.next/static/chunks/app/api/keys/[id]/route-5c09ac097fc0cc9b.js +1 -0
  126. package/.next/standalone/.next/static/chunks/app/api/keys/route-5c09ac097fc0cc9b.js +1 -0
  127. package/.next/standalone/.next/static/chunks/app/api/locale/route-5c09ac097fc0cc9b.js +1 -0
  128. package/.next/standalone/.next/static/chunks/app/api/models/alias/route-5c09ac097fc0cc9b.js +1 -0
  129. package/.next/standalone/.next/static/chunks/app/api/models/route-5c09ac097fc0cc9b.js +1 -0
  130. package/.next/standalone/.next/static/chunks/app/api/providers/route-5c09ac097fc0cc9b.js +1 -0
  131. package/.next/standalone/.next/static/chunks/app/api/settings/route-5c09ac097fc0cc9b.js +1 -0
  132. package/.next/standalone/.next/static/chunks/app/api/version/route-5c09ac097fc0cc9b.js +1 -0
  133. package/.next/standalone/.next/static/chunks/app/{layout-6de9a5310276adf9.js → layout-6e491caa4df42293.js} +1 -1
  134. package/.next/standalone/.next/static/chunks/{main-9b410d84e10d7a77.js → main-842bf1ddb8ee9ec0.js} +2 -2
  135. package/.next/standalone/.next/static/chunks/{main-app-2ed2446a2e4f75e7.js → main-app-0fea626ed7ee1281.js} +1 -1
  136. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-5c09ac097fc0cc9b.js +1 -0
  137. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-5c09ac097fc0cc9b.js +1 -0
  138. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-89d8af6ad4f69554.js +1 -0
  139. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-5c09ac097fc0cc9b.js +1 -0
  140. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-5c09ac097fc0cc9b.js +1 -0
  141. package/.next/standalone/.next/static/rZAYFVGk5tWg3Az1gc9jl/_buildManifest.js +1 -0
  142. package/.next/standalone/node_modules/@next/env/package.json +1 -1
  143. package/.next/standalone/node_modules/next/dist/build/swc/index.js +1 -1
  144. package/.next/standalone/node_modules/next/dist/build/webpack-config.js +3 -3
  145. package/.next/standalone/node_modules/next/dist/compiled/http-proxy/index.js +5 -5
  146. package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-experimental.runtime.prod.js +3 -3
  147. package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js +12 -12
  148. package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo.runtime.prod.js +3 -3
  149. package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js +3 -3
  150. package/.next/standalone/node_modules/next/dist/compiled/next-server/app-route.runtime.prod.js +2 -2
  151. package/.next/standalone/node_modules/next/dist/compiled/next-server/pages-turbo.runtime.prod.js +2 -2
  152. package/.next/standalone/node_modules/next/dist/compiled/next-server/pages.runtime.prod.js +2 -2
  153. package/.next/standalone/node_modules/next/dist/server/app-render/action-handler.js +7 -11
  154. package/.next/standalone/node_modules/next/dist/server/base-server.js +22 -8
  155. package/.next/standalone/node_modules/next/dist/server/config-schema.js +0 -1
  156. package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-turbopack.js +1 -1
  157. package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-webpack.js +1 -1
  158. package/.next/standalone/node_modules/next/dist/server/image-optimizer.js +22 -148
  159. package/.next/standalone/node_modules/next/dist/server/lib/app-info-log.js +1 -1
  160. package/.next/standalone/node_modules/next/dist/server/lib/lru-cache.js +1 -2
  161. package/.next/standalone/node_modules/next/dist/server/lib/patch-fetch.js +6 -15
  162. package/.next/standalone/node_modules/next/dist/server/lib/router-server.js +3 -3
  163. package/.next/standalone/node_modules/next/dist/server/lib/router-utils/{block-cross-site-dev.js → block-cross-site.js} +17 -11
  164. package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
  165. package/.next/standalone/node_modules/next/dist/shared/lib/errors/canary-only-config-error.js +1 -1
  166. package/.next/standalone/node_modules/next/dist/shared/lib/image-config.js +0 -1
  167. package/.next/standalone/node_modules/next/dist/telemetry/anonymous-meta.js +1 -1
  168. package/.next/standalone/node_modules/next/dist/telemetry/events/version.js +2 -2
  169. package/.next/standalone/node_modules/next/package.json +16 -16
  170. package/.next/standalone/package.json +1 -1
  171. package/.next/standalone/server.js +1 -1
  172. package/.next/standalone/src/mitm/manager.js +51 -9
  173. package/bin/arouter.js +292 -0
  174. package/bin/arouter.mjs +264 -111
  175. package/bin/paths.js +23 -0
  176. package/bin/paths.mjs +23 -0
  177. package/package.json +1 -1
  178. package/scripts/postinstall.mjs +19 -23
  179. package/.next/standalone/.next/server/chunks/411.js +0 -1
  180. package/.next/standalone/.next/server/chunks/63.js +0 -13
  181. package/.next/standalone/.next/server/chunks/724.js +0 -7
  182. package/.next/standalone/.next/static/chunks/app/(dashboard)/layout-384bfa634ec14bbe.js +0 -1
  183. package/.next/standalone/.next/static/chunks/app/(dashboard)/mitm/page-3dca1ab0735aaa0f.js +0 -7
  184. package/.next/standalone/.next/static/chunks/app/api/cli-tools/antigravity-mitm/route-a4e7c4e324778903.js +0 -1
  185. package/.next/standalone/.next/static/chunks/app/api/cli-tools/antigravity-mitm/settings/route-a4e7c4e324778903.js +0 -1
  186. package/.next/standalone/.next/static/chunks/app/api/cli-tools/claude-settings/route-a4e7c4e324778903.js +0 -1
  187. package/.next/standalone/.next/static/chunks/app/api/cli-tools/codex-settings/route-a4e7c4e324778903.js +0 -1
  188. package/.next/standalone/.next/static/chunks/app/api/cli-tools/copilot-settings/route-a4e7c4e324778903.js +0 -1
  189. package/.next/standalone/.next/static/chunks/app/api/cli-tools/droid-settings/route-a4e7c4e324778903.js +0 -1
  190. package/.next/standalone/.next/static/chunks/app/api/cli-tools/openclaw-settings/route-a4e7c4e324778903.js +0 -1
  191. package/.next/standalone/.next/static/chunks/app/api/cli-tools/opencode-settings/route-a4e7c4e324778903.js +0 -1
  192. package/.next/standalone/.next/static/chunks/app/api/keys/[id]/route-a4e7c4e324778903.js +0 -1
  193. package/.next/standalone/.next/static/chunks/app/api/keys/route-a4e7c4e324778903.js +0 -1
  194. package/.next/standalone/.next/static/chunks/app/api/locale/route-a4e7c4e324778903.js +0 -1
  195. package/.next/standalone/.next/static/chunks/app/api/models/alias/route-a4e7c4e324778903.js +0 -1
  196. package/.next/standalone/.next/static/chunks/app/api/models/route-a4e7c4e324778903.js +0 -1
  197. package/.next/standalone/.next/static/chunks/app/api/providers/route-a4e7c4e324778903.js +0 -1
  198. package/.next/standalone/.next/static/chunks/app/api/settings/route-a4e7c4e324778903.js +0 -1
  199. package/.next/standalone/.next/static/chunks/app/api/version/route-a4e7c4e324778903.js +0 -1
  200. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-a4e7c4e324778903.js +0 -1
  201. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-a4e7c4e324778903.js +0 -1
  202. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-a42479e2ca7868a9.js +0 -1
  203. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-a4e7c4e324778903.js +0 -1
  204. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-a4e7c4e324778903.js +0 -1
  205. package/.next/standalone/.next/static/cn0nPxdvWWK5t_Uw1V17t/_buildManifest.js +0 -1
  206. package/.next/standalone/node_modules/next/dist/server/lib/disk-lru-cache.external.js +0 -57
  207. package/.next/standalone/node_modules/next/dist/server/lib/postponed-request-body.js +0 -64
  208. /package/.next/standalone/.next/static/{cn0nPxdvWWK5t_Uw1V17t → rZAYFVGk5tWg3Az1gc9jl}/_ssgManifest.js +0 -0
package/bin/arouter.mjs CHANGED
@@ -1,148 +1,301 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { spawn } from 'child_process';
4
- import path from 'path';
5
- import fs from 'fs';
6
- import { fileURLToPath } from 'url';
7
- import os from 'os';
8
-
9
- const __filename = fileURLToPath(import.meta.url);
10
- const __dirname = path.dirname(__filename);
11
-
12
- const args = process.argv.slice(2);
13
- const command = args[0] || 'start';
14
-
15
- let port = '20129';
16
- const portIndex = args.indexOf('--port');
17
- if (portIndex !== -1 && args[portIndex + 1]) {
18
- port = args[portIndex + 1];
19
- }
20
- // If running from node_modules after npm install -g, the standalone structure is slightly different
21
- // than running it locally in the dev repo.
22
- // Path to the Next.js standalone server
23
- // When installed globally, the structure is:
24
- // global/node_modules/@thangnm.nip/arouter/
25
- // ├── bin/arouter.mjs
26
- // └── .next/standalone/server.js
27
- const serverPath = path.join(__dirname, '..', '.next', 'standalone', 'server.js');
28
-
29
-
30
- const arouterHome = path.join(os.homedir(), '.arouter');
31
- const pidFile = path.join(arouterHome, 'server.pid');
32
- const logFile = path.join(arouterHome, 'server.log');
33
- const portFile = path.join(arouterHome, 'server.port');
34
-
35
- if (!fs.existsSync(arouterHome)) {
36
- fs.mkdirSync(arouterHome, { recursive: true });
3
+ import { spawn, execSync } from "child_process";
4
+ import { existsSync, readFileSync, writeFileSync, unlinkSync, openSync, cpSync } from "fs";
5
+ import { resolve } from "path";
6
+ import { platform } from "os";
7
+ import { createServer } from "net";
8
+ import { PROJECT_ROOT, DATA_DIR, PID_FILE, LOG_FILE, PORT, DASHBOARD_URL } from "./paths.mjs";
9
+
10
+ // ─── Helpers ────────────────────────────────────────────────────────────
11
+
12
+ const IS_WIN = platform() === "win32";
13
+ const GREEN = "\x1b[32m";
14
+ const YELLOW = "\x1b[33m";
15
+ const RED = "\x1b[31m";
16
+ const CYAN = "\x1b[36m";
17
+ const DIM = "\x1b[2m";
18
+ const BOLD = "\x1b[1m";
19
+ const RESET = "\x1b[0m";
20
+
21
+ function log(msg) { console.log(`${DIM}[arouter]${RESET} ${msg}`); }
22
+ function success(msg) { console.log(`${GREEN}✔${RESET} ${msg}`); }
23
+ function warn(msg) { console.log(`${YELLOW}⚠${RESET} ${msg}`); }
24
+ function error(msg) { console.error(`${RED}✖${RESET} ${msg}`); }
25
+
26
+ /** Cross-platform port check using Node.js net module */
27
+ function isPortInUse(port) {
28
+ return new Promise((resolve) => {
29
+ const server = createServer();
30
+ server.once("error", (err) => {
31
+ if (err.code === "EADDRINUSE") resolve(true);
32
+ else resolve(false);
33
+ });
34
+ server.once("listening", () => {
35
+ server.close(() => resolve(false));
36
+ });
37
+ server.listen(port, "0.0.0.0");
38
+ });
37
39
  }
38
40
 
39
- function checkStatus() {
40
- if (!fs.existsSync(pidFile)) {
41
- return false;
42
- }
43
- const pid = parseInt(fs.readFileSync(pidFile, 'utf8'), 10);
41
+ function getRunningPid() {
42
+ if (!existsSync(PID_FILE)) return null;
43
+ const pid = parseInt(readFileSync(PID_FILE, "utf-8").trim(), 10);
44
+ if (isNaN(pid)) return null;
44
45
  try {
45
- // process.kill(pid, 0) throws an error if the process doesn't exist
46
46
  process.kill(pid, 0);
47
47
  return pid;
48
+ } catch {
49
+ try { unlinkSync(PID_FILE); } catch { /* ignore */ }
50
+ return null;
51
+ }
52
+ }
53
+
54
+ function waitForServer(timeoutMs = 60000) {
55
+ return new Promise((resolve, reject) => {
56
+ const start = Date.now();
57
+ const check = () => {
58
+ if (Date.now() - start > timeoutMs) {
59
+ return reject(new Error("Server startup timed out"));
60
+ }
61
+ import("http").then(({ default: http }) => {
62
+ const req = http.get(`http://localhost:${PORT}`, (res) => {
63
+ res.resume();
64
+ resolve();
65
+ });
66
+ req.on("error", () => setTimeout(check, 500));
67
+ req.setTimeout(2000, () => { req.destroy(); setTimeout(check, 500); });
68
+ });
69
+ };
70
+ check();
71
+ });
72
+ }
73
+
74
+ function npmCommand() {
75
+ return IS_WIN ? "npm.cmd" : "npm";
76
+ }
77
+
78
+ // ─── Commands ───────────────────────────────────────────────────────────
79
+
80
+ async function buildIfNeeded() {
81
+ const standaloneServer = resolve(PROJECT_ROOT, ".next/standalone/server.js");
82
+ if (existsSync(standaloneServer)) return;
83
+
84
+ log("First run — building production bundle...");
85
+ log(`${DIM}This will take a minute, please wait...${RESET}`);
86
+
87
+ try {
88
+ execSync(`${npmCommand()} run build`, {
89
+ cwd: PROJECT_ROOT,
90
+ stdio: "inherit",
91
+ env: { ...process.env, NODE_ENV: "production" },
92
+ shell: true,
93
+ });
94
+ success("Build complete!");
95
+
96
+ // Next.js standalone requires static assets + public to be copied manually
97
+ const standaloneDir = resolve(PROJECT_ROOT, ".next/standalone");
98
+ const staticSrc = resolve(PROJECT_ROOT, ".next/static");
99
+ const staticDest = resolve(standaloneDir, ".next/static");
100
+ const publicSrc = resolve(PROJECT_ROOT, "public");
101
+ const publicDest = resolve(standaloneDir, "public");
102
+
103
+ if (existsSync(staticSrc) && !existsSync(staticDest)) {
104
+ log("Copying static assets...");
105
+ cpSync(staticSrc, staticDest, { recursive: true });
106
+ }
107
+ if (existsSync(publicSrc) && !existsSync(publicDest)) {
108
+ log("Copying public files...");
109
+ cpSync(publicSrc, publicDest, { recursive: true });
110
+ }
111
+ success("Assets ready!");
48
112
  } catch (e) {
49
- // Process is not running, clean up stale PID file
50
- fs.unlinkSync(pidFile);
51
- return false;
113
+ error("Build failed. Check the output above.");
114
+ process.exit(1);
52
115
  }
53
116
  }
54
117
 
55
- if (command === 'start') {
56
- const currentPid = checkStatus();
57
- if (currentPid) {
58
- const savedPort = fs.existsSync(portFile) ? fs.readFileSync(portFile, 'utf8') : port;
59
- console.log(`arouter is already running (PID: ${currentPid}). Access it at http://localhost:${savedPort}`);
60
- process.exit(0);
118
+ async function startServer() {
119
+ const pid = getRunningPid();
120
+ if (pid) {
121
+ success(`aRouter is already running ${DIM}(PID: ${pid})${RESET}`);
122
+ console.log();
123
+ console.log(` ${BOLD}Dashboard${RESET} ${CYAN}${DASHBOARD_URL}${RESET}`);
124
+ console.log();
125
+ return;
61
126
  }
62
127
 
63
- if (!fs.existsSync(serverPath)) {
64
- console.error(`Error: Could not find standalone server at ${serverPath}`);
65
- console.error('Make sure you have built the application using `npm run build`.');
128
+ const portBusy = await isPortInUse(PORT);
129
+ if (portBusy) {
130
+ error(`Port ${PORT} is already in use by another process.`);
131
+ log(`Stop the other process or change the port.`);
66
132
  process.exit(1);
67
133
  }
68
134
 
69
- console.log('Starting arouter server in the background...');
70
-
71
- // We use standard out/err redirection to a log file
72
- const out = fs.openSync(logFile, 'a');
73
- const err = fs.openSync(logFile, 'a');
135
+ await buildIfNeeded();
136
+
137
+ log("Starting aRouter...");
138
+
139
+ const logFd = openSync(LOG_FILE, "a");
74
140
 
75
- const child = spawn(process.execPath, [serverPath], {
76
- detached: true,
77
- stdio: ['ignore', out, err],
141
+ const serverScript = resolve(PROJECT_ROOT, ".next/standalone/server.js");
142
+ const child = spawn(process.execPath, [serverScript], {
143
+ cwd: PROJECT_ROOT, // Important: CWD must be PROJECT_ROOT so MITM can find src/mitm/
144
+ detached: !IS_WIN,
145
+ stdio: ["ignore", logFd, logFd],
78
146
  env: {
79
147
  ...process.env,
80
- NODE_ENV: 'production',
81
- PORT: port
82
- }
148
+ NODE_ENV: "production",
149
+ PORT: String(PORT),
150
+ HOSTNAME: "0.0.0.0",
151
+ // Tell MITM manager where the real server.js is (not the standalone bundled one)
152
+ MITM_SERVER_PATH: resolve(PROJECT_ROOT, "src/mitm/server.js"),
153
+ },
154
+ ...(IS_WIN ? { windowsHide: true } : {}),
83
155
  });
84
156
 
85
- child.unref(); // Allow the parent process to exit gracefully
86
-
87
- if (child.pid) {
88
- fs.writeFileSync(pidFile, child.pid.toString());
89
- fs.writeFileSync(portFile, port.toString());
90
- console.log(`Server started successfully in background! (PID: ${child.pid})`);
91
- console.log(`You can view logs at: ${logFile}`);
92
-
93
- // Give it a moment to bind to the port before telling the user it's ready
94
- setTimeout(() => {
95
- console.log(`\n🚀 arouter is available at http://localhost:${port}\n`);
96
- process.exit(0);
97
- }, 1000);
98
- } else {
99
- console.error('Failed to start server.');
100
- process.exit(1);
157
+ writeFileSync(PID_FILE, String(child.pid));
158
+ child.unref();
159
+
160
+ try {
161
+ process.stdout.write(` Waiting for server `);
162
+ await waitForServer(60000);
163
+ process.stdout.write(`${GREEN}ready!${RESET}\n`);
164
+ } catch {
165
+ process.stdout.write(`${YELLOW}(timeout check logs)${RESET}\n`);
101
166
  }
102
167
 
103
- } else if (command === 'stop') {
104
- const pid = checkStatus();
168
+ console.log();
169
+ console.log(` ${GREEN}${BOLD}aRouter is running!${RESET}`);
170
+ console.log();
171
+ console.log(` ${BOLD}Dashboard${RESET} ${CYAN}${DASHBOARD_URL}${RESET}`);
172
+ console.log(` ${BOLD}API${RESET} ${CYAN}${DASHBOARD_URL}/v1${RESET}`);
173
+ console.log(` ${BOLD}PID${RESET} ${DIM}${child.pid}${RESET}`);
174
+ console.log(` ${BOLD}Logs${RESET} ${DIM}${LOG_FILE}${RESET}`);
175
+ console.log();
176
+ console.log(` ${DIM}Run ${RESET}arouter stop${DIM} to stop the server.${RESET}`);
177
+ console.log();
178
+ }
179
+
180
+ function stopServer() {
181
+ const pid = getRunningPid();
105
182
  if (!pid) {
106
- console.log('arouter is not currently running.');
107
- if (fs.existsSync(portFile)) fs.unlinkSync(portFile);
108
- process.exit(0);
183
+ warn("aRouter is not running.");
184
+ return;
109
185
  }
110
186
 
111
- console.log(`Stopping arouter (PID: ${pid})...`);
187
+ log(`Stopping aRouter (PID: ${pid})...`);
112
188
  try {
113
- process.kill(pid); // Send default SIGTERM
114
- fs.unlinkSync(pidFile);
115
- if (fs.existsSync(portFile)) fs.unlinkSync(portFile);
116
- console.log('Server stopped successfully.');
189
+ if (IS_WIN) {
190
+ execSync(`taskkill /PID ${pid} /T /F`, { stdio: "ignore", shell: true });
191
+ } else {
192
+ process.kill(pid, "SIGTERM");
193
+ setTimeout(() => {
194
+ try {
195
+ process.kill(pid, 0);
196
+ process.kill(pid, "SIGKILL");
197
+ } catch { /* already dead */ }
198
+ }, 3000);
199
+ }
117
200
  } catch (e) {
118
- console.error(`Failed to stop server: ${e.message}`);
119
- process.exit(1);
201
+ warn(`Could not kill process: ${e.message}`);
120
202
  }
121
203
 
122
- } else if (command === 'status') {
123
- const pid = checkStatus();
204
+ try { unlinkSync(PID_FILE); } catch { /* ignore */ }
205
+ success("aRouter stopped.");
206
+ }
207
+
208
+ function showStatus() {
209
+ const pid = getRunningPid();
124
210
  if (pid) {
125
- const savedPort = fs.existsSync(portFile) ? fs.readFileSync(portFile, 'utf8') : port;
126
- console.log(`arouter is running (PID: ${pid}).`);
127
- console.log(`Interface: http://localhost:${savedPort}`);
128
- console.log(`Logs: ${logFile}`);
211
+ success(`aRouter is running ${DIM}(PID: ${pid})${RESET}`);
212
+ console.log(` ${BOLD}Dashboard${RESET} ${CYAN}${DASHBOARD_URL}${RESET}`);
129
213
  } else {
130
- console.log('arouter is not running.');
214
+ warn("aRouter is not running.");
131
215
  }
216
+ }
132
217
 
133
- } else if (command === 'logs') {
134
- if (fs.existsSync(logFile)) {
135
- // Simple log dump, you could use 'tail' for streaming if preferred
136
- console.log(`Reading logs from ${logFile}:`);
137
- console.log(fs.readFileSync(logFile, 'utf8'));
218
+ function showLogs() {
219
+ if (!existsSync(LOG_FILE)) {
220
+ warn("No log file found. Start the server first.");
221
+ return;
222
+ }
223
+ try {
224
+ const content = readFileSync(LOG_FILE, "utf-8");
225
+ const lines = content.split("\n").slice(-50);
226
+ console.log(lines.join("\n"));
227
+ } catch (e) {
228
+ error(`Could not read logs: ${e.message}`);
229
+ }
230
+ }
231
+
232
+ async function restartServer() {
233
+ stopServer();
234
+ await new Promise(r => setTimeout(r, 1500));
235
+ await startServer();
236
+ }
237
+
238
+ function showHelp() {
239
+ console.log();
240
+ console.log(` ${BOLD}aRouter${RESET} — AI Model Router & MITM Proxy`);
241
+ console.log();
242
+ console.log(` ${BOLD}Usage:${RESET}`);
243
+ console.log(` ${CYAN}arouter${RESET} Start the server (background)`);
244
+ console.log(` ${CYAN}arouter start${RESET} Same as above`);
245
+ console.log(` ${CYAN}arouter stop${RESET} Stop the server`);
246
+ console.log(` ${CYAN}arouter restart${RESET} Restart the server`);
247
+ console.log(` ${CYAN}arouter status${RESET} Show server status`);
248
+ console.log(` ${CYAN}arouter logs${RESET} Show recent logs`);
249
+ console.log(` ${CYAN}arouter dev${RESET} Run in foreground (dev mode)`);
250
+ console.log(` ${CYAN}arouter build${RESET} Force rebuild`);
251
+ console.log(` ${CYAN}arouter help${RESET} Show this help`);
252
+ console.log();
253
+ console.log(` ${BOLD}Data:${RESET} ${DIM}${DATA_DIR}${RESET}`);
254
+ console.log(` ${BOLD}Port:${RESET} ${DIM}${PORT}${RESET}`);
255
+ console.log();
256
+ }
257
+
258
+ function devMode() {
259
+ log("Starting in dev mode (foreground)...");
260
+ const child = spawn(npmCommand(), ["run", "dev"], {
261
+ cwd: PROJECT_ROOT,
262
+ stdio: "inherit",
263
+ env: { ...process.env },
264
+ shell: IS_WIN,
265
+ });
266
+ child.on("exit", (code) => process.exit(code || 0));
267
+ }
268
+
269
+ async function forceBuild() {
270
+ log("Force rebuilding...");
271
+ const nextDir = resolve(PROJECT_ROOT, ".next");
272
+ try {
273
+ if (IS_WIN) {
274
+ execSync(`rmdir /s /q "${nextDir}"`, { cwd: PROJECT_ROOT, shell: true, stdio: "ignore" });
138
275
  } else {
139
- console.log(`No logs found at ${logFile}`);
276
+ execSync(`rm -rf "${nextDir}"`, { cwd: PROJECT_ROOT, stdio: "ignore" });
140
277
  }
141
- } else {
142
- console.log('Usage: arouter <command>');
143
- console.log('Commands:');
144
- console.log(' start Start the server in the background');
145
- console.log(' stop Stop the running server');
146
- console.log(' status Check if the server is running');
147
- console.log(' logs View the server logs');
278
+ } catch { /* ignore */ }
279
+ await buildIfNeeded();
280
+ }
281
+
282
+ // ─── Main ───────────────────────────────────────────────────────────────
283
+
284
+ const command = process.argv[2] || "start";
285
+
286
+ switch (command) {
287
+ case "start": await startServer(); break;
288
+ case "stop": stopServer(); break;
289
+ case "restart": await restartServer(); break;
290
+ case "status": showStatus(); break;
291
+ case "logs": showLogs(); break;
292
+ case "dev": devMode(); break;
293
+ case "build": await forceBuild(); break;
294
+ case "help":
295
+ case "--help":
296
+ case "-h": showHelp(); break;
297
+ default:
298
+ error(`Unknown command: ${command}`);
299
+ showHelp();
300
+ process.exit(1);
148
301
  }
package/bin/paths.js ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { resolve, dirname } from "path";
4
+ import { fileURLToPath } from "url";
5
+ import { homedir } from "os";
6
+ import { existsSync, mkdirSync } from "fs";
7
+
8
+ const __dirname = dirname(fileURLToPath(import.meta.url));
9
+
10
+ // Project root (where package.json lives)
11
+ export const PROJECT_ROOT = resolve(__dirname, "..");
12
+
13
+ // User data directory (~/.arouter/)
14
+ export const DATA_DIR = resolve(homedir(), ".arouter");
15
+
16
+ // Ensure data dir exists
17
+ if (!existsSync(DATA_DIR)) mkdirSync(DATA_DIR, { recursive: true });
18
+
19
+ // Files in data dir
20
+ export const PID_FILE = resolve(DATA_DIR, "arouter.pid");
21
+ export const LOG_FILE = resolve(DATA_DIR, "arouter.log");
22
+ export const PORT = 20129;
23
+ export const DASHBOARD_URL = `http://localhost:${PORT}`;
package/bin/paths.mjs ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { resolve, dirname } from "path";
4
+ import { fileURLToPath } from "url";
5
+ import { homedir } from "os";
6
+ import { existsSync, mkdirSync } from "fs";
7
+
8
+ const __dirname = dirname(fileURLToPath(import.meta.url));
9
+
10
+ // Project root (where package.json lives)
11
+ export const PROJECT_ROOT = resolve(__dirname, "..");
12
+
13
+ // User data directory (~/.arouter/)
14
+ export const DATA_DIR = resolve(homedir(), ".arouter");
15
+
16
+ // Ensure data dir exists
17
+ if (!existsSync(DATA_DIR)) mkdirSync(DATA_DIR, { recursive: true });
18
+
19
+ // Files in data dir
20
+ export const PID_FILE = resolve(DATA_DIR, "arouter.pid");
21
+ export const LOG_FILE = resolve(DATA_DIR, "arouter.log");
22
+ export const PORT = 20129;
23
+ export const DASHBOARD_URL = `http://localhost:${PORT}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thangnm.nip/arouter",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "aRouter",
5
5
  "bin": {
6
6
  "arouter": "./bin/arouter.mjs"
@@ -117,16 +117,15 @@ function setupMacOS() {
117
117
  log(`✅ User service started (arouter UI)`);
118
118
 
119
119
  // 2. LaunchDaemon for MITM Server (System space - needs root)
120
- // We write it to a temp file, then ask macOS to move it to /Library/LaunchDaemons
121
- const mitmPlistName = 'com.arouter.mitm.plist';
122
- const mitmTmpPath = path.join(os.tmpdir(), mitmPlistName);
123
- const mitmDaemonPath = `/Library/LaunchDaemons/${mitmPlistName}`;
124
-
125
120
  if (!fs.existsSync(mitmServerPath)) {
126
- warn(`MITM server not found at: ${mitmServerPath}. Skipping MITM startup.`);
121
+ warn(`MITM server not found at: ${mitmServerPath}. Skipping MITM LaunchDaemon setup.`);
127
122
  return;
128
123
  }
129
124
 
125
+ const mitmPlistName = 'com.arouter.mitm.plist';
126
+ const mitmTmpPath = path.join(os.tmpdir(), mitmPlistName);
127
+ const mitmSystemPath = `/Library/LaunchDaemons/${mitmPlistName}`;
128
+
130
129
  const mitmPlist = `<?xml version="1.0" encoding="UTF-8"?>
131
130
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
132
131
  <plist version="1.0">
@@ -144,11 +143,11 @@ function setupMacOS() {
144
143
  <string>${os.homedir()}</string>
145
144
  <key>DATA_DIR</key>
146
145
  <string>${path.join(os.homedir(), '.arouter')}</string>
146
+ <key>NODE_ENV</key>
147
+ <string>production</string>
147
148
  </dict>
148
149
  <key>RunAtLoad</key>
149
150
  <true/>
150
- <key>KeepAlive</key>
151
- <true/>
152
151
  <key>StandardOutPath</key>
153
152
  <string>${path.join(logDir, 'mitm.startup.log')}</string>
154
153
  <key>StandardErrorPath</key>
@@ -157,21 +156,20 @@ function setupMacOS() {
157
156
  </plist>`;
158
157
 
159
158
  fs.writeFileSync(mitmTmpPath, mitmPlist, 'utf8');
160
-
161
- log('Requesting Administrator privileges to install MITM LaunchDaemon (auto-bind port 443)...');
162
- const commands = [
163
- `mkdir -p /Library/LaunchDaemons`,
164
- `mv "${mitmTmpPath}" "${mitmDaemonPath}"`,
165
- `chown root:wheel "${mitmDaemonPath}"`,
166
- `chmod 644 "${mitmDaemonPath}"`,
167
- `launchctl unload "${mitmDaemonPath}" || true`,
168
- `launchctl load "${mitmDaemonPath}"`
159
+
160
+ log('Requesting administrator privileges to install MITM LaunchDaemon (port 443 requires root)...');
161
+ const cmds = [
162
+ `cp '${mitmTmpPath}' '${mitmSystemPath}'`,
163
+ `chmod 644 '${mitmSystemPath}'`,
164
+ `chown root:wheel '${mitmSystemPath}'`,
165
+ `launchctl unload '${mitmSystemPath}' 2>/dev/null || true`,
166
+ `launchctl load '${mitmSystemPath}'`
169
167
  ].join(' && ');
170
168
 
171
- if (execElevatedMac(commands)) {
172
- log(`✅ System service started (MITM Server on port 443)`);
169
+ if (execElevatedMac(cmds)) {
170
+ log(`✅ MITM LaunchDaemon installed and started`);
173
171
  } else {
174
- warn('Failed to install MITM LaunchDaemon. You can start it manually or run this setup script as root.');
172
+ warn('Failed to install MITM LaunchDaemon. You can start the MITM server manually from the UI.');
175
173
  }
176
174
  }
177
175
 
@@ -225,8 +223,6 @@ Type=simple
225
223
  Environment="HOME=${os.homedir()}"
226
224
  Environment="DATA_DIR=${path.join(os.homedir(), '.arouter')}"
227
225
  ExecStart=${nodeBin} ${mitmServerPath}
228
- Restart=always
229
- RestartSec=5
230
226
  StandardOutput=append:${path.join(logDir, 'mitm.startup.log')}
231
227
  StandardError=append:${path.join(logDir, 'mitm.startup.error.log')}
232
228
 
@@ -302,7 +298,7 @@ function setupWindows() {
302
298
 
303
299
  log('Requesting Administrator privileges to install MITM scheduled task...');
304
300
  const psCmd = `Start-Process schtasks -ArgumentList '/Create /TN "${mitmTask}" /XML "${mitmXmlPath}" /F' -Verb RunAs -WindowStyle Hidden -Wait`;
305
-
301
+
306
302
  if (execElevatedWindows(psCmd)) {
307
303
  log(`✅ Windows Task Scheduler: Admin task (MITM) created`);
308
304
  } else {