@alibarbar/common 1.0.9 → 1.1.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.
Files changed (185) hide show
  1. package/dist/{chunk-O3O67R4I.js → algorithm.cjs} +1 -3
  2. package/dist/algorithm.js +130 -44
  3. package/dist/{chunk-LOAZSPGQ.js → array.cjs} +1 -3
  4. package/dist/array.js +135 -84
  5. package/dist/{chunk-Y364QIQH.js → color.cjs} +1 -3
  6. package/dist/color.js +127 -40
  7. package/dist/{chunk-DYBSRI7V.js → crypto.cjs} +109 -3
  8. package/dist/crypto.d.mts +48 -1
  9. package/dist/crypto.d.ts +48 -1
  10. package/dist/crypto.js +274 -60
  11. package/dist/{chunk-BHCRFURU.js → data-structure.cjs} +1 -3
  12. package/dist/data-structure.js +481 -32
  13. package/dist/{chunk-I3L42475.js → date.cjs} +1 -3
  14. package/dist/date.js +125 -72
  15. package/dist/{chunk-JK2SE3I2.js → dom.cjs} +1 -3
  16. package/dist/dom.js +84 -56
  17. package/dist/{chunk-7V5UQXIO.js → file.cjs} +1 -3
  18. package/dist/file.js +79 -32
  19. package/dist/{chunk-OX5PLOWB.js → i18n.cjs} +1 -3
  20. package/dist/i18n.js +78 -40
  21. package/dist/index.cjs +4543 -0
  22. package/dist/index.d.mts +6 -162
  23. package/dist/index.d.ts +6 -162
  24. package/dist/index.js +3712 -17374
  25. package/dist/{chunk-4RGXV4SJ.js → network.cjs} +1 -3
  26. package/dist/network.js +97 -28
  27. package/dist/{chunk-3FRYJPHG.js → number.cjs} +1 -3
  28. package/dist/number.js +77 -56
  29. package/dist/{chunk-27UDDVLZ.js → object.cjs} +1 -3
  30. package/dist/object.js +237 -80
  31. package/dist/{chunk-JQZBPAPO.js → performance.cjs} +1 -3
  32. package/dist/performance.js +145 -40
  33. package/dist/services.cjs +291 -0
  34. package/dist/services.d.mts +161 -0
  35. package/dist/services.d.ts +161 -0
  36. package/dist/services.js +281 -0
  37. package/dist/storage.cjs +943 -0
  38. package/dist/storage.d.mts +46 -1
  39. package/dist/storage.d.ts +46 -1
  40. package/dist/storage.js +930 -32
  41. package/dist/{chunk-D7CS5EKF.js → string.cjs} +1 -3
  42. package/dist/string.js +91 -68
  43. package/dist/{chunk-56W6YECK.js → tracking.cjs} +1 -3
  44. package/dist/tracking.js +359 -52
  45. package/dist/{chunk-ZDMFMUDR.js → transform.cjs} +1 -3
  46. package/dist/transform.js +299 -32
  47. package/dist/{chunk-NJARVI6X.mjs → upload.cjs} +42 -15
  48. package/dist/upload.d.mts +1 -1
  49. package/dist/upload.d.ts +1 -1
  50. package/dist/upload.js +402 -20
  51. package/dist/{chunk-KGFTD255.js → url.cjs} +1 -3
  52. package/dist/url.js +91 -44
  53. package/dist/{chunk-TQN37HIN.js → validation.cjs} +1 -3
  54. package/dist/validation.js +77 -60
  55. package/package.json +7 -2
  56. package/dist/algorithm.js.map +0 -1
  57. package/dist/algorithm.mjs +0 -4
  58. package/dist/algorithm.mjs.map +0 -1
  59. package/dist/array.js.map +0 -1
  60. package/dist/array.mjs +0 -4
  61. package/dist/array.mjs.map +0 -1
  62. package/dist/chunk-27UDDVLZ.js.map +0 -1
  63. package/dist/chunk-2R2QWFJC.mjs +0 -138
  64. package/dist/chunk-2R2QWFJC.mjs.map +0 -1
  65. package/dist/chunk-3FRYJPHG.js.map +0 -1
  66. package/dist/chunk-4RGXV4SJ.js.map +0 -1
  67. package/dist/chunk-56W6YECK.js.map +0 -1
  68. package/dist/chunk-5BGSUGTI.mjs +0 -128
  69. package/dist/chunk-5BGSUGTI.mjs.map +0 -1
  70. package/dist/chunk-7E6GELHJ.mjs +0 -302
  71. package/dist/chunk-7E6GELHJ.mjs.map +0 -1
  72. package/dist/chunk-7V5UQXIO.js.map +0 -1
  73. package/dist/chunk-A4SWQXX7.mjs +0 -484
  74. package/dist/chunk-A4SWQXX7.mjs.map +0 -1
  75. package/dist/chunk-BHCRFURU.js.map +0 -1
  76. package/dist/chunk-CDSGEAOK.mjs +0 -80
  77. package/dist/chunk-CDSGEAOK.mjs.map +0 -1
  78. package/dist/chunk-D7CS5EKF.js.map +0 -1
  79. package/dist/chunk-DYBSRI7V.js.map +0 -1
  80. package/dist/chunk-FEBKPX5A.js +0 -386
  81. package/dist/chunk-FEBKPX5A.js.map +0 -1
  82. package/dist/chunk-FJ6ZGZIA.mjs +0 -39
  83. package/dist/chunk-FJ6ZGZIA.mjs.map +0 -1
  84. package/dist/chunk-HLDFI7R2.mjs +0 -175
  85. package/dist/chunk-HLDFI7R2.mjs.map +0 -1
  86. package/dist/chunk-I3L42475.js.map +0 -1
  87. package/dist/chunk-JBLX27WD.mjs +0 -240
  88. package/dist/chunk-JBLX27WD.mjs.map +0 -1
  89. package/dist/chunk-JHZ7M2MR.mjs +0 -133
  90. package/dist/chunk-JHZ7M2MR.mjs.map +0 -1
  91. package/dist/chunk-JK2SE3I2.js.map +0 -1
  92. package/dist/chunk-JQZBPAPO.js.map +0 -1
  93. package/dist/chunk-JXYGC2C5.mjs +0 -100
  94. package/dist/chunk-JXYGC2C5.mjs.map +0 -1
  95. package/dist/chunk-KGFTD255.js.map +0 -1
  96. package/dist/chunk-LBHBNPNJ.mjs +0 -148
  97. package/dist/chunk-LBHBNPNJ.mjs.map +0 -1
  98. package/dist/chunk-LF4CILQS.mjs +0 -87
  99. package/dist/chunk-LF4CILQS.mjs.map +0 -1
  100. package/dist/chunk-LOAZSPGQ.js.map +0 -1
  101. package/dist/chunk-NJARVI6X.mjs.map +0 -1
  102. package/dist/chunk-NSSDYX2U.mjs +0 -80
  103. package/dist/chunk-NSSDYX2U.mjs.map +0 -1
  104. package/dist/chunk-O3O67R4I.js.map +0 -1
  105. package/dist/chunk-OIXQ3E6W.mjs +0 -354
  106. package/dist/chunk-OIXQ3E6W.mjs.map +0 -1
  107. package/dist/chunk-OX5PLOWB.js.map +0 -1
  108. package/dist/chunk-PJ7UCTX4.mjs +0 -362
  109. package/dist/chunk-PJ7UCTX4.mjs.map +0 -1
  110. package/dist/chunk-PR4QN5HX.js +0 -44
  111. package/dist/chunk-PR4QN5HX.js.map +0 -1
  112. package/dist/chunk-QIBE7GVN.mjs +0 -81
  113. package/dist/chunk-QIBE7GVN.mjs.map +0 -1
  114. package/dist/chunk-QIOC54LQ.mjs +0 -130
  115. package/dist/chunk-QIOC54LQ.mjs.map +0 -1
  116. package/dist/chunk-TQN37HIN.js.map +0 -1
  117. package/dist/chunk-WZDOPUJW.js +0 -361
  118. package/dist/chunk-WZDOPUJW.js.map +0 -1
  119. package/dist/chunk-XJTZDXSR.mjs +0 -94
  120. package/dist/chunk-XJTZDXSR.mjs.map +0 -1
  121. package/dist/chunk-Y364QIQH.js.map +0 -1
  122. package/dist/chunk-YXM6Q4JS.mjs +0 -94
  123. package/dist/chunk-YXM6Q4JS.mjs.map +0 -1
  124. package/dist/chunk-ZDMFMUDR.js.map +0 -1
  125. package/dist/chunk-ZVJ6NQUM.mjs +0 -82
  126. package/dist/chunk-ZVJ6NQUM.mjs.map +0 -1
  127. package/dist/color.js.map +0 -1
  128. package/dist/color.mjs +0 -4
  129. package/dist/color.mjs.map +0 -1
  130. package/dist/crypto.js.map +0 -1
  131. package/dist/crypto.mjs +0 -4
  132. package/dist/crypto.mjs.map +0 -1
  133. package/dist/data-structure.js.map +0 -1
  134. package/dist/data-structure.mjs +0 -4
  135. package/dist/data-structure.mjs.map +0 -1
  136. package/dist/date.js.map +0 -1
  137. package/dist/date.mjs +0 -4
  138. package/dist/date.mjs.map +0 -1
  139. package/dist/dom.js.map +0 -1
  140. package/dist/dom.mjs +0 -4
  141. package/dist/dom.mjs.map +0 -1
  142. package/dist/file.js.map +0 -1
  143. package/dist/file.mjs +0 -4
  144. package/dist/file.mjs.map +0 -1
  145. package/dist/i18n.js.map +0 -1
  146. package/dist/i18n.mjs +0 -4
  147. package/dist/i18n.mjs.map +0 -1
  148. package/dist/index.js.map +0 -1
  149. package/dist/index.mjs +0 -17155
  150. package/dist/index.mjs.map +0 -1
  151. package/dist/network.js.map +0 -1
  152. package/dist/network.mjs +0 -4
  153. package/dist/network.mjs.map +0 -1
  154. package/dist/number.js.map +0 -1
  155. package/dist/number.mjs +0 -4
  156. package/dist/number.mjs.map +0 -1
  157. package/dist/object.js.map +0 -1
  158. package/dist/object.mjs +0 -4
  159. package/dist/object.mjs.map +0 -1
  160. package/dist/performance.js.map +0 -1
  161. package/dist/performance.mjs +0 -4
  162. package/dist/performance.mjs.map +0 -1
  163. package/dist/storage.js.map +0 -1
  164. package/dist/storage.mjs +0 -5
  165. package/dist/storage.mjs.map +0 -1
  166. package/dist/string.js.map +0 -1
  167. package/dist/string.mjs +0 -4
  168. package/dist/string.mjs.map +0 -1
  169. package/dist/tracking.js.map +0 -1
  170. package/dist/tracking.mjs +0 -4
  171. package/dist/tracking.mjs.map +0 -1
  172. package/dist/transform.js.map +0 -1
  173. package/dist/transform.mjs +0 -4
  174. package/dist/transform.mjs.map +0 -1
  175. package/dist/upload.js.map +0 -1
  176. package/dist/upload.mjs +0 -5
  177. package/dist/upload.mjs.map +0 -1
  178. package/dist/url.js.map +0 -1
  179. package/dist/url.mjs +0 -4
  180. package/dist/url.mjs.map +0 -1
  181. package/dist/validation.js.map +0 -1
  182. package/dist/validation.mjs +0 -4
  183. package/dist/validation.mjs.map +0 -1
  184. /package/dist/{upload-DchqyDBQ.d.mts → index-DchqyDBQ.d.mts} +0 -0
  185. /package/dist/{upload-DchqyDBQ.d.ts → index-DchqyDBQ.d.ts} +0 -0
