@alibarbar/common 1.1.2 → 1.1.4

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/dist/index.cjs CHANGED
@@ -1,10 +1,14 @@
1
1
  'use strict';
2
2
 
3
+ var JSEncrypt = require('jsencrypt');
4
+ var CryptoJS = require('crypto-js');
3
5
  var Qs = require('qs');
4
6
  var axios = require('axios');
5
7
 
6
8
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
9
 
10
+ var JSEncrypt__default = /*#__PURE__*/_interopDefault(JSEncrypt);
11
+ var CryptoJS__default = /*#__PURE__*/_interopDefault(CryptoJS);
8
12
  var Qs__default = /*#__PURE__*/_interopDefault(Qs);
9
13
  var axios__default = /*#__PURE__*/_interopDefault(axios);
10
14
 
@@ -769,8 +773,8 @@ function parseUrl(url) {
769
773
  }
770
774
  }
771
775
  function buildUrl(parts) {
772
- const { protocol = "https:", host = "", pathname = "/", search = "", hash: hash2 = "" } = parts;
773
- return `${protocol}//${host}${pathname}${search}${hash2}`;
776
+ const { protocol = "https:", host = "", pathname = "/", search = "", hash = "" } = parts;
777
+ return `${protocol}//${host}${pathname}${search}${hash}`;
774
778
  }
