@decocms/apps-vtex 8.1.0-next.0 → 8.1.0-next.2

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 (163) hide show
  1. package/dist/index.d.ts +6 -0
  2. package/dist/index.d.ts.map +1 -0
  3. package/dist/index.js +6 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/utils/constants.d.ts +28 -0
  6. package/dist/utils/constants.d.ts.map +1 -0
  7. package/dist/utils/constants.js +17 -0
  8. package/dist/utils/constants.js.map +1 -0
  9. package/dist/utils/cookieSanitizer.d.ts +87 -0
  10. package/dist/utils/cookieSanitizer.d.ts.map +1 -0
  11. package/dist/utils/cookieSanitizer.js +136 -0
  12. package/dist/utils/cookieSanitizer.js.map +1 -0
  13. package/dist/utils/operationRouter.d.ts +25 -0
  14. package/dist/utils/operationRouter.d.ts.map +1 -0
  15. package/dist/utils/operationRouter.js +120 -0
  16. package/dist/utils/operationRouter.js.map +1 -0
  17. package/dist/utils/types.d.ts +944 -0
  18. package/dist/utils/types.d.ts.map +1 -0
  19. package/dist/utils/types.js +25 -0
  20. package/dist/utils/types.js.map +1 -0
  21. package/dist/vtexClient.d.ts +173 -0
  22. package/dist/vtexClient.d.ts.map +1 -0
  23. package/dist/vtexClient.js +242 -0
  24. package/dist/vtexClient.js.map +1 -0
  25. package/package.json +16 -57
  26. package/src/index.ts +11 -29
  27. package/src/utils/constants.ts +2 -56
  28. package/src/utils/cookieSanitizer.ts +59 -59
  29. package/src/utils/operationRouter.ts +75 -65
  30. package/src/utils/types.ts +709 -1557
  31. package/src/vtexClient.ts +358 -347
  32. package/src/README.md +0 -6
  33. package/src/__conformance__/upstream.test.ts +0 -158
  34. package/src/__tests__/client-segment-cookie.test.ts +0 -255
  35. package/src/__tests__/client-set-cookie-forward.test.ts +0 -257
  36. package/src/__tests__/schemas.test.ts +0 -71
  37. package/src/actions/address.ts +0 -250
  38. package/src/actions/analytics/sendEvent.ts +0 -86
  39. package/src/actions/auth.ts +0 -333
  40. package/src/actions/checkout.ts +0 -659
  41. package/src/actions/index.ts +0 -11
  42. package/src/actions/masterData.ts +0 -168
  43. package/src/actions/misc.ts +0 -188
  44. package/src/actions/newsletter.ts +0 -105
  45. package/src/actions/orders.ts +0 -34
  46. package/src/actions/profile.ts +0 -201
  47. package/src/actions/session.ts +0 -85
  48. package/src/actions/trigger.ts +0 -43
  49. package/src/actions/wishlist.ts +0 -114
  50. package/src/client.ts +0 -724
  51. package/src/commerceLoaders.ts +0 -267
  52. package/src/hooks/__tests__/createCart.render.test.ts +0 -114
  53. package/src/hooks/__tests__/createCart.test.ts +0 -92
  54. package/src/hooks/__tests__/createUseCart.test.ts +0 -184
  55. package/src/hooks/__tests__/createUseUser.test.ts +0 -48
  56. package/src/hooks/__tests__/createUseWishlist.test.ts +0 -87
  57. package/src/hooks/cartQuery.ts +0 -204
  58. package/src/hooks/createCart.ts +0 -427
  59. package/src/hooks/createUseCart.ts +0 -360
  60. package/src/hooks/createUseUser.ts +0 -153
  61. package/src/hooks/createUseWishlist.ts +0 -242
  62. package/src/hooks/index.ts +0 -25
  63. package/src/hooks/useAutocomplete.ts +0 -83
  64. package/src/hooks/useCart.ts +0 -243
  65. package/src/hooks/useUser.ts +0 -78
  66. package/src/hooks/useWishlist.ts +0 -119
  67. package/src/invoke.ts +0 -235
  68. package/src/loaders/ProductDetailsPage.ts +0 -1
  69. package/src/loaders/ProductList.ts +0 -1
  70. package/src/loaders/ProductListingPage.ts +0 -1
  71. package/src/loaders/__tests__/legacyProductList.test.ts +0 -157
  72. package/src/loaders/address.ts +0 -115
  73. package/src/loaders/autocomplete.ts +0 -56
  74. package/src/loaders/brands.ts +0 -44
  75. package/src/loaders/cart/attachments.ts +0 -53
  76. package/src/loaders/cart/full.ts +0 -67
  77. package/src/loaders/cart/gifts.ts +0 -43
  78. package/src/loaders/cart/orderFormId.ts +0 -31
  79. package/src/loaders/cart/shipping.test.ts +0 -125
  80. package/src/loaders/cart/shipping.ts +0 -136
  81. package/src/loaders/cart/summary.ts +0 -36
  82. package/src/loaders/cart.ts +0 -52
  83. package/src/loaders/catalog.ts +0 -163
  84. package/src/loaders/collections.ts +0 -55
  85. package/src/loaders/index.ts +0 -20
  86. package/src/loaders/intelligentSearch/__tests__/productListingPage.test.ts +0 -51
  87. package/src/loaders/intelligentSearch/productDetailsPage.ts +0 -111
  88. package/src/loaders/intelligentSearch/productList.ts +0 -170
  89. package/src/loaders/intelligentSearch/productListingPage.ts +0 -525
  90. package/src/loaders/intelligentSearch/suggestions.ts +0 -44
  91. package/src/loaders/legacy/productDetailsPage.ts +0 -1
  92. package/src/loaders/legacy/productList.ts +0 -1
  93. package/src/loaders/legacy/relatedProductsLoader.ts +0 -79
  94. package/src/loaders/legacy.ts +0 -710
  95. package/src/loaders/logistics.ts +0 -111
  96. package/src/loaders/minicart.ts +0 -78
  97. package/src/loaders/navbar.ts +0 -26
  98. package/src/loaders/orders.ts +0 -92
  99. package/src/loaders/pageType.ts +0 -68
  100. package/src/loaders/paths/PDPDefaultPath.ts +0 -51
  101. package/src/loaders/payment.ts +0 -97
  102. package/src/loaders/productListFull.ts +0 -157
  103. package/src/loaders/profile.ts +0 -138
  104. package/src/loaders/promotion.ts +0 -30
  105. package/src/loaders/search.ts +0 -124
  106. package/src/loaders/session.ts +0 -83
  107. package/src/loaders/user.ts +0 -87
  108. package/src/loaders/wishlist.ts +0 -89
  109. package/src/loaders/wishlistProducts.ts +0 -69
  110. package/src/loaders/workflow/products.ts +0 -62
  111. package/src/loaders/workflow.ts +0 -316
  112. package/src/logo.png +0 -0
  113. package/src/manifest.gen.ts +0 -89
  114. package/src/middleware.cacheHeaders.test.ts +0 -44
  115. package/src/middleware.ts +0 -240
  116. package/src/mod.ts +0 -173
  117. package/src/registry.ts +0 -9
  118. package/src/schemas.gen.ts +0 -3191
  119. package/src/schemas.ts +0 -30
  120. package/src/types.ts +0 -248
  121. package/src/utils/__tests__/cartProjection.test.ts +0 -118
  122. package/src/utils/__tests__/cookieSanitizer.test.ts +0 -162
  123. package/src/utils/__tests__/fetch.test.ts +0 -80
  124. package/src/utils/__tests__/fetchCache.test.ts +0 -155
  125. package/src/utils/__tests__/instrumentedFetch.test.ts +0 -158
  126. package/src/utils/__tests__/intelligentSearch.test.ts +0 -88
  127. package/src/utils/__tests__/minicart.test.ts +0 -184
  128. package/src/utils/__tests__/operationRouter.test.ts +0 -227
  129. package/src/utils/__tests__/resilience.test.ts +0 -205
  130. package/src/utils/__tests__/resourceRange.test.ts +0 -32
  131. package/src/utils/__tests__/simulationCache.test.ts +0 -40
  132. package/src/utils/__tests__/sitemap.test.ts +0 -185
  133. package/src/utils/__tests__/slugify.test.ts +0 -31
  134. package/src/utils/__tests__/storefrontBaseUrl.test.ts +0 -61
  135. package/src/utils/__tests__/transform.test.ts +0 -1111
  136. package/src/utils/accountLoaders.ts +0 -203
  137. package/src/utils/authHelpers.ts +0 -85
  138. package/src/utils/batch.ts +0 -18
  139. package/src/utils/buildOfferShelf.test.ts +0 -59
  140. package/src/utils/cartProjection.ts +0 -96
  141. package/src/utils/cookies.ts +0 -167
  142. package/src/utils/enrichment.ts +0 -556
  143. package/src/utils/fetch.ts +0 -111
  144. package/src/utils/fetchCache.ts +0 -55
  145. package/src/utils/index.ts +0 -19
  146. package/src/utils/instrumentedFetch.ts +0 -98
  147. package/src/utils/intelligentSearch.ts +0 -96
  148. package/src/utils/legacy.ts +0 -139
  149. package/src/utils/minicart.ts +0 -139
  150. package/src/utils/pickAndOmit.ts +0 -25
  151. package/src/utils/proxy.ts +0 -495
  152. package/src/utils/resilience.ts +0 -352
  153. package/src/utils/resourceRange.ts +0 -10
  154. package/src/utils/segment.ts +0 -152
  155. package/src/utils/similars.ts +0 -35
  156. package/src/utils/simulationCache.ts +0 -73
  157. package/src/utils/sitemap.ts +0 -283
  158. package/src/utils/slugCache.ts +0 -28
  159. package/src/utils/slugify.ts +0 -13
  160. package/src/utils/transform.ts +0 -1691
  161. package/src/utils/vtexId.ts +0 -151
  162. package/src/vtexClient.test.ts +0 -204
  163. package/tsconfig.json +0 -7
