@yumerijs/core 3.0.0-alpha.3 → 3.0.0-alpha.6

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 CHANGED
@@ -3,6 +3,7 @@ import { Route } from './route.js';
3
3
  import { HookHandler } from './hook.js';
4
4
  import { Middleware } from './middleware.js';
5
5
  import { IRenderer } from '@yumerijs/types';
6
+ import { SessionStorageProcessor, Storage, SessionStorageSnapshot } from './storage.js';
6
7
  export interface Components {
7
8
  [key: string]: any;
8
9
  }
@@ -71,6 +72,10 @@ export declare class Context {
71
72
  executeHook(name: string, ...args: any[]): Promise<any[]>;
72
73
  /** 获取 Core 实例 */
73
74
  getCore(): Core;
75
+ /**
76
+ * 替换 core 的 session 存储处理器或底层存储。
77
+ */
78
+ setStorage(storage: SessionStorageProcessor | Storage<SessionStorageSnapshot>): void;
74
79
  /**
75
80
  * 触发事件
76
81
  * @param event 事件名称
@@ -105,7 +110,7 @@ export declare class Context {
105
110
  * @param module 插件模块
106
111
  * @param config 插件配置
107
112
  */
108
- plugin(module: Plugin, config?: any): Promise<Context>;
113
+ plugin(module: Plugin, config?: any): Promise<Context | undefined>;
109
114
  /**
110
115
  * 注册 i18n
111
116
  * @param content 内容(可以是嵌套对象或单个key)
package/dist/context.js CHANGED
@@ -102,6 +102,12 @@ export class Context {
102
102
  getCore() {
103
103
  return this.core;
104
104
  }
105
+ /**
106
+ * 替换 core 的 session 存储处理器或底层存储。
107
+ */
108
+ setStorage(storage) {
109
+ this.core.setStorage(storage);
110
+ }
105
111
  /**
106
112
  * 触发事件
107
113
  * @param event 事件名称
@@ -139,7 +145,7 @@ export class Context {
139
145
  */
140
146
  fork(name = this.pluginname, path) {
141
147
  const ctx = new Context(this.core, name);
142
- ctx.childpath = path;
148
+ ctx.childpath = path ?? '/';
143
149
  this.childContexts.push(ctx);
144
150
  return ctx;
145
151
  }
package/dist/core.d.ts CHANGED
@@ -9,6 +9,7 @@ import { HookHandler, Hook } from './hook.js';
9
9
  import { Server as CoreServer } from './server.js';
10
10
  import { I18n } from './i18n.js';
11
11
  import { IRenderer } from '@yumerijs/types';
12
+ import { SessionStorageProcessor, Storage, SessionStorageSnapshot } from './storage.js';
12
13
  export interface Plugin {
13
14
  apply?: (ctx: Context, config: Config) => Promise<void> | void;
14
15
  disable?: (ctx: Context) => Promise<void> | void;
@@ -55,11 +56,14 @@ export declare class Core {
55
56
  server: CoreServer;
56
57
  i18n: I18n;
57
58
  loader: any;
59
+ storage: SessionStorageProcessor;
58
60
  renderers: Map<string, IRenderer>;
59
61
  pluginRenderers: Map<string, string>;
60
62
  constructor(loader?: any, coreConfig?: CoreOptions, loggersetCore?: boolean, splash?: boolean);
61
- checkUpdate(): Promise<void>;
63
+ private checkUpdate;
62
64
  addRenderer(renderer: IRenderer): void;
65
+ setStorage(storage: SessionStorageProcessor | Storage<SessionStorageSnapshot>): void;
66
+ getStorage(): SessionStorageProcessor;
63
67
  getRendererForPlugin(pluginName: string): string | undefined;
64
68
  runCore(): Promise<void>;
65
69
  getShortPluginName(pluginName: string): string;
package/dist/core.js CHANGED
@@ -4,7 +4,9 @@ import { Logger } from './logger.js';
4
4
  import { Route } from './route.js';
5
5
  import { Hook } from './hook.js';
6
6
  import { Server as CoreServer } from './server.js';
7
+ import { SessionStorageProcessor } from './storage.js';
7
8
  import * as fs from 'fs';
9
+ import semver from 'semver';
8
10
  const version = JSON.parse(await fs.promises.readFile(new URL('../package.json', import.meta.url), 'utf-8')).version;
9
11
  function isClassPlugin(value) {
10
12
  if (typeof value !== 'function')
@@ -28,14 +30,7 @@ function mergePluginMeta(target, source) {
28
30
  return target;
29
31
  }
30
32
  export function resolvePluginModule(module, context, config) {
31
- let candidate;
32
- // 只有对象模块才取 default/apply
33
- if (typeof module === 'object' && module !== null) {
34
- candidate = module.default ?? module.apply ?? module;
35
- }
36
- else {
37
- candidate = module;
38
- }
33
+ const candidate = module?.default ?? module?.apply ?? module;
39
34
  let plugin;
40
35
  if (isClassPlugin(candidate)) {
41
36
  plugin = new candidate(context, config);
@@ -74,6 +69,7 @@ export class Core {
74
69
  server;
75
70
  i18n;
76
71
  loader;
72
+ storage = new SessionStorageProcessor();
77
73
  renderers = new Map();
78
74
  pluginRenderers = new Map(); // Stores which plugin uses which renderer
79
75
  constructor(loader, coreConfig = {}, loggersetCore = true, splash = true) {
@@ -88,15 +84,17 @@ export class Core {
88
84
  }
89
85
  async checkUpdate() {
90
86
  try {
91
- const response = await fetch('https://registry.npmjs.org/yumeri/latest');
87
+ const response = await fetch('https://registry.npmjs.org/yumeri');
92
88
  if (!response.ok)
93
89
  return;
94
- const { version: latest } = await response.json();
95
- if (latest !== version) {
90
+ const pkg = await response.json();
91
+ const currentMajor = semver.major(version);
92
+ const latest = Object.keys(pkg.versions)
93
+ .filter(v => semver.valid(v) && semver.major(v) === currentMajor)
94
+ .sort(semver.rcompare)[0];
95
+ if (latest && semver.gt(latest, version)) {
96
96
  this.logger.info(`There is new version for Yumeri: ${version} -> ${latest}`);
97
97
  }
98
- else {
99
- }
100
98
  }
101
99
  catch (error) {
102
100
  this.logger.error('Error while checking updates: ', error.message);
@@ -108,6 +106,17 @@ export class Core {
108
106
  }
109
107
  this.renderers.set(renderer.name, renderer);
110
108
  }
109
+ setStorage(storage) {
110
+ if (storage instanceof SessionStorageProcessor) {
111
+ this.storage = storage;
112
+ }
113
+ else {
114
+ this.storage.setStorage(storage);
115
+ }
116
+ }
117
+ getStorage() {
118
+ return this.storage;
119
+ }
111
120
  getRendererForPlugin(pluginName) {
112
121
  return this.pluginRenderers.get(pluginName);
113
122
  }
package/dist/index.d.ts CHANGED
@@ -12,3 +12,4 @@ export * from './context.js';
12
12
  export * from './hook.js';
13
13
  export * from './middleware.js';
14
14
  export * from './i18n.js';
15
+ export * from './storage.js';
package/dist/index.js CHANGED
@@ -12,3 +12,4 @@ export * from './context.js';
12
12
  export * from './hook.js';
13
13
  export * from './middleware.js';
14
14
  export * from './i18n.js';
15
+ export * from './storage.js';
package/dist/route.d.ts CHANGED
@@ -23,7 +23,7 @@ export declare class Route {
23
23
  private handler;
24
24
  middlewares: Middleware[];
25
25
  allowedMethods: string[];
26
- ws: WebSocketServer;
26
+ ws: WebSocketServer | null;
27
27
  context: Context;
28
28
  private routehost;
29
29
  /**
package/dist/route.js CHANGED
@@ -436,11 +436,19 @@ export class Route {
436
436
  // after finishing pattern, path must be fully consumed (no extra segments)
437
437
  if (j !== parts.length)
438
438
  return null;
439
- const result = { params, pathParams, hostParams };
439
+ const normalizedHostParams = {};
440
+ for (const [key, value] of Object.entries(hostParams)) {
441
+ normalizedHostParams[key] = value ?? '';
442
+ }
443
+ const result = { params, pathParams, hostParams: normalizedHostParams };
440
444
  return result;
441
445
  }
442
446
  else if (pathname.startsWith('root') && this.path == pathname) {
443
- const result = { params: { pathname }, pathParams: [pathname], hostParams };
447
+ const normalizedHostParams = {};
448
+ for (const [key, value] of Object.entries(hostParams)) {
449
+ normalizedHostParams[key] = value ?? '';
450
+ }
451
+ const result = { params: { pathname }, pathParams: [pathname], hostParams: normalizedHostParams };
444
452
  return result;
445
453
  }
446
454
  return null;
package/dist/server.js CHANGED
@@ -28,7 +28,7 @@ export class Server {
28
28
  * 创建一个新的会话对象
29
29
  */
30
30
  createSession(ip, cookies, res, req, pathname, pluginContext, extra = {}) {
31
- const session = new Session(ip, cookies, this, req, res, pathname, undefined, pluginContext);
31
+ const session = new Session(ip, cookies, this, req, res ?? undefined, pathname, undefined, pluginContext);
32
32
  Object.assign(session.properties, extra);
33
33
  session.protocol = extra.protocol ?? 'http';
34
34
  return session;
@@ -90,9 +90,18 @@ export class Server {
90
90
  const pluginContext = route ? route.context : (rootroute ? rootroute.context : undefined);
91
91
  const session = this.createSession(ip, cookies, res, req, pathname, pluginContext, { protocol: 'http', header: req.headers });
92
92
  session._startAt = Date.now();
93
+ await session.loadData();
93
94
  /** 路由处理逻辑 */
94
95
  const handleRoute = async (routePath) => {
95
- const matched = await this.core.executeRoute(routePath, session, queryParams);
96
+ let matched = false;
97
+ try {
98
+ matched = await this.core.executeRoute(routePath, session, queryParams);
99
+ }
100
+ finally {
101
+ if (matched) {
102
+ await session.saveData(true);
103
+ }
104
+ }
96
105
  if (!matched) {
97
106
  // 核心层不再提供静态文件服务,直接返回 404
98
107
  res.writeHead(404, { 'Content-Type': 'text/plain' });
@@ -166,15 +175,18 @@ export class Server {
166
175
  const route = this.core.getRoute(pathname);
167
176
  const pluginContext = route ? route.context : undefined;
168
177
  const session = this.createSession(ip, cookies, null, req, pathname, pluginContext, { protocol: 'http', header: req.headers });
178
+ await session.loadData();
169
179
  if (route && route.ws != null) {
180
+ const wsServer = route.ws;
170
181
  const matched = await this.core.executeRoute(pathname, session, queryParams);
171
182
  if (!matched) {
172
183
  socket.write('HTTP/1.1 400 Bad Request\r\n\r\n');
173
184
  socket.destroy();
174
185
  }
175
186
  else {
176
- route.ws.handleUpgrade(req, socket, head, (ws) => {
177
- route.ws.emit('connection', ws, req, session);
187
+ await session.saveData(true);
188
+ wsServer.handleUpgrade(req, socket, head, (ws) => {
189
+ wsServer.emit('connection', ws, req, session);
178
190
  });
179
191
  }
180
192
  }
package/dist/session.d.ts CHANGED
@@ -12,9 +12,9 @@ type ParsedParams = Record<string, string | string[] | undefined>;
12
12
  /** 客户端对象,包含原始的 HTTP 请求和响应对象 */
13
13
  export interface Client {
14
14
  /** 原始的 Node.js HTTP 请求对象 */
15
- req: IncomingMessage;
15
+ req?: IncomingMessage;
16
16
  /** 原始的 Node.js HTTP 响应对象 */
17
- res: ServerResponse;
17
+ res?: ServerResponse;
18
18
  /** 经过处理后的规范化请求头 */
19
19
  headers?: Record<string, string>;
20
20
  }
@@ -90,14 +90,14 @@ declare class SessionRequest {
90
90
  /** 请求使用的协议 */
91
91
  protocol: string;
92
92
  /** 原始的 IncomingMessage 对象 */
93
- raw: IncomingMessage;
93
+ raw?: IncomingMessage;
94
94
  constructor(data: {
95
95
  ip: string;
96
96
  cookies: Record<string, string>;
97
97
  query?: Record<string, string>;
98
98
  pathname?: string;
99
99
  headers: Record<string, string>;
100
- raw: IncomingMessage;
100
+ raw?: IncomingMessage;
101
101
  });
102
102
  }
103
103
  /**
@@ -121,8 +121,8 @@ declare class SessionResponse {
121
121
  /** 标识该响应是否已经处理完毕 */
122
122
  handled: boolean;
123
123
  /** 原始的 ServerResponse 对象 */
124
- raw: ServerResponse;
125
- constructor(res: ServerResponse);
124
+ raw?: ServerResponse;
125
+ constructor(res?: ServerResponse);
126
126
  }
127
127
  /**
128
128
  * 会话对象 (Session)
@@ -137,6 +137,8 @@ export declare class Session {
137
137
  sessionid: string;
138
138
  /** 持久化的会话数据存储 */
139
139
  data: Record<string, any>;
140
+ private dataDirty;
141
+ private dataDestroyed;
140
142
  /** 供插件或中间件挂载的临时属性 */
141
143
  properties: Record<string, any>;
142
144
  /** 对核心服务器实例的引用 */
@@ -160,7 +162,7 @@ export declare class Session {
160
162
  /** 获取请求中的 Cookie 集合 */
161
163
  get cookie(): Record<string, string>;
162
164
  /** 获取 URL 查询参数 */
163
- get query(): Record<string, string>;
165
+ get query(): Record<string, string> | undefined;
164
166
  /** 获取请求路径 */
165
167
  get pathname(): string;
166
168
  /** 获取语言列表 */
@@ -227,6 +229,10 @@ export declare class Session {
227
229
  * MD5 加密
228
230
  */
229
231
  private md5;
232
+ /** 从 core 存储处理器加载会话数据 */
233
+ loadData(): Promise<void>;
234
+ /** 将当前会话数据保存到 core 存储处理器 */
235
+ saveData(force?: boolean): Promise<void>;
230
236
  /** 设置会话数据 */
231
237
  setData(key: string, value: any): void;
232
238
  /** 删除会话数据 */
package/dist/session.js CHANGED
@@ -72,6 +72,8 @@ export class Session {
72
72
  sessionid;
73
73
  /** 持久化的会话数据存储 */
74
74
  data = {};
75
+ dataDirty = false;
76
+ dataDestroyed = false;
75
77
  /** 供插件或中间件挂载的临时属性 */
76
78
  properties = {};
77
79
  /** 对核心服务器实例的引用 */
@@ -238,6 +240,8 @@ export class Session {
238
240
  */
239
241
  async parseRequestBody(client = this.client) {
240
242
  const req = client.req;
243
+ if (!req)
244
+ return {};
241
245
  return new Promise((resolve, reject) => {
242
246
  const contentType = (req.headers['content-type'] || '').toLowerCase();
243
247
  if (contentType.includes('application/json') || contentType.includes('application/x-www-form-urlencoded')) {
@@ -295,14 +299,46 @@ export class Session {
295
299
  hash.update(str);
296
300
  return hash.digest('hex');
297
301
  }
302
+ /** 从 core 存储处理器加载会话数据 */
303
+ async loadData() {
304
+ this.data = await this.server.core.storage.load(this.sessionid);
305
+ this.dataDirty = false;
306
+ this.dataDestroyed = false;
307
+ }
308
+ /** 将当前会话数据保存到 core 存储处理器 */
309
+ async saveData(force = false) {
310
+ if (this.dataDestroyed) {
311
+ await this.server.core.storage.delete(this.sessionid);
312
+ this.dataDirty = false;
313
+ return;
314
+ }
315
+ if (force || this.dataDirty) {
316
+ await this.server.core.storage.save(this.sessionid, this.data);
317
+ this.dataDirty = false;
318
+ }
319
+ }
298
320
  /** 设置会话数据 */
299
- setData(key, value) { this.data[key] = value; }
321
+ setData(key, value) {
322
+ this.data[key] = value;
323
+ this.dataDirty = true;
324
+ this.dataDestroyed = false;
325
+ }
300
326
  /** 删除会话数据 */
301
- deleteData(key) { delete this.data[key]; }
327
+ deleteData(key) {
328
+ delete this.data[key];
329
+ this.dataDirty = true;
330
+ }
302
331
  /** 清空会话数据 */
303
- clearData() { this.data = {}; }
332
+ clearData() {
333
+ this.data = {};
334
+ this.dataDirty = true;
335
+ }
304
336
  /** 销毁会话 */
305
- destroy() { this.clearData(); }
337
+ destroy() {
338
+ this.data = {};
339
+ this.dataDirty = true;
340
+ this.dataDestroyed = true;
341
+ }
306
342
  /** 设置 MIME 类型 */
307
343
  setMime(mimeType) {
308
344
  const map = {
@@ -313,10 +349,16 @@ export class Session {
313
349
  this.response.headers['Content-Type'] = map[mimeType] || mimeType;
314
350
  }
315
351
  /** 向响应流写入数据 */
316
- send(data) { return this.response.raw.write(data); }
352
+ send(data) {
353
+ if (!this.response.raw)
354
+ throw new Error('Cannot send data without a response object.');
355
+ return this.response.raw.write(data);
356
+ }
317
357
  /** 结束响应 */
318
358
  endsession(message) {
319
359
  this.response.handled = true;
360
+ if (!this.response.raw)
361
+ throw new Error('Cannot end session without a response object.');
320
362
  return this.response.raw.end(message);
321
363
  }
322
364
  /** 获取国际化文本 */
@@ -0,0 +1,39 @@
1
+ export type MaybePromise<T> = T | Promise<T>;
2
+ export interface Storage<T = any> {
3
+ get(key: string): MaybePromise<T | undefined | null>;
4
+ set(key: string, value: T): MaybePromise<void>;
5
+ delete(key: string): MaybePromise<void>;
6
+ clear?(): MaybePromise<void>;
7
+ }
8
+ export declare class MemoryStorage<T = any> implements Storage<T> {
9
+ private data;
10
+ get(key: string): T | undefined;
11
+ set(key: string, value: T): void;
12
+ delete(key: string): void;
13
+ clear(): void;
14
+ }
15
+ export interface SessionStorageSnapshot {
16
+ sessionid: string;
17
+ data: Record<string, any>;
18
+ createdAt: number;
19
+ updatedAt: number;
20
+ expiresAt?: number | null;
21
+ }
22
+ export interface SessionStorageOptions {
23
+ keyPrefix?: string;
24
+ ttl?: number;
25
+ }
26
+ export declare class SessionStorageProcessor {
27
+ private storage;
28
+ private keyPrefix;
29
+ private ttl?;
30
+ constructor(storage?: Storage<SessionStorageSnapshot>, options?: SessionStorageOptions);
31
+ setStorage(storage: Storage<SessionStorageSnapshot>): void;
32
+ getStorage(): Storage<SessionStorageSnapshot>;
33
+ load(sessionid: string): Promise<Record<string, any>>;
34
+ save(sessionid: string, data: Record<string, any>): Promise<void>;
35
+ delete(sessionid: string): Promise<void>;
36
+ clear(): Promise<void>;
37
+ private getKey;
38
+ private isExpired;
39
+ }
@@ -0,0 +1,69 @@
1
+ export class MemoryStorage {
2
+ data = new Map();
3
+ get(key) {
4
+ return this.data.get(key);
5
+ }
6
+ set(key, value) {
7
+ this.data.set(key, value);
8
+ }
9
+ delete(key) {
10
+ this.data.delete(key);
11
+ }
12
+ clear() {
13
+ this.data.clear();
14
+ }
15
+ }
16
+ export class SessionStorageProcessor {
17
+ storage;
18
+ keyPrefix;
19
+ ttl;
20
+ constructor(storage = new MemoryStorage(), options = {}) {
21
+ this.storage = storage;
22
+ this.keyPrefix = options.keyPrefix ?? 'session:';
23
+ this.ttl = options.ttl;
24
+ }
25
+ setStorage(storage) {
26
+ this.storage = storage;
27
+ }
28
+ getStorage() {
29
+ return this.storage;
30
+ }
31
+ async load(sessionid) {
32
+ const snapshot = await this.storage.get(this.getKey(sessionid));
33
+ if (!snapshot)
34
+ return {};
35
+ if (this.isExpired(snapshot)) {
36
+ await this.delete(sessionid);
37
+ return {};
38
+ }
39
+ return { ...(snapshot.data || {}) };
40
+ }
41
+ async save(sessionid, data) {
42
+ const key = this.getKey(sessionid);
43
+ const now = Date.now();
44
+ const current = await this.storage.get(key);
45
+ const createdAt = current && !this.isExpired(current) ? current.createdAt : now;
46
+ const snapshot = {
47
+ sessionid,
48
+ data: { ...(data || {}) },
49
+ createdAt,
50
+ updatedAt: now,
51
+ expiresAt: this.ttl ? now + this.ttl : null,
52
+ };
53
+ await this.storage.set(key, snapshot);
54
+ }
55
+ async delete(sessionid) {
56
+ await this.storage.delete(this.getKey(sessionid));
57
+ }
58
+ async clear() {
59
+ if (this.storage.clear) {
60
+ await this.storage.clear();
61
+ }
62
+ }
63
+ getKey(sessionid) {
64
+ return `${this.keyPrefix}${sessionid}`;
65
+ }
66
+ isExpired(snapshot) {
67
+ return typeof snapshot.expiresAt === 'number' && snapshot.expiresAt > 0 && snapshot.expiresAt <= Date.now();
68
+ }
69
+ }
package/package.json CHANGED
@@ -1,46 +1,48 @@
1
- {
2
- "name": "@yumerijs/core",
3
- "version": "3.0.0-alpha.3",
4
- "description": "Core module for yumeri",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "type": "module",
8
- "files": [
9
- "dist"
10
- ],
11
- "scripts": {
12
- "build": "tsc",
13
- "prepublishOnly": "yarn build"
14
- },
15
- "repository": {
16
- "type": "git",
17
- "url": "git+https://github.com/yumerijs/yumeri.git"
18
- },
19
- "keywords": [
20
- "yumeri",
21
- "API"
22
- ],
23
- "author": "WindyPear-Team,FireGuo",
24
- "license": "MIT",
25
- "bugs": {
26
- "url": "https://github.com/yumerijs/yumeri/issues"
27
- },
28
- "homepage": "https://github.com/yumerijs/yumeri#readme",
29
- "devDependencies": {
30
- "@types/formidable": "^3",
31
- "@types/js-yaml": "^4.0.9",
32
- "@types/mime-types": "^3",
33
- "@types/node": "^22.13.10",
34
- "@types/ws": "^8",
35
- "typescript": "^5.8.2"
36
- },
37
- "dependencies": {
38
- "chokidar": "^4.0.3",
39
- "formidable": "^3.5.4",
40
- "js-yaml": "^4.1.0",
41
- "mime-types": "^3.0.1",
42
- "picocolors": "^1.1.1",
43
- "ws": "^8.18.3"
44
- },
45
- "packageManager": "yarn@4.9.1"
46
- }
1
+ {
2
+ "name": "@yumerijs/core",
3
+ "version": "3.0.0-alpha.6",
4
+ "description": "Core module for yumeri",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "type": "module",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "prepublishOnly": "yarn build"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/yumerijs/yumeri.git"
18
+ },
19
+ "keywords": [
20
+ "yumeri",
21
+ "API"
22
+ ],
23
+ "author": "WindyPear-Team,FireGuo",
24
+ "license": "MIT",
25
+ "bugs": {
26
+ "url": "https://github.com/yumerijs/yumeri/issues"
27
+ },
28
+ "homepage": "https://github.com/yumerijs/yumeri#readme",
29
+ "devDependencies": {
30
+ "@types/formidable": "^3",
31
+ "@types/js-yaml": "^4.0.9",
32
+ "@types/mime-types": "^3",
33
+ "@types/node": "^22.13.10",
34
+ "@types/semver": "^7",
35
+ "@types/ws": "^8",
36
+ "typescript": "^6.0.3"
37
+ },
38
+ "dependencies": {
39
+ "chokidar": "^4.0.3",
40
+ "formidable": "^3.5.4",
41
+ "js-yaml": "^4.1.0",
42
+ "mime-types": "^3.0.1",
43
+ "picocolors": "^1.1.1",
44
+ "semver": "^7.8.4",
45
+ "ws": "^8.18.3"
46
+ },
47
+ "packageManager": "yarn@4.9.1"
48
+ }
package/dist/command.d.ts DELETED
@@ -1,144 +0,0 @@
1
- /**
2
- * @time: 2025/08/14 09:48
3
- * @author: FireGuo
4
- * WindyPear-Team All right reserved
5
- **/
6
- import { Core } from './core';
7
- import { Session } from './session';
8
- import { Middleware } from './middleware';
9
- /**
10
- * 命令处理函数接口
11
- * @param session 会话对象
12
- * @param args 其他参数
13
- * @returns Promise<any>
14
- */
15
- interface ActionFn {
16
- (session: any, ...args: any[]): Promise<any>;
17
- }
18
- /**
19
- * 支持的协议类型
20
- * @enum {string}
21
- */
22
- export declare enum ProtocolType {
23
- /** HTTP 协议 */
24
- HTTP = "http",
25
- /** WebSocket 协议 */
26
- WS = "ws",
27
- /** 所有协议 */
28
- ALL = "all"
29
- }
30
- /**
31
- * 支持的 HTTP 方法
32
- * @enum {string}
33
- */
34
- export declare enum HttpMethod {
35
- /** GET 请求方法 */
36
- GET = "get",
37
- /** POST 请求方法 */
38
- POST = "post",
39
- /** PUT 请求方法 */
40
- PUT = "put",
41
- /** DELETE 请求方法 */
42
- DELETE = "delete",
43
- /** PATCH 请求方法 */
44
- PATCH = "patch",
45
- /** HEAD 请求方法 */
46
- HEAD = "head",
47
- /** OPTIONS 请求方法 */
48
- OPTIONS = "options",
49
- /** 所有 HTTP 方法 */
50
- ALL = "all"
51
- }
52
- /**
53
- * 命令类,用于注册和执行命令
54
- */
55
- /**
56
- * @deprecated Use Route instead.
57
- */
58
- export declare class Command {
59
- /** 命令名称 */
60
- name: string;
61
- /** 命令处理函数 */
62
- actionFn: ActionFn | null;
63
- /** WebSocket 连接处理函数 */
64
- connectFn: ActionFn | null;
65
- /** WebSocket 关闭处理函数 */
66
- closeFn: ActionFn | null;
67
- /** 核心实例 */
68
- core: Core;
69
- /** 命令特定的中间件数组 */
70
- middlewares: Middleware[];
71
- /** 支持的协议类型,默认为所有协议 */
72
- protocol: ProtocolType;
73
- /** 支持的 HTTP 方法,默认为所有方法 */
74
- httpMethods: HttpMethod[];
75
- /**
76
- * 创建命令实例
77
- * @param core 核心实例
78
- * @param name 命令名称
79
- */
80
- constructor(core: Core, name: string);
81
- /**
82
- * 注册命令处理函数
83
- * @param fn 处理函数
84
- * @returns this 支持链式调用
85
- */
86
- action(fn: ActionFn): this;
87
- /**
88
- * 注册 WebSocket 关闭处理函数
89
- * @param fn 处理函数
90
- * @returns this 支持链式调用
91
- */
92
- close(fn: ActionFn): this;
93
- /**
94
- * 注册 WebSocket 连接处理函数
95
- * @param fn 处理函数
96
- * @returns this 支持链式调用
97
- */
98
- connect(fn: ActionFn): this;
99
- /**
100
- * 设置命令支持的协议类型
101
- * @param protocol 协议类型
102
- * @returns this 支持链式调用
103
- */
104
- setProtocol(protocol: ProtocolType): this;
105
- /**
106
- * 设置命令支持的 HTTP 方法
107
- * @param methods 单个 HTTP 方法或 HTTP 方法数组
108
- * @returns this 支持链式调用
109
- */
110
- setHttpMethods(methods: HttpMethod | HttpMethod[]): this;
111
- /**
112
- * 检查命令是否支持指定的协议类型
113
- * @param protocol 协议类型
114
- * @returns 是否支持
115
- */
116
- supportsProtocol(protocol: ProtocolType): boolean;
117
- /**
118
- * 检查命令是否支持指定的 HTTP 方法
119
- * @param method HTTP 方法
120
- * @returns 是否支持
121
- */
122
- supportsHttpMethod(method: string): boolean;
123
- /**
124
- * 注册命令特定的中间件
125
- * @param middleware 中间件函数
126
- * @returns this 支持链式调用
127
- */
128
- use(middleware: Middleware): this;
129
- /**
130
- * 执行命令,包括中间件链和处理函数
131
- * @param session 会话对象
132
- * @param args 其他参数
133
- * @returns 处理后的会话对象
134
- */
135
- execute(session: any, ...args: any[]): Promise<Session | null>;
136
- /**
137
- * 执行命令处理函数(不包含中间件)
138
- * @param session 会话对象
139
- * @param args 其他参数
140
- * @returns 处理后的会话对象
141
- */
142
- executeHandler(session: any, ...args: any[]): Promise<Session | null>;
143
- }
144
- export {};
package/dist/command.js DELETED
@@ -1,181 +0,0 @@
1
- "use strict";
2
- /**
3
- * @time: 2025/08/14 09:48
4
- * @author: FireGuo
5
- * WindyPear-Team All right reserved
6
- **/
7
- Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.Command = exports.HttpMethod = exports.ProtocolType = void 0;
9
- /**
10
- * 支持的协议类型
11
- * @enum {string}
12
- */
13
- var ProtocolType;
14
- (function (ProtocolType) {
15
- /** HTTP 协议 */
16
- ProtocolType["HTTP"] = "http";
17
- /** WebSocket 协议 */
18
- ProtocolType["WS"] = "ws";
19
- /** 所有协议 */
20
- ProtocolType["ALL"] = "all";
21
- })(ProtocolType || (exports.ProtocolType = ProtocolType = {}));
22
- /**
23
- * 支持的 HTTP 方法
24
- * @enum {string}
25
- */
26
- var HttpMethod;
27
- (function (HttpMethod) {
28
- /** GET 请求方法 */
29
- HttpMethod["GET"] = "get";
30
- /** POST 请求方法 */
31
- HttpMethod["POST"] = "post";
32
- /** PUT 请求方法 */
33
- HttpMethod["PUT"] = "put";
34
- /** DELETE 请求方法 */
35
- HttpMethod["DELETE"] = "delete";
36
- /** PATCH 请求方法 */
37
- HttpMethod["PATCH"] = "patch";
38
- /** HEAD 请求方法 */
39
- HttpMethod["HEAD"] = "head";
40
- /** OPTIONS 请求方法 */
41
- HttpMethod["OPTIONS"] = "options";
42
- /** 所有 HTTP 方法 */
43
- HttpMethod["ALL"] = "all";
44
- })(HttpMethod || (exports.HttpMethod = HttpMethod = {}));
45
- /**
46
- * 命令类,用于注册和执行命令
47
- */
48
- /**
49
- * @deprecated Use Route instead.
50
- */
51
- class Command {
52
- /** 命令名称 */
53
- name;
54
- /** 命令处理函数 */
55
- actionFn = null;
56
- /** WebSocket 连接处理函数 */
57
- connectFn = null;
58
- /** WebSocket 关闭处理函数 */
59
- closeFn = null;
60
- /** 核心实例 */
61
- core;
62
- /** 命令特定的中间件数组 */
63
- middlewares = [];
64
- /** 支持的协议类型,默认为所有协议 */
65
- protocol = ProtocolType.ALL;
66
- /** 支持的 HTTP 方法,默认为所有方法 */
67
- httpMethods = [HttpMethod.ALL];
68
- /**
69
- * 创建命令实例
70
- * @param core 核心实例
71
- * @param name 命令名称
72
- */
73
- constructor(core, name) {
74
- this.core = core;
75
- this.name = name;
76
- }
77
- /**
78
- * 注册命令处理函数
79
- * @param fn 处理函数
80
- * @returns this 支持链式调用
81
- */
82
- action(fn) {
83
- this.actionFn = fn;
84
- return this;
85
- }
86
- /**
87
- * 注册 WebSocket 关闭处理函数
88
- * @param fn 处理函数
89
- * @returns this 支持链式调用
90
- */
91
- close(fn) {
92
- this.closeFn = fn;
93
- return this;
94
- }
95
- /**
96
- * 注册 WebSocket 连接处理函数
97
- * @param fn 处理函数
98
- * @returns this 支持链式调用
99
- */
100
- connect(fn) {
101
- this.connectFn = fn;
102
- return this;
103
- }
104
- /**
105
- * 设置命令支持的协议类型
106
- * @param protocol 协议类型
107
- * @returns this 支持链式调用
108
- */
109
- setProtocol(protocol) {
110
- this.protocol = protocol;
111
- return this;
112
- }
113
- /**
114
- * 设置命令支持的 HTTP 方法
115
- * @param methods 单个 HTTP 方法或 HTTP 方法数组
116
- * @returns this 支持链式调用
117
- */
118
- setHttpMethods(methods) {
119
- if (Array.isArray(methods)) {
120
- this.httpMethods = methods;
121
- }
122
- else {
123
- this.httpMethods = [methods];
124
- }
125
- return this;
126
- }
127
- /**
128
- * 检查命令是否支持指定的协议类型
129
- * @param protocol 协议类型
130
- * @returns 是否支持
131
- */
132
- supportsProtocol(protocol) {
133
- return this.protocol === ProtocolType.ALL || this.protocol === protocol;
134
- }
135
- /**
136
- * 检查命令是否支持指定的 HTTP 方法
137
- * @param method HTTP 方法
138
- * @returns 是否支持
139
- */
140
- supportsHttpMethod(method) {
141
- const lowerMethod = method.toLowerCase();
142
- return this.httpMethods.includes(HttpMethod.ALL) ||
143
- this.httpMethods.some(m => m.toLowerCase() === lowerMethod);
144
- }
145
- /**
146
- * 注册命令特定的中间件
147
- * @param middleware 中间件函数
148
- * @returns this 支持链式调用
149
- */
150
- use(middleware) {
151
- this.middlewares.push(middleware);
152
- return this;
153
- }
154
- /**
155
- * 执行命令,包括中间件链和处理函数
156
- * @param session 会话对象
157
- * @param args 其他参数
158
- * @returns 处理后的会话对象
159
- */
160
- async execute(session, ...args) {
161
- if (this.actionFn) {
162
- await this.actionFn(session, ...args);
163
- return session;
164
- }
165
- return null;
166
- }
167
- /**
168
- * 执行命令处理函数(不包含中间件)
169
- * @param session 会话对象
170
- * @param args 其他参数
171
- * @returns 处理后的会话对象
172
- */
173
- async executeHandler(session, ...args) {
174
- if (this.actionFn) {
175
- await this.actionFn(session, ...args);
176
- return session;
177
- }
178
- return null;
179
- }
180
- }
181
- exports.Command = Command;
@@ -1,164 +0,0 @@
1
- /**
2
- * @time: 2025/08/14 09:48
3
- * @author: FireGuo
4
- * WindyPear-Team All right reserved
5
- **/
6
- import { Session } from './session';
7
- import { Core } from './core';
8
- import { ConfigSchema } from './config';
9
- /**
10
- * Platform 基类
11
- * 作为平台接入的基础类,提供标准化的接口和通用能力
12
- * 各平台实现类需继承此类并实现所有抽象方法
13
- */
14
- export declare abstract class Platform {
15
- protected status: 'idle' | 'starting' | 'running' | 'stopping' | 'error';
16
- protected errorMessage: string | null;
17
- protected config: Record<string, any>;
18
- protected instanceId: string;
19
- protected eventListeners: Record<string, Array<(...args: any[]) => void>>;
20
- /**
21
- * 构造函数
22
- * @param config 平台配置
23
- */
24
- constructor(config?: Record<string, any>);
25
- /**
26
- * 生成平台实例ID
27
- * @returns 实例ID字符串
28
- */
29
- protected generateInstanceId(): string;
30
- /**
31
- * 向客户端发送消息
32
- * @param session 会话对象
33
- * @param data 要发送的数据
34
- * @returns 发送结果
35
- */
36
- abstract sendMessage(session: Session, data: any): any;
37
- /**
38
- * 结束会话
39
- * @param session 会话对象
40
- * @param message 结束消息
41
- * @returns 结束结果
42
- */
43
- abstract terminationSession(session: Session, message: any): any;
44
- /**
45
- * 获取平台名称
46
- * @returns 平台名称
47
- */
48
- abstract getPlatformName(): string;
49
- /**
50
- * 获取平台版本号
51
- * @returns 平台版本号
52
- */
53
- abstract getPlatformVersionCode(): string;
54
- /**
55
- * 获取平台ID
56
- * @returns 平台ID
57
- */
58
- abstract getPlatformId(): string;
59
- /**
60
- * 获取平台状态
61
- * @returns 平台状态对象
62
- */
63
- abstract getPlatformStatus(): Record<string, any>;
64
- /**
65
- * 启动平台
66
- * @param core Core实例
67
- * @returns 启动结果
68
- */
69
- abstract startPlatform(core?: Core): Promise<any>;
70
- /**
71
- * 停止平台
72
- * @returns 停止结果
73
- */
74
- abstract stopPlatform(): Promise<void>;
75
- /**
76
- * 重启平台
77
- * @param core Core实例
78
- * @returns 重启结果
79
- */
80
- restartPlatform(core?: Core): Promise<any>;
81
- /**
82
- * 设置平台配置
83
- * @param key 配置键
84
- * @param value 配置值
85
- */
86
- setConfig(key: string, value: any): void;
87
- /**
88
- * 获取平台配置
89
- * @param key 配置键
90
- * @param defaultValue 默认值
91
- * @returns 配置值
92
- */
93
- getConfig<T>(key: string, defaultValue?: T): T;
94
- /**
95
- * 获取平台实例ID
96
- * @returns 实例ID
97
- */
98
- getInstanceId(): string;
99
- /**
100
- * 获取当前平台状态
101
- * @returns 状态字符串
102
- */
103
- getStatus(): 'idle' | 'starting' | 'running' | 'stopping' | 'error';
104
- /**
105
- * 获取错误信息
106
- * @returns 错误信息
107
- */
108
- getErrorMessage(): string | null;
109
- /**
110
- * 添加平台事件监听器
111
- * @param event 事件名称
112
- * @param listener 监听器函数
113
- */
114
- on(event: string, listener: (...args: any[]) => void): void;
115
- /**
116
- * 移除平台事件监听器
117
- * @param event 事件名称
118
- * @param listener 监听器函数
119
- */
120
- off(event: string, listener: (...args: any[]) => void): void;
121
- /**
122
- * 触发平台事件
123
- * @param event 事件名称
124
- * @param args 事件参数
125
- */
126
- protected emit(event: string, ...args: any[]): void;
127
- /**
128
- * 创建会话
129
- * @param ip 客户端IP
130
- * @param cookie Cookie对象
131
- * @param query 查询参数
132
- * @returns 会话对象
133
- */
134
- createSession(ip: string, cookie: Record<string, string>, query?: Record<string, string>): Session;
135
- /**
136
- * 处理会话数据
137
- * @param session 会话对象
138
- * @param data 会话数据
139
- * @returns 处理结果
140
- */
141
- processSessionData(session: Session, data: any): any;
142
- /**
143
- * 验证会话
144
- * @param session 会话对象
145
- * @returns 验证结果
146
- */
147
- validateSession(session: Session): boolean;
148
- /**
149
- * 获取平台支持的MIME类型
150
- * @returns MIME类型数组
151
- */
152
- getSupportedMimeTypes(): string[];
153
- /**
154
- * 获取平台元数据
155
- * @returns 平台元数据
156
- */
157
- getMetadata(): Record<string, any>;
158
- /**
159
- * 获取平台配置模式
160
- * 子类可以覆盖此方法提供自定义配置模式
161
- * @returns 配置模式对象
162
- */
163
- static getConfigSchema(): Record<string, ConfigSchema>;
164
- }
package/dist/platform.js DELETED
@@ -1,199 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Platform = void 0;
4
- /**
5
- * @time: 2025/08/14 09:48
6
- * @author: FireGuo
7
- * WindyPear-Team All right reserved
8
- **/
9
- const session_1 = require("./session");
10
- /**
11
- * Platform 基类
12
- * 作为平台接入的基础类,提供标准化的接口和通用能力
13
- * 各平台实现类需继承此类并实现所有抽象方法
14
- */
15
- class Platform {
16
- // 平台状态
17
- status = 'idle';
18
- // 平台错误信息
19
- errorMessage = null;
20
- // 平台配置
21
- config = {};
22
- // 平台实例ID
23
- instanceId = '';
24
- // 平台事件监听器
25
- eventListeners = {};
26
- /**
27
- * 构造函数
28
- * @param config 平台配置
29
- */
30
- constructor(config) {
31
- if (config) {
32
- this.config = { ...config };
33
- }
34
- this.instanceId = this.generateInstanceId();
35
- }
36
- /**
37
- * 生成平台实例ID
38
- * @returns 实例ID字符串
39
- */
40
- generateInstanceId() {
41
- return `${this.getPlatformId()}-${Date.now()}-${Math.floor(Math.random() * 1000)}`;
42
- }
43
- /**
44
- * 重启平台
45
- * @param core Core实例
46
- * @returns 重启结果
47
- */
48
- async restartPlatform(core) {
49
- await this.stopPlatform();
50
- return this.startPlatform(core);
51
- }
52
- /**
53
- * 设置平台配置
54
- * @param key 配置键
55
- * @param value 配置值
56
- */
57
- setConfig(key, value) {
58
- this.config[key] = value;
59
- }
60
- /**
61
- * 获取平台配置
62
- * @param key 配置键
63
- * @param defaultValue 默认值
64
- * @returns 配置值
65
- */
66
- getConfig(key, defaultValue) {
67
- return (this.config[key] !== undefined) ? this.config[key] : defaultValue;
68
- }
69
- /**
70
- * 获取平台实例ID
71
- * @returns 实例ID
72
- */
73
- getInstanceId() {
74
- return this.instanceId;
75
- }
76
- /**
77
- * 获取当前平台状态
78
- * @returns 状态字符串
79
- */
80
- getStatus() {
81
- return this.status;
82
- }
83
- /**
84
- * 获取错误信息
85
- * @returns 错误信息
86
- */
87
- getErrorMessage() {
88
- return this.errorMessage;
89
- }
90
- /**
91
- * 添加平台事件监听器
92
- * @param event 事件名称
93
- * @param listener 监听器函数
94
- */
95
- on(event, listener) {
96
- if (!this.eventListeners[event]) {
97
- this.eventListeners[event] = [];
98
- }
99
- this.eventListeners[event].push(listener);
100
- }
101
- /**
102
- * 移除平台事件监听器
103
- * @param event 事件名称
104
- * @param listener 监听器函数
105
- */
106
- off(event, listener) {
107
- if (!this.eventListeners[event]) {
108
- return;
109
- }
110
- this.eventListeners[event] = this.eventListeners[event].filter(l => l !== listener);
111
- }
112
- /**
113
- * 触发平台事件
114
- * @param event 事件名称
115
- * @param args 事件参数
116
- */
117
- emit(event, ...args) {
118
- if (!this.eventListeners[event]) {
119
- return;
120
- }
121
- for (const listener of this.eventListeners[event]) {
122
- try {
123
- listener(...args);
124
- }
125
- catch (error) {
126
- console.error(`Error in platform event listener for "${event}":`, error);
127
- }
128
- }
129
- }
130
- /**
131
- * 创建会话
132
- * @param ip 客户端IP
133
- * @param cookie Cookie对象
134
- * @param query 查询参数
135
- * @returns 会话对象
136
- */
137
- createSession(ip, cookie, query) {
138
- return new session_1.Session(ip, cookie, this, query);
139
- }
140
- /**
141
- * 处理会话数据
142
- * @param session 会话对象
143
- * @param data 会话数据
144
- * @returns 处理结果
145
- */
146
- processSessionData(session, data) {
147
- // 默认实现,子类可覆盖
148
- return data;
149
- }
150
- /**
151
- * 验证会话
152
- * @param session 会话对象
153
- * @returns 验证结果
154
- */
155
- validateSession(session) {
156
- // 默认实现,子类可覆盖
157
- return true;
158
- }
159
- /**
160
- * 获取平台支持的MIME类型
161
- * @returns MIME类型数组
162
- */
163
- getSupportedMimeTypes() {
164
- // 默认实现,子类可覆盖
165
- return [
166
- 'text/plain',
167
- 'text/html',
168
- 'application/json',
169
- 'application/xml',
170
- 'image/png',
171
- 'image/jpeg',
172
- 'application/pdf'
173
- ];
174
- }
175
- /**
176
- * 获取平台元数据
177
- * @returns 平台元数据
178
- */
179
- getMetadata() {
180
- return {
181
- id: this.getPlatformId(),
182
- name: this.getPlatformName(),
183
- version: this.getPlatformVersionCode(),
184
- status: this.getStatus(),
185
- instanceId: this.getInstanceId(),
186
- supportedMimeTypes: this.getSupportedMimeTypes(),
187
- ...this.getPlatformStatus()
188
- };
189
- }
190
- /**
191
- * 获取平台配置模式
192
- * 子类可以覆盖此方法提供自定义配置模式
193
- * @returns 配置模式对象
194
- */
195
- static getConfigSchema() {
196
- return {};
197
- }
198
- }
199
- exports.Platform = Platform;