@vielzeug/vault 2.4.0 → 3.0.0

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.
Files changed (79) hide show
  1. package/README.md +25 -32
  2. package/dist/adapter-core.cjs +1 -1
  3. package/dist/adapter-core.cjs.map +1 -1
  4. package/dist/adapter-core.d.ts +32 -7
  5. package/dist/adapter-core.d.ts.map +1 -1
  6. package/dist/adapter-core.js +204 -120
  7. package/dist/adapter-core.js.map +1 -1
  8. package/dist/adapters/indexeddb.cjs +1 -1
  9. package/dist/adapters/indexeddb.cjs.map +1 -1
  10. package/dist/adapters/indexeddb.d.ts +8 -5
  11. package/dist/adapters/indexeddb.d.ts.map +1 -1
  12. package/dist/adapters/indexeddb.js +204 -172
  13. package/dist/adapters/indexeddb.js.map +1 -1
  14. package/dist/adapters/memory.cjs +1 -1
  15. package/dist/adapters/memory.cjs.map +1 -1
  16. package/dist/adapters/memory.d.ts +2 -4
  17. package/dist/adapters/memory.d.ts.map +1 -1
  18. package/dist/adapters/memory.js +30 -52
  19. package/dist/adapters/memory.js.map +1 -1
  20. package/dist/adapters/sqlite.cjs +21 -21
  21. package/dist/adapters/sqlite.cjs.map +1 -1
  22. package/dist/adapters/sqlite.d.ts +4 -6
  23. package/dist/adapters/sqlite.d.ts.map +1 -1
  24. package/dist/adapters/sqlite.js +246 -248
  25. package/dist/adapters/sqlite.js.map +1 -1
  26. package/dist/adapters/webstorage.cjs +1 -1
  27. package/dist/adapters/webstorage.cjs.map +1 -1
  28. package/dist/adapters/webstorage.d.ts +4 -4
  29. package/dist/adapters/webstorage.d.ts.map +1 -1
  30. package/dist/adapters/webstorage.js +100 -119
  31. package/dist/adapters/webstorage.js.map +1 -1
  32. package/dist/codec.cjs +2 -0
  33. package/dist/codec.cjs.map +1 -0
  34. package/dist/codec.d.ts +5 -0
  35. package/dist/codec.d.ts.map +1 -0
  36. package/dist/codec.js +6 -0
  37. package/dist/codec.js.map +1 -0
  38. package/dist/errors.cjs +1 -1
  39. package/dist/errors.cjs.map +1 -1
  40. package/dist/errors.d.ts +5 -0
  41. package/dist/errors.d.ts.map +1 -1
  42. package/dist/errors.js +10 -2
  43. package/dist/errors.js.map +1 -1
  44. package/dist/index.cjs +1 -1
  45. package/dist/index.d.ts +3 -2
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +3 -2
  48. package/dist/indexeddb.d.ts +1 -1
  49. package/dist/indexeddb.d.ts.map +1 -1
  50. package/dist/internal.cjs +1 -1
  51. package/dist/internal.cjs.map +1 -1
  52. package/dist/internal.d.ts.map +1 -1
  53. package/dist/internal.js +16 -13
  54. package/dist/internal.js.map +1 -1
  55. package/dist/query.cjs +1 -1
  56. package/dist/query.cjs.map +1 -1
  57. package/dist/query.d.ts +8 -24
  58. package/dist/query.d.ts.map +1 -1
  59. package/dist/query.js +23 -35
  60. package/dist/query.js.map +1 -1
  61. package/dist/sqlite.d.ts +1 -1
  62. package/dist/sqlite.d.ts.map +1 -1
  63. package/dist/ttl.cjs +1 -1
  64. package/dist/ttl.cjs.map +1 -1
  65. package/dist/ttl.js +1 -1
  66. package/dist/ttl.js.map +1 -1
  67. package/dist/types.cjs +1 -1
  68. package/dist/types.cjs.map +1 -1
  69. package/dist/types.d.ts +46 -33
  70. package/dist/types.d.ts.map +1 -1
  71. package/dist/types.js +8 -2
  72. package/dist/types.js.map +1 -1
  73. package/dist/vault.cjs +1 -1
  74. package/dist/vault.cjs.map +1 -1
  75. package/dist/vault.iife.js +1 -1
  76. package/dist/vault.iife.js.map +1 -1
  77. package/dist/vault.js +1 -1
  78. package/dist/vault.js.map +1 -1
  79. package/package.json +10 -8
