@fast-china/utils 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/docs/API.md CHANGED
@@ -21,10 +21,15 @@ import { Local, Session } from "@fast-china/utils";
21
21
 
22
22
  Local.set("profile", { name: "Ada" }, { ttlMs: 3_600_000 });
23
23
  Session.set("draft", { step: 2 });
24
+
25
+ Local.set("private-profile", { name: "Ada" }, { crypto: true });
26
+ Local.get<{ name: string }>("private-profile", { crypto: true });
24
27
  ```
25
28
 
26
29
  `Local` and `Session` provide `get`, `set`, `has`, `remove`, `removeByPrefix`, `keys`, `pruneExpired`, and namespace-scoped `clear`. Missing and expired values return `undefined`. Invalid TTL values, empty prefixes, malformed stored envelopes, unavailable platform storage, and conflicting repeated configuration throw errors. Native storage quota and privacy errors are propagated. Custom options must be configured before the first Storage operation.
27
30
 
31
+ `get<Value = string>()` has the static return type `string | undefined` when its generic is omitted, so string entries can be read directly. The codec still restores the original JSON value at runtime and does not convert objects, arrays, or other non-string values to strings; pass an explicit generic when accurate type information is required.
32
+
28
33
  For uni-app, the first Storage operation or an explicit `configureStorage` call detects the global `uni` object and uses its synchronous Storage API. uni-app has no separate session backend, so `Session` throws when called in this mode.
29
34
 
30
35
  ```ts
@@ -33,7 +38,11 @@ import { Local } from "@fast-china/utils";
33
38
  Local.set("token", "value");
34
39
  ```
35
40
 
36
- `configureStorage({ prefix: "admin:", crypto: true })` restores the old global prefix and Base64-obfuscation options. `crypto: true` and `base64StorageCodec` are reversible encoding rather than encryption and must not protect secrets. A custom `codec` may be supplied instead of `crypto`.
41
+ `configureStorage({ prefix: "admin:", crypto: true })` restores the old global prefix and Base64-obfuscation options. `Local` and `Session` `set/get` also accept a per-operation `{ crypto: boolean }`: `true` selects the Base64 codec, `false` selects the JSON codec, and omission uses the global codec. An operation override does not mutate global configuration. The current v3 envelope does not record its codec, so writes and reads of the same entry must use matching options; a mismatch throws a decoding error.
42
+
43
+ `crypto: true` and `base64StorageCodec` are reversible encoding rather than encryption and must not protect secrets. A custom `codec` may be supplied instead of global `crypto`.
44
+
45
+ `decodeBase64`, `decodeBase64Url`, `decodeLatin1Base64`, and `decodeSecureBase64` return the primitive-string `DecodedText` type. It is directly assignable to `string` and supports strict equality; an explicit `.parseJson<T = any>()` call attempts JSON parsing and returns the unchanged source string when its syntax is invalid. The first text decode lazily installs a non-enumerable `String.prototype.parseJson`; a foreign property with the same name causes a `TypeError` instead of being overwritten. The generic type describes the expected shape but neither validates it nor guarantees an object result at runtime. Storage codecs do not use this fallback and continue to reject invalid JSON strictly.
37
46
 
38
47
  `encodeSecureBase64` and `decodeSecureBase64` preserve the legacy dictionary payload. The random prefix prefers Web Crypto and falls back to `Math.random()` when unavailable; it does not provide a security property. Given the same default six-character prefix, valid legacy payloads remain byte-for-byte compatible. The old dictionary references an unavailable character for Base64 lengths 101–124, so the current implementation inserts a one-character fallback that the legacy removal flow can decode. The old custom-length argument always generated six random characters; the current API correctly generates `prefixLength` characters. Custom lengths must match during encoding and decoding; `0` disables both the prefix and dictionary insertion. The format remains reversible encoding rather than encryption.
39
48
 
@@ -55,16 +64,25 @@ The identifier is an installation-scoped value, not a hardware identifier, authe
55
64
 
56
65
  ## Logger
57
66
 
58
- Logger scope belongs to each message rather than a mutable logger or child instance:
67
+ Logger scope belongs to each entry rather than a logger or child instance. The default `logger` works without construction and has a minimum level of `debug`. Configure it once
68
+ at application startup when uni-app App-Plus needs split object output:
59
69
 
60
70
  ```ts
