@maiyunnet/kebab 2.0.7 → 2.0.9

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 +5 -0
  58. package/main.js +12 -0
  59. package/package.json +3 -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/text.d.ts CHANGED
@@ -1,40 +1,171 @@
1
1
  import * as types from '../types';
2
+ /**
3
+ * --- 将文件大小格式化为带单位的字符串 ---
4
+ * @param size 文件大小
5
+ * @param spliter 分隔符
6
+ */
2
7
  export declare function sizeFormat(size: number, spliter?: string): string;
8
+ /**
9
+ * --- 格式化一段 URL ---
10
+ * @param url
11
+ */
3
12
  export declare function parseUrl(url: string): types.IUrlParse;
13
+ /**
14
+ * --- 将相对路径根据基准路径进行转换 ---
15
+ * @param from 基准路径
16
+ * @param to 相对路径
17
+ */
4
18
  export declare function urlResolve(from: string, to: string): string;
19
+ /**
20
+ * --- 将路径中的 ../ ./ 都按规范妥善处理 ---
21
+ * @param url 要处理的地址
22
+ */
5
23
  export declare function urlAtom(url: string): string;
6
24
  export declare const REGEXP_EMAIL: RegExp;
25
+ /**
26
+ * --- 是否是邮件地址 ---
27
+ * @param email
28
+ */
7
29
  export declare function isEMail(email: string): boolean;
8
30
  export declare const REGEXP_IPV4: RegExp;
31
+ /**
32
+ * --- 是否是 IPv4 ---
33
+ * @param ip
34
+ */
9
35
  export declare function isIPv4(ip: string): boolean;
10
36
  export declare const REGEXP_IPV6: RegExp;
37
+ /**
38
+ * --- 是否是 IPv6 ---
39
+ * @param ip
40
+ */
11
41
  export declare function isIPv6(ip: string): boolean;
12
42
  export declare const REGEXP_DOMAIN: RegExp;
43
+ /**
44
+ * --- 判断是否是域名 ---
45
+ * @param string $domain
46
+ * @return bool
47
+ */
13
48
  export declare function isDomain(domain: string): boolean;
14
49
  export declare const REGEXP_ASCII: RegExp;
50
+ /**
51
+ * --- 判断是否在 ascii 字符集内,仅可输入部分 ---
52
+ * @param text 要判断的文本
53
+ */
15
54
  export declare function isAscii(text: string): boolean;
55
+ /**
56
+ * --- 换行替换为别的 ---
57
+ * @param str 要替换的字符串
58
+ * @param to 换行替换符
59
+ */
16
60
  export declare function nlReplace(str: string, to?: string): string;
61
+ /** 解析后的 domain */
17
62
  export interface IDomain {
18
63
  tld: string | null;
19
64
  sld: string | null;
20
65
  domain: string | null;
21
66
  sub: string | null;
22
67
  }
68
+ /**
69
+ * --- 解析域名并获取 tld/sld/domain/sub ---
70
+ * @param domain 域名
71
+ */
23
72
  export declare function parseDomain(domain: string): Promise<IDomain>;
73
+ /**
74
+ * --- 传入正则进行匹配 str 是否有一项满足 ---
75
+ * @param str 要检测的字符串
76
+ * @param regs 正则列表
77
+ */
24
78
  export declare function match(str: string, regs: RegExp[]): boolean;
79
+ /**
80
+ * --- 判断手机号是否是 11 位,不做真实性校验 ---
81
+ * @param p 手机号
82
+ */
25
83
  export declare function isPhoneCN(p: string): boolean;
84
+ /**
85
+ * --- 是否是中国大陆身份证号码 ---
86
+ * @param idcard 身份证号
87
+ */
26
88
  export declare function isIdCardCN(idcard: string): boolean;
89
+ /**
90
+ * --- 将对象转换为 query string ---
91
+ * @param query 要转换的对象
92
+ * @param encode 是否转义
93
+ */
27
94
  export declare function queryStringify(query: Record<string, any>, encode?: boolean): string;
