@decocms/apps 0.23.3 → 0.24.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.
- package/LICENSE +21 -0
- package/commerce/components/Image.tsx +129 -143
- package/commerce/components/JsonLd.tsx +192 -201
- package/commerce/components/Picture.tsx +65 -75
- package/commerce/sdk/analytics.ts +15 -15
- package/commerce/sdk/formatPrice.ts +13 -16
- package/commerce/sdk/url.ts +7 -7
- package/commerce/sdk/useOffer.ts +46 -57
- package/commerce/sdk/useVariantPossibilities.ts +25 -25
- package/commerce/types/commerce.ts +868 -875
- package/commerce/utils/canonical.ts +5 -8
- package/commerce/utils/constants.ts +5 -6
- package/commerce/utils/filters.ts +4 -4
- package/commerce/utils/productToAnalyticsItem.ts +52 -56
- package/commerce/utils/stateByZip.ts +42 -42
- package/package.json +23 -4
- package/shopify/actions/cart/addItems.ts +24 -25
- package/shopify/actions/cart/updateCoupons.ts +19 -20
- package/shopify/actions/cart/updateItems.ts +19 -20
- package/shopify/actions/user/signIn.ts +25 -30
- package/shopify/actions/user/signUp.ts +19 -24
- package/shopify/client.ts +24 -24
- package/shopify/index.ts +20 -18
- package/shopify/init.ts +18 -21
- package/shopify/loaders/ProductDetailsPage.ts +16 -20
- package/shopify/loaders/ProductList.ts +66 -69
- package/shopify/loaders/ProductListingPage.ts +150 -158
- package/shopify/loaders/RelatedProducts.ts +24 -27
- package/shopify/loaders/cart.ts +53 -52
- package/shopify/loaders/shop.ts +22 -27
- package/shopify/loaders/user.ts +27 -32
- package/shopify/utils/admin/admin.ts +33 -34
- package/shopify/utils/admin/queries.ts +2 -2
- package/shopify/utils/cart.ts +18 -14
- package/shopify/utils/cookies.ts +62 -65
- package/shopify/utils/enums.ts +424 -424
- package/shopify/utils/graphql.ts +44 -55
- package/shopify/utils/storefront/queries.ts +24 -29
- package/shopify/utils/storefront/storefront.graphql.gen.ts +55 -55
- package/shopify/utils/transform.ts +370 -376
- package/shopify/utils/types.ts +118 -118
- package/shopify/utils/user.ts +11 -11
- package/shopify/utils/utils.ts +135 -140
- package/vtex/actions/address.ts +86 -86
- package/vtex/actions/auth.ts +14 -27
- package/vtex/actions/checkout.ts +36 -49
- package/vtex/actions/masterData.ts +10 -27
- package/vtex/actions/misc.ts +101 -111
- package/vtex/actions/newsletter.ts +48 -52
- package/vtex/actions/orders.ts +13 -16
- package/vtex/actions/profile.ts +55 -55
- package/vtex/actions/session.ts +36 -35
- package/vtex/actions/trigger.ts +25 -25
- package/vtex/actions/wishlist.ts +51 -53
- package/vtex/client.ts +14 -42
- package/vtex/hooks/index.ts +4 -4
- package/vtex/hooks/useAutocomplete.ts +42 -48
- package/vtex/hooks/useCart.ts +153 -165
- package/vtex/hooks/useUser.ts +40 -40
- package/vtex/hooks/useWishlist.ts +70 -70
- package/vtex/inline-loaders/productDetailsPage.ts +1 -3
- package/vtex/inline-loaders/productList.ts +121 -127
- package/vtex/inline-loaders/productListingPage.ts +10 -34
- package/vtex/inline-loaders/relatedProducts.ts +1 -3
- package/vtex/inline-loaders/suggestions.ts +36 -39
- package/vtex/inline-loaders/workflowProducts.ts +45 -49
- package/vtex/invoke.ts +159 -194
- package/vtex/loaders/address.ts +49 -54
- package/vtex/loaders/brands.ts +19 -26
- package/vtex/loaders/cart.ts +24 -21
- package/vtex/loaders/catalog.ts +51 -53
- package/vtex/loaders/collections.ts +25 -27
- package/vtex/loaders/legacy.ts +487 -534
- package/vtex/loaders/logistics.ts +33 -37
- package/vtex/loaders/navbar.ts +5 -8
- package/vtex/loaders/orders.ts +28 -39
- package/vtex/loaders/pageType.ts +41 -35
- package/vtex/loaders/payment.ts +27 -37
- package/vtex/loaders/profile.ts +38 -38
- package/vtex/loaders/promotion.ts +5 -8
- package/vtex/loaders/search.ts +56 -59
- package/vtex/loaders/session.ts +22 -30
- package/vtex/loaders/user.ts +39 -41
- package/vtex/loaders/wishlist.ts +35 -35
- package/vtex/loaders/wishlistProducts.ts +3 -15
- package/vtex/loaders/workflow.ts +220 -227
- package/vtex/middleware.ts +116 -119
- package/vtex/types.ts +201 -201
- package/vtex/utils/batch.ts +13 -16
- package/vtex/utils/cookies.ts +76 -80
- package/vtex/utils/enrichment.ts +62 -42
- package/vtex/utils/fetchCache.ts +1 -4
- package/vtex/utils/index.ts +6 -6
- package/vtex/utils/intelligentSearch.ts +48 -57
- package/vtex/utils/legacy.ts +108 -124
- package/vtex/utils/pickAndOmit.ts +15 -20
- package/vtex/utils/proxy.ts +136 -146
- package/vtex/utils/resourceRange.ts +3 -3
- package/vtex/utils/segment.ts +100 -111
- package/vtex/utils/similars.ts +1 -2
- package/vtex/utils/sitemap.ts +91 -91
- package/vtex/utils/slugCache.ts +2 -6
- package/vtex/utils/slugify.ts +9 -9
- package/vtex/utils/transform.ts +1012 -1105
- package/vtex/utils/types.ts +1381 -1381
- package/vtex/utils/vtexId.ts +44 -47
- package/.github/workflows/release.yml +0 -34
- package/.releaserc.json +0 -28
- package/knip.json +0 -19
- package/tsconfig.json +0 -11
package/vtex/utils/sitemap.ts
CHANGED
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
import { getVtexConfig, vtexFetchResponse, vtexHost } from "../client";
|
|
10
10
|
|
|
11
11
|
export interface SitemapEntry {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
try {
|
|
48
|
+
const mainSitemapUrl = `https://${vtexSitemapHost}/sitemap.xml`;
|
|
49
|
+
const mainResponse = await vtexFetchResponse(mainSitemapUrl);
|
|
50
|
+
const mainXml = await mainResponse.text();
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
const subSitemapUrls = extractLocs(mainXml);
|
|
53
|
+
const entries: SitemapEntry[] = [];
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
|
|
84
|
+
const today = new Date().toISOString().split("T")[0];
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
}
|
package/vtex/utils/slugCache.ts
CHANGED
|
@@ -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
|
}
|
package/vtex/utils/slugify.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
const mapped = JSON.parse(
|
|
2
|
-
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
str
|
|
7
|
+
.replace(/,/g, "")
|
|
8
|
+
.replace(/[·/_,:]/g, "-")
|
|
9
|
+
.replace(/[*+~.()'"!:@&[\]`/ %$#?{}|><=_^]/g, "-")
|
|
10
|
+
.split("")
|
|
11
|
+
.map((char) => mapped[char] ?? char)
|
|
12
|
+
.join("")
|
|
13
|
+
.toLowerCase();
|