first commit

This commit is contained in:
2026-02-06 20:21:10 +08:00
commit f9d7f980bb
3994 changed files with 1146030 additions and 0 deletions
+136
View File
@@ -0,0 +1,136 @@
Object.defineProperty(exports, '__esModule', { value: true });
//#region src/runtime/utils.ts
function get(obj, path) {
if (obj == null) return void 0;
let value = obj;
for (let i = 0; i < path.length; i++) {
if (value === void 0 || value[path[i]] === void 0) return void 0;
if (value === null || value[path[i]] === null) return null;
value = value[path[i]];
}
return value;
}
function set(obj, value, path) {
if (path.length === 0) return value;
const idx = path[0];
if (path.length > 1) value = set(typeof obj !== "object" || obj === null || !Object.prototype.hasOwnProperty.call(obj, idx) ? Number.isInteger(Number(path[1])) ? [] : {} : obj[idx], value, Array.prototype.slice.call(path, 1));
if (Number.isInteger(Number(idx)) && Array.isArray(obj)) return obj.slice()[idx];
return Object.assign({}, obj, { [idx]: value });
}
function unset(obj, path) {
if (obj == null || path.length === 0) return obj;
if (path.length === 1) {
if (obj == null) return obj;
if (Number.isInteger(path[0]) && Array.isArray(obj)) return Array.prototype.slice.call(obj, 0).splice(path[0], 1);
const result = {};
for (const p in obj) result[p] = obj[p];
delete result[path[0]];
return result;
}
if (obj[path[0]] == null) {
if (Number.isInteger(path[0]) && Array.isArray(obj)) return Array.prototype.concat.call([], obj);
const result = {};
for (const p in obj) result[p] = obj[p];
return result;
}
return set(obj, unset(obj[path[0]], Array.prototype.slice.call(path, 1)), [path[0]]);
}
function deepPick(obj, paths) {
return paths.map((p) => p.split(".")).map((p) => [p, get(obj, p)]).filter((t) => t[1] !== void 0).reduce((acc, cur) => set(acc, cur[1], cur[0]), {});
}
function deepOmit(obj, paths) {
return paths.map((p) => p.split(".")).reduce((acc, cur) => unset(acc, cur), obj);
}
//#endregion
//#region src/runtime/core.ts
function hydrateStore(store, { storage, serializer, key, debug, pick, omit, beforeHydrate, afterHydrate }, context, runHooks = true) {
try {
if (runHooks) beforeHydrate?.(context);
const fromStorage = storage.getItem(key);
if (fromStorage) {
const deserialized = serializer.deserialize(fromStorage);
const picked = pick ? deepPick(deserialized, pick) : deserialized;
const omitted = omit ? deepOmit(picked, omit) : picked;
store.$patch(omitted);
}
if (runHooks) afterHydrate?.(context);
} catch (error) {
if (debug) console.error("[pinia-plugin-persistedstate]", error);
}
}
function persistState(state, { storage, serializer, key, debug, pick, omit }) {
try {
const picked = pick ? deepPick(state, pick) : state;
const omitted = omit ? deepOmit(picked, omit) : picked;
const toStorage = serializer.serialize(omitted);
storage.setItem(key, toStorage);
} catch (error) {
if (debug) console.error("[pinia-plugin-persistedstate]", error);
}
}
function parsePersistKey(key, storeId) {
return typeof key === "function" ? key(storeId) : typeof key === "string" ? key : storeId;
}
function createPersistence(context, optionsParser, auto) {
const { pinia, store, options: { persist = auto } } = context;
if (!persist) return;
// v8 ignore if -- @preserve
if (!(store.$id in pinia.state.value)) {
const originalStore = pinia._s.get(store.$id.replace("__hot:", ""));
if (originalStore) Promise.resolve().then(() => originalStore.$persist());
return;
}
const persistences = (Array.isArray(persist) ? persist : persist === true ? [{}] : [persist]).map(optionsParser);
store.$hydrate = ({ runHooks = true } = {}) => {
persistences.forEach((p) => {
hydrateStore(store, p, context, runHooks);
});
};
store.$persist = () => {
persistences.forEach((p) => {
persistState(store.$state, p);
});
};
persistences.forEach((p) => {
hydrateStore(store, p, context);
store.$subscribe((_mutation, state) => persistState(state, p), { detached: true });
});
}
//#endregion
//#region src/index.ts
/**
* Create a Pinia persistence plugin.
* @see https://codeberg.org/praz/pinia-plugin-persistedstate
*/
function createPersistedState(options = {}) {
return function(context) {
createPersistence(context, (p) => {
const persistKey = parsePersistKey(p.key, context.store.$id);
return {
key: (options.key ? options.key : (x) => x)(persistKey),
debug: p.debug ?? options.debug ?? false,
serializer: p.serializer ?? options.serializer ?? {
serialize: (data) => JSON.stringify(data),
deserialize: (data) => JSON.parse(data)
},
storage: p.storage ?? options.storage ?? window.localStorage,
beforeHydrate: p.beforeHydrate ?? options.beforeHydrate,
afterHydrate: p.afterHydrate ?? options.afterHydrate,
pick: p.pick,
omit: p.omit
};
}, options.auto ?? false);
};
}
/**
* Pinia plugin to persist stores.
* @see https://codeberg.org/praz/pinia-plugin-persistedstate
*/
var src_default = createPersistedState();
//#endregion
exports.createPersistedState = createPersistedState;
exports.default = src_default;
+128
View File
@@ -0,0 +1,128 @@
import { PiniaPluginContext, StateTree } from "pinia";
//#region src/types.d.ts
type IsAny<T> = unknown extends T ? ([keyof T] extends [never] ? false : true) : false;
type ExcludeArrayKeys<T> = T extends ArrayLike<any> ? Exclude<keyof T, keyof any[]> : keyof T;
type PathImpl<T, Key extends keyof T> = Key extends string ? IsAny<T[Key]> extends true ? never : T[Key] extends Record<string, any> ? `${Key}.${PathImpl<T[Key], ExcludeArrayKeys<T[Key]>> & string}` | `${Key}.${ExcludeArrayKeys<T[Key]> & string}` : never : never;
type Path<T> = keyof T extends string ? (PathImpl<T, keyof T> | keyof T) extends infer P ? P extends string | keyof T ? P : keyof T : keyof T : never;
/**
* Synchronous storage based on Web Storage API.
* @see https://developer.mozilla.org/en-US/docs/Web/API/Storage
*/
interface StorageLike {
/**
* Get a key's value if it exists.
*/
getItem: (key: string) => string | null;
/**
* Set a key with a value, or update it if it exists.
*/
setItem: (key: string, value: string) => void;
}
/**
* Serializer implementation to stringify/parse state.
*/
interface Serializer {
/**
* Serialize state into string before storing.
* @default JSON.stringify
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
*/
serialize: (data: StateTree) => string;
/**
* Deserializes string into state before hydrating.
* @default JSON.parse
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
*/
deserialize: (data: string) => StateTree;
}
interface Persistence<State extends StateTree = StateTree> {
key: string;
/**
* Log errors in console.
* @default false
*/
debug: boolean;
/**
* Synchronous storage to persist the state.
*/
storage: StorageLike;
/**
* Serializer to serialize/deserialize state into storage.
*/
serializer: Serializer;
/**
* Hook called before hydrating store.
*/
beforeHydrate?: (context: PiniaPluginContext) => void;
/**
* Hook called after hydrating store.
*/
afterHydrate?: (context: PiniaPluginContext) => void;
/**
* Dot-notation paths to pick from state before persisting.
*/
pick?: Path<State>[] | string[];
/**
* Dot-notation paths to omit from state before persisting.
*/
omit?: Path<State>[] | string[];
}
type PersistenceOptions<State extends StateTree = StateTree> = Partial<Omit<Persistence<State>, 'key'>> & {
/**
* Storage key to use.
* @default $store.id
*/
key?: ((s: string) => string) | string;
};
type Persist<State extends StateTree = StateTree> = boolean | PersistenceOptions<State> | PersistenceOptions<State>[];
declare module 'pinia' {
interface DefineStoreOptionsBase<S extends StateTree, Store> {
/**
* Persist store in storage
* @see https://codeberg.org/praz/pinia-plugin-persistedstate
*/
persist?: Persist<S>;
}
interface PiniaCustomProperties {
/**
* Hydrate store from configured storage
* Warning: this is for advances usecases, make sure you know what you're doing
*/
$hydrate: (opts?: {
runHooks?: boolean;
}) => void;
/**
* Persist store into configured storage
* Warning: this is for advances usecases, make sure you know what you're doing
*/
$persist: () => void;
}
}
//#endregion
//#region src/index.d.ts
/**
* Options passed to `createPersistedState` to apply globally.
*/
type PluginOptions = Pick<PersistenceOptions, 'storage' | 'debug' | 'serializer' | 'afterHydrate' | 'beforeHydrate'> & {
/**
* Global key generator, allow pre/postfixing store keys.
*/
key?: (storeKey: string) => string;
/**
* Automatically persist all stores with global defaults, opt-out individually.
*/
auto?: boolean;
};
/**
* Create a Pinia persistence plugin.
* @see https://codeberg.org/praz/pinia-plugin-persistedstate
*/
declare function createPersistedState(options?: PluginOptions): (context: PiniaPluginContext) => void;
/**
* Pinia plugin to persist stores.
* @see https://codeberg.org/praz/pinia-plugin-persistedstate
*/
declare const _default: (context: PiniaPluginContext) => void;
//#endregion
export { type PersistenceOptions, PluginOptions, type Serializer, type StorageLike, createPersistedState, _default as default };
+128
View File
@@ -0,0 +1,128 @@
import { PiniaPluginContext, StateTree } from "pinia";
//#region src/types.d.ts
type IsAny<T> = unknown extends T ? ([keyof T] extends [never] ? false : true) : false;
type ExcludeArrayKeys<T> = T extends ArrayLike<any> ? Exclude<keyof T, keyof any[]> : keyof T;
type PathImpl<T, Key extends keyof T> = Key extends string ? IsAny<T[Key]> extends true ? never : T[Key] extends Record<string, any> ? `${Key}.${PathImpl<T[Key], ExcludeArrayKeys<T[Key]>> & string}` | `${Key}.${ExcludeArrayKeys<T[Key]> & string}` : never : never;
type Path<T> = keyof T extends string ? (PathImpl<T, keyof T> | keyof T) extends infer P ? P extends string | keyof T ? P : keyof T : keyof T : never;
/**
* Synchronous storage based on Web Storage API.
* @see https://developer.mozilla.org/en-US/docs/Web/API/Storage
*/
interface StorageLike {
/**
* Get a key's value if it exists.
*/
getItem: (key: string) => string | null;
/**
* Set a key with a value, or update it if it exists.
*/
setItem: (key: string, value: string) => void;
}
/**
* Serializer implementation to stringify/parse state.
*/
interface Serializer {
/**
* Serialize state into string before storing.
* @default JSON.stringify
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
*/
serialize: (data: StateTree) => string;
/**
* Deserializes string into state before hydrating.
* @default JSON.parse
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
*/
deserialize: (data: string) => StateTree;
}
interface Persistence<State extends StateTree = StateTree> {
key: string;
/**
* Log errors in console.
* @default false
*/
debug: boolean;
/**
* Synchronous storage to persist the state.
*/
storage: StorageLike;
/**
* Serializer to serialize/deserialize state into storage.
*/
serializer: Serializer;
/**
* Hook called before hydrating store.
*/
beforeHydrate?: (context: PiniaPluginContext) => void;
/**
* Hook called after hydrating store.
*/
afterHydrate?: (context: PiniaPluginContext) => void;
/**
* Dot-notation paths to pick from state before persisting.
*/
pick?: Path<State>[] | string[];
/**
* Dot-notation paths to omit from state before persisting.
*/
omit?: Path<State>[] | string[];
}
type PersistenceOptions<State extends StateTree = StateTree> = Partial<Omit<Persistence<State>, 'key'>> & {
/**
* Storage key to use.
* @default $store.id
*/
key?: ((s: string) => string) | string;
};
type Persist<State extends StateTree = StateTree> = boolean | PersistenceOptions<State> | PersistenceOptions<State>[];
declare module 'pinia' {
interface DefineStoreOptionsBase<S extends StateTree, Store> {
/**
* Persist store in storage
* @see https://codeberg.org/praz/pinia-plugin-persistedstate
*/
persist?: Persist<S>;
}
interface PiniaCustomProperties {
/**
* Hydrate store from configured storage
* Warning: this is for advances usecases, make sure you know what you're doing
*/
$hydrate: (opts?: {
runHooks?: boolean;
}) => void;
/**
* Persist store into configured storage
* Warning: this is for advances usecases, make sure you know what you're doing
*/
$persist: () => void;
}
}
//#endregion
//#region src/index.d.ts
/**
* Options passed to `createPersistedState` to apply globally.
*/
type PluginOptions = Pick<PersistenceOptions, 'storage' | 'debug' | 'serializer' | 'afterHydrate' | 'beforeHydrate'> & {
/**
* Global key generator, allow pre/postfixing store keys.
*/
key?: (storeKey: string) => string;
/**
* Automatically persist all stores with global defaults, opt-out individually.
*/
auto?: boolean;
};
/**
* Create a Pinia persistence plugin.
* @see https://codeberg.org/praz/pinia-plugin-persistedstate
*/
declare function createPersistedState(options?: PluginOptions): (context: PiniaPluginContext) => void;
/**
* Pinia plugin to persist stores.
* @see https://codeberg.org/praz/pinia-plugin-persistedstate
*/
declare const _default: (context: PiniaPluginContext) => void;
//#endregion
export { type PersistenceOptions, PluginOptions, type Serializer, type StorageLike, createPersistedState, _default as default };
+140
View File
@@ -0,0 +1,140 @@
var piniaPluginPersistedstate = (function(exports) {
Object.defineProperty(exports, '__esModule', { value: true });
//#region src/runtime/utils.ts
function get(obj, path) {
if (obj == null) return void 0;
let value = obj;
for (let i = 0; i < path.length; i++) {
if (value === void 0 || value[path[i]] === void 0) return void 0;
if (value === null || value[path[i]] === null) return null;
value = value[path[i]];
}
return value;
}
function set(obj, value, path) {
if (path.length === 0) return value;
const idx = path[0];
if (path.length > 1) value = set(typeof obj !== "object" || obj === null || !Object.prototype.hasOwnProperty.call(obj, idx) ? Number.isInteger(Number(path[1])) ? [] : {} : obj[idx], value, Array.prototype.slice.call(path, 1));
if (Number.isInteger(Number(idx)) && Array.isArray(obj)) return obj.slice()[idx];
return Object.assign({}, obj, { [idx]: value });
}
function unset(obj, path) {
if (obj == null || path.length === 0) return obj;
if (path.length === 1) {
if (obj == null) return obj;
if (Number.isInteger(path[0]) && Array.isArray(obj)) return Array.prototype.slice.call(obj, 0).splice(path[0], 1);
const result = {};
for (const p in obj) result[p] = obj[p];
delete result[path[0]];
return result;
}
if (obj[path[0]] == null) {
if (Number.isInteger(path[0]) && Array.isArray(obj)) return Array.prototype.concat.call([], obj);
const result = {};
for (const p in obj) result[p] = obj[p];
return result;
}
return set(obj, unset(obj[path[0]], Array.prototype.slice.call(path, 1)), [path[0]]);
}
function deepPick(obj, paths) {
return paths.map((p) => p.split(".")).map((p) => [p, get(obj, p)]).filter((t) => t[1] !== void 0).reduce((acc, cur) => set(acc, cur[1], cur[0]), {});
}
function deepOmit(obj, paths) {
return paths.map((p) => p.split(".")).reduce((acc, cur) => unset(acc, cur), obj);
}
//#endregion
//#region src/runtime/core.ts
function hydrateStore(store, { storage, serializer, key, debug, pick, omit, beforeHydrate, afterHydrate }, context, runHooks = true) {
try {
if (runHooks) beforeHydrate?.(context);
const fromStorage = storage.getItem(key);
if (fromStorage) {
const deserialized = serializer.deserialize(fromStorage);
const picked = pick ? deepPick(deserialized, pick) : deserialized;
const omitted = omit ? deepOmit(picked, omit) : picked;
store.$patch(omitted);
}
if (runHooks) afterHydrate?.(context);
} catch (error) {
if (debug) console.error("[pinia-plugin-persistedstate]", error);
}
}
function persistState(state, { storage, serializer, key, debug, pick, omit }) {
try {
const picked = pick ? deepPick(state, pick) : state;
const omitted = omit ? deepOmit(picked, omit) : picked;
const toStorage = serializer.serialize(omitted);
storage.setItem(key, toStorage);
} catch (error) {
if (debug) console.error("[pinia-plugin-persistedstate]", error);
}
}
function parsePersistKey(key, storeId) {
return typeof key === "function" ? key(storeId) : typeof key === "string" ? key : storeId;
}
function createPersistence(context, optionsParser, auto) {
const { pinia, store, options: { persist = auto } } = context;
if (!persist) return;
// v8 ignore if -- @preserve
if (!(store.$id in pinia.state.value)) {
const originalStore = pinia._s.get(store.$id.replace("__hot:", ""));
if (originalStore) Promise.resolve().then(() => originalStore.$persist());
return;
}
const persistences = (Array.isArray(persist) ? persist : persist === true ? [{}] : [persist]).map(optionsParser);
store.$hydrate = ({ runHooks = true } = {}) => {
persistences.forEach((p) => {
hydrateStore(store, p, context, runHooks);
});
};
store.$persist = () => {
persistences.forEach((p) => {
persistState(store.$state, p);
});
};
persistences.forEach((p) => {
hydrateStore(store, p, context);
store.$subscribe((_mutation, state) => persistState(state, p), { detached: true });
});
}
//#endregion
//#region src/index.ts
/**
* Create a Pinia persistence plugin.
* @see https://codeberg.org/praz/pinia-plugin-persistedstate
*/
function createPersistedState(options = {}) {
return function(context) {
createPersistence(context, (p) => {
const persistKey = parsePersistKey(p.key, context.store.$id);
return {
key: (options.key ? options.key : (x) => x)(persistKey),
debug: p.debug ?? options.debug ?? false,
serializer: p.serializer ?? options.serializer ?? {
serialize: (data) => JSON.stringify(data),
deserialize: (data) => JSON.parse(data)
},
storage: p.storage ?? options.storage ?? window.localStorage,
beforeHydrate: p.beforeHydrate ?? options.beforeHydrate,
afterHydrate: p.afterHydrate ?? options.afterHydrate,
pick: p.pick,
omit: p.omit
};
}, options.auto ?? false);
};
}
/**
* Pinia plugin to persist stores.
* @see https://codeberg.org/praz/pinia-plugin-persistedstate
*/
var src_default = createPersistedState();
//#endregion
exports.createPersistedState = createPersistedState;
exports.default = src_default;
return exports;
})({});
+133
View File
@@ -0,0 +1,133 @@
//#region src/runtime/utils.ts
function get(obj, path) {
if (obj == null) return void 0;
let value = obj;
for (let i = 0; i < path.length; i++) {
if (value === void 0 || value[path[i]] === void 0) return void 0;
if (value === null || value[path[i]] === null) return null;
value = value[path[i]];
}
return value;
}
function set(obj, value, path) {
if (path.length === 0) return value;
const idx = path[0];
if (path.length > 1) value = set(typeof obj !== "object" || obj === null || !Object.prototype.hasOwnProperty.call(obj, idx) ? Number.isInteger(Number(path[1])) ? [] : {} : obj[idx], value, Array.prototype.slice.call(path, 1));
if (Number.isInteger(Number(idx)) && Array.isArray(obj)) return obj.slice()[idx];
return Object.assign({}, obj, { [idx]: value });
}
function unset(obj, path) {
if (obj == null || path.length === 0) return obj;
if (path.length === 1) {
if (obj == null) return obj;
if (Number.isInteger(path[0]) && Array.isArray(obj)) return Array.prototype.slice.call(obj, 0).splice(path[0], 1);
const result = {};
for (const p in obj) result[p] = obj[p];
delete result[path[0]];
return result;
}
if (obj[path[0]] == null) {
if (Number.isInteger(path[0]) && Array.isArray(obj)) return Array.prototype.concat.call([], obj);
const result = {};
for (const p in obj) result[p] = obj[p];
return result;
}
return set(obj, unset(obj[path[0]], Array.prototype.slice.call(path, 1)), [path[0]]);
}
function deepPick(obj, paths) {
return paths.map((p) => p.split(".")).map((p) => [p, get(obj, p)]).filter((t) => t[1] !== void 0).reduce((acc, cur) => set(acc, cur[1], cur[0]), {});
}
function deepOmit(obj, paths) {
return paths.map((p) => p.split(".")).reduce((acc, cur) => unset(acc, cur), obj);
}
//#endregion
//#region src/runtime/core.ts
function hydrateStore(store, { storage, serializer, key, debug, pick, omit, beforeHydrate, afterHydrate }, context, runHooks = true) {
try {
if (runHooks) beforeHydrate?.(context);
const fromStorage = storage.getItem(key);
if (fromStorage) {
const deserialized = serializer.deserialize(fromStorage);
const picked = pick ? deepPick(deserialized, pick) : deserialized;
const omitted = omit ? deepOmit(picked, omit) : picked;
store.$patch(omitted);
}
if (runHooks) afterHydrate?.(context);
} catch (error) {
if (debug) console.error("[pinia-plugin-persistedstate]", error);
}
}
function persistState(state, { storage, serializer, key, debug, pick, omit }) {
try {
const picked = pick ? deepPick(state, pick) : state;
const omitted = omit ? deepOmit(picked, omit) : picked;
const toStorage = serializer.serialize(omitted);
storage.setItem(key, toStorage);
} catch (error) {
if (debug) console.error("[pinia-plugin-persistedstate]", error);
}
}
function parsePersistKey(key, storeId) {
return typeof key === "function" ? key(storeId) : typeof key === "string" ? key : storeId;
}
function createPersistence(context, optionsParser, auto) {
const { pinia, store, options: { persist = auto } } = context;
if (!persist) return;
// v8 ignore if -- @preserve
if (!(store.$id in pinia.state.value)) {
const originalStore = pinia._s.get(store.$id.replace("__hot:", ""));
if (originalStore) Promise.resolve().then(() => originalStore.$persist());
return;
}
const persistences = (Array.isArray(persist) ? persist : persist === true ? [{}] : [persist]).map(optionsParser);
store.$hydrate = ({ runHooks = true } = {}) => {
persistences.forEach((p) => {
hydrateStore(store, p, context, runHooks);
});
};
store.$persist = () => {
persistences.forEach((p) => {
persistState(store.$state, p);
});
};
persistences.forEach((p) => {
hydrateStore(store, p, context);
store.$subscribe((_mutation, state) => persistState(state, p), { detached: true });
});
}
//#endregion
//#region src/index.ts
/**
* Create a Pinia persistence plugin.
* @see https://codeberg.org/praz/pinia-plugin-persistedstate
*/
function createPersistedState(options = {}) {
return function(context) {
createPersistence(context, (p) => {
const persistKey = parsePersistKey(p.key, context.store.$id);
return {
key: (options.key ? options.key : (x) => x)(persistKey),
debug: p.debug ?? options.debug ?? false,
serializer: p.serializer ?? options.serializer ?? {
serialize: (data) => JSON.stringify(data),
deserialize: (data) => JSON.parse(data)
},
storage: p.storage ?? options.storage ?? window.localStorage,
beforeHydrate: p.beforeHydrate ?? options.beforeHydrate,
afterHydrate: p.afterHydrate ?? options.afterHydrate,
pick: p.pick,
omit: p.omit
};
}, options.auto ?? false);
};
}
/**
* Pinia plugin to persist stores.
* @see https://codeberg.org/praz/pinia-plugin-persistedstate
*/
var src_default = createPersistedState();
//#endregion
export { createPersistedState, src_default as default };
+142
View File
@@ -0,0 +1,142 @@
(function(global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.piniaPluginPersistedstate = {})));
})(this, function(exports) {
Object.defineProperty(exports, '__esModule', { value: true });
//#region src/runtime/utils.ts
function get(obj, path) {
if (obj == null) return void 0;
let value = obj;
for (let i = 0; i < path.length; i++) {
if (value === void 0 || value[path[i]] === void 0) return void 0;
if (value === null || value[path[i]] === null) return null;
value = value[path[i]];
}
return value;
}
function set(obj, value, path) {
if (path.length === 0) return value;
const idx = path[0];
if (path.length > 1) value = set(typeof obj !== "object" || obj === null || !Object.prototype.hasOwnProperty.call(obj, idx) ? Number.isInteger(Number(path[1])) ? [] : {} : obj[idx], value, Array.prototype.slice.call(path, 1));
if (Number.isInteger(Number(idx)) && Array.isArray(obj)) return obj.slice()[idx];
return Object.assign({}, obj, { [idx]: value });
}
function unset(obj, path) {
if (obj == null || path.length === 0) return obj;
if (path.length === 1) {
if (obj == null) return obj;
if (Number.isInteger(path[0]) && Array.isArray(obj)) return Array.prototype.slice.call(obj, 0).splice(path[0], 1);
const result = {};
for (const p in obj) result[p] = obj[p];
delete result[path[0]];
return result;
}
if (obj[path[0]] == null) {
if (Number.isInteger(path[0]) && Array.isArray(obj)) return Array.prototype.concat.call([], obj);
const result = {};
for (const p in obj) result[p] = obj[p];
return result;
}
return set(obj, unset(obj[path[0]], Array.prototype.slice.call(path, 1)), [path[0]]);
}
function deepPick(obj, paths) {
return paths.map((p) => p.split(".")).map((p) => [p, get(obj, p)]).filter((t) => t[1] !== void 0).reduce((acc, cur) => set(acc, cur[1], cur[0]), {});
}
function deepOmit(obj, paths) {
return paths.map((p) => p.split(".")).reduce((acc, cur) => unset(acc, cur), obj);
}
//#endregion
//#region src/runtime/core.ts
function hydrateStore(store, { storage, serializer, key, debug, pick, omit, beforeHydrate, afterHydrate }, context, runHooks = true) {
try {
if (runHooks) beforeHydrate?.(context);
const fromStorage = storage.getItem(key);
if (fromStorage) {
const deserialized = serializer.deserialize(fromStorage);
const picked = pick ? deepPick(deserialized, pick) : deserialized;
const omitted = omit ? deepOmit(picked, omit) : picked;
store.$patch(omitted);
}
if (runHooks) afterHydrate?.(context);
} catch (error) {
if (debug) console.error("[pinia-plugin-persistedstate]", error);
}
}
function persistState(state, { storage, serializer, key, debug, pick, omit }) {
try {
const picked = pick ? deepPick(state, pick) : state;
const omitted = omit ? deepOmit(picked, omit) : picked;
const toStorage = serializer.serialize(omitted);
storage.setItem(key, toStorage);
} catch (error) {
if (debug) console.error("[pinia-plugin-persistedstate]", error);
}
}
function parsePersistKey(key, storeId) {
return typeof key === "function" ? key(storeId) : typeof key === "string" ? key : storeId;
}
function createPersistence(context, optionsParser, auto) {
const { pinia, store, options: { persist = auto } } = context;
if (!persist) return;
// v8 ignore if -- @preserve
if (!(store.$id in pinia.state.value)) {
const originalStore = pinia._s.get(store.$id.replace("__hot:", ""));
if (originalStore) Promise.resolve().then(() => originalStore.$persist());
return;
}
const persistences = (Array.isArray(persist) ? persist : persist === true ? [{}] : [persist]).map(optionsParser);
store.$hydrate = ({ runHooks = true } = {}) => {
persistences.forEach((p) => {
hydrateStore(store, p, context, runHooks);
});
};
store.$persist = () => {
persistences.forEach((p) => {
persistState(store.$state, p);
});
};
persistences.forEach((p) => {
hydrateStore(store, p, context);
store.$subscribe((_mutation, state) => persistState(state, p), { detached: true });
});
}
//#endregion
//#region src/index.ts
/**
* Create a Pinia persistence plugin.
* @see https://codeberg.org/praz/pinia-plugin-persistedstate
*/
function createPersistedState(options = {}) {
return function(context) {
createPersistence(context, (p) => {
const persistKey = parsePersistKey(p.key, context.store.$id);
return {
key: (options.key ? options.key : (x) => x)(persistKey),
debug: p.debug ?? options.debug ?? false,
serializer: p.serializer ?? options.serializer ?? {
serialize: (data) => JSON.stringify(data),
deserialize: (data) => JSON.parse(data)
},
storage: p.storage ?? options.storage ?? window.localStorage,
beforeHydrate: p.beforeHydrate ?? options.beforeHydrate,
afterHydrate: p.afterHydrate ?? options.afterHydrate,
pick: p.pick,
omit: p.omit
};
}, options.auto ?? false);
};
}
/**
* Pinia plugin to persist stores.
* @see https://codeberg.org/praz/pinia-plugin-persistedstate
*/
var src_default = createPersistedState();
//#endregion
exports.createPersistedState = createPersistedState;
exports.default = src_default;
});
+132
View File
@@ -0,0 +1,132 @@
import * as _nuxt_schema from '@nuxt/schema';
import { CookiesStorageOptions } from '../dist/nuxt/runtime/storages.js';
import { StateTree, PiniaPluginContext } from 'pinia';
type IsAny<T> = unknown extends T ? ([keyof T] extends [never] ? false : true) : false;
type ExcludeArrayKeys<T> = T extends ArrayLike<any> ? Exclude<keyof T, keyof any[]> : keyof T;
type PathImpl<T, Key extends keyof T> = Key extends string ? IsAny<T[Key]> extends true ? never : T[Key] extends Record<string, any> ? `${Key}.${PathImpl<T[Key], ExcludeArrayKeys<T[Key]>> & string}` | `${Key}.${ExcludeArrayKeys<T[Key]> & string}` : never : never;
type Path<T> = keyof T extends string ? (PathImpl<T, keyof T> | keyof T) extends infer P ? P extends string | keyof T ? P : keyof T : keyof T : never;
/**
* Synchronous storage based on Web Storage API.
* @see https://developer.mozilla.org/en-US/docs/Web/API/Storage
*/
interface StorageLike {
/**
* Get a key's value if it exists.
*/
getItem: (key: string) => string | null;
/**
* Set a key with a value, or update it if it exists.
*/
setItem: (key: string, value: string) => void;
}
/**
* Serializer implementation to stringify/parse state.
*/
interface Serializer {
/**
* Serialize state into string before storing.
* @default JSON.stringify
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
*/
serialize: (data: StateTree) => string;
/**
* Deserializes string into state before hydrating.
* @default JSON.parse
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
*/
deserialize: (data: string) => StateTree;
}
interface Persistence<State extends StateTree = StateTree> {
key: string;
/**
* Log errors in console.
* @default false
*/
debug: boolean;
/**
* Synchronous storage to persist the state.
*/
storage: StorageLike;
/**
* Serializer to serialize/deserialize state into storage.
*/
serializer: Serializer;
/**
* Hook called before hydrating store.
*/
beforeHydrate?: (context: PiniaPluginContext) => void;
/**
* Hook called after hydrating store.
*/
afterHydrate?: (context: PiniaPluginContext) => void;
/**
* Dot-notation paths to pick from state before persisting.
*/
pick?: Path<State>[] | string[];
/**
* Dot-notation paths to omit from state before persisting.
*/
omit?: Path<State>[] | string[];
}
type PersistenceOptions<State extends StateTree = StateTree> = Partial<Omit<Persistence<State>, 'key'>> & {
/**
* Storage key to use.
* @default $store.id
*/
key?: ((s: string) => string) | string;
};
type Persist<State extends StateTree = StateTree> = boolean | PersistenceOptions<State> | PersistenceOptions<State>[];
declare module 'pinia' {
interface DefineStoreOptionsBase<S extends StateTree, Store> {
/**
* Persist store in storage
* @see https://codeberg.org/praz/pinia-plugin-persistedstate
*/
persist?: Persist<S>;
}
interface PiniaCustomProperties {
/**
* Hydrate store from configured storage
* Warning: this is for advances usecases, make sure you know what you're doing
*/
$hydrate: (opts?: {
runHooks?: boolean;
}) => void;
/**
* Persist store into configured storage
* Warning: this is for advances usecases, make sure you know what you're doing
*/
$persist: () => void;
}
}
type ModuleOptions = Pick<PersistenceOptions, 'debug'> & {
/**
* Default storage for persistence. Only accepts presets.
*/
storage?: 'cookies' | 'localStorage' | 'sessionStorage';
/**
* Global key template, allow pre/postfixing store keys.
* @example 'my-%id-persistence' will yield 'my-<store-id>-persistence'
*/
key?: `${string}%id${string}`;
/**
* Options used globally by default cookie storage.
* Ignored for other storages.
*/
cookieOptions?: Omit<CookiesStorageOptions, 'encode' | 'decode'>;
/**
* Automatically persist all stores with global defaults, opt-out individually.
*/
auto?: boolean;
};
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
declare module '@nuxt/schema' {
interface PublicRuntimeConfig {
piniaPluginPersistedstate: ModuleOptions;
}
}
export { _default as default };
+12
View File
@@ -0,0 +1,12 @@
{
"name": "pinia-plugin-persistedstate",
"configKey": "piniaPluginPersistedstate",
"compatibility": {
"nuxt": ">=3.0.0"
},
"version": "4.7.1",
"builder": {
"@nuxt/module-builder": "1.0.2",
"unbuild": "3.6.0"
}
}
+31
View File
@@ -0,0 +1,31 @@
import { defineNuxtModule, createResolver, useLogger, hasNuxtModule, addImports, addPlugin } from '@nuxt/kit';
import { defu } from 'defu';
const module = defineNuxtModule({
meta: {
name: "pinia-plugin-persistedstate",
configKey: "piniaPluginPersistedstate",
compatibility: {
nuxt: ">=3.0.0"
}
},
defaults: {},
setup(options, nuxt) {
const resolver = createResolver(import.meta.url);
const logger = useLogger();
if (!hasNuxtModule("pinia", nuxt)) {
logger.warn("The `@pinia/nuxt` module was not found, `pinia-plugin-persistedstate/nuxt` will not work.");
return;
}
nuxt.options.build.transpile.push(resolver.resolve("./runtime"));
nuxt.options.runtimeConfig.public.piniaPluginPersistedstate = defu(nuxt.options.runtimeConfig.public.piniaPluginPersistedstate, options);
addImports({
name: "storages",
from: resolver.resolve("./runtime/storages"),
as: "piniaPluginPersistedstate"
});
addPlugin(resolver.resolve("./runtime/plugin"));
}
});
export { module as default };
+4
View File
@@ -0,0 +1,4 @@
import type { PiniaPluginContext } from 'pinia';
import type { Persistence, PersistenceOptions } from '../types.js';
export declare function parsePersistKey(key: PersistenceOptions['key'], storeId: string): string;
export declare function createPersistence(context: PiniaPluginContext, optionsParser: (p: PersistenceOptions) => Persistence, auto: boolean): void;
+80
View File
@@ -0,0 +1,80 @@
import { deepOmit, deepPick } from "./utils.js";
function hydrateStore(store, {
storage,
serializer,
key,
debug,
pick,
omit,
beforeHydrate,
afterHydrate
}, context, runHooks = true) {
try {
if (runHooks)
beforeHydrate?.(context);
const fromStorage = storage.getItem(key);
if (fromStorage) {
const deserialized = serializer.deserialize(fromStorage);
const picked = pick ? deepPick(deserialized, pick) : deserialized;
const omitted = omit ? deepOmit(picked, omit) : picked;
store.$patch(omitted);
}
if (runHooks)
afterHydrate?.(context);
} catch (error) {
if (debug)
console.error("[pinia-plugin-persistedstate]", error);
}
}
function persistState(state, {
storage,
serializer,
key,
debug,
pick,
omit
}) {
try {
const picked = pick ? deepPick(state, pick) : state;
const omitted = omit ? deepOmit(picked, omit) : picked;
const toStorage = serializer.serialize(omitted);
storage.setItem(key, toStorage);
} catch (error) {
if (debug)
console.error("[pinia-plugin-persistedstate]", error);
}
}
export function parsePersistKey(key, storeId) {
return typeof key === "function" ? key(storeId) : typeof key === "string" ? key : storeId;
}
export function createPersistence(context, optionsParser, auto) {
const { pinia, store, options: { persist = auto } } = context;
if (!persist)
return;
// v8 ignore if -- @preserve
if (!(store.$id in pinia.state.value)) {
const originalStore = pinia._s.get(store.$id.replace("__hot:", ""));
if (originalStore)
void Promise.resolve().then(() => originalStore.$persist());
return;
}
const persistenceOptions = Array.isArray(persist) ? persist : persist === true ? [{}] : [persist];
const persistences = persistenceOptions.map(optionsParser);
store.$hydrate = ({ runHooks = true } = {}) => {
persistences.forEach((p) => {
hydrateStore(store, p, context, runHooks);
});
};
store.$persist = () => {
persistences.forEach((p) => {
persistState(store.$state, p);
});
};
persistences.forEach((p) => {
hydrateStore(store, p, context);
store.$subscribe(
(_mutation, state) => persistState(state, p),
{ detached: true }
);
});
}
@@ -0,0 +1,2 @@
declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
export default _default;
+33
View File
@@ -0,0 +1,33 @@
import { defineNuxtPlugin, useRuntimeConfig } from "#app";
import { createPersistence, parsePersistKey } from "./core.js";
import { storages } from "./storages.js";
function piniaPlugin(context) {
const config = useRuntimeConfig();
const options = config.public.piniaPluginPersistedstate;
createPersistence(
context,
(p) => {
const persistKey = parsePersistKey(p.key, context.store.$id);
return {
key: options.key ? options.key.replace(/%id/g, persistKey) : persistKey,
debug: p.debug ?? options.debug ?? false,
serializer: p.serializer ?? {
serialize: (data) => JSON.stringify(data),
deserialize: (data) => JSON.parse(data)
},
storage: p.storage ?? (options.storage ? options.storage === "cookies" ? storages.cookies(options.cookieOptions) : storages[options.storage]() : storages.cookies()),
beforeHydrate: p.beforeHydrate,
afterHydrate: p.afterHydrate,
pick: p.pick,
omit: p.omit
};
},
options.auto ?? false
);
}
export default defineNuxtPlugin({
name: "pinia-plugin-persistedstate",
setup({ $pinia }) {
$pinia.use(piniaPlugin);
}
});
@@ -0,0 +1,24 @@
import type { CookieOptions } from '#app';
import type { StorageLike } from '../types.js';
export type CookiesStorageOptions = Omit<CookieOptions, 'default' | 'watch' | 'readonly' | 'filter'>;
/**
* Cookie-based storage. Cookie options can be passed as parameter.
* Uses Nuxt's `useCookie` under the hood.
*/
declare function cookies(options?: CookiesStorageOptions): StorageLike;
/**
* LocalStorage-based storage.
* Warning: only works client-side.
*/
declare function localStorage(): StorageLike;
/**
* SessionStorage-based storage.
* Warning: only works client-side.
*/
declare function sessionStorage(): StorageLike;
export declare const storages: {
cookies: typeof cookies;
localStorage: typeof localStorage;
sessionStorage: typeof sessionStorage;
};
export {};
+37
View File
@@ -0,0 +1,37 @@
import { useCookie, useRuntimeConfig } from "#app";
function cookies(options) {
return {
getItem: (key) => useCookie(
key,
{
...options ?? useRuntimeConfig().public.piniaPluginPersistedstate.cookieOptions ?? {},
decode: options?.decode ?? decodeURIComponent,
readonly: true
}
).value,
setItem: (key, value) => useCookie(
key,
{
...options ?? useRuntimeConfig().public.piniaPluginPersistedstate.cookieOptions ?? {},
encode: options?.encode ?? encodeURIComponent
}
).value = value
};
}
function localStorage() {
return {
getItem: (key) => import.meta.client ? window.localStorage.getItem(key) : null,
setItem: (key, value) => import.meta.client ? window.localStorage.setItem(key, value) : null
};
}
function sessionStorage() {
return {
getItem: (key) => import.meta.client ? window.sessionStorage.getItem(key) : null,
setItem: (key, value) => import.meta.client ? window.sessionStorage.setItem(key, value) : null
};
}
export const storages = {
cookies,
localStorage,
sessionStorage
};
@@ -0,0 +1,2 @@
export declare function deepPick(obj: object, paths: Array<string>): {};
export declare function deepOmit(obj: object, paths: Array<string>): object;
+65
View File
@@ -0,0 +1,65 @@
function get(obj, path) {
if (obj == null)
return void 0;
let value = obj;
for (let i = 0; i < path.length; i++) {
if (value === void 0 || value[path[i]] === void 0)
return void 0;
if (value === null || value[path[i]] === null)
return null;
value = value[path[i]];
}
return value;
}
function set(obj, value, path) {
if (path.length === 0)
return value;
const idx = path[0];
if (path.length > 1) {
value = set(
typeof obj !== "object" || obj === null || !Object.prototype.hasOwnProperty.call(obj, idx) ? Number.isInteger(Number(path[1])) ? [] : {} : obj[idx],
value,
Array.prototype.slice.call(path, 1)
);
}
if (Number.isInteger(Number(idx)) && Array.isArray(obj))
return obj.slice()[idx];
return Object.assign({}, obj, { [idx]: value });
}
function unset(obj, path) {
if (obj == null || path.length === 0)
return obj;
if (path.length === 1) {
if (obj == null)
return obj;
if (Number.isInteger(path[0]) && Array.isArray(obj))
return Array.prototype.slice.call(obj, 0).splice(path[0], 1);
const result = {};
for (const p in obj)
result[p] = obj[p];
delete result[path[0]];
return result;
}
if (obj[path[0]] == null) {
if (Number.isInteger(path[0]) && Array.isArray(obj))
return Array.prototype.concat.call([], obj);
const result = {};
for (const p in obj)
result[p] = obj[p];
return result;
}
return set(
obj,
unset(
obj[path[0]],
Array.prototype.slice.call(path, 1)
),
[path[0]]
);
}
export function deepPick(obj, paths) {
return paths.map((p) => p.split(".")).map((p) => [p, get(obj, p)]).filter((t) => t[1] !== void 0).reduce((acc, cur) => set(acc, cur[1], cur[0]), {});
}
export function deepOmit(obj, paths) {
return paths.map((p) => p.split(".")).reduce((acc, cur) => unset(acc, cur), obj);
}
+7
View File
@@ -0,0 +1,7 @@
import type { NuxtModule } from '@nuxt/schema'
import type { default as Module } from './module.mjs'
export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
export { default } from './module.mjs'