skybridge 0.0.0-dev.f40327b → 0.0.0-dev.f40afe0

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 (214) hide show
  1. package/README.md +1 -0
  2. package/dist/cli/build-helpers.d.ts +10 -0
  3. package/dist/cli/build-helpers.js +93 -0
  4. package/dist/cli/build-helpers.js.map +1 -0
  5. package/dist/cli/build-helpers.test.d.ts +1 -0
  6. package/dist/cli/build-helpers.test.js +89 -0
  7. package/dist/cli/build-helpers.test.js.map +1 -0
  8. package/dist/cli/build-steps.d.ts +2 -0
  9. package/dist/cli/build-steps.js +68 -0
  10. package/dist/cli/build-steps.js.map +1 -0
  11. package/dist/cli/build-steps.test.d.ts +1 -0
  12. package/dist/cli/build-steps.test.js +52 -0
  13. package/dist/cli/build-steps.test.js.map +1 -0
  14. package/dist/cli/detect-port.d.ts +2 -2
  15. package/dist/cli/detect-port.js +9 -20
  16. package/dist/cli/detect-port.js.map +1 -1
  17. package/dist/cli/header.d.ts +1 -1
  18. package/dist/cli/resolve-views-dir.d.ts +1 -0
  19. package/dist/cli/resolve-views-dir.js +17 -0
  20. package/dist/cli/resolve-views-dir.js.map +1 -0
  21. package/dist/cli/run-plain.d.ts +18 -0
  22. package/dist/cli/run-plain.js +89 -0
  23. package/dist/cli/run-plain.js.map +1 -0
  24. package/dist/cli/start-tunnel-view-build.d.ts +1 -0
  25. package/dist/cli/start-tunnel-view-build.js +16 -0
  26. package/dist/cli/start-tunnel-view-build.js.map +1 -0
  27. package/dist/cli/use-execute-steps.d.ts +1 -1
  28. package/dist/cli/use-nodemon.d.ts +14 -0
  29. package/dist/cli/use-nodemon.js +71 -60
  30. package/dist/cli/use-nodemon.js.map +1 -1
  31. package/dist/cli/use-typescript-check.d.ts +8 -2
  32. package/dist/cli/use-typescript-check.js +70 -67
  33. package/dist/cli/use-typescript-check.js.map +1 -1
  34. package/dist/commands/build.d.ts +0 -3
  35. package/dist/commands/build.js +2 -73
  36. package/dist/commands/build.js.map +1 -1
  37. package/dist/commands/dev.d.ts +1 -0
  38. package/dist/commands/dev.js +57 -0
  39. package/dist/commands/dev.js.map +1 -1
  40. package/dist/commands/start.js +7 -1
  41. package/dist/commands/start.js.map +1 -1
  42. package/dist/server/auth/discovery.d.ts +32 -0
  43. package/dist/server/auth/discovery.js +56 -0
  44. package/dist/server/auth/discovery.js.map +1 -0
  45. package/dist/server/auth/discovery.test.d.ts +1 -0
  46. package/dist/server/auth/discovery.test.js +93 -0
  47. package/dist/server/auth/discovery.test.js.map +1 -0
  48. package/dist/server/auth/index.d.ts +18 -0
  49. package/dist/server/auth/index.js +2 -0
  50. package/dist/server/auth/index.js.map +1 -0
  51. package/dist/server/auth/providers/auth0.d.ts +18 -0
  52. package/dist/server/auth/providers/auth0.js +31 -0
  53. package/dist/server/auth/providers/auth0.js.map +1 -0
  54. package/dist/server/auth/providers/auth0.test.d.ts +1 -0
  55. package/dist/server/auth/providers/auth0.test.js +48 -0
  56. package/dist/server/auth/providers/auth0.test.js.map +1 -0
  57. package/dist/server/auth/providers/clerk.d.ts +14 -0
  58. package/dist/server/auth/providers/clerk.js +16 -0
  59. package/dist/server/auth/providers/clerk.js.map +1 -0
  60. package/dist/server/auth/providers/clerk.test.d.ts +1 -0
  61. package/dist/server/auth/providers/clerk.test.js +28 -0
  62. package/dist/server/auth/providers/clerk.test.js.map +1 -0
  63. package/dist/server/auth/providers/custom.d.ts +24 -0
  64. package/dist/server/auth/providers/custom.js +37 -0
  65. package/dist/server/auth/providers/custom.js.map +1 -0
  66. package/dist/server/auth/providers/custom.test.d.ts +1 -0
  67. package/dist/server/auth/providers/custom.test.js +107 -0
  68. package/dist/server/auth/providers/custom.test.js.map +1 -0
  69. package/dist/server/auth/providers/descope.d.ts +15 -0
  70. package/dist/server/auth/providers/descope.js +33 -0
  71. package/dist/server/auth/providers/descope.js.map +1 -0
  72. package/dist/server/auth/providers/descope.test.d.ts +1 -0
  73. package/dist/server/auth/providers/descope.test.js +37 -0
  74. package/dist/server/auth/providers/descope.test.js.map +1 -0
  75. package/dist/server/auth/providers/shared.d.ts +2 -0
  76. package/dist/server/auth/providers/shared.js +6 -0
  77. package/dist/server/auth/providers/shared.js.map +1 -0
  78. package/dist/server/auth/providers/shared.test.d.ts +1 -0
  79. package/dist/server/auth/providers/shared.test.js +10 -0
  80. package/dist/server/auth/providers/shared.test.js.map +1 -0
  81. package/dist/server/auth/providers/stytch.d.ts +12 -0
  82. package/dist/server/auth/providers/stytch.js +13 -0
  83. package/dist/server/auth/providers/stytch.js.map +1 -0
  84. package/dist/server/auth/providers/workos.d.ts +11 -0
  85. package/dist/server/auth/providers/workos.js +12 -0
  86. package/dist/server/auth/providers/workos.js.map +1 -0
  87. package/dist/server/auth/setup.d.ts +4 -0
  88. package/dist/server/auth/setup.js +51 -0
  89. package/dist/server/auth/setup.js.map +1 -0
  90. package/dist/server/auth/setup.test.d.ts +1 -0
  91. package/dist/server/auth/setup.test.js +185 -0
  92. package/dist/server/auth/setup.test.js.map +1 -0
  93. package/dist/server/auth/verify.d.ts +12 -0
  94. package/dist/server/auth/verify.js +38 -0
  95. package/dist/server/auth/verify.js.map +1 -0
  96. package/dist/server/auth/verify.test.d.ts +1 -0
  97. package/dist/server/auth/verify.test.js +100 -0
  98. package/dist/server/auth/verify.test.js.map +1 -0
  99. package/dist/server/build-manifest.test.d.ts +1 -0
  100. package/dist/server/build-manifest.test.js +27 -0
  101. package/dist/server/build-manifest.test.js.map +1 -0
  102. package/dist/server/express.js +3 -0
  103. package/dist/server/express.js.map +1 -1
  104. package/dist/server/express.test.js +61 -0
  105. package/dist/server/express.test.js.map +1 -1
  106. package/dist/server/index.d.ts +9 -2
  107. package/dist/server/index.js +7 -1
  108. package/dist/server/index.js.map +1 -1
  109. package/dist/server/requestOrigin.d.ts +7 -0
  110. package/dist/server/requestOrigin.js +25 -0
  111. package/dist/server/requestOrigin.js.map +1 -0
  112. package/dist/server/server.d.ts +56 -35
  113. package/dist/server/server.js +232 -136
  114. package/dist/server/server.js.map +1 -1
  115. package/dist/server/view-name.test-d.d.ts +1 -0
  116. package/dist/server/view-name.test-d.js +8 -0
  117. package/dist/server/view-name.test-d.js.map +1 -0
  118. package/dist/server/view-resource-resolution.test.d.ts +6 -0
  119. package/dist/server/view-resource-resolution.test.js +207 -0
  120. package/dist/server/view-resource-resolution.test.js.map +1 -0
  121. package/dist/test/view.test.js +69 -101
  122. package/dist/test/view.test.js.map +1 -1
  123. package/dist/web/bridges/adaptor.d.ts +51 -0
  124. package/dist/web/bridges/adaptor.js +330 -0
  125. package/dist/web/bridges/adaptor.js.map +1 -0
  126. package/dist/web/bridges/adaptor.test.d.ts +1 -0
  127. package/dist/web/bridges/adaptor.test.js +208 -0
  128. package/dist/web/bridges/adaptor.test.js.map +1 -0
  129. package/dist/web/bridges/apps-sdk/bridge.d.ts +6 -2
  130. package/dist/web/bridges/apps-sdk/bridge.js +15 -4
  131. package/dist/web/bridges/apps-sdk/bridge.js.map +1 -1
  132. package/dist/web/bridges/apps-sdk/index.d.ts +0 -1
  133. package/dist/web/bridges/apps-sdk/index.js +0 -1
  134. package/dist/web/bridges/apps-sdk/index.js.map +1 -1
  135. package/dist/web/bridges/get-adaptor.d.ts +4 -4
  136. package/dist/web/bridges/get-adaptor.js +6 -11
  137. package/dist/web/bridges/get-adaptor.js.map +1 -1
  138. package/dist/web/bridges/get-adaptor.test.d.ts +1 -0
  139. package/dist/web/bridges/get-adaptor.test.js +32 -0
  140. package/dist/web/bridges/get-adaptor.test.js.map +1 -0
  141. package/dist/web/bridges/mcp-app/bridge.d.ts +15 -3
  142. package/dist/web/bridges/mcp-app/bridge.js +68 -5
  143. package/dist/web/bridges/mcp-app/bridge.js.map +1 -1
  144. package/dist/web/bridges/mcp-app/bridge.test.d.ts +1 -0
  145. package/dist/web/bridges/mcp-app/bridge.test.js +17 -0
  146. package/dist/web/bridges/mcp-app/bridge.test.js.map +1 -0
  147. package/dist/web/bridges/mcp-app/index.d.ts +0 -1
  148. package/dist/web/bridges/mcp-app/index.js +0 -1
  149. package/dist/web/bridges/mcp-app/index.js.map +1 -1
  150. package/dist/web/bridges/mcp-app/view-tools.test.d.ts +1 -0
  151. package/dist/web/bridges/mcp-app/view-tools.test.js +143 -0
  152. package/dist/web/bridges/mcp-app/view-tools.test.js.map +1 -0
  153. package/dist/web/bridges/types.d.ts +44 -1
  154. package/dist/web/bridges/types.js +14 -1
  155. package/dist/web/bridges/types.js.map +1 -1
  156. package/dist/web/bridges/types.test.d.ts +1 -0
  157. package/dist/web/bridges/types.test.js +19 -0
  158. package/dist/web/bridges/types.test.js.map +1 -0
  159. package/dist/web/components/modal-provider.d.ts +1 -1
  160. package/dist/web/components/modal-provider.js +4 -3
  161. package/dist/web/components/modal-provider.js.map +1 -1
  162. package/dist/web/create-store.test.js +8 -5
  163. package/dist/web/create-store.test.js.map +1 -1
  164. package/dist/web/data-llm.d.ts +1 -1
  165. package/dist/web/data-llm.test.js +17 -5
  166. package/dist/web/data-llm.test.js.map +1 -1
  167. package/dist/web/generate-helpers.test-d.js +4 -2
  168. package/dist/web/generate-helpers.test-d.js.map +1 -1
  169. package/dist/web/hooks/index.d.ts +1 -0
  170. package/dist/web/hooks/index.js +1 -0
  171. package/dist/web/hooks/index.js.map +1 -1
  172. package/dist/web/hooks/use-call-tool.test.js +37 -23
  173. package/dist/web/hooks/use-call-tool.test.js.map +1 -1
  174. package/dist/web/hooks/use-display-mode.test.js +56 -20
  175. package/dist/web/hooks/use-display-mode.test.js.map +1 -1
  176. package/dist/web/hooks/use-download.test.js +11 -3
  177. package/dist/web/hooks/use-download.test.js.map +1 -1
  178. package/dist/web/hooks/use-files.test.js +10 -2
  179. package/dist/web/hooks/use-files.test.js.map +1 -1
  180. package/dist/web/hooks/use-layout.test.js +59 -26
  181. package/dist/web/hooks/use-layout.test.js.map +1 -1
  182. package/dist/web/hooks/use-open-external.test.js +13 -3
  183. package/dist/web/hooks/use-open-external.test.js.map +1 -1
  184. package/dist/web/hooks/use-register-view-tool.d.ts +38 -0
  185. package/dist/web/hooks/use-register-view-tool.js +50 -0
  186. package/dist/web/hooks/use-register-view-tool.js.map +1 -0
  187. package/dist/web/hooks/use-request-close.test.js +35 -40
  188. package/dist/web/hooks/use-request-close.test.js.map +1 -1
  189. package/dist/web/hooks/use-request-modal.test.js +10 -0
  190. package/dist/web/hooks/use-request-modal.test.js.map +1 -1
  191. package/dist/web/hooks/use-request-size.test.js +35 -53
  192. package/dist/web/hooks/use-request-size.test.js.map +1 -1
  193. package/dist/web/hooks/use-set-open-in-app-url.test.js +28 -8
  194. package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -1
  195. package/dist/web/hooks/use-tool-info.d.ts +25 -7
  196. package/dist/web/hooks/use-tool-info.js +5 -8
  197. package/dist/web/hooks/use-tool-info.js.map +1 -1
  198. package/dist/web/hooks/use-tool-info.test-d.js +11 -29
  199. package/dist/web/hooks/use-tool-info.test-d.js.map +1 -1
  200. package/dist/web/hooks/use-tool-info.test.js +42 -32
  201. package/dist/web/hooks/use-tool-info.test.js.map +1 -1
  202. package/dist/web/hooks/use-user.test.js +81 -35
  203. package/dist/web/hooks/use-user.test.js.map +1 -1
  204. package/dist/web/hooks/use-view-state.test.js +6 -2
  205. package/dist/web/hooks/use-view-state.test.js.map +1 -1
  206. package/dist/web/plugin/plugin.js +0 -1
  207. package/dist/web/plugin/plugin.js.map +1 -1
  208. package/package.json +22 -19
  209. package/dist/web/bridges/apps-sdk/adaptor.d.ts +0 -28
  210. package/dist/web/bridges/apps-sdk/adaptor.js +0 -113
  211. package/dist/web/bridges/apps-sdk/adaptor.js.map +0 -1
  212. package/dist/web/bridges/mcp-app/adaptor.d.ts +0 -52
  213. package/dist/web/bridges/mcp-app/adaptor.js +0 -280
  214. package/dist/web/bridges/mcp-app/adaptor.js.map +0 -1
