@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
@@ -9,10 +9,10 @@
9
9
  import { getVtexConfig, vtexFetchResponse, vtexHost } from "../client";
10
10
 
11
11
  export interface SitemapEntry {
12
- loc: string;
13
- lastmod?: string;
14
- changefreq?: "always" | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | "never";
15
- priority?: number;
12
+ loc: string;
13
+ lastmod?: string;
14
+ changefreq?: "always" | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | "never";
15
+ priority?: number;
16
16
  }
17
17
 
18
18
  /**
@@ -28,106 +28,106 @@ export interface SitemapEntry {
28
28
  * @param options.rewriteHost - Whether to rewrite VTEX hostnames to the storefront origin (default: true)
29
29
  */
30
30
  export async function getVtexSitemapEntries(
31
- origin: string,
32
- options?: {
33
- maxDepth?: number;
34
- rewriteHost?: boolean;
35
- includeBrands?: boolean;
36
- includeCategories?: boolean;
37
- includeProducts?: boolean;
38
- },
31
+ origin: string,
32
+ options?: {
33
+ maxDepth?: number;
34
+ rewriteHost?: boolean;
35
+ includeBrands?: boolean;
36
+ includeCategories?: boolean;
37
+ includeProducts?: boolean;
38
+ },
39
39
  ): Promise<SitemapEntry[]> {
40
- const config = getVtexConfig();
41
- const vtexSitemapHost = vtexHost("vtexcommercestable", config);
42
- const rewrite = options?.rewriteHost !== false;
43
- const includeProducts = options?.includeProducts !== false;
44
- const includeCategories = options?.includeCategories !== false;
45
- const includeBrands = options?.includeBrands !== false;
40
+ const config = getVtexConfig();
41
+ const vtexSitemapHost = vtexHost("vtexcommercestable", config);
42
+ const rewrite = options?.rewriteHost !== false;
43
+ const includeProducts = options?.includeProducts !== false;
44
+ const includeCategories = options?.includeCategories !== false;
45
+ const includeBrands = options?.includeBrands !== false;
46
46
 
47
- try {
48
- const mainSitemapUrl = `https://${vtexSitemapHost}/sitemap.xml`;
49
- const mainResponse = await vtexFetchResponse(mainSitemapUrl);
50
- const mainXml = await mainResponse.text();
47
+ try {
48
+ const mainSitemapUrl = `https://${vtexSitemapHost}/sitemap.xml`;
49
+ const mainResponse = await vtexFetchResponse(mainSitemapUrl);
50
+ const mainXml = await mainResponse.text();
51
51
 
52
- const subSitemapUrls = extractLocs(mainXml);
53
- const entries: SitemapEntry[] = [];
52
+ const subSitemapUrls = extractLocs(mainXml);
53
+ const entries: SitemapEntry[] = [];
54
54
 
55
- const filteredUrls = subSitemapUrls.filter((url) => {
56
- const lower = url.toLowerCase();
57
- if (!includeProducts && lower.includes("product")) return false;
58
- if (!includeCategories && lower.includes("categor")) return false;
59
- if (!includeBrands && lower.includes("brand")) return false;
60
- return true;
61
- });
55
+ const filteredUrls = subSitemapUrls.filter((url) => {
56
+ const lower = url.toLowerCase();
57
+ if (!includeProducts && lower.includes("product")) return false;
58
+ if (!includeCategories && lower.includes("categor")) return false;
59
+ if (!includeBrands && lower.includes("brand")) return false;
60
+ return true;
61
+ });
62
62
 
63
- const maxDepth = options?.maxDepth ?? 1;
64
- if (maxDepth < 1) {
65
- return filteredUrls.map((url) => ({
66
- loc: rewrite ? rewriteUrl(url, vtexSitemapHost, origin) : url,
67
- changefreq: "daily" as const,
68
- priority: 0.5,
69
- }));
70
- }
63
+ const maxDepth = options?.maxDepth ?? 1;
64
+ if (maxDepth < 1) {
65
+ return filteredUrls.map((url) => ({
66
+ loc: rewrite ? rewriteUrl(url, vtexSitemapHost, origin) : url,
67
+ changefreq: "daily" as const,
68
+ priority: 0.5,
69
+ }));
70
+ }
71
71
 
72
- const settled = await Promise.allSettled(
73
- filteredUrls.map(async (subUrl) => {
74
- try {
75
- const resp = await vtexFetchResponse(subUrl);
76
- const xml = await resp.text();
77
- return extractLocs(xml);
78
- } catch {
79
- return [];
80
- }
81
- }),
82
- );
72
+ const settled = await Promise.allSettled(
73
+ filteredUrls.map(async (subUrl) => {
74
+ try {
75
+ const resp = await vtexFetchResponse(subUrl);
76
+ const xml = await resp.text();
77
+ return extractLocs(xml);
78
+ } catch {
79
+ return [];
80
+ }
81
+ }),
82
+ );
83
83
 
84
- const today = new Date().toISOString().split("T")[0];
84
+ const today = new Date().toISOString().split("T")[0];
85
85
 
86
- for (const result of settled) {
87
- if (result.status !== "fulfilled") continue;
88
- for (const loc of result.value) {
89
- entries.push({
90
- loc: rewrite ? rewriteUrl(loc, vtexSitemapHost, origin) : loc,
91
- lastmod: today,
92
- changefreq: "daily",
93
- priority: 0.5,
94
- });
95
- }
96
- }
86
+ for (const result of settled) {
87
+ if (result.status !== "fulfilled") continue;
88
+ for (const loc of result.value) {
89
+ entries.push({
90
+ loc: rewrite ? rewriteUrl(loc, vtexSitemapHost, origin) : loc,
91
+ lastmod: today,
92
+ changefreq: "daily",
93
+ priority: 0.5,
94
+ });
95
+ }
96
+ }
97
97
 
98
- return entries;
99
- } catch (error) {
100
- console.error("[VTEX Sitemap] Failed to fetch VTEX sitemap:", error);
101
- return [];
102
- }
98
+ return entries;
99
+ } catch (error) {
100
+ console.error("[VTEX Sitemap] Failed to fetch VTEX sitemap:", error);
101
+ return [];
102
+ }
103
103
  }
