medusa-product-helper 0.0.12 → 0.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. package/.medusa/server/src/api/store/product-helper/products/route.js +76 -0
  2. package/.medusa/server/src/api/store/product-helper/products/validators.js +2 -1
  3. package/.medusa/server/src/config/product-helper-options.js +15 -1
  4. package/.medusa/server/src/helpers/wishlist.js +6 -13
  5. package/.medusa/server/src/index.js +101 -0
  6. package/.medusa/server/src/providers/filter-providers/availability-provider.js +96 -0
  7. package/.medusa/server/src/providers/filter-providers/base-filter-provider.js +32 -0
  8. package/.medusa/server/src/providers/filter-providers/base-product-provider.js +122 -0
  9. package/.medusa/server/src/providers/filter-providers/category-provider.js +55 -0
  10. package/.medusa/server/src/providers/filter-providers/collection-provider.js +53 -0
  11. package/.medusa/server/src/providers/filter-providers/index.js +94 -0
  12. package/.medusa/server/src/providers/filter-providers/metadata-provider.js +88 -0
  13. package/.medusa/server/src/providers/filter-providers/price-range-provider.js +108 -0
  14. package/.medusa/server/src/providers/filter-providers/promotion-provider.js +197 -0
  15. package/.medusa/server/src/providers/filter-providers/promotion-window-provider.js +125 -0
  16. package/.medusa/server/src/providers/filter-providers/rating-provider.js +92 -0
  17. package/.medusa/server/src/services/dynamic-filter-service.js +814 -0
  18. package/.medusa/server/src/services/filter-provider-loader.js +155 -0
  19. package/.medusa/server/src/services/filter-provider-registry.js +142 -0
  20. package/.medusa/server/src/services/product-filter-service.js +230 -0
  21. package/.medusa/server/src/utils/query-parser.js +103 -0
  22. package/README.md +142 -4
  23. package/package.json +3 -3
package/README.md CHANGED
@@ -147,6 +147,17 @@ const plugins = [
147
147
  // Require products to have at least one review
148
148
  require_reviews: false,
149
149
  },
150
+ // Custom filter providers (optional)
151
+ filterProviders: [
152
+ // File path (relative to project root)
153
+ "./src/providers/margin-provider.ts",
154
+ // Or module reference
155
+ "@my-org/custom-filters/brand-provider",
156
+ ],
157
+ // Disable specific built-in providers (optional)
158
+ disableBuiltInProviders: [
159
+ // "rating", // Uncomment to disable rating filter provider
160
+ ],
150
161
  },
151
162
  },
152
163
  ]
@@ -230,6 +241,84 @@ Configure rating-based filtering:
230
241
  - `max`: Maximum rating (0-5)
231
242
  - `require_reviews`: Require at least one review
232
243
 
