everything-dev 0.3.2 → 1.3.2

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 (308) 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 +317 -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 +309 -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/mf.cjs +77 -0
  123. package/dist/mf.cjs.map +1 -0
  124. package/dist/mf.d.cts +19 -0
  125. package/dist/mf.d.cts.map +1 -0
  126. package/dist/mf.d.mts +19 -0
  127. package/dist/mf.d.mts.map +1 -0
  128. package/dist/mf.mjs +71 -0
  129. package/dist/mf.mjs.map +1 -0
  130. package/dist/near-cli.cjs +196 -0
  131. package/dist/near-cli.cjs.map +1 -0
  132. package/dist/near-cli.mjs +193 -0
  133. package/dist/near-cli.mjs.map +1 -0
  134. package/dist/network.cjs +9 -0
  135. package/dist/network.cjs.map +1 -0
  136. package/dist/network.mjs +8 -0
  137. package/dist/network.mjs.map +1 -0
  138. package/dist/orchestrator.cjs +441 -0
  139. package/dist/orchestrator.cjs.map +1 -0
  140. package/dist/orchestrator.d.cts +40 -0
  141. package/dist/orchestrator.d.cts.map +1 -0
  142. package/dist/orchestrator.d.mts +40 -0
  143. package/dist/orchestrator.d.mts.map +1 -0
  144. package/dist/orchestrator.mjs +436 -0
  145. package/dist/orchestrator.mjs.map +1 -0
  146. package/dist/plugin.cjs +825 -0
  147. package/dist/plugin.cjs.map +1 -0
  148. package/dist/plugin.d.cts +347 -0
  149. package/dist/plugin.d.cts.map +1 -0
  150. package/dist/plugin.d.mts +348 -0
  151. package/dist/plugin.d.mts.map +1 -0
  152. package/dist/plugin.mjs +822 -0
  153. package/dist/plugin.mjs.map +1 -0
  154. package/dist/process-registry.cjs +120 -0
  155. package/dist/process-registry.cjs.map +1 -0
  156. package/dist/process-registry.d.cts +25 -0
  157. package/dist/process-registry.d.cts.map +1 -0
  158. package/dist/process-registry.d.mts +25 -0
  159. package/dist/process-registry.d.mts.map +1 -0
  160. package/dist/process-registry.mjs +119 -0
  161. package/dist/process-registry.mjs.map +1 -0
  162. package/dist/sdk.cjs +61 -0
  163. package/dist/sdk.d.cts +5 -0
  164. package/dist/sdk.d.mts +5 -0
  165. package/dist/sdk.mjs +6 -0
  166. package/dist/shared.cjs +143 -0
  167. package/dist/shared.cjs.map +1 -0
  168. package/dist/shared.d.cts +33 -0
  169. package/dist/shared.d.cts.map +1 -0
  170. package/dist/shared.d.mts +33 -0
  171. package/dist/shared.d.mts.map +1 -0
  172. package/dist/shared.mjs +140 -0
  173. package/dist/shared.mjs.map +1 -0
  174. package/dist/types.cjs +160 -0
  175. package/dist/types.cjs.map +1 -0
  176. package/dist/types.d.cts +269 -0
  177. package/dist/types.d.cts.map +1 -0
  178. package/dist/types.d.mts +269 -0
  179. package/dist/types.d.mts.map +1 -0
  180. package/dist/types.mjs +144 -0
  181. package/dist/types.mjs.map +1 -0
  182. package/dist/ui/head.cjs +67 -0
  183. package/dist/ui/head.cjs.map +1 -0
  184. package/dist/ui/head.d.cts +19 -0
  185. package/dist/ui/head.d.cts.map +1 -0
  186. package/dist/ui/head.d.mts +19 -0
  187. package/dist/ui/head.d.mts.map +1 -0
  188. package/dist/ui/head.mjs +61 -0
  189. package/dist/ui/head.mjs.map +1 -0
  190. package/dist/ui/index.cjs +32 -0
  191. package/dist/ui/index.d.cts +7 -0
  192. package/dist/ui/index.d.mts +7 -0
  193. package/dist/ui/index.mjs +6 -0
  194. package/dist/ui/metadata.cjs +106 -0
  195. package/dist/ui/metadata.cjs.map +1 -0
  196. package/dist/ui/metadata.d.cts +35 -0
  197. package/dist/ui/metadata.d.cts.map +1 -0
  198. package/dist/ui/metadata.d.mts +35 -0
  199. package/dist/ui/metadata.d.mts.map +1 -0
  200. package/dist/ui/metadata.mjs +100 -0
  201. package/dist/ui/metadata.mjs.map +1 -0
  202. package/dist/ui/router.cjs +56 -0
  203. package/dist/ui/router.cjs.map +1 -0
  204. package/dist/ui/router.d.cts +11 -0
  205. package/dist/ui/router.d.cts.map +1 -0
  206. package/dist/ui/router.d.mts +11 -0
  207. package/dist/ui/router.d.mts.map +1 -0
  208. package/dist/ui/router.mjs +51 -0
  209. package/dist/ui/router.mjs.map +1 -0
  210. package/dist/ui/runtime.cjs +65 -0
  211. package/dist/ui/runtime.cjs.map +1 -0
  212. package/dist/ui/runtime.d.cts +29 -0
  213. package/dist/ui/runtime.d.cts.map +1 -0
  214. package/dist/ui/runtime.d.mts +29 -0
  215. package/dist/ui/runtime.d.mts.map +1 -0
  216. package/dist/ui/runtime.mjs +53 -0
  217. package/dist/ui/runtime.mjs.map +1 -0
  218. package/dist/ui/types.cjs +0 -0
  219. package/dist/ui/types.d.cts +52 -0
  220. package/dist/ui/types.d.cts.map +1 -0
  221. package/dist/ui/types.d.mts +52 -0
  222. package/dist/ui/types.d.mts.map +1 -0
  223. package/dist/ui/types.mjs +1 -0
  224. package/dist/utils/banner.cjs +24 -0
  225. package/dist/utils/banner.cjs.map +1 -0
  226. package/dist/utils/banner.mjs +23 -0
  227. package/dist/utils/banner.mjs.map +1 -0
  228. package/dist/utils/linkify.cjs +15 -0
  229. package/dist/utils/linkify.cjs.map +1 -0
  230. package/dist/utils/linkify.mjs +14 -0
  231. package/dist/utils/linkify.mjs.map +1 -0
  232. package/dist/utils/run.cjs +40 -0
  233. package/dist/utils/run.cjs.map +1 -0
  234. package/dist/utils/run.mjs +39 -0
  235. package/dist/utils/run.mjs.map +1 -0
  236. package/dist/utils/theme.cjs +44 -0
  237. package/dist/utils/theme.cjs.map +1 -0
  238. package/dist/utils/theme.mjs +37 -0
  239. package/dist/utils/theme.mjs.map +1 -0
  240. package/package.json +269 -80
  241. package/src/api-contract.ts +309 -0
  242. package/src/api.ts +181 -0
  243. package/src/app.ts +346 -0
  244. package/src/cli/catalog.ts +49 -0
  245. package/src/cli/help.ts +13 -0
  246. package/src/cli/init.ts +415 -0
  247. package/src/cli/parse.ts +130 -0
  248. package/src/cli/prompts.ts +64 -0
  249. package/src/cli.ts +203 -1507
  250. package/src/components/dev-view.tsx +104 -41
  251. package/src/components/streaming-view.ts +89 -22
  252. package/src/config.ts +462 -532
  253. package/src/contract.meta.ts +96 -0
  254. package/src/contract.ts +164 -561
  255. package/src/dev-logs.ts +85 -0
  256. package/src/dev-session.ts +318 -0
  257. package/src/fastkv.ts +153 -0
  258. package/src/federation.server.ts +43 -0
  259. package/src/host.ts +526 -0
  260. package/src/index.ts +6 -3
  261. package/src/integrity.ts +54 -0
  262. package/src/mf.ts +105 -0
  263. package/src/near-cli.ts +284 -0
  264. package/src/network.ts +3 -0
  265. package/src/orchestrator.ts +648 -0
  266. package/src/plugin.ts +1116 -2303
  267. package/src/process-registry.ts +154 -0
  268. package/src/scripts/sync-api-contract.ts +24 -0
  269. package/src/sdk.ts +14 -0
  270. package/src/shared.ts +206 -0
  271. package/src/types.ts +152 -206
  272. package/src/ui/head.ts +34 -27
  273. package/src/ui/index.ts +3 -3
  274. package/src/ui/metadata.ts +95 -0
  275. package/src/ui/router.ts +22 -6
  276. package/src/ui/runtime.ts +55 -6
  277. package/src/ui/types.ts +24 -11
  278. package/src/utils/banner.ts +10 -6
  279. package/src/utils/run.ts +26 -27
  280. package/src/utils/theme.ts +3 -66
  281. package/src/components/monitor-view.tsx +0 -475
  282. package/src/components/status-view.tsx +0 -173
  283. package/src/lib/env.ts +0 -109
  284. package/src/lib/near-cli.ts +0 -289
  285. package/src/lib/nova.ts +0 -266
  286. package/src/lib/orchestrator.ts +0 -276
  287. package/src/lib/process-registry.ts +0 -166
  288. package/src/lib/process.ts +0 -549
  289. package/src/lib/resource-monitor/assertions.ts +0 -234
  290. package/src/lib/resource-monitor/command.ts +0 -283
  291. package/src/lib/resource-monitor/diff.ts +0 -157
  292. package/src/lib/resource-monitor/errors.ts +0 -127
  293. package/src/lib/resource-monitor/index.ts +0 -305
  294. package/src/lib/resource-monitor/platform/darwin.ts +0 -306
  295. package/src/lib/resource-monitor/platform/index.ts +0 -35
  296. package/src/lib/resource-monitor/platform/linux.ts +0 -332
  297. package/src/lib/resource-monitor/platform/windows.ts +0 -298
  298. package/src/lib/resource-monitor/snapshot.ts +0 -217
  299. package/src/lib/resource-monitor/types.ts +0 -74
  300. package/src/lib/session-recorder/errors.ts +0 -102
  301. package/src/lib/session-recorder/flows/login.ts +0 -210
  302. package/src/lib/session-recorder/index.ts +0 -361
  303. package/src/lib/session-recorder/playwright.ts +0 -257
  304. package/src/lib/session-recorder/report.ts +0 -353
  305. package/src/lib/session-recorder/server.ts +0 -267
  306. package/src/lib/session-recorder/types.ts +0 -115
  307. package/src/lib/sync.ts +0 -1
  308. package/src/ui/files.ts +0 -134
