Skip to content

Справочник

Архитектура

vue-storage-kit

├── StorageAdapterFactory (синглтон на каждую цель)
│     LocalStorageAdapter     → window.localStorage
│     SessionStorageAdapter   → window.sessionStorage
│     MemoryStorageAdapter    → Map<string, string>  (SSR / цель 'memory')
│     IndexedDBStorageAdapter → выделенное object store IndexedDB (цель 'indexeddb')

│     StorageAdapter асинхронен (getItem/setItem/removeItem/keys возвращают Promise),
│     так что все четыре бэкенда — включая IndexedDB — используют один конвейер.

├── src/engine  (фреймворк-агностично — здесь нигде нет импорта vue или react)
│     │
│     ├── StorageEngine
│     │     Владеет полным конвейером чтения/записи: TTL, миграции схемы,
│     │     encrypt/compress/sign, синхронизация вкладок, debounce/throttle,
│     │     история undo/redo, восстановление при превышении квоты (зачистка
│     │     по TTL, затем опциональное LRU-вытеснение). Экспонирует
│     │     getSnapshot()/subscribe() — форму «внешнего хранилища», пригодную
│     │     для любого фреймворка — плюс onEvent() для потребителей в стиле
│     │     таймлайна devtools.
│     │
│     └── engineCache
│           acquireEngine()/releaseEngine() — кэш со счётчиком ссылок, общий
│           для Vue *и* React: два компонента в любом из фреймворков (или
│           обоих), запрашивающих один key+target, получают один StorageEngine.

├── composables/useStorage  (Vue)
│     Тонкая обёртка: ref/computed, отражающие engine.getSnapshot(),
│     watch(value, flush:'sync'), который вызывает engine.setValue(), и
│     собственный wrapperCache поверх engineCache, чтобы несколько
│     Vue-компонентов делили один и тот же `Ref` (а не только движок).

├── react/useStorage  (React, точка входа `/react`)
│     Тонкая обёртка: useSyncExternalStore(engine.subscribe, engine.getSnapshot)
│     плюс коллбэк setValue(). Захватывает/освобождает через тот же engineCache.

├── SchemaManager
│     Строит и запускает цепочки миграций (up или down)

├── TTLManager
│     Проверяет exp при каждом чтении (ленивое истечение)
│     cleanExpired() — массовая зачистка с опциональным префиксом

