@decocms/apps 0.23.3 → 0.25.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 (111) hide show
  1. package/LICENSE +21 -0
  2. package/commerce/components/Image.tsx +129 -143
  3. package/commerce/components/JsonLd.tsx +192 -201
  4. package/commerce/components/Picture.tsx +65 -75
  5. package/commerce/sdk/analytics.ts +15 -15
  6. package/commerce/sdk/formatPrice.ts +13 -16
  7. package/commerce/sdk/url.ts +7 -7
  8. package/commerce/sdk/useOffer.ts +46 -57
  9. package/commerce/sdk/useVariantPossibilities.ts +25 -25
  10. package/commerce/types/commerce.ts +868 -875
  11. package/commerce/utils/canonical.ts +5 -8
  12. package/commerce/utils/constants.ts +5 -6
  13. package/commerce/utils/filters.ts +4 -4
  14. package/commerce/utils/productToAnalyticsItem.ts +52 -56
  15. package/commerce/utils/stateByZip.ts +42 -42
  16. package/package.json +24 -4
  17. package/shopify/actions/cart/addItems.ts +24 -25
  18. package/shopify/actions/cart/updateCoupons.ts +19 -20
  19. package/shopify/actions/cart/updateItems.ts +19 -20
  20. package/shopify/actions/user/signIn.ts +25 -30
  21. package/shopify/actions/user/signUp.ts +19 -24
  22. package/shopify/client.ts +24 -24
  23. package/shopify/index.ts +20 -18
  24. package/shopify/init.ts +18 -21
  25. package/shopify/loaders/ProductDetailsPage.ts +16 -20
  26. package/shopify/loaders/ProductList.ts +66 -69
  27. package/shopify/loaders/ProductListingPage.ts +150 -158
  28. package/shopify/loaders/RelatedProducts.ts +24 -27
  29. package/shopify/loaders/cart.ts +53 -52
  30. package/shopify/loaders/shop.ts +22 -27
  31. package/shopify/loaders/user.ts +27 -32
  32. package/shopify/utils/admin/admin.ts +33 -34
  33. package/shopify/utils/admin/queries.ts +2 -2
  34. package/shopify/utils/cart.ts +18 -14
  35. package/shopify/utils/cookies.ts +62 -65
  36. package/shopify/utils/enums.ts +424 -424
  37. package/shopify/utils/graphql.ts +44 -55
  38. package/shopify/utils/storefront/queries.ts +24 -29
  39. package/shopify/utils/storefront/storefront.graphql.gen.ts +55 -55
  40. package/shopify/utils/transform.ts +370 -376
  41. package/shopify/utils/types.ts +118 -118
  42. package/shopify/utils/user.ts +11 -11
  43. package/shopify/utils/utils.ts +135 -140
  44. package/vtex/actions/address.ts +86 -86
  45. package/vtex/actions/auth.ts +14 -27
  46. package/vtex/actions/checkout.ts +36 -49
  47. package/vtex/actions/masterData.ts +10 -27
  48. package/vtex/actions/misc.ts +101 -111
  49. package/vtex/actions/newsletter.ts +48 -52
  50. package/vtex/actions/orders.ts +13 -16
  51. package/vtex/actions/profile.ts +55 -55
  52. package/vtex/actions/session.ts +36 -35
  53. package/vtex/actions/trigger.ts +25 -25
  54. package/vtex/actions/wishlist.ts +51 -53
  55. package/vtex/client.ts +14 -42
  56. package/vtex/hooks/index.ts +4 -4
  57. package/vtex/hooks/useAutocomplete.ts +42 -48
  58. package/vtex/hooks/useCart.ts +153 -165
  59. package/vtex/hooks/useUser.ts +40 -40
  60. package/vtex/hooks/useWishlist.ts +70 -70
  61. package/vtex/inline-loaders/productDetailsPage.ts +1 -3
  62. package/vtex/inline-loaders/productList.ts +121 -127
  63. package/vtex/inline-loaders/productListShelf.ts +159 -0
  64. package/vtex/inline-loaders/productListingPage.ts +10 -34
  65. package/vtex/inline-loaders/relatedProducts.ts +1 -3
  66. package/vtex/inline-loaders/suggestions.ts +36 -39
  67. package/vtex/inline-loaders/workflowProducts.ts +45 -49
  68. package/vtex/invoke.ts +159 -194
  69. package/vtex/loaders/address.ts +49 -54
  70. package/vtex/loaders/brands.ts +19 -26
  71. package/vtex/loaders/cart.ts +24 -21
  72. package/vtex/loaders/catalog.ts +51 -53
  73. package/vtex/loaders/collections.ts +25 -27
  74. package/vtex/loaders/legacy.ts +487 -534
  75. package/vtex/loaders/logistics.ts +33 -37
  76. package/vtex/loaders/navbar.ts +5 -8
  77. package/vtex/loaders/orders.ts +28 -39
  78. package/vtex/loaders/pageType.ts +41 -35
  79. package/vtex/loaders/payment.ts +27 -37
  80. package/vtex/loaders/profile.ts +38 -38
  81. package/vtex/loaders/promotion.ts +5 -8
  82. package/vtex/loaders/search.ts +56 -59
  83. package/vtex/loaders/session.ts +22 -30
  84. package/vtex/loaders/user.ts +39 -41
  85. package/vtex/loaders/wishlist.ts +35 -35
  86. package/vtex/loaders/wishlistProducts.ts +3 -15
  87. package/vtex/loaders/workflow.ts +220 -227
  88. package/vtex/middleware.ts +116 -119
  89. package/vtex/types.ts +201 -201
  90. package/vtex/utils/batch.ts +13 -16
  91. package/vtex/utils/cookies.ts +76 -80
  92. package/vtex/utils/enrichment.ts +62 -42
  93. package/vtex/utils/fetchCache.ts +1 -4
  94. package/vtex/utils/index.ts +6 -6
  95. package/vtex/utils/intelligentSearch.ts +48 -57
  96. package/vtex/utils/legacy.ts +108 -124
  97. package/vtex/utils/pickAndOmit.ts +15 -20
  98. package/vtex/utils/proxy.ts +136 -146
  99. package/vtex/utils/resourceRange.ts +3 -3
  100. package/vtex/utils/segment.ts +100 -111
  101. package/vtex/utils/similars.ts +1 -2
  102. package/vtex/utils/sitemap.ts +91 -91
  103. package/vtex/utils/slugCache.ts +2 -6
  104. package/vtex/utils/slugify.ts +9 -9
  105. package/vtex/utils/transform.ts +1178 -1105
  106. package/vtex/utils/types.ts +1381 -1381
  107. package/vtex/utils/vtexId.ts +44 -47
  108. package/.github/workflows/release.yml +0 -34
  109. package/.releaserc.json +0 -28
  110. package/knip.json +0 -19
  111. package/tsconfig.json +0 -11
