diff --git a/.changeset/good-moles-camp.md b/.changeset/good-moles-camp.md new file mode 100644 index 0000000000000..9e1a197bb90f3 --- /dev/null +++ b/.changeset/good-moles-camp.md @@ -0,0 +1,5 @@ +--- +"@medusajs/utils": patch +--- + +chore(utils): DML#hasOne allow mappedBy to not be defined diff --git a/packages/core/utils/src/dml/__tests__/entity-builder.spec.ts b/packages/core/utils/src/dml/__tests__/entity-builder.spec.ts index 4dba3a02b3a1a..3dac21d178ee7 100644 --- a/packages/core/utils/src/dml/__tests__/entity-builder.spec.ts +++ b/packages/core/utils/src/dml/__tests__/entity-builder.spec.ts @@ -2461,6 +2461,93 @@ describe("Entity builder", () => { }) }) + test("define custom mappedBy key to undefined to not get the auto generated value", () => { + const email = model.define("email", { + email: model.text(), + isVerified: model.boolean(), + }) + + const user = model.define("user", { + id: model.number(), + username: model.text(), + email: model.hasOne(() => email, { mappedBy: undefined }), + }) + + const User = toMikroORMEntity(user) + expectTypeOf(new User()).toMatchTypeOf<{ + id: number + username: string + email: { email: string; isVerified: boolean } + }>() + + const metaData = MetadataStorage.getMetadataFromDecorator(User) + expect(metaData.className).toEqual("User") + expect(metaData.path).toEqual("User") + expect(metaData.properties).toEqual({ + id: { + reference: "scalar", + type: "number", + columnType: "integer", + name: "id", + fieldName: "id", + nullable: false, + getter: false, + setter: false, + }, + username: { + reference: "scalar", + type: "string", + columnType: "text", + name: "username", + fieldName: "username", + nullable: false, + getter: false, + setter: false, + }, + email: { + reference: "1:1", + name: "email", + entity: "Email", + nullable: false, + }, + created_at: { + reference: "scalar", + type: "date", + columnType: "timestamptz", + name: "created_at", + fieldName: "created_at", + defaultRaw: "now()", + onCreate: expect.any(Function), + nullable: false, + getter: false, + setter: false, + }, + updated_at: { + reference: "scalar", + type: "date", + columnType: "timestamptz", + name: "updated_at", + fieldName: "updated_at", + defaultRaw: "now()", + onCreate: expect.any(Function), + onUpdate: expect.any(Function), + nullable: false, + getter: false, + setter: false, + }, + deleted_at: { + reference: "scalar", + type: "date", + columnType: "timestamptz", + name: "deleted_at", + fieldName: "deleted_at", + nullable: true, + getter: false, + setter: false, + }, + }) + }) + test("define custom mappedBy key for relationship", () => { const email = model.define("email", { email: model.text(), @@ -2899,6 +2986,7 @@ describe("Entity builder", () => { username: model.text(), email: model.hasOne(() => email, { foreignKey: true, + mappedBy: undefined, }), }) @@ -3010,6 +3098,7 @@ describe("Entity builder", () => { emails: model .hasOne(() => email, { foreignKey: true, + mappedBy: undefined, }) .nullable(), }) @@ -3265,6 +3354,7 @@ describe("Entity builder", () => { entity: "Email", nullable: false, cascade: ["persist", "soft-remove"], + mappedBy: "user", }, email_id: { columnType: "text", @@ -3440,6 +3530,7 @@ describe("Entity builder", () => { entity: "Email", nullable: false, cascade: ["persist", "soft-remove"], + mappedBy: "user", }, email_id: { columnType: "text", diff --git a/packages/core/utils/src/dml/helpers/entity-builder/define-relationship.ts b/packages/core/utils/src/dml/helpers/entity-builder/define-relationship.ts index b41a704560ff5..3d7f91cb12af2 100644 --- a/packages/core/utils/src/dml/helpers/entity-builder/define-relationship.ts +++ b/packages/core/utils/src/dml/helpers/entity-builder/define-relationship.ts @@ -11,17 +11,18 @@ import { ManyToOne, OneToMany, OneToOne, + OneToOneOptions, OnInit, Property, rel, } from "@mikro-orm/core" +import { camelToSnakeCase, pluralize } from "../../../common" import { DmlEntity } from "../../entity" -import { HasOne } from "../../relations/has-one" import { HasMany } from "../../relations/has-many" -import { parseEntityName } from "./parse-entity-name" -import { camelToSnakeCase, pluralize } from "../../../common" -import { applyEntityIndexes } from "../mikro-orm/apply-indexes" +import { HasOne } from "../../relations/has-one" import { ManyToMany as DmlManyToMany } from "../../relations/many-to-many" +import { applyEntityIndexes } from "../mikro-orm/apply-indexes" +import { parseEntityName } from "./parse-entity-name" import { HasOneWithForeignKey } from "../../relations/has-one-fk" type Context = { @@ -141,14 +142,19 @@ export function defineHasOneRelationship( ) { const shouldRemoveRelated = !!cascades.delete?.includes(relationship.name) + let mappedBy: string | undefined = camelToSnakeCase(MikroORMEntity.name) + if ("mappedBy" in relationship) { + mappedBy = relationship.mappedBy + } + OneToOne({ entity: relatedModelName, nullable: relationship.nullable, - mappedBy: relationship.mappedBy || camelToSnakeCase(MikroORMEntity.name), + ...(mappedBy ? { mappedBy } : {}), cascade: shouldRemoveRelated ? (["persist", "soft-remove"] as any) : undefined, - })(MikroORMEntity.prototype, relationship.name) + } as OneToOneOptions)(MikroORMEntity.prototype, relationship.name) } /** @@ -163,12 +169,10 @@ export function defineHasOneWithFKRelationship( ) { const foreignKeyName = camelToSnakeCase(`${relationship.name}Id`) const shouldRemoveRelated = !!cascades.delete?.includes(relationship.name) - let mappedBy: string | undefined + let mappedBy: string | undefined = camelToSnakeCase(MikroORMEntity.name) if ("mappedBy" in relationship) { mappedBy = relationship.mappedBy - } else { - mappedBy = camelToSnakeCase(MikroORMEntity.name) } OneToOne({ @@ -178,7 +182,7 @@ export function defineHasOneWithFKRelationship( cascade: shouldRemoveRelated ? (["persist", "soft-remove"] as any) : undefined, - } as any)(MikroORMEntity.prototype, relationship.name) + } as OneToOneOptions)(MikroORMEntity.prototype, relationship.name) Property({ type: "string", diff --git a/packages/core/utils/src/dml/relations/base.ts b/packages/core/utils/src/dml/relations/base.ts index ea343af09b2e2..67b1110efc1d4 100644 --- a/packages/core/utils/src/dml/relations/base.ts +++ b/packages/core/utils/src/dml/relations/base.ts @@ -69,7 +69,9 @@ export abstract class BaseRelationship implements RelationshipType { return { name: relationshipName, nullable: false, - mappedBy: this.options.mappedBy, + ...("mappedBy" in this.options + ? { mappedBy: this.options.mappedBy } + : {}), options: this.options, searchable: this.#searchable, entity: this.#referencedEntity,