@wix/headless-stores 0.0.48 → 0.0.50

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.
@@ -4,4 +4,4 @@ export { ProductModifiersService, ProductModifiersServiceDefinition, } from "./p
4
4
  export { ProductService, ProductServiceDefinition, loadProductServiceConfig, } from "./product-service.js";
5
5
  export { SelectedVariantService, SelectedVariantServiceDefinition, } from "./selected-variant-service.js";
6
6
  export { ProductListService, ProductsListServiceDefinition, loadProductsListServiceConfig, ProductsListServiceConfig, } from "./products-list-service.js";
7
- export { ProductOption, InventoryStatusType, SortType, ProductChoice, ProductsListSearchService, ProductsListSearchServiceDefinition, ProductsListSearchServiceConfig, loadProductsListSearchServiceConfig, parseUrlForProductsListSearch, convertUrlSortToSortType, } from "./products-list-search-service.js";
7
+ export { ProductOption, InventoryStatusType, SortType, ProductChoice, ProductsListSearchService, ProductsListSearchServiceDefinition, ProductsListSearchServiceConfig, loadProductsListSearchServiceConfig, parseUrlToSearchOptions, convertUrlSortToSortType, } from "./products-list-search-service.js";
@@ -4,4 +4,4 @@ export { ProductModifiersService, ProductModifiersServiceDefinition, } from "./p
4
4
  export { ProductService, ProductServiceDefinition, loadProductServiceConfig, } from "./product-service.js";
5
5
  export { SelectedVariantService, SelectedVariantServiceDefinition, } from "./selected-variant-service.js";
6
6
  export { ProductListService, ProductsListServiceDefinition, loadProductsListServiceConfig, } from "./products-list-service.js";
