Skip to content
Merged

6.9 #12949

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a036c12
typescript: Allow null for optional document fields
JavaScriptBach Dec 8, 2022
3611dd0
update tests
JavaScriptBach Dec 9, 2022
8327ccf
lint
JavaScriptBach Dec 9, 2022
3160949
fix(cast): remove empty conditions after strict applied
0x0a0d Jan 10, 2023
629b1ed
Merge pull request #12898 from 0x0a0d/fix-strict-return-all
vkarpov15 Jan 14, 2023
474451a
Merge branch '6.9' of github.com:Automattic/mongoose into 6.9
vkarpov15 Jan 17, 2023
6114228
Update .gitignore
IslandRhythms Jan 17, 2023
0a35676
feature: add `schema.removeVirtual(path)` function
IslandRhythms Jan 17, 2023
e7ab0fb
lint fix
IslandRhythms Jan 17, 2023
d222dd4
fix mistakes in logic and add new test
IslandRhythms Jan 18, 2023
c98f07b
addressed comments
IslandRhythms Jan 19, 2023
af20f0e
Update schema.js
vkarpov15 Jan 19, 2023
c591139
Update schema.js
vkarpov15 Jan 19, 2023
0386d51
Update schema.js
vkarpov15 Jan 19, 2023
b74eff1
Update schema.js
vkarpov15 Jan 19, 2023
51e9313
Update schema.test.js
vkarpov15 Jan 19, 2023
abdd928
Merge pull request #12920 from Automattic/IslandRhythms/removeVirtual
vkarpov15 Jan 19, 2023
74b5f00
Merge branch 'master' into 6.9
vkarpov15 Jan 19, 2023
d1dea8f
style: fix lint
vkarpov15 Jan 19, 2023
32a0d08
Merge branch 'master' into 6.9
vkarpov15 Jan 23, 2023
90acf2b
Merge branch '6.9' into infer-null
vkarpov15 Jan 23, 2023
71d80e4
Merge pull request #12781 from JavaScriptBach/infer-null
vkarpov15 Jan 23, 2023
392ae0a
Merge branch 'master' into 6.9
vkarpov15 Jan 25, 2023
5ab7a0f
Merge branch '6.9' of github.com:Automattic/mongoose into 6.9
vkarpov15 Jan 25, 2023
c6c30ed
feat: use mongodb driver 4.13.0
vkarpov15 Jan 25, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ coverage
npm-debug.log
data/
.nyc_output/

.env
tools/31*