@@ -1 +1 @@
1
- {"version":3,"file":"webstorage.js","names":[],"sources":["../../src/adapters/webstorage.ts"],"sourcesContent":["import { buildAdapterOps, type StorageBackend } from '../adapter-core';\nimport { VaultError, VaultQuotaError } from '../errors';\nimport {\n decodeStorageTableFromKey,\n encodeDbPrefix,\n encodeStorageKey,\n encodeStorageTablePrefix,\n getRecordKey,\n} from '../internal';\nimport { isExpired, parseStored } from '../ttl';\nimport type { AnySchema, BaseAdapterOptions, KeyOf, RecordOf, VaultStore } from '../types';\n\n// Firefox historically threw 'NS_ERROR_DOM_QUOTA_REACHED'; modern browsers use the standard name.\nconst QUOTA_ERROR_NAMES = new Set(['QuotaExceededError', 'NS_ERROR_DOM_QUOTA_REACHED']);\n\ntype WebStorageOptions<S extends AnySchema> = BaseAdapterOptions<S> & {\n name: string;\n /**\n * Called when localStorage/sessionStorage quota is exceeded on a write.\n * Return `'ignore'` to silently drop the write, or `'throw'` (default) to rethrow the error.\n */\n onQuotaExceeded?: (table: keyof S, error: VaultQuotaError) => 'ignore' | 'throw';\n};\n\nfunction createWebStorageAdapter<S extends AnySchema>(\n options: WebStorageOptions<S> & {\n getStorage: () => Storage;\n storageLabel: string;\n },\n): VaultStore<S> {\n const { getStorage, name, onQuotaExceeded, schema, storageLabel, validators } = options;\n\n let resolvedStorage: Storage;\n\n try {\n resolvedStorage = getStorage();\n } catch (cause) {\n throw new VaultError(\n `${storageLabel} is not available in this environment (private browsing or sandboxed iframe?)`,\n {\n cause,\n },\n );\n }\n\n const storage = (): Storage => resolvedStorage;\n\n const prefixMap = new Map(Object.keys(schema).map((table) => [table, encodeStorageTablePrefix(name, table)]));\n const getPrefix = (table: string): string => {\n const cached = prefixMap.get(table);\n\n if (!cached) throw new VaultError(`table \"${table}\" not in schema`);\n\n return cached;\n };\n\n const writeItem = (table: keyof S, storageKey: string, value: unknown): void => {\n try {\n storage().setItem(storageKey, JSON.stringify(value));\n } catch (error) {\n if (error instanceof DOMException && QUOTA_ERROR_NAMES.has(error.name)) {\n const wrappedError = new VaultQuotaError(`${storageLabel} quota exceeded while writing record`, {\n cause: error,\n });\n\n if (onQuotaExceeded?.(table, wrappedError) === 'ignore') return;\n\n throw wrappedError;\n }\n\n throw error;\n }\n };\n\n // Per-instance registry of all storage keys owned by this adapter instance.\n // Populated once at construction; kept current by every mutation.\n const ownedKeys = new Set<string>();\n\n const initOwnedKeys = (): void => {\n const dbPrefix = encodeDbPrefix(name);\n\n for (let i = 0; i < resolvedStorage.length; i++) {\n const key = resolvedStorage.key(i);\n\n if (key?.startsWith(dbPrefix)) ownedKeys.add(key);\n }\n };\n\n initOwnedKeys();\n\n /**\n * Reads a single entry without side effects. Returns the live value,\n * or `undefined` if missing/expired/corrupt.\n *\n * Callers that want to evict stale entries must call `evict(storageKey)` explicitly.\n * This design avoids the `{ cleanup?: boolean }` flag that required callers to remember\n * to pass `{ cleanup: false }` inside loops.\n */\n const parseEntry = <T extends object>(storageKey: string): T | undefined => {\n const raw = storage().getItem(storageKey);\n\n if (!raw) return undefined;\n\n try {\n const stored = parseStored<T>(JSON.parse(raw) as unknown);\n\n if (!stored || isExpired(stored.expiresAt)) return undefined;\n\n return stored.value;\n } catch {\n return undefined;\n }\n };\n\n /** Removes a stale/expired/corrupt entry from storage and the owned-keys registry. */\n const evict = (storageKey: string): void => {\n storage().removeItem(storageKey);\n ownedKeys.delete(storageKey);\n };\n\n const core: StorageBackend<S> = {\n async clear<K extends keyof S & string>(table: K): Promise<void> {\n const target = storage();\n const prefix = getPrefix(table);\n const toRemove: string[] = [];\n\n for (const key of ownedKeys) {\n if (key.startsWith(prefix)) toRemove.push(key);\n }\n\n for (const key of toRemove) {\n target.removeItem(key);\n ownedKeys.delete(key);\n }\n },\n\n async count<K extends keyof S & string>(table: K): Promise<number> {\n const prefix = getPrefix(table);\n const expiredKeys: string[] = [];\n let liveCount = 0;\n\n for (const storageKey of ownedKeys) {\n if (!storageKey.startsWith(prefix)) continue;\n\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value === undefined) {\n expiredKeys.push(storageKey);\n } else {\n liveCount += 1;\n }\n }\n\n for (const storageKey of expiredKeys) {\n evict(storageKey);\n }\n\n return liveCount;\n },\n\n async delete<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<boolean> {\n const storageKey = encodeStorageKey(name, table, key);\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value !== undefined) {\n evict(storageKey);\n\n return true;\n }\n\n if (ownedKeys.has(storageKey)) evict(storageKey);\n\n return false;\n },\n\n async deleteMany<K extends keyof S & string>(table: K, keys: KeyOf<S, K>[]): Promise<number> {\n let deleted = 0;\n\n for (const key of keys) {\n const storageKey = encodeStorageKey(name, table, key);\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value !== undefined) {\n evict(storageKey);\n deleted += 1;\n } else if (ownedKeys.has(storageKey)) {\n evict(storageKey);\n }\n }\n\n return deleted;\n },\n\n async get<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<RecordOf<S, K> | undefined> {\n const storageKey = encodeStorageKey(name, table, key);\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value === undefined && ownedKeys.has(storageKey)) evict(storageKey);\n\n return value;\n },\n\n async getAll<K extends keyof S & string>(table: K): Promise<RecordOf<S, K>[]> {\n const records: RecordOf<S, K>[] = [];\n const expiredKeys: string[] = [];\n const prefix = getPrefix(table);\n\n for (const storageKey of ownedKeys) {\n if (!storageKey.startsWith(prefix)) continue;\n\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value === undefined) {\n expiredKeys.push(storageKey);\n continue;\n }\n\n records.push(value);\n }\n\n for (const storageKey of expiredKeys) {\n evict(storageKey);\n }\n\n return records;\n },\n\n async getAllKeys<K extends keyof S & string>(table: K): Promise<KeyOf<S, K>[]> {\n const prefix = getPrefix(table);\n const keys: KeyOf<S, K>[] = [];\n const expiredStorageKeys: string[] = [];\n\n for (const storageKey of ownedKeys) {\n if (!storageKey.startsWith(prefix)) continue;\n\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value === undefined) {\n expiredStorageKeys.push(storageKey);\n continue;\n }\n\n // Extract the record key from the already-decoded value (avoids a second parse).\n keys.push((value as Record<string, unknown>)[schema[table].key] as KeyOf<S, K>);\n }\n\n for (const storageKey of expiredStorageKeys) {\n evict(storageKey);\n }\n\n return keys;\n },\n\n async has<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<boolean> {\n const storageKey = encodeStorageKey(name, table, key);\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value === undefined && ownedKeys.has(storageKey)) evict(storageKey);\n\n return value !== undefined;\n },\n\n async pruneExpiredInTable<K extends keyof S & string>(table: K): Promise<number> {\n const prefix = getPrefix(table);\n const expiredKeys: string[] = [];\n\n for (const storageKey of ownedKeys) {\n if (!storageKey.startsWith(prefix)) continue;\n\n const raw = storage().getItem(storageKey);\n\n if (raw === null) {\n expiredKeys.push(storageKey);\n continue;\n }\n\n try {\n const stored = parseStored(JSON.parse(raw) as unknown);\n\n if (!stored || isExpired(stored.expiresAt)) {\n expiredKeys.push(storageKey);\n }\n } catch {\n expiredKeys.push(storageKey);\n }\n }\n\n for (const storageKey of expiredKeys) {\n evict(storageKey);\n }\n\n return expiredKeys.length;\n },\n\n async put<K extends keyof S & string>(table: K, value: RecordOf<S, K>, ttl?: number): Promise<void> {\n const storageKey = encodeStorageKey(name, table, getRecordKey(schema, table, value));\n const expiresAt = ttl !== undefined ? Date.now() + ttl : undefined;\n\n writeItem(table, storageKey, expiresAt === undefined ? { value } : { expiresAt, value });\n ownedKeys.add(storageKey);\n },\n\n async putAll<K extends keyof S & string>(table: K, values: RecordOf<S, K>[], ttl?: number): Promise<void> {\n const expiresAt = ttl !== undefined ? Date.now() + ttl : undefined;\n\n for (const value of values) {\n const storageKey = encodeStorageKey(name, table, getRecordKey(schema, table, value));\n\n writeItem(table, storageKey, expiresAt === undefined ? { value } : { expiresAt, value });\n ownedKeys.add(storageKey);\n }\n },\n };\n\n return buildAdapterOps(schema, core, {\n onCrossTabMessage(notify) {\n if (typeof window === 'undefined' || typeof window.addEventListener !== 'function') {\n return undefined;\n }\n\n const listener = (event: StorageEvent) => {\n if (event.storageArea && event.storageArea !== resolvedStorage) return;\n\n if (event.key === null) {\n // storage.clear() from another tab — all keys are gone; purge ownedKeys\n ownedKeys.clear();\n\n for (const table of Object.keys(schema)) {\n notify(table as keyof S & string);\n }\n\n return;\n }\n\n const tableName = decodeStorageTableFromKey(name, event.key);\n\n if (tableName && Object.hasOwn(schema, tableName)) {\n if (event.newValue === null) {\n ownedKeys.delete(event.key);\n } else {\n ownedKeys.add(event.key);\n }\n\n notify(tableName as keyof S & string);\n }\n };\n\n window.addEventListener('storage', listener);\n\n return () => window.removeEventListener('storage', listener);\n },\n schema,\n validators,\n });\n}\n\nexport function createLocalStorage<S extends AnySchema>(options: WebStorageOptions<S>): VaultStore<S> {\n return createWebStorageAdapter({\n ...options,\n getStorage: () => (typeof window !== 'undefined' ? window.localStorage : localStorage),\n storageLabel: 'localStorage',\n });\n}\n\nexport function createSessionStorage<S extends AnySchema>(options: WebStorageOptions<S>): VaultStore<S> {\n return createWebStorageAdapter({\n ...options,\n getStorage: () => (typeof window !== 'undefined' ? window.sessionStorage : sessionStorage),\n storageLabel: 'sessionStorage',\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"webstorage.js","names":[],"sources":["../../src/adapters/webstorage.ts"],"sourcesContent":["import { buildKeyValueStore, type StorageBackend } from '../adapter-core';\nimport { decodeRecord, encodeRecord } from '../codec';\nimport { VaultError, VaultQuotaError } from '../errors';\nimport {\n decodeStorageTableFromKey,\n encodeDbPrefix,\n encodeStorageKey,\n encodeStorageTablePrefix,\n getRecordKey,\n} from '../internal';\nimport { isExpired, parseStored, type StoredRecord } from '../ttl';\nimport type { AnySchema, DurableStoreOptions, KeyOf, KeyValueVaultStore, RecordOf } from '../types';\n\n// Firefox historically threw 'NS_ERROR_DOM_QUOTA_REACHED'; modern browsers use the standard name.\nconst QUOTA_ERROR_NAMES = new Set(['QuotaExceededError', 'NS_ERROR_DOM_QUOTA_REACHED']);\n\ntype WebStorageOptions<S extends AnySchema> = DurableStoreOptions<S> & {\n name: string;\n /**\n * Called when localStorage/sessionStorage quota is exceeded on a write.\n * Return `'ignore'` to silently drop the write, or `'throw'` (default) to rethrow the error.\n */\n onQuotaExceeded?: (table: keyof S, error: VaultQuotaError) => 'ignore' | 'throw';\n};\n\nfunction createWebStorageAdapter<S extends AnySchema>(\n options: WebStorageOptions<S> & {\n getStorage: () => Storage;\n storageLabel: string;\n },\n): KeyValueVaultStore<S> {\n const { getStorage, name, onQuotaExceeded, schema, storageLabel, codecs } = options;\n\n if (!codecs) {\n throw new VaultError(`${storageLabel} requires codecs for durable persistence`);\n }\n\n let resolvedStorage: Storage;\n\n try {\n resolvedStorage = getStorage();\n } catch (cause) {\n throw new VaultError(\n `${storageLabel} is not available in this environment (private browsing or sandboxed iframe?)`,\n {\n cause,\n },\n );\n }\n\n const storage = (): Storage => resolvedStorage;\n\n const prefixMap = new Map(Object.keys(schema).map((table) => [table, encodeStorageTablePrefix(name, table)]));\n const getPrefix = (table: string): string => {\n const cached = prefixMap.get(table);\n\n if (!cached) throw new VaultError(`table \"${table}\" not in schema`);\n\n return cached;\n };\n\n const writeItem = (table: keyof S, storageKey: string, value: unknown): void => {\n try {\n storage().setItem(storageKey, JSON.stringify(value));\n } catch (error) {\n if (error instanceof DOMException && QUOTA_ERROR_NAMES.has(error.name)) {\n const wrappedError = new VaultQuotaError(`${storageLabel} quota exceeded while writing record`, {\n cause: error,\n });\n\n if (onQuotaExceeded?.(table, wrappedError) === 'ignore') return;\n\n throw wrappedError;\n }\n\n throw error;\n }\n };\n\n // Per-instance registry of storage keys owned by this namespace.\n // Table-wide operations resynchronize it so same-window adapters stay consistent.\n const ownedKeys = new Set<string>();\n\n const syncOwnedKeys = (): void => {\n const dbPrefix = encodeDbPrefix(name);\n ownedKeys.clear();\n\n for (let i = 0; i < resolvedStorage.length; i++) {\n const key = resolvedStorage.key(i);\n\n if (key?.startsWith(dbPrefix)) ownedKeys.add(key);\n }\n };\n\n syncOwnedKeys();\n\n /**\n * Reads a single entry without side effects. Returns the decoded live value,\n * or `undefined` if missing/expired/corrupt.\n *\n * Callers that want to evict stale entries must call `evict(storageKey)` explicitly.\n */\n const parseEntry = <T extends object>(table: keyof S, storageKey: string): T | undefined => {\n const raw = storage().getItem(storageKey);\n\n if (!raw) return undefined;\n\n let stored: StoredRecord<unknown> | undefined;\n try {\n stored = parseStored<unknown>(JSON.parse(raw) as unknown);\n } catch {\n return undefined;\n }\n\n if (!stored || isExpired(stored.expiresAt)) return undefined;\n\n try {\n return decodeRecord(codecs[table], stored.value) as unknown as T;\n } catch (error) {\n throw new VaultError(`validation failed for table \"${String(table)}\"`, { cause: error });\n }\n };\n\n /** Removes a stale/expired/corrupt entry from storage and the owned-keys registry. */\n const evict = (storageKey: string): void => {\n storage().removeItem(storageKey);\n ownedKeys.delete(storageKey);\n };\n\n const core: StorageBackend<S> = {\n async clear<K extends keyof S & string>(table: K): Promise<void> {\n syncOwnedKeys();\n const target = storage();\n const prefix = getPrefix(table);\n const toRemove: string[] = [];\n\n for (const key of ownedKeys) {\n if (key.startsWith(prefix)) toRemove.push(key);\n }\n\n for (const key of toRemove) {\n target.removeItem(key);\n ownedKeys.delete(key);\n }\n },\n\n async delete<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<boolean> {\n const storageKey = encodeStorageKey(name, table, key);\n const value = parseEntry<RecordOf<S, K>>(table, storageKey);\n\n if (value !== undefined) {\n evict(storageKey);\n\n return true;\n }\n\n if (ownedKeys.has(storageKey)) evict(storageKey);\n\n return false;\n },\n\n async get<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<RecordOf<S, K> | undefined> {\n const storageKey = encodeStorageKey(name, table, key);\n const value = parseEntry<RecordOf<S, K>>(table, storageKey);\n\n if (value === undefined && ownedKeys.has(storageKey)) evict(storageKey);\n\n return value;\n },\n\n async getAll<K extends keyof S & string>(table: K): Promise<RecordOf<S, K>[]> {\n syncOwnedKeys();\n const records: RecordOf<S, K>[] = [];\n const expiredKeys: string[] = [];\n const prefix = getPrefix(table);\n\n for (const storageKey of ownedKeys) {\n if (!storageKey.startsWith(prefix)) continue;\n\n const value = parseEntry<RecordOf<S, K>>(table, storageKey);\n\n if (value === undefined) {\n expiredKeys.push(storageKey);\n continue;\n }\n\n records.push(value);\n }\n\n for (const storageKey of expiredKeys) {\n evict(storageKey);\n }\n\n return records;\n },\n\n async pruneExpiredInTable<K extends keyof S & string>(table: K): Promise<number> {\n syncOwnedKeys();\n const prefix = getPrefix(table);\n const expiredKeys: string[] = [];\n\n for (const storageKey of ownedKeys) {\n if (!storageKey.startsWith(prefix)) continue;\n\n const raw = storage().getItem(storageKey);\n\n if (raw === null) {\n expiredKeys.push(storageKey);\n continue;\n }\n\n try {\n const stored = parseStored(JSON.parse(raw) as unknown);\n\n if (!stored || isExpired(stored.expiresAt)) {\n expiredKeys.push(storageKey);\n }\n } catch {\n expiredKeys.push(storageKey);\n }\n }\n\n for (const storageKey of expiredKeys) {\n evict(storageKey);\n }\n\n return expiredKeys.length;\n },\n\n async put<K extends keyof S & string>(table: K, value: RecordOf<S, K>, ttl?: number): Promise<void> {\n const storageKey = encodeStorageKey(name, table, getRecordKey(schema, table, value));\n const expiresAt = ttl !== undefined ? Date.now() + ttl : undefined;\n const encoded = encodeRecord(codecs[table], value);\n\n writeItem(table, storageKey, expiresAt === undefined ? { value: encoded } : { expiresAt, value: encoded });\n ownedKeys.add(storageKey);\n },\n\n async putAll<K extends keyof S & string>(table: K, values: RecordOf<S, K>[], ttl?: number): Promise<void> {\n const expiresAt = ttl !== undefined ? Date.now() + ttl : undefined;\n\n for (const value of values) {\n const storageKey = encodeStorageKey(name, table, getRecordKey(schema, table, value));\n const encoded = encodeRecord(codecs[table], value);\n\n writeItem(table, storageKey, expiresAt === undefined ? { value: encoded } : { expiresAt, value: encoded });\n ownedKeys.add(storageKey);\n }\n },\n };\n\n return buildKeyValueStore(schema, core, {\n codecs,\n onCrossTabMessage(notify) {\n if (typeof window === 'undefined' || typeof window.addEventListener !== 'function') {\n return undefined;\n }\n\n const listener = (event: StorageEvent) => {\n if (event.storageArea && event.storageArea !== resolvedStorage) return;\n\n if (event.key === null) {\n // storage.clear() from another tab — all keys are gone; purge ownedKeys\n ownedKeys.clear();\n\n for (const table of Object.keys(schema)) {\n notify(table as keyof S & string);\n }\n\n return;\n }\n\n const tableName = decodeStorageTableFromKey(name, event.key);\n\n if (tableName && Object.hasOwn(schema, tableName)) {\n if (event.newValue === null) {\n ownedKeys.delete(event.key);\n } else {\n ownedKeys.add(event.key);\n }\n\n notify(tableName as keyof S & string);\n }\n };\n\n window.addEventListener('storage', listener);\n\n return () => window.removeEventListener('storage', listener);\n },\n schema,\n });\n}\n\nexport function createLocalStorage<S extends AnySchema>(options: WebStorageOptions<S>): KeyValueVaultStore<S> {\n return createWebStorageAdapter({\n ...options,\n getStorage: () => (typeof window !== 'undefined' ? window.localStorage : localStorage),\n storageLabel: 'localStorage',\n });\n}\n\nexport function createSessionStorage<S extends AnySchema>(options: WebStorageOptions<S>): KeyValueVaultStore<S> {\n return createWebStorageAdapter({\n ...options,\n getStorage: () => (typeof window !== 'undefined' ? window.sessionStorage : sessionStorage),\n storageLabel: 'sessionStorage',\n });\n}\n"],"mappings":"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"}
package/dist/codec.cjs ADDED
@@ -0,0 +1,2 @@
1
+ var e=e=>`encode`in e&&`decode`in e,t=(t,n)=>e(t)?t.encode(n):n,n=(t,n)=>e(t)?t.decode(n):t.parse(n),r=(t,n)=>e(t)?t.decode(t.encode(n)):t.parse(n);exports.decodeRecord=n,exports.encodeRecord=t,exports.validateRecord=r;
2
+ //# sourceMappingURL=codec.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec.cjs","names":[],"sources":["../src/codec.ts"],"sourcesContent":["import type { CodecInput, RecordCodec } from './types';\n\nconst isCodec = <T>(input: CodecInput<T>): input is RecordCodec<T> => 'encode' in input && 'decode' in input;\n\nexport const encodeRecord = <T>(input: CodecInput<T>, value: T): unknown =>\n isCodec(input) ? input.encode(value) : value;\n\nexport const decodeRecord = <T>(input: CodecInput<T>, value: unknown): T =>\n isCodec(input) ? input.decode(value) : input.parse(value);\n\nexport const validateRecord = <T>(input: CodecInput<T>, value: T): T =>\n isCodec(input) ? input.decode(input.encode(value)) : input.parse(value);\n"],"mappings":"AAEA,IAAM,EAAc,GAAkD,WAAY,GAAS,WAAY,EAE1F,GAAmB,EAAsB,IACpD,EAAQ,CAAK,EAAI,EAAM,OAAO,CAAK,EAAI,EAE5B,GAAmB,EAAsB,IACpD,EAAQ,CAAK,EAAI,EAAM,OAAO,CAAK,EAAI,EAAM,MAAM,CAAK,EAE7C,GAAqB,EAAsB,IACtD,EAAQ,CAAK,EAAI,EAAM,OAAO,EAAM,OAAO,CAAK,CAAC,EAAI,EAAM,MAAM,CAAK"}
@@ -0,0 +1,5 @@
1
+ import type { CodecInput } from './types';
2
+ export declare const encodeRecord: <T>(input: CodecInput<T>, value: T) => unknown;
3
+ export declare const decodeRecord: <T>(input: CodecInput<T>, value: unknown) => T;
4
+ export declare const validateRecord: <T>(input: CodecInput<T>, value: T) => T;
5
+ //# sourceMappingURL=codec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../src/codec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,SAAS,CAAC;AAIvD,eAAO,MAAM,YAAY,GAAI,CAAC,EAAE,OAAO,UAAU,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,KAAG,OACnB,CAAC;AAE/C,eAAO,MAAM,YAAY,GAAI,CAAC,EAAE,OAAO,UAAU,CAAC,CAAC,CAAC,EAAE,OAAO,OAAO,KAAG,CACZ,CAAC;AAE5D,eAAO,MAAM,cAAc,GAAI,CAAC,EAAE,OAAO,UAAU,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,KAAG,CACM,CAAC"}
package/dist/codec.js ADDED
@@ -0,0 +1,6 @@
1
+ //#region src/codec.ts
2
+ var e = (e) => "encode" in e && "decode" in e, t = (t, n) => e(t) ? t.encode(n) : n, n = (t, n) => e(t) ? t.decode(n) : t.parse(n), r = (t, n) => e(t) ? t.decode(t.encode(n)) : t.parse(n);
3
+ //#endregion
4
+ export { n as decodeRecord, t as encodeRecord, r as validateRecord };
5
+
6
+ //# sourceMappingURL=codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec.js","names":[],"sources":["../src/codec.ts"],"sourcesContent":["import type { CodecInput, RecordCodec } from './types';\n\nconst isCodec = <T>(input: CodecInput<T>): input is RecordCodec<T> => 'encode' in input && 'decode' in input;\n\nexport const encodeRecord = <T>(input: CodecInput<T>, value: T): unknown =>\n isCodec(input) ? input.encode(value) : value;\n\nexport const decodeRecord = <T>(input: CodecInput<T>, value: unknown): T =>\n isCodec(input) ? input.decode(value) : input.parse(value);\n\nexport const validateRecord = <T>(input: CodecInput<T>, value: T): T =>\n isCodec(input) ? input.decode(input.encode(value)) : input.parse(value);\n"],"mappings":";AAEA,IAAM,KAAc,MAAkD,YAAY,KAAS,YAAY,GAE1F,KAAmB,GAAsB,MACpD,EAAQ,CAAK,IAAI,EAAM,OAAO,CAAK,IAAI,GAE5B,KAAmB,GAAsB,MACpD,EAAQ,CAAK,IAAI,EAAM,OAAO,CAAK,IAAI,EAAM,MAAM,CAAK,GAE7C,KAAqB,GAAsB,MACtD,EAAQ,CAAK,IAAI,EAAM,OAAO,EAAM,OAAO,CAAK,CAAC,IAAI,EAAM,MAAM,CAAK"}
package/dist/errors.cjs CHANGED
@@ -1,2 +1,2 @@
1
- var e=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},t=class extends e{constructor(e=`adapter is disposed`,t){super(e,t)}},n=class extends e{},r=class extends e{},i=class extends e{};exports.VaultDisposedError=t,exports.VaultError=e,exports.VaultMigrationError=i,exports.VaultQuotaError=r,exports.VaultScopeError=n;
1
+ var e=class extends Error{static errorName=`VaultError`;constructor(e,t){super(e,t),this.name=new.target.errorName,Object.setPrototypeOf(this,new.target.prototype)}},t=class extends e{static errorName=`VaultDisposedError`;constructor(e=`adapter is disposed`,t){super(e,t)}},n=class extends e{static errorName=`VaultScopeError`},r=class extends e{static errorName=`VaultQuotaError`},i=class extends e{static errorName=`VaultMigrationError`};exports.VaultDisposedError=t,exports.VaultError=e,exports.VaultMigrationError=i,exports.VaultQuotaError=r,exports.VaultScopeError=n;
2
2
  //# sourceMappingURL=errors.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.cjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Base class for all vault errors. Catch with `instanceof VaultError` to\n * handle any vault-originated error regardless of its specific subtype.\n */\nexport class VaultError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n // Ensures `instanceof` works correctly when transpiled to ES5.\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when an operation is attempted on a disposed adapter or observer hub. */\nexport class VaultDisposedError extends VaultError {\n constructor(message = 'adapter is disposed', opts?: ErrorOptions) {\n super(message, opts);\n }\n}\n\n/** Thrown when a `batch()` callback accesses a table not declared in the scope. */\nexport class VaultScopeError extends VaultError {}\n\n/** Thrown when a WebStorage write exceeds the storage quota. */\nexport class VaultQuotaError extends VaultError {}\n\n/** Thrown when an IndexedDB `onupgradeneeded` migration callback throws. */\nexport class VaultMigrationError extends VaultError {}\n"],"mappings":"AAIA,IAAa,EAAb,cAAgC,KAAM,CACpC,YAAY,EAAiB,EAAqB,CAChD,MAAM,EAAS,CAAI,EACnB,KAAK,KAAO,WAAW,KAEvB,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CACF,EAGa,EAAb,cAAwC,CAAW,CACjD,YAAY,EAAU,sBAAuB,EAAqB,CAChE,MAAM,EAAS,CAAI,CACrB,CACF,EAGa,EAAb,cAAqC,CAAW,CAAC,EAGpC,EAAb,cAAqC,CAAW,CAAC,EAGpC,EAAb,cAAyC,CAAW,CAAC"}
1
+ {"version":3,"file":"errors.cjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Base class for all vault errors. Catch with `instanceof VaultError` to\n * handle any vault-originated error regardless of its specific subtype.\n */\nexport class VaultError extends Error {\n protected static readonly errorName: string = 'VaultError';\n\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = (new.target as typeof VaultError).errorName;\n // Ensures `instanceof` works correctly when transpiled to ES5.\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when an operation is attempted on a disposed adapter or observer hub. */\nexport class VaultDisposedError extends VaultError {\n protected static override readonly errorName = 'VaultDisposedError';\n\n constructor(message = 'adapter is disposed', opts?: ErrorOptions) {\n super(message, opts);\n }\n}\n\n/** Thrown when a `batch()` callback accesses a table not declared in the scope. */\nexport class VaultScopeError extends VaultError {\n protected static override readonly errorName = 'VaultScopeError';\n}\n\n/** Thrown when a WebStorage write exceeds the storage quota. */\nexport class VaultQuotaError extends VaultError {\n protected static override readonly errorName = 'VaultQuotaError';\n}\n\n/** Thrown when an IndexedDB `onupgradeneeded` migration callback throws. */\nexport class VaultMigrationError extends VaultError {\n protected static override readonly errorName = 'VaultMigrationError';\n}\n"],"mappings":"AAIA,IAAa,EAAb,cAAgC,KAAM,CACpC,OAA0B,UAAoB,aAE9C,YAAY,EAAiB,EAAqB,CAChD,MAAM,EAAS,CAAI,EACnB,KAAK,KAAQ,WAAiC,UAE9C,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CACF,EAGa,EAAb,cAAwC,CAAW,CACjD,OAAmC,UAAY,qBAE/C,YAAY,EAAU,sBAAuB,EAAqB,CAChE,MAAM,EAAS,CAAI,CACrB,CACF,EAGa,EAAb,cAAqC,CAAW,CAC9C,OAAmC,UAAY,iBACjD,EAGa,EAAb,cAAqC,CAAW,CAC9C,OAAmC,UAAY,iBACjD,EAGa,EAAb,cAAyC,CAAW,CAClD,OAAmC,UAAY,qBACjD"}
package/dist/errors.d.ts CHANGED
@@ -3,19 +3,24 @@
3
3
  * handle any vault-originated error regardless of its specific subtype.