61
- import { logger } from "@fast-china/utils";
71
+ import { configureLogger, logger } from "@fast-china/utils";
62
72
 
63
- logger.info("storage", "profile loaded", { userId: 1 });
73
+ configureLogger({ uniAppPlusSplit: true });
74
+ logger.log("Launch", { code: 200, data: { id: 1 } });
75
+ logger.log("storage", "profile loaded", { userId: 1 });
64
76
  logger.error("network", "request failed", error);
65
77
  ```
66
78
 
67
- `createLogger` configures the minimum level, brand prefix, sink, and optional uni-app App-Plus split output. Scope must be a non-empty string without surrounding whitespace.
79
+ Log content is optional and may directly contain objects, arrays, `Error` instances, or other values. Non-string values are passed unchanged to
80
+ the Sink in normal runtimes. With App-Plus splitting enabled, the heading is emitted separately and each additional value is converted to readable
81
+ text because HBuilderX does not reliably display objects.
82
+
83
+ `configureLogger` replaces the complete configuration of the default `logger`; previously retained `logger` references immediately observe the new
84
+ configuration. Calling it without options restores all defaults. `createLogger` creates an isolated instance unaffected by global configuration.
85
+ Logger's `debug`, `log`, `warn`, and `error` methods call the matching Sink methods; the default Sink maps them to `console.debug`, `console.log`, `console.warn`, and `console.error`. Both support a minimum level, brand prefix, Sink, and optional App-Plus split output. Scope must be a non-empty string without surrounding whitespace.
68
86
 
69
87
  ## Clipboard
70
88
 
@@ -93,13 +111,21 @@ The TypeScript Crypto public API mirrors the public methods and algorithm casing
93
111
 
94
112
  The Base64 v1 payload produced by `AESEncryptAuthenticated`, the `FAST-AES-256-GCM-V1` password payload, PBKDF2 password hashes, and PKCS#8/SPKI PEM keys interoperate with .NET in both directions. MD5 and HMAC output lowercase hexadecimal; SHA-1/256/384/512 output uppercase hexadecimal, matching .NET.
95
113
 
114
+ `AESDecrypt`, `AESDecryptAuthenticated`, `AESDecryptWithPassword`, and `RSADecryptOAEP` return the primitive-string `DecodedText` type (wrapped in a Promise for asynchronous APIs). Use the result directly as plaintext or call `.parseJson<T = any>()` explicitly:
115
+
116
+ ```ts
117
+ const plaintext = await AESDecryptWithPassword(payload, password);
118
+ const raw: string = plaintext;
119
+ const result = plaintext.parseJson<{ id: number }>();
120
+ ```
121
+
96
122
  Store passwords with `HashPasswordPBKDF2SHA256` and `VerifyPasswordPBKDF2SHA256`; the result is not decryptable. AES-GCM provides confidentiality and integrity, HMAC authenticates with a shared key, SHA-2 computes digests, and HKDF/PBKDF2 derive keys. MD5, SHA-1, AES-CBC, and AES-ECB do not provide modern password-storage or authenticated-encryption guarantees.
97
123
 
98
124
  ## Modules
99
125
 
100
126
  - `array`: `chunk`, `removeNullishValues`, `unique`, `uniqueBy`, `groupBy`, `partition`, `difference`, `intersection`, `hasDuplicatesBy`, and `allEqualBy`.
101
127
  - `async`: abort-aware `sleep`, timeout, retry, bounded concurrent mapping, debounce, and throttle primitives.
102
- - `base64`: strict UTF-8 Base64/Base64URL byte and text functions plus the historical Latin-1 and dictionary-obfuscation functions.
128
+ - `base64`: strict UTF-8 Base64/Base64URL byte functions and chainable text results plus the historical Latin-1 and dictionary-obfuscation functions.
103
129
  - `color`: Hex parsing/formatting/mixing, explicit black/white mixing, luminance, and contrast helpers.
104
130
  - `crypto`: random bytes, digests, HMAC, PBKDF2, HKDF, AES, RSA-OAEP/PSS, ECDSA, and ECDH.
105
131
  - `date`: date validation and arithmetic, day ranges, relative formatting, and the seven historical date helpers as named functions.
package/docs/API.zh-CN.md CHANGED
@@ -21,10 +21,15 @@ import { Local, Session } from "@fast-china/utils";
21
21
 
22
22
  Local.set("profile", { name: "Ada" }, { ttlMs: 3_600_000 });
23
23
  Session.set("draft", { step: 2 });
24
+
25
+ Local.set("private-profile", { name: "Ada" }, { crypto: true });
26
+ Local.get<{ name: string }>("private-profile", { crypto: true });
24
27
  ```
