@maiyunnet/kebab 2.0.6 → 2.0.8

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.
Files changed (83) hide show
  1. package/index.d.ts +11 -1
  2. package/index.js +13 -1
  3. package/lib/buffer.d.ts +25 -0
  4. package/lib/buffer.js +30 -5
  5. package/lib/captcha.d.ts +15 -0
  6. package/lib/captcha.js +20 -0
  7. package/lib/consistent.d.ts +51 -0
  8. package/lib/consistent.js +59 -0
  9. package/lib/core.d.ts +134 -0
  10. package/lib/core.js +176 -0
  11. package/lib/crypto.d.ts +75 -6
  12. package/lib/crypto.js +206 -38
  13. package/lib/db.d.ts +104 -0
  14. package/lib/db.js +126 -0
  15. package/lib/dns.d.ts +51 -0
  16. package/lib/dns.js +54 -2
  17. package/lib/fs.d.ts +100 -0
  18. package/lib/fs.js +118 -0
  19. package/lib/jwt.d.ts +43 -0
  20. package/lib/jwt.js +45 -0
  21. package/lib/kv.d.ts +362 -0
  22. package/lib/kv.js +377 -0
  23. package/lib/lan.d.ts +6 -0
  24. package/lib/lan.js +7 -0
  25. package/lib/net/formdata.d.ts +38 -0
  26. package/lib/net/formdata.js +43 -0
  27. package/lib/net/request.d.ts +62 -0
  28. package/lib/net/request.js +57 -0
  29. package/lib/net/response.d.ts +21 -0
  30. package/lib/net/response.js +16 -0
  31. package/lib/net.d.ts +86 -0
  32. package/lib/net.js +140 -0
  33. package/lib/s3.d.ts +52 -0
  34. package/lib/s3.js +51 -0
  35. package/lib/scan.d.ts +52 -0
  36. package/lib/scan.js +84 -0
  37. package/lib/session.d.ts +31 -0
  38. package/lib/session.js +52 -1
  39. package/lib/sql.d.ts +176 -0
  40. package/lib/sql.js +287 -2
  41. package/lib/ssh/sftp.d.ts +106 -0
  42. package/lib/ssh/sftp.js +106 -0
  43. package/lib/ssh/shell.d.ts +37 -0
  44. package/lib/ssh/shell.js +31 -0
  45. package/lib/ssh.d.ts +32 -0
  46. package/lib/ssh.js +32 -0
  47. package/lib/text.d.ts +131 -0
  48. package/lib/text.js +188 -0
  49. package/lib/time.d.ts +53 -0
  50. package/lib/time.js +55 -0
  51. package/lib/ws.d.ts +68 -0
  52. package/lib/ws.js +74 -0
  53. package/lib/zip.d.ts +53 -0
  54. package/lib/zip.js +73 -0
  55. package/lib/zlib.d.ts +76 -0
  56. package/lib/zlib.js +78 -0
  57. package/main.d.ts +6 -1
  58. package/main.js +11 -1
  59. package/package.json +2 -2
  60. package/sys/child.js +104 -0
  61. package/sys/cmd.js +28 -0
  62. package/sys/ctr.d.ts +166 -0
  63. package/sys/ctr.js +177 -0
  64. package/sys/master.js +63 -0
  65. package/sys/mod.d.ts +266 -0
  66. package/sys/mod.js +335 -0
  67. package/sys/route.d.ts +34 -0
  68. package/sys/route.js +164 -0
  69. package/www/example/ctr/test.d.ts +3 -0
  70. package/www/example/ctr/test.js +63 -1
  71. package/www/example/mod/test.js +14 -0
  72. package/www/example/mod/testdata.js +9 -0
  73. package/www/example/ws/test.js +1 -0
  74. package/.VSCodeCounter/2025-02-14_14-46-44/details.md +0 -82
  75. package/.VSCodeCounter/2025-02-14_14-46-44/diff-details.md +0 -15
  76. package/.VSCodeCounter/2025-02-14_14-46-44/diff.csv +0 -2
  77. package/.VSCodeCounter/2025-02-14_14-46-44/diff.md +0 -19
  78. package/.VSCodeCounter/2025-02-14_14-46-44/diff.txt +0 -22
  79. package/.VSCodeCounter/2025-02-14_14-46-44/results.csv +0 -69
  80. package/.VSCodeCounter/2025-02-14_14-46-44/results.json +0 -1
  81. package/.VSCodeCounter/2025-02-14_14-46-44/results.md +0 -48
  82. package/.VSCodeCounter/2025-02-14_14-46-44/results.txt +0 -118
  83. package/.vscode/tasks.json +0 -15
