Socket
Socket
Sign inDemoInstall

@andrewscwei/mongodb-odm

Package Overview
Dependencies
Maintainers
1
Versions
83
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@andrewscwei/mongodb-odm - npm Package Compare versions

Comparing version 0.21.0 to 0.22.0

50

build/core/Model.js

@@ -797,5 +797,3 @@ "use strict";

const fieldSpecs = fields[key];
if (!validateFieldValue_1.default(val, fieldSpecs)) {
throw new Error(`Error validating field '${key}' with value [${JSON.stringify(val, undefined, 0)}] of type [${typeof val}], constraints: ${JSON.stringify(fieldSpecs, null, 0)}, doc: ${JSON.stringify(doc, null, 0)}`);
}
validateFieldValue_1.default(val, fieldSpecs);
}

@@ -979,17 +977,17 @@ // #3 Check for unique fields only if `ignoreUniqueIndex` is not `true`.

// valid and that the update object is a proper update query.
const qq = sanitizeQuery_1.default(this.schema, q);
let uu;
const sanitizedQuery = sanitizeQuery_1.default(this.schema, q);
let sanitizedUpdate;
if (types_1.typeIsUpdate(u)) {
uu = Object.assign({}, u);
if (uu.$set)
uu.$set = sanitizeDocument_1.default(this.schema, uu.$set);
if (uu.$setOnInsert)
uu.$setOnInsert = sanitizeDocument_1.default(this.schema, uu.$setOnInsert);
if (uu.$addToSet)
uu.$addToSet = sanitizeDocument_1.default(this.schema, uu.$addToSet);
if (uu.$push)
uu.$push = sanitizeDocument_1.default(this.schema, uu.$push);
sanitizedUpdate = Object.assign({}, u);
if (sanitizedUpdate.$set)
sanitizedUpdate.$set = sanitizeDocument_1.default(this.schema, sanitizedUpdate.$set);
if (sanitizedUpdate.$setOnInsert)
sanitizedUpdate.$setOnInsert = sanitizeDocument_1.default(this.schema, sanitizedUpdate.$setOnInsert);
if (sanitizedUpdate.$addToSet)
sanitizedUpdate.$addToSet = sanitizeDocument_1.default(this.schema, sanitizedUpdate.$addToSet);
if (sanitizedUpdate.$push)
sanitizedUpdate.$push = sanitizeDocument_1.default(this.schema, sanitizedUpdate.$push);
}
else {
uu = {
sanitizedUpdate = {
$set: sanitizeDocument_1.default(this.schema, u),

@@ -1000,10 +998,10 @@ };

if ((this.schema.timestamps === true) && (options.ignoreTimestamps !== true)) {
if (!uu.$set)
uu.$set = {};
if (!is_1.default.date(uu.$set.updatedAt))
uu.$set.updatedAt = new Date();
if (!sanitizedUpdate.$set)
sanitizedUpdate.$set = {};
if (!is_1.default.date(sanitizedUpdate.$set.updatedAt))
sanitizedUpdate.$set.updatedAt = new Date();
}
// Format all fields in the update query.
if (uu.$set) {
uu.$set = yield this.formatDocument(uu.$set);
if (sanitizedUpdate.$set) {
sanitizedUpdate.$set = yield this.formatDocument(sanitizedUpdate.$set);
}

@@ -1016,11 +1014,11 @@ // In the case of an upsert, we need to preprocess the query as if this was

// Make a copy of the query in case it is manipulated by the hooks.
const beforeInsert = yield this.beforeInsert(lodash_1.default.cloneDeep(qq), Object.assign({}, options, { strict: false }));
const setOnInsert = lodash_1.default.omit(Object.assign({}, uu.$setOnInsert || {}, beforeInsert), Object.keys(uu.$set || {}));
const beforeInsert = yield this.beforeInsert(lodash_1.default.cloneDeep(sanitizedQuery), Object.assign({}, options, { strict: false }));
const setOnInsert = lodash_1.default.omit(Object.assign({}, sanitizedUpdate.$setOnInsert || {}, beforeInsert), Object.keys(sanitizedUpdate.$set || {}));
if (!is_1.default.emptyObject(setOnInsert)) {
uu.$setOnInsert = setOnInsert;
sanitizedUpdate.$setOnInsert = setOnInsert;
}
}
// Validate all fields in the update query.
yield this.validateDocument(uu.$set, Object.assign({ ignoreUniqueIndex: true }, options));
return [qq, uu];
yield this.validateDocument(sanitizedUpdate.$set, Object.assign({ ignoreUniqueIndex: true }, options));
return [sanitizedQuery, sanitizedUpdate];
});

