create-koishi-ce 1.6.4 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -27,7 +27,7 @@ npm create koishi-ce my-app
27
27
 
28
28
  ## 生成的项目
29
29
 
30
- - **package.json**:`type: module`、`packageManager` 钉 Bun、workspaces 含 `plugins/*` 与 `external/*`;dependencies 预装全套 `@koishi-ce` 常用插件(console、config、market、auth、admin、help、sandbox、database-sqlite 等),并预置四行 npm alias 钉住上游名——`koishi` / `@koishijs/core` / `@koishijs/loader` 指向 `@koishi-ce/koishi-shim`、`@koishijs/plugin-console` 指向 `@koishi-ce/console-shim`,社区插件由此全部解析到 CE 框架;
30
+ - **package.json**:`type: module`、`packageManager` 钉 Bun、workspaces 含 `plugins/*` 与 `external/*`;dependencies 预装全套 `@koishi-ce` 常用插件(console、config、market、auth、admin、help、sandbox、database-sqlite 等),并预置六行 npm alias 钉住上游名——`koishi` / `@koishijs/core` / `@koishijs/loader` 指向 `@koishi-ce/koishi-shim`、`@koishijs/plugin-console` 指向 `@koishi-ce/console-shim`、`@koishijs/client` / `@koishijs/components` 分别指向 `@koishi-ce/client-shim` / `@koishi-ce/components-shim`,社区插件(含把上游前端库写进 dependencies 的 webui 插件)由此全部解析到 CE 对应包;
31
31
  - **koishi.yml**:按 server(端口 5140-5149)/ basic / console(自动打开、市场指向 registry.koishi.chat 镜像)/ storage / adapter / develop(开发模式启用热重载)分组预写;官方 adapter 插件以 `~` 停用条目预写、不预装,装好后在控制台按需启用;数据库开箱即用——`database-sqlite` 默认启用,mongo / mysql / postgres 等其余 database 不预写占位条目,市场安装后自动出现;
32
32
  - **开发工具链**:devDependencies 预置 `@koishi-ce/client`、`@koishi-ce/plugin-hmr` 与 `@koishi-ce/scripts`(`koishi-scripts setup` 可在 external/ 下继续创建插件项目)。
33
33
 
package/lib/bin.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bun
2
- import { t as start } from "./src-D2Fw0uXq.mjs";
2
+ import { t as start } from "./src-D36TrO6G.mjs";
3
3
  //#region src/bin.ts
4
4
  /**
5
5
  * create-koishi-ce 的 CLI 可执行入口:shebang 由 rolldown 原样保留到
package/lib/index.d.ts CHANGED
@@ -16,6 +16,7 @@ interface Manifest {
16
16
  workspaces?: unknown;
17
17
  dependencies?: Record<string, string>;
18
18
  devDependencies?: Record<string, string>;
19
+ overrides?: Record<string, string>;
19
20
  [key: string]: unknown;
20
21
  }
21
22
  /**
package/lib/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { a as renderManifest, i as readNpmrcRegistry, n as detectAgent, r as getLocalRegistry, t as start } from "./src-D2Fw0uXq.mjs";
1
+ import { a as renderManifest, i as readNpmrcRegistry, n as detectAgent, r as getLocalRegistry, t as start } from "./src-D36TrO6G.mjs";
2
2
  export { detectAgent, getLocalRegistry, readNpmrcRegistry, renderManifest, start };
@@ -9,7 +9,7 @@ import { downloadTemplate } from "giget";
9
9
  var package_default = {
10
10
  name: "create-koishi-ce",
11
11
  description: "Setup a Koishi application",
12
- version: "1.6.4",
12
+ version: "1.8.0",
13
13
  type: "module",
14
14
  main: "./lib/index.mjs",
15
15
  module: "./lib/index.mjs",
@@ -157,10 +157,12 @@ function writePackageJson(rootDir, project, prod) {
157
157
  * 均以 Bun 为准(ESM-only 产物,Bun 原生加载 TS / yml);脚本里的环境
158
158
  * 变量注入直接写 `NODE_ENV=... ` 前缀——bun run 走 Bun Shell,跨平台
159
159
  * 原生支持,无需 cross-env 一类的依赖;
160
- * - "koishi" 裸名与 @koishijs/core / @koishijs/loader / @koishijs/plugin-console
161
- * 上游名用 npm alias 钉到 @koishi-ce shim(版本冻结线,见 packages/shim):
162
- * 上游官方 adapter / database 插件与社区 koishi-plugin-* 的 peer 由此满足,
163
- * 不会拉入 npm 官方全家桶形成第二份框架副本;市场安装亦不改写该声明
160
+ * - "koishi" 裸名与 @koishijs/core / @koishijs/loader / @koishijs/plugin-console /
161
+ * @koishijs/client / @koishijs/components 上游名用 npm alias 钉到 @koishi-ce
162
+ * shim(版本冻结线,见 packages/shim):上游官方 adapter / database 插件与
163
+ * 社区 koishi-plugin-* 的 peer 由此满足,webui 插件写进 dependencies 的
164
+ * client / components 亦被钉住(满足性判定看落盘版本),不会拉入 npm
165
+ * 官方全家桶形成第二份框架副本;市场安装亦不改写该声明
164
166
  * (installer 的 isGuardedRequest 护栏将 npm:@koishi-ce alias 与
165
167
  * workspace: 同等保护);
166
168
  * - koishi.yml 采用配置页导出形态:插件键带 uid 实例后缀,分组带中文
@@ -195,6 +197,74 @@ const dotFiles = {
195
197
  /** 模板静态文件(相对项目根的路径 → 文件内容),package.json 另行渲染 */
