@nsnanocat/util 2.4.1 → 2.5.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.
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  核心目标:
6
6
  - 统一不同平台的 HTTP、通知、持久化、结束脚本等调用方式。
7
7
  - 在一个脚本里尽量少写平台分支。
8
- - 提供一组可直接复用的 polyfill(`fetch` / `Storage` / `KV` / `Console` / `Lodash` / `qs`)。
8
+ - 提供一组可直接复用的 polyfill(`fetch` / `Storage` / `Console` / `Lodash` / `qs`)。
9
9
 
10
10
  ## 目录
11
11
  - [安装与导入](#安装与导入)
@@ -65,7 +65,6 @@ import {
65
65
  wait, // 延时等待工具(Promise)
66
66
  Console, // 统一日志工具(支持 logLevel)
67
67
  Lodash as _, // Lodash 建议按官方示例惯例使用 `_` 作为工具对象别名
68
- KV, // Cloudflare Workers KV 异步适配器(显式传入 namespace binding)
69
68
  qs, // 查询字符串工具(parse / stringify)
70
69
  Storage, // 统一持久化存储接口(适配 $prefs / $persistentStore / 内存 / 文件)
71
70
  } from "@nsnanocat/util";
@@ -82,7 +81,6 @@ import {
82
81
  - `lib/wait.mjs`
83
82
  - `polyfill/Console.mjs`
84
83
  - `polyfill/fetch.mjs`
85
- - `polyfill/KV.mjs`
86
84
  - `polyfill/Lodash.mjs`
87
85
  - `polyfill/qs.mjs`
88
86
  - `polyfill/StatusTexts.mjs`
@@ -110,7 +108,6 @@ import {
110
108
  | `getStorage.mjs` | `lib/argument.mjs`, `polyfill/Console.mjs`, `polyfill/Lodash.mjs`, `polyfill/Storage.mjs` | `Console.debug`, `Console.logLevel`, `Lodash.merge`, `Storage.getItem` | 先标准化 `$argument`,再合并默认配置/持久化配置/运行参数 |
111
109
  | `polyfill/Console.mjs` | `lib/app.mjs` | `$app` | 日志在 Worker / Node.js 与 iOS 脚本环境使用不同错误输出策略 |
112
110
  | `polyfill/fetch.mjs` | `lib/app.mjs`, `polyfill/Lodash.mjs`, `polyfill/StatusTexts.mjs`, `polyfill/Console.mjs` | `$app`, `Lodash.set`, `StatusTexts`(`Console` 当前版本未实际调用) | 按平台选请求引擎并做参数映射、响应结构统一 |
113
- | `polyfill/KV.mjs` | `lib/app.mjs`, `polyfill/Lodash.mjs`, `polyfill/Storage.mjs` | `$app`, `Lodash.get`, `Lodash.set`, `Lodash.unset`, `Storage` | 为 Cloudflare Workers KV 提供异步适配,并在非 Worker 平台回退到 `Storage` |
114
111
  | `polyfill/Storage.mjs` | `lib/app.mjs`, `polyfill/Lodash.mjs` | `$app`, `Lodash.get`, `Lodash.set`, `Lodash.unset` | 按平台选持久化后端并支持 `@key.path` 读写 |
115
112
  | `polyfill/Lodash.mjs` | 无 | 无 | 提供路径/合并等基础能力,被多个模块复用 |
116
113
  | `polyfill/qs.mjs` | `polyfill/Lodash.mjs` | `Lodash.get`, `Lodash.set`, `Lodash.toPath` | 提供查询字符串与对象之间的解析/序列化能力 |
@@ -478,39 +475,6 @@ const store = getStorage("@my_box", ["YouTube", "Global"], database);
478
475
  | Worker | 进程内内存缓存 |
479
476
  | Node.js | 本地 `box.dat` |
480
477
 
481
- ### `polyfill/KV.mjs`
482
-
483
- `KV` 是面向 Cloudflare Workers KV 的异步适配器:
484
- - 调用方显式传入 namespace binding:`new KV(env.NAMESPACE)`
485
- - Worker 分支直接调用 `namespace.get/put/delete/list`
486
- - `get()` 不传 `type`,默认按 Cloudflare 行为读取字符串
487
- - 非 Worker 平台会回退到 `Storage.getItem/setItem/removeItem`
488
- - `list()` 仅支持 Worker,返回 Cloudflare KV 原生列举结果
489
- - `clear()` 始终返回 `false`
490
-
491
- #### `new KV(namespace)`
492
- - `namespace` 需提供 `get(key)` / `put(key, value)` / `delete(key)`。
493
-
494
- #### `await kv.getItem(keyName, defaultValue = null)`
495
- - 支持普通 key。
496
- - 支持路径 key:`@root.path.to.key`。
497
- - 读取后会尝试 `JSON.parse`。
498
-
499
- #### `await kv.setItem(keyName, keyValue)`
500
- - 支持普通 key 与路径 key。
501
- - `keyValue` 为对象时自动 `JSON.stringify`。
502
-
503
- #### `await kv.removeItem(keyName)`
504
- - 支持普通 key 与路径 key。
505
-
506
- #### `await kv.list(options = {})`
507
- - 仅支持 Worker。
508
- - 透传 `prefix` / `limit` / `cursor` 到 `namespace.list(options)`。
509
- - 返回 Cloudflare KV 的原生结果:`keys` / `list_complete` / `cursor`。
510
-
511
- #### `await kv.clear()`
512
- - 始终返回 `false`。
513
-
514
478
  ### `polyfill/Console.mjs`
515
479
 
516
480
  `Console` 是统一日志工具(静态类)。
package/index.js CHANGED
@@ -6,7 +6,6 @@ export * from "./lib/time.mjs";
6
6
  export * from "./lib/wait.mjs";
7
7
  export * from "./polyfill/Console.mjs";
8
8
  export * from "./polyfill/fetch.mjs";
9
- export * from "./polyfill/KV.mjs";
10
9
  export * from "./polyfill/Lodash.mjs";
11
10
  export * from "./polyfill/qs.mjs";
12
11
  export * from "./polyfill/StatusTexts.mjs";
package/package.json CHANGED
@@ -42,5 +42,5 @@
42
42
  "registry": "https://registry.npmjs.org/",
43
43
  "access": "public"
44
44
  },
45
- "version": "2.4.1"
45
+ "version": "2.5.1"
46
46
  }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * 统一请求参数。
3
+ * Unified request payload.
4
+ */
5
+ export interface FetchRequest {
6
+ url: string;
7
+ method?: string;
8
+ headers?: Record<string, unknown>;
9
+ body?: string | ArrayBuffer | ArrayBufferView | object;
10
+ bodyBytes?: ArrayBuffer;
11
+ timeout?: number | string;
12
+ policy?: string;
13
+ redirection?: boolean;
14
+ "auto-redirect"?: boolean;
15
+ "auto-cookie"?: boolean | number | string;
16
+ opts?: Record<string, unknown>;
17
+ [key: string]: unknown;
18
+ }
19
+
20
+ /**
21
+ * 统一响应结构。
22
+ * Unified response payload.
23
+ */
24
+ export interface FetchResponse {
25
+ ok: boolean;
26
+ status: number;
27
+ statusCode?: number;
28
+ statusText?: string;
29
+ headers?: Record<string, unknown>;
30
+ body?: string | ArrayBuffer;
31
+ bodyBytes?: ArrayBuffer;
32
+ [key: string]: unknown;
33
+ }
34
+
35
+ /**
36
+ * 跨平台 `fetch` 适配层。
37
+ * Cross-platform `fetch` adapter.
38
+ *
39
+ * @param resource 请求对象或 URL / Request object or URL string.
40
+ * @param options 追加参数 / Extra options.
41
+ * @returns 统一响应结构 / Normalized response payload.
42
+ */
43
+ export function fetch(resource: FetchRequest | string, options?: Partial<FetchRequest>): Promise<FetchResponse>;
@@ -0,0 +1,48 @@
1
+ import { fetch as fetchRuntime } from "./fetch.mjs";
2
+
3
+ /**
4
+ * 统一请求参数。
5
+ * Unified request payload.
6
+ */
7
+ export interface FetchRequest {
8
+ url: string;
9
+ method?: string;
10
+ headers?: Record<string, unknown>;
11
+ body?: string | ArrayBuffer | ArrayBufferView | object;
12
+ bodyBytes?: ArrayBuffer;
13
+ timeout?: number | string;
14
+ policy?: string;
15
+ redirection?: boolean;
16
+ "auto-redirect"?: boolean;
17
+ "auto-cookie"?: boolean | number | string;
18
+ opts?: Record<string, unknown>;
19
+ [key: string]: unknown;
20
+ }
21
+
22
+ /**
23
+ * 统一响应结构。
24
+ * Unified response payload.
25
+ */
26
+ export interface FetchResponse {
27
+ ok: boolean;
28
+ status: number;
29
+ statusCode?: number;
30
+ statusText?: string;
31
+ headers?: Record<string, unknown>;
32
+ body?: string | ArrayBuffer;
33
+ bodyBytes?: ArrayBuffer;
34
+ [key: string]: unknown;
35
+ }
36
+
37
+ /**
38
+ * 跨平台 `fetch` 适配层。
39
+ * Cross-platform `fetch` adapter.
40
+ *
41
+ * @param resource 请求对象或 URL / Request object or URL string.
42
+ * @param options 追加参数 / Extra options.
43
+ * @returns 统一响应结构 / Normalized response payload.
44
+ */
45
+ export const fetch: (resource: FetchRequest | string, options?: Partial<FetchRequest>) => Promise<FetchResponse> = fetchRuntime as (
46
+ resource: FetchRequest | string,
47
+ options?: Partial<FetchRequest>,
48
+ ) => Promise<FetchResponse>;
package/polyfill/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  export * from "./Console.mjs";
2
2
  export * from "./fetch.mjs";
3
- export * from "./KV.mjs";
4
3
  export * from "./Lodash.mjs";
5
4
  export * from "./qs.mjs";
6
5
  export * from "./StatusTexts.mjs";
@@ -2,6 +2,5 @@
2
2
  /// <reference path="./modules/fetch.d.ts" />
3
3
  /// <reference path="./modules/polyfills.d.ts" />
4
4
  /// <reference path="./modules/storage.d.ts" />
5
- /// <reference path="./modules/kv.d.ts" />
6
5
  /// <reference path="./modules/getStorage.d.ts" />
7
6
  /// <reference path="./modules/environment.d.ts" />
package/polyfill/KV.mjs DELETED
@@ -1,218 +0,0 @@
1
- import { $app } from "../lib/app.mjs";
2
- import { Lodash as _ } from "./Lodash.mjs";
3
- import { Storage } from "./Storage.mjs";
4
-
5
- /**
6
- * Cloudflare Workers KV 异步适配器。
7
- * Async adapter for Cloudflare Workers KV.
8
- *
9
- * 设计目标:
10
- * Design goal:
11
- * - 提供与 `Storage` 接近的异步接口
12
- * - Provide an async API close to `Storage`
13
- * - 在 Worker 中使用显式传入的 KV namespace binding
14
- * - Use an explicitly passed KV namespace binding in Workers
15
- * - 在非 Worker 平台回退到 `Storage`
16
- * - Fall back to `Storage` on non-Worker platforms
17
- *
18
- * 支持路径键:
19
- * Supports path key:
20
- * - `@root.path.to.value`
21
- *
22
- * @link https://developers.cloudflare.com/kv/get-started/#5-access-your-kv-namespace-from-your-worker
23
- * @link https://developers.cloudflare.com/kv/api/read-key-value-pairs/
24
- * @link https://developers.cloudflare.com/kv/api/write-key-value-pairs/
25
- * @link https://developers.cloudflare.com/kv/api/delete-key-value-pairs/
26
- * @link https://developers.cloudflare.com/kv/api/list-keys/
27
- */
28
- export class KV {
29
- /**
30
- * `@key.path` 解析正则。
31
- * Regex for `@key.path` parsing.
32
- *
33
- * @type {RegExp}
34
- */
35
- static #nameRegex = /^@(?<key>[^.]+)(?:\.(?<path>.*))?$/;
36
-
37
- /**
38
- * Cloudflare KV namespace 绑定。
39
- * Cloudflare KV namespace binding.
40
- *
41
- * @type {{ get(key: string): Promise<string|null>; put(key: string, value: string): Promise<void>; delete(key: string): Promise<void>; list?(options?: { prefix?: string; limit?: number; cursor?: string }): Promise<{ keys: { name: string; expiration?: number; metadata?: object }[]; list_complete: boolean; cursor: string }> } | undefined}
42
- */
43
- namespace;
44
-
45
- /**
46
- * 创建 KV 适配器实例。
47
- * Create a KV adapter instance.
48
- *
49
- * @param {{ get(key: string): Promise<string|null>; put(key: string, value: string): Promise<void>; delete(key: string): Promise<void>; list?(options?: { prefix?: string; limit?: number; cursor?: string }): Promise<{ keys: { name: string; expiration?: number; metadata?: object }[]; list_complete: boolean; cursor: string }> } | null | undefined} namespace KV namespace 绑定 / KV namespace binding.
50
- */
51
- constructor(namespace) {
52
- this.namespace = namespace ?? undefined;
53
- }
54
-
55
- /**
56
- * 读取存储值。
57
- * Read value from persistent storage.
58
- *
59
- * @param {string} keyName 键名或路径键 / Key or path key.
60
- * @param {*} [defaultValue=null] 默认值 / Default value when key is missing.
61
- * @returns {Promise<*>}
62
- */
63
- async getItem(keyName, defaultValue = null) {
64
- let keyValue = defaultValue;
65
- switch (keyName.startsWith("@")) {
66
- case true: {
67
- const { key, path } = keyName.match(KV.#nameRegex)?.groups ?? {};
68
- keyName = key;
69
- let value = await this.getItem(keyName, {});
70
- if (typeof value !== "object" || value === null) value = {};
71
- keyValue = _.get(value, path);
72
- keyValue = KV.#deserialize(keyValue);
73
- break;
74
- }
75
- default:
76
- switch ($app) {
77
- case "Worker":
78
- keyValue = await this.namespace.get(keyName);
79
- break;
80
- default:
81
- keyValue = Storage.getItem(keyName, defaultValue);
82
- break;
83
- }
84
- keyValue = KV.#deserialize(keyValue);
85
- break;
86
- }
87
- return keyValue ?? defaultValue;
88
- }
89
-
90
- /**
91
- * 写入存储值。
92
- * Write value into persistent storage.
93
- *
94
- * @param {string} keyName 键名或路径键 / Key or path key.
95
- * @param {*} keyValue 写入值 / Value to store.
96
- * @returns {Promise<boolean>}
97
- */
98
- async setItem(keyName = new String(), keyValue = new String()) {
99
- let result = false;
100
- keyValue = KV.#serialize(keyValue);
101
- switch (keyName.startsWith("@")) {
102
- case true: {
103
- const { key, path } = keyName.match(KV.#nameRegex)?.groups ?? {};
104
- keyName = key;
105
- let value = await this.getItem(keyName, {});
106
- if (typeof value !== "object" || value === null) value = {};
107
- _.set(value, path, keyValue);
108
- result = await this.setItem(keyName, value);
109
- break;
110
- }
111
- default:
112
- switch ($app) {
113
- case "Worker":
114
- await this.namespace.put(keyName, keyValue);
115
- result = true;
116
- break;
117
- default:
118
- result = Storage.setItem(keyName, keyValue);
119
- break;
120
- }
121
- break;
122
- }
123
- return result;
124
- }
125
-
126
- /**
127
- * 删除存储值。
128
- * Remove value from persistent storage.
129
- *
130
- * @param {string} keyName 键名或路径键 / Key or path key.
131
- * @returns {Promise<boolean>}
132
- */
133
- async removeItem(keyName) {
134
- let result = false;
135
- switch (keyName.startsWith("@")) {
136
- case true: {
137
- const { key, path } = keyName.match(KV.#nameRegex)?.groups ?? {};
138
- keyName = key;
139
- let value = await this.getItem(keyName);
140
- if (typeof value !== "object" || value === null) value = {};
141
- _.unset(value, path);
142
- result = await this.setItem(keyName, value);
143
- break;
144
- }
145
- default:
146
- switch ($app) {
147
- case "Worker":
148
- await this.namespace.delete(keyName);
149
- result = true;
150
- break;
151
- default:
152
- result = Storage.removeItem(keyName);
153
- break;
154
- }
155
- break;
156
- }
157
- return result;
158
- }
159
-
160
- /**
161
- * 清空存储。
162
- * Clear storage.
163
- *
164
- * @returns {Promise<boolean>}
165
- */
166
- async clear() {
167
- return false;
168
- }
169
-
170
- /**
171
- * 列出命名空间中的键。
172
- * List keys in the namespace.
173
- *
174
- * @param {{ prefix?: string; limit?: number; cursor?: string }} [options={}] 列举选项 / List options.
175
- * @returns {Promise<{ keys: { name: string; expiration?: number; metadata?: object }[]; list_complete: boolean; cursor: string }>}
176
- */
177
- async list(options = {}) {
178
- switch ($app) {
179
- case "Worker":
180
- return await this.namespace.list(options);
181
- default:
182
- throw new TypeError("KV.list() is only supported in Worker runtime.");
183
- }
184
- }
185
-
186
- /**
187
- * 尝试将字符串反序列化为原始值。
188
- * Try to deserialize a string into its original value.
189
- *
190
- * @private
191
- * @param {*} value 原始值 / Raw value.
192
- * @returns {*}
193
- */
194
- static #deserialize(value) {
195
- try {
196
- return JSON.parse(value);
197
- } catch (e) {
198
- return value;
199
- }
200
- }
201
-
202
- /**
203
- * 规范化待写入的值。
204
- * Normalize a value before persisting it.
205
- *
206
- * @private
207
- * @param {*} value 原始值 / Raw value.
208
- * @returns {string}
209
- */
210
- static #serialize(value) {
211
- switch (typeof value) {
212
- case "object":
213
- return JSON.stringify(value);
214
- default:
215
- return String(value);
216
- }
217
- }
218
- }
@@ -1,35 +0,0 @@
1
- declare module "@nsnanocat/util" {
2
- export interface KVNamespaceLike {
3
- get(key: string): Promise<string | null>;
4
- put(key: string, value: string): Promise<void>;
5
- delete(key: string): Promise<void>;
6
- list?(options?: KVListOptions): Promise<KVListResult>;
7
- }
8
-
9
- export interface KVListOptions {
10
- prefix?: string;
11
- limit?: number;
12
- cursor?: string;
13
- }
14
-
15
- export interface KVListKey {
16
- name: string;
17
- expiration?: number;
18
- metadata?: Record<string, unknown>;
19
- }
20
-
21
- export interface KVListResult {
22
- keys: KVListKey[];
23
- list_complete: boolean;
24
- cursor: string;
25
- }
26
-
27
- export class KV {
28
- constructor(namespace?: KVNamespaceLike | null);
29
- getItem<T = unknown>(keyName: string, defaultValue?: T): Promise<T>;
30
- setItem(keyName: string, keyValue: unknown): Promise<boolean>;
31
- removeItem(keyName: string): Promise<boolean>;
32
- clear(): Promise<boolean>;
33
- list(options?: KVListOptions): Promise<KVListResult>;
34
- }
35
- }