@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/session.js CHANGED
@@ -4,12 +4,46 @@
4
4
  * @author: FireGuo
5
5
  * WindyPear-Team All right reserved
6
6
  **/
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
7
40
  var __importDefault = (this && this.__importDefault) || function (mod) {
8
41
  return (mod && mod.__esModule) ? mod : { "default": mod };
9
42
  };
10
43
  Object.defineProperty(exports, "__esModule", { value: true });
11
44
  exports.Session = void 0;
12
45
  const crypto_1 = __importDefault(require("crypto"));
46
+ const formidable = __importStar(require("formidable"));
13
47
  class Session {
14
48
  ip;
15
49
  cookie;
@@ -21,22 +55,27 @@ class Session {
21
55
  status = 200;
22
56
  body;
23
57
  properties = {};
24
- res = null;
25
- req = null;
58
+ client = null;
26
59
  server;
27
60
  protocol = 'http';
28
- /*
29
- * @ip: string,用户IP
30
- * @cookie: string,会话cookie
31
- * @query: string,请求字符串
61
+ pathname;
62
+ languages;
63
+ /**
64
+ * @constructor
65
+ * @param ip 用户IP
66
+ * @param cookie 会话cookie
67
+ * @param query 请求字符串
32
68
  */
33
- constructor(ip, cookie, server, req, res, query) {
69
+ constructor(ip, cookie, server, req, res, pathname, query) {
34
70
  this.ip = ip;
35
71
  this.cookie = cookie;
36
72
  this.query = query;
37
73
  this.server = server;
38
- this.req = req;
39
- this.res = res;
74
+ this.pathname = pathname;
75
+ this.client = {
76
+ req: req,
77
+ res: res
78
+ };
40
79
  this.head['Content-Type'] = 'text/plain';
41
80
  if (cookie.sessionid) {
42
81
  this.sessionid = cookie.sessionid;
@@ -45,16 +84,122 @@ class Session {
45
84
  this.sessionid = this.generateId(this.ip);
46
85
  this.newCookie.sessionid = this.sessionid;
47
86
  }
87
+ if (cookie.lang) {
88
+ this.languages = cookie.lang.split(',');
89
+ }
90
+ else if (req.headers['accept-language']) {
91
+ this.languages = this.parseAcceptLanguages(req.headers['accept-language']);
92
+ this.newCookie.lang = this.languages.join(',');
93
+ }
94
+ }
95
+ /**
96
+ * 解析 Accept-Language 字符串为排序后的语言数组
97
+ * @param header Accept-Language 头,比如 "zh-CN,zh-TW;q=0.8,en-US;q=0.6"
98
+ * @returns 按优先级排序的语言数组,自动补上父语言
99
+ */
100
+ parseAcceptLanguages(header) {
101
+ if (!header)
102
+ return [];
103
+ const langs = header
104
+ .split(',')
105
+ .map(item => {
106
+ const [lang, qStr] = item.trim().split(';');
107
+ const q = qStr ? parseFloat(qStr.split('=')[1]) || 1 : 1;
108
+ return { lang: lang.toLowerCase(), q };
109
+ })
110
+ .sort((a, b) => b.q - a.q);
111
+ const result = [];
112
+ const seen = new Set();
113
+ for (const { lang } of langs) {
114
+ if (!seen.has(lang)) {
115
+ result.push(lang);
116
+ seen.add(lang);
117
+ }
118
+ const parts = lang.split('-');
119
+ if (parts.length > 1) {
120
+ const base = parts[0];
121
+ if (!seen.has(base)) {
122
+ let insertIndex = -1;
123
+ for (let i = result.length - 1; i >= 0; i--) {
124
+ if (result[i].startsWith(base + '-')) {
125
+ insertIndex = i + 1;
126
+ break;
127
+ }
128
+ }
129
+ if (insertIndex === -1)
130
+ insertIndex = result.length;
131
+ result.splice(insertIndex, 0, base);
132
+ seen.add(base);
133
+ }
134
+ }
135
+ }
136
+ return result;
48
137
  }
49
- // 生成 sessionid
50
- /*
51
- * @ip: string,用户IP
52
- * @option: string,选项
138
+ /**
139
+ * 生成 sessionid
140
+ * @param ip 用户IP
141
+ * @param option 选项
53
142
  */
54
143
  generateId(ip, option) {
55
144
  const sessionId = this.md5(ip + Date.now().toString() + Math.random().toString()); // 添加随机性
56
145
  return sessionId;
57
146
  }
147
+ /**
148
+ * 解析请求体
149
+ * @param client 客户端
150
+ * @returns Promise<ParsedParams>
151
+ */
152
+ async parseRequestBody(client = this.client) {
153
+ const req = client.req;
154
+ return new Promise((resolve, reject) => {
155
+ const contentType = (req.headers['content-type'] || '').toLowerCase();
156
+ if (contentType.includes('application/json') || contentType.includes('application/x-www-form-urlencoded')) {
157
+ let body = '';
158
+ req.on('data', chunk => body += chunk.toString());
159
+ req.on('end', () => {
160
+ try {
161
+ if (contentType.includes('application/json'))
162
+ resolve(JSON.parse(body));
163
+ else {
164
+ const params = new URLSearchParams(body);
165
+ const parsed = {};
166
+ params.forEach((v, k) => parsed[k] = v);
167
+ resolve(parsed);
168
+ }
169
+ }
170
+ catch (e) {
171
+ reject(e);
172
+ }
173
+ });
174
+ }
175
+ else if (contentType.includes('multipart/form-data')) {
176
+ const form = formidable.formidable({});
177
+ form.parse(req, (err, fields) => {
178
+ if (err)
179
+ return reject(err);
180
+ const parsed = {};
181
+ Object.keys(fields).forEach(k => {
182
+ const val = fields[k];
183
+ parsed[k] = Array.isArray(val) && val.length === 1 ? val[0] : val;
184
+ });
185
+ resolve(parsed);
186
+ });
187
+ }
188
+ else
189
+ resolve({});
190
+ req.on('error', reject);
191
+ });
192
+ }
193
+ /**
194
+ * 获取请求体
195
+ * @param req 请求对象
196
+ * @returns Promise<string>
197
+ */
198
+ async getReqBody(req) {
199
+ let body = "";
200
+ req.on('data', chunk => body += chunk.toString());
201
+ return body;
202
+ }
58
203
  // MD5 加密
59
204
  md5(str) {
60
205
  const hash = crypto_1.default.createHash('md5');
@@ -107,10 +252,17 @@ class Session {
107
252
  }
108
253
  }
109
254
  send(data) {
110
- return this.res.send(data);
255
+ return this.client.res.write(data);
111
256
  }
112
257
  endsession(message) {
113
- return this.res.end(message);
258
+ return this.client.res.end(message);
259
+ }
260
+ /**
261
+ * 获取I18n文本
262
+ * @param name 文本点名称
263
+ */
264
+ text(name) {
265
+ return this.server.core.i18n.get(name, this.languages);
114
266
  }
115
267
  }
116
268
  exports.Session = Session;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yumerijs/core",
3
- "version": "1.3.3",
3
+ "version": "2.0.0",
4
4
  "description": "Core module for yumeri",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -34,7 +34,7 @@
34
34
  "typescript": "^5.8.2"
35
35
  },
36
36
  "dependencies": {
37
- "@yumerijs/loader": "^1.2.0",
37
+ "@yumerijs/loader": "^2.0.0",
38
38
  "chokidar": "^4.0.3",
39
39
  "formidable": "^3.5.4",
40
40
  "js-yaml": "^4.1.0",