@travetto/model-mongo 4.0.0-rc.3 → 4.0.0-rc.5
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/package.json +5 -5
- package/src/internal/util.ts +10 -10
- package/src/service.ts +22 -19
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/model-mongo",
|
|
3
|
-
"version": "4.0.0-rc.
|
|
3
|
+
"version": "4.0.0-rc.5",
|
|
4
4
|
"description": "Mongo backing for the travetto model module.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mongo",
|
|
@@ -25,13 +25,13 @@
|
|
|
25
25
|
"directory": "module/model-mongo"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@travetto/config": "^4.0.0-rc.
|
|
29
|
-
"@travetto/model": "^4.0.0-rc.
|
|
30
|
-
"@travetto/model-query": "^4.0.0-rc.
|
|
28
|
+
"@travetto/config": "^4.0.0-rc.5",
|
|
29
|
+
"@travetto/model": "^4.0.0-rc.5",
|
|
30
|
+
"@travetto/model-query": "^4.0.0-rc.5",
|
|
31
31
|
"mongodb": "^6.3.0"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"@travetto/command": "^4.0.0-rc.
|
|
34
|
+
"@travetto/command": "^4.0.0-rc.5"
|
|
35
35
|
},
|
|
36
36
|
"peerDependenciesMeta": {
|
|
37
37
|
"@travetto/command": {
|
package/src/internal/util.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Binary, ObjectId } from 'mongodb';
|
|
2
2
|
|
|
3
3
|
import { Class, ObjectUtil } from '@travetto/base';
|
|
4
4
|
import { DistanceUnit, ModelQuery, Query, WhereClause } from '@travetto/model-query';
|
|
@@ -18,7 +18,7 @@ const RADIANS_TO: Record<DistanceUnit, number> = {
|
|
|
18
18
|
rad: 1
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
export type WithId<T> = T & { _id?:
|
|
21
|
+
export type WithId<T> = T & { _id?: Binary };
|
|
22
22
|
const isWithId = <T extends ModelType>(o: T): o is WithId<T> => o && '_id' in o;
|
|
23
23
|
|
|
24
24
|
/**
|
|
@@ -41,14 +41,14 @@ export class MongoUtil {
|
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
static uuid(val: string):
|
|
45
|
-
return new
|
|
44
|
+
static uuid(val: string): Binary {
|
|
45
|
+
return new Binary(Buffer.from(val.replace(/-/g, ''), 'hex'), Binary.SUBTYPE_UUID);
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
static idToString(id: string |
|
|
48
|
+
static idToString(id: string | ObjectId | Binary): string {
|
|
49
49
|
if (typeof id === 'string') {
|
|
50
50
|
return id;
|
|
51
|
-
} else if (id instanceof
|
|
51
|
+
} else if (id instanceof ObjectId) {
|
|
52
52
|
return id.toHexString();
|
|
53
53
|
} else {
|
|
54
54
|
return Buffer.from(id.buffer).toString('hex');
|
|
@@ -107,9 +107,9 @@ export class MongoUtil {
|
|
|
107
107
|
/**
|
|
108
108
|
* Convert ids from '_id' to 'id'
|
|
109
109
|
*/
|
|
110
|
-
static replaceId(v: Record<string, unknown>): Record<string,
|
|
111
|
-
static replaceId(v: string[]):
|
|
112
|
-
static replaceId(v: string):
|
|
110
|
+
static replaceId(v: Record<string, unknown>): Record<string, Binary>;
|
|
111
|
+
static replaceId(v: string[]): Binary[];
|
|
112
|
+
static replaceId(v: string): Binary;
|
|
113
113
|
static replaceId(v: unknown): undefined;
|
|
114
114
|
static replaceId(v: string | string[] | Record<string, unknown> | unknown): unknown {
|
|
115
115
|
if (typeof v === 'string') {
|
|
@@ -117,7 +117,7 @@ export class MongoUtil {
|
|
|
117
117
|
} else if (Array.isArray(v)) {
|
|
118
118
|
return v.map(x => this.replaceId(x));
|
|
119
119
|
} else if (ObjectUtil.isPlainObject(v)) {
|
|
120
|
-
const out: Record<string,
|
|
120
|
+
const out: Record<string, Binary> = {};
|
|
121
121
|
for (const [k, el] of Object.entries(v)) {
|
|
122
122
|
const found = this.replaceId(el);
|
|
123
123
|
if (found) {
|
package/src/service.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
// Wildcard import needed here due to packaging issues
|
|
2
|
-
import
|
|
2
|
+
import {
|
|
3
|
+
type Db, GridFSBucket, MongoClient, type Sort, type CreateIndexesOptions,
|
|
4
|
+
type GridFSFile, type IndexSpecification, type Collection, type ObjectId, type Filter, type Document
|
|
5
|
+
} from 'mongodb';
|
|
3
6
|
import { Readable } from 'node:stream';
|
|
4
7
|
import { pipeline } from 'node:stream/promises';
|
|
5
8
|
|
|
@@ -37,11 +40,11 @@ import { MongoModelConfig } from './config';
|
|
|
37
40
|
const IdxFieldsⲐ = Symbol.for('@travetto/model-mongo:idx');
|
|
38
41
|
|
|
39
42
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
40
|
-
const asFielded = <T extends ModelType>(cfg: IndexConfig<T>): { [IdxFieldsⲐ]:
|
|
43
|
+
const asFielded = <T extends ModelType>(cfg: IndexConfig<T>): { [IdxFieldsⲐ]: Sort } => (cfg as unknown as { [IdxFieldsⲐ]: Sort });
|
|
41
44
|
|
|
42
|
-
type IdxCfg =
|
|
45
|
+
type IdxCfg = CreateIndexesOptions;
|
|
43
46
|
|
|
44
|
-
type StreamRaw =
|
|
47
|
+
type StreamRaw = GridFSFile & { metadata: StreamMeta };
|
|
45
48
|
|
|
46
49
|
/**
|
|
47
50
|
* Mongo-based model source
|
|
@@ -55,9 +58,9 @@ export class MongoModelService implements
|
|
|
55
58
|
ModelQuerySuggestSupport, ModelExpirySupport {
|
|
56
59
|
|
|
57
60
|
idSource = ModelCrudUtil.uuidSource();
|
|
58
|
-
client:
|
|
59
|
-
#db:
|
|
60
|
-
#bucket:
|
|
61
|
+
client: MongoClient;
|
|
62
|
+
#db: Db;
|
|
63
|
+
#bucket: GridFSBucket;
|
|
61
64
|
|
|
62
65
|
constructor(public readonly config: MongoModelConfig) { }
|
|
63
66
|
|
|
@@ -73,9 +76,9 @@ export class MongoModelService implements
|
|
|
73
76
|
}
|
|
74
77
|
|
|
75
78
|
async postConstruct(): Promise<void> {
|
|
76
|
-
this.client = await
|
|
79
|
+
this.client = await MongoClient.connect(this.config.url, this.config.options);
|
|
77
80
|
this.#db = this.client.db(this.config.namespace);
|
|
78
|
-
this.#bucket = new
|
|
81
|
+
this.#bucket = new GridFSBucket(this.#db, {
|
|
79
82
|
bucketName: STREAMS,
|
|
80
83
|
writeConcern: { w: 1 }
|
|
81
84
|
});
|
|
@@ -95,11 +98,11 @@ export class MongoModelService implements
|
|
|
95
98
|
await this.#db.dropDatabase();
|
|
96
99
|
}
|
|
97
100
|
|
|
98
|
-
getGeoIndices<T extends ModelType>(cls: Class<T>, path: FieldConfig[] = [], root = cls):
|
|
101
|
+
getGeoIndices<T extends ModelType>(cls: Class<T>, path: FieldConfig[] = [], root = cls): IndexSpecification[] {
|
|
99
102
|
const fields = SchemaRegistry.has(cls) ?
|
|
100
103
|
Object.values(SchemaRegistry.get(cls).views[AllViewⲐ].schema) :
|
|
101
104
|
[];
|
|
102
|
-
const out:
|
|
105
|
+
const out: IndexSpecification[] = [];
|
|
103
106
|
for (const field of fields) {
|
|
104
107
|
if (SchemaRegistry.has(field.type)) {
|
|
105
108
|
// Recurse
|
|
@@ -113,18 +116,18 @@ export class MongoModelService implements
|
|
|
113
116
|
return out;
|
|
114
117
|
}
|
|
115
118
|
|
|
116
|
-
getIndicies<T extends ModelType>(cls: Class<T>): ([
|
|
119
|
+
getIndicies<T extends ModelType>(cls: Class<T>): ([IndexSpecification] | [IndexSpecification, IdxCfg])[] {
|
|
117
120
|
const indices = ModelRegistry.get(cls).indices ?? [];
|
|
118
121
|
return [
|
|
119
|
-
...indices.map((idx): [
|
|
122
|
+
...indices.map((idx): [IndexSpecification, IdxCfg] => {
|
|
120
123
|
const combined = asFielded(idx)[IdxFieldsⲐ] ??= Object.assign({}, ...idx.fields.map(x => MongoUtil.toIndex(x)));
|
|
121
124
|
return [
|
|
122
125
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
123
|
-
combined as
|
|
126
|
+
combined as IndexSpecification,
|
|
124
127
|
(idx.type === 'unique' ? { unique: true } : {})
|
|
125
128
|
];
|
|
126
129
|
}),
|
|
127
|
-
...this.getGeoIndices(cls).map((x): [
|
|
130
|
+
...this.getGeoIndices(cls).map((x): [IndexSpecification] => [x])
|
|
128
131
|
];
|
|
129
132
|
}
|
|
130
133
|
|
|
@@ -161,7 +164,7 @@ export class MongoModelService implements
|
|
|
161
164
|
/**
|
|
162
165
|
* Get mongo collection
|
|
163
166
|
*/
|
|
164
|
-
async getStore<T extends ModelType>(cls: Class<T>): Promise<
|
|
167
|
+
async getStore<T extends ModelType>(cls: Class<T>): Promise<Collection> {
|
|
165
168
|
return this.#db.collection(ModelRegistry.getStore(cls).toLowerCase().replace(/[^A-Za-z0-9_]+/g, '_'));
|
|
166
169
|
}
|
|
167
170
|
|
|
@@ -373,7 +376,7 @@ export class MongoModelService implements
|
|
|
373
376
|
}
|
|
374
377
|
}
|
|
375
378
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
376
|
-
for (const [index, _id] of TypedObject.entries(res.upsertedIds) as [number,
|
|
379
|
+
for (const [index, _id] of TypedObject.entries(res.upsertedIds) as [number, ObjectId][]) {
|
|
377
380
|
out.insertedIds.set(+index, MongoUtil.idToString(_id));
|
|
378
381
|
}
|
|
379
382
|
|
|
@@ -453,7 +456,7 @@ export class MongoModelService implements
|
|
|
453
456
|
cls,
|
|
454
457
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
455
458
|
ModelIndexedUtil.projectIndex(cls, idx, body, { emptySortValue: { $exists: true } }) as WhereClause<T>
|
|
456
|
-
) as
|
|
459
|
+
) as Filter<Document>;
|
|
457
460
|
|
|
458
461
|
const cursor = store.find(where, { timeout: true }).batchSize(100).sort(asFielded(idxCfg)[IdxFieldsⲐ]);
|
|
459
462
|
|
|
@@ -571,7 +574,7 @@ export class MongoModelService implements
|
|
|
571
574
|
aggs.unshift({ $match: q });
|
|
572
575
|
|
|
573
576
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
574
|
-
const result = (await col.aggregate(aggs).toArray()) as { _id:
|
|
577
|
+
const result = (await col.aggregate(aggs).toArray()) as { _id: ObjectId, count: number }[];
|
|
575
578
|
|
|
576
579
|
return result.map(val => ({
|
|
577
580
|
key: MongoUtil.idToString(val._id),
|