95
+ /**
96
+ * --- 将 query string 转换为对象 ---
97
+ * @param query 要转换的字符串
98
+ */
28
99
  export declare function queryParse(query: string): Record<string, string | string[]>;
100
+ /**
101
+ * --- HTML 特殊字符转换为实体字符 ---
102
+ * @param html 待转换的 HTML
103
+ */
29
104
  export declare function htmlescape(html: string): string;
105
+ /**
106
+ * --- 判断是否是绝对路径,是返回 true,相对路径返回 false ---
107
+ * @param path 要判断的路径字符串
108
+ */
30
109
  export declare function isRealPath(path: string): boolean;
110
+ /**
111
+ * --- 获取文件名 ---
112
+ * @param path 文件路径
113
+ */
31
114
  export declare function getFilename(path: string): string;
115
+ /**
116
+ * --- 将普通的返回 JSON 对象序列化为字符串,Mutton 不能使用 ---
117
+ * @param o 返回 JSON 对象
118
+ */
32
119
  export declare function stringifyResult(rtn: types.Json): string;
120
+ /**
121
+ * --- 将字符串解析为对象,返回 false 代表解析失败,支持 BigInt,Kebab true, Mutton false ---
122
+ * @param str 要解析的 json 字符串
123
+ */
33
124
  export declare function parseJson(str: string): any;
125
+ /**
126
+ * --- 将对象转换为 json 字符串,返回 false 代表解析失败,支持 BigInt,Kebab true, Mutton false ---
127
+ * @param obj 要转换的 json 对象
128
+ * @param space 美化方式
129
+ */
34
130
  export declare function stringifyJson(obj: types.Json, space?: string | number): string;
131
+ /**
132
+ * --- 输出文本格式的 buffer ---
133
+ * @param buf 原始 buffer
134
+ */
135
+ export declare function stringifyBuffer(buf: Buffer): string;
35
136
  type TFalsy = false | '' | 0 | null | undefined | typeof NaN;
137
+ /**
138
+ * --- 判断一个值是否是虚假的(为 null/undefined/空字符串/false/0) ---
139
+ * @param val 要判断的值
140
+ */
36
141
  export declare function isFalsy(val: any): val is TFalsy;
142
+ /**
143
+ * --- 类似 || 运算符的效果 ---
144
+ * @param v1 比对值
145
+ * @param v2 比对值
146
+ */
37
147
  export declare function logicalOr<T, T2>(v1: T, v2: T2): [T] extends [TFalsy] ? T2 : T;
148
+ /**
149
+ * --- 为解决精度问题,将字符串数字转换为整数显示 ---
150
+ * --- 以下几个示例都是当 digits 为 2 时 ---
151
+ * --- str 传入 '1.234',返回 123 ---
152
+ * --- str 传入 '1.235',返回 124 ---
153
+ * --- str 传入 '1.1',返回 110 ---
154
+ * --- str 传入 '6',返回 600 ---
155
+ * @param str 要转换的数字字符串
156
+ * @param digits 小数点右移位数
157
+ */
38
158
  export declare function str2int(str: string, digits?: number): number;
159
+ /**
160
+ * --- 为解决精度问题,将整数转换为小数字符串 ---
161
+ * --- 以下几个示例都是当 digits 为 3、decimal 为 2 时 ---
162
+ * --- int 传入 2341,返回 '2.34' ---
163
+ * --- int 传入 2345,返回 '2.35' ---
164
+ * --- int 传入 23,返回 '0.02' ---
165
+ * --- int 传入 2,返回 '0.00' ---
166
+ * @param int 要转换的整数
167
+ * @param digits 小数点左移位数
168
+ * @param decimal 最终保留的小数位数
169
+ */
39
170
  export declare function int2str(int: number, digits?: number, decimal?: number): string;
40
171
  export {};
package/lib/text.js CHANGED
@@ -56,12 +56,23 @@ exports.getFilename = getFilename;
56
56
  exports.stringifyResult = stringifyResult;
57
57
  exports.parseJson = parseJson;
