@metreeca/keep 0.10.0 → 0.11.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,36 +1,33 @@
1
- import type { Reference } from "@metreeca/qest/resource";
1
+ import type { Reference } from "@metreeca/qest/state";
2
2
  import type { Store } from "../index.js";
3
3
  /**
4
4
  * Creates a caching store backed by a delegate.
5
5
  *
6
- * Serves repeated retrievals from an in-memory cache, sparing the delegate a round-trip whenever a prior retrieval
7
- * can be reused; this cuts latency and backend load for read-heavy workloads, while writes and eviction keep cached
6
+ * Serves repeated retrievals from an in-memory cache, sparing the delegate a round-trip whenever a prior result can
7
+ * be reused. This cuts latency and backend load for read-heavy workloads, while writes and eviction keep cached
8
8
  * results coherent and bounded.
9
9
  *
10
- * Retrievals are memoised under an `(entry, model, locale, limit)` key, where the model is canonicalised bottom-up so
11
- * templates differing only in property or element order (including arrays of objects) share a cache entry, widening
12
- * the set of requests a single cached result can serve.
10
+ * Results are cached by `entry`, `model`, and the `locale` and `limit` of the {@link Store.lookup lookup} retrieval scope.
11
+ * Templates differing only in member or element order share a cached result.
13
12
  *
14
13
  * > [!IMPORTANT]
15
- * > `shape` is deliberately excluded from the cache key: the retrieval result must be a pure function of
16
- * > `(entry, model, locale, limit)`, with `shape` supplying only structural metadata that does not affect the
17
- * > returned payload.
14
+ * > `shape` is not part of the cache key. A retrieval result MUST depend only on `entry`, `model`, `locale` and
15
+ * > `limit`, with `shape` supplying structural metadata that does not affect the returned payload.
18
16
  *
19
17
  * > [!IMPORTANT]
20
- * > `opts.locale` is part of the cache key because it selects which localised content a retrieval returns. Unlike
21
- * > the model, the locale priority list is order-significant — `["en", "it"]` and `["it", "en"]` key separately —
22
- * > since order encodes language-negotiation preference. An omitted or empty locale list collapses to a single key,
23
- * > distinct from any explicit list.
18
+ * > The scope `locale` is part of the cache key, because it selects which localised content a retrieval returns.
19
+ * > Unlike the model, the locale priority list is order-significant: `["en", "it"]` and `["it", "en"]` are cached
20
+ * > separately. An omitted and an empty locale list share a single cached result, distinct from any explicit list.
24
21
  *
25
22
  * > [!IMPORTANT]
26
- * > `opts.limit` is part of the cache key because it caps each selection's `#` and so changes the returned payload,
27
- * > with an omitted or `0` limit collapsing to a single unbounded key. `opts.plain`/`opts.depth` are excluded: they
28
- * > only accept or reject a model, never altering a successful payload.
23
+ * > The scope `limit` is part of the cache key, because it caps the page size of each collection and so changes the
24
+ * > returned payload. An omitted and a `0` limit share a single cached result. The scope `plain` and `depth` are not
25
+ * > part of the key: they only accept or reject a model, and never alter a successful payload.
29
26
  *
30
27
  * The cache offers three observable guarantees:
31
28
  *
32
29
  * - **coalescing** — concurrent retrievals for the same key resolve from a single delegate fetch, and a failed
33
- * retrieval is never cached, so a later retrieval re-fetches;
30
+ * retrieval or one finding no resource is never cached, so a later retrieval re-fetches;
34
31
  * - **read-after-write coherence** — a retrieval never returns content staler than the latest write made through this
35
32
  * store: {@link Store.create create}, {@link Store.update update}, {@link Store.delete delete},
36
33
  * {@link Store.insert insert} and {@link Store.remove remove} invalidate matching entries, and a
@@ -80,9 +77,9 @@ export declare function createCachingStore(store: Store, { size, ttl, match }?:
80
77
  /**
81
78
  * Predicate deciding which cached records an invalidation event discards.
82
79
  *
83
- * Invoked by both invalidation paths — pre-commit writes on the wrapper and reactive mutation events from the
84
- * delegate — with the mutated resource's identifier and the identifier carried on each cached record. Return
85
- * true to evict the record.
80
+ * Invoked for writes made through the wrapper and for mutation events signalled by the delegate. It receives the
81
+ * identifier of the mutated resource and the identifier of each cached record, and returns `true` if the record
82
+ * is to be evicted.
86
83
  *
87
84
  * @param entry - Identifier of the mutated resource
88
85
  * @param cache - Identifier associated with a cached record
@@ -1 +1 @@
1
- {"version":3,"file":"caching.d.ts","sourceRoot":"","sources":["../../src/stores/caching.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEzD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,EAEhD,IAAQ,EACR,GAAO,EACP,KAAkB,EAElB,GAAE;IAEF;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAEvB;;;;;;;;OAQG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC;CAE5D,GAAG,KAAK,CAyUb"}
1
+ {"version":3,"file":"caching.d.ts","sourceRoot":"","sources":["../../src/stores/caching.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,EAEhD,IAAQ,EACR,GAAO,EACP,KAAkB,EAElB,GAAE;IAEF;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAEvB;;;;;;;;OAQG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC;CAE5D,GAAG,KAAK,CA0Vb"}
@@ -16,46 +16,42 @@
16
16
  /**
17
17
  * Caching store wrapper.
18
18
  *
19
- * Provides {@link createCachingStore}, which wraps a {@link Store} with an in-memory cache
20
- * supporting LRU and TTL-based eviction, in-flight request sharing, an in-flight write bypass that prevents
21
- * pre-commit values from being cached, and coherent invalidation driven by both the wrapper's own write
22
- * operations and the delegate's mutation events.
19
+ * Speeds up read-heavy workloads by serving repeated retrievals from an in-memory cache. The cache stays bounded
20
+ * by size and age, shares concurrent identical retrievals, and stays coherent with writes made through the store, by
21
+ * other clients, or signalled by the backend.
23
22
  *
24
23
  * @module
25
24
  */
