create-kokkoro 0.1.1 → 0.2.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.
Files changed (3) hide show
  1. package/README.md +28 -23
  2. package/package.json +1 -1
  3. package/src/project.ts +52 -6
package/README.md CHANGED
@@ -1,43 +1,48 @@
1
1
  # create-kokkoro
2
2
 
3
- Kokkoro QQ 机器人框架的项目创建工具。
3
+ Kokkoro QQ 机器人框架的项目创建工具。按照终端提示填写配置,即可生成项目目录和启动文件。
4
4
 
5
- ## 使用
5
+ 使用前需要安装 [Bun](https://bun.com/docs/installation),它负责安装项目依赖和运行 Kokkoro。
6
6
 
7
- 运行以下命令创建 Kokkoro 项目:
7
+ ## 创建项目
8
+
9
+ 在终端中进入准备存放项目的目录,运行:
8
10
 
9
11
  ```shell
10
12
  bun create kokkoro
11
13
  ```
12
14
 
13
- 命令会创建项目目录、`plugins` 目录、`package.json`、`kokkoro.json` 和 `main.ts`。
15
+ 按照提示输入项目名称、服务端口、QQ 服务接入方式和机器人配置。直接按回车可使用默认项目名称 `kokkoro-app` 和端口 `3000`。
16
+
17
+ 本地开发可以选择 WebSocket。添加机器人时,需要填写从 QQ 开放平台获取的 AppID 和 ClientSecret。还没有机器人时,可以在“是否添加机器人”处选择“否”,以后再修改 `kokkoro.json`。具体操作见[快速上手](https://kokkoro.js.org/guide/quick-start)。
18
+
19
+ ## 启动项目
14
20
 
15
- 如果项目目录不是空目录,创建将中止。使用 `--force` 或 `-f` 选项可以覆盖脚手架创建的同名文件,目录中的其他内容不受影响。
21
+ 创建完成后,进入生成的文件夹,安装依赖并启动服务。下面使用默认项目名称:
16
22
 
17
23
  ```shell
18
- bun create kokkoro --force
24
+ cd kokkoro-app
25
+ bun install
26
+ bun start
19
27
  ```
20
28
 
21
- ## 配置项目
29
+ 如果使用了其他名称,将 `kokkoro-app` 换成对应的文件夹名称。终端显示“服务已启动”后,说明 HTTP 服务已经运行。按 `Ctrl+C` 可以停止服务。
22
30
 
23
- 命令会依次询问以下内容:
31
+ ## 项目文件
24
32
 
25
- 1. 输入项目名称,默认值为 `kokkoro-app`。
26
- 2. 输入服务端口,默认值为 `3000`。
27
- 3. 选择 QQ 服务接入方式,可选 `WebSocket` 或 `WebHook`。
28
- 4. 选择是否添加机器人。不添加机器人时,`kokkoro.json` 中的 `bots` 为空数组。
29
- 5. 添加机器人时,输入机器人的 `AppID` 和 `ClientSecret`。
30
- 6. 使用 `WebHook` 并添加机器人时,输入 WebHook 路径,默认值为 `/callback`。
33
+ 生成的项目包含以下内容:
31
34
 
32
- ### 启动项目
35
+ | 路径 | 用途 |
36
+ | -------------- | ----------------------- |
37
+ | `kokkoro.json` | 保存机器人和服务配置 |
38
+ | `main.ts` | 启动 Kokkoro 的入口文件 |
39
+ | `plugins/` | 存放自己编写的插件 |
40
+ | `package.json` | 声明项目依赖和启动命令 |
33
41
 
34
- 创建完成后,进入项目目录并安装依赖:
42
+ 如果同名文件夹已经存在且不为空,创建过程会停止。需要覆盖已有模板文件时,可以运行 `bun create kokkoro --force`,其他文件会保留。覆盖范围见[创建项目](https://kokkoro.js.org/guide/cli#create-project)。
35
43
 
36
- ```shell
37
- cd kokkoro-app
38
-
39
- bun install
40
- bun start
41
- ```
44
+ ## 接下来
42
45
 
43
- 将 `kokkoro-app` 替换为你输入的项目名称。
46
+ - [配置文件](https://kokkoro.js.org/guide/config),修改机器人凭证、端口和接入方式。
47
+ - [编写第一个插件](https://kokkoro.js.org/develop/first-plugin),为机器人添加功能。
48
+ - [命令行工具](https://kokkoro.js.org/guide/cli),使用 `kokkoro` 命令创建插件和启动项目。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-kokkoro",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "The project creation tool for the Kokkoro QQ bot framework.",
5
5
  "keywords": [
6
6
  "bot",
package/src/project.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Glob, write } from 'bun';
1
+ import { $, file, Glob, write } from 'bun';
2
2
  import { existsSync } from 'node:fs';
3
3
  import { mkdir } from 'node:fs/promises';
4
4
  import { basename, join, resolve } from 'node:path';
@@ -15,6 +15,15 @@ const MAIN = [
15
15
  '',
16
16
  ].join('\n');
17
17
 
18
+ const PLUGIN = [
19
+ "import { useCommand } from '@kokkoro/core';",
20
+ '',
21
+ 'export default () => {',
22
+ " useCommand('/ping', () => 'pong');",
23
+ '};',
24
+ '',
25
+ ].join('\n');
26
+
18
27
  async function hasEntries(directory: string): Promise<boolean> {
19
28
  if (!existsSync(directory)) {
20
29
  return false;
@@ -24,8 +33,7 @@ async function hasEntries(directory: string): Promise<boolean> {
24
33
  dot: true,
25
34
  onlyFiles: false,
26
35
  });
27
- const iterator = entries[Symbol.asyncIterator]();
28
- const { done } = await iterator.next();
36
+ const { done } = await entries.next();
29
37
 
30
38
  return !done;
31
39
  }
@@ -100,7 +108,7 @@ function promptBots(protocol: Protocol) {
100
108
 
101
109
  /** 在指定目录创建 Kokkoro 项目。 */
102
110
  export async function createProject(directory: string, isForced = false): Promise<void> {
103
- if ((await hasEntries(directory)) && !isForced) {
111
+ if (!isForced && (await hasEntries(directory))) {
104
112
  throw new Error(`目标目录不是空目录,如需继续,请使用 --force 选项覆盖模板文件\n${directory}`);
105
113
  }
106
114
  const port = promptPort();
@@ -116,7 +124,10 @@ export async function createProject(directory: string, isForced = false): Promis
116
124
  start: 'bun run main.ts',
117
125
  },
118
126
  dependencies: {
119
- kokkoro: '^3.0.1',
127
+ kokkoro: '^3.0.3',
128
+ },
129
+ peerDependencies: {
130
+ typescript: '^6.0.3',
120
131
  },
121
132
  devEngines: {
122
133
  runtime: {
@@ -147,8 +158,43 @@ export async function createProject(directory: string, isForced = false): Promis
147
158
  console.log('\n项目创建完成,请依次运行以下命令:\n');
148
159
 
149
160
  if (directory !== '.') {
150
- console.log(` cd ${directory}`);
161
+ console.log(` cd ${$.escape(resolve(directory))}`);
151
162
  }
152
163
  console.log(' bun install');
153
164
  console.log(' bun start');
154
165
  }
166
+
167
+ /** 在当前 Kokkoro 项目中创建本地插件。 */
168
+ export async function createPlugin(name: string, isForced = false): Promise<void> {
169
+ if (!/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/.test(name)) {
170
+ throw new Error('插件名称必须以小写字母开头,且只能包含小写字母、数字和连字符');
171
+ }
172
+
173
+ if (!(await file('kokkoro.json').exists())) {
174
+ throw new Error('当前目录不是 Kokkoro 项目,请先运行 init 命令');
175
+ }
176
+ const destination = join('plugins', name);
177
+
178
+ if (!isForced && (await hasEntries(destination))) {
179
+ throw new Error(`目标插件目录不是空目录,如需继续,请使用 --force 选项覆盖模板文件\n${destination}`);
180
+ }
181
+ const source = join(destination, 'src');
182
+ const manifest = {
183
+ name: `kokkoro-plugin-${name}`,
184
+ version: '0.0.0',
185
+ type: 'module',
186
+ files: ['src'],
187
+ exports: './src/index.ts',
188
+ peerDependencies: {
189
+ '@kokkoro/core': '^3.1.5',
190
+ typescript: '^6.0.3',
191
+ },
192
+ };
193
+
194
+ await Promise.all([
195
+ write(join(destination, 'package.json'), `${JSON.stringify(manifest, null, 2)}\n`),
196
+ write(join(source, 'index.ts'), PLUGIN),
197
+ ]);
198
+
199
+ console.log(`插件 ${name} 创建完成,请运行 bun i 同步工作区依赖`);
200
+ }