@travetto/model-mongo 3.0.0-rc.1 → 3.0.0-rc.11
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 +15 -25
- package/{index.ts → __index__.ts} +0 -0
- package/package.json +18 -8
- package/src/config.ts +9 -19
- package/src/internal/util.ts +7 -9
- package/src/service.ts +25 -10
- package/support/service.mongo.ts +4 -4
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!-- This file was generated by @travetto/doc and should not be modified directly -->
|
|
2
|
-
<!-- Please modify https://github.com/travetto/travetto/tree/main/module/model-mongo/
|
|
2
|
+
<!-- Please modify https://github.com/travetto/travetto/tree/main/module/model-mongo/DOC.ts and execute "npx trv doc" to rebuild -->
|
|
3
3
|
# MongoDB Model Support
|
|
4
4
|
## Mongo backing for the travetto model module.
|
|
5
5
|
|
|
@@ -15,7 +15,7 @@ Supported features:
|
|
|
15
15
|
* [CRUD](https://github.com/travetto/travetto/tree/main/module/model/src/service/crud.ts#L11)
|
|
16
16
|
* [Streaming](https://github.com/travetto/travetto/tree/main/module/model/src/service/stream.ts#L3)
|
|
17
17
|
* [Expiry](https://github.com/travetto/travetto/tree/main/module/model/src/service/expiry.ts#L11)
|
|
18
|
-
* [Bulk](https://github.com/travetto/travetto/tree/main/module/model/src/service/bulk.ts#
|
|
18
|
+
* [Bulk](https://github.com/travetto/travetto/tree/main/module/model/src/service/bulk.ts#L19)
|
|
19
19
|
* [Indexed](https://github.com/travetto/travetto/tree/main/module/model/src/service/indexed.ts#L12)
|
|
20
20
|
* [Query Crud](https://github.com/travetto/travetto/tree/main/module/model-query/src/service/crud.ts#L11)
|
|
21
21
|
* [Facet](https://github.com/travetto/travetto/tree/main/module/model-query/src/service/facet.ts#L12)
|
|
@@ -41,15 +41,14 @@ export class Init {
|
|
|
41
41
|
}
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
where the [MongoModelConfig](https://github.com/travetto/travetto/tree/main/module/model-mongo/src/config.ts#
|
|
44
|
+
where the [MongoModelConfig](https://github.com/travetto/travetto/tree/main/module/model-mongo/src/config.ts#L11) is defined by:
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
**Code: Structure of MongoModelConfig**
|
|
48
48
|
```typescript
|
|
49
|
-
import
|
|
50
|
-
import { promises as fs } from 'fs';
|
|
49
|
+
import type mongo from 'mongodb';
|
|
51
50
|
|
|
52
|
-
import {
|
|
51
|
+
import { FileResourceProvider, TimeSpan } from '@travetto/base';
|
|
53
52
|
import { Config } from '@travetto/config';
|
|
54
53
|
import { Field } from '@travetto/schema';
|
|
55
54
|
|
|
@@ -104,35 +103,26 @@ export class MongoModelConfig {
|
|
|
104
103
|
*/
|
|
105
104
|
cullRate?: number | TimeSpan;
|
|
106
105
|
|
|
107
|
-
/**
|
|
108
|
-
* Load a resource
|
|
109
|
-
*/
|
|
110
|
-
async fetch(val: string): Promise<string> {
|
|
111
|
-
return ResourceManager.read(val)
|
|
112
|
-
.then(res => typeof res === 'string' ? res : res.toString('utf8'))
|
|
113
|
-
.catch(() => fs.readFile(val)
|
|
114
|
-
.then(res => typeof res === 'string' ? res : res.toString('utf8'))
|
|
115
|
-
)
|
|
116
|
-
.catch(() => val);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
106
|
/**
|
|
120
107
|
* Load all the ssl certs as needed
|
|
121
108
|
*/
|
|
122
109
|
async postConstruct(): Promise<void> {
|
|
110
|
+
const resources = new FileResourceProvider({ includeCommon: true });
|
|
111
|
+
const resolve = (file: string): Promise<string> => resources.describe(file).then(({ path }) => path, () => file);
|
|
112
|
+
|
|
123
113
|
const opts = this.options;
|
|
124
114
|
if (opts.ssl) {
|
|
125
115
|
if (opts.sslCert) {
|
|
126
|
-
opts.tlsCertificateFile = await
|
|
116
|
+
opts.tlsCertificateFile = await resolve(opts.sslCert);
|
|
127
117
|
}
|
|
128
118
|
if (opts.sslKey) {
|
|
129
|
-
opts.sslKey = await
|
|
119
|
+
opts.sslKey = await resolve(opts.sslKey);
|
|
130
120
|
}
|
|
131
121
|
if (opts.sslCA) {
|
|
132
|
-
opts.sslCA = await
|
|
122
|
+
opts.sslCA = await resolve(opts.sslCA);
|
|
133
123
|
}
|
|
134
124
|
if (opts.sslCRL) {
|
|
135
|
-
opts.sslCRL = await
|
|
125
|
+
opts.sslCRL = await resolve(opts.sslCRL);
|
|
136
126
|
}
|
|
137
127
|
}
|
|
138
128
|
}
|
|
@@ -155,8 +145,8 @@ export class MongoModelConfig {
|
|
|
155
145
|
}
|
|
156
146
|
```
|
|
157
147
|
|
|
158
|
-
Additionally, you can see that the class is registered with the [@Config](https://github.com/travetto/travetto/tree/main/module/config/src/decorator.ts#
|
|
159
|
-
standard [Configuration](https://github.com/travetto/travetto/tree/main/module/config#readme "
|
|
148
|
+
Additionally, you can see that the class is registered with the [@Config](https://github.com/travetto/travetto/tree/main/module/config/src/decorator.ts#L13) annotation, and so these values can be overridden using the
|
|
149
|
+
standard [Configuration](https://github.com/travetto/travetto/tree/main/module/config#readme "Configuration support")resolution paths.
|
|
160
150
|
|
|
161
151
|
|
|
162
|
-
The SSL file options in `clientOptions` will automatically be resolved to files when given a path. This path can be a [
|
|
152
|
+
The SSL file options in `clientOptions` will automatically be resolved to files when given a path. This path can be a [FileResourceProvider](https://github.com/travetto/travetto/tree/main/module/base/src/resource.ts#L46) path or just a standard file path.
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/model-mongo",
|
|
3
|
-
"
|
|
4
|
-
"version": "3.0.0-rc.1",
|
|
3
|
+
"version": "3.0.0-rc.11",
|
|
5
4
|
"description": "Mongo backing for the travetto model module.",
|
|
6
5
|
"keywords": [
|
|
7
6
|
"mongo",
|
|
@@ -16,20 +15,31 @@
|
|
|
16
15
|
"name": "Travetto Framework"
|
|
17
16
|
},
|
|
18
17
|
"files": [
|
|
19
|
-
"
|
|
18
|
+
"__index__.ts",
|
|
20
19
|
"src",
|
|
21
20
|
"support"
|
|
22
21
|
],
|
|
23
|
-
"main": "
|
|
22
|
+
"main": "__index__.ts",
|
|
24
23
|
"repository": {
|
|
25
24
|
"url": "https://github.com/travetto/travetto.git",
|
|
26
25
|
"directory": "module/model-mongo"
|
|
27
26
|
},
|
|
28
27
|
"dependencies": {
|
|
29
|
-
"@travetto/config": "^3.0.0-rc.
|
|
30
|
-
"@travetto/model": "^3.0.0-rc.
|
|
31
|
-
"@travetto/model-query": "3.0.0-rc.
|
|
32
|
-
"mongodb": "^
|
|
28
|
+
"@travetto/config": "^3.0.0-rc.11",
|
|
29
|
+
"@travetto/model": "^3.0.0-rc.11",
|
|
30
|
+
"@travetto/model-query": "^3.0.0-rc.11",
|
|
31
|
+
"mongodb": "^5.0.0"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"@travetto/command": "^3.0.0-rc.8"
|
|
35
|
+
},
|
|
36
|
+
"peerDependenciesMeta": {
|
|
37
|
+
"@travetto/command": {
|
|
38
|
+
"optional": true
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"travetto": {
|
|
42
|
+
"displayName": "MongoDB Model Support"
|
|
33
43
|
},
|
|
34
44
|
"publishConfig": {
|
|
35
45
|
"access": "public"
|
package/src/config.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { promises as fs } from 'fs';
|
|
1
|
+
import type mongo from 'mongodb';
|
|
3
2
|
|
|
4
|
-
import {
|
|
3
|
+
import { FileResourceProvider, TimeSpan } from '@travetto/base';
|
|
5
4
|
import { Config } from '@travetto/config';
|
|
6
5
|
import { Field } from '@travetto/schema';
|
|
7
6
|
|
|
@@ -56,35 +55,26 @@ export class MongoModelConfig {
|
|
|
56
55
|
*/
|
|
57
56
|
cullRate?: number | TimeSpan;
|
|
58
57
|
|
|
59
|
-
/**
|
|
60
|
-
* Load a resource
|
|
61
|
-
*/
|
|
62
|
-
async fetch(val: string): Promise<string> {
|
|
63
|
-
return ResourceManager.read(val)
|
|
64
|
-
.then(res => typeof res === 'string' ? res : res.toString('utf8'))
|
|
65
|
-
.catch(() => fs.readFile(val)
|
|
66
|
-
.then(res => typeof res === 'string' ? res : res.toString('utf8'))
|
|
67
|
-
)
|
|
68
|
-
.catch(() => val);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
58
|
/**
|
|
72
59
|
* Load all the ssl certs as needed
|
|
73
60
|
*/
|
|
74
61
|
async postConstruct(): Promise<void> {
|
|
62
|
+
const resources = new FileResourceProvider({ includeCommon: true });
|
|
63
|
+
const resolve = (file: string): Promise<string> => resources.describe(file).then(({ path }) => path, () => file);
|
|
64
|
+
|
|
75
65
|
const opts = this.options;
|
|
76
66
|
if (opts.ssl) {
|
|
77
67
|
if (opts.sslCert) {
|
|
78
|
-
opts.tlsCertificateFile = await
|
|
68
|
+
opts.tlsCertificateFile = await resolve(opts.sslCert);
|
|
79
69
|
}
|
|
80
70
|
if (opts.sslKey) {
|
|
81
|
-
opts.sslKey = await
|
|
71
|
+
opts.sslKey = await resolve(opts.sslKey);
|
|
82
72
|
}
|
|
83
73
|
if (opts.sslCA) {
|
|
84
|
-
opts.sslCA = await
|
|
74
|
+
opts.sslCA = await resolve(opts.sslCA);
|
|
85
75
|
}
|
|
86
76
|
if (opts.sslCRL) {
|
|
87
|
-
opts.sslCRL = await
|
|
77
|
+
opts.sslCRL = await resolve(opts.sslCRL);
|
|
88
78
|
}
|
|
89
79
|
}
|
|
90
80
|
}
|
package/src/internal/util.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import * as mongo from 'mongodb';
|
|
2
2
|
|
|
3
|
-
import { Class,
|
|
3
|
+
import { Class, DataUtil, ObjectUtil } from '@travetto/base';
|
|
4
4
|
import { DistanceUnit, ModelQuery, Query, WhereClause } from '@travetto/model-query';
|
|
5
|
-
import { ModelType } from '@travetto/model';
|
|
5
|
+
import type { ModelType, IndexField } from '@travetto/model';
|
|
6
6
|
import { ModelQueryUtil } from '@travetto/model-query/src/internal/service/query';
|
|
7
|
-
import { IndexField } from '@travetto/model/src/registry/types';
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
9
|
* Converting units to various radians
|
|
@@ -20,7 +19,6 @@ const RADIANS_TO: Record<DistanceUnit, number> = {
|
|
|
20
19
|
export type WithId<T> = T & { _id?: mongo.Binary };
|
|
21
20
|
const isWithId = <T extends ModelType>(o: T): o is WithId<T> => o && '_id' in o;
|
|
22
21
|
|
|
23
|
-
|
|
24
22
|
/**
|
|
25
23
|
* Basic mongo utils for conforming to the model module
|
|
26
24
|
*/
|
|
@@ -51,7 +49,7 @@ export class MongoUtil {
|
|
|
51
49
|
} else if (id instanceof mongo.ObjectId) {
|
|
52
50
|
return id.toHexString();
|
|
53
51
|
} else {
|
|
54
|
-
return id.buffer.toString('hex');
|
|
52
|
+
return Buffer.from(id.buffer).toString('hex');
|
|
55
53
|
}
|
|
56
54
|
}
|
|
57
55
|
|
|
@@ -119,7 +117,7 @@ export class MongoUtil {
|
|
|
119
117
|
return this.uuid(v);
|
|
120
118
|
} else if (Array.isArray(v)) {
|
|
121
119
|
return v.map(x => this.replaceId(x));
|
|
122
|
-
} else if (
|
|
120
|
+
} else if (ObjectUtil.isPlainObject(v)) {
|
|
123
121
|
const out: Record<string, mongo.Binary> = {};
|
|
124
122
|
for (const [k, el] of Object.entries(v)) {
|
|
125
123
|
const found = this.replaceId(el);
|
|
@@ -149,9 +147,9 @@ export class MongoUtil {
|
|
|
149
147
|
if (subpath === 'id') { // Handle ids directly
|
|
150
148
|
out._id = this.replaceId(v);
|
|
151
149
|
} else {
|
|
152
|
-
const isPlain = v &&
|
|
150
|
+
const isPlain = v && ObjectUtil.isPlainObject(v);
|
|
153
151
|
const firstKey = isPlain ? Object.keys(v)[0] : '';
|
|
154
|
-
if ((isPlain && !firstKey.startsWith('$')) || v?.constructor
|
|
152
|
+
if ((isPlain && !firstKey.startsWith('$')) || v?.constructor?.Ⲑid) {
|
|
155
153
|
Object.assign(out, this.extractSimple(v, `${subpath}.`));
|
|
156
154
|
} else {
|
|
157
155
|
if (firstKey === '$gt' || firstKey === '$lt' || firstKey === '$gte' || firstKey === '$lte') {
|
|
@@ -160,7 +158,7 @@ export class MongoUtil {
|
|
|
160
158
|
}
|
|
161
159
|
} else if (firstKey === '$regex') {
|
|
162
160
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
163
|
-
v.$regex =
|
|
161
|
+
v.$regex = DataUtil.toRegex(v.$regex as string | RegExp);
|
|
164
162
|
} else if (firstKey && '$near' in v) {
|
|
165
163
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
166
164
|
const dist = v.$maxDistance as number;
|
package/src/service.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// Wildcard import needed here due to packaging issues
|
|
2
2
|
import * as mongo from 'mongodb';
|
|
3
3
|
import { Readable } from 'stream';
|
|
4
4
|
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
PageableModelQuery, ValidStringFields, WhereClause, ModelQuerySuggestSupport
|
|
15
15
|
} from '@travetto/model-query';
|
|
16
16
|
|
|
17
|
-
import { ShutdownManager,
|
|
17
|
+
import { ShutdownManager, type Class, AppError } from '@travetto/base';
|
|
18
18
|
import { Injectable } from '@travetto/di';
|
|
19
19
|
import { DeepPartial, FieldConfig, SchemaRegistry, SchemaValidator } from '@travetto/schema';
|
|
20
20
|
|
|
@@ -29,11 +29,12 @@ import { ModelExpiryUtil } from '@travetto/model/src/internal/service/expiry';
|
|
|
29
29
|
import { StreamModel, STREAMS } from '@travetto/model/src/internal/service/stream';
|
|
30
30
|
import { AllViewⲐ } from '@travetto/schema/src/internal/types';
|
|
31
31
|
import { ModelBulkUtil } from '@travetto/model/src/internal/service/bulk';
|
|
32
|
+
import { ModelUtil } from '@travetto/model/src/internal/util';
|
|
32
33
|
|
|
33
34
|
import { MongoUtil, WithId } from './internal/util';
|
|
34
35
|
import { MongoModelConfig } from './config';
|
|
35
36
|
|
|
36
|
-
const IdxFieldsⲐ = Symbol.for('@
|
|
37
|
+
const IdxFieldsⲐ = Symbol.for('@travetto/model-mongo:idx');
|
|
37
38
|
|
|
38
39
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
39
40
|
const asFielded = <T extends ModelType>(cfg: IndexConfig<T>): { [IdxFieldsⲐ]: mongo.Sort } => (cfg as unknown as { [IdxFieldsⲐ]: mongo.Sort });
|
|
@@ -78,7 +79,7 @@ export class MongoModelService implements
|
|
|
78
79
|
writeConcern: { w: 1 }
|
|
79
80
|
});
|
|
80
81
|
await ModelStorageUtil.registerModelChangeListener(this);
|
|
81
|
-
ShutdownManager.onShutdown(this
|
|
82
|
+
ShutdownManager.onShutdown(this, () => this.client.close());
|
|
82
83
|
ModelExpiryUtil.registerCull(this);
|
|
83
84
|
}
|
|
84
85
|
|
|
@@ -90,7 +91,7 @@ export class MongoModelService implements
|
|
|
90
91
|
* Build a mongo identifier
|
|
91
92
|
*/
|
|
92
93
|
uuid(): string {
|
|
93
|
-
return
|
|
94
|
+
return ModelUtil.uuid();
|
|
94
95
|
}
|
|
95
96
|
|
|
96
97
|
// Storage
|
|
@@ -111,7 +112,7 @@ export class MongoModelService implements
|
|
|
111
112
|
out.push(...this.getGeoIndices(field.type, [...path, field], root));
|
|
112
113
|
} else if (field.type === PointImpl) {
|
|
113
114
|
const name = [...path, field].map(x => x.name).join('.');
|
|
114
|
-
console.debug('Preparing geo-index', { cls: root
|
|
115
|
+
console.debug('Preparing geo-index', { cls: root.Ⲑid, name });
|
|
115
116
|
out.push({ [name]: '2d' });
|
|
116
117
|
}
|
|
117
118
|
}
|
|
@@ -193,6 +194,7 @@ export class MongoModelService implements
|
|
|
193
194
|
if (!result.insertedId) {
|
|
194
195
|
throw new ExistsError(cls, cleaned.id);
|
|
195
196
|
}
|
|
197
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
196
198
|
delete (cleaned as { _id?: unknown })._id;
|
|
197
199
|
return cleaned;
|
|
198
200
|
}
|
|
@@ -244,9 +246,11 @@ export class MongoModelService implements
|
|
|
244
246
|
.entries(items)
|
|
245
247
|
.reduce<Record<string, unknown>>((acc, [k, v]) => {
|
|
246
248
|
if (v === null || v === undefined) {
|
|
249
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
247
250
|
const o = (acc.$unset ??= {}) as Record<string, unknown>;
|
|
248
251
|
o[k] = v;
|
|
249
252
|
} else {
|
|
253
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
250
254
|
const o = (acc.$set ??= {}) as Record<string, unknown>;
|
|
251
255
|
o[k] = v;
|
|
252
256
|
}
|
|
@@ -297,9 +301,7 @@ export class MongoModelService implements
|
|
|
297
301
|
});
|
|
298
302
|
|
|
299
303
|
await new Promise<unknown>((resolve, reject) => {
|
|
300
|
-
input.pipe(writeStream);
|
|
301
|
-
input.on('error', reject);
|
|
302
|
-
writeStream.once('finish', resolve);
|
|
304
|
+
input.pipe(writeStream).on('finish', resolve).on('error', reject);
|
|
303
305
|
});
|
|
304
306
|
}
|
|
305
307
|
|
|
@@ -348,6 +350,7 @@ export class MongoModelService implements
|
|
|
348
350
|
|
|
349
351
|
for (const op of operations) {
|
|
350
352
|
if (op.insert) {
|
|
353
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
351
354
|
bulk.insert(MongoUtil.preInsertId(op.insert as T));
|
|
352
355
|
} else if (op.upsert) {
|
|
353
356
|
bulk.find({ _id: MongoUtil.uuid(op.upsert.id!) }).upsert().updateOne({ $set: op.upsert });
|
|
@@ -362,9 +365,11 @@ export class MongoModelService implements
|
|
|
362
365
|
|
|
363
366
|
for (const op of operations) {
|
|
364
367
|
if (op.insert) {
|
|
368
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
365
369
|
MongoUtil.postLoadId(op.insert as T);
|
|
366
370
|
}
|
|
367
371
|
}
|
|
372
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
368
373
|
for (const { index, _id } of res.getUpsertedIds() as { index: number, _id: mongo.ObjectId }[]) {
|
|
369
374
|
out.insertedIds.set(index, MongoUtil.idToString(_id));
|
|
370
375
|
}
|
|
@@ -380,6 +385,7 @@ export class MongoModelService implements
|
|
|
380
385
|
out.errors = res.getWriteErrors();
|
|
381
386
|
for (const err of out.errors) {
|
|
382
387
|
const op = operations[err.index];
|
|
388
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
383
389
|
const k = Object.keys(op)[0] as keyof BulkResponse['counts'];
|
|
384
390
|
out.counts[k] -= 1;
|
|
385
391
|
}
|
|
@@ -401,6 +407,7 @@ export class MongoModelService implements
|
|
|
401
407
|
const result = await store.findOne(
|
|
402
408
|
this.getWhere(
|
|
403
409
|
cls,
|
|
410
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
404
411
|
ModelIndexedUtil.projectIndex(cls, idx, body) as WhereClause<T>
|
|
405
412
|
)
|
|
406
413
|
);
|
|
@@ -416,6 +423,7 @@ export class MongoModelService implements
|
|
|
416
423
|
const result = await store.deleteOne(
|
|
417
424
|
this.getWhere(
|
|
418
425
|
cls,
|
|
426
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
419
427
|
ModelIndexedUtil.projectIndex(cls, idx, body) as WhereClause<T>
|
|
420
428
|
)
|
|
421
429
|
);
|
|
@@ -437,14 +445,17 @@ export class MongoModelService implements
|
|
|
437
445
|
throw new AppError('Cannot list on unique indices', 'data');
|
|
438
446
|
}
|
|
439
447
|
|
|
448
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
440
449
|
const where = this.getWhere(
|
|
441
450
|
cls,
|
|
451
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
442
452
|
ModelIndexedUtil.projectIndex(cls, idx, body, { emptySortValue: { $exists: true } }) as WhereClause<T>
|
|
443
|
-
) as mongo.Filter<
|
|
453
|
+
) as mongo.Filter<Document>;
|
|
444
454
|
|
|
445
455
|
const cursor = store.find(where, { timeout: true }).batchSize(100).sort(asFielded(idxCfg)[IdxFieldsⲐ]);
|
|
446
456
|
|
|
447
457
|
for await (const el of cursor) {
|
|
458
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
448
459
|
yield (await MongoUtil.postLoadId(await ModelCrudUtil.load(cls, el))) as T;
|
|
449
460
|
}
|
|
450
461
|
}
|
|
@@ -506,9 +517,11 @@ export class MongoModelService implements
|
|
|
506
517
|
const items = MongoUtil.extractSimple(data);
|
|
507
518
|
const final = Object.entries(items).reduce<Record<string, unknown>>((acc, [k, v]) => {
|
|
508
519
|
if (v === null || v === undefined) {
|
|
520
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
509
521
|
const o = (acc.$unset = acc.$unset ?? {}) as Record<string, unknown>;
|
|
510
522
|
o[k] = v;
|
|
511
523
|
} else {
|
|
524
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
512
525
|
const o = (acc.$set = acc.$set ?? {}) as Record<string, unknown>;
|
|
513
526
|
o[k] = v;
|
|
514
527
|
}
|
|
@@ -525,6 +538,7 @@ export class MongoModelService implements
|
|
|
525
538
|
const col = await this.getStore(cls);
|
|
526
539
|
const pipeline: object[] = [{
|
|
527
540
|
$group: {
|
|
541
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
528
542
|
_id: `$${field as string}`,
|
|
529
543
|
count: {
|
|
530
544
|
$sum: 1
|
|
@@ -540,6 +554,7 @@ export class MongoModelService implements
|
|
|
540
554
|
|
|
541
555
|
pipeline.unshift({ $match: q });
|
|
542
556
|
|
|
557
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
543
558
|
const result = (await col.aggregate(pipeline).toArray()) as { _id: mongo.ObjectId, count: number }[];
|
|
544
559
|
|
|
545
560
|
return result.map(val => ({
|
package/support/service.mongo.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type {
|
|
1
|
+
import { Env } from '@travetto/base';
|
|
2
|
+
import type { CommandService } from '@travetto/command';
|
|
3
3
|
|
|
4
|
-
const version =
|
|
4
|
+
const version = Env.get('MONGO_VERSION', '6.0');
|
|
5
5
|
|
|
6
|
-
export const service:
|
|
6
|
+
export const service: CommandService = {
|
|
7
7
|
name: 'mongodb',
|
|
8
8
|
version,
|
|
9
9
|
port: 27017,
|