@bedrockio/model 0.21.2 → 0.22.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 0.22.0
2
+
3
+ - Removed regex parsing in search.
4
+
5
+ ## 0.21.3
6
+
7
+ - Fixed issue with middleware hook patch.
8
+ - Output model name in UniqueConstraintError.
9
+
1
10
  ## 0.21.2
2
11
 
3
12
  - Export `loadDefinition` and readme updates.
package/README.md CHANGED
@@ -603,8 +603,6 @@ Input to `search` will execute the optimal mongo query and supports several
603
603
  advanced features:
604
604
 
605
605
  - Array fields will be executed using `$in`.
606
- - Javascript regular expressions will map to `$regex` which allows for
607
- [more advanced PCRE compatible features](https://docs.mongodb.com/manual/reference/operator/query/regex/#pcre-vs-javascript).
608
606
  - Nested objects will be automatically flattened to query subdocuments:
609
607
 
610
608
  ```
@@ -1183,6 +1181,17 @@ const user = await User.find({
1183
1181
  });
1184
1182
  ```
1185
1183
 
1184
+ #### Include with Create
1185
+
1186
+ Includes are not allowed in create operations by default. Instead use the `createWithInclude` method:
1187
+
1188
+ ```js
1189
+ const user = await User.createWithInclude({
1190
+ firstName: 'Frank',
1191
+ include: 'profile',
1192
+ });
1193
+ ```
1194
+
1186
1195
  #### Validation with includes
1187
1196
 
1188
1197
  The [validation](#validation) methods additionally allow `include` as a special
@@ -1205,6 +1214,18 @@ The `getSearchValidation` will allow the `include` property to be passed,
1205
1214
  letting the client populate documents as they require. Note that the fields a
1206
1215
  client is able to include is subject to [access control](#access-control).
1207
1216
 
1217
+ Additionally the `getIncludeValidation` exports the includes as a standalone schema so that it can be used ad-hoc in routes and [composed with other custom validations](https://github.com/bedrockio/yada#append).
1218
+
1219
+
1220
+ |Method|Includes|
1221
+ |---|---|
1222
+ |getSearchValiation|default|
1223
+ |getIncludeValidation|default|
1224
+ |getCreateValidation|optional|
1225
+ |getUpdateValidation|optional|
1226
+
1227
+
1228
+
1208
1229
  #### Other Differences with Populate
1209
1230
 
1210
1231
  Calling `populate` on a Mongoose document will always load the current data. In
package/dist/cjs/load.js CHANGED
@@ -36,6 +36,7 @@ function loadModel(definition, name) {
36
36
  * Loads all model definitions in the given directory.
37
37
  * Returns the full loaded model set.
38
38
  * @param {string} dir
39
+ * @returns {{ [name: string]: mongoose.Model<any> }}
39
40
  */
40
41
  function loadModelDir(dir) {
41
42
  const files = _fs.default.readdirSync(dir);
@@ -351,8 +351,6 @@ function hasTextIndex(schema) {
351
351
  // handling specialed query syntax:
352
352
  // ranges:
353
353
  // path: { min: n, max n }
354
- // regex:
355
- // path: "/reg/"
356
354
  // array:
357
355
  // path; [1,2,3]
358
356
  function normalizeQuery(query, schema, root = {}, rootPath = []) {
@@ -364,8 +362,6 @@ function normalizeQuery(query, schema, root = {}, rootPath = []) {
364
362
  }
365
363
  } else if (isNestedQuery(key, value)) {
366
364
  normalizeQuery(value, (0, _utils.getField)(schema, key), root, path);
367
- } else if (isRegexQuery(key, value)) {
368
- root[path.join('.')] = parseRegexQuery(value);
369
365
  } else if (isArrayQuery(key, value)) {
370
366
  root[path.join('.')] = {
371
367
  $in: value
@@ -420,23 +416,6 @@ function isInclude(str) {
420
416
  return str === 'include';
421
417
  }
422
418
 
423
- // Regex queries
424
-
425
- const REGEX_QUERY = /^\/(.+)\/(\w*)$/;
426
- function isRegexQuery(key, value) {
427
- return REGEX_QUERY.test(value);
428
- }
429
- function parseRegexQuery(str) {
430
- // Note that using the $options syntax allows for PCRE features
431
- // that aren't supported in Javascript as compared to RegExp(...):
432
- // https://docs.mongodb.com/manual/reference/operator/query/regex/#pcre-vs-javascript
433
- const [, $regex, $options] = str.match(REGEX_QUERY);
434
- return {
435
- $regex,
436
- $options
437
- };
438
- }
439
-
440
419
  // Search field caching
441
420
 
442
421
  function validateSearchFields(schema, definition) {
@@ -35,8 +35,11 @@ async function assertUnique(options) {
35
35
  const exists = await model.exists(query);
36
36
  if (exists) {
37
37
  const message = getUniqueErrorMessage(field, options);
38
+ const {
39
+ modelName
40
+ } = model;
38
41
  throw new _errors.UniqueConstraintError(message, {
39
- model,
42
+ modelName,
40
43
  field,
41
44
  value
42
45
  });
@@ -407,6 +410,12 @@ function applyHookPatch(schema) {
407
410
  const schemaPre = schema.pre;
408
411
  const schemaPost = schema.post;
409
412
  schema.pre = function (name, fn) {
413
+ // Newer Mongoose versions appear to use internal plugins
414
+ // that pass objects instead of functions here (not documented)
415
+ // so abort and pass to internal handler.
416
+ if (typeof fn !== 'function') {
417
+ return schemaPre.apply(this, arguments);
418
+ }
410
419
  if (name === 'restore') {
411
420
  // Document hooks
412
421
  schemaPre.call(this, 'save', getPreDocRestore(fn));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bedrockio/model",
3
- "version": "0.21.2",
3
+ "version": "0.22.0",
4
4
  "description": "Bedrock utilities for model creation.",
5
5
  "type": "module",
6
6
  "scripts": {
package/src/load.js CHANGED
@@ -30,6 +30,7 @@ export function loadModel(definition, name) {
30
30
  * Loads all model definitions in the given directory.
31
31
  * Returns the full loaded model set.
32
32
  * @param {string} dir
33
+ * @returns {{ [name: string]: mongoose.Model<any> }}
33
34
  */
34
35
  export function loadModelDir(dir) {
35
36
  const files = fs.readdirSync(dir);
package/src/search.js CHANGED
@@ -398,8 +398,6 @@ function hasTextIndex(schema) {
398
398
  // handling specialed query syntax:
399
399
  // ranges:
400
400
  // path: { min: n, max n }
401
- // regex:
402
- // path: "/reg/"
403
401
  // array:
404
402
  // path; [1,2,3]
405
403
  function normalizeQuery(query, schema, root = {}, rootPath = []) {
@@ -411,8 +409,6 @@ function normalizeQuery(query, schema, root = {}, rootPath = []) {
411
409
  }
412
410
  } else if (isNestedQuery(key, value)) {
413
411
  normalizeQuery(value, getField(schema, key), root, path);
414
- } else if (isRegexQuery(key, value)) {
415
- root[path.join('.')] = parseRegexQuery(value);
416
412
  } else if (isArrayQuery(key, value)) {
417
413
  root[path.join('.')] = { $in: value };
418
414
  } else if (isEmptyArrayQuery(schema, key, value)) {
@@ -475,25 +471,6 @@ function isInclude(str) {
475
471
  return str === 'include';
476
472
  }
477
473
 
478
- // Regex queries
479
-
480
- const REGEX_QUERY = /^\/(.+)\/(\w*)$/;
481
-
482
- function isRegexQuery(key, value) {
483
- return REGEX_QUERY.test(value);
484
- }
485
-
486
- function parseRegexQuery(str) {
487
- // Note that using the $options syntax allows for PCRE features
488
- // that aren't supported in Javascript as compared to RegExp(...):
489
- // https://docs.mongodb.com/manual/reference/operator/query/regex/#pcre-vs-javascript
490
- const [, $regex, $options] = str.match(REGEX_QUERY);
491
- return {
492
- $regex,
493
- $options,
494
- };
495
- }
496
-
497
474
  // Search field caching
498
475
 
499
476
  function validateSearchFields(schema, definition) {
@@ -28,8 +28,10 @@ export async function assertUnique(options) {
28
28
 
29
29
  if (exists) {
30
30
  const message = getUniqueErrorMessage(field, options);
31
+ const { modelName } = model;
32
+
31
33
  throw new UniqueConstraintError(message, {
32
- model,
34
+ modelName,
33
35
  field,
34
36
  value,
35
37
  });
@@ -454,6 +456,13 @@ function applyHookPatch(schema) {
454
456
  const schemaPost = schema.post;
455
457
 
456
458
  schema.pre = function (name, fn) {
459
+ // Newer Mongoose versions appear to use internal plugins
460
+ // that pass objects instead of functions here (not documented)
461
+ // so abort and pass to internal handler.
462
+ if (typeof fn !== 'function') {
463
+ return schemaPre.apply(this, arguments);
464
+ }
465
+
457
466
  if (name === 'restore') {
458
467
  // Document hooks
459
468
  schemaPre.call(this, 'save', getPreDocRestore(fn));
@@ -9,8 +9,11 @@ export function loadModel(definition: object, name: string): any;
9
9
  * Loads all model definitions in the given directory.
10
10
  * Returns the full loaded model set.
11
11
  * @param {string} dir
12
+ * @returns {{ [name: string]: mongoose.Model<any> }}
12
13
  */
13
- export function loadModelDir(dir: string): mongoose.Models;
14
+ export function loadModelDir(dir: string): {
15
+ [name: string]: mongoose.Model<any>;
16
+ };
14
17
  /**
15
18
  * Loads the schema from a .json or .jsonc file.
16
19
  * @param {string} name - The model or schema name.
@@ -1 +1 @@
1
- {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/load.js"],"names":[],"mappings":"AAUA;;;;;GAKG;AACH,sCAJW,MAAM,QACN,MAAM,OAahB;AAED;;;;GAIG;AACH,kCAFW,MAAM,mBAoBhB;AAED;;;;GAIG;AACH,iCAHW,MAAM,QACN,MAAM;;;;;;;;;;;;;;;;GAKhB;AAKD,yDAIC;qBAhEoB,UAAU"}
1
+ {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/load.js"],"names":[],"mappings":"AAUA;;;;;GAKG;AACH,sCAJW,MAAM,QACN,MAAM,OAahB;AAED;;;;;GAKG;AACH,kCAHW,MAAM,GACJ;IAAE,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;CAAE,CAoBnD;AAED;;;;GAIG;AACH,iCAHW,MAAM,QACN,MAAM;;;;;;;;;;;;;;;;GAKhB;AAKD,yDAIC;qBAjEoB,UAAU"}
@@ -1 +1 @@
1
- {"version":3,"file":"soft-delete.d.ts","sourceRoot":"","sources":["../../src/soft-delete.js"],"names":[],"mappings":"AAMA,mDAIC;AAED,0DAwBC"}
1
+ {"version":3,"file":"soft-delete.d.ts","sourceRoot":"","sources":["../../src/soft-delete.js"],"names":[],"mappings":"AAMA,mDAIC;AAED,0DA0BC"}