25
28
 
26
29
  `Local` 和 `Session` 提供 `get`、`set`、`has`、`remove`、`removeByPrefix`、`keys`、`pruneExpired` 和仅清理当前命名空间的 `clear`。键缺失或过期时返回 `undefined`。TTL 非法、Prefix 为空、存储包络损坏、平台 Storage 不可用或重复配置发生冲突时抛出错误;浏览器配额与隐私策略错误直接向上传播。自定义选项必须在首次 Storage 操作前配置。
27
30
 
31
+ `get<Value = string>()` 在未传泛型时的静态返回类型为 `string | undefined`,可以直接读取字符串条目。Codec 在运行时仍通过 JSON 反序列化恢复原值,因此对象、数组或其他非字符串值不会被转换成字符串;需要准确类型提示时显式传入对应泛型。
32
+
28
33
  uni-app 中,首次 Storage 操作或显式调用 `configureStorage` 会自动检测全局 `uni` 并使用其同步 Storage API。uni-app 没有独立 Session 后端,因此该模式调用 `Session` 会明确抛错。
29
34
 
30
35
  ```ts
@@ -33,7 +38,11 @@ import { Local } from "@fast-china/utils";
33
38
  Local.set("token", "value");
34
39
  ```
35
40
 
36
- `configureStorage({ prefix: "admin:", crypto: true })` 恢复了旧版全局前缀与 Base64 混淆选项。`crypto: true` `base64StorageCodec` 都只是可逆编码,不是加密,不能保护敏感数据。可以使用自定义 `codec` 替代 `crypto`。
41
+ `configureStorage({ prefix: "admin:", crypto: true })` 恢复了旧版全局前缀与 Base64 混淆选项。`Local` `Session` `set/get` 也接受单次 `{ crypto: boolean }`:`true` 使用 Base64 Codec,`false` 使用 JSON Codec,省略时沿用全局 Codec。单次设置不会修改全局配置;当前 v3 包络不记录 Codec,读写同一条目时必须传入一致选项,错误配置会明确抛出解码错误。
42
+
43
+ `crypto: true` 和 `base64StorageCodec` 都只是可逆编码,不是加密,不能保护敏感数据。可以使用自定义 `codec` 替代全局 `crypto`。
44
+
45
+ `decodeBase64`、`decodeBase64Url`、`decodeLatin1Base64` 与 `decodeSecureBase64` 返回原始字符串类型 `DecodedText`,可以直接赋值给 `string` 或参与严格比较;显式调用 `.parseJson<T = any>()` 才尝试解析 JSON,语法无效时返回未经修改的原始字符串。首次文本解码会按需安装不可枚举的 `String.prototype.parseJson`;若同名属性已被其他实现占用则抛出 `TypeError`,不会覆盖。泛型只描述期望类型,不执行运行时结构校验,也不保证结果一定是对象。Storage Codec 不使用该容错行为,仍会严格拒绝非法 JSON。
37
46
 
