everything-dev 2.0.0-rc.0 → 2.0.0-rc.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/dist/auth-login.cjs +1 -1
  2. package/dist/auth-login.mjs +1 -1
  3. package/dist/build.cjs +2 -2
  4. package/dist/build.mjs +2 -2
  5. package/dist/bundle-fs-resolve.cjs +9 -17
  6. package/dist/bundle-fs-resolve.cjs.map +1 -1
  7. package/dist/bundle-fs-resolve.d.cts +6 -0
  8. package/dist/bundle-fs-resolve.d.mts +6 -0
  9. package/dist/bundle-fs-resolve.mjs +9 -17
  10. package/dist/bundle-fs-resolve.mjs.map +1 -1
  11. package/dist/bundle-path.cjs +48 -0
  12. package/dist/bundle-path.cjs.map +1 -0
  13. package/dist/bundle-path.mjs +45 -0
  14. package/dist/bundle-path.mjs.map +1 -0
  15. package/dist/cli/init.cjs +13 -13
  16. package/dist/cli/init.cjs.map +1 -1
  17. package/dist/cli/init.mjs +13 -13
  18. package/dist/cli/init.mjs.map +1 -1
  19. package/dist/cli/status.cjs +69 -3
  20. package/dist/cli/status.cjs.map +1 -1
  21. package/dist/cli/status.mjs +67 -4
  22. package/dist/cli/status.mjs.map +1 -1
  23. package/dist/cli/sync.cjs +1 -1
  24. package/dist/cli/sync.cjs.map +1 -1
  25. package/dist/cli/sync.mjs +1 -1
  26. package/dist/cli/sync.mjs.map +1 -1
  27. package/dist/cli/upgrade.cjs +2 -2
  28. package/dist/cli/upgrade.cjs.map +1 -1
  29. package/dist/cli/upgrade.mjs +2 -2
  30. package/dist/cli/upgrade.mjs.map +1 -1
  31. package/dist/cli.cjs +5 -7
  32. package/dist/cli.cjs.map +1 -1
  33. package/dist/cli.mjs +5 -7
  34. package/dist/cli.mjs.map +1 -1
  35. package/dist/commands/deploy.cjs +26 -16
  36. package/dist/commands/deploy.cjs.map +1 -1
  37. package/dist/commands/deploy.mjs +26 -16
  38. package/dist/commands/deploy.mjs.map +1 -1
  39. package/dist/commands/init.cjs +1 -1
  40. package/dist/commands/init.cjs.map +1 -1
  41. package/dist/commands/init.mjs +1 -1
  42. package/dist/commands/init.mjs.map +1 -1
  43. package/dist/commands/plugins.cjs +2 -2
  44. package/dist/commands/plugins.cjs.map +1 -1
  45. package/dist/commands/plugins.mjs +2 -2
  46. package/dist/commands/plugins.mjs.map +1 -1
  47. package/dist/commands/upgrade.cjs +1 -1
  48. package/dist/commands/upgrade.mjs +1 -1
  49. package/dist/components/dev-render.cjs +1 -1
  50. package/dist/components/dev-render.mjs +1 -1
  51. package/dist/config.cjs +3 -3
  52. package/dist/config.cjs.map +1 -1
  53. package/dist/config.mjs +3 -3
  54. package/dist/config.mjs.map +1 -1
  55. package/dist/contract.cjs +2 -0
  56. package/dist/contract.cjs.map +1 -1
  57. package/dist/contract.d.cts +3 -0
  58. package/dist/contract.d.mts +3 -0
  59. package/dist/contract.meta.cjs +2 -1
  60. package/dist/contract.meta.cjs.map +1 -1
  61. package/dist/contract.meta.d.cts +4 -1
  62. package/dist/contract.meta.d.mts +4 -1
  63. package/dist/contract.meta.mjs +2 -1
  64. package/dist/contract.meta.mjs.map +1 -1
  65. package/dist/contract.mjs +2 -0
  66. package/dist/contract.mjs.map +1 -1
  67. package/dist/db/driver.cjs +22 -2
  68. package/dist/db/driver.cjs.map +1 -1
  69. package/dist/db/driver.d.cts +13 -2
  70. package/dist/db/driver.d.mts +13 -2
  71. package/dist/db/driver.mjs +22 -3
  72. package/dist/db/driver.mjs.map +1 -1
  73. package/dist/db/index.cjs +1 -0
  74. package/dist/db/index.d.cts +2 -2
  75. package/dist/db/index.d.mts +2 -2
  76. package/dist/db/index.mjs +2 -2
  77. package/dist/deploy-diff.cjs +1 -1
  78. package/dist/deploy-diff.cjs.map +1 -1
  79. package/dist/deploy-diff.mjs +1 -1
  80. package/dist/deploy-diff.mjs.map +1 -1
  81. package/dist/dev-program.cjs +10 -2
  82. package/dist/dev-program.cjs.map +1 -1
  83. package/dist/dev-program.mjs +10 -2
  84. package/dist/dev-program.mjs.map +1 -1
  85. package/dist/image-deploy.cjs +65 -17
  86. package/dist/image-deploy.cjs.map +1 -1
  87. package/dist/image-deploy.mjs +64 -18
  88. package/dist/image-deploy.mjs.map +1 -1
  89. package/dist/internal/manifest-normalizer.cjs.map +1 -1
  90. package/dist/internal/manifest-normalizer.mjs.map +1 -1
  91. package/dist/plugin.d.cts +902 -1
  92. package/dist/plugin.d.mts +902 -1
  93. package/dist/publish.cjs +51 -2
  94. package/dist/publish.cjs.map +1 -1
  95. package/dist/publish.mjs +51 -4
  96. package/dist/publish.mjs.map +1 -1
  97. package/dist/resolution/session.cjs.map +1 -1
  98. package/dist/resolution/session.d.cts +5 -5
  99. package/dist/resolution/session.d.mts +5 -5
  100. package/dist/resolution/session.mjs.map +1 -1
  101. package/dist/types.d.cts +31 -1
  102. package/dist/types.d.mts +31 -1
  103. package/dist/ui/auth-guards.d.cts +78 -2
  104. package/dist/ui/auth-guards.d.mts +78 -2
  105. package/dist/ui/auth.cjs.map +1 -1
  106. package/dist/ui/auth.d.cts +4133 -7
  107. package/dist/ui/auth.d.mts +4133 -7
  108. package/dist/ui/auth.mjs.map +1 -1
  109. package/dist/ui/hydrate.cjs +2 -2
  110. package/dist/ui/hydrate.cjs.map +1 -1
  111. package/dist/ui/hydrate.mjs +2 -2
  112. package/dist/ui/hydrate.mjs.map +1 -1
  113. package/dist/utils/theme.cjs +2 -2
  114. package/dist/utils/theme.cjs.map +1 -1
  115. package/dist/utils/theme.mjs +2 -2
  116. package/dist/utils/theme.mjs.map +1 -1
  117. package/dist/version-manifest-resolve.cjs +55 -10
  118. package/dist/version-manifest-resolve.cjs.map +1 -1
  119. package/dist/version-manifest-resolve.mjs +53 -10
  120. package/dist/version-manifest-resolve.mjs.map +1 -1
  121. package/dist/workspace.cjs +26 -13
  122. package/dist/workspace.cjs.map +1 -1
  123. package/dist/workspace.mjs +26 -14
  124. package/dist/workspace.mjs.map +1 -1
  125. package/package.json +11 -10
