chore: Adjusting the v2 product module to follow the v1 specs (#6618)
In this PR: 1. I added upsert support for the product 2. I updated the create and update signatures to match the latest interface standards 3. Small changes to make the v1 and v2 APIs compatible (WIP)
This commit is contained in:
1 parent
c19d276458
commit
a92cdeb01d
15 files changed
+648
-395
No files matched your search
@@ -9,6 +9,7 @@ import {
|
||||
|
||||
import { UpdateProductDTO } from "@medusajs/types"
|
||||
import { remoteQueryObjectFromString } from "@medusajs/utils"
|
||||
import { UpdateProductOptionDTO } from "../../../../../../../../types/dist"
|
||||
|
||||
export const GET = async (
|
||||
req: AuthenticatedMedusaRequest,
|
||||
@@ -33,7 +34,7 @@ export const GET = async (
|
||||
}
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<UpdateProductDTO>,
|
||||
req: AuthenticatedMedusaRequest<UpdateProductOptionDTO>,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
// TODO: Should we allow fetching a option without knowing the product ID? In such case we'll need to change the route to /admin/products/options/:id
|
||||
|
||||
@@ -1,62 +1,3 @@
|
||||
export const allowedAdminProductRelations = [
|
||||
"variants",
|
||||
// TODO: Add in next iteration
|
||||
// "variants.prices",
|
||||
// TODO: See how this should be handled
|
||||
// "variants.options",
|
||||
"images",
|
||||
// TODO: What is this?
|
||||
// "profiles",
|
||||
"options",
|
||||
// TODO: See how this should be handled
|
||||
// "options.values",
|
||||
// TODO: Handle in next iteration
|
||||
// "tags",
|
||||
// "type",
|
||||
// "collection",
|
||||
]
|
||||
export const defaultAdminProductRelations = []
|
||||
export const defaultAdminProductFields = [
|
||||
"id",
|
||||
"title",
|
||||
"subtitle",
|
||||
"status",
|
||||
"external_id",
|
||||
"description",
|
||||
"handle",
|
||||
"is_giftcard",
|
||||
"discountable",
|
||||
"thumbnail",
|
||||
// TODO: Handle in next iteration
|
||||
// "collection_id",
|
||||
// "type_id",
|
||||
"weight",
|
||||
"length",
|
||||
"height",
|
||||
"width",
|
||||
"hs_code",
|
||||
"origin_country",
|
||||
"mid_code",
|
||||
"material",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"deleted_at",
|
||||
"metadata",
|
||||
]
|
||||
|
||||
export const retrieveTransformQueryConfig = {
|
||||
defaultFields: defaultAdminProductFields,
|
||||
defaultRelations: defaultAdminProductRelations,
|
||||
allowedRelations: allowedAdminProductRelations,
|
||||
isList: false,
|
||||
}
|
||||
|
||||
export const listTransformQueryConfig = {
|
||||
...retrieveTransformQueryConfig,
|
||||
defaultLimit: 50,
|
||||
isList: true,
|
||||
}
|
||||
|
||||
export const defaultAdminProductsVariantFields = [
|
||||
"id",
|
||||
"product_id",
|
||||
@@ -81,6 +22,7 @@ export const defaultAdminProductsVariantFields = [
|
||||
"ean",
|
||||
"upc",
|
||||
"barcode",
|
||||
"options",
|
||||
]
|
||||
|
||||
export const retrieveVariantConfig = {
|
||||
@@ -110,3 +52,92 @@ export const listOptionConfig = {
|
||||
defaultLimit: 50,
|
||||
isList: true,
|
||||
}
|
||||
|
||||
export const allowedAdminProductRelations = [
|
||||
"variants",
|
||||
// TODO: Add in next iteration
|
||||
// "variants.prices",
|
||||
// TODO: See how this should be handled
|
||||
// "variants.options",
|
||||
"images",
|
||||
// TODO: What is this?
|
||||
// "profiles",
|
||||
"options",
|
||||
// TODO: See how this should be handled
|
||||
// "options.values",
|
||||
// TODO: Handle in next iteration
|
||||
// "tags",
|
||||
// "type",
|
||||
// "collection",
|
||||
]
|
||||
|
||||
// TODO: This is what we had in the v1 list. Do we still want to expand that much by default? Also this doesn't work in v2 it seems.
|
||||
export const defaultAdminProductRelations = [
|
||||
"variants",
|
||||
"variants.prices",
|
||||
"variants.options",
|
||||
"profiles",
|
||||
"images",
|
||||
"options",
|
||||
"options.values",
|
||||
"tags",
|
||||
"type",
|
||||
"collection",
|
||||
]
|
||||
|
||||
export const defaultAdminProductFields = [
|
||||
"id",
|
||||
"title",
|
||||
"subtitle",
|
||||
"status",
|
||||
"external_id",
|
||||
"description",
|
||||
"handle",
|
||||
"is_giftcard",
|
||||
"discountable",
|
||||
"thumbnail",
|
||||
"collection_id",
|
||||
"type_id",
|
||||
"weight",
|
||||
"length",
|
||||
"height",
|
||||
"width",
|
||||
"hs_code",
|
||||
"origin_country",
|
||||
"mid_code",
|
||||
"material",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"deleted_at",
|
||||
"metadata",
|
||||
"collection.id",
|
||||
"collection.title",
|
||||
"collection.handle",
|
||||
"collection.created_at",
|
||||
"collection.updated_at",
|
||||
"tags.id",
|
||||
"tags.value",
|
||||
"tags.created_at",
|
||||
"tags.updated_at",
|
||||
"images.id",
|
||||
"images.url",
|
||||
"images.metadata",
|
||||
"images.created_at",
|
||||
"images.updated_at",
|
||||
"images.deleted_at",
|
||||
// TODO: Until we support wildcards we have to do something like this.
|
||||
...defaultAdminProductsVariantFields.map((f) => `variants.${f}`),
|
||||
]
|
||||
|
||||
export const retrieveTransformQueryConfig = {
|
||||
defaultFields: defaultAdminProductFields,
|
||||
defaultRelations: defaultAdminProductRelations,
|
||||
allowedRelations: allowedAdminProductRelations,
|
||||
isList: false,
|
||||
}
|
||||
|
||||
export const listTransformQueryConfig = {
|
||||
...retrieveTransformQueryConfig,
|
||||
defaultLimit: 50,
|
||||
isList: true,
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import { OperatorMapValidator } from "../../../types/validators/operator-map"
|
||||
import { ProductStatus } from "@medusajs/utils"
|
||||
import { IsType } from "../../../utils"
|
||||
import { optionalBooleanMapper } from "../../../utils/validators/is-boolean"
|
||||
import { ProductTagReq, ProductTypeReq } from "../../../types/product"
|
||||
|
||||
export class AdminGetProductsProductParams extends FindParams {}
|
||||
export class AdminGetProductsProductVariantsVariantParams extends FindParams {}
|
||||
@@ -89,26 +90,26 @@ export class AdminGetProductsParams extends extendedFindParamsMixin({
|
||||
// @IsOptional()
|
||||
// price_list_id?: string[]
|
||||
|
||||
// /**
|
||||
// * Filter products by their associated product collection's ID.
|
||||
// */
|
||||
// @IsArray()
|
||||
// @IsOptional()
|
||||
// collection_id?: string[]
|
||||
/**
|
||||
* Filter products by their associated product collection's ID.
|
||||
*/
|
||||
@IsArray()
|
||||
@IsOptional()
|
||||
collection_id?: string[]
|
||||
|
||||
// /**
|
||||
// * Filter products by their associated tags' value.
|
||||
// */
|
||||
// @IsArray()
|
||||
// @IsOptional()
|
||||
// tags?: string[]
|
||||
/**
|
||||
* Filter products by their associated tags' value.
|
||||
*/
|
||||
@IsArray()
|
||||
@IsOptional()
|
||||
tags?: string[]
|
||||
|
||||
// /**
|
||||
// * Filter products by their associated product type's ID.
|
||||
// */
|
||||
// @IsArray()
|
||||
// @IsOptional()
|
||||
// type_id?: string[]
|
||||
/**
|
||||
* Filter products by their associated product type's ID.
|
||||
*/
|
||||
@IsArray()
|
||||
@IsOptional()
|
||||
type_id?: string[]
|
||||
|
||||
// /**
|
||||
// * Filter products by their associated sales channels' ID.
|
||||
@@ -172,6 +173,7 @@ export class AdminGetProductsVariantsParams extends extendedFindParamsMixin({
|
||||
limit: 50,
|
||||
offset: 0,
|
||||
}) {
|
||||
// TODO: Will search be handled the same way? Should it be part of the `findParams` class instead, or the mixin?
|
||||
/**
|
||||
* Search term to search product variants' title, sku, and products' title.
|
||||
*/
|
||||
@@ -186,14 +188,6 @@ export class AdminGetProductsVariantsParams extends extendedFindParamsMixin({
|
||||
@IsType([String, [String]])
|
||||
id?: string | string[]
|
||||
|
||||
// TODO: This should be part of the Mixin or base FindParams
|
||||
// /**
|
||||
// * The field to sort the data by. By default, the sort order is ascending. To change the order to descending, prefix the field name with `-`.
|
||||
// */
|
||||
// @IsString()
|
||||
// @IsOptional()
|
||||
// order?: string
|
||||
|
||||
/**
|
||||
* Filter product variants by whether their inventory is managed or not.
|
||||
*/
|
||||
@@ -295,21 +289,20 @@ export class AdminPostProductsReq {
|
||||
@IsEnum(ProductStatus)
|
||||
status?: ProductStatus = ProductStatus.DRAFT
|
||||
|
||||
// TODO: Add in next iteration
|
||||
// @IsOptional()
|
||||
// @Type(() => ProductTypeReq)
|
||||
// @ValidateNested()
|
||||
// type?: ProductTypeReq
|
||||
@IsOptional()
|
||||
@Type(() => ProductTypeReq)
|
||||
@ValidateNested()
|
||||
type?: ProductTypeReq
|
||||
|
||||
// @IsOptional()
|
||||
// @IsString()
|
||||
// collection_id?: string
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
collection_id?: string
|
||||
|
||||
// @IsOptional()
|
||||
// @Type(() => ProductTagReq)
|
||||
// @ValidateNested({ each: true })
|
||||
// @IsArray()
|
||||
// tags?: ProductTagReq[]
|
||||
@IsOptional()
|
||||
@Type(() => ProductTagReq)
|
||||
@ValidateNested({ each: true })
|
||||
@IsArray()
|
||||
tags?: ProductTagReq[]
|
||||
|
||||
// @IsOptional()
|
||||
// @Type(() => ProductProductCategoryReq)
|
||||
@@ -326,7 +319,6 @@ export class AdminPostProductsReq {
|
||||
// ])
|
||||
// sales_channels?: ProductSalesChannelReq[]
|
||||
|
||||
// TODO: I suggest we don't allow creation options and variants in 1 call, but rather do it through separate endpoints.
|
||||
@IsOptional()
|
||||
@Type(() => AdminPostProductsProductOptionsReq)
|
||||
@ValidateNested({ each: true })
|
||||
@@ -416,15 +408,15 @@ export class AdminPostProductsProductReq {
|
||||
// @ValidateNested()
|
||||
// type?: ProductTypeReq
|
||||
|
||||
// @IsOptional()
|
||||
// @IsString()
|
||||
// collection_id?: string
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
collection_id?: string
|
||||
|
||||
// @IsOptional()
|
||||
// @Type(() => ProductTagReq)
|
||||
// @ValidateNested({ each: true })
|
||||
// @IsArray()
|
||||
// tags?: ProductTagReq[]
|
||||
@IsOptional()
|
||||
@Type(() => ProductTagReq)
|
||||
@ValidateNested({ each: true })
|
||||
@IsArray()
|
||||
tags?: ProductTagReq[]
|
||||
|
||||
// @IsOptional()
|
||||
// @Type(() => ProductProductCategoryReq)
|
||||
@@ -558,12 +550,9 @@ export class AdminPostProductsProductVariantsReq {
|
||||
// @Type(() => ProductVariantPricesCreateReq)
|
||||
// prices: ProductVariantPricesCreateReq[]
|
||||
|
||||
// TODO: Think how these link to the `options` on the product-level
|
||||
// @IsOptional()
|
||||
// @Type(() => ProductVariantOptionReq)
|
||||
// @ValidateNested({ each: true })
|
||||
// @IsArray()
|
||||
// options?: ProductVariantOptionReq[] = []
|
||||
@IsOptional()
|
||||
@IsObject()
|
||||
options?: Record<string, string>
|
||||
}
|
||||
|
||||
export class AdminPostProductsProductVariantsVariantReq {
|
||||
@@ -642,20 +631,23 @@ export class AdminPostProductsProductVariantsVariantReq {
|
||||
// @Type(() => ProductVariantPricesUpdateReq)
|
||||
// prices?: ProductVariantPricesUpdateReq[]
|
||||
|
||||
// TODO: Align handling with the create case.
|
||||
// @Type(() => ProductVariantOptionReq)
|
||||
// @ValidateNested({ each: true })
|
||||
// @IsOptional()
|
||||
// @IsArray()
|
||||
// options?: ProductVariantOptionReq[] = []
|
||||
@IsOptional()
|
||||
@IsObject()
|
||||
options?: Record<string, string>
|
||||
}
|
||||
|
||||
export class AdminPostProductsProductOptionsReq {
|
||||
@IsString()
|
||||
title: string
|
||||
|
||||
@IsArray()
|
||||
values: string[]
|
||||
}
|
||||
|
||||
export class AdminPostProductsProductOptionsOptionReq {
|
||||
@IsString()
|
||||
title: string
|
||||
|
||||
@IsArray()
|
||||
values: string[]
|
||||
}
|
||||
@@ -545,14 +545,24 @@ export class FindPaginationParams {
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
limit?: number = 20
|
||||
|
||||
/**
|
||||
* {@inheritDoc RequestQueryFields.order}
|
||||
*/
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@Type(() => String)
|
||||
order?: string
|
||||
}
|
||||
|
||||
export function extendedFindParamsMixin({
|
||||
limit,
|
||||
offset,
|
||||
order,
|
||||
}: {
|
||||
limit?: number
|
||||
offset?: number
|
||||
order?: string
|
||||
} = {}): ClassConstructor<FindParams & FindPaginationParams> {
|
||||
/**
|
||||
* {@inheritDoc FindParams}
|
||||
@@ -575,6 +585,14 @@ export function extendedFindParamsMixin({
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
limit?: number = limit ?? 20
|
||||
|
||||
/**
|
||||
* {@inheritDoc FindPaginationParams.order}
|
||||
*/
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@Type(() => String)
|
||||
order?: string = order
|
||||
}
|
||||
|
||||
return FindExtendedPaginationParams
|
||||
|
||||
Reference in new issue
Block a user