create-koishi-ce 1.6.3 → 1.7.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-C4V0N-Vc.mjs";
2
+ import { t as start } from "./src-Cj4uFpkr.mjs";
3
3
  //#region src/bin.ts
4
4
  /**
5
5
  * create-koishi-ce 的 CLI 可执行入口:shebang 由 rolldown 原样保留到
package/lib/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { getLocalRegistry, readNpmrcRegistry } from "@koishi-ce/utils";
1
2
  //#region src/manifest.d.ts
2
3
  /**
3
4
  * 模板项目 package.json 的类型与改写(纯函数域,无副作用):定义本流程
@@ -23,19 +24,6 @@ interface Manifest {
23
24
  */
24
25
  export declare function renderManifest(source: Manifest, project: string, prod: boolean): string;
25
26
  //#endregion
26
- //#region src/registry.d.ts
27
- /**
28
- * 从单个 .npmrc 文件提取 registry 配置项(非注释、非 scoped 的 registry= 行)。
29
- * 文件不存在或未配置时返回 undefined,读文件异常一律静默吞掉。
30
- */
31
- export declare function readNpmrcRegistry(file: string): string | undefined;
32
- /**
33
- * 读取本机 npm registry 配置(优先级对齐 npm 自身:环境变量 > 项目
34
- * .npmrc > 用户 ~/.npmrc)。任何一步都拿不到时返回 undefined,由调用方
35
- * 回落官方源。
36
- */
37
- export declare function getLocalRegistry(cwd?: string, userHome?: string): string | undefined;
38
- //#endregion
39
27
  //#region src/utils.d.ts
40
28
  /**
41
29
  * 探测后续安装/启动使用的包管理器(Bun-first):yarn / pnpm 用户跟随其
@@ -51,4 +39,4 @@ export declare function detectAgent(): string;
51
39
  */
52
40
  export declare function start(): Promise<void>;
53
41
  //#endregion
54
- export type { Manifest };
42
+ export { type Manifest, getLocalRegistry, readNpmrcRegistry };
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-C4V0N-Vc.mjs";
1
+ import { a as renderManifest, i as readNpmrcRegistry, n as detectAgent, r as getLocalRegistry, t as start } from "./src-Cj4uFpkr.mjs";
2
2
  export { detectAgent, getLocalRegistry, readNpmrcRegistry, renderManifest, start };
@@ -3,18 +3,18 @@ import { basename, join, relative } from "node:path";
3
3
  import { parseArgs } from "node:util";
4
4
  import * as p from "@clack/prompts";
5
5
  import pc from "picocolors";
6
- import { homedir } from "node:os";
6
+ import { getLocalRegistry, readNpmrcRegistry } from "@koishi-ce/utils";
7
7
  import { downloadTemplate } from "giget";
8
8
  //#region package.json
