### Install Vue Context Storage Source: https://context7.com/lviobio/vue-context-storage/llms.txt Command to install the library via npm. ```bash npm install vue-context-storage ``` -------------------------------- ### Example Test Structure in TypeScript Source: https://github.com/lviobio/vue-context-storage/blob/main/tests/README.md An example demonstrating the structure for writing new tests using Vitest. It follows the AAA pattern (Arrange, Act, Assert) and includes nested describe blocks for organization and clear test case naming. ```typescript describe('myFunction', () => { describe('basic usage', () => { it('should return expected value for valid input', () => { const result = myFunction('valid') expect(result).toBe('expected') }) }) describe('edge cases', () => { it('should handle null input', () => { const result = myFunction(null) expect(result).toBe(undefined) }) }) }) ``` -------------------------------- ### Configure Custom Query, Local, and Session Handlers (TypeScript) Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Provides an example of creating a custom set of handlers for `ContextStorage`, including a query handler with specific options ('push' mode, `preserveUnusedKeys: false`), and default local and session storage handlers. This offers full control over storage behavior. ```typescript import { createQueryHandler, createLocalStorageHandler, createSessionStorageHandler, } from 'vue-context-storage' const customHandlers = [ createQueryHandler({ mode: 'push', // 'replace' (default) or 'push' for history preserveUnusedKeys: false, // Default is true — set to false for exclusive query ownership preserveEmptyState: false, }), createLocalStorageHandler(), createSessionStorageHandler(), ] // Pass to ContextStorage or ContextStorageCollection component: // ``` -------------------------------- ### Sync Reactive State with URL Query Parameters Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Provides a specific example of using useContextStorage to synchronize a reactive 'filters' object with URL query parameters. It highlights how the 'key' option in the configuration affects the URL structure. ```vue ``` -------------------------------- ### Using Transform Helpers for URL Query Values Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Illustrates the advanced usage of transform helpers within useContextStorage to convert URL query string values into their correct data types. This example shows converting 'page' and 'perPage' to numbers and 'search' to a string. ```typescript import { ref } from 'vue' import { useContextStorage, transform } from 'vue-context-storage' interface TableState { page: number search: string perPage: number } const state = ref({ page: 1, search: '', perPage: 25, }) useContextStorage('query', state, { key: 'table', transform: (deserialized, initial) => ({ page: transform.asNumber(deserialized.page, { fallback: 1 }), search: transform.asString(deserialized.search, { fallback: '' }), perPage: transform.asNumber(deserialized.perPage, { fallback: 25 }), }), }) ``` -------------------------------- ### Transform Helper Example Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Transform helpers provide utilities for converting and validating data, particularly useful when dealing with data from storage. The `asNumber` helper, for instance, converts a value to a number and supports options for fallback values, nullability, and missability (undefined). ```typescript import { transform } from 'vue-context-storage'; const numericValue = transform.asNumber(someValue, { fallback: 0, nullable: false, missable: false, }); // Example: // If someValue is '123', numericValue will be 123. // If someValue is null and nullable is false, it might throw an error or use fallback depending on context. // If someValue is undefined and missable is false, it might throw an error or use fallback. ``` -------------------------------- ### Transform and validate stored data Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Examples of using custom transformation functions to cast storage values and integrating Zod schemas for runtime validation and type safety. ```typescript import { useContextStorage, transform } from 'vue-context-storage' import { z } from 'zod' // Using Transform const settings = reactive({ theme: 'light', fontSize: 14 }) useContextStorage('localStorage', settings, { key: 'app-settings', transform: (deserialized, initial) => ({ theme: transform.asString(deserialized.theme, { fallback: 'light' }), fontSize: transform.asNumber(deserialized.fontSize, { fallback: 14 }), }), }) // Using Zod Schema const SettingsSchema = z.object({ theme: z.enum(['light', 'dark']).default('light'), fontSize: z.number().int().positive().default(14), sidebarOpen: z.boolean().default(true), }) const settingsZod = reactive(SettingsSchema.parse({})) useContextStorage('localStorage', settingsZod, { key: 'app-settings', schema: SettingsSchema, }) ``` -------------------------------- ### Override Query Handler with Push Mode (Vue Component) Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Demonstrates how to override a default query handler in a Vue component using the `additional-handlers` prop. This example specifically configures the query handler to use 'push' mode for history management. It requires 'vue-router'. ```vue ``` -------------------------------- ### Project Build and Development Commands Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Common CLI commands for developing, building, and testing the vue-context-storage library. ```bash npm run play npm run build npm run check npm run lint npm run format ``` -------------------------------- ### Run All Tests with npm Source: https://github.com/lviobio/vue-context-storage/blob/main/tests/README.md Commands to execute the test suite using npm. Supports running all tests, in watch mode, specific files, or with coverage reports. ```bash npm test npm test -- --watch npm test -- tests/transform-helpers.test.ts npm test -- --coverage ``` -------------------------------- ### Configure Storage Handler Factories Source: https://context7.com/lviobio/vue-context-storage/llms.txt Demonstrates how to create custom handlers for URL query parameters, localStorage, and sessionStorage with specific configuration options like synchronization modes and event listening. ```typescript import { createQueryHandler, createLocalStorageHandler, createSessionStorageHandler } from 'vue-context-storage' const customQueryHandler = createQueryHandler({ mode: 'push', preserveUnusedKeys: true, preserveEmptyState: false, onlyChanges: true, emptyPlaceholder: '_', }) const customLocalStorageHandler = createLocalStorageHandler({ listenToStorageEvents: true, }) const customSessionStorageHandler = createSessionStorageHandler({ listenToStorageEvents: false, }) ``` -------------------------------- ### Configure LocalStorage Handler for Cross-Tab Sync (TypeScript) Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Demonstrates how to configure the `createLocalStorageHandler` with the `listenToStorageEvents` option. Setting this to `true` (which is the default) enables automatic synchronization of local storage data across different browser tabs. This is crucial for a consistent user experience. ```typescript import { createLocalStorageHandler } from 'vue-context-storage' const customLocalStorage = createLocalStorageHandler({ listenToStorageEvents: true, // Cross-tab sync (default: true) }) ``` -------------------------------- ### Configure ContextStoragePrefix with Per-Handler Prefixes Source: https://context7.com/lviobio/vue-context-storage/llms.txt Demonstrates how to apply different storage prefixes for specific handler types like query, localStorage, and sessionStorage using an object configuration within the ContextStoragePrefix component. ```vue ``` -------------------------------- ### Injecting Query Handler Key Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Demonstrates how to pass an injection key directly to useContextStorage instead of a string identifier for the query handler. This is an alternative way to specify which handler to use, potentially useful in complex dependency injection scenarios. ```typescript import { useContextStorage } from 'vue-context-storage' import { contextStorageQueryHandlerInjectKey } from 'vue-context-storage' useContextStorage(contextStorageQueryHandlerInjectKey, filters, { key: 'filters', }) ``` -------------------------------- ### Initialize Reactive Objects with createSchemaObject Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Creates a reactive object from a Zod schema. Supports options for default values and attaching schema metadata to the resulting object. ```typescript import { z } from 'zod' import { createSchemaObject, SCHEMA_SYMBOL } from 'vue-context-storage/zod' const FiltersSchema = z.object({ search: z.string().default(''), page: z.coerce.number().default(1), active: z.boolean().default(false), score: z.number().nullable(), }) const filters = reactive(createSchemaObject(FiltersSchema)) const data = createSchemaObject(FiltersSchema, { withSchema: true }) ``` -------------------------------- ### Using Zod Schemas for Validation and Coercion Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Demonstrates the use of Zod schemas with useContextStorage for automatic validation and type inference of URL query parameters. This approach simplifies type coercion and provides runtime validation with detailed error reporting. ```typescript import { z } from 'zod' import { useContextStorage } from 'vue-context-storage' // Define schema with automatic coercion const FiltersSchema = z.object({ search: z.string().default(''), page: z.coerce.number().int().positive().default(1), status: z.enum(['active', 'inactive']).default('active'), }) const filters = ref(FiltersSchema.parse({})) // Use schema for automatic validation useContextStorage('query', filters, { key: 'filters', schema: FiltersSchema, }) ``` -------------------------------- ### Initialize ContextStorage Component Source: https://context7.com/lviobio/vue-context-storage/llms.txt Wraps the application router view with the ContextStorage component to enable storage synchronization across the component tree. ```vue ``` -------------------------------- ### Group storage keys with bracket notation Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Shows how to organize multiple reactive objects under a common root key using bracket notation in the key property. ```typescript const filters = reactive({ search: '', status: 'active' }) useContextStorage('sessionStorage', filters, { key: 'app-state[filters]', // Storage key: 'app-state[filters]' }) const pagination = reactive({ page: 1, perPage: 25 }) useContextStorage('sessionStorage', pagination, { key: 'app-state[pagination]', // Storage key: 'app-state[pagination]' }) ``` -------------------------------- ### Synchronize State with Query, Local, and Session Storage Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Demonstrates using useContextStorage to synchronize a reactive 'filters' object with URL query parameters, localStorage, and sessionStorage. This provides a unified entry point for managing state across different persistence layers. ```vue ``` -------------------------------- ### Manage Multiple Storage Keys with Bracket Notation Source: https://context7.com/lviobio/vue-context-storage/llms.txt Organizes multiple data objects under a common root key in storage using bracket notation, facilitating structured state management. ```typescript import { reactive } from 'vue' import { useContextStorage } from 'vue-context-storage' const filters = reactive({ search: '', status: 'active' }) const pagination = reactive({ page: 1, perPage: 25 }) const sorting = reactive({ field: 'date', direction: 'desc' }) useContextStorage('sessionStorage', filters, { key: 'app-state[filters]' }) useContextStorage('sessionStorage', pagination, { key: 'app-state[pagination]' }) useContextStorage('sessionStorage', sorting, { key: 'app-state[sorting]' }) ``` -------------------------------- ### Create Query Handler Factory Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md The `createQueryHandler` factory creates a handler for synchronizing data with URL query parameters. It supports options to control navigation mode ('replace' or 'push'), whether to preserve unused query keys, preserve empty states, define a placeholder for empty values, and only write changed values to the URL. ```typescript import { createQueryHandler } from 'vue-context-storage'; const queryHandler = createQueryHandler({ mode: 'push', preserveUnusedKeys: false, preserveEmptyState: true, emptyPlaceholder: '_', onlyChanges: false, }); // This handler can then be used with useContextStorage or registered as a custom handler. ``` -------------------------------- ### Custom Handler Registration Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md APIs for defining and resolving custom storage handlers, allowing for flexible integration with different storage solutions. ```APIDOC ## Custom Handler Registration ### Description These functions allow you to extend `vue-context-storage` by defining your own custom storage handlers or looking them up by their injection keys. ### `defineContextStorageHandler(name, injectionKey)` #### Description Registers a new custom storage handler with a given name and its corresponding injection key. #### Parameters - **name** (`string`) - Required - The name to identify the custom handler. - **injectionKey** (`InjectionKey`) - Required - The injection key associated with the custom handler. ### `resolveHandlerInjectionKey(type)` #### Description Retrieves the injection key for a given handler type or name. #### Parameters - **type** (`'query' | 'localStorage' | 'sessionStorage' | string`) - Required - The type or name of the handler to resolve. #### Returns `InjectionKey | undefined` - The injection key if found, otherwise undefined. ``` -------------------------------- ### Zod Helpers (`vue-context-storage/zod`) Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Zod-specific helpers for integrating Zod schemas with `vue-context-storage`, including array serialization and automatic type coercion for query parameters. ```APIDOC ## Zod Helpers (`vue-context-storage/zod`) ### Description This module provides utilities to integrate Zod schemas with `vue-context-storage`, simplifying data validation and type coercion, especially for URL query parameters. Ensure you have `zod` installed as a peer dependency. ```bash npm install zod ``` ### `zObjectArray(itemSchema)` #### Description Creates a Zod schema for arrays of objects that are serialized as indexed query parameters. It wraps `z.record()` and includes a transformation to convert indexed objects back into sorted arrays. #### Parameters - **itemSchema** (`ZodSchema`) - Required - The Zod schema for individual items within the array. #### Usage Example ```javascript import { z } from 'zod' import { zObjectArray } from 'vue-context-storage/zod' const ItemSchema = z.object({ product: z.string().default(''), quantity: z.coerce.number().default(0), }) const DataSchema = z.object({ title: z.string().default(''), items: zObjectArray(ItemSchema), }) // Example usage with useContextStorage: // const { data } = useContextStorage('query', ref(initialData), { schema: DataSchema }) ``` ### Automatic Type Coercion #### Description When a `schema` is provided to `useContextStorage` (specifically for the `'query'` type), the library automatically attempts to coerce URL query parameter values to match the expected Zod types before validation. This addresses common URL serialization quirks, particularly with arrays. #### Array Coercion URLs can represent arrays in different ways (e.g., `?ids=1&ids=2` vs. `?ids=1`). Zod's `.array()` schema expects an array. This library automatically wraps single values into arrays if the schema expects an array, ensuring consistency. This coercion works recursively for nested objects and handles various Zod types including `.string().array()`, `.coerce.number().array()`, and `.enum().array()`. #### Usage Example ```javascript import { z } from 'zod' const Schema = z.object({ tags: z.string().array().default([]), ids: z.coerce.number().array().default([]), statuses: z.enum(['active', 'inactive']).array().default([]), filters: z .object({ categories: z.string().array().default([]), }) .default({ categories: [] }), }) // With useContextStorage('query', ref(initialData), { schema: Schema }) // These URL query parameters will be automatically handled: // ?tags=vue → { tags: ['vue'], ... } // ?tags=vue&tags=ts → { tags: ['vue', 'ts'], ... } // (no tags param) → { tags: [], ... } // ?ids=1 → { ids: [1], ... } // ?ids=1&ids=2 → { ids: [1, 2], ... } // ?statuses=active → { statuses: ['active'], ... } // ?filters[categories]=electronics → { filters: { categories: ['electronics'] }, ... } ``` ``` -------------------------------- ### Handle Boolean Coercion with Zod Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Demonstrates how the library automatically handles URL boolean serialization ('1'/'0') using standard Zod schemas, bypassing JavaScript's default truthy behavior for strings. ```typescript const Schema = z.object({ active: z.boolean().default(false), enabled: z.boolean().default(true), }) ``` -------------------------------- ### Using Context Storage with Vue Plugin Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Illustrates how to use the ContextStorage component in App.vue after registering the VueContextStoragePlugin. The component enables context storage features globally. ```vue ``` -------------------------------- ### Implement Custom Serialization for Storage Handlers Source: https://context7.com/lviobio/vue-context-storage/llms.txt Shows how to provide custom serializer and deserializer functions to localStorage or sessionStorage handlers, useful for encrypting or encoding sensitive data. ```typescript import { reactive } from 'vue' import { useContextStorage } from 'vue-context-storage' const sensitiveData = reactive({ apiKey: '', preferences: {}, }) useContextStorage('localStorage', sensitiveData, { key: 'encrypted-settings', serializer: (data) => btoa(JSON.stringify(data)), deserializer: (str) => JSON.parse(atob(str)), }) ``` -------------------------------- ### Use LocalStorage Handler for State Persistence (TypeScript) Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Shows how to use the `useContextStorage` hook with the 'localStorage' handler to persist reactive state in the browser's local storage. Data is automatically synchronized across different browser tabs under a specified key. Requires 'vue'. ```typescript import { reactive } from 'vue' import { useContextStorage } from 'vue-context-storage' const settings = reactive({ theme: 'light', fontSize: 14, sidebarOpen: true, }) // Automatically syncs settings with localStorage under the key "app-settings" useContextStorage('localStorage', settings, { key: 'app-settings', }) ``` -------------------------------- ### Sync State with URL Query Parameters Source: https://context7.com/lviobio/vue-context-storage/llms.txt Uses the useContextStorage composable to bind reactive state to URL query parameters, including custom transformation logic for type safety. ```vue ``` -------------------------------- ### Create Local Storage Handler Factory Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md The `createLocalStorageHandler` factory creates a handler for synchronizing data with the browser's localStorage. It has an option `listenToStorageEvents` which, when enabled, allows for cross-tab synchronization by listening to storage events. ```typescript import { createLocalStorageHandler } from 'vue-context-storage'; const localStorageHandler = createLocalStorageHandler({ listenToStorageEvents: true, }); // This handler can then be used with useContextStorage or registered as a custom handler. ``` -------------------------------- ### Handler Factories Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Factory functions to create specific types of storage handlers with customizable options. ```APIDOC ## Handler Factories ### `createQueryHandler(options?)` #### Description Creates a factory for a query handler, which synchronizes reactive state with URL query parameters. #### Options - **mode** (`'replace' | 'push'`) - Optional - Router navigation mode. Defaults to `'replace'`. - **preserveUnusedKeys** (`boolean`) - Optional - Whether to keep other query parameters in the URL. Defaults to `true`. - **preserveEmptyState** (`boolean`) - Optional - Whether to preserve empty state values in the URL. Defaults to `false`. - **emptyPlaceholder** (`string`) - Optional - Placeholder string for empty state values. Defaults to `'_'`. - **onlyChanges** (`boolean`) - Optional - Whether to only write changed values to the URL. Defaults to `true`. ### `createLocalStorageHandler(options?)` #### Description Creates a factory for a localStorage handler, enabling synchronization of reactive state with the browser's local storage. #### Options - **listenToStorageEvents** (`boolean`) - Optional - Whether to listen to `storage` events for cross-tab synchronization. Defaults to `true`. ### `createSessionStorageHandler(options?)` #### Description Creates a factory for a sessionStorage handler, enabling synchronization of reactive state with the browser's session storage. #### Options - **listenToStorageEvents** (`boolean`) - Optional - Whether to listen to `storage` events for cross-tab synchronization. Defaults to `false`. ``` -------------------------------- ### Query Handler Type Coercion with Zod Schema Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Illustrates how to handle type coercion for URL query parameters using Zod schemas. This is crucial because URL parameters are always strings, and Zod schemas automatically convert them to the correct types (e.g., numbers, booleans) and provide validation. ```typescript import { z } from 'zod' import { useContextStorage } from 'vue-context-storage' const FiltersSchema = z.object({ search: z.string().default(''), page: z.coerce.number().int().positive().default(1), status: z.enum(['active', 'inactive']).default('active'), }) const filters = ref(FiltersSchema.parse({})) // Use schema for automatic validation useContextStorage('query', filters, { key: 'filters', schema: FiltersSchema, }) ``` -------------------------------- ### Register VueContextStoragePlugin Source: https://context7.com/lviobio/vue-context-storage/llms.txt Globally registers all context storage components as a Vue plugin, removing the need for manual imports in individual components. ```typescript import { createApp } from 'vue' import { VueContextStoragePlugin } from 'vue-context-storage' import App from './App.vue' const app = createApp(App) app.use(VueContextStoragePlugin) app.mount('#app') ``` -------------------------------- ### Implement custom serialization Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Allows defining custom logic for serializing and deserializing data before it is written to or read from storage. ```typescript useContextStorage('localStorage', settings, { key: 'app-settings', serializer: (data) => btoa(JSON.stringify(data)), deserializer: (str) => JSON.parse(atob(str)), }) ``` -------------------------------- ### Use Context Storage Composable Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md The `useContextStorage` composable provides a unified interface for synchronizing reactive data with different storage handlers. It accepts a type (e.g., 'query', 'localStorage', 'sessionStorage', or an injection key), the data to sync, and handler-specific options. It returns the synced data, a stop function to unregister, a reset function, and a computed ref indicating if the data has changed. ```typescript import { useContextStorage } from 'vue-context-storage'; const { data, stop, reset, wasChanged } = useContextStorage('localStorage', ref('initialValue')); // Example usage: // stop(); // Unregister and stop syncing // reset(); // Restore data to initial state // console.log(wasChanged.value); // true or false ``` -------------------------------- ### Convert to Boolean - asBoolean Source: https://context7.com/lviobio/vue-context-storage/llms.txt The `asBoolean` transform helper converts URL string values such as 'true', 'false', '1', or '0' into their corresponding boolean representations. It supports a fallback value for cases where the input is not recognized. ```typescript import { reactive } from 'vue' import { useContextStorage, transform } from 'vue-context-storage' const options = reactive({ showArchived: false, compactView: true, autoRefresh: false, }) useContextStorage('query', options, { key: 'opts', transform: (deserialized, initial) => ({ showArchived: transform.asBoolean(deserialized.showArchived, { fallbackValue: false }), compactView: transform.asBoolean(deserialized.compactView, { fallbackValue: true }), autoRefresh: transform.asBoolean(deserialized.autoRefresh, { fallbackValue: false }), }), }) // URL: ?opts[showArchived]=1&opts[compactView]=true // Result: { showArchived: true, compactView: true, autoRefresh: false } ``` -------------------------------- ### Configure Additional Default Data for Query Handler (TypeScript) Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Explains how to use `additionalDefaultData` to specify values that should be treated as defaults and excluded from the URL, even if they differ from the initial snapshot. This is particularly useful when initial reactive data might be `undefined` before an API response. Requires 'vue'. ```typescript import { ref } from 'vue' import { useContextStorage } from 'vue-context-storage' const data = ref({ page: undefined as number | undefined }) useContextStorage('query', data, { key: 'filters', onlyChanges: true, additionalDefaultData: { page: 1 }, }) // page=undefined → not in query (matches initial) // page=1 → not in query (matches additionalDefaultData) // page=2 → appears in query as ?filters[page]=2 ``` -------------------------------- ### Transform Helpers Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Utility functions for transforming and handling data, particularly useful when dealing with potentially null or undefined values. ```APIDOC ## Transform Helpers ### Description Provides utility functions for data transformation, with built-in support for handling nullable and missable values. ### `transform.asNumber(value, options?)` #### Description Attempts to transform a value into a number. Supports fallback, nullability, and missability. #### Parameters - **value** (`any`) - The value to transform. - **options** (`object`) - Optional configuration object: - **fallback** (`number`) - The default value to return if transformation fails or the value is null/undefined. Defaults to `0`. - **nullable** (`boolean`) - If `true`, allows `null` to be returned. Defaults to `false`. - **missable** (`boolean`) - If `true`, allows `undefined` to be returned. Defaults to `false`. ### Usage Example ```javascript import { transform } from 'vue-context-storage' const num1 = transform.asNumber('123') // 123 const num2 = transform.asNumber('abc', { fallback: 10 }) const num3 = transform.asNumber(null, { fallback: 5, nullable: true }) // 5 (because nullable is true, but fallback takes precedence) const num4 = transform.asNumber(undefined, { fallback: 7, missable: true }) // 7 (because missable is true, but fallback takes precedence) const num5 = transform.asNumber(null, { nullable: true }) // null const num6 = transform.asNumber(undefined, { missable: true }) // undefined ``` ``` -------------------------------- ### Scope storage keys with ContextStoragePrefix Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Utilize the ContextStoragePrefix component to automatically prepend keys to all nested useContextStorage calls, supporting stacking and dynamic updates. ```vue ``` -------------------------------- ### Sync Pagination State with URL Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Uses useContextStorage to synchronize a pagination object with URL query parameters, utilizing custom transformation logic to handle fallbacks and filter specific fields. ```typescript import { ref } from 'vue' import { useContextStorage, transform } from 'vue-context-storage' const pagination = ref({ page: 1, perPage: 25, total: 0, }) useContextStorage('query', pagination, { key: 'page', transform: (data, initial) => ({ page: transform.asNumber(data.page, { fallback: 1 }), perPage: transform.asNumber(data.perPage, { fallback: 25 }), total: initial.total, }), }) ``` -------------------------------- ### Register Custom Storage Handlers Source: https://context7.com/lviobio/vue-context-storage/llms.txt Registers custom storage handlers at runtime and provides TypeScript type safety via module augmentation. ```typescript import { defineContextStorageHandler, useContextStorage } from 'vue-context-storage' import type { InjectionKey } from 'vue' const myCustomHandlerKey: InjectionKey = Symbol('myCustomHandler') defineContextStorageHandler('myCustom', myCustomHandlerKey) declare module 'vue-context-storage' { interface ContextStorageHandlerMap { myCustom: { key: string; customOption?: boolean } } } useContextStorage('myCustom', data, { key: 'example', customOption: true, }) ``` -------------------------------- ### Utilize zObjectArray for Indexed Query Parameters Source: https://context7.com/lviobio/vue-context-storage/llms.txt A specialized Zod helper that manages arrays of objects serialized as indexed query parameters. It automatically handles the conversion between flat URL indices and nested array structures. ```typescript import { reactive } from 'vue' import { z } from 'zod' import { useContextStorage } from 'vue-context-storage' import { zObjectArray } from 'vue-context-storage/zod' const ItemSchema = z.object({ product: z.string().default(''), quantity: z.coerce.number().default(1), selected: z.boolean().default(false), }) const OrderSchema = z.object({ title: z.string().default(''), notes: z.string().default(''), items: zObjectArray(ItemSchema), }) const order = reactive(OrderSchema.parse({})) useContextStorage('query', order, { key: 'order', schema: OrderSchema, }) ``` -------------------------------- ### Convert to Number with Fallback - asNumber Source: https://context7.com/lviobio/vue-context-storage/llms.txt The `asNumber` transform helper converts URL query string values to proper number types. It handles potential NaN cases by allowing a fallback value to be specified, ensuring a valid number is always returned. ```typescript import { reactive } from 'vue' import { useContextStorage, transform } from 'vue-context-storage' const pagination = reactive({ page: 1, perPage: 25, offset: 0, }) useContextStorage('query', pagination, { key: 'page', transform: (deserialized, initial) => ({ page: transform.asNumber(deserialized.page, { fallbackValue: 1 }), perPage: transform.asNumber(deserialized.perPage, { fallbackValue: 25 }), offset: transform.asNumber(deserialized.offset, { fallbackValue: 0 }), }), }) // URL: ?page[page]=2&page[perPage]=50 // Result: { page: 2, perPage: 50, offset: 0 } ``` -------------------------------- ### Convert to String with Validation - asString Source: https://context7.com/lviobio/vue-context-storage/llms.txt The `asString` transform helper converts values to strings. It includes an option to validate against a list of allowed values, ensuring that the resulting string conforms to expected formats. A fallback value can also be provided. ```typescript import { reactive } from 'vue' import { useContextStorage, transform } from 'vue-context-storage' const filters = reactive({ search: '', status: 'active' as 'active' | 'inactive' | 'pending', sortBy: 'date', }) useContextStorage('query', filters, { key: 'f', transform: (deserialized, initial) => ({ search: transform.asString(deserialized.search, { fallbackValue: '' }), status: transform.asString(deserialized.status, { allowedValues: ['active', 'inactive', 'pending'] as const, fallbackValue: 'active', }), sortBy: transform.asString(deserialized.sortBy, { fallbackValue: 'date' }), }), }) ``` -------------------------------- ### useContextStorage Composable Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md A unified composable function that manages reactive data synchronization across different storage types (query, localStorage, sessionStorage) or custom handlers. ```APIDOC ## useContextStorage(type, data, options) ### Description This composable function provides a unified interface for managing reactive state. It delegates the actual storage and synchronization logic to a specific handler based on the provided `type`. ### Method `useContextStorage` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None #### Parameters - **type** (`'query' | 'localStorage' | 'sessionStorage' | InjectionKey`) - Required - Specifies the storage mechanism or a custom handler's injection key. - **data** (`MaybeRefOrGetter`) - Required - A reactive reference or getter containing the data to be synchronized. - **options** (`Handler-specific options`) - Optional - Configuration options tailored to the selected handler type. ### Returns An object containing: - **data** (`Ref`) - The reactive reference passed in, now managed by the storage handler. - **stop** (`() => void`) - A function to unregister the handler and stop synchronization. Automatically called on component unmount. - **reset** (`() => void`) - A function to restore the data to its initial state. - **wasChanged** (`ComputedRef`) - A computed boolean indicating whether the current data differs from its initial state. ### Request Example ```javascript import { ref } from 'vue' import { useContextStorage } from 'vue-context-storage' const count = ref(0) const { data, stop, reset, wasChanged } = useContextStorage('localStorage', count, { listenToStorageEvents: true }) // Later, to stop syncing manually: // stop() ``` ### Response #### Success Response (200) N/A (This is a composable function, not an API endpoint). #### Response Example N/A ``` -------------------------------- ### Convert to Array/Number Array - asArray and asNumberArray Source: https://context7.com/lviobio/vue-context-storage/llms.txt These helpers convert URL parameters into arrays. `asArray` handles general string arrays, while `asNumberArray` specifically converts values to numbers within an array. Both can manage single values or multiple values for the same key in the URL. ```typescript import { reactive } from 'vue' import { useContextStorage, transform } from 'vue-context-storage' const selection = reactive({ tags: [] as string[], categoryIds: [] as number[], statuses: [] as string[], }) useContextStorage('query', selection, { key: 'sel', transform: (deserialized, initial) => ({ tags: transform.asArray(deserialized.tags), categoryIds: transform.asNumberArray(deserialized.categoryIds), statuses: transform.asArray(deserialized.statuses), }), }) // URL: ?sel[tags]=vue&sel[tags]=typescript&sel[categoryIds]=1&sel[categoryIds]=2 // Result: { tags: ['vue', 'typescript'], categoryIds: [1, 2], statuses: [] } ``` -------------------------------- ### Zod Helper: zObjectArray Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md The `zObjectArray` helper from `vue-context-storage/zod` creates a Zod schema for arrays of objects that are serialized as indexed query parameters. It wraps `z.record()` and `.transform()` to correctly convert these indexed objects back into sorted arrays during deserialization. ```typescript import { z } from 'zod'; import { zObjectArray } from 'vue-context-storage/zod'; const ItemSchema = z.object({ product: z.string().default(''), quantity: z.coerce.number().default(0), }); const DataSchema = z.object({ title: z.string().default(''), items: zObjectArray(ItemSchema), }); // Example usage with URL parameters: // ?items[0][product]=apple&items[0][quantity]=5&items[1][product]=banana&items[1][quantity]=10 // This would parse into: // { title: '', items: [{ product: 'apple', quantity: 5 }, { product: 'banana', quantity: 10 }] } ``` -------------------------------- ### ContextStoragePrefix Component Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md A Vue component used to scope prefixes for descendant `useContextStorage` calls via provide/inject, enabling hierarchical state management. ```APIDOC ## `` Component ### Description This component allows you to define a prefix that will be applied to all `useContextStorage` calls within its scope. This is useful for organizing state, especially when using multiple instances or different storage types. ### Props - **name** (`string | Partial>`) - Required - The prefix to apply. Can be a single string for all handlers, or an object mapping handler types to specific prefixes (e.g., `{ query: 'q', localStorage: 'ls' }`). ### Usage Nested `` components stack their prefixes. If the `name` prop changes dynamically, all descendant components will be re-created to reflect the new prefix. ```vue ``` ``` -------------------------------- ### Persist reactive state with sessionStorage Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Demonstrates how to sync a reactive object with sessionStorage using the useContextStorage composable. The state persists across page refreshes but clears when the tab is closed. ```vue ``` -------------------------------- ### Scope State with ContextStoragePrefix Source: https://context7.com/lviobio/vue-context-storage/llms.txt Uses the ContextStoragePrefix component to namespace descendant storage calls. Prefixes are concatenated using bracket notation, allowing for organized URL query structures. ```vue ``` -------------------------------- ### Deserialize Query Parameters with Zod Schema (TypeScript) Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Shows how to deserialize indexed query parameters into an array of objects using the Zod helper `zObjectArray`. This method leverages Zod for schema definition and validation, providing a robust way to handle complex data structures from URLs. Requires 'zod' and 'vue-context-storage/zod'. ```typescript import { z } from 'zod' import { zObjectArray } from 'vue-context-storage/zod' const ItemSchema = z.object({ product: z.string().default(''), quantity: z.coerce.number().default(0), }) const DataSchema = z.object({ title: z.string().default(''), items: zObjectArray(ItemSchema), }) useContextStorage('query', data, { schema: DataSchema }) ``` -------------------------------- ### Create Session Storage Handler Factory Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md The `createSessionStorageHandler` factory creates a handler for synchronizing data with the browser's sessionStorage. It provides an option `listenToStorageEvents` to enable listening to storage events, facilitating cross-tab synchronization. ```typescript import { createSessionStorageHandler } from 'vue-context-storage'; const sessionStorageHandler = createSessionStorageHandler({ listenToStorageEvents: false, }); // This handler can then be used with useContextStorage or registered as a custom handler. ``` -------------------------------- ### Deserialize Query Parameters as Object Array (TypeScript) Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Demonstrates how to deserialize indexed query parameters into an array of objects using `transform.asObjectArray`. This is necessary because URL parameters are deserialized as indexed objects by default. It requires 'vue' and 'vue-context-storage' packages. ```typescript import { reactive } from 'vue' import { useContextStorage, transform } from 'vue-context-storage' const data = reactive({ title: '', items: [] as { product: string; quantity: number }[], }) useContextStorage('query', data, { transform: (value) => ({ title: transform.asString(value.title), items: transform.asObjectArray(value.entry => ({ product: transform.asString(entry.product), quantity: transform.asNumber(entry.quantity), })), }), }) ``` -------------------------------- ### Implement Zod Schema Integration for Type Coercion Source: https://context7.com/lviobio/vue-context-storage/llms.txt Uses Zod schemas to automatically coerce and validate complex data structures synced with URL query parameters. It ensures runtime type safety and provides default values for state objects. ```typescript import { reactive } from 'vue' import { z } from 'zod' import { useContextStorage } from 'vue-context-storage' const FiltersSchema = z.object({ search: z.string().default(''), page: z.coerce.number().int().positive().default(1), perPage: z.coerce.number().int().min(10).max(100).default(25), status: z.enum(['active', 'inactive', 'all']).default('all'), showArchived: z.boolean().default(false), tags: z.string().array().default([]), }) type Filters = z.infer const filters = reactive(FiltersSchema.parse({})) useContextStorage('query', filters, { key: 'filters', schema: FiltersSchema, }) ``` -------------------------------- ### Context Storage Prefix Component Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md The `` component is used to scope prefixes for all descendant `useContextStorage` calls. It utilizes Vue's provide/inject mechanism. The `name` prop can be a string for a universal prefix or an object to apply prefixes per handler type. Nested components stack prefixes using bracket notation. ```vue ``` -------------------------------- ### Query Handler Type Coercion with Transform Function Source: https://github.com/lviobio/vue-context-storage/blob/main/README.md Shows an alternative method for type coercion of URL query parameters using a custom 'transform' function. This approach allows for manual conversion of string values to their intended types, providing fallback values if needed. ```typescript import { useContextStorage } from 'vue-context-storage' // Assume asNumber, asString are imported or defined elsewhere useContextStorage('query', filters, { key: 'filters', transform: (deserialized, initial) => ({ page: asNumber(deserialized.page, { fallback: initial.page }), search: asString(deserialized.search, { fallback: initial.search }), status: asString(deserialized.status, { fallback: initial.status }), }), }) ``` -------------------------------- ### Persist State to localStorage Source: https://context7.com/lviobio/vue-context-storage/llms.txt Uses the useContextStorage composable to persist reactive state to localStorage, enabling cross-tab synchronization. ```vue ``` -------------------------------- ### Configure ContextStorage with Custom Handlers Source: https://context7.com/lviobio/vue-context-storage/llms.txt Overrides default storage behavior by providing custom configurations to the ContextStorage component via the additional-handlers prop. ```vue ``` -------------------------------- ### Preserve Empty State in URL Source: https://context7.com/lviobio/vue-context-storage/llms.txt Enables the preservation of empty state in the URL to prevent data resetting upon page reloads or when sharing URLs. ```typescript import { reactive } from 'vue' import { useContextStorage } from 'vue-context-storage' const filters = reactive({ search: '', category: '', }) useContextStorage('query', filters, { key: 'f', preserveEmptyState: true, }) ```