4
4
  */
5
5
  export declare class VaultError extends Error {
6
+ protected static readonly errorName: string;
6
7
  constructor(message: string, opts?: ErrorOptions);
7
8
  }
8
9
  /** Thrown when an operation is attempted on a disposed adapter or observer hub. */
9
10
  export declare class VaultDisposedError extends VaultError {
11
+ protected static readonly errorName = "VaultDisposedError";
10
12
  constructor(message?: string, opts?: ErrorOptions);
11
13
  }
12
14
  /** Thrown when a `batch()` callback accesses a table not declared in the scope. */
13
15
  export declare class VaultScopeError extends VaultError {
16
+ protected static readonly errorName = "VaultScopeError";
14
17
  }
15
18
  /** Thrown when a WebStorage write exceeds the storage quota. */
16
19
  export declare class VaultQuotaError extends VaultError {
20
+ protected static readonly errorName = "VaultQuotaError";
17
21
  }
18
22
  /** Thrown when an IndexedDB `onupgradeneeded` migration callback throws. */
19
23
  export declare class VaultMigrationError extends VaultError {
24
+ protected static readonly errorName = "VaultMigrationError";
20
25
  }
21
26
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;CAMjD;AAED,mFAAmF;AACnF,qBAAa,kBAAmB,SAAQ,UAAU;gBACpC,OAAO,SAAwB,EAAE,IAAI,CAAC,EAAE,YAAY;CAGjE;AAED,mFAAmF;AACnF,qBAAa,eAAgB,SAAQ,UAAU;CAAG;AAElD,gEAAgE;AAChE,qBAAa,eAAgB,SAAQ,UAAU;CAAG;AAElD,4EAA4E;AAC5E,qBAAa,mBAAoB,SAAQ,UAAU;CAAG"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,UAAW,SAAQ,KAAK;IACnC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAgB;gBAE/C,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;CAMjD;AAED,mFAAmF;AACnF,qBAAa,kBAAmB,SAAQ,UAAU;IAChD,0BAAmC,SAAS,wBAAwB;gBAExD,OAAO,SAAwB,EAAE,IAAI,CAAC,EAAE,YAAY;CAGjE;AAED,mFAAmF;AACnF,qBAAa,eAAgB,SAAQ,UAAU;IAC7C,0BAAmC,SAAS,qBAAqB;CAClE;AAED,gEAAgE;AAChE,qBAAa,eAAgB,SAAQ,UAAU;IAC7C,0BAAmC,SAAS,qBAAqB;CAClE;AAED,4EAA4E;AAC5E,qBAAa,mBAAoB,SAAQ,UAAU;IACjD,0BAAmC,SAAS,yBAAyB;CACtE"}
package/dist/errors.js CHANGED
@@ -1,13 +1,21 @@
1
1
  //#region src/errors.ts
2
2
  var e = class extends Error {
3
+ static errorName = "VaultError";
3
4
  constructor(e, t) {
4
- super(e, t), this.name = new.target.name, Object.setPrototypeOf(this, new.target.prototype);
5
+ super(e, t), this.name = new.target.errorName, Object.setPrototypeOf(this, new.target.prototype);
5
6
  }
6
7
  }, t = class extends e {
8
+ static errorName = "VaultDisposedError";
7
9
  constructor(e = "adapter is disposed", t) {
8
10
  super(e, t);
9
11
  }
10
- }, n = class extends e {}, r = class extends e {}, i = class extends e {};
12
+ }, n = class extends e {
13
+ static errorName = "VaultScopeError";
14
+ }, r = class extends e {
15
+ static errorName = "VaultQuotaError";
16
+ }, i = class extends e {
17
+ static errorName = "VaultMigrationError";
18
+ };
11
19
  //#endregion
12
20
  export { t as VaultDisposedError, e as VaultError, i as VaultMigrationError, r as VaultQuotaError, n as VaultScopeError };