26
25
  import { isArray, isObject } from "@metreeca/core";
27
- import { immutable } from "@metreeca/core/structures";
26
+ import { immutable } from "@metreeca/core/values";
28
27
  /**
29
28
  * Creates a caching store backed by a delegate.
30
29
  *
31
- * Serves repeated retrievals from an in-memory cache, sparing the delegate a round-trip whenever a prior retrieval
32
- * can be reused; this cuts latency and backend load for read-heavy workloads, while writes and eviction keep cached
30
+ * Serves repeated retrievals from an in-memory cache, sparing the delegate a round-trip whenever a prior result can
31
+ * be reused. This cuts latency and backend load for read-heavy workloads, while writes and eviction keep cached
33
32
  * results coherent and bounded.
34
33
  *
35
- * Retrievals are memoised under an `(entry, model, locale, limit)` key, where the model is canonicalised bottom-up so
36
- * templates differing only in property or element order (including arrays of objects) share a cache entry, widening
37
- * the set of requests a single cached result can serve.
34
+ * Results are cached by `entry`, `model`, and the `locale` and `limit` of the {@link Store.lookup lookup} retrieval scope.
35
+ * Templates differing only in member or element order share a cached result.
38
36
  *
39
37
  * > [!IMPORTANT]
40
- * > `shape` is deliberately excluded from the cache key: the retrieval result must be a pure function of
41
- * > `(entry, model, locale, limit)`, with `shape` supplying only structural metadata that does not affect the
42
- * > returned payload.
38
+ * > `shape` is not part of the cache key. A retrieval result MUST depend only on `entry`, `model`, `locale` and
39
+ * > `limit`, with `shape` supplying structural metadata that does not affect the returned payload.
43
40
  *
44
41
  * > [!IMPORTANT]
45
- * > `opts.locale` is part of the cache key because it selects which localised content a retrieval returns. Unlike
46
- * > the model, the locale priority list is order-significant — `["en", "it"]` and `["it", "en"]` key separately —
47
- * > since order encodes language-negotiation preference. An omitted or empty locale list collapses to a single key,
48
- * > distinct from any explicit list.
42
+ * > The scope `locale` is part of the cache key, because it selects which localised content a retrieval returns.
43
+ * > Unlike the model, the locale priority list is order-significant: `["en", "it"]` and `["it", "en"]` are cached
44
+ * > separately. An omitted and an empty locale list share a single cached result, distinct from any explicit list.
49
45
  *
50
46
  * > [!IMPORTANT]
51
- * > `opts.limit` is part of the cache key because it caps each selection's `#` and so changes the returned payload,
52
- * > with an omitted or `0` limit collapsing to a single unbounded key. `opts.plain`/`opts.depth` are excluded: they
53
- * > only accept or reject a model, never altering a successful payload.
47
+ * > The scope `limit` is part of the cache key, because it caps the page size of each collection and so changes the
48
+ * > returned payload. An omitted and a `0` limit share a single cached result. The scope `plain` and `depth` are not
49
+ * > part of the key: they only accept or reject a model, and never alter a successful payload.
54
50
  *
55
51
  * The cache offers three observable guarantees:
56
52
  *
57
53
  * - **coalescing** — concurrent retrievals for the same key resolve from a single delegate fetch, and a failed
58
- * retrieval is never cached, so a later retrieval re-fetches;
54
+ * retrieval or one finding no resource is never cached, so a later retrieval re-fetches;
59
55
  * - **read-after-write coherence** — a retrieval never returns content staler than the latest write made through this
60
56
  * store: {@link Store.create create}, {@link Store.update update}, {@link Store.delete delete},
61
57
  * {@link Store.insert insert} and {@link Store.remove remove} invalidate matching entries, and a
@@ -88,8 +84,8 @@ export function createCachingStore(store, { size = 0, ttl = 0, match = () => tru
88
84
  // moving it to the tail, so `cache.keys().next().value` is always the least-recently-used key.
89
85
  const cache = new Map();
90
86
  // Tracks entries with at least one in-flight wrapper-initiated write. Reads of these entries bypass the
91
- // cache entirely — they still query the delegate, but their result is not stored. This closes the window
92
- // between a lookup resolving with a pre-commit value and the reactive observer firing on commit, during
87
+ // cache entirely: they still query the delegate, but their result is not stored. This closes the window
88
+ // between a lookup call resolving with a pre-commit value and the reactive observer firing on commit, during
93
89
  // which the cache would otherwise hold a stale-but-fresh-looking record.
94
90
  const writing = new Map();
95
91
  // Reactive invalidation: subscribe to the delegate's mutation events and drop matching records on commit.
@@ -103,8 +99,8 @@ export function createCachingStore(store, { size = 0, ttl = 0, match = () => tru
103
99
  lookup({ entry, shape, model }, opts) {
104
100
  return memoise(entry, model, opts, () => store.lookup({ entry, shape, model }, opts));
105
101
  },
106
- create({ entry, shape, state }) {
107
- return write(entry, () => store.create({ entry, shape, state }));
102
+ create({ entry, shape, model, state }) {
103
+ return write(entry, () => store.create({ entry, shape, model, state }));
108
104
  },
109
105
  update({ entry, shape, state }) {
110
106
  return write(entry, () => store.update({ entry, shape, state }));
@@ -112,8 +108,8 @@ export function createCachingStore(store, { size = 0, ttl = 0, match = () => tru
112
108
  delete({ entry, shape }) {
113
109
  return write(entry, () => store.delete({ entry, shape }));
114
110
  },
115
- insert({ entry, shape, state }, opts) {
116
- return write(entry, () => store.insert({ entry, shape, state }, opts));
111
+ insert({ entry, shape, state }) {
112
+ return write(entry, () => store.insert({ entry, shape, state }));
117
113
  },
118
114
  remove({ entry, shape }) {
119
115
  return write(entry, () => store.remove({ entry, shape }));
@@ -139,57 +135,70 @@ export function createCachingStore(store, { size = 0, ttl = 0, match = () => tru
139
135
  * - **fresh hit** — returns the memoised promise and re-inserts the record to bump its LRU position;
140
136
  * - **miss / TTL-expired** — runs `miss()`, stores the pending promise under the canonicalised key so
141
137
  * concurrent callers share the in-flight request, and enforces TTL/size bounds via {@link purge}; a
142
- * rejected fetch evicts its record only if an intervening invalidation has not already replaced it.
138
+ * fetch resolving to an absent resource or rejecting evicts its record only if an intervening invalidation
139
+ * has not already replaced it.
143
140
  *
144
- * @param entry - Resource identifier; paired with the canonicalised model and varying opts to form the cache key
145
- * @param model - Retrieval template, canonicalised so that equivalent templates in different orderings share a key
146
- * @param vary - Retrieval opts whose values vary the returned payload, folded into the key: `locale`
141
+ * @typeParam V - The retrieved payload, opaque to the cache
142
+ *
143
+ * @param entry - Resource identifier; paired with the canonicalised model and varying scope members to form the
144
+ * cache key
145
+ * @param model - Retrieval model, canonicalised so that equivalent models in different orderings share a key
146
+ * @param vary - Retrieval scope members whose values vary the returned payload, folded into the key: `locale`
147
147
  * order-significantly (an omitted or empty list collapsing to a single key) and `limit` because it caps each
148
- * selection's `#` pagination bound (an omitted or `0` unbounded value collapsing to a single key)
148
+ * collection's `#` pagination bound (an omitted or `0` unbounded value collapsing to a single key)
149
149
  * @param miss - Fetcher invoked on cache miss, on TTL expiration, or while the entry has an in-flight write
150
150
  *
151
151
  * @returns The memoised, freshly-fetched, or bypass-fetched promise
152
152
  */