7
- export { InventoryStatusType, SortType, ProductsListSearchService, ProductsListSearchServiceDefinition, loadProductsListSearchServiceConfig, parseUrlForProductsListSearch, convertUrlSortToSortType, } from "./products-list-search-service.js";
7
+ export { InventoryStatusType, SortType, ProductsListSearchService, ProductsListSearchServiceDefinition, loadProductsListSearchServiceConfig, parseUrlToSearchOptions, convertUrlSortToSortType, } from "./products-list-search-service.js";
@@ -33,7 +33,7 @@ export interface ProductChoice {
33
33
  /**
34
34
  * Initial search state that can be loaded from URL parameters.
35
35
  */
36
- type InitialSearchState = {
36
+ export type InitialSearchState = {
37
37
  sort?: SortType;
38
38
  limit?: number;
39
39
  cursor?: string | null;
@@ -138,16 +138,75 @@ export declare const ProductsListSearchServiceDefinition: string & {
138
138
  */
139
139
  export declare function convertUrlSortToSortType(urlSort: string): SortType | null;
140
140
  /**
141
- * Parse URL and build complete search options with all filters, sort, and pagination
141
+ * Parse URL and build complete search options with all filters, sort, and pagination.
142
+ * This function extracts search parameters, filters, sorting, and pagination from a URL
143
+ * and converts them into the format expected by the Wix Stores API.
144
+ *
145
+ * @param {string} url - The URL to parse search parameters from
146
+ * @param {Category[]} categoriesList - List of available categories for category slug resolution
147
+ * @param {productsV3.V3ProductSearch} [defaultSearchOptions] - Default search options to merge with parsed URL parameters
148
+ * @returns {Promise<{searchOptions: productsV3.V3ProductSearch, initialSearchState: InitialSearchState}>}
149
+ * Object containing both API-ready search options and UI-ready initial state
150
+ *
151
+ * @example
152
+ * ```tsx
153
+ * // Parse URL with filters, sort, and pagination
154
+ * const categories = await loadCategoriesListServiceConfig();
155
+ * const { searchOptions, initialSearchState } = await parseUrlToSearchOptions(
156
+ * 'https://example.com/products?sort=price:desc&Color=red,blue&minPrice=50',
157
+ * categories.categories
158
+ * );
159
+ *
160
+ * // Use searchOptions for API calls
161
+ * const products = await productsV3.searchProducts(searchOptions);
162
+ *
163
+ * // Use initialSearchState for UI initialization
164
+ * const filterState = initialSearchState.productOptions; // { colorId: ['red-id', 'blue-id'] }
165
+ * ```
142
166
  */
143
- export declare function parseUrlForProductsListSearch(url: string, categoriesList: Category[], defaultSearchOptions?: productsV3.V3ProductSearch): Promise<{
167
+ export declare function parseUrlToSearchOptions(url: string, categoriesList: Category[], defaultSearchOptions?: productsV3.V3ProductSearch): Promise<{
144
168
  searchOptions: productsV3.V3ProductSearch;
145
169
  initialSearchState: InitialSearchState;
146
170
  }>;
147
171
  /**
148
- * Load search service configuration from URL
172
+ * Load search service configuration from URL or parsed URL result.
173
+ * This function provides the configuration for the Products List Search service,
174
+ * including customizations and initial search state.
175
+ *
176
+ * @param {string | { searchOptions: productsV3.V3ProductSearch; initialSearchState: InitialSearchState }} input - Either a URL to parse or parsed URL result from parseUrlToSearchOptions
177
+ * @returns {Promise<ProductsListSearchServiceConfig>} Promise that resolves to the search service configuration
178
+ *
179
+ * @example
180
+ * ```tsx
181
+ * // Option 1: Load from URL (will parse filters, sort, pagination from URL params)
182
+ * const searchConfig = await loadProductsListSearchServiceConfig(window.location.href);
183
+ *
184
+ * // Option 2: Custom parsing with defaults
185
+ * const categories = await loadCategoriesListServiceConfig();
186
+ * const parsed = await parseUrlToSearchOptions(
187
+ * window.location.href,
188
+ * categories.categories,
189
+ * {
190
+ * cursorPaging: { limit: 12 },
191
+ * filter: { 'categoryIds': ['123'] },
192
+ * sort: [{ fieldName: 'name' as const, order: 'ASC' as const }]
193
+ * }
194
+ * );
195
+ * const searchConfig = await loadProductsListSearchServiceConfig(parsed);
196
+ *
197
+ * // Option 3: Performance optimization - use parsed result for both services (no duplicate parsing)
198
+ * const categories = await loadCategoriesListServiceConfig();
199
+ * const parsed = await parseUrlToSearchOptions(url, categories.categories);
200
+ * const [productsConfig, searchConfig] = await Promise.all([
201
+ * loadProductsListServiceConfig(parsed),
202
+ * loadProductsListSearchServiceConfig(parsed),
203
+ * ]);
204
+ * ```
149
205
  */
150
- export declare function loadProductsListSearchServiceConfig(url: string): Promise<ProductsListSearchServiceConfig>;
206
+ export declare function loadProductsListSearchServiceConfig(input: string | {
207
+ searchOptions: productsV3.V3ProductSearch;
208
+ initialSearchState: InitialSearchState;
209
+ }): Promise<ProductsListSearchServiceConfig>;
151
210
  /**
152
211
  * Implementation of the Products List Search service
153
212
  */
@@ -164,9 +164,33 @@ function updateUrlWithSearchState(searchState) {
164
164
  }
165
165
  }
166
166
  /**
167
- * Parse URL and build complete search options with all filters, sort, and pagination
167
+ * Parse URL and build complete search options with all filters, sort, and pagination.
168
+ * This function extracts search parameters, filters, sorting, and pagination from a URL
169
+ * and converts them into the format expected by the Wix Stores API.
170
+ *
171
+ * @param {string} url - The URL to parse search parameters from
172
+ * @param {Category[]} categoriesList - List of available categories for category slug resolution
173
+ * @param {productsV3.V3ProductSearch} [defaultSearchOptions] - Default search options to merge with parsed URL parameters
174
+ * @returns {Promise<{searchOptions: productsV3.V3ProductSearch, initialSearchState: InitialSearchState}>}
175
+ * Object containing both API-ready search options and UI-ready initial state
176
+ *
177
+ * @example
178
+ * ```tsx
179
+ * // Parse URL with filters, sort, and pagination
180
+ * const categories = await loadCategoriesListServiceConfig();
181
+ * const { searchOptions, initialSearchState } = await parseUrlToSearchOptions(
182
+ * 'https://example.com/products?sort=price:desc&Color=red,blue&minPrice=50',
183
+ * categories.categories
184
+ * );
185
+ *
186
+ * // Use searchOptions for API calls
187
+ * const products = await productsV3.searchProducts(searchOptions);
188
+ *
189
+ * // Use initialSearchState for UI initialization
190
+ * const filterState = initialSearchState.productOptions; // { colorId: ['red-id', 'blue-id'] }
191
+ * ```
168
192
  */
169
- export async function parseUrlForProductsListSearch(url, categoriesList, defaultSearchOptions) {
193
+ export async function parseUrlToSearchOptions(url, categoriesList, defaultSearchOptions) {
170
194
  const urlObj = new URL(url);
171
195
  const searchParams = urlObj.searchParams;
172
196
  // Get customizations for product option parsing
@@ -182,19 +206,16 @@ export async function parseUrlForProductsListSearch(url, categoriesList, default
182
206
  };
183
207
  // Initialize search state for service
184
208
  const initialSearchState = {};
185
- // Extract category slug from URL path (e.g., /category/category-slug)
186
- const pathSegments = urlObj.pathname.split("/");
187
- const categoryIndex = pathSegments.findIndex((segment) => segment === "category");
188
- let categorySlug = null;
209
+ // Extract category slug from URL path
210
+ // The category slug is always the last segment of the path
211
+ const pathSegments = urlObj.pathname.split("/").filter(Boolean);
189
212
  let category = undefined;
190
- if (categoryIndex !== -1 && categoryIndex + 1 < pathSegments.length) {
191
- categorySlug = pathSegments[categoryIndex + 1] || null;
192
- // Find the category by slug from the provided categories list
193
- if (categorySlug) {
194
- category = categoriesList.find((cat) => cat.slug === categorySlug);
195
- if (category) {
196
- initialSearchState.category = category;
197
- }
213
+ if (pathSegments.length > 0) {
214
+ const lastSegment = pathSegments[pathSegments.length - 1];
215
+ // Check if the last segment matches any category in the categories list
216
+ category = categoriesList.find((cat) => cat.slug === lastSegment);
217
+ if (category) {
218
+ initialSearchState.category = category;
198
219
  }
199
220
  }
200
221
  // Handle text search (q parameter)
@@ -399,12 +420,52 @@ export async function parseUrlForProductsListSearch(url, categoriesList, default
399
420
  return { searchOptions, initialSearchState };
400
421
  }
401
422
  /**
402
- * Load search service configuration from URL
423
+ * Load search service configuration from URL or parsed URL result.
424
+ * This function provides the configuration for the Products List Search service,
425
+ * including customizations and initial search state.
426
+ *
427
+ * @param {string | { searchOptions: productsV3.V3ProductSearch; initialSearchState: InitialSearchState }} input - Either a URL to parse or parsed URL result from parseUrlToSearchOptions
428
+ * @returns {Promise<ProductsListSearchServiceConfig>} Promise that resolves to the search service configuration
429
+ *
430
+ * @example
431
+ * ```tsx
432
+ * // Option 1: Load from URL (will parse filters, sort, pagination from URL params)
433
+ * const searchConfig = await loadProductsListSearchServiceConfig(window.location.href);
434
+ *
435
+ * // Option 2: Custom parsing with defaults
436
+ * const categories = await loadCategoriesListServiceConfig();
437
+ * const parsed = await parseUrlToSearchOptions(
438
+ * window.location.href,
439
+ * categories.categories,
440
+ * {
441
+ * cursorPaging: { limit: 12 },
442
+ * filter: { 'categoryIds': ['123'] },
443
+ * sort: [{ fieldName: 'name' as const, order: 'ASC' as const }]
444
+ * }
445
+ * );
446
+ * const searchConfig = await loadProductsListSearchServiceConfig(parsed);
447
+ *
448
+ * // Option 3: Performance optimization - use parsed result for both services (no duplicate parsing)
449
+ * const categories = await loadCategoriesListServiceConfig();
450
+ * const parsed = await parseUrlToSearchOptions(url, categories.categories);
451
+ * const [productsConfig, searchConfig] = await Promise.all([
452
+ * loadProductsListServiceConfig(parsed),
453
+ * loadProductsListSearchServiceConfig(parsed),
454
+ * ]);
455
+ * ```
403
456
  */
404
- export async function loadProductsListSearchServiceConfig(url) {
405
- // Load categories using the categories service
406
- const categoriesListConfig = await loadCategoriesListServiceConfig();
407
- const { initialSearchState } = await parseUrlForProductsListSearch(url, categoriesListConfig.categories);
457
+ export async function loadProductsListSearchServiceConfig(input) {
458
+ let initialSearchState;
459
+ if (typeof input === "string") {
460
+ // URL input - parse it
461
+ const categoriesListConfig = await loadCategoriesListServiceConfig();
462
+ const { initialSearchState: parsedState } = await parseUrlToSearchOptions(input, categoriesListConfig.categories);
463
+ initialSearchState = parsedState;
464
+ }
465
+ else {
466
+ // Parsed URL result - use initialSearchState directly (no duplicate work)
467
+ initialSearchState = input.initialSearchState;
468
+ }
408
469
  const { items: customizations = [] } = await customizationsV3
409
470
  .queryCustomizations()
410
471
  .find();
@@ -1,5 +1,6 @@
1
1
  import { type Signal } from "@wix/services-definitions/core-services/signals";
2
2
  import { productsV3 } from "@wix/stores";
3
+ import { type InitialSearchState } from "./products-list-search-service.js";
3
4
  export declare const DEFAULT_QUERY_LIMIT = 100;
4
5
  /**
5
6
  * Configuration interface for the Products List service.
@@ -20,27 +21,33 @@ export type ProductsListServiceConfig = {
20
21
  /**
21
22
  * Loads products list service configuration from the Wix Stores API for SSR initialization.
22
23
  * This function is designed to be used during Server-Side Rendering (SSR) to preload
23
- * a list of products based on search criteria.
24
+ * a list of products based on search criteria or URL parameters.
24
25
  *
25
- * @param {productsV3.V3ProductSearch} searchOptions - The search options for querying products
26
+ * @param {string | { searchOptions: productsV3.V3ProductSearch; initialSearchState: InitialSearchState }} input - Either a URL to parse or parsed URL result from parseUrlToSearchOptions
26
27
  * @returns {Promise<ProductsListServiceConfig>} Promise that resolves to the products list configuration
27
28
  *
28
29
  * @example
29
30
  * ```astro
30
31
  * ---
31
32
  * // Astro page example - pages/products.astro
32
- * import { loadProductsListServiceConfig } from '@wix/stores/services';
33
+ * import { loadProductsListServiceConfig, parseUrlToSearchOptions, loadCategoriesListServiceConfig } from '@wix/stores/services';
33
34
  * import { ProductList } from '@wix/stores/components';
34
35
  *
35
- * // Define search options
36
- * const searchOptions = {
37
- * cursorPaging: { limit: 12 },
38
- * filter: {},
39
- * sort: [{ fieldName: 'name', order: 'ASC' }]
40
- * };
36
+ * // Option 1: Load from URL (will parse filters, sort, pagination from URL params)
37
+ * const productsConfig = await loadProductsListServiceConfig(Astro.url.href);
41
38
  *
42
- * // Load products data during SSR
43
- * const productsConfig = await loadProductsListServiceConfig(searchOptions);
39
+ * // Option 2: Custom parsing with defaults
40
+ * const categories = await loadCategoriesListServiceConfig();
41
+ * const parsed = await parseUrlToSearchOptions(
42
+ * Astro.url.href,
43
+ * categories.categories,
44
+ * {
45
+ * cursorPaging: { limit: 12 },
46
+ * filter: {},
47
+ * sort: [{ fieldName: 'name' as const, order: 'ASC' as const }]
48
+ * }
49
+ * );
50
+ * const productsConfig = await loadProductsListServiceConfig(parsed);
44
51
  * ---
45
52
  *
46
53
  * <ProductList.Root productsConfig={productsConfig}>
@@ -59,23 +66,31 @@ export type ProductsListServiceConfig = {
59
66
  * ```tsx
60
67
  * // Next.js page example - pages/products.tsx
61
68
  * import { GetServerSideProps } from 'next';
62
- * import { loadProductsListServiceConfig } from '@wix/stores/services';
69
+ * import { loadProductsListServiceConfig, parseUrlToSearchOptions, loadCategoriesListServiceConfig } from '@wix/stores/services';
63
70
  * import { ProductsList } from '@wix/stores/components';
64
71
  *
65
72
  * interface ProductsPageProps {
66
73
  * productsConfig: Awaited<ReturnType<typeof loadProductsListServiceConfig>>;
67
74
  * }
68
75
  *
69
- * export const getServerSideProps: GetServerSideProps<ProductsPageProps> = async () => {
70
- * const searchOptions = {
71
- * cursorPaging: { limit: 12 },
72
- * filter: {
73
- * 'allCategoriesInfo.categories': { $matchItems: [{ _id: { $in: [category._id] } }] }
74
- * },
75
- * sort: [{ fieldName: 'name' as const, order: 'ASC' as const }]
76
- * };
76
+ * export const getServerSideProps: GetServerSideProps<ProductsPageProps> = async ({ req }) => {
77
+ * // Option 1: Parse from URL
78
+ * const productsConfig = await loadProductsListServiceConfig(`${req.url}`);
77
79
  *
78
- * const productsConfig = await loadProductsListServiceConfig(searchOptions);
80
+ * // Option 2: Custom parsing with filters
81
+ * const categories = await loadCategoriesListServiceConfig();
82
+ * const parsed = await parseUrlToSearchOptions(
83
+ * `${req.url}`,
84
+ * categories.categories,
85
+ * {
86
+ * cursorPaging: { limit: 12 },
87
+ * filter: {
88
+ * 'allCategoriesInfo.categories': { $matchItems: [{ _id: { $in: [category._id] } }] }
89
+ * },
90
+ * sort: [{ fieldName: 'name' as const, order: 'ASC' as const }]
91
+ * }
92
+ * );
93
+ * const productsConfig = await loadProductsListServiceConfig(parsed);
79
94
  *
80
95
  * return {
81
96
  * props: {
@@ -99,8 +114,26 @@ export type ProductsListServiceConfig = {
99
114
  * );
100
115
  * }
101
116
  * ```
117
+ *
118
+ * @example
119
+ * ```tsx
120
+ * // Advanced: Performance optimization when using both services
121
+ * import { parseUrlToSearchOptions, loadProductsListServiceConfig, loadProductsListSearchServiceConfig, loadCategoriesListServiceConfig } from '@wix/stores/services';
122
+ *
123
+ * const categories = await loadCategoriesListServiceConfig();
124
+ * const parsed = await parseUrlToSearchOptions(url, categories.categories);
125
+ *
126
+ * // Both services use the same parsed result (no duplicate URL parsing)
127
+ * const [productsConfig, searchConfig] = await Promise.all([
128
+ * loadProductsListServiceConfig(parsed),
129
+ * loadProductsListSearchServiceConfig(parsed)
130
+ * ]);
131
+ * ```
102
132
  */
103
- export declare function loadProductsListServiceConfig(searchOptions: productsV3.V3ProductSearch): Promise<ProductsListServiceConfig>;
133
+ export declare function loadProductsListServiceConfig(input: string | {
134
+ searchOptions: productsV3.V3ProductSearch;
135
+ initialSearchState: InitialSearchState;
136
+ }): Promise<ProductsListServiceConfig>;
104
137
  /**
105
138
  * Service definition for the Products List service.
106
139
  * This defines the reactive API contract for managing a list of products with search, pagination, and filtering capabilities.
@@ -1,31 +1,39 @@
1
1
  import { defineService, implementService } from "@wix/services-definitions";
2
2
  import { SignalsServiceDefinition, } from "@wix/services-definitions/core-services/signals";
3
3
  import { productsV3, readOnlyVariantsV3 } from "@wix/stores";
4
+ import { loadCategoriesListServiceConfig } from "./categories-list-service.js";
5
+ import { parseUrlToSearchOptions } from "./products-list-search-service.js";
4
6
  export const DEFAULT_QUERY_LIMIT = 100;
5
7
  /**
6
8
  * Loads products list service configuration from the Wix Stores API for SSR initialization.
7
9
  * This function is designed to be used during Server-Side Rendering (SSR) to preload
8
- * a list of products based on search criteria.
10
+ * a list of products based on search criteria or URL parameters.
9
11
  *
10
- * @param {productsV3.V3ProductSearch} searchOptions - The search options for querying products
12
+ * @param {string | { searchOptions: productsV3.V3ProductSearch; initialSearchState: InitialSearchState }} input - Either a URL to parse or parsed URL result from parseUrlToSearchOptions
11
13
  * @returns {Promise<ProductsListServiceConfig>} Promise that resolves to the products list configuration
12
14
  *
13
15
  * @example
14
16
  * ```astro
15
17
  * ---
16
18
  * // Astro page example - pages/products.astro
17
- * import { loadProductsListServiceConfig } from '@wix/stores/services';
19
+ * import { loadProductsListServiceConfig, parseUrlToSearchOptions, loadCategoriesListServiceConfig } from '@wix/stores/services';
18
20
  * import { ProductList } from '@wix/stores/components';
19
21
  *
20
- * // Define search options
21
- * const searchOptions = {
22
- * cursorPaging: { limit: 12 },
23
- * filter: {},
24
- * sort: [{ fieldName: 'name', order: 'ASC' }]
25
- * };
22
+ * // Option 1: Load from URL (will parse filters, sort, pagination from URL params)
23
+ * const productsConfig = await loadProductsListServiceConfig(Astro.url.href);
26
24
  *
27
- * // Load products data during SSR
28
- * const productsConfig = await loadProductsListServiceConfig(searchOptions);
25
+ * // Option 2: Custom parsing with defaults
26
+ * const categories = await loadCategoriesListServiceConfig();
27
+ * const parsed = await parseUrlToSearchOptions(
28
+ * Astro.url.href,
29
+ * categories.categories,
30
+ * {
31
+ * cursorPaging: { limit: 12 },
32
+ * filter: {},
33
+ * sort: [{ fieldName: 'name' as const, order: 'ASC' as const }]
34
+ * }
35
+ * );
36
+ * const productsConfig = await loadProductsListServiceConfig(parsed);
29
37
  * ---
30
38
  *
31
39
  * <ProductList.Root productsConfig={productsConfig}>
@@ -44,23 +52,31 @@ export const DEFAULT_QUERY_LIMIT = 100;
44
52
  * ```tsx
45
53
  * // Next.js page example - pages/products.tsx
46
54
  * import { GetServerSideProps } from 'next';
47
- * import { loadProductsListServiceConfig } from '@wix/stores/services';
55
+ * import { loadProductsListServiceConfig, parseUrlToSearchOptions, loadCategoriesListServiceConfig } from '@wix/stores/services';
48
56
  * import { ProductsList } from '@wix/stores/components';
49
57
  *
50
58
  * interface ProductsPageProps {
51
59
  * productsConfig: Awaited<ReturnType<typeof loadProductsListServiceConfig>>;
52
60
  * }
53
61
  *
54
- * export const getServerSideProps: GetServerSideProps<ProductsPageProps> = async () => {
55
- * const searchOptions = {
56
- * cursorPaging: { limit: 12 },
57
- * filter: {
58
- * 'allCategoriesInfo.categories': { $matchItems: [{ _id: { $in: [category._id] } }] }
59
- * },
60
- * sort: [{ fieldName: 'name' as const, order: 'ASC' as const }]
61
- * };
62
+ * export const getServerSideProps: GetServerSideProps<ProductsPageProps> = async ({ req }) => {
63
+ * // Option 1: Parse from URL
64
+ * const productsConfig = await loadProductsListServiceConfig(`${req.url}`);
62
65
  *
63
- * const productsConfig = await loadProductsListServiceConfig(searchOptions);
66
+ * // Option 2: Custom parsing with filters
67
+ * const categories = await loadCategoriesListServiceConfig();
68
+ * const parsed = await parseUrlToSearchOptions(
69
+ * `${req.url}`,
70
+ * categories.categories,
71
+ * {
72
+ * cursorPaging: { limit: 12 },
73
+ * filter: {
74
+ * 'allCategoriesInfo.categories': { $matchItems: [{ _id: { $in: [category._id] } }] }
75
+ * },
76
+ * sort: [{ fieldName: 'name' as const, order: 'ASC' as const }]
77
+ * }
78
+ * );
79
+ * const productsConfig = await loadProductsListServiceConfig(parsed);
64
80
  *
65
81
  * return {
66
82
  * props: {
@@ -84,8 +100,34 @@ export const DEFAULT_QUERY_LIMIT = 100;
84
100
  * );
85
101
  * }
86
102
  * ```
103
+ *
104
+ * @example
105
+ * ```tsx
106
+ * // Advanced: Performance optimization when using both services
107
+ * import { parseUrlToSearchOptions, loadProductsListServiceConfig, loadProductsListSearchServiceConfig, loadCategoriesListServiceConfig } from '@wix/stores/services';
108
+ *
109
+ * const categories = await loadCategoriesListServiceConfig();
110
+ * const parsed = await parseUrlToSearchOptions(url, categories.categories);
111
+ *
112
+ * // Both services use the same parsed result (no duplicate URL parsing)
113
+ * const [productsConfig, searchConfig] = await Promise.all([
114
+ * loadProductsListServiceConfig(parsed),
115
+ * loadProductsListSearchServiceConfig(parsed)
116
+ * ]);
117
+ * ```
87
118
  */
88
- export async function loadProductsListServiceConfig(searchOptions) {
119
+ export async function loadProductsListServiceConfig(input) {
120
+ let searchOptions;
121
+ if (typeof input === 'string') {
122
+ // URL input - parse it
123
+ const categoriesListConfig = await loadCategoriesListServiceConfig();
124
+ const { searchOptions: parsedOptions } = await parseUrlToSearchOptions(input, categoriesListConfig.categories);
125
+ searchOptions = parsedOptions;
126
+ }
127
+ else {
128
+ // Parsed URL result - use searchOptions directly
129
+ searchOptions = input.searchOptions;
130
+ }
89
131
  const searchWithoutFilter = { ...searchOptions, filter: {} };
90
132
  const [resultWithoutFilter, resultWithFilter] = await Promise.all([
91
133
  fetchProducts(searchWithoutFilter),
@@ -4,4 +4,4 @@ export { ProductModifiersService, ProductModifiersServiceDefinition, } from "./p
4
4
  export { ProductService, ProductServiceDefinition, loadProductServiceConfig, } from "./product-service.js";
5
5
  export { SelectedVariantService, SelectedVariantServiceDefinition, } from "./selected-variant-service.js";
6
6
  export { ProductListService, ProductsListServiceDefinition, loadProductsListServiceConfig, ProductsListServiceConfig, } from "./products-list-service.js";
7
- export { ProductOption, InventoryStatusType, SortType, ProductChoice, ProductsListSearchService, ProductsListSearchServiceDefinition, ProductsListSearchServiceConfig, loadProductsListSearchServiceConfig, parseUrlForProductsListSearch, convertUrlSortToSortType, } from "./products-list-search-service.js";
7
+ export { ProductOption, InventoryStatusType, SortType, ProductChoice, ProductsListSearchService, ProductsListSearchServiceDefinition, ProductsListSearchServiceConfig, loadProductsListSearchServiceConfig, parseUrlToSearchOptions, convertUrlSortToSortType, } from "./products-list-search-service.js";
@@ -4,4 +4,4 @@ export { ProductModifiersService, ProductModifiersServiceDefinition, } from "./p
4
4
  export { ProductService, ProductServiceDefinition, loadProductServiceConfig, } from "./product-service.js";
5
5
  export { SelectedVariantService, SelectedVariantServiceDefinition, } from "./selected-variant-service.js";
6
6
  export { ProductListService, ProductsListServiceDefinition, loadProductsListServiceConfig, } from "./products-list-service.js";
7
- export { InventoryStatusType, SortType, ProductsListSearchService, ProductsListSearchServiceDefinition, loadProductsListSearchServiceConfig, parseUrlForProductsListSearch, convertUrlSortToSortType, } from "./products-list-search-service.js";
7
+ export { InventoryStatusType, SortType, ProductsListSearchService, ProductsListSearchServiceDefinition, loadProductsListSearchServiceConfig, parseUrlToSearchOptions, convertUrlSortToSortType, } from "./products-list-search-service.js";
@@ -33,7 +33,7 @@ export interface ProductChoice {
33
33
  /**
34
34
  * Initial search state that can be loaded from URL parameters.
35
35
  */
36
- type InitialSearchState = {
36
+ export type InitialSearchState = {
37
37
  sort?: SortType;
38
38
  limit?: number;
39
39
  cursor?: string | null;
@@ -138,16 +138,75 @@ export declare const ProductsListSearchServiceDefinition: string & {
138
138
  */
139
139
  export declare function convertUrlSortToSortType(urlSort: string): SortType | null;
140
140
  /**
141
- * Parse URL and build complete search options with all filters, sort, and pagination
141
+ * Parse URL and build complete search options with all filters, sort, and pagination.
142
+ * This function extracts search parameters, filters, sorting, and pagination from a URL
143
+ * and converts them into the format expected by the Wix Stores API.
144
+ *
145
+ * @param {string} url - The URL to parse search parameters from
146
+ * @param {Category[]} categoriesList - List of available categories for category slug resolution
147
+ * @param {productsV3.V3ProductSearch} [defaultSearchOptions] - Default search options to merge with parsed URL parameters
148
+ * @returns {Promise<{searchOptions: productsV3.V3ProductSearch, initialSearchState: InitialSearchState}>}
149
+ * Object containing both API-ready search options and UI-ready initial state
150
+ *
151
+ * @example
152
+ * ```tsx
153
+ * // Parse URL with filters, sort, and pagination
154
+ * const categories = await loadCategoriesListServiceConfig();
155
+ * const { searchOptions, initialSearchState } = await parseUrlToSearchOptions(
156
+ * 'https://example.com/products?sort=price:desc&Color=red,blue&minPrice=50',
157
+ * categories.categories
158
+ * );
159
+ *
160
+ * // Use searchOptions for API calls
161
+ * const products = await productsV3.searchProducts(searchOptions);
162
+ *
163
+ * // Use initialSearchState for UI initialization
164
+ * const filterState = initialSearchState.productOptions; // { colorId: ['red-id', 'blue-id'] }
165
+ * ```
142
166
  */
143
- export declare function parseUrlForProductsListSearch(url: string, categoriesList: Category[], defaultSearchOptions?: productsV3.V3ProductSearch): Promise<{
167
+ export declare function parseUrlToSearchOptions(url: string, categoriesList: Category[], defaultSearchOptions?: productsV3.V3ProductSearch): Promise<{
144
168
  searchOptions: productsV3.V3ProductSearch;
145
169
  initialSearchState: InitialSearchState;
146
170
  }>;
147
171
  /**
148
- * Load search service configuration from URL
172
+ * Load search service configuration from URL or parsed URL result.
173
+ * This function provides the configuration for the Products List Search service,
174
+ * including customizations and initial search state.
175
+ *
176
+ * @param {string | { searchOptions: productsV3.V3ProductSearch; initialSearchState: InitialSearchState }} input - Either a URL to parse or parsed URL result from parseUrlToSearchOptions
177
+ * @returns {Promise<ProductsListSearchServiceConfig>} Promise that resolves to the search service configuration
178
+ *
179
+ * @example
180
+ * ```tsx
181
+ * // Option 1: Load from URL (will parse filters, sort, pagination from URL params)
182
+ * const searchConfig = await loadProductsListSearchServiceConfig(window.location.href);
183
+ *
184
+ * // Option 2: Custom parsing with defaults
185
+ * const categories = await loadCategoriesListServiceConfig();
186
+ * const parsed = await parseUrlToSearchOptions(
187
+ * window.location.href,
188
+ * categories.categories,
189
+ * {
190
+ * cursorPaging: { limit: 12 },
191
+ * filter: { 'categoryIds': ['123'] },
192
+ * sort: [{ fieldName: 'name' as const, order: 'ASC' as const }]
193
+ * }
194
+ * );
195
+ * const searchConfig = await loadProductsListSearchServiceConfig(parsed);
196
+ *
197
+ * // Option 3: Performance optimization - use parsed result for both services (no duplicate parsing)
198
+ * const categories = await loadCategoriesListServiceConfig();
199
+ * const parsed = await parseUrlToSearchOptions(url, categories.categories);
200
+ * const [productsConfig, searchConfig] = await Promise.all([
201
+ * loadProductsListServiceConfig(parsed),
202
+ * loadProductsListSearchServiceConfig(parsed),
203
+ * ]);
204
+ * ```
149
205
  */
150
- export declare function loadProductsListSearchServiceConfig(url: string): Promise<ProductsListSearchServiceConfig>;
206
+ export declare function loadProductsListSearchServiceConfig(input: string | {
207
+ searchOptions: productsV3.V3ProductSearch;
208
+ initialSearchState: InitialSearchState;
209
+ }): Promise<ProductsListSearchServiceConfig>;
151
210
  /**
152
211
  * Implementation of the Products List Search service
153
212
  */
@@ -164,9 +164,33 @@ function updateUrlWithSearchState(searchState) {
164
164
  }
165
165
  }
166
166
  /**
167
- * Parse URL and build complete search options with all filters, sort, and pagination
167
+ * Parse URL and build complete search options with all filters, sort, and pagination.
168
+ * This function extracts search parameters, filters, sorting, and pagination from a URL
169
+ * and converts them into the format expected by the Wix Stores API.
170
+ *
171
+ * @param {string} url - The URL to parse search parameters from
172
+ * @param {Category[]} categoriesList - List of available categories for category slug resolution
173
+ * @param {productsV3.V3ProductSearch} [defaultSearchOptions] - Default search options to merge with parsed URL parameters
174
+ * @returns {Promise<{searchOptions: productsV3.V3ProductSearch, initialSearchState: InitialSearchState}>}
175
+ * Object containing both API-ready search options and UI-ready initial state
176
+ *
177
+ * @example
178
+ * ```tsx
179
+ * // Parse URL with filters, sort, and pagination
180
+ * const categories = await loadCategoriesListServiceConfig();
181
+ * const { searchOptions, initialSearchState } = await parseUrlToSearchOptions(
182
+ * 'https://example.com/products?sort=price:desc&Color=red,blue&minPrice=50',
183
+ * categories.categories
184
+ * );
185
+ *
186
+ * // Use searchOptions for API calls
187
+ * const products = await productsV3.searchProducts(searchOptions);
188
+ *
189
+ * // Use initialSearchState for UI initialization
190
+ * const filterState = initialSearchState.productOptions; // { colorId: ['red-id', 'blue-id'] }
191
+ * ```
168
192
  */
169
- export async function parseUrlForProductsListSearch(url, categoriesList, defaultSearchOptions) {
193
+ export async function parseUrlToSearchOptions(url, categoriesList, defaultSearchOptions) {
170
194
  const urlObj = new URL(url);
171
195
  const searchParams = urlObj.searchParams;
172
196
  // Get customizations for product option parsing
@@ -182,19 +206,16 @@ export async function parseUrlForProductsListSearch(url, categoriesList, default
182
206
  };
183
207
  // Initialize search state for service
184
208
  const initialSearchState = {};
185
- // Extract category slug from URL path (e.g., /category/category-slug)
186
- const pathSegments = urlObj.pathname.split("/");
187
- const categoryIndex = pathSegments.findIndex((segment) => segment === "category");
188
- let categorySlug = null;
209
+ // Extract category slug from URL path
210
+ // The category slug is always the last segment of the path
211
+ const pathSegments = urlObj.pathname.split("/").filter(Boolean);
189
212
  let category = undefined;
190
- if (categoryIndex !== -1 && categoryIndex + 1 < pathSegments.length) {
191
- categorySlug = pathSegments[categoryIndex + 1] || null;
192
- // Find the category by slug from the provided categories list
193
- if (categorySlug) {
194
- category = categoriesList.find((cat) => cat.slug === categorySlug);
195
- if (category) {
196
- initialSearchState.category = category;
197
- }
213
+ if (pathSegments.length > 0) {
214
+ const lastSegment = pathSegments[pathSegments.length - 1];
215
+ // Check if the last segment matches any category in the categories list
216
+ category = categoriesList.find((cat) => cat.slug === lastSegment);
217
+ if (category) {
218
+ initialSearchState.category = category;
198
219
  }
199
220
  }
200
221
  // Handle text search (q parameter)
@@ -399,12 +420,52 @@ export async function parseUrlForProductsListSearch(url, categoriesList, default
399
420
  return { searchOptions, initialSearchState };
400
421
  }
401
422
  /**
402
- * Load search service configuration from URL
423
+ * Load search service configuration from URL or parsed URL result.
424
+ * This function provides the configuration for the Products List Search service,
425
+ * including customizations and initial search state.
426
+ *
427
+ * @param {string | { searchOptions: productsV3.V3ProductSearch; initialSearchState: InitialSearchState }} input - Either a URL to parse or parsed URL result from parseUrlToSearchOptions
428
+ * @returns {Promise<ProductsListSearchServiceConfig>} Promise that resolves to the search service configuration
429
+ *
430
+ * @example
431
+ * ```tsx
432
+ * // Option 1: Load from URL (will parse filters, sort, pagination from URL params)
433
+ * const searchConfig = await loadProductsListSearchServiceConfig(window.location.href);
434
+ *
435
+ * // Option 2: Custom parsing with defaults
436
+ * const categories = await loadCategoriesListServiceConfig();
437
+ * const parsed = await parseUrlToSearchOptions(
438
+ * window.location.href,
439
+ * categories.categories,
440
+ * {
441
+ * cursorPaging: { limit: 12 },
442
+ * filter: { 'categoryIds': ['123'] },
443
+ * sort: [{ fieldName: 'name' as const, order: 'ASC' as const }]
444
+ * }
445
+ * );
446
+ * const searchConfig = await loadProductsListSearchServiceConfig(parsed);
447
+ *
448
+ * // Option 3: Performance optimization - use parsed result for both services (no duplicate parsing)
449
+ * const categories = await loadCategoriesListServiceConfig();
450
+ * const parsed = await parseUrlToSearchOptions(url, categories.categories);
451
+ * const [productsConfig, searchConfig] = await Promise.all([
452
+ * loadProductsListServiceConfig(parsed),
453
+ * loadProductsListSearchServiceConfig(parsed),
454
+ * ]);
455
+ * ```
403
456
  */
404
- export async function loadProductsListSearchServiceConfig(url) {
405
- // Load categories using the categories service
406
- const categoriesListConfig = await loadCategoriesListServiceConfig();
407
- const { initialSearchState } = await parseUrlForProductsListSearch(url, categoriesListConfig.categories);
457
+ export async function loadProductsListSearchServiceConfig(input) {
458
+ let initialSearchState;
459
+ if (typeof input === "string") {
460
+ // URL input - parse it
461
+ const categoriesListConfig = await loadCategoriesListServiceConfig();
462
+ const { initialSearchState: parsedState } = await parseUrlToSearchOptions(input, categoriesListConfig.categories);
463
+ initialSearchState = parsedState;
464
+ }
465
+ else {
466
+ // Parsed URL result - use initialSearchState directly (no duplicate work)
467
+ initialSearchState = input.initialSearchState;
468
+ }
408
469
  const { items: customizations = [] } = await customizationsV3
409
470
  .queryCustomizations()
410
471
  .find();
@@ -1,5 +1,6 @@
1
1
  import { type Signal } from "@wix/services-definitions/core-services/signals";
2
2
  import { productsV3 } from "@wix/stores";
3
+ import { type InitialSearchState } from "./products-list-search-service.js";
3
4
  export declare const DEFAULT_QUERY_LIMIT = 100;
4
5
  /**
5
6
  * Configuration interface for the Products List service.
@@ -20,27 +21,33 @@ export type ProductsListServiceConfig = {
20
21
  /**
21
22
  * Loads products list service configuration from the Wix Stores API for SSR initialization.
22
23
  * This function is designed to be used during Server-Side Rendering (SSR) to preload
23
- * a list of products based on search criteria.
24
+ * a list of products based on search criteria or URL parameters.
24
25
  *
25
- * @param {productsV3.V3ProductSearch} searchOptions - The search options for querying products
26
+ * @param {string | { searchOptions: productsV3.V3ProductSearch; initialSearchState: InitialSearchState }} input - Either a URL to parse or parsed URL result from parseUrlToSearchOptions
26
27
  * @returns {Promise<ProductsListServiceConfig>} Promise that resolves to the products list configuration
27
28
  *
28
29
  * @example
29
30
  * ```astro
30
31
  * ---
31
32
  * // Astro page example - pages/products.astro
32
- * import { loadProductsListServiceConfig } from '@wix/stores/services';
33
+ * import { loadProductsListServiceConfig, parseUrlToSearchOptions, loadCategoriesListServiceConfig } from '@wix/stores/services';
33
34
  * import { ProductList } from '@wix/stores/components';
34
35
  *
35
- * // Define search options
36
- * const searchOptions = {
37
- * cursorPaging: { limit: 12 },
38
- * filter: {},
39
- * sort: [{ fieldName: 'name', order: 'ASC' }]
40
- * };
36
+ * // Option 1: Load from URL (will parse filters, sort, pagination from URL params)
37
+ * const productsConfig = await loadProductsListServiceConfig(Astro.url.href);
41
38
  *
42
- * // Load products data during SSR
43
- * const productsConfig = await loadProductsListServiceConfig(searchOptions);
39
+ * // Option 2: Custom parsing with defaults
40
+ * const categories = await loadCategoriesListServiceConfig();
41
+ * const parsed = await parseUrlToSearchOptions(
42
+ * Astro.url.href,
43
+ * categories.categories,
44
+ * {
45
+ * cursorPaging: { limit: 12 },
46
+ * filter: {},
47
+ * sort: [{ fieldName: 'name' as const, order: 'ASC' as const }]
48
+ * }
49
+ * );
50
+ * const productsConfig = await loadProductsListServiceConfig(parsed);
44
51
  * ---
45
52
  *
46
53
  * <ProductList.Root productsConfig={productsConfig}>
@@ -59,23 +66,31 @@ export type ProductsListServiceConfig = {
59
66
  * ```tsx
60
67
  * // Next.js page example - pages/products.tsx
61
68
  * import { GetServerSideProps } from 'next';
62
- * import { loadProductsListServiceConfig } from '@wix/stores/services';
69
+ * import { loadProductsListServiceConfig, parseUrlToSearchOptions, loadCategoriesListServiceConfig } from '@wix/stores/services';
63
70
  * import { ProductsList } from '@wix/stores/components';
64
71
  *
65
72
  * interface ProductsPageProps {
66
73
  * productsConfig: Awaited<ReturnType<typeof loadProductsListServiceConfig>>;
67
74
  * }
68
75
  *
69
- * export const getServerSideProps: GetServerSideProps<ProductsPageProps> = async () => {
70
- * const searchOptions = {
71
- * cursorPaging: { limit: 12 },
72
- * filter: {
73
- * 'allCategoriesInfo.categories': { $matchItems: [{ _id: { $in: [category._id] } }] }
74
- * },
75
- * sort: [{ fieldName: 'name' as const, order: 'ASC' as const }]
76
- * };
76
+ * export const getServerSideProps: GetServerSideProps<ProductsPageProps> = async ({ req }) => {
77
+ * // Option 1: Parse from URL
78
+ * const productsConfig = await loadProductsListServiceConfig(`${req.url}`);
77
79
  *
78
- * const productsConfig = await loadProductsListServiceConfig(searchOptions);
80
+ * // Option 2: Custom parsing with filters
81
+ * const categories = await loadCategoriesListServiceConfig();
82
+ * const parsed = await parseUrlToSearchOptions(
83
+ * `${req.url}`,
84
+ * categories.categories,
85
+ * {
86
+ * cursorPaging: { limit: 12 },
87
+ * filter: {
88
+ * 'allCategoriesInfo.categories': { $matchItems: [{ _id: { $in: [category._id] } }] }
89
+ * },
90
+ * sort: [{ fieldName: 'name' as const, order: 'ASC' as const }]
91
+ * }
92
+ * );
93
+ * const productsConfig = await loadProductsListServiceConfig(parsed);
79
94
  *
80
95
  * return {
81
96
  * props: {
@@ -99,8 +114,26 @@ export type ProductsListServiceConfig = {
99
114
  * );
100
115
  * }
101
116
  * ```
117
+ *
118
+ * @example
119
+ * ```tsx
120
+ * // Advanced: Performance optimization when using both services
121
+ * import { parseUrlToSearchOptions, loadProductsListServiceConfig, loadProductsListSearchServiceConfig, loadCategoriesListServiceConfig } from '@wix/stores/services';
122
+ *
123
+ * const categories = await loadCategoriesListServiceConfig();
124
+ * const parsed = await parseUrlToSearchOptions(url, categories.categories);
125
+ *
126
+ * // Both services use the same parsed result (no duplicate URL parsing)
127
+ * const [productsConfig, searchConfig] = await Promise.all([
128
+ * loadProductsListServiceConfig(parsed),
129
+ * loadProductsListSearchServiceConfig(parsed)
130
+ * ]);
131
+ * ```
102
132
  */
103
- export declare function loadProductsListServiceConfig(searchOptions: productsV3.V3ProductSearch): Promise<ProductsListServiceConfig>;
133
+ export declare function loadProductsListServiceConfig(input: string | {
134
+ searchOptions: productsV3.V3ProductSearch;
135
+ initialSearchState: InitialSearchState;
136
+ }): Promise<ProductsListServiceConfig>;
104
137
  /**
105
138
  * Service definition for the Products List service.
106
139
  * This defines the reactive API contract for managing a list of products with search, pagination, and filtering capabilities.
@@ -1,31 +1,39 @@
1
1
  import { defineService, implementService } from "@wix/services-definitions";
2
2
  import { SignalsServiceDefinition, } from "@wix/services-definitions/core-services/signals";
3
3
  import { productsV3, readOnlyVariantsV3 } from "@wix/stores";
4
+ import { loadCategoriesListServiceConfig } from "./categories-list-service.js";
5
+ import { parseUrlToSearchOptions } from "./products-list-search-service.js";
4
6
  export const DEFAULT_QUERY_LIMIT = 100;
5
7
  /**
6
8
  * Loads products list service configuration from the Wix Stores API for SSR initialization.
7
9
  * This function is designed to be used during Server-Side Rendering (SSR) to preload
8
- * a list of products based on search criteria.
10
+ * a list of products based on search criteria or URL parameters.
9
11
  *
10
- * @param {productsV3.V3ProductSearch} searchOptions - The search options for querying products
12
+ * @param {string | { searchOptions: productsV3.V3ProductSearch; initialSearchState: InitialSearchState }} input - Either a URL to parse or parsed URL result from parseUrlToSearchOptions
11
13
  * @returns {Promise<ProductsListServiceConfig>} Promise that resolves to the products list configuration
12
14
  *
13
15
  * @example
14
16
  * ```astro
15
17
  * ---
16
18
  * // Astro page example - pages/products.astro
17
- * import { loadProductsListServiceConfig } from '@wix/stores/services';
19
+ * import { loadProductsListServiceConfig, parseUrlToSearchOptions, loadCategoriesListServiceConfig } from '@wix/stores/services';
18
20
  * import { ProductList } from '@wix/stores/components';
19
21
  *
20
- * // Define search options
21
- * const searchOptions = {
22
- * cursorPaging: { limit: 12 },
23
- * filter: {},
24
- * sort: [{ fieldName: 'name', order: 'ASC' }]
25
- * };
22
+ * // Option 1: Load from URL (will parse filters, sort, pagination from URL params)
23
+ * const productsConfig = await loadProductsListServiceConfig(Astro.url.href);
26
24
  *
27
- * // Load products data during SSR
28
- * const productsConfig = await loadProductsListServiceConfig(searchOptions);
25
+ * // Option 2: Custom parsing with defaults
26
+ * const categories = await loadCategoriesListServiceConfig();
27
+ * const parsed = await parseUrlToSearchOptions(
28
+ * Astro.url.href,
29
+ * categories.categories,
30
+ * {
31
+ * cursorPaging: { limit: 12 },
32
+ * filter: {},
33
+ * sort: [{ fieldName: 'name' as const, order: 'ASC' as const }]
34
+ * }
35
+ * );
36
+ * const productsConfig = await loadProductsListServiceConfig(parsed);
29
37
  * ---
30
38
  *
31
39
  * <ProductList.Root productsConfig={productsConfig}>
@@ -44,23 +52,31 @@ export const DEFAULT_QUERY_LIMIT = 100;
44
52
  * ```tsx
45
53
  * // Next.js page example - pages/products.tsx
46
54
  * import { GetServerSideProps } from 'next';
47
- * import { loadProductsListServiceConfig } from '@wix/stores/services';
55
+ * import { loadProductsListServiceConfig, parseUrlToSearchOptions, loadCategoriesListServiceConfig } from '@wix/stores/services';
48
56
  * import { ProductsList } from '@wix/stores/components';
49
57
  *
50
58
  * interface ProductsPageProps {
51
59
  * productsConfig: Awaited<ReturnType<typeof loadProductsListServiceConfig>>;
52
60
  * }
53
61
  *
54
- * export const getServerSideProps: GetServerSideProps<ProductsPageProps> = async () => {
55
- * const searchOptions = {
56
- * cursorPaging: { limit: 12 },
57
- * filter: {
58
- * 'allCategoriesInfo.categories': { $matchItems: [{ _id: { $in: [category._id] } }] }
59
- * },
60
- * sort: [{ fieldName: 'name' as const, order: 'ASC' as const }]
61
- * };
62
+ * export const getServerSideProps: GetServerSideProps<ProductsPageProps> = async ({ req }) => {
63
+ * // Option 1: Parse from URL
64
+ * const productsConfig = await loadProductsListServiceConfig(`${req.url}`);
62
65
  *
63
- * const productsConfig = await loadProductsListServiceConfig(searchOptions);
66
+ * // Option 2: Custom parsing with filters
67
+ * const categories = await loadCategoriesListServiceConfig();
68
+ * const parsed = await parseUrlToSearchOptions(
69
+ * `${req.url}`,
70
+ * categories.categories,
71
+ * {
72
+ * cursorPaging: { limit: 12 },
73
+ * filter: {
74
+ * 'allCategoriesInfo.categories': { $matchItems: [{ _id: { $in: [category._id] } }] }
75
+ * },
76
+ * sort: [{ fieldName: 'name' as const, order: 'ASC' as const }]
77
+ * }
78
+ * );
79
+ * const productsConfig = await loadProductsListServiceConfig(parsed);
64
80
  *
65
81
  * return {
66
82
  * props: {
@@ -84,8 +100,34 @@ export const DEFAULT_QUERY_LIMIT = 100;
84
100
  * );
85
101
  * }
86
102
  * ```
103
+ *
104
+ * @example
105
+ * ```tsx
106
+ * // Advanced: Performance optimization when using both services
107
+ * import { parseUrlToSearchOptions, loadProductsListServiceConfig, loadProductsListSearchServiceConfig, loadCategoriesListServiceConfig } from '@wix/stores/services';
108
+ *
109
+ * const categories = await loadCategoriesListServiceConfig();
110
+ * const parsed = await parseUrlToSearchOptions(url, categories.categories);
111
+ *
112
+ * // Both services use the same parsed result (no duplicate URL parsing)
113
+ * const [productsConfig, searchConfig] = await Promise.all([
114
+ * loadProductsListServiceConfig(parsed),
115
+ * loadProductsListSearchServiceConfig(parsed)
116
+ * ]);
117
+ * ```
87
118
  */
88
- export async function loadProductsListServiceConfig(searchOptions) {
119
+ export async function loadProductsListServiceConfig(input) {
120
+ let searchOptions;
121
+ if (typeof input === 'string') {
122
+ // URL input - parse it
123
+ const categoriesListConfig = await loadCategoriesListServiceConfig();
124
+ const { searchOptions: parsedOptions } = await parseUrlToSearchOptions(input, categoriesListConfig.categories);
125
+ searchOptions = parsedOptions;
126
+ }
127
+ else {
128
+ // Parsed URL result - use searchOptions directly
129
+ searchOptions = input.searchOptions;
130
+ }
89
131
  const searchWithoutFilter = { ...searchOptions, filter: {} };
90
132
  const [resultWithoutFilter, resultWithFilter] = await Promise.all([
91
133
  fetchProducts(searchWithoutFilter),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/headless-stores",
3
- "version": "0.0.48",
3
+ "version": "0.0.50",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "prebuild": "cd ../media && yarn build && cd ../ecom && yarn build",