@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
package/README.md CHANGED
@@ -1,50 +1,43 @@
1
1
  # @vielzeug/vault
2
2
 
3
- > Typed browser and SQLite storage with portable string/number keys, TTL, queries, and snapshot observation.
3
+ > Adapter-free typed storage core with focused browser and SQLite subpaths
4
4
 
5
- ## Quick start
5
+ ## Installation
6
+
7
+ ```sh
8
+ pnpm add @vielzeug/vault
9
+ npm install @vielzeug/vault
10
+ yarn add @vielzeug/vault
11
+ ```
12
+
13
+ ## Quick Start
6
14
 
7
15
  ```ts
16
+ import { s } from '@vielzeug/spell';
8
17
  import { table } from '@vielzeug/vault';
9
18
  import { createLocalStorage } from '@vielzeug/vault/local-storage';
10
19
 
11
20
  type User = { id: number; name: string };
12
- const store = createLocalStorage({ name: 'app', schema: { users: table<User>('id') } });
21
+ const UserSchema = s.object({ id: s.number(), name: s.string() });
22
+ const store = createLocalStorage({
23
+ codecs: { users: UserSchema },
24
+ name: 'app',
25
+ schema: { users: table<User>('id') },
26
+ });
13
27
 
14
28
  await store.put('users', { id: 1, name: 'Ada' });
15
29
  const stop = store.observe('users', (users) => console.log(users));
16
30
  stop();
17
31
  ```
18
32
 
19
- The root entry provides schemas, shared types, errors, TTL, and pruning. Import one focused adapter only when needed: `/memory`, `/local-storage`, `/session-storage`, `/indexeddb`, or `/sqlite`.
20
-
21
- `createMemory`, `createLocalStorage`, and `createSessionStorage` return the portable `VaultStore<S>` API. `createIndexedDB` and `createSQLite` add cursor or keyset `iterate()` plus atomic `batch()` transactions.
22
-
23
- ## SQLite
24
-
25
- Use the driver-neutral `@vielzeug/vault/sqlite` subpath outside the browser. The caller opens and owns the connection unless `closeOnDispose` is enabled.
26
-
27
- ```ts
28
- import { DatabaseSync } from 'node:sqlite';
29
-
30
- import { table } from '@vielzeug/vault';
31
- import { createSQLite } from '@vielzeug/vault/sqlite';
32
-
33
- const store = createSQLite({
34
- database: new DatabaseSync('app.db'),
35
- name: 'app',
36
- schema: { users: table<{ id: number; name: string }>('id') },
37
- });
38
- ```
39
-
40
- Node's `node:sqlite` API remains experimental. Bun's `Database` is compatible directly; configure WAL in application code when needed. Deno has no native SQLite API, but `jsr:@db/sqlite`'s `Database` is compatible directly when its FFI, filesystem, and environment permissions are granted.
41
-
42
- SQLite values must be JSON-compatible plain objects. SQLite operations execute synchronously beneath Vault's Promise API, so use a worker or isolate for large scans and writes on latency-sensitive paths. During a `batch()` callback, use only `tx.*`; calls on any store sharing that connection reject. Stores observe their own and same-connection Vault writes after commit; direct SQL and other processes are not observed.
43
-
44
- Vault stores record values and expiry metadata using each adapter's native layout. Number and string primary keys are tagged internally, so `1` and `'1'` are distinct everywhere.
45
-
46
33
  ## Documentation
47
34
 
