From e0be2da15e622cae3d090319b91acb6dcc3697a8 Mon Sep 17 00:00:00 2001 From: Philip Korsholm <88927411+pKorsholm@users.noreply.github.com> Date: Fri, 17 Dec 2021 12:30:04 +0100 Subject: [PATCH] Feat: Client admin products (#930) * add exports in product * add product resource * fix failling tests * import reflect metadata Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com> --- .../medusa-js/src/resources/admin/index.ts | 2 + .../medusa-js/src/resources/admin/products.ts | 133 ++++++++++++++++++ packages/medusa/src/api/index.js | 1 + .../api/routes/admin/products/add-option.ts | 2 +- .../routes/admin/products/create-product.ts | 7 +- .../src/api/routes/admin/products/index.ts | 34 +++-- .../routes/admin/products/update-variant.ts | 2 +- packages/medusa/src/types/product.ts | 6 + 8 files changed, 172 insertions(+), 15 deletions(-) create mode 100644 packages/medusa-js/src/resources/admin/products.ts create mode 100644 packages/medusa/src/types/product.ts diff --git a/packages/medusa-js/src/resources/admin/index.ts b/packages/medusa-js/src/resources/admin/index.ts index 767af29f9a..1704c59607 100644 --- a/packages/medusa-js/src/resources/admin/index.ts +++ b/packages/medusa-js/src/resources/admin/index.ts @@ -7,6 +7,7 @@ import AdminDraftOrdersResource from "./draft-orders" import AdminGiftCardsResource from "./gift-cards" import AdminInvitesResource from "./invites" import AdminNotesResource from "./notes" +import AdminProductsResource from "./products" import AdminUsersResource from "./users" import AdminReturnsResource from "./returns" import AdminOrdersResource from "./orders" @@ -27,6 +28,7 @@ class Admin extends BaseResource { public giftCards = new AdminGiftCardsResource(this.client) public invites = new AdminInvitesResource(this.client) public notes = new AdminNotesResource(this.client) + public products = new AdminProductsResource(this.client) public users = new AdminUsersResource(this.client) public returns = new AdminReturnsResource(this.client) public orders = new AdminOrdersResource(this.client) diff --git a/packages/medusa-js/src/resources/admin/products.ts b/packages/medusa-js/src/resources/admin/products.ts new file mode 100644 index 0000000000..9dd2a9d0da --- /dev/null +++ b/packages/medusa-js/src/resources/admin/products.ts @@ -0,0 +1,133 @@ +import { + AdminGetNotesParams, + AdminNotesDeleteRes, + AdminNotesListRes, + AdminNotesRes, + AdminPostNotesNoteReq, + AdminPostNotesReq, + AdminPostProductsProductReq, + AdminPostProductsReq, + AdminProductsListTypesRes, + AdminProductsListTagsRes, + AdminProductsRes, + AdminPostProductsProductVariantsReq, + AdminPostProductsProductVariantsVariantReq, + AdminPostProductsProductOptionsReq, + AdminPostProductsProductOptionsOption, + AdminProductsDeleteVariantRes, + AdminProductsDeleteRes, + AdminProductsDeleteOptionRes, + AdminPostProductsProductMetadataReq, + AdminGetProductsParams, + AdminProductsListRes, +} from "@medusajs/medusa" +import { ResponsePromise } from "../../typings" +import BaseResource from "../base" + +class AdminProductsResource extends BaseResource { + create(payload: AdminPostProductsReq): ResponsePromise { + const path = `/admin/products/` + return this.client.request("POST", path, payload) + } + + retrieve(id: string): ResponsePromise { + const path = `/admin/products/${id}` + return this.client.request("GET", path) + } + + update( + id: string, + payload: AdminPostProductsProductReq + ): ResponsePromise { + const path = `/admin/products/${id}` + return this.client.request("POST", path, payload) + } + + delete(id: string): ResponsePromise { + const path = `/admin/products/${id}` + return this.client.request("DELETE", path) + } + + list(query: AdminGetProductsParams): ResponsePromise { + let path = `/admin/products` + + if (query) { + const queryString = Object.entries(query).map(([key, value]) => { + return typeof value !== "undefined" ? `${key}=${value}` : "" + }) + path = `/admin/products?${queryString.join("&")}` + } + + return this.client.request("GET", path) + } + + listTypes(): ResponsePromise { + const path = `/admin/products/types` + return this.client.request("GET", path) + } + + listTags(): ResponsePromise { + const path = `/admin/products/tag-usage` + return this.client.request("GET", path) + } + + setMetadata( + id: string, + payload: AdminPostProductsProductMetadataReq + ): ResponsePromise { + const path = `/admin/products/${id}/metadata` + return this.client.request("POST", path, payload) + } + + createVariant( + id: string, + payload: AdminPostProductsProductVariantsReq + ): ResponsePromise { + const path = `/admin/products/${id}/variants` + return this.client.request("POST", path, payload) + } + + updateVariant( + id: string, + variantId: string, + payload: AdminPostProductsProductVariantsVariantReq + ): ResponsePromise { + const path = `/admin/products/${id}/variants/${variantId}` + return this.client.request("POST", path, payload) + } + + deleteVariant( + id: string, + variantId: string + ): ResponsePromise { + const path = `/admin/products/${id}/variants/${variantId}` + return this.client.request("DELETE", path) + } + + addOption( + id: string, + payload: AdminPostProductsProductOptionsReq + ): ResponsePromise { + const path = `/admin/products/${id}/options` + return this.client.request("POST", path, payload) + } + + updateOption( + id: string, + optionId: string, + payload: AdminPostProductsProductOptionsOption + ): ResponsePromise { + const path = `/admin/products/${id}/options/${optionId}` + return this.client.request("POST", path, payload) + } + + deleteOption( + id: string, + optionId: string + ): ResponsePromise { + const path = `/admin/products/${id}/options/${optionId}` + return this.client.request("DELETE", path) + } +} + +export default AdminProductsResource diff --git a/packages/medusa/src/api/index.js b/packages/medusa/src/api/index.js index d847a8079f..6fb37c139c 100644 --- a/packages/medusa/src/api/index.js +++ b/packages/medusa/src/api/index.js @@ -27,6 +27,7 @@ export * from "./routes/admin/notes" export * from "./routes/admin/notifications" export * from "./routes/admin/shipping-profiles" export * from "./routes/admin/store" +export * from "./routes/admin/products" export * from "./routes/admin/users" export * from "./routes/admin/orders" export * from "./routes/admin/variants" diff --git a/packages/medusa/src/api/routes/admin/products/add-option.ts b/packages/medusa/src/api/routes/admin/products/add-option.ts index cfde9cd338..c91ebc8a91 100644 --- a/packages/medusa/src/api/routes/admin/products/add-option.ts +++ b/packages/medusa/src/api/routes/admin/products/add-option.ts @@ -52,7 +52,7 @@ export default async (req, res) => { res.json({ product }) } -class AdminPostProductsProductOptionsReq { +export class AdminPostProductsProductOptionsReq { @IsString() title: string } diff --git a/packages/medusa/src/api/routes/admin/products/create-product.ts b/packages/medusa/src/api/routes/admin/products/create-product.ts index fd08d38fd7..46a0da7eef 100644 --- a/packages/medusa/src/api/routes/admin/products/create-product.ts +++ b/packages/medusa/src/api/routes/admin/products/create-product.ts @@ -12,16 +12,13 @@ import { ValidateNested, } from "class-validator" import { EntityManager } from "typeorm" -import { - defaultAdminProductFields, - defaultAdminProductRelations, - ProductStatus, -} from "." +import { defaultAdminProductFields, defaultAdminProductRelations } from "." import { ProductService, ProductVariantService, ShippingProfileService, } from "../../../../services" +import { ProductStatus } from "../../../../types/product" import { XorConstraint } from "../../../../types/validators/xor" import { validator } from "../../../../utils/validator" diff --git a/packages/medusa/src/api/routes/admin/products/index.ts b/packages/medusa/src/api/routes/admin/products/index.ts index 88488165b7..a8fd9b54ca 100644 --- a/packages/medusa/src/api/routes/admin/products/index.ts +++ b/packages/medusa/src/api/routes/admin/products/index.ts @@ -1,7 +1,8 @@ import { Router } from "express" -import { Product } from "../../../.." +import { Product, ProductTag, ProductType } from "../../../.." import { DeleteResponse, PaginatedResponse } from "../../../../types/common" import middlewares from "../../../middlewares" +import "reflect-metadata" const route = Router() @@ -128,13 +129,6 @@ export const allowedAdminProductRelations = [ "collection", ] -export enum ProductStatus { - DRAFT = "draft", - PROPOSED = "proposed", - PUBLISHED = "published", - REJECTED = "rejected", -} - export type AdminProductsDeleteOptionRes = { option_id: string object: "option" @@ -159,6 +153,30 @@ export type AdminProductsListRes = PaginatedResponse & { products: Product[] } +export type AdminProductsListTypesRes = { + types: ProductType[] +} + +export type AdminProductsListTagsRes = { + types: ProductTag[] +} + export type AdminProductsRes = { product: Product } + +export * from "./add-option" +export * from "./create-product" +export * from "./create-variant" +export * from "./delete-option" +export * from "./delete-product" +export * from "./delete-variant" +export * from "./get-product" +export * from "./get-variants" +export * from "./list-products" +export * from "./list-tag-usage-count" +export * from "./list-types" +export * from "./set-metadata" +export * from "./update-option" +export * from "./update-product" +export * from "./update-variant" diff --git a/packages/medusa/src/api/routes/admin/products/update-variant.ts b/packages/medusa/src/api/routes/admin/products/update-variant.ts index 7a0cba8a7c..91bd89d16b 100644 --- a/packages/medusa/src/api/routes/admin/products/update-variant.ts +++ b/packages/medusa/src/api/routes/admin/products/update-variant.ts @@ -167,7 +167,7 @@ class ProductVariantPricesReq { sale_amount?: number } -class AdminPostProductsProductVariantsVariantReq { +export class AdminPostProductsProductVariantsVariantReq { @IsString() @IsOptional() title?: string diff --git a/packages/medusa/src/types/product.ts b/packages/medusa/src/types/product.ts new file mode 100644 index 0000000000..a00fdcf0d0 --- /dev/null +++ b/packages/medusa/src/types/product.ts @@ -0,0 +1,6 @@ +export enum ProductStatus { + DRAFT = "draft", + PROPOSED = "proposed", + PUBLISHED = "published", + REJECTED = "rejected", +}