@@ -5,159 +5,153 @@
5
5
  * Supports: query search, collection IDs, SKU IDs, facets, sort, and
6
6
  * hideUnavailableItems — matching the original productList.ts behavior.
7
7
  */
8
- import { intelligentSearch, getVtexConfig, toFacetPath } from "../client";
9
- import { toProduct, pickSku, sortProducts } from "../utils/transform";
10
- import type { Product as ProductVTEX } from "../utils/types";
8
+
11
9
  import type { Product } from "../../commerce/types/commerce";
10
+ import { getVtexConfig, intelligentSearch, toFacetPath } from "../client";
11
+ import { pickSku, sortProducts, toProduct } from "../utils/transform";
12
+ import type { Product as ProductVTEX } from "../utils/types";
12
13
 
13
14
  export interface ProductListProps {
14
- props?: CollectionProps | QueryProps | ProductIDProps | FacetsProps;
15
- query?: string;
16
- count?: number;
17
- sort?: string;
18
- collection?: string;
19
- hideUnavailableItems?: boolean;
15
+ props?: CollectionProps | QueryProps | ProductIDProps | FacetsProps;
16
+ query?: string;
17
+ count?: number;
18
+ sort?: string;
19
+ collection?: string;
20
+ hideUnavailableItems?: boolean;
20
21
  }
