@travetto/model-mongo 7.0.0-rc.0 → 7.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
@@ -37,8 +37,8 @@ export class Init {
37
37
  @InjectableFactory({
38
38
  primary: true
39
39
  })
40
- static getModelSource(conf: MongoModelConfig) {
41
- return new MongoModelService(conf);
40
+ static getModelSource(config: MongoModelConfig) {
41
+ return new MongoModelService(config);
42
42
  }
43
43
  }
44
44
  ```
@@ -107,11 +107,11 @@ export class MongoModelConfig {
107
107
  * Load all the ssl certs as needed
108
108
  */
109
109
  async postConstruct(): Promise<void> {
110
- const resolve = (file: string): Promise<string> => RuntimeResources.resolve(file).then(v => v, () => file);
110
+ const resolve = (file: string): Promise<string> => RuntimeResources.resolve(file).catch(() => file);
111
111
 
112
112
  if (this.connectionString) {
113
113
  const details = new URL(this.connectionString);
114
- this.hosts ??= details.hostname.split(',').filter(x => !!x);
114
+ this.hosts ??= details.hostname.split(',').filter(host => !!host);
115
115
  this.srvRecord ??= details.protocol === 'mongodb+srv:';
116
116
  this.namespace ??= details.pathname.replace('/', '');
117
117
  Object.assign(this.options, Object.fromEntries(details.searchParams.entries()));
@@ -131,24 +131,24 @@ export class MongoModelConfig {
131
131
  this.hosts = ['localhost'];
132
132
  }
133
133
 
134
- const opts = this.options;
135
- if (opts.ssl) {
136
- if (opts.cert) {
137
- opts.cert = await Promise.all([opts.cert].flat(2).map(f => Buffer.isBuffer(f) ? f : resolve(f)));
134
+ const options = this.options;
135
+ if (options.ssl) {
136
+ if (options.cert) {
137
+ options.cert = await Promise.all([options.cert].flat(2).map(data => Buffer.isBuffer(data) ? data : resolve(data)));
138
138
  }
139
- if (opts.tlsCertificateKeyFile) {
140
- opts.tlsCertificateKeyFile = await resolve(opts.tlsCertificateKeyFile);
139
+ if (options.tlsCertificateKeyFile) {
140
+ options.tlsCertificateKeyFile = await resolve(options.tlsCertificateKeyFile);
141
141
  }
142
- if (opts.tlsCAFile) {
143
- opts.tlsCAFile = await resolve(opts.tlsCAFile);
142
+ if (options.tlsCAFile) {
143
+ options.tlsCAFile = await resolve(options.tlsCAFile);
144
144
  }
145
- if (opts.tlsCRLFile) {
146
- opts.tlsCRLFile = await resolve(opts.tlsCRLFile);
145
+ if (options.tlsCRLFile) {
146
+ options.tlsCRLFile = await resolve(options.tlsCRLFile);
147
147
  }
148
148
  }
149
149
 
150
150
  if (!Runtime.production) {
151
- opts.waitQueueTimeoutMS ??= TimeUtil.asMillis(1, 'd'); // Wait a day in dev mode
151
+ options.waitQueueTimeoutMS ??= TimeUtil.asMillis(1, 'd'); // Wait a day in dev mode
152
152
  }
153
153
  }
154
154
 
@@ -157,14 +157,14 @@ export class MongoModelConfig {
157
157
  */
158
158
  get url(): string {
159
159
  const hosts = this.hosts!
160
- .map(h => (this.srvRecord || h.includes(':')) ? h : `${h}:${this.port ?? 27017}`)
160
+ .map(host => (this.srvRecord || host.includes(':')) ? host : `${host}:${this.port ?? 27017}`)
161
161
  .join(',');
162
- const opts = Object.entries(this.options).map(([k, v]) => `${k}=${v}`).join('&');
162
+ const optionString = Object.entries(this.options).map(([key, value]) => `${key}=${value}`).join('&');
163
163
  let creds = '';
164
164
  if (this.username) {
165
- creds = `${[this.username, this.password].filter(x => !!x).join(':')}@`;
165
+ creds = `${[this.username, this.password].filter(part => !!part).join(':')}@`;
166
166
  }
167
- const url = `mongodb${this.srvRecord ? '+srv' : ''}://${creds}${hosts}/${this.namespace}?${opts}`;
167
+ const url = `mongodb${this.srvRecord ? '+srv' : ''}://${creds}${hosts}/${this.namespace}?${optionString}`;
168
168
  return url;
169
169
  }
