feat(medusa): List products with Remote Query (#4969)

**What**
- includes some type fixes in the DAL layer
- List products including their prices and filtered by the sales channel as well as q parameter and category scope and all other filters
- Assign shipping profile
- ordering
- Add missing columns in the product module
- update product module migrations

**Comment**
-  In regards to the fields, we can pass whatever we want the module will only return the one that exists (default behavior), but on the other hand, that is not possible for the relations.

**question**
- To simplify usage, should we expose the fields/relations available from the module to simplify building a query for the user and be aware of what the module provides

**todo**
- Add back the support for the user to ask for fields/relations
This commit is contained in:
Adrien de Peretti
2023-09-12 15:55:05 +00:00
committed by GitHub
parent afd4e72cdf
commit 30863fee52
34 changed files with 1066 additions and 124 deletions
@@ -1,5 +1,7 @@
{
"namespaces": ["public"],
"namespaces": [
"public"
],
"name": "public",
"tables": [
{
@@ -97,6 +99,7 @@
"primary": false,
"nullable": false,
"length": 6,
"default": "now()",
"mappedType": "datetime"
},
"updated_at": {
@@ -107,6 +110,7 @@
"primary": false,
"nullable": false,
"length": 6,
"default": "now()",
"mappedType": "datetime"
}
},
@@ -115,21 +119,27 @@
"indexes": [
{
"keyName": "IDX_product_category_path",
"columnNames": ["mpath"],
"columnNames": [
"mpath"
],
"composite": false,
"primary": false,
"unique": false
},
{
"keyName": "IDX_product_category_handle",
"columnNames": ["handle"],
"columnNames": [
"handle"
],
"composite": false,
"primary": false,
"unique": true
},
{
"keyName": "product_category_pkey",
"columnNames": ["id"],
"columnNames": [
"id"
],
"composite": false,
"primary": true,
"unique": true
@@ -139,9 +149,13 @@
"foreignKeys": {
"product_category_parent_category_id_foreign": {
"constraintName": "product_category_parent_category_id_foreign",
"columnNames": ["parent_category_id"],
"columnNames": [
"parent_category_id"
],
"localTableName": "public.product_category",
"referencedColumnNames": ["id"],
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.product_category",
"deleteRule": "set null",
"updateRule": "cascade"
@@ -186,6 +200,28 @@
"nullable": true,
"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",
@@ -201,7 +237,9 @@
"schema": "public",
"indexes": [
{
"columnNames": ["deleted_at"],
"columnNames": [
"deleted_at"
],
"composite": false,
"keyName": "IDX_product_collection_deleted_at",
"primary": false,
@@ -209,14 +247,18 @@
},
{
"keyName": "IDX_product_collection_handle_unique",
"columnNames": ["handle"],
"columnNames": [
"handle"
],
"composite": false,
"primary": false,
"unique": true
},
{
"keyName": "product_collection_pkey",
"columnNames": ["id"],
"columnNames": [
"id"
],
"composite": false,
"primary": true,
"unique": true
@@ -254,6 +296,28 @@
"nullable": true,
"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",
@@ -269,14 +333,18 @@
"schema": "public",
"indexes": [
{
"columnNames": ["url"],
"columnNames": [
"url"
],
"composite": false,
"keyName": "IDX_product_image_url",
"primary": false,
"unique": false
},
{
"columnNames": ["deleted_at"],
"columnNames": [
"deleted_at"
],
"composite": false,
"keyName": "IDX_product_image_deleted_at",
"primary": false,
@@ -284,7 +352,9 @@
},
{
"keyName": "image_pkey",
"columnNames": ["id"],
"columnNames": [
"id"
],
"composite": false,
"primary": true,
"unique": true
@@ -322,6 +392,28 @@
"nullable": true,
"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",
@@ -337,7 +429,9 @@
"schema": "public",
"indexes": [
{
"columnNames": ["deleted_at"],
"columnNames": [
"deleted_at"
],
"composite": false,
"keyName": "IDX_product_tag_deleted_at",
"primary": false,
@@ -345,7 +439,9 @@
},
{
"keyName": "product_tag_pkey",
"columnNames": ["id"],
"columnNames": [
"id"
],
"composite": false,
"primary": true,
"unique": true
@@ -383,6 +479,28 @@
"nullable": true,
"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",
@@ -398,7 +516,9 @@
"schema": "public",
"indexes": [
{
"columnNames": ["deleted_at"],
"columnNames": [
"deleted_at"
],
"composite": false,
"keyName": "IDX_product_type_deleted_at",
"primary": false,
@@ -406,7 +526,9 @@
},
{
"keyName": "product_type_pkey",
"columnNames": ["id"],
"columnNames": [
"id"
],
"composite": false,
"primary": true,
"unique": true
@@ -479,7 +601,12 @@
"autoincrement": false,
"primary": false,
"nullable": false,
"enumItems": ["draft", "proposed", "published", "rejected"],
"enumItems": [
"draft",
"proposed",
"published",
"rejected"
],
"mappedType": "enum"
},
"thumbnail": {
@@ -608,6 +735,7 @@
"primary": false,
"nullable": false,
"length": 6,
"default": "now()",
"mappedType": "datetime"
},
"updated_at": {
@@ -618,6 +746,7 @@
"primary": false,
"nullable": false,
"length": 6,
"default": "now()",
"mappedType": "datetime"
},
"deleted_at": {
@@ -644,14 +773,18 @@
"schema": "public",
"indexes": [
{
"columnNames": ["type_id"],
"columnNames": [
"type_id"
],
"composite": false,
"keyName": "IDX_product_type_id",
"primary": false,
"unique": false
},
{
"columnNames": ["deleted_at"],
"columnNames": [
"deleted_at"
],
"composite": false,
"keyName": "IDX_product_deleted_at",
"primary": false,
@@ -659,14 +792,18 @@
},
{
"keyName": "IDX_product_handle_unique",
"columnNames": ["handle"],
"columnNames": [
"handle"
],
"composite": false,
"primary": false,
"unique": true
},
{
"keyName": "product_pkey",
"columnNames": ["id"],
"columnNames": [
"id"
],
"composite": false,
"primary": true,
"unique": true
@@ -676,18 +813,26 @@
"foreignKeys": {
"product_collection_id_foreign": {
"constraintName": "product_collection_id_foreign",
"columnNames": ["collection_id"],
"columnNames": [
"collection_id"
],
"localTableName": "public.product",
"referencedColumnNames": ["id"],
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.product_collection",
"deleteRule": "set null",
"updateRule": "cascade"
},
"product_type_id_foreign": {
"constraintName": "product_type_id_foreign",
"columnNames": ["type_id"],
"columnNames": [
"type_id"
],
"localTableName": "public.product",
"referencedColumnNames": ["id"],
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.product_type",
"deleteRule": "set null",
"updateRule": "cascade"
@@ -732,6 +877,28 @@
"nullable": true,
"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",
@@ -747,14 +914,18 @@
"schema": "public",
"indexes": [
{
"columnNames": ["product_id"],
"columnNames": [
"product_id"
],
"composite": false,
"keyName": "IDX_product_option_product_id",
"primary": false,
"unique": false
},
{
"columnNames": ["deleted_at"],
"columnNames": [
"deleted_at"
],
"composite": false,
"keyName": "IDX_product_option_deleted_at",
"primary": false,
@@ -762,7 +933,9 @@
},
{
"keyName": "product_option_pkey",
"columnNames": ["id"],
"columnNames": [
"id"
],
"composite": false,
"primary": true,
"unique": true
@@ -772,9 +945,13 @@
"foreignKeys": {
"product_option_product_id_foreign": {
"constraintName": "product_option_product_id_foreign",
"columnNames": ["product_id"],
"columnNames": [
"product_id"
],
"localTableName": "public.product_option",
"referencedColumnNames": ["id"],
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.product",
"updateRule": "cascade"
}
@@ -806,7 +983,10 @@
"indexes": [
{
"keyName": "product_tags_pkey",
"columnNames": ["product_id", "product_tag_id"],
"columnNames": [
"product_id",
"product_tag_id"
],
"composite": true,
"primary": true,
"unique": true
@@ -816,18 +996,26 @@
"foreignKeys": {
"product_tags_product_id_foreign": {
"constraintName": "product_tags_product_id_foreign",
"columnNames": ["product_id"],
"columnNames": [
"product_id"
],
"localTableName": "public.product_tags",
"referencedColumnNames": ["id"],
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.product",
"deleteRule": "cascade",
"updateRule": "cascade"
},
"product_tags_product_tag_id_foreign": {
"constraintName": "product_tags_product_tag_id_foreign",
"columnNames": ["product_tag_id"],
"columnNames": [
"product_tag_id"
],
"localTableName": "public.product_tags",
"referencedColumnNames": ["id"],
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.product_tag",
"deleteRule": "cascade",
"updateRule": "cascade"
@@ -873,9 +1061,13 @@
"foreignKeys": {
"product_images_product_id_foreign": {
"constraintName": "product_images_product_id_foreign",
"columnNames": ["product_id"],
"columnNames": [
"product_id"
],
"localTableName": "public.product_images",
"referencedColumnNames": ["id"],
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.product",
"deleteRule": "cascade",
"updateRule": "cascade"
@@ -886,7 +1078,9 @@
"image_id"
],
"localTableName": "public.product_images",
"referencedColumnNames": ["id"],
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.image",
"deleteRule": "cascade",
"updateRule": "cascade"
@@ -919,7 +1113,10 @@
"indexes": [
{
"keyName": "product_category_product_pkey",
"columnNames": ["product_id", "product_category_id"],
"columnNames": [
"product_id",
"product_category_id"
],
"composite": true,
"primary": true,
"unique": true
@@ -929,18 +1126,26 @@
"foreignKeys": {
"product_category_product_product_id_foreign": {
"constraintName": "product_category_product_product_id_foreign",
"columnNames": ["product_id"],
"columnNames": [
"product_id"
],
"localTableName": "public.product_category_product",
"referencedColumnNames": ["id"],
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.product",
"deleteRule": "cascade",
"updateRule": "cascade"
},
"product_category_product_product_category_id_foreign": {
"constraintName": "product_category_product_product_category_id_foreign",
"columnNames": ["product_category_id"],
"columnNames": [
"product_category_id"
],
"localTableName": "public.product_category_product",
"referencedColumnNames": ["id"],
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.product_category",
"deleteRule": "cascade",
"updateRule": "cascade"
@@ -1141,6 +1346,7 @@
"primary": false,
"nullable": false,
"length": 6,
"default": "now()",
"mappedType": "datetime"
},
"updated_at": {
@@ -1151,6 +1357,7 @@
"primary": false,
"nullable": false,
"length": 6,
"default": "now()",
"mappedType": "datetime"
},
"deleted_at": {
@@ -1168,14 +1375,18 @@
"schema": "public",
"indexes": [
{
"columnNames": ["deleted_at"],
"columnNames": [
"deleted_at"
],
"composite": false,
"keyName": "IDX_product_variant_deleted_at",
"primary": false,
"unique": false
},
{
"columnNames": ["product_id"],
"columnNames": [
"product_id"
],
"composite": false,
"keyName": "IDX_product_variant_product_id",
"primary": false,
@@ -1183,35 +1394,45 @@
},
{
"keyName": "IDX_product_variant_sku_unique",
"columnNames": ["sku"],
"columnNames": [
"sku"
],
"composite": false,
"primary": false,
"unique": true
},
{
"keyName": "IDX_product_variant_barcode_unique",
"columnNames": ["barcode"],
"columnNames": [
"barcode"
],
"composite": false,
"primary": false,
"unique": true
},
{
"keyName": "IDX_product_variant_ean_unique",
"columnNames": ["ean"],
"columnNames": [
"ean"
],
"composite": false,
"primary": false,
"unique": true
},
{
"keyName": "IDX_product_variant_upc_unique",
"columnNames": ["upc"],
"columnNames": [
"upc"
],
"composite": false,
"primary": false,
"unique": true
},
{
"keyName": "product_variant_pkey",
"columnNames": ["id"],
"columnNames": [
"id"
],
"composite": false,
"primary": true,
"unique": true
@@ -1221,9 +1442,13 @@
"foreignKeys": {
"product_variant_product_id_foreign": {
"constraintName": "product_variant_product_id_foreign",
"columnNames": ["product_id"],
"columnNames": [
"product_id"
],
"localTableName": "public.product_variant",
"referencedColumnNames": ["id"],
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.product",
"deleteRule": "cascade",
"updateRule": "cascade"
@@ -1277,6 +1502,28 @@
"nullable": true,
"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",
@@ -1292,21 +1539,27 @@
"schema": "public",
"indexes": [
{
"columnNames": ["option_id"],
"columnNames": [
"option_id"
],
"composite": false,
"keyName": "IDX_product_option_value_option_id",
"primary": false,
"unique": false
},
{
"columnNames": ["variant_id"],
"columnNames": [
"variant_id"
],
"composite": false,
"keyName": "IDX_product_option_value_variant_id",
"primary": false,
"unique": false
},
{
"columnNames": ["deleted_at"],
"columnNames": [
"deleted_at"
],
"composite": false,
"keyName": "IDX_product_option_value_deleted_at",
"primary": false,
@@ -1314,7 +1567,9 @@
},
{
"keyName": "product_option_value_pkey",
"columnNames": ["id"],
"columnNames": [
"id"
],
"composite": false,
"primary": true,
"unique": true
@@ -1324,17 +1579,25 @@
"foreignKeys": {
"product_option_value_option_id_foreign": {
"constraintName": "product_option_value_option_id_foreign",
"columnNames": ["option_id"],
"columnNames": [
"option_id"
],
"localTableName": "public.product_option_value",
"referencedColumnNames": ["id"],
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.product_option",
"updateRule": "cascade"
},
"product_option_value_variant_id_foreign": {
"constraintName": "product_option_value_variant_id_foreign",
"columnNames": ["variant_id"],
"columnNames": [
"variant_id"
],
"localTableName": "public.product_option_value",
"referencedColumnNames": ["id"],
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.product_variant",
"deleteRule": "cascade",
"updateRule": "cascade"
@@ -0,0 +1,69 @@
import { Migration } from '@mikro-orm/migrations';
export class Migration20230908084537 extends Migration {
async up(): Promise<void> {
this.addSql('alter table "product_category" alter column "created_at" type timestamptz using ("created_at"::timestamptz);');
this.addSql('alter table "product_category" alter column "created_at" set default now();');
this.addSql('alter table "product_category" alter column "updated_at" type timestamptz using ("updated_at"::timestamptz);');
this.addSql('alter table "product_category" alter column "updated_at" set default now();');
this.addSql('alter table "product_collection" add column "created_at" timestamptz not null default now(), add column "updated_at" timestamptz not null default now();');
this.addSql('alter table "image" add column "created_at" timestamptz not null default now(), add column "updated_at" timestamptz not null default now();');
this.addSql('alter table "product_tag" add column "created_at" timestamptz not null default now(), add column "updated_at" timestamptz not null default now();');
this.addSql('alter table "product_type" add column "created_at" timestamptz not null default now(), add column "updated_at" timestamptz not null default now();');
this.addSql('alter table "product" alter column "created_at" type timestamptz using ("created_at"::timestamptz);');
this.addSql('alter table "product" alter column "created_at" set default now();');
this.addSql('alter table "product" alter column "updated_at" type timestamptz using ("updated_at"::timestamptz);');
this.addSql('alter table "product" alter column "updated_at" set default now();');
this.addSql('alter table "product_option" add column "created_at" timestamptz not null default now(), add column "updated_at" timestamptz not null default now();');
this.addSql('alter table "product_variant" alter column "created_at" type timestamptz using ("created_at"::timestamptz);');
this.addSql('alter table "product_variant" alter column "created_at" set default now();');
this.addSql('alter table "product_variant" alter column "updated_at" type timestamptz using ("updated_at"::timestamptz);');
this.addSql('alter table "product_variant" alter column "updated_at" set default now();');
this.addSql('alter table "product_option_value" add column "created_at" timestamptz not null default now(), add column "updated_at" timestamptz not null default now();');
}
async down(): Promise<void> {
this.addSql('alter table "product_category" alter column "created_at" drop default;');
this.addSql('alter table "product_category" alter column "created_at" type timestamptz using ("created_at"::timestamptz);');
this.addSql('alter table "product_category" alter column "updated_at" drop default;');
this.addSql('alter table "product_category" alter column "updated_at" type timestamptz using ("updated_at"::timestamptz);');
this.addSql('alter table "product_collection" drop column "created_at";');
this.addSql('alter table "product_collection" drop column "updated_at";');
this.addSql('alter table "image" drop column "created_at";');
this.addSql('alter table "image" drop column "updated_at";');
this.addSql('alter table "product_tag" drop column "created_at";');
this.addSql('alter table "product_tag" drop column "updated_at";');
this.addSql('alter table "product_type" drop column "created_at";');
this.addSql('alter table "product_type" drop column "updated_at";');
this.addSql('alter table "product" alter column "created_at" drop default;');
this.addSql('alter table "product" alter column "created_at" type timestamptz using ("created_at"::timestamptz);');
this.addSql('alter table "product" alter column "updated_at" drop default;');
this.addSql('alter table "product" alter column "updated_at" type timestamptz using ("updated_at"::timestamptz);');
this.addSql('alter table "product_option" drop column "created_at";');
this.addSql('alter table "product_option" drop column "updated_at";');
this.addSql('alter table "product_variant" alter column "created_at" drop default;');
this.addSql('alter table "product_variant" alter column "created_at" type timestamptz using ("created_at"::timestamptz);');
this.addSql('alter table "product_variant" alter column "updated_at" drop default;');
this.addSql('alter table "product_variant" alter column "updated_at" type timestamptz using ("updated_at"::timestamptz);');
this.addSql('alter table "product_option_value" drop column "created_at";');
this.addSql('alter table "product_option_value" drop column "updated_at";');
}
}
@@ -8,15 +8,21 @@ import {
ManyToMany,
ManyToOne,
OneToMany,
OptionalProps,
PrimaryKey,
Property,
Unique,
} from "@mikro-orm/core"
import Product from "./product"
import { DAL } from "@medusajs/types"
type OptionalFields = DAL.SoftDeletableEntityDateColumns
@Entity({ tableName: "product_category" })
class ProductCategory {
[OptionalProps]?: OptionalFields
@PrimaryKey({ columnType: "text" })
id!: string
@@ -61,13 +67,18 @@ class ProductCategory {
})
category_children = new Collection<ProductCategory>(this)
@Property({ onCreate: () => new Date(), columnType: "timestamptz" })
@Property({
onCreate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
created_at?: Date
@Property({
onCreate: () => new Date(),
onUpdate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
updated_at?: Date
@@ -13,13 +13,15 @@ import {
import { DALUtils, generateEntityId, kebabCase } from "@medusajs/utils"
import Product from "./product"
import { DAL } from "@medusajs/types"
type OptionalRelations = "products"
type OptionalFields = DAL.SoftDeletableEntityDateColumns
@Entity({ tableName: "product_collection" })
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
class ProductCollection {
[OptionalProps]?: OptionalRelations
[OptionalProps]?: OptionalRelations | OptionalFields
@PrimaryKey({ columnType: "text" })
id!: string
@@ -40,6 +42,21 @@ class ProductCollection {
@Property({ columnType: "jsonb", nullable: true })
metadata?: Record<string, unknown> | null
@Property({
onCreate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
created_at: Date
@Property({
onCreate: () => new Date(),
onUpdate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
updated_at: Date
@Index({ name: "IDX_product_collection_deleted_at" })
@Property({ columnType: "timestamptz", nullable: true })
deleted_at?: Date
+18 -1
View File
@@ -12,13 +12,15 @@ import {
import { DALUtils, generateEntityId } from "@medusajs/utils"
import Product from "./product"
import { DAL } from "@medusajs/types"
type OptionalRelations = "products"
type OptionalFields = DAL.SoftDeletableEntityDateColumns
@Entity({ tableName: "image" })
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
class ProductImage {
[OptionalProps]?: OptionalRelations
[OptionalProps]?: OptionalRelations | OptionalFields
@PrimaryKey({ columnType: "text" })
id!: string
@@ -30,6 +32,21 @@ class ProductImage {
@Property({ columnType: "jsonb", nullable: true })
metadata?: Record<string, unknown> | null
@Property({
onCreate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
created_at: Date
@Property({
onCreate: () => new Date(),
onUpdate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
updated_at: Date
@Index({ name: "IDX_product_image_deleted_at" })
@Property({ columnType: "timestamptz", nullable: true })
deleted_at?: Date
@@ -10,14 +10,14 @@ import {
} from "@mikro-orm/core"
import { ProductOption, ProductVariant } from "./index"
import { DALUtils, generateEntityId } from "@medusajs/utils"
import { DAL } from "@medusajs/types"
type OptionalFields =
| "created_at"
| "updated_at"
| "allow_backorder"
| "manage_inventory"
| "option_id"
| "variant_id"
| DAL.SoftDeletableEntityDateColumns
type OptionalRelations = "product" | "option" | "variant"
@Entity({ tableName: "product_option_value" })
@@ -53,6 +53,21 @@ class ProductOptionValue {
@Property({ columnType: "jsonb", nullable: true })
metadata?: Record<string, unknown> | null
@Property({
onCreate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
created_at: Date
@Property({
onCreate: () => new Date(),
onUpdate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
updated_at: Date
@Index({ name: "IDX_product_option_value_deleted_at" })
@Property({ columnType: "timestamptz", nullable: true })
deleted_at?: Date
+20 -1
View File
@@ -14,8 +14,12 @@ import {
} from "@mikro-orm/core"
import { Product } from "./index"
import ProductOptionValue from "./product-option-value"
import { DAL } from "@medusajs/types"
type OptionalRelations = "values" | "product"
type OptionalRelations =
| "values"
| "product"
| DAL.SoftDeletableEntityDateColumns
type OptionalFields = "product_id"
@Entity({ tableName: "product_option" })
@@ -46,6 +50,21 @@ class ProductOption {
@Property({ columnType: "jsonb", nullable: true })
metadata?: Record<string, unknown> | null
@Property({
onCreate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
created_at: Date
@Property({
onCreate: () => new Date(),
onUpdate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
updated_at: Date
@Index({ name: "IDX_product_option_deleted_at" })
@Property({ columnType: "timestamptz", nullable: true })
deleted_at?: Date
+18 -1
View File
@@ -12,13 +12,15 @@ import {
import { DALUtils, generateEntityId } from "@medusajs/utils"
import Product from "./product"
import { DAL } from "@medusajs/types"
type OptionalRelations = "products"
type OptionalFields = DAL.SoftDeletableEntityDateColumns
@Entity({ tableName: "product_tag" })
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
class ProductTag {
[OptionalProps]?: OptionalRelations
[OptionalProps]?: OptionalRelations | OptionalFields
@PrimaryKey({ columnType: "text" })
id!: string
@@ -29,6 +31,21 @@ class ProductTag {
@Property({ columnType: "jsonb", nullable: true })
metadata?: Record<string, unknown> | null
@Property({
onCreate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
created_at: Date
@Property({
onCreate: () => new Date(),
onUpdate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
updated_at: Date
@Index({ name: "IDX_product_tag_deleted_at" })
@Property({ columnType: "timestamptz", nullable: true })
deleted_at?: Date
@@ -3,15 +3,21 @@ import {
Entity,
Filter,
Index,
OptionalProps,
PrimaryKey,
Property,
} from "@mikro-orm/core"
import { DALUtils, generateEntityId } from "@medusajs/utils"
import { DAL } from "@medusajs/types"
type OptionalFields = DAL.SoftDeletableEntityDateColumns
@Entity({ tableName: "product_type" })
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
class ProductType {
[OptionalProps]?: OptionalFields
@PrimaryKey({ columnType: "text" })
id!: string
@@ -21,6 +27,21 @@ class ProductType {
@Property({ columnType: "json", nullable: true })
metadata?: Record<string, unknown> | null
@Property({
onCreate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
created_at: Date
@Property({
onCreate: () => new Date(),
onUpdate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
updated_at: Date
@Index({ name: "IDX_product_type_deleted_at" })
@Property({ columnType: "timestamptz", nullable: true })
deleted_at?: Date
@@ -15,14 +15,14 @@ import {
} from "@mikro-orm/core"
import { Product } from "@models"
import ProductOptionValue from "./product-option-value"
import { DAL } from "@medusajs/types"
type OptionalFields =
| "created_at"
| "updated_at"
| "allow_backorder"
| "manage_inventory"
| "product"
| "product_id"
| DAL.SoftDeletableEntityDateColumns
@Entity({ tableName: "product_variant" })
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
@@ -108,13 +108,18 @@ class ProductVariant {
@Property({ columnType: "text", nullable: true })
product_id!: string
@Property({ onCreate: () => new Date(), columnType: "timestamptz" })
@Property({
onCreate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
created_at: Date
@Property({
onCreate: () => new Date(),
onUpdate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
updated_at: Date
+8 -3
View File
@@ -27,6 +27,7 @@ import ProductTag from "./product-tag"
import ProductType from "./product-type"
import ProductVariant from "./product-variant"
import ProductImage from "./product-image"
import { DAL } from "@medusajs/types"
type OptionalRelations = "collection" | "type"
type OptionalFields =
@@ -34,8 +35,7 @@ type OptionalFields =
| "type_id"
| "is_giftcard"
| "discountable"
| "created_at"
| "updated_at"
| DAL.SoftDeletableEntityDateColumns
@Entity({ tableName: "product" })
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
@@ -154,13 +154,18 @@ class Product {
@Property({ columnType: "text", nullable: true })
external_id?: string | null
@Property({ onCreate: () => new Date(), columnType: "timestamptz" })
@Property({
onCreate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
created_at: Date
@Property({
onCreate: () => new Date(),
onUpdate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
updated_at: Date
@@ -91,8 +91,13 @@ export class ProductCategoryRepository extends DALUtils.MikroOrmBaseTreeReposito
},
}
delete whereOptions.parent_category_id
delete whereOptions.id
if ("parent_category_id" in whereOptions) {
delete whereOptions.parent_category_id
}
if ("id" in whereOptions) {
delete whereOptions.id
}
const descendantsForCategory = await manager.find(
ProductCategory,
+54 -3
View File
@@ -35,7 +35,7 @@ export class ProductRepository extends DALUtils.MikroOrmAbstractBaseRepository<P
}
async find(
findOptions: DAL.FindOptions<Product> = { where: {} },
findOptions: DAL.FindOptions<Product & { q?: string }> = { where: {} },
context: Context = {}
): Promise<Product[]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
@@ -49,6 +49,11 @@ export class ProductRepository extends DALUtils.MikroOrmAbstractBaseRepository<P
await this.mutateNotInCategoriesConstraints(findOptions_)
this.applyFreeTextSearchFilters<Product>(
findOptions_,
this.getFreeTextSearchConstraints
)
return await manager.find(
Product,
findOptions_.where as MikroFilterQuery<Product>,
@@ -57,7 +62,7 @@ export class ProductRepository extends DALUtils.MikroOrmAbstractBaseRepository<P
}
async findAndCount(
findOptions: DAL.FindOptions<Product> = { where: {} },
findOptions: DAL.FindOptions<Product & { q?: string }> = { where: {} },
context: Context = {}
): Promise<[Product[], number]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
@@ -71,6 +76,11 @@ export class ProductRepository extends DALUtils.MikroOrmAbstractBaseRepository<P
await this.mutateNotInCategoriesConstraints(findOptions_)
this.applyFreeTextSearchFilters<Product>(
findOptions_,
this.getFreeTextSearchConstraints
)
return await manager.findAndCount(
Product,
findOptions_.where as MikroFilterQuery<Product>,
@@ -88,7 +98,10 @@ export class ProductRepository extends DALUtils.MikroOrmAbstractBaseRepository<P
): Promise<void> {
const manager = this.getActiveManager<SqlEntityManager>(context)
if (findOptions.where.categories?.id?.["$nin"]) {
if (
"categories" in findOptions.where &&
findOptions.where.categories?.id?.["$nin"]
) {
const productsInCategories = await manager.find(
Product,
{
@@ -307,4 +320,42 @@ export class ProductRepository extends DALUtils.MikroOrmAbstractBaseRepository<P
return products
}
protected getFreeTextSearchConstraints(q: string) {
return [
{
description: {
$ilike: `%${q}%`,
},
},
{
title: {
$ilike: `%${q}%`,
},
},
{
collection: {
title: {
$ilike: `%${q}%`,
},
},
},
{
variants: {
$or: [
{
title: {
$ilike: `%${q}%`,
},
},
{
sku: {
$ilike: `%${q}%`,
},
},
],
},
},
]
}
}
@@ -20,7 +20,7 @@ describe("Product service", function () {
options: {
fields: undefined,
limit: 15,
offset: undefined,
offset: 0,
populate: [],
withDeleted: undefined,
},
@@ -45,7 +45,7 @@ describe("Product service", function () {
options: {
fields: undefined,
limit: 15,
offset: undefined,
offset: 0,
populate: [],
withDeleted: undefined,
},
@@ -75,7 +75,7 @@ describe("Product service", function () {
options: {
fields: undefined,
limit: 15,
offset: undefined,
offset: 0,
populate: [],
withDeleted: undefined,
},
@@ -113,7 +113,7 @@ describe("Product service", function () {
options: {
fields: undefined,
limit: 15,
offset: undefined,
offset: 0,
populate: [],
withDeleted: undefined,
},
@@ -151,7 +151,7 @@ describe("Product service", function () {
options: {
fields: undefined,
limit: 15,
offset: undefined,
offset: 0,
withDeleted: undefined,
populate: ["tags"],
},
@@ -189,7 +189,7 @@ describe("Product service", function () {
options: {
fields: undefined,
limit: 15,
offset: undefined,
offset: 0,
withDeleted: undefined,
populate: ["tags"],
},