58
58
  exports.stringifyJson = stringifyJson;
59
+ exports.stringifyBuffer = stringifyBuffer;
59
60
  exports.isFalsy = isFalsy;
60
61
  exports.logicalOr = logicalOr;
61
62
  exports.str2int = str2int;
62
63
  exports.int2str = int2str;
64
+ /**
65
+ * Project: Kebab, User: JianSuoQiYue
66
+ * Date: 2019-5-15 16:49:39
67
+ * Last: 2020-04-06 20:51:06, 2022-9-29 15:18:16, 2022-12-29 00:01:30, 2024-3-6 17:53:14, 2024-5-31 17:29:52, 2025-6-13 15:47:02
68
+ */
63
69
  const kebab = __importStar(require("../index"));
64
70
  const fs = __importStar(require("./fs"));
71
+ /**
72
+ * --- 将文件大小格式化为带单位的字符串 ---
73
+ * @param size 文件大小
74
+ * @param spliter 分隔符
75
+ */
65
76
  function sizeFormat(size, spliter = ' ') {
66
77
  const units = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
67
78
  let i = 0;
@@ -70,7 +81,12 @@ function sizeFormat(size, spliter = ' ') {
70
81
  }
71
82
  return (Math.round(size * 100) / 100).toString() + spliter + units[i];
72
83
  }
