@fern-api/fdr-sdk 1.2.38-cc77d6a840 → 1.2.39-5576c2c80f

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.
@@ -94,6 +94,9 @@ var AuthSchemeIdSchema = z2.string();
94
94
  var SubpackageIdSchema = z2.string();
95
95
  var WebSocketMessageIdSchema = z2.string();
96
96
  var FileIdSchema = z2.string();
97
+ function FileId(value) {
98
+ return value;
99
+ }
97
100
  var MultipleAuthTypeSchema = z2.object({
98
101
  schemes: z2.array(AuthSchemeIdSchema)
99
102
  });
@@ -657,6 +660,77 @@ function getChildren(node) {
657
660
  }
658
661
  }
659
662
 
663
+ // ../commons/core-utils/dist/assertNever.js
664
+ function assertNever(x) {
665
+ throw new Error("Unexpected value: " + JSON.stringify(x));
666
+ }
667
+
668
+ // ../commons/core-utils/dist/visitDiscriminatedUnion.js
669
+ function visitDiscriminatedUnion(item, discriminant = "type") {
670
+ return {
671
+ _visit: (visitor) => {
672
+ const visit = visitor[item[discriminant]];
673
+ if (visit != null) {
674
+ return visit(item);
675
+ } else {
676
+ if (visitor._other == null) {
677
+ assertNever(item);
678
+ }
679
+ return visitor._other(item);
680
+ }
681
+ }
682
+ };
683
+ }
684
+ var visitDiscriminatedUnion_default = visitDiscriminatedUnion;
685
+
686
+ // src/navigation/versions/latest/getPageId.ts
687
+ var RETURN_PAGEID = (node) => node.pageId;
688
+ var RETURN_OVERVIEW_PAGEID = (node) => node.overviewPageId;
689
+ var RETURN_UNDEFINED = () => void 0;
690
+ function getPageId(node) {
691
+ return visitDiscriminatedUnion_default(node)._visit({
692
+ section: RETURN_OVERVIEW_PAGEID,
693
+ apiReference: RETURN_OVERVIEW_PAGEID,
694
+ changelog: RETURN_OVERVIEW_PAGEID,
695
+ apiPackage: RETURN_OVERVIEW_PAGEID,
696
+ changelogEntry: RETURN_PAGEID,
697
+ page: RETURN_PAGEID,
698
+ landingPage: RETURN_PAGEID,
699
+ // if the following changes, make sure to update the algolia records generator
700
+ endpoint: RETURN_UNDEFINED,
701
+ webSocket: RETURN_UNDEFINED,
702
+ webhook: RETURN_UNDEFINED,
703
+ grpc: RETURN_UNDEFINED,
704
+ graphql: RETURN_UNDEFINED,
705
+ graphqlType: RETURN_UNDEFINED
706
+ // changelogYear: RETURN_UNDEFINED,
707
+ // changelogMonth: RETURN_UNDEFINED,
708
+ });
709
+ }
710
+
711
+ // src/navigation/versions/latest/NavigationNodeSection.ts
712
+ function isSection(node) {
713
+ return node.type === "section" || node.type === "apiReference" || node.type === "changelog" || node.type === "apiPackage";
714
+ }
715
+
716
+ // src/navigation/versions/latest/NavigationNodeSectionOverview.ts
717
+ function isSectionOverview(node) {
718
+ return isSection(node) && node.overviewPageId != null;
719
+ }
720
+
721
+ // src/navigation/versions/latest/NavigationNodeMarkdown.ts
722
+ function hasMarkdown(node) {
723
+ return isMarkdownLeaf(node) || isSectionOverview(node);
724
+ }
725
+
726
+ // src/navigation/versions/latest/NavigationNodePage.ts
727
+ function isPage(node) {
728
+ return isApiLeaf(node) || node.type === "changelog" || // TODO: Uncomment when changelog years and months are visitable
729
+ // node.type === "changelogYear" ||
730
+ // node.type === "changelogMonth" ||
731
+ hasMarkdown(node);
732
+ }
733
+
660
734
  // src/navigation/versions/latest/NavigationNodeWithMetadata.ts
661
735
  function hasMetadata(node) {
662
736
  return typeof node.title === "string" && typeof node.slug === "string";
@@ -794,6 +868,13 @@ function metaStrArr(metadata, key) {
794
868
  }
795
869
  return void 0;
796
870
  }
