create-koishi-ce 1.2.1 → 1.3.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 ADDED
@@ -0,0 +1,77 @@
1
+ # create-koishi-ce
2
+
3
+ **简体中文** | [English](#english)
4
+
5
+ Koishi CE 生态的项目脚手架。一条命令生成以 Bun 为运行时、纯 `@koishi-ce` 依赖的完整机器人项目:预装常用插件、钉住上游包名 alias、预写分组配置,开箱即可 `koishi start`。
6
+
7
+ ```bash
8
+ bunx create-koishi-ce my-app
9
+ # 或
10
+ npm create koishi-ce my-app
11
+ ```
12
+
13
+ ## 选项
14
+
15
+ | 选项 | 默认值 | 说明 |
16
+ | --- | --- | --- |
17
+ | `[名称]` | 交互询问(初始值 koishi-app) | 项目名,同时作为目标目录名 |
18
+ | `-t, --template <名称>` | 内置模板 | 改用 npm registry 上的远程模板包(逃生舱) |
19
+ | `-r, --ref <引用>` | latest | 远程模板的版本引用 |
20
+ | `-f, --forced` | - | 强制清空目标目录 |
21
+ | `-g, --git` | - | 初始化 git 仓库(分支取 init.defaultBranch,未配置则 main) |
22
+ | `--registry <地址>` | 参数 > npm_config_registry > .npmrc > 官方源 | npm registry |
23
+ | `-p, --prod` | - | 生产模式:删除模板的 workspaces 与 devDependencies |
24
+ | `-y, --yes` | - | 跳过全部询问(含跳过依赖安装) |
25
+
26
+ 交互流程:项目名;目标目录非空时确认是否清空;最后确认是否立即安装依赖并启动(包管理器一律使用 Bun)。
27
+
28
+ ## 生成的项目
29
+
30
+ - **package.json**:`type: module`、`packageManager` 钉 Bun、workspaces 含 `plugins/*` 与 `external/*`;dependencies 预装全套 `@koishi-ce` 常用插件(console、config、market、auth、admin、help、sandbox 等),并预置四行 npm alias 钉住上游名——`koishi` / `@koishijs/core` / `@koishijs/loader` 指向 `@koishi-ce/koishi-shim`、`@koishijs/plugin-console` 指向 `@koishi-ce/console-shim`,社区插件由此全部解析到 CE 框架;
31
+ - **koishi.yml**:按 server(端口 5140-5149)/ basic / console(自动打开、市场指向 registry.koishi.chat 镜像)/ storage / adapter / develop(开发模式启用热重载)分组预写;官方 adapter / database 插件以 `~` 停用条目预写,可按需启用;
32
+ - **开发工具链**:devDependencies 预置 `@koishi-ce/client`、`@koishi-ce/plugin-hmr` 与 `@koishi-ce/scripts`(`koishi-scripts setup` 可在 external/ 下继续创建插件项目)。
33
+
34
+ 不预装任何 adapter 与 database——官方版本可后续从市场安装,peer 已被 alias 钉住不会形成双实例。
35
+
36
+ ## 许可证
37
+
38
+ [MIT](https://github.com/Koishi-CE/koishi/blob/main/LICENSE),本仓库原创作品,版权归 Koishi-CE 贡献者,见 [NOTICE](https://github.com/Koishi-CE/koishi/blob/main/NOTICE)。
39
+
40
+ ---
41
+
42
+ ## English
43
+
44
+ The project scaffold for the Koishi CE ecosystem. One command generates a complete bot project on the Bun runtime with pure `@koishi-ce` dependencies: common plugins preinstalled, upstream-name aliases pinned, grouped config prewritten — ready for `koishi start` out of the box.
45
+
46
+ ```bash
47
+ bunx create-koishi-ce my-app
48
+ # or
49
+ npm create koishi-ce my-app
50
+ ```
51
+
52
+ ## Options
53
+
54
+ | Option | Default | Description |
55
+ | --- | --- | --- |
56
+ | `[name]` | prompted (initial koishi-app) | Project name, also the target directory |
57
+ | `-t, --template <name>` | built-in template | Use a remote template package from the npm registry (escape hatch) |
58
+ | `-r, --ref <ref>` | latest | Version ref of the remote template |
59
+ | `-f, --forced` | - | Force-clean the target directory |
60
+ | `-g, --git` | - | Initialize a git repository (branch from init.defaultBranch, fallback main) |
61
+ | `--registry <url>` | arg > npm_config_registry > .npmrc > official | npm registry |
62
+ | `-p, --prod` | - | Production mode: drop workspaces and devDependencies from the template |
63
+ | `-y, --yes` | - | Skip all prompts (including dependency installation) |
64
+
65
+ Interactive flow: project name; confirm cleaning a non-empty target directory; confirm installing dependencies and starting right away (Bun is always the package manager).
66
+
67
+ ## Generated project
68
+
69
+ - **package.json** — `type: module`, `packageManager` pinned to Bun, workspaces covering `plugins/*` and `external/*`; dependencies preinstall the common `@koishi-ce` plugin set (console, config, market, auth, admin, help, sandbox, etc.) plus the four npm-alias lines pinning the upstream names (`koishi` / `@koishijs/core` / `@koishijs/loader` to `@koishi-ce/koishi-shim`, `@koishijs/plugin-console` to `@koishi-ce/console-shim`), so community plugins all resolve to the CE framework.
70
+ - **koishi.yml** — grouped prewrites for server (ports 5140-5149), basic, console (auto-open, market pointed at the registry.koishi.chat mirror), storage, adapter and develop (HMR in development mode); official adapter / database plugins are prewritten as `~`-disabled entries.
71
+ - **Toolchain** — devDependencies include `@koishi-ce/client`, `@koishi-ce/plugin-hmr` and `@koishi-ce/scripts` (`koishi-scripts setup` scaffolds further plugin projects under external/).
72
+
73
+ No adapter or database is preinstalled — official ones can be installed from the market later; their peers are already pinned by the aliases.
74
+
75
+ ## License
76
+
77
+ [MIT](https://github.com/Koishi-CE/koishi/blob/main/LICENSE), original work of this repository, copyright Koishi-CE contributors — see [NOTICE](https://github.com/Koishi-CE/koishi/blob/main/NOTICE).
package/lib/bin.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bun
2
- import { a as start } from "./src-CwJZjC5d.mjs";
2
+ import { a as start } from "./src-DiZgIQu5.mjs";
3
3
  //#region src/bin.ts
4
4
  /**
5
5
  * create-koishi-ce 的 CLI 可执行入口:shebang 由 rolldown 原样保留到
package/lib/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { a as start, i as renderManifest, n as getLocalRegistry, r as readNpmrcRegistry, t as detectAgent } from "./src-CwJZjC5d.mjs";
1
+ import { a as start, i as renderManifest, n as getLocalRegistry, r as readNpmrcRegistry, t as detectAgent } from "./src-DiZgIQu5.mjs";
2
2
  export { detectAgent, getLocalRegistry, readNpmrcRegistry, renderManifest, start };
@@ -1,17 +1,18 @@
1
1
  import { spawnSync } from "node:child_process";
2
2
  import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
3
3
  import { homedir } from "node:os";
4
- import { basename, join, relative } from "node:path";
4
+ import { basename, dirname, join, relative } from "node:path";
5
5
  import { Readable } from "node:stream";
6
6
  import kleur from "kleur";
7
7
  import prompts from "prompts";
8
8
  import { extract } from "tar";
9
9
  import parse from "yargs-parser";
10
+ import { fileURLToPath } from "node:url";
10
11
  //#region package.json
11
12
  var package_default = {
12
13
  name: "create-koishi-ce",
13
14
  description: "Setup a Koishi application",
14
- version: "1.2.1",
15
+ version: "1.3.0",
15
16
  type: "module",
16
17
  main: "./lib/index.mjs",
17
18
  module: "./lib/index.mjs",
@@ -62,98 +63,57 @@ var package_default = {
62
63
  };
63
64
  //#endregion
64
65
  //#region src/template.ts
65
- /** 模板静态文件(相对项目根的路径 → 文件内容),package.json 另行渲染 */
66
- const templateFiles = {
67
- ".env": [
68
- "GITHUB_MIRROR = https://ghproxy.com/https://github.com",
69
- "GITHUB_CONTENT_MIRROR = https://ghproxy.com/https://raw.githubusercontent.com",
70
- "GRAVATAR_MIRROR = https://cravatar.cn"
71
- ].join("\n"),
72
- ".gitignore": ["node_modules/", "data/"].join("\n"),
73
- "koishi.yml": [
74
- "plugins:",
75
- " group:server:",
76
- " server:",
77
- " port: 5140",
78
- " maxPort: 5149",
79
- " group:basic:",
80
- " ~admin: {}",
81
- " ~bind: {}",
82
- " commands: {}",
83
- " help: {}",
84
- " http: {}",
85
- " ~inspect: {}",
86
- " locales: {}",
87
- " proxy-agent: {}",
88
- " group:console:",
89
- " actions: {}",
90
- " ~analytics: {}",
91
- " ~auth: {}",
92
- " config: {}",
93
- " console:",
94
- " open: true",
95
- " explorer: {}",
96
- " insight: {}",
97
- " logger: {}",
98
- " market:",
99
- " search:",
100
- " endpoint: https://registry.koishi.chat/index.json",
101
- " notifier: {}",
102
- " oobe: {}",
103
- " sandbox: {}",
104
- " status: {}",
105
- " group:develop:",
106
- " $if: env.NODE_ENV === 'development'",
107
- " hmr:",
108
- " root: ."
109
- ].join("\n"),
110
- "tsconfig.json": [
111
- "{",
112
- " \"compilerOptions\": {",
113
- " \"target\": \"ESNext\",",
114
- " \"module\": \"ESNext\",",
115
- " \"moduleResolution\": \"bundler\",",
116
- " \"lib\": [\"ESNext\"],",
117
- " \"types\": [\"bun-types\"],",
118
- " \"strict\": true,",
119
- " \"skipLibCheck\": true,",
120
- " \"noEmit\": true,",
121
- " \"allowImportingTsExtensions\": true,",
122
- " \"verbatimModuleSyntax\": true,",
123
- " \"erasableSyntaxOnly\": true",
124
- " },",
125
- " \"include\": [\"plugins/*/src\", \"external/*/src\"]",
126
- "}"
127
- ].join("\n"),
128
- "README.md": `# Koishi 机器人项目
129
-
130
- 由 \`bun create koishi-ce\` 生成,运行于 [@koishi-ce 社区再分发版](https://github.com/Koishi-CE/koishi) 生态。
131
-
132
- ## 环境要求
133
-
134
- - [Bun](https://bun.sh) ≥ 1.2(运行时:koishi CLI 与插件加载链以 Bun 为准)
135
-
136
- ## 快速开始
137
-
138
- \`\`\`bash
139
- bun install
140
- bun run start # 启动(生产模式)
141
- bun run dev # 启动(开发模式,启用 HMR 热更新)
142
- \`\`\`
143
-
144
- 启动后访问控制台:<http://127.0.0.1:5140>
145
-
146
- ## 安装插件
147
-
148
- 推荐在控制台「插件市场」页安装(已预配 registry.koishi.chat 镜像源);也可以手动 \`bun add <包名>\` 后在 \`koishi.yml\` 中启用。
149
-
150
- 上游官方 adapter(如 adapter-discord / adapter-telegram)、数据库插件(如 database-sqlite)与社区 koishi-plugin-* 插件均可直接安装:根依赖中的四行 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 副本。analytics 等依赖数据库的插件请先安装数据库插件,再去掉配置中对应的 \`~\` 前缀启用。
151
-
152
- ## 自定义插件
153
-
154
- 在 \`plugins/\` 目录下创建插件包(可用 \`bun run new <名称>\` 生成骨架),在 \`koishi.yml\` 中以相对路径引用(如 \`./plugins/my-plugin\`)即可启用;Bun 直接加载 TypeScript 源码,无需预编译。
155
- `
66
+ /**
67
+ * 内置项目模板(create-koishi-ce 的默认模板)。
68
+ *
69
+ * 历史包袱修正:本脚手架最初直接下载上游官方 @koishijs/boilerplate 解包
70
+ * 生成项目,产物依赖全是 npm 官方包(koishi / @koishijs/*),完全绕开了
71
+ * 本仓的 @koishi-ce 再分发生态(官方 market 还带 Bun 下必炸的 get-registry)。
72
+ * 默认模板改为内置的纯 @koishi-ce 依赖集;确需上游官方模板时用
73
+ * --template <包名> 走 npm 远程下载(见 index.ts scaffoldRemote)。
74
+ *
75
+ * 模板的静态文本一律放在 src/template/ 下的真实文件里(本模块只负责
76
+ * 定位与读取,不再内嵌字符串常量)。npm 包的 files 含 src,因此 lib
77
+ * 产物与 src 直跑两种形态都能按相对路径定位到模板目录。
78
+ *
79
+ * 模板要点:
80
+ * - 运行时 Bun:koishi CLI(@koishi-ce/koishi 的 bin)与 loader 插件加载链
81
+ * 均以 Bun 为准(ESM-only 产物,Bun 原生加载 TS / yml);脚本里的环境
82
+ * 变量注入直接写 `NODE_ENV=... ` 前缀——bun run 走 Bun Shell,跨平台
83
+ * 原生支持,无需 cross-env 一类的依赖;
84
+ * - "koishi" 裸名与 @koishijs/core / @koishijs/loader / @koishijs/plugin-console
85
+ * 上游名用 npm alias 钉到 @koishi-ce shim(版本冻结线,见 packages/shim):
86
+ * 上游官方 adapter / database 插件与社区 koishi-plugin-* 的 peer 由此满足,
87
+ * 不会拉入 npm 官方全家桶形成第二份框架副本;市场安装亦不改写该声明
88
+ * (installer 的 isGuardedRequest 护栏将 npm:@koishi-ce alias 与
89
+ * workspace: 同等保护);
90
+ * - koishi.yml 对齐官方实例的预写策略:控制台与基础插件全量预装(依赖
91
+ * 数据库的保持 ~ 禁用);本仓不再分发的 adapter / database 官方插件只以
92
+ * ~ 禁用条目预写、不预装——loader 跳过禁用条目,装好后在控制台启用;
93
+ * - 依赖版本统一 ^1.0.0 区间(安装时取最新 1.x),shim 版本例外(冻结线)。
94
+ */
95
+ /**
96
+ * 定位内置模板目录:src 直跑(开发 / 测试)与 lib 产物(npm 消费)两种
97
+ * 形态各按相对路径探测(发布包 files 含 src,lib 同级的 ../src/template
98
+ * 恒存在)。
99
+ */
100
+ function locateTemplateDir() {
101
+ const base = dirname(fileURLToPath(import.meta.url));
102
+ for (const dir of [join(base, "template"), join(base, "../src/template")]) if (existsSync(dir)) return dir;
103
+ throw new Error("create-koishi-ce 内置模板目录缺失(src/template)");
104
+ }
105
+ const templateDir = locateTemplateDir();
106
+ /**
107
+ * 无点前缀的模板源文件名 生成项目中的目标路径。点开头文件会被 npm
108
+ * 发布规则与各路工具的特殊处理波及(.env 恒不入包、嵌套 .gitignore 会被
109
+ * git 当真),模板目录里一律存无点文件名。
110
+ */
111
+ const dotFiles = {
112
+ env: ".env",
113
+ gitignore: ".gitignore"
156
114
  };
115
+ /** 模板静态文件(相对项目根的路径 → 文件内容),package.json 另行渲染 */
116
+ const templateFiles = Object.fromEntries(readdirSync(templateDir).filter((file) => !file.startsWith(".")).map((file) => [dotFiles[file] ?? file, readFileSync(join(templateDir, file), "utf8")]));
157
117
  /**
158
118
  * 内置模板的 package.json 基础内容(name/version 会被 renderManifest 覆写,
159
119
  * prod 模式下 workspaces 与 devDependencies 会被移除)。
@@ -161,10 +121,11 @@ bun run dev # 启动(开发模式,启用 HMR 热更新)
161
121
  function baseManifest() {
162
122
  return {
163
123
  type: "module",
124
+ packageManager: `bun@${Bun.version}`,
164
125
  workspaces: ["plugins/*", "external/*"],
165
126
  scripts: {
166
127
  start: "koishi start",
167
- dev: "cross-env NODE_ENV=development koishi start",
128
+ dev: "NODE_ENV=development koishi start",
168
129
  new: "koishi-scripts setup"
169
130
  },
170
131
  dependencies: {
@@ -172,11 +133,13 @@ function baseManifest() {
172
133
  "@koishi-ce/plugin-actions": "^1.0.0",
173
134
  "@koishi-ce/plugin-admin": "^1.0.0",
174
135
  "@koishi-ce/plugin-analytics": "^1.0.0",
136
+ "@koishi-ce/plugin-assets-local": "^1.0.0",
175
137
  "@koishi-ce/plugin-auth": "^1.0.0",
176
138
  "@koishi-ce/plugin-bind": "^1.0.0",
177
139
  "@koishi-ce/plugin-commands": "^1.0.0",
178
140
  "@koishi-ce/plugin-config": "^1.0.0",
179
141
  "@koishi-ce/plugin-console": "^1.0.0",
142
+ "@koishi-ce/plugin-dataview": "^1.0.0",
180
143
  "@koishi-ce/plugin-explorer": "^1.0.0",
181
144
  "@koishi-ce/plugin-help": "^1.0.0",
182
145
  "@koishi-ce/plugin-http": "^1.0.0",
@@ -188,9 +151,12 @@ function baseManifest() {
188
151
  "@koishi-ce/plugin-notifier": "^1.0.0",
189
152
  "@koishi-ce/plugin-oobe": "^1.0.0",
190
153
  "@koishi-ce/plugin-proxy-agent": "^1.0.0",
154
+ "@koishi-ce/plugin-rate-limit": "^1.0.0",
191
155
  "@koishi-ce/plugin-sandbox": "^1.0.0",
192
156
  "@koishi-ce/plugin-server": "^1.0.0",
157
+ "@koishi-ce/plugin-server-temp": "^1.0.0",
193
158
  "@koishi-ce/plugin-status": "^1.0.0",
159
+ "@koishi-ce/plugin-theme-vanilla": "^1.0.0",
194
160
  koishi: "npm:@koishi-ce/koishi-shim@^4.18.11",
195
161
  "@koishijs/plugin-console": "npm:@koishi-ce/console-shim@^5.30.11",
196
162
  "@koishijs/core": "npm:@koishi-ce/koishi-shim@4.18.11",
@@ -200,8 +166,7 @@ function baseManifest() {
200
166
  "@koishi-ce/client": "^1.0.0",
201
167
  "@koishi-ce/plugin-hmr": "^1.0.0",
202
168
  "@koishi-ce/scripts": "^1.0.0",
203
- "bun-types": "^1.4.0",
204
- "cross-env": "^7.0.3"
169
+ "bun-types": "^1.4.0"
205
170
  }
206
171
  };
207
172
  }
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.2.1",
4
+ "version": "1.3.0",
5
5
  "type": "module",
6
6
  "main": "./lib/index.mjs",
7
7
  "module": "./lib/index.mjs",
@@ -1,3 +1,6 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026-present Koishi-CE contributors.
3
+
1
4
  import { expect, test } from "bun:test";
2
5
  import { detectAgent, type Manifest, renderManifest } from "../index.ts";
3
6
 
@@ -1,3 +1,6 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026-present Koishi-CE contributors.
3
+
1
4
  import { expect, test } from "bun:test";
2
5
  import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
3
6
  import { tmpdir } from "node:os";
@@ -1,3 +1,6 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026-present Koishi-CE contributors.
3
+
1
4
  import { afterAll, beforeAll, describe, expect, it, mock } from "bun:test";
2
5
  import { spawnSync } from "node:child_process";
3
6
  import {
@@ -1,3 +1,6 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026-present Koishi-CE contributors.
3
+
1
4
  import { afterAll, beforeAll, describe, expect, it } from "bun:test";
2
5
 
3
6
  /**
@@ -1,3 +1,6 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026-present Koishi-CE contributors.
3
+
1
4
  import { afterAll, beforeAll, describe, expect, it, mock } from "bun:test";
2
5
  import {
3
6
  existsSync,
@@ -1,3 +1,6 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026-present Koishi-CE contributors.
3
+
1
4
  import { expect, test } from "bun:test";
2
5
  import { renderManifest } from "../index.ts";
3
6
  import { baseManifest, templateFiles } from "../template.ts";
@@ -15,12 +18,23 @@ test("内置模板依赖纯度:不含任何 @koishijs / koishi-plugin 官方
15
18
  for (const key of Object.keys(dependencies ?? {})) {
16
19
  expect(guarded.has(key) || key.startsWith("@koishi-ce/")).toBe(true);
17
20
  }
18
- const toolchain = new Set(["bun-types", "cross-env"]);
19
21
  for (const key of Object.keys(devDependencies ?? {})) {
20
- expect(key.startsWith("@koishi-ce/") || toolchain.has(key)).toBe(true);
22
+ expect(key === "bun-types" || key.startsWith("@koishi-ce/")).toBe(true);
21
23
  }
22
24
  });
23
25
 
26
+ test("内置模板 packageManager 钉 Bun,脚本用 Bun Shell 环境变量前缀", () => {
27
+ const manifest = baseManifest();
28
+ const { scripts } = manifest as unknown as {
29
+ scripts: Record<string, string>;
30
+ };
31
+ // 本项目只支持 Bun 运行时:packageManager 形如 bun@1.x.y
32
+ expect(manifest["packageManager"] ?? "").toMatch(/^bun@\d+\.\d+\.\d+/);
33
+ // cross-env 已移除:bun run 走 Bun Shell,环境变量前缀天然跨平台
34
+ expect(scripts["dev"]).toBe("NODE_ENV=development koishi start");
35
+ expect(JSON.stringify(manifest)).not.toContain("cross-env");
36
+ });
37
+
24
38
  test("内置模板以 npm alias 钉住 koishi 裸名,版本保持 4.18.x 冻结线", () => {
25
39
  const request = baseManifest().dependencies?.["koishi"];
26
40
  expect(typeof request).toBe("string");
@@ -59,8 +73,40 @@ test("内置模板静态文件齐备,koishi.yml 预配 market 镜像源", () =
59
73
  expect(templateFiles["koishi.yml"]).toContain(
60
74
  "endpoint: https://registry.koishi.chat/index.json",
61
75
  );
62
- // 模板不预装数据库,依赖数据库的插件保持 ~ 禁用
63
- expect(templateFiles["koishi.yml"]).toContain("~analytics");
76
+ });
77
+
78
+ test("koishi.yml 预写策略对齐官方实例:CE 插件装而禁用,官方 adapter/database 只写不装", () => {
79
+ const yml = templateFiles["koishi.yml"] ?? "";
80
+ // 依赖数据库 / 暂无需启用的 CE 插件:预装但 ~ 禁用
81
+ for (const name of [
82
+ "~admin",
83
+ "~bind",
84
+ "~analytics",
85
+ "~auth",
86
+ "~dataview",
87
+ "~rate-limit",
88
+ "~inspect",
89
+ "~server-temp",
90
+ ]) {
91
+ expect(yml).toContain(name);
92
+ }
93
+ // 无需数据库即可工作的 CE 插件:直接启用
94
+ for (const name of ["assets-local", "theme-vanilla", "status", "sandbox"]) {
95
+ expect(yml).toContain(name);
96
+ }
97
+ // 官方 adapter / database 只以 ~ 禁用条目预写(未预装,市场装后启用)
98
+ for (const name of [
99
+ "~adapter-discord",
100
+ "~adapter-telegram",
101
+ "~adapter-qq",
102
+ "~database-sqlite",
103
+ "~database-postgres",
104
+ ]) {
105
+ expect(yml).toContain(name);
106
+ }
107
+ // 模板依赖里不得出现官方 adapter / database 包名(只预写不预装)
108
+ expect(JSON.stringify(baseManifest())).not.toContain("adapter-");
109
+ expect(JSON.stringify(baseManifest())).not.toContain("database-");
64
110
  });
65
111
 
66
112
  test("renderManifest 渲染内置模板:常规改写生效,prod 模式保留 koishi alias", () => {
@@ -69,6 +115,7 @@ test("renderManifest 渲染内置模板:常规改写生效,prod 模式保留
69
115
  expect(output.private).toBe(true);
70
116
  expect(output.version).toBe("0.0.0");
71
117
  expect(output.scripts.start).toBe("koishi start");
118
+ expect(output.packageManager).toMatch(/^bun@/);
72
119
  expect(output.dependencies.koishi).toBe(
73
120
  "npm:@koishi-ce/koishi-shim@^4.18.11",
74
121
  );
package/src/bin.ts CHANGED
@@ -1,4 +1,7 @@
1
1
  #!/usr/bin/env bun
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) 2026-present Koishi-CE contributors.
4
+
2
5
  /**
3
6
  * create-koishi-ce 的 CLI 可执行入口:shebang 由 rolldown 原样保留到
4
7
  * lib/bin.mjs,package.json 的 bin 字段指向它(范式同 @koishi-ce/scripts)。
package/src/index.ts CHANGED
@@ -1,3 +1,6 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026-present Koishi-CE contributors.
3
+
1
4
  /**
2
5
  * create-koishi-ce 脚手架(npm 包名 create-koishi-ce,目录名为
3
6
  * apps/koishi-create,二者不一致是历史遗留,以目录名为准)。
@@ -0,0 +1,32 @@
1
+ # Koishi 机器人项目
2
+
3
+ 由 `bun create koishi-ce` 生成,运行于 [@koishi-ce 社区再分发版](https://github.com/Koishi-CE/koishi) 生态。
4
+
5
+ ## 环境要求
6
+
7
+ - [Bun](https://bun.sh) ≥ 1.2(本项目唯一支持的运行时与包管理器:koishi CLI 与插件加载链均以 Bun 为准)
8
+
9
+ ## 快速开始
10
+
11
+ ```bash
12
+ bun install
13
+ bun run start # 启动(生产模式)
14
+ bun run dev # 启动(开发模式,启用 HMR 热更新)
15
+ ```
16
+
17
+ 启动后访问控制台:<http://127.0.0.1:5140>
18
+
19
+ ## 预装与预写
20
+
21
+ - **已预装**:基础与控制台插件(@koishi-ce 全家桶)。其中依赖数据库的(admin / bind / analytics / auth / dataview / rate-limit 等)与暂无需启用的(inspect / server-temp)在 `koishi.yml` 中以 `~` 前缀保持禁用——安装并启用任一数据库插件后,去掉对应 `~` 即可。
22
+ - **只预写、未预装**:adapter(discord / telegram / qq …)与数据库(sqlite / mongo / postgres …)官方插件以 `~` 禁用条目预写在 `koishi.yml` 的 `group:adapter` / `group:storage`——loader 会跳过禁用条目,不安装也能正常启动;需要时在控制台「插件市场」搜索安装,回到配置页点击启用即可。
23
+
24
+ ## 安装插件
25
+
26
+ 推荐在控制台「插件市场」页安装(已预配 registry.koishi.chat 镜像源);也可以手动 `bun add <包名>` 后在 `koishi.yml` 中启用。
27
+
28
+ 根依赖中的四行 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
+
30
+ ## 自定义插件
31
+
32
+ 在 `plugins/` 目录下创建插件包(可用 `bun run new <名称>` 生成骨架),在 `koishi.yml` 中以相对路径引用(如 `./plugins/my-plugin`)即可启用;Bun 直接加载 TypeScript 源码,无需预编译。
@@ -0,0 +1,3 @@
1
+ GITHUB_MIRROR = https://ghproxy.com/https://github.com
2
+ GITHUB_CONTENT_MIRROR = https://ghproxy.com/https://raw.githubusercontent.com
3
+ GRAVATAR_MIRROR = https://cravatar.cn
@@ -0,0 +1,3 @@
1
+ node_modules/
2
+ data/
3
+ temp/
@@ -0,0 +1,65 @@
1
+ plugins:
2
+ group:server:
3
+ server:
4
+ port: 5140
5
+ maxPort: 5149
6
+ ~server-temp: {}
7
+ group:basic:
8
+ ~admin: {}
9
+ ~bind: {}
10
+ commands: {}
11
+ help: {}
12
+ http: {}
13
+ ~inspect: {}
14
+ locales: {}
15
+ proxy-agent: {}
16
+ ~rate-limit: {}
17
+ group:console:
18
+ actions: {}
19
+ ~analytics: {}
20
+ ~auth: {}
21
+ config: {}
22
+ console:
23
+ open: true
24
+ ~dataview: {}
25
+ explorer: {}
26
+ insight: {}
27
+ logger: {}
28
+ market:
29
+ search:
30
+ endpoint: https://registry.koishi.chat/index.json
31
+ notifier: {}
32
+ oobe: {}
33
+ sandbox: {}
34
+ status: {}
35
+ theme-vanilla: {}
36
+ group:storage:
37
+ ~database-mongo:
38
+ database: koishi
39
+ ~database-mysql:
40
+ database: koishi
41
+ ~database-postgres:
42
+ database: koishi
43
+ ~database-sqlite:
44
+ path: data/koishi.db
45
+ assets-local: {}
46
+ group:adapter:
47
+ ~adapter-dingtalk: {}
48
+ ~adapter-discord: {}
49
+ ~adapter-kook: {}
50
+ ~adapter-lark: {}
51
+ ~adapter-line: {}
52
+ ~adapter-mail: {}
53
+ ~adapter-matrix: {}
54
+ ~adapter-qq: {}
55
+ ~adapter-satori: {}
56
+ ~adapter-slack: {}
57
+ ~adapter-telegram: {}
58
+ ~adapter-wechat-official: {}
59
+ ~adapter-wecom: {}
60
+ ~adapter-whatsapp: {}
61
+ ~adapter-zulip: {}
62
+ group:develop:
63
+ $if: env.NODE_ENV === 'development'
64
+ hmr:
65
+ root: .
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ESNext"],
7
+ "types": ["bun-types"],
8
+ "strict": true,
9
+ "skipLibCheck": true,
10
+ "noEmit": true,
11
+ "allowImportingTsExtensions": true,
12
+ "verbatimModuleSyntax": true,
13
+ "erasableSyntaxOnly": true
14
+ },
15
+ "include": ["plugins/*/src", "external/*/src"]
16
+ }
package/src/template.ts CHANGED
@@ -1,3 +1,6 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026-present Koishi-CE contributors.
3
+
1
4
  /**
2
5
  * 内置项目模板(create-koishi-ce 的默认模板)。
3
6
  *
@@ -7,115 +10,66 @@
7
10
  * 默认模板改为内置的纯 @koishi-ce 依赖集;确需上游官方模板时用
8
11
  * --template <包名> 走 npm 远程下载(见 index.ts 的 scaffoldRemote)。
9
12
  *
13
+ * 模板的静态文本一律放在 src/template/ 下的真实文件里(本模块只负责
14
+ * 定位与读取,不再内嵌字符串常量)。npm 包的 files 含 src,因此 lib
15
+ * 产物与 src 直跑两种形态都能按相对路径定位到模板目录。
16
+ *
10
17
  * 模板要点:
11
18
  * - 运行时 Bun:koishi CLI(@koishi-ce/koishi 的 bin)与 loader 插件加载链
12
- * 均以 Bun 为准(ESM-only 产物,Bun 原生加载 TS / yml);
13
- * - "koishi" 裸名与 @koishijs/core / @koishijs/loader 上游名用 npm alias
14
- * 钉到 @koishi-ce/koishi-shim(4.18.x 冻结线,见 packages/shim/koishi-shim):
15
- * 上游官方 adapter / database 插件与社区
16
- * koishi-plugin-* peer `koishi ^4.x` 等由此满足,不会拉入 npm 官方
17
- * koishi 形成第二份框架副本;市场安装亦不改写该声明(installer
18
- * isGuardedRequest 护栏将 npm:@koishi-ce alias 与 workspace: 同等保护);
19
- * - 本仓没有 adapter / database 插件的再分发,模板不预装这两类;依赖数据库
20
- * 的插件(如 analytics)在 koishi.yml 中保持 ~ 禁用,待用户从市场安装
21
- * 数据库插件后再启用;
19
+ * 均以 Bun 为准(ESM-only 产物,Bun 原生加载 TS / yml);脚本里的环境
20
+ * 变量注入直接写 `NODE_ENV=... ` 前缀——bun run Bun Shell,跨平台
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 官方全家桶形成第二份框架副本;市场安装亦不改写该声明
26
+ * (installer isGuardedRequest 护栏将 npm:@koishi-ce alias
27
+ * workspace: 同等保护);
28
+ * - koishi.yml 对齐官方实例的预写策略:控制台与基础插件全量预装(依赖
29
+ * 数据库的保持 ~ 禁用);本仓不再分发的 adapter / database 官方插件只以
30
+ * ~ 禁用条目预写、不预装——loader 跳过禁用条目,装好后在控制台启用;
22
31
  * - 依赖版本统一 ^1.0.0 区间(安装时取最新 1.x),shim 版本例外(冻结线)。
23
32
  */
33
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
34
+ import { dirname, join } from "node:path";
35
+ import { fileURLToPath } from "node:url";
24
36
  import type { Manifest } from "./index.ts";
25
37
 
26
- /** 模板静态文件(相对项目根的路径 → 文件内容),package.json 另行渲染 */
27
- export const templateFiles: Record<string, string> = {
28
- ".env": [
29
- "GITHUB_MIRROR = https://ghproxy.com/https://github.com",
30
- "GITHUB_CONTENT_MIRROR = https://ghproxy.com/https://raw.githubusercontent.com",
31
- "GRAVATAR_MIRROR = https://cravatar.cn",
32
- ].join("\n"),
33
- ".gitignore": ["node_modules/", "data/"].join("\n"),
34
- "koishi.yml": [
35
- "plugins:",
36
- " group:server:",
37
- " server:",
38
- " port: 5140",
39
- " maxPort: 5149",
40
- " group:basic:",
41
- " ~admin: {}",
42
- " ~bind: {}",
43
- " commands: {}",
44
- " help: {}",
45
- " http: {}",
46
- " ~inspect: {}",
47
- " locales: {}",
48
- " proxy-agent: {}",
49
- " group:console:",
50
- " actions: {}",
51
- " ~analytics: {}",
52
- " ~auth: {}",
53
- " config: {}",
54
- " console:",
55
- " open: true",
56
- " explorer: {}",
57
- " insight: {}",
58
- " logger: {}",
59
- " market:",
60
- " search:",
61
- " endpoint: https://registry.koishi.chat/index.json",
62
- " notifier: {}",
63
- " oobe: {}",
64
- " sandbox: {}",
65
- " status: {}",
66
- " group:develop:",
67
- " $if: env.NODE_ENV === 'development'",
68
- " hmr:",
69
- " root: .",
70
- ].join("\n"),
71
- "tsconfig.json": [
72
- "{",
73
- ' "compilerOptions": {',
74
- ' "target": "ESNext",',
75
- ' "module": "ESNext",',
76
- ' "moduleResolution": "bundler",',
77
- ' "lib": ["ESNext"],',
78
- ' "types": ["bun-types"],',
79
- ' "strict": true,',
80
- ' "skipLibCheck": true,',
81
- ' "noEmit": true,',
82
- ' "allowImportingTsExtensions": true,',
83
- ' "verbatimModuleSyntax": true,',
84
- ' "erasableSyntaxOnly": true',
85
- " },",
86
- ' "include": ["plugins/*/src", "external/*/src"]',
87
- "}",
88
- ].join("\n"),
89
- "README.md": `# Koishi 机器人项目
90
-
91
- 由 \`bun create koishi-ce\` 生成,运行于 [@koishi-ce 社区再分发版](https://github.com/Koishi-CE/koishi) 生态。
92
-
93
- ## 环境要求
94
-
95
- - [Bun](https://bun.sh) ≥ 1.2(运行时:koishi CLI 与插件加载链以 Bun 为准)
96
-
97
- ## 快速开始
98
-
99
- \`\`\`bash
100
- bun install
101
- bun run start # 启动(生产模式)
102
- bun run dev # 启动(开发模式,启用 HMR 热更新)
103
- \`\`\`
104
-
105
- 启动后访问控制台:<http://127.0.0.1:5140>
106
-
107
- ## 安装插件
108
-
109
- 推荐在控制台「插件市场」页安装(已预配 registry.koishi.chat 镜像源);也可以手动 \`bun add <包名>\` 后在 \`koishi.yml\` 中启用。
110
-
111
- 上游官方 adapter(如 adapter-discord / adapter-telegram)、数据库插件(如 database-sqlite)与社区 koishi-plugin-* 插件均可直接安装:根依赖中的四行 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 副本。analytics 等依赖数据库的插件请先安装数据库插件,再去掉配置中对应的 \`~\` 前缀启用。
38
+ /**
39
+ * 定位内置模板目录:src 直跑(开发 / 测试)与 lib 产物(npm 消费)两种
40
+ * 形态各按相对路径探测(发布包 files 含 src,lib 同级的 ../src/template
41
+ * 恒存在)。
42
+ */
43
+ function locateTemplateDir(): string {
44
+ const base = dirname(fileURLToPath(import.meta.url));
45
+ for (const dir of [join(base, "template"), join(base, "../src/template")]) {
46
+ if (existsSync(dir)) return dir;
47
+ }
48
+ throw new Error("create-koishi-ce 内置模板目录缺失(src/template)");
49
+ }
112
50
 
113
- ## 自定义插件
51
+ const templateDir = locateTemplateDir();
114
52
 
115
- 在 \`plugins/\` 目录下创建插件包(可用 \`bun run new <名称>\` 生成骨架),在 \`koishi.yml\` 中以相对路径引用(如 \`./plugins/my-plugin\`)即可启用;Bun 直接加载 TypeScript 源码,无需预编译。
116
- `,
53
+ /**
54
+ * 无点前缀的模板源文件名 → 生成项目中的目标路径。点开头文件会被 npm
55
+ * 发布规则与各路工具的特殊处理波及(.env 恒不入包、嵌套 .gitignore 会被
56
+ * git 当真),模板目录里一律存无点文件名。
57
+ */
58
+ const dotFiles: Record<string, string> = {
59
+ env: ".env",
60
+ gitignore: ".gitignore",
117
61
  };
118
62
 
63
+ /** 模板静态文件(相对项目根的路径 → 文件内容),package.json 另行渲染 */
64
+ export const templateFiles: Record<string, string> = Object.fromEntries(
65
+ readdirSync(templateDir)
66
+ .filter((file) => !file.startsWith("."))
67
+ .map((file) => [
68
+ dotFiles[file] ?? file,
69
+ readFileSync(join(templateDir, file), "utf8"),
70
+ ]),
71
+ );
72
+
119
73
  /**
120
74
  * 内置模板的 package.json 基础内容(name/version 会被 renderManifest 覆写,
121
75
  * prod 模式下 workspaces 与 devDependencies 会被移除)。
@@ -123,10 +77,13 @@ bun run dev # 启动(开发模式,启用 HMR 热更新)
123
77
  export function baseManifest(): Manifest {
124
78
  return {
125
79
  type: "module",
80
+ // 本项目只用 Bun:钉住创建时的 Bun 版本(bun run 亦据此选择解释器)
81
+ packageManager: `bun@${Bun.version}`,
126
82
  workspaces: ["plugins/*", "external/*"],
127
83
  scripts: {
128
84
  start: "koishi start",
129
- dev: "cross-env NODE_ENV=development koishi start",
85
+ // bun run 走 Bun Shell,`NODE_ENV=...` 前缀天然跨平台,无需 cross-env
86
+ dev: "NODE_ENV=development koishi start",
130
87
  new: "koishi-scripts setup",
131
88
  },
132
89
  dependencies: {
@@ -134,11 +91,13 @@ export function baseManifest(): Manifest {
134
91
  "@koishi-ce/plugin-actions": "^1.0.0",
135
92
  "@koishi-ce/plugin-admin": "^1.0.0",
136
93
  "@koishi-ce/plugin-analytics": "^1.0.0",
94
+ "@koishi-ce/plugin-assets-local": "^1.0.0",
137
95
  "@koishi-ce/plugin-auth": "^1.0.0",
138
96
  "@koishi-ce/plugin-bind": "^1.0.0",
139
97
  "@koishi-ce/plugin-commands": "^1.0.0",
140
98
  "@koishi-ce/plugin-config": "^1.0.0",
141
99
  "@koishi-ce/plugin-console": "^1.0.0",
100
+ "@koishi-ce/plugin-dataview": "^1.0.0",
142
101
  "@koishi-ce/plugin-explorer": "^1.0.0",
143
102
  "@koishi-ce/plugin-help": "^1.0.0",
144
103
  "@koishi-ce/plugin-http": "^1.0.0",
@@ -150,9 +109,12 @@ export function baseManifest(): Manifest {
150
109
  "@koishi-ce/plugin-notifier": "^1.0.0",
151
110
  "@koishi-ce/plugin-oobe": "^1.0.0",
152
111
  "@koishi-ce/plugin-proxy-agent": "^1.0.0",
112
+ "@koishi-ce/plugin-rate-limit": "^1.0.0",
153
113
  "@koishi-ce/plugin-sandbox": "^1.0.0",
154
114
  "@koishi-ce/plugin-server": "^1.0.0",
115
+ "@koishi-ce/plugin-server-temp": "^1.0.0",
155
116
  "@koishi-ce/plugin-status": "^1.0.0",
117
+ "@koishi-ce/plugin-theme-vanilla": "^1.0.0",
156
118
  // 上游裸名占位:npm alias 钉到 @koishi-ce 的 koishi shim(勿删,
157
119
  // 语义见文件头注释);版本必须保持 4.18.x 冻结线以满足 ^4 peer
158
120
  koishi: "npm:@koishi-ce/koishi-shim@^4.18.11",
@@ -173,7 +135,6 @@ export function baseManifest(): Manifest {
173
135
  "@koishi-ce/plugin-hmr": "^1.0.0",
174
136
  "@koishi-ce/scripts": "^1.0.0",
175
137
  "bun-types": "^1.4.0",
176
- "cross-env": "^7.0.3",
177
138
  },
178
139
  };
179
140
  }