@wix/headless-stores 0.0.0

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 (150) hide show
  1. package/astro/actions/package.json +4 -0
  2. package/cjs/dist/astro/actions/custom-checkout.d.ts +50 -0
  3. package/cjs/dist/astro/actions/custom-checkout.js +53 -0
  4. package/cjs/dist/astro/actions/index.d.ts +1 -0
  5. package/cjs/dist/astro/actions/index.js +1 -0
  6. package/cjs/dist/data-component-tags.d.ts +8 -0
  7. package/cjs/dist/data-component-tags.js +9 -0
  8. package/cjs/dist/enums/index.d.ts +2 -0
  9. package/cjs/dist/enums/index.js +2 -0
  10. package/cjs/dist/enums/social-platform-enums.d.ts +25 -0
  11. package/cjs/dist/enums/social-platform-enums.js +27 -0
  12. package/cjs/dist/enums/sort-enums.d.ts +17 -0
  13. package/cjs/dist/enums/sort-enums.js +18 -0
  14. package/cjs/dist/react/Category.d.ts +242 -0
  15. package/cjs/dist/react/Category.js +235 -0
  16. package/cjs/dist/react/CategoryList.d.ts +107 -0
  17. package/cjs/dist/react/CategoryList.js +91 -0
  18. package/cjs/dist/react/Choice.d.ts +211 -0
  19. package/cjs/dist/react/Choice.js +213 -0
  20. package/cjs/dist/react/Option.d.ts +242 -0
  21. package/cjs/dist/react/Option.js +346 -0
  22. package/cjs/dist/react/Product.d.ts +1065 -0
  23. package/cjs/dist/react/Product.js +1157 -0
  24. package/cjs/dist/react/ProductList.d.ts +400 -0
  25. package/cjs/dist/react/ProductList.js +368 -0
  26. package/cjs/dist/react/core/CategoryList.d.ts +194 -0
  27. package/cjs/dist/react/core/CategoryList.js +180 -0
  28. package/cjs/dist/react/core/Product.d.ts +225 -0
  29. package/cjs/dist/react/core/Product.js +190 -0
  30. package/cjs/dist/react/core/ProductList.d.ts +235 -0
  31. package/cjs/dist/react/core/ProductList.js +217 -0
  32. package/cjs/dist/react/core/ProductListFilters.d.ts +138 -0
  33. package/cjs/dist/react/core/ProductListFilters.js +242 -0
  34. package/cjs/dist/react/core/ProductListPagination.d.ts +49 -0
  35. package/cjs/dist/react/core/ProductListPagination.js +41 -0
  36. package/cjs/dist/react/core/ProductListSort.d.ts +19 -0
  37. package/cjs/dist/react/core/ProductListSort.js +52 -0
  38. package/cjs/dist/react/core/ProductModifiers.d.ts +416 -0
  39. package/cjs/dist/react/core/ProductModifiers.js +413 -0
  40. package/cjs/dist/react/core/ProductVariantSelector.d.ts +313 -0
  41. package/cjs/dist/react/core/ProductVariantSelector.js +291 -0
  42. package/cjs/dist/react/core/SelectedVariant.d.ts +230 -0
  43. package/cjs/dist/react/core/SelectedVariant.js +269 -0
  44. package/cjs/dist/react/index.d.ts +6 -0
  45. package/cjs/dist/react/index.js +6 -0
  46. package/cjs/dist/react/types.d.ts +8 -0
  47. package/cjs/dist/react/types.js +9 -0
  48. package/cjs/dist/server-actions/custom-checkout-action.d.ts +49 -0
  49. package/cjs/dist/server-actions/custom-checkout-action.js +64 -0
  50. package/cjs/dist/server-actions/index.d.ts +1 -0
  51. package/cjs/dist/server-actions/index.js +1 -0
  52. package/cjs/dist/services/buy-now-service.d.ts +346 -0
  53. package/cjs/dist/services/buy-now-service.js +197 -0
  54. package/cjs/dist/services/categories-list-service.d.ts +164 -0
  55. package/cjs/dist/services/categories-list-service.js +148 -0
  56. package/cjs/dist/services/index.d.ts +5 -0
  57. package/cjs/dist/services/index.js +5 -0
  58. package/cjs/dist/services/pay-now-service.d.ts +214 -0
  59. package/cjs/dist/services/pay-now-service.js +156 -0
  60. package/cjs/dist/services/product-modifiers-service.d.ts +34 -0
  61. package/cjs/dist/services/product-modifiers-service.js +107 -0
  62. package/cjs/dist/services/product-service.d.ts +177 -0
  63. package/cjs/dist/services/product-service.js +190 -0
  64. package/cjs/dist/services/products-list-search-service.d.ts +1 -0
  65. package/cjs/dist/services/products-list-search-service.js +1 -0
  66. package/cjs/dist/services/products-list-service.d.ts +429 -0
  67. package/cjs/dist/services/products-list-service.js +893 -0
  68. package/cjs/dist/services/selected-variant-service.d.ts +66 -0
  69. package/cjs/dist/services/selected-variant-service.js +527 -0
  70. package/cjs/dist/utils/index.d.ts +1 -0
  71. package/cjs/dist/utils/index.js +30 -0
  72. package/cjs/dist/utils/url-params.d.ts +73 -0
  73. package/cjs/dist/utils/url-params.js +114 -0
  74. package/cjs/package.json +3 -0
  75. package/dist/astro/actions/custom-checkout.d.ts +50 -0
  76. package/dist/astro/actions/custom-checkout.js +53 -0
  77. package/dist/astro/actions/index.d.ts +1 -0
  78. package/dist/astro/actions/index.js +1 -0
  79. package/dist/data-component-tags.d.ts +8 -0
  80. package/dist/data-component-tags.js +9 -0
  81. package/dist/enums/index.d.ts +2 -0
  82. package/dist/enums/index.js +2 -0
  83. package/dist/enums/social-platform-enums.d.ts +25 -0
  84. package/dist/enums/social-platform-enums.js +27 -0
  85. package/dist/enums/sort-enums.d.ts +17 -0
  86. package/dist/enums/sort-enums.js +18 -0
  87. package/dist/react/Category.d.ts +242 -0
  88. package/dist/react/Category.js +235 -0
  89. package/dist/react/CategoryList.d.ts +107 -0
  90. package/dist/react/CategoryList.js +91 -0
  91. package/dist/react/Choice.d.ts +211 -0
  92. package/dist/react/Choice.js +213 -0
  93. package/dist/react/Option.d.ts +242 -0
  94. package/dist/react/Option.js +346 -0
  95. package/dist/react/Product.d.ts +1065 -0
  96. package/dist/react/Product.js +1157 -0
  97. package/dist/react/ProductList.d.ts +400 -0
  98. package/dist/react/ProductList.js +368 -0
  99. package/dist/react/core/CategoryList.d.ts +194 -0
  100. package/dist/react/core/CategoryList.js +180 -0
  101. package/dist/react/core/Product.d.ts +225 -0
  102. package/dist/react/core/Product.js +190 -0
  103. package/dist/react/core/ProductList.d.ts +235 -0
  104. package/dist/react/core/ProductList.js +217 -0
  105. package/dist/react/core/ProductListFilters.d.ts +138 -0
  106. package/dist/react/core/ProductListFilters.js +242 -0
  107. package/dist/react/core/ProductListPagination.d.ts +49 -0
  108. package/dist/react/core/ProductListPagination.js +41 -0
  109. package/dist/react/core/ProductListSort.d.ts +19 -0
  110. package/dist/react/core/ProductListSort.js +52 -0
  111. package/dist/react/core/ProductModifiers.d.ts +416 -0
  112. package/dist/react/core/ProductModifiers.js +413 -0
  113. package/dist/react/core/ProductVariantSelector.d.ts +313 -0
  114. package/dist/react/core/ProductVariantSelector.js +291 -0
  115. package/dist/react/core/SelectedVariant.d.ts +230 -0
  116. package/dist/react/core/SelectedVariant.js +269 -0
  117. package/dist/react/index.d.ts +6 -0
  118. package/dist/react/index.js +6 -0
  119. package/dist/react/types.d.ts +8 -0
  120. package/dist/react/types.js +9 -0
  121. package/dist/server-actions/custom-checkout-action.d.ts +49 -0
  122. package/dist/server-actions/custom-checkout-action.js +64 -0
  123. package/dist/server-actions/index.d.ts +1 -0
  124. package/dist/server-actions/index.js +1 -0
  125. package/dist/services/buy-now-service.d.ts +346 -0
  126. package/dist/services/buy-now-service.js +197 -0
  127. package/dist/services/categories-list-service.d.ts +164 -0
  128. package/dist/services/categories-list-service.js +148 -0
  129. package/dist/services/index.d.ts +5 -0
  130. package/dist/services/index.js +5 -0
  131. package/dist/services/pay-now-service.d.ts +214 -0
  132. package/dist/services/pay-now-service.js +156 -0
  133. package/dist/services/product-modifiers-service.d.ts +34 -0
  134. package/dist/services/product-modifiers-service.js +107 -0
  135. package/dist/services/product-service.d.ts +177 -0
  136. package/dist/services/product-service.js +190 -0
  137. package/dist/services/products-list-search-service.d.ts +0 -0
  138. package/dist/services/products-list-search-service.js +1 -0
  139. package/dist/services/products-list-service.d.ts +429 -0
  140. package/dist/services/products-list-service.js +893 -0
  141. package/dist/services/selected-variant-service.d.ts +66 -0
  142. package/dist/services/selected-variant-service.js +527 -0
  143. package/dist/utils/index.d.ts +1 -0
  144. package/dist/utils/index.js +30 -0
  145. package/dist/utils/url-params.d.ts +73 -0
  146. package/dist/utils/url-params.js +114 -0
  147. package/package.json +89 -0
  148. package/react/package.json +4 -0
  149. package/server-actions/package.json +4 -0
  150. package/services/package.json +4 -0
