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:
Stevche Radevski authored and GitHub committed 2024-03-08 14:03:59 +00:00
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[]
}
+18
View File
@@ -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