@anjianshi/utils 2.7.0 → 2.8.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/env-browser/device.d.ts +24 -0
- package/env-browser/device.js +50 -0
- package/env-browser/global.d.ts +10 -0
- package/env-browser/global.js +15 -0
- package/env-browser/load-script.d.ts +5 -0
- package/env-browser/load-script.js +13 -0
- package/env-browser/logging.d.ts +18 -0
- package/env-browser/logging.js +49 -0
- package/env-browser/manage-vconsole.d.ts +16 -0
- package/env-browser/manage-vconsole.js +38 -0
- package/env-node/crypto-random.d.ts +13 -0
- package/env-node/crypto-random.js +28 -0
- package/env-node/fs.d.ts +19 -0
- package/env-node/fs.js +48 -0
- package/env-node/index.d.ts +6 -0
- package/env-node/index.js +6 -0
- package/env-node/logging/handlers.d.ts +58 -0
- package/env-node/logging/handlers.js +154 -0
- package/env-node/logging/index.d.ts +11 -0
- package/env-node/logging/index.js +14 -0
- package/env-node/safe-request.d.ts +26 -0
- package/env-node/safe-request.js +40 -0
- package/env-react/emotion.d.ts +20 -0
- package/env-react/emotion.jsx +34 -0
- package/env-service/controllers.d.ts +30 -0
- package/env-service/controllers.js +41 -0
- package/env-service/env-reader.d.ts +55 -0
- package/env-service/env-reader.js +79 -0
- package/env-service/index.d.ts +6 -0
- package/env-service/index.js +6 -0
- package/env-service/prisma/adapt-logging.d.ts +21 -0
- package/env-service/prisma/adapt-logging.js +30 -0
- package/env-service/prisma/extensions/exist.d.ts +10 -0
- package/env-service/prisma/extensions/exist.js +16 -0
- package/env-service/prisma/extensions/find-and-count.d.ts +7 -0
- package/env-service/prisma/extensions/find-and-count.js +19 -0
- package/env-service/prisma/extensions/soft-delete.d.ts +52 -0
- package/env-service/prisma/extensions/soft-delete.js +123 -0
- package/env-service/prisma/extensions/with-transaction.d.ts +9 -0
- package/env-service/prisma/extensions/with-transaction.js +54 -0
- package/env-service/prisma/index.d.ts +6 -0
- package/env-service/prisma/index.js +6 -0
- package/env-service/prisma/transaction-contexted.d.ts +11 -0
- package/env-service/prisma/transaction-contexted.js +52 -0
- package/env-service/redis-cache.d.ts +39 -0
- package/env-service/redis-cache.js +116 -0
- package/env-service/tasks.d.ts +12 -0
- package/env-service/tasks.js +37 -0
- package/index.d.ts +3 -0
- package/index.js +3 -0
- package/init-dayjs.d.ts +2 -0
- package/init-dayjs.js +7 -0
- package/lang/async.d.ts +19 -0
- package/lang/async.js +34 -0
- package/lang/color.d.ts +37 -0
- package/lang/color.js +111 -0
- package/lang/index.d.ts +7 -0
- package/lang/index.js +7 -0
- package/lang/may-success.d.ts +40 -0
- package/lang/may-success.js +27 -0
- package/lang/object.d.ts +12 -0
- package/lang/object.js +41 -0
- package/lang/random.d.ts +13 -0
- package/lang/random.js +24 -0
- package/lang/string.d.ts +29 -0
- package/lang/string.js +92 -0
- package/lang/time.d.ts +10 -0
- package/lang/time.js +18 -0
- package/{src/lang/types.ts → lang/types.d.ts} +23 -43
- package/lang/types.js +28 -0
- package/logging/adapt.d.ts +10 -0
- package/logging/adapt.js +43 -0
- package/logging/formatters.d.ts +10 -0
- package/logging/formatters.js +22 -0
- package/logging/index.d.ts +45 -0
- package/logging/index.js +90 -0
- package/md5.d.ts +30 -0
- package/md5.js +308 -0
- package/package.json +14 -20
- package/url.d.ts +77 -0
- package/url.js +149 -0
- package/validators/array.d.ts +30 -0
- package/validators/array.js +47 -0
- package/validators/base.d.ts +82 -0
- package/validators/base.js +42 -0
- package/validators/boolean.d.ts +3 -0
- package/validators/boolean.js +22 -0
- package/validators/datetime.d.ts +12 -0
- package/validators/datetime.js +30 -0
- package/validators/factory.d.ts +70 -0
- package/validators/factory.js +121 -0
- package/validators/index.d.ts +9 -0
- package/validators/index.js +9 -0
- package/validators/number.d.ts +19 -0
- package/validators/number.js +26 -0
- package/validators/object.d.ts +28 -0
- package/validators/object.js +49 -0
- package/validators/one-of.d.ts +10 -0
- package/validators/one-of.js +15 -0
- package/validators/string.d.ts +22 -0
- package/validators/string.js +35 -0
- package/README.md +0 -10
- package/eslint.config.cjs +0 -33
- package/publish-prepare.cjs +0 -16
- package/src/env-browser/device.ts +0 -62
- package/src/env-browser/global.ts +0 -21
- package/src/env-browser/load-script.ts +0 -13
- package/src/env-browser/logging.ts +0 -58
- package/src/env-browser/manage-vconsole.ts +0 -54
- package/src/env-node/crypto-random.ts +0 -30
- package/src/env-node/fs.ts +0 -50
- package/src/env-node/index.ts +0 -6
- package/src/env-node/logging/handlers.ts +0 -190
- package/src/env-node/logging/index.ts +0 -16
- package/src/env-node/safe-request.ts +0 -66
- package/src/env-react/emotion.tsx +0 -42
- package/src/env-service/controllers.ts +0 -93
- package/src/env-service/env-reader.ts +0 -141
- package/src/env-service/index.ts +0 -6
- package/src/env-service/prisma/adapt-logging.ts +0 -39
- package/src/env-service/prisma/extensions/exist.ts +0 -21
- package/src/env-service/prisma/extensions/find-and-count.ts +0 -24
- package/src/env-service/prisma/extensions/soft-delete.ts +0 -162
- package/src/env-service/prisma/extensions/with-transaction.ts +0 -65
- package/src/env-service/prisma/index.ts +0 -6
- package/src/env-service/prisma/transaction-contexted.ts +0 -80
- package/src/env-service/redis-cache.ts +0 -142
- package/src/env-service/tasks.ts +0 -45
- package/src/index.ts +0 -3
- package/src/init-dayjs.ts +0 -8
- package/src/lang/async.ts +0 -47
- package/src/lang/color.ts +0 -119
- package/src/lang/index.ts +0 -7
- package/src/lang/may-success.ts +0 -57
- package/src/lang/object.ts +0 -39
- package/src/lang/random.ts +0 -25
- package/src/lang/string.ts +0 -95
- package/src/lang/time.ts +0 -19
- package/src/logging/adapt.ts +0 -49
- package/src/logging/formatters.ts +0 -23
- package/src/logging/index.ts +0 -106
- package/src/md5.ts +0 -318
- package/src/url.ts +0 -185
- package/src/validators/array.ts +0 -97
- package/src/validators/base.ts +0 -145
- package/src/validators/boolean.ts +0 -21
- package/src/validators/datetime.ts +0 -39
- package/src/validators/factory.ts +0 -244
- package/src/validators/index.ts +0 -9
- package/src/validators/number.ts +0 -54
- package/src/validators/object.ts +0 -101
- package/src/validators/one-of.ts +0 -33
- package/src/validators/string.ts +0 -72
package/md5.js
ADDED
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
/* eslint-disable no-multi-assign */
|
|
2
|
+
/**
|
|
3
|
+
* MD5 算法来自:https://github.com/emn178/js-md5
|
|
4
|
+
*/
|
|
5
|
+
export function md5(content) {
|
|
6
|
+
const md5 = new MD5();
|
|
7
|
+
md5.update(content);
|
|
8
|
+
return md5.hex();
|
|
9
|
+
}
|
|
10
|
+
// -------------------------------------------------------------------
|
|
11
|
+
/**
|
|
12
|
+
* 使用方法:
|
|
13
|
+
* const md5 = new MD5()
|
|
14
|
+
* md5.update(xxx) // 对于大文件,可以拆分开,多次调用 md5.update()
|
|
15
|
+
* const hash = md5.hex()
|
|
16
|
+
*/
|
|
17
|
+
export class MD5 {
|
|
18
|
+
buffer8;
|
|
19
|
+
blocks;
|
|
20
|
+
h0 = 0;
|
|
21
|
+
h1 = 0;
|
|
22
|
+
h2 = 0;
|
|
23
|
+
h3 = 0;
|
|
24
|
+
start = 0;
|
|
25
|
+
bytes = 0;
|
|
26
|
+
hBytes = 0;
|
|
27
|
+
lastByteIndex = 0;
|
|
28
|
+
finalized = false;
|
|
29
|
+
hashed = false;
|
|
30
|
+
first = true;
|
|
31
|
+
constructor() {
|
|
32
|
+
const buffer = new ArrayBuffer(68);
|
|
33
|
+
this.buffer8 = new Uint8Array(buffer);
|
|
34
|
+
this.blocks = new Uint32Array(buffer);
|
|
35
|
+
}
|
|
36
|
+
update(message) {
|
|
37
|
+
if (this.finalized)
|
|
38
|
+
return;
|
|
39
|
+
if (message instanceof ArrayBuffer) {
|
|
40
|
+
message = new Uint8Array(message);
|
|
41
|
+
}
|
|
42
|
+
if (typeof message !== 'string' && !Array.isArray(message) && !ArrayBuffer.isView(message)) {
|
|
43
|
+
throw new Error('input is invalid type');
|
|
44
|
+
}
|
|
45
|
+
const length = message.length;
|
|
46
|
+
const { blocks, buffer8 } = this;
|
|
47
|
+
let code;
|
|
48
|
+
let index = 0;
|
|
49
|
+
let i;
|
|
50
|
+
while (index < length) {
|
|
51
|
+
if (this.hashed) {
|
|
52
|
+
this.hashed = false;
|
|
53
|
+
blocks[0] = blocks[16];
|
|
54
|
+
// prettier-ignore
|
|
55
|
+
blocks[16] = blocks[1] = blocks[2] = blocks[3] = blocks[4] = blocks[5] =
|
|
56
|
+
blocks[6] = blocks[7] = blocks[8] = blocks[9] = blocks[10] =
|
|
57
|
+
blocks[11] = blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
|
|
58
|
+
}
|
|
59
|
+
if (typeof message !== 'string') {
|
|
60
|
+
for (i = this.start; index < length && i < 64; ++index) {
|
|
61
|
+
buffer8[i++] = message[index];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
for (i = this.start; index < length && i < 64; ++index) {
|
|
66
|
+
code = message.charCodeAt(index);
|
|
67
|
+
if (code < 0x80) {
|
|
68
|
+
buffer8[i++] = code;
|
|
69
|
+
}
|
|
70
|
+
else if (code < 0x800) {
|
|
71
|
+
buffer8[i++] = 0xc0 | (code >> 6);
|
|
72
|
+
buffer8[i++] = 0x80 | (code & 0x3f);
|
|
73
|
+
}
|
|
74
|
+
else if (code < 0xd800 || code >= 0xe000) {
|
|
75
|
+
buffer8[i++] = 0xe0 | (code >> 12);
|
|
76
|
+
buffer8[i++] = 0x80 | ((code >> 6) & 0x3f);
|
|
77
|
+
buffer8[i++] = 0x80 | (code & 0x3f);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
|
|
81
|
+
buffer8[i++] = 0xf0 | (code >> 18);
|
|
82
|
+
buffer8[i++] = 0x80 | ((code >> 12) & 0x3f);
|
|
83
|
+
buffer8[i++] = 0x80 | ((code >> 6) & 0x3f);
|
|
84
|
+
buffer8[i++] = 0x80 | (code & 0x3f);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
this.lastByteIndex = i;
|
|
89
|
+
this.bytes += i - this.start;
|
|
90
|
+
if (i >= 64) {
|
|
91
|
+
this.start = i - 64;
|
|
92
|
+
this.hash();
|
|
93
|
+
this.hashed = true;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
this.start = i;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (this.bytes > 4294967295) {
|
|
100
|
+
this.hBytes += (this.bytes / 4294967296) << 0;
|
|
101
|
+
this.bytes = this.bytes % 4294967296;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
finalize() {
|
|
105
|
+
if (this.finalized)
|
|
106
|
+
return;
|
|
107
|
+
this.finalized = true;
|
|
108
|
+
const { blocks } = this;
|
|
109
|
+
const i = this.lastByteIndex;
|
|
110
|
+
const EXTRA = [128, 32768, 8388608, -2147483648];
|
|
111
|
+
blocks[i >> 2] |= EXTRA[i & 3];
|
|
112
|
+
if (i >= 56) {
|
|
113
|
+
if (!this.hashed)
|
|
114
|
+
this.hash();
|
|
115
|
+
blocks[0] = blocks[16];
|
|
116
|
+
// prettier-ignore
|
|
117
|
+
blocks[16] = blocks[1] = blocks[2] = blocks[3] = blocks[4] = blocks[5] =
|
|
118
|
+
blocks[6] = blocks[7] = blocks[8] = blocks[9] = blocks[10] =
|
|
119
|
+
blocks[11] = blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
|
|
120
|
+
}
|
|
121
|
+
blocks[14] = this.bytes << 3;
|
|
122
|
+
blocks[15] = (this.hBytes << 3) | (this.bytes >>> 29);
|
|
123
|
+
this.hash();
|
|
124
|
+
}
|
|
125
|
+
hash() {
|
|
126
|
+
let a, b, c, d, bc, da;
|
|
127
|
+
const { blocks } = this;
|
|
128
|
+
if (this.first) {
|
|
129
|
+
a = blocks[0] - 680876937;
|
|
130
|
+
a = (((a << 7) | (a >>> 25)) - 271733879) << 0;
|
|
131
|
+
d = (-1732584194 ^ (a & 2004318071)) + blocks[1] - 117830708;
|
|
132
|
+
d = (((d << 12) | (d >>> 20)) + a) << 0;
|
|
133
|
+
c = (-271733879 ^ (d & (a ^ -271733879))) + blocks[2] - 1126478375;
|
|
134
|
+
c = (((c << 17) | (c >>> 15)) + d) << 0;
|
|
135
|
+
b = (a ^ (c & (d ^ a))) + blocks[3] - 1316259209;
|
|
136
|
+
b = (((b << 22) | (b >>> 10)) + c) << 0;
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
a = this.h0;
|
|
140
|
+
b = this.h1;
|
|
141
|
+
c = this.h2;
|
|
142
|
+
d = this.h3;
|
|
143
|
+
a += (d ^ (b & (c ^ d))) + blocks[0] - 680876936;
|
|
144
|
+
a = (((a << 7) | (a >>> 25)) + b) << 0;
|
|
145
|
+
d += (c ^ (a & (b ^ c))) + blocks[1] - 389564586;
|
|
146
|
+
d = (((d << 12) | (d >>> 20)) + a) << 0;
|
|
147
|
+
c += (b ^ (d & (a ^ b))) + blocks[2] + 606105819;
|
|
148
|
+
c = (((c << 17) | (c >>> 15)) + d) << 0;
|
|
149
|
+
b += (a ^ (c & (d ^ a))) + blocks[3] - 1044525330;
|
|
150
|
+
b = (((b << 22) | (b >>> 10)) + c) << 0;
|
|
151
|
+
}
|
|
152
|
+
a += (d ^ (b & (c ^ d))) + blocks[4] - 176418897;
|
|
153
|
+
a = (((a << 7) | (a >>> 25)) + b) << 0;
|
|
154
|
+
d += (c ^ (a & (b ^ c))) + blocks[5] + 1200080426;
|
|
155
|
+
d = (((d << 12) | (d >>> 20)) + a) << 0;
|
|
156
|
+
c += (b ^ (d & (a ^ b))) + blocks[6] - 1473231341;
|
|
157
|
+
c = (((c << 17) | (c >>> 15)) + d) << 0;
|
|
158
|
+
b += (a ^ (c & (d ^ a))) + blocks[7] - 45705983;
|
|
159
|
+
b = (((b << 22) | (b >>> 10)) + c) << 0;
|
|
160
|
+
a += (d ^ (b & (c ^ d))) + blocks[8] + 1770035416;
|
|
161
|
+
a = (((a << 7) | (a >>> 25)) + b) << 0;
|
|
162
|
+
d += (c ^ (a & (b ^ c))) + blocks[9] - 1958414417;
|
|
163
|
+
d = (((d << 12) | (d >>> 20)) + a) << 0;
|
|
164
|
+
c += (b ^ (d & (a ^ b))) + blocks[10] - 42063;
|
|
165
|
+
c = (((c << 17) | (c >>> 15)) + d) << 0;
|
|
166
|
+
b += (a ^ (c & (d ^ a))) + blocks[11] - 1990404162;
|
|
167
|
+
b = (((b << 22) | (b >>> 10)) + c) << 0;
|
|
168
|
+
a += (d ^ (b & (c ^ d))) + blocks[12] + 1804603682;
|
|
169
|
+
a = (((a << 7) | (a >>> 25)) + b) << 0;
|
|
170
|
+
d += (c ^ (a & (b ^ c))) + blocks[13] - 40341101;
|
|
171
|
+
d = (((d << 12) | (d >>> 20)) + a) << 0;
|
|
172
|
+
c += (b ^ (d & (a ^ b))) + blocks[14] - 1502002290;
|
|
173
|
+
c = (((c << 17) | (c >>> 15)) + d) << 0;
|
|
174
|
+
b += (a ^ (c & (d ^ a))) + blocks[15] + 1236535329;
|
|
175
|
+
b = (((b << 22) | (b >>> 10)) + c) << 0;
|
|
176
|
+
a += (c ^ (d & (b ^ c))) + blocks[1] - 165796510;
|
|
177
|
+
a = (((a << 5) | (a >>> 27)) + b) << 0;
|
|
178
|
+
d += (b ^ (c & (a ^ b))) + blocks[6] - 1069501632;
|
|
179
|
+
d = (((d << 9) | (d >>> 23)) + a) << 0;
|
|
180
|
+
c += (a ^ (b & (d ^ a))) + blocks[11] + 643717713;
|
|
181
|
+
c = (((c << 14) | (c >>> 18)) + d) << 0;
|
|
182
|
+
b += (d ^ (a & (c ^ d))) + blocks[0] - 373897302;
|
|
183
|
+
b = (((b << 20) | (b >>> 12)) + c) << 0;
|
|
184
|
+
a += (c ^ (d & (b ^ c))) + blocks[5] - 701558691;
|
|
185
|
+
a = (((a << 5) | (a >>> 27)) + b) << 0;
|
|
186
|
+
d += (b ^ (c & (a ^ b))) + blocks[10] + 38016083;
|
|
187
|
+
d = (((d << 9) | (d >>> 23)) + a) << 0;
|
|
188
|
+
c += (a ^ (b & (d ^ a))) + blocks[15] - 660478335;
|
|
189
|
+
c = (((c << 14) | (c >>> 18)) + d) << 0;
|
|
190
|
+
b += (d ^ (a & (c ^ d))) + blocks[4] - 405537848;
|
|
191
|
+
b = (((b << 20) | (b >>> 12)) + c) << 0;
|
|
192
|
+
a += (c ^ (d & (b ^ c))) + blocks[9] + 568446438;
|
|
193
|
+
a = (((a << 5) | (a >>> 27)) + b) << 0;
|
|
194
|
+
d += (b ^ (c & (a ^ b))) + blocks[14] - 1019803690;
|
|
195
|
+
d = (((d << 9) | (d >>> 23)) + a) << 0;
|
|
196
|
+
c += (a ^ (b & (d ^ a))) + blocks[3] - 187363961;
|
|
197
|
+
c = (((c << 14) | (c >>> 18)) + d) << 0;
|
|
198
|
+
b += (d ^ (a & (c ^ d))) + blocks[8] + 1163531501;
|
|
199
|
+
b = (((b << 20) | (b >>> 12)) + c) << 0;
|
|
200
|
+
a += (c ^ (d & (b ^ c))) + blocks[13] - 1444681467;
|
|
201
|
+
a = (((a << 5) | (a >>> 27)) + b) << 0;
|
|
202
|
+
d += (b ^ (c & (a ^ b))) + blocks[2] - 51403784;
|
|
203
|
+
d = (((d << 9) | (d >>> 23)) + a) << 0;
|
|
204
|
+
c += (a ^ (b & (d ^ a))) + blocks[7] + 1735328473;
|
|
205
|
+
c = (((c << 14) | (c >>> 18)) + d) << 0;
|
|
206
|
+
b += (d ^ (a & (c ^ d))) + blocks[12] - 1926607734;
|
|
207
|
+
b = (((b << 20) | (b >>> 12)) + c) << 0;
|
|
208
|
+
bc = b ^ c;
|
|
209
|
+
a += (bc ^ d) + blocks[5] - 378558;
|
|
210
|
+
a = (((a << 4) | (a >>> 28)) + b) << 0;
|
|
211
|
+
d += (bc ^ a) + blocks[8] - 2022574463;
|
|
212
|
+
d = (((d << 11) | (d >>> 21)) + a) << 0;
|
|
213
|
+
da = d ^ a;
|
|
214
|
+
c += (da ^ b) + blocks[11] + 1839030562;
|
|
215
|
+
c = (((c << 16) | (c >>> 16)) + d) << 0;
|
|
216
|
+
b += (da ^ c) + blocks[14] - 35309556;
|
|
217
|
+
b = (((b << 23) | (b >>> 9)) + c) << 0;
|
|
218
|
+
bc = b ^ c;
|
|
219
|
+
a += (bc ^ d) + blocks[1] - 1530992060;
|
|
220
|
+
a = (((a << 4) | (a >>> 28)) + b) << 0;
|
|
221
|
+
d += (bc ^ a) + blocks[4] + 1272893353;
|
|
222
|
+
d = (((d << 11) | (d >>> 21)) + a) << 0;
|
|
223
|
+
da = d ^ a;
|
|
224
|
+
c += (da ^ b) + blocks[7] - 155497632;
|
|
225
|
+
c = (((c << 16) | (c >>> 16)) + d) << 0;
|
|
226
|
+
b += (da ^ c) + blocks[10] - 1094730640;
|
|
227
|
+
b = (((b << 23) | (b >>> 9)) + c) << 0;
|
|
228
|
+
bc = b ^ c;
|
|
229
|
+
a += (bc ^ d) + blocks[13] + 681279174;
|
|
230
|
+
a = (((a << 4) | (a >>> 28)) + b) << 0;
|
|
231
|
+
d += (bc ^ a) + blocks[0] - 358537222;
|
|
232
|
+
d = (((d << 11) | (d >>> 21)) + a) << 0;
|
|
233
|
+
da = d ^ a;
|
|
234
|
+
c += (da ^ b) + blocks[3] - 722521979;
|
|
235
|
+
c = (((c << 16) | (c >>> 16)) + d) << 0;
|
|
236
|
+
b += (da ^ c) + blocks[6] + 76029189;
|
|
237
|
+
b = (((b << 23) | (b >>> 9)) + c) << 0;
|
|
238
|
+
bc = b ^ c;
|
|
239
|
+
a += (bc ^ d) + blocks[9] - 640364487;
|
|
240
|
+
a = (((a << 4) | (a >>> 28)) + b) << 0;
|
|
241
|
+
d += (bc ^ a) + blocks[12] - 421815835;
|
|
242
|
+
d = (((d << 11) | (d >>> 21)) + a) << 0;
|
|
243
|
+
da = d ^ a;
|
|
244
|
+
c += (da ^ b) + blocks[15] + 530742520;
|
|
245
|
+
c = (((c << 16) | (c >>> 16)) + d) << 0;
|
|
246
|
+
b += (da ^ c) + blocks[2] - 995338651;
|
|
247
|
+
b = (((b << 23) | (b >>> 9)) + c) << 0;
|
|
248
|
+
a += (c ^ (b | ~d)) + blocks[0] - 198630844;
|
|
249
|
+
a = (((a << 6) | (a >>> 26)) + b) << 0;
|
|
250
|
+
d += (b ^ (a | ~c)) + blocks[7] + 1126891415;
|
|
251
|
+
d = (((d << 10) | (d >>> 22)) + a) << 0;
|
|
252
|
+
c += (a ^ (d | ~b)) + blocks[14] - 1416354905;
|
|
253
|
+
c = (((c << 15) | (c >>> 17)) + d) << 0;
|
|
254
|
+
b += (d ^ (c | ~a)) + blocks[5] - 57434055;
|
|
255
|
+
b = (((b << 21) | (b >>> 11)) + c) << 0;
|
|
256
|
+
a += (c ^ (b | ~d)) + blocks[12] + 1700485571;
|
|
257
|
+
a = (((a << 6) | (a >>> 26)) + b) << 0;
|
|
258
|
+
d += (b ^ (a | ~c)) + blocks[3] - 1894986606;
|
|
259
|
+
d = (((d << 10) | (d >>> 22)) + a) << 0;
|
|
260
|
+
c += (a ^ (d | ~b)) + blocks[10] - 1051523;
|
|
261
|
+
c = (((c << 15) | (c >>> 17)) + d) << 0;
|
|
262
|
+
b += (d ^ (c | ~a)) + blocks[1] - 2054922799;
|
|
263
|
+
b = (((b << 21) | (b >>> 11)) + c) << 0;
|
|
264
|
+
a += (c ^ (b | ~d)) + blocks[8] + 1873313359;
|
|
265
|
+
a = (((a << 6) | (a >>> 26)) + b) << 0;
|
|
266
|
+
d += (b ^ (a | ~c)) + blocks[15] - 30611744;
|
|
267
|
+
d = (((d << 10) | (d >>> 22)) + a) << 0;
|
|
268
|
+
c += (a ^ (d | ~b)) + blocks[6] - 1560198380;
|
|
269
|
+
c = (((c << 15) | (c >>> 17)) + d) << 0;
|
|
270
|
+
b += (d ^ (c | ~a)) + blocks[13] + 1309151649;
|
|
271
|
+
b = (((b << 21) | (b >>> 11)) + c) << 0;
|
|
272
|
+
a += (c ^ (b | ~d)) + blocks[4] - 145523070;
|
|
273
|
+
a = (((a << 6) | (a >>> 26)) + b) << 0;
|
|
274
|
+
d += (b ^ (a | ~c)) + blocks[11] - 1120210379;
|
|
275
|
+
d = (((d << 10) | (d >>> 22)) + a) << 0;
|
|
276
|
+
c += (a ^ (d | ~b)) + blocks[2] + 718787259;
|
|
277
|
+
c = (((c << 15) | (c >>> 17)) + d) << 0;
|
|
278
|
+
b += (d ^ (c | ~a)) + blocks[9] - 343485551;
|
|
279
|
+
b = (((b << 21) | (b >>> 11)) + c) << 0;
|
|
280
|
+
if (this.first) {
|
|
281
|
+
this.h0 = (a + 1732584193) << 0;
|
|
282
|
+
this.h1 = (b - 271733879) << 0;
|
|
283
|
+
this.h2 = (c - 1732584194) << 0;
|
|
284
|
+
this.h3 = (d + 271733878) << 0;
|
|
285
|
+
this.first = false;
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
this.h0 = (this.h0 + a) << 0;
|
|
289
|
+
this.h1 = (this.h1 + b) << 0;
|
|
290
|
+
this.h2 = (this.h2 + c) << 0;
|
|
291
|
+
this.h3 = (this.h3 + d) << 0;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
hex() {
|
|
295
|
+
this.finalize();
|
|
296
|
+
const { h0, h1, h2, h3 } = this;
|
|
297
|
+
const HEX_CHARS = '0123456789abcdef'.split('');
|
|
298
|
+
return (
|
|
299
|
+
// prettier-ignore
|
|
300
|
+
HEX_CHARS[(h0 >> 4) & 0x0f] + HEX_CHARS[h0 & 0x0f] + HEX_CHARS[(h0 >> 12) & 0x0f] + HEX_CHARS[(h0 >> 8) & 0x0f] + HEX_CHARS[(h0 >> 20) & 0x0f] +
|
|
301
|
+
HEX_CHARS[(h0 >> 16) & 0x0f] + HEX_CHARS[(h0 >> 28) & 0x0f] + HEX_CHARS[(h0 >> 24) & 0x0f] + HEX_CHARS[(h1 >> 4) & 0x0f] + HEX_CHARS[h1 & 0x0f] +
|
|
302
|
+
HEX_CHARS[(h1 >> 12) & 0x0f] + HEX_CHARS[(h1 >> 8) & 0x0f] + HEX_CHARS[(h1 >> 20) & 0x0f] + HEX_CHARS[(h1 >> 16) & 0x0f] + HEX_CHARS[(h1 >> 28) & 0x0f] +
|
|
303
|
+
HEX_CHARS[(h1 >> 24) & 0x0f] + HEX_CHARS[(h2 >> 4) & 0x0f] + HEX_CHARS[h2 & 0x0f] + HEX_CHARS[(h2 >> 12) & 0x0f] + HEX_CHARS[(h2 >> 8) & 0x0f] +
|
|
304
|
+
HEX_CHARS[(h2 >> 20) & 0x0f] + HEX_CHARS[(h2 >> 16) & 0x0f] + HEX_CHARS[(h2 >> 28) & 0x0f] + HEX_CHARS[(h2 >> 24) & 0x0f] + HEX_CHARS[(h3 >> 4) & 0x0f] +
|
|
305
|
+
HEX_CHARS[h3 & 0x0f] + HEX_CHARS[(h3 >> 12) & 0x0f] + HEX_CHARS[(h3 >> 8) & 0x0f] + HEX_CHARS[(h3 >> 20) & 0x0f] + HEX_CHARS[(h3 >> 16) & 0x0f] +
|
|
306
|
+
HEX_CHARS[(h3 >> 28) & 0x0f] + HEX_CHARS[(h3 >> 24) & 0x0f]);
|
|
307
|
+
}
|
|
308
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anjianshi/utils",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"description": "Common JavaScript Utils",
|
|
5
5
|
"homepage": "https://github.com/anjianshi/js-packages/utils",
|
|
6
6
|
"bugs": {
|
|
@@ -9,32 +9,20 @@
|
|
|
9
9
|
},
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"author": "anjianshi <anjianshi@gmail.com>",
|
|
12
|
-
"repository":
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/anjianshi/js-packages.git"
|
|
15
|
+
},
|
|
13
16
|
"publishConfig": {
|
|
14
17
|
"registry": "https://registry.npmjs.org/",
|
|
15
|
-
"access": "public"
|
|
16
|
-
"directory": "dist"
|
|
18
|
+
"access": "public"
|
|
17
19
|
},
|
|
18
20
|
"type": "module",
|
|
19
|
-
"scripts": {
|
|
20
|
-
"watch": "npm run clear && tsc --watch",
|
|
21
|
-
"build": "npm run clear && tsc",
|
|
22
|
-
"clear": "rm -rf dist",
|
|
23
|
-
"prepublishOnly": "npm run build && node publish-prepare.cjs",
|
|
24
|
-
"postpublish": "rm dist/package.json",
|
|
25
|
-
"lint": "tsc --noEmit && node ../node_modules/eslint/bin/eslint.js './src/'"
|
|
26
|
-
},
|
|
27
21
|
"main": "index.js",
|
|
28
22
|
"dependencies": {
|
|
29
23
|
"lodash": "^4.17.21"
|
|
30
24
|
},
|
|
31
25
|
"devDependencies": {
|
|
32
|
-
"@anjianshi/presets-eslint-base": "workspace:*",
|
|
33
|
-
"@anjianshi/presets-eslint-node": "workspace:*",
|
|
34
|
-
"@anjianshi/presets-eslint-react": "workspace:*",
|
|
35
|
-
"@anjianshi/presets-eslint-typescript": "workspace:*",
|
|
36
|
-
"@anjianshi/presets-prettier": "workspace:*",
|
|
37
|
-
"@anjianshi/presets-typescript": "workspace:*",
|
|
38
26
|
"@types/lodash": "^4.17.20",
|
|
39
27
|
"@types/node": "^22.16.0",
|
|
40
28
|
"@types/react": "^19.1.8",
|
|
@@ -42,7 +30,13 @@
|
|
|
42
30
|
"eslint": "^9.30.1",
|
|
43
31
|
"redis": "^5.5.6",
|
|
44
32
|
"typescript": "^5.8.3",
|
|
45
|
-
"vconsole": "^3.15.1"
|
|
33
|
+
"vconsole": "^3.15.1",
|
|
34
|
+
"@anjianshi/presets-eslint-base": "6.0.0",
|
|
35
|
+
"@anjianshi/presets-eslint-node": "6.0.0",
|
|
36
|
+
"@anjianshi/presets-eslint-typescript": "6.0.0",
|
|
37
|
+
"@anjianshi/presets-eslint-react": "6.0.0",
|
|
38
|
+
"@anjianshi/presets-typescript": "3.2.4",
|
|
39
|
+
"@anjianshi/presets-prettier": "3.0.4"
|
|
46
40
|
},
|
|
47
41
|
"peerDependencies": {
|
|
48
42
|
"@emotion/react": "^11.14.0",
|
|
@@ -81,4 +75,4 @@
|
|
|
81
75
|
}
|
|
82
76
|
},
|
|
83
77
|
"prettier": "@anjianshi/presets-prettier/prettierrc"
|
|
84
|
-
}
|
|
78
|
+
}
|
package/url.d.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 从 URL 中解析出 query 对象
|
|
3
|
+
* 注意:不带 ? 号的纯 query 内容需手动加上 ? 再传入。
|
|
4
|
+
*
|
|
5
|
+
* [array]
|
|
6
|
+
* 是否把重复出现的 key 保存为数组(默认不开启)
|
|
7
|
+
* a=1&a=2 => { a: [1,2] }
|
|
8
|
+
*
|
|
9
|
+
* [loose]
|
|
10
|
+
* 是否开启“宽松模式”(默认不开启)
|
|
11
|
+
* 1. hash 里的内容也会被解析,以兼容拼接错误的 URL(把 query 拼到了 hash 后面)。
|
|
12
|
+
* 2. 出现多个 ? 符号时,会把 ? 也当做 & 分隔符(index.html?a=1&b=2?c=3)
|
|
13
|
+
*
|
|
14
|
+
* [decode]
|
|
15
|
+
* 是否对 query 值进行 decode(默认开启)
|
|
16
|
+
*/
|
|
17
|
+
declare function parseQuery(url: string, options?: {
|
|
18
|
+
array?: false;
|
|
19
|
+
loose?: boolean;
|
|
20
|
+
decode?: boolean;
|
|
21
|
+
}): Record<string, string>;
|
|
22
|
+
declare function parseQuery(url: string, options: {
|
|
23
|
+
array: true;
|
|
24
|
+
loose?: boolean;
|
|
25
|
+
decode?: boolean;
|
|
26
|
+
}): Record<string, string | string[]>;
|
|
27
|
+
export { parseQuery };
|
|
28
|
+
/**
|
|
29
|
+
* 把对象合并成 query string。
|
|
30
|
+
* - 支持字符串、数值、布尔值、数组。
|
|
31
|
+
* - 布尔值会替换成 0 和 1。
|
|
32
|
+
* - 数组会多次赋值:{ a: [1,2,3] } => 'a=1&a=2&a=3',不支持嵌套数组
|
|
33
|
+
* - encode 为 true 时会对 value 执行 encodeURIComponent(默认为 true)
|
|
34
|
+
*/
|
|
35
|
+
export type StringifyVal = string | number | boolean;
|
|
36
|
+
export type StringifyQuery = Record<string, StringifyVal | StringifyVal[] | undefined>;
|
|
37
|
+
export declare function stringifyQuery(obj: StringifyQuery, encode?: boolean): string;
|
|
38
|
+
/**
|
|
39
|
+
* 拆分 URL 的各个部分
|
|
40
|
+
*
|
|
41
|
+
* bare 为 true,则 search 不带 '?',hash 不带 '#'
|
|
42
|
+
* 否则和 location.search / hash 一样
|
|
43
|
+
* (默认为 true)
|
|
44
|
+
*/
|
|
45
|
+
export declare function splitUrl(url: string, bare?: boolean): {
|
|
46
|
+
base: string;
|
|
47
|
+
search: string;
|
|
48
|
+
hash: string;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* 把 query 和 hash 内容合并到 url 上
|
|
52
|
+
*
|
|
53
|
+
* query object 与现有 search 合并,替换同名项(值为数组的,用新数组代替老的,不会合并数组)
|
|
54
|
+
* hash string 带不带开头的 '#' 皆可。会代替 url 已有的 hash。
|
|
55
|
+
*/
|
|
56
|
+
export declare function combineUrl(origUrl: string, query?: StringifyQuery, hash?: string): string;
|
|
57
|
+
/**
|
|
58
|
+
* 移除路径中所有非必须的 "/"
|
|
59
|
+
* 清理后的字符串只有这几种可能的格式:''、'abc'、'abc/def'
|
|
60
|
+
* 例如 /abc/def 和 abc/def/ 都会变成 abc/def
|
|
61
|
+
*
|
|
62
|
+
* 注意:此操作不会统一大小写,因此不保证处理后两个字符串在代码层面全等(a === b)
|
|
63
|
+
*/
|
|
64
|
+
export declare function clearSlash(path: string): string;
|
|
65
|
+
/**
|
|
66
|
+
* 合并几段路径,保证合并处只有一个斜杠
|
|
67
|
+
*/
|
|
68
|
+
export declare function joinPath(...nodes: string[]): string;
|
|
69
|
+
/**
|
|
70
|
+
* decodeURIComponent() 对于不规范编码的字符串可能会报错(例如字符串里出现了“%”)
|
|
71
|
+
* 用此函数代替可避免此问题
|
|
72
|
+
*/
|
|
73
|
+
export declare function safeDecode(content: string): string;
|
|
74
|
+
/**
|
|
75
|
+
* 将 URL 中的 http:// 协议改成 https://
|
|
76
|
+
*/
|
|
77
|
+
export declare function ensureHttps(url: string | undefined): string | undefined;
|
package/url.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL 工具函数
|
|
3
|
+
* 部分灵感来自:https://www.npmjs.com/package/qs
|
|
4
|
+
*
|
|
5
|
+
* [名词定义]
|
|
6
|
+
* query: 指 a=1&b=2 格式的“查询字符串”或此类字符串的解析结果。
|
|
7
|
+
* search: URL 中的 search 部分,与 location.search 一致,空字符串或以 '?' 开头。
|
|
8
|
+
* hash: URL 中的 hash 部分,与 location.hash 一直,空字符串或以 '#' 开头。
|
|
9
|
+
*/
|
|
10
|
+
import isPlainObject from 'lodash/isPlainObject.js';
|
|
11
|
+
function parseQuery(url, options) {
|
|
12
|
+
const { array = false, loose = false, decode = true } = options ?? {};
|
|
13
|
+
// 正常状态下,将仅剩 a=1&b=1(即不会再有 ? 和 #);loose 模式下,可能为 a=1&b=2#c=3?d=4
|
|
14
|
+
const queryString = (loose ? /(\?|#)(.+)/ : /(\?)(.+?)(#|$)/).exec(url)?.[2] ?? '';
|
|
15
|
+
if (!queryString)
|
|
16
|
+
return {};
|
|
17
|
+
const query = {};
|
|
18
|
+
const reg = /([^#?&]*)=([^#?&]*)/g;
|
|
19
|
+
let re = reg.exec(queryString);
|
|
20
|
+
while (re) {
|
|
21
|
+
const [name, rawValue] = [re[1], re[2]];
|
|
22
|
+
const value = decode ? safeDecode(rawValue) : rawValue;
|
|
23
|
+
if (array && query[name] !== undefined) {
|
|
24
|
+
const prev = query[name];
|
|
25
|
+
query[name] = Array.isArray(prev) ? [...prev, value] : [prev, value];
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
query[name] = value;
|
|
29
|
+
}
|
|
30
|
+
re = reg.exec(queryString);
|
|
31
|
+
}
|
|
32
|
+
return query;
|
|
33
|
+
}
|
|
34
|
+
export { parseQuery };
|
|
35
|
+
export function stringifyQuery(obj, encode = true) {
|
|
36
|
+
if (!isPlainObject(obj))
|
|
37
|
+
return '';
|
|
38
|
+
return (Object.entries(obj)
|
|
39
|
+
// 过滤值为 undefined 的项目,使其完全不出现在最终的 query 中
|
|
40
|
+
.filter((entry) => entry[1] !== undefined)
|
|
41
|
+
.map(([name, value]) => stringifyQueryItem(name, value, encode))
|
|
42
|
+
.join('&'));
|
|
43
|
+
}
|
|
44
|
+
function stringifyQueryItem(name, value, encode) {
|
|
45
|
+
if (Array.isArray(value))
|
|
46
|
+
return value.map(subValue => stringifyQueryItem(name, subValue, encode)).join('&');
|
|
47
|
+
if (typeof value === 'boolean')
|
|
48
|
+
value = value ? '1' : '0';
|
|
49
|
+
if (typeof value === 'number')
|
|
50
|
+
value = value.toString();
|
|
51
|
+
if (encode)
|
|
52
|
+
value = encodeURIComponent(value);
|
|
53
|
+
return `${name}=${value}`;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 拆分 URL 的各个部分
|
|
57
|
+
*
|
|
58
|
+
* bare 为 true,则 search 不带 '?',hash 不带 '#'
|
|
59
|
+
* 否则和 location.search / hash 一样
|
|
60
|
+
* (默认为 true)
|
|
61
|
+
*/
|
|
62
|
+
export function splitUrl(url, bare = true) {
|
|
63
|
+
let hashIndex = url.indexOf('#');
|
|
64
|
+
if (hashIndex === -1)
|
|
65
|
+
hashIndex = url.length;
|
|
66
|
+
const bareHash = url.slice(hashIndex + 1);
|
|
67
|
+
let searchIndex = url.slice(0, hashIndex).indexOf('?');
|
|
68
|
+
if (searchIndex === -1)
|
|
69
|
+
searchIndex = hashIndex;
|
|
70
|
+
const bareSearch = url.slice(searchIndex + 1, hashIndex);
|
|
71
|
+
return {
|
|
72
|
+
base: url.slice(0, searchIndex),
|
|
73
|
+
search: bare ? bareSearch : bareSearch ? '?' + bareSearch : '',
|
|
74
|
+
hash: bare ? bareHash : bareHash ? '#' + bareHash : '',
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* 把 query 和 hash 内容合并到 url 上
|
|
79
|
+
*
|
|
80
|
+
* query object 与现有 search 合并,替换同名项(值为数组的,用新数组代替老的,不会合并数组)
|
|
81
|
+
* hash string 带不带开头的 '#' 皆可。会代替 url 已有的 hash。
|
|
82
|
+
*/
|
|
83
|
+
export function combineUrl(origUrl, query = {}, hash = '') {
|
|
84
|
+
if (hash.startsWith('#'))
|
|
85
|
+
hash = hash.slice(1);
|
|
86
|
+
// 拆分原 url 的 search、hash
|
|
87
|
+
const { base, search: origSearch, hash: origHash } = splitUrl(origUrl);
|
|
88
|
+
// 拼接新 URL
|
|
89
|
+
let newUrl = base;
|
|
90
|
+
const newSearch = stringifyQuery({ ...parseQuery(origSearch), ...query });
|
|
91
|
+
const newHash = hash || origHash;
|
|
92
|
+
if (newSearch)
|
|
93
|
+
newUrl += `?${newSearch}`;
|
|
94
|
+
if (newHash)
|
|
95
|
+
newUrl += `#${newHash}`;
|
|
96
|
+
return newUrl;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* 移除路径中所有非必须的 "/"
|
|
100
|
+
* 清理后的字符串只有这几种可能的格式:''、'abc'、'abc/def'
|
|
101
|
+
* 例如 /abc/def 和 abc/def/ 都会变成 abc/def
|
|
102
|
+
*
|
|
103
|
+
* 注意:此操作不会统一大小写,因此不保证处理后两个字符串在代码层面全等(a === b)
|
|
104
|
+
*/
|
|
105
|
+
export function clearSlash(path) {
|
|
106
|
+
if (path.startsWith('/'))
|
|
107
|
+
path = path.slice(1);
|
|
108
|
+
if (path.endsWith('/'))
|
|
109
|
+
path = path.slice(0, -1);
|
|
110
|
+
path = path.replace(/\/+/g, '/');
|
|
111
|
+
return path;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* 合并几段路径,保证合并处只有一个斜杠
|
|
115
|
+
*/
|
|
116
|
+
export function joinPath(...nodes) {
|
|
117
|
+
// - node 为 '' 时忽略 node
|
|
118
|
+
// - path 可能的格式:'' 'a' 'a/' ‘/a/'
|
|
119
|
+
// - path 为 '',则 node 开头 '/' 保持原样
|
|
120
|
+
// - 否则,根据 path 结尾有没有 '/',决定 node 开头带不带 '/'
|
|
121
|
+
// - node 开头、结尾若有多个 '/' 均替换成单个
|
|
122
|
+
return nodes.reduce((path, node) => {
|
|
123
|
+
if (!node)
|
|
124
|
+
return path;
|
|
125
|
+
const [, origPrefix, content, origSuffix] = /^(\/*)(.*?)(\/*)$/.exec(node);
|
|
126
|
+
const prefix = (path === '' ? !!origPrefix : !path.endsWith('/')) ? '/' : '';
|
|
127
|
+
const suffix = origSuffix ? '/' : '';
|
|
128
|
+
const result = `${path}${prefix}${content}${suffix}`;
|
|
129
|
+
return result;
|
|
130
|
+
}, '');
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* decodeURIComponent() 对于不规范编码的字符串可能会报错(例如字符串里出现了“%”)
|
|
134
|
+
* 用此函数代替可避免此问题
|
|
135
|
+
*/
|
|
136
|
+
export function safeDecode(content) {
|
|
137
|
+
try {
|
|
138
|
+
return decodeURIComponent(content);
|
|
139
|
+
}
|
|
140
|
+
catch (e) {
|
|
141
|
+
return content;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* 将 URL 中的 http:// 协议改成 https://
|
|
146
|
+
*/
|
|
147
|
+
export function ensureHttps(url) {
|
|
148
|
+
return url?.replace(/http:\/\//g, 'https://');
|
|
149
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type CommonOptions, type Validator, type Validated } from './base.js';
|
|
2
|
+
/** 验证元素数量任意、元素类型相同的数组 */
|
|
3
|
+
export interface ArrayOptions extends CommonOptions {
|
|
4
|
+
/** 验证数组各元素 */
|
|
5
|
+
item: Validator<unknown, CommonOptions>;
|
|
6
|
+
/** 数组最小长度 */
|
|
7
|
+
min?: number;
|
|
8
|
+
/** 数组最大长度 */
|
|
9
|
+
max?: number;
|
|
10
|
+
/** 是否对数组元素进行去重 @defaults false */
|
|
11
|
+
unique?: boolean;
|
|
12
|
+
/** 如果传入的不是数组,是否要将其视为数组内元素,包裹成数组 */
|
|
13
|
+
toArray?: boolean;
|
|
14
|
+
}
|
|
15
|
+
type ArrayValues<Options extends ArrayOptions> = Validated<Options extends {
|
|
16
|
+
item: Validator<infer T, CommonOptions>;
|
|
17
|
+
} ? T : never, Options extends {
|
|
18
|
+
item: Validator<unknown, infer T>;
|
|
19
|
+
} ? T : never>[];
|
|
20
|
+
export declare function getArrayValidator<Options extends ArrayOptions>(options: Options): Validator<ArrayValues<Options>, Options>;
|
|
21
|
+
/** 验证元素数量固定、类型可以不同的数组 */
|
|
22
|
+
export interface TupleOptions extends CommonOptions {
|
|
23
|
+
/** 验证数组各元素(validator 与元素一一对应) */
|
|
24
|
+
tuple: Validator<unknown, CommonOptions>[];
|
|
25
|
+
}
|
|
26
|
+
type TupleValues<Options extends TupleOptions> = {
|
|
27
|
+
[Key in keyof Options['tuple']]: Options['tuple'][Key] extends Validator<infer Value, infer Options> ? Validated<Value, Options> : never;
|
|
28
|
+
};
|
|
29
|
+
export declare function getTupleValidator<const Options extends TupleOptions>(options: Options): Validator<TupleValues<Options>, Options>;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { success, failed } from '../lang/index.js';
|
|
2
|
+
import { getValidatorGenerator, } from './base.js';
|
|
3
|
+
export function getArrayValidator(options) {
|
|
4
|
+
return getValidatorGenerator(function validate(field, value, options) {
|
|
5
|
+
if (!Array.isArray(value)) {
|
|
6
|
+
if (options.toArray)
|
|
7
|
+
value = [value];
|
|
8
|
+
else
|
|
9
|
+
return failed(`${field} should be an array`);
|
|
10
|
+
}
|
|
11
|
+
let formatted = [];
|
|
12
|
+
if (typeof options.min === 'number' && value.length < options.min)
|
|
13
|
+
return failed(`array ${field}'s length should >= ${options.min}`);
|
|
14
|
+
if (typeof options.max === 'number' && value.length > options.max)
|
|
15
|
+
return failed(`array ${field}'s length should <= ${options.max}`);
|
|
16
|
+
const itemValidator = options.item;
|
|
17
|
+
for (let i = 0; i < value.length; i++) {
|
|
18
|
+
const itemResult = itemValidator(`${field}[${i}]`, value[i]);
|
|
19
|
+
if (itemResult.success)
|
|
20
|
+
formatted.push(itemResult.data);
|
|
21
|
+
else
|
|
22
|
+
return itemResult;
|
|
23
|
+
}
|
|
24
|
+
if (options.unique === true)
|
|
25
|
+
formatted = [...new Set(formatted)];
|
|
26
|
+
return success(formatted);
|
|
27
|
+
})(options);
|
|
28
|
+
}
|
|
29
|
+
export function getTupleValidator(options) {
|
|
30
|
+
return getValidatorGenerator(function validate(field, value, options) {
|
|
31
|
+
if (!Array.isArray(value))
|
|
32
|
+
return failed(`${field} should be an array`);
|
|
33
|
+
if (value.length > options.tuple.length)
|
|
34
|
+
return failed(`${field} should be a tuple with ${options.tuple.length} items`);
|
|
35
|
+
const formatted = [];
|
|
36
|
+
// 这种情况不能遍历 value,因为它的长度可能小于 opt.tuple
|
|
37
|
+
for (let i = 0; i < options.tuple.length; i++) {
|
|
38
|
+
const itemValidator = options.tuple[i];
|
|
39
|
+
const itemResult = itemValidator(`${field}[${i}]`, value[i]);
|
|
40
|
+
if (itemResult.success)
|
|
41
|
+
formatted.push(itemResult.data);
|
|
42
|
+
else
|
|
43
|
+
return itemResult;
|
|
44
|
+
}
|
|
45
|
+
return success(formatted);
|
|
46
|
+
})(options);
|
|
47
|
+
}
|