13
21
 
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Base class for all vault errors. Catch with `instanceof VaultError` to\n * handle any vault-originated error regardless of its specific subtype.\n */\nexport class VaultError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n // Ensures `instanceof` works correctly when transpiled to ES5.\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when an operation is attempted on a disposed adapter or observer hub. */\nexport class VaultDisposedError extends VaultError {\n constructor(message = 'adapter is disposed', opts?: ErrorOptions) {\n super(message, opts);\n }\n}\n\n/** Thrown when a `batch()` callback accesses a table not declared in the scope. */\nexport class VaultScopeError extends VaultError {}\n\n/** Thrown when a WebStorage write exceeds the storage quota. */\nexport class VaultQuotaError extends VaultError {}\n\n/** Thrown when an IndexedDB `onupgradeneeded` migration callback throws. */\nexport class VaultMigrationError extends VaultError {}\n"],"mappings":";AAIA,IAAa,IAAb,cAAgC,MAAM;CACpC,YAAY,GAAiB,GAAqB;EAIhD,AAHA,MAAM,GAAS,CAAI,GACnB,KAAK,OAAO,WAAW,MAEvB,OAAO,eAAe,MAAM,WAAW,SAAS;CAClD;AACF,GAGa,IAAb,cAAwC,EAAW;CACjD,YAAY,IAAU,uBAAuB,GAAqB;EAChE,MAAM,GAAS,CAAI;CACrB;AACF,GAGa,IAAb,cAAqC,EAAW,CAAC,GAGpC,IAAb,cAAqC,EAAW,CAAC,GAGpC,IAAb,cAAyC,EAAW,CAAC"}
1
+ {"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Base class for all vault errors. Catch with `instanceof VaultError` to\n * handle any vault-originated error regardless of its specific subtype.\n */\nexport class VaultError extends Error {\n protected static readonly errorName: string = 'VaultError';\n\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = (new.target as typeof VaultError).errorName;\n // Ensures `instanceof` works correctly when transpiled to ES5.\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when an operation is attempted on a disposed adapter or observer hub. */\nexport class VaultDisposedError extends VaultError {\n protected static override readonly errorName = 'VaultDisposedError';\n\n constructor(message = 'adapter is disposed', opts?: ErrorOptions) {\n super(message, opts);\n }\n}\n\n/** Thrown when a `batch()` callback accesses a table not declared in the scope. */\nexport class VaultScopeError extends VaultError {\n protected static override readonly errorName = 'VaultScopeError';\n}\n\n/** Thrown when a WebStorage write exceeds the storage quota. */\nexport class VaultQuotaError extends VaultError {\n protected static override readonly errorName = 'VaultQuotaError';\n}\n\n/** Thrown when an IndexedDB `onupgradeneeded` migration callback throws. */\nexport class VaultMigrationError extends VaultError {\n protected static override readonly errorName = 'VaultMigrationError';\n}\n"],"mappings":";AAIA,IAAa,IAAb,cAAgC,MAAM;CACpC,OAA0B,YAAoB;CAE9C,YAAY,GAAiB,GAAqB;EAIhD,AAHA,MAAM,GAAS,CAAI,GACnB,KAAK,OAAQ,WAAiC,WAE9C,OAAO,eAAe,MAAM,WAAW,SAAS;CAClD;AACF,GAGa,IAAb,cAAwC,EAAW;CACjD,OAAmC,YAAY;CAE/C,YAAY,IAAU,uBAAuB,GAAqB;EAChE,MAAM,GAAS,CAAI;CACrB;AACF,GAGa,IAAb,cAAqC,EAAW;CAC9C,OAAmC,YAAY;AACjD,GAGa,IAAb,cAAqC,EAAW;CAC9C,OAAmC,YAAY;AACjD,GAGa,IAAb,cAAyC,EAAW;CAClD,OAAmC,YAAY;AACjD"}
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./errors.cjs"),t=require("./ttl.cjs"),n=require("./types.cjs");exports.VaultDisposedError=e.VaultDisposedError,exports.VaultError=e.VaultError,exports.VaultMigrationError=e.VaultMigrationError,exports.VaultQuotaError=e.VaultQuotaError,exports.VaultScopeError=e.VaultScopeError,exports.isExpired=t.isExpired,exports.table=n.table,exports.ttl=t.ttl;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./errors.cjs"),t=require("./ttl.cjs"),n=require("./adapter-core.cjs"),r=require("./types.cjs");exports.VaultDisposedError=e.VaultDisposedError,exports.VaultError=e.VaultError,exports.VaultMigrationError=e.VaultMigrationError,exports.VaultQuotaError=e.VaultQuotaError,exports.VaultScopeError=e.VaultScopeError,exports.count=n.count,exports.deleteMany=n.deleteMany,exports.getMany=n.getMany,exports.has=n.has,exports.isEmpty=n.isEmpty,exports.isExpired=t.isExpired,exports.keys=n.keys,exports.table=r.table,exports.ttl=t.ttl,exports.update=n.update,exports.upsert=n.upsert,exports.validatorCodec=r.validatorCodec;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
+ export { count, deleteMany, getMany, has, isEmpty, keys, update, upsert, } from './adapter-core';
1
2
  export { VaultDisposedError, VaultError, VaultMigrationError, VaultQuotaError, VaultScopeError } from './errors';
2
3
  export type { QueryBuilder } from './query';
3
4
  export { isExpired, ttl } from './ttl';
4
- export type { AnySchema, BaseAdapterOptions, KeyOf, Observer, RecordOf, RecordValidator, SchemaEntry, TableValidators, TransactionalVaultStore, Unsubscribe, VaultKey, VaultStore, } from './types';
5
- export { table } from './types';
5
+ export type { AnySchema, CodecInput, DocumentVaultStore, DurableStoreOptions, KeyOf, KeyValueVaultStore, MemoryStoreOptions, Observer, RecordCodec, RecordOf, RecordParser, SchemaEntry, TableCodecs, TransactionContext, Unsubscribe, VaultConveniences, VaultKey, } from './types';
6
+ export { table, validatorCodec } from './types';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,mBAAmB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AACjH,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AACvC,YAAY,EACV,SAAS,EACT,kBAAkB,EAClB,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,WAAW,EACX,eAAe,EACf,uBAAuB,EACvB,WAAW,EACX,QAAQ,EACR,UAAU,GACX,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,UAAU,EACV,OAAO,EACP,GAAG,EACH,OAAO,EACP,IAAI,EACJ,MAAM,EACN,MAAM,GACP,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,mBAAmB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AACjH,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AACvC,YAAY,EACV,SAAS,EACT,UAAU,EACV,kBAAkB,EAClB,mBAAmB,EACnB,KAAK,EACL,kBAAkB,EAClB,kBAAkB,EAClB,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,QAAQ,GACT,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { VaultDisposedError as e, VaultError as t, VaultMigrationError as n, VaultQuotaError as r, VaultScopeError as i } from "./errors.js";
2
2
  import { isExpired as a, ttl as o } from "./ttl.js";
3
- import { table as s } from "./types.js";
4
- export { e as VaultDisposedError, t as VaultError, n as VaultMigrationError, r as VaultQuotaError, i as VaultScopeError, a as isExpired, s as table, o as ttl };
3
+ import { count as s, deleteMany as c, getMany as l, has as u, isEmpty as d, keys as f, update as p, upsert as m } from "./adapter-core.js";
4
+ import { table as h, validatorCodec as g } from "./types.js";
5
+ export { e as VaultDisposedError, t as VaultError, n as VaultMigrationError, r as VaultQuotaError, i as VaultScopeError, s as count, c as deleteMany, l as getMany, u as has, d as isEmpty, a as isExpired, f as keys, h as table, o as ttl, p as update, m as upsert, g as validatorCodec };
@@ -1,4 +1,4 @@
1
- export type { IndexedDbVaultStore, MigrationContext, MigrationFn, MigrationStep, } from './adapters/indexeddb';
1
+ export type { MigrationContext, MigrationFn, MigrationStep } from './adapters/indexeddb';
2
2
  export { createIndexedDB, defineMigration } from './adapters/indexeddb';
3
3
  export type { TransactionContext } from './types';
4
4
  //# sourceMappingURL=indexeddb.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"indexeddb.d.ts","sourceRoot":"","sources":["../src/indexeddb.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,mBAAmB,EACnB,gBAAgB,EAChB,WAAW,EACX,aAAa,GACd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACxE,YAAY,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"indexeddb.d.ts","sourceRoot":"","sources":["../src/indexeddb.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACzF,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACxE,YAAY,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC"}
