Skip to content

Commit 6bf274a

Browse files
fix(): should embed a subdocument when options are provided
1 parent 4015e3d commit 6bf274a

File tree

2 files changed

+84
-15
lines changed

2 files changed

+84
-15
lines changed

lib/factories/definitions.factory.ts

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,24 +41,40 @@ export class DefinitionsFactory {
4141
}
4242

4343
private static inspectTypeDefinition(
44-
options: mongoose.SchemaTypeOpts<unknown> | Function,
44+
optionsOrType: mongoose.SchemaTypeOpts<unknown> | Function,
4545
): PropOptions {
46-
if (typeof options === 'function') {
47-
if (this.isPrimitive(options)) {
48-
return options;
49-
} else if (this.isMongooseSchemaType(options)) {
50-
return options;
46+
if (typeof optionsOrType === 'function') {
47+
if (this.isPrimitive(optionsOrType)) {
48+
return optionsOrType;
49+
} else if (this.isMongooseSchemaType(optionsOrType)) {
50+
return optionsOrType;
5151
}
52-
return this.createForClass(options as Type<unknown>);
53-
} else if (typeof options.type === 'function') {
54-
options.type = this.inspectTypeDefinition(options.type);
55-
return options;
56-
} else if (Array.isArray(options)) {
57-
return options.length > 0
58-
? [this.inspectTypeDefinition(options[0])]
59-
: options;
52+
53+
const schemaDefinition = this.createForClass(
54+
optionsOrType as Type<unknown>,
55+
);
56+
const schemaMetadata = TypeMetadataStorage.getSchemaMetadataByTarget(
57+
optionsOrType as Type<unknown>,
58+
);
59+
if (schemaMetadata?.options) {
60+
/**
61+
* When options are provided (e.g., `@Schema({ timestamps: true })`)
62+
* create a new nested schema for a subdocument
63+
* @ref https://mongoosejs.com/docs/subdocs.html
64+
**/
65+
66+
return new mongoose.Schema(schemaDefinition, schemaMetadata.options);
67+
}
68+
return schemaDefinition;
69+
} else if (typeof optionsOrType.type === 'function') {
70+
optionsOrType.type = this.inspectTypeDefinition(optionsOrType.type);
71+
return optionsOrType;
72+
} else if (Array.isArray(optionsOrType)) {
73+
return optionsOrType.length > 0
74+
? [this.inspectTypeDefinition(optionsOrType[0])]
75+
: optionsOrType;
6076
}
61-
return options;
77+
return optionsOrType;
6278
}
6379

6480
private static isPrimitive(type: Function) {

tests/e2e/schema.factory.spec.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { Prop, Schema, SchemaFactory } from '../../lib';
2+
3+
@Schema({ validateBeforeSave: false, _id: true, autoIndex: true })
4+
class ChildClass {
5+
@Prop()
6+
id: number;
7+
8+
@Prop()
9+
name: string;
10+
}
11+
12+
@Schema({
13+
validateBeforeSave: false,
14+
_id: true,
15+
autoIndex: true,
16+
timestamps: true,
17+
})
18+
class ExampleClass {
19+
@Prop({ required: true })
20+
children: ChildClass;
21+
22+
@Prop([ChildClass])
23+
nodes: ChildClass[];
24+
25+
@Prop()
26+
array: Array<any>;
27+
}
28+
29+
describe('SchemaFactory', () => {
30+
it('should populate the schema options', () => {
31+
const schema = SchemaFactory.createForClass(ExampleClass) as any;
32+
33+
expect(schema.$timestamps).toBeDefined();
34+
expect(schema.options).toEqual(
35+
jasmine.objectContaining({
36+
validateBeforeSave: false,
37+
_id: true,
38+
autoIndex: true,
39+
timestamps: true,
40+
}),
41+
);
42+
43+
expect(schema.childSchemas[0].schema).toEqual(
44+
jasmine.objectContaining({
45+
options: jasmine.objectContaining({
46+
validateBeforeSave: false,
47+
_id: true,
48+
autoIndex: true,
49+
}),
50+
}),
51+
);
52+
});
53+
});

0 commit comments

Comments
 (0)