170
170
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/model-mongo",
3
- "version": "7.0.0-rc.0",
3
+ "version": "7.0.0-rc.2",
4
4
  "description": "Mongo backing for the travetto model module.",
5
5
  "keywords": [
6
6
  "mongo",
@@ -25,10 +25,10 @@
25
25
  "directory": "module/model-mongo"
26
26
  },
27
27
  "dependencies": {
28
- "@travetto/cli": "^7.0.0-rc.0",
29
- "@travetto/config": "^7.0.0-rc.0",
30
- "@travetto/model": "^7.0.0-rc.0",
31
- "@travetto/model-query": "^7.0.0-rc.0",
28
+ "@travetto/cli": "^7.0.0-rc.2",
29
+ "@travetto/config": "^7.0.0-rc.2",
30
+ "@travetto/model": "^7.0.0-rc.2",
31
+ "@travetto/model-query": "^7.0.0-rc.2",
32
32
  "mongodb": "^7.0.0"
33
33
  },
34
34
  "travetto": {
package/src/config.ts CHANGED
@@ -66,11 +66,11 @@ export class MongoModelConfig {
66
66
  * Load all the ssl certs as needed
67
67
  */
68
68
  async postConstruct(): Promise<void> {
69
- const resolve = (file: string): Promise<string> => RuntimeResources.resolve(file).then(v => v, () => file);
69
+ const resolve = (file: string): Promise<string> => RuntimeResources.resolve(file).catch(() => file);
70
70
 
71
71
  if (this.connectionString) {
72
72
  const details = new URL(this.connectionString);
73
- this.hosts ??= details.hostname.split(',').filter(x => !!x);
73
+ this.hosts ??= details.hostname.split(',').filter(host => !!host);
74
74
  this.srvRecord ??= details.protocol === 'mongodb+srv:';
75
75
  this.namespace ??= details.pathname.replace('/', '');
76
76
  Object.assign(this.options, Object.fromEntries(details.searchParams.entries()));
@@ -90,24 +90,24 @@ export class MongoModelConfig {
90
90
  this.hosts = ['localhost'];
91
91
  }
92
92
 
93
- const opts = this.options;
94
- if (opts.ssl) {
95
- if (opts.cert) {
96
- opts.cert = await Promise.all([opts.cert].flat(2).map(f => Buffer.isBuffer(f) ? f : resolve(f)));
93
+ const options = this.options;
94
+ if (options.ssl) {
95
+ if (options.cert) {
96
+ options.cert = await Promise.all([options.cert].flat(2).map(data => Buffer.isBuffer(data) ? data : resolve(data)));
97
97
  }
98
- if (opts.tlsCertificateKeyFile) {
99
- opts.tlsCertificateKeyFile = await resolve(opts.tlsCertificateKeyFile);
98
+ if (options.tlsCertificateKeyFile) {
99
+ options.tlsCertificateKeyFile = await resolve(options.tlsCertificateKeyFile);
100
100
  }
101
- if (opts.tlsCAFile) {
102
- opts.tlsCAFile = await resolve(opts.tlsCAFile);
101
+ if (options.tlsCAFile) {
102
+ options.tlsCAFile = await resolve(options.tlsCAFile);
103
103
  }
104
- if (opts.tlsCRLFile) {
105
- opts.tlsCRLFile = await resolve(opts.tlsCRLFile);
104
+ if (options.tlsCRLFile) {
105
+ options.tlsCRLFile = await resolve(options.tlsCRLFile);
106
106
  }
107
107
  }
108
108
 
109
109
  if (!Runtime.production) {
110
- opts.waitQueueTimeoutMS ??= TimeUtil.asMillis(1, 'd'); // Wait a day in dev mode
110
+ options.waitQueueTimeoutMS ??= TimeUtil.asMillis(1, 'd'); // Wait a day in dev mode
111
111
  }
112
112
  }
113
113
 
@@ -116,14 +116,14 @@ export class MongoModelConfig {
116
116
  */
117
117
  get url(): string {
118
118
  const hosts = this.hosts!
119
- .map(h => (this.srvRecord || h.includes(':')) ? h : `${h}:${this.port ?? 27017}`)
119
+ .map(host => (this.srvRecord || host.includes(':')) ? host : `${host}:${this.port ?? 27017}`)
120
120
  .join(',');
121
- const opts = Object.entries(this.options).map(([k, v]) => `${k}=${v}`).join('&');
121
+ const optionString = Object.entries(this.options).map(([key, value]) => `${key}=${value}`).join('&');
122
122
  let creds = '';
123
123
  if (this.username) {
124
- creds = `${[this.username, this.password].filter(x => !!x).join(':')}@`;
124
+ creds = `${[this.username, this.password].filter(part => !!part).join(':')}@`;
125
125
  }
126
- const url = `mongodb${this.srvRecord ? '+srv' : ''}://${creds}${hosts}/${this.namespace}?${opts}`;
126
+ const url = `mongodb${this.srvRecord ? '+srv' : ''}://${creds}${hosts}/${this.namespace}?${optionString}`;
127
127
  return url;
128
128
  }
129
129
  }
@@ -7,9 +7,9 @@ import { type DistanceUnit, type PageableModelQuery, type WhereClause, ModelQuer
7
7
  import type { ModelType, IndexField, IndexConfig } from '@travetto/model';
8
8
  import { DataUtil, SchemaRegistryIndex, type Point } from '@travetto/schema';
9
9
 
10
- const PointImpl = toConcrete<Point>();
10
+ const PointConcrete = toConcrete<Point>();
11
11
 
12
- type IdxCfg = CreateIndexesOptions;
12
+ type IdxConfig = CreateIndexesOptions;
13
13
 
14
14
  /**
15
15
  * Converting units to various radians
@@ -31,21 +31,21 @@ export type PlainIdx = Record<string, -1 | 0 | 1>;
31
31
  */
32
32
  export class MongoUtil {
33
33
 
34
- static toIndex<T extends ModelType>(f: IndexField<T>): PlainIdx {
34
+ static toIndex<T extends ModelType>(field: IndexField<T>): PlainIdx {
35
35
  const keys = [];
36
- while (typeof f !== 'number' && typeof f !== 'boolean' && Object.keys(f)) {
37
- const key = TypedObject.keys(f)[0];
38
- f = castTo(f[key]);
36
+ while (typeof field !== 'number' && typeof field !== 'boolean' && Object.keys(field)) {
37
+ const key = TypedObject.keys(field)[0];
38
+ field = castTo(field[key]);
39
39
  keys.push(key);
40
40
  }
41
- const rf: number | boolean = castTo(f);
41
+ const rf: number | boolean = castTo(field);
42
42
  return {
43
43
  [keys.join('.')]: typeof rf === 'boolean' ? (rf ? 1 : 0) : castTo<-1 | 1 | 0>(rf)
44
44
  };
45
45
  }
46
46
 
47
- static uuid(val: string): Binary {
48
- return new Binary(Buffer.from(val.replaceAll('-', ''), 'hex'), Binary.SUBTYPE_UUID);
47
+ static uuid(value: string): Binary {
48
+ return new Binary(Buffer.from(value.replaceAll('-', ''), 'hex'), Binary.SUBTYPE_UUID);
49
49
  }
50
50
 
51
51
  static idToString(id: string | ObjectId | Binary): string {
@@ -66,84 +66,84 @@ export class MongoUtil {
66
66
  /**
67
67
  * Build mongo where clause
68
68
  */
69
- static extractWhereClause<T>(cls: Class<T>, o: WhereClause<T>): Record<string, unknown> {
70
- if (ModelQueryUtil.has$And(o)) {
71
- return { $and: o.$and.map(x => this.extractWhereClause<T>(cls, x)) };
72
- } else if (ModelQueryUtil.has$Or(o)) {
73
- return { $or: o.$or.map(x => this.extractWhereClause<T>(cls, x)) };
74
- } else if (ModelQueryUtil.has$Not(o)) {
75
- return { $nor: [this.extractWhereClause<T>(cls, o.$not)] };
69
+ static extractWhereClause<T>(cls: Class<T>, clause: WhereClause<T>): Record<string, unknown> {
70
+ if (ModelQueryUtil.has$And(clause)) {
71
+ return { $and: clause.$and.map(item => this.extractWhereClause<T>(cls, item)) };
72
+ } else if (ModelQueryUtil.has$Or(clause)) {
73
+ return { $or: clause.$or.map(item => this.extractWhereClause<T>(cls, item)) };
74
+ } else if (ModelQueryUtil.has$Not(clause)) {
75
+ return { $nor: [this.extractWhereClause<T>(cls, clause.$not)] };
76
76
  } else {
77
- return this.extractSimple(cls, o);
77
+ return this.extractSimple(cls, clause);
78
78
  }
79
79
  }
80
80
 
81
81
  /**/
82
- static extractSimple<T>(base: Class<T> | undefined, o: Record<string, unknown>, path: string = '', recursive: boolean = true): Record<string, unknown> {
83
- const fields = base ? SchemaRegistryIndex.getOptionalConfig(base)?.fields : undefined;
82
+ static extractSimple<T>(base: Class<T> | undefined, item: Record<string, unknown>, path: string = '', recursive: boolean = true): Record<string, unknown> {
83
+ const fields = base ? SchemaRegistryIndex.getOptional(base)?.getFields() : undefined;
84
84
  const out: Record<string, unknown> = {};
85
- const sub = o;
85
+ const sub = item;
86
86
  const keys = Object.keys(sub);
87
87
  for (const key of keys) {
88
88
  const subpath = `${path}${key}`;
89
- const v: Record<string, unknown> = castTo(sub[key]);
89
+ const value: Record<string, unknown> = castTo(sub[key]);
90
90
  const subField = fields?.[key];
91
91
 
92
- const isPlain = v && DataUtil.isPlainObject(v);
93
- const firstKey = isPlain ? Object.keys(v)[0] : '';
92
+ const isPlain = value && DataUtil.isPlainObject(value);
93
+ const firstKey = isPlain ? Object.keys(value)[0] : '';
94
94
 
95
95
  if (subpath === 'id') {
96
96
  if (!firstKey) {
97
- out._id = Array.isArray(v) ? v.map(x => this.uuid(x)) : this.uuid(`${v}`);
97
+ out._id = Array.isArray(value) ? value.map(subValue => this.uuid(subValue)) : this.uuid(`${value}`);
98
98
  } else if (firstKey === '$in' || firstKey === '$nin' || firstKey === '$eq' || firstKey === '$ne') {
99
- const temp = v[firstKey];
100
- out._id = { [firstKey]: Array.isArray(temp) ? temp.map(x => this.uuid(x)) : this.uuid(`${temp}`) };
99
+ const temp = value[firstKey];
100
+ out._id = { [firstKey]: Array.isArray(temp) ? temp.map(subValue => this.uuid(subValue)) : this.uuid(`${temp}`) };
101
101
  } else {
102
102
  throw new AppError('Invalid id query');
103
103
  }
104
- } else if ((isPlain && !firstKey.startsWith('$')) || v?.constructor?.Ⲑid) {
104
+ } else if ((isPlain && !firstKey.startsWith('$')) || value?.constructor?.Ⲑid) {
105
105
  if (recursive) {
106
- Object.assign(out, this.extractSimple(subField?.type, v, `${subpath}.`, recursive));
106
+ Object.assign(out, this.extractSimple(subField?.type, value, `${subpath}.`, recursive));
107
107
  } else {
108
- out[subpath] = v;
108
+ out[subpath] = value;
109
109
  }
110
110
  } else {
111
111
  if (firstKey === '$gt' || firstKey === '$lt' || firstKey === '$gte' || firstKey === '$lte') {
112
- for (const [sk, sv] of Object.entries(v)) {
113
- v[sk] = ModelQueryUtil.resolveComparator(sv);
112
+ for (const [sk, sv] of Object.entries(value)) {
113
+ value[sk] = ModelQueryUtil.resolveComparator(sv);
114
114
  }
115
115
  } else if (firstKey === '$exists' && subField?.array) {
116
- const exists = v.$exists;
116
+ const exists = value.$exists;
117
117
  if (!exists) {
118
- delete v.$exists;
119
- v.$in = [null, []];
118
+ delete value.$exists;
119
+ value.$in = [null, []];
120
120
  } else {
121
- v.$exists = true;
122
- v.$nin = [null, []];
121
+ value.$exists = true;
122
+ value.$nin = [null, []];
123
123
  }
124
124
  } else if (firstKey === '$regex') {
125
- v.$regex = DataUtil.toRegex(castTo(v.$regex));
126
- } else if (firstKey && '$near' in v) {
127
- const dist: number = castTo(v.$maxDistance);
128
- const distance = dist / RADIANS_TO[(castTo<DistanceUnit>(v.$unit) ?? 'km')];
129
- v.$maxDistance = distance;
130
- delete v.$unit;
131
- } else if (firstKey && '$geoWithin' in v) {
132
- const coords: [number, number][] = castTo(v.$geoWithin);
125
+ value.$regex = DataUtil.toRegex(castTo(value.$regex));
126
+ } else if (firstKey && '$near' in value) {
127
+ const dist: number = castTo(value.$maxDistance);
128
+ const distance = dist / RADIANS_TO[(castTo<DistanceUnit>(value.$unit) ?? 'km')];
129
+ value.$maxDistance = distance;
130
+ delete value.$unit;
131
+ } else if (firstKey && '$geoWithin' in value) {
132
+ const coords: [number, number][] = castTo(value.$geoWithin);
133
133
  const first = coords[0];
134
134
  const last = coords.at(-1)!;
135
135
  // Connect if not
136
136
  if (first[0] !== last[0] || first[1] !== last[1]) {
137
137
  coords.push(first);
138
138
  }
139
- v.$geoWithin = {
139
+ value.$geoWithin = {
140
140
  $geometry: {
141
141
  type: 'Polygon',
142
142
  coordinates: [coords]
143
143
  }
144
144
  };
145
145
  }
146
- out[subpath === 'id' ? '_id' : subpath] = v;
146
+ out[subpath === 'id' ? '_id' : subpath] = value;
147
147
  }
148
148
  }
149
149
  return out;
@@ -153,11 +153,11 @@ export class MongoUtil {
153
153
  const out: BasicIdx[] = [];
154
154
  const textFields: string[] = [];
155
155
  SchemaRegistryIndex.visitFields(cls, (field, path) => {
156
- if (field.type === PointImpl) {
157
- const name = [...path, field].map(x => x.name).join('.');
156
+ if (field.type === PointConcrete) {
157
+ const name = [...path, field].map(schema => schema.name).join('.');
158
158
  out.push({ [name]: '2d' });
159
159
  } else if (field.specifiers?.includes('text') && (field.specifiers?.includes('long') || field.specifiers.includes('search'))) {
160
- const name = [...path, field].map(x => x.name).join('.');
160
+ const name = [...path, field].map(schema => schema.name).join('.');
161
161
  textFields.push(name);
162
162
  }
163
163
  });
@@ -173,17 +173,17 @@ export class MongoUtil {
173
173
 
174
174
  static getPlainIndex(idx: IndexConfig<ModelType>): PlainIdx {
175
175
  let out: PlainIdx = {};
176
- for (const cfg of idx.fields.map(x => this.toIndex(x))) {
177
- out = Object.assign(out, cfg);
176
+ for (const config of idx.fields.map(value => this.toIndex(value))) {
177
+ out = Object.assign(out, config);
178
178
  }
179
179
  return out;
180
180
  }
181
181
 
182
- static getIndices<T extends ModelType>(cls: Class<T>, indices: IndexConfig<ModelType>[] = []): [BasicIdx, IdxCfg][] {
182
+ static getIndices<T extends ModelType>(cls: Class<T>, indices: IndexConfig<ModelType>[] = []): [BasicIdx, IdxConfig][] {
183
183
  return [
184
184
  ...indices.map(idx => [this.getPlainIndex(idx), (idx.type === 'unique' ? { unique: true } : {})] as const),
185
- ...this.getExtraIndices(cls).map((x) => [x, {}] as const)
186
- ].map(x => [...x]);
185
+ ...this.getExtraIndices(cls).map((idx) => [idx, {}] as const)
186
+ ].map(idx => [...idx]);
187
187
  }
188
188
 
189
189
  static prepareCursor<T extends ModelType>(cls: Class<T>, cursor: FindCursor<T | MongoWithId<T>>, query: PageableModelQuery<T>): FindCursor<T> {
@@ -201,7 +201,7 @@ export class MongoUtil {
201
201
  }
202
202
 
203
203
  if (query.sort) {
204
- cursor = cursor.sort(Object.assign({}, ...query.sort.map(x => this.extractSimple(cls, x))));
204
+ cursor = cursor.sort(Object.assign({}, ...query.sort.map(item => this.extractSimple(cls, item))));
205
205
  }
206
206
 
207
207
  cursor = cursor.limit(Math.trunc(query.limit ?? 200));
package/src/service.ts CHANGED
@@ -8,7 +8,7 @@ import {
8
8
 
9
9
  import {
10
10
  ModelRegistryIndex, ModelType, OptionalId, ModelCrudSupport, ModelStorageSupport,
11
- ModelExpirySupport, ModelBulkSupport, ModelIndexedSupport, BulkOp, BulkResponse,
11
+ ModelExpirySupport, ModelBulkSupport, ModelIndexedSupport, BulkOperation, BulkResponse,
12
12
  NotFoundError, ExistsError, ModelBlobSupport,
13
13
  ModelCrudUtil, ModelIndexedUtil, ModelStorageUtil, ModelExpiryUtil, ModelBulkUtil, ModelBlobUtil,
14
14
  } from '@travetto/model';
@@ -131,8 +131,8 @@ export class MongoModelService implements
131
131
  const creating = MongoUtil.getIndices(cls, ModelRegistryIndex.getConfig(cls).indices);
132
132
  if (creating.length) {
133
133
  console.debug('Creating indexes', { indices: creating });
134
- for (const el of creating) {
135
- await col.createIndex(...el);
134
+ for (const toCreate of creating) {
135
+ await col.createIndex(...toCreate);
136
136
  }
137
137
  }
138
138
  }
@@ -208,11 +208,11 @@ export class MongoModelService implements
208
208
  { $set: cleaned },
209
209
  { upsert: true }
210
210
  );
211
- } catch (err) {
212
- if (err instanceof Error && err.message.includes('duplicate key error')) {
211
+ } catch (error) {
212
+ if (error instanceof Error && error.message.includes('duplicate key error')) {
213
213
  throw new ExistsError(cls, id);
214
214
  } else {
215
- throw err;
215
+ throw error;
216
216
  }
217
217
  }
218
218
  return this.postUpdate(cleaned, id);
@@ -226,13 +226,13 @@ export class MongoModelService implements
226
226
 
227
227
  const operation: Partial<T> = castTo(Object
228
228
  .entries(simple)
229
- .reduce<Partial<Record<'$unset' | '$set', Record<string, unknown>>>>((acc, [k, v]) => {
230
- if (v === null || v === undefined) {
231
- (acc.$unset ??= {})[k] = v;
229
+ .reduce<Partial<Record<'$unset' | '$set', Record<string, unknown>>>>((document, [key, value]) => {
230
+ if (value === null || value === undefined) {
231
+ (document.$unset ??= {})[key] = value;
232
232
  } else {
233
- (acc.$set ??= {})[k] = v;
233
+ (document.$set ??= {})[key] = value;
234
234
  }
235
- return acc;
235
+ return document;
236
236
  }, {}));
237
237
 
238
238
  const id = item.id;
@@ -261,12 +261,12 @@ export class MongoModelService implements
261
261
  async * list<T extends ModelType>(cls: Class<T>): AsyncIterable<T> {
262
262
  const store = await this.getStore(cls);
263
263
  const cursor = store.find(this.getWhereFilter(cls, {}), { timeout: true }).batchSize(100);
264
- for await (const el of cursor) {
264
+ for await (const item of cursor) {
265
265
  try {
266
- yield await this.postLoad(cls, el);
267
- } catch (err) {
268
- if (!(err instanceof NotFoundError)) {
269
- throw err;
266
+ yield await this.postLoad(cls, item);
267
+ } catch (error) {
268
+ if (!(error instanceof NotFoundError)) {
269
+ throw error;
270
270
  }
271
271
  }
272
272
  }
@@ -279,10 +279,7 @@ export class MongoModelService implements
279
279
  return;
280
280
  }
281
281
  const [stream, blobMeta] = await ModelBlobUtil.getInput(input, meta);
282
- const writeStream = this.#bucket.openUploadStream(location, {
283
- contentType: blobMeta.contentType,
284
- metadata: blobMeta,
285
- });
282
+ const writeStream = this.#bucket.openUploadStream(location, { metadata: blobMeta });
286
283
  await pipeline(stream, writeStream);
287
284
 
288
285
  if (existing) {
@@ -316,7 +313,7 @@ export class MongoModelService implements
316
313
  }
317
314
 
318
315
  // Bulk
319
- async processBulk<T extends ModelType>(cls: Class<T>, operations: BulkOp<T>[]): Promise<BulkResponse<{ index: number }>> {
316
+ async processBulk<T extends ModelType>(cls: Class<T>, operations: BulkOperation<T>[]): Promise<BulkResponse<{ index: number }>> {
320
317
  const out: BulkResponse<{ index: number }> = {
321
318
  errors: [],
322
319
  counts: {
@@ -339,26 +336,26 @@ export class MongoModelService implements
339
336
 
340
337
  out.insertedIds = new Map([...upsertedIds.entries(), ...insertedIds.entries()]);
341
338
 
342
- for (const op of operations) {
343
- if (op.insert) {
344
- this.preUpdate(op.insert);
345
- bulk.insert(op.insert);
346
- } else if (op.upsert) {
347
- const id = this.preUpdate(op.upsert);
348
- bulk.find({ _id: MongoUtil.uuid(id!) }).upsert().updateOne({ $set: op.upsert });
349
- } else if (op.update) {
350
- const id = this.preUpdate(op.update);
351
- bulk.find({ _id: MongoUtil.uuid(id) }).update({ $set: op.update });
352
- } else if (op.delete) {
353
- bulk.find({ _id: MongoUtil.uuid(op.delete.id) }).deleteOne();
339
+ for (const operation of operations) {
340
+ if (operation.insert) {
341
+ this.preUpdate(operation.insert);
342
+ bulk.insert(operation.insert);
343
+ } else if (operation.upsert) {
344
+ const id = this.preUpdate(operation.upsert);
345
+ bulk.find({ _id: MongoUtil.uuid(id!) }).upsert().updateOne({ $set: operation.upsert });
346
+ } else if (operation.update) {
347
+ const id = this.preUpdate(operation.update);
348
+ bulk.find({ _id: MongoUtil.uuid(id) }).update({ $set: operation.update });
349
+ } else if (operation.delete) {
350
+ bulk.find({ _id: MongoUtil.uuid(operation.delete.id) }).deleteOne();
354
351
  }
355
352
  }
356
353
 
357
354
  const result = await bulk.execute({});
358
355
 
359
356
  // Restore all ids
360
- for (const op of operations) {
361
- const core = op.insert ?? op.upsert ?? op.update;
357
+ for (const operation of operations) {
358
+ const core = operation.insert ?? operation.upsert ?? operation.update;
362
359
  if (core) {
363
360
  this.postUpdate(asFull(core));
364
361
  }
@@ -370,17 +367,17 @@ export class MongoModelService implements
370
367
 
371
368
  if (out.counts) {
372
369
  out.counts.delete = result.deletedCount;
373
- out.counts.update = operations.filter(x => x.update).length;
370
+ out.counts.update = operations.filter(item => item.update).length;
374
371
  out.counts.insert = result.insertedCount;
375
- out.counts.upsert = operations.filter(x => x.upsert).length;
372
+ out.counts.upsert = operations.filter(item => item.upsert).length;
376
373
  }
377
374
 
378
375
  if (result.hasWriteErrors()) {
379
376
  out.errors = result.getWriteErrors();
380
- for (const err of out.errors) {
381
- const op = operations[err.index];
382
- const k = TypedObject.keys(op)[0];
383
- out.counts[k] -= 1;
377
+ for (const error of out.errors) {
378
+ const operation = operations[error.index];
379
+ const key = TypedObject.keys(operation)[0];
380
+ out.counts[key] -= 1;
384
381
  }
385
382
  out.counts.error = out.errors.length;
386
383
  }
@@ -430,18 +427,18 @@ export class MongoModelService implements
430
427
 
431
428
  async * listByIndex<T extends ModelType>(cls: Class<T>, idx: string, body?: DeepPartial<T>): AsyncIterable<T> {
432
429
  const store = await this.getStore(cls);
433
- const idxCfg = ModelRegistryIndex.getIndex(cls, idx, ['sorted', 'unsorted']);
430
+ const idxConfig = ModelRegistryIndex.getIndex(cls, idx, ['sorted', 'unsorted']);
434
431
 
435
432
  const where = this.getWhereFilter(
436
433
  cls,
437
434
  castTo(ModelIndexedUtil.projectIndex(cls, idx, body, { emptySortValue: { $exists: true } }))
438
435
  );
439
436
 
440
- const sort = castTo<{ [ListIndexSymbol]: PlainIdx }>(idxCfg)[ListIndexSymbol] ??= MongoUtil.getPlainIndex(idxCfg);
437
+ const sort = castTo<{ [ListIndexSymbol]: PlainIdx }>(idxConfig)[ListIndexSymbol] ??= MongoUtil.getPlainIndex(idxConfig);
441
438
  const cursor = store.find(where, { timeout: true }).batchSize(100).sort(castTo(sort));
442
439
 
443
- for await (const el of cursor) {
444
- yield await this.postLoad(cls, el);
440
+ for await (const item of cursor) {
441
+ yield await this.postLoad(cls, item);
445
442
  }
446
443
  }
447
444
 
@@ -453,7 +450,7 @@ export class MongoModelService implements
453
450
  const filter = MongoUtil.extractWhereFilter(cls, query.where);
454
451
  const cursor = col.find(filter, {});
455
452
  const items = await MongoUtil.prepareCursor(cls, cursor, query).toArray();
456
- return await Promise.all(items.map(r => this.postLoad(cls, r)));
453
+ return await Promise.all(items.map(item => this.postLoad(cls, item)));
457
454
  }
458
455
 
459
456
  async queryCount<T extends ModelType>(cls: Class<T>, query: ModelQuery<T>): Promise<number> {
@@ -503,13 +500,13 @@ export class MongoModelService implements
503
500
  const col = await this.getStore(cls);
504
501
  const items = MongoUtil.extractSimple(cls, item);
505
502
  const final = Object.entries(items).reduce<Partial<Record<'$unset' | '$set', Record<string, unknown>>>>(
506
- (acc, [k, v]) => {
507
- if (v === null || v === undefined) {
508
- (acc.$unset ??= {})[k] = v;
503
+ (document, [key, value]) => {
504
+ if (value === null || value === undefined) {
505
+ (document.$unset ??= {})[key] = value;
509
506
  } else {
510
- (acc.$set ??= {})[k] = v;
507
+ (document.$set ??= {})[key] = value;
511
508
  }
512
- return acc;
509
+ return document;
513
510
  }, {});
514
511
 
515
512
  const filter = MongoUtil.extractWhereFilter(cls, query.where);
@@ -526,14 +523,14 @@ export class MongoModelService implements
526
523
  await QueryVerifier.verify(cls, query);
527
524
  }
528
525
 
529
- let q: Record<string, unknown> = { [field]: { $exists: true } };
526
+ let queryObject: Record<string, unknown> = { [field]: { $exists: true } };
530
527
 
531
528
  if (query?.where) {
532
- q = { $and: [q, MongoUtil.extractWhereFilter(cls, query.where)] };
529
+ queryObject = { $and: [queryObject, MongoUtil.extractWhereFilter(cls, query.where)] };
533
530
  }
534
531
 
535
532
  const aggregations: object[] = [
536
- { $match: q },
533
+ { $match: queryObject },
537
534
  {
538
535
  $group: {
539
536
  _id: `$${field}`,
@@ -547,9 +544,9 @@ export class MongoModelService implements
547
544
  const result = await col.aggregate<{ _id: ObjectId, count: number }>(aggregations).toArray();
548
545
 
549
546
  return result
550
- .map(val => ({
551
- key: MongoUtil.idToString(val._id),
552
- count: val.count
547
+ .map(item => ({
548
+ key: MongoUtil.idToString(item._id),
549
+ count: item.count
553
550
  }))
554
551
  .toSorted((a, b) => b.count - a.count);
555
552
  }
@@ -557,15 +554,15 @@ export class MongoModelService implements
557
554
  // Suggest
558
555
  async suggestValues<T extends ModelType>(cls: Class<T>, field: ValidStringFields<T>, prefix?: string, query?: PageableModelQuery<T>): Promise<string[]> {
559
556
  await QueryVerifier.verify(cls, query);
560
- const q = ModelQuerySuggestUtil.getSuggestFieldQuery<T>(cls, field, prefix, query);
561
- const results = await this.query<T>(cls, q);
557
+ const resolvedQuery = ModelQuerySuggestUtil.getSuggestFieldQuery<T>(cls, field, prefix, query);
558
+ const results = await this.query<T>(cls, resolvedQuery);
562
559
  return ModelQuerySuggestUtil.combineSuggestResults<T, string>(cls, field, prefix, results, (a) => a, query && query.limit);
563
560
  }
564
561
 
565
562
  async suggest<T extends ModelType>(cls: Class<T>, field: ValidStringFields<T>, prefix?: string, query?: PageableModelQuery<T>): Promise<T[]> {
566
563
  await QueryVerifier.verify(cls, query);
567
- const q = ModelQuerySuggestUtil.getSuggestQuery<T>(cls, field, prefix, query);
568
- const results = await this.query<T>(cls, q);
564
+ const resolvedQuery = ModelQuerySuggestUtil.getSuggestQuery<T>(cls, field, prefix, query);
565
+ const results = await this.query<T>(cls, resolvedQuery);
569
566
  return ModelQuerySuggestUtil.combineSuggestResults(cls, field, prefix, results, (_, b) => b, query && query.limit);
570
567
  }
571
568
 
@@ -585,6 +582,6 @@ export class MongoModelService implements
585
582
 
586
583
  const cursor = col.find(castTo({ $and: [{ $text: search }, filter] }), {});
587
584
  const items = await MongoUtil.prepareCursor(cls, cursor, query).toArray();
588
- return await Promise.all(items.map(r => this.postLoad(cls, r)));
585
+ return await Promise.all(items.map(item => this.postLoad(cls, item)));
589
586
  }
590
587
  }