UNPKG

everything-dev

Version:

A consolidated product package for building Module Federation apps with oRPC APIs.

1 lines • 75.1 kB
{"version":3,"file":"config.mjs","names":[],"sources":["../src/config.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { Effect, Schema } from \"effect\";\nimport { getProcessEnv } from \"./env/process-env\";\n\nconst warnOutsideEffect = (...args: unknown[]): void => {\n  console.warn(...args);\n};\n\nimport { sanitizeContainerName } from \"every-plugin/ui/manifest/contract\";\nimport { fetchApiPluginManifest } from \"./api-contract\";\nimport { manifestPluginsToNodes } from \"./dag\";\nimport { resolveApp, toConfigInput } from \"./descriptor/resolve\";\nimport { type AppDescriptor, AppDescriptorSchema } from \"./descriptor/schema\";\nimport { fetchBosConfigFromFastKv } from \"./fastkv\";\nimport { fetchJsonOrNull } from \"./http-client\";\nimport {\n  type BosEnv,\n  bosConfigMerger,\n  isPlainObject,\n  type ResolvedConfigMeta,\n  rebuildOrderedConfig,\n  resolveExtendsRef,\n} from \"./merge\";\nimport { getNetworkIdForAccount } from \"./network\";\nimport type {\n  BosConfig,\n  BosConfigInput,\n  BosPluginRef,\n  JsonObject,\n  JsonValue,\n  PluginEntryValue,\n  RuntimeConfig,\n  RuntimePluginConfig,\n} from \"./types\";\nimport { BosConfigSchema } from \"./types\";\nimport { type ResolvedSlotVersion, resolveSlotVersion } from \"./version-manifest-resolve\";\n\nconst LOCAL_PREFIX = \"local:\";\nconst DEFAULT_HOST_PORT = 3000;\nconst RESOLVED_CONFIG_FILENAME = \"bos.resolved-config.json\";\n\nexport const MISSING_CONFIG_MESSAGE = \"No config found (bos.app.ts or bos.config.json)\";\n\nexport const DEV_OVERLAY_FILENAME = \"bos.dev.ts\";\n\ntype RuntimeOverrideTarget = \"ui\" | \"api\" | \"plugins\" | `plugins.${string}`;\n\ninterface RuntimeTarget {\n  source: \"local\" | \"remote\";\n  url: string;\n  localPath?: string;\n  port?: number;\n}\n\ninterface ConfigWarningCapture {\n  sink: string[];\n  previous: ConfigWarningCapture | undefined;\n}\n\nconst warningCapture = new AsyncLocalStorage<ConfigWarningCapture | undefined>();\n\n/**\n * @internal — runs `fn` with config warnings captured into `sink` instead of\n * the console. Plumbing for the resolution session; not part of the public\n * config surface.\n */\nexport function runWithConfigWarningSink<T>(sink: string[], fn: () => T): T {\n  return warningCapture.run({ sink, previous: warningCapture.getStore() }, fn);\n}\n\nfunction emitConfigWarning(message: string): void {\n  const capture = warningCapture.getStore();\n  if (capture) {\n    capture.sink.push(message);\n  } else {\n    console.warn(message);\n  }\n}\n\nconst configPathCache = new Map<string, string | null>();\n\n/**\n * @internal — clears the findConfigPath memo. Plumbing for tests and the\n * resolution session; not part of the public config surface.\n */\nexport function resetConfigPathCache(): void {\n  configPathCache.clear();\n}\n\n/**\n * Reads the local authored config without resolving the extends chain or\n * touching the network — the build-surface factories (generated rsbuild\n * configs) consume it for their APP_NAME/APP_ACCOUNT defines.\n */\nexport async function readAuthoredConfigInput(cwd?: string): Promise<BosConfigInput | null> {\n  const configPath = findConfigPath(cwd);\n  if (!configPath || configPath.startsWith(\"bos://\")) return null;\n  return readConfigInput(configPath, dirname(configPath));\n}\n\n/**\n * The authored config entry inside exactly `dir` — no upward walk. Unlike\n * `findConfigPath` this never escapes the given directory, for write targets\n * and nested-local-path resolution where a parent's config must not be\n * picked up. Prefers the authored `bos.app.ts` descriptor (the canonical\n * form) over a legacy `bos.config.json`.\n */\nexport function localConfigEntryPath(dir: string): string | null {\n  const appPath = join(dir, \"bos.app.ts\");\n  if (existsSync(appPath)) return appPath;\n  const jsonPath = join(dir, \"bos.config.json\");\n  return existsSync(jsonPath) ? jsonPath : null;\n}\n\n/** `localConfigEntryPath` + the form-aware read (`BosConfigInput`). */\nexport async function readLocalAuthoredConfigInput(dir: string): Promise<BosConfigInput | null> {\n  const entry = localConfigEntryPath(dir);\n  if (!entry) return null;\n  return readConfigInput(entry, dirname(entry));\n}\n\n/**\n * The authored `bos.app.ts` descriptor is the canonical form — when both\n * forms coexist (e.g. a generated `bos.config.json` write-back beside the\n * authored descriptor), the authored file wins. JSON-form-only children are\n * unaffected: with no `bos.app.ts`, the JSON file is the entry.\n */\nexport function findConfigPath(cwd?: string): string | null {\n  const cacheKey = resolve(cwd ?? process.cwd());\n  const cached = configPathCache.get(cacheKey);\n  if (cached !== undefined) return cached;\n\n  let dir = cacheKey;\n  while (true) {\n    const appPath = join(dir, \"bos.app.ts\");\n    if (existsSync(appPath)) {\n      configPathCache.set(cacheKey, appPath);\n      return appPath;\n    }\n    const jsonPath = join(dir, \"bos.config.json\");\n    if (existsSync(jsonPath)) {\n      configPathCache.set(cacheKey, jsonPath);\n      return jsonPath;\n    }\n    const parent = dirname(dir);\n    if (parent === dir) break;\n    dir = parent;\n  }\n  configPathCache.set(cacheKey, null);\n  return null;\n}\n\nexport function isAppDescriptorPath(configPath: string): boolean {\n  return configPath.endsWith(\".app.ts\") || configPath.endsWith(\".app.js\");\n}\n\n/**\n * Materialize an authored bos.app.ts descriptor into the authoring-shape\n * `BosConfigInput` the config pipeline consumes. Import-extends is honored\n * two ways: the parent descriptor value can be imported directly (an\n * inlined parent, resolved through `resolveApp`), or `extends` can name a\n * published config (`bos://…`) / a local file, which flows into the JSON\n * extends chain unchanged.\n */\nexport async function loadAppDescriptorConfig(resolvedPath: string): Promise<BosConfigInput> {\n  // webpackIgnore: the path is inherently runtime-resolved — bundlers must\n  // not try to statically analyze it (rsbuild otherwise warns \"Critical\n  // dependency: the request of a dependency is an expression\").\n  const mod = (await import(/* webpackIgnore: true */ pathToFileURL(resolvedPath).href)) as Record<\n    string,\n    unknown\n  >;\n  return parseAppDescriptorModule(mod, resolvedPath);\n}\n\n/**\n * @internal — parses an already-imported app descriptor module into the\n * authoring-shape `BosConfigInput`. Plumbing for the resolution session's\n * injectable module loader; not part of the public config surface.\n */\nexport function parseAppDescriptorModule(\n  mod: Record<string, unknown>,\n  sourcePath?: string,\n): BosConfigInput {\n  if (!mod.default) {\n    throw new Error(\n      `${sourcePath ?? \"App descriptor module\"} must default-export an App() descriptor`,\n    );\n  }\n  const descriptor = AppDescriptorSchema.parse(mod.default);\n\n  // Registry candidates: named exports that parse as App descriptors.\n  const registry: Record<string, unknown> = {};\n  for (const value of Object.values(mod)) {\n    const parsed = AppDescriptorSchema.safeParse(value);\n    if (parsed.success) registry[parsed.data.name] = parsed.data;\n  }\n\n  const extendsRef = descriptor.extends;\n  const inRegistry = typeof extendsRef === \"string\" && registry[extendsRef] !== undefined;\n  const importedParent = extendsRef !== undefined && typeof extendsRef !== \"string\";\n\n  if (inRegistry || importedParent) {\n    return resolveApp(descriptor.name, registry as never);\n  }\n\n  const input = toConfigInput(descriptor);\n  if (extendsRef !== undefined) {\n    input.extends = extendsRef as BosConfigInput[\"extends\"];\n  }\n  return input;\n}\n\n/**\n * @internal — validates an already-imported `bos.dev.ts` module as a\n * `Partial<AppDescriptor>` dev overlay. Plumbing for the resolution session's\n * injectable module loader; not part of the public config surface.\n */\nexport function parseDevOverlayModule(\n  mod: Record<string, unknown>,\n  sourcePath?: string,\n): Partial<AppDescriptor> {\n  const source = sourcePath ?? DEV_OVERLAY_FILENAME;\n  if (!mod?.default) {\n    throw new DevOverlayError({\n      path: source,\n      message: `${source} must default-export a dev overlay (Partial<AppDescriptor>)`,\n    });\n  }\n  const parsed = AppDescriptorSchema.partial().safeParse(mod.default);\n  if (!parsed.success) {\n    throw new DevOverlayError({\n      path: source,\n      message: `${source} is not a valid dev overlay: ${parsed.error.message}`,\n      cause: parsed.error,\n    });\n  }\n  return parsed.data;\n}\n\nexport interface ResolvedComposableReference {\n  entry: BosPluginRef;\n  providerBaseDir: string;\n  targetPath: string;\n  associatedUi?: Record<string, unknown>;\n}\n\ninterface ParsedExtendsTarget {\n  configPath: string;\n  targetPath?: string;\n}\n\nexport class ConfigLoadError extends Schema.TaggedError<ConfigLoadError>()(\"ConfigLoadError\", {\n  path: Schema.String,\n  message: Schema.String,\n  cause: Schema.optional(Schema.Unknown),\n}) {}\n\nexport class CircularExtendsError extends Schema.TaggedError<CircularExtendsError>()(\n  \"CircularExtendsError\",\n  { chain: Schema.Array(Schema.String), message: Schema.String },\n) {}\n\nexport class ConfigNotfoundError extends Schema.TaggedError<ConfigNotfoundError>()(\n  \"ConfigNotfoundError\",\n  { message: Schema.String },\n) {}\n\nexport class ConfigExtendsError extends Schema.TaggedError<ConfigExtendsError>()(\n  \"ConfigExtendsError\",\n  {\n    message: Schema.String,\n    cause: Schema.optional(Schema.Unknown),\n  },\n) {}\n\nexport class ConfigVersionManifestError extends Schema.TaggedError<ConfigVersionManifestError>()(\n  \"ConfigVersionManifestError\",\n  {\n    message: Schema.String,\n    cause: Schema.optional(Schema.Unknown),\n  },\n) {}\n\nexport class DevOverlayError extends Schema.TaggedError<DevOverlayError>()(\"DevOverlayError\", {\n  path: Schema.String,\n  message: Schema.String,\n  cause: Schema.optional(Schema.Unknown),\n}) {}\n\nexport function defaultConfigEnv(): BosEnv {\n  return process.env.NODE_ENV === \"production\" ? \"production\" : \"development\";\n}\n\nexport function parseRuntimeOverrideTargets(value?: string | null): RuntimeOverrideTarget[] {\n  if (!value) {\n    return [];\n  }\n\n  return [\n    ...new Set(\n      value\n        .split(\",\")\n        .map((entry) => entry.trim())\n        .filter(Boolean),\n    ),\n  ].map((entry) => {\n    if (entry === \"ui\" || entry === \"api\" || entry === \"plugins\") {\n      return entry;\n    }\n\n    if (entry.startsWith(\"plugins.\") && entry.length > \"plugins.\".length) {\n      return entry as RuntimeOverrideTarget;\n    }\n\n    throw new ConfigExtendsError({ message: `Invalid runtime override target: ${entry}` });\n  });\n}\n\nexport function isRuntimeOverrideAllowed(\n  allowedTargets: ReadonlyArray<RuntimeOverrideTarget>,\n  target: \"ui\" | \"api\" | \"plugins\" | `plugins.${string}`,\n): boolean {\n  if (allowedTargets.includes(target as RuntimeOverrideTarget)) {\n    return true;\n  }\n\n  if (target.startsWith(\"plugins.\")) {\n    return allowedTargets.includes(\"plugins.*\");\n  }\n\n  return false;\n}\n\nexport async function buildRuntimePluginsForConfig(\n  config: BosConfig,\n  baseDir: string,\n  env: BosEnv,\n  remotePlugins?: string[],\n): Promise<Record<string, RuntimePluginConfig> | undefined> {\n  const plugins = await resolveRuntimePlugins(config.plugins ?? {}, baseDir, env, remotePlugins);\n  return Object.keys(plugins).length > 0 ? plugins : undefined;\n}\n\nfunction getEntryAssociatedUi(entry: Partial<BosPluginRef>): Record<string, unknown> | undefined {\n  const flat = isPlainObject(entry.ui) ? (entry.ui as Record<string, unknown>) : undefined;\n  const nested = (() => {\n    if (!isPlainObject(entry.app)) return undefined;\n    const app = entry.app as Record<string, unknown>;\n    return isPlainObject(app.ui) ? (app.ui as Record<string, unknown>) : undefined;\n  })();\n  const ui = flat ?? nested;\n  if (!ui) return undefined;\n\n  if (\"shared\" in ui) {\n    throw new ConfigExtendsError({\n      message:\n        \"app.ui.shared is no longer supported. Move shared deps to app.api.shared, app.auth.shared, or plugins.*.shared.\",\n    });\n  }\n\n  return ui;\n}\n\nfunction mergeAssociatedUi(\n  parentUi: Record<string, unknown> | undefined,\n  childUi: Record<string, unknown> | undefined,\n): Record<string, unknown> | undefined {\n  if (!parentUi) {\n    return childUi ? { ...childUi } : undefined;\n  }\n\n  if (!childUi) {\n    return { ...parentUi };\n  }\n\n  return bosConfigMerger({ ...childUi }, parentUi) as Record<string, unknown>;\n}\n\nfunction withAssociatedUi(\n  entry: BosPluginRef,\n  associatedUi?: Record<string, unknown>,\n): BosPluginRef {\n  if (!associatedUi) {\n    return entry;\n  }\n\n  const app = isPlainObject(entry.app)\n    ? ({ ...(entry.app as Record<string, unknown>) } as Record<string, unknown>)\n    : {};\n  app.ui = mergeAssociatedUi(getEntryAssociatedUi(entry), associatedUi);\n\n  return {\n    ...entry,\n    app,\n  };\n}\n\nexport async function resolveConfigComposableEntries(\n  config: BosConfig,\n  baseDir: string,\n  env: BosEnv,\n): Promise<BosConfig> {\n  const [resolvedApi, resolvedAuth] = await Promise.all([\n    resolveComposableReference(config.app.api as BosPluginRef, baseDir, env, \"app.api\"),\n    config.app.auth\n      ? resolveComposableReference(config.app.auth as BosPluginRef, baseDir, env, \"app.auth\")\n      : Promise.resolve(undefined),\n  ]);\n\n  const resolvedPlugins = config.plugins\n    ? Object.fromEntries(\n        await Promise.all(\n          Object.entries(config.plugins).map(async ([pluginId, pluginValue]) => {\n            const resolvedPlugin = await resolveComposableReference(\n              asComposableEntry(pluginValue),\n              baseDir,\n              env,\n              `plugins.${pluginId}`,\n            );\n\n            return [\n              pluginId,\n              withAssociatedUi(resolvedPlugin.entry, resolvedPlugin.associatedUi),\n            ] as const;\n          }),\n        ),\n      )\n    : undefined;\n\n  return {\n    ...config,\n    app: {\n      ...config.app,\n      api: resolvedApi.entry,\n      auth: resolvedAuth?.entry,\n    },\n    plugins: resolvedPlugins,\n  };\n}\n\nexport function getResolvedConfigPath(configDir: string): string {\n  return join(configDir, \".bos\", RESOLVED_CONFIG_FILENAME);\n}\n\nexport function loadGeneratedResolvedConfig(configDir: string): BosConfig | null {\n  const resolvedPath = getResolvedConfigPath(configDir);\n  if (!existsSync(resolvedPath)) return null;\n  try {\n    const raw = JSON.parse(readFileSync(resolvedPath, \"utf-8\"));\n    if (!isPlainObject(raw)) return null;\n    const { _resolved, ...configData } = raw;\n    return BosConfigSchema.parse(configData);\n  } catch {\n    return null;\n  }\n}\n\nexport function writeResolvedConfig(\n  configDir: string,\n  config: BosConfig,\n  env: BosEnv,\n  extendsChain?: string[],\n  source?: string,\n): void {\n  const resolvedPath = getResolvedConfigPath(configDir);\n  const resolvedDir = dirname(resolvedPath);\n  if (!existsSync(resolvedDir)) {\n    mkdirSync(resolvedDir, { recursive: true });\n  }\n\n  const ordered = rebuildOrderedConfig(config);\n  const meta: ResolvedConfigMeta = {\n    env,\n    resolvedAt: new Date().toISOString(),\n    extendsChain: extendsChain ?? [],\n    ...(source ? { source } : {}),\n  };\n  const output = {\n    _resolved: meta,\n    ...ordered,\n  };\n\n  const content = `${JSON.stringify(output, null, 2)}\\n`;\n  try {\n    if (readFileSync(resolvedPath, \"utf-8\") === content) return;\n  } catch {\n    // file doesn't exist yet\n  }\n  writeFileSync(resolvedPath, content);\n}\n\nexport function resolveBosConfigPath(configDir: string): string {\n  const resolvedPath = getResolvedConfigPath(configDir);\n  if (existsSync(resolvedPath)) return resolvedPath;\n  return join(configDir, \"bos.config.json\");\n}\n\nexport async function readBosConfigForBuild(configDir: string): Promise<Record<string, unknown>> {\n  const resolvedPath = getResolvedConfigPath(configDir);\n  if (existsSync(resolvedPath)) {\n    try {\n      const raw = JSON.parse(readFileSync(resolvedPath, \"utf-8\"));\n      if (isPlainObject(raw)) {\n        const { _resolved, ...configData } = raw;\n        return configData as Record<string, unknown>;\n      }\n    } catch (e) {\n      console.warn(\n        `[Config] Failed to parse _resolved.json, falling back to the authored config: ${String(e)}`,\n      );\n    }\n  }\n  // Form-aware fallback: the authored `bos.app.ts` descriptor is canonical —\n  // a TS-form child has no committed bos.config.json to parse.\n  const authored = await readLocalAuthoredConfigInput(configDir);\n  if (authored) return authored as unknown as Record<string, unknown>;\n  const bosConfigPath = join(configDir, \"bos.config.json\");\n  return JSON.parse(readFileSync(bosConfigPath, \"utf-8\")) as Record<string, unknown>;\n}\n\n/**\n * @internal — splits an extends ref into its config path and optional\n * `#target` suffix. Plumbing for the resolution session; not part of the\n * public config surface.\n */\nexport function parseExtendsTarget(ref: string): ParsedExtendsTarget {\n  const hashIndex = ref.indexOf(\"#\");\n  if (hashIndex === -1) {\n    return { configPath: ref };\n  }\n\n  const configPath = ref.slice(0, hashIndex);\n  const targetPath = ref.slice(hashIndex + 1);\n  return {\n    configPath,\n    targetPath: targetPath.length > 0 ? targetPath : undefined,\n  };\n}\n\n/**\n * @internal — resolves the base directory a config path extends from.\n * Plumbing for the resolution session; not part of the public config surface.\n */\nexport function getConfigBaseDir(configPath: string, baseDir: string): string {\n  if (configPath.startsWith(\"bos://\")) return baseDir;\n  return dirname(isAbsolute(configPath) ? configPath : resolve(baseDir, configPath));\n}\n\nfunction asComposableEntry(value: unknown): BosPluginRef {\n  if (value === undefined) {\n    return {};\n  }\n  if (typeof value === \"string\") {\n    return { extends: value };\n  }\n  if (!isPlainObject(value)) {\n    throw new ConfigExtendsError({\n      message: `Expected config entry object, received ${typeof value}`,\n    });\n  }\n  return value as BosPluginRef;\n}\n\nfunction getTargetedEntry(config: BosConfigInput, targetPath: string): BosPluginRef {\n  if (targetPath.startsWith(\"app.\")) {\n    const entryKey = targetPath.slice(\"app.\".length);\n    return asComposableEntry(config.app?.[entryKey]);\n  }\n\n  if (targetPath.startsWith(\"plugins.\")) {\n    const pluginId = targetPath.slice(\"plugins.\".length);\n    if (pluginId.length === 0) {\n      throw new ConfigExtendsError({ message: `Invalid plugin target path: ${targetPath}` });\n    }\n    return asComposableEntry(config.plugins?.[pluginId]);\n  }\n\n  throw new ConfigExtendsError({ message: `Unsupported extends target path: ${targetPath}` });\n}\n\nfunction getAssociatedUi(\n  config: BosConfigInput,\n  _targetPath: string,\n): Record<string, unknown> | undefined {\n  if (!isPlainObject(config.app?.ui)) {\n    return undefined;\n  }\n\n  const ui = config.app.ui as Record<string, unknown>;\n  if (\"shared\" in ui) {\n    throw new ConfigExtendsError({\n      message:\n        \"app.ui.shared is no longer supported. Move shared deps to app.api.shared, app.auth.shared, or plugins.*.shared.\",\n    });\n  }\n\n  return ui;\n}\n\nfunction applyNullOverrides(\n  target: Record<string, unknown>,\n  source: Record<string, unknown>,\n): void {\n  for (const [key, value] of Object.entries(source)) {\n    if (value === null) {\n      target[key] = null;\n    } else if (isPlainObject(value) && isPlainObject(target[key])) {\n      applyNullOverrides(target[key] as Record<string, unknown>, value as Record<string, unknown>);\n    }\n  }\n}\n\nfunction mergeComposableEntries(\n  parent: Partial<BosPluginRef>,\n  child: Partial<BosPluginRef>,\n): BosPluginRef {\n  const merged = bosConfigMerger({ ...child }, parent) as Record<string, unknown>;\n  applyNullOverrides(merged, child as Record<string, unknown>);\n  return merged as BosPluginRef;\n}\n\nfunction stripUnsafeLocalDevelopment<T extends Record<string, unknown> | undefined>(\n  entry: T,\n  allowLocalPaths: boolean,\n): T {\n  if (!entry || allowLocalPaths) {\n    return entry;\n  }\n\n  if (typeof entry.development === \"string\" && entry.development.startsWith(LOCAL_PREFIX)) {\n    const { development: _ignored, ...rest } = entry;\n    return rest as T;\n  }\n\n  return entry;\n}\n\nexport async function resolveComposableReference(\n  source: BosPluginRef,\n  baseDir: string,\n  env: BosEnv,\n  defaultTargetPath: string,\n): Promise<ResolvedComposableReference> {\n  let resolvedEntry: BosPluginRef = {};\n  let providerBaseDir = baseDir;\n  let targetPath = defaultTargetPath;\n  let associatedUi = getEntryAssociatedUi(source);\n  let allowLocalPaths = false;\n  let extendsError: unknown;\n\n  const extendsRef = source.extends ? resolveExtendsRef(source.extends, env) : undefined;\n  if (extendsRef) {\n    const { resolveMergedConfigInput } = await import(\"./resolution/session\");\n    const parsed = parseExtendsTarget(extendsRef);\n    targetPath = parsed.targetPath ?? defaultTargetPath;\n    const extendsBaseDir = getConfigBaseDir(parsed.configPath, baseDir);\n    try {\n      const extendedConfig = await resolveMergedConfigInput(parsed.configPath, {\n        baseDir: extendsBaseDir,\n        env,\n      });\n      resolvedEntry = mergeComposableEntries(\n        resolvedEntry,\n        getTargetedEntry(extendedConfig, targetPath),\n      );\n      providerBaseDir = extendsBaseDir;\n      associatedUi = mergeAssociatedUi(associatedUi, getAssociatedUi(extendedConfig, targetPath));\n    } catch (error) {\n      extendsError = error;\n    }\n  }\n\n  const localDevelopment =\n    typeof source.development === \"string\" && source.development.startsWith(LOCAL_PREFIX)\n      ? source.development\n      : undefined;\n  const localDevelopmentPath = localDevelopment\n    ? resolve(baseDir, localDevelopment.slice(LOCAL_PREFIX.length).trim())\n    : undefined;\n  const hasUsableLocalDevelopment = Boolean(\n    localDevelopmentPath && existsSync(localDevelopmentPath),\n  );\n\n  if (localDevelopmentPath) {\n    const { resolveMergedConfigInput } = await import(\"./resolution/session\");\n    const localPath = localDevelopmentPath;\n    const localConfigPath = localConfigEntryPath(localPath);\n    if (localConfigPath) {\n      const localConfig = await resolveMergedConfigInput(localConfigPath, {\n        baseDir: localPath,\n        env,\n      });\n      resolvedEntry = mergeComposableEntries(\n        resolvedEntry,\n        getTargetedEntry(localConfig, targetPath),\n      );\n      providerBaseDir = localPath;\n      associatedUi = mergeAssociatedUi(associatedUi, getAssociatedUi(localConfig, targetPath));\n      allowLocalPaths = true;\n    }\n  }\n\n  const sourceOverrides = { ...source };\n  if (allowLocalPaths && localDevelopment) {\n    delete sourceOverrides.development;\n  }\n\n  resolvedEntry = mergeComposableEntries(resolvedEntry, sourceOverrides);\n  associatedUi = mergeAssociatedUi(associatedUi, getEntryAssociatedUi(sourceOverrides));\n\n  if (extendsError && !allowLocalPaths && !hasUsableLocalDevelopment) {\n    throw extendsError;\n  }\n\n  return {\n    entry: stripUnsafeLocalDevelopment(resolvedEntry, allowLocalPaths || Boolean(localDevelopment)),\n    providerBaseDir,\n    targetPath,\n    // A plugin's own ui lives under its local development tree — the same\n    // safety argument as the entry itself: keep its local target when the\n    // plugin resolves locally, or the folder-form ui surface silently\n    // disappears (no BOS_UI_PORT, an unassigned ui dev server, and a\n    // port collision with another plugin's ui slot).\n    associatedUi: stripUnsafeLocalDevelopment(\n      associatedUi,\n      allowLocalPaths || Boolean(localDevelopment),\n    ),\n  };\n}\n\nfunction resolveDevelopmentTarget(\n  development: string | undefined,\n  production: string | undefined,\n  baseDir: string,\n  forceSource?: \"local\" | \"remote\",\n  target?: string,\n  extendsRef?: string,\n): RuntimeTarget {\n  if (forceSource === \"remote\") {\n    return resolveRuntimeTarget(production, baseDir, \"remote\");\n  }\n  if (!development) {\n    if (production && target) {\n      if (extendsRef) {\n        emitConfigWarning(`[Config] Resolving \"${target}\" from ${extendsRef}`);\n      } else {\n        emitConfigWarning(`[Config] No development target for \"${target}\", using production`);\n      }\n    }\n    return resolveRuntimeTarget(production, baseDir, \"remote\");\n  }\n  const devTarget = resolveRuntimeTarget(development, baseDir);\n  if (devTarget.source === \"local\" && (!devTarget.localPath || !existsSync(devTarget.localPath))) {\n    if (production && target) {\n      emitConfigWarning(`[Config] Could not load local target for \"${target}\", using production`);\n    }\n    return resolveRuntimeTarget(production, baseDir, \"remote\");\n  }\n  return devTarget;\n}\n\nexport interface BuildRuntimeConfigOptions {\n  plugins?: Record<string, RuntimePluginConfig>;\n  hostSource?: \"local\" | \"remote\";\n  uiSource?: \"local\" | \"remote\";\n  apiSource?: \"local\" | \"remote\";\n  authSource?: \"local\" | \"remote\";\n  proxy?: string;\n}\n\nexport const buildRuntimeConfigEffect = Effect.fn(\"buildRuntimeConfig\")(function* (\n  config: BosConfig,\n  baseDir: string,\n  env: BosEnv,\n  options?: BuildRuntimeConfigOptions,\n): Effect.fn.Return<RuntimeConfig, ConfigExtendsError | ConfigVersionManifestError> {\n  const uiConfig = config.app.ui;\n  const apiConfig = config.app.api;\n  const authConfig = config.app.auth;\n  const uiRuntime =\n    env === \"development\"\n      ? resolveDevelopmentTarget(\n          uiConfig.development,\n          uiConfig.production,\n          baseDir,\n          options?.uiSource,\n          \"app.ui\",\n        )\n      : resolveRuntimeTarget(uiConfig.production, baseDir, \"remote\");\n  const apiRuntime =\n    env === \"development\"\n      ? resolveDevelopmentTarget(\n          apiConfig.development,\n          apiConfig.production,\n          baseDir,\n          options?.apiSource,\n          \"app.api\",\n        )\n      : resolveRuntimeTarget(apiConfig.production, baseDir, \"remote\");\n  const authExtendsRef = authConfig?.extends\n    ? resolveExtendsRef(authConfig.extends, env)\n    : undefined;\n  const authRuntime = authConfig\n    ? env === \"development\"\n      ? resolveDevelopmentTarget(\n          authConfig.development,\n          authConfig.production,\n          baseDir,\n          options?.authSource,\n          \"app.auth\",\n          authExtendsRef,\n        )\n      : resolveRuntimeTarget(authConfig.production, baseDir, \"remote\")\n    : undefined;\n\n  const hostConfig = config.app.host;\n  const hostRuntime =\n    env === \"development\"\n      ? resolveDevelopmentTarget(\n          hostConfig.development,\n          hostConfig.production,\n          baseDir,\n          options?.hostSource,\n          \"app.host\",\n        )\n      : resolveRuntimeTarget(hostConfig.production, baseDir, \"remote\");\n\n  const hostListeningUrl =\n    env === \"development\"\n      ? resolveDevelopmentHostUrl(hostConfig.development)\n      : `http://localhost:${getProcessEnv(\"PORT\") ?? DEFAULT_HOST_PORT}`;\n\n  const hostIsRemote = hostRuntime.source === \"remote\";\n  const uiIsRemote = uiRuntime.source === \"remote\";\n  const apiIsRemote = apiRuntime.source === \"remote\";\n  const resolvedApiName = resolvePluginRuntimeName(apiConfig.name, apiRuntime.localPath, \"api\");\n\n  const authEntry = yield* Effect.tryPromise({\n    try: async () => {\n      if (!authConfig || !authRuntime) return undefined;\n      if (!authRuntime.localPath && !authRuntime.url) return undefined;\n      let authName = resolvePluginRuntimeName(authConfig.name, authRuntime.localPath, \"auth\");\n      if (\n        authRuntime.source === \"remote\" &&\n        authRuntime.url &&\n        !authRuntime.localPath &&\n        typeof authConfig.name !== \"string\"\n      ) {\n        authName = await resolveRemotePluginRuntimeName(authRuntime.url, authName);\n      }\n      return {\n        name: authName,\n        extendsRef: authExtendsRef,\n        url: authRuntime.url,\n        entry: authRuntime.url ? `${authRuntime.url}/mf-manifest.json` : \"/mf-manifest.json\",\n        localPath: authRuntime.localPath,\n        port: authRuntime.port,\n        source: authRuntime.source,\n        proxy: authConfig.proxy,\n        variables: authConfig.variables,\n        secrets: authConfig.secrets,\n        integrity: authRuntime.source === \"remote\" ? authConfig.integrity : undefined,\n        shared: authConfig.shared,\n        ui: buildRuntimeUiConfig(\n          \"auth\",\n          env,\n          getEntryAssociatedUi(authConfig as Partial<BosPluginRef>),\n          baseDir,\n          authName,\n          options?.authSource,\n        ),\n      };\n    },\n    catch: (cause) => new ConfigExtendsError({ message: String(cause), cause }),\n  });\n\n  const explicitPlugins =\n    options?.plugins && Object.keys(options.plugins).length > 0 ? options.plugins : undefined;\n  const runtimePlugins: Record<string, RuntimePluginConfig> = { ...explicitPlugins };\n  if (authEntry && !runtimePlugins.auth) {\n    runtimePlugins.auth = authEntry;\n  }\n\n  const result: RuntimeConfig = {\n    env,\n    account: config.account,\n    domain: config.domain,\n    title: config.title,\n    description: config.description,\n    networkId: getNetworkIdForAccount(config.account),\n    repository: config.repository,\n    host: {\n      name: \"host\",\n      url: hostListeningUrl,\n      entry: `${hostListeningUrl}/mf-manifest.json`,\n      localPath: hostRuntime.localPath,\n      port:\n        env === \"development\"\n          ? parsePort(hostListeningUrl)\n          : Number(getProcessEnv(\"PORT\")) || DEFAULT_HOST_PORT,\n      secrets: hostConfig.secrets,\n      integrity: hostIsRemote ? hostConfig.integrity : undefined,\n      source: hostRuntime.source,\n      remoteUrl: hostIsRemote ? hostRuntime.url : undefined,\n    },\n    ui: {\n      name: resolvePluginRuntimeName(uiConfig.name, uiRuntime.localPath, \"ui\"),\n      url: uiRuntime.url,\n      entry: uiRuntime.url ? `${uiRuntime.url}/mf-manifest.json` : \"/mf-manifest.json\",\n      publicUrl: typeof uiConfig.publicUrl === \"string\" ? uiConfig.publicUrl : undefined,\n      localPath: uiRuntime.localPath,\n      port: uiRuntime.port,\n      ssrUrl: uiIsRemote ? uiConfig.ssr : undefined,\n      ssrIntegrity: uiIsRemote ? uiConfig.ssrIntegrity : undefined,\n      integrity: uiIsRemote ? uiConfig.integrity : undefined,\n      source: uiRuntime.source,\n    },\n    api: {\n      name: resolvedApiName,\n      url: apiRuntime.url,\n      entry: apiRuntime.url ? `${apiRuntime.url}/mf-manifest.json` : \"/mf-manifest.json\",\n      localPath: apiRuntime.localPath,\n      port: apiRuntime.port,\n      source: apiRuntime.source,\n      proxy: options?.proxy ?? apiConfig.proxy,\n      variables: apiConfig.variables,\n      secrets: apiConfig.secrets,\n      integrity: apiIsRemote ? apiConfig.integrity : undefined,\n      shared: apiConfig.shared,\n      dependsOn: apiConfig.dependsOn ? normalizeStringArray(apiConfig.dependsOn) : undefined,\n    },\n    auth: authEntry,\n    plugins: Object.keys(runtimePlugins).length > 0 ? runtimePlugins : undefined,\n  };\n\n  yield* Effect.tryPromise({\n    try: async () => {\n      // catch-all diagnostics: a failed discovery fetch degrades to a\n      // warning, never fails the runtime config build\n      try {\n        if (result.api.source !== \"remote\" || !result.api.url) return;\n        const manifest = await fetchApiPluginManifest(result.api.url);\n        const manifestPluginEntries: Array<{ key: string; config: RuntimePluginConfig }> = [];\n        if (manifest.plugins?.length) {\n          for (const node of manifestPluginsToNodes(manifest.plugins)) {\n            if (!result.plugins?.[node.key]) {\n              manifestPluginEntries.push({\n                key: node.key,\n                config: {\n                  name: node.name,\n                  url: node.url,\n                  entry: node.entry,\n                  source: \"remote\",\n                  dependsOn: node.dependsOn,\n                  secrets: node.secrets,\n                  variables: node.variables,\n                },\n              });\n              if (node.secrets) {\n                for (const secretName of node.secrets) {\n                  if (!getProcessEnv(secretName)) {\n                    warnOutsideEffect(\n                      `[Config] Plugin \"${node.key}\" (discovered from manifest) expects secret \"${secretName}\" but it is not set in the environment.`,\n                    );\n                  }\n                }\n              }\n            }\n          }\n        }\n        if (manifest.dependsOn?.length) {\n          const existing = new Set(result.api.dependsOn ?? []);\n          for (const dep of manifest.dependsOn) {\n            if (!existing.has(dep)) {\n              result.api.dependsOn = [...(result.api.dependsOn ?? []), dep];\n            }\n          }\n        }\n        if (manifestPluginEntries.length > 0) {\n          if (!result.plugins) result.plugins = {};\n          for (const { key, config: pluginConfig } of manifestPluginEntries) {\n            if (!result.plugins[key]) {\n              result.plugins[key] = pluginConfig;\n            }\n          }\n        }\n      } catch (error) {\n        const message = error instanceof Error ? error.message : String(error);\n        warnOutsideEffect(`[Config] Failed to fetch API plugin manifest for discovery: ${message}`);\n      }\n    },\n    catch: (cause) => new ConfigExtendsError({ message: String(cause), cause }),\n  });\n\n  yield* Effect.tryPromise({\n    try: () => deriveVersionManifestFields(result, config, env),\n    catch: (cause) => new ConfigVersionManifestError({ message: String(cause), cause }),\n  });\n\n  return result;\n});\n\n/**\n * Version-manifest derivation (atomic-deploys 04): for every remote slot,\n * resolve its `pin` (fetch + SRI-verify the pinned manifest, process-cached\n * per pin) and stamp the derived entry-level fields — `entryUrl` (hashed\n * container entry), the browser-manifest `entry`, and entry-level\n * `integrity`/`ssrIntegrity`/`ssrEntryUrl` — so consumers load immutable\n * hashed bytes without knowing the pointer indirection.\n *\n * Hard break: outside development every remote slot MUST pin a version\n * manifest — an unpinned remote slot fails resolution loudly (the deploy\n * train pins every workspace it uploads; a manifest-less slot means a\n * pre-atomic-deploy config).\n */\nasync function deriveVersionManifestFields(\n  result: RuntimeConfig,\n  config: BosConfig,\n  env: BosEnv,\n): Promise<void> {\n  if (env === \"development\") return;\n\n  const derive = async (\n    label: string,\n    slotConfig: { pin?: unknown } | undefined,\n    slot: { url?: string; remoteUrl?: string; source?: string } | undefined,\n    apply: (resolved: ResolvedSlotVersion) => void,\n  ): Promise<void> => {\n    if (!slot || slot.source !== \"remote\" || !slot.url) return;\n    // A config without a production form (the image's baked boot fallback, or\n    // a dev resolution materialized under NODE_ENV=production) has no\n    // deployment artifacts to pin — the slot URL is the local listening\n    // fallback. Pin enforcement is for published configs.\n    const slotWithProduction = slotConfig as { production?: unknown } | undefined;\n    if (!slotWithProduction || slotWithProduction.production === undefined) return;\n    const rawPin = slotConfig?.pin as { manifest?: unknown; integrity?: unknown } | undefined;\n    const pin =\n      rawPin &&\n      typeof rawPin.manifest === \"string\" &&\n      rawPin.manifest &&\n      typeof rawPin.integrity === \"string\" &&\n      rawPin.integrity\n        ? { manifest: rawPin.manifest, integrity: rawPin.integrity }\n        : undefined;\n    if (!pin) {\n      throw new Error(\n        `slot \"${label}\" (${slot.url}) pins no version manifest — remote slots must pin ` +\n          `a version manifest outside development (pre-atomic-deploy config; redeploy required)`,\n      );\n    }\n    // The pin resolves against the slot's REMOTE base — the host slot's `url`\n    // is its own listening origin (the bytes it would serve don't exist\n    // there); its `remoteUrl` carries the deployment bundle base.\n    const resolved = await resolveSlotVersion({ base: slot.remoteUrl ?? slot.url, pin });\n    apply(resolved);\n  };\n\n  const applyUi = (ui: RuntimePluginConfig[\"ui\"], r: ResolvedSlotVersion): void => {\n    if (!ui) return;\n    ui.entryUrl = r.entryUrl;\n    ui.entry = r.browserManifestUrl ?? ui.entry;\n    ui.browserManifestUrl = r.browserManifestUrl;\n    ui.integrity = r.entryIntegrity;\n    ui.ssrEntryUrl = r.ssrEntryUrl;\n    ui.ssrIntegrity = r.ssrIntegrity ?? ui.ssrIntegrity;\n  };\n\n  await derive(\"app.host\", config.app.host, result.host, (r) => {\n    result.host.entryUrl = r.entryUrl;\n    result.host.integrity = r.entryIntegrity;\n  });\n  await derive(\"app.ui\", config.app.ui, result.ui, (r) => applyUi(result.ui, r));\n  await derive(\"app.api\", config.app.api, result.api, (r) => {\n    result.api.entryUrl = r.entryUrl;\n    result.api.integrity = r.entryIntegrity;\n  });\n  if (result.auth) {\n    await derive(\"app.auth\", config.app.auth, result.auth, (r) => {\n      result.auth!.entryUrl = r.entryUrl;\n      result.auth!.integrity = r.entryIntegrity;\n    });\n    await derive(\n      \"app.auth.ui\",\n      getEntryAssociatedUi(config.app.auth as Partial<BosPluginRef>),\n      result.auth.ui,\n      (r) => applyUi(result.auth!.ui, r),\n    );\n  }\n  for (const [key, plugin] of Object.entries(result.plugins ?? {})) {\n    let pluginConfig = config.plugins?.[key];\n    // The auth mirror (config.ts adds plugins.auth when the authored config\n    // has no plugins.auth entry) derives from the app.auth slot — it is the\n    // only compose surface for the auth ui, and its pins live on app.auth.\n    const isAuthMirror =\n      key === \"auth\" && result.auth && (plugin === result.auth || plugin.url === result.auth.url);\n    if ((!pluginConfig || typeof pluginConfig === \"string\") && isAuthMirror) {\n      pluginConfig = config.app.auth;\n    }\n    if (!pluginConfig || typeof pluginConfig === \"string\") continue;\n    await derive(`plugins.${key}`, pluginConfig, plugin, (r) => {\n      plugin.entryUrl = r.entryUrl;\n      plugin.integrity = r.entryIntegrity;\n    });\n    await derive(\n      `plugins.${key}.ui`,\n      getEntryAssociatedUi(pluginConfig as Partial<BosPluginRef>),\n      plugin.ui,\n      (r) => applyUi(plugin.ui, r),\n    );\n  }\n}\n\nexport async function buildRuntimeConfig(\n  config: BosConfig,\n  baseDir: string,\n  env: BosEnv,\n  options?: BuildRuntimeConfigOptions,\n): Promise<RuntimeConfig> {\n  return Effect.runPromise(buildRuntimeConfigEffect(config, baseDir, env, options));\n}\n\nasync function readConfigInput(configPath: string, baseDir: string): Promise<BosConfigInput> {\n  if (configPath.startsWith(\"bos://\")) {\n    return fetchBosConfigFromFastKv<BosConfigInput>(configPath);\n  }\n\n  const resolvedPath = isAbsolute(configPath) ? configPath : resolve(baseDir, configPath);\n  if (isAppDescriptorPath(resolvedPath)) {\n    return loadAppDescriptorConfig(resolvedPath);\n  }\n  return JSON.parse(readFileSync(resolvedPath, \"utf-8\")) as BosConfigInput;\n}\n\ntype PluginOverrideValue = PluginEntryValue | null | false;\n\nfunction normalizePluginEntry(raw: PluginOverrideValue): BosPluginRef | null | false {\n  if (raw === null || raw === false) return raw;\n  if (typeof raw === \"string\") {\n    return { extends: raw };\n  }\n  return raw;\n}\n\nconst resolveRuntimePluginsEffect = Effect.fn(\"resolveRuntimePlugins\")(function* (\n  plugins: Record<string, PluginOverrideValue>,\n  baseDir: string,\n  env: BosEnv,\n  remotePlugins?: string[],\n): Effect.fn.Return<Record<string, RuntimePluginConfig>, ConfigExtendsError> {\n  const entries = Object.entries(plugins)\n    .map(([pluginId, rawInput]) => ({\n      pluginId,\n      normalized: normalizePluginEntry(rawInput),\n    }))\n    .filter(\n      (entry): entry is { pluginId: string; normalized: BosPluginRef } =>\n        entry.normalized !== null && entry.normalized !== false,\n    );\n\n  const resolved = yield* Effect.forEach(\n    entries,\n    ({ pluginId, normalized }) =>\n      Effect.gen(function* () {\n        const resolvedReference = yield* Effect.tryPromise({\n          try: () => resolveComposableReference(normalized, baseDir, env, `plugins.${pluginId}`),\n          catch: (cause) => new ConfigExtendsError({ message: String(cause), cause }),\n        });\n\n        const forceSource =\n          remotePlugins === undefined\n            ? undefined\n            : remotePlugins.length === 0 || remotePlugins.includes(pluginId)\n              ? (\"remote\" as const)\n              : undefined;\n        const pluginRuntime = buildRuntimePluginConfig(\n          pluginId,\n          env,\n          resolvedReference,\n          forceSource,\n        );\n\n        if (!pluginRuntime.localPath && !pluginRuntime.url) {\n          if (forceSource === \"remote\") {\n            emitConfigWarning(\n              `[Config] Plugin \"${pluginId}\" has no production URL in bos.config.json and cannot be resolved as remote. Add a \"production\" field or remove it from --remote-plugins.`,\n            );\n          }\n          return null;\n        }\n\n        if (\n          pluginRuntime.source === \"remote\" &&\n          pluginRuntime.url &&\n          !pluginRuntime.localPath &&\n          typeof resolvedReference.entry.name !== \"string\"\n        ) {\n          pluginRuntime.name = yield* Effect.tryPromise({\n            try: () => resolveRemotePluginRuntimeName(pluginRuntime.url, pluginRuntime.name),\n            catch: (cause) => new ConfigExtendsError({ message: String(cause), cause }),\n          });\n        }\n\n        return [pluginId, pluginRuntime] as const;\n      }),\n    { concurrency: \"unbounded\" },\n  );\n\n  const out: Record<string, RuntimePluginConfig> = {};\n  for (const entry of resolved) {\n    if (entry) {\n      out[entry[0]] = entry[1];\n    }\n  }\n\n  return out;\n});\n\nfunction resolveRuntimePlugins(\n  plugins: Record<string, PluginOverrideValue>,\n  baseDir: string,\n  env: BosEnv,\n  remotePlugins?: string[],\n): Promise<Record<string, RuntimePluginConfig>> {\n  return Effect.runPromise(resolveRuntimePluginsEffect(plugins, baseDir, env, remotePlugins));\n}\n\nasync function resolveRemotePluginRuntimeName(baseUrl: string, fallback: string): Promise<string> {\n  const manifest = await fetchJsonOrNull<{\n    plugin?: { name?: unknown };\n  }>(`${baseUrl.replace(/\\/$/, \"\")}/plugin.manifest.json`, { retries: 2 });\n\n  return typeof manifest?.plugin?.name === \"string\" && manifest.plugin.name.length > 0\n    ? manifest.plugin.name\n    : fallback;\n}\n\nfunction buildRuntimePluginConfig(\n  pluginId: string,\n  env: BosEnv,\n  resolved: ResolvedComposableReference,\n  forceSource?: \"local\" | \"remote\",\n): RuntimePluginConfig {\n  const source = resolved.entry;\n  const development = typeof source.development === \"string\" ? source.development : undefined;\n  const production = typeof source.production === \"string\" ? source.production : undefined;\n\n  if (production?.startsWith(\"bos://\")) {\n    throw new ConfigExtendsError({\n      message: `Plugin \"${pluginId}\" has unsupported production target \"${production}\". Use extends: \"bos://account/domain\" for plugin configs or a CDN URL for production.`,\n    });\n  }\n\n  const pluginExtendsRef = source.extends ? resolveExtendsRef(source.extends, env) : undefined;\n\n  const runtimeTarget =\n    env === \"development\"\n      ? resolveDevelopmentTarget(\n          development,\n          production,\n          resolved.providerBaseDir,\n          forceSource,\n          `plugins.${pluginId}`,\n          pluginExtendsRef,\n        )\n      : resolveRuntimeTarget(production, resolved.providerBaseDir, \"remote\");\n  const apiName = resolvePluginRuntimeName(source.name, runtimeTarget.localPath, pluginId);\n\n  const ui = buildRuntimeUiConfig(\n    pluginId,\n    env,\n    resolved.associatedUi,\n    resolved.providerBaseDir,\n    apiName,\n    forceSource,\n  );\n\n  const routes = source.routes;\n\n  return {\n    name: apiName,\n    url: runtimeTarget.url,\n    entry: runtimeTarget.url\n      ? `${runtimeTarget.url.replace(/\\/$/, \"\")}/mf-manifest.json`\n      : \"/mf-manifest.json\",\n    source: runtimeTarget.source,\n    extendsRef: pluginExtendsRef,\n    localPath: runtimeTarget.localPath,\n    port: runtimeTarget.port,\n    proxy: typeof source.proxy === \"string\" ? source.proxy : undefined,\n    variables: normalizeJsonRecord(source.variables),\n    secrets: normalizeStringArray(source.secrets),\n    shared: source.shared,\n    connectSrc: normalizeStringArray(source.connectSrc),\n    integrity: runtimeTarget.source === \"remote\" ? source.integrity : undefined,\n    ui,\n    routes,\n    dependsOn: source.dependsOn ? normalizeStringArray(source.dependsOn) : undefined,\n  };\n}\n\n/**\n * Resolve a plugin entry's associated ui surface (`plugins.<id>.ui` / legacy\n * `plugins.<id>.app.ui`) into the runtime ui config. Extracted so app-slot\n * entries (app.auth) resolve their ui the same way.\n */\nfunction buildRuntimeUiConfig(\n  pluginId: string,\n  env: BosEnv,\n  uiConfig: Record<string, unknown> | undefined,\n  providerBaseDir: string,\n  apiName: string,\n  forceSource?: \"local\" | \"remote\",\n): RuntimePluginConfig[\"ui\"] {\n  const uiDevelopment =\n    typeof uiConfig?.development === \"string\" ? uiConfig.development : undefined;\n  const uiProduction = typeof uiConfig?.production === \"string\" ? uiConfig.production : undefined;\n  const uiRuntime =\n    uiConfig && (uiDevelopment || uiProduction)\n      ? env === \"development\"\n        ? resolveDevelopmentTarget(\n            uiDevelopment,\n            uiProduction,\n            providerBaseDir,\n            forceSource,\n            `plugins.${pluginId}.ui`,\n          )\n        : resolveRuntimeTarget(uiProduction, providerBaseDir, \"remote\")\n      : undefined;\n  if (!uiRuntime) return undefined;\n  // A remote ui target with no URL is not a deployable surface (e.g. a\n  // plugin ui entry with only a development key) — dropping it here keeps\n  // the phantom source out of runtime resolution and client payloads.\n  if (uiRuntime.source === \"remote\" && !uiRuntime.url) return undefined;\n\n  return {\n    name: resolveUiRuntimeName(uiConfig, uiRuntime.localPath, apiName),\n    url: uiRuntime.url,\n    entry: uiRuntime.url\n      ? `${uiRuntime.url.replace(/\\/$/, \"\")}/mf-manifest.json`\n      : \"/mf-manifest.json\",\n    source: uiRuntime.source,\n    publicUrl: typeof uiConfig?.publicUrl === \"string\" ? uiConfig.publicUrl : undefined,\n    localPath: uiRuntime.localPath,\n    port: uiRuntime.port,\n    integrity:\n      uiRuntime.source === \"remote\" && typeof uiConfig?.integrity === \"string\"\n        ? uiConfig.integrity\n        : undefined,\n    ssrUrl:\n      uiRuntime.source === \"remote\" && typeof uiConfig?.ssr === \"string\"\n        ? uiConfig.ssr\n        : uiRuntime.source === \"local\"\n          ? uiRuntime.url\n          : undefined,\n    ssrIntegrity:\n      uiRuntime.source === \"remote\" && typeof uiConfig?.ssrIntegrity === \"string\"\n        ? uiConfig.ssrIntegrity\n        : undefined,\n  };\n}\n\n/**\n * MF container identity must match the build: folder-form plugin ui sources\n * build under the sanitized plugin workspace package name (the generated\n * rsbuild config imports the plugin's package.json), so derive the same\n * value here — an authored `ui.name` is only a fallback, and can never\n * override what the container actually registers under.\n */\nexport function resolveUiRuntimeName(\n  uiConfig: Record<string, unknown> | undefined,\n  localPath: string | undefined,\n  apiName: string,\n): string {\n  if (localPath) {\n    const uiPkgPath = join(localPath, \"package.json\");\n    const pkgPath = existsSync(uiPkgPath) ? uiPkgPath : join(dirname(localPath), \"package.json\");\n    try {\n      const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as { name?: unknown };\n      if (typeof pkg.name === \"string\" && pkg.name.length > 0) {\n        return sanitizeContainerName(pkg.name);\n      }\n    } catch (e) {\n      console.warn(`[Config] Could not read package.json at ${pkgPath}: ${String(e)}`);\n    }\n  }\n  return typeof uiConfig?.name === \"string\" ? uiConfig.name : `${apiName}-ui`;\n}\n\nexport function resolvePluginRuntimeName(\n  explicitName: string | undefined,\n  localPath: string | undefined,\n  fallback: string,\n): string {\n  if (explicitName) {\n    return explicitName;\n  }\n\n  if (!localPath) {\n    return fallback;\n  }\n\n  try {\n    const packageJsonPath = join(localPath, \"package.json\");\n    const packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\")) as { name?: unknown };\n    if (typeof packageJson.name === \"string\" && packageJson.name.length > 0) {\n      return packageJson.name;\n    }\n  } catch (e) {\n    console.warn(`[Config] Could not read package.json at ${localPath}: ${String(e)}`);\n  }\n\n  return fallback;\n}\n\nfunction normalizeJsonValue(value: unknown): JsonValue | undefined {\n  if (\n    value === null ||\n    typeof value === \"string\" ||\n    typeof value === \"number\" ||\n    typeof value === \"boolean\"\n  ) {\n    return value;\n  }\n\n  if (Array.isArray(value)) {\n    return value\n      .map((item) => normalizeJsonValue(item))\n      .filter((item): item is JsonValue => item !== undefined);\n  }\n\n  if (isPlainObject(value)) {\n    const out: JsonObject = {};\n    for (const [key, raw] of Object.entries(value)) {\n      const normalized = normalizeJsonValue(raw);\n      if (normalized !== undefined) {\n        out[key] = normalized;\n      }\n    }\n    return out;\n  }\n\n  return undefined;\n}\n\nfunction normalizeJsonRecord(value: unknown): JsonObject | undefined {\n  if (!isPlainObject(value)) return undefined;\n  const out: JsonObject = {};\n  for (const [key, raw] of Object.entries(value)) {\n    const normalized = normalizeJsonValue(raw);\n    if (normalized !== undefined) {\n      out[key] = normalized;\n    }\n  }\n  return Object.keys(out).length > 0 ? out : undefined;\n}\n\nfunction normalizeStringArray(value: unknown): string[] | undefined {\n  if (!Array.isArray(value)) return undefined;\n  const out = value.filter((item): item is string => typeof item === \"string\" && item.length > 0);\n  return out.length > 0 ? out : undefined;\n}\n\nfunction resolveRuntimeTarget(\n  value: string | undefined,\n  baseDir: string,\n  defaultSource: \"local\" | \"remote\" = \"remote\",\n): RuntimeTarget {\n  if (!value) {\n    return { source: defaultSource, url: \"\" };\n  }\n\n  if (value.startsWith(LOCAL_PREFIX)) {\n    const localTarget = value?.slice(LOCAL_PREFIX.length).trim();\n    if (!localTarget) {\n      throw new ConfigExtendsError({ message: `Invalid local development target: ${value}` });\n    }\n\n    const localPath = resolve(baseDir, localTarget);\n    if (!existsSync(localPath)) {\n      return { source: \"local\", url: \"\" };\n    }\n\n    return {\n      source: \"local\",\n      url: \"\",\n      localPath,\n    };\n  }\n\n  return {\n    source: defaultSource,\n    url: value.replace(/\\/$/, \"\"),\n    port: parsePort(value),\n  };\n}\n\nexport function isLocalDevelopmentTarget(\n  value: string | undefined,\n): value is `${typeof LOCAL_PREFIX}${string}` {\n  return typeof value === \"string\" && value.startsWith(LOCAL_PREFIX);\n}\n\nexport function resolveLocalDevelopmentPath(\n  value: string | undefined,\n  baseDir: string,\n): string | null {\n  if (!isLocalDevelopmentTarget(value)) {\n    return null;\n  }\n\n  const localTarget = value.slice(LOCAL_PREFIX.length).trim();\n  return localTarget ? resolve(baseDir, localTarget) : null;\n}\n\nexport function resolveDevelopmentHostUrl(value: string | undefined): string {\n  if (!value || isLocalDevelopmentTarget(value)) {\n    return `http://localhost:${DEFAULT_HOST_PORT}`;\n  }\n\n  return value.replace(/\\/$/, \"\");\n}\n\nexport function getHostDevelopmentPort(value: string | undefined): number {\n  return parsePort(resolveDevelopmentHostUrl(value));\n}\n\nexport function parsePort(url: string): number {\n  try {\n    const parsed = new URL(url);\n    return parsed.port ? parseInt(parsed.port, 10) : parsed.protocol === \"https:\" ? 443 : 80;\n  } catch {\n    return 3000;\n  }\n}\n\nexport type { BosEnv } from \"./merge\";\nexport {\n  BOS_CONFIG_ORDER,\n  mergeBosConfigWithExtends,\n  rebuildOrderedConfig,\n  resolveExtendsRef,\n} from \"./merge\";\nexport type { BosConfig, RuntimeConfig } from \"./types\";\nexport { BosConfigSchema } from \"./types\";\n"],"mappings":"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"}