Identify the owner when both sides defines a many to many relationship (#7741)

This commit is contained in:
Harminder Virk authored and GitHub committed 2024-06-17 14:47:14 +05:30
1 parent 3ecbec9685
commit 0b9a6d5a52
2 files changed
+649 -36

No files matched your search

@@ -18,7 +18,8 @@ describe("Entity builder", () => {
email: model.text(), email: model.text(),
}) })
const User = createMikrORMEntity(user) const entityBuilder = createMikrORMEntity()
const User = entityBuilder(user)
expectTypeOf(new User()).toMatchTypeOf<{ expectTypeOf(new User()).toMatchTypeOf<{
id: number id: number
username: string username: string
@@ -67,7 +68,8 @@ describe("Entity builder", () => {
email: model.text(), email: model.text(),
}) })
const User = createMikrORMEntity(user) const entityBuilder = createMikrORMEntity()
const User = entityBuilder(user)
expectTypeOf(new User()).toMatchTypeOf<{ expectTypeOf(new User()).toMatchTypeOf<{
id: number id: number
username: string username: string
@@ -117,7 +119,8 @@ describe("Entity builder", () => {
email: model.text(), email: model.text(),
}) })
const User = createMikrORMEntity(user) const entityBuilder = createMikrORMEntity()
const User = entityBuilder(user)
expectTypeOf(new User()).toMatchTypeOf<{ expectTypeOf(new User()).toMatchTypeOf<{
id: number id: number
username: string | null username: string | null
@@ -167,7 +170,8 @@ describe("Entity builder", () => {
role: model.enum(["moderator", "admin", "guest"]), role: model.enum(["moderator", "admin", "guest"]),
}) })
const User = createMikrORMEntity(user) const entityBuilder = createMikrORMEntity()
const User = entityBuilder(user)
expectTypeOf(new User()).toMatchTypeOf<{ expectTypeOf(new User()).toMatchTypeOf<{
id: number id: number
username: string username: string
@@ -231,7 +235,8 @@ describe("Entity builder", () => {
role: model.enum(["moderator", "admin", "guest"]).default("guest"), role: model.enum(["moderator", "admin", "guest"]).default("guest"),
}) })
const User = createMikrORMEntity(user) const entityBuilder = createMikrORMEntity()
const User = entityBuilder(user)
expectTypeOf(new User()).toMatchTypeOf<{ expectTypeOf(new User()).toMatchTypeOf<{
id: number id: number
username: string username: string
@@ -296,7 +301,8 @@ describe("Entity builder", () => {
role: model.enum(["moderator", "admin", "guest"]).nullable(), role: model.enum(["moderator", "admin", "guest"]).nullable(),
}) })
const User = createMikrORMEntity(user) const entityBuilder = createMikrORMEntity()
const User = entityBuilder(user)
expectTypeOf(new User()).toMatchTypeOf<{ expectTypeOf(new User()).toMatchTypeOf<{
id: number id: number
username: string username: string
@@ -366,7 +372,8 @@ describe("Entity builder", () => {
email: model.hasOne(() => email), email: model.hasOne(() => email),
}) })
const User = createMikrORMEntity(user) const entityBuilder = createMikrORMEntity()
const User = entityBuilder(user)
expectTypeOf(new User()).toMatchTypeOf<{ expectTypeOf(new User()).toMatchTypeOf<{
id: number id: number
username: string username: string
@@ -418,7 +425,8 @@ describe("Entity builder", () => {
emails: model.hasOne(() => email).nullable(), emails: model.hasOne(() => email).nullable(),
}) })
const User = createMikrORMEntity(user) const entityBuilder = createMikrORMEntity()
const User = entityBuilder(user)
expectTypeOf(new User()).toMatchTypeOf<{ expectTypeOf(new User()).toMatchTypeOf<{
id: number id: number
@@ -471,7 +479,8 @@ describe("Entity builder", () => {
email: model.hasOne(() => email, { mappedBy: "owner" }), email: model.hasOne(() => email, { mappedBy: "owner" }),
}) })
const User = createMikrORMEntity(user) const entityBuilder = createMikrORMEntity()
const User = entityBuilder(user)
expectTypeOf(new User()).toMatchTypeOf<{ expectTypeOf(new User()).toMatchTypeOf<{
id: number id: number
username: string username: string
@@ -527,7 +536,8 @@ describe("Entity builder", () => {
delete: ["email"], delete: ["email"],
}) })
const User = createMikrORMEntity(user) const entityBuilder = createMikrORMEntity()
const User = entityBuilder(user)
expectTypeOf(new User()).toMatchTypeOf<{ expectTypeOf(new User()).toMatchTypeOf<{
id: number id: number
username: string username: string
@@ -566,7 +576,7 @@ describe("Entity builder", () => {
}, },
}) })
const Email = createMikrORMEntity(email) const Email = entityBuilder(email)
const emailMetaData = MetadataStorage.getMetadataFromDecorator(Email) const emailMetaData = MetadataStorage.getMetadataFromDecorator(Email)
expect(emailMetaData.className).toEqual("Email") expect(emailMetaData.className).toEqual("Email")
expect(emailMetaData.path).toEqual("Email") expect(emailMetaData.path).toEqual("Email")
@@ -610,7 +620,8 @@ describe("Entity builder", () => {
delete: ["email"], delete: ["email"],
}) })
const User = createMikrORMEntity(user) const entityBuilder = createMikrORMEntity()
const User = entityBuilder(user)
expectTypeOf(new User()).toMatchTypeOf<{ expectTypeOf(new User()).toMatchTypeOf<{
id: number id: number
username: string username: string
@@ -656,7 +667,7 @@ describe("Entity builder", () => {
}, },
}) })
const Email = createMikrORMEntity(email) const Email = entityBuilder(email)
const emailMetaData = MetadataStorage.getMetadataFromDecorator(Email) const emailMetaData = MetadataStorage.getMetadataFromDecorator(Email)
expect(emailMetaData.className).toEqual("Email") expect(emailMetaData.className).toEqual("Email")
expect(emailMetaData.path).toEqual("Email") expect(emailMetaData.path).toEqual("Email")
@@ -706,7 +717,8 @@ describe("Entity builder", () => {
emails: model.hasMany(() => email), emails: model.hasMany(() => email),
}) })
const User = createMikrORMEntity(user) const entityBuilder = createMikrORMEntity()
const User = entityBuilder(user)
expectTypeOf(new User()).toMatchTypeOf<{ expectTypeOf(new User()).toMatchTypeOf<{
id: number id: number
username: string username: string
@@ -760,7 +772,8 @@ describe("Entity builder", () => {
}), }),
}) })
const User = createMikrORMEntity(user) const entityBuilder = createMikrORMEntity()
const User = entityBuilder(user)
expectTypeOf(new User()).toMatchTypeOf<{ expectTypeOf(new User()).toMatchTypeOf<{
id: number id: number
@@ -817,7 +830,8 @@ describe("Entity builder", () => {
delete: ["emails"], delete: ["emails"],
}) })
const User = createMikrORMEntity(user) const entityBuilder = createMikrORMEntity()
const User = entityBuilder(user)
expectTypeOf(new User()).toMatchTypeOf<{ expectTypeOf(new User()).toMatchTypeOf<{
id: number id: number
username: string username: string
@@ -875,8 +889,9 @@ describe("Entity builder", () => {
delete: ["emails"], delete: ["emails"],
}) })
const User = createMikrORMEntity(user) const entityBuilder = createMikrORMEntity()
const Email = createMikrORMEntity(email) const User = entityBuilder(user)
const Email = entityBuilder(email)
expectTypeOf(new User()).toMatchTypeOf<{ expectTypeOf(new User()).toMatchTypeOf<{
id: number id: number
username: string username: string
@@ -973,8 +988,9 @@ describe("Entity builder", () => {
email: model.hasOne(() => email), email: model.hasOne(() => email),
}) })
const User = createMikrORMEntity(user) const entityBuilder = createMikrORMEntity()
const Email = createMikrORMEntity(email) const User = entityBuilder(user)
const Email = entityBuilder(email)
expectTypeOf(new User()).toMatchTypeOf<{ expectTypeOf(new User()).toMatchTypeOf<{
id: number id: number
@@ -1081,8 +1097,9 @@ describe("Entity builder", () => {
email: model.hasOne(() => email), email: model.hasOne(() => email),
}) })
const User = createMikrORMEntity(user) const entityBuilder = createMikrORMEntity()
const Email = createMikrORMEntity(email) const User = entityBuilder(user)
const Email = entityBuilder(email)
expectTypeOf(new User()).toMatchTypeOf<{ expectTypeOf(new User()).toMatchTypeOf<{
id: number id: number
@@ -1189,8 +1206,9 @@ describe("Entity builder", () => {
emails: model.hasMany(() => email), emails: model.hasMany(() => email),
}) })
const User = createMikrORMEntity(user) const entityBuilder = createMikrORMEntity()
const Email = createMikrORMEntity(email) const User = entityBuilder(user)
const Email = entityBuilder(email)
expectTypeOf(new User()).toMatchTypeOf<{ expectTypeOf(new User()).toMatchTypeOf<{
id: number id: number
@@ -1304,8 +1322,9 @@ describe("Entity builder", () => {
emails: model.hasMany(() => email), emails: model.hasMany(() => email),
}) })
const User = createMikrORMEntity(user) const entityBuilder = createMikrORMEntity()
const Email = createMikrORMEntity(email) const User = entityBuilder(user)
const Email = entityBuilder(email)
expectTypeOf(new User()).toMatchTypeOf<{ expectTypeOf(new User()).toMatchTypeOf<{
id: number id: number
@@ -1418,7 +1437,8 @@ describe("Entity builder", () => {
username: model.text(), username: model.text(),
}) })
expect(() => createMikrORMEntity(email)).toThrow( const entityBuilder = createMikrORMEntity()
expect(() => entityBuilder(email)).toThrow(
'Missing property "email" on "user" entity. Make sure to define it as a relationship' 'Missing property "email" on "user" entity. Make sure to define it as a relationship'
) )
}) })
@@ -1438,7 +1458,8 @@ describe("Entity builder", () => {
email: model.manyToMany(() => email), email: model.manyToMany(() => email),
}) })
expect(() => createMikrORMEntity(email)).toThrow( const entityBuilder = createMikrORMEntity()
expect(() => entityBuilder(email)).toThrow(
'Invalid relationship reference for "email" on "user" entity. Make sure to define a hasOne or hasMany relationship' 'Invalid relationship reference for "email" on "user" entity. Make sure to define a hasOne or hasMany relationship'
) )
}) })
@@ -1484,8 +1505,9 @@ describe("Entity builder", () => {
teams: model.manyToMany(() => team), teams: model.manyToMany(() => team),
}) })
const User = createMikrORMEntity(user) const entityBuilder = createMikrORMEntity()
const Team = createMikrORMEntity(team) const User = entityBuilder(user)
const Team = entityBuilder(team)
expectTypeOf(new User()).toMatchTypeOf<{ expectTypeOf(new User()).toMatchTypeOf<{
id: number id: number
@@ -1539,6 +1561,7 @@ describe("Entity builder", () => {
reference: "m:n", reference: "m:n",
name: "teams", name: "teams",
entity: "Team", entity: "Team",
pivotTable: "team_users",
}, },
}) })
@@ -1568,6 +1591,517 @@ describe("Entity builder", () => {
reference: "m:n", reference: "m:n",
name: "users", name: "users",
entity: "User", entity: "User",
pivotTable: "team_users",
},
})
})
test("define mappedBy on one side", () => {
const model = new EntityBuilder()
const team = model.define("team", {
id: model.number(),
name: model.text(),
users: model.manyToMany(() => user),
})
const user = model.define("user", {
id: model.number(),
username: model.text(),
teams: model.manyToMany(() => team, { mappedBy: "users" }),
})
const entityBuilder = createMikrORMEntity()
const User = entityBuilder(user)
const Team = entityBuilder(team)
expectTypeOf(new User()).toMatchTypeOf<{
id: number
username: string
teams: EntityConstructor<{
id: number
name: string
users: EntityConstructor<{
id: number
username: string
}>
}>
}>()
expectTypeOf(new Team()).toMatchTypeOf<{
id: number
name: string
users: EntityConstructor<{
id: number
username: string
teams: EntityConstructor<{
id: number
name: string
}>
}>
}>()
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",
nullable: false,
getter: false,
setter: false,
},
username: {
reference: "scalar",
type: "string",
columnType: "text",
name: "username",
nullable: false,
getter: false,
setter: false,
},
teams: {
reference: "m:n",
name: "teams",
entity: "Team",
pivotTable: "team_users",
mappedBy: "users",
},
})
const teamMetaData = MetadataStorage.getMetadataFromDecorator(Team)
expect(teamMetaData.className).toEqual("Team")
expect(teamMetaData.path).toEqual("Team")
expect(teamMetaData.properties).toEqual({
id: {
reference: "scalar",
type: "number",
columnType: "integer",
name: "id",
nullable: false,
getter: false,
setter: false,
},
name: {
reference: "scalar",
type: "string",
columnType: "text",
name: "name",
nullable: false,
getter: false,
setter: false,
},
users: {
reference: "m:n",
name: "users",
entity: "User",
pivotTable: "team_users",
},
})
})
test("throw error when unable to locate relationship via mappedBy", () => {
const model = new EntityBuilder()
const team = model.define("team", {
id: model.number(),
name: model.text(),
})
const user = model.define("user", {
id: model.number(),
username: model.text(),
teams: model.manyToMany(() => team, { mappedBy: "users" }),
})
const entityBuilder = createMikrORMEntity()
expect(() => entityBuilder(user)).toThrow(
'Missing property "users" on "team" entity. Make sure to define it as a relationship'
)
})
test("throw error when mappedBy relationship is not a manyToMany", () => {
const model = new EntityBuilder()
const team = model.define("team", {
id: model.number(),
name: model.text(),
users: model.belongsTo(() => team, { mappedBy: "teams" }),
})
const user = model.define("user", {
id: model.number(),
username: model.text(),
teams: model.manyToMany(() => team, { mappedBy: "users" }),
})
const entityBuilder = createMikrORMEntity()
expect(() => entityBuilder(user)).toThrow(
'Invalid relationship reference for "users" on "team" entity. Make sure to define a manyToMany relationship'
)
})
test("define mappedBy on both sides", () => {
const model = new EntityBuilder()
const team = model.define("team", {
id: model.number(),
name: model.text(),
users: model.manyToMany(() => user, { mappedBy: "teams" }),
})
const user = model.define("user", {
id: model.number(),
username: model.text(),
teams: model.manyToMany(() => team, { mappedBy: "users" }),
})
const entityBuilder = createMikrORMEntity()
const User = entityBuilder(user)
const Team = entityBuilder(team)
expectTypeOf(new User()).toMatchTypeOf<{
id: number
username: string
teams: EntityConstructor<{
id: number
name: string
users: EntityConstructor<{
id: number
username: string
}>
}>
}>()
expectTypeOf(new Team()).toMatchTypeOf<{
id: number
name: string
users: EntityConstructor<{
id: number
username: string
teams: EntityConstructor<{
id: number
name: string
}>
}>
}>()
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",
nullable: false,
getter: false,
setter: false,
},
username: {
reference: "scalar",
type: "string",
columnType: "text",
name: "username",
nullable: false,
getter: false,
setter: false,
},
teams: {
reference: "m:n",
name: "teams",
entity: "Team",
pivotTable: "team_users",
mappedBy: "users",
},
})
const teamMetaData = MetadataStorage.getMetadataFromDecorator(Team)
expect(teamMetaData.className).toEqual("Team")
expect(teamMetaData.path).toEqual("Team")
expect(teamMetaData.properties).toEqual({
id: {
reference: "scalar",
type: "number",
columnType: "integer",
name: "id",
nullable: false,
getter: false,
setter: false,
},
name: {
reference: "scalar",
type: "string",
columnType: "text",
name: "name",
nullable: false,
getter: false,
setter: false,
},
users: {
reference: "m:n",
name: "users",
entity: "User",
pivotTable: "team_users",
/**
* The other side should be inversed in order for Mikro ORM
* to work. Both sides cannot have mappedBy.
*/
inversedBy: "teams",
},
})
})
test("define mappedBy on both sides and reverse order of registering entities", () => {
const model = new EntityBuilder()
const team = model.define("team", {
id: model.number(),
name: model.text(),
users: model.manyToMany(() => user, { mappedBy: "teams" }),
})
const user = model.define("user", {
id: model.number(),
username: model.text(),
teams: model.manyToMany(() => team, { mappedBy: "users" }),
})
const entityBuilder = createMikrORMEntity()
const Team = entityBuilder(team)
const User = entityBuilder(user)
expectTypeOf(new User()).toMatchTypeOf<{
id: number
username: string
teams: EntityConstructor<{
id: number
name: string
users: EntityConstructor<{
id: number
username: string
}>
}>
}>()
expectTypeOf(new Team()).toMatchTypeOf<{
id: number
name: string
users: EntityConstructor<{
id: number
username: string
teams: EntityConstructor<{
id: number
name: string
}>
}>
}>()
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",
nullable: false,
getter: false,
setter: false,
},
username: {
reference: "scalar",
type: "string",
columnType: "text",
name: "username",
nullable: false,
getter: false,
setter: false,
},
teams: {
reference: "m:n",
name: "teams",
entity: "Team",
pivotTable: "team_users",
/**
* The other side should be inversed in order for Mikro ORM
* to work. Both sides cannot have mappedBy.
*/
inversedBy: "users",
},
})
const teamMetaData = MetadataStorage.getMetadataFromDecorator(Team)
expect(teamMetaData.className).toEqual("Team")
expect(teamMetaData.path).toEqual("Team")
expect(teamMetaData.properties).toEqual({
id: {
reference: "scalar",
type: "number",
columnType: "integer",
name: "id",
nullable: false,
getter: false,
setter: false,
},
name: {
reference: "scalar",
type: "string",
columnType: "text",
name: "name",
nullable: false,
getter: false,
setter: false,
},
users: {
reference: "m:n",
name: "users",
entity: "User",
pivotTable: "team_users",
mappedBy: "teams",
},
})
})
test("define multiple many to many relationships to the same entity", () => {
const model = new EntityBuilder()
const team = model.define("team", {
id: model.number(),
name: model.text(),
activeTeamsUsers: model.manyToMany(() => user, {
mappedBy: "activeTeams",
}),
users: model.manyToMany(() => user, { mappedBy: "teams" }),
})
const user = model.define("user", {
id: model.number(),
username: model.text(),
activeTeams: model.manyToMany(() => team, {
mappedBy: "activeTeamsUsers",
}),
teams: model.manyToMany(() => team, { mappedBy: "users" }),
})
const entityBuilder = createMikrORMEntity()
const Team = entityBuilder(team)
const User = entityBuilder(user)
expectTypeOf(new User()).toMatchTypeOf<{
id: number
username: string
teams: EntityConstructor<{
id: number
name: string
users: EntityConstructor<{
id: number
username: string
}>
}>
activeTeams: EntityConstructor<{
id: number
name: string
users: EntityConstructor<{
id: number
username: string
}>
}>
}>()
expectTypeOf(new Team()).toMatchTypeOf<{
id: number
name: string
users: EntityConstructor<{
id: number
username: string
teams: EntityConstructor<{
id: number
name: string
}>
activeTeams: EntityConstructor<{
id: number
name: string
}>
}>
}>()
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",
nullable: false,
getter: false,
setter: false,
},
username: {
reference: "scalar",
type: "string",
columnType: "text",
name: "username",
nullable: false,
getter: false,
setter: false,
},
teams: {
reference: "m:n",
name: "teams",
entity: "Team",
pivotTable: "team_users",
/**
* The other side should be inversed in order for Mikro ORM
* to work. Both sides cannot have mappedBy.
*/
inversedBy: "users",
},
activeTeams: {
reference: "m:n",
name: "activeTeams",
entity: "Team",
pivotTable: "team_users",
inversedBy: "activeTeamsUsers",
},
})
const teamMetaData = MetadataStorage.getMetadataFromDecorator(Team)
expect(teamMetaData.className).toEqual("Team")
expect(teamMetaData.path).toEqual("Team")
expect(teamMetaData.properties).toEqual({
id: {
reference: "scalar",
type: "number",
columnType: "integer",
name: "id",
nullable: false,
getter: false,
setter: false,
},
name: {
reference: "scalar",
type: "string",
columnType: "text",
name: "name",
nullable: false,
getter: false,
setter: false,
},
users: {
reference: "m:n",
name: "users",
entity: "User",
pivotTable: "team_users",
mappedBy: "teams",
},
activeTeamsUsers: {
reference: "m:n",
name: "activeTeamsUsers",
entity: "User",
pivotTable: "team_users",
mappedBy: "activeTeams",
}, },
}) })
}) })
@@ -22,6 +22,7 @@ import type {
} from "../types" } from "../types"
import { HasOne } from "../relations/has-one" import { HasOne } from "../relations/has-one"
import { HasMany } from "../relations/has-many" import { HasMany } from "../relations/has-many"
import { ManyToMany as DmlManyToMany } from "../relations/many-to-many"
/** /**
* DML entity data types to PostgreSQL data types via * DML entity data types to PostgreSQL data types via
@@ -57,6 +58,27 @@ const PROPERTY_TYPES: {
json: "any", json: "any",
} }
/**
* Factory function to create the mikro orm entity builder. The return
* value is a function that can be used to convert DML entities
* to Mikro ORM entities.
*/
export function createMikrORMEntity() {
/**
* The following property is used to track many to many relationship
* between two entities. It is needed because we have to mark one
* of them as the owner of the relationship without exposing
* any user land APIs to explicitly define an owner.
*
* The object contains values as follows.
* - [entityname.relationship]: true // true means, it is already marked as owner
*
* Example:
* - [user.teams]: true // the teams relationship on user is an owner
* - [team.users] // cannot be an owner
*/
const MANY_TO_MANY_TRACKED_REALTIONS: Record<string, boolean> = {}
/** /**
* Defines a DML entity schema field as a Mikro ORM property * Defines a DML entity schema field as a Mikro ORM property
*/ */
@@ -233,9 +255,69 @@ function defineManyToManyRelationship(
cascades: EntityCascades<string[]> cascades: EntityCascades<string[]>
) { ) {
const relatedModelName = upperCaseFirst(relatedEntity.name) const relatedModelName = upperCaseFirst(relatedEntity.name)
let mappedBy = relationship.mappedBy
let inversedBy: undefined | string
/**
* A consistent pivot table name is created by:
*
* - Combining both the entity's names.
* - Sorting them by alphabetical order
* - Converting them from camelCase to snake_case.
* - And finally pluralizing the second entity name.
*/
const pivotTableName = [
MikroORMEntity.name.toLowerCase(),
relatedEntity.name.toLowerCase(),
]
.sort()
.map((token, index) => {
if (index === 1) {
return pluralize(camelToSnakeCase(token))
}
return camelToSnakeCase(token)
})
.join("_")
if (mappedBy) {
const otherSideRelation = relatedEntity.parse().schema[mappedBy]
if (!otherSideRelation) {
throw new Error(
`Missing property "${mappedBy}" on "${relatedEntity.name}" entity. Make sure to define it as a relationship`
)
}
if (otherSideRelation instanceof DmlManyToMany === false) {
throw new Error(
`Invalid relationship reference for "${mappedBy}" on "${relatedEntity.name}" entity. Make sure to define a manyToMany relationship`
)
}
/**
* Check if the other side has defined a mapped by and if that
* mapping is already tracked as the owner.
*
* - If yes, we will inverse our mapped by
* - Otherwise, we will track ourselves as the owner.
*/
if (
otherSideRelation.parse(mappedBy).mappedBy &&
MANY_TO_MANY_TRACKED_REALTIONS[`${relatedModelName}.${mappedBy}`]
) {
inversedBy = mappedBy
mappedBy = undefined
} else {
MANY_TO_MANY_TRACKED_REALTIONS[
`${MikroORMEntity.name}.${relationship.name}`
] = true
}
}
ManyToMany({ ManyToMany({
entity: relatedModelName, entity: relatedModelName,
mappedBy: relationship.mappedBy as any, pivotTable: pivotTableName,
...(mappedBy ? { mappedBy: mappedBy as any } : {}),
...(inversedBy ? { inversedBy: inversedBy as any } : {}),
})(MikroORMEntity.prototype, relationship.name) })(MikroORMEntity.prototype, relationship.name)
} }
@@ -312,12 +394,8 @@ function defineRelationship(
/** /**
* A helper function to define a Mikro ORM entity from a * A helper function to define a Mikro ORM entity from a
* DML entity. * DML entity.
* @todo: Handle soft deleted indexes and filters
* @todo: Finalize if custom pivot entities are needed
*/ */
export function createMikrORMEntity<T extends DmlEntity<any>>( return function createEntity<T extends DmlEntity<any>>(entity: T): Infer<T> {
entity: T
): Infer<T> {
class MikroORMEntity {} class MikroORMEntity {}
const { name, schema, cascades } = entity.parse() const { name, schema, cascades } = entity.parse()
@@ -351,3 +429,4 @@ export function createMikrORMEntity<T extends DmlEntity<any>>(
*/ */
return Entity({ tableName })(MikroORMEntity) as Infer<T> return Entity({ tableName })(MikroORMEntity) as Infer<T>
} }
}