9
9
  var package_default = {
10
10
  name: "create-koishi-ce",
11
11
  description: "Setup a Koishi application",
12
- version: "1.6.3",
12
+ version: "1.7.0",
13
13
  type: "module",
14
14
  main: "./lib/index.mjs",
15
15
  module: "./lib/index.mjs",
16
16
  types: "./lib/index.d.ts",
17
- bin: { "create-koishi-ce": "./lib/bin.mjs" },
17
+ bin: { "create-koishi-ce": "lib/bin.mjs" },
18
18
  files: ["lib", "src"],
19
19
  contributors: ["Shigma <shigma10826@gmail.com>", "Oppenheymu <oppenheymu@gmail.com>"],
20
20
  license: "MIT",
@@ -40,6 +40,7 @@ var package_default = {
40
40
  ],
41
41
  dependencies: {
42
42
  "@clack/prompts": "^1.7.0",
43
+ "@koishi-ce/utils": "workspace:*",
43
44
  "picocolors": "^1.1.1",
44
45
  "giget": "^3.3.1"
45
46
  },
@@ -71,40 +72,6 @@ function renderManifest(source, project, prod) {
71
72
  return `${JSON.stringify(meta, null, 2)}\n`;
72
73
  }
73
74
  //#endregion
74
- //#region src/registry.ts
75
- /**
76
- * 本机 npm registry 配置探测(纯函数域,零子进程、零网络):优先级对齐
77
- * npm 自身(环境变量 > 项目 .npmrc > 用户 ~/.npmrc)。刻意不 spawn 子进程
78
- * 探测——既有实现按 user-agent 选 `bun config get registry`,而 Bun 没有
79
- * config 子命令,bunx 场景下子进程退出码 1 直接炸掉脚手架;读 npmrc 是
80
- * 零依赖、零子进程的等价路径。远程模板下载流程见 remote.ts,不在本文件。
81
- */
82
- /**
83
- * 从单个 .npmrc 文件提取 registry 配置项(非注释、非 scoped 的 registry= 行)。
84
- * 文件不存在或未配置时返回 undefined,读文件异常一律静默吞掉。
85
- */
86
- function readNpmrcRegistry(file) {
87
- try {
88
- for (const line of readFileSync(file, "utf8").split(/\r?\n/)) {
89
- const value = /^\s*registry\s*=\s*(\S+)\s*$/.exec(line)?.[1];
90
- if (value) return value;
91
- }
92
- } catch {}
93
- }
94
- /**
95
- * 读取本机 npm registry 配置(优先级对齐 npm 自身:环境变量 > 项目
96
- * .npmrc > 用户 ~/.npmrc)。任何一步都拿不到时返回 undefined,由调用方
97
- * 回落官方源。
98
- */
99
- function getLocalRegistry(cwd = process.cwd(), userHome = homedir()) {
100
- const candidates = [
101
- Bun.env["npm_config_registry"],
102
- readNpmrcRegistry(join(cwd, ".npmrc")),
103
- readNpmrcRegistry(join(userHome, ".npmrc"))
104
- ];
105
- for (const candidate of candidates) if (candidate?.startsWith("https://") || candidate?.startsWith("http://")) return candidate;
106
- }
107
- //#endregion
108
75
  //#region src/remote.ts
109
76
  /**
110
77
  * 远程模板分支(--template <包名>)的下载-解包-改写全流程:拉取 npm
@@ -190,10 +157,12 @@ function writePackageJson(rootDir, project, prod) {
190
157
  * 均以 Bun 为准(ESM-only 产物,Bun 原生加载 TS / yml);脚本里的环境
191
158
  * 变量注入直接写 `NODE_ENV=... ` 前缀——bun run 走 Bun Shell,跨平台
192
159
  * 原生支持,无需 cross-env 一类的依赖;
193
- * - "koishi" 裸名与 @koishijs/core / @koishijs/loader / @koishijs/plugin-console
194
- * 上游名用 npm alias 钉到 @koishi-ce shim(版本冻结线,见 packages/shim):
195
- * 上游官方 adapter / database 插件与社区 koishi-plugin-* 的 peer 由此满足,
196
- * 不会拉入 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
+ * 官方全家桶形成第二份框架副本;市场安装亦不改写该声明
197
166
  * (installer 的 isGuardedRequest 护栏将 npm:@koishi-ce alias 与
198
167
  * workspace: 同等保护);
199
168
  * - koishi.yml 采用配置页导出形态:插件键带 uid 实例后缀,分组带中文
@@ -288,7 +257,9 @@ function baseManifest() {
288
257
  koishi: "npm:@koishi-ce/koishi-shim@^4.18.11",
289
258
  "@koishijs/plugin-console": "npm:@koishi-ce/console-shim@^5.30.11",
290
259
  "@koishijs/core": "npm:@koishi-ce/koishi-shim@4.18.11",
291
- "@koishijs/loader": "npm:@koishi-ce/koishi-shim@^4.18.11"
260
+ "@koishijs/loader": "npm:@koishi-ce/koishi-shim@^4.18.11",
261
+ "@koishijs/client": "npm:@koishi-ce/client-shim@^5.30.11",
262
+ "@koishijs/components": "npm:@koishi-ce/components-shim@^1.5.22"
292
263
  },
293
264
  devDependencies: {
294
265
  "@koishi-ce/client": "^1.0.0",
@@ -423,7 +394,7 @@ async function getName() {
423
394
  initialValue: "koishi-app",
424
395
  validate: (value) => value?.trim() ? void 0 : "项目名不能为空"
425
396
  });
426
- if (p.isCancel(answer)) process.exit(0);
397
+ if (p.isCancel(answer) || typeof answer !== "string") process.exit(0);
427
398
  const trimmed = answer.trim();
428
399
  if (!trimmed) process.exit(0);
429
400
  return trimmed;
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "create-koishi-ce",
3
3
  "description": "Setup a Koishi application",
4
- "version": "1.6.3",
4
+ "version": "1.7.0",
5
5
  "type": "module",
6
6
  "main": "./lib/index.mjs",
7
7
  "module": "./lib/index.mjs",
8
8
  "types": "./lib/index.d.ts",
9
9
  "bin": {
10
- "create-koishi-ce": "./lib/bin.mjs"
10
+ "create-koishi-ce": "lib/bin.mjs"
11
11
  },
12
12
  "files": [
13
13
  "lib",
@@ -44,6 +44,7 @@
44
44
  ],
45
45
  "dependencies": {
46
46
  "@clack/prompts": "^1.7.0",
47
+ "@koishi-ce/utils": "^1.1.0",
47
48
  "picocolors": "^1.1.1",
48
49
  "giget": "^3.3.1"
49
50
  },
@@ -56,4 +57,4 @@
56
57
  },
57
58
  "./package.json": "./package.json"
58
59
  }
59
- }
60
+ }
@@ -18,7 +18,7 @@ import {
18
18
  rmSync,
19
19
  writeFileSync,
20
20
  } from "node:fs";
21
- import { tmpdir } from "node:os";
21
+ import { homedir, tmpdir } from "node:os";
22
22
  import { join } from "node:path";
23
23
  import { tarPack } from "./tar-pack.ts";
24
24
 
@@ -203,13 +203,19 @@ function reset(sc: typeof scenario): void {
203
203
  recursive: true,
204
204
  force: true,
205
205
  });
206
- // giget 把 tarball 缓存到系统临时目录(win32 为 tmpdir()/giget,不受
207
- // XDG_CACHE_HOME 影响);逐用例清理,避免上一场景的缓存(tarball-404
208
- // 的缺失或 corrupt 的损坏归档)被 giget 的「下载失败回退缓存」吞掉
209
- rmSync(join(tmpdir(), "giget"), {
210
- recursive: true,
211
- force: true,
212
- });
206
+ // giget 缓存位置随平台而异(win32 为 tmpdir()/giget,POSIX 跟随
207
+ // XDG_CACHE_HOME——默认 ~/.cache);逐用例清理,避免上一场景的缓存
208
+ // (tarball-404 的缺失或 corrupt 的损坏归档)被 giget
209
+ // 「下载失败回退缓存」吞掉
210
+ const cacheRoot =
211
+ process.env["XDG_CACHE_HOME"] ??
212
+ join(homedir(), ".cache");
213
+ for (const dir of [
214
+ join(tmpdir(), "giget"),
215
+ join(cacheRoot, "giget"),
216
+ ]) {
217
+ rmSync(dir, { recursive: true, force: true });
218
+ }
213
219
  }
214
220
 
215
221
  describe("create-koishi-ce 远程模板", () => {
@@ -10,13 +10,16 @@ import {
10
10
 
11
11
  test("内置模板依赖纯度:不含任何 @koishijs / koishi-plugin 官方生态包", () => {
12
12
  const { dependencies, devDependencies } = baseManifest();
13
- // 四个上游名是刻意的 npm alias 占位(koishi 裸名 / @koishijs/plugin-console /
14
- // @koishijs/core / @koishijs/loader),其余必须是 @koishi-ce 作用域
13
+ // 六个上游名是刻意的 npm alias 占位(koishi 裸名 / @koishijs/plugin-console /
14
+ // @koishijs/core / @koishijs/loader / @koishijs/client / @koishijs/components),
15
+ // 其余必须是 @koishi-ce 作用域
15
16
  const guarded = new Set([
16
17
  "koishi",
17
18
  "@koishijs/plugin-console",
18
19
  "@koishijs/core",
19
20
  "@koishijs/loader",
21
+ "@koishijs/client",
22
+ "@koishijs/components",
20
23
  ]);
21
24
  for (const key of Object.keys(dependencies ?? {})) {
22
25
  expect(
@@ -96,6 +99,15 @@ test("内置模板钉住 console / core / loader 上游 peer 名,防 Bun 自
96
99
  expect(dependencies?.["@koishijs/loader"]).toBe(
97
100
  "npm:@koishi-ce/koishi-shim@^4.18.11",
98
101
  );
102
+ // webui 插件把 client 写进 dependencies 的形态(napuketto 实证):
103
+ // 版本冻结 5.30.x 线满足 ^5.x,官方 client(连带 components)不再落盘
104
+ expect(dependencies?.["@koishijs/client"]).toBe(
105
+ "npm:@koishi-ce/client-shim@^5.30.11",
106
+ );
107
+ // 官方 client 的硬依赖、插件生态常直接依赖;冻结 1.5.x 线满足 ^1.5
108
+ expect(dependencies?.["@koishijs/components"]).toBe(
109
+ "npm:@koishi-ce/components-shim@^1.5.22",
110
+ );
99
111
  });
100
112
 
101
113
  test("内置模板静态文件齐备,koishi.yml 预配 market 镜像源", () => {
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/registry.ts CHANGED
@@ -2,60 +2,13 @@
2
2
  // Copyright (c) 2026-present Koishi-CE contributors.
3
3
 
4
4
  /**
5
- * 本机 npm registry 配置探测(纯函数域,零子进程、零网络):优先级对齐
6
- * npm 自身(环境变量 > 项目 .npmrc > 用户 ~/.npmrc)。刻意不 spawn 子进程
7
- * 探测——既有实现按 user-agent `bun config get registry`,而 Bun 没有
8
- * config 子命令,bunx 场景下子进程退出码 1 直接炸掉脚手架;读 npmrc 是
9
- * 零依赖、零子进程的等价路径。远程模板下载流程见 remote.ts,不在本文件。
5
+ * 本机 npm registry 配置探测。
6
+ *
7
+ * 实现已收敛到 @koishi-ce/utils npm-registry 模块(与 market 插件的
8
+ * installer 共享同一实现),此处按原公共 API 再导出,调用方与测试的
9
+ * 导入路径不变。远程模板下载流程见 remote.ts,不在本文件。
10
10
  */
11
- import { readFileSync } from "node:fs";
12
- import { homedir } from "node:os";
13
- import { join } from "node:path";
14
-
15
- /**
16
- * 从单个 .npmrc 文件提取 registry 配置项(非注释、非 scoped 的 registry= 行)。
17
- * 文件不存在或未配置时返回 undefined,读文件异常一律静默吞掉。
18
- */
19
- export function readNpmrcRegistry(
20
- file: string,
21
- ): string | undefined {
22
- try {
23
- for (const line of readFileSync(file, "utf8").split(
24
- /\r?\n/,
25
- )) {
26
- const matched = /^\s*registry\s*=\s*(\S+)\s*$/.exec(
27
- line,
28
- );
29
- const value = matched?.[1];
30
- if (value) return value;
31
- }
32
- } catch {
33
- // registry 探测不允许打断主流程,任何读取失败都视为未配置
34
- }
35
- return undefined;
36
- }
37
-
38
- /**
39
- * 读取本机 npm registry 配置(优先级对齐 npm 自身:环境变量 > 项目
40
- * .npmrc > 用户 ~/.npmrc)。任何一步都拿不到时返回 undefined,由调用方
41
- * 回落官方源。
42
- */
43
- export function getLocalRegistry(
44
- cwd: string = process.cwd(),
45
- userHome: string = homedir(),
46
- ): string | undefined {
47
- const candidates = [
48
- Bun.env["npm_config_registry"],
49
- readNpmrcRegistry(join(cwd, ".npmrc")),
50
- readNpmrcRegistry(join(userHome, ".npmrc")),
51
- ];
52
- for (const candidate of candidates) {
53
- if (
54
- candidate?.startsWith("https://") ||
55
- candidate?.startsWith("http://")
56
- ) {
57
- return candidate;
58
- }
59
- }
60
- return undefined;
61
- }
11
+ export {
12
+ getLocalRegistry,
13
+ readNpmrcRegistry,
14
+ } from "@koishi-ce/utils";
@@ -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 实例后缀,分组带中文
@@ -175,6 +177,15 @@ export function baseManifest(): Manifest {
175
177
  // koishi-shim(4.18.11 满足 ^4.6.11),勿指回已废弃的 loader-shim
176
178
  "@koishijs/loader":
177
179
  "npm:@koishi-ce/koishi-shim@^4.18.11",
180
+ // 上游 client 名占位:第三方 webui 插件常把 @koishijs/client 写进
181
+ // dependencies(非 peer,napuketto 实证),无归属时 Bun 装下官方
182
+ // client 并连带官方 components 全家桶;版本冻结 5.30.x 线满足 ^5.x
183
+ "@koishijs/client":
184
+ "npm:@koishi-ce/client-shim@^5.30.11",
185
+ // 上游 components 名占位:官方 client 的硬依赖,插件生态亦常直接
186
+ // 依赖(element-plus 系共享组件库);版本冻结 1.5.x 线满足 ^1.5
187
+ "@koishijs/components":
188
+ "npm:@koishi-ce/components-shim@^1.5.22",
178
189
  },
179
190
  devDependencies: {
180
191
  "@koishi-ce/client": "^1.0.0",
@@ -1,81 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- // Copyright (c) 2026-present Koishi-CE contributors.
3
-
4
- import { expect, test } from "bun:test";
5
- import {
6
- mkdtempSync,
7
- rmSync,
8
- writeFileSync,
9
- } from "node:fs";
10
- import { tmpdir } from "node:os";
11
- import { join } from "node:path";
12
- import {
13
- getLocalRegistry,
14
- readNpmrcRegistry,
15
- } from "../index.ts";
16
-
17
- test("readNpmrcRegistry:提取首个 registry= 行,忽略注释与空行", () => {
18
- const dir = mkdtempSync(join(tmpdir(), "ckc-npmrc-"));
19
- const file = join(dir, ".npmrc");
20
- writeFileSync(
21
- file,
22
- "# 注释行\n; 另一种注释\n\nstrict-ssl=false\nregistry=https://registry.npmmirror.com/\r\n@scope:registry=https://example.com/\n",
23
- );
24
- expect(readNpmrcRegistry(file)).toBe(
25
- "https://registry.npmmirror.com/",
26
- );
27
- rmSync(dir, { recursive: true, force: true });
28
- });
29
-
30
- test("readNpmrcRegistry:文件不存在或未配置时返回 undefined 而不抛错", () => {
31
- expect(
32
- readNpmrcRegistry(
33
- join(tmpdir(), "ckc-不存在", ".npmrc"),
34
- ),
35
- ).toBeUndefined();
36
- const dir = mkdtempSync(join(tmpdir(), "ckc-npmrc-"));
37
- const file = join(dir, ".npmrc");
38
- writeFileSync(file, "strict-ssl=false\n");
39
- expect(readNpmrcRegistry(file)).toBeUndefined();
40
- rmSync(dir, { recursive: true, force: true });
41
- });
42
-
43
- test("getLocalRegistry:环境变量优先且校验协议,非法值跳过", () => {
44
- const key = "npm_config_registry";
45
- const isolated = mkdtempSync(
46
- join(tmpdir(), "ckc-npmrc-"),
47
- );
48
- Bun.env[key] = "https://registry.example.com/";
49
- expect(getLocalRegistry(isolated, isolated)).toBe(
50
- "https://registry.example.com/",
51
- );
52
- // 非 http(s) 的值视为未配置,继续走后续候选
53
- Bun.env[key] = "ftp://not-a-registry/";
54
- expect(
55
- getLocalRegistry(isolated, isolated),
56
- ).toBeUndefined();
57
- delete Bun.env[key];
58
- rmSync(isolated, { recursive: true, force: true });
59
- });
60
-
61
- test("getLocalRegistry:项目 .npmrc 优先于用户级 .npmrc,均无配置时返回 undefined", () => {
62
- const key = "npm_config_registry";
63
- delete Bun.env[key];
64
- const dir = mkdtempSync(join(tmpdir(), "ckc-npmrc-"));
65
- const emptyHome = mkdtempSync(
66
- join(tmpdir(), "ckc-home-"),
67
- );
68
- writeFileSync(
69
- join(dir, ".npmrc"),
70
- "registry=http://localhost:4873/\n",
71
- );
72
- expect(getLocalRegistry(dir, emptyHome)).toBe(
73
- "http://localhost:4873/",
74
- );
75
- // 目录与用户级均无 .npmrc 时返回 undefined,主流程回落官方源
76
- expect(
77
- getLocalRegistry(emptyHome, emptyHome),
78
- ).toBeUndefined();
79
- rmSync(dir, { recursive: true, force: true });
80
- rmSync(emptyHome, { recursive: true, force: true });
81
- });