@@ -0,0 +1,89 @@
1
+ import { startNodemon } from "./use-nodemon.js";
2
+ import { startTypeScriptCheck } from "./use-typescript-check.js";
3
+ // Banner/URLs/diagnostics go to stderr so a downstream pipe (e.g.
4
+ // `skybridge dev --plain | bunyan`) only ever sees the server's own stdout.
5
+ function info(message) {
6
+ process.stderr.write(`${message}\n`);
7
+ }
8
+ function describeTunnel(state, port) {
9
+ switch (state.status) {
10
+ case "starting":
11
+ return `🌍 ${state.message}`;
12
+ case "connected":
13
+ return `🌍 Exposed on ${state.url}/mcp\n→ Test with an LLM on Playground: ${state.url}/try`;
14
+ case "error":
15
+ return `🌍 Cannot open tunnel: ${state.message}\n→ Try manually: npx alpic tunnel --port ${port}`;
16
+ default:
17
+ return "";
18
+ }
19
+ }
20
+ /**
21
+ * Run `skybridge dev` without the Ink UI. The server's stdout is forwarded
22
+ * verbatim to the real stdout so it can be piped through a formatter
23
+ * (`skybridge dev --plain | bunyan`); everything else (banner, URLs, tunnel
24
+ * state, TypeScript errors, restarts) is written to stderr.
25
+ *
26
+ * Returns a cleanup function that tears down nodemon and the tsc watcher.
27
+ */
28
+ export function runPlain(options) {
29
+ const { env, port, fallback, version, tunnel, tunnelManager } = options;
30
+ // If the downstream formatter (e.g. `| bunyan`) exits, the next write raises
31
+ // EPIPE. Swallow it so a closed pipe doesn't crash the dev server.
32
+ const ignoreEpipe = (err) => {
33
+ if (err.code !== "EPIPE") {
34
+ throw err;
35
+ }
36
+ };
37
+ process.stdout.on("error", ignoreEpipe);
38
+ process.stderr.on("error", ignoreEpipe);
39
+ info(`⛰ Skybridge v${version}`);
40
+ info(fallback
41
+ ? `🏠 3000 in use, running on http://localhost:${port}/mcp`
42
+ : `🏠 Running on http://localhost:${port}/mcp`);
43
+ info(`→ Test locally with DevTools: http://localhost:${port}/`);
44
+ if (!tunnel) {
45
+ info("🌍 Get a public URL and LLM Playground access with --tunnel.");
46
+ }
47
+ const stopNodemon = startNodemon(env, {
48
+ onStdout: (chunk) => process.stdout.write(chunk),
49
+ onStderr: (message) => info(message),
50
+ onRestart: (files) => info(`✓ Server restarted due to file changes: ${files.join(", ")}`),
51
+ });
52
+ let lastTsErrorKey = "";
53
+ const stopTypeScriptCheck = startTypeScriptCheck((errors) => {
54
+ // tsc re-emits on every save; only print when the error set actually changes.
55
+ const key = errors
56
+ .map((e) => `${e.file}:${e.line}:${e.col}:${e.message}`)
57
+ .join("|");
58
+ if (key === lastTsErrorKey) {
59
+ return;
60
+ }
61
+ lastTsErrorKey = key;
62
+ if (errors.length === 0) {
63
+ return;
64
+ }
65
+ info("⚠️ TypeScript errors found:");
66
+ for (const error of errors) {
67
+ info(` ${error.file}(${error.line},${error.col}): ${error.message}`);
68
+ }
69
+ });
70
+ const unsubscribeTunnel = tunnel
71
+ ? tunnelManager.subscribe((state) => {
72
+ const message = describeTunnel(state, port);
73
+ if (message) {
74
+ info(message);
75
+ }
76
+ })
77
+ : () => { };
78
+ if (tunnel) {
79
+ tunnelManager.start();
80
+ }
81
+ return () => {
82
+ unsubscribeTunnel();
83
+ stopNodemon();
84
+ stopTypeScriptCheck();
85
+ process.stdout.off("error", ignoreEpipe);
86
+ process.stderr.off("error", ignoreEpipe);
87
+ };
88
+ }
89
+ //# sourceMappingURL=run-plain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-plain.js","sourceRoot":"","sources":["../../src/cli/run-plain.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TunnelManager, TunnelState } from \"./tunnel.js\";\nimport { startNodemon } from \"./use-nodemon.js\";\nimport { startTypeScriptCheck, type TsError } from \"./use-typescript-check.js\";\n\nexport interface RunPlainOptions {\n env: NodeJS.ProcessEnv;\n port: number;\n fallback: boolean;\n version: string;\n tunnel: boolean;\n tunnelManager: TunnelManager;\n}\n\n// Banner/URLs/diagnostics go to stderr so a downstream pipe (e.g.\n// `skybridge dev --plain | bunyan`) only ever sees the server's own stdout.\nfunction info(message: string): void {\n process.stderr.write(`${message}\\n`);\n}\n\nfunction describeTunnel(state: TunnelState, port: number): string {\n switch (state.status) {\n case \"starting\":\n return `🌍 ${state.message}`;\n case \"connected\":\n return `🌍 Exposed on ${state.url}/mcp\\n→ Test with an LLM on Playground: ${state.url}/try`;\n case \"error\":\n return `🌍 Cannot open tunnel: ${state.message}\\n→ Try manually: npx alpic tunnel --port ${port}`;\n default:\n return \"\";\n }\n}\n\n/**\n * Run `skybridge dev` without the Ink UI. The server's stdout is forwarded\n * verbatim to the real stdout so it can be piped through a formatter\n * (`skybridge dev --plain | bunyan`); everything else (banner, URLs, tunnel\n * state, TypeScript errors, restarts) is written to stderr.\n *\n * Returns a cleanup function that tears down nodemon and the tsc watcher.\n */\nexport function runPlain(options: RunPlainOptions): () => void {\n const { env, port, fallback, version, tunnel, tunnelManager } = options;\n\n // If the downstream formatter (e.g. `| bunyan`) exits, the next write raises\n // EPIPE. Swallow it so a closed pipe doesn't crash the dev server.\n const ignoreEpipe = (err: NodeJS.ErrnoException) => {\n if (err.code !== \"EPIPE\") {\n throw err;\n }\n };\n process.stdout.on(\"error\", ignoreEpipe);\n process.stderr.on(\"error\", ignoreEpipe);\n\n info(`⛰ Skybridge v${version}`);\n info(\n fallback\n ? `🏠 3000 in use, running on http://localhost:${port}/mcp`\n : `🏠 Running on http://localhost:${port}/mcp`,\n );\n info(`→ Test locally with DevTools: http://localhost:${port}/`);\n if (!tunnel) {\n info(\"🌍 Get a public URL and LLM Playground access with --tunnel.\");\n }\n\n const stopNodemon = startNodemon(env, {\n onStdout: (chunk) => process.stdout.write(chunk),\n onStderr: (message) => info(message),\n onRestart: (files) =>\n info(`✓ Server restarted due to file changes: ${files.join(\", \")}`),\n });\n\n let lastTsErrorKey = \"\";\n const stopTypeScriptCheck = startTypeScriptCheck((errors: Array<TsError>) => {\n // tsc re-emits on every save; only print when the error set actually changes.\n const key = errors\n .map((e) => `${e.file}:${e.line}:${e.col}:${e.message}`)\n .join(\"|\");\n if (key === lastTsErrorKey) {\n return;\n }\n lastTsErrorKey = key;\n if (errors.length === 0) {\n return;\n }\n info(\"⚠️ TypeScript errors found:\");\n for (const error of errors) {\n info(` ${error.file}(${error.line},${error.col}): ${error.message}`);\n }\n });\n\n const unsubscribeTunnel = tunnel\n ? tunnelManager.subscribe((state) => {\n const message = describeTunnel(state, port);\n if (message) {\n info(message);\n }\n })\n : () => {};\n\n if (tunnel) {\n tunnelManager.start();\n }\n\n return () => {\n unsubscribeTunnel();\n stopNodemon();\n stopTypeScriptCheck();\n process.stdout.off(\"error\", ignoreEpipe);\n process.stderr.off(\"error\", ignoreEpipe);\n };\n}\n"]}
@@ -0,0 +1 @@
1
+ export declare function startTunnelViewBuild(root?: string): void;
@@ -0,0 +1,16 @@
1
+ import path from "node:path";
2
+ export function startTunnelViewBuild(root = process.cwd()) {
3
+ void (async () => {
4
+ const { build } = await import("vite");
5
+ await build({
6
+ root,
7
+ configFile: path.join(root, "vite.config.ts"),
8
+ mode: "development",
9
+ logLevel: "warn",
10
+ build: { watch: {}, minify: false },
11
+ });
12
+ })().catch((err) => {
13
+ console.error("skybridge: tunnel view build failed", err);
14
+ });
15
+ }
16
+ //# sourceMappingURL=start-tunnel-view-build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-tunnel-view-build.js","sourceRoot":"","sources":["../../src/cli/start-tunnel-view-build.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,UAAU,oBAAoB,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE;IACvD,KAAK,CAAC,KAAK,IAAI,EAAE;QACf,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,KAAK,CAAC;YACV,IAAI;YACJ,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,gBAAgB,CAAC;YAC7C,IAAI,EAAE,aAAa;YACnB,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE;SACpC,CAAC,CAAC;IACL,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACjB,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,GAAG,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import path from \"node:path\";\n\nexport function startTunnelViewBuild(root = process.cwd()): void {\n void (async () => {\n const { build } = await import(\"vite\");\n await build({\n root,\n configFile: path.join(root, \"vite.config.ts\"),\n mode: \"development\",\n logLevel: \"warn\",\n build: { watch: {}, minify: false },\n });\n })().catch((err) => {\n console.error(\"skybridge: tunnel view build failed\", err);\n });\n}\n"]}
@@ -5,7 +5,7 @@ export interface CommandStep {
5
5
  }
