@bedrockio/model 0.1.17 → 0.1.19
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/dist/cjs/assign.js +1 -1
- package/dist/cjs/include.js +16 -3
- package/dist/cjs/search.js +1 -1
- package/dist/cjs/serialization.js +2 -2
- package/dist/cjs/utils.js +50 -34
- package/package.json +1 -1
- package/src/assign.js +2 -2
- package/src/include.js +18 -4
- package/src/search.js +2 -2
- package/src/serialization.js +3 -3
- package/src/utils.js +48 -30
- package/types/utils.d.ts +2 -2
- package/types/utils.d.ts.map +1 -1
package/dist/cjs/assign.js
CHANGED
|
@@ -28,7 +28,7 @@ function unsetReferenceFields(fields, schema = {}) {
|
|
|
28
28
|
if (!value && (0, _utils.isReferenceField)(schema, key)) {
|
|
29
29
|
fields[key] = undefined;
|
|
30
30
|
} else if (value && typeof value === 'object') {
|
|
31
|
-
unsetReferenceFields(value, (0, _utils.
|
|
31
|
+
unsetReferenceFields(value, (0, _utils.getField)(schema, key));
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
}
|
package/dist/cjs/include.js
CHANGED
|
@@ -218,7 +218,7 @@ function setNodePath(node, options) {
|
|
|
218
218
|
let halt = false;
|
|
219
219
|
for (let [key, type] of resolvePaths(schema, str)) {
|
|
220
220
|
if (type === 'real') {
|
|
221
|
-
const field = (0, _utils.
|
|
221
|
+
const field = (0, _utils.getInnerField)(schema.obj, key);
|
|
222
222
|
// Only exclude the field if the match is exact, ie:
|
|
223
223
|
// -name - Exclude "name"
|
|
224
224
|
// -user.name - Implies population of "user" but exclude "user.name",
|
|
@@ -256,8 +256,8 @@ function resolvePaths(schema, str) {
|
|
|
256
256
|
source = source.replaceAll('\\*', '[^.]+');
|
|
257
257
|
source = `^${source}$`;
|
|
258
258
|
const reg = RegExp(source);
|
|
259
|
-
paths =
|
|
260
|
-
return
|
|
259
|
+
paths = getSchemaPaths(schema).filter(path => {
|
|
260
|
+
return reg.test(path);
|
|
261
261
|
});
|
|
262
262
|
} else {
|
|
263
263
|
paths = [str];
|
|
@@ -265,4 +265,17 @@ function resolvePaths(schema, str) {
|
|
|
265
265
|
return paths.map(path => {
|
|
266
266
|
return [path, schema.pathType(path)];
|
|
267
267
|
});
|
|
268
|
+
}
|
|
269
|
+
function getSchemaPaths(schema) {
|
|
270
|
+
return Object.entries(schema.paths || {}).flatMap(([key, schema]) => {
|
|
271
|
+
if (key.startsWith('_')) {
|
|
272
|
+
return [];
|
|
273
|
+
} else if (schema.schema) {
|
|
274
|
+
return getSchemaPaths(schema.schema).map(path => {
|
|
275
|
+
return [key, path].join('.');
|
|
276
|
+
});
|
|
277
|
+
} else {
|
|
278
|
+
return [key];
|
|
279
|
+
}
|
|
280
|
+
});
|
|
268
281
|
}
|
package/dist/cjs/search.js
CHANGED
|
@@ -227,7 +227,7 @@ function normalizeQuery(query, schema, root = {}, rootPath = []) {
|
|
|
227
227
|
root[path.join('.')] = mapOperatorQuery(value);
|
|
228
228
|
}
|
|
229
229
|
} else if (isNestedQuery(key, value)) {
|
|
230
|
-
normalizeQuery(value, (0, _utils.
|
|
230
|
+
normalizeQuery(value, (0, _utils.getField)(schema, key), root, path);
|
|
231
231
|
} else if (isRegexQuery(key, value)) {
|
|
232
232
|
root[path.join('.')] = parseRegexQuery(value);
|
|
233
233
|
} else if (isArrayQuery(key, value)) {
|
|
@@ -28,7 +28,7 @@ function transformField(obj, field, options) {
|
|
|
28
28
|
if (!isAllowedField(key, field, options)) {
|
|
29
29
|
delete obj[key];
|
|
30
30
|
} else {
|
|
31
|
-
transformField(val, (0, _utils.
|
|
31
|
+
transformField(val, (0, _utils.getInnerField)(field, key), options);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
}
|
|
@@ -44,7 +44,7 @@ function isAllowedField(key, field, options) {
|
|
|
44
44
|
} else {
|
|
45
45
|
const {
|
|
46
46
|
readAccess
|
|
47
|
-
} = (0, _utils.
|
|
47
|
+
} = (0, _utils.getField)(field, key);
|
|
48
48
|
try {
|
|
49
49
|
return (0, _access.hasReadAccess)(readAccess, options);
|
|
50
50
|
} catch {
|
package/dist/cjs/utils.js
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.getField = getField;
|
|
7
|
+
exports.getInnerField = getInnerField;
|
|
6
8
|
exports.isDateField = isDateField;
|
|
7
9
|
exports.isMongooseSchema = isMongooseSchema;
|
|
8
10
|
exports.isNumberField = isNumberField;
|
|
9
11
|
exports.isReferenceField = isReferenceField;
|
|
10
12
|
exports.isSchemaTypedef = isSchemaTypedef;
|
|
11
|
-
exports.resolveField = resolveField;
|
|
12
|
-
exports.resolveInnerField = resolveInnerField;
|
|
13
13
|
var _mongoose = _interopRequireDefault(require("mongoose"));
|
|
14
14
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
15
|
function isMongooseSchema(obj) {
|
|
@@ -27,47 +27,63 @@ function isNumberField(obj, path) {
|
|
|
27
27
|
function isType(obj, path, test) {
|
|
28
28
|
const {
|
|
29
29
|
type
|
|
30
|
-
} =
|
|
30
|
+
} = getInnerField(obj, path);
|
|
31
31
|
return type === test || type === _mongoose.default.Schema.Types[test];
|
|
32
32
|
}
|
|
33
33
|
function isSchemaTypedef(arg) {
|
|
34
34
|
// Has a type defined and is not a literal type field.
|
|
35
|
-
return arg?.type && !arg.type?.type;
|
|
35
|
+
return !!arg?.type && !arg.type?.type;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
// Gets the schema "field". For a structure like below:
|
|
39
|
+
// {
|
|
40
|
+
// products: {
|
|
41
|
+
// type: [
|
|
42
|
+
// {
|
|
43
|
+
// inventory: {
|
|
44
|
+
// type: [
|
|
45
|
+
// {
|
|
46
|
+
// type: 'Number',
|
|
47
|
+
// },
|
|
48
|
+
// ],
|
|
49
|
+
// writeAccess: 'none',
|
|
50
|
+
// },
|
|
51
|
+
// },
|
|
52
|
+
// ],
|
|
53
|
+
// },
|
|
54
|
+
// }
|
|
55
|
+
//
|
|
56
|
+
// Given a path "products.inventory" it will return the inner
|
|
57
|
+
// "inventory" field. It must traverse into arrays and other mongoose
|
|
58
|
+
// schemas along the way except for the final field.
|
|
59
|
+
function getField(obj, path) {
|
|
60
|
+
let field = obj;
|
|
61
|
+
if (typeof path === 'string') {
|
|
62
|
+
path = path.split('.');
|
|
45
63
|
}
|
|
46
|
-
|
|
64
|
+
path.forEach((key, i) => {
|
|
65
|
+
field = field[key];
|
|
66
|
+
if (i < path.length - 1) {
|
|
67
|
+
field = resolveInnerField(field);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
return field || {};
|
|
47
71
|
}
|
|
48
72
|
|
|
49
|
-
// The same as
|
|
50
|
-
//
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
typedef = typedef.type[0];
|
|
55
|
-
}
|
|
56
|
-
return typedef;
|
|
73
|
+
// The same as getField but traverses into the final field
|
|
74
|
+
// as well. In the above example this will return:
|
|
75
|
+
// { type: 'Number' }, given "product.inventory"
|
|
76
|
+
function getInnerField(obj, path) {
|
|
77
|
+
return resolveInnerField(getField(obj, path));
|
|
57
78
|
}
|
|
58
|
-
function
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
} else {
|
|
67
|
-
typedef = type[key];
|
|
68
|
-
}
|
|
69
|
-
} else {
|
|
70
|
-
typedef = obj[key];
|
|
79
|
+
function resolveInnerField(field) {
|
|
80
|
+
if (Array.isArray(field?.type)) {
|
|
81
|
+
field = field.type[0];
|
|
82
|
+
}
|
|
83
|
+
if (field?.type instanceof _mongoose.default.Schema) {
|
|
84
|
+
field = field.type.obj;
|
|
85
|
+
} else if (field instanceof _mongoose.default.Schema) {
|
|
86
|
+
field = field.obj;
|
|
71
87
|
}
|
|
72
|
-
return
|
|
88
|
+
return field;
|
|
73
89
|
}
|
package/package.json
CHANGED
package/src/assign.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isPlainObject } from 'lodash';
|
|
2
2
|
|
|
3
|
-
import { isReferenceField,
|
|
3
|
+
import { isReferenceField, getField } from './utils';
|
|
4
4
|
|
|
5
5
|
export function applyAssign(schema) {
|
|
6
6
|
schema.method('assign', function assign(fields) {
|
|
@@ -24,7 +24,7 @@ function unsetReferenceFields(fields, schema = {}) {
|
|
|
24
24
|
if (!value && isReferenceField(schema, key)) {
|
|
25
25
|
fields[key] = undefined;
|
|
26
26
|
} else if (value && typeof value === 'object') {
|
|
27
|
-
unsetReferenceFields(value,
|
|
27
|
+
unsetReferenceFields(value, getField(schema, key));
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
}
|
package/src/include.js
CHANGED
|
@@ -2,7 +2,7 @@ import mongoose from 'mongoose';
|
|
|
2
2
|
import { escapeRegExp } from 'lodash';
|
|
3
3
|
import yd from '@bedrockio/yada';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { getInnerField, isSchemaTypedef } from './utils';
|
|
6
6
|
import { POPULATE_MAX_DEPTH } from './const';
|
|
7
7
|
|
|
8
8
|
// @ts-ignore
|
|
@@ -202,7 +202,7 @@ function setNodePath(node, options) {
|
|
|
202
202
|
|
|
203
203
|
for (let [key, type] of resolvePaths(schema, str)) {
|
|
204
204
|
if (type === 'real') {
|
|
205
|
-
const field =
|
|
205
|
+
const field = getInnerField(schema.obj, key);
|
|
206
206
|
// Only exclude the field if the match is exact, ie:
|
|
207
207
|
// -name - Exclude "name"
|
|
208
208
|
// -user.name - Implies population of "user" but exclude "user.name",
|
|
@@ -242,8 +242,8 @@ function resolvePaths(schema, str) {
|
|
|
242
242
|
source = source.replaceAll('\\*', '[^.]+');
|
|
243
243
|
source = `^${source}$`;
|
|
244
244
|
const reg = RegExp(source);
|
|
245
|
-
paths =
|
|
246
|
-
return
|
|
245
|
+
paths = getSchemaPaths(schema).filter((path) => {
|
|
246
|
+
return reg.test(path);
|
|
247
247
|
});
|
|
248
248
|
} else {
|
|
249
249
|
paths = [str];
|
|
@@ -252,3 +252,17 @@ function resolvePaths(schema, str) {
|
|
|
252
252
|
return [path, schema.pathType(path)];
|
|
253
253
|
});
|
|
254
254
|
}
|
|
255
|
+
|
|
256
|
+
function getSchemaPaths(schema) {
|
|
257
|
+
return Object.entries(schema.paths || {}).flatMap(([key, schema]) => {
|
|
258
|
+
if (key.startsWith('_')) {
|
|
259
|
+
return [];
|
|
260
|
+
} else if (schema.schema) {
|
|
261
|
+
return getSchemaPaths(schema.schema).map((path) => {
|
|
262
|
+
return [key, path].join('.');
|
|
263
|
+
});
|
|
264
|
+
} else {
|
|
265
|
+
return [key];
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
}
|
package/src/search.js
CHANGED
|
@@ -3,7 +3,7 @@ import logger from '@bedrockio/logger';
|
|
|
3
3
|
import mongoose from 'mongoose';
|
|
4
4
|
import { pick, isEmpty, isPlainObject } from 'lodash';
|
|
5
5
|
|
|
6
|
-
import { isDateField, isNumberField,
|
|
6
|
+
import { isDateField, isNumberField, getField } from './utils';
|
|
7
7
|
import { SEARCH_DEFAULTS } from './const';
|
|
8
8
|
import { OBJECT_ID_SCHEMA } from './validation';
|
|
9
9
|
import { debug } from './env';
|
|
@@ -239,7 +239,7 @@ function normalizeQuery(query, schema, root = {}, rootPath = []) {
|
|
|
239
239
|
root[path.join('.')] = mapOperatorQuery(value);
|
|
240
240
|
}
|
|
241
241
|
} else if (isNestedQuery(key, value)) {
|
|
242
|
-
normalizeQuery(value,
|
|
242
|
+
normalizeQuery(value, getField(schema, key), root, path);
|
|
243
243
|
} else if (isRegexQuery(key, value)) {
|
|
244
244
|
root[path.join('.')] = parseRegexQuery(value);
|
|
245
245
|
} else if (isArrayQuery(key, value)) {
|
package/src/serialization.js
CHANGED
|
@@ -2,7 +2,7 @@ import { isPlainObject } from 'lodash';
|
|
|
2
2
|
|
|
3
3
|
import { checkSelects } from './include';
|
|
4
4
|
import { hasReadAccess } from './access';
|
|
5
|
-
import {
|
|
5
|
+
import { getField, getInnerField } from './utils';
|
|
6
6
|
|
|
7
7
|
export const serializeOptions = {
|
|
8
8
|
getters: true,
|
|
@@ -24,7 +24,7 @@ function transformField(obj, field, options) {
|
|
|
24
24
|
if (!isAllowedField(key, field, options)) {
|
|
25
25
|
delete obj[key];
|
|
26
26
|
} else {
|
|
27
|
-
transformField(val,
|
|
27
|
+
transformField(val, getInnerField(field, key), options);
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
}
|
|
@@ -39,7 +39,7 @@ function isAllowedField(key, field, options) {
|
|
|
39
39
|
// to false and should not be exposed.
|
|
40
40
|
return false;
|
|
41
41
|
} else {
|
|
42
|
-
const { readAccess } =
|
|
42
|
+
const { readAccess } = getField(field, key);
|
|
43
43
|
try {
|
|
44
44
|
return hasReadAccess(readAccess, options);
|
|
45
45
|
} catch {
|
package/src/utils.js
CHANGED
|
@@ -17,47 +17,65 @@ export function isNumberField(obj, path) {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
function isType(obj, path, test) {
|
|
20
|
-
const { type } =
|
|
20
|
+
const { type } = getInnerField(obj, path);
|
|
21
21
|
return type === test || type === mongoose.Schema.Types[test];
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export function isSchemaTypedef(arg) {
|
|
25
25
|
// Has a type defined and is not a literal type field.
|
|
26
|
-
return arg?.type && !arg.type?.type;
|
|
26
|
+
return !!arg?.type && !arg.type?.type;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
// Gets the schema "field". For a structure like below:
|
|
30
|
+
// {
|
|
31
|
+
// products: {
|
|
32
|
+
// type: [
|
|
33
|
+
// {
|
|
34
|
+
// inventory: {
|
|
35
|
+
// type: [
|
|
36
|
+
// {
|
|
37
|
+
// type: 'Number',
|
|
38
|
+
// },
|
|
39
|
+
// ],
|
|
40
|
+
// writeAccess: 'none',
|
|
41
|
+
// },
|
|
42
|
+
// },
|
|
43
|
+
// ],
|
|
44
|
+
// },
|
|
45
|
+
// }
|
|
46
|
+
//
|
|
47
|
+
// Given a path "products.inventory" it will return the inner
|
|
48
|
+
// "inventory" field. It must traverse into arrays and other mongoose
|
|
49
|
+
// schemas along the way except for the final field.
|
|
50
|
+
export function getField(obj, path) {
|
|
51
|
+
let field = obj;
|
|
52
|
+
if (typeof path === 'string') {
|
|
53
|
+
path = path.split('.');
|
|
36
54
|
}
|
|
37
|
-
|
|
55
|
+
path.forEach((key, i) => {
|
|
56
|
+
field = field[key];
|
|
57
|
+
if (i < path.length - 1) {
|
|
58
|
+
field = resolveInnerField(field);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
return field || {};
|
|
38
62
|
}
|
|
39
63
|
|
|
40
|
-
// The same as
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
typedef = typedef.type[0];
|
|
46
|
-
}
|
|
47
|
-
return typedef;
|
|
64
|
+
// The same as getField but traverses into the final field
|
|
65
|
+
// as well. In the above example this will return:
|
|
66
|
+
// { type: 'Number' }, given "product.inventory"
|
|
67
|
+
export function getInnerField(obj, path) {
|
|
68
|
+
return resolveInnerField(getField(obj, path));
|
|
48
69
|
}
|
|
49
70
|
|
|
50
|
-
function
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
} else {
|
|
60
|
-
typedef = obj[key];
|
|
71
|
+
function resolveInnerField(field) {
|
|
72
|
+
if (Array.isArray(field?.type)) {
|
|
73
|
+
field = field.type[0];
|
|
74
|
+
}
|
|
75
|
+
if (field?.type instanceof mongoose.Schema) {
|
|
76
|
+
field = field.type.obj;
|
|
77
|
+
} else if (field instanceof mongoose.Schema) {
|
|
78
|
+
field = field.obj;
|
|
61
79
|
}
|
|
62
|
-
return
|
|
80
|
+
return field;
|
|
63
81
|
}
|
package/types/utils.d.ts
CHANGED
|
@@ -3,6 +3,6 @@ export function isReferenceField(obj: any, path: any): boolean;
|
|
|
3
3
|
export function isDateField(obj: any, path: any): boolean;
|
|
4
4
|
export function isNumberField(obj: any, path: any): boolean;
|
|
5
5
|
export function isSchemaTypedef(arg: any): boolean;
|
|
6
|
-
export function
|
|
7
|
-
export function
|
|
6
|
+
export function getField(obj: any, path: any): any;
|
|
7
|
+
export function getInnerField(obj: any, path: any): any;
|
|
8
8
|
//# sourceMappingURL=utils.d.ts.map
|
package/types/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.js"],"names":[],"mappings":"AAEA,oDAEC;AAED,+DAEC;AAED,0DAEC;AAED,4DAEC;AAOD,mDAGC;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.js"],"names":[],"mappings":"AAEA,oDAEC;AAED,+DAEC;AAED,0DAEC;AAED,4DAEC;AAOD,mDAGC;AAuBD,mDAYC;AAKD,wDAEC"}
|