@nsnanocat/util 2.0.0 → 2.1.1

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.
@@ -1,5 +1,28 @@
1
1
  /* https://www.lodashjs.com */
2
+ /**
3
+ * 轻量 Lodash 工具集。
4
+ * Lightweight Lodash-like utilities.
5
+ *
6
+ * 说明:
7
+ * Notes:
8
+ * - 这是 Lodash 的“部分方法”简化实现,不等价于完整 Lodash
9
+ * - This is a simplified subset, not a full Lodash implementation
10
+ * - 各方法语义可参考 Lodash 官方文档
11
+ * - Method semantics can be referenced from official Lodash docs
12
+ *
13
+ * 参考:
14
+ * Reference:
15
+ * - https://www.lodashjs.com
16
+ * - https://lodash.com
17
+ */
2
18
  export class Lodash {
19
+ /**
20
+ * HTML 特殊字符转义。
21
+ * Escape HTML special characters.
22
+ *
23
+ * @param {string} string 输入文本 / Input text.
24
+ * @returns {string}
25
+ */
3
26
  static escape(string) {
4
27
  const map = {
5
28
  "&": "&",
@@ -11,6 +34,15 @@ export class Lodash {
11
34
  return string.replace(/[&<>"']/g, m => map[m]);
12
35
  }
13
36
 
37
+ /**
38
+ * 按路径读取对象值。
39
+ * Get object value by path.
40
+ *
41
+ * @param {object} [object={}] 目标对象 / Target object.
42
+ * @param {string|string[]} [path=""] 路径 / Path.
43
+ * @param {*} [defaultValue=undefined] 默认值 / Default value.
44
+ * @returns {*}
45
+ */
14
46
  static get(object = {}, path = "", defaultValue = undefined) {
15
47
  // translate array case to dot case, then split with .
16
48
  // a[0].b -> a.0.b -> ['a', '0', 'b']
@@ -24,7 +56,9 @@ export class Lodash {
24
56
 
25
57
  /**
26
58
  * 递归合并源对象的自身可枚举属性到目标对象
59
+ * Recursively merge source enumerable properties into target object.
27
60
  * @description 简化版 lodash.merge,用于合并配置对象
61
+ * @description A simplified lodash.merge for config merging.
28
62
  *
29
63
  * 适用情况:
30
64
  * - 合并嵌套的配置/设置对象
@@ -41,8 +75,11 @@ export class Lodash {
41
75
  * - 会修改原始目标对象 (mutates target)
42
76
  *
43
77
  * @param {object} object - 目标对象
78
+ * @param {object} object - Target object.
44
79
  * @param {...object} sources - 源对象(可多个)
80
+ * @param {...object} sources - Source objects.
45
81
  * @returns {object} 返回合并后的目标对象
82
+ * @returns {object} Merged target object.
46
83
  * @example
47
84
  * const target = { a: { b: 1 }, c: 2 };
48
85
  * const source = { a: { d: 3 }, e: 4 };
@@ -99,8 +136,11 @@ export class Lodash {
99
136
 
100
137
  /**
101
138
  * 判断值是否为普通对象 (Plain Object)
139
+ * Check whether a value is a plain object.
102
140
  * @param {*} value - 要检查的值
141
+ * @param {*} value - Value to check.
103
142
  * @returns {boolean} 如果是普通对象返回 true
143
+ * @returns {boolean} Returns true when value is a plain object.
104
144
  */
105
145
  static #isPlainObject(value) {
106
146
  if (value === null || typeof value !== "object") return false;
@@ -108,24 +148,56 @@ export class Lodash {
108
148
  return proto === null || proto === Object.prototype;
109
149
  }
110
150
 
151
+ /**
152
+ * 删除对象指定路径并返回对象。
153
+ * Omit paths from object and return the same object.
154
+ *
155
+ * @param {object} [object={}] 目标对象 / Target object.
156
+ * @param {string|string[]} [paths=[]] 要删除的路径 / Paths to remove.
157
+ * @returns {object}
158
+ */
111
159
  static omit(object = {}, paths = []) {
112
160
  if (!Array.isArray(paths)) paths = [paths.toString()];
113
161
  paths.forEach(path => Lodash.unset(object, path));
114
162
  return object;
115
163
  }
116
164
 
165
+ /**
166
+ * 仅保留对象指定键(第一层)。
167
+ * Pick selected keys from object (top level only).
168
+ *
169
+ * @param {object} [object={}] 目标对象 / Target object.
170
+ * @param {string|string[]} [paths=[]] 需要保留的键 / Keys to keep.
171
+ * @returns {object}
172
+ */
117
173
  static pick(object = {}, paths = []) {
118
174
  if (!Array.isArray(paths)) paths = [paths.toString()];
119
175
  const filteredEntries = Object.entries(object).filter(([key, value]) => paths.includes(key));
120
176
  return Object.fromEntries(filteredEntries);
121
177
  }
122
178
 
179
+ /**
180
+ * 按路径写入对象值。
181
+ * Set object value by path.
182
+ *
183
+ * @param {object} object 目标对象 / Target object.
184
+ * @param {string|string[]} path 路径 / Path.
185
+ * @param {*} value 写入值 / Value.
186
+ * @returns {object}
187
+ */
123
188
  static set(object, path, value) {
124
189
  if (!Array.isArray(path)) path = Lodash.toPath(path);
125
190
  path.slice(0, -1).reduce((previousValue, currentValue, currentIndex) => (Object(previousValue[currentValue]) === previousValue[currentValue] ? previousValue[currentValue] : (previousValue[currentValue] = /^\d+$/.test(path[currentIndex + 1]) ? [] : {})), object)[path[path.length - 1]] = value;
126
191
  return object;
127
192
  }
128
193
 
194
+ /**
195
+ * 将点路径或数组下标路径转换为数组。
196
+ * Convert dot/array-index path string into path segments.
197
+ *
198
+ * @param {string} value 路径字符串 / Path string.
199
+ * @returns {string[]}
200
+ */
129
201
  static toPath(value) {
130
202
  return value
131
203
  .replace(/\[(\d+)\]/g, ".$1")
@@ -133,6 +205,13 @@ export class Lodash {
133
205
  .filter(Boolean);
134
206
  }
135
207
 
208
+ /**
209
+ * HTML 实体反转义。
210
+ * Unescape HTML entities.
211
+ *
212
+ * @param {string} string 输入文本 / Input text.
213
+ * @returns {string}
214
+ */
136
215
  static unescape(string) {
137
216
  const map = {
138
217
  "&amp;": "&",
@@ -144,6 +223,14 @@ export class Lodash {
144
223
  return string.replace(/&amp;|&lt;|&gt;|&quot;|&#39;/g, m => map[m]);
145
224
  }
146
225
 
226
+ /**
227
+ * 删除对象路径对应的值。
228
+ * Remove value by object path.
229
+ *
230
+ * @param {object} [object={}] 目标对象 / Target object.
231
+ * @param {string|string[]} [path=""] 路径 / Path.
232
+ * @returns {boolean}
233
+ */
147
234
  static unset(object = {}, path = "") {
148
235
  if (!Array.isArray(path)) path = Lodash.toPath(path);
149
236
  const result = path.reduce((previousValue, currentValue, currentIndex) => {
@@ -1,3 +1,20 @@
1
+ /**
2
+ * HTTP 状态码文本映射表。
3
+ * HTTP status code to status text map.
4
+ *
5
+ * 主要用途:
6
+ * Primary usage:
7
+ * - 为 Quantumult X 的 `$done` 状态行拼接提供状态文本
8
+ * - Provide status text for Quantumult X `$done` status-line composition
9
+ * - QX 在部分场景要求 `status` 为完整状态行(如 `HTTP/1.1 200 OK`)
10
+ * - QX may require full status line (e.g. `HTTP/1.1 200 OK`) in some cases
11
+ *
12
+ * 参考:
13
+ * Reference:
14
+ * - https://github.com/crossutility/Quantumult-X/raw/refs/heads/master/sample-rewrite-response-header.js
15
+ *
16
+ * @type {Record<number, string>}
17
+ */
1
18
  export const StatusTexts = {
2
19
  100: "Continue",
3
20
  101: "Switching Protocols",
@@ -2,36 +2,70 @@ import { $app } from "../lib/app.mjs";
2
2
  import { Lodash as _ } from "./Lodash.mjs";
3
3
 
4
4
  /**
5
- * Storage
5
+ * 跨平台持久化存储适配器。
6
+ * Cross-platform persistent storage adapter.
6
7
  *
7
- * @link https://developer.mozilla.org/zh-CN/docs/Web/API/Storage/setItem
8
- * @export
9
- * @class Storage
10
- * @typedef {Storage}
8
+ * 设计目标:
9
+ * Design goal:
10
+ * - 仿照 Web Storage (`Storage`) 接口设计
11
+ * - Modeled after Web Storage (`Storage`) interface
12
+ * - 统一 VPN App 脚本环境中的持久化读写接口
13
+ * - Unify persistence APIs across VPN app script environments
14
+ *
15
+ * 支持后端:
16
+ * Supported backends:
17
+ * - Surge/Loon/Stash/Egern/Shadowrocket: `$persistentStore`
18
+ * - Quantumult X: `$prefs`
19
+ * - Node.js: 本地 `box.dat`
20
+ * - Node.js: local `box.dat`
21
+ *
22
+ * 支持路径键:
23
+ * Supports path key:
24
+ * - `@root.path.to.value`
25
+ *
26
+ * 与 Web Storage 的已知差异:
27
+ * Known differences from Web Storage:
28
+ * - 支持 `@key.path` 深路径读写(Web Storage 原生不支持)
29
+ * - Supports `@key.path` deep-path access (not native in Web Storage)
30
+ * - `removeItem/clear` 并非所有平台都可用
31
+ * - `removeItem/clear` are not available on every platform
32
+ * - 读取时会尝试 `JSON.parse`,写入对象会 `JSON.stringify`
33
+ * - Reads try `JSON.parse`, writes stringify objects
34
+ *
35
+ * @link https://developer.mozilla.org/en-US/docs/Web/API/Storage
36
+ * @link https://developer.mozilla.org/zh-CN/docs/Web/API/Storage
11
37
  */
12
38
  export class Storage {
13
39
  /**
14
- * data
40
+ * Node.js 环境下的内存数据缓存。
41
+ * In-memory data cache for Node.js runtime.
15
42
  *
16
- * @static
17
- * @type {file}
43
+ * @type {Record<string, any>|null}
18
44
  */
19
45
  static data = null;
46
+
47
+ /**
48
+ * Node.js 持久化文件名。
49
+ * Data file name used in Node.js.
50
+ *
51
+ * @type {string}
52
+ */
20
53
  static dataFile = "box.dat";
54
+
21
55
  /**
22
- * nameRegex
56
+ * `@key.path` 解析正则。
57
+ * Regex for `@key.path` parsing.
23
58
  *
24
- * @static
25
- * @type {regexp}
59
+ * @type {RegExp}
26
60
  */
27
61
  static #nameRegex = /^@(?<key>[^.]+)(?:\.(?<path>.*))?$/;
28
62
 
29
63
  /**
30
- * getItem
64
+ * 读取存储值。
65
+ * Read value from persistent storage.
31
66
  *
32
- * @static
33
- * @param {string} keyName
34
- * @param {*} [defaultValue]
67
+ * @param {string} keyName 键名或路径键 / Key or path key.
68
+ * @param {*} [defaultValue=null] 默认值 / Default value when key is missing.
35
69
  * @returns {*}
36
70
  */
37
71
  static getItem(keyName, defaultValue = null) {
@@ -80,11 +114,11 @@ export class Storage {
80
114
  }
81
115
 
82
116
  /**
83
- * setItem
117
+ * 写入存储值。
118
+ * Write value into persistent storage.
84
119
  *
85
- * @static
86
- * @param {string} keyName
87
- * @param {*} keyValue
120
+ * @param {string} keyName 键名或路径键 / Key or path key.
121
+ * @param {*} keyValue 写入值 / Value to store.
88
122
  * @returns {boolean}
89
123
  */
90
124
  static setItem(keyName = new String(), keyValue = new String()) {
@@ -135,10 +169,10 @@ export class Storage {
135
169
  }
136
170
 
137
171
  /**
138
- * removeItem
172
+ * 删除存储值。
173
+ * Remove value from persistent storage.
139
174
  *
140
- * @static
141
- * @param {string} keyName
175
+ * @param {string} keyName 键名或路径键 / Key or path key.
142
176
  * @returns {boolean}
143
177
  */
144
178
  static removeItem(keyName) {
@@ -178,9 +212,9 @@ export class Storage {
178
212
  }
179
213
 
180
214
  /**
181
- * clear
215
+ * 清空存储(仅 Quantumult X 支持)。
216
+ * Clear storage (supported by Quantumult X only).
182
217
  *
183
- * @static
184
218
  * @returns {boolean}
185
219
  */
186
220
  static clear() {
@@ -207,10 +241,12 @@ export class Storage {
207
241
  }
208
242
 
209
243
  /**
210
- * #loaddata
244
+ * 从 Node.js 数据文件加载 JSON。
245
+ * Load JSON data from Node.js data file.
211
246
  *
212
- * @param {string} dataFile
213
- * @returns {*}
247
+ * @private
248
+ * @param {string} dataFile 数据文件名 / Data file name.
249
+ * @returns {Record<string, any>}
214
250
  */
215
251
  static #loaddata = dataFile => {
216
252
  if ($app === "Node.js") {
@@ -232,9 +268,12 @@ export class Storage {
232
268
  };
233
269
 
234
270
  /**
235
- * #writedata
271
+ * 将内存数据写入 Node.js 数据文件。
272
+ * Persist in-memory data to Node.js data file.
236
273
  *
237
- * @param {string} [dataFile=this.dataFile]
274
+ * @private
275
+ * @param {string} [dataFile=this.dataFile] 数据文件名 / Data file name.
276
+ * @returns {void}
238
277
  */
239
278
  static #writedata = (dataFile = this.dataFile) => {
240
279
  if ($app === "Node.js") {
@@ -4,14 +4,69 @@ import { Lodash as _ } from "./Lodash.mjs";
4
4
  import { StatusTexts } from "./StatusTexts.mjs";
5
5
 
6
6
  /**
7
- * fetch
7
+ * 统一请求参数。
8
+ * Unified request payload.
8
9
  *
9
- * @link https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API
10
- * @export
10
+ * @typedef {object} FetchRequest
11
+ * @property {string} url 请求地址 / Request URL.
12
+ * @property {string} [method] 请求方法 / HTTP method.
13
+ * @property {Record<string, any>} [headers] 请求头 / Request headers.
14
+ * @property {string|ArrayBuffer|ArrayBufferView|object} [body] 请求体 / Request body.
15
+ * @property {ArrayBuffer} [bodyBytes] 二进制请求体 / Binary request body.
16
+ * @property {number|string} [timeout] 超时(秒或毫秒)/ Timeout (seconds or milliseconds).
17
+ * @property {string} [policy] 指定策略 / Preferred policy.
18
+ * @property {boolean} [redirection] 是否跟随重定向 / Whether to follow redirects.
19
+ * @property {boolean} ["auto-redirect"] 平台重定向字段 / Platform redirect flag.
20
+ * @property {Record<string, any>} [opts] 平台扩展字段 / Platform extension fields.
21
+ */
22
+
23
+ /**
24
+ * 统一响应结构。
25
+ * Unified response payload.
26
+ *
27
+ * @typedef {object} FetchResponse
28
+ * @property {boolean} ok 请求是否成功 / Whether request is successful.
29
+ * @property {number} status 状态码 / HTTP status code.
30
+ * @property {number} [statusCode] 状态码别名 / Status code alias.
31
+ * @property {string} [statusText] 状态文本 / HTTP status text.
32
+ * @property {Record<string, any>} [headers] 响应头 / Response headers.
33
+ * @property {string|ArrayBuffer} [body] 响应体 / Response body.
34
+ * @property {ArrayBuffer} [bodyBytes] 二进制响应体 / Binary response body.
35
+ */
36
+
37
+ /**
38
+ * 跨平台 `fetch` 适配层。
39
+ * Cross-platform `fetch` adapter.
40
+ *
41
+ * 设计目标:
42
+ * Design goal:
43
+ * - 仿照 Web API `fetch`(`Window.fetch`)接口设计
44
+ * - Modeled after Web API `fetch` (`Window.fetch`)
45
+ * - 统一 VPN App 与 Node.js 环境中的请求调用
46
+ * - Unify request calls across VPN apps and Node.js
47
+ *
48
+ * 功能:
49
+ * Features:
50
+ * - 统一 Quantumult X / Loon / Surge / Stash / Egern / Shadowrocket / Node.js 请求接口
51
+ * - Normalize request APIs across Quantumult X / Loon / Surge / Stash / Egern / Shadowrocket / Node.js
52
+ * - 统一返回体字段(`ok/status/statusText/body/bodyBytes`)
53
+ * - Normalize response fields (`ok/status/statusText/body/bodyBytes`)
54
+ *
55
+ * 与 Web `fetch` 的已知差异:
56
+ * Known differences from Web `fetch`:
57
+ * - 支持 `policy`、`auto-redirect` 等平台扩展字段
58
+ * - Supports platform extension fields like `policy` and `auto-redirect`
59
+ * - 非浏览器平台通过 `$httpClient/$task` 实现,不是原生 Fetch 实现
60
+ * - Non-browser platforms use `$httpClient/$task` instead of native Fetch engine
61
+ * - 返回结构包含 `statusCode/bodyBytes` 等兼容字段
62
+ * - Response includes compatibility fields like `statusCode/bodyBytes`
63
+ *
64
+ * @link https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch
65
+ * @link https://developer.mozilla.org/zh-CN/docs/Web/API/Window/fetch
11
66
  * @async
12
- * @param {object|string} resource
13
- * @param {object} [options]
14
- * @returns {Promise<object>}
67
+ * @param {FetchRequest|string} resource 请求对象或 URL / Request object or URL string.
68
+ * @param {Partial<FetchRequest>} [options={}] 追加参数 / Extra options.
69
+ * @returns {Promise<FetchResponse>}
15
70
  */
16
71
  export async function fetch(resource, options = {}) {
17
72
  // 初始化参数