feat: Add v2 product types endpoints (#6880)

Also adjusts the product type module APIs to follow the conventions
This commit is contained in:
Stevche Radevski
2024-03-29 19:27:10 +00:00
committed by GitHub
parent 1bcb13f892
commit 1a48fe0282
21 changed files with 833 additions and 41 deletions
@@ -0,0 +1,78 @@
import {
deleteProductTypesWorkflow,
updateProductTypesWorkflow,
} from "@medusajs/core-flows"
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "../../../../types/routing"
import { UpdateProductTypeDTO } from "@medusajs/types"
import { remoteQueryObjectFromString } from "@medusajs/utils"
import { refetchProductType } from "../helpers"
export const GET = async (
req: AuthenticatedMedusaRequest,
res: MedusaResponse
) => {
const remoteQuery = req.scope.resolve("remoteQuery")
const variables = { id: req.params.id }
const queryObject = remoteQueryObjectFromString({
entryPoint: "product_type",
variables,
fields: req.remoteQueryConfig.fields,
})
const [product_type] = await remoteQuery(queryObject)
res.status(200).json({ product_type })
}
export const POST = async (
req: AuthenticatedMedusaRequest<UpdateProductTypeDTO>,
res: MedusaResponse
) => {
const { result, errors } = await updateProductTypesWorkflow(req.scope).run({
input: {
selector: { id: req.params.id },
update: req.validatedBody,
},
throwOnError: false,
})
if (Array.isArray(errors) && errors[0]) {
throw errors[0].error
}
const productType = await refetchProductType(
result[0].id,
req.scope,
req.remoteQueryConfig.fields
)
res.status(200).json({ product_type: productType })
}
export const DELETE = async (
req: AuthenticatedMedusaRequest,
res: MedusaResponse
) => {
const id = req.params.id
const { errors } = await deleteProductTypesWorkflow(req.scope).run({
input: { ids: [id] },
throwOnError: false,
})
if (Array.isArray(errors) && errors[0]) {
throw errors[0].error
}
res.status(200).json({
id,
object: "product_type",
deleted: true,
})
}
@@ -0,0 +1,20 @@
import { MedusaContainer } from "@medusajs/types"
import { remoteQueryObjectFromString } from "@medusajs/utils"
export const refetchProductType = async (
productTypeId: string,
scope: MedusaContainer,
fields: string[]
) => {
const remoteQuery = scope.resolve("remoteQuery")
const queryObject = remoteQueryObjectFromString({
entryPoint: "product_type",
variables: {
filters: { id: productTypeId },
},
fields: fields,
})
const productTypes = await remoteQuery(queryObject)
return productTypes[0]
}
@@ -0,0 +1,69 @@
import * as QueryConfig from "./query-config"
import {
AdminGetProductTypesProductTypeParams,
AdminGetProductTypesParams,
AdminPostProductTypesProductTypeReq,
AdminPostProductTypesReq,
} from "./validators"
import { transformBody, transformQuery } from "../../../api/middlewares"
import { MiddlewareRoute } from "../../../loaders/helpers/routing/types"
import { authenticate } from "../../../utils/authenticate-middleware"
export const adminProductTypeRoutesMiddlewares: MiddlewareRoute[] = [
{
method: ["ALL"],
matcher: "/admin/product-types/*",
middlewares: [authenticate("admin", ["bearer", "session", "api-key"])],
},
{
method: ["GET"],
matcher: "/admin/product-types",
middlewares: [
transformQuery(
AdminGetProductTypesParams,
QueryConfig.listProductTypesTransformQueryConfig
),
],
},
{
method: ["GET"],
matcher: "/admin/product-types/:id",
middlewares: [
transformQuery(
AdminGetProductTypesProductTypeParams,
QueryConfig.retrieveProductTypeTransformQueryConfig
),
],
},
// Create/update/delete methods are new in v2
{
method: ["POST"],
matcher: "/admin/product-types",
middlewares: [
transformBody(AdminPostProductTypesReq),
transformQuery(
AdminGetProductTypesParams,
QueryConfig.retrieveProductTypeTransformQueryConfig
),
],
},
{
method: ["POST"],
matcher: "/admin/product-types/:id",
middlewares: [
transformBody(AdminPostProductTypesProductTypeReq),
transformQuery(
AdminGetProductTypesProductTypeParams,
QueryConfig.retrieveProductTypeTransformQueryConfig
),
],
},
{
method: ["DELETE"],
matcher: "/admin/product-types/:id",
middlewares: [],
},
]
@@ -0,0 +1,17 @@
export const defaultAdminProductTypeFields = [
"id",
"value",
"created_at",
"updated_at",
]
export const retrieveProductTypeTransformQueryConfig = {
defaults: defaultAdminProductTypeFields,
isList: false,
}
export const listProductTypesTransformQueryConfig = {
...retrieveProductTypeTransformQueryConfig,
defaultLimit: 20,
isList: true,
}
@@ -0,0 +1,63 @@
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "../../../types/routing"
import {
ContainerRegistrationKeys,
remoteQueryObjectFromString,
} from "@medusajs/utils"
import {
AdminGetProductTypesParams,
AdminPostProductTypesReq,
} from "./validators"
import { createProductTypesWorkflow } from "@medusajs/core-flows"
import { refetchProductType } from "./helpers"
export const GET = async (
req: AuthenticatedMedusaRequest<AdminGetProductTypesParams>,
res: MedusaResponse
) => {
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
const queryObject = remoteQueryObjectFromString({
entryPoint: "product",
variables: {
filters: req.filterableFields,
...req.remoteQueryConfig.pagination,
},
fields: req.remoteQueryConfig.fields,
})
const { rows: product_types, metadata } = await remoteQuery(queryObject)
res.json({
product_types: product_types,
count: metadata.count,
offset: metadata.skip,
limit: metadata.take,
})
}
export const POST = async (
req: AuthenticatedMedusaRequest<AdminPostProductTypesReq>,
res: MedusaResponse
) => {
const input = [req.validatedBody]
const { result, errors } = await createProductTypesWorkflow(req.scope).run({
input: { product_types: input },
throwOnError: false,
})
if (Array.isArray(errors) && errors[0]) {
throw errors[0].error
}
const productType = await refetchProductType(
result[0].id,
req.scope,
req.remoteQueryConfig.fields
)
res.status(200).json({ product_type: productType })
}
@@ -0,0 +1,113 @@
import { OperatorMap } from "@medusajs/types"
import { Type } from "class-transformer"
import {
IsNotEmpty,
IsObject,
IsOptional,
IsString,
ValidateNested,
} from "class-validator"
import { FindParams, extendedFindParamsMixin } from "../../../types/common"
import { OperatorMapValidator } from "../../../types/validators/operator-map"
export class AdminGetProductTypesProductTypeParams extends FindParams {}
/**
* Parameters used to filter and configure the pagination of the retrieved product types.
*/
export class AdminGetProductTypesParams extends extendedFindParamsMixin({
limit: 10,
offset: 0,
}) {
/**
* Term to search product product types by their title and handle.
*/
@IsString()
@IsOptional()
q?: string
/**
* Id to filter product product types by.
*/
@IsOptional()
@IsString()
id?: string | string[]
/**
* Title to filter product product types by.
*/
@IsOptional()
@IsString()
value?: string | string[] | OperatorMap<string>
/**
* Handle to filter product product types by.
*/
@IsOptional()
@IsString()
handle?: string | string[]
/**
* Date filters to apply on the product product types' `created_at` date.
*/
@IsOptional()
@ValidateNested()
@Type(() => OperatorMapValidator)
created_at?: OperatorMap<string>
/**
* Date filters to apply on the product product types' `updated_at` date.
*/
@IsOptional()
@ValidateNested()
@Type(() => OperatorMapValidator)
updated_at?: OperatorMap<string>
/**
* Date filters to apply on the product product types' `deleted_at` date.
*/
@ValidateNested()
@IsOptional()
@Type(() => OperatorMapValidator)
deleted_at?: OperatorMap<string>
// TODO: To be added in next iteration
// /**
// * Filter product types by their associated discount condition's ID.
// */
// @IsString()
// @IsOptional()
// discount_condition_id?: string
// Note: These are new in v2
// Additional filters from BaseFilterable
@IsOptional()
@ValidateNested({ each: true })
@Type(() => AdminGetProductTypesParams)
$and?: AdminGetProductTypesParams[]
@IsOptional()
@ValidateNested({ each: true })
@Type(() => AdminGetProductTypesParams)
$or?: AdminGetProductTypesParams[]
}
export class AdminPostProductTypesReq {
@IsString()
@IsNotEmpty()
value: string
@IsObject()
@IsOptional()
metadata?: Record<string, unknown>
}
export class AdminPostProductTypesProductTypeReq {
@IsString()
@IsOptional()
value?: string
@IsObject()
@IsOptional()
metadata?: Record<string, unknown>
}