From f03a8222534ce98ad3ea84316fa44a5ce392e1b9 Mon Sep 17 00:00:00 2001 From: Stevche Radevski Date: Thu, 25 Apr 2024 17:36:59 +0200 Subject: [PATCH] feat: Add support for search to all endpoints (#7149) * feat: Add search capability to api keys * feat: Add support for searching to currency and customer endpoints * fix: Clean up product search filters * feat: Add search support to regions * feat: Add search support to sales channels * feat: Add search support to store module * feat: Add search support to user module * fix: Clean up inventory search * feat: Add search support for payments * fix: Add searchable attributes to stock location models * feat: Add search support to tax * feat: Add search support to promotions * feat: Add search support for pricing, filtering cleanup * fix: Further cleanups around search --- .../api/__tests__/admin/api-key.spec.ts | 37 ++++++++ .../api/__tests__/admin/product.js | 40 +++++++++ .../api/__tests__/admin/sales-channels.js | 85 ++++++++++++------- .../api/__tests__/admin/store.js | 35 +++++++- integration-tests/api/__tests__/admin/user.js | 6 +- .../__tests__/currency/admin/currency.spec.ts | 12 +++ .../admin/list-customer-groups.spec.ts | 23 +++++ .../customer/admin/list-customer-addresses.ts | 47 ++++++++++ .../customer/admin/list-customers.spec.ts | 37 ++++++++ .../price-lists/admin/price-lists.spec.ts | 65 ++++++++++++++ .../promotion/admin/list-campaigns.spec.ts | 14 +++ .../promotion/admin/list-promotions.spec.ts | 32 +++++++ .../__tests__/regions/admin/regions.spec.ts | 25 ++++++ .../modules/__tests__/tax/admin/tax.spec.ts | 52 ++++++++++++ packages/api-key/src/models/api-key.ts | 3 + .../src/services/api-key-module-service.ts | 4 + packages/customer/src/models/address.ts | 11 ++- .../customer/src/models/customer-group.ts | 3 +- .../src/models/inventory-item.ts | 2 + .../src/api-v2/admin/api-keys/validators.ts | 1 + .../src/api-v2/admin/campaigns/validators.ts | 1 + .../src/api-v2/admin/customers/validators.ts | 1 + .../src/api-v2/admin/payments/validators.ts | 1 + .../api-v2/admin/price-lists/validators.ts | 24 ++++-- .../src/api-v2/admin/regions/validators.ts | 1 + .../api-v2/admin/sales-channels/validators.ts | 1 + .../src/api-v2/admin/stores/validators.ts | 1 + .../api-v2/admin/tax-regions/validators.ts | 2 +- .../src/api-v2/admin/users/validators.ts | 2 +- packages/payment/src/models/payment.ts | 4 + packages/pricing/src/models/price-list.ts | 3 + packages/promotion/src/models/campaign.ts | 4 +- packages/promotion/src/models/promotion.ts | 9 +- packages/region/src/models/region.ts | 4 +- .../sales-channel/src/models/sales-channel.ts | 4 +- .../src/models/stock-location-address.ts | 8 +- .../src/models/stock-location.ts | 4 +- packages/store/src/models/store.ts | 2 + packages/types/src/api-key/common/api-key.ts | 4 + .../types/src/currency/common/currency.ts | 4 + packages/types/src/customer/common.ts | 15 ++++ .../src/inventory/common/inventory-item.ts | 10 +-- packages/types/src/payment/common.ts | 5 ++ .../types/src/pricing/common/price-list.ts | 12 ++- packages/types/src/product/common.ts | 8 +- .../types/src/promotion/common/campaign.ts | 4 + .../types/src/promotion/common/promotion.ts | 5 ++ packages/types/src/region/common.ts | 4 + packages/types/src/sales-channel/common.ts | 5 ++ packages/types/src/store/common/store.ts | 4 + packages/types/src/tax/common.ts | 10 +++ packages/types/src/user/common.ts | 4 + 52 files changed, 640 insertions(+), 64 deletions(-) diff --git a/integration-tests/api/__tests__/admin/api-key.spec.ts b/integration-tests/api/__tests__/admin/api-key.spec.ts index 45b3d3d096..e4f6b27ff3 100644 --- a/integration-tests/api/__tests__/admin/api-key.spec.ts +++ b/integration-tests/api/__tests__/admin/api-key.spec.ts @@ -85,6 +85,43 @@ medusaIntegrationTestRunner({ expect(listedApiKeys.data.api_keys).toHaveLength(0) }) + it("should allow searching for api keys", async () => { + await api.post( + `/admin/api-keys`, + { + title: "Test Secret Key", + type: ApiKeyType.SECRET, + }, + adminHeaders + ) + await api.post( + `/admin/api-keys`, + { + title: "Test Publishable Key", + type: ApiKeyType.PUBLISHABLE, + }, + adminHeaders + ) + + const listedSecretKeys = await api.get( + `/admin/api-keys?q=Secret`, + adminHeaders + ) + const listedPublishableKeys = await api.get( + `/admin/api-keys?q=Publish`, + adminHeaders + ) + + expect(listedSecretKeys.data.api_keys).toHaveLength(1) + expect(listedSecretKeys.data.api_keys[0].title).toEqual( + "Test Secret Key" + ) + expect(listedPublishableKeys.data.api_keys).toHaveLength(1) + expect(listedPublishableKeys.data.api_keys[0].title).toEqual( + "Test Publishable Key" + ) + }) + it("can use a secret api key for authentication", async () => { const created = await api.post( `/admin/api-keys`, diff --git a/integration-tests/api/__tests__/admin/product.js b/integration-tests/api/__tests__/admin/product.js index 74b5f68cd0..fc6c23ab03 100644 --- a/integration-tests/api/__tests__/admin/product.js +++ b/integration-tests/api/__tests__/admin/product.js @@ -1948,6 +1948,46 @@ medusaIntegrationTestRunner({ ]) ) }) + + it("should allow searching of variants", async () => { + await breaking( + () => {}, + async () => { + const newProduct = ( + await api.post( + "/admin/products", + getProductFixture({ + variants: [ + { title: "First variant", prices: [] }, + { title: "Second variant", prices: [] }, + ], + }), + adminHeaders + ) + ).data.product + + const res = await api + .get( + `/admin/products/${newProduct.id}/variants?q=first`, + adminHeaders + ) + .catch((err) => { + console.log(err) + }) + + expect(res.status).toEqual(200) + expect(res.data.variants).toHaveLength(1) + expect(res.data.variants).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + title: "First variant", + product_id: newProduct.id, + }), + ]) + ) + } + ) + }) }) describe("updates a variant's default prices (ignores prices associated with a Price List)", () => { diff --git a/integration-tests/api/__tests__/admin/sales-channels.js b/integration-tests/api/__tests__/admin/sales-channels.js index 5503473ce6..d7f6347d7d 100644 --- a/integration-tests/api/__tests__/admin/sales-channels.js +++ b/integration-tests/api/__tests__/admin/sales-channels.js @@ -157,40 +157,30 @@ medusaIntegrationTestRunner({ }) it("should list the sales channel using filters", async () => { - const response = await breaking( - async () => { - return await api.get(`/admin/sales-channels?q=2`, adminReqConfig) - }, - () => undefined + const response = await api.get( + `/admin/sales-channels?q=2`, + adminReqConfig ) - breaking( - () => { - expect(response.status).toEqual(200) - expect(response.data.sales_channels).toBeTruthy() - expect(response.data.sales_channels.length).toBe(1) - expect(response.data).toEqual({ - count: 1, - limit: 20, - offset: 0, - sales_channels: expect.arrayContaining([ - expect.objectContaining({ - id: expect.any(String), - name: salesChannel2.name, - description: salesChannel2.description, - is_disabled: false, - deleted_at: null, - created_at: expect.any(String), - updated_at: expect.any(String), - }), - ]), - }) - }, - () => { - // TODO: Free text search is not supported in the new sales channel API (yet) - expect(response).toBeUndefined() - } - ) + expect(response.status).toEqual(200) + expect(response.data.sales_channels).toBeTruthy() + expect(response.data.sales_channels.length).toBe(1) + expect(response.data).toEqual({ + count: 1, + limit: 20, + offset: 0, + sales_channels: expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(String), + name: salesChannel2.name, + description: salesChannel2.description, + is_disabled: false, + deleted_at: null, + created_at: expect.any(String), + updated_at: expect.any(String), + }), + ]), + }) }) it("should list the sales channel using properties filters", async () => { @@ -219,6 +209,37 @@ medusaIntegrationTestRunner({ ]), }) }) + + it("should support searching of sales channels", async () => { + await breaking( + () => {}, + async () => { + await api.post( + "/admin/sales-channels", + { name: "first channel", description: "to fetch" }, + adminReqConfig + ) + + await api.post( + "/admin/sales-channels", + { name: "second channel", description: "not in response" }, + adminReqConfig + ) + + const response = await api.get( + `/admin/sales-channels?q=fetch`, + adminReqConfig + ) + + expect(response.status).toEqual(200) + expect(response.data.sales_channels).toEqual([ + expect.objectContaining({ + name: "first channel", + }), + ]) + } + ) + }) }) describe("POST /admin/sales-channels/:id", () => { diff --git a/integration-tests/api/__tests__/admin/store.js b/integration-tests/api/__tests__/admin/store.js index f159b5e4bc..4abe04741f 100644 --- a/integration-tests/api/__tests__/admin/store.js +++ b/integration-tests/api/__tests__/admin/store.js @@ -50,7 +50,11 @@ medusaIntegrationTestRunner({ () => api .get("/admin/stores", adminHeaders) - .then((r) => r.data.stores[0]) + .then((r) => + r.data.stores.find( + (s) => s.default_sales_channel_id === "sc_12345" + ) + ) ) expect(store).toEqual( @@ -245,6 +249,35 @@ medusaIntegrationTestRunner({ ) }) }) + + describe("GET /admin/store", () => { + it("supports searching of stores", async () => { + await breaking( + () => {}, + async () => { + const service = container.resolve(ModuleRegistrationName.STORE) + const secondStore = await service.create({ + name: "Second Store", + supported_currency_codes: ["eur"], + default_currency_code: "eur", + }) + + const response = await api.get( + "/admin/stores?q=second", + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.stores).toEqual([ + expect.objectContaining({ + id: secondStore.id, + name: "Second Store", + }), + ]) + } + ) + }) + }) }) }, }) diff --git a/integration-tests/api/__tests__/admin/user.js b/integration-tests/api/__tests__/admin/user.js index 920cd7c910..4b512fec18 100644 --- a/integration-tests/api/__tests__/admin/user.js +++ b/integration-tests/api/__tests__/admin/user.js @@ -143,7 +143,6 @@ medusaIntegrationTestRunner({ ) }) - // TODO: Free text search not supported in 2.0 yet it("should list users that match the free text search", async () => { const response = await api.get("/admin/users?q=member", adminHeaders) @@ -159,7 +158,10 @@ medusaIntegrationTestRunner({ last_name: "user", created_at: expect.any(String), updated_at: expect.any(String), - role: "member", + ...breaking( + () => ({ role: "member" }), + () => ({}) + ), }), ]) ) diff --git a/integration-tests/modules/__tests__/currency/admin/currency.spec.ts b/integration-tests/modules/__tests__/currency/admin/currency.spec.ts index edc09f5f92..5783fe0640 100644 --- a/integration-tests/modules/__tests__/currency/admin/currency.spec.ts +++ b/integration-tests/modules/__tests__/currency/admin/currency.spec.ts @@ -53,6 +53,18 @@ medusaIntegrationTestRunner({ expect.objectContaining({ code: "zwl", name: "Zimbabwean Dollar" }) ) }) + + it("should allow for searching of currencies", async () => { + const listResp = await api.get( + "/admin/currencies?q=zimbabwean", + adminHeaders + ) + + expect(listResp.data.currencies).toHaveLength(1) + expect(listResp.data.currencies[0]).toEqual( + expect.objectContaining({ code: "zwl", name: "Zimbabwean Dollar" }) + ) + }) }) }, }) diff --git a/integration-tests/modules/__tests__/customer-group/admin/list-customer-groups.spec.ts b/integration-tests/modules/__tests__/customer-group/admin/list-customer-groups.spec.ts index 5a546787fd..2ce766900a 100644 --- a/integration-tests/modules/__tests__/customer-group/admin/list-customer-groups.spec.ts +++ b/integration-tests/modules/__tests__/customer-group/admin/list-customer-groups.spec.ts @@ -44,6 +44,29 @@ medusaIntegrationTestRunner({ }), ]) }) + + it("should support searching of customer groups", async () => { + await customerModuleService.createCustomerGroup([ + { + name: "First group", + }, + { name: "Second group" }, + ]) + + const response = await api.get( + `/admin/customer-groups?q=fir`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.customer_groups).toHaveLength(1) + expect(response.data.customer_groups[0]).toEqual( + expect.objectContaining({ + id: expect.any(String), + name: "First group", + }) + ) + }) }) }, }) diff --git a/integration-tests/modules/__tests__/customer/admin/list-customer-addresses.ts b/integration-tests/modules/__tests__/customer/admin/list-customer-addresses.ts index 433d071d70..2e7be1b0c0 100644 --- a/integration-tests/modules/__tests__/customer/admin/list-customer-addresses.ts +++ b/integration-tests/modules/__tests__/customer/admin/list-customer-addresses.ts @@ -92,6 +92,53 @@ medusaIntegrationTestRunner({ ]) ) }) + + it("should support searching through the addresses", async () => { + const [customer] = await customerModuleService.create([ + { + first_name: "Test", + last_name: "Test", + email: "test@me.com", + addresses: [ + { + first_name: "John", + last_name: "Doe", + address_1: "Huntingdon 123", + }, + { + first_name: "Jane", + last_name: "Doe", + address_1: "Horseshoe 555", + }, + { + first_name: "Jack", + last_name: "Doe", + address_1: "Hawkins 12", + }, + ], + }, + ]) + + const response = await api.get( + `/admin/customers/${customer.id}/addresses?q=12`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.addresses).toHaveLength(2) + expect(response.data.addresses).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(String), + address_1: "Huntingdon 123", + }), + expect.objectContaining({ + id: expect.any(String), + address_1: "Hawkins 12", + }), + ]) + ) + }) }) }, }) diff --git a/integration-tests/modules/__tests__/customer/admin/list-customers.spec.ts b/integration-tests/modules/__tests__/customer/admin/list-customers.spec.ts index e083750051..bc1a49705d 100644 --- a/integration-tests/modules/__tests__/customer/admin/list-customers.spec.ts +++ b/integration-tests/modules/__tests__/customer/admin/list-customers.spec.ts @@ -141,6 +141,43 @@ medusaIntegrationTestRunner({ }) ) }) + + it("should support searching of customers", async () => { + await customerModuleService.create([ + { + first_name: "Jane", + last_name: "Doe", + email: "jane@me.com", + }, + { + first_name: "John", + last_name: "Doe", + email: "john@me.com", + }, + { + first_name: "LeBron", + last_name: "James", + email: "lebron@me.com", + }, + ]) + + const response = await api.get(`/admin/customers?q=do`, adminHeaders) + + expect(response.status).toEqual(200) + expect(response.data.customers).toHaveLength(2) + expect(response.data.customers).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + first_name: "Jane", + last_name: "Doe", + }), + expect.objectContaining({ + first_name: "John", + last_name: "Doe", + }), + ]) + ) + }) }) }, }) diff --git a/integration-tests/modules/__tests__/price-lists/admin/price-lists.spec.ts b/integration-tests/modules/__tests__/price-lists/admin/price-lists.spec.ts index 24212aa0ae..33aef26893 100644 --- a/integration-tests/modules/__tests__/price-lists/admin/price-lists.spec.ts +++ b/integration-tests/modules/__tests__/price-lists/admin/price-lists.spec.ts @@ -162,6 +162,71 @@ medusaIntegrationTestRunner({ }, ]) }) + + it("should support searching of price lists", async () => { + const priceSet = await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [], + }) + + await pricingModule.createPriceLists([ + { + title: "first price list", + description: "test price", + ends_at: new Date(), + starts_at: new Date(), + status: PriceListStatus.ACTIVE, + type: PriceListType.OVERRIDE, + prices: [ + { + amount: 5000, + currency_code: "usd", + price_set_id: priceSet.id, + rules: { + region_id: region.id, + }, + }, + ], + rules: { + customer_group_id: [customerGroup.id], + }, + }, + { + title: "second price list", + description: "second test", + ends_at: new Date(), + starts_at: new Date(), + status: PriceListStatus.ACTIVE, + type: PriceListType.OVERRIDE, + prices: [ + { + amount: 5000, + currency_code: "usd", + price_set_id: priceSet.id, + rules: { + region_id: region.id, + }, + }, + ], + rules: { + customer_group_id: [customerGroup.id], + }, + }, + ]) + + let response = await api.get( + `/admin/price-lists?q=second`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.price_lists).toEqual([ + expect.objectContaining({ + title: "second price list", + }), + ]) + }) }) describe("GET /admin/price-lists/:id", () => { diff --git a/integration-tests/modules/__tests__/promotion/admin/list-campaigns.spec.ts b/integration-tests/modules/__tests__/promotion/admin/list-campaigns.spec.ts index 2f30c08c80..c1f1eb7c8d 100644 --- a/integration-tests/modules/__tests__/promotion/admin/list-campaigns.spec.ts +++ b/integration-tests/modules/__tests__/promotion/admin/list-campaigns.spec.ts @@ -130,6 +130,20 @@ medusaIntegrationTestRunner({ ) }) + it("should support search on campaigns", async () => { + const response = await api.get( + `/admin/campaigns?q=ign%202`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.campaigns).toEqual([ + expect.objectContaining({ + name: "campaign 2", + }), + ]) + }) + it("should get all campaigns and its count filtered", async () => { const response = await api.get( `/admin/campaigns?fields=name,created_at,budget.id`, diff --git a/integration-tests/modules/__tests__/promotion/admin/list-promotions.spec.ts b/integration-tests/modules/__tests__/promotion/admin/list-promotions.spec.ts index e63e9a3e09..94ca5b6cd1 100644 --- a/integration-tests/modules/__tests__/promotion/admin/list-promotions.spec.ts +++ b/integration-tests/modules/__tests__/promotion/admin/list-promotions.spec.ts @@ -67,6 +67,38 @@ medusaIntegrationTestRunner({ ]) }) + it("should support search of promotions", async () => { + await promotionModuleService.create([ + { + code: "first", + type: PromotionType.STANDARD, + application_method: { + type: "fixed", + target_type: "order", + value: 100, + }, + }, + { + code: "second", + type: PromotionType.STANDARD, + application_method: { + type: "fixed", + target_type: "order", + value: 100, + }, + }, + ]) + + const response = await api.get(`/admin/promotions?q=fir`, adminHeaders) + + expect(response.status).toEqual(200) + expect(response.data.promotions).toEqual([ + expect.objectContaining({ + code: "first", + }), + ]) + }) + it("should get all promotions and its count filtered", async () => { await promotionModuleService.create([ { diff --git a/integration-tests/modules/__tests__/regions/admin/regions.spec.ts b/integration-tests/modules/__tests__/regions/admin/regions.spec.ts index 35a0407b91..6fa145a72f 100644 --- a/integration-tests/modules/__tests__/regions/admin/regions.spec.ts +++ b/integration-tests/modules/__tests__/regions/admin/regions.spec.ts @@ -343,6 +343,31 @@ medusaIntegrationTestRunner({ ]) }) + it("should support searching of regions", async () => { + await service.create([ + { + name: "APAC", + currency_code: "usd", + countries: ["jp"], + }, + { + name: "Europe", + currency_code: "eur", + countries: ["de"], + }, + ]) + + const response = await api.get(`/admin/regions?q=eu`, adminHeaders) + + expect(response.status).toEqual(200) + expect(response.data.regions).toEqual([ + expect.objectContaining({ + name: "Europe", + currency_code: "eur", + }), + ]) + }) + it("should get a region", async () => { const [region] = await service.create([ { diff --git a/integration-tests/modules/__tests__/tax/admin/tax.spec.ts b/integration-tests/modules/__tests__/tax/admin/tax.spec.ts index 8ce08d417b..4b757d85ef 100644 --- a/integration-tests/modules/__tests__/tax/admin/tax.spec.ts +++ b/integration-tests/modules/__tests__/tax/admin/tax.spec.ts @@ -64,6 +64,33 @@ medusaIntegrationTestRunner({ }) }) + it("can search through tax rates", async () => { + const region = await service.createTaxRegions({ + country_code: "us", + }) + + await service.create({ + tax_region_id: region.id, + code: "low", + rate: 2.5, + name: "low rate", + }) + + await service.create({ + tax_region_id: region.id, + code: "high", + rate: 5, + name: "high rate", + }) + + const response = await api.get(`/admin/tax-rates?q=high`, adminHeaders) + + expect(response.status).toEqual(200) + expect(response.data.tax_rates).toEqual( + expect.arrayContaining([expect.objectContaining({ code: "high" })]) + ) + }) + it("can create a tax region with rates and rules", async () => { const regionRes = await api.post( `/admin/tax-regions`, @@ -402,6 +429,31 @@ medusaIntegrationTestRunner({ }) }) + it("can search through tax regions", async () => { + await service.createTaxRegions([ + { + country_code: "us", + province_code: "texas", + }, + { + country_code: "us", + province_code: "florida", + }, + ]) + + const response = await api.get(`/admin/tax-regions?q=ida`, adminHeaders) + + expect(response.status).toEqual(200) + expect(response.data.tax_regions).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + country_code: "us", + province_code: "florida", + }), + ]) + ) + }) + it("can create a tax region and delete it", async () => { const regionRes = await api.post( `/admin/tax-regions`, diff --git a/packages/api-key/src/models/api-key.ts b/packages/api-key/src/models/api-key.ts index d8ab241378..c62b847a5a 100644 --- a/packages/api-key/src/models/api-key.ts +++ b/packages/api-key/src/models/api-key.ts @@ -1,4 +1,5 @@ import { + Searchable, createPsqlIndexStatementHelper, generateEntityId, } from "@medusajs/utils" @@ -35,9 +36,11 @@ export default class ApiKey { @Property({ columnType: "text" }) salt: string + @Searchable() @Property({ columnType: "text" }) redacted: string + @Searchable() @Property({ columnType: "text" }) title: string diff --git a/packages/api-key/src/services/api-key-module-service.ts b/packages/api-key/src/services/api-key-module-service.ts index 9a2123ccb0..2b1e32531a 100644 --- a/packages/api-key/src/services/api-key-module-service.ts +++ b/packages/api-key/src/services/api-key-module-service.ts @@ -443,6 +443,10 @@ export default class ApiKeyModuleService // There can only be 2 secret keys at most, and one has to be with a revoked_at date set, so only 1 can be newly created. const secretKeysToCreate = data.filter((k) => k.type === ApiKeyType.SECRET) + if (!secretKeysToCreate.length) { + return + } + if (secretKeysToCreate.length > 1) { throw new MedusaError( MedusaError.Types.INVALID_DATA, diff --git a/packages/customer/src/models/address.ts b/packages/customer/src/models/address.ts index 817d4c2771..fdfb3acac1 100644 --- a/packages/customer/src/models/address.ts +++ b/packages/customer/src/models/address.ts @@ -1,5 +1,5 @@ import { DAL } from "@medusajs/types" -import { generateEntityId } from "@medusajs/utils" +import { Searchable, generateEntityId } from "@medusajs/utils" import { BeforeCreate, Cascade, @@ -37,6 +37,7 @@ export default class Address { @PrimaryKey({ columnType: "text" }) id!: string + @Searchable() @Property({ columnType: "text", nullable: true }) address_name: string | null = null @@ -56,30 +57,38 @@ export default class Address { }) customer: Customer + @Searchable() @Property({ columnType: "text", nullable: true }) company: string | null = null + @Searchable() @Property({ columnType: "text", nullable: true }) first_name: string | null = null + @Searchable() @Property({ columnType: "text", nullable: true }) last_name: string | null = null + @Searchable() @Property({ columnType: "text", nullable: true }) address_1: string | null = null + @Searchable() @Property({ columnType: "text", nullable: true }) address_2: string | null = null + @Searchable() @Property({ columnType: "text", nullable: true }) city: string | null = null @Property({ columnType: "text", nullable: true }) country_code: string | null = null + @Searchable() @Property({ columnType: "text", nullable: true }) province: string | null = null + @Searchable() @Property({ columnType: "text", nullable: true }) postal_code: string | null = null diff --git a/packages/customer/src/models/customer-group.ts b/packages/customer/src/models/customer-group.ts index c6db5c3486..54dce4eb69 100644 --- a/packages/customer/src/models/customer-group.ts +++ b/packages/customer/src/models/customer-group.ts @@ -1,5 +1,5 @@ import { DAL } from "@medusajs/types" -import { DALUtils, generateEntityId } from "@medusajs/utils" +import { DALUtils, Searchable, generateEntityId } from "@medusajs/utils" import { BeforeCreate, Entity, @@ -24,6 +24,7 @@ export default class CustomerGroup { @PrimaryKey({ columnType: "text" }) id!: string + @Searchable() @Property({ columnType: "text", nullable: true }) name: string | null = null diff --git a/packages/inventory-next/src/models/inventory-item.ts b/packages/inventory-next/src/models/inventory-item.ts index 31fcd3e8f3..52d55eca59 100644 --- a/packages/inventory-next/src/models/inventory-item.ts +++ b/packages/inventory-next/src/models/inventory-item.ts @@ -70,9 +70,11 @@ export class InventoryItem { @Property({ columnType: "text", nullable: true }) origin_country: string | null = null + @Searchable() @Property({ columnType: "text", nullable: true }) hs_code: string | null = null + @Searchable() @Property({ columnType: "text", nullable: true }) mid_code: string | null = null diff --git a/packages/medusa/src/api-v2/admin/api-keys/validators.ts b/packages/medusa/src/api-v2/admin/api-keys/validators.ts index 547930293f..d01c07d851 100644 --- a/packages/medusa/src/api-v2/admin/api-keys/validators.ts +++ b/packages/medusa/src/api-v2/admin/api-keys/validators.ts @@ -14,6 +14,7 @@ export const AdminGetApiKeysParams = createFindParams({ limit: 50, }).merge( z.object({ + q: z.string().optional(), id: z.union([z.string(), z.array(z.string())]).optional(), title: z.union([z.string(), z.array(z.string())]).optional(), token: z.union([z.string(), z.array(z.string())]).optional(), diff --git a/packages/medusa/src/api-v2/admin/campaigns/validators.ts b/packages/medusa/src/api-v2/admin/campaigns/validators.ts index 5404606c8b..10d6735f51 100644 --- a/packages/medusa/src/api-v2/admin/campaigns/validators.ts +++ b/packages/medusa/src/api-v2/admin/campaigns/validators.ts @@ -12,6 +12,7 @@ export const AdminGetCampaignsParams = createFindParams({ limit: 50, }).merge( z.object({ + q: z.string().optional(), campaign_identifier: z.string().optional(), currency: z.string().optional(), $and: z.lazy(() => AdminGetCampaignsParams.array()).optional(), diff --git a/packages/medusa/src/api-v2/admin/customers/validators.ts b/packages/medusa/src/api-v2/admin/customers/validators.ts index 300a2baffd..3d679a04df 100644 --- a/packages/medusa/src/api-v2/admin/customers/validators.ts +++ b/packages/medusa/src/api-v2/admin/customers/validators.ts @@ -82,6 +82,7 @@ export const AdminCustomerAdressesParams = createFindParams({ limit: 50, }).merge( z.object({ + q: z.string().optional(), address_name: z.union([z.string(), z.array(z.string())]).optional(), is_default_shipping: z.boolean().optional(), is_default_billing: z.boolean().optional(), diff --git a/packages/medusa/src/api-v2/admin/payments/validators.ts b/packages/medusa/src/api-v2/admin/payments/validators.ts index 9d2ef4eeec..f1e1af1c1a 100644 --- a/packages/medusa/src/api-v2/admin/payments/validators.ts +++ b/packages/medusa/src/api-v2/admin/payments/validators.ts @@ -14,6 +14,7 @@ export const AdminGetPaymentsParams = createFindParams({ offset: 0, }).merge( z.object({ + q: z.string().optional(), id: z.union([z.string(), z.array(z.string())]).optional(), created_at: createOperatorMap().optional(), updated_at: createOperatorMap().optional(), diff --git a/packages/medusa/src/api-v2/admin/price-lists/validators.ts b/packages/medusa/src/api-v2/admin/price-lists/validators.ts index 6b422afaa7..01ca9241f0 100644 --- a/packages/medusa/src/api-v2/admin/price-lists/validators.ts +++ b/packages/medusa/src/api-v2/admin/price-lists/validators.ts @@ -1,17 +1,29 @@ import { PriceListStatus, PriceListType } from "@medusajs/types" import { z } from "zod" -import { createFindParams, createSelectParams } from "../../utils/validators" +import { + createFindParams, + createOperatorMap, + createSelectParams, +} from "../../utils/validators" export const AdminGetPriceListPricesParams = createSelectParams() export const AdminGetPriceListsParams = createFindParams({ offset: 0, limit: 50, -}) +}).merge( + z.object({ + q: z.string().optional(), + id: z.union([z.string(), z.array(z.string())]).optional(), + starts_at: createOperatorMap().optional(), + ends_at: createOperatorMap().optional(), + status: z.array(z.nativeEnum(PriceListStatus)).optional(), + rules_count: z.array(z.number()).optional(), + $and: z.lazy(() => AdminGetPriceListsParams.array()).optional(), + $or: z.lazy(() => AdminGetPriceListsParams.array()).optional(), + }) +) -export const AdminGetPriceListParams = createFindParams({ - offset: 0, - limit: 50, -}) +export const AdminGetPriceListParams = createSelectParams() export const AdminCreatePriceListPrice = z.object({ currency_code: z.string(), diff --git a/packages/medusa/src/api-v2/admin/regions/validators.ts b/packages/medusa/src/api-v2/admin/regions/validators.ts index 2b4050c311..190cc259f3 100644 --- a/packages/medusa/src/api-v2/admin/regions/validators.ts +++ b/packages/medusa/src/api-v2/admin/regions/validators.ts @@ -14,6 +14,7 @@ export const AdminGetRegionsParams = createFindParams({ offset: 0, }).merge( z.object({ + q: z.string().optional(), id: z.union([z.string(), z.array(z.string())]).optional(), code: z.union([z.string(), z.array(z.string())]).optional(), name: z.union([z.string(), z.array(z.string())]).optional(), diff --git a/packages/medusa/src/api-v2/admin/sales-channels/validators.ts b/packages/medusa/src/api-v2/admin/sales-channels/validators.ts index ccbcb437a6..7df80e4011 100644 --- a/packages/medusa/src/api-v2/admin/sales-channels/validators.ts +++ b/packages/medusa/src/api-v2/admin/sales-channels/validators.ts @@ -18,6 +18,7 @@ export const AdminGetSalesChannelsParams = createFindParams({ offset: 0, }).merge( z.object({ + q: z.string().optional(), id: z.union([z.string(), z.array(z.string())]).optional(), name: z.union([z.string(), z.array(z.string())]).optional(), description: z.string().optional(), diff --git a/packages/medusa/src/api-v2/admin/stores/validators.ts b/packages/medusa/src/api-v2/admin/stores/validators.ts index 908f2b528a..82124970d7 100644 --- a/packages/medusa/src/api-v2/admin/stores/validators.ts +++ b/packages/medusa/src/api-v2/admin/stores/validators.ts @@ -10,6 +10,7 @@ export const AdminGetStoresParams = createFindParams({ offset: 0, }).merge( z.object({ + q: z.string().optional(), id: z.union([z.string(), z.array(z.string())]).optional(), name: z.union([z.string(), z.array(z.string())]).optional(), $and: z.lazy(() => AdminGetStoresParams.array()).optional(), diff --git a/packages/medusa/src/api-v2/admin/tax-regions/validators.ts b/packages/medusa/src/api-v2/admin/tax-regions/validators.ts index 11bf4f3b87..56332daddb 100644 --- a/packages/medusa/src/api-v2/admin/tax-regions/validators.ts +++ b/packages/medusa/src/api-v2/admin/tax-regions/validators.ts @@ -18,8 +18,8 @@ export const AdminGetTaxRegionsParams = createFindParams({ offset: 0, }).merge( z.object({ - id: z.union([z.string(), z.array(z.string())]).optional(), q: z.string().optional(), + id: z.union([z.string(), z.array(z.string())]).optional(), country_code: z .union([z.string(), z.array(z.string()), createOperatorMap()]) .optional(), diff --git a/packages/medusa/src/api-v2/admin/users/validators.ts b/packages/medusa/src/api-v2/admin/users/validators.ts index d38ef5d6a1..8489fc1cce 100644 --- a/packages/medusa/src/api-v2/admin/users/validators.ts +++ b/packages/medusa/src/api-v2/admin/users/validators.ts @@ -13,6 +13,7 @@ export const AdminGetUsersParams = createFindParams({ limit: 50, }).merge( z.object({ + q: z.string().optional(), id: z.union([z.string(), z.array(z.string())]).optional(), created_at: createOperatorMap().optional(), updated_at: createOperatorMap().optional(), @@ -20,7 +21,6 @@ export const AdminGetUsersParams = createFindParams({ email: z.string().optional(), first_name: z.string().optional(), last_name: z.string().optional(), - q: z.string().optional(), }) ) diff --git a/packages/payment/src/models/payment.ts b/packages/payment/src/models/payment.ts index 0800b6a903..5ee84bf01b 100644 --- a/packages/payment/src/models/payment.ts +++ b/packages/payment/src/models/payment.ts @@ -3,6 +3,7 @@ import { BigNumber, DALUtils, MikroOrmBigNumberProperty, + Searchable, generateEntityId, } from "@medusajs/utils" import { @@ -46,12 +47,15 @@ export default class Payment { @Property({ columnType: "text" }) provider_id: string + @Searchable() @Property({ columnType: "text", nullable: true }) cart_id: string | null = null + @Searchable() @Property({ columnType: "text", nullable: true }) order_id: string | null = null + @Searchable() @Property({ columnType: "text", nullable: true }) customer_id: string | null = null diff --git a/packages/pricing/src/models/price-list.ts b/packages/pricing/src/models/price-list.ts index 671fbe5637..1d3679de82 100644 --- a/packages/pricing/src/models/price-list.ts +++ b/packages/pricing/src/models/price-list.ts @@ -5,6 +5,7 @@ import { generateEntityId, PriceListStatus, PriceListType, + Searchable, } from "@medusajs/utils" import { BeforeCreate, @@ -46,9 +47,11 @@ export default class PriceList { @PrimaryKey({ columnType: "text" }) id!: string + @Searchable() @Property({ columnType: "text" }) title: string + @Searchable() @Property({ columnType: "text" }) description: string diff --git a/packages/promotion/src/models/campaign.ts b/packages/promotion/src/models/campaign.ts index 056f8ea802..6874398035 100644 --- a/packages/promotion/src/models/campaign.ts +++ b/packages/promotion/src/models/campaign.ts @@ -1,5 +1,5 @@ import { DAL } from "@medusajs/types" -import { DALUtils, generateEntityId } from "@medusajs/utils" +import { DALUtils, Searchable, generateEntityId } from "@medusajs/utils" import { BeforeCreate, Collection, @@ -32,9 +32,11 @@ export default class Campaign { @PrimaryKey({ columnType: "text" }) id!: string + @Searchable() @Property({ columnType: "text" }) name: string + @Searchable() @Property({ columnType: "text", nullable: true }) description: string | null = null diff --git a/packages/promotion/src/models/promotion.ts b/packages/promotion/src/models/promotion.ts index 29de7193f4..bee0fe91c3 100644 --- a/packages/promotion/src/models/promotion.ts +++ b/packages/promotion/src/models/promotion.ts @@ -1,5 +1,10 @@ import { DAL, PromotionTypeValues } from "@medusajs/types" -import { DALUtils, PromotionUtils, generateEntityId } from "@medusajs/utils" +import { + DALUtils, + PromotionUtils, + Searchable, + generateEntityId, +} from "@medusajs/utils" import { BeforeCreate, Collection, @@ -31,6 +36,7 @@ export default class Promotion { @PrimaryKey({ columnType: "text" }) id!: string + @Searchable() @Property({ columnType: "text" }) @Index({ name: "IDX_promotion_code" }) @Unique({ @@ -39,6 +45,7 @@ export default class Promotion { }) code: string + @Searchable() @ManyToOne(() => Campaign, { fieldName: "campaign_id", nullable: true, diff --git a/packages/region/src/models/region.ts b/packages/region/src/models/region.ts index 5ac1fdb773..2196a325fb 100644 --- a/packages/region/src/models/region.ts +++ b/packages/region/src/models/region.ts @@ -1,5 +1,5 @@ import { DAL } from "@medusajs/types" -import { DALUtils, generateEntityId } from "@medusajs/utils" +import { DALUtils, Searchable, generateEntityId } from "@medusajs/utils" import { BeforeCreate, Collection, @@ -24,9 +24,11 @@ export default class Region { @PrimaryKey({ columnType: "text" }) id: string + @Searchable() @Property({ columnType: "text" }) name: string + @Searchable() @Property({ columnType: "text" }) currency_code: string diff --git a/packages/sales-channel/src/models/sales-channel.ts b/packages/sales-channel/src/models/sales-channel.ts index ac89db208a..96827b3d6a 100644 --- a/packages/sales-channel/src/models/sales-channel.ts +++ b/packages/sales-channel/src/models/sales-channel.ts @@ -1,4 +1,4 @@ -import { DALUtils, generateEntityId } from "@medusajs/utils" +import { DALUtils, Searchable, generateEntityId } from "@medusajs/utils" import { DAL } from "@medusajs/types" import { @@ -22,9 +22,11 @@ export default class SalesChannel { @PrimaryKey({ columnType: "text" }) id!: string + @Searchable() @Property({ columnType: "text" }) name!: string + @Searchable() @Property({ columnType: "text", nullable: true }) description: string | null = null diff --git a/packages/stock-location/src/models/stock-location-address.ts b/packages/stock-location/src/models/stock-location-address.ts index 5f3d8d3faa..f2068833e9 100644 --- a/packages/stock-location/src/models/stock-location-address.ts +++ b/packages/stock-location/src/models/stock-location-address.ts @@ -1,4 +1,4 @@ -import { generateEntityId } from "@medusajs/utils" +import { Searchable, generateEntityId } from "@medusajs/utils" import { BeforeInsert, Column, @@ -24,15 +24,19 @@ export class StockLocationAddress { @DeleteDateColumn({ type: "timestamptz" }) deleted_at: Date | null + @Searchable() @Column({ type: "text" }) address_1: string + @Searchable() @Column({ type: "text", nullable: true }) address_2: string | null + @Searchable() @Column({ type: "text", nullable: true }) company: string | null + @Searchable() @Column({ type: "text", nullable: true }) city: string | null @@ -43,9 +47,11 @@ export class StockLocationAddress { @Column({ type: "text", nullable: true }) phone: string | null + @Searchable() @Column({ type: "text", nullable: true }) province: string | null + @Searchable() @Column({ type: "text", nullable: true }) postal_code: string | null diff --git a/packages/stock-location/src/models/stock-location.ts b/packages/stock-location/src/models/stock-location.ts index ebf857c7da..f6e1df6945 100644 --- a/packages/stock-location/src/models/stock-location.ts +++ b/packages/stock-location/src/models/stock-location.ts @@ -1,4 +1,4 @@ -import { generateEntityId } from "@medusajs/utils" +import { Searchable, generateEntityId } from "@medusajs/utils" import { BeforeInsert, Column, @@ -27,6 +27,7 @@ export class StockLocation { @DeleteDateColumn({ type: "timestamptz" }) deleted_at: Date | null + @Searchable() @Column({ type: "text" }) name: string @@ -34,6 +35,7 @@ export class StockLocation { @Column({ type: "text", nullable: true }) address_id: string | null + @Searchable() @ManyToOne(() => StockLocationAddress) @JoinColumn({ name: "address_id" }) address: StockLocationAddress | null diff --git a/packages/store/src/models/store.ts b/packages/store/src/models/store.ts index ab45877f50..752a654105 100644 --- a/packages/store/src/models/store.ts +++ b/packages/store/src/models/store.ts @@ -1,5 +1,6 @@ import { DALUtils, + Searchable, createPsqlIndexStatementHelper, generateEntityId, } from "@medusajs/utils" @@ -32,6 +33,7 @@ export default class Store { @PrimaryKey({ columnType: "text" }) id: string + @Searchable() @Property({ columnType: "text", default: "Medusa Store" }) name: string diff --git a/packages/types/src/api-key/common/api-key.ts b/packages/types/src/api-key/common/api-key.ts index 86b9bbe40c..45f7c74140 100644 --- a/packages/types/src/api-key/common/api-key.ts +++ b/packages/types/src/api-key/common/api-key.ts @@ -67,6 +67,10 @@ export interface ApiKeyDTO { */ export interface FilterableApiKeyProps extends BaseFilterable { + /** + * Search through the api key names and redacted keys using this search term. + */ + q?: string /** * The IDs to filter the API keys by. */ diff --git a/packages/types/src/currency/common/currency.ts b/packages/types/src/currency/common/currency.ts index b7fa283d95..4e5423c9c5 100644 --- a/packages/types/src/currency/common/currency.ts +++ b/packages/types/src/currency/common/currency.ts @@ -43,6 +43,10 @@ export interface CurrencyDTO { */ export interface FilterableCurrencyProps extends BaseFilterable { + /** + * Search through currencies using this search term. + */ + q?: string /** * The codes to filter the currencies by. */ diff --git a/packages/types/src/customer/common.ts b/packages/types/src/customer/common.ts index d220dd75e7..2d86ac8a4d 100644 --- a/packages/types/src/customer/common.ts +++ b/packages/types/src/customer/common.ts @@ -102,6 +102,11 @@ export interface CustomerAddressDTO { */ export interface FilterableCustomerAddressProps extends BaseFilterable { + /** + * Searches for addreses by properties such as name and street using this search term. + */ + q?: string + /** * The IDs to filter the customer address by. */ @@ -203,6 +208,11 @@ export interface FilterableCustomerAddressProps */ export interface FilterableCustomerGroupProps extends BaseFilterable { + /** + * Searches for customer groups by name using this search term. + */ + q?: string + /** * The IDs to filter the customer group by. */ @@ -285,6 +295,11 @@ export interface FilterableCustomerGroupCustomerProps */ export interface FilterableCustomerProps extends BaseFilterable { + /** + * Searches for customers by properties such as name and email using this search term. + */ + q?: string + /** * The IDs to filter the customer by. */ diff --git a/packages/types/src/inventory/common/inventory-item.ts b/packages/types/src/inventory/common/inventory-item.ts index 4f788d313e..da10d03150 100644 --- a/packages/types/src/inventory/common/inventory-item.ts +++ b/packages/types/src/inventory/common/inventory-item.ts @@ -101,6 +101,11 @@ export interface InventoryItemDTO { * The filters to apply on retrieved inventory items. */ export interface FilterableInventoryItemProps { + /** + * Search term to search inventory items' attributes. + */ + q?: string + /** * The IDs to filter inventory items by. */ @@ -111,11 +116,6 @@ export interface FilterableInventoryItemProps { */ location_id?: string | string[] - /** - * Search term to search inventory items' attributes. - */ - q?: string - /** * The SKUs to filter inventory items by. */ diff --git a/packages/types/src/payment/common.ts b/packages/types/src/payment/common.ts index e9b22ed1d2..0f208f12ef 100644 --- a/packages/types/src/payment/common.ts +++ b/packages/types/src/payment/common.ts @@ -419,6 +419,11 @@ export interface PaymentDTO { */ export interface FilterablePaymentProps extends BaseFilterable { + /** + * Find payments based on cart, order, or customer IDs through this search term. + */ + q?: string + /** * The IDs to filter the payments by. */ diff --git a/packages/types/src/pricing/common/price-list.ts b/packages/types/src/pricing/common/price-list.ts index 96b4ce78ca..7320e8851c 100644 --- a/packages/types/src/pricing/common/price-list.ts +++ b/packages/types/src/pricing/common/price-list.ts @@ -1,4 +1,4 @@ -import { BaseFilterable } from "../../dal" +import { BaseFilterable, OperatorMap } from "../../dal" import { CreateMoneyAmountDTO, MoneyAmountDTO, @@ -240,18 +240,22 @@ export interface UpdatePriceListDTO { */ export interface FilterablePriceListProps extends BaseFilterable { + /** + * Find price lists by title or description through this search term. + */ + q?: string /** * The IDs to filter price lists by */ - id?: string[] + id?: string | string[] /** * The start dates to filter price lists by. */ - starts_at?: string[] + starts_at?: OperatorMap /** * The end dates to filter price lists by. */ - ends_at?: string[] + ends_at?: OperatorMap /** * The statuses to filter price lists by. */ diff --git a/packages/types/src/product/common.ts b/packages/types/src/product/common.ts index 5e62cd0d95..96da2f0fc4 100644 --- a/packages/types/src/product/common.ts +++ b/packages/types/src/product/common.ts @@ -888,6 +888,10 @@ export interface FilterableProductVariantProps */ export interface FilterableProductCategoryProps extends BaseFilterable { + /** + * Filter product categories based on searchable fields + */ + q?: string /** * The IDs to filter product categories by. */ @@ -920,10 +924,6 @@ export interface FilterableProductCategoryProps * Whether to include parents of retrieved product categories. */ include_ancestors_tree?: boolean - /** - * Filter product categories based on searchable fields - */ - q?: string } /** diff --git a/packages/types/src/promotion/common/campaign.ts b/packages/types/src/promotion/common/campaign.ts index dbd685a6af..fa502c1b27 100644 --- a/packages/types/src/promotion/common/campaign.ts +++ b/packages/types/src/promotion/common/campaign.ts @@ -51,6 +51,10 @@ export interface CampaignDTO { */ export interface FilterableCampaignProps extends BaseFilterable { + /** + * Find campaigns by their name or description through this search term. + */ + q?: string /** * The IDs to filter the campaigns by. */ diff --git a/packages/types/src/promotion/common/promotion.ts b/packages/types/src/promotion/common/promotion.ts index 6bc0cec185..73bd193ee8 100644 --- a/packages/types/src/promotion/common/promotion.ts +++ b/packages/types/src/promotion/common/promotion.ts @@ -141,6 +141,11 @@ export interface UpdatePromotionDTO { */ export interface FilterablePromotionProps extends BaseFilterable { + /** + * The IDs to filter the promotions by. + */ + q?: string + /** * The IDs to filter the promotions by. */ diff --git a/packages/types/src/region/common.ts b/packages/types/src/region/common.ts index 5a14aa2cb6..ee815c36c4 100644 --- a/packages/types/src/region/common.ts +++ b/packages/types/src/region/common.ts @@ -90,6 +90,10 @@ export interface RegionCountryDTO { */ export interface FilterableRegionProps extends BaseFilterable { + /** + * Find regions by name through this search term + */ + q?: string /** * The IDs to filter the regions by. */ diff --git a/packages/types/src/sales-channel/common.ts b/packages/types/src/sales-channel/common.ts index 703c5cd23f..2c88116145 100644 --- a/packages/types/src/sales-channel/common.ts +++ b/packages/types/src/sales-channel/common.ts @@ -60,6 +60,11 @@ export interface SalesChannelDTO { */ export interface FilterableSalesChannelProps extends BaseFilterable { + /** + * Find sales channels by their name or description through this search term. + */ + q?: string + /** * The IDs to filter the sales channel by. */ diff --git a/packages/types/src/store/common/store.ts b/packages/types/src/store/common/store.ts index 56594f9828..1f0f242c45 100644 --- a/packages/types/src/store/common/store.ts +++ b/packages/types/src/store/common/store.ts @@ -60,6 +60,10 @@ export interface StoreDTO { */ export interface FilterableStoreProps extends BaseFilterable { + /** + * Find stores by name through this search term. + */ + q?: string /** * The IDs to filter the stores by. */ diff --git a/packages/types/src/tax/common.ts b/packages/types/src/tax/common.ts index 6a054289e4..dcc73511bd 100644 --- a/packages/types/src/tax/common.ts +++ b/packages/types/src/tax/common.ts @@ -93,6 +93,11 @@ export interface TaxProviderDTO { */ export interface FilterableTaxRateProps extends BaseFilterable { + /** + * Find tax rates based on name and code properties through this search term. + */ + q?: string + /** * The IDs to filter the tax rates by. */ @@ -190,6 +195,11 @@ export interface TaxRegionDTO { */ export interface FilterableTaxRegionProps extends BaseFilterable { + /** + * Find tax regions based on currency and province codes through this search term. + */ + q?: string + /** * The IDs to filter the tax regions by. */ diff --git a/packages/types/src/user/common.ts b/packages/types/src/user/common.ts index 121f62a1d8..efd2e7f4e6 100644 --- a/packages/types/src/user/common.ts +++ b/packages/types/src/user/common.ts @@ -52,6 +52,10 @@ export interface UserDTO { */ export interface FilterableUserProps extends BaseFilterable { + /** + * Find users by name or email through this search term + */ + q?: string /** * The IDs to filter users by. */