21
22
 
22
23
  interface CollectionProps {
23
- collection: string;
24
- count?: number;
25
- sort?: string;
26
- hideUnavailableItems?: boolean;
24
+ collection: string;
25
+ count?: number;
26
+ sort?: string;
27
+ hideUnavailableItems?: boolean;
27
28
  }
28
29
 
29
30
  interface QueryProps {
30
- query: string;
31
- count?: number;
32
- sort?: string;
33
- fuzzy?: string;
34
- hideUnavailableItems?: boolean;
31
+ query: string;
32
+ count?: number;
33
+ sort?: string;
34
+ fuzzy?: string;
35
+ hideUnavailableItems?: boolean;
35
36
  }
36
37
 
37
38
  interface ProductIDProps {
38
- ids: string[];
39
- hideUnavailableItems?: boolean;
39
+ ids: string[];
40
+ hideUnavailableItems?: boolean;
40
41
  }
41
42
 
42
43
  interface FacetsProps {
43
- query?: string;
44
- facets: string;
45
- count?: number;
46
- sort?: string;
47
- hideUnavailableItems?: boolean;
44
+ query?: string;
45
+ facets: string;
46
+ count?: number;
47
+ sort?: string;
48
+ hideUnavailableItems?: boolean;
48
49
  }
49
50
 
50
51
  function isCollectionProps(p: any): p is CollectionProps {
51
- return typeof p?.collection === "string";
52
+ return typeof p?.collection === "string";
52
53
  }
53
54
  function isProductIDProps(p: any): p is ProductIDProps {
54
- return Array.isArray(p?.ids) && p.ids.length > 0;
55
+ return Array.isArray(p?.ids) && p.ids.length > 0;
55
56
  }
56
57
  function isFacetsProps(p: any): p is FacetsProps {
57
- return typeof p?.facets === "string";
58
+ return typeof p?.facets === "string";
58
59
  }
59
60
 
60
61
  function resolveParams(props: ProductListProps): {
61
- query: string;
62
- count: number;
63
- sort: string;
64
- facetPath: string;
65
- fuzzy?: string;
66
- hideUnavailableItems: boolean;
67
- ids?: string[];
62
+ query: string;
63
+ count: number;
64
+ sort: string;
65
+ facetPath: string;
66
+ fuzzy?: string;
67
+ hideUnavailableItems: boolean;
68
+ ids?: string[];
68
69
  } {
69
- const inner = props.props ?? props;
70
-
71
- if (isProductIDProps(inner)) {
72
- return {
73
- query: `sku:${inner.ids.join(";")}`,
74
- count: inner.ids.length,
75
- sort: "",
76
- facetPath: "",
77
- hideUnavailableItems: inner.hideUnavailableItems ?? false,
78
- ids: inner.ids,
79
- };
80
- }
81
-
82
- if (isFacetsProps(inner)) {
83
- return {
84
- query: inner.query ?? "",
85
- count: inner.count ?? 12,
86
- sort: inner.sort ?? "",
87
- facetPath: inner.facets,
88
- hideUnavailableItems: inner.hideUnavailableItems ?? false,
89
- };
90
- }
91
-
92
- if (isCollectionProps(inner)) {
93
- return {
94
- query: "",
95
- count: inner.count ?? 12,
96
- sort: inner.sort ?? "",
97
- facetPath: toFacetPath([{ key: "productClusterIds", value: inner.collection }]),
98
- hideUnavailableItems: inner.hideUnavailableItems ?? false,
99
- };
100
- }
101
-
102
- return {
103
- query: (inner as any).query ?? "",
104
- count: (inner as any).count ?? 12,
105
- sort: (inner as any).sort ?? "",
106
- facetPath: "",
107
- fuzzy: (inner as any).fuzzy,
108
- hideUnavailableItems: (inner as any).hideUnavailableItems ?? false,
109
- };
70
+ const inner = props.props ?? props;
71
+
72
+ if (isProductIDProps(inner)) {
73
+ return {
74
+ query: `sku:${inner.ids.join(";")}`,
75
+ count: inner.ids.length,
76
+ sort: "",
77
+ facetPath: "",
78
+ hideUnavailableItems: inner.hideUnavailableItems ?? false,
79
+ ids: inner.ids,
80
+ };
81
+ }
82
+
83
+ if (isFacetsProps(inner)) {
84
+ return {
85
+ query: inner.query ?? "",
86
+ count: inner.count ?? 12,
87
+ sort: inner.sort ?? "",
88
+ facetPath: inner.facets,
89
+ hideUnavailableItems: inner.hideUnavailableItems ?? false,
90
+ };
91
+ }
92
+
93
+ if (isCollectionProps(inner)) {
94
+ return {
95
+ query: "",
96
+ count: inner.count ?? 12,
97
+ sort: inner.sort ?? "",
98
+ facetPath: toFacetPath([{ key: "productClusterIds", value: inner.collection }]),
99
+ hideUnavailableItems: inner.hideUnavailableItems ?? false,
100
+ };
101
+ }
102
+
103
+ return {
104
+ query: (inner as any).query ?? "",
105
+ count: (inner as any).count ?? 12,
106
+ sort: (inner as any).sort ?? "",
107
+ facetPath: "",
108
+ fuzzy: (inner as any).fuzzy,
109
+ hideUnavailableItems: (inner as any).hideUnavailableItems ?? false,
110
+ };
110
111
  }