196
198
  const templateFiles = Object.fromEntries(readdirSync(templateDir).filter((file) => !file.startsWith(".")).map((file) => [dotFiles[file] ?? file, readFileSync(join(templateDir, file), "utf8")]));
197
199
  /**
200
+ * 上游名 → CE 对应包的 overrides 兜底映射(值统一 npm:<目标>@^1.0.0,
201
+ * 经 buildUpstreamOverrides 包装)。
202
+ *
203
+ * 六行钉名依赖「落盘版本满足声明范围」:第三方插件的声明超出冻结线
204
+ * (如未来上游升线后的 ^6)或引用清单外的上游名(如 dependencies 直接
205
+ * 依赖 @koishijs/plugin-admin / @koishijs/utils)时,官方包仍会落盘。
206
+ * overrides 是包管理器级的强制重写——不看版本满足性,把整棵依赖树中对
207
+ * 这些上游名的解析一律改指 CE 对应包,与钉名构成双层防线(napuketto
208
+ * 事件 2026-09-19 后补)。
209
+ *
210
+ * 清单 = CE 已再分发且官方同名的包,2026-09-19 逐一 npm view 核实:
211
+ * - plugin-cron 不在列(上游是裸名社区包 koishi-plugin-cron,非 @koishijs
212
+ * 作用域);
213
+ * - plugin-welcome / plugin-theme-vanilla 不在列(CE 原创,上游无此名);
214
+ * - plugin-assets 的 CE 对应物是 @koishi-ce/assets(无 plugin 前缀)。
215
+ * 新增 CE 再分发包时须同步本表与 sandbox 生成器的同款清单
216
+ * (tooling/sandbox/manifest.ts,对账测试防漂移)。
217
+ */
218
+ const UPSTREAM_OVERRIDES = {
219
+ koishi: "@koishi-ce/koishi",
220
+ "@koishijs/core": "@koishi-ce/koishi",
221
+ "@koishijs/loader": "@koishi-ce/koishi",
222
+ "@koishijs/utils": "@koishi-ce/utils",
223
+ "@koishijs/i18n-utils": "@koishi-ce/i18n-utils",
224
+ "@koishijs/client": "@koishi-ce/client",
225
+ "@koishijs/components": "@koishi-ce/components",
226
+ "@koishijs/console": "@koishi-ce/console",
227
+ "@koishijs/registry": "@koishi-ce/registry",
228
+ "@koishijs/plugin-console": "@koishi-ce/plugin-console",
229
+ "@koishijs/plugin-assets": "@koishi-ce/assets"
230
+ };
231
+ for (const name of [
232
+ "actions",
233
+ "admin",
234
+ "analytics",
235
+ "assets-local",
236
+ "auth",
237
+ "bind",
238
+ "broadcast",
239
+ "callme",
240
+ "commands",
241
+ "config",
242
+ "database-sqlite",
243
+ "dataview",
244
+ "echo",
245
+ "explorer",
246
+ "help",
247
+ "hmr",
248
+ "insight",
249
+ "inspect",
250
+ "locales",
251
+ "logger",
252
+ "market",
253
+ "mock",
254
+ "notifier",
255
+ "oobe",
256
+ "proxy-agent",
257
+ "rate-limit",
258
+ "sandbox",
259
+ "server",
260
+ "server-temp",
261
+ "status"
262
+ ]) UPSTREAM_OVERRIDES[`@koishijs/plugin-${name}`] = `@koishi-ce/plugin-${name}`;
263
+ /** 生成模板 overrides 块:键为上游名,值统一 npm:<CE 包>@^1.0.0。 */
264
+ function buildUpstreamOverrides() {
265
+ return Object.fromEntries(Object.entries(UPSTREAM_OVERRIDES).map(([name, target]) => [name, `npm:${target}@^1.0.0`]));
266
+ }
267
+ /**
198
268
  * 内置模板的 package.json 基础内容(name/version 会被 renderManifest 覆写,
199
269
  * prod 模式下 workspaces 与 devDependencies 会被移除)。
200
270
  */
