everything-dev 1.27.0 → 1.28.0
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/dist/cli/infra.cjs +1 -1
- package/dist/cli/infra.mjs +1 -1
- package/dist/cli/init.cjs +7 -9
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.d.cts +1 -1
- package/dist/cli/init.d.cts.map +1 -1
- package/dist/cli/init.d.mts +1 -1
- package/dist/cli/init.d.mts.map +1 -1
- package/dist/cli/init.mjs +7 -9
- package/dist/cli/init.mjs.map +1 -1
- package/dist/cli/prompts.cjs +28 -24
- package/dist/cli/prompts.cjs.map +1 -1
- package/dist/cli/prompts.mjs +27 -24
- package/dist/cli/prompts.mjs.map +1 -1
- package/dist/cli/sync.cjs +4 -1
- package/dist/cli/sync.cjs.map +1 -1
- package/dist/cli/sync.mjs +4 -1
- package/dist/cli/sync.mjs.map +1 -1
- package/dist/cli.cjs +187 -12
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +186 -11
- package/dist/cli.mjs.map +1 -1
- package/dist/contract.cjs +1 -1
- package/dist/contract.cjs.map +1 -1
- package/dist/contract.d.cts +38 -34
- package/dist/contract.d.cts.map +1 -1
- package/dist/contract.d.mts +38 -34
- package/dist/contract.d.mts.map +1 -1
- package/dist/contract.mjs +1 -0
- package/dist/contract.mjs.map +1 -1
- package/dist/dev-session.cjs +0 -1
- package/dist/dev-session.mjs +1 -1
- package/dist/index.cjs +0 -2
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +0 -1
- package/dist/near-cli.cjs +1 -1
- package/dist/near-cli.mjs +1 -1
- package/dist/orchestrator.cjs +1 -1
- package/dist/orchestrator.mjs +1 -1
- package/dist/plugin.cjs +163 -139
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +67 -34
- package/dist/plugin.d.cts.map +1 -1
- package/dist/plugin.d.mts +66 -34
- package/dist/plugin.d.mts.map +1 -1
- package/dist/plugin.mjs +153 -130
- package/dist/plugin.mjs.map +1 -1
- package/dist/service-descriptor.d.cts +34 -0
- package/dist/service-descriptor.d.cts.map +1 -0
- package/dist/service-descriptor.d.mts +36 -0
- package/dist/service-descriptor.d.mts.map +1 -0
- package/dist/types.d.cts +2 -2
- package/dist/types.d.mts +2 -2
- package/package.json +2 -2
- package/src/api-contract.ts +0 -623
- package/src/app.ts +0 -193
- package/src/cli/catalog.ts +0 -49
- package/src/cli/framework-version.ts +0 -61
- package/src/cli/help.ts +0 -13
- package/src/cli/infra.ts +0 -190
- package/src/cli/init.ts +0 -1145
- package/src/cli/parse.ts +0 -147
- package/src/cli/prompts.ts +0 -135
- package/src/cli/snapshot.ts +0 -46
- package/src/cli/status.ts +0 -99
- package/src/cli/sync.ts +0 -429
- package/src/cli/timing.ts +0 -63
- package/src/cli/upgrade.ts +0 -869
- package/src/cli.ts +0 -516
- package/src/components/dev-view.tsx +0 -352
- package/src/components/streaming-view.ts +0 -177
- package/src/config.ts +0 -893
- package/src/contract.meta.ts +0 -140
- package/src/contract.ts +0 -326
- package/src/dev-logs.ts +0 -92
- package/src/dev-session.ts +0 -283
- package/src/fastkv.ts +0 -181
- package/src/index.ts +0 -8
- package/src/integrity.ts +0 -138
- package/src/internal/manifest-normalizer.ts +0 -290
- package/src/merge.ts +0 -187
- package/src/mf.ts +0 -147
- package/src/near-cli.ts +0 -259
- package/src/network.ts +0 -3
- package/src/orchestrator.ts +0 -493
- package/src/plugin.ts +0 -1799
- package/src/sdk.ts +0 -14
- package/src/service-descriptor.ts +0 -281
- package/src/shared.ts +0 -249
- package/src/sidebar.ts +0 -140
- package/src/types.ts +0 -330
- package/src/ui/head.ts +0 -83
- package/src/ui/index.ts +0 -5
- package/src/ui/metadata.ts +0 -95
- package/src/ui/router.ts +0 -88
- package/src/ui/runtime.ts +0 -42
- package/src/ui/types.ts +0 -65
- package/src/utils/banner.ts +0 -21
- package/src/utils/linkify.ts +0 -11
- package/src/utils/path-match.ts +0 -16
- package/src/utils/run.ts +0 -31
- package/src/utils/save-config.ts +0 -20
- package/src/utils/theme.ts +0 -39
package/src/config.ts
DELETED
|
@@ -1,893 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
3
|
-
import { fetchBosConfigFromFastKv } from "./fastkv";
|
|
4
|
-
import {
|
|
5
|
-
type BosEnv,
|
|
6
|
-
bosConfigMerger,
|
|
7
|
-
isPlainObject,
|
|
8
|
-
mergeBosConfigWithExtends,
|
|
9
|
-
type ResolvedConfigMeta,
|
|
10
|
-
rebuildOrderedConfig,
|
|
11
|
-
resolveExtendsRef,
|
|
12
|
-
} from "./merge";
|
|
13
|
-
import { getNetworkIdForAccount } from "./network";
|
|
14
|
-
import type {
|
|
15
|
-
BosConfig,
|
|
16
|
-
BosConfigInput,
|
|
17
|
-
BosPluginRef,
|
|
18
|
-
ExtendsConfig,
|
|
19
|
-
PluginEntryValue,
|
|
20
|
-
RuntimeConfig,
|
|
21
|
-
RuntimePluginConfig,
|
|
22
|
-
} from "./types";
|
|
23
|
-
import { BosConfigSchema } from "./types";
|
|
24
|
-
|
|
25
|
-
const LOCAL_PREFIX = "local:";
|
|
26
|
-
const DEFAULT_HOST_PORT = 3000;
|
|
27
|
-
const RESOLVED_CONFIG_FILENAME = "bos.resolved-config.json";
|
|
28
|
-
|
|
29
|
-
interface RuntimeTarget {
|
|
30
|
-
source: "local" | "remote";
|
|
31
|
-
url: string;
|
|
32
|
-
localPath?: string;
|
|
33
|
-
port?: number;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
let cachedConfig: BosConfig | null = null;
|
|
37
|
-
let projectRoot: string | null = null;
|
|
38
|
-
|
|
39
|
-
export function clearConfigCache(): void {
|
|
40
|
-
cachedConfig = null;
|
|
41
|
-
projectRoot = null;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function findConfigPath(cwd?: string): string | null {
|
|
45
|
-
let dir = cwd ?? process.cwd();
|
|
46
|
-
while (dir !== "/") {
|
|
47
|
-
const configPath = join(dir, "bos.config.json");
|
|
48
|
-
if (existsSync(configPath)) {
|
|
49
|
-
return configPath;
|
|
50
|
-
}
|
|
51
|
-
dir = dirname(dir);
|
|
52
|
-
}
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export function getConfig(): BosConfig | null {
|
|
57
|
-
return cachedConfig;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function getProjectRoot(): string {
|
|
61
|
-
if (!projectRoot) {
|
|
62
|
-
throw new Error("Config not loaded. Call loadConfig() first.");
|
|
63
|
-
}
|
|
64
|
-
return projectRoot;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export interface ConfigResult {
|
|
68
|
-
config: BosConfig;
|
|
69
|
-
runtime: RuntimeConfig;
|
|
70
|
-
source: {
|
|
71
|
-
path: string;
|
|
72
|
-
extended?: string[];
|
|
73
|
-
remote?: boolean;
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export interface ResolvedComposableReference {
|
|
78
|
-
entry: BosPluginRef;
|
|
79
|
-
providerBaseDir: string;
|
|
80
|
-
targetPath: string;
|
|
81
|
-
associatedUi?: Record<string, unknown>;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
interface ParsedExtendsTarget {
|
|
85
|
-
configPath: string;
|
|
86
|
-
targetPath?: string;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export async function loadConfig(options?: {
|
|
90
|
-
cwd?: string;
|
|
91
|
-
path?: string;
|
|
92
|
-
env?: BosEnv;
|
|
93
|
-
}): Promise<ConfigResult | null> {
|
|
94
|
-
const configPath = options?.path ?? findConfigPath(options?.cwd);
|
|
95
|
-
if (!configPath) {
|
|
96
|
-
projectRoot = options?.cwd ?? process.cwd();
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const baseDir = dirname(configPath);
|
|
101
|
-
const env = options?.env ?? "development";
|
|
102
|
-
const runtimeEnv: BosEnv = env === "staging" ? "production" : env;
|
|
103
|
-
|
|
104
|
-
try {
|
|
105
|
-
const extendedChain: string[] = [];
|
|
106
|
-
const parsed = await resolveConfigWithExtends(
|
|
107
|
-
configPath,
|
|
108
|
-
baseDir,
|
|
109
|
-
new Set(),
|
|
110
|
-
extendedChain,
|
|
111
|
-
env,
|
|
112
|
-
);
|
|
113
|
-
const config = await resolveRootComposableEntries(
|
|
114
|
-
BosConfigSchema.parse(parsed),
|
|
115
|
-
baseDir,
|
|
116
|
-
runtimeEnv,
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
cachedConfig = config;
|
|
120
|
-
projectRoot = baseDir;
|
|
121
|
-
|
|
122
|
-
const pluginRuntime = await resolveRuntimePlugins(config.plugins ?? {}, baseDir, runtimeEnv);
|
|
123
|
-
const runtime = buildRuntimeConfig(config, baseDir, runtimeEnv, {
|
|
124
|
-
plugins: pluginRuntime,
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
return {
|
|
128
|
-
config,
|
|
129
|
-
runtime,
|
|
130
|
-
source: {
|
|
131
|
-
path: configPath,
|
|
132
|
-
extended: extendedChain.length > 0 ? extendedChain : undefined,
|
|
133
|
-
remote: extendedChain.some((entry) => entry.startsWith("bos://")),
|
|
134
|
-
},
|
|
135
|
-
};
|
|
136
|
-
} catch (error) {
|
|
137
|
-
throw new Error(`Failed to load config from ${configPath}: ${error}`);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export async function loadBosConfig(options?: {
|
|
142
|
-
cwd?: string;
|
|
143
|
-
path?: string;
|
|
144
|
-
env?: BosEnv;
|
|
145
|
-
}): Promise<RuntimeConfig> {
|
|
146
|
-
const result = await loadConfig(options);
|
|
147
|
-
if (!result) {
|
|
148
|
-
throw new Error("No bos.config.json found");
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return result.runtime;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export async function buildRuntimePluginsForConfig(
|
|
155
|
-
config: BosConfig,
|
|
156
|
-
baseDir: string,
|
|
157
|
-
env: BosEnv,
|
|
158
|
-
): Promise<Record<string, RuntimePluginConfig> | undefined> {
|
|
159
|
-
const plugins = await resolveRuntimePlugins(config.plugins ?? {}, baseDir, env);
|
|
160
|
-
return Object.keys(plugins).length > 0 ? plugins : undefined;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
async function resolveRootComposableEntries(
|
|
164
|
-
config: BosConfig,
|
|
165
|
-
baseDir: string,
|
|
166
|
-
env: BosEnv,
|
|
167
|
-
): Promise<BosConfig> {
|
|
168
|
-
const resolvedApi = await resolveComposableReference(
|
|
169
|
-
config.app.api as BosPluginRef,
|
|
170
|
-
baseDir,
|
|
171
|
-
env,
|
|
172
|
-
"app.api",
|
|
173
|
-
);
|
|
174
|
-
const resolvedAuth = config.app.auth
|
|
175
|
-
? await resolveComposableReference(config.app.auth as BosPluginRef, baseDir, env, "app.auth")
|
|
176
|
-
: undefined;
|
|
177
|
-
|
|
178
|
-
return {
|
|
179
|
-
...config,
|
|
180
|
-
app: {
|
|
181
|
-
...config.app,
|
|
182
|
-
api: resolvedApi.entry,
|
|
183
|
-
auth: resolvedAuth?.entry,
|
|
184
|
-
},
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
export function getResolvedConfigPath(configDir: string): string {
|
|
189
|
-
return join(configDir, ".bos", RESOLVED_CONFIG_FILENAME);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
export function loadResolvedConfig(configDir: string): BosConfig | null {
|
|
193
|
-
const resolvedPath = getResolvedConfigPath(configDir);
|
|
194
|
-
if (!existsSync(resolvedPath)) return null;
|
|
195
|
-
try {
|
|
196
|
-
const raw = JSON.parse(readFileSync(resolvedPath, "utf-8"));
|
|
197
|
-
if (!isPlainObject(raw)) return null;
|
|
198
|
-
const { _resolved, ...configData } = raw;
|
|
199
|
-
return BosConfigSchema.parse(configData);
|
|
200
|
-
} catch {
|
|
201
|
-
return null;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
export function writeResolvedConfig(
|
|
206
|
-
configDir: string,
|
|
207
|
-
config: BosConfig,
|
|
208
|
-
env: BosEnv,
|
|
209
|
-
extendsChain?: string[],
|
|
210
|
-
source?: string,
|
|
211
|
-
): void {
|
|
212
|
-
const resolvedPath = getResolvedConfigPath(configDir);
|
|
213
|
-
const resolvedDir = dirname(resolvedPath);
|
|
214
|
-
if (!existsSync(resolvedDir)) {
|
|
215
|
-
mkdirSync(resolvedDir, { recursive: true });
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
const ordered = rebuildOrderedConfig(config);
|
|
219
|
-
const meta: ResolvedConfigMeta = {
|
|
220
|
-
env,
|
|
221
|
-
resolvedAt: new Date().toISOString(),
|
|
222
|
-
extendsChain: extendsChain ?? [],
|
|
223
|
-
...(source ? { source } : {}),
|
|
224
|
-
};
|
|
225
|
-
const output = {
|
|
226
|
-
_resolved: meta,
|
|
227
|
-
...ordered,
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
const content = `${JSON.stringify(output, null, 2)}\n`;
|
|
231
|
-
try {
|
|
232
|
-
if (readFileSync(resolvedPath, "utf-8") === content) return;
|
|
233
|
-
} catch {
|
|
234
|
-
// file doesn't exist yet
|
|
235
|
-
}
|
|
236
|
-
writeFileSync(resolvedPath, content);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
export function resolveBosConfigPath(configDir: string): string {
|
|
240
|
-
const resolvedPath = getResolvedConfigPath(configDir);
|
|
241
|
-
if (existsSync(resolvedPath)) return resolvedPath;
|
|
242
|
-
return join(configDir, "bos.config.json");
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
export function readBosConfigForBuild(configDir: string): Record<string, unknown> {
|
|
246
|
-
const resolvedPath = getResolvedConfigPath(configDir);
|
|
247
|
-
if (existsSync(resolvedPath)) {
|
|
248
|
-
try {
|
|
249
|
-
const raw = JSON.parse(readFileSync(resolvedPath, "utf-8"));
|
|
250
|
-
if (isPlainObject(raw)) {
|
|
251
|
-
const { _resolved, ...configData } = raw;
|
|
252
|
-
return configData as Record<string, unknown>;
|
|
253
|
-
}
|
|
254
|
-
} catch {}
|
|
255
|
-
}
|
|
256
|
-
const bosConfigPath = join(configDir, "bos.config.json");
|
|
257
|
-
return JSON.parse(readFileSync(bosConfigPath, "utf-8")) as Record<string, unknown>;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
function parseExtendsTarget(ref: string): ParsedExtendsTarget {
|
|
261
|
-
const hashIndex = ref.indexOf("#");
|
|
262
|
-
if (hashIndex === -1) {
|
|
263
|
-
return { configPath: ref };
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
const configPath = ref.slice(0, hashIndex);
|
|
267
|
-
const targetPath = ref.slice(hashIndex + 1);
|
|
268
|
-
return {
|
|
269
|
-
configPath,
|
|
270
|
-
targetPath: targetPath.length > 0 ? targetPath : undefined,
|
|
271
|
-
};
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
function getConfigBaseDir(configPath: string, baseDir: string): string {
|
|
275
|
-
if (configPath.startsWith("bos://")) return baseDir;
|
|
276
|
-
return dirname(isAbsolute(configPath) ? configPath : resolve(baseDir, configPath));
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
function asComposableEntry(value: unknown): BosPluginRef {
|
|
280
|
-
if (typeof value === "string") {
|
|
281
|
-
return { extends: value };
|
|
282
|
-
}
|
|
283
|
-
if (!isPlainObject(value)) {
|
|
284
|
-
throw new Error(`Expected config entry object, received ${typeof value}`);
|
|
285
|
-
}
|
|
286
|
-
return value as BosPluginRef;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
function getTargetedEntry(config: BosConfigInput, targetPath: string): BosPluginRef {
|
|
290
|
-
if (targetPath === "app.api") {
|
|
291
|
-
return asComposableEntry(config.app?.api);
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
if (targetPath === "app.auth") {
|
|
295
|
-
return asComposableEntry(config.app?.auth);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
if (targetPath.startsWith("plugins.")) {
|
|
299
|
-
const pluginId = targetPath.slice("plugins.".length);
|
|
300
|
-
if (pluginId.length === 0) {
|
|
301
|
-
throw new Error(`Invalid plugin target path: ${targetPath}`);
|
|
302
|
-
}
|
|
303
|
-
return asComposableEntry(config.plugins?.[pluginId]);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
throw new Error(`Unsupported extends target path: ${targetPath}`);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
function getAssociatedUi(
|
|
310
|
-
config: BosConfigInput,
|
|
311
|
-
_targetPath: string,
|
|
312
|
-
): Record<string, unknown> | undefined {
|
|
313
|
-
return isPlainObject(config.app?.ui) ? (config.app.ui as Record<string, unknown>) : undefined;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
function mergeComposableEntries(
|
|
317
|
-
parent: Partial<BosPluginRef>,
|
|
318
|
-
child: Partial<BosPluginRef>,
|
|
319
|
-
): BosPluginRef {
|
|
320
|
-
return bosConfigMerger({ ...child }, parent) as BosPluginRef;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
function stripUnsafeLocalDevelopment<T extends Record<string, unknown> | undefined>(
|
|
324
|
-
entry: T,
|
|
325
|
-
allowLocalPaths: boolean,
|
|
326
|
-
): T {
|
|
327
|
-
if (!entry || allowLocalPaths) {
|
|
328
|
-
return entry;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
if (typeof entry.development === "string" && entry.development.startsWith(LOCAL_PREFIX)) {
|
|
332
|
-
const { development: _ignored, ...rest } = entry;
|
|
333
|
-
return rest as T;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
return entry;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
export async function resolveComposableReference(
|
|
340
|
-
source: BosPluginRef,
|
|
341
|
-
baseDir: string,
|
|
342
|
-
env: BosEnv,
|
|
343
|
-
defaultTargetPath: string,
|
|
344
|
-
): Promise<ResolvedComposableReference> {
|
|
345
|
-
let resolvedEntry: BosPluginRef = {};
|
|
346
|
-
let providerBaseDir = baseDir;
|
|
347
|
-
let targetPath = defaultTargetPath;
|
|
348
|
-
let associatedUi: Record<string, unknown> | undefined;
|
|
349
|
-
let allowLocalPaths = false;
|
|
350
|
-
let extendsError: unknown;
|
|
351
|
-
|
|
352
|
-
const extendsRef = source.extends ? resolveExtendsRef(source.extends, env) : undefined;
|
|
353
|
-
if (extendsRef) {
|
|
354
|
-
const parsed = parseExtendsTarget(extendsRef);
|
|
355
|
-
targetPath = parsed.targetPath ?? defaultTargetPath;
|
|
356
|
-
const extendsBaseDir = getConfigBaseDir(parsed.configPath, baseDir);
|
|
357
|
-
try {
|
|
358
|
-
const extendedConfig = await resolveConfigWithExtends(
|
|
359
|
-
parsed.configPath,
|
|
360
|
-
extendsBaseDir,
|
|
361
|
-
new Set(),
|
|
362
|
-
[],
|
|
363
|
-
env,
|
|
364
|
-
);
|
|
365
|
-
resolvedEntry = mergeComposableEntries(
|
|
366
|
-
resolvedEntry,
|
|
367
|
-
getTargetedEntry(extendedConfig, targetPath),
|
|
368
|
-
);
|
|
369
|
-
providerBaseDir = extendsBaseDir;
|
|
370
|
-
associatedUi = getAssociatedUi(extendedConfig, targetPath);
|
|
371
|
-
} catch (error) {
|
|
372
|
-
extendsError = error;
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
const localDevelopment =
|
|
377
|
-
typeof source.development === "string" && source.development.startsWith(LOCAL_PREFIX)
|
|
378
|
-
? source.development
|
|
379
|
-
: undefined;
|
|
380
|
-
|
|
381
|
-
if (localDevelopment) {
|
|
382
|
-
const localPath = resolve(baseDir, localDevelopment.slice(LOCAL_PREFIX.length).trim());
|
|
383
|
-
const localConfigPath = join(localPath, "bos.config.json");
|
|
384
|
-
if (existsSync(localConfigPath)) {
|
|
385
|
-
const localConfig = await resolveConfigWithExtends(
|
|
386
|
-
localConfigPath,
|
|
387
|
-
localPath,
|
|
388
|
-
new Set(),
|
|
389
|
-
[],
|
|
390
|
-
env,
|
|
391
|
-
);
|
|
392
|
-
resolvedEntry = mergeComposableEntries(
|
|
393
|
-
resolvedEntry,
|
|
394
|
-
getTargetedEntry(localConfig, targetPath),
|
|
395
|
-
);
|
|
396
|
-
providerBaseDir = localPath;
|
|
397
|
-
associatedUi = getAssociatedUi(localConfig, targetPath);
|
|
398
|
-
allowLocalPaths = true;
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
const sourceOverrides = { ...source };
|
|
403
|
-
if (allowLocalPaths && localDevelopment) {
|
|
404
|
-
delete sourceOverrides.development;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
resolvedEntry = mergeComposableEntries(resolvedEntry, sourceOverrides);
|
|
408
|
-
|
|
409
|
-
if (
|
|
410
|
-
extendsError &&
|
|
411
|
-
!allowLocalPaths &&
|
|
412
|
-
typeof resolvedEntry.development !== "string" &&
|
|
413
|
-
typeof resolvedEntry.production !== "string" &&
|
|
414
|
-
typeof resolvedEntry.name !== "string"
|
|
415
|
-
) {
|
|
416
|
-
throw extendsError;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
return {
|
|
420
|
-
entry: stripUnsafeLocalDevelopment(resolvedEntry, allowLocalPaths || Boolean(localDevelopment)),
|
|
421
|
-
providerBaseDir,
|
|
422
|
-
targetPath,
|
|
423
|
-
associatedUi: stripUnsafeLocalDevelopment(associatedUi, allowLocalPaths),
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
function resolveDevelopmentTarget(
|
|
428
|
-
development: string | undefined,
|
|
429
|
-
production: string | undefined,
|
|
430
|
-
baseDir: string,
|
|
431
|
-
forceSource?: "local" | "remote",
|
|
432
|
-
): RuntimeTarget {
|
|
433
|
-
if (forceSource === "remote") {
|
|
434
|
-
return resolveRuntimeTarget(production, baseDir, "remote");
|
|
435
|
-
}
|
|
436
|
-
if (!development) {
|
|
437
|
-
return resolveRuntimeTarget(production, baseDir, "remote");
|
|
438
|
-
}
|
|
439
|
-
const devTarget = resolveRuntimeTarget(development, baseDir);
|
|
440
|
-
if (devTarget.source === "local" && (!devTarget.localPath || !existsSync(devTarget.localPath))) {
|
|
441
|
-
return resolveRuntimeTarget(production, baseDir, "remote");
|
|
442
|
-
}
|
|
443
|
-
return devTarget;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
export interface BuildRuntimeConfigOptions {
|
|
447
|
-
plugins?: Record<string, RuntimePluginConfig>;
|
|
448
|
-
hostSource?: "local" | "remote";
|
|
449
|
-
uiSource?: "local" | "remote";
|
|
450
|
-
apiSource?: "local" | "remote";
|
|
451
|
-
authSource?: "local" | "remote";
|
|
452
|
-
proxy?: string;
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
export function buildRuntimeConfig(
|
|
456
|
-
config: BosConfig,
|
|
457
|
-
baseDir: string,
|
|
458
|
-
env: BosEnv,
|
|
459
|
-
options?: BuildRuntimeConfigOptions,
|
|
460
|
-
): RuntimeConfig {
|
|
461
|
-
const uiConfig = config.app.ui;
|
|
462
|
-
const apiConfig = config.app.api;
|
|
463
|
-
const authConfig = config.app.auth;
|
|
464
|
-
const uiRuntime =
|
|
465
|
-
env === "development"
|
|
466
|
-
? resolveDevelopmentTarget(
|
|
467
|
-
uiConfig.development,
|
|
468
|
-
uiConfig.production,
|
|
469
|
-
baseDir,
|
|
470
|
-
options?.uiSource,
|
|
471
|
-
)
|
|
472
|
-
: resolveRuntimeTarget(uiConfig.production, baseDir, "remote");
|
|
473
|
-
const apiRuntime =
|
|
474
|
-
env === "development"
|
|
475
|
-
? resolveDevelopmentTarget(
|
|
476
|
-
apiConfig.development,
|
|
477
|
-
apiConfig.production,
|
|
478
|
-
baseDir,
|
|
479
|
-
options?.apiSource,
|
|
480
|
-
)
|
|
481
|
-
: resolveRuntimeTarget(apiConfig.production, baseDir, "remote");
|
|
482
|
-
const authRuntime = authConfig
|
|
483
|
-
? env === "development"
|
|
484
|
-
? resolveDevelopmentTarget(
|
|
485
|
-
authConfig.development,
|
|
486
|
-
authConfig.production,
|
|
487
|
-
baseDir,
|
|
488
|
-
options?.authSource,
|
|
489
|
-
)
|
|
490
|
-
: resolveRuntimeTarget(authConfig.production, baseDir, "remote")
|
|
491
|
-
: undefined;
|
|
492
|
-
|
|
493
|
-
const hostConfig = config.app.host;
|
|
494
|
-
const hostRuntime =
|
|
495
|
-
env === "development"
|
|
496
|
-
? resolveDevelopmentTarget(
|
|
497
|
-
hostConfig.development,
|
|
498
|
-
hostConfig.production,
|
|
499
|
-
baseDir,
|
|
500
|
-
options?.hostSource,
|
|
501
|
-
)
|
|
502
|
-
: resolveRuntimeTarget(hostConfig.production, baseDir, "remote");
|
|
503
|
-
|
|
504
|
-
const hostListeningUrl =
|
|
505
|
-
env === "development"
|
|
506
|
-
? resolveDevelopmentHostUrl(hostConfig.development)
|
|
507
|
-
: `http://localhost:${hostRuntime.port ?? DEFAULT_HOST_PORT}`;
|
|
508
|
-
|
|
509
|
-
const hostIsRemote = hostRuntime.source === "remote";
|
|
510
|
-
const uiIsRemote = uiRuntime.source === "remote";
|
|
511
|
-
const apiIsRemote = apiRuntime.source === "remote";
|
|
512
|
-
const resolvedApiName = resolvePluginRuntimeName(apiConfig.name, apiRuntime.localPath, "api");
|
|
513
|
-
|
|
514
|
-
return {
|
|
515
|
-
env,
|
|
516
|
-
account: config.account,
|
|
517
|
-
domain: config.domain,
|
|
518
|
-
title: config.title,
|
|
519
|
-
description: config.description,
|
|
520
|
-
networkId: getNetworkIdForAccount(config.account),
|
|
521
|
-
repository: config.repository,
|
|
522
|
-
host: {
|
|
523
|
-
name: "host",
|
|
524
|
-
url: hostListeningUrl,
|
|
525
|
-
entry: `${hostListeningUrl}/mf-manifest.json`,
|
|
526
|
-
localPath: hostRuntime.localPath,
|
|
527
|
-
port: hostRuntime.port ?? DEFAULT_HOST_PORT,
|
|
528
|
-
secrets: hostConfig.secrets,
|
|
529
|
-
integrity: hostIsRemote ? hostConfig.integrity : undefined,
|
|
530
|
-
source: hostRuntime.source,
|
|
531
|
-
remoteUrl: hostIsRemote ? hostRuntime.url : undefined,
|
|
532
|
-
},
|
|
533
|
-
shared: config.shared,
|
|
534
|
-
ui: {
|
|
535
|
-
name: uiConfig.name,
|
|
536
|
-
url: uiRuntime.url,
|
|
537
|
-
entry: uiRuntime.url ? `${uiRuntime.url}/mf-manifest.json` : "/mf-manifest.json",
|
|
538
|
-
localPath: uiRuntime.localPath,
|
|
539
|
-
port: uiRuntime.port,
|
|
540
|
-
ssrUrl: uiIsRemote ? uiConfig.ssr : undefined,
|
|
541
|
-
ssrIntegrity: uiIsRemote ? uiConfig.ssrIntegrity : undefined,
|
|
542
|
-
integrity: uiIsRemote ? uiConfig.integrity : undefined,
|
|
543
|
-
source: uiRuntime.source,
|
|
544
|
-
},
|
|
545
|
-
api: {
|
|
546
|
-
name: resolvedApiName,
|
|
547
|
-
url: apiRuntime.url,
|
|
548
|
-
entry: apiRuntime.url ? `${apiRuntime.url}/mf-manifest.json` : "/mf-manifest.json",
|
|
549
|
-
localPath: apiRuntime.localPath,
|
|
550
|
-
port: apiRuntime.port,
|
|
551
|
-
source: apiRuntime.source,
|
|
552
|
-
proxy: options?.proxy ?? apiConfig.proxy,
|
|
553
|
-
variables: apiConfig.variables,
|
|
554
|
-
secrets: apiConfig.secrets,
|
|
555
|
-
integrity: apiIsRemote ? apiConfig.integrity : undefined,
|
|
556
|
-
},
|
|
557
|
-
auth: (() => {
|
|
558
|
-
if (!authConfig || !authRuntime) return undefined;
|
|
559
|
-
return {
|
|
560
|
-
name: resolvePluginRuntimeName(authConfig.name, authRuntime.localPath, "auth"),
|
|
561
|
-
url: authRuntime.url,
|
|
562
|
-
entry: authRuntime.url ? `${authRuntime.url}/mf-manifest.json` : "/mf-manifest.json",
|
|
563
|
-
localPath: authRuntime.localPath,
|
|
564
|
-
port: authRuntime.port,
|
|
565
|
-
source: authRuntime.source,
|
|
566
|
-
proxy: authConfig.proxy,
|
|
567
|
-
variables: authConfig.variables,
|
|
568
|
-
secrets: authConfig.secrets,
|
|
569
|
-
integrity: authRuntime.source === "remote" ? authConfig.integrity : undefined,
|
|
570
|
-
sidebar: authConfig.sidebar?.map((item) => ({
|
|
571
|
-
...item,
|
|
572
|
-
to: item.to ?? "/auth",
|
|
573
|
-
roleRequired: item.roleRequired ?? ("member" as const),
|
|
574
|
-
})),
|
|
575
|
-
};
|
|
576
|
-
})(),
|
|
577
|
-
plugins:
|
|
578
|
-
options?.plugins && Object.keys(options.plugins).length > 0 ? options.plugins : undefined,
|
|
579
|
-
};
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
async function loadConfigFile(configPath: string, baseDir: string): Promise<BosConfigInput> {
|
|
583
|
-
if (configPath.startsWith("bos://")) {
|
|
584
|
-
return fetchBosConfigFromFastKv<BosConfigInput>(configPath);
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
const resolvedPath = isAbsolute(configPath) ? configPath : resolve(baseDir, configPath);
|
|
588
|
-
return JSON.parse(readFileSync(resolvedPath, "utf-8")) as BosConfigInput;
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
async function resolveConfigWithExtends(
|
|
592
|
-
configPath: string,
|
|
593
|
-
baseDir: string,
|
|
594
|
-
visited: Set<string>,
|
|
595
|
-
chain: string[],
|
|
596
|
-
env: BosEnv = "development",
|
|
597
|
-
): Promise<BosConfigInput> {
|
|
598
|
-
if (visited.has(configPath)) {
|
|
599
|
-
throw new Error(`Circular extends detected: ${[...visited, configPath].join(" -> ")}`);
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
const config = await loadConfigFile(configPath, baseDir);
|
|
603
|
-
chain.push(configPath);
|
|
604
|
-
|
|
605
|
-
if (!config.extends) {
|
|
606
|
-
return config;
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
const extendsRef = resolveExtendsRef(config.extends as string | ExtendsConfig, env);
|
|
610
|
-
if (!extendsRef) {
|
|
611
|
-
return config;
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
const parsedParentRef = parseExtendsTarget(extendsRef);
|
|
615
|
-
|
|
616
|
-
const nextVisited = new Set(visited);
|
|
617
|
-
nextVisited.add(configPath);
|
|
618
|
-
const parentBaseDir = getConfigBaseDir(parsedParentRef.configPath, baseDir);
|
|
619
|
-
const parent = await resolveConfigWithExtends(
|
|
620
|
-
parsedParentRef.configPath,
|
|
621
|
-
parentBaseDir,
|
|
622
|
-
nextVisited,
|
|
623
|
-
chain,
|
|
624
|
-
env,
|
|
625
|
-
);
|
|
626
|
-
|
|
627
|
-
return mergeBosConfigWithExtends(parent, config);
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
type PluginOverrideValue = PluginEntryValue | null | false;
|
|
631
|
-
|
|
632
|
-
function normalizePluginEntry(raw: PluginOverrideValue): BosPluginRef | null | false {
|
|
633
|
-
if (raw === null || raw === false) return raw;
|
|
634
|
-
if (typeof raw === "string") {
|
|
635
|
-
return { extends: raw };
|
|
636
|
-
}
|
|
637
|
-
return raw;
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
async function resolveRuntimePlugins(
|
|
641
|
-
plugins: Record<string, PluginOverrideValue>,
|
|
642
|
-
baseDir: string,
|
|
643
|
-
env: BosEnv,
|
|
644
|
-
): Promise<Record<string, RuntimePluginConfig>> {
|
|
645
|
-
const out: Record<string, RuntimePluginConfig> = {};
|
|
646
|
-
|
|
647
|
-
for (const [pluginId, rawInput] of Object.entries(plugins)) {
|
|
648
|
-
const normalized = normalizePluginEntry(rawInput);
|
|
649
|
-
if (normalized === null || normalized === false) continue;
|
|
650
|
-
|
|
651
|
-
const resolvedReference = await resolveComposableReference(
|
|
652
|
-
normalized,
|
|
653
|
-
baseDir,
|
|
654
|
-
env,
|
|
655
|
-
`plugins.${pluginId}`,
|
|
656
|
-
);
|
|
657
|
-
|
|
658
|
-
const pluginRuntime = buildRuntimePluginConfig(pluginId, env, resolvedReference);
|
|
659
|
-
|
|
660
|
-
if (
|
|
661
|
-
pluginRuntime.source === "remote" &&
|
|
662
|
-
pluginRuntime.url &&
|
|
663
|
-
!pluginRuntime.localPath &&
|
|
664
|
-
typeof resolvedReference.entry.name !== "string"
|
|
665
|
-
) {
|
|
666
|
-
pluginRuntime.name = await resolveRemotePluginRuntimeName(
|
|
667
|
-
pluginRuntime.url,
|
|
668
|
-
pluginRuntime.name,
|
|
669
|
-
);
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
out[pluginId] = pluginRuntime;
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
return out;
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
async function resolveRemotePluginRuntimeName(baseUrl: string, fallback: string): Promise<string> {
|
|
679
|
-
try {
|
|
680
|
-
const controller = new AbortController();
|
|
681
|
-
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
682
|
-
const response = await fetch(`${baseUrl.replace(/\/$/, "")}/plugin.manifest.json`, {
|
|
683
|
-
signal: controller.signal,
|
|
684
|
-
});
|
|
685
|
-
clearTimeout(timeout);
|
|
686
|
-
|
|
687
|
-
if (!response.ok) {
|
|
688
|
-
return fallback;
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
const manifest = (await response.json()) as {
|
|
692
|
-
plugin?: { name?: unknown };
|
|
693
|
-
};
|
|
694
|
-
|
|
695
|
-
return typeof manifest.plugin?.name === "string" && manifest.plugin.name.length > 0
|
|
696
|
-
? manifest.plugin.name
|
|
697
|
-
: fallback;
|
|
698
|
-
} catch {
|
|
699
|
-
return fallback;
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
function buildRuntimePluginConfig(
|
|
704
|
-
pluginId: string,
|
|
705
|
-
env: BosEnv,
|
|
706
|
-
resolved: ResolvedComposableReference,
|
|
707
|
-
): RuntimePluginConfig {
|
|
708
|
-
const source = resolved.entry;
|
|
709
|
-
const development = typeof source.development === "string" ? source.development : undefined;
|
|
710
|
-
const production = typeof source.production === "string" ? source.production : undefined;
|
|
711
|
-
|
|
712
|
-
if (production?.startsWith("bos://")) {
|
|
713
|
-
throw new Error(
|
|
714
|
-
`Plugin "${pluginId}" has unsupported production target "${production}". Use extends: "bos://account/domain" for plugin configs or a CDN URL for production.`,
|
|
715
|
-
);
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
const runtimeTarget =
|
|
719
|
-
env === "development"
|
|
720
|
-
? resolveDevelopmentTarget(development, production, resolved.providerBaseDir)
|
|
721
|
-
: resolveRuntimeTarget(production, resolved.providerBaseDir, "remote");
|
|
722
|
-
const apiName = resolvePluginRuntimeName(source.name, runtimeTarget.localPath, pluginId);
|
|
723
|
-
|
|
724
|
-
const uiConfig = resolved.associatedUi;
|
|
725
|
-
const uiDevelopment =
|
|
726
|
-
typeof uiConfig?.development === "string" ? uiConfig.development : undefined;
|
|
727
|
-
const uiProduction = typeof uiConfig?.production === "string" ? uiConfig.production : undefined;
|
|
728
|
-
const uiRuntime =
|
|
729
|
-
uiConfig && (uiDevelopment || uiProduction)
|
|
730
|
-
? env === "development"
|
|
731
|
-
? resolveDevelopmentTarget(uiDevelopment, uiProduction, resolved.providerBaseDir)
|
|
732
|
-
: resolveRuntimeTarget(uiProduction, resolved.providerBaseDir, "remote")
|
|
733
|
-
: undefined;
|
|
734
|
-
|
|
735
|
-
const sidebar = source.sidebar?.map((item) => ({
|
|
736
|
-
...item,
|
|
737
|
-
to: item.to ?? `/${pluginId}`,
|
|
738
|
-
roleRequired: item.roleRequired ?? ("member" as const),
|
|
739
|
-
}));
|
|
740
|
-
|
|
741
|
-
const routes = source.routes;
|
|
742
|
-
|
|
743
|
-
return {
|
|
744
|
-
name: apiName,
|
|
745
|
-
url: runtimeTarget.url,
|
|
746
|
-
entry: runtimeTarget.url
|
|
747
|
-
? `${runtimeTarget.url.replace(/\/$/, "")}/mf-manifest.json`
|
|
748
|
-
: "/mf-manifest.json",
|
|
749
|
-
source: runtimeTarget.source,
|
|
750
|
-
localPath: runtimeTarget.localPath,
|
|
751
|
-
port: runtimeTarget.port,
|
|
752
|
-
proxy: typeof source.proxy === "string" ? source.proxy : undefined,
|
|
753
|
-
variables: normalizeStringRecord(source.variables),
|
|
754
|
-
secrets: normalizeStringArray(source.secrets),
|
|
755
|
-
integrity: runtimeTarget.source === "remote" ? source.integrity : undefined,
|
|
756
|
-
ui: uiRuntime
|
|
757
|
-
? {
|
|
758
|
-
name: typeof uiConfig?.name === "string" ? uiConfig.name : `${apiName}-ui`,
|
|
759
|
-
url: uiRuntime.url,
|
|
760
|
-
entry: uiRuntime.url
|
|
761
|
-
? `${uiRuntime.url.replace(/\/$/, "")}/mf-manifest.json`
|
|
762
|
-
: "/mf-manifest.json",
|
|
763
|
-
source: uiRuntime.source,
|
|
764
|
-
localPath: uiRuntime.localPath,
|
|
765
|
-
port: uiRuntime.port,
|
|
766
|
-
integrity:
|
|
767
|
-
uiRuntime.source === "remote" && typeof uiConfig?.integrity === "string"
|
|
768
|
-
? uiConfig.integrity
|
|
769
|
-
: undefined,
|
|
770
|
-
}
|
|
771
|
-
: undefined,
|
|
772
|
-
sidebar,
|
|
773
|
-
routes,
|
|
774
|
-
};
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
export function resolvePluginRuntimeName(
|
|
778
|
-
explicitName: string | undefined,
|
|
779
|
-
localPath: string | undefined,
|
|
780
|
-
fallback: string,
|
|
781
|
-
): string {
|
|
782
|
-
if (explicitName) {
|
|
783
|
-
return explicitName;
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
if (!localPath) {
|
|
787
|
-
return fallback;
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
try {
|
|
791
|
-
const packageJsonPath = join(localPath, "package.json");
|
|
792
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8")) as { name?: unknown };
|
|
793
|
-
if (typeof packageJson.name === "string" && packageJson.name.length > 0) {
|
|
794
|
-
return packageJson.name;
|
|
795
|
-
}
|
|
796
|
-
} catch {}
|
|
797
|
-
|
|
798
|
-
return fallback;
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
function normalizeStringRecord(value: unknown): Record<string, string> | undefined {
|
|
802
|
-
if (!isPlainObject(value)) return undefined;
|
|
803
|
-
const out: Record<string, string> = {};
|
|
804
|
-
for (const [key, raw] of Object.entries(value)) {
|
|
805
|
-
if (typeof raw === "string") {
|
|
806
|
-
out[key] = raw;
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
return Object.keys(out).length > 0 ? out : undefined;
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
function normalizeStringArray(value: unknown): string[] | undefined {
|
|
813
|
-
if (!Array.isArray(value)) return undefined;
|
|
814
|
-
const out = value.filter((item): item is string => typeof item === "string" && item.length > 0);
|
|
815
|
-
return out.length > 0 ? out : undefined;
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
function resolveRuntimeTarget(
|
|
819
|
-
value: string | undefined,
|
|
820
|
-
baseDir: string,
|
|
821
|
-
defaultSource: "local" | "remote" = "remote",
|
|
822
|
-
): RuntimeTarget {
|
|
823
|
-
if (!value) {
|
|
824
|
-
return { source: defaultSource, url: "" };
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
if (value.startsWith(LOCAL_PREFIX)) {
|
|
828
|
-
const localTarget = value?.slice(LOCAL_PREFIX.length).trim();
|
|
829
|
-
if (!localTarget) {
|
|
830
|
-
throw new Error(`Invalid local development target: ${value}`);
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
const localPath = resolve(baseDir, localTarget);
|
|
834
|
-
if (!existsSync(localPath)) {
|
|
835
|
-
return { source: "local", url: "" };
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
return {
|
|
839
|
-
source: "local",
|
|
840
|
-
url: "",
|
|
841
|
-
localPath,
|
|
842
|
-
};
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
return {
|
|
846
|
-
source: defaultSource,
|
|
847
|
-
url: value.replace(/\/$/, ""),
|
|
848
|
-
port: parsePort(value),
|
|
849
|
-
};
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
export function isLocalDevelopmentTarget(
|
|
853
|
-
value: string | undefined,
|
|
854
|
-
): value is `${typeof LOCAL_PREFIX}${string}` {
|
|
855
|
-
return typeof value === "string" && value.startsWith(LOCAL_PREFIX);
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
export function resolveLocalDevelopmentPath(
|
|
859
|
-
value: string | undefined,
|
|
860
|
-
baseDir: string,
|
|
861
|
-
): string | null {
|
|
862
|
-
if (!isLocalDevelopmentTarget(value)) {
|
|
863
|
-
return null;
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
const localTarget = value.slice(LOCAL_PREFIX.length).trim();
|
|
867
|
-
return localTarget ? resolve(baseDir, localTarget) : null;
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
export function resolveDevelopmentHostUrl(value: string | undefined): string {
|
|
871
|
-
if (!value || isLocalDevelopmentTarget(value)) {
|
|
872
|
-
return `http://localhost:${DEFAULT_HOST_PORT}`;
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
return value.replace(/\/$/, "");
|
|
876
|
-
}
|
|
877
|
-
|
|
878
|
-
export function getHostDevelopmentPort(value: string | undefined): number {
|
|
879
|
-
return parsePort(resolveDevelopmentHostUrl(value));
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
export function parsePort(url: string): number {
|
|
883
|
-
try {
|
|
884
|
-
const parsed = new URL(url);
|
|
885
|
-
return parsed.port ? parseInt(parsed.port, 10) : parsed.protocol === "https:" ? 443 : 80;
|
|
886
|
-
} catch {
|
|
887
|
-
return 3000;
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
export { BOS_CONFIG_ORDER, rebuildOrderedConfig } from "./merge";
|
|
892
|
-
export type { BosConfig, RuntimeConfig } from "./types";
|
|
893
|
-
export { BosConfigSchema } from "./types";
|