@opra/mongodb 1.5.6 → 1.6.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.
@@ -19,6 +19,7 @@ class MongoPatchGenerator {
19
19
  return {
20
20
  update,
21
21
  arrayFilters: ctx.arrayFilters,
22
+ initArrayFields: ctx.initArrayFields,
22
23
  };
23
24
  }
24
25
  _processComplexType(ctx, dataType, path, input, scope) {
@@ -84,6 +85,8 @@ class MongoPatchGenerator {
84
85
  if (!value)
85
86
  continue;
86
87
  if (field.isArray) {
88
+ ctx.initArrayFields = ctx.initArrayFields || [];
89
+ ctx.initArrayFields.push(pathDot + field.name);
87
90
  if (!value.length)
88
91
  continue;
89
92
  keyField = field.keyField || field.type.keyField;
@@ -190,7 +190,7 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
190
190
  if (options?.postStages)
191
191
  stages.push(...options.postStages);
192
192
  const dataType = this.dataType;
193
- const projection = mongo_adapter_js_1.MongoAdapter.prepareProjection(dataType, options?.projection);
193
+ const projection = mongo_adapter_js_1.MongoAdapter.prepareProjection(dataType, options?.projection, this._dataTypeScope);
194
194
  if (projection)
195
195
  stages.push({ $project: projection });
196
196
  const db = this.getDatabase();
@@ -253,7 +253,7 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
253
253
  /** Limit */
254
254
  dataStages.push({ $limit: limit });
255
255
  const dataType = this.dataType;
256
- const projection = mongo_adapter_js_1.MongoAdapter.prepareProjection(dataType, options?.projection);
256
+ const projection = mongo_adapter_js_1.MongoAdapter.prepareProjection(dataType, options?.projection, this._dataTypeScope);
257
257
  if (projection)
258
258
  dataStages.push({ $project: projection });
259
259
  const outputCodec = this._getOutputCodec('find');
@@ -303,7 +303,7 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
303
303
  returnDocument: 'after',
304
304
  includeResultMetadata: false,
305
305
  session: options?.session ?? this.getSession(),
306
- projection: mongo_adapter_js_1.MongoAdapter.prepareProjection(this.dataType, options?.projection),
306
+ projection: mongo_adapter_js_1.MongoAdapter.prepareProjection(this.dataType, options?.projection, this._dataTypeScope),
307
307
  });
308
308
  const outputCodec = this._getOutputCodec('update');
309
309
  if (out)
@@ -329,6 +329,21 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
329
329
  ]);
330
330
  const db = this.getDatabase();
331
331
  const collection = await this.getCollection(db);
