chore(index): index dml (#10482)

What:
- DML - `autoincrement` property
- Index `type` option (GIN)
- Index module - DML
This commit is contained in:
Carlos R. L. Rodrigues authored and GitHub committed 2024-12-10 10:55:12 +00:00
1 parent 096f1c2a9b
commit 69f4c4f4e0
17 files changed
+471 -204

No files matched your search

+7
View File
@@ -0,0 +1,7 @@
---
"@medusajs/index": patch
"@medusajs/types": patch
"@medusajs/utils": patch
---
chore: index module to DML
+6
View File
@@ -41,6 +41,7 @@ export type KnownDataTypes =
| "enum" | "enum"
| "number" | "number"
| "bigNumber" | "bigNumber"
| "serial"
| "dateTime" | "dateTime"
| "array" | "array"
| "json" | "json"
@@ -310,6 +311,11 @@ export type EntityIndex<
* Conditions to restrict which records are indexed. * Conditions to restrict which records are indexed.
*/ */
where?: Where where?: Where
/**
* The type of the index. (e.g: GIN)
*/
type?: string
} }
export type SimpleQueryValue = string | number | boolean | null export type SimpleQueryValue = string | number | boolean | null
@@ -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<number>()
expect(property.parse("display_id")).toEqual({
fieldName: "display_id",
dataType: {
name: "serial",
options: {},
},
nullable: false,
indexes: [],
relationships: [],
})
})
})
@@ -3736,6 +3736,7 @@ describe("Entity builder", () => {
}, },
group: { group: {
entity: "Group", entity: "Group",
fieldName: "group_id",
name: "group", name: "group",
nullable: false, nullable: false,
persist: false, persist: false,
@@ -4355,6 +4356,7 @@ describe("Entity builder", () => {
}, },
user: { user: {
entity: "User", entity: "User",
fieldName: "user_id",
name: "user", name: "user",
nullable: false, nullable: false,
persist: false, persist: false,
@@ -4363,8 +4365,8 @@ describe("Entity builder", () => {
user_id: { user_id: {
columnType: "text", columnType: "text",
entity: "User", entity: "User",
fieldName: "user_id",
mapToPk: true, mapToPk: true,
fieldName: "user_id",
name: "user_id", name: "user_id",
nullable: false, nullable: false,
onDelete: "cascade", onDelete: "cascade",
@@ -4949,6 +4951,7 @@ describe("Entity builder", () => {
name: "user", name: "user",
reference: "m:1", reference: "m:1",
entity: "User", entity: "User",
fieldName: "user_id",
persist: false, persist: false,
nullable: false, nullable: false,
}, },
@@ -5136,6 +5139,7 @@ describe("Entity builder", () => {
user: { user: {
name: "user", name: "user",
reference: "m:1", reference: "m:1",
fieldName: "user_id",
entity: "User", entity: "User",
persist: false, persist: false,
nullable: true, nullable: true,
@@ -5697,6 +5701,7 @@ describe("Entity builder", () => {
}, },
parent: { parent: {
name: "parent", name: "parent",
fieldName: "parent_id",
reference: "m:1", reference: "m:1",
entity: "User", entity: "User",
persist: false, persist: false,
@@ -7447,39 +7452,37 @@ describe("Entity builder", () => {
}, },
user_id: { user_id: {
name: "user_id", name: "user_id",
reference: "m:1", reference: "scalar",
entity: "User",
columnType: "text", columnType: "text",
mapToPk: true,
fieldName: "user_id", fieldName: "user_id",
getter: false,
setter: false,
nullable: false, nullable: false,
type: "User",
}, },
user: { user: {
reference: "scalar", reference: "m:1",
type: "User", entity: "User",
persist: false, persist: false,
nullable: false, nullable: false,
name: "user", name: "user",
getter: false,
setter: false,
}, },
team_id: { team_id: {
name: "team_id", name: "team_id",
reference: "m:1", reference: "scalar",
entity: "Team",
columnType: "text", columnType: "text",
mapToPk: true,
fieldName: "team_id", fieldName: "team_id",
nullable: false, nullable: false,
getter: false,
setter: false,
type: "Team",
}, },
team: { team: {
reference: "scalar", reference: "m:1",
type: "Team", entity: "Team",
persist: false, persist: false,
nullable: false, nullable: false,
name: "team", name: "team",
getter: false,
setter: false,
}, },
created_at: { created_at: {
reference: "scalar", reference: "scalar",
+32 -3
View File
@@ -13,6 +13,7 @@ import {
DMLSchemaDefaults, DMLSchemaDefaults,
} from "./helpers/entity-builder/create-default-properties" } from "./helpers/entity-builder/create-default-properties"
import { ArrayProperty } from "./properties/array" import { ArrayProperty } from "./properties/array"
import { AutoIncrementProperty } from "./properties/autoincrement"
import { BigNumberProperty } from "./properties/big-number" import { BigNumberProperty } from "./properties/big-number"
import { BooleanProperty } from "./properties/boolean" import { BooleanProperty } from "./properties/boolean"
import { DateTimeProperty } from "./properties/date-time" import { DateTimeProperty } from "./properties/date-time"
@@ -24,8 +25,8 @@ import { TextProperty } from "./properties/text"
import { BelongsTo } from "./relations/belongs-to" import { BelongsTo } from "./relations/belongs-to"
import { HasMany } from "./relations/has-many" import { HasMany } from "./relations/has-many"
import { HasOne } from "./relations/has-one" import { HasOne } from "./relations/has-one"
import { ManyToMany } from "./relations/many-to-many"
import { HasOneWithForeignKey } from "./relations/has-one-fk" import { HasOneWithForeignKey } from "./relations/has-one-fk"
import { ManyToMany } from "./relations/many-to-many"
/** /**
* The implicit properties added by EntityBuilder in every schema * 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 * 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 * 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. * database for this relationship.
*/ */
pivotEntity?: () => DmlEntity<any, any> pivotEntity?: () => DmlEntity<any, any>
/**
* 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() 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. * This method defines an array of strings property.
* *
@@ -4,8 +4,6 @@ import {
PropertyMetadata, PropertyMetadata,
PropertyType, PropertyType,
} from "@medusajs/types" } from "@medusajs/types"
import { MikroOrmBigNumberProperty } from "../../../dal"
import { generateEntityId, isDefined } from "../../../common"
import { import {
ArrayType, ArrayType,
BeforeCreate, BeforeCreate,
@@ -14,7 +12,10 @@ import {
PrimaryKey, PrimaryKey,
Property, Property,
Utils, Utils,
t as mikroOrmType,
} from "@mikro-orm/core" } from "@mikro-orm/core"
import { generateEntityId, isDefined } from "../../../common"
import { MikroOrmBigNumberProperty } from "../../../dal"
import { PrimaryKeyModifier } from "../../properties/primary-key" import { PrimaryKeyModifier } from "../../properties/primary-key"
import { applyEntityIndexes } from "../mikro-orm/apply-indexes" import { applyEntityIndexes } from "../mikro-orm/apply-indexes"
@@ -32,6 +33,7 @@ const COLUMN_TYPES: {
dateTime: "timestamptz", dateTime: "timestamptz",
number: "integer", number: "integer",
bigNumber: "numeric", bigNumber: "numeric",
serial: "number",
text: "text", text: "text",
json: "jsonb", json: "jsonb",
array: "array", array: "array",
@@ -51,6 +53,7 @@ const PROPERTY_TYPES: {
dateTime: "date", dateTime: "date",
number: "number", number: "number",
bigNumber: "number", bigNumber: "number",
serial: "number",
text: "string", text: "string",
json: "any", json: "any",
array: "string[]", array: "string[]",
@@ -202,14 +205,11 @@ export function defineProperty(
* Defining an id property * Defining an id property
*/ */
if (field.dataType.name === "id") { if (field.dataType.name === "id") {
const IdDecorator = PrimaryKeyModifier.isPrimaryKeyModifier(property) const Prop = PrimaryKeyModifier.isPrimaryKeyModifier(property)
? PrimaryKey({ ? PrimaryKey
columnType: "text", : Property
type: "string",
nullable: false, const IdDecorator = Prop({
fieldName: field.fieldName,
})
: Property({
columnType: "text", columnType: "text",
type: "string", type: "string",
nullable: false, nullable: false,
@@ -259,6 +259,24 @@ export function defineProperty(
return 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 * Define rest of properties
*/ */
@@ -21,10 +21,10 @@ import { camelToSnakeCase, pluralize } from "../../../common"
import { DmlEntity } from "../../entity" import { DmlEntity } from "../../entity"
import { HasMany } from "../../relations/has-many" import { HasMany } from "../../relations/has-many"
import { HasOne } from "../../relations/has-one" import { HasOne } from "../../relations/has-one"
import { HasOneWithForeignKey } from "../../relations/has-one-fk"
import { ManyToMany as DmlManyToMany } from "../../relations/many-to-many" import { ManyToMany as DmlManyToMany } from "../../relations/many-to-many"
import { applyEntityIndexes } from "../mikro-orm/apply-indexes" import { applyEntityIndexes } from "../mikro-orm/apply-indexes"
import { parseEntityName } from "./parse-entity-name" import { parseEntityName } from "./parse-entity-name"
import { HasOneWithForeignKey } from "../../relations/has-one-fk"
type Context = { type Context = {
MANY_TO_MANY_TRACKED_RELATIONS: Record<string, boolean> MANY_TO_MANY_TRACKED_RELATIONS: Record<string, boolean>
@@ -329,6 +329,20 @@ export function defineBelongsToRelationship(
) { ) {
const foreignKeyName = camelToSnakeCase(`${relationship.name}Id`) const foreignKeyName = camelToSnakeCase(`${relationship.name}Id`)
if (DmlManyToMany.isManyToMany(otherSideRelation)) {
Property({
type: relatedModelName,
columnType: "text",
fieldName: foreignKeyName,
nullable: relationship.nullable,
})(MikroORMEntity.prototype, foreignKeyName)
ManyToOne({
entity: relatedModelName,
nullable: relationship.nullable,
persist: false,
})(MikroORMEntity.prototype, relationship.name)
} else {
ManyToOne({ ManyToOne({
entity: relatedModelName, entity: relatedModelName,
columnType: "text", columnType: "text",
@@ -338,16 +352,9 @@ export function defineBelongsToRelationship(
onDelete: shouldCascade ? "cascade" : undefined, onDelete: shouldCascade ? "cascade" : undefined,
})(MikroORMEntity.prototype, foreignKeyName) })(MikroORMEntity.prototype, foreignKeyName)
if (DmlManyToMany.isManyToMany(otherSideRelation)) {
Property({
type: relatedModelName,
persist: false,
nullable: relationship.nullable,
})(MikroORMEntity.prototype, relationship.name)
} else {
// HasMany case
ManyToOne({ ManyToOne({
entity: relatedModelName, entity: relatedModelName,
fieldName: foreignKeyName,
persist: false, persist: false,
nullable: relationship.nullable, nullable: relationship.nullable,
})(MikroORMEntity.prototype, relationship.name) })(MikroORMEntity.prototype, relationship.name)
@@ -446,9 +453,30 @@ export function defineManyToManyRelationship(
let inversedBy: undefined | string let inversedBy: undefined | string
let pivotEntityName: undefined | string let pivotEntityName: undefined | string
let pivotTableName: 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
)
? relationship.options.inverseJoinColumn
: undefined
const inverseJoinColumns: undefined | string[] = Array.isArray(
relationship.options.inverseJoinColumn
)
? relationship.options.inverseJoinColumn
: undefined
const [otherSideRelationshipProperty, otherSideRelationship] = const [otherSideRelationshipProperty, otherSideRelationship] =
retrieveOtherSideRelationshipManyToMany({ retrieveOtherSideRelationshipManyToMany({
@@ -540,7 +568,9 @@ export function defineManyToManyRelationship(
const configuresRelationship = !!( const configuresRelationship = !!(
joinColumn || joinColumn ||
joinColumns ||
inverseJoinColumn || inverseJoinColumn ||
inverseJoinColumns ||
relationship.options.pivotTable relationship.options.pivotTable
) )
const relatedOneConfiguresRelationship = !!( const relatedOneConfiguresRelationship = !!(
@@ -586,7 +616,16 @@ export function defineManyToManyRelationship(
const mappedByPropValue = const mappedByPropValue =
mappedBy ?? inversedBy ?? otherSideRelationshipProperty 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, owner: isOwner,
entity: relatedModelName, entity: relatedModelName,
...(pivotTableName ...(pivotTableName
@@ -598,9 +637,11 @@ export function defineManyToManyRelationship(
: {}), : {}),
...(pivotEntityName ? { pivotEntity: pivotEntityName } : {}), ...(pivotEntityName ? { pivotEntity: pivotEntityName } : {}),
...({ [mappedByProp]: mappedByPropValue } as any), ...({ [mappedByProp]: mappedByPropValue } as any),
...(joinColumn ? { joinColumn } : {}), [joinColumnProp]: joinColumn ?? joinColumns,
...(inverseJoinColumn ? { inverseJoinColumn } : {}), [inverseJoinColumnProp]: inverseJoinColumn ?? inverseJoinColumns,
})(MikroORMEntity.prototype, relationship.name) }
ManyToMany(manytoManyOptions)(MikroORMEntity.prototype, relationship.name)
} }
/** /**
@@ -48,6 +48,7 @@ export function applyEntityIndexes(
columns: index.on as string[], columns: index.on as string[],
unique: index.unique, unique: index.unique,
where: index.where, where: index.where,
type: index.type,
}) })
entityIndexStatement.MikroORMIndex()(MikroORMEntity) entityIndexStatement.MikroORMIndex()(MikroORMEntity)
@@ -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<number> {
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<number, AutoIncrementProperty>(this)
}
constructor(options?: { primaryKey?: boolean }) {
super()
this.dataType = {
name: "serial",
options: { ...options },
}
}
}
@@ -1,4 +1,5 @@
export * from "./array" export * from "./array"
export * from "./autoincrement"
export * from "./base" export * from "./base"
export * from "./big-number" export * from "./big-number"
export * from "./boolean" export * from "./boolean"
@@ -10,11 +10,12 @@ import {
ContainerRegistrationKeys, ContainerRegistrationKeys,
ModuleRegistrationName, ModuleRegistrationName,
Modules, Modules,
toMikroORMEntity,
} from "@medusajs/framework/utils" } from "@medusajs/framework/utils"
import { initDb, TestDatabaseUtils } from "@medusajs/test-utils"
import { EntityManager } from "@mikro-orm/postgresql" import { EntityManager } from "@mikro-orm/postgresql"
import { IndexData, IndexRelation } from "@models" import { IndexData, IndexRelation } from "@models"
import { asValue } from "awilix" import { asValue } from "awilix"
import { initDb, TestDatabaseUtils } from "@medusajs/test-utils"
import * as path from "path" import * as path from "path"
import { EventBusServiceMock } from "../__fixtures__" import { EventBusServiceMock } from "../__fixtures__"
import { dbName } from "../__fixtures__/medusa-config" import { dbName } from "../__fixtures__/medusa-config"
@@ -254,7 +255,10 @@ describe("IndexModuleService", function () {
* Validate all index entries and index relation entries * 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) => { const productIndexEntries = indexEntries.filter((entry) => {
return entry.name === "Product" return entry.name === "Product"
@@ -412,7 +416,10 @@ describe("IndexModuleService", function () {
* Validate all index entries and index relation entries * 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) => { const productIndexEntries = indexEntries.filter((entry) => {
return entry.name === "Product" return entry.name === "Product"
@@ -596,7 +603,10 @@ describe("IndexModuleService", function () {
afterEach(afterEach_) afterEach(afterEach_)
it("should update the corresponding index entries", async () => { 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) expect(updatedIndexEntries).toHaveLength(2)
@@ -710,8 +720,14 @@ describe("IndexModuleService", function () {
afterEach(afterEach_) afterEach(afterEach_)
it("should consume all deleted events and delete the index entries", async () => { it("should consume all deleted events and delete the index entries", async () => {
const indexEntries = await manager.find(IndexData, {}) const indexEntries = await manager.find(toMikroORMEntity(IndexData), {})
const indexRelationEntries = await manager.find(IndexRelation, {}) const indexRelationEntries = await manager.find(
toMikroORMEntity(IndexRelation),
{},
{
populate: ["parent", "child"],
}
)
expect(indexEntries).toHaveLength(3) expect(indexEntries).toHaveLength(3)
expect(indexRelationEntries).toHaveLength(2) expect(indexRelationEntries).toHaveLength(2)
@@ -1,5 +1,7 @@
{ {
"namespaces": ["public"], "namespaces": [
"public"
],
"name": "public", "name": "public",
"tables": [ "tables": [
{ {
@@ -31,36 +33,81 @@
"nullable": false, "nullable": false,
"default": "'{}'", "default": "'{}'",
"mappedType": "json" "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", "name": "index_data",
"schema": "public", "schema": "public",
"indexes": [ "indexes": [
{ {
"columnNames": ["id"], "keyName": "IDX_index_data_deleted_at",
"composite": false, "columnNames": [],
"keyName": "IDX_index_data_id",
"primary": false,
"unique": false
},
{
"columnNames": ["name"],
"composite": false,
"keyName": "IDX_index_data_name",
"primary": false,
"unique": false
},
{
"keyName": "IDX_index_data_gin",
"columnNames": ["data"],
"composite": false, "composite": false,
"primary": false, "primary": false,
"unique": false, "unique": false,
"type": "GIN" "expression": "CREATE INDEX IF NOT EXISTS \"IDX_index_data_deleted_at\" ON \"index_data\" (deleted_at) WHERE deleted_at IS NULL"
},
{
"keyName": "IDX_index_data_gin",
"columnNames": [],
"composite": false,
"primary": 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_id",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"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", "keyName": "index_data_pkey",
"columnNames": ["id", "name"], "columnNames": [
"id",
"name"
],
"composite": true, "composite": true,
"primary": true, "primary": true,
"unique": true "unique": true
@@ -73,12 +120,12 @@
"columns": { "columns": {
"id": { "id": {
"name": "id", "name": "id",
"type": "text", "type": "number",
"unsigned": true, "unsigned": true,
"autoincrement": true, "autoincrement": true,
"primary": false, "primary": true,
"nullable": false, "nullable": false,
"mappedType": "text" "mappedType": "integer"
}, },
"pivot": { "pivot": {
"name": "pivot", "name": "pivot",
@@ -89,15 +136,6 @@
"nullable": false, "nullable": false,
"mappedType": "text" "mappedType": "text"
}, },
"parent_id": {
"name": "parent_id",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
},
"parent_name": { "parent_name": {
"name": "parent_name", "name": "parent_name",
"type": "text", "type": "text",
@@ -107,6 +145,24 @@
"nullable": false, "nullable": false,
"mappedType": "text" "mappedType": "text"
}, },
"child_name": {
"name": "child_name",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
},
"parent_id": {
"name": "parent_id",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
},
"child_id": { "child_id": {
"name": "child_id", "name": "child_id",
"type": "text", "type": "text",
@@ -116,30 +172,72 @@
"nullable": false, "nullable": false,
"mappedType": "text" "mappedType": "text"
}, },
"child_name": { "created_at": {
"name": "child_name", "name": "created_at",
"type": "text", "type": "timestamptz",
"unsigned": false, "unsigned": false,
"autoincrement": false, "autoincrement": false,
"primary": false, "primary": false,
"nullable": false, "nullable": false,
"mappedType": "text" "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", "name": "index_relation",
"schema": "public", "schema": "public",
"indexes": [ "indexes": [
{ {
"keyName": "IDX_index_relation_child_id", "keyName": "IDX_index_relation_parent_id",
"columnNames": ["child_id"], "columnNames": [],
"composite": false, "composite": false,
"primary": false, "primary": false,
"unique": 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": [],
"composite": false,
"primary": 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", "keyName": "index_relation_pkey",
"columnNames": ["id", "pivot"], "columnNames": [
"composite": true, "id"
],
"composite": false,
"primary": true, "primary": true,
"unique": true "unique": true
} }
@@ -0,0 +1,35 @@
import { Migration } from "@mikro-orm/migrations"
export class Migration20241209173313 extends Migration {
async up(): Promise<void> {
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<void> {
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";
`)
}
}
+32 -42
View File
@@ -1,45 +1,35 @@
import { import { model } from "@medusajs/framework/utils"
Cascade, import IndexRelation from "./index-relation"
Collection,
Entity,
Index,
ManyToMany,
OptionalProps,
PrimaryKey,
PrimaryKeyType,
Property,
} from "@mikro-orm/core"
import { IndexRelation } from "./index-relation"
type OptionalRelations = "parents" const IndexData = model
.define("IndexData", {
@Entity({ id: model.text().primaryKey(),
tableName: "index_data", name: model.text().primaryKey(),
}) data: model.json().default({}),
export class IndexData { parents: model.manyToMany(() => IndexData, {
[OptionalProps]: OptionalRelations mappedBy: "children",
@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<string, unknown>
@ManyToMany({
owner: true,
entity: () => IndexData,
pivotEntity: () => IndexRelation, pivotEntity: () => IndexRelation,
cascade: [Cascade.REMOVE], joinColumn: ["child_id", "child_name"],
inverseJoinColumns: ["parent_id", "parent_name"], inverseJoinColumn: ["parent_id", "parent_name"],
joinColumns: ["child_id", "child_name"], }),
children: model.manyToMany(() => IndexData, {
mappedBy: "parents",
}),
}) })
parents = new Collection<IndexData>(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
@@ -1,64 +1,16 @@
import { import { model } from "@medusajs/framework/utils"
Entity, import IndexData from "./index-data"
Index,
ManyToOne,
OptionalProps,
PrimaryKey,
Property,
Ref,
} from "@mikro-orm/core"
import { IndexData } from "./index-data"
type OptionalRelations = const IndexRelation = model.define("IndexRelation", {
| "parent" id: model.autoincrement().primaryKey(),
| "child" pivot: model.text(),
| "parent_id" parent_name: model.text(),
| "child_id" child_name: model.text(),
| "parent_name" parent: model.belongsTo(() => IndexData, {
| "child_name" mappedBy: "parents",
}),
@Entity({ child: model.belongsTo(() => IndexData, {
tableName: "index_relation", mappedBy: "children",
}),
}) })
@Index({ export default IndexRelation
name: "IDX_index_relation_child_id",
properties: ["child_id"],
})
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<IndexData>
@ManyToOne({
entity: () => IndexData,
onDelete: "cascade",
persist: false,
})
child?: Ref<IndexData>
}
+2 -2
View File
@@ -1,2 +1,2 @@
export { IndexData } from "./index-data" export { default as IndexData } from "./index-data"
export { IndexRelation } from "./index-relation" export { default as IndexRelation } from "./index-relation"
@@ -12,6 +12,7 @@ import {
InjectTransactionManager, InjectTransactionManager,
isDefined, isDefined,
MedusaContext, MedusaContext,
toMikroORMEntity,
} from "@medusajs/framework/utils" } from "@medusajs/framework/utils"
import { EntityManager, SqlEntityManager } from "@mikro-orm/postgresql" import { EntityManager, SqlEntityManager } from "@mikro-orm/postgresql"
import { IndexData, IndexRelation } from "@models" import { IndexData, IndexRelation } from "@models"
@@ -338,8 +339,10 @@ export class PostgresProvider implements IndexTypes.StorageProvider {
const { transactionManager: em } = sharedContext as { const { transactionManager: em } = sharedContext as {
transactionManager: SqlEntityManager transactionManager: SqlEntityManager
} }
const indexRepository = em.getRepository(IndexData) const indexRepository = em.getRepository(toMikroORMEntity(IndexData))
const indexRelationRepository = em.getRepository(IndexRelation) const indexRelationRepository = em.getRepository(
toMikroORMEntity(IndexRelation)
)
const { const {
data: data_, data: data_,
@@ -432,7 +435,7 @@ export class PostgresProvider implements IndexTypes.StorageProvider {
const { transactionManager: em } = sharedContext as { const { transactionManager: em } = sharedContext as {
transactionManager: SqlEntityManager transactionManager: SqlEntityManager
} }
const indexRepository = em.getRepository(IndexData) const indexRepository = em.getRepository(toMikroORMEntity(IndexData))
const { data: data_, entityProperties } = PostgresProvider.parseData( const { data: data_, entityProperties } = PostgresProvider.parseData(
data, data,
@@ -479,8 +482,10 @@ export class PostgresProvider implements IndexTypes.StorageProvider {
const { transactionManager: em } = sharedContext as { const { transactionManager: em } = sharedContext as {
transactionManager: SqlEntityManager transactionManager: SqlEntityManager
} }
const indexRepository = em.getRepository(IndexData) const indexRepository = em.getRepository(toMikroORMEntity(IndexData))
const indexRelationRepository = em.getRepository(IndexRelation) const indexRelationRepository = em.getRepository(
toMikroORMEntity(IndexRelation)
)
const { data: data_ } = PostgresProvider.parseData( const { data: data_ } = PostgresProvider.parseData(
data, data,
@@ -533,8 +538,10 @@ export class PostgresProvider implements IndexTypes.StorageProvider {
const { transactionManager: em } = sharedContext as { const { transactionManager: em } = sharedContext as {
transactionManager: SqlEntityManager transactionManager: SqlEntityManager
} }
const indexRepository = em.getRepository(IndexData) const indexRepository = em.getRepository(toMikroORMEntity(IndexData))
const indexRelationRepository = em.getRepository(IndexRelation) const indexRelationRepository = em.getRepository(
toMikroORMEntity(IndexRelation)
)
const { data: data_, entityProperties } = PostgresProvider.parseData( const { data: data_, entityProperties } = PostgresProvider.parseData(
data, data,
@@ -654,8 +661,10 @@ export class PostgresProvider implements IndexTypes.StorageProvider {
const { transactionManager: em } = sharedContext as { const { transactionManager: em } = sharedContext as {
transactionManager: SqlEntityManager transactionManager: SqlEntityManager
} }
const indexRepository = em.getRepository(IndexData) const indexRepository = em.getRepository(toMikroORMEntity(IndexData))
const indexRelationRepository = em.getRepository(IndexRelation) const indexRelationRepository = em.getRepository(
toMikroORMEntity(IndexRelation)
)
const { data: data_ } = PostgresProvider.parseData( const { data: data_ } = PostgresProvider.parseData(
data, data,