@yumerijs/core 1.3.3 → 2.0.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/dist/context.d.ts +32 -13
- package/dist/context.js +103 -28
- package/dist/core.d.ts +4 -1
- package/dist/core.js +6 -1
- package/dist/hook.js +2 -2
- package/dist/i18n.d.ts +29 -0
- package/dist/i18n.js +79 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/logger.d.ts +5 -1
- package/dist/logger.js +3 -3
- package/dist/route.d.ts +7 -0
- package/dist/route.js +122 -104
- package/dist/server.d.ts +1 -4
- package/dist/server.js +48 -92
- package/dist/session.d.ts +45 -3
- package/dist/session.js +167 -15
- package/package.json +2 -2
package/dist/context.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @time: 2025/
|
|
2
|
+
* @time: 2025/10/25 01:30
|
|
3
3
|
* @author: FireGuo
|
|
4
4
|
* WindyPear-Team All right reserved
|
|
5
5
|
**/
|
|
@@ -7,6 +7,13 @@ import { Core } from './core';
|
|
|
7
7
|
import { Route } from './route';
|
|
8
8
|
import { HookHandler } from './hook';
|
|
9
9
|
import { Middleware } from './middleware';
|
|
10
|
+
import { Config } from './config';
|
|
11
|
+
interface Plugin {
|
|
12
|
+
apply: (ctx: Context, config: Config) => Promise<void>;
|
|
13
|
+
disable: (ctx: Context) => Promise<void>;
|
|
14
|
+
depend: Array<string>;
|
|
15
|
+
provide: Array<string>;
|
|
16
|
+
}
|
|
10
17
|
/**
|
|
11
18
|
* 插件上下文对象
|
|
12
19
|
* 每个插件一个 Context,用于管理插件注册的命令、路由、事件、组件和中间件
|
|
@@ -18,9 +25,10 @@ export declare class Context {
|
|
|
18
25
|
private components;
|
|
19
26
|
private middlewares;
|
|
20
27
|
private hooks;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
28
|
+
private childContexts;
|
|
29
|
+
private childPlugins;
|
|
30
|
+
private i18ns;
|
|
31
|
+
/** 插件名称 */
|
|
24
32
|
pluginname: string;
|
|
25
33
|
/**
|
|
26
34
|
* 创建 Context 实例
|
|
@@ -57,25 +65,19 @@ export declare class Context {
|
|
|
57
65
|
* 执行 Hook 钩子
|
|
58
66
|
* @param name Hook 点名称
|
|
59
67
|
* @param args Hook 参数
|
|
60
|
-
* @returns Promise<any[]>
|
|
61
68
|
*/
|
|
62
69
|
executeHook(name: string, ...args: any[]): Promise<any[]>;
|
|
63
|
-
/**
|
|
64
|
-
* 获取 Core 实例
|
|
65
|
-
* @returns Core
|
|
66
|
-
*/
|
|
70
|
+
/** 获取 Core 实例 */
|
|
67
71
|
getCore(): Core;
|
|
68
72
|
/**
|
|
69
73
|
* 触发事件
|
|
70
74
|
* @param event 事件名称
|
|
71
75
|
* @param args 事件参数
|
|
72
|
-
* @returns Promise<void>
|
|
73
76
|
*/
|
|
74
77
|
emit(event: string, ...args: any[]): Promise<void>;
|
|
75
78
|
/**
|
|
76
79
|
* 获取组件实例
|
|
77
80
|
* @param name 组件名称
|
|
78
|
-
* @returns 组件实例
|
|
79
81
|
*/
|
|
80
82
|
getComponent(name: string): any;
|
|
81
83
|
/**
|
|
@@ -84,9 +86,26 @@ export declare class Context {
|
|
|
84
86
|
* @param component 组件实例
|
|
85
87
|
*/
|
|
86
88
|
registerComponent(name: string, component: any): void;
|
|
89
|
+
/**
|
|
90
|
+
* 注册子 Context
|
|
91
|
+
* @param name 子 Context 名称
|
|
92
|
+
*/
|
|
93
|
+
fork(name?: string): Context;
|
|
94
|
+
/**
|
|
95
|
+
* 注册子插件
|
|
96
|
+
* @param plugin 插件实例
|
|
97
|
+
* @param config 插件配置
|
|
98
|
+
*/
|
|
99
|
+
apply(plugin: Plugin, config: Config): Promise<void>;
|
|
100
|
+
/**
|
|
101
|
+
* 注册 i18n
|
|
102
|
+
* @param content 内容(可以是嵌套对象或单个key)
|
|
103
|
+
* @param locale 可选的语言映射
|
|
104
|
+
*/
|
|
105
|
+
i18n(content: string | Record<string, any>, locale?: Record<string, string>): void;
|
|
87
106
|
/**
|
|
88
107
|
* 卸载插件时清理注册的所有资源
|
|
89
|
-
* 包括组件、路由、中间件和事件监听器
|
|
90
108
|
*/
|
|
91
|
-
dispose(): void
|
|
109
|
+
dispose(): Promise<void>;
|
|
92
110
|
}
|
|
111
|
+
export {};
|
package/dist/context.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @time: 2025/10/25 01:30
|
|
4
|
+
* @author: FireGuo
|
|
5
|
+
* WindyPear-Team All right reserved
|
|
6
|
+
**/
|
|
2
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
8
|
exports.Context = void 0;
|
|
4
9
|
const route_1 = require("./route");
|
|
@@ -13,9 +18,10 @@ class Context {
|
|
|
13
18
|
components = [];
|
|
14
19
|
middlewares = [];
|
|
15
20
|
hooks = {};
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
childContexts = [];
|
|
22
|
+
childPlugins = new Map();
|
|
23
|
+
i18ns = [];
|
|
24
|
+
/** 插件名称 */
|
|
19
25
|
pluginname;
|
|
20
26
|
/**
|
|
21
27
|
* 创建 Context 实例
|
|
@@ -25,6 +31,7 @@ class Context {
|
|
|
25
31
|
constructor(core, pluginname) {
|
|
26
32
|
this.core = core;
|
|
27
33
|
this.pluginname = pluginname;
|
|
34
|
+
this.childPlugins = new Map();
|
|
28
35
|
}
|
|
29
36
|
/**
|
|
30
37
|
* 注册路由
|
|
@@ -45,9 +52,9 @@ class Context {
|
|
|
45
52
|
* @param listener 事件监听器
|
|
46
53
|
*/
|
|
47
54
|
on(name, listener) {
|
|
48
|
-
|
|
55
|
+
if (!listener)
|
|
56
|
+
return;
|
|
49
57
|
this.eventlisteners.push({ name, listener });
|
|
50
|
-
// 注册到 core 的全局事件监听器中
|
|
51
58
|
this.core.on(name, listener);
|
|
52
59
|
}
|
|
53
60
|
/**
|
|
@@ -56,6 +63,8 @@ class Context {
|
|
|
56
63
|
* @param callback 中间件回调函数
|
|
57
64
|
*/
|
|
58
65
|
use(name, callback) {
|
|
66
|
+
if (!callback)
|
|
67
|
+
return;
|
|
59
68
|
this.middlewares.push(name);
|
|
60
69
|
this.core.use(name, callback);
|
|
61
70
|
}
|
|
@@ -66,22 +75,22 @@ class Context {
|
|
|
66
75
|
* @param callback 钩子回调函数
|
|
67
76
|
*/
|
|
68
77
|
hook(name, hookname, callback) {
|
|
78
|
+
if (!callback || !hookname)
|
|
79
|
+
return;
|
|
69
80
|
this.core.hook(name, hookname, callback);
|
|
81
|
+
if (!this.hooks[name])
|
|
82
|
+
this.hooks[name] = [];
|
|
70
83
|
this.hooks[name].push(hookname);
|
|
71
84
|
}
|
|
72
85
|
/**
|
|
73
86
|
* 执行 Hook 钩子
|
|
74
87
|
* @param name Hook 点名称
|
|
75
88
|
* @param args Hook 参数
|
|
76
|
-
* @returns Promise<any[]>
|
|
77
89
|
*/
|
|
78
90
|
async executeHook(name, ...args) {
|
|
79
91
|
return await this.core.hookExecute(name, ...args);
|
|
80
92
|
}
|
|
81
|
-
/**
|
|
82
|
-
* 获取 Core 实例
|
|
83
|
-
* @returns Core
|
|
84
|
-
*/
|
|
93
|
+
/** 获取 Core 实例 */
|
|
85
94
|
getCore() {
|
|
86
95
|
return this.core;
|
|
87
96
|
}
|
|
@@ -89,7 +98,6 @@ class Context {
|
|
|
89
98
|
* 触发事件
|
|
90
99
|
* @param event 事件名称
|
|
91
100
|
* @param args 事件参数
|
|
92
|
-
* @returns Promise<void>
|
|
93
101
|
*/
|
|
94
102
|
async emit(event, ...args) {
|
|
95
103
|
return await this.core.emit(event, ...args);
|
|
@@ -97,7 +105,6 @@ class Context {
|
|
|
97
105
|
/**
|
|
98
106
|
* 获取组件实例
|
|
99
107
|
* @param name 组件名称
|
|
100
|
-
* @returns 组件实例
|
|
101
108
|
*/
|
|
102
109
|
getComponent(name) {
|
|
103
110
|
return this.core.getComponent(name);
|
|
@@ -108,6 +115,8 @@ class Context {
|
|
|
108
115
|
* @param component 组件实例
|
|
109
116
|
*/
|
|
110
117
|
registerComponent(name, component) {
|
|
118
|
+
if (!component)
|
|
119
|
+
return;
|
|
111
120
|
if (this.core.components[name]) {
|
|
112
121
|
this.core.logger.warn(`Plugin "${this.pluginname}" attempt to register component "${name}", but it has already been registered.`);
|
|
113
122
|
return;
|
|
@@ -115,41 +124,107 @@ class Context {
|
|
|
115
124
|
this.core.components[name] = component;
|
|
116
125
|
this.components.push(name);
|
|
117
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* 注册子 Context
|
|
129
|
+
* @param name 子 Context 名称
|
|
130
|
+
*/
|
|
131
|
+
fork(name = this.pluginname) {
|
|
132
|
+
const ctx = new Context(this.core, name);
|
|
133
|
+
this.childContexts.push(ctx);
|
|
134
|
+
return ctx;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* 注册子插件
|
|
138
|
+
* @param plugin 插件实例
|
|
139
|
+
* @param config 插件配置
|
|
140
|
+
*/
|
|
141
|
+
async apply(plugin, config) {
|
|
142
|
+
if (!plugin || !plugin.apply)
|
|
143
|
+
return;
|
|
144
|
+
const ctx = this.fork();
|
|
145
|
+
await plugin.apply(ctx, config);
|
|
146
|
+
this.childPlugins.set(ctx, plugin);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* 注册 i18n
|
|
150
|
+
* @param content 内容(可以是嵌套对象或单个key)
|
|
151
|
+
* @param locale 可选的语言映射
|
|
152
|
+
*/
|
|
153
|
+
i18n(content, locale) {
|
|
154
|
+
if (!this.i18ns)
|
|
155
|
+
this.i18ns = [];
|
|
156
|
+
const isLangObject = (obj) => typeof obj === 'object' && Object.values(obj).every(v => typeof v === 'string');
|
|
157
|
+
const flatten = (obj, prefix = '') => {
|
|
158
|
+
const result = {};
|
|
159
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
160
|
+
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
161
|
+
if (isLangObject(value)) {
|
|
162
|
+
result[fullKey] = value;
|
|
163
|
+
}
|
|
164
|
+
else if (typeof value === 'object') {
|
|
165
|
+
Object.assign(result, flatten(value, fullKey));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return result;
|
|
169
|
+
};
|
|
170
|
+
if (typeof content === 'string' && locale) {
|
|
171
|
+
this.core.i18n.register(content, locale);
|
|
172
|
+
this.i18ns.push(content);
|
|
173
|
+
}
|
|
174
|
+
else if (typeof content === 'object') {
|
|
175
|
+
const flat = flatten(content);
|
|
176
|
+
this.core.i18n.register(flat);
|
|
177
|
+
this.i18ns.push(...Object.keys(flat));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
118
180
|
/**
|
|
119
181
|
* 卸载插件时清理注册的所有资源
|
|
120
|
-
* 包括组件、路由、中间件和事件监听器
|
|
121
182
|
*/
|
|
122
|
-
dispose() {
|
|
183
|
+
async dispose() {
|
|
123
184
|
// 删除组件
|
|
124
|
-
this.components.forEach((name) =>
|
|
125
|
-
delete this.core.components[name];
|
|
126
|
-
});
|
|
185
|
+
this.components.forEach((name) => delete this.core.components[name]);
|
|
127
186
|
// 删除路由
|
|
128
|
-
this.routes.forEach((route) =>
|
|
129
|
-
delete this.core.routes[route];
|
|
130
|
-
});
|
|
187
|
+
this.routes.forEach((route) => delete this.core.routes[route]);
|
|
131
188
|
// 删除中间件
|
|
132
|
-
this.middlewares.forEach((middleware) =>
|
|
133
|
-
delete this.core.globalMiddlewares[middleware];
|
|
134
|
-
});
|
|
189
|
+
this.middlewares.forEach((middleware) => delete this.core.globalMiddlewares[middleware]);
|
|
135
190
|
// 删除事件监听器
|
|
136
191
|
this.eventlisteners.forEach(({ name, listener }) => {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
192
|
+
const listeners = this.core.eventListeners?.[name];
|
|
193
|
+
if (listeners) {
|
|
194
|
+
this.core.eventListeners[name] = listeners.filter(l => l !== listener);
|
|
140
195
|
}
|
|
141
196
|
});
|
|
142
197
|
// 删除钩子
|
|
143
198
|
for (const hook in this.hooks) {
|
|
144
199
|
this.hooks[hook].forEach((hookname) => {
|
|
145
|
-
|
|
200
|
+
if (hookname)
|
|
201
|
+
this.core.unhook(hook, hookname);
|
|
146
202
|
});
|
|
147
203
|
}
|
|
148
|
-
//
|
|
204
|
+
// 卸载子插件(异步即可,不必按顺序)
|
|
205
|
+
this.childPlugins.forEach(async (plugin, ctx) => {
|
|
206
|
+
if (plugin?.disable)
|
|
207
|
+
await plugin.disable(ctx);
|
|
208
|
+
});
|
|
209
|
+
// 删除子上下文
|
|
210
|
+
this.childContexts.forEach((ctx) => {
|
|
211
|
+
if (ctx?.dispose)
|
|
212
|
+
ctx.dispose();
|
|
213
|
+
});
|
|
214
|
+
// 删除i18n
|
|
215
|
+
if (this.i18ns?.length) {
|
|
216
|
+
for (const key of this.i18ns) {
|
|
217
|
+
this.core.i18n.delete(key);
|
|
218
|
+
}
|
|
219
|
+
this.i18ns.length = 0;
|
|
220
|
+
}
|
|
221
|
+
// 清空内部记录
|
|
149
222
|
this.components = [];
|
|
150
223
|
this.routes = [];
|
|
151
224
|
this.middlewares = [];
|
|
152
225
|
this.eventlisteners = [];
|
|
226
|
+
this.hooks = {};
|
|
227
|
+
this.childContexts = [];
|
|
153
228
|
}
|
|
154
229
|
}
|
|
155
230
|
exports.Context = Context;
|
package/dist/core.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { Route } from './route';
|
|
|
6
6
|
import { Context } from './context';
|
|
7
7
|
import { HookHandler, Hook } from './hook';
|
|
8
8
|
import { Server as CoreServer } from './server';
|
|
9
|
+
import { I18n } from './i18n';
|
|
9
10
|
interface Plugin {
|
|
10
11
|
apply: (ctx: Context, config: Config) => Promise<void>;
|
|
11
12
|
disable: (ctx: Context) => Promise<void>;
|
|
@@ -25,6 +26,7 @@ interface CoreOptions {
|
|
|
25
26
|
staticDir: string;
|
|
26
27
|
enableCors: boolean;
|
|
27
28
|
enableWs: boolean;
|
|
29
|
+
lang: string[];
|
|
28
30
|
}
|
|
29
31
|
/**
|
|
30
32
|
* 定义插件状态枚举
|
|
@@ -56,6 +58,7 @@ export declare class Core {
|
|
|
56
58
|
hooks: Record<string, Hook>;
|
|
57
59
|
coreConfig: CoreOptions;
|
|
58
60
|
server: CoreServer;
|
|
61
|
+
i18n: I18n;
|
|
59
62
|
private pluginWatchers;
|
|
60
63
|
private pluginModules;
|
|
61
64
|
private configPath;
|
|
@@ -63,7 +66,7 @@ export declare class Core {
|
|
|
63
66
|
* 插件名 -> Context 映射
|
|
64
67
|
*/
|
|
65
68
|
private pluginContexts;
|
|
66
|
-
constructor(pluginLoader?: PluginLoader, coreConfig?: CoreOptions);
|
|
69
|
+
constructor(pluginLoader?: PluginLoader, coreConfig?: CoreOptions, setCore?: boolean);
|
|
67
70
|
/**
|
|
68
71
|
* 获取或创建插件对应 Context
|
|
69
72
|
*/
|
package/dist/core.js
CHANGED
|
@@ -49,6 +49,7 @@ const route_1 = require("./route");
|
|
|
49
49
|
const context_1 = require("./context");
|
|
50
50
|
const hook_1 = require("./hook");
|
|
51
51
|
const server_1 = require("./server");
|
|
52
|
+
const i18n_1 = require("./i18n");
|
|
52
53
|
class Core {
|
|
53
54
|
plugins = {};
|
|
54
55
|
config = null;
|
|
@@ -62,6 +63,7 @@ class Core {
|
|
|
62
63
|
hooks = {};
|
|
63
64
|
coreConfig;
|
|
64
65
|
server;
|
|
66
|
+
i18n;
|
|
65
67
|
pluginWatchers = {};
|
|
66
68
|
pluginModules = {};
|
|
67
69
|
configPath = '';
|
|
@@ -69,9 +71,11 @@ class Core {
|
|
|
69
71
|
* 插件名 -> Context 映射
|
|
70
72
|
*/
|
|
71
73
|
pluginContexts = {};
|
|
72
|
-
constructor(pluginLoader, coreConfig) {
|
|
74
|
+
constructor(pluginLoader, coreConfig, setCore = true) {
|
|
73
75
|
this.coreConfig = coreConfig;
|
|
74
76
|
this.pluginLoader = pluginLoader;
|
|
77
|
+
if (setCore)
|
|
78
|
+
logger_1.Logger.setCore(this);
|
|
75
79
|
}
|
|
76
80
|
/**
|
|
77
81
|
* 获取或创建插件对应 Context
|
|
@@ -111,6 +115,7 @@ class Core {
|
|
|
111
115
|
this.logger.error('Failed to load config:', e);
|
|
112
116
|
throw e;
|
|
113
117
|
}
|
|
118
|
+
this.i18n = new i18n_1.I18n(this.coreConfig.lang || ['zh', 'en']);
|
|
114
119
|
}
|
|
115
120
|
/**
|
|
116
121
|
* 启动应用
|
package/dist/hook.js
CHANGED
|
@@ -41,9 +41,9 @@ class Hook {
|
|
|
41
41
|
* @returns 执行结果
|
|
42
42
|
*/
|
|
43
43
|
async trigger(...args) {
|
|
44
|
-
let result;
|
|
44
|
+
let result = [];
|
|
45
45
|
for (const handler of Object.values(this.handlers)) {
|
|
46
|
-
result.push(handler(...args));
|
|
46
|
+
result.push(await handler(...args));
|
|
47
47
|
}
|
|
48
48
|
return result;
|
|
49
49
|
}
|
package/dist/i18n.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @time: 2025/10/28 22:13
|
|
3
|
+
* @author: FireGuo
|
|
4
|
+
* WindyPear-Team All right reserved
|
|
5
|
+
**/
|
|
6
|
+
type I18nData = Record<string, Record<string, string>>;
|
|
7
|
+
export declare class I18n {
|
|
8
|
+
private data;
|
|
9
|
+
private fallback;
|
|
10
|
+
constructor(fallback?: string[]);
|
|
11
|
+
register(key: string | Record<string, any>, lang?: Record<string, string>): void;
|
|
12
|
+
setFallback(fallback: string[]): void;
|
|
13
|
+
private flattenAndRegister;
|
|
14
|
+
isRegistered(key: string): boolean;
|
|
15
|
+
delete(key: string): void;
|
|
16
|
+
/**
|
|
17
|
+
* 获取指定key的翻译
|
|
18
|
+
* @param key 文本点
|
|
19
|
+
* @param langs 用户的语言优先级数组
|
|
20
|
+
*/
|
|
21
|
+
get(key: string, langs?: string[]): string;
|
|
22
|
+
/**
|
|
23
|
+
* 替换模板字符串中的文本点
|
|
24
|
+
* e.g. "Hello {{app.title}}" -> "Hello 世界"
|
|
25
|
+
*/
|
|
26
|
+
replaceAll(input: string, langs?: string[]): string;
|
|
27
|
+
all(): I18nData;
|
|
28
|
+
}
|
|
29
|
+
export {};
|
package/dist/i18n.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @time: 2025/10/28 22:13
|
|
4
|
+
* @author: FireGuo
|
|
5
|
+
* WindyPear-Team All right reserved
|
|
6
|
+
**/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.I18n = void 0;
|
|
9
|
+
class I18n {
|
|
10
|
+
data = {};
|
|
11
|
+
fallback;
|
|
12
|
+
constructor(fallback = ['en']) {
|
|
13
|
+
this.fallback = fallback;
|
|
14
|
+
}
|
|
15
|
+
register(key, lang) {
|
|
16
|
+
if (typeof key === 'string' && lang) {
|
|
17
|
+
if (!this.data[key])
|
|
18
|
+
this.data[key] = {};
|
|
19
|
+
Object.assign(this.data[key], lang);
|
|
20
|
+
}
|
|
21
|
+
else if (typeof key === 'object') {
|
|
22
|
+
this.flattenAndRegister(key);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
setFallback(fallback) {
|
|
26
|
+
this.fallback = fallback;
|
|
27
|
+
}
|
|
28
|
+
flattenAndRegister(obj, prefix = '') {
|
|
29
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
30
|
+
const fullKey = prefix ? `${prefix}.${k}` : k;
|
|
31
|
+
if (typeof v === 'object' && !('zh' in v || 'en' in v)) {
|
|
32
|
+
this.flattenAndRegister(v, fullKey);
|
|
33
|
+
}
|
|
34
|
+
else if (typeof v === 'object') {
|
|
35
|
+
if (!this.data[fullKey])
|
|
36
|
+
this.data[fullKey] = {};
|
|
37
|
+
Object.assign(this.data[fullKey], v);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
isRegistered(key) {
|
|
42
|
+
return !!this.data[key];
|
|
43
|
+
}
|
|
44
|
+
delete(key) {
|
|
45
|
+
delete this.data[key];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 获取指定key的翻译
|
|
49
|
+
* @param key 文本点
|
|
50
|
+
* @param langs 用户的语言优先级数组
|
|
51
|
+
*/
|
|
52
|
+
get(key, langs) {
|
|
53
|
+
const entry = this.data[key];
|
|
54
|
+
if (!entry)
|
|
55
|
+
return key;
|
|
56
|
+
if (langs && langs.length) {
|
|
57
|
+
for (const l of langs) {
|
|
58
|
+
if (entry[l])
|
|
59
|
+
return entry[l];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
for (const fb of this.fallback) {
|
|
63
|
+
if (entry[fb])
|
|
64
|
+
return entry[fb];
|
|
65
|
+
}
|
|
66
|
+
return key;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* 替换模板字符串中的文本点
|
|
70
|
+
* e.g. "Hello {{app.title}}" -> "Hello 世界"
|
|
71
|
+
*/
|
|
72
|
+
replaceAll(input, langs) {
|
|
73
|
+
return input.replace(/\{\{(.*?)\}\}/g, (_, key) => this.get(key.trim(), langs));
|
|
74
|
+
}
|
|
75
|
+
all() {
|
|
76
|
+
return this.data;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.I18n = I18n;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/logger.d.ts
CHANGED
|
@@ -8,7 +8,11 @@ export declare class Logger {
|
|
|
8
8
|
private title;
|
|
9
9
|
private titleColor;
|
|
10
10
|
static coreInstance: Core | null;
|
|
11
|
-
static logs:
|
|
11
|
+
static logs: {
|
|
12
|
+
level: string;
|
|
13
|
+
message: string;
|
|
14
|
+
timestamp: string;
|
|
15
|
+
}[];
|
|
12
16
|
static setCore(core: Core): void;
|
|
13
17
|
constructor(title: string);
|
|
14
18
|
private getRandomColor;
|
package/dist/logger.js
CHANGED
|
@@ -17,8 +17,7 @@ class Logger {
|
|
|
17
17
|
static logs = [];
|
|
18
18
|
static setCore(core) {
|
|
19
19
|
if (Logger.coreInstance !== null) {
|
|
20
|
-
|
|
21
|
-
logger.warn("Logger.coreInstance is already set. Overwriting would cause confusion.");
|
|
20
|
+
return;
|
|
22
21
|
}
|
|
23
22
|
Logger.coreInstance = core;
|
|
24
23
|
}
|
|
@@ -43,7 +42,8 @@ class Logger {
|
|
|
43
42
|
const levelColor = level === 'E' ? picocolors_1.default.red : level === 'W' ? picocolors_1.default.yellow : picocolors_1.default.cyan;
|
|
44
43
|
const timestamp = this.getTimestamp();
|
|
45
44
|
console.log(`${picocolors_1.default.gray(timestamp)} [${levelColor(level)}] ${this.titleColor(this.title)}`, ...args);
|
|
46
|
-
Logger.coreInstance?.emit('log', { level, message: args.join(' ') });
|
|
45
|
+
Logger.coreInstance?.emit('log', { level, message: args.join(' '), timestamp });
|
|
46
|
+
Logger.logs.push({ level, message: args.join(' '), timestamp });
|
|
47
47
|
}
|
|
48
48
|
info(...args) { this.log('I', ...args); }
|
|
49
49
|
warn(...args) { this.log('W', ...args); }
|
package/dist/route.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
**/
|
|
6
6
|
import { Session } from './session';
|
|
7
7
|
import { Middleware } from './middleware';
|
|
8
|
+
import { WebSocketServer } from 'ws';
|
|
8
9
|
export type RouteHandler = (session: Session, queryParams: URLSearchParams, ...pathParams: string[]) => Promise<void> | void;
|
|
9
10
|
/**
|
|
10
11
|
* Route class using segment-based matching (no fragile capture-group-index mapping).
|
|
@@ -21,6 +22,7 @@ export declare class Route {
|
|
|
21
22
|
private handler;
|
|
22
23
|
middlewares: Middleware[];
|
|
23
24
|
allowedMethods: string[];
|
|
25
|
+
ws: WebSocketServer;
|
|
24
26
|
/**
|
|
25
27
|
* 创建路由
|
|
26
28
|
* @param path 路由路径
|
|
@@ -60,4 +62,9 @@ export declare class Route {
|
|
|
60
62
|
* @returns this
|
|
61
63
|
*/
|
|
62
64
|
methods(...methods: string[]): Route;
|
|
65
|
+
/**
|
|
66
|
+
* 注册Ws处理器
|
|
67
|
+
* @param handler 处理器
|
|
68
|
+
*/
|
|
69
|
+
wsOn(event: string, handler: (...args: any[]) => void): this;
|
|
63
70
|
}
|