244
+ #### Filter Providers
245
+
246
+ Configure custom filter providers:
247
+ - `filterProviders`: Array of file paths or module references to custom filter providers
248
+ - `disableBuiltInProviders`: Array of provider identifiers to disable (e.g., `["rating"]`)
249
+
250
+ See the [Provider Development Guide](./PROVIDER_DEVELOPMENT_GUIDE.md) for details on creating custom filter providers.
251
+
252
+ ## Dynamic Filter Provider System
253
+
254
+ The plugin includes a provider-based dynamic filter system that allows you to extend product filtering capabilities without modifying the plugin code. All built-in filters (category, collection, metadata, price range, etc.) are implemented as filter providers, and you can add your own custom providers.
255
+
256
+ ### Built-in Filter Providers
257
+
258
+ The plugin includes the following built-in filter providers:
259
+
260
+ - **Category Filter** (`category_id`): Filter products by category IDs
261
+ - **Collection Filter** (`collection_id`): Filter products by collection IDs
262
+ - **Metadata Filter** (`metadata`): Filter products by metadata with allowlist validation
263
+ - **Price Range Filter** (`price_range`): Filter products by price range (min/max)
264
+ - **Promotion Window Filter** (`promotion_window`): Filter products by promotion date windows
265
+ - **Availability Filter** (`availability`): Filter products by availability status
266
+ - **Rating Filter** (`rating`): Filter products by rating (min/max)
267
+ - **Base Product Filters** (`base_product`): Filter by ID, handle, tags, sales channel
268
+
269
+ ### Using Filters
270
+
271
+ All filters are available through the `/store/product-helper/products` endpoint:
272
+
273
+ ```bash
274
+ # Filter by category
275
+ GET /store/product-helper/products?category_id=cat_123,cat_456
276
+
277
+ # Filter by price range
278
+ GET /store/product-helper/products?price_min=10&price_max=100
279
+
280
+ # Filter by metadata (if filterable)
281
+ GET /store/product-helper/products?metadata[brand]=nike&metadata[color]=red
282
+
283
+ # Multiple filters
284
+ GET /store/product-helper/products?category_id=cat_123&price_min=10&rating_min=4
285
+ ```
286
+
287
+ ### Custom Filter Providers
288
+
289
+ You can create custom filter providers to add new filtering capabilities. See the [Provider Development Guide](./PROVIDER_DEVELOPMENT_GUIDE.md) for complete documentation.
290
+
291
+ **Quick Example:**
292
+
293
+ ```typescript
294
+ // src/providers/margin-provider.ts
295
+ import { BaseFilterProvider } from "medusa-product-helper/providers/filter-providers"
296
+
297
+ export class MarginFilterProvider extends BaseFilterProvider {
298
+ static readonly identifier = "margin"
299
+ static readonly displayName = "Margin Filter"
300
+
301
+ apply(filters: Record<string, unknown>, value: unknown): Record<string, unknown> {
302
+ if (!value || typeof value !== "object") return filters
303
+
304
+ const { min, max } = value as { min?: number; max?: number }
305
+ // Apply margin filter logic...
306
+ return filters
307
+ }
308
+ }
309
+ ```
310
+
311
+ Then register it in `medusa-config.ts`:
312
+
313
+ ```typescript
314
+ {
315
+ resolve: "medusa-product-helper",
316
+ options: {
317
+ filterProviders: ["./src/providers/margin-provider.ts"],
318
+ },
319
+ }
320
+ ```
321
+
233
322
  ## Wishlist Feature
234
323
 
235
324
  The plugin includes a comprehensive wishlist feature that allows customers to save products they're interested in and admins to view wishlist statistics.
