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.
- package/README.md +64 -0
- package/cli.js +10 -0
- package/dist/_virtual/_rolldown/runtime.cjs +29 -0
- package/dist/api-contract.cjs +172 -0
- package/dist/api-contract.cjs.map +1 -0
- package/dist/api-contract.mjs +171 -0
- package/dist/api-contract.mjs.map +1 -0
- package/dist/api.cjs +124 -0
- package/dist/api.cjs.map +1 -0
- package/dist/api.d.cts +36 -0
- package/dist/api.d.cts.map +1 -0
- package/dist/api.d.mts +36 -0
- package/dist/api.d.mts.map +1 -0
- package/dist/api.mjs +119 -0
- package/dist/api.mjs.map +1 -0
- package/dist/app.cjs +156 -0
- package/dist/app.cjs.map +1 -0
- package/dist/app.mjs +153 -0
- package/dist/app.mjs.map +1 -0
- package/dist/cli/catalog.cjs +30 -0
- package/dist/cli/catalog.cjs.map +1 -0
- package/dist/cli/catalog.mjs +29 -0
- package/dist/cli/catalog.mjs.map +1 -0
- package/dist/cli/help.cjs +16 -0
- package/dist/cli/help.cjs.map +1 -0
- package/dist/cli/help.mjs +16 -0
- package/dist/cli/help.mjs.map +1 -0
- package/dist/cli/init.cjs +287 -0
- package/dist/cli/init.cjs.map +1 -0
- package/dist/cli/init.d.cts +36 -0
- package/dist/cli/init.d.cts.map +1 -0
- package/dist/cli/init.d.mts +36 -0
- package/dist/cli/init.d.mts.map +1 -0
- package/dist/cli/init.mjs +279 -0
- package/dist/cli/init.mjs.map +1 -0
- package/dist/cli/parse.cjs +96 -0
- package/dist/cli/parse.cjs.map +1 -0
- package/dist/cli/parse.mjs +95 -0
- package/dist/cli/parse.mjs.map +1 -0
- package/dist/cli/prompts.cjs +42 -0
- package/dist/cli/prompts.cjs.map +1 -0
- package/dist/cli/prompts.mjs +41 -0
- package/dist/cli/prompts.mjs.map +1 -0
- package/dist/cli.cjs +167 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +166 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/components/dev-view.cjs +307 -0
- package/dist/components/dev-view.cjs.map +1 -0
- package/dist/components/dev-view.mjs +306 -0
- package/dist/components/dev-view.mjs.map +1 -0
- package/dist/components/streaming-view.cjs +146 -0
- package/dist/components/streaming-view.cjs.map +1 -0
- package/dist/components/streaming-view.mjs +144 -0
- package/dist/components/streaming-view.mjs.map +1 -0
- package/dist/config.cjs +280 -0
- package/dist/config.cjs.map +1 -0
- package/dist/config.d.cts +35 -0
- package/dist/config.d.cts.map +1 -0
- package/dist/config.d.mts +35 -0
- package/dist/config.d.mts.map +1 -0
- package/dist/config.mjs +266 -0
- package/dist/config.mjs.map +1 -0
- package/dist/contract.cjs +209 -0
- package/dist/contract.cjs.map +1 -0
- package/dist/contract.d.cts +490 -0
- package/dist/contract.d.cts.map +1 -0
- package/dist/contract.d.mts +490 -0
- package/dist/contract.d.mts.map +1 -0
- package/dist/contract.meta.cjs +104 -0
- package/dist/contract.meta.cjs.map +1 -0
- package/dist/contract.meta.d.cts +141 -0
- package/dist/contract.meta.d.cts.map +1 -0
- package/dist/contract.meta.d.mts +141 -0
- package/dist/contract.meta.d.mts.map +1 -0
- package/dist/contract.meta.mjs +102 -0
- package/dist/contract.meta.mjs.map +1 -0
- package/dist/contract.mjs +186 -0
- package/dist/contract.mjs.map +1 -0
- package/dist/dev-logs.cjs +53 -0
- package/dist/dev-logs.cjs.map +1 -0
- package/dist/dev-logs.mjs +51 -0
- package/dist/dev-logs.mjs.map +1 -0
- package/dist/dev-session.cjs +195 -0
- package/dist/dev-session.cjs.map +1 -0
- package/dist/dev-session.mjs +194 -0
- package/dist/dev-session.mjs.map +1 -0
- package/dist/fastkv.cjs +89 -0
- package/dist/fastkv.cjs.map +1 -0
- package/dist/fastkv.d.cts +11 -0
- package/dist/fastkv.d.cts.map +1 -0
- package/dist/fastkv.d.mts +11 -0
- package/dist/fastkv.d.mts.map +1 -0
- package/dist/fastkv.mjs +82 -0
- package/dist/fastkv.mjs.map +1 -0
- package/dist/federation.server.cjs +27 -0
- package/dist/federation.server.cjs.map +1 -0
- package/dist/federation.server.mjs +27 -0
- package/dist/federation.server.mjs.map +1 -0
- package/dist/host.cjs +367 -0
- package/dist/host.cjs.map +1 -0
- package/dist/host.d.cts +22 -0
- package/dist/host.d.cts.map +1 -0
- package/dist/host.d.mts +22 -0
- package/dist/host.d.mts.map +1 -0
- package/dist/host.mjs +364 -0
- package/dist/host.mjs.map +1 -0
- package/dist/index.cjs +122 -0
- package/dist/index.d.cts +7 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.mjs +9 -0
- package/dist/integrity.cjs +39 -0
- package/dist/integrity.cjs.map +1 -0
- package/dist/integrity.d.cts +7 -0
- package/dist/integrity.d.cts.map +1 -0
- package/dist/integrity.d.mts +7 -0
- package/dist/integrity.d.mts.map +1 -0
- package/dist/integrity.mjs +35 -0
- package/dist/integrity.mjs.map +1 -0
- package/dist/internal/manifest-normalizer.cjs +140 -0
- package/dist/internal/manifest-normalizer.cjs.map +1 -0
- package/dist/internal/manifest-normalizer.mjs +138 -0
- package/dist/internal/manifest-normalizer.mjs.map +1 -0
- package/dist/mf.cjs +77 -0
- package/dist/mf.cjs.map +1 -0
- package/dist/mf.d.cts +19 -0
- package/dist/mf.d.cts.map +1 -0
- package/dist/mf.d.mts +19 -0
- package/dist/mf.d.mts.map +1 -0
- package/dist/mf.mjs +71 -0
- package/dist/mf.mjs.map +1 -0
- package/dist/near-cli.cjs +196 -0
- package/dist/near-cli.cjs.map +1 -0
- package/dist/near-cli.mjs +193 -0
- package/dist/near-cli.mjs.map +1 -0
- package/dist/network.cjs +9 -0
- package/dist/network.cjs.map +1 -0
- package/dist/network.mjs +8 -0
- package/dist/network.mjs.map +1 -0
- package/dist/orchestrator.cjs +441 -0
- package/dist/orchestrator.cjs.map +1 -0
- package/dist/orchestrator.d.cts +40 -0
- package/dist/orchestrator.d.cts.map +1 -0
- package/dist/orchestrator.d.mts +40 -0
- package/dist/orchestrator.d.mts.map +1 -0
- package/dist/orchestrator.mjs +436 -0
- package/dist/orchestrator.mjs.map +1 -0
- package/dist/plugin.cjs +830 -0
- package/dist/plugin.cjs.map +1 -0
- package/dist/plugin.d.cts +347 -0
- package/dist/plugin.d.cts.map +1 -0
- package/dist/plugin.d.mts +348 -0
- package/dist/plugin.d.mts.map +1 -0
- package/dist/plugin.mjs +827 -0
- package/dist/plugin.mjs.map +1 -0
- package/dist/process-registry.cjs +120 -0
- package/dist/process-registry.cjs.map +1 -0
- package/dist/process-registry.d.cts +25 -0
- package/dist/process-registry.d.cts.map +1 -0
- package/dist/process-registry.d.mts +25 -0
- package/dist/process-registry.d.mts.map +1 -0
- package/dist/process-registry.mjs +119 -0
- package/dist/process-registry.mjs.map +1 -0
- package/dist/sdk.cjs +61 -0
- package/dist/sdk.d.cts +5 -0
- package/dist/sdk.d.mts +5 -0
- package/dist/sdk.mjs +6 -0
- package/dist/shared.cjs +143 -0
- package/dist/shared.cjs.map +1 -0
- package/dist/shared.d.cts +33 -0
- package/dist/shared.d.cts.map +1 -0
- package/dist/shared.d.mts +33 -0
- package/dist/shared.d.mts.map +1 -0
- package/dist/shared.mjs +140 -0
- package/dist/shared.mjs.map +1 -0
- package/dist/types.cjs +160 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +269 -0
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.mts +269 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +144 -0
- package/dist/types.mjs.map +1 -0
- package/dist/ui/head.cjs +67 -0
- package/dist/ui/head.cjs.map +1 -0
- package/dist/ui/head.d.cts +19 -0
- package/dist/ui/head.d.cts.map +1 -0
- package/dist/ui/head.d.mts +19 -0
- package/dist/ui/head.d.mts.map +1 -0
- package/dist/ui/head.mjs +61 -0
- package/dist/ui/head.mjs.map +1 -0
- package/dist/ui/index.cjs +32 -0
- package/dist/ui/index.d.cts +7 -0
- package/dist/ui/index.d.mts +7 -0
- package/dist/ui/index.mjs +6 -0
- package/dist/ui/metadata.cjs +106 -0
- package/dist/ui/metadata.cjs.map +1 -0
- package/dist/ui/metadata.d.cts +35 -0
- package/dist/ui/metadata.d.cts.map +1 -0
- package/dist/ui/metadata.d.mts +35 -0
- package/dist/ui/metadata.d.mts.map +1 -0
- package/dist/ui/metadata.mjs +100 -0
- package/dist/ui/metadata.mjs.map +1 -0
- package/dist/ui/router.cjs +56 -0
- package/dist/ui/router.cjs.map +1 -0
- package/dist/ui/router.d.cts +11 -0
- package/dist/ui/router.d.cts.map +1 -0
- package/dist/ui/router.d.mts +11 -0
- package/dist/ui/router.d.mts.map +1 -0
- package/dist/ui/router.mjs +51 -0
- package/dist/ui/router.mjs.map +1 -0
- package/dist/ui/runtime.cjs +65 -0
- package/dist/ui/runtime.cjs.map +1 -0
- package/dist/ui/runtime.d.cts +29 -0
- package/dist/ui/runtime.d.cts.map +1 -0
- package/dist/ui/runtime.d.mts +29 -0
- package/dist/ui/runtime.d.mts.map +1 -0
- package/dist/ui/runtime.mjs +53 -0
- package/dist/ui/runtime.mjs.map +1 -0
- package/dist/ui/types.cjs +0 -0
- package/dist/ui/types.d.cts +52 -0
- package/dist/ui/types.d.cts.map +1 -0
- package/dist/ui/types.d.mts +52 -0
- package/dist/ui/types.d.mts.map +1 -0
- package/dist/ui/types.mjs +1 -0
- package/dist/utils/banner.cjs +24 -0
- package/dist/utils/banner.cjs.map +1 -0
- package/dist/utils/banner.mjs +23 -0
- package/dist/utils/banner.mjs.map +1 -0
- package/dist/utils/linkify.cjs +15 -0
- package/dist/utils/linkify.cjs.map +1 -0
- package/dist/utils/linkify.mjs +14 -0
- package/dist/utils/linkify.mjs.map +1 -0
- package/dist/utils/run.cjs +40 -0
- package/dist/utils/run.cjs.map +1 -0
- package/dist/utils/run.mjs +39 -0
- package/dist/utils/run.mjs.map +1 -0
- package/dist/utils/theme.cjs +44 -0
- package/dist/utils/theme.cjs.map +1 -0
- package/dist/utils/theme.mjs +37 -0
- package/dist/utils/theme.mjs.map +1 -0
- package/package.json +269 -80
- package/src/api-contract.ts +309 -0
- package/src/api.ts +181 -0
- package/src/app.ts +346 -0
- package/src/cli/catalog.ts +49 -0
- package/src/cli/help.ts +13 -0
- package/src/cli/init.ts +386 -0
- package/src/cli/parse.ts +130 -0
- package/src/cli/prompts.ts +64 -0
- package/src/cli.ts +203 -1507
- package/src/components/dev-view.tsx +307 -255
- package/src/components/streaming-view.ts +164 -128
- package/src/config.ts +462 -532
- package/src/contract.meta.ts +96 -0
- package/src/contract.ts +164 -561
- package/src/dev-logs.ts +85 -0
- package/src/dev-session.ts +318 -0
- package/src/fastkv.ts +153 -0
- package/src/federation.server.ts +43 -0
- package/src/host.ts +526 -0
- package/src/index.ts +6 -3
- package/src/integrity.ts +54 -0
- package/src/internal/manifest-normalizer.ts +251 -0
- package/src/mf.ts +105 -0
- package/src/near-cli.ts +284 -0
- package/src/network.ts +3 -0
- package/src/orchestrator.ts +648 -0
- package/src/plugin.ts +1130 -2311
- package/src/process-registry.ts +154 -0
- package/src/scripts/sync-api-contract.ts +24 -0
- package/src/sdk.ts +14 -0
- package/src/shared.ts +206 -0
- package/src/types.ts +152 -206
- package/src/ui/head.ts +34 -27
- package/src/ui/index.ts +3 -3
- package/src/ui/metadata.ts +95 -0
- package/src/ui/router.ts +22 -6
- package/src/ui/runtime.ts +55 -6
- package/src/ui/types.ts +24 -11
- package/src/utils/banner.ts +10 -6
- package/src/utils/run.ts +26 -27
- package/src/utils/theme.ts +3 -66
- package/src/components/monitor-view.tsx +0 -475
- package/src/components/status-view.tsx +0 -173
- package/src/lib/env.ts +0 -109
- package/src/lib/near-cli.ts +0 -289
- package/src/lib/nova.ts +0 -266
- package/src/lib/orchestrator.ts +0 -276
- package/src/lib/process-registry.ts +0 -166
- package/src/lib/process.ts +0 -550
- package/src/lib/resource-monitor/assertions.ts +0 -234
- package/src/lib/resource-monitor/command.ts +0 -283
- package/src/lib/resource-monitor/diff.ts +0 -157
- package/src/lib/resource-monitor/errors.ts +0 -127
- package/src/lib/resource-monitor/index.ts +0 -305
- package/src/lib/resource-monitor/platform/darwin.ts +0 -306
- package/src/lib/resource-monitor/platform/index.ts +0 -35
- package/src/lib/resource-monitor/platform/linux.ts +0 -332
- package/src/lib/resource-monitor/platform/windows.ts +0 -298
- package/src/lib/resource-monitor/snapshot.ts +0 -217
- package/src/lib/resource-monitor/types.ts +0 -74
- package/src/lib/session-recorder/errors.ts +0 -102
- package/src/lib/session-recorder/flows/login.ts +0 -210
- package/src/lib/session-recorder/index.ts +0 -361
- package/src/lib/session-recorder/playwright.ts +0 -257
- package/src/lib/session-recorder/report.ts +0 -353
- package/src/lib/session-recorder/server.ts +0 -268
- package/src/lib/session-recorder/types.ts +0 -115
- package/src/lib/sync.ts +0 -1
- 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
|
package/dist/api.mjs.map
ADDED
|
@@ -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
|
package/dist/app.cjs.map
ADDED
|
@@ -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
|
package/dist/app.mjs.map
ADDED
|
@@ -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"}
|