@@ -0,0 +1,943 @@
1
+ 'use strict';
2
+
3
+ // src/helper/crypto/index.ts
4
+ function base64Encode(data) {
5
+ if (typeof data === "string") {
6
+ return btoa(unescape(encodeURIComponent(data)));
7
+ }
8
+ const bytes = new Uint8Array(data);
9
+ let binary = "";
10
+ for (let i = 0; i < bytes.length; i++) {
11
+ binary += String.fromCharCode(bytes[i]);
12
+ }
13
+ return btoa(binary);
14
+ }
15
+ function base64Decode(data) {
16
+ try {
17
+ return decodeURIComponent(escape(atob(data)));
18
+ } catch {
19
+ throw new Error("Invalid Base64 string");
20
+ }
21
+ }
22
+ function generateRandomString(length, charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") {
23
+ let result = "";
24
+ for (let i = 0; i < length; i++) {
25
+ result += charset.charAt(Math.floor(Math.random() * charset.length));
26
+ }
27
+ return result;
28
+ }
29
+ async function generateRSAKeyPair(modulusLength = 2048) {
30
+ if (typeof crypto === "undefined" || !crypto.subtle) {
31
+ throw new Error("Web Crypto API is not available");
32
+ }
33
+ const keyPair = await crypto.subtle.generateKey(
34
+ {
35
+ name: "RSA-OAEP",
36
+ modulusLength,
37
+ publicExponent: new Uint8Array([1, 0, 1]),
38
+ hash: "SHA-256"
39
+ },
40
+ true,
41
+ ["encrypt", "decrypt"]
42
+ );
43
+ return {
44
+ publicKey: keyPair.publicKey,
45
+ privateKey: keyPair.privateKey
46
+ };
47
+ }
48
+ async function rsaEncrypt(data, publicKey) {
49
+ if (typeof crypto === "undefined" || !crypto.subtle) {
50
+ throw new Error("Web Crypto API is not available");
51
+ }
52
+ const encoder = new TextEncoder();
53
+ const dataBuffer = encoder.encode(data);
54
+ const maxChunkSize = 245;
55
+ const chunks = [];
56
+ for (let i = 0; i < dataBuffer.length; i += maxChunkSize) {
57
+ const chunk = dataBuffer.slice(i, i + maxChunkSize);
58
+ const encrypted = await crypto.subtle.encrypt(
59
+ {
60
+ name: "RSA-OAEP"
61
+ },
62
+ publicKey,
63
+ chunk
64
+ );
65
+ chunks.push(encrypted);
66
+ }
67
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);
68
+ const merged = new Uint8Array(totalLength);
69
+ let offset = 0;
70
+ for (const chunk of chunks) {
71
+ merged.set(new Uint8Array(chunk), offset);
72
+ offset += chunk.byteLength;
73
+ }
74
+ return base64Encode(merged.buffer);
75
+ }
76
+ async function rsaDecrypt(encryptedData, privateKey) {
77
+ if (typeof crypto === "undefined" || !crypto.subtle) {
78
+ throw new Error("Web Crypto API is not available");
79
+ }
80
+ const binaryString = atob(encryptedData);
81
+ const encryptedArray = new Uint8Array(binaryString.length);
82
+ for (let i = 0; i < binaryString.length; i++) {
83
+ encryptedArray[i] = binaryString.charCodeAt(i);
84
+ }
85
+ const chunkSize = 256;
86
+ const chunks = [];
87
+ for (let i = 0; i < encryptedArray.length; i += chunkSize) {
88
+ const chunk = encryptedArray.slice(i, i + chunkSize);
89
+ const decrypted = await crypto.subtle.decrypt(
90
+ {
91
+ name: "RSA-OAEP"
92
+ },
93
+ privateKey,
94
+ chunk
95
+ );
96
+ const decoder = new TextDecoder();
97
+ chunks.push(decoder.decode(decrypted));
98
+ }
99
+ return chunks.join("");
100
+ }
101
+ async function exportPublicKey(publicKey) {
102
+ if (typeof crypto === "undefined" || !crypto.subtle) {
103
+ throw new Error("Web Crypto API is not available");
104
+ }
105
+ const exported = await crypto.subtle.exportKey("spki", publicKey);
106
+ return base64Encode(exported);
107
+ }
108
+ async function exportPrivateKey(privateKey) {
109
+ if (typeof crypto === "undefined" || !crypto.subtle) {
110
+ throw new Error("Web Crypto API is not available");
111
+ }
112
+ const exported = await crypto.subtle.exportKey("pkcs8", privateKey);
113
+ return base64Encode(exported);
114
+ }
115
+ async function importPublicKey(keyData) {
116
+ if (typeof crypto === "undefined" || !crypto.subtle) {
117
+ throw new Error("Web Crypto API is not available");
118
+ }
119
+ const keyBuffer = base64Decode(keyData);
120
+ const keyArray = new Uint8Array(keyBuffer.split("").map((char) => char.charCodeAt(0)));
121
+ return crypto.subtle.importKey(
122
+ "spki",
123
+ keyArray.buffer,
124
+ {
125
+ name: "RSA-OAEP",
126
+ hash: "SHA-256"
127
+ },
128
+ true,
129
+ ["encrypt"]
130
+ );
131
+ }
132
+ async function importPrivateKey(keyData) {
133
+ if (typeof crypto === "undefined" || !crypto.subtle) {
134
+ throw new Error("Web Crypto API is not available");
135
+ }
136
+ const keyBuffer = base64Decode(keyData);
137
+ const keyArray = new Uint8Array(keyBuffer.split("").map((char) => char.charCodeAt(0)));
138
+ return crypto.subtle.importKey(
139
+ "pkcs8",
140
+ keyArray.buffer,
141
+ {
142
+ name: "RSA-OAEP",
143
+ hash: "SHA-256"
144
+ },
145
+ true,
146
+ ["decrypt"]
147
+ );
148
+ }
149
+ async function generateHMACKey() {
150
+ if (typeof crypto === "undefined" || !crypto.subtle) {
151
+ throw new Error("Web Crypto API is not available");
152
+ }
153
+ return crypto.subtle.generateKey(
154
+ {
155
+ name: "HMAC",
156
+ hash: "SHA-256"
157
+ },
158
+ true,
159
+ ["sign", "verify"]
160
+ );
161
+ }
162
+ async function computeHMAC(data, key) {
163
+ if (typeof crypto === "undefined" || !crypto.subtle) {
164
+ throw new Error("Web Crypto API is not available");
165
+ }
166
+ const buffer = typeof data === "string" ? new TextEncoder().encode(data) : data;
167
+ const signature = await crypto.subtle.sign("HMAC", key, buffer);
168
+ return base64Encode(signature);
169
+ }
170
+ async function verifyHMAC(data, signature, key) {
171
+ if (typeof crypto === "undefined" || !crypto.subtle) {
172
+ throw new Error("Web Crypto API is not available");
173
+ }
174
+ try {
175
+ const dataBuffer = typeof data === "string" ? new TextEncoder().encode(data) : data;
176
+ const signatureBuffer = new Uint8Array(
177
+ atob(signature).split("").map((char) => char.charCodeAt(0))
178
+ );
179
+ return await crypto.subtle.verify("HMAC", key, signatureBuffer, dataBuffer);
180
+ } catch {
181
+ return false;
182
+ }
183
+ }
184
+ async function deriveKeyFromPassword(password, salt, iterations = 1e5, keyLength = 256) {
185
+ if (typeof crypto === "undefined" || !crypto.subtle) {
186
+ throw new Error("Web Crypto API is not available");
187
+ }
188
+ const saltBuffer = typeof salt === "string" ? new TextEncoder().encode(salt) : salt;
189
+ const passwordKey = await crypto.subtle.importKey(
190
+ "raw",
191
+ new TextEncoder().encode(password),
192
+ "PBKDF2",
193
+ false,
194
+ ["deriveBits", "deriveKey"]
195
+ );
196
+ return crypto.subtle.deriveKey(
197
+ {
198
+ name: "PBKDF2",
199
+ salt: saltBuffer,
200
+ iterations,
201
+ hash: "SHA-256"
202
+ },
203
+ passwordKey,
204
+ {
205
+ name: "AES-GCM",
206
+ length: keyLength
207
+ },
208
+ false,
209
+ ["encrypt", "decrypt"]
210
+ );
211
+ }
212
+ async function aesGCMEncrypt(data, key) {
213
+ if (typeof crypto === "undefined" || !crypto.subtle) {
214
+ throw new Error("Web Crypto API is not available");
215
+ }
216
+ const dataBuffer = typeof data === "string" ? new TextEncoder().encode(data) : data;
217
+ const iv = crypto.getRandomValues(new Uint8Array(12));
218
+ const encrypted = await crypto.subtle.encrypt(
219
+ {
220
+ name: "AES-GCM",
221
+ iv
222
+ },
223
+ key,
224
+ dataBuffer
225
+ );
226
+ return {
227
+ encrypted: base64Encode(encrypted),
228
+ iv: base64Encode(iv.buffer)
229
+ };
230
+ }
231
+ async function aesGCMDecrypt(encryptedData, iv, key) {
232
+ if (typeof crypto === "undefined" || !crypto.subtle) {
233
+ throw new Error("Web Crypto API is not available");
234
+ }
235
+ const encryptedBuffer = new Uint8Array(
236
+ atob(encryptedData).split("").map((char) => char.charCodeAt(0))
237
+ );
238
+ const ivBuffer = new Uint8Array(
239
+ atob(iv).split("").map((char) => char.charCodeAt(0))
240
+ );
241
+ const decrypted = await crypto.subtle.decrypt(
242
+ {
243
+ name: "AES-GCM",
244
+ iv: ivBuffer
245
+ },
246
+ key,
247
+ encryptedBuffer
248
+ );
249
+ return new TextDecoder().decode(decrypted);
250
+ }
251
+
252
+ // src/browser/SecureStorage/index.ts
253
+ var globalKeyPair = null;
254
+ var globalHMACKey = null;
255
+ var keyPairInitialized = false;
256
+ var initOptions = {
257
+ autoGenerateKeys: true,
258
+ persistKeys: false,
259
+ keyStorageKey: void 0,
260
+ // 将自动生成随机键名
261
+ keyEncryptionPassword: void 0,
262
+ pbkdf2Iterations: 1e5,
263
+ keyModulusLength: 2048,
264
+ enableHMAC: true,
265
+ enableTimestampValidation: true,
266
+ timestampMaxAge: 7 * 24 * 60 * 60 * 1e3,
267
+ // 7 天
268
+ isProduction: false
269
+ };
270
+ var actualKeyStorageKey = null;
271
+ var keyUsageCount = 0;
272
+ var initializationPromise = null;
273
+ function generateKeyStorageKey() {
274
+ return `_sk_${generateRandomString(32)}_${Date.now()}`;
275
+ }
276
+ async function initializeStorageKeys(options = {}) {
277
+ if (options.forceReinitialize) {
278
+ globalKeyPair = null;
279
+ globalHMACKey = null;
280
+ keyPairInitialized = false;
281
+ actualKeyStorageKey = null;
282
+ keyUsageCount = 0;
283
+ initializationPromise = null;
284
+ } else if (keyPairInitialized && globalKeyPair) {
285
+ initOptions = { ...initOptions, ...options };
286
+ return;
287
+ }
288
+ initOptions = { ...initOptions, ...options };
289
+ if (initOptions.keyStorageKey) {
290
+ actualKeyStorageKey = initOptions.keyStorageKey;
291
+ } else {
292
+ actualKeyStorageKey = generateKeyStorageKey();
293
+ }
294
+ if (initOptions.persistKeys && typeof window !== "undefined" && window.localStorage) {
295
+ try {
296
+ const storedKeys = window.localStorage.getItem(actualKeyStorageKey);
297
+ if (storedKeys) {
298
+ const keyData = JSON.parse(storedKeys);
299
+ if (keyData.encrypted && keyData.privateKeyEncrypted && keyData.salt) {
300
+ if (!initOptions.keyEncryptionPassword) {
301
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
302
+ console.error("Encrypted keys found but no password provided");
303
+ }
304
+ throw new Error("Password required to decrypt stored keys");
305
+ }
306
+ const saltArray = new Uint8Array(
307
+ atob(keyData.salt).split("").map((char) => char.charCodeAt(0))
308
+ );
309
+ const iterations = keyData.pbkdf2Iterations || initOptions.pbkdf2Iterations;
310
+ const derivedKey = await deriveKeyFromPassword(
311
+ initOptions.keyEncryptionPassword,
312
+ saltArray.buffer,
313
+ iterations
314
+ );
315
+ const decryptedPrivateKey = await aesGCMDecrypt(
316
+ keyData.privateKeyEncrypted,
317
+ keyData.iv,
318
+ derivedKey
319
+ );
320
+ globalKeyPair = {
321
+ publicKey: await importPublicKey(keyData.publicKey),
322
+ privateKey: await importPrivateKey(decryptedPrivateKey)
323
+ };
324
+ } else if (keyData.publicKey && keyData.privateKey) {
325
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
326
+ console.warn(
327
+ "\u26A0\uFE0F SECURITY WARNING: Loading unencrypted keys from storage. Consider re-initializing with password encryption."
328
+ );
329
+ }
330
+ globalKeyPair = {
331
+ publicKey: await importPublicKey(keyData.publicKey),
332
+ privateKey: await importPrivateKey(keyData.privateKey)
333
+ };
334
+ }
335
+ if (globalKeyPair) {
336
+ keyPairInitialized = true;
337
+ if (initOptions.enableHMAC && !globalHMACKey) {
338
+ globalHMACKey = await generateHMACKey();
339
+ }
340
+ return;
341
+ }
342
+ }
343
+ } catch (error) {
344
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
345
+ console.warn("Failed to load persisted keys, will generate new ones");
346
+ }
347
+ }
348
+ }
349
+ if (initOptions.autoGenerateKeys && !globalKeyPair) {
350
+ try {
351
+ globalKeyPair = await generateRSAKeyPair(initOptions.keyModulusLength);
352
+ if (initOptions.enableHMAC && !globalHMACKey) {
353
+ globalHMACKey = await generateHMACKey();
354
+ }
355
+ keyPairInitialized = true;
356
+ keyUsageCount = 0;
357
+ if (initOptions.persistKeys && typeof window !== "undefined" && window.localStorage) {
358
+ try {
359
+ const publicKeyStr = await exportPublicKey(globalKeyPair.publicKey);
360
+ if (initOptions.keyEncryptionPassword) {
361
+ const privateKeyStr = await exportPrivateKey(globalKeyPair.privateKey);
362
+ const salt = crypto.getRandomValues(new Uint8Array(16));
363
+ const derivedKey = await deriveKeyFromPassword(
364
+ initOptions.keyEncryptionPassword,
365
+ salt.buffer,
366
+ initOptions.pbkdf2Iterations
367
+ );
368
+ const { encrypted, iv } = await aesGCMEncrypt(privateKeyStr, derivedKey);
369
+ const keyData = {
370
+ encrypted: true,
371
+ publicKey: publicKeyStr,
372
+ privateKeyEncrypted: encrypted,
373
+ iv,
374
+ salt: base64Encode(salt.buffer),
375
+ pbkdf2Iterations: initOptions.pbkdf2Iterations
376
+ };
377
+ window.localStorage.setItem(actualKeyStorageKey, JSON.stringify(keyData));
378
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.info) {
379
+ console.info("\u2705 Keys encrypted and stored securely");
380
+ }
381
+ } else {
382
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
383
+ console.warn(
384
+ "\u26A0\uFE0F SECURITY WARNING: Storing private keys without encryption! Private keys will be stored in plain text (Base64 encoded). Provide keyEncryptionPassword for secure storage."
385
+ );
386
+ }
387
+ const keyData = {
388
+ publicKey: publicKeyStr,
389
+ privateKey: await exportPrivateKey(globalKeyPair.privateKey)
390
+ };
391
+ window.localStorage.setItem(actualKeyStorageKey, JSON.stringify(keyData));
392
+ }
393
+ } catch (error) {
394
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
395
+ console.error("Failed to persist keys");
396
+ }
397
+ }
398
+ }
399
+ } catch (error) {
400
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
401
+ console.error("Failed to generate storage keys");
402
+ }
403
+ throw error;
404
+ }
405
+ }
406
+ if (initOptions.enableHMAC && !globalHMACKey) {
407
+ globalHMACKey = await generateHMACKey();
408
+ }
409
+ }
410
+ function setStorageKeyPair(keyPair) {
411
+ globalKeyPair = keyPair;
412
+ keyPairInitialized = true;
413
+ }
414
+ function getStorageKeyPair() {
415
+ return globalKeyPair;
416
+ }
417
+ function clearPersistedKeys() {
418
+ if (typeof window !== "undefined" && window.localStorage && actualKeyStorageKey) {
419
+ try {
420
+ window.localStorage.removeItem(actualKeyStorageKey);
421
+ actualKeyStorageKey = null;
422
+ keyPairInitialized = false;
423
+ globalKeyPair = null;
424
+ globalHMACKey = null;
425
+ keyUsageCount = 0;
426
+ } catch (error) {
427
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
428
+ console.error("Failed to clear persisted keys");
429
+ }
430
+ }
431
+ }
432
+ }
433
+ function getKeyUsageCount() {
434
+ return keyUsageCount;
435
+ }
436
+ function resetKeyUsageCount() {
437
+ keyUsageCount = 0;
438
+ }
439
+ async function ensureKeyPair() {
440
+ if (globalKeyPair) {
441
+ keyUsageCount++;
442
+ return;
443
+ }
444
+ if (!initOptions.autoGenerateKeys) {
445
+ return;
446
+ }
447
+ if (initializationPromise) {
448
+ await initializationPromise;
449
+ if (globalKeyPair) {
450
+ keyUsageCount++;
451
+ }
452
+ return;
453
+ }
454
+ initializationPromise = initializeStorageKeys();
455
+ try {
456
+ await initializationPromise;
457
+ } finally {
458
+ initializationPromise = null;
459
+ }
460
+ if (globalKeyPair) {
461
+ keyUsageCount++;
462
+ }
463
+ }
464
+ function safeParseJSON(jsonStr, expectedType) {
465
+ try {
466
+ const parsed = JSON.parse(jsonStr);
467
+ if (expectedType === "object" && (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))) {
468
+ throw new Error("Expected object but got different type");
469
+ }
470
+ if (expectedType === "array" && !Array.isArray(parsed)) {
471
+ throw new Error("Expected array but got different type");
472
+ }
473
+ return parsed;
474
+ } catch (error) {
475
+ if (error instanceof SyntaxError) {
476
+ throw new Error(`Invalid JSON format: ${error.message}`);
477
+ }
478
+ throw error;
479
+ }
480
+ }
481
+ function validateTimestamp(timestamp, maxClockSkew = 5 * 60 * 1e3) {
482
+ if (!initOptions.enableTimestampValidation || !timestamp) {
483
+ return true;
484
+ }
485
+ if (initOptions.timestampMaxAge === 0) {
486
+ return true;
487
+ }
488
+ const now = Date.now();
489
+ const age = now - timestamp;
490
+ const maxAge = initOptions.timestampMaxAge || 7 * 24 * 60 * 60 * 1e3;
491
+ if (age < -maxClockSkew) {
492
+ return false;
493
+ }
494
+ return age >= -maxClockSkew && age <= maxAge;
495
+ }
496
+ async function encryptValue(value, publicKey, hmacKey) {
497
+ const encryptedData = await rsaEncrypt(value, publicKey);
498
+ if (hmacKey) {
499
+ const hmac = await computeHMAC(encryptedData, hmacKey);
500
+ const item = {
501
+ data: encryptedData,
502
+ hmac,
503
+ encrypted: true,
504
+ timestamp: Date.now()
505
+ };
506
+ return JSON.stringify(item);
507
+ }
508
+ return encryptedData;
509
+ }
510
+ async function handleDecryptError(error, encryptedStr, key) {
511
+ if (error instanceof Error && error.message.includes("HMAC verification failed")) {
512
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
513
+ console.error(
514
+ "\u26A0\uFE0F SECURITY ALERT: Data integrity check failed! Data may have been tampered with."
515
+ );
516
+ }
517
+ throw error;
518
+ }
519
+ if (error instanceof Error && error.message.includes("Data timestamp validation failed")) {
520
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
521
+ console.warn("\u26A0\uFE0F SECURITY WARNING: Data timestamp validation failed");
522
+ }
523
+ throw error;
524
+ }
525
+ try {
526
+ const decryptedStr = base64Decode(encryptedStr);
527
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
528
+ console.warn(
529
+ `\u26A0\uFE0F SECURITY WARNING: Reading unencrypted data for key "${key}". This may be a security risk if sensitive data was stored without encryption.`
530
+ );
531
+ }
532
+ return decryptedStr;
533
+ } catch {
534
+ throw error;
535
+ }
536
+ }
537
+ function handleNoKeyDecode(encryptedStr, key) {
538
+ try {
539
+ const decryptedStr = base64Decode(encryptedStr);
540
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
541
+ console.warn(
542
+ `\u26A0\uFE0F SECURITY WARNING: Reading unencrypted data for key "${key}" without encryption keys.`
543
+ );
544
+ }
545
+ return decryptedStr;
546
+ } catch (error) {
547
+ throw new Error(`Failed to decode storage value for key "${key}"`);
548
+ }
549
+ }
550
+ async function decryptValue(encryptedValue, privateKey, hmacKey) {
551
+ try {
552
+ const item = JSON.parse(encryptedValue);
553
+ if (item.encrypted && item.data && item.hmac) {
554
+ if (hmacKey) {
555
+ const isValid = await verifyHMAC(item.data, item.hmac, hmacKey);
556
+ if (!isValid) {
557
+ throw new Error("HMAC verification failed: data may have been tampered with");
558
+ }
559
+ }
560
+ if (item.timestamp && !validateTimestamp(item.timestamp)) {
561
+ throw new Error("Data timestamp validation failed: data may be expired or replayed");
562
+ }
563
+ return await rsaDecrypt(item.data, privateKey);
564
+ }
565
+ return await rsaDecrypt(encryptedValue, privateKey);
566
+ } catch (error) {
567
+ if (error instanceof Error && error.message.includes("HMAC verification failed")) {
568
+ throw error;
569
+ }
570
+ throw new Error("Failed to decrypt storage value: invalid format or corrupted data");
571
+ }
572
+ }
573
+ var localStorage = {
574
+ /**
575
+ * 设置值
576
+ * @param key - 键
577
+ * @param value - 值
578
+ * @param options - 选项(过期时间、密钥等)
579
+ * @returns Promise<void>
580
+ */
581
+ async set(key, value, options = {}) {
582
+ if (typeof window === "undefined" || !window.localStorage) {
583
+ throw new Error("localStorage is not available");
584
+ }
585
+ const { expiry, publicKey } = options;
586
+ const item = {
587
+ value,
588
+ expiry: expiry ? Date.now() + expiry : void 0
589
+ };
590
+ try {
591
+ const jsonStr = JSON.stringify(item);
592
+ await ensureKeyPair();
593
+ const keyToUse = publicKey || globalKeyPair?.publicKey;
594
+ if (keyToUse) {
595
+ const encrypted = await encryptValue(jsonStr, keyToUse, globalHMACKey);
596
+ window.localStorage.setItem(key, encrypted);
597
+ } else {
598
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
599
+ console.warn(
600
+ `\u26A0\uFE0F SECURITY WARNING: Storing data without encryption for key "${key}". Data is only Base64 encoded, not encrypted!`
601
+ );
602
+ }
603
+ const encoded = base64Encode(jsonStr);
604
+ window.localStorage.setItem(key, encoded);
605
+ }
606
+ } catch (error) {
607
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
608
+ console.error("localStorage.set error:", error);
609
+ }
610
+ throw error;
611
+ }
612
+ },
613
+ /**
614
+ * 获取值
615
+ * @param key - 键
616
+ * @param options - 选项(默认值、私钥等)
617
+ * @returns Promise<T | undefined> 值或默认值
618
+ */
619
+ async get(key, options = {}) {
620
+ if (typeof window === "undefined" || !window.localStorage) {
621
+ return options.defaultValue;
622
+ }
623
+ const { defaultValue, privateKey } = options;
624
+ try {
625
+ const encryptedStr = window.localStorage.getItem(key);
626
+ if (!encryptedStr) return defaultValue;
627
+ await ensureKeyPair();
628
+ let decryptedStr;
629
+ const keyToUse = privateKey || globalKeyPair?.privateKey;
630
+ if (keyToUse) {
631
+ try {
632
+ decryptedStr = await decryptValue(encryptedStr, keyToUse, globalHMACKey);
633
+ } catch (error) {
634
+ try {
635
+ decryptedStr = await handleDecryptError(error, encryptedStr, key);
636
+ } catch {
637
+ return defaultValue;
638
+ }
639
+ }
640
+ } else {
641
+ try {
642
+ decryptedStr = handleNoKeyDecode(encryptedStr, key);
643
+ } catch {
644
+ return defaultValue;
645
+ }
646
+ }
647
+ const item = safeParseJSON(decryptedStr, "object");
648
+ if (item.expiry && Date.now() > item.expiry) {
649
+ window.localStorage.removeItem(key);
650
+ return defaultValue;
651
+ }
652
+ return item.value;
653
+ } catch (error) {
654
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
655
+ console.warn(`Failed to parse storage item for key "${key}"`);
656
+ }
657
+ return defaultValue;
658
+ }
659
+ },
660
+ /**
661
+ * 移除值
662
+ * @param key - 键
663
+ */
664
+ remove(key) {
665
+ if (typeof window === "undefined" || !window.localStorage) return;
666
+ try {
667
+ window.localStorage.removeItem(key);
668
+ } catch (error) {
669
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
670
+ console.error("localStorage.remove error");
671
+ }
672
+ }
673
+ },
674
+ /**
675
+ * 清空所有值
676
+ */
677
+ clear() {
678
+ if (typeof window === "undefined" || !window.localStorage) return;
679
+ try {
680
+ window.localStorage.clear();
681
+ } catch (error) {
682
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
683
+ console.error("localStorage.clear error");
684
+ }
685
+ }
686
+ },
687
+ /**
688
+ * 获取所有键
689
+ * @returns 键数组
690
+ */
691
+ keys() {
692
+ if (typeof window === "undefined" || !window.localStorage) return [];
693
+ const keys = [];
694
+ try {
695
+ for (let i = 0; i < window.localStorage.length; i++) {
696
+ const key = window.localStorage.key(i);
697
+ if (key) keys.push(key);
698
+ }
699
+ } catch (error) {
700
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
701
+ console.error("localStorage.keys error");
702
+ }
703
+ }
704
+ return keys;
705
+ }
706
+ };
707
+ var sessionStorage = {
708
+ /**
709
+ * 设置值
710
+ * @param key - 键
711
+ * @param value - 值
712
+ * @param options - 选项(公钥等)
713
+ * @returns Promise<void>
714
+ */
715
+ async set(key, value, options = {}) {
716
+ if (typeof window === "undefined" || !window.sessionStorage) {
717
+ throw new Error("sessionStorage is not available");
718
+ }
719
+ const { publicKey } = options;
720
+ try {
721
+ const jsonStr = JSON.stringify(value);
722
+ await ensureKeyPair();
723
+ const keyToUse = publicKey || globalKeyPair?.publicKey;
724
+ if (keyToUse) {
725
+ const encrypted = await encryptValue(jsonStr, keyToUse, globalHMACKey);
726
+ window.sessionStorage.setItem(key, encrypted);
727
+ } else {
728
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
729
+ console.warn(
730
+ `\u26A0\uFE0F SECURITY WARNING: Storing data without encryption for key "${key}". Data is only Base64 encoded, not encrypted!`
731
+ );
732
+ }
733
+ const encoded = base64Encode(jsonStr);
734
+ window.sessionStorage.setItem(key, encoded);
735
+ }
736
+ } catch (error) {
737
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
738
+ console.error("sessionStorage.set error:", error);
739
+ }
740
+ throw error;
741
+ }
742
+ },
743
+ /**
744
+ * 获取值
745
+ * @param key - 键
746
+ * @param options - 选项(默认值、私钥等)
747
+ * @returns Promise<T | undefined> 值或默认值
748
+ */
749
+ async get(key, options = {}) {
750
+ if (typeof window === "undefined" || !window.sessionStorage) {
751
+ return options.defaultValue;
752
+ }
753
+ const { defaultValue, privateKey } = options;
754
+ try {
755
+ const encryptedStr = window.sessionStorage.getItem(key);
756
+ if (!encryptedStr) return defaultValue;
757
+ await ensureKeyPair();
758
+ let decryptedStr;
759
+ const keyToUse = privateKey || globalKeyPair?.privateKey;
760
+ if (keyToUse) {
761
+ try {
762
+ decryptedStr = await decryptValue(encryptedStr, keyToUse, globalHMACKey);
763
+ } catch (error) {
764
+ try {
765
+ decryptedStr = await handleDecryptError(error, encryptedStr, key);
766
+ } catch {
767
+ return defaultValue;
768
+ }
769
+ }
770
+ } else {
771
+ try {
772
+ decryptedStr = handleNoKeyDecode(encryptedStr, key);
773
+ } catch {
774
+ return defaultValue;
775
+ }
776
+ }
777
+ return safeParseJSON(decryptedStr);
778
+ } catch {
779
+ return defaultValue;
780
+ }
781
+ },
782
+ /**
783
+ * 移除值
784
+ * @param key - 键
785
+ */
786
+ remove(key) {
787
+ if (typeof window === "undefined" || !window.sessionStorage) return;
788
+ try {
789
+ window.sessionStorage.removeItem(key);
790
+ } catch (error) {
791
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
792
+ console.error("sessionStorage.remove error");
793
+ }
794
+ }
795
+ },
796
+ /**
797
+ * 清空所有值
798
+ */
799
+ clear() {
800
+ if (typeof window === "undefined" || !window.sessionStorage) return;
801
+ try {
802
+ window.sessionStorage.clear();
803
+ } catch (error) {
804
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
805
+ console.error("sessionStorage.clear error");
806
+ }
807
+ }
808
+ }
809
+ };
810
+ var cookie = {
811
+ /**
812
+ * 设置Cookie
813
+ * @param key - 键
814
+ * @param value - 值
815
+ * @param options - Cookie选项
816
+ */
817
+ set(key, value, options = {}) {
818
+ if (typeof document === "undefined") {
819
+ throw new Error("document is not available");
820
+ }
821
+ let cookieStr = `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
822
+ if (options.expires) {
823
+ const expiresDate = options.expires instanceof Date ? options.expires : new Date(Date.now() + options.expires * 24 * 60 * 60 * 1e3);
824
+ cookieStr += `; expires=${expiresDate.toUTCString()}`;
825
+ }
826
+ if (options.path) cookieStr += `; path=${options.path}`;
827
+ if (options.domain) cookieStr += `; domain=${options.domain}`;
828
+ if (options.secure) cookieStr += "; secure";
829
+ if (options.sameSite) cookieStr += `; sameSite=${options.sameSite}`;
830
+ document.cookie = cookieStr;
831
+ },
832
+ /**
833
+ * 获取Cookie
834
+ * @param key - 键
835
+ * @returns Cookie值
836
+ */
837
+ get(key) {
838
+ if (typeof document === "undefined") return void 0;
839
+ const name = encodeURIComponent(key);
840
+ const cookies = document.cookie.split(";");
841
+ for (const cookieStr of cookies) {
842
+ const trimmed = cookieStr.trim();
843
+ const eqIndex = trimmed.indexOf("=");
844
+ if (eqIndex === -1) continue;
845
+ const cookieKey = trimmed.substring(0, eqIndex).trim();
846
+ const cookieValue = trimmed.substring(eqIndex + 1).trim();
847
+ if (cookieKey === name) {
848
+ return decodeURIComponent(cookieValue);
849
+ }
850
+ }
851
+ return void 0;
852
+ },
853
+ /**
854
+ * 移除Cookie
855
+ * @param key - 键
856
+ * @param options - Cookie选项
857
+ */
858
+ remove(key, options = {}) {
859
+ cookie.set(key, "", {
860
+ ...options,
861
+ expires: /* @__PURE__ */ new Date(0)
862
+ });
863
+ },
864
+ /**
865
+ * 获取所有Cookie
866
+ * @returns Cookie对象
867
+ */
868
+ getAll() {
869
+ if (typeof document === "undefined") return {};
870
+ const cookies = {};
871
+ document.cookie.split(";").forEach((cookieStr) => {
872
+ const trimmed = cookieStr.trim();
873
+ const eqIndex = trimmed.indexOf("=");
874
+ if (eqIndex === -1) return;
875
+ const key = trimmed.substring(0, eqIndex).trim();
876
+ const value = trimmed.substring(eqIndex + 1).trim();
877
+ if (key && value) {
878
+ cookies[decodeURIComponent(key)] = decodeURIComponent(value);
879
+ }
880
+ });
881
+ return cookies;
882
+ }
883
+ };
884
+ var storage = {
885
+ /**
886
+ * 设置值(优先使用localStorage,失败则使用sessionStorage)
887
+ * @param key - 键
888
+ * @param value - 值
889
+ * @param options - 选项(过期时间、公钥等)
890
+ * @returns Promise<void>
891
+ */
892
+ async set(key, value, options = {}) {
893
+ try {
894
+ await localStorage.set(key, value, options);
895
+ } catch {
896
+ try {
897
+ await sessionStorage.set(key, value, { publicKey: options.publicKey });
898
+ } catch {
899
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
900
+ console.warn("Both localStorage and sessionStorage are not available");
901
+ }
902
+ }
903
+ }
904
+ },
905
+ /**
906
+ * 获取值
907
+ * @param key - 键
908
+ * @param options - 选项(默认值、私钥等)
909
+ * @returns Promise<T | undefined> 值或默认值
910
+ */
911
+ async get(key, options = {}) {
912
+ const localValue = await localStorage.get(key, options);
913
+ if (localValue !== void 0) return localValue;
914
+ const sessionValue = await sessionStorage.get(key, options);
915
+ return sessionValue !== void 0 ? sessionValue : options.defaultValue;
916
+ },
917
+ /**
918
+ * 移除值
919
+ * @param key - 键
920
+ */
921
+ remove(key) {
922
+ localStorage.remove(key);
923
+ sessionStorage.remove(key);
924
+ },
925
+ /**
926
+ * 清空所有值
927
+ */
928
+ clear() {
929
+ localStorage.clear();
930
+ sessionStorage.clear();
931
+ }
932
+ };
933
+
934
+ exports.clearPersistedKeys = clearPersistedKeys;
935
+ exports.cookie = cookie;
936
+ exports.getKeyUsageCount = getKeyUsageCount;
937
+ exports.getStorageKeyPair = getStorageKeyPair;
938
+ exports.initializeStorageKeys = initializeStorageKeys;
939
+ exports.localStorage = localStorage;
940
+ exports.resetKeyUsageCount = resetKeyUsageCount;
941
+ exports.sessionStorage = sessionStorage;
942
+ exports.setStorageKeyPair = setStorageKeyPair;
943
+ exports.storage = storage;