@decocms/apps-vtex 7.25.0 → 7.26.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decocms/apps-vtex",
3
- "version": "7.25.0",
3
+ "version": "7.26.1",
4
4
  "type": "module",
5
5
  "description": "Deco commerce app: VTEX integration",
6
6
  "repository": {
@@ -51,10 +51,10 @@
51
51
  "lint:unused": "knip"
52
52
  },
53
53
  "dependencies": {
54
- "@decocms/blocks": "7.25.0",
55
- "@decocms/apps-commerce": "7.25.0",
56
- "@decocms/apps-website": "7.25.0",
57
- "@decocms/tanstack": "7.25.0"
54
+ "@decocms/blocks": "7.26.1",
55
+ "@decocms/apps-commerce": "7.26.1",
56
+ "@decocms/apps-website": "7.26.1",
57
+ "@decocms/tanstack": "7.26.1"
58
58
  },
59
59
  "peerDependencies": {
60
60
  "@tanstack/react-query": ">=5.0.0",
@@ -6,6 +6,7 @@
6
6
 
7
7
  import type { ProductDetailsPage } from "@decocms/apps-commerce/types";
8
8
  import { getVtexConfig, vtexCachedFetch } from "../../client";
9
+ import PDPDefaultPath from "../paths/PDPDefaultPath";
9
10
  import { searchBySlug } from "../../utils/slugCache";
10
11
  import { pickSku, toProductPage } from "../../utils/transform";
11
12
  import type { LegacyProduct } from "../../utils/types";
@@ -42,10 +43,27 @@ export default async function vtexProductDetailsPage(
42
43
  variantIncludeImage = true,
43
44
  variantIncludeInventory = true,
44
45
  } = props;
45
- if (!slug) return null;
46
46
 
47
47
  try {
48
- const linkText = slug.replace(/\/p$/, "").replace(/^\//, "").toLowerCase();
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();
49
67
  const config = getVtexConfig();
50
68
  const sc = config.salesChannel;
51
69
 
@@ -0,0 +1,51 @@
1
+ /**
2
+ * PDP default-path resolver.
3
+ *
4
+ * Ported from deco-cx/apps (`vtex/loaders/paths/PDPDefaultPath.ts`). When a
5
+ * Product page is previewed/configured in the CMS, it is resolved at its raw
6
+ * route pattern (`/:slug/p`), so the `slug` route-param comes through as the
7
+ * literal placeholder `:slug` — there is no concrete product in the URL. Rather
8
+ * than render a 404, we fall back to a real product — the best seller — so the
9
+ * PDP has something to show in the admin.
10
+ *
11
+ * We query Intelligent Search for the top-selling, in-stock product and return
12
+ * its `linkText` as the slug the PDP loader should render.
13
+ */
14
+ import { intelligentSearch } from "../../client";
15
+
16
+ export interface PDPDefaultPathProps {
17
+ /** How many candidate paths to fetch. Defaults to 1. */
18
+ count?: number;
19
+ }
20
+
21
+ export interface DefaultPathResult {
22
+ possiblePaths: string[];
23
+ }
24
+
25
+ export default async function PDPDefaultPath(
26
+ props: PDPDefaultPathProps = {},
27
+ ): Promise<DefaultPathResult | null> {
28
+ const { count = 1 } = props;
29
+
30
+ try {
31
+ const data = await intelligentSearch<{ products?: Array<{ linkText?: string }> }>(
32
+ "/product_search/",
33
+ {
34
+ page: "1",
35
+ count: String(count),
36
+ query: "",
37
+ sort: "orders:desc",
38
+ hideUnavailableItems: "true",
39
+ },
40
+ );
41
+
42
+ const possiblePaths = (data.products ?? [])
43
+ .map((p) => p.linkText)
44
+ .filter((linkText): linkText is string => Boolean(linkText));
45
+
46
+ return { possiblePaths };
47
+ } catch (error) {
48
+ console.error("[VTEX] PDPDefaultPath error:", error);
49
+ return null;
50
+ }
51
+ }