arrayProp of ObjectId error
nllahat opened this issue · comments
Versions
- NodeJS: 8.8.1
- Typegoose(NPM): 5.8.0
- mongoose: 5.4.23
- mongodb: 3.4
Code Example
@arrayProp({ items: Types.ObjectId })
public classifications?: Types.ObjectId[]
Do you know why it happenes?
Because in Typegoose version ~5.8.0 and ~5.9.0 the array of objectIds really sent as Array type to the mongoose schema function interpretAsType (mongoose/lib/schema.js) and it triggers this code (the error of Invalid schema configuration is thrown):
if (Array.isArray(type) || Array === type || type === 'array') {
// if it was specified through { type } look for `cast`
let cast = (Array === type || type === 'array')
? obj.cast
: type[0];
if (cast && cast.instanceOfSchema) {
return new MongooseTypes.DocumentArray(path, cast, obj);
}
if (cast &&
cast[options.typeKey] &&
cast[options.typeKey].instanceOfSchema) {
return new MongooseTypes.DocumentArray(path, cast[options.typeKey], obj, cast);
}
if (Array.isArray(cast)) {
return new MongooseTypes.Array(path, this.interpretAsType(path, cast, options), obj);
}
if (typeof cast === 'string') {
cast = MongooseTypes[cast.charAt(0).toUpperCase() + cast.substring(1)];
} else if (cast && (!cast[options.typeKey] || (options.typeKey === 'type' && cast.type.type))
&& utils.isPOJO(cast)) {
if (Object.keys(cast).length) {
// The `minimize` and `typeKey` options propagate to child schemas
// declared inline, like `{ arr: [{ val: { $type: String } }] }`.
// See gh-3560
const childSchemaOptions = {minimize: options.minimize};
if (options.typeKey) {
childSchemaOptions.typeKey = options.typeKey;
}
//propagate 'strict' option to child schema
if (options.hasOwnProperty('strict')) {
childSchemaOptions.strict = options.strict;
}
const childSchema = new Schema(cast, childSchemaOptions);
childSchema.$implicitlyCreated = true;
return new MongooseTypes.DocumentArray(path, childSchema, obj);
} else {
// Special case: empty object becomes mixed
return new MongooseTypes.Array(path, MongooseTypes.Mixed, obj);
}
}
if (cast) {
type = cast[options.typeKey] && (options.typeKey !== 'type' || !cast.type.type)
? cast[options.typeKey]
: cast;
name = typeof type === 'string'
? type
: type.schemaName || utils.getFunctionName(type);
if (!(name in MongooseTypes)) {
throw new TypeError('Invalid schema configuration: ' +
`\`${name}\` is not a valid type within the array \`${path}\`.` +
'See http://bit.ly/mongoose-schematypes for a list of valid schema types.');
}
}
return new MongooseTypes.Array(path, cast || MongooseTypes.Mixed, obj, options);
}
In the old version of Typegoose (5.7.2) the property type is not sent as Array and the mongoose code is triggered:
// Special case re: gh-7049 because the bson `ObjectID` class' capitalization
// doesn't line up with Mongoose's.
if (name === 'ObjectID') {
name = 'ObjectId';
}
and that's why I don't get this error below
The Error
TypeError: Invalid schema configuration: ObjectID
is not a valid type within the array classifications
.See http://bit.ly/mongoose-schematypes for a list of valid schema types.
mongoose: 5.4.23
in typegoose 5.9.0+ it needs mongoose 5.6.7+
(just pointing it out)
and you are sure you dont want to use ref for this?
i looked into the source code, and between release 5.7.2 and 5.9.0, nothing has changed how the array is handled, only the mongoose version has changed
could confirm that it errors out, but as already stated, since version 5.7.2 nothing at array handling has changed...
import * as mongoose from "mongoose";
import "source-map-support/register";
import { arrayProp, prop, Typegoose } from "./typegoose/src/typegoose";
class Dummy extends Typegoose {
@prop({ required: true })
public doc?: mongoose.Types.ObjectId;
}
class DummyArray extends Typegoose {
@arrayProp({ required: true, items: mongoose.Types.ObjectId })
public docs?: mongoose.Types.ObjectId[];
}
const DummyModel = new Dummy().getModelForClass(Dummy);
const DummyArrayModel = new DummyArray().getModelForClass(DummyArray);
(async () => {
mongoose.set("debug", true);
await mongoose.connect(`mongodb://mongodb:27017/`, {
useNewUrlParser: true,
useFindAndModify: true,
useCreateIndex: true,
dbName: "verify362",
user: "user",
pass: "passwd",
authSource: "admin",
autoIndex: true
});
const doc = new DummyModel({ doc: new mongoose.Types.ObjectId() });
await doc.save();
console.log(doc.toObject());
const docs = new DummyArrayModel({ docs: [new mongoose.Types.ObjectId(), new mongoose.Types.ObjectId(), new mongoose.Types.ObjectId()] });
await docs.save();
console.log(docs.toObject());
await mongoose.disconnect();
})();
found the error, its not an error with typegoose, but i could fix it in typegoose
description of the error:
the type mongoose.Types.ObjectId
has Type.name
of ObjectID
, but mongoose expects ObjectId
, will implement a workaround soon
made an mongoose issue Automattic/mongoose#8034
(please dont close this issue until the mongoose issue is fixed)
in typegoose 5.9.0+ it needs mongoose 5.6.7+
(just pointing it out)
Thanks. Will check if it is possible for us to upgrade.
and you are sure you dont want to use ref for this?
Those objectIds are from another microservice in other db. so ref won't fit.
Thanks for helping. Waiting for the mongoose fix (:
Those objectIds are from another microservice in other db. so ref won't fit.
just wanted to confirm that it didnt got overseen, because that happened already :)
the temporary fix #363 got merged, but still waiting on mongoose to fix it on their side
@hasezoey still getting this error on ^5.9.0
error TS2352: Conversion of type 'Ref<User>' to type 'ObjectId' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
Type 'User' is missing the following properties from type 'ObjectId': generationTime, equals, getTimestamp, toHexString
I believe its related to this ObjectId vs ObjectID right?
@ChrisLahaye, yes it got merged long ago, but since then @Ben305 has not made a new version, so it was never in a version yet, but it got fixed my mongoose itself now (i dont know the version anymore)
PS: as of version 5.9.1 it got released
@hasezoey can you update your fork to mongoose 5.6.9 such that mongoose exports ObjectID (which I believe is used in the union type Ref)
@ChrisLahaye typegoose v6.0.0 uses 5.7, after arrayvalidators get merged
but v5.x will not get and updated mongoose, otherwise, it works with every mongoose, because it is a peer dependency