@alibarbar/common 1.1.0 → 1.1.2

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/crypto.cjs CHANGED
@@ -76,7 +76,11 @@ async function rsaEncrypt(data, publicKey) {
76
76
  }
77
77
  const encoder = new TextEncoder();
78
78
  const dataBuffer = encoder.encode(data);
79
- const maxChunkSize = 245;
79
+ const algo = publicKey.algorithm;
80
+ const modulusLength = typeof algo.modulusLength === "number" ? algo.modulusLength : 2048;
81
+ const hashName = typeof algo.hash === "object" && "name" in algo.hash ? algo.hash.name : "SHA-256";
82
+ const hashLength = hashName === "SHA-1" ? 20 : 32;
83
+ const maxChunkSize = Math.max(Math.floor(modulusLength / 8 - 2 * hashLength - 2), 1);
80
84
  const chunks = [];
81
85
  for (let i = 0; i < dataBuffer.length; i += maxChunkSize) {
82
86
  const chunk = dataBuffer.slice(i, i + maxChunkSize);
package/dist/crypto.js CHANGED
@@ -74,7 +74,11 @@ async function rsaEncrypt(data, publicKey) {
74
74
  }
75
75
  const encoder = new TextEncoder();
76
76
  const dataBuffer = encoder.encode(data);
77
- const maxChunkSize = 245;
77
+ const algo = publicKey.algorithm;
78
+ const modulusLength = typeof algo.modulusLength === "number" ? algo.modulusLength : 2048;
79
+ const hashName = typeof algo.hash === "object" && "name" in algo.hash ? algo.hash.name : "SHA-256";
80
+ const hashLength = hashName === "SHA-1" ? 20 : 32;
81
+ const maxChunkSize = Math.max(Math.floor(modulusLength / 8 - 2 * hashLength - 2), 1);
78
82
  const chunks = [];
79
83
  for (let i = 0; i < dataBuffer.length; i += maxChunkSize) {
80
84
  const chunk = dataBuffer.slice(i, i + maxChunkSize);
package/dist/index.cjs CHANGED
@@ -1577,7 +1577,11 @@ async function rsaEncrypt(data, publicKey) {
1577
1577
  }
1578
1578
  const encoder = new TextEncoder();
1579
1579
  const dataBuffer = encoder.encode(data);
1580
- const maxChunkSize = 245;
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);
1581
1585
  const chunks = [];
1582
1586
  for (let i = 0; i < dataBuffer.length; i += maxChunkSize) {
1583
1587
  const chunk2 = dataBuffer.slice(i, i + maxChunkSize);
@@ -1796,6 +1800,7 @@ var initOptions = {
1796
1800
  var actualKeyStorageKey = null;
1797
1801
  var keyUsageCount = 0;
1798
1802
  var initializationPromise = null;
1803
+ var KEY_STORAGE_KEY_REGISTRY = "__SECURE_STORAGE_KEY__";
1799
1804
  function generateKeyStorageKey() {
1800
1805
  return `_sk_${generateRandomString(32)}_${Date.now()}`;
1801
1806
  }
@@ -1814,8 +1819,18 @@ async function initializeStorageKeys(options = {}) {
1814
1819
  initOptions = { ...initOptions, ...options };
1815
1820
  if (initOptions.keyStorageKey) {
1816
1821
  actualKeyStorageKey = initOptions.keyStorageKey;
1817
- } else {
1818
- actualKeyStorageKey = generateKeyStorageKey();
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
+ }
1819
1834
  }
1820
1835
  if (initOptions.persistKeys && typeof window !== "undefined" && window.localStorage) {
1821
1836
  try {
@@ -2371,7 +2386,8 @@ var cookie = {
2371
2386
  const cookieKey = trimmed.substring(0, eqIndex).trim();
2372
2387
  const cookieValue = trimmed.substring(eqIndex + 1).trim();
2373
2388
  if (cookieKey === name) {
2374
- return decodeURIComponent(cookieValue);
2389
+ const decoded = decodeURIComponent(cookieValue);
2390
+ return decoded === "" ? void 0 : decoded;
2375
2391
  }
2376
2392
  }
2377
2393
  return void 0;
@@ -2396,66 +2412,116 @@ var cookie = {
2396
2412
  const cookies = {};
2397
2413
  document.cookie.split(";").forEach((cookieStr) => {
2398
2414
  const trimmed = cookieStr.trim();
2415
+ if (!trimmed) return;
2399
2416
  const eqIndex = trimmed.indexOf("=");
2400
2417
  if (eqIndex === -1) return;
2401
2418
  const key = trimmed.substring(0, eqIndex).trim();
2402
2419
  const value = trimmed.substring(eqIndex + 1).trim();
2403
2420
  if (key && value) {
2404
- cookies[decodeURIComponent(key)] = decodeURIComponent(value);
2421
+ const decodedKey = decodeURIComponent(key);
2422
+ const decodedValue = decodeURIComponent(value);
2423
+ if (decodedValue !== "") {
2424
+ cookies[decodedKey] = decodedValue;
2425
+ }
2405
2426
  }
2406
2427
  });
2407
2428
  return cookies;
2408
2429
  }
2409
2430
  };
2410
- var storage = {
2411
- /**
2412
- * 设置值(优先使用localStorage,失败则使用sessionStorage)
2413
- * @param key - 键
2414
- * @param value -
2415
- * @param options - 选项(过期时间、公钥等)
2416
- * @returns Promise<void>
2417
- */
2418
- async set(key, value, options = {}) {
2419
- try {
2420
- await localStorage.set(key, value, options);
2421
- } catch {
2422
- try {
2423
- await sessionStorage.set(key, value, { publicKey: options.publicKey });
2424
- } catch {
2425
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
2426
- console.warn("Both localStorage and sessionStorage are not available");
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();
2427
2455
  }
2428
- }
2429
- }
2430
- },
2431
- /**
2432
- * 获取值
2433
- * @param key - 键
2434
- * @param options - 选项(默认值、私钥等)
2435
- * @returns Promise<T | undefined> 值或默认值
2436
- */
2437
- async get(key, options = {}) {
2438
- const localValue = await localStorage.get(key, options);
2439
- if (localValue !== void 0) return localValue;
2440
- const sessionValue = await sessionStorage.get(key, options);
2441
- return sessionValue !== void 0 ? sessionValue : options.defaultValue;
2442
- },
2443
- /**
2444
- * 移除值
2445
- * @param key - 键
2446
- */
2447
- remove(key) {
2448
- localStorage.remove(key);
2449
- sessionStorage.remove(key);
2450
- },
2451
- /**
2452
- * 清空所有值
2453
- */
2454
- clear() {
2455
- localStorage.clear();
2456
- sessionStorage.clear();
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");
2457
2519
  }
2458
- };
2520
+ }
2521
+ function createSecureStorage(type = "local") {
2522
+ return createBackendAdapter(type);
2523
+ }
2524
+ var secureStorage = createSecureStorage("local");
2459
2525
 
2460
2526
  // src/browser/network/index.ts
2461
2527
  async function fetchWithRetry(url, options = {}, retryCount = 3, retryDelay = 1e3) {
@@ -4364,6 +4430,7 @@ exports.computeHMAC = computeHMAC;
4364
4430
  exports.contrast = contrast;
4365
4431
  exports.cookie = cookie;
4366
4432
  exports.copyToClipboard = copyToClipboard;
4433
+ exports.createSecureStorage = createSecureStorage;
4367
4434
  exports.createTracker = createTracker;
4368
4435
  exports.createTranslator = createTranslator;
4369
4436
  exports.createUploader = createUploader;
@@ -4463,7 +4530,6 @@ exports.kebabCase = kebabCase;
4463
4530
  exports.keys = keys;
4464
4531
  exports.lcm = lcm;
4465
4532
  exports.lighten = lighten;
4466
- exports.localStorage = localStorage;
4467
4533
  exports.mapKeys = mapKeys;
4468
4534
  exports.mapValues = mapValues;
4469
4535
  exports.mask = mask;
@@ -4500,7 +4566,7 @@ exports.rsaDecrypt = rsaDecrypt;
4500
4566
  exports.rsaEncrypt = rsaEncrypt;
4501
4567
  exports.sample = sample;
4502
4568
  exports.scrollTo = scrollTo;
4503
- exports.sessionStorage = sessionStorage;
4569
+ exports.secureStorage = secureStorage;
4504
4570
  exports.set = set;
4505
4571
  exports.setCommonParams = setCommonParams;
4506
4572
  exports.setQueryParams = setQueryParams;
@@ -4515,7 +4581,6 @@ exports.snakeCase = snakeCase;
4515
4581
  exports.sortBy = sortBy;
4516
4582
  exports.splitFileIntoChunks = splitFileIntoChunks;
4517
4583
  exports.startOfDay = startOfDay;
4518
- exports.storage = storage;
4519
4584
  exports.take = take;
4520
4585
  exports.takeWhile = takeWhile;
4521
4586
  exports.template = template;
package/dist/index.d.mts CHANGED
@@ -9,7 +9,7 @@ export { HSL, RGB, contrast, darken, hexToRgb, hslToRgb, lighten, mix, rgbToHex,
9
9
  export { CurrencyCode, Locale, TranslationDictionary, createTranslator, formatCurrencyI18n, formatDateI18n, formatNumberI18n, formatRelativeTime, getLocale, pluralize, translate } from './i18n.mjs';
10
10
  export { calculateBlobMD5, calculateFileMD5, formatFileSize, getFileExtension, getFileNameWithoutExtension, splitFileIntoChunks } from './file.mjs';
11
11
  export { A as ApiResponse, h as ChunkInfo, b as ChunkUploadResponse, C as ChunkUploader, d as CompleteUploadResponse, U as UploadInitRequest, a as UploadInitResponse, f as UploadOptions, e as UploadProgress, g as UploadStatus, c as createUploader, u as uploadFile } from './index-DchqyDBQ.mjs';
12
- export { StorageInitOptions, StorageOptions, clearPersistedKeys, cookie, getKeyUsageCount, getStorageKeyPair, initializeStorageKeys, localStorage, resetKeyUsageCount, sessionStorage, setStorageKeyPair, storage } from './storage.mjs';
12
+ export { SecureStorageInstance, StorageInitOptions, StorageOptions, clearPersistedKeys, cookie, createSecureStorage, getKeyUsageCount, getStorageKeyPair, initializeStorageKeys, resetKeyUsageCount, secureStorage, setStorageKeyPair } from './storage.mjs';
13
13
  export { checkOnline, downloadFile, fetchWithRetry, fetchWithTimeout, request } from './network.mjs';
14
14
  export { $, $$, addClass, copyToClipboard, getElementOffset, getScrollPosition, getStyle, isInViewport, removeClass, scrollTo, setStyle, toggleClass } from './dom.mjs';
15
15
  export { csvToJson, jsonToCsv, jsonToXml, jsonToYaml, xmlToJson, yamlToJson } from './transform.mjs';
package/dist/index.d.ts CHANGED
@@ -9,7 +9,7 @@ export { HSL, RGB, contrast, darken, hexToRgb, hslToRgb, lighten, mix, rgbToHex,
9
9
  export { CurrencyCode, Locale, TranslationDictionary, createTranslator, formatCurrencyI18n, formatDateI18n, formatNumberI18n, formatRelativeTime, getLocale, pluralize, translate } from './i18n.js';
10
10
  export { calculateBlobMD5, calculateFileMD5, formatFileSize, getFileExtension, getFileNameWithoutExtension, splitFileIntoChunks } from './file.js';
11
11
  export { A as ApiResponse, h as ChunkInfo, b as ChunkUploadResponse, C as ChunkUploader, d as CompleteUploadResponse, U as UploadInitRequest, a as UploadInitResponse, f as UploadOptions, e as UploadProgress, g as UploadStatus, c as createUploader, u as uploadFile } from './index-DchqyDBQ.js';
12
- export { StorageInitOptions, StorageOptions, clearPersistedKeys, cookie, getKeyUsageCount, getStorageKeyPair, initializeStorageKeys, localStorage, resetKeyUsageCount, sessionStorage, setStorageKeyPair, storage } from './storage.js';
12
+ export { SecureStorageInstance, StorageInitOptions, StorageOptions, clearPersistedKeys, cookie, createSecureStorage, getKeyUsageCount, getStorageKeyPair, initializeStorageKeys, resetKeyUsageCount, secureStorage, setStorageKeyPair } from './storage.js';
13
13
  export { checkOnline, downloadFile, fetchWithRetry, fetchWithTimeout, request } from './network.js';
14
14
  export { $, $$, addClass, copyToClipboard, getElementOffset, getScrollPosition, getStyle, isInViewport, removeClass, scrollTo, setStyle, toggleClass } from './dom.js';
15
15
  export { csvToJson, jsonToCsv, jsonToXml, jsonToYaml, xmlToJson, yamlToJson } from './transform.js';
package/dist/index.js CHANGED
@@ -1570,7 +1570,11 @@ async function rsaEncrypt(data, publicKey) {
1570
1570
  }
1571
1571
  const encoder = new TextEncoder();
1572
1572
  const dataBuffer = encoder.encode(data);
1573
- const maxChunkSize = 245;
1573
+ const algo = publicKey.algorithm;
1574
+ const modulusLength = typeof algo.modulusLength === "number" ? algo.modulusLength : 2048;
1575
+ const hashName = typeof algo.hash === "object" && "name" in algo.hash ? algo.hash.name : "SHA-256";
1576
+ const hashLength = hashName === "SHA-1" ? 20 : 32;
1577
+ const maxChunkSize = Math.max(Math.floor(modulusLength / 8 - 2 * hashLength - 2), 1);
1574
1578
  const chunks = [];
1575
1579
  for (let i = 0; i < dataBuffer.length; i += maxChunkSize) {
1576
1580
  const chunk2 = dataBuffer.slice(i, i + maxChunkSize);
@@ -1789,6 +1793,7 @@ var initOptions = {
1789
1793
  var actualKeyStorageKey = null;
1790
1794
  var keyUsageCount = 0;
1791
1795
  var initializationPromise = null;
1796
+ var KEY_STORAGE_KEY_REGISTRY = "__SECURE_STORAGE_KEY__";
1792
1797
  function generateKeyStorageKey() {
1793
1798
  return `_sk_${generateRandomString(32)}_${Date.now()}`;
1794
1799
  }
@@ -1807,8 +1812,18 @@ async function initializeStorageKeys(options = {}) {
1807
1812
  initOptions = { ...initOptions, ...options };
1808
1813
  if (initOptions.keyStorageKey) {
1809
1814
  actualKeyStorageKey = initOptions.keyStorageKey;
1810
- } else {
1811
- actualKeyStorageKey = generateKeyStorageKey();
1815
+ } else if (!actualKeyStorageKey) {
1816
+ if (typeof window !== "undefined" && window.localStorage) {
1817
+ const savedKeyName = window.localStorage.getItem(KEY_STORAGE_KEY_REGISTRY);
1818
+ if (savedKeyName) {
1819
+ actualKeyStorageKey = savedKeyName;
1820
+ } else {
1821
+ actualKeyStorageKey = generateKeyStorageKey();
1822
+ window.localStorage.setItem(KEY_STORAGE_KEY_REGISTRY, actualKeyStorageKey);
1823
+ }
1824
+ } else {
1825
+ actualKeyStorageKey = generateKeyStorageKey();
1826
+ }
1812
1827
  }
1813
1828
  if (initOptions.persistKeys && typeof window !== "undefined" && window.localStorage) {
1814
1829
  try {
@@ -2364,7 +2379,8 @@ var cookie = {
2364
2379
  const cookieKey = trimmed.substring(0, eqIndex).trim();
2365
2380
  const cookieValue = trimmed.substring(eqIndex + 1).trim();
2366
2381
  if (cookieKey === name) {
2367
- return decodeURIComponent(cookieValue);
2382
+ const decoded = decodeURIComponent(cookieValue);
2383
+ return decoded === "" ? void 0 : decoded;
2368
2384
  }
2369
2385
  }
2370
2386
  return void 0;
@@ -2389,66 +2405,116 @@ var cookie = {
2389
2405
  const cookies = {};
2390
2406
  document.cookie.split(";").forEach((cookieStr) => {
2391
2407
  const trimmed = cookieStr.trim();
2408
+ if (!trimmed) return;
2392
2409
  const eqIndex = trimmed.indexOf("=");
2393
2410
  if (eqIndex === -1) return;
2394
2411
  const key = trimmed.substring(0, eqIndex).trim();
2395
2412
  const value = trimmed.substring(eqIndex + 1).trim();
2396
2413
  if (key && value) {
2397
- cookies[decodeURIComponent(key)] = decodeURIComponent(value);
2414
+ const decodedKey = decodeURIComponent(key);
2415
+ const decodedValue = decodeURIComponent(value);
2416
+ if (decodedValue !== "") {
2417
+ cookies[decodedKey] = decodedValue;
2418
+ }
2398
2419
  }
2399
2420
  });
2400
2421
  return cookies;
2401
2422
  }
2402
2423
  };
2403
- var storage = {
2404
- /**
2405
- * 设置值(优先使用localStorage,失败则使用sessionStorage)
2406
- * @param key - 键
2407
- * @param value -
2408
- * @param options - 选项(过期时间、公钥等)
2409
- * @returns Promise<void>
2410
- */
2411
- async set(key, value, options = {}) {
2412
- try {
2413
- await localStorage.set(key, value, options);
2414
- } catch {
2415
- try {
2416
- await sessionStorage.set(key, value, { publicKey: options.publicKey });
2417
- } catch {
2418
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
2419
- console.warn("Both localStorage and sessionStorage are not available");
2424
+ function createBackendAdapter(type) {
2425
+ switch (type) {
2426
+ case "local":
2427
+ return {
2428
+ async set(key, value, options) {
2429
+ await localStorage.set(key, value, {
2430
+ expiry: options?.expiry,
2431
+ publicKey: options?.publicKey
2432
+ });
2433
+ },
2434
+ async get(key, options) {
2435
+ return localStorage.get(key, {
2436
+ defaultValue: options?.defaultValue,
2437
+ privateKey: options?.privateKey
2438
+ });
2439
+ },
2440
+ remove(key) {
2441
+ localStorage.remove(key);
2442
+ },
2443
+ clear() {
2444
+ localStorage.clear();
2445
+ },
2446
+ keys() {
2447
+ return localStorage.keys();
2420
2448
  }
2421
- }
2422
- }
2423
- },
2424
- /**
2425
- * 获取值
2426
- * @param key - 键
2427
- * @param options - 选项(默认值、私钥等)
2428
- * @returns Promise<T | undefined> 值或默认值
2429
- */
2430
- async get(key, options = {}) {
2431
- const localValue = await localStorage.get(key, options);
2432
- if (localValue !== void 0) return localValue;
2433
- const sessionValue = await sessionStorage.get(key, options);
2434
- return sessionValue !== void 0 ? sessionValue : options.defaultValue;
2435
- },
2436
- /**
2437
- * 移除值
2438
- * @param key - 键
2439
- */
2440
- remove(key) {
2441
- localStorage.remove(key);
2442
- sessionStorage.remove(key);
2443
- },
2444
- /**
2445
- * 清空所有值
2446
- */
2447
- clear() {
2448
- localStorage.clear();
2449
- sessionStorage.clear();
2449
+ };
2450
+ case "session":
2451
+ return {
2452
+ async set(key, value, options) {
2453
+ await sessionStorage.set(key, value, {
2454
+ publicKey: options?.publicKey
2455
+ });
2456
+ },
2457
+ async get(key, options) {
2458
+ return sessionStorage.get(key, {
2459
+ defaultValue: options?.defaultValue,
2460
+ privateKey: options?.privateKey
2461
+ });
2462
+ },
2463
+ remove(key) {
2464
+ sessionStorage.remove(key);
2465
+ },
2466
+ clear() {
2467
+ sessionStorage.clear();
2468
+ },
2469
+ keys() {
2470
+ if (typeof window === "undefined" || !window.sessionStorage) return [];
2471
+ const keys2 = [];
2472
+ try {
2473
+ for (let i = 0; i < window.sessionStorage.length; i++) {
2474
+ const key = window.sessionStorage.key(i);
2475
+ if (key) keys2.push(key);
2476
+ }
2477
+ } catch (error) {
2478
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
2479
+ console.error("sessionStorage.keys error");
2480
+ }
2481
+ }
2482
+ return keys2;
2483
+ }
2484
+ };
2485
+ case "cookie":
2486
+ return {
2487
+ async set(key, value) {
2488
+ cookie.set(key, String(value));
2489
+ },
2490
+ async get(key, options) {
2491
+ const value = cookie.get(key);
2492
+ if (value === void 0) return options?.defaultValue;
2493
+ try {
2494
+ return JSON.parse(value);
2495
+ } catch {
2496
+ return value;
2497
+ }
2498
+ },
2499
+ remove(key) {
2500
+ cookie.remove(key);
2501
+ },
2502
+ clear() {
2503
+ const all = cookie.getAll();
2504
+ Object.keys(all).forEach((k) => cookie.remove(k));
2505
+ },
2506
+ keys() {
2507
+ return Object.keys(cookie.getAll());
2508
+ }
2509
+ };
2510
+ default:
2511
+ return createBackendAdapter("local");
2450
2512
  }
2451
- };
2513
+ }
2514
+ function createSecureStorage(type = "local") {
2515
+ return createBackendAdapter(type);
2516
+ }
2517
+ var secureStorage = createSecureStorage("local");
2452
2518
 
2453
2519
  // src/browser/network/index.ts
2454
2520
  async function fetchWithRetry(url, options = {}, retryCount = 3, retryDelay = 1e3) {
@@ -4319,4 +4385,4 @@ function convertRes2Blob(response) {
4319
4385
  }
4320
4386
  }
4321
4387
 
4322
- export { $, $$, BinaryTree, ChunkUploader, DataQueue, Graph, LRUCache, LinkedList, Queue, Stack, Tracker, UploadStatus, addClass, addDays, addMonths, addYears, aesGCMDecrypt, aesGCMEncrypt, base64Decode, base64Encode, batch, binarySearch, bubbleSort, buildUrl, calculateBlobMD5, calculateFileMD5, camelCase, capitalize, ceil, checkOnline, chunk, clamp, clearPersistedKeys, compact, computeHMAC, contrast, cookie, copyToClipboard, createTracker, createTranslator, createUploader, csvToJson, darken, debounce, deepClone, deepMerge, defaults, deriveKeyFromPassword, diffDays, difference, downloadFile, drop, dropWhile, endOfDay, escapeHtml, exportPrivateKey, exportPublicKey, factorial, fetchWithRetry, fetchWithTimeout, fibonacci, fibonacciSequence, findIndexBy, flatten, floor, flush, formatBytes, formatCurrency, formatCurrencyI18n, formatDate, formatDateI18n, formatFileSize, formatNumber, formatNumberI18n, formatRelativeTime, gcd, generateHMACKey, generateRSAKeyPair, generateRandomString, generateUUID, get, getDateFormatByGMT, getElementOffset, getFileExtension, getFileNameWithoutExtension, getKeyUsageCount, getLocale, getQuarter, getQueryParams, getRelativeTime, getScrollPosition, getStorageKeyPair, getStyle, getTimeFromGMT, getTracker, getWeekNumber, groupBy, hash, hexToRgb, highlight, hslToRgb, importPrivateKey, importPublicKey, initTracker, initializeStorageKeys, intersection, invert, isAbsoluteUrl, isBetween, isEmpty, isEmptyObject, isEqual, isFloat, isInViewport, isInteger, isNumeric, isToday, isValidDomain, isValidEmail, isValidHexColor, isValidIP, isValidIdCard, isValidJSON, isValidPhone, isValidUUID, isValidUrl, isWeekday, isWeekend, isYesterday, joinUrl, jsonToCsv, jsonToXml, jsonToYaml, kebabCase, keys, lcm, lighten, localStorage, mapKeys, mapValues, mask, maskEmail, maskPhone, memoize, merge, mergeSort, mix, normalizeUrl, omit, omitBy, once, parseNumber, parseUrl, partition, pascalCase, percent, pick, pickBy, pluralize, quickSort, random, removeAccents, removeClass, removeQueryParams, request, resetKeyUsageCount, retry, rgbToHex, rgbToHsl, round, rsaDecrypt, rsaEncrypt, sample, scrollTo, sessionStorage, set, setCommonParams, setQueryParams, setServiceEventHandlers, setStorageKeyPair, setStyle, setUserInfo, sha256, shuffle, slugify, snakeCase, sortBy, splitFileIntoChunks, startOfDay, storage, take, takeWhile, template, throttle, timeout, toFixed, toggleClass, trackClick, trackEvent, trackExposure, trackPageView, transform, translate, truncate, unescapeHtml, union, unique, unzip, updateQueryParams, uploadFile, values, verifyHMAC, xmlToJson, yamlToJson, zip };
4388
+ export { $, $$, BinaryTree, ChunkUploader, DataQueue, Graph, LRUCache, LinkedList, Queue, Stack, Tracker, UploadStatus, addClass, addDays, addMonths, addYears, aesGCMDecrypt, aesGCMEncrypt, base64Decode, base64Encode, batch, binarySearch, bubbleSort, buildUrl, calculateBlobMD5, calculateFileMD5, camelCase, capitalize, ceil, checkOnline, chunk, clamp, clearPersistedKeys, compact, computeHMAC, contrast, cookie, copyToClipboard, createSecureStorage, createTracker, createTranslator, createUploader, csvToJson, darken, debounce, deepClone, deepMerge, defaults, deriveKeyFromPassword, diffDays, difference, downloadFile, drop, dropWhile, endOfDay, escapeHtml, exportPrivateKey, exportPublicKey, factorial, fetchWithRetry, fetchWithTimeout, fibonacci, fibonacciSequence, findIndexBy, flatten, floor, flush, formatBytes, formatCurrency, formatCurrencyI18n, formatDate, formatDateI18n, formatFileSize, formatNumber, formatNumberI18n, formatRelativeTime, gcd, generateHMACKey, generateRSAKeyPair, generateRandomString, generateUUID, get, getDateFormatByGMT, getElementOffset, getFileExtension, getFileNameWithoutExtension, getKeyUsageCount, getLocale, getQuarter, getQueryParams, getRelativeTime, getScrollPosition, getStorageKeyPair, getStyle, getTimeFromGMT, getTracker, getWeekNumber, groupBy, hash, hexToRgb, highlight, hslToRgb, importPrivateKey, importPublicKey, initTracker, initializeStorageKeys, intersection, invert, isAbsoluteUrl, isBetween, isEmpty, isEmptyObject, isEqual, isFloat, isInViewport, isInteger, isNumeric, isToday, isValidDomain, isValidEmail, isValidHexColor, isValidIP, isValidIdCard, isValidJSON, isValidPhone, isValidUUID, isValidUrl, isWeekday, isWeekend, isYesterday, joinUrl, jsonToCsv, jsonToXml, jsonToYaml, kebabCase, keys, lcm, lighten, mapKeys, mapValues, mask, maskEmail, maskPhone, memoize, merge, mergeSort, mix, normalizeUrl, omit, omitBy, once, parseNumber, parseUrl, partition, pascalCase, percent, pick, pickBy, pluralize, quickSort, random, removeAccents, removeClass, removeQueryParams, request, resetKeyUsageCount, retry, rgbToHex, rgbToHsl, round, rsaDecrypt, rsaEncrypt, sample, scrollTo, secureStorage, set, setCommonParams, setQueryParams, setServiceEventHandlers, setStorageKeyPair, setStyle, setUserInfo, sha256, shuffle, slugify, snakeCase, sortBy, splitFileIntoChunks, startOfDay, take, takeWhile, template, throttle, timeout, toFixed, toggleClass, trackClick, trackEvent, trackExposure, trackPageView, transform, translate, truncate, unescapeHtml, union, unique, unzip, updateQueryParams, uploadFile, values, verifyHMAC, xmlToJson, yamlToJson, zip };
package/dist/storage.cjs CHANGED
@@ -51,7 +51,11 @@ async function rsaEncrypt(data, publicKey) {
51
51
  }
52
52
  const encoder = new TextEncoder();
53
53
  const dataBuffer = encoder.encode(data);
54
- const maxChunkSize = 245;
54
+ const algo = publicKey.algorithm;
55
+ const modulusLength = typeof algo.modulusLength === "number" ? algo.modulusLength : 2048;
56
+ const hashName = typeof algo.hash === "object" && "name" in algo.hash ? algo.hash.name : "SHA-256";
57
+ const hashLength = hashName === "SHA-1" ? 20 : 32;
58
+ const maxChunkSize = Math.max(Math.floor(modulusLength / 8 - 2 * hashLength - 2), 1);
55
59
  const chunks = [];
56
60
  for (let i = 0; i < dataBuffer.length; i += maxChunkSize) {
57
61
  const chunk = dataBuffer.slice(i, i + maxChunkSize);
@@ -270,6 +274,7 @@ var initOptions = {
270
274
  var actualKeyStorageKey = null;
271
275
  var keyUsageCount = 0;
272
276
  var initializationPromise = null;
277
+ var KEY_STORAGE_KEY_REGISTRY = "__SECURE_STORAGE_KEY__";
273
278
  function generateKeyStorageKey() {
274
279
  return `_sk_${generateRandomString(32)}_${Date.now()}`;
275
280
  }
@@ -288,8 +293,18 @@ async function initializeStorageKeys(options = {}) {
288
293
  initOptions = { ...initOptions, ...options };
289
294
  if (initOptions.keyStorageKey) {
290
295
  actualKeyStorageKey = initOptions.keyStorageKey;
291
- } else {
292
- actualKeyStorageKey = generateKeyStorageKey();
296
+ } else if (!actualKeyStorageKey) {
297
+ if (typeof window !== "undefined" && window.localStorage) {
298
+ const savedKeyName = window.localStorage.getItem(KEY_STORAGE_KEY_REGISTRY);
299
+ if (savedKeyName) {
300
+ actualKeyStorageKey = savedKeyName;
301
+ } else {
302
+ actualKeyStorageKey = generateKeyStorageKey();
303
+ window.localStorage.setItem(KEY_STORAGE_KEY_REGISTRY, actualKeyStorageKey);
304
+ }
305
+ } else {
306
+ actualKeyStorageKey = generateKeyStorageKey();
307
+ }
293
308
  }
294
309
  if (initOptions.persistKeys && typeof window !== "undefined" && window.localStorage) {
295
310
  try {
@@ -845,7 +860,8 @@ var cookie = {
845
860
  const cookieKey = trimmed.substring(0, eqIndex).trim();
846
861
  const cookieValue = trimmed.substring(eqIndex + 1).trim();
847
862
  if (cookieKey === name) {
848
- return decodeURIComponent(cookieValue);
863
+ const decoded = decodeURIComponent(cookieValue);
864
+ return decoded === "" ? void 0 : decoded;
849
865
  }
850
866
  }
851
867
  return void 0;
@@ -870,74 +886,123 @@ var cookie = {
870
886
  const cookies = {};
871
887
  document.cookie.split(";").forEach((cookieStr) => {
872
888
  const trimmed = cookieStr.trim();
889
+ if (!trimmed) return;
873
890
  const eqIndex = trimmed.indexOf("=");
874
891
  if (eqIndex === -1) return;
875
892
  const key = trimmed.substring(0, eqIndex).trim();
876
893
  const value = trimmed.substring(eqIndex + 1).trim();
877
894
  if (key && value) {
878
- cookies[decodeURIComponent(key)] = decodeURIComponent(value);
895
+ const decodedKey = decodeURIComponent(key);
896
+ const decodedValue = decodeURIComponent(value);
897
+ if (decodedValue !== "") {
898
+ cookies[decodedKey] = decodedValue;
899
+ }
879
900
  }
880
901
  });
881
902
  return cookies;
882
903
  }
883
904
  };
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");
905
+ function createBackendAdapter(type) {
906
+ switch (type) {
907
+ case "local":
908
+ return {
909
+ async set(key, value, options) {
910
+ await localStorage.set(key, value, {
911
+ expiry: options?.expiry,
912
+ publicKey: options?.publicKey
913
+ });
914
+ },
915
+ async get(key, options) {
916
+ return localStorage.get(key, {
917
+ defaultValue: options?.defaultValue,
918
+ privateKey: options?.privateKey
919
+ });
920
+ },
921
+ remove(key) {
922
+ localStorage.remove(key);
923
+ },
924
+ clear() {
925
+ localStorage.clear();
926
+ },
927
+ keys() {
928
+ return localStorage.keys();
901
929
  }
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();
930
+ };
931
+ case "session":
932
+ return {
933
+ async set(key, value, options) {
934
+ await sessionStorage.set(key, value, {
935
+ publicKey: options?.publicKey
936
+ });
937
+ },
938
+ async get(key, options) {
939
+ return sessionStorage.get(key, {
940
+ defaultValue: options?.defaultValue,
941
+ privateKey: options?.privateKey
942
+ });
943
+ },
944
+ remove(key) {
945
+ sessionStorage.remove(key);
946
+ },
947
+ clear() {
948
+ sessionStorage.clear();
949
+ },
950
+ keys() {
951
+ if (typeof window === "undefined" || !window.sessionStorage) return [];
952
+ const keys = [];
953
+ try {
954
+ for (let i = 0; i < window.sessionStorage.length; i++) {
955
+ const key = window.sessionStorage.key(i);
956
+ if (key) keys.push(key);
957
+ }
958
+ } catch (error) {
959
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
960
+ console.error("sessionStorage.keys error");
961
+ }
962
+ }
963
+ return keys;
964
+ }
965
+ };
966
+ case "cookie":
967
+ return {
968
+ async set(key, value) {
969
+ cookie.set(key, String(value));
970
+ },
971
+ async get(key, options) {
972
+ const value = cookie.get(key);
973
+ if (value === void 0) return options?.defaultValue;
974
+ try {
975
+ return JSON.parse(value);
976
+ } catch {
977
+ return value;
978
+ }
979
+ },
980
+ remove(key) {
981
+ cookie.remove(key);
982
+ },
983
+ clear() {
984
+ const all = cookie.getAll();
985
+ Object.keys(all).forEach((k) => cookie.remove(k));
986
+ },
987
+ keys() {
988
+ return Object.keys(cookie.getAll());
989
+ }
990
+ };
991
+ default:
992
+ return createBackendAdapter("local");
931
993
  }
932
- };
994
+ }
995
+ function createSecureStorage(type = "local") {
996
+ return createBackendAdapter(type);
997
+ }
998
+ var secureStorage = createSecureStorage("local");
933
999
 
934
1000
  exports.clearPersistedKeys = clearPersistedKeys;
935
1001
  exports.cookie = cookie;
1002
+ exports.createSecureStorage = createSecureStorage;
936
1003
  exports.getKeyUsageCount = getKeyUsageCount;
937
1004
  exports.getStorageKeyPair = getStorageKeyPair;
938
1005
  exports.initializeStorageKeys = initializeStorageKeys;
939
- exports.localStorage = localStorage;
940
1006
  exports.resetKeyUsageCount = resetKeyUsageCount;
941
- exports.sessionStorage = sessionStorage;
1007
+ exports.secureStorage = secureStorage;
942
1008
  exports.setStorageKeyPair = setStorageKeyPair;
943
- exports.storage = storage;
@@ -70,80 +70,6 @@ declare function getKeyUsageCount(): number;
70
70
  * 重置密钥使用计数
71
71
  */
72
72
  declare function resetKeyUsageCount(): void;
73
- /**
74
- * localStorage封装(支持过期时间和RSA加密)
75
- */
76
- declare const localStorage: {
77
- /**
78
- * 设置值
79
- * @param key - 键
80
- * @param value - 值
81
- * @param options - 选项(过期时间、密钥等)
82
- * @returns Promise<void>
83
- */
84
- set<T>(key: string, value: T, options?: {
85
- expiry?: number;
86
- publicKey?: CryptoKey;
87
- }): Promise<void>;
88
- /**
89
- * 获取值
90
- * @param key - 键
91
- * @param options - 选项(默认值、私钥等)
92
- * @returns Promise<T | undefined> 值或默认值
93
- */
94
- get<T>(key: string, options?: {
95
- defaultValue?: T;
96
- privateKey?: CryptoKey;
97
- }): Promise<T | undefined>;
98
- /**
99
- * 移除值
100
- * @param key - 键
101
- */
102
- remove(key: string): void;
103
- /**
104
- * 清空所有值
105
- */
106
- clear(): void;
107
- /**
108
- * 获取所有键
109
- * @returns 键数组
110
- */
111
- keys(): string[];
112
- };
113
- /**
114
- * sessionStorage封装(支持RSA加密)
115
- */
116
- declare const sessionStorage: {
117
- /**
118
- * 设置值
119
- * @param key - 键
120
- * @param value - 值
121
- * @param options - 选项(公钥等)
122
- * @returns Promise<void>
123
- */
124
- set<T>(key: string, value: T, options?: {
125
- publicKey?: CryptoKey;
126
- }): Promise<void>;
127
- /**
128
- * 获取值
129
- * @param key - 键
130
- * @param options - 选项(默认值、私钥等)
131
- * @returns Promise<T | undefined> 值或默认值
132
- */
133
- get<T>(key: string, options?: {
134
- defaultValue?: T;
135
- privateKey?: CryptoKey;
136
- }): Promise<T | undefined>;
137
- /**
138
- * 移除值
139
- * @param key - 键
140
- */
141
- remove(key: string): void;
142
- /**
143
- * 清空所有值
144
- */
145
- clear(): void;
146
- };
147
73
  /**
148
74
  * Cookie操作封装
149
75
  */
@@ -183,39 +109,33 @@ declare const cookie: {
183
109
  getAll(): Record<string, string>;
184
110
  };
185
111
  /**
186
- * 统一存储接口(自动选择存储方式,支持RSA加密)
112
+ * 统一安全存储接口(通过后端适配器封装 localStorage / sessionStorage / Cookie)
187
113
  */
188
- declare const storage: {
189
- /**
190
- * 设置值(优先使用localStorage,失败则使用sessionStorage)
191
- * @param key - 键
192
- * @param value - 值
193
- * @param options - 选项(过期时间、公钥等)
194
- * @returns Promise<void>
195
- */
114
+ type SecureStorageBackendType = 'local' | 'session' | 'cookie';
115
+ interface SecureStorageInstance {
196
116
  set<T>(key: string, value: T, options?: {
197
117
  expiry?: number;
198
118
  publicKey?: CryptoKey;
119
+ privateKey?: CryptoKey;
120
+ defaultValue?: T;
199
121
  }): Promise<void>;
200
- /**
201
- * 获取值
202
- * @param key - 键
203
- * @param options - 选项(默认值、私钥等)
204
- * @returns Promise<T | undefined> 值或默认值
205
- */
206
122
  get<T>(key: string, options?: {
207
123
  defaultValue?: T;
208
124
  privateKey?: CryptoKey;
209
125
  }): Promise<T | undefined>;
210
- /**
211
- * 移除值
212
- * @param key - 键
213
- */
214
126
  remove(key: string): void;
215
- /**
216
- * 清空所有值
217
- */
218
127
  clear(): void;
219
- };
128
+ keys(): string[];
129
+ }
130
+ /**
131
+ * 工厂函数:根据后端类型创建 SecureStorage 实例
132
+ * 使用方可在应用启动时自行决定使用 local / session / cookie
133
+ */
134
+ declare function createSecureStorage(type?: SecureStorageBackendType): SecureStorageInstance;
135
+ /**
136
+ * 默认导出的 SecureStorage:使用 localStorage 作为后端
137
+ * 与之前 `secureStorage` 的语义保持一致
138
+ */
139
+ declare const secureStorage: SecureStorageInstance;
220
140
 
221
- export { type StorageInitOptions, type StorageOptions, clearPersistedKeys, cookie, getKeyUsageCount, getStorageKeyPair, initializeStorageKeys, localStorage, resetKeyUsageCount, sessionStorage, setStorageKeyPair, storage };
141
+ export { type SecureStorageInstance, type StorageInitOptions, type StorageOptions, clearPersistedKeys, cookie, createSecureStorage, getKeyUsageCount, getStorageKeyPair, initializeStorageKeys, resetKeyUsageCount, secureStorage, setStorageKeyPair };
package/dist/storage.d.ts CHANGED
@@ -70,80 +70,6 @@ declare function getKeyUsageCount(): number;
70
70
  * 重置密钥使用计数
71
71
  */
72
72
  declare function resetKeyUsageCount(): void;
73
- /**
74
- * localStorage封装(支持过期时间和RSA加密)
75
- */
76
- declare const localStorage: {
77
- /**
78
- * 设置值
79
- * @param key - 键
80
- * @param value - 值
81
- * @param options - 选项(过期时间、密钥等)
82
- * @returns Promise<void>
83
- */
84
- set<T>(key: string, value: T, options?: {
85
- expiry?: number;
86
- publicKey?: CryptoKey;
87
- }): Promise<void>;
88
- /**
89
- * 获取值
90
- * @param key - 键
91
- * @param options - 选项(默认值、私钥等)
92
- * @returns Promise<T | undefined> 值或默认值
93
- */
94
- get<T>(key: string, options?: {
95
- defaultValue?: T;
96
- privateKey?: CryptoKey;
97
- }): Promise<T | undefined>;
98
- /**
99
- * 移除值
100
- * @param key - 键
101
- */
102
- remove(key: string): void;
103
- /**
104
- * 清空所有值
105
- */
106
- clear(): void;
107
- /**
108
- * 获取所有键
109
- * @returns 键数组
110
- */
111
- keys(): string[];
112
- };
113
- /**
114
- * sessionStorage封装(支持RSA加密)
115
- */
116
- declare const sessionStorage: {
117
- /**
118
- * 设置值
119
- * @param key - 键
120
- * @param value - 值
121
- * @param options - 选项(公钥等)
122
- * @returns Promise<void>
123
- */
124
- set<T>(key: string, value: T, options?: {
125
- publicKey?: CryptoKey;
126
- }): Promise<void>;
127
- /**
128
- * 获取值
129
- * @param key - 键
130
- * @param options - 选项(默认值、私钥等)
131
- * @returns Promise<T | undefined> 值或默认值
132
- */
133
- get<T>(key: string, options?: {
134
- defaultValue?: T;
135
- privateKey?: CryptoKey;
136
- }): Promise<T | undefined>;
137
- /**
138
- * 移除值
139
- * @param key - 键
140
- */
141
- remove(key: string): void;
142
- /**
143
- * 清空所有值
144
- */
145
- clear(): void;
146
- };
147
73
  /**
148
74
  * Cookie操作封装
149
75
  */
@@ -183,39 +109,33 @@ declare const cookie: {
183
109
  getAll(): Record<string, string>;
184
110
  };
185
111
  /**
186
- * 统一存储接口(自动选择存储方式,支持RSA加密)
112
+ * 统一安全存储接口(通过后端适配器封装 localStorage / sessionStorage / Cookie)
187
113
  */
188
- declare const storage: {
189
- /**
190
- * 设置值(优先使用localStorage,失败则使用sessionStorage)
191
- * @param key - 键
192
- * @param value - 值
193
- * @param options - 选项(过期时间、公钥等)
194
- * @returns Promise<void>
195
- */
114
+ type SecureStorageBackendType = 'local' | 'session' | 'cookie';
115
+ interface SecureStorageInstance {
196
116
  set<T>(key: string, value: T, options?: {
197
117
  expiry?: number;
198
118
  publicKey?: CryptoKey;
119
+ privateKey?: CryptoKey;
120
+ defaultValue?: T;
199
121
  }): Promise<void>;
200
- /**
201
- * 获取值
202
- * @param key - 键
203
- * @param options - 选项(默认值、私钥等)
204
- * @returns Promise<T | undefined> 值或默认值
205
- */
206
122
  get<T>(key: string, options?: {
207
123
  defaultValue?: T;
208
124
  privateKey?: CryptoKey;
209
125
  }): Promise<T | undefined>;
210
- /**
211
- * 移除值
212
- * @param key - 键
213
- */
214
126
  remove(key: string): void;
215
- /**
216
- * 清空所有值
217
- */
218
127
  clear(): void;
219
- };
128
+ keys(): string[];
129
+ }
130
+ /**
131
+ * 工厂函数:根据后端类型创建 SecureStorage 实例
132
+ * 使用方可在应用启动时自行决定使用 local / session / cookie
133
+ */
134
+ declare function createSecureStorage(type?: SecureStorageBackendType): SecureStorageInstance;
135
+ /**
136
+ * 默认导出的 SecureStorage:使用 localStorage 作为后端
137
+ * 与之前 `secureStorage` 的语义保持一致
138
+ */
139
+ declare const secureStorage: SecureStorageInstance;
220
140
 
221
- export { type StorageInitOptions, type StorageOptions, clearPersistedKeys, cookie, getKeyUsageCount, getStorageKeyPair, initializeStorageKeys, localStorage, resetKeyUsageCount, sessionStorage, setStorageKeyPair, storage };
141
+ export { type SecureStorageInstance, type StorageInitOptions, type StorageOptions, clearPersistedKeys, cookie, createSecureStorage, getKeyUsageCount, getStorageKeyPair, initializeStorageKeys, resetKeyUsageCount, secureStorage, setStorageKeyPair };
package/dist/storage.js CHANGED
@@ -49,7 +49,11 @@ async function rsaEncrypt(data, publicKey) {
49
49
  }
50
50
  const encoder = new TextEncoder();
51
51
  const dataBuffer = encoder.encode(data);
52
- const maxChunkSize = 245;
52
+ const algo = publicKey.algorithm;
53
+ const modulusLength = typeof algo.modulusLength === "number" ? algo.modulusLength : 2048;
54
+ const hashName = typeof algo.hash === "object" && "name" in algo.hash ? algo.hash.name : "SHA-256";
55
+ const hashLength = hashName === "SHA-1" ? 20 : 32;
56
+ const maxChunkSize = Math.max(Math.floor(modulusLength / 8 - 2 * hashLength - 2), 1);
53
57
  const chunks = [];
54
58
  for (let i = 0; i < dataBuffer.length; i += maxChunkSize) {
55
59
  const chunk = dataBuffer.slice(i, i + maxChunkSize);
@@ -268,6 +272,7 @@ var initOptions = {
268
272
  var actualKeyStorageKey = null;
269
273
  var keyUsageCount = 0;
270
274
  var initializationPromise = null;
275
+ var KEY_STORAGE_KEY_REGISTRY = "__SECURE_STORAGE_KEY__";
271
276
  function generateKeyStorageKey() {
272
277
  return `_sk_${generateRandomString(32)}_${Date.now()}`;
273
278
  }
@@ -286,8 +291,18 @@ async function initializeStorageKeys(options = {}) {
286
291
  initOptions = { ...initOptions, ...options };
287
292
  if (initOptions.keyStorageKey) {
288
293
  actualKeyStorageKey = initOptions.keyStorageKey;
289
- } else {
290
- actualKeyStorageKey = generateKeyStorageKey();
294
+ } else if (!actualKeyStorageKey) {
295
+ if (typeof window !== "undefined" && window.localStorage) {
296
+ const savedKeyName = window.localStorage.getItem(KEY_STORAGE_KEY_REGISTRY);
297
+ if (savedKeyName) {
298
+ actualKeyStorageKey = savedKeyName;
299
+ } else {
300
+ actualKeyStorageKey = generateKeyStorageKey();
301
+ window.localStorage.setItem(KEY_STORAGE_KEY_REGISTRY, actualKeyStorageKey);
302
+ }
303
+ } else {
304
+ actualKeyStorageKey = generateKeyStorageKey();
305
+ }
291
306
  }
292
307
  if (initOptions.persistKeys && typeof window !== "undefined" && window.localStorage) {
293
308
  try {
@@ -843,7 +858,8 @@ var cookie = {
843
858
  const cookieKey = trimmed.substring(0, eqIndex).trim();
844
859
  const cookieValue = trimmed.substring(eqIndex + 1).trim();
845
860
  if (cookieKey === name) {
846
- return decodeURIComponent(cookieValue);
861
+ const decoded = decodeURIComponent(cookieValue);
862
+ return decoded === "" ? void 0 : decoded;
847
863
  }
848
864
  }
849
865
  return void 0;
@@ -868,65 +884,115 @@ var cookie = {
868
884
  const cookies = {};
869
885
  document.cookie.split(";").forEach((cookieStr) => {
870
886
  const trimmed = cookieStr.trim();
887
+ if (!trimmed) return;
871
888
  const eqIndex = trimmed.indexOf("=");
872
889
  if (eqIndex === -1) return;
873
890
  const key = trimmed.substring(0, eqIndex).trim();
874
891
  const value = trimmed.substring(eqIndex + 1).trim();
875
892
  if (key && value) {
876
- cookies[decodeURIComponent(key)] = decodeURIComponent(value);
893
+ const decodedKey = decodeURIComponent(key);
894
+ const decodedValue = decodeURIComponent(value);
895
+ if (decodedValue !== "") {
896
+ cookies[decodedKey] = decodedValue;
897
+ }
877
898
  }
878
899
  });
879
900
  return cookies;
880
901
  }
881
902
  };
882
- var storage = {
883
- /**
884
- * 设置值(优先使用localStorage,失败则使用sessionStorage)
885
- * @param key - 键
886
- * @param value -
887
- * @param options - 选项(过期时间、公钥等)
888
- * @returns Promise<void>
889
- */
890
- async set(key, value, options = {}) {
891
- try {
892
- await localStorage.set(key, value, options);
893
- } catch {
894
- try {
895
- await sessionStorage.set(key, value, { publicKey: options.publicKey });
896
- } catch {
897
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
898
- console.warn("Both localStorage and sessionStorage are not available");
903
+ function createBackendAdapter(type) {
904
+ switch (type) {
905
+ case "local":
906
+ return {
907
+ async set(key, value, options) {
908
+ await localStorage.set(key, value, {
909
+ expiry: options?.expiry,
910
+ publicKey: options?.publicKey
911
+ });
912
+ },
913
+ async get(key, options) {
914
+ return localStorage.get(key, {
915
+ defaultValue: options?.defaultValue,
916
+ privateKey: options?.privateKey
917
+ });
918
+ },
919
+ remove(key) {
920
+ localStorage.remove(key);
921
+ },
922
+ clear() {
923
+ localStorage.clear();
924
+ },
925
+ keys() {
926
+ return localStorage.keys();
899
927
  }
900
- }
901
- }
902
- },
903
- /**
904
- * 获取值
905
- * @param key - 键
906
- * @param options - 选项(默认值、私钥等)
907
- * @returns Promise<T | undefined> 值或默认值
908
- */
909
- async get(key, options = {}) {
910
- const localValue = await localStorage.get(key, options);
911
- if (localValue !== void 0) return localValue;
912
- const sessionValue = await sessionStorage.get(key, options);
913
- return sessionValue !== void 0 ? sessionValue : options.defaultValue;
914
- },
915
- /**
916
- * 移除值
917
- * @param key - 键
918
- */
919
- remove(key) {
920
- localStorage.remove(key);
921
- sessionStorage.remove(key);
922
- },
923
- /**
924
- * 清空所有值
925
- */
926
- clear() {
927
- localStorage.clear();
928
- sessionStorage.clear();
928
+ };
929
+ case "session":
930
+ return {
931
+ async set(key, value, options) {
932
+ await sessionStorage.set(key, value, {
933
+ publicKey: options?.publicKey
934
+ });
935
+ },
936
+ async get(key, options) {
937
+ return sessionStorage.get(key, {
938
+ defaultValue: options?.defaultValue,
939
+ privateKey: options?.privateKey
940
+ });
941
+ },
942
+ remove(key) {
943
+ sessionStorage.remove(key);
944
+ },
945
+ clear() {
946
+ sessionStorage.clear();
947
+ },
948
+ keys() {
949
+ if (typeof window === "undefined" || !window.sessionStorage) return [];
950
+ const keys = [];
951
+ try {
952
+ for (let i = 0; i < window.sessionStorage.length; i++) {
953
+ const key = window.sessionStorage.key(i);
954
+ if (key) keys.push(key);
955
+ }
956
+ } catch (error) {
957
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
958
+ console.error("sessionStorage.keys error");
959
+ }
960
+ }
961
+ return keys;
962
+ }
963
+ };
964
+ case "cookie":
965
+ return {
966
+ async set(key, value) {
967
+ cookie.set(key, String(value));
968
+ },
969
+ async get(key, options) {
970
+ const value = cookie.get(key);
971
+ if (value === void 0) return options?.defaultValue;
972
+ try {
973
+ return JSON.parse(value);
974
+ } catch {
975
+ return value;
976
+ }
977
+ },
978
+ remove(key) {
979
+ cookie.remove(key);
980
+ },
981
+ clear() {
982
+ const all = cookie.getAll();
983
+ Object.keys(all).forEach((k) => cookie.remove(k));
984
+ },
985
+ keys() {
986
+ return Object.keys(cookie.getAll());
987
+ }
988
+ };
989
+ default:
990
+ return createBackendAdapter("local");
929
991
  }
930
- };
992
+ }
993
+ function createSecureStorage(type = "local") {
994
+ return createBackendAdapter(type);
995
+ }
996
+ var secureStorage = createSecureStorage("local");
931
997
 
932
- export { clearPersistedKeys, cookie, getKeyUsageCount, getStorageKeyPair, initializeStorageKeys, localStorage, resetKeyUsageCount, sessionStorage, setStorageKeyPair, storage };
998
+ export { clearPersistedKeys, cookie, createSecureStorage, getKeyUsageCount, getStorageKeyPair, initializeStorageKeys, resetKeyUsageCount, secureStorage, setStorageKeyPair };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alibarbar/common",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "Alibarbar 通用工具库",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -139,6 +139,8 @@
139
139
  "format": "prettier --write \"src/**/*.{ts,json,md}\"",
140
140
  "format:check": "prettier --check \"src/**/*.{ts,json,md}\"",
141
141
  "prepublishOnly": "npm run build && npm run test",
142
+ "prepack": "npm run build",
143
+ "pack:dry-run": "npm pack --dry-run",
142
144
  "type-check": "tsc --noEmit",
143
145
  "analyze": "echo 'Bundle size analysis - check dist/ directory'",
144
146
  "precommit": "npm run lint && npm run format:check && npm run type-check",