@yumerijs/core 2.0.13 → 2.0.14

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
@@ -9,6 +9,8 @@ interface Plugin {
9
9
  depend: Array<string>;
10
10
  provide: Array<string>;
11
11
  }
12
+ export interface Components {
13
+ }
12
14
  /**
13
15
  * 插件上下文对象
14
16
  * 每个插件一个 Context,用于管理插件注册的命令、路由、事件、组件和中间件
@@ -23,6 +25,7 @@ export declare class Context {
23
25
  private childContexts;
24
26
  private childPlugins;
25
27
  private i18ns;
28
+ component: Components;
26
29
  /** 插件名称 */
27
30
  pluginname: string;
28
31
  /**
@@ -30,7 +33,13 @@ export declare class Context {
30
33
  * @param core Core 实例
31
34
  * @param pluginname 插件名称
32
35
  */
33
- constructor(core: Core, pluginname: string);
36
+ constructor(core: Core, pluginname: string, injections?: Record<string, any>);
37
+ /**
38
+ * 注入依赖
39
+ * @param name 依赖名称
40
+ * @param value 依赖值
41
+ */
42
+ inject(name: string, value: any): void;
34
43
  /**
35
44
  * 注册路由
36
45
  * @param path 路由路径
@@ -72,6 +81,7 @@ export declare class Context {
72
81
  emit(event: string, ...args: any[]): Promise<void>;
73
82
  /**
74
83
  * 获取组件实例
84
+ * @deprecated
75
85
  * @param name 组件名称
76
86
  */
77
87
  getComponent(name: string): any;
