diff --git a/.changeset/yellow-penguins-pay.md b/.changeset/yellow-penguins-pay.md new file mode 100644 index 0000000000000..de25a21faad74 --- /dev/null +++ b/.changeset/yellow-penguins-pay.md @@ -0,0 +1,7 @@ +--- +"@medusajs/index": patch +"@medusajs/types": patch +"@medusajs/utils": patch +--- + +chore: index module to DML diff --git a/packages/core/types/src/dml/index.ts b/packages/core/types/src/dml/index.ts index f45752fa8fd27..3dbf20968d762 100644 --- a/packages/core/types/src/dml/index.ts +++ b/packages/core/types/src/dml/index.ts @@ -41,6 +41,7 @@ export type KnownDataTypes = | "enum" | "number" | "bigNumber" + | "serial" | "dateTime" | "array" | "json" @@ -310,6 +311,11 @@ export type EntityIndex< * Conditions to restrict which records are indexed. */ where?: Where + + /** + * The type of the index. (e.g: GIN) + */ + type?: string } export type SimpleQueryValue = string | number | boolean | null diff --git a/packages/core/utils/src/dml/__tests__/autoincrement-property.spec.ts b/packages/core/utils/src/dml/__tests__/autoincrement-property.spec.ts new file mode 100644 index 0000000000000..dd2a1e851bee2 --- /dev/null +++ b/packages/core/utils/src/dml/__tests__/autoincrement-property.spec.ts @@ -0,0 +1,20 @@ +import { expectTypeOf } from "expect-type" +import { AutoIncrementProperty } from "../properties/autoincrement" + +describe("Autoincrement property", () => { + test("create autoincrement property type", () => { + const property = new AutoIncrementProperty() + + expectTypeOf(property["$dataType"]).toEqualTypeOf() + expect(property.parse("display_id")).toEqual({ + fieldName: "display_id", + dataType: { + name: "serial", + options: {}, + }, + nullable: false, + indexes: [], + relationships: [], + }) + }) +}) diff --git a/packages/core/utils/src/dml/__tests__/entity-builder.spec.ts b/packages/core/utils/src/dml/__tests__/entity-builder.spec.ts index 12501f91f1d67..92891fcd5cecb 100644 --- a/packages/core/utils/src/dml/__tests__/entity-builder.spec.ts +++ b/packages/core/utils/src/dml/__tests__/entity-builder.spec.ts @@ -3736,6 +3736,7 @@ describe("Entity builder", () => { }, group: { entity: "Group", + fieldName: "group_id", name: "group", nullable: false, persist: false, @@ -4355,6 +4356,7 @@ describe("Entity builder", () => { }, user: { entity: "User", + fieldName: "user_id", name: "user", nullable: false, persist: false, @@ -4363,8 +4365,8 @@ describe("Entity builder", () => { user_id: { columnType: "text", entity: "User", - fieldName: "user_id", mapToPk: true, + fieldName: "user_id", name: "user_id", nullable: false, onDelete: "cascade", @@ -4949,6 +4951,7 @@ describe("Entity builder", () => { name: "user", reference: "m:1", entity: "User", + fieldName: "user_id", persist: false, nullable: false, }, @@ -5136,6 +5139,7 @@ describe("Entity builder", () => { user: { name: "user", reference: "m:1", + fieldName: "user_id", entity: "User", persist: false, nullable: true, @@ -5697,6 +5701,7 @@ describe("Entity builder", () => { }, parent: { name: "parent", + fieldName: "parent_id", reference: "m:1", entity: "User", persist: false, @@ -7447,39 +7452,37 @@ describe("Entity builder", () => { }, user_id: { name: "user_id", - reference: "m:1", - entity: "User", + reference: "scalar", columnType: "text", - mapToPk: true, fieldName: "user_id", + getter: false, + setter: false, nullable: false, + type: "User", }, user: { - reference: "scalar", - type: "User", + reference: "m:1", + entity: "User", persist: false, nullable: false, name: "user", - getter: false, - setter: false, }, team_id: { name: "team_id", - reference: "m:1", - entity: "Team", + reference: "scalar", columnType: "text", - mapToPk: true, fieldName: "team_id", nullable: false, + getter: false, + setter: false, + type: "Team", }, team: { - reference: "scalar", - type: "Team", + reference: "m:1", + entity: "Team", persist: false, nullable: false, name: "team", - getter: false, - setter: false, }, created_at: { reference: "scalar", diff --git a/packages/core/utils/src/dml/entity-builder.ts b/packages/core/utils/src/dml/entity-builder.ts index f93d2a2044bb0..4545171084c4e 100644 --- a/packages/core/utils/src/dml/entity-builder.ts +++ b/packages/core/utils/src/dml/entity-builder.ts @@ -13,6 +13,7 @@ import { DMLSchemaDefaults, } from "./helpers/entity-builder/create-default-properties" import { ArrayProperty } from "./properties/array" +import { AutoIncrementProperty } from "./properties/autoincrement" import { BigNumberProperty } from "./properties/big-number" import { BooleanProperty } from "./properties/boolean" import { DateTimeProperty } from "./properties/date-time" @@ -24,8 +25,8 @@ import { TextProperty } from "./properties/text" import { BelongsTo } from "./relations/belongs-to" import { HasMany } from "./relations/has-many" import { HasOne } from "./relations/has-one" -import { ManyToMany } from "./relations/many-to-many" import { HasOneWithForeignKey } from "./relations/has-one-fk" +import { ManyToMany } from "./relations/many-to-many" /** * The implicit properties added by EntityBuilder in every schema @@ -60,11 +61,11 @@ export type ManyToManyOptions = RelationshipOptions & /** * The column name in the pivot table that for the current entity */ - joinColumn?: string + joinColumn?: string | string[] /** * The column name in the pivot table for the opposite entity */ - inverseJoinColumn?: string + inverseJoinColumn?: string | string[] } | { /** @@ -77,6 +78,14 @@ export type ManyToManyOptions = RelationshipOptions & * database for this relationship. */ pivotEntity?: () => DmlEntity + /** + * The column name in the pivot table that for the current entity + */ + joinColumn?: string | string[] + /** + * The column name in the pivot table for the opposite entity + */ + inverseJoinColumn?: string | string[] } ) @@ -240,6 +249,26 @@ export class EntityBuilder { return new BigNumberProperty() } + /** + * This method defines an autoincrement property. + * + * @example + * import { model } from "@medusajs/framework/utils" + * + * const MyCustom = model.define("my_custom", { + * serial_id: model.autoincrement(), + * // ... + * }) + * + * export default MyCustom + * + * @customNamespace Property + */ + + autoincrement() { + return new AutoIncrementProperty() + } + /** * This method defines an array of strings property. * diff --git a/packages/core/utils/src/dml/helpers/entity-builder/define-property.ts b/packages/core/utils/src/dml/helpers/entity-builder/define-property.ts index a52387832f855..f31b1b27f9b6f 100644 --- a/packages/core/utils/src/dml/helpers/entity-builder/define-property.ts +++ b/packages/core/utils/src/dml/helpers/entity-builder/define-property.ts @@ -4,8 +4,6 @@ import { PropertyMetadata, PropertyType, } from "@medusajs/types" -import { MikroOrmBigNumberProperty } from "../../../dal" -import { generateEntityId, isDefined } from "../../../common" import { ArrayType, BeforeCreate, @@ -14,7 +12,10 @@ import { PrimaryKey, Property, Utils, + t as mikroOrmType, } from "@mikro-orm/core" +import { generateEntityId, isDefined } from "../../../common" +import { MikroOrmBigNumberProperty } from "../../../dal" import { PrimaryKeyModifier } from "../../properties/primary-key" import { applyEntityIndexes } from "../mikro-orm/apply-indexes" @@ -32,6 +33,7 @@ const COLUMN_TYPES: { dateTime: "timestamptz", number: "integer", bigNumber: "numeric", + serial: "number", text: "text", json: "jsonb", array: "array", @@ -51,6 +53,7 @@ const PROPERTY_TYPES: { dateTime: "date", number: "number", bigNumber: "number", + serial: "number", text: "string", json: "any", array: "string[]", @@ -202,19 +205,16 @@ export function defineProperty( * Defining an id property */ if (field.dataType.name === "id") { - const IdDecorator = PrimaryKeyModifier.isPrimaryKeyModifier(property) - ? PrimaryKey({ - columnType: "text", - type: "string", - nullable: false, - fieldName: field.fieldName, - }) - : Property({ - columnType: "text", - type: "string", - nullable: false, - fieldName: field.fieldName, - }) + const Prop = PrimaryKeyModifier.isPrimaryKeyModifier(property) + ? PrimaryKey + : Property + + const IdDecorator = Prop({ + columnType: "text", + type: "string", + nullable: false, + fieldName: field.fieldName, + }) IdDecorator(MikroORMEntity.prototype, field.fieldName) @@ -259,6 +259,24 @@ export function defineProperty( return } + /** + * Handling serial property separately to set the column type + */ + if (field.dataType.name === "serial") { + const Prop = PrimaryKeyModifier.isPrimaryKeyModifier(property) + ? PrimaryKey + : Property + + Prop({ + columnType: "serial", + type: mikroOrmType.integer, + nullable: true, + fieldName: field.fieldName, + serializer: Number, + })(MikroORMEntity.prototype, field.fieldName) + return + } + /** * Define rest of properties */ diff --git a/packages/core/utils/src/dml/helpers/entity-builder/define-relationship.ts b/packages/core/utils/src/dml/helpers/entity-builder/define-relationship.ts index e15a8bf9c664d..49462f165b371 100644 --- a/packages/core/utils/src/dml/helpers/entity-builder/define-relationship.ts +++ b/packages/core/utils/src/dml/helpers/entity-builder/define-relationship.ts @@ -21,10 +21,10 @@ import { camelToSnakeCase, pluralize } from "../../../common" import { DmlEntity } from "../../entity" import { HasMany } from "../../relations/has-many" import { HasOne } from "../../relations/has-one" +import { HasOneWithForeignKey } from "../../relations/has-one-fk" import { ManyToMany as DmlManyToMany } from "../../relations/many-to-many" import { applyEntityIndexes } from "../mikro-orm/apply-indexes" import { parseEntityName } from "./parse-entity-name" -import { HasOneWithForeignKey } from "../../relations/has-one-fk" type Context = { MANY_TO_MANY_TRACKED_RELATIONS: Record @@ -329,25 +329,32 @@ export function defineBelongsToRelationship( ) { const foreignKeyName = camelToSnakeCase(`${relationship.name}Id`) - ManyToOne({ - entity: relatedModelName, - columnType: "text", - mapToPk: true, - fieldName: foreignKeyName, - nullable: relationship.nullable, - onDelete: shouldCascade ? "cascade" : undefined, - })(MikroORMEntity.prototype, foreignKeyName) - if (DmlManyToMany.isManyToMany(otherSideRelation)) { Property({ type: relatedModelName, - persist: false, + columnType: "text", + fieldName: foreignKeyName, + nullable: relationship.nullable, + })(MikroORMEntity.prototype, foreignKeyName) + + ManyToOne({ + entity: relatedModelName, nullable: relationship.nullable, + persist: false, })(MikroORMEntity.prototype, relationship.name) } else { - // HasMany case ManyToOne({ entity: relatedModelName, + columnType: "text", + mapToPk: true, + fieldName: foreignKeyName, + nullable: relationship.nullable, + onDelete: shouldCascade ? "cascade" : undefined, + })(MikroORMEntity.prototype, foreignKeyName) + + ManyToOne({ + entity: relatedModelName, + fieldName: foreignKeyName, persist: false, nullable: relationship.nullable, })(MikroORMEntity.prototype, relationship.name) @@ -446,9 +453,30 @@ export function defineManyToManyRelationship( let inversedBy: undefined | string let pivotEntityName: undefined | string let pivotTableName: undefined | string - let joinColumn: undefined | string = relationship.options.joinColumn - let inverseJoinColumn: undefined | string = + + const joinColumn: undefined | string = !Array.isArray( + relationship.options.joinColumn + ) + ? relationship.options.joinColumn + : undefined + + const joinColumns: undefined | string[] = Array.isArray( + relationship.options.joinColumn + ) + ? relationship.options.joinColumn + : undefined + + const inverseJoinColumn: undefined | string = !Array.isArray( relationship.options.inverseJoinColumn + ) + ? relationship.options.inverseJoinColumn + : undefined + + const inverseJoinColumns: undefined | string[] = Array.isArray( + relationship.options.inverseJoinColumn + ) + ? relationship.options.inverseJoinColumn + : undefined const [otherSideRelationshipProperty, otherSideRelationship] = retrieveOtherSideRelationshipManyToMany({ @@ -540,7 +568,9 @@ export function defineManyToManyRelationship( const configuresRelationship = !!( joinColumn || + joinColumns || inverseJoinColumn || + inverseJoinColumns || relationship.options.pivotTable ) const relatedOneConfiguresRelationship = !!( @@ -586,7 +616,16 @@ export function defineManyToManyRelationship( const mappedByPropValue = mappedBy ?? inversedBy ?? otherSideRelationshipProperty - ManyToMany({ + const joinColumnProp = Array.isArray(relationship.options.joinColumn) + ? "joinColumns" + : "joinColumn" + const inverseJoinColumnProp = Array.isArray( + relationship.options.inverseJoinColumn + ) + ? "inverseJoinColumns" + : "inverseJoinColumn" + + const manytoManyOptions = { owner: isOwner, entity: relatedModelName, ...(pivotTableName @@ -598,9 +637,11 @@ export function defineManyToManyRelationship( : {}), ...(pivotEntityName ? { pivotEntity: pivotEntityName } : {}), ...({ [mappedByProp]: mappedByPropValue } as any), - ...(joinColumn ? { joinColumn } : {}), - ...(inverseJoinColumn ? { inverseJoinColumn } : {}), - })(MikroORMEntity.prototype, relationship.name) + [joinColumnProp]: joinColumn ?? joinColumns, + [inverseJoinColumnProp]: inverseJoinColumn ?? inverseJoinColumns, + } + + ManyToMany(manytoManyOptions)(MikroORMEntity.prototype, relationship.name) } /** diff --git a/packages/core/utils/src/dml/helpers/mikro-orm/apply-indexes.ts b/packages/core/utils/src/dml/helpers/mikro-orm/apply-indexes.ts index f6b43f7da4d66..d03750807d884 100644 --- a/packages/core/utils/src/dml/helpers/mikro-orm/apply-indexes.ts +++ b/packages/core/utils/src/dml/helpers/mikro-orm/apply-indexes.ts @@ -48,6 +48,7 @@ export function applyEntityIndexes( columns: index.on as string[], unique: index.unique, where: index.where, + type: index.type, }) entityIndexStatement.MikroORMIndex()(MikroORMEntity) diff --git a/packages/core/utils/src/dml/properties/autoincrement.ts b/packages/core/utils/src/dml/properties/autoincrement.ts new file mode 100644 index 0000000000000..e78279db62026 --- /dev/null +++ b/packages/core/utils/src/dml/properties/autoincrement.ts @@ -0,0 +1,41 @@ +import { BaseProperty } from "./base" +import { PrimaryKeyModifier } from "./primary-key" + +/** + * The AutoIncrementProperty is used to define a serial + * property + */ +export class AutoIncrementProperty extends BaseProperty { + protected dataType: { + name: "serial" + options: {} + } + + /** + * This method indicates that the property is the data model's primary key. + * + * @example + * import { model } from "@medusajs/framework/utils" + * + * const Product = model.define("Product", { + * id: model.autoincrement().primaryKey(), + * // ... + * }) + * + * export default Product + * + * @customNamespace Property Configuration Methods + */ + primaryKey() { + return new PrimaryKeyModifier(this) + } + + constructor(options?: { primaryKey?: boolean }) { + super() + + this.dataType = { + name: "serial", + options: { ...options }, + } + } +} diff --git a/packages/core/utils/src/dml/properties/index.ts b/packages/core/utils/src/dml/properties/index.ts index 9c55e703660a0..5d85ca547ca93 100644 --- a/packages/core/utils/src/dml/properties/index.ts +++ b/packages/core/utils/src/dml/properties/index.ts @@ -1,4 +1,5 @@ export * from "./array" +export * from "./autoincrement" export * from "./base" export * from "./big-number" export * from "./boolean" diff --git a/packages/modules/index/integration-tests/__tests__/index-engine-module.spec.ts b/packages/modules/index/integration-tests/__tests__/index-engine-module.spec.ts index 7ae1190cd2636..8916ba3440b83 100644 --- a/packages/modules/index/integration-tests/__tests__/index-engine-module.spec.ts +++ b/packages/modules/index/integration-tests/__tests__/index-engine-module.spec.ts @@ -10,11 +10,12 @@ import { ContainerRegistrationKeys, ModuleRegistrationName, Modules, + toMikroORMEntity, } from "@medusajs/framework/utils" +import { initDb, TestDatabaseUtils } from "@medusajs/test-utils" import { EntityManager } from "@mikro-orm/postgresql" import { IndexData, IndexRelation } from "@models" import { asValue } from "awilix" -import { initDb, TestDatabaseUtils } from "@medusajs/test-utils" import * as path from "path" import { EventBusServiceMock } from "../__fixtures__" import { dbName } from "../__fixtures__/medusa-config" @@ -254,7 +255,10 @@ describe("IndexModuleService", function () { * Validate all index entries and index relation entries */ - const indexEntries: IndexData[] = await manager.find(IndexData, {}) + const indexEntries: IndexData[] = await manager.find( + toMikroORMEntity(IndexData), + {} + ) const productIndexEntries = indexEntries.filter((entry) => { return entry.name === "Product" @@ -412,7 +416,10 @@ describe("IndexModuleService", function () { * Validate all index entries and index relation entries */ - const indexEntries: IndexData[] = await manager.find(IndexData, {}) + const indexEntries: IndexData[] = await manager.find( + toMikroORMEntity(IndexData), + {} + ) const productIndexEntries = indexEntries.filter((entry) => { return entry.name === "Product" @@ -596,7 +603,10 @@ describe("IndexModuleService", function () { afterEach(afterEach_) it("should update the corresponding index entries", async () => { - const updatedIndexEntries = await manager.find(IndexData, {}) + const updatedIndexEntries = await manager.find( + toMikroORMEntity(IndexData), + {} + ) expect(updatedIndexEntries).toHaveLength(2) @@ -710,8 +720,14 @@ describe("IndexModuleService", function () { afterEach(afterEach_) it("should consume all deleted events and delete the index entries", async () => { - const indexEntries = await manager.find(IndexData, {}) - const indexRelationEntries = await manager.find(IndexRelation, {}) + const indexEntries = await manager.find(toMikroORMEntity(IndexData), {}) + const indexRelationEntries = await manager.find( + toMikroORMEntity(IndexRelation), + {}, + { + populate: ["parent", "child"], + } + ) expect(indexEntries).toHaveLength(3) expect(indexRelationEntries).toHaveLength(2) diff --git a/packages/modules/index/src/migrations/.snapshot-medusa-index.json b/packages/modules/index/src/migrations/.snapshot-medusa-index.json index 3f8bf1d91e7b4..4f1381987680c 100644 --- a/packages/modules/index/src/migrations/.snapshot-medusa-index.json +++ b/packages/modules/index/src/migrations/.snapshot-medusa-index.json @@ -1,5 +1,7 @@ { - "namespaces": ["public"], + "namespaces": [ + "public" + ], "name": "public", "tables": [ { @@ -31,36 +33,81 @@ "nullable": false, "default": "'{}'", "mappedType": "json" + }, + "created_at": { + "name": "created_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 6, + "mappedType": "datetime" } }, "name": "index_data", "schema": "public", "indexes": [ { - "columnNames": ["id"], + "keyName": "IDX_index_data_deleted_at", + "columnNames": [], "composite": false, - "keyName": "IDX_index_data_id", "primary": false, - "unique": false + "unique": false, + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_index_data_deleted_at\" ON \"index_data\" (deleted_at) WHERE deleted_at IS NULL" }, { - "columnNames": ["name"], + "keyName": "IDX_index_data_gin", + "columnNames": [], "composite": false, - "keyName": "IDX_index_data_name", "primary": false, - "unique": false + "unique": false, + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_index_data_gin\" ON \"index_data\" USING GIN (data) WHERE deleted_at IS NULL" }, { - "keyName": "IDX_index_data_gin", - "columnNames": ["data"], + "keyName": "IDX_index_data_id", + "columnNames": [], "composite": false, "primary": false, "unique": false, - "type": "GIN" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_index_data_id\" ON \"index_data\" (id) WHERE deleted_at IS NULL" + }, + { + "keyName": "IDX_index_data_name", + "columnNames": [], + "composite": false, + "primary": false, + "unique": false, + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_index_data_name\" ON \"index_data\" (name) WHERE deleted_at IS NULL" }, { "keyName": "index_data_pkey", - "columnNames": ["id", "name"], + "columnNames": [ + "id", + "name" + ], "composite": true, "primary": true, "unique": true @@ -73,12 +120,12 @@ "columns": { "id": { "name": "id", - "type": "text", + "type": "number", "unsigned": true, "autoincrement": true, - "primary": false, + "primary": true, "nullable": false, - "mappedType": "text" + "mappedType": "integer" }, "pivot": { "name": "pivot", @@ -89,8 +136,8 @@ "nullable": false, "mappedType": "text" }, - "parent_id": { - "name": "parent_id", + "parent_name": { + "name": "parent_name", "type": "text", "unsigned": false, "autoincrement": false, @@ -98,8 +145,8 @@ "nullable": false, "mappedType": "text" }, - "parent_name": { - "name": "parent_name", + "child_name": { + "name": "child_name", "type": "text", "unsigned": false, "autoincrement": false, @@ -107,8 +154,8 @@ "nullable": false, "mappedType": "text" }, - "child_id": { - "name": "child_id", + "parent_id": { + "name": "parent_id", "type": "text", "unsigned": false, "autoincrement": false, @@ -116,30 +163,81 @@ "nullable": false, "mappedType": "text" }, - "child_name": { - "name": "child_name", + "child_id": { + "name": "child_id", "type": "text", "unsigned": false, "autoincrement": false, "primary": false, "nullable": false, "mappedType": "text" + }, + "created_at": { + "name": "created_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "default": "now()", + "mappedType": "datetime" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 6, + "mappedType": "datetime" } }, "name": "index_relation", "schema": "public", "indexes": [ + { + "keyName": "IDX_index_relation_parent_id", + "columnNames": [], + "composite": false, + "primary": false, + "unique": false, + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_index_relation_parent_id\" ON \"index_relation\" (parent_id) WHERE deleted_at IS NULL" + }, { "keyName": "IDX_index_relation_child_id", - "columnNames": ["child_id"], + "columnNames": [], "composite": false, "primary": false, - "unique": false + "unique": false, + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_index_relation_child_id\" ON \"index_relation\" (child_id) WHERE deleted_at IS NULL" + }, + { + "keyName": "IDX_index_relation_deleted_at", + "columnNames": [], + "composite": false, + "primary": false, + "unique": false, + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_index_relation_deleted_at\" ON \"index_relation\" (deleted_at) WHERE deleted_at IS NULL" }, { "keyName": "index_relation_pkey", - "columnNames": ["id", "pivot"], - "composite": true, + "columnNames": [ + "id" + ], + "composite": false, "primary": true, "unique": true } diff --git a/packages/modules/index/src/migrations/Migration20241209173313.ts b/packages/modules/index/src/migrations/Migration20241209173313.ts new file mode 100644 index 0000000000000..0fe2f0c1f3810 --- /dev/null +++ b/packages/modules/index/src/migrations/Migration20241209173313.ts @@ -0,0 +1,35 @@ +import { Migration } from "@mikro-orm/migrations" + +export class Migration20241209173313 extends Migration { + async up(): Promise { + this.addSql(` + ALTER TABLE "index_data" + ADD COLUMN IF NOT EXISTS "created_at" timestamptz NOT NULL DEFAULT now(), + ADD COLUMN IF NOT EXISTS "updated_at" timestamptz NOT NULL DEFAULT now(), + ADD COLUMN IF NOT EXISTS "deleted_at" timestamptz NULL; + `) + + this.addSql(` + ALTER TABLE "index_relation" + ADD COLUMN IF NOT EXISTS "created_at" timestamptz NOT NULL DEFAULT now(), + ADD COLUMN IF NOT EXISTS "updated_at" timestamptz NOT NULL DEFAULT now(), + ADD COLUMN IF NOT EXISTS "deleted_at" timestamptz NULL; + `) + } + + async down(): Promise { + this.addSql(` + ALTER TABLE "index_data" + DROP COLUMN IF EXISTS "created_at", + DROP COLUMN IF EXISTS "updated_at", + DROP COLUMN IF EXISTS "deleted_at"; + `) + + this.addSql(` + ALTER TABLE "index_relation" + DROP COLUMN IF EXISTS "created_at", + DROP COLUMN IF EXISTS "updated_at", + DROP COLUMN IF EXISTS "deleted_at"; + `) + } +} diff --git a/packages/modules/index/src/models/index-data.ts b/packages/modules/index/src/models/index-data.ts index 4d1a6cb23da11..b56cb86674fad 100644 --- a/packages/modules/index/src/models/index-data.ts +++ b/packages/modules/index/src/models/index-data.ts @@ -1,45 +1,35 @@ -import { - Cascade, - Collection, - Entity, - Index, - ManyToMany, - OptionalProps, - PrimaryKey, - PrimaryKeyType, - Property, -} from "@mikro-orm/core" -import { IndexRelation } from "./index-relation" +import { model } from "@medusajs/framework/utils" +import IndexRelation from "./index-relation" -type OptionalRelations = "parents" - -@Entity({ - tableName: "index_data", -}) -export class IndexData { - [OptionalProps]: OptionalRelations - - @PrimaryKey({ columnType: "text" }) - @Index({ name: "IDX_index_data_id" }) - id!: string - - @PrimaryKey({ columnType: "text" }) - @Index({ name: "IDX_index_data_name" }) - name: string; - - [PrimaryKeyType]?: [string, string] - - @Index({ name: "IDX_index_data_gin", type: "GIN" }) - @Property({ columnType: "jsonb", default: "{}" }) - data: Record - - @ManyToMany({ - owner: true, - entity: () => IndexData, - pivotEntity: () => IndexRelation, - cascade: [Cascade.REMOVE], - inverseJoinColumns: ["parent_id", "parent_name"], - joinColumns: ["child_id", "child_name"], +const IndexData = model + .define("IndexData", { + id: model.text().primaryKey(), + name: model.text().primaryKey(), + data: model.json().default({}), + parents: model.manyToMany(() => IndexData, { + mappedBy: "children", + pivotEntity: () => IndexRelation, + joinColumn: ["child_id", "child_name"], + inverseJoinColumn: ["parent_id", "parent_name"], + }), + children: model.manyToMany(() => IndexData, { + mappedBy: "parents", + }), }) - parents = new Collection(this) -} + .indexes([ + { + name: "IDX_index_data_gin", + type: "GIN", + on: ["data"], + }, + { + name: "IDX_index_data_id", + on: ["id"], + }, + { + name: "IDX_index_data_name", + on: ["name"], + }, + ]) + +export default IndexData diff --git a/packages/modules/index/src/models/index-relation.ts b/packages/modules/index/src/models/index-relation.ts index 7e4f00c2eec56..d2ae894ed8557 100644 --- a/packages/modules/index/src/models/index-relation.ts +++ b/packages/modules/index/src/models/index-relation.ts @@ -1,64 +1,16 @@ -import { - Entity, - Index, - ManyToOne, - OptionalProps, - PrimaryKey, - Property, - Ref, -} from "@mikro-orm/core" -import { IndexData } from "./index-data" - -type OptionalRelations = - | "parent" - | "child" - | "parent_id" - | "child_id" - | "parent_name" - | "child_name" - -@Entity({ - tableName: "index_relation", -}) -@Index({ - name: "IDX_index_relation_child_id", - properties: ["child_id"], +import { model } from "@medusajs/framework/utils" +import IndexData from "./index-data" + +const IndexRelation = model.define("IndexRelation", { + id: model.autoincrement().primaryKey(), + pivot: model.text(), + parent_name: model.text(), + child_name: model.text(), + parent: model.belongsTo(() => IndexData, { + mappedBy: "parents", + }), + child: model.belongsTo(() => IndexData, { + mappedBy: "children", + }), }) -export class IndexRelation { - [OptionalProps]: OptionalRelations - - @PrimaryKey({ columnType: "integer", autoincrement: true }) - id!: string - - // if added as PK, BeforeCreate value isn't set - @Property({ - columnType: "text", - }) - pivot: string - - @Property({ columnType: "text" }) - parent_id?: string - - @Property({ columnType: "text" }) - parent_name?: string - - @Property({ columnType: "text" }) - child_id?: string - - @Property({ columnType: "text" }) - child_name?: string - - @ManyToOne({ - entity: () => IndexData, - onDelete: "cascade", - persist: false, - }) - parent?: Ref - - @ManyToOne({ - entity: () => IndexData, - onDelete: "cascade", - persist: false, - }) - child?: Ref -} +export default IndexRelation diff --git a/packages/modules/index/src/models/index.ts b/packages/modules/index/src/models/index.ts index f448137cb5516..62e9850c7ad18 100644 --- a/packages/modules/index/src/models/index.ts +++ b/packages/modules/index/src/models/index.ts @@ -1,2 +1,2 @@ -export { IndexData } from "./index-data" -export { IndexRelation } from "./index-relation" +export { default as IndexData } from "./index-data" +export { default as IndexRelation } from "./index-relation" diff --git a/packages/modules/index/src/services/postgres-provider.ts b/packages/modules/index/src/services/postgres-provider.ts index e5bbb20ecefae..4b4e4429686d9 100644 --- a/packages/modules/index/src/services/postgres-provider.ts +++ b/packages/modules/index/src/services/postgres-provider.ts @@ -12,6 +12,7 @@ import { InjectTransactionManager, isDefined, MedusaContext, + toMikroORMEntity, } from "@medusajs/framework/utils" import { EntityManager, SqlEntityManager } from "@mikro-orm/postgresql" import { IndexData, IndexRelation } from "@models" @@ -338,8 +339,10 @@ export class PostgresProvider implements IndexTypes.StorageProvider { const { transactionManager: em } = sharedContext as { transactionManager: SqlEntityManager } - const indexRepository = em.getRepository(IndexData) - const indexRelationRepository = em.getRepository(IndexRelation) + const indexRepository = em.getRepository(toMikroORMEntity(IndexData)) + const indexRelationRepository = em.getRepository( + toMikroORMEntity(IndexRelation) + ) const { data: data_, @@ -432,7 +435,7 @@ export class PostgresProvider implements IndexTypes.StorageProvider { const { transactionManager: em } = sharedContext as { transactionManager: SqlEntityManager } - const indexRepository = em.getRepository(IndexData) + const indexRepository = em.getRepository(toMikroORMEntity(IndexData)) const { data: data_, entityProperties } = PostgresProvider.parseData( data, @@ -479,8 +482,10 @@ export class PostgresProvider implements IndexTypes.StorageProvider { const { transactionManager: em } = sharedContext as { transactionManager: SqlEntityManager } - const indexRepository = em.getRepository(IndexData) - const indexRelationRepository = em.getRepository(IndexRelation) + const indexRepository = em.getRepository(toMikroORMEntity(IndexData)) + const indexRelationRepository = em.getRepository( + toMikroORMEntity(IndexRelation) + ) const { data: data_ } = PostgresProvider.parseData( data, @@ -533,8 +538,10 @@ export class PostgresProvider implements IndexTypes.StorageProvider { const { transactionManager: em } = sharedContext as { transactionManager: SqlEntityManager } - const indexRepository = em.getRepository(IndexData) - const indexRelationRepository = em.getRepository(IndexRelation) + const indexRepository = em.getRepository(toMikroORMEntity(IndexData)) + const indexRelationRepository = em.getRepository( + toMikroORMEntity(IndexRelation) + ) const { data: data_, entityProperties } = PostgresProvider.parseData( data, @@ -654,8 +661,10 @@ export class PostgresProvider implements IndexTypes.StorageProvider { const { transactionManager: em } = sharedContext as { transactionManager: SqlEntityManager } - const indexRepository = em.getRepository(IndexData) - const indexRelationRepository = em.getRepository(IndexRelation) + const indexRepository = em.getRepository(toMikroORMEntity(IndexData)) + const indexRelationRepository = em.getRepository( + toMikroORMEntity(IndexRelation) + ) const { data: data_ } = PostgresProvider.parseData( data,