feat(medusa, medusa-js, medusa-react): Add endpoint to retrieve product tags from the storefront (#3051)
This commit is contained in:
1 parent
ab580066ae
commit
150696de99
15 files changed
+491
-21
No files matched your search
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
"@medusajs/medusa-js": patch
|
||||||
|
"medusa-react": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
feat(medusa, medusa-js, medusa-react): Add endpoint to retrieve Product Tags through the Storefront API
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
const path = require("path")
|
||||||
|
|
||||||
|
const setupServer = require("../../../helpers/setup-server")
|
||||||
|
const { useApi } = require("../../../helpers/use-api")
|
||||||
|
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||||
|
|
||||||
|
const {
|
||||||
|
simpleProductTagFactory,
|
||||||
|
} = require("../../factories/simple-product-tag-factory")
|
||||||
|
|
||||||
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
|
describe("/store/product-tags", () => {
|
||||||
|
let medusaProcess
|
||||||
|
let dbConnection
|
||||||
|
|
||||||
|
const doAfterEach = async () => {
|
||||||
|
const db = useDb()
|
||||||
|
await db.teardown()
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||||
|
dbConnection = await initDb({ cwd })
|
||||||
|
medusaProcess = await setupServer({ cwd })
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
const db = useDb()
|
||||||
|
await db.shutdown()
|
||||||
|
medusaProcess.kill()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("GET /store/product-tags", () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
await simpleProductTagFactory(dbConnection, {
|
||||||
|
id: `ptag-${i}`,
|
||||||
|
value: `tag-${i}`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await doAfterEach()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("lists product tags in store", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const res = await api.get("/store/product-tags")
|
||||||
|
|
||||||
|
expect(res.status).toEqual(200)
|
||||||
|
expect(res.data.product_tags.length).toEqual(10)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("lists product tags in store with limit", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const res = await api.get("/store/product-tags?limit=5")
|
||||||
|
|
||||||
|
expect(res.status).toEqual(200)
|
||||||
|
expect(res.data.product_tags.length).toEqual(5)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("lists product tags in store with offset", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const res = await api.get("/store/product-tags?offset=5")
|
||||||
|
|
||||||
|
expect(res.status).toEqual(200)
|
||||||
|
expect(res.data.product_tags.length).toEqual(5)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("lists product tags in store with offset and limit", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const res = await api.get("/store/product-tags?offset=5&limit=5")
|
||||||
|
|
||||||
|
expect(res.status).toEqual(200)
|
||||||
|
expect(res.data.product_tags.length).toEqual(5)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("lists product tags in store where id matches query", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const res = await api.get("/store/product-tags?id=ptag-1")
|
||||||
|
|
||||||
|
expect(res.status).toEqual(200)
|
||||||
|
expect(res.data.product_tags.length).toEqual(1)
|
||||||
|
expect(res.data.product_tags[0].id).toEqual("ptag-1")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("lists product tags in store where value matches query", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const res = await api.get("/store/product-tags?value=tag-1")
|
||||||
|
|
||||||
|
expect(res.status).toEqual(200)
|
||||||
|
expect(res.data.product_tags.length).toEqual(1)
|
||||||
|
expect(res.data.product_tags[0].value).toEqual("tag-1")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("lists product tags in store where value matches free text", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const res = await api.get("/store/product-tags?q=tag-1")
|
||||||
|
|
||||||
|
expect(res.status).toEqual(200)
|
||||||
|
expect(res.data.product_tags.length).toEqual(1)
|
||||||
|
expect(res.data.product_tags[0].value).toEqual("tag-1")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { ProductTag } from "@medusajs/medusa"
|
||||||
|
import faker from "faker"
|
||||||
|
import { Connection } from "typeorm"
|
||||||
|
|
||||||
|
type ProductTagFactoryData = {
|
||||||
|
id?: string
|
||||||
|
value?: string
|
||||||
|
metadata?: Record<string, unknown>
|
||||||
|
}
|
||||||
|
|
||||||
|
export const simpleProductTagFactory = async (
|
||||||
|
connection: Connection,
|
||||||
|
data: ProductTagFactoryData = {},
|
||||||
|
seed?: number
|
||||||
|
): Promise<ProductTag | undefined> => {
|
||||||
|
if (typeof seed !== "undefined") {
|
||||||
|
faker.seed(seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
const manager = connection.manager
|
||||||
|
|
||||||
|
const productTag = manager.create(ProductTag, {
|
||||||
|
id: data.id || faker.datatype.uuid(),
|
||||||
|
value: data.value || faker.commerce.productAdjective(),
|
||||||
|
metadata: data.metadata || {},
|
||||||
|
})
|
||||||
|
|
||||||
|
return await manager.save(productTag)
|
||||||
|
}
|
||||||
@@ -26,9 +26,7 @@
|
|||||||
"medusa-interfaces": "^1.3.3"
|
"medusa-interfaces": "^1.3.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "babel src -d .",
|
|
||||||
"prepare": "cross-env NODE_ENV=production yarn run build",
|
"prepare": "cross-env NODE_ENV=production yarn run build",
|
||||||
"watch": "babel -w src --out-dir .",
|
|
||||||
"test": "jest --passWithNoTests src",
|
"test": "jest --passWithNoTests src",
|
||||||
"build": "babel src --out-dir dist/ --ignore '**/__tests__','**/__mocks__'",
|
"build": "babel src --out-dir dist/ --ignore '**/__tests__','**/__mocks__'",
|
||||||
"watch": "babel -w src --out-dir dist/ --ignore '**/__tests__','**/__mocks__'"
|
"watch": "babel -w src --out-dir dist/ --ignore '**/__tests__','**/__mocks__'"
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import OrderEditsResource from "./resources/order-edits"
|
|||||||
import OrdersResource from "./resources/orders"
|
import OrdersResource from "./resources/orders"
|
||||||
import PaymentCollectionsResource from "./resources/payment-collections"
|
import PaymentCollectionsResource from "./resources/payment-collections"
|
||||||
import PaymentMethodsResource from "./resources/payment-methods"
|
import PaymentMethodsResource from "./resources/payment-methods"
|
||||||
|
import ProductTagsResource from "./resources/product-tags"
|
||||||
import ProductTypesResource from "./resources/product-types"
|
import ProductTypesResource from "./resources/product-types"
|
||||||
import ProductsResource from "./resources/products"
|
import ProductsResource from "./resources/products"
|
||||||
import RegionsResource from "./resources/regions"
|
import RegionsResource from "./resources/regions"
|
||||||
@@ -40,6 +41,7 @@ class Medusa {
|
|||||||
public giftCards: GiftCardsResource
|
public giftCards: GiftCardsResource
|
||||||
public paymentMethods: PaymentMethodsResource
|
public paymentMethods: PaymentMethodsResource
|
||||||
public paymentCollections: PaymentCollectionsResource
|
public paymentCollections: PaymentCollectionsResource
|
||||||
|
public productTags: ProductTagsResource
|
||||||
|
|
||||||
constructor(config: Config) {
|
constructor(config: Config) {
|
||||||
this.client = new Client(config)
|
this.client = new Client(config)
|
||||||
@@ -63,6 +65,7 @@ class Medusa {
|
|||||||
this.giftCards = new GiftCardsResource(this.client)
|
this.giftCards = new GiftCardsResource(this.client)
|
||||||
this.paymentMethods = new PaymentMethodsResource(this.client)
|
this.paymentMethods = new PaymentMethodsResource(this.client)
|
||||||
this.paymentCollections = new PaymentCollectionsResource(this.client)
|
this.paymentCollections = new PaymentCollectionsResource(this.client)
|
||||||
|
this.productTags = new ProductTagsResource(this.client)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import {
|
||||||
|
StoreGetProductTagsParams,
|
||||||
|
StoreProductTagsListRes,
|
||||||
|
} from "@medusajs/medusa"
|
||||||
|
import qs from "qs"
|
||||||
|
import { ResponsePromise } from "../typings"
|
||||||
|
import BaseResource from "./base"
|
||||||
|
|
||||||
|
class ProductTagsResource extends BaseResource {
|
||||||
|
/**
|
||||||
|
* @description Retrieves a list of product tags
|
||||||
|
* @param {StoreGetProductTagsParams} query is optional. Can contain a limit and offset for the returned list
|
||||||
|
* @param customHeaders
|
||||||
|
* @return {ResponsePromise<StoreProductTagsListRes>}
|
||||||
|
*/
|
||||||
|
list(
|
||||||
|
query?: StoreGetProductTagsParams,
|
||||||
|
customHeaders: Record<string, any> = {}
|
||||||
|
): ResponsePromise<StoreProductTagsListRes> {
|
||||||
|
let path = `/store/product-tags`
|
||||||
|
|
||||||
|
if (query) {
|
||||||
|
const queryString = qs.stringify(query)
|
||||||
|
path += `?${queryString}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.client.request("GET", path, undefined, {}, customHeaders)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProductTagsResource
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { fixtures } from "../data"
|
|
||||||
import { rest } from "msw"
|
import { rest } from "msw"
|
||||||
|
import { fixtures } from "../data"
|
||||||
|
|
||||||
export const storeHandlers = [
|
export const storeHandlers = [
|
||||||
rest.get("/store/products", (req, res, ctx) => {
|
rest.get("/store/products", (req, res, ctx) => {
|
||||||
@@ -550,4 +550,15 @@ export const storeHandlers = [
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
|
||||||
|
rest.get("/store/product-tags", (req, res, ctx) => {
|
||||||
|
return res(
|
||||||
|
ctx.status(200),
|
||||||
|
ctx.json({
|
||||||
|
product_tags: fixtures.list("product_tag", 10),
|
||||||
|
limit: 5,
|
||||||
|
offset: 0,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}),
|
||||||
]
|
]
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
export * from "./products/"
|
|
||||||
export * from "./product-types/"
|
|
||||||
export * from "./carts/"
|
export * from "./carts/"
|
||||||
export * from "./shipping-options/"
|
export * from "./collections"
|
||||||
export * from "./regions/"
|
|
||||||
export * from "./return-reasons/"
|
|
||||||
export * from "./swaps/"
|
|
||||||
export * from "./carts/"
|
|
||||||
export * from "./orders/"
|
|
||||||
export * from "./order-edits"
|
|
||||||
export * from "./customers/"
|
export * from "./customers/"
|
||||||
export * from "./returns/"
|
|
||||||
export * from "./gift-cards/"
|
export * from "./gift-cards/"
|
||||||
export * from "./line-items/"
|
export * from "./line-items/"
|
||||||
export * from "./collections"
|
export * from "./order-edits"
|
||||||
|
export * from "./orders/"
|
||||||
export * from "./payment-collections"
|
export * from "./payment-collections"
|
||||||
|
export * from "./product-tags"
|
||||||
|
export * from "./product-types/"
|
||||||
|
export * from "./products/"
|
||||||
|
export * from "./regions/"
|
||||||
|
export * from "./return-reasons/"
|
||||||
|
export * from "./returns/"
|
||||||
|
export * from "./shipping-options/"
|
||||||
|
export * from "./swaps/"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from "./queries"
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import {
|
||||||
|
StoreGetProductTagsParams,
|
||||||
|
StoreProductTagsListRes,
|
||||||
|
} from "@medusajs/medusa"
|
||||||
|
import { Response } from "@medusajs/medusa-js"
|
||||||
|
import { useQuery } from "@tanstack/react-query"
|
||||||
|
import { useMedusa } from "../../../contexts"
|
||||||
|
import { UseQueryOptionsWrapper } from "../../../types"
|
||||||
|
import { queryKeysFactory } from "../../utils"
|
||||||
|
|
||||||
|
const PRODUCT_TAGS_QUERY_KEY = `product_tags` as const
|
||||||
|
|
||||||
|
export const productTagKeys = queryKeysFactory(PRODUCT_TAGS_QUERY_KEY)
|
||||||
|
|
||||||
|
type ProductTypesQueryKeys = typeof productTagKeys
|
||||||
|
|
||||||
|
export const useProductTags = (
|
||||||
|
query?: StoreGetProductTagsParams,
|
||||||
|
options?: UseQueryOptionsWrapper<
|
||||||
|
Response<StoreProductTagsListRes>,
|
||||||
|
Error,
|
||||||
|
ReturnType<ProductTypesQueryKeys["list"]>
|
||||||
|
>
|
||||||
|
) => {
|
||||||
|
const { client } = useMedusa()
|
||||||
|
const { data, ...rest } = useQuery(
|
||||||
|
productTagKeys.list(query),
|
||||||
|
() => client.productTags.list(query),
|
||||||
|
options
|
||||||
|
)
|
||||||
|
return { ...data, ...rest } as const
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { renderHook } from "@testing-library/react-hooks"
|
||||||
|
import { fixtures } from "../../../../mocks/data/index"
|
||||||
|
import { useProductTags } from "../../../../src"
|
||||||
|
import { createWrapper } from "../../../utils"
|
||||||
|
|
||||||
|
describe("useProductTags hook", () => {
|
||||||
|
test("gets a list of products", async () => {
|
||||||
|
const { result, waitFor } = renderHook(() => useProductTags(), {
|
||||||
|
wrapper: createWrapper(),
|
||||||
|
})
|
||||||
|
|
||||||
|
await waitFor(() => result.current.isSuccess)
|
||||||
|
|
||||||
|
expect(result.current.response.status).toEqual(200)
|
||||||
|
expect(result.current.product_tags).toEqual(
|
||||||
|
fixtures.list("product_tag", 10)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -29,10 +29,10 @@ export * from "./routes/admin/gift-cards"
|
|||||||
export * from "./routes/admin/invites"
|
export * from "./routes/admin/invites"
|
||||||
export * from "./routes/admin/notes"
|
export * from "./routes/admin/notes"
|
||||||
export * from "./routes/admin/notifications"
|
export * from "./routes/admin/notifications"
|
||||||
export * from "./routes/admin/payment-collections"
|
|
||||||
export * from "./routes/admin/payments"
|
|
||||||
export * from "./routes/admin/order-edits"
|
export * from "./routes/admin/order-edits"
|
||||||
export * from "./routes/admin/orders"
|
export * from "./routes/admin/orders"
|
||||||
|
export * from "./routes/admin/payment-collections"
|
||||||
|
export * from "./routes/admin/payments"
|
||||||
export * from "./routes/admin/price-lists"
|
export * from "./routes/admin/price-lists"
|
||||||
export * from "./routes/admin/product-tags"
|
export * from "./routes/admin/product-tags"
|
||||||
export * from "./routes/admin/product-types"
|
export * from "./routes/admin/product-types"
|
||||||
@@ -59,12 +59,13 @@ export * from "./routes/store/customers"
|
|||||||
export * from "./routes/store/gift-cards"
|
export * from "./routes/store/gift-cards"
|
||||||
export * from "./routes/store/order-edits"
|
export * from "./routes/store/order-edits"
|
||||||
export * from "./routes/store/orders"
|
export * from "./routes/store/orders"
|
||||||
export * from "./routes/store/products"
|
export * from "./routes/store/payment-collections"
|
||||||
|
export * from "./routes/store/product-tags"
|
||||||
export * from "./routes/store/product-types"
|
export * from "./routes/store/product-types"
|
||||||
|
export * from "./routes/store/products"
|
||||||
export * from "./routes/store/regions"
|
export * from "./routes/store/regions"
|
||||||
export * from "./routes/store/return-reasons"
|
export * from "./routes/store/return-reasons"
|
||||||
export * from "./routes/store/returns"
|
export * from "./routes/store/returns"
|
||||||
export * from "./routes/store/shipping-options"
|
export * from "./routes/store/shipping-options"
|
||||||
export * from "./routes/store/swaps"
|
export * from "./routes/store/swaps"
|
||||||
export * from "./routes/store/variants"
|
export * from "./routes/store/variants"
|
||||||
export * from "./routes/store/payment-collections"
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import cors from "cors"
|
import cors from "cors"
|
||||||
import { Router } from "express"
|
import { Router } from "express"
|
||||||
|
import { parseCorsOrigins } from "medusa-core-utils"
|
||||||
import middlewares from "../../middlewares"
|
import middlewares from "../../middlewares"
|
||||||
import productTypesRoutes from "../admin/product-types"
|
import productTypesRoutes from "../admin/product-types"
|
||||||
import authRoutes from "./auth"
|
import authRoutes from "./auth"
|
||||||
@@ -9,6 +10,9 @@ import customerRoutes from "./customers"
|
|||||||
import giftCardRoutes from "./gift-cards"
|
import giftCardRoutes from "./gift-cards"
|
||||||
import orderEditRoutes from "./order-edits"
|
import orderEditRoutes from "./order-edits"
|
||||||
import orderRoutes from "./orders"
|
import orderRoutes from "./orders"
|
||||||
|
import paymentCollectionRoutes from "./payment-collections"
|
||||||
|
import productCategoryRoutes from "./product-categories"
|
||||||
|
import productTagsRoutes from "./product-tags"
|
||||||
import productRoutes from "./products"
|
import productRoutes from "./products"
|
||||||
import regionRoutes from "./regions"
|
import regionRoutes from "./regions"
|
||||||
import returnReasonRoutes from "./return-reasons"
|
import returnReasonRoutes from "./return-reasons"
|
||||||
@@ -16,9 +20,6 @@ import returnRoutes from "./returns"
|
|||||||
import shippingOptionRoutes from "./shipping-options"
|
import shippingOptionRoutes from "./shipping-options"
|
||||||
import swapRoutes from "./swaps"
|
import swapRoutes from "./swaps"
|
||||||
import variantRoutes from "./variants"
|
import variantRoutes from "./variants"
|
||||||
import paymentCollectionRoutes from "./payment-collections"
|
|
||||||
import productCategoryRoutes from "./product-categories"
|
|
||||||
import { parseCorsOrigins } from "medusa-core-utils"
|
|
||||||
|
|
||||||
const route = Router()
|
const route = Router()
|
||||||
|
|
||||||
@@ -41,6 +42,7 @@ export default (app, container, config) => {
|
|||||||
collectionRoutes(route)
|
collectionRoutes(route)
|
||||||
customerRoutes(route, container)
|
customerRoutes(route, container)
|
||||||
productRoutes(route, featureFlagRouter)
|
productRoutes(route, featureFlagRouter)
|
||||||
|
productTagsRoutes(route)
|
||||||
productTypesRoutes(route)
|
productTypesRoutes(route)
|
||||||
orderRoutes(route)
|
orderRoutes(route)
|
||||||
orderEditRoutes(route)
|
orderEditRoutes(route)
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { Router } from "express"
|
||||||
|
import { ProductTag } from "../../../../models"
|
||||||
|
import { PaginatedResponse } from "../../../../types/common"
|
||||||
|
import middlewares, { transformQuery } from "../../../middlewares"
|
||||||
|
import { StoreGetProductTagsParams } from "./list-product-tags"
|
||||||
|
|
||||||
|
const route = Router()
|
||||||
|
|
||||||
|
export default (app: Router) => {
|
||||||
|
app.use("/product-tags", route)
|
||||||
|
|
||||||
|
route.get(
|
||||||
|
"/",
|
||||||
|
transformQuery(StoreGetProductTagsParams, {
|
||||||
|
defaultFields: defaultStoreProductTagFields,
|
||||||
|
defaultRelations: defaultStoreProductTagRelations,
|
||||||
|
allowedFields: allowedStoreProductTagFields,
|
||||||
|
isList: true,
|
||||||
|
}),
|
||||||
|
middlewares.wrap(require("./list-product-tags").default)
|
||||||
|
)
|
||||||
|
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
export const defaultStoreProductTagFields = [
|
||||||
|
"id",
|
||||||
|
"value",
|
||||||
|
"created_at",
|
||||||
|
"updated_at",
|
||||||
|
]
|
||||||
|
|
||||||
|
export const allowedStoreProductTagFields = [...defaultStoreProductTagFields]
|
||||||
|
|
||||||
|
export const defaultStoreProductTagRelations = []
|
||||||
|
|
||||||
|
export type StoreProductTagsListRes = PaginatedResponse & {
|
||||||
|
product_tags: ProductTag[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./list-product-tags"
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
import { IsOptional, IsString } from "class-validator"
|
||||||
|
import {
|
||||||
|
DateComparisonOperator,
|
||||||
|
FindPaginationParams,
|
||||||
|
StringComparisonOperator,
|
||||||
|
} from "../../../../types/common"
|
||||||
|
|
||||||
|
import { Request, Response } from "express"
|
||||||
|
import ProductTagService from "../../../../services/product-tag"
|
||||||
|
import { IsType } from "../../../../utils/validators/is-type"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @oas [get] /product-tags
|
||||||
|
* operationId: "GetProductTags"
|
||||||
|
* summary: "List Product Tags"
|
||||||
|
* description: "Retrieve a list of Product Tags."
|
||||||
|
* x-authenticated: true
|
||||||
|
* parameters:
|
||||||
|
* - (query) limit=20 {integer} The number of types to return.
|
||||||
|
* - (query) offset=0 {integer} The number of items to skip before the results.
|
||||||
|
* - (query) order {string} The field to sort items by.
|
||||||
|
* - (query) discount_condition_id {string} The discount condition id on which to filter the product tags.
|
||||||
|
* - in: query
|
||||||
|
* name: value
|
||||||
|
* style: form
|
||||||
|
* explode: false
|
||||||
|
* description: The tag values to search for
|
||||||
|
* schema:
|
||||||
|
* type: array
|
||||||
|
* items:
|
||||||
|
* type: string
|
||||||
|
* - in: query
|
||||||
|
* name: id
|
||||||
|
* style: form
|
||||||
|
* explode: false
|
||||||
|
* description: The tag IDs to search for
|
||||||
|
* schema:
|
||||||
|
* type: array
|
||||||
|
* items:
|
||||||
|
* type: string
|
||||||
|
* - (query) q {string} A query string to search values for
|
||||||
|
* - in: query
|
||||||
|
* name: created_at
|
||||||
|
* description: Date comparison for when resulting product tags were created.
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* lt:
|
||||||
|
* type: string
|
||||||
|
* description: filter by dates less than this date
|
||||||
|
* format: date
|
||||||
|
* gt:
|
||||||
|
* type: string
|
||||||
|
* description: filter by dates greater than this date
|
||||||
|
* format: date
|
||||||
|
* lte:
|
||||||
|
* type: string
|
||||||
|
* description: filter by dates less than or equal to this date
|
||||||
|
* format: date
|
||||||
|
* gte:
|
||||||
|
* type: string
|
||||||
|
* description: filter by dates greater than or equal to this date
|
||||||
|
* format: date
|
||||||
|
* - in: query
|
||||||
|
* name: updated_at
|
||||||
|
* description: Date comparison for when resulting product tags were updated.
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* lt:
|
||||||
|
* type: string
|
||||||
|
* description: filter by dates less than this date
|
||||||
|
* format: date
|
||||||
|
* gt:
|
||||||
|
* type: string
|
||||||
|
* description: filter by dates greater than this date
|
||||||
|
* format: date
|
||||||
|
* lte:
|
||||||
|
* type: string
|
||||||
|
* description: filter by dates less than or equal to this date
|
||||||
|
* format: date
|
||||||
|
* gte:
|
||||||
|
* type: string
|
||||||
|
* description: filter by dates greater than or equal to this date
|
||||||
|
* format: date
|
||||||
|
* x-codeSamples:
|
||||||
|
* - lang: JavaScript
|
||||||
|
* label: JS Client
|
||||||
|
* source: |
|
||||||
|
* import Medusa from "@medusajs/medusa-js"
|
||||||
|
* const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 })
|
||||||
|
* medusa.store.productTags.list()
|
||||||
|
* .then(({ product_tags }) => {
|
||||||
|
* console.log(product_tags.length);
|
||||||
|
* });
|
||||||
|
* - lang: Shell
|
||||||
|
* label: cURL
|
||||||
|
* source: |
|
||||||
|
* curl --location --request GET 'https://medusa-url.com/store/product-tags'
|
||||||
|
* tags:
|
||||||
|
* - Product Tag
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: OK
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* product_tags:
|
||||||
|
* $ref: "#/components/schemas/ProductTag"
|
||||||
|
* count:
|
||||||
|
* type: integer
|
||||||
|
* description: The total number of items available
|
||||||
|
* offset:
|
||||||
|
* type: integer
|
||||||
|
* description: The number of items skipped before these items
|
||||||
|
* limit:
|
||||||
|
* type: integer
|
||||||
|
* description: The number of items per page
|
||||||
|
* "400":
|
||||||
|
* $ref: "#/components/responses/400_error"
|
||||||
|
* "401":
|
||||||
|
* $ref: "#/components/responses/unauthorized"
|
||||||
|
* "404":
|
||||||
|
* $ref: "#/components/responses/not_found_error"
|
||||||
|
* "409":
|
||||||
|
* $ref: "#/components/responses/invalid_state_error"
|
||||||
|
* "422":
|
||||||
|
* $ref: "#/components/responses/invalid_request_error"
|
||||||
|
* "500":
|
||||||
|
* $ref: "#/components/responses/500_error"
|
||||||
|
*/
|
||||||
|
export default async (req: Request, res: Response) => {
|
||||||
|
const tagService: ProductTagService = req.scope.resolve("productTagService")
|
||||||
|
|
||||||
|
const { listConfig, filterableFields } = req
|
||||||
|
const { skip, take } = req.listConfig
|
||||||
|
|
||||||
|
const [tags, count] = await tagService.listAndCount(
|
||||||
|
filterableFields,
|
||||||
|
listConfig
|
||||||
|
)
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
product_tags: tags,
|
||||||
|
count,
|
||||||
|
offset: skip,
|
||||||
|
limit: take,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export class StoreGetProductTagsParams extends FindPaginationParams {
|
||||||
|
@IsType([String, [String], StringComparisonOperator])
|
||||||
|
@IsOptional()
|
||||||
|
id?: string | string[] | StringComparisonOperator
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
q?: string
|
||||||
|
|
||||||
|
@IsType([String, [String], StringComparisonOperator])
|
||||||
|
@IsOptional()
|
||||||
|
value?: string | string[] | StringComparisonOperator
|
||||||
|
|
||||||
|
@IsType([DateComparisonOperator])
|
||||||
|
@IsOptional()
|
||||||
|
created_at?: DateComparisonOperator
|
||||||
|
|
||||||
|
@IsType([DateComparisonOperator])
|
||||||
|
@IsOptional()
|
||||||
|
updated_at?: DateComparisonOperator
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
order?: string
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
discount_condition_id?: string
|
||||||
|
}
|
||||||
Reference in new issue
Block a user