diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 97fca34996..e3019cf472 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,7 @@ Thank you for considering contributing to Medusa! This document will outline how ## Issues before PRs -1. Before you start working on a change please make sure that there is an issue for what you will be working on. You can either find and [existing issue](https://github.com/medusajs/medusa/issues) or [open a new issue](https://github.com/medusajs/medusa/issues/new) if none exists. Doing this makes sure that others can contribute with thoughts or suggest alternatives, ultimately making sure that we only add changes that make +1. Before you start working on a change please make sure that there is an issue for what you will be working on. You can either find and [existing issue](https://github.com/medusajs/medusa/issues) or [open a new issue](https://github.com/medusajs/medusa/issues/new) if none exists. Doing this makes sure that others can contribute with thoughts or suggest alternatives, ultimately making sure that we only add changes that make 2. When you are ready to start working on a change you should first [fork the Medusa repo](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) and [branch out](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-and-deleting-branches-within-your-repository) from the `develop` branch. 3. Make your changes. @@ -21,17 +21,21 @@ Thank you for considering contributing to Medusa! This document will outline how ### Branches All changes should be part of a branch and submitted as a pull request - your branches should be prefixed with one of: + - `fix/` for bug fixes - `feat/` for features - `docs/` for documentation changes ### Commits + Strive towards keeping your commits small and isolated - this helps the reviewer understand what is going on and makes it easier to process your requests. ### Pull Requests -Once your changes are ready you must submit your branch as a pull request. Your pull request should be opened against the `develop` branch in the main Medusa repo. + +Once your changes are ready you must submit your branch as a pull request. Your pull request should be opened against the `develop` branch in the main Medusa repo. In your PR's description you should follow the structure: + - **What** - what changes are in this PR - **Why** - why are these changes relevant - **How** - how have the changes been implemented @@ -52,8 +56,8 @@ All PRs should include tests for the changes that are included. We have two type ### Documentation -- We generally encourage to document your changes through comments in your code. -- If you alter user-facing behaviour you must provide documentation for such changes. +- We generally encourage to document your changes through comments in your code. +- If you alter user-facing behaviour you must provide documentation for such changes. - All methods and endpoints should be documented using [JSDoc](https://jsdoc.app/) and [`swagger-inline`](https://www.npmjs.com/package/swagger-inline) ### Release diff --git a/README.md b/README.md index 62c86e2708..0d4905d0f8 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,7 @@ After these four steps and only a couple of minutes, you now have a complete com Write-ups for all features will be made available in [Github discussions](https://github.com/medusajs/medusa/discussions) prior to starting the implementation process. ### Q1 + - [x] Admin revamp - [x] Tax API - [x] Strategy pattern @@ -74,12 +75,13 @@ Write-ups for all features will be made available in [Github discussions](https: - [ ] Bulk import / export ### Q2 + - [ ] Extended Product API (custom fields, price lists, publishing control, and more) - [ ] Extended Order API (managing placed orders, improved inventory control, and more) - [ ] Sales Channel API - [ ] Multi-warehouse support - [ ] GraphQL API - + ## Setting up a storefront for your Medusa project Medusa is a headless commerce engine which means that it can be used for any type of digital commerce experience - you may use it as the backend for an app, a voice application, social commerce experiences or a traditional e-commerce website, you may even want to integrate Medusa into your own software to enable commerce functionality. All of these are use cases that Medusa supports - to learn more read the documentation or reach out. diff --git a/docs/api/store-spec3.yaml b/docs/api/store-spec3.yaml index a9c4648621..fd11e6d96c 100644 --- a/docs/api/store-spec3.yaml +++ b/docs/api/store-spec3.yaml @@ -38,7 +38,7 @@ tags: - name: Product Variant x-resourceId: product_variant servers: - - url: 'https://api.medusa-commerce.com/store' + - url: "https://api.medusa-commerce.com/store" paths: /auth: post: @@ -51,14 +51,14 @@ paths: tags: - Auth responses: - '200': + "200": description: OK content: application/json: schema: properties: customer: - $ref: '#/components/schemas/customer' + $ref: "#/components/schemas/customer" requestBody: content: application/json: @@ -81,7 +81,7 @@ paths: tags: - Auth responses: - '200': + "200": description: OK get: operationId: GetAuth @@ -91,15 +91,15 @@ paths: tags: - Auth responses: - '200': + "200": description: OK content: application/json: schema: properties: customer: - $ref: '#/components/schemas/customer' - '/auth/{email}': + $ref: "#/components/schemas/customer" + "/auth/{email}": get: operationId: GetAuthEmail summary: Check if email has account @@ -114,7 +114,7 @@ paths: tags: - Auth responses: - '200': + "200": description: OK content: application/json: @@ -122,7 +122,7 @@ paths: properties: exists: type: boolean - '/collections/{id}': + "/collections/{id}": get: operationId: GetCollectionsCollection summary: Retrieve a Product Collection @@ -137,14 +137,14 @@ paths: tags: - Collection responses: - '200': + "200": description: OK content: application/json: schema: properties: collection: - $ref: '#/components/schemas/product_collection' + $ref: "#/components/schemas/product_collection" /collections: get: operationId: GetCollections @@ -168,14 +168,14 @@ paths: tags: - Collection responses: - '200': + "200": description: OK content: application/json: schema: properties: collection: - $ref: '#/components/schemas/product_collection' + $ref: "#/components/schemas/product_collection" /customers/me/addresses: post: operationId: PostCustomersCustomerAddresses @@ -192,18 +192,18 @@ paths: address: description: The Address to add to the Customer. anyOf: - - $ref: '#/components/schemas/address' + - $ref: "#/components/schemas/address" tags: - Customer responses: - '200': + "200": description: A successful response content: application/json: schema: properties: customer: - $ref: '#/components/schemas/customer' + $ref: "#/components/schemas/customer" /customers: post: operationId: PostCustomers @@ -213,14 +213,14 @@ paths: tags: - Customer responses: - '200': + "200": description: OK content: application/json: schema: properties: customer: - $ref: '#/components/schemas/customer' + $ref: "#/components/schemas/customer" requestBody: content: application/json: @@ -247,7 +247,7 @@ paths: phone: type: string description: The Customer's phone number. - '/customers/me/addresses/{address_id}': + "/customers/me/addresses/{address_id}": delete: operationId: DeleteCustomersCustomerAddressesAddress summary: Delete an Address @@ -263,14 +263,14 @@ paths: tags: - Customer responses: - '200': + "200": description: OK content: application/json: schema: properties: customer: - $ref: '#/components/schemas/customer' + $ref: "#/components/schemas/customer" post: operationId: PostCustomersCustomerAddressesAddress summary: Update a Shipping Address @@ -291,18 +291,18 @@ paths: address: description: The updated Address. anyOf: - - $ref: '#/components/schemas/address' + - $ref: "#/components/schemas/address" tags: - Customer responses: - '200': + "200": description: OK content: application/json: schema: properties: customer: - $ref: '#/components/schemas/customer' + $ref: "#/components/schemas/customer" /customers/me: get: operationId: GetCustomersCustomer @@ -314,14 +314,14 @@ paths: tags: - Customer responses: - '200': + "200": description: OK content: application/json: schema: properties: customer: - $ref: '#/components/schemas/customer' + $ref: "#/components/schemas/customer" post: operationId: PostCustomersCustomer summary: Update Customer details @@ -341,7 +341,7 @@ paths: billing_address: description: The Address to be used for billing purposes. anyOf: - - $ref: '#/components/schemas/address' + - $ref: "#/components/schemas/address" password: description: The Customer's password. type: string @@ -357,14 +357,14 @@ paths: tags: - Customer responses: - '200': + "200": description: OK content: application/json: schema: properties: customer: - $ref: '#/components/schemas/customer' + $ref: "#/components/schemas/customer" /customers/me/payment-methods: get: operationId: GetCustomersCustomerPaymentMethods @@ -377,7 +377,7 @@ paths: tags: - Customer responses: - '200': + "200": description: OK content: application/json: @@ -431,7 +431,7 @@ paths: tags: - Customer responses: - '200': + "200": description: OK content: application/json: @@ -444,12 +444,12 @@ paths: description: The offset for pagination. type: integer limit: - description: 'The maxmimum number of Orders to return,' + description: "The maxmimum number of Orders to return," type: integer orders: type: array items: - $ref: '#/components/schemas/order' + $ref: "#/components/schemas/order" /customers/password-token: post: operationId: PostCustomersCustomerPasswordToken @@ -462,7 +462,7 @@ paths: tags: - Customer responses: - '204': + "204": description: OK requestBody: content: @@ -486,14 +486,14 @@ paths: tags: - Customer responses: - '200': + "200": description: OK content: application/json: schema: properties: customer: - $ref: '#/components/schemas/customer' + $ref: "#/components/schemas/customer" requestBody: content: application/json: @@ -513,7 +513,7 @@ paths: password: type: string description: The new password to set for the Customer. - '/gift-cards/{code}': + "/gift-cards/{code}": get: operationId: GetGiftCardsCode summary: Retrieve Gift Card by Code @@ -528,7 +528,7 @@ paths: tags: - Gift Card responses: - '200': + "200": description: OK content: application/json: @@ -543,8 +543,8 @@ paths: balance: description: The current balanace of the Gift Card region: - $ref: '#/components/schemas/region' - '/carts/{id}/shipping-methods': + $ref: "#/components/schemas/region" + "/carts/{id}/shipping-methods": post: operationId: PostCartsCartShippingMethod description: Adds a Shipping Method to the Cart. @@ -559,14 +559,14 @@ paths: schema: type: string responses: - '200': + "200": description: A successful response content: application/json: schema: properties: cart: - $ref: '#/components/schemas/cart' + $ref: "#/components/schemas/cart" requestBody: content: application/json: @@ -585,7 +585,7 @@ paths: process the fulfillment of the order. Look at the documentation for your installed fulfillment providers to find out what to send. - '/carts/{id}/taxes': + "/carts/{id}/taxes": post: summary: Calculate Cart Taxes operationId: PostCartsCartTaxes @@ -602,7 +602,7 @@ paths: tags: - Cart responses: - '200': + "200": description: A cart object with the tax_total field populated content: application/json: @@ -611,8 +611,8 @@ paths: - type: object properties: cart: - $ref: '#/components/schemas/cart' - '/carts/{id}/complete': + $ref: "#/components/schemas/cart" + "/carts/{id}/complete": post: summary: Complete a Cart operationId: PostCartsCartComplete @@ -633,7 +633,7 @@ paths: tags: - Cart responses: - '200': + "200": description: >- If a cart was successfully authorized, but requires further action from the user the response body will contain the cart with an @@ -646,15 +646,15 @@ paths: - type: object properties: order: - $ref: '#/components/schemas/order' + $ref: "#/components/schemas/order" - type: object properties: cart: - $ref: '#/components/schemas/cart' + $ref: "#/components/schemas/cart" - type: object properties: cart: - $ref: '#/components/schemas/swap' + $ref: "#/components/schemas/swap" /carts: post: summary: Create a Cart @@ -700,15 +700,15 @@ paths: tags: - Cart responses: - '200': + "200": description: Successfully created a new Cart content: application/json: schema: properties: cart: - $ref: '#/components/schemas/cart' - '/carts/{id}/line-items': + $ref: "#/components/schemas/cart" + "/carts/{id}/line-items": post: operationId: PostCartsCartLineItems summary: Add a Line Item @@ -725,14 +725,14 @@ paths: tags: - Cart responses: - '200': + "200": description: OK content: application/json: schema: properties: cart: - $ref: '#/components/schemas/cart' + $ref: "#/components/schemas/cart" requestBody: content: application/json: @@ -755,7 +755,7 @@ paths: description: >- An optional key-value map with additional details about the Line Item. - '/carts/{id}/payment-sessions': + "/carts/{id}/payment-sessions": post: operationId: PostCartsCartPaymentSessions summary: Initialize Payment Sessions @@ -772,15 +772,15 @@ paths: tags: - Cart responses: - '200': + "200": description: OK content: application/json: schema: properties: cart: - $ref: '#/components/schemas/cart' - '/carts/{id}/discounts/{code}': + $ref: "#/components/schemas/cart" + "/carts/{id}/discounts/{code}": delete: operationId: DeleteCartsCartDiscountsDiscount description: Removes a Discount from a Cart. @@ -801,15 +801,15 @@ paths: tags: - Cart responses: - '200': + "200": description: OK content: application/json: schema: properties: cart: - $ref: '#/components/schemas/cart' - '/carts/{id}/line-items/{line_id}': + $ref: "#/components/schemas/cart" + "/carts/{id}/line-items/{line_id}": delete: operationId: DeleteCartsCartLineItemsItem summary: Delete a Line Item @@ -830,14 +830,14 @@ paths: tags: - Cart responses: - '200': + "200": description: OK content: application/json: schema: properties: cart: - $ref: '#/components/schemas/cart' + $ref: "#/components/schemas/cart" post: operationId: PostCartsCartLineItemsItem summary: Update a Line Item @@ -858,14 +858,14 @@ paths: tags: - Cart responses: - '200': + "200": description: OK content: application/json: schema: properties: cart: - $ref: '#/components/schemas/cart' + $ref: "#/components/schemas/cart" requestBody: content: application/json: @@ -877,7 +877,7 @@ paths: quantity: type: integer description: The quantity to set the Line Item to. - '/carts/{id}/payment-sessions/{provider_id}': + "/carts/{id}/payment-sessions/{provider_id}": delete: operationId: DeleteCartsCartPaymentSessionsSession summary: Delete a Payment Session @@ -902,14 +902,14 @@ paths: tags: - Cart responses: - '200': + "200": description: OK content: application/json: schema: properties: cart: - $ref: '#/components/schemas/cart' + $ref: "#/components/schemas/cart" post: operationId: PostCartsCartPaymentSessionUpdate summary: Update a Payment Session @@ -930,14 +930,14 @@ paths: tags: - Cart responses: - '200': + "200": description: OK content: application/json: schema: properties: cart: - $ref: '#/components/schemas/cart' + $ref: "#/components/schemas/cart" requestBody: content: application/json: @@ -949,7 +949,7 @@ paths: data: type: object description: The data to update the payment session with. - '/carts/{id}': + "/carts/{id}": get: operationId: GetCartsCart summary: Retrieve a Cart @@ -964,15 +964,15 @@ paths: tags: - Cart responses: - '200': + "200": description: OK content: application/json: schema: properties: cart: - $ref: '#/components/schemas/cart' - '/carts/{id}/payment-sessions/{provider_id}/refresh': + $ref: "#/components/schemas/cart" + "/carts/{id}/payment-sessions/{provider_id}/refresh": post: operationId: PostCartsCartPaymentSessionsSession summary: Refresh a Payment Session @@ -997,15 +997,15 @@ paths: tags: - Cart responses: - '200': + "200": description: OK content: application/json: schema: properties: cart: - $ref: '#/components/schemas/cart' - '/carts/{id}/payment-session': + $ref: "#/components/schemas/cart" + "/carts/{id}/payment-session": post: operationId: PostCartsCartPaymentSession summary: Select a Payment Session @@ -1022,14 +1022,14 @@ paths: tags: - Cart responses: - '200': + "200": description: OK content: application/json: schema: properties: cart: - $ref: '#/components/schemas/cart' + $ref: "#/components/schemas/cart" requestBody: content: application/json: @@ -1041,7 +1041,7 @@ paths: provider_id: type: string description: The id of the Payment Provider. - '/store/carts/{id}': + "/store/carts/{id}": post: operationId: PostCartsCartPaymentMethodUpdate summary: Update a Cart" @@ -1065,19 +1065,19 @@ paths: description: The id of the Payment Provider. data: type: object - description: '' + description: "" tags: - Cart responses: - '200': + "200": description: OK content: application/json: schema: properties: cart: - $ref: '#/components/schemas/cart' - '/orders/cart/{cart_id}': + $ref: "#/components/schemas/cart" + "/orders/cart/{cart_id}": get: operationId: GetOrdersOrderCartId summary: Retrieves Order by Cart id @@ -1094,15 +1094,15 @@ paths: tags: - Order responses: - '200': + "200": description: OK content: application/json: schema: properties: order: - $ref: '#/components/schemas/order' - '/orders/{id}': + $ref: "#/components/schemas/order" + "/orders/{id}": get: operationId: GetOrdersOrder summary: Retrieves an Order @@ -1117,14 +1117,14 @@ paths: tags: - Order responses: - '200': + "200": description: OK content: application/json: schema: properties: customer: - $ref: '#/components/schemas/customer' + $ref: "#/components/schemas/customer" /orders: get: operationId: GetOrders @@ -1149,15 +1149,15 @@ paths: tags: - Order responses: - '200': + "200": description: OK content: application/json: schema: properties: order: - $ref: '#/components/schemas/order' - '/products/{id}': + $ref: "#/components/schemas/order" + "/products/{id}": get: operationId: GetProductsProduct summary: Retrieves a Product @@ -1172,14 +1172,14 @@ paths: tags: - Product responses: - '200': + "200": description: OK content: application/json: schema: properties: product: - $ref: '#/components/schemas/product' + $ref: "#/components/schemas/product" /products: get: operationId: GetProducts @@ -1265,7 +1265,7 @@ paths: tags: - Product responses: - '200': + "200": description: OK content: application/json: @@ -1278,13 +1278,13 @@ paths: description: The offset for pagination. type: integer limit: - description: 'The maxmimum number of Products to return,' + description: "The maxmimum number of Products to return," type: integer products: type: array items: - $ref: '#/components/schemas/product' - '/regions/{id}': + $ref: "#/components/schemas/product" + "/regions/{id}": get: operationId: GetRegionsRegion summary: Retrieves a Region @@ -1299,14 +1299,14 @@ paths: tags: - Region responses: - '200': + "200": description: OK content: application/json: schema: properties: region: - $ref: '#/components/schemas/region' + $ref: "#/components/schemas/region" /regions: get: operationId: GetRegions @@ -1315,7 +1315,7 @@ paths: tags: - Region responses: - '200': + "200": description: OK content: application/json: @@ -1328,13 +1328,13 @@ paths: description: The offset for pagination. type: integer limit: - description: 'The maxmimum number of regions to return,' + description: "The maxmimum number of regions to return," type: integer regions: type: array items: - $ref: '#/components/schemas/region' - '/return-reasons/{id}': + $ref: "#/components/schemas/region" + "/return-reasons/{id}": get: operationId: GetReturnReasonsReason summary: Retrieve a Return Reason @@ -1349,14 +1349,14 @@ paths: tags: - Return Reason responses: - '200': + "200": description: OK content: application/json: schema: properties: return_reason: - $ref: '#/components/schemas/return_reason' + $ref: "#/components/schemas/return_reason" /return-reasons: get: operationId: GetReturnReasons @@ -1365,7 +1365,7 @@ paths: tags: - Return Reason responses: - '200': + "200": description: OK content: application/json: @@ -1374,7 +1374,7 @@ paths: return_reasons: type: array items: - $ref: '#/components/schemas/return_reason' + $ref: "#/components/schemas/return_reason" /returns: post: operationId: PostReturns @@ -1422,14 +1422,14 @@ paths: tags: - Return responses: - '200': + "200": description: OK content: application/json: schema: properties: return: - $ref: '#/components/schemas/return' + $ref: "#/components/schemas/return" /shipping-options: get: operationId: GetShippingOptions @@ -1456,7 +1456,7 @@ paths: tags: - Shipping Option responses: - '200': + "200": description: OK content: application/json: @@ -1465,8 +1465,8 @@ paths: shipping_options: type: array items: - $ref: '#/components/schemas/shipping_option' - '/shipping-options/{cart_id}': + $ref: "#/components/schemas/shipping_option" + "/shipping-options/{cart_id}": get: operationId: GetShippingOptionsCartId summary: Retrieve Shipping Options for Cart @@ -1481,7 +1481,7 @@ paths: tags: - Shipping Option responses: - '200': + "200": description: OK content: application/json: @@ -1490,7 +1490,7 @@ paths: shipping_options: type: array items: - $ref: '#/components/schemas/shipping_option' + $ref: "#/components/schemas/shipping_option" /swaps: post: operationId: PostSwaps @@ -1552,15 +1552,15 @@ paths: tags: - Swap responses: - '200': + "200": description: OK content: application/json: schema: properties: swap: - $ref: '#/components/schemas/swap' - '/swaps/{cart_id}': + $ref: "#/components/schemas/swap" + "/swaps/{cart_id}": get: operationId: GetSwapsSwapCartId summary: Retrieve Swap by Cart id @@ -1575,15 +1575,15 @@ paths: tags: - Swap responses: - '200': + "200": description: OK content: application/json: schema: properties: swap: - $ref: '#/components/schemas/swap' - '/variants/{variant_id}': + $ref: "#/components/schemas/swap" + "/variants/{variant_id}": get: operationId: GetVariantsVariant summary: Retrieve a Product Variant @@ -1598,14 +1598,14 @@ paths: tags: - Product Variant responses: - '200': + "200": description: OK content: application/json: schema: properties: variant: - $ref: '#/components/schemas/product_variant' + $ref: "#/components/schemas/product_variant" /variants: get: operationId: GetVariants @@ -1634,7 +1634,7 @@ paths: tags: - Product Variant responses: - '200': + "200": description: OK content: application/json: @@ -1643,7 +1643,7 @@ paths: variants: type: array items: - $ref: '#/components/schemas/product_variant' + $ref: "#/components/schemas/product_variant" components: schemas: address: @@ -1670,7 +1670,7 @@ components: country_code: type: string country: - $ref: '#/components/schemas/country' + $ref: "#/components/schemas/country" cart: title: Cart description: Represents a user cart @@ -1683,43 +1683,43 @@ components: billing_address_id: type: string billing_address: - $ref: '#/components/schemas/address' + $ref: "#/components/schemas/address" shipping_address_id: type: string shipping_address: - $ref: '#/components/schemas/address' + $ref: "#/components/schemas/address" items: type: array items: - $ref: '#/components/schemas/line_item' + $ref: "#/components/schemas/line_item" region_id: type: string region: - $ref: '#/components/schemas/region' + $ref: "#/components/schemas/region" discounts: type: array items: - $ref: '#/components/schemas/region' + $ref: "#/components/schemas/region" gift_cards: type: array items: - $ref: '#/components/schemas/gift_card' + $ref: "#/components/schemas/gift_card" customer_id: type: string customer: - $ref: '#/components/schemas/customer' + $ref: "#/components/schemas/customer" payment_session: - $ref: '#/components/schemas/payment_session' + $ref: "#/components/schemas/payment_session" payment_sessions: type: array items: - $ref: '#/components/schemas/payment_session' + $ref: "#/components/schemas/payment_session" payment: - $ref: '#/components/schemas/payment' + $ref: "#/components/schemas/payment" shipping_methods: type: array items: - $ref: '#/components/schemas/shipping_method' + $ref: "#/components/schemas/shipping_method" type: type: string enum: @@ -1786,19 +1786,19 @@ components: images: type: array items: - $ref: '#/components/schemas/claim_image' + $ref: "#/components/schemas/claim_image" claim_order_id: type: string item_id: type: string item: description: The Line Item that the claim refers to - $ref: '#/components/schemas/line_item' + $ref: "#/components/schemas/line_item" variant_id: type: string variant: description: The Product Variant that is claimed. - $ref: '#/components/schemas/product_variant' + $ref: "#/components/schemas/product_variant" reason: description: The reason for the claim type: string @@ -1808,7 +1808,7 @@ components: - production_failure - other note: - description: 'An optional note about the claim, for additional information' + description: "An optional note about the claim, for additional information" type: string quantity: description: >- @@ -1819,7 +1819,7 @@ components: description: User defined tags for easy filtering and grouping. type: array items: - $ref: '#/components/schemas/claim_tag' + $ref: "#/components/schemas/claim_tag" created_at: type: string format: date-time @@ -1868,36 +1868,36 @@ components: description: The items that have been claimed type: array items: - $ref: '#/components/schemas/claim_item' + $ref: "#/components/schemas/claim_item" additional_items: description: >- Refers to the new items to be shipped when the claim order has the type `replace` type: array items: - $ref: '#/components/schemas/line_item' + $ref: "#/components/schemas/line_item" order_id: description: The id of the order that the claim comes from. type: string return_order: description: Holds information about the return if the claim is to be returned - $ref: '#/components/schemas/return' + $ref: "#/components/schemas/return" shipping_address_id: description: The id of the address that the new items should be shipped to type: string shipping_address: description: The address that the new items should be shipped to - $ref: '#/components/schemas/address' + $ref: "#/components/schemas/address" shipping_methods: description: The shipping methods that the claim order will be shipped with. type: array items: - $ref: '#/components/schemas/shipping_method' + $ref: "#/components/schemas/shipping_method" fulfillments: description: The fulfillments of the new items to be shipped type: array items: - $ref: '#/components/schemas/fulfillment' + $ref: "#/components/schemas/fulfillment" refund_amount: description: The amount that will be refunded in conjunction with the claim type: integer @@ -2012,11 +2012,11 @@ components: The id of the Shipping Option that the custom shipping option overrides anyOf: - - $ref: '#/components/schemas/shipping_option' + - $ref: "#/components/schemas/shipping_option" cart_id: description: The id of the Cart that the custom shipping option is attached to anyOf: - - $ref: '#/components/schemas/cart' + - $ref: "#/components/schemas/cart" created_at: description: The date with timezone at which the resource was created. type: string @@ -2070,11 +2070,11 @@ components: billing_address: description: The Customer's billing address. anyOf: - - $ref: '#/components/schemas/address' + - $ref: "#/components/schemas/address" shipping_addresses: type: array items: - $ref: '#/components/schemas/address' + $ref: "#/components/schemas/address" first_name: type: string last_name: @@ -2132,7 +2132,7 @@ components: description: A set of Products that the discount can be used for. type: array items: - $ref: '#/components/schemas/product' + $ref: "#/components/schemas/product" created_at: description: The date with timezone at which the resource was created. type: string @@ -2171,7 +2171,7 @@ components: rule: description: The Discount Rule that governs the behaviour of the Discount anyOf: - - $ref: '#/components/schemas/discount_rule' + - $ref: "#/components/schemas/discount_rule" is_disabled: description: >- Whether the Discount has been disabled. Disabled discounts cannot be @@ -2194,7 +2194,7 @@ components: description: The Regions in which the Discount can be used type: array items: - $ref: '#/components/schemas/region' + $ref: "#/components/schemas/region" usage_limit: description: The maximum number of times that a discount can be used. type: integer @@ -2234,12 +2234,12 @@ components: type: string cart: anyOf: - - $ref: '#/components/schemas/cart' + - $ref: "#/components/schemas/cart" order_id: type: string order: anyOf: - - $ref: '#/components/schemas/order' + - $ref: "#/components/schemas/order" canceled_at: type: string format: date-time @@ -2277,7 +2277,7 @@ components: item: description: The Line Item that the Fulfillment Item references. anyOf: - - $ref: '#/components/schemas/line_item' + - $ref: "#/components/schemas/line_item" quantity: description: The quantity of the Line Item that is included in the Fulfillment. type: integer @@ -2332,7 +2332,7 @@ components: about how many of each Line Item has been fulfilled. type: array items: - $ref: '#/components/schemas/fulfillment_item' + $ref: "#/components/schemas/fulfillment_item" tracking_links: description: >- The Tracking Links that can be used to track the status of the @@ -2340,7 +2340,7 @@ components: Provider. type: array items: - $ref: '#/components/schemas/tracking_link' + $ref: "#/components/schemas/tracking_link" tracking_numbers: deprecated: true description: >- @@ -2391,7 +2391,7 @@ components: gift_card: description: The Gift Card that was used in the transaction. anyOf: - - $ref: '#/components/schemas/gift_card' + - $ref: "#/components/schemas/gift_card" order_id: description: The id of the Order that the Gift Card was used to pay for. type: string @@ -2429,7 +2429,7 @@ components: region: description: The Region in which the Gift Card is available. anyOf: - - $ref: '#/components/schemas/region' + - $ref: "#/components/schemas/region" order_id: description: The id of the Order that the Gift Card was purchased in. type: string @@ -2577,7 +2577,7 @@ components: variant: description: The Product Variant contained in the Line Item. anyOf: - - $ref: '#/components/schemas/product_variant' + - $ref: "#/components/schemas/product_variant" quantity: description: The quantity of the content in the Line Item. type: integer @@ -2642,7 +2642,7 @@ components: region: description: The Region that the Money Amount is defined for. anyOf: - - $ref: '#/components/schemas/region' + - $ref: "#/components/schemas/region" created_at: description: The date with timezone at which the resource was created. type: string @@ -2678,7 +2678,7 @@ components: author: description: The author of the note. anyOf: - - $ref: '#/components/schemas/user' + - $ref: "#/components/schemas/user" created_at: description: The date with timezone at which the resource was created. type: string @@ -2737,7 +2737,7 @@ components: customer: description: The Customer that the Notification was sent to. anyOf: - - $ref: '#/components/schemas/customer' + - $ref: "#/components/schemas/customer" to: description: >- The address that the Notification was sent to. This will usually be @@ -2758,7 +2758,7 @@ components: Notification. type: array items: - $ref: '#/components/schemas/notification_resend' + $ref: "#/components/schemas/notification_resend" provider_id: description: The id of the Notification Provider that handles the Notification. type: string @@ -2877,76 +2877,76 @@ components: discounts: type: array items: - $ref: '#/components/schemas/discount' + $ref: "#/components/schemas/discount" email: type: string billing_address_id: type: string billing_address: anyOf: - - $ref: '#/components/schemas/address' + - $ref: "#/components/schemas/address" shipping_address_id: type: string shipping_address: anyOf: - - $ref: '#/components/schemas/address' + - $ref: "#/components/schemas/address" items: type: array items: - $ref: '#/components/schemas/line_item' + $ref: "#/components/schemas/line_item" region_id: type: string region: anyOf: - - $ref: '#/components/schemas/region' + - $ref: "#/components/schemas/region" gift_cards: type: array items: - $ref: '#/components/schemas/gift_card' + $ref: "#/components/schemas/gift_card" customer_id: type: string customer: anyOf: - - $ref: '#/components/schemas/customer' + - $ref: "#/components/schemas/customer" payment_session: anyOf: - - $ref: '#/components/schemas/payment_session' + - $ref: "#/components/schemas/payment_session" payment_sessions: type: array items: - $ref: '#/components/schemas/payment_session' + $ref: "#/components/schemas/payment_session" payments: type: array items: - $ref: '#/components/schemas/payment' + $ref: "#/components/schemas/payment" shipping_methods: type: array items: - $ref: '#/components/schemas/shipping_method' + $ref: "#/components/schemas/shipping_method" fulfillments: type: array items: - $ref: '#/components/schemas/fulfillment' + $ref: "#/components/schemas/fulfillment" returns: type: array items: - $ref: '#/components/schemas/return' + $ref: "#/components/schemas/return" claims: type: array items: - $ref: '#/components/schemas/claim_order' + $ref: "#/components/schemas/claim_order" refunds: type: array items: - $ref: '#/components/schemas/refund' + $ref: "#/components/schemas/refund" swaps: type: array items: - $ref: '#/components/schemas/refund' + $ref: "#/components/schemas/refund" gift_card_transactions: type: array items: - $ref: '#/components/schemas/gift_card_transaction' + $ref: "#/components/schemas/gift_card_transaction" canceled_at: type: string format: date-time @@ -3212,7 +3212,7 @@ components: description: The Product Option Values that are defined for the Product Option. type: array items: - $ref: '#/components/schemas/product_option_value' + $ref: "#/components/schemas/product_option_value" product_id: description: The id of the Product that the Product Option is defined for. type: string @@ -3372,7 +3372,7 @@ components: Region. type: array items: - $ref: '#/components/schemas/money_amount' + $ref: "#/components/schemas/money_amount" sku: description: >- The unique stock keeping unit used to identify the Product Variant. @@ -3453,7 +3453,7 @@ components: description: The Product Option Values specified for the Product Variant. type: array items: - $ref: '#/components/schemas/product_option_value' + $ref: "#/components/schemas/product_option_value" created_at: description: The date with timezone at which the resource was created. type: string @@ -3511,7 +3511,7 @@ components: description: Images of the Product type: array items: - $ref: '#/components/schemas/image' + $ref: "#/components/schemas/image" thumbnail: description: A URL to an image file that can be used to identify the Product. type: string @@ -3522,14 +3522,14 @@ components: Option Values. type: array items: - $ref: '#/components/schemas/product_option' + $ref: "#/components/schemas/product_option" variants: description: >- The Product Variants that belong to the Product. Each will have a unique combination of Product Option Values. type: array items: - $ref: '#/components/schemas/product_variant' + $ref: "#/components/schemas/product_variant" profile_id: description: >- The id of the Shipping Profile that the Product belongs to. Shipping @@ -3583,16 +3583,16 @@ components: type: description: The Product Type of the Product (e.g. "Clothing") anyOf: - - $ref: '#/components/schemas/product_type' + - $ref: "#/components/schemas/product_type" collection: description: The Product Collection that the Product belongs to (e.g. "SS20") anyOf: - - $ref: '#/components/schemas/product_collection' + - $ref: "#/components/schemas/product_collection" tags: description: The Product Tags assigned to the Product. type: array items: - $ref: '#/components/schemas/product_tag' + $ref: "#/components/schemas/product_tag" created_at: description: The date with timezone at which the resource was created. type: string @@ -3684,21 +3684,21 @@ components: description: The countries that are included in the Region. type: array items: - $ref: '#/components/schemas/country' + $ref: "#/components/schemas/country" payment_providers: description: >- The Payment Providers that can be used to process Payments in the Region. type: array items: - $ref: '#/components/schemas/payment_provider' + $ref: "#/components/schemas/payment_provider" fulfillment_providers: description: >- The Fulfillment Providers that can be used to fulfill orders in the Region. type: array items: - $ref: '#/components/schemas/fulfillment_provider' + $ref: "#/components/schemas/fulfillment_provider" created_at: description: The date with timezone at which the resource was created. type: string @@ -3730,7 +3730,7 @@ components: item: description: The Line Item that the Return Item references. anyOf: - - $ref: '#/components/schemas/line_item' + - $ref: "#/components/schemas/line_item" quantity: description: The quantity of the Line Item that is included in the Return. type: integer @@ -3748,7 +3748,7 @@ components: reason: description: The reason for returning the item. anyOf: - - $ref: '#/components/schemas/return_reason' + - $ref: "#/components/schemas/return_reason" note: description: An optional note with additional details about the Return. type: string @@ -3810,7 +3810,7 @@ components: items: description: >- The Return Items that will be shipped back to the warehouse. type: - array items: $ref: + array items: $ref: swap_id: description: The id of the Swap that the Return is a part of. type: string @@ -3825,7 +3825,7 @@ components: The Shipping Method that will be used to send the Return back. Can be null if the Customer facilitates the return shipment themselves. anyOf: - - $ref: '#/components/schemas/shipping_method' + - $ref: "#/components/schemas/shipping_method" shipping_data: description: >- Data about the return shipment as provided by the Fulfilment @@ -3876,7 +3876,7 @@ components: shipping_option: description: The Shipping Option that the Shipping Method is built from. anyOf: - - $ref: '#/components/schemas/shipping_option' + - $ref: "#/components/schemas/shipping_option" order_id: description: The id of the Order that the Shipping Method is used on. type: string @@ -3962,7 +3962,7 @@ components: region: description: The id of the Region that the Shipping Option belongs to. anyOf: - - $ref: '#/components/schemas/region' + - $ref: "#/components/schemas/region" profile_id: description: >- The id of the Shipping Profile that the Shipping Option belongs to. @@ -4000,7 +4000,7 @@ components: be available for a Cart. type: array items: - $ref: '#/components/schemas/shipping_option_requirement' + $ref: "#/components/schemas/shipping_option_requirement" data: description: >- The data needed for the Fulfillment Provider to identify the @@ -4051,7 +4051,7 @@ components: description: The Products that the Shipping Profile defines Shipping Options for. type: array items: - $ref: '#/components/schemas/product' + $ref: "#/components/schemas/product" shipping_options: description: >- The Shipping Options that can be used to fulfill the Products in the @@ -4059,7 +4059,7 @@ components: type: array items: anyOf: - - $ref: '#/components/schemas/shipping_option' + - $ref: "#/components/schemas/shipping_option" created_at: description: The date with timezone at which the resource was created. type: string @@ -4105,7 +4105,7 @@ components: type: object store: title: Store - description: 'Holds settings for the Store, such as name, currencies, etc.' + description: "Holds settings for the Store, such as name, currencies, etc." x-resourceId: store properties: id: @@ -4123,7 +4123,7 @@ components: description: The currencies that are enabled for the Store. type: array items: - $ref: '#/components/schemas/currency' + $ref: "#/components/schemas/currency" swap_link_template: description: >- A template to generate Swap links from use {{cart_id}} to include @@ -4189,22 +4189,22 @@ components: description: The new Line Items to ship to the Customer. type: array items: - $ref: '#/components/schemas/line_item' + $ref: "#/components/schemas/line_item" return_order: description: The Return that is issued for the return part of the Swap. anyOf: - - $ref: '#/components/schemas/return' + - $ref: "#/components/schemas/return" fulfillments: description: The Fulfillments used to send the new Line Items. type: array items: - $ref: '#/components/schemas/fulfillment' + $ref: "#/components/schemas/fulfillment" payment: description: >- The Payment authorized when the Swap requires an additional amount to be charged from the Customer. anyOf: - - $ref: '#/components/schemas/payment' + - $ref: "#/components/schemas/payment" difference_due: description: >- The difference that is paid or refunded as a result of the Swap. May @@ -4216,17 +4216,17 @@ components: The Address to send the new Line Items to - in most cases this will be the same as the shipping address on the Order. anyOf: - - $ref: '#/components/schemas/address' + - $ref: "#/components/schemas/address" shipping_methods: description: The Shipping Methods used to fulfill the addtional items purchased. type: array items: - $ref: '#/components/schemas/shipping_method' + $ref: "#/components/schemas/shipping_method" cart_id: description: The id of the Cart that the Customer will use to confirm the Swap. type: string allow_backorder: - description: 'If true, swaps can be completed with items out of stock' + description: "If true, swaps can be completed with items out of stock" type: boolean confirmed_at: description: >- @@ -4247,7 +4247,7 @@ components: type: string format: date-time no_notification: - description: 'If set to true, no notification will be sent related to this swap' + description: "If set to true, no notification will be sent related to this swap" type: boolean metadata: description: An optional key-value map with additional information. @@ -4385,7 +4385,7 @@ components: last_name: description: The Customer's billing address. anyOf: - - $ref: '#/components/schemas/address' + - $ref: "#/components/schemas/address" created_at: type: string format: date-time diff --git a/docs/content/add-plugins/strapi.md b/docs/content/add-plugins/strapi.md index 637595a45d..2b4dfeda27 100644 --- a/docs/content/add-plugins/strapi.md +++ b/docs/content/add-plugins/strapi.md @@ -120,8 +120,8 @@ yarn global add create-strapi-app@3.6.8 create-strapi-app strapi-medusa --template https://github.com/Deathwish98/strapi-medusa-template.git ``` -> Note: The plugin expects node version to be '>= 10.16.0 and <=14.x.x', otherwise it will throw an error. +> Note: The plugin expects node version to be '>= 10.16.0 and <=14.x.x', otherwise it will throw an error. After running the command, you have a full Strapi project configured to synchronize with Medusa. Upon the initial start of the Strapi server, all the required models will be created. They will correlate with models from Medusa to allow for two-way synchronization. diff --git a/docs/content/add-plugins/stripe.md b/docs/content/add-plugins/stripe.md index 0fb742204a..297be64155 100644 --- a/docs/content/add-plugins/stripe.md +++ b/docs/content/add-plugins/stripe.md @@ -8,7 +8,6 @@ - ### Introduction Handling payments is at the core of every commerce system; it allows us to run our businesses. Consequently, a vast landscape of payment providers has developed, each with varying cost models, implementational specifications, and analytical capabilities. diff --git a/docs/content/advanced/backend/endpoints/add-admin.md b/docs/content/advanced/backend/endpoints/add-admin.md index b04d18dcae..bcfff56878 100644 --- a/docs/content/advanced/backend/endpoints/add-admin.md +++ b/docs/content/advanced/backend/endpoints/add-admin.md @@ -24,7 +24,7 @@ export default () => { router.get("/admin/hello", (req, res) => { res.json({ - message: "Welcome to Your Store!" + message: "Welcome to Your Store!", }) }) @@ -53,8 +53,8 @@ Then, create an object that will hold the CORS configurations: ```js const corsOptions = { - origin: projectConfig.admin_cors.split(","), - credentials: true, + origin: projectConfig.admin_cors.split(","), + credentials: true, } ``` @@ -64,7 +64,7 @@ Finally, for each route you add, create an `OPTIONS` request: router.options("/admin/hello", cors(corsOptions)) router.get("/admin/hello", (req, res) => { //... -}); +}) ``` ## Multiple Endpoints @@ -76,13 +76,13 @@ You can add more than one endpoints in `src/api/index.js`: ```js router.get("/admin/hello", (req, res) => { res.json({ - message: "Welcome to Your Store!" + message: "Welcome to Your Store!", }) }) router.get("/admin/bye", (req, res) => { res.json({ - message: "Come back again!" + message: "Come back again!", }) }) ``` @@ -97,7 +97,7 @@ To do that with the previous example, first, create the file `src/api/hello.js` export default (router) => { router.get("/admin/hello", (req, res) => { res.json({ - message: "Welcome to Your Store!" + message: "Welcome to Your Store!", }) }) } @@ -111,7 +111,7 @@ Next, create the file `src/api/bye.js` with the following content: export default (router) => { router.get("/admin/bye", (req, res) => { res.json({ - message: "Come back again!" + message: "Come back again!", }) }) } @@ -148,17 +148,15 @@ You can retrieve any registered service in your endpoint using `req.scope.resolv Here’s an example of an endpoint that retrieves the count of products in your store: ```js -router.get('/admin/products/count', (req, res) => { - const productService = req.scope.resolve('productService') +router.get("/admin/products/count", (req, res) => { + const productService = req.scope.resolve("productService") - productService - .count() - .then((count) => { - res.json({ - count - }) - }) + productService.count().then((count) => { + res.json({ + count, + }) }) +}) ``` The `productService` has a `count` method that returns a Promise. This Promise resolves to the count of the products. You return a JSON of the product count. @@ -170,13 +168,13 @@ Protected routes are routes that should be accessible by logged-in users only. To make a route protected, first, import the `authenticate` middleware: ```js -import authenticate from '@medusajs/medusa/dist/api/middlewares/authenticate' +import authenticate from "@medusajs/medusa/dist/api/middlewares/authenticate" ``` Then, add the middleware to your route: ```js -router.get('/store/products/count', authenticate(), (req, res) => { +router.get("/store/products/count", authenticate(), (req, res) => { //... }) ``` diff --git a/docs/content/advanced/backend/endpoints/add-storefront.md b/docs/content/advanced/backend/endpoints/add-storefront.md index 3fff09c195..abd2c676e6 100644 --- a/docs/content/advanced/backend/endpoints/add-storefront.md +++ b/docs/content/advanced/backend/endpoints/add-storefront.md @@ -24,7 +24,7 @@ export default () => { router.get("/store/hello", (req, res) => { res.json({ - message: "Welcome to My Store!" + message: "Welcome to My Store!", }) }) @@ -47,13 +47,13 @@ You can add more than one endpoints in `src/api/index.js`: ```js router.get("/store/hello", (req, res) => { res.json({ - message: "Welcome to My Store!" + message: "Welcome to My Store!", }) }) router.get("/store/bye", (req, res) => { res.json({ - message: "Come back again!" + message: "Come back again!", }) }) ``` @@ -68,7 +68,7 @@ To do that with the previous example, first, create the file `src/api/hello.js` export default (router) => { router.get("/store/hello", (req, res) => { res.json({ - message: "Welcome to My Store!" + message: "Welcome to My Store!", }) }) } @@ -82,7 +82,7 @@ Next, create the file `src/api/bye.js` with the following content: export default (router) => { router.get("/store/bye", (req, res) => { res.json({ - message: "Come back again!" + message: "Come back again!", }) }) } @@ -119,17 +119,15 @@ You can retrieve any registered service in your endpoint using `req.scope.resolv Here’s an example of an endpoint that retrieves the count of products in your store: ```js -router.get('/store/products/count', (req, res) => { - const productService = req.scope.resolve('productService') +router.get("/store/products/count", (req, res) => { + const productService = req.scope.resolve("productService") - productService - .count() - .then((count) => { - res.json({ - count - }) - }) + productService.count().then((count) => { + res.json({ + count, + }) }) +}) ``` The `productService` has a `count` method that returns a Promise. This Promise resolves to the count of the products. You return a JSON of the product count. @@ -141,13 +139,13 @@ Protected routes are routes that should be accessible by logged-in customers onl To make a route protected, first, import the `authenticate` middleware: ```js -import authenticate from '@medusajs/medusa/dist/api/middlewares/authenticate' +import authenticate from "@medusajs/medusa/dist/api/middlewares/authenticate" ``` Then, add the middleware to your route: ```jsx -router.get('/store/products/count', authenticate(), (req, res) => { +router.get("/store/products/count", authenticate(), (req, res) => { //... }) ``` diff --git a/docs/content/advanced/backend/services/create-service.md b/docs/content/advanced/backend/services/create-service.md index 5615872889..6ddfc01017 100644 --- a/docs/content/advanced/backend/services/create-service.md +++ b/docs/content/advanced/backend/services/create-service.md @@ -1,7 +1,5 @@ --- - title: Create a Service - --- # Create a Service @@ -31,7 +29,7 @@ To create a service, you should create a JavaScript file in `src/services` to ho For example, if you want to create a service `helloService`, create the file `hello.js` in `src/services` with the following content: ```js -import { BaseService } from "medusa-interfaces"; +import { BaseService } from "medusa-interfaces" class HelloService extends BaseService { getMessage() { @@ -39,7 +37,7 @@ class HelloService extends BaseService { } } -export default HelloService; +export default HelloService ``` ## Service Constructor @@ -85,10 +83,10 @@ constructor({ helloService }) { To use your custom service in an endpoint, you can use `req.scope.resolve` passing it the service’s registration name: ```js -const helloService = req.scope.resolve('helloService'); +const helloService = req.scope.resolve("helloService") res.json({ - message: helloService.getMessage() + message: helloService.getMessage(), }) ``` diff --git a/docs/content/introduction.md b/docs/content/introduction.md index c86212baac..ff50dfeaac 100644 --- a/docs/content/introduction.md +++ b/docs/content/introduction.md @@ -1,7 +1,5 @@ --- - title: Introduction - --- ## Architecture overview @@ -18,11 +16,11 @@ Your Medusa server will include all functionalities related to your store’s ch ### Admin Dashboard -The admin dashboard is accessible by store operators. Store operators can use the admin dashboard to view, create, and modify data such as orders and products. +The admin dashboard is accessible by store operators. Store operators can use the admin dashboard to view, create, and modify data such as orders and products. Medusa provides a beautiful [admin dashboard](https://demo.medusajs.com) that you can use right off the bat. Our admin dashboard provides a lot of functionalities to manage your store including Order management, product management, user management and more. - You can also create your own admin dashboard by utilizing the [Admin REST APIs](https://docs.medusajs.com/api/admin/auth). +You can also create your own admin dashboard by utilizing the [Admin REST APIs](https://docs.medusajs.com/api/admin/auth). ### Storefront diff --git a/packages/medusa-js/src/resources/admin/index.ts b/packages/medusa-js/src/resources/admin/index.ts index 854f901f56..372c69d783 100644 --- a/packages/medusa-js/src/resources/admin/index.ts +++ b/packages/medusa-js/src/resources/admin/index.ts @@ -24,6 +24,7 @@ import AdminRegionsResource from "./regions" import AdminNotificationsResource from "./notifications" import AdminUploadsResource from "./uploads" import AdminProductTagsResource from "./product-tags" +import AdminPriceListResource from "./price-lists" class Admin extends BaseResource { public auth = new AdminAuthResource(this.client) @@ -35,6 +36,7 @@ class Admin extends BaseResource { public giftCards = new AdminGiftCardsResource(this.client) public invites = new AdminInvitesResource(this.client) public notes = new AdminNotesResource(this.client) + public priceLists = new AdminPriceListResource(this.client) public products = new AdminProductsResource(this.client) public productTags = new AdminProductTagsResource(this.client) public productTypes = new AdminProductTypesResource(this.client) diff --git a/packages/medusa-js/src/resources/admin/price-lists.ts b/packages/medusa-js/src/resources/admin/price-lists.ts new file mode 100644 index 0000000000..fce3dadd0d --- /dev/null +++ b/packages/medusa-js/src/resources/admin/price-lists.ts @@ -0,0 +1,99 @@ +import { + AdminPostPriceListPricesPricesReq, + AdminPostPriceListsPriceListPriceListReq, + AdminPostPriceListsPriceListReq, + AdminPriceListDeleteRes, + AdminPriceListRes, + AdminGetPriceListPaginationParams, + AdminPriceListsListRes, + AdminDeletePriceListPricesPricesReq, + AdminPriceListDeleteBatchRes, + AdminGetPriceListsPriceListProductsParams, +} from "@medusajs/medusa" +import qs from "qs" +import { ResponsePromise } from "../../typings" +import BaseResource from "../base" + +class AdminPriceListResource extends BaseResource { + create( + payload: AdminPostPriceListsPriceListReq, + customHeaders: Record = {} + ): ResponsePromise { + const path = `/admin/price-lists` + return this.client.request("POST", path, payload, {}, customHeaders) + } + + update( + id: string, + payload: AdminPostPriceListsPriceListPriceListReq, + customHeaders: Record = {} + ): ResponsePromise { + const path = `/admin/price-lists/${id}` + return this.client.request("POST", path, payload, {}, customHeaders) + } + + delete( + id: string, + customHeaders: Record = {} + ): ResponsePromise { + const path = `/admin/price-lists/${id}` + return this.client.request("DELETE", path, {}, {}, customHeaders) + } + + retrieve( + id: string, + customHeaders: Record = {} + ): ResponsePromise { + const path = `/admin/price-lists/${id}` + return this.client.request("GET", path, {}, {}, customHeaders) + } + + list( + query?: AdminGetPriceListPaginationParams, + customHeaders: Record = {} + ): ResponsePromise { + let path = `/admin/price-lists/` + + if (query) { + const queryString = qs.stringify(query) + path = `/admin/price-lists?${queryString}` + } + + return this.client.request("GET", path, {}, {}, customHeaders) + } + + listProducts( + id: string, + query?: AdminGetPriceListsPriceListProductsParams, + customHeaders: Record = {} + ): ResponsePromise { + let path = `/admin/price-lists/${id}/products` + + if (query) { + const queryString = qs.stringify(query) + path = `/admin/price-lists/${id}/products?${queryString}` + } + + return this.client.request("GET", path, {}, {}, customHeaders) + } + + addPrices( + id: string, + payload: AdminPostPriceListPricesPricesReq, + customHeaders: Record = {} + ): ResponsePromise { + const path = `/admin/price-lists/${id}/prices/batch` + return this.client.request("POST", path, payload, {}, customHeaders) + } + + deletePrices( + id: string, + payload: AdminDeletePriceListPricesPricesReq, + customHeaders: Record = {} + ): ResponsePromise { + const path = `/admin/price-lists/${id}/prices/batch` + return this.client.request("DELETE", path, payload, {}, customHeaders) + } +} + +export default AdminPriceListResource diff --git a/packages/medusa-js/src/resources/customers.ts b/packages/medusa-js/src/resources/customers.ts index 47e1a7b268..c1e5f03940 100644 --- a/packages/medusa-js/src/resources/customers.ts +++ b/packages/medusa-js/src/resources/customers.ts @@ -22,7 +22,10 @@ class CustomerResource extends BaseResource { * @param customHeaders * @return { ResponsePromise} */ - create(payload: StorePostCustomersReq, customHeaders: Record = {}): ResponsePromise { + create( + payload: StorePostCustomersReq, + customHeaders: Record = {} + ): ResponsePromise { const path = `/store/customers` return this.client.request("POST", path, payload, {}, customHeaders) } @@ -32,7 +35,9 @@ class CustomerResource extends BaseResource { * @param customHeaders * @return {ResponsePromise} */ - retrieve(customHeaders: Record = {}): ResponsePromise { + retrieve( + customHeaders: Record = {} + ): ResponsePromise { const path = `/store/customers/me` return this.client.request("GET", path, {}, {}, customHeaders) } @@ -45,7 +50,8 @@ class CustomerResource extends BaseResource { */ update( payload: StorePostCustomersCustomerReq, - customHeaders: Record = {}): ResponsePromise { + customHeaders: Record = {} + ): ResponsePromise { const path = `/store/customers/me` return this.client.request("POST", path, payload, {}, customHeaders) } @@ -58,7 +64,8 @@ class CustomerResource extends BaseResource { */ listOrders( params?: StoreGetCustomersCustomerOrdersParams, - customHeaders: Record = {}): ResponsePromise { + customHeaders: Record = {} + ): ResponsePromise { let path = `/store/customers/me/orders` if (params) { const query = qs.stringify(params) @@ -77,7 +84,8 @@ class CustomerResource extends BaseResource { */ resetPassword( payload: StorePostCustomersCustomerPasswordTokenReq, - customHeaders: Record = {}): ResponsePromise { + customHeaders: Record = {} + ): ResponsePromise { const path = `/store/customers/password-reset` return this.client.request("POST", path, payload, {}, customHeaders) } diff --git a/packages/medusa-react/mocks/data/fixtures.json b/packages/medusa-react/mocks/data/fixtures.json index 9d32ddae57..5223dacbca 100644 --- a/packages/medusa-react/mocks/data/fixtures.json +++ b/packages/medusa-react/mocks/data/fixtures.json @@ -1076,6 +1076,18 @@ "deleted_at": null, "metadata": null }, + "price_list": { + "id": "pl_ZXDBABWJVW6115VEMZXDBAB", + "name": "test price list", + "description": "test price list", + "type": "products", + "status": "active", + "starts_at": null, + "ends_at": null, + "created_at": "2021-03-16T21:24:35.828Z", + "updated_at": "2021-03-16T21:24:35.828Z", + "deleted_at": null + }, "note": { "id": "note_01F0ZXDBAB9KVZWJVW6115VEM7", "value": "customer contacted", diff --git a/packages/medusa-react/mocks/handlers/admin.ts b/packages/medusa-react/mocks/handlers/admin.ts index 2848430e4c..271012c0f7 100644 --- a/packages/medusa-react/mocks/handlers/admin.ts +++ b/packages/medusa-react/mocks/handlers/admin.ts @@ -170,6 +170,89 @@ export const adminHandlers = [ ) }), + rest.post("/admin/price-lists/", (req, res, ctx) => { + const body = req.body as Record + return res( + ctx.status(200), + ctx.json({ + price_list: { + ...fixtures.get("price_list"), + ...body, + }, + }) + ) + }), + + rest.get("/admin/price-lists/", (req, res, ctx) => { + return res( + ctx.status(200), + ctx.json({ + price_lists: fixtures.list("price_list"), + count: 2, + offset: 0, + limit: 10, + }) + ) + }), + + rest.get("/admin/price-lists/:id", (req, res, ctx) => { + return res( + ctx.status(200), + ctx.json({ + price_list: fixtures.get("price_list"), + }) + ) + }), + + rest.post("/admin/price-lists/:id", (req, res, ctx) => { + const body = req.body as Record + return res( + ctx.status(200), + ctx.json({ + price_list: { + ...fixtures.get("price_list"), + ...body, + id: req.params.id, + }, + }) + ) + }), + + rest.delete("/admin/price-lists/:id", (req, res, ctx) => { + return res( + ctx.status(200), + ctx.json({ + id: req.params.id, + object: "price_list", + deleted: true, + }) + ) + }), + + rest.delete("/admin/price-lists/:id/prices/batch", (req, res, ctx) => { + const body = req.body as Record + return res( + ctx.status(200), + ctx.json({ + ids: body.price_ids, + object: "money-amount", + deleted: true, + }) + ) + }), + + rest.post("/admin/price-lists/:id/prices/batch", (req, res, ctx) => { + return res( + ctx.status(200), + ctx.json({ + price_list: { + ...fixtures.get("price_list"), + id: req.params.id, + }, + }) + ) + }), + rest.post("/admin/return-reasons/", (req, res, ctx) => { const body = req.body as Record return res( diff --git a/packages/medusa-react/src/hooks/admin/index.ts b/packages/medusa-react/src/hooks/admin/index.ts index 984ad38311..01968c7e2d 100644 --- a/packages/medusa-react/src/hooks/admin/index.ts +++ b/packages/medusa-react/src/hooks/admin/index.ts @@ -10,6 +10,7 @@ export * from "./orders" export * from "./products" export * from "./product-tags" export * from "./product-types" +export * from "./price-lists" export * from "./return-reasons" export * from "./regions" export * from "./shipping-options" diff --git a/packages/medusa-react/src/hooks/admin/price-lists/index.ts b/packages/medusa-react/src/hooks/admin/price-lists/index.ts new file mode 100644 index 0000000000..a494946b87 --- /dev/null +++ b/packages/medusa-react/src/hooks/admin/price-lists/index.ts @@ -0,0 +1,2 @@ +export * from "./queries" +export * from "./mutations" diff --git a/packages/medusa-react/src/hooks/admin/price-lists/mutations.ts b/packages/medusa-react/src/hooks/admin/price-lists/mutations.ts new file mode 100644 index 0000000000..634d349cbe --- /dev/null +++ b/packages/medusa-react/src/hooks/admin/price-lists/mutations.ts @@ -0,0 +1,108 @@ +import { + AdminPriceListRes, + AdminPostPriceListsPriceListPriceListReq, + AdminPostPriceListsPriceListReq, + AdminPostPriceListPricesPricesReq, + AdminDeletePriceListPricesPricesReq, + AdminPriceListDeleteRes, + AdminPriceListDeleteBatchRes, +} from "@medusajs/medusa" +import { Response } from "@medusajs/medusa-js" +import { useMutation, UseMutationOptions, useQueryClient } from "react-query" +import { useMedusa } from "../../../contexts/medusa" +import { buildOptions } from "../../utils/buildOptions" +import { adminPriceListKeys } from "./queries" + +export const useAdminCreatePriceList = ( + options?: UseMutationOptions< + Response, + Error, + AdminPostPriceListsPriceListReq + > +) => { + const { client } = useMedusa() + const queryClient = useQueryClient() + return useMutation( + (payload: AdminPostPriceListsPriceListReq) => + client.admin.priceLists.create(payload), + buildOptions(queryClient, adminPriceListKeys.lists(), options) + ) +} + +export const useAdminUpdatePriceList = ( + id: string, + options?: UseMutationOptions< + Response, + Error, + AdminPostPriceListsPriceListPriceListReq + > +) => { + const { client } = useMedusa() + const queryClient = useQueryClient() + + return useMutation( + (payload: AdminPostPriceListsPriceListPriceListReq) => + client.admin.priceLists.update(id, payload), + buildOptions( + queryClient, + [adminPriceListKeys.detail(id), adminPriceListKeys.lists()], + options + ) + ) +} + +export const useAdminDeletePriceList = ( + id: string, + options?: UseMutationOptions, Error, void> +) => { + const { client } = useMedusa() + const queryClient = useQueryClient() + + return useMutation( + () => client.admin.priceLists.delete(id), + buildOptions( + queryClient, + [adminPriceListKeys.detail(id), adminPriceListKeys.lists()], + options + ) + ) +} + +export const useAdminCreatePriceListPrices = ( + id: string, + options?: UseMutationOptions< + Response, + Error, + AdminPostPriceListPricesPricesReq + > +) => { + const { client } = useMedusa() + const queryClient = useQueryClient() + return useMutation( + (payload: AdminPostPriceListPricesPricesReq) => + client.admin.priceLists.addPrices(id, payload), + buildOptions(queryClient, adminPriceListKeys.lists(), options) + ) +} + +export const useAdminDeletePriceListPrices = ( + id: string, + options?: UseMutationOptions< + Response, + Error, + AdminDeletePriceListPricesPricesReq + > +) => { + const { client } = useMedusa() + const queryClient = useQueryClient() + + return useMutation( + (payload: AdminDeletePriceListPricesPricesReq) => + client.admin.priceLists.deletePrices(id, payload), + buildOptions( + queryClient, + [adminPriceListKeys.detail(id), adminPriceListKeys.lists()], + options + ) + ) +} diff --git a/packages/medusa-react/src/hooks/admin/price-lists/queries.ts b/packages/medusa-react/src/hooks/admin/price-lists/queries.ts new file mode 100644 index 0000000000..8259615886 --- /dev/null +++ b/packages/medusa-react/src/hooks/admin/price-lists/queries.ts @@ -0,0 +1,70 @@ +import { + AdminGetPriceListsPriceListProductsParams, + AdminGetPriceListPaginationParams, + AdminPriceListsListRes, + AdminPriceListRes, + AdminProductsListRes, +} from "@medusajs/medusa" +import { Response } from "@medusajs/medusa-js" +import { useQuery } from "react-query" +import { useMedusa } from "../../../contexts" +import { UseQueryOptionsWrapper } from "../../../types" +import { queryKeysFactory } from "../../utils/index" + +const ADMIN_PRICE_LISTS_QUERY_KEY = `admin_price_lists` as const + +export const adminPriceListKeys = queryKeysFactory(ADMIN_PRICE_LISTS_QUERY_KEY) + +type PriceListQueryKeys = typeof adminPriceListKeys + +export const useAdminPriceLists = ( + query?: AdminGetPriceListPaginationParams, + options?: UseQueryOptionsWrapper< + Response, + Error, + ReturnType + > +) => { + const { client } = useMedusa() + const { data, ...rest } = useQuery( + adminPriceListKeys.list(query), + () => client.admin.priceLists.list(query), + options + ) + return { ...data, ...rest } as const +} + +export const useAdminPriceListProducts = ( + id: string, + query?: AdminGetPriceListsPriceListProductsParams, + options?: UseQueryOptionsWrapper< + Response, + Error, + ReturnType + > +) => { + const { client } = useMedusa() + const { data, ...rest } = useQuery( + adminPriceListKeys.detail(id), + () => client.admin.priceLists.listProducts(id, query), + options + ) + return { ...data, ...rest } as const +} + +export const useAdminPriceList = ( + id: string, + options?: UseQueryOptionsWrapper< + Response, + Error, + ReturnType + > +) => { + const { client } = useMedusa() + const { data, ...rest } = useQuery( + adminPriceListKeys.detail(id), + () => client.admin.priceLists.retrieve(id), + options + ) + return { ...data, ...rest } as const +} diff --git a/packages/medusa-react/test/hooks/admin/price-lists/mutations.test.ts b/packages/medusa-react/test/hooks/admin/price-lists/mutations.test.ts new file mode 100644 index 0000000000..f2bdea588b --- /dev/null +++ b/packages/medusa-react/test/hooks/admin/price-lists/mutations.test.ts @@ -0,0 +1,139 @@ +import { + useAdminCreatePriceList, + useAdminCreatePriceListPrices, + useAdminDeletePriceList, + useAdminDeletePriceListPrices, + useAdminUpdatePriceList, +} from "../../../../src" +import { renderHook } from "@testing-library/react-hooks" +import { fixtures } from "../../../../mocks/data" +import { createWrapper } from "../../../utils" + +import { PriceListType } from "@medusajs/medusa/dist/types/price-list" + +describe("useAdminCreatePriceList hook", () => { + test("creates a price list and returns it", async () => { + const priceList = { + name: "talked to customer", + type: PriceListType.SALE, + description: "test", + prices: [], + } + + const { result, waitFor } = renderHook(() => useAdminCreatePriceList(), { + wrapper: createWrapper(), + }) + + result.current.mutate(priceList) + + await waitFor(() => result.current.isSuccess) + + expect(result.current.data.response.status).toEqual(200) + expect(result.current.data.price_list).toEqual( + expect.objectContaining({ + ...fixtures.get("price_list"), + ...priceList, + }) + ) + }) +}) + +describe("useAdminUpdatePriceList hook", () => { + test("updates a price list and returns it", async () => { + const priceList = { + name: "talked to customer", + type: PriceListType.SALE, + prices: [], + customer_groups: [], + } + + const { result, waitFor } = renderHook( + () => useAdminUpdatePriceList(fixtures.get("price_list").id), + { + wrapper: createWrapper(), + } + ) + + result.current.mutate(priceList) + + await waitFor(() => result.current.isSuccess) + + expect(result.current.data.response.status).toEqual(200) + expect(result.current.data.price_list).toEqual( + expect.objectContaining({ + ...fixtures.get("price_list"), + ...priceList, + }) + ) + }) +}) + +describe("useAdminDeletePriceList hook", () => { + test("deletes a price list", async () => { + const { result, waitFor } = renderHook( + () => useAdminDeletePriceList(fixtures.get("price_list").id), + { + wrapper: createWrapper(), + } + ) + + result.current.mutate() + + await waitFor(() => result.current.isSuccess) + + expect(result.current.data.response.status).toEqual(200) + expect(result.current.data).toEqual( + expect.objectContaining({ + id: fixtures.get("price_list").id, + deleted: true, + }) + ) + }) +}) + +describe("useAdminDeletePriceListBatch hook", () => { + test("deletes a money amounts from price list", async () => { + const { result, waitFor } = renderHook( + () => useAdminDeletePriceListPrices(fixtures.get("price_list").id), + { + wrapper: createWrapper(), + } + ) + + result.current.mutate({ price_ids: [fixtures.get("money_amount").id] }) + + await waitFor(() => result.current.isSuccess) + + expect(result.current.data.response.status).toEqual(200) + expect(result.current.data).toEqual( + expect.objectContaining({ + ids: [fixtures.get("money_amount").id], + deleted: true, + }) + ) + }) +}) + +describe("useAdminDeletePriceList hook", () => { + test("Adds prices to price list", async () => { + const { result, waitFor } = renderHook( + () => useAdminCreatePriceListPrices(fixtures.get("price_list").id), + { + wrapper: createWrapper(), + } + ) + + result.current.mutate({ prices: [] }) + + await waitFor(() => result.current.isSuccess) + + expect(result.current.data.response.status).toEqual(200) + expect(result.current.data).toEqual( + expect.objectContaining({ + price_list: { + ...fixtures.get("price_list"), + }, + }) + ) + }) +}) diff --git a/packages/medusa-react/test/hooks/admin/price-lists/queries.test.ts b/packages/medusa-react/test/hooks/admin/price-lists/queries.test.ts new file mode 100644 index 0000000000..b37486544d --- /dev/null +++ b/packages/medusa-react/test/hooks/admin/price-lists/queries.test.ts @@ -0,0 +1,35 @@ +import { useAdminPriceList, useAdminPriceLists } from "../../../../src" +import { renderHook } from "@testing-library/react-hooks" +import { fixtures } from "../../../../mocks/data" +import { createWrapper } from "../../../utils" + +describe("useAdminPriceLists hook", () => { + test("returns a list of price lists", async () => { + const priceLists = fixtures.list("price_list") + const { result, waitFor } = renderHook(() => useAdminPriceLists(), { + wrapper: createWrapper(), + }) + + await waitFor(() => result.current.isSuccess) + + expect(result.current.response.status).toEqual(200) + expect(result.current.price_lists).toEqual(priceLists) + }) +}) + +describe("useAdminPriceList hook", () => { + test("returns a price list", async () => { + const priceList = fixtures.get("price_list") + const { result, waitFor } = renderHook( + () => useAdminPriceList(priceList.id), + { + wrapper: createWrapper(), + } + ) + + await waitFor(() => result.current.isSuccess) + + expect(result.current.response.status).toEqual(200) + expect(result.current.price_list).toEqual(priceList) + }) +}) diff --git a/packages/medusa/src/api/index.js b/packages/medusa/src/api/index.js index 6f879f23d1..290b631600 100644 --- a/packages/medusa/src/api/index.js +++ b/packages/medusa/src/api/index.js @@ -41,6 +41,7 @@ export * from "./routes/admin/shipping-options" export * from "./routes/admin/regions" export * from "./routes/admin/product-tags" export * from "./routes/admin/product-types" +export * from "./routes/admin/price-lists" // Store export * from "./routes/store/auth" diff --git a/packages/medusa/src/api/routes/admin/price-lists/index.ts b/packages/medusa/src/api/routes/admin/price-lists/index.ts index d61f46a077..8c8ec7cc3e 100644 --- a/packages/medusa/src/api/routes/admin/price-lists/index.ts +++ b/packages/medusa/src/api/routes/admin/price-lists/index.ts @@ -58,6 +58,12 @@ export type AdminPriceListRes = { price_list: PriceList } +export type AdminPriceListDeleteBatchRes = { + ids: string[] + deleted: boolean + object: string +} + export type AdminPriceListDeleteRes = DeleteResponse export type AdminPriceListsListRes = PaginatedResponse & { @@ -70,4 +76,5 @@ export * from "./delete-price-list" export * from "./get-price-list" export * from "./list-price-lists" export * from "./update-price-list" +export * from "./delete-prices-batch" export * from "./list-price-list-products" diff --git a/packages/medusa/src/api/routes/admin/products/list-products.ts b/packages/medusa/src/api/routes/admin/products/list-products.ts index dd5a9e3e78..ae1a2be327 100644 --- a/packages/medusa/src/api/routes/admin/products/list-products.ts +++ b/packages/medusa/src/api/routes/admin/products/list-products.ts @@ -9,7 +9,6 @@ import { ValidateNested, } from "class-validator" import { omit } from "lodash" - import { Product } from "../../../../models/product" import { DateComparisonOperator } from "../../../../types/common" import { diff --git a/packages/medusa/src/controllers/products/admin-list-products.ts b/packages/medusa/src/controllers/products/admin-list-products.ts index 030a82ba68..9c37eadc09 100644 --- a/packages/medusa/src/controllers/products/admin-list-products.ts +++ b/packages/medusa/src/controllers/products/admin-list-products.ts @@ -5,7 +5,6 @@ import { MedusaError } from "medusa-core-utils" import { Product } from "../../models/product" import { ProductService } from "../../services" import { getListConfig } from "../../utils/get-query-config" -import { FindConfig } from "../../types/common" import { FilterableProductProps } from "../../types/product" type ListContext = {