153
153
  function memoise(entry, model, vary = {}, miss) {
154
154
  // Bypass the cache while a write to this entry is in flight: still query the delegate so the caller
155
- // gets a value, but do not store the result — it is liable to be the pre-commit snapshot that the
155
+ // gets a value, but do not store the result: it is liable to be the pre-commit snapshot that the
156
156
  // reactive observer would invalidate moments later
157
157
  if (writing.has(entry)) {
158
158
  return miss();
159
159
  }
160
160
  else {
161
- // Cache key layout: `<entry>\x00<canonical-model>\x00<locale>\x00<limit>`. `canonical` walks the model
162
- // bottom-up, sorting object keys and (already-canonical) array elements, so templates differing only in
163
- // ordering share a key. The locale segment is serialised verbatim (order preserved, since the priority
161
+ // Cache key layout: `<entry>\x00<canonical-model>\x00<locale>\x00<limit>`. `canonical` walks the
162
+ // model bottom-up, sorting object keys and (already-canonical) array elements, so models differing only
163
+ // in ordering share a key. The locale segment is serialised verbatim (order preserved, since the priority
164
164
  // list is order-significant) with omitted and empty lists collapsing to `[]`. The limit segment is
165
- // keyed because it caps each selection's `#` and so changes the payload, with omitted and `0` (both
166
- // unbounded) collapsing to `0`. `\x00` is safe as a separator — IRIs cannot contain it and JSON always
165
+ // keyed because it caps each collection's `#` and so changes the payload, with omitted and `0` (both
166
+ // unbounded) collapsing to `0`. `\x00` is safe as a separator: IRIs cannot contain it and JSON always
167
167
  // escapes it inside string payloads.
168
- const key = `${entry}\x00${canonical(model)}\x00${JSON.stringify(vary.locale ?? [])}\x00${vary.limit ?? 0}`;
168
+ const key = [entry, canonical(model), JSON.stringify(vary.locale ?? []), vary.limit ?? 0].join("\x00");
169
169
  const cached = cache.get(key);
170
170
  if (cached && !expired(cached.created)) {
171
171
  // hit: re-insert to move the entry to the tail of the Map's iteration order (the LRU position),
172
- // and return the memoised promise; the cast reflects the type-erased `Promise<unknown>` storage
173
- // that lets records with different template types share one Map
172
+ // and return the memoised promise; ;(cast) the type-erased `Promise<unknown>` storage lets records
173
+ // with different payload types share one Map
174
174
  cache.delete(key);
175
175
  cache.set(key, cached);
176
176
  return cached.value;
177
177
  }
178
178
  else {
179
179
  // miss (or TTL-expired): drop any stale record, run the fetcher, and memoise the pending promise
180
- // under the same key so concurrent callers share the in-flight request; a failure evicts its own
181
- // record through the catch handler so transient errors are not retained
180
+ // under the same key so concurrent callers share the in-flight request; an absent resource or a
181
+ // failure evicts its own record once settled, so neither a missing resource nor a transient error
182
+ // is retained
182
183
  if (cached) {
183
184
  cache.delete(key);
184
185
  }
185
- const value = miss().catch(error => {
186
- // identity-check: only evict if this promise is still the cached one —
187
- // avoids dropping a newer record installed after an intervening invalidate
188
- if (cache.get(key)?.value === value) {
189
- cache.delete(key);
186
+ const value = miss().then(resource => {
187
+ if (resource === undefined) {
188
+ evict();
190
189
  }
190
+ return resource;
191
+ }, error => {
192
+ evict();
191
193
  throw error;
192
194
  });
195
+ // identity-check: only evict if this promise is still the cached one, avoiding dropping a newer
196
+ // record installed after an intervening invalidate
197
+ function evict() {
198
+ if (cache.get(key)?.value === value) {
199
+ cache.delete(key);
200
+ }
201
+ }
193
202
  cache.set(key, {
194
203
  entry,
195
204
  value,
@@ -203,7 +212,7 @@ export function createCachingStore(store, { size = 0, ttl = 0, match = () => tru
203
212
  /**
204
213
  * Serialises a value to a canonical JSON-like string.
205
214
  *
206
- * Children are canonicalised first, then sorted by their already-canonical string form — so arrays of
215
+ * Children are canonicalised first, then sorted by their already-canonical string form, so arrays of
207
216
  * objects are ordered by structural content rather than by the `"[object Object]"` placeholder that
208
217
  * `Array.prototype.sort` would otherwise impose. The output collapses values differing only in property
209
218
  * or element order to the same string.
@@ -288,7 +297,7 @@ export function createCachingStore(store, { size = 0, ttl = 0, match = () => tru
288
297
  * Runs two sweeps: first, when `ttl > 0`, drops every record older than `ttl` milliseconds; second, when
289
298
  * `size > 0` and the cache is overfull, drops the head slice of the Map (least-recently-used first) in
290
299
  * a single batch sized to the exact overflow. Invoked after every miss so expired siblings and overfill
291
- * are cleaned up incrementally — the cache has no background sweeper.
300
+ * are cleaned up incrementally, as the cache has no background sweeper.
292
301
  */
293
302
  function purge() {
294
303
  if (ttl > 0) {
@@ -300,7 +309,7 @@ export function createCachingStore(store, { size = 0, ttl = 0, match = () => tru
300
309
  }
301
310
  }
302
311
  // LRU sweep: when over the size bound, take the head slice of Map keys (insertion order = LRU first)
303
- // and drop them — `cache.size - size` is the exact overflow, so no loop condition needs re-checking
312
+ // and drop them: `cache.size - size` is the exact overflow, so no loop condition needs re-checking
304
313
  if (size > 0 && cache.size > size) {
305
314
  Array.from(cache.keys())
306
315
  .slice(0, cache.size - size)
@@ -1 +1 @@
1
- {"version":3,"file":"caching.js","sourceRoot":"","sources":["../../src/stores/caching.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"caching.js","sourceRoot":"","sources":["../../src/stores/caching.ts"],"names":[],"mappings":"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"}
@@ -1,55 +1,57 @@
1
- import type { Store, StoreClient } from "../index.js";
1
+ import type { Store } from "../index.js";
2
2
  /**
3
- * Manages mutation events, transactional execution, and lifecycle for a bare {@link StoreClient},
3
+ * Manages mutation events, transactional execution, and lifecycle for a connector's {@link StoreClient},
4
4
  * exposing it as a full {@link Store}.
5
5
  *
6
- * This lets a connector implement only the {@link StoreClient} data surface and obtain
7
- * mutation events, transactional execution, and lifecycle for free: supply nothing and the wrapper provides working
8
- * defaults, or hand it backend primitives through `management` to back any of `execute`, `observe`, or `close`.
6
+ * A connector can implement only the {@link StoreClient} data surface and still offer the full {@link Store}
7
+ * contract. The connector supplies its transaction primitive through `management.execute`, which hands the
8
+ * connector's {@link StoreClient} to every data call. The option is required, since only the connector knows what
9
+ * atomicity its backend can provide. Backend primitives supplied through `management` may also back `observe` or
10
+ * `close`, and the wrapper fills in whatever is missing.
9
11
  *
10
- * Each standalone mutation call and each {@link Store.execute execute} call accumulates its own
11
- * batch of mutation signals and delivers a single filtered event to each matching registered
12
- * {@link StoreObserver observer} when the call resolves; if it rejects, pending signals are discarded
13
- * and no observers are notified. Both synchronous throws and asynchronous rejections from observers
14
- * are caught and silently ignored so that one faulty observer cannot break delivery to others.
12
+ * Each standalone mutation call and each {@link Store.execute execute} call delivers a single filtered event to each
13
+ * matching {@link StoreObserver observer} once the call resolves. If the call rejects, its pending events are
14
+ * discarded and no observer is notified. Synchronous throws and asynchronous rejections from observers are caught and
15
+ * silently ignored, so one faulty observer cannot break delivery to others.
15
16
  *
16
- * Any of the {@link Store} management methods may be supplied through `management` to delegate to an inner
17
- * implementation; the wrapper fills in whatever is missing.
18
- *
19
- * All errors — `RangeError`, {@link @metreeca/core!TraceError | TraceError},
20
- * {@link @metreeca/http!Problem | Problem} —
21
- * propagate as promise rejections per the unified {@link Store} error channel.
17
+ * All errors, including {@link !RangeError RangeError}, {@link @metreeca/core!TraceError | TraceError} and
18
+ * {@link @metreeca/http!Problem | Problem}, propagate as promise rejections, in line with the unified {@link Store}
19
+ * error channel.
22
20
  *
23
21
  * > [!IMPORTANT]
24
- * > **Transaction Isolation** — `None` by default: the built-in `execute` is a deferred identity that applies each
25
- * > call directly, with no write buffering and no rollback. When an `execute` opt is supplied through `management`,
26
- * > the level is determined by that wrapper (typically a backend transaction primitive).
22
+ * > **Transaction Isolation** — Determined by the supplied `execute` option, typically through a backend
23
+ * > transaction primitive: the wrapper adds neither isolation nor atomicity of its own.
27
24
  *
28
25
  * > [!IMPORTANT]
29
26
  * > **Mutation Events** — emits in-process observer events: each standalone mutation and each
30
27
  * > {@link Store.execute execute} call delivers a single filtered batch to matching {@link StoreObserver observer}s
31
- * > on resolve, and none on rejection. Cross-client signals reach local observers only when a backend-bridging
32
- * > `observe` opt is supplied through `management`.
33
- *
34
- * @param store - Inner StoreClient to delegate data calls to
35
- * @param management - Subset of {@link Store} management methods to delegate to; the wrapper fills in whatever is
36
- * missing
37
- * @param management.execute - Wraps every standalone StoreClient call and the body of {@link Store.execute execute},
38
- * typically a backend transaction primitive (for example, `graph.execute` for a SPARQL connector) responsible for
39
- * atomic commit and rollback. The wrapper StoreClient passed to the user task does NOT re-enter the opt; it relies
40
- * on the outer wrap so cross-call isolation works as expected. The task receives a per-call `scope` StoreClient,
41
- * and every delegated call within the wrap routes through `scope` (mirroring the {@link Store.execute} contract),
42
- * letting the wrapper install per-call state such as a freshly-bound graph buffer without leaking it across
43
- * concurrent invocations. Defaults to a deferred identity (`task => Promise.resolve().then(() => task(store))`);
44
- * user-supplied wrappers MUST pass a per-call `scope` StoreClient to `task` and MUST convert synchronous throws
45
- * from `task` into promise rejections to preserve the unified Store error channel; the `lookup` path delegates
46
- * directly to the wrapper and provides no additional guard
47
- * @param management.observe - Registers each observer with the delegate as well as locally, combining the two
48
- * unsubscribe handles so a single detach call releases both; this is how storage-level events (mutations from
49
- * other clients sharing the backend) reach the wrapper's local observers. Absent by default
50
- * @param management.close - Exposed verbatim on the returned store. Defaults to a resolved no-op
51
- *
52
- * @returns An immutable {@link Store} composing `store` with the supplied `management` opts
28
+ * > on resolve, and none on rejection. Mutations made by other clients reach local observers only if a
29
+ * > backend-bridging `observe` option is supplied through `management`.
30
+ *
31
+ * @param management - {@link Store} management methods backed by the connector: `execute` is required, and the
32
+ * wrapper fills in whatever else is missing
33
+ * @param management.execute - Transaction wrapper applied to every standalone StoreClient call and to the body of
34
+ * each {@link Store.execute execute} call, typically a backend transaction primitive (for example,
35
+ * `graph.execute` for a SPARQL connector) responsible for atomic commit and rollback. A backend with no
36
+ * transaction primitive supplies a wrapper applying the task directly to its StoreClient, and declares on its
37
+ * factory that a failing task neither rolls back nor isolates its mutations. The option MUST call each task it
38
+ * receives with a `scope` StoreClient dedicated to that call, so per-call state, such as a freshly bound graph
39
+ * buffer, never leaks across concurrent invocations; every data call within the transaction is routed through
40
+ * `scope`. Calls made by a user task inside {@link Store.execute execute} do not open further transactions: they
41
+ * share the outer one. The option MUST convert synchronous throws from the task into promise rejections, to
42
+ * preserve the unified Store error channel: lookups are routed through it with no additional guard
43
+ * @param management.observe - Backend registration for storage-level events, such as mutations made by other clients
44
+ * sharing the backend. Each observer is registered both with this option and locally, and a single detach call
45
+ * releases both registrations. The resource filter always arrives as an array of references, or as `undefined`
46
+ * for an unfiltered registration, so the option never has to handle bare references or single-pass iterables.
47
+ * Absent by default
48
+ * @param management.close - Exposed as is on the returned store. Defaults to a resolved no-op
49
+ *
50
+ * @returns An immutable {@link Store} serving data calls through the supplied `management` opts
53
51
  */
54
- export declare function createManagingStore(store: StoreClient, { observe, execute, close }?: Partial<Store>): Store;
52
+ export declare function createManagingStore({ observe, execute, close }: {
53
+ readonly observe?: Store["observe"];
54
+ readonly execute: Store["execute"];
55
+ readonly close?: Store["close"];
56
+ }): Store;
55
57
  //# sourceMappingURL=managing.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"managing.d.ts","sourceRoot":"","sources":["../../src/stores/managing.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAiB,MAAM,aAAa,CAAC;AAGrE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,WAAW,EAAE,EAEvD,OAAO,EACP,OAAwG,EACxG,KAA+B,EAE/B,GAAE,OAAO,CAAC,KAAK,CAAM,GAAG,KAAK,CA2H7B"}
1
+ {"version":3,"file":"managing.d.ts","sourceRoot":"","sources":["../../src/stores/managing.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,KAAK,EAA8B,MAAM,aAAa,CAAC;AAGrE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,wBAAgB,mBAAmB,CAAC,EAEnC,OAAO,EACP,OAAO,EAEP,KAA+B,EAE/B,EAAE;IAEF,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAA;IACnC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,CAAA;IAElC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;CAE/B,GAAG,KAAK,CA2HR"}