@@ -448,11 +537,12 @@ import {
448
537
  #### Example Usage
449
538
 
450
539
  ```typescript
540
+ // Recommended: Using Bearer token for authentication
451
541
  const options: HelperTransportOptions = {
452
542
  baseUrl: "https://store.example.com",
453
543
  publishableApiKey: "pk_your_publishable_api_key",
454
544
  headers: {
455
- Cookie: "connect.sid=...", // or Authorization header
545
+ Authorization: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", // Customer JWT token
456
546
  },
457
547
  }
458
548
 
@@ -466,23 +556,44 @@ const { wishlist } = await getWishlist({ includeDetails: true }, options)
466
556
  await removeFromWishlist({ product_id: "prod_123" }, options)
467
557
  ```
468
558
 
559
+ **Alternative: Using session cookie**
560
+ ```typescript
561
+ const options: HelperTransportOptions = {
562
+ baseUrl: "https://store.example.com",
563
+ publishableApiKey: "pk_your_publishable_api_key",
564
+ headers: {
565
+ Cookie: "connect.sid=...", // Session cookie (browser-based)
566
+ },
567
+ }
568
+ ```
569
+
469
570
  #### Configuration Options
470
571
 
471
572
  All helper calls accept the following options:
472
573
 
473
574
  - `publishableApiKey`: Required for public storefront calls when not passing a Medusa JS client. Add it from **Settings → API Keys** in the Medusa dashboard.
474
- - `client`: Medusa JS/SDK client instance. When provided, network requests are delegated to `client.request` and the clients publishable key is reused.
575
+ - `client`: Medusa JS/SDK client instance. When provided, network requests are delegated to `client.request` and the client's publishable key is reused.
475
576
  - `baseUrl`: Base URL for the Store API (e.g., `https://store.example.com`). Required when a client is not provided.
476
577
  - `fetchImpl`: Custom `fetch` implementation for SSR or React Native environments. Defaults to `globalThis.fetch`.
477
- - `headers`: Additional headers appended to every request (useful for `Cookie` / `Authorization` headers).
578
+ - `headers`: Additional headers appended to every request. **Required for authenticated endpoints** - include `Authorization: Bearer <token>` for customer authentication:
579
+ ```ts
580
+ headers: {
581
+ "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
582
+ }
583
+ ```
584
+
585
+ **Note:** All wishlist endpoints require customer authentication. Pass the Bearer token via the `headers` option.
478
586
 
479
587
  You can also generate pre-configured helpers:
480
588
 
481
589
  ```typescript
590
+ // Recommended: Using Bearer token
482
591
  const wishlist = createWishlistHelpers({
483
592
  baseUrl: "https://store.example.com",
484
593
  publishableApiKey: "pk_your_publishable_api_key",
485
- headers: { Cookie: "connect.sid=..." },
594
+ headers: {
595
+ Authorization: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
596
+ },
486
597
  })
487
598
 
488
599
  await wishlist.addToWishlist({ product_id: "prod_123" })
@@ -490,6 +601,33 @@ const { wishlist: items } = await wishlist.getWishlist({ includeDetails: true })
490
601
  await wishlist.removeFromWishlist({ product_id: "prod_123" })
491
602
  ```
492
603
 
604
+ **Getting the Bearer Token:**
605
+ ```typescript
606
+ // Login to get JWT token
607
+ const loginResponse = await fetch("https://store.example.com/store/auth/customer/emailpass", {
608
+ method: "POST",
609
+ headers: {
610
+ "Content-Type": "application/json",
611
+ "x-publishable-api-key": "pk_your_publishable_api_key",
612
+ },
613
+ body: JSON.stringify({
614
+ email: "customer@example.com",
615
+ password: "password123",
616
+ }),
617
+ })
618
+
619
+ const { token } = await loginResponse.json()
620
+
621
+ // Use token in wishlist helpers
622
+ const wishlist = createWishlistHelpers({
623
+ baseUrl: "https://store.example.com",
624
+ publishableApiKey: "pk_your_publishable_api_key",
625
+ headers: {
626
+ Authorization: `Bearer ${token}`,
627
+ },
628
+ })
629
+ ```
630
+
493
631
  ### Using Workflows Directly
494
632
 
495
633
  You can also use the workflows directly in your custom code:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "medusa-product-helper",
3
- "version": "0.0.12",
3
+ "version": "0.0.16",
4
4
  "description": "A starter for Medusa plugins.",
5
5
  "author": "Medusa (https://medusajs.com)",
6
6
  "license": "MIT",
@@ -37,10 +37,10 @@
37
37
  "@medusajs/admin-sdk": "2.11.2",
38
38
  "@medusajs/cli": "2.11.2",
39
39
  "@medusajs/framework": "2.11.2",
40
+ "@medusajs/icons": "2.11.2",
40
41
  "@medusajs/medusa": "2.11.2",
41
42
  "@medusajs/test-utils": "2.11.2",
42
43
  "@medusajs/ui": "4.0.25",
43
- "@medusajs/icons": "2.11.2",
44
44
  "@swc/core": "1.5.7",
45
45
  "@types/node": "^20.0.0",
46
46
  "@types/react": "^18.3.2",
@@ -68,4 +68,4 @@
68
68
  "engines": {
69
69
  "node": ">=20"
70
70
  }
71
- }
71
+ }