create-kokkoro 0.1.0 → 0.1.2
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 +1 -1
- package/package.json +4 -6
- package/src/index.ts +2 -2
- package/src/project.ts +46 -47
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ bun create kokkoro
|
|
|
12
12
|
|
|
13
13
|
命令会创建项目目录、`plugins` 目录、`package.json`、`kokkoro.json` 和 `main.ts`。
|
|
14
14
|
|
|
15
|
-
如果项目目录不是空目录,创建将中止。使用 `--force` 选项可以覆盖脚手架创建的同名文件,目录中的其他内容不受影响。
|
|
15
|
+
如果项目目录不是空目录,创建将中止。使用 `--force` 或 `-f` 选项可以覆盖脚手架创建的同名文件,目录中的其他内容不受影响。
|
|
16
16
|
|
|
17
17
|
```shell
|
|
18
18
|
bun create kokkoro --force
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-kokkoro",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "The project creation tool for the Kokkoro QQ bot framework.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bot",
|
|
@@ -8,10 +8,8 @@
|
|
|
8
8
|
"qq",
|
|
9
9
|
"qqbot"
|
|
10
10
|
],
|
|
11
|
-
"homepage": "https://kokkoro.js.org
|
|
12
|
-
"bugs":
|
|
13
|
-
"url": "https://github.com/kokkorojs/kokkoro/issues"
|
|
14
|
-
},
|
|
11
|
+
"homepage": "https://kokkoro.js.org",
|
|
12
|
+
"bugs": "https://github.com/kokkorojs/kokkoro/issues",
|
|
15
13
|
"repository": {
|
|
16
14
|
"type": "git",
|
|
17
15
|
"url": "git+https://github.com/kokkorojs/kokkoro.git",
|
|
@@ -28,7 +26,7 @@
|
|
|
28
26
|
"src"
|
|
29
27
|
],
|
|
30
28
|
"dependencies": {
|
|
31
|
-
"komut": "^0.
|
|
29
|
+
"komut": "^0.3.1"
|
|
32
30
|
},
|
|
33
31
|
"peerDependencies": {
|
|
34
32
|
"typescript": "^6.0.3"
|
package/src/index.ts
CHANGED
|
@@ -9,8 +9,8 @@ import { createProject } from './project';
|
|
|
9
9
|
const name = input('项目名称', { default: 'kokkoro-app' });
|
|
10
10
|
|
|
11
11
|
if (name === null) {
|
|
12
|
-
throw new Error('
|
|
12
|
+
throw new Error('已取消创建项目');
|
|
13
13
|
}
|
|
14
|
-
const isForced = argv.includes('--force');
|
|
14
|
+
const isForced = argv.includes('--force') || argv.includes('-f');
|
|
15
15
|
|
|
16
16
|
await createProject(name, isForced);
|
package/src/project.ts
CHANGED
|
@@ -1,59 +1,61 @@
|
|
|
1
1
|
import { Glob, write } from 'bun';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
2
3
|
import { mkdir } from 'node:fs/promises';
|
|
3
4
|
import { basename, join, resolve } from 'node:path';
|
|
4
5
|
|
|
5
|
-
import { input, select } from 'komut/prompts';
|
|
6
|
+
import { type InputOptions, input, select } from 'komut/prompts';
|
|
6
7
|
|
|
7
8
|
type Protocol = 'websocket' | 'webhook';
|
|
8
9
|
|
|
10
|
+
// prettier-ignore
|
|
11
|
+
const MAIN = [
|
|
12
|
+
"import { run } from 'kokkoro';",
|
|
13
|
+
'',
|
|
14
|
+
'await run();',
|
|
15
|
+
'',
|
|
16
|
+
].join('\n');
|
|
17
|
+
|
|
9
18
|
async function hasEntries(directory: string): Promise<boolean> {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
cwd: directory,
|
|
13
|
-
dot: true,
|
|
14
|
-
onlyFiles: false,
|
|
15
|
-
});
|
|
16
|
-
const iterator = entries[Symbol.asyncIterator]();
|
|
17
|
-
const { done } = await iterator.next();
|
|
18
|
-
|
|
19
|
-
return !done;
|
|
20
|
-
} catch (error) {
|
|
21
|
-
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
22
|
-
return false;
|
|
23
|
-
}
|
|
24
|
-
throw error;
|
|
19
|
+
if (!existsSync(directory)) {
|
|
20
|
+
return false;
|
|
25
21
|
}
|
|
22
|
+
const entries = new Glob('*').scan({
|
|
23
|
+
cwd: directory,
|
|
24
|
+
dot: true,
|
|
25
|
+
onlyFiles: false,
|
|
26
|
+
});
|
|
27
|
+
const iterator = entries[Symbol.asyncIterator]();
|
|
28
|
+
const { done } = await iterator.next();
|
|
29
|
+
|
|
30
|
+
return !done;
|
|
26
31
|
}
|
|
27
32
|
|
|
28
|
-
function prompt(message: string,
|
|
29
|
-
const value = input(message,
|
|
33
|
+
function prompt(message: string, options?: InputOptions): string {
|
|
34
|
+
const value = input(message, options);
|
|
30
35
|
|
|
31
36
|
if (value === null) {
|
|
32
|
-
throw new Error('
|
|
37
|
+
throw new Error('已取消创建项目');
|
|
33
38
|
}
|
|
34
39
|
return value;
|
|
35
40
|
}
|
|
36
41
|
|
|
37
42
|
function promptRequired(message: string): string {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if (value) {
|
|
42
|
-
return value;
|
|
43
|
-
}
|
|
44
|
-
console.error(`${message}不能为空。`);
|
|
45
|
-
}
|
|
43
|
+
return prompt(message, {
|
|
44
|
+
validate: value => value.length > 0 || `${message}不能为空`,
|
|
45
|
+
});
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
function promptPort(): number {
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
const value = prompt('服务端口', {
|
|
50
|
+
default: '3000',
|
|
51
|
+
validate: value => {
|
|
52
|
+
const port = Number(value);
|
|
51
53
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
return (Number.isInteger(port) && port >= 0 && port <= 65535) || '服务端口必须是 0 到 65535 之间的整数';
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
return Number(value);
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
function promptProtocol(): Protocol {
|
|
@@ -63,20 +65,16 @@ function promptProtocol(): Protocol {
|
|
|
63
65
|
]);
|
|
64
66
|
|
|
65
67
|
if (choice === null) {
|
|
66
|
-
throw new Error('
|
|
68
|
+
throw new Error('已取消创建项目');
|
|
67
69
|
}
|
|
68
70
|
return <Protocol>choice.value;
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
function promptWebHookPath(): string {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
return path;
|
|
77
|
-
}
|
|
78
|
-
console.error('WebHook 路径必须以 / 开头。');
|
|
79
|
-
}
|
|
74
|
+
return prompt('WebHook 路径', {
|
|
75
|
+
default: '/callback',
|
|
76
|
+
validate: value => value.startsWith('/') || 'WebHook 路径必须以 / 开头',
|
|
77
|
+
});
|
|
80
78
|
}
|
|
81
79
|
|
|
82
80
|
function promptBots(protocol: Protocol) {
|
|
@@ -86,7 +84,7 @@ function promptBots(protocol: Protocol) {
|
|
|
86
84
|
]);
|
|
87
85
|
|
|
88
86
|
if (choice === null) {
|
|
89
|
-
throw new Error('
|
|
87
|
+
throw new Error('已取消创建项目');
|
|
90
88
|
}
|
|
91
89
|
|
|
92
90
|
if (choice.value === 'no') {
|
|
@@ -103,7 +101,7 @@ function promptBots(protocol: Protocol) {
|
|
|
103
101
|
/** 在指定目录创建 Kokkoro 项目。 */
|
|
104
102
|
export async function createProject(directory: string, isForced = false): Promise<void> {
|
|
105
103
|
if ((await hasEntries(directory)) && !isForced) {
|
|
106
|
-
throw new Error(
|
|
104
|
+
throw new Error(`目标目录不是空目录,如需继续,请使用 --force 选项覆盖模板文件\n${directory}`);
|
|
107
105
|
}
|
|
108
106
|
const port = promptPort();
|
|
109
107
|
const protocol = promptProtocol();
|
|
@@ -113,11 +111,12 @@ export async function createProject(directory: string, isForced = false): Promis
|
|
|
113
111
|
name,
|
|
114
112
|
private: true,
|
|
115
113
|
type: 'module',
|
|
114
|
+
workspaces: ['plugins/*'],
|
|
116
115
|
scripts: {
|
|
117
116
|
start: 'bun run main.ts',
|
|
118
117
|
},
|
|
119
118
|
dependencies: {
|
|
120
|
-
kokkoro: '^3.0.
|
|
119
|
+
kokkoro: '^3.0.2',
|
|
121
120
|
},
|
|
122
121
|
devEngines: {
|
|
123
122
|
runtime: {
|
|
@@ -142,7 +141,7 @@ export async function createProject(directory: string, isForced = false): Promis
|
|
|
142
141
|
await Promise.all([
|
|
143
142
|
write(join(directory, 'package.json'), `${JSON.stringify(manifest, null, 2)}\n`),
|
|
144
143
|
write(join(directory, 'kokkoro.json'), `${JSON.stringify(config, null, 2)}\n`),
|
|
145
|
-
write(join(directory, 'main.ts'),
|
|
144
|
+
write(join(directory, 'main.ts'), MAIN),
|
|
146
145
|
]);
|
|
147
146
|
|
|
148
147
|
console.log('\n项目创建完成,请依次运行以下命令:\n');
|