332
+ /** Create array fields if not exists */
333
+ if (options?.initArrayFields) {
334
+ const $set = options.initArrayFields.reduce((a, k) => {
335
+ a[k] = { $ifNull: ['$' + k, []] };
336
+ return a;
337
+ }, {});
338
+ await collection.updateOne(filter || {}, [{ $set }], {
339
+ ...options,
340
+ session: options?.session ?? this.getSession(),
341
+ arrayFilters: undefined,
342
+ upsert: false,
343
+ });
344
+ delete options.initArrayFields;
345
+ }
346
+ /** Execute update operation */
332
347
  return (await collection.updateOne(filter || {}, update, {
333
348
  ...options,
334
349
  session: options?.session ?? this.getSession(),
@@ -352,6 +367,21 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
352
367
  const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter(options?.filter);
353
368
  const db = this.getDatabase();
354
369
  const collection = await this.getCollection(db);
370
+ /** Create array fields if not exists */
371
+ if (options?.initArrayFields) {
372
+ const $set = options.initArrayFields.reduce((a, k) => {
373
+ a[k] = { $ifNull: ['$' + k, []] };
374
+ return a;
375
+ }, {});
376
+ await collection.updateMany(filter || {}, [{ $set }], {
377
+ ...(0, objects_1.omit)(options, ['filter']),
378
+ session: options?.session ?? this.getSession(),
379
+ arrayFilters: undefined,
380
+ upsert: false,
381
+ });
382
+ delete options.initArrayFields;
383
+ }
384
+ /** Execute update operation */
355
385
  return (await collection.updateMany(filter || {}, update, {
356
386
  ...(0, objects_1.omit)(options, ['filter']),
357
387
  session: options?.session ?? this.getSession(),
@@ -382,7 +412,7 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
382
412
  returnDocument: 'after',
383
413
  includeResultMetadata: false,
384
414
  session: options?.session ?? this.getSession(),
385
- projection: mongo_adapter_js_1.MongoAdapter.prepareProjection(this.dataType, options?.projection),
415
+ projection: mongo_adapter_js_1.MongoAdapter.prepareProjection(this.dataType, options?.projection, this._dataTypeScope),
386
416
  });
387
417
  const outputCodec = this._getOutputCodec('replace');
388
418
  if (out)
@@ -406,13 +436,14 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
406
436
  }
407
437
  _generatePatch(command, doc) {
408
438
  const patchGenerator = new mongo_patch_generator_js_1.MongoPatchGenerator();
409
- const { update, arrayFilters } = patchGenerator.generatePatch(this.dataType, doc, {
439
+ const { update, arrayFilters, initArrayFields } = patchGenerator.generatePatch(this.dataType, doc, {
410
440
  scope: this._dataTypeScope,
411
441
  });
412
442
  command.options = command.options || {};
413
443
  if (arrayFilters) {
414
444
  command.options.arrayFilters = command.options.arrayFilters || [];
415
445
  command.options.arrayFilters.push(...arrayFilters);
446
+ command.options.initArrayFields = initArrayFields;
416
447
  }
417
448
  return update;
418
449
  }
@@ -495,7 +495,7 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
495
495
  /** Limit */
496
496
  stages.push({ $limit: limit });
497
497
  const dataType = this.dataType;
498
- const projection = mongo_adapter_js_1.MongoAdapter.prepareProjection(dataType, options?.projection);
498
+ const projection = mongo_adapter_js_1.MongoAdapter.prepareProjection(dataType, options?.projection, this._dataTypeScope);
499
499
  if (projection)
500
500
  stages.push({ $project: projection });
501
501
  /** Post-Stages */
@@ -590,7 +590,7 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
590
590
  if (options?.postStages)
591
591
  dataStages.push(...options.postStages);
592
592
  const dataType = this.dataType;
593
- const projection = mongo_adapter_js_1.MongoAdapter.prepareProjection(dataType, options?.projection);
593
+ const projection = mongo_adapter_js_1.MongoAdapter.prepareProjection(dataType, options?.projection, this._dataTypeScope);
594
594
  if (projection)
595
595
  dataStages.push({ $project: projection });
596
596
  const db = this.getDatabase();
@@ -253,6 +253,7 @@ class MongoService extends core_1.ServiceBase {
253
253
  if (operation === 'update') {
254
254
  options.partial = 'deep';
255
255
  options.allowPatchOperators = true;
256
+ options.keepKeyFields = true;
256
257
  }
257
258
  const dataType = this.dataType;
258
259
  validator = dataType.generateCodec('decode', options);
@@ -16,6 +16,7 @@ export class MongoPatchGenerator {
16
16
  return {
17
17
  update,
18
18
  arrayFilters: ctx.arrayFilters,
19
+ initArrayFields: ctx.initArrayFields,
19
20
  };
20
21
  }
21
22
  _processComplexType(ctx, dataType, path, input, scope) {
@@ -81,6 +82,8 @@ export class MongoPatchGenerator {
81
82
  if (!value)
82
83
  continue;
83
84
  if (field.isArray) {
85
+ ctx.initArrayFields = ctx.initArrayFields || [];
86
+ ctx.initArrayFields.push(pathDot + field.name);
84
87
  if (!value.length)
85
88
  continue;
86
89
  keyField = field.keyField || field.type.keyField;
@@ -187,7 +187,7 @@ export class MongoEntityService extends MongoService {
187
187
  if (options?.postStages)
188
188
  stages.push(...options.postStages);
189
189
  const dataType = this.dataType;
190
- const projection = MongoAdapter.prepareProjection(dataType, options?.projection);
190
+ const projection = MongoAdapter.prepareProjection(dataType, options?.projection, this._dataTypeScope);
191
191
  if (projection)
192
192
  stages.push({ $project: projection });
193
193
  const db = this.getDatabase();
@@ -250,7 +250,7 @@ export class MongoEntityService extends MongoService {
250
250
  /** Limit */
251
251
  dataStages.push({ $limit: limit });
252
252
  const dataType = this.dataType;
253
- const projection = MongoAdapter.prepareProjection(dataType, options?.projection);
253
+ const projection = MongoAdapter.prepareProjection(dataType, options?.projection, this._dataTypeScope);
254
254
  if (projection)
255
255
  dataStages.push({ $project: projection });
256
256
  const outputCodec = this._getOutputCodec('find');
@@ -300,7 +300,7 @@ export class MongoEntityService extends MongoService {
300
300
  returnDocument: 'after',
301
301
  includeResultMetadata: false,
302
302
  session: options?.session ?? this.getSession(),
303
- projection: MongoAdapter.prepareProjection(this.dataType, options?.projection),
303
+ projection: MongoAdapter.prepareProjection(this.dataType, options?.projection, this._dataTypeScope),
304
304
  });
305
305
  const outputCodec = this._getOutputCodec('update');
306
306
  if (out)
@@ -326,6 +326,21 @@ export class MongoEntityService extends MongoService {
326
326
  ]);
327
327
  const db = this.getDatabase();
328
328
  const collection = await this.getCollection(db);
329
+ /** Create array fields if not exists */
330
+ if (options?.initArrayFields) {
331
+ const $set = options.initArrayFields.reduce((a, k) => {
332
+ a[k] = { $ifNull: ['$' + k, []] };
333
+ return a;
334
+ }, {});
335
+ await collection.updateOne(filter || {}, [{ $set }], {
336
+ ...options,
337
+ session: options?.session ?? this.getSession(),
338
+ arrayFilters: undefined,
339
+ upsert: false,
340
+ });
341
+ delete options.initArrayFields;
342
+ }
343
+ /** Execute update operation */
329
344
  return (await collection.updateOne(filter || {}, update, {
330
345
  ...options,
331
346
  session: options?.session ?? this.getSession(),
@@ -349,6 +364,21 @@ export class MongoEntityService extends MongoService {
349
364
  const filter = MongoAdapter.prepareFilter(options?.filter);
350
365
  const db = this.getDatabase();
351
366
  const collection = await this.getCollection(db);
367
+ /** Create array fields if not exists */
368
+ if (options?.initArrayFields) {
369
+ const $set = options.initArrayFields.reduce((a, k) => {
370
+ a[k] = { $ifNull: ['$' + k, []] };
371
+ return a;
372
+ }, {});
373
+ await collection.updateMany(filter || {}, [{ $set }], {
374
+ ...omit(options, ['filter']),
375
+ session: options?.session ?? this.getSession(),
376
+ arrayFilters: undefined,
377
+ upsert: false,
378
+ });
379
+ delete options.initArrayFields;
380
+ }
381
+ /** Execute update operation */
352
382
  return (await collection.updateMany(filter || {}, update, {
353
383
  ...omit(options, ['filter']),
354
384
  session: options?.session ?? this.getSession(),
@@ -379,7 +409,7 @@ export class MongoEntityService extends MongoService {
379
409
  returnDocument: 'after',
380
410
  includeResultMetadata: false,
381
411
  session: options?.session ?? this.getSession(),
382
- projection: MongoAdapter.prepareProjection(this.dataType, options?.projection),
412
+ projection: MongoAdapter.prepareProjection(this.dataType, options?.projection, this._dataTypeScope),
383
413
  });
384
414
  const outputCodec = this._getOutputCodec('replace');
385
415
  if (out)
@@ -403,13 +433,14 @@ export class MongoEntityService extends MongoService {
403
433
  }
404
434
  _generatePatch(command, doc) {
405
435
  const patchGenerator = new MongoPatchGenerator();
406
- const { update, arrayFilters } = patchGenerator.generatePatch(this.dataType, doc, {
436
+ const { update, arrayFilters, initArrayFields } = patchGenerator.generatePatch(this.dataType, doc, {
407
437
  scope: this._dataTypeScope,
408
438
  });
409
439
  command.options = command.options || {};
410
440
  if (arrayFilters) {
411
441
  command.options.arrayFilters = command.options.arrayFilters || [];
412
442
  command.options.arrayFilters.push(...arrayFilters);
443
+ command.options.initArrayFields = initArrayFields;
413
444
  }
414
445
  return update;
415
446
  }
@@ -492,7 +492,7 @@ export class MongoNestedService extends MongoService {
492
492
  /** Limit */
493
493
  stages.push({ $limit: limit });
494
494
  const dataType = this.dataType;
495
- const projection = MongoAdapter.prepareProjection(dataType, options?.projection);
495
+ const projection = MongoAdapter.prepareProjection(dataType, options?.projection, this._dataTypeScope);
496
496
  if (projection)
497
497
  stages.push({ $project: projection });
498
498
  /** Post-Stages */
@@ -587,7 +587,7 @@ export class MongoNestedService extends MongoService {
587
587
  if (options?.postStages)
588
588
  dataStages.push(...options.postStages);
589
589
  const dataType = this.dataType;
590
- const projection = MongoAdapter.prepareProjection(dataType, options?.projection);
590
+ const projection = MongoAdapter.prepareProjection(dataType, options?.projection, this._dataTypeScope);
591
591
  if (projection)
592
592
  dataStages.push({ $project: projection });
593
593
  const db = this.getDatabase();
@@ -250,6 +250,7 @@ export class MongoService extends ServiceBase {
250
250
  if (operation === 'update') {
251
251
  options.partial = 'deep';
252
252
  options.allowPatchOperators = true;
253
+ options.keepKeyFields = true;
253
254
  }
254
255
  const dataType = this.dataType;
255
256
  validator = dataType.generateCodec('decode', options);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opra/mongodb",
3
- "version": "1.5.6",
3
+ "version": "1.6.0",
4
4
  "description": "Opra MongoDB adapter package",
5
5
  "author": "Panates",
6
6
  "license": "MIT",
@@ -10,9 +10,9 @@
10
10
  "valgen": "^5.12.0"
11
11
  },
12
12
  "peerDependencies": {
13
- "@opra/common": "^1.5.6",
14
- "@opra/core": "^1.5.6",
15
- "@opra/http": "^1.5.6",
13
+ "@opra/common": "^1.6.0",
14
+ "@opra/core": "^1.6.0",
15
+ "@opra/http": "^1.6.0",
16
16
  "mongodb": ">= 6.0.0"
17
17
  },
18
18
  "type": "module",
@@ -7,11 +7,13 @@ interface Context {
7
7
  $push?: Record<string, any>;
8
8
  $pull?: Record<string, any>;
9
9
  arrayFilters?: Record<string, any>[];
10
+ initArrayFields?: string[];
10
11
  }
11
12
  export declare class MongoPatchGenerator {
12
13
  generatePatch<T extends object>(dataType: ComplexType, doc: PatchDTO<T>, options?: MongoPatchGenerator.Options): {
13
14
  update: UpdateFilter<T>;
14
15
  arrayFilters?: Record<string, any>[];
16
+ initArrayFields?: string[];
15
17
  };
16
18
  protected _processComplexType(ctx: Context, dataType: ComplexType, path: string, input: any, scope?: string): boolean;
17
19
  protected _processPush(ctx: Context, dataType: ComplexType, path: string, input: any, scope?: string): boolean;
@@ -36,8 +36,10 @@ export declare namespace MongoEntityService {
36
36
  interface ReplaceOptions<T> extends MongoService.ReplaceOptions<T> {
37
37
  }
38
38
  interface UpdateOneOptions<T> extends MongoService.UpdateOneOptions<T> {
39
+ initArrayFields?: string[];
39
40
  }
40
41
  interface UpdateManyOptions<T> extends MongoService.UpdateManyOptions<T> {
42
+ initArrayFields?: string[];
41
43
  }
42
44
  interface CreateCommand<T> extends StrictOmit<CommandInfo, 'documentId' | 'nestedId' | 'input'> {
43
45
  crud: 'create';