@@ -255,8 +325,11 @@ function baseManifest() {
255
325
  koishi: "npm:@koishi-ce/koishi-shim@^4.18.11",
256
326
  "@koishijs/plugin-console": "npm:@koishi-ce/console-shim@^5.30.11",
257
327
  "@koishijs/core": "npm:@koishi-ce/koishi-shim@4.18.11",
258
- "@koishijs/loader": "npm:@koishi-ce/koishi-shim@^4.18.11"
328
+ "@koishijs/loader": "npm:@koishi-ce/koishi-shim@^4.18.11",
329
+ "@koishijs/client": "npm:@koishi-ce/client-shim@^5.30.11",
330
+ "@koishijs/components": "npm:@koishi-ce/components-shim@^1.5.22"
259
331
  },
332
+ overrides: buildUpstreamOverrides(),
260
333
  devDependencies: {
261
334
  "@koishi-ce/client": "^1.0.0",
262
335
  "@koishi-ce/plugin-hmr": "^1.0.0",
@@ -390,7 +463,7 @@ async function getName() {
390
463
  initialValue: "koishi-app",
391
464
  validate: (value) => value?.trim() ? void 0 : "项目名不能为空"
392
465
  });
393
- if (p.isCancel(answer)) process.exit(0);
466
+ if (p.isCancel(answer) || typeof answer !== "string") process.exit(0);
394
467
  const trimmed = answer.trim();
395
468
  if (!trimmed) process.exit(0);
396
469
  return trimmed;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "create-koishi-ce",
3
3
  "description": "Setup a Koishi application",
4
- "version": "1.6.4",
4
+ "version": "1.8.0",
5
5
  "type": "module",
6
6
  "main": "./lib/index.mjs",
7
7
  "module": "./lib/index.mjs",
@@ -5,18 +5,22 @@ import { expect, test } from "bun:test";
5
5
  import { renderManifest } from "../index.ts";
6
6
  import {
7
7
  baseManifest,
8
+ buildUpstreamOverrides,
8
9
  templateFiles,
9
10
  } from "../template.ts";
10
11
 
