@kotori-bot/loader 1.2.0 → 1.4.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 +27 -0
- package/lib/consts.d.ts +5 -1
- package/lib/consts.js +6 -2
- package/lib/index.d.ts +3 -2
- package/lib/index.js +19 -7
- package/lib/loader.d.ts +32 -5
- package/lib/loader.js +213 -81
- package/lib/log.d.ts +2 -2
- package/lib/log.js +10 -9
- package/lib/runner.d.ts +55 -0
- package/lib/runner.js +205 -0
- package/lib/service/database.d.ts +12 -0
- package/lib/service/database.js +43 -0
- package/lib/service/file.d.ts +10 -0
- package/lib/service/file.js +27 -0
- package/lib/service/server.d.ts +26 -0
- package/lib/service/server.js +60 -0
- package/lib/utils/logger.d.ts +15 -0
- package/lib/utils/logger.js +53 -0
- package/package.json +29 -7
- package/lib/global.d.ts +0 -25
- package/lib/global.js +0 -53
- package/lib/modules.d.ts +0 -18
- package/lib/modules.js +0 -84
package/README.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# @kotori-bot/core
|
|
2
|
+
|
|
3
|
+
```typescript
|
|
4
|
+
interface Context {
|
|
5
|
+
readonly baseDir: Runner['baseDir'];
|
|
6
|
+
readonly options: Runner['options'];
|
|
7
|
+
readonly [Symbols.modules]: Runner[typeof Symbols.modules];
|
|
8
|
+
loadAll(): void;
|
|
9
|
+
watcher(): void;
|
|
10
|
+
logger: Logger;
|
|
11
|
+
/* Service */
|
|
12
|
+
server: Server;
|
|
13
|
+
db: Database;
|
|
14
|
+
file: File;
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
- Loader
|
|
19
|
+
- Runner
|
|
20
|
+
- Server
|
|
21
|
+
- Database
|
|
22
|
+
- File
|
|
23
|
+
- log
|
|
24
|
+
|
|
25
|
+
## Reference
|
|
26
|
+
|
|
27
|
+
- [Kotori Docs](https://kotori.js.org/)
|
package/lib/consts.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export declare const DEV_FILE = ".ts";
|
|
2
2
|
export declare const BUILD_FILE = ".js";
|
|
3
|
-
export declare const DEV_IMPORT = "./src/index.ts";
|
|
4
3
|
export declare const DEV_CODE_DIRS = "./src/";
|
|
4
|
+
export declare const DEV_IMPORT = "./src/index.ts";
|
|
5
|
+
export declare const BUILD_CONFIG_NAME = "kotori.yml";
|
|
6
|
+
export declare const DEV_CONFIG_NAME = "kotori.dev.yml";
|
|
7
|
+
export declare const SUPPORTS_VERSION: RegExp;
|
|
8
|
+
export declare const SUPPORTS_HALF_VERSION: RegExp;
|
package/lib/consts.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.SUPPORTS_HALF_VERSION = exports.SUPPORTS_VERSION = exports.DEV_CONFIG_NAME = exports.BUILD_CONFIG_NAME = exports.DEV_IMPORT = exports.DEV_CODE_DIRS = exports.BUILD_FILE = exports.DEV_FILE = void 0;
|
|
4
4
|
exports.DEV_FILE = '.ts';
|
|
5
5
|
exports.BUILD_FILE = '.js';
|
|
6
|
-
exports.DEV_IMPORT = './src/index.ts';
|
|
7
6
|
exports.DEV_CODE_DIRS = './src/';
|
|
7
|
+
exports.DEV_IMPORT = `${exports.DEV_CODE_DIRS}index.ts`;
|
|
8
|
+
exports.BUILD_CONFIG_NAME = 'kotori.yml';
|
|
9
|
+
exports.DEV_CONFIG_NAME = 'kotori.dev.yml';
|
|
10
|
+
exports.SUPPORTS_VERSION = /(1\.1\.0)|(1\.2\.0)/;
|
|
11
|
+
exports.SUPPORTS_HALF_VERSION = /(x\.x\.(.*?))/;
|
package/lib/index.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
1
|
+
export * from './loader';
|
|
2
|
+
export * from './consts';
|
|
3
|
+
export * from '@kotori-bot/logger';
|
package/lib/index.js
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
2
|
/*
|
|
7
3
|
* @Author: Hotaru biyuehuya@gmail.com
|
|
8
4
|
* @Blog: https://hotaru.icu
|
|
9
5
|
* @Date: 2023-10-29 16:20:51
|
|
10
6
|
* @LastEditors: Hotaru biyuehuya@gmail.com
|
|
11
|
-
* @LastEditTime:
|
|
7
|
+
* @LastEditTime: 2024-02-20 20:20:54
|
|
12
8
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
21
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
22
|
+
};
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
__exportStar(require("./loader"), exports);
|
|
25
|
+
__exportStar(require("./consts"), exports);
|
|
26
|
+
__exportStar(require("@kotori-bot/logger"), exports);
|
package/lib/loader.d.ts
CHANGED
|
@@ -1,13 +1,40 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { Container, Symbols } from '@kotori-bot/core';
|
|
2
|
+
import Logger from '@kotori-bot/logger';
|
|
3
|
+
import Runner from './runner';
|
|
4
|
+
import Server from './service/server';
|
|
5
|
+
import Database from './service/database';
|
|
6
|
+
import File from './service/file';
|
|
7
|
+
declare module '@kotori-bot/core' {
|
|
8
|
+
interface Context {
|
|
9
|
+
readonly baseDir: Runner['baseDir'];
|
|
10
|
+
readonly options: Runner['options'];
|
|
11
|
+
readonly [Symbols.modules]: Runner[typeof Symbols.modules];
|
|
12
|
+
loadAll(): void;
|
|
13
|
+
watcher(): void;
|
|
14
|
+
logger: Logger;
|
|
15
|
+
server: Server;
|
|
16
|
+
db: Database;
|
|
17
|
+
file: File;
|
|
18
|
+
}
|
|
19
|
+
interface GlobalConfig {
|
|
20
|
+
dirs: string[];
|
|
21
|
+
port: number;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export declare class Loader extends Container {
|
|
3
25
|
private ctx;
|
|
4
|
-
|
|
26
|
+
private loadCount;
|
|
27
|
+
constructor(options?: {
|
|
28
|
+
dir?: string;
|
|
29
|
+
mode?: string;
|
|
30
|
+
});
|
|
5
31
|
run(): void;
|
|
6
32
|
private handleError;
|
|
7
33
|
private catchError;
|
|
8
34
|
private listenMessage;
|
|
9
|
-
private
|
|
35
|
+
private setPreService;
|
|
36
|
+
private loadAllModules;
|
|
10
37
|
private loadAllAdapter;
|
|
11
38
|
private checkUpdate;
|
|
12
39
|
}
|
|
13
|
-
export default
|
|
40
|
+
export default Loader;
|
package/lib/loader.js
CHANGED
|
@@ -1,130 +1,262 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
27
|
};
|
|
5
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.Loader = void 0;
|
|
6
30
|
/*
|
|
7
31
|
* @Author: hotaru biyuehuya@gmail.com
|
|
8
32
|
* @Blog: https://hotaru.icu
|
|
9
33
|
* @Date: 2023-06-24 15:12:55
|
|
10
34
|
* @LastEditors: Hotaru biyuehuya@gmail.com
|
|
11
|
-
* @LastEditTime:
|
|
35
|
+
* @LastEditTime: 2024-02-21 11:35:04
|
|
12
36
|
*/
|
|
13
37
|
const core_1 = require("@kotori-bot/core");
|
|
14
|
-
const
|
|
15
|
-
const
|
|
38
|
+
const path_1 = __importDefault(require("path"));
|
|
39
|
+
const fs_1 = __importDefault(require("fs"));
|
|
40
|
+
const logger_1 = __importDefault(require("@kotori-bot/logger"));
|
|
41
|
+
const runner_1 = __importStar(require("./runner"));
|
|
16
42
|
const log_1 = __importDefault(require("./log"));
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
43
|
+
const consts_1 = require("./consts");
|
|
44
|
+
const server_1 = __importDefault(require("./service/server"));
|
|
45
|
+
const database_1 = __importDefault(require("./service/database"));
|
|
46
|
+
const file_1 = __importDefault(require("./service/file"));
|
|
47
|
+
function getRunnerConfig(file, dir) {
|
|
48
|
+
const handle = (root) => {
|
|
49
|
+
const baseDir = {
|
|
50
|
+
root,
|
|
51
|
+
modules: path_1.default.join(root, 'modules'),
|
|
52
|
+
data: path_1.default.join(root, 'data'),
|
|
53
|
+
logs: path_1.default.join(root, 'logs')
|
|
54
|
+
};
|
|
55
|
+
Object.values(baseDir).forEach((val) => {
|
|
56
|
+
if (!fs_1.default.existsSync(val))
|
|
57
|
+
fs_1.default.mkdirSync(val);
|
|
58
|
+
});
|
|
59
|
+
return baseDir;
|
|
26
60
|
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
61
|
+
const options = {
|
|
62
|
+
mode: file === consts_1.DEV_CONFIG_NAME ? 'dev' : 'build'
|
|
63
|
+
};
|
|
64
|
+
if (dir)
|
|
65
|
+
return { baseDir: handle(path_1.default.resolve(dir)), options };
|
|
66
|
+
let root = path_1.default.resolve(__dirname, '..').replace('loader', 'kotori');
|
|
67
|
+
let count = 0;
|
|
68
|
+
while (!fs_1.default.existsSync(path_1.default.join(root, file))) {
|
|
69
|
+
if (count > 5) {
|
|
70
|
+
logger_1.default.fatal(`cannot find file ${file} `);
|
|
71
|
+
process.exit();
|
|
72
|
+
}
|
|
73
|
+
root = path_1.default.join(root, '..');
|
|
74
|
+
count += 1;
|
|
75
|
+
}
|
|
76
|
+
return { baseDir: handle(root), options };
|
|
77
|
+
}
|
|
78
|
+
/* eslint consistent-return: 0 */
|
|
79
|
+
function getCoreConfig(file, baseDir) {
|
|
80
|
+
try {
|
|
81
|
+
const result1 = core_1.Tsu.Object({
|
|
82
|
+
global: core_1.Tsu.Object({
|
|
83
|
+
dirs: core_1.Tsu.Array(core_1.Tsu.String()).default([]),
|
|
84
|
+
port: core_1.Tsu.Number().default(core_1.DEFAULT_PORT),
|
|
85
|
+
lang: runner_1.localeTypeSchema.default(core_1.DEFAULT_CORE_CONFIG.global.lang),
|
|
86
|
+
'command-prefix': core_1.Tsu.String().default(core_1.DEFAULT_CORE_CONFIG.global['command-prefix'])
|
|
87
|
+
}),
|
|
88
|
+
plugin: core_1.Tsu.Object({})
|
|
89
|
+
.index(core_1.Tsu.Object({
|
|
90
|
+
filter: core_1.Tsu.Object({}).default({})
|
|
91
|
+
}).default({ filter: {} }))
|
|
92
|
+
.default(core_1.DEFAULT_CORE_CONFIG.plugin)
|
|
93
|
+
})
|
|
94
|
+
.default({ global: Object.assign(core_1.DEFAULT_CORE_CONFIG.global), plugin: core_1.DEFAULT_CORE_CONFIG.plugin })
|
|
95
|
+
.parse((0, core_1.loadConfig)(path_1.default.join(baseDir.root, file), 'yaml'));
|
|
96
|
+
return core_1.Tsu.Object({
|
|
97
|
+
adapter: core_1.Tsu.Object({})
|
|
98
|
+
.index(core_1.Tsu.Object({
|
|
99
|
+
extends: core_1.Tsu.String(),
|
|
100
|
+
master: core_1.Tsu.Union([core_1.Tsu.Number(), core_1.Tsu.String()]),
|
|
101
|
+
lang: runner_1.localeTypeSchema.default(result1.global.lang),
|
|
102
|
+
'command-prefix': core_1.Tsu.String().default(result1.global['command-prefix'])
|
|
103
|
+
}))
|
|
104
|
+
.default(core_1.DEFAULT_CORE_CONFIG.adapter)
|
|
105
|
+
}).parse(result1);
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
if (!(err instanceof core_1.TsuError))
|
|
109
|
+
throw err;
|
|
110
|
+
logger_1.default.fatal(`file ${file} format error: ${err.message}`);
|
|
111
|
+
process.exit();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
class Loader extends core_1.Container {
|
|
30
115
|
ctx;
|
|
31
|
-
|
|
116
|
+
loadCount = 0;
|
|
117
|
+
constructor(options) {
|
|
32
118
|
super();
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
119
|
+
const file = options && options.mode === 'dev' ? consts_1.DEV_CONFIG_NAME : consts_1.BUILD_CONFIG_NAME;
|
|
120
|
+
const runnerConfig = getRunnerConfig(file, options?.dir);
|
|
121
|
+
const ctx = new core_1.Core(getCoreConfig(file, runnerConfig.baseDir));
|
|
122
|
+
ctx.provide('runner', new runner_1.default(ctx, runnerConfig));
|
|
123
|
+
ctx.mixin('runner', ['baseDir', 'options']);
|
|
124
|
+
core_1.Container.setInstance(ctx);
|
|
125
|
+
this.ctx = core_1.Container.getInstance();
|
|
36
126
|
}
|
|
37
127
|
run() {
|
|
38
|
-
(0, log_1.default)(this.ctx.
|
|
128
|
+
(0, log_1.default)(this.ctx.pkg, this.ctx);
|
|
39
129
|
this.catchError();
|
|
40
130
|
this.listenMessage();
|
|
41
|
-
this.
|
|
131
|
+
this.setPreService();
|
|
132
|
+
this.loadAllModules();
|
|
42
133
|
this.checkUpdate();
|
|
43
134
|
}
|
|
44
135
|
handleError(err, prefix) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
136
|
+
if (!(err instanceof core_1.KotoriError)) {
|
|
137
|
+
if (err instanceof Error) {
|
|
138
|
+
this.ctx.logger.label(prefix).error(err.message, err.stack);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
this.ctx.logger.label(prefix).error(err);
|
|
142
|
+
}
|
|
48
143
|
return;
|
|
49
144
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
145
|
+
const list = {
|
|
146
|
+
ServiceError: () => this.ctx.logger.label('service').warn,
|
|
147
|
+
ModuleError: () => this.ctx.logger.label('module').error,
|
|
148
|
+
UnknownError: () => this.ctx.logger.error,
|
|
149
|
+
DevError: () => this.ctx.logger.label('error').debug
|
|
150
|
+
};
|
|
151
|
+
list[err.name]().bind(this.ctx.logger)(err.message, err.stack);
|
|
56
152
|
}
|
|
57
153
|
catchError() {
|
|
58
|
-
process.on('uncaughtExceptionMonitor', err => this.handleError(err, '
|
|
59
|
-
process.on('unhandledRejection', err => this.handleError(err, '
|
|
60
|
-
process.on('SIGINT', () =>
|
|
61
|
-
|
|
62
|
-
});
|
|
63
|
-
this.ctx.logger.debug('Run info: develop with debuing...');
|
|
154
|
+
process.on('uncaughtExceptionMonitor', (err) => this.handleError(err, 'sync'));
|
|
155
|
+
process.on('unhandledRejection', (err) => this.handleError(err, 'async'));
|
|
156
|
+
process.on('SIGINT', () => process.exit());
|
|
157
|
+
this.ctx.logger.debug('run info: develop with debuing...');
|
|
64
158
|
}
|
|
65
159
|
listenMessage() {
|
|
66
|
-
|
|
67
|
-
|
|
160
|
+
this.ctx.on('connect', (data) => {
|
|
161
|
+
const { type, mode, normal, address, adapter } = data;
|
|
162
|
+
let msg;
|
|
163
|
+
if (type === 'connect') {
|
|
164
|
+
switch (mode) {
|
|
165
|
+
case 'ws':
|
|
166
|
+
msg = `${normal ? 'Connect' : 'Reconnect'} server to ${address}`;
|
|
167
|
+
break;
|
|
168
|
+
case 'ws-reverse':
|
|
169
|
+
msg = `server ${normal ? 'start' : 'restart'} at ${address}`;
|
|
170
|
+
break;
|
|
171
|
+
default:
|
|
172
|
+
msg = `ready completed about ${address}`;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
switch (mode) {
|
|
177
|
+
case 'ws':
|
|
178
|
+
msg = `disconnect server from ${address}${normal ? '' : ' unexpectedly'}`;
|
|
179
|
+
break;
|
|
180
|
+
case 'ws-reverse':
|
|
181
|
+
msg = `server stop at ${address}${normal ? '' : ' unexpectedly'}`;
|
|
182
|
+
break;
|
|
183
|
+
default:
|
|
184
|
+
msg = `dispose completed about ${address}`;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
adapter.ctx.logger[normal ? 'info' : 'warn'](msg);
|
|
188
|
+
});
|
|
189
|
+
this.ctx.on('status', (data) => {
|
|
190
|
+
const { status, adapter } = data;
|
|
191
|
+
adapter.ctx.logger.info(status);
|
|
192
|
+
});
|
|
193
|
+
this.ctx.on('ready_module', (data) => {
|
|
194
|
+
if (typeof data.instance !== 'object')
|
|
68
195
|
return;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
this.ctx.on('load_module', data => {
|
|
74
|
-
if (!data.module)
|
|
196
|
+
const pkg = data.instance.name
|
|
197
|
+
? this.ctx.get('runner')[core_1.Symbols.modules].get(data.instance.name)
|
|
198
|
+
: undefined;
|
|
199
|
+
if (!pkg)
|
|
75
200
|
return;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
201
|
+
this.loadCount += 1;
|
|
202
|
+
const { name, version, author, peerDependencies } = pkg[0].pkg;
|
|
203
|
+
this.ctx.logger.info(`loaded module ${name} version: ${version} ${Array.isArray(author) ? `authors: ${author.join(',')}` : `author: ${author}`}`);
|
|
204
|
+
const requiredVersion = peerDependencies['kotori-bot'];
|
|
205
|
+
if (!requiredVersion.includes('workspace') &&
|
|
206
|
+
(!consts_1.SUPPORTS_VERSION.exec(requiredVersion) || requiredVersion !== this.ctx.pkg.version)) {
|
|
207
|
+
if (consts_1.SUPPORTS_HALF_VERSION.exec(requiredVersion)) {
|
|
208
|
+
this.ctx.logger.warn(`incomplete supported module version: ${requiredVersion}`);
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
this.ctx.logger.error(`unsupported module version: ${requiredVersion}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
83
214
|
});
|
|
84
215
|
}
|
|
85
|
-
|
|
86
|
-
this.ctx.
|
|
87
|
-
|
|
88
|
-
|
|
216
|
+
setPreService() {
|
|
217
|
+
this.ctx.service('server', new server_1.default(this.ctx.extends(), { port: this.ctx.config.global.port }));
|
|
218
|
+
this.ctx.service('db', new database_1.default(this.ctx.extends()));
|
|
219
|
+
this.ctx.service('file', new file_1.default(this.ctx.extends()));
|
|
220
|
+
}
|
|
221
|
+
loadAllModules() {
|
|
222
|
+
this.ctx.get('runner').loadAll();
|
|
223
|
+
const failLoadCount = this.ctx.get('runner')[core_1.Symbols.modules].size - this.loadCount;
|
|
224
|
+
this.ctx.logger.info(`loaded ${this.loadCount} modules successfully${failLoadCount > 0 ? `, failed to load ${failLoadCount} modules` : ''} `);
|
|
225
|
+
this.loadAllAdapter();
|
|
226
|
+
this.ctx.emit('ready');
|
|
89
227
|
}
|
|
90
228
|
loadAllAdapter() {
|
|
91
|
-
const adapters = this.ctx.
|
|
92
|
-
Object.keys(this.ctx.config.adapter).forEach(botName => {
|
|
229
|
+
const adapters = this.ctx[core_1.Symbols.adapter];
|
|
230
|
+
Object.keys(this.ctx.config.adapter).forEach((botName) => {
|
|
93
231
|
const botConfig = this.ctx.config.adapter[botName];
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
const array = adapters[botConfig.extends];
|
|
99
|
-
const isSchema = array[1]?.parseSafe(botConfig);
|
|
100
|
-
if (isSchema && !isSchema.value) {
|
|
232
|
+
const array = adapters.get(botConfig.extends);
|
|
233
|
+
if (!array) {
|
|
234
|
+
this.ctx.logger.warn(`cannot find adapter '${botConfig.extends}' for ${botName}`);
|
|
101
235
|
return;
|
|
102
236
|
}
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
bot.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
apis.forEach(api => adapters.push(api.adapter));
|
|
111
|
-
}); */
|
|
112
|
-
// this.ctx.emit({ type: 'adapters', adapters });
|
|
237
|
+
const result = array[1]?.parseSafe(botConfig);
|
|
238
|
+
if (result && !result.value)
|
|
239
|
+
throw new core_1.ModuleError(`Config format of adapter ${botName} is error: ${result.error.message}`);
|
|
240
|
+
const bot = new array[0](this.ctx.extends({}, `${botConfig.extends}/${botName}`), result ? result.data : botConfig, botName);
|
|
241
|
+
this.ctx.on('ready', () => bot.start());
|
|
242
|
+
this.ctx.on('dispose', () => bot.stop());
|
|
243
|
+
});
|
|
113
244
|
}
|
|
114
245
|
async checkUpdate() {
|
|
115
|
-
const { version } = this.ctx.
|
|
246
|
+
const { version } = this.ctx.pkg;
|
|
116
247
|
const res = await this.ctx.http
|
|
117
|
-
.get(
|
|
118
|
-
.catch(() => this.ctx.logger.error('
|
|
248
|
+
.get("https://hotaru.icu/api/agent/?url=https://raw.githubusercontent.com/kotorijs/kotori/master/packages/kotori/package.json" /* GLOBAL.UPDATE */)
|
|
249
|
+
.catch(() => this.ctx.logger.error('get update failed, please check your network'));
|
|
119
250
|
if (!res || !core_1.Tsu.Object({ version: core_1.Tsu.String() }).check(res)) {
|
|
120
|
-
this.ctx.logger.
|
|
251
|
+
this.ctx.logger.warn(`detection update failed`);
|
|
121
252
|
}
|
|
122
253
|
else if (version === res.version) {
|
|
123
|
-
this.ctx.logger.
|
|
254
|
+
this.ctx.logger.info('kotori is currently the latest version');
|
|
124
255
|
}
|
|
125
256
|
else {
|
|
126
|
-
this.ctx.logger.warn(`
|
|
257
|
+
this.ctx.logger.warn(`the current version of Kotori is ${version}, and the latest version is ${res.version}. please go to ${"https://github.com/kotorijs/kotori" /* GLOBAL.REPO */} to update`);
|
|
127
258
|
}
|
|
128
259
|
}
|
|
129
260
|
}
|
|
130
|
-
exports.
|
|
261
|
+
exports.Loader = Loader;
|
|
262
|
+
exports.default = Loader;
|
package/lib/log.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { Context
|
|
2
|
-
export declare function loadInfo(info:
|
|
1
|
+
import type { Context } from '@kotori-bot/core';
|
|
2
|
+
export declare function loadInfo(info: Context['pkg'], ctx: Context): void;
|
|
3
3
|
export default loadInfo;
|
package/lib/log.js
CHANGED
|
@@ -2,18 +2,19 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.loadInfo = void 0;
|
|
4
4
|
function loadInfo(info, ctx) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
██╗ ██╗ ██████╗ ████████╗ ██████╗ ██████╗ ██╗
|
|
8
|
-
██║ ██╔╝██╔═══██╗╚══██╔══╝██╔═══██╗██╔══██╗██║
|
|
9
|
-
█████╔╝ ██║ ██║ ██║ ██║ ██║██████╔╝██║
|
|
10
|
-
██╔═██╗ ██║ ██║ ██║ ██║ ██║██╔══██╗██║
|
|
11
|
-
██║ ██╗╚██████╔╝ ██║ ╚██████╔╝██║ ██║██║
|
|
12
|
-
╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝
|
|
5
|
+
process.stdout.write('Kotori Bot is loading...');
|
|
6
|
+
process.stdout.write(`
|
|
7
|
+
██╗ ██╗ ██████╗ ████████╗ ██████╗ ██████╗ ██╗
|
|
8
|
+
██║ ██╔╝██╔═══██╗╚══██╔══╝██╔═══██╗██╔══██╗██║
|
|
9
|
+
█████╔╝ ██║ ██║ ██║ ██║ ██║██████╔╝██║
|
|
10
|
+
██╔═██╗ ██║ ██║ ██║ ██║ ██║██╔══██╗██║
|
|
11
|
+
██║ ██╗╚██████╔╝ ██║ ╚██████╔╝██║ ██║██║
|
|
12
|
+
╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝
|
|
13
13
|
`);
|
|
14
|
+
ctx.logger.info('loader base dir:', ctx.baseDir.root);
|
|
14
15
|
ctx.logger.info(`Kotori Bot Version: ${info.version} License: ${info.license}`);
|
|
15
16
|
ctx.logger.info(`Kotori Bot By ${info.author}`);
|
|
16
|
-
ctx.logger.info(`Copyright © 2023 ${info.author} All rights reserved
|
|
17
|
+
ctx.logger.info(`Copyright © 2023 - 2024 ${info.author} All rights reserved`);
|
|
17
18
|
}
|
|
18
19
|
exports.loadInfo = loadInfo;
|
|
19
20
|
exports.default = loadInfo;
|
package/lib/runner.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Context, LocaleType, ModuleConfig, Symbols } from '@kotori-bot/core';
|
|
2
|
+
interface BaseDir {
|
|
3
|
+
root: string;
|
|
4
|
+
modules: string;
|
|
5
|
+
data: string;
|
|
6
|
+
logs: string;
|
|
7
|
+
}
|
|
8
|
+
interface Options {
|
|
9
|
+
mode: 'dev' | 'build';
|
|
10
|
+
}
|
|
11
|
+
interface RunnerConfig {
|
|
12
|
+
baseDir: BaseDir;
|
|
13
|
+
options: Options;
|
|
14
|
+
}
|
|
15
|
+
interface ModulePackage {
|
|
16
|
+
name: string;
|
|
17
|
+
version: string;
|
|
18
|
+
description: string;
|
|
19
|
+
main: string;
|
|
20
|
+
keywords: string[];
|
|
21
|
+
license: 'GPL-3.0';
|
|
22
|
+
author: string | string[];
|
|
23
|
+
peerDependencies: {
|
|
24
|
+
'kotori-bot': string;
|
|
25
|
+
[propName: string]: string;
|
|
26
|
+
};
|
|
27
|
+
kotori: {
|
|
28
|
+
enforce?: 'pre' | 'post';
|
|
29
|
+
meta: {
|
|
30
|
+
language: LocaleType[];
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
interface ModuleMeta {
|
|
35
|
+
pkg: ModulePackage;
|
|
36
|
+
files: string[];
|
|
37
|
+
main: string;
|
|
38
|
+
}
|
|
39
|
+
export declare const localeTypeSchema: import("@kotori-bot/core").UnionParser<[import("@kotori-bot/core").UnionParser<[import("@kotori-bot/core").LiteralParser<"en_US">, import("@kotori-bot/core").LiteralParser<"ja_JP">]>, import("@kotori-bot/core").UnionParser<[import("@kotori-bot/core").LiteralParser<"zh_TW">, import("@kotori-bot/core").AnyParser<any>]>]>;
|
|
40
|
+
export declare class Runner {
|
|
41
|
+
readonly baseDir: BaseDir;
|
|
42
|
+
readonly options: Options;
|
|
43
|
+
private ctx;
|
|
44
|
+
private isDev;
|
|
45
|
+
readonly [Symbols.modules]: Map<string, [ModuleMeta, ModuleConfig]>;
|
|
46
|
+
constructor(ctx: Context, config: RunnerConfig);
|
|
47
|
+
private getDirFiles;
|
|
48
|
+
private getModuleRootDir;
|
|
49
|
+
private getModuleList;
|
|
50
|
+
private loadEx;
|
|
51
|
+
private unloadEx;
|
|
52
|
+
loadAll(): void;
|
|
53
|
+
watcher(): void;
|
|
54
|
+
}
|
|
55
|
+
export default Runner;
|
package/lib/runner.js
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.Runner = exports.localeTypeSchema = void 0;
|
|
30
|
+
const fs_1 = __importStar(require("fs"));
|
|
31
|
+
const path_1 = __importDefault(require("path"));
|
|
32
|
+
const core_1 = require("@kotori-bot/core");
|
|
33
|
+
const logger_1 = require("@kotori-bot/logger");
|
|
34
|
+
const consts_1 = require("./consts");
|
|
35
|
+
const logger_2 = __importDefault(require("./utils/logger"));
|
|
36
|
+
exports.localeTypeSchema = core_1.Tsu.Union([
|
|
37
|
+
core_1.Tsu.Union([core_1.Tsu.Literal('en_US'), core_1.Tsu.Literal('ja_JP')]),
|
|
38
|
+
core_1.Tsu.Union([core_1.Tsu.Literal('zh_TW'), core_1.Tsu.Any()])
|
|
39
|
+
]);
|
|
40
|
+
const modulePackageSchema = core_1.Tsu.Object({
|
|
41
|
+
name: core_1.Tsu.String().regexp(/kotori-plugin-[a-z]([a-z,0-9]{2,13})\b/),
|
|
42
|
+
version: core_1.Tsu.String(),
|
|
43
|
+
description: core_1.Tsu.String(),
|
|
44
|
+
main: core_1.Tsu.String(),
|
|
45
|
+
license: core_1.Tsu.Literal('GPL-3.0'),
|
|
46
|
+
keywords: core_1.Tsu.Custom((val) => Array.isArray(val) && val.includes('kotori') && val.includes('chatbot') && val.includes('kotori-plugin')),
|
|
47
|
+
author: core_1.Tsu.Union([core_1.Tsu.String(), core_1.Tsu.Array(core_1.Tsu.String())]),
|
|
48
|
+
peerDependencies: core_1.Tsu.Object({
|
|
49
|
+
'kotori-bot': core_1.Tsu.String()
|
|
50
|
+
}),
|
|
51
|
+
kotori: core_1.Tsu.Object({
|
|
52
|
+
enforce: core_1.Tsu.Union([core_1.Tsu.Literal('pre'), core_1.Tsu.Literal('post')]).optional(),
|
|
53
|
+
meta: core_1.Tsu.Object({
|
|
54
|
+
language: core_1.Tsu.Array(exports.localeTypeSchema).default([])
|
|
55
|
+
}).default({ language: [] })
|
|
56
|
+
}).default({
|
|
57
|
+
enforce: undefined,
|
|
58
|
+
meta: { language: [] }
|
|
59
|
+
})
|
|
60
|
+
});
|
|
61
|
+
function moduleLoadOrder(pkg) {
|
|
62
|
+
if (pkg.name.includes(core_1.DATABASE_PREFIX))
|
|
63
|
+
return 1;
|
|
64
|
+
if (pkg.name.includes(core_1.ADAPTER_PREFIX))
|
|
65
|
+
return 2;
|
|
66
|
+
// if (CORE_MODULES.includes(pkg.name)) return 3;
|
|
67
|
+
if (pkg.kotori.enforce === 'pre')
|
|
68
|
+
return 4;
|
|
69
|
+
if (!pkg.kotori.enforce)
|
|
70
|
+
return 5;
|
|
71
|
+
return 6;
|
|
72
|
+
}
|
|
73
|
+
class Runner {
|
|
74
|
+
baseDir;
|
|
75
|
+
options;
|
|
76
|
+
ctx;
|
|
77
|
+
isDev;
|
|
78
|
+
[core_1.Symbols.modules] = new Map();
|
|
79
|
+
constructor(ctx, config) {
|
|
80
|
+
this.ctx = ctx;
|
|
81
|
+
/* handle config */
|
|
82
|
+
this.baseDir = config.baseDir;
|
|
83
|
+
this.options = config.options;
|
|
84
|
+
this.isDev = this.options.mode === 'dev';
|
|
85
|
+
const loggerOptions = {
|
|
86
|
+
level: this.isDev ? logger_1.LoggerLevel.TRACE : logger_1.LoggerLevel.INFO,
|
|
87
|
+
label: [],
|
|
88
|
+
transports: [
|
|
89
|
+
new logger_1.ConsoleTransport(),
|
|
90
|
+
new logger_1.FileTransport({ dir: this.baseDir.logs, filter: (data) => data.level >= logger_1.LoggerLevel.WARN })
|
|
91
|
+
]
|
|
92
|
+
};
|
|
93
|
+
ctx.provide('logger', new logger_2.default(loggerOptions, this.ctx));
|
|
94
|
+
ctx.inject('logger');
|
|
95
|
+
}
|
|
96
|
+
getDirFiles(rootDir) {
|
|
97
|
+
const files = fs_1.default.readdirSync(rootDir);
|
|
98
|
+
const list = [];
|
|
99
|
+
files.forEach((fileName) => {
|
|
100
|
+
const file = path_1.default.join(rootDir, fileName);
|
|
101
|
+
if (fs_1.default.statSync(file).isDirectory()) {
|
|
102
|
+
list.push(...this.getDirFiles(file));
|
|
103
|
+
}
|
|
104
|
+
if (path_1.default.parse(file).ext !== (this.isDev ? consts_1.DEV_FILE : consts_1.BUILD_FILE))
|
|
105
|
+
return;
|
|
106
|
+
list.push(path_1.default.resolve(file));
|
|
107
|
+
});
|
|
108
|
+
return list;
|
|
109
|
+
}
|
|
110
|
+
getModuleRootDir() {
|
|
111
|
+
const moduleRootDir = [];
|
|
112
|
+
[
|
|
113
|
+
...this.ctx.config.global.dirs.map((dir) => path_1.default.resolve(this.ctx.baseDir.root, dir)),
|
|
114
|
+
this.ctx.baseDir.modules
|
|
115
|
+
].forEach((dir) => {
|
|
116
|
+
if (fs_1.default.existsSync(dir) && fs_1.default.statSync(dir).isDirectory())
|
|
117
|
+
moduleRootDir.push(dir);
|
|
118
|
+
});
|
|
119
|
+
return moduleRootDir;
|
|
120
|
+
}
|
|
121
|
+
getModuleList(rootDir) {
|
|
122
|
+
fs_1.default.readdirSync(rootDir).forEach(async (fileName) => {
|
|
123
|
+
const dir = path_1.default.join(rootDir, fileName);
|
|
124
|
+
if (!fs_1.default.statSync(dir).isDirectory())
|
|
125
|
+
return;
|
|
126
|
+
if (rootDir !== this.ctx.baseDir.modules && !fileName.startsWith(core_1.PLUGIN_PREFIX))
|
|
127
|
+
return;
|
|
128
|
+
const packagePath = path_1.default.join(dir, 'package.json');
|
|
129
|
+
let pkg;
|
|
130
|
+
if (!fs_1.default.existsSync(packagePath))
|
|
131
|
+
return;
|
|
132
|
+
try {
|
|
133
|
+
pkg = JSON.parse(fs_1.default.readFileSync(packagePath).toString());
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
throw new core_1.DevError(`illegal package.json ${packagePath}`);
|
|
137
|
+
}
|
|
138
|
+
const result = modulePackageSchema.parseSafe(pkg);
|
|
139
|
+
if (!result.value) {
|
|
140
|
+
if (rootDir !== this.ctx.baseDir.modules)
|
|
141
|
+
return;
|
|
142
|
+
throw new core_1.DevError(`package.json format error ${packagePath}: ${result.error.message}`);
|
|
143
|
+
}
|
|
144
|
+
pkg = result.data;
|
|
145
|
+
const devMode = this.isDev && (0, fs_1.existsSync)(path_1.default.resolve(dir, consts_1.DEV_IMPORT));
|
|
146
|
+
const main = path_1.default.resolve(dir, devMode ? consts_1.DEV_IMPORT : pkg.main);
|
|
147
|
+
if (!fs_1.default.existsSync(main))
|
|
148
|
+
throw new core_1.DevError(`cannot find ${main}`);
|
|
149
|
+
const dirs = path_1.default.join(dir, devMode ? consts_1.DEV_CODE_DIRS : path_1.default.dirname(pkg.main));
|
|
150
|
+
const files = fs_1.default.statSync(dirs).isDirectory() ? this.getDirFiles(dirs) : [];
|
|
151
|
+
this[core_1.Symbols.modules].set(pkg.name, [
|
|
152
|
+
{ pkg, files, main },
|
|
153
|
+
this.ctx.config.plugin[(0, core_1.stringRightSplit)(pkg.name, core_1.PLUGIN_PREFIX)] || {}
|
|
154
|
+
]);
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
loadEx(instance, config) {
|
|
158
|
+
const { main, pkg } = instance;
|
|
159
|
+
/* eslint-disable-next-line import/no-dynamic-require, global-require, @typescript-eslint/no-var-requires */
|
|
160
|
+
let obj = require(main);
|
|
161
|
+
let handle = config;
|
|
162
|
+
const adapterName = pkg.name.split(core_1.ADAPTER_PREFIX)[1];
|
|
163
|
+
if (core_1.Adapter.isPrototypeOf.call(core_1.Adapter, obj.default) &&
|
|
164
|
+
adapterName &&
|
|
165
|
+
(!obj.config || obj.config instanceof core_1.Parser)) {
|
|
166
|
+
this.ctx[core_1.Symbols.adapter].set(adapterName, [obj.default, obj.config]);
|
|
167
|
+
obj = {};
|
|
168
|
+
}
|
|
169
|
+
else if (core_1.Service.isPrototypeOf.call(core_1.Service, obj.default)) {
|
|
170
|
+
obj = {};
|
|
171
|
+
}
|
|
172
|
+
else if (obj.config instanceof core_1.Parser) {
|
|
173
|
+
const result = obj.config.parseSafe(handle);
|
|
174
|
+
if (!result.value)
|
|
175
|
+
throw new core_1.ModuleError(`Config format of module ${pkg.name} is error: ${result.error.message}`);
|
|
176
|
+
handle = result.data;
|
|
177
|
+
}
|
|
178
|
+
if (obj.lang)
|
|
179
|
+
this.ctx.i18n.use(Array.isArray(obj.lang) ? path_1.default.resolve(...obj.lang) : path_1.default.resolve(obj.lang));
|
|
180
|
+
this.ctx.load({ name: pkg.name, ...obj, config: handle });
|
|
181
|
+
}
|
|
182
|
+
unloadEx(instance) {
|
|
183
|
+
instance.files.forEach((file) => delete require.cache[require.resolve(file)]);
|
|
184
|
+
this.ctx.load({ name: instance.pkg.name });
|
|
185
|
+
}
|
|
186
|
+
loadAll() {
|
|
187
|
+
this.getModuleRootDir().forEach((dir) => this.getModuleList(dir));
|
|
188
|
+
const modules = [];
|
|
189
|
+
this[core_1.Symbols.modules].forEach((val) => modules.push(val));
|
|
190
|
+
modules
|
|
191
|
+
.sort((el1, el2) => moduleLoadOrder(el1[0].pkg) - moduleLoadOrder(el2[0].pkg))
|
|
192
|
+
.forEach((el) => this.loadEx(...el));
|
|
193
|
+
if (this.isDev)
|
|
194
|
+
this.watcher();
|
|
195
|
+
}
|
|
196
|
+
watcher() {
|
|
197
|
+
this[core_1.Symbols.modules].forEach((data) => data[0].files.forEach((file) => fs_1.default.watchFile(file, async () => {
|
|
198
|
+
this.ctx.logger.debug(`file happen changed, module ${data[0].pkg.name} is reloading...`);
|
|
199
|
+
this.unloadEx(data[0]);
|
|
200
|
+
this.loadEx(...data);
|
|
201
|
+
})));
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
exports.Runner = Runner;
|
|
205
|
+
exports.default = Runner;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Context, Service } from '@kotori-bot/core';
|
|
2
|
+
import knex from 'knex';
|
|
3
|
+
export declare class Database extends Service {
|
|
4
|
+
internal: ReturnType<typeof knex>;
|
|
5
|
+
select: ReturnType<typeof knex>['select'];
|
|
6
|
+
delete: ReturnType<typeof knex>['delete'];
|
|
7
|
+
update: ReturnType<typeof knex>['update'];
|
|
8
|
+
insert: ReturnType<typeof knex>['insert'];
|
|
9
|
+
schema: ReturnType<typeof knex>['schema'];
|
|
10
|
+
constructor(ctx: Context);
|
|
11
|
+
}
|
|
12
|
+
export default Database;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Database = void 0;
|
|
7
|
+
const core_1 = require("@kotori-bot/core");
|
|
8
|
+
const knex_1 = __importDefault(require("knex"));
|
|
9
|
+
const path_1 = require("path");
|
|
10
|
+
class Database extends core_1.Service {
|
|
11
|
+
internal;
|
|
12
|
+
select;
|
|
13
|
+
delete;
|
|
14
|
+
update;
|
|
15
|
+
insert;
|
|
16
|
+
schema;
|
|
17
|
+
constructor(ctx) {
|
|
18
|
+
super(ctx, {}, 'database');
|
|
19
|
+
this.internal = (0, knex_1.default)({
|
|
20
|
+
client: 'sqlite',
|
|
21
|
+
connection: {
|
|
22
|
+
filename: (0, path_1.resolve)(this.ctx.baseDir.root, 'kotori.db')
|
|
23
|
+
},
|
|
24
|
+
useNullAsDefault: true
|
|
25
|
+
} /* {
|
|
26
|
+
client: 'mysql',
|
|
27
|
+
connection: {
|
|
28
|
+
host: '127.0.0.1',
|
|
29
|
+
port: 3306,
|
|
30
|
+
user: 'kotori',
|
|
31
|
+
password: 'kotori',
|
|
32
|
+
database: 'kotori'
|
|
33
|
+
}
|
|
34
|
+
} */);
|
|
35
|
+
this.select = this.internal.select.bind(this.internal);
|
|
36
|
+
this.delete = this.internal.delete.bind(this.internal);
|
|
37
|
+
this.update = this.internal.update.bind(this.internal);
|
|
38
|
+
this.insert = this.internal.insert.bind(this.internal);
|
|
39
|
+
this.schema = this.internal.schema;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.Database = Database;
|
|
43
|
+
exports.default = Database;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Context, Service, createConfig, loadConfig, saveConfig } from '@kotori-bot/core';
|
|
2
|
+
export declare class File extends Service {
|
|
3
|
+
constructor(ctx: Context);
|
|
4
|
+
getDir(): string;
|
|
5
|
+
getFile(filename: string): string;
|
|
6
|
+
load(filename: string, type?: Parameters<typeof loadConfig>[1], init?: Parameters<typeof loadConfig>[2]): string | object | unknown[] | null;
|
|
7
|
+
save(filename: string, data: Parameters<typeof saveConfig>[1], type?: Parameters<typeof saveConfig>[2]): void;
|
|
8
|
+
create(filename: string, data?: Parameters<typeof createConfig>[1], type?: Parameters<typeof createConfig>[2]): void;
|
|
9
|
+
}
|
|
10
|
+
export default File;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.File = void 0;
|
|
4
|
+
const core_1 = require("@kotori-bot/core");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
class File extends core_1.Service {
|
|
7
|
+
constructor(ctx) {
|
|
8
|
+
super(ctx, {}, 'file');
|
|
9
|
+
}
|
|
10
|
+
getDir() {
|
|
11
|
+
return (0, path_1.join)(this.ctx.baseDir.data, ...(this.ctx.identity ? this.ctx.identity.split('/') : []));
|
|
12
|
+
}
|
|
13
|
+
getFile(filename) {
|
|
14
|
+
return (0, path_1.join)(this.getDir(), filename);
|
|
15
|
+
}
|
|
16
|
+
load(filename, type, init) {
|
|
17
|
+
return (0, core_1.loadConfig)(this.getFile(filename), type, init);
|
|
18
|
+
}
|
|
19
|
+
save(filename, data, type) {
|
|
20
|
+
(0, core_1.saveConfig)(this.getFile(filename), data, type);
|
|
21
|
+
}
|
|
22
|
+
create(filename, data, type) {
|
|
23
|
+
(0, core_1.createConfig)(this.getFile(filename), data, type);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.File = File;
|
|
27
|
+
exports.default = File;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/// <reference types="body-parser" />
|
|
2
|
+
/// <reference types="connect" />
|
|
3
|
+
/// <reference types="serve-static" />
|
|
4
|
+
import { Context, Service } from '@kotori-bot/core';
|
|
5
|
+
import express from 'express';
|
|
6
|
+
interface ServerConfig {
|
|
7
|
+
port: number;
|
|
8
|
+
}
|
|
9
|
+
export declare class Server extends Service<ServerConfig> {
|
|
10
|
+
private app;
|
|
11
|
+
private server?;
|
|
12
|
+
constructor(ctx: Context, config: ServerConfig);
|
|
13
|
+
start(): void;
|
|
14
|
+
stop(): void;
|
|
15
|
+
get: Server['app']['get'];
|
|
16
|
+
post: Server['app']['post'];
|
|
17
|
+
patch: Server['app']['patch'];
|
|
18
|
+
put: Server['app']['put'];
|
|
19
|
+
delete: Server['app']['delete'];
|
|
20
|
+
all: Server['app']['all'];
|
|
21
|
+
use: Server['app']['use'];
|
|
22
|
+
router: typeof express.Router;
|
|
23
|
+
json: (options?: import("body-parser").OptionsJson | undefined) => import("connect").NextHandleFunction;
|
|
24
|
+
static: import("serve-static").RequestHandlerConstructor<express.Response<any, Record<string, any>>>;
|
|
25
|
+
}
|
|
26
|
+
export default Server;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Server = void 0;
|
|
7
|
+
const core_1 = require("@kotori-bot/core");
|
|
8
|
+
const express_1 = __importDefault(require("express"));
|
|
9
|
+
class Server extends core_1.Service {
|
|
10
|
+
app;
|
|
11
|
+
server;
|
|
12
|
+
constructor(ctx, config) {
|
|
13
|
+
super(ctx, config, 'server');
|
|
14
|
+
this.app = (0, express_1.default)();
|
|
15
|
+
this.app.use('/', (_, res, next) => {
|
|
16
|
+
let isWebui = false;
|
|
17
|
+
ctx[core_1.Symbols.modules].forEach((module) => {
|
|
18
|
+
if (isWebui)
|
|
19
|
+
return;
|
|
20
|
+
if (module[0].pkg.name === '@kotori-bot/kotori-plugin-webui')
|
|
21
|
+
isWebui = true;
|
|
22
|
+
});
|
|
23
|
+
if (!isWebui) {
|
|
24
|
+
res.setHeader('Content-type', 'text/html');
|
|
25
|
+
res.send(/* html */ `<h1>Welcome to kotori!</h1>`);
|
|
26
|
+
}
|
|
27
|
+
next();
|
|
28
|
+
});
|
|
29
|
+
this.get = this.app.get.bind(this.app);
|
|
30
|
+
this.post = this.app.post.bind(this.app);
|
|
31
|
+
this.patch = this.app.patch.bind(this.app);
|
|
32
|
+
this.put = this.app.put.bind(this.app);
|
|
33
|
+
this.delete = this.app.delete.bind(this.app);
|
|
34
|
+
this.use = this.app.use.bind(this.app);
|
|
35
|
+
this.all = this.app.all.bind(this.app);
|
|
36
|
+
}
|
|
37
|
+
start() {
|
|
38
|
+
if (this.server)
|
|
39
|
+
return;
|
|
40
|
+
this.server = this.app.listen(this.config.port);
|
|
41
|
+
this.ctx.logger.label('server').info(`server start at http://127.0.0.1:${this.config.port}`);
|
|
42
|
+
}
|
|
43
|
+
stop() {
|
|
44
|
+
if (!this.server)
|
|
45
|
+
return;
|
|
46
|
+
this.server.close();
|
|
47
|
+
}
|
|
48
|
+
get;
|
|
49
|
+
post;
|
|
50
|
+
patch;
|
|
51
|
+
put;
|
|
52
|
+
delete;
|
|
53
|
+
all;
|
|
54
|
+
use;
|
|
55
|
+
router = express_1.default.Router;
|
|
56
|
+
json = express_1.default.json;
|
|
57
|
+
static = express_1.default.static;
|
|
58
|
+
}
|
|
59
|
+
exports.Server = Server;
|
|
60
|
+
exports.default = Server;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Context } from '@kotori-bot/core';
|
|
2
|
+
import { Logger } from '@kotori-bot/logger';
|
|
3
|
+
export declare class KotoriLogger extends Logger {
|
|
4
|
+
private optionsSelf;
|
|
5
|
+
private ctx;
|
|
6
|
+
constructor(optionsSelf: Logger['options'], ctx: Context);
|
|
7
|
+
private setLabel;
|
|
8
|
+
fatal(...args: unknown[]): void;
|
|
9
|
+
error(...args: unknown[]): void;
|
|
10
|
+
warn(...args: unknown[]): void;
|
|
11
|
+
info(...args: unknown[]): void;
|
|
12
|
+
debug(...args: unknown[]): void;
|
|
13
|
+
trace(...args: unknown[]): void;
|
|
14
|
+
}
|
|
15
|
+
export default KotoriLogger;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KotoriLogger = void 0;
|
|
4
|
+
const logger_1 = require("@kotori-bot/logger");
|
|
5
|
+
class KotoriLogger extends logger_1.Logger {
|
|
6
|
+
optionsSelf;
|
|
7
|
+
ctx;
|
|
8
|
+
constructor(optionsSelf, ctx) {
|
|
9
|
+
super(optionsSelf);
|
|
10
|
+
this.optionsSelf = optionsSelf;
|
|
11
|
+
this.ctx = ctx;
|
|
12
|
+
}
|
|
13
|
+
setLabel() {
|
|
14
|
+
const origin = Object.create(this.optionsSelf.label);
|
|
15
|
+
const label = this.ctx.identity ? [this.ctx.identity, ...this.optionsSelf.label] : this.optionsSelf.label;
|
|
16
|
+
this[(() => 'options')()].label = label;
|
|
17
|
+
return () => {
|
|
18
|
+
this[(() => 'options')()].label = origin;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
fatal(...args) {
|
|
22
|
+
const dispose = this.setLabel();
|
|
23
|
+
super.fatal(...args);
|
|
24
|
+
dispose();
|
|
25
|
+
}
|
|
26
|
+
error(...args) {
|
|
27
|
+
const dispose = this.setLabel();
|
|
28
|
+
super.error(...args);
|
|
29
|
+
dispose();
|
|
30
|
+
}
|
|
31
|
+
warn(...args) {
|
|
32
|
+
const dispose = this.setLabel();
|
|
33
|
+
super.warn(...args);
|
|
34
|
+
dispose();
|
|
35
|
+
}
|
|
36
|
+
info(...args) {
|
|
37
|
+
const dispose = this.setLabel();
|
|
38
|
+
super.info(...args);
|
|
39
|
+
dispose();
|
|
40
|
+
}
|
|
41
|
+
debug(...args) {
|
|
42
|
+
const dispose = this.setLabel();
|
|
43
|
+
super.debug(...args);
|
|
44
|
+
dispose();
|
|
45
|
+
}
|
|
46
|
+
trace(...args) {
|
|
47
|
+
const dispose = this.setLabel();
|
|
48
|
+
super.trace(...args);
|
|
49
|
+
dispose();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.KotoriLogger = KotoriLogger;
|
|
53
|
+
exports.default = KotoriLogger;
|
package/package.json
CHANGED
|
@@ -1,18 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kotori-bot/loader",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Loader For KotoriBot",
|
|
5
5
|
"license": "GPL-3.0",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"author": "Hotaru <biyuehuya@gmail.com>",
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
|
|
8
|
+
"keywords": [
|
|
9
|
+
"kotori",
|
|
10
|
+
"chatbot",
|
|
11
|
+
"loader"
|
|
12
|
+
],
|
|
11
13
|
"files": [
|
|
12
|
-
"lib"
|
|
14
|
+
"lib",
|
|
15
|
+
"LICENSE",
|
|
16
|
+
"README.md"
|
|
13
17
|
],
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/kotorijs/kotori/issues"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/kotorijs/kotori.git"
|
|
24
|
+
},
|
|
25
|
+
"homepage": "https://kotori.js.org",
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"express": "^4.18.2",
|
|
28
|
+
"knex": "^3.1.0",
|
|
29
|
+
"sqlite3": "^5.1.7",
|
|
30
|
+
"@kotori-bot/logger": "^1.1.1",
|
|
31
|
+
"@kotori-bot/core": "^1.3.0"
|
|
32
|
+
},
|
|
14
33
|
"devDependencies": {
|
|
15
|
-
"
|
|
16
|
-
"
|
|
34
|
+
"@types/body-parser": "^1.19.5",
|
|
35
|
+
"@types/connect": "^3.4.38",
|
|
36
|
+
"@types/express": "^4.17.21",
|
|
37
|
+
"@types/express-serve-static-core": "^4.17.43",
|
|
38
|
+
"@types/serve-static": "^1.15.5"
|
|
17
39
|
}
|
|
18
40
|
}
|
package/lib/global.d.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { BaseDir } from '@kotori-bot/core';
|
|
2
|
-
export declare const isDev: () => boolean;
|
|
3
|
-
export declare const CONFIG_FILE: () => "kotori.dev.yml" | "kotori.yml";
|
|
4
|
-
export declare const getBaseDir: () => {
|
|
5
|
-
root: any;
|
|
6
|
-
modules: string;
|
|
7
|
-
};
|
|
8
|
-
export declare const getGlobalConfig: (baseDir: BaseDir) => import("@kotori-bot/core").ObjectParserInfer<{
|
|
9
|
-
global: import("@kotori-bot/core").IntersectionParser<[import("@kotori-bot/core").ObjectParser<{
|
|
10
|
-
dirs: import("@kotori-bot/core").ArrayParser<import("@kotori-bot/core").StringParser>;
|
|
11
|
-
}>, import("@kotori-bot/core").ObjectParser<{
|
|
12
|
-
lang: import("@kotori-bot/core").UnionParser<[import("@kotori-bot/core").UnionParser<[import("@kotori-bot/core").LiteralParser<"en_US">, import("@kotori-bot/core").LiteralParser<"ja_JP">]>, import("@kotori-bot/core").UnionParser<[import("@kotori-bot/core").LiteralParser<"zh_CN">, import("@kotori-bot/core").LiteralParser<"zh_TW">]>]>;
|
|
13
|
-
'command-prefix': import("@kotori-bot/core").StringParser;
|
|
14
|
-
}>]>;
|
|
15
|
-
adapter: import("@kotori-bot/core").Parser<import("@kotori-bot/core").IndexObject<import("@kotori-bot/core").ObjectParserInfer<{
|
|
16
|
-
extends: import("@kotori-bot/core").StringParser;
|
|
17
|
-
master: import("@kotori-bot/core").UnionParser<[import("@kotori-bot/core").NumberParser, import("@kotori-bot/core").StringParser]>;
|
|
18
|
-
}> & import("@kotori-bot/core").ObjectParserInfer<{
|
|
19
|
-
lang: import("@kotori-bot/core").UnionParser<[import("@kotori-bot/core").UnionParser<[import("@kotori-bot/core").LiteralParser<"en_US">, import("@kotori-bot/core").LiteralParser<"ja_JP">]>, import("@kotori-bot/core").UnionParser<[import("@kotori-bot/core").LiteralParser<"zh_CN">, import("@kotori-bot/core").LiteralParser<"zh_TW">]>]>;
|
|
20
|
-
'command-prefix': import("@kotori-bot/core").StringParser;
|
|
21
|
-
}>>>;
|
|
22
|
-
plugin: import("@kotori-bot/core").Parser<import("@kotori-bot/core").IndexObject<import("@kotori-bot/core").ObjectParserInfer<{
|
|
23
|
-
priority: import("@kotori-bot/core").NumberParser;
|
|
24
|
-
}>>>;
|
|
25
|
-
}>;
|
package/lib/global.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getGlobalConfig = exports.getBaseDir = exports.CONFIG_FILE = exports.isDev = void 0;
|
|
7
|
-
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const core_1 = require("@kotori-bot/core");
|
|
10
|
-
const isDev = () => globalThis.env_mode === 'dev';
|
|
11
|
-
exports.isDev = isDev;
|
|
12
|
-
const CONFIG_FILE = () => ((0, exports.isDev)() ? 'kotori.dev.yml' : 'kotori.yml');
|
|
13
|
-
exports.CONFIG_FILE = CONFIG_FILE;
|
|
14
|
-
const getBaseDir = () => {
|
|
15
|
-
const { env_dir: envDir } = globalThis;
|
|
16
|
-
if (envDir) {
|
|
17
|
-
return {
|
|
18
|
-
root: envDir,
|
|
19
|
-
modules: path_1.default.join(envDir, 'modules'),
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
let root = path_1.default.resolve(__dirname, '..').replace('loader', 'kotori');
|
|
23
|
-
let count = 0;
|
|
24
|
-
while (!fs_1.default.existsSync(path_1.default.join(root, (0, exports.CONFIG_FILE)()))) {
|
|
25
|
-
if (count > 5)
|
|
26
|
-
throw new core_1.CoreError(`cannot find kotori-bot global ${exports.CONFIG_FILE}`);
|
|
27
|
-
root = path_1.default.join(root, '..');
|
|
28
|
-
count += 1;
|
|
29
|
-
}
|
|
30
|
-
return {
|
|
31
|
-
root,
|
|
32
|
-
modules: path_1.default.join(root, 'modules'),
|
|
33
|
-
};
|
|
34
|
-
};
|
|
35
|
-
exports.getBaseDir = getBaseDir;
|
|
36
|
-
const getGlobalConfig = (baseDir) => {
|
|
37
|
-
const data = (0, core_1.loadConfig)(path_1.default.join(baseDir.root, (0, exports.CONFIG_FILE)()), 'yaml');
|
|
38
|
-
const isExistsGlobal = data && typeof data === 'object' && data.global && typeof data.global === 'object';
|
|
39
|
-
try {
|
|
40
|
-
if (!isExistsGlobal)
|
|
41
|
-
throw new core_1.TsuError('en_US', 'array_error');
|
|
42
|
-
const lang = data.global.lang ? core_1.localeTypeSchema.parse(data.global.lang) : undefined;
|
|
43
|
-
const commandPrefix = data.global['command-prefix'] ? data.global['command-prefix'] : undefined;
|
|
44
|
-
return (0, core_1.globalConfigSchemaController)(lang, commandPrefix).parse(data);
|
|
45
|
-
}
|
|
46
|
-
catch (err) {
|
|
47
|
-
if (!(err instanceof core_1.TsuError))
|
|
48
|
-
throw err;
|
|
49
|
-
// process.exit(1);
|
|
50
|
-
throw new core_1.CoreError(`kotori-bot global ${exports.CONFIG_FILE} format error: ${err.message}`);
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
exports.getGlobalConfig = getGlobalConfig;
|
package/lib/modules.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { Context } from '@kotori-bot/core';
|
|
2
|
-
declare module '@kotori-bot/core' {
|
|
3
|
-
interface Context {
|
|
4
|
-
readonly moduleAll?: () => void;
|
|
5
|
-
readonly watchFile?: () => void;
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
export declare class Modules extends Context {
|
|
9
|
-
private isDev;
|
|
10
|
-
private readonly moduleRootDir;
|
|
11
|
-
private getDirFiles;
|
|
12
|
-
private getModuleRootDir;
|
|
13
|
-
private getModuleList;
|
|
14
|
-
private moduleQuick;
|
|
15
|
-
readonly moduleAll: () => Promise<void>;
|
|
16
|
-
readonly watchFile: () => Promise<void>;
|
|
17
|
-
}
|
|
18
|
-
export default Modules;
|
package/lib/modules.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.Modules = void 0;
|
|
7
|
-
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const core_1 = require("@kotori-bot/core");
|
|
10
|
-
const consts_1 = require("./consts");
|
|
11
|
-
class Modules extends core_1.Context {
|
|
12
|
-
isDev = this.options.env === 'dev';
|
|
13
|
-
moduleRootDir = [];
|
|
14
|
-
getDirFiles(rootDir) {
|
|
15
|
-
const files = fs_1.default.readdirSync(rootDir);
|
|
16
|
-
const list = [];
|
|
17
|
-
files.forEach(fileName => {
|
|
18
|
-
const file = path_1.default.join(rootDir, fileName);
|
|
19
|
-
if (fs_1.default.statSync(file).isDirectory()) {
|
|
20
|
-
list.push(...this.getDirFiles(file));
|
|
21
|
-
}
|
|
22
|
-
if (path_1.default.parse(file).ext !== (this.isDev ? consts_1.DEV_FILE : consts_1.BUILD_FILE))
|
|
23
|
-
return;
|
|
24
|
-
list.push(path_1.default.resolve(file));
|
|
25
|
-
});
|
|
26
|
-
return list;
|
|
27
|
-
}
|
|
28
|
-
getModuleRootDir() {
|
|
29
|
-
Object.assign(this.config.global.dirs, [this.baseDir.modules]).forEach(dir => {
|
|
30
|
-
if (fs_1.default.existsSync(dir) && fs_1.default.statSync(dir).isDirectory())
|
|
31
|
-
this.moduleRootDir.push(dir);
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
getModuleList(rootDir) {
|
|
35
|
-
const files = fs_1.default.readdirSync(rootDir);
|
|
36
|
-
files.forEach(fileName => {
|
|
37
|
-
const dir = path_1.default.join(rootDir, fileName);
|
|
38
|
-
if (!fs_1.default.statSync(dir).isDirectory())
|
|
39
|
-
return;
|
|
40
|
-
if (rootDir !== this.baseDir.modules && fileName.startsWith(core_1.PLUGIN_PREFIX))
|
|
41
|
-
return;
|
|
42
|
-
const packagePath = path_1.default.join(dir, 'package.json');
|
|
43
|
-
let packageJson;
|
|
44
|
-
if (!fs_1.default.existsSync(packagePath))
|
|
45
|
-
return;
|
|
46
|
-
try {
|
|
47
|
-
packageJson = JSON.parse(fs_1.default.readFileSync(packagePath).toString());
|
|
48
|
-
}
|
|
49
|
-
catch {
|
|
50
|
-
throw new core_1.DevError(`illegal package.json ${packagePath}`);
|
|
51
|
-
}
|
|
52
|
-
const result = core_1.ModulePackageSchema.parseSafe(packageJson);
|
|
53
|
-
if (!result.value && rootDir === this.baseDir.modules) {
|
|
54
|
-
throw new core_1.DevError(`package.json format error ${packagePath}: ${result.error.message}`);
|
|
55
|
-
}
|
|
56
|
-
const mainPath = path_1.default.join(dir, this.isDev ? consts_1.DEV_IMPORT : packageJson.main);
|
|
57
|
-
if (!fs_1.default.existsSync(mainPath))
|
|
58
|
-
throw new core_1.DevError(`cannot find ${mainPath}`);
|
|
59
|
-
const codeDirs = path_1.default.join(dir, this.isDev ? consts_1.DEV_CODE_DIRS : path_1.default.dirname(packageJson.main));
|
|
60
|
-
this.moduleStack.push({
|
|
61
|
-
package: packageJson,
|
|
62
|
-
fileList: fs_1.default.statSync(codeDirs).isDirectory() ? this.getDirFiles(codeDirs) : [],
|
|
63
|
-
mainPath: path_1.default.resolve(mainPath),
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
moduleQuick(moduleData) {
|
|
68
|
-
return this.use(moduleData, this, this.config.plugin[(0, core_1.stringRightSplit)(moduleData.package.name, core_1.PLUGIN_PREFIX)] ?? {});
|
|
69
|
-
}
|
|
70
|
-
moduleAll = async () => {
|
|
71
|
-
this.getModuleRootDir();
|
|
72
|
-
this.moduleRootDir.forEach(dir => {
|
|
73
|
-
this.getModuleList(dir);
|
|
74
|
-
});
|
|
75
|
-
const array = this.moduleStack.filter(data => data.package.name.startsWith(core_1.OFFICIAL_MODULES_SCOPE));
|
|
76
|
-
array.push(...this.moduleStack.filter(data => !array.includes(data)));
|
|
77
|
-
array.forEach(moduleData => this.moduleQuick(moduleData));
|
|
78
|
-
};
|
|
79
|
-
watchFile = async () => {
|
|
80
|
-
this.moduleStack.forEach(moduleData => moduleData.fileList.forEach(file => fs_1.default.watchFile(file, () => this.dispose(moduleData) && this.moduleQuick(moduleData))));
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
exports.Modules = Modules;
|
|
84
|
-
exports.default = Modules;
|