package/dist/context.js CHANGED
@@ -16,6 +16,7 @@ class Context {
16
16
  childContexts = [];
17
17
  childPlugins = new Map();
18
18
  i18ns = [];
19
+ component;
19
20
  /** 插件名称 */
20
21
  pluginname;
21
22
  /**
@@ -23,10 +24,19 @@ class Context {
23
24
  * @param core Core 实例
24
25
  * @param pluginname 插件名称
25
26
  */
26
- constructor(core, pluginname) {
27
+ constructor(core, pluginname, injections = {}) {
27
28
  this.core = core;
28
29
  this.pluginname = pluginname;
29
30
  this.childPlugins = new Map();
31
+ this.component = injections;
32
+ }
33
+ /**
34
+ * 注入依赖
35
+ * @param name 依赖名称
36
+ * @param value 依赖值
37
+ */
38
+ inject(name, value) {
39
+ this.component[name] = value;
30
40
  }
31
41
  /**
32
42
  * 注册路由
@@ -99,6 +109,7 @@ class Context {
99
109
  }
100
110
  /**
101
111
  * 获取组件实例
112
+ * @deprecated
102
113
  * @param name 组件名称
103
114
  */
104
115
  getComponent(name) {
package/dist/server.js CHANGED
@@ -45,6 +45,9 @@ const path = __importStar(require("path"));
45
45
  const url_1 = require("url");
46
46
  const mime = __importStar(require("mime-types"));
47
47
  const logger = new logger_1.Logger('server');
48
+ function isStream(value) {
49
+ return value && typeof value.pipe === "function";
50
+ }
48
51
  class Server {
49
52
  core;
50
53
  port;
@@ -112,81 +115,60 @@ class Server {
112
115
  const session = this.createSession(ip, cookies, res, req, pathname, { protocol: 'http', header: req.headers });
113
116
  const route = this.core.getRoute(pathname);
114
117
  const rootroute = this.core.getRoute('root');
115
- if (route && route.allowedMethods.includes(req.method ?? 'GET')) {
116
- const matched = await this.core.executeRoute(pathname, session, queryParams);
118
+ const handleRoute = async (routePath) => {
119
+ const matched = await this.core.executeRoute(routePath, session, queryParams);
117
120
  if (!matched) {
118
121
  this.serveStaticFile(pathname, res);
122
+ return;
119
123
  }
120
- else {
121
- if (!session.responseHandled) {
122
- let head = session.head;
123
- head['Set-Cookie'] = Object.entries(session.newCookie).map(([name, cookie]) => {
124
- let cookieString = `${name}=${cookie.value}`;
125
- if (cookie.options.expires) {
126
- cookieString += `; Expires=${cookie.options.expires.toUTCString()}`;
127
- }
128
- if (cookie.options.path) {
129
- cookieString += `; Path=${cookie.options.path}`;
130
- }
131
- if (cookie.options.domain) {
132
- cookieString += `; Domain=${cookie.options.domain}`;
133
- }
134
- if (cookie.options.secure) {
135
- cookieString += `; Secure`;
136
- }
137
- if (cookie.options.httpOnly) {
138
- cookieString += `; HttpOnly`;
139
- }
140
- if (cookie.options.sameSite) {
141
- cookieString += `; SameSite=${cookie.options.sameSite}`;
142
- }
143
- return cookieString;
144
- });
145
- if (this.enableCors) {
146
- head['Access-Control-Allow-Origin'] = '*';
147
- }
148
- res.writeHead(session.status ?? 200, head);
124
+ if (session.responseHandled)
125
+ return;
126
+ const head = { ...session.head };
127
+ head['Set-Cookie'] = Object.entries(session.newCookie).map(([name, cookie]) => {
128
+ let cookieString = `${name}=${cookie.value}`;
129
+ if (cookie.options.expires)
130
+ cookieString += `; Expires=${cookie.options.expires.toUTCString()}`;
131
+ if (cookie.options.path)
132
+ cookieString += `; Path=${cookie.options.path}`;
133
+ if (cookie.options.domain)
134
+ cookieString += `; Domain=${cookie.options.domain}`;
135
+ if (cookie.options.secure)
136
+ cookieString += `; Secure`;
137
+ if (cookie.options.httpOnly)
138
+ cookieString += `; HttpOnly`;
139
+ if (cookie.options.sameSite)
140
+ cookieString += `; SameSite=${cookie.options.sameSite}`;
141
+ return cookieString;
142
+ });
143
+ if (this.enableCors) {
144
+ head['Access-Control-Allow-Origin'] = '*';
145
+ }
146
+ res.writeHead(session.status ?? 200, head);
147
+ switch (session.restype) {
148
+ case 'plain':
149
149
  res.end(session.body);
150
- }
150
+ break;
151
+ case 'buffer':
152
+ res.end(session.body);
153
+ break;
154
+ case 'json':
155
+ res.end(JSON.stringify(session.body));
156
+ break;
157
+ case 'stream':
158
+ if (isStream(session.body)) {
159
+ const stream = session.body;
160
+ stream.pipe(res);
161
+ }
162
+ break;
163
+ default:
164
+ res.end(session.body); // fallback
151
165
  }
166
+ };
167
+ if (route && route.allowedMethods.includes(req.method ?? 'GET')) {
168
+ await handleRoute(pathname);
152
169
  }
153
170
  else if (rootroute && rootroute.allowedMethods.includes(req.method ?? 'GET')) {
154
- const matched = await this.core.executeRoute('root', session, queryParams);
155
- if (!matched) {
156
- this.serveStaticFile(pathname, res);
157
- }
158
- else {
159
- if (!session.responseHandled) {
160
- let head = session.head;
161
- head['Set-Cookie'] = Object.entries(session.newCookie).map(([name, cookie]) => {
162
- let cookieString = `${name}=${cookie.value}`;
163
- if (cookie.options.expires) {
164
- cookieString += `; Expires=${cookie.options.expires.toUTCString()}`;
165
- }
166
- if (cookie.options.path) {
167
- cookieString += `; Path=${cookie.options.path}`;
168
- }
169
- if (cookie.options.domain) {
170
- cookieString += `; Domain=${cookie.options.domain}`;
171
- }
172
- if (cookie.options.secure) {
173
- cookieString += `; Secure`;
174
- }
175
- if (cookie.options.httpOnly) {
176
- cookieString += `; HttpOnly`;
177
- }
178
- if (cookie.options.sameSite) {
179
- cookieString += `; SameSite=${cookie.options.sameSite}`;
180
- }
181
- return cookieString;
182
- });
183
- if (this.enableCors) {
184
- head['Access-Control-Allow-Origin'] = '*';
185
- }
186
- res.writeHead(session.status ?? 200, head);
187
- res.end(session.body);
188
- }
189
- }
171
+ await handleRoute('root');
190
172
  }
191
173
  else {
192
174
  this.serveStaticFile(pathname, res);
package/dist/session.d.ts CHANGED
@@ -5,6 +5,7 @@
5
5
  **/
6
6
  import { Server } from './server';
7
7
  import { IncomingMessage, ServerResponse } from 'http';
8
+ import { Stream } from "stream";
8
9
  type ParsedParams = Record<string, string | string[] | undefined>;
9
10
  export interface Client {
10
11
  req: IncomingMessage;
@@ -34,6 +35,13 @@ export interface StaticCacheOptions {
34
35
  smaxAge?: number;
35
36
  etagType?: 'md5' | 'sha1' | 'sha256' | 'sha512';
36
37
  }
38
+ type ResType = "plain" | "json" | "stream" | "buffer";
39
+ interface BodyMap {
40
+ plain: string;
41
+ json: Record<string, any>;
42
+ stream: Stream;
43
+ buffer: Buffer;
44
+ }
37
45
  export declare class Session {
38
46
  ip: string;
39
47
  cookie: Record<string, string>;
@@ -46,7 +54,8 @@ export declare class Session {
46
54
  }>;
47
55
  head: Record<string, any>;
48
56
  status: number;
49
- body: any;
57
+ private _restype;
58
+ private _body;
50
59
  properties?: Record<string, any>;
51
60
  client: Client;
52
61
  server: Server;
@@ -61,6 +70,10 @@ export declare class Session {
61
70
  * @param query 请求字符串
62
71
  */
63
72
  constructor(ip: string, cookie: Record<string, string>, server: Server, req?: IncomingMessage, res?: ServerResponse, pathname?: string, query?: Record<string, string>);
73
+ response<T extends ResType>(body: BodyMap[T], type?: T): void;
74
+ get restype(): ResType;
75
+ get body(): string;
76
+ set body(value: string);
64
77
  setCookie(name: string, value: string, options?: CookieOptions): void;
65
78
  /**
66
79
  * 解析 Accept-Language 字符串为排序后的语言数组
@@ -104,7 +117,24 @@ export declare class Session {
104
117
  * @param option 选项
105
118
  */
106
119
  setCache(option: CacheOptions): void;
120
+ /**
121
+ * 设置静态文件
122
+ * @param content 文件内容
123
+ * @param option 选项
124
+ */
107
125
  static(content: string, option: CacheOptions): void;
126
+ /**
127
+ * 发送静态文件
128
+ * @param path 文件路径
129
+ * @param option 缓存选项
130
+ * @returns void
131
+ */
108
132
  file(path: string, option: StaticCacheOptions): void;
133
+ /**
134
+ * 发送普通文件
135
+ * @param path 文件路径
136
+ * @param isStream 是否流式传输
137
+ */
138
+ sendFile(path: string, isStream?: boolean): void;
109
139
  }
110
140
  export {};
package/dist/session.js CHANGED
@@ -54,7 +54,8 @@ class Session {
54
54
  newCookie = {};
55
55
  head = {};
56
56
  status = 200;
57
- body;
57
+ _restype = "plain";
58
+ _body;
58
59
  properties = {};
59
60
  client = null;
60
61
  server;
@@ -108,6 +109,20 @@ class Session {
108
109
  this.setCookie('lang', this.languages.join(','));
109
110
  }
110
111
  }
112
+ response(body, type = 'text') {
113
+ this._restype = type;
114
+ this._body = body;
115
+ }
116
+ get restype() {
117
+ return this._restype;
118
+ }
119
+ get body() {
120
+ return this._body;
121
+ }
122
+ set body(value) {
123
+ this._body = value;
124
+ this._restype = "plain"; // 自动把 restype 设成 plain
125
+ }
111
126
  setCookie(name, value, options = {}) {
112
127
  if (options.path === undefined) {
113
128
  options.path = '/';
@@ -310,6 +325,11 @@ class Session {
310
325
  if (option.expires)
311
326
  this.head['Expires'] = option.expires.toUTCString();
312
327
  }
328
+ /**
329
+ * 设置静态文件
330
+ * @param content 文件内容
331
+ * @param option 选项
332
+ */
313
333
  static(content, option) {
314
334
  // 先查看用户是否在询问文件修改情况
315
335
  if (this.client.headers['If-Modified-Since']) {
@@ -326,8 +346,14 @@ class Session {
326
346
  }
327
347
  }
328
348
  this.setCache(option);
329
- this.body = content;
349
+ this.response(content);
330
350
  }
351
+ /**
352
+ * 发送静态文件
353
+ * @param path 文件路径
354
+ * @param option 缓存选项
355
+ * @returns void
356
+ */
331
357
  file(path, option) {
332
358
  if (this.client.headers['If-Modified-Since']) {
333
359
  const modified = new Date(this.client.headers['If-Modified-Since']);
@@ -353,7 +379,21 @@ class Session {
353
379
  smaxAge: option.smaxAge,
354
380
  cacheControl: 'public'
355
381
  });
356
- this.body = fs_1.default.readFileSync(path, 'utf-8');
382
+ this.response(fs_1.default.createReadStream(path), 'stream');
383
+ }
384
+ /**
385
+ * 发送普通文件
386
+ * @param path 文件路径
387
+ * @param isStream 是否流式传输
388
+ */
389
+ sendFile(path, isStream = false) {
390
+ if (isStream) {
391
+ this.setMime('application/octet-stream');
392
+ this.response(fs_1.default.createReadStream(path), 'stream');
393
+ }
394
+ else {
395
+ this.response(fs_1.default.readFileSync(path), 'buffer');
396
+ }
357
397
  }
358
398
  }
359
399
  exports.Session = Session;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yumerijs/core",
3
- "version": "2.0.13",
3
+ "version": "2.0.14",
4
4
  "description": "Core module for yumeri",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",