@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 +9 -0
- package/README.md +23 -2
- package/dist/cjs/load.js +1 -0
- package/dist/cjs/search.js +0 -21
- package/dist/cjs/soft-delete.js +10 -1
- package/package.json +1 -1
- package/src/load.js +1 -0
- package/src/search.js +0 -23
- package/src/soft-delete.js +10 -1
- package/types/generated/load.d.ts +4 -1
- package/types/generated/load.d.ts.map +1 -1
- package/types/generated/soft-delete.d.ts.map +1 -1
package/CHANGELOG.md
CHANGED
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);
|
package/dist/cjs/search.js
CHANGED
|
@@ -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) {
|
package/dist/cjs/soft-delete.js
CHANGED
|
@@ -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
|
-
|
|
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
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) {
|
package/src/soft-delete.js
CHANGED
|
@@ -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
|
-
|
|
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):
|
|
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
|
|
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,
|
|
1
|
+
{"version":3,"file":"soft-delete.d.ts","sourceRoot":"","sources":["../../src/soft-delete.js"],"names":[],"mappings":"AAMA,mDAIC;AAED,0DA0BC"}
|