871
+ function metaFeatureFlags(metadata) {
872
+ if (metadata != null && typeof metadata === "object" && "featureFlags" in metadata) {
873
+ const v = metadata.featureFlags;
874
+ return Array.isArray(v) && v.length > 0 ? v : void 0;
875
+ }
876
+ return void 0;
877
+ }
797
878
  function toViewers(viewers) {
798
879
  if (viewers == null || viewers.length === 0) {
799
880
  return void 0;
@@ -829,17 +910,17 @@ function scopeKey(seg) {
829
910
  return [seg.product?.id ?? "", seg.version?.id ?? "", seg.variant?.id ?? "", seg.tab?.id ?? ""].join("|");
830
911
  }
831
912
  function withMetadataDefaults(base) {
832
- const { viewers, ...rest } = base;
913
+ const { viewers, featureFlags, ...rest } = base;
833
914
  return {
834
915
  ...rest,
835
916
  canonicalSlug: void 0,
836
- authed: void 0,
917
+ authed: base.authed === true ? true : void 0,
837
918
  collapsed: void 0,
838
919
  // Normalise empty arrays to undefined so unrestricted nodes don't add
839
920
  // filter-level noise; a non-empty array engages the RBAC view gate.
840
921
  viewers: viewers != null && viewers.length > 0 ? viewers : void 0,
841
- orphaned: void 0,
842
- featureFlags: void 0
922
+ orphaned: base.orphaned === true ? true : void 0,
923
+ featureFlags: featureFlags != null && featureFlags.length > 0 ? featureFlags : void 0
843
924
  };
844
925
  }
845
926
  function artifactToNode(ctx, route) {
@@ -862,7 +943,10 @@ function artifactToNode(ctx, route) {
862
943
  slug,
863
944
  icon,
864
945
  hidden: route.hidden,
865
- viewers
946
+ authed: metaBool(md, "authed"),
947
+ viewers,
948
+ orphaned: metaBool(md, "orphaned"),
949
+ featureFlags: metaFeatureFlags(md)
866
950
  }),
867
951
  pageId: PageId(pageId),
868
952
  noindex: metaBool(md, "noindex"),
@@ -878,7 +962,7 @@ function artifactToNode(ctx, route) {
878
962
  title,
879
963
  icon,
880
964
  url: Url(metaStr(md, "url") ?? ""),
881
- target: void 0
965
+ target: metaStr(md, "target")
882
966
  };
883
967
  return node;
884
968
  }
@@ -913,7 +997,10 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
913
997
  slug,
914
998
  icon,
915
999
  hidden: route.hidden,
916
- viewers
1000
+ authed: metaBool(md, "authed"),
1001
+ viewers,
1002
+ orphaned: metaBool(md, "orphaned"),
1003
+ featureFlags: metaFeatureFlags(md)
917
1004
  });
918
1005
  if (route.type === "rest") {
919
1006
  const endpointId = metaStr(md, "endpointId");
@@ -928,7 +1015,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
928
1015
  endpointId: EndpointId(endpointId),
929
1016
  apiDefinitionId,
930
1017
  isResponseStream: metaBool(md, "isResponseStream"),
931
- availability: void 0,
1018
+ availability: metaStr(md, "availability"),
932
1019
  playground: void 0
933
1020
  };
934
1021
  }
@@ -944,7 +1031,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
944
1031
  method,
945
1032
  webhookId: WebhookId(webhookId),
946
1033
  apiDefinitionId,
947
- availability: void 0
1034
+ availability: metaStr(md, "availability")
948
1035
  };
949
1036
  }
950
1037
  if (route.type === "asyncapi") {
@@ -957,7 +1044,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
957
1044
  ...meta,
958
1045
  webSocketId: WebSocketId(webSocketId),
959
1046
  apiDefinitionId,
960
- availability: void 0,
1047
+ availability: metaStr(md, "availability"),
961
1048
  playground: void 0
962
1049
  };
963
1050
  }
@@ -973,7 +1060,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
973
1060
  method,
974
1061
  grpcId: GrpcId(grpcId),
975
1062
  apiDefinitionId,
976
- availability: void 0
1063
+ availability: metaStr(md, "availability")
977
1064
  };
978
1065
  }