111
112
 
112
- export default async function vtexProductList(
113
- props: ProductListProps,
114
- ): Promise<Product[] | null> {
115
- try {
116
- const { query, count, sort, facetPath, fuzzy, hideUnavailableItems, ids } =
117
- resolveParams(props);
118
-
119
- const config = getVtexConfig();
120
- const locale = config.locale ?? "pt-BR";
121
-
122
- const params: Record<string, string> = {
123
- page: "1",
124
- count: String(count),
125
- locale,
126
- hideUnavailableItems: String(hideUnavailableItems),
127
- };
128
- if (query) params.query = query;
129
- if (sort) params.sort = sort;
130
- if (fuzzy) params.fuzzy = fuzzy;
131
-
132
- const endpoint = facetPath
133
- ? `/product_search/${facetPath}`
134
- : "/product_search/";
135
-
136
- const data = await intelligentSearch<{ products: ProductVTEX[] }>(
137
- endpoint,
138
- params,
139
- );
140
-
141
- const vtexProducts = data.products ?? [];
142
- const baseUrl = config.publicUrl
143
- ? `https://${config.publicUrl}`
144
- : `https://${config.account}.vtexcommercestable.${config.domain ?? "com.br"}`;
145
-
146
- let products = vtexProducts.map((p) => {
147
- const fetchedSkus = ids ? new Set(ids) : null;
148
- const preferredSku = fetchedSkus
149
- ? p.items.find((item) => fetchedSkus.has(item.itemId)) ?? pickSku(p)
150
- : pickSku(p);
151
- return toProduct(p, preferredSku, 0, { baseUrl, priceCurrency: "BRL" });
152
- });
153
-
154
- if (ids) {
155
- products = sortProducts(products, ids, "sku");
156
- }
157
-
158
- return products;
159
- } catch (error) {
160
- console.error("[VTEX] ProductList error:", error);
161
- return null;
162
- }
113
+ export default async function vtexProductList(props: ProductListProps): Promise<Product[] | null> {
114
+ try {
115
+ const { query, count, sort, facetPath, fuzzy, hideUnavailableItems, ids } =
116
+ resolveParams(props);
117
+
118
+ const config = getVtexConfig();
119
+ const locale = config.locale ?? "pt-BR";
120
+
121
+ const params: Record<string, string> = {
122
+ page: "1",
123
+ count: String(count),
124
+ locale,
125
+ hideUnavailableItems: String(hideUnavailableItems),
126
+ };
127
+ if (query) params.query = query;
128
+ if (sort) params.sort = sort;
129
+ if (fuzzy) params.fuzzy = fuzzy;
130
+
131
+ const endpoint = facetPath ? `/product_search/${facetPath}` : "/product_search/";
132
+
133
+ const data = await intelligentSearch<{ products: ProductVTEX[] }>(endpoint, params);
134
+
135
+ const vtexProducts = data.products ?? [];
136
+ const baseUrl = config.publicUrl
137
+ ? `https://${config.publicUrl}`
138
+ : `https://${config.account}.vtexcommercestable.${config.domain ?? "com.br"}`;
139
+
140
+ let products = vtexProducts.map((p) => {
141
+ const fetchedSkus = ids ? new Set(ids) : null;
142
+ const preferredSku = fetchedSkus
143
+ ? (p.items.find((item) => fetchedSkus.has(item.itemId)) ?? pickSku(p))
144
+ : pickSku(p);
145
+ return toProduct(p, preferredSku, 0, { baseUrl, priceCurrency: "BRL" });
146
+ });
147
+
148
+ if (ids) {
149
+ products = sortProducts(products, ids, "sku");
150
+ }
151
+
152
+ return products;
153
+ } catch (error) {
154
+ console.error("[VTEX] ProductList error:", error);
155
+ return null;
156
+ }
163
157
  }
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Lean product list loader for shelf/card display.
3
+ * Same API call as productList.ts but uses toProductShelf() for ~90% smaller payloads.
4
+ *
5
+ * Use this loader for ProductShelf sections where only card-level data is needed
6
+ * (name, URL, images, price, installments, PIX, availability, brand).
7
+ */
8
+
9
+ import type { Product } from "../../commerce/types/commerce";
10
+ import { getVtexConfig, intelligentSearch, toFacetPath } from "../client";
11
+ import { pickSku, sortProducts, toProductShelf } from "../utils/transform";
12
+ import type { Product as ProductVTEX } from "../utils/types";
13
+
14
+ export interface ProductListProps {
15
+ props?: CollectionProps | QueryProps | ProductIDProps | FacetsProps;
16
+ query?: string;
17
+ count?: number;
18
+ sort?: string;
19
+ collection?: string;
20
+ hideUnavailableItems?: boolean;
21
+ }
22
+
23
+ interface CollectionProps {
24
+ collection: string;
25
+ count?: number;
26
+ sort?: string;
27
+ hideUnavailableItems?: boolean;
28
+ }
29
+
30
+ interface QueryProps {
31
+ query: string;
32
+ count?: number;
33
+ sort?: string;
34
+ fuzzy?: string;
35
+ hideUnavailableItems?: boolean;
36
+ }
37
+
38
+ interface ProductIDProps {
39
+ ids: string[];
40
+ hideUnavailableItems?: boolean;
41
+ }
42
+
43
+ interface FacetsProps {
44
+ query?: string;
45
+ facets: string;
46
+ count?: number;
47
+ sort?: string;
48
+ hideUnavailableItems?: boolean;
49
+ }
50
+
51
+ function isCollectionProps(p: any): p is CollectionProps {
52
+ return typeof p?.collection === "string";
53
+ }
54
+ function isProductIDProps(p: any): p is ProductIDProps {
55
+ return Array.isArray(p?.ids) && p.ids.length > 0;
56
+ }
57
+ function isFacetsProps(p: any): p is FacetsProps {
58
+ return typeof p?.facets === "string";
59
+ }
60
+
61
+ function resolveParams(props: ProductListProps): {
62
+ query: string;
63
+ count: number;
64
+ sort: string;
65
+ facetPath: string;
66
+ fuzzy?: string;
67
+ hideUnavailableItems: boolean;
68
+ ids?: string[];
69
+ } {
70
+ const inner = props.props ?? props;
71
+
72
+ if (isProductIDProps(inner)) {
73
+ return {
74
+ query: `sku:${inner.ids.join(";")}`,
75
+ count: inner.ids.length,
76
+ sort: "",
77
+ facetPath: "",
78
+ hideUnavailableItems: inner.hideUnavailableItems ?? false,
79
+ ids: inner.ids,
80
+ };
81
+ }
82
+
83
+ if (isFacetsProps(inner)) {
84
+ return {
85
+ query: inner.query ?? "",
86
+ count: inner.count ?? 12,
87
+ sort: inner.sort ?? "",
88
+ facetPath: inner.facets,
89
+ hideUnavailableItems: inner.hideUnavailableItems ?? false,
90
+ };
91
+ }
92
+
93
+ if (isCollectionProps(inner)) {
94
+ return {
95
+ query: "",
96
+ count: inner.count ?? 12,
97
+ sort: inner.sort ?? "",
98
+ facetPath: toFacetPath([{ key: "productClusterIds", value: inner.collection }]),
99
+ hideUnavailableItems: inner.hideUnavailableItems ?? false,
100
+ };
101
+ }
102
+
103
+ return {
104
+ query: (inner as any).query ?? "",
105
+ count: (inner as any).count ?? 12,
106
+ sort: (inner as any).sort ?? "",
107
+ facetPath: "",
108
+ fuzzy: (inner as any).fuzzy,
109
+ hideUnavailableItems: (inner as any).hideUnavailableItems ?? false,
110
+ };
111
+ }
112
+
113
+ export default async function vtexProductListShelf(
114
+ props: ProductListProps,
115
+ ): Promise<Product[] | null> {
116
+ try {
117
+ const { query, count, sort, facetPath, fuzzy, hideUnavailableItems, ids } =
118
+ resolveParams(props);
119
+
120
+ const config = getVtexConfig();
121
+ const locale = config.locale ?? "pt-BR";
122
+
123
+ const params: Record<string, string> = {
124
+ page: "1",
125
+ count: String(count),
126
+ locale,
127
+ hideUnavailableItems: String(hideUnavailableItems),
128
+ };
129
+ if (query) params.query = query;
130
+ if (sort) params.sort = sort;
131
+ if (fuzzy) params.fuzzy = fuzzy;
132
+
133
+ const endpoint = facetPath ? `/product_search/${facetPath}` : "/product_search/";
134
+
135
+ const data = await intelligentSearch<{ products: ProductVTEX[] }>(endpoint, params);
136
+
137
+ const vtexProducts = data.products ?? [];
138
+ const baseUrl = config.publicUrl
139
+ ? `https://${config.publicUrl}`
140
+ : `https://${config.account}.vtexcommercestable.${config.domain ?? "com.br"}`;
141
+
142
+ let products = vtexProducts.map((p) => {
143
+ const fetchedSkus = ids ? new Set(ids) : null;
144
+ const preferredSku = fetchedSkus
145
+ ? (p.items.find((item) => fetchedSkus.has(item.itemId)) ?? pickSku(p))
146
+ : pickSku(p);
147
+ return toProductShelf(p, preferredSku, 0, { baseUrl, priceCurrency: "BRL" });
148
+ });
149
+
150
+ if (ids) {
151
+ products = sortProducts(products, ids, "sku");
152
+ }
153
+
154
+ return products;
155
+ } catch (error) {
156
+ console.error("[VTEX] ProductListShelf error:", error);
157
+ return null;
158
+ }
159
+ }
@@ -149,18 +149,13 @@ function facetToToggle(
149
149
  };
150
150
  }