@@ -0,0 +1,156 @@
1
+ import { defineService, implementService } from '@wix/services-definitions';
2
+ import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
3
+ /**
4
+ * Service definition for the Pay Now service.
5
+ * This defines the reactive API contract for managing custom payment checkout functionality.
6
+ *
7
+ * @constant
8
+ */
9
+ export const PayNowServiceDefinition = defineService('PayNow');
10
+ /**
11
+ * Implementation of the Pay Now service that manages custom payment checkout functionality.
12
+ * This service provides signals for loading state and error handling, along with a method
13
+ * to redirect to checkout using a custom checkout action.
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * import { PayNowServiceImplementation, PayNowServiceDefinition } from '@wix/stores/services';
18
+ * import { useService } from '@wix/services-manager-react';
19
+ *
20
+ * function PayNowComponent({ payNowConfig }) {
21
+ * return (
22
+ * <ServiceProvider services={createServicesMap([
23
+ * [PayNowServiceDefinition, PayNowServiceImplementation.withConfig(payNowConfig)]
24
+ * ])}>
25
+ * <PayNowButton />
26
+ * </ServiceProvider>
27
+ * );
28
+ * }
29
+ *
30
+ * function PayNowButton() {
31
+ * const payNowService = useService(PayNowServiceDefinition);
32
+ * const isLoading = payNowService.loadingSignal.get();
33
+ * const error = payNowService.errorSignal.get();
34
+ *
35
+ * const handlePayNow = async () => {
36
+ * await payNowService.redirectToCheckout();
37
+ * };
38
+ *
39
+ * return (
40
+ * <div>
41
+ * {error && <div className="error">{error}</div>}
42
+ * <button
43
+ * onClick={handlePayNow}
44
+ * disabled={isLoading}
45
+ * className="pay-now-btn"
46
+ * >
47
+ * {isLoading ? 'Processing...' : 'Pay Now'}
48
+ * </button>
49
+ * </div>
50
+ * );
51
+ * }
52
+ * ```
53
+ */
54
+ export const PayNowServiceImplementation = implementService.withConfig()(PayNowServiceDefinition, ({ getService, config }) => {
55
+ const signalsService = getService(SignalsServiceDefinition);
56
+ const loadingSignal = signalsService.signal(false);
57
+ const errorSignal = signalsService.signal(null);
58
+ return {
59
+ redirectToCheckout: async () => {
60
+ loadingSignal.set(true);
61
+ try {
62
+ if (config.customCheckoutAction) {
63
+ const result = await config.customCheckoutAction();
64
+ if (result && result.data) {
65
+ window.location.href = result.data;
66
+ }
67
+ else {
68
+ throw new Error('Failed to create checkout' + result?.error);
69
+ }
70
+ }
71
+ }
72
+ catch (error) {
73
+ errorSignal.set(error.toString());
74
+ loadingSignal.set(false);
75
+ }
76
+ },
77
+ loadingSignal,
78
+ errorSignal,
79
+ };
80
+ });
81
+ /**
82
+ * Loads pay now service initial data for SSR initialization.
83
+ * This function returns an empty configuration as the Pay Now service
84
+ * is typically configured with custom checkout actions at runtime.
85
+ *
86
+ * @returns {Promise} Promise that resolves to an empty pay now service configuration
87
+ *
88
+ * @example
89
+ * ```astro
90
+ * ---
91
+ * // Astro page example
92
+ * import { loadPayNowServiceInitialData } from '@wix/stores/services';
93
+ * import { PayNow } from '@wix/stores/components';
94
+ *
95
+ * // Load initial data (empty for PayNow)
96
+ * const payNowData = await loadPayNowServiceInitialData();
97
+ * ---
98
+ *
99
+ * <PayNow.PayNow payNowConfig={payNowData.PayNow}>
100
+ * {({ redirectToCheckout, isLoading, error }) => (
101
+ * <button onClick={redirectToCheckout} disabled={isLoading}>
102
+ * {isLoading ? 'Processing...' : 'Pay Now'}
103
+ * </button>
104
+ * )}
105
+ * </PayNow.PayNow>
106
+ * ```
107
+ */
108
+ export const loadPayNowServiceInitialData = async () => {
109
+ return {
110
+ [PayNowServiceDefinition]: {},
111
+ };
112
+ };
113
+ /**
114
+ * Helper function to create a pay now service binding with configuration.
115
+ * This function simplifies the process of binding the pay now service with its configuration
116
+ * and allows for additional configuration overrides, particularly for custom checkout actions.
117
+ *
118
+ * @template T - Type of the services configurations object
119
+ * @param {T} servicesConfigs - Object containing service configurations
120
+ * @param {Partial<PayNowServiceConfig>} [additionalConfig={}] - Additional configuration to override defaults
121
+ * @returns Tuple containing service definition, implementation, and merged configuration
122
+ *
123
+ * @example
124
+ * ```tsx
125
+ * import { payNowServiceBinding, loadPayNowServiceInitialData } from '@wix/stores/services';
126
+ * import { actions } from 'astro:actions';
127
+ *
128
+ * // Load initial data
129
+ * const initialData = await loadPayNowServiceInitialData();
130
+ *
131
+ * // Create service binding with custom checkout action
132
+ * const payNowBinding = payNowServiceBinding(initialData, {
133
+ * customCheckoutAction: async () => {
134
+ * try {
135
+ * const result = await actions.customCheckout();
136
+ * return { data: result, error: null };
137
+ * } catch (error) {
138
+ * return { data: undefined, error };
139
+ * }
140
+ * }
141
+ * });
142
+ *
143
+ * // Use in service provider
144
+ * const services = createServicesMap([payNowBinding]);
145
+ * ```
146
+ */
147
+ export const payNowServiceBinding = (servicesConfigs, additionalConfig = {}) => {
148
+ return [
149
+ PayNowServiceDefinition,
150
+ PayNowServiceImplementation,
151
+ {
152
+ ...servicesConfigs[PayNowServiceDefinition],
153
+ ...additionalConfig,
154
+ },
155
+ ];
156
+ };
@@ -0,0 +1,34 @@
1
+ import { type ServiceFactoryConfig } from '@wix/services-definitions';
2
+ import { type Signal, type ReadOnlySignal } from '@wix/services-definitions/core-services/signals';
3
+ import * as productsV3 from '@wix/auto_sdk_stores_products-v-3';
4
+ export interface ModifierValue {
5
+ modifierName: string;
6
+ choiceValue?: string;
7
+ freeTextValue?: string;
8
+ }
9
+ export interface ProductModifiersServiceAPI {
10
+ modifiers: ReadOnlySignal<productsV3.ConnectedModifier[]>;
11
+ selectedModifiers: Signal<Record<string, ModifierValue>>;
12
+ hasModifiers: ReadOnlySignal<boolean>;
13
+ isLoading: Signal<boolean>;
14
+ error: Signal<string | null>;
15
+ setModifierChoice: (modifierName: string, choiceValue: string) => void;
16
+ setModifierFreeText: (modifierName: string, freeTextValue: string) => void;
17
+ clearModifier: (modifierName: string) => void;
18
+ clearAllModifiers: () => void;
19
+ getModifierValue: (modifierName: string) => ModifierValue | null;
20
+ isModifierRequired: (modifierName: string) => boolean;
21
+ hasRequiredModifiers: () => boolean;
22
+ areAllRequiredModifiersFilled: () => boolean;
23
+ }
24
+ export declare const ProductModifiersServiceDefinition: string & {
25
+ __api: ProductModifiersServiceAPI;
26
+ __config: {};
27
+ isServiceDefinition?: boolean;
28
+ } & ProductModifiersServiceAPI;
29
+ export declare const ProductModifiersService: import("@wix/services-definitions").ServiceFactory<string & {
30
+ __api: ProductModifiersServiceAPI;
31
+ __config: {};
32
+ isServiceDefinition?: boolean;
33
+ } & ProductModifiersServiceAPI, unknown>;
34
+ export declare function createProductModifiersServiceConfig(product: productsV3.V3Product): ServiceFactoryConfig<typeof ProductModifiersService>;
@@ -0,0 +1,107 @@
1
+ import { defineService, implementService, } from '@wix/services-definitions';
2
+ import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
3
+ import * as productsV3 from '@wix/auto_sdk_stores_products-v-3';
4
+ import { ProductServiceDefinition } from './product-service.js';
5
+ export const ProductModifiersServiceDefinition = defineService('productModifiers');
6
+ export const ProductModifiersService = implementService.withConfig()(ProductModifiersServiceDefinition, ({ getService }) => {
7
+ const signalsService = getService(SignalsServiceDefinition);
8
+ const productService = getService(ProductServiceDefinition);
9
+ const selectedModifiers = signalsService.signal({});
10
+ const isLoading = signalsService.signal(false);
11
+ const error = signalsService.signal(null);
12
+ // Extract modifiers from product
13
+ const modifiers = signalsService.computed(() => {
14
+ const configProduct = productService.product.get();
15
+ return (configProduct?.modifiers || []);
16
+ });
17
+ const hasModifiers = signalsService.computed(() => {
18
+ const mods = modifiers.get();
19
+ return mods.length > 0;
20
+ });
21
+ const setModifierChoice = (modifierName, choiceValue) => {
22
+ const current = selectedModifiers.get();
23
+ selectedModifiers.set({
24
+ ...current,
25
+ [modifierName]: {
26
+ modifierName,
27
+ choiceValue,
28
+ },
29
+ });
30
+ };
31
+ const setModifierFreeText = (modifierName, freeTextValue) => {
32
+ const current = selectedModifiers.get();
33
+ selectedModifiers.set({
34
+ ...current,
35
+ [modifierName]: {
36
+ modifierName,
37
+ freeTextValue,
38
+ },
39
+ });
40
+ };
41
+ const clearModifier = (modifierName) => {
42
+ const current = selectedModifiers.get();
43
+ const updated = { ...current };
44
+ delete updated[modifierName];
45
+ selectedModifiers.set(updated);
46
+ };
47
+ const clearAllModifiers = () => {
48
+ selectedModifiers.set({});
49
+ };
50
+ const getModifierValue = (modifierName) => {
51
+ const current = selectedModifiers.get();
52
+ return current[modifierName] || null;
53
+ };
54
+ const isModifierRequired = (modifierName) => {
55
+ const mods = modifiers.get();
56
+ const modifier = mods.find((m) => m.name === modifierName);
57
+ return modifier?.mandatory || false;
58
+ };
59
+ const hasRequiredModifiers = () => {
60
+ const mods = modifiers.get();
61
+ return mods.some((m) => m.mandatory);
62
+ };
63
+ const areAllRequiredModifiersFilled = () => {
64
+ const mods = modifiers.get();
65
+ const current = selectedModifiers.get();
66
+ return mods.every((modifier) => {
67
+ if (!modifier.mandatory)
68
+ return true;
69
+ const selectedValue = current[modifier.name || ''];
70
+ if (!selectedValue)
71
+ return false;
72
+ // Check based on modifier type
73
+ const renderType = modifier.modifierRenderType;
74
+ if (!renderType)
75
+ return false;
76
+ if (renderType === productsV3.ModifierRenderType.SWATCH_CHOICES ||
77
+ renderType === productsV3.ModifierRenderType.TEXT_CHOICES) {
78
+ return !!selectedValue.choiceValue;
79
+ }
80
+ else if (renderType === productsV3.ModifierRenderType.FREE_TEXT) {
81
+ return (!!selectedValue.freeTextValue &&
82
+ selectedValue.freeTextValue.trim() !== '');
83
+ }
84
+ return false;
85
+ });
86
+ };
87
+ return {
88
+ modifiers,
89
+ selectedModifiers,
90
+ hasModifiers,
91
+ isLoading,
92
+ error,
93
+ setModifierChoice,
94
+ setModifierFreeText,
95
+ clearModifier,
96
+ clearAllModifiers,
97
+ getModifierValue,
98
+ isModifierRequired,
99
+ hasRequiredModifiers,
100
+ areAllRequiredModifiersFilled,
101
+ };
102
+ });
103
+ export function createProductModifiersServiceConfig(product) {
104
+ return {
105
+ product,
106
+ };
107
+ }
@@ -0,0 +1,177 @@
1
+ import { type Signal } from '@wix/services-definitions/core-services/signals';
2
+ import * as productsV3 from '@wix/auto_sdk_stores_products-v-3';
3
+ /**
4
+ * API interface for the Product service, providing reactive product data management.
5
+ * This service handles loading and managing a single product's data, loading state, and errors.
6
+ *
7
+ * @interface ProductServiceAPI
8
+ */
9
+ export interface ProductServiceAPI {
10
+ /** Reactive signal containing the current product data */
11
+ product: Signal<productsV3.V3Product>;
12
+ /** Reactive signal indicating if a product is currently being loaded */
13
+ isLoading: Signal<boolean>;
14
+ /** Reactive signal containing any error message, or null if no error */
15
+ error: Signal<string | null>;
16
+ /** Function to load a product by its slug */
17
+ loadProduct: (slug: string) => Promise<void>;
18
+ }
19
+ /**
20
+ * Service definition for the Product service.
21
+ * This defines the contract that the ProductService must implement.
22
+ *
23
+ * @constant
24
+ */
25
+ export declare const ProductServiceDefinition: string & {
26
+ __api: ProductServiceAPI;
27
+ __config: {};
28
+ isServiceDefinition?: boolean;
29
+ } & ProductServiceAPI;
30
+ /**
31
+ * Configuration interface required to initialize the ProductService.
32
+ * Contains the initial product data that will be loaded into the service.
33
+ *
34
+ * @interface ProductServiceConfig
35
+ */
36
+ export interface ProductServiceConfig {
37
+ /** The initial product data to configure the service with */
38
+ product?: productsV3.V3Product;
39
+ productSlug?: string;
40
+ }
41
+ /**
42
+ * Implementation of the Product service that manages reactive product data.
43
+ * This service provides signals for product data, loading state, and error handling,
44
+ * along with methods to dynamically load products.
45
+ *
46
+ * @example
47
+ * ```tsx
48
+ * import { ProductService, ProductServiceDefinition } from '@wix/stores/services';
49
+ * import { useService } from '@wix/services-manager-react';
50
+ *
51
+ * function ProductComponent({ productConfig }) {
52
+ * return (
53
+ * <ServiceProvider services={createServicesMap([
54
+ * [ProductServiceDefinition, ProductService.withConfig(productConfig)]
55
+ * ])}>
56
+ * <ProductDisplay />
57
+ * </ServiceProvider>
58
+ * );
59
+ * }
60
+ *
61
+ * function ProductDisplay() {
62
+ * const productService = useService(ProductServiceDefinition);
63
+ * const product = productService.product.get();
64
+ * const isLoading = productService.isLoading.get();
65
+ * const error = productService.error.get();
66
+ *
67
+ * if (isLoading) return <div>Loading...</div>;
68
+ * if (error) return <div>Error: {error}</div>;
69
+ *
70
+ * return <h1>{product.name}</h1>;
71
+ * }
72
+ * ```
73
+ */
74
+ export declare const ProductService: import("@wix/services-definitions").ServiceFactory<string & {
75
+ __api: ProductServiceAPI;
76
+ __config: {};
77
+ isServiceDefinition?: boolean;
78
+ } & ProductServiceAPI, ProductServiceConfig>;
79
+ /**
80
+ * Success result interface for product service configuration loading.
81
+ * Returned when a product is successfully found and loaded.
82
+ *
83
+ * @interface SuccessProductServiceConfigResult
84
+ */
85
+ export interface SuccessProductServiceConfigResult {
86
+ /** Type "success" means that the product was found and the config is valid */
87
+ type: 'success';
88
+ /** The product config containing the loaded product data */
89
+ config: ProductServiceConfig;
90
+ }
91
+ /**
92
+ * Not found result interface for product service configuration loading.
93
+ * Returned when a product with the given slug cannot be found.
94
+ *
95
+ * @interface NotFoundProductServiceConfigResult
96
+ */
97
+ export interface NotFoundProductServiceConfigResult {
98
+ /** Type "notFound" means that the product was not found */
99
+ type: 'notFound';
100
+ }
101
+ /**
102
+ * Loads product service configuration from the Wix Products API for SSR initialization.
103
+ * This function is designed to be used during Server-Side Rendering (SSR) to preload
104
+ * a specific product by slug that will be used to configure the ProductService.
105
+ *
106
+ * @param productSlug The product slug to load
107
+ * @returns Promise that resolves to ProductServiceConfigResult (success with config or notFound)
108
+ *
109
+ * @example
110
+ * ```astro
111
+ * ---
112
+ * // Astro page example - pages/product/[slug].astro
113
+ * import { loadProductServiceConfig } from '@wix/stores/services';
114
+ * import { Product } from '@wix/stores/components';
115
+ *
116
+ * // Get product slug from URL params
117
+ * const { slug } = Astro.params;
118
+ *
119
+ * // Load product data during SSR
120
+ * const productResult = await loadProductServiceConfig(slug);
121
+ *
122
+ * // Handle not found case
123
+ * if (productResult.type === 'notFound') {
124
+ * return Astro.redirect('/404');
125
+ * }
126
+ * ---
127
+ *
128
+ * <Product.Root productConfig={productResult.config}>
129
+ * <Product.Name>
130
+ * {({ name }) => <h1>{name}</h1>}
131
+ * </Product.Name>
132
+ * </Product.Root>
133
+ * ```
134
+ *
135
+ * @example
136
+ * ```tsx
137
+ * // Next.js page example - pages/product/[slug].tsx
138
+ * import { GetServerSideProps } from 'next';
139
+ * import { loadProductServiceConfig } from '@wix/stores/services';
140
+ * import { Product } from '@wix/stores/components';
141
+ *
142
+ * interface ProductPageProps {
143
+ * productConfig: Extract<Awaited<ReturnType<typeof loadProductServiceConfig>>, { type: 'success' }>['config'];
144
+ * }
145
+ *
146
+ * export const getServerSideProps: GetServerSideProps<ProductPageProps> = async ({ params }) => {
147
+ * const slug = params?.slug as string;
148
+ *
149
+ * // Load product data during SSR
150
+ * const productResult = await loadProductServiceConfig(slug);
151
+ *
152
+ * // Handle not found case
153
+ * if (productResult.type === 'notFound') {
154
+ * return {
155
+ * notFound: true,
156
+ * };
157
+ * }
158
+ *
159
+ * return {
160
+ * props: {
161
+ * productConfig: productResult.config,
162
+ * },
163
+ * };
164
+ * };
165
+ *
166
+ * export default function ProductPage({ productConfig }: ProductPageProps) {
167
+ * return (
168
+ * <Product.Root productConfig={productConfig}>
169
+ * <Product.Name>
170
+ * {({ name }) => <h1>{name}</h1>}
171
+ * </Product.Name>
172
+ * </Product.Root>
173
+ * );
174
+ * }
175
+ * ```
176
+ */
177
+ export declare function loadProductServiceConfig(productSlug: string): Promise<SuccessProductServiceConfigResult | NotFoundProductServiceConfigResult>;
@@ -0,0 +1,190 @@
1
+ import { defineService, implementService } from '@wix/services-definitions';
2
+ import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
3
+ import * as productsV3 from '@wix/auto_sdk_stores_products-v-3';
4
+ /**
5
+ * Service definition for the Product service.
6
+ * This defines the contract that the ProductService must implement.
7
+ *
8
+ * @constant
9
+ */
10
+ export const ProductServiceDefinition = defineService('product');
11
+ /**
12
+ * Implementation of the Product service that manages reactive product data.
13
+ * This service provides signals for product data, loading state, and error handling,
14
+ * along with methods to dynamically load products.
15
+ *
16
+ * @example
17
+ * ```tsx
18
+ * import { ProductService, ProductServiceDefinition } from '@wix/stores/services';
19
+ * import { useService } from '@wix/services-manager-react';
20
+ *
21
+ * function ProductComponent({ productConfig }) {
22
+ * return (
23
+ * <ServiceProvider services={createServicesMap([
24
+ * [ProductServiceDefinition, ProductService.withConfig(productConfig)]
25
+ * ])}>
26
+ * <ProductDisplay />
27
+ * </ServiceProvider>
28
+ * );
29
+ * }
30
+ *
31
+ * function ProductDisplay() {
32
+ * const productService = useService(ProductServiceDefinition);
33
+ * const product = productService.product.get();
34
+ * const isLoading = productService.isLoading.get();
35
+ * const error = productService.error.get();
36
+ *
37
+ * if (isLoading) return <div>Loading...</div>;
38
+ * if (error) return <div>Error: {error}</div>;
39
+ *
40
+ * return <h1>{product.name}</h1>;
41
+ * }
42
+ * ```
43
+ */
44
+ export const ProductService = implementService.withConfig()(ProductServiceDefinition, ({ getService, config }) => {
45
+ const signalsService = getService(SignalsServiceDefinition);
46
+ const product = signalsService.signal(config.product);
47
+ const isLoading = signalsService.signal(!!config.productSlug);
48
+ const error = signalsService.signal(null);
49
+ const loadProduct = async (slug) => {
50
+ isLoading.set(true);
51
+ const productResponse = await loadProductBySlug(slug);
52
+ if (!productResponse.product) {
53
+ error.set('Product not found');
54
+ }
55
+ else {
56
+ product.set(productResponse.product);
57
+ error.set(null);
58
+ }
59
+ isLoading.set(false);
60
+ };
61
+ if (config.productSlug) {
62
+ loadProduct(config.productSlug);
63
+ }
64
+ return {
65
+ product,
66
+ isLoading,
67
+ error,
68
+ loadProduct,
69
+ };
70
+ });
71
+ /**
72
+ * Internal helper function to load a product by its slug from the Wix Products API.
73
+ * Fetches comprehensive product data including description, categories, media, etc.
74
+ *
75
+ * @private
76
+ * @param {string} slug - The product slug to load
77
+ * @returns {Promise} Product response from the API
78
+ */
79
+ const loadProductBySlug = async (slug) => {
80
+ const productResponse = await productsV3.getProductBySlug(slug, {
81
+ fields: [
82
+ 'DESCRIPTION',
83
+ 'DIRECT_CATEGORIES_INFO',
84
+ 'BREADCRUMBS_INFO',
85
+ 'INFO_SECTION',
86
+ 'MEDIA_ITEMS_INFO',
87
+ 'PLAIN_DESCRIPTION',
88
+ 'THUMBNAIL',
89
+ 'URL',
90
+ 'VARIANT_OPTION_CHOICE_NAMES',
91
+ 'WEIGHT_MEASUREMENT_UNIT_INFO',
92
+ ],
93
+ });
94
+ return productResponse;
95
+ };
96
+ /**
97
+ * Loads product service configuration from the Wix Products API for SSR initialization.
98
+ * This function is designed to be used during Server-Side Rendering (SSR) to preload
99
+ * a specific product by slug that will be used to configure the ProductService.
100
+ *
101
+ * @param productSlug The product slug to load
102
+ * @returns Promise that resolves to ProductServiceConfigResult (success with config or notFound)
103
+ *
104
+ * @example
105
+ * ```astro
106
+ * ---
107
+ * // Astro page example - pages/product/[slug].astro
108
+ * import { loadProductServiceConfig } from '@wix/stores/services';
109
+ * import { Product } from '@wix/stores/components';
110
+ *
111
+ * // Get product slug from URL params
112
+ * const { slug } = Astro.params;
113
+ *
114
+ * // Load product data during SSR
115
+ * const productResult = await loadProductServiceConfig(slug);
116
+ *
117
+ * // Handle not found case
118
+ * if (productResult.type === 'notFound') {
119
+ * return Astro.redirect('/404');
120
+ * }
121
+ * ---
122
+ *
123
+ * <Product.Root productConfig={productResult.config}>
124
+ * <Product.Name>
125
+ * {({ name }) => <h1>{name}</h1>}
126
+ * </Product.Name>
127
+ * </Product.Root>
128
+ * ```
129
+ *
130
+ * @example
131
+ * ```tsx
132
+ * // Next.js page example - pages/product/[slug].tsx
133
+ * import { GetServerSideProps } from 'next';
134
+ * import { loadProductServiceConfig } from '@wix/stores/services';
135
+ * import { Product } from '@wix/stores/components';
136
+ *
137
+ * interface ProductPageProps {
138
+ * productConfig: Extract<Awaited<ReturnType<typeof loadProductServiceConfig>>, { type: 'success' }>['config'];
139
+ * }
140
+ *
141
+ * export const getServerSideProps: GetServerSideProps<ProductPageProps> = async ({ params }) => {
142
+ * const slug = params?.slug as string;
143
+ *
144
+ * // Load product data during SSR
145
+ * const productResult = await loadProductServiceConfig(slug);
146
+ *
147
+ * // Handle not found case
148
+ * if (productResult.type === 'notFound') {
149
+ * return {
150
+ * notFound: true,
151
+ * };
152
+ * }
153
+ *
154
+ * return {
155
+ * props: {
156
+ * productConfig: productResult.config,
157
+ * },
158
+ * };
159
+ * };
160
+ *
161
+ * export default function ProductPage({ productConfig }: ProductPageProps) {
162
+ * return (
163
+ * <Product.Root productConfig={productConfig}>
164
+ * <Product.Name>
165
+ * {({ name }) => <h1>{name}</h1>}
166
+ * </Product.Name>
167
+ * </Product.Root>
168
+ * );
169
+ * }
170
+ * ```
171
+ */
172
+ export async function loadProductServiceConfig(productSlug) {
173
+ try {
174
+ // Use getProductBySlug directly - single API call with comprehensive fields
175
+ const productResponse = await loadProductBySlug(productSlug);
176
+ if (!productResponse.product) {
177
+ return { type: 'notFound' };
178
+ }
179
+ return {
180
+ type: 'success',
181
+ config: {
182
+ product: productResponse.product,
183
+ },
184
+ };
185
+ }
186
+ catch (error) {
187
+ console.error(`Failed to load product for slug "${productSlug}":`, error);
188
+ return { type: 'notFound' };
189
+ }
190
+ }
@@ -0,0 +1 @@
1
+ "use strict";