979
1066
  if (route.type === "graphql") {
@@ -989,7 +1076,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
989
1076
  graphqlOperationId: GraphQlOperationId(graphqlOperationId),
990
1077
  graphqlOperationIds: void 0,
991
1078
  apiDefinitionId,
992
- availability: void 0,
1079
+ availability: metaStr(md, "availability"),
993
1080
  playground: void 0
994
1081
  };
995
1082
  }
@@ -1084,8 +1171,9 @@ function sectionNode(ctx, scoped, sectionChildren, scopePrefix) {
1084
1171
  const { seg, nav } = scoped;
1085
1172
  const overview = overviewRoute(nav) ?? overviewRouteFromSegmentMeta(seg, nav);
1086
1173
  const overviewPageId = overview != null ? metaStr(overview.metadata, "pageId") : void 0;
1087
- let slug = structuralNodeSlug(ctx, overview?.fullPath, seg.section, scopePrefix);
1088
- if (seg.section === "" && overview?.fullPath == null) {
1174
+ const relSection = stripLeadingScopePrefix(seg.section, scopePrefix);
1175
+ let slug = structuralNodeSlug(ctx, overview?.fullPath, relSection, scopePrefix);
1176
+ if (relSection === "" && overview?.fullPath == null) {
1089
1177
  slug = inferSectionSlugFromNav(ctx, nav, scopePrefix) ?? slug;
1090
1178
  }
1091
1179
  const metaPointsTo = metaStr(seg.metadata, "pointsTo");
@@ -1095,17 +1183,20 @@ function sectionNode(ctx, scoped, sectionChildren, scopePrefix) {
1095
1183
  slug,
1096
1184
  icon: metaStr(seg.metadata, "icon"),
1097
1185
  hidden: seg.hidden,
1098
- viewers: mergeVariantViewers(seg)
1186
+ authed: metaBool(seg.metadata, "authed"),
1187
+ viewers: mergeVariantViewers(seg),
1188
+ orphaned: metaBool(seg.metadata, "orphaned"),
1189
+ featureFlags: metaFeatureFlags(seg.metadata)
1099
1190
  });
1100
1191
  return {
1101
1192
  type: "section",
1102
1193
  ...defaults,
1103
1194
  collapsed: metaCollapsed(seg.metadata) ?? defaults.collapsed,
1104
1195
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1105
- noindex: void 0,
1196
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1106
1197
  collapsible: metaBool(seg.metadata, "collapsible") ?? (metaCollapsed(seg.metadata) != null ? true : void 0),
1107
1198
  collapsedByDefault: metaBool(seg.metadata, "collapsedByDefault") ?? (metaCollapsed(seg.metadata) === true ? true : void 0),
1108
- availability: void 0,
1199
+ availability: metaStr(seg.metadata, "availability"),
1109
1200
  pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1110
1201
  children: mergeChildrenByPosition(ctx, nav, sectionChildren)
1111
1202
  };
@@ -1166,7 +1257,12 @@ function apiPackageChildNode(ctx, scoped, scopeSegs, parentApiDefinitionId, scop
1166
1257
  const overview = overviewRoute(nav);
1167
1258
  const overviewPageId = overview != null ? metaStr(overview.metadata, "pageId") : void 0;
1168
1259
  const apiDefinitionId = metaStr(seg.metadata, "apiDefinitionId") ?? parentApiDefinitionId;
1169
- const slug = structuralNodeSlug(ctx, overview?.fullPath, seg.section, scopePrefix);
1260
+ const slug = structuralNodeSlug(
1261
+ ctx,
1262
+ overview?.fullPath,
1263
+ stripLeadingScopePrefix(seg.section, scopePrefix),
1264
+ scopePrefix
1265
+ );
1170
1266
  const metaPointsTo = metaStr(seg.metadata, "pointsTo");
1171
1267
  const children = buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix);
1172
1268
  return {
@@ -1177,12 +1273,15 @@ function apiPackageChildNode(ctx, scoped, scopeSegs, parentApiDefinitionId, scop
1177
1273
  slug,
1178
1274
  icon: metaStr(seg.metadata, "icon"),
1179
1275
  hidden: seg.hidden,
1180
- viewers: toViewers(metaStrArr(seg.metadata, "viewers"))
1276
+ authed: metaBool(seg.metadata, "authed"),
1277
+ viewers: toViewers(metaStrArr(seg.metadata, "viewers")),
1278
+ orphaned: metaBool(seg.metadata, "orphaned"),
1279
+ featureFlags: metaFeatureFlags(seg.metadata)
1181
1280
  }),
1182
1281
  apiDefinitionId: ApiDefinitionId(apiDefinitionId),
1183
1282
  availability: metaStr(seg.metadata, "availability"),
1184
1283
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1185
- noindex: void 0,
1284
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1186
1285
  pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1187
1286
  children,
1188
1287
  playground: void 0
@@ -1245,7 +1344,12 @@ function apiReferenceNode(ctx, scoped, scopeSegs, scopePrefix) {
1245
1344
  const overview = overviewRoute(nav);
1246
1345
  const overviewPageId = overview != null ? metaStr(overview.metadata, "pageId") : void 0;
1247
1346
  const apiDefinitionId = metaStr(seg.metadata, "apiDefinitionId") ?? "";
1248
- const slug = structuralNodeSlug(ctx, overview?.fullPath, seg.section, scopePrefix);
1347
+ const slug = structuralNodeSlug(
1348
+ ctx,
1349
+ overview?.fullPath,
1350
+ stripLeadingScopePrefix(seg.section, scopePrefix),
1351
+ scopePrefix
1352
+ );
1249
1353
  const metaPointsTo = metaStr(seg.metadata, "pointsTo");
1250
1354
  const children = buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix);
1251
1355
  const changelog = attachedApiChangelogNode(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix);
@@ -1257,12 +1361,15 @@ function apiReferenceNode(ctx, scoped, scopeSegs, scopePrefix) {
1257
1361
  slug,
1258
1362
  icon: metaStr(seg.metadata, "icon"),
1259
1363
  hidden: seg.hidden,
1260
- viewers: mergeVariantViewers(seg)
1364
+ authed: metaBool(seg.metadata, "authed"),
1365
+ viewers: mergeVariantViewers(seg),
1366
+ orphaned: metaBool(seg.metadata, "orphaned"),
1367
+ featureFlags: metaFeatureFlags(seg.metadata)
1261
1368
  }),
