@nsnanocat/util 2.1.4 → 2.1.7

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 CHANGED
@@ -87,7 +87,7 @@ import {
87
87
  ### 仓库中存在但未从主入口导出
88
88
  - `lib/environment.mjs`
89
89
  - `lib/runScript.mjs`
90
- - `getStorage.mjs`(薯条项目自用,仅当你的存储结构与薯条项目一致时再使用)
90
+ - `getStorage.mjs`(薯条项目自用,仅当你的存储结构与薯条项目一致时再使用;请通过子路径 `@nsnanocat/util/getStorage.mjs` 导入)
91
91
 
92
92
  ## 模块依赖关系
93
93
 
@@ -331,7 +331,25 @@ await runScript("$done({})", { timeout: 20 });
331
331
 
332
332
  示例:
333
333
  ```js
334
- import { getStorage } from "@nsnanocat/util/getStorage.mjs";
334
+ import getStorage from "@nsnanocat/util/getStorage.mjs";
335
+
336
+ const store = getStorage("@my_box", ["YouTube", "Global"], database);
337
+ ```
338
+
339
+ #### 命名导出(辅助函数)
340
+
341
+ `getStorage.mjs` 同时导出以下辅助函数:
342
+ - `traverseObject(o, c)`:深度遍历对象并替换叶子值
343
+ - `string2number(string)`:将纯数字字符串转换为数字
344
+ - `value2array(value)`:字符串按逗号拆分;数字/布尔值会被包装为单元素数组
345
+
346
+ 示例:
347
+ ```js
348
+ import getStorage, {
349
+ traverseObject,
350
+ string2number,
351
+ value2array,
352
+ } from "@nsnanocat/util/getStorage.mjs";
335
353
 
336
354
  const store = getStorage("@my_box", ["YouTube", "Global"], database);
337
355
  ```
@@ -412,10 +430,12 @@ const store = getStorage("@my_box", ["YouTube", "Global"], database);
412
430
  #### `Storage.removeItem(keyName)`
413
431
  - Quantumult X:可用(`$prefs.removeValueForKey`)。
414
432
  - Surge:通过 `$persistentStore.write(null, keyName)` 删除。
415
- - Loon / Stash / Egern / Shadowrocket / Node.js:返回 `false`。
433
+ - Node.js:可用(删除 `box.dat` 中对应 key 并落盘)。
434
+ - Loon / Stash / Egern / Shadowrocket:返回 `false`。
416
435
 
417
436
  #### `Storage.clear()`
418
437
  - Quantumult X:可用(`$prefs.removeAllValues`)。
438
+ - Node.js:可用(清空 `box.dat` 并落盘)。
419
439
  - 其他平台:返回 `false`。
420
440
 
421
441
  #### Node.js 特性
@@ -424,7 +444,7 @@ const store = getStorage("@my_box", ["YouTube", "Global"], database);
424
444
 
425
445
  与 Web Storage 的行为差异:
426
446
  - 支持 `@key.path` 深路径读写(Web Storage 原生不支持)。
427
- - `removeItem/clear` 仅部分平台可用(目前为 Quantumult X,以及 Surge 的 `removeItem`)。
447
+ - `removeItem/clear` 仅部分平台可用(目前为 Quantumult X、Node.js,以及 Surge 的 `removeItem`)。
428
448
  - `getItem` 会尝试 `JSON.parse`,`setItem` 写入对象会 `JSON.stringify`。
429
449
 
430
450
  平台后端映射:
@@ -604,7 +624,7 @@ console.log(value); // 1
604
624
  | 通知 | `$notify` | `$notification.post` | `$notification.post` | `$notification.post` | `$notification.post` | `$notification.post` | 无 |
605
625
  | 持久化 | `$prefs` | `$persistentStore` | `$persistentStore` | `$persistentStore` | `$persistentStore` | `$persistentStore` | `box.dat` |
606
626
  | 结束脚本 | `$done` | `$done` | `$done` | `$done` | `$done` | `$done` | `process.exit(1)` |
607
- | `removeItem/clear` | 可用 | 不可用 | `removeItem` 可用 / `clear` 不可用 | 不可用 | 不可用 | 不可用 | 不可用 |
627
+ | `removeItem/clear` | 可用 | 不可用 | `removeItem` 可用 / `clear` 不可用 | 不可用 | 不可用 | 不可用 | 可用 |
608
628
  | `policy` 注入(`fetch/done`) | `opts.policy` | `node` | `X-Surge-Policy`(done) | `X-Stash-Selected-Proxy` | 无专门映射 | `X-Surge-Proxy`(fetch) | 无 |
609
629
 
610
630
  ## 已知限制与注意事项
package/getStorage.mjs CHANGED
@@ -36,8 +36,11 @@ import { Storage } from "./polyfill/Storage.mjs";
36
36
  * @param {string|string[]|Array<string|string[]>} names 目标配置名 / Target profile names.
37
37
  * @param {Record<string, any>} database 默认数据库 / Default database object.
38
38
  * @returns {StorageProfile}
39
+ *
40
+ * @module getStorage
41
+ * @default
39
42
  */
40
- export function getStorage(key, names, database) {
43
+ export default function getStorage(key, names, database) {
41
44
  if (database?.Default?.Settings?.LogLevel) Console.logLevel = database.Default.Settings.LogLevel;
42
45
  Console.debug("☑️ getStorage");
43
46
  names = [names].flat(Number.POSITIVE_INFINITY);
@@ -103,12 +106,20 @@ export function getStorage(key, names, database) {
103
106
  /***************** traverseObject *****************/
104
107
  traverseObject(Root.Settings, (key, value) => {
105
108
  Console.debug("☑️ traverseObject", `${key}: ${typeof value}`, `${key}: ${JSON.stringify(value)}`);
106
- if (value === "true" || value === "false")
107
- value = JSON.parse(value); // 字符串转Boolean
108
- else if (typeof value === "string") {
109
- if (value.includes(","))
110
- value = value.split(",").map(item => string2number(item)); // 字符串转数组转数字
111
- else value = string2number(value); // 字符串转数字
109
+ switch (typeof value) {
110
+ case "string":
111
+ switch (value) {
112
+ case "true":
113
+ case "false":
114
+ case "[]":
115
+ value = JSON.parse(value); // 字符串转Boolean/空数组
116
+ break;
117
+ default:
118
+ if (value.includes(","))
119
+ value = value2array(value).map(item => string2number(item)); // 字符串转数组转数字
120
+ else value = string2number(value); // 字符串转数字
121
+ }
122
+ break;
112
123
  }
113
124
  return value;
114
125
  });
@@ -125,7 +136,7 @@ export function getStorage(key, names, database) {
125
136
  * @param {(key: string, value: any) => any} c 处理回调 / Transformer callback.
126
137
  * @returns {Record<string, any>}
127
138
  */
128
- function traverseObject(o, c) {
139
+ export function traverseObject(o, c) {
129
140
  for (const t in o) {
130
141
  const n = o[t];
131
142
  o[t] = "object" === typeof n && null !== n ? traverseObject(n, c) : c(t, n);
@@ -140,7 +151,26 @@ function traverseObject(o, c) {
140
151
  * @param {string} string 输入字符串 / Input string.
141
152
  * @returns {string|number}
142
153
  */
143
- function string2number(string) {
154
+ export function string2number(string) {
144
155
  if (/^\d+$/.test(string)) string = Number.parseInt(string, 10);
145
156
  return string;
146
157
  }
158
+
159
+ /**
160
+ * 将值包装为数组。
161
+ * Split value into array.
162
+ *
163
+ * @param {string|number|boolean|string[]|null|undefined} value 输入值 / Input value.
164
+ * @returns {(string|number|boolean)[]}
165
+ */
166
+ export function value2array(value) {
167
+ switch (typeof value) {
168
+ case "string":
169
+ return value.split(",");
170
+ case "number":
171
+ case "boolean":
172
+ return [value];
173
+ default:
174
+ return value || [];
175
+ }
176
+ }
package/package.json CHANGED
@@ -14,6 +14,7 @@
14
14
  "license": "Apache-2.0",
15
15
  "bugs": "https://github.com/NSNanoCat/util/issues",
16
16
  "main": "index.js",
17
+ "types": "types/nsnanocat-util.d.ts",
17
18
  "type": "module",
18
19
  "scripts": {
19
20
  "tsc:build": "npx tsc",
@@ -30,7 +31,8 @@
30
31
  "index.js",
31
32
  "lib",
32
33
  "polyfill",
33
- "getStorage.mjs"
34
+ "getStorage.mjs",
35
+ "types"
34
36
  ],
35
37
  "devDependencies": {
36
38
  "typescript": "^5.6.3"
@@ -39,5 +41,5 @@
39
41
  "registry": "https://registry.npmjs.org/",
40
42
  "access": "public"
41
43
  },
42
- "version": "2.1.4"
44
+ "version": "2.1.7"
43
45
  }
@@ -208,7 +208,11 @@ export class Storage {
208
208
  result = $prefs.removeValueForKey(keyName);
209
209
  break;
210
210
  case "Node.js":
211
- result = false;
211
+ // result = false;
212
+ Storage.data = Storage.#loaddata(Storage.dataFile);
213
+ delete Storage.data[keyName];
214
+ Storage.#writedata(Storage.dataFile);
215
+ result = true;
212
216
  break;
213
217
  default:
214
218
  result = false;
@@ -239,7 +243,11 @@ export class Storage {
239
243
  result = $prefs.removeAllValues();
240
244
  break;
241
245
  case "Node.js":
242
- result = false;
246
+ // result = false;
247
+ Storage.data = Storage.#loaddata(Storage.dataFile);
248
+ Storage.data = {};
249
+ Storage.#writedata(Storage.dataFile);
250
+ result = true;
243
251
  break;
244
252
  default:
245
253
  result = false;
@@ -0,0 +1,143 @@
1
+ declare module "@nsnanocat/util" {
2
+ export type AppName = "Quantumult X" | "Loon" | "Shadowrocket" | "Node.js" | "Egern" | "Surge" | "Stash";
3
+
4
+ export const $app: AppName | undefined;
5
+ export const $argument: Record<string, unknown>;
6
+ export const argument: typeof $argument;
7
+
8
+ export interface DonePayload {
9
+ status?: number | string;
10
+ url?: string;
11
+ headers?: Record<string, unknown>;
12
+ body?: string | ArrayBuffer | ArrayBufferView;
13
+ bodyBytes?: ArrayBuffer;
14
+ policy?: string;
15
+ }
16
+
17
+ export function done(object?: DonePayload): void;
18
+
19
+ export interface NotificationContentObject {
20
+ open?: string;
21
+ "open-url"?: string;
22
+ url?: string;
23
+ openUrl?: string;
24
+ copy?: string;
25
+ "update-pasteboard"?: string;
26
+ updatePasteboard?: string;
27
+ media?: string;
28
+ "media-url"?: string;
29
+ mediaUrl?: string;
30
+ mime?: string;
31
+ "auto-dismiss"?: number;
32
+ sound?: string;
33
+ }
34
+
35
+ export type NotificationContent = NotificationContentObject | string | number | boolean;
36
+
37
+ export function notification(
38
+ title?: string,
39
+ subtitle?: string,
40
+ body?: string,
41
+ content?: NotificationContent,
42
+ ): void;
43
+
44
+ export function time(format: string, ts?: number): string;
45
+ export function wait(delay?: number): Promise<void>;
46
+
47
+ export interface FetchRequest {
48
+ url: string;
49
+ method?: string;
50
+ headers?: Record<string, unknown>;
51
+ body?: string | ArrayBuffer | ArrayBufferView | object;
52
+ bodyBytes?: ArrayBuffer;
53
+ timeout?: number | string;
54
+ policy?: string;
55
+ redirection?: boolean;
56
+ "auto-redirect"?: boolean;
57
+ opts?: Record<string, unknown>;
58
+ [key: string]: unknown;
59
+ }
60
+
61
+ export interface FetchResponse {
62
+ ok: boolean;
63
+ status: number;
64
+ statusCode?: number;
65
+ statusText?: string;
66
+ headers?: Record<string, unknown>;
67
+ body?: string | ArrayBuffer;
68
+ bodyBytes?: ArrayBuffer;
69
+ [key: string]: unknown;
70
+ }
71
+
72
+ export function fetch(resource: FetchRequest | string, options?: Partial<FetchRequest>): Promise<FetchResponse>;
73
+
74
+ export class Console {
75
+ static clear(): void;
76
+ static count(label?: string): void;
77
+ static countReset(label?: string): void;
78
+ static debug(...msg: unknown[]): void;
79
+ static error(...msg: unknown[]): void;
80
+ static exception(...msg: unknown[]): void;
81
+ static group(label: string): number;
82
+ static groupEnd(): string | undefined;
83
+ static info(...msg: unknown[]): void;
84
+ static get logLevel(): "OFF" | "ERROR" | "WARN" | "INFO" | "DEBUG" | "ALL";
85
+ static set logLevel(level: number | string);
86
+ static log(...msg: unknown[]): void;
87
+ static time(label?: string): Map<string, number>;
88
+ static timeEnd(label?: string): boolean;
89
+ static timeLog(label?: string): void;
90
+ static warn(...msg: unknown[]): void;
91
+ }
92
+
93
+ export class Lodash {
94
+ static escape(string: string): string;
95
+ static get<T = unknown, D = undefined>(object?: Record<string, unknown>, path?: string | string[], defaultValue?: D): T | D;
96
+ static merge<T extends Record<string, unknown>>(object: T, ...sources: Array<Record<string, unknown> | null | undefined>): T;
97
+ static omit<T extends Record<string, unknown>>(object?: T, paths?: string | string[]): T;
98
+ static pick<T extends Record<string, unknown>, K extends keyof T>(object?: T, paths?: K | K[]): Pick<T, K>;
99
+ static set<T extends Record<string, unknown>>(object: T, path: string | string[], value: unknown): T;
100
+ static toPath(value: string): string[];
101
+ static unescape(string: string): string;
102
+ static unset(object?: Record<string, unknown>, path?: string | string[]): boolean;
103
+ }
104
+
105
+ export const StatusTexts: Record<number, string>;
106
+
107
+ export class Storage {
108
+ static data: Record<string, unknown> | null;
109
+ static dataFile: string;
110
+ static getItem<T = unknown>(keyName: string, defaultValue?: T): T;
111
+ static setItem(keyName: string, keyValue: unknown): boolean;
112
+ static removeItem(keyName: string): boolean;
113
+ static clear(): boolean;
114
+ }
115
+ }
116
+
117
+ declare module "@nsnanocat/util/getStorage.mjs" {
118
+ export interface StorageProfile {
119
+ Settings: Record<string, unknown>;
120
+ Configs: Record<string, unknown>;
121
+ Caches: Record<string, unknown>;
122
+ }
123
+
124
+ export function traverseObject(
125
+ o: Record<string, unknown>,
126
+ c: (key: string, value: unknown) => unknown,
127
+ ): Record<string, unknown>;
128
+
129
+ export function string2number(string: string): string | number;
130
+
131
+ export function value2array(value: string | number | boolean | string[] | null | undefined): Array<string | number | boolean>;
132
+
133
+ export default function getStorage(
134
+ key: string,
135
+ names: string | string[] | Array<string | string[]>,
136
+ database: Record<string, unknown>,
137
+ ): StorageProfile;
138
+ }
139
+
140
+ declare module "@nsnanocat/util/lib/environment.mjs" {
141
+ export const $environment: Record<string, unknown>;
142
+ export function environment(): Record<string, unknown>;
143
+ }