fix: DML relation management for many to one relation ship foreign keys (#7790)
FIXES CORE-2369 cc @thetutlage Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
1 parent
25210369d9
commit
34c44078e7
9 files changed
+617
-226
No files matched your search
@@ -97,17 +97,36 @@ export interface EntityConstructor<Props> extends Function {
|
|||||||
new (): Props
|
new (): Props
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* From a IDmlEntity, infer the foreign keys name and type for belongsTo relation meaning hasOne and ManyToOne
|
||||||
|
*/
|
||||||
|
export type InferForeignKeys<T> = T extends IDmlEntity<infer Schema>
|
||||||
|
? {
|
||||||
|
[K in keyof Schema as Schema[K] extends RelationshipType<any>
|
||||||
|
? Schema[K]["type"] extends "belongsTo"
|
||||||
|
? `${K & string}_id`
|
||||||
|
: K
|
||||||
|
: K]: Schema[K] extends RelationshipType<infer R>
|
||||||
|
? Schema[K]["type"] extends "belongsTo"
|
||||||
|
? string
|
||||||
|
: Schema[K]
|
||||||
|
: Schema[K]
|
||||||
|
}
|
||||||
|
: never
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper to infer the schema type of a DmlEntity
|
* Helper to infer the schema type of a DmlEntity
|
||||||
*/
|
*/
|
||||||
export type Infer<T> = T extends IDmlEntity<infer Schema>
|
export type Infer<T> = T extends IDmlEntity<infer Schema>
|
||||||
? EntityConstructor<{
|
? EntityConstructor<
|
||||||
|
{
|
||||||
[K in keyof Schema]: Schema[K]["$dataType"] extends () => infer R
|
[K in keyof Schema]: Schema[K]["$dataType"] extends () => infer R
|
||||||
? Infer<R>
|
? Infer<R>
|
||||||
: Schema[K]["$dataType"] extends (() => infer R) | null
|
: Schema[K]["$dataType"] extends (() => infer R) | null
|
||||||
? Infer<R> | null
|
? Infer<R> | null
|
||||||
: Schema[K]["$dataType"]
|
: Schema[K]["$dataType"]
|
||||||
}>
|
} & InferForeignKeys<T>
|
||||||
|
>
|
||||||
: never
|
: never
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,7 +152,7 @@ export type EntityCascades<Relationships> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper to infer the instance type of a DmlEntity once converted as an Entity
|
* Helper to infer the instance type of a IDmlEntity once converted as an Entity
|
||||||
*/
|
*/
|
||||||
export type InferTypeOf<T extends IDmlEntity<any>> = InstanceType<Infer<T>>
|
export type InferTypeOf<T extends IDmlEntity<any>> = InstanceType<Infer<T>>
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { dirname, join } from "path"
|
import { dirname, join } from "path"
|
||||||
import {
|
import {
|
||||||
promises,
|
|
||||||
constants,
|
constants,
|
||||||
type Dirent,
|
type Dirent,
|
||||||
|
type MakeDirectoryOptions,
|
||||||
|
promises,
|
||||||
type RmOptions,
|
type RmOptions,
|
||||||
type StatOptions,
|
type StatOptions,
|
||||||
type WriteFileOptions,
|
type WriteFileOptions,
|
||||||
type MakeDirectoryOptions,
|
|
||||||
} from "fs"
|
} from "fs"
|
||||||
|
|
||||||
const { rm, stat, mkdir, access, readdir, readFile, writeFile } = promises
|
const { rm, stat, mkdir, access, readdir, readFile, writeFile } = promises
|
||||||
@@ -31,7 +31,7 @@ export class FileSystem {
|
|||||||
* Cleanup directory
|
* Cleanup directory
|
||||||
*/
|
*/
|
||||||
async cleanup(options?: RmOptions) {
|
async cleanup(options?: RmOptions) {
|
||||||
return rm(this.basePath, {
|
return await rm(this.basePath, {
|
||||||
recursive: true,
|
recursive: true,
|
||||||
maxRetries: 10,
|
maxRetries: 10,
|
||||||
force: true,
|
force: true,
|
||||||
@@ -61,7 +61,7 @@ export class FileSystem {
|
|||||||
* Remove a file
|
* Remove a file
|
||||||
*/
|
*/
|
||||||
async remove(filePath: string, options?: RmOptions) {
|
async remove(filePath: string, options?: RmOptions) {
|
||||||
return rm(this.makePath(filePath), {
|
return await rm(this.makePath(filePath), {
|
||||||
recursive: true,
|
recursive: true,
|
||||||
force: true,
|
force: true,
|
||||||
maxRetries: 2,
|
maxRetries: 2,
|
||||||
@@ -103,7 +103,7 @@ export class FileSystem {
|
|||||||
* Returns file contents
|
* Returns file contents
|
||||||
*/
|
*/
|
||||||
async contents(filePath: string) {
|
async contents(filePath: string) {
|
||||||
return readFile(this.makePath(filePath), "utf-8")
|
return await readFile(this.makePath(filePath), "utf-8")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -139,14 +139,14 @@ export class FileSystem {
|
|||||||
async createJson(filePath: string, contents: any, options?: JSONFileOptions) {
|
async createJson(filePath: string, contents: any, options?: JSONFileOptions) {
|
||||||
if (options && typeof options === "object") {
|
if (options && typeof options === "object") {
|
||||||
const { replacer, spaces, ...rest } = options
|
const { replacer, spaces, ...rest } = options
|
||||||
return this.create(
|
return await this.create(
|
||||||
filePath,
|
filePath,
|
||||||
JSON.stringify(contents, replacer, spaces),
|
JSON.stringify(contents, replacer, spaces),
|
||||||
rest
|
rest
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.create(filePath, JSON.stringify(contents), options)
|
return await this.create(filePath, JSON.stringify(contents), options)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
|
import { EntityConstructor } from "@medusajs/types"
|
||||||
import { MetadataStorage } from "@mikro-orm/core"
|
import { MetadataStorage } from "@mikro-orm/core"
|
||||||
import { expectTypeOf } from "expect-type"
|
import { expectTypeOf } from "expect-type"
|
||||||
import { DmlEntity } from "../entity"
|
import { DmlEntity } from "../entity"
|
||||||
import { EntityBuilder } from "../entity-builder"
|
import { model } from "../entity-builder"
|
||||||
import {
|
import {
|
||||||
createMikrORMEntity,
|
createMikrORMEntity,
|
||||||
|
toMikroOrmEntities,
|
||||||
toMikroORMEntity,
|
toMikroORMEntity,
|
||||||
} from "../helpers/create-mikro-orm-entity"
|
} from "../helpers/create-mikro-orm-entity"
|
||||||
import { EntityConstructor } from "../types"
|
|
||||||
|
|
||||||
describe("Entity builder", () => {
|
describe("Entity builder", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -15,7 +16,6 @@ describe("Entity builder", () => {
|
|||||||
|
|
||||||
describe("Entity builder | properties", () => {
|
describe("Entity builder | properties", () => {
|
||||||
test("should identify a DML entity correctly", () => {
|
test("should identify a DML entity correctly", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const user = model.define("user", {
|
const user = model.define("user", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
username: model.text(),
|
username: model.text(),
|
||||||
@@ -30,7 +30,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define an entity", () => {
|
test("define an entity", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const user = model.define("user", {
|
const user = model.define("user", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
username: model.text(),
|
username: model.text(),
|
||||||
@@ -38,8 +37,7 @@ describe("Entity builder", () => {
|
|||||||
spend_limit: model.bigNumber(),
|
spend_limit: model.bigNumber(),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
|
||||||
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
@@ -148,7 +146,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define a property with default value", () => {
|
test("define a property with default value", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const user = model.define("user", {
|
const user = model.define("user", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
username: model.text().default("foo"),
|
username: model.text().default("foo"),
|
||||||
@@ -156,8 +153,7 @@ describe("Entity builder", () => {
|
|||||||
spend_limit: model.bigNumber().default(500.4),
|
spend_limit: model.bigNumber().default(500.4),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
username: string
|
username: string
|
||||||
@@ -263,7 +259,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("mark property nullable", () => {
|
test("mark property nullable", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const user = model.define("user", {
|
const user = model.define("user", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
username: model.text().nullable(),
|
username: model.text().nullable(),
|
||||||
@@ -398,7 +393,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define an entity with enum property", () => {
|
test("define an entity with enum property", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const user = model.define("user", {
|
const user = model.define("user", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
username: model.text(),
|
username: model.text(),
|
||||||
@@ -406,8 +400,7 @@ describe("Entity builder", () => {
|
|||||||
role: model.enum(["moderator", "admin", "guest"]),
|
role: model.enum(["moderator", "admin", "guest"]),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
username: string
|
username: string
|
||||||
@@ -507,7 +500,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define enum property with default value", () => {
|
test("define enum property with default value", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const user = model.define("user", {
|
const user = model.define("user", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
username: model.text(),
|
username: model.text(),
|
||||||
@@ -515,8 +507,7 @@ describe("Entity builder", () => {
|
|||||||
role: model.enum(["moderator", "admin", "guest"]).default("guest"),
|
role: model.enum(["moderator", "admin", "guest"]).default("guest"),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
username: string
|
username: string
|
||||||
@@ -616,7 +607,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("mark enum property nullable", () => {
|
test("mark enum property nullable", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const user = model.define("user", {
|
const user = model.define("user", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
username: model.text(),
|
username: model.text(),
|
||||||
@@ -624,8 +614,7 @@ describe("Entity builder", () => {
|
|||||||
role: model.enum(["moderator", "admin", "guest"]).nullable(),
|
role: model.enum(["moderator", "admin", "guest"]).nullable(),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
username: string
|
username: string
|
||||||
@@ -730,7 +719,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("disallow defining created_at and updated_at timestamps", () => {
|
test("disallow defining created_at and updated_at timestamps", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
model.define("user", {
|
model.define("user", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
@@ -745,7 +733,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("disallow defining deleted_at timestamp", () => {
|
test("disallow defining deleted_at timestamp", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
model.define("user", {
|
model.define("user", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
@@ -759,15 +746,13 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define pg schema name in the entity name", () => {
|
test("define pg schema name in the entity name", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const user = model.define("public.user", {
|
const user = model.define("public.user", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
username: model.text(),
|
username: model.text(),
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
username: string
|
username: string
|
||||||
@@ -857,15 +842,13 @@ describe("Entity builder", () => {
|
|||||||
|
|
||||||
describe("Entity builder | id", () => {
|
describe("Entity builder | id", () => {
|
||||||
test("define an entity with id property", () => {
|
test("define an entity with id property", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const user = model.define("user", {
|
const user = model.define("user", {
|
||||||
id: model.id(),
|
id: model.id(),
|
||||||
username: model.text(),
|
username: model.text(),
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: string
|
id: string
|
||||||
username: string
|
username: string
|
||||||
@@ -956,15 +939,13 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("mark id as non-primary", () => {
|
test("mark id as non-primary", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const user = model.define("user", {
|
const user = model.define("user", {
|
||||||
id: model.id({ primaryKey: false }),
|
id: model.id({ primaryKey: false }),
|
||||||
username: model.text(),
|
username: model.text(),
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: string
|
id: string
|
||||||
username: string
|
username: string
|
||||||
@@ -1061,15 +1042,13 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define prefix for the id", () => {
|
test("define prefix for the id", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const user = model.define("user", {
|
const user = model.define("user", {
|
||||||
id: model.id({ primaryKey: false, prefix: "us" }),
|
id: model.id({ primaryKey: false, prefix: "us" }),
|
||||||
username: model.text(),
|
username: model.text(),
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: string
|
id: string
|
||||||
username: string
|
username: string
|
||||||
@@ -1168,7 +1147,6 @@ describe("Entity builder", () => {
|
|||||||
|
|
||||||
describe("Entity builder | primaryKey", () => {
|
describe("Entity builder | primaryKey", () => {
|
||||||
test("should create both id fields and primaryKey fields", () => {
|
test("should create both id fields and primaryKey fields", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const user = model.define("user", {
|
const user = model.define("user", {
|
||||||
id: model.id({ primaryKey: false }),
|
id: model.id({ primaryKey: false }),
|
||||||
email: model.text().primaryKey(),
|
email: model.text().primaryKey(),
|
||||||
@@ -1271,15 +1249,13 @@ describe("Entity builder", () => {
|
|||||||
|
|
||||||
describe("Entity builder | indexes", () => {
|
describe("Entity builder | indexes", () => {
|
||||||
test("define index on a field", () => {
|
test("define index on a field", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const user = model.define("user", {
|
const user = model.define("user", {
|
||||||
id: model.number().index(),
|
id: model.number().index(),
|
||||||
username: model.text(),
|
username: model.text(),
|
||||||
email: model.text().unique(),
|
email: model.text().unique(),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
username: string
|
username: string
|
||||||
@@ -1377,15 +1353,13 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define index when entity is using an explicit pg Schema", () => {
|
test("define index when entity is using an explicit pg Schema", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const user = model.define("platform.user", {
|
const user = model.define("platform.user", {
|
||||||
id: model.number().index(),
|
id: model.number().index(),
|
||||||
username: model.text(),
|
username: model.text(),
|
||||||
email: model.text().unique(),
|
email: model.text().unique(),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
username: string
|
username: string
|
||||||
@@ -1486,7 +1460,6 @@ describe("Entity builder", () => {
|
|||||||
|
|
||||||
describe("Entity builder | hasOne", () => {
|
describe("Entity builder | hasOne", () => {
|
||||||
test("define hasOne relationship", () => {
|
test("define hasOne relationship", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const email = model.define("email", {
|
const email = model.define("email", {
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
isVerified: model.boolean(),
|
isVerified: model.boolean(),
|
||||||
@@ -1498,8 +1471,7 @@ describe("Entity builder", () => {
|
|||||||
email: model.hasOne(() => email),
|
email: model.hasOne(() => email),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
username: string
|
username: string
|
||||||
@@ -1576,7 +1548,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("mark hasOne relationship as nullable", () => {
|
test("mark hasOne relationship as nullable", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const email = model.define("email", {
|
const email = model.define("email", {
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
isVerified: model.boolean(),
|
isVerified: model.boolean(),
|
||||||
@@ -1588,8 +1559,7 @@ describe("Entity builder", () => {
|
|||||||
emails: model.hasOne(() => email).nullable(),
|
emails: model.hasOne(() => email).nullable(),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
|
||||||
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
@@ -1667,7 +1637,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define custom mappedBy key for relationship", () => {
|
test("define custom mappedBy key for relationship", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const email = model.define("email", {
|
const email = model.define("email", {
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
isVerified: model.boolean(),
|
isVerified: model.boolean(),
|
||||||
@@ -1679,8 +1648,7 @@ describe("Entity builder", () => {
|
|||||||
email: model.hasOne(() => email, { mappedBy: "owner" }),
|
email: model.hasOne(() => email, { mappedBy: "owner" }),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
username: string
|
username: string
|
||||||
@@ -1752,7 +1720,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define delete cascades for the entity", () => {
|
test("define delete cascades for the entity", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const email = model.define("email", {
|
const email = model.define("email", {
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
isVerified: model.boolean(),
|
isVerified: model.boolean(),
|
||||||
@@ -1768,8 +1735,7 @@ describe("Entity builder", () => {
|
|||||||
delete: ["email"],
|
delete: ["email"],
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
username: string
|
username: string
|
||||||
@@ -1840,7 +1806,7 @@ describe("Entity builder", () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const Email = entityBuilder(email)
|
const Email = toMikroORMEntity(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")
|
||||||
@@ -1899,7 +1865,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define delete cascades with belongsTo on the other end", () => {
|
test("define delete cascades with belongsTo on the other end", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const email = model.define("email", {
|
const email = model.define("email", {
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
isVerified: model.boolean(),
|
isVerified: model.boolean(),
|
||||||
@@ -1916,8 +1881,7 @@ describe("Entity builder", () => {
|
|||||||
delete: ["email"],
|
delete: ["email"],
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
username: string
|
username: string
|
||||||
@@ -1995,7 +1959,7 @@ describe("Entity builder", () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const Email = entityBuilder(email)
|
const Email = toMikroORMEntity(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")
|
||||||
@@ -2027,6 +1991,15 @@ describe("Entity builder", () => {
|
|||||||
owner: true,
|
owner: true,
|
||||||
reference: "1:1",
|
reference: "1:1",
|
||||||
},
|
},
|
||||||
|
user_id: {
|
||||||
|
columnType: "text",
|
||||||
|
getter: false,
|
||||||
|
name: "user_id",
|
||||||
|
nullable: false,
|
||||||
|
reference: "scalar",
|
||||||
|
setter: false,
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
created_at: {
|
created_at: {
|
||||||
reference: "scalar",
|
reference: "scalar",
|
||||||
type: "date",
|
type: "date",
|
||||||
@@ -2065,7 +2038,6 @@ describe("Entity builder", () => {
|
|||||||
|
|
||||||
describe("Entity builder | hasMany", () => {
|
describe("Entity builder | hasMany", () => {
|
||||||
test("define hasMany relationship", () => {
|
test("define hasMany relationship", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const email = model.define("email", {
|
const email = model.define("email", {
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
isVerified: model.boolean(),
|
isVerified: model.boolean(),
|
||||||
@@ -2077,8 +2049,7 @@ describe("Entity builder", () => {
|
|||||||
emails: model.hasMany(() => email),
|
emails: model.hasMany(() => email),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
username: string
|
username: string
|
||||||
@@ -2150,7 +2121,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define custom mappedBy property name for hasMany relationship", () => {
|
test("define custom mappedBy property name for hasMany relationship", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const email = model.define("email", {
|
const email = model.define("email", {
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
isVerified: model.boolean(),
|
isVerified: model.boolean(),
|
||||||
@@ -2164,8 +2134,7 @@ describe("Entity builder", () => {
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
|
||||||
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
@@ -2238,7 +2207,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define delete cascades for the entity", () => {
|
test("define delete cascades for the entity", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const email = model.define("email", {
|
const email = model.define("email", {
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
isVerified: model.boolean(),
|
isVerified: model.boolean(),
|
||||||
@@ -2254,8 +2222,7 @@ describe("Entity builder", () => {
|
|||||||
delete: ["emails"],
|
delete: ["emails"],
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
username: string
|
username: string
|
||||||
@@ -2328,7 +2295,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define delete cascades with belongsTo on the other end", () => {
|
test("define delete cascades with belongsTo on the other end", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const email = model.define("email", {
|
const email = model.define("email", {
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
isVerified: model.boolean(),
|
isVerified: model.boolean(),
|
||||||
@@ -2345,9 +2311,8 @@ describe("Entity builder", () => {
|
|||||||
delete: ["emails"],
|
delete: ["emails"],
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
const Email = toMikroORMEntity(email)
|
||||||
const Email = entityBuilder(email)
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
username: string
|
username: string
|
||||||
@@ -2441,10 +2406,11 @@ describe("Entity builder", () => {
|
|||||||
setter: false,
|
setter: false,
|
||||||
},
|
},
|
||||||
user: {
|
user: {
|
||||||
reference: "m:1",
|
|
||||||
name: "user",
|
|
||||||
entity: "User",
|
entity: "User",
|
||||||
|
name: "user",
|
||||||
|
nullable: false,
|
||||||
persist: false,
|
persist: false,
|
||||||
|
reference: "m:1",
|
||||||
},
|
},
|
||||||
user_id: {
|
user_id: {
|
||||||
columnType: "text",
|
columnType: "text",
|
||||||
@@ -2453,8 +2419,8 @@ describe("Entity builder", () => {
|
|||||||
mapToPk: true,
|
mapToPk: true,
|
||||||
name: "user_id",
|
name: "user_id",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
reference: "m:1",
|
|
||||||
onDelete: "cascade",
|
onDelete: "cascade",
|
||||||
|
reference: "m:1",
|
||||||
},
|
},
|
||||||
created_at: {
|
created_at: {
|
||||||
reference: "scalar",
|
reference: "scalar",
|
||||||
@@ -2494,8 +2460,6 @@ describe("Entity builder", () => {
|
|||||||
|
|
||||||
describe("Entity builder | belongsTo", () => {
|
describe("Entity builder | belongsTo", () => {
|
||||||
test("define belongsTo relationship with hasOne", () => {
|
test("define belongsTo relationship with hasOne", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
|
|
||||||
const email = model.define("email", {
|
const email = model.define("email", {
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
isVerified: model.boolean(),
|
isVerified: model.boolean(),
|
||||||
@@ -2508,9 +2472,7 @@ describe("Entity builder", () => {
|
|||||||
email: model.hasOne(() => email),
|
email: model.hasOne(() => email),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const [User, Email] = [user, email].map(toMikroORMEntity)
|
||||||
const User = entityBuilder(user)
|
|
||||||
const Email = entityBuilder(email)
|
|
||||||
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
@@ -2630,12 +2592,21 @@ describe("Entity builder", () => {
|
|||||||
setter: false,
|
setter: false,
|
||||||
},
|
},
|
||||||
user: {
|
user: {
|
||||||
reference: "1:1",
|
|
||||||
name: "user",
|
name: "user",
|
||||||
|
reference: "1:1",
|
||||||
entity: "User",
|
entity: "User",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
owner: true,
|
|
||||||
mappedBy: "email",
|
mappedBy: "email",
|
||||||
|
owner: true,
|
||||||
|
},
|
||||||
|
user_id: {
|
||||||
|
reference: "scalar",
|
||||||
|
type: "string",
|
||||||
|
columnType: "text",
|
||||||
|
nullable: false,
|
||||||
|
name: "user_id",
|
||||||
|
getter: false,
|
||||||
|
setter: false,
|
||||||
},
|
},
|
||||||
created_at: {
|
created_at: {
|
||||||
reference: "scalar",
|
reference: "scalar",
|
||||||
@@ -2673,8 +2644,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("mark belongsTo with hasOne as nullable", () => {
|
test("mark belongsTo with hasOne as nullable", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
|
|
||||||
const email = model.define("email", {
|
const email = model.define("email", {
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
isVerified: model.boolean(),
|
isVerified: model.boolean(),
|
||||||
@@ -2687,9 +2656,8 @@ describe("Entity builder", () => {
|
|||||||
email: model.hasOne(() => email),
|
email: model.hasOne(() => email),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
const Email = toMikroORMEntity(email)
|
||||||
const Email = entityBuilder(email)
|
|
||||||
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
@@ -2803,12 +2771,21 @@ describe("Entity builder", () => {
|
|||||||
setter: false,
|
setter: false,
|
||||||
},
|
},
|
||||||
user: {
|
user: {
|
||||||
reference: "1:1",
|
|
||||||
name: "user",
|
name: "user",
|
||||||
|
reference: "1:1",
|
||||||
entity: "User",
|
entity: "User",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
owner: true,
|
|
||||||
mappedBy: "email",
|
mappedBy: "email",
|
||||||
|
owner: true,
|
||||||
|
},
|
||||||
|
user_id: {
|
||||||
|
reference: "scalar",
|
||||||
|
type: "string",
|
||||||
|
columnType: "text",
|
||||||
|
nullable: true,
|
||||||
|
name: "user_id",
|
||||||
|
getter: false,
|
||||||
|
setter: false,
|
||||||
},
|
},
|
||||||
created_at: {
|
created_at: {
|
||||||
reference: "scalar",
|
reference: "scalar",
|
||||||
@@ -2846,8 +2823,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define belongsTo relationship with hasMany", () => {
|
test("define belongsTo relationship with hasMany", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
|
|
||||||
const email = model.define("email", {
|
const email = model.define("email", {
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
isVerified: model.boolean(),
|
isVerified: model.boolean(),
|
||||||
@@ -2860,9 +2835,8 @@ describe("Entity builder", () => {
|
|||||||
emails: model.hasMany(() => email),
|
emails: model.hasMany(() => email),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
const Email = toMikroORMEntity(email)
|
||||||
const Email = entityBuilder(email)
|
|
||||||
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
@@ -2976,19 +2950,20 @@ describe("Entity builder", () => {
|
|||||||
setter: false,
|
setter: false,
|
||||||
},
|
},
|
||||||
user: {
|
user: {
|
||||||
reference: "m:1",
|
|
||||||
name: "user",
|
name: "user",
|
||||||
|
reference: "m:1",
|
||||||
entity: "User",
|
entity: "User",
|
||||||
persist: false,
|
persist: false,
|
||||||
|
nullable: false,
|
||||||
},
|
},
|
||||||
user_id: {
|
user_id: {
|
||||||
columnType: "text",
|
|
||||||
entity: "User",
|
|
||||||
fieldName: "user_id",
|
|
||||||
mapToPk: true,
|
|
||||||
name: "user_id",
|
name: "user_id",
|
||||||
nullable: false,
|
|
||||||
reference: "m:1",
|
reference: "m:1",
|
||||||
|
entity: "User",
|
||||||
|
columnType: "text",
|
||||||
|
mapToPk: true,
|
||||||
|
fieldName: "user_id",
|
||||||
|
nullable: false,
|
||||||
},
|
},
|
||||||
created_at: {
|
created_at: {
|
||||||
reference: "scalar",
|
reference: "scalar",
|
||||||
@@ -3026,8 +3001,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define belongsTo with hasMany as nullable", () => {
|
test("define belongsTo with hasMany as nullable", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
|
|
||||||
const email = model.define("email", {
|
const email = model.define("email", {
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
isVerified: model.boolean(),
|
isVerified: model.boolean(),
|
||||||
@@ -3040,9 +3013,8 @@ describe("Entity builder", () => {
|
|||||||
emails: model.hasMany(() => email),
|
emails: model.hasMany(() => email),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
const Email = toMikroORMEntity(email)
|
||||||
const Email = entityBuilder(email)
|
|
||||||
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
@@ -3156,19 +3128,20 @@ describe("Entity builder", () => {
|
|||||||
setter: false,
|
setter: false,
|
||||||
},
|
},
|
||||||
user: {
|
user: {
|
||||||
reference: "m:1",
|
|
||||||
name: "user",
|
name: "user",
|
||||||
|
reference: "m:1",
|
||||||
entity: "User",
|
entity: "User",
|
||||||
persist: false,
|
persist: false,
|
||||||
|
nullable: true,
|
||||||
},
|
},
|
||||||
user_id: {
|
user_id: {
|
||||||
columnType: "text",
|
|
||||||
entity: "User",
|
|
||||||
fieldName: "user_id",
|
|
||||||
mapToPk: true,
|
|
||||||
name: "user_id",
|
name: "user_id",
|
||||||
nullable: true,
|
|
||||||
reference: "m:1",
|
reference: "m:1",
|
||||||
|
entity: "User",
|
||||||
|
columnType: "text",
|
||||||
|
mapToPk: true,
|
||||||
|
fieldName: "user_id",
|
||||||
|
nullable: true,
|
||||||
},
|
},
|
||||||
created_at: {
|
created_at: {
|
||||||
reference: "scalar",
|
reference: "scalar",
|
||||||
@@ -3206,8 +3179,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("throw error when other side relationship is missing", () => {
|
test("throw error when other side relationship is missing", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
|
|
||||||
const email = model.define("email", {
|
const email = model.define("email", {
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
isVerified: model.boolean(),
|
isVerified: model.boolean(),
|
||||||
@@ -3219,15 +3190,12 @@ describe("Entity builder", () => {
|
|||||||
username: model.text(),
|
username: model.text(),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
expect(() => toMikroORMEntity(email)).toThrow(
|
||||||
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'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("throw error when other side relationship is invalid", () => {
|
test("throw error when other side relationship is invalid", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
|
|
||||||
const email = model.define("email", {
|
const email = model.define("email", {
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
isVerified: model.boolean(),
|
isVerified: model.boolean(),
|
||||||
@@ -3240,15 +3208,12 @@ describe("Entity builder", () => {
|
|||||||
email: model.belongsTo(() => email),
|
email: model.belongsTo(() => email),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
expect(() => toMikroORMEntity(email)).toThrow(
|
||||||
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'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("throw error when cascading a parent from a child", () => {
|
test("throw error when cascading a parent from a child", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
|
|
||||||
const user = model.define("user", {
|
const user = model.define("user", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
username: model.text(),
|
username: model.text(),
|
||||||
@@ -3272,8 +3237,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define relationships when entity names has pg schema name", () => {
|
test("define relationships when entity names has pg schema name", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
|
|
||||||
const email = model.define("platform.email", {
|
const email = model.define("platform.email", {
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
isVerified: model.boolean(),
|
isVerified: model.boolean(),
|
||||||
@@ -3286,9 +3249,8 @@ describe("Entity builder", () => {
|
|||||||
email: model.hasOne(() => email),
|
email: model.hasOne(() => email),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
const Email = toMikroORMEntity(email)
|
||||||
const Email = entityBuilder(email)
|
|
||||||
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
@@ -3410,12 +3372,21 @@ describe("Entity builder", () => {
|
|||||||
setter: false,
|
setter: false,
|
||||||
},
|
},
|
||||||
user: {
|
user: {
|
||||||
reference: "1:1",
|
|
||||||
name: "user",
|
name: "user",
|
||||||
|
reference: "1:1",
|
||||||
entity: "User",
|
entity: "User",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
owner: true,
|
|
||||||
mappedBy: "email",
|
mappedBy: "email",
|
||||||
|
owner: true,
|
||||||
|
},
|
||||||
|
user_id: {
|
||||||
|
reference: "scalar",
|
||||||
|
type: "string",
|
||||||
|
columnType: "text",
|
||||||
|
nullable: false,
|
||||||
|
name: "user_id",
|
||||||
|
getter: false,
|
||||||
|
setter: false,
|
||||||
},
|
},
|
||||||
created_at: {
|
created_at: {
|
||||||
reference: "scalar",
|
reference: "scalar",
|
||||||
@@ -3453,8 +3424,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define relationships between cross pg schemas entities", () => {
|
test("define relationships between cross pg schemas entities", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
|
|
||||||
const email = model.define("platform.email", {
|
const email = model.define("platform.email", {
|
||||||
email: model.text(),
|
email: model.text(),
|
||||||
isVerified: model.boolean(),
|
isVerified: model.boolean(),
|
||||||
@@ -3467,9 +3436,8 @@ describe("Entity builder", () => {
|
|||||||
email: model.hasOne(() => email),
|
email: model.hasOne(() => email),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
const Email = toMikroORMEntity(email)
|
||||||
const Email = entityBuilder(email)
|
|
||||||
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
@@ -3591,12 +3559,21 @@ describe("Entity builder", () => {
|
|||||||
setter: false,
|
setter: false,
|
||||||
},
|
},
|
||||||
user: {
|
user: {
|
||||||
reference: "1:1",
|
|
||||||
name: "user",
|
name: "user",
|
||||||
|
reference: "1:1",
|
||||||
entity: "User",
|
entity: "User",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
owner: true,
|
|
||||||
mappedBy: "email",
|
mappedBy: "email",
|
||||||
|
owner: true,
|
||||||
|
},
|
||||||
|
user_id: {
|
||||||
|
reference: "scalar",
|
||||||
|
type: "string",
|
||||||
|
columnType: "text",
|
||||||
|
nullable: false,
|
||||||
|
name: "user_id",
|
||||||
|
getter: false,
|
||||||
|
setter: false,
|
||||||
},
|
},
|
||||||
created_at: {
|
created_at: {
|
||||||
reference: "scalar",
|
reference: "scalar",
|
||||||
@@ -3636,7 +3613,6 @@ describe("Entity builder", () => {
|
|||||||
|
|
||||||
describe("Entity builder | manyToMany", () => {
|
describe("Entity builder | manyToMany", () => {
|
||||||
test("define manyToMany relationship", () => {
|
test("define manyToMany relationship", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const team = model.define("team", {
|
const team = model.define("team", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
name: model.text(),
|
name: model.text(),
|
||||||
@@ -3649,9 +3625,8 @@ describe("Entity builder", () => {
|
|||||||
teams: model.manyToMany(() => team),
|
teams: model.manyToMany(() => team),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
const Team = toMikroORMEntity(team)
|
||||||
const Team = entityBuilder(team)
|
|
||||||
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
@@ -3805,7 +3780,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define mappedBy on one side", () => {
|
test("define mappedBy on one side", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const team = model.define("team", {
|
const team = model.define("team", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
name: model.text(),
|
name: model.text(),
|
||||||
@@ -3818,9 +3792,8 @@ describe("Entity builder", () => {
|
|||||||
teams: model.manyToMany(() => team, { mappedBy: "users" }),
|
teams: model.manyToMany(() => team, { mappedBy: "users" }),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
const Team = toMikroORMEntity(team)
|
||||||
const Team = entityBuilder(team)
|
|
||||||
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
@@ -3975,7 +3948,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("throw error when unable to locate relationship via mappedBy", () => {
|
test("throw error when unable to locate relationship via mappedBy", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const team = model.define("team", {
|
const team = model.define("team", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
name: model.text(),
|
name: model.text(),
|
||||||
@@ -3987,14 +3959,12 @@ describe("Entity builder", () => {
|
|||||||
teams: model.manyToMany(() => team, { mappedBy: "users" }),
|
teams: model.manyToMany(() => team, { mappedBy: "users" }),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
expect(() => toMikroORMEntity(user)).toThrow(
|
||||||
expect(() => entityBuilder(user)).toThrow(
|
|
||||||
'Missing property "users" on "Team" entity. Make sure to define it as a relationship'
|
'Missing property "users" on "Team" entity. Make sure to define it as a relationship'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("throw error when mappedBy relationship is not a manyToMany", () => {
|
test("throw error when mappedBy relationship is not a manyToMany", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const team = model.define("team", {
|
const team = model.define("team", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
name: model.text(),
|
name: model.text(),
|
||||||
@@ -4007,14 +3977,12 @@ describe("Entity builder", () => {
|
|||||||
teams: model.manyToMany(() => team, { mappedBy: "users" }),
|
teams: model.manyToMany(() => team, { mappedBy: "users" }),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
expect(() => toMikroORMEntity(user)).toThrow(
|
||||||
expect(() => entityBuilder(user)).toThrow(
|
|
||||||
'Invalid relationship reference for "users" on "Team" entity. Make sure to define a manyToMany relationship'
|
'Invalid relationship reference for "users" on "Team" entity. Make sure to define a manyToMany relationship'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("define mappedBy on both sides", () => {
|
test("define mappedBy on both sides", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const team = model.define("team", {
|
const team = model.define("team", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
name: model.text(),
|
name: model.text(),
|
||||||
@@ -4027,9 +3995,7 @@ describe("Entity builder", () => {
|
|||||||
teams: model.manyToMany(() => team, { mappedBy: "users" }),
|
teams: model.manyToMany(() => team, { mappedBy: "users" }),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const [User, Team] = toMikroOrmEntities([user, team, {}])
|
||||||
const User = entityBuilder(user)
|
|
||||||
const Team = entityBuilder(team)
|
|
||||||
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
@@ -4189,7 +4155,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define mappedBy on both sides and reverse order of registering entities", () => {
|
test("define mappedBy on both sides and reverse order of registering entities", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const team = model.define("team", {
|
const team = model.define("team", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
name: model.text(),
|
name: model.text(),
|
||||||
@@ -4364,7 +4329,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define multiple many to many relationships to the same entity", () => {
|
test("define multiple many to many relationships to the same entity", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const team = model.define("team", {
|
const team = model.define("team", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
name: model.text(),
|
name: model.text(),
|
||||||
@@ -4571,7 +4535,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define manyToMany relationship when entity names has pg schema name", () => {
|
test("define manyToMany relationship when entity names has pg schema name", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const team = model.define("platform.team", {
|
const team = model.define("platform.team", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
name: model.text(),
|
name: model.text(),
|
||||||
@@ -4584,9 +4547,8 @@ describe("Entity builder", () => {
|
|||||||
teams: model.manyToMany(() => team),
|
teams: model.manyToMany(() => team),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
const Team = toMikroORMEntity(team)
|
||||||
const Team = entityBuilder(team)
|
|
||||||
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
@@ -4742,7 +4704,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define custom pivot table name", () => {
|
test("define custom pivot table name", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const team = model.define("team", {
|
const team = model.define("team", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
name: model.text(),
|
name: model.text(),
|
||||||
@@ -4757,9 +4718,8 @@ describe("Entity builder", () => {
|
|||||||
teams: model.manyToMany(() => team, { pivotTable: "users_teams" }),
|
teams: model.manyToMany(() => team, { pivotTable: "users_teams" }),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const User = toMikroORMEntity(user)
|
||||||
const User = entityBuilder(user)
|
const Team = toMikroORMEntity(team)
|
||||||
const Team = entityBuilder(team)
|
|
||||||
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
@@ -4913,7 +4873,6 @@ describe("Entity builder", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("define custom pivot entity", () => {
|
test("define custom pivot entity", () => {
|
||||||
const model = new EntityBuilder()
|
|
||||||
const team = model.define("team", {
|
const team = model.define("team", {
|
||||||
id: model.number(),
|
id: model.number(),
|
||||||
name: model.text(),
|
name: model.text(),
|
||||||
@@ -4934,10 +4893,7 @@ describe("Entity builder", () => {
|
|||||||
teams: model.manyToMany(() => team, { pivotEntity: () => squad }),
|
teams: model.manyToMany(() => team, { pivotEntity: () => squad }),
|
||||||
})
|
})
|
||||||
|
|
||||||
const entityBuilder = createMikrORMEntity()
|
const [User, Team, Squad] = toMikroOrmEntities([user, team, squad])
|
||||||
const User = entityBuilder(user)
|
|
||||||
const Team = entityBuilder(team)
|
|
||||||
const Squad = entityBuilder(squad)
|
|
||||||
|
|
||||||
expectTypeOf(new User()).toMatchTypeOf<{
|
expectTypeOf(new User()).toMatchTypeOf<{
|
||||||
id: number
|
id: number
|
||||||
@@ -4973,74 +4929,78 @@ describe("Entity builder", () => {
|
|||||||
expect(squadMetaData.properties).toEqual({
|
expect(squadMetaData.properties).toEqual({
|
||||||
id: {
|
id: {
|
||||||
reference: "scalar",
|
reference: "scalar",
|
||||||
type: "number",
|
|
||||||
columnType: "integer",
|
columnType: "integer",
|
||||||
name: "id",
|
type: "number",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
|
name: "id",
|
||||||
getter: false,
|
getter: false,
|
||||||
setter: false,
|
setter: false,
|
||||||
},
|
},
|
||||||
team: {
|
user_id: {
|
||||||
entity: "Team",
|
name: "user_id",
|
||||||
name: "team",
|
|
||||||
persist: false,
|
|
||||||
reference: "m:1",
|
reference: "m:1",
|
||||||
},
|
entity: "User",
|
||||||
team_id: {
|
|
||||||
columnType: "text",
|
columnType: "text",
|
||||||
entity: "Team",
|
|
||||||
fieldName: "team_id",
|
|
||||||
mapToPk: true,
|
mapToPk: true,
|
||||||
name: "team_id",
|
fieldName: "user_id",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
onDelete: undefined,
|
|
||||||
reference: "m:1",
|
|
||||||
},
|
},
|
||||||
user: {
|
user: {
|
||||||
entity: "User",
|
reference: "scalar",
|
||||||
name: "user",
|
type: "User",
|
||||||
persist: false,
|
persist: false,
|
||||||
reference: "m:1",
|
|
||||||
},
|
|
||||||
user_id: {
|
|
||||||
columnType: "text",
|
|
||||||
entity: "User",
|
|
||||||
fieldName: "user_id",
|
|
||||||
mapToPk: true,
|
|
||||||
name: "user_id",
|
|
||||||
nullable: false,
|
nullable: false,
|
||||||
onDelete: undefined,
|
name: "user",
|
||||||
|
getter: false,
|
||||||
|
setter: false,
|
||||||
|
},
|
||||||
|
team_id: {
|
||||||
|
name: "team_id",
|
||||||
reference: "m:1",
|
reference: "m:1",
|
||||||
|
entity: "Team",
|
||||||
|
columnType: "text",
|
||||||
|
mapToPk: true,
|
||||||
|
fieldName: "team_id",
|
||||||
|
nullable: false,
|
||||||
|
},
|
||||||
|
team: {
|
||||||
|
reference: "scalar",
|
||||||
|
type: "Team",
|
||||||
|
persist: false,
|
||||||
|
nullable: false,
|
||||||
|
name: "team",
|
||||||
|
getter: false,
|
||||||
|
setter: false,
|
||||||
},
|
},
|
||||||
created_at: {
|
created_at: {
|
||||||
reference: "scalar",
|
reference: "scalar",
|
||||||
type: "date",
|
|
||||||
columnType: "timestamptz",
|
columnType: "timestamptz",
|
||||||
name: "created_at",
|
type: "date",
|
||||||
defaultRaw: "now()",
|
|
||||||
onCreate: expect.any(Function),
|
|
||||||
nullable: false,
|
nullable: false,
|
||||||
|
onCreate: expect.any(Function),
|
||||||
|
defaultRaw: "now()",
|
||||||
|
name: "created_at",
|
||||||
getter: false,
|
getter: false,
|
||||||
setter: false,
|
setter: false,
|
||||||
},
|
},
|
||||||
updated_at: {
|
updated_at: {
|
||||||
reference: "scalar",
|
reference: "scalar",
|
||||||
type: "date",
|
|
||||||
columnType: "timestamptz",
|
columnType: "timestamptz",
|
||||||
name: "updated_at",
|
type: "date",
|
||||||
defaultRaw: "now()",
|
nullable: false,
|
||||||
onCreate: expect.any(Function),
|
onCreate: expect.any(Function),
|
||||||
onUpdate: expect.any(Function),
|
onUpdate: expect.any(Function),
|
||||||
nullable: false,
|
defaultRaw: "now()",
|
||||||
|
name: "updated_at",
|
||||||
getter: false,
|
getter: false,
|
||||||
setter: false,
|
setter: false,
|
||||||
},
|
},
|
||||||
deleted_at: {
|
deleted_at: {
|
||||||
reference: "scalar",
|
reference: "scalar",
|
||||||
type: "date",
|
|
||||||
columnType: "timestamptz",
|
columnType: "timestamptz",
|
||||||
name: "deleted_at",
|
type: "date",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
|
name: "deleted_at",
|
||||||
getter: false,
|
getter: false,
|
||||||
setter: false,
|
setter: false,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -154,6 +154,7 @@ export function createMikrORMEntity() {
|
|||||||
* - [user.teams]: true // the teams relationship on user is an owner
|
* - [user.teams]: true // the teams relationship on user is an owner
|
||||||
* - [team.users] // cannot be an owner
|
* - [team.users] // cannot be an owner
|
||||||
*/
|
*/
|
||||||
|
// TODO: if we use the util toMikroOrmEntities then a new builder will be used each time, lets think about this. Currently if means that with many to many we need to use the same builder
|
||||||
const MANY_TO_MANY_TRACKED_REALTIONS: Record<string, boolean> = {}
|
const MANY_TO_MANY_TRACKED_REALTIONS: Record<string, boolean> = {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -390,6 +391,23 @@ export function createMikrORMEntity() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function applyForeignKeyAssignationHooks(foreignKeyName: string) {
|
||||||
|
const hookName = `assignRelationFromForeignKeyValue${foreignKeyName}`
|
||||||
|
/**
|
||||||
|
* Hook to handle foreign key assignation
|
||||||
|
*/
|
||||||
|
MikroORMEntity.prototype[hookName] = function () {
|
||||||
|
this[relationship.name] ??= this[foreignKeyName]
|
||||||
|
this[foreignKeyName] ??= this[relationship.name]?.id
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute hook via lifecycle decorators
|
||||||
|
*/
|
||||||
|
BeforeCreate()(MikroORMEntity.prototype, hookName)
|
||||||
|
OnInit()(MikroORMEntity.prototype, hookName)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Otherside is a has many. Hence we should defined a ManyToOne
|
* Otherside is a has many. Hence we should defined a ManyToOne
|
||||||
*/
|
*/
|
||||||
@@ -397,6 +415,8 @@ export function createMikrORMEntity() {
|
|||||||
otherSideRelation instanceof HasMany ||
|
otherSideRelation instanceof HasMany ||
|
||||||
otherSideRelation instanceof DmlManyToMany
|
otherSideRelation instanceof DmlManyToMany
|
||||||
) {
|
) {
|
||||||
|
const foreignKeyName = camelToSnakeCase(`${relationship.name}Id`)
|
||||||
|
|
||||||
ManyToOne({
|
ManyToOne({
|
||||||
entity: relatedModelName,
|
entity: relatedModelName,
|
||||||
columnType: "text",
|
columnType: "text",
|
||||||
@@ -406,10 +426,22 @@ export function createMikrORMEntity() {
|
|||||||
onDelete: shouldCascade ? "cascade" : undefined,
|
onDelete: shouldCascade ? "cascade" : undefined,
|
||||||
})(MikroORMEntity.prototype, camelToSnakeCase(`${relationship.name}Id`))
|
})(MikroORMEntity.prototype, camelToSnakeCase(`${relationship.name}Id`))
|
||||||
|
|
||||||
|
if (otherSideRelation instanceof DmlManyToMany) {
|
||||||
|
Property({
|
||||||
|
type: relatedModelName,
|
||||||
|
persist: false,
|
||||||
|
nullable: relationship.nullable,
|
||||||
|
})(MikroORMEntity.prototype, relationship.name)
|
||||||
|
} else {
|
||||||
|
// HasMany case
|
||||||
ManyToOne({
|
ManyToOne({
|
||||||
entity: relatedModelName,
|
entity: relatedModelName,
|
||||||
persist: false,
|
persist: false,
|
||||||
|
nullable: relationship.nullable,
|
||||||
})(MikroORMEntity.prototype, relationship.name)
|
})(MikroORMEntity.prototype, relationship.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
applyForeignKeyAssignationHooks(foreignKeyName)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,6 +449,8 @@ export function createMikrORMEntity() {
|
|||||||
* Otherside is a has one. Hence we should defined a OneToOne
|
* Otherside is a has one. Hence we should defined a OneToOne
|
||||||
*/
|
*/
|
||||||
if (otherSideRelation instanceof HasOne) {
|
if (otherSideRelation instanceof HasOne) {
|
||||||
|
const foreignKeyName = camelToSnakeCase(`${relationship.name}Id`)
|
||||||
|
|
||||||
OneToOne({
|
OneToOne({
|
||||||
entity: relatedModelName,
|
entity: relatedModelName,
|
||||||
nullable: relationship.nullable,
|
nullable: relationship.nullable,
|
||||||
@@ -424,6 +458,23 @@ export function createMikrORMEntity() {
|
|||||||
owner: true,
|
owner: true,
|
||||||
onDelete: shouldCascade ? "cascade" : undefined,
|
onDelete: shouldCascade ? "cascade" : undefined,
|
||||||
})(MikroORMEntity.prototype, relationship.name)
|
})(MikroORMEntity.prototype, relationship.name)
|
||||||
|
|
||||||
|
if (relationship.nullable) {
|
||||||
|
Object.defineProperty(MikroORMEntity.prototype, foreignKeyName, {
|
||||||
|
value: null,
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
writable: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Property({
|
||||||
|
type: "string",
|
||||||
|
columnType: "text",
|
||||||
|
nullable: relationship.nullable,
|
||||||
|
})(MikroORMEntity.prototype, foreignKeyName)
|
||||||
|
|
||||||
|
applyForeignKeyAssignationHooks(foreignKeyName)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -681,12 +732,18 @@ export function createMikrORMEntity() {
|
|||||||
* return the input idempotently
|
* return the input idempotently
|
||||||
* @param entity
|
* @param entity
|
||||||
*/
|
*/
|
||||||
export const toMikroORMEntity = (entity: any) => {
|
export const toMikroORMEntity = <T>(
|
||||||
|
entity: T
|
||||||
|
): T extends DmlEntity<infer Schema> ? EntityConstructor<Schema> : T => {
|
||||||
|
let mikroOrmEntity: T | EntityConstructor<any> = entity
|
||||||
|
|
||||||
if (DmlEntity.isDmlEntity(entity)) {
|
if (DmlEntity.isDmlEntity(entity)) {
|
||||||
return createMikrORMEntity()(entity)
|
mikroOrmEntity = createMikrORMEntity()(entity)
|
||||||
}
|
}
|
||||||
|
|
||||||
return entity
|
return mikroOrmEntity as T extends DmlEntity<infer Schema>
|
||||||
|
? EntityConstructor<Schema>
|
||||||
|
: T
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -694,6 +751,16 @@ export const toMikroORMEntity = (entity: any) => {
|
|||||||
* This action is idempotent if non of the entities are DmlEntity
|
* This action is idempotent if non of the entities are DmlEntity
|
||||||
* @param entities
|
* @param entities
|
||||||
*/
|
*/
|
||||||
export const toMikroOrmEntities = function (entities: any[]) {
|
export const toMikroOrmEntities = function <T extends any[]>(entities: T) {
|
||||||
return entities.map(toMikroORMEntity)
|
const entityBuilder = createMikrORMEntity()
|
||||||
|
|
||||||
|
return entities.map((entity) => {
|
||||||
|
if (DmlEntity.isDmlEntity(entity)) {
|
||||||
|
return entityBuilder(entity)
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity
|
||||||
|
}) as {
|
||||||
|
[K in keyof T]: T[K] extends DmlEntity<any> ? EntityConstructor<T[K]> : T[K]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
import { MetadataStorage, MikroORM } from "@mikro-orm/core"
|
||||||
|
import { model } from "../entity-builder"
|
||||||
|
import { toMikroOrmEntities } from "../helpers/create-mikro-orm-entity"
|
||||||
|
import { createDatabase, dropDatabase } from "pg-god"
|
||||||
|
import { mikroOrmSerializer, TSMigrationGenerator } from "../../dal"
|
||||||
|
import { FileSystem } from "../../common"
|
||||||
|
import { join } from "path"
|
||||||
|
import { EntityConstructor } from "@medusajs/types"
|
||||||
|
|
||||||
|
const DB_HOST = process.env.DB_HOST
|
||||||
|
const DB_USERNAME = process.env.DB_USERNAME
|
||||||
|
const DB_PASSWORD = process.env.DB_PASSWORD
|
||||||
|
|
||||||
|
const pgGodCredentials = {
|
||||||
|
user: DB_USERNAME,
|
||||||
|
password: DB_PASSWORD,
|
||||||
|
host: DB_HOST,
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileSystem = new FileSystem(join(__dirname, "../../migrations"))
|
||||||
|
|
||||||
|
describe("manyToMany - manyToMany", () => {
|
||||||
|
const dbName = "EntityBuilder-ManyToMany"
|
||||||
|
|
||||||
|
let orm!: MikroORM
|
||||||
|
|
||||||
|
let Team: EntityConstructor<any>,
|
||||||
|
User: EntityConstructor<any>,
|
||||||
|
Squad: EntityConstructor<any>
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
fileSystem.cleanup()
|
||||||
|
})
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
MetadataStorage.clear()
|
||||||
|
|
||||||
|
const team = model.define("team", {
|
||||||
|
id: model.id(),
|
||||||
|
name: model.text(),
|
||||||
|
users: model.manyToMany(() => user, {
|
||||||
|
pivotEntity: () => squad,
|
||||||
|
mappedBy: "squads",
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
const squad = model.define("teamUsers", {
|
||||||
|
id: model.id(),
|
||||||
|
user: model.belongsTo(() => user, { mappedBy: "squads" }),
|
||||||
|
squad: model.belongsTo(() => team, { mappedBy: "users" }),
|
||||||
|
})
|
||||||
|
|
||||||
|
const user = model.define("user", {
|
||||||
|
id: model.id(),
|
||||||
|
username: model.text(),
|
||||||
|
squads: model.manyToMany(() => team, {
|
||||||
|
pivotEntity: () => squad,
|
||||||
|
mappedBy: "users",
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
;[User, Squad, Team] = toMikroOrmEntities([user, squad, team])
|
||||||
|
|
||||||
|
await createDatabase({ databaseName: dbName }, pgGodCredentials)
|
||||||
|
|
||||||
|
orm = await MikroORM.init({
|
||||||
|
entities: [Team, User, Squad],
|
||||||
|
tsNode: true,
|
||||||
|
dbName,
|
||||||
|
debug: true,
|
||||||
|
type: "postgresql",
|
||||||
|
migrations: {
|
||||||
|
generator: TSMigrationGenerator,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const migrator = orm.getMigrator()
|
||||||
|
await migrator.createMigration()
|
||||||
|
await migrator.up()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await orm.close()
|
||||||
|
|
||||||
|
await dropDatabase(
|
||||||
|
{ databaseName: dbName, errorIfNonExist: false },
|
||||||
|
pgGodCredentials
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`should handle the relation properly`, async () => {
|
||||||
|
let manager = orm.em.fork()
|
||||||
|
|
||||||
|
const user1 = manager.create(User, {
|
||||||
|
username: "User 1",
|
||||||
|
})
|
||||||
|
const user2 = manager.create(User, {
|
||||||
|
username: "User 2",
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.persistAndFlush([user1, user2])
|
||||||
|
manager = orm.em.fork()
|
||||||
|
|
||||||
|
const team1 = manager.create(Team, {
|
||||||
|
name: "Team 1",
|
||||||
|
})
|
||||||
|
const team2 = manager.create(Team, {
|
||||||
|
name: "Team 2",
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.persistAndFlush([team1, team2])
|
||||||
|
manager = orm.em.fork()
|
||||||
|
|
||||||
|
const squad1 = manager.create(Squad, {
|
||||||
|
user_id: user1.id,
|
||||||
|
squad_id: team1.id,
|
||||||
|
})
|
||||||
|
const squad2 = manager.create(Squad, {
|
||||||
|
user_id: user2.id,
|
||||||
|
squad_id: team1.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.persistAndFlush([squad1, squad2])
|
||||||
|
manager = orm.em.fork()
|
||||||
|
|
||||||
|
const team = await manager.findOne(
|
||||||
|
Team,
|
||||||
|
{
|
||||||
|
id: team1.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
populate: ["users"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const serializedSquad = mikroOrmSerializer<InstanceType<typeof Team>>(team)
|
||||||
|
|
||||||
|
expect(serializedSquad.users).toHaveLength(2)
|
||||||
|
expect(serializedSquad).toEqual({
|
||||||
|
id: team1.id,
|
||||||
|
name: "Team 1",
|
||||||
|
created_at: expect.any(Date),
|
||||||
|
updated_at: expect.any(Date),
|
||||||
|
deleted_at: null,
|
||||||
|
users: expect.arrayContaining([
|
||||||
|
{
|
||||||
|
id: user1.id,
|
||||||
|
username: "User 1",
|
||||||
|
created_at: expect.any(Date),
|
||||||
|
updated_at: expect.any(Date),
|
||||||
|
deleted_at: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: user2.id,
|
||||||
|
username: "User 2",
|
||||||
|
created_at: expect.any(Date),
|
||||||
|
updated_at: expect.any(Date),
|
||||||
|
deleted_at: null,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
})
|
||||||
|
|
||||||
|
const user = await manager.findOne(
|
||||||
|
User,
|
||||||
|
{
|
||||||
|
id: user1.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
populate: ["squads"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const serializedUser = mikroOrmSerializer<InstanceType<typeof User>>(user)
|
||||||
|
|
||||||
|
expect(serializedUser.squads).toHaveLength(1)
|
||||||
|
expect(serializedUser).toEqual({
|
||||||
|
id: user1.id,
|
||||||
|
username: "User 1",
|
||||||
|
created_at: expect.any(Date),
|
||||||
|
updated_at: expect.any(Date),
|
||||||
|
deleted_at: null,
|
||||||
|
squads: expect.arrayContaining([
|
||||||
|
{
|
||||||
|
id: team1.id,
|
||||||
|
name: "Team 1",
|
||||||
|
created_at: expect.any(Date),
|
||||||
|
updated_at: expect.any(Date),
|
||||||
|
deleted_at: null,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
import { MetadataStorage, MikroORM } from "@mikro-orm/core"
|
||||||
|
import { model } from "../entity-builder"
|
||||||
|
import { toMikroOrmEntities } from "../helpers/create-mikro-orm-entity"
|
||||||
|
import { createDatabase, dropDatabase } from "pg-god"
|
||||||
|
import { mikroOrmSerializer } from "../../dal"
|
||||||
|
import { FileSystem } from "../../common"
|
||||||
|
import { join } from "path"
|
||||||
|
import { EntityConstructor } from "@medusajs/types"
|
||||||
|
|
||||||
|
const DB_HOST = process.env.DB_HOST
|
||||||
|
const DB_USERNAME = process.env.DB_USERNAME
|
||||||
|
const DB_PASSWORD = process.env.DB_PASSWORD
|
||||||
|
|
||||||
|
const pgGodCredentials = {
|
||||||
|
user: DB_USERNAME,
|
||||||
|
password: DB_PASSWORD,
|
||||||
|
host: DB_HOST,
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileSystem = new FileSystem(join(__dirname, "../../migrations"))
|
||||||
|
|
||||||
|
describe("manyToOne - belongTo", () => {
|
||||||
|
const dbName = "EntityBuilder-ManyToOne"
|
||||||
|
|
||||||
|
let orm!: MikroORM
|
||||||
|
let Team: EntityConstructor<any>, User: EntityConstructor<any>
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
fileSystem.cleanup()
|
||||||
|
})
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
MetadataStorage.clear()
|
||||||
|
|
||||||
|
const team = model.define("team", {
|
||||||
|
id: model.id(),
|
||||||
|
name: model.text(),
|
||||||
|
user: model.belongsTo(() => user, { mappedBy: "teams" }),
|
||||||
|
})
|
||||||
|
|
||||||
|
const user = model.define("user", {
|
||||||
|
id: model.id(),
|
||||||
|
username: model.text(),
|
||||||
|
teams: model.hasMany(() => team, { mappedBy: "user" }),
|
||||||
|
})
|
||||||
|
|
||||||
|
;[User, Team] = toMikroOrmEntities([user, team])
|
||||||
|
|
||||||
|
await createDatabase({ databaseName: dbName }, pgGodCredentials)
|
||||||
|
|
||||||
|
orm = await MikroORM.init({
|
||||||
|
entities: [Team, User],
|
||||||
|
tsNode: true,
|
||||||
|
dbName,
|
||||||
|
debug: true,
|
||||||
|
type: "postgresql",
|
||||||
|
})
|
||||||
|
|
||||||
|
const migrator = orm.getMigrator()
|
||||||
|
await migrator.createMigration()
|
||||||
|
await migrator.up()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await orm.close()
|
||||||
|
|
||||||
|
await dropDatabase(
|
||||||
|
{ databaseName: dbName, errorIfNonExist: false },
|
||||||
|
pgGodCredentials
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it(`should handle the relation properly`, async () => {
|
||||||
|
let manager = orm.em.fork()
|
||||||
|
|
||||||
|
const user1 = manager.create(User, {
|
||||||
|
username: "User 1",
|
||||||
|
})
|
||||||
|
const user2 = manager.create(User, {
|
||||||
|
username: "User 2",
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.persistAndFlush([user1, user2])
|
||||||
|
manager = orm.em.fork()
|
||||||
|
|
||||||
|
const team1 = manager.create(Team, {
|
||||||
|
name: "Team 1",
|
||||||
|
user_id: user1.id,
|
||||||
|
})
|
||||||
|
const team2 = manager.create(Team, {
|
||||||
|
name: "Team 2",
|
||||||
|
user_id: user2.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
await manager.persistAndFlush([team1, team2])
|
||||||
|
manager = orm.em.fork()
|
||||||
|
|
||||||
|
const team = await manager.findOne(
|
||||||
|
Team,
|
||||||
|
{
|
||||||
|
id: team1.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
populate: ["user"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(mikroOrmSerializer<InstanceType<typeof Team>>(team)).toEqual({
|
||||||
|
id: team1.id,
|
||||||
|
name: "Team 1",
|
||||||
|
created_at: expect.any(Date),
|
||||||
|
updated_at: expect.any(Date),
|
||||||
|
deleted_at: null,
|
||||||
|
user_id: user1.id,
|
||||||
|
user: {
|
||||||
|
id: user1.id,
|
||||||
|
username: "User 1",
|
||||||
|
created_at: expect.any(Date),
|
||||||
|
updated_at: expect.any(Date),
|
||||||
|
deleted_at: null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const user = await manager.findOne(
|
||||||
|
User,
|
||||||
|
{
|
||||||
|
id: user1.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
populate: ["teams"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(mikroOrmSerializer<InstanceType<typeof User>>(user)).toEqual({
|
||||||
|
id: user1.id,
|
||||||
|
username: "User 1",
|
||||||
|
created_at: expect.any(Date),
|
||||||
|
updated_at: expect.any(Date),
|
||||||
|
deleted_at: null,
|
||||||
|
teams: [
|
||||||
|
{
|
||||||
|
id: team1.id,
|
||||||
|
name: "Team 1",
|
||||||
|
created_at: expect.any(Date),
|
||||||
|
updated_at: expect.any(Date),
|
||||||
|
deleted_at: null,
|
||||||
|
user_id: user1.id,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -13,3 +13,4 @@ export * from "./medusa-internal-service"
|
|||||||
export * from "./medusa-service"
|
export * from "./medusa-service"
|
||||||
export * from "./migration-scripts"
|
export * from "./migration-scripts"
|
||||||
export * from "./mikro-orm-cli-config-builder"
|
export * from "./mikro-orm-cli-config-builder"
|
||||||
|
|
||||||
@@ -1,8 +1,12 @@
|
|||||||
import { MikroORMOptions } from "@mikro-orm/core/utils/Configuration"
|
import { MikroORMOptions } from "@mikro-orm/core/utils/Configuration"
|
||||||
import { DmlEntity, toMikroORMEntity } from "../dml"
|
import { DmlEntity, toMikroORMEntity } from "../dml"
|
||||||
import { TSMigrationGenerator } from "../dal"
|
import { TSMigrationGenerator } from "../dal"
|
||||||
import { AnyEntity, EntityClassGroup, EntitySchema } from "@mikro-orm/core"
|
import type {
|
||||||
import { EntityClass } from "@mikro-orm/core/typings"
|
AnyEntity,
|
||||||
|
EntityClass,
|
||||||
|
EntityClassGroup,
|
||||||
|
} from "@mikro-orm/core/typings"
|
||||||
|
import type { EntitySchema } from "@mikro-orm/core/metadata/EntitySchema"
|
||||||
|
|
||||||
type Options = Partial<MikroORMOptions> & {
|
type Options = Partial<MikroORMOptions> & {
|
||||||
entities: (
|
entities: (
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
import * as entities from "./src/models"
|
import * as entities from "./src/models"
|
||||||
import { TSMigrationGenerator } from "@medusajs/utils"
|
import { defineMikroOrmCliConfig } from "@medusajs/utils"
|
||||||
|
|
||||||
module.exports = {
|
module.exports = defineMikroOrmCliConfig({
|
||||||
entities: Object.values(entities),
|
entities: Object.values(entities),
|
||||||
schema: "public",
|
databaseName: "medusa-fulfillment",
|
||||||
clientUrl: "postgres://postgres@localhost/medusa-fulfillment",
|
})
|
||||||
type: "postgresql",
|
|
||||||
migrations: {
|
|
||||||
generator: TSMigrationGenerator,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user