package/lib/core.d.ts CHANGED
@@ -4,6 +4,7 @@ import * as stream from 'stream';
4
4
  import * as lResponse from '../lib/net/response';
5
5
  import * as sCtr from '../sys/ctr';
6
6
  import * as types from '../types';
7
+ /** --- 全局参数 --- */
7
8
  export declare const globalConfig: types.IConfig & {
8
9
  'httpPort': number;
9
10
  'httpsPort': number;
@@ -12,6 +13,7 @@ export declare const globalConfig: types.IConfig & {
12
13
  'debug': boolean;
13
14
  'max': number;
14
15
  };
16
+ /** --- Cookie 设置的选项 --- */
15
17
  export interface ICookieOptions {
16
18
  'ttl'?: number;
17
19
  'path'?: string;
@@ -20,7 +22,20 @@ export interface ICookieOptions {
20
22
  'httponly'?: boolean;
21
23
  'samesite'?: 'None' | 'Lax' | 'Strict';
22
24
  }
25
+ /**
26
+ * --- 设置 cookie ---
27
+ * @param ctr ctr 实例
28
+ * @param name 名
29
+ * @param value 值
30
+ * @param opt 选项,ttl, 默认和 undefined 为关闭浏览器失效
31
+ */
23
32
  export declare function setCookie(ctr: sCtr.Ctr, name: string, value: string, opt?: ICookieOptions): void;
33
+ /**
34
+ * --- 生成基础的范围随机数 ---
35
+ * @param min >= 最小值
36
+ * @param max <= 最大值
37
+ * @param prec 保留几位小数
38
+ */
24
39
  export declare function rand(min: number, max: number, prec?: number): number;
25
40
  export declare const RANDOM_N = "0123456789";
26
41
  export declare const RANDOM_U = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
@@ -31,12 +46,41 @@ export declare const RANDOM_LU: string;
31
46
  export declare const RANDOM_LUN: string;
32
47
  export declare const RANDOM_V = "ACEFGHJKLMNPRSTWXY34567";
33
48
  export declare const RANDOM_LUNS: string;
49
+ /**
50
+ * --- 生成随机字符串 ---
51
+ * @param length 长度
52
+ * @param source 采样值
53
+ * @param block 排除的字符
54
+ */
34
55
  export declare function random(length?: number, source?: string, block?: string): string;
35
56
  export declare const CONVERT62_CHAR = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
57
+ /**
58
+ * --- 将 10 进制转换为 62 进制 ---
59
+ * @param n 10 进制数字最大 9223372036854775807n
60
+ */
36
61
  export declare function convert62(n: bigint | number | string): string;
62
+ /**
63
+ * --- 将 62 进制转换为 10 进制 ---
64
+ * @param n 62 进制数字最大 aZl8N0y58M7
65
+ */
37
66
  export declare function unconvert62(n: string): bigint;
67
+ /**
68
+ * --- 去除 html 的空白符、换行以及注释 ---
69
+ * @param text 要纯净的字符串
70
+ */
38
71
  export declare function purify(text: string): string;
72
+ /**
73
+ * --- 判断一个对象是否符合示例组,返回空字符串代表校验通过,返回:应该的类型:位置:传入的类型 ---
74
+ * @param val 对象
75
+ * @param type 示例组
76
+ * @param tree 当前树,无需传入
77
+ */
39
78
  export declare function checkType(val: any, type: any, tree?: string): string;
79
+ /**
80
+ * --- 获取 MUID ---
81
+ * @param ctr Ctr 对象
82
+ * @param opt len: 8 - 32, 默认 8; bin: 是否含有大小写, 默认 true; key: 多样性混合, 默认空; insert: 插入指定字符, 最好不超过 2 字符,默认空,num: 是否含有数字,默认 true
83
+ */
40
84
  export declare function muid(ctr: sCtr.Ctr, opt?: {
41
85
  'len'?: number;
42
86
  'bin'?: boolean;
@@ -44,24 +88,84 @@ export declare function muid(ctr: sCtr.Ctr, opt?: {
44
88
  'insert'?: string;
45
89
  'num'?: boolean;
46
90
  }): string;
91
+ /**
92
+ * --- 获取 IP(非安全 IP)---
93
+ * @param ctr
94
+ */
47
95
  export declare function ip(ctr: sCtr.Ctr | http.IncomingHttpHeaders, req?: http2.Http2ServerRequest | http.IncomingMessage): string;
48
96
  export declare const REAL_IP_X = "x-forwarded-for";
49
97
  export declare const REAL_IP_CF = "cf-connecting-ip";
98
+ /**
99
+ * --- 获取直连 IP(安全 IP) ---
100
+ * @param ctr
101
+ * @param name 输入安全的 header
102
+ */
50
103
  export declare function realIP(ctr: sCtr.Ctr, name?: string): string;
104
+ /**
105
+ * --- 间隔一段时间 ---
106
+ * @param ms 间隔毫秒
107
+ */
51
108
  export declare function sleep(ms: number): Promise<void>;
109
+ /**
110
+ * --- 将对象进行升序排列 ---
111
+ * @param o 要重排的对象
112
+ */
52
113
  export declare function objectSort<T extends Record<string, any>>(o: T): T;
114
+ /**
115
+ * --- 将对象的所有属性清除包括键,不会破坏引用关系,对象变量依然保证是引用状态 ---
116
+ * @param obj 要清除的对象
117
+ * @patam deep 也将子项都清空,如果子项有独立引用的话也要清空的话则要设置为 true
118
+ */
53
119
  export declare function emptyObject(obj: Record<string, types.Json>, deep?: boolean): void;
120
+ /**
121
+ * --- 调用前自行创建 passThrough,并且调用 pipe 绑定到应该绑定的对象,然后再调用本函数 ---
122
+ * @param passThrough passThrough 对象
123
+ * @param data 数组
124
+ * @param end 是否关闭写入,默认是,关闭后 passThrough 不能被写入,但仍然可读
125
+ */
54
126
  export declare function passThroughAppend(passThrough: stream.PassThrough, data: Array<stream.Readable | lResponse.Response | string | Buffer>, end?: boolean): Promise<void>;
127
+ /**
128
+ * --- 执行命令行 ---
129
+ * @param command 命令字符串
130
+ */
55
131
  export declare function exec(command: string): Promise<string | false>;
132
+ /**
133
+ * --- 向主进程(或局域网同代码机子)发送广播将进行 reload 操作,等待回传 ---
134
+ * --- 主要作用除代码热更新以外的其他情况 ---
135
+ */
56
136
  export declare function sendReload(hosts?: string[]): Promise<string[]>;
137
+ /**
138
+ * --- 向主进程(或局域网同代码机子)发送广播将进行 restart 操作,停止监听并启动新进程,老进程在连接全部断开后自行销毁 ---
139
+ * --- 主要用作不间断的代码热更新 ---
140
+ */
57
141
  export declare function sendRestart(hosts?: string[]): Promise<string[]>;
142
+ /** --- 跨进程全局变量 --- */
58
143
  export declare const global: Record<string, any>;
144
+ /**
145
+ * --- 设置跨线程的全局变量 ---
146
+ * @param key 变量名
147
+ * @param data 变量值
148
+ * @param hosts 局域网列表
149
+ */
59
150
  export declare function setGlobal(key: string, data: types.Json, hosts?: string[]): Promise<string[]>;
151
+ /**
152
+ * --- 移除某个跨线程全局变量 ---
153
+ * @param key 变量名
154
+ * @param hosts 局域网列表
155
+ */
60
156
  export declare function removeGlobal(key: string, hosts?: string[]): Promise<string[]>;
157
+ /**
158
+ * --- 上传并覆盖代码文件,config.json、kebab.json、.js.map、.ts, .gitignore 不会被覆盖和新建 ---
159
+ * @param sourcePath zip 文件
160
+ * @param path 要覆盖到的路径,无所谓是否 / 开头 / 结尾,是对方 kebab 的根据路开始算起
161
+ * @param hosts 局域网多机部署,不设置默认本机部署
162
+ * @param config 是否自动更新 config 的 set.staticVer 为最新,默认更新
163
+ */
61
164
  export declare function updateCode(sourcePath: string, path: string, hosts?: string[], config?: boolean): Promise<Record<string, {
62
165
  'result': boolean;
63
166
  'return': string;
64
167
  }>>;
168
+ /** --- log 设置的选项 --- */
65
169
  export interface ILogOptions {
66
170
  'path': string;
67
171
  'urlFull': string;
@@ -71,15 +175,45 @@ export interface ILogOptions {
71
175
  'cookie': Record<string, string>;
72
176
  'headers': http.IncomingHttpHeaders;
73
177
  }
178
+ /**
179
+ * --- 写入文件日志 ---
180
+ * @param msg 自定义内容
181
+ * @param fend 文件名追加
182
+ * @param opt 选项
183
+ */
74
184
  export declare function log(opt: sCtr.Ctr | ILogOptions, msg: string, fend?: string): Promise<void>;
185
+ /**
186
+ * --- 获取日志内容为一个数组 ---
187
+ * @param opt 参数
188
+ */
75
189
  export declare function getLog(opt: {
190
+ /** --- 如 127.0.0.1 --- */
76
191
  'host': string;
192
+ /** --- 如 2024/08/01/22 --- */
77
193
  'path': string;
194
+ /** --- 如 -error --- */
78
195
  'fend'?: string;
196
+ /** --- 仅显示被搜索到的行 --- */
79
197
  'search'?: string;
198
+ /** --- 跳过条数 --- */
80
199
  'offset'?: number;
200
+ /** --- 最大限制,默认 100 --- */
81
201
  'limit'?: number;
82
202
  }): Promise<string[][] | null | false>;
203
+ /**
204
+ * --- 完整的克隆一份数组/对象,Kebab: yes, Mutton: no ---
205
+ * @param obj 要克隆的对象
206
+ */
83
207
  export declare function clone(obj: Record<string, any> | any[]): any[] | any;
208
+ /**
209
+ * --- 打印调试信息,线上环境不会打印 ---
210
+ * @param message 参数
211
+ * @param optionalParams 参数
212
+ */
84
213
  export declare function debug(message?: any, ...optionalParams: any[]): void;
214
+ /**
215
+ * --- 向控制台直接显示内容,一般情况下禁止使用 ---
216
+ * @param message 参数
217
+ * @param optionalParams 参数
218
+ */
85
219
  export declare function display(message?: any, ...optionalParams: any[]): void;
package/lib/core.js CHANGED
@@ -59,6 +59,11 @@ exports.getLog = getLog;
59
59
  exports.clone = clone;
60
60
  exports.debug = debug;
61
61
  exports.display = display;
62
+ /**
63
+ * Project: Kebab, User: JianSuoQiYue
64
+ * Date: 2019-5-3 23:54
65
+ * Last: 2020-4-11 22:34:58, 2022-10-2 14:13:06, 2022-12-28 20:33:24, 2023-12-15 11:49:02, 2024-7-2 15:23:35, 2025-6-13 19:45:53
66
+ */
62
67
  const cp = __importStar(require("child_process"));
63
68
  const stream = __importStar(require("stream"));
64
69
  const lTime = __importStar(require("../lib/time"));
@@ -69,12 +74,25 @@ const lCrypto = __importStar(require("../lib/crypto"));
69
74
  const lResponse = __importStar(require("../lib/net/response"));
70
75
  const sCtr = __importStar(require("../sys/ctr"));
71
76
  const kebab = __importStar(require("../index"));
77
+ /** --- 全局参数 --- */
72
78
  exports.globalConfig = {};
79
+ /**
80
+ * --- 设置 cookie ---
81
+ * @param ctr ctr 实例
82
+ * @param name 名
83
+ * @param value 值
84
+ * @param opt 选项,ttl, 默认和 undefined 为关闭浏览器失效
85
+ */
73
86
  function setCookie(ctr, name, value, opt = {}) {
74
87
  const res = ctr.getPrototype('_res');
75
88
  if (!res) {
76
89
  return;
77
90
  }
91
+ /*
92
+ const expires = lTime.get(ctr, {
93
+ 'data': lTime.stamp() + ttl
94
+ }).toUTCString();
95
+ */
78
96
  const maxAge = opt.ttl === undefined ? '' : `; Max-Age=${opt.ttl}`;
79
97
  const path = `; path=${opt.path ?? '/'}`;
80
98
  const domain = opt.domain ? `; domain=${opt.domain}` : '';
@@ -82,9 +100,16 @@ function setCookie(ctr, name, value, opt = {}) {
82
100
  const httpOnly = opt.httponly ? '; HttpOnly' : '';
83
101
  const sameSite = opt.samesite ? '; SameSite=' + opt.samesite : '';
84
102
  const cookies = res.getHeader('set-cookie') ?? [];
103
+ // cookies.push(`${name}=${encodeURIComponent(value)}; expires=${expires}; Max-Age=${ttl}${path}${domain}${secure}${httpOnly}`);
85
104
  cookies.push(`${name}=${encodeURIComponent(value)}${maxAge}${path}${domain}${secure}${httpOnly}${sameSite}`);
86
105
  res.setHeader('set-cookie', cookies);
87
106
  }
107
+ /**
108
+ * --- 生成基础的范围随机数 ---
109
+ * @param min >= 最小值
110
+ * @param max <= 最大值
111
+ * @param prec 保留几位小数
112
+ */
88
113
  function rand(min, max, prec = 0) {
89
114
  if (prec < 0) {
90
115
  prec = 0;
@@ -94,6 +119,7 @@ function rand(min, max, prec = 0) {
94
119
  max = max * p;
95
120
  return Math.round(Math.random() * (max - min) + min) / p;
96
121
  }
122
+ // --- 随机 ---
97
123
  exports.RANDOM_N = '0123456789';
98
124
  exports.RANDOM_U = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
99
125
  exports.RANDOM_L = 'abcdefghijklmnopqrstuvwxyz';
@@ -103,7 +129,14 @@ exports.RANDOM_LU = exports.RANDOM_L + exports.RANDOM_U;
103
129
  exports.RANDOM_LUN = exports.RANDOM_L + exports.RANDOM_U + exports.RANDOM_N;
104
130
  exports.RANDOM_V = 'ACEFGHJKLMNPRSTWXY34567';
105
131
  exports.RANDOM_LUNS = exports.RANDOM_LUN + '()`~!@#$%^&*-+=_|{}[]:;"<>,.?/]"';
132
+ /**
133
+ * --- 生成随机字符串 ---
134
+ * @param length 长度
135
+ * @param source 采样值
136
+ * @param block 排除的字符
137
+ */
106
138
  function random(length = 8, source = exports.RANDOM_LN, block = '') {
139
+ // --- 剔除 block 字符 ---
107
140
  let len = block.length;
108
141
  if (len > 0) {
109
142
  for (let i = 0; i < len; ++i) {
@@ -121,6 +154,10 @@ function random(length = 8, source = exports.RANDOM_LN, block = '') {
121
154
  return temp;
122
155
  }
123
156
  exports.CONVERT62_CHAR = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
157
+ /**
158
+ * --- 将 10 进制转换为 62 进制 ---
159
+ * @param n 10 进制数字最大 9223372036854775807n
160
+ */
124
161
  function convert62(n) {
125
162
  if (typeof n !== 'bigint') {
126
163
  n = BigInt(n);
@@ -132,6 +169,10 @@ function convert62(n) {
132
169
  }
133
170
  return res;
134
171
  }
172
+ /**
173
+ * --- 将 62 进制转换为 10 进制 ---
174
+ * @param n 62 进制数字最大 aZl8N0y58M7
175
+ */
135
176
  function unconvert62(n) {
136
177
  let res = 0n;
137
178
  const nl = n.length;
@@ -140,6 +181,10 @@ function unconvert62(n) {
140
181
  }
141
182
  return res;
142
183
  }
184
+ /**
185
+ * --- 去除 html 的空白符、换行以及注释 ---
186
+ * @param text 要纯净的字符串
187
+ */
143
188
  function purify(text) {
144
189
  text = '>' + text + '<';
145
190
  const keepScripts = [];
@@ -163,9 +208,17 @@ function purify(text) {
163
208
  });
164
209
  return text.slice(1, -1);
165
210
  }
211
+ /**
212
+ * --- 判断一个对象是否符合示例组,返回空字符串代表校验通过,返回:应该的类型:位置:传入的类型 ---
213
+ * @param val 对象
214
+ * @param type 示例组
215
+ * @param tree 当前树,无需传入
216
+ */
166
217
  function checkType(val, type, tree = 'root') {
218
+ /** --- 要校验的对象 --- */
167
219
  const vtype = typeof val;
168
220
  if (Array.isArray(type)) {
221
+ // --- 数组的话 ---
169
222
  if (!Array.isArray(val)) {
170
223
  return 'array:' + tree + ':' + vtype;
171
224
  }
@@ -177,8 +230,10 @@ function checkType(val, type, tree = 'root') {
177
230
  }
178
231
  return '';
179
232
  }
233
+ /** --- 要符合的类型 --- */
180
234
  const ttype = typeof type;
181
235
  if (type instanceof RegExp) {
236
+ // --- 正则 ---
182
237
  if (vtype !== 'string') {
183
238
  return 'regexp:' + tree + ':' + vtype;
184
239
  }
@@ -188,6 +243,7 @@ function checkType(val, type, tree = 'root') {
188
243
  if (vtype !== 'string' && val !== undefined && val !== null) {
189
244
  return 'string:' + tree + ':' + vtype;
190
245
  }
246
+ // --- 是字符串、undefined、null ---
191
247
  if (type) {
192
248
  return val ? '' : 'require:' + tree + ':' + vtype;
193
249
  }
@@ -206,12 +262,14 @@ function checkType(val, type, tree = 'root') {
206
262
  if (!Object.keys(type).length) {
207
263
  return '';
208
264
  }
265
+ // --- 先判断每个值是否相等 ---
209
266
  for (const key in type) {
210
267
  const res = checkType(val[key], type[key], tree + '.' + key);
211
268
  if (res) {
212
269
  return res;
213
270
  }
214
271
  }
272
+ // --- 再判断是否传了类型限定中没有的值 ---
215
273
  for (const key in val) {
216
274
  if (type[key] !== undefined) {
217
275
  continue;
@@ -222,6 +280,11 @@ function checkType(val, type, tree = 'root') {
222
280
  }
223
281
  return vtype === ttype ? '' : ttype + ':' + tree + ':' + vtype;
224
282
  }
283
+ /**
284
+ * --- 获取 MUID ---
285
+ * @param ctr Ctr 对象
286
+ * @param opt len: 8 - 32, 默认 8; bin: 是否含有大小写, 默认 true; key: 多样性混合, 默认空; insert: 插入指定字符, 最好不超过 2 字符,默认空,num: 是否含有数字,默认 true
287
+ */
225
288
  function muid(ctr, opt = {}) {
226
289
  const len = opt.len ?? 8;
227
290
  const bin = opt.bin ?? true;
@@ -240,9 +303,14 @@ function muid(ctr, opt = {}) {
240
303
  if (!char) {
241
304
  return '';
242
305
  }
306
+ // --- 生成随机数 ---
243
307
  const over = random(len - 1 - ilen, bin ? (num ? exports.RANDOM_LUN : exports.RANDOM_LU) : (num ? exports.RANDOM_LN : exports.RANDOM_L)) + char[20];
244
308
  return over[0] + insert + over.slice(1);
245
309
  }
310
+ /**
311
+ * --- 获取 IP(非安全 IP)---
312
+ * @param ctr
313
+ */
246
314
  function ip(ctr, req) {
247
315
  const headers = ctr instanceof sCtr.Ctr ? ctr.getPrototype('_headers') : ctr;
248
316
  if (typeof headers['cf-connecting-ip'] === 'string') {
@@ -265,6 +333,11 @@ function ip(ctr, req) {
265
333
  }
266
334
  exports.REAL_IP_X = 'x-forwarded-for';
267
335
  exports.REAL_IP_CF = 'cf-connecting-ip';
336
+ /**
337
+ * --- 获取直连 IP(安全 IP) ---
338
+ * @param ctr
339
+ * @param name 输入安全的 header
340
+ */
268
341
  function realIP(ctr, name = '') {
269
342
  const headers = ctr.getPrototype('_headers');
270
343
  if (name !== '') {
@@ -276,6 +349,11 @@ function realIP(ctr, name = '') {
276
349
  const req = ctr.getPrototype('_req');
277
350
  return req.socket.remoteAddress ?? '';
278
351
  }
352
+ // --- 以下 Mutton 没有 ---
353
+ /**
354
+ * --- 间隔一段时间 ---
355
+ * @param ms 间隔毫秒
356
+ */
279
357
  function sleep(ms) {
280
358
  return new Promise(function (resolve) {
281
359
  setTimeout(function () {
@@ -283,6 +361,10 @@ function sleep(ms) {
283
361
  }, ms);
284
362
  });
285
363
  }
364
+ /**
365
+ * --- 将对象进行升序排列 ---
366
+ * @param o 要重排的对象
367
+ */
286
368
  function objectSort(o) {
287
369
  const ordered = {};
288
370
  const list = Object.keys(o).sort();
@@ -296,6 +378,11 @@ function objectSort(o) {
296
378
  }
297
379
  return ordered;
298
380
  }
381
+ /**
382
+ * --- 将对象的所有属性清除包括键,不会破坏引用关系,对象变量依然保证是引用状态 ---
383
+ * @param obj 要清除的对象
384
+ * @patam deep 也将子项都清空,如果子项有独立引用的话也要清空的话则要设置为 true
385
+ */
299
386
  function emptyObject(obj, deep = false) {
300
387
  const keys = Object.keys(obj);
301
388
  for (const key of keys) {
@@ -308,10 +395,17 @@ function emptyObject(obj, deep = false) {
308
395
  delete obj[key];
309
396
  }
310
397
  }
398
+ /**
399
+ * --- 调用前自行创建 passThrough,并且调用 pipe 绑定到应该绑定的对象,然后再调用本函数 ---
400
+ * @param passThrough passThrough 对象
401
+ * @param data 数组
402
+ * @param end 是否关闭写入,默认是,关闭后 passThrough 不能被写入,但仍然可读
403
+ */
311
404
  async function passThroughAppend(passThrough, data, end = true) {
312
405
  for (const item of data) {
313
406
  if (item instanceof stream.Readable || item instanceof lResponse.Response) {
314
407
  const stm = item instanceof stream.Readable ? item : item.getStream();
408
+ // --- 读取流、Net 库 Response 对象 ---
315
409
  stm.pipe(passThrough, {
316
410
  'end': false
317
411
  });
@@ -322,6 +416,7 @@ async function passThroughAppend(passThrough, data, end = true) {
322
416
  });
323
417
  }
324
418
  else {
419
+ // --- 字符串、Buffer ---
325
420
  await new Promise((resolve) => {
326
421
  passThrough.write(item, () => {
327
422
  resolve();
@@ -333,6 +428,10 @@ async function passThroughAppend(passThrough, data, end = true) {
333
428
  passThrough.end();
334
429
  }
335
430
  }
431
+ /**
432
+ * --- 执行命令行 ---
433
+ * @param command 命令字符串
434
+ */
336
435
  function exec(command) {
337
436
  return new Promise(function (resolve) {
338
437
  cp.exec(command, function (err, stdout) {
@@ -344,15 +443,23 @@ function exec(command) {
344
443
  });
345
444
  });
346
445
  }
446
+ /**
447
+ * --- 向主进程(或局域网同代码机子)发送广播将进行 reload 操作,等待回传 ---
448
+ * --- 主要作用除代码热更新以外的其他情况 ---
449
+ */
347
450
  async function sendReload(hosts) {
348
451
  if (!hosts) {
452
+ // --- 本地模式 ---
453
+ // eslint-disable-next-line no-console
349
454
  console.log('[ Child] Sending reload request...');
350
455
  process.send({
351
456
  'action': 'reload'
352
457
  });
353
458
  return [];
354
459
  }
460
+ // --- 局域网模式 ---
355
461
  const time = lTime.stamp();
462
+ /** --- 返回成功的 host --- */
356
463
  const rtn = [];
357
464
  for (const host of hosts) {
358
465
  const res = await lNet.get('http://' + host + ':' + exports.globalConfig.rpcPort.toString() + '/' + lCrypto.aesEncrypt(lText.stringifyJson({
@@ -372,15 +479,23 @@ async function sendReload(hosts) {
372
479
  }
373
480
  return rtn;
374
481
  }
482
+ /**
483
+ * --- 向主进程(或局域网同代码机子)发送广播将进行 restart 操作,停止监听并启动新进程,老进程在连接全部断开后自行销毁 ---
484
+ * --- 主要用作不间断的代码热更新 ---
485
+ */
375
486
  async function sendRestart(hosts) {
376
487
  if (!hosts) {
488
+ // --- 本地模式 ---
489
+ // eslint-disable-next-line no-console
377
490
  console.log('[ Child] Sending restart request...');
378
491
  process.send({
379
492
  'action': 'restart'
380
493
  });
381
494
  return [];
382
495
  }
496
+ // --- 局域网模式 ---
383
497
  const time = lTime.stamp();
498
+ /** --- 返回成功的 host --- */
384
499
  const rtn = [];
385
500
  for (const host of hosts) {
386
501
  const res = await lNet.get('http://' + host + ':' + exports.globalConfig.rpcPort.toString() + '/' + lCrypto.aesEncrypt(lText.stringifyJson({
@@ -400,9 +515,17 @@ async function sendRestart(hosts) {
400
515
  }
401
516
  return rtn;
402
517
  }
518
+ /** --- 跨进程全局变量 --- */
403
519
  exports.global = {};
520
+ /**
521
+ * --- 设置跨线程的全局变量 ---
522
+ * @param key 变量名
523
+ * @param data 变量值
524
+ * @param hosts 局域网列表
525
+ */
404
526
  async function setGlobal(key, data, hosts) {
405
527
  if (!hosts) {
528
+ // --- 本地模式 ---
406
529
  process.send({
407
530
  'action': 'global',
408
531
  'key': key,
@@ -410,7 +533,9 @@ async function setGlobal(key, data, hosts) {
410
533
  });
411
534
  return [];
412
535
  }
536
+ // --- 局域网模式 ---
413
537
  const time = lTime.stamp();
538
+ /** --- 返回成功的 host --- */
414
539
  const rtn = [];
415
540
  for (const host of hosts) {
416
541
  const res = await lNet.get('http://' + host + ':' + exports.globalConfig.rpcPort.toString() + '/' + lCrypto.aesEncrypt(lText.stringifyJson({
@@ -430,11 +555,24 @@ async function setGlobal(key, data, hosts) {
430
555
  }
431
556
  return rtn;
432
557
  }
558
+ /**
559
+ * --- 移除某个跨线程全局变量 ---
560
+ * @param key 变量名
561
+ * @param hosts 局域网列表
562
+ */
433
563
  async function removeGlobal(key, hosts) {
434
564
  return setGlobal(key, null, hosts);
435
565
  }
566
+ /**
567
+ * --- 上传并覆盖代码文件,config.json、kebab.json、.js.map、.ts, .gitignore 不会被覆盖和新建 ---
568
+ * @param sourcePath zip 文件
569
+ * @param path 要覆盖到的路径,无所谓是否 / 开头 / 结尾,是对方 kebab 的根据路开始算起
570
+ * @param hosts 局域网多机部署,不设置默认本机部署
571
+ * @param config 是否自动更新 config 的 set.staticVer 为最新,默认更新
572
+ */
436
573
  async function updateCode(sourcePath, path, hosts, config = true) {
437
574
  hosts ??= ['127.0.0.1'];
575
+ /** --- 返回成功的 host --- */
438
576
  const rtn = {};
439
577
  for (const host of hosts) {
440
578
  const fd = lNet.getFormData();
@@ -465,6 +603,12 @@ async function updateCode(sourcePath, path, hosts, config = true) {
465
603
  }
466
604
  return rtn;
467
605
  }
606
+ /**
607
+ * --- 写入文件日志 ---
608
+ * @param msg 自定义内容
609
+ * @param fend 文件名追加
610
+ * @param opt 选项
611
+ */
468
612
  async function log(opt, msg, fend = '') {
469
613
  let req;
470
614
  let headers;
@@ -526,16 +670,24 @@ async function log(opt, msg, fend = '') {
526
670
  'flag': 'a'
527
671
  });
528
672
  }
673
+ /**
674
+ * --- 获取日志内容为一个数组 ---
675
+ * @param opt 参数
676
+ */
529
677
  async function getLog(opt) {
530
678
  const path = kebab.LOG_CWD + opt.host + (opt.fend ?? '') + '/' + opt.path + '.csv';
531
679
  if (!await lFs.isFile(path)) {
532
680
  return null;
533
681
  }
682
+ /** --- 剩余 limit --- */
534
683
  let limit = opt.limit ?? 100;
684
+ /** --- 剩余 offset --- */
535
685
  let offset = opt.offset ?? 0;
536
686
  return new Promise((resolve) => {
537
687
  const list = [];
688
+ /** --- 当前行号 --- */
538
689
  let line = 0;
690
+ /** --- 当前行数据 --- */
539
691
  let packet = '';
540
692
  lFs.createReadStream(path, {
541
693
  'encoding': 'utf8'
@@ -544,17 +696,21 @@ async function getLog(opt) {
544
696
  return;
545
697
  }
546
698
  while (true) {
699
+ // --- 分包 ---
547
700
  const index = buf.indexOf('\n');
548
701
  if (index === -1) {
702
+ // --- 本次包还没有结束 ---
549
703
  packet += buf;
550
704
  break;
551
705
  }
706
+ // --- 本次行结束了 ---
552
707
  if (limit === 0) {
553
708
  break;
554
709
  }
555
710
  packet += buf.slice(0, index);
556
711
  buf = buf.slice(index + 1);
557
712
  ++line;
713
+ // --- 先执行下本次完成的 ---
558
714
  if (line > 1) {
559
715
  if (offset === 0) {
560
716
  if (!opt.search || packet.includes(opt.search)) {
@@ -589,10 +745,14 @@ async function getLog(opt) {
589
745
  --offset;
590
746
  }
591
747
  }
748
+ // --- 处理结束 ---
592
749
  packet = '';
750
+ // --- 看看还有没有后面的粘连包 ---
593
751
  if (!buf.length) {
752
+ // --- 没粘连包 ---
594
753
  break;
595
754
  }
755
+ // --- 有粘连包 ---
596
756
  }
597
757
  }).on('end', () => {
598
758
  resolve(list);
@@ -601,6 +761,10 @@ async function getLog(opt) {
601
761
  });
602
762
  });
603
763
  }
764
+ /**
765
+ * --- 完整的克隆一份数组/对象,Kebab: yes, Mutton: no ---
766
+ * @param obj 要克隆的对象
767
+ */
604
768
  function clone(obj) {
605
769
  let newObj = {};
606
770
  if (obj instanceof Array) {
@@ -652,12 +816,24 @@ function clone(obj) {
652
816
  }
653
817
  return newObj;
654
818
  }
819
+ /**
820
+ * --- 打印调试信息,线上环境不会打印 ---
821
+ * @param message 参数
822
+ * @param optionalParams 参数
823
+ */
655
824
  function debug(message, ...optionalParams) {
656
825
  if (!exports.globalConfig.debug) {
657
826
  return;
658
827
  }
828
+ // eslint-disable-next-line no-console
659
829
  console.debug(message, ...optionalParams);
660
830
  }
831
+ /**
832
+ * --- 向控制台直接显示内容,一般情况下禁止使用 ---
833
+ * @param message 参数
834
+ * @param optionalParams 参数
835
+ */
661
836
  function display(message, ...optionalParams) {
837
+ // eslint-disable-next-line no-console
662
838
  console.log(message, ...optionalParams);
663
839
  }