everything-dev 0.3.3 → 1.3.3

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 (313) hide show
  1. package/README.md +64 -0
  2. package/cli.js +10 -0
  3. package/dist/_virtual/_rolldown/runtime.cjs +29 -0
  4. package/dist/api-contract.cjs +172 -0
  5. package/dist/api-contract.cjs.map +1 -0
  6. package/dist/api-contract.mjs +171 -0
  7. package/dist/api-contract.mjs.map +1 -0
  8. package/dist/api.cjs +124 -0
  9. package/dist/api.cjs.map +1 -0
  10. package/dist/api.d.cts +36 -0
  11. package/dist/api.d.cts.map +1 -0
  12. package/dist/api.d.mts +36 -0
  13. package/dist/api.d.mts.map +1 -0
  14. package/dist/api.mjs +119 -0
  15. package/dist/api.mjs.map +1 -0
  16. package/dist/app.cjs +156 -0
  17. package/dist/app.cjs.map +1 -0
  18. package/dist/app.mjs +153 -0
  19. package/dist/app.mjs.map +1 -0
  20. package/dist/cli/catalog.cjs +30 -0
  21. package/dist/cli/catalog.cjs.map +1 -0
  22. package/dist/cli/catalog.mjs +29 -0
  23. package/dist/cli/catalog.mjs.map +1 -0
  24. package/dist/cli/help.cjs +16 -0
  25. package/dist/cli/help.cjs.map +1 -0
  26. package/dist/cli/help.mjs +16 -0
  27. package/dist/cli/help.mjs.map +1 -0
  28. package/dist/cli/init.cjs +287 -0
  29. package/dist/cli/init.cjs.map +1 -0
  30. package/dist/cli/init.d.cts +36 -0
  31. package/dist/cli/init.d.cts.map +1 -0
  32. package/dist/cli/init.d.mts +36 -0
  33. package/dist/cli/init.d.mts.map +1 -0
  34. package/dist/cli/init.mjs +279 -0
  35. package/dist/cli/init.mjs.map +1 -0
  36. package/dist/cli/parse.cjs +96 -0
  37. package/dist/cli/parse.cjs.map +1 -0
  38. package/dist/cli/parse.mjs +95 -0
  39. package/dist/cli/parse.mjs.map +1 -0
  40. package/dist/cli/prompts.cjs +42 -0
  41. package/dist/cli/prompts.cjs.map +1 -0
  42. package/dist/cli/prompts.mjs +41 -0
  43. package/dist/cli/prompts.mjs.map +1 -0
  44. package/dist/cli.cjs +167 -0
  45. package/dist/cli.cjs.map +1 -0
  46. package/dist/cli.d.cts +1 -0
  47. package/dist/cli.d.mts +1 -0
  48. package/dist/cli.mjs +166 -0
  49. package/dist/cli.mjs.map +1 -0
  50. package/dist/components/dev-view.cjs +307 -0
  51. package/dist/components/dev-view.cjs.map +1 -0
  52. package/dist/components/dev-view.mjs +306 -0
  53. package/dist/components/dev-view.mjs.map +1 -0
  54. package/dist/components/streaming-view.cjs +146 -0
  55. package/dist/components/streaming-view.cjs.map +1 -0
  56. package/dist/components/streaming-view.mjs +144 -0
  57. package/dist/components/streaming-view.mjs.map +1 -0
  58. package/dist/config.cjs +280 -0
  59. package/dist/config.cjs.map +1 -0
  60. package/dist/config.d.cts +35 -0
  61. package/dist/config.d.cts.map +1 -0
  62. package/dist/config.d.mts +35 -0
  63. package/dist/config.d.mts.map +1 -0
  64. package/dist/config.mjs +266 -0
  65. package/dist/config.mjs.map +1 -0
  66. package/dist/contract.cjs +209 -0
  67. package/dist/contract.cjs.map +1 -0
  68. package/dist/contract.d.cts +490 -0
  69. package/dist/contract.d.cts.map +1 -0
  70. package/dist/contract.d.mts +490 -0
  71. package/dist/contract.d.mts.map +1 -0
  72. package/dist/contract.meta.cjs +104 -0
  73. package/dist/contract.meta.cjs.map +1 -0
  74. package/dist/contract.meta.d.cts +141 -0
  75. package/dist/contract.meta.d.cts.map +1 -0
  76. package/dist/contract.meta.d.mts +141 -0
  77. package/dist/contract.meta.d.mts.map +1 -0
  78. package/dist/contract.meta.mjs +102 -0
  79. package/dist/contract.meta.mjs.map +1 -0
  80. package/dist/contract.mjs +186 -0
  81. package/dist/contract.mjs.map +1 -0
  82. package/dist/dev-logs.cjs +53 -0
  83. package/dist/dev-logs.cjs.map +1 -0
  84. package/dist/dev-logs.mjs +51 -0
  85. package/dist/dev-logs.mjs.map +1 -0
  86. package/dist/dev-session.cjs +195 -0
  87. package/dist/dev-session.cjs.map +1 -0
  88. package/dist/dev-session.mjs +194 -0
  89. package/dist/dev-session.mjs.map +1 -0
  90. package/dist/fastkv.cjs +89 -0
  91. package/dist/fastkv.cjs.map +1 -0
  92. package/dist/fastkv.d.cts +11 -0
  93. package/dist/fastkv.d.cts.map +1 -0
  94. package/dist/fastkv.d.mts +11 -0
  95. package/dist/fastkv.d.mts.map +1 -0
  96. package/dist/fastkv.mjs +82 -0
  97. package/dist/fastkv.mjs.map +1 -0
  98. package/dist/federation.server.cjs +27 -0
  99. package/dist/federation.server.cjs.map +1 -0
  100. package/dist/federation.server.mjs +27 -0
  101. package/dist/federation.server.mjs.map +1 -0
  102. package/dist/host.cjs +367 -0
  103. package/dist/host.cjs.map +1 -0
  104. package/dist/host.d.cts +22 -0
  105. package/dist/host.d.cts.map +1 -0
  106. package/dist/host.d.mts +22 -0
  107. package/dist/host.d.mts.map +1 -0
  108. package/dist/host.mjs +364 -0
  109. package/dist/host.mjs.map +1 -0
  110. package/dist/index.cjs +122 -0
  111. package/dist/index.d.cts +7 -0
  112. package/dist/index.d.mts +7 -0
  113. package/dist/index.mjs +9 -0
  114. package/dist/integrity.cjs +39 -0
  115. package/dist/integrity.cjs.map +1 -0
  116. package/dist/integrity.d.cts +7 -0
  117. package/dist/integrity.d.cts.map +1 -0
  118. package/dist/integrity.d.mts +7 -0
  119. package/dist/integrity.d.mts.map +1 -0
  120. package/dist/integrity.mjs +35 -0
  121. package/dist/integrity.mjs.map +1 -0
  122. package/dist/internal/manifest-normalizer.cjs +140 -0
  123. package/dist/internal/manifest-normalizer.cjs.map +1 -0
  124. package/dist/internal/manifest-normalizer.mjs +138 -0
  125. package/dist/internal/manifest-normalizer.mjs.map +1 -0
  126. package/dist/mf.cjs +77 -0
  127. package/dist/mf.cjs.map +1 -0
  128. package/dist/mf.d.cts +19 -0
  129. package/dist/mf.d.cts.map +1 -0
  130. package/dist/mf.d.mts +19 -0
  131. package/dist/mf.d.mts.map +1 -0
  132. package/dist/mf.mjs +71 -0
  133. package/dist/mf.mjs.map +1 -0
  134. package/dist/near-cli.cjs +196 -0
  135. package/dist/near-cli.cjs.map +1 -0
  136. package/dist/near-cli.mjs +193 -0
  137. package/dist/near-cli.mjs.map +1 -0
  138. package/dist/network.cjs +9 -0
  139. package/dist/network.cjs.map +1 -0
  140. package/dist/network.mjs +8 -0
  141. package/dist/network.mjs.map +1 -0
  142. package/dist/orchestrator.cjs +441 -0
  143. package/dist/orchestrator.cjs.map +1 -0
  144. package/dist/orchestrator.d.cts +40 -0
  145. package/dist/orchestrator.d.cts.map +1 -0
  146. package/dist/orchestrator.d.mts +40 -0
  147. package/dist/orchestrator.d.mts.map +1 -0
  148. package/dist/orchestrator.mjs +436 -0
  149. package/dist/orchestrator.mjs.map +1 -0
  150. package/dist/plugin.cjs +830 -0
  151. package/dist/plugin.cjs.map +1 -0
  152. package/dist/plugin.d.cts +347 -0
  153. package/dist/plugin.d.cts.map +1 -0
  154. package/dist/plugin.d.mts +348 -0
  155. package/dist/plugin.d.mts.map +1 -0
  156. package/dist/plugin.mjs +827 -0
  157. package/dist/plugin.mjs.map +1 -0
  158. package/dist/process-registry.cjs +120 -0
  159. package/dist/process-registry.cjs.map +1 -0
  160. package/dist/process-registry.d.cts +25 -0
  161. package/dist/process-registry.d.cts.map +1 -0
  162. package/dist/process-registry.d.mts +25 -0
  163. package/dist/process-registry.d.mts.map +1 -0
  164. package/dist/process-registry.mjs +119 -0
  165. package/dist/process-registry.mjs.map +1 -0
  166. package/dist/sdk.cjs +61 -0
  167. package/dist/sdk.d.cts +5 -0
  168. package/dist/sdk.d.mts +5 -0
  169. package/dist/sdk.mjs +6 -0
  170. package/dist/shared.cjs +143 -0
  171. package/dist/shared.cjs.map +1 -0
  172. package/dist/shared.d.cts +33 -0
  173. package/dist/shared.d.cts.map +1 -0
  174. package/dist/shared.d.mts +33 -0
  175. package/dist/shared.d.mts.map +1 -0
  176. package/dist/shared.mjs +140 -0
  177. package/dist/shared.mjs.map +1 -0
  178. package/dist/types.cjs +160 -0
  179. package/dist/types.cjs.map +1 -0
  180. package/dist/types.d.cts +269 -0
  181. package/dist/types.d.cts.map +1 -0
  182. package/dist/types.d.mts +269 -0
  183. package/dist/types.d.mts.map +1 -0
  184. package/dist/types.mjs +144 -0
  185. package/dist/types.mjs.map +1 -0
  186. package/dist/ui/head.cjs +67 -0
  187. package/dist/ui/head.cjs.map +1 -0
  188. package/dist/ui/head.d.cts +19 -0
  189. package/dist/ui/head.d.cts.map +1 -0
  190. package/dist/ui/head.d.mts +19 -0
  191. package/dist/ui/head.d.mts.map +1 -0
  192. package/dist/ui/head.mjs +61 -0
  193. package/dist/ui/head.mjs.map +1 -0
  194. package/dist/ui/index.cjs +32 -0
  195. package/dist/ui/index.d.cts +7 -0
  196. package/dist/ui/index.d.mts +7 -0
  197. package/dist/ui/index.mjs +6 -0
  198. package/dist/ui/metadata.cjs +106 -0
  199. package/dist/ui/metadata.cjs.map +1 -0
  200. package/dist/ui/metadata.d.cts +35 -0
  201. package/dist/ui/metadata.d.cts.map +1 -0
  202. package/dist/ui/metadata.d.mts +35 -0
  203. package/dist/ui/metadata.d.mts.map +1 -0
  204. package/dist/ui/metadata.mjs +100 -0
  205. package/dist/ui/metadata.mjs.map +1 -0
  206. package/dist/ui/router.cjs +56 -0
  207. package/dist/ui/router.cjs.map +1 -0
  208. package/dist/ui/router.d.cts +11 -0
  209. package/dist/ui/router.d.cts.map +1 -0
  210. package/dist/ui/router.d.mts +11 -0
  211. package/dist/ui/router.d.mts.map +1 -0
  212. package/dist/ui/router.mjs +51 -0
  213. package/dist/ui/router.mjs.map +1 -0
  214. package/dist/ui/runtime.cjs +65 -0
  215. package/dist/ui/runtime.cjs.map +1 -0
  216. package/dist/ui/runtime.d.cts +29 -0
  217. package/dist/ui/runtime.d.cts.map +1 -0
  218. package/dist/ui/runtime.d.mts +29 -0
  219. package/dist/ui/runtime.d.mts.map +1 -0
  220. package/dist/ui/runtime.mjs +53 -0
  221. package/dist/ui/runtime.mjs.map +1 -0
  222. package/dist/ui/types.cjs +0 -0
  223. package/dist/ui/types.d.cts +52 -0
  224. package/dist/ui/types.d.cts.map +1 -0
  225. package/dist/ui/types.d.mts +52 -0
  226. package/dist/ui/types.d.mts.map +1 -0
  227. package/dist/ui/types.mjs +1 -0
  228. package/dist/utils/banner.cjs +24 -0
  229. package/dist/utils/banner.cjs.map +1 -0
  230. package/dist/utils/banner.mjs +23 -0
  231. package/dist/utils/banner.mjs.map +1 -0
  232. package/dist/utils/linkify.cjs +15 -0
  233. package/dist/utils/linkify.cjs.map +1 -0
  234. package/dist/utils/linkify.mjs +14 -0
  235. package/dist/utils/linkify.mjs.map +1 -0
  236. package/dist/utils/run.cjs +40 -0
  237. package/dist/utils/run.cjs.map +1 -0
  238. package/dist/utils/run.mjs +39 -0
  239. package/dist/utils/run.mjs.map +1 -0
  240. package/dist/utils/theme.cjs +44 -0
  241. package/dist/utils/theme.cjs.map +1 -0
  242. package/dist/utils/theme.mjs +37 -0
  243. package/dist/utils/theme.mjs.map +1 -0
  244. package/package.json +269 -80
  245. package/src/api-contract.ts +309 -0
  246. package/src/api.ts +181 -0
  247. package/src/app.ts +346 -0
  248. package/src/cli/catalog.ts +49 -0
  249. package/src/cli/help.ts +13 -0
  250. package/src/cli/init.ts +386 -0
  251. package/src/cli/parse.ts +130 -0
  252. package/src/cli/prompts.ts +64 -0
  253. package/src/cli.ts +203 -1507
  254. package/src/components/dev-view.tsx +307 -255
  255. package/src/components/streaming-view.ts +164 -128
  256. package/src/config.ts +462 -532
  257. package/src/contract.meta.ts +96 -0
  258. package/src/contract.ts +164 -561
  259. package/src/dev-logs.ts +85 -0
  260. package/src/dev-session.ts +318 -0
  261. package/src/fastkv.ts +153 -0
  262. package/src/federation.server.ts +43 -0
  263. package/src/host.ts +526 -0
  264. package/src/index.ts +6 -3
  265. package/src/integrity.ts +54 -0
  266. package/src/internal/manifest-normalizer.ts +251 -0
  267. package/src/mf.ts +105 -0
  268. package/src/near-cli.ts +284 -0
  269. package/src/network.ts +3 -0
  270. package/src/orchestrator.ts +648 -0
  271. package/src/plugin.ts +1130 -2311
  272. package/src/process-registry.ts +154 -0
  273. package/src/scripts/sync-api-contract.ts +24 -0
  274. package/src/sdk.ts +14 -0
  275. package/src/shared.ts +206 -0
  276. package/src/types.ts +152 -206
  277. package/src/ui/head.ts +34 -27
  278. package/src/ui/index.ts +3 -3
  279. package/src/ui/metadata.ts +95 -0
  280. package/src/ui/router.ts +22 -6
  281. package/src/ui/runtime.ts +55 -6
  282. package/src/ui/types.ts +24 -11
  283. package/src/utils/banner.ts +10 -6
  284. package/src/utils/run.ts +26 -27
  285. package/src/utils/theme.ts +3 -66
  286. package/src/components/monitor-view.tsx +0 -475
  287. package/src/components/status-view.tsx +0 -173
  288. package/src/lib/env.ts +0 -109
  289. package/src/lib/near-cli.ts +0 -289
  290. package/src/lib/nova.ts +0 -266
  291. package/src/lib/orchestrator.ts +0 -276
  292. package/src/lib/process-registry.ts +0 -166
  293. package/src/lib/process.ts +0 -550
  294. package/src/lib/resource-monitor/assertions.ts +0 -234
  295. package/src/lib/resource-monitor/command.ts +0 -283
  296. package/src/lib/resource-monitor/diff.ts +0 -157
  297. package/src/lib/resource-monitor/errors.ts +0 -127
  298. package/src/lib/resource-monitor/index.ts +0 -305
  299. package/src/lib/resource-monitor/platform/darwin.ts +0 -306
  300. package/src/lib/resource-monitor/platform/index.ts +0 -35
  301. package/src/lib/resource-monitor/platform/linux.ts +0 -332
  302. package/src/lib/resource-monitor/platform/windows.ts +0 -298
  303. package/src/lib/resource-monitor/snapshot.ts +0 -217
  304. package/src/lib/resource-monitor/types.ts +0 -74
  305. package/src/lib/session-recorder/errors.ts +0 -102
  306. package/src/lib/session-recorder/flows/login.ts +0 -210
  307. package/src/lib/session-recorder/index.ts +0 -361
  308. package/src/lib/session-recorder/playwright.ts +0 -257
  309. package/src/lib/session-recorder/report.ts +0 -353
  310. package/src/lib/session-recorder/server.ts +0 -268
  311. package/src/lib/session-recorder/types.ts +0 -115
  312. package/src/lib/sync.ts +0 -1
  313. package/src/ui/files.ts +0 -134