package/dist/internal.cjs CHANGED
@@ -1,2 +1,2 @@
1
- const e=require("./errors.cjs");var t=`\0`;function n(t){if(typeof t==`number`){if(!Number.isFinite(t))throw new e.VaultError(`primary key must be a finite number, received ${String(t)}`);return`n:${String(t)}`}return`s:${encodeURIComponent(t)}`}function r(e){return`${encodeURIComponent(e)}${t}`}function i(e,r,i){return`${encodeURIComponent(e)}${t}${encodeURIComponent(r)}${t}${n(i)}`}function a(e,n){return`${encodeURIComponent(e)}${t}${encodeURIComponent(n)}${t}`}function o(e,n){if(!n)return;let i=r(e);if(!n.startsWith(i))return;let a=n.slice(i.length),o=a.indexOf(t);if(o!==-1)try{return decodeURIComponent(a.slice(0,o))}catch{return}}function s(t){let n=new Map,r=!1,i=e=>{if(r)return;let i=n.get(e);!i||i.size===0||t(e).then(t=>{if(r)return;let i=n.get(e);if(!(!i||i.size===0))for(let e of i)try{e(t)}catch{}}).catch(()=>{})};return{dispose:()=>{r=!0,n.clear()},notify:i,observe:(t,a,{immediate:o=!0,signal:s}={})=>{if(r)throw new e.VaultDisposedError(`observer hub is disposed`);if(s?.aborted)return()=>{};let c=a,l=n.get(t)??new Set;n.set(t,l),l.add(c),o&&i(t);let u=()=>{let e=n.get(t);e&&(e.delete(c),e.size===0&&n.delete(t))};return s?.addEventListener(`abort`,u,{once:!0}),u}}}function c(t,n,r){let i=String(t[n].key),a=r[i];if(typeof a!=`number`&&typeof a!=`string`)throw new e.VaultError(`record in table "${String(n)}" must have a string or finite-number key at "${i}"`);if(typeof a==`number`&&!Number.isFinite(a))throw new e.VaultError(`record in table "${String(n)}" must have a finite-number key at "${i}"`);return a}exports.createObserverHub=s,exports.decodeStorageTableFromKey=o,exports.encodeDbPrefix=r,exports.encodeStorageKey=i,exports.encodeStorageTablePrefix=a,exports.encodeVaultKey=n,exports.getRecordKey=c;
1
+ const e=require("./errors.cjs");var t=`\0`;function n(t){if(typeof t==`number`){if(!Number.isFinite(t))throw new e.VaultError(`primary key must be a finite number, received ${String(t)}`);return`n:${String(t)}`}return`s:${encodeURIComponent(t)}`}function r(e){return`${encodeURIComponent(e)}${t}`}function i(e,r,i){return`${encodeURIComponent(e)}${t}${encodeURIComponent(r)}${t}${n(i)}`}function a(e,n){return`${encodeURIComponent(e)}${t}${encodeURIComponent(n)}${t}`}function o(e,n){if(!n)return;let i=r(e);if(!n.startsWith(i))return;let a=n.slice(i.length),o=a.indexOf(t);if(o!==-1)try{return decodeURIComponent(a.slice(0,o))}catch{return}}function s(t){let n=new Map,r=new Map,i=!1,a=e=>{if(i)return;let a=(r.get(e)??0)+1;r.set(e,a);let o=n.get(e);o&&o.size!==0&&t(e).then(t=>{if(i||r.get(e)!==a)return;let o=n.get(e);if(o&&o.size!==0)for(let e of o)try{e(t)}catch{}}).catch(()=>{})};return{dispose:()=>{i=!0,n.clear(),r.clear()},notify:a,observe:(t,r,{immediate:o=!0,signal:s}={})=>{if(i)throw new e.VaultDisposedError(`observer hub is disposed`);if(s?.aborted)return()=>{};let c=r,l=n.get(t)??new Set;n.set(t,l),l.add(c),o&&a(t);let u=()=>{s?.removeEventListener(`abort`,u);let e=n.get(t);e&&(e.delete(c),e.size===0&&n.delete(t))};return s?.addEventListener(`abort`,u,{once:!0}),u}}}function c(t,n,r){let i=String(t[n].key),a=r[i];if(typeof a!=`number`&&typeof a!=`string`)throw new e.VaultError(`record in table "${String(n)}" must have a string or finite-number key at "${i}"`);if(typeof a==`number`&&!Number.isFinite(a))throw new e.VaultError(`record in table "${String(n)}" must have a finite-number key at "${i}"`);return a}exports.createObserverHub=s,exports.decodeStorageTableFromKey=o,exports.encodeDbPrefix=r,exports.encodeStorageKey=i,exports.encodeStorageTablePrefix=a,exports.encodeVaultKey=n,exports.getRecordKey=c;
2
2
  //# sourceMappingURL=internal.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"internal.cjs","names":[],"sources":["../src/internal.ts"],"sourcesContent":["import { VaultDisposedError, VaultError } from './errors';\nimport type { AnySchema, KeyOf, RecordOf, VaultKey } from './types';\n\ntype ObserverListener<T> = (records: T[]) => void;\n\nconst SEP = '\\x00';\n\n/**\n * Type-tagged keys make `1` and `'1'` distinct in string-keyed adapters while\n * keeping the same portable primary-key contract as IndexedDB.\n */\nexport function encodeVaultKey(key: VaultKey): string {\n if (typeof key === 'number') {\n if (!Number.isFinite(key)) throw new VaultError(`primary key must be a finite number, received ${String(key)}`);\n\n return `n:${String(key)}`;\n }\n\n return `s:${encodeURIComponent(key)}`;\n}\n\nexport function encodeDbPrefix(dbName: string): string {\n return `${encodeURIComponent(dbName)}${SEP}`;\n}\n\nexport function encodeStorageKey(dbName: string, table: string, key: VaultKey): string {\n return `${encodeURIComponent(dbName)}${SEP}${encodeURIComponent(table)}${SEP}${encodeVaultKey(key)}`;\n}\n\nexport function encodeStorageTablePrefix(dbName: string, table: string): string {\n return `${encodeURIComponent(dbName)}${SEP}${encodeURIComponent(table)}${SEP}`;\n}\n\nexport function decodeStorageTableFromKey(dbName: string, storageKey: string | null): string | undefined {\n if (!storageKey) return undefined;\n\n const prefix = encodeDbPrefix(dbName);\n\n if (!storageKey.startsWith(prefix)) return undefined;\n\n const tail = storageKey.slice(prefix.length);\n const end = tail.indexOf(SEP);\n\n if (end === -1) return undefined;\n\n try {\n return decodeURIComponent(tail.slice(0, end));\n } catch {\n return undefined;\n }\n}\n\n/** `observe()` is Vault's single reactivity primitive: a snapshot now, then on mutations. */\nexport function createObserverHub<S extends AnySchema>(\n getAll: <K extends keyof S & string>(table: K) => Promise<RecordOf<S, K>[]>,\n) {\n const observers = new Map<string, Set<ObserverListener<unknown>>>();\n let disposed = false;\n\n const notify = <K extends keyof S & string>(table: K): void => {\n if (disposed) return;\n\n const listeners = observers.get(table);\n\n if (!listeners || listeners.size === 0) return;\n\n void getAll(table)\n .then((records) => {\n if (disposed) return;\n\n const current = observers.get(table);\n\n if (!current || current.size === 0) return;\n\n for (const listener of current) {\n try {\n listener(records as unknown[]);\n } catch {\n /* observer listener errors are intentionally swallowed */\n }\n }\n })\n .catch(() => {\n /* observer source errors are intentionally swallowed */\n });\n };\n\n const observe = <K extends keyof S & string>(\n table: K,\n listener: (records: RecordOf<S, K>[]) => void,\n { immediate = true, signal }: { immediate?: boolean; signal?: AbortSignal } = {},\n ): (() => void) => {\n if (disposed) throw new VaultDisposedError('observer hub is disposed');\n\n if (signal?.aborted) return () => {};\n\n const wrapped = listener as ObserverListener<unknown>;\n const listeners = observers.get(table) ?? new Set<ObserverListener<unknown>>();\n\n observers.set(table, listeners);\n listeners.add(wrapped);\n\n if (immediate) notify(table);\n\n const stop = (): void => {\n const current = observers.get(table);\n\n if (!current) return;\n\n current.delete(wrapped);\n\n if (current.size === 0) observers.delete(table);\n };\n\n signal?.addEventListener('abort', stop, { once: true });\n\n return stop;\n };\n\n return {\n dispose: () => {\n disposed = true;\n observers.clear();\n },\n notify,\n observe,\n };\n}\n\nexport function getRecordKey<S extends AnySchema, K extends keyof S>(\n schema: S,\n table: K,\n value: RecordOf<S, K>,\n): KeyOf<S, K> {\n const keyField = String(schema[table].key);\n const keyValue = (value as Record<string, unknown>)[keyField];\n\n if (typeof keyValue !== 'number' && typeof keyValue !== 'string') {\n throw new VaultError(`record in table \"${String(table)}\" must have a string or finite-number key at \"${keyField}\"`);\n }\n\n if (typeof keyValue === 'number' && !Number.isFinite(keyValue)) {\n throw new VaultError(`record in table \"${String(table)}\" must have a finite-number key at \"${keyField}\"`);\n }\n\n return keyValue as KeyOf<S, K>;\n}\n"],"mappings":"gCAKA,IAAM,EAAM,KAMZ,SAAgB,EAAe,EAAuB,CACpD,GAAI,OAAO,GAAQ,SAAU,CAC3B,GAAI,CAAC,OAAO,SAAS,CAAG,EAAG,MAAM,IAAI,EAAA,WAAW,iDAAiD,OAAO,CAAG,GAAG,EAE9G,MAAO,KAAK,OAAO,CAAG,GACxB,CAEA,MAAO,KAAK,mBAAmB,CAAG,GACpC,CAEA,SAAgB,EAAe,EAAwB,CACrD,MAAO,GAAG,mBAAmB,CAAM,IAAI,GACzC,CAEA,SAAgB,EAAiB,EAAgB,EAAe,EAAuB,CACrF,MAAO,GAAG,mBAAmB,CAAM,IAAI,IAAM,mBAAmB,CAAK,IAAI,IAAM,EAAe,CAAG,GACnG,CAEA,SAAgB,EAAyB,EAAgB,EAAuB,CAC9E,MAAO,GAAG,mBAAmB,CAAM,IAAI,IAAM,mBAAmB,CAAK,IAAI,GAC3E,CAEA,SAAgB,EAA0B,EAAgB,EAA+C,CACvG,GAAI,CAAC,EAAY,OAEjB,IAAM,EAAS,EAAe,CAAM,EAEpC,GAAI,CAAC,EAAW,WAAW,CAAM,EAAG,OAEpC,IAAM,EAAO,EAAW,MAAM,EAAO,MAAM,EACrC,EAAM,EAAK,QAAQ,CAAG,EAExB,OAAQ,GAEZ,GAAI,CACF,OAAO,mBAAmB,EAAK,MAAM,EAAG,CAAG,CAAC,CAC9C,MAAQ,CACN,MACF,CACF,CAGA,SAAgB,EACd,EACA,CACA,IAAM,EAAY,IAAI,IAClB,EAAW,GAET,EAAsC,GAAmB,CAC7D,GAAI,EAAU,OAEd,IAAM,EAAY,EAAU,IAAI,CAAK,EAEjC,CAAC,GAAa,EAAU,OAAS,GAErC,EAAY,CAAK,CAAC,CACf,KAAM,GAAY,CACjB,GAAI,EAAU,OAEd,IAAM,EAAU,EAAU,IAAI,CAAK,EAE/B,MAAC,GAAW,EAAQ,OAAS,GAEjC,IAAK,IAAM,KAAY,EACrB,GAAI,CACF,EAAS,CAAoB,CAC/B,MAAQ,CAER,CAEJ,CAAC,CAAC,CACD,UAAY,CAEb,CAAC,CACL,EAkCA,MAAO,CACL,YAAe,CACb,EAAW,GACX,EAAU,MAAM,CAClB,EACA,SACA,SArCA,EACA,EACA,CAAE,YAAY,GAAM,UAA0D,CAAC,IAC9D,CACjB,GAAI,EAAU,MAAM,IAAI,EAAA,mBAAmB,0BAA0B,EAErE,GAAI,GAAQ,QAAS,UAAa,CAAC,EAEnC,IAAM,EAAU,EACV,EAAY,EAAU,IAAI,CAAK,GAAK,IAAI,IAE9C,EAAU,IAAI,EAAO,CAAS,EAC9B,EAAU,IAAI,CAAO,EAEjB,GAAW,EAAO,CAAK,EAE3B,IAAM,MAAmB,CACvB,IAAM,EAAU,EAAU,IAAI,CAAK,EAE9B,IAEL,EAAQ,OAAO,CAAO,EAElB,EAAQ,OAAS,GAAG,EAAU,OAAO,CAAK,EAChD,EAIA,OAFA,GAAQ,iBAAiB,QAAS,EAAM,CAAE,KAAM,EAAK,CAAC,EAE/C,CACT,CASA,CACF,CAEA,SAAgB,EACd,EACA,EACA,EACa,CACb,IAAM,EAAW,OAAO,EAAO,EAAM,CAAC,GAAG,EACnC,EAAY,EAAkC,GAEpD,GAAI,OAAO,GAAa,UAAY,OAAO,GAAa,SACtD,MAAM,IAAI,EAAA,WAAW,oBAAoB,OAAO,CAAK,EAAE,gDAAgD,EAAS,EAAE,EAGpH,GAAI,OAAO,GAAa,UAAY,CAAC,OAAO,SAAS,CAAQ,EAC3D,MAAM,IAAI,EAAA,WAAW,oBAAoB,OAAO,CAAK,EAAE,sCAAsC,EAAS,EAAE,EAG1G,OAAO,CACT"}
1
+ {"version":3,"file":"internal.cjs","names":[],"sources":["../src/internal.ts"],"sourcesContent":["import { VaultDisposedError, VaultError } from './errors';\nimport type { AnySchema, KeyOf, RecordOf, VaultKey } from './types';\n\ntype ObserverListener<T> = (records: T[]) => void;\n\nconst SEP = '\\x00';\n\n/**\n * Type-tagged keys make `1` and `'1'` distinct in string-keyed adapters while\n * keeping the same portable primary-key contract as IndexedDB.\n */\nexport function encodeVaultKey(key: VaultKey): string {\n if (typeof key === 'number') {\n if (!Number.isFinite(key)) throw new VaultError(`primary key must be a finite number, received ${String(key)}`);\n\n return `n:${String(key)}`;\n }\n\n return `s:${encodeURIComponent(key)}`;\n}\n\nexport function encodeDbPrefix(dbName: string): string {\n return `${encodeURIComponent(dbName)}${SEP}`;\n}\n\nexport function encodeStorageKey(dbName: string, table: string, key: VaultKey): string {\n return `${encodeURIComponent(dbName)}${SEP}${encodeURIComponent(table)}${SEP}${encodeVaultKey(key)}`;\n}\n\nexport function encodeStorageTablePrefix(dbName: string, table: string): string {\n return `${encodeURIComponent(dbName)}${SEP}${encodeURIComponent(table)}${SEP}`;\n}\n\nexport function decodeStorageTableFromKey(dbName: string, storageKey: string | null): string | undefined {\n if (!storageKey) return undefined;\n\n const prefix = encodeDbPrefix(dbName);\n\n if (!storageKey.startsWith(prefix)) return undefined;\n\n const tail = storageKey.slice(prefix.length);\n const end = tail.indexOf(SEP);\n\n if (end === -1) return undefined;\n\n try {\n return decodeURIComponent(tail.slice(0, end));\n } catch {\n return undefined;\n }\n}\n\n/** `observe()` is Vault's single reactivity primitive: a snapshot now, then on mutations. */\nexport function createObserverHub<S extends AnySchema>(\n getAll: <K extends keyof S & string>(table: K) => Promise<RecordOf<S, K>[]>,\n) {\n const observers = new Map<string, Set<ObserverListener<unknown>>>();\n const revisions = new Map<string, number>();\n let disposed = false;\n\n const notify = <K extends keyof S & string>(table: K): void => {\n if (disposed) return;\n\n const revision = (revisions.get(table) ?? 0) + 1;\n revisions.set(table, revision);\n const listeners = observers.get(table);\n\n if (!listeners || listeners.size === 0) return;\n\n void getAll(table)\n .then((records) => {\n if (disposed || revisions.get(table) !== revision) return;\n\n const current = observers.get(table);\n\n if (!current || current.size === 0) return;\n\n for (const listener of current) {\n try {\n listener(records as unknown[]);\n } catch {\n /* observer listener errors are intentionally swallowed */\n }\n }\n })\n .catch(() => {\n /* observer source errors are intentionally swallowed */\n });\n };\n\n const observe = <K extends keyof S & string>(\n table: K,\n listener: (records: RecordOf<S, K>[]) => void,\n { immediate = true, signal }: { immediate?: boolean; signal?: AbortSignal } = {},\n ): (() => void) => {\n if (disposed) throw new VaultDisposedError('observer hub is disposed');\n\n if (signal?.aborted) return () => {};\n\n const wrapped = listener as ObserverListener<unknown>;\n const listeners = observers.get(table) ?? new Set<ObserverListener<unknown>>();\n\n observers.set(table, listeners);\n listeners.add(wrapped);\n\n if (immediate) notify(table);\n\n const stop = (): void => {\n signal?.removeEventListener('abort', stop);\n const current = observers.get(table);\n\n if (!current) return;\n\n current.delete(wrapped);\n\n if (current.size === 0) observers.delete(table);\n };\n\n signal?.addEventListener('abort', stop, { once: true });\n\n return stop;\n };\n\n return {\n dispose: () => {\n disposed = true;\n observers.clear();\n revisions.clear();\n },\n notify,\n observe,\n };\n}\n\nexport function getRecordKey<S extends AnySchema, K extends keyof S>(\n schema: S,\n table: K,\n value: RecordOf<S, K>,\n): KeyOf<S, K> {\n const keyField = String(schema[table].key);\n const keyValue = (value as Record<string, unknown>)[keyField];\n\n if (typeof keyValue !== 'number' && typeof keyValue !== 'string') {\n throw new VaultError(`record in table \"${String(table)}\" must have a string or finite-number key at \"${keyField}\"`);\n }\n\n if (typeof keyValue === 'number' && !Number.isFinite(keyValue)) {\n throw new VaultError(`record in table \"${String(table)}\" must have a finite-number key at \"${keyField}\"`);\n }\n\n return keyValue as KeyOf<S, K>;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAMpE;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAQpD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,GAAG,MAAM,CAErF;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,SAAS,CAiBvG;AAED,6FAA6F;AAC7F,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,SAAS,EACnD,MAAM,EAAE,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;;aAK3D,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC,KAAG,IAAI;cA4B1C,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,SAClC,CAAC,YACE,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,IAAI,0BACf;QAAE,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,KAC1E,CAAC,MAAM,IAAI,CAAC;EAoChB;AAED,wBAAgB,YAAY,CAAC,CAAC,SAAS,SAAS,EAAE,CAAC,SAAS,MAAM,CAAC,EACjE,MAAM,EAAE,CAAC,EACT,KAAK,EAAE,CAAC,EACR,KAAK,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,GACpB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAab"}
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAMpE;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAQpD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,GAAG,MAAM,CAErF;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,SAAS,CAiBvG;AAED,6FAA6F;AAC7F,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,SAAS,EACnD,MAAM,EAAE,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;;aAM3D,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC,KAAG,IAAI;cA8B1C,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,SAClC,CAAC,YACE,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,IAAI,0BACf;QAAE,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,KAC1E,CAAC,MAAM,IAAI,CAAC;EAsChB;AAED,wBAAgB,YAAY,CAAC,CAAC,SAAS,SAAS,EAAE,CAAC,SAAS,MAAM,CAAC,EACjE,MAAM,EAAE,CAAC,EACT,KAAK,EAAE,CAAC,EACR,KAAK,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,GACpB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAab"}
package/dist/internal.js CHANGED
@@ -29,28 +29,31 @@ function s(e, t) {
29
29
  }
30
30
  }