38
47
  `encodeSecureBase64` 与 `decodeSecureBase64` 保留旧字典兼容载荷。随机前缀优先使用 Web Crypto,能力缺失时回退到 `Math.random()`;它不承担安全用途。给定相同的默认 6 字符前缀时,有效旧载荷保持逐字符兼容;旧字典在 Base64 长度 101–124 时会引用越界,当前实现使用单字符回退,旧删除字典流程仍可解码。旧自定义长度参数始终生成 6 个随机字符,当前 API 已按 `prefixLength` 正确生成。自定义 `prefixLength` 必须在编码和解码时保持一致;传入 `0` 会同时关闭随机前缀与字典插入。该格式仍是可逆编码,不等同于加密。
39
48
 
@@ -55,16 +64,24 @@ installationIdentity.clear();
55
64
 
56
65
  ## Logger
57
66
 
58
- Logger 作用域属于每条日志,不保存在可变 Logger 或 Child 实例中:
67
+ Logger 作用域属于每条日志,不保存在 Logger 或 Child 实例中。默认 `logger` 无需创建即可使用,最低输出级别为 `debug`;uni-app App-Plus
68
+ 需要拆分对象输出时,在应用入口配置一次:
59
69
 
60
70
  ```ts
61
- import { logger } from "@fast-china/utils";
71
+ import { configureLogger, logger } from "@fast-china/utils";
62
72
 
63
- logger.info("storage", "profile loaded", { userId: 1 });
73
+ configureLogger({ uniAppPlusSplit: true });
74
+ logger.log("Launch", { code: 200, data: { id: 1 } });
75
+ logger.log("storage", "profile loaded", { userId: 1 });
64
76
  logger.error("network", "request failed", error);
65
77
  ```
66
78
 
67
- `createLogger` 只配置最低级别、品牌前缀、Sink 和可选的 uni-app App-Plus 拆分输出。作用域必须是无外围空白的非空字符串。
79
+ 日志内容可省略,也可以直接传入对象、数组、`Error` 等任意值。普通环境会把非字符串值原样传给 Sink;启用 App-Plus
80
+ 拆分输出后,为解决 HBuilderX 无法正确显示对象的问题,标题单独输出,附加值逐条转换为可读文本。
81
+
82
+ `configureLogger` 会替换默认 `logger` 的完整配置,已经保存的 `logger` 引用也会立即使用新配置;无参数调用会恢复默认值。
83
+ `createLogger` 用于创建不受全局配置影响的独立实例。Logger 的 `debug`、`log`、`warn`、`error` 分别调用 Sink 的同名方法,默认 Sink 对应 `console.debug`、`console.log`、`console.warn`、`console.error`。两者均支持最低级别、品牌前缀、Sink 和可选的 App-Plus 拆分输出。
84
+ 作用域必须是无外围空白的非空字符串。
68
85
 
69
86
  ## 剪贴板
70
87
 
@@ -93,13 +110,21 @@ TypeScript Crypto 公共 API 与 .NET `CryptoUtil` 的公开方法及算法名
93
110
 
94
111
  `AESEncryptAuthenticated` 的 Base64 v1 载荷、`AESEncryptWithPassword` 的 `FAST-AES-256-GCM-V1` 载荷、PBKDF2 密码哈希以及 PKCS#8/SPKI PEM 密钥均可与 .NET 双向使用。MD5 与 HMAC 输出小写十六进制;SHA-1/256/384/512 输出大写十六进制,与 .NET 保持一致。
95
112
 
