Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Migrate customer module to DML #10499

Merged
merged 13 commits into from
Dec 11, 2024
7 changes: 7 additions & 0 deletions .changeset/healthy-ears-agree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@medusajs/customer": patch
"@medusajs/types": patch
"@medusajs/utils": patch
---

Feat/customer dml
5 changes: 3 additions & 2 deletions packages/core/types/src/dml/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,13 @@ export type Infer<T> = T extends IDmlEntity<infer Schema, any>
* The actions to cascade from a given entity to its
* relationship.
*/
export type EntityCascades<Relationships> = {
export type EntityCascades<DeletableRelationships, DetachableRelationships> = {
/**
* The related models to delete when a record of this data model
* is deleted.
*/
delete?: Relationships
delete?: DeletableRelationships
detach?: DetachableRelationships
}

/**
Expand Down
80 changes: 80 additions & 0 deletions packages/core/utils/src/dml/__tests__/entity-builder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6231,6 +6231,86 @@ describe("Entity builder", () => {
})
})

test("should define onDelete cascade on pivot entity when applying detach cascade", () => {
const teamUser = model.define("teamUser", {
id: model.number(),
user: model.belongsTo(() => user, { mappedBy: "teams" }),
team: model.belongsTo(() => team, { mappedBy: "users" }),
})
const user = model
.define("user", {
id: model.number(),
username: model.text(),
teams: model.manyToMany(() => team, {
pivotEntity: () => teamUser,
}),
})
.cascades({
detach: ["teams"],
})

const team = model
.define("team", {
id: model.number(),
name: model.text(),
users: model.manyToMany(() => user, {
pivotEntity: () => teamUser,
}),
})
.cascades({
detach: ["users"],
})

type CascadeDetach = Parameters<(typeof team)["cascades"]>[0]["detach"]

expectTypeOf<CascadeDetach>().toEqualTypeOf<"users"[] | undefined>()

const [, , TeamUserEntity] = toMikroOrmEntities([user, team, teamUser])

const teamUserMetadata =
MetadataStorage.getMetadataFromDecorator(TeamUserEntity)
expect(teamUserMetadata.properties).toEqual(
expect.objectContaining({
user_id: {
reference: "scalar",
type: "User",
columnType: "text",
fieldName: "user_id",
nullable: false,
name: "user_id",
getter: false,
setter: false,
},
user: {
name: "user",
reference: "m:1",
entity: "User",
nullable: false,
persist: false,
onDelete: "cascade",
},
team_id: {
reference: "scalar",
type: "Team",
columnType: "text",
fieldName: "team_id",
nullable: false,
name: "team_id",
getter: false,
setter: false,
},
team: {
name: "team",
reference: "m:1",
entity: "Team",
nullable: false,
persist: false,
onDelete: "cascade",
},
})
)
})

test("throw error when unable to locate relationship via mappedBy", () => {
const team = model.define("team", {
id: model.number(),
Expand Down
7 changes: 4 additions & 3 deletions packages/core/utils/src/dml/entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export class DmlEntity<
schema: Schema

readonly #tableName: string
#cascades: EntityCascades<string[]> = {}
#cascades: EntityCascades<string[], string[]> = {}
#indexes: EntityIndex<Schema>[] = []
#checks: CheckConstraint<Schema>[] = []

Expand Down Expand Up @@ -100,7 +100,7 @@ export class DmlEntity<
name: InferDmlEntityNameFromConfig<TConfig>
tableName: string
schema: DMLSchema
cascades: EntityCascades<string[]>
cascades: EntityCascades<string[], string[]>
indexes: EntityIndex<Schema>[]
checks: CheckConstraint<Schema>[]
} {
Expand Down Expand Up @@ -139,7 +139,8 @@ export class DmlEntity<
*/
cascades(
options: EntityCascades<
ExtractEntityRelations<Schema, "hasOne" | "hasOneWithFK" | "hasMany">
ExtractEntityRelations<Schema, "hasOne" | "hasOneWithFK" | "hasMany">,
ExtractEntityRelations<Schema, "manyToMany">
>
) {
const childToParentCascades = options.delete?.filter((relationship) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export function defineHasOneRelationship(
any
>,
{ relatedModelName }: { relatedModelName: string },
cascades: EntityCascades<string[]>
cascades: EntityCascades<string[], string[]>
) {
const shouldRemoveRelated = !!cascades.delete?.includes(relationship.name)
const { schema: relationSchema } = relatedEntity.parse()
Expand Down Expand Up @@ -179,7 +179,7 @@ export function defineHasOneWithFKRelationship(
MikroORMEntity: EntityConstructor<any>,
relationship: RelationshipMetadata,
{ relatedModelName }: { relatedModelName: string },
cascades: EntityCascades<string[]>
cascades: EntityCascades<string[], string[]>
) {
const foreignKeyName = camelToSnakeCase(`${relationship.name}Id`)
const shouldRemoveRelated = !!cascades.delete?.includes(relationship.name)
Expand Down Expand Up @@ -213,7 +213,7 @@ export function defineHasManyRelationship(
MikroORMEntity: EntityConstructor<any>,
relationship: RelationshipMetadata,
{ relatedModelName }: { relatedModelName: string },
cascades: EntityCascades<string[]>
cascades: EntityCascades<string[], string[]>
) {
const shouldRemoveRelated = !!cascades.delete?.includes(relationship.name)

Expand Down Expand Up @@ -259,7 +259,7 @@ export function defineBelongsToRelationship(
* define a onDelete: cascade when we are included in the delete
* list of parent cascade.
*/
const shouldCascade = relationCascades.delete?.includes(mappedBy)
const shouldCascade = !!relationCascades.delete?.includes(mappedBy)

/**
* Ensure the mapped by is defined as relationship on the other side
Expand Down Expand Up @@ -337,6 +337,9 @@ export function defineBelongsToRelationship(
DmlManyToMany.isManyToMany(otherSideRelation)
) {
const foreignKeyName = camelToSnakeCase(`${relationship.name}Id`)
const detachCascade =
!!relationship.mappedBy &&
relationCascades.detach?.includes(relationship.mappedBy)

if (DmlManyToMany.isManyToMany(otherSideRelation)) {
Property({
Expand All @@ -350,6 +353,7 @@ export function defineBelongsToRelationship(
entity: relatedModelName,
nullable: relationship.nullable,
persist: false,
onDelete: shouldCascade || detachCascade ? "cascade" : undefined,
})(MikroORMEntity.prototype, relationship.name)
} else {
ManyToOne({
Expand Down Expand Up @@ -660,7 +664,7 @@ export function defineRelationship(
MikroORMEntity: EntityConstructor<any>,
entity: DmlEntity<any, any>,
relationship: RelationshipMetadata,
cascades: EntityCascades<string[]>,
cascades: EntityCascades<string[], string[]>,
context: Context
) {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ moduleIntegrationTestRunner<ICustomerModuleService>({

expect(Object.keys(linkable)).toEqual([
"customerAddress",
"customerGroupCustomer",
"customerGroup",
"customer",
"customerGroup",
"customerGroupCustomer",
])

Object.keys(linkable).forEach((key) => {
Expand Down
Loading
Loading