84
+ /**
85
+ * --- 格式化一段 URL ---
86
+ * @param url
87
+ */
73
88
  function parseUrl(url) {
89
+ // --- test: https://ab-3dc:aak9()$@github.com:80/nodejs/node/blob/master/lib/url.js?mail=abc@def.com#223 ---
74
90
  const rtn = {
75
91
  'protocol': null,
76
92
  'auth': null,
@@ -114,6 +130,7 @@ function parseUrl(url) {
114
130
  const authStr = url.slice(0, auth);
115
131
  const authSplit = authStr.indexOf(':');
116
132
  if (authSplit > -1) {
133
+ // --- 有密码 ---
117
134
  rtn['user'] = authStr.slice(0, authSplit);
118
135
  rtn['pass'] = authStr.slice(authSplit + 1);
119
136
  rtn['auth'] = rtn['user'] + ':' + rtn['pass'];
@@ -138,28 +155,43 @@ function parseUrl(url) {
138
155
  }
139
156
  }
140
157
  else {
158
+ // --- 没有 protocol ---
141
159
  rtn['pathname'] = url;
142
160
  }
161
+ // --- 组合 ---
143
162
  rtn['path'] = rtn['pathname'] + (rtn['query'] ? '?' + rtn['query'] : '');
144
163
  return rtn;
145
164
  }
165
+ /**
166
+ * --- 将相对路径根据基准路径进行转换 ---
167
+ * @param from 基准路径
168
+ * @param to 相对路径
169
+ */
146
170
  function urlResolve(from, to) {
147
171
  from = from.replace('\\', '/');
148
172
  to = to.replace('\\', '/');
173
+ // --- to 为空,直接返回 form ---
149
174
  if (to === '') {
150
175
  return urlAtom(from);
151
176
  }
177
+ // --- 获取 from 的 scheme, host, path ---
152
178
  const f = parseUrl(from);
179
+ // --- 以 // 开头的,加上 from 的 protocol 返回 ---
153
180
  if (to.startsWith('//')) {
154
181
  return urlAtom(f.protocol ? f.protocol + to : to);
155
182
  }
156
183
  if (f.protocol) {
184
+ // --- 获取小写的 protocol ---
157
185
  from = f.protocol + from.slice(f.protocol.length);
158
186
  }
187
+ // --- 获取 to 的 scheme, host, path ---
159
188
  const t = parseUrl(to);
189
+ // --- 已经是绝对路径,直接返回 ---
160
190
  if (t.protocol) {
191
+ // --- 获取小写的 protocol ---
161
192
  return urlAtom(t.protocol + to.slice(t.protocol.length));
162
193
  }
194
+ // --- # 或 ? 替换后返回 ---
163
195
  if (to.startsWith('#') || to.startsWith('?')) {
164
196
  const sp = from.indexOf(to[0]);
165
197
  if (sp !== -1) {
@@ -169,25 +201,39 @@ function urlResolve(from, to) {
169
201
  return urlAtom(from + to);
170
202
  }
171
203
  }
204
+ // --- 处理后面的尾随路径 ---
172
205
  let abs = (f.auth ? f.auth + '@' : '') + (f.host ?? '');
173
206
  if (to.startsWith('/')) {
207
+ // -- abs 类似是 /xx/xx ---
174
208
  abs += to;
175
209
  }
176
210
  else {
211
+ // --- to 是 xx/xx 这样的 ---
212
+ // --- 移除基准 path 不是路径的部分,如 /ab/c 变成了 /ab,/ab 变成了 空 ---
177
213
  const path = f.pathname.replace(/\/[^/]*$/g, '');
214
+ // --- abs 是 /xx/xx 了,因为如果 path 是空,则跟上了 /,如果 path 不为空,也是 / 开头 ---
178
215
  abs += path + '/' + to;
179
216
  }
217
+ // --- 返回最终结果 ---
180
218
  if (f.protocol && (f.protocol !== 'file:') && !f.host) {
219
+ // --- 类似 c:/ ---
181
220
  return urlAtom(f.protocol + abs);
182
221
  }
183
222
  else {
223
+ // --- 类似 http:// ---
184
224
  return urlAtom((f.protocol ? f.protocol + '//' : '') + abs);
185
225
  }
186
226
  }
227
+ /**
228
+ * --- 将路径中的 ../ ./ 都按规范妥善处理 ---
229
+ * @param url 要处理的地址
230
+ */
187
231
  function urlAtom(url) {
232
+ // --- 删掉 ./ ---
188
233
  while (url.includes('/./')) {
189
234
  url = url.replace(/\/\.\//g, '/');
190
235
  }
236
+ // --- 删掉 ../ ---
191
237
  while (/\/(?!\.\.)[^/]+\/\.\.\//.test(url)) {
192
238
  url = url.replace(/\/(?!\.\.)[^/]+\/\.\.\//g, '/');
193
239
  }
@@ -195,25 +241,51 @@ function urlAtom(url) {
195
241
  return url;
196
242
  }
197
243
  exports.REGEXP_EMAIL = /^[-_\w.]+@[-_\w.]+\.([a-zA-Z]+)$/i;
244
+ /**
245
+ * --- 是否是邮件地址 ---
246
+ * @param email
247
+ */
198
248
  function isEMail(email) {
199
249
  return exports.REGEXP_EMAIL.test(email);
200
250
  }
201
251
  exports.REGEXP_IPV4 = /^[0-9]{1,3}(\.[0-9]{1,3}){3}$/i;
252
+ /**
253
+ * --- 是否是 IPv4 ---
254
+ * @param ip
255
+ */
202
256
  function isIPv4(ip) {
203
257
  return exports.REGEXP_IPV4.test(ip);
204
258
  }
205
259
  exports.REGEXP_IPV6 = /^(\w*?:){2,7}[\w.]*$/i;
260
+ /**
261
+ * --- 是否是 IPv6 ---
262
+ * @param ip
263
+ */
206
264
  function isIPv6(ip) {
207
265
  return exports.REGEXP_IPV6.test(ip + ':');
208
266
  }
209
267
  exports.REGEXP_DOMAIN = /^.+?\.((?![0-9]).)+$/i;
268
+ /**
269
+ * --- 判断是否是域名 ---
270
+ * @param string $domain
271
+ * @return bool
272
+ */
210
273
  function isDomain(domain) {
211
274
  return exports.REGEXP_DOMAIN.test(domain);
212
275
  }
213
276
  exports.REGEXP_ASCII = /^[\x20-\x7E]*$/;
277
+ /**
278
+ * --- 判断是否在 ascii 字符集内,仅可输入部分 ---
279
+ * @param text 要判断的文本
280
+ */
214
281
  function isAscii(text) {
215
282
  return exports.REGEXP_ASCII.test(text);
216
283
  }
284
+ /**
285
+ * --- 换行替换为别的 ---
286
+ * @param str 要替换的字符串
287
+ * @param to 换行替换符
288
+ */
217
289
  function nlReplace(str, to = '\n') {
218
290
  str = str.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
219
291
  if (to !== '\n') {
@@ -221,7 +293,12 @@ function nlReplace(str, to = '\n') {
221
293
  }
222
294
  return str;
223
295
  }
296
+ /** Tld 列表 */
224
297
  let tldList;
298
+ /**
299
+ * --- 解析域名并获取 tld/sld/domain/sub ---
300
+ * @param domain 域名
301
+ */
225
302
  async function parseDomain(domain) {
226
303
  const rtn = {
227
304
  tld: null,
@@ -243,13 +320,16 @@ async function parseDomain(domain) {
243
320
  }
244
321
  const last2 = (arr[arr.length - 2] + '.' + arr[arr.length - 1]).toLowerCase();
245
322
  if (tldList.includes(last2)) {
323
+ // --- last2 就是 tld ---
246
324
  rtn.tld = last2;
247
325
  if (arr.length === 2) {
326
+ // --- 没有 sld ---
248
327
  rtn.domain = last2;
249
328
  return rtn;
250
329
  }
251
330
  rtn.sld = arr[arr.length - 3].toLowerCase();
252
331
  rtn.domain = rtn.sld + '.' + rtn.tld;
332
+ // --- 判断是否有 sub ---
253
333
  if (arr.length === 3) {
254
334
  return rtn;
255
335
  }
@@ -260,6 +340,7 @@ async function parseDomain(domain) {
260
340
  rtn.tld = arr[arr.length - 1].toLowerCase();
261
341
  rtn.sld = arr[arr.length - 2].toLowerCase();
262
342
  rtn.domain = rtn.sld + '.' + rtn.tld;
343
+ // --- 判断是否有 sub ---
263
344
  if (arr.length === 2) {
264
345
  return rtn;
265
346
  }
@@ -269,6 +350,11 @@ async function parseDomain(domain) {
269
350
  }
270
351
  return rtn;
271
352
  }
353
+ /**
354
+ * --- 传入正则进行匹配 str 是否有一项满足 ---
355
+ * @param str 要检测的字符串
356
+ * @param regs 正则列表
357
+ */
272
358
  function match(str, regs) {
273
359
  for (const reg of regs) {
274
360
  if (reg.test(str)) {
@@ -277,22 +363,38 @@ function match(str, regs) {
277
363
  }
278
364
  return false;
279
365
  }
366
+ // --- 以下是适用于中国大陆的方法 ---
367
+ /**
368
+ * --- 判断手机号是否是 11 位,不做真实性校验 ---
369
+ * @param p 手机号
370
+ */
280
371
  function isPhoneCN(p) {
281
372
  return /^1[0-9]{10}$/.test(p);
282
373
  }
374
+ /**
375
+ * --- 是否是中国大陆身份证号码 ---
376
+ * @param idcard 身份证号
377
+ */
283
378
  function isIdCardCN(idcard) {
284
379
  if (idcard.length !== 18) {
285
380
  return false;
286
381
  }
382
+ // --- 取出本码 ---
287
383
  const idcardBase = idcard.slice(0, 17);
384
+ // --- 取出校验码 ---
288
385
  const verifyCode = idcard.slice(17, 18);
386
+ // --- 加权因子 ---
289
387
  const factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
388
+ // --- 校验码对应值 ---
290
389
  const verifyCodeList = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
390
+ // --- 根据前17位计算校验码 ---
291
391
  let total = BigInt(0);
292
392
  for (let i = 0; i < 17; i++) {
293
393
  total += BigInt(idcardBase.slice(i, i + 1)) * BigInt(factor[i]);
294
394
  }
395
+ // --- 取模 ---
295
396
  const mod = total % BigInt(11);
397
+ // --- 比较校验码 ---
296
398
  if (verifyCode === verifyCodeList[Number(mod)]) {
297
399
  return true;
298
400
  }
@@ -300,6 +402,12 @@ function isIdCardCN(idcard) {
300
402
  return false;
301
403
  }
302
404
  }
405
+ // --- 以下 Mutton: false, Kebab: true ---
406
+ /**
407
+ * --- 将对象转换为 query string ---
408
+ * @param query 要转换的对象
409
+ * @param encode 是否转义
410
+ */
303
411
  function queryStringify(query, encode = true) {
304
412
  if (encode) {
305
413
  return Object.entries(query).map(([k, v]) => {
@@ -316,6 +424,10 @@ function queryStringify(query, encode = true) {
316
424
  return `${k}=${v}`;
317
425
  }).join('&');
318
426
  }
427
+ /**
428
+ * --- 将 query string 转换为对象 ---
429
+ * @param query 要转换的字符串
430
+ */
319
431
  function queryParse(query) {
320
432
  const ret = {};
321
433
  const arrayKeys = {};
@@ -346,6 +458,10 @@ function queryParse(query) {
346
458
  }
347
459
  return ret;
348
460
  }
461
+ /**
462
+ * --- HTML 特殊字符转换为实体字符 ---
463
+ * @param html 待转换的 HTML
464
+ */
349
465
  function htmlescape(html) {
350
466
  const type = typeof html;
351
467
  if (type !== 'string') {
@@ -353,6 +469,10 @@ function htmlescape(html) {
353
469
  }
354
470
  return html.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/'/g, '&quot;');
355
471
  }
472
+ /**
473
+ * --- 判断是否是绝对路径,是返回 true,相对路径返回 false ---
474
+ * @param path 要判断的路径字符串
475
+ */
356
476
  function isRealPath(path) {
357
477
  path = path.replace(/\\/g, '/');
358
478
  if (path.startsWith('/')) {
@@ -360,6 +480,10 @@ function isRealPath(path) {
360
480
  }
361
481
  return /[a-z]+:/i.test(path.split('/')[0]) ? true : false;
362
482
  }
483
+ /**
484
+ * --- 获取文件名 ---
485
+ * @param path 文件路径
486
+ */
363
487
  function getFilename(path) {
364
488
  path = path.replace(/\\/g, '/');
365
489
  const lio = path.lastIndexOf('/');
@@ -368,8 +492,13 @@ function getFilename(path) {
368
492
  }
369
493
  return path.slice(lio + 1);
370
494
  }
495
+ /**
496
+ * --- 将普通的返回 JSON 对象序列化为字符串,Mutton 不能使用 ---
497
+ * @param o 返回 JSON 对象
498
+ */
371
499
  function stringifyResult(rtn) {
372
500
  if (Array.isArray(rtn)) {
501
+ // --- [0, 'xxx'] 模式 ---
373
502
  if (rtn.length === 0) {
374
503
  return JSON.stringify({
375
504
  'result': 0,
@@ -377,14 +506,17 @@ function stringifyResult(rtn) {
377
506
  });
378
507
  }
379
508
  if (typeof rtn[0] === 'number') {
509
+ // --- 1. ---
380
510
  const json = { 'result': rtn[0] };
381
511
  if (rtn[1] !== undefined) {
382
512
  if (typeof rtn[1] === 'object') {
513
+ // --- [0, ...{'xx': 'xx'}] ---
383
514
  for (let i = 1; i < rtn.length; ++i) {
384
515
  Object.assign(json, rtn[i]);
385
516
  }
386
517
  }
387
518
  else {
519
+ // --- [0, 'xxx'], [0, 'xxx', ...{'xx': 'xx'}] ---
388
520
  json['msg'] = rtn[1];
389
521
  for (let i = 2; i < rtn.length; ++i) {
390
522
  Object.assign(json, rtn[i]);
@@ -393,10 +525,16 @@ function stringifyResult(rtn) {
393
525
  }
394
526
  return JSON.stringify(json);
395
527
  }
528
+ // --- 直接是个 json 对象 ---
396
529
  return JSON.stringify(rtn);
397
530
  }
531
+ // --- 直接是个 json 对象 ---
398
532
  return JSON.stringify(rtn);
399
533
  }
534
+ /**
535
+ * --- 将字符串解析为对象,返回 false 代表解析失败,支持 BigInt,Kebab true, Mutton false ---
536
+ * @param str 要解析的 json 字符串
537
+ */
400
538
  function parseJson(str) {
401
539
  try {
402
540
  str = str.replace(/("[\w-]+?" *: *)([-+0-9]+)([ \r\n]*[,}]|$)/g, (v, v1, v2, v3) => {
@@ -421,6 +559,11 @@ function parseJson(str) {
421
559
  return false;
422
560
  }
423
561
  }
562
+ /**
563
+ * --- 将对象转换为 json 字符串,返回 false 代表解析失败,支持 BigInt,Kebab true, Mutton false ---
564
+ * @param obj 要转换的 json 对象
565
+ * @param space 美化方式
566
+ */
424
567
  function stringifyJson(obj, space) {
425
568
  return JSON.stringify(obj, (k, v) => {
426
569
  if (typeof v === 'bigint') {
@@ -429,27 +572,72 @@ function stringifyJson(obj, space) {
429
572
  return v;
430
573
  }, space).replace(/"-mybigint-([-+0-9]+?)"/g, '$1');
431
574
  }
575
+ /**
576
+ * --- 输出文本格式的 buffer ---
577
+ * @param buf 原始 buffer
578
+ */
579
+ function stringifyBuffer(buf) {
580
+ const arr = buf.toString('hex').match(/.{1,2}/g);
581
+ return `<Buffer ${arr ? arr.join(' ') : ''}>`;
582
+ }
583
+ /**
584
+ * --- 判断一个值是否是虚假的(为 null/undefined/空字符串/false/0) ---
585
+ * @param val 要判断的值
586
+ */
432
587
  function isFalsy(val) {
433
588
  return (val === null) || (val === undefined) || (val === '') || (val === false) || (val === 0);
434
589
  }
590
+ /**
591
+ * --- 类似 || 运算符的效果 ---
592
+ * @param v1 比对值
593
+ * @param v2 比对值
594
+ */
435
595
  function logicalOr(v1, v2) {
436
596
  return (isFalsy(v1) ? v2 : v1);
437
597
  }
598
+ /**
599
+ * --- 为解决精度问题,将字符串数字转换为整数显示 ---
600
+ * --- 以下几个示例都是当 digits 为 2 时 ---
601
+ * --- str 传入 '1.234',返回 123 ---
602
+ * --- str 传入 '1.235',返回 124 ---
603
+ * --- str 传入 '1.1',返回 110 ---
604
+ * --- str 传入 '6',返回 600 ---
605
+ * @param str 要转换的数字字符串
606
+ * @param digits 小数点右移位数
607
+ */
438
608
  function str2int(str, digits = 3) {
439
609
  const num = parseFloat(str);
610
+ /** --- 位数,如 1000 --- */
440
611
  const factor = Math.pow(10, digits);
441
612
  return Math.round(num * factor);
442
613
  }
614
+ /**
615
+ * --- 为解决精度问题,将整数转换为小数字符串 ---
616
+ * --- 以下几个示例都是当 digits 为 3、decimal 为 2 时 ---
617
+ * --- int 传入 2341,返回 '2.34' ---
618
+ * --- int 传入 2345,返回 '2.35' ---
619
+ * --- int 传入 23,返回 '0.02' ---
620
+ * --- int 传入 2,返回 '0.00' ---
621
+ * @param int 要转换的整数
622
+ * @param digits 小数点左移位数
623
+ * @param decimal 最终保留的小数位数
624
+ */
443
625
  function int2str(int, digits = 4, decimal = 2) {
626
+ /** --- 正负符号 --- */
444
627
  const sign = int < 0 ? '-' : '';
445
628
  const absInt = Math.abs(int);
446
629
  let intStr = absInt.toString();
630
+ // --- 补前导零至长度 digits + 1 ---
447
631
  while (intStr.length < digits + 1) {
448
632
  intStr = '0' + intStr;
449
633
  }
634
+ /** --- 整数部分字符串 --- */
450
635
  const intPart = intStr.slice(0, intStr.length - digits);
636
+ /** --- 小数部分字符串 --- */
451
637
  const decPart = intStr.slice(intStr.length - digits);
638
+ /** --- 小数部分数字 --- */
452
639
  const decNum = parseInt(decPart);
640
+ /** --- 要除的数 --- */
453
641
  const div = Math.pow(10, digits - decimal);
454
642
  const round = Math.round(decNum / div);
455
643
  const carry = Math.floor(round / Math.pow(10, decimal));
package/lib/time.d.ts CHANGED
@@ -1,22 +1,75 @@
1
+ /**
2
+ * Project: Kebab, User: JianSuoQiYue
3
+ * Date: 2019-6-6 12:04:15
4
+ * Last: 2020-3-29 23:41:21, 2024-1-18 17:16:50, 2024-8-5 10:55:21
5
+ */
1
6
  import * as sCtr from '../sys/ctr';
2
7
  export interface IOptions {
8
+ /** --- 时区 --- */
3
9
  'zone'?: number;
10
+ /** --- 字符串、时间戳(秒或毫秒) --- */
4
11
  'data'?: string | number;
5
12
  }
13
+ /** --- 一小时的秒数 --- */
6
14
  export declare const HOUR = 3600;
15
+ /** --- 一天的秒数 --- */
7
16
  export declare const DAY = 86400;
17
+ /** --- 一年(365 天) */
8
18
  export declare const YEAR = 31536000;
9
19
  export declare class Time {
20
+ /** --- 当前 date --- */
10
21
  private readonly _date;
22
+ /** --- 当前时区 --- */
11
23
  private _zone;
24
+ /**
25
+ * --- 构造函数 ---
26
+ * @param opt
27
+ */
12
28
  constructor(ctr: sCtr.Ctr, opt: IOptions);
29
+ /**
30
+ * --- 设置时区 ---
31
+ * @param zone 北京时间如 8
32
+ */
13
33
  setZone(zone: number): void;
34
+ /**
35
+ * --- 获取时区 ---
36
+ */
14
37
  getZone(): number;
38
+ /**
39
+ * --- 获取 UTC 字符串 ---
40
+ */
15
41
  toUTCString(): string;
42
+ /**
43
+ * --- 获取格式化的字符串 ---
44
+ * @param f 格式化字符串
45
+ * @param zone 时区小时,如 8
46
+ */
16
47
  format(f: string, zone?: number): string;
48
+ /**
49
+ * --- 获取秒级时间戳 ---
50
+ */
17
51
  stamp(): number;
18
52
  }
53
+ /**
54
+ * --- 创建获取一个时间对象 ---
55
+ * @param opt
56
+ */
19
57
  export declare function get(ctr: sCtr.Ctr, opt?: IOptions): Time;
58
+ /**
59
+ * --- 获取秒级时间戳 ---
60
+ * @param date Date 对象可选
61
+ * @param zone 时区小时或 ctr 对象,如 8,设置 null 则以系统时区为准
62
+ */
20
63
  export declare function stamp(date?: Date | string, zone?: number | sCtr.Ctr | null): number;
64
+ /**
65
+ * --- 是否是毫秒 ---
66
+ * @param time 要判断的时间戳
67
+ */
21
68
  export declare function isMs(time: number): boolean;
69
+ /**
70
+ * --- 将时间对象转换为时间字符串 ---
71
+ * @param zone 时区小时或 ctr 对象,如 8,设置 null 则以系统时区为准
72
+ * @param f 转换格式
73
+ * @param date 时间对象或秒/毫秒级数字,如果是秒请乘以 1000
74
+ */
22
75
  export declare function format(zone: number | sCtr.Ctr | null, f: string, date?: Date | number): string;