@@ -0,0 +1,436 @@
1
+ import { getHostDevelopmentPort, getProjectRoot, parsePort } from "./config.mjs";
2
+ import { patchManifestFetchForSsrPublicPath } from "./mf.mjs";
3
+ import { Deferred, Effect, Fiber, Ref } from "effect";
4
+ import { createConnection } from "node:net";
5
+
6
+ //#region src/orchestrator.ts
7
+ const processConfigBases = {
8
+ "host-build": {
9
+ name: "host-build",
10
+ command: "bun",
11
+ args: ["run", "build"],
12
+ cwd: "host",
13
+ readyPatterns: [/built in/i, /compiled.*successfully/i],
14
+ errorPatterns: [
15
+ /error:/i,
16
+ /failed/i,
17
+ /exception/i
18
+ ]
19
+ },
20
+ host: {
21
+ name: "host",
22
+ command: "bun",
23
+ args: ["run", "dev"],
24
+ cwd: "host",
25
+ readyPatterns: [/Host (dev|production) server running at/i, /Server running at/i],
26
+ errorPatterns: [
27
+ /error:/i,
28
+ /failed/i,
29
+ /exception/i
30
+ ]
31
+ },
32
+ ui: {
33
+ name: "ui",
34
+ command: "bun",
35
+ args: ["run", "dev"],
36
+ cwd: "ui",
37
+ readyPatterns: [
38
+ /\bready\s+built in\b/i,
39
+ /\bLocal:\b/i,
40
+ /\bcompiled\b.*successfully/i
41
+ ],
42
+ errorPatterns: [/error/i, /failed to compile/i]
43
+ },
44
+ "ui-ssr": {
45
+ name: "ui-ssr",
46
+ command: "bun",
47
+ args: ["run", "dev:ssr"],
48
+ cwd: "ui",
49
+ readyPatterns: [/\bready\s+built in\b/i, /\bcompiled\b.*successfully/i],
50
+ errorPatterns: [/error/i, /failed/i]
51
+ },
52
+ api: {
53
+ name: "api",
54
+ command: "bun",
55
+ args: ["run", "dev"],
56
+ cwd: "api",
57
+ readyPatterns: [
58
+ /ready in/i,
59
+ /compiled.*successfully/i,
60
+ /listening/i,
61
+ /started/i
62
+ ],
63
+ errorPatterns: [/error/i, /failed/i]
64
+ }
65
+ };
66
+ function getProcessConfig(pkg, env, portOverride, bosConfig, runtimeConfig) {
67
+ if (pkg.startsWith("plugin:")) {
68
+ const pluginId = pkg.slice(7);
69
+ const pluginConfig = runtimeConfig?.plugins?.[pluginId] ?? null;
70
+ const localPath = pluginConfig?.localPath;
71
+ if (!localPath || pluginConfig?.source !== "local") return null;
72
+ return {
73
+ name: pkg,
74
+ command: "bun",
75
+ args: ["run", "dev"],
76
+ cwd: localPath,
77
+ port: portOverride ?? pluginConfig?.port ?? (pluginConfig?.url ? parsePort(pluginConfig.url) : 0),
78
+ readyPatterns: [
79
+ /ready in/i,
80
+ /compiled.*successfully/i,
81
+ /listening/i,
82
+ /started/i
83
+ ],
84
+ errorPatterns: [/error/i, /failed/i],
85
+ env
86
+ };
87
+ }
88
+ const base = processConfigBases[pkg];
89
+ if (!base) return null;
90
+ let port;
91
+ if (pkg === "host") port = portOverride ?? (runtimeConfig?.hostUrl ? parsePort(runtimeConfig.hostUrl) : bosConfig ? getHostDevelopmentPort(bosConfig.app.host.development) : 3e3);
92
+ else if (pkg === "ui") port = runtimeConfig?.ui.port ?? (runtimeConfig?.ui.url ? parsePort(runtimeConfig.ui.url) : 3002);
93
+ else if (pkg === "ui-ssr") port = runtimeConfig?.ui.ssrUrl ? parsePort(runtimeConfig.ui.ssrUrl) : runtimeConfig?.ui.port ? runtimeConfig.ui.port + 1 : 3003;
94
+ else if (pkg === "api") port = runtimeConfig?.api.port ?? (runtimeConfig?.api.url ? parsePort(runtimeConfig.api.url) : 3014);
95
+ else port = 0;
96
+ const cwd = pkg === "ui" ? runtimeConfig?.ui.localPath ?? base.cwd : pkg === "api" ? runtimeConfig?.api.localPath ?? base.cwd : base.cwd;
97
+ return {
98
+ ...base,
99
+ cwd,
100
+ port,
101
+ env
102
+ };
103
+ }
104
+ const stripAnsi = (input) => {
105
+ const ESC = String.fromCharCode(27);
106
+ const BEL = String.fromCharCode(7);
107
+ return input.replace(new RegExp(`${ESC}\\][^${BEL}]*${BEL}`, "g"), "").replace(new RegExp(`${ESC}\\[[0-?]*[ -/]*[@-~]`, "g"), "");
108
+ };
109
+ const probeHttpOk = async (url, timeoutMs = 400) => {
110
+ const controller = new AbortController();
111
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
112
+ try {
113
+ return (await fetch(url, { signal: controller.signal })).ok;
114
+ } catch {
115
+ return false;
116
+ } finally {
117
+ clearTimeout(timer);
118
+ }
119
+ };
120
+ const probeTcpOpen = async (port, timeoutMs = 250) => {
121
+ return new Promise((resolve) => {
122
+ const socket = createConnection({
123
+ host: "127.0.0.1",
124
+ port
125
+ });
126
+ const timer = setTimeout(() => {
127
+ socket.destroy();
128
+ resolve(false);
129
+ }, timeoutMs);
130
+ socket.once("connect", () => {
131
+ clearTimeout(timer);
132
+ socket.destroy();
133
+ resolve(true);
134
+ });
135
+ socket.once("error", () => {
136
+ clearTimeout(timer);
137
+ resolve(false);
138
+ });
139
+ });
140
+ };
141
+ const detectStatus = (line, config) => {
142
+ const cleanLine = stripAnsi(line);
143
+ for (const pattern of config.errorPatterns) if (pattern.test(cleanLine)) return {
144
+ status: "error",
145
+ isError: true
146
+ };
147
+ for (const pattern of config.readyPatterns) if (pattern.test(cleanLine)) return {
148
+ status: "ready",
149
+ isError: false
150
+ };
151
+ return null;
152
+ };
153
+ const killProcessTree = (pid) => Effect.gen(function* () {
154
+ const killSignal = (signal) => Effect.try({
155
+ try: () => {
156
+ process.kill(-pid, signal);
157
+ },
158
+ catch: () => null
159
+ }).pipe(Effect.ignore);
160
+ const killDirect = (signal) => Effect.try({
161
+ try: () => {
162
+ process.kill(pid, signal);
163
+ },
164
+ catch: () => null
165
+ }).pipe(Effect.ignore);
166
+ const isRunning = () => Effect.try({
167
+ try: () => {
168
+ process.kill(pid, 0);
169
+ return true;
170
+ },
171
+ catch: () => false
172
+ });
173
+ yield* killSignal("SIGTERM");
174
+ yield* killDirect("SIGTERM");
175
+ yield* Effect.sleep("200 millis");
176
+ if (yield* isRunning()) {
177
+ yield* killSignal("SIGKILL");
178
+ yield* killDirect("SIGKILL");
179
+ yield* Effect.sleep("100 millis");
180
+ }
181
+ });
182
+ const patchConsole = (name, callbacks) => {
183
+ const originalLog = console.log;
184
+ const originalError = console.error;
185
+ const originalWarn = console.warn;
186
+ const originalInfo = console.info;
187
+ const formatArgs = (args) => {
188
+ return args.map((arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : String(arg)).join(" ");
189
+ };
190
+ console.log = (...args) => {
191
+ callbacks.onLog(name, formatArgs(args), false);
192
+ };
193
+ console.error = (...args) => {
194
+ callbacks.onLog(name, formatArgs(args), true);
195
+ };
196
+ console.warn = (...args) => {
197
+ callbacks.onLog(name, formatArgs(args), false);
198
+ };
199
+ console.info = (...args) => {
200
+ callbacks.onLog(name, formatArgs(args), false);
201
+ };
202
+ return () => {
203
+ console.log = originalLog;
204
+ console.error = originalError;
205
+ console.warn = originalWarn;
206
+ console.info = originalInfo;
207
+ };
208
+ };
209
+ const spawnRemoteHost = (config, callbacks, runtimeConfig) => Effect.gen(function* () {
210
+ const remoteUrl = config.env?.HOST_REMOTE_URL;
211
+ if (!remoteUrl) return yield* Effect.fail(/* @__PURE__ */ new Error("HOST_REMOTE_URL not provided for remote host"));
212
+ if (config.env) for (const [key, value] of Object.entries(config.env)) process.env[key] = value;
213
+ callbacks.onStatus(config.name, "starting");
214
+ callbacks.onLog(config.name, `Remote: ${remoteUrl}`);
215
+ const restoreConsole = patchConsole(config.name, callbacks);
216
+ callbacks.onLog(config.name, "Loading Module Federation runtime...");
217
+ const mfRuntime = yield* Effect.tryPromise({
218
+ try: () => import("@module-federation/enhanced/runtime"),
219
+ catch: (e) => /* @__PURE__ */ new Error(`Failed to load MF runtime: ${e}`)
220
+ });
221
+ const mfCore = yield* Effect.tryPromise({
222
+ try: () => import("@module-federation/runtime-core"),
223
+ catch: (e) => /* @__PURE__ */ new Error(`Failed to load MF core: ${e}`)
224
+ });
225
+ let mf = mfRuntime.getInstance();
226
+ if (!mf) {
227
+ mf = mfRuntime.createInstance({
228
+ name: "cli-host",
229
+ remotes: []
230
+ });
231
+ mfCore.setGlobalFederationInstance(mf);
232
+ }
233
+ patchManifestFetchForSsrPublicPath(mf);
234
+ const baseUrl = remoteUrl.replace(/\/remoteEntry\.js$/, "").replace(/\/mf-manifest\.json$/, "").replace(/\/$/, "");
235
+ const remoteEntryUrl = `${baseUrl}/remoteEntry.js`;
236
+ const manifestUrl = `${baseUrl}/mf-manifest.json`;
237
+ const entryUrl = yield* Effect.tryPromise({
238
+ try: async () => {
239
+ try {
240
+ const res = await fetch(manifestUrl);
241
+ if (!res.ok) return remoteEntryUrl;
242
+ const json = await res.json();
243
+ if (json && typeof json === "object" && "metaData" in json && "exposes" in json && "shared" in json) return manifestUrl;
244
+ } catch {}
245
+ return remoteEntryUrl;
246
+ },
247
+ catch: () => remoteEntryUrl
248
+ });
249
+ mf.registerRemotes([{
250
+ name: "host",
251
+ entry: entryUrl
252
+ }]);
253
+ callbacks.onLog(config.name, `Loading host from ${entryUrl}...`);
254
+ const hostModule = yield* Effect.tryPromise({
255
+ try: () => mf.loadRemote("host/Server"),
256
+ catch: (e) => /* @__PURE__ */ new Error(`Failed to load host module: ${e}`)
257
+ });
258
+ if (!hostModule?.runServer) return yield* Effect.fail(/* @__PURE__ */ new Error("Host module does not export runServer function"));
259
+ callbacks.onLog(config.name, "Starting server...");
260
+ const serverHandle = hostModule.runServer({ config: runtimeConfig });
261
+ yield* Effect.tryPromise({
262
+ try: () => serverHandle.ready,
263
+ catch: (e) => /* @__PURE__ */ new Error(`Server failed to start: ${e}`)
264
+ });
265
+ callbacks.onStatus(config.name, "ready");
266
+ return {
267
+ name: config.name,
268
+ pid: process.pid,
269
+ kill: async () => {
270
+ callbacks.onLog(config.name, "Shutting down remote host...");
271
+ restoreConsole();
272
+ await serverHandle.shutdown();
273
+ },
274
+ waitForReady: Effect.succeed(void 0),
275
+ waitForExit: Effect.never
276
+ };
277
+ });
278
+ const spawnDevProcess = (config, callbacks, runtimeConfig, registry) => Effect.gen(function* () {
279
+ let configDir;
280
+ try {
281
+ configDir = getProjectRoot();
282
+ } catch {
283
+ configDir = process.cwd();
284
+ }
285
+ const fullCwd = config.cwd.startsWith("/") ? config.cwd : `${configDir}/${config.cwd}`;
286
+ const readyDeferred = yield* Deferred.make();
287
+ const statusRef = yield* Ref.make("starting");
288
+ callbacks.onStatus(config.name, "starting");
289
+ const envVars = {
290
+ ...process.env,
291
+ ...config.env,
292
+ FORCE_COLOR: "1",
293
+ ...config.port > 0 ? { PORT: String(config.port) } : {}
294
+ };
295
+ if (runtimeConfig && config.name === "host") envVars.BOS_RUNTIME_CONFIG = JSON.stringify(runtimeConfig);
296
+ const proc = Bun.spawn({
297
+ cmd: [config.command, ...config.args],
298
+ cwd: fullCwd,
299
+ env: envVars,
300
+ stdio: [
301
+ "inherit",
302
+ "pipe",
303
+ "pipe"
304
+ ]
305
+ });
306
+ const markReady = Effect.gen(function* () {
307
+ const currentStatus = yield* Ref.get(statusRef);
308
+ if (currentStatus === "ready" || currentStatus === "error") return;
309
+ yield* Ref.set(statusRef, "ready");
310
+ callbacks.onStatus(config.name, "ready");
311
+ yield* Deferred.succeed(readyDeferred, void 0).pipe(Effect.ignore);
312
+ });
313
+ if (config.port > 0) {
314
+ const readinessPath = config.name === "host" ? "/health" : config.name === "ui-ssr" ? "/" : "/remoteEntry.js";
315
+ const url = `http://127.0.0.1:${config.port}${readinessPath}`;
316
+ yield* Effect.fork(Effect.gen(function* () {
317
+ const deadline = Date.now() + 9e4;
318
+ while (Date.now() < deadline) {
319
+ const status = yield* Ref.get(statusRef);
320
+ if (status === "ready" || status === "error") return;
321
+ if (url ? yield* Effect.tryPromise({
322
+ try: () => probeHttpOk(url),
323
+ catch: () => false
324
+ }) : yield* Effect.tryPromise({
325
+ try: () => probeTcpOpen(config.port),
326
+ catch: () => false
327
+ })) {
328
+ yield* markReady;
329
+ return;
330
+ }
331
+ yield* Effect.sleep("200 millis");
332
+ }
333
+ }));
334
+ }
335
+ if (registry && proc.pid) yield* registry.track({
336
+ pid: proc.pid,
337
+ name: config.name,
338
+ port: config.port,
339
+ startedAt: Date.now(),
340
+ command: [config.command, ...config.args].join(" ")
341
+ });
342
+ yield* Effect.fork(Effect.promise(() => proc.exited).pipe(Effect.andThen((code) => Effect.gen(function* () {
343
+ if (registry && proc.pid) yield* registry.untrack(proc.pid).pipe(Effect.ignore);
344
+ if ((yield* Ref.get(statusRef)) === "ready") return;
345
+ callbacks.onLog(config.name, `Process exited before ready (exit code: ${code})`, true);
346
+ yield* Ref.set(statusRef, "error");
347
+ callbacks.onStatus(config.name, "error");
348
+ yield* Deferred.fail(readyDeferred, /* @__PURE__ */ new Error(`Process exited before ready: ${config.name}`)).pipe(Effect.ignore);
349
+ }))));
350
+ const handleLine = (line, isStderr) => Effect.gen(function* () {
351
+ if (!line.trim()) return;
352
+ callbacks.onLog(config.name, line, isStderr);
353
+ if ((yield* Ref.get(statusRef)) === "ready") return;
354
+ const detected = detectStatus(line, config);
355
+ if (detected) {
356
+ yield* Ref.set(statusRef, detected.status);
357
+ callbacks.onStatus(config.name, detected.status);
358
+ if (detected.status === "ready" || detected.status === "error") if (detected.status === "ready") yield* Deferred.succeed(readyDeferred, void 0).pipe(Effect.ignore);
359
+ else yield* Deferred.fail(readyDeferred, /* @__PURE__ */ new Error(`Process failed: ${config.name}`)).pipe(Effect.ignore);
360
+ }
361
+ });
362
+ const decoder = new TextDecoder();
363
+ const stdoutFiber = yield* Effect.fork(Effect.async((resume) => {
364
+ if (!proc.stdout) {
365
+ resume(Effect.void);
366
+ return;
367
+ }
368
+ const reader = proc.stdout.getReader();
369
+ let buffer = "";
370
+ const pump = () => reader.read().then(({ done, value }) => {
371
+ if (done) {
372
+ if (buffer) Effect.runSync(handleLine(buffer, false));
373
+ return;
374
+ }
375
+ buffer += decoder.decode(value, { stream: true }).replace(/\r\n/g, "\n").replace(/\r/g, "\n");
376
+ const lines = buffer.split("\n");
377
+ buffer = lines.pop() ?? "";
378
+ for (const line of lines) Effect.runSync(handleLine(line, false));
379
+ return pump();
380
+ });
381
+ pump().then(() => resume(Effect.void));
382
+ }));
383
+ const stderrFiber = yield* Effect.fork(Effect.async((resume) => {
384
+ if (!proc.stderr) {
385
+ resume(Effect.void);
386
+ return;
387
+ }
388
+ const reader = proc.stderr.getReader();
389
+ let buffer = "";
390
+ const pump = () => reader.read().then(({ done, value }) => {
391
+ if (done) {
392
+ if (buffer) Effect.runSync(handleLine(buffer, true));
393
+ return;
394
+ }
395
+ buffer += decoder.decode(value, { stream: true }).replace(/\r\n/g, "\n").replace(/\r/g, "\n");
396
+ const lines = buffer.split("\n");
397
+ buffer = lines.pop() ?? "";
398
+ for (const line of lines) Effect.runSync(handleLine(line, true));
399
+ return pump();
400
+ });
401
+ pump().then(() => resume(Effect.void));
402
+ }));
403
+ return {
404
+ name: config.name,
405
+ pid: proc.pid,
406
+ kill: async () => {
407
+ const pid = proc.pid;
408
+ if (pid) await Effect.runPromise(killProcessTree(pid));
409
+ else {
410
+ proc.kill("SIGTERM");
411
+ await new Promise((r) => setTimeout(r, 100));
412
+ try {
413
+ proc.kill("SIGKILL");
414
+ } catch {}
415
+ }
416
+ },
417
+ waitForReady: Deferred.await(readyDeferred),
418
+ waitForExit: Effect.gen(function* () {
419
+ yield* Fiber.joinAll([stdoutFiber, stderrFiber]);
420
+ return yield* Effect.promise(() => proc.exited);
421
+ })
422
+ };
423
+ });
424
+ const makeDevProcess = (pkg, env, callbacks, portOverride, bosConfig, runtimeConfig, registry) => Effect.gen(function* () {
425
+ const config = getProcessConfig(pkg, env, portOverride, bosConfig, runtimeConfig);
426
+ if (!config) return yield* Effect.fail(/* @__PURE__ */ new Error(`Unknown package: ${pkg}`));
427
+ if (pkg === "host" && runtimeConfig) {
428
+ if (env?.HOST_SOURCE === "remote") return yield* spawnRemoteHost(config, callbacks, runtimeConfig);
429
+ return yield* spawnDevProcess(config, callbacks, runtimeConfig, registry);
430
+ }
431
+ return yield* spawnDevProcess(config, callbacks, runtimeConfig, registry);
432
+ });
433
+
434
+ //#endregion
435
+ export { getProcessConfig, makeDevProcess, spawnDevProcess, spawnRemoteHost };
436
+ //# sourceMappingURL=orchestrator.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.mjs","names":[],"sources":["../src/orchestrator.ts"],"sourcesContent":["import { createConnection } from \"node:net\";\nimport { Deferred, Effect, Fiber, Ref } from \"effect\";\nimport { getHostDevelopmentPort, getProjectRoot, parsePort } from \"./config\";\nimport { patchManifestFetchForSsrPublicPath } from \"./mf\";\nimport type { ProcessRegistry } from \"./process-registry\";\nimport type { BosConfig, RuntimeConfig } from \"./types\";\n\nexport interface DevProcess {\n name: string;\n command: string;\n args: string[];\n cwd: string;\n env?: Record<string, string>;\n port: number;\n readyPatterns: RegExp[];\n errorPatterns: RegExp[];\n}\n\nexport interface ProcessCallbacks {\n onStatus: (name: string, status: ProcessStatus, message?: string) => void;\n onLog: (name: string, line: string, isError?: boolean) => void;\n}\n\nexport interface ProcessHandle {\n name: string;\n pid: number | undefined;\n kill: () => Promise<void>;\n waitForReady: Effect.Effect<void, Error>;\n waitForExit: Effect.Effect<unknown>;\n}\n\nexport type ProcessStatus = \"pending\" | \"starting\" | \"ready\" | \"error\";\n\ninterface ProcessConfigBase {\n name: string;\n command: string;\n args: string[];\n cwd: string;\n readyPatterns: RegExp[];\n errorPatterns: RegExp[];\n}\n\nconst processConfigBases: Record<string, ProcessConfigBase> = {\n \"host-build\": {\n name: \"host-build\",\n command: \"bun\",\n args: [\"run\", \"build\"],\n cwd: \"host\",\n readyPatterns: [/built in/i, /compiled.*successfully/i],\n errorPatterns: [/error:/i, /failed/i, /exception/i],\n },\n host: {\n name: \"host\",\n command: \"bun\",\n args: [\"run\", \"dev\"],\n cwd: \"host\",\n readyPatterns: [/Host (dev|production) server running at/i, /Server running at/i],\n errorPatterns: [/error:/i, /failed/i, /exception/i],\n },\n ui: {\n name: \"ui\",\n command: \"bun\",\n args: [\"run\", \"dev\"],\n cwd: \"ui\",\n // Wait for the client build (mf) specifically, not just SSR.\n readyPatterns: [/\\bready\\s+built in\\b/i, /\\bLocal:\\b/i, /\\bcompiled\\b.*successfully/i],\n errorPatterns: [/error/i, /failed to compile/i],\n },\n \"ui-ssr\": {\n name: \"ui-ssr\",\n command: \"bun\",\n args: [\"run\", \"dev:ssr\"],\n cwd: \"ui\",\n readyPatterns: [/\\bready\\s+built in\\b/i, /\\bcompiled\\b.*successfully/i],\n errorPatterns: [/error/i, /failed/i],\n },\n api: {\n name: \"api\",\n command: \"bun\",\n args: [\"run\", \"dev\"],\n cwd: \"api\",\n readyPatterns: [/ready in/i, /compiled.*successfully/i, /listening/i, /started/i],\n errorPatterns: [/error/i, /failed/i],\n },\n};\n\nexport function getProcessConfig(\n pkg: string,\n env?: Record<string, string>,\n portOverride?: number,\n bosConfig?: BosConfig,\n runtimeConfig?: RuntimeConfig,\n): DevProcess | null {\n if (pkg.startsWith(\"plugin:\")) {\n const pluginId = pkg.slice(\"plugin:\".length);\n const pluginConfig = runtimeConfig?.plugins?.[pluginId] ?? null;\n const localPath = pluginConfig?.localPath;\n\n if (!localPath || pluginConfig?.source !== \"local\") return null;\n\n const port =\n portOverride ?? pluginConfig?.port ?? (pluginConfig?.url ? parsePort(pluginConfig.url) : 0);\n\n return {\n name: pkg,\n command: \"bun\",\n args: [\"run\", \"dev\"],\n cwd: localPath,\n port,\n readyPatterns: [/ready in/i, /compiled.*successfully/i, /listening/i, /started/i],\n errorPatterns: [/error/i, /failed/i],\n env,\n };\n }\n\n const base = processConfigBases[pkg];\n if (!base) return null;\n\n let port: number;\n if (pkg === \"host\") {\n port =\n portOverride ??\n (runtimeConfig?.hostUrl\n ? parsePort(runtimeConfig.hostUrl)\n : bosConfig\n ? getHostDevelopmentPort(bosConfig.app.host.development)\n : 3000);\n } else if (pkg === \"ui\") {\n port =\n runtimeConfig?.ui.port ?? (runtimeConfig?.ui.url ? parsePort(runtimeConfig.ui.url) : 3002);\n } else if (pkg === \"ui-ssr\") {\n const uiPort = runtimeConfig?.ui.ssrUrl\n ? parsePort(runtimeConfig.ui.ssrUrl)\n : runtimeConfig?.ui.port\n ? runtimeConfig.ui.port + 1\n : 3003;\n port = uiPort;\n } else if (pkg === \"api\") {\n port =\n runtimeConfig?.api.port ?? (runtimeConfig?.api.url ? parsePort(runtimeConfig.api.url) : 3014);\n } else {\n port = 0;\n }\n\n const cwd =\n pkg === \"ui\"\n ? (runtimeConfig?.ui.localPath ?? base.cwd)\n : pkg === \"api\"\n ? (runtimeConfig?.api.localPath ?? base.cwd)\n : base.cwd;\n\n return { ...base, cwd, port, env };\n}\n\nconst stripAnsi = (input: string): string => {\n const ESC = String.fromCharCode(27);\n const BEL = String.fromCharCode(7);\n return input\n .replace(new RegExp(`${ESC}\\\\][^${BEL}]*${BEL}`, \"g\"), \"\")\n .replace(new RegExp(`${ESC}\\\\[[0-?]*[ -/]*[@-~]`, \"g\"), \"\");\n};\n\nconst probeHttpOk = async (url: string, timeoutMs = 400): Promise<boolean> => {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const res = await fetch(url, { signal: controller.signal });\n return res.ok;\n } catch {\n return false;\n } finally {\n clearTimeout(timer);\n }\n};\n\nconst probeTcpOpen = async (port: number, timeoutMs = 250): Promise<boolean> => {\n return new Promise((resolve) => {\n const socket = createConnection({ host: \"127.0.0.1\", port });\n const timer = setTimeout(() => {\n socket.destroy();\n resolve(false);\n }, timeoutMs);\n socket.once(\"connect\", () => {\n clearTimeout(timer);\n socket.destroy();\n resolve(true);\n });\n socket.once(\"error\", () => {\n clearTimeout(timer);\n resolve(false);\n });\n });\n};\n\nconst detectStatus = (\n line: string,\n config: DevProcess,\n): { status: ProcessStatus; isError: boolean } | null => {\n const cleanLine = stripAnsi(line);\n for (const pattern of config.errorPatterns) {\n if (pattern.test(cleanLine)) {\n return { status: \"error\", isError: true };\n }\n }\n for (const pattern of config.readyPatterns) {\n if (pattern.test(cleanLine)) {\n return { status: \"ready\", isError: false };\n }\n }\n return null;\n};\n\nconst killProcessTree = (pid: number) =>\n Effect.gen(function* () {\n const killSignal = (signal: NodeJS.Signals) =>\n Effect.try({\n try: () => {\n process.kill(-pid, signal);\n },\n catch: () => null,\n }).pipe(Effect.ignore);\n\n const killDirect = (signal: NodeJS.Signals) =>\n Effect.try({\n try: () => {\n process.kill(pid, signal);\n },\n catch: () => null,\n }).pipe(Effect.ignore);\n\n const isRunning = () =>\n Effect.try({\n try: () => {\n process.kill(pid, 0);\n return true;\n },\n catch: () => false,\n });\n\n yield* killSignal(\"SIGTERM\");\n yield* killDirect(\"SIGTERM\");\n\n yield* Effect.sleep(\"200 millis\");\n\n const stillRunning = yield* isRunning();\n if (stillRunning) {\n yield* killSignal(\"SIGKILL\");\n yield* killDirect(\"SIGKILL\");\n yield* Effect.sleep(\"100 millis\");\n }\n });\n\ninterface ServerHandle {\n ready: Promise<void>;\n shutdown: () => Promise<void>;\n}\n\ninterface ServerInput {\n config: RuntimeConfig;\n}\n\nconst patchConsole = (name: string, callbacks: ProcessCallbacks): (() => void) => {\n const originalLog = console.log;\n const originalError = console.error;\n const originalWarn = console.warn;\n const originalInfo = console.info;\n\n const formatArgs = (args: unknown[]): string => {\n return args\n .map((arg) => (typeof arg === \"object\" ? JSON.stringify(arg, null, 2) : String(arg)))\n .join(\" \");\n };\n\n console.log = (...args: unknown[]) => {\n callbacks.onLog(name, formatArgs(args), false);\n };\n console.error = (...args: unknown[]) => {\n callbacks.onLog(name, formatArgs(args), true);\n };\n console.warn = (...args: unknown[]) => {\n callbacks.onLog(name, formatArgs(args), false);\n };\n console.info = (...args: unknown[]) => {\n callbacks.onLog(name, formatArgs(args), false);\n };\n\n return () => {\n console.log = originalLog;\n console.error = originalError;\n console.warn = originalWarn;\n console.info = originalInfo;\n };\n};\n\nexport const spawnRemoteHost = (\n config: DevProcess,\n callbacks: ProcessCallbacks,\n runtimeConfig: RuntimeConfig,\n) =>\n Effect.gen(function* () {\n const remoteUrl = config.env?.HOST_REMOTE_URL;\n if (!remoteUrl) {\n return yield* Effect.fail(new Error(\"HOST_REMOTE_URL not provided for remote host\"));\n }\n\n if (config.env) {\n for (const [key, value] of Object.entries(config.env)) {\n process.env[key] = value;\n }\n }\n\n callbacks.onStatus(config.name, \"starting\");\n callbacks.onLog(config.name, `Remote: ${remoteUrl}`);\n const restoreConsole = patchConsole(config.name, callbacks);\n callbacks.onLog(config.name, \"Loading Module Federation runtime...\");\n\n const mfRuntime = yield* Effect.tryPromise({\n try: () => import(\"@module-federation/enhanced/runtime\"),\n catch: (e) => new Error(`Failed to load MF runtime: ${e}`),\n });\n\n const mfCore = yield* Effect.tryPromise({\n try: () => import(\"@module-federation/runtime-core\"),\n catch: (e) => new Error(`Failed to load MF core: ${e}`),\n });\n\n let mf = mfRuntime.getInstance();\n if (!mf) {\n mf = mfRuntime.createInstance({ name: \"cli-host\", remotes: [] });\n mfCore.setGlobalFederationInstance(mf);\n }\n patchManifestFetchForSsrPublicPath(mf as any);\n\n const baseUrl = remoteUrl\n .replace(/\\/remoteEntry\\.js$/, \"\")\n .replace(/\\/mf-manifest\\.json$/, \"\")\n .replace(/\\/$/, \"\");\n const remoteEntryUrl = `${baseUrl}/remoteEntry.js`;\n const manifestUrl = `${baseUrl}/mf-manifest.json`;\n\n const entryUrl = yield* Effect.tryPromise({\n try: async () => {\n try {\n const res = await fetch(manifestUrl);\n if (!res.ok) return remoteEntryUrl;\n const json = (await res.json()) as Record<string, unknown>;\n if (\n json &&\n typeof json === \"object\" &&\n \"metaData\" in json &&\n \"exposes\" in json &&\n \"shared\" in json\n ) {\n return manifestUrl;\n }\n } catch {}\n return remoteEntryUrl;\n },\n catch: () => remoteEntryUrl,\n });\n\n (mf as any).registerRemotes([{ name: \"host\", entry: entryUrl }]);\n callbacks.onLog(config.name, `Loading host from ${entryUrl}...`);\n\n const hostModule = yield* Effect.tryPromise({\n try: () =>\n (mf as any).loadRemote(\"host/Server\") as Promise<{\n runServer: (input: ServerInput) => ServerHandle;\n }>,\n catch: (e) => new Error(`Failed to load host module: ${e}`),\n });\n\n if (!hostModule?.runServer) {\n return yield* Effect.fail(new Error(\"Host module does not export runServer function\"));\n }\n\n callbacks.onLog(config.name, \"Starting server...\");\n const serverHandle = hostModule.runServer({ config: runtimeConfig });\n yield* Effect.tryPromise({\n try: () => serverHandle.ready,\n catch: (e) => new Error(`Server failed to start: ${e}`),\n });\n\n callbacks.onStatus(config.name, \"ready\");\n\n return {\n name: config.name,\n pid: process.pid,\n kill: async () => {\n callbacks.onLog(config.name, \"Shutting down remote host...\");\n restoreConsole();\n await serverHandle.shutdown();\n },\n waitForReady: Effect.succeed(undefined),\n waitForExit: Effect.never,\n } satisfies ProcessHandle;\n });\n\nexport const spawnDevProcess = (\n config: DevProcess,\n callbacks: ProcessCallbacks,\n runtimeConfig?: RuntimeConfig,\n registry?: ProcessRegistry,\n) =>\n Effect.gen(function* () {\n let configDir: string;\n try {\n configDir = getProjectRoot();\n } catch {\n configDir = process.cwd();\n }\n const fullCwd = config.cwd.startsWith(\"/\") ? config.cwd : `${configDir}/${config.cwd}`;\n const readyDeferred = yield* Deferred.make<void, Error>();\n const statusRef = yield* Ref.make<ProcessStatus>(\"starting\");\n\n callbacks.onStatus(config.name, \"starting\");\n\n const envVars: Record<string, string> = {\n ...(process.env as Record<string, string>),\n ...config.env,\n FORCE_COLOR: \"1\",\n ...(config.port > 0 ? { PORT: String(config.port) } : {}),\n };\n\n if (runtimeConfig && config.name === \"host\") {\n envVars.BOS_RUNTIME_CONFIG = JSON.stringify(runtimeConfig);\n }\n\n const proc = Bun.spawn({\n cmd: [config.command, ...config.args],\n cwd: fullCwd,\n env: envVars,\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n });\n\n const markReady = Effect.gen(function* () {\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\" || currentStatus === \"error\") return;\n yield* Ref.set(statusRef, \"ready\");\n callbacks.onStatus(config.name, \"ready\");\n yield* Deferred.succeed(readyDeferred, undefined).pipe(Effect.ignore);\n });\n\n // Prefer probe-based readiness to avoid brittle log regexes.\n // This is best-effort and complements log detection.\n if (config.port > 0) {\n const readinessPath =\n config.name === \"host\" ? \"/health\" : config.name === \"ui-ssr\" ? \"/\" : \"/remoteEntry.js\";\n const url = `http://127.0.0.1:${config.port}${readinessPath}`;\n\n yield* Effect.fork(\n Effect.gen(function* () {\n const deadline = Date.now() + 90_000;\n while (Date.now() < deadline) {\n const status = yield* Ref.get(statusRef);\n if (status === \"ready\" || status === \"error\") return;\n const ok = url\n ? yield* Effect.tryPromise({\n try: () => probeHttpOk(url),\n catch: () => false,\n })\n : yield* Effect.tryPromise({\n try: () => probeTcpOpen(config.port),\n catch: () => false,\n });\n if (ok) {\n yield* markReady;\n return;\n }\n yield* Effect.sleep(\"200 millis\");\n }\n }),\n );\n }\n\n if (registry && proc.pid) {\n yield* registry.track({\n pid: proc.pid,\n name: config.name,\n port: config.port,\n startedAt: Date.now(),\n command: [config.command, ...config.args].join(\" \"),\n });\n }\n\n yield* Effect.fork(\n Effect.promise(() => proc.exited).pipe(\n Effect.andThen((code) =>\n Effect.gen(function* () {\n if (registry && proc.pid) {\n yield* registry.untrack(proc.pid).pipe(Effect.ignore);\n }\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\") return;\n callbacks.onLog(config.name, `Process exited before ready (exit code: ${code})`, true);\n yield* Ref.set(statusRef, \"error\");\n callbacks.onStatus(config.name, \"error\");\n yield* Deferred.fail(\n readyDeferred,\n new Error(`Process exited before ready: ${config.name}`),\n ).pipe(Effect.ignore);\n }),\n ),\n ),\n );\n\n const handleLine = (line: string, isStderr: boolean) =>\n Effect.gen(function* () {\n if (!line.trim()) return;\n\n callbacks.onLog(config.name, line, isStderr);\n\n const currentStatus = yield* Ref.get(statusRef);\n if (currentStatus === \"ready\") return;\n\n const detected = detectStatus(line, config);\n if (detected) {\n yield* Ref.set(statusRef, detected.status);\n callbacks.onStatus(config.name, detected.status);\n if (detected.status === \"ready\" || detected.status === \"error\") {\n if (detected.status === \"ready\") {\n yield* Deferred.succeed(readyDeferred, undefined).pipe(Effect.ignore);\n } else {\n yield* Deferred.fail(readyDeferred, new Error(`Process failed: ${config.name}`)).pipe(\n Effect.ignore,\n );\n }\n }\n }\n });\n\n const decoder = new TextDecoder();\n\n const stdoutFiber = yield* Effect.fork(\n Effect.async<void>((resume) => {\n if (!proc.stdout) {\n resume(Effect.void);\n return;\n }\n const reader = proc.stdout.getReader();\n let buffer = \"\";\n\n const pump = (): Promise<void> =>\n reader.read().then(({ done, value }) => {\n if (done) {\n if (buffer) {\n Effect.runSync(handleLine(buffer, false));\n }\n return;\n }\n buffer += decoder\n .decode(value, { stream: true })\n .replace(/\\r\\n/g, \"\\n\")\n .replace(/\\r/g, \"\\n\");\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n for (const line of lines) {\n Effect.runSync(handleLine(line, false));\n }\n return pump();\n });\n\n pump().then(() => resume(Effect.void));\n }),\n );\n\n const stderrFiber = yield* Effect.fork(\n Effect.async<void>((resume) => {\n if (!proc.stderr) {\n resume(Effect.void);\n return;\n }\n const reader = proc.stderr.getReader();\n let buffer = \"\";\n\n const pump = (): Promise<void> =>\n reader.read().then(({ done, value }) => {\n if (done) {\n if (buffer) {\n Effect.runSync(handleLine(buffer, true));\n }\n return;\n }\n buffer += decoder\n .decode(value, { stream: true })\n .replace(/\\r\\n/g, \"\\n\")\n .replace(/\\r/g, \"\\n\");\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n for (const line of lines) {\n Effect.runSync(handleLine(line, true));\n }\n return pump();\n });\n\n pump().then(() => resume(Effect.void));\n }),\n );\n\n const handle: ProcessHandle = {\n name: config.name,\n pid: proc.pid,\n kill: async () => {\n const pid = proc.pid;\n if (pid) {\n await Effect.runPromise(killProcessTree(pid));\n } else {\n proc.kill(\"SIGTERM\");\n await new Promise((r) => setTimeout(r, 100));\n try {\n proc.kill(\"SIGKILL\");\n } catch {}\n }\n },\n waitForReady: Deferred.await(readyDeferred),\n waitForExit: Effect.gen(function* () {\n yield* Fiber.joinAll([stdoutFiber, stderrFiber]);\n return yield* Effect.promise(() => proc.exited);\n }),\n };\n\n return handle;\n });\n\nexport const makeDevProcess = (\n pkg: string,\n env: Record<string, string> | undefined,\n callbacks: ProcessCallbacks,\n portOverride?: number,\n bosConfig?: BosConfig,\n runtimeConfig?: RuntimeConfig,\n registry?: ProcessRegistry,\n) =>\n Effect.gen(function* () {\n const config = getProcessConfig(pkg, env, portOverride, bosConfig, runtimeConfig);\n if (!config) {\n return yield* Effect.fail(new Error(`Unknown package: ${pkg}`));\n }\n\n if (pkg === \"host\" && runtimeConfig) {\n if (env?.HOST_SOURCE === \"remote\") {\n return yield* spawnRemoteHost(config, callbacks, runtimeConfig);\n }\n return yield* spawnDevProcess(config, callbacks, runtimeConfig, registry);\n }\n\n return yield* spawnDevProcess(config, callbacks, runtimeConfig, registry);\n });\n"],"mappings":"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"}