@@ -1027,0 +1025,0 @@ }

@@ -235,3 +235,8 @@ "use strict";

}));
mocha_1.it('foo', () => __awaiter(this, void 0, void 0, function* () {
const s = faker_1.default.random.alphaNumeric(10);
const baz = yield Baz_1.default.insertOneStrict({ aString: s });
yield Baz_1.default.updateOneStrict(baz._id, { aNumber: null, aBoolean: false });
}));
});
//# sourceMappingURL=Model.spec.js.map

@@ -13,56 +13,56 @@ "use strict";

const i = 'Hello, world!';
assert_1.default(validateFieldValue_1.default(i, { type: String, validate: 13 }) === true);
assert_1.default(validateFieldValue_1.default(i, { type: String, validate: 12 }) === false);
assert_1.default.doesNotThrow(() => validateFieldValue_1.default(i, { type: String, validate: 13 }));
assert_1.default.throws(() => validateFieldValue_1.default(i, { type: String, validate: 12 }));
});
mocha_1.it('can validate string regex', () => {
const i = 'Hello, world!';
assert_1.default(validateFieldValue_1.default(i, { type: String, validate: /^Hello.*$/ }) === true);
assert_1.default(validateFieldValue_1.default(i, { type: String, validate: /^hello.*$/ }) === false);
assert_1.default.doesNotThrow(() => validateFieldValue_1.default(i, { type: String, validate: /^Hello.*$/ }));
assert_1.default.throws(() => validateFieldValue_1.default(i, { type: String, validate: /^hello.*$/ }));
});
mocha_1.it('can validate string from list', () => {
const i = 'Hello, world!';
assert_1.default(validateFieldValue_1.default(i, { type: String, validate: [i] }) === true);
assert_1.default(validateFieldValue_1.default(i, { type: String, validate: [] }) === false);
assert_1.default.doesNotThrow(() => validateFieldValue_1.default(i, { type: String, validate: [i] }));
assert_1.default.throws(() => validateFieldValue_1.default(i, { type: String, validate: [] }));
});
mocha_1.it('can validate string with custom method', () => {
const i = 'Hello, world!';
assert_1.default(validateFieldValue_1.default(i, { type: String, validate: (v) => (v === i) }) === true);
assert_1.default(validateFieldValue_1.default(i, { type: String, validate: (v) => (v !== i) }) === false);
assert_1.default.doesNotThrow(() => validateFieldValue_1.default(i, { type: String, validate: (v) => (v === i) }));
assert_1.default.throws(() => validateFieldValue_1.default(i, { type: String, validate: (v) => (v !== i) }));
});
mocha_1.it('can validate numbers with inclusive maximum', () => {
const i = 6;
assert_1.default(validateFieldValue_1.default(i, { type: Number, validate: 6 }) === true);
assert_1.default(validateFieldValue_1.default(i, { type: Number, validate: 5 }) === false);
assert_1.default.doesNotThrow(() => validateFieldValue_1.default(i, { type: Number, validate: 6 }));
assert_1.default.throws(() => validateFieldValue_1.default(i, { type: Number, validate: 5 }));
});
mocha_1.it('can validate numbers from list', () => {
const i = 6;
assert_1.default(validateFieldValue_1.default(i, { type: Number, validate: [6] }) === true);
assert_1.default(validateFieldValue_1.default(i, { type: Number, validate: [] }) === false);
assert_1.default.doesNotThrow(() => validateFieldValue_1.default(i, { type: Number, validate: [6] }));
assert_1.default.throws(() => validateFieldValue_1.default(i, { type: Number, validate: [] }));
});
mocha_1.it('can validate numbers from custom method', () => {
const i = 6;
assert_1.default(validateFieldValue_1.default(i, { type: Number, validate: (v) => (v > 5 && v < 7) }) === true);
assert_1.default(validateFieldValue_1.default(i, { type: Number, validate: (v) => (v < 5) }) === false);
assert_1.default.doesNotThrow(() => validateFieldValue_1.default(i, { type: Number, validate: (v) => (v > 5 && v < 7) }));
assert_1.default.throws(() => validateFieldValue_1.default(i, { type: Number, validate: (v) => (v < 5) }));
});
mocha_1.it('can validate booleans', () => {
const i = true;
assert_1.default(validateFieldValue_1.default(i, { type: Boolean }) === true);
assert_1.default.doesNotThrow(() => validateFieldValue_1.default(i, { type: Boolean }));
});
mocha_1.it('can validate dates', () => {
const i = new Date();
assert_1.default(validateFieldValue_1.default(i, { type: Date }) === true);
assert_1.default.doesNotThrow(() => validateFieldValue_1.default(i, { type: Date }));
});
mocha_1.it('can validate arrays', () => {
assert_1.default(validateFieldValue_1.default([0, 1, 2, 3], { type: [Number] }) === true);
assert_1.default(validateFieldValue_1.default([0, false, 2, 3], { type: [Number] }) === false);
assert_1.default.doesNotThrow(() => validateFieldValue_1.default([0, 1, 2, 3], { type: [Number] }));
assert_1.default.throws(() => validateFieldValue_1.default([0, false, 2, 3], { type: [Number] }));
});
mocha_1.it('can validate objects', () => {
assert_1.default(validateFieldValue_1.default({ a: 'foo', b: 0 }, { type: { a: { type: String }, b: { type: Number } } }) === true);
assert_1.default(validateFieldValue_1.default({ a: 'foo', b: { c: true, d: [0, 1, 2, 3] } }, { type: { a: { type: String }, b: { type: { c: { type: Boolean }, d: { type: [Number] } } } } }) === true);
assert_1.default.doesNotThrow(() => validateFieldValue_1.default({ a: 'foo', b: 0 }, { type: { a: { type: String }, b: { type: Number } } }));
assert_1.default.doesNotThrow(() => validateFieldValue_1.default({ a: 'foo', b: { c: true, d: [0, 1, 2, 3] } }, { type: { a: { type: String }, b: { type: { c: { type: Boolean }, d: { type: [Number] } } } } }));
});
mocha_1.it('can validate ObjectIDs', () => {
const i = new mongodb_1.ObjectID();
assert_1.default(validateFieldValue_1.default(i, { type: mongodb_1.ObjectID }) === true);
assert_1.default.doesNotThrow(() => validateFieldValue_1.default(i, { type: mongodb_1.ObjectID }));
});
});
//# sourceMappingURL=validateFieldValue.spec.js.map