@@ -1,427 +0,0 @@
1
- /**
2
- * Cart v2 factory — modular, granular, framework-agnostic client hooks.
3
- *
4
- * Built on the same module-singleton + listener pattern as `createUseCart`
5
- * (no `@tanstack/react-query` required, works identically under Next.js and
6
- * TanStack Start), but redesigned around the Cart v2 goals:
7
- *
8
- * - **Lazy**: nothing hits VTEX on mount. No OrderForm is created until the
9
- * first add-to-cart. The badge shows 0 (or the reconciled count) until then.
10
- * - **Granular**: separate hooks per concern (`useCartSummary` for the badge,
11
- * `useCart` for the drawer, `useShipping`, `useGifts`) so a component pulls
12
- * only what it renders.
13
- * - **Minimal by default + optimistic**: `useAddToCart` bumps the local count
14
- * immediately and reconciles from the server's projected response. The
15
- * optimistic + reconciliation logic lives here so the storefront never
16
- * reimplements it.
17
- *
18
- * Injection: pass your site's `invoke` (the generated server-function proxy).
19
- * The `CreateCartInvoke` interface declares only the v2 methods this factory
20
- * calls — a structural subset, same as `CreateUseCartInvoke`.
21
- *
22
- * @example
23
- * ```ts
24
- * // src/hooks/cart.ts
25
- * import { createCart } from "@decocms/apps/vtex/hooks/createCart";
26
- * import { invoke } from "~/server/invoke";
27
- * export const { useCart, useCartSummary, useAddToCart } = createCart({ invoke });
28
- * ```
29
- */
30
-
31
- import type {
32
- CartProjection,
33
- CartSection,
34
- CartSummary,
35
- CartSummaryWithItems,
36
- Minicart,
37
- } from "@decocms/apps-commerce/types";
38
- import { useEffect, useState } from "react";
39
- import type { CartItemAttachments } from "../loaders/cart/attachments";
40
- import type { CartGifts } from "../loaders/cart/gifts";
41
- import type { CartShipping } from "../loaders/cart/shipping";
42
- import type { OrderForm } from "../types";
43
- import type { VtexCartProjectionResult } from "../utils/cartProjection";
44
-
45
- /** Structural subset of the invoke proxy this factory needs. */
46
- export interface CreateCartInvoke {
47
- vtex: {
48
- actions: {
49
- getOrCreateCartV2: (args: {
50
- data: { orderFormId?: string; projection?: CartProjection; sections?: CartSection[] };
51
- }) => Promise<unknown>;
52
- addItemsToCartV2: (args: {
53
- data: {
54
- orderFormId: string;
55
- orderItems: Array<{ id: string; seller: string; quantity: number }>;
56
- projection?: CartProjection;
57
- sections?: CartSection[];
58
- };
59
- }) => Promise<unknown>;
60
- updateCartItemsV2: (args: {
61
- data: {
62
- orderFormId: string;
63
- orderItems: Array<{ index: number; quantity: number }>;
64
- projection?: CartProjection;
65
- sections?: CartSection[];
66
- };
67
- }) => Promise<unknown>;
68
- addCouponToCartV2: (args: {
69
- data: {
70
- orderFormId: string;
71
- text: string;
72
- projection?: CartProjection;
73
- sections?: CartSection[];
74
- };
75
- }) => Promise<unknown>;
76
- };
77
- loaders: {
78
- cart: {
79
- summary: (args: { data?: { orderFormId?: string } }) => Promise<CartSummary>;
80
- full: (args: {
81
- data?: {
82
- orderFormId?: string;
83
- freeShippingTarget?: number;
84
- locale?: string;
85
- checkoutHref?: string;
86
- enableCoupon?: boolean;
87
- };
88
- }) => Promise<Minicart<OrderForm | null>>;
89
- shipping: (args: {
90
- data: {
91
- items: Array<{ id: string | number; quantity: number; seller: string }>;
92
- postalCode: string;
93
- country?: string;
94
- };
95
- }) => Promise<CartShipping>;
96
- gifts: (args: { data?: { orderFormId?: string } }) => Promise<CartGifts>;
97
- attachments: (args: {
98
- data: { orderFormId?: string; itemIndex: number };
99
- }) => Promise<CartItemAttachments>;
100
- };
101
- };
102
- };
103
- }
104
-
105
- export interface CreateCartOptions {
106
- invoke: CreateCartInvoke;
107
- /** Override the orderFormId cookie name. Default: VTEX standard. */
108
- orderFormCookieName?: string;
109
- /** Override the cookie max-age in seconds. Default: 7 days. */
110
- orderFormCookieMaxAge?: number;
111
- }
112
-
113
- const EMPTY_SUMMARY: CartSummary = { orderFormId: null, totalItems: 0, total: 0 };
114
-
115
- export interface AddToCartOptions {
116
- /** What the server should return. Default: `"summary+items"`. */
117
- projection?: CartProjection;
118
- sections?: CartSection[];
119
- }
120
-
121
- export interface UseCartInclude {
122
- /** Fetch the full minicart (drawer). Default: false. */
123
- full?: boolean;
124
- }
125
-
126
- export interface UseCartV2Options {
127
- include?: UseCartInclude;
128
- freeShippingTarget?: number;
129
- locale?: string;
130
- checkoutHref?: string;
131
- enableCoupon?: boolean;
132
- }
133
-
134
- /** Build a per-site set of Cart v2 hooks. */
135
- export function createCart(opts: CreateCartOptions) {
136
- const { invoke } = opts;
137
- const COOKIE_NAME = opts.orderFormCookieName ?? "checkout.vtex.com__orderFormId";
138
- const COOKIE_MAX_AGE = opts.orderFormCookieMaxAge ?? 7 * 24 * 3600;
139
-
140
- // --- module-singleton state --------------------------------------------
141
- let _summary: CartSummary = EMPTY_SUMMARY;
142
- let _minicart: Minicart<OrderForm | null> | null = null;
143
- let _loading = false;
144
- const _listeners = new Set<() => void>();
145
-
146
- function notify() {
147
- for (const fn of _listeners) fn();
148
- }
149
- function setSummary(s: CartSummary) {
150
- _summary = s;
151
- notify();
152
- }
153
- function setMinicart(m: Minicart<OrderForm | null> | null) {
154
- _minicart = m;
155
- if (m) {
156
- // Keep the badge in sync whenever the full cart is loaded.
157
- _summary = {
158
- orderFormId: m.original?.orderFormId ?? _summary.orderFormId,
159
- totalItems: m.storefront.items.reduce((n, i) => n + (i.quantity ?? 0), 0),
160
- total: m.storefront.total,
161
- };
162
- }
163
- notify();
164
- }
165
- function setLoading(v: boolean) {
166
- _loading = v;
167
- notify();
168
- }
169
-
170
- // --- cookie helpers ----------------------------------------------------
171
- function escapeRegex(s: string): string {
172
- return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
173
- }
174
- function getOrderFormIdFromCookie(): string | null {
175
- if (typeof document === "undefined") return null;
176
- const re = new RegExp(`${escapeRegex(COOKIE_NAME)}=([^;]*)`);
177
- const match = document.cookie.match(re);
178
- return match ? decodeURIComponent(match[1]) : null;
179
- }
180
- function setOrderFormIdCookie(id: string) {
181
- if (typeof document === "undefined") return;
182
- // biome-ignore lint/suspicious/noDocumentCookie: the orderFormId cookie is intentionally client-readable (VTEX standard, mirrored by createUseCart).
183
- document.cookie = `${COOKIE_NAME}=${encodeURIComponent(id)}; path=/; max-age=${COOKIE_MAX_AGE}; SameSite=Lax`;
184
- }
185
-
186
- /**
187
- * Ensure an OrderForm exists. Only called from mutations — never on mount —
188
- * so a browsing-only visitor provisions no cart. If the cookie has an id we
189
- * trust it; otherwise we create one (projection "summary" — we only need the
190
- * id + count back).
191
- */
192
- async function ensureOrderFormId(): Promise<string> {
193
- const existing = _summary.orderFormId ?? getOrderFormIdFromCookie();
194
- if (existing) {
195
- _summary = { ..._summary, orderFormId: existing };
196
- return existing;
197
- }
198
- const created = (await invoke.vtex.actions.getOrCreateCartV2({
199
- data: { projection: "summary" },
200
- })) as CartSummary;
201
- if (created.orderFormId) setOrderFormIdCookie(created.orderFormId);
202
- setSummary(created);
203
- return created.orderFormId ?? "";
204
- }
205
-
206
- /** Reconcile local state from a projected mutation response. */
207
- function reconcile(result: unknown, projection: CartProjection) {
208
- if (projection === "none") return; // optimistic-only; nothing to reconcile
209
- if (projection === "minicart") {
210
- setMinicart(result as Minicart<OrderForm | null>);
211
- return;
212
- }
213
- // "summary" | "summary+items" | "raw" all expose the totals we need.
214
- const r = result as Partial<CartSummaryWithItems> & { value?: number };
215
- if (r && typeof r.totalItems === "number") {
216
- setSummary({
217
- orderFormId: r.orderFormId ?? _summary.orderFormId,
218
- totalItems: r.totalItems,
219
- total: r.total ?? _summary.total,
220
- });
221
- }
222
- }
223
-
224
- // --- shared React subscription ----------------------------------------
225
- function useCartState() {
226
- const [, forceRender] = useState(0);
227
- useEffect(() => {
228
- const listener = () => forceRender((n) => n + 1);
229
- _listeners.add(listener);
230
- return () => {
231
- _listeners.delete(listener);
232
- };
233
- }, []);
234
- }
235
-
236
- // --- hooks -------------------------------------------------------------
237
-
238
- /** Badge hook. Reads the local summary; never triggers a VTEX call by itself. */
239
- function useCartSummary() {
240
- useCartState();
241
- return { summary: _summary, totalItems: _summary.totalItems, loading: _loading };
242
- }
243
-
244
- /**
245
- * Add-to-cart with built-in optimistic count + reconciliation.
246
- * `projection: "none"` → pure 200, optimistic-only (no server data used).
247
- */
248
- function useAddToCart(hookOpts: AddToCartOptions = {}) {
249
- useCartState();
250
- const projection: CartProjection = hookOpts.projection ?? "summary+items";
251
-
252
- async function add(params: {
253
- id: string;
254
- seller: string;
255
- quantity?: number;
256
- }): Promise<VtexCartProjectionResult> {
257
- const qty = params.quantity ?? 1;
258
- // Optimistic: bump the badge immediately.
259
- setSummary({ ..._summary, totalItems: _summary.totalItems + qty });
260
- setLoading(true);
261
- try {
262
- const orderFormId = await ensureOrderFormId();
263
- const result = await invoke.vtex.actions.addItemsToCartV2({
264
- data: {
265
- orderFormId,
266
- orderItems: [{ id: params.id, seller: params.seller, quantity: qty }],
267
- projection,
268
- sections: hookOpts.sections,
269
- },
270
- });
271
- reconcile(result, projection);
272
- // Return the projected payload so callers can drive a toast / analytics
273
- // without a second fetch (e.g. `summary+items` → name/image/price/variant).
274
- return result as VtexCartProjectionResult;
275
- } catch (err) {
276
- // Roll back the optimistic bump on failure.
277
- setSummary({ ..._summary, totalItems: Math.max(0, _summary.totalItems - qty) });
278
- console.error("[cart] addToCart failed:", err);
279
- throw err;
280
- } finally {
281
- setLoading(false);
282
- }
283
- }
284
-
285
- return { add, loading: _loading };
286
- }
287
-
288
- /**
289
- * Composed cart hook for the drawer. Fetches ONLY what `include` enables —
290
- * default is nothing beyond the already-local summary. Call `openDrawer()`
291
- * (or pass `include.full`) to load the full minicart on demand.
292
- */
293
- function useCart(cartOpts: UseCartV2Options = {}) {
294
- useCartState();
295
- const wantFull = cartOpts.include?.full === true;
296
-
297
- // biome-ignore lint/correctness/useExhaustiveDependencies: the drawer loads once when enabled; storefront options are stable per-mount and must not re-trigger the fetch.
298
- useEffect(() => {
299
- if (!wantFull) return;
300
- let cancelled = false;
301
- setLoading(true);
302
- invoke.vtex.loaders.cart
303
- .full({
304
- data: {
305
- freeShippingTarget: cartOpts.freeShippingTarget,
306
- locale: cartOpts.locale,
307
- checkoutHref: cartOpts.checkoutHref,
308
- enableCoupon: cartOpts.enableCoupon,
309
- },
310
- })
311
- .then((m) => {
312
- if (!cancelled) setMinicart(m);
313
- })
314
- .catch((err) => console.error("[cart] load full failed:", err))
315
- .finally(() => {
316
- if (!cancelled) setLoading(false);
317
- });
318
- return () => {
319
- cancelled = true;
320
- };
321
- }, [wantFull]);
322
-
323
- async function refresh() {
324
- const m = await invoke.vtex.loaders.cart.full({
325
- data: {
326
- freeShippingTarget: cartOpts.freeShippingTarget,
327
- locale: cartOpts.locale,
328
- checkoutHref: cartOpts.checkoutHref,
329
- enableCoupon: cartOpts.enableCoupon,
330
- },
331
- });
332
- setMinicart(m);
333
- return m;
334
- }
335
-
336
- async function updateQuantity(index: number, quantity: number) {
337
- const orderFormId = await ensureOrderFormId();
338
- setLoading(true);
339
- try {
340
- const result = await invoke.vtex.actions.updateCartItemsV2({
341
- data: { orderFormId, orderItems: [{ index, quantity }], projection: "minicart" },
342
- });
343
- reconcile(result, "minicart");
344
- return result as Minicart<OrderForm | null>;
345
- } finally {
346
- setLoading(false);
347
- }
348
- }
349
-
350
- async function removeItem(index: number) {
351
- return updateQuantity(index, 0);
352
- }
353
-
354
- async function addCoupon(text: string) {
355
- const orderFormId = await ensureOrderFormId();
356
- setLoading(true);
357
- try {
358
- const result = await invoke.vtex.actions.addCouponToCartV2({
359
- data: { orderFormId, text, projection: "minicart" },
360
- });
361
- reconcile(result, "minicart");
362
- return result as Minicart<OrderForm | null>;
363
- } finally {
364
- setLoading(false);
365
- }
366
- }
367
-
368
- return {
369
- minicart: _minicart,
370
- summary: _summary,
371
- loading: _loading,
372
- refresh,
373
- updateQuantity,
374
- removeItem,
375
- addCoupon,
376
- };
377
- }
378
-
379
- /** On-demand shipping estimate for the drawer. Not cached (see loader note). */
380
- function useShipping() {
381
- useCartState();
382
- async function estimate(params: {
383
- items: Array<{ id: string | number; quantity: number; seller: string }>;
384
- postalCode: string;
385
- country?: string;
386
- }) {
387
- return invoke.vtex.loaders.cart.shipping({ data: params });
388
- }
389
- return { estimate };
390
- }
391
-
392
- /** On-demand selectable-gifts / promotions read. */
393
- function useGifts() {
394
- useCartState();
395
- async function load() {
396
- return invoke.vtex.loaders.cart.gifts({ data: {} });
397
- }
398
- return { load };
399
- }
400
-
401
- /** On-demand attachments/offerings read for a single line (engraving, gift-wrap…). */
402
- function useAttachments() {
403
- useCartState();
404
- async function load(itemIndex: number) {
405
- return invoke.vtex.loaders.cart.attachments({ data: { itemIndex } });
406
- }
407
- return { load };
408
- }
409
-
410
- /** Reset all module-level state (e.g. after logout / order placed). */
411
- function resetCart() {
412
- _summary = EMPTY_SUMMARY;
413
- _minicart = null;
414
- _loading = false;
415
- notify();
416
- }
417
-
418
- return {
419
- useCart,
420
- useCartSummary,
421
- useAddToCart,
422
- useShipping,
423
- useGifts,
424
- useAttachments,
425
- resetCart,
426
- };
427
- }