Identify the owner when both sides defines a many to many relationship (#7741)
This commit is contained in:
1 parent
3ecbec9685
commit
0b9a6d5a52
2 files changed
+673
-60
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
|
||||||
@@ -58,12 +59,33 @@ const PROPERTY_TYPES: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 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
|
||||||
*/
|
*/
|
||||||
function defineProperty(
|
function defineProperty(
|
||||||
MikroORMEntity: EntityConstructor<any>,
|
MikroORMEntity: EntityConstructor<any>,
|
||||||
field: SchemaMetadata
|
field: SchemaMetadata
|
||||||
) {
|
) {
|
||||||
/**
|
/**
|
||||||
* Defining an enum property
|
* Defining an enum property
|
||||||
*/
|
*/
|
||||||
@@ -88,19 +110,19 @@ function defineProperty(
|
|||||||
nullable: field.nullable,
|
nullable: field.nullable,
|
||||||
default: field.defaultValue,
|
default: field.defaultValue,
|
||||||
})(MikroORMEntity.prototype, field.fieldName)
|
})(MikroORMEntity.prototype, field.fieldName)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines has one relationship on the Mikro ORM entity.
|
* Defines has one relationship on the Mikro ORM entity.
|
||||||
*/
|
*/
|
||||||
function defineHasOneRelationship(
|
function defineHasOneRelationship(
|
||||||
MikroORMEntity: EntityConstructor<any>,
|
MikroORMEntity: EntityConstructor<any>,
|
||||||
relationship: RelationshipMetadata,
|
relationship: RelationshipMetadata,
|
||||||
relatedEntity: DmlEntity<
|
relatedEntity: DmlEntity<
|
||||||
Record<string, SchemaType<any> | RelationshipType<any>>
|
Record<string, SchemaType<any> | RelationshipType<any>>
|
||||||
>,
|
>,
|
||||||
cascades: EntityCascades<string[]>
|
cascades: EntityCascades<string[]>
|
||||||
) {
|
) {
|
||||||
const relatedModelName = upperCaseFirst(relatedEntity.name)
|
const relatedModelName = upperCaseFirst(relatedEntity.name)
|
||||||
const shouldRemoveRelated = !!cascades.delete?.includes(relationship.name)
|
const shouldRemoveRelated = !!cascades.delete?.includes(relationship.name)
|
||||||
|
|
||||||
@@ -112,19 +134,19 @@ function defineHasOneRelationship(
|
|||||||
? (["perist", "soft-remove"] as any)
|
? (["perist", "soft-remove"] as any)
|
||||||
: undefined,
|
: undefined,
|
||||||
})(MikroORMEntity.prototype, relationship.name)
|
})(MikroORMEntity.prototype, relationship.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines has many relationship on the Mikro ORM entity
|
* Defines has many relationship on the Mikro ORM entity
|
||||||
*/
|
*/
|
||||||
function defineHasManyRelationship(
|
function defineHasManyRelationship(
|
||||||
MikroORMEntity: EntityConstructor<any>,
|
MikroORMEntity: EntityConstructor<any>,
|
||||||
relationship: RelationshipMetadata,
|
relationship: RelationshipMetadata,
|
||||||
relatedEntity: DmlEntity<
|
relatedEntity: DmlEntity<
|
||||||
Record<string, SchemaType<any> | RelationshipType<any>>
|
Record<string, SchemaType<any> | RelationshipType<any>>
|
||||||
>,
|
>,
|
||||||
cascades: EntityCascades<string[]>
|
cascades: EntityCascades<string[]>
|
||||||
) {
|
) {
|
||||||
const relatedModelName = upperCaseFirst(relatedEntity.name)
|
const relatedModelName = upperCaseFirst(relatedEntity.name)
|
||||||
const shouldRemoveRelated = !!cascades.delete?.includes(relationship.name)
|
const shouldRemoveRelated = !!cascades.delete?.includes(relationship.name)
|
||||||
|
|
||||||
@@ -136,9 +158,9 @@ function defineHasManyRelationship(
|
|||||||
? (["perist", "soft-remove"] as any)
|
? (["perist", "soft-remove"] as any)
|
||||||
: undefined,
|
: undefined,
|
||||||
})(MikroORMEntity.prototype, relationship.name)
|
})(MikroORMEntity.prototype, relationship.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines belongs to relationship on the Mikro ORM entity. The belongsTo
|
* Defines belongs to relationship on the Mikro ORM entity. The belongsTo
|
||||||
* relationship inspects the related entity for the other side of
|
* relationship inspects the related entity for the other side of
|
||||||
* the relationship and then uses one of the following Mikro ORM
|
* the relationship and then uses one of the following Mikro ORM
|
||||||
@@ -147,13 +169,13 @@ function defineHasManyRelationship(
|
|||||||
* - OneToOne: When the other side uses "hasOne" with "owner: true"
|
* - OneToOne: When the other side uses "hasOne" with "owner: true"
|
||||||
* - ManyToOne: When the other side uses "hasMany"
|
* - ManyToOne: When the other side uses "hasMany"
|
||||||
*/
|
*/
|
||||||
function defineBelongsToRelationship(
|
function defineBelongsToRelationship(
|
||||||
MikroORMEntity: EntityConstructor<any>,
|
MikroORMEntity: EntityConstructor<any>,
|
||||||
relationship: RelationshipMetadata,
|
relationship: RelationshipMetadata,
|
||||||
relatedEntity: DmlEntity<
|
relatedEntity: DmlEntity<
|
||||||
Record<string, SchemaType<any> | RelationshipType<any>>
|
Record<string, SchemaType<any> | RelationshipType<any>>
|
||||||
>
|
>
|
||||||
) {
|
) {
|
||||||
const mappedBy =
|
const mappedBy =
|
||||||
relationship.mappedBy || camelToSnakeCase(MikroORMEntity.name)
|
relationship.mappedBy || camelToSnakeCase(MikroORMEntity.name)
|
||||||
const { schema: relationSchema, cascades: relationCascades } =
|
const { schema: relationSchema, cascades: relationCascades } =
|
||||||
@@ -219,34 +241,94 @@ function defineBelongsToRelationship(
|
|||||||
throw new Error(
|
throw new Error(
|
||||||
`Invalid relationship reference for "${mappedBy}" on "${relatedEntity.name}" entity. Make sure to define a hasOne or hasMany relationship`
|
`Invalid relationship reference for "${mappedBy}" on "${relatedEntity.name}" entity. Make sure to define a hasOne or hasMany relationship`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a many to many relationship on the Mikro ORM entity
|
* Defines a many to many relationship on the Mikro ORM entity
|
||||||
*/
|
*/
|
||||||
function defineManyToManyRelationship(
|
function defineManyToManyRelationship(
|
||||||
MikroORMEntity: EntityConstructor<any>,
|
MikroORMEntity: EntityConstructor<any>,
|
||||||
relationship: RelationshipMetadata,
|
relationship: RelationshipMetadata,
|
||||||
relatedEntity: DmlEntity<
|
relatedEntity: DmlEntity<
|
||||||
Record<string, SchemaType<any> | RelationshipType<any>>
|
Record<string, SchemaType<any> | RelationshipType<any>>
|
||||||
>,
|
>,
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a DML entity schema field as a Mikro ORM relationship
|
* Defines a DML entity schema field as a Mikro ORM relationship
|
||||||
*/
|
*/
|
||||||
function defineRelationship(
|
function defineRelationship(
|
||||||
MikroORMEntity: EntityConstructor<any>,
|
MikroORMEntity: EntityConstructor<any>,
|
||||||
relationship: RelationshipMetadata,
|
relationship: RelationshipMetadata,
|
||||||
cascades: EntityCascades<string[]>
|
cascades: EntityCascades<string[]>
|
||||||
) {
|
) {
|
||||||
/**
|
/**
|
||||||
* We expect the relationship.entity to be a function that
|
* We expect the relationship.entity to be a function that
|
||||||
* lazily returns the related entity
|
* lazily returns the related entity
|
||||||
@@ -307,17 +389,13 @@ function defineRelationship(
|
|||||||
)
|
)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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()
|
||||||
|
|
||||||
@@ -350,4 +428,5 @@ export function createMikrORMEntity<T extends DmlEntity<any>>(
|
|||||||
* Converting class to a MikroORM entity
|
* Converting class to a MikroORM entity
|
||||||
*/
|
*/
|
||||||
return Entity({ tableName })(MikroORMEntity) as Infer<T>
|
return Entity({ tableName })(MikroORMEntity) as Infer<T>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user