6
6
  export declare const useExecuteSteps: (steps: CommandStep[]) => {
7
7
  currentStep: number;
8
- status: "error" | "success" | "running";
8
+ status: "error" | "running" | "success";
9
9
  error: string | null;
10
10
  execute: () => Promise<void>;
11
11
  };
@@ -1,2 +1,16 @@
1
1
  import type { PushMessage } from "./use-messages.js";
2
+ export interface NodemonHandlers {
3
+ /** A raw chunk of server stdout, forwarded untouched. */
4
+ onStdout: (chunk: Buffer) => void;
5
+ /** A (filtered) chunk of server stderr. */
6
+ onStderr: (message: string) => void;
7
+ /** The server restarted because the listed files changed. */
8
+ onRestart: (files: string[]) => void;
9
+ }
10
+ /**
11
+ * Boot nodemon and wire its stdout/stderr to the provided handlers. Returns a
12
+ * cleanup function that detaches the listeners and quits nodemon. Shared by the
13
+ * Ink-based dev UI (via {@link useNodemon}) and the `--plain` runner.
14
+ */
15
+ export declare function startNodemon(env: NodeJS.ProcessEnv, handlers: NodemonHandlers): () => void;
2
16
  export declare function useNodemon(env: NodeJS.ProcessEnv, pushMessage: PushMessage): void;
