feat: Correctly define all product module models and SQL migration script (#6906)

The only thing remaining is modifying `upsertWithReplace` to handle many-to-many constraints correctly and not cascade updates to them. This is something that we should do separately though.
This commit is contained in:
Stevche Radevski authored and GitHub committed 2024-04-02 12:27:12 +00:00
1 parent 7fe164bc1d
commit 3dee91426e
13 files changed
+257 -294

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
---
"@medusajs/product": patch
---
Correctly define all product module models and SQL migration script
@@ -126,15 +126,6 @@
"primary": false, "primary": false,
"unique": false "unique": false
}, },
{
"keyName": "IDX_product_category_handle",
"columnNames": [
"handle"
],
"composite": false,
"primary": false,
"unique": true
},
{ {
"keyName": "product_category_pkey", "keyName": "product_category_pkey",
"columnNames": [ "columnNames": [
@@ -157,7 +148,7 @@
"id" "id"
], ],
"referencedTableName": "public.product_category", "referencedTableName": "public.product_category",
"deleteRule": "set null", "deleteRule": "cascade",
"updateRule": "cascade" "updateRule": "cascade"
} }
} }
@@ -245,15 +236,6 @@
"primary": false, "primary": false,
"unique": false "unique": false
}, },
{
"keyName": "IDX_product_collection_handle_unique",
"columnNames": [
"handle"
],
"composite": false,
"primary": false,
"unique": true
},
{ {
"keyName": "product_collection_pkey", "keyName": "product_collection_pkey",
"columnNames": [ "columnNames": [
@@ -790,15 +772,6 @@
"primary": false, "primary": false,
"unique": false "unique": false
}, },
{
"keyName": "IDX_product_handle_unique",
"columnNames": [
"handle"
],
"composite": false,
"primary": false,
"unique": true
},
{ {
"keyName": "product_pkey", "keyName": "product_pkey",
"columnNames": [ "columnNames": [
@@ -1503,42 +1476,6 @@
"primary": false, "primary": false,
"unique": false "unique": false
}, },
{
"keyName": "IDX_product_variant_sku_unique",
"columnNames": [
"sku"
],
"composite": false,
"primary": false,
"unique": true
},
{
"keyName": "IDX_product_variant_barcode_unique",
"columnNames": [
"barcode"
],
"composite": false,
"primary": false,
"unique": true
},
{
"keyName": "IDX_product_variant_ean_unique",
"columnNames": [
"ean"
],
"composite": false,
"primary": false,
"unique": true
},
{
"keyName": "IDX_product_variant_upc_unique",
"columnNames": [
"upc"
],
"composite": false,
"primary": false,
"unique": true
},
{ {
"keyName": "product_variant_pkey", "keyName": "product_variant_pkey",
"columnNames": [ "columnNames": [
@@ -1662,7 +1599,7 @@
"id" "id"
], ],
"referencedTableName": "public.product_option_value", "referencedTableName": "public.product_option_value",
"deleteRule": "set null", "deleteRule": "cascade",
"updateRule": "cascade" "updateRule": "cascade"
}, },
"product_variant_option_variant_id_foreign": { "product_variant_option_variant_id_foreign": {
@@ -1675,7 +1612,7 @@
"id" "id"
], ],
"referencedTableName": "public.product_variant", "referencedTableName": "public.product_variant",
"deleteRule": "set null", "deleteRule": "cascade",
"updateRule": "cascade" "updateRule": "cascade"
} }
} }
@@ -2,7 +2,6 @@ import { Migration } from '@mikro-orm/migrations';
export class InitialSetup20240315083440 extends Migration { export class InitialSetup20240315083440 extends Migration {
async up(): Promise<void> { async up(): Promise<void> {
// TODO: These migrations that get generated don't even reflect the models, write by hand.
const productTables = await this.execute( const productTables = await this.execute(
"select * from information_schema.tables where table_name = 'product' and table_schema = 'public'" "select * from information_schema.tables where table_name = 'product' and table_schema = 'public'"
) )
@@ -15,78 +14,88 @@ export class InitialSetup20240315083440 extends Migration {
this.addSql( this.addSql(
`alter table "product_variant" alter column "inventory_quantity" drop not null;` `alter table "product_variant" alter column "inventory_quantity" drop not null;`
) )
this.addSql(
`alter table "product_category" add column "deleted_at" timestamptz null;`
)
} }
this.addSql('create table if not exists "product_category" ("id" text not null, "name" text not null, "description" text not null default \'\', "handle" text not null, "mpath" text not null, "is_active" boolean not null default false, "is_internal" boolean not null default false, "rank" numeric not null default 0, "parent_category_id" text null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), constraint "product_category_pkey" primary key ("id"));'); /* --- ENTITY TABLES AND INDICES --- */
this.addSql('create index if not exists "IDX_product_category_path" on "product_category" ("mpath");');
// TODO: Re-enable when we run the migration from v1
// this.addSql('alter table if exists "product_category" add constraint "IDX_product_category_handle" unique ("handle");');
this.addSql('create table if not exists "product_collection" ("id" text not null, "title" text not null, "handle" text not null, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "product_collection_pkey" primary key ("id"));');
this.addSql('create index if not exists "IDX_product_collection_deleted_at" on "product_collection" ("deleted_at");');
this.addSql('alter table if exists "product_collection" add constraint "IDX_product_collection_handle_unique" unique ("handle");');
this.addSql('create table if not exists "image" ("id" text not null, "url" text not null, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "image_pkey" primary key ("id"));');
this.addSql('create index if not exists "IDX_product_image_url" on "image" ("url");');
this.addSql('create index if not exists "IDX_product_image_deleted_at" on "image" ("deleted_at");');
this.addSql('create table if not exists "product_tag" ("id" text not null, "value" text not null, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "product_tag_pkey" primary key ("id"));');
this.addSql('create index if not exists "IDX_product_tag_deleted_at" on "product_tag" ("deleted_at");');
this.addSql('create table if not exists "product_type" ("id" text not null, "value" text not null, "metadata" json null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "product_type_pkey" primary key ("id"));');
this.addSql('create index if not exists "IDX_product_type_deleted_at" on "product_type" ("deleted_at");');
this.addSql('create table if not exists "product" ("id" text not null, "title" text not null, "handle" text not null, "subtitle" text null, "description" text null, "is_giftcard" boolean not null default false, "status" text check ("status" in (\'draft\', \'proposed\', \'published\', \'rejected\')) not null, "thumbnail" text null, "weight" text null, "length" text null, "height" text null, "width" text null, "origin_country" text null, "hs_code" text null, "mid_code" text null, "material" text null, "collection_id" text null, "type_id" text null, "discountable" boolean not null default true, "external_id" text null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, "metadata" jsonb null, constraint "product_pkey" primary key ("id"));'); this.addSql('create table if not exists "product" ("id" text not null, "title" text not null, "handle" text not null, "subtitle" text null, "description" text null, "is_giftcard" boolean not null default false, "status" text check ("status" in (\'draft\', \'proposed\', \'published\', \'rejected\')) not null, "thumbnail" text null, "weight" text null, "length" text null, "height" text null, "width" text null, "origin_country" text null, "hs_code" text null, "mid_code" text null, "material" text null, "collection_id" text null, "type_id" text null, "discountable" boolean not null default true, "external_id" text null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, "metadata" jsonb null, constraint "product_pkey" primary key ("id"));');
this.addSql('create index if not exists "IDX_product_type_id" on "product" ("type_id");'); this.addSql('create unique index if not exists "IDX_product_handle_unique" on "product" (handle) where deleted_at is null;')
this.addSql('create index if not exists "IDX_product_type_id" on "product" ("type_id") where deleted_at is null;');
this.addSql('create index if not exists "IDX_product_collection_id" on "product" ("collection_id") where deleted_at is null;');
this.addSql('create index if not exists "IDX_product_deleted_at" on "product" ("deleted_at");'); this.addSql('create index if not exists "IDX_product_deleted_at" on "product" ("deleted_at");');
this.addSql('alter table if exists "product" add constraint "IDX_product_handle_unique" unique ("handle");');
this.addSql('create table if not exists "product_variant" ("id" text not null, "title" text not null, "sku" text null, "barcode" text null, "ean" text null, "upc" text null, "inventory_quantity" numeric not null default 100, "allow_backorder" boolean not null default false, "manage_inventory" boolean not null default true, "hs_code" text null, "origin_country" text null, "mid_code" text null, "material" text null, "weight" numeric null, "length" numeric null, "height" numeric null, "width" numeric null, "metadata" jsonb null, "variant_rank" numeric null default 0, "product_id" text null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "product_variant_pkey" primary key ("id"));');
this.addSql('create unique index if not exists "IDX_product_variant_ean_unique" on "product_variant" (ean) where deleted_at is null;')
this.addSql('create unique index if not exists "IDX_product_variant_upc_unique" on "product_variant" (upc) where deleted_at is null;')
this.addSql('create unique index if not exists "IDX_product_variant_sku_unique" on "product_variant" (sku) where deleted_at is null;')
this.addSql('create unique index if not exists "IDX_product_variant_barcode_unique" on "product_variant" (barcode) where deleted_at is null;')
this.addSql('create index if not exists "IDX_product_variant_product_id" on "product_variant" ("product_id") where deleted_at is null;');
this.addSql('create index if not exists "IDX_product_variant_deleted_at" on "product_variant" ("deleted_at");');
this.addSql('create table if not exists "product_option" ("id" text not null, "title" text not null, "product_id" text null, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "product_option_pkey" primary key ("id"));'); this.addSql('create table if not exists "product_option" ("id" text not null, "title" text not null, "product_id" text null, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "product_option_pkey" primary key ("id"));');
this.addSql('create unique index if not exists "IDX_option_product_id_title_unique" on "product_option" (product_id, title) where deleted_at is null;')
this.addSql('create index if not exists "IDX_product_option_deleted_at" on "product_option" ("deleted_at");'); this.addSql('create index if not exists "IDX_product_option_deleted_at" on "product_option" ("deleted_at");');
this.addSql('create table if not exists "product_option_value" ("id" text not null, "value" text not null, "option_id" text null, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "product_option_value_pkey" primary key ("id"));'); this.addSql('create table if not exists "product_option_value" ("id" text not null, "value" text not null, "option_id" text null, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "product_option_value_pkey" primary key ("id"));');
this.addSql('create index if not exists "IDX_product_option_value_option_id" on "product_option_value" ("option_id");'); this.addSql('create unique index if not exists "IDX_option_value_option_id_unique" on "product_option_value" (option_id, value) where deleted_at is null;')
this.addSql('create index if not exists "IDX_product_option_value_deleted_at" on "product_option_value" ("deleted_at");'); this.addSql('create index if not exists "IDX_product_option_value_deleted_at" on "product_option_value" ("deleted_at");');
this.addSql('create table if not exists "product_tags" ("product_id" text not null, "product_tag_id" text not null, constraint "product_tags_pkey" primary key ("product_id", "product_tag_id"));');
this.addSql('create table if not exists "product_images" ("product_id" text not null, "image_id" text not null, constraint "product_images_pkey" primary key ("product_id", "image_id"));');
this.addSql('create table if not exists "product_category_product" ("product_id" text not null, "product_category_id" text not null, constraint "product_category_product_pkey" primary key ("product_id", "product_category_id"));');
this.addSql('create table if not exists "product_variant" ("id" text not null, "title" text not null, "sku" text null, "barcode" text null, "ean" text null, "upc" text null, "inventory_quantity" numeric not null default 100, "allow_backorder" boolean not null default false, "manage_inventory" boolean not null default true, "hs_code" text null, "origin_country" text null, "mid_code" text null, "material" text null, "weight" numeric null, "length" numeric null, "height" numeric null, "width" numeric null, "metadata" jsonb null, "variant_rank" numeric null default 0, "product_id" text null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "product_variant_pkey" primary key ("id"));');
this.addSql('create index if not exists "IDX_product_variant_product_id" on "product_variant" ("product_id");');
this.addSql('create index if not exists "IDX_product_variant_deleted_at" on "product_variant" ("deleted_at");');
this.addSql('alter table if exists "product_variant" add constraint "IDX_product_variant_sku_unique" unique ("sku");');
this.addSql('alter table if exists "product_variant" add constraint "IDX_product_variant_barcode_unique" unique ("barcode");');
this.addSql('alter table if exists "product_variant" add constraint "IDX_product_variant_ean_unique" unique ("ean");');
this.addSql('alter table if exists "product_variant" add constraint "IDX_product_variant_upc_unique" unique ("upc");');
this.addSql('create table if not exists "product_variant_option" ("id" text not null, "option_value_id" text null, "variant_id" text null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "product_variant_option_pkey" primary key ("id"));'); this.addSql('create table if not exists "product_variant_option" ("id" text not null, "option_value_id" text null, "variant_id" text null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "product_variant_option_pkey" primary key ("id"));');
this.addSql('create unique index if not exists "IDX_variant_option_option_value_unique" on "product_variant_option" (variant_id, option_value_id) where deleted_at is null;')
this.addSql('create index if not exists "IDX_product_variant_option_deleted_at" on "product_variant_option" ("deleted_at");'); this.addSql('create index if not exists "IDX_product_variant_option_deleted_at" on "product_variant_option" ("deleted_at");');
this.addSql('alter table if exists "product_category" add constraint "product_category_parent_category_id_foreign" foreign key ("parent_category_id") references "product_category" ("id") on update cascade on delete set null;'); this.addSql('create table if not exists "image" ("id" text not null, "url" text not null, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "image_pkey" primary key ("id"));');
this.addSql('create index if not exists "IDX_product_image_url" on "image" ("url") where deleted_at is null;');
this.addSql('create index if not exists "IDX_product_image_deleted_at" on "image" ("deleted_at");');
this.addSql('create table if not exists "product_tag" ("id" text not null, "value" text not null, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "product_tag_pkey" primary key ("id"));');
// TODO: We need to modify upsertWithReplace to handle unique constraints
// this.addSql('create unique index if not exists "IDX_tag_value_unique" on "product_tag" (value) where deleted_at is null;')
this.addSql('create index if not exists "IDX_product_tag_deleted_at" on "product_tag" ("deleted_at");');
this.addSql('create table if not exists "product_type" ("id" text not null, "value" text not null, "metadata" json null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "product_type_pkey" primary key ("id"));');
this.addSql('create unique index if not exists "IDX_type_value_unique" on "product_type" (value) where deleted_at is null;')
this.addSql('create index if not exists "IDX_product_type_deleted_at" on "product_type" ("deleted_at");');
this.addSql('create table if not exists "product_collection" ("id" text not null, "title" text not null, "handle" text not null, "metadata" jsonb null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "product_collection_pkey" primary key ("id"));');
this.addSql('create unique index if not exists "IDX_collection_handle_unique" on "product_collection" (handle) where deleted_at is null;')
this.addSql('create index if not exists "IDX_product_collection_deleted_at" on "product_collection" ("deleted_at");');
this.addSql('create table if not exists "product_category" ("id" text not null, "name" text not null, "description" text not null default \'\', "handle" text not null, "mpath" text not null, "is_active" boolean not null default false, "is_internal" boolean not null default false, "rank" numeric not null default 0, "parent_category_id" text null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "product_category_pkey" primary key ("id"));');
this.addSql('create unique index if not exists "IDX_category_handle_unique" on "product_category" (handle) where deleted_at is null;')
this.addSql('create index if not exists "IDX_product_category_path" on "product_category" ("mpath") where deleted_at is null;');
this.addSql('create index if not exists "IDX_product_category_deleted_at" on "product_collection" ("deleted_at");');
/* --- PIVOT TABLES --- */
this.addSql('create table if not exists "product_tags" ("product_id" text not null, "product_tag_id" text not null, constraint "product_tags_pkey" primary key ("product_id", "product_tag_id"));');
this.addSql('create table if not exists "product_images" ("product_id" text not null, "image_id" text not null, constraint "product_images_pkey" primary key ("product_id", "image_id"));');
this.addSql('create table if not exists "product_category_product" ("product_id" text not null, "product_category_id" text not null, constraint "product_category_product_pkey" primary key ("product_id", "product_category_id"));');
/* --- FOREIGN KEYS AND CONSTRAINTS --- */
this.addSql('alter table if exists "product" add constraint "product_collection_id_foreign" foreign key ("collection_id") references "product_collection" ("id") on update cascade on delete set null;'); this.addSql('alter table if exists "product" add constraint "product_collection_id_foreign" foreign key ("collection_id") references "product_collection" ("id") on update cascade on delete set null;');
this.addSql('alter table if exists "product" add constraint "product_type_id_foreign" foreign key ("type_id") references "product_type" ("id") on update cascade on delete set null;'); this.addSql('alter table if exists "product" add constraint "product_type_id_foreign" foreign key ("type_id") references "product_type" ("id") on update cascade on delete set null;');
this.addSql('alter table if exists "product_variant" add constraint "product_variant_product_id_foreign" foreign key ("product_id") references "product" ("id") on update cascade on delete cascade;');
this.addSql('alter table if exists "product_option" add constraint "product_option_product_id_foreign" foreign key ("product_id") references "product" ("id") on update cascade on delete cascade;'); this.addSql('alter table if exists "product_option" add constraint "product_option_product_id_foreign" foreign key ("product_id") references "product" ("id") on update cascade on delete cascade;');
this.addSql('alter table if exists "product_option_value" add constraint "product_option_value_option_id_foreign" foreign key ("option_id") references "product_option" ("id") on update cascade on delete cascade;'); this.addSql('alter table if exists "product_option_value" add constraint "product_option_value_option_id_foreign" foreign key ("option_id") references "product_option" ("id") on update cascade on delete cascade;');
this.addSql('alter table if exists "product_tags" add constraint "product_tags_product_id_foreign" foreign key ("product_id") references "product" ("id") on update cascade on delete cascade;'); this.addSql('alter table if exists "product_variant_option" add constraint "product_variant_option_option_value_id_foreign" foreign key ("option_value_id") references "product_option_value" ("id") on update cascade on delete cascade;');
this.addSql('alter table if exists "product_tags" add constraint "product_tags_product_tag_id_foreign" foreign key ("product_tag_id") references "product_tag" ("id") on update cascade on delete cascade;'); this.addSql('alter table if exists "product_variant_option" add constraint "product_variant_option_variant_id_foreign" foreign key ("variant_id") references "product_variant" ("id") on update cascade on delete cascade;');
this.addSql('alter table if exists "product_images" add constraint "product_images_product_id_foreign" foreign key ("product_id") references "product" ("id") on update cascade on delete cascade;'); this.addSql('alter table if exists "product_images" add constraint "product_images_product_id_foreign" foreign key ("product_id") references "product" ("id") on update cascade on delete cascade;');
this.addSql('alter table if exists "product_images" add constraint "product_images_image_id_foreign" foreign key ("image_id") references "image" ("id") on update cascade on delete cascade;'); this.addSql('alter table if exists "product_images" add constraint "product_images_image_id_foreign" foreign key ("image_id") references "image" ("id") on update cascade on delete cascade;');
this.addSql('alter table if exists "product_tags" add constraint "product_tags_product_id_foreign" foreign key ("product_id") references "product" ("id") on update cascade on delete cascade;');
this.addSql('alter table if exists "product_tags" add constraint "product_tags_product_tag_id_foreign" foreign key ("product_tag_id") references "product_tag" ("id") on update cascade on delete cascade;');
this.addSql('alter table if exists "product_category_product" add constraint "product_category_product_product_id_foreign" foreign key ("product_id") references "product" ("id") on update cascade on delete cascade;'); this.addSql('alter table if exists "product_category_product" add constraint "product_category_product_product_id_foreign" foreign key ("product_id") references "product" ("id") on update cascade on delete cascade;');
this.addSql('alter table if exists "product_category_product" add constraint "product_category_product_product_category_id_foreign" foreign key ("product_category_id") references "product_category" ("id") on update cascade on delete cascade;'); this.addSql('alter table if exists "product_category_product" add constraint "product_category_product_product_category_id_foreign" foreign key ("product_category_id") references "product_category" ("id") on update cascade on delete cascade;');
this.addSql('alter table if exists "product_variant" add constraint "product_variant_product_id_foreign" foreign key ("product_id") references "product" ("id") on update cascade on delete cascade;'); this.addSql('alter table if exists "product_category" add constraint "product_category_parent_category_id_foreign" foreign key ("parent_category_id") references "product_category" ("id") on update cascade on delete cascade;');
this.addSql('alter table if exists "product_variant_option" add constraint "product_variant_option_option_value_id_foreign" foreign key ("option_value_id") references "product_option_value" ("id") on update cascade on delete set null;');
this.addSql('alter table if exists "product_variant_option" add constraint "product_variant_option_variant_id_foreign" foreign key ("variant_id") references "product_variant" ("id") on update cascade on delete set null;');
} }
} }
+32 -15
View File
@@ -1,29 +1,49 @@
import { generateEntityId, kebabCase } from "@medusajs/utils" import {
DALUtils,
createPsqlIndexStatementHelper,
generateEntityId,
kebabCase,
} from "@medusajs/utils"
import { import {
BeforeCreate, BeforeCreate,
Collection, Collection,
Entity, Entity,
EventArgs, EventArgs,
Filter,
Index, Index,
ManyToMany, ManyToMany,
ManyToOne, ManyToOne,
OnInit, OnInit,
OneToMany, OneToMany,
OptionalProps,
PrimaryKey, PrimaryKey,
Property, Property,
Unique,
} from "@mikro-orm/core" } from "@mikro-orm/core"
import { DAL } from "@medusajs/types"
import Product from "./product" import Product from "./product"
type OptionalFields = DAL.SoftDeletableEntityDateColumns const categoryHandleIndexName = "IDX_category_handle_unique"
const categoryHandleIndexStatement = createPsqlIndexStatementHelper({
name: categoryHandleIndexName,
tableName: "product_category",
columns: ["handle"],
unique: true,
where: "deleted_at IS NULL",
})
const categoryMpathIndexName = "IDX_product_category_path"
const categoryMpathIndexStatement = createPsqlIndexStatementHelper({
name: categoryMpathIndexName,
tableName: "product_category",
columns: ["mpath"],
unique: false,
where: "deleted_at IS NULL",
})
categoryMpathIndexStatement.MikroORMIndex()
categoryHandleIndexStatement.MikroORMIndex()
@Entity({ tableName: "product_category" }) @Entity({ tableName: "product_category" })
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
class ProductCategory { class ProductCategory {
[OptionalProps]?: OptionalFields
@PrimaryKey({ columnType: "text" }) @PrimaryKey({ columnType: "text" })
id!: string id!: string
@@ -33,17 +53,9 @@ class ProductCategory {
@Property({ columnType: "text", default: "", nullable: false }) @Property({ columnType: "text", default: "", nullable: false })
description?: string description?: string
@Unique({
name: "IDX_product_category_handle",
properties: ["handle"],
})
@Property({ columnType: "text", nullable: false }) @Property({ columnType: "text", nullable: false })
handle?: string handle?: string
@Index({
name: "IDX_product_category_path",
properties: ["mpath"],
})
@Property({ columnType: "text", nullable: false }) @Property({ columnType: "text", nullable: false })
mpath?: string mpath?: string
@@ -61,6 +73,7 @@ class ProductCategory {
fieldName: "parent_category_id", fieldName: "parent_category_id",
nullable: true, nullable: true,
mapToPk: true, mapToPk: true,
onDelete: "cascade",
}) })
parent_category_id?: string | null parent_category_id?: string | null
@@ -88,6 +101,10 @@ class ProductCategory {
}) })
updated_at?: Date updated_at?: Date
@Index({ name: "IDX_product_category_deleted_at" })
@Property({ columnType: "timestamptz", nullable: true })
deleted_at?: Date
@ManyToMany(() => Product, (product) => product.categories) @ManyToMany(() => Product, (product) => product.categories)
products = new Collection<Product>(this) products = new Collection<Product>(this)
@@ -6,24 +6,31 @@ import {
Index, Index,
OnInit, OnInit,
OneToMany, OneToMany,
OptionalProps,
PrimaryKey, PrimaryKey,
Property, Property,
Unique,
} from "@mikro-orm/core" } from "@mikro-orm/core"
import { DAL } from "@medusajs/types" import {
import { DALUtils, generateEntityId, kebabCase } from "@medusajs/utils" DALUtils,
createPsqlIndexStatementHelper,
generateEntityId,
kebabCase,
} from "@medusajs/utils"
import Product from "./product" import Product from "./product"
type OptionalRelations = "products" const collectionHandleIndexName = "IDX_collection_handle_unique"
type OptionalFields = DAL.SoftDeletableEntityDateColumns const collectionHandleIndexStatement = createPsqlIndexStatementHelper({
name: collectionHandleIndexName,
tableName: "product_collection",
columns: ["handle"],
unique: true,
where: "deleted_at IS NULL",
})
collectionHandleIndexStatement.MikroORMIndex()
@Entity({ tableName: "product_collection" }) @Entity({ tableName: "product_collection" })
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) @Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
class ProductCollection { class ProductCollection {
[OptionalProps]?: OptionalRelations | OptionalFields
@PrimaryKey({ columnType: "text" }) @PrimaryKey({ columnType: "text" })
id!: string id!: string
@@ -31,10 +38,6 @@ class ProductCollection {
title: string title: string
@Property({ columnType: "text" }) @Property({ columnType: "text" })
@Unique({
name: "IDX_product_collection_handle_unique",
properties: ["handle"],
})
handle?: string handle?: string
@OneToMany(() => Product, (product) => product.collection) @OneToMany(() => Product, (product) => product.collection)
@@ -63,16 +66,8 @@ class ProductCollection {
deleted_at?: Date deleted_at?: Date
@OnInit() @OnInit()
onInit() {
this.id = generateEntityId(this.id, "pcol")
if (!this.handle && this.title) {
this.handle = kebabCase(this.title)
}
}
@BeforeCreate() @BeforeCreate()
onCreate() { onInit() {
this.id = generateEntityId(this.id, "pcol") this.id = generateEntityId(this.id, "pcol")
if (!this.handle && this.title) { if (!this.handle && this.title) {
+14 -8
View File
@@ -6,27 +6,33 @@ import {
Index, Index,
ManyToMany, ManyToMany,
OnInit, OnInit,
OptionalProps,
PrimaryKey, PrimaryKey,
Property, Property,
} from "@mikro-orm/core" } from "@mikro-orm/core"
import { DAL } from "@medusajs/types" import {
import { DALUtils, generateEntityId } from "@medusajs/utils" DALUtils,
createPsqlIndexStatementHelper,
generateEntityId,
} from "@medusajs/utils"
import Product from "./product" import Product from "./product"
type OptionalRelations = "products" const imageUrlIndexName = "IDX_product_image_url"
type OptionalFields = DAL.SoftDeletableEntityDateColumns const imageUrlIndexStatement = createPsqlIndexStatementHelper({
name: imageUrlIndexName,
tableName: "image",
columns: ["url"],
unique: false,
where: "deleted_at IS NULL",
})
imageUrlIndexStatement.MikroORMIndex()
@Entity({ tableName: "image" }) @Entity({ tableName: "image" })
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) @Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
class ProductImage { class ProductImage {
[OptionalProps]?: OptionalRelations | OptionalFields
@PrimaryKey({ columnType: "text" }) @PrimaryKey({ columnType: "text" })
id!: string id!: string
@Index({ name: "IDX_product_image_url" })
@Property({ columnType: "text" }) @Property({ columnType: "text" })
url: string url: string
@@ -1,4 +1,3 @@
import { DAL } from "@medusajs/types"
import { import {
DALUtils, DALUtils,
createPsqlIndexStatementHelper, createPsqlIndexStatementHelper,
@@ -13,18 +12,10 @@ import {
ManyToOne, ManyToOne,
OnInit, OnInit,
OneToMany, OneToMany,
OptionalProps,
PrimaryKey, PrimaryKey,
Property, Property,
} from "@mikro-orm/core" } from "@mikro-orm/core"
import { ProductOption, ProductVariant, ProductVariantOption } from "./index" import { ProductOption, ProductVariantOption } from "./index"
type OptionalFields =
| "allow_backorder"
| "manage_inventory"
| "option_id"
| DAL.SoftDeletableEntityDateColumns
type OptionalRelations = "product" | "option" | "variant"
const optionValueOptionIdIndexName = "IDX_option_value_option_id_unique" const optionValueOptionIdIndexName = "IDX_option_value_option_id_unique"
const optionValueOptionIdIndexStatement = createPsqlIndexStatementHelper({ const optionValueOptionIdIndexStatement = createPsqlIndexStatementHelper({
@@ -39,8 +30,6 @@ optionValueOptionIdIndexStatement.MikroORMIndex()
@Entity({ tableName: "product_option_value" }) @Entity({ tableName: "product_option_value" })
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) @Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
class ProductOptionValue { class ProductOptionValue {
[OptionalProps]?: OptionalFields | OptionalRelations
@PrimaryKey({ columnType: "text" }) @PrimaryKey({ columnType: "text" })
id!: string id!: string
@@ -52,7 +41,6 @@ class ProductOptionValue {
fieldName: "option_id", fieldName: "option_id",
mapToPk: true, mapToPk: true,
nullable: true, nullable: true,
index: "IDX_product_option_value_option_id",
onDelete: "cascade", onDelete: "cascade",
}) })
option_id: string | null option_id: string | null
@@ -89,13 +77,8 @@ class ProductOptionValue {
deleted_at?: Date deleted_at?: Date
@OnInit() @OnInit()
onInit() {
this.id = generateEntityId(this.id, "optval")
this.option_id ??= this.option?.id ?? null
}
@BeforeCreate() @BeforeCreate()
beforeCreate() { onInit() {
this.id = generateEntityId(this.id, "optval") this.id = generateEntityId(this.id, "optval")
this.option_id ??= this.option?.id ?? null this.option_id ??= this.option?.id ?? null
} }
+2 -17
View File
@@ -1,4 +1,3 @@
import { DAL } from "@medusajs/types"
import { import {
DALUtils, DALUtils,
createPsqlIndexStatementHelper, createPsqlIndexStatementHelper,
@@ -14,19 +13,12 @@ import {
ManyToOne, ManyToOne,
OnInit, OnInit,
OneToMany, OneToMany,
OptionalProps,
PrimaryKey, PrimaryKey,
Property, Property,
} from "@mikro-orm/core" } from "@mikro-orm/core"
import { Product } from "./index" import { Product } from "./index"
import ProductOptionValue from "./product-option-value" import ProductOptionValue from "./product-option-value"
type OptionalRelations =
| "values"
| "product"
| DAL.SoftDeletableEntityDateColumns
type OptionalFields = "product_id"
const optionProductIdTitleIndexName = "IDX_option_product_id_title_unique" const optionProductIdTitleIndexName = "IDX_option_product_id_title_unique"
const optionProductIdTitleIndexStatement = createPsqlIndexStatementHelper({ const optionProductIdTitleIndexStatement = createPsqlIndexStatementHelper({
name: optionProductIdTitleIndexName, name: optionProductIdTitleIndexName,
@@ -40,8 +32,6 @@ optionProductIdTitleIndexStatement.MikroORMIndex()
@Entity({ tableName: "product_option" }) @Entity({ tableName: "product_option" })
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) @Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
class ProductOption { class ProductOption {
[OptionalProps]?: OptionalRelations | OptionalFields
@PrimaryKey({ columnType: "text" }) @PrimaryKey({ columnType: "text" })
id!: string id!: string
@@ -64,7 +54,7 @@ class ProductOption {
product: Product | null product: Product | null
@OneToMany(() => ProductOptionValue, (value) => value.option, { @OneToMany(() => ProductOptionValue, (value) => value.option, {
cascade: [Cascade.PERSIST, Cascade.REMOVE, "soft-remove" as any], cascade: [Cascade.PERSIST, "soft-remove" as any],
}) })
values = new Collection<ProductOptionValue>(this) values = new Collection<ProductOptionValue>(this)
@@ -91,13 +81,8 @@ class ProductOption {
deleted_at?: Date deleted_at?: Date
@OnInit() @OnInit()
onInit() {
this.id = generateEntityId(this.id, "opt")
this.product_id ??= this.product?.id ?? null
}
@BeforeCreate() @BeforeCreate()
beforeCreate() { onInit() {
this.id = generateEntityId(this.id, "opt") this.id = generateEntityId(this.id, "opt")
this.product_id ??= this.product?.id ?? null this.product_id ??= this.product?.id ?? null
} }
+15 -12
View File
@@ -6,23 +6,30 @@ import {
Index, Index,
ManyToMany, ManyToMany,
OnInit, OnInit,
OptionalProps,
PrimaryKey, PrimaryKey,
Property, Property,
} from "@mikro-orm/core" } from "@mikro-orm/core"
import { DAL } from "@medusajs/types" import {
import { DALUtils, generateEntityId } from "@medusajs/utils" DALUtils,
createPsqlIndexStatementHelper,
generateEntityId,
} from "@medusajs/utils"
import Product from "./product" import Product from "./product"
type OptionalRelations = "products" const tagValueIndexName = "IDX_tag_value_unique"
type OptionalFields = DAL.SoftDeletableEntityDateColumns const tagValueIndexStatement = createPsqlIndexStatementHelper({
name: tagValueIndexName,
tableName: "product_tag",
columns: ["value"],
unique: true,
where: "deleted_at IS NULL",
})
tagValueIndexStatement.MikroORMIndex()
@Entity({ tableName: "product_tag" }) @Entity({ tableName: "product_tag" })
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) @Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
class ProductTag { class ProductTag {
[OptionalProps]?: OptionalRelations | OptionalFields
@PrimaryKey({ columnType: "text" }) @PrimaryKey({ columnType: "text" })
id!: string id!: string
@@ -55,12 +62,8 @@ class ProductTag {
products = new Collection<Product>(this) products = new Collection<Product>(this)
@OnInit() @OnInit()
onInit() {
this.id = generateEntityId(this.id, "ptag")
}
@BeforeCreate() @BeforeCreate()
onCreate() { onInit() {
this.id = generateEntityId(this.id, "ptag") this.id = generateEntityId(this.id, "ptag")
} }
} }
+15 -11
View File
@@ -4,21 +4,29 @@ import {
Filter, Filter,
Index, Index,
OnInit, OnInit,
OptionalProps,
PrimaryKey, PrimaryKey,
Property, Property,
} from "@mikro-orm/core" } from "@mikro-orm/core"
import { DAL } from "@medusajs/types" import {
import { DALUtils, generateEntityId } from "@medusajs/utils" DALUtils,
createPsqlIndexStatementHelper,
generateEntityId,
} from "@medusajs/utils"
type OptionalFields = DAL.SoftDeletableEntityDateColumns const typeValueIndexName = "IDX_type_value_unique"
const typeValueIndexStatement = createPsqlIndexStatementHelper({
name: typeValueIndexName,
tableName: "product_type",
columns: ["value"],
unique: true,
where: "deleted_at IS NULL",
})
typeValueIndexStatement.MikroORMIndex()
@Entity({ tableName: "product_type" }) @Entity({ tableName: "product_type" })
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) @Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
class ProductType { class ProductType {
[OptionalProps]?: OptionalFields
@PrimaryKey({ columnType: "text" }) @PrimaryKey({ columnType: "text" })
id!: string id!: string
@@ -48,12 +56,8 @@ class ProductType {
deleted_at?: Date deleted_at?: Date
@OnInit() @OnInit()
onInit() {
this.id = generateEntityId(this.id, "ptyp")
}
@BeforeCreate() @BeforeCreate()
onCreate() { onInit() {
this.id = generateEntityId(this.id, "ptyp") this.id = generateEntityId(this.id, "ptyp")
} }
} }
@@ -36,6 +36,7 @@ class ProductVariantOption {
nullable: true, nullable: true,
fieldName: "option_value_id", fieldName: "option_value_id",
mapToPk: true, mapToPk: true,
onDelete: "cascade",
}) })
option_value_id!: string option_value_id!: string
@@ -50,6 +51,7 @@ class ProductVariantOption {
nullable: true, nullable: true,
fieldName: "variant_id", fieldName: "variant_id",
mapToPk: true, mapToPk: true,
onDelete: "cascade",
}) })
variant_id: string | null variant_id: string | null
@@ -79,14 +81,8 @@ class ProductVariantOption {
deleted_at?: Date deleted_at?: Date
@OnInit() @OnInit()
onInit() {
this.id = generateEntityId(this.id, "varopt")
this.variant_id ??= this.variant?.id ?? null
this.option_value_id ??= this.option_value?.id ?? null
}
@BeforeCreate() @BeforeCreate()
beforeCreate() { onInit() {
this.id = generateEntityId(this.id, "varopt") this.id = generateEntityId(this.id, "varopt")
this.variant_id ??= this.variant?.id ?? null this.variant_id ??= this.variant?.id ?? null
this.option_value_id ??= this.option_value?.id ?? null this.option_value_id ??= this.option_value?.id ?? null
+62 -43
View File
@@ -1,6 +1,6 @@
import { DAL } from "@medusajs/types"
import { import {
DALUtils, DALUtils,
createPsqlIndexStatementHelper,
generateEntityId, generateEntityId,
optionalNumericSerializer, optionalNumericSerializer,
} from "@medusajs/utils" } from "@medusajs/utils"
@@ -14,26 +14,65 @@ import {
ManyToOne, ManyToOne,
OnInit, OnInit,
OneToMany, OneToMany,
OptionalProps,
PrimaryKey, PrimaryKey,
Property, Property,
Unique,
} from "@mikro-orm/core" } from "@mikro-orm/core"
import { Product } from "@models" import { Product } from "@models"
import ProductVariantOption from "./product-variant-option" import ProductVariantOption from "./product-variant-option"
type OptionalFields = const variantSkuIndexName = "IDX_product_variant_sku_unique"
| "allow_backorder" const variantSkuIndexStatement = createPsqlIndexStatementHelper({
| "manage_inventory" name: variantSkuIndexName,
| "product" tableName: "product_variant",
| "product_id" columns: ["sku"],
| DAL.SoftDeletableEntityDateColumns unique: true,
where: "deleted_at IS NULL",
})
const variantBarcodeIndexName = "IDX_product_variant_barcode_unique"
const variantBarcodeIndexStatement = createPsqlIndexStatementHelper({
name: variantBarcodeIndexName,
tableName: "product_variant",
columns: ["barcode"],
unique: true,
where: "deleted_at IS NULL",
})
const variantEanIndexName = "IDX_product_variant_ean_unique"
const variantEanIndexStatement = createPsqlIndexStatementHelper({
name: variantEanIndexName,
tableName: "product_variant",
columns: ["ean"],
unique: true,
where: "deleted_at IS NULL",
})
const variantUpcIndexName = "IDX_product_variant_upc_unique"
const variantUpcIndexStatement = createPsqlIndexStatementHelper({
name: variantUpcIndexName,
tableName: "product_variant",
columns: ["upc"],
unique: true,
where: "deleted_at IS NULL",
})
const variantProductIdIndexName = "IDX_product_variant_product_id"
const variantProductIdIndexStatement = createPsqlIndexStatementHelper({
name: variantProductIdIndexName,
tableName: "product_variant",
columns: ["product_id"],
unique: false,
where: "deleted_at IS NULL",
})
variantProductIdIndexStatement.MikroORMIndex()
variantSkuIndexStatement.MikroORMIndex()
variantBarcodeIndexStatement.MikroORMIndex()
variantEanIndexStatement.MikroORMIndex()
variantUpcIndexStatement.MikroORMIndex()
@Entity({ tableName: "product_variant" }) @Entity({ tableName: "product_variant" })
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) @Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
class ProductVariant { class ProductVariant {
[OptionalProps]?: OptionalFields
@PrimaryKey({ columnType: "text" }) @PrimaryKey({ columnType: "text" })
id!: string id!: string
@@ -41,33 +80,18 @@ class ProductVariant {
title: string title: string
@Property({ columnType: "text", nullable: true }) @Property({ columnType: "text", nullable: true })
@Unique({
name: "IDX_product_variant_sku_unique",
properties: ["sku"],
})
sku?: string | null sku?: string | null
@Property({ columnType: "text", nullable: true }) @Property({ columnType: "text", nullable: true })
@Unique({
name: "IDX_product_variant_barcode_unique",
properties: ["barcode"],
})
barcode?: string | null barcode?: string | null
@Property({ columnType: "text", nullable: true }) @Property({ columnType: "text", nullable: true })
@Unique({
name: "IDX_product_variant_ean_unique",
properties: ["ean"],
})
ean?: string | null ean?: string | null
@Property({ columnType: "text", nullable: true }) @Property({ columnType: "text", nullable: true })
@Unique({
name: "IDX_product_variant_upc_unique",
properties: ["upc"],
})
upc?: string | null upc?: string | null
// TODO: replace with BigNumber
// Note: Upon serialization, this turns to a string. This is on purpose, because you would loose // Note: Upon serialization, this turns to a string. This is on purpose, because you would loose
// precision if you cast numeric to JS number, as JS number is a float. // precision if you cast numeric to JS number, as JS number is a float.
// Ref: https://github.com/mikro-orm/mikro-orm/issues/2295 // Ref: https://github.com/mikro-orm/mikro-orm/issues/2295
@@ -111,6 +135,7 @@ class ProductVariant {
@Property({ columnType: "jsonb", nullable: true }) @Property({ columnType: "jsonb", nullable: true })
metadata?: Record<string, unknown> | null metadata?: Record<string, unknown> | null
// TODO: replace with BigNumber, or in this case a normal int should work
@Property({ @Property({
columnType: "numeric", columnType: "numeric",
nullable: true, nullable: true,
@@ -124,7 +149,6 @@ class ProductVariant {
nullable: true, nullable: true,
onDelete: "cascade", onDelete: "cascade",
fieldName: "product_id", fieldName: "product_id",
index: "IDX_product_variant_product_id",
mapToPk: true, mapToPk: true,
}) })
product_id: string | null product_id: string | null
@@ -135,6 +159,15 @@ class ProductVariant {
}) })
product: Product | null product: Product | null
@OneToMany(
() => ProductVariantOption,
(variantOption) => variantOption.variant,
{
cascade: [Cascade.PERSIST, "soft-remove" as any],
}
)
options = new Collection<ProductVariantOption>(this)
@Property({ @Property({
onCreate: () => new Date(), onCreate: () => new Date(),
columnType: "timestamptz", columnType: "timestamptz",
@@ -154,23 +187,9 @@ class ProductVariant {
@Property({ columnType: "timestamptz", nullable: true }) @Property({ columnType: "timestamptz", nullable: true })
deleted_at?: Date deleted_at?: Date
@OneToMany(
() => ProductVariantOption,
(variantOption) => variantOption.variant,
{
cascade: [Cascade.PERSIST, Cascade.REMOVE, "soft-remove" as any],
}
)
options = new Collection<ProductVariantOption>(this)
@OnInit() @OnInit()
onInit() {
this.id = generateEntityId(this.id, "variant")
this.product_id ??= this.product?.id ?? null
}
@BeforeCreate() @BeforeCreate()
onCreate() { onInit() {
this.id = generateEntityId(this.id, "variant") this.id = generateEntityId(this.id, "variant")
this.product_id ??= this.product?.id ?? null this.product_id ??= this.product?.id ?? null
} }
+34 -30
View File
@@ -9,14 +9,12 @@ import {
ManyToOne, ManyToOne,
OneToMany, OneToMany,
OnInit, OnInit,
OptionalProps,
PrimaryKey, PrimaryKey,
Property, Property,
Unique,
} from "@mikro-orm/core" } from "@mikro-orm/core"
import { DAL } from "@medusajs/types"
import { import {
createPsqlIndexStatementHelper,
DALUtils, DALUtils,
generateEntityId, generateEntityId,
kebabCase, kebabCase,
@@ -30,19 +28,39 @@ import ProductTag from "./product-tag"
import ProductType from "./product-type" import ProductType from "./product-type"
import ProductVariant from "./product-variant" import ProductVariant from "./product-variant"
type OptionalRelations = "collection" | "type" const productHandleIndexName = "IDX_product_handle_unique"
type OptionalFields = const productHandleIndexStatement = createPsqlIndexStatementHelper({
| "collection_id" name: productHandleIndexName,
| "type_id" tableName: "product",
| "is_giftcard" columns: ["handle"],
| "discountable" unique: true,
| DAL.SoftDeletableEntityDateColumns where: "deleted_at IS NULL",
})
const productTypeIndexName = "IDX_product_type_id"
const productTypeIndexStatement = createPsqlIndexStatementHelper({
name: productTypeIndexName,
tableName: "product",
columns: ["type_id"],
unique: false,
where: "deleted_at IS NULL",
})
const productCollectionIndexName = "IDX_product_collection_id"
const productCollectionIndexStatement = createPsqlIndexStatementHelper({
name: productCollectionIndexName,
tableName: "product",
columns: ["collection_id"],
unique: false,
where: "deleted_at IS NULL",
})
productTypeIndexStatement.MikroORMIndex()
productCollectionIndexStatement.MikroORMIndex()
productHandleIndexStatement.MikroORMIndex()
@Entity({ tableName: "product" }) @Entity({ tableName: "product" })
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) @Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
class Product { class Product {
[OptionalProps]?: OptionalRelations | OptionalFields
@PrimaryKey({ columnType: "text" }) @PrimaryKey({ columnType: "text" })
id!: string id!: string
@@ -50,11 +68,7 @@ class Product {
title: string title: string
@Property({ columnType: "text" }) @Property({ columnType: "text" })
@Unique({ handle?: string
name: "IDX_product_handle_unique",
properties: ["handle"],
})
handle?: string | null
@Property({ columnType: "text", nullable: true }) @Property({ columnType: "text", nullable: true })
subtitle?: string | null subtitle?: string | null
@@ -111,6 +125,7 @@ class Product {
nullable: true, nullable: true,
fieldName: "collection_id", fieldName: "collection_id",
mapToPk: true, mapToPk: true,
onDelete: "set null",
}) })
collection_id: string | null collection_id: string | null
@@ -124,8 +139,8 @@ class Product {
columnType: "text", columnType: "text",
nullable: true, nullable: true,
fieldName: "type_id", fieldName: "type_id",
index: "IDX_product_type_id",
mapToPk: true, mapToPk: true,
onDelete: "set null",
}) })
type_id: string | null type_id: string | null
@@ -145,7 +160,6 @@ class Product {
@ManyToMany(() => ProductImage, "products", { @ManyToMany(() => ProductImage, "products", {
owner: true, owner: true,
pivotTable: "product_images", pivotTable: "product_images",
index: "IDX_product_image_id",
joinColumn: "product_id", joinColumn: "product_id",
inverseJoinColumn: "image_id", inverseJoinColumn: "image_id",
}) })
@@ -186,18 +200,8 @@ class Product {
metadata?: Record<string, unknown> | null metadata?: Record<string, unknown> | null
@OnInit() @OnInit()
onInit() {
this.id = generateEntityId(this.id, "prod")
this.type_id ??= this.type?.id ?? null
this.collection_id ??= this.collection?.id ?? null
if (!this.handle && this.title) {
this.handle = kebabCase(this.title)
}
}
@BeforeCreate() @BeforeCreate()
beforeCreate() { onInit() {
this.id = generateEntityId(this.id, "prod") this.id = generateEntityId(this.id, "prod")
this.type_id ??= this.type?.id ?? null this.type_id ??= this.type?.id ?? null
this.collection_id ??= this.collection?.id ?? null this.collection_id ??= this.collection?.id ?? null