everything-dev
Version:
A consolidated product package for building Module Federation apps with oRPC APIs.
1 lines • 52.3 kB
Source Map (JSON)
{"version":3,"file":"config.cjs","names":["BosConfigSchema","isPlainObject","bosConfigMerger","rebuildOrderedConfig","resolveExtendsRef","getNetworkIdForAccount","fetchBosConfigFromFastKv","mergeBosConfigWithExtends","fetchJsonOrNull"],"sources":["../src/config.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, resolve } from \"node:path\";\nimport { fetchBosConfigFromFastKv } from \"./fastkv\";\nimport { fetchJsonOrNull } from \"./http-client\";\nimport {\n type BosEnv,\n bosConfigMerger,\n isPlainObject,\n mergeBosConfigWithExtends,\n type ResolvedConfigMeta,\n rebuildOrderedConfig,\n resolveExtendsRef,\n} from \"./merge\";\nimport { getNetworkIdForAccount } from \"./network\";\nimport type {\n BosConfig,\n BosConfigInput,\n BosPluginRef,\n ExtendsConfig,\n JsonObject,\n JsonValue,\n PluginEntryValue,\n RuntimeConfig,\n RuntimePluginConfig,\n} from \"./types\";\nimport { BosConfigSchema } from \"./types\";\n\nconst LOCAL_PREFIX = \"local:\";\nconst DEFAULT_HOST_PORT = 3000;\nconst RESOLVED_CONFIG_FILENAME = \"bos.resolved-config.json\";\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\nlet cachedConfig: BosConfig | null = null;\nlet projectRoot: string | null = null;\nlet configWarnings: string[] = [];\nlet suppressConfigWarnings = false;\n\nexport function clearConfigCache(): void {\n cachedConfig = null;\n projectRoot = null;\n configWarnings = [];\n}\n\nexport function suppressWarnings(): void {\n suppressConfigWarnings = true;\n}\n\nexport function resumeWarnings(): void {\n suppressConfigWarnings = false;\n}\n\nexport function drainConfigWarnings(): string[] {\n const warnings = [...configWarnings];\n configWarnings = [];\n return warnings;\n}\n\nfunction emitConfigWarning(message: string): void {\n if (suppressConfigWarnings) {\n configWarnings.push(message);\n } else {\n console.warn(message);\n }\n}\n\nconst configPathCache = new Map<string, string | null>();\n\nexport function findConfigPath(cwd?: string): string | null {\n const cacheKey = cwd ?? process.cwd();\n const cached = configPathCache.get(cacheKey);\n if (cached !== undefined) return cached;\n\n let dir = cacheKey;\n while (dir !== \"/\") {\n const configPath = join(dir, \"bos.config.json\");\n if (existsSync(configPath)) {\n configPathCache.set(cacheKey, configPath);\n return configPath;\n }\n dir = dirname(dir);\n }\n configPathCache.set(cacheKey, null);\n return null;\n}\n\nexport function getConfig(): BosConfig | null {\n return cachedConfig;\n}\n\nexport function getProjectRoot(): string {\n if (!projectRoot) {\n throw new Error(\"Config not loaded. Call loadResolvedConfig() first.\");\n }\n return projectRoot;\n}\n\nexport interface ConfigResult {\n config: BosConfig;\n runtime: RuntimeConfig;\n source: {\n path: string;\n extended?: string[];\n remote?: boolean;\n };\n warnings?: string[];\n}\n\nexport interface LocalConfigResult {\n config: BosConfigInput;\n source: {\n path: string;\n };\n}\n\nexport interface RemoteConfigResult {\n rawConfig: BosConfigInput;\n config: BosConfig;\n source: string;\n extendsChain: string[];\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 async function loadLocalConfig(options?: {\n cwd?: string;\n path?: string;\n}): Promise<LocalConfigResult | null> {\n const configPath = options?.path ?? findConfigPath(options?.cwd);\n if (!configPath) {\n projectRoot = options?.cwd ?? process.cwd();\n return null;\n }\n\n const baseDir = dirname(configPath);\n const config = await loadConfigFile(configPath, baseDir);\n\n projectRoot = baseDir;\n\n return {\n config,\n source: {\n path: configPath,\n },\n };\n}\n\nexport async function loadResolvedConfig(options?: {\n cwd?: string;\n path?: string;\n env?: BosEnv;\n remotePlugins?: string[];\n}): Promise<ConfigResult | null> {\n const configPath = options?.path ?? findConfigPath(options?.cwd);\n if (!configPath) {\n projectRoot = options?.cwd ?? process.cwd();\n return null;\n }\n\n const baseDir = dirname(configPath);\n const env = options?.env ?? \"development\";\n const runtimeEnv: BosEnv = env === \"staging\" ? \"production\" : env;\n\n try {\n suppressWarnings();\n const extendedChain: string[] = [];\n const parsed = await resolveConfigWithExtends(\n configPath,\n baseDir,\n new Set(),\n extendedChain,\n env,\n );\n const config = await resolveConfigComposableEntries(\n BosConfigSchema.parse(parsed),\n baseDir,\n runtimeEnv,\n );\n\n cachedConfig = config;\n projectRoot = baseDir;\n\n const pluginRuntime = await resolveRuntimePlugins(\n config.plugins ?? {},\n baseDir,\n runtimeEnv,\n options?.remotePlugins,\n );\n const runtime = buildRuntimeConfig(config, baseDir, runtimeEnv, {\n plugins: pluginRuntime,\n });\n const warnings = drainConfigWarnings();\n resumeWarnings();\n\n return {\n config,\n runtime,\n source: {\n path: configPath,\n extended: extendedChain.length > 0 ? extendedChain : undefined,\n remote: extendedChain.some((entry) => entry.startsWith(\"bos://\")),\n },\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n } catch (error) {\n resumeWarnings();\n if (error instanceof Error) {\n throw new Error(`Failed to load config from ${configPath}: ${error.message}`, {\n cause: error,\n });\n }\n throw new Error(`Failed to load config from ${configPath}: ${String(error)}`);\n }\n}\n\nexport async function loadBosConfig(options?: {\n cwd?: string;\n path?: string;\n env?: BosEnv;\n}): Promise<RuntimeConfig> {\n const result = await loadResolvedConfig(options);\n if (!result) {\n throw new Error(\"No bos.config.json found\");\n }\n\n return result.runtime;\n}\n\nexport async function loadRemoteConfig(\n bosUrl: string,\n env: BosEnv = \"production\",\n): Promise<RemoteConfigResult> {\n const runtimeEnv: BosEnv = env === \"staging\" ? \"production\" : env;\n const extendedChain: string[] = [];\n const parsed = await resolveConfigWithExtends(\n bosUrl,\n process.cwd(),\n new Set(),\n extendedChain,\n env,\n );\n const config = await resolveConfigComposableEntries(\n BosConfigSchema.parse(parsed),\n process.cwd(),\n runtimeEnv,\n );\n\n return {\n rawConfig: await loadConfigFile(bosUrl, process.cwd()),\n config,\n source: bosUrl,\n extendsChain: extendedChain,\n };\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 Error(`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): Promise<Record<string, RuntimePluginConfig> | undefined> {\n const plugins = await resolveRuntimePlugins(config.plugins ?? {}, baseDir, env);\n return Object.keys(plugins).length > 0 ? plugins : undefined;\n}\n\nfunction getEntryAssociatedUi(entry: Partial<BosPluginRef>): Record<string, unknown> | undefined {\n if (!isPlainObject(entry.app)) {\n return undefined;\n }\n\n const app = entry.app as Record<string, unknown>;\n if (!isPlainObject(app.ui)) {\n return undefined;\n }\n\n const ui = app.ui as Record<string, unknown>;\n if (\"shared\" in ui) {\n throw new Error(\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 function readBosConfigForBuild(configDir: string): 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 bos.config.json: ${e}`,\n );\n }\n }\n const bosConfigPath = join(configDir, \"bos.config.json\");\n return JSON.parse(readFileSync(bosConfigPath, \"utf-8\")) as Record<string, unknown>;\n}\n\nfunction 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\nfunction 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 Error(`Expected config entry object, received ${typeof value}`);\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 Error(`Invalid plugin target path: ${targetPath}`);\n }\n return asComposableEntry(config.plugins?.[pluginId]);\n }\n\n throw new Error(`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 Error(\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 mergeComposableEntries(\n parent: Partial<BosPluginRef>,\n child: Partial<BosPluginRef>,\n): BosPluginRef {\n return bosConfigMerger({ ...child }, parent) 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 parsed = parseExtendsTarget(extendsRef);\n targetPath = parsed.targetPath ?? defaultTargetPath;\n const extendsBaseDir = getConfigBaseDir(parsed.configPath, baseDir);\n try {\n const extendedConfig = await resolveConfigWithExtends(\n parsed.configPath,\n extendsBaseDir,\n new Set(),\n [],\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 localPath = localDevelopmentPath;\n const localConfigPath = join(localPath, \"bos.config.json\");\n if (existsSync(localConfigPath)) {\n const localConfig = await resolveConfigWithExtends(\n localConfigPath,\n localPath,\n new Set(),\n [],\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 associatedUi: stripUnsafeLocalDevelopment(associatedUi, allowLocalPaths),\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 function buildRuntimeConfig(\n config: BosConfig,\n baseDir: string,\n env: BosEnv,\n options?: BuildRuntimeConfigOptions,\n): RuntimeConfig {\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:${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 return {\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: env === \"development\" ? parsePort(hostListeningUrl) : 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 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 },\n auth: (() => {\n if (!authConfig || !authRuntime) return undefined;\n if (!authRuntime.localPath && !authRuntime.url) return undefined;\n return {\n name: resolvePluginRuntimeName(authConfig.name, authRuntime.localPath, \"auth\"),\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 };\n })(),\n plugins:\n options?.plugins && Object.keys(options.plugins).length > 0 ? options.plugins : undefined,\n };\n}\n\nasync function loadConfigFile(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 return JSON.parse(readFileSync(resolvedPath, \"utf-8\")) as BosConfigInput;\n}\n\nasync function resolveConfigWithExtends(\n configPath: string,\n baseDir: string,\n visited: Set<string>,\n chain: string[],\n env: BosEnv = \"development\",\n): Promise<BosConfigInput> {\n if (visited.has(configPath)) {\n throw new Error(`Circular extends detected: ${[...visited, configPath].join(\" -> \")}`);\n }\n\n const config = await loadConfigFile(configPath, baseDir);\n chain.push(configPath);\n\n if (!config.extends) {\n return config;\n }\n\n const extendsRef = resolveExtendsRef(config.extends as string | ExtendsConfig, env);\n if (!extendsRef) {\n return config;\n }\n\n const parsedParentRef = parseExtendsTarget(extendsRef);\n\n const nextVisited = new Set(visited);\n nextVisited.add(configPath);\n const parentBaseDir = getConfigBaseDir(parsedParentRef.configPath, baseDir);\n const parent = await resolveConfigWithExtends(\n parsedParentRef.configPath,\n parentBaseDir,\n nextVisited,\n chain,\n env,\n );\n\n return mergeBosConfigWithExtends(parent, config);\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\nasync function resolveRuntimePlugins(\n plugins: Record<string, PluginOverrideValue>,\n baseDir: string,\n env: BosEnv,\n remotePlugins?: string[],\n): Promise<Record<string, RuntimePluginConfig>> {\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 = await Promise.all(\n entries.map(async ({ pluginId, normalized }) => {\n const resolvedReference = await resolveComposableReference(\n normalized,\n baseDir,\n env,\n `plugins.${pluginId}`,\n );\n\n const forceSource =\n remotePlugins === undefined\n ? undefined\n : remotePlugins.length === 0 || remotePlugins.includes(pluginId)\n ? \"remote\"\n : undefined;\n const pluginRuntime = buildRuntimePluginConfig(pluginId, env, resolvedReference, forceSource);\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 = await resolveRemotePluginRuntimeName(\n pluginRuntime.url,\n pluginRuntime.name,\n );\n }\n\n return [pluginId, pluginRuntime] as const;\n }),\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\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: 0 });\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 Error(\n `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 uiConfig = resolved.associatedUi;\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 resolved.providerBaseDir,\n forceSource,\n `plugins.${pluginId}.ui`,\n )\n : resolveRuntimeTarget(uiProduction, resolved.providerBaseDir, \"remote\")\n : undefined;\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 integrity: runtimeTarget.source === \"remote\" ? source.integrity : undefined,\n ui: uiRuntime\n ? {\n name: typeof uiConfig?.name === \"string\" ? uiConfig.name : `${apiName}-ui`,\n url: uiRuntime.url,\n entry: uiRuntime.url\n ? `${uiRuntime.url.replace(/\\/$/, \"\")}/mf-manifest.json`\n : \"/mf-manifest.json\",\n source: uiRuntime.source,\n localPath: uiRuntime.localPath,\n port: uiRuntime.port,\n integrity:\n uiRuntime.source === \"remote\" && typeof uiConfig?.integrity === \"string\"\n ? uiConfig.integrity\n : undefined,\n }\n : undefined,\n routes,\n };\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}: ${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 Error(`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 {\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":";;;;;;;;;;AA2BA,MAAM,eAAe;AACrB,MAAM,oBAAoB;AAC1B,MAAM,2BAA2B;AAWjC,IAAI,eAAiC;AACrC,IAAI,cAA6B;AACjC,IAAI,iBAA2B,CAAC;AAChC,IAAI,yBAAyB;AAE7B,SAAgB,mBAAyB;CACvC,eAAe;CACf,cAAc;CACd,iBAAiB,CAAC;AACpB;AAEA,SAAgB,mBAAyB;CACvC,yBAAyB;AAC3B;AAEA,SAAgB,iBAAuB;CACrC,yBAAyB;AAC3B;AAEA,SAAgB,sBAAgC;CAC9C,MAAM,WAAW,CAAC,GAAG,cAAc;CACnC,iBAAiB,CAAC;CAClB,OAAO;AACT;AAEA,SAAS,kBAAkB,SAAuB;CAChD,IAAI,wBACF,eAAe,KAAK,OAAO;MAE3B,QAAQ,KAAK,OAAO;AAExB;AAEA,MAAM,kCAAkB,IAAI,IAA2B;AAEvD,SAAgB,eAAe,KAA6B;CAC1D,MAAM,WAAW,OAAO,QAAQ,IAAI;CACpC,MAAM,SAAS,gBAAgB,IAAI,QAAQ;CAC3C,IAAI,WAAW,QAAW,OAAO;CAEjC,IAAI,MAAM;CACV,OAAO,QAAQ,KAAK;EAClB,MAAM,iCAAkB,KAAK,iBAAiB;EAC9C,4BAAe,UAAU,GAAG;GAC1B,gBAAgB,IAAI,UAAU,UAAU;GACxC,OAAO;EACT;EACA,6BAAc,GAAG;CACnB;CACA,gBAAgB,IAAI,UAAU,IAAI;CAClC,OAAO;AACT;AAEA,SAAgB,YAA8B;CAC5C,OAAO;AACT;AAEA,SAAgB,iBAAyB;CACvC,IAAI,CAAC,aACH,MAAM,IAAI,MAAM,qDAAqD;CAEvE,OAAO;AACT;AAuCA,eAAsB,gBAAgB,SAGA;CACpC,MAAM,aAAa,SAAS,QAAQ,eAAe,SAAS,GAAG;CAC/D,IAAI,CAAC,YAAY;EACf,cAAc,SAAS,OAAO,QAAQ,IAAI;EAC1C,OAAO;CACT;CAEA,MAAM,iCAAkB,UAAU;CAClC,MAAM,SAAS,MAAM,eAAe,YAAY,OAAO;CAEvD,cAAc;CAEd,OAAO;EACL;EACA,QAAQ,EACN,MAAM,WACR;CACF;AACF;AAEA,eAAsB,mBAAmB,SAKR;CAC/B,MAAM,aAAa,SAAS,QAAQ,eAAe,SAAS,GAAG;CAC/D,IAAI,CAAC,YAAY;EACf,cAAc,SAAS,OAAO,QAAQ,IAAI;EAC1C,OAAO;CACT;CAEA,MAAM,iCAAkB,UAAU;CAClC,MAAM,MAAM,SAAS,OAAO;CAC5B,MAAM,aAAqB,QAAQ,YAAY,eAAe;CAE9D,IAAI;EACF,iBAAiB;EACjB,MAAM,gBAA0B,CAAC;EACjC,MAAM,SAAS,MAAM,yBACnB,YACA,yBACA,IAAI,IAAI,GACR,eACA,GACF;EACA,MAAM,SAAS,MAAM,+BACnBA,8BAAgB,MAAM,MAAM,GAC5B,SACA,UACF;EAEA,eAAe;EACf,cAAc;EAQd,MAAM,UAAU,mBAAmB,QAAQ,SAAS,YAAY,EAC9D,SAAS,MAPiB,sBAC1B,OAAO,WAAW,CAAC,GACnB,SACA,YACA,SAAS,aACX,EAGA,CAAC;EACD,MAAM,WAAW,oBAAoB;EACrC,eAAe;EAEf,OAAO;GACL;GACA;GACA,QAAQ;IACN,MAAM;IACN,UAAU,cAAc,SAAS,IAAI,gBAAgB;IACrD,QAAQ,cAAc,MAAM,UAAU,MAAM,WAAW,QAAQ,CAAC;GAClE;GACA,UAAU,SAAS,SAAS,IAAI,WAAW;EAC7C;CACF,SAAS,OAAO;EACd,eAAe;EACf,IAAI,iBAAiB,OACnB,MAAM,IAAI,MAAM,8BAA8B,WAAW,IAAI,MAAM,WAAW,EAC5E,OAAO,MACT,CAAC;EAEH,MAAM,IAAI,MAAM,8BAA8B,WAAW,IAAI,OAAO,KAAK,GAAG;CAC9E;AACF;AAEA,eAAsB,cAAc,SAIT;CACzB,MAAM,SAAS,MAAM,mBAAmB,OAAO;CAC/C,IAAI,CAAC,QACH,MAAM,IAAI,MAAM,0BAA0B;CAG5C,OAAO,OAAO;AAChB;AAEA,eAAsB,iBACpB,QACA,MAAc,cACe;CAC7B,MAAM,aAAqB,QAAQ,YAAY,eAAe;CAC9D,MAAM,gBAA0B,CAAC;CACjC,MAAM,SAAS,MAAM,yBACnB,QACA,QAAQ,IAAI,mBACZ,IAAI,IAAI,GACR,eACA,GACF;CACA,MAAM,SAAS,MAAM,+BACnBA,8BAAgB,MAAM,MAAM,GAC5B,QAAQ,IAAI,GACZ,UACF;CAEA,OAAO;EACL,WAAW,MAAM,eAAe,QAAQ,QAAQ,IAAI,CAAC;EACrD;EACA,QAAQ;EACR,cAAc;CAChB;AACF;AAEA,SAAgB,4BAA4B,OAAgD;CAC1F,IAAI,CAAC,OACH,OAAO,CAAC;CAGV,OAAO,CACL,GAAG,IAAI,IACL,MACG,MAAM,GAAG,CAAC,CACV,KAAK,UAAU,MAAM,KAAK,CAAC,CAAC,CAC5B,OAAO,OAAO,CACnB,CACF,CAAC,CAAC,KAAK,UAAU;EACf,IAAI,UAAU,QAAQ,UAAU,SAAS,UAAU,WACjD,OAAO;EAGT,IAAI,MAAM,WAAW,UAAU,KAAK,MAAM,SAAS,GACjD,OAAO;EAGT,MAAM,IAAI,MAAM,oCAAoC,OAAO;CAC7D,CAAC;AACH;AAEA,SAAgB,yBACd,gBACA,QACS;CACT,IAAI,eAAe,SAAS,MAA+B,GACzD,OAAO;CAGT,IAAI,OAAO,WAAW,UAAU,GAC9B,OAAO,eAAe,SAAS,WAAW;CAG5C,OAAO;AACT;AAEA,eAAsB,6BACpB,QACA,SACA,KAC0D;CAC1D,MAAM,UAAU,MAAM,sBAAsB,OAAO,WAAW,CAAC,GAAG,SAAS,GAAG;CAC9E,OAAO,OAAO,KAAK,OAAO,CAAC,CAAC,SAAS,IAAI,UAAU;AACrD;AAEA,SAAS,qBAAqB,OAAmE;CAC/F,IAAI,CAACC,4BAAc,MAAM,GAAG,GAC1B;CAGF,MAAM,MAAM,MAAM;CAClB,IAAI,CAACA,4BAAc,IAAI,EAAE,GACvB;CAGF,MAAM,KAAK,IAAI;CACf,IAAI,YAAY,IACd,MAAM,IAAI,MACR,iHACF;CAGF,OAAO;AACT;AAEA,SAAS,kBACP,UACA,SACqC;CACrC,IAAI,CAAC,UACH,OAAO,UAAU,EAAE,GAAG,QAAQ,IAAI;CAGpC,IAAI,CAAC,SACH,OAAO,EAAE,GAAG,SAAS;CAGvB,OAAOC,8BAAgB,EAAE,GAAG,QAAQ,GAAG,QAAQ;AACjD;AAEA,SAAS,iBACP,OACA,cACc;CACd,IAAI,CAAC,cACH,OAAO;CAGT,MAAM,MAAMD,4BAAc,MAAM,GAAG,IAC9B,EAAE,GAAI,MAAM,IAAgC,IAC7C,CAAC;CACL,IAAI,KAAK,kBAAkB,qBAAqB,KAAK,GAAG,YAAY;CAEpE,OAAO;EACL,GAAG;EACH;CACF;AACF;AAEA,eAAsB,+BACpB,QACA,SACA,KACoB;CACpB,MAAM,CAAC,aAAa,gBAAgB,MAAM,QAAQ,IAAI,CACpD,2BAA2B,OAAO,IAAI,KAAqB,SAAS,KAAK,SAAS,GAClF,OAAO,IAAI,OACP,2BAA2B,OAAO,IAAI,MAAsB,SAAS,KAAK,UAAU,IACpF,QAAQ,QAAQ,MAAS,CAC/B,CAAC;CAED,MAAM,kBAAkB,OAAO,UAC3B,OAAO,YACL,MAAM,QAAQ,IACZ,OAAO,QAAQ,OAAO,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,UAAU,iBAAiB;EACpE,MAAM,iBAAiB,MAAM,2BAC3B,kBAAkB,WAAW,GAC7B,SACA,KACA,WAAW,UACb;EAEA,OAAO,CACL,UACA,iBAAiB,eAAe,OAAO,eAAe,YAAY,CACpE;CACF,CAAC,CACH,CACF,IACA;CAEJ,OAAO;EACL,GAAG;EACH,KAAK;GACH,GAAG,OAAO;GACV,KAAK,YAAY;GACjB,MAAM,cAAc;EACtB;EACA,SAAS;CACX;AACF;AAEA,SAAgB,sBAAsB,WAA2B;CAC/D,2BAAY,WAAW,QAAQ,wBAAwB;AACzD;AAEA,SAAgB,4BAA4B,WAAqC;CAC/E,MAAM,eAAe,sBAAsB,SAAS;CACpD,IAAI,yBAAY,YAAY,GAAG,OAAO;CACtC,IAAI;EACF,MAAM,MAAM,KAAK,gCAAmB,cAAc,OAAO,CAAC;EAC1D,IAAI,CAACA,4BAAc,GAAG,GAAG,OAAO;EAChC,MAAM,EAAE,WAAW,GAAG,eAAe;EACrC,OAAOD,8BAAgB,MAAM,UAAU;CACzC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAgB,oBACd,WACA,QACA,KACA,cACA,QACM;CACN,MAAM,eAAe,sBAAsB,SAAS;CACpD,MAAM,qCAAsB,YAAY;CACxC,IAAI,yBAAY,WAAW,GACzB,uBAAU,aAAa,EAAE,WAAW,KAAK,CAAC;CAG5C,MAAM,UAAUG,mCAAqB,MAAM;CAO3C,MAAM,SAAS;EACb,WAAW;GANX;GACA,6BAAY,IAAI,KAAK,EAAC,CAAC,YAAY;GACnC,cAAc,gBAAgB,CAAC;GAC/B,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;EAGb;EACd,GAAG;CACL;CAEA,MAAM,UAAU,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE;CACnD,IAAI;EACF,8BAAiB,cAAc,OAAO,MAAM,SAAS;CACvD,QAAQ,CAER;CACA,2BAAc,cAAc,OAAO;AACrC;AAEA,SAAgB,qBAAqB,WAA2B;CAC9D,MAAM,eAAe,sBAAsB,SAAS;CACpD,4BAAe,YAAY,GAAG,OAAO;CACrC,2BAAY,WAAW,iBAAiB;AAC1C;AAEA,SAAgB,sBAAsB,WAA4C;CAChF,MAAM,eAAe,sBAAsB,SAAS;CACpD,4BAAe,YAAY,GACzB,IAAI;EACF,MAAM,MAAM,KAAK,gCAAmB,cAAc,OAAO,CAAC;EAC1D,IAAIF,4BAAc,GAAG,GAAG;GACtB,MAAM,EAAE,WAAW,GAAG,eAAe;GACrC,OAAO;EACT;CACF,SAAS,GAAG;EACV,QAAQ,KACN,6EAA6E,GAC/E;CACF;CAEF,MAAM,oCAAqB,WAAW,iBAAiB;CACvD,OAAO,KAAK,gCAAmB,eAAe,OAAO,CAAC;AACxD;AAEA,SAAS,mBAAmB,KAAkC;CAC5D,MAAM,YAAY,IAAI,QAAQ,GAAG;CACjC,IAAI,cAAc,IAChB,OAAO,EAAE,YAAY,IAAI;CAG3B,MAAM,aAAa,IAAI,MAAM,GAAG,SAAS;CACzC,MAAM,aAAa,IAAI,MAAM,YAAY,CAAC;CAC1C,OAAO;EACL;EACA,YAAY,WAAW,SAAS,IAAI,aAAa;CACnD;AACF;AAEA,SAAS,iBAAiB,YAAoB,SAAyB;CACrE,IAAI,WAAW,WAAW,QAAQ,GAAG,OAAO;CAC5C,wDAA0B,UAAU,IAAI,oCAAqB,SAAS,UAAU,CAAC;AACnF;AAEA,SAAS,kBAAkB,OAA8B;CACvD,IAAI,UAAU,QACZ,OAAO,CAAC;CAEV,IAAI,OAAO,UAAU,UACnB,OAAO,EAAE,SAAS,MAAM;CAE1B,IAAI,CAACA,4BAAc,KAAK,GACtB,MAAM,IAAI,MAAM,0CAA0C,OAAO,OAAO;CAE1E,OAAO;AACT;AAEA,SAAS,iBAAiB,QAAwB,YAAkC;CAClF,IAAI,WAAW,WAAW,MAAM,GAAG;EACjC,MAAM,WAAW,WAAW,MAAM,CAAa;EAC/C,OAAO,kBAAkB,OAAO,MAAM,SAAS;CACjD;CAEA,IAAI,WAAW,WAAW,UAAU,GAAG;EACrC,MAAM,WAAW,WAAW,MAAM,CAAiB;EACnD,IAAI,SAAS,WAAW,GACtB,MAAM,IAAI,MAAM,+BAA+B,YAAY;EAE7D,OAAO,kBAAkB,OAAO,UAAU,SAAS;CACrD;CAEA,MAAM,IAAI,MAAM,oCAAoC,YAAY;AAClE;AAEA,SAAS,gBACP,QACA,aACqC;CACrC,IAAI,CAACA,4BAAc,OAAO,KAAK,EAAE,GAC/B;CAGF,MAAM,KAAK,OAAO,IAAI;CACtB,IAAI,YAAY,IACd,MAAM,IAAI,MACR,iHACF;CAGF,OAAO;AACT;AAEA,SAAS,uBACP,QACA,OACc;CACd,OAAOC,8BAAgB,EAAE,GAAG,MAAM,GAAG,MAAM;AAC7C;AAEA,SAAS,4BACP,OACA,iBACG;CACH,IAAI,CAAC,SAAS,iBACZ,OAAO;CAGT,IAAI,OAAO,MAAM,gBAAgB,YAAY,MAAM,YAAY,WAAW,YAAY,GAAG;EACvF,MAAM,EAAE,aAAa,UAAU,GAAG,SAAS;EAC3C,OAAO;CACT;CAEA,OAAO;AACT;AAEA,eAAsB,2BACpB,QACA,SACA,KACA,mBACsC;CACtC,IAAI,gBAA8B,CAAC;CACnC,IAAI,kBAAkB;CACtB,IAAI,aAAa;CACjB,IAAI,eAAe,qBAAqB,MAAM;CAC9C,IAAI,kBAAkB;CACtB,IAAI;CAEJ,MAAM,aAAa,OAAO,UAAUE,gCAAkB,OAAO,SAAS,GAAG,IAAI;CAC7E,IAAI,YAAY;EACd,MAAM,SAAS,mBAAmB,UAAU;EAC5C,aAAa,OAAO,cAAc;EAClC,MAAM,iBAAiB,iBAAiB,OAAO,YAAY,OAAO;EAClE,IAAI;GACF,MAAM,iBAAiB,MAAM,yBAC3B,OAAO,YACP,gCACA,IAAI,IAAI,GACR,CAAC,GACD,GACF;GACA,gBAAgB,uBACd,eACA,iBAAiB,gBAAgB,UAAU,CAC7C;GACA,kBAAkB;GAClB,eAAe,kBAAkB,cAAc,gBAAgB,gBAAgB,UAAU,CAAC;EAC5F,SAAS,OAAO;GACd,eAAe;EACjB;CACF;CAEA,MAAM,mBACJ,OAAO,OAAO,gBAAgB,YAAY,OAAO,YAAY,WAAW,YAAY,IAChF,OAAO,cACP;CACN,MAAM,uBAAuB,0CACjB,SAAS,iBAAiB,MAAM,CAAmB,CAAC,CAAC,KAAK,CAAC,IACnE;CACJ,MAAM,4BAA4B,QAChC,gDAAmC,oBAAoB,CACzD;CAEA,IAAI,sBAAsB;EACxB,MAAM,YAAY;EAClB,MAAM,sCAAuB,WAAW,iBAAiB;EACzD,4BAAe,eAAe,GAAG;GAC/B,MAAM,cAAc,MAAM,yBACxB,iBACA,2BACA,IAAI,IAAI,GACR,CAAC,GACD,GACF;GACA,gBAAgB,uBACd,eACA,iBAAiB,aAAa,UAAU,CAC1C;GACA,kBAAkB;GAClB,eAAe,kBAAkB,cAAc,gBAAgB,aAAa,UAAU,CAAC;GACvF,kBAAkB;EACpB;CACF;CAEA,MAAM,kBAAkB,EAAE,GAAG,OAAO;CACpC,IAAI,mBAAmB,kBACrB,OAAO,gBAAgB;CAGzB,gBAAgB,uBAAuB,eAAe,eAAe;CACrE,eAAe,kBAAkB,cAAc,qBAAqB,eAAe,CAAC;CAEpF,IAAI,gBAAgB,CAAC,mBAAmB,CAAC,2BACvC,MAAM;CAGR,OAAO;EACL,OAAO,4BAA4B,eAAe,mBAAmB,QAAQ,gBAAgB,CAAC;EAC9F;EACA;EACA,cAAc,4BAA4B,cAAc,eAAe;CACzE;AACF;AAEA,SAAS,yBACP,aACA,YACA,SACA,aACA,QACA,YACe;CACf,IAAI,gBAAgB,UAClB,OAAO,qBAAqB,YAAY,SAAS,QAAQ;CAE3D,IAAI,CAAC,aAAa;EAChB,IAAI,cAAc,QAChB,IAAI,YACF,kBAAkB,uBAAuB,OAAO,SAAS,YAAY;OAErE,kBAAkB,uCAAuC,OAAO,oBAAoB;EAGxF,OAAO,qBAAqB,YAAY,SAAS,QAAQ;CAC3D;CACA,MAAM,YAAY,qBAAqB,aAAa,OAAO;CAC3D,IAAI,UAAU,WAAW,YAAY,CAAC,UAAU,aAAa,yBAAY,UAAU,SAAS,IAAI;EAC9F,IAAI,cAAc,QAChB,kBAAkB,6CAA6C,OAAO,oBAAoB;EAE5F,OAAO,qBAAqB,YAAY,SAAS,QAAQ;CAC3D;CACA,OAAO;AACT;AAWA,SAAgB,mBACd,QACA,SACA,KACA,SACe;CACf,MAAM,WAAW,OAAO,IAAI;CAC5B,MAAM,YAAY,OAAO,IAAI;CAC7B,MAAM,aAAa,OAAO,IAAI;CAC9B,MAAM,YACJ,QAAQ,gBACJ,yBACE,SAAS,aACT,SAAS,YACT,SACA,SAAS,UACT,QACF,IACA,qBAAqB,SAAS,YAAY,SAAS,QAAQ;CACjE,MAAM,aACJ,QAAQ,gBACJ,yBACE,UAAU,aACV,UAAU,YACV,SACA,SAAS,WACT,SACF,IACA,qBAAqB,UAAU,YAAY,SAAS,QAAQ;CAClE,MAAM,iBAAiB,YAAY,UAC/BA,gCAAkB,WAAW,SAAS,GAAG,IACzC;CACJ,MAAM,cAAc,aAChB,QAAQ,gBACN,yBACE,WAAW,aACX,WAAW,YACX,SACA,SAAS,YACT,YACA,cACF,IACA,qBAAqB,WAAW,YAAY,SAAS,QAAQ,IAC/D;CAEJ,MAAM,aAAa,OAAO,IAAI;CAC9B,MAAM,cACJ,QAAQ,gBACJ,yBACE,WAAW,aACX,WAAW,YACX,SACA,SAAS,YACT,UACF,IACA,qBAAqB,WAAW,YAAY,SAAS,QAAQ;CAEnE,MAAM,mBACJ,QAAQ,gBACJ,0BAA0B,WAAW,WAAW,IAChD,oBAAoB;CAE1B,MAAM,eAAe,YAAY,WAAW;CAC5C,MAAM,aAAa,UAAU,WAAW;CACxC,MAAM,cAAc,WAAW,WAAW;CAC1C,MAAM,kBAAkB,yBAAyB,UAAU,MAAM,WAAW,WAAW,KAAK;CAE5F,OAAO;EACL;EACA,SAAS,OAAO;EAChB,QAAQ,OAAO;EACf,OAAO,OAAO;EACd,aAAa,OAAO;EACpB,WAAWC,uCAAuB,OAAO,OAAO;EAChD,YAAY,OAAO;EACnB,MAAM;GACJ,MAAM;GACN,KAAK;GACL,OAAO,GAAG,iBAAiB;GAC3B,WAAW,YAAY;GACvB,MAAM,QAAQ,gBAAgB,UAAU,gBAAgB,IAAI;GAC5D,SAAS,WAAW;GACpB,WAAW,eAAe,WAAW,YAAY;GACjD,QAAQ,YAAY;GACpB,WAAW,eAAe,YAAY,MAAM;EAC9C;EACA,IAAI;GACF,MAAM,yBAAyB,SAAS,MAAM,UAAU,WAAW,IAAI;GACvE,KAAK,UAAU;GACf,OAAO,UAAU,MAAM,GAAG,UAAU,IAAI,qBAAqB;GAC7D,WAAW,UAAU;GACrB,MAAM,UAAU;GAChB,QAAQ,aAAa,SAAS,MAAM;GACpC,cAAc,aAAa,SAAS,eAAe;GACnD,WAAW,aAAa,SAAS,YAAY;GAC7C,QAAQ,UAAU;EACpB;EACA,KAAK;GACH,MAAM;GACN,KAAK,WAAW;GAChB,OAAO,WAAW,MAAM,GAAG,WAAW,IAAI,qBAAqB;GAC/D,WAAW,WAAW;GACtB,MAAM,WAAW;GACjB,QAAQ,WAAW;GACnB,OAAO,SAAS,SAAS,UAAU;GACnC,WAAW,UAAU;GACrB,SAAS,UAAU;GACnB,WAAW,cAAc,UAAU,YAAY;GAC/C,QAAQ,UAAU;EACpB;EACA,aAAa;GACX,IAAI,CAAC,cAAc,CAAC,aAAa,OAAO;GACxC,IAAI,CAAC,YAAY,aAAa,CAAC,YAAY,KAAK,OAAO;GACvD,OAAO;IACL,MAAM,yBAAyB,WAAW,MAAM,YAAY,WAAW,MAAM;IAC7E,YAAY;IACZ,KAAK,YAAY;IACjB,OAAO,YAAY,MAAM,GAAG,YAAY,IAAI,qBAAqB;IACjE,WAAW,YAAY;IACvB,MAAM,YAAY;IAClB,QAAQ,YAAY;IACpB,OAAO,WAAW;IAClB,WAAW,WAAW;IACtB,SAAS,WAAW;IACpB,WAAW,YAAY,WAAW,WAAW,WAAW,YAAY;IACpE,QAAQ,WAAW;GACrB;EACF,EAAC,CAAE;EACH,SACE,SAAS,WAAW,OAAO,KAAK,QAAQ,OAAO,CAAC,CAAC,SAAS,IAAI,QAAQ,UAAU;CACpF;AACF;AAEA,eAAe,eAAe,YAAoB,SAA0C;CAC1F,IAAI,WAAW,WAAW,QAAQ,GAChC,OAAOC,wCAAyC,UAAU;CAG5D,MAAM,yCAA0B,UAAU,IAAI,oCAAqB,SAAS,UAAU;CACtF,OAAO,KAAK,gCAAmB,cAAc,OAAO,CAAC;AACvD;AAEA,eAAe,yBACb,YACA,SACA,SACA,OACA,MAAc,eACW;CACzB,IAAI,QAAQ,IAAI,UAAU,GACxB,MAAM,IAAI,MAAM,8BAA8B,CAAC,GAAG,SAAS,UAAU,CAAC,CAAC,KAAK,MAAM,GAAG;CAGvF,MAAM,SAAS,MAAM,eAAe,YAAY,OAAO;CACvD,MAAM,KAAK,UAAU;CAErB,IAAI,CAAC,OAAO,SACV,OAAO;CAGT,MAAM,aAAaF,gCAAkB,OAAO,SAAmC,GAAG;CAClF,IAAI,CAAC,YACH,OAAO;CAGT,MAAM,kBAAkB,mBAAmB,UAAU;CAErD,MAAM,cAAc,IAAI,IAAI,OAAO;CACnC,YAAY,IAAI,UAAU;CAC1B,MAAM,gBAAgB,iBAAiB,gBAAgB,YAAY,OAAO;CAS1E,OAAOG,wCAA0B,MARZ,yBACnB,gBAAgB,YAChB,eACA,aACA,OACA,GACF,GAEyC,MAAM;AACjD;AAIA,SAAS,qBAAqB,KAAuD;CACnF,IAAI,QAAQ,QAAQ,QAAQ,OAAO,OAAO;CAC1C,IAAI,OAAO,QAAQ,UACjB,OAAO,EAAE,SAAS,IAAI;CAExB,OAAO;AACT;AAEA,eAAe,sBACb,SACA,SACA,KACA,eAC8C;CAC9C,MAAM,UAAU,OAAO,QAAQ,OAAO,CAAC,CACpC,KAAK,CAAC,UAAU,eAAe;EAC9B;EACA,YAAY,qBAAqB,QAAQ;CAC3C,EAAE,CAAC,CACF,QACE,UACC,MAAM,eAAe,QAAQ,MAAM,eAAe,KACtD;CAEF,MAAM,WAAW,MAAM,QAAQ,IAC7B,QAAQ,IAAI,OAAO,EAAE,UAAU,iBAAiB;EAC9C,MAAM,oBAAoB,MAAM,2BAC9B,YACA,SACA,KACA,WAAW,UACb;EAEA,MAAM,cACJ,kBAAkB,SACd,SACA,cAAc,WAAW,KAAK,cAAc,SAAS,QAAQ,IAC3D,WACA;EACR,MAAM,gBAAgB,yBAAyB,UAAU,KAAK,mBAAmB,WAAW;EAE5F,IAAI,CAAC,cAAc,aAAa,CAAC,cAAc,KAAK;GAClD,IAAI,gBAAgB,UAClB,kBACE,oBAAoB,SAAS,0IAC/B;GAEF,OAAO;EACT;EAEA,IACE,cAAc,WAAW,YACzB,cAAc,OACd,CAAC,cAAc,aACf,OAAO,kBAAkB,MAAM,SAAS,UAExC,cAAc,OAAO,MAAM,+BACzB,cAAc,KACd,cAAc,IAChB;EAGF,OAAO,CAAC,UAAU,aAAa;CACjC,CAAC,CACH;CAEA,MAAM,MAA2C,CAAC;CAClD,KAAK,MAAM,SAAS,UAClB,IAAI,OACF,IAAI,MAAM,MAAM,MAAM;CAI1B,OAAO;AACT;AAEA,eAAe,+BAA+B,SAAiB,UAAmC;CAChG,MAAM,WAAW,MAAMC,oCAEpB,GAAG,QAAQ,QAAQ,OAAO,EAAE,EAAE,wBAAwB,EAAE,SAAS,EAAE,CAAC;CAEvE,OAAO,OAAO,UAAU,QAAQ,SAAS,YAAY,SAAS,OAAO,KAAK,SAAS,IAC/E,SAAS,OAAO,OAChB;AACN;AAEA,SAAS,yBACP,UACA,KACA,UACA,aACqB;CACrB,MAAM,SAAS,SAAS;CACxB,MAAM,cAAc,OAAO,OAAO,gBAAgB,WAAW,OAAO,cAAc;CAClF,MAAM,aAAa,OAAO,OAAO,eAAe,WAAW,OAAO,aAAa;CAE/E,IAAI,YAAY,WAAW,QAAQ,GACjC,MAAM,IAAI,MACR,WAAW,SAAS,uCAAuC,WAAW,uFACxE;CAGF,MAAM,mBAAmB,OAAO,UAAUJ,gCAAkB,OAAO,SAAS,GAAG,IAAI;CAEnF,MAAM,gBACJ,QAAQ,gBACJ,yBACE,aACA,YACA,SAAS,iBACT,aACA,WAAW,YACX,gBACF,IACA,qBAAqB,YAAY,SAAS,iBAAiB,QAAQ;CACzE,MAAM,UAAU,yBAAyB,OAAO,MAAM,cAAc,WAAW,QAAQ;CAEvF,MAAM,WAAW,SAAS;CAC1B,MAAM,gBACJ,OAAO,UAAU,gBAAgB,WAAW,SAAS,cAAc;CACrE,MAAM,eAAe,OAAO,UAAU,eAAe,WAAW,SAAS,aAAa;CACtF,MAAM,YACJ,aAAa,iBAAiB,gBAC1B,QAAQ,gBACN,yBACE,eACA,cACA,SAAS,iBACT,aACA,WAAW,SAAS,IACtB,IACA,qBAAqB,cAAc,SAAS,iBAAiB,QAAQ,IACvE;CAEN,MAAM,SAAS,OAAO;CAEtB,OAAO;EACL,MAAM;EACN,KAAK,cAAc;EACnB,OAAO,cAAc,MACjB,GAAG,cAAc,IAAI,QAAQ,OAAO,EAAE,EAAE,qBACxC;EACJ,QAAQ,cAAc;EACtB,YAAY;EACZ,WAAW,cAAc;EACzB,MAAM,cAAc;EACpB,OAAO,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ;EACzD,WAAW,oBAAoB,OAAO,SAAS;EAC/C,SAAS,qBAAqB,OAAO,OAAO;EAC5C,QAAQ,OAAO;EACf,WAAW,cAAc,WAAW,WAAW,OAAO,YAAY;EAClE,IAAI,YAC