104
104
 
105
105
  function extractLocs(xml: string): string[] {
106
- const locs: string[] = [];
107
- const regex = /<loc>\s*(.*?)\s*<\/loc>/g;
108
- let match: RegExpExecArray | null;
109
- while ((match = regex.exec(xml)) !== null) {
110
- if (match[1]) locs.push(match[1].trim());
111
- }
112
- return locs;
106
+ const locs: string[] = [];
107
+ const regex = /<loc>\s*(.*?)\s*<\/loc>/g;
108
+ let match: RegExpExecArray | null;
109
+ while ((match = regex.exec(xml)) !== null) {
110
+ if (match[1]) locs.push(match[1].trim());
111
+ }
112
+ return locs;
113
113
  }
114
114
 
115
115
  function rewriteUrl(url: string, vtexSitemapHost: string, origin: string): string {
116
- try {
117
- const parsed = new URL(url);
118
- const originParsed = new URL(origin);
119
- const config = getVtexConfig();
120
- const domain = config.domain ?? "com.br";
121
- if (
122
- parsed.hostname === vtexSitemapHost ||
123
- parsed.hostname.endsWith(`.vtexcommercestable.${domain}`)
124
- ) {
125
- parsed.protocol = originParsed.protocol;
126
- parsed.hostname = originParsed.hostname;
127
- parsed.port = originParsed.port;
128
- }
129
- return parsed.toString();
130
- } catch {
131
- return url.replace(`https://${vtexSitemapHost}`, origin);
132
- }
116
+ try {
117
+ const parsed = new URL(url);
118
+ const originParsed = new URL(origin);
119
+ const config = getVtexConfig();
120
+ const domain = config.domain ?? "com.br";
121
+ if (
122
+ parsed.hostname === vtexSitemapHost ||
123
+ parsed.hostname.endsWith(`.vtexcommercestable.${domain}`)
124
+ ) {
125
+ parsed.protocol = originParsed.protocol;
126
+ parsed.hostname = originParsed.hostname;
127
+ parsed.port = originParsed.port;
128
+ }
129
+ return parsed.toString();
130
+ } catch {
131
+ return url.replace(`https://${vtexSitemapHost}`, origin);
132
+ }
133
133
  }
@@ -9,9 +9,7 @@
9
9
  import { getVtexConfig, vtexCachedFetch } from "../client";
10
10
  import type { LegacyProduct } from "./types";
11
11
 
12
- export function searchBySlug(
13
- linkText: string,
14
- ): Promise<LegacyProduct[] | null> {
12
+ export function searchBySlug(linkText: string): Promise<LegacyProduct[] | null> {
15
13
  const config = getVtexConfig();
16
14
  const sc = config.salesChannel;
17
15
  const scParam = sc ? `?sc=${sc}` : "";
@@ -24,9 +22,7 @@ export function searchBySlug(
24
22
  });
25
23
  }