1262
1369
  apiDefinitionId: ApiDefinitionId(apiDefinitionId),
1263
- availability: void 0,
1370
+ availability: metaStr(seg.metadata, "availability"),
1264
1371
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1265
- noindex: void 0,
1372
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1266
1373
  paginated: true,
1267
1374
  showErrors: metaBool(seg.metadata, "showErrors"),
1268
1375
  hideTitle: metaBool(seg.metadata, "hideTitle"),
@@ -1315,10 +1422,13 @@ function changelogNode(ctx, scoped, scopePrefix) {
1315
1422
  slug: ctx.contentSlug(r.fullPath ?? ""),
1316
1423
  icon: metaStr(r.metadata, "icon"),
1317
1424
  hidden: r.hidden,
1318
- viewers: toViewers(metaStrArr(r.metadata, "viewers"))
1425
+ authed: metaBool(r.metadata, "authed"),
1426
+ viewers: toViewers(metaStrArr(r.metadata, "viewers")),
1427
+ orphaned: metaBool(r.metadata, "orphaned"),
1428
+ featureFlags: metaFeatureFlags(r.metadata)
1319
1429
  }),
1320
1430
  pageId: PageId(metaStr(r.metadata, "pageId") ?? ""),
1321
- noindex: void 0,
1431
+ noindex: metaBool(r.metadata, "noindex"),
1322
1432
  date: dateStr ?? "",
1323
1433
  tags: void 0
1324
1434
  };
@@ -1364,10 +1474,13 @@ function changelogNode(ctx, scoped, scopePrefix) {
1364
1474
  slug: baseSlug,
1365
1475
  icon: metaStr(seg.metadata, "icon"),
1366
1476
  hidden: seg.hidden,
1367
- viewers: mergeVariantViewers(seg)
1477
+ authed: metaBool(seg.metadata, "authed"),
1478
+ viewers: mergeVariantViewers(seg),
1479
+ orphaned: metaBool(seg.metadata, "orphaned"),
1480
+ featureFlags: metaFeatureFlags(seg.metadata)
1368
1481
  }),
1369
1482
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1370
- noindex: void 0,
1483
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1371
1484
  children: years
1372
1485
  };
1373
1486
  }
