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/src/config.ts
CHANGED
|
@@ -1,573 +1,503 @@
|
|
|
1
|
-
import { existsSync,
|
|
2
|
-
import { access, readFile } from "node:fs/promises";
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
2
|
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import type {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
// Constants
|
|
34
|
-
export const DEFAULT_DEV_CONFIG: AppConfig = {
|
|
35
|
-
host: "local",
|
|
36
|
-
ui: "local",
|
|
37
|
-
api: "local",
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
// Global state (for caching)
|
|
41
|
-
const configCache = new Map<string, { config: BosConfig; timestamp: number }>();
|
|
3
|
+
import { fetchBosConfigFromFastKv } from "./fastkv";
|
|
4
|
+
import { getNetworkIdForAccount } from "./network";
|
|
5
|
+
import type { BosConfig, RuntimeConfig, RuntimePluginConfig } from "./types";
|
|
6
|
+
import { BosConfigSchema } from "./types";
|
|
7
|
+
|
|
8
|
+
interface BosConfigInput extends Record<string, unknown> {
|
|
9
|
+
extends?: string;
|
|
10
|
+
development?: string;
|
|
11
|
+
production?: string;
|
|
12
|
+
productionIntegrity?: string;
|
|
13
|
+
proxy?: string;
|
|
14
|
+
variables?: Record<string, string>;
|
|
15
|
+
secrets?: string[];
|
|
16
|
+
app?: Record<string, Record<string, unknown>>;
|
|
17
|
+
shared?: Record<string, Record<string, Record<string, unknown>>>;
|
|
18
|
+
plugins?: Record<string, BosConfigInput>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const LOCAL_PREFIX = "local:";
|
|
22
|
+
const DEFAULT_HOST_PORT = 3000;
|
|
23
|
+
|
|
24
|
+
interface RuntimeTarget {
|
|
25
|
+
source: "local" | "remote";
|
|
26
|
+
url: string;
|
|
27
|
+
localPath?: string;
|
|
28
|
+
port?: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
42
31
|
let cachedConfig: BosConfig | null = null;
|
|
43
32
|
let projectRoot: string | null = null;
|
|
44
|
-
let configLoaded = false;
|
|
45
|
-
|
|
46
|
-
// ============================================================================
|
|
47
|
-
// PUBLIC API (6 methods)
|
|
48
|
-
// ============================================================================
|
|
49
33
|
|
|
50
|
-
/**
|
|
51
|
-
* Clear the config cache. Used by --force flag.
|
|
52
|
-
*/
|
|
53
34
|
export function clearConfigCache(): void {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
projectRoot = null;
|
|
57
|
-
configLoaded = false;
|
|
35
|
+
cachedConfig = null;
|
|
36
|
+
projectRoot = null;
|
|
58
37
|
}
|
|
59
38
|
|
|
60
|
-
/**
|
|
61
|
-
* Find the path to bos.config.json by walking up the directory tree.
|
|
62
|
-
*/
|
|
63
39
|
export function findConfigPath(cwd?: string): string | null {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
40
|
+
let dir = cwd ?? process.cwd();
|
|
41
|
+
while (dir !== "/") {
|
|
42
|
+
const configPath = join(dir, "bos.config.json");
|
|
43
|
+
if (existsSync(configPath)) {
|
|
44
|
+
return configPath;
|
|
45
|
+
}
|
|
46
|
+
dir = dirname(dir);
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
73
49
|
}
|
|
74
50
|
|
|
75
|
-
/**
|
|
76
|
-
* Get the cached config. Returns null if not loaded yet.
|
|
77
|
-
*/
|
|
78
51
|
export function getConfig(): BosConfig | null {
|
|
79
|
-
|
|
52
|
+
return cachedConfig;
|
|
80
53
|
}
|
|
81
54
|
|
|
82
|
-
/**
|
|
83
|
-
* Get the project root directory (where bos.config.json is located).
|
|
84
|
-
* Throws if config hasn't been loaded.
|
|
85
|
-
*/
|
|
86
55
|
export function getProjectRoot(): string {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
56
|
+
if (!projectRoot) {
|
|
57
|
+
throw new Error("Config not loaded. Call loadConfig() first.");
|
|
58
|
+
}
|
|
59
|
+
return projectRoot;
|
|
91
60
|
}
|
|
92
61
|
|
|
93
|
-
/**
|
|
94
|
-
* Result of loading config - includes everything needed by callers.
|
|
95
|
-
*/
|
|
96
62
|
export interface ConfigResult {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
extended?: string[];
|
|
105
|
-
remote?: boolean;
|
|
106
|
-
};
|
|
107
|
-
/** Package information */
|
|
108
|
-
packages: {
|
|
109
|
-
all: string[];
|
|
110
|
-
resolved: PackageResolution[];
|
|
111
|
-
};
|
|
63
|
+
config: BosConfig;
|
|
64
|
+
runtime: RuntimeConfig;
|
|
65
|
+
source: {
|
|
66
|
+
path: string;
|
|
67
|
+
extended?: string[];
|
|
68
|
+
remote?: boolean;
|
|
69
|
+
};
|
|
112
70
|
}
|
|
113
71
|
|
|
114
|
-
/**
|
|
115
|
-
* Resolution info for a single package.
|
|
116
|
-
*/
|
|
117
|
-
export interface PackageResolution {
|
|
118
|
-
name: string;
|
|
119
|
-
mode: SourceMode;
|
|
120
|
-
exists: boolean;
|
|
121
|
-
port: number;
|
|
122
|
-
url: string;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Primary config loader - handles everything.
|
|
127
|
-
* - Local config loading
|
|
128
|
-
* - Config inheritance (extends)
|
|
129
|
-
* - BOS URL fetching
|
|
130
|
-
* - Caching
|
|
131
|
-
* - Runtime config generation
|
|
132
|
-
*/
|
|
133
72
|
export async function loadConfig(options?: {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
env?: "development" | "production";
|
|
73
|
+
cwd?: string;
|
|
74
|
+
path?: string;
|
|
75
|
+
env?: "development" | "production";
|
|
138
76
|
}): Promise<ConfigResult | null> {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
return {
|
|
177
|
-
config: cached.config,
|
|
178
|
-
runtime,
|
|
179
|
-
source: { path: configPath },
|
|
180
|
-
packages: {
|
|
181
|
-
all: Object.keys(cached.config.app),
|
|
182
|
-
resolved: [],
|
|
183
|
-
},
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
try {
|
|
188
|
-
// Resolve config with extends
|
|
189
|
-
const extendedChain: string[] = [];
|
|
190
|
-
const rawConfig = await resolveConfigWithExtends(
|
|
191
|
-
configPath,
|
|
192
|
-
baseDir,
|
|
193
|
-
new Set(),
|
|
194
|
-
extendedChain,
|
|
195
|
-
);
|
|
196
|
-
|
|
197
|
-
// Validate with strict schema
|
|
198
|
-
const validated = BosConfigSchema.parse(rawConfig);
|
|
199
|
-
|
|
200
|
-
// Cache result
|
|
201
|
-
configCache.set(configPath, { config: validated, timestamp: Date.now() });
|
|
202
|
-
projectRoot = baseDir;
|
|
203
|
-
cachedConfig = validated;
|
|
204
|
-
configLoaded = true;
|
|
205
|
-
|
|
206
|
-
// Build runtime config
|
|
207
|
-
const runtime = buildRuntimeConfig(
|
|
208
|
-
validated,
|
|
209
|
-
options?.env ?? "development",
|
|
210
|
-
);
|
|
211
|
-
|
|
212
|
-
return {
|
|
213
|
-
config: validated,
|
|
214
|
-
runtime,
|
|
215
|
-
source: {
|
|
216
|
-
path: configPath,
|
|
217
|
-
extended: extendedChain.length > 0 ? extendedChain : undefined,
|
|
218
|
-
remote: extendedChain.some((e) => e.startsWith("bos://")),
|
|
219
|
-
},
|
|
220
|
-
packages: {
|
|
221
|
-
all: Object.keys(validated.app),
|
|
222
|
-
resolved: [],
|
|
223
|
-
},
|
|
224
|
-
};
|
|
225
|
-
} catch (error) {
|
|
226
|
-
if (error instanceof ConfigCircularExtendsError) {
|
|
227
|
-
throw error;
|
|
228
|
-
}
|
|
229
|
-
if (error instanceof ConfigFetchError) {
|
|
230
|
-
throw error;
|
|
231
|
-
}
|
|
232
|
-
if (error instanceof ConfigResolutionError) {
|
|
233
|
-
throw error;
|
|
234
|
-
}
|
|
235
|
-
throw new ConfigResolutionError(
|
|
236
|
-
`Failed to load config from ${configPath}: ${error}`,
|
|
237
|
-
);
|
|
238
|
-
}
|
|
77
|
+
const configPath = options?.path ?? findConfigPath(options?.cwd);
|
|
78
|
+
if (!configPath) {
|
|
79
|
+
projectRoot = options?.cwd ?? process.cwd();
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const baseDir = dirname(configPath);
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
const extendedChain: string[] = [];
|
|
87
|
+
const parsed = await resolveConfigWithExtends(configPath, baseDir, new Set(), extendedChain);
|
|
88
|
+
const config = BosConfigSchema.parse(parsed);
|
|
89
|
+
|
|
90
|
+
cachedConfig = config;
|
|
91
|
+
projectRoot = baseDir;
|
|
92
|
+
|
|
93
|
+
const pluginRuntime = await resolveRuntimePlugins(
|
|
94
|
+
config.plugins ?? {},
|
|
95
|
+
baseDir,
|
|
96
|
+
options?.env ?? "development",
|
|
97
|
+
);
|
|
98
|
+
const runtime = buildRuntimeConfig(config, baseDir, options?.env ?? "development", {
|
|
99
|
+
plugins: pluginRuntime,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
config,
|
|
104
|
+
runtime,
|
|
105
|
+
source: {
|
|
106
|
+
path: configPath,
|
|
107
|
+
extended: extendedChain.length > 0 ? extendedChain : undefined,
|
|
108
|
+
remote: extendedChain.some((entry) => entry.startsWith("bos://")),
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
} catch (error) {
|
|
112
|
+
throw new Error(`Failed to load config from ${configPath}: ${error}`);
|
|
113
|
+
}
|
|
239
114
|
}
|
|
240
115
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
)
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
const dir = getProjectRoot();
|
|
253
|
-
const resolved: Record<string, PackageResolution> = {};
|
|
254
|
-
const autoRemote: string[] = [];
|
|
255
|
-
|
|
256
|
-
// Get config for port calculations
|
|
257
|
-
const config = getConfig();
|
|
258
|
-
|
|
259
|
-
for (const pkg of packages) {
|
|
260
|
-
const exists = await fileExists(`${dir}/${pkg}/package.json`);
|
|
261
|
-
const requestedMode = requestedModes[pkg] ?? "local";
|
|
262
|
-
|
|
263
|
-
// Auto-switch to remote if package doesn't exist locally
|
|
264
|
-
const mode =
|
|
265
|
-
!exists && requestedMode === "local" ? "remote" : requestedMode;
|
|
266
|
-
if (!exists && requestedMode === "local") {
|
|
267
|
-
autoRemote.push(pkg);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// Calculate port and URL
|
|
271
|
-
let port = 0;
|
|
272
|
-
let url = "";
|
|
273
|
-
|
|
274
|
-
if (config && pkg in config.app) {
|
|
275
|
-
const pkgConfig = config.app[pkg];
|
|
276
|
-
if (pkg === "host") {
|
|
277
|
-
port = parsePort(pkgConfig.development);
|
|
278
|
-
url = mode === "remote" ? pkgConfig.production : pkgConfig.development;
|
|
279
|
-
} else {
|
|
280
|
-
// For ui/api and other packages, access via index signature
|
|
281
|
-
const devUrl = (pkgConfig as { development?: string }).development;
|
|
282
|
-
const prodUrl = (pkgConfig as { production?: string }).production;
|
|
283
|
-
if (devUrl) {
|
|
284
|
-
port = parsePort(devUrl);
|
|
285
|
-
url = mode === "remote" ? (prodUrl ?? devUrl) : devUrl;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
resolved[pkg] = { name: pkg, mode, exists, port, url };
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
return { resolved, autoRemote };
|
|
116
|
+
export async function loadBosConfig(options?: {
|
|
117
|
+
cwd?: string;
|
|
118
|
+
path?: string;
|
|
119
|
+
env?: "development" | "production";
|
|
120
|
+
}): Promise<RuntimeConfig> {
|
|
121
|
+
const result = await loadConfig(options);
|
|
122
|
+
if (!result) {
|
|
123
|
+
throw new Error("No bos.config.json found");
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return result.runtime;
|
|
294
127
|
}
|
|
295
128
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
129
|
+
export async function buildRuntimePluginsForConfig(
|
|
130
|
+
config: BosConfig,
|
|
131
|
+
baseDir: string,
|
|
132
|
+
env: "development" | "production",
|
|
133
|
+
): Promise<Record<string, RuntimePluginConfig> | undefined> {
|
|
134
|
+
const plugins = await resolveRuntimePlugins(config.plugins ?? {}, baseDir, env);
|
|
135
|
+
return Object.keys(plugins).length > 0 ? plugins : undefined;
|
|
136
|
+
}
|
|
299
137
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
138
|
+
function buildRuntimeConfig(
|
|
139
|
+
config: BosConfig,
|
|
140
|
+
baseDir: string,
|
|
141
|
+
env: "development" | "production",
|
|
142
|
+
options?: { plugins?: Record<string, RuntimePluginConfig> },
|
|
143
|
+
): RuntimeConfig {
|
|
144
|
+
const uiConfig = config.app.ui;
|
|
145
|
+
const apiConfig = config.app.api;
|
|
146
|
+
const uiRuntime =
|
|
147
|
+
env === "development"
|
|
148
|
+
? resolveRuntimeTarget(uiConfig.development, baseDir)
|
|
149
|
+
: resolveRuntimeTarget(uiConfig.production, baseDir, "remote");
|
|
150
|
+
const apiRuntime =
|
|
151
|
+
env === "development"
|
|
152
|
+
? resolveRuntimeTarget(apiConfig.development, baseDir)
|
|
153
|
+
: resolveRuntimeTarget(apiConfig.production, baseDir, "remote");
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
env,
|
|
157
|
+
account: config.account,
|
|
158
|
+
domain: config.domain,
|
|
159
|
+
networkId: getNetworkIdForAccount(config.account),
|
|
160
|
+
repository: config.repository,
|
|
161
|
+
hostUrl:
|
|
162
|
+
env === "development"
|
|
163
|
+
? resolveDevelopmentHostUrl(config.app.host.development)
|
|
164
|
+
: config.app.host.production,
|
|
165
|
+
shared: config.shared,
|
|
166
|
+
ui: {
|
|
167
|
+
name: uiConfig.name,
|
|
168
|
+
url: uiRuntime.url,
|
|
169
|
+
entry: uiRuntime.url ? `${uiRuntime.url}/mf-manifest.json` : "/mf-manifest.json",
|
|
170
|
+
localPath: uiRuntime.localPath,
|
|
171
|
+
port: uiRuntime.port,
|
|
172
|
+
ssrUrl: uiConfig.ssr,
|
|
173
|
+
ssrIntegrity: env === "production" ? uiConfig.ssrIntegrity : undefined,
|
|
174
|
+
integrity: env === "production" ? uiConfig.productionIntegrity : undefined,
|
|
175
|
+
source: uiRuntime.source,
|
|
176
|
+
},
|
|
177
|
+
api: {
|
|
178
|
+
name: apiConfig.name,
|
|
179
|
+
url: apiRuntime.url,
|
|
180
|
+
entry: apiRuntime.url ? `${apiRuntime.url}/mf-manifest.json` : "/mf-manifest.json",
|
|
181
|
+
localPath: apiRuntime.localPath,
|
|
182
|
+
port: apiRuntime.port,
|
|
183
|
+
source: apiRuntime.source,
|
|
184
|
+
proxy: apiConfig.proxy,
|
|
185
|
+
variables: apiConfig.variables,
|
|
186
|
+
secrets: apiConfig.secrets,
|
|
187
|
+
integrity: env === "production" ? apiConfig.productionIntegrity : undefined,
|
|
188
|
+
},
|
|
189
|
+
plugins:
|
|
190
|
+
options?.plugins && Object.keys(options.plugins).length > 0 ? options.plugins : undefined,
|
|
191
|
+
};
|
|
314
192
|
}
|
|
315
193
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
194
|
+
async function loadConfigFile(configPath: string, baseDir: string): Promise<BosConfigInput> {
|
|
195
|
+
if (configPath.startsWith("bos://")) {
|
|
196
|
+
return fetchBosConfigFromFastKv<BosConfigInput>(configPath);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const resolvedPath = isAbsolute(configPath) ? configPath : resolve(baseDir, configPath);
|
|
200
|
+
return JSON.parse(readFileSync(resolvedPath, "utf-8")) as BosConfigInput;
|
|
323
201
|
}
|
|
324
202
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
203
|
+
async function resolveConfigWithExtends(
|
|
204
|
+
configPath: string,
|
|
205
|
+
baseDir: string,
|
|
206
|
+
visited: Set<string>,
|
|
207
|
+
chain: string[],
|
|
208
|
+
): Promise<BosConfigInput> {
|
|
209
|
+
if (visited.has(configPath)) {
|
|
210
|
+
throw new Error(`Circular extends detected: ${[...visited, configPath].join(" -> ")}`);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const config = await loadConfigFile(configPath, baseDir);
|
|
214
|
+
if (configPath.startsWith("bos://")) {
|
|
215
|
+
chain.push(configPath);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (!config.extends) {
|
|
219
|
+
return config;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const nextVisited = new Set(visited);
|
|
223
|
+
nextVisited.add(configPath);
|
|
224
|
+
const parentPath = config.extends;
|
|
225
|
+
const parentBaseDir = parentPath.startsWith("bos://")
|
|
226
|
+
? baseDir
|
|
227
|
+
: isAbsolute(parentPath)
|
|
228
|
+
? dirname(parentPath)
|
|
229
|
+
: baseDir;
|
|
230
|
+
const parent = await resolveConfigWithExtends(parentPath, parentBaseDir, nextVisited, chain);
|
|
231
|
+
|
|
232
|
+
return mergeConfigs(parent, config);
|
|
338
233
|
}
|
|
339
234
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
try {
|
|
348
|
-
const data = await Effect.runPromise(
|
|
349
|
-
Effect.tryPromise({
|
|
350
|
-
try: () =>
|
|
351
|
-
Promise.race([
|
|
352
|
-
graph.get({ keys: [configPath] }),
|
|
353
|
-
new Promise<never>((_, reject) =>
|
|
354
|
-
setTimeout(() => reject(new Error("Timeout after 10s")), 10000),
|
|
355
|
-
),
|
|
356
|
-
]),
|
|
357
|
-
catch: (e) => new ConfigFetchError(bosUrl, e),
|
|
358
|
-
}),
|
|
359
|
-
);
|
|
360
|
-
|
|
361
|
-
if (!data) {
|
|
362
|
-
throw new ConfigFetchError(bosUrl, "No data returned");
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
// Navigate nested structure
|
|
366
|
-
const parts = configPath.split("/");
|
|
367
|
-
let current: unknown = data;
|
|
368
|
-
for (const part of parts) {
|
|
369
|
-
if (current && typeof current === "object" && part in current) {
|
|
370
|
-
current = (current as Record<string, unknown>)[part];
|
|
371
|
-
} else {
|
|
372
|
-
throw new ConfigFetchError(bosUrl, `Path not found: ${configPath}`);
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
if (typeof current !== "string") {
|
|
377
|
-
throw new ConfigFetchError(bosUrl, "Config is not a string");
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
return JSON.parse(current) as BosConfigInput;
|
|
381
|
-
} catch (error) {
|
|
382
|
-
if (error instanceof ConfigFetchError) {
|
|
383
|
-
throw error;
|
|
384
|
-
}
|
|
385
|
-
throw new ConfigFetchError(bosUrl, error);
|
|
386
|
-
}
|
|
235
|
+
function mergeConfigs(parent: BosConfigInput, child: BosConfigInput): BosConfigInput {
|
|
236
|
+
const result = mergeValues(parent, child) as BosConfigInput;
|
|
237
|
+
if (child.plugins !== undefined) {
|
|
238
|
+
result.plugins = child.plugins;
|
|
239
|
+
}
|
|
240
|
+
return result;
|
|
387
241
|
}
|
|
388
242
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
243
|
+
async function resolveRuntimePlugins(
|
|
244
|
+
plugins: Record<string, BosConfigInput>,
|
|
245
|
+
baseDir: string,
|
|
246
|
+
env: "development" | "production",
|
|
247
|
+
prefix: string[] = [],
|
|
248
|
+
): Promise<Record<string, RuntimePluginConfig>> {
|
|
249
|
+
const out: Record<string, RuntimePluginConfig> = {};
|
|
250
|
+
|
|
251
|
+
for (const [pluginId, pluginInput] of Object.entries(plugins)) {
|
|
252
|
+
const runtimeKey = [...prefix, pluginId].join("/");
|
|
253
|
+
const { config: resolvedConfig, baseDir: pluginBaseDir } = await resolveBosConfigInput(
|
|
254
|
+
pluginInput,
|
|
255
|
+
baseDir,
|
|
256
|
+
new Set(),
|
|
257
|
+
[],
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
const pluginRuntime = buildRuntimePluginConfig(
|
|
261
|
+
runtimeKey,
|
|
262
|
+
resolvedConfig,
|
|
263
|
+
pluginBaseDir,
|
|
264
|
+
env,
|
|
265
|
+
pluginInput,
|
|
266
|
+
);
|
|
267
|
+
if (
|
|
268
|
+
pluginRuntime.source === "remote" &&
|
|
269
|
+
pluginRuntime.url &&
|
|
270
|
+
!pluginRuntime.localPath &&
|
|
271
|
+
typeof resolvedConfig.app?.api?.name !== "string"
|
|
272
|
+
) {
|
|
273
|
+
pluginRuntime.name = await resolveRemotePluginRuntimeName(
|
|
274
|
+
pluginRuntime.url,
|
|
275
|
+
pluginRuntime.name,
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const productionIntegrity = pluginInput.productionIntegrity;
|
|
280
|
+
if (env === "production" && productionIntegrity) {
|
|
281
|
+
pluginRuntime.integrity = productionIntegrity;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
out[runtimeKey] = pluginRuntime;
|
|
285
|
+
|
|
286
|
+
if (resolvedConfig.plugins && Object.keys(resolvedConfig.plugins).length > 0) {
|
|
287
|
+
const nested = await resolveRuntimePlugins(resolvedConfig.plugins, pluginBaseDir, env, [
|
|
288
|
+
...prefix,
|
|
289
|
+
pluginId,
|
|
290
|
+
]);
|
|
291
|
+
Object.assign(out, nested);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return out;
|
|
410
296
|
}
|
|
411
297
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
for (const key of new Set([
|
|
431
|
-
...Object.keys(parentApps),
|
|
432
|
-
...Object.keys(childApps),
|
|
433
|
-
])) {
|
|
434
|
-
const parentApp = parentApps[key as keyof typeof parentApps];
|
|
435
|
-
const childApp = childApps[key as keyof typeof childApps];
|
|
436
|
-
|
|
437
|
-
if (parentApp && childApp) {
|
|
438
|
-
(merged.app as Record<string, unknown>)[key] = {
|
|
439
|
-
...parentApp,
|
|
440
|
-
...childApp,
|
|
441
|
-
};
|
|
442
|
-
} else if (childApp) {
|
|
443
|
-
(merged.app as Record<string, unknown>)[key] = childApp;
|
|
444
|
-
} else if (parentApp) {
|
|
445
|
-
(merged.app as Record<string, unknown>)[key] = parentApp;
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
// Merge shared deps deeply
|
|
451
|
-
if (parent.shared || child.shared) {
|
|
452
|
-
merged.shared = { ...parent.shared, ...child.shared };
|
|
453
|
-
const parentShared = parent.shared || {};
|
|
454
|
-
const childShared = child.shared || {};
|
|
455
|
-
|
|
456
|
-
// Deep merge each shared category (ui, api, etc.)
|
|
457
|
-
for (const category of new Set([
|
|
458
|
-
...Object.keys(parentShared),
|
|
459
|
-
...Object.keys(childShared),
|
|
460
|
-
])) {
|
|
461
|
-
const parentCategory =
|
|
462
|
-
parentShared[category as keyof typeof parentShared];
|
|
463
|
-
const childCategory = childShared[category as keyof typeof childShared];
|
|
464
|
-
|
|
465
|
-
if (parentCategory && childCategory) {
|
|
466
|
-
(merged.shared as Record<string, unknown>)[category] = {
|
|
467
|
-
...parentCategory,
|
|
468
|
-
...childCategory,
|
|
469
|
-
};
|
|
470
|
-
} else if (childCategory) {
|
|
471
|
-
(merged.shared as Record<string, unknown>)[category] = childCategory;
|
|
472
|
-
} else if (parentCategory) {
|
|
473
|
-
(merged.shared as Record<string, unknown>)[category] = parentCategory;
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
return merged;
|
|
298
|
+
async function resolveRemotePluginRuntimeName(baseUrl: string, fallback: string): Promise<string> {
|
|
299
|
+
try {
|
|
300
|
+
const response = await fetch(`${baseUrl.replace(/\/$/, "")}/plugin.manifest.json`);
|
|
301
|
+
if (!response.ok) {
|
|
302
|
+
return fallback;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const manifest = (await response.json()) as {
|
|
306
|
+
plugin?: { name?: unknown };
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
return typeof manifest.plugin?.name === "string" && manifest.plugin.name.length > 0
|
|
310
|
+
? manifest.plugin.name
|
|
311
|
+
: fallback;
|
|
312
|
+
} catch {
|
|
313
|
+
return fallback;
|
|
314
|
+
}
|
|
479
315
|
}
|
|
480
316
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
: baseDir;
|
|
519
|
-
|
|
520
|
-
const parentConfig = await resolveConfigWithExtends(
|
|
521
|
-
parentPath,
|
|
522
|
-
parentBaseDir,
|
|
523
|
-
newVisited,
|
|
524
|
-
chain,
|
|
525
|
-
);
|
|
526
|
-
|
|
527
|
-
// Merge and return
|
|
528
|
-
return mergeConfigs(parentConfig, config);
|
|
317
|
+
function buildRuntimePluginConfig(
|
|
318
|
+
pluginId: string,
|
|
319
|
+
config: BosConfigInput,
|
|
320
|
+
baseDir: string,
|
|
321
|
+
env: "development" | "production",
|
|
322
|
+
source: BosConfigInput,
|
|
323
|
+
): RuntimePluginConfig {
|
|
324
|
+
const apiConfig = config.app?.api ?? {};
|
|
325
|
+
const apiDevelopment =
|
|
326
|
+
typeof apiConfig.development === "string" ? apiConfig.development : undefined;
|
|
327
|
+
const apiProduction = typeof apiConfig.production === "string" ? apiConfig.production : undefined;
|
|
328
|
+
const sourceDevelopment = typeof source.development === "string" ? source.development : undefined;
|
|
329
|
+
const sourceProduction = typeof source.production === "string" ? source.production : undefined;
|
|
330
|
+
const proxy = typeof apiConfig.proxy === "string" ? apiConfig.proxy : undefined;
|
|
331
|
+
const runtimeTarget =
|
|
332
|
+
env === "development"
|
|
333
|
+
? resolveRuntimeTarget(apiDevelopment ?? sourceDevelopment, baseDir)
|
|
334
|
+
: resolveRuntimeTarget(apiProduction ?? sourceProduction, baseDir, "remote");
|
|
335
|
+
const apiName = resolvePluginRuntimeName(
|
|
336
|
+
typeof apiConfig.name === "string" ? apiConfig.name : undefined,
|
|
337
|
+
runtimeTarget.localPath,
|
|
338
|
+
pluginId,
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
return {
|
|
342
|
+
name: apiName,
|
|
343
|
+
url: runtimeTarget.url,
|
|
344
|
+
entry: runtimeTarget.url
|
|
345
|
+
? `${runtimeTarget.url.replace(/\/$/, "")}/mf-manifest.json`
|
|
346
|
+
: "/mf-manifest.json",
|
|
347
|
+
source: runtimeTarget.source,
|
|
348
|
+
localPath: runtimeTarget.localPath,
|
|
349
|
+
port: runtimeTarget.port,
|
|
350
|
+
proxy: proxy ?? (typeof source.proxy === "string" ? source.proxy : undefined),
|
|
351
|
+
variables: normalizeStringRecord(apiConfig.variables ?? source.variables),
|
|
352
|
+
secrets: normalizeStringArray(apiConfig.secrets ?? source.secrets),
|
|
353
|
+
};
|
|
529
354
|
}
|
|
530
355
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
356
|
+
function resolvePluginRuntimeName(
|
|
357
|
+
explicitName: string | undefined,
|
|
358
|
+
localPath: string | undefined,
|
|
359
|
+
fallback: string,
|
|
360
|
+
): string {
|
|
361
|
+
if (explicitName) {
|
|
362
|
+
return explicitName;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (!localPath) {
|
|
366
|
+
return fallback;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
try {
|
|
370
|
+
const packageJsonPath = join(localPath, "package.json");
|
|
371
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8")) as { name?: unknown };
|
|
372
|
+
if (typeof packageJson.name === "string" && packageJson.name.length > 0) {
|
|
373
|
+
return packageJson.name;
|
|
374
|
+
}
|
|
375
|
+
} catch {}
|
|
376
|
+
|
|
377
|
+
return fallback;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
async function resolveBosConfigInput(
|
|
381
|
+
input: BosConfigInput,
|
|
382
|
+
baseDir: string,
|
|
383
|
+
visited: Set<string>,
|
|
384
|
+
chain: string[],
|
|
385
|
+
): Promise<{ config: BosConfigInput; baseDir: string }> {
|
|
386
|
+
if (input.extends) {
|
|
387
|
+
const parentBaseDir = input.extends.startsWith("bos://")
|
|
388
|
+
? baseDir
|
|
389
|
+
: isAbsolute(input.extends)
|
|
390
|
+
? dirname(input.extends)
|
|
391
|
+
: baseDir;
|
|
392
|
+
const config = await resolveConfigWithExtends(input.extends, parentBaseDir, visited, chain);
|
|
393
|
+
return { config: mergeConfigs(config, input), baseDir: parentBaseDir };
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
return { config: input, baseDir };
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function mergeValues(parent: unknown, child: unknown): unknown {
|
|
400
|
+
if (Array.isArray(parent) && Array.isArray(child)) {
|
|
401
|
+
return child;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (isPlainObject(parent) && isPlainObject(child)) {
|
|
405
|
+
const merged: Record<string, unknown> = { ...parent };
|
|
406
|
+
for (const [key, value] of Object.entries(child)) {
|
|
407
|
+
merged[key] = key in merged ? mergeValues(merged[key], value) : value;
|
|
408
|
+
}
|
|
409
|
+
return merged;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
return child ?? parent;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
416
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function normalizeStringRecord(value: unknown): Record<string, string> | undefined {
|
|
420
|
+
if (!isPlainObject(value)) return undefined;
|
|
421
|
+
const out: Record<string, string> = {};
|
|
422
|
+
for (const [key, raw] of Object.entries(value)) {
|
|
423
|
+
if (typeof raw === "string") {
|
|
424
|
+
out[key] = raw;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
function normalizeStringArray(value: unknown): string[] | undefined {
|
|
431
|
+
if (!Array.isArray(value)) return undefined;
|
|
432
|
+
const out = value.filter((item): item is string => typeof item === "string" && item.length > 0);
|
|
433
|
+
return out.length > 0 ? out : undefined;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function resolveRuntimeTarget(
|
|
437
|
+
value: string | undefined,
|
|
438
|
+
baseDir: string,
|
|
439
|
+
defaultSource: "local" | "remote" = "remote",
|
|
440
|
+
): RuntimeTarget {
|
|
441
|
+
if (!value) {
|
|
442
|
+
return { source: defaultSource, url: "" };
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (value.startsWith(LOCAL_PREFIX)) {
|
|
446
|
+
const localTarget = value.slice(LOCAL_PREFIX.length).trim();
|
|
447
|
+
if (!localTarget) {
|
|
448
|
+
throw new Error(`Invalid local development target: ${value}`);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
return {
|
|
452
|
+
source: "local",
|
|
453
|
+
url: "",
|
|
454
|
+
localPath: resolve(baseDir, localTarget),
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
return {
|
|
459
|
+
source: defaultSource,
|
|
460
|
+
url: value.replace(/\/$/, ""),
|
|
461
|
+
port: parsePort(value),
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
export function isLocalDevelopmentTarget(value: string | undefined): boolean {
|
|
466
|
+
return typeof value === "string" && value.startsWith(LOCAL_PREFIX);
|
|
573
467
|
}
|
|
468
|
+
|
|
469
|
+
export function resolveLocalDevelopmentPath(
|
|
470
|
+
value: string | undefined,
|
|
471
|
+
baseDir: string,
|
|
472
|
+
): string | null {
|
|
473
|
+
if (!isLocalDevelopmentTarget(value)) {
|
|
474
|
+
return null;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
const localTarget = value!.slice(LOCAL_PREFIX.length).trim();
|
|
478
|
+
return localTarget ? resolve(baseDir, localTarget) : null;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
export function resolveDevelopmentHostUrl(value: string | undefined): string {
|
|
482
|
+
if (!value || isLocalDevelopmentTarget(value)) {
|
|
483
|
+
return `http://localhost:${DEFAULT_HOST_PORT}`;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
return value.replace(/\/$/, "");
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
export function getHostDevelopmentPort(value: string | undefined): number {
|
|
490
|
+
return parsePort(resolveDevelopmentHostUrl(value));
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
export function parsePort(url: string): number {
|
|
494
|
+
try {
|
|
495
|
+
const parsed = new URL(url);
|
|
496
|
+
return parsed.port ? parseInt(parsed.port, 10) : parsed.protocol === "https:" ? 443 : 80;
|
|
497
|
+
} catch {
|
|
498
|
+
return 3000;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
export type { BosConfig, RuntimeConfig } from "./types";
|
|
503
|
+
export { BosConfigSchema } from "./types";
|