11
12
  test("内置模板依赖纯度:不含任何 @koishijs / koishi-plugin 官方生态包", () => {
12
13
  const { dependencies, devDependencies } = baseManifest();
13
- // 四个上游名是刻意的 npm alias 占位(koishi 裸名 / @koishijs/plugin-console /
14
- // @koishijs/core / @koishijs/loader),其余必须是 @koishi-ce 作用域
14
+ // 六个上游名是刻意的 npm alias 占位(koishi 裸名 / @koishijs/plugin-console /
15
+ // @koishijs/core / @koishijs/loader / @koishijs/client / @koishijs/components),
16
+ // 其余必须是 @koishi-ce 作用域
15
17
  const guarded = new Set([
16
18
  "koishi",
17
19
  "@koishijs/plugin-console",
18
20
  "@koishijs/core",
19
21
  "@koishijs/loader",
22
+ "@koishijs/client",
23
+ "@koishijs/components",
20
24
  ]);
21
25
  for (const key of Object.keys(dependencies ?? {})) {
22
26
  expect(
@@ -96,6 +100,15 @@ test("内置模板钉住 console / core / loader 上游 peer 名,防 Bun 自
96
100
  expect(dependencies?.["@koishijs/loader"]).toBe(
97
101
  "npm:@koishi-ce/koishi-shim@^4.18.11",
98
102
  );
103
+ // webui 插件把 client 写进 dependencies 的形态(napuketto 实证):
104
+ // 版本冻结 5.30.x 线满足 ^5.x,官方 client(连带 components)不再落盘
105
+ expect(dependencies?.["@koishijs/client"]).toBe(
106
+ "npm:@koishi-ce/client-shim@^5.30.11",
107
+ );
108
+ // 官方 client 的硬依赖、插件生态常直接依赖;冻结 1.5.x 线满足 ^1.5
109
+ expect(dependencies?.["@koishijs/components"]).toBe(
110
+ "npm:@koishi-ce/components-shim@^1.5.22",
111
+ );
99
112
  });
100
113
 
101
114
  test("内置模板静态文件齐备,koishi.yml 预配 market 镜像源", () => {
@@ -166,13 +179,14 @@ test("koishi.yml 预写策略:sqlite 默认启用开箱数据库,非必需
166
179
  expect(yml).toContain(name);
167
180
  }
168
181
  expect(yml).not.toContain("database-mongo");
169
- // 模板依赖里不得出现官方 adapter / database 包名(只预写不预装)
170
- expect(JSON.stringify(baseManifest())).not.toContain(
171
- "adapter-",
172
- );
173
- expect(JSON.stringify(baseManifest())).not.toContain(
174
- "@koishijs/plugin-database-",
175
- );
182
+ // 模板依赖里不得出现官方 adapter / database 包名(只预写不预装)。
183
+ // 断言只扫 dependencies——overrides 的键含官方名是重写所需,属预期
184
+ expect(
185
+ JSON.stringify(baseManifest().dependencies),
186
+ ).not.toContain("adapter-");
187
+ expect(
188
+ JSON.stringify(baseManifest().dependencies),
189
+ ).not.toContain("@koishijs/plugin-database-");
176
190
  });
177
191
 
178
192
  test("koishi.yml 预写条目与模板依赖对账:CE 插件必须在册,官方 adapter 只预写不预装", () => {
@@ -252,3 +266,65 @@ test("renderManifest 渲染内置模板:常规改写生效,prod 模式保留
252
266
  "npm:@koishi-ce/koishi-shim@^4.18.11",
253
267
  );
254
268
  });
269
+
270
+ test("内置模板 overrides 兜底层:41 个上游名强制重定向 CE 包", () => {
271
+ const table = baseManifest().overrides ?? {};
272
+ expect(Object.keys(table)).toHaveLength(41);
273
+ const keys = Object.keys(table);
274
+ // 核心九名(钉名六行之外由 overrides 补齐覆盖面)
275
+ expect(table["koishi"]).toBe(
276
+ "npm:@koishi-ce/koishi@^1.0.0",
277
+ );
278
+ expect(table["@koishijs/core"]).toBe(
279
+ "npm:@koishi-ce/koishi@^1.0.0",
280
+ );
281
+ expect(table["@koishijs/loader"]).toBe(
282
+ "npm:@koishi-ce/koishi@^1.0.0",
283
+ );
284
+ expect(table["@koishijs/utils"]).toBe(
285
+ "npm:@koishi-ce/utils@^1.0.0",
286
+ );
287
+ expect(table["@koishijs/i18n-utils"]).toBe(
288
+ "npm:@koishi-ce/i18n-utils@^1.0.0",
289
+ );
290
+ expect(table["@koishijs/client"]).toBe(
291
+ "npm:@koishi-ce/client@^1.0.0",
292
+ );
293
+ expect(table["@koishijs/components"]).toBe(
294
+ "npm:@koishi-ce/components@^1.0.0",
295
+ );
296
+ expect(table["@koishijs/console"]).toBe(
297
+ "npm:@koishi-ce/console@^1.0.0",
298
+ );
299
+ expect(table["@koishijs/registry"]).toBe(
300
+ "npm:@koishi-ce/registry@^1.0.0",
301
+ );
302
+ // CE 原创与上游裸名社区对应物不进清单(不拦官方生态的真实依赖)
303
+ expect(keys.includes("@koishijs/plugin-welcome")).toBe(
304
+ false,
305
+ );
306
+ expect(
307
+ keys.includes("@koishijs/plugin-theme-vanilla"),
308
+ ).toBe(false);
309
+ expect(keys.includes("@koishijs/plugin-cron")).toBe(
310
+ false,
311
+ );
312
+ // plugin-assets 的 CE 对应物无 plugin 前缀
313
+ expect(table["@koishijs/plugin-assets"]).toBe(
314
+ "npm:@koishi-ce/assets@^1.0.0",
315
+ );
316
+ // 全部值为 npm:@koishi-ce/ 前缀,键全为 @koishijs/ 上游名或 koishi 裸名
317
+ for (const key of keys) {
318
+ expect(
319
+ key === "koishi" || key.startsWith("@koishijs/"),
320
+ ).toBe(true);
321
+ expect(table[key]).toMatch(/^npm:@koishi-ce\//);
322
+ }
323
+ // buildUpstreamOverrides 与 baseManifest().overrides 同源
324
+ expect(buildUpstreamOverrides()).toEqual(table);
325
+ // renderManifest 全程透传 overrides(prod 模式也不删)
326
+ const prod = JSON.parse(
327
+ renderManifest(baseManifest(), "my-app", true),
328
+ );
329
+ expect(prod.overrides).toEqual(table);
330
+ });
package/src/index.ts CHANGED
@@ -115,7 +115,10 @@ async function getName(): Promise<string> {
115
115
  validate: (value) =>
116
116
  value?.trim() ? undefined : "项目名不能为空",
117
117
  });
118
- if (p.isCancel(answer)) process.exit(0);
118
+ // @clack/core 1.5 的 isCancel 只收窄 unique symbol,而 text() 返回泛型
119
+ // symbol,需叠加 typeof 才能把类型收窄到 string
120
+ if (p.isCancel(answer) || typeof answer !== "string")
121
+ process.exit(0);
119
122
  const trimmed = answer.trim();
120
123
  if (!trimmed) process.exit(0);
121
124
  return trimmed;
package/src/manifest.ts CHANGED
@@ -18,6 +18,7 @@ export interface Manifest {
18
18
  workspaces?: unknown;
19
19
  dependencies?: Record<string, string>;
20
20
  devDependencies?: Record<string, string>;
21
+ overrides?: Record<string, string>;
21
22
  [key: string]: unknown;
22
23
  }
23
24
 
@@ -26,7 +26,7 @@ bun run dev # 启动(开发模式,启用 HMR 热更新)
26
26
 
27
27
  推荐在控制台「插件市场」页安装(已预配 registry.koishi.chat 镜像源);也可以手动 `bun add <包名>` 后在 `koishi.yml` 中启用。
28
28
 
29
- 根依赖中的四行 npm alias——`"koishi": "npm:@koishi-ce/koishi-shim@^4.18.11"`、`"@koishijs/plugin-console": "npm:@koishi-ce/console-shim@^5.30.11"`、`"@koishijs/core": "npm:@koishi-ce/koishi-shim@4.18.11"`、`"@koishijs/loader": "npm:@koishi-ce/koishi-shim@^4.18.11"`——已把上游生态的 peer 依赖全部钉回 @koishi-ce 框架(前两行与后两行分别只涉及 koishi-shim / console-shim 两个包;**请勿删除或改写这四行**),不会形成第二份框架 / console / loader 副本。
29
+ 根依赖中的六行 npm alias——`"koishi": "npm:@koishi-ce/koishi-shim@^4.18.11"`、`"@koishijs/plugin-console": "npm:@koishi-ce/console-shim@^5.30.11"`、`"@koishijs/core": "npm:@koishi-ce/koishi-shim@4.18.11"`、`"@koishijs/loader": "npm:@koishi-ce/koishi-shim@^4.18.11"`、`"@koishijs/client": "npm:@koishi-ce/client-shim@^5.30.11"`、`"@koishijs/components": "npm:@koishi-ce/components-shim@^1.5.22"`——已把上游生态的 peer dependencies 声明全部钉回 @koishi-ce 对应包(涉及 koishi-shim / console-shim / client-shim / components-shim 四个包;**请勿删除或改写这六行**),不会形成第二份框架 / console / 前端库副本。
30
30
 
31
31
  ## 更新依赖
32
32
 
package/src/template.ts CHANGED
@@ -19,10 +19,12 @@
19
19
  * 均以 Bun 为准(ESM-only 产物,Bun 原生加载 TS / yml);脚本里的环境
20
20
  * 变量注入直接写 `NODE_ENV=... ` 前缀——bun run 走 Bun Shell,跨平台
21
21
  * 原生支持,无需 cross-env 一类的依赖;
22
- * - "koishi" 裸名与 @koishijs/core / @koishijs/loader / @koishijs/plugin-console
23
- * 上游名用 npm alias 钉到 @koishi-ce shim(版本冻结线,见 packages/shim):
24
- * 上游官方 adapter / database 插件与社区 koishi-plugin-* 的 peer 由此满足,
25
- * 不会拉入 npm 官方全家桶形成第二份框架副本;市场安装亦不改写该声明
22
+ * - "koishi" 裸名与 @koishijs/core / @koishijs/loader / @koishijs/plugin-console /
23
+ * @koishijs/client / @koishijs/components 上游名用 npm alias 钉到 @koishi-ce
24
+ * shim(版本冻结线,见 packages/shim):上游官方 adapter / database 插件与
25
+ * 社区 koishi-plugin-* 的 peer 由此满足,webui 插件写进 dependencies 的
26
+ * client / components 亦被钉住(满足性判定看落盘版本),不会拉入 npm
27
+ * 官方全家桶形成第二份框架副本;市场安装亦不改写该声明
26
28
  * (installer 的 isGuardedRequest 护栏将 npm:@koishi-ce alias 与
27
29
  * workspace: 同等保护);
28
30
  * - koishi.yml 采用配置页导出形态:插件键带 uid 实例后缀,分组带中文
@@ -83,6 +85,88 @@ export const templateFiles: Record<string, string> =
83
85
  ]),
84
86
  );