@@ -4,70 +4,81 @@ import nodemonOriginal from "nodemon";
4
4
  import { useEffect } from "react";
5
5
  const nodemon = nodemonOriginal;
6
6
  const SOURCEMAP_WARNING = /^Sourcemap for ".*" points to missing source files$/;
7
+ /**
8
+ * Boot nodemon and wire its stdout/stderr to the provided handlers. Returns a
9
+ * cleanup function that detaches the listeners and quits nodemon. Shared by the
10
+ * Ink-based dev UI (via {@link useNodemon}) and the `--plain` runner.
11
+ */
12
+ export function startNodemon(env, handlers) {
13
+ const configFile = resolve(process.cwd(), "nodemon.json");
14
+ const config = existsSync(configFile)
15
+ ? {
16
+ configFile,
17
+ }
18
+ : {
19
+ watch: ["src"],
20
+ ext: "ts,json",
21
+ exec: "tsx src/server.ts",
22
+ };
23
+ nodemon({ ...config, env, stdout: false });
24
+ const handleStdoutData = (chunk) => {
25
+ handlers.onStdout(chunk);
26
+ };
27
+ const handleStderrData = (chunk) => {
28
+ const message = chunk.toString().trim();
29
+ if (!message) {
30
+ return;
31
+ }
32
+ // Node's source-map warnings for third-party deps (superjson, @mcp/sdk, …) — not actionable.
33
+ const filtered = message
34
+ .split("\n")
35
+ .filter((line) => !SOURCEMAP_WARNING.test(line))
36
+ .join("\n");
37
+ if (filtered) {
38
+ handlers.onStderr(filtered);
39
+ }
40
+ };
41
+ const setupStdoutListener = () => {
42
+ if (nodemon.stdout) {
43
+ nodemon.stdout.off("data", handleStdoutData);
44
+ nodemon.stdout.on("data", handleStdoutData);
45
+ }
46
+ };
47
+ const setupStderrListener = () => {
48
+ if (nodemon.stderr) {
49
+ nodemon.stderr.off("data", handleStderrData);
50
+ nodemon.stderr.on("data", handleStderrData);
51
+ }
52
+ };
53
+ nodemon.on("readable", () => {
54
+ setupStdoutListener();
55
+ setupStderrListener();
56
+ });
57
+ nodemon.on("restart", (files) => {
58
+ handlers.onRestart(files);
59
+ setupStdoutListener();
60
+ setupStderrListener();
61
+ });
62
+ return () => {
63
+ if (nodemon.stdout) {
64
+ nodemon.stdout.off("data", handleStdoutData);
65
+ }
66
+ if (nodemon.stderr) {
67
+ nodemon.stderr.off("data", handleStderrData);
68
+ }
69
+ nodemon.emit("quit");
70
+ };
71
+ }
7
72
  export function useNodemon(env, pushMessage) {
8
- useEffect(() => {
9
- const configFile = resolve(process.cwd(), "nodemon.json");
10
- const config = existsSync(configFile)
11
- ? {
12
- configFile,
13
- }
14
- : {
15
- watch: ["src"],
16
- ext: "ts,json",
17
- exec: "tsx src/server.ts",
18
- };
19
- nodemon({ ...config, env, stdout: false });
20
- const handleStdoutData = (chunk) => {
73
+ useEffect(() => startNodemon(env, {
74
+ onStdout: (chunk) => {
21
75
  const message = chunk.toString().trim();
22
76
  if (message) {
23
77
  pushMessage(message, "log");
24
78
  }
25
- };
26
- const handleStderrData = (chunk) => {
27
- const message = chunk.toString().trim();
28
- if (!message) {
29
- return;
30
- }
31
- // Node's source-map warnings for third-party deps (superjson, @mcp/sdk, …) — not actionable.
32
- const filtered = message
33
- .split("\n")
34
- .filter((line) => !SOURCEMAP_WARNING.test(line))
35
- .join("\n");
36
- if (filtered) {
37
- pushMessage(filtered, "error");
38
- }
39
- };
40
- const setupStdoutListener = () => {
41
- if (nodemon.stdout) {
42
- nodemon.stdout.off("data", handleStdoutData);
43
- nodemon.stdout.on("data", handleStdoutData);
44
- }
45
- };
46
- const setupStderrListener = () => {
47
- if (nodemon.stderr) {
48
- nodemon.stderr.off("data", handleStderrData);
49
- nodemon.stderr.on("data", handleStderrData);
50
- }
51
- };
52
- nodemon.on("readable", () => {
53
- setupStdoutListener();
54
- setupStderrListener();
55
- });
56
- nodemon.on("restart", (files) => {
57
- const restartMessage = `Server restarted due to file changes: ${files.join(", ")}`;
58
- pushMessage(restartMessage, "restart");
59
- setupStdoutListener();
60
- setupStderrListener();
61
- });
62
- return () => {
63
- if (nodemon.stdout) {
64
- nodemon.stdout.off("data", handleStdoutData);
65
- }
66
- if (nodemon.stderr) {
67
- nodemon.stderr.off("data", handleStderrData);
68
- }
69
- nodemon.emit("quit");
70
- };
71
- }, [env, pushMessage]);
79
+ },
80
+ onStderr: (message) => pushMessage(message, "error"),
81
+ onRestart: (files) => pushMessage(`Server restarted due to file changes: ${files.join(", ")}`, "restart"),
82
+ }), [env, pushMessage]);
72
83
  }
