@nsnanocat/util 2.1.1 → 2.1.3
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/README.md +65 -11
- package/getStorage.mjs +59 -28
- package/lib/argument.mjs +20 -8
- package/package.json +1 -1
- package/polyfill/Lodash.mjs +22 -0
- package/polyfill/Storage.mjs +8 -0
package/README.md
CHANGED
|
@@ -64,7 +64,7 @@ import {
|
|
|
64
64
|
time, // 时间格式化工具
|
|
65
65
|
wait, // 延时等待工具(Promise)
|
|
66
66
|
Console, // 统一日志工具(支持 logLevel)
|
|
67
|
-
Lodash,
|
|
67
|
+
Lodash as _, // Lodash 建议按官方示例惯例使用 `_` 作为工具对象别名
|
|
68
68
|
Storage, // 统一持久化存储接口(适配 $prefs / $persistentStore / 文件)
|
|
69
69
|
} from "@nsnanocat/util";
|
|
70
70
|
```
|
|
@@ -177,7 +177,7 @@ console.log(environment()); // 当前环境对象
|
|
|
177
177
|
- 使用点路径展开对象(`a.b=1 -> { a: { b: "1" } }`)。
|
|
178
178
|
- 当全局 `$argument` 为 `object` 时:
|
|
179
179
|
- 将 key 当路径写回新对象(`{"a.b":"1"}` -> `{a:{b:"1"}}`)。
|
|
180
|
-
- 当 `$argument` 为 `undefined
|
|
180
|
+
- 当 `$argument` 为 `null` 或 `undefined`:会归一化为 `{}`。
|
|
181
181
|
- 若 `$argument.LogLevel` 存在:同步到 `Console.logLevel`。
|
|
182
182
|
|
|
183
183
|
#### 用法
|
|
@@ -315,13 +315,15 @@ await runScript("$done({})", { timeout: 20 });
|
|
|
315
315
|
- `database: object`(默认数据库)
|
|
316
316
|
- 返回:`{ Settings, Configs, Caches }`
|
|
317
317
|
|
|
318
|
-
|
|
319
|
-
1.
|
|
320
|
-
2.
|
|
321
|
-
3.
|
|
322
|
-
4.
|
|
318
|
+
合并顺序由 `$argument.Storage` 控制(持久化读取统一使用 `PersistentStore = Storage.getItem(key, {})`):
|
|
319
|
+
1. 默认(`undefined`):`database[name]` -> `$argument` -> `PersistentStore[name]`
|
|
320
|
+
2. `$argument`:`database[name]` -> `PersistentStore[name]` -> `$argument`
|
|
321
|
+
3. `PersistentStore` / `BoxJs`:`database[name]` -> `PersistentStore[name]`
|
|
322
|
+
4. `database`:仅 `database[name]`
|
|
323
323
|
|
|
324
|
-
|
|
324
|
+
注意:`Configs` 与 `Caches` 始终按每个 `name` 合并(与 `$argument.Storage` 无关)。
|
|
325
|
+
|
|
326
|
+
自动类型转换(`Root.Settings`):
|
|
325
327
|
- 字符串 `"true"/"false"` -> `boolean`
|
|
326
328
|
- 纯数字字符串 -> `number`
|
|
327
329
|
- 含逗号字符串 -> `array`,并尝试逐项转数字
|
|
@@ -408,7 +410,8 @@ const store = getStorage("@my_box", ["YouTube", "Global"], database);
|
|
|
408
410
|
|
|
409
411
|
#### `Storage.removeItem(keyName)`
|
|
410
412
|
- Quantumult X:可用(`$prefs.removeValueForKey`)。
|
|
411
|
-
- Surge
|
|
413
|
+
- Surge:通过 `$persistentStore.write(null, keyName)` 删除。
|
|
414
|
+
- Loon / Stash / Egern / Shadowrocket / Node.js:返回 `false`。
|
|
412
415
|
|
|
413
416
|
#### `Storage.clear()`
|
|
414
417
|
- Quantumult X:可用(`$prefs.removeAllValues`)。
|
|
@@ -420,7 +423,7 @@ const store = getStorage("@my_box", ["YouTube", "Global"], database);
|
|
|
420
423
|
|
|
421
424
|
与 Web Storage 的行为差异:
|
|
422
425
|
- 支持 `@key.path` 深路径读写(Web Storage 原生不支持)。
|
|
423
|
-
- `removeItem/clear`
|
|
426
|
+
- `removeItem/clear` 仅部分平台可用(目前为 Quantumult X,以及 Surge 的 `removeItem`)。
|
|
424
427
|
- `getItem` 会尝试 `JSON.parse`,`setItem` 写入对象会 `JSON.stringify`。
|
|
425
428
|
|
|
426
429
|
平台后端映射:
|
|
@@ -499,6 +502,28 @@ console.log(Console.logLevel); // "WARN"
|
|
|
499
502
|
- https://www.lodashjs.com
|
|
500
503
|
- https://lodash.com
|
|
501
504
|
|
|
505
|
+
导入约定(建议):
|
|
506
|
+
- 这是 lodash 官方示例中常见的惯例写法:使用 `_` 作为工具对象别名。
|
|
507
|
+
|
|
508
|
+
```js
|
|
509
|
+
import { Lodash as _ } from "@nsnanocat/util";
|
|
510
|
+
|
|
511
|
+
const data = {};
|
|
512
|
+
_.set(data, "a.b", 1);
|
|
513
|
+
console.log(data); // { a: { b: 1 } }
|
|
514
|
+
|
|
515
|
+
const value = _.get(data, "a.b", 0);
|
|
516
|
+
console.log(value); // 1
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
示例对应的 lodash 官方文档页面:
|
|
520
|
+
- `set(object, path, value)`
|
|
521
|
+
- 官方文档:https://lodash.com/docs/#set
|
|
522
|
+
- 中文文档:https://www.lodashjs.com/docs/lodash.set
|
|
523
|
+
- `get(object, path, defaultValue)`
|
|
524
|
+
- 官方文档:https://lodash.com/docs/#get
|
|
525
|
+
- 中文文档:https://www.lodashjs.com/docs/lodash.get
|
|
526
|
+
|
|
502
527
|
当前实现包含:
|
|
503
528
|
- `escape(string)`
|
|
504
529
|
- `unescape(string)`
|
|
@@ -510,6 +535,35 @@ console.log(Console.logLevel); // "WARN"
|
|
|
510
535
|
- `omit(object, paths)`
|
|
511
536
|
- `merge(object, ...sources)`
|
|
512
537
|
|
|
538
|
+
对应 lodash 官方文档页面:
|
|
539
|
+
- `escape(string)`
|
|
540
|
+
- 官方文档:https://lodash.com/docs/#escape
|
|
541
|
+
- 中文文档:https://www.lodashjs.com/docs/lodash.escape
|
|
542
|
+
- `unescape(string)`
|
|
543
|
+
- 官方文档:https://lodash.com/docs/#unescape
|
|
544
|
+
- 中文文档:https://www.lodashjs.com/docs/lodash.unescape
|
|
545
|
+
- `toPath(value)`
|
|
546
|
+
- 官方文档:https://lodash.com/docs/#toPath
|
|
547
|
+
- 中文文档:https://www.lodashjs.com/docs/lodash.toPath
|
|
548
|
+
- `get(object, path, defaultValue)`
|
|
549
|
+
- 官方文档:https://lodash.com/docs/#get
|
|
550
|
+
- 中文文档:https://www.lodashjs.com/docs/lodash.get
|
|
551
|
+
- `set(object, path, value)`
|
|
552
|
+
- 官方文档:https://lodash.com/docs/#set
|
|
553
|
+
- 中文文档:https://www.lodashjs.com/docs/lodash.set
|
|
554
|
+
- `unset(object, path)`
|
|
555
|
+
- 官方文档:https://lodash.com/docs/#unset
|
|
556
|
+
- 中文文档:https://www.lodashjs.com/docs/lodash.unset
|
|
557
|
+
- `pick(object, paths)`
|
|
558
|
+
- 官方文档:https://lodash.com/docs/#pick
|
|
559
|
+
- 中文文档:https://www.lodashjs.com/docs/lodash.pick
|
|
560
|
+
- `omit(object, paths)`
|
|
561
|
+
- 官方文档:https://lodash.com/docs/#omit
|
|
562
|
+
- 中文文档:https://www.lodashjs.com/docs/lodash.omit
|
|
563
|
+
- `merge(object, ...sources)`
|
|
564
|
+
- 官方文档:https://lodash.com/docs/#merge
|
|
565
|
+
- 中文文档:https://www.lodashjs.com/docs/lodash.merge
|
|
566
|
+
|
|
513
567
|
参数与返回值:
|
|
514
568
|
|
|
515
569
|
| 方法 | 参数 | 返回值 | 说明 |
|
|
@@ -549,7 +603,7 @@ console.log(Console.logLevel); // "WARN"
|
|
|
549
603
|
| 通知 | `$notify` | `$notification.post` | `$notification.post` | `$notification.post` | `$notification.post` | `$notification.post` | 无 |
|
|
550
604
|
| 持久化 | `$prefs` | `$persistentStore` | `$persistentStore` | `$persistentStore` | `$persistentStore` | `$persistentStore` | `box.dat` |
|
|
551
605
|
| 结束脚本 | `$done` | `$done` | `$done` | `$done` | `$done` | `$done` | `process.exit(1)` |
|
|
552
|
-
| `removeItem/clear` | 可用 | 不可用 | 不可用 | 不可用 | 不可用 | 不可用 | 不可用 |
|
|
606
|
+
| `removeItem/clear` | 可用 | 不可用 | `removeItem` 可用 / `clear` 不可用 | 不可用 | 不可用 | 不可用 | 不可用 |
|
|
553
607
|
| `policy` 注入(`fetch/done`) | `opts.policy` | `node` | `X-Surge-Policy`(done) | `X-Stash-Selected-Proxy` | 无专门映射 | `X-Surge-Proxy`(fetch) | 无 |
|
|
554
608
|
|
|
555
609
|
## 已知限制与注意事项
|
package/getStorage.mjs
CHANGED
|
@@ -17,13 +17,17 @@ import { Storage } from "./polyfill/Storage.mjs";
|
|
|
17
17
|
* 读取并合并默认配置、持久化配置与 `$argument`。
|
|
18
18
|
* Read and merge default config, persisted config and `$argument`.
|
|
19
19
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* 1) `database.Default`
|
|
23
|
-
* 2) BoxJS persisted value
|
|
24
|
-
* 3) `database[name]` + `BoxJs[name]`
|
|
25
|
-
* 4) `$argument`
|
|
20
|
+
* 注意:`Configs` 与 `Caches` 始终按每个 profile(`names`)合并;`Settings` 的合并顺序由 `$argument.Storage` 控制。
|
|
21
|
+
* Note: `Configs` and `Caches` are always merged per-profile (`names`); the merge order for `Settings` is controlled by `$argument.Storage`.
|
|
26
22
|
*
|
|
23
|
+
* 合并来源与顺序由 `$argument.Storage` 控制:
|
|
24
|
+
* Merge source order is controlled by `$argument.Storage`:
|
|
25
|
+
* - `undefined`(默认): `database[name]` -> `$argument` -> `PersistentStore[name]`
|
|
26
|
+
* - `$argument`: `database[name]` -> `PersistentStore[name]` -> `$argument`
|
|
27
|
+
* - `PersistentStore` / `BoxJs`: `database[name]` -> `PersistentStore[name]`
|
|
28
|
+
* - `database`: 仅 `database[name]`
|
|
29
|
+
*
|
|
30
|
+
* @since 2.1.2
|
|
27
31
|
* @link https://github.com/NanoCat-Me/utils/blob/main/getStorage.mjs
|
|
28
32
|
* @author VirgilClyne
|
|
29
33
|
* @param {string} key 持久化主键 / Persistent store key.
|
|
@@ -36,36 +40,63 @@ export function getStorage(key, names, database) {
|
|
|
36
40
|
Console.debug("☑️ getStorage");
|
|
37
41
|
names = [names].flat(Number.POSITIVE_INFINITY);
|
|
38
42
|
/***************** Default *****************/
|
|
39
|
-
const
|
|
40
|
-
Console.debug("Default", `
|
|
41
|
-
/*****************
|
|
43
|
+
const Root = { Settings: database?.Default?.Settings || {}, Configs: database?.Default?.Configs || {}, Caches: {} };
|
|
44
|
+
Console.debug("Default", `Root.Settings类型: ${typeof Root.Settings}`, `Root.Settings: ${JSON.stringify(Root.Settings)}`);
|
|
45
|
+
/***************** PersistentStore *****************/
|
|
42
46
|
// 包装为局部变量,用完释放内存
|
|
43
|
-
// BoxJs的清空操作返回假值空字符串, 逻辑或操作符会在左侧操作数为假值时返回右侧操作数。
|
|
44
|
-
const
|
|
45
|
-
if (
|
|
46
|
-
Console.debug("☑️
|
|
47
|
+
// BoxJs 的清空操作返回假值空字符串, 逻辑或操作符会在左侧操作数为假值时返回右侧操作数。
|
|
48
|
+
const PersistentStore = Storage.getItem(key, {});
|
|
49
|
+
if (PersistentStore) {
|
|
50
|
+
Console.debug("☑️ PersistentStore", `PersistentStore类型: ${typeof PersistentStore}`, `PersistentStore内容: ${JSON.stringify(PersistentStore || {})}`);
|
|
47
51
|
names.forEach(name => {
|
|
48
|
-
if (typeof
|
|
49
|
-
|
|
52
|
+
if (typeof PersistentStore?.[name]?.Settings === "string") {
|
|
53
|
+
PersistentStore[name].Settings = JSON.parse(PersistentStore[name].Settings || "{}");
|
|
50
54
|
}
|
|
51
|
-
if (typeof
|
|
52
|
-
|
|
55
|
+
if (typeof PersistentStore?.[name]?.Caches === "string") {
|
|
56
|
+
PersistentStore[name].Caches = JSON.parse(PersistentStore[name].Caches || "{}");
|
|
53
57
|
}
|
|
54
58
|
});
|
|
55
|
-
if (
|
|
56
|
-
Console.debug("✅
|
|
59
|
+
if (PersistentStore.LogLevel) Console.logLevel = PersistentStore.LogLevel;
|
|
60
|
+
Console.debug("✅ PersistentStore", `Root.Settings类型: ${typeof Root.Settings}`, `Root.Settings: ${JSON.stringify(Root.Settings)}`);
|
|
57
61
|
}
|
|
58
62
|
/***************** Merge *****************/
|
|
59
63
|
names.forEach(name => {
|
|
60
|
-
_.merge(
|
|
61
|
-
_.merge(
|
|
62
|
-
_.merge(Store.Caches, BoxJs?.[name]?.Caches);
|
|
64
|
+
_.merge(Root.Configs, database?.[name]?.Configs);
|
|
65
|
+
_.merge(Root.Caches, PersistentStore?.[name]?.Caches);
|
|
63
66
|
});
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
switch ($argument.Storage) {
|
|
68
|
+
case "$argument":
|
|
69
|
+
names.forEach(name => {
|
|
70
|
+
_.merge(Root.Settings, database?.[name]?.Settings, PersistentStore?.[name]?.Settings);
|
|
71
|
+
});
|
|
72
|
+
_.merge(Root.Settings, $argument);
|
|
73
|
+
break;
|
|
74
|
+
case "BoxJs":
|
|
75
|
+
case "PersistentStore":
|
|
76
|
+
names.forEach(name => {
|
|
77
|
+
_.merge(Root.Settings, database?.[name]?.Settings, PersistentStore?.[name]?.Settings);
|
|
78
|
+
});
|
|
79
|
+
break;
|
|
80
|
+
case "database":
|
|
81
|
+
names.forEach(name => {
|
|
82
|
+
_.merge(Root.Settings, database?.[name]?.Settings);
|
|
83
|
+
});
|
|
84
|
+
break;
|
|
85
|
+
default:
|
|
86
|
+
case undefined:
|
|
87
|
+
names.forEach(name => {
|
|
88
|
+
_.merge(Root.Settings, database?.[name]?.Settings);
|
|
89
|
+
});
|
|
90
|
+
_.merge(Root.Settings, $argument);
|
|
91
|
+
names.forEach(name => {
|
|
92
|
+
_.merge(Root.Settings, PersistentStore?.[name]?.Settings);
|
|
93
|
+
});
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
if (Root.Settings.LogLevel) Console.logLevel = Root.Settings.LogLevel;
|
|
97
|
+
Console.debug("✅ Merge", `Root.Settings类型: ${typeof Root.Settings}`, `Root.Settings: ${JSON.stringify(Root.Settings)}`);
|
|
67
98
|
/***************** traverseObject *****************/
|
|
68
|
-
traverseObject(
|
|
99
|
+
traverseObject(Root.Settings, (key, value) => {
|
|
69
100
|
Console.debug("☑️ traverseObject", `${key}: ${typeof value}`, `${key}: ${JSON.stringify(value)}`);
|
|
70
101
|
if (value === "true" || value === "false")
|
|
71
102
|
value = JSON.parse(value); // 字符串转Boolean
|
|
@@ -76,9 +107,9 @@ export function getStorage(key, names, database) {
|
|
|
76
107
|
}
|
|
77
108
|
return value;
|
|
78
109
|
});
|
|
79
|
-
Console.debug("✅ traverseObject", `
|
|
110
|
+
Console.debug("✅ traverseObject", `Root.Settings类型: ${typeof Root.Settings}`, `Root.Settings: ${JSON.stringify(Root.Settings)}`);
|
|
80
111
|
Console.debug("✅ getStorage");
|
|
81
|
-
return
|
|
112
|
+
return Root;
|
|
82
113
|
}
|
|
83
114
|
|
|
84
115
|
/**
|
package/lib/argument.mjs
CHANGED
|
@@ -18,25 +18,37 @@ import { Lodash as _ } from "../polyfill/Lodash.mjs";
|
|
|
18
18
|
* Execution timing:
|
|
19
19
|
* - 该模块为即时执行模块,`import` 时立即处理全局 `$argument`
|
|
20
20
|
* - This module executes immediately and mutates global `$argument` on import
|
|
21
|
+
*
|
|
22
|
+
* 归一化规则补充:
|
|
23
|
+
* Normalization details:
|
|
24
|
+
* - 使用 `globalThis.$argument` 读写,避免运行环境下未声明变量引用问题
|
|
25
|
+
* - Read/write via `globalThis.$argument` to avoid undeclared variable access
|
|
26
|
+
* - 当 `$argument` 为 `null` 或 `undefined` 时,会重置为 `{}`
|
|
27
|
+
* - When `$argument` is `null` or `undefined`, it is normalized to `{}`
|
|
21
28
|
*/
|
|
22
29
|
(() => {
|
|
23
30
|
Console.debug("☑️ $argument");
|
|
24
|
-
switch (typeof
|
|
31
|
+
switch (typeof globalThis.$argument) {
|
|
25
32
|
case "string": {
|
|
26
|
-
const argument = Object.fromEntries(
|
|
27
|
-
|
|
28
|
-
Object.keys(argument).forEach(key => _.set(
|
|
33
|
+
const argument = Object.fromEntries(globalThis.$argument.split("&").map(item => item.split("=", 2).map(i => i.replace(/\"/g, ""))));
|
|
34
|
+
globalThis.$argument = {};
|
|
35
|
+
Object.keys(argument).forEach(key => _.set(globalThis.$argument, key, argument[key]));
|
|
29
36
|
break;
|
|
30
37
|
}
|
|
31
38
|
case "object": {
|
|
39
|
+
if (globalThis.$argument === null) {
|
|
40
|
+
globalThis.$argument = {};
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
32
43
|
const argument = {};
|
|
33
|
-
Object.keys(
|
|
34
|
-
|
|
44
|
+
Object.keys(globalThis.$argument).forEach(key => _.set(argument, key, globalThis.$argument[key]));
|
|
45
|
+
globalThis.$argument = argument;
|
|
35
46
|
break;
|
|
36
47
|
}
|
|
37
48
|
case "undefined":
|
|
49
|
+
globalThis.$argument = {};
|
|
38
50
|
break;
|
|
39
51
|
}
|
|
40
|
-
if (
|
|
41
|
-
Console.debug("✅ $argument", `$argument: ${JSON.stringify(
|
|
52
|
+
if (globalThis.$argument.LogLevel) Console.logLevel = globalThis.$argument.LogLevel;
|
|
53
|
+
Console.debug("✅ $argument", `$argument: ${JSON.stringify(globalThis.$argument)}`);
|
|
42
54
|
})();
|
package/package.json
CHANGED
package/polyfill/Lodash.mjs
CHANGED
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
* - This is a simplified subset, not a full Lodash implementation
|
|
10
10
|
* - 各方法语义可参考 Lodash 官方文档
|
|
11
11
|
* - Method semantics can be referenced from official Lodash docs
|
|
12
|
+
* - 导入时建议使用 `Lodash as _`,遵循 lodash 官方示例惯例
|
|
13
|
+
* - Use `Lodash as _` when importing, following official lodash example convention
|
|
12
14
|
*
|
|
13
15
|
* 参考:
|
|
14
16
|
* Reference:
|
|
@@ -22,6 +24,8 @@ export class Lodash {
|
|
|
22
24
|
*
|
|
23
25
|
* @param {string} string 输入文本 / Input text.
|
|
24
26
|
* @returns {string}
|
|
27
|
+
* @see {@link https://lodash.com/docs/#escape lodash.escape}
|
|
28
|
+
* @see {@link https://www.lodashjs.com/docs/lodash.escape lodash.escape (中文)}
|
|
25
29
|
*/
|
|
26
30
|
static escape(string) {
|
|
27
31
|
const map = {
|
|
@@ -42,6 +46,8 @@ export class Lodash {
|
|
|
42
46
|
* @param {string|string[]} [path=""] 路径 / Path.
|
|
43
47
|
* @param {*} [defaultValue=undefined] 默认值 / Default value.
|
|
44
48
|
* @returns {*}
|
|
49
|
+
* @see {@link https://lodash.com/docs/#get lodash.get}
|
|
50
|
+
* @see {@link https://www.lodashjs.com/docs/lodash.get lodash.get (中文)}
|
|
45
51
|
*/
|
|
46
52
|
static get(object = {}, path = "", defaultValue = undefined) {
|
|
47
53
|
// translate array case to dot case, then split with .
|
|
@@ -80,6 +86,8 @@ export class Lodash {
|
|
|
80
86
|
* @param {...object} sources - Source objects.
|
|
81
87
|
* @returns {object} 返回合并后的目标对象
|
|
82
88
|
* @returns {object} Merged target object.
|
|
89
|
+
* @see {@link https://lodash.com/docs/#merge lodash.merge}
|
|
90
|
+
* @see {@link https://www.lodashjs.com/docs/lodash.merge lodash.merge (中文)}
|
|
83
91
|
* @example
|
|
84
92
|
* const target = { a: { b: 1 }, c: 2 };
|
|
85
93
|
* const source = { a: { d: 3 }, e: 4 };
|
|
@@ -141,6 +149,8 @@ export class Lodash {
|
|
|
141
149
|
* @param {*} value - Value to check.
|
|
142
150
|
* @returns {boolean} 如果是普通对象返回 true
|
|
143
151
|
* @returns {boolean} Returns true when value is a plain object.
|
|
152
|
+
* @see {@link https://lodash.com/docs/#isPlainObject lodash.isPlainObject}
|
|
153
|
+
* @see {@link https://www.lodashjs.com/docs/lodash.isPlainObject lodash.isPlainObject (中文)}
|
|
144
154
|
*/
|
|
145
155
|
static #isPlainObject(value) {
|
|
146
156
|
if (value === null || typeof value !== "object") return false;
|
|
@@ -155,6 +165,8 @@ export class Lodash {
|
|
|
155
165
|
* @param {object} [object={}] 目标对象 / Target object.
|
|
156
166
|
* @param {string|string[]} [paths=[]] 要删除的路径 / Paths to remove.
|
|
157
167
|
* @returns {object}
|
|
168
|
+
* @see {@link https://lodash.com/docs/#omit lodash.omit}
|
|
169
|
+
* @see {@link https://www.lodashjs.com/docs/lodash.omit lodash.omit (中文)}
|
|
158
170
|
*/
|
|
159
171
|
static omit(object = {}, paths = []) {
|
|
160
172
|
if (!Array.isArray(paths)) paths = [paths.toString()];
|
|
@@ -169,6 +181,8 @@ export class Lodash {
|
|
|
169
181
|
* @param {object} [object={}] 目标对象 / Target object.
|
|
170
182
|
* @param {string|string[]} [paths=[]] 需要保留的键 / Keys to keep.
|
|
171
183
|
* @returns {object}
|
|
184
|
+
* @see {@link https://lodash.com/docs/#pick lodash.pick}
|
|
185
|
+
* @see {@link https://www.lodashjs.com/docs/lodash.pick lodash.pick (中文)}
|
|
172
186
|
*/
|
|
173
187
|
static pick(object = {}, paths = []) {
|
|
174
188
|
if (!Array.isArray(paths)) paths = [paths.toString()];
|
|
@@ -184,6 +198,8 @@ export class Lodash {
|
|
|
184
198
|
* @param {string|string[]} path 路径 / Path.
|
|
185
199
|
* @param {*} value 写入值 / Value.
|
|
186
200
|
* @returns {object}
|
|
201
|
+
* @see {@link https://lodash.com/docs/#set lodash.set}
|
|
202
|
+
* @see {@link https://www.lodashjs.com/docs/lodash.set lodash.set (中文)}
|
|
187
203
|
*/
|
|
188
204
|
static set(object, path, value) {
|
|
189
205
|
if (!Array.isArray(path)) path = Lodash.toPath(path);
|
|
@@ -197,6 +213,8 @@ export class Lodash {
|
|
|
197
213
|
*
|
|
198
214
|
* @param {string} value 路径字符串 / Path string.
|
|
199
215
|
* @returns {string[]}
|
|
216
|
+
* @see {@link https://lodash.com/docs/#toPath lodash.toPath}
|
|
217
|
+
* @see {@link https://www.lodashjs.com/docs/lodash.toPath lodash.toPath (中文)}
|
|
200
218
|
*/
|
|
201
219
|
static toPath(value) {
|
|
202
220
|
return value
|
|
@@ -211,6 +229,8 @@ export class Lodash {
|
|
|
211
229
|
*
|
|
212
230
|
* @param {string} string 输入文本 / Input text.
|
|
213
231
|
* @returns {string}
|
|
232
|
+
* @see {@link https://lodash.com/docs/#unescape lodash.unescape}
|
|
233
|
+
* @see {@link https://www.lodashjs.com/docs/lodash.unescape lodash.unescape (中文)}
|
|
214
234
|
*/
|
|
215
235
|
static unescape(string) {
|
|
216
236
|
const map = {
|
|
@@ -230,6 +250,8 @@ export class Lodash {
|
|
|
230
250
|
* @param {object} [object={}] 目标对象 / Target object.
|
|
231
251
|
* @param {string|string[]} [path=""] 路径 / Path.
|
|
232
252
|
* @returns {boolean}
|
|
253
|
+
* @see {@link https://lodash.com/docs/#unset lodash.unset}
|
|
254
|
+
* @see {@link https://www.lodashjs.com/docs/lodash.unset lodash.unset (中文)}
|
|
233
255
|
*/
|
|
234
256
|
static unset(object = {}, path = "") {
|
|
235
257
|
if (!Array.isArray(path)) path = Lodash.toPath(path);
|
package/polyfill/Storage.mjs
CHANGED
|
@@ -172,6 +172,12 @@ export class Storage {
|
|
|
172
172
|
* 删除存储值。
|
|
173
173
|
* Remove value from persistent storage.
|
|
174
174
|
*
|
|
175
|
+
* 平台说明:
|
|
176
|
+
* Platform notes:
|
|
177
|
+
* - Quantumult X: `$prefs.removeValueForKey`
|
|
178
|
+
* - Surge: 通过 `$persistentStore.write(null, keyName)` 删除
|
|
179
|
+
* - 其余平台当前返回 `false`
|
|
180
|
+
*
|
|
175
181
|
* @param {string} keyName 键名或路径键 / Key or path key.
|
|
176
182
|
* @returns {boolean}
|
|
177
183
|
*/
|
|
@@ -190,6 +196,8 @@ export class Storage {
|
|
|
190
196
|
default:
|
|
191
197
|
switch ($app) {
|
|
192
198
|
case "Surge":
|
|
199
|
+
result = $persistentStore.write(null, keyName);
|
|
200
|
+
break;
|
|
193
201
|
case "Loon":
|
|
194
202
|
case "Stash":
|
|
195
203
|
case "Egern":
|