26
24
 
27
- export async function resolveProductIdBySlug(
28
- linkText: string,
29
- ): Promise<string | null> {
25
+ export async function resolveProductIdBySlug(linkText: string): Promise<string | null> {
30
26
  const products = await searchBySlug(linkText);
31
27
  return products?.length ? products[0].productId : null;
32
28
  }
@@ -1,13 +1,13 @@
1
1
  const mapped = JSON.parse(
2
- `{"Á":"A","Ä":"A","Â":"A","À":"A","Ã":"A","Å":"A","Č":"C","Ç":"C","Ć":"C","Ď":"D","É":"E","Ě":"E","Ë":"E","È":"E","Ê":"E","Ẽ":"E","Ĕ":"E","Ȇ":"E","Í":"I","Ì":"I","Î":"I","Ï":"I","Ň":"N","Ñ":"N","Ó":"O","Ö":"O","Ò":"O","Ô":"O","Õ":"O","Ø":"O","Ř":"R","Ŕ":"R","Š":"S","Ť":"T","Ú":"U","Ů":"U","Ü":"U","Ù":"U","Û":"U","Ý":"Y","Ÿ":"Y","Ž":"Z","á":"a","ä":"a","â":"a","à":"a","ã":"a","å":"a","č":"c","ç":"c","ć":"c","ď":"d","é":"e","ě":"e","ë":"e","è":"e","ê":"e","ẽ":"e","ĕ":"e","ȇ":"e","í":"i","ì":"i","î":"i","ï":"i","ň":"n","ñ":"n","ó":"o","ö":"o","ò":"o","ô":"o","õ":"o","ø":"o","ð":"o","ř":"r","ŕ":"r","š":"s","ť":"t","ú":"u","ů":"u","ü":"u","ù":"u","û":"u","ý":"y","ÿ":"y","ž":"z","þ":"b","Þ":"B","Đ":"D","đ":"d","ß":"B","Æ":"A","a":"a"}`,
2
+ `{"Á":"A","Ä":"A","Â":"A","À":"A","Ã":"A","Å":"A","Č":"C","Ç":"C","Ć":"C","Ď":"D","É":"E","Ě":"E","Ë":"E","È":"E","Ê":"E","Ẽ":"E","Ĕ":"E","Ȇ":"E","Í":"I","Ì":"I","Î":"I","Ï":"I","Ň":"N","Ñ":"N","Ó":"O","Ö":"O","Ò":"O","Ô":"O","Õ":"O","Ø":"O","Ř":"R","Ŕ":"R","Š":"S","Ť":"T","Ú":"U","Ů":"U","Ü":"U","Ù":"U","Û":"U","Ý":"Y","Ÿ":"Y","Ž":"Z","á":"a","ä":"a","â":"a","à":"a","ã":"a","å":"a","č":"c","ç":"c","ć":"c","ď":"d","é":"e","ě":"e","ë":"e","è":"e","ê":"e","ẽ":"e","ĕ":"e","ȇ":"e","í":"i","ì":"i","î":"i","ï":"i","ň":"n","ñ":"n","ó":"o","ö":"o","ò":"o","ô":"o","õ":"o","ø":"o","ð":"o","ř":"r","ŕ":"r","š":"s","ť":"t","ú":"u","ů":"u","ü":"u","ù":"u","û":"u","ý":"y","ÿ":"y","ž":"z","þ":"b","Þ":"B","Đ":"D","đ":"d","ß":"B","Æ":"A","a":"a"}`,
3
3
  );
4
4
 
5
5
  export const slugify = (str: string) =>
6
- str
7
- .replace(/,/g, "")
8
- .replace(/[·/_,:]/g, "-")
9
- .replace(/[*+~.()'"!:@&\[\]`/ %$#?{}|><=_^]/g, "-")
10
- .split("")
11
- .map((char) => mapped[char] ?? char)
12
- .join("")
13
- .toLowerCase();
6
+ str
7
+ .replace(/,/g, "")
8
+ .replace(/[·/_,:]/g, "-")
9
+ .replace(/[*+~.()'"!:@&[\]`/ %$#?{}|><=_^]/g, "-")
10
+ .split("")
11
+ .map((char) => mapped[char] ?? char)
12
+ .join("")
13
+ .toLowerCase();