73
84
  //# sourceMappingURL=use-nodemon.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-nodemon.js","sourceRoot":"","sources":["../../src/cli/use-nodemon.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport nodemonOriginal from \"nodemon\";\nimport { useEffect } from \"react\";\nimport type { ExtendedNodemon } from \"./nodemon.d.ts\";\nimport type { PushMessage } from \"./use-messages.js\";\n\nconst nodemon = nodemonOriginal as ExtendedNodemon;\n\nconst SOURCEMAP_WARNING = /^Sourcemap for \".*\" points to missing source files$/;\n\nexport function useNodemon(\n env: NodeJS.ProcessEnv,\n pushMessage: PushMessage,\n): void {\n useEffect(() => {\n const configFile = resolve(process.cwd(), \"nodemon.json\");\n\n const config = existsSync(configFile)\n ? {\n configFile,\n }\n : {\n watch: [\"src\"],\n ext: \"ts,json\",\n exec: \"tsx src/server.ts\",\n };\n\n nodemon({ ...config, env, stdout: false });\n\n const handleStdoutData = (chunk: Buffer) => {\n const message = chunk.toString().trim();\n if (message) {\n pushMessage(message, \"log\");\n }\n };\n\n const handleStderrData = (chunk: Buffer) => {\n const message = chunk.toString().trim();\n if (!message) {\n return;\n }\n // Node's source-map warnings for third-party deps (superjson, @mcp/sdk, …) — not actionable.\n const filtered = message\n .split(\"\\n\")\n .filter((line) => !SOURCEMAP_WARNING.test(line))\n .join(\"\\n\");\n if (filtered) {\n pushMessage(filtered, \"error\");\n }\n };\n\n const setupStdoutListener = () => {\n if (nodemon.stdout) {\n nodemon.stdout.off(\"data\", handleStdoutData);\n nodemon.stdout.on(\"data\", handleStdoutData);\n }\n };\n\n const setupStderrListener = () => {\n if (nodemon.stderr) {\n nodemon.stderr.off(\"data\", handleStderrData);\n nodemon.stderr.on(\"data\", handleStderrData);\n }\n };\n\n nodemon.on(\"readable\", () => {\n setupStdoutListener();\n setupStderrListener();\n });\n\n nodemon.on(\"restart\", (files: string[]) => {\n const restartMessage = `Server restarted due to file changes: ${files.join(\", \")}`;\n pushMessage(restartMessage, \"restart\");\n setupStdoutListener();\n setupStderrListener();\n });\n\n return () => {\n if (nodemon.stdout) {\n nodemon.stdout.off(\"data\", handleStdoutData);\n }\n if (nodemon.stderr) {\n nodemon.stderr.off(\"data\", handleStderrData);\n }\n nodemon.emit(\"quit\");\n };\n }, [env, pushMessage]);\n}\n"]}
