liwi-subscribe-store 13.1.1 → 13.3.3

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
@@ -13,6 +13,12 @@
13
13
  <a href="https://npmjs.org/package/liwi-subscribe-store"><img src="https://img.shields.io/npm/types/liwi-subscribe-store.svg?style=flat-square" alt="types"></a>
14
14
  </p>
15
15
 
16
+ ## About
17
+
18
+ A proxy around a [`liwi-store`](../liwi-store) `Store` that adds live query subscriptions. It implements the full `Store` interface, so it is a drop-in replacement: every write goes through to the wrapped store and then notifies listeners, which is how open queries learn about inserts, updates and deletes.
19
+
20
+ Only writes made **through this proxy, in this process** are observed. Changes written directly to the database (another process, mongo shell, migrations) are not detected.
21
+
16
22
  ## Install
17
23
 
18
24
  ```bash
@@ -21,8 +27,62 @@ npm install --save liwi-subscribe-store
21
27
 
22
28
  ## Usage
23
29
 
24
- ```js
25
- import liwiStore from "liwi-subscribe-store";
30
+ ```ts
31
+ import { SubscribeStore } from "liwi-subscribe-store";
32
+
33
+ const store = new SubscribeStore(mongoStore);
34
+ ```
35
+
36
+ With mongo, prefer the helper which builds the same thing with the types already applied:
37
+
38
+ ```ts
39
+ import { createMongoSubscribeStore } from "liwi-mongo";
40
+
41
+ export const tasksStore = createMongoSubscribeStore<Task>(
42
+ createMongoStore("tasks"),
43
+ );
44
+ ```
45
+
46
+ Queries created from it support `subscribe` / `fetchAndSubscribe`:
47
+
48
+ ```ts
49
+ const query = tasksStore.createQueryCollection({
50
+ criteria: { completed: false },
51
+ sort: { created: 1 },
52
+ limit: 100,
53
+ });
26
54
 
27
- console.log(liwiStore);
55
+ const subscription = query.fetchAndSubscribe((error, changes) => {
56
+ if (error) throw error;
57
+ for (const change of changes) {
58
+ // change.type: "initial" | "inserted" | "updated" | "deleted"
59
+ }
60
+ });
61
+
62
+ // later
63
+ subscription.stop();
28
64
  ```
65
+
66
+ ## API
67
+
68
+ ### `new SubscribeStore(store)`
69
+
70
+ Wraps a `SubscribableStore`. Beyond the `Store` interface it adds:
71
+
72
+ - `subscribe(listener): () => void` — listen to every write going through the proxy; returns an unsubscribe function.
73
+ - `callSubscribed(action): void` — dispatch an action to listeners manually (used by the store implementation, e.g. after an out-of-band write you want queries to see).
74
+
75
+ ### `Actions<Model>`
76
+
77
+ ```ts
78
+ type Actions<Model> =
79
+ | { type: "inserted"; next: Model[] }
80
+ | { type: "updated"; changes: [Model, Model][] } // [previous, next]
81
+ | { type: "deleted"; prev: Model[] };
82
+ ```
83
+
84
+ ### `AbstractSubscribableStoreQuery`
85
+
86
+ 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).
87
+
88
+ Queries built this way are fixed: `changeParams` / `changePartialParams` throw — create a new query instead.
@@ -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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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=SubscribeStore.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubscribeStore.test.d.ts","sourceRoot":"","sources":["../../src/SubscribeStore.test.ts"],"names":[],"mappings":""}
@@ -65,13 +65,16 @@ class SubscribeStore {
65
65
  object,
66
66
  setOnInsertPartialObject
67
67
  );
68
- if (upsertedWithInfo.inserted) {
68
+ if (upsertedWithInfo.resolvedAs === "inserted") {
69
69
  this.callSubscribed({
70
70
  type: "inserted",
71
71
  next: [upsertedWithInfo.object]
72
72
  });
73
73
  } else {
74
- throw new Error("TODO");
74
+ this.callSubscribed({
75
+ type: "updated",
76
+ changes: [[upsertedWithInfo.prev, upsertedWithInfo.object]]
77
+ });
75
78
  }
76
79
  return upsertedWithInfo;
77
80
  }
@@ -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.inserted) {\n this.callSubscribed({\n type: \"inserted\",\n next: [upsertedWithInfo.object],\n });\n } else {\n throw new Error(\"TODO\");\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 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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"}
@@ -65,13 +65,16 @@ class SubscribeStore {
65
65
  object,
66
66
  setOnInsertPartialObject
67
67
  );
68
- if (upsertedWithInfo.inserted) {
68
+ if (upsertedWithInfo.resolvedAs === "inserted") {
69
69
  this.callSubscribed({
70
70
  type: "inserted",
71
71
  next: [upsertedWithInfo.object]
72
72
  });
73
73
  } else {
74
- throw new Error("TODO");
74
+ this.callSubscribed({
75
+ type: "updated",
76
+ changes: [[upsertedWithInfo.prev, upsertedWithInfo.object]]
77
+ });
75
78
  }
76
79
  return upsertedWithInfo;
77
80
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index-node.mjs","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.inserted) {\n this.callSubscribed({\n type: \"inserted\",\n next: [upsertedWithInfo.object],\n });\n } else {\n throw new Error(\"TODO\");\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-node.mjs","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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "liwi-subscribe-store",
3
- "version": "13.1.1",
3
+ "version": "13.3.3",
4
4
  "description": "subscribe store proxy",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/christophehurpeau/liwi",
@@ -37,7 +37,7 @@
37
37
  }
38
38
  },
39
39
  "dependencies": {
40
- "liwi-store": "13.1.1"
40
+ "liwi-store": "13.3.3"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@pob/rollup-esbuild": "10.0.0",
@@ -0,0 +1,97 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+ import type {
4
+ AbstractConnection,
5
+ SubscribableStore,
6
+ UpsertResult,
7
+ } from "liwi-store";
8
+ import type { Actions } from "./SubscribeStore.ts";
9
+ import SubscribeStore from "./SubscribeStore.ts";
10
+
11
+ interface TestModel {
12
+ _id: string;
13
+ created: Date;
14
+ updated: Date;
15
+ label: string;
16
+ }
17
+
18
+ type TestStore = SubscribableStore<
19
+ "_id",
20
+ string,
21
+ TestModel,
22
+ TestModel,
23
+ AbstractConnection
24
+ >;
25
+
26
+ type TestSubscribeStore = SubscribeStore<
27
+ "_id",
28
+ string,
29
+ TestModel,
30
+ TestModel,
31
+ AbstractConnection,
32
+ TestStore
33
+ >;
34
+
35
+ const created = new Date("2020-01-01");
36
+ const updated = new Date("2021-01-01");
37
+
38
+ const createSubscribeStore = (
39
+ upsertResult: UpsertResult<TestModel>,
40
+ ): {
41
+ subscribeStore: TestSubscribeStore;
42
+ actions: Actions<TestModel>[];
43
+ } => {
44
+ const store: Pick<TestStore, "keyPath" | "upsertOneWithInfo"> = {
45
+ keyPath: "_id",
46
+ upsertOneWithInfo: () => Promise.resolve(upsertResult),
47
+ };
48
+ const subscribeStore: TestSubscribeStore = new SubscribeStore(
49
+ store as TestStore,
50
+ );
51
+ const actions: Actions<TestModel>[] = [];
52
+ subscribeStore.subscribe((action) => actions.push(action));
53
+ return { subscribeStore, actions };
54
+ };
55
+
56
+ describe("SubscribeStore upsertOneWithInfo", () => {
57
+ it("emits inserted when the upsert resolved as inserted", async () => {
58
+ const object: TestModel = { _id: "1", label: "a", created, updated };
59
+ const upsertResult: UpsertResult<TestModel> = {
60
+ resolvedAs: "inserted",
61
+ inserted: true,
62
+ object,
63
+ };
64
+ const { subscribeStore, actions } = createSubscribeStore(upsertResult);
65
+
66
+ const result = await subscribeStore.upsertOneWithInfo(object);
67
+
68
+ assert.equal(result, upsertResult);
69
+ assert.deepEqual(actions, [{ type: "inserted", next: [object] }]);
70
+ });
71
+
72
+ it("emits updated with prev and next when the upsert resolved as updated", async () => {
73
+ const prev: TestModel = {
74
+ _id: "1",
75
+ label: "old",
76
+ created,
77
+ updated: created,
78
+ };
79
+ const object: TestModel = { _id: "1", label: "a", created, updated };
80
+ const upsertResult: UpsertResult<TestModel> = {
81
+ resolvedAs: "updated",
82
+ inserted: false,
83
+ object,
84
+ prev,
85
+ };
86
+ const { subscribeStore, actions } = createSubscribeStore(upsertResult);
87
+
88
+ const result = await subscribeStore.upsertOneWithInfo({
89
+ _id: "1",
90
+ label: "a",
91
+ updated,
92
+ });
93
+
94
+ assert.equal(result, upsertResult);
95
+ assert.deepEqual(actions, [{ type: "updated", changes: [[prev, object]] }]);
96
+ });
97
+ });
@@ -180,13 +180,16 @@ export default class SubscribeStore<
180
180
  object,
181
181
  setOnInsertPartialObject,
182
182
  );
183
- if (upsertedWithInfo.inserted) {
183
+ if (upsertedWithInfo.resolvedAs === "inserted") {
184
184
  this.callSubscribed({
185
185
  type: "inserted",
186
186
  next: [upsertedWithInfo.object],
187
187
  });
188
188
  } else {
189
- throw new Error("TODO");
189
+ this.callSubscribed({
190
+ type: "updated",
191
+ changes: [[upsertedWithInfo.prev, upsertedWithInfo.object]],
192
+ });
190
193
  }
191
194
  return upsertedWithInfo;
192
195
  }