@decocms/apps-vtex 8.0.0 → 8.1.0-next.1

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 (133) hide show
  1. package/package.json +7 -52
  2. package/src/index.ts +12 -15
  3. package/src/utils/constants.ts +2 -56
  4. package/src/utils/cookieSanitizer.ts +59 -59
  5. package/src/utils/operationRouter.ts +76 -72
  6. package/src/utils/types.ts +709 -1557
  7. package/src/vtexClient.ts +444 -0
  8. package/src/README.md +0 -6
  9. package/src/__tests__/client-segment-cookie.test.ts +0 -255
  10. package/src/__tests__/client-set-cookie-forward.test.ts +0 -257
  11. package/src/__tests__/schemas.test.ts +0 -71
  12. package/src/actions/address.ts +0 -250
  13. package/src/actions/analytics/sendEvent.ts +0 -86
  14. package/src/actions/auth.ts +0 -333
  15. package/src/actions/checkout.ts +0 -659
  16. package/src/actions/index.ts +0 -11
  17. package/src/actions/masterData.ts +0 -168
  18. package/src/actions/misc.ts +0 -188
  19. package/src/actions/newsletter.ts +0 -105
  20. package/src/actions/orders.ts +0 -34
  21. package/src/actions/profile.ts +0 -201
  22. package/src/actions/session.ts +0 -85
  23. package/src/actions/trigger.ts +0 -43
  24. package/src/actions/wishlist.ts +0 -114
  25. package/src/client.ts +0 -667
  26. package/src/commerceLoaders.ts +0 -267
  27. package/src/hooks/__tests__/createCart.render.test.ts +0 -114
  28. package/src/hooks/__tests__/createCart.test.ts +0 -92
  29. package/src/hooks/__tests__/createUseCart.test.ts +0 -184
  30. package/src/hooks/__tests__/createUseUser.test.ts +0 -48
  31. package/src/hooks/__tests__/createUseWishlist.test.ts +0 -87
  32. package/src/hooks/cartQuery.ts +0 -204
  33. package/src/hooks/createCart.ts +0 -427
  34. package/src/hooks/createUseCart.ts +0 -360
  35. package/src/hooks/createUseUser.ts +0 -153
  36. package/src/hooks/createUseWishlist.ts +0 -242
  37. package/src/hooks/index.ts +0 -25
  38. package/src/hooks/useAutocomplete.ts +0 -83
  39. package/src/hooks/useCart.ts +0 -243
  40. package/src/hooks/useUser.ts +0 -78
  41. package/src/hooks/useWishlist.ts +0 -119
  42. package/src/invoke.ts +0 -235
  43. package/src/loaders/ProductDetailsPage.ts +0 -1
  44. package/src/loaders/ProductList.ts +0 -1
  45. package/src/loaders/ProductListingPage.ts +0 -1
  46. package/src/loaders/address.ts +0 -115
  47. package/src/loaders/autocomplete.ts +0 -58
  48. package/src/loaders/brands.ts +0 -44
  49. package/src/loaders/cart/attachments.ts +0 -53
  50. package/src/loaders/cart/full.ts +0 -67
  51. package/src/loaders/cart/gifts.ts +0 -43
  52. package/src/loaders/cart/orderFormId.ts +0 -31
  53. package/src/loaders/cart/shipping.test.ts +0 -125
  54. package/src/loaders/cart/shipping.ts +0 -136
  55. package/src/loaders/cart/summary.ts +0 -36
  56. package/src/loaders/cart.ts +0 -52
  57. package/src/loaders/catalog.ts +0 -163
  58. package/src/loaders/collections.ts +0 -55
  59. package/src/loaders/index.ts +0 -20
  60. package/src/loaders/intelligentSearch/__tests__/productListingPage.test.ts +0 -51
  61. package/src/loaders/intelligentSearch/productDetailsPage.ts +0 -113
  62. package/src/loaders/intelligentSearch/productList.ts +0 -154
  63. package/src/loaders/intelligentSearch/productListingPage.ts +0 -526
  64. package/src/loaders/intelligentSearch/suggestions.ts +0 -46
  65. package/src/loaders/legacy/productDetailsPage.ts +0 -1
  66. package/src/loaders/legacy/productList.ts +0 -1
  67. package/src/loaders/legacy/relatedProductsLoader.ts +0 -81
  68. package/src/loaders/legacy.ts +0 -635
  69. package/src/loaders/logistics.ts +0 -111
  70. package/src/loaders/minicart.ts +0 -78
  71. package/src/loaders/navbar.ts +0 -26
  72. package/src/loaders/orders.ts +0 -92
  73. package/src/loaders/pageType.ts +0 -68
  74. package/src/loaders/paths/PDPDefaultPath.ts +0 -51
  75. package/src/loaders/payment.ts +0 -97
  76. package/src/loaders/productListFull.ts +0 -159
  77. package/src/loaders/profile.ts +0 -138
  78. package/src/loaders/promotion.ts +0 -30
  79. package/src/loaders/search.ts +0 -124
  80. package/src/loaders/session.ts +0 -83
  81. package/src/loaders/user.ts +0 -87
  82. package/src/loaders/wishlist.ts +0 -89
  83. package/src/loaders/wishlistProducts.ts +0 -69
  84. package/src/loaders/workflow/products.ts +0 -64
  85. package/src/loaders/workflow.ts +0 -316
  86. package/src/logo.png +0 -0
  87. package/src/manifest.gen.ts +0 -89
  88. package/src/middleware.ts +0 -240
  89. package/src/mod.ts +0 -157
  90. package/src/registry.ts +0 -9
  91. package/src/schemas.gen.ts +0 -3191
  92. package/src/schemas.ts +0 -30
  93. package/src/types.ts +0 -248
  94. package/src/utils/__tests__/cartProjection.test.ts +0 -118
  95. package/src/utils/__tests__/cookieSanitizer.test.ts +0 -162
  96. package/src/utils/__tests__/fetch.test.ts +0 -80
  97. package/src/utils/__tests__/fetchCache.test.ts +0 -155
  98. package/src/utils/__tests__/instrumentedFetch.test.ts +0 -158
  99. package/src/utils/__tests__/intelligentSearch.test.ts +0 -88
  100. package/src/utils/__tests__/minicart.test.ts +0 -184
  101. package/src/utils/__tests__/operationRouter.test.ts +0 -227
  102. package/src/utils/__tests__/resilience.test.ts +0 -205
  103. package/src/utils/__tests__/resourceRange.test.ts +0 -32
  104. package/src/utils/__tests__/simulationCache.test.ts +0 -40
  105. package/src/utils/__tests__/sitemap.test.ts +0 -185
  106. package/src/utils/__tests__/slugify.test.ts +0 -31
  107. package/src/utils/__tests__/transform.test.ts +0 -769
  108. package/src/utils/accountLoaders.ts +0 -203
  109. package/src/utils/authHelpers.ts +0 -85
  110. package/src/utils/batch.ts +0 -18
  111. package/src/utils/cartProjection.ts +0 -96
  112. package/src/utils/cookies.ts +0 -167
  113. package/src/utils/enrichment.ts +0 -560
  114. package/src/utils/fetch.ts +0 -107
  115. package/src/utils/fetchCache.ts +0 -199
  116. package/src/utils/index.ts +0 -19
  117. package/src/utils/instrumentedFetch.ts +0 -97
  118. package/src/utils/intelligentSearch.ts +0 -96
  119. package/src/utils/legacy.ts +0 -139
  120. package/src/utils/minicart.ts +0 -139
  121. package/src/utils/pickAndOmit.ts +0 -25
  122. package/src/utils/proxy.ts +0 -435
  123. package/src/utils/resilience.ts +0 -352
  124. package/src/utils/resourceRange.ts +0 -10
  125. package/src/utils/segment.ts +0 -152
  126. package/src/utils/similars.ts +0 -37
  127. package/src/utils/simulationCache.ts +0 -73
  128. package/src/utils/sitemap.ts +0 -282
  129. package/src/utils/slugCache.ts +0 -28
  130. package/src/utils/slugify.ts +0 -13
  131. package/src/utils/transform.ts +0 -1522
  132. package/src/utils/vtexId.ts +0 -138
  133. package/tsconfig.json +0 -7