113
+ `AESDecrypt`、`AESDecryptAuthenticated`、`AESDecryptWithPassword` 与 `RSADecryptOAEP` 返回原始字符串类型 `DecodedText`(异步入口返回其 Promise)。返回值可直接作为明文字符串使用,也可通过 `.parseJson<T = any>()` 显式解析 JSON:
114
+
115
+ ```ts
116
+ const plaintext = await AESDecryptWithPassword(payload, password);
117
+ const raw: string = plaintext;
118
+ const result = plaintext.parseJson<{ id: number }>();
119
+ ```
120
+
96
121
  密码存储使用 `HashPasswordPBKDF2SHA256` 和 `VerifyPasswordPBKDF2SHA256`;该哈希不可解密。需要同时保证机密性和完整性的文本使用 AES-GCM 入口。HMAC 用于共享密钥认证,SHA-2 用于摘要,HKDF/PBKDF2 用于密钥派生。MD5、SHA-1、AES-CBC 和 AES-ECB 不提供现代密码存储或认证加密保证。
97
122
 
98
123
  ## 模块
99
124
 
100
125
  - `array`:分块、压缩、去重、分组、分区、差集、交集和一致性判断。
101
126
  - `async`:支持取消的 Sleep、超时、重试、受限并发映射、防抖和节流。
102
- - `base64`:严格 UTF-8 Base64/Base64URL 字节与文本函数,以及 Latin-1 和 SecureBase64 兼容函数。
127
+ - `base64`:严格 UTF-8 Base64/Base64URL 字节与链式文本结果,以及 Latin-1 和 SecureBase64 兼容函数。
103
128
  - `color`:颜色解析、格式化、混合、明暗、亮度和对比度。
104
129
  - `crypto`:随机字节、摘要、HMAC、PBKDF2、HKDF、AES、RSA-OAEP/PSS、ECDSA 和 ECDH。
105
130
  - `date`:日期校验、加减、日范围、相对时间,以及七个历史日期功能的具名函数。
@@ -7,7 +7,9 @@
7
7
  - Framework boundary: Vue remains external to the package-manager build and is a required peer in `^3.3.0`.
8
8
  - uni-app boundary: the first Storage operation, or an earlier `configureStorage({ prefix })` call, detects global `uni` and uses its synchronous Storage API.
9
9
  - Browser storage: applications import `Local` and `Session` directly; `configureStorage()` is needed only to override defaults before the first operation.
10
- - Stateful browser defaults: Storage and Identity configuration are page-global by design. Conflicting reconfiguration throws.
10
+ - Storage operation overrides: `set/get({ crypto })` select JSON or Base64 for one operation without mutating global configuration. The v3 envelope does not identify its codec, so callers must use matching options for the same entry.
11
+ - Storage read typing: `get<Value = string>()` defaults to `string | undefined` when no generic is supplied; codecs still restore the original runtime JSON value.
12
+ - Stateful browser defaults: Storage, Identity, and default Logger configuration are page-global by design. Storage and Identity reject conflicting reconfiguration; `configureLogger` replaces the default Logger configuration while preserving the exported facade reference.
11
13
  - Randomness: every random generation entry prefers Web Crypto and falls back to `Math.random()` when unavailable.
12
14
  - Publishing: the repository root is the only package, `dist/` is the only build output, and `package.json#exports` is the complete public path whitelist.
13
15
 
@@ -17,7 +19,8 @@ Importing a module does not itself read `window`, browser Storage, or `uni`, so
17
19
 
18
20
  - Stateless Array, Date, String, Number, Object, Base64, Color, DOM, Env, Async, and Crypto capabilities use named exports.
19
21
  - The public API uses named functions instead of mutable aggregate utility objects.
