|
|
@@ -43,6 +43,13 @@ interface StorageData<T = any> {
|
|
|
expire: number;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * 是否处于可访问 localStorage 的浏览器环境。
|
|
|
+ * 预渲染(SSG)在 Node 端执行,无 window/localStorage,此时所有 storage 操作应安全降级为空操作/返回 null,
|
|
|
+ * 而非抛错。hydrate 后回到浏览器环境即恢复正常读写。
|
|
|
+ */
|
|
|
+const canUseStorage = () => typeof window !== 'undefined' && !!window.localStorage;
|
|
|
+
|
|
|
function shouldEncryptKey(functionOptions?: StorageOptions, instanceOptions?: StorageOptions) {
|
|
|
if (globalConfig.security.enableStorageEncryption) {
|
|
|
return functionOptions?.encryptKey ?? instanceOptions?.encryptKey ?? false;
|
|
|
@@ -74,6 +81,7 @@ export function createLocalStorage({
|
|
|
* @param opts 当传递了 opts 时,opts 中存在的配置项会覆盖当前实例的全局配置中的配置项。
|
|
|
*/
|
|
|
function set<T = any>(key: string, data: T, opts?: StorageOptions) {
|
|
|
+ if (!canUseStorage()) return;
|
|
|
const expire = opts?.expire ?? confExpire;
|
|
|
const isEncryptKey = shouldEncryptKey(opts, { encryptKey: confEncryptKey });
|
|
|
const isEncryptData = shouldEncryptData(opts, { encryptData: confEncryptData });
|
|
|
@@ -97,6 +105,7 @@ export function createLocalStorage({
|
|
|
* @returns
|
|
|
*/
|
|
|
function get<T = any>(key: string, opts?: StorageOptions) {
|
|
|
+ if (!canUseStorage()) return null;
|
|
|
const isEncryptKey = shouldEncryptKey(opts, { encryptKey: confEncryptKey });
|
|
|
const isEncryptData = shouldEncryptData(opts, { encryptData: confEncryptData });
|
|
|
|
|
|
@@ -131,6 +140,7 @@ export function createLocalStorage({
|
|
|
* @param opts 当传递了 opts 时,opts 中存在的配置项会覆盖当前实例的全局配置中的配置项。
|
|
|
*/
|
|
|
function remove(key: string, opts?: StorageOptions) {
|
|
|
+ if (!canUseStorage()) return;
|
|
|
const isEncryptKey = shouldEncryptKey(opts, { encryptKey: confEncryptKey });
|
|
|
const finalKey = isEncryptKey ? encryptKey(key) : key;
|
|
|
window.localStorage.removeItem(finalKey);
|
|
|
@@ -140,6 +150,7 @@ export function createLocalStorage({
|
|
|
* 清除 localStorage 中的所有数据。**慎用**
|
|
|
*/
|
|
|
function clear() {
|
|
|
+ if (!canUseStorage()) return;
|
|
|
window.localStorage.clear();
|
|
|
}
|
|
|
|
|
|
@@ -163,6 +174,7 @@ export function createSessionStorage({
|
|
|
* @param opts 当传递了 opts 时,opts 中存在的配置项会覆盖当前实例的全局配置中的配置项。
|
|
|
*/
|
|
|
function set<T = any>(key: string, data: T, opts?: StorageOptions) {
|
|
|
+ if (!canUseStorage()) return;
|
|
|
const expire = opts?.expire ?? confExpire;
|
|
|
const isEncryptKey = shouldEncryptKey(opts, { encryptKey: confEncryptKey });
|
|
|
const isEncryptData = shouldEncryptData(opts, { encryptData: confEncryptData });
|
|
|
@@ -186,6 +198,7 @@ export function createSessionStorage({
|
|
|
* @returns
|
|
|
*/
|
|
|
function get<T = any>(key: string, opts?: StorageOptions) {
|
|
|
+ if (!canUseStorage()) return null;
|
|
|
const isEncryptKey = shouldEncryptKey(opts, { encryptKey: confEncryptKey });
|
|
|
const isEncryptData = shouldEncryptData(opts, { encryptData: confEncryptData });
|
|
|
|
|
|
@@ -220,6 +233,7 @@ export function createSessionStorage({
|
|
|
* @param opts 当传递了 opts 时,opts 中存在的配置项会覆盖当前实例的全局配置中的配置项。
|
|
|
*/
|
|
|
function remove(key: string, opts?: StorageOptions) {
|
|
|
+ if (!canUseStorage()) return;
|
|
|
const isEncryptKey = shouldEncryptKey(opts, { encryptKey: confEncryptKey });
|
|
|
const finalKey = isEncryptKey ? encryptKey(key) : key;
|
|
|
window.sessionStorage.removeItem(finalKey);
|
|
|
@@ -229,6 +243,7 @@ export function createSessionStorage({
|
|
|
* 清除 sessionStorage 中的所有数据。**慎用**
|
|
|
*/
|
|
|
function clear() {
|
|
|
+ if (!canUseStorage()) return;
|
|
|
window.sessionStorage.clear();
|
|
|
}
|
|
|
|