@bedrockio/model 0.3.1 → 0.4.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/dist/cjs/assign.js +4 -1
- package/dist/cjs/hydrate.js +33 -0
- package/dist/cjs/schema.js +2 -0
- package/dist/cjs/validation.js +5 -2
- package/package.json +4 -4
- package/src/assign.js +3 -1
- package/src/hydrate.js +28 -0
- package/src/schema.js +2 -0
- package/src/validation.js +5 -2
- package/types/assign.d.ts.map +1 -1
- package/types/hydrate.d.ts +2 -0
- package/types/hydrate.d.ts.map +1 -0
- package/types/load.d.ts +67 -1
- package/types/load.d.ts.map +1 -1
- package/types/schema.d.ts +7 -4
- package/types/schema.d.ts.map +1 -1
- package/types/validation.d.ts.map +1 -1
package/dist/cjs/assign.js
CHANGED
|
@@ -5,14 +5,15 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.applyAssign = applyAssign;
|
|
7
7
|
var _lodash = require("lodash");
|
|
8
|
+
var _mongoose = _interopRequireDefault(require("mongoose"));
|
|
8
9
|
var _utils = require("./utils");
|
|
10
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
9
11
|
function applyAssign(schema) {
|
|
10
12
|
schema.method('assign', function assign(fields) {
|
|
11
13
|
unsetReferenceFields(fields, schema.obj);
|
|
12
14
|
for (let [path, value] of Object.entries(flattenObject(fields))) {
|
|
13
15
|
if (value === null) {
|
|
14
16
|
this.set(path, undefined);
|
|
15
|
-
this.markModified(path);
|
|
16
17
|
} else {
|
|
17
18
|
this.set(path, value);
|
|
18
19
|
}
|
|
@@ -27,6 +28,8 @@ function unsetReferenceFields(fields, schema = {}) {
|
|
|
27
28
|
for (let [key, value] of Object.entries(fields)) {
|
|
28
29
|
if (!value && (0, _utils.isReferenceField)(schema, key)) {
|
|
29
30
|
fields[key] = undefined;
|
|
31
|
+
} else if (value instanceof _mongoose.default.Document) {
|
|
32
|
+
fields[key] = value;
|
|
30
33
|
} else if (value && typeof value === 'object') {
|
|
31
34
|
unsetReferenceFields(value, (0, _utils.getField)(schema, key));
|
|
32
35
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.applyHydrate = applyHydrate;
|
|
7
|
+
var _mongoose = require("mongoose");
|
|
8
|
+
// Patching mongoose hydrate method to be less useless
|
|
9
|
+
// as it sets all input fields on the resulting document.
|
|
10
|
+
// Compare this to creating a new model which will only
|
|
11
|
+
// set the fields known to the schema. This results in:
|
|
12
|
+
//
|
|
13
|
+
// 1. Sending too much data down the wire
|
|
14
|
+
// 2. Potentially leaking sensitive data in aggregations.
|
|
15
|
+
|
|
16
|
+
function applyHydrate(schema) {
|
|
17
|
+
schema.static('hydrate', function hydrate(obj) {
|
|
18
|
+
return _mongoose.Model.hydrate.call(this, obj, getProjection(schema));
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Note that the mongoose docs imply that an array of
|
|
23
|
+
// strings will work for the projection, however this
|
|
24
|
+
// does not seem to work.
|
|
25
|
+
// https://mongoosejs.com/docs/7.x/docs/api/model.html
|
|
26
|
+
function getProjection(schema) {
|
|
27
|
+
const keys = Object.keys(schema.paths);
|
|
28
|
+
const result = {};
|
|
29
|
+
for (let key of keys) {
|
|
30
|
+
result[key] = true;
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
}
|
package/dist/cjs/schema.js
CHANGED
|
@@ -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 _hydrate = require("./hydrate");
|
|
15
16
|
var _include = require("./include");
|
|
16
17
|
var _softDelete = require("./soft-delete");
|
|
17
18
|
var _deleteHooks = require("./delete-hooks");
|
|
@@ -54,6 +55,7 @@ function createSchema(definition, options = {}) {
|
|
|
54
55
|
(0, _search.applySearch)(schema, definition);
|
|
55
56
|
(0, _disallowed.applyDisallowed)(schema);
|
|
56
57
|
(0, _include.applyInclude)(schema);
|
|
58
|
+
(0, _hydrate.applyHydrate)(schema);
|
|
57
59
|
(0, _assign.applyAssign)(schema);
|
|
58
60
|
(0, _slug.applySlug)(schema);
|
|
59
61
|
return schema;
|
package/dist/cjs/validation.js
CHANGED
|
@@ -282,11 +282,14 @@ function getSchemaForTypedef(typedef, options = {}) {
|
|
|
282
282
|
schema = getObjectSchema(type, options);
|
|
283
283
|
} else {
|
|
284
284
|
schema = getSchemaForType(type, options);
|
|
285
|
+
|
|
286
|
+
// Unsetting only allowed for primitive types.
|
|
287
|
+
if (allowUnset(typedef, options)) {
|
|
288
|
+
schema = _yada.default.allow(null, '', schema);
|
|
289
|
+
}
|
|
285
290
|
}
|
|
286
291
|
if (isRequired(typedef, options)) {
|
|
287
292
|
schema = schema.required();
|
|
288
|
-
} else if (allowUnset(typedef, options)) {
|
|
289
|
-
schema = _yada.default.allow(null, '', schema);
|
|
290
293
|
}
|
|
291
294
|
if (typedef.default && options.allowDefaultTags) {
|
|
292
295
|
// Tag the default value to allow OpenAPI description
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bedrockio/model",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Bedrock utilities for model creation.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@bedrockio/yada": "^1.0.40",
|
|
34
|
-
"mongoose": "^7.6.
|
|
34
|
+
"mongoose": "^7.6.13"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@babel/cli": "^7.20.7",
|
|
@@ -39,13 +39,13 @@
|
|
|
39
39
|
"@babel/preset-env": "^7.20.2",
|
|
40
40
|
"@bedrockio/prettier-config": "^1.0.2",
|
|
41
41
|
"@bedrockio/yada": "^1.0.40",
|
|
42
|
-
"@shelf/jest-mongodb": "^4.2
|
|
42
|
+
"@shelf/jest-mongodb": "^4.3.2",
|
|
43
43
|
"eslint": "^8.33.0",
|
|
44
44
|
"eslint-plugin-bedrock": "^1.0.26",
|
|
45
45
|
"jest": "^29.4.1",
|
|
46
46
|
"jest-environment-node": "^29.4.1",
|
|
47
47
|
"mongodb": "^6.5.0",
|
|
48
|
-
"mongoose": "
|
|
48
|
+
"mongoose": "7.6.13",
|
|
49
49
|
"prettier-eslint": "^15.0.1",
|
|
50
50
|
"typescript": "^4.9.5"
|
|
51
51
|
},
|
package/src/assign.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isPlainObject } from 'lodash';
|
|
2
|
+
import mongoose from 'mongoose';
|
|
2
3
|
|
|
3
4
|
import { isReferenceField, getField } from './utils';
|
|
4
5
|
|
|
@@ -8,7 +9,6 @@ export function applyAssign(schema) {
|
|
|
8
9
|
for (let [path, value] of Object.entries(flattenObject(fields))) {
|
|
9
10
|
if (value === null) {
|
|
10
11
|
this.set(path, undefined);
|
|
11
|
-
this.markModified(path);
|
|
12
12
|
} else {
|
|
13
13
|
this.set(path, value);
|
|
14
14
|
}
|
|
@@ -23,6 +23,8 @@ function unsetReferenceFields(fields, schema = {}) {
|
|
|
23
23
|
for (let [key, value] of Object.entries(fields)) {
|
|
24
24
|
if (!value && isReferenceField(schema, key)) {
|
|
25
25
|
fields[key] = undefined;
|
|
26
|
+
} else if (value instanceof mongoose.Document) {
|
|
27
|
+
fields[key] = value;
|
|
26
28
|
} else if (value && typeof value === 'object') {
|
|
27
29
|
unsetReferenceFields(value, getField(schema, key));
|
|
28
30
|
}
|
package/src/hydrate.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Model } from 'mongoose';
|
|
2
|
+
|
|
3
|
+
// Patching mongoose hydrate method to be less useless
|
|
4
|
+
// as it sets all input fields on the resulting document.
|
|
5
|
+
// Compare this to creating a new model which will only
|
|
6
|
+
// set the fields known to the schema. This results in:
|
|
7
|
+
//
|
|
8
|
+
// 1. Sending too much data down the wire
|
|
9
|
+
// 2. Potentially leaking sensitive data in aggregations.
|
|
10
|
+
|
|
11
|
+
export function applyHydrate(schema) {
|
|
12
|
+
schema.static('hydrate', function hydrate(obj) {
|
|
13
|
+
return Model.hydrate.call(this, obj, getProjection(schema));
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Note that the mongoose docs imply that an array of
|
|
18
|
+
// strings will work for the projection, however this
|
|
19
|
+
// does not seem to work.
|
|
20
|
+
// https://mongoosejs.com/docs/7.x/docs/api/model.html
|
|
21
|
+
function getProjection(schema) {
|
|
22
|
+
const keys = Object.keys(schema.paths);
|
|
23
|
+
const result = {};
|
|
24
|
+
for (let key of keys) {
|
|
25
|
+
result[key] = true;
|
|
26
|
+
}
|
|
27
|
+
return result;
|
|
28
|
+
}
|
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 { applyHydrate } from './hydrate';
|
|
10
11
|
import { applyInclude } from './include';
|
|
11
12
|
import { applySoftDelete } from './soft-delete';
|
|
12
13
|
import { applyDeleteHooks } from './delete-hooks';
|
|
@@ -58,6 +59,7 @@ export function createSchema(definition, options = {}) {
|
|
|
58
59
|
applySearch(schema, definition);
|
|
59
60
|
applyDisallowed(schema);
|
|
60
61
|
applyInclude(schema);
|
|
62
|
+
applyHydrate(schema);
|
|
61
63
|
applyAssign(schema);
|
|
62
64
|
applySlug(schema);
|
|
63
65
|
|
package/src/validation.js
CHANGED
|
@@ -297,12 +297,15 @@ function getSchemaForTypedef(typedef, options = {}) {
|
|
|
297
297
|
schema = getObjectSchema(type, options);
|
|
298
298
|
} else {
|
|
299
299
|
schema = getSchemaForType(type, options);
|
|
300
|
+
|
|
301
|
+
// Unsetting only allowed for primitive types.
|
|
302
|
+
if (allowUnset(typedef, options)) {
|
|
303
|
+
schema = yd.allow(null, '', schema);
|
|
304
|
+
}
|
|
300
305
|
}
|
|
301
306
|
|
|
302
307
|
if (isRequired(typedef, options)) {
|
|
303
308
|
schema = schema.required();
|
|
304
|
-
} else if (allowUnset(typedef, options)) {
|
|
305
|
-
schema = yd.allow(null, '', schema);
|
|
306
309
|
}
|
|
307
310
|
|
|
308
311
|
if (typedef.default && options.allowDefaultTags) {
|
package/types/assign.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assign.d.ts","sourceRoot":"","sources":["../src/assign.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"assign.d.ts","sourceRoot":"","sources":["../src/assign.js"],"names":[],"mappings":"AAKA,+CAWC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hydrate.d.ts","sourceRoot":"","sources":["../src/hydrate.js"],"names":[],"mappings":"AAUA,gDAIC"}
|
package/types/load.d.ts
CHANGED
|
@@ -4,7 +4,73 @@
|
|
|
4
4
|
* @param {string} name
|
|
5
5
|
* @returns mongoose.Model
|
|
6
6
|
*/
|
|
7
|
-
export function loadModel(definition: object, name: string): any
|
|
7
|
+
export function loadModel(definition: object, name: string): mongoose.Model<any, any, any, any, any, mongoose.Schema<any, mongoose.Model<any, any, any, any, any, any>, any, any, any, {
|
|
8
|
+
[x: string]: any;
|
|
9
|
+
}, {
|
|
10
|
+
autoIndex?: boolean;
|
|
11
|
+
autoCreate?: boolean;
|
|
12
|
+
bufferCommands?: boolean;
|
|
13
|
+
bufferTimeoutMS?: number;
|
|
14
|
+
capped?: number | boolean | {
|
|
15
|
+
size?: number;
|
|
16
|
+
max?: number;
|
|
17
|
+
autoIndexId?: boolean;
|
|
18
|
+
};
|
|
19
|
+
collation?: mongoose.mongo.CollationOptions;
|
|
20
|
+
collectionOptions?: mongoose.mongo.CreateCollectionOptions;
|
|
21
|
+
timeseries?: mongoose.mongo.TimeSeriesCollectionOptions;
|
|
22
|
+
expireAfterSeconds?: number;
|
|
23
|
+
expires?: string | number;
|
|
24
|
+
collection?: string;
|
|
25
|
+
discriminatorKey?: string;
|
|
26
|
+
excludeIndexes?: boolean;
|
|
27
|
+
id?: boolean;
|
|
28
|
+
_id?: boolean;
|
|
29
|
+
minimize?: boolean;
|
|
30
|
+
optimisticConcurrency?: boolean;
|
|
31
|
+
pluginTags?: string[];
|
|
32
|
+
read?: string;
|
|
33
|
+
writeConcern?: mongoose.mongo.WriteConcern;
|
|
34
|
+
safe?: boolean | {
|
|
35
|
+
w?: string | number;
|
|
36
|
+
wtimeout?: number;
|
|
37
|
+
j?: boolean;
|
|
38
|
+
};
|
|
39
|
+
shardKey?: Record<string, unknown>;
|
|
40
|
+
strict?: boolean | "throw";
|
|
41
|
+
strictQuery?: boolean | "throw";
|
|
42
|
+
toJSON: {
|
|
43
|
+
getters: boolean;
|
|
44
|
+
versionKey: boolean;
|
|
45
|
+
transform: (doc: any, ret: any, options: any) => void;
|
|
46
|
+
} | mongoose.ToObjectOptions<any>;
|
|
47
|
+
toObject: {
|
|
48
|
+
getters: boolean;
|
|
49
|
+
versionKey: boolean;
|
|
50
|
+
transform: (doc: any, ret: any, options: any) => void;
|
|
51
|
+
} | mongoose.ToObjectOptions<any>;
|
|
52
|
+
typeKey?: string;
|
|
53
|
+
validateBeforeSave?: boolean;
|
|
54
|
+
validateModifiedOnly?: boolean;
|
|
55
|
+
versionKey?: string | boolean;
|
|
56
|
+
selectPopulatedPaths?: boolean;
|
|
57
|
+
skipVersioning?: {
|
|
58
|
+
[key: string]: boolean;
|
|
59
|
+
};
|
|
60
|
+
storeSubdocValidationError?: boolean;
|
|
61
|
+
timestamps: boolean | mongoose.SchemaTimestampsConfig;
|
|
62
|
+
suppressReservedKeysWarning?: boolean;
|
|
63
|
+
statics?: {
|
|
64
|
+
[x: string]: any;
|
|
65
|
+
};
|
|
66
|
+
methods?: any;
|
|
67
|
+
query?: any;
|
|
68
|
+
castNonArrays?: boolean;
|
|
69
|
+
virtuals?: mongoose.SchemaOptionsVirtualsPropertyType<any, any, any>;
|
|
70
|
+
overwriteModels?: boolean;
|
|
71
|
+
}, any, any>> & {
|
|
72
|
+
[x: string]: any;
|
|
73
|
+
};
|
|
8
74
|
/**
|
|
9
75
|
* Loads all model definitions in the given directory.
|
|
10
76
|
* Returns the full loaded model set.
|
package/types/load.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../src/load.js"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,sCAJW,MAAM,QACN,MAAM
|
|
1
|
+
{"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../src/load.js"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,sCAJW,MAAM,QACN,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAahB;AAED;;;;GAIG;AACH,sCAFW,MAAM,mBAkBhB"}
|
package/types/schema.d.ts
CHANGED
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
* @param {mongoose.SchemaOptions} options
|
|
7
7
|
* @returns mongoose.Schema
|
|
8
8
|
*/
|
|
9
|
-
export function createSchema(definition: object, options?: mongoose.SchemaOptions): mongoose.Schema<any, mongoose.Model<any, any, any, any, any, any>, any, any, any,
|
|
9
|
+
export function createSchema(definition: object, options?: mongoose.SchemaOptions): mongoose.Schema<any, mongoose.Model<any, any, any, any, any, any>, any, any, any, {
|
|
10
|
+
[x: string]: any;
|
|
11
|
+
}, {
|
|
10
12
|
autoIndex?: boolean;
|
|
11
|
-
autoSearchIndex?: boolean;
|
|
12
13
|
autoCreate?: boolean;
|
|
13
14
|
bufferCommands?: boolean;
|
|
14
15
|
bufferTimeoutMS?: number;
|
|
@@ -61,8 +62,10 @@ export function createSchema(definition: object, options?: mongoose.SchemaOption
|
|
|
61
62
|
storeSubdocValidationError?: boolean;
|
|
62
63
|
timestamps: boolean | mongoose.SchemaTimestampsConfig;
|
|
63
64
|
suppressReservedKeysWarning?: boolean;
|
|
64
|
-
statics?:
|
|
65
|
-
|
|
65
|
+
statics?: {
|
|
66
|
+
[x: string]: any;
|
|
67
|
+
};
|
|
68
|
+
methods?: any;
|
|
66
69
|
query?: any;
|
|
67
70
|
castNonArrays?: boolean;
|
|
68
71
|
virtuals?: mongoose.SchemaOptionsVirtualsPropertyType<any, any, any>;
|
package/types/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.js"],"names":[],"mappings":"
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.js"],"names":[],"mappings":"AAkFA,kDAEC;AAED,oEA8FC;AAsBD,wEA2BC;
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.js"],"names":[],"mappings":"AAkFA,kDAEC;AAED,oEA8FC;AAsBD,wEA2BC;AAmSD;;;EAEC;AAED;;;EAOC;AAjgBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQK"}
|