├── createJSONSerializer
│     Обрабатывает Date, Map, Set, undefined через preProcess()
│     (preProcess обходит дерево перед JSON.stringify, чтобы избежать
│      перехвата replacer'а через Date.prototype.toJSON())

├── useIndexedDB / useIDBRef  (Vue)
│     IndexedDBAdapter — лениво открывает IDB, создаёт store при обновлении
│     useIDBRef следит за ref и вызывает adapter.set() при изменении

├── useCookie  (Vue)
│     Парсит document.cookie при монтировании
│     watch → строит строку Set-Cookie и присваивает её document.cookie

├── /crypto  (отдельная точка входа)
│     StorageEncryption — encrypt() / decrypt() / reencrypt() / rotateEncryptedKey()
│     Вывод ключа через PBKDF2; выведенные ключи кэшируются по (password, iterations, salt)
│     StorageSigning — sign() / verify(), HMAC-SHA256

├── /sync  (отдельная точка входа)
│     LeaderElection — navigator.locks; держит блокировку на время жизни вкладки
│     TabSync — BroadcastChannel + запасной вариант через событие storage
│               последняя запись побеждает по временной метке; при ничьей побеждает лидер

├── VueStoragePlugin  (Vue)
│     prefix/defaultTarget/defaultSerializer/defaultEncrypt/onError, читается
│     каждым вызовом Vue useStorage() после установки через getGlobalOptions()

├── /devtools  (отдельная точка входа, опционально через setupDevtools(app))
│     Инспектор + таймлайн поверх engineCache — видит экземпляры и Vue, и React

├── /testing  (отдельная точка входа)
│     mockStorage()/resetStorageState()/seedEnvelope()/flushAsync()

└── Модуль Nuxt (vue-storage-kit/nuxt)
      addImports — автоимпорт всех composables (useCookie → SSR-совместимая runtime-версия)
      addPlugin  — устанавливает VueStoragePlugin с runtimeConfig.storageKit.prefix

Размер бандла и peer-зависимости

Точка входаНужен ли vue?Peer/runtime-зависимостиЗаметки
vue-storage-kitДаvue ^3.3Vue composables, плагин, адаптеры, сериализатор
vue-storage-kit/reactНетreact ^18React-хук useStorage()
vue-storage-kit/cryptoНетAES-GCM шифрование, HMAC-подписи, смена ключа
vue-storage-kit/syncНетТолько TabSync и LeaderElection
vue-storage-kit/compressНетТолько хелперы Compression Streams + CompressAdapter
vue-storage-kit/piniaНетpinia ^2 | ^3 (опциональная peer)Только createPiniaPersist
vue-storage-kit/devtoolsНет@vue/devtools-api (входит как runtime-зависимость)Инспектор + таймлайн, опционально
vue-storage-kit/testingДа¹Хелперы для тестов
vue-storage-kit/nuxt@nuxt/kit (опциональная peer), h3 (опциональная peer)Модуль Nuxt

¹ /testing подключает Vue composable-модуль ради хелпера сброса кэша, даже если вы тестируете только React-код — это стоит только на dev/test, никогда не попадает в продакшен, поэтому не оптимизируется.

Пакет поставляется как tree-shakeable ESM (dist/index.js) и CommonJS (dist/index.cjs). Точки входа /crypto, /sync и /compress также разбиты на отдельные чанки внутри useStorage — загружаются динамически только когда опции encrypt, sync или compress реально заданы, сохраняя базовый вес маленьким независимо от того, какая точка входа их подключила. @vue/devtools-api — единственная обязательная runtime-зависимость пакета, и она никогда не включается в ., /react или /nuxt — загружается только если вы явно импортируете vue-storage-kit/devtools и сами вызываете setupDevtools(app). Ни vue, ни react не являются жёсткой зависимостью пакета в целом — только той конкретной точки входа, которую вы импортируете.

Сравнение с @vueuse/core

vue-storage-kit расширяет и расходится с @vueuse/core в конкретных областях.

Прямые замены

@vueuse/corevue-storage-kitЗаметки
useLocalStorage(key, default)useLocalStorage(key, default)Та же сигнатура; flush: 'sync' по умолчанию
useSessionStorage(key, default)useSessionStorage(key, default)Та же сигнатура
useCookies()useCookie(name, options)Реактивный Ref для каждой cookie вместо одного объекта
useStorageAsync()useIDBRef()Реактивный Ref на базе асинхронного хранилища (IndexedDB)
useBroadcastChannel()useBroadcastChannel()Идентичный API

Расширенная функциональность (нет аналога в vueuse)

Возможностьvue-storage-kit
Миграции схемыОпция migrations: [{ version, up, down? }] в StorageOptions
TTL / истечениеОпция ttl (секунды); ленивая проверка при чтении; без фоновых таймеров
AES-GCM шифрованиеОпция encrypt: { password }; только Web Crypto API, без дополнительных зависимостей
Синхронизация вкладокОпция sync: true; BroadcastChannel с запасным вариантом через событие storage
Выборы лидераЛидер на базе navigator.locks в LeaderElection
Полный API IndexedDBuseIndexedDB() — get / set / delete / keys / getAll / transaction / индексы
Вторичные индексы IDBuseIndexedDB('db', 'store', onError, { indexes: [...] })
CRUD-коллекцияuseStorageList<T>() — add / update / remove / find / findAll
Персистентность PiniaТочка входа /piniacreatePiniaPersist({ pick?, omit? })
СжатиеОпция compress: true на useStorage, либо самостоятельная точка входа /compresscompress() / decompress() через Compression Streams API
Экспорт / импортexportStorage() / importStorage() — снапшот и восстановление всех ключей
Общий кэш экземпляровДва компонента (Vue или React), вызывающие useStorage('key'), делят один движок — ноль дублирующихся наблюдателей/таймеров
Инспектор + таймлайн DevtoolsТочка входа /devtoolssetupDevtools(app), видит экземпляры и Vue, и React
HMAC-подписиОпция sign: { password } — обнаружение случайного повреждения без требования секретности
Undo / redoОпция history: nundo()/redo() в памяти, без дополнительного управления состоянием
ThrottleОпция throttle, наряду с debounce
Восстановление при превышении квотыАвтоматическая зачистка по TTL + повтор; опциональный evictOnQuota для LRU-вытеснения других ключей
Поддержка ReactТочка входа /react — те же опции, тот же движок, на базе useSyncExternalStore
Утилиты для тестированияТочка входа /testingmockStorage(), resetStorageState(), seedEnvelope()

Отличия в поведении

Поведение@vueuse/corevue-storage-kit
Flush наблюдателя'pre' (по умолчанию у Vue)'sync' — запись происходит в той же микрозадаче, что и присваивание
Обновление между вкладкамиТолько событие storageBroadcastChannel с запасным вариантом через событие storage
СериализацияТолько JSONJSON + round-trip для Date, Map, Set, BigInt; кастомный Serializer<T>
Несколько экземпляровНезависимые наблюдатели на каждый вызовОбщий StorageEngine через кэш со счётчиком ссылок, между Vue и React
SSRГлобальные заглушкиТе же заглушки; useCookie принимает событие H3 для серверных маршрутов Nuxt

Лицензия

MIT