151
151
 
152
- function toFilter(
153
- selectedFacets: SelectedFacet[],
154
- paramsToPersist?: URLSearchParams,
155
- ) {
152
+ function toFilter(selectedFacets: SelectedFacet[], paramsToPersist?: URLSearchParams) {
156
153
  return (facet: ISFacet) => ({
157
154
  "@type": "FilterToggle" as const,
158
155
  key: facet.key,
159
156
  label: facet.name,
160
157
  quantity: facet.quantity,
161
- values: facet.values.map(
162
- facetToToggle(selectedFacets, facet.key, paramsToPersist),
163
- ),
158
+ values: facet.values.map(facetToToggle(selectedFacets, facet.key, paramsToPersist)),
164
159
  });
165
160
  }
166
161
 
@@ -169,9 +164,7 @@ function toFilter(
169
164
  function pageTypesToBreadcrumb(pageTypes: PageType[]) {
170
165
  const filtered = pageTypes.filter(
171
166
  (pt) =>
172
- pt.pageType === "Category" ||
173
- pt.pageType === "Department" ||
174
- pt.pageType === "SubCategory",
167
+ pt.pageType === "Category" || pt.pageType === "Department" || pt.pageType === "SubCategory",
175
168
  );
176
169
  return filtered.map((page, index) => {
177
170
  const position = index + 1;
@@ -268,12 +261,8 @@ function isValidPLPPath(path: string): boolean {
268
261
  * 4. Transform facets to FilterToggle format
269
262
  * 5. Build pagination from IS response
270
263
  */
271
- export default async function vtexProductListingPage(
272
- props: PLPProps,
273
- ): Promise<any | null> {
274
- const pageUrl = props.__pageUrl
275
- ? new URL(props.__pageUrl, "https://localhost")
276
- : null;
264
+ export default async function vtexProductListingPage(props: PLPProps): Promise<any | null> {
265
+ const pageUrl = props.__pageUrl ? new URL(props.__pageUrl, "https://localhost") : null;
277
266
 
278
267
  const query = props.query ?? pageUrl?.searchParams.get("q") ?? "";
279
268
  const countFromUrl = pageUrl?.searchParams.get("PS");
@@ -283,21 +272,14 @@ export default async function vtexProductListingPage(
283
272
  const fuzzy = props.fuzzy ?? pageUrl?.searchParams.get("fuzzy") ?? undefined;
284
273
  const pageFromUrl = pageUrl?.searchParams.get("page");
285
274
  const rawPage = props.page ?? (pageFromUrl ? Number(pageFromUrl) - 1 : 0);
286
- const page =
287
- Number.isFinite(rawPage) && rawPage >= 0 ? Math.floor(rawPage) : 0;
275
+ const page = Number.isFinite(rawPage) && rawPage >= 0 ? Math.floor(rawPage) : 0;
288
276
 
289
- const {
290
- selectedFacets: cmsSelectedFacets,
291
- hideUnavailableItems = false,
292
- __pagePath,
293
- } = props;
277
+ const { selectedFacets: cmsSelectedFacets, hideUnavailableItems = false, __pagePath } = props;
294
278
 
295
279
  try {
296
280
  // 1. Resolve selected facets (CMS + URL filter.* params, matching original)
297
281
  let facets: SelectedFacet[] =
298
- cmsSelectedFacets && cmsSelectedFacets.length > 0
299
- ? [...cmsSelectedFacets]
300
- : [];
282
+ cmsSelectedFacets && cmsSelectedFacets.length > 0 ? [...cmsSelectedFacets] : [];
301
283
 
302
284
  // Extract filter.* params from URL (e.g. filter.category-1=telhas)
303
285
  if (pageUrl) {
@@ -344,9 +326,7 @@ export default async function vtexProductListingPage(
344
326
  hideUnavailableItems,
345
327
  });
346
328
 
347
- const productEndpoint = facetPath
348
- ? `/product_search/${facetPath}`
349
- : "/product_search/";
329
+ const productEndpoint = facetPath ? `/product_search/${facetPath}` : "/product_search/";
350
330
 
351
331
  const facetsEndpoint = facetPath ? `/facets/${facetPath}` : "/facets/";
352
332
 
@@ -356,11 +336,7 @@ export default async function vtexProductListingPage(
356
336
  intelligentSearch<ISFacetsResult>(facetsEndpoint, params),
357
337
  ]);
358
338
 
359
- const {
360
- products: vtexProducts,
361
- pagination,
362
- recordsFiltered,
363
- } = productsResult;
339
+ const { products: vtexProducts, pagination, recordsFiltered } = productsResult;
364
340
 
365
341
  // 3. Transform products using shared transform pipeline (same as deco-cx/apps)
366
342
  const baseUrl = config.publicUrl
@@ -69,9 +69,7 @@ export default async function vtexRelatedProducts(
69
69
 
70
70
  if (props.hideUnavailableItems) {
71
71
  result = result.filter((p) =>
72
- p.offers?.offers?.some(
73
- (o) => o.availability === "https://schema.org/InStock",
74
- ),
72
+ p.offers?.offers?.some((o) => o.availability === "https://schema.org/InStock"),
75
73
  );
76
74
  }
77
75
 
@@ -2,48 +2,45 @@
2
2
  * IS autocomplete suggestions loader.
3
3
  * Maps VTEX IS response to commerce Suggestion type.
4
4
  */
5
- import { intelligentSearch, getVtexConfig, toFacetPath } from "../client";
6
- import { toProduct, pickSku } from "../utils/transform";
5
+
6
+ import type { Product, Suggestion } from "../../commerce/types/commerce";
7
+ import { getVtexConfig, intelligentSearch } from "../client";
8
+ import { pickSku, toProduct } from "../utils/transform";
7
9
  import type { Product as ProductVTEX } from "../utils/types";
8
- import type { Suggestion, Product } from "../../commerce/types/commerce";
9
10
 
10
11
  export interface SuggestionsProps {
11
- query?: string;
12
- count?: number;
12
+ query?: string;
13
+ count?: number;
13
14
  }
14
15
 
15
- export default async function vtexSuggestions(
16
- props: SuggestionsProps,
17
- ): Promise<Suggestion | null> {
18
- const query = props.query || "";
19
- if (!query.trim()) return { searches: [], products: [] };
20
-
21
- try {
22
- const data = await intelligentSearch<{
23
- searches: Array<{ term: string; count: number }>;
24
- products: ProductVTEX[];
25
- }>("/autocomplete_suggestions/", { query });
26
-
27
- const searches = (data.searches ?? []).map((s) => ({
28
- term: s.term,
29
- hits: s.count || 0,
30
- }));
31
-
32
- const config = getVtexConfig();
33
- const baseUrl = config.publicUrl
34
- ? `https://${config.publicUrl}`
35
- : `https://${config.account}.vtexcommercestable.${config.domain ?? "com.br"}`;
36
-
37
- const products: Product[] = (data.products ?? [])
38
- .slice(0, props.count ?? 4)
39
- .map((p) => {
40
- const sku = pickSku(p);
41
- return toProduct(p, sku, 0, { baseUrl, priceCurrency: "BRL" });
42
- });
43
-
44
- return { searches, products };
45
- } catch (error) {
46
- console.error("[VTEX] Suggestions error:", error);
47
- return null;
48
- }
16
+ export default async function vtexSuggestions(props: SuggestionsProps): Promise<Suggestion | null> {
17
+ const query = props.query || "";
18
+ if (!query.trim()) return { searches: [], products: [] };
19
+
20
+ try {
21
+ const data = await intelligentSearch<{
22
+ searches: Array<{ term: string; count: number }>;
23
+ products: ProductVTEX[];
24
+ }>("/autocomplete_suggestions/", { query });
25
+
26
+ const searches = (data.searches ?? []).map((s) => ({
27
+ term: s.term,
28
+ hits: s.count || 0,
29
+ }));
30
+
31
+ const config = getVtexConfig();
32
+ const baseUrl = config.publicUrl
33
+ ? `https://${config.publicUrl}`
34
+ : `https://${config.account}.vtexcommercestable.${config.domain ?? "com.br"}`;
35
+
36
+ const products: Product[] = (data.products ?? []).slice(0, props.count ?? 4).map((p) => {
37
+ const sku = pickSku(p);
38
+ return toProduct(p, sku, 0, { baseUrl, priceCurrency: "BRL" });
39
+ });
40
+
41
+ return { searches, products };
42
+ } catch (error) {
43
+ console.error("[VTEX] Suggestions error:", error);
44
+ return null;
45
+ }
49
46
  }