@bedrockio/model 0.5.3 → 0.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.
@@ -12,6 +12,7 @@ var _serialization = require("./serialization");
12
12
  var _slug = require("./slug");
13
13
  var _search = require("./search");
14
14
  var _assign = require("./assign");
15
+ var _upsert = require("./upsert");
15
16
  var _hydrate = require("./hydrate");
16
17
  var _include = require("./include");
17
18
  var _softDelete = require("./soft-delete");
@@ -57,6 +58,7 @@ function createSchema(definition, options = {}) {
57
58
  (0, _include.applyInclude)(schema);
58
59
  (0, _hydrate.applyHydrate)(schema);
59
60
  (0, _assign.applyAssign)(schema);
61
+ (0, _upsert.applyUpsert)(schema);
60
62
  (0, _slug.applySlug)(schema);
61
63
  return schema;
62
64
  }
@@ -26,6 +26,7 @@ function applySearch(schema, definition) {
26
26
  validateDefinition(definition);
27
27
  validateSearchFields(schema, definition);
28
28
  applySearchCache(schema, definition);
29
+ applySearchSync(schema, definition);
29
30
  const {
30
31
  query: searchQuery,
31
32
  fields: searchFields
@@ -362,14 +363,16 @@ function createCacheFields(schema, definition) {
362
363
  for (let [cachedField, def] of Object.entries(definition.search.cache)) {
363
364
  // Fall back to string type for virtuals or not defined.
364
365
  const {
365
- type = 'String'
366
+ type = 'String',
367
+ path,
368
+ ...rest
366
369
  } = def;
367
370
  schema.add({
368
371
  [cachedField]: type
369
372
  });
370
373
  schema.obj[cachedField] = {
371
374
  type,
372
- readAccess: 'none'
375
+ ...rest
373
376
  };
374
377
  }
375
378
  }
@@ -389,6 +392,32 @@ function applyCacheHook(schema, definition) {
389
392
  this.assign(getUpdates(this, paths, definition));
390
393
  });
391
394
  }