31
31
  function c(t) {
32
- let n = /* @__PURE__ */ new Map(), r = !1, i = (e) => {
33
- if (r) return;
34
- let i = n.get(e);
35
- !i || i.size === 0 || t(e).then((t) => {
36
- if (r) return;
37
- let i = n.get(e);
38
- if (!(!i || i.size === 0)) for (let e of i) try {
32
+ let n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(), i = !1, a = (e) => {
33
+ if (i) return;
34
+ let a = (r.get(e) ?? 0) + 1;
35
+ r.set(e, a);
36
+ let o = n.get(e);
37
+ o && o.size !== 0 && t(e).then((t) => {
38
+ if (i || r.get(e) !== a) return;
39
+ let o = n.get(e);
40
+ if (o && o.size !== 0) for (let e of o) try {
39
41
  e(t);
40
42
  } catch {}
41
43
  }).catch(() => {});
42
44
  };
43
45
  return {
44
46
  dispose: () => {
45
- r = !0, n.clear();
47
+ i = !0, n.clear(), r.clear();
46
48
  },
47
- notify: i,
48
- observe: (t, a, { immediate: o = !0, signal: s } = {}) => {
49
- if (r) throw new e("observer hub is disposed");
49
+ notify: a,
50
+ observe: (t, r, { immediate: o = !0, signal: s } = {}) => {
51
+ if (i) throw new e("observer hub is disposed");
50
52
  if (s?.aborted) return () => {};
51
- let c = a, l = n.get(t) ?? /* @__PURE__ */ new Set();
52
- n.set(t, l), l.add(c), o && i(t);
53
+ let c = r, l = n.get(t) ?? /* @__PURE__ */ new Set();
54
+ n.set(t, l), l.add(c), o && a(t);
53
55
  let u = () => {
56
+ s?.removeEventListener("abort", u);
54
57
  let e = n.get(t);
55
58
  e && (e.delete(c), e.size === 0 && n.delete(t));
56
59
  };
@@ -1 +1 @@
1
- {"version":3,"file":"internal.js","names":[],"sources":["../src/internal.ts"],"sourcesContent":["import { VaultDisposedError, VaultError } from './errors';\nimport type { AnySchema, KeyOf, RecordOf, VaultKey } from './types';\n\ntype ObserverListener<T> = (records: T[]) => void;\n\nconst SEP = '\\x00';\n\n/**\n * Type-tagged keys make `1` and `'1'` distinct in string-keyed adapters while\n * keeping the same portable primary-key contract as IndexedDB.\n */\nexport function encodeVaultKey(key: VaultKey): string {\n if (typeof key === 'number') {\n if (!Number.isFinite(key)) throw new VaultError(`primary key must be a finite number, received ${String(key)}`);\n\n return `n:${String(key)}`;\n }\n\n return `s:${encodeURIComponent(key)}`;\n}\n\nexport function encodeDbPrefix(dbName: string): string {\n return `${encodeURIComponent(dbName)}${SEP}`;\n}\n\nexport function encodeStorageKey(dbName: string, table: string, key: VaultKey): string {\n return `${encodeURIComponent(dbName)}${SEP}${encodeURIComponent(table)}${SEP}${encodeVaultKey(key)}`;\n}\n\nexport function encodeStorageTablePrefix(dbName: string, table: string): string {\n return `${encodeURIComponent(dbName)}${SEP}${encodeURIComponent(table)}${SEP}`;\n}\n\nexport function decodeStorageTableFromKey(dbName: string, storageKey: string | null): string | undefined {\n if (!storageKey) return undefined;\n\n const prefix = encodeDbPrefix(dbName);\n\n if (!storageKey.startsWith(prefix)) return undefined;\n\n const tail = storageKey.slice(prefix.length);\n const end = tail.indexOf(SEP);\n\n if (end === -1) return undefined;\n\n try {\n return decodeURIComponent(tail.slice(0, end));\n } catch {\n return undefined;\n }\n}\n\n/** `observe()` is Vault's single reactivity primitive: a snapshot now, then on mutations. */\nexport function createObserverHub<S extends AnySchema>(\n getAll: <K extends keyof S & string>(table: K) => Promise<RecordOf<S, K>[]>,\n) {\n const observers = new Map<string, Set<ObserverListener<unknown>>>();\n let disposed = false;\n\n const notify = <K extends keyof S & string>(table: K): void => {\n if (disposed) return;\n\n const listeners = observers.get(table);\n\n if (!listeners || listeners.size === 0) return;\n\n void getAll(table)\n .then((records) => {\n if (disposed) return;\n\n const current = observers.get(table);\n\n if (!current || current.size === 0) return;\n\n for (const listener of current) {\n try {\n listener(records as unknown[]);\n } catch {\n /* observer listener errors are intentionally swallowed */\n }\n }\n })\n .catch(() => {\n /* observer source errors are intentionally swallowed */\n });\n };\n\n const observe = <K extends keyof S & string>(\n table: K,\n listener: (records: RecordOf<S, K>[]) => void,\n { immediate = true, signal }: { immediate?: boolean; signal?: AbortSignal } = {},\n ): (() => void) => {\n if (disposed) throw new VaultDisposedError('observer hub is disposed');\n\n if (signal?.aborted) return () => {};\n\n const wrapped = listener as ObserverListener<unknown>;\n const listeners = observers.get(table) ?? new Set<ObserverListener<unknown>>();\n\n observers.set(table, listeners);\n listeners.add(wrapped);\n\n if (immediate) notify(table);\n\n const stop = (): void => {\n const current = observers.get(table);\n\n if (!current) return;\n\n current.delete(wrapped);\n\n if (current.size === 0) observers.delete(table);\n };\n\n signal?.addEventListener('abort', stop, { once: true });\n\n return stop;\n };\n\n return {\n dispose: () => {\n disposed = true;\n observers.clear();\n },\n notify,\n observe,\n };\n}\n\nexport function getRecordKey<S extends AnySchema, K extends keyof S>(\n schema: S,\n table: K,\n value: RecordOf<S, K>,\n): KeyOf<S, K> {\n const keyField = String(schema[table].key);\n const keyValue = (value as Record<string, unknown>)[keyField];\n\n if (typeof keyValue !== 'number' && typeof keyValue !== 'string') {\n throw new VaultError(`record in table \"${String(table)}\" must have a string or finite-number key at \"${keyField}\"`);\n }\n\n if (typeof keyValue === 'number' && !Number.isFinite(keyValue)) {\n throw new VaultError(`record in table \"${String(table)}\" must have a finite-number key at \"${keyField}\"`);\n }\n\n return keyValue as KeyOf<S, K>;\n}\n"],"mappings":";;AAKA,IAAM,IAAM;AAMZ,SAAgB,EAAe,GAAuB;CACpD,IAAI,OAAO,KAAQ,UAAU;EAC3B,IAAI,CAAC,OAAO,SAAS,CAAG,GAAG,MAAM,IAAI,EAAW,iDAAiD,OAAO,CAAG,GAAG;EAE9G,OAAO,KAAK,OAAO,CAAG;CACxB;CAEA,OAAO,KAAK,mBAAmB,CAAG;AACpC;AAEA,SAAgB,EAAe,GAAwB;CACrD,OAAO,GAAG,mBAAmB,CAAM,IAAI;AACzC;AAEA,SAAgB,EAAiB,GAAgB,GAAe,GAAuB;CACrF,OAAO,GAAG,mBAAmB,CAAM,IAAI,IAAM,mBAAmB,CAAK,IAAI,IAAM,EAAe,CAAG;AACnG;AAEA,SAAgB,EAAyB,GAAgB,GAAuB;CAC9E,OAAO,GAAG,mBAAmB,CAAM,IAAI,IAAM,mBAAmB,CAAK,IAAI;AAC3E;AAEA,SAAgB,EAA0B,GAAgB,GAA+C;CACvG,IAAI,CAAC,GAAY;CAEjB,IAAM,IAAS,EAAe,CAAM;CAEpC,IAAI,CAAC,EAAW,WAAW,CAAM,GAAG;CAEpC,IAAM,IAAO,EAAW,MAAM,EAAO,MAAM,GACrC,IAAM,EAAK,QAAQ,CAAG;CAExB,UAAQ,IAEZ,IAAI;EACF,OAAO,mBAAmB,EAAK,MAAM,GAAG,CAAG,CAAC;CAC9C,QAAQ;EACN;CACF;AACF;AAGA,SAAgB,EACd,GACA;CACA,IAAM,oBAAY,IAAI,IAA4C,GAC9D,IAAW,IAET,KAAsC,MAAmB;EAC7D,IAAI,GAAU;EAEd,IAAM,IAAY,EAAU,IAAI,CAAK;EAEjC,CAAC,KAAa,EAAU,SAAS,KAErC,EAAY,CAAK,CAAC,CACf,MAAM,MAAY;GACjB,IAAI,GAAU;GAEd,IAAM,IAAU,EAAU,IAAI,CAAK;GAE/B,OAAC,KAAW,EAAQ,SAAS,IAEjC,KAAK,IAAM,KAAY,GACrB,IAAI;IACF,EAAS,CAAoB;GAC/B,QAAQ,CAER;EAEJ,CAAC,CAAC,CACD,YAAY,CAEb,CAAC;CACL;CAkCA,OAAO;EACL,eAAe;GAEb,AADA,IAAW,IACX,EAAU,MAAM;EAClB;EACA;EACA,UArCA,GACA,GACA,EAAE,eAAY,IAAM,cAA0D,CAAC,MAC9D;GACjB,IAAI,GAAU,MAAM,IAAI,EAAmB,0BAA0B;GAErE,IAAI,GAAQ,SAAS,aAAa,CAAC;GAEnC,IAAM,IAAU,GACV,IAAY,EAAU,IAAI,CAAK,qBAAK,IAAI,IAA+B;GAK7E,AAHA,EAAU,IAAI,GAAO,CAAS,GAC9B,EAAU,IAAI,CAAO,GAEjB,KAAW,EAAO,CAAK;GAE3B,IAAM,UAAmB;IACvB,IAAM,IAAU,EAAU,IAAI,CAAK;IAE9B,MAEL,EAAQ,OAAO,CAAO,GAElB,EAAQ,SAAS,KAAG,EAAU,OAAO,CAAK;GAChD;GAIA,OAFA,GAAQ,iBAAiB,SAAS,GAAM,EAAE,MAAM,GAAK,CAAC,GAE/C;EACT;CASA;AACF;AAEA,SAAgB,EACd,GACA,GACA,GACa;CACb,IAAM,IAAW,OAAO,EAAO,EAAM,CAAC,GAAG,GACnC,IAAY,EAAkC;CAEpD,IAAI,OAAO,KAAa,YAAY,OAAO,KAAa,UACtD,MAAM,IAAI,EAAW,oBAAoB,OAAO,CAAK,EAAE,gDAAgD,EAAS,EAAE;CAGpH,IAAI,OAAO,KAAa,YAAY,CAAC,OAAO,SAAS,CAAQ,GAC3D,MAAM,IAAI,EAAW,oBAAoB,OAAO,CAAK,EAAE,sCAAsC,EAAS,EAAE;CAG1G,OAAO;AACT"}
1
+ {"version":3,"file":"internal.js","names":[],"sources":["../src/internal.ts"],"sourcesContent":["import { VaultDisposedError, VaultError } from './errors';\nimport type { AnySchema, KeyOf, RecordOf, VaultKey } from './types';\n\ntype ObserverListener<T> = (records: T[]) => void;\n\nconst SEP = '\\x00';\n\n/**\n * Type-tagged keys make `1` and `'1'` distinct in string-keyed adapters while\n * keeping the same portable primary-key contract as IndexedDB.\n */\nexport function encodeVaultKey(key: VaultKey): string {\n if (typeof key === 'number') {\n if (!Number.isFinite(key)) throw new VaultError(`primary key must be a finite number, received ${String(key)}`);\n\n return `n:${String(key)}`;\n }\n\n return `s:${encodeURIComponent(key)}`;\n}\n\nexport function encodeDbPrefix(dbName: string): string {\n return `${encodeURIComponent(dbName)}${SEP}`;\n}\n\nexport function encodeStorageKey(dbName: string, table: string, key: VaultKey): string {\n return `${encodeURIComponent(dbName)}${SEP}${encodeURIComponent(table)}${SEP}${encodeVaultKey(key)}`;\n}\n\nexport function encodeStorageTablePrefix(dbName: string, table: string): string {\n return `${encodeURIComponent(dbName)}${SEP}${encodeURIComponent(table)}${SEP}`;\n}\n\nexport function decodeStorageTableFromKey(dbName: string, storageKey: string | null): string | undefined {\n if (!storageKey) return undefined;\n\n const prefix = encodeDbPrefix(dbName);\n\n if (!storageKey.startsWith(prefix)) return undefined;\n\n const tail = storageKey.slice(prefix.length);\n const end = tail.indexOf(SEP);\n\n if (end === -1) return undefined;\n\n try {\n return decodeURIComponent(tail.slice(0, end));\n } catch {\n return undefined;\n }\n}\n\n/** `observe()` is Vault's single reactivity primitive: a snapshot now, then on mutations. */\nexport function createObserverHub<S extends AnySchema>(\n getAll: <K extends keyof S & string>(table: K) => Promise<RecordOf<S, K>[]>,\n) {\n const observers = new Map<string, Set<ObserverListener<unknown>>>();\n const revisions = new Map<string, number>();\n let disposed = false;\n\n const notify = <K extends keyof S & string>(table: K): void => {\n if (disposed) return;\n\n const revision = (revisions.get(table) ?? 0) + 1;\n revisions.set(table, revision);\n const listeners = observers.get(table);\n\n if (!listeners || listeners.size === 0) return;\n\n void getAll(table)\n .then((records) => {\n if (disposed || revisions.get(table) !== revision) return;\n\n const current = observers.get(table);\n\n if (!current || current.size === 0) return;\n\n for (const listener of current) {\n try {\n listener(records as unknown[]);\n } catch {\n /* observer listener errors are intentionally swallowed */\n }\n }\n })\n .catch(() => {\n /* observer source errors are intentionally swallowed */\n });\n };\n\n const observe = <K extends keyof S & string>(\n table: K,\n listener: (records: RecordOf<S, K>[]) => void,\n { immediate = true, signal }: { immediate?: boolean; signal?: AbortSignal } = {},\n ): (() => void) => {\n if (disposed) throw new VaultDisposedError('observer hub is disposed');\n\n if (signal?.aborted) return () => {};\n\n const wrapped = listener as ObserverListener<unknown>;\n const listeners = observers.get(table) ?? new Set<ObserverListener<unknown>>();\n\n observers.set(table, listeners);\n listeners.add(wrapped);\n\n if (immediate) notify(table);\n\n const stop = (): void => {\n signal?.removeEventListener('abort', stop);\n const current = observers.get(table);\n\n if (!current) return;\n\n current.delete(wrapped);\n\n if (current.size === 0) observers.delete(table);\n };\n\n signal?.addEventListener('abort', stop, { once: true });\n\n return stop;\n };\n\n return {\n dispose: () => {\n disposed = true;\n observers.clear();\n revisions.clear();\n },\n notify,\n observe,\n };\n}\n\nexport function getRecordKey<S extends AnySchema, K extends keyof S>(\n schema: S,\n table: K,\n value: RecordOf<S, K>,\n): KeyOf<S, K> {\n const keyField = String(schema[table].key);\n const keyValue = (value as Record<string, unknown>)[keyField];\n\n if (typeof keyValue !== 'number' && typeof keyValue !== 'string') {\n throw new VaultError(`record in table \"${String(table)}\" must have a string or finite-number key at \"${keyField}\"`);\n }\n\n if (typeof keyValue === 'number' && !Number.isFinite(keyValue)) {\n throw new VaultError(`record in table \"${String(table)}\" must have a finite-number key at \"${keyField}\"`);\n }\n\n return keyValue as KeyOf<S, K>;\n}\n"],"mappings":"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"}
package/dist/query.cjs CHANGED
@@ -1,2 +1,2 @@
1
- const e=require("./errors.cjs");async function t(e,t){let n=await e.source();for(let e of t)n=e.apply(n);return n}function n(t,n){if(!Number.isInteger(t)||t<0)throw new e.VaultError(`${n} must be a non-negative integer`);return t}function r(i,a=[]){let o=e=>r(i,[...a,e]);return{count(){return t(i,a.filter(e=>!e.isNonFilter)).then(e=>e.length)},async delete(){if(!i.deleteMany)throw new e.VaultError(`query.delete is not available for this adapter context`);let n=await t(i,a);return i.deleteMany(n)},equals(e,t){return o({apply:n=>n.filter(n=>n[e]===t)})},filter(e){return o({apply:t=>t.filter(e)})},first(){return a.length===0?i.source().then(e=>e[0]):t(i,a).then(e=>e[0])},limit(e){let t=n(e,`query.limit`);return o({apply:e=>e.slice(0,t),isNonFilter:!0})},offset(e){let t=n(e,`query.offset`);return o({apply:e=>e.slice(t),isNonFilter:!0})},orderBy(e,t=`asc`){return o({apply:n=>{let r=t===`asc`?1:-1;return[...n].sort((t,n)=>{let i=t[e],a=n[e];return i===a?0:i>a?r:-r})},isNonFilter:!0})},toArray(){return t(i,a)}}}exports.createQueryBuilder=r;
1
+ const e=require("./errors.cjs");var t=async(e,t)=>{let n=await e.source();for(let e of t)n=e.apply(n);return n},n=(t,n)=>{if(!Number.isInteger(t)||t<0)throw new e.VaultError(`${n} must be a non-negative integer`);return t};function r(i,a=[]){let o=e=>r(i,[...a,e]);return{count:()=>t(i,a.filter(e=>!e.isPresentation)).then(e=>e.length),async delete(){if(!i.deleteMany)throw new e.VaultError(`query.delete is not available in this context`);return i.deleteMany(await t(i,a))},equals:(e,t)=>o({apply:n=>n.filter(n=>n[e]===t)}),filter:e=>o({apply:t=>t.filter(e)}),async first(){return(await t(i,a))[0]},limit(e){let t=n(e,`query.limit`);return o({apply:e=>e.slice(0,t),isPresentation:!0})},offset(e){let t=n(e,`query.offset`);return o({apply:e=>e.slice(t),isPresentation:!0})},orderBy:(e,t=`asc`)=>o({apply:n=>{let r=t===`asc`?1:-1;return[...n].sort((t,n)=>{let i=t[e],a=n[e];return i===a?0:i>a?r:-r})},isPresentation:!0}),toArray:()=>t(i,a)}}exports.createQueryBuilder=r;
2
2
  //# sourceMappingURL=query.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"query.cjs","names":[],"sources":["../src/query.ts"],"sourcesContent":["import { VaultError } from './errors';\n\ntype Predicate<T> = (value: T, index: number, array: T[]) => boolean;\n/**\n * `isNonFilter`: when true this op is excluded from `count()` — it does not restrict\n * *which* records match (limit, offset, orderBy), only how results are presented.\n */\ntype QueryOp<T> = { apply: (data: T[]) => T[]; isNonFilter?: boolean };\n\nexport type QueryContext<T extends object> = {\n deleteMany?: (records: T[]) => Promise<number>;\n source: () => Promise<T[]>;\n};\n\n/* -------------------- Public interfaces -------------------- */\n\n/**\n * Fluent query builder. `T` is the record type.\n */\nexport interface QueryBuilder<T extends object> {\n /**\n * Returns the number of records matching the applied filter predicates.\n * Presentation-only ops (`limit`, `offset`, `orderBy`) are intentionally ignored — this\n * always counts the full filtered set, making paginated total-count queries possible\n * without a second query.\n */\n count(): Promise<number>;\n delete(): Promise<number>;\n /**\n * Filter records where `field` exactly equals `value`.\n */\n equals<K extends keyof T & string, V extends T[K]>(field: K, value: V): QueryBuilder<T>;\n filter(fn: Predicate<T>): QueryBuilder<T>;\n first(): Promise<T | undefined>;\n limit(n: number): QueryBuilder<T>;\n offset(n: number): QueryBuilder<T>;\n orderBy<K extends keyof T>(field: K, direction?: 'asc' | 'desc'): QueryBuilder<T>;\n toArray(): Promise<T[]>;\n}\n\n/* -------------------- Helpers -------------------- */\n\nasync function applyOps<T extends object>(ctx: QueryContext<T>, ops: readonly QueryOp<T>[]): Promise<T[]> {\n let data = await ctx.source();\n\n for (const op of ops) {\n data = op.apply(data);\n }\n\n return data;\n}\n\nfunction assertNonNegativeInteger(value: number, name: string): number {\n if (!Number.isInteger(value) || value < 0) {\n throw new VaultError(`${name} must be a non-negative integer`);\n }\n\n return value;\n}\n\n/* -------------------- Factory -------------------- */\n\nexport function createQueryBuilder<T extends object>(\n ctx: QueryContext<T>,\n ops: readonly QueryOp<T>[] = [],\n): QueryBuilder<T> {\n const append = (op: QueryOp<T>): QueryBuilder<T> => createQueryBuilder<T>(ctx, [...ops, op]);\n\n return {\n count(): Promise<number> {\n const filterOps = ops.filter((op) => !op.isNonFilter);\n\n return applyOps(ctx, filterOps).then((r) => r.length);\n },\n async delete(): Promise<number> {\n if (!ctx.deleteMany) {\n throw new VaultError('query.delete is not available for this adapter context');\n }\n\n const records = await applyOps(ctx, ops);\n\n return ctx.deleteMany(records);\n },\n equals<K extends keyof T & string, V extends T[K]>(field: K, value: V): QueryBuilder<T> {\n return append({ apply: (data) => data.filter((r) => r[field] === value) });\n },\n filter(fn) {\n return append({ apply: (data) => data.filter(fn) });\n },\n first(): Promise<T | undefined> {\n if (ops.length === 0) return ctx.source().then((r) => r[0]);\n\n return applyOps(ctx, ops).then((r) => r[0]);\n },\n limit(n) {\n const safeN = assertNonNegativeInteger(n, 'query.limit');\n\n return append({ apply: (data) => data.slice(0, safeN), isNonFilter: true });\n },\n offset(n) {\n const safeN = assertNonNegativeInteger(n, 'query.offset');\n\n return append({ apply: (data) => data.slice(safeN), isNonFilter: true });\n },\n orderBy(field, direction = 'asc') {\n return append({\n apply: (data) => {\n const sign = direction === 'asc' ? 1 : -1;\n\n return [...data].sort((a, b) => {\n const av = a[field] as number | string;\n const bv = b[field] as number | string;\n\n if (av === bv) return 0;\n\n return av > bv ? sign : -sign;\n });\n },\n isNonFilter: true,\n });\n },\n toArray(): Promise<T[]> {\n return applyOps(ctx, ops);\n },\n };\n}\n"],"mappings":"gCA0CA,eAAe,EAA2B,EAAsB,EAA0C,CACxG,IAAI,EAAO,MAAM,EAAI,OAAO,EAE5B,IAAK,IAAM,KAAM,EACf,EAAO,EAAG,MAAM,CAAI,EAGtB,OAAO,CACT,CAEA,SAAS,EAAyB,EAAe,EAAsB,CACrE,GAAI,CAAC,OAAO,UAAU,CAAK,GAAK,EAAQ,EACtC,MAAM,IAAI,EAAA,WAAW,GAAG,EAAK,gCAAgC,EAG/D,OAAO,CACT,CAIA,SAAgB,EACd,EACA,EAA6B,CAAC,EACb,CACjB,IAAM,EAAU,GAAoC,EAAsB,EAAK,CAAC,GAAG,EAAK,CAAE,CAAC,EAE3F,MAAO,CACL,OAAyB,CAGvB,OAAO,EAAS,EAFE,EAAI,OAAQ,GAAO,CAAC,EAAG,WAEpB,CAAS,CAAC,CAAC,KAAM,GAAM,EAAE,MAAM,CACtD,EACA,MAAM,QAA0B,CAC9B,GAAI,CAAC,EAAI,WACP,MAAM,IAAI,EAAA,WAAW,wDAAwD,EAG/E,IAAM,EAAU,MAAM,EAAS,EAAK,CAAG,EAEvC,OAAO,EAAI,WAAW,CAAO,CAC/B,EACA,OAAmD,EAAU,EAA2B,CACtF,OAAO,EAAO,CAAE,MAAQ,GAAS,EAAK,OAAQ,GAAM,EAAE,KAAW,CAAK,CAAE,CAAC,CAC3E,EACA,OAAO,EAAI,CACT,OAAO,EAAO,CAAE,MAAQ,GAAS,EAAK,OAAO,CAAE,CAAE,CAAC,CACpD,EACA,OAAgC,CAG9B,OAFI,EAAI,SAAW,EAAU,EAAI,OAAO,CAAC,CAAC,KAAM,GAAM,EAAE,EAAE,EAEnD,EAAS,EAAK,CAAG,CAAC,CAAC,KAAM,GAAM,EAAE,EAAE,CAC5C,EACA,MAAM,EAAG,CACP,IAAM,EAAQ,EAAyB,EAAG,aAAa,EAEvD,OAAO,EAAO,CAAE,MAAQ,GAAS,EAAK,MAAM,EAAG,CAAK,EAAG,YAAa,EAAK,CAAC,CAC5E,EACA,OAAO,EAAG,CACR,IAAM,EAAQ,EAAyB,EAAG,cAAc,EAExD,OAAO,EAAO,CAAE,MAAQ,GAAS,EAAK,MAAM,CAAK,EAAG,YAAa,EAAK,CAAC,CACzE,EACA,QAAQ,EAAO,EAAY,MAAO,CAChC,OAAO,EAAO,CACZ,MAAQ,GAAS,CACf,IAAM,EAAO,IAAc,MAAQ,EAAI,GAEvC,MAAO,CAAC,GAAG,CAAI,CAAC,CAAC,MAAM,EAAG,IAAM,CAC9B,IAAM,EAAK,EAAE,GACP,EAAK,EAAE,GAIb,OAFI,IAAO,EAAW,EAEf,EAAK,EAAK,EAAO,CAAC,CAC3B,CAAC,CACH,EACA,YAAa,EACf,CAAC,CACH,EACA,SAAwB,CACtB,OAAO,EAAS,EAAK,CAAG,CAC1B,CACF,CACF"}
1
+ {"version":3,"file":"query.cjs","names":[],"sources":["../src/query.ts"],"sourcesContent":["import { VaultError } from './errors';\n\ntype Predicate<T> = (value: T, index: number, array: readonly T[]) => boolean;\ntype QueryOp<T> = { apply: (data: T[]) => T[]; isPresentation?: boolean };\n\nexport type QueryContext<T extends object> = {\n deleteMany?: (records: readonly T[]) => Promise<number>;\n source: () => Promise<T[]>;\n};\n\nexport interface QueryBuilder<T extends object> {\n count(): Promise<number>;\n delete(): Promise<number>;\n equals<K extends keyof T & string>(field: K, value: T[K]): QueryBuilder<T>;\n filter(predicate: Predicate<T>): QueryBuilder<T>;\n first(): Promise<T | undefined>;\n limit(count: number): QueryBuilder<T>;\n offset(count: number): QueryBuilder<T>;\n orderBy<K extends keyof T>(field: K, direction?: 'asc' | 'desc'): QueryBuilder<T>;\n toArray(): Promise<T[]>;\n}\n\nconst applyOps = async <T extends object>(\n context: QueryContext<T>,\n operations: readonly QueryOp<T>[],\n): Promise<T[]> => {\n let data = await context.source();\n for (const operation of operations) data = operation.apply(data);\n return data;\n};\n\nconst nonNegativeInteger = (value: number, name: string): number => {\n if (!Number.isInteger(value) || value < 0) throw new VaultError(`${name} must be a non-negative integer`);\n return value;\n};\n\nexport function createQueryBuilder<T extends object>(\n context: QueryContext<T>,\n operations: readonly QueryOp<T>[] = [],\n): QueryBuilder<T> {\n const append = (operation: QueryOp<T>): QueryBuilder<T> => createQueryBuilder(context, [...operations, operation]);\n\n return {\n count: () =>\n applyOps(\n context,\n operations.filter((operation) => !operation.isPresentation),\n ).then((data) => data.length),\n async delete() {\n if (!context.deleteMany) throw new VaultError('query.delete is not available in this context');\n return context.deleteMany(await applyOps(context, operations));\n },\n equals: (field, value) => append({ apply: (data) => data.filter((record) => record[field] === value) }),\n filter: (predicate) => append({ apply: (data) => data.filter(predicate) }),\n async first() {\n return (await applyOps(context, operations))[0];\n },\n limit(count) {\n const safeCount = nonNegativeInteger(count, 'query.limit');\n return append({ apply: (data) => data.slice(0, safeCount), isPresentation: true });\n },\n offset(count) {\n const safeCount = nonNegativeInteger(count, 'query.offset');\n return append({ apply: (data) => data.slice(safeCount), isPresentation: true });\n },\n orderBy: (field, direction = 'asc') =>\n append({\n apply: (data) => {\n const sign = direction === 'asc' ? 1 : -1;\n return [...data].sort((left, right) => {\n const a = left[field] as number | string;\n const b = right[field] as number | string;\n return a === b ? 0 : a > b ? sign : -sign;\n });\n },\n isPresentation: true,\n }),\n toArray: () => applyOps(context, operations),\n };\n}\n"],"mappings":"gCAsBA,IAAM,EAAW,MACf,EACA,IACiB,CACjB,IAAI,EAAO,MAAM,EAAQ,OAAO,EAChC,IAAK,IAAM,KAAa,EAAY,EAAO,EAAU,MAAM,CAAI,EAC/D,OAAO,CACT,EAEM,GAAsB,EAAe,IAAyB,CAClE,GAAI,CAAC,OAAO,UAAU,CAAK,GAAK,EAAQ,EAAG,MAAM,IAAI,EAAA,WAAW,GAAG,EAAK,gCAAgC,EACxG,OAAO,CACT,EAEA,SAAgB,EACd,EACA,EAAoC,CAAC,EACpB,CACjB,IAAM,EAAU,GAA2C,EAAmB,EAAS,CAAC,GAAG,EAAY,CAAS,CAAC,EAEjH,MAAO,CACL,UACE,EACE,EACA,EAAW,OAAQ,GAAc,CAAC,EAAU,cAAc,CAC5D,CAAC,CAAC,KAAM,GAAS,EAAK,MAAM,EAC9B,MAAM,QAAS,CACb,GAAI,CAAC,EAAQ,WAAY,MAAM,IAAI,EAAA,WAAW,+CAA+C,EAC7F,OAAO,EAAQ,WAAW,MAAM,EAAS,EAAS,CAAU,CAAC,CAC/D,EACA,QAAS,EAAO,IAAU,EAAO,CAAE,MAAQ,GAAS,EAAK,OAAQ,GAAW,EAAO,KAAW,CAAK,CAAE,CAAC,EACtG,OAAS,GAAc,EAAO,CAAE,MAAQ,GAAS,EAAK,OAAO,CAAS,CAAE,CAAC,EACzE,MAAM,OAAQ,CACZ,OAAQ,MAAM,EAAS,EAAS,CAAU,EAAA,CAAG,EAC/C,EACA,MAAM,EAAO,CACX,IAAM,EAAY,EAAmB,EAAO,aAAa,EACzD,OAAO,EAAO,CAAE,MAAQ,GAAS,EAAK,MAAM,EAAG,CAAS,EAAG,eAAgB,EAAK,CAAC,CACnF,EACA,OAAO,EAAO,CACZ,IAAM,EAAY,EAAmB,EAAO,cAAc,EAC1D,OAAO,EAAO,CAAE,MAAQ,GAAS,EAAK,MAAM,CAAS,EAAG,eAAgB,EAAK,CAAC,CAChF,EACA,SAAU,EAAO,EAAY,QAC3B,EAAO,CACL,MAAQ,GAAS,CACf,IAAM,EAAO,IAAc,MAAQ,EAAI,GACvC,MAAO,CAAC,GAAG,CAAI,CAAC,CAAC,MAAM,EAAM,IAAU,CACrC,IAAM,EAAI,EAAK,GACT,EAAI,EAAM,GAChB,OAAO,IAAM,EAAI,EAAI,EAAI,EAAI,EAAO,CAAC,CACvC,CAAC,CACH,EACA,eAAgB,EAClB,CAAC,EACH,YAAe,EAAS,EAAS,CAAU,CAC7C,CACF"}
package/dist/query.d.ts CHANGED
@@ -1,39 +1,23 @@
1
- type Predicate<T> = (value: T, index: number, array: T[]) => boolean;
2
- /**
3
- * `isNonFilter`: when true this op is excluded from `count()` — it does not restrict
4
- * *which* records match (limit, offset, orderBy), only how results are presented.
5
- */
1
+ type Predicate<T> = (value: T, index: number, array: readonly T[]) => boolean;
6
2
  type QueryOp<T> = {
7
3
  apply: (data: T[]) => T[];
8
- isNonFilter?: boolean;
4
+ isPresentation?: boolean;
9
5
  };
10
6
  export type QueryContext<T extends object> = {
11
- deleteMany?: (records: T[]) => Promise<number>;
7
+ deleteMany?: (records: readonly T[]) => Promise<number>;
12
8
  source: () => Promise<T[]>;
13
9
  };
14
- /**
15
- * Fluent query builder. `T` is the record type.
16
- */
17
10
  export interface QueryBuilder<T extends object> {
18
- /**
19
- * Returns the number of records matching the applied filter predicates.
20
- * Presentation-only ops (`limit`, `offset`, `orderBy`) are intentionally ignored — this
21
- * always counts the full filtered set, making paginated total-count queries possible
22
- * without a second query.
23
- */
24
11
  count(): Promise<number>;
25
12
  delete(): Promise<number>;
26
- /**
27
- * Filter records where `field` exactly equals `value`.
28
- */
29
- equals<K extends keyof T & string, V extends T[K]>(field: K, value: V): QueryBuilder<T>;
30
- filter(fn: Predicate<T>): QueryBuilder<T>;
13
+ equals<K extends keyof T & string>(field: K, value: T[K]): QueryBuilder<T>;
14
+ filter(predicate: Predicate<T>): QueryBuilder<T>;
31
15
  first(): Promise<T | undefined>;
32
- limit(n: number): QueryBuilder<T>;
33
- offset(n: number): QueryBuilder<T>;
16
+ limit(count: number): QueryBuilder<T>;
17
+ offset(count: number): QueryBuilder<T>;
34
18
  orderBy<K extends keyof T>(field: K, direction?: 'asc' | 'desc'): QueryBuilder<T>;
35
19
  toArray(): Promise<T[]>;
36
20
  }
37
- export declare function createQueryBuilder<T extends object>(ctx: QueryContext<T>, ops?: readonly QueryOp<T>[]): QueryBuilder<T>;
21
+ export declare function createQueryBuilder<T extends object>(context: QueryContext<T>, operations?: readonly QueryOp<T>[]): QueryBuilder<T>;
38
22
  export {};
39
23
  //# sourceMappingURL=query.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAEA,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,OAAO,CAAC;AACrE;;;GAGG;AACH,KAAK,OAAO,CAAC,CAAC,IAAI;IAAE,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEvE,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,IAAI;IAC3C,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;CAC5B,CAAC;AAIF;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,MAAM;IAC5C;;;;;OAKG;IACH,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1B;;OAEG;IACH,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IACxF,MAAM,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAC1C,KAAK,IAAI,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAChC,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IACnC,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAClF,OAAO,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;CACzB;AAwBD,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,EACjD,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,EACpB,GAAG,GAAE,SAAS,OAAO,CAAC,CAAC,CAAC,EAAO,GAC9B,YAAY,CAAC,CAAC,CAAC,CA4DjB"}
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAEA,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,KAAK,OAAO,CAAC;AAC9E,KAAK,OAAO,CAAC,CAAC,IAAI;IAAE,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAE1E,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,IAAI;IAC3C,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACxD,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;CAC5B,CAAC;AAEF,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,MAAM;IAC5C,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1B,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAC3E,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IACjD,KAAK,IAAI,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAChC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IACvC,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAClF,OAAO,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;CACzB;AAgBD,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,EACjD,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EACxB,UAAU,GAAE,SAAS,OAAO,CAAC,CAAC,CAAC,EAAO,GACrC,YAAY,CAAC,CAAC,CAAC,CAwCjB"}
package/dist/query.js CHANGED
@@ -1,63 +1,51 @@
1
1
  import { VaultError as e } from "./errors.js";
2
2
  //#region src/query.ts
3
- async function t(e, t) {
3
+ var t = async (e, t) => {
4
4
  let n = await e.source();
5
5
  for (let e of t) n = e.apply(n);
6
6
  return n;
7
- }
8
- function n(t, n) {
7
+ }, n = (t, n) => {
9
8
  if (!Number.isInteger(t) || t < 0) throw new e(`${n} must be a non-negative integer`);
10
9
  return t;
11
- }
10
+ };
12
11
  function r(i, a = []) {
13
12
  let o = (e) => r(i, [...a, e]);
14
13
  return {
15
- count() {
16
- return t(i, a.filter((e) => !e.isNonFilter)).then((e) => e.length);
17
- },
14
+ count: () => t(i, a.filter((e) => !e.isPresentation)).then((e) => e.length),
18
15
  async delete() {
19
- if (!i.deleteMany) throw new e("query.delete is not available for this adapter context");
20
- let n = await t(i, a);
21
- return i.deleteMany(n);
22
- },
23
- equals(e, t) {
24
- return o({ apply: (n) => n.filter((n) => n[e] === t) });
16
+ if (!i.deleteMany) throw new e("query.delete is not available in this context");
17
+ return i.deleteMany(await t(i, a));
25
18
  },
26
- filter(e) {
27
- return o({ apply: (t) => t.filter(e) });
28
- },
29
- first() {
30
- return a.length === 0 ? i.source().then((e) => e[0]) : t(i, a).then((e) => e[0]);
19
+ equals: (e, t) => o({ apply: (n) => n.filter((n) => n[e] === t) }),
20
+ filter: (e) => o({ apply: (t) => t.filter(e) }),
21
+ async first() {
22
+ return (await t(i, a))[0];
31
23
  },
32
24
  limit(e) {
33
25
  let t = n(e, "query.limit");
34
26
  return o({
35
27
  apply: (e) => e.slice(0, t),
36
- isNonFilter: !0
28
+ isPresentation: !0
37
29
  });
38
30
  },
39
31
  offset(e) {
40
32
  let t = n(e, "query.offset");
41
33
  return o({
42
34
  apply: (e) => e.slice(t),
43
- isNonFilter: !0
44
- });
45
- },
46
- orderBy(e, t = "asc") {
47
- return o({
48
- apply: (n) => {
49
- let r = t === "asc" ? 1 : -1;
50
- return [...n].sort((t, n) => {
51
- let i = t[e], a = n[e];
52
- return i === a ? 0 : i > a ? r : -r;
53
- });
54
- },
55
- isNonFilter: !0
35
+ isPresentation: !0
56
36
  });
57
37
  },
58
- toArray() {
59
- return t(i, a);
60
- }
38
+ orderBy: (e, t = "asc") => o({
39
+ apply: (n) => {
40
+ let r = t === "asc" ? 1 : -1;
41
+ return [...n].sort((t, n) => {
42
+ let i = t[e], a = n[e];
43
+ return i === a ? 0 : i > a ? r : -r;
44
+ });
45
+ },
46
+ isPresentation: !0
47
+ }),
48
+ toArray: () => t(i, a)
61
49
  };
62
50
  }
63
51
  //#endregion