48
35
  - [Overview](https://vielzeug.dev/vault/)
49
- - [Usage](https://vielzeug.dev/vault/usage)
50
- - [API](https://vielzeug.dev/vault/api)
36
+ - [Usage Guide](https://vielzeug.dev/vault/usage)
37
+ - [API Reference](https://vielzeug.dev/vault/api)
38
+ - [Examples](https://vielzeug.dev/vault/examples)
39
+ - [Migration Guide](https://vielzeug.dev/vault/migration)
40
+
41
+ ## License
42
+
43
+ MIT © [Helmuth Saatkamp](https://github.com/helmuthdu) — part of the [Vielzeug](https://github.com/helmuthdu/vielzeug) monorepo.
@@ -1,2 +1,2 @@
1
- const e=require("./errors.cjs"),t=require("./ttl.cjs"),n=require("./internal.cjs"),r=require("./query.cjs");function i(t){if(t.length===0)throw new e.VaultError(`batch: declare at least one table`)}function a(e,n,r){return r!==void 0&&t.assertPositiveFinite(r,`put/putAll`),r??e[n].defaultTtl}function o(t,r,i,a,o){let s=n.getRecordKey(t,r,a);if(s!==i)throw new e.VaultError(`${o}: key field "${t[r].key}" must be "${String(i)}" but got "${String(s)}" in table "${r}"`)}function s(e,t,n){return e.getMany?e.getMany(t,n):Promise.all(n.map(n=>e.get(t,n)))}function c(e,t,r,i){return{deleteMany:async a=>{if(a.length===0)return 0;let o=a.map(t=>n.getRecordKey(r,e,t)),s=await t.deleteMany(e,o);return s>0&&i(e),s},source:()=>t.getAll(e)}}function l(t,n,i,l,u){let d=l??((e,t)=>t),f=u?t=>{if(!u.has(t))throw new e.VaultScopeError(`table "${t}" is not part of this batch scope`)}:e=>{};return{async clear(e){f(e);let t=await n.count(e);await n.clear(e),t>0&&i(e)},async count(e){return f(e),n.count(e)},async delete(e,t){f(e);let r=await n.delete(e,t);return r&&i(e),r},async deleteMany(e,t){f(e);let r=await n.deleteMany(e,t);return r>0&&i(e),r},async get(e,t){return f(e),n.get(e,t)},async getAll(e){return f(e),n.getAll(e)},async getMany(e,t){return f(e),s(n,e,t)},async has(e,t){return f(e),n.has(e,t)},async isEmpty(e){return f(e),await n.count(e)===0},async keys(e,r){if(f(e),r){let i=await n.getAll(e),a=t[e].key;return i.filter(r).map(e=>e[a])}if(n.getAllKeys)return n.getAllKeys(e);let i=await n.getAll(e),a=t[e].key;return i.map(e=>e[a])},async put(e,r,o){f(e),await n.put(e,d(e,r),a(t,e,o)),i(e)},async putAll(e,r,o){if(f(e),r.length===0)return;let s=r.map(t=>d(e,t));await n.putAll(e,s,a(t,e,o)),i(e)},query(e){return f(e),r.createQueryBuilder(c(e,n,t,i))},async update(e,r,s,c){f(e);let l=await n.get(e,r);if(!l)return;let u={...l,...s};return o(t,e,r,u,`update`),await n.put(e,d(e,u),a(t,e,c)),i(e),u},async upsert(e,r,s,c){f(e);let l=s(await n.get(e,r));return o(t,e,r,l,`upsert: fn()`),await n.put(e,d(e,l),a(t,e,c)),i(e),l}}}function u(t,i,a){let{validators:o}=a??{},s=n.createObserverHub(e=>i.getAll(e)),u=e=>{s.notify(e),a?.onMutation?.(e)},d=e=>{s.notify(e)},f=i.pruneAllExpired?.bind(i),p=a?.onCrossTabMessage?.(d)??void 0,m=(t,n)=>{let r=o?.[t];if(!r)return n;try{return r.parse(n)}catch(n){throw new e.VaultError(`validation failed for table "${t}"`,{cause:n})}};a?.onTransactions?.({notifyMutation:u,validate:m});let h=l(t,i,u,m),g=new AbortController,_=!1,v=()=>{if(_)throw new e.VaultDisposedError},y={async clear(e){v(),await h.clear(e)},async count(e){return v(),i.count(e)},async delete(e,t){return v(),h.delete(e,t)},async deleteMany(e,t){return v(),h.deleteMany(e,t)},get disposalSignal(){return g.signal},async dispose(){_||(_=!0,g.abort(),p?.(),s.dispose(),await i.dispose?.())},get disposed(){return _},async get(e,t){return v(),h.get(e,t)},async getAll(e){return v(),h.getAll(e)},async getMany(e,t){return v(),h.getMany(e,t)},async has(e,t){return v(),h.has(e,t)},async isEmpty(e){return v(),await i.count(e)===0},async keys(e,t){return v(),h.keys(e,t)},observe(e,t,n){return v(),s.observe(e,t,n)},async pruneExpired(){if(v(),f)return await f();let e=Object.keys(t),n=await Promise.all(e.map(async e=>[e,await i.pruneExpiredInTable(e)]));return Object.fromEntries(n)},async put(e,t,n){v(),await h.put(e,t,n)},async putAll(e,t,n){v(),await h.putAll(e,t,n)},query(e){return v(),r.createQueryBuilder(c(e,i,t,u))},async[Symbol.asyncDispose](){await y.dispose()},async update(e,t,n,r){return v(),h.update(e,t,n,r)},async upsert(e,t,n,r){return v(),h.upsert(e,t,n,r)}};return y}function d(e,t){return Object.assign(e,{batch:t})}exports.assertBatchTables=i,exports.buildAdapterOps=u,exports.buildTxContext=l,exports.withIndexedDbTransactions=d;
1
+ const e=require("./codec.cjs"),t=require("./errors.cjs"),n=require("./internal.cjs"),r=require("./query.cjs"),i=require("./ttl.cjs");function a(e){if(e.length===0)throw new t.VaultError(`batch: declare at least one table`)}function o(e,t,n){return n!==void 0&&i.assertPositiveFinite(n,`put/putAll`),n??e[t].defaultTtl}function s(e,r,i,a,o){let s=n.getRecordKey(e,r,a);if(s!==i)throw new t.VaultError(`${o}: key field "${e[r].key}" must be "${String(i)}" but got "${String(s)}" in table "${r}"`)}function c(n){return(r,i)=>{let a=n?.[r];if(!a)return i;try{return e.validateRecord(a,i)}catch(e){throw new t.VaultError(`validation failed for table "${r}"`,{cause:e})}}}function l(e,i,a,c,l,u=()=>!0){let d=c??((e,t)=>t),f=e=>{if(!u())throw new t.VaultScopeError(`transaction context is no longer active`);if(l&&!l.has(e))throw new t.VaultScopeError(`table "${e}" is not part of this batch scope`)},p={async clear(e){f(e),await i.clear(e),a(e)},async count(e){return f(e),i.count?i.count(e):(await i.getAll(e)).length},async delete(e,t){f(e);let n=await i.delete(e,t);return n&&a(e),n},async deleteMany(e,t){if(f(e),!i.deleteMany){let n=(await Promise.all(t.map(t=>i.delete(e,t)))).filter(Boolean).length;return n>0&&a(e),n}let n=await i.deleteMany(e,t);return n>0&&a(e),n},async get(e,t){return f(e),i.get(e,t)},async getAll(e){return f(e),i.getAll(e)},async getMany(e,t){return f(e),i.getMany?i.getMany(e,t):Promise.all(t.map(t=>i.get(e,t)))},async has(e,t){return f(e),i.has?i.has(e,t):await i.get(e,t)!==void 0},async isEmpty(e){return await p.count(e)===0},iterate(e){return f(e),i.iterate?i.iterate(e):(async function*(){let t=await i.getAll(e);for(let e of t)yield e})()},async keys(t,n){if(f(t),!n&&i.getAllKeys)return i.getAllKeys(t);let r=await i.getAll(t),a=n?r.filter(n):r,o=e[t].key;return a.map(e=>e[o])},async put(t,n,r){f(t);let s=d(t,n);return await i.put(t,s,o(e,t,r)),a(t),s},async putAll(t,n,r){if(f(t),n.length===0)return;let s=n.map(e=>d(t,e));await i.putAll(t,s,o(e,t,r)),a(t)},query(t){return f(t),r.createQueryBuilder({deleteMany:async r=>{let i=r.map(r=>n.getRecordKey(e,t,r));return p.deleteMany(t,i)},source:()=>p.getAll(t)})},async update(t,n,r,i){let a=await p.get(t,n);if(a===void 0)return;let o={...a,...r};return s(e,t,n,o,`update`),p.put(t,o,i)},async upsert(t,n,r,i){let a=r(await p.get(t,n));return s(e,t,n,a,`upsert: update()`),p.put(t,a,i)}};return p}function u(e,i,a){let{codecs:l}=a??{},u=n.createObserverHub(e=>i.getAll(e)),d=e=>{u.notify(e),a?.onMutation?.(e)},f=e=>{u.notify(e)},p=i.pruneAllExpired?.bind(i),m=a?.onCrossTabMessage?.(f)??void 0,h=c(l);a?.onTransactions?.({notifyMutation:d,validate:h});let g=new AbortController,_=!1,v=()=>{if(_)throw new t.VaultDisposedError},y={async clear(e){v(),await i.clear(e),d(e)},async count(e){return v(),i.count?i.count(e):(await i.getAll(e)).length},async delete(e,t){v();let n=await i.delete(e,t);return n&&d(e),n},async deleteMany(e,t){v();let n=i.deleteMany?await i.deleteMany(e,t):(await Promise.all(t.map(t=>i.delete(e,t)))).filter(Boolean).length;return n>0&&d(e),n},get disposalSignal(){return g.signal},async dispose(){_||(_=!0,g.abort(),m?.(),u.dispose(),await i.dispose?.())},get disposed(){return _},async get(e,t){return v(),i.get(e,t)},async getAll(e){return v(),i.getAll(e)},async getMany(e,t){return v(),i.getMany?i.getMany(e,t):Promise.all(t.map(t=>i.get(e,t)))},async has(e,t){return v(),i.has?i.has(e,t):await i.get(e,t)!==void 0},async isEmpty(e){return await y.count(e)===0},async keys(t,n){if(v(),!n&&i.getAllKeys)return i.getAllKeys(t);let r=await i.getAll(t),a=n?r.filter(n):r,o=e[t].key;return a.map(e=>e[o])},observe(e,t,n){return v(),u.observe(e,t,n)},async pruneExpired(){if(v(),p){let e=await p();for(let[t,n]of Object.entries(e))n>0&&d(t);return e}let t=Object.keys(e),n=await Promise.all(t.map(async e=>[e,await i.pruneExpiredInTable(e)]));for(let[e,t]of n)t>0&&d(e);return Object.fromEntries(n)},async put(t,n,r){v();let a=h(t,n);return await i.put(t,a,o(e,t,r)),d(t),a},async putAll(t,n,r){if(v(),n.length===0)return;let a=n.map(e=>h(t,e));await i.putAll(t,a,o(e,t,r)),d(t)},query(t){return v(),r.createQueryBuilder({deleteMany:async r=>{let i=r.map(r=>n.getRecordKey(e,t,r));return y.deleteMany(t,i)},source:()=>y.getAll(t)})},async update(t,n,r,i){let a=await y.get(t,n);if(a===void 0)return;let o={...a,...r};return s(e,t,n,o,`update`),y.put(t,o,i)},async upsert(t,n,r,i){let a=r(await y.get(t,n));return s(e,t,n,a,`upsert: apply()`),y.put(t,a,i)},async[Symbol.asyncDispose](){await y.dispose()}};return y}function d(e,n,r){let i=u(e,n,r);return Object.assign(i,{iterate(e){if(i.disposed)throw new t.VaultDisposedError;return n.iterate?n.iterate(e):(async function*(){for(let t of await i.getAll(e))yield t})()}})}function f(e,i,a){let o=(n,r)=>e.disposed?Promise.reject(new t.VaultDisposedError):i(n,r);return Object.assign(e,{batch:o,deleteMany(e,t){return o([e],n=>n.deleteMany(e,t))},query(i){if(e.disposed)throw new t.VaultDisposedError;return r.createQueryBuilder({deleteMany:async e=>{let t=e.map(e=>n.getRecordKey(a,i,e));return o([i],e=>e.deleteMany(i,t))},source:()=>e.getAll(i)})},update(e,t,n,r){return o([e],i=>i.update(e,t,n,r))},upsert(e,t,n,r){return o([e],i=>i.upsert(e,t,n,r))}})}async function p(e,t,n){return e.has(t,n)}async function m(e,t){return e.count(t)}async function h(e,t){return e.isEmpty(t)}async function g(e,t,n){return e.getMany(t,n)}async function _(e,t,n){return e.keys(t,n)}async function v(e,t,n){return e.deleteMany(t,n)}async function y(e,t,n,r,i){return e.update(t,n,r,i)}async function b(e,t,n,r,i){return e.upsert(t,n,r,i)}exports.assertBatchTables=a,exports.buildDocumentStore=d,exports.buildKeyValueStore=u,exports.buildTxContext=l,exports.count=m,exports.deleteMany=v,exports.getMany=g,exports.has=p,exports.isEmpty=h,exports.keys=_,exports.makeValidator=c,exports.update=y,exports.upsert=b,exports.withBatch=f;
2
2
  //# sourceMappingURL=adapter-core.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"adapter-core.cjs","names":[],"sources":["../src/adapter-core.ts"],"sourcesContent":["import { VaultDisposedError, VaultError, VaultScopeError } from './errors';\nimport { createObserverHub, getRecordKey } from './internal';\nimport { createQueryBuilder, type QueryContext } from './query';\nimport { assertPositiveFinite } from './ttl';\nimport type {\n AnySchema,\n BaseAdapterOptions,\n KeyOf,\n RecordOf,\n TransactionalVaultStore,\n TransactionContext,\n VaultStore,\n} from './types';\n\n/* -------------------- Internal backend protocol -------------------- */\n\n/** @internal Full backend protocol implemented by each adapter. A single flat interface — no StorageCore/StorageBackend split. */\nexport type StorageBackend<S extends AnySchema, K extends keyof S & string = keyof S & string> = {\n clear<T extends K>(table: T): Promise<void>;\n /** Returns live (non-expired) record count for the table. */\n count<T extends K>(table: T): Promise<number>;\n delete<T extends K>(table: T, key: KeyOf<S, T>): Promise<boolean>;\n deleteMany<T extends K>(table: T, keys: KeyOf<S, T>[]): Promise<number>;\n dispose?(): Promise<void>;\n get<T extends K>(table: T, key: KeyOf<S, T>): Promise<RecordOf<S, T> | undefined>;\n getAll<T extends K>(table: T): Promise<RecordOf<S, T>[]>;\n /**\n * Optional: fetch all live primary keys without materialising full records.\n * When present, `keys()` uses this instead of `getAll()` + key extraction.\n * For tables with TTL, implementations may still fall back to `getAll()` to\n * filter expired keys accurately.\n */\n getAllKeys?<T extends K>(table: T): Promise<KeyOf<S, T>[]>;\n /**\n * Optional: fetch multiple records by key in a single operation. Preserves key order; missing keys yield\n * `undefined`. Falls back to N individual `get` calls when absent.\n */\n getMany?<T extends K>(table: T, keys: KeyOf<S, T>[]): Promise<Array<RecordOf<S, T> | undefined>>;\n has<T extends K>(table: T, key: KeyOf<S, T>): Promise<boolean>;\n /**\n * Optional: prune all expired records across all tables in a single atomic operation.\n * When present, `pruneExpired()` delegates here instead of calling `pruneExpiredInTable` N times.\n */\n pruneAllExpired?(): Promise<Record<string, number>>;\n pruneExpiredInTable<T extends K>(table: T): Promise<number>;\n put<T extends K>(table: T, value: RecordOf<S, T>, ttl?: number): Promise<void>;\n putAll<T extends K>(table: T, values: RecordOf<S, T>[], ttl?: number): Promise<void>;\n};\n\n/** @internal */\nexport type BatchDeps<S extends AnySchema> = {\n notifyMutation: (table: keyof S & string) => void;\n validate: <K extends keyof S & string>(table: K, value: RecordOf<S, K>) => RecordOf<S, K>;\n};\n\n/** @internal */\nexport type BatchImpl<S extends AnySchema> = <K extends keyof S & string, R>(\n tables: readonly K[],\n fn: (tx: TransactionContext<S, K>) => Promise<R>,\n) => Promise<R>;\n\n/* -------------------- Helpers -------------------- */\n\nexport function assertBatchTables(tables: readonly string[]): void {\n if (tables.length === 0) throw new VaultError('batch: declare at least one table');\n}\n\nfunction resolveTtl<S extends AnySchema, K extends keyof S & string>(\n schema: S,\n table: K,\n ttl?: number,\n): number | undefined {\n if (ttl !== undefined) assertPositiveFinite(ttl, 'put/putAll');\n\n return ttl ?? schema[table].defaultTtl;\n}\n\nfunction verifyKey<S extends AnySchema, K extends keyof S & string>(\n schema: S,\n table: K,\n expected: KeyOf<S, K>,\n value: RecordOf<S, K>,\n op: string,\n): void {\n const actual = getRecordKey(schema, table, value);\n\n if (actual !== expected) {\n throw new VaultError(\n `${op}: key field \"${schema[table].key}\" must be \"${String(expected)}\" but got \"${String(actual)}\" in table \"${table}\"`,\n );\n }\n}\n\nfunction getManyWithFallback<S extends AnySchema, K extends keyof S & string>(\n core: Pick<StorageBackend<S, K>, 'get' | 'getMany'>,\n table: K,\n keys: KeyOf<S, K>[],\n): Promise<Array<RecordOf<S, K> | undefined>> {\n if (core.getMany) return core.getMany(table, keys);\n\n return Promise.all(keys.map((k) => core.get(table, k)));\n}\n\nfunction buildQueryCtx<S extends AnySchema, K extends keyof S & string>(\n table: K,\n core: Pick<StorageBackend<S, K>, 'deleteMany' | 'getAll'>,\n schema: S,\n onMutate: (t: K) => void,\n): QueryContext<RecordOf<S, K>> {\n const deleteManyFn = async (records: RecordOf<S, K>[]): Promise<number> => {\n if (records.length === 0) return 0;\n\n const keys = records.map((r) => getRecordKey(schema, table, r));\n const deleted = await core.deleteMany(table, keys);\n\n if (deleted > 0) onMutate(table);\n\n return deleted;\n };\n\n return {\n deleteMany: deleteManyFn,\n source: () => core.getAll(table),\n };\n}\n\n/* -------------------- buildTxContext -------------------- */\n\nexport function buildTxContext<S extends AnySchema, K extends keyof S & string>(\n schema: S,\n core: StorageBackend<S, K>,\n onMutate: (table: K) => void,\n validate?: <T extends K>(table: T, value: RecordOf<S, T>) => RecordOf<S, T>,\n scope?: ReadonlySet<string>,\n): TransactionContext<S, K> {\n const applyValidation = validate ?? ((_: K, v: RecordOf<S, K>) => v);\n\n const checkScope = scope\n ? (t: K): void => {\n if (!scope.has(t)) {\n throw new VaultScopeError(`table \"${t}\" is not part of this batch scope`);\n }\n }\n : (_t: K): void => {};\n\n return {\n async clear(table) {\n checkScope(table);\n\n const live = await core.count(table);\n\n await core.clear(table);\n\n if (live > 0) onMutate(table);\n },\n async count(table) {\n checkScope(table);\n\n return core.count(table);\n },\n async delete(table, key) {\n checkScope(table);\n\n const deleted = await core.delete(table, key);\n\n if (deleted) onMutate(table);\n\n return deleted;\n },\n async deleteMany(table, keys) {\n checkScope(table);\n\n const deleted = await core.deleteMany(table, keys);\n\n if (deleted > 0) onMutate(table);\n\n return deleted;\n },\n async get(table, key) {\n checkScope(table);\n\n return core.get(table, key);\n },\n async getAll(table) {\n checkScope(table);\n\n return core.getAll(table);\n },\n async getMany(table, keys) {\n checkScope(table);\n\n return getManyWithFallback(core, table, keys);\n },\n async has(table, key) {\n checkScope(table);\n\n return core.has(table, key);\n },\n async isEmpty(table) {\n checkScope(table);\n\n return (await core.count(table)) === 0;\n },\n async keys(table, filter) {\n checkScope(table);\n\n if (filter) {\n const records = await core.getAll(table);\n const keyField = schema[table].key;\n\n return records.filter(filter).map((r) => (r as Record<string, unknown>)[keyField] as KeyOf<S, typeof table>);\n }\n\n // R1: prefer native getAllKeys when the backend supports it (e.g. IDB store.getAllKeys).\n if (core.getAllKeys) {\n return core.getAllKeys(table);\n }\n\n const records = await core.getAll(table);\n const keyField = schema[table].key;\n\n return records.map((r) => (r as Record<string, unknown>)[keyField] as KeyOf<S, typeof table>);\n },\n async put(table, value, ttl) {\n checkScope(table);\n\n await core.put(table, applyValidation(table, value), resolveTtl(schema, table, ttl));\n onMutate(table);\n },\n async putAll(table, values, ttl) {\n checkScope(table);\n\n if (values.length === 0) return;\n\n const toWrite = values.map((v) => applyValidation(table, v));\n\n await core.putAll(table, toWrite, resolveTtl(schema, table, ttl));\n onMutate(table);\n },\n query(table) {\n checkScope(table);\n\n return createQueryBuilder(buildQueryCtx(table, core, schema, onMutate));\n },\n async update(table, key, changes, ttl) {\n checkScope(table);\n\n const current = await core.get(table, key);\n\n if (!current) return undefined;\n\n const merged = { ...current, ...changes } as RecordOf<S, typeof table>;\n\n verifyKey(schema, table, key, merged, 'update');\n await core.put(table, applyValidation(table, merged), resolveTtl(schema, table, ttl));\n onMutate(table);\n\n return merged;\n },\n async upsert(table, key, fn, ttl) {\n checkScope(table);\n\n const existing = await core.get(table, key);\n const value = fn(existing);\n\n verifyKey(schema, table, key, value, 'upsert: fn()');\n await core.put(table, applyValidation(table, value), resolveTtl(schema, table, ttl));\n onMutate(table);\n\n return value;\n },\n };\n}\n\n/* -------------------- buildAdapterOps -------------------- */\n\n/** Builds the portable surface first; IndexedDB opts into transactions at its factory boundary. */\nexport function buildAdapterOps<S extends AnySchema>(\n schema: S,\n core: StorageBackend<S>,\n options?: BaseAdapterOptions<S> & {\n onCrossTabMessage?: (notify: (table: keyof S & string) => void) => (() => void) | undefined;\n onMutation?: (table: keyof S & string) => void;\n onTransactions?: (deps: BatchDeps<S>) => void;\n },\n): VaultStore<S> {\n const { validators } = options ?? {};\n\n const observers = createObserverHub<S>((table) => core.getAll(table));\n\n const notifyMutation = (table: keyof S & string): void => {\n observers.notify(table);\n options?.onMutation?.(table);\n };\n\n // Cross-tab notifications must NOT call onMutation (which would re-publish to BroadcastChannel,\n // creating an infinite loop). They only notify local observers.\n const notifyExternal = (table: keyof S & string): void => {\n observers.notify(table);\n };\n\n // R6: Resolve optional backend capabilities once at construction — no per-call checks.\n const pruneAll = core.pruneAllExpired?.bind(core);\n\n const disconnectExternal = options?.onCrossTabMessage?.(notifyExternal) ?? undefined;\n\n const validate = <K extends keyof S & string>(table: K, value: RecordOf<S, K>): RecordOf<S, K> => {\n const validator = validators?.[table];\n\n if (!validator) return value;\n\n try {\n return validator.parse(value) as RecordOf<S, K>;\n } catch (err) {\n throw new VaultError(`validation failed for table \"${table}\"`, { cause: err });\n }\n };\n\n options?.onTransactions?.({ notifyMutation, validate });\n\n const txCtx = buildTxContext<S, keyof S & string>(schema, core, notifyMutation, validate);\n\n const disposeController = new AbortController();\n let disposed = false;\n\n const checkDisposed = (): void => {\n if (disposed) throw new VaultDisposedError();\n };\n\n const adapter: VaultStore<S> = {\n async clear(table) {\n checkDisposed();\n await txCtx.clear(table);\n },\n\n async count(table) {\n checkDisposed();\n\n return core.count(table);\n },\n\n async delete(table, key) {\n checkDisposed();\n\n return txCtx.delete(table, key);\n },\n\n async deleteMany(table, keys) {\n checkDisposed();\n\n return txCtx.deleteMany(table, keys);\n },\n\n get disposalSignal(): AbortSignal {\n return disposeController.signal;\n },\n\n async dispose() {\n if (disposed) return;\n\n disposed = true;\n disposeController.abort();\n disconnectExternal?.();\n observers.dispose();\n await core.dispose?.();\n },\n\n get disposed(): boolean {\n return disposed;\n },\n\n async get(table, key) {\n checkDisposed();\n\n return txCtx.get(table, key);\n },\n\n async getAll(table) {\n checkDisposed();\n\n return txCtx.getAll(table);\n },\n\n async getMany(table, keys) {\n checkDisposed();\n\n return txCtx.getMany(table, keys);\n },\n\n async has(table, key) {\n checkDisposed();\n\n return txCtx.has(table, key);\n },\n\n async isEmpty(table) {\n checkDisposed();\n\n return (await core.count(table)) === 0;\n },\n\n async keys(table, filter) {\n checkDisposed();\n\n return txCtx.keys(table, filter);\n },\n\n observe(table, listener, opts) {\n checkDisposed();\n\n return observers.observe(table, listener, opts);\n },\n\n async pruneExpired() {\n checkDisposed();\n\n if (pruneAll) {\n const result = await pruneAll();\n\n return result as { [K in keyof S & string]: number };\n }\n\n const tableNames = Object.keys(schema) as Array<keyof S & string>;\n const pairs = await Promise.all(\n tableNames.map(async (name) => {\n const pruned = await core.pruneExpiredInTable(name);\n\n return [name, pruned] as const;\n }),\n );\n\n return Object.fromEntries(pairs) as { [K in keyof S & string]: number };\n },\n\n async put(table, value, ttl) {\n checkDisposed();\n await txCtx.put(table, value, ttl);\n },\n\n async putAll(table, values, ttl) {\n checkDisposed();\n await txCtx.putAll(table, values, ttl);\n },\n\n query(table) {\n checkDisposed();\n\n return createQueryBuilder(buildQueryCtx(table, core, schema, notifyMutation));\n },\n\n async [Symbol.asyncDispose]() {\n await adapter.dispose();\n },\n\n async update(table, key, changes, ttl) {\n checkDisposed();\n\n return txCtx.update(table, key, changes, ttl);\n },\n\n async upsert(table, key, fn, ttl) {\n checkDisposed();\n\n return txCtx.upsert(table, key, fn, ttl);\n },\n };\n\n return adapter;\n}\n\n/** IndexedDB is the only backend that can bind this callback to one native transaction. */\nexport function withIndexedDbTransactions<S extends AnySchema>(\n store: VaultStore<S>,\n batch: BatchImpl<S>,\n): TransactionalVaultStore<S> {\n return Object.assign(store, { batch }) as TransactionalVaultStore<S>;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"adapter-core.cjs","names":[],"sources":["../src/adapter-core.ts"],"sourcesContent":["import { validateRecord } from './codec';\nimport { VaultDisposedError, VaultError, VaultScopeError } from './errors';\nimport { createObserverHub, getRecordKey } from './internal';\nimport { createQueryBuilder } from './query';\nimport { assertPositiveFinite } from './ttl';\nimport type {\n AnySchema,\n DocumentVaultStore,\n DurableStoreOptions,\n KeyOf,\n KeyValueVaultStore,\n MemoryStoreOptions,\n RecordOf,\n TableCodecs,\n TransactionContext,\n} from './types';\n\n/* -------------------- Internal backend protocol -------------------- */\n\n/** @internal Full backend protocol implemented by each adapter. */\nexport type StorageBackend<S extends AnySchema, K extends keyof S & string = keyof S & string> = {\n clear<T extends K>(table: T): Promise<void>;\n count?<T extends K>(table: T): Promise<number>;\n delete<T extends K>(table: T, key: KeyOf<S, T>): Promise<boolean>;\n deleteMany?<T extends K>(table: T, keys: readonly KeyOf<S, T>[]): Promise<number>;\n dispose?(): Promise<void>;\n get<T extends K>(table: T, key: KeyOf<S, T>): Promise<RecordOf<S, T> | undefined>;\n getAll<T extends K>(table: T): Promise<RecordOf<S, T>[]>;\n getAllKeys?<T extends K>(table: T): Promise<KeyOf<S, T>[]>;\n getMany?<T extends K>(table: T, keys: readonly KeyOf<S, T>[]): Promise<Array<RecordOf<S, T> | undefined>>;\n has?<T extends K>(table: T, key: KeyOf<S, T>): Promise<boolean>;\n /**\n * Optional: lazy iteration over live records. Document stores implement this natively\n * (IDB cursor, SQLite keyset pagination). Key-value stores fall back to getAll().\n */\n iterate?<T extends K>(table: T): AsyncIterable<RecordOf<S, T>>;\n /**\n * Optional: prune all expired records across all tables in a single atomic operation.\n * When present, `pruneExpired()` delegates here instead of calling `pruneExpiredInTable` N times.\n */\n pruneAllExpired?(): Promise<Record<string, number>>;\n pruneExpiredInTable<T extends K>(table: T): Promise<number>;\n put<T extends K>(table: T, value: RecordOf<S, T>, ttl?: number): Promise<void>;\n putAll<T extends K>(table: T, values: readonly RecordOf<S, T>[], ttl?: number): Promise<void>;\n};\n\n/** @internal */\nexport type BatchDeps<S extends AnySchema> = {\n notifyMutation: (table: keyof S & string) => void;\n validate: <K extends keyof S & string>(table: K, value: RecordOf<S, K>) => RecordOf<S, K>;\n};\n\n/** @internal */\nexport type BatchImpl<S extends AnySchema> = <K extends keyof S & string, R>(\n tables: readonly K[],\n fn: (tx: TransactionContext<S, K>) => Promise<R>,\n) => Promise<R>;\n\n/* -------------------- Helpers -------------------- */\n\nexport function assertBatchTables(tables: readonly string[]): void {\n if (tables.length === 0) throw new VaultError('batch: declare at least one table');\n}\n\nfunction resolveTtl<S extends AnySchema, K extends keyof S & string>(\n schema: S,\n table: K,\n ttl?: number,\n): number | undefined {\n if (ttl !== undefined) assertPositiveFinite(ttl, 'put/putAll');\n\n return ttl ?? schema[table].defaultTtl;\n}\n\nfunction verifyKey<S extends AnySchema, K extends keyof S & string>(\n schema: S,\n table: K,\n expected: KeyOf<S, K>,\n value: RecordOf<S, K>,\n op: string,\n): void {\n const actual = getRecordKey(schema, table, value);\n\n if (actual !== expected) {\n throw new VaultError(\n `${op}: key field \"${schema[table].key}\" must be \"${String(expected)}\" but got \"${String(actual)}\" in table \"${table}\"`,\n );\n }\n}\n\n/* -------------------- Codec helpers -------------------- */\n\nexport function makeValidator<S extends AnySchema>(\n codecs: TableCodecs<S> | undefined,\n): <K extends keyof S & string>(table: K, value: RecordOf<S, K>) => RecordOf<S, K> {\n return <K extends keyof S & string>(table: K, value: RecordOf<S, K>): RecordOf<S, K> => {\n const codec = codecs?.[table];\n\n if (!codec) return value;\n\n try {\n return validateRecord(codec, value);\n } catch (err) {\n throw new VaultError(`validation failed for table \"${table}\"`, { cause: err });\n }\n };\n}\n\n/* -------------------- buildTxContext -------------------- */\n\nexport function buildTxContext<S extends AnySchema, K extends keyof S & string>(\n schema: S,\n core: StorageBackend<S, K>,\n onMutate: (table: K) => void,\n validate?: <T extends K>(table: T, value: RecordOf<S, T>) => RecordOf<S, T>,\n scope?: ReadonlySet<string>,\n isActive: () => boolean = () => true,\n): TransactionContext<S, K> {\n const applyValidation = validate ?? ((_: K, v: RecordOf<S, K>) => v);\n\n const checkScope = (table: K): void => {\n if (!isActive()) throw new VaultScopeError('transaction context is no longer active');\n if (scope && !scope.has(table)) throw new VaultScopeError(`table \"${table}\" is not part of this batch scope`);\n };\n\n const context: TransactionContext<S, K> = {\n async clear(table) {\n checkScope(table);\n await core.clear(table);\n onMutate(table);\n },\n async count(table) {\n checkScope(table);\n return core.count ? core.count(table) : (await core.getAll(table)).length;\n },\n async delete(table, key) {\n checkScope(table);\n\n const deleted = await core.delete(table, key);\n\n if (deleted) onMutate(table);\n\n return deleted;\n },\n async deleteMany(table, keys) {\n checkScope(table);\n if (!core.deleteMany) {\n const results = await Promise.all(keys.map((key) => core.delete(table, key)));\n const deleted = results.filter(Boolean).length;\n if (deleted > 0) onMutate(table);\n return deleted;\n }\n const deleted = await core.deleteMany(table, keys);\n if (deleted > 0) onMutate(table);\n return deleted;\n },\n async get(table, key) {\n checkScope(table);\n\n return core.get(table, key);\n },\n async getAll(table) {\n checkScope(table);\n\n return core.getAll(table);\n },\n async getMany(table, keys) {\n checkScope(table);\n return core.getMany ? core.getMany(table, keys) : Promise.all(keys.map((key) => core.get(table, key)));\n },\n async has(table, key) {\n checkScope(table);\n return core.has ? core.has(table, key) : (await core.get(table, key)) !== undefined;\n },\n async isEmpty(table) {\n return (await context.count(table)) === 0;\n },\n iterate(table) {\n checkScope(table);\n\n if (core.iterate) return core.iterate(table);\n\n // Fallback: iterate over getAll() materialized records.\n return (async function* (): AsyncIterable<RecordOf<S, typeof table>> {\n const records = await core.getAll(table);\n\n for (const record of records) yield record;\n })();\n },\n async keys(table, filter) {\n checkScope(table);\n if (!filter && core.getAllKeys) return core.getAllKeys(table);\n const records = await core.getAll(table);\n const selected = filter ? records.filter(filter) : records;\n const keyField = schema[table].key;\n return selected.map((record) => (record as Record<string, unknown>)[keyField] as KeyOf<S, typeof table>);\n },\n async put(table, value, ttl) {\n checkScope(table);\n const canonical = applyValidation(table, value);\n await core.put(table, canonical, resolveTtl(schema, table, ttl));\n onMutate(table);\n return canonical;\n },\n async putAll(table, values, ttl) {\n checkScope(table);\n\n if (values.length === 0) return;\n\n const toWrite = values.map((v) => applyValidation(table, v));\n\n await core.putAll(table, toWrite, resolveTtl(schema, table, ttl));\n onMutate(table);\n },\n query(table) {\n checkScope(table);\n return createQueryBuilder({\n deleteMany: async (records) => {\n const keys = records.map((record) => getRecordKey(schema, table, record));\n return context.deleteMany(table, keys);\n },\n source: () => context.getAll(table),\n });\n },\n async update(table, key, changes, ttl) {\n const current = await context.get(table, key);\n if (current === undefined) return undefined;\n const merged = { ...current, ...changes } as RecordOf<S, typeof table>;\n verifyKey(schema, table, key, merged, 'update');\n return context.put(table, merged, ttl);\n },\n async upsert(table, key, update, ttl) {\n const value = update(await context.get(table, key));\n verifyKey(schema, table, key, value, 'upsert: update()');\n return context.put(table, value, ttl);\n },\n };\n\n return context;\n}\n\n/* -------------------- buildKeyValueStore -------------------- */\n\n/** Builds a KeyValueVaultStore from a backend and options. */\nexport function buildKeyValueStore<S extends AnySchema>(\n schema: S,\n core: StorageBackend<S>,\n options?: MemoryStoreOptions<S> & {\n onCrossTabMessage?: (notify: (table: keyof S & string) => void) => (() => void) | undefined;\n onMutation?: (table: keyof S & string) => void;\n onTransactions?: (deps: BatchDeps<S>) => void;\n },\n): KeyValueVaultStore<S> {\n const { codecs } = options ?? {};\n\n const observers = createObserverHub<S>((table) => core.getAll(table));\n\n const notifyMutation = (table: keyof S & string): void => {\n observers.notify(table);\n options?.onMutation?.(table);\n };\n\n // Cross-tab notifications must NOT call onMutation (which would re-publish to BroadcastChannel,\n // creating an infinite loop). They only notify local observers.\n const notifyExternal = (table: keyof S & string): void => {\n observers.notify(table);\n };\n\n const pruneAll = core.pruneAllExpired?.bind(core);\n\n const disconnectExternal = options?.onCrossTabMessage?.(notifyExternal) ?? undefined;\n\n const validate = makeValidator(codecs);\n\n options?.onTransactions?.({ notifyMutation, validate });\n\n const disposeController = new AbortController();\n let disposed = false;\n\n const checkDisposed = (): void => {\n if (disposed) throw new VaultDisposedError();\n };\n\n const adapter: KeyValueVaultStore<S> = {\n async clear(table) {\n checkDisposed();\n await core.clear(table);\n notifyMutation(table);\n },\n async count(table) {\n checkDisposed();\n return core.count ? core.count(table) : (await core.getAll(table)).length;\n },\n\n async delete(table, key) {\n checkDisposed();\n\n const deleted = await core.delete(table, key);\n\n if (deleted) notifyMutation(table);\n\n return deleted;\n },\n async deleteMany(table, keys) {\n checkDisposed();\n const deleted = core.deleteMany\n ? await core.deleteMany(table, keys)\n : (await Promise.all(keys.map((key) => core.delete(table, key)))).filter(Boolean).length;\n if (deleted > 0) notifyMutation(table);\n return deleted;\n },\n\n get disposalSignal(): AbortSignal {\n return disposeController.signal;\n },\n\n async dispose() {\n if (disposed) return;\n\n disposed = true;\n disposeController.abort();\n disconnectExternal?.();\n observers.dispose();\n await core.dispose?.();\n },\n\n get disposed(): boolean {\n return disposed;\n },\n\n async get(table, key) {\n checkDisposed();\n\n return core.get(table, key);\n },\n\n async getAll(table) {\n checkDisposed();\n\n return core.getAll(table);\n },\n async getMany(table, keys) {\n checkDisposed();\n return core.getMany ? core.getMany(table, keys) : Promise.all(keys.map((key) => core.get(table, key)));\n },\n async has(table, key) {\n checkDisposed();\n return core.has ? core.has(table, key) : (await core.get(table, key)) !== undefined;\n },\n async isEmpty(table) {\n return (await adapter.count(table)) === 0;\n },\n async keys(table, filter) {\n checkDisposed();\n if (!filter && core.getAllKeys) return core.getAllKeys(table);\n const records = await core.getAll(table);\n const selected = filter ? records.filter(filter) : records;\n const keyField = schema[table].key;\n return selected.map((record) => (record as Record<string, unknown>)[keyField] as KeyOf<S, typeof table>);\n },\n\n observe(table, listener, opts) {\n checkDisposed();\n\n return observers.observe(table, listener, opts);\n },\n\n async pruneExpired() {\n checkDisposed();\n\n if (pruneAll) {\n const result = await pruneAll();\n\n for (const [table, pruned] of Object.entries(result)) {\n if (pruned > 0) notifyMutation(table as keyof S & string);\n }\n\n return result as { [K in keyof S & string]: number };\n }\n\n const tableNames = Object.keys(schema) as Array<keyof S & string>;\n const pairs = await Promise.all(\n tableNames.map(async (name) => {\n const pruned = await core.pruneExpiredInTable(name);\n\n return [name, pruned] as const;\n }),\n );\n\n for (const [table, pruned] of pairs) {\n if (pruned > 0) notifyMutation(table);\n }\n\n return Object.fromEntries(pairs) as { [K in keyof S & string]: number };\n },\n\n async put(table, value, ttl) {\n checkDisposed();\n const canonical = validate(table, value);\n await core.put(table, canonical, resolveTtl(schema, table, ttl));\n notifyMutation(table);\n return canonical;\n },\n\n async putAll(table, values, ttl) {\n checkDisposed();\n\n if (values.length === 0) return;\n\n const toWrite = values.map((v) => validate(table, v));\n\n await core.putAll(table, toWrite, resolveTtl(schema, table, ttl));\n notifyMutation(table);\n },\n query(table) {\n checkDisposed();\n return createQueryBuilder({\n deleteMany: async (records) => {\n const keys = records.map((record) => getRecordKey(schema, table, record));\n return adapter.deleteMany(table, keys);\n },\n source: () => adapter.getAll(table),\n });\n },\n async update(table, key, changes, ttl) {\n const current = await adapter.get(table, key);\n if (current === undefined) return undefined;\n const merged = { ...current, ...changes } as RecordOf<S, typeof table>;\n verifyKey(schema, table, key, merged, 'update');\n return adapter.put(table, merged, ttl);\n },\n async upsert(table, key, apply, ttl) {\n const value = apply(await adapter.get(table, key));\n verifyKey(schema, table, key, value, 'upsert: apply()');\n return adapter.put(table, value, ttl);\n },\n\n async [Symbol.asyncDispose]() {\n await adapter.dispose();\n },\n };\n\n return adapter;\n}\n\n/* -------------------- buildDocumentStore -------------------- */\n\n/** A document store before batch() is attached. */\nexport type DocumentVaultStoreWithoutBatch<S extends AnySchema> = Omit<DocumentVaultStore<S>, 'batch'>;\n\n/** Builds a DocumentVaultStore (without batch) from a backend, codecs, and options. */\nexport function buildDocumentStore<S extends AnySchema>(\n schema: S,\n core: StorageBackend<S>,\n options: DurableStoreOptions<S> & {\n onCrossTabMessage?: (notify: (table: keyof S & string) => void) => (() => void) | undefined;\n onMutation?: (table: keyof S & string) => void;\n onTransactions?: (deps: BatchDeps<S>) => void;\n },\n): DocumentVaultStoreWithoutBatch<S> {\n const store = buildKeyValueStore(schema, core, options);\n\n return Object.assign(store, {\n iterate<K extends keyof S & string>(table: K): AsyncIterable<RecordOf<S, K>> {\n if (store.disposed) throw new VaultDisposedError();\n if (core.iterate) return core.iterate(table);\n return (async function* (): AsyncIterable<RecordOf<S, K>> {\n for (const record of await store.getAll(table)) yield record;\n })();\n },\n });\n}\n\n/** Attaches a batch() implementation to a document store. */\nexport function withBatch<S extends AnySchema>(\n store: DocumentVaultStoreWithoutBatch<S>,\n batch: BatchImpl<S>,\n schema: S,\n): DocumentVaultStore<S> {\n const runBatch: BatchImpl<S> = (tables, fn) => {\n if (store.disposed) return Promise.reject(new VaultDisposedError());\n return batch(tables, fn);\n };\n\n return Object.assign(store, {\n batch: runBatch,\n deleteMany<K extends keyof S & string>(table: K, keys: readonly KeyOf<S, K>[]) {\n return runBatch([table], (tx) => tx.deleteMany(table, keys));\n },\n query<K extends keyof S & string>(table: K) {\n if (store.disposed) throw new VaultDisposedError();\n return createQueryBuilder({\n deleteMany: async (records) => {\n const keys = records.map((record) => getRecordKey(schema, table, record));\n return runBatch([table], (tx) => tx.deleteMany(table, keys));\n },\n source: () => store.getAll(table),\n });\n },\n update<K extends keyof S & string>(table: K, key: KeyOf<S, K>, changes: Partial<RecordOf<S, K>>, ttl?: number) {\n return runBatch([table], (tx) => tx.update(table, key, changes, ttl));\n },\n upsert<K extends keyof S & string>(\n table: K,\n key: KeyOf<S, K>,\n apply: (existing: RecordOf<S, K> | undefined) => RecordOf<S, K>,\n ttl?: number,\n ) {\n return runBatch([table], (tx) => tx.upsert(table, key, apply, ttl));\n },\n }) as DocumentVaultStore<S>;\n}\n\n/* -------------------- Derived convenience helpers -------------------- */\n\n/** Check whether a record exists for the given key. */\nexport async function has<S extends AnySchema, K extends keyof S & string>(\n store: KeyValueVaultStore<S>,\n table: K,\n key: KeyOf<S, K>,\n): Promise<boolean> {\n return store.has(table, key);\n}\n\n/** Count live records in a table. */\nexport async function count<S extends AnySchema, K extends keyof S & string>(\n store: KeyValueVaultStore<S>,\n table: K,\n): Promise<number> {\n return store.count(table);\n}\n\n/** Check whether a table has no live records. */\nexport async function isEmpty<S extends AnySchema, K extends keyof S & string>(\n store: KeyValueVaultStore<S>,\n table: K,\n): Promise<boolean> {\n return store.isEmpty(table);\n}\n\n/** Fetch multiple records by key. Preserves key order; missing keys yield `undefined`. */\nexport async function getMany<S extends AnySchema, K extends keyof S & string>(\n store: KeyValueVaultStore<S>,\n table: K,\n keys: readonly KeyOf<S, K>[],\n): Promise<Array<RecordOf<S, K> | undefined>> {\n return store.getMany(table, keys);\n}\n\n/** Fetch all live primary keys for a table. */\nexport async function keys<S extends AnySchema, K extends keyof S & string>(\n store: KeyValueVaultStore<S>,\n table: K,\n filter?: (record: RecordOf<S, K>) => boolean,\n): Promise<KeyOf<S, K>[]> {\n return store.keys(table, filter);\n}\n\n/** Delete multiple records by key. Returns the count of records that were actually deleted. */\nexport async function deleteMany<S extends AnySchema, K extends keyof S & string>(\n store: KeyValueVaultStore<S>,\n table: K,\n keys: readonly KeyOf<S, K>[],\n): Promise<number> {\n return store.deleteMany(table, keys);\n}\n\n/** Partially update an existing record. Returns `undefined` when the key does not exist. */\nexport async function update<S extends AnySchema, K extends keyof S & string>(\n store: KeyValueVaultStore<S>,\n table: K,\n key: KeyOf<S, K>,\n changes: Partial<RecordOf<S, K>>,\n ttl?: number,\n): Promise<RecordOf<S, K> | undefined> {\n return store.update(table, key, changes, ttl);\n}\n\n/** Read-modify-write: the callback receives the current record (or `undefined`) and returns the value to store. */\nexport async function upsert<S extends AnySchema, K extends keyof S & string>(\n store: KeyValueVaultStore<S>,\n table: K,\n key: KeyOf<S, K>,\n apply: (existing: RecordOf<S, K> | undefined) => RecordOf<S, K>,\n ttl?: number,\n): Promise<RecordOf<S, K>> {\n return store.upsert(table, key, apply, ttl);\n}\n"],"mappings":"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"}
@@ -1,12 +1,37 @@
1
- import type { AnySchema, BaseAdapterOptions, RecordOf, TransactionalVaultStore, TransactionContext, VaultStore } from './types';
1
+ import type { AnySchema, DocumentVaultStore, DurableStoreOptions, KeyOf, KeyValueVaultStore, MemoryStoreOptions, RecordOf, TableCodecs, TransactionContext } from './types';
2
2
  export declare function assertBatchTables(tables: readonly string[]): void;
3
- export declare function buildTxContext<S extends AnySchema, K extends keyof S & string>(schema: S, core: StorageBackend<S, K>, onMutate: (table: K) => void, validate?: <T extends K>(table: T, value: RecordOf<S, T>) => RecordOf<S, T>, scope?: ReadonlySet<string>): TransactionContext<S, K>;
4
- /** Builds the portable surface first; IndexedDB opts into transactions at its factory boundary. */
5
- export declare function buildAdapterOps<S extends AnySchema>(schema: S, core: StorageBackend<S>, options?: BaseAdapterOptions<S> & {
3
+ export declare function makeValidator<S extends AnySchema>(codecs: TableCodecs<S> | undefined): <K extends keyof S & string>(table: K, value: RecordOf<S, K>) => RecordOf<S, K>;
4
+ export declare function buildTxContext<S extends AnySchema, K extends keyof S & string>(schema: S, core: StorageBackend<S, K>, onMutate: (table: K) => void, validate?: <T extends K>(table: T, value: RecordOf<S, T>) => RecordOf<S, T>, scope?: ReadonlySet<string>, isActive?: () => boolean): TransactionContext<S, K>;
5
+ /** Builds a KeyValueVaultStore from a backend and options. */
6
+ export declare function buildKeyValueStore<S extends AnySchema>(schema: S, core: StorageBackend<S>, options?: MemoryStoreOptions<S> & {
6
7
  onCrossTabMessage?: (notify: (table: keyof S & string) => void) => (() => void) | undefined;
7
8
  onMutation?: (table: keyof S & string) => void;
8
9
  onTransactions?: (deps: BatchDeps<S>) => void;
9
- }): VaultStore<S>;
10
- /** IndexedDB is the only backend that can bind this callback to one native transaction. */
11
- export declare function withIndexedDbTransactions<S extends AnySchema>(store: VaultStore<S>, batch: BatchImpl<S>): TransactionalVaultStore<S>;
10
+ }): KeyValueVaultStore<S>;
11
+ /** A document store before batch() is attached. */
12
+ export type DocumentVaultStoreWithoutBatch<S extends AnySchema> = Omit<DocumentVaultStore<S>, 'batch'>;
13
+ /** Builds a DocumentVaultStore (without batch) from a backend, codecs, and options. */
14
+ export declare function buildDocumentStore<S extends AnySchema>(schema: S, core: StorageBackend<S>, options: DurableStoreOptions<S> & {
15
+ onCrossTabMessage?: (notify: (table: keyof S & string) => void) => (() => void) | undefined;
16
+ onMutation?: (table: keyof S & string) => void;
17
+ onTransactions?: (deps: BatchDeps<S>) => void;
18
+ }): DocumentVaultStoreWithoutBatch<S>;
19
+ /** Attaches a batch() implementation to a document store. */
20
+ export declare function withBatch<S extends AnySchema>(store: DocumentVaultStoreWithoutBatch<S>, batch: BatchImpl<S>, schema: S): DocumentVaultStore<S>;
21
+ /** Check whether a record exists for the given key. */
22
+ export declare function has<S extends AnySchema, K extends keyof S & string>(store: KeyValueVaultStore<S>, table: K, key: KeyOf<S, K>): Promise<boolean>;
23
+ /** Count live records in a table. */
24
+ export declare function count<S extends AnySchema, K extends keyof S & string>(store: KeyValueVaultStore<S>, table: K): Promise<number>;
25
+ /** Check whether a table has no live records. */
26
+ export declare function isEmpty<S extends AnySchema, K extends keyof S & string>(store: KeyValueVaultStore<S>, table: K): Promise<boolean>;
27
+ /** Fetch multiple records by key. Preserves key order; missing keys yield `undefined`. */
28
+ export declare function getMany<S extends AnySchema, K extends keyof S & string>(store: KeyValueVaultStore<S>, table: K, keys: readonly KeyOf<S, K>[]): Promise<Array<RecordOf<S, K> | undefined>>;
29
+ /** Fetch all live primary keys for a table. */
30
+ export declare function keys<S extends AnySchema, K extends keyof S & string>(store: KeyValueVaultStore<S>, table: K, filter?: (record: RecordOf<S, K>) => boolean): Promise<KeyOf<S, K>[]>;
31
+ /** Delete multiple records by key. Returns the count of records that were actually deleted. */
32
+ export declare function deleteMany<S extends AnySchema, K extends keyof S & string>(store: KeyValueVaultStore<S>, table: K, keys: readonly KeyOf<S, K>[]): Promise<number>;
33
+ /** Partially update an existing record. Returns `undefined` when the key does not exist. */
34
+ export declare function update<S extends AnySchema, K extends keyof S & string>(store: KeyValueVaultStore<S>, table: K, key: KeyOf<S, K>, changes: Partial<RecordOf<S, K>>, ttl?: number): Promise<RecordOf<S, K> | undefined>;
35
+ /** Read-modify-write: the callback receives the current record (or `undefined`) and returns the value to store. */
36
+ export declare function upsert<S extends AnySchema, K extends keyof S & string>(store: KeyValueVaultStore<S>, table: K, key: KeyOf<S, K>, apply: (existing: RecordOf<S, K> | undefined) => RecordOf<S, K>, ttl?: number): Promise<RecordOf<S, K>>;
12
37
  //# sourceMappingURL=adapter-core.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"adapter-core.d.ts","sourceRoot":"","sources":["../src/adapter-core.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,SAAS,EACT,kBAAkB,EAElB,QAAQ,EACR,uBAAuB,EACvB,kBAAkB,EAClB,UAAU,EACX,MAAM,SAAS,CAAC;AAmDjB,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAEjE;AA+DD,wBAAgB,cAAc,CAAC,CAAC,SAAS,SAAS,EAAE,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAC5E,MAAM,EAAE,CAAC,EACT,IAAI,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,EAC1B,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,EAC5B,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3E,KAAK,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAC1B,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,CA0I1B;AAID,mGAAmG;AACnG,wBAAgB,eAAe,CAAC,CAAC,SAAS,SAAS,EACjD,MAAM,EAAE,CAAC,EACT,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EACvB,OAAO,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG;IAChC,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IAC5F,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,MAAM,KAAK,IAAI,CAAC;IAC/C,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;CAC/C,GACA,UAAU,CAAC,CAAC,CAAC,CAuLf;AAED,2FAA2F;AAC3F,wBAAgB,yBAAyB,CAAC,CAAC,SAAS,SAAS,EAC3D,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EACpB,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,GAClB,uBAAuB,CAAC,CAAC,CAAC,CAE5B"}
1
+ {"version":3,"file":"adapter-core.d.ts","sourceRoot":"","sources":["../src/adapter-core.ts"],"names":[],"mappings":"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"}