85
87
 
88
+ /**
89
+ * 上游名 → CE 对应包的 overrides 兜底映射(值统一 npm:<目标>@^1.0.0,
90
+ * 经 buildUpstreamOverrides 包装)。
91
+ *
92
+ * 六行钉名依赖「落盘版本满足声明范围」:第三方插件的声明超出冻结线
93
+ * (如未来上游升线后的 ^6)或引用清单外的上游名(如 dependencies 直接
94
+ * 依赖 @koishijs/plugin-admin / @koishijs/utils)时,官方包仍会落盘。
95
+ * overrides 是包管理器级的强制重写——不看版本满足性,把整棵依赖树中对
96
+ * 这些上游名的解析一律改指 CE 对应包,与钉名构成双层防线(napuketto
97
+ * 事件 2026-09-19 后补)。
98
+ *
99
+ * 清单 = CE 已再分发且官方同名的包,2026-09-19 逐一 npm view 核实:
100
+ * - plugin-cron 不在列(上游是裸名社区包 koishi-plugin-cron,非 @koishijs
101
+ * 作用域);
102
+ * - plugin-welcome / plugin-theme-vanilla 不在列(CE 原创,上游无此名);
103
+ * - plugin-assets 的 CE 对应物是 @koishi-ce/assets(无 plugin 前缀)。
104
+ * 新增 CE 再分发包时须同步本表与 sandbox 生成器的同款清单
105
+ * (tooling/sandbox/manifest.ts,对账测试防漂移)。
106
+ */
107
+ const UPSTREAM_OVERRIDES: Record<string, string> = {
108
+ koishi: "@koishi-ce/koishi",
109
+ "@koishijs/core": "@koishi-ce/koishi",
110
+ "@koishijs/loader": "@koishi-ce/koishi",
111
+ "@koishijs/utils": "@koishi-ce/utils",
112
+ "@koishijs/i18n-utils": "@koishi-ce/i18n-utils",
113
+ "@koishijs/client": "@koishi-ce/client",
114
+ "@koishijs/components": "@koishi-ce/components",
115
+ "@koishijs/console": "@koishi-ce/console",
116
+ "@koishijs/registry": "@koishi-ce/registry",
117
+ "@koishijs/plugin-console": "@koishi-ce/plugin-console",
118
+ "@koishijs/plugin-assets": "@koishi-ce/assets",
119
+ };
120
+
121
+ // CE 与上游同名再分发的 plugin-*:机械一一对应
122
+ for (const name of [
123
+ "actions",
124
+ "admin",
125
+ "analytics",
126
+ "assets-local",
127
+ "auth",
128
+ "bind",
129
+ "broadcast",
130
+ "callme",
131
+ "commands",
132
+ "config",
133
+ "database-sqlite",
134
+ "dataview",
135
+ "echo",
136
+ "explorer",
137
+ "help",
138
+ "hmr",
139
+ "insight",
140
+ "inspect",
141
+ "locales",
142
+ "logger",
143
+ "market",
144
+ "mock",
145
+ "notifier",
146
+ "oobe",
147
+ "proxy-agent",
148
+ "rate-limit",
149
+ "sandbox",
150
+ "server",
151
+ "server-temp",
152
+ "status",
153
+ ]) {
154
+ UPSTREAM_OVERRIDES[`@koishijs/plugin-${name}`] =
155
+ `@koishi-ce/plugin-${name}`;
156
+ }
157
+
158
+ /** 生成模板 overrides 块:键为上游名,值统一 npm:<CE 包>@^1.0.0。 */
159
+ export function buildUpstreamOverrides(): Record<
160
+ string,
161
+ string
162
+ > {
163
+ return Object.fromEntries(
164
+ Object.entries(UPSTREAM_OVERRIDES).map(
165
+ ([name, target]) => [name, `npm:${target}@^1.0.0`],
166
+ ),
167
+ );
168
+ }
169
+
86
170
  /**
87
171
  * 内置模板的 package.json 基础内容(name/version 会被 renderManifest 覆写,
88
172
  * prod 模式下 workspaces 与 devDependencies 会被移除)。
@@ -175,7 +259,19 @@ export function baseManifest(): Manifest {
175
259
  // koishi-shim(4.18.11 满足 ^4.6.11),勿指回已废弃的 loader-shim
176
260
  "@koishijs/loader":
177
261
  "npm:@koishi-ce/koishi-shim@^4.18.11",
262
+ // 上游 client 名占位:第三方 webui 插件常把 @koishijs/client 写进
263
+ // dependencies(非 peer,napuketto 实证),无归属时 Bun 装下官方
264
+ // client 并连带官方 components 全家桶;版本冻结 5.30.x 线满足 ^5.x
265
+ "@koishijs/client":
266
+ "npm:@koishi-ce/client-shim@^5.30.11",
267
+ // 上游 components 名占位:官方 client 的硬依赖,插件生态亦常直接
268
+ // 依赖(element-plus 系共享组件库);版本冻结 1.5.x 线满足 ^1.5
269
+ "@koishijs/components":
270
+ "npm:@koishi-ce/components-shim@^1.5.22",
178
271
  },
272
+ // overrides 兜底层(语义见 UPSTREAM_OVERRIDES 注释):不看版本
273
+ // 满足性强制重写整棵依赖树,拦住钉名覆盖面之外的上游声明
274
+ overrides: buildUpstreamOverrides(),
179
275
  devDependencies: {
180
276
  "@koishi-ce/client": "^1.0.0",
181
277
  "@koishi-ce/plugin-hmr": "^1.0.0",