@@ -1613,7 +1726,7 @@ function buildVariantedNode(ctx, variants, scopeSegs, scopePrefix) {
1613
1726
  default: detailIsDefault(variant),
1614
1727
  variantId: VariantId(String(variant.id)),
1615
1728
  subtitle: metaStr(variant.metadata, "subtitle") ?? void 0,
1616
- image: void 0,
1729
+ image: metaStr(variant.metadata, "image") != null ? FileId(metaStr(variant.metadata, "image")) : void 0,
1617
1730
  pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1618
1731
  children
1619
1732
  };
@@ -1650,7 +1763,10 @@ function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix) {
1650
1763
  const tabDetails = uniqueDetails(scopeSegs, "tab");
1651
1764
  const children = tabDetails.map((tab) => {
1652
1765
  const tabType = metaStr(tab.metadata, "tab_type");
1653
- const tabSlug = asSlug(scopeSlugPrefix(scopePrefix, tab));
1766
+ const rawTabSlug = detailSlug(tab);
1767
+ const versionDetail = scopeSegs[0]?.seg.version;
1768
+ const versionSlugStr = versionDetail != null ? detailSlug(versionDetail) : void 0;
1769
+ const tabSlug = versionSlugStr != null && rawTabSlug !== "" && (rawTabSlug === versionSlugStr || rawTabSlug.startsWith(versionSlugStr + "/")) ? asSlug(rawTabSlug) : asSlug(scopeSlugPrefix(scopePrefix, tab));
1654
1770
  if (tabType === "link") {
1655
1771
  return {
1656
1772
  type: "link",
@@ -1659,7 +1775,7 @@ function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix) {
1659
1775
  title: tab.displayName,
1660
1776
  icon: tab.icon ?? void 0,
1661
1777
  url: Url(metaStr(tab.metadata, "url") ?? ""),
1662
- target: void 0
1778
+ target: metaStr(tab.metadata, "target")
1663
1779
  };
1664
1780
  }
1665
1781
  if (tabType === "changelog") {
@@ -1747,7 +1863,7 @@ function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix) {
1747
1863
  default: detailIsDefault(version),
1748
1864
  versionId: VersionId(version.id),
1749
1865
  availability: void 0,
1750
- landingPage: void 0,
1866
+ landingPage: buildVersionLandingPage(ctx, versionSegs, asSlug(slug)),
1751
1867
  announcement: void 0,
1752
1868
  pointsTo: metaStr(version.metadata, "pointsTo") != null ? pointsToSlug(metaStr(version.metadata, "pointsTo")) : void 0,
1753
1869
  // The version's full slug roots structural sections so the whole
@@ -1759,6 +1875,7 @@ function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix) {
1759
1875
  }
1760
1876
  return node;
1761
1877
  });
1878
+ markCrossVersionCanonicalSlugs(children);
1762
1879
  return {
1763
1880
  type: "versioned",
1764
1881
  id: ctx.nodeId(`versioned:${productPrefix ?? "root"}`),
@@ -1784,6 +1901,111 @@ function markDefaultVersionCanonicalSlugs(node, pruneSlug, versionSlug) {
1784
1901
  return;
1785
1902
  });
1786
1903
  }
