feat: Add skeleton for supporting product imports in BE (#8232)
This commit is contained in:
1 parent
55b55b6a92
commit
4b09be3a88
17 files changed
+204
-1178
No files matched your search
@@ -0,0 +1,34 @@
|
||||
import {
|
||||
WorkflowData,
|
||||
createWorkflow,
|
||||
transform,
|
||||
} from "@medusajs/workflows-sdk"
|
||||
import { WorkflowTypes } from "@medusajs/types"
|
||||
import { sendNotificationsStep } from "../../notification"
|
||||
|
||||
export const importProductsWorkflowId = "import-products"
|
||||
export const importProductsWorkflow = createWorkflow(
|
||||
importProductsWorkflowId,
|
||||
(
|
||||
input: WorkflowData<WorkflowTypes.ProductWorkflow.ImportProductsDTO>
|
||||
): WorkflowData<void> => {
|
||||
// validateImportCsvStep(input.fileContent)
|
||||
|
||||
const notifications = transform({ input }, (data) => {
|
||||
return [
|
||||
{
|
||||
// We don't need the recipient here for now, but if we want to push feed notifications to a specific user we could add it.
|
||||
to: "",
|
||||
channel: "feed",
|
||||
template: "admin-ui",
|
||||
data: {
|
||||
title: "Product import",
|
||||
description: `Product import of file ${data.input.filename} completed successfully!`,
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
sendNotificationsStep(notifications)
|
||||
}
|
||||
)
|
||||
@@ -21,3 +21,4 @@ export * from "./update-product-tags"
|
||||
export * from "./update-product-variants"
|
||||
export * from "./update-products"
|
||||
export * from "./export-products"
|
||||
export * from "./import-products"
|
||||
@@ -2,6 +2,7 @@ import { BatchMethodRequest } from "../../../common"
|
||||
import { ProductStatus } from "../common"
|
||||
|
||||
export interface AdminExportProductRequest {}
|
||||
export interface AdminImportProductRequest {}
|
||||
export interface AdminBatchProductRequest
|
||||
extends BatchMethodRequest<AdminCreateProduct, AdminUpdateProduct> {}
|
||||
|
||||
|
||||
@@ -35,6 +35,10 @@ export interface AdminExportProductResponse {
|
||||
workflow_id: string
|
||||
}
|
||||
|
||||
export interface AdminImportProductResponse {
|
||||
workflow_id: string
|
||||
}
|
||||
|
||||
export interface AdminBatchProductVariantResponse
|
||||
extends BatchMethodResponse<AdminProductVariant> {}
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface ImportProductsDTO {
|
||||
fileContent: string
|
||||
filename: string
|
||||
}
|
||||
@@ -3,3 +3,4 @@ export * from "./create-products"
|
||||
export * from "./update-product-variants"
|
||||
export * from "./update-products"
|
||||
export * from "./export-products"
|
||||
export * from "./import-products"
|
||||
@@ -0,0 +1,30 @@
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../../types/routing"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { MedusaError } from "@medusajs/utils"
|
||||
import { importProductsWorkflow } from "@medusajs/core-flows"
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<HttpTypes.AdminImportProductRequest>,
|
||||
res: MedusaResponse<HttpTypes.AdminImportProductResponse>
|
||||
) => {
|
||||
const input = req.file as Express.Multer.File
|
||||
|
||||
if (!input) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
"No file was uploaded for importing"
|
||||
)
|
||||
}
|
||||
|
||||
const { transaction } = await importProductsWorkflow(req.scope).run({
|
||||
input: {
|
||||
filename: input.originalname,
|
||||
fileContent: input.buffer.toString("utf-8"),
|
||||
},
|
||||
})
|
||||
|
||||
res.status(202).json({ workflow_id: transaction.transactionId })
|
||||
}
|
||||
@@ -28,6 +28,12 @@ import {
|
||||
AdminUpdateProductVariant,
|
||||
AdminUpdateVariantInventoryItem,
|
||||
} from "./validators"
|
||||
import multer from "multer"
|
||||
|
||||
// TODO: For now we keep the files in memory, as that's how they get passed to the workflows
|
||||
// This will need revisiting once we are closer to prod-ready v2, since with workflows and potentially
|
||||
// services on other machines using streams is not as simple as it used to be.
|
||||
const upload = multer({ storage: multer.memoryStorage() })
|
||||
|
||||
export const adminProductRoutesMiddlewares: MiddlewareRoute[] = [
|
||||
{
|
||||
@@ -81,12 +87,17 @@ export const adminProductRoutesMiddlewares: MiddlewareRoute[] = [
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
method: ["POST"],
|
||||
matcher: "/admin/products/import",
|
||||
middlewares: [upload.single("file")],
|
||||
},
|
||||
{
|
||||
method: ["GET"],
|
||||
matcher: "/admin/products/:id",
|
||||
middlewares: [
|
||||
unlessPath(
|
||||
/.*\/products\/(batch|export)/,
|
||||
/.*\/products\/(batch|export|import)/,
|
||||
validateAndTransformQuery(
|
||||
AdminGetProductParams,
|
||||
QueryConfig.retrieveProductQueryConfig
|
||||
@@ -99,11 +110,11 @@ export const adminProductRoutesMiddlewares: MiddlewareRoute[] = [
|
||||
matcher: "/admin/products/:id",
|
||||
middlewares: [
|
||||
unlessPath(
|
||||
/.*\/products\/(batch|export)/,
|
||||
/.*\/products\/(batch|export|import)/,
|
||||
validateAndTransformBody(AdminUpdateProduct)
|
||||
),
|
||||
unlessPath(
|
||||
/.*\/products\/(batch|export)/,
|
||||
/.*\/products\/(batch|export|import)/,
|
||||
validateAndTransformQuery(
|
||||
AdminGetProductParams,
|
||||
QueryConfig.retrieveProductQueryConfig
|
||||
@@ -116,7 +127,7 @@ export const adminProductRoutesMiddlewares: MiddlewareRoute[] = [
|
||||
matcher: "/admin/products/:id",
|
||||
middlewares: [
|
||||
unlessPath(
|
||||
/.*\/products\/(batch|export)/,
|
||||
/.*\/products\/(batch|export|import)/,
|
||||
validateAndTransformQuery(
|
||||
AdminGetProductParams,
|
||||
QueryConfig.retrieveProductQueryConfig
|
||||
|
||||
Reference in new issue
Block a user