@miaixz/sdk 0.5.0
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/LICENSE +202 -0
- package/NOTICE +7 -0
- package/README.md +412 -0
- package/dist/api/client.d.ts +223 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +1069 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/endpoint.d.ts +10 -0
- package/dist/api/endpoint.d.ts.map +1 -0
- package/dist/api/endpoint.js +51 -0
- package/dist/api/endpoint.js.map +1 -0
- package/dist/api/errors.d.ts +180 -0
- package/dist/api/errors.d.ts.map +1 -0
- package/dist/api/errors.js +173 -0
- package/dist/api/errors.js.map +1 -0
- package/dist/api/index.d.ts +6 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +5 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/request.d.ts +135 -0
- package/dist/api/request.d.ts.map +1 -0
- package/dist/api/request.js +2 -0
- package/dist/api/request.js.map +1 -0
- package/dist/api/response.d.ts +69 -0
- package/dist/api/response.d.ts.map +1 -0
- package/dist/api/response.js +43 -0
- package/dist/api/response.js.map +1 -0
- package/dist/api/telemetry.d.ts +139 -0
- package/dist/api/telemetry.d.ts.map +1 -0
- package/dist/api/telemetry.js +2 -0
- package/dist/api/telemetry.js.map +1 -0
- package/dist/appearance/appearance.d.ts +161 -0
- package/dist/appearance/appearance.d.ts.map +1 -0
- package/dist/appearance/appearance.js +614 -0
- package/dist/appearance/appearance.js.map +1 -0
- package/dist/appearance/index.d.ts +3 -0
- package/dist/appearance/index.d.ts.map +1 -0
- package/dist/appearance/index.js +3 -0
- package/dist/appearance/index.js.map +1 -0
- package/dist/auth/auth.d.ts +197 -0
- package/dist/auth/auth.d.ts.map +1 -0
- package/dist/auth/auth.js +314 -0
- package/dist/auth/auth.js.map +1 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +2 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/config/config.d.ts +117 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +241 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +2 -0
- package/dist/config/index.js.map +1 -0
- package/dist/consts/index.d.ts +35 -0
- package/dist/consts/index.d.ts.map +1 -0
- package/dist/consts/index.js +35 -0
- package/dist/consts/index.js.map +1 -0
- package/dist/context/context.d.ts +123 -0
- package/dist/context/context.d.ts.map +1 -0
- package/dist/context/context.js +252 -0
- package/dist/context/context.js.map +1 -0
- package/dist/context/index.d.ts +2 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +2 -0
- package/dist/context/index.js.map +1 -0
- package/dist/contracts/host-context.d.ts +132 -0
- package/dist/contracts/host-context.d.ts.map +1 -0
- package/dist/contracts/host-context.js +2 -0
- package/dist/contracts/host-context.js.map +1 -0
- package/dist/contracts/index.d.ts +8 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +2 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/contracts/lifecycle.d.ts +49 -0
- package/dist/contracts/lifecycle.d.ts.map +1 -0
- package/dist/contracts/lifecycle.js +2 -0
- package/dist/contracts/lifecycle.js.map +1 -0
- package/dist/contracts/module-manifest.d.ts +110 -0
- package/dist/contracts/module-manifest.d.ts.map +1 -0
- package/dist/contracts/module-manifest.js +317 -0
- package/dist/contracts/module-manifest.js.map +1 -0
- package/dist/contracts/navigation.d.ts +36 -0
- package/dist/contracts/navigation.d.ts.map +1 -0
- package/dist/contracts/navigation.js +11 -0
- package/dist/contracts/navigation.js.map +1 -0
- package/dist/contracts/permission.d.ts +8 -0
- package/dist/contracts/permission.d.ts.map +1 -0
- package/dist/contracts/permission.js +14 -0
- package/dist/contracts/permission.js.map +1 -0
- package/dist/contracts/post-message.d.ts +124 -0
- package/dist/contracts/post-message.d.ts.map +1 -0
- package/dist/contracts/post-message.js +2 -0
- package/dist/contracts/post-message.js.map +1 -0
- package/dist/contracts/route.d.ts +45 -0
- package/dist/contracts/route.d.ts.map +1 -0
- package/dist/contracts/route.js +35 -0
- package/dist/contracts/route.js.map +1 -0
- package/dist/events/events.d.ts +191 -0
- package/dist/events/events.d.ts.map +1 -0
- package/dist/events/events.js +486 -0
- package/dist/events/events.js.map +1 -0
- package/dist/events/index.d.ts +2 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +2 -0
- package/dist/events/index.js.map +1 -0
- package/dist/files/files.d.ts +138 -0
- package/dist/files/files.d.ts.map +1 -0
- package/dist/files/files.js +144 -0
- package/dist/files/files.js.map +1 -0
- package/dist/files/index.d.ts +2 -0
- package/dist/files/index.d.ts.map +1 -0
- package/dist/files/index.js +2 -0
- package/dist/files/index.js.map +1 -0
- package/dist/formatters/index.d.ts +44 -0
- package/dist/formatters/index.d.ts.map +1 -0
- package/dist/formatters/index.js +50 -0
- package/dist/formatters/index.js.map +1 -0
- package/dist/i18n/default-translator.d.ts +17 -0
- package/dist/i18n/default-translator.d.ts.map +1 -0
- package/dist/i18n/default-translator.js +19 -0
- package/dist/i18n/default-translator.js.map +1 -0
- package/dist/i18n/i18n.d.ts +248 -0
- package/dist/i18n/i18n.d.ts.map +1 -0
- package/dist/i18n/i18n.js +617 -0
- package/dist/i18n/i18n.js.map +1 -0
- package/dist/i18n/index.d.ts +2 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +2 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/models/index.d.ts +2 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +2 -0
- package/dist/models/index.js.map +1 -0
- package/dist/permissions/index.d.ts +2 -0
- package/dist/permissions/index.d.ts.map +1 -0
- package/dist/permissions/index.js +2 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/permissions/permissions.d.ts +67 -0
- package/dist/permissions/permissions.d.ts.map +1 -0
- package/dist/permissions/permissions.js +123 -0
- package/dist/permissions/permissions.js.map +1 -0
- package/dist/runtime/direct-host-bridge.d.ts +11 -0
- package/dist/runtime/direct-host-bridge.d.ts.map +1 -0
- package/dist/runtime/direct-host-bridge.js +299 -0
- package/dist/runtime/direct-host-bridge.js.map +1 -0
- package/dist/runtime/index.d.ts +5 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +3 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/post-message-bridge.d.ts +20 -0
- package/dist/runtime/post-message-bridge.d.ts.map +1 -0
- package/dist/runtime/post-message-bridge.js +1115 -0
- package/dist/runtime/post-message-bridge.js.map +1 -0
- package/dist/sdk.d.ts +177 -0
- package/dist/sdk.d.ts.map +1 -0
- package/dist/sdk.js +214 -0
- package/dist/sdk.js.map +1 -0
- package/dist/storage/index.d.ts +2 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +2 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/storage.d.ts +246 -0
- package/dist/storage/storage.d.ts.map +1 -0
- package/dist/storage/storage.js +358 -0
- package/dist/storage/storage.js.map +1 -0
- package/dist/types/api.d.ts +82 -0
- package/dist/types/api.d.ts.map +1 -0
- package/dist/types/api.js +2 -0
- package/dist/types/api.js.map +1 -0
- package/dist/types/appearance.d.ts +85 -0
- package/dist/types/appearance.d.ts.map +1 -0
- package/dist/types/appearance.js +48 -0
- package/dist/types/appearance.js.map +1 -0
- package/dist/types/config.d.ts +49 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +2 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/context.d.ts +41 -0
- package/dist/types/context.d.ts.map +1 -0
- package/dist/types/context.js +2 -0
- package/dist/types/context.js.map +1 -0
- package/dist/types/file.d.ts +48 -0
- package/dist/types/file.d.ts.map +1 -0
- package/dist/types/file.js +2 -0
- package/dist/types/file.js.map +1 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +12 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/organization.d.ts +56 -0
- package/dist/types/organization.d.ts.map +1 -0
- package/dist/types/organization.js +2 -0
- package/dist/types/organization.js.map +1 -0
- package/dist/types/pagination.d.ts +55 -0
- package/dist/types/pagination.d.ts.map +1 -0
- package/dist/types/pagination.js +13 -0
- package/dist/types/pagination.js.map +1 -0
- package/dist/types/permissions.d.ts +26 -0
- package/dist/types/permissions.d.ts.map +1 -0
- package/dist/types/permissions.js +2 -0
- package/dist/types/permissions.js.map +1 -0
- package/dist/types/space.d.ts +43 -0
- package/dist/types/space.d.ts.map +1 -0
- package/dist/types/space.js +2 -0
- package/dist/types/space.js.map +1 -0
- package/dist/types/tenant.d.ts +31 -0
- package/dist/types/tenant.d.ts.map +1 -0
- package/dist/types/tenant.js +2 -0
- package/dist/types/tenant.js.map +1 -0
- package/dist/types/user.d.ts +48 -0
- package/dist/types/user.d.ts.map +1 -0
- package/dist/types/user.js +2 -0
- package/dist/types/user.js.map +1 -0
- package/dist/utils/date.d.ts +9 -0
- package/dist/utils/date.d.ts.map +1 -0
- package/dist/utils/date.js +11 -0
- package/dist/utils/date.js.map +1 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +5 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/number.d.ts +11 -0
- package/dist/utils/number.d.ts.map +1 -0
- package/dist/utils/number.js +13 -0
- package/dist/utils/number.js.map +1 -0
- package/dist/utils/object.d.ts +9 -0
- package/dist/utils/object.d.ts.map +1 -0
- package/dist/utils/object.js +11 -0
- package/dist/utils/object.js.map +1 -0
- package/dist/utils/string.d.ts +9 -0
- package/dist/utils/string.d.ts.map +1 -0
- package/dist/utils/string.js +11 -0
- package/dist/utils/string.js.map +1 -0
- package/dist/validators/index.d.ts +8 -0
- package/dist/validators/index.d.ts.map +1 -0
- package/dist/validators/index.js +8 -0
- package/dist/validators/index.js.map +1 -0
- package/package.json +156 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC","sourcesContent":["export * from \"./storage.js\";\n"]}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import type { MiaixzResponseParser } from "../api/request.js";
|
|
2
|
+
/**
|
|
3
|
+
* Defines the browser-compatible storage operations required by the SDK.
|
|
4
|
+
*
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export interface MiaixzKeyValueStorage {
|
|
8
|
+
/**
|
|
9
|
+
* Reads a serialized value or returns `null` when the key is absent.
|
|
10
|
+
*
|
|
11
|
+
* @param key - Storage key to read.
|
|
12
|
+
* @returns Serialized value or null when the key is absent.
|
|
13
|
+
*/
|
|
14
|
+
getItem(key: string): string | null;
|
|
15
|
+
/**
|
|
16
|
+
* Stores a serialized value under the supplied key.
|
|
17
|
+
*
|
|
18
|
+
* @param key - Storage key to write.
|
|
19
|
+
* @param value - Serialized value to store.
|
|
20
|
+
*/
|
|
21
|
+
setItem(key: string, value: string): void;
|
|
22
|
+
/**
|
|
23
|
+
* Removes the supplied key.
|
|
24
|
+
*
|
|
25
|
+
* @param key - Storage key to remove.
|
|
26
|
+
*/
|
|
27
|
+
removeItem(key: string): void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Wraps persisted data with its schema version.
|
|
31
|
+
*
|
|
32
|
+
* @typeParam T - Persisted application value type.
|
|
33
|
+
* @public
|
|
34
|
+
*/
|
|
35
|
+
export interface MiaixzVersionedValue<T> {
|
|
36
|
+
/**
|
|
37
|
+
* Identifies the schema used to serialize the value.
|
|
38
|
+
*/
|
|
39
|
+
readonly schemaVersion: number;
|
|
40
|
+
/**
|
|
41
|
+
* Contains the persisted application value.
|
|
42
|
+
*/
|
|
43
|
+
readonly value: T;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Migrates one persisted schema version to its immediate successor.
|
|
47
|
+
*
|
|
48
|
+
* @public
|
|
49
|
+
*/
|
|
50
|
+
export interface MiaixzStorageMigration {
|
|
51
|
+
/**
|
|
52
|
+
* Identifies the source schema version.
|
|
53
|
+
*/
|
|
54
|
+
readonly from: number;
|
|
55
|
+
/**
|
|
56
|
+
* Identifies the immediate target schema version.
|
|
57
|
+
*/
|
|
58
|
+
readonly to: number;
|
|
59
|
+
/**
|
|
60
|
+
* Converts one untrusted persisted value to the next schema.
|
|
61
|
+
*
|
|
62
|
+
* @param value - Value produced by storage or the previous migration.
|
|
63
|
+
* @returns Value represented in the target schema.
|
|
64
|
+
*/
|
|
65
|
+
migrate(value: unknown): unknown;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Identifies the application and optional tenant owning persisted data.
|
|
69
|
+
*
|
|
70
|
+
* @public
|
|
71
|
+
*/
|
|
72
|
+
export interface MiaixzStorageScope {
|
|
73
|
+
/**
|
|
74
|
+
* Identifies the consuming frontend application.
|
|
75
|
+
*/
|
|
76
|
+
readonly appId: string;
|
|
77
|
+
/**
|
|
78
|
+
* Identifies the optional tenant-specific persistence boundary.
|
|
79
|
+
*/
|
|
80
|
+
readonly tenantId?: string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Configures validated versioned storage reads.
|
|
84
|
+
*
|
|
85
|
+
* @typeParam T - Parsed application value type.
|
|
86
|
+
* @public
|
|
87
|
+
*/
|
|
88
|
+
export interface MiaixzVersionedStorageOptions<T> {
|
|
89
|
+
/**
|
|
90
|
+
* Supplies the optional physical storage adapter.
|
|
91
|
+
*/
|
|
92
|
+
readonly storage?: MiaixzKeyValueStorage;
|
|
93
|
+
/**
|
|
94
|
+
* Selects the application and tenant persistence boundary.
|
|
95
|
+
*/
|
|
96
|
+
readonly scope: Readonly<MiaixzStorageScope>;
|
|
97
|
+
/**
|
|
98
|
+
* Selects the fixed persisted data category.
|
|
99
|
+
*/
|
|
100
|
+
readonly kind: "appearance" | "context" | "preferences";
|
|
101
|
+
/**
|
|
102
|
+
* Identifies the current target schema version.
|
|
103
|
+
*/
|
|
104
|
+
readonly schemaVersion: number;
|
|
105
|
+
/**
|
|
106
|
+
* Supplies an optional continuous sequence of one-version migrations.
|
|
107
|
+
*/
|
|
108
|
+
readonly migrations?: readonly MiaixzStorageMigration[];
|
|
109
|
+
/**
|
|
110
|
+
* Parses the current-schema value into its normalized application representation.
|
|
111
|
+
*/
|
|
112
|
+
readonly parse: MiaixzResponseParser<T>;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Builds a collision-safe physical key for versioned Miaixz data.
|
|
116
|
+
*
|
|
117
|
+
* @param scope - Application and optional tenant persistence boundary.
|
|
118
|
+
* @param kind - Fixed persisted data category.
|
|
119
|
+
* @returns Physical storage key using the Miaixz version-one namespace.
|
|
120
|
+
* @throws MiaixzSdkError When the application, tenant, or kind is invalid.
|
|
121
|
+
* @public
|
|
122
|
+
*/
|
|
123
|
+
export declare function createMiaixzStorageKey(scope: Readonly<MiaixzStorageScope>, kind: "appearance" | "context" | "preferences"): string;
|
|
124
|
+
/**
|
|
125
|
+
* Reads, migrates, validates, and optionally upgrades one versioned value.
|
|
126
|
+
*
|
|
127
|
+
* @typeParam T - Parsed application value type.
|
|
128
|
+
* @param options - Scope, schema, migration, parser, and storage configuration.
|
|
129
|
+
* @returns Parsed normalized value, or undefined when data is absent or unusable.
|
|
130
|
+
* @throws MiaixzSdkError When scope, schema, or migration configuration is invalid.
|
|
131
|
+
* @public
|
|
132
|
+
*/
|
|
133
|
+
export declare function readMiaixzVersionedValue<T>(options: Readonly<MiaixzVersionedStorageOptions<T>>): T | undefined;
|
|
134
|
+
/**
|
|
135
|
+
* Writes or removes one versioned value without affecting caller memory on persistence failure.
|
|
136
|
+
*
|
|
137
|
+
* @typeParam T - Persisted application value type.
|
|
138
|
+
* @param options - Scope, target schema, and optional storage configuration.
|
|
139
|
+
* @param value - Value to persist, or undefined to remove the physical key.
|
|
140
|
+
* @throws MiaixzSdkError When scope, kind, or target schema is invalid.
|
|
141
|
+
* @public
|
|
142
|
+
*/
|
|
143
|
+
export declare function writeMiaixzVersionedValue<T>(options: Readonly<Omit<MiaixzVersionedStorageOptions<T>, "migrations" | "parse">>, value: T | undefined): void;
|
|
144
|
+
/**
|
|
145
|
+
* In-memory storage adapter suitable for tests, SSR, and isolated runtimes.
|
|
146
|
+
*
|
|
147
|
+
* @public
|
|
148
|
+
*/
|
|
149
|
+
export declare class MiaixzMemoryStorage implements MiaixzKeyValueStorage {
|
|
150
|
+
#private;
|
|
151
|
+
/**
|
|
152
|
+
* Reads a value from memory.
|
|
153
|
+
*
|
|
154
|
+
* @param key - Storage key to read.
|
|
155
|
+
* @returns Serialized value or null when the key is absent.
|
|
156
|
+
*/
|
|
157
|
+
getItem(key: string): string | null;
|
|
158
|
+
/**
|
|
159
|
+
* Stores a value in memory.
|
|
160
|
+
*
|
|
161
|
+
* @param key - Storage key to write.
|
|
162
|
+
* @param value - Serialized value to store.
|
|
163
|
+
*/
|
|
164
|
+
setItem(key: string, value: string): void;
|
|
165
|
+
/**
|
|
166
|
+
* Removes one in-memory value.
|
|
167
|
+
*
|
|
168
|
+
* @param key - Storage key to remove.
|
|
169
|
+
*/
|
|
170
|
+
removeItem(key: string): void;
|
|
171
|
+
/**
|
|
172
|
+
* Removes every in-memory value.
|
|
173
|
+
*/
|
|
174
|
+
clear(): void;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Prefixes storage keys so multiple services can safely share one backend.
|
|
178
|
+
*
|
|
179
|
+
* @public
|
|
180
|
+
*/
|
|
181
|
+
export declare class MiaixzNamespacedStorage implements MiaixzKeyValueStorage {
|
|
182
|
+
#private;
|
|
183
|
+
/**
|
|
184
|
+
* Underlying storage adapter receiving the namespaced keys.
|
|
185
|
+
*/
|
|
186
|
+
readonly storage: MiaixzKeyValueStorage;
|
|
187
|
+
/**
|
|
188
|
+
* Prefix applied to every logical storage key.
|
|
189
|
+
*/
|
|
190
|
+
readonly namespace: string;
|
|
191
|
+
/**
|
|
192
|
+
* Creates a namespaced storage adapter.
|
|
193
|
+
*
|
|
194
|
+
* @param storage - Underlying adapter.
|
|
195
|
+
* @param namespace - Key prefix.
|
|
196
|
+
*/
|
|
197
|
+
constructor(storage: MiaixzKeyValueStorage, namespace: string);
|
|
198
|
+
/**
|
|
199
|
+
* Reads a namespaced value.
|
|
200
|
+
*
|
|
201
|
+
* @param key - Logical storage key to read.
|
|
202
|
+
* @returns Serialized value or null when the key is absent.
|
|
203
|
+
*/
|
|
204
|
+
getItem(key: string): string | null;
|
|
205
|
+
/**
|
|
206
|
+
* Stores a namespaced value.
|
|
207
|
+
*
|
|
208
|
+
* @param key - Logical storage key to write.
|
|
209
|
+
* @param value - Serialized value to store.
|
|
210
|
+
*/
|
|
211
|
+
setItem(key: string, value: string): void;
|
|
212
|
+
/**
|
|
213
|
+
* Removes a namespaced value.
|
|
214
|
+
*
|
|
215
|
+
* @param key - Logical storage key to remove.
|
|
216
|
+
*/
|
|
217
|
+
removeItem(key: string): void;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Safely obtains local or session storage when running in a browser.
|
|
221
|
+
*
|
|
222
|
+
* @param type - Browser storage area to obtain.
|
|
223
|
+
* @returns `undefined` during SSR or when browser storage is blocked.
|
|
224
|
+
* @public
|
|
225
|
+
*/
|
|
226
|
+
export declare function getMiaixzBrowserStorage(type?: "local" | "session"): MiaixzKeyValueStorage | undefined;
|
|
227
|
+
/**
|
|
228
|
+
* Parses and optionally validates JSON stored by a key-value adapter.
|
|
229
|
+
*
|
|
230
|
+
* @param storage - Optional storage adapter to read.
|
|
231
|
+
* @param key - Storage key containing JSON.
|
|
232
|
+
* @param validate - Optional type guard for parsed data.
|
|
233
|
+
* @returns Parsed and validated value when available.
|
|
234
|
+
* @public
|
|
235
|
+
*/
|
|
236
|
+
export declare function readMiaixzJson<T>(storage: MiaixzKeyValueStorage | undefined, key: string, validate?: (value: unknown) => value is T): T | undefined;
|
|
237
|
+
/**
|
|
238
|
+
* Serializes a value as JSON, or removes the key for `undefined`.
|
|
239
|
+
*
|
|
240
|
+
* @param storage - Optional storage adapter to update.
|
|
241
|
+
* @param key - Storage key to write or remove.
|
|
242
|
+
* @param value - Value to serialize, or undefined to remove the key.
|
|
243
|
+
* @public
|
|
244
|
+
*/
|
|
245
|
+
export declare function writeMiaixzJson<T>(storage: MiaixzKeyValueStorage | undefined, key: string, value: T | undefined): void;
|
|
246
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/storage/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import { MiaixzSdkError } from "../api/errors.js";
|
|
2
|
+
import { translateMiaixzDefaultMessage } from "../i18n/default-translator.js";
|
|
3
|
+
const miaixzApplicationIdPattern = /^[a-z][a-z0-9-]{1,63}$/;
|
|
4
|
+
const miaixzTenantIdPattern = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
5
|
+
const miaixzStorageKinds = new Set(["appearance", "context", "preferences"]);
|
|
6
|
+
/**
|
|
7
|
+
* Creates the fixed localized error for an invalid storage scope or kind.
|
|
8
|
+
*
|
|
9
|
+
* @returns Stable SDK storage-scope error.
|
|
10
|
+
*/
|
|
11
|
+
function createStorageScopeError() {
|
|
12
|
+
return new MiaixzSdkError(translateMiaixzDefaultMessage("sdk.error.storage.scopeInvalid"), {
|
|
13
|
+
code: "STORAGE_SCOPE_INVALID",
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Creates the fixed localized error for invalid schema or migration configuration.
|
|
18
|
+
*
|
|
19
|
+
* @returns Stable SDK migration-chain error.
|
|
20
|
+
*/
|
|
21
|
+
function createMigrationChainError() {
|
|
22
|
+
return new MiaixzSdkError(translateMiaixzDefaultMessage("sdk.error.storage.migrationChainInvalid"), { code: "STORAGE_MIGRATION_CHAIN_INVALID" });
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Reports whether a number is a non-negative safe schema version.
|
|
26
|
+
*
|
|
27
|
+
* @param value - Version candidate to inspect.
|
|
28
|
+
* @returns Whether the value is a supported persisted or migration version.
|
|
29
|
+
*/
|
|
30
|
+
function isNonNegativeSchemaVersion(value) {
|
|
31
|
+
return Number.isSafeInteger(value) && value >= 0;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Validates a current target schema version.
|
|
35
|
+
*
|
|
36
|
+
* @param schemaVersion - Target version to validate.
|
|
37
|
+
* @throws MiaixzSdkError When the target is not a positive safe integer.
|
|
38
|
+
*/
|
|
39
|
+
function validateTargetSchemaVersion(schemaVersion) {
|
|
40
|
+
if (!Number.isSafeInteger(schemaVersion) || schemaVersion < 1) {
|
|
41
|
+
throw createMigrationChainError();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Validates the complete configured migration sequence in caller order.
|
|
46
|
+
*
|
|
47
|
+
* @param migrations - Optional migration chain to validate.
|
|
48
|
+
* @throws MiaixzSdkError When a version is invalid, duplicated, or discontinuous.
|
|
49
|
+
*/
|
|
50
|
+
function validateMigrationChain(migrations = []) {
|
|
51
|
+
let previousTarget;
|
|
52
|
+
for (const migration of migrations) {
|
|
53
|
+
if (!migration ||
|
|
54
|
+
typeof migration !== "object" ||
|
|
55
|
+
!isNonNegativeSchemaVersion(migration.from) ||
|
|
56
|
+
!isNonNegativeSchemaVersion(migration.to) ||
|
|
57
|
+
migration.to !== migration.from + 1 ||
|
|
58
|
+
(previousTarget !== undefined && migration.from !== previousTarget) ||
|
|
59
|
+
typeof migration.migrate !== "function") {
|
|
60
|
+
throw createMigrationChainError();
|
|
61
|
+
}
|
|
62
|
+
previousTarget = migration.to;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Builds a collision-safe physical key for versioned Miaixz data.
|
|
67
|
+
*
|
|
68
|
+
* @param scope - Application and optional tenant persistence boundary.
|
|
69
|
+
* @param kind - Fixed persisted data category.
|
|
70
|
+
* @returns Physical storage key using the Miaixz version-one namespace.
|
|
71
|
+
* @throws MiaixzSdkError When the application, tenant, or kind is invalid.
|
|
72
|
+
* @public
|
|
73
|
+
*/
|
|
74
|
+
export function createMiaixzStorageKey(scope, kind) {
|
|
75
|
+
if (!scope ||
|
|
76
|
+
!miaixzApplicationIdPattern.test(scope.appId) ||
|
|
77
|
+
(scope.tenantId !== undefined &&
|
|
78
|
+
(!miaixzTenantIdPattern.test(scope.tenantId) || scope.tenantId === "global")) ||
|
|
79
|
+
!miaixzStorageKinds.has(kind)) {
|
|
80
|
+
throw createStorageScopeError();
|
|
81
|
+
}
|
|
82
|
+
return `miaixz:v1:${scope.tenantId ?? "global"}:${scope.appId}:${kind}`;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Reports whether parsed JSON uses the exact versioned-value envelope.
|
|
86
|
+
*
|
|
87
|
+
* @param value - Parsed JSON candidate to inspect.
|
|
88
|
+
* @returns Whether the value contains exactly schemaVersion and value fields.
|
|
89
|
+
*/
|
|
90
|
+
function isVersionedEnvelope(value) {
|
|
91
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
92
|
+
return false;
|
|
93
|
+
const keys = Object.keys(value);
|
|
94
|
+
return (keys.length === 2 &&
|
|
95
|
+
keys.includes("schemaVersion") &&
|
|
96
|
+
keys.includes("value") &&
|
|
97
|
+
"schemaVersion" in value &&
|
|
98
|
+
"value" in value);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Removes one physical storage key while swallowing adapter failures.
|
|
102
|
+
*
|
|
103
|
+
* @param storage - Storage adapter to update.
|
|
104
|
+
* @param key - Exact physical key to remove.
|
|
105
|
+
*/
|
|
106
|
+
function safelyRemoveStorageValue(storage, key) {
|
|
107
|
+
try {
|
|
108
|
+
storage.removeItem(key);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// Persistence failures never change the caller's in-memory state.
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Reads, migrates, validates, and optionally upgrades one versioned value.
|
|
116
|
+
*
|
|
117
|
+
* @typeParam T - Parsed application value type.
|
|
118
|
+
* @param options - Scope, schema, migration, parser, and storage configuration.
|
|
119
|
+
* @returns Parsed normalized value, or undefined when data is absent or unusable.
|
|
120
|
+
* @throws MiaixzSdkError When scope, schema, or migration configuration is invalid.
|
|
121
|
+
* @public
|
|
122
|
+
*/
|
|
123
|
+
export function readMiaixzVersionedValue(options) {
|
|
124
|
+
const key = createMiaixzStorageKey(options.scope, options.kind);
|
|
125
|
+
validateTargetSchemaVersion(options.schemaVersion);
|
|
126
|
+
validateMigrationChain(options.migrations);
|
|
127
|
+
if (!options.storage)
|
|
128
|
+
return undefined;
|
|
129
|
+
let serialized;
|
|
130
|
+
try {
|
|
131
|
+
serialized = options.storage.getItem(key);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
if (serialized === null)
|
|
137
|
+
return undefined;
|
|
138
|
+
try {
|
|
139
|
+
const envelope = JSON.parse(serialized);
|
|
140
|
+
if (!isVersionedEnvelope(envelope) || !isNonNegativeSchemaVersion(envelope.schemaVersion)) {
|
|
141
|
+
safelyRemoveStorageValue(options.storage, key);
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
if (envelope.schemaVersion > options.schemaVersion) {
|
|
145
|
+
safelyRemoveStorageValue(options.storage, key);
|
|
146
|
+
return undefined;
|
|
147
|
+
}
|
|
148
|
+
let currentVersion = envelope.schemaVersion;
|
|
149
|
+
let migratedValue = envelope.value;
|
|
150
|
+
while (currentVersion < options.schemaVersion) {
|
|
151
|
+
const migration = options.migrations?.find((candidate) => candidate.from === currentVersion);
|
|
152
|
+
if (!migration) {
|
|
153
|
+
safelyRemoveStorageValue(options.storage, key);
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
migratedValue = migration.migrate(migratedValue);
|
|
157
|
+
currentVersion = migration.to;
|
|
158
|
+
}
|
|
159
|
+
const parsed = options.parse(migratedValue);
|
|
160
|
+
if (envelope.schemaVersion < options.schemaVersion) {
|
|
161
|
+
writeMiaixzVersionedValue({
|
|
162
|
+
storage: options.storage,
|
|
163
|
+
scope: options.scope,
|
|
164
|
+
kind: options.kind,
|
|
165
|
+
schemaVersion: options.schemaVersion,
|
|
166
|
+
}, parsed);
|
|
167
|
+
}
|
|
168
|
+
return parsed;
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
safelyRemoveStorageValue(options.storage, key);
|
|
172
|
+
return undefined;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Writes or removes one versioned value without affecting caller memory on persistence failure.
|
|
177
|
+
*
|
|
178
|
+
* @typeParam T - Persisted application value type.
|
|
179
|
+
* @param options - Scope, target schema, and optional storage configuration.
|
|
180
|
+
* @param value - Value to persist, or undefined to remove the physical key.
|
|
181
|
+
* @throws MiaixzSdkError When scope, kind, or target schema is invalid.
|
|
182
|
+
* @public
|
|
183
|
+
*/
|
|
184
|
+
export function writeMiaixzVersionedValue(options, value) {
|
|
185
|
+
const key = createMiaixzStorageKey(options.scope, options.kind);
|
|
186
|
+
validateTargetSchemaVersion(options.schemaVersion);
|
|
187
|
+
if (!options.storage)
|
|
188
|
+
return;
|
|
189
|
+
if (value === undefined) {
|
|
190
|
+
safelyRemoveStorageValue(options.storage, key);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
try {
|
|
194
|
+
const envelope = {
|
|
195
|
+
schemaVersion: options.schemaVersion,
|
|
196
|
+
value,
|
|
197
|
+
};
|
|
198
|
+
options.storage.setItem(key, JSON.stringify(envelope));
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
// Serialization and adapter failures intentionally degrade to non-persistence.
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* In-memory storage adapter suitable for tests, SSR, and isolated runtimes.
|
|
206
|
+
*
|
|
207
|
+
* @public
|
|
208
|
+
*/
|
|
209
|
+
export class MiaixzMemoryStorage {
|
|
210
|
+
#values = new Map();
|
|
211
|
+
/**
|
|
212
|
+
* Reads a value from memory.
|
|
213
|
+
*
|
|
214
|
+
* @param key - Storage key to read.
|
|
215
|
+
* @returns Serialized value or null when the key is absent.
|
|
216
|
+
*/
|
|
217
|
+
getItem(key) {
|
|
218
|
+
return this.#values.get(key) ?? null;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Stores a value in memory.
|
|
222
|
+
*
|
|
223
|
+
* @param key - Storage key to write.
|
|
224
|
+
* @param value - Serialized value to store.
|
|
225
|
+
*/
|
|
226
|
+
setItem(key, value) {
|
|
227
|
+
this.#values.set(key, value);
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Removes one in-memory value.
|
|
231
|
+
*
|
|
232
|
+
* @param key - Storage key to remove.
|
|
233
|
+
*/
|
|
234
|
+
removeItem(key) {
|
|
235
|
+
this.#values.delete(key);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Removes every in-memory value.
|
|
239
|
+
*/
|
|
240
|
+
clear() {
|
|
241
|
+
this.#values.clear();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Prefixes storage keys so multiple services can safely share one backend.
|
|
246
|
+
*
|
|
247
|
+
* @public
|
|
248
|
+
*/
|
|
249
|
+
export class MiaixzNamespacedStorage {
|
|
250
|
+
/**
|
|
251
|
+
* Underlying storage adapter receiving the namespaced keys.
|
|
252
|
+
*/
|
|
253
|
+
storage;
|
|
254
|
+
/**
|
|
255
|
+
* Prefix applied to every logical storage key.
|
|
256
|
+
*/
|
|
257
|
+
namespace;
|
|
258
|
+
/**
|
|
259
|
+
* Creates a namespaced storage adapter.
|
|
260
|
+
*
|
|
261
|
+
* @param storage - Underlying adapter.
|
|
262
|
+
* @param namespace - Key prefix.
|
|
263
|
+
*/
|
|
264
|
+
constructor(storage, namespace) {
|
|
265
|
+
this.storage = storage;
|
|
266
|
+
this.namespace = namespace;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Builds the physical key used by the underlying adapter.
|
|
270
|
+
*
|
|
271
|
+
* @param key - Logical storage key.
|
|
272
|
+
* @returns Namespaced physical storage key.
|
|
273
|
+
*/
|
|
274
|
+
#key(key) {
|
|
275
|
+
return `${this.namespace}:${key}`;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Reads a namespaced value.
|
|
279
|
+
*
|
|
280
|
+
* @param key - Logical storage key to read.
|
|
281
|
+
* @returns Serialized value or null when the key is absent.
|
|
282
|
+
*/
|
|
283
|
+
getItem(key) {
|
|
284
|
+
return this.storage.getItem(this.#key(key));
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Stores a namespaced value.
|
|
288
|
+
*
|
|
289
|
+
* @param key - Logical storage key to write.
|
|
290
|
+
* @param value - Serialized value to store.
|
|
291
|
+
*/
|
|
292
|
+
setItem(key, value) {
|
|
293
|
+
this.storage.setItem(this.#key(key), value);
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Removes a namespaced value.
|
|
297
|
+
*
|
|
298
|
+
* @param key - Logical storage key to remove.
|
|
299
|
+
*/
|
|
300
|
+
removeItem(key) {
|
|
301
|
+
this.storage.removeItem(this.#key(key));
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Safely obtains local or session storage when running in a browser.
|
|
306
|
+
*
|
|
307
|
+
* @param type - Browser storage area to obtain.
|
|
308
|
+
* @returns `undefined` during SSR or when browser storage is blocked.
|
|
309
|
+
* @public
|
|
310
|
+
*/
|
|
311
|
+
export function getMiaixzBrowserStorage(type = "local") {
|
|
312
|
+
if (typeof window === "undefined")
|
|
313
|
+
return undefined;
|
|
314
|
+
try {
|
|
315
|
+
return type === "local" ? window.localStorage : window.sessionStorage;
|
|
316
|
+
}
|
|
317
|
+
catch {
|
|
318
|
+
return undefined;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Parses and optionally validates JSON stored by a key-value adapter.
|
|
323
|
+
*
|
|
324
|
+
* @param storage - Optional storage adapter to read.
|
|
325
|
+
* @param key - Storage key containing JSON.
|
|
326
|
+
* @param validate - Optional type guard for parsed data.
|
|
327
|
+
* @returns Parsed and validated value when available.
|
|
328
|
+
* @public
|
|
329
|
+
*/
|
|
330
|
+
export function readMiaixzJson(storage, key, validate) {
|
|
331
|
+
const serialized = storage?.getItem(key);
|
|
332
|
+
if (!serialized)
|
|
333
|
+
return undefined;
|
|
334
|
+
try {
|
|
335
|
+
const value = JSON.parse(serialized);
|
|
336
|
+
return validate && !validate(value) ? undefined : value;
|
|
337
|
+
}
|
|
338
|
+
catch {
|
|
339
|
+
return undefined;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Serializes a value as JSON, or removes the key for `undefined`.
|
|
344
|
+
*
|
|
345
|
+
* @param storage - Optional storage adapter to update.
|
|
346
|
+
* @param key - Storage key to write or remove.
|
|
347
|
+
* @param value - Value to serialize, or undefined to remove the key.
|
|
348
|
+
* @public
|
|
349
|
+
*/
|
|
350
|
+
export function writeMiaixzJson(storage, key, value) {
|
|
351
|
+
if (!storage)
|
|
352
|
+
return;
|
|
353
|
+
if (value === undefined)
|
|
354
|
+
storage.removeItem(key);
|
|
355
|
+
else
|
|
356
|
+
storage.setItem(key, JSON.stringify(value));
|
|
357
|
+
}
|
|
358
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/storage/storage.ts"],"names":[],"mappings":"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","sourcesContent":["import { MiaixzSdkError } from \"../api/errors.js\";\nimport type { MiaixzResponseParser } from \"../api/request.js\";\nimport { translateMiaixzDefaultMessage } from \"../i18n/default-translator.js\";\n\n/**\n * Defines the browser-compatible storage operations required by the SDK.\n *\n * @public\n */\nexport interface MiaixzKeyValueStorage {\n /**\n * Reads a serialized value or returns `null` when the key is absent.\n *\n * @param key - Storage key to read.\n * @returns Serialized value or null when the key is absent.\n */\n getItem(key: string): string | null;\n /**\n * Stores a serialized value under the supplied key.\n *\n * @param key - Storage key to write.\n * @param value - Serialized value to store.\n */\n setItem(key: string, value: string): void;\n /**\n * Removes the supplied key.\n *\n * @param key - Storage key to remove.\n */\n removeItem(key: string): void;\n}\n\n/**\n * Wraps persisted data with its schema version.\n *\n * @typeParam T - Persisted application value type.\n * @public\n */\nexport interface MiaixzVersionedValue<T> {\n /**\n * Identifies the schema used to serialize the value.\n */\n readonly schemaVersion: number;\n\n /**\n * Contains the persisted application value.\n */\n readonly value: T;\n}\n\n/**\n * Migrates one persisted schema version to its immediate successor.\n *\n * @public\n */\nexport interface MiaixzStorageMigration {\n /**\n * Identifies the source schema version.\n */\n readonly from: number;\n\n /**\n * Identifies the immediate target schema version.\n */\n readonly to: number;\n\n /**\n * Converts one untrusted persisted value to the next schema.\n *\n * @param value - Value produced by storage or the previous migration.\n * @returns Value represented in the target schema.\n */\n migrate(value: unknown): unknown;\n}\n\n/**\n * Identifies the application and optional tenant owning persisted data.\n *\n * @public\n */\nexport interface MiaixzStorageScope {\n /**\n * Identifies the consuming frontend application.\n */\n readonly appId: string;\n\n /**\n * Identifies the optional tenant-specific persistence boundary.\n */\n readonly tenantId?: string;\n}\n\n/**\n * Configures validated versioned storage reads.\n *\n * @typeParam T - Parsed application value type.\n * @public\n */\nexport interface MiaixzVersionedStorageOptions<T> {\n /**\n * Supplies the optional physical storage adapter.\n */\n readonly storage?: MiaixzKeyValueStorage;\n\n /**\n * Selects the application and tenant persistence boundary.\n */\n readonly scope: Readonly<MiaixzStorageScope>;\n\n /**\n * Selects the fixed persisted data category.\n */\n readonly kind: \"appearance\" | \"context\" | \"preferences\";\n\n /**\n * Identifies the current target schema version.\n */\n readonly schemaVersion: number;\n\n /**\n * Supplies an optional continuous sequence of one-version migrations.\n */\n readonly migrations?: readonly MiaixzStorageMigration[];\n\n /**\n * Parses the current-schema value into its normalized application representation.\n */\n readonly parse: MiaixzResponseParser<T>;\n}\n\nconst miaixzApplicationIdPattern = /^[a-z][a-z0-9-]{1,63}$/;\nconst miaixzTenantIdPattern = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;\nconst miaixzStorageKinds = new Set([\"appearance\", \"context\", \"preferences\"]);\n\n/**\n * Creates the fixed localized error for an invalid storage scope or kind.\n *\n * @returns Stable SDK storage-scope error.\n */\nfunction createStorageScopeError(): MiaixzSdkError {\n return new MiaixzSdkError(translateMiaixzDefaultMessage(\"sdk.error.storage.scopeInvalid\"), {\n code: \"STORAGE_SCOPE_INVALID\",\n });\n}\n\n/**\n * Creates the fixed localized error for invalid schema or migration configuration.\n *\n * @returns Stable SDK migration-chain error.\n */\nfunction createMigrationChainError(): MiaixzSdkError {\n return new MiaixzSdkError(\n translateMiaixzDefaultMessage(\"sdk.error.storage.migrationChainInvalid\"),\n { code: \"STORAGE_MIGRATION_CHAIN_INVALID\" },\n );\n}\n\n/**\n * Reports whether a number is a non-negative safe schema version.\n *\n * @param value - Version candidate to inspect.\n * @returns Whether the value is a supported persisted or migration version.\n */\nfunction isNonNegativeSchemaVersion(value: number): boolean {\n return Number.isSafeInteger(value) && value >= 0;\n}\n\n/**\n * Validates a current target schema version.\n *\n * @param schemaVersion - Target version to validate.\n * @throws MiaixzSdkError When the target is not a positive safe integer.\n */\nfunction validateTargetSchemaVersion(schemaVersion: number): void {\n if (!Number.isSafeInteger(schemaVersion) || schemaVersion < 1) {\n throw createMigrationChainError();\n }\n}\n\n/**\n * Validates the complete configured migration sequence in caller order.\n *\n * @param migrations - Optional migration chain to validate.\n * @throws MiaixzSdkError When a version is invalid, duplicated, or discontinuous.\n */\nfunction validateMigrationChain(migrations: readonly MiaixzStorageMigration[] = []): void {\n let previousTarget: number | undefined;\n for (const migration of migrations) {\n if (\n !migration ||\n typeof migration !== \"object\" ||\n !isNonNegativeSchemaVersion(migration.from) ||\n !isNonNegativeSchemaVersion(migration.to) ||\n migration.to !== migration.from + 1 ||\n (previousTarget !== undefined && migration.from !== previousTarget) ||\n typeof migration.migrate !== \"function\"\n ) {\n throw createMigrationChainError();\n }\n previousTarget = migration.to;\n }\n}\n\n/**\n * Builds a collision-safe physical key for versioned Miaixz data.\n *\n * @param scope - Application and optional tenant persistence boundary.\n * @param kind - Fixed persisted data category.\n * @returns Physical storage key using the Miaixz version-one namespace.\n * @throws MiaixzSdkError When the application, tenant, or kind is invalid.\n * @public\n */\nexport function createMiaixzStorageKey(\n scope: Readonly<MiaixzStorageScope>,\n kind: \"appearance\" | \"context\" | \"preferences\",\n): string {\n if (\n !scope ||\n !miaixzApplicationIdPattern.test(scope.appId) ||\n (scope.tenantId !== undefined &&\n (!miaixzTenantIdPattern.test(scope.tenantId) || scope.tenantId === \"global\")) ||\n !miaixzStorageKinds.has(kind)\n ) {\n throw createStorageScopeError();\n }\n return `miaixz:v1:${scope.tenantId ?? \"global\"}:${scope.appId}:${kind}`;\n}\n\n/**\n * Reports whether parsed JSON uses the exact versioned-value envelope.\n *\n * @param value - Parsed JSON candidate to inspect.\n * @returns Whether the value contains exactly schemaVersion and value fields.\n */\nfunction isVersionedEnvelope(value: unknown): value is MiaixzVersionedValue<unknown> {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) return false;\n const keys = Object.keys(value);\n return (\n keys.length === 2 &&\n keys.includes(\"schemaVersion\") &&\n keys.includes(\"value\") &&\n \"schemaVersion\" in value &&\n \"value\" in value\n );\n}\n\n/**\n * Removes one physical storage key while swallowing adapter failures.\n *\n * @param storage - Storage adapter to update.\n * @param key - Exact physical key to remove.\n */\nfunction safelyRemoveStorageValue(storage: MiaixzKeyValueStorage, key: string): void {\n try {\n storage.removeItem(key);\n } catch {\n // Persistence failures never change the caller's in-memory state.\n }\n}\n\n/**\n * Reads, migrates, validates, and optionally upgrades one versioned value.\n *\n * @typeParam T - Parsed application value type.\n * @param options - Scope, schema, migration, parser, and storage configuration.\n * @returns Parsed normalized value, or undefined when data is absent or unusable.\n * @throws MiaixzSdkError When scope, schema, or migration configuration is invalid.\n * @public\n */\nexport function readMiaixzVersionedValue<T>(\n options: Readonly<MiaixzVersionedStorageOptions<T>>,\n): T | undefined {\n const key = createMiaixzStorageKey(options.scope, options.kind);\n validateTargetSchemaVersion(options.schemaVersion);\n validateMigrationChain(options.migrations);\n if (!options.storage) return undefined;\n let serialized: string | null;\n try {\n serialized = options.storage.getItem(key);\n } catch {\n return undefined;\n }\n if (serialized === null) return undefined;\n try {\n const envelope: unknown = JSON.parse(serialized);\n if (!isVersionedEnvelope(envelope) || !isNonNegativeSchemaVersion(envelope.schemaVersion)) {\n safelyRemoveStorageValue(options.storage, key);\n return undefined;\n }\n if (envelope.schemaVersion > options.schemaVersion) {\n safelyRemoveStorageValue(options.storage, key);\n return undefined;\n }\n let currentVersion = envelope.schemaVersion;\n let migratedValue: unknown = envelope.value;\n while (currentVersion < options.schemaVersion) {\n const migration = options.migrations?.find((candidate) => candidate.from === currentVersion);\n if (!migration) {\n safelyRemoveStorageValue(options.storage, key);\n return undefined;\n }\n migratedValue = migration.migrate(migratedValue);\n currentVersion = migration.to;\n }\n const parsed = options.parse(migratedValue);\n if (envelope.schemaVersion < options.schemaVersion) {\n writeMiaixzVersionedValue(\n {\n storage: options.storage,\n scope: options.scope,\n kind: options.kind,\n schemaVersion: options.schemaVersion,\n },\n parsed,\n );\n }\n return parsed;\n } catch {\n safelyRemoveStorageValue(options.storage, key);\n return undefined;\n }\n}\n\n/**\n * Writes or removes one versioned value without affecting caller memory on persistence failure.\n *\n * @typeParam T - Persisted application value type.\n * @param options - Scope, target schema, and optional storage configuration.\n * @param value - Value to persist, or undefined to remove the physical key.\n * @throws MiaixzSdkError When scope, kind, or target schema is invalid.\n * @public\n */\nexport function writeMiaixzVersionedValue<T>(\n options: Readonly<Omit<MiaixzVersionedStorageOptions<T>, \"migrations\" | \"parse\">>,\n value: T | undefined,\n): void {\n const key = createMiaixzStorageKey(options.scope, options.kind);\n validateTargetSchemaVersion(options.schemaVersion);\n if (!options.storage) return;\n if (value === undefined) {\n safelyRemoveStorageValue(options.storage, key);\n return;\n }\n try {\n const envelope: MiaixzVersionedValue<T> = {\n schemaVersion: options.schemaVersion,\n value,\n };\n options.storage.setItem(key, JSON.stringify(envelope));\n } catch {\n // Serialization and adapter failures intentionally degrade to non-persistence.\n }\n}\n\n/**\n * In-memory storage adapter suitable for tests, SSR, and isolated runtimes.\n *\n * @public\n */\nexport class MiaixzMemoryStorage implements MiaixzKeyValueStorage {\n readonly #values = new Map<string, string>();\n\n /**\n * Reads a value from memory.\n *\n * @param key - Storage key to read.\n * @returns Serialized value or null when the key is absent.\n */\n getItem(key: string): string | null {\n return this.#values.get(key) ?? null;\n }\n\n /**\n * Stores a value in memory.\n *\n * @param key - Storage key to write.\n * @param value - Serialized value to store.\n */\n setItem(key: string, value: string): void {\n this.#values.set(key, value);\n }\n\n /**\n * Removes one in-memory value.\n *\n * @param key - Storage key to remove.\n */\n removeItem(key: string): void {\n this.#values.delete(key);\n }\n\n /**\n * Removes every in-memory value.\n */\n clear(): void {\n this.#values.clear();\n }\n}\n\n/**\n * Prefixes storage keys so multiple services can safely share one backend.\n *\n * @public\n */\nexport class MiaixzNamespacedStorage implements MiaixzKeyValueStorage {\n /**\n * Underlying storage adapter receiving the namespaced keys.\n */\n readonly storage: MiaixzKeyValueStorage;\n\n /**\n * Prefix applied to every logical storage key.\n */\n readonly namespace: string;\n\n /**\n * Creates a namespaced storage adapter.\n *\n * @param storage - Underlying adapter.\n * @param namespace - Key prefix.\n */\n constructor(storage: MiaixzKeyValueStorage, namespace: string) {\n this.storage = storage;\n this.namespace = namespace;\n }\n\n /**\n * Builds the physical key used by the underlying adapter.\n *\n * @param key - Logical storage key.\n * @returns Namespaced physical storage key.\n */\n #key(key: string): string {\n return `${this.namespace}:${key}`;\n }\n\n /**\n * Reads a namespaced value.\n *\n * @param key - Logical storage key to read.\n * @returns Serialized value or null when the key is absent.\n */\n getItem(key: string): string | null {\n return this.storage.getItem(this.#key(key));\n }\n\n /**\n * Stores a namespaced value.\n *\n * @param key - Logical storage key to write.\n * @param value - Serialized value to store.\n */\n setItem(key: string, value: string): void {\n this.storage.setItem(this.#key(key), value);\n }\n\n /**\n * Removes a namespaced value.\n *\n * @param key - Logical storage key to remove.\n */\n removeItem(key: string): void {\n this.storage.removeItem(this.#key(key));\n }\n}\n\n/**\n * Safely obtains local or session storage when running in a browser.\n *\n * @param type - Browser storage area to obtain.\n * @returns `undefined` during SSR or when browser storage is blocked.\n * @public\n */\nexport function getMiaixzBrowserStorage(\n type: \"local\" | \"session\" = \"local\",\n): MiaixzKeyValueStorage | undefined {\n if (typeof window === \"undefined\") return undefined;\n try {\n return type === \"local\" ? window.localStorage : window.sessionStorage;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Parses and optionally validates JSON stored by a key-value adapter.\n *\n * @param storage - Optional storage adapter to read.\n * @param key - Storage key containing JSON.\n * @param validate - Optional type guard for parsed data.\n * @returns Parsed and validated value when available.\n * @public\n */\nexport function readMiaixzJson<T>(\n storage: MiaixzKeyValueStorage | undefined,\n key: string,\n validate?: (value: unknown) => value is T,\n): T | undefined {\n const serialized = storage?.getItem(key);\n if (!serialized) return undefined;\n try {\n const value: unknown = JSON.parse(serialized);\n return validate && !validate(value) ? undefined : (value as T);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Serializes a value as JSON, or removes the key for `undefined`.\n *\n * @param storage - Optional storage adapter to update.\n * @param key - Storage key to write or remove.\n * @param value - Value to serialize, or undefined to remove the key.\n * @public\n */\nexport function writeMiaixzJson<T>(\n storage: MiaixzKeyValueStorage | undefined,\n key: string,\n value: T | undefined,\n): void {\n if (!storage) return;\n if (value === undefined) storage.removeItem(key);\n else storage.setItem(key, JSON.stringify(value));\n}\n"]}
|