20
- - Stateful browser capabilities use cohesive package-owned objects: `Local`, `Session`, `installationIdentity`, and logger instances. Logger scope is supplied to each severity method rather than stored in child instances.
22
+ - Base64 and Crypto text decoders return primitive strings typed as `DecodedText`. They can be used directly as strings; an explicit `.parseJson<T = any>()` call attempts JSON parsing and falls back to the original string for invalid JSON. The first text decode lazily installs a non-enumerable `String.prototype.parseJson` and rejects a foreign same-name property instead of overwriting it. Storage codecs continue to parse JSON automatically and strictly.
23
+ - Stateful browser capabilities use cohesive package-owned objects: `Local`, `Session`, `installationIdentity`, and Logger instances. Logger exposes the matching `debug`, `log`, `warn`, and `error` levels, defaults to the `debug` minimum, and receives scope on each method rather than storing it in child instances. `createLogger` returns isolated instances, while `configureLogger` only changes the default `logger` facade.
21
24
  - Internal adapters and client factories are implementation details and are not public export paths.
22
25
  - Removing a named function, changing Storage/ciphertext formats, raising the browser syntax target, or changing the Vue peer range requires an explicit major-version Breaking Change.
23
26
 
@@ -28,10 +31,12 @@ Importing a module does not itself read `window`, browser Storage, or `uni`, so
28
31
  - Vue 边界:Vue 不会打进包管理器使用的构建产物,是 `^3.3.0` 的必需 Peer。
29
32
  - uni-app:首次 Storage 操作或更早的 `configureStorage({ prefix })` 调用会检测全局 `uni`,并使用其同步 Storage API。
30
33
  - Storage:直接从包导入 `Local` 和 `Session` 即可;只有覆盖默认值时才需在首次操作前调用 `configureStorage()`。
31
- - 状态:Storage Identity 配置按浏览器页面全局共享;冲突配置明确抛错。
34
+ - Storage 单次覆盖:`set/get({ crypto })` 只为当前操作选择 JSON 或 Base64,不修改全局配置。v3 包络不记录 Codec,调用方必须对同一条目使用匹配的读写选项。
35
+ - Storage 读取类型:`get<Value = string>()` 未传泛型时默认推断为 `string | undefined`,Codec 在运行时仍恢复原始 JSON 值。
36
+ - 状态:Storage、Identity 与默认 Logger 配置按浏览器页面全局共享。Storage 和 Identity 的冲突配置明确抛错;`configureLogger` 替换默认 Logger 的配置,同时保持导出的门面引用稳定。
32
37
  - 随机数:所有随机生成入口都优先使用 Web Crypto,缺失时回退到 `Math.random()`。
33
38
  - 发布:根目录是唯一 npm 包,`dist/` 是唯一构建输出,`exports` 是完整公共路径白名单。
34
39
 
35
40
  模块导入本身不读取 `window`、浏览器 Storage 或 `uni`,不具备对应平台能力时只在调用相关 API 时明确失败。
36
41
 
37
- 无状态能力统一使用具名导出。有状态浏览器能力使用 `Local`、`Session`、`installationIdentity` 和 Logger 实例;Logger 作用域随每次级别方法调用传入,不创建 Child Logger
42
+ 无状态能力统一使用具名导出。Base64 与 Crypto 文本解码入口返回原始字符串类型 `DecodedText`,可以直接作为字符串使用;`.parseJson<T = any>()` 只在显式调用时尝试解析 JSON,非法 JSON 回退为原始字符串。首次文本解码会按需安装不可枚举的 `String.prototype.parseJson`,若同名属性已被其他实现占用则拒绝覆盖并抛错。Storage Codec 继续严格自动解析 JSON。有状态浏览器能力使用 `Local`、`Session`、`installationIdentity` 和 Logger 实例;Logger 提供与 Sink 同名的 `debug`、`log`、`warn`、`error` 级别,默认最低级别为 `debug`,作用域随每次调用传入,不创建 Child Logger。`createLogger` 返回隔离实例,`configureLogger` 只修改默认 `logger` 门面。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fast-china/utils",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "description": "Typed utilities for modern browsers, WebViews, Vue 3, and uni-app applications.",
5
5
  "type": "module",
6
6
  "keywords": [