@@ -25,2 +25,5 @@ "use strict";

continue;
// Ignore undefined fields.
if (doc[key] === undefined)
continue;
o[key] = doc[key];

@@ -27,0 +30,0 @@ }

@@ -8,4 +8,2 @@ import { FieldSpecs } from '../types';

*
* @returns `true` if validation passes, `false` otherwise.
*
* @throws {TypeError} Value is marked as required in the specs but it is null

@@ -71,2 +69,2 @@ * or undefined.

*/
export default function validateFieldValue(value: any, specs: FieldSpecs): boolean;
export default function validateFieldValue(value: any, specs: FieldSpecs): true | undefined;

@@ -16,4 +16,2 @@ "use strict";

*
* @returns `true` if validation passes, `false` otherwise.
*
* @throws {TypeError} Value is marked as required in the specs but it is null

@@ -80,145 +78,120 @@ * or undefined.

function validateFieldValue(value, specs) {
try {
// Check if value is undefined or null, then respond accordingly depending on
// whether or not it is a required value.
if (is_1.default.nullOrUndefined(value)) {
if (specs.required) {
throw new TypeError('The value is marked as required but it is null or undefined');
// Check if value is undefined or null, then respond accordingly depending on
// whether or not it is a required value.
if (is_1.default.nullOrUndefined(value)) {
if (specs.required) {
throw new TypeError('The value is marked as required but it is null or undefined');
}
else {
return true;
}
}
switch (specs.type) {
case String:
assert_1.default(is_1.default.string(value), new TypeError(`The value "${value}" is expected to be a string but instead it is a(n) ${is_1.default(value)}`));
if (is_1.default.regExp(specs.validate)) {
assert_1.default(specs.validate.test(value), new TypeError(`The string value does not conform to the RegEx validator: ${specs.validate}`));
}
else {
return true;
else if (is_1.default.number(specs.validate)) {
assert_1.default(value.length <= specs.validate, new TypeError(`The length of the string value "${value}" must be less than or equal to ${specs.validate}`));
}
}
switch (specs.type) {
case String:
assert_1.default(is_1.default.string(value), new TypeError(`The value "${value}" is expected to be a string but instead it is a(n) ${is_1.default(value)}`));
if (is_1.default.regExp(specs.validate)) {
assert_1.default(specs.validate.test(value), new TypeError(`The string value does not conform to the RegEx validator: ${specs.validate}`));
else if (is_1.default.array(specs.validate)) {
assert_1.default(specs.validate.indexOf(value) > -1, new TypeError(`The string value "${value}" is not an element of ${specs.validate}`));
}
break;
case Number:
assert_1.default(is_1.default.number(value), new TypeError(`The value "${value}" is expected to be a number but instead it is a(n) ${is_1.default(value)}`));
if (is_1.default.regExp(specs.validate)) {
throw new TypeError('The RegExp validation method is not supported for number values');
}
else if (is_1.default.number(specs.validate)) {
assert_1.default(value <= specs.validate, new TypeError(`The number value "${value}" must be less than or equal to ${specs.validate}`));
}
else if (is_1.default.array(specs.validate)) {
assert_1.default(specs.validate.indexOf(value) > -1, new TypeError(`The number value "${value}" is not an element of ${specs.validate}`));
}
break;
case Boolean:
assert_1.default(is_1.default.boolean(value), new TypeError(`The value "${value}" is expected to be a boolean but instead it is a(n) ${is_1.default(value)}`));
if (is_1.default.regExp(specs.validate)) {
throw new TypeError('The RegExp validation method is not supported for boolean values');
}
else if (is_1.default.number(specs.validate)) {
throw new TypeError('The number validation method is not supported for boolean vlaues');
}
else if (is_1.default.array(specs.validate)) {
assert_1.default(specs.validate.indexOf(value) > -1, new TypeError(`The boolean value "${value}" is not an element of ${specs.validate}`));
}
break;
case Date:
assert_1.default(is_1.default.date(value), new TypeError(`The value "${value}" is expected to be a date but instead it is a(n) ${is_1.default(value)}`));
if (is_1.default.regExp(specs.validate)) {
throw new TypeError('The RegExp validation method is not supported for date values');
}
else if (is_1.default.number(specs.validate)) {
throw new TypeError('The number validation method is not supported for date values');
}
else if (is_1.default.array(specs.validate)) {
throw new TypeError('The array validation method is not supported for date values');
}
break;
case Array:
assert_1.default(is_1.default.array(value), new TypeError(`The value "${value}" is expected to be an array but instead it is a(n) ${is_1.default(value)}`));
if (is_1.default.regExp(specs.validate)) {
throw new TypeError('The RegExp validation method is not supported for array values');
}
else if (is_1.default.number(specs.validate)) {
throw new TypeError('The number validation method is not supported for array values');
}
else if (is_1.default.array(specs.validate)) {
throw new TypeError('The array validation method is not supported for array values');
}
break;
case mongodb_1.ObjectID:
assert_1.default(types_1.typeIsValidObjectID(value), new TypeError(`The value "${value}" is expected to be an ObjectID but instead it is a(n) ${is_1.default(value)}`));
if (is_1.default.regExp(specs.validate)) {
throw new TypeError('The RegExp validation method is not supported for ObjectID values');
}
else if (is_1.default.number(specs.validate)) {
throw new TypeError('The number validation method is not supported for ObjectID values');
}
else if (is_1.default.array(specs.validate)) {
throw new TypeError('The array validation method is not supported for ObjectID values');
}
break;
default:
// If type is an array of a type, i.e. [Number].
if (is_1.default.array(specs.type)) {
if (specs.type.length !== 1)
throw new TypeError(`Incorrect definition of a typed array type ${specs.type}: when specifying a type as an array of another type, wrap the type with [], hence a one-element array`);
if (!is_1.default.array(value))
throw new TypeError(`The value "${value}" is expected to be a typed array but instead it is a(n) ${is_1.default(value)}`);
// Ensure that every element within the array conforms to the specified
// type and passes the validation test.
for (const item of value) {
validateFieldValue(item, Object.assign({}, specs, { type: specs.type[0] }));
}
else if (is_1.default.number(specs.validate)) {
assert_1.default(value.length <= specs.validate, new TypeError(`The length of the string value "${value}" must be less than or equal to ${specs.validate}`));
}
else if (is_1.default.array(specs.validate)) {
assert_1.default(specs.validate.indexOf(value) > -1, new TypeError(`The string value "${value}" is not an element of ${specs.validate}`));
}
break;
case Number:
assert_1.default(is_1.default.number(value), new TypeError(`The value "${value}" is expected to be a number but instead it is a(n) ${is_1.default(value)}`));
}
// If type is an object.
else if (is_1.default.plainObject(specs.type)) {
assert_1.default(is_1.default.plainObject(value), new TypeError(`The value "${value}" is expected to be an object but instead it is a(n) ${is_1.default(value)}`));
if (is_1.default.regExp(specs.validate)) {
throw new TypeError('The RegExp validation method is not supported for number values');
throw new TypeError('The RegExp validation method is not supported for object values');
}
else if (is_1.default.number(specs.validate)) {
assert_1.default(value <= specs.validate, new TypeError(`The number value "${value}" must be less than or equal to ${specs.validate}`));
throw new TypeError('The number validation method is not supported for object values');
}
else if (is_1.default.array(specs.validate)) {
assert_1.default(specs.validate.indexOf(value) > -1, new TypeError(`The number value "${value}" is not an element of ${specs.validate}`));
throw new TypeError('The array validation method is not supported for object values');
}
break;
case Boolean:
assert_1.default(is_1.default.boolean(value), new TypeError(`The value "${value}" is expected to be a boolean but instead it is a(n) ${is_1.default(value)}`));
if (is_1.default.regExp(specs.validate)) {
throw new TypeError('The RegExp validation method is not supported for boolean values');
// Validate each field.
for (const subFieldName in specs.type) {
if (!specs.type.hasOwnProperty(subFieldName))
continue;
validateFieldValue(value[subFieldName], specs.type[subFieldName]);
}
else if (is_1.default.number(specs.validate)) {
throw new TypeError('The number validation method is not supported for boolean vlaues');
}
else if (is_1.default.array(specs.validate)) {
assert_1.default(specs.validate.indexOf(value) > -1, new TypeError(`The boolean value "${value}" is not an element of ${specs.validate}`));
}
break;
case Date:
assert_1.default(is_1.default.date(value), new TypeError(`The value "${value}" is expected to be a date but instead it is a(n) ${is_1.default(value)}`));
if (is_1.default.regExp(specs.validate)) {
throw new TypeError('The RegExp validation method is not supported for date values');
}
else if (is_1.default.number(specs.validate)) {
throw new TypeError('The number validation method is not supported for date values');
}
else if (is_1.default.array(specs.validate)) {
throw new TypeError('The array validation method is not supported for date values');
}
break;
case Array:
assert_1.default(is_1.default.array(value), new TypeError(`The value "${value}" is expected to be an array but instead it is a(n) ${is_1.default(value)}`));
if (is_1.default.regExp(specs.validate)) {
throw new TypeError('The RegExp validation method is not supported for array values');
}
else if (is_1.default.number(specs.validate)) {
throw new TypeError('The number validation method is not supported for array values');
}
else if (is_1.default.array(specs.validate)) {
throw new TypeError('The array validation method is not supported for array values');
}
break;
case mongodb_1.ObjectID:
assert_1.default(types_1.typeIsValidObjectID(value), new TypeError(`The value "${value}" is expected to be an ObjectID but instead it is a(n) ${is_1.default(value)}`));
if (is_1.default.regExp(specs.validate)) {
throw new TypeError('The RegExp validation method is not supported for ObjectID values');
}
else if (is_1.default.number(specs.validate)) {
throw new TypeError('The number validation method is not supported for ObjectID values');
}
else if (is_1.default.array(specs.validate)) {
throw new TypeError('The array validation method is not supported for ObjectID values');
}
break;
default:
// If type is an array of a type, i.e. [Number].
if (is_1.default.array(specs.type)) {
if (specs.type.length !== 1)
throw new TypeError(`Incorrect definition of a typed array type ${specs.type}: when specifying a type as an array of another type, wrap the type with [], hence a one-element array`);
if (!is_1.default.array(value))
throw new TypeError(`The value "${value}" is expected to be a typed array but instead it is a(n) ${is_1.default(value)}`);
// Ensure that every element within the array conforms to the specified
// type and passes the validation test.
let t = true;
let error;
try {
t = value.reduce((prevVal, currVal) => {
return prevVal && validateFieldValue(currVal, Object.assign({}, specs, { type: specs.type[0] }));
}, true);
}
catch (err) {
t = false;
error = err;
}
if (!t || error)
throw new TypeError(`One or more values within the supposed typed array "${value}" are not of the correct type: ${error ? error.message : 'Unknown reason'}`);
}
// If type is an object.
else if (is_1.default.plainObject(specs.type)) {
assert_1.default(is_1.default.plainObject(value), new TypeError(`The value "${value}" is expected to be an object but instead it is a(n) ${is_1.default(value)}`));
if (is_1.default.regExp(specs.validate)) {
throw new TypeError('The RegExp validation method is not supported for object values');
}
else if (is_1.default.number(specs.validate)) {
throw new TypeError('The number validation method is not supported for object values');
}
else if (is_1.default.array(specs.validate)) {
throw new TypeError('The array validation method is not supported for object values');
}
let error;
let t = true;
try {
for (const subFieldName in specs.type) {
if (!specs.type.hasOwnProperty(subFieldName))
continue;
t = t && validateFieldValue(value[subFieldName], specs.type[subFieldName]);
}
}
catch (err) {
error = err;
t = false;
}
if (!t || error)
throw new TypeError(`One or more sub-fields are not valid: ${error ? error.message : 'Unknown reason'}`);
}
}
if (is_1.default.function_(specs.validate)) {
assert_1.default(specs.validate(value), new TypeError(`The value "${value}" failed to pass custom validation function`));
}
return true;
}
}
catch (error) {
return false;
if (is_1.default.function_(specs.validate)) {
assert_1.default(specs.validate(value), new TypeError(`The value "${value}" failed to pass custom validation function`));
}

@@ -225,0 +198,0 @@ }

{
"name": "@andrewscwei/mongodb-odm",
"version": "0.21.0",
"version": "0.22.0",
"description": "ODM for MongoDB",

@@ -9,2 +9,3 @@ "main": "build/index.js",

"build": "npm run clean && tsc",
"test:ts": "NODE_ENV=test DEBUG=mongodb-odm* mocha --require ts-node/register --timeout 10000 --reporter spec --full-trace --colors --recursive --bail --exit \"src/tests/**/*.ts\"",
"test": "NODE_ENV=test DEBUG=mongodb-odm* mocha --require dotenv/config --timeout 10000 --reporter spec --full-trace --colors --recursive --bail --exit $([ -z \"$npm_config_path\" ] && echo build/tests || echo $npm_config_path)",

@@ -11,0 +12,0 @@ "db": "mkdirp .mongodb/data && mongod --bind_ip 0.0.0.0 --dbpath .mongodb/data --logpath .mongodb/mongod.log --fork",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc