forked from medusajs/medusa
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(user): Migrate user module to DML (medusajs#10389)
* feat(user): Migrate user module to DML * Create rotten-tigers-worry.md * update indexes names following conventions * remove duplicate modifier
- Loading branch information
Showing
8 changed files
with
105 additions
and
259 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@medusajs/user": minor | ||
--- | ||
|
||
feat(user): Migrate user module to DML |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,22 +8,16 @@ import jwt, { JwtPayload } from "jsonwebtoken" | |
|
||
jest.setTimeout(30000) | ||
|
||
const expireDate = new Date().setMilliseconds( | ||
new Date().getMilliseconds() + 60 * 60 * 24 | ||
) | ||
|
||
const defaultInviteData = [ | ||
{ | ||
id: "1", | ||
email: "[email protected]", | ||
token: "test", | ||
expires_at: expireDate, | ||
}, | ||
{ | ||
id: "2", | ||
email: "[email protected]", | ||
token: "test", | ||
expires_at: expireDate, | ||
}, | ||
] | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
packages/modules/user/src/migrations/Migration20241202103352.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { Migration } from '@mikro-orm/migrations'; | ||
|
||
export class Migration20241202103352 extends Migration { | ||
|
||
async up(): Promise<void> { | ||
this.addSql('drop index if exists "IDX_invite_email";'); | ||
this.addSql('CREATE UNIQUE INDEX IF NOT EXISTS "IDX_invite_email_unique" ON "invite" (email) WHERE deleted_at IS NULL;'); | ||
|
||
this.addSql('drop index if exists "IDX_user_email";'); | ||
this.addSql('CREATE UNIQUE INDEX IF NOT EXISTS "IDX_user_email_unique" ON "user" (email) WHERE deleted_at IS NULL;'); | ||
} | ||
|
||
async down(): Promise<void> { | ||
this.addSql('drop index if exists "IDX_invite_email_unique";'); | ||
this.addSql('CREATE UNIQUE INDEX IF NOT EXISTS "IDX_invite_email" ON "invite" (email) WHERE deleted_at IS NULL;'); | ||
|
||
this.addSql('drop index if exists "IDX_user_email_unique";'); | ||
this.addSql('CREATE UNIQUE INDEX IF NOT EXISTS "IDX_user_email" ON "user" (email) WHERE deleted_at IS NULL;'); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
export { default as User } from "./user" | ||
export { default as Invite } from "./invite" | ||
export { User } from "./user" | ||
export { Invite } from "./invite" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,112 +1,22 @@ | ||
import { | ||
BeforeCreate, | ||
Entity, | ||
Filter, | ||
Index, | ||
OnInit, | ||
OptionalProps, | ||
PrimaryKey, | ||
Property, | ||
} from "@mikro-orm/core" | ||
|
||
import { DAL } from "@medusajs/framework/types" | ||
import { | ||
DALUtils, | ||
createPsqlIndexStatementHelper, | ||
generateEntityId, | ||
Searchable, | ||
} from "@medusajs/framework/utils" | ||
|
||
const inviteEmailIndexName = "IDX_invite_email" | ||
const inviteEmailIndexStatement = createPsqlIndexStatementHelper({ | ||
name: inviteEmailIndexName, | ||
tableName: "invite", | ||
columns: "email", | ||
where: "deleted_at IS NULL", | ||
unique: true, | ||
}).expression | ||
|
||
const inviteTokenIndexName = "IDX_invite_token" | ||
const inviteTokenIndexStatement = createPsqlIndexStatementHelper({ | ||
name: inviteTokenIndexName, | ||
tableName: "invite", | ||
columns: "token", | ||
where: "deleted_at IS NULL", | ||
}).expression | ||
|
||
const inviteDeletedAtIndexName = "IDX_invite_deleted_at" | ||
const inviteDeletedAtIndexStatement = createPsqlIndexStatementHelper({ | ||
name: inviteDeletedAtIndexName, | ||
tableName: "invite", | ||
columns: "deleted_at", | ||
where: "deleted_at IS NOT NULL", | ||
}).expression | ||
|
||
type OptionalFields = | ||
| "metadata" | ||
| "accepted" | ||
| DAL.SoftDeletableModelDateColumns | ||
@Entity({ tableName: "invite" }) | ||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) | ||
export default class Invite { | ||
[OptionalProps]: OptionalFields | ||
|
||
@PrimaryKey({ columnType: "text" }) | ||
id: string | ||
|
||
@Index({ | ||
name: inviteEmailIndexName, | ||
expression: inviteEmailIndexStatement, | ||
}) | ||
@Searchable() | ||
@Property({ columnType: "text" }) | ||
email: string | ||
|
||
@Property({ columnType: "boolean" }) | ||
accepted: boolean = false | ||
|
||
@Index({ | ||
name: inviteTokenIndexName, | ||
expression: inviteTokenIndexStatement, | ||
import { model } from "@medusajs/framework/utils" | ||
|
||
export const Invite = model | ||
.define("invite", { | ||
id: model.id({ prefix: "invite" }).primaryKey(), | ||
email: model.text().searchable(), | ||
accepted: model.boolean().default(false), | ||
token: model.text(), | ||
expires_at: model.dateTime(), | ||
metadata: model.json().nullable(), | ||
}) | ||
@Property({ columnType: "text" }) | ||
token: string | ||
|
||
@Property({ columnType: "timestamptz" }) | ||
expires_at: Date | ||
|
||
@Property({ columnType: "jsonb", nullable: true }) | ||
metadata: Record<string, unknown> | null = null | ||
|
||
@Property({ | ||
onCreate: () => new Date(), | ||
columnType: "timestamptz", | ||
defaultRaw: "now()", | ||
}) | ||
created_at: Date | ||
|
||
@Property({ | ||
onCreate: () => new Date(), | ||
onUpdate: () => new Date(), | ||
columnType: "timestamptz", | ||
defaultRaw: "now()", | ||
}) | ||
updated_at: Date | ||
|
||
@Index({ | ||
name: inviteDeletedAtIndexName, | ||
expression: inviteDeletedAtIndexStatement, | ||
}) | ||
@Property({ columnType: "timestamptz", nullable: true }) | ||
deleted_at: Date | null = null | ||
|
||
@OnInit() | ||
onInit() { | ||
this.id = generateEntityId(this.id, "invite") | ||
} | ||
|
||
@BeforeCreate() | ||
beforeCreate() { | ||
this.id = generateEntityId(this.id, "invite") | ||
} | ||
} | ||
.indexes([ | ||
{ | ||
on: ["email"], | ||
unique: true, | ||
where: "deleted_at IS NULL", | ||
}, | ||
{ | ||
on: ["token"], | ||
where: "deleted_at IS NULL", | ||
}, | ||
]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,102 +1,18 @@ | ||
import { | ||
BeforeCreate, | ||
Entity, | ||
Filter, | ||
Index, | ||
OnInit, | ||
OptionalProps, | ||
PrimaryKey, | ||
Property, | ||
} from "@mikro-orm/core" | ||
|
||
import { DAL } from "@medusajs/framework/types" | ||
import { | ||
createPsqlIndexStatementHelper, | ||
DALUtils, | ||
generateEntityId, | ||
Searchable, | ||
} from "@medusajs/framework/utils" | ||
|
||
const userEmailIndexName = "IDX_user_email" | ||
const userEmailIndexStatement = createPsqlIndexStatementHelper({ | ||
name: userEmailIndexName, | ||
unique: true, | ||
tableName: "user", | ||
columns: "email", | ||
where: "deleted_at IS NULL", | ||
}) | ||
|
||
const userDeletedAtIndexName = "IDX_user_deleted_at" | ||
const userDeletedAtIndexStatement = createPsqlIndexStatementHelper({ | ||
name: userDeletedAtIndexName, | ||
tableName: "user", | ||
columns: "deleted_at", | ||
where: "deleted_at IS NOT NULL", | ||
}).expression | ||
|
||
type OptionalFields = | ||
| "first_name" | ||
| "last_name" | ||
| "metadata" | ||
| "avatar_url" | ||
| DAL.SoftDeletableModelDateColumns | ||
|
||
@Entity() | ||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) | ||
export default class User { | ||
[OptionalProps]?: OptionalFields | ||
|
||
@PrimaryKey({ columnType: "text" }) | ||
id!: string | ||
|
||
@Searchable() | ||
@Property({ columnType: "text", nullable: true }) | ||
first_name: string | null = null | ||
|
||
@Searchable() | ||
@Property({ columnType: "text", nullable: true }) | ||
last_name: string | null = null | ||
|
||
@userEmailIndexStatement.MikroORMIndex() | ||
@Searchable() | ||
@Property({ columnType: "text" }) | ||
email: string | ||
|
||
@Property({ columnType: "text", nullable: true }) | ||
avatar_url: string | null = null | ||
|
||
@Property({ columnType: "jsonb", nullable: true }) | ||
metadata: Record<string, unknown> | null = null | ||
|
||
@Property({ | ||
onCreate: () => new Date(), | ||
columnType: "timestamptz", | ||
defaultRaw: "now()", | ||
}) | ||
created_at: Date | ||
|
||
@Property({ | ||
onCreate: () => new Date(), | ||
onUpdate: () => new Date(), | ||
columnType: "timestamptz", | ||
defaultRaw: "now()", | ||
import { model } from "@medusajs/framework/utils" | ||
|
||
export const User = model | ||
.define("user", { | ||
id: model.id({ prefix: "user" }).primaryKey(), | ||
first_name: model.text().searchable().nullable(), | ||
last_name: model.text().searchable().nullable(), | ||
email: model.text().searchable(), | ||
avatar_url: model.text().nullable(), | ||
metadata: model.json().nullable(), | ||
}) | ||
updated_at: Date | ||
|
||
@Index({ | ||
name: userDeletedAtIndexName, | ||
expression: userDeletedAtIndexStatement, | ||
}) | ||
@Property({ columnType: "timestamptz", nullable: true }) | ||
deleted_at?: Date | null = null | ||
|
||
@BeforeCreate() | ||
onCreate() { | ||
this.id = generateEntityId(this.id, "user") | ||
} | ||
|
||
@OnInit() | ||
onInit() { | ||
this.id = generateEntityId(this.id, "user") | ||
} | ||
} | ||
.indexes([ | ||
{ | ||
unique: true, | ||
on: ["email"], | ||
where: "deleted_at IS NULL", | ||
}, | ||
]) |
Oops, something went wrong.