liwi-subscribe-store 13.4.0 → 14.1.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.
package/README.md CHANGED
@@ -81,6 +81,35 @@ type Actions<Model> =
81
81
  | { type: "deleted"; prev: Model[] };
82
82
  ```
83
83
 
84
+ `prev` is always the **stored** document, never the object passed by the caller: queries decide whether a document entered or left their result by testing `prev` and `next` against their criteria, so a stale copy would leave rows in lists they no longer belong to.
85
+
86
+ | Write | Where `prev` comes from |
87
+ | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
88
+ | `partialUpdateByKey` / `partialUpdateOne` | `partialUpdateByKeyWithInfo` of the wrapped store (atomic with the write), else `findOne` just before the write |
89
+ | `replaceOne` / `replaceSeveral` | `replaceOneWithInfo` (atomic), else `findByKey` just before the write |
90
+ | `deleteByKey` / `deleteOne` | `deleteByKeyWithInfo` (atomic), else `findByKey` just before the write |
91
+ | `upsertOne` / `upsertOneWithInfo` | `upsertOneWithInfo` of the wrapped store |
92
+ | `partialUpdateMany` | the matching keys are read first, then each document is updated as by `partialUpdateByKey`, re-checking `criteria` |
93
+ | `deleteMany` | the matching keys are read first, then each document is deleted with `deleteByKeyWithInfo`, re-checking `criteria`; without it, a cursor read before one `deleteMany` (not atomic) |
94
+
95
+ See [Writes with info](../liwi-store#writes-with-info) for the `…WithInfo` contract.
96
+
97
+ For `partialUpdateMany` and `deleteMany`, the emitted documents are exactly the ones written: a document that stopped matching `criteria` after the keys were read is left alone and not emitted, and a document inserted after the keys were read is not written. This costs one round trip per document instead of a single command.
98
+
99
+ ### Without listeners
100
+
101
+ When nothing is subscribed (no `subscribe` listener and no open query subscription), nobody needs `prev`, so writes go straight to the wrapped store: `partialUpdateMany` and `deleteMany` are a single command again, and `partialUpdateByKey`, `replaceOne` and `deleteByKey` use the plain methods (one round trip for a partial update by key instead of two). Behaviour is otherwise the same, including `NotFoundError` on a missing key.
102
+
103
+ ### Missing keys and failures
104
+
105
+ - A write on a key that does not exist emits nothing. `partialUpdateByKey`, `partialUpdateOne`, `replaceOne` and `replaceSeveral` throw [`NotFoundError`](../liwi-store#errors); `deleteByKey` and `deleteOne` resolve.
106
+ - When a concurrent delete lands between a partial update and its read-back, the update was applied but there is no `next`: nothing is emitted (the delete emits its own `deleted` action) and `partialUpdateByKey` / `partialUpdateOne` throw `DeletedAfterUpdateError`, a subclass of `NotFoundError`. `partialUpdateMany` skips that document.
107
+ - `replaceSeveral`, `partialUpdateMany` and `deleteMany` emit the writes that succeeded before rethrowing the first failure, so listeners stay in sync with what was written.
108
+
109
+ ### `updated`
110
+
111
+ Stamping `updated` and rejecting protected field updates is done by the wrapped store (see [`created` and `updated`](../liwi-store#created-and-updated)); partial update `options` such as `touchUpdated` are passed through. Because `partialUpdateMany` writes document by document here, each document gets its own write time, where a plain `MongoStore` gives the whole command one.
112
+
84
113
  ### `AbstractSubscribableStoreQuery`
85
114
 
86
115
  Base class for store implementations providing subscribable queries. It holds the subscribe store (`setSubscribeStore` / `getSubscribeStore`) and implements `fetchAndSubscribe` / `subscribe` on top of an abstract `_subscribe`; implementations turn store actions into query `Changes` by testing each affected model against the query criteria. `liwi-mongo` does this in memory with [mingo](https://github.com/kofrasa/mingo).
@@ -1,4 +1,4 @@
1
- import type { AbstractConnection, AbstractStoreCursor, AllowedKeyValue, BaseModel, CreateQueryOptions, Criteria, InsertType, OptionalBaseModelKeysForInsert, QueryParams, Sort, Store as StoreInterface, SubscribableStore, SubscribableStoreQuery, Update, UpsertPartialObject, UpsertResult } from "liwi-store";
1
+ import type { AbstractConnection, AbstractStoreCursor, AllowedKeyValue, BaseModel, CreateQueryOptions, Criteria, InsertType, OptionalBaseModelKeysForInsert, PartialUpdateOptions, QueryParams, Sort, Store as StoreInterface, SubscribableStore, SubscribableStoreQuery, Update, UpsertPartialObject, UpsertResult } from "liwi-store";
2
2
  export type Actions<Model> = {
3
3
  type: "deleted";
4
4
  prev: Model[];
@@ -18,6 +18,15 @@ export default class SubscribeStore<KeyPath extends keyof Model, KeyValue extend
18
18
  get connection(): Connection;
19
19
  subscribe(callback: Listener<Model>): () => void;
20
20
  callSubscribed(action: Actions<Model>): void;
21
+ /**
22
+ * Nobody needs `prev` without listeners: writes then go straight to the wrapped
23
+ * store, skipping the per-document reads and loops.
24
+ */
25
+ private hasListeners;
26
+ private findKeys;
27
+ private replaceOneAndGetChange;
28
+ private partialUpdateByKeyAndGetResult;
29
+ private deleteByKeyAndGetPrev;
21
30
  createQuerySingleItem<Result extends Record<KeyPath, KeyValue>, Params extends QueryParams<Params>>(options: CreateQueryOptions<Model, Result>): SubscribableStoreQuery<KeyPath, KeyValue, Model, SubscribableStore<KeyPath, KeyValue, Model, ModelInsertType, Connection>, Result, Params>;
22
31
  createQueryCollection<Item extends Record<KeyPath, KeyValue>, Params extends QueryParams<Params>>(options: CreateQueryOptions<Model, Item>): SubscribableStoreQuery<KeyPath, KeyValue, Model, SubscribableStore<KeyPath, KeyValue, Model, ModelInsertType, Connection>, Item[], Params>;
23
32
  findAll(criteria?: Criteria<Model>, sort?: Sort<Model>): Promise<Model[]>;
@@ -28,11 +37,24 @@ export default class SubscribeStore<KeyPath extends keyof Model, KeyValue extend
28
37
  replaceSeveral(objects: Model[]): Promise<Model[]>;
29
38
  upsertOne<K extends Exclude<keyof Model, KeyPath | OptionalBaseModelKeysForInsert>>(object: UpsertPartialObject<KeyPath, KeyValue, Model, K>, setOnInsertPartialObject?: Update<Model>["$setOnInsert"]): Promise<Model>;
30
39
  upsertOneWithInfo<K extends Exclude<keyof Model, KeyPath | OptionalBaseModelKeysForInsert>>(object: UpsertPartialObject<KeyPath, KeyValue, Model, K>, setOnInsertPartialObject?: Update<Model>["$setOnInsert"]): Promise<UpsertResult<Model>>;
31
- partialUpdateByKey(key: KeyValue, partialUpdate: Update<Model>, criteria?: Criteria<Model>): Promise<Model>;
32
- partialUpdateOne(object: Model, partialUpdate: Update<Model>): Promise<Model>;
33
- partialUpdateMany(criteria: Criteria<Model>, partialUpdate: Update<Model>): Promise<void>;
40
+ partialUpdateByKey(key: KeyValue, partialUpdate: Update<Model>, criteria?: Criteria<Model>, options?: PartialUpdateOptions): Promise<Model>;
41
+ partialUpdateOne(object: Model, partialUpdate: Update<Model>, options?: PartialUpdateOptions): Promise<Model>;
42
+ /**
43
+ * Without listeners, one command on the wrapped store. With listeners, the keys
44
+ * matching `criteria` are read first, then each document is updated on its own
45
+ * (re-checking `criteria`) so that every change carries its true `prev`: N + 1
46
+ * round trips. A document inserted after the keys were read is not updated.
47
+ */
48
+ partialUpdateMany(criteria: Criteria<Model>, partialUpdate: Update<Model>, options?: PartialUpdateOptions): Promise<void>;
34
49
  deleteByKey(key: KeyValue, criteria?: Criteria<Model>): Promise<void>;
35
50
  deleteOne(object: Model): Promise<void>;
51
+ /**
52
+ * Without listeners, one command on the wrapped store. With listeners and a store
53
+ * implementing `deleteByKeyWithInfo`, the keys matching `criteria` are read first,
54
+ * then each document is deleted on its own (re-checking `criteria`), so that the
55
+ * emitted documents are exactly the deleted ones: N + 1 round trips. A document
56
+ * inserted after the keys were read is not deleted.
57
+ */
36
58
  deleteMany(criteria: Criteria<Model>): Promise<void>;
37
59
  count(criteria?: Criteria<Model>): Promise<number>;
38
60
  cursor<Result extends Partial<Model> = Model>(criteria?: Criteria<Model>, sort?: Sort<Model>): Promise<AbstractStoreCursor<any, KeyValue, Model, Result>>;
@@ -1 +1 @@
1
- {"version":3,"file":"SubscribeStore.d.ts","sourceRoot":"","sources":["../../src/SubscribeStore.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SubscribeStore.d.ts","sourceRoot":"","sources":["../../src/SubscribeStore.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,5 @@
1
+ import { NotFoundError, DeletedAfterUpdateError } from 'liwi-store';
2
+
1
3
  class SubscribeStore {
2
4
  store;
3
5
  listeners = /* @__PURE__ */ new Set();
@@ -16,6 +18,68 @@ class SubscribeStore {
16
18
  callSubscribed(action) {
17
19
  this.listeners.forEach((listener) => listener(action));
18
20
  }
21
+ /**
22
+ * Nobody needs `prev` without listeners: writes then go straight to the wrapped
23
+ * store, skipping the per-document reads and loops.
24
+ */
25
+ hasListeners() {
26
+ return this.listeners.size > 0;
27
+ }
28
+ async findKeys(criteria) {
29
+ const cursor = await this.store.cursor(criteria);
30
+ const keys = [];
31
+ await cursor.forEach((model) => {
32
+ keys.push(model[this.keyPath]);
33
+ });
34
+ return keys;
35
+ }
36
+ async replaceOneAndGetChange(object) {
37
+ const key = object[this.keyPath];
38
+ if (this.store.replaceOneWithInfo) {
39
+ const result = await this.store.replaceOneWithInfo(object);
40
+ if (!result) {
41
+ throw new NotFoundError(`Document not found: ${String(key)}`);
42
+ }
43
+ return [result.prev, result.next];
44
+ }
45
+ const prev = await this.store.findByKey(key);
46
+ if (!prev) throw new NotFoundError(`Document not found: ${String(key)}`);
47
+ return [prev, await this.store.replaceOne(object)];
48
+ }
49
+ async partialUpdateByKeyAndGetResult(key, partialUpdate, criteria, options) {
50
+ if (this.store.partialUpdateByKeyWithInfo) {
51
+ return this.store.partialUpdateByKeyWithInfo(
52
+ key,
53
+ partialUpdate,
54
+ criteria,
55
+ options
56
+ );
57
+ }
58
+ const prev = await this.store.findOne({
59
+ [this.keyPath]: key,
60
+ ...criteria
61
+ });
62
+ if (!prev) return void 0;
63
+ return {
64
+ prev,
65
+ next: await this.store.partialUpdateByKey(
66
+ key,
67
+ partialUpdate,
68
+ criteria,
69
+ options
70
+ )
71
+ };
72
+ }
73
+ async deleteByKeyAndGetPrev(key, criteria) {
74
+ if (this.store.deleteByKeyWithInfo) {
75
+ const result = await this.store.deleteByKeyWithInfo(key, criteria);
76
+ return result?.prev;
77
+ }
78
+ const prev = await this.store.findByKey(key, criteria);
79
+ if (!prev) return void 0;
80
+ await this.store.deleteByKey(key, criteria);
81
+ return prev;
82
+ }
19
83
  createQuerySingleItem(options) {
20
84
  const query = this.store.createQuerySingleItem(options);
21
85
  query.setSubscribeStore(this);
@@ -41,17 +105,25 @@ class SubscribeStore {
41
105
  return inserted;
42
106
  }
43
107
  async replaceOne(object) {
44
- const replaced = await this.store.replaceOne(object);
45
- this.callSubscribed({ type: "updated", changes: [[object, replaced]] });
46
- return replaced;
108
+ if (!this.hasListeners()) return this.store.replaceOne(object);
109
+ const change = await this.replaceOneAndGetChange(object);
110
+ this.callSubscribed({ type: "updated", changes: [change] });
111
+ return change[1];
47
112
  }
48
113
  async replaceSeveral(objects) {
49
- const replacedObjects = await this.store.replaceSeveral(objects);
50
- this.callSubscribed({
51
- type: "updated",
52
- changes: objects.map((prev, index) => [prev, replacedObjects[index]])
53
- });
54
- return replacedObjects;
114
+ if (!this.hasListeners()) return this.store.replaceSeveral(objects);
115
+ const results = await Promise.allSettled(
116
+ objects.map((object) => this.replaceOneAndGetChange(object))
117
+ );
118
+ const changes = results.flatMap(
119
+ (result) => result.status === "fulfilled" ? [result.value] : []
120
+ );
121
+ if (changes.length > 0) this.callSubscribed({ type: "updated", changes });
122
+ const failure = results.find(
123
+ (result) => result.status === "rejected"
124
+ );
125
+ if (failure) throw failure.reason;
126
+ return changes.map(([, next]) => next);
55
127
  }
56
128
  async upsertOne(object, setOnInsertPartialObject) {
57
129
  const result = await this.upsertOneWithInfo(
@@ -78,46 +150,109 @@ class SubscribeStore {
78
150
  }
79
151
  return upsertedWithInfo;
80
152
  }
81
- async partialUpdateByKey(key, partialUpdate, criteria) {
82
- return this.partialUpdateOne(
83
- await this.findOne({
84
- [this.store.keyPath]: key,
85
- ...criteria
86
- }),
87
- partialUpdate
88
- );
89
- }
90
- async partialUpdateOne(object, partialUpdate) {
91
- const updated = await this.store.partialUpdateOne(object, partialUpdate);
92
- this.callSubscribed({ type: "updated", changes: [[object, updated]] });
93
- return updated;
94
- }
95
- async partialUpdateMany(criteria, partialUpdate) {
96
- const cursor = await this.store.cursor(criteria);
97
- const changes = [];
98
- await cursor.forEach(async (model) => {
99
- const key = model[this.store.keyPath];
100
- const updated = await this.store.partialUpdateByKey(
153
+ async partialUpdateByKey(key, partialUpdate, criteria, options) {
154
+ if (!this.hasListeners()) {
155
+ return this.store.partialUpdateByKey(
101
156
  key,
102
157
  partialUpdate,
103
- criteria
158
+ criteria,
159
+ options
104
160
  );
105
- changes.push([model, updated]);
161
+ }
162
+ const result = await this.partialUpdateByKeyAndGetResult(
163
+ key,
164
+ partialUpdate,
165
+ criteria,
166
+ options
167
+ );
168
+ if (!result) throw new NotFoundError(`Document not found: ${String(key)}`);
169
+ if (!result.next) {
170
+ throw new DeletedAfterUpdateError(
171
+ `Document deleted after update: ${String(key)}`
172
+ );
173
+ }
174
+ this.callSubscribed({
175
+ type: "updated",
176
+ changes: [[result.prev, result.next]]
106
177
  });
107
- this.callSubscribed({ type: "updated", changes });
178
+ return result.next;
179
+ }
180
+ partialUpdateOne(object, partialUpdate, options) {
181
+ return this.partialUpdateByKey(
182
+ object[this.keyPath],
183
+ partialUpdate,
184
+ void 0,
185
+ options
186
+ );
187
+ }
188
+ /**
189
+ * Without listeners, one command on the wrapped store. With listeners, the keys
190
+ * matching `criteria` are read first, then each document is updated on its own
191
+ * (re-checking `criteria`) so that every change carries its true `prev`: N + 1
192
+ * round trips. A document inserted after the keys were read is not updated.
193
+ */
194
+ async partialUpdateMany(criteria, partialUpdate, options) {
195
+ if (!this.hasListeners()) {
196
+ await this.store.partialUpdateMany(criteria, partialUpdate, options);
197
+ return;
198
+ }
199
+ const keys = await this.findKeys(criteria);
200
+ const changes = [];
201
+ try {
202
+ for (const key of keys) {
203
+ const result = await this.partialUpdateByKeyAndGetResult(
204
+ key,
205
+ partialUpdate,
206
+ criteria,
207
+ options
208
+ );
209
+ if (result?.next) changes.push([result.prev, result.next]);
210
+ }
211
+ } finally {
212
+ if (changes.length > 0) this.callSubscribed({ type: "updated", changes });
213
+ }
108
214
  }
109
215
  async deleteByKey(key, criteria) {
110
- return this.deleteOne(await this.findByKey(key, criteria));
216
+ if (!this.hasListeners()) {
217
+ await this.store.deleteByKey(key, criteria);
218
+ return;
219
+ }
220
+ const prev = await this.deleteByKeyAndGetPrev(key, criteria);
221
+ if (!prev) return;
222
+ this.callSubscribed({ type: "deleted", prev: [prev] });
111
223
  }
112
- async deleteOne(object) {
113
- await this.store.deleteOne(object);
114
- this.callSubscribed({ type: "deleted", prev: [object] });
224
+ deleteOne(object) {
225
+ return this.deleteByKey(object[this.keyPath]);
115
226
  }
227
+ /**
228
+ * Without listeners, one command on the wrapped store. With listeners and a store
229
+ * implementing `deleteByKeyWithInfo`, the keys matching `criteria` are read first,
230
+ * then each document is deleted on its own (re-checking `criteria`), so that the
231
+ * emitted documents are exactly the deleted ones: N + 1 round trips. A document
232
+ * inserted after the keys were read is not deleted.
233
+ */
116
234
  async deleteMany(criteria) {
117
- const cursor = await this.store.cursor(criteria);
118
- const prev = await cursor.toArray();
119
- await this.store.deleteMany(criteria);
120
- this.callSubscribed({ type: "deleted", prev });
235
+ if (!this.hasListeners()) {
236
+ await this.store.deleteMany(criteria);
237
+ return;
238
+ }
239
+ if (!this.store.deleteByKeyWithInfo) {
240
+ const cursor = await this.store.cursor(criteria);
241
+ const prev2 = await cursor.toArray();
242
+ await this.store.deleteMany(criteria);
243
+ this.callSubscribed({ type: "deleted", prev: prev2 });
244
+ return;
245
+ }
246
+ const keys = await this.findKeys(criteria);
247
+ const prev = [];
248
+ try {
249
+ for (const key of keys) {
250
+ const result = await this.store.deleteByKeyWithInfo(key, criteria);
251
+ if (result) prev.push(result.prev);
252
+ }
253
+ } finally {
254
+ if (prev.length > 0) this.callSubscribed({ type: "deleted", prev });
255
+ }
121
256
  }
122
257
  async count(criteria) {
123
258
  return this.store.count(criteria);
@@ -1 +1 @@
1
- {"version":3,"file":"index-browser.es.js","sources":["../src/SubscribeStore.ts","../src/AbstractSubscribableStoreQuery.ts"],"sourcesContent":["import type {\n AbstractConnection,\n AbstractStoreCursor,\n AllowedKeyValue,\n BaseModel,\n CreateQueryOptions,\n Criteria,\n InsertType,\n OptionalBaseModelKeysForInsert,\n QueryParams,\n Sort,\n Store as StoreInterface,\n SubscribableStore,\n SubscribableStoreQuery,\n Update,\n UpsertPartialObject,\n UpsertResult,\n} from \"liwi-store\";\n\nexport type Actions<Model> =\n | { type: \"deleted\"; prev: Model[] }\n | { type: \"inserted\"; next: Model[] }\n | { type: \"updated\"; changes: [Model, Model][] };\n\nexport type Listener<Model> = (action: Actions<Model>) => unknown;\n\nexport default class SubscribeStore<\n KeyPath extends keyof Model,\n KeyValue extends AllowedKeyValue,\n Model extends BaseModel & Record<KeyPath, KeyValue>,\n ModelInsertType extends InsertType<Model, KeyPath>,\n Connection extends AbstractConnection,\n Store extends SubscribableStore<\n KeyPath,\n KeyValue,\n Model,\n ModelInsertType,\n Connection\n >,\n> implements StoreInterface<\n KeyPath,\n KeyValue,\n Model,\n ModelInsertType,\n Connection\n> {\n private readonly store: Store;\n\n private readonly listeners = new Set<Listener<Model>>();\n\n readonly keyPath: KeyPath;\n\n constructor(store: Store) {\n this.store = store;\n this.keyPath = store.keyPath;\n }\n\n get connection(): Connection {\n return this.store.connection;\n }\n\n subscribe(callback: Listener<Model>): () => void {\n this.listeners.add(callback);\n return () => this.listeners.delete(callback);\n }\n\n callSubscribed(action: Actions<Model>): void {\n this.listeners.forEach((listener) => listener(action));\n }\n\n createQuerySingleItem<\n Result extends Record<KeyPath, KeyValue>,\n Params extends QueryParams<Params>,\n >(\n options: CreateQueryOptions<Model, Result>,\n ): SubscribableStoreQuery<\n KeyPath,\n KeyValue,\n Model,\n SubscribableStore<KeyPath, KeyValue, Model, ModelInsertType, Connection>,\n Result,\n Params\n > {\n const query: SubscribableStoreQuery<\n KeyPath,\n KeyValue,\n Model,\n SubscribableStore<KeyPath, KeyValue, Model, ModelInsertType, Connection>,\n Result,\n Params\n > = this.store.createQuerySingleItem<Result, Params>(options);\n query.setSubscribeStore(this);\n return query;\n }\n\n createQueryCollection<\n Item extends Record<KeyPath, KeyValue>,\n Params extends QueryParams<Params>,\n >(\n options: CreateQueryOptions<Model, Item>,\n ): SubscribableStoreQuery<\n KeyPath,\n KeyValue,\n Model,\n SubscribableStore<KeyPath, KeyValue, Model, ModelInsertType, Connection>,\n Item[],\n Params\n > {\n const query: SubscribableStoreQuery<\n KeyPath,\n KeyValue,\n Model,\n SubscribableStore<KeyPath, KeyValue, Model, ModelInsertType, Connection>,\n Item[],\n Params\n > = this.store.createQueryCollection<Item, Params>(options);\n query.setSubscribeStore(this);\n return query;\n }\n\n findAll(criteria?: Criteria<Model>, sort?: Sort<Model>): Promise<Model[]> {\n return this.store.findAll(criteria, sort);\n }\n\n findByKey(\n key: KeyValue,\n criteria?: Criteria<Model>,\n ): Promise<Model | undefined> {\n return this.store.findByKey(key, criteria);\n }\n\n findOne(\n criteria: Criteria<Model>,\n sort?: Sort<Model>,\n ): Promise<Model | undefined> {\n return this.store.findOne(criteria, sort);\n }\n\n async insertOne(object: ModelInsertType): Promise<Model> {\n const inserted = await this.store.insertOne(object);\n this.callSubscribed({ type: \"inserted\", next: [inserted] });\n return inserted;\n }\n\n async replaceOne(object: Model): Promise<Model> {\n const replaced = await this.store.replaceOne(object);\n this.callSubscribed({ type: \"updated\", changes: [[object, replaced]] });\n return replaced;\n }\n\n async replaceSeveral(objects: Model[]): Promise<Model[]> {\n const replacedObjects = await this.store.replaceSeveral(objects);\n this.callSubscribed({\n type: \"updated\",\n changes: objects.map((prev, index) => [prev, replacedObjects[index]!]),\n });\n return replacedObjects;\n }\n\n async upsertOne<\n K extends Exclude<keyof Model, KeyPath | OptionalBaseModelKeysForInsert>,\n >(\n object: UpsertPartialObject<KeyPath, KeyValue, Model, K>,\n setOnInsertPartialObject?: Update<Model>[\"$setOnInsert\"],\n ): Promise<Model> {\n const result = await this.upsertOneWithInfo(\n object,\n setOnInsertPartialObject,\n );\n return result.object;\n }\n\n async upsertOneWithInfo<\n K extends Exclude<keyof Model, KeyPath | OptionalBaseModelKeysForInsert>,\n >(\n object: UpsertPartialObject<KeyPath, KeyValue, Model, K>,\n setOnInsertPartialObject?: Update<Model>[\"$setOnInsert\"],\n ): Promise<UpsertResult<Model>> {\n const upsertedWithInfo = await this.store.upsertOneWithInfo(\n object,\n setOnInsertPartialObject,\n );\n if (upsertedWithInfo.resolvedAs === \"inserted\") {\n this.callSubscribed({\n type: \"inserted\",\n next: [upsertedWithInfo.object],\n });\n } else {\n this.callSubscribed({\n type: \"updated\",\n changes: [[upsertedWithInfo.prev, upsertedWithInfo.object]],\n });\n }\n return upsertedWithInfo;\n }\n\n async partialUpdateByKey(\n key: KeyValue,\n partialUpdate: Update<Model>,\n criteria?: Criteria<Model>,\n ): Promise<Model> {\n return this.partialUpdateOne(\n (await this.findOne({\n [this.store.keyPath]: key,\n ...criteria,\n }))!,\n partialUpdate,\n );\n }\n\n async partialUpdateOne(\n object: Model,\n partialUpdate: Update<Model>,\n ): Promise<Model> {\n const updated = await this.store.partialUpdateOne(object, partialUpdate);\n this.callSubscribed({ type: \"updated\", changes: [[object, updated]] });\n return updated;\n }\n\n async partialUpdateMany(\n criteria: Criteria<Model>,\n partialUpdate: Update<Model>,\n ): Promise<void> {\n const cursor = await this.store.cursor(criteria);\n const changes: [Model, Model][] = [];\n\n await cursor.forEach(async (model) => {\n const key = model[this.store.keyPath];\n const updated = await this.store.partialUpdateByKey(\n key,\n partialUpdate,\n criteria,\n );\n changes.push([model, updated]);\n });\n this.callSubscribed({ type: \"updated\", changes });\n }\n\n async deleteByKey(key: KeyValue, criteria?: Criteria<Model>): Promise<void> {\n return this.deleteOne((await this.findByKey(key, criteria))!);\n }\n\n async deleteOne(object: Model): Promise<void> {\n await this.store.deleteOne(object);\n this.callSubscribed({ type: \"deleted\", prev: [object] });\n }\n\n async deleteMany(criteria: Criteria<Model>): Promise<void> {\n const cursor = await this.store.cursor(criteria);\n const prev: Model[] = await cursor.toArray();\n await this.store.deleteMany(criteria);\n this.callSubscribed({ type: \"deleted\", prev });\n }\n\n async count(criteria?: Criteria<Model>): Promise<number> {\n return this.store.count(criteria);\n }\n\n async cursor<Result extends Partial<Model> = Model>(\n criteria?: Criteria<Model>,\n sort?: Sort<Model>,\n ): Promise<AbstractStoreCursor<any, KeyValue, Model, Result>> {\n const cursor = await this.store.cursor<Result>(criteria, sort);\n cursor.overrideStore(this);\n return cursor;\n }\n}\n","import type {\n AllowedKeyValue,\n BaseModel,\n InsertType,\n Query,\n QueryParams,\n QueryResult,\n QuerySubscription,\n SubscribeCallback,\n} from \"liwi-store\";\nimport type SubscribeStore from \"./SubscribeStore\";\n\nexport default abstract class AbstractSubscribableStoreQuery<\n KeyPath extends keyof Model,\n KeyValue extends AllowedKeyValue,\n Model extends BaseModel & Record<KeyPath, KeyValue>,\n ModelInsertType extends InsertType<Model, KeyPath>,\n Params extends QueryParams<Params> = never,\n Result = Model,\n> implements Query<Result, Params, KeyValue> {\n changeParams(params: Params): never {\n throw new Error(\"Method not supported. Please create a new query.\");\n }\n\n changePartialParams(\n params: Params extends undefined ? never : Partial<Params>,\n ): never {\n throw new Error(\"Method not supported. Please create a new query.\");\n }\n\n private _subscribeStore?: SubscribeStore<\n KeyPath,\n KeyValue,\n Model,\n ModelInsertType,\n any,\n any\n >;\n\n setSubscribeStore(\n store: SubscribeStore<KeyPath, KeyValue, Model, ModelInsertType, any, any>,\n ): void {\n this._subscribeStore = store;\n }\n\n getSubscribeStore(): SubscribeStore<\n KeyPath,\n KeyValue,\n Model,\n ModelInsertType,\n any,\n any\n > {\n if (!this._subscribeStore) {\n throw new Error(\"_subscribeStore is not initialized\");\n }\n return this._subscribeStore;\n }\n\n abstract fetch<T>(\n onFulfilled: (result: QueryResult<Result>) => T,\n ): Promise<T>;\n\n fetchAndSubscribe(\n callback: SubscribeCallback<KeyValue, Result>,\n ): QuerySubscription {\n return this._subscribe(callback, true);\n }\n\n subscribe(callback: SubscribeCallback<KeyValue, Result>): QuerySubscription {\n return this._subscribe(callback, false);\n }\n\n abstract _subscribe(\n callback: SubscribeCallback<KeyValue, Result>,\n _includeInitial: boolean,\n ): QuerySubscription;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index-browser.es.js","sources":["../src/SubscribeStore.ts","../src/AbstractSubscribableStoreQuery.ts"],"sourcesContent":["import { DeletedAfterUpdateError, NotFoundError } from \"liwi-store\";\nimport type {\n AbstractConnection,\n AbstractStoreCursor,\n AllowedKeyValue,\n BaseModel,\n CreateQueryOptions,\n Criteria,\n InsertType,\n OptionalBaseModelKeysForInsert,\n PartialUpdateOptions,\n PartialUpdateResult,\n QueryParams,\n Sort,\n Store as StoreInterface,\n SubscribableStore,\n SubscribableStoreQuery,\n Update,\n UpsertPartialObject,\n UpsertResult,\n} from \"liwi-store\";\n\nexport type Actions<Model> =\n | { type: \"deleted\"; prev: Model[] }\n | { type: \"inserted\"; next: Model[] }\n | { type: \"updated\"; changes: [Model, Model][] };\n\nexport type Listener<Model> = (action: Actions<Model>) => unknown;\n\nexport default class SubscribeStore<\n KeyPath extends keyof Model,\n KeyValue extends AllowedKeyValue,\n Model extends BaseModel & Record<KeyPath, KeyValue>,\n ModelInsertType extends InsertType<Model, KeyPath>,\n Connection extends AbstractConnection,\n Store extends SubscribableStore<\n KeyPath,\n KeyValue,\n Model,\n ModelInsertType,\n Connection\n >,\n> implements StoreInterface<\n KeyPath,\n KeyValue,\n Model,\n ModelInsertType,\n Connection\n> {\n private readonly store: Store;\n\n private readonly listeners = new Set<Listener<Model>>();\n\n readonly keyPath: KeyPath;\n\n constructor(store: Store) {\n this.store = store;\n this.keyPath = store.keyPath;\n }\n\n get connection(): Connection {\n return this.store.connection;\n }\n\n subscribe(callback: Listener<Model>): () => void {\n this.listeners.add(callback);\n return () => this.listeners.delete(callback);\n }\n\n callSubscribed(action: Actions<Model>): void {\n this.listeners.forEach((listener) => listener(action));\n }\n\n /**\n * Nobody needs `prev` without listeners: writes then go straight to the wrapped\n * store, skipping the per-document reads and loops.\n */\n private hasListeners(): boolean {\n return this.listeners.size > 0;\n }\n\n private async findKeys(criteria: Criteria<Model>): Promise<KeyValue[]> {\n const cursor = await this.store.cursor(criteria);\n const keys: KeyValue[] = [];\n await cursor.forEach((model) => {\n keys.push(model[this.keyPath]);\n });\n return keys;\n }\n\n private async replaceOneAndGetChange(object: Model): Promise<[Model, Model]> {\n const key = object[this.keyPath];\n if (this.store.replaceOneWithInfo) {\n const result = await this.store.replaceOneWithInfo(object);\n if (!result) {\n throw new NotFoundError(`Document not found: ${String(key)}`);\n }\n return [result.prev, result.next];\n }\n const prev = await this.store.findByKey(key);\n if (!prev) throw new NotFoundError(`Document not found: ${String(key)}`);\n return [prev, await this.store.replaceOne(object)];\n }\n\n private async partialUpdateByKeyAndGetResult(\n key: KeyValue,\n partialUpdate: Update<Model>,\n criteria?: Criteria<Model>,\n options?: PartialUpdateOptions,\n ): Promise<PartialUpdateResult<Model> | undefined> {\n if (this.store.partialUpdateByKeyWithInfo) {\n return this.store.partialUpdateByKeyWithInfo(\n key,\n partialUpdate,\n criteria,\n options,\n );\n }\n const prev = await this.store.findOne({\n [this.keyPath]: key,\n ...criteria,\n });\n if (!prev) return undefined;\n return {\n prev,\n next: await this.store.partialUpdateByKey(\n key,\n partialUpdate,\n criteria,\n options,\n ),\n };\n }\n\n private async deleteByKeyAndGetPrev(\n key: KeyValue,\n criteria?: Criteria<Model>,\n ): Promise<Model | undefined> {\n if (this.store.deleteByKeyWithInfo) {\n const result = await this.store.deleteByKeyWithInfo(key, criteria);\n return result?.prev;\n }\n const prev = await this.store.findByKey(key, criteria);\n if (!prev) return undefined;\n await this.store.deleteByKey(key, criteria);\n return prev;\n }\n\n createQuerySingleItem<\n Result extends Record<KeyPath, KeyValue>,\n Params extends QueryParams<Params>,\n >(\n options: CreateQueryOptions<Model, Result>,\n ): SubscribableStoreQuery<\n KeyPath,\n KeyValue,\n Model,\n SubscribableStore<KeyPath, KeyValue, Model, ModelInsertType, Connection>,\n Result,\n Params\n > {\n const query: SubscribableStoreQuery<\n KeyPath,\n KeyValue,\n Model,\n SubscribableStore<KeyPath, KeyValue, Model, ModelInsertType, Connection>,\n Result,\n Params\n > = this.store.createQuerySingleItem<Result, Params>(options);\n query.setSubscribeStore(this);\n return query;\n }\n\n createQueryCollection<\n Item extends Record<KeyPath, KeyValue>,\n Params extends QueryParams<Params>,\n >(\n options: CreateQueryOptions<Model, Item>,\n ): SubscribableStoreQuery<\n KeyPath,\n KeyValue,\n Model,\n SubscribableStore<KeyPath, KeyValue, Model, ModelInsertType, Connection>,\n Item[],\n Params\n > {\n const query: SubscribableStoreQuery<\n KeyPath,\n KeyValue,\n Model,\n SubscribableStore<KeyPath, KeyValue, Model, ModelInsertType, Connection>,\n Item[],\n Params\n > = this.store.createQueryCollection<Item, Params>(options);\n query.setSubscribeStore(this);\n return query;\n }\n\n findAll(criteria?: Criteria<Model>, sort?: Sort<Model>): Promise<Model[]> {\n return this.store.findAll(criteria, sort);\n }\n\n findByKey(\n key: KeyValue,\n criteria?: Criteria<Model>,\n ): Promise<Model | undefined> {\n return this.store.findByKey(key, criteria);\n }\n\n findOne(\n criteria: Criteria<Model>,\n sort?: Sort<Model>,\n ): Promise<Model | undefined> {\n return this.store.findOne(criteria, sort);\n }\n\n async insertOne(object: ModelInsertType): Promise<Model> {\n const inserted = await this.store.insertOne(object);\n this.callSubscribed({ type: \"inserted\", next: [inserted] });\n return inserted;\n }\n\n async replaceOne(object: Model): Promise<Model> {\n if (!this.hasListeners()) return this.store.replaceOne(object);\n\n const change = await this.replaceOneAndGetChange(object);\n this.callSubscribed({ type: \"updated\", changes: [change] });\n return change[1];\n }\n\n async replaceSeveral(objects: Model[]): Promise<Model[]> {\n if (!this.hasListeners()) return this.store.replaceSeveral(objects);\n\n const results = await Promise.allSettled(\n objects.map((object) => this.replaceOneAndGetChange(object)),\n );\n const changes = results.flatMap((result) =>\n result.status === \"fulfilled\" ? [result.value] : [],\n );\n if (changes.length > 0) this.callSubscribed({ type: \"updated\", changes });\n\n const failure = results.find(\n (result): result is PromiseRejectedResult => result.status === \"rejected\",\n );\n if (failure) throw failure.reason;\n return changes.map(([, next]) => next);\n }\n\n async upsertOne<\n K extends Exclude<keyof Model, KeyPath | OptionalBaseModelKeysForInsert>,\n >(\n object: UpsertPartialObject<KeyPath, KeyValue, Model, K>,\n setOnInsertPartialObject?: Update<Model>[\"$setOnInsert\"],\n ): Promise<Model> {\n const result = await this.upsertOneWithInfo(\n object,\n setOnInsertPartialObject,\n );\n return result.object;\n }\n\n async upsertOneWithInfo<\n K extends Exclude<keyof Model, KeyPath | OptionalBaseModelKeysForInsert>,\n >(\n object: UpsertPartialObject<KeyPath, KeyValue, Model, K>,\n setOnInsertPartialObject?: Update<Model>[\"$setOnInsert\"],\n ): Promise<UpsertResult<Model>> {\n const upsertedWithInfo = await this.store.upsertOneWithInfo(\n object,\n setOnInsertPartialObject,\n );\n if (upsertedWithInfo.resolvedAs === \"inserted\") {\n this.callSubscribed({\n type: \"inserted\",\n next: [upsertedWithInfo.object],\n });\n } else {\n this.callSubscribed({\n type: \"updated\",\n changes: [[upsertedWithInfo.prev, upsertedWithInfo.object]],\n });\n }\n return upsertedWithInfo;\n }\n\n async partialUpdateByKey(\n key: KeyValue,\n partialUpdate: Update<Model>,\n criteria?: Criteria<Model>,\n options?: PartialUpdateOptions,\n ): Promise<Model> {\n if (!this.hasListeners()) {\n return this.store.partialUpdateByKey(\n key,\n partialUpdate,\n criteria,\n options,\n );\n }\n\n const result = await this.partialUpdateByKeyAndGetResult(\n key,\n partialUpdate,\n criteria,\n options,\n );\n if (!result) throw new NotFoundError(`Document not found: ${String(key)}`);\n if (!result.next) {\n throw new DeletedAfterUpdateError(\n `Document deleted after update: ${String(key)}`,\n );\n }\n this.callSubscribed({\n type: \"updated\",\n changes: [[result.prev, result.next]],\n });\n return result.next;\n }\n\n partialUpdateOne(\n object: Model,\n partialUpdate: Update<Model>,\n options?: PartialUpdateOptions,\n ): Promise<Model> {\n return this.partialUpdateByKey(\n object[this.keyPath],\n partialUpdate,\n undefined,\n options,\n );\n }\n\n /**\n * Without listeners, one command on the wrapped store. With listeners, the keys\n * matching `criteria` are read first, then each document is updated on its own\n * (re-checking `criteria`) so that every change carries its true `prev`: N + 1\n * round trips. A document inserted after the keys were read is not updated.\n */\n async partialUpdateMany(\n criteria: Criteria<Model>,\n partialUpdate: Update<Model>,\n options?: PartialUpdateOptions,\n ): Promise<void> {\n if (!this.hasListeners()) {\n await this.store.partialUpdateMany(criteria, partialUpdate, options);\n return;\n }\n\n const keys = await this.findKeys(criteria);\n const changes: [Model, Model][] = [];\n\n try {\n for (const key of keys) {\n const result = await this.partialUpdateByKeyAndGetResult(\n key,\n partialUpdate,\n criteria,\n options,\n );\n if (result?.next) changes.push([result.prev, result.next]);\n }\n } finally {\n if (changes.length > 0) this.callSubscribed({ type: \"updated\", changes });\n }\n }\n\n async deleteByKey(key: KeyValue, criteria?: Criteria<Model>): Promise<void> {\n if (!this.hasListeners()) {\n await this.store.deleteByKey(key, criteria);\n return;\n }\n\n const prev = await this.deleteByKeyAndGetPrev(key, criteria);\n if (!prev) return;\n this.callSubscribed({ type: \"deleted\", prev: [prev] });\n }\n\n deleteOne(object: Model): Promise<void> {\n return this.deleteByKey(object[this.keyPath]);\n }\n\n /**\n * Without listeners, one command on the wrapped store. With listeners and a store\n * implementing `deleteByKeyWithInfo`, the keys matching `criteria` are read first,\n * then each document is deleted on its own (re-checking `criteria`), so that the\n * emitted documents are exactly the deleted ones: N + 1 round trips. A document\n * inserted after the keys were read is not deleted.\n */\n async deleteMany(criteria: Criteria<Model>): Promise<void> {\n if (!this.hasListeners()) {\n await this.store.deleteMany(criteria);\n return;\n }\n\n if (!this.store.deleteByKeyWithInfo) {\n const cursor = await this.store.cursor(criteria);\n const prev: Model[] = await cursor.toArray();\n await this.store.deleteMany(criteria);\n this.callSubscribed({ type: \"deleted\", prev });\n return;\n }\n\n const keys = await this.findKeys(criteria);\n const prev: Model[] = [];\n\n try {\n for (const key of keys) {\n const result = await this.store.deleteByKeyWithInfo(key, criteria);\n if (result) prev.push(result.prev);\n }\n } finally {\n if (prev.length > 0) this.callSubscribed({ type: \"deleted\", prev });\n }\n }\n\n async count(criteria?: Criteria<Model>): Promise<number> {\n return this.store.count(criteria);\n }\n\n async cursor<Result extends Partial<Model> = Model>(\n criteria?: Criteria<Model>,\n sort?: Sort<Model>,\n ): Promise<AbstractStoreCursor<any, KeyValue, Model, Result>> {\n const cursor = await this.store.cursor<Result>(criteria, sort);\n cursor.overrideStore(this);\n return cursor;\n }\n}\n","import type {\n AllowedKeyValue,\n BaseModel,\n InsertType,\n Query,\n QueryParams,\n QueryResult,\n QuerySubscription,\n SubscribeCallback,\n} from \"liwi-store\";\nimport type SubscribeStore from \"./SubscribeStore\";\n\nexport default abstract class AbstractSubscribableStoreQuery<\n KeyPath extends keyof Model,\n KeyValue extends AllowedKeyValue,\n Model extends BaseModel & Record<KeyPath, KeyValue>,\n ModelInsertType extends InsertType<Model, KeyPath>,\n Params extends QueryParams<Params> = never,\n Result = Model,\n> implements Query<Result, Params, KeyValue> {\n changeParams(params: Params): never {\n throw new Error(\"Method not supported. Please create a new query.\");\n }\n\n changePartialParams(\n params: Params extends undefined ? never : Partial<Params>,\n ): never {\n throw new Error(\"Method not supported. Please create a new query.\");\n }\n\n private _subscribeStore?: SubscribeStore<\n KeyPath,\n KeyValue,\n Model,\n ModelInsertType,\n any,\n any\n >;\n\n setSubscribeStore(\n store: SubscribeStore<KeyPath, KeyValue, Model, ModelInsertType, any, any>,\n ): void {\n this._subscribeStore = store;\n }\n\n getSubscribeStore(): SubscribeStore<\n KeyPath,\n KeyValue,\n Model,\n ModelInsertType,\n any,\n any\n > {\n if (!this._subscribeStore) {\n throw new Error(\"_subscribeStore is not initialized\");\n }\n return this._subscribeStore;\n }\n\n abstract fetch<T>(\n onFulfilled: (result: QueryResult<Result>) => T,\n ): Promise<T>;\n\n fetchAndSubscribe(\n callback: SubscribeCallback<KeyValue, Result>,\n ): QuerySubscription {\n return this._subscribe(callback, true);\n }\n\n subscribe(callback: SubscribeCallback<KeyValue, Result>): QuerySubscription {\n return this._subscribe(callback, false);\n }\n\n abstract _subscribe(\n callback: SubscribeCallback<KeyValue, Result>,\n _includeInitial: boolean,\n ): QuerySubscription;\n}\n"],"names":["prev"],"mappings":"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"}