@vope/utils 1.4.24 → 1.4.26
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/cjs/index.js +5531 -208
- package/lib/compare/weak-equal.js +6 -2
- package/lib/index.js +2 -0
- package/lib/serialize/url-params.js +32 -80
- package/lib/storage/offline.js +232 -0
- package/lib/url/params.js +4 -20
- package/package.json +17 -6
- package/types/compare/weak-equal.d.ts +1 -1
- package/types/index.d.ts +2 -1
- package/types/serialize/url-params.d.ts +27 -20
- package/types/storage/offline.d.ts +51 -0
- package/types/url/params.d.ts +3 -6
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { hash8strings } from "../convert/strings";
|
|
2
|
+
const deepWeakEqual = (from, to, exclude) => {
|
|
2
3
|
if (typeof from !== "object" || from === null || typeof to !== "object" || to === null)
|
|
3
4
|
return from === to;
|
|
4
5
|
if (Array.isArray(from) && Array.isArray(to)) {
|
|
@@ -11,7 +12,10 @@ const deepWeakEqual = (from, to) => {
|
|
|
11
12
|
});
|
|
12
13
|
} else {
|
|
13
14
|
const caches = {};
|
|
15
|
+
const excludeCaches = exclude && hash8strings(exclude);
|
|
14
16
|
for (const key in from) {
|
|
17
|
+
if (excludeCaches && key in excludeCaches)
|
|
18
|
+
continue;
|
|
15
19
|
if (!deepWeakEqual(from[key], to[key])) {
|
|
16
20
|
return false;
|
|
17
21
|
} else {
|
|
@@ -19,7 +23,7 @@ const deepWeakEqual = (from, to) => {
|
|
|
19
23
|
}
|
|
20
24
|
}
|
|
21
25
|
for (const key in to) {
|
|
22
|
-
if (key in caches)
|
|
26
|
+
if (excludeCaches && key in excludeCaches || key in caches)
|
|
23
27
|
continue;
|
|
24
28
|
if (!deepWeakEqual(from[key], to[key])) {
|
|
25
29
|
return false;
|
package/lib/index.js
CHANGED
|
@@ -25,6 +25,7 @@ import { deconPowersSum } from "./power/decon";
|
|
|
25
25
|
import { rotateAngle } from "./rotate/angle";
|
|
26
26
|
import { rotateRad } from "./rotate/rad";
|
|
27
27
|
import { cubeURLParams, flatURLParams } from "./serialize/url-params";
|
|
28
|
+
import { OfflineStorage } from "./storage/offline";
|
|
28
29
|
import { css } from "./style/css";
|
|
29
30
|
import { default as default4 } from "./subscriber";
|
|
30
31
|
import { FlexTable } from "./table/flex";
|
|
@@ -40,6 +41,7 @@ export {
|
|
|
40
41
|
MemorySimple,
|
|
41
42
|
default3 as Neo4j,
|
|
42
43
|
default2 as Neo4jAhchors,
|
|
44
|
+
OfflineStorage,
|
|
43
45
|
default4 as Subscriber,
|
|
44
46
|
Union,
|
|
45
47
|
clamp,
|
|
@@ -1,99 +1,51 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isString } from "lodash-es";
|
|
2
|
+
import { isKey } from "../is/key";
|
|
3
|
+
const cubes = {
|
|
4
|
+
string: (text) => text,
|
|
5
|
+
boolean: (text) => text === "true",
|
|
6
|
+
number: (text) => Number(text),
|
|
7
|
+
bigint: (text) => BigInt(text),
|
|
8
|
+
date: (text) => new Date(text),
|
|
9
|
+
regexp: (text) => new RegExp(text),
|
|
10
|
+
null: () => null
|
|
11
|
+
};
|
|
12
|
+
const flats = {
|
|
13
|
+
string: (data) => flatEncode(data),
|
|
14
|
+
boolean: (data) => `${data}`,
|
|
15
|
+
number: (data) => `${data}`,
|
|
16
|
+
bigint: (data) => `${data}`,
|
|
17
|
+
date: (data) => data.toJSON(),
|
|
18
|
+
regexp: (data) => flatEncode(data.source),
|
|
19
|
+
null: () => "null"
|
|
20
|
+
};
|
|
2
21
|
const cubeURLParams = (text, serializes) => {
|
|
3
22
|
const params = new URLSearchParams(text);
|
|
4
23
|
const result = {};
|
|
5
24
|
for (const [key, value] of params) {
|
|
6
25
|
const serialize = serializes[key];
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
break;
|
|
14
|
-
case Date:
|
|
15
|
-
result[key] = new Date(value);
|
|
16
|
-
break;
|
|
17
|
-
case BigInt:
|
|
18
|
-
result[key] = BigInt(value);
|
|
19
|
-
break;
|
|
20
|
-
case RegExp:
|
|
21
|
-
result[key] = new RegExp(value);
|
|
22
|
-
break;
|
|
23
|
-
default:
|
|
24
|
-
if (isFunction(serialize)) {
|
|
25
|
-
result[key] = serialize(value);
|
|
26
|
-
} else if (isObject(serialize) && isFunction(serialize.cube)) {
|
|
27
|
-
result[key] = serialize.cube(value);
|
|
28
|
-
} else {
|
|
29
|
-
result[key] = value;
|
|
30
|
-
}
|
|
26
|
+
if (!serialize)
|
|
27
|
+
continue;
|
|
28
|
+
if (isString(serialize) && isKey(serialize, cubes)) {
|
|
29
|
+
result[key] = cubes[serialize](value);
|
|
30
|
+
} else {
|
|
31
|
+
result[key] = serialize.cube(value);
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
34
|
return result;
|
|
34
35
|
};
|
|
35
36
|
const re_flat = /\+/g;
|
|
36
37
|
const flatEncode = (text) => text.replace(re_flat, () => "%2B");
|
|
37
|
-
const flatValue = (value) => {
|
|
38
|
-
switch (typeof value) {
|
|
39
|
-
case "boolean":
|
|
40
|
-
case "bigint":
|
|
41
|
-
case "number":
|
|
42
|
-
case "symbol":
|
|
43
|
-
case "function":
|
|
44
|
-
return value.toString();
|
|
45
|
-
case "string":
|
|
46
|
-
return flatEncode(value);
|
|
47
|
-
case "undefined":
|
|
48
|
-
return "";
|
|
49
|
-
default:
|
|
50
|
-
if (value === null) {
|
|
51
|
-
return "";
|
|
52
|
-
}
|
|
53
|
-
if (value instanceof Date) {
|
|
54
|
-
return value.toJSON();
|
|
55
|
-
} else if (value instanceof RegExp) {
|
|
56
|
-
return flatEncode(value.source);
|
|
57
|
-
} else {
|
|
58
|
-
return flatEncode(value.toString());
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
38
|
const flatURLParams = (data, serializes) => {
|
|
63
39
|
const params = new URLSearchParams();
|
|
64
40
|
for (const key in data) {
|
|
65
41
|
const value = data[key];
|
|
66
42
|
const serialize = serializes[key];
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
result = typeof value === "number" ? `${value}` : "";
|
|
74
|
-
break;
|
|
75
|
-
case Date:
|
|
76
|
-
result = value instanceof Date ? value.toJSON() : "";
|
|
77
|
-
break;
|
|
78
|
-
case BigInt:
|
|
79
|
-
result = typeof value === "bigint" ? `${value}` : "";
|
|
80
|
-
break;
|
|
81
|
-
case RegExp:
|
|
82
|
-
result = value instanceof RegExp ? flatEncode(value.source) : "";
|
|
83
|
-
break;
|
|
84
|
-
case String:
|
|
85
|
-
result = typeof value === "string" ? flatEncode(value) : "";
|
|
86
|
-
break;
|
|
87
|
-
default:
|
|
88
|
-
if (isFunction(serialize)) {
|
|
89
|
-
result = flatValue(value);
|
|
90
|
-
} else if (isObject(serialize) && isFunction(serialize.flat)) {
|
|
91
|
-
result = serialize.flat(value);
|
|
92
|
-
} else {
|
|
93
|
-
result = flatValue(value);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
params.append(key, result);
|
|
43
|
+
if (!serialize)
|
|
44
|
+
continue;
|
|
45
|
+
params.append(
|
|
46
|
+
key,
|
|
47
|
+
isString(serialize) && isKey(serialize, flats) ? flats[serialize](value) : serialize.flat(value)
|
|
48
|
+
);
|
|
97
49
|
}
|
|
98
50
|
return params.toString();
|
|
99
51
|
};
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { name } from "@package";
|
|
2
|
+
import localforage from "localforage";
|
|
3
|
+
import { isString } from "lodash-es";
|
|
4
|
+
import { sm4 } from "sm-crypto";
|
|
5
|
+
const PREFIX = name + "_";
|
|
6
|
+
const key = [25, 144, 1, 32, 25, 135, 6, 40, 32, 23, 18, 19, 32, 36, 9, 5];
|
|
7
|
+
const iv = [182, 59, 9, 29, 86, 64, 118, 111, 112, 101, 47, 117, 116, 105, 108, 115];
|
|
8
|
+
const config = {
|
|
9
|
+
output: "string",
|
|
10
|
+
mode: "cbc",
|
|
11
|
+
iv
|
|
12
|
+
};
|
|
13
|
+
const HEADER = "." + sm4.encrypt(name, key, config);
|
|
14
|
+
const encrypt = (data) => {
|
|
15
|
+
let text = "";
|
|
16
|
+
for (const key2 in data) {
|
|
17
|
+
const value = data[key2];
|
|
18
|
+
if (value === void 0)
|
|
19
|
+
continue;
|
|
20
|
+
text && (text += "&");
|
|
21
|
+
text += key2 + ":" + value;
|
|
22
|
+
}
|
|
23
|
+
return sm4.encrypt(text, key, config);
|
|
24
|
+
};
|
|
25
|
+
const decrypt = (text) => {
|
|
26
|
+
const data = {};
|
|
27
|
+
let value;
|
|
28
|
+
try {
|
|
29
|
+
value = sm4.decrypt(text, key, config);
|
|
30
|
+
} catch {
|
|
31
|
+
value = "";
|
|
32
|
+
}
|
|
33
|
+
value.split("&").forEach((pair) => {
|
|
34
|
+
const [key2, value2] = pair.split(":");
|
|
35
|
+
if (key2 === "expire") {
|
|
36
|
+
data[key2] = +value2;
|
|
37
|
+
} else {
|
|
38
|
+
data[key2] = value2;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
return data;
|
|
42
|
+
};
|
|
43
|
+
const structKey = (index) => index.toString(16).padStart(8, "0");
|
|
44
|
+
const reductKey = (key2) => parseInt(key2, 16);
|
|
45
|
+
const MESSAGES = {
|
|
46
|
+
mount: "Please wait for the mounting to complete",
|
|
47
|
+
auth: "Unauthorized operation",
|
|
48
|
+
push: "Cannot add data to expired databases",
|
|
49
|
+
update: "Cannot update data to expired databases",
|
|
50
|
+
get: "Cannot get data from expired databases"
|
|
51
|
+
};
|
|
52
|
+
const createInstance = (name2, version = 2) => localforage.createInstance({
|
|
53
|
+
driver: localforage.INDEXEDDB,
|
|
54
|
+
name: name2,
|
|
55
|
+
version
|
|
56
|
+
});
|
|
57
|
+
class OfflineStorage {
|
|
58
|
+
#forage;
|
|
59
|
+
#expire;
|
|
60
|
+
#auth = false;
|
|
61
|
+
#crypto;
|
|
62
|
+
#size = 0;
|
|
63
|
+
#mount;
|
|
64
|
+
#mounted = false;
|
|
65
|
+
get size() {
|
|
66
|
+
return this.#size;
|
|
67
|
+
}
|
|
68
|
+
get mounted() {
|
|
69
|
+
return this.#mounted;
|
|
70
|
+
}
|
|
71
|
+
constructor({
|
|
72
|
+
name: name2,
|
|
73
|
+
expire: newExpire,
|
|
74
|
+
token: newToken,
|
|
75
|
+
crypto
|
|
76
|
+
}) {
|
|
77
|
+
const forage = this.#forage = createInstance(sm4.encrypt(PREFIX + name2, key, config));
|
|
78
|
+
this.#mount = new Promise(async (resolve) => {
|
|
79
|
+
const keys = await forage.keys().then((keys2) => keys2).catch(() => []);
|
|
80
|
+
let size = 0;
|
|
81
|
+
let expire = newExpire;
|
|
82
|
+
let token = newToken;
|
|
83
|
+
let auth = true;
|
|
84
|
+
for (const key2 of keys) {
|
|
85
|
+
if (key2 === HEADER) {
|
|
86
|
+
const {
|
|
87
|
+
expire: oldExpire,
|
|
88
|
+
token: oldToken
|
|
89
|
+
} = decrypt(await forage.getItem(key2));
|
|
90
|
+
expire = oldExpire === void 0 ? newExpire : Date.now() < oldExpire ? newExpire : oldExpire;
|
|
91
|
+
auth = oldToken ? oldToken === newToken : true;
|
|
92
|
+
token = oldToken || newToken;
|
|
93
|
+
} else {
|
|
94
|
+
const value = reductKey(key2) + 1;
|
|
95
|
+
value > size && (size = value);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
this.#size = size;
|
|
99
|
+
this.#expire = expire;
|
|
100
|
+
this.#auth = auth;
|
|
101
|
+
this.#crypto = crypto;
|
|
102
|
+
await forage.setItem(HEADER, encrypt({
|
|
103
|
+
expire,
|
|
104
|
+
token
|
|
105
|
+
}));
|
|
106
|
+
this.#mounted = true;
|
|
107
|
+
resolve(this);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
ready() {
|
|
111
|
+
return this.#mount;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* 校验存储是否过期
|
|
115
|
+
*/
|
|
116
|
+
validateExpire() {
|
|
117
|
+
const expire = this.#expire;
|
|
118
|
+
return expire === void 0 || Date.now() < expire;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* 校验
|
|
122
|
+
*/
|
|
123
|
+
validate(callback, expireMessage) {
|
|
124
|
+
if (!this.#mounted) {
|
|
125
|
+
callback(new Error(MESSAGES.mount));
|
|
126
|
+
} else if (!this.#auth) {
|
|
127
|
+
callback(new Error(MESSAGES.auth));
|
|
128
|
+
} else if (expireMessage && !this.validateExpire()) {
|
|
129
|
+
callback(new Error(expireMessage));
|
|
130
|
+
} else {
|
|
131
|
+
callback();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* 插入数据
|
|
136
|
+
*/
|
|
137
|
+
async push(data) {
|
|
138
|
+
this.validate((e) => {
|
|
139
|
+
if (e)
|
|
140
|
+
throw e;
|
|
141
|
+
}, MESSAGES.push);
|
|
142
|
+
const size = this.#size;
|
|
143
|
+
const key2 = structKey(size);
|
|
144
|
+
await this.#forage.setItem(key2, await this.#crypto.encrypt(data));
|
|
145
|
+
return this.#size = size + 1;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* 修改数据
|
|
149
|
+
*/
|
|
150
|
+
async update(index, data) {
|
|
151
|
+
this.validate((e) => {
|
|
152
|
+
if (e)
|
|
153
|
+
throw e;
|
|
154
|
+
}, MESSAGES.update);
|
|
155
|
+
const forage = this.#forage;
|
|
156
|
+
const key2 = structKey(index);
|
|
157
|
+
const value = await forage.getItem(key2);
|
|
158
|
+
if (value === null)
|
|
159
|
+
return false;
|
|
160
|
+
await forage.setItem(key2, await this.#crypto.encrypt(data));
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* 获取数据
|
|
165
|
+
*/
|
|
166
|
+
async get(index) {
|
|
167
|
+
this.validate((e) => {
|
|
168
|
+
if (e)
|
|
169
|
+
throw e;
|
|
170
|
+
}, MESSAGES.get);
|
|
171
|
+
const key2 = structKey(index);
|
|
172
|
+
const value = await this.#forage.getItem(key2);
|
|
173
|
+
return value === null ? null : await this.#crypto.decrypt(value);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* 清理存储
|
|
177
|
+
*/
|
|
178
|
+
async clear() {
|
|
179
|
+
this.validate((e) => {
|
|
180
|
+
if (e)
|
|
181
|
+
throw e;
|
|
182
|
+
});
|
|
183
|
+
this.#size = 0;
|
|
184
|
+
await localforage.dropInstance({
|
|
185
|
+
name: this.#forage.config().name
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
static default(options) {
|
|
189
|
+
isString(options) && (options = { name: options });
|
|
190
|
+
return new OfflineStorage({
|
|
191
|
+
...options,
|
|
192
|
+
crypto: {
|
|
193
|
+
encrypt(plain) {
|
|
194
|
+
return plain;
|
|
195
|
+
},
|
|
196
|
+
decrypt(cipher) {
|
|
197
|
+
return cipher;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
static async clear(token, callback) {
|
|
203
|
+
const size = PREFIX.length;
|
|
204
|
+
const databases = await indexedDB.databases();
|
|
205
|
+
const tasks = [];
|
|
206
|
+
for (const { name: name2, version } of databases) {
|
|
207
|
+
if (name2 === void 0)
|
|
208
|
+
continue;
|
|
209
|
+
let text;
|
|
210
|
+
try {
|
|
211
|
+
text = sm4.decrypt(name2, key, config);
|
|
212
|
+
} catch {
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
if (text.slice(0, size) !== PREFIX)
|
|
216
|
+
continue;
|
|
217
|
+
const forage = createInstance(name2, version);
|
|
218
|
+
const value = await forage.getItem(HEADER);
|
|
219
|
+
if (value === null || decrypt(value).token !== token || callback && callback(text.slice(size)))
|
|
220
|
+
continue;
|
|
221
|
+
const idb = indexedDB.deleteDatabase(text);
|
|
222
|
+
tasks.push(new Promise((resolve) => {
|
|
223
|
+
idb.onerror = () => resolve();
|
|
224
|
+
idb.onsuccess = () => resolve();
|
|
225
|
+
}));
|
|
226
|
+
}
|
|
227
|
+
await Promise.all(tasks);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
export {
|
|
231
|
+
OfflineStorage
|
|
232
|
+
};
|
package/lib/url/params.js
CHANGED
|
@@ -1,23 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
for (const key in params) {
|
|
6
|
-
const value = params[key];
|
|
7
|
-
if (value === void 0) {
|
|
8
|
-
list.push(key);
|
|
9
|
-
} else if (Array.isArray(value)) {
|
|
10
|
-
list.push(
|
|
11
|
-
key + "=" + (isOpenType ? JSON.stringify(value).slice(1, -1) : value.join(","))
|
|
12
|
-
);
|
|
13
|
-
} else {
|
|
14
|
-
list.push(key + "=" + (isOpenType ? JSON.stringify(value) : value.toString()));
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
if (!list.length)
|
|
18
|
-
return url;
|
|
19
|
-
const caches = list.join("&");
|
|
20
|
-
return url.includes("?") ? url + "&" + caches : url + "?" + caches;
|
|
1
|
+
import { flatURLParams } from "../serialize/url-params";
|
|
2
|
+
const connectURLParams = (url, params, serializes) => {
|
|
3
|
+
const query = flatURLParams(params, serializes);
|
|
4
|
+
return query ? url.includes("?") ? url + "&" + query : url + "?" + query : url;
|
|
21
5
|
};
|
|
22
6
|
export {
|
|
23
7
|
connectURLParams
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vope/utils",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.26",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -12,13 +12,14 @@
|
|
|
12
12
|
"module": "./lib/index.js",
|
|
13
13
|
"main": "./cjs/index.js",
|
|
14
14
|
"scripts": {
|
|
15
|
-
"start": "esbuild ./
|
|
16
|
-
"
|
|
17
|
-
"build": "node ./build.cjs",
|
|
15
|
+
"start": "esbuild ./start.ts --outfile=start.cjs --format=cjs & node ./start.cjs",
|
|
16
|
+
"poststart": "esbuild ./pre.ts --outfile=pre.cjs --format=cjs & node ./pre.cjs",
|
|
17
|
+
"build": "npm run start & node ./build.cjs",
|
|
18
18
|
"premocha": "node ./build.cjs --type=test",
|
|
19
19
|
"mocha": "mocha __tests/**/*.js",
|
|
20
20
|
"test": "npm run mocha",
|
|
21
|
-
"prepublishOnly": "npm run build & npm run test"
|
|
21
|
+
"prepublishOnly": "npm run build & npm run test",
|
|
22
|
+
"debug": "npm run build & npm run premocha"
|
|
22
23
|
},
|
|
23
24
|
"exports": {
|
|
24
25
|
".": {
|
|
@@ -37,14 +38,22 @@
|
|
|
37
38
|
"@babel/parser": "^7.23.4",
|
|
38
39
|
"@babel/traverse": "^7.23.4",
|
|
39
40
|
"@babel/types": "^7.23.4",
|
|
41
|
+
"@rollup/plugin-alias": "^5.1.1",
|
|
42
|
+
"@rollup/plugin-commonjs": "^28.0.0",
|
|
43
|
+
"@rollup/plugin-json": "^6.1.0",
|
|
44
|
+
"@rollup/plugin-node-resolve": "^15.3.0",
|
|
45
|
+
"@rollup/plugin-typescript": "^12.1.0",
|
|
40
46
|
"@types/babel__traverse": "^7.20.4",
|
|
41
47
|
"@types/mocha": "^10.0.6",
|
|
42
48
|
"@types/node": "^20.4.5",
|
|
49
|
+
"@types/sm-crypto": "^0.3.4",
|
|
43
50
|
"esbuild": "^0.19.4",
|
|
44
51
|
"glob": "^10.3.10",
|
|
45
52
|
"iconv-lite": "^0.6.3",
|
|
46
53
|
"mocha": "^10.2.0",
|
|
54
|
+
"puppeteer": "^23.4.1",
|
|
47
55
|
"rimraf": "^5.0.5",
|
|
56
|
+
"rollup": "^4.22.5",
|
|
48
57
|
"tslib": "^2.6.1",
|
|
49
58
|
"typescript": "^5.3.3"
|
|
50
59
|
},
|
|
@@ -53,6 +62,8 @@
|
|
|
53
62
|
"@types/lodash-es": "^4.17.9",
|
|
54
63
|
"@vope/types": "^1.0.13",
|
|
55
64
|
"csstype": "^3.1.3",
|
|
56
|
-
"
|
|
65
|
+
"localforage": "^1.10.0",
|
|
66
|
+
"lodash-es": "^4.17.21",
|
|
67
|
+
"sm-crypto": "^0.3.13"
|
|
57
68
|
}
|
|
58
69
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -24,7 +24,8 @@ export { parseNum } from './parse/num';
|
|
|
24
24
|
export { deconPowersSum } from './power/decon';
|
|
25
25
|
export { rotateAngle } from './rotate/angle';
|
|
26
26
|
export { rotateRad } from './rotate/rad';
|
|
27
|
-
export { type
|
|
27
|
+
export { type Serializes, cubeURLParams, flatURLParams } from './serialize/url-params';
|
|
28
|
+
export { type ICrypto, OfflineStorage } from './storage/offline';
|
|
28
29
|
export { type CSSProperties, type StyleValue, css } from './style/css';
|
|
29
30
|
export { type SModel, default as Subscriber } from './subscriber';
|
|
30
31
|
export { FlexTable } from './table/flex';
|
|
@@ -1,36 +1,43 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { Equal } from '@type-challenges/utils';
|
|
2
|
+
import { UnionToTuple } from '@vope/types';
|
|
3
|
+
type NativeMap = {
|
|
4
|
+
string: string;
|
|
5
|
+
boolean: boolean;
|
|
6
|
+
number: number;
|
|
7
|
+
bigint: bigint;
|
|
8
|
+
date: Date;
|
|
9
|
+
regexp: RegExp;
|
|
10
|
+
null: null;
|
|
11
|
+
};
|
|
12
|
+
type NativeValue = keyof NativeMap;
|
|
3
13
|
interface AccessorValue<T = any> {
|
|
4
14
|
cube(text: string): T;
|
|
5
|
-
flat
|
|
15
|
+
flat(value: T): string;
|
|
6
16
|
}
|
|
7
|
-
type
|
|
8
|
-
|
|
17
|
+
type NativeUnion = UnionToTuple<{
|
|
18
|
+
[P in NativeValue]: [NativeMap[P], P];
|
|
19
|
+
}[NativeValue]>;
|
|
20
|
+
type Signal<T, U extends any[] = NativeUnion> = U extends [infer A1, ...infer A2] ? A1 extends [infer V, infer K] ? Equal<T, V> extends true ? K : Signal<T, A2> : Signal<T, A2> : never;
|
|
9
21
|
/**
|
|
10
22
|
* 转换套件类型
|
|
11
23
|
*/
|
|
12
|
-
type
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
type Cubes<T extends Values, Branch extends boolean = false> = {
|
|
19
|
-
[P in keyof T]: Cube<T[P], Branch>;
|
|
24
|
+
export type Serializes<T extends object> = {
|
|
25
|
+
[P in keyof T & string]: Signal<T[P]> | AccessorValue<T[P]>;
|
|
26
|
+
};
|
|
27
|
+
type Cube<T> = [T] extends [NativeValue] ? NativeMap[T] : [T] extends [AccessorValue<infer B>] ? B : never;
|
|
28
|
+
type Cubes<T extends object, S extends Serializes<T>> = {
|
|
29
|
+
[P in Extract<keyof T, keyof S> & string]: Cube<S[P]>;
|
|
20
30
|
};
|
|
21
31
|
/**
|
|
22
32
|
* 将URL查询参数转换成(复杂)对象
|
|
23
33
|
* @param text URL查询参数字符串
|
|
24
34
|
* @param serializes 转换套件
|
|
25
35
|
*/
|
|
26
|
-
export declare const cubeURLParams: <T extends
|
|
27
|
-
/**
|
|
28
|
-
* 符合套件的(复杂)数据类型
|
|
29
|
-
*/
|
|
30
|
-
export type URLParamsFlats<T extends Values> = Cubes<T, true>;
|
|
36
|
+
export declare const cubeURLParams: <T extends object, S extends Serializes<T>>(text: string, serializes: S) => Cubes<T, S>;
|
|
31
37
|
/**
|
|
32
38
|
* 将(复杂)对象转换成URL查询参数
|
|
33
|
-
* @param data
|
|
39
|
+
* @param data 数据
|
|
34
40
|
* @param serializes 转换套件
|
|
35
41
|
*/
|
|
36
|
-
export declare const flatURLParams: <T extends
|
|
42
|
+
export declare const flatURLParams: <T extends object, S extends Serializes<T>>(data: T, serializes: S) => string;
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export interface ICrypto<From, To> {
|
|
2
|
+
encrypt(plain: From): To | Promise<To>;
|
|
3
|
+
decrypt(cipher: To): From | Promise<From>;
|
|
4
|
+
}
|
|
5
|
+
interface Options<From, To> {
|
|
6
|
+
/** 存储名称 */
|
|
7
|
+
name: string;
|
|
8
|
+
/** 存储认证 */
|
|
9
|
+
token?: string;
|
|
10
|
+
/** 存储期限 */
|
|
11
|
+
expire?: number;
|
|
12
|
+
/** 存储加密 */
|
|
13
|
+
crypto: ICrypto<From, To>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 离线存储
|
|
17
|
+
*/
|
|
18
|
+
export declare class OfflineStorage<From, To> {
|
|
19
|
+
#private;
|
|
20
|
+
get size(): number;
|
|
21
|
+
get mounted(): boolean;
|
|
22
|
+
constructor({ name, expire: newExpire, token: newToken, crypto, }: Options<From, To>);
|
|
23
|
+
ready(): Promise<this>;
|
|
24
|
+
/**
|
|
25
|
+
* 校验存储是否过期
|
|
26
|
+
*/
|
|
27
|
+
validateExpire(): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* 校验
|
|
30
|
+
*/
|
|
31
|
+
validate(callback: (error?: Error) => void, expireMessage?: string): void;
|
|
32
|
+
/**
|
|
33
|
+
* 插入数据
|
|
34
|
+
*/
|
|
35
|
+
push(data: From): Promise<number>;
|
|
36
|
+
/**
|
|
37
|
+
* 修改数据
|
|
38
|
+
*/
|
|
39
|
+
update(index: number, data: From): Promise<boolean>;
|
|
40
|
+
/**
|
|
41
|
+
* 获取数据
|
|
42
|
+
*/
|
|
43
|
+
get(index: number): Promise<From | null>;
|
|
44
|
+
/**
|
|
45
|
+
* 清理存储
|
|
46
|
+
*/
|
|
47
|
+
clear(): Promise<void>;
|
|
48
|
+
static default<T>(options: string | Omit<Options<T, T>, 'crypto'>): OfflineStorage<T, T>;
|
|
49
|
+
static clear(token?: string, callback?: (name: string) => boolean): Promise<void>;
|
|
50
|
+
}
|
|
51
|
+
export {};
|
package/types/url/params.d.ts
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
type Params = Param | Param[];
|
|
1
|
+
import { Serializes } from '../serialize/url-params';
|
|
3
2
|
/**
|
|
4
3
|
* url拼接参数
|
|
5
4
|
* @param url
|
|
6
5
|
* @param params 需要让url携带的参数
|
|
7
|
-
* @param
|
|
8
|
-
* @description 开始类型处理的情况下,undefined会被转成null
|
|
6
|
+
* @param serializes 转换套件
|
|
9
7
|
*/
|
|
10
|
-
export declare const connectURLParams: (url: string, params
|
|
11
|
-
export {};
|
|
8
|
+
export declare const connectURLParams: <T extends object>(url: string, params: T, serializes: Serializes<T>) => string;
|