1
+ {"version":3,"file":"use-nodemon.js","sourceRoot":"","sources":["../../src/cli/use-nodemon.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport nodemonOriginal from \"nodemon\";\nimport { useEffect } from \"react\";\nimport type { ExtendedNodemon } from \"./nodemon.d.ts\";\nimport type { PushMessage } from \"./use-messages.js\";\n\nconst nodemon = nodemonOriginal as ExtendedNodemon;\n\nconst SOURCEMAP_WARNING = /^Sourcemap for \".*\" points to missing source files$/;\n\nexport interface NodemonHandlers {\n /** A raw chunk of server stdout, forwarded untouched. */\n onStdout: (chunk: Buffer) => void;\n /** A (filtered) chunk of server stderr. */\n onStderr: (message: string) => void;\n /** The server restarted because the listed files changed. */\n onRestart: (files: string[]) => void;\n}\n\n/**\n * Boot nodemon and wire its stdout/stderr to the provided handlers. Returns a\n * cleanup function that detaches the listeners and quits nodemon. Shared by the\n * Ink-based dev UI (via {@link useNodemon}) and the `--plain` runner.\n */\nexport function startNodemon(\n env: NodeJS.ProcessEnv,\n handlers: NodemonHandlers,\n): () => void {\n const configFile = resolve(process.cwd(), \"nodemon.json\");\n\n const config = existsSync(configFile)\n ? {\n configFile,\n }\n : {\n watch: [\"src\"],\n ext: \"ts,json\",\n exec: \"tsx src/server.ts\",\n };\n\n nodemon({ ...config, env, stdout: false });\n\n const handleStdoutData = (chunk: Buffer) => {\n handlers.onStdout(chunk);\n };\n\n const handleStderrData = (chunk: Buffer) => {\n const message = chunk.toString().trim();\n if (!message) {\n return;\n }\n // Node's source-map warnings for third-party deps (superjson, @mcp/sdk, …) — not actionable.\n const filtered = message\n .split(\"\\n\")\n .filter((line) => !SOURCEMAP_WARNING.test(line))\n .join(\"\\n\");\n if (filtered) {\n handlers.onStderr(filtered);\n }\n };\n\n const setupStdoutListener = () => {\n if (nodemon.stdout) {\n nodemon.stdout.off(\"data\", handleStdoutData);\n nodemon.stdout.on(\"data\", handleStdoutData);\n }\n };\n\n const setupStderrListener = () => {\n if (nodemon.stderr) {\n nodemon.stderr.off(\"data\", handleStderrData);\n nodemon.stderr.on(\"data\", handleStderrData);\n }\n };\n\n nodemon.on(\"readable\", () => {\n setupStdoutListener();\n setupStderrListener();\n });\n\n nodemon.on(\"restart\", (files: string[]) => {\n handlers.onRestart(files);\n setupStdoutListener();\n setupStderrListener();\n });\n\n return () => {\n if (nodemon.stdout) {\n nodemon.stdout.off(\"data\", handleStdoutData);\n }\n if (nodemon.stderr) {\n nodemon.stderr.off(\"data\", handleStderrData);\n }\n nodemon.emit(\"quit\");\n };\n}\n\nexport function useNodemon(\n env: NodeJS.ProcessEnv,\n pushMessage: PushMessage,\n): void {\n useEffect(\n () =>\n startNodemon(env, {\n onStdout: (chunk) => {\n const message = chunk.toString().trim();\n if (message) {\n pushMessage(message, \"log\");\n }\n },\n onStderr: (message) => pushMessage(message, \"error\"),\n onRestart: (files) =>\n pushMessage(\n `Server restarted due to file changes: ${files.join(\", \")}`,\n \"restart\",\n ),\n }),\n [env, pushMessage],\n );\n}\n"]}
@@ -1,9 +1,15 @@
1
- type TsError = {
1
+ export type TsError = {
2
2
  file: string;
3
3
  line: number;
4
4
  col: number;
5
5
  code: string;
6
6
  message: string;
7
7
  };
8
+ /**
9
+ * Spawn `tsc --noEmit --watch` and report each completed check via `onErrors`
10
+ * (empty array when the check is clean). Returns a cleanup function that kills
11
+ * the watcher. Shared by the Ink-based dev UI (via {@link useTypeScriptCheck})
12
+ * and the `--plain` runner.
13
+ */
14
+ export declare function startTypeScriptCheck(onErrors: (errors: Array<TsError>) => void): () => void;
8
15
  export declare function useTypeScriptCheck(): Array<TsError>;
9
- export {};
@@ -1,6 +1,6 @@
1
1
  import { isAbsolute, relative } from "node:path";
2
2
  import spawn from "cross-spawn";
3
- import { useEffect, useRef, useState } from "react";
3
+ import { useEffect, useState } from "react";
4
4
  // TypeScript nests from general to specific — the deepest line is the root cause.
5
5
  function extractBestMessage(message, continuationLines) {
6
6
  if (!continuationLines.length) {
@@ -19,76 +19,79 @@ function extractBestMessage(message, continuationLines) {
19
19
  .filter(Boolean)[0];
20
20
  return deepest ?? message;
21
21
  }
22
- export function useTypeScriptCheck() {
23
- const tsProcessRef = useRef(null);
24
- const [tsErrors, setTsErrors] = useState([]);
25
- useEffect(() => {
26
- const tsProcess = spawn("npx", ["tsc", "--noEmit", "--watch", "--pretty", "false"], {
27
- stdio: ["ignore", "pipe", "pipe"],
28
- shell: true,
29
- });
30
- tsProcessRef.current = tsProcess;
31
- let outputBuffer = "";
32
- let currentErrors = [];
33
- let pendingError = null;
34
- let continuationLines = [];
35
- const flushPending = () => {
36
- if (!pendingError) {
37
- return;
38
- }
39
- pendingError.message = extractBestMessage(pendingError.message, continuationLines);
40
- currentErrors.push(pendingError);
41
- pendingError = null;
42
- continuationLines = [];
43
- };
44
- const processOutput = (data) => {
45
- outputBuffer += data.toString();
46
- const lines = outputBuffer.split("\n");
47
- outputBuffer = lines.pop() || "";
48
- for (const line of lines) {
49
- const trimmed = line.trim();
50
- const errorMatch = trimmed.match(/^(.+?)\((\d+),(\d+)\):\s+error\s+(TS\d+)?\s*:?\s*(.+)$/);
51
- if (errorMatch) {
52
- flushPending();
53
- const [, file, lineStr, colStr, code, message] = errorMatch;
54
- if (file && lineStr && colStr && message) {
55
- let cleanFile = file.trim();
56
- if (isAbsolute(cleanFile)) {
57
- cleanFile = relative(process.cwd(), cleanFile);
58
- }
59
- pendingError = {
60
- file: cleanFile,
61
- line: Number.parseInt(lineStr, 10),
62
- col: Number.parseInt(colStr, 10),
63
- code: code ?? "",
64
- message: message.trim(),
65
- };
22
+ /**
23
+ * Spawn `tsc --noEmit --watch` and report each completed check via `onErrors`
24
+ * (empty array when the check is clean). Returns a cleanup function that kills
25
+ * the watcher. Shared by the Ink-based dev UI (via {@link useTypeScriptCheck})
26
+ * and the `--plain` runner.
27
+ */
28
+ export function startTypeScriptCheck(onErrors) {
29
+ const tsProcess = spawn("npx", ["tsc", "--noEmit", "--watch", "--pretty", "false"], {
30
+ stdio: ["ignore", "pipe", "pipe"],
31
+ shell: true,
32
+ });
33
+ let outputBuffer = "";
34
+ let currentErrors = [];
35
+ let pendingError = null;
36
+ let continuationLines = [];
37
+ const flushPending = () => {
38
+ if (!pendingError) {
39
+ return;
40
+ }
41
+ pendingError.message = extractBestMessage(pendingError.message, continuationLines);
42
+ currentErrors.push(pendingError);
43
+ pendingError = null;
44
+ continuationLines = [];
45
+ };
46
+ const processOutput = (data) => {
47
+ outputBuffer += data.toString();
48
+ const lines = outputBuffer.split("\n");
49
+ outputBuffer = lines.pop() || "";
50
+ for (const line of lines) {
51
+ const trimmed = line.trim();
52
+ const errorMatch = trimmed.match(/^(.+?)\((\d+),(\d+)\):\s+error\s+(TS\d+)?\s*:?\s*(.+)$/);
53
+ if (errorMatch) {
54
+ flushPending();
55
+ const [, file, lineStr, colStr, code, message] = errorMatch;
56
+ if (file && lineStr && colStr && message) {
57
+ let cleanFile = file.trim();
58
+ if (isAbsolute(cleanFile)) {
59
+ cleanFile = relative(process.cwd(), cleanFile);
66
60
  }
67
- continue;
68
- }
69
- if (pendingError && line.startsWith(" ")) {
70
- continuationLines.push(line);
71
- continue;
72
- }
73
- if (trimmed.includes("Found") && trimmed.includes("error")) {
74
- flushPending();
75
- setTsErrors(trimmed.match(/Found 0 error/) ? [] : [...currentErrors]);
76
- currentErrors = [];
61
+ pendingError = {
62
+ file: cleanFile,
63
+ line: Number.parseInt(lineStr, 10),
64
+ col: Number.parseInt(colStr, 10),
65
+ code: code ?? "",
66
+ message: message.trim(),
67
+ };
77
68
  }
69
+ continue;
78
70
  }
79
- };
80
- if (tsProcess.stdout) {
81
- tsProcess.stdout.on("data", processOutput);
82
- }
83
- if (tsProcess.stderr) {
84
- tsProcess.stderr.on("data", processOutput);
85
- }
86
- return () => {
87
- if (tsProcessRef.current) {
88
- tsProcessRef.current.kill();
71
+ if (pendingError && line.startsWith(" ")) {
72
+ continuationLines.push(line);
73
+ continue;
89
74
  }
90
- };
91
- }, []);
75
+ if (trimmed.includes("Found") && trimmed.includes("error")) {
76
+ flushPending();
77
+ onErrors(trimmed.match(/Found 0 error/) ? [] : [...currentErrors]);
78
+ currentErrors = [];
79
+ }
80
+ }
81
+ };
82
+ if (tsProcess.stdout) {
83
+ tsProcess.stdout.on("data", processOutput);
84
+ }
85
+ if (tsProcess.stderr) {
86
+ tsProcess.stderr.on("data", processOutput);
87
+ }
88
+ return () => {
89
+ tsProcess.kill();
90
+ };
91
+ }
92
+ export function useTypeScriptCheck() {
93
+ const [tsErrors, setTsErrors] = useState([]);
94
+ useEffect(() => startTypeScriptCheck(setTsErrors), []);
92
95
  return tsErrors;
93
96
  }
94
97
  //# sourceMappingURL=use-typescript-check.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-typescript-check.js","sourceRoot":"","sources":["../../src/cli/use-typescript-check.ts"],"names":[],"mappings":"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","sourcesContent":["import { isAbsolute, relative } from \"node:path\";\nimport spawn from \"cross-spawn\";\nimport { useEffect, useRef, useState } from \"react\";\n\ntype TsError = {\n file: string;\n line: number;\n col: number;\n code: string;\n message: string;\n};\n\n// TypeScript nests from general to specific — the deepest line is the root cause.\nfunction extractBestMessage(\n message: string,\n continuationLines: Array<string>,\n): string {\n if (!continuationLines.length) {\n return message;\n }\n let maxIndent = 0;\n for (const line of continuationLines) {\n const indent = line.length - line.trimStart().length;\n if (indent > maxIndent) {\n maxIndent = indent;\n }\n }\n const deepest = continuationLines\n .filter((l) => l.length - l.trimStart().length === maxIndent)\n .map((l) => l.trim())\n .filter(Boolean)[0];\n return deepest ?? message;\n}\n\nexport function useTypeScriptCheck(): Array<TsError> {\n const tsProcessRef = useRef<ReturnType<typeof spawn> | null>(null);\n const [tsErrors, setTsErrors] = useState<Array<TsError>>([]);\n\n useEffect(() => {\n const tsProcess = spawn(\n \"npx\",\n [\"tsc\", \"--noEmit\", \"--watch\", \"--pretty\", \"false\"],\n {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n shell: true,\n },\n );\n\n tsProcessRef.current = tsProcess;\n\n let outputBuffer = \"\";\n let currentErrors: Array<TsError> = [];\n let pendingError: TsError | null = null;\n let continuationLines: Array<string> = [];\n\n const flushPending = () => {\n if (!pendingError) {\n return;\n }\n pendingError.message = extractBestMessage(\n pendingError.message,\n continuationLines,\n );\n currentErrors.push(pendingError);\n pendingError = null;\n continuationLines = [];\n };\n\n const processOutput = (data: Buffer) => {\n outputBuffer += data.toString();\n const lines = outputBuffer.split(\"\\n\");\n outputBuffer = lines.pop() || \"\";\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n const errorMatch = trimmed.match(\n /^(.+?)\\((\\d+),(\\d+)\\):\\s+error\\s+(TS\\d+)?\\s*:?\\s*(.+)$/,\n );\n if (errorMatch) {\n flushPending();\n const [, file, lineStr, colStr, code, message] = errorMatch;\n if (file && lineStr && colStr && message) {\n let cleanFile = file.trim();\n if (isAbsolute(cleanFile)) {\n cleanFile = relative(process.cwd(), cleanFile);\n }\n pendingError = {\n file: cleanFile,\n line: Number.parseInt(lineStr, 10),\n col: Number.parseInt(colStr, 10),\n code: code ?? \"\",\n message: message.trim(),\n };\n }\n continue;\n }\n\n if (pendingError && line.startsWith(\" \")) {\n continuationLines.push(line);\n continue;\n }\n\n if (trimmed.includes(\"Found\") && trimmed.includes(\"error\")) {\n flushPending();\n setTsErrors(trimmed.match(/Found 0 error/) ? [] : [...currentErrors]);\n currentErrors = [];\n }\n }\n };\n\n if (tsProcess.stdout) {\n tsProcess.stdout.on(\"data\", processOutput);\n }\n if (tsProcess.stderr) {\n tsProcess.stderr.on(\"data\", processOutput);\n }\n\n return () => {\n if (tsProcessRef.current) {\n tsProcessRef.current.kill();\n }\n };\n }, []);\n\n return tsErrors;\n}\n"]}
1
+ {"version":3,"file":"use-typescript-check.js","sourceRoot":"","sources":["../../src/cli/use-typescript-check.ts"],"names":[],"mappings":"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","sourcesContent":["import { isAbsolute, relative } from \"node:path\";\nimport spawn from \"cross-spawn\";\nimport { useEffect, useState } from \"react\";\n\nexport type TsError = {\n file: string;\n line: number;\n col: number;\n code: string;\n message: string;\n};\n\n// TypeScript nests from general to specific — the deepest line is the root cause.\nfunction extractBestMessage(\n message: string,\n continuationLines: Array<string>,\n): string {\n if (!continuationLines.length) {\n return message;\n }\n let maxIndent = 0;\n for (const line of continuationLines) {\n const indent = line.length - line.trimStart().length;\n if (indent > maxIndent) {\n maxIndent = indent;\n }\n }\n const deepest = continuationLines\n .filter((l) => l.length - l.trimStart().length === maxIndent)\n .map((l) => l.trim())\n .filter(Boolean)[0];\n return deepest ?? message;\n}\n\n/**\n * Spawn `tsc --noEmit --watch` and report each completed check via `onErrors`\n * (empty array when the check is clean). Returns a cleanup function that kills\n * the watcher. Shared by the Ink-based dev UI (via {@link useTypeScriptCheck})\n * and the `--plain` runner.\n */\nexport function startTypeScriptCheck(\n onErrors: (errors: Array<TsError>) => void,\n): () => void {\n const tsProcess = spawn(\n \"npx\",\n [\"tsc\", \"--noEmit\", \"--watch\", \"--pretty\", \"false\"],\n {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n shell: true,\n },\n );\n\n let outputBuffer = \"\";\n let currentErrors: Array<TsError> = [];\n let pendingError: TsError | null = null;\n let continuationLines: Array<string> = [];\n\n const flushPending = () => {\n if (!pendingError) {\n return;\n }\n pendingError.message = extractBestMessage(\n pendingError.message,\n continuationLines,\n );\n currentErrors.push(pendingError);\n pendingError = null;\n continuationLines = [];\n };\n\n const processOutput = (data: Buffer) => {\n outputBuffer += data.toString();\n const lines = outputBuffer.split(\"\\n\");\n outputBuffer = lines.pop() || \"\";\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n const errorMatch = trimmed.match(\n /^(.+?)\\((\\d+),(\\d+)\\):\\s+error\\s+(TS\\d+)?\\s*:?\\s*(.+)$/,\n );\n if (errorMatch) {\n flushPending();\n const [, file, lineStr, colStr, code, message] = errorMatch;\n if (file && lineStr && colStr && message) {\n let cleanFile = file.trim();\n if (isAbsolute(cleanFile)) {\n cleanFile = relative(process.cwd(), cleanFile);\n }\n pendingError = {\n file: cleanFile,\n line: Number.parseInt(lineStr, 10),\n col: Number.parseInt(colStr, 10),\n code: code ?? \"\",\n message: message.trim(),\n };\n }\n continue;\n }\n\n if (pendingError && line.startsWith(\" \")) {\n continuationLines.push(line);\n continue;\n }\n\n if (trimmed.includes(\"Found\") && trimmed.includes(\"error\")) {\n flushPending();\n onErrors(trimmed.match(/Found 0 error/) ? [] : [...currentErrors]);\n currentErrors = [];\n }\n }\n };\n\n if (tsProcess.stdout) {\n tsProcess.stdout.on(\"data\", processOutput);\n }\n if (tsProcess.stderr) {\n tsProcess.stderr.on(\"data\", processOutput);\n }\n\n return () => {\n tsProcess.kill();\n };\n}\n\nexport function useTypeScriptCheck(): Array<TsError> {\n const [tsErrors, setTsErrors] = useState<Array<TsError>>([]);\n\n useEffect(() => startTypeScriptCheck(setTsErrors), []);\n\n return tsErrors;\n}\n"]}
@@ -1,9 +1,6 @@
1
1
  import { Command } from "@oclif/core";
2
- import { type CommandStep } from "../cli/use-execute-steps.js";
3
- export declare const commandSteps: CommandStep[];
4
2
  export default class Build extends Command {
5
3
  static description: string;
6
4
  static examples: string[];
7
- static flags: {};
8
5
  run(): Promise<void>;
9
6
  }