package/dist/api.d.cts ADDED
@@ -0,0 +1,36 @@
1
+ import { RuntimeConfig } from "./types.cjs";
2
+
3
+ //#region src/api.d.ts
4
+ interface LoadedPluginResult {
5
+ key: string;
6
+ name: string;
7
+ router: any;
8
+ createClient: (context?: unknown) => any;
9
+ metadata: {
10
+ remoteUrl: string;
11
+ version?: string;
12
+ };
13
+ }
14
+ interface LoadedPluginsResult {
15
+ base: LoadedPluginResult | null;
16
+ plugins: LoadedPluginResult[];
17
+ errors: Array<{
18
+ key: string;
19
+ error: string;
20
+ }>;
21
+ }
22
+ declare function loadApiPlugin(opts: {
23
+ key: string;
24
+ runtimeId: string;
25
+ name: string;
26
+ entry: string;
27
+ variables?: Record<string, string>;
28
+ secrets?: Record<string, string>;
29
+ integrity?: string;
30
+ plugins?: Record<string, unknown>;
31
+ }): Promise<LoadedPluginResult>;
32
+ declare function loadApiPluginsFromRuntimeConfig(runtimeConfig: RuntimeConfig, envSecrets?: Record<string, string>): Promise<LoadedPluginsResult>;
33
+ declare function createStitchedRouter(baseRouter: any, plugins: LoadedPluginResult[] | null): any;
34
+ //#endregion
35
+ export { LoadedPluginResult, LoadedPluginsResult, createStitchedRouter, loadApiPlugin, loadApiPluginsFromRuntimeConfig };
36
+ //# sourceMappingURL=api.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.cts","names":[],"sources":["../src/api.ts"],"mappings":";;;UAKiB,kBAAA;EACf,GAAA;EACA,IAAA;EACA,MAAA;EACA,YAAA,GAAe,OAAA;EACf,QAAA;IACE,SAAA;IACA,OAAA;EAAA;AAAA;AAAA,UAIa,mBAAA;EACf,IAAA,EAAM,kBAAA;EACN,OAAA,EAAS,kBAAA;EACT,MAAA,EAAQ,KAAA;IAAQ,GAAA;IAAa,KAAA;EAAA;AAAA;AAAA,iBAGT,aAAA,CAAc,IAAA;EAClC,GAAA;EACA,SAAA;EACA,IAAA;EACA,KAAA;EACA,SAAA,GAAY,MAAA;EACZ,OAAA,GAAU,MAAA;EACV,SAAA;EACA,OAAA,GAAU,MAAA;AAAA,IACR,OAAA,CAAQ,kBAAA;AAAA,iBAyDU,+BAAA,CACpB,aAAA,EAAe,aAAA,EACf,UAAA,GAAa,MAAA,mBACZ,OAAA,CAAQ,mBAAA;AAAA,iBAmFK,oBAAA,CAAqB,UAAA,OAAiB,OAAA,EAAS,kBAAA"}
package/dist/api.d.mts ADDED
@@ -0,0 +1,36 @@
1
+ import { RuntimeConfig } from "./types.mjs";
2
+
3
+ //#region src/api.d.ts
4
+ interface LoadedPluginResult {
5
+ key: string;
6
+ name: string;
7
+ router: any;
8
+ createClient: (context?: unknown) => any;
9
+ metadata: {
10
+ remoteUrl: string;
11
+ version?: string;
12
+ };
13
+ }
14
+ interface LoadedPluginsResult {
15
+ base: LoadedPluginResult | null;
16
+ plugins: LoadedPluginResult[];
17
+ errors: Array<{
18
+ key: string;
19
+ error: string;
20
+ }>;
21
+ }
22
+ declare function loadApiPlugin(opts: {
23
+ key: string;
24
+ runtimeId: string;
25
+ name: string;
26
+ entry: string;
27
+ variables?: Record<string, string>;
28
+ secrets?: Record<string, string>;
29
+ integrity?: string;
30
+ plugins?: Record<string, unknown>;
31
+ }): Promise<LoadedPluginResult>;
32
+ declare function loadApiPluginsFromRuntimeConfig(runtimeConfig: RuntimeConfig, envSecrets?: Record<string, string>): Promise<LoadedPluginsResult>;
33
+ declare function createStitchedRouter(baseRouter: any, plugins: LoadedPluginResult[] | null): any;
34
+ //#endregion
35
+ export { LoadedPluginResult, LoadedPluginsResult, createStitchedRouter, loadApiPlugin, loadApiPluginsFromRuntimeConfig };
36
+ //# sourceMappingURL=api.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.mts","names":[],"sources":["../src/api.ts"],"mappings":";;;UAKiB,kBAAA;EACf,GAAA;EACA,IAAA;EACA,MAAA;EACA,YAAA,GAAe,OAAA;EACf,QAAA;IACE,SAAA;IACA,OAAA;EAAA;AAAA;AAAA,UAIa,mBAAA;EACf,IAAA,EAAM,kBAAA;EACN,OAAA,EAAS,kBAAA;EACT,MAAA,EAAQ,KAAA;IAAQ,GAAA;IAAa,KAAA;EAAA;AAAA;AAAA,iBAGT,aAAA,CAAc,IAAA;EAClC,GAAA;EACA,SAAA;EACA,IAAA;EACA,KAAA;EACA,SAAA,GAAY,MAAA;EACZ,OAAA,GAAU,MAAA;EACV,SAAA;EACA,OAAA,GAAU,MAAA;AAAA,IACR,OAAA,CAAQ,kBAAA;AAAA,iBAyDU,+BAAA,CACpB,aAAA,EAAe,aAAA,EACf,UAAA,GAAa,MAAA,mBACZ,OAAA,CAAQ,mBAAA;AAAA,iBAmFK,oBAAA,CAAqB,UAAA,OAAiB,OAAA,EAAS,kBAAA"}
package/dist/api.mjs ADDED
@@ -0,0 +1,119 @@
1
+ import { createPluginRuntime } from "./sdk.mjs";
2
+ import { ensureNodeRuntimePlugin, registerRemote } from "./mf.mjs";
3
+ import { verifySriForUrl } from "./integrity.mjs";
4
+
5
+ //#region src/api.ts
6
+ async function loadApiPlugin(opts) {
7
+ const remoteEntryUrl = (() => {
8
+ if (opts.entry.endsWith("/remoteEntry.js")) return opts.entry;
9
+ if (opts.entry.endsWith("/mf-manifest.json")) return `${opts.entry.replace(/\/mf-manifest\.json$/, "")}/remoteEntry.js`;
10
+ if (opts.entry.endsWith(".js")) return opts.entry;
11
+ return `${opts.entry.replace(/\/$/, "")}/remoteEntry.js`;
12
+ })();
13
+ if (opts.integrity) await verifySriForUrl(remoteEntryUrl, opts.integrity);
14
+ await ensureNodeRuntimePlugin();
15
+ await registerRemote({
16
+ name: opts.runtimeId,
17
+ entry: remoteEntryUrl
18
+ });
19
+ const plugin = await createPluginRuntime({
20
+ registry: { [opts.runtimeId]: { remote: remoteEntryUrl } },
21
+ secrets: opts.secrets ?? {}
22
+ }).usePlugin(opts.runtimeId, {
23
+ variables: opts.variables ?? {},
24
+ secrets: opts.secrets ?? {}
25
+ }, opts.plugins);
26
+ return {
27
+ key: opts.key,
28
+ name: opts.name,
29
+ router: plugin.router,
30
+ createClient: plugin.createClient,
31
+ metadata: {
32
+ remoteUrl: remoteEntryUrl,
33
+ version: plugin.metadata.version
34
+ }
35
+ };
36
+ }
37
+ function collectSecrets(config, envSecrets) {
38
+ const secrets = {};
39
+ for (const key of config.secrets ?? []) {
40
+ const value = envSecrets?.[key] ?? process.env[key];
41
+ if (value) secrets[key] = value;
42
+ }
43
+ return secrets;
44
+ }
45
+ async function loadApiPluginsFromRuntimeConfig(runtimeConfig, envSecrets) {
46
+ const entries = [];
47
+ if (runtimeConfig.api?.url) entries.push(["api", runtimeConfig.api]);
48
+ for (const [key, plugin] of Object.entries(runtimeConfig.plugins ?? {})) if (plugin.url) entries.push([key, plugin]);
49
+ if (entries.length === 0) {
50
+ console.log("[API] No plugins configured");
51
+ return {
52
+ base: null,
53
+ plugins: [],
54
+ errors: []
55
+ };
56
+ }
57
+ const pluginEntries = entries.filter(([key]) => key !== "api");
58
+ const apiEntry = entries.find(([key]) => key === "api");
59
+ const pluginResults = await Promise.allSettled(pluginEntries.map(async ([key, pluginConfig]) => {
60
+ console.log(`[API] Loading plugin: ${pluginConfig.name} from ${pluginConfig.entry}`);
61
+ return loadApiPlugin({
62
+ key,
63
+ runtimeId: pluginConfig.name,
64
+ name: pluginConfig.name,
65
+ entry: pluginConfig.entry,
66
+ variables: pluginConfig.variables,
67
+ secrets: collectSecrets(pluginConfig, envSecrets),
68
+ integrity: pluginConfig.integrity
69
+ });
70
+ }));
71
+ const plugins = [];
72
+ const errors = [];
73
+ const pluginsClient = {};
74
+ pluginResults.forEach((result, index) => {
75
+ const [key] = pluginEntries[index] ?? ["unknown"];
76
+ if (result.status === "fulfilled") {
77
+ plugins.push(result.value);
78
+ pluginsClient[key] = result.value.createClient;
79
+ } else errors.push({
80
+ key,
81
+ error: result.reason instanceof Error ? result.reason.message : String(result.reason)
82
+ });
83
+ });
84
+ let base = null;
85
+ if (apiEntry) {
86
+ const [key, apiConfig] = apiEntry;
87
+ try {
88
+ console.log(`[API] Loading API plugin: ${apiConfig.name} from ${apiConfig.entry}`);
89
+ base = await loadApiPlugin({
90
+ key,
91
+ runtimeId: apiConfig.name,
92
+ name: apiConfig.name,
93
+ entry: apiConfig.entry,
94
+ variables: apiConfig.variables,
95
+ secrets: collectSecrets(apiConfig, envSecrets),
96
+ integrity: apiConfig.integrity,
97
+ plugins: pluginsClient
98
+ });
99
+ } catch (error) {
100
+ errors.push({
101
+ key,
102
+ error: error instanceof Error ? error.message : String(error)
103
+ });
104
+ }
105
+ }
106
+ return {
107
+ base,
108
+ plugins,
109
+ errors
110
+ };
111
+ }
112
+ function createStitchedRouter(baseRouter, plugins) {
113
+ if (!plugins || plugins.length === 0) return baseRouter;
114
+ return plugins.reduce((router, plugin) => Object.assign(router, plugin.router), baseRouter);
115
+ }
116
+
117
+ //#endregion
118
+ export { createStitchedRouter, loadApiPlugin, loadApiPluginsFromRuntimeConfig };
119
+ //# sourceMappingURL=api.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.mjs","names":[],"sources":["../src/api.ts"],"sourcesContent":["import { verifySriForUrl } from \"./integrity\";\nimport { ensureNodeRuntimePlugin, registerRemote } from \"./mf\";\nimport { createPluginRuntime } from \"./sdk\";\nimport type { RuntimeConfig, RuntimePluginConfig } from \"./types\";\n\nexport interface LoadedPluginResult {\n key: string;\n name: string;\n router: any;\n createClient: (context?: unknown) => any;\n metadata: {\n remoteUrl: string;\n version?: string;\n };\n}\n\nexport interface LoadedPluginsResult {\n base: LoadedPluginResult | null;\n plugins: LoadedPluginResult[];\n errors: Array<{ key: string; error: string }>;\n}\n\nexport async function loadApiPlugin(opts: {\n key: string;\n runtimeId: string;\n name: string;\n entry: string;\n variables?: Record<string, string>;\n secrets?: Record<string, string>;\n integrity?: string;\n plugins?: Record<string, unknown>;\n}): Promise<LoadedPluginResult> {\n const remoteEntryUrl = (() => {\n if (opts.entry.endsWith(\"/remoteEntry.js\")) return opts.entry;\n if (opts.entry.endsWith(\"/mf-manifest.json\")) {\n return `${opts.entry.replace(/\\/mf-manifest\\.json$/, \"\")}/remoteEntry.js`;\n }\n if (opts.entry.endsWith(\".js\")) return opts.entry;\n return `${opts.entry.replace(/\\/$/, \"\")}/remoteEntry.js`;\n })();\n\n if (opts.integrity) {\n await verifySriForUrl(remoteEntryUrl, opts.integrity);\n }\n\n await ensureNodeRuntimePlugin();\n await registerRemote({ name: opts.runtimeId, entry: remoteEntryUrl });\n\n const runtime: any = createPluginRuntime({\n registry: {\n [opts.runtimeId]: { remote: remoteEntryUrl },\n },\n secrets: opts.secrets ?? {},\n });\n\n // biome-ignore lint/correctness/useHookAtTopLevel: usePlugin is not a React hook\n const plugin = await runtime.usePlugin(\n opts.runtimeId,\n {\n variables: opts.variables ?? {},\n secrets: opts.secrets ?? {},\n },\n opts.plugins,\n );\n\n return {\n key: opts.key,\n name: opts.name,\n router: plugin.router,\n createClient: plugin.createClient as (context?: unknown) => any,\n metadata: {\n remoteUrl: remoteEntryUrl,\n version: plugin.metadata.version,\n },\n };\n}\n\nfunction collectSecrets(config: RuntimePluginConfig, envSecrets?: Record<string, string>) {\n const secrets: Record<string, string> = {};\n for (const key of config.secrets ?? []) {\n const value = envSecrets?.[key] ?? process.env[key];\n if (value) {\n secrets[key] = value;\n }\n }\n return secrets;\n}\n\nexport async function loadApiPluginsFromRuntimeConfig(\n runtimeConfig: RuntimeConfig,\n envSecrets?: Record<string, string>,\n): Promise<LoadedPluginsResult> {\n const entries: Array<[string, RuntimePluginConfig]> = [];\n\n if (runtimeConfig.api?.url) {\n entries.push([\"api\", runtimeConfig.api]);\n }\n\n for (const [key, plugin] of Object.entries(runtimeConfig.plugins ?? {})) {\n if (plugin.url) {\n entries.push([key, plugin]);\n }\n }\n\n if (entries.length === 0) {\n console.log(\"[API] No plugins configured\");\n return { base: null, plugins: [], errors: [] };\n }\n\n // Phase 1: Load non-API plugins first\n const pluginEntries = entries.filter(([key]) => key !== \"api\");\n const apiEntry = entries.find(([key]) => key === \"api\");\n\n const pluginResults = await Promise.allSettled(\n pluginEntries.map(async ([key, pluginConfig]) => {\n console.log(`[API] Loading plugin: ${pluginConfig.name} from ${pluginConfig.entry}`);\n return loadApiPlugin({\n key,\n runtimeId: pluginConfig.name,\n name: pluginConfig.name,\n entry: pluginConfig.entry,\n variables: pluginConfig.variables,\n secrets: collectSecrets(pluginConfig, envSecrets),\n integrity: pluginConfig.integrity,\n });\n }),\n );\n\n const plugins: LoadedPluginResult[] = [];\n const errors: Array<{ key: string; error: string }> = [];\n\n const pluginsClient: Record<string, unknown> = {};\n\n pluginResults.forEach((result, index) => {\n const [key] = pluginEntries[index] ?? [\"unknown\"];\n if (result.status === \"fulfilled\") {\n plugins.push(result.value);\n pluginsClient[key] = result.value.createClient;\n } else {\n errors.push({\n key,\n error: result.reason instanceof Error ? result.reason.message : String(result.reason),\n });\n }\n });\n\n // Phase 2: Load API plugin with injected plugins client\n let base: LoadedPluginResult | null = null;\n\n if (apiEntry) {\n const [key, apiConfig] = apiEntry;\n try {\n console.log(`[API] Loading API plugin: ${apiConfig.name} from ${apiConfig.entry}`);\n base = await loadApiPlugin({\n key,\n runtimeId: apiConfig.name,\n name: apiConfig.name,\n entry: apiConfig.entry,\n variables: apiConfig.variables,\n secrets: collectSecrets(apiConfig, envSecrets),\n integrity: apiConfig.integrity,\n plugins: pluginsClient,\n });\n } catch (error) {\n errors.push({\n key,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n return { base, plugins, errors };\n}\n\nexport function createStitchedRouter(baseRouter: any, plugins: LoadedPluginResult[] | null): any {\n if (!plugins || plugins.length === 0) {\n return baseRouter;\n }\n\n return plugins.reduce((router, plugin) => Object.assign(router, plugin.router), baseRouter);\n}\n"],"mappings":"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"}
package/dist/app.cjs ADDED
@@ -0,0 +1,156 @@
1
+ const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
2
+ const require_network = require('./network.cjs');
3
+ const require_config = require('./config.cjs');
4
+ require('./orchestrator.cjs');
5
+ let node_fs = require("node:fs");
6
+ let node_path = require("node:path");
7
+ let effect = require("effect");
8
+ let node_net = require("node:net");
9
+
10
+ //#region src/app.ts
11
+ const DEFAULT_HOST_PORT = 3e3;
12
+ const DEFAULT_UI_PORT = 3002;
13
+ const DEFAULT_API_PORT = 3014;
14
+ const DEFAULT_PLUGIN_PORT_START = 3021;
15
+ function detectLocalPackages(bosConfig, runtimeConfig) {
16
+ const packages = [];
17
+ const configDir = require_config.getProjectRoot();
18
+ const uiLocalPath = runtimeConfig?.ui.localPath ?? require_config.resolveLocalDevelopmentPath(bosConfig?.app.ui.development, configDir);
19
+ if (uiLocalPath && (0, node_fs.existsSync)((0, node_path.join)(uiLocalPath, "package.json"))) packages.push("ui");
20
+ const apiLocalPath = runtimeConfig?.api.localPath ?? require_config.resolveLocalDevelopmentPath(bosConfig?.app.api.development, configDir);
21
+ if (apiLocalPath && (0, node_fs.existsSync)((0, node_path.join)(apiLocalPath, "package.json"))) packages.push("api");
22
+ const hostLocalPath = require_config.resolveLocalDevelopmentPath(bosConfig?.app.host.development, configDir);
23
+ if (hostLocalPath && (0, node_fs.existsSync)((0, node_path.join)(hostLocalPath, "package.json"))) packages.push("host");
24
+ else if ((0, node_fs.existsSync)((0, node_path.join)(configDir, "host", "package.json"))) packages.push("host");
25
+ for (const [pluginId, pluginConfig] of Object.entries(runtimeConfig?.plugins ?? {})) if (pluginConfig.localPath && (0, node_fs.existsSync)((0, node_path.join)(pluginConfig.localPath, "package.json"))) packages.push(`plugin:${pluginId}`);
26
+ return packages;
27
+ }
28
+ function buildRuntimeConfig(bosConfig, options) {
29
+ const configDir = require_config.getProjectRoot();
30
+ const uiConfig = bosConfig.app.ui;
31
+ const apiConfig = bosConfig.app.api;
32
+ const uiSource = options.uiSource ?? "local";
33
+ const apiSource = options.apiSource ?? "local";
34
+ const uiLocalPath = require_config.resolveLocalDevelopmentPath(uiConfig.development, configDir);
35
+ const apiLocalPath = require_config.resolveLocalDevelopmentPath(apiConfig.development, configDir);
36
+ const uiLocalUrl = !uiLocalPath && uiConfig.development && !require_config.isLocalDevelopmentTarget(uiConfig.development) ? uiConfig.development : "";
37
+ const apiLocalUrl = !apiLocalPath && apiConfig.development && !require_config.isLocalDevelopmentTarget(apiConfig.development) ? apiConfig.development : "";
38
+ return {
39
+ env: options.env ?? "development",
40
+ account: bosConfig.account,
41
+ domain: bosConfig.domain,
42
+ networkId: require_network.getNetworkIdForAccount(bosConfig.account),
43
+ hostUrl: options.hostUrl,
44
+ shared: bosConfig.shared,
45
+ ui: uiConfig ? {
46
+ name: uiConfig.name,
47
+ url: uiSource === "remote" ? uiConfig.production ?? "" : uiLocalUrl,
48
+ entry: uiSource === "remote" ? `${uiConfig.production ?? ""}/mf-manifest.json` : uiLocalUrl ? `${uiLocalUrl}/mf-manifest.json` : "/mf-manifest.json",
49
+ localPath: uiSource === "local" ? uiLocalPath ?? void 0 : void 0,
50
+ port: uiSource === "local" && uiLocalUrl ? require_config.parsePort(uiLocalUrl) : void 0,
51
+ ssrUrl: uiSource === "remote" ? uiConfig.ssr : void 0,
52
+ ssrIntegrity: uiSource === "remote" ? uiConfig.ssrIntegrity : void 0,
53
+ integrity: uiSource === "remote" ? uiConfig.productionIntegrity : void 0,
54
+ source: uiSource === "local" ? uiLocalPath ? "local" : "remote" : "remote"
55
+ } : {
56
+ name: "ui",
57
+ url: "",
58
+ entry: "/mf-manifest.json",
59
+ source: uiSource
60
+ },
61
+ api: apiConfig ? {
62
+ name: apiConfig.name,
63
+ url: apiSource === "remote" ? apiConfig.production ?? "" : apiLocalUrl,
64
+ entry: apiSource === "remote" ? `${apiConfig.production ?? ""}/mf-manifest.json` : apiLocalUrl ? `${apiLocalUrl}/mf-manifest.json` : "/mf-manifest.json",
65
+ localPath: apiSource === "local" ? apiLocalPath ?? void 0 : void 0,
66
+ port: apiSource === "local" && apiLocalUrl ? require_config.parsePort(apiLocalUrl) : void 0,
67
+ source: apiSource === "local" ? apiLocalPath ? "local" : "remote" : "remote",
68
+ proxy: options.proxy ?? apiConfig.proxy,
69
+ variables: apiConfig.variables,
70
+ secrets: apiConfig.secrets,
71
+ integrity: apiSource === "remote" ? apiConfig.productionIntegrity : void 0
72
+ } : {
73
+ name: "api",
74
+ url: "",
75
+ entry: "/mf-manifest.json",
76
+ source: apiSource
77
+ },
78
+ plugins: options.plugins
79
+ };
80
+ }
81
+ function probeTcpOpen(port, timeoutMs = 250) {
82
+ return new Promise((resolve) => {
83
+ const socket = (0, node_net.createConnection)({
84
+ host: "127.0.0.1",
85
+ port
86
+ });
87
+ const timer = setTimeout(() => {
88
+ socket.destroy();
89
+ resolve(false);
90
+ }, timeoutMs);
91
+ socket.once("connect", () => {
92
+ clearTimeout(timer);
93
+ socket.destroy();
94
+ resolve(true);
95
+ });
96
+ socket.once("error", () => {
97
+ clearTimeout(timer);
98
+ resolve(false);
99
+ });
100
+ });
101
+ }
102
+ async function pickAvailablePort(preferred, usedPorts) {
103
+ let port = preferred;
104
+ while (usedPorts.has(port) || await probeTcpOpen(port)) port += 1;
105
+ usedPorts.add(port);
106
+ return port;
107
+ }
108
+ function withLocalRuntimeUrl(entry, port) {
109
+ const url = `http://localhost:${port}`;
110
+ return {
111
+ ...entry,
112
+ url,
113
+ entry: `${url}/mf-manifest.json`,
114
+ port
115
+ };
116
+ }
117
+ async function prepareDevelopmentRuntimeConfig(runtimeConfig, options) {
118
+ const usedPorts = /* @__PURE__ */ new Set();
119
+ const hostPort = await pickAvailablePort(options?.hostPort ?? (runtimeConfig.hostUrl ? require_config.parsePort(runtimeConfig.hostUrl) : DEFAULT_HOST_PORT), usedPorts);
120
+ const next = {
121
+ ...runtimeConfig,
122
+ hostUrl: `http://localhost:${hostPort}`,
123
+ ui: { ...runtimeConfig.ui },
124
+ api: { ...runtimeConfig.api },
125
+ plugins: runtimeConfig.plugins ? { ...runtimeConfig.plugins } : void 0
126
+ };
127
+ if (next.ui.source === "local" && next.ui.localPath) {
128
+ const uiPort = await pickAvailablePort(next.ui.port ?? DEFAULT_UI_PORT, usedPorts);
129
+ next.ui = withLocalRuntimeUrl(next.ui, uiPort);
130
+ if (options?.ssr) {
131
+ const ssrPort = await pickAvailablePort(uiPort + 1, usedPorts);
132
+ next.ui.ssrUrl = `http://localhost:${ssrPort}`;
133
+ } else next.ui.ssrUrl = void 0;
134
+ }
135
+ if (next.api.source === "local" && next.api.localPath) {
136
+ const apiPort = await pickAvailablePort(next.api.port ?? DEFAULT_API_PORT, usedPorts);
137
+ next.api = withLocalRuntimeUrl(next.api, apiPort);
138
+ }
139
+ if (next.plugins) {
140
+ const entries = Object.entries(next.plugins).sort(([a], [b]) => a.localeCompare(b));
141
+ let pluginBasePort = DEFAULT_PLUGIN_PORT_START;
142
+ for (const [pluginId, plugin] of entries) {
143
+ if (plugin.source !== "local" || !plugin.localPath) continue;
144
+ const pluginPort = await pickAvailablePort(plugin.port ?? pluginBasePort, usedPorts);
145
+ next.plugins[pluginId] = withLocalRuntimeUrl(plugin, pluginPort);
146
+ pluginBasePort = pluginPort + 1;
147
+ }
148
+ }
149
+ return next;
150
+ }
151
+
152
+ //#endregion
153
+ exports.buildRuntimeConfig = buildRuntimeConfig;
154
+ exports.detectLocalPackages = detectLocalPackages;
155
+ exports.prepareDevelopmentRuntimeConfig = prepareDevelopmentRuntimeConfig;
156
+ //# sourceMappingURL=app.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.cjs","names":["getProjectRoot","resolveLocalDevelopmentPath","isLocalDevelopmentTarget","getNetworkIdForAccount","parsePort"],"sources":["../src/app.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { createConnection } from \"node:net\";\nimport { join } from \"node:path\";\nimport { Effect } from \"effect\";\nimport {\n getProjectRoot,\n isLocalDevelopmentTarget,\n parsePort,\n resolveLocalDevelopmentPath,\n} from \"./config\";\nimport { getNetworkIdForAccount } from \"./network\";\nimport { makeDevProcess, type ProcessCallbacks, type ProcessHandle } from \"./orchestrator\";\nimport type { ProcessRegistry } from \"./process-registry\";\nimport type { BosConfig, RuntimeConfig, RuntimePluginConfig } from \"./types\";\n\nexport interface AppOrchestrator {\n packages: string[];\n env: Record<string, string>;\n description: string;\n bosConfig: BosConfig;\n runtimeConfig: RuntimeConfig;\n port?: number;\n interactive?: boolean;\n}\n\nconst STARTUP_ORDER = [\"ui-ssr\", \"ui\", \"api\", \"plugin\", \"host-build\", \"host\"];\nconst DEFAULT_HOST_PORT = 3000;\nconst DEFAULT_UI_PORT = 3002;\nconst DEFAULT_API_PORT = 3014;\nconst DEFAULT_PLUGIN_PORT_START = 3021;\n\nconst sortByOrder = (packages: string[]): string[] => {\n return [...packages].sort((a, b) => {\n const aIdx = a.startsWith(\"plugin:\")\n ? STARTUP_ORDER.indexOf(\"plugin\")\n : STARTUP_ORDER.indexOf(a);\n const bIdx = b.startsWith(\"plugin:\")\n ? STARTUP_ORDER.indexOf(\"plugin\")\n : STARTUP_ORDER.indexOf(b);\n if (aIdx === -1 && bIdx === -1) return 0;\n if (aIdx === -1) return 1;\n if (bIdx === -1) return -1;\n return aIdx - bIdx;\n });\n};\n\n// Note: log filtering and persistence lives at the CLI layer.\n\nexport interface DevServersHandle {\n handles: ProcessHandle[];\n shutdown: Effect.Effect<void>;\n}\n\nexport const startDevServers = (\n orchestrator: AppOrchestrator,\n callbacks: ProcessCallbacks,\n registry?: ProcessRegistry,\n) => {\n const run = Effect.gen(function* () {\n const orderedPackages = sortByOrder(orchestrator.packages);\n const handles: ProcessHandle[] = [];\n\n const startProcess = (pkg: string) => {\n const portOverride = pkg === \"host\" ? orchestrator.port : undefined;\n return makeDevProcess(\n pkg,\n orchestrator.env,\n callbacks,\n portOverride,\n orchestrator.bosConfig,\n orchestrator.runtimeConfig,\n registry,\n );\n };\n\n const startGroup = (packages: string[]) =>\n Effect.forEach(packages, startProcess, { concurrency: \"unbounded\" });\n\n const awaitReady = (pkg: string, handle: ProcessHandle) =>\n Effect.race(\n handle.waitForReady,\n Effect.sleep(\"30 seconds\").pipe(\n Effect.andThen(\n Effect.sync(() => {\n callbacks.onLog(pkg, \"Timeout waiting for ready, continuing...\", true);\n }),\n ),\n ),\n );\n\n const nonHostPackages = orderedPackages.filter((pkg) => pkg !== \"host\");\n const hostPackages = orderedPackages.filter((pkg) => pkg === \"host\");\n\n const nonHostHandles = yield* startGroup(nonHostPackages);\n handles.push(...nonHostHandles);\n\n yield* Effect.forEach(\n nonHostHandles.map((handle, index) => ({\n handle,\n pkg: nonHostPackages[index] ?? handle.name,\n })),\n ({ handle, pkg }) => awaitReady(pkg, handle),\n { concurrency: \"unbounded\" },\n );\n\n const hostHandles = yield* startGroup(hostPackages);\n handles.push(...hostHandles);\n\n yield* Effect.forEach(\n hostHandles.map((handle, index) => ({ handle, pkg: hostPackages[index] ?? handle.name })),\n ({ handle, pkg }) => awaitReady(pkg, handle),\n { concurrency: \"unbounded\" },\n );\n\n const shutdown = Effect.gen(function* () {\n const reversed = [...handles].reverse();\n for (const handle of reversed) {\n yield* Effect.tryPromise({\n try: () => handle.kill(),\n catch: () => null,\n }).pipe(Effect.ignore);\n }\n });\n\n return { handles, shutdown } satisfies DevServersHandle;\n });\n\n return run;\n};\n\nexport function detectLocalPackages(\n bosConfig?: BosConfig,\n runtimeConfig?: RuntimeConfig,\n): string[] {\n const packages: string[] = [];\n const configDir = getProjectRoot();\n\n const uiLocalPath =\n runtimeConfig?.ui.localPath ??\n resolveLocalDevelopmentPath(bosConfig?.app.ui.development, configDir);\n if (uiLocalPath && existsSync(join(uiLocalPath, \"package.json\"))) {\n packages.push(\"ui\");\n }\n\n const apiLocalPath =\n runtimeConfig?.api.localPath ??\n resolveLocalDevelopmentPath(bosConfig?.app.api.development, configDir);\n if (apiLocalPath && existsSync(join(apiLocalPath, \"package.json\"))) {\n packages.push(\"api\");\n }\n\n const hostLocalPath = resolveLocalDevelopmentPath(bosConfig?.app.host.development, configDir);\n if (hostLocalPath && existsSync(join(hostLocalPath, \"package.json\"))) {\n packages.push(\"host\");\n } else if (existsSync(join(configDir, \"host\", \"package.json\"))) {\n packages.push(\"host\");\n }\n\n for (const [pluginId, pluginConfig] of Object.entries(runtimeConfig?.plugins ?? {})) {\n if (pluginConfig.localPath && existsSync(join(pluginConfig.localPath, \"package.json\"))) {\n packages.push(`plugin:${pluginId}`);\n }\n }\n\n return packages;\n}\n\nexport function buildRuntimeConfig(\n bosConfig: BosConfig,\n options: {\n uiSource?: \"local\" | \"remote\";\n apiSource?: \"local\" | \"remote\";\n hostUrl: string;\n proxy?: string;\n env?: \"development\" | \"production\";\n plugins?: Record<string, RuntimePluginConfig>;\n },\n): RuntimeConfig {\n const configDir = getProjectRoot();\n const uiConfig = bosConfig.app.ui;\n const apiConfig = bosConfig.app.api;\n const uiSource = options.uiSource ?? \"local\";\n const apiSource = options.apiSource ?? \"local\";\n const uiLocalPath = resolveLocalDevelopmentPath(uiConfig.development, configDir);\n const apiLocalPath = resolveLocalDevelopmentPath(apiConfig.development, configDir);\n const uiLocalUrl =\n !uiLocalPath && uiConfig.development && !isLocalDevelopmentTarget(uiConfig.development)\n ? uiConfig.development\n : \"\";\n const apiLocalUrl =\n !apiLocalPath && apiConfig.development && !isLocalDevelopmentTarget(apiConfig.development)\n ? apiConfig.development\n : \"\";\n\n return {\n env: options.env ?? \"development\",\n account: bosConfig.account,\n domain: bosConfig.domain,\n networkId: getNetworkIdForAccount(bosConfig.account),\n hostUrl: options.hostUrl,\n shared: bosConfig.shared,\n ui: uiConfig\n ? {\n name: uiConfig.name,\n url: uiSource === \"remote\" ? (uiConfig.production ?? \"\") : uiLocalUrl,\n entry:\n uiSource === \"remote\"\n ? `${uiConfig.production ?? \"\"}/mf-manifest.json`\n : uiLocalUrl\n ? `${uiLocalUrl}/mf-manifest.json`\n : \"/mf-manifest.json\",\n localPath: uiSource === \"local\" ? (uiLocalPath ?? undefined) : undefined,\n port: uiSource === \"local\" && uiLocalUrl ? parsePort(uiLocalUrl) : undefined,\n ssrUrl: uiSource === \"remote\" ? uiConfig.ssr : undefined,\n ssrIntegrity: uiSource === \"remote\" ? uiConfig.ssrIntegrity : undefined,\n integrity: uiSource === \"remote\" ? uiConfig.productionIntegrity : undefined,\n source: uiSource === \"local\" ? (uiLocalPath ? \"local\" : \"remote\") : \"remote\",\n }\n : {\n name: \"ui\",\n url: \"\",\n entry: \"/mf-manifest.json\",\n source: uiSource,\n },\n api: apiConfig\n ? {\n name: apiConfig.name,\n url: apiSource === \"remote\" ? (apiConfig.production ?? \"\") : apiLocalUrl,\n entry:\n apiSource === \"remote\"\n ? `${apiConfig.production ?? \"\"}/mf-manifest.json`\n : apiLocalUrl\n ? `${apiLocalUrl}/mf-manifest.json`\n : \"/mf-manifest.json\",\n localPath: apiSource === \"local\" ? (apiLocalPath ?? undefined) : undefined,\n port: apiSource === \"local\" && apiLocalUrl ? parsePort(apiLocalUrl) : undefined,\n source: apiSource === \"local\" ? (apiLocalPath ? \"local\" : \"remote\") : \"remote\",\n proxy: options.proxy ?? apiConfig.proxy,\n variables: apiConfig.variables,\n secrets: apiConfig.secrets,\n integrity: apiSource === \"remote\" ? apiConfig.productionIntegrity : undefined,\n }\n : {\n name: \"api\",\n url: \"\",\n entry: \"/mf-manifest.json\",\n source: apiSource,\n },\n plugins: options.plugins,\n };\n}\n\nfunction probeTcpOpen(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\n socket.once(\"connect\", () => {\n clearTimeout(timer);\n socket.destroy();\n resolve(true);\n });\n\n socket.once(\"error\", () => {\n clearTimeout(timer);\n resolve(false);\n });\n });\n}\n\nasync function pickAvailablePort(preferred: number, usedPorts: Set<number>): Promise<number> {\n let port = preferred;\n while (usedPorts.has(port) || (await probeTcpOpen(port))) {\n port += 1;\n }\n usedPorts.add(port);\n return port;\n}\n\nfunction withLocalRuntimeUrl<\n T extends { url: string; entry: string; port?: number; localPath?: string },\n>(entry: T, port: number): T {\n const url = `http://localhost:${port}`;\n return {\n ...entry,\n url,\n entry: `${url}/mf-manifest.json`,\n port,\n };\n}\n\nexport async function prepareDevelopmentRuntimeConfig(\n runtimeConfig: RuntimeConfig,\n options?: { hostPort?: number; ssr?: boolean },\n): Promise<RuntimeConfig> {\n const usedPorts = new Set<number>();\n const hostPort = await pickAvailablePort(\n options?.hostPort ??\n (runtimeConfig.hostUrl ? parsePort(runtimeConfig.hostUrl) : DEFAULT_HOST_PORT),\n usedPorts,\n );\n\n const next: RuntimeConfig = {\n ...runtimeConfig,\n hostUrl: `http://localhost:${hostPort}`,\n ui: { ...runtimeConfig.ui },\n api: { ...runtimeConfig.api },\n plugins: runtimeConfig.plugins ? { ...runtimeConfig.plugins } : undefined,\n };\n\n if (next.ui.source === \"local\" && next.ui.localPath) {\n const uiPort = await pickAvailablePort(next.ui.port ?? DEFAULT_UI_PORT, usedPorts);\n next.ui = withLocalRuntimeUrl(next.ui, uiPort);\n if (options?.ssr) {\n const ssrPort = await pickAvailablePort(uiPort + 1, usedPorts);\n next.ui.ssrUrl = `http://localhost:${ssrPort}`;\n } else {\n next.ui.ssrUrl = undefined;\n }\n }\n\n if (next.api.source === \"local\" && next.api.localPath) {\n const apiPort = await pickAvailablePort(next.api.port ?? DEFAULT_API_PORT, usedPorts);\n next.api = withLocalRuntimeUrl(next.api, apiPort);\n }\n\n if (next.plugins) {\n const entries = Object.entries(next.plugins).sort(([a], [b]) => a.localeCompare(b));\n let pluginBasePort = DEFAULT_PLUGIN_PORT_START;\n\n for (const [pluginId, plugin] of entries) {\n if (plugin.source !== \"local\" || !plugin.localPath) {\n continue;\n }\n\n const pluginPort = await pickAvailablePort(plugin.port ?? pluginBasePort, usedPorts);\n next.plugins[pluginId] = withLocalRuntimeUrl(plugin, pluginPort);\n pluginBasePort = pluginPort + 1;\n }\n }\n\n return next;\n}\n"],"mappings":"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"}
package/dist/app.mjs ADDED
@@ -0,0 +1,153 @@
1
+ import { getNetworkIdForAccount } from "./network.mjs";
2
+ import { getProjectRoot, isLocalDevelopmentTarget, parsePort, resolveLocalDevelopmentPath } from "./config.mjs";
3
+ import "./orchestrator.mjs";
4
+ import { existsSync } from "node:fs";
5
+ import { join } from "node:path";
6
+ import { Effect } from "effect";
7
+ import { createConnection } from "node:net";
8
+
9
+ //#region src/app.ts
10
+ const DEFAULT_HOST_PORT = 3e3;
11
+ const DEFAULT_UI_PORT = 3002;
12
+ const DEFAULT_API_PORT = 3014;
13
+ const DEFAULT_PLUGIN_PORT_START = 3021;
14
+ function detectLocalPackages(bosConfig, runtimeConfig) {
15
+ const packages = [];
16
+ const configDir = getProjectRoot();
17
+ const uiLocalPath = runtimeConfig?.ui.localPath ?? resolveLocalDevelopmentPath(bosConfig?.app.ui.development, configDir);
18
+ if (uiLocalPath && existsSync(join(uiLocalPath, "package.json"))) packages.push("ui");
19
+ const apiLocalPath = runtimeConfig?.api.localPath ?? resolveLocalDevelopmentPath(bosConfig?.app.api.development, configDir);
20
+ if (apiLocalPath && existsSync(join(apiLocalPath, "package.json"))) packages.push("api");
21
+ const hostLocalPath = resolveLocalDevelopmentPath(bosConfig?.app.host.development, configDir);
22
+ if (hostLocalPath && existsSync(join(hostLocalPath, "package.json"))) packages.push("host");
23
+ else if (existsSync(join(configDir, "host", "package.json"))) packages.push("host");
24
+ for (const [pluginId, pluginConfig] of Object.entries(runtimeConfig?.plugins ?? {})) if (pluginConfig.localPath && existsSync(join(pluginConfig.localPath, "package.json"))) packages.push(`plugin:${pluginId}`);
25
+ return packages;
26
+ }
27
+ function buildRuntimeConfig(bosConfig, options) {
28
+ const configDir = getProjectRoot();
29
+ const uiConfig = bosConfig.app.ui;
30
+ const apiConfig = bosConfig.app.api;
31
+ const uiSource = options.uiSource ?? "local";
32
+ const apiSource = options.apiSource ?? "local";
33
+ const uiLocalPath = resolveLocalDevelopmentPath(uiConfig.development, configDir);
34
+ const apiLocalPath = resolveLocalDevelopmentPath(apiConfig.development, configDir);
35
+ const uiLocalUrl = !uiLocalPath && uiConfig.development && !isLocalDevelopmentTarget(uiConfig.development) ? uiConfig.development : "";
36
+ const apiLocalUrl = !apiLocalPath && apiConfig.development && !isLocalDevelopmentTarget(apiConfig.development) ? apiConfig.development : "";
37
+ return {
38
+ env: options.env ?? "development",
39
+ account: bosConfig.account,
40
+ domain: bosConfig.domain,
41
+ networkId: getNetworkIdForAccount(bosConfig.account),
42
+ hostUrl: options.hostUrl,
43
+ shared: bosConfig.shared,
44
+ ui: uiConfig ? {
45
+ name: uiConfig.name,
46
+ url: uiSource === "remote" ? uiConfig.production ?? "" : uiLocalUrl,
47
+ entry: uiSource === "remote" ? `${uiConfig.production ?? ""}/mf-manifest.json` : uiLocalUrl ? `${uiLocalUrl}/mf-manifest.json` : "/mf-manifest.json",
48
+ localPath: uiSource === "local" ? uiLocalPath ?? void 0 : void 0,
49
+ port: uiSource === "local" && uiLocalUrl ? parsePort(uiLocalUrl) : void 0,
50
+ ssrUrl: uiSource === "remote" ? uiConfig.ssr : void 0,
51
+ ssrIntegrity: uiSource === "remote" ? uiConfig.ssrIntegrity : void 0,
52
+ integrity: uiSource === "remote" ? uiConfig.productionIntegrity : void 0,
53
+ source: uiSource === "local" ? uiLocalPath ? "local" : "remote" : "remote"
54
+ } : {
55
+ name: "ui",
56
+ url: "",
57
+ entry: "/mf-manifest.json",
58
+ source: uiSource
59
+ },
60
+ api: apiConfig ? {
61
+ name: apiConfig.name,
62
+ url: apiSource === "remote" ? apiConfig.production ?? "" : apiLocalUrl,
63
+ entry: apiSource === "remote" ? `${apiConfig.production ?? ""}/mf-manifest.json` : apiLocalUrl ? `${apiLocalUrl}/mf-manifest.json` : "/mf-manifest.json",
64
+ localPath: apiSource === "local" ? apiLocalPath ?? void 0 : void 0,
65
+ port: apiSource === "local" && apiLocalUrl ? parsePort(apiLocalUrl) : void 0,
66
+ source: apiSource === "local" ? apiLocalPath ? "local" : "remote" : "remote",
67
+ proxy: options.proxy ?? apiConfig.proxy,
68
+ variables: apiConfig.variables,
69
+ secrets: apiConfig.secrets,
70
+ integrity: apiSource === "remote" ? apiConfig.productionIntegrity : void 0
71
+ } : {
72
+ name: "api",
73
+ url: "",
74
+ entry: "/mf-manifest.json",
75
+ source: apiSource
76
+ },
77
+ plugins: options.plugins
78
+ };
79
+ }
80
+ function probeTcpOpen(port, timeoutMs = 250) {
81
+ return new Promise((resolve) => {
82
+ const socket = createConnection({
83
+ host: "127.0.0.1",
84
+ port
85
+ });
86
+ const timer = setTimeout(() => {
87
+ socket.destroy();
88
+ resolve(false);
89
+ }, timeoutMs);
90
+ socket.once("connect", () => {
91
+ clearTimeout(timer);
92
+ socket.destroy();
93
+ resolve(true);
94
+ });
95
+ socket.once("error", () => {
96
+ clearTimeout(timer);
97
+ resolve(false);
98
+ });
99
+ });
100
+ }
101
+ async function pickAvailablePort(preferred, usedPorts) {
102
+ let port = preferred;
103
+ while (usedPorts.has(port) || await probeTcpOpen(port)) port += 1;
104
+ usedPorts.add(port);
105
+ return port;
106
+ }
107
+ function withLocalRuntimeUrl(entry, port) {
108
+ const url = `http://localhost:${port}`;
109
+ return {
110
+ ...entry,
111
+ url,
112
+ entry: `${url}/mf-manifest.json`,
113
+ port
114
+ };
115
+ }
116
+ async function prepareDevelopmentRuntimeConfig(runtimeConfig, options) {
117
+ const usedPorts = /* @__PURE__ */ new Set();
118
+ const hostPort = await pickAvailablePort(options?.hostPort ?? (runtimeConfig.hostUrl ? parsePort(runtimeConfig.hostUrl) : DEFAULT_HOST_PORT), usedPorts);
119
+ const next = {
120
+ ...runtimeConfig,
121
+ hostUrl: `http://localhost:${hostPort}`,
122
+ ui: { ...runtimeConfig.ui },
123
+ api: { ...runtimeConfig.api },
124
+ plugins: runtimeConfig.plugins ? { ...runtimeConfig.plugins } : void 0
125
+ };
126
+ if (next.ui.source === "local" && next.ui.localPath) {
127
+ const uiPort = await pickAvailablePort(next.ui.port ?? DEFAULT_UI_PORT, usedPorts);
128
+ next.ui = withLocalRuntimeUrl(next.ui, uiPort);
129
+ if (options?.ssr) {
130
+ const ssrPort = await pickAvailablePort(uiPort + 1, usedPorts);
131
+ next.ui.ssrUrl = `http://localhost:${ssrPort}`;
132
+ } else next.ui.ssrUrl = void 0;
133
+ }
134
+ if (next.api.source === "local" && next.api.localPath) {
135
+ const apiPort = await pickAvailablePort(next.api.port ?? DEFAULT_API_PORT, usedPorts);
136
+ next.api = withLocalRuntimeUrl(next.api, apiPort);
137
+ }
138
+ if (next.plugins) {
139
+ const entries = Object.entries(next.plugins).sort(([a], [b]) => a.localeCompare(b));
140
+ let pluginBasePort = DEFAULT_PLUGIN_PORT_START;
141
+ for (const [pluginId, plugin] of entries) {
142
+ if (plugin.source !== "local" || !plugin.localPath) continue;
143
+ const pluginPort = await pickAvailablePort(plugin.port ?? pluginBasePort, usedPorts);
144
+ next.plugins[pluginId] = withLocalRuntimeUrl(plugin, pluginPort);
145
+ pluginBasePort = pluginPort + 1;
146
+ }
147
+ }
148
+ return next;
149
+ }
150
+
151
+ //#endregion
152
+ export { buildRuntimeConfig, detectLocalPackages, prepareDevelopmentRuntimeConfig };
153
+ //# sourceMappingURL=app.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.mjs","names":[],"sources":["../src/app.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { createConnection } from \"node:net\";\nimport { join } from \"node:path\";\nimport { Effect } from \"effect\";\nimport {\n getProjectRoot,\n isLocalDevelopmentTarget,\n parsePort,\n resolveLocalDevelopmentPath,\n} from \"./config\";\nimport { getNetworkIdForAccount } from \"./network\";\nimport { makeDevProcess, type ProcessCallbacks, type ProcessHandle } from \"./orchestrator\";\nimport type { ProcessRegistry } from \"./process-registry\";\nimport type { BosConfig, RuntimeConfig, RuntimePluginConfig } from \"./types\";\n\nexport interface AppOrchestrator {\n packages: string[];\n env: Record<string, string>;\n description: string;\n bosConfig: BosConfig;\n runtimeConfig: RuntimeConfig;\n port?: number;\n interactive?: boolean;\n}\n\nconst STARTUP_ORDER = [\"ui-ssr\", \"ui\", \"api\", \"plugin\", \"host-build\", \"host\"];\nconst DEFAULT_HOST_PORT = 3000;\nconst DEFAULT_UI_PORT = 3002;\nconst DEFAULT_API_PORT = 3014;\nconst DEFAULT_PLUGIN_PORT_START = 3021;\n\nconst sortByOrder = (packages: string[]): string[] => {\n return [...packages].sort((a, b) => {\n const aIdx = a.startsWith(\"plugin:\")\n ? STARTUP_ORDER.indexOf(\"plugin\")\n : STARTUP_ORDER.indexOf(a);\n const bIdx = b.startsWith(\"plugin:\")\n ? STARTUP_ORDER.indexOf(\"plugin\")\n : STARTUP_ORDER.indexOf(b);\n if (aIdx === -1 && bIdx === -1) return 0;\n if (aIdx === -1) return 1;\n if (bIdx === -1) return -1;\n return aIdx - bIdx;\n });\n};\n\n// Note: log filtering and persistence lives at the CLI layer.\n\nexport interface DevServersHandle {\n handles: ProcessHandle[];\n shutdown: Effect.Effect<void>;\n}\n\nexport const startDevServers = (\n orchestrator: AppOrchestrator,\n callbacks: ProcessCallbacks,\n registry?: ProcessRegistry,\n) => {\n const run = Effect.gen(function* () {\n const orderedPackages = sortByOrder(orchestrator.packages);\n const handles: ProcessHandle[] = [];\n\n const startProcess = (pkg: string) => {\n const portOverride = pkg === \"host\" ? orchestrator.port : undefined;\n return makeDevProcess(\n pkg,\n orchestrator.env,\n callbacks,\n portOverride,\n orchestrator.bosConfig,\n orchestrator.runtimeConfig,\n registry,\n );\n };\n\n const startGroup = (packages: string[]) =>\n Effect.forEach(packages, startProcess, { concurrency: \"unbounded\" });\n\n const awaitReady = (pkg: string, handle: ProcessHandle) =>\n Effect.race(\n handle.waitForReady,\n Effect.sleep(\"30 seconds\").pipe(\n Effect.andThen(\n Effect.sync(() => {\n callbacks.onLog(pkg, \"Timeout waiting for ready, continuing...\", true);\n }),\n ),\n ),\n );\n\n const nonHostPackages = orderedPackages.filter((pkg) => pkg !== \"host\");\n const hostPackages = orderedPackages.filter((pkg) => pkg === \"host\");\n\n const nonHostHandles = yield* startGroup(nonHostPackages);\n handles.push(...nonHostHandles);\n\n yield* Effect.forEach(\n nonHostHandles.map((handle, index) => ({\n handle,\n pkg: nonHostPackages[index] ?? handle.name,\n })),\n ({ handle, pkg }) => awaitReady(pkg, handle),\n { concurrency: \"unbounded\" },\n );\n\n const hostHandles = yield* startGroup(hostPackages);\n handles.push(...hostHandles);\n\n yield* Effect.forEach(\n hostHandles.map((handle, index) => ({ handle, pkg: hostPackages[index] ?? handle.name })),\n ({ handle, pkg }) => awaitReady(pkg, handle),\n { concurrency: \"unbounded\" },\n );\n\n const shutdown = Effect.gen(function* () {\n const reversed = [...handles].reverse();\n for (const handle of reversed) {\n yield* Effect.tryPromise({\n try: () => handle.kill(),\n catch: () => null,\n }).pipe(Effect.ignore);\n }\n });\n\n return { handles, shutdown } satisfies DevServersHandle;\n });\n\n return run;\n};\n\nexport function detectLocalPackages(\n bosConfig?: BosConfig,\n runtimeConfig?: RuntimeConfig,\n): string[] {\n const packages: string[] = [];\n const configDir = getProjectRoot();\n\n const uiLocalPath =\n runtimeConfig?.ui.localPath ??\n resolveLocalDevelopmentPath(bosConfig?.app.ui.development, configDir);\n if (uiLocalPath && existsSync(join(uiLocalPath, \"package.json\"))) {\n packages.push(\"ui\");\n }\n\n const apiLocalPath =\n runtimeConfig?.api.localPath ??\n resolveLocalDevelopmentPath(bosConfig?.app.api.development, configDir);\n if (apiLocalPath && existsSync(join(apiLocalPath, \"package.json\"))) {\n packages.push(\"api\");\n }\n\n const hostLocalPath = resolveLocalDevelopmentPath(bosConfig?.app.host.development, configDir);\n if (hostLocalPath && existsSync(join(hostLocalPath, \"package.json\"))) {\n packages.push(\"host\");\n } else if (existsSync(join(configDir, \"host\", \"package.json\"))) {\n packages.push(\"host\");\n }\n\n for (const [pluginId, pluginConfig] of Object.entries(runtimeConfig?.plugins ?? {})) {\n if (pluginConfig.localPath && existsSync(join(pluginConfig.localPath, \"package.json\"))) {\n packages.push(`plugin:${pluginId}`);\n }\n }\n\n return packages;\n}\n\nexport function buildRuntimeConfig(\n bosConfig: BosConfig,\n options: {\n uiSource?: \"local\" | \"remote\";\n apiSource?: \"local\" | \"remote\";\n hostUrl: string;\n proxy?: string;\n env?: \"development\" | \"production\";\n plugins?: Record<string, RuntimePluginConfig>;\n },\n): RuntimeConfig {\n const configDir = getProjectRoot();\n const uiConfig = bosConfig.app.ui;\n const apiConfig = bosConfig.app.api;\n const uiSource = options.uiSource ?? \"local\";\n const apiSource = options.apiSource ?? \"local\";\n const uiLocalPath = resolveLocalDevelopmentPath(uiConfig.development, configDir);\n const apiLocalPath = resolveLocalDevelopmentPath(apiConfig.development, configDir);\n const uiLocalUrl =\n !uiLocalPath && uiConfig.development && !isLocalDevelopmentTarget(uiConfig.development)\n ? uiConfig.development\n : \"\";\n const apiLocalUrl =\n !apiLocalPath && apiConfig.development && !isLocalDevelopmentTarget(apiConfig.development)\n ? apiConfig.development\n : \"\";\n\n return {\n env: options.env ?? \"development\",\n account: bosConfig.account,\n domain: bosConfig.domain,\n networkId: getNetworkIdForAccount(bosConfig.account),\n hostUrl: options.hostUrl,\n shared: bosConfig.shared,\n ui: uiConfig\n ? {\n name: uiConfig.name,\n url: uiSource === \"remote\" ? (uiConfig.production ?? \"\") : uiLocalUrl,\n entry:\n uiSource === \"remote\"\n ? `${uiConfig.production ?? \"\"}/mf-manifest.json`\n : uiLocalUrl\n ? `${uiLocalUrl}/mf-manifest.json`\n : \"/mf-manifest.json\",\n localPath: uiSource === \"local\" ? (uiLocalPath ?? undefined) : undefined,\n port: uiSource === \"local\" && uiLocalUrl ? parsePort(uiLocalUrl) : undefined,\n ssrUrl: uiSource === \"remote\" ? uiConfig.ssr : undefined,\n ssrIntegrity: uiSource === \"remote\" ? uiConfig.ssrIntegrity : undefined,\n integrity: uiSource === \"remote\" ? uiConfig.productionIntegrity : undefined,\n source: uiSource === \"local\" ? (uiLocalPath ? \"local\" : \"remote\") : \"remote\",\n }\n : {\n name: \"ui\",\n url: \"\",\n entry: \"/mf-manifest.json\",\n source: uiSource,\n },\n api: apiConfig\n ? {\n name: apiConfig.name,\n url: apiSource === \"remote\" ? (apiConfig.production ?? \"\") : apiLocalUrl,\n entry:\n apiSource === \"remote\"\n ? `${apiConfig.production ?? \"\"}/mf-manifest.json`\n : apiLocalUrl\n ? `${apiLocalUrl}/mf-manifest.json`\n : \"/mf-manifest.json\",\n localPath: apiSource === \"local\" ? (apiLocalPath ?? undefined) : undefined,\n port: apiSource === \"local\" && apiLocalUrl ? parsePort(apiLocalUrl) : undefined,\n source: apiSource === \"local\" ? (apiLocalPath ? \"local\" : \"remote\") : \"remote\",\n proxy: options.proxy ?? apiConfig.proxy,\n variables: apiConfig.variables,\n secrets: apiConfig.secrets,\n integrity: apiSource === \"remote\" ? apiConfig.productionIntegrity : undefined,\n }\n : {\n name: \"api\",\n url: \"\",\n entry: \"/mf-manifest.json\",\n source: apiSource,\n },\n plugins: options.plugins,\n };\n}\n\nfunction probeTcpOpen(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\n socket.once(\"connect\", () => {\n clearTimeout(timer);\n socket.destroy();\n resolve(true);\n });\n\n socket.once(\"error\", () => {\n clearTimeout(timer);\n resolve(false);\n });\n });\n}\n\nasync function pickAvailablePort(preferred: number, usedPorts: Set<number>): Promise<number> {\n let port = preferred;\n while (usedPorts.has(port) || (await probeTcpOpen(port))) {\n port += 1;\n }\n usedPorts.add(port);\n return port;\n}\n\nfunction withLocalRuntimeUrl<\n T extends { url: string; entry: string; port?: number; localPath?: string },\n>(entry: T, port: number): T {\n const url = `http://localhost:${port}`;\n return {\n ...entry,\n url,\n entry: `${url}/mf-manifest.json`,\n port,\n };\n}\n\nexport async function prepareDevelopmentRuntimeConfig(\n runtimeConfig: RuntimeConfig,\n options?: { hostPort?: number; ssr?: boolean },\n): Promise<RuntimeConfig> {\n const usedPorts = new Set<number>();\n const hostPort = await pickAvailablePort(\n options?.hostPort ??\n (runtimeConfig.hostUrl ? parsePort(runtimeConfig.hostUrl) : DEFAULT_HOST_PORT),\n usedPorts,\n );\n\n const next: RuntimeConfig = {\n ...runtimeConfig,\n hostUrl: `http://localhost:${hostPort}`,\n ui: { ...runtimeConfig.ui },\n api: { ...runtimeConfig.api },\n plugins: runtimeConfig.plugins ? { ...runtimeConfig.plugins } : undefined,\n };\n\n if (next.ui.source === \"local\" && next.ui.localPath) {\n const uiPort = await pickAvailablePort(next.ui.port ?? DEFAULT_UI_PORT, usedPorts);\n next.ui = withLocalRuntimeUrl(next.ui, uiPort);\n if (options?.ssr) {\n const ssrPort = await pickAvailablePort(uiPort + 1, usedPorts);\n next.ui.ssrUrl = `http://localhost:${ssrPort}`;\n } else {\n next.ui.ssrUrl = undefined;\n }\n }\n\n if (next.api.source === \"local\" && next.api.localPath) {\n const apiPort = await pickAvailablePort(next.api.port ?? DEFAULT_API_PORT, usedPorts);\n next.api = withLocalRuntimeUrl(next.api, apiPort);\n }\n\n if (next.plugins) {\n const entries = Object.entries(next.plugins).sort(([a], [b]) => a.localeCompare(b));\n let pluginBasePort = DEFAULT_PLUGIN_PORT_START;\n\n for (const [pluginId, plugin] of entries) {\n if (plugin.source !== \"local\" || !plugin.localPath) {\n continue;\n }\n\n const pluginPort = await pickAvailablePort(plugin.port ?? pluginBasePort, usedPorts);\n next.plugins[pluginId] = withLocalRuntimeUrl(plugin, pluginPort);\n pluginBasePort = pluginPort + 1;\n }\n }\n\n return next;\n}\n"],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ const require_contract = require('../contract.cjs');
2
+ const require_contract_meta = require('../contract.meta.cjs');
3
+
4
+ //#region src/cli/catalog.ts
5
+ function splitCamelCase(value) {
6
+ return value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").split(/\s+/).map((part) => part.trim()).filter(Boolean).map((part) => part.toLowerCase());
7
+ }
8
+ const commandCatalog = Object.entries(require_contract.bosContract).map(([key, procedure]) => {
9
+ const meta = require_contract_meta.cliCommandMeta[key] ?? { summary: splitCamelCase(String(key)).join(" ") };
10
+ return {
11
+ key,
12
+ commandPath: meta.commandPath ?? splitCamelCase(String(key)),
13
+ summary: meta.summary,
14
+ meta,
15
+ procedure
16
+ };
17
+ });
18
+ function findCommandDescriptor(args) {
19
+ const sorted = [...commandCatalog].sort((a, b) => b.commandPath.length - a.commandPath.length);
20
+ for (const descriptor of sorted) if (args.slice(0, descriptor.commandPath.length).map((part) => part.toLowerCase()).join(" ") === descriptor.commandPath.join(" ")) return {
21
+ descriptor,
22
+ consumed: descriptor.commandPath.length
23
+ };
24
+ return null;
25
+ }
26
+
27
+ //#endregion
28
+ exports.commandCatalog = commandCatalog;
29
+ exports.findCommandDescriptor = findCommandDescriptor;
30
+ //# sourceMappingURL=catalog.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.cjs","names":["bosContract","cliCommandMeta"],"sources":["../../src/cli/catalog.ts"],"sourcesContent":["import { bosContract } from \"../contract\";\nimport { type CliCommandMeta, cliCommandMeta } from \"../contract.meta\";\n\nexport type CommandDescriptor = {\n key: keyof typeof bosContract;\n commandPath: string[];\n summary: string;\n meta: CliCommandMeta;\n procedure: (typeof bosContract)[keyof typeof bosContract];\n};\n\nfunction splitCamelCase(value: string): string[] {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .split(/\\s+/)\n .map((part) => part.trim())\n .filter(Boolean)\n .map((part) => part.toLowerCase());\n}\n\nexport const commandCatalog: CommandDescriptor[] = (\n Object.entries(bosContract) as Array<\n [keyof typeof bosContract, (typeof bosContract)[keyof typeof bosContract]]\n >\n).map(([key, procedure]) => {\n const meta = cliCommandMeta[key as keyof typeof cliCommandMeta] ?? {\n summary: splitCamelCase(String(key)).join(\" \"),\n };\n return {\n key,\n commandPath: meta.commandPath ?? splitCamelCase(String(key)),\n summary: meta.summary,\n meta,\n procedure,\n };\n});\n\nexport function findCommandDescriptor(\n args: string[],\n): { descriptor: CommandDescriptor; consumed: number } | null {\n const sorted = [...commandCatalog].sort((a, b) => b.commandPath.length - a.commandPath.length);\n for (const descriptor of sorted) {\n const parts = args.slice(0, descriptor.commandPath.length).map((part) => part.toLowerCase());\n if (parts.join(\" \") === descriptor.commandPath.join(\" \")) {\n return { descriptor, consumed: descriptor.commandPath.length };\n }\n }\n return null;\n}\n"],"mappings":";;;;AAWA,SAAS,eAAe,OAAyB;AAC/C,QAAO,MACJ,QAAQ,sBAAsB,QAAQ,CACtC,MAAM,MAAM,CACZ,KAAK,SAAS,KAAK,MAAM,CAAC,CAC1B,OAAO,QAAQ,CACf,KAAK,SAAS,KAAK,aAAa,CAAC;;AAGtC,MAAa,iBACX,OAAO,QAAQA,6BAAY,CAG3B,KAAK,CAAC,KAAK,eAAe;CAC1B,MAAM,OAAOC,qCAAe,QAAuC,EACjE,SAAS,eAAe,OAAO,IAAI,CAAC,CAAC,KAAK,IAAI,EAC/C;AACD,QAAO;EACL;EACA,aAAa,KAAK,eAAe,eAAe,OAAO,IAAI,CAAC;EAC5D,SAAS,KAAK;EACd;EACA;EACD;EACD;AAEF,SAAgB,sBACd,MAC4D;CAC5D,MAAM,SAAS,CAAC,GAAG,eAAe,CAAC,MAAM,GAAG,MAAM,EAAE,YAAY,SAAS,EAAE,YAAY,OAAO;AAC9F,MAAK,MAAM,cAAc,OAEvB,KADc,KAAK,MAAM,GAAG,WAAW,YAAY,OAAO,CAAC,KAAK,SAAS,KAAK,aAAa,CAAC,CAClF,KAAK,IAAI,KAAK,WAAW,YAAY,KAAK,IAAI,CACtD,QAAO;EAAE;EAAY,UAAU,WAAW,YAAY;EAAQ;AAGlE,QAAO"}