395
+
396
+ // Search field syncing
397
+
398
+ function applySearchSync(schema, definition) {
399
+ if (!definition.search?.sync) {
400
+ return;
401
+ }
402
+ schema.post('save', async function postSave() {
403
+ for (let entry of definition.search.sync) {
404
+ const {
405
+ ref,
406
+ path
407
+ } = entry;
408
+ const Model = _mongoose.default.models[ref];
409
+ const docs = await Model.find({
410
+ [path]: this.id
411
+ });
412
+ await Promise.all(docs.map(async doc => {
413
+ await doc.save();
414
+ }));
415
+ }
416
+ });
417
+ }
418
+
419
+ // Utils
420
+
392
421
  function isForeignField(schema, path) {
393
422
  if (!path.includes('.')) {
394
423
  return false;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.applyUpsert = applyUpsert;
7
+ function applyUpsert(schema) {
8
+ // Note: Intentionally avoiding the findOneAndUpdate approach here
9
+ // as this will prevent hooks from being run on the document. This
10
+ // means however that we cannot always return a query here as the
11
+ // operations are inherently different.
12
+
13
+ schema.static('findOrCreate', async function findOrCreate(query, fields) {
14
+ fields ||= query;
15
+ let doc = await this.findOne(query);
16
+ if (!doc) {
17
+ doc = await this.create(fields);
18
+ }
19
+ return doc;
20
+ });
21
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bedrockio/model",
3
- "version": "0.5.3",
3
+ "version": "0.6.0",
4
4
  "description": "Bedrock utilities for model creation.",
5
5
  "type": "module",
6
6
  "scripts": {
package/src/schema.js CHANGED
@@ -7,6 +7,7 @@ import { serializeOptions } from './serialization';
7
7
  import { applySlug } from './slug';
8
8
  import { applySearch } from './search';
9
9
  import { applyAssign } from './assign';
10
+ import { applyUpsert } from './upsert';
10
11
  import { applyHydrate } from './hydrate';
11
12
  import { applyInclude } from './include';
12
13
  import { applySoftDelete } from './soft-delete';
@@ -61,6 +62,7 @@ export function createSchema(definition, options = {}) {
61
62
  applyInclude(schema);
62
63
  applyHydrate(schema);
63
64
  applyAssign(schema);
65
+ applyUpsert(schema);
64
66
  applySlug(schema);
65
67
 
66
68
  return schema;
package/src/search.js CHANGED
@@ -18,6 +18,7 @@ export function applySearch(schema, definition) {
18
18
  validateDefinition(definition);
19
19
  validateSearchFields(schema, definition);
20
20
  applySearchCache(schema, definition);
21
+ applySearchSync(schema, definition);
21
22
 
22
23
  const { query: searchQuery, fields: searchFields } = definition.search || {};
23
24
 
@@ -384,13 +385,14 @@ function validateSearchFields(schema, definition) {
384
385
  function createCacheFields(schema, definition) {
385
386
  for (let [cachedField, def] of Object.entries(definition.search.cache)) {
386
387
  // Fall back to string type for virtuals or not defined.
387
- const { type = 'String' } = def;
388
+ const { type = 'String', path, ...rest } = def;
389
+
388
390
  schema.add({
389
391
  [cachedField]: type,
390
392
  });
391
393
  schema.obj[cachedField] = {
392
394
  type,
393
- readAccess: 'none',
395
+ ...rest,
394
396
  };
395
397
  }
396
398
  }
@@ -414,6 +416,32 @@ function applyCacheHook(schema, definition) {
414
416
  });
415
417
  }
416
418
 
419
+ // Search field syncing
420
+
421
+ function applySearchSync(schema, definition) {
422
+ if (!definition.search?.sync) {
423
+ return;
424
+ }
425
+
426
+ schema.post('save', async function postSave() {
427
+ for (let entry of definition.search.sync) {
428
+ const { ref, path } = entry;
429
+ const Model = mongoose.models[ref];
430
+ const docs = await Model.find({
431
+ [path]: this.id,
432
+ });
433
+
434
+ await Promise.all(
435
+ docs.map(async (doc) => {
436
+ await doc.save();
437
+ })
438
+ );
439
+ }
440
+ });
441
+ }
442
+
443
+ // Utils
444
+
417
445
  function isForeignField(schema, path) {
418
446
  if (!path.includes('.')) {
419
447
  return false;
package/src/upsert.js ADDED
@@ -0,0 +1,18 @@
1
+ export function applyUpsert(schema) {
2
+ // Note: Intentionally avoiding the findOneAndUpdate approach here
3
+ // as this will prevent hooks from being run on the document. This
4
+ // means however that we cannot always return a query here as the
5
+ // operations are inherently different.
6
+
7
+ schema.static('findOrCreate', async function findOrCreate(query, fields) {
8
+ fields ||= query;
9
+
10
+ let doc = await this.findOne(query);
11
+
12
+ if (!doc) {
13
+ doc = await this.create(fields);
14
+ }
15
+
16
+ return doc;
17
+ });
18
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.js"],"names":[],"mappings":"AAqBA;;;;;;;GAOG;AACH,yCAJW,MAAM,YACN,SAAS,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAwChC;AAED,iEAsBC"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.js"],"names":[],"mappings":"AAsBA;;;;;;;GAOG;AACH,yCAJW,MAAM,YACN,SAAS,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAyChC;AAED,iEAsBC"}
@@ -1 +1 @@
1
- {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.js"],"names":[],"mappings":"AAgBA,gEAyDC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyBC"}
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.js"],"names":[],"mappings":"AAgBA,gEA0DC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyBC"}
@@ -0,0 +1,2 @@
1
+ export function applyUpsert(schema: any): void;
2
+ //# sourceMappingURL=upsert.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upsert.d.ts","sourceRoot":"","sources":["../src/upsert.js"],"names":[],"mappings":"AAAA,+CAiBC"}