1904
+ function unversionedParents(parents) {
1905
+ let versionIdx = -1;
1906
+ for (let i = parents.length - 1; i >= 0; i--) {
1907
+ if (parents[i].type === "version") {
1908
+ versionIdx = i;
1909
+ break;
1910
+ }
1911
+ }
1912
+ return versionIdx >= 0 ? parents.slice(versionIdx + 1) : parents;
1913
+ }
1914
+ function crossVersionDedupKeys(node, parents) {
1915
+ const keys = [];
1916
+ const uParents = unversionedParents(parents);
1917
+ const pid = getPageId(node);
1918
+ if (pid != null) {
1919
+ keys.push(`pid:${pid}`);
1920
+ }
1921
+ if (node.type === "endpoint" || node.type === "webSocket" || node.type === "webhook" || node.type === "grpc" || node.type === "graphql") {
1922
+ const apiParentTitles = uParents.filter(
1923
+ (p) => p.type === "apiReference"
1924
+ ).map((p) => p.title.replaceAll(" ", ""));
1925
+ const apiPrefix = apiParentTitles.join(":");
1926
+ if (node.type === "endpoint") {
1927
+ keys.push(`${apiPrefix}:api:endpoint:${node.method}:${node.endpointId}`);
1928
+ } else if (node.type === "webSocket") {
1929
+ keys.push(`${apiPrefix}:api:websocket:${node.webSocketId}`);
1930
+ } else if (node.type === "webhook") {
1931
+ keys.push(`${apiPrefix}:api:webhook:${node.method}:${node.webhookId}`);
1932
+ } else if (node.type === "grpc") {
1933
+ keys.push(`${apiPrefix}:api:grpc:${node.method}:${node.grpcId}`);
1934
+ } else if (node.type === "graphql") {
1935
+ keys.push(`${apiPrefix}:api:graphql:${node.id}`);
1936
+ }
1937
+ }
1938
+ const parentTitles = [];
1939
+ for (const p of uParents) {
1940
+ if (hasMetadata(p)) {
1941
+ parentTitles.push(p.title);
1942
+ }
1943
+ }
1944
+ keys.push([...parentTitles, node.title].join("###"));
1945
+ return keys;
1946
+ }
1947
+ function buildVersionLandingPage(ctx, versionSegs, versionSlug) {
1948
+ const tablessSegs = versionSegs.filter((s) => s.seg.tab == null);
1949
+ if (tablessSegs.length === 0) {
1950
+ return void 0;
1951
+ }
1952
+ for (const s of tablessSegs) {
1953
+ for (const r of s.nav) {
1954
+ if (r.type === "markdown" && r.fullPath != null) {
1955
+ const md = r.metadata;
1956
+ const pageId = metaStr(md, "pageId") ?? "";
1957
+ const slug = ctx.contentSlug(r.fullPath);
1958
+ return {
1959
+ type: "landingPage",
1960
+ ...withMetadataDefaults({
1961
+ id: ctx.nodeId(`landing:${slug}`),
1962
+ title: metaStr(md, "title") ?? "",
1963
+ slug,
1964
+ icon: metaStr(md, "icon"),
1965
+ hidden: r.hidden,
1966
+ viewers: toViewers(metaStrArr(md, "viewers"))
1967
+ }),
1968
+ pageId: PageId(pageId),
1969
+ noindex: metaBool(md, "noindex")
1970
+ };
1971
+ }
1972
+ }
1973
+ }
1974
+ return void 0;
1975
+ }
1976
+ function markCrossVersionCanonicalSlugs(versionNodes) {
1977
+ const keyToCanonical = /* @__PURE__ */ new Map();
1978
+ const sorted = [...versionNodes].sort((a, b) => {
1979
+ if (a.default !== b.default) {
1980
+ return a.default ? -1 : 1;
1981
+ }
1982
+ return 0;
1983
+ });
1984
+ for (const version of sorted) {
1985
+ traverseDF(version, (child, parents) => {
1986
+ if (hasMetadata(child) && isPage(child)) {
1987
+ const keys = crossVersionDedupKeys(child, parents);
1988
+ let matched = false;
1989
+ for (const key of keys) {
1990
+ const canonical = keyToCanonical.get(key);
1991
+ if (canonical != null && !version.default) {
1992
+ child.canonicalSlug = canonical;
1993
+ matched = true;
1994
+ break;
1995
+ }
1996
+ }
1997
+ if (!matched) {
1998
+ const canonical = child.canonicalSlug ?? child.slug;
1999
+ for (const key of keys) {
2000
+ if (!keyToCanonical.has(key)) {
2001
+ keyToCanonical.set(key, canonical);
2002
+ }
2003
+ }
2004
+ }
2005
+ }
2006
+ });
2007
+ }
2008
+ }
1787
2009
  function buildProductGroup(ctx, products, scoped, rootSlug) {
1788
2010
  const children = products.map((product) => {
1789
2011
  const productSegs = scoped.filter((s) => s.seg.product?.id === product.id);
@@ -1809,7 +2031,7 @@ function buildProductGroup(ctx, products, scoped, rootSlug) {
1809
2031
  // here; sourcing it from the hash makes that filter match nothing.
1810
2032
  productId: ProductId(product.displayName),
1811
2033
  subtitle: metaStr(product.metadata, "subtitle") ?? "",
1812
- image: void 0,
2034
+ image: metaStr(product.metadata, "image") != null ? FileId(metaStr(product.metadata, "image")) : void 0,
1813
2035
  announcement: void 0,
1814
2036
  pointsTo: metaStr(product.metadata, "pointsTo") != null ? pointsToSlug(metaStr(product.metadata, "pointsTo")) : void 0,
1815
2037
  child: productChild