@@ -1 +1 @@
1
- {"version":3,"file":"plugins.cjs","names":["Context","BosDepsTag","MISSING_CONFIG_MESSAGE","saveBosConfig","generateCodeArtifacts","existsSync","join","publishToFastKv","openResolution","fetchRemotePluginManifest","basename","getPluginRef"],"sources":["../../src/commands/plugins.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport { Context } from \"effect\";\nimport { getPluginRef } from \"../build\";\nimport { generateCodeArtifacts } from \"../code-artifacts\";\nimport { MISSING_CONFIG_MESSAGE } from \"../config\";\nimport type { PluginListResult } from \"../contract\";\nimport { fetchRemotePluginManifest } from \"../fastkv\";\nimport { publishToFastKv } from \"../publish\";\nimport { openResolution } from \"../resolution/session\";\nimport type { BosConfig } from \"../types\";\nimport { saveBosConfig } from \"../utils/save-config\";\nimport { type BosBuilder, BosDepsTag } from \"./shared\";\n\nexport function registerPlugins(builder: BosBuilder) {\n return {\n pluginAdd: builder.pluginAdd.handler(async ({ input, context }) => {\n const deps = Context.get(context[\"effect/context\"], BosDepsTag);\n const session = deps.session;\n if (!session?.config) {\n return {\n status: \"error\" as const,\n key: \"\",\n error: MISSING_CONFIG_MESSAGE,\n };\n }\n\n const isBosRef = input.source.startsWith(\"bos://\");\n const isLocal = input.source.startsWith(\"local:\");\n const key = sanitizePluginKey(\n input.as ??\n (isBosRef ? (input.source.split(\"/\").pop() ?? \"plugin\") : defaultPluginKey(input.source)),\n );\n const existing = session.config.plugins?.[key];\n const existingEntry = existing && typeof existing === \"object\" ? existing : {};\n // Adding a source is a switch, not an additive patch: a remote URL (or\n // bos:// ref) replaces a conflicting local development ref. Dual-mode\n // (local in dev, production URL in prod) remains expressible by\n // hand-editing the authored config.\n const applyEntryDelta = (base: Record<string, unknown>): Record<string, unknown> => {\n if (isBosRef) {\n const { development: _dropped, ...rest } = base;\n return { ...rest, extends: input.source };\n }\n if (isLocal) {\n const { extends: _dropped, ...rest } = base;\n return { ...rest, development: input.source };\n }\n const { development: _dropped, ...rest } = base;\n return { ...rest, production: input.production ?? input.source };\n };\n const nextPlugins = { ...session.config.plugins };\n nextPlugins[key] = applyEntryDelta(existingEntry);\n\n const nextConfig: BosConfig = {\n ...session.config,\n plugins: nextPlugins,\n };\n\n const authored = session.rawConfig;\n if (authored) {\n // Authoring-surface save: the authored leaf input + delta, never the\n // resolved config (which would bake inherited values into the file).\n const authoredExisting = authored.plugins?.[key];\n const authoredBase: Record<string, unknown> =\n typeof authoredExisting === \"string\"\n ? { extends: authoredExisting }\n : authoredExisting && typeof authoredExisting === \"object\"\n ? (authoredExisting as Record<string, unknown>)\n : {};\n await saveBosConfig(session.root, {\n ...authored,\n plugins: {\n ...(authored.plugins ?? {}),\n [key]: applyEntryDelta(authoredBase),\n },\n });\n } else {\n await saveBosConfig(session.root, nextConfig);\n }\n await generateCodeArtifacts(session.root, nextConfig);\n\n const stored = nextConfig.plugins?.[key];\n const storedObj = stored && typeof stored === \"object\" ? stored : {};\n\n return {\n status: \"added\" as const,\n key,\n development: storedObj.development,\n production: storedObj.production,\n integrity: storedObj.integrity,\n version: storedObj.version,\n };\n }),\n\n pluginRemove: builder.pluginRemove.handler(async ({ input, context }) => {\n const deps = Context.get(context[\"effect/context\"], BosDepsTag);\n const session = deps.session;\n if (!session?.config) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: MISSING_CONFIG_MESSAGE,\n };\n }\n\n if (!session.config.plugins?.[input.key]) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: `Plugin '${input.key}' is not configured`,\n };\n }\n\n const nextPlugins = { ...session.config.plugins };\n delete nextPlugins[input.key];\n const nextConfig: BosConfig = {\n ...session.config,\n plugins: Object.keys(nextPlugins).length > 0 ? nextPlugins : undefined,\n };\n\n const authored = session.rawConfig;\n if (authored) {\n const authoredPlugins: Record<string, unknown> = { ...(authored.plugins ?? {}) };\n if (authoredPlugins[input.key] === undefined) {\n // Inherited from the parent runtime. JSON-form children can express\n // removal with a null sentinel (dropped by the extends merge); the\n // TS descriptor schema cannot, so only those error out.\n if (existsSync(join(session.root, \"bos.app.ts\"))) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: `'${input.key}' is inherited from the parent runtime — remove it in the parent config or override it there (the authored descriptor cannot express removal)`,\n };\n }\n authoredPlugins[input.key] = null;\n } else {\n delete authoredPlugins[input.key];\n }\n await saveBosConfig(session.root, {\n ...authored,\n plugins: Object.keys(authoredPlugins).length > 0 ? authoredPlugins : undefined,\n });\n } else {\n await saveBosConfig(session.root, nextConfig);\n }\n await generateCodeArtifacts(session.root, nextConfig);\n\n return {\n status: \"removed\" as const,\n key: input.key,\n };\n }),\n\n pluginList: builder.pluginList.handler(async ({ context }) => {\n const deps = Context.get(context[\"effect/context\"], BosDepsTag);\n const plugins: PluginListResult[\"plugins\"] = listPluginAttachments(\n deps.session?.config ?? null,\n );\n return {\n status: \"listed\" as const,\n plugins,\n };\n }),\n\n pluginPublish: builder.pluginPublish.handler(async ({ input, context }) => {\n const deps = Context.get(context[\"effect/context\"], BosDepsTag);\n const session = deps.session;\n if (!session?.config) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: MISSING_CONFIG_MESSAGE,\n };\n }\n\n const attachment = session.config?.plugins?.[input.key];\n if (!attachment) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: `Plugin '${input.key}' is not configured`,\n };\n }\n\n const localPath = pluginLocalPath(session.root, attachment);\n if (!localPath) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: `Plugin '${input.key}' does not have a local development path`,\n };\n }\n\n const result = await publishToFastKv({\n bosConfig: session.config,\n runtimeConfig: session.runtime,\n configDir: session.root,\n env: \"production\",\n build: true,\n dryRun: false,\n verbose: false,\n packages: input.key,\n });\n if (result.status === \"error\") {\n return {\n status: \"error\" as const,\n key: input.key,\n error: result.error,\n };\n }\n\n const nextSession = (await openResolution({ cwd: session.root })) ?? session;\n const production = (\n nextSession.config?.plugins?.[input.key] as\n | {\n production?: string;\n }\n | undefined\n )?.production;\n\n const manifest = production ? await fetchRemotePluginManifest(production) : null;\n if (production && nextSession.config) {\n await generateCodeArtifacts(session.root, nextSession.config);\n }\n\n return {\n status: \"published\" as const,\n key: input.key,\n path: localPath,\n production,\n fingerprint: result.fingerprint,\n version: manifest?.plugin.version,\n };\n }),\n };\n}\n\ntype PluginAttachmentConfig = NonNullable<BosConfig[\"plugins\"]>[string];\n\nfunction sanitizePluginKey(value: string): string {\n return value\n .replace(/[^A-Za-z0-9/_-]/g, \"-\")\n .replace(/\\/+/g, \"/\")\n .split(\"/\")\n .filter(Boolean)\n .map((segment) => segment.replace(/[^A-Za-z0-9_-]/g, \"-\"))\n .join(\"/\")\n .replace(/^\\/+|\\/+$/g, \"\");\n}\n\nfunction defaultPluginKey(source: string): string {\n const normalized = source.replace(/^local:/, \"\").replace(/\\/$/, \"\");\n if (source.startsWith(\"local:\")) {\n return sanitizePluginKey(basename(normalized)) || \"plugin\";\n }\n\n try {\n const url = new URL(source);\n return sanitizePluginKey(basename(url.pathname) || url.hostname) || \"plugin\";\n } catch {\n return sanitizePluginKey(source) || \"plugin\";\n }\n}\n\nfunction pluginLocalPath(configDir: string, attachment: PluginAttachmentConfig): string | null {\n const ref = getPluginRef(attachment);\n const source = ref?.development ?? ref?.production;\n if (!source?.startsWith(\"local:\")) {\n return null;\n }\n\n return join(configDir, source.slice(\"local:\".length));\n}\n\nfunction listPluginAttachments(config: BosConfig | null) {\n return (Object.entries(config?.plugins ?? {}) as Array<[string, PluginAttachmentConfig]>)\n .map(([key, attachment]) => {\n const ref = getPluginRef(attachment);\n return {\n key,\n development: ref?.development,\n production: ref?.production,\n localPath: ref?.development?.startsWith(\"local:\")\n ? ref.development.slice(\"local:\".length)\n : undefined,\n source: ref?.development?.startsWith(\"local:\") ? (\"local\" as const) : (\"remote\" as const),\n integrity: ref?.integrity,\n version: ref?.version,\n name: ref?.name,\n };\n })\n .sort((a, b) => a.key.localeCompare(b.key));\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"plugins.cjs","names":["Context","BosDepsTag","MISSING_CONFIG_MESSAGE","saveBosConfig","generateCodeArtifacts","existsSync","join","publishToFastKv","openResolution","fetchRemotePluginManifest","basename","getPluginRef"],"sources":["../../src/commands/plugins.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport { Context } from \"effect\";\nimport { getPluginRef } from \"../build\";\nimport { generateCodeArtifacts } from \"../code-artifacts\";\nimport { MISSING_CONFIG_MESSAGE } from \"../config\";\nimport type { PluginListResult } from \"../contract\";\nimport { fetchRemotePluginManifest } from \"../fastkv\";\nimport { publishToFastKv } from \"../publish\";\nimport { openResolution } from \"../resolution/session\";\nimport type { BosConfig } from \"../types\";\nimport { saveBosConfig } from \"../utils/save-config\";\nimport { type BosBuilder, BosDepsTag } from \"./shared\";\n\nexport function registerPlugins(builder: BosBuilder) {\n return {\n pluginAdd: builder.pluginAdd.handler(async ({ input, context }) => {\n const deps = Context.get(context[\"effect/context\"], BosDepsTag);\n const session = deps.session;\n if (!session?.config) {\n return {\n status: \"error\" as const,\n key: \"\",\n error: MISSING_CONFIG_MESSAGE,\n };\n }\n\n const isBosRef = input.source.startsWith(\"bos://\");\n const isLocal = input.source.startsWith(\"local:\");\n const key = sanitizePluginKey(\n input.as ??\n (isBosRef ? (input.source.split(\"/\").pop() ?? \"plugin\") : defaultPluginKey(input.source)),\n );\n const existing = session.config.plugins?.[key];\n const existingEntry = existing && typeof existing === \"object\" ? existing : {};\n // Adding a source is a switch, not an additive patch: a remote URL (or\n // bos:// ref) replaces a conflicting local development ref. Dual-mode\n // (local in dev, production URL in prod) remains expressible by\n // hand-editing the authored config.\n const applyEntryDelta = (base: Record<string, unknown>): Record<string, unknown> => {\n if (isBosRef) {\n const { development: _dropped, ...rest } = base;\n return { ...rest, extends: input.source };\n }\n if (isLocal) {\n const { extends: _dropped, ...rest } = base;\n return { ...rest, development: input.source };\n }\n const { development: _dropped, ...rest } = base;\n return { ...rest, production: input.production ?? input.source };\n };\n const nextPlugins = { ...session.config.plugins };\n nextPlugins[key] = applyEntryDelta(existingEntry);\n\n const nextConfig: BosConfig = {\n ...session.config,\n plugins: nextPlugins,\n };\n\n const authored = session.rawConfig;\n if (authored) {\n // Authoring-surface save: the authored leaf input + delta, never the\n // resolved config (which would bake inherited values into the file).\n const authoredExisting = authored.plugins?.[key];\n const authoredBase: Record<string, unknown> =\n typeof authoredExisting === \"string\"\n ? { extends: authoredExisting }\n : authoredExisting && typeof authoredExisting === \"object\"\n ? (authoredExisting as Record<string, unknown>)\n : {};\n await saveBosConfig(session.root, {\n ...authored,\n plugins: {\n ...authored.plugins,\n [key]: applyEntryDelta(authoredBase),\n },\n });\n } else {\n await saveBosConfig(session.root, nextConfig);\n }\n await generateCodeArtifacts(session.root, nextConfig);\n\n const stored = nextConfig.plugins?.[key];\n const storedObj = stored && typeof stored === \"object\" ? stored : {};\n\n return {\n status: \"added\" as const,\n key,\n development: storedObj.development,\n production: storedObj.production,\n integrity: storedObj.integrity,\n version: storedObj.version,\n };\n }),\n\n pluginRemove: builder.pluginRemove.handler(async ({ input, context }) => {\n const deps = Context.get(context[\"effect/context\"], BosDepsTag);\n const session = deps.session;\n if (!session?.config) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: MISSING_CONFIG_MESSAGE,\n };\n }\n\n if (!session.config.plugins?.[input.key]) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: `Plugin '${input.key}' is not configured`,\n };\n }\n\n const nextPlugins = { ...session.config.plugins };\n delete nextPlugins[input.key];\n const nextConfig: BosConfig = {\n ...session.config,\n plugins: Object.keys(nextPlugins).length > 0 ? nextPlugins : undefined,\n };\n\n const authored = session.rawConfig;\n if (authored) {\n const authoredPlugins: Record<string, unknown> = { ...authored.plugins };\n if (authoredPlugins[input.key] === undefined) {\n // Inherited from the parent runtime. JSON-form children can express\n // removal with a null sentinel (dropped by the extends merge); the\n // TS descriptor schema cannot, so only those error out.\n if (existsSync(join(session.root, \"bos.app.ts\"))) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: `'${input.key}' is inherited from the parent runtime — remove it in the parent config or override it there (the authored descriptor cannot express removal)`,\n };\n }\n authoredPlugins[input.key] = null;\n } else {\n delete authoredPlugins[input.key];\n }\n await saveBosConfig(session.root, {\n ...authored,\n plugins: Object.keys(authoredPlugins).length > 0 ? authoredPlugins : undefined,\n });\n } else {\n await saveBosConfig(session.root, nextConfig);\n }\n await generateCodeArtifacts(session.root, nextConfig);\n\n return {\n status: \"removed\" as const,\n key: input.key,\n };\n }),\n\n pluginList: builder.pluginList.handler(async ({ context }) => {\n const deps = Context.get(context[\"effect/context\"], BosDepsTag);\n const plugins: PluginListResult[\"plugins\"] = listPluginAttachments(\n deps.session?.config ?? null,\n );\n return {\n status: \"listed\" as const,\n plugins,\n };\n }),\n\n pluginPublish: builder.pluginPublish.handler(async ({ input, context }) => {\n const deps = Context.get(context[\"effect/context\"], BosDepsTag);\n const session = deps.session;\n if (!session?.config) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: MISSING_CONFIG_MESSAGE,\n };\n }\n\n const attachment = session.config?.plugins?.[input.key];\n if (!attachment) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: `Plugin '${input.key}' is not configured`,\n };\n }\n\n const localPath = pluginLocalPath(session.root, attachment);\n if (!localPath) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: `Plugin '${input.key}' does not have a local development path`,\n };\n }\n\n const result = await publishToFastKv({\n bosConfig: session.config,\n runtimeConfig: session.runtime,\n configDir: session.root,\n env: \"production\",\n build: true,\n dryRun: false,\n verbose: false,\n packages: input.key,\n });\n if (result.status === \"error\") {\n return {\n status: \"error\" as const,\n key: input.key,\n error: result.error,\n };\n }\n\n const nextSession = (await openResolution({ cwd: session.root })) ?? session;\n const production = (\n nextSession.config?.plugins?.[input.key] as\n | {\n production?: string;\n }\n | undefined\n )?.production;\n\n const manifest = production ? await fetchRemotePluginManifest(production) : null;\n if (production && nextSession.config) {\n await generateCodeArtifacts(session.root, nextSession.config);\n }\n\n return {\n status: \"published\" as const,\n key: input.key,\n path: localPath,\n production,\n fingerprint: result.fingerprint,\n version: manifest?.plugin.version,\n };\n }),\n };\n}\n\ntype PluginAttachmentConfig = NonNullable<BosConfig[\"plugins\"]>[string];\n\nfunction sanitizePluginKey(value: string): string {\n return value\n .replace(/[^A-Za-z0-9/_-]/g, \"-\")\n .replace(/\\/+/g, \"/\")\n .split(\"/\")\n .filter(Boolean)\n .map((segment) => segment.replace(/[^A-Za-z0-9_-]/g, \"-\"))\n .join(\"/\")\n .replace(/^\\/+|\\/+$/g, \"\");\n}\n\nfunction defaultPluginKey(source: string): string {\n const normalized = source.replace(/^local:/, \"\").replace(/\\/$/, \"\");\n if (source.startsWith(\"local:\")) {\n return sanitizePluginKey(basename(normalized)) || \"plugin\";\n }\n\n try {\n const url = new URL(source);\n return sanitizePluginKey(basename(url.pathname) || url.hostname) || \"plugin\";\n } catch {\n return sanitizePluginKey(source) || \"plugin\";\n }\n}\n\nfunction pluginLocalPath(configDir: string, attachment: PluginAttachmentConfig): string | null {\n const ref = getPluginRef(attachment);\n const source = ref?.development ?? ref?.production;\n if (!source?.startsWith(\"local:\")) {\n return null;\n }\n\n return join(configDir, source.slice(\"local:\".length));\n}\n\nfunction listPluginAttachments(config: BosConfig | null) {\n return (Object.entries(config?.plugins ?? {}) as Array<[string, PluginAttachmentConfig]>)\n .map(([key, attachment]) => {\n const ref = getPluginRef(attachment);\n return {\n key,\n development: ref?.development,\n production: ref?.production,\n localPath: ref?.development?.startsWith(\"local:\")\n ? ref.development.slice(\"local:\".length)\n : undefined,\n source: ref?.development?.startsWith(\"local:\") ? (\"local\" as const) : (\"remote\" as const),\n integrity: ref?.integrity,\n version: ref?.version,\n name: ref?.name,\n };\n })\n .sort((a, b) => a.key.localeCompare(b.key));\n}\n"],"mappings":"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"}
@@ -59,7 +59,7 @@ function registerPlugins(builder) {
59
59
  await saveBosConfig(session.root, {
60
60
  ...authored,
61
61
  plugins: {
62
- ...authored.plugins ?? {},
62
+ ...authored.plugins,
63
63
  [key]: applyEntryDelta(authoredBase)
64
64
  }
65
65
  });
@@ -96,7 +96,7 @@ function registerPlugins(builder) {
96
96
  };
97
97
  const authored = session.rawConfig;
98
98
  if (authored) {
99
- const authoredPlugins = { ...authored.plugins ?? {} };
99
+ const authoredPlugins = { ...authored.plugins };
100
100
  if (authoredPlugins[input.key] === void 0) {
101
101
  if (existsSync(join(session.root, "bos.app.ts"))) return {
102
102
  status: "error",
@@ -1 +1 @@
1
- {"version":3,"file":"plugins.mjs","names":[],"sources":["../../src/commands/plugins.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport { Context } from \"effect\";\nimport { getPluginRef } from \"../build\";\nimport { generateCodeArtifacts } from \"../code-artifacts\";\nimport { MISSING_CONFIG_MESSAGE } from \"../config\";\nimport type { PluginListResult } from \"../contract\";\nimport { fetchRemotePluginManifest } from \"../fastkv\";\nimport { publishToFastKv } from \"../publish\";\nimport { openResolution } from \"../resolution/session\";\nimport type { BosConfig } from \"../types\";\nimport { saveBosConfig } from \"../utils/save-config\";\nimport { type BosBuilder, BosDepsTag } from \"./shared\";\n\nexport function registerPlugins(builder: BosBuilder) {\n return {\n pluginAdd: builder.pluginAdd.handler(async ({ input, context }) => {\n const deps = Context.get(context[\"effect/context\"], BosDepsTag);\n const session = deps.session;\n if (!session?.config) {\n return {\n status: \"error\" as const,\n key: \"\",\n error: MISSING_CONFIG_MESSAGE,\n };\n }\n\n const isBosRef = input.source.startsWith(\"bos://\");\n const isLocal = input.source.startsWith(\"local:\");\n const key = sanitizePluginKey(\n input.as ??\n (isBosRef ? (input.source.split(\"/\").pop() ?? \"plugin\") : defaultPluginKey(input.source)),\n );\n const existing = session.config.plugins?.[key];\n const existingEntry = existing && typeof existing === \"object\" ? existing : {};\n // Adding a source is a switch, not an additive patch: a remote URL (or\n // bos:// ref) replaces a conflicting local development ref. Dual-mode\n // (local in dev, production URL in prod) remains expressible by\n // hand-editing the authored config.\n const applyEntryDelta = (base: Record<string, unknown>): Record<string, unknown> => {\n if (isBosRef) {\n const { development: _dropped, ...rest } = base;\n return { ...rest, extends: input.source };\n }\n if (isLocal) {\n const { extends: _dropped, ...rest } = base;\n return { ...rest, development: input.source };\n }\n const { development: _dropped, ...rest } = base;\n return { ...rest, production: input.production ?? input.source };\n };\n const nextPlugins = { ...session.config.plugins };\n nextPlugins[key] = applyEntryDelta(existingEntry);\n\n const nextConfig: BosConfig = {\n ...session.config,\n plugins: nextPlugins,\n };\n\n const authored = session.rawConfig;\n if (authored) {\n // Authoring-surface save: the authored leaf input + delta, never the\n // resolved config (which would bake inherited values into the file).\n const authoredExisting = authored.plugins?.[key];\n const authoredBase: Record<string, unknown> =\n typeof authoredExisting === \"string\"\n ? { extends: authoredExisting }\n : authoredExisting && typeof authoredExisting === \"object\"\n ? (authoredExisting as Record<string, unknown>)\n : {};\n await saveBosConfig(session.root, {\n ...authored,\n plugins: {\n ...(authored.plugins ?? {}),\n [key]: applyEntryDelta(authoredBase),\n },\n });\n } else {\n await saveBosConfig(session.root, nextConfig);\n }\n await generateCodeArtifacts(session.root, nextConfig);\n\n const stored = nextConfig.plugins?.[key];\n const storedObj = stored && typeof stored === \"object\" ? stored : {};\n\n return {\n status: \"added\" as const,\n key,\n development: storedObj.development,\n production: storedObj.production,\n integrity: storedObj.integrity,\n version: storedObj.version,\n };\n }),\n\n pluginRemove: builder.pluginRemove.handler(async ({ input, context }) => {\n const deps = Context.get(context[\"effect/context\"], BosDepsTag);\n const session = deps.session;\n if (!session?.config) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: MISSING_CONFIG_MESSAGE,\n };\n }\n\n if (!session.config.plugins?.[input.key]) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: `Plugin '${input.key}' is not configured`,\n };\n }\n\n const nextPlugins = { ...session.config.plugins };\n delete nextPlugins[input.key];\n const nextConfig: BosConfig = {\n ...session.config,\n plugins: Object.keys(nextPlugins).length > 0 ? nextPlugins : undefined,\n };\n\n const authored = session.rawConfig;\n if (authored) {\n const authoredPlugins: Record<string, unknown> = { ...(authored.plugins ?? {}) };\n if (authoredPlugins[input.key] === undefined) {\n // Inherited from the parent runtime. JSON-form children can express\n // removal with a null sentinel (dropped by the extends merge); the\n // TS descriptor schema cannot, so only those error out.\n if (existsSync(join(session.root, \"bos.app.ts\"))) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: `'${input.key}' is inherited from the parent runtime — remove it in the parent config or override it there (the authored descriptor cannot express removal)`,\n };\n }\n authoredPlugins[input.key] = null;\n } else {\n delete authoredPlugins[input.key];\n }\n await saveBosConfig(session.root, {\n ...authored,\n plugins: Object.keys(authoredPlugins).length > 0 ? authoredPlugins : undefined,\n });\n } else {\n await saveBosConfig(session.root, nextConfig);\n }\n await generateCodeArtifacts(session.root, nextConfig);\n\n return {\n status: \"removed\" as const,\n key: input.key,\n };\n }),\n\n pluginList: builder.pluginList.handler(async ({ context }) => {\n const deps = Context.get(context[\"effect/context\"], BosDepsTag);\n const plugins: PluginListResult[\"plugins\"] = listPluginAttachments(\n deps.session?.config ?? null,\n );\n return {\n status: \"listed\" as const,\n plugins,\n };\n }),\n\n pluginPublish: builder.pluginPublish.handler(async ({ input, context }) => {\n const deps = Context.get(context[\"effect/context\"], BosDepsTag);\n const session = deps.session;\n if (!session?.config) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: MISSING_CONFIG_MESSAGE,\n };\n }\n\n const attachment = session.config?.plugins?.[input.key];\n if (!attachment) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: `Plugin '${input.key}' is not configured`,\n };\n }\n\n const localPath = pluginLocalPath(session.root, attachment);\n if (!localPath) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: `Plugin '${input.key}' does not have a local development path`,\n };\n }\n\n const result = await publishToFastKv({\n bosConfig: session.config,\n runtimeConfig: session.runtime,\n configDir: session.root,\n env: \"production\",\n build: true,\n dryRun: false,\n verbose: false,\n packages: input.key,\n });\n if (result.status === \"error\") {\n return {\n status: \"error\" as const,\n key: input.key,\n error: result.error,\n };\n }\n\n const nextSession = (await openResolution({ cwd: session.root })) ?? session;\n const production = (\n nextSession.config?.plugins?.[input.key] as\n | {\n production?: string;\n }\n | undefined\n )?.production;\n\n const manifest = production ? await fetchRemotePluginManifest(production) : null;\n if (production && nextSession.config) {\n await generateCodeArtifacts(session.root, nextSession.config);\n }\n\n return {\n status: \"published\" as const,\n key: input.key,\n path: localPath,\n production,\n fingerprint: result.fingerprint,\n version: manifest?.plugin.version,\n };\n }),\n };\n}\n\ntype PluginAttachmentConfig = NonNullable<BosConfig[\"plugins\"]>[string];\n\nfunction sanitizePluginKey(value: string): string {\n return value\n .replace(/[^A-Za-z0-9/_-]/g, \"-\")\n .replace(/\\/+/g, \"/\")\n .split(\"/\")\n .filter(Boolean)\n .map((segment) => segment.replace(/[^A-Za-z0-9_-]/g, \"-\"))\n .join(\"/\")\n .replace(/^\\/+|\\/+$/g, \"\");\n}\n\nfunction defaultPluginKey(source: string): string {\n const normalized = source.replace(/^local:/, \"\").replace(/\\/$/, \"\");\n if (source.startsWith(\"local:\")) {\n return sanitizePluginKey(basename(normalized)) || \"plugin\";\n }\n\n try {\n const url = new URL(source);\n return sanitizePluginKey(basename(url.pathname) || url.hostname) || \"plugin\";\n } catch {\n return sanitizePluginKey(source) || \"plugin\";\n }\n}\n\nfunction pluginLocalPath(configDir: string, attachment: PluginAttachmentConfig): string | null {\n const ref = getPluginRef(attachment);\n const source = ref?.development ?? ref?.production;\n if (!source?.startsWith(\"local:\")) {\n return null;\n }\n\n return join(configDir, source.slice(\"local:\".length));\n}\n\nfunction listPluginAttachments(config: BosConfig | null) {\n return (Object.entries(config?.plugins ?? {}) as Array<[string, PluginAttachmentConfig]>)\n .map(([key, attachment]) => {\n const ref = getPluginRef(attachment);\n return {\n key,\n development: ref?.development,\n production: ref?.production,\n localPath: ref?.development?.startsWith(\"local:\")\n ? ref.development.slice(\"local:\".length)\n : undefined,\n source: ref?.development?.startsWith(\"local:\") ? (\"local\" as const) : (\"remote\" as const),\n integrity: ref?.integrity,\n version: ref?.version,\n name: ref?.name,\n };\n })\n .sort((a, b) => a.key.localeCompare(b.key));\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"plugins.mjs","names":[],"sources":["../../src/commands/plugins.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport { Context } from \"effect\";\nimport { getPluginRef } from \"../build\";\nimport { generateCodeArtifacts } from \"../code-artifacts\";\nimport { MISSING_CONFIG_MESSAGE } from \"../config\";\nimport type { PluginListResult } from \"../contract\";\nimport { fetchRemotePluginManifest } from \"../fastkv\";\nimport { publishToFastKv } from \"../publish\";\nimport { openResolution } from \"../resolution/session\";\nimport type { BosConfig } from \"../types\";\nimport { saveBosConfig } from \"../utils/save-config\";\nimport { type BosBuilder, BosDepsTag } from \"./shared\";\n\nexport function registerPlugins(builder: BosBuilder) {\n return {\n pluginAdd: builder.pluginAdd.handler(async ({ input, context }) => {\n const deps = Context.get(context[\"effect/context\"], BosDepsTag);\n const session = deps.session;\n if (!session?.config) {\n return {\n status: \"error\" as const,\n key: \"\",\n error: MISSING_CONFIG_MESSAGE,\n };\n }\n\n const isBosRef = input.source.startsWith(\"bos://\");\n const isLocal = input.source.startsWith(\"local:\");\n const key = sanitizePluginKey(\n input.as ??\n (isBosRef ? (input.source.split(\"/\").pop() ?? \"plugin\") : defaultPluginKey(input.source)),\n );\n const existing = session.config.plugins?.[key];\n const existingEntry = existing && typeof existing === \"object\" ? existing : {};\n // Adding a source is a switch, not an additive patch: a remote URL (or\n // bos:// ref) replaces a conflicting local development ref. Dual-mode\n // (local in dev, production URL in prod) remains expressible by\n // hand-editing the authored config.\n const applyEntryDelta = (base: Record<string, unknown>): Record<string, unknown> => {\n if (isBosRef) {\n const { development: _dropped, ...rest } = base;\n return { ...rest, extends: input.source };\n }\n if (isLocal) {\n const { extends: _dropped, ...rest } = base;\n return { ...rest, development: input.source };\n }\n const { development: _dropped, ...rest } = base;\n return { ...rest, production: input.production ?? input.source };\n };\n const nextPlugins = { ...session.config.plugins };\n nextPlugins[key] = applyEntryDelta(existingEntry);\n\n const nextConfig: BosConfig = {\n ...session.config,\n plugins: nextPlugins,\n };\n\n const authored = session.rawConfig;\n if (authored) {\n // Authoring-surface save: the authored leaf input + delta, never the\n // resolved config (which would bake inherited values into the file).\n const authoredExisting = authored.plugins?.[key];\n const authoredBase: Record<string, unknown> =\n typeof authoredExisting === \"string\"\n ? { extends: authoredExisting }\n : authoredExisting && typeof authoredExisting === \"object\"\n ? (authoredExisting as Record<string, unknown>)\n : {};\n await saveBosConfig(session.root, {\n ...authored,\n plugins: {\n ...authored.plugins,\n [key]: applyEntryDelta(authoredBase),\n },\n });\n } else {\n await saveBosConfig(session.root, nextConfig);\n }\n await generateCodeArtifacts(session.root, nextConfig);\n\n const stored = nextConfig.plugins?.[key];\n const storedObj = stored && typeof stored === \"object\" ? stored : {};\n\n return {\n status: \"added\" as const,\n key,\n development: storedObj.development,\n production: storedObj.production,\n integrity: storedObj.integrity,\n version: storedObj.version,\n };\n }),\n\n pluginRemove: builder.pluginRemove.handler(async ({ input, context }) => {\n const deps = Context.get(context[\"effect/context\"], BosDepsTag);\n const session = deps.session;\n if (!session?.config) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: MISSING_CONFIG_MESSAGE,\n };\n }\n\n if (!session.config.plugins?.[input.key]) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: `Plugin '${input.key}' is not configured`,\n };\n }\n\n const nextPlugins = { ...session.config.plugins };\n delete nextPlugins[input.key];\n const nextConfig: BosConfig = {\n ...session.config,\n plugins: Object.keys(nextPlugins).length > 0 ? nextPlugins : undefined,\n };\n\n const authored = session.rawConfig;\n if (authored) {\n const authoredPlugins: Record<string, unknown> = { ...authored.plugins };\n if (authoredPlugins[input.key] === undefined) {\n // Inherited from the parent runtime. JSON-form children can express\n // removal with a null sentinel (dropped by the extends merge); the\n // TS descriptor schema cannot, so only those error out.\n if (existsSync(join(session.root, \"bos.app.ts\"))) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: `'${input.key}' is inherited from the parent runtime — remove it in the parent config or override it there (the authored descriptor cannot express removal)`,\n };\n }\n authoredPlugins[input.key] = null;\n } else {\n delete authoredPlugins[input.key];\n }\n await saveBosConfig(session.root, {\n ...authored,\n plugins: Object.keys(authoredPlugins).length > 0 ? authoredPlugins : undefined,\n });\n } else {\n await saveBosConfig(session.root, nextConfig);\n }\n await generateCodeArtifacts(session.root, nextConfig);\n\n return {\n status: \"removed\" as const,\n key: input.key,\n };\n }),\n\n pluginList: builder.pluginList.handler(async ({ context }) => {\n const deps = Context.get(context[\"effect/context\"], BosDepsTag);\n const plugins: PluginListResult[\"plugins\"] = listPluginAttachments(\n deps.session?.config ?? null,\n );\n return {\n status: \"listed\" as const,\n plugins,\n };\n }),\n\n pluginPublish: builder.pluginPublish.handler(async ({ input, context }) => {\n const deps = Context.get(context[\"effect/context\"], BosDepsTag);\n const session = deps.session;\n if (!session?.config) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: MISSING_CONFIG_MESSAGE,\n };\n }\n\n const attachment = session.config?.plugins?.[input.key];\n if (!attachment) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: `Plugin '${input.key}' is not configured`,\n };\n }\n\n const localPath = pluginLocalPath(session.root, attachment);\n if (!localPath) {\n return {\n status: \"error\" as const,\n key: input.key,\n error: `Plugin '${input.key}' does not have a local development path`,\n };\n }\n\n const result = await publishToFastKv({\n bosConfig: session.config,\n runtimeConfig: session.runtime,\n configDir: session.root,\n env: \"production\",\n build: true,\n dryRun: false,\n verbose: false,\n packages: input.key,\n });\n if (result.status === \"error\") {\n return {\n status: \"error\" as const,\n key: input.key,\n error: result.error,\n };\n }\n\n const nextSession = (await openResolution({ cwd: session.root })) ?? session;\n const production = (\n nextSession.config?.plugins?.[input.key] as\n | {\n production?: string;\n }\n | undefined\n )?.production;\n\n const manifest = production ? await fetchRemotePluginManifest(production) : null;\n if (production && nextSession.config) {\n await generateCodeArtifacts(session.root, nextSession.config);\n }\n\n return {\n status: \"published\" as const,\n key: input.key,\n path: localPath,\n production,\n fingerprint: result.fingerprint,\n version: manifest?.plugin.version,\n };\n }),\n };\n}\n\ntype PluginAttachmentConfig = NonNullable<BosConfig[\"plugins\"]>[string];\n\nfunction sanitizePluginKey(value: string): string {\n return value\n .replace(/[^A-Za-z0-9/_-]/g, \"-\")\n .replace(/\\/+/g, \"/\")\n .split(\"/\")\n .filter(Boolean)\n .map((segment) => segment.replace(/[^A-Za-z0-9_-]/g, \"-\"))\n .join(\"/\")\n .replace(/^\\/+|\\/+$/g, \"\");\n}\n\nfunction defaultPluginKey(source: string): string {\n const normalized = source.replace(/^local:/, \"\").replace(/\\/$/, \"\");\n if (source.startsWith(\"local:\")) {\n return sanitizePluginKey(basename(normalized)) || \"plugin\";\n }\n\n try {\n const url = new URL(source);\n return sanitizePluginKey(basename(url.pathname) || url.hostname) || \"plugin\";\n } catch {\n return sanitizePluginKey(source) || \"plugin\";\n }\n}\n\nfunction pluginLocalPath(configDir: string, attachment: PluginAttachmentConfig): string | null {\n const ref = getPluginRef(attachment);\n const source = ref?.development ?? ref?.production;\n if (!source?.startsWith(\"local:\")) {\n return null;\n }\n\n return join(configDir, source.slice(\"local:\".length));\n}\n\nfunction listPluginAttachments(config: BosConfig | null) {\n return (Object.entries(config?.plugins ?? {}) as Array<[string, PluginAttachmentConfig]>)\n .map(([key, attachment]) => {\n const ref = getPluginRef(attachment);\n return {\n key,\n development: ref?.development,\n production: ref?.production,\n localPath: ref?.development?.startsWith(\"local:\")\n ? ref.development.slice(\"local:\".length)\n : undefined,\n source: ref?.development?.startsWith(\"local:\") ? (\"local\" as const) : (\"remote\" as const),\n integrity: ref?.integrity,\n version: ref?.version,\n name: ref?.name,\n };\n })\n .sort((a, b) => a.key.localeCompare(b.key));\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
2
2
  const require_config = require('../config.cjs');
3
+ const require_theme = require('../utils/theme.cjs');
3
4
  const require_resolution_session = require('../resolution/session.cjs');
4
5
  const require_mf = require('../mf.cjs');
5
- const require_theme = require('../utils/theme.cjs');
6
6
  const require_build = require('../build.cjs');
7
7
  const require_code_artifacts = require('../code-artifacts.cjs');
8
8
  const require_sync = require('../cli/sync.cjs');
@@ -1,7 +1,7 @@
1
1
  import { MISSING_CONFIG_MESSAGE, findConfigPath, readAuthoredConfigInput } from "../config.mjs";
2
+ import { colors } from "../utils/theme.mjs";
2
3
  import { openResolution } from "../resolution/session.mjs";
3
4
  import { checkFederationCompat } from "../mf.mjs";
4
- import { colors } from "../utils/theme.mjs";
5
5
  import { selectWorkspaceTargets } from "../build.mjs";
6
6
  import { generateCodeArtifacts } from "../code-artifacts.mjs";
7
7
  import { syncTemplate } from "../cli/sync.mjs";
@@ -1,6 +1,6 @@
1
1
  const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
2
- const require_dev_log_pipeline = require('../dev-log-pipeline.cjs');
3
2
  const require_theme = require('../utils/theme.cjs');
3
+ const require_dev_log_pipeline = require('../dev-log-pipeline.cjs');
4
4
  const require_linkify = require('../utils/linkify.cjs');
5
5
  let chalk = require("chalk");
6
6
  chalk = require_runtime.__toESM(chalk, 1);
@@ -1,5 +1,5 @@
1
- import { stripAnsi } from "../dev-log-pipeline.mjs";
2
1
  import { colors, divider, frames, gradients, icons } from "../utils/theme.mjs";
2
+ import { stripAnsi } from "../dev-log-pipeline.mjs";
3
3
  import { linkify } from "../utils/linkify.mjs";
4
4
  import chalk from "chalk";
5
5
 
package/dist/config.cjs CHANGED
@@ -298,7 +298,7 @@ async function readBosConfigForBuild(configDir) {
298
298
  return configData;
299
299
  }
300
300
  } catch (e) {
301
- console.warn(`[Config] Failed to parse _resolved.json, falling back to the authored config: ${e}`);
301
+ console.warn(`[Config] Failed to parse _resolved.json, falling back to the authored config: ${String(e)}`);
302
302
  }
303
303
  const authored = await readLocalAuthoredConfigInput(configDir);
304
304
  if (authored) return authored;
@@ -772,7 +772,7 @@ function resolveUiRuntimeName(uiConfig, localPath, apiName) {
772
772
  const pkg = JSON.parse((0, node_fs.readFileSync)(pkgPath, "utf-8"));
773
773
  if (typeof pkg.name === "string" && pkg.name.length > 0) return (0, every_plugin_ui_manifest_contract.sanitizeContainerName)(pkg.name);
774
774
  } catch (e) {
775
- console.warn(`[Config] Could not read package.json at ${pkgPath}: ${e}`);
775
+ console.warn(`[Config] Could not read package.json at ${pkgPath}: ${String(e)}`);
776
776
  }
777
777
  }
778
778
  return typeof uiConfig?.name === "string" ? uiConfig.name : `${apiName}-ui`;
@@ -785,7 +785,7 @@ function resolvePluginRuntimeName(explicitName, localPath, fallback) {
785
785
  const packageJson = JSON.parse((0, node_fs.readFileSync)(packageJsonPath, "utf-8"));
786
786
  if (typeof packageJson.name === "string" && packageJson.name.length > 0) return packageJson.name;
787
787
  } catch (e) {
788
- console.warn(`[Config] Could not read package.json at ${localPath}: ${e}`);
788
+ console.warn(`[Config] Could not read package.json at ${localPath}: ${String(e)}`);
789
789
  }
790
790
  return fallback;
791
791
  }