775
779
  function getQueryParams(url) {
776
780
  const searchParams = url ? new URL(url).searchParams : new URLSearchParams(window.location.search);
@@ -1144,6 +1148,8 @@ var ChunkUploader = class {
1144
1148
  this.uploadedChunks = /* @__PURE__ */ new Set();
1145
1149
  this.status = "pending" /* PENDING */;
1146
1150
  this.abortController = null;
1151
+ /** 进度流专用 AbortController,用于在上传结束/取消时关闭流 */
1152
+ this.progressStreamAbortController = null;
1147
1153
  this.file = file;
1148
1154
  this.options = {
1149
1155
  chunkSize: options.chunkSize || 2 * 1024 * 1024,
@@ -1251,7 +1257,6 @@ var ChunkUploader = class {
1251
1257
  });
1252
1258
  if (response.code === 200 && response.data.success) {
1253
1259
  this.uploadedChunks.add(chunkInfo.index);
1254
- await this.updateProgress();
1255
1260
  } else {
1256
1261
  throw new Error(response.message || "\u5206\u7247\u4E0A\u4F20\u5931\u8D25");
1257
1262
  }
@@ -1286,23 +1291,60 @@ var ChunkUploader = class {
1286
1291
  await Promise.all(tasks);
1287
1292
  }
1288
1293
  /**
1289
- * 更新上传进度(仅用于回调前端显示)
1294
+ * 启动进度流式接口(单次请求,通过 ReadableStream 消费多条 SSE 事件)
1290
1295
  */
1291
- async updateProgress() {
1296
+ startProgressStream() {
1292
1297
  if (!this.taskId) return;
1293
- try {
1294
- const response = await this.request(
1295
- `/api/files/common/progress/${this.taskId}`,
1296
- {
1297
- method: "GET",
1298
- headers: this.options.headers
1298
+ this.progressStreamAbortController = new AbortController();
1299
+ const url = `${this.options.baseURL}/api/files/common/progress/${this.taskId}`;
1300
+ fetch(url, {
1301
+ method: "GET",
1302
+ headers: {
1303
+ Accept: "text/event-stream",
1304
+ ...this.options.headers
1305
+ },
1306
+ signal: this.progressStreamAbortController.signal
1307
+ }).then(async (response) => {
1308
+ if (!response.ok || !response.body) return;
1309
+ const reader = response.body.getReader();
1310
+ const decoder = new TextDecoder();
1311
+ let buffer = "";
1312
+ try {
1313
+ while (true) {
1314
+ const { done, value } = await reader.read();
1315
+ if (done) break;
1316
+ buffer += decoder.decode(value, { stream: true });
1317
+ const lines = buffer.split("\n");
1318
+ buffer = lines.pop() ?? "";
1319
+ for (const line of lines) {
1320
+ if (line.startsWith("data: ")) {
1321
+ const jsonStr = line.slice(6).trim();
1322
+ if (!jsonStr) continue;
1323
+ try {
1324
+ const apiRes = JSON.parse(jsonStr);
1325
+ if (apiRes.code === 200 && apiRes.data) {
1326
+ this.options.onProgress(apiRes.data);
1327
+ }
1328
+ } catch {
1329
+ }
1330
+ }
1331
+ }
1299
1332
  }
1300
- );
1301
- if (response.code === 200 && response.data) {
1302
- this.options.onProgress(response.data);
1333
+ } finally {
1334
+ reader.releaseLock();
1303
1335
  }
1304
- } catch (error) {
1305
- console.warn("\u83B7\u53D6\u4E0A\u4F20\u8FDB\u5EA6\u5931\u8D25:", error);
1336
+ }).catch((error) => {
1337
+ if (error?.name === "AbortError") return;
1338
+ console.warn("\u8FDB\u5EA6\u6D41\u5F0F\u63A5\u53E3\u5F02\u5E38:", error);
1339
+ });
1340
+ }
1341
+ /**
1342
+ * 关闭进度流
1343
+ */
1344
+ closeProgressStream() {
1345
+ if (this.progressStreamAbortController) {
1346
+ this.progressStreamAbortController.abort();
1347
+ this.progressStreamAbortController = null;
1306
1348
  }
1307
1349
  }
1308
1350
  /**
@@ -1375,6 +1417,7 @@ var ChunkUploader = class {
1375
1417
  this.options.onComplete(result);
1376
1418
  return result;
1377
1419
  }
1420
+ this.startProgressStream();
1378
1421
  console.log("[\u4E0A\u4F20\u6D41\u7A0B] 2. \u51C6\u5907\u5206\u7247");
1379
1422
  this.prepareChunks();
1380
1423
  const totalChunks = this.chunks.length;
@@ -1418,6 +1461,8 @@ var ChunkUploader = class {
1418
1461
  this.options.onError(err);
1419
1462
  console.error("[\u4E0A\u4F20\u6D41\u7A0B] \u274C \u4E0A\u4F20\u5931\u8D25:", err);
1420
1463
  throw err;
1464
+ } finally {
1465
+ this.closeProgressStream();
1421
1466
  }
1422
1467
  }
1423
1468
  /**
@@ -1444,6 +1489,7 @@ var ChunkUploader = class {
1444
1489
  * 取消上传
1445
1490
  */
1446
1491
  async cancel() {
1492
+ this.closeProgressStream();
1447
1493
  if (this.taskId && this.status === "uploading" /* UPLOADING */) {
1448
1494
  try {
1449
1495
  await this.request(`/api/files/common/cancel/${this.taskId}`, {
@@ -1500,14 +1546,6 @@ async function uploadFile(file, options) {
1500
1546
  const uploader = createUploader(file, options);
1501
1547
  return uploader.upload();
1502
1548
  }
1503
-
1504
- // src/helper/crypto/index.ts
1505
- async function sha256(data) {
1506
- const buffer = typeof data === "string" ? new TextEncoder().encode(data) : data;
1507
- const hashBuffer = await crypto.subtle.digest("SHA-256", buffer);
1508
- const hashArray = Array.from(new Uint8Array(hashBuffer));
1509
- return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
1510
- }
1511
1549
  function base64Encode(data) {
1512
1550
  if (typeof data === "string") {
1513
1551
  return btoa(unescape(encodeURIComponent(data)));
@@ -1519,1009 +1557,444 @@ function base64Encode(data) {
1519
1557
  }
1520
1558
  return btoa(binary);
1521
1559
  }
1522
- function base64Decode(data) {
1523
- try {
1524
- return decodeURIComponent(escape(atob(data)));
1525
- } catch {
1526
- throw new Error("Invalid Base64 string");
1527
- }
1528
- }
1529
- function generateUUID() {
1530
- if (typeof crypto !== "undefined" && crypto.randomUUID) {
1531
- return crypto.randomUUID();
1532
- }
1533
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
1534
- const r = Math.random() * 16 | 0;
1535
- const v = c === "x" ? r : r & 3 | 8;
1536
- return v.toString(16);
1537
- });
1538
- }
1539
- function generateRandomString(length, charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") {
1540
- let result = "";
1541
- for (let i = 0; i < length; i++) {
1542
- result += charset.charAt(Math.floor(Math.random() * charset.length));
1543
- }
1544
- return result;
1560
+ function generateRandomAESKeyString() {
1561
+ return CryptoJS__default.default.lib.WordArray.random(256 / 8).toString();
1545
1562
  }
1546
- function hash(data) {
1547
- let hashValue = 0;
1548
- for (let i = 0; i < data.length; i++) {
1549
- const char = data.charCodeAt(i);
1550
- hashValue = (hashValue << 5) - hashValue + char;
1551
- hashValue = hashValue & hashValue;
1563
+ function encryptJsonWithAES(data, aesKey) {
1564
+ try {
1565
+ const jsonString = JSON.stringify(data);
1566
+ return CryptoJS__default.default.AES.encrypt(jsonString, aesKey).toString();
1567
+ } catch (error) {
1568
+ throw new Error(
1569
+ "[encryption] AES encryptJsonWithAES failed: " + (error instanceof Error ? error.message : String(error))
1570
+ );
1552
1571
  }
1553
- return Math.abs(hashValue);
1554
1572
  }
1555
- async function generateRSAKeyPair(modulusLength = 2048) {
1556
- if (typeof crypto === "undefined" || !crypto.subtle) {
1557
- throw new Error("Web Crypto API is not available");
1573
+ function decryptJsonWithAES(encryptedData, aesKey) {
1574
+ try {
1575
+ const decrypted = CryptoJS__default.default.AES.decrypt(encryptedData, aesKey);
1576
+ const jsonString = decrypted.toString(CryptoJS__default.default.enc.Utf8);
1577
+ if (!jsonString) {
1578
+ throw new Error("decrypted JSON string is empty");
1579
+ }
1580
+ return JSON.parse(jsonString);
1581
+ } catch (error) {
1582
+ throw new Error(
1583
+ "[encryption] AES decryptJsonWithAES failed: " + (error instanceof Error ? error.message : String(error))
1584
+ );
1558
1585
  }
1559
- const keyPair = await crypto.subtle.generateKey(
1560
- {
1561
- name: "RSA-OAEP",
1562
- modulusLength,
1563
- publicExponent: new Uint8Array([1, 0, 1]),
1564
- hash: "SHA-256"
1565
- },
1566
- true,
1567
- ["encrypt", "decrypt"]
1568
- );
1569
- return {
1570
- publicKey: keyPair.publicKey,
1571
- privateKey: keyPair.privateKey
1572
- };
1573
1586
  }
1574
- async function rsaEncrypt(data, publicKey) {
1575
- if (typeof crypto === "undefined" || !crypto.subtle) {
1576
- throw new Error("Web Crypto API is not available");
1577
- }
1578
- const encoder = new TextEncoder();
1579
- const dataBuffer = encoder.encode(data);
1580
- const algo = publicKey.algorithm;
1581
- const modulusLength = typeof algo.modulusLength === "number" ? algo.modulusLength : 2048;
1582
- const hashName = typeof algo.hash === "object" && "name" in algo.hash ? algo.hash.name : "SHA-256";
1583
- const hashLength = hashName === "SHA-1" ? 20 : 32;
1584
- const maxChunkSize = Math.max(Math.floor(modulusLength / 8 - 2 * hashLength - 2), 1);
1585
- const chunks = [];
1586
- for (let i = 0; i < dataBuffer.length; i += maxChunkSize) {
1587
- const chunk2 = dataBuffer.slice(i, i + maxChunkSize);
1588
- const encrypted = await crypto.subtle.encrypt(
1589
- {
1590
- name: "RSA-OAEP"
1591
- },
1592
- publicKey,
1593
- chunk2
1587
+ function getEnvPublicKey() {
1588
+ const key = undefined.VITE_RSA_PUBLIC_KEY?.trim();
1589
+ if (!key) {
1590
+ throw new Error(
1591
+ "[encryption] VITE_RSA_PUBLIC_KEY is not set. Please configure RSA public key in environment variables."
1594
1592
  );
1595
- chunks.push(encrypted);
1596
1593
  }
1597
- const totalLength = chunks.reduce((sum, chunk2) => sum + chunk2.byteLength, 0);
1598
- const merged = new Uint8Array(totalLength);
1599
- let offset = 0;
1600
- for (const chunk2 of chunks) {
1601
- merged.set(new Uint8Array(chunk2), offset);
1602
- offset += chunk2.byteLength;
1603
- }
1604
- return base64Encode(merged.buffer);
1594
+ return key;
1605
1595
  }
1606
- async function rsaDecrypt(encryptedData, privateKey) {
1607
- if (typeof crypto === "undefined" || !crypto.subtle) {
1608
- throw new Error("Web Crypto API is not available");
1609
- }
1610
- const binaryString = atob(encryptedData);
1611
- const encryptedArray = new Uint8Array(binaryString.length);
1612
- for (let i = 0; i < binaryString.length; i++) {
1613
- encryptedArray[i] = binaryString.charCodeAt(i);
1614
- }
1615
- const chunkSize = 256;
1616
- const chunks = [];
1617
- for (let i = 0; i < encryptedArray.length; i += chunkSize) {
1618
- const chunk2 = encryptedArray.slice(i, i + chunkSize);
1619
- const decrypted = await crypto.subtle.decrypt(
1620
- {
1621
- name: "RSA-OAEP"
1622
- },
1623
- privateKey,
1624
- chunk2
1596
+ function getEnvPrivateKey() {
1597
+ const key = undefined.VITE_RSA_PRIVATE_KEY?.trim();
1598
+ if (!key) {
1599
+ throw new Error(
1600
+ "[encryption] VITE_RSA_PRIVATE_KEY is not set. Please configure RSA private key in environment variables."
1625
1601
  );
1626
- const decoder = new TextDecoder();
1627
- chunks.push(decoder.decode(decrypted));
1628
1602
  }
1629
- return chunks.join("");
1603
+ return key;
1630
1604
  }
1631
- async function exportPublicKey(publicKey) {
1632
- if (typeof crypto === "undefined" || !crypto.subtle) {
1633
- throw new Error("Web Crypto API is not available");
1605
+ function base64ToPem(base64Key, type) {
1606
+ const chunks = [];
1607
+ for (let i = 0; i < base64Key.length; i += 64) {
1608
+ chunks.push(base64Key.slice(i, i + 64));
1634
1609
  }
1635
- const exported = await crypto.subtle.exportKey("spki", publicKey);
1636
- return base64Encode(exported);
1610
+ const body = chunks.join("\n");
1611
+ const header = type === "PUBLIC" ? "-----BEGIN PUBLIC KEY-----" : "-----BEGIN PRIVATE KEY-----";
1612
+ const footer = type === "PUBLIC" ? "-----END PUBLIC KEY-----" : "-----END PRIVATE KEY-----";
1613
+ return `${header}
1614
+ ${body}
1615
+ ${footer}`;
1637
1616
  }
1638
- async function exportPrivateKey(privateKey) {
1639
- if (typeof crypto === "undefined" || !crypto.subtle) {
1640
- throw new Error("Web Crypto API is not available");
1617
+ async function rsaEncrypt(plain, publicKeyPem) {
1618
+ try {
1619
+ const encrypt = new JSEncrypt__default.default();
1620
+ let publicKeyString;
1621
+ if (typeof publicKeyPem === "string") {
1622
+ const trimmedKey = publicKeyPem.trim();
1623
+ if (!trimmedKey) {
1624
+ throw new Error("Public key string is empty");
1625
+ }
1626
+ if (trimmedKey.includes("-----BEGIN")) {
1627
+ publicKeyString = trimmedKey;
1628
+ } else {
1629
+ publicKeyString = base64ToPem(trimmedKey, "PUBLIC");
1630
+ }
1631
+ } else if (publicKeyPem instanceof CryptoJS__default.default.lib.WordArray) {
1632
+ const base64Key = publicKeyPem.toString();
1633
+ publicKeyString = base64ToPem(base64Key, "PUBLIC");
1634
+ } else {
1635
+ try {
1636
+ const exported = await crypto.subtle.exportKey("spki", publicKeyPem);
1637
+ const base64Key = base64Encode(exported);
1638
+ publicKeyString = base64ToPem(base64Key, "PUBLIC");
1639
+ } catch (error) {
1640
+ throw new Error(
1641
+ "Failed to export CryptoKey. In non-HTTPS environment, use string publicKey (Base64 or PEM) directly. " + (error instanceof Error ? error.message : String(error))
1642
+ );
1643
+ }
1644
+ }
1645
+ encrypt.setPublicKey(publicKeyString);
1646
+ const MAX_ENCRYPT_LENGTH = 200;
1647
+ if (plain.length > MAX_ENCRYPT_LENGTH) {
1648
+ const chunks = [];
1649
+ for (let i = 0; i < plain.length; i += MAX_ENCRYPT_LENGTH) {
1650
+ const chunk2 = plain.slice(i, i + MAX_ENCRYPT_LENGTH);
1651
+ const encrypted2 = encrypt.encrypt(chunk2);
1652
+ if (!encrypted2) {
1653
+ throw new Error(
1654
+ `RSA encryption failed for chunk ${i / MAX_ENCRYPT_LENGTH + 1}. Public key may be invalid or JSEncrypt may not be loaded correctly.`
1655
+ );
1656
+ }
1657
+ chunks.push(encrypted2);
1658
+ }
1659
+ return chunks.join("|");
1660
+ }
1661
+ const encrypted = encrypt.encrypt(plain);
1662
+ if (!encrypted) {
1663
+ throw new Error(
1664
+ `RSA encryption failed. Public key may be invalid or JSEncrypt may not be loaded correctly. Plain text length: ${plain.length} bytes.`
1665
+ );
1666
+ }
1667
+ return encrypted;
1668
+ } catch (error) {
1669
+ if (error instanceof Error) {
1670
+ if (error.message.includes("RSA encryption failed") || error.message.includes("Public key")) {
1671
+ throw error;
1672
+ }
1673
+ throw new Error(`[encryption] rsaEncrypt failed: ${error.message}`);
1674
+ }
1675
+ throw new Error(`[encryption] rsaEncrypt failed: ${String(error)}`);
1641
1676
  }
1642
- const exported = await crypto.subtle.exportKey("pkcs8", privateKey);
1643
- return base64Encode(exported);
1644
1677
  }
1645
- async function importPublicKey(keyData) {
1646
- if (typeof crypto === "undefined" || !crypto.subtle) {
1647
- throw new Error("Web Crypto API is not available");
1678
+ async function rsaDecrypt(cipher, privateKeyPem) {
1679
+ const decrypt = new JSEncrypt__default.default();
1680
+ let privateKeyString;
1681
+ if (typeof privateKeyPem === "string") {
1682
+ if (privateKeyPem.includes("-----BEGIN")) {
1683
+ privateKeyString = privateKeyPem.trim();
1684
+ } else {
1685
+ const trimmed = privateKeyPem.trim();
1686
+ privateKeyString = base64ToPem(trimmed, "PRIVATE");
1687
+ }
1688
+ } else if (privateKeyPem instanceof CryptoJS__default.default.lib.WordArray) {
1689
+ const base64Key = privateKeyPem.toString();
1690
+ privateKeyString = base64ToPem(base64Key, "PRIVATE");
1691
+ } else {
1692
+ try {
1693
+ const exported = await crypto.subtle.exportKey("pkcs8", privateKeyPem);
1694
+ const base64Key = base64Encode(exported);
1695
+ privateKeyString = base64ToPem(base64Key, "PRIVATE");
1696
+ } catch (error) {
1697
+ throw new Error(
1698
+ "[encryption] rsaDecrypt: failed to export CryptoKey. In non-HTTPS environment, use PEM string directly."
1699
+ );
1700
+ }
1648
1701
  }
1649
- const keyBuffer = base64Decode(keyData);
1650
- const keyArray = new Uint8Array(keyBuffer.split("").map((char) => char.charCodeAt(0)));
1651
- return crypto.subtle.importKey(
1652
- "spki",
1653
- keyArray.buffer,
1654
- {
1655
- name: "RSA-OAEP",
1656
- hash: "SHA-256"
1657
- },
1658
- true,
1659
- ["encrypt"]
1660
- );
1661
- }
1662
- async function importPrivateKey(keyData) {
1663
- if (typeof crypto === "undefined" || !crypto.subtle) {
1664
- throw new Error("Web Crypto API is not available");
1702
+ decrypt.setPrivateKey(privateKeyString);
1703
+ const chunks = cipher.split("|");
1704
+ const decryptedChunks = [];
1705
+ for (const chunk2 of chunks) {
1706
+ const decrypted = decrypt.decrypt(chunk2);
1707
+ if (!decrypted) {
1708
+ throw new Error("[encryption] rsaDecrypt: RSA decryption failed");
1709
+ }
1710
+ decryptedChunks.push(decrypted);
1665
1711
  }
1666
- const keyBuffer = base64Decode(keyData);
1667
- const keyArray = new Uint8Array(keyBuffer.split("").map((char) => char.charCodeAt(0)));
1668
- return crypto.subtle.importKey(
1669
- "pkcs8",
1670
- keyArray.buffer,
1671
- {
1672
- name: "RSA-OAEP",
1673
- hash: "SHA-256"
1674
- },
1675
- true,
1676
- ["decrypt"]
1677
- );
1712
+ return decryptedChunks.join("");
1678
1713
  }
1679
- async function generateHMACKey() {
1680
- if (typeof crypto === "undefined" || !crypto.subtle) {
1681
- throw new Error("Web Crypto API is not available");
1682
- }
1683
- return crypto.subtle.generateKey(
1684
- {
1685
- name: "HMAC",
1686
- hash: "SHA-256"
1687
- },
1688
- true,
1689
- ["sign", "verify"]
1690
- );
1714
+ async function encryptWithEnvPublicKey(plain) {
1715
+ const publicKey = getEnvPublicKey();
1716
+ return rsaEncrypt(plain, publicKey);
1691
1717
  }
1692
- async function computeHMAC(data, key) {
1693
- if (typeof crypto === "undefined" || !crypto.subtle) {
1694
- throw new Error("Web Crypto API is not available");
1695
- }
1696
- const buffer = typeof data === "string" ? new TextEncoder().encode(data) : data;
1697
- const signature = await crypto.subtle.sign("HMAC", key, buffer);
1698
- return base64Encode(signature);
1718
+ async function decryptWithEnvPrivateKey(cipher) {
1719
+ const privateKey = getEnvPrivateKey();
1720
+ return rsaDecrypt(cipher, privateKey);
1699
1721
  }
1700
- async function verifyHMAC(data, signature, key) {
1722
+ async function generateRSAKeyPair(modulusLength = 2048) {
1701
1723
  if (typeof crypto === "undefined" || !crypto.subtle) {
1702
- throw new Error("Web Crypto API is not available");
1703
- }
1704
- try {
1705
- const dataBuffer = typeof data === "string" ? new TextEncoder().encode(data) : data;
1706
- const signatureBuffer = new Uint8Array(
1707
- atob(signature).split("").map((char) => char.charCodeAt(0))
1724
+ throw new Error(
1725
+ "[encryption] Web Crypto API is not available. Cannot generate RSA key pair. Please use fixed key pair from environment variables."
1708
1726
  );
1709
- return await crypto.subtle.verify("HMAC", key, signatureBuffer, dataBuffer);
1710
- } catch {
1711
- return false;
1712
1727
  }
1713
- }
1714
- async function deriveKeyFromPassword(password, salt, iterations = 1e5, keyLength = 256) {
1715
- if (typeof crypto === "undefined" || !crypto.subtle) {
1716
- throw new Error("Web Crypto API is not available");
1717
- }
1718
- const saltBuffer = typeof salt === "string" ? new TextEncoder().encode(salt) : salt;
1719
- const passwordKey = await crypto.subtle.importKey(
1720
- "raw",
1721
- new TextEncoder().encode(password),
1722
- "PBKDF2",
1723
- false,
1724
- ["deriveBits", "deriveKey"]
1725
- );
1726
- return crypto.subtle.deriveKey(
1728
+ const keyPair = await crypto.subtle.generateKey(
1727
1729
  {
1728
- name: "PBKDF2",
1729
- salt: saltBuffer,
1730
- iterations,
1730
+ name: "RSA-OAEP",
1731
+ modulusLength,
1732
+ publicExponent: new Uint8Array([1, 0, 1]),
1731
1733
  hash: "SHA-256"
1732
1734
  },
1733
- passwordKey,
1734
- {
1735
- name: "AES-GCM",
1736
- length: keyLength
1737
- },
1738
- false,
1735
+ true,
1739
1736
  ["encrypt", "decrypt"]
1740
1737
  );
1741
- }
1742
- async function aesGCMEncrypt(data, key) {
1743
- if (typeof crypto === "undefined" || !crypto.subtle) {
1744
- throw new Error("Web Crypto API is not available");
1745
- }
1746
- const dataBuffer = typeof data === "string" ? new TextEncoder().encode(data) : data;
1747
- const iv = crypto.getRandomValues(new Uint8Array(12));
1748
- const encrypted = await crypto.subtle.encrypt(
1749
- {
1750
- name: "AES-GCM",
1751
- iv
1752
- },
1753
- key,
1754
- dataBuffer
1755
- );
1738
+ const publicKeyDer = await crypto.subtle.exportKey("spki", keyPair.publicKey);
1739
+ const privateKeyDer = await crypto.subtle.exportKey("pkcs8", keyPair.privateKey);
1740
+ const publicKeyBase64 = base64Encode(publicKeyDer);
1741
+ const privateKeyBase64 = base64Encode(privateKeyDer);
1756
1742
  return {
1757
- encrypted: base64Encode(encrypted),
1758
- iv: base64Encode(iv.buffer)
1743
+ publicKey: base64ToPem(publicKeyBase64, "PUBLIC"),
1744
+ privateKey: base64ToPem(privateKeyBase64, "PRIVATE")
1759
1745
  };
1760
1746
  }
1761
- async function aesGCMDecrypt(encryptedData, iv, key) {
1762
- if (typeof crypto === "undefined" || !crypto.subtle) {
1763
- throw new Error("Web Crypto API is not available");
1764
- }
1765
- const encryptedBuffer = new Uint8Array(
1766
- atob(encryptedData).split("").map((char) => char.charCodeAt(0))
1767
- );
1768
- const ivBuffer = new Uint8Array(
1769
- atob(iv).split("").map((char) => char.charCodeAt(0))
1770
- );
1771
- const decrypted = await crypto.subtle.decrypt(
1772
- {
1773
- name: "AES-GCM",
1774
- iv: ivBuffer
1775
- },
1776
- key,
1777
- encryptedBuffer
1778
- );
1779
- return new TextDecoder().decode(decrypted);
1780
- }
1781
1747
 
1782
1748
  // src/browser/SecureStorage/index.ts
1783
- var globalKeyPair = null;
1784
- var globalHMACKey = null;
1785
- var keyPairInitialized = false;
1786
- var initOptions = {
1787
- autoGenerateKeys: true,
1788
- persistKeys: false,
1789
- keyStorageKey: void 0,
1790
- // 将自动生成随机键名
1791
- keyEncryptionPassword: void 0,
1792
- pbkdf2Iterations: 1e5,
1793
- keyModulusLength: 2048,
1794
- enableHMAC: true,
1795
- enableTimestampValidation: true,
1796
- timestampMaxAge: 7 * 24 * 60 * 60 * 1e3,
1797
- // 7 天
1798
- isProduction: false
1749
+ var CONFIG = {
1750
+ NAMESPACE: "sec_b_",
1751
+ DEFAULT_EXPIRE: null
1799
1752
  };
1800
- var actualKeyStorageKey = null;
1801
- var keyUsageCount = 0;
1802
- var initializationPromise = null;
1803
- var KEY_STORAGE_KEY_REGISTRY = "__SECURE_STORAGE_KEY__";
1804
- function generateKeyStorageKey() {
1805
- return `_sk_${generateRandomString(32)}_${Date.now()}`;
1806
- }
1807
- async function initializeStorageKeys(options = {}) {
1808
- if (options.forceReinitialize) {
1809
- globalKeyPair = null;
1810
- globalHMACKey = null;
1811
- keyPairInitialized = false;
1812
- actualKeyStorageKey = null;
1813
- keyUsageCount = 0;
1814
- initializationPromise = null;
1815
- } else if (keyPairInitialized && globalKeyPair) {
1816
- initOptions = { ...initOptions, ...options };
1817
- return;
1818
- }
1819
- initOptions = { ...initOptions, ...options };
1820
- if (initOptions.keyStorageKey) {
1821
- actualKeyStorageKey = initOptions.keyStorageKey;
1822
- } else if (!actualKeyStorageKey) {
1823
- if (typeof window !== "undefined" && window.localStorage) {
1824
- const savedKeyName = window.localStorage.getItem(KEY_STORAGE_KEY_REGISTRY);
1825
- if (savedKeyName) {
1826
- actualKeyStorageKey = savedKeyName;
1827
- } else {
1828
- actualKeyStorageKey = generateKeyStorageKey();
1829
- window.localStorage.setItem(KEY_STORAGE_KEY_REGISTRY, actualKeyStorageKey);
1830
- }
1831
- } else {
1832
- actualKeyStorageKey = generateKeyStorageKey();
1833
- }
1834
- }
1835
- if (initOptions.persistKeys && typeof window !== "undefined" && window.localStorage) {
1836
- try {
1837
- const storedKeys = window.localStorage.getItem(actualKeyStorageKey);
1838
- if (storedKeys) {
1839
- const keyData = JSON.parse(storedKeys);
1840
- if (keyData.encrypted && keyData.privateKeyEncrypted && keyData.salt) {
1841
- if (!initOptions.keyEncryptionPassword) {
1842
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
1843
- console.error("Encrypted keys found but no password provided");
1844
- }
1845
- throw new Error("Password required to decrypt stored keys");
1846
- }
1847
- const saltArray = new Uint8Array(
1848
- atob(keyData.salt).split("").map((char) => char.charCodeAt(0))
1849
- );
1850
- const iterations = keyData.pbkdf2Iterations || initOptions.pbkdf2Iterations;
1851
- const derivedKey = await deriveKeyFromPassword(
1852
- initOptions.keyEncryptionPassword,
1853
- saltArray.buffer,
1854
- iterations
1855
- );
1856
- const decryptedPrivateKey = await aesGCMDecrypt(
1857
- keyData.privateKeyEncrypted,
1858
- keyData.iv,
1859
- derivedKey
1860
- );
1861
- globalKeyPair = {
1862
- publicKey: await importPublicKey(keyData.publicKey),
1863
- privateKey: await importPrivateKey(decryptedPrivateKey)
1864
- };
1865
- } else if (keyData.publicKey && keyData.privateKey) {
1866
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
1867
- console.warn(
1868
- "\u26A0\uFE0F SECURITY WARNING: Loading unencrypted keys from storage. Consider re-initializing with password encryption."
1869
- );
1870
- }
1871
- globalKeyPair = {
1872
- publicKey: await importPublicKey(keyData.publicKey),
1873
- privateKey: await importPrivateKey(keyData.privateKey)
1874
- };
1875
- }
1876
- if (globalKeyPair) {
1877
- keyPairInitialized = true;
1878
- if (initOptions.enableHMAC && !globalHMACKey) {
1879
- globalHMACKey = await generateHMACKey();
1880
- }
1881
- return;
1882
- }
1883
- }
1884
- } catch (error) {
1885
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
1886
- console.warn("Failed to load persisted keys, will generate new ones");
1887
- }
1888
- }
1889
- }
1890
- if (initOptions.autoGenerateKeys && !globalKeyPair) {
1891
- try {
1892
- globalKeyPair = await generateRSAKeyPair(initOptions.keyModulusLength);
1893
- if (initOptions.enableHMAC && !globalHMACKey) {
1894
- globalHMACKey = await generateHMACKey();
1895
- }
1896
- keyPairInitialized = true;
1897
- keyUsageCount = 0;
1898
- if (initOptions.persistKeys && typeof window !== "undefined" && window.localStorage) {
1899
- try {
1900
- const publicKeyStr = await exportPublicKey(globalKeyPair.publicKey);
1901
- if (initOptions.keyEncryptionPassword) {
1902
- const privateKeyStr = await exportPrivateKey(globalKeyPair.privateKey);
1903
- const salt = crypto.getRandomValues(new Uint8Array(16));
1904
- const derivedKey = await deriveKeyFromPassword(
1905
- initOptions.keyEncryptionPassword,
1906
- salt.buffer,
1907
- initOptions.pbkdf2Iterations
1908
- );
1909
- const { encrypted, iv } = await aesGCMEncrypt(privateKeyStr, derivedKey);
1910
- const keyData = {
1911
- encrypted: true,
1912
- publicKey: publicKeyStr,
1913
- privateKeyEncrypted: encrypted,
1914
- iv,
1915
- salt: base64Encode(salt.buffer),
1916
- pbkdf2Iterations: initOptions.pbkdf2Iterations
1917
- };
1918
- window.localStorage.setItem(actualKeyStorageKey, JSON.stringify(keyData));
1919
- if (!initOptions.isProduction && typeof console !== "undefined" && console.info) {
1920
- console.info("\u2705 Keys encrypted and stored securely");
1921
- }
1922
- } else {
1923
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
1924
- console.warn(
1925
- "\u26A0\uFE0F SECURITY WARNING: Storing private keys without encryption! Private keys will be stored in plain text (Base64 encoded). Provide keyEncryptionPassword for secure storage."
1926
- );
1927
- }
1928
- const keyData = {
1929
- publicKey: publicKeyStr,
1930
- privateKey: await exportPrivateKey(globalKeyPair.privateKey)
1931
- };
1932
- window.localStorage.setItem(actualKeyStorageKey, JSON.stringify(keyData));
1933
- }
1934
- } catch (error) {
1935
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
1936
- console.error("Failed to persist keys");
1937
- }
1938
- }
1939
- }
1940
- } catch (error) {
1941
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
1942
- console.error("Failed to generate storage keys");
1943
- }
1944
- throw error;
1945
- }
1946
- }
1947
- if (initOptions.enableHMAC && !globalHMACKey) {
1948
- globalHMACKey = await generateHMACKey();
1949
- }
1950
- }
1951
- function setStorageKeyPair(keyPair) {
1952
- globalKeyPair = keyPair;
1953
- keyPairInitialized = true;
1954
- }
1955
- function getStorageKeyPair() {
1956
- return globalKeyPair;
1957
- }
1958
- function clearPersistedKeys() {
1959
- if (typeof window !== "undefined" && window.localStorage && actualKeyStorageKey) {
1960
- try {
1961
- window.localStorage.removeItem(actualKeyStorageKey);
1962
- actualKeyStorageKey = null;
1963
- keyPairInitialized = false;
1964
- globalKeyPair = null;
1965
- globalHMACKey = null;
1966
- keyUsageCount = 0;
1967
- } catch (error) {
1968
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
1969
- console.error("Failed to clear persisted keys");
1970
- }
1971
- }
1972
- }
1973
- }
1974
- function getKeyUsageCount() {
1975
- return keyUsageCount;
1976
- }
1977
- function resetKeyUsageCount() {
1978
- keyUsageCount = 0;
1979
- }
1980
- async function ensureKeyPair() {
1981
- if (globalKeyPair) {
1982
- keyUsageCount++;
1983
- return;
1984
- }
1985
- if (!initOptions.autoGenerateKeys) {
1986
- return;
1987
- }
1988
- if (initializationPromise) {
1989
- await initializationPromise;
1990
- if (globalKeyPair) {
1991
- keyUsageCount++;
1753
+ var SecureStorage = class _SecureStorage {
1754
+ static get instances() {
1755
+ if (!this._instances) {
1756
+ this._instances = /* @__PURE__ */ new Map();
1992
1757
  }
1993
- return;
1994
- }
1995
- initializationPromise = initializeStorageKeys();
1996
- try {
1997
- await initializationPromise;
1998
- } finally {
1999
- initializationPromise = null;
1758
+ return this._instances;
2000
1759
  }
2001
- if (globalKeyPair) {
2002
- keyUsageCount++;
2003
- }
2004
- }
2005
- function safeParseJSON(jsonStr, expectedType) {
2006
- try {
2007
- const parsed = JSON.parse(jsonStr);
2008
- if (expectedType === "object" && (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))) {
2009
- throw new Error("Expected object but got different type");
2010
- }
2011
- if (expectedType === "array" && !Array.isArray(parsed)) {
2012
- throw new Error("Expected array but got different type");
2013
- }
2014
- return parsed;
2015
- } catch (error) {
2016
- if (error instanceof SyntaxError) {
2017
- throw new Error(`Invalid JSON format: ${error.message}`);
1760
+ constructor(options) {
1761
+ const storageType = options.storage === window.sessionStorage ? "session" : "local";
1762
+ const namespace = options.namespace || CONFIG.NAMESPACE;
1763
+ const instanceKey = `${storageType}_${namespace}`;
1764
+ const existingInstance = _SecureStorage.instances.get(instanceKey);
1765
+ if (existingInstance) {
1766
+ return existingInstance;
2018
1767
  }
2019
- throw error;
2020
- }
2021
- }
2022
- function validateTimestamp(timestamp, maxClockSkew = 5 * 60 * 1e3) {
2023
- if (!initOptions.enableTimestampValidation || !timestamp) {
2024
- return true;
2025
- }
2026
- if (initOptions.timestampMaxAge === 0) {
2027
- return true;
2028
- }
2029
- const now = Date.now();
2030
- const age = now - timestamp;
2031
- const maxAge = initOptions.timestampMaxAge || 7 * 24 * 60 * 60 * 1e3;
2032
- if (age < -maxClockSkew) {
2033
- return false;
1768
+ this.namespace = namespace;
1769
+ this.storage = options.storage || window.localStorage;
1770
+ this.defaultExpire = options.defaultExpire ?? CONFIG.DEFAULT_EXPIRE;
1771
+ this.instanceKey = instanceKey;
1772
+ _SecureStorage.instances.set(instanceKey, this);
2034
1773
  }
2035
- return age >= -maxClockSkew && age <= maxAge;
2036
- }
2037
- async function encryptValue(value, publicKey, hmacKey) {
2038
- const encryptedData = await rsaEncrypt(value, publicKey);
2039
- if (hmacKey) {
2040
- const hmac = await computeHMAC(encryptedData, hmacKey);
2041
- const item = {
2042
- data: encryptedData,
2043
- hmac,
2044
- encrypted: true,
2045
- timestamp: Date.now()
2046
- };
2047
- return JSON.stringify(item);
2048
- }
2049
- return encryptedData;
2050
- }
2051
- async function handleDecryptError(error, encryptedStr, key) {
2052
- if (error instanceof Error && error.message.includes("HMAC verification failed")) {
2053
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
2054
- console.error(
2055
- "\u26A0\uFE0F SECURITY ALERT: Data integrity check failed! Data may have been tampered with."
2056
- );
2057
- }
2058
- throw error;
1774
+ /**
1775
+ * 获取单例实例(静态方法)
1776
+ */
1777
+ static getInstance(options) {
1778
+ return new _SecureStorage(options);
2059
1779
  }
2060
- if (error instanceof Error && error.message.includes("Data timestamp validation failed")) {
2061
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
2062
- console.warn("\u26A0\uFE0F SECURITY WARNING: Data timestamp validation failed");
2063
- }
2064
- throw error;
1780
+ /**
1781
+ * 清除所有单例实例(用于测试或重置)
1782
+ */
1783
+ static clearInstances() {
1784
+ _SecureStorage.instances.clear();
2065
1785
  }
2066
- try {
2067
- const decryptedStr = base64Decode(encryptedStr);
2068
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
2069
- console.warn(
2070
- `\u26A0\uFE0F SECURITY WARNING: Reading unencrypted data for key "${key}". This may be a security risk if sensitive data was stored without encryption.`
2071
- );
2072
- }
2073
- return decryptedStr;
2074
- } catch {
2075
- throw error;
1786
+ /**
1787
+ * 获取当前所有实例的数量(用于调试)
1788
+ */
1789
+ static getInstanceCount() {
1790
+ return _SecureStorage.instances.size;
2076
1791
  }
2077
- }
2078
- function handleNoKeyDecode(encryptedStr, key) {
2079
- try {
2080
- const decryptedStr = base64Decode(encryptedStr);
2081
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
2082
- console.warn(
2083
- `\u26A0\uFE0F SECURITY WARNING: Reading unencrypted data for key "${key}" without encryption keys.`
2084
- );
2085
- }
2086
- return decryptedStr;
2087
- } catch (error) {
2088
- throw new Error(`Failed to decode storage value for key "${key}"`);
1792
+ /**
1793
+ * 获取完整键名(带命名空间)
1794
+ */
1795
+ _getFullKey(key) {
1796
+ return `${this.namespace}${key}`;
2089
1797
  }
2090
- }
2091
- async function decryptValue(encryptedValue, privateKey, hmacKey) {
2092
- try {
2093
- const item = JSON.parse(encryptedValue);
2094
- if (item.encrypted && item.data && item.hmac) {
2095
- if (hmacKey) {
2096
- const isValid = await verifyHMAC(item.data, item.hmac, hmacKey);
2097
- if (!isValid) {
2098
- throw new Error("HMAC verification failed: data may have been tampered with");
2099
- }
2100
- }
2101
- if (item.timestamp && !validateTimestamp(item.timestamp)) {
2102
- throw new Error("Data timestamp validation failed: data may be expired or replayed");
2103
- }
2104
- return await rsaDecrypt(item.data, privateKey);
2105
- }
2106
- return await rsaDecrypt(encryptedValue, privateKey);
2107
- } catch (error) {
2108
- if (error instanceof Error && error.message.includes("HMAC verification failed")) {
2109
- throw error;
2110
- }
2111
- throw new Error("Failed to decrypt storage value: invalid format or corrupted data");
1798
+ /**
1799
+ * 检查数据是否过期
1800
+ */
1801
+ _isExpired(expire) {
1802
+ if (!expire) return false;
1803
+ return Date.now() > expire;
2112
1804
  }
2113
- }
2114
- var localStorage = {
2115
1805
  /**
2116
1806
  * 设置值
2117
- * @param key - 键
2118
- * @param value - 值
2119
- * @param options - 选项(过期时间、密钥等)
2120
- * @returns Promise<void>
2121
1807
  */
2122
- async set(key, value, options = {}) {
2123
- if (typeof window === "undefined" || !window.localStorage) {
2124
- throw new Error("localStorage is not available");
2125
- }
2126
- const { expiry, publicKey } = options;
2127
- const item = {
2128
- value,
2129
- expiry: expiry ? Date.now() + expiry : void 0
2130
- };
1808
+ async set(key, value, expire = this.defaultExpire) {
2131
1809
  try {
2132
- const jsonStr = JSON.stringify(item);
2133
- await ensureKeyPair();
2134
- const keyToUse = publicKey || globalKeyPair?.publicKey;
2135
- if (keyToUse) {
2136
- const encrypted = await encryptValue(jsonStr, keyToUse, globalHMACKey);
2137
- window.localStorage.setItem(key, encrypted);
2138
- } else {
2139
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
2140
- console.warn(
2141
- `\u26A0\uFE0F SECURITY WARNING: Storing data without encryption for key "${key}". Data is only Base64 encoded, not encrypted!`
2142
- );
2143
- }
2144
- const encoded = base64Encode(jsonStr);
2145
- window.localStorage.setItem(key, encoded);
2146
- }
1810
+ const fullKey = this._getFullKey(key);
1811
+ const aesKey = generateRandomAESKeyString();
1812
+ const storageData = {
1813
+ value,
1814
+ expire: expire ? Date.now() + expire : null,
1815
+ timestamp: Date.now()
1816
+ };
1817
+ const encryptedData = encryptJsonWithAES(storageData, aesKey);
1818
+ const encryptedKey = await encryptWithEnvPublicKey(aesKey);
1819
+ const finalData = {
1820
+ data: encryptedData,
1821
+ key: encryptedKey,
1822
+ version: "1.0"
1823
+ };
1824
+ this.storage.setItem(fullKey, JSON.stringify(finalData));
1825
+ return true;
2147
1826
  } catch (error) {
2148
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
2149
- console.error("localStorage.set error:", error);
2150
- }
2151
- throw error;
1827
+ console.error("[SecureStorage] \u4FDD\u5B58\u5931\u8D25:", error);
1828
+ return false;
2152
1829
  }
2153
- },
1830
+ }
2154
1831
  /**
2155
1832
  * 获取值
2156
- * @param key - 键
2157
- * @param options - 选项(默认值、私钥等)
2158
- * @returns Promise<T | undefined> 值或默认值
2159
1833
  */
2160
- async get(key, options = {}) {
2161
- if (typeof window === "undefined" || !window.localStorage) {
2162
- return options.defaultValue;
2163
- }
2164
- const { defaultValue, privateKey } = options;
1834
+ async get(key, defaultValue = null) {
2165
1835
  try {
2166
- const encryptedStr = window.localStorage.getItem(key);
2167
- if (!encryptedStr) return defaultValue;
2168
- await ensureKeyPair();
2169
- let decryptedStr;
2170
- const keyToUse = privateKey || globalKeyPair?.privateKey;
2171
- if (keyToUse) {
2172
- try {
2173
- decryptedStr = await decryptValue(encryptedStr, keyToUse, globalHMACKey);
2174
- } catch (error) {
2175
- try {
2176
- decryptedStr = await handleDecryptError(error, encryptedStr, key);
2177
- } catch {
2178
- return defaultValue;
2179
- }
2180
- }
2181
- } else {
2182
- try {
2183
- decryptedStr = handleNoKeyDecode(encryptedStr, key);
2184
- } catch {
2185
- return defaultValue;
2186
- }
1836
+ const fullKey = this._getFullKey(key);
1837
+ const storedData = this.storage.getItem(fullKey);
1838
+ if (!storedData) {
1839
+ return defaultValue;
2187
1840
  }
2188
- const item = safeParseJSON(decryptedStr, "object");
2189
- if (item.expiry && Date.now() > item.expiry) {
2190
- window.localStorage.removeItem(key);
1841
+ const finalData = JSON.parse(storedData);
1842
+ const aesKey = await decryptWithEnvPrivateKey(finalData.key);
1843
+ const storageData = decryptJsonWithAES(finalData.data, aesKey);
1844
+ if (this._isExpired(storageData.expire)) {
1845
+ this.remove(key);
2191
1846
  return defaultValue;
2192
1847
  }
2193
- return item.value;
1848
+ return storageData.value;
2194
1849
  } catch (error) {
2195
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
2196
- console.warn(`Failed to parse storage item for key "${key}"`);
2197
- }
1850
+ console.error("[SecureStorage] \u8BFB\u53D6\u5931\u8D25:", error);
2198
1851
  return defaultValue;
2199
1852
  }
2200
- },
1853
+ }
2201
1854
  /**
2202
- * 移除值
2203
- * @param key - 键
1855
+ * 删除值
2204
1856
  */
2205
1857
  remove(key) {
2206
- if (typeof window === "undefined" || !window.localStorage) return;
2207
1858
  try {
2208
- window.localStorage.removeItem(key);
1859
+ const fullKey = this._getFullKey(key);
1860
+ this.storage.removeItem(fullKey);
1861
+ return true;
2209
1862
  } catch (error) {
2210
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
2211
- console.error("localStorage.remove error");
2212
- }
1863
+ console.error("[SecureStorage] \u79FB\u9664\u5931\u8D25:", error);
1864
+ return false;
2213
1865
  }
2214
- },
1866
+ }
2215
1867
  /**
2216
- * 清空所有值
1868
+ * 检查键是否存在
2217
1869
  */
2218
- clear() {
2219
- if (typeof window === "undefined" || !window.localStorage) return;
1870
+ async has(key) {
2220
1871
  try {
2221
- window.localStorage.clear();
2222
- } catch (error) {
2223
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
2224
- console.error("localStorage.clear error");
1872
+ const fullKey = this._getFullKey(key);
1873
+ const storedData = this.storage.getItem(fullKey);
1874
+ if (!storedData) return false;
1875
+ const finalData = JSON.parse(storedData);
1876
+ const aesKey = await decryptWithEnvPrivateKey(finalData.key);
1877
+ const storageData = decryptJsonWithAES(finalData.data, aesKey);
1878
+ if (this._isExpired(storageData.expire)) {
1879
+ this.remove(key);
1880
+ return false;
2225
1881
  }
1882
+ return true;
1883
+ } catch (error) {
1884
+ return false;
2226
1885
  }
2227
- },
1886
+ }
2228
1887
  /**
2229
- * 获取所有键
2230
- * @returns 键数组
1888
+ * 清空所有数据
2231
1889
  */
2232
- keys() {
2233
- if (typeof window === "undefined" || !window.localStorage) return [];
2234
- const keys2 = [];
1890
+ clear() {
2235
1891
  try {
2236
- for (let i = 0; i < window.localStorage.length; i++) {
2237
- const key = window.localStorage.key(i);
2238
- if (key) keys2.push(key);
1892
+ let count = 0;
1893
+ const keys2 = [];
1894
+ for (let i = 0; i < this.storage.length; i++) {
1895
+ const key = this.storage.key(i);
1896
+ if (key && key.startsWith(this.namespace)) {
1897
+ keys2.push(key);
1898
+ }
2239
1899
  }
1900
+ keys2.forEach((key) => {
1901
+ this.storage.removeItem(key);
1902
+ count++;
1903
+ });
1904
+ return count;
2240
1905
  } catch (error) {
2241
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
2242
- console.error("localStorage.keys error");
2243
- }
1906
+ console.error("[SecureStorage] \u6E05\u7A7A\u5931\u8D25:", error);
1907
+ return 0;
2244
1908
  }
2245
- return keys2;
2246
1909
  }
2247
- };
2248
- var sessionStorage = {
2249
1910
  /**
2250
- * 设置值
2251
- * @param key - 键
2252
- * @param value - 值
2253
- * @param options - 选项(公钥等)
2254
- * @returns Promise<void>
1911
+ * 获取所有键名
2255
1912
  */
2256
- async set(key, value, options = {}) {
2257
- if (typeof window === "undefined" || !window.sessionStorage) {
2258
- throw new Error("sessionStorage is not available");
2259
- }
2260
- const { publicKey } = options;
1913
+ keys() {
2261
1914
  try {
2262
- const jsonStr = JSON.stringify(value);
2263
- await ensureKeyPair();
2264
- const keyToUse = publicKey || globalKeyPair?.publicKey;
2265
- if (keyToUse) {
2266
- const encrypted = await encryptValue(jsonStr, keyToUse, globalHMACKey);
2267
- window.sessionStorage.setItem(key, encrypted);
2268
- } else {
2269
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
2270
- console.warn(
2271
- `\u26A0\uFE0F SECURITY WARNING: Storing data without encryption for key "${key}". Data is only Base64 encoded, not encrypted!`
2272
- );
1915
+ const keys2 = [];
1916
+ for (let i = 0; i < this.storage.length; i++) {
1917
+ const key = this.storage.key(i);
1918
+ if (key && key.startsWith(this.namespace)) {
1919
+ keys2.push(key.substring(this.namespace.length));
2273
1920
  }
2274
- const encoded = base64Encode(jsonStr);
2275
- window.sessionStorage.setItem(key, encoded);
2276
1921
  }
1922
+ return keys2;
2277
1923
  } catch (error) {
2278
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
2279
- console.error("sessionStorage.set error:", error);
2280
- }
2281
- throw error;
1924
+ console.error("[SecureStorage] \u83B7\u53D6\u952E\u540D\u5931\u8D25:", error);
1925
+ return [];
2282
1926
  }
2283
- },
1927
+ }
2284
1928
  /**
2285
- * 获取值
2286
- * @param key - 键
2287
- * @param options - 选项(默认值、私钥等)
2288
- * @returns Promise<T | undefined> 值或默认值
1929
+ * 获取数据条数
2289
1930
  */
2290
- async get(key, options = {}) {
2291
- if (typeof window === "undefined" || !window.sessionStorage) {
2292
- return options.defaultValue;
2293
- }
2294
- const { defaultValue, privateKey } = options;
1931
+ size() {
1932
+ return this.keys().length;
1933
+ }
1934
+ /**
1935
+ * 清理过期数据
1936
+ */
1937
+ async clearExpired() {
2295
1938
  try {
2296
- const encryptedStr = window.sessionStorage.getItem(key);
2297
- if (!encryptedStr) return defaultValue;
2298
- await ensureKeyPair();
2299
- let decryptedStr;
2300
- const keyToUse = privateKey || globalKeyPair?.privateKey;
2301
- if (keyToUse) {
1939
+ let count = 0;
1940
+ const keys2 = this.keys();
1941
+ for (const key of keys2) {
1942
+ const fullKey = this._getFullKey(key);
2302
1943
  try {
2303
- decryptedStr = await decryptValue(encryptedStr, keyToUse, globalHMACKey);
2304
- } catch (error) {
2305
- try {
2306
- decryptedStr = await handleDecryptError(error, encryptedStr, key);
2307
- } catch {
2308
- return defaultValue;
1944
+ const storedData = this.storage.getItem(fullKey);
1945
+ if (storedData) {
1946
+ const finalData = JSON.parse(storedData);
1947
+ const aesKey = await decryptWithEnvPrivateKey(finalData.key);
1948
+ const storageData = decryptJsonWithAES(finalData.data, aesKey);
1949
+ if (this._isExpired(storageData.expire)) {
1950
+ this.remove(key);
1951
+ count++;
1952
+ }
2309
1953
  }
1954
+ } catch (error) {
1955
+ this.remove(key);
1956
+ count++;
2310
1957
  }
2311
- } else {
2312
- try {
2313
- decryptedStr = handleNoKeyDecode(encryptedStr, key);
2314
- } catch {
2315
- return defaultValue;
2316
- }
2317
- }
2318
- return safeParseJSON(decryptedStr);
2319
- } catch {
2320
- return defaultValue;
2321
- }
2322
- },
2323
- /**
2324
- * 移除值
2325
- * @param key - 键
2326
- */
2327
- remove(key) {
2328
- if (typeof window === "undefined" || !window.sessionStorage) return;
2329
- try {
2330
- window.sessionStorage.removeItem(key);
2331
- } catch (error) {
2332
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
2333
- console.error("sessionStorage.remove error");
2334
1958
  }
2335
- }
2336
- },
2337
- /**
2338
- * 清空所有值
2339
- */
2340
- clear() {
2341
- if (typeof window === "undefined" || !window.sessionStorage) return;
2342
- try {
2343
- window.sessionStorage.clear();
1959
+ return count;
2344
1960
  } catch (error) {
2345
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
2346
- console.error("sessionStorage.clear error");
2347
- }
1961
+ console.error("[SecureStorage] \u6E05\u7406\u8FC7\u671F\u6570\u636E\u5931\u8D25:", error);
1962
+ return 0;
2348
1963
  }
2349
1964
  }
2350
- };
2351
- var cookie = {
2352
- /**
2353
- * 设置Cookie
2354
- * @param key - 键
2355
- * @param value - 值
2356
- * @param options - Cookie选项
2357
- */
2358
- set(key, value, options = {}) {
2359
- if (typeof document === "undefined") {
2360
- throw new Error("document is not available");
2361
- }
2362
- let cookieStr = `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
2363
- if (options.expires) {
2364
- const expiresDate = options.expires instanceof Date ? options.expires : new Date(Date.now() + options.expires * 24 * 60 * 60 * 1e3);
2365
- cookieStr += `; expires=${expiresDate.toUTCString()}`;
2366
- }
2367
- if (options.path) cookieStr += `; path=${options.path}`;
2368
- if (options.domain) cookieStr += `; domain=${options.domain}`;
2369
- if (options.secure) cookieStr += "; secure";
2370
- if (options.sameSite) cookieStr += `; sameSite=${options.sameSite}`;
2371
- document.cookie = cookieStr;
2372
- },
2373
- /**
2374
- * 获取Cookie
2375
- * @param key - 键
2376
- * @returns Cookie值
2377
- */
2378
- get(key) {
2379
- if (typeof document === "undefined") return void 0;
2380
- const name = encodeURIComponent(key);
2381
- const cookies = document.cookie.split(";");
2382
- for (const cookieStr of cookies) {
2383
- const trimmed = cookieStr.trim();
2384
- const eqIndex = trimmed.indexOf("=");
2385
- if (eqIndex === -1) continue;
2386
- const cookieKey = trimmed.substring(0, eqIndex).trim();
2387
- const cookieValue = trimmed.substring(eqIndex + 1).trim();
2388
- if (cookieKey === name) {
2389
- const decoded = decodeURIComponent(cookieValue);
2390
- return decoded === "" ? void 0 : decoded;
2391
- }
2392
- }
2393
- return void 0;
2394
- },
2395
1965
  /**
2396
- * 移除Cookie
2397
- * @param key - 键
2398
- * @param options - Cookie选项
1966
+ * 获取实例的唯一标识
2399
1967
  */
2400
- remove(key, options = {}) {
2401
- cookie.set(key, "", {
2402
- ...options,
2403
- expires: /* @__PURE__ */ new Date(0)
2404
- });
2405
- },
1968
+ getInstanceKey() {
1969
+ return this.instanceKey;
1970
+ }
2406
1971
  /**
2407
- * 获取所有Cookie
2408
- * @returns Cookie对象
1972
+ * 检查是否为单例实例
2409
1973
  */
2410
- getAll() {
2411
- if (typeof document === "undefined") return {};
2412
- const cookies = {};
2413
- document.cookie.split(";").forEach((cookieStr) => {
2414
- const trimmed = cookieStr.trim();
2415
- if (!trimmed) return;
2416
- const eqIndex = trimmed.indexOf("=");
2417
- if (eqIndex === -1) return;
2418
- const key = trimmed.substring(0, eqIndex).trim();
2419
- const value = trimmed.substring(eqIndex + 1).trim();
2420
- if (key && value) {
2421
- const decodedKey = decodeURIComponent(key);
2422
- const decodedValue = decodeURIComponent(value);
2423
- if (decodedValue !== "") {
2424
- cookies[decodedKey] = decodedValue;
2425
- }
2426
- }
2427
- });
2428
- return cookies;
1974
+ isSingleton() {
1975
+ return _SecureStorage.instances.has(this.instanceKey);
2429
1976
  }
2430
1977
  };
2431
- function createBackendAdapter(type) {
2432
- switch (type) {
2433
- case "local":
2434
- return {
2435
- async set(key, value, options) {
2436
- await localStorage.set(key, value, {
2437
- expiry: options?.expiry,
2438
- publicKey: options?.publicKey
2439
- });
2440
- },
2441
- async get(key, options) {
2442
- return localStorage.get(key, {
2443
- defaultValue: options?.defaultValue,
2444
- privateKey: options?.privateKey
2445
- });
2446
- },
2447
- remove(key) {
2448
- localStorage.remove(key);
2449
- },
2450
- clear() {
2451
- localStorage.clear();
2452
- },
2453
- keys() {
2454
- return localStorage.keys();
2455
- }
2456
- };
2457
- case "session":
2458
- return {
2459
- async set(key, value, options) {
2460
- await sessionStorage.set(key, value, {
2461
- publicKey: options?.publicKey
2462
- });
2463
- },
2464
- async get(key, options) {
2465
- return sessionStorage.get(key, {
2466
- defaultValue: options?.defaultValue,
2467
- privateKey: options?.privateKey
2468
- });
2469
- },
2470
- remove(key) {
2471
- sessionStorage.remove(key);
2472
- },
2473
- clear() {
2474
- sessionStorage.clear();
2475
- },
2476
- keys() {
2477
- if (typeof window === "undefined" || !window.sessionStorage) return [];
2478
- const keys2 = [];
2479
- try {
2480
- for (let i = 0; i < window.sessionStorage.length; i++) {
2481
- const key = window.sessionStorage.key(i);
2482
- if (key) keys2.push(key);
2483
- }
2484
- } catch (error) {
2485
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
2486
- console.error("sessionStorage.keys error");
2487
- }
2488
- }
2489
- return keys2;
2490
- }
2491
- };
2492
- case "cookie":
2493
- return {
2494
- async set(key, value) {
2495
- cookie.set(key, String(value));
2496
- },
2497
- async get(key, options) {
2498
- const value = cookie.get(key);
2499
- if (value === void 0) return options?.defaultValue;
2500
- try {
2501
- return JSON.parse(value);
2502
- } catch {
2503
- return value;
2504
- }
2505
- },
2506
- remove(key) {
2507
- cookie.remove(key);
2508
- },
2509
- clear() {
2510
- const all = cookie.getAll();
2511
- Object.keys(all).forEach((k) => cookie.remove(k));
2512
- },
2513
- keys() {
2514
- return Object.keys(cookie.getAll());
2515
- }
2516
- };
2517
- default:
2518
- return createBackendAdapter("local");
1978
+ var _defaultSecureStorage = null;
1979
+ function _getDefaultSecureStorage() {
1980
+ if (typeof window === "undefined") {
1981
+ throw new Error("[SecureStorage] secureStorage is only available in browser environments.");
2519
1982
  }
1983
+ if (!_defaultSecureStorage) {
1984
+ _defaultSecureStorage = new SecureStorage({});
1985
+ }
1986
+ return _defaultSecureStorage;
2520
1987
  }
2521
- function createSecureStorage(type = "local") {
2522
- return createBackendAdapter(type);
2523
- }
2524
- var secureStorage = createSecureStorage("local");
1988
+ var secureStorage = new Proxy({}, {
1989
+ get(_target, prop) {
1990
+ const instance = _getDefaultSecureStorage();
1991
+ const value = instance[prop];
1992
+ if (typeof value === "function") {
1993
+ return value.bind(instance);
1994
+ }
1995
+ return value;
1996
+ }
1997
+ });
2525
1998
 
2526
1999
  // src/browser/network/index.ts
2527
2000
  async function fetchWithRetry(url, options = {}, retryCount = 3, retryDelay = 1e3) {
@@ -4117,6 +3590,48 @@ function setCommonParams(params) {
4117
3590
  async function flush() {
4118
3591
  await getTracker().flush();
4119
3592
  }
3593
+ function convertRes2Blob(response) {
3594
+ const contentDisposition = response.headers["content-disposition"];
3595
+ let fileName = "file.xlsx";
3596
+ if (contentDisposition) {
3597
+ const rfc5987Match = contentDisposition.match(/filename\*=UTF-8''([^;]+)/i);
3598
+ if (rfc5987Match) {
3599
+ fileName = decodeURIComponent(rfc5987Match[1]);
3600
+ } else {
3601
+ const standardMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/i);
3602
+ if (standardMatch) {
3603
+ fileName = standardMatch[1];
3604
+ fileName = fileName.replace(/^['"]|['"]$/g, "");
3605
+ try {
3606
+ fileName = decodeURIComponent(fileName);
3607
+ } catch (e) {
3608
+ try {
3609
+ fileName = decodeURI(fileName);
3610
+ } catch (e2) {
3611
+ }
3612
+ }
3613
+ }
3614
+ }
3615
+ fileName = fileName.trim().replace(/^_+|_+$/g, "");
3616
+ }
3617
+ const blob = new Blob([response.data], { type: "application/vnd.ms-excel;charset=utf-8" });
3618
+ if (typeof window.navigator.msSaveBlob !== "undefined") {
3619
+ window.navigator.msSaveBlob(blob, fileName);
3620
+ } else {
3621
+ const blobURL = window.URL.createObjectURL(blob);
3622
+ const tempLink = document.createElement("a");
3623
+ tempLink.style.display = "none";
3624
+ tempLink.href = blobURL;
3625
+ tempLink.setAttribute("download", fileName);
3626
+ if (typeof tempLink.download === "undefined") {
3627
+ tempLink.setAttribute("target", "_blank");
3628
+ }
3629
+ document.body.appendChild(tempLink);
3630
+ tempLink.click();
3631
+ document.body.removeChild(tempLink);
3632
+ window.URL.revokeObjectURL(blobURL);
3633
+ }
3634
+ }
4120
3635
  var serviceEventHandlers = {
4121
3636
  message: null
4122
3637
  };
@@ -4150,11 +3665,28 @@ function filterEmptyKey(params, emptyString) {
4150
3665
  }
4151
3666
  });
4152
3667
  }
3668
+ function isFileUpload(data) {
3669
+ if (!data) return false;
3670
+ if (data instanceof FormData) return true;
3671
+ if (data instanceof File) return true;
3672
+ if (data instanceof Blob) return true;
3673
+ if (data instanceof ArrayBuffer) return true;
3674
+ if (typeof data === "object" && data !== null && !Array.isArray(data)) {
3675
+ const obj = data;
3676
+ return Object.values(obj).some(
3677
+ (value) => value instanceof File || value instanceof Blob || value instanceof FormData
3678
+ );
3679
+ }
3680
+ return false;
3681
+ }
4153
3682
  function getTransformRequest(contentType) {
4154
3683
  if (!contentType) {
4155
3684
  return (data) => Qs__default.default.stringify(data);
4156
3685
  }
4157
3686
  const normalizedType = contentType.toLowerCase().trim();
3687
+ if (normalizedType.startsWith("multipart/form-data")) {
3688
+ return void 0;
3689
+ }
4158
3690
  if (normalizedType.startsWith("application/json")) {
4159
3691
  return (data) => JSON.stringify(data);
4160
3692
  }
@@ -4175,6 +3707,15 @@ var service = axios__default.default.create({
4175
3707
  });
4176
3708
  service.interceptors.request.use(
4177
3709
  async (config) => {
3710
+ const isFileUploadRequest = isFileUpload(config.data);
3711
+ if (isFileUploadRequest) {
3712
+ if (config.headers) {
3713
+ delete config.headers["Content-Type"];
3714
+ delete config.headers["content-type"];
3715
+ }
3716
+ config.transformRequest = void 0;
3717
+ return config;
3718
+ }
4178
3719
  const contentType = config.headers?.["Content-Type"] || config.headers?.["content-type"];
4179
3720
  if (!config.transformRequest && contentType) {
4180
3721
  const transformRequest = getTransformRequest(
@@ -4187,9 +3728,11 @@ service.interceptors.request.use(
4187
3728
  config.transformRequest = (data) => Qs__default.default.stringify(data);
4188
3729
  }
4189
3730
  if (config.method === "post" || config.method === "put" || config.method === "patch") {
4190
- const params = { ...config.data || {} };
4191
- filterEmptyKey(params, config.emptyParams ?? false);
4192
- config.data = params;
3731
+ if (config.data && typeof config.data === "object" && !isFileUploadRequest) {
3732
+ const params = { ...config.data || {} };
3733
+ filterEmptyKey(params, config.emptyParams ?? false);
3734
+ config.data = params;
3735
+ }
4193
3736
  } else if (config.method === "get" || config.method === "delete") {
4194
3737
  if (!config.disableTimestamp) {
4195
3738
  config.params = {
@@ -4273,19 +3816,7 @@ service.interceptors.response.use(
4273
3816
  if (status === 401) {
4274
3817
  handle401Error(config, error);
4275
3818
  }
4276
- if (isAborted && config && !config._noAutoRetry) {
4277
- config._retryCount = config._retryCount || 0;
4278
- if (config._retryCount < 2) {
4279
- config._retryCount++;
4280
- console.debug(
4281
- `[request] aborted, retry attempt #${config._retryCount} -> ${config.url || ""}`
4282
- );
4283
- return new Promise((resolve) => setTimeout(resolve, 300)).then(
4284
- () => service.request(config)
4285
- );
4286
- }
4287
- }
4288
- if (!config?.hidden && !isAborted) {
3819
+ if (!config?.hidden && !isAborted && status !== 401) {
4289
3820
  let friendly = messageText;
4290
3821
  if (status === 403) friendly = "No permission";
4291
3822
  else if (status === 502) friendly = "System is upgrading or unavailable";
@@ -4311,7 +3842,7 @@ service.json = function(url, params, config) {
4311
3842
  };
4312
3843
  return service.post(
4313
3844
  url,
4314
- Array.isArray(params) ? params : params,
3845
+ params,
4315
3846
  newConfig
4316
3847
  );
4317
3848
  };
@@ -4320,7 +3851,13 @@ service.put = function(url, params, config) {
4320
3851
  headers: { "Content-Type": "application/json", ...config?.headers },
4321
3852
  ...config
4322
3853
  };
4323
- return service.put(url, Array.isArray(params) ? params : params, newConfig).then((res) => res);
3854
+ const data = Array.isArray(params) ? params : params;
3855
+ return service.request({
3856
+ url,
3857
+ method: "put",
3858
+ data,
3859
+ ...newConfig
3860
+ }).then((res) => res);
4324
3861
  };
4325
3862
  service.arrayGet = function(url, config) {
4326
3863
  if (config) {
@@ -4349,48 +3886,6 @@ service.download = function(url, config = {}) {
4349
3886
  return service.post(url, params, newConfig).then(() => void 0);
4350
3887
  }
4351
3888
  };
4352
- function convertRes2Blob(response) {
4353
- const contentDisposition = response.headers["content-disposition"];
4354
- let fileName = "file.xlsx";
4355
- if (contentDisposition) {
4356
- const rfc5987Match = contentDisposition.match(/filename\*=UTF-8''([^;]+)/i);
4357
- if (rfc5987Match) {
4358
- fileName = decodeURIComponent(rfc5987Match[1]);
4359
- } else {
4360
- const standardMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/i);
4361
- if (standardMatch) {
4362
- fileName = standardMatch[1];
4363
- fileName = fileName.replace(/^['"]|['"]$/g, "");
4364
- try {
4365
- fileName = decodeURIComponent(fileName);
4366
- } catch (e) {
4367
- try {
4368
- fileName = decodeURI(fileName);
4369
- } catch (e2) {
4370
- }
4371
- }
4372
- }
4373
- }
4374
- fileName = fileName.trim().replace(/^_+|_+$/g, "");
4375
- }
4376
- const blob = new Blob([response.data], { type: "application/vnd.ms-excel;charset=utf-8" });
4377
- if (typeof window.navigator.msSaveBlob !== "undefined") {
4378
- window.navigator.msSaveBlob(blob, fileName);
4379
- } else {
4380
- const blobURL = window.URL.createObjectURL(blob);
4381
- const tempLink = document.createElement("a");
4382
- tempLink.style.display = "none";
4383
- tempLink.href = blobURL;
4384
- tempLink.setAttribute("download", fileName);
4385
- if (typeof tempLink.download === "undefined") {
4386
- tempLink.setAttribute("target", "_blank");
4387
- }
4388
- document.body.appendChild(tempLink);
4389
- tempLink.click();
4390
- document.body.removeChild(tempLink);
4391
- window.URL.revokeObjectURL(blobURL);
4392
- }
4393
- }
4394
3889
 
4395
3890
  exports.$ = $;
4396
3891
  exports.$$ = $$;
@@ -4401,6 +3896,7 @@ exports.Graph = Graph;
4401
3896
  exports.LRUCache = LRUCache;
4402
3897
  exports.LinkedList = LinkedList;
4403
3898
  exports.Queue = Queue;
3899
+ exports.SecureStorage = SecureStorage;
4404
3900
  exports.Stack = Stack;
4405
3901
  exports.Tracker = Tracker;
4406
3902
  exports.UploadStatus = UploadStatus;
@@ -4408,9 +3904,6 @@ exports.addClass = addClass;
4408
3904
  exports.addDays = addDays;
4409
3905
  exports.addMonths = addMonths;
4410
3906
  exports.addYears = addYears;
4411
- exports.aesGCMDecrypt = aesGCMDecrypt;
4412
- exports.aesGCMEncrypt = aesGCMEncrypt;
4413
- exports.base64Decode = base64Decode;
4414
3907
  exports.base64Encode = base64Encode;
4415
3908
  exports.batch = batch;
4416
3909
  exports.binarySearch = binarySearch;
@@ -4424,32 +3917,29 @@ exports.ceil = ceil;
4424
3917
  exports.checkOnline = checkOnline;
4425
3918
  exports.chunk = chunk;
4426
3919
  exports.clamp = clamp;
4427
- exports.clearPersistedKeys = clearPersistedKeys;
4428
3920
  exports.compact = compact;
4429
- exports.computeHMAC = computeHMAC;
4430
3921
  exports.contrast = contrast;
4431
- exports.cookie = cookie;
4432
3922
  exports.copyToClipboard = copyToClipboard;
4433
- exports.createSecureStorage = createSecureStorage;
4434
3923
  exports.createTracker = createTracker;
4435
3924
  exports.createTranslator = createTranslator;
4436
3925
  exports.createUploader = createUploader;
4437
3926
  exports.csvToJson = csvToJson;
4438
3927
  exports.darken = darken;
4439
3928
  exports.debounce = debounce;
3929
+ exports.decryptJsonWithAES = decryptJsonWithAES;
3930
+ exports.decryptWithEnvPrivateKey = decryptWithEnvPrivateKey;
4440
3931
  exports.deepClone = deepClone;
4441
3932
  exports.deepMerge = deepMerge;
4442
3933
  exports.defaults = defaults;
4443
- exports.deriveKeyFromPassword = deriveKeyFromPassword;
4444
3934
  exports.diffDays = diffDays;
4445
3935
  exports.difference = difference;
4446
3936
  exports.downloadFile = downloadFile;
4447
3937
  exports.drop = drop;
4448
3938
  exports.dropWhile = dropWhile;
3939
+ exports.encryptJsonWithAES = encryptJsonWithAES;
3940
+ exports.encryptWithEnvPublicKey = encryptWithEnvPublicKey;
4449
3941
  exports.endOfDay = endOfDay;
4450
3942
  exports.escapeHtml = escapeHtml;
4451
- exports.exportPrivateKey = exportPrivateKey;
4452
- exports.exportPublicKey = exportPublicKey;
4453
3943
  exports.factorial = factorial;
4454
3944
  exports.fetchWithRetry = fetchWithRetry;
4455
3945
  exports.fetchWithTimeout = fetchWithTimeout;
@@ -4469,35 +3959,29 @@ exports.formatNumber = formatNumber;
4469
3959
  exports.formatNumberI18n = formatNumberI18n;
4470
3960
  exports.formatRelativeTime = formatRelativeTime;
4471
3961
  exports.gcd = gcd;
4472
- exports.generateHMACKey = generateHMACKey;
4473
3962
  exports.generateRSAKeyPair = generateRSAKeyPair;
4474
- exports.generateRandomString = generateRandomString;
4475
- exports.generateUUID = generateUUID;
3963
+ exports.generateRandomAESKeyString = generateRandomAESKeyString;
4476
3964
  exports.get = get;
4477
3965
  exports.getDateFormatByGMT = getDateFormatByGMT;
4478
3966
  exports.getElementOffset = getElementOffset;
3967
+ exports.getEnvPrivateKey = getEnvPrivateKey;
3968
+ exports.getEnvPublicKey = getEnvPublicKey;
4479
3969
  exports.getFileExtension = getFileExtension;
4480
3970
  exports.getFileNameWithoutExtension = getFileNameWithoutExtension;
4481
- exports.getKeyUsageCount = getKeyUsageCount;
4482
3971
  exports.getLocale = getLocale;
4483
3972
  exports.getQuarter = getQuarter;
4484
3973
  exports.getQueryParams = getQueryParams;
4485
3974
  exports.getRelativeTime = getRelativeTime;
4486
3975
  exports.getScrollPosition = getScrollPosition;
4487
- exports.getStorageKeyPair = getStorageKeyPair;
4488
3976
  exports.getStyle = getStyle;
4489
3977
  exports.getTimeFromGMT = getTimeFromGMT;
4490
3978
  exports.getTracker = getTracker;
4491
3979
  exports.getWeekNumber = getWeekNumber;
4492
3980
  exports.groupBy = groupBy;
4493
- exports.hash = hash;
4494
3981
  exports.hexToRgb = hexToRgb;
4495
3982
  exports.highlight = highlight;
4496
3983
  exports.hslToRgb = hslToRgb;
4497
- exports.importPrivateKey = importPrivateKey;
4498
- exports.importPublicKey = importPublicKey;
4499
3984
  exports.initTracker = initTracker;
4500
- exports.initializeStorageKeys = initializeStorageKeys;
4501
3985
  exports.intersection = intersection;
4502
3986
  exports.invert = invert;
4503
3987
  exports.isAbsoluteUrl = isAbsoluteUrl;
@@ -4557,7 +4041,6 @@ exports.removeAccents = removeAccents;
4557
4041
  exports.removeClass = removeClass;
4558
4042
  exports.removeQueryParams = removeQueryParams;
4559
4043
  exports.request = request;
4560
- exports.resetKeyUsageCount = resetKeyUsageCount;
4561
4044
  exports.retry = retry;
4562
4045
  exports.rgbToHex = rgbToHex;
4563
4046
  exports.rgbToHsl = rgbToHsl;
@@ -4571,10 +4054,8 @@ exports.set = set;
4571
4054
  exports.setCommonParams = setCommonParams;
4572
4055
  exports.setQueryParams = setQueryParams;
4573
4056
  exports.setServiceEventHandlers = setServiceEventHandlers;
4574
- exports.setStorageKeyPair = setStorageKeyPair;
4575
4057
  exports.setStyle = setStyle;
4576
4058
  exports.setUserInfo = setUserInfo;
4577
- exports.sha256 = sha256;
4578
4059
  exports.shuffle = shuffle;
4579
4060
  exports.slugify = slugify;
4580
4061
  exports.snakeCase = snakeCase;
@@ -4602,7 +4083,6 @@ exports.unzip = unzip;
4602
4083
  exports.updateQueryParams = updateQueryParams;
4603
4084
  exports.uploadFile = uploadFile;
4604
4085
  exports.values = values;
4605
- exports.verifyHMAC = verifyHMAC;
4606
4086
  exports.xmlToJson = xmlToJson;
4607
4087
  exports.yamlToJson = yamlToJson;
4608
4088
  exports.zip = zip;