@travetto/model-mongo 6.0.0-rc.0 → 6.0.0-rc.2

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
@@ -16,15 +16,15 @@ yarn add @travetto/model-mongo
16
16
  This module provides an [mongodb](https://mongodb.com)-based implementation for the [Data Modeling Support](https://github.com/travetto/travetto/tree/main/module/model#readme "Datastore abstraction for core operations."). This source allows the [Data Modeling Support](https://github.com/travetto/travetto/tree/main/module/model#readme "Datastore abstraction for core operations.") module to read, write and query against [mongodb](https://mongodb.com).. Given the dynamic nature of [mongodb](https://mongodb.com), during development when models are modified, nothing needs to be done to adapt to the latest schema.
17
17
 
18
18
  Supported features:
19
- * [CRUD](https://github.com/travetto/travetto/tree/main/module/model/src/service/crud.ts#L11)
20
- * [Expiry](https://github.com/travetto/travetto/tree/main/module/model/src/service/expiry.ts#L11)
21
- * [Bulk](https://github.com/travetto/travetto/tree/main/module/model/src/service/bulk.ts#L19)
22
- * [Indexed](https://github.com/travetto/travetto/tree/main/module/model/src/service/indexed.ts#L12)
23
- * [Blob](https://github.com/travetto/travetto/tree/main/module/model/src/service/blob.ts#L8)
24
- * [Query Crud](https://github.com/travetto/travetto/tree/main/module/model-query/src/service/crud.ts#L11)
25
- * [Facet](https://github.com/travetto/travetto/tree/main/module/model-query/src/service/facet.ts#L12)
26
- * [Query](https://github.com/travetto/travetto/tree/main/module/model-query/src/service/query.ts#L10)
27
- * [Suggest](https://github.com/travetto/travetto/tree/main/module/model-query/src/service/suggest.ts#L12)
19
+ * [CRUD](https://github.com/travetto/travetto/tree/main/module/model/src/types/crud.ts#L11)
20
+ * [Expiry](https://github.com/travetto/travetto/tree/main/module/model/src/types/expiry.ts#L10)
21
+ * [Bulk](https://github.com/travetto/travetto/tree/main/module/model/src/types/bulk.ts#L64)
22
+ * [Indexed](https://github.com/travetto/travetto/tree/main/module/model/src/types/indexed.ts#L11)
23
+ * [Blob](https://github.com/travetto/travetto/tree/main/module/model/src/types/blob.ts#L8)
24
+ * [Query Crud](https://github.com/travetto/travetto/tree/main/module/model-query/src/types/crud.ts#L11)
25
+ * [Facet](https://github.com/travetto/travetto/tree/main/module/model-query/src/types/facet.ts#L14)
26
+ * [Query](https://github.com/travetto/travetto/tree/main/module/model-query/src/types/query.ts#L10)
27
+ * [Suggest](https://github.com/travetto/travetto/tree/main/module/model-query/src/types/suggest.ts#L12)
28
28
  Out of the box, by installing the module, everything should be wired up by default.If you need to customize any aspect of the source or config, you can override and register it with the [Dependency Injection](https://github.com/travetto/travetto/tree/main/module/di#readme "Dependency registration/management and injection support.") module.
29
29
 
30
30
  **Code: Wiring up a custom Model Source**
@@ -46,15 +46,6 @@ where the [MongoModelConfig](https://github.com/travetto/travetto/tree/main/modu
46
46
 
47
47
  **Code: Structure of MongoModelConfig**
48
48
  ```typescript
49
- import type mongo from 'mongodb';
50
-
51
- import { TimeSpan, TimeUtil, RuntimeResources, Runtime } from '@travetto/runtime';
52
- import { Config } from '@travetto/config';
53
- import { Field } from '@travetto/schema';
54
-
55
- /**
56
- * Mongo model config
57
- */
58
49
  @Config('model.mongo')
59
50
  export class MongoModelConfig {
60
51
  /**
package/__index__.ts CHANGED
@@ -1,2 +1,2 @@
1
- export * from './src/service';
2
- export * from './src/config';
1
+ export * from './src/service.ts';
2
+ export * from './src/config.ts';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/model-mongo",
3
- "version": "6.0.0-rc.0",
3
+ "version": "6.0.0-rc.2",
4
4
  "description": "Mongo backing for the travetto model module.",
5
5
  "keywords": [
6
6
  "mongo",
@@ -25,11 +25,11 @@
25
25
  "directory": "module/model-mongo"
26
26
  },
27
27
  "dependencies": {
28
- "@travetto/cli": "^6.0.0-rc.0",
29
- "@travetto/config": "^6.0.0-rc.0",
30
- "@travetto/model": "^6.0.0-rc.0",
31
- "@travetto/model-query": "^6.0.0-rc.0",
32
- "mongodb": "^6.12.0"
28
+ "@travetto/cli": "^6.0.0-rc.2",
29
+ "@travetto/config": "^6.0.0-rc.2",
30
+ "@travetto/model": "^6.0.0-rc.2",
31
+ "@travetto/model-query": "^6.0.0-rc.2",
32
+ "mongodb": "^6.16.0"
33
33
  },
34
34
  "travetto": {
35
35
  "displayName": "MongoDB Model Support"
@@ -2,14 +2,12 @@ import {
2
2
  Binary, type CreateIndexesOptions, type Filter, type FindCursor, type IndexDirection, ObjectId, type WithId as MongoWithId
3
3
  } from 'mongodb';
4
4
 
5
- import { AppError, castTo, Class, TypedObject } from '@travetto/runtime';
6
- import type { DistanceUnit, PageableModelQuery, WhereClause } from '@travetto/model-query';
5
+ import { AppError, castTo, Class, toConcrete, TypedObject } from '@travetto/runtime';
6
+ import { type DistanceUnit, type PageableModelQuery, type WhereClause, ModelQueryUtil } from '@travetto/model-query';
7
7
  import type { ModelType, IndexField, IndexConfig } from '@travetto/model';
8
- import { DataUtil, SchemaRegistry } from '@travetto/schema';
8
+ import { DataUtil, SchemaRegistry, type Point } from '@travetto/schema';
9
9
 
10
- import { ModelQueryUtil } from '@travetto/model-query/src/internal/service/query';
11
- import { AllViewSymbol } from '@travetto/schema/src/internal/types';
12
- import { PointImpl } from '@travetto/model-query/src/internal/model/point';
10
+ const PointImpl = toConcrete<Point>();
13
11
 
14
12
  type IdxCfg = CreateIndexesOptions;
15
13
 
@@ -89,7 +87,7 @@ export class MongoUtil {
89
87
  for (const key of keys) {
90
88
  const subpath = `${path}${key}`;
91
89
  const v: Record<string, unknown> = castTo(sub[key]);
92
- const subField = schema?.views[AllViewSymbol].schema[key];
90
+ const subField = schema?.totalView.schema[key];
93
91
 
94
92
  const isPlain = v && DataUtil.isPlainObject(v);
95
93
  const firstKey = isPlain ? Object.keys(v)[0] : '';
package/src/service.ts CHANGED
@@ -9,12 +9,14 @@ import {
9
9
  import {
10
10
  ModelRegistry, ModelType, OptionalId, ModelCrudSupport, ModelStorageSupport,
11
11
  ModelExpirySupport, ModelBulkSupport, ModelIndexedSupport, BulkOp, BulkResponse,
12
- NotFoundError, ExistsError, ModelBlobSupport
12
+ NotFoundError, ExistsError, ModelBlobSupport,
13
+ ModelCrudUtil, ModelIndexedUtil, ModelStorageUtil, ModelExpiryUtil, ModelBulkUtil, ModelBlobUtil,
13
14
  } from '@travetto/model';
14
15
  import {
15
16
  ModelQuery, ModelQueryCrudSupport, ModelQueryFacetSupport, ModelQuerySupport,
16
17
  PageableModelQuery, ValidStringFields, WhereClause, ModelQuerySuggestSupport,
17
- QueryVerifier
18
+ QueryVerifier, ModelQueryUtil, ModelQuerySuggestUtil, ModelQueryCrudUtil,
19
+ ModelQueryFacet,
18
20
  } from '@travetto/model-query';
19
21
 
20
22
  import {
@@ -23,25 +25,17 @@ import {
23
25
  } from '@travetto/runtime';
24
26
  import { Injectable } from '@travetto/di';
25
27
 
26
- import { ModelCrudUtil } from '@travetto/model/src/internal/service/crud';
27
- import { ModelIndexedUtil } from '@travetto/model/src/internal/service/indexed';
28
- import { ModelStorageUtil } from '@travetto/model/src/internal/service/storage';
29
- import { ModelQueryUtil } from '@travetto/model-query/src/internal/service/query';
30
- import { ModelQuerySuggestUtil } from '@travetto/model-query/src/internal/service/suggest';
31
- import { ModelQueryExpiryUtil } from '@travetto/model-query/src/internal/service/expiry';
32
- import { ModelExpiryUtil } from '@travetto/model/src/internal/service/expiry';
33
- import { ModelBulkUtil } from '@travetto/model/src/internal/service/bulk';
34
- import { MODEL_BLOB, ModelBlobNamespace, ModelBlobUtil } from '@travetto/model/src/internal/service/blob';
28
+ import { MongoUtil, PlainIdx, WithId } from './internal/util.ts';
29
+ import { MongoModelConfig } from './config.ts';
35
30
 
36
- import { MongoUtil, PlainIdx, WithId } from './internal/util';
37
- import { MongoModelConfig } from './config';
38
-
39
- const ListIndexSymbol = Symbol.for('@travetto/mongo-model:list-index');
31
+ const ListIndexSymbol = Symbol();
40
32
 
41
33
  type BlobRaw = GridFSFile & { metadata?: BlobMeta };
42
34
 
43
35
  type MongoTextSearch = RootFilterOperators<unknown>['$text'];
44
36
 
37
+ export const ModelBlobNamespace = '__blobs';
38
+
45
39
  /**
46
40
  * Mongo-based model source
47
41
  */
@@ -152,12 +146,12 @@ export class MongoModelService implements
152
146
  }
153
147
 
154
148
  async truncateModel<T extends ModelType>(cls: Class<T>): Promise<void> {
155
- if (cls === MODEL_BLOB) {
156
- await this.#bucket.drop().catch(() => { });
157
- } else {
158
- const col = await this.getStore(cls);
159
- await col.deleteMany({});
160
- }
149
+ const col = await this.getStore(cls);
150
+ await col.deleteMany({});
151
+ }
152
+
153
+ async truncateBlob(): Promise<void> {
154
+ await this.#bucket.drop().catch(() => { });
161
155
  }
162
156
 
163
157
  /**
@@ -172,9 +166,9 @@ export class MongoModelService implements
172
166
  const store = await this.getStore(cls);
173
167
  const result = await store.findOne(this.getIdFilter(cls, id), {});
174
168
  if (result) {
175
- const res = await this.postLoad(cls, result);
176
- if (res) {
177
- return res;
169
+ const finalized = await this.postLoad(cls, result);
170
+ if (finalized) {
171
+ return finalized;
178
172
  }
179
173
  }
180
174
  throw new NotFoundError(cls, id);
@@ -196,8 +190,8 @@ export class MongoModelService implements
196
190
  item = await ModelCrudUtil.preStore(cls, item, this);
197
191
  const id = this.preUpdate(item);
198
192
  const store = await this.getStore(cls);
199
- const res = await store.replaceOne(this.getIdFilter(cls, id), item);
200
- if (res.matchedCount === 0) {
193
+ const result = await store.replaceOne(this.getIdFilter(cls, id), item);
194
+ if (result.matchedCount === 0) {
201
195
  throw new NotFoundError(cls, id);
202
196
  }
203
197
  return this.postUpdate(item, id);
@@ -243,13 +237,13 @@ export class MongoModelService implements
243
237
 
244
238
  const id = item.id;
245
239
 
246
- const res = await store.findOneAndUpdate(
240
+ const result = await store.findOneAndUpdate(
247
241
  this.getIdFilter(cls, id),
248
242
  operation,
249
243
  { returnDocument: 'after', includeResultMetadata: true }
250
244
  );
251
245
 
252
- if (!res.value) {
246
+ if (!result.value) {
253
247
  throw new NotFoundError(cls, id);
254
248
  }
255
249
 
@@ -305,8 +299,8 @@ export class MongoModelService implements
305
299
  }
306
300
 
307
301
  async getBlobMeta(location: string): Promise<BlobMeta> {
308
- const res = await this.#db.collection<{ metadata: BlobMeta }>(`${ModelBlobNamespace}.files`).findOne({ filename: location });
309
- return res!.metadata;
302
+ const result = await this.#db.collection<{ metadata: BlobMeta }>(`${ModelBlobNamespace}.files`).findOne({ filename: location });
303
+ return result!.metadata;
310
304
  }
311
305
 
312
306
  async deleteBlob(location: string): Promise<void> {
@@ -360,7 +354,7 @@ export class MongoModelService implements
360
354
  }
361
355
  }
362
356
 
363
- const res = await bulk.execute({});
357
+ const result = await bulk.execute({});
364
358
 
365
359
  // Restore all ids
366
360
  for (const op of operations) {
@@ -370,19 +364,19 @@ export class MongoModelService implements
370
364
  }
371
365
  }
372
366
 
373
- for (const [index, _id] of TypedObject.entries<Record<string, string>>(res.upsertedIds)) {
367
+ for (const [index, _id] of TypedObject.entries<Record<string, string>>(result.upsertedIds)) {
374
368
  out.insertedIds.set(+index, MongoUtil.idToString(_id));
375
369
  }
376
370
 
377
371
  if (out.counts) {
378
- out.counts.delete = res.deletedCount;
372
+ out.counts.delete = result.deletedCount;
379
373
  out.counts.update = operations.filter(x => x.update).length;
380
- out.counts.insert = res.insertedCount;
374
+ out.counts.insert = result.insertedCount;
381
375
  out.counts.upsert = operations.filter(x => x.upsert).length;
382
376
  }
383
377
 
384
- if (res.hasWriteErrors()) {
385
- out.errors = res.getWriteErrors();
378
+ if (result.hasWriteErrors()) {
379
+ out.errors = result.getWriteErrors();
386
380
  for (const err of out.errors) {
387
381
  const op = operations[err.index];
388
382
  const k = TypedObject.keys(op)[0];
@@ -396,7 +390,7 @@ export class MongoModelService implements
396
390
 
397
391
  // Expiry
398
392
  deleteExpired<T extends ModelType>(cls: Class<T>): Promise<number> {
399
- return ModelQueryExpiryUtil.deleteExpired(this, cls);
393
+ return ModelQueryCrudUtil.deleteExpired(this, cls);
400
394
  }
401
395
 
402
396
  // Indexed
@@ -486,8 +480,8 @@ export class MongoModelService implements
486
480
  where.id = id;
487
481
 
488
482
  const filter = MongoUtil.extractWhereFilter(cls, where);
489
- const res = await col.replaceOne(filter, item);
490
- if (res.matchedCount === 0) {
483
+ const result = await col.replaceOne(filter, item);
484
+ if (result.matchedCount === 0) {
491
485
  throw new NotFoundError(cls, id);
492
486
  }
493
487
  return this.postUpdate(item, id);
@@ -498,8 +492,8 @@ export class MongoModelService implements
498
492
 
499
493
  const col = await this.getStore(cls);
500
494
  const filter = MongoUtil.extractWhereFilter(cls, query.where, false);
501
- const res = await col.deleteMany(filter);
502
- return res.deletedCount ?? 0;
495
+ const result = await col.deleteMany(filter);
496
+ return result.deletedCount ?? 0;
503
497
  }
504
498
 
505
499
  async updatePartialByQuery<T extends ModelType>(cls: Class<T>, query: ModelQuery<T>, data: Partial<T>): Promise<number> {
@@ -519,12 +513,12 @@ export class MongoModelService implements
519
513
  }, {});
520
514
 
521
515
  const filter = MongoUtil.extractWhereFilter(cls, query.where);
522
- const res = await col.updateMany(filter, castTo(final));
523
- return res.matchedCount;
516
+ const result = await col.updateMany(filter, castTo(final));
517
+ return result.matchedCount;
524
518
  }
525
519
 
526
520
  // Facet
527
- async facet<T extends ModelType>(cls: Class<T>, field: ValidStringFields<T>, query?: ModelQuery<T>): Promise<{ key: string, count: number }[]> {
521
+ async facet<T extends ModelType>(cls: Class<T>, field: ValidStringFields<T>, query?: ModelQuery<T>): Promise<ModelQueryFacet[]> {
528
522
  await QueryVerifier.verify(cls, query);
529
523
 
530
524
  const col = await this.getStore(cls);
@@ -552,10 +546,12 @@ export class MongoModelService implements
552
546
 
553
547
  const result = await col.aggregate<{ _id: ObjectId, count: number }>(aggregations).toArray();
554
548
 
555
- return result.map(val => ({
556
- key: MongoUtil.idToString(val._id),
557
- count: val.count
558
- })).sort((a, b) => b.count - a.count);
549
+ return result
550
+ .map(val => ({
551
+ key: MongoUtil.idToString(val._id),
552
+ count: val.count
553
+ }))
554
+ .toSorted((a, b) => b.count - a.count);
559
555
  }
560
556
 
561
557
  // Suggest