diff --git a/packages/mongoose/src/decorators/index.ts b/packages/mongoose/src/decorators/index.ts index fc777ed96ce..3963e130492 100644 --- a/packages/mongoose/src/decorators/index.ts +++ b/packages/mongoose/src/decorators/index.ts @@ -6,5 +6,6 @@ export * from "./postHook"; export * from "./preHook"; export * from "./ref"; export * from "./schema"; -export * from "./unique"; export * from "./select"; +export * from "./unique"; +export * from "./virtualRef"; diff --git a/packages/mongoose/src/decorators/virtualRef.ts b/packages/mongoose/src/decorators/virtualRef.ts new file mode 100644 index 00000000000..bf47b149944 --- /dev/null +++ b/packages/mongoose/src/decorators/virtualRef.ts @@ -0,0 +1,49 @@ +import {PropertyMetadata, PropertyRegistry} from "@tsed/common"; +import {MONGOOSE_SCHEMA} from "../constants"; + +export type VirtualRef = T | null; +export type VirtualRefs = T[]; + +/** + * Define a property as mongoose virtual reference to other Model (decorated with @Model). + * + * Warning: To avoid circular dependencies, do not use the virtual reference model in + * anything except a type declaration. Using the virtual reference model will prevent + * typescript transpiler from stripping away the import statement and cause a circular + * import in node. + * + * ### Example + * + * ```typescript + * + * @Model() + * class FooModel { + * + * @VirtualRef("Foo2Model", "foo") + * field: VirtualRef + * + * @VirtualRef("Foo2Model", "foo") + * list: VirtualRefs + * } + * + * @Model() + * class Foo2Model { + * @Ref(FooModel) + * foo: Ref; + * } + * ``` + * + * @param type + * @returns {Function} + * @decorator + * @mongoose + */ +export function VirtualRef(type: string, foreignField: string) { + return PropertyRegistry.decorate((propertyMetadata: PropertyMetadata) => { + propertyMetadata.store.merge(MONGOOSE_SCHEMA, { + ref: type, + localField: propertyMetadata.name, + foreignField + }); + }); +} diff --git a/packages/mongoose/test/decorators/virtualRef.spec.ts b/packages/mongoose/test/decorators/virtualRef.spec.ts new file mode 100644 index 00000000000..3ef783601e7 --- /dev/null +++ b/packages/mongoose/test/decorators/virtualRef.spec.ts @@ -0,0 +1,23 @@ +import {Store} from "@tsed/core"; +import {descriptorOf} from "@tsed/core"; +import {MONGOOSE_SCHEMA} from "../../src/constants"; +import {VirtualRef} from "../../src/decorators"; +import {expect} from "chai"; + +describe("@VirtualRef()", () => { + class Test {} + class RefTest {} + + before(() => { + VirtualRef("RefTest", "foreign")(Test, "test", descriptorOf(Test, "test")); + this.store = Store.from(Test, "test", descriptorOf(Test, "test")); + }); + + it("should set metadata", () => { + expect(this.store.get(MONGOOSE_SCHEMA)).to.deep.eq({ + ref: "RefTest", + foreignField: "foreign", + localField: "test" + }); + }); +});