vue-context-storage 0.1.22 → 0.1.23
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/README.md +642 -357
- package/dist/index.d.ts +181 -33
- package/dist/index.js +262 -11
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as vue9 from "vue";
|
|
2
2
|
import { InjectionKey, MaybeRefOrGetter, Plugin, PropType, UnwrapNestedRefs, WatchHandle } from "vue";
|
|
3
3
|
import { LocationQuery, LocationQueryValue } from "vue-router";
|
|
4
4
|
|
|
5
5
|
//#region src/components/ContextStorageActivator.vue.d.ts
|
|
6
6
|
declare const _default$1: typeof __VLS_export$3;
|
|
7
|
-
declare const __VLS_export$3:
|
|
7
|
+
declare const __VLS_export$3: vue9.DefineComponent<{}, () => vue9.VNode<vue9.RendererNode, vue9.RendererElement, {
|
|
8
8
|
[key: string]: any;
|
|
9
|
-
}>, {}, {}, {},
|
|
9
|
+
}>, {}, {}, {}, vue9.ComponentOptionsMixin, vue9.ComponentOptionsMixin, {}, string, vue9.PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, vue9.ComponentProvideOptions, true, {}, any>;
|
|
10
10
|
//#endregion
|
|
11
11
|
//#region src/handlers.d.ts
|
|
12
12
|
interface ContextStorageHandlerConstructor {
|
|
@@ -26,55 +26,55 @@ interface ContextStorageHandler {
|
|
|
26
26
|
//#endregion
|
|
27
27
|
//#region src/components/ContextStorageCollection.vue.d.ts
|
|
28
28
|
declare const _default$2: typeof __VLS_export$2;
|
|
29
|
-
declare const __VLS_export$2:
|
|
29
|
+
declare const __VLS_export$2: vue9.DefineComponent<vue9.ExtractPropTypes<{
|
|
30
30
|
handlers: {
|
|
31
31
|
type: PropType<ContextStorageHandlerConstructor[]>;
|
|
32
32
|
default: () => ContextStorageHandlerConstructor[];
|
|
33
33
|
};
|
|
34
|
-
}>, () =>
|
|
34
|
+
}>, () => vue9.VNode<vue9.RendererNode, vue9.RendererElement, {
|
|
35
35
|
[key: string]: any;
|
|
36
|
-
}>[] | undefined, {}, {}, {},
|
|
36
|
+
}>[] | undefined, {}, {}, {}, vue9.ComponentOptionsMixin, vue9.ComponentOptionsMixin, {}, string, vue9.PublicProps, Readonly<vue9.ExtractPropTypes<{
|
|
37
37
|
handlers: {
|
|
38
38
|
type: PropType<ContextStorageHandlerConstructor[]>;
|
|
39
39
|
default: () => ContextStorageHandlerConstructor[];
|
|
40
40
|
};
|
|
41
41
|
}>> & Readonly<{}>, {
|
|
42
42
|
handlers: ContextStorageHandlerConstructor[];
|
|
43
|
-
}, {}, {}, {}, string,
|
|
43
|
+
}, {}, {}, {}, string, vue9.ComponentProvideOptions, true, {}, any>;
|
|
44
44
|
//#endregion
|
|
45
45
|
//#region src/components/ContextStorageProvider.vue.d.ts
|
|
46
46
|
declare const _default$3: typeof __VLS_export$1;
|
|
47
|
-
declare const __VLS_export$1:
|
|
47
|
+
declare const __VLS_export$1: vue9.DefineComponent<vue9.ExtractPropTypes<{
|
|
48
48
|
itemKey: {
|
|
49
49
|
type: StringConstructor;
|
|
50
50
|
required: true;
|
|
51
51
|
};
|
|
52
|
-
}>, () =>
|
|
52
|
+
}>, () => vue9.VNode<vue9.RendererNode, vue9.RendererElement, {
|
|
53
53
|
[key: string]: any;
|
|
54
|
-
}>[] | undefined, {}, {}, {},
|
|
54
|
+
}>[] | undefined, {}, {}, {}, vue9.ComponentOptionsMixin, vue9.ComponentOptionsMixin, {}, string, vue9.PublicProps, Readonly<vue9.ExtractPropTypes<{
|
|
55
55
|
itemKey: {
|
|
56
56
|
type: StringConstructor;
|
|
57
57
|
required: true;
|
|
58
58
|
};
|
|
59
|
-
}>> & Readonly<{}>, {}, {}, {}, {}, string,
|
|
59
|
+
}>> & Readonly<{}>, {}, {}, {}, {}, string, vue9.ComponentProvideOptions, true, {}, any>;
|
|
60
60
|
//#endregion
|
|
61
61
|
//#region src/components/ContextStorage.vue.d.ts
|
|
62
62
|
declare const _default: typeof __VLS_export;
|
|
63
|
-
declare const __VLS_export:
|
|
63
|
+
declare const __VLS_export: vue9.DefineComponent<vue9.ExtractPropTypes<{
|
|
64
64
|
handlers: {
|
|
65
65
|
type: PropType<ContextStorageHandlerConstructor[]>;
|
|
66
66
|
default: () => ContextStorageHandlerConstructor[];
|
|
67
67
|
};
|
|
68
|
-
}>, () =>
|
|
68
|
+
}>, () => vue9.VNode<vue9.RendererNode, vue9.RendererElement, {
|
|
69
69
|
[key: string]: any;
|
|
70
|
-
}>[] | undefined, {}, {}, {},
|
|
70
|
+
}>[] | undefined, {}, {}, {}, vue9.ComponentOptionsMixin, vue9.ComponentOptionsMixin, {}, string, vue9.PublicProps, Readonly<vue9.ExtractPropTypes<{
|
|
71
71
|
handlers: {
|
|
72
72
|
type: PropType<ContextStorageHandlerConstructor[]>;
|
|
73
73
|
default: () => ContextStorageHandlerConstructor[];
|
|
74
74
|
};
|
|
75
75
|
}>> & Readonly<{}>, {
|
|
76
76
|
handlers: ContextStorageHandlerConstructor[];
|
|
77
|
-
}, {}, {}, {}, string,
|
|
77
|
+
}, {}, {}, {}, string, vue9.ComponentProvideOptions, true, {}, any>;
|
|
78
78
|
//#endregion
|
|
79
79
|
//#region src/plugin.d.ts
|
|
80
80
|
declare const VueContextStoragePlugin: Plugin;
|
|
@@ -105,23 +105,6 @@ declare class CollectionManager {
|
|
|
105
105
|
setActive(activeItem: CollectionManagerItem): void;
|
|
106
106
|
}
|
|
107
107
|
//#endregion
|
|
108
|
-
//#region src/composables/useContextStorageActivator.d.ts
|
|
109
|
-
declare function useContextStorageActivator(): {
|
|
110
|
-
activate: () => void;
|
|
111
|
-
};
|
|
112
|
-
//#endregion
|
|
113
|
-
//#region src/composables/useContextStorageCollection.d.ts
|
|
114
|
-
declare function useContextStorageCollection(handlers?: ContextStorageHandlerConstructor[]): CollectionManager;
|
|
115
|
-
//#endregion
|
|
116
|
-
//#region src/composables/useContextStorageProvider.d.ts
|
|
117
|
-
declare function useContextStorageProvider(key: string): void;
|
|
118
|
-
//#endregion
|
|
119
|
-
//#region src/symbols.d.ts
|
|
120
|
-
declare const collection: unique symbol;
|
|
121
|
-
declare const collectionItem: unique symbol;
|
|
122
|
-
declare const handlers: unique symbol;
|
|
123
|
-
declare const contextStorageQueryHandler: unique symbol;
|
|
124
|
-
//#endregion
|
|
125
108
|
//#region src/handlers/query/types.d.ts
|
|
126
109
|
type QueryValue = LocationQueryValue | LocationQueryValue[];
|
|
127
110
|
type DeepTransformValuesToLocationQueryValue<T> = { [K in keyof T]?: T[K] extends object ? T[K] extends Array<any> ? QueryValue : DeepTransformValuesToLocationQueryValue<T[K]> : QueryValue };
|
|
@@ -257,6 +240,149 @@ interface ContextStorageQueryRegisteredItem<T extends Record<string, unknown>> {
|
|
|
257
240
|
watchHandle: WatchHandle;
|
|
258
241
|
}
|
|
259
242
|
//#endregion
|
|
243
|
+
//#region src/handlers/web-storage-base/types.d.ts
|
|
244
|
+
interface WebStorageHandlerBaseOptions {
|
|
245
|
+
/**
|
|
246
|
+
* Default: true for localStorage, false for sessionStorage
|
|
247
|
+
*
|
|
248
|
+
* If enabled - storage events will be listened to for cross-tab synchronization.
|
|
249
|
+
* Only works with localStorage (sessionStorage is per-tab).
|
|
250
|
+
*/
|
|
251
|
+
listenToStorageEvents?: boolean;
|
|
252
|
+
}
|
|
253
|
+
interface RegisterWebStorageHandlerBaseOptions<T> {
|
|
254
|
+
/**
|
|
255
|
+
* Storage key for this data.
|
|
256
|
+
*/
|
|
257
|
+
key?: string;
|
|
258
|
+
/**
|
|
259
|
+
* Optional prefix for nested data within the storage key.
|
|
260
|
+
* When provided, data will be stored under this prefix within the main storage object.
|
|
261
|
+
*/
|
|
262
|
+
prefix?: string;
|
|
263
|
+
/**
|
|
264
|
+
* Transform function to convert deserialized storage data to the expected type.
|
|
265
|
+
*
|
|
266
|
+
* Note: If `schema` is provided, it takes priority over `transform`.
|
|
267
|
+
*/
|
|
268
|
+
transform?: (deserialized: Record<string, unknown>, initialData: T) => UnwrapNestedRefs<T>;
|
|
269
|
+
/**
|
|
270
|
+
* Zod schema for automatic validation and type coercion.
|
|
271
|
+
*
|
|
272
|
+
* When provided, the schema will be used to parse and validate storage data.
|
|
273
|
+
* This option takes priority over the `transform` option.
|
|
274
|
+
*
|
|
275
|
+
* @example
|
|
276
|
+
* ```typescript
|
|
277
|
+
* import { z } from 'zod'
|
|
278
|
+
*
|
|
279
|
+
* const SettingsSchema = z.object({
|
|
280
|
+
* theme: z.enum(['light', 'dark']).default('light'),
|
|
281
|
+
* fontSize: z.number().int().positive().default(14),
|
|
282
|
+
* })
|
|
283
|
+
*
|
|
284
|
+
* useContextStorageLocalStorage(settings, {
|
|
285
|
+
* key: 'app-settings',
|
|
286
|
+
* schema: SettingsSchema,
|
|
287
|
+
* })
|
|
288
|
+
* ```
|
|
289
|
+
*/
|
|
290
|
+
schema?: {
|
|
291
|
+
safeParse: (data: unknown) => {
|
|
292
|
+
success: true;
|
|
293
|
+
data: T;
|
|
294
|
+
} | {
|
|
295
|
+
success: false;
|
|
296
|
+
error: any;
|
|
297
|
+
};
|
|
298
|
+
parse: (data: unknown) => T;
|
|
299
|
+
};
|
|
300
|
+
/**
|
|
301
|
+
* Custom serializer function. Defaults to JSON.stringify.
|
|
302
|
+
*/
|
|
303
|
+
serializer?: (data: T) => string;
|
|
304
|
+
/**
|
|
305
|
+
* Custom deserializer function. Defaults to JSON.parse.
|
|
306
|
+
*/
|
|
307
|
+
deserializer?: (str: string) => unknown;
|
|
308
|
+
}
|
|
309
|
+
interface RegisterWebStorageHandlerOptions<T> extends RegisterBaseOptions, RegisterWebStorageHandlerBaseOptions<T> {}
|
|
310
|
+
interface IContextStorageWebStorageHandler extends ContextStorageHandler {
|
|
311
|
+
register: <T extends Record<string, unknown>>(data: MaybeRefOrGetter<T>, options: RegisterWebStorageHandlerOptions<T>) => () => void;
|
|
312
|
+
}
|
|
313
|
+
interface ContextStorageWebStorageRegisteredItem<T extends Record<string, unknown>> {
|
|
314
|
+
data: MaybeRefOrGetter<T>;
|
|
315
|
+
initialData: T;
|
|
316
|
+
options: RegisterWebStorageHandlerOptions<T>;
|
|
317
|
+
watchHandle: WatchHandle;
|
|
318
|
+
}
|
|
319
|
+
//#endregion
|
|
320
|
+
//#region src/handlers/web-storage-base/index.d.ts
|
|
321
|
+
declare abstract class ContextStorageWebStorageHandler implements IContextStorageWebStorageHandler {
|
|
322
|
+
protected enabled: boolean;
|
|
323
|
+
protected registered: ContextStorageWebStorageRegisteredItem<any>[];
|
|
324
|
+
protected initialState?: Record<string, unknown>;
|
|
325
|
+
protected hasAnyRegistered: boolean;
|
|
326
|
+
protected preventSyncToStorage: boolean;
|
|
327
|
+
protected abstract readonly storage: Storage;
|
|
328
|
+
protected abstract readonly injectionKey: InjectionKey<ContextStorageWebStorageHandler>;
|
|
329
|
+
protected readonly options: Required<WebStorageHandlerBaseOptions>;
|
|
330
|
+
private storageEventHandler;
|
|
331
|
+
constructor(defaultOptions: Required<WebStorageHandlerBaseOptions>);
|
|
332
|
+
protected initializeStorageListener(): void;
|
|
333
|
+
protected handleStorageEvent(event: StorageEvent): void;
|
|
334
|
+
getInjectionKey(): InjectionKey<ContextStorageWebStorageHandler>;
|
|
335
|
+
setInitialState(state: Record<string, unknown> | undefined): void;
|
|
336
|
+
setEnabled(state: boolean, initial: boolean): void;
|
|
337
|
+
syncRegisteredToStorage(): void;
|
|
338
|
+
syncStorageToRegisteredItem<T extends Record<string, unknown>>(item: ContextStorageWebStorageRegisteredItem<T>): void;
|
|
339
|
+
syncStorageToRegistered(): void;
|
|
340
|
+
register<T extends Record<string, unknown>>(data: MaybeRefOrGetter<T>, options: RegisterWebStorageHandlerOptions<T>): () => void;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Options for the web storage composable with required key
|
|
344
|
+
*/
|
|
345
|
+
type UseWebStorageOptions<T> = RegisterWebStorageHandlerBaseOptions<T> & Required<Pick<RegisterWebStorageHandlerBaseOptions<T>, 'key'>>;
|
|
346
|
+
//#endregion
|
|
347
|
+
//#region src/registry.d.ts
|
|
348
|
+
/**
|
|
349
|
+
* Augmentable interface mapping handler names to their options types.
|
|
350
|
+
*
|
|
351
|
+
* Users can extend this via module declaration:
|
|
352
|
+
* ```typescript
|
|
353
|
+
* declare module 'vue-context-storage' {
|
|
354
|
+
* interface ContextStorageHandlerMap {
|
|
355
|
+
* myHandler: MyHandlerOptions
|
|
356
|
+
* }
|
|
357
|
+
* }
|
|
358
|
+
* ```
|
|
359
|
+
*/
|
|
360
|
+
interface ContextStorageHandlerMap {
|
|
361
|
+
query: RegisterQueryHandlerBaseOptions<any>;
|
|
362
|
+
localStorage: UseWebStorageOptions<any>;
|
|
363
|
+
sessionStorage: UseWebStorageOptions<any>;
|
|
364
|
+
}
|
|
365
|
+
declare function defineContextStorageHandler(name: string, injectionKey: InjectionKey<ContextStorageHandler>): void;
|
|
366
|
+
declare function resolveHandlerInjectionKey(type: string): InjectionKey<ContextStorageHandler> | undefined;
|
|
367
|
+
//#endregion
|
|
368
|
+
//#region src/composables/useContextStorage.d.ts
|
|
369
|
+
declare function useContextStorage<K$1 extends keyof ContextStorageHandlerMap, T extends Record<string, unknown>>(type: K$1, data: MaybeRefOrGetter<T>, options: ContextStorageHandlerMap[K$1]): void;
|
|
370
|
+
declare function useContextStorage<T extends Record<string, unknown>>(type: InjectionKey<ContextStorageHandler>, data: MaybeRefOrGetter<T>, options?: Record<string, unknown>): void;
|
|
371
|
+
//#endregion
|
|
372
|
+
//#region src/composables/useContextStorageActivator.d.ts
|
|
373
|
+
declare function useContextStorageActivator(): {
|
|
374
|
+
activate: () => void;
|
|
375
|
+
};
|
|
376
|
+
//#endregion
|
|
377
|
+
//#region src/composables/useContextStorageCollection.d.ts
|
|
378
|
+
declare function useContextStorageCollection(handlers?: ContextStorageHandlerConstructor[]): CollectionManager;
|
|
379
|
+
//#endregion
|
|
380
|
+
//#region src/composables/useContextStorageProvider.d.ts
|
|
381
|
+
declare function useContextStorageProvider(key: string): void;
|
|
382
|
+
//#endregion
|
|
383
|
+
//#region src/symbols.d.ts
|
|
384
|
+
declare const contextStorageQueryHandler: unique symbol;
|
|
385
|
+
//#endregion
|
|
260
386
|
//#region src/handlers/query/index.d.ts
|
|
261
387
|
declare function useContextStorageQueryHandler<T extends Record<string, unknown>>(data: MaybeRefOrGetter<T>, options?: RegisterQueryHandlerBaseOptions<T>): void;
|
|
262
388
|
declare class ContextStorageQueryHandler implements IContextStorageQueryHandler {
|
|
@@ -285,6 +411,26 @@ declare class ContextStorageQueryHandler implements IContextStorageQueryHandler
|
|
|
285
411
|
register<T extends Record<string, unknown>>(data: MaybeRefOrGetter<T>, options: RegisterQueryHandlerOptions<T>): () => void;
|
|
286
412
|
}
|
|
287
413
|
//#endregion
|
|
414
|
+
//#region src/handlers/local-storage/index.d.ts
|
|
415
|
+
declare class ContextStorageLocalStorageHandler extends ContextStorageWebStorageHandler {
|
|
416
|
+
protected readonly storage: Storage;
|
|
417
|
+
protected readonly injectionKey: InjectionKey<ContextStorageLocalStorageHandler>;
|
|
418
|
+
static customHandlerOptions: WebStorageHandlerBaseOptions;
|
|
419
|
+
constructor();
|
|
420
|
+
static configure(options: WebStorageHandlerBaseOptions): ContextStorageHandlerConstructor;
|
|
421
|
+
}
|
|
422
|
+
declare const useContextStorageLocalStorage: <T extends Record<string, unknown>>(data: vue9.MaybeRefOrGetter<T>, options: UseWebStorageOptions<T>) => void;
|
|
423
|
+
//#endregion
|
|
424
|
+
//#region src/handlers/session-storage/index.d.ts
|
|
425
|
+
declare class ContextStorageSessionStorageHandler extends ContextStorageWebStorageHandler {
|
|
426
|
+
protected readonly storage: Storage;
|
|
427
|
+
protected readonly injectionKey: InjectionKey<ContextStorageSessionStorageHandler>;
|
|
428
|
+
static customHandlerOptions: WebStorageHandlerBaseOptions;
|
|
429
|
+
constructor();
|
|
430
|
+
static configure(options: WebStorageHandlerBaseOptions): ContextStorageHandlerConstructor;
|
|
431
|
+
}
|
|
432
|
+
declare const useContextStorageSessionStorage: <T extends Record<string, unknown>>(data: vue9.MaybeRefOrGetter<T>, options: UseWebStorageOptions<T>) => void;
|
|
433
|
+
//#endregion
|
|
288
434
|
//#region src/handlers/query/transform-helpers.d.ts
|
|
289
435
|
declare function asNumber(value: QueryValue | number | undefined): number;
|
|
290
436
|
declare function asNumber(value: QueryValue | number | undefined, options: {
|
|
@@ -460,8 +606,10 @@ declare const contextStorageCollectionInjectKey: InjectionKey<CollectionManager>
|
|
|
460
606
|
declare const contextStorageCollectionItemInjectKey: InjectionKey<CollectionManagerItem>;
|
|
461
607
|
declare const contextStorageHandlersInjectKey: InjectionKey<CollectionManagerItem['handlers']>;
|
|
462
608
|
declare const contextStorageQueryHandlerInjectKey: InjectionKey<InstanceType<typeof ContextStorageQueryHandler>>;
|
|
609
|
+
declare const contextStorageLocalStorageHandlerInjectKey: InjectionKey<InstanceType<typeof ContextStorageLocalStorageHandler>>;
|
|
610
|
+
declare const contextStorageSessionStorageHandlerInjectKey: InjectionKey<InstanceType<typeof ContextStorageSessionStorageHandler>>;
|
|
463
611
|
//#endregion
|
|
464
612
|
//#region src/constants.d.ts
|
|
465
613
|
declare const defaultHandlers: ContextStorageHandlerConstructor[];
|
|
466
614
|
//#endregion
|
|
467
|
-
export { CollectionManager, type CollectionManagerItem, _default as ContextStorage, _default$1 as ContextStorageActivator, _default$2 as ContextStorageCollection, type ContextStorageHandler, type ContextStorageHandlerConstructor, _default$3 as ContextStorageProvider, ContextStorageQueryHandler, type IContextStorageQueryHandler, type QueryValue, type RegisterBaseOptions, VueContextStoragePlugin, asArray, asBoolean, asNumber, asNumberArray, asString,
|
|
615
|
+
export { CollectionManager, type CollectionManagerItem, _default as ContextStorage, _default$1 as ContextStorageActivator, _default$2 as ContextStorageCollection, type ContextStorageHandler, type ContextStorageHandlerConstructor, type ContextStorageHandlerMap, ContextStorageLocalStorageHandler, _default$3 as ContextStorageProvider, ContextStorageQueryHandler, ContextStorageSessionStorageHandler, type IContextStorageWebStorageHandler as IContextStorageLocalStorageHandler, type IContextStorageWebStorageHandler as IContextStorageSessionStorageHandler, type IContextStorageQueryHandler, type WebStorageHandlerBaseOptions as LocalStorageHandlerBaseOptions, type WebStorageHandlerBaseOptions as SessionStorageHandlerBaseOptions, type QueryValue, type RegisterBaseOptions, type RegisterWebStorageHandlerBaseOptions as RegisterLocalStorageHandlerBaseOptions, type RegisterWebStorageHandlerBaseOptions as RegisterSessionStorageHandlerBaseOptions, VueContextStoragePlugin, asArray, asBoolean, asNumber, asNumberArray, asString, contextStorageCollectionInjectKey, contextStorageCollectionItemInjectKey, contextStorageHandlersInjectKey, contextStorageLocalStorageHandlerInjectKey, contextStorageQueryHandlerInjectKey, contextStorageSessionStorageHandlerInjectKey, defaultHandlers, defineContextStorageHandler, deserializeParams as deserializeQueryParams, resolveHandlerInjectionKey, serializeParams as serializeQueryParams, transform, useContextStorage, useContextStorageActivator, useContextStorageCollection, useContextStorageLocalStorage, useContextStorageProvider, useContextStorageQueryHandler, useContextStorageSessionStorage };
|
package/dist/index.js
CHANGED
|
@@ -59,6 +59,200 @@ var CollectionManager = class {
|
|
|
59
59
|
}
|
|
60
60
|
};
|
|
61
61
|
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/symbols.ts
|
|
64
|
+
const collection = Symbol("context-storage-collection");
|
|
65
|
+
const collectionItem = Symbol("context-storage-collection-item");
|
|
66
|
+
const handlers = Symbol("context-storage-handlers");
|
|
67
|
+
const contextStorageQueryHandler = Symbol("context-storage-query-handler");
|
|
68
|
+
const contextStorageLocalStorageHandler = Symbol("context-storage-local-storage-handler");
|
|
69
|
+
const contextStorageSessionStorageHandler = Symbol("context-storage-session-storage-handler");
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region src/handlers/web-storage-base/index.ts
|
|
73
|
+
var ContextStorageWebStorageHandler = class {
|
|
74
|
+
enabled = false;
|
|
75
|
+
registered = [];
|
|
76
|
+
initialState;
|
|
77
|
+
hasAnyRegistered = false;
|
|
78
|
+
preventSyncToStorage = false;
|
|
79
|
+
options;
|
|
80
|
+
storageEventHandler = null;
|
|
81
|
+
constructor(defaultOptions) {
|
|
82
|
+
this.options = { ...defaultOptions };
|
|
83
|
+
}
|
|
84
|
+
initializeStorageListener() {
|
|
85
|
+
if (this.options.listenToStorageEvents && typeof window !== "undefined") {
|
|
86
|
+
this.storageEventHandler = (event) => {
|
|
87
|
+
this.handleStorageEvent(event);
|
|
88
|
+
};
|
|
89
|
+
window.addEventListener("storage", this.storageEventHandler);
|
|
90
|
+
onBeforeUnmount(() => {
|
|
91
|
+
if (this.storageEventHandler) {
|
|
92
|
+
window.removeEventListener("storage", this.storageEventHandler);
|
|
93
|
+
this.storageEventHandler = null;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
handleStorageEvent(event) {
|
|
99
|
+
if (!this.enabled) return;
|
|
100
|
+
this.registered.forEach((item) => {
|
|
101
|
+
if (event.key === item.options.key) this.syncStorageToRegisteredItem(item);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
getInjectionKey() {
|
|
105
|
+
return this.injectionKey;
|
|
106
|
+
}
|
|
107
|
+
setInitialState(state) {
|
|
108
|
+
this.initialState = state;
|
|
109
|
+
}
|
|
110
|
+
setEnabled(state, initial) {
|
|
111
|
+
const prevState = this.enabled;
|
|
112
|
+
this.enabled = state;
|
|
113
|
+
if (this.hasAnyRegistered) {
|
|
114
|
+
if (initial) this.syncStorageToRegistered();
|
|
115
|
+
if (state && !prevState || !initial) this.syncRegisteredToStorage();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
syncRegisteredToStorage() {
|
|
119
|
+
if (!this.enabled) return;
|
|
120
|
+
if (this.preventSyncToStorage) return;
|
|
121
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
122
|
+
this.registered.forEach((item) => {
|
|
123
|
+
const key = item.options.key;
|
|
124
|
+
if (!byKey.has(key)) byKey.set(key, []);
|
|
125
|
+
byKey.get(key).push(item);
|
|
126
|
+
});
|
|
127
|
+
byKey.forEach((items, key) => {
|
|
128
|
+
let storageData = {};
|
|
129
|
+
try {
|
|
130
|
+
const existing = this.storage.getItem(key);
|
|
131
|
+
if (existing) storageData = JSON.parse(existing);
|
|
132
|
+
} catch {}
|
|
133
|
+
items.forEach((item) => {
|
|
134
|
+
const { prefix, serializer } = item.options;
|
|
135
|
+
const data = toValue(item.data);
|
|
136
|
+
if (prefix) storageData[prefix] = data;
|
|
137
|
+
else storageData = {
|
|
138
|
+
...storageData,
|
|
139
|
+
...data
|
|
140
|
+
};
|
|
141
|
+
if (serializer && !prefix) {
|
|
142
|
+
try {
|
|
143
|
+
this.storage.setItem(key, serializer(data));
|
|
144
|
+
} catch (e) {
|
|
145
|
+
console.error("[vue-context-storage] Error writing to storage", e);
|
|
146
|
+
}
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
try {
|
|
151
|
+
this.storage.setItem(key, JSON.stringify(storageData));
|
|
152
|
+
} catch (e) {
|
|
153
|
+
console.error("[vue-context-storage] Error writing to storage", e);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
syncStorageToRegisteredItem(item) {
|
|
158
|
+
const { key, prefix, deserializer } = item.options;
|
|
159
|
+
let stored = null;
|
|
160
|
+
try {
|
|
161
|
+
stored = this.storage.getItem(key);
|
|
162
|
+
} catch {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (stored === null) return;
|
|
166
|
+
let deserialized;
|
|
167
|
+
try {
|
|
168
|
+
if (deserializer) deserialized = deserializer(stored);
|
|
169
|
+
else deserialized = JSON.parse(stored);
|
|
170
|
+
} catch {
|
|
171
|
+
console.warn("[vue-context-storage] Failed to parse storage data for key:", key);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (typeof prefix === "string" && prefix.length > 0) deserialized = deserialized[prefix] || {};
|
|
175
|
+
if (deserialized === void 0 || deserialized === null) return;
|
|
176
|
+
const itemData = toValue(item.data);
|
|
177
|
+
if (item.options?.schema) {
|
|
178
|
+
const result = item.options.schema.safeParse(deserialized);
|
|
179
|
+
if (result.success) deserialized = result.data;
|
|
180
|
+
else {
|
|
181
|
+
console.warn("[vue-context-storage] schema parse failed", result.error);
|
|
182
|
+
merge(itemData, item.initialData);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
if (item.options?.transform) console.warn("[vue-context-storage] transform is not supported with schema");
|
|
186
|
+
} else if (item.options?.transform) deserialized = item.options.transform(deserialized, item.initialData);
|
|
187
|
+
else deserialized = pick(deserialized, Object.keys(item.initialData));
|
|
188
|
+
if (isEqual(itemData, deserialized)) return;
|
|
189
|
+
merge(itemData, deserialized);
|
|
190
|
+
}
|
|
191
|
+
syncStorageToRegistered() {
|
|
192
|
+
this.registered.forEach((item) => this.syncStorageToRegisteredItem(item));
|
|
193
|
+
}
|
|
194
|
+
register(data, options) {
|
|
195
|
+
if (!options.key) throw new Error("[vue-context-storage] Storage handler requires a key option");
|
|
196
|
+
this.hasAnyRegistered = true;
|
|
197
|
+
const watchHandle = watch(data, () => this.syncRegisteredToStorage(), { deep: true });
|
|
198
|
+
const item = {
|
|
199
|
+
data,
|
|
200
|
+
initialData: cloneDeep(toValue(data)),
|
|
201
|
+
options,
|
|
202
|
+
watchHandle
|
|
203
|
+
};
|
|
204
|
+
this.registered.push(item);
|
|
205
|
+
const syncCallback = () => {
|
|
206
|
+
this.syncStorageToRegisteredItem(item);
|
|
207
|
+
this.syncRegisteredToStorage();
|
|
208
|
+
};
|
|
209
|
+
queueMicrotask(syncCallback);
|
|
210
|
+
return () => {
|
|
211
|
+
watchHandle();
|
|
212
|
+
this.registered.splice(this.registered.indexOf(item), 1);
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
function createWebStorageComposable(injectionKey, handlerName) {
|
|
217
|
+
return function useContextStorageWebStorage(data, options) {
|
|
218
|
+
const handler = inject(injectionKey);
|
|
219
|
+
if (!handler) throw new Error(`[vue-context-storage] ${handlerName} is not provided`);
|
|
220
|
+
const uid = getCurrentInstance()?.uid || 0;
|
|
221
|
+
const causer = (/* @__PURE__ */ new Error()).stack?.split("\n")[2]?.trimStart() || "unknown";
|
|
222
|
+
const stop = handler.register(data, {
|
|
223
|
+
causer,
|
|
224
|
+
uid,
|
|
225
|
+
...options
|
|
226
|
+
});
|
|
227
|
+
onBeforeUnmount(() => {
|
|
228
|
+
stop();
|
|
229
|
+
});
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
//#endregion
|
|
234
|
+
//#region src/handlers/local-storage/index.ts
|
|
235
|
+
var ContextStorageLocalStorageHandler = class ContextStorageLocalStorageHandler extends ContextStorageWebStorageHandler {
|
|
236
|
+
storage;
|
|
237
|
+
injectionKey;
|
|
238
|
+
static customHandlerOptions = {};
|
|
239
|
+
constructor() {
|
|
240
|
+
const defaultOptions = {
|
|
241
|
+
listenToStorageEvents: true,
|
|
242
|
+
...ContextStorageLocalStorageHandler.customHandlerOptions
|
|
243
|
+
};
|
|
244
|
+
super(defaultOptions);
|
|
245
|
+
this.storage = localStorage;
|
|
246
|
+
this.injectionKey = contextStorageLocalStorageHandler;
|
|
247
|
+
this.initializeStorageListener();
|
|
248
|
+
}
|
|
249
|
+
static configure(options) {
|
|
250
|
+
ContextStorageLocalStorageHandler.customHandlerOptions = options;
|
|
251
|
+
return ContextStorageLocalStorageHandler;
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
const useContextStorageLocalStorage = createWebStorageComposable(contextStorageLocalStorageHandler, "ContextStorageLocalStorageHandler");
|
|
255
|
+
|
|
62
256
|
//#endregion
|
|
63
257
|
//#region src/handlers/query/helpers.ts
|
|
64
258
|
/**
|
|
@@ -133,13 +327,6 @@ function deserializeParams(params) {
|
|
|
133
327
|
}, {});
|
|
134
328
|
}
|
|
135
329
|
|
|
136
|
-
//#endregion
|
|
137
|
-
//#region src/symbols.ts
|
|
138
|
-
const collection = Symbol("context-storage-collection");
|
|
139
|
-
const collectionItem = Symbol("context-storage-collection-item");
|
|
140
|
-
const handlers = Symbol("context-storage-handlers");
|
|
141
|
-
const contextStorageQueryHandler = Symbol("context-storage-query-handler");
|
|
142
|
-
|
|
143
330
|
//#endregion
|
|
144
331
|
//#region src/handlers/query/index.ts
|
|
145
332
|
function useContextStorageQueryHandler(data, options) {
|
|
@@ -352,12 +539,37 @@ var ContextStorageQueryHandler = class ContextStorageQueryHandler {
|
|
|
352
539
|
}
|
|
353
540
|
};
|
|
354
541
|
|
|
542
|
+
//#endregion
|
|
543
|
+
//#region src/handlers/session-storage/index.ts
|
|
544
|
+
var ContextStorageSessionStorageHandler = class ContextStorageSessionStorageHandler extends ContextStorageWebStorageHandler {
|
|
545
|
+
storage;
|
|
546
|
+
injectionKey;
|
|
547
|
+
static customHandlerOptions = {};
|
|
548
|
+
constructor() {
|
|
549
|
+
const defaultOptions = {
|
|
550
|
+
listenToStorageEvents: false,
|
|
551
|
+
...ContextStorageSessionStorageHandler.customHandlerOptions
|
|
552
|
+
};
|
|
553
|
+
super(defaultOptions);
|
|
554
|
+
this.storage = sessionStorage;
|
|
555
|
+
this.injectionKey = contextStorageSessionStorageHandler;
|
|
556
|
+
this.initializeStorageListener();
|
|
557
|
+
}
|
|
558
|
+
static configure(options) {
|
|
559
|
+
ContextStorageSessionStorageHandler.customHandlerOptions = options;
|
|
560
|
+
return ContextStorageSessionStorageHandler;
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
const useContextStorageSessionStorage = createWebStorageComposable(contextStorageSessionStorageHandler, "ContextStorageSessionStorageHandler");
|
|
564
|
+
|
|
355
565
|
//#endregion
|
|
356
566
|
//#region src/injectionSymbols.ts
|
|
357
567
|
const contextStorageCollectionInjectKey = collection;
|
|
358
568
|
const contextStorageCollectionItemInjectKey = collectionItem;
|
|
359
569
|
const contextStorageHandlersInjectKey = handlers;
|
|
360
570
|
const contextStorageQueryHandlerInjectKey = contextStorageQueryHandler;
|
|
571
|
+
const contextStorageLocalStorageHandlerInjectKey = contextStorageLocalStorageHandler;
|
|
572
|
+
const contextStorageSessionStorageHandlerInjectKey = contextStorageSessionStorageHandler;
|
|
361
573
|
|
|
362
574
|
//#endregion
|
|
363
575
|
//#region src/composables/useContextStorageActivator.ts
|
|
@@ -380,7 +592,11 @@ var ContextStorageActivator_default = ContextStorageActivator_vue_vue_type_scrip
|
|
|
380
592
|
|
|
381
593
|
//#endregion
|
|
382
594
|
//#region src/constants.ts
|
|
383
|
-
const defaultHandlers = [
|
|
595
|
+
const defaultHandlers = [
|
|
596
|
+
ContextStorageQueryHandler,
|
|
597
|
+
ContextStorageLocalStorageHandler,
|
|
598
|
+
ContextStorageSessionStorageHandler
|
|
599
|
+
];
|
|
384
600
|
|
|
385
601
|
//#endregion
|
|
386
602
|
//#region src/composables/useContextStorageCollection.ts
|
|
@@ -468,8 +684,7 @@ var ContextStorage_vue_vue_type_script_lang_default = defineComponent({
|
|
|
468
684
|
const initItem = () => {
|
|
469
685
|
item.handlers.forEach((handler) => {
|
|
470
686
|
const state = initialNavigatorState.get(handler.constructor);
|
|
471
|
-
if (
|
|
472
|
-
handler.setInitialState?.(state);
|
|
687
|
+
if (state) handler.setInitialState?.(state);
|
|
473
688
|
handler.setEnabled?.(true, true);
|
|
474
689
|
});
|
|
475
690
|
};
|
|
@@ -496,6 +711,42 @@ const VueContextStoragePlugin = { install(app) {
|
|
|
496
711
|
app.component("ContextStorage", ContextStorage_default);
|
|
497
712
|
} };
|
|
498
713
|
|
|
714
|
+
//#endregion
|
|
715
|
+
//#region src/registry.ts
|
|
716
|
+
const handlerRegistry = /* @__PURE__ */ new Map();
|
|
717
|
+
function defineContextStorageHandler(name, injectionKey) {
|
|
718
|
+
handlerRegistry.set(name, injectionKey);
|
|
719
|
+
}
|
|
720
|
+
function resolveHandlerInjectionKey(type) {
|
|
721
|
+
return handlerRegistry.get(type);
|
|
722
|
+
}
|
|
723
|
+
defineContextStorageHandler("query", contextStorageQueryHandlerInjectKey);
|
|
724
|
+
defineContextStorageHandler("localStorage", contextStorageLocalStorageHandlerInjectKey);
|
|
725
|
+
defineContextStorageHandler("sessionStorage", contextStorageSessionStorageHandlerInjectKey);
|
|
726
|
+
|
|
727
|
+
//#endregion
|
|
728
|
+
//#region src/composables/useContextStorage.ts
|
|
729
|
+
function useContextStorage(type, data, options) {
|
|
730
|
+
let injectionKey;
|
|
731
|
+
if (typeof type === "string") {
|
|
732
|
+
const resolved = resolveHandlerInjectionKey(type);
|
|
733
|
+
if (!resolved) throw new Error(`[vue-context-storage] Unknown handler type: "${type}". Use defineContextStorageHandler() to register it.`);
|
|
734
|
+
injectionKey = resolved;
|
|
735
|
+
} else injectionKey = type;
|
|
736
|
+
const handler = inject(injectionKey);
|
|
737
|
+
if (!handler) throw new Error(`[vue-context-storage] Handler not provided for type: "${String(type)}"`);
|
|
738
|
+
const uid = getCurrentInstance()?.uid || 0;
|
|
739
|
+
const causer = (/* @__PURE__ */ new Error()).stack?.split("\n")[2]?.trimStart() || "unknown";
|
|
740
|
+
const stop = handler.register(data, {
|
|
741
|
+
causer,
|
|
742
|
+
uid,
|
|
743
|
+
...options
|
|
744
|
+
});
|
|
745
|
+
onBeforeUnmount(() => {
|
|
746
|
+
stop();
|
|
747
|
+
});
|
|
748
|
+
}
|
|
749
|
+
|
|
499
750
|
//#endregion
|
|
500
751
|
//#region src/handlers/query/transform-helpers.ts
|
|
501
752
|
function asNumber(value, options) {
|
|
@@ -559,4 +810,4 @@ const transform = {
|
|
|
559
810
|
};
|
|
560
811
|
|
|
561
812
|
//#endregion
|
|
562
|
-
export { CollectionManager, ContextStorage_default as ContextStorage, ContextStorageActivator_default as ContextStorageActivator, ContextStorageCollection_default as ContextStorageCollection, ContextStorageProvider_default as ContextStorageProvider, ContextStorageQueryHandler, VueContextStoragePlugin, asArray, asBoolean, asNumber, asNumberArray, asString,
|
|
813
|
+
export { CollectionManager, ContextStorage_default as ContextStorage, ContextStorageActivator_default as ContextStorageActivator, ContextStorageCollection_default as ContextStorageCollection, ContextStorageLocalStorageHandler, ContextStorageProvider_default as ContextStorageProvider, ContextStorageQueryHandler, ContextStorageSessionStorageHandler, VueContextStoragePlugin, asArray, asBoolean, asNumber, asNumberArray, asString, contextStorageCollectionInjectKey, contextStorageCollectionItemInjectKey, contextStorageHandlersInjectKey, contextStorageLocalStorageHandlerInjectKey, contextStorageQueryHandlerInjectKey, contextStorageSessionStorageHandlerInjectKey, defaultHandlers, defineContextStorageHandler, deserializeParams as deserializeQueryParams, resolveHandlerInjectionKey, serializeParams as serializeQueryParams, transform, useContextStorage, useContextStorageActivator, useContextStorageCollection, useContextStorageLocalStorage, useContextStorageProvider, useContextStorageQueryHandler, useContextStorageSessionStorage };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vue-context-storage",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.23",
|
|
5
5
|
"description": "Vue 3 context storage system with URL query synchronization support",
|
|
6
6
|
"author": "",
|
|
7
7
|
"license": "MIT",
|
|
@@ -68,6 +68,7 @@
|
|
|
68
68
|
"eslint-config-prettier": "^10.1.8",
|
|
69
69
|
"eslint-plugin-vue": "^10.6.2",
|
|
70
70
|
"happy-dom": "^20.1.0",
|
|
71
|
+
"highlight.js": "^11.11.1",
|
|
71
72
|
"jsdom": "^27.4.0",
|
|
72
73
|
"naive-ui": "^2.43.2",
|
|
73
74
|
"playwright": "^1.57.0",
|