create-koishi-ce 1.6.2 → 1.6.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.
package/lib/bin.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bun
2
- import { t as start } from "./src-bupbxcI6.mjs";
2
+ import { t as start } from "./src-D2Fw0uXq.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-bupbxcI6.mjs";
1
+ import { a as renderManifest, i as readNpmrcRegistry, n as detectAgent, r as getLocalRegistry, t as start } from "./src-D2Fw0uXq.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.2",
12
+ version: "1.6.4",
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
@@ -235,7 +202,11 @@ function baseManifest() {
235
202
  return {
236
203
  type: "module",
237
204
  packageManager: `bun@${Bun.version}`,
238
- workspaces: ["plugins/*", "external/*"],
205
+ workspaces: [
206
+ "plugins/*",
207
+ "external/**",
208
+ "!external/**/node_modules/**"
209
+ ],
239
210
  scripts: {
240
211
  start: "koishi start",
241
212
  dev: "NODE_ENV=development koishi start",
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.2",
4
+ "version": "1.6.4",
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
+ }
@@ -231,9 +231,12 @@ function expectTemplateFiles(dir: string): void {
231
231
  ) as Record<string, unknown>;
232
232
  expect(manifest["private"]).toBe(true);
233
233
  expect(manifest["version"]).toBe("0.0.0");
234
+ // globstar + 负向排除形态:external 任意深度(含克隆的 monorepo
235
+ // 子包)都是成员,node_modules 残留被排除(与 template.test.ts 同步)
234
236
  expect(manifest["workspaces"]).toEqual([
235
237
  "plugins/*",
236
- "external/*",
238
+ "external/**",
239
+ "!external/**/node_modules/**",
237
240
  ]);
238
241
  }
239
242
 
@@ -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 远程模板", () => {
@@ -224,6 +224,14 @@ test("renderManifest 渲染内置模板:常规改写生效,prod 模式保留
224
224
  expect(output.dependencies.koishi).toBe(
225
225
  "npm:@koishi-ce/koishi-shim@^4.18.11",
226
226
  );
227
+ // workspaces 是 globstar + 负向排除形态:external 任意深度(含克隆的
228
+ // monorepo 子包)都是成员,node_modules 排除搬迁残留——配置页的
229
+ // 「添加插件」列表按同一份声明展开收录,写法回退即嵌套不可见
230
+ expect(output.workspaces).toEqual([
231
+ "plugins/*",
232
+ "external/**",
233
+ "!external/**/node_modules/**",
234
+ ]);
227
235
 
228
236
  const prod = JSON.parse(
229
237
  renderManifest(baseManifest(), "my-app", true),
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";
@@ -43,7 +43,7 @@ bun run update # 安全更新:只更新 @koishi-ce/* 生态位依赖
43
43
  - `bun run new <名称>` —— 生成插件骨架到 `external/`(`--console` 附带控制台前端扩展)
44
44
  - `bun run clone <仓库>` —— 克隆已有插件源码到 `external/` 本地联动调试
45
45
 
46
- 两种来源的插件都在 `koishi.yml` 中以相对路径引用(如 `./plugins/my-plugin`、`./external/my-plugin`)即可启用;Bun 直接加载 TypeScript 源码,无需预编译。
46
+ 两种来源的插件都在 `koishi.yml` 中以相对路径引用(如 `./plugins/my-plugin`、`./external/my-plugin`)即可启用;Bun 直接加载 TypeScript 源码,无需预编译。克隆来的 **monorepo 形态插件仓库**(插件在 `packages/` 等子目录)无需平铺——`workspaces` 声明的 `external/**` 通配任意深度,控制台「添加插件」列表同样按此声明收录,子包直接可见可启用(搬迁自其它包管理器的仓库若带着旧 `node_modules`,负向声明已将其排除,建议顺手删除节省空间)。
47
47
 
48
48
  ## 插件构建与发布
49
49
 
package/src/template.ts CHANGED
@@ -92,7 +92,16 @@ export function baseManifest(): Manifest {
92
92
  type: "module",
93
93
  // 本项目只用 Bun:钉住创建时的 Bun 版本(bun run 亦据此选择解释器)
94
94
  packageManager: `bun@${Bun.version}`,
95
- workspaces: ["plugins/*", "external/*"],
95
+ // globstar + 负向排除(Bun workspaces 支持完整 glob 语法):external
96
+ // 下任意深度的插件包(含克隆来的 monorepo 形态 packages/ 子包)都是
97
+ // workspace 成员;node_modules 排除搬迁残留的依赖目录(包管理器
98
+ // 对其另有管理,混入成员会污染解析)。配置页的「添加插件」列表按
99
+ // 同一份声明展开收录,声明写多深列表就能看多深
100
+ workspaces: [
101
+ "plugins/*",
102
+ "external/**",
103
+ "!external/**/node_modules/**",
104
+ ],
96
105
  scripts: {
97
106
  start: "koishi start",
98
107
  // bun run 走 Bun Shell,`NODE_ENV=...` 前缀天然跨平台,无需 cross-env
@@ -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
- });