@@ -1,55 +0,0 @@
1
- /**
2
- * VTEX Collections loader.
3
- * Pure async function — requires configureVtex() to have been called.
4
- *
5
- * Ported from deco-cx/apps:
6
- * vtex/loaders/collections/list.ts
7
- *
8
- * @see https://developers.vtex.com/docs/api-reference/catalog-api#get-/api/catalog_system/pvt/collection/search
9
- */
10
- import { vtexFetch } from "../client";
11
- import type { CollectionList } from "../utils/types";
12
-
13
- export interface CollectionOption {
14
- value: string;
15
- label: string;
16
- }
17
-
18
- /**
19
- * Fetch collections, optionally filtering by search term.
20
- *
21
- * Without a term returns up to 3 000 collections; with a term
22
- * returns the first 15 matches. Results are mapped to a simple
23
- * `{ value, label }` list suitable for dropdowns / selectors.
24
- *
25
- * Note: uses the **pvt** (private) endpoint — requires appKey/appToken.
26
- */
27
- export async function getCollections(term?: string): Promise<CollectionOption[]> {
28
- const params = new URLSearchParams();
29
-
30
- if (term) {
31
- params.set("page", "1");
32
- params.set("pageSize", "15");
33
- const list = await vtexFetch<CollectionList>(
34
- `/api/catalog_system/pvt/collection/search/${encodeURIComponent(term)}?${params}`,
35
- );
36
- return mapToOptions(list);
37
- }
38
-
39
- params.set("page", "1");
40
- params.set("pageSize", "3000");
41
- params.set("orderByAsc", "false");
42
- const list = await vtexFetch<CollectionList>(
43
- `/api/catalog_system/pvt/collection/search?${params}`,
44
- );
45
- return mapToOptions(list);
46
- }
47
-
48
- function mapToOptions(list: CollectionList): CollectionOption[] {
49
- return (
50
- list.items?.map((c) => ({
51
- value: `${c.id}`,
52
- label: `${c.id} - ${c.name}`,
53
- })) ?? []
54
- );
55
- }
@@ -1,20 +0,0 @@
1
- export * from "./address";
2
- export * from "./brands";
3
- export * from "./cart";
4
- export * from "./cart/shipping";
5
- export * from "./catalog";
6
- export * from "./collections";
7
- export * from "./legacy";
8
- export * from "./logistics";
9
- export * from "./navbar";
10
- export * from "./orders";
11
- export * from "./pageType";
12
- export * from "./payment";
13
- export * from "./profile";
14
- export * from "./promotion";
15
- export * from "./search";
16
- export * from "./session";
17
- export * from "./user";
18
- export * from "./wishlist";
19
- export * from "./wishlistProducts";
20
- export * from "./workflow";
@@ -1,51 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { mapLabelledFuzzyToFuzzy, resolvePage } from "../productListingPage";
3
-
4
- describe("mapLabelledFuzzyToFuzzy", () => {
5
- it("translates 'automatic' to 'auto'", () => {
6
- expect(mapLabelledFuzzyToFuzzy("automatic")).toBe("auto");
7
- });
8
-
9
- it("translates 'enabled' to '1'", () => {
10
- expect(mapLabelledFuzzyToFuzzy("enabled")).toBe("1");
11
- });
12
-
13
- it("translates 'disabled' to '0'", () => {
14
- expect(mapLabelledFuzzyToFuzzy("disabled")).toBe("0");
15
- });
16
-
17
- it("returns undefined for missing label", () => {
18
- expect(mapLabelledFuzzyToFuzzy(undefined)).toBeUndefined();
19
- });
20
- });
21
-
22
- describe("resolvePage (#391)", () => {
23
- it("defaults to page 0 with no props.page and no URL page", () => {
24
- expect(resolvePage(undefined, undefined)).toBe(0);
25
- });
26
-
27
- it("converts a 1-indexed URL ?page= to the 0-indexed internal page", () => {
28
- expect(resolvePage(undefined, "3")).toBe(2);
29
- });
30
-
31
- it("uses props.page directly (already 0-indexed) over the URL", () => {
32
- expect(resolvePage(5, "3")).toBe(5);
33
- });
34
-
35
- it("coerces a string props.page instead of silently falling back to 0", () => {
36
- expect(resolvePage("3", undefined)).toBe(3);
37
- });
38
-
39
- it("falls through to the URL page when props.page is a non-finite string", () => {
40
- expect(resolvePage("not-a-number", "3")).toBe(2);
41
- });
42
-
43
- it("resets a malformed ?page= to 0 instead of propagating NaN", () => {
44
- expect(resolvePage(undefined, "abc")).toBe(0);
45
- });
46
-
47
- it("floors a fractional page and never returns a negative page", () => {
48
- expect(resolvePage(2.7, undefined)).toBe(2);
49
- expect(resolvePage(-1, undefined)).toBe(0);
50
- });
51
- });
@@ -1,113 +0,0 @@
1
- /**
2
- * PDP loader using Legacy Catalog API + shared transform pipeline.
3
- * Maps VTEX catalog response to schema.org ProductDetailsPage
4
- * following the same pattern as deco-cx/apps.
5
- */
6
-
7
- import type { ProductDetailsPage } from "@decocms/apps-commerce/types";
8
- import { getVtexConfig, vtexCachedFetch } from "../../client";
9
- import PDPDefaultPath from "../paths/PDPDefaultPath";
10
- import { searchBySlug } from "../../utils/slugCache";
11
- import { pickSku, toProductPage } from "../../utils/transform";
12
- import type { LegacyProduct } from "../../utils/types";
13
-
14
- export interface PDPProps {
15
- slug?: string;
16
- skuId?: string;
17
- /** When true, PDP pages with ?skuId remain indexable */
18
- indexingSkus?: boolean;
19
- /** Use product.description instead of metaTagDescription for SEO */
20
- preferDescription?: boolean;
21
- /**
22
- * Use lean variant transform for hasVariant[]. Defaults to false on PDPs:
23
- * variant selectors need image[] and real inventoryLevel to render thumbnails
24
- * and per-SKU stock state, so a full toProduct(level=1) is the safe default.
25
- * Opt-in only if payload size becomes a problem.
26
- */
27
- leanVariants?: boolean;
28
- /** When leanVariants is true, still include image[0] on each variant. Default true. */
29
- variantIncludeImage?: boolean;
30
- /** When leanVariants is true, still include inventoryLevel on each variant. Default true. */
31
- variantIncludeInventory?: boolean;
32
- }
33
-
34
- export default async function vtexProductDetailsPage(
35
- props: PDPProps,
36
- ): Promise<ProductDetailsPage | null> {
37
- const {
38
- slug,
39
- skuId,
40
- indexingSkus,
41
- preferDescription,
42
- leanVariants = false,
43
- variantIncludeImage = true,
44
- variantIncludeInventory = true,
45
- } = props;
46
-
47
- try {
48
- // Only the admin hits the PDP at its raw route pattern (`/:slug/p`), so the
49
- // `slug` route-param resolves to the literal placeholder `:slug` — there's
50
- // no real product in the URL, so render the best seller as a preview.
51
- //
52
- // This is NOT a general fallback: a concrete slug that resolves to no
53
- // product (e.g. `/dssadals/p`) must still 404 like any missing product, and
54
- // a genuinely absent slug must NOT pull in an unrelated product either. So
55
- // we trigger ONLY on the `:`-prefixed placeholder, never on empty/missing.
56
- // Mirrors deco-cx/apps' PDPDefaultPath behavior.
57
- let effectiveSlug = slug;
58
-
59
- if (slug?.startsWith(":")) {
60
- const defaultPaths = await PDPDefaultPath({ count: 1 });
61
- effectiveSlug = defaultPaths?.possiblePaths[0];
62
- }
63
-
64
- if (!effectiveSlug) return null;
65
-
66
- const linkText = effectiveSlug.replace(/\/p$/, "").replace(/^\//, "").toLowerCase();
67
- const config = getVtexConfig();
68
- const sc = config.salesChannel;
69
-
70
- const products = await searchBySlug(linkText);
71
-
72
- if (!products || products.length === 0) {
73
- return null;
74
- }
75
-
76
- const product = products[0];
77
- const baseUrl = config.publicUrl
78
- ? `https://${config.publicUrl}`
79
- : `https://${config.account}.vtexcommercestable.${config.domain ?? "com.br"}`;
80
-
81
- const sku = pickSku(product, skuId);
82
-
83
- const kitItems: LegacyProduct[] =
84
- Array.isArray(sku.kitItems) && sku.kitItems.length > 0
85
- ? ((await vtexCachedFetch<LegacyProduct[]>(
86
- `/api/catalog_system/pub/products/search/?fq=${sku.kitItems.map((item: any) => `skuId:${item.itemId}`).join("&fq=")}&_from=0&_to=49${sc ? `&sc=${sc}` : ""}`,
87
- )) ?? [])
88
- : [];
89
-
90
- const page = toProductPage(product, sku, kitItems, {
91
- baseUrl,
92
- priceCurrency: "BRL",
93
- leanVariants,
94
- variantIncludeImage,
95
- variantIncludeInventory,
96
- });
97
-
98
- return {
99
- ...page,
100
- seo: {
101
- title: product.productTitle || product.productName,
102
- description: preferDescription
103
- ? product.description
104
- : product.metaTagDescription || product.description?.substring(0, 160) || "",
105
- canonical: `/${product.linkText}/p`,
106
- noIndexing: indexingSkus ? false : !!skuId,
107
- },
108
- };
109
- } catch (error) {
110
- console.error("[VTEX] PDP error:", error);
111
- return null;
112
- }
113
- }
@@ -1,154 +0,0 @@
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 "@decocms/apps-commerce/types";
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
- }
17
-
18
- interface CollectionProps {
19
- collection: string;
20
- count?: number;
21
- sort?: string;
22
- hideUnavailableItems?: boolean;
23
- }
24
-
25
- interface QueryProps {
26
- query: string;
27
- count?: number;
28
- sort?: string;
29
- fuzzy?: string;
30
- hideUnavailableItems?: boolean;
31
- }
32
-
33
- interface ProductIDProps {
34
- ids: string[];
35
- hideUnavailableItems?: boolean;
36
- }
37
-
38
- interface FacetsProps {
39
- query?: string;
40
- facets: string;
41
- count?: number;
42
- sort?: string;
43
- hideUnavailableItems?: boolean;
44
- }
45
-
46
- function isCollectionProps(p: any): p is CollectionProps {
47
- return typeof p?.collection === "string";
48
- }
49
- function isProductIDProps(p: any): p is ProductIDProps {
50
- return Array.isArray(p?.ids) && p.ids.length > 0;
51
- }
52
- function isFacetsProps(p: any): p is FacetsProps {
53
- return typeof p?.facets === "string";
54
- }
55
-
56
- function resolveParams(props: ProductListProps): {
57
- query: string;
58
- count: number;
59
- sort: string;
60
- facetPath: string;
61
- fuzzy?: string;
62
- hideUnavailableItems: boolean;
63
- ids?: string[];
64
- } {
65
- const inner = props.props ?? props;
66
-
67
- if (isProductIDProps(inner)) {
68
- return {
69
- query: `sku:${inner.ids.join(";")}`,
70
- count: inner.ids.length,
71
- sort: "",
72
- facetPath: "",
73
- hideUnavailableItems: inner.hideUnavailableItems ?? false,
74
- ids: inner.ids,
75
- };
76
- }
77
-
78
- if (isFacetsProps(inner)) {
79
- return {
80
- query: inner.query ?? "",
81
- count: inner.count ?? 12,
82
- sort: inner.sort ?? "",
83
- facetPath: inner.facets,
84
- hideUnavailableItems: inner.hideUnavailableItems ?? false,
85
- };
86
- }
87
-
88
- if (isCollectionProps(inner)) {
89
- return {
90
- query: "",
91
- count: inner.count ?? 12,
92
- sort: inner.sort ?? "",
93
- facetPath: toFacetPath([{ key: "productClusterIds", value: inner.collection }]),
94
- hideUnavailableItems: inner.hideUnavailableItems ?? false,
95
- };
96
- }
97
-
98
- return {
99
- query: (inner as any).query ?? "",
100
- count: (inner as any).count ?? 12,
101
- sort: (inner as any).sort ?? "",
102
- facetPath: "",
103
- fuzzy: (inner as any).fuzzy,
104
- hideUnavailableItems: (inner as any).hideUnavailableItems ?? false,
105
- };
106
- }
107
-
108
- export default async function vtexProductListShelf(
109
- props: ProductListProps,
110
- ): Promise<Product[] | null> {
111
- try {
112
- const { query, count, sort, facetPath, fuzzy, hideUnavailableItems, ids } =
113
- resolveParams(props);
114
-
115
- const config = getVtexConfig();
116
- const locale = config.locale ?? "pt-BR";
117
-
118
- const params: Record<string, string> = {
119
- page: "1",
120
- count: String(count),
121
- locale,
122
- hideUnavailableItems: String(hideUnavailableItems),
123
- };
124
- if (query) params.query = query;
125
- if (sort) params.sort = sort;
126
- if (fuzzy) params.fuzzy = fuzzy;
127
-
128
- const endpoint = facetPath ? `/product_search/${facetPath}` : "/product_search/";
129
-
130
- const data = await intelligentSearch<{ products: ProductVTEX[] }>(endpoint, params);
131
-
132
- const vtexProducts = data.products ?? [];
133
- const baseUrl = config.publicUrl
134
- ? `https://${config.publicUrl}`
135
- : `https://${config.account}.vtexcommercestable.${config.domain ?? "com.br"}`;
136
-
137
- let products = vtexProducts.map((p) => {
138
- const fetchedSkus = ids ? new Set(ids) : null;
139
- const preferredSku = fetchedSkus
140
- ? (p.items.find((item) => fetchedSkus.has(item.itemId)) ?? pickSku(p))
141
- : pickSku(p);
142
- return toProductShelf(p, preferredSku, 0, { baseUrl, priceCurrency: "BRL" });
143
- });
144
-
145
- if (ids) {
146
- products = sortProducts(products, ids, "sku");
147
- }
148
-
149
- return products;
150
- } catch (error) {
151
- console.error("[VTEX] ProductListShelf error:", error);
152
- return null;
153
- }
154
- }