# Visual Studio
Expand Down
9 changes: 8 additions & 1 deletion lib/cast.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,18 @@ module.exports = function cast(schema, obj, options, context) {
if (!Array.isArray(val)) {
throw new CastError('Array', val, path);
}
for (let k = 0; k < val.length; ++k) {
for (let k = val.length - 1; k >= 0; k--) {
if (val[k] == null || typeof val[k] !== 'object') {
throw new CastError('Object', val[k], path + '.' + k);
}
val[k] = cast(schema, val[k], options, context);
if (Object.keys(val[k]).length === 0) {
val.splice(k, 1);
}
}

if (val.length === 0) {
delete obj[path];
}
} else if (path === '$where') {
type = typeof val;
Expand Down
26 changes: 26 additions & 0 deletions lib/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -2251,6 +2251,32 @@ function _deletePath(schema, name) {
delete branch[last];
}

/**
*
* @param {String|Array} path The virutal path(s) to remove.
* @returns {Schema} the Schema instance, or a mongoose error if the virtual does not exist.
* @api public
*/

Schema.prototype.removeVirtual = function(path) {
if (typeof path === 'string') {
path = [path];
}
if (Array.isArray(path)) {
for (const virtual of path) {
if (this.virtuals[virtual] == null) {
throw new MongooseError(`Attempting to remove virtual "${virtual}" that does not exist.`);
}
}

for (const virtual of path) {
delete this.paths[virtual];
delete this.virtuals[virtual];
}
}
return this;
};

/**
* Loads an ES6 class into a schema. Maps [setters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set) + [getters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get), [static methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static),
* and [instance methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#Class_body_and_method_definitions)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"dependencies": {
"bson": "^4.7.0",
"kareem": "2.5.1",
"mongodb": "4.12.1",
"mongodb": "4.13.0",
"mpath": "0.9.0",
"mquery": "4.0.3",
"ms": "2.1.3",
Expand Down
74 changes: 46 additions & 28 deletions test/docs/cast.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,40 +101,58 @@ describe('Cast Tutorial', function() {
await query.exec();
});

it('strictQuery true', async function() {
mongoose.deleteModel('Character');
const schema = new mongoose.Schema({ name: String, age: Number }, {
strictQuery: true
describe('strictQuery', function() {
it('strictQuery true - simple object', async function() {
mongoose.deleteModel('Character');
const schema = new mongoose.Schema({ name: String, age: Number }, {
strictQuery: true
});
Character = mongoose.model('Character', schema);

const query = Character.findOne({ notInSchema: { $lt: 'not a number' } });

await query.exec();
query.getFilter(); // Empty object `{}`, Mongoose removes `notInSchema`
// acquit:ignore:start
assert.deepEqual(query.getFilter(), {});
// acquit:ignore:end
});
Character = mongoose.model('Character', schema);

const query = Character.findOne({ notInSchema: { $lt: 'not a number' } });
it('strictQuery true - conditions', async function() {
mongoose.deleteModel('Character');
const schema = new mongoose.Schema({ name: String, age: Number }, {
strictQuery: true
});
Character = mongoose.model('Character', schema);

await query.exec();
query.getFilter(); // Empty object `{}`, Mongoose removes `notInSchema`
// acquit:ignore:start
assert.deepEqual(query.getFilter(), {});
// acquit:ignore:end
});
const query = Character.findOne({ $or: [{ notInSchema: { $lt: 'not a number' } }], $and: [{ name: 'abc' }, { age: { $gt: 18 } }, { notInSchema: { $lt: 'not a number' } }] });

it('strictQuery throw', async function() {
mongoose.deleteModel('Character');
const schema = new mongoose.Schema({ name: String, age: Number }, {
strictQuery: 'throw'
await query.exec();
query.getFilter(); // Empty object `{}`, Mongoose removes `notInSchema`
// acquit:ignore:start
assert.deepEqual(query.getFilter(), { $and: [{ name: 'abc' }, { age: { $gt: 18 } }] });
// acquit:ignore:end
});
Character = mongoose.model('Character', schema);

const query = Character.findOne({ notInSchema: { $lt: 'not a number' } });

const err = await query.exec().then(() => null, err => err);
err.name; // 'StrictModeError'
// Path "notInSchema" is not in schema and strictQuery is 'throw'.
err.message;
// acquit:ignore:start
assert.equal(err.name, 'StrictModeError');
assert.equal(err.message, 'Path "notInSchema" is not in schema and ' +
'strictQuery is \'throw\'.');
// acquit:ignore:end
it('strictQuery throw', async function() {
mongoose.deleteModel('Character');
const schema = new mongoose.Schema({ name: String, age: Number }, {
strictQuery: 'throw'
});
Character = mongoose.model('Character', schema);

const query = Character.findOne({ notInSchema: { $lt: 'not a number' } });

const err = await query.exec().then(() => null, err => err);
err.name; // 'StrictModeError'
// Path "notInSchema" is not in schema and strictQuery is 'throw'.
err.message;
// acquit:ignore:start
assert.equal(err.name, 'StrictModeError');
assert.equal(err.message, 'Path "notInSchema" is not in schema and ' +
'strictQuery is \'throw\'.');
// acquit:ignore:end
});
});

it('implicit in', async function() {
Expand Down
59 changes: 59 additions & 0 deletions test/schema.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2910,4 +2910,63 @@ describe('schema', function() {

assert.equal(schema._getSchema('child.testMap.foo.bar').instance, 'Mixed');
});

it('should allow deleting a virtual path off the schema gh-8397', async function() {
const schema = new Schema({
name: String
}, {
virtuals: {
foo: {
get() {
return 42;
}
}
}
});
assert.ok(schema.virtuals.foo);
schema.removeVirtual('foo');
assert.ok(!schema.virtuals.foo);
const Test = db.model('gh-8397', schema);
const doc = new Test({ name: 'Test' });
assert.equal(doc.foo, undefined);
});

it('should allow deleting multiple virtuals gh-8397', async function() {
const schema = new Schema({
name: String
}, {
virtuals: {
foo: {
get() {
return 42;
}
},
bar: {
get() {
return 41;
}
}
}
});
assert.ok(schema.virtuals.foo);
assert.ok(schema.virtuals.bar);
schema.removeVirtual(['foo', 'bar']);
assert.ok(!schema.virtuals.foo);
assert.ok(!schema.virtuals.bar);
const Test = db.model('gh-8397', schema);
const doc = new Test({ name: 'Test' });
assert.equal(doc.foo, undefined);
assert.equal(doc.bar, undefined);
});

it('should throw an error if attempting to delete a virtual path that does not exist gh-8397', function() {
const schema = new Schema({
name: String
});
assert.ok(!schema.virtuals.foo);
assert.throws(() => {
schema.removeVirtual('foo');
}, { message: 'Attempting to remove virtual "foo" that does not exist.' });

});
});
2 changes: 1 addition & 1 deletion test/types/models.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ function gh12100() {
const TestModel = model('test', schema_with_string_id);
const obj = new TestModel();

expectType<string>(obj._id);
expectType<string | null>(obj._id);
})();

(async function gh12094() {
Expand Down
2 changes: 1 addition & 1 deletion test/types/queries.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ async function gh12342_manual() {

async function gh12342_auto() {
interface Project {
name?: string, stars?: number
name?: string | null, stars?: number | null
}

const ProjectSchema = new Schema({
Expand Down
Loading