liwi-mongo 8.1.1 → 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -24,10 +24,10 @@ import type MongoStore from './MongoStore';
24
24
 
25
25
  const identityTransformer = <
26
26
  Model extends MongoBaseModel<any>,
27
- Transformed = Model
27
+ Transformed = Model,
28
28
  >(
29
29
  model: Model,
30
- ): Transformed => (model as unknown) as Transformed;
30
+ ): Transformed => model as unknown as Transformed;
31
31
 
32
32
  type TestCriteria = (obj: any) => boolean;
33
33
 
@@ -35,7 +35,7 @@ export default class MongoQueryCollection<
35
35
  Model extends MongoBaseModel<KeyValue>,
36
36
  Params extends QueryParams<Params> = never,
37
37
  KeyValue extends AllowedKeyValue = Model['_id'],
38
- Item extends Record<MongoKeyPath, KeyValue> = Model
38
+ Item extends Record<MongoKeyPath, KeyValue> = Model,
39
39
  > extends AbstractSubscribableStoreQuery<
40
40
  MongoKeyPath,
41
41
  KeyValue,
@@ -76,10 +76,9 @@ export default class MongoQueryCollection<
76
76
  }
77
77
 
78
78
  async fetch<T>(onFulfilled: (result: QueryResult<Item[]>) => T): Promise<T> {
79
- const cursor = await this.createMongoCursor();
80
79
  const [result, count] = await Promise.all([
81
- cursor.toArray(),
82
- cursor.count(),
80
+ this.createMongoCursor().then((cursor) => cursor.toArray()),
81
+ this.store.count(),
83
82
  ]);
84
83
 
85
84
  return onFulfilled({
@@ -137,30 +136,27 @@ export default class MongoQueryCollection<
137
136
  break;
138
137
  }
139
138
  case 'updated': {
140
- const { deleted, updated, inserted } = action.changes.reduce(
141
- (
142
- acc: {
143
- deleted: KeyValue[];
144
- updated: Item[];
145
- inserted: Item[];
146
- },
147
- [prevObject, nextObject]: [Model, Model],
148
- index: number,
149
- ) => {
150
- if (testCriteria(prevObject)) {
151
- if (!testCriteria(nextObject)) {
152
- acc.deleted.push(prevObject[this.store.keyPath]);
153
- } else {
154
- acc.updated.push(this.transformer(nextObject));
155
- }
156
- } else if (testCriteria(nextObject)) {
157
- acc.inserted.push(this.transformer(nextObject));
139
+ const {
140
+ deleted,
141
+ updated,
142
+ inserted,
143
+ }: {
144
+ deleted: KeyValue[];
145
+ updated: Item[];
146
+ inserted: Item[];
147
+ } = { deleted: [], updated: [], inserted: [] };
148
+
149
+ action.changes.forEach(([prevObject, nextObject]: [Model, Model]) => {
150
+ if (testCriteria(prevObject)) {
151
+ if (!testCriteria(nextObject)) {
152
+ deleted.push(prevObject[this.store.keyPath]);
153
+ } else {
154
+ updated.push(this.transformer(nextObject));
158
155
  }
159
-
160
- return acc;
161
- },
162
- { deleted: [], updated: [], inserted: [] },
163
- );
156
+ } else if (testCriteria(nextObject)) {
157
+ inserted.push(this.transformer(nextObject));
158
+ }
159
+ });
164
160
 
165
161
  if (deleted.length > 0) {
166
162
  changes.push({ type: 'deleted', keys: deleted });
@@ -23,20 +23,18 @@ import type MongoStore from './MongoStore';
23
23
 
24
24
  const identityTransformer = <
25
25
  Model extends MongoBaseModel<any>,
26
- Transformed = Model
26
+ Transformed = Model,
27
27
  >(
28
28
  model: Model,
29
- ): Transformed => (model as unknown) as Transformed;
29
+ ): Transformed => model as unknown as Transformed;
30
30
 
31
- interface TestCriteria {
32
- test: (obj: any) => boolean;
33
- }
31
+ type TestCriteria = (obj: any) => boolean;
34
32
 
35
33
  export default class MongoQuerySingleItem<
36
34
  Model extends MongoBaseModel<KeyValue>,
37
35
  Params extends QueryParams<Params> = never,
38
36
  Result extends Record<MongoKeyPath, KeyValue> | null = Model | null,
39
- KeyValue extends AllowedKeyValue = Model['_id']
37
+ KeyValue extends AllowedKeyValue = Model['_id'],
40
38
  > extends AbstractSubscribableStoreQuery<
41
39
  MongoKeyPath,
42
40
  KeyValue,
@@ -49,7 +47,7 @@ export default class MongoQuerySingleItem<
49
47
 
50
48
  private readonly options: QueryOptions<Model>;
51
49
 
52
- private mingoQuery?: TestCriteria;
50
+ private testCriteria?: TestCriteria;
53
51
 
54
52
  private readonly transformer: Transformer<Model, Result>;
55
53
 
@@ -64,16 +62,17 @@ export default class MongoQuerySingleItem<
64
62
  this.transformer = transformer;
65
63
  }
66
64
 
67
- createMingoQuery(): TestCriteria {
68
- if (!this.mingoQuery) {
65
+ createMingoTestCriteria(): TestCriteria {
66
+ if (!this.testCriteria) {
69
67
  if (!this.options.criteria) {
70
- return { test: () => true };
68
+ return () => true;
71
69
  }
72
70
 
73
- this.mingoQuery = new mingo.Query(this.options.criteria);
71
+ const mingoQuery = new mingo.Query(this.options.criteria);
72
+ this.testCriteria = mingoQuery.test.bind(mingoQuery);
74
73
  }
75
74
 
76
- return this.mingoQuery;
75
+ return this.testCriteria;
77
76
  }
78
77
 
79
78
  async fetch<T>(onFulfilled: (result: QueryResult<Result>) => T): Promise<T> {
@@ -98,7 +97,7 @@ export default class MongoQuerySingleItem<
98
97
  _includeInitial: boolean,
99
98
  ): QuerySubscription {
100
99
  const store = super.getSubscribeStore();
101
- const mingoQuery: TestCriteria = this.createMingoQuery();
100
+ const testCriteria: TestCriteria = this.createMingoTestCriteria();
102
101
 
103
102
  const promise: Promise<void> = _includeInitial
104
103
  ? this.fetch(({ result, meta, info }: QueryResult<Result>) => {
@@ -117,7 +116,7 @@ export default class MongoQuerySingleItem<
117
116
  const changes: Changes<KeyValue, Result> = [];
118
117
  switch (action.type) {
119
118
  case 'inserted': {
120
- const filtered = action.next.filter(mingoQuery.test);
119
+ const filtered = action.next.filter(testCriteria);
121
120
  if (filtered.length > 0) {
122
121
  changes.push({
123
122
  type: 'updated',
@@ -127,7 +126,7 @@ export default class MongoQuerySingleItem<
127
126
  break;
128
127
  }
129
128
  case 'deleted': {
130
- const filtered = action.prev.filter(mingoQuery.test);
129
+ const filtered = action.prev.filter(testCriteria);
131
130
  if (filtered.length > 0) {
132
131
  changes.push({
133
132
  type: 'deleted',
@@ -138,7 +137,7 @@ export default class MongoQuerySingleItem<
138
137
  }
139
138
  case 'updated': {
140
139
  const filtered = action.changes.filter(([prev, next]) =>
141
- mingoQuery.test(prev),
140
+ testCriteria(prev),
142
141
  );
143
142
  if (filtered.length > 0) {
144
143
  if (this.options.sort) {
@@ -155,7 +154,7 @@ export default class MongoQuerySingleItem<
155
154
  const [, next] = filtered[0];
156
155
  changes.push({
157
156
  type: 'updated',
158
- result: mingoQuery.test(next) ? this.transformer(next) : null!,
157
+ result: testCriteria(next) ? this.transformer(next) : null!,
159
158
  });
160
159
  }
161
160
  } else if (filtered.length === 0) {
package/src/MongoStore.ts CHANGED
@@ -14,7 +14,12 @@ import type {
14
14
  AllowedKeyValue,
15
15
  OptionalBaseModelKeysForInsert,
16
16
  } from 'liwi-types';
17
- import type { Collection, MongoClient } from 'mongodb';
17
+ import type {
18
+ Collection,
19
+ FindCursor,
20
+ MongoClient,
21
+ UpdateFilter,
22
+ } from 'mongodb';
18
23
  import mongodb from 'mongodb';
19
24
  import type {
20
25
  MongoBaseModel,
@@ -28,7 +33,7 @@ import MongoQuerySingleItem from './MongoQuerySingleItem';
28
33
 
29
34
  export interface MongoUpsertResult<
30
35
  KeyValue extends AllowedKeyValue,
31
- Model extends MongoBaseModel<KeyValue>
36
+ Model extends MongoBaseModel<KeyValue>,
32
37
  > extends UpsertResult<Model> {
33
38
  object: Model;
34
39
  inserted: boolean;
@@ -36,7 +41,7 @@ export interface MongoUpsertResult<
36
41
 
37
42
  export default class MongoStore<
38
43
  Model extends MongoBaseModel<KeyValue>,
39
- KeyValue extends AllowedKeyValue = Model[MongoKeyPath]
44
+ KeyValue extends AllowedKeyValue = Model[MongoKeyPath],
40
45
  > implements
41
46
  SubscribableStore<
42
47
  MongoKeyPath,
@@ -44,12 +49,13 @@ export default class MongoStore<
44
49
  Model,
45
50
  MongoInsertType<Model>,
46
51
  MongoConnection
47
- > {
52
+ >
53
+ {
48
54
  readonly keyPath: MongoKeyPath = '_id';
49
55
 
50
56
  readonly connection: MongoConnection;
51
57
 
52
- private _collection: Collection | Promise<Collection>;
58
+ private _collection: Collection<Model> | Promise<Collection<Model>>;
53
59
 
54
60
  constructor(connection: MongoConnection, collectionName: string) {
55
61
  this.connection = connection;
@@ -70,7 +76,7 @@ export default class MongoStore<
70
76
  );
71
77
  }
72
78
 
73
- get collection(): Promise<Collection> {
79
+ get collection(): Promise<Collection<Model>> {
74
80
  if (this.connection.connectionFailed) {
75
81
  return Promise.reject(new Error('MongoDB connection failed'));
76
82
  }
@@ -80,7 +86,7 @@ export default class MongoStore<
80
86
 
81
87
  createQuerySingleItem<
82
88
  Result extends Record<MongoKeyPath, KeyValue> = Model,
83
- Params extends QueryParams<Params> = never
89
+ Params extends QueryParams<Params> = never,
84
90
  >(
85
91
  options: QueryOptions<Model>,
86
92
  transformer?: Transformer<Model, Result>,
@@ -94,7 +100,7 @@ export default class MongoStore<
94
100
 
95
101
  createQueryCollection<
96
102
  Item extends Record<MongoKeyPath, KeyValue> = Model,
97
- Params extends QueryParams<Params> = never
103
+ Params extends QueryParams<Params> = never,
98
104
  >(
99
105
  options: QueryOptions<Model>,
100
106
  transformer?: Transformer<Model, Item>,
@@ -108,15 +114,18 @@ export default class MongoStore<
108
114
 
109
115
  async insertOne(object: MongoInsertType<Model>): Promise<Model> {
110
116
  if (!object._id) {
111
- object._id = new mongodb.ObjectID().toString() as Model['_id'];
117
+ object._id = new mongodb.ObjectId().toString() as Model['_id'];
112
118
  }
113
119
 
114
120
  if (!object.created) object.created = new Date();
115
121
  if (!object.updated) object.updated = new Date();
116
122
 
117
123
  const collection = await this.collection;
118
- const { result } = await collection.insertOne(object);
119
- if (!result.ok || result.n !== 1) {
124
+ const { acknowledged: isAcknowledged } = await collection.insertOne(
125
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
126
+ object as any,
127
+ );
128
+ if (!isAcknowledged) {
120
129
  throw new Error('Fail to insert');
121
130
  }
122
131
 
@@ -127,18 +136,18 @@ export default class MongoStore<
127
136
  if (!object.updated) object.updated = new Date();
128
137
 
129
138
  const collection = await this.collection;
130
- await collection.replaceOne({ _id: object._id }, object);
131
- return object!;
139
+ await collection.replaceOne({ _id: object._id } as Criteria<Model>, object);
140
+ return object;
132
141
  }
133
142
 
134
143
  async upsertOne<
135
144
  K extends Exclude<
136
145
  keyof Model,
137
146
  MongoKeyPath | OptionalBaseModelKeysForInsert
138
- >
147
+ >,
139
148
  >(
140
149
  object: UpsertPartialObject<MongoKeyPath, KeyValue, Model, K>,
141
- setOnInsertPartialObject?: Pick<Model, K>,
150
+ setOnInsertPartialObject?: Update<Model>['$setOnInsert'],
142
151
  ): Promise<Model> {
143
152
  const result = await this.upsertOneWithInfo(
144
153
  object,
@@ -151,10 +160,10 @@ export default class MongoStore<
151
160
  K extends Exclude<
152
161
  keyof Model,
153
162
  MongoKeyPath | OptionalBaseModelKeysForInsert
154
- >
163
+ >,
155
164
  >(
156
165
  object: UpsertPartialObject<MongoKeyPath, KeyValue, Model, K>,
157
- setOnInsertPartialObject?: Pick<Model, K>,
166
+ setOnInsertPartialObject?: Update<Model>['$setOnInsert'],
158
167
  ): Promise<MongoUpsertResult<KeyValue, Model>> {
159
168
  const $setOnInsert = {
160
169
  created: object.created || new Date(),
@@ -171,8 +180,8 @@ export default class MongoStore<
171
180
  const collection = await this.collection;
172
181
 
173
182
  const { upsertedCount } = await collection.updateOne(
174
- { _id: object._id },
175
- { $set, $setOnInsert },
183
+ { _id: object._id } as Criteria<Model>,
184
+ { $set, $setOnInsert } as UpdateFilter<Model>,
176
185
  { upsert: true },
177
186
  );
178
187
 
@@ -180,7 +189,7 @@ export default class MongoStore<
180
189
  Object.assign(object, $setOnInsert);
181
190
  }
182
191
 
183
- return { object: (object as unknown) as Model, inserted: !!upsertedCount };
192
+ return { object: object as unknown as Model, inserted: !!upsertedCount };
184
193
  }
185
194
 
186
195
  replaceSeveral(objects: Model[]): Promise<Model[]> {
@@ -188,16 +197,16 @@ export default class MongoStore<
188
197
  }
189
198
 
190
199
  async partialUpdateByKey(
191
- key: any,
200
+ key: KeyValue,
192
201
  partialUpdate: Update<Model>,
193
202
  criteria?: Criteria<Model>,
194
203
  ): Promise<Model> {
195
204
  const collection = await this.collection;
196
205
  const commandResult = await collection.updateOne(
197
- { _id: key, ...criteria },
198
- partialUpdate,
206
+ { _id: key, ...criteria } as Criteria<Model>,
207
+ partialUpdate as UpdateFilter<Model>,
199
208
  );
200
- if (!commandResult.result.ok) {
209
+ if (!commandResult.acknowledged) {
201
210
  console.error(commandResult);
202
211
  throw new Error('Update failed');
203
212
  }
@@ -217,13 +226,18 @@ export default class MongoStore<
217
226
  partialUpdate: Update<Model>,
218
227
  ): Promise<void> {
219
228
  return this.collection
220
- .then((collection) => collection.updateMany(criteria, partialUpdate))
229
+ .then((collection) =>
230
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
231
+ collection.updateMany(criteria, partialUpdate as any),
232
+ )
221
233
  .then((res) => undefined); // TODO return updated object
222
234
  }
223
235
 
224
- deleteByKey(key: any, criteria?: Criteria<Model>): Promise<void> {
236
+ deleteByKey(key: KeyValue, criteria?: Criteria<Model>): Promise<void> {
225
237
  return this.collection
226
- .then((collection) => collection.deleteOne({ _id: key, ...criteria }))
238
+ .then((collection) =>
239
+ collection.deleteOne({ _id: key, ...criteria } as Criteria<Model>),
240
+ )
227
241
  .then(() => undefined);
228
242
  }
229
243
 
@@ -237,20 +251,35 @@ export default class MongoStore<
237
251
  .then(() => undefined);
238
252
  }
239
253
 
240
- cursor<Result = Model>(
241
- criteria?: Criteria<Model>,
254
+ async count(filter?: Criteria<Model>): Promise<number> {
255
+ const collection = await this.collection;
256
+ return filter
257
+ ? collection.countDocuments(filter)
258
+ : collection.countDocuments();
259
+ }
260
+
261
+ async cursor<Result = Model>(
262
+ filter?: Criteria<Model>,
242
263
  sort?: Sort<Model>,
243
264
  ): Promise<MongoCursor<Model, Result, KeyValue>> {
244
- return this.collection
245
- .then((collection) => collection.find(criteria))
246
- .then(sort && ((cursor) => cursor.sort(sort)))
247
- .then((cursor) => new MongoCursor(this, cursor));
265
+ const collection = await this.collection;
266
+ const findCursor = filter
267
+ ? collection.find<Result>(filter)
268
+ : (collection.find() as unknown as FindCursor<Result>);
269
+ if (sort) findCursor.sort(sort);
270
+ return new MongoCursor<Model, Result, KeyValue>(this, findCursor);
248
271
  }
249
272
 
250
- findByKey(key: any, criteria?: Criteria<Model>): Promise<Model | undefined> {
251
- return this.collection
252
- .then((collection) => collection.findOne({ _id: key, ...criteria }))
253
- .then((result) => result || undefined);
273
+ async findByKey(
274
+ key: KeyValue,
275
+ criteria?: Criteria<Model>,
276
+ ): Promise<Model | undefined> {
277
+ const collection = await this.collection;
278
+ const result = await collection.findOne<Model>({
279
+ _id: key,
280
+ ...criteria,
281
+ } as Criteria<Model>);
282
+ return result || undefined;
254
283
  }
255
284
 
256
285
  findAll(criteria?: Criteria<Model>, sort?: Sort<Model>): Promise<Model[]> {
@@ -259,13 +288,14 @@ export default class MongoStore<
259
288
  );
260
289
  }
261
290
 
262
- findOne(
263
- criteria: Criteria<Model>,
291
+ async findOne(
292
+ filter: Criteria<Model>,
264
293
  sort?: Sort<Model>,
265
294
  ): Promise<Model | undefined> {
266
- return this.collection
267
- .then((collection) => collection.find(criteria))
268
- .then(sort && ((cursor) => cursor.sort(sort)))
269
- .then((cursor) => cursor.limit(1).next());
295
+ const collection = await this.collection;
296
+ const result = await collection.findOne<Model>(filter, {
297
+ sort,
298
+ });
299
+ return result || undefined;
270
300
  }
271
301
  }
@@ -10,7 +10,7 @@ import type MongoStore from './MongoStore';
10
10
 
11
11
  export default function createMongoSubscribeStore<
12
12
  Model extends MongoBaseModel<KeyValue>,
13
- KeyValue extends AllowedKeyValue = Model[MongoKeyPath]
13
+ KeyValue extends AllowedKeyValue = Model[MongoKeyPath],
14
14
  >(
15
15
  mongoStore: MongoStore<Model, KeyValue>,
16
16
  ): SubscribeStore<
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+
4
+ "compilerOptions": {
5
+ "noEmit": true
6
+ }
7
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-node12-dev.cjs.js","sources":["../src/MongoCursor.ts","../src/MongoQueryCollection.ts","../src/MongoQuerySingleItem.ts","../src/MongoStore.ts","../src/MongoConnection.ts","../src/createMongoSubscribeStore.ts"],"sourcesContent":["import { AbstractStoreCursor } from 'liwi-store';\nimport type { AllowedKeyValue } from 'liwi-types';\nimport type { Cursor } from 'mongodb';\nimport type { MongoBaseModel } from './MongoBaseModel';\nimport type MongoStore from './MongoStore';\n\nexport default class MongoCursor<\n Model extends MongoBaseModel<KeyValue>,\n Result extends Partial<Model> = Model,\n KeyValue extends AllowedKeyValue = Model['_id']\n> extends AbstractStoreCursor<\n MongoStore<Model, KeyValue>,\n KeyValue,\n Model,\n Result\n> {\n // key in AbstractCursor\n\n private readonly cursor: Cursor;\n\n private _result?: Result;\n\n constructor(store: MongoStore<Model, KeyValue>, cursor: Cursor) {\n super(store);\n this.cursor = cursor;\n }\n\n advance(count: number): void {\n this.cursor.skip(count);\n }\n\n next(): Promise<any> {\n return this.cursor.next().then((value) => {\n this._result = value;\n this.key = value?._id;\n return this.key;\n });\n }\n\n limit(newLimit: number): Promise<this> {\n this.cursor.limit(newLimit);\n return Promise.resolve(this);\n }\n\n count(applySkipLimit = false): Promise<number> {\n return this.cursor.count(applySkipLimit);\n }\n\n result(): Promise<Result> {\n if (!this._result) throw new Error('Cannot call result() before next()');\n return Promise.resolve(this._result!);\n }\n\n close(): Promise<void> {\n if (this.cursor) {\n this.cursor.close();\n }\n\n return Promise.resolve();\n }\n\n toArray(): Promise<Result[]> {\n return this.cursor.toArray();\n }\n}\n","/* eslint-disable complexity, max-lines */\nimport type {\n QuerySubscription,\n SubscribeCallback,\n QueryResult,\n QueryParams,\n} from 'liwi-store';\nimport type { Actions } from 'liwi-subscribe-store';\nimport { AbstractSubscribableStoreQuery } from 'liwi-subscribe-store';\nimport type {\n Changes,\n QueryOptions,\n Transformer,\n AllowedKeyValue,\n} from 'liwi-types';\nimport mingo from 'mingo';\nimport type {\n MongoBaseModel,\n MongoInsertType,\n MongoKeyPath,\n} from './MongoBaseModel';\nimport type MongoCursor from './MongoCursor';\nimport type MongoStore from './MongoStore';\n\nconst identityTransformer = <\n Model extends MongoBaseModel<any>,\n Transformed = Model\n>(\n model: Model,\n): Transformed => (model as unknown) as Transformed;\n\ntype TestCriteria = (obj: any) => boolean;\n\nexport default class MongoQueryCollection<\n Model extends MongoBaseModel<KeyValue>,\n Params extends QueryParams<Params> = never,\n KeyValue extends AllowedKeyValue = Model['_id'],\n Item extends Record<MongoKeyPath, KeyValue> = Model\n> extends AbstractSubscribableStoreQuery<\n MongoKeyPath,\n KeyValue,\n Model,\n MongoInsertType<Model, KeyValue>,\n Params,\n Item[]\n> {\n private readonly store: MongoStore<Model, KeyValue>;\n\n private readonly options: QueryOptions<Model>;\n\n private testCriteria?: TestCriteria;\n\n private readonly transformer: Transformer<Model, Item>;\n\n constructor(\n store: MongoStore<Model, KeyValue>,\n options: QueryOptions<Model>,\n transformer: Transformer<Model, Item> = identityTransformer,\n ) {\n super();\n this.store = store;\n this.options = options;\n this.transformer = transformer;\n }\n\n createTestCriteria(): TestCriteria {\n if (!this.testCriteria) {\n if (!this.options.criteria) {\n return () => true;\n }\n\n const mingoQuery = new mingo.Query(this.options.criteria);\n this.testCriteria = mingoQuery.test.bind(mingoQuery);\n }\n return this.testCriteria;\n }\n\n async fetch<T>(onFulfilled: (result: QueryResult<Item[]>) => T): Promise<T> {\n const cursor = await this.createMongoCursor();\n const [result, count] = await Promise.all([\n cursor.toArray(),\n cursor.count(),\n ]);\n\n return onFulfilled({\n result: result.map(this.transformer),\n meta: { total: count },\n info: {\n sort: this.options.sort,\n limit: this.options.limit,\n keyPath: this.store.keyPath,\n },\n });\n }\n\n _subscribe(\n callback: SubscribeCallback<KeyValue, Item[]>,\n _includeInitial: boolean,\n ): QuerySubscription {\n const store = super.getSubscribeStore();\n const testCriteria: TestCriteria = this.createTestCriteria();\n\n const promise: Promise<void> = _includeInitial\n ? this.fetch(({ result, meta, info }: QueryResult<Item[]>) => {\n callback(null, [\n {\n type: 'initial',\n initial: result,\n queryInfo: info,\n meta,\n },\n ]);\n })\n : Promise.resolve();\n\n const unsubscribe = store.subscribe((action: Actions<Model>) => {\n const changes: Changes<KeyValue, Item[]> = [];\n switch (action.type) {\n case 'inserted': {\n const filtered = action.next.filter(testCriteria);\n if (filtered.length > 0) {\n changes.push({\n type: 'inserted',\n result: filtered.map(this.transformer),\n });\n }\n break;\n }\n case 'deleted': {\n const filtered = action.prev.filter(testCriteria);\n if (filtered.length > 0) {\n changes.push({\n type: 'deleted',\n keys: filtered.map((object) => object[this.store.keyPath]),\n });\n }\n break;\n }\n case 'updated': {\n const { deleted, updated, inserted } = action.changes.reduce(\n (\n acc: {\n deleted: KeyValue[];\n updated: Item[];\n inserted: Item[];\n },\n [prevObject, nextObject]: [Model, Model],\n index: number,\n ) => {\n if (testCriteria(prevObject)) {\n if (!testCriteria(nextObject)) {\n acc.deleted.push(prevObject[this.store.keyPath]);\n } else {\n acc.updated.push(this.transformer(nextObject));\n }\n } else if (testCriteria(nextObject)) {\n acc.inserted.push(this.transformer(nextObject));\n }\n\n return acc;\n },\n { deleted: [], updated: [], inserted: [] },\n );\n\n if (deleted.length > 0) {\n changes.push({ type: 'deleted', keys: deleted });\n }\n if (updated.length > 0) {\n changes.push({ type: 'updated', result: updated });\n }\n if (inserted.length > 0) {\n changes.push({ type: 'inserted', result: inserted });\n }\n\n break;\n }\n default:\n throw new Error('Unsupported type');\n }\n\n if (changes.length === 0) return;\n\n callback(null, changes);\n });\n // let _feed;\n // const promise = this.queryCallback(this.store.query(), this.store.r)\n // .changes({\n // includeInitial: _includeInitial,\n // includeStates: true,\n // includeTypes: true,\n // includeOffsets: true,\n // })\n // .then((feed) => {\n // if (args.length === 0) {\n // _feed = feed;\n // delete this._promise;\n // }\n //\n // feed.each(callback);\n // return feed;\n // });\n //\n // if (args.length === 0) this._promise = promise;\n\n return {\n stop: unsubscribe,\n cancel: unsubscribe,\n then: <T, U>(\n onFulfilled: () => T | Promise<T>,\n onRejected?: (error: any) => U | Promise<U>,\n ): Promise<T | U> => promise.then(onFulfilled, onRejected),\n };\n }\n\n private async createMongoCursor(): Promise<\n MongoCursor<Model, Model, KeyValue>\n > {\n const cursor = await this.store.cursor(\n this.options.criteria,\n this.options.sort,\n );\n\n if (this.options.skip) {\n cursor.advance(this.options.skip);\n }\n\n if (this.options.limit) {\n await cursor.limit(this.options.limit);\n }\n\n return cursor;\n }\n}\n","import type {\n QuerySubscription,\n SubscribeCallback,\n QueryResult,\n QueryParams,\n} from 'liwi-store';\nimport type { Actions } from 'liwi-subscribe-store';\nimport { AbstractSubscribableStoreQuery } from 'liwi-subscribe-store';\nimport type {\n Changes,\n QueryOptions,\n Transformer,\n AllowedKeyValue,\n} from 'liwi-types';\nimport mingo from 'mingo';\nimport type {\n MongoBaseModel,\n MongoInsertType,\n MongoKeyPath,\n} from './MongoBaseModel';\nimport type MongoCursor from './MongoCursor';\nimport type MongoStore from './MongoStore';\n\nconst identityTransformer = <\n Model extends MongoBaseModel<any>,\n Transformed = Model\n>(\n model: Model,\n): Transformed => (model as unknown) as Transformed;\n\ninterface TestCriteria {\n test: (obj: any) => boolean;\n}\n\nexport default class MongoQuerySingleItem<\n Model extends MongoBaseModel<KeyValue>,\n Params extends QueryParams<Params> = never,\n Result extends Record<MongoKeyPath, KeyValue> | null = Model | null,\n KeyValue extends AllowedKeyValue = Model['_id']\n> extends AbstractSubscribableStoreQuery<\n MongoKeyPath,\n KeyValue,\n Model,\n MongoInsertType<Model, KeyValue>,\n Params,\n Result\n> {\n private readonly store: MongoStore<Model, KeyValue>;\n\n private readonly options: QueryOptions<Model>;\n\n private mingoQuery?: TestCriteria;\n\n private readonly transformer: Transformer<Model, Result>;\n\n constructor(\n store: MongoStore<Model, KeyValue>,\n options: QueryOptions<Model>,\n transformer: Transformer<Model, Result> = identityTransformer,\n ) {\n super();\n this.store = store;\n this.options = options;\n this.transformer = transformer;\n }\n\n createMingoQuery(): TestCriteria {\n if (!this.mingoQuery) {\n if (!this.options.criteria) {\n return { test: () => true };\n }\n\n this.mingoQuery = new mingo.Query(this.options.criteria);\n }\n\n return this.mingoQuery;\n }\n\n async fetch<T>(onFulfilled: (result: QueryResult<Result>) => T): Promise<T> {\n const cursor = await this.createMongoCursor();\n await cursor.limit(1);\n return cursor.toArray().then((result: Model[]) => {\n const item: Result =\n result.length === 0 ? (null as Result) : this.transformer(result[0]);\n return onFulfilled({\n result: item,\n meta: { total: result === null ? 0 : 1 },\n info: {\n limit: 1,\n keyPath: this.store.keyPath,\n },\n });\n });\n }\n\n _subscribe(\n callback: SubscribeCallback<KeyValue, Result>,\n _includeInitial: boolean,\n ): QuerySubscription {\n const store = super.getSubscribeStore();\n const mingoQuery: TestCriteria = this.createMingoQuery();\n\n const promise: Promise<void> = _includeInitial\n ? this.fetch(({ result, meta, info }: QueryResult<Result>) => {\n callback(null, [\n {\n type: 'initial',\n initial: result,\n queryInfo: info,\n meta,\n },\n ]);\n })\n : Promise.resolve();\n\n const unsubscribe = store.subscribe(async (action: Actions<Model>) => {\n const changes: Changes<KeyValue, Result> = [];\n switch (action.type) {\n case 'inserted': {\n const filtered = action.next.filter(mingoQuery.test);\n if (filtered.length > 0) {\n changes.push({\n type: 'updated',\n result: this.transformer(filtered[0]),\n });\n }\n break;\n }\n case 'deleted': {\n const filtered = action.prev.filter(mingoQuery.test);\n if (filtered.length > 0) {\n changes.push({\n type: 'deleted',\n keys: filtered.map((object) => object[this.store.keyPath]),\n });\n }\n break;\n }\n case 'updated': {\n const filtered = action.changes.filter(([prev, next]) =>\n mingoQuery.test(prev),\n );\n if (filtered.length > 0) {\n if (this.options.sort) {\n const { result } = await this.fetch((res) => res);\n changes.push({\n type: 'updated',\n result,\n });\n } else if (filtered.length !== 1) {\n throw new Error(\n 'should not match more than 1, use sort if you can have multiple match',\n );\n } else {\n const [, next] = filtered[0];\n changes.push({\n type: 'updated',\n result: mingoQuery.test(next) ? this.transformer(next) : null!,\n });\n }\n } else if (filtered.length === 0) {\n }\n break;\n }\n default:\n throw new Error('Unsupported type');\n }\n\n if (changes.length === 0) return;\n\n callback(null, changes);\n });\n\n return {\n stop: unsubscribe,\n cancel: unsubscribe,\n then: <T, U>(\n onFulfilled: () => T | Promise<T>,\n onRejected?: (error: any) => U | Promise<U>,\n ): Promise<T | U> => promise.then(onFulfilled, onRejected),\n };\n }\n\n private async createMongoCursor(): Promise<\n MongoCursor<Model, Model, KeyValue>\n > {\n const cursor = await this.store.cursor(\n this.options.criteria,\n this.options.sort,\n );\n\n if (this.options.limit) {\n await cursor.limit(this.options.limit);\n }\n\n return cursor;\n }\n}\n","/* eslint-disable max-lines */\nimport type {\n UpsertResult,\n SubscribableStore,\n QueryParams,\n UpsertPartialObject,\n} from 'liwi-store';\nimport type {\n Criteria,\n Sort,\n Update,\n QueryOptions,\n Transformer,\n AllowedKeyValue,\n OptionalBaseModelKeysForInsert,\n} from 'liwi-types';\nimport type { Collection, MongoClient } from 'mongodb';\nimport mongodb from 'mongodb';\nimport type {\n MongoBaseModel,\n MongoKeyPath,\n MongoInsertType,\n} from './MongoBaseModel';\nimport type MongoConnection from './MongoConnection';\nimport MongoCursor from './MongoCursor';\nimport MongoQueryCollection from './MongoQueryCollection';\nimport MongoQuerySingleItem from './MongoQuerySingleItem';\n\nexport interface MongoUpsertResult<\n KeyValue extends AllowedKeyValue,\n Model extends MongoBaseModel<KeyValue>\n> extends UpsertResult<Model> {\n object: Model;\n inserted: boolean;\n}\n\nexport default class MongoStore<\n Model extends MongoBaseModel<KeyValue>,\n KeyValue extends AllowedKeyValue = Model[MongoKeyPath]\n> implements\n SubscribableStore<\n MongoKeyPath,\n KeyValue,\n Model,\n MongoInsertType<Model>,\n MongoConnection\n > {\n readonly keyPath: MongoKeyPath = '_id';\n\n readonly connection: MongoConnection;\n\n private _collection: Collection | Promise<Collection>;\n\n constructor(connection: MongoConnection, collectionName: string) {\n this.connection = connection;\n\n if (!collectionName) {\n throw new Error(`Invalid collectionName: \"${collectionName}\"`);\n }\n\n this._collection = connection.getConnection().then(\n (client: MongoClient) => {\n this._collection = client.db().collection(collectionName);\n return this._collection;\n },\n (err: any) => {\n this._collection = Promise.reject(err);\n return this._collection;\n },\n );\n }\n\n get collection(): Promise<Collection> {\n if (this.connection.connectionFailed) {\n return Promise.reject(new Error('MongoDB connection failed'));\n }\n\n return Promise.resolve(this._collection);\n }\n\n createQuerySingleItem<\n Result extends Record<MongoKeyPath, KeyValue> = Model,\n Params extends QueryParams<Params> = never\n >(\n options: QueryOptions<Model>,\n transformer?: Transformer<Model, Result>,\n ): MongoQuerySingleItem<Model, Params, Result, KeyValue> {\n return new MongoQuerySingleItem<Model, Params, Result, KeyValue>(\n this,\n options,\n transformer,\n );\n }\n\n createQueryCollection<\n Item extends Record<MongoKeyPath, KeyValue> = Model,\n Params extends QueryParams<Params> = never\n >(\n options: QueryOptions<Model>,\n transformer?: Transformer<Model, Item>,\n ): MongoQueryCollection<Model, Params, Model['_id'], Item> {\n return new MongoQueryCollection<Model, Params, KeyValue, Item>(\n this,\n options,\n transformer,\n );\n }\n\n async insertOne(object: MongoInsertType<Model>): Promise<Model> {\n if (!object._id) {\n object._id = new mongodb.ObjectID().toString() as Model['_id'];\n }\n\n if (!object.created) object.created = new Date();\n if (!object.updated) object.updated = new Date();\n\n const collection = await this.collection;\n const { result } = await collection.insertOne(object);\n if (!result.ok || result.n !== 1) {\n throw new Error('Fail to insert');\n }\n\n return object as Model;\n }\n\n async replaceOne(object: Model): Promise<Model> {\n if (!object.updated) object.updated = new Date();\n\n const collection = await this.collection;\n await collection.replaceOne({ _id: object._id }, object);\n return object!;\n }\n\n async upsertOne<\n K extends Exclude<\n keyof Model,\n MongoKeyPath | OptionalBaseModelKeysForInsert\n >\n >(\n object: UpsertPartialObject<MongoKeyPath, KeyValue, Model, K>,\n setOnInsertPartialObject?: Pick<Model, K>,\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<\n keyof Model,\n MongoKeyPath | OptionalBaseModelKeysForInsert\n >\n >(\n object: UpsertPartialObject<MongoKeyPath, KeyValue, Model, K>,\n setOnInsertPartialObject?: Pick<Model, K>,\n ): Promise<MongoUpsertResult<KeyValue, Model>> {\n const $setOnInsert = {\n created: object.created || new Date(),\n ...setOnInsertPartialObject,\n };\n\n if (!object.updated) {\n (object as MongoBaseModel).updated = new Date();\n }\n\n const $set: Partial<typeof object> = { ...object };\n delete $set.created;\n\n const collection = await this.collection;\n\n const { upsertedCount } = await collection.updateOne(\n { _id: object._id },\n { $set, $setOnInsert },\n { upsert: true },\n );\n\n if (upsertedCount) {\n Object.assign(object, $setOnInsert);\n }\n\n return { object: (object as unknown) as Model, inserted: !!upsertedCount };\n }\n\n replaceSeveral(objects: Model[]): Promise<Model[]> {\n return Promise.all(objects.map((object: Model) => this.replaceOne(object)));\n }\n\n async partialUpdateByKey(\n key: any,\n partialUpdate: Update<Model>,\n criteria?: Criteria<Model>,\n ): Promise<Model> {\n const collection = await this.collection;\n const commandResult = await collection.updateOne(\n { _id: key, ...criteria },\n partialUpdate,\n );\n if (!commandResult.result.ok) {\n console.error(commandResult);\n throw new Error('Update failed');\n }\n const object = await this.findByKey(key);\n return object!;\n }\n\n partialUpdateOne(\n object: Model,\n partialUpdate: Update<Model>,\n ): Promise<Model> {\n return this.partialUpdateByKey(object._id, partialUpdate);\n }\n\n partialUpdateMany(\n criteria: Criteria<Model>,\n partialUpdate: Update<Model>,\n ): Promise<void> {\n return this.collection\n .then((collection) => collection.updateMany(criteria, partialUpdate))\n .then((res) => undefined); // TODO return updated object\n }\n\n deleteByKey(key: any, criteria?: Criteria<Model>): Promise<void> {\n return this.collection\n .then((collection) => collection.deleteOne({ _id: key, ...criteria }))\n .then(() => undefined);\n }\n\n deleteOne(object: Model): Promise<void> {\n return this.deleteByKey(object._id);\n }\n\n deleteMany(selector: Criteria<Model>): Promise<void> {\n return this.collection\n .then((collection) => collection.deleteMany(selector))\n .then(() => undefined);\n }\n\n cursor<Result = Model>(\n criteria?: Criteria<Model>,\n sort?: Sort<Model>,\n ): Promise<MongoCursor<Model, Result, KeyValue>> {\n return this.collection\n .then((collection) => collection.find(criteria))\n .then(sort && ((cursor) => cursor.sort(sort)))\n .then((cursor) => new MongoCursor(this, cursor));\n }\n\n findByKey(key: any, criteria?: Criteria<Model>): Promise<Model | undefined> {\n return this.collection\n .then((collection) => collection.findOne({ _id: key, ...criteria }))\n .then((result) => result || undefined);\n }\n\n findAll(criteria?: Criteria<Model>, sort?: Sort<Model>): Promise<Model[]> {\n return this.cursor<Model>(criteria, sort).then((cursor) =>\n cursor.toArray(),\n );\n }\n\n findOne(\n criteria: Criteria<Model>,\n sort?: Sort<Model>,\n ): Promise<Model | undefined> {\n return this.collection\n .then((collection) => collection.find(criteria))\n .then(sort && ((cursor) => cursor.sort(sort)))\n .then((cursor) => cursor.limit(1).next());\n }\n}\n","import { AbstractConnection } from 'liwi-store';\nimport mongodb from 'mongodb';\nimport Logger from 'nightingale-logger';\n\nconst logger = new Logger('liwi:mongo:MongoConnection');\n\nexport default class MongoConnection extends AbstractConnection {\n _connection?: mongodb.MongoClient;\n\n _connecting?: Promise<mongodb.MongoClient>;\n\n connectionFailed?: boolean;\n\n // TODO interface\n constructor(config: Map<string, string | number>) {\n super();\n\n if (!config.has('host')) {\n config.set('host', 'localhost');\n }\n if (!config.has('port')) {\n config.set('port', '27017');\n }\n if (!config.has('database')) {\n throw new Error('Missing config database');\n }\n\n const connectionString =\n `mongodb://${\n config.has('user')\n ? `${config.get('user') as string}:${\n config.get('password') as string\n }@`\n : ''\n }` +\n `${config.get('host') as string}:${config.get('port') as string}/${\n config.get('database') as string\n }`;\n\n this.connect(connectionString);\n }\n\n connect(connectionString: string): void {\n logger.info('connecting', { connectionString });\n\n const connectPromise = mongodb.MongoClient.connect(connectionString, {\n useNewUrlParser: true,\n })\n .then((connection) => {\n logger.info('connected', { connectionString });\n connection.on('close', () => {\n logger.warn('close', { connectionString });\n this.connectionFailed = true;\n this.getConnection = () => {\n throw new Error('MongoDB connection closed');\n };\n });\n connection.on('timeout', () => {\n logger.warn('timeout', { connectionString });\n this.connectionFailed = true;\n this.getConnection = () => {\n throw new Error('MongoDB connection timeout');\n };\n });\n connection.on('reconnect', () => {\n logger.warn('reconnect', { connectionString });\n this.connectionFailed = false;\n this.getConnection = () => Promise.resolve(this._connection!);\n });\n connection.on('error', (err) => {\n logger.warn('error', { connectionString, err });\n });\n\n this._connection = connection;\n this._connecting = undefined;\n this.getConnection = () => Promise.resolve(this._connection!);\n return connection;\n })\n .catch((err) => {\n logger.info('not connected', { connectionString });\n console.error(err.message || err);\n // throw err;\n process.nextTick(() => {\n // eslint-disable-next-line unicorn/no-process-exit\n process.exit(1);\n });\n\n throw err;\n });\n\n this.getConnection = () => Promise.resolve(connectPromise);\n this._connecting = this.getConnection();\n }\n\n getConnection(): Promise<mongodb.MongoClient> {\n throw new Error('call connect()');\n }\n\n async close(): Promise<void> {\n this.getConnection = () => Promise.reject(new Error('Connection closed'));\n if (this._connection) {\n await this._connection.close();\n this._connection = undefined;\n } else if (this._connecting) {\n await this._connecting;\n await this.close();\n }\n }\n}\n","import { SubscribeStore } from 'liwi-subscribe-store';\nimport type { AllowedKeyValue } from 'liwi-types';\nimport type {\n MongoBaseModel,\n MongoInsertType,\n MongoKeyPath,\n} from './MongoBaseModel';\nimport type MongoConnection from './MongoConnection';\nimport type MongoStore from './MongoStore';\n\nexport default function createMongoSubscribeStore<\n Model extends MongoBaseModel<KeyValue>,\n KeyValue extends AllowedKeyValue = Model[MongoKeyPath]\n>(\n mongoStore: MongoStore<Model, KeyValue>,\n): SubscribeStore<\n MongoKeyPath,\n KeyValue,\n Model,\n MongoInsertType<Model, KeyValue>,\n MongoConnection,\n MongoStore<Model, KeyValue>\n> {\n return new SubscribeStore(mongoStore);\n}\n"],"names":["MongoCursor","AbstractStoreCursor","constructor","store","cursor","advance","count","skip","next","then","value","_result","key","_id","limit","newLimit","Promise","resolve","applySkipLimit","result","Error","close","toArray","identityTransformer","model","MongoQueryCollection","AbstractSubscribableStoreQuery","options","transformer","createTestCriteria","testCriteria","criteria","mingoQuery","mingo","Query","test","bind","fetch","onFulfilled","createMongoCursor","all","map","meta","total","info","sort","keyPath","_subscribe","callback","_includeInitial","getSubscribeStore","promise","type","initial","queryInfo","unsubscribe","subscribe","action","changes","filtered","filter","length","push","prev","keys","object","deleted","updated","inserted","reduce","acc","prevObject","nextObject","stop","cancel","onRejected","MongoQuerySingleItem","createMingoQuery","item","res","MongoStore","connection","collectionName","_collection","getConnection","client","db","collection","err","reject","connectionFailed","createQuerySingleItem","createQueryCollection","insertOne","mongodb","ObjectID","toString","created","Date","ok","n","replaceOne","upsertOne","setOnInsertPartialObject","upsertOneWithInfo","$setOnInsert","$set","upsertedCount","updateOne","upsert","Object","assign","replaceSeveral","objects","partialUpdateByKey","partialUpdate","commandResult","console","error","findByKey","partialUpdateOne","partialUpdateMany","updateMany","undefined","deleteByKey","deleteOne","deleteMany","selector","find","findOne","findAll","logger","Logger","MongoConnection","AbstractConnection","config","has","set","connectionString","get","connect","connectPromise","MongoClient","useNewUrlParser","on","warn","_connection","_connecting","catch","message","process","nextTick","exit","createMongoSubscribeStore","mongoStore","SubscribeStore"],"mappings":"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"}