@fern-api/fdr-sdk 1.2.38-cc77d6a840 → 1.2.39-008eed59b3

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.
@@ -135,6 +135,9 @@ var AuthSchemeIdSchema = z2.string();
135
135
  var SubpackageIdSchema = z2.string();
136
136
  var WebSocketMessageIdSchema = z2.string();
137
137
  var FileIdSchema = z2.string();
138
+ function FileId(value) {
139
+ return value;
140
+ }
138
141
  var MultipleAuthTypeSchema = z2.object({
139
142
  schemes: z2.array(AuthSchemeIdSchema)
140
143
  });
@@ -698,6 +701,77 @@ function getChildren(node) {
698
701
  }
699
702
  }
700
703
 
704
+ // ../commons/core-utils/dist/assertNever.js
705
+ function assertNever(x) {
706
+ throw new Error("Unexpected value: " + JSON.stringify(x));
707
+ }
708
+
709
+ // ../commons/core-utils/dist/visitDiscriminatedUnion.js
710
+ function visitDiscriminatedUnion(item, discriminant = "type") {
711
+ return {
712
+ _visit: (visitor) => {
713
+ const visit = visitor[item[discriminant]];
714
+ if (visit != null) {
715
+ return visit(item);
716
+ } else {
717
+ if (visitor._other == null) {
718
+ assertNever(item);
719
+ }
720
+ return visitor._other(item);
721
+ }
722
+ }
723
+ };
724
+ }
725
+ var visitDiscriminatedUnion_default = visitDiscriminatedUnion;
726
+
727
+ // src/navigation/versions/latest/getPageId.ts
728
+ var RETURN_PAGEID = (node) => node.pageId;
729
+ var RETURN_OVERVIEW_PAGEID = (node) => node.overviewPageId;
730
+ var RETURN_UNDEFINED = () => void 0;
731
+ function getPageId(node) {
732
+ return visitDiscriminatedUnion_default(node)._visit({
733
+ section: RETURN_OVERVIEW_PAGEID,
734
+ apiReference: RETURN_OVERVIEW_PAGEID,
735
+ changelog: RETURN_OVERVIEW_PAGEID,
736
+ apiPackage: RETURN_OVERVIEW_PAGEID,
737
+ changelogEntry: RETURN_PAGEID,
738
+ page: RETURN_PAGEID,
739
+ landingPage: RETURN_PAGEID,
740
+ // if the following changes, make sure to update the algolia records generator
741
+ endpoint: RETURN_UNDEFINED,
742
+ webSocket: RETURN_UNDEFINED,
743
+ webhook: RETURN_UNDEFINED,
744
+ grpc: RETURN_UNDEFINED,
745
+ graphql: RETURN_UNDEFINED,
746
+ graphqlType: RETURN_UNDEFINED
747
+ // changelogYear: RETURN_UNDEFINED,
748
+ // changelogMonth: RETURN_UNDEFINED,
749
+ });
750
+ }
751
+
752
+ // src/navigation/versions/latest/NavigationNodeSection.ts
753
+ function isSection(node) {
754
+ return node.type === "section" || node.type === "apiReference" || node.type === "changelog" || node.type === "apiPackage";
755
+ }
756
+
757
+ // src/navigation/versions/latest/NavigationNodeSectionOverview.ts
758
+ function isSectionOverview(node) {
759
+ return isSection(node) && node.overviewPageId != null;
760
+ }
761
+
762
+ // src/navigation/versions/latest/NavigationNodeMarkdown.ts
763
+ function hasMarkdown(node) {
764
+ return isMarkdownLeaf(node) || isSectionOverview(node);
765
+ }
766
+
767
+ // src/navigation/versions/latest/NavigationNodePage.ts
768
+ function isPage(node) {
769
+ return isApiLeaf(node) || node.type === "changelog" || // TODO: Uncomment when changelog years and months are visitable
770
+ // node.type === "changelogYear" ||
771
+ // node.type === "changelogMonth" ||
772
+ hasMarkdown(node);
773
+ }
774
+
701
775
  // src/navigation/versions/latest/NavigationNodeWithMetadata.ts
702
776
  function hasMetadata(node) {
703
777
  return typeof node.title === "string" && typeof node.slug === "string";
@@ -835,6 +909,13 @@ function metaStrArr(metadata, key) {
835
909
  }
836
910
  return void 0;
837
911
  }
912
+ function metaFeatureFlags(metadata) {
913
+ if (metadata != null && typeof metadata === "object" && "featureFlags" in metadata) {
914
+ const v = metadata.featureFlags;
915
+ return Array.isArray(v) && v.length > 0 ? v : void 0;
916
+ }
917
+ return void 0;
918
+ }
838
919
  function toViewers(viewers) {
839
920
  if (viewers == null || viewers.length === 0) {
840
921
  return void 0;
@@ -870,17 +951,17 @@ function scopeKey(seg) {
870
951
  return [seg.product?.id ?? "", seg.version?.id ?? "", seg.variant?.id ?? "", seg.tab?.id ?? ""].join("|");
871
952
  }
872
953
  function withMetadataDefaults(base) {
873
- const { viewers, ...rest } = base;
954
+ const { viewers, featureFlags, ...rest } = base;
874
955
  return {
875
956
  ...rest,
876
957
  canonicalSlug: void 0,
877
- authed: void 0,
958
+ authed: base.authed === true ? true : void 0,
878
959
  collapsed: void 0,
879
960
  // Normalise empty arrays to undefined so unrestricted nodes don't add
880
961
  // filter-level noise; a non-empty array engages the RBAC view gate.
881
962
  viewers: viewers != null && viewers.length > 0 ? viewers : void 0,
882
- orphaned: void 0,
883
- featureFlags: void 0
963
+ orphaned: base.orphaned === true ? true : void 0,
964
+ featureFlags: featureFlags != null && featureFlags.length > 0 ? featureFlags : void 0
884
965
  };
885
966
  }
886
967
  function artifactToNode(ctx, route) {
@@ -903,7 +984,10 @@ function artifactToNode(ctx, route) {
903
984
  slug,
904
985
  icon,
905
986
  hidden: route.hidden,
906
- viewers
987
+ authed: metaBool(md, "authed"),
988
+ viewers,
989
+ orphaned: metaBool(md, "orphaned"),
990
+ featureFlags: metaFeatureFlags(md)
907
991
  }),
908
992
  pageId: PageId(pageId),
909
993
  noindex: metaBool(md, "noindex"),
@@ -919,7 +1003,7 @@ function artifactToNode(ctx, route) {
919
1003
  title,
920
1004
  icon,
921
1005
  url: Url(metaStr(md, "url") ?? ""),
922
- target: void 0
1006
+ target: metaStr(md, "target")
923
1007
  };
924
1008
  return node;
925
1009
  }
@@ -954,7 +1038,10 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
954
1038
  slug,
955
1039
  icon,
956
1040
  hidden: route.hidden,
957
- viewers
1041
+ authed: metaBool(md, "authed"),
1042
+ viewers,
1043
+ orphaned: metaBool(md, "orphaned"),
1044
+ featureFlags: metaFeatureFlags(md)
958
1045
  });
959
1046
  if (route.type === "rest") {
960
1047
  const endpointId = metaStr(md, "endpointId");
@@ -969,7 +1056,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
969
1056
  endpointId: EndpointId(endpointId),
970
1057
  apiDefinitionId,
971
1058
  isResponseStream: metaBool(md, "isResponseStream"),
972
- availability: void 0,
1059
+ availability: metaStr(md, "availability"),
973
1060
  playground: void 0
974
1061
  };
975
1062
  }
@@ -985,7 +1072,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
985
1072
  method,
986
1073
  webhookId: WebhookId(webhookId),
987
1074
  apiDefinitionId,
988
- availability: void 0
1075
+ availability: metaStr(md, "availability")
989
1076
  };
990
1077
  }
991
1078
  if (route.type === "asyncapi") {
@@ -998,7 +1085,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
998
1085
  ...meta,
999
1086
  webSocketId: WebSocketId(webSocketId),
1000
1087
  apiDefinitionId,
1001
- availability: void 0,
1088
+ availability: metaStr(md, "availability"),
1002
1089
  playground: void 0
1003
1090
  };
1004
1091
  }
@@ -1014,7 +1101,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
1014
1101
  method,
1015
1102
  grpcId: GrpcId(grpcId),
1016
1103
  apiDefinitionId,
1017
- availability: void 0
1104
+ availability: metaStr(md, "availability")
1018
1105
  };
1019
1106
  }
1020
1107
  if (route.type === "graphql") {
@@ -1030,7 +1117,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
1030
1117
  graphqlOperationId: GraphQlOperationId(graphqlOperationId),
1031
1118
  graphqlOperationIds: void 0,
1032
1119
  apiDefinitionId,
1033
- availability: void 0,
1120
+ availability: metaStr(md, "availability"),
1034
1121
  playground: void 0
1035
1122
  };
1036
1123
  }
@@ -1125,8 +1212,9 @@ function sectionNode(ctx, scoped, sectionChildren, scopePrefix) {
1125
1212
  const { seg, nav } = scoped;
1126
1213
  const overview = overviewRoute(nav) ?? overviewRouteFromSegmentMeta(seg, nav);
1127
1214
  const overviewPageId = overview != null ? metaStr(overview.metadata, "pageId") : void 0;
1128
- let slug = structuralNodeSlug(ctx, overview?.fullPath, seg.section, scopePrefix);
1129
- if (seg.section === "" && overview?.fullPath == null) {
1215
+ const relSection = stripLeadingScopePrefix(seg.section, scopePrefix);
1216
+ let slug = structuralNodeSlug(ctx, overview?.fullPath, relSection, scopePrefix);
1217
+ if (relSection === "" && overview?.fullPath == null) {
1130
1218
  slug = inferSectionSlugFromNav(ctx, nav, scopePrefix) ?? slug;
1131
1219
  }
1132
1220
  const metaPointsTo = metaStr(seg.metadata, "pointsTo");
@@ -1136,17 +1224,22 @@ function sectionNode(ctx, scoped, sectionChildren, scopePrefix) {
1136
1224
  slug,
1137
1225
  icon: metaStr(seg.metadata, "icon"),
1138
1226
  hidden: seg.hidden,
1139
- viewers: mergeVariantViewers(seg)
1227
+ authed: metaBool(seg.metadata, "authed"),
1228
+ viewers: mergeVariantViewers(seg),
1229
+ orphaned: metaBool(seg.metadata, "orphaned"),
1230
+ featureFlags: metaFeatureFlags(seg.metadata)
1140
1231
  });
1141
1232
  return {
1142
1233
  type: "section",
1143
1234
  ...defaults,
1144
- collapsed: metaCollapsed(seg.metadata) ?? defaults.collapsed,
1235
+ // V2 convention: collapsed:false in docs.yml maps to "open-by-default"
1236
+ // so getInitiallyOpenByDefaultNodes picks it up and the UI starts open.
1237
+ collapsed: metaCollapsed(seg.metadata) === false ? "open-by-default" : metaCollapsed(seg.metadata) ?? defaults.collapsed,
1145
1238
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1146
- noindex: void 0,
1239
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1147
1240
  collapsible: metaBool(seg.metadata, "collapsible") ?? (metaCollapsed(seg.metadata) != null ? true : void 0),
1148
1241
  collapsedByDefault: metaBool(seg.metadata, "collapsedByDefault") ?? (metaCollapsed(seg.metadata) === true ? true : void 0),
1149
- availability: void 0,
1242
+ availability: metaStr(seg.metadata, "availability"),
1150
1243
  pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1151
1244
  children: mergeChildrenByPosition(ctx, nav, sectionChildren)
1152
1245
  };
@@ -1207,7 +1300,12 @@ function apiPackageChildNode(ctx, scoped, scopeSegs, parentApiDefinitionId, scop
1207
1300
  const overview = overviewRoute(nav);
1208
1301
  const overviewPageId = overview != null ? metaStr(overview.metadata, "pageId") : void 0;
1209
1302
  const apiDefinitionId = metaStr(seg.metadata, "apiDefinitionId") ?? parentApiDefinitionId;
1210
- const slug = structuralNodeSlug(ctx, overview?.fullPath, seg.section, scopePrefix);
1303
+ const slug = structuralNodeSlug(
1304
+ ctx,
1305
+ overview?.fullPath,
1306
+ stripLeadingScopePrefix(seg.section, scopePrefix),
1307
+ scopePrefix
1308
+ );
1211
1309
  const metaPointsTo = metaStr(seg.metadata, "pointsTo");
1212
1310
  const children = buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix);
1213
1311
  return {
@@ -1218,12 +1316,15 @@ function apiPackageChildNode(ctx, scoped, scopeSegs, parentApiDefinitionId, scop
1218
1316
  slug,
1219
1317
  icon: metaStr(seg.metadata, "icon"),
1220
1318
  hidden: seg.hidden,
1221
- viewers: toViewers(metaStrArr(seg.metadata, "viewers"))
1319
+ authed: metaBool(seg.metadata, "authed"),
1320
+ viewers: toViewers(metaStrArr(seg.metadata, "viewers")),
1321
+ orphaned: metaBool(seg.metadata, "orphaned"),
1322
+ featureFlags: metaFeatureFlags(seg.metadata)
1222
1323
  }),
1223
1324
  apiDefinitionId: ApiDefinitionId(apiDefinitionId),
1224
1325
  availability: metaStr(seg.metadata, "availability"),
1225
1326
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1226
- noindex: void 0,
1327
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1227
1328
  pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1228
1329
  children,
1229
1330
  playground: void 0
@@ -1286,7 +1387,12 @@ function apiReferenceNode(ctx, scoped, scopeSegs, scopePrefix) {
1286
1387
  const overview = overviewRoute(nav);
1287
1388
  const overviewPageId = overview != null ? metaStr(overview.metadata, "pageId") : void 0;
1288
1389
  const apiDefinitionId = metaStr(seg.metadata, "apiDefinitionId") ?? "";
1289
- const slug = structuralNodeSlug(ctx, overview?.fullPath, seg.section, scopePrefix);
1390
+ const slug = structuralNodeSlug(
1391
+ ctx,
1392
+ overview?.fullPath,
1393
+ stripLeadingScopePrefix(seg.section, scopePrefix),
1394
+ scopePrefix
1395
+ );
1290
1396
  const metaPointsTo = metaStr(seg.metadata, "pointsTo");
1291
1397
  const children = buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix);
1292
1398
  const changelog = attachedApiChangelogNode(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix);
@@ -1298,12 +1404,15 @@ function apiReferenceNode(ctx, scoped, scopeSegs, scopePrefix) {
1298
1404
  slug,
1299
1405
  icon: metaStr(seg.metadata, "icon"),
1300
1406
  hidden: seg.hidden,
1301
- viewers: mergeVariantViewers(seg)
1407
+ authed: metaBool(seg.metadata, "authed"),
1408
+ viewers: mergeVariantViewers(seg),
1409
+ orphaned: metaBool(seg.metadata, "orphaned"),
1410
+ featureFlags: metaFeatureFlags(seg.metadata)
1302
1411
  }),
1303
1412
  apiDefinitionId: ApiDefinitionId(apiDefinitionId),
1304
- availability: void 0,
1413
+ availability: metaStr(seg.metadata, "availability"),
1305
1414
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1306
- noindex: void 0,
1415
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1307
1416
  paginated: true,
1308
1417
  showErrors: metaBool(seg.metadata, "showErrors"),
1309
1418
  hideTitle: metaBool(seg.metadata, "hideTitle"),
@@ -1356,10 +1465,13 @@ function changelogNode(ctx, scoped, scopePrefix) {
1356
1465
  slug: ctx.contentSlug(r.fullPath ?? ""),
1357
1466
  icon: metaStr(r.metadata, "icon"),
1358
1467
  hidden: r.hidden,
1359
- viewers: toViewers(metaStrArr(r.metadata, "viewers"))
1468
+ authed: metaBool(r.metadata, "authed"),
1469
+ viewers: toViewers(metaStrArr(r.metadata, "viewers")),
1470
+ orphaned: metaBool(r.metadata, "orphaned"),
1471
+ featureFlags: metaFeatureFlags(r.metadata)
1360
1472
  }),
1361
1473
  pageId: PageId(metaStr(r.metadata, "pageId") ?? ""),
1362
- noindex: void 0,
1474
+ noindex: metaBool(r.metadata, "noindex"),
1363
1475
  date: dateStr ?? "",
1364
1476
  tags: void 0
1365
1477
  };
@@ -1405,10 +1517,13 @@ function changelogNode(ctx, scoped, scopePrefix) {
1405
1517
  slug: baseSlug,
1406
1518
  icon: metaStr(seg.metadata, "icon"),
1407
1519
  hidden: seg.hidden,
1408
- viewers: mergeVariantViewers(seg)
1520
+ authed: metaBool(seg.metadata, "authed"),
1521
+ viewers: mergeVariantViewers(seg),
1522
+ orphaned: metaBool(seg.metadata, "orphaned"),
1523
+ featureFlags: metaFeatureFlags(seg.metadata)
1409
1524
  }),
1410
1525
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1411
- noindex: void 0,
1526
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1412
1527
  children: years
1413
1528
  };
1414
1529
  }
@@ -1594,6 +1709,24 @@ function buildFullRootFromSegments(options) {
1594
1709
  } else if (child.type === "versioned") {
1595
1710
  const defaultVersion = child.children.find((v) => v.default) ?? child.children[0];
1596
1711
  rootPointsTo = defaultVersion?.pointsTo;
1712
+ } else if (child.type === "unversioned") {
1713
+ if (tabs.length > 0) {
1714
+ const firstTab = tabs[0];
1715
+ const pt = firstTab != null ? metaStr(firstTab.metadata, "pointsTo") : void 0;
1716
+ rootPointsTo = pt != null ? pointsToSlug(pt) : void 0;
1717
+ } else {
1718
+ const sorted = [...scoped].sort((a, b) => a.seg.sortOrder - b.seg.sortOrder);
1719
+ for (const s of sorted) {
1720
+ if (s.seg.hidden) {
1721
+ continue;
1722
+ }
1723
+ const pt = metaStr(s.seg.metadata, "pointsTo");
1724
+ if (pt != null) {
1725
+ rootPointsTo = pointsToSlug(pt);
1726
+ break;
1727
+ }
1728
+ }
1729
+ }
1597
1730
  }
1598
1731
  const root = {
1599
1732
  type: "root",
@@ -1606,21 +1739,22 @@ function buildFullRootFromSegments(options) {
1606
1739
  return root;
1607
1740
  }
1608
1741
  function uniqueDetails(scoped, dim) {
1609
- const bySlug = /* @__PURE__ */ new Map();
1742
+ const byKey = /* @__PURE__ */ new Map();
1610
1743
  for (const s of scoped) {
1611
1744
  const d = s.seg[dim];
1612
1745
  if (d == null) {
1613
1746
  continue;
1614
1747
  }
1615
1748
  const slug = detailSlug(d);
1616
- const existing = bySlug.get(slug);
1749
+ const key = slug !== "" ? slug : d.id;
1750
+ const existing = byKey.get(key);
1617
1751
  if (existing == null) {
1618
- bySlug.set(slug, d);
1752
+ byKey.set(key, d);
1619
1753
  } else if (metaStr(d.metadata, "pointsTo") != null && metaStr(existing.metadata, "pointsTo") == null) {
1620
- bySlug.set(slug, d);
1754
+ byKey.set(key, d);
1621
1755
  }
1622
1756
  }
1623
- return [...bySlug.values()].sort((a, b) => a.sortOrder - b.sortOrder);
1757
+ return [...byKey.values()].sort((a, b) => a.sortOrder - b.sortOrder);
1624
1758
  }
1625
1759
  function scopeSlugPrefix(rootSlug, ...details) {
1626
1760
  const parts = [rootSlug];
@@ -1654,7 +1788,7 @@ function buildVariantedNode(ctx, variants, scopeSegs, scopePrefix) {
1654
1788
  default: detailIsDefault(variant),
1655
1789
  variantId: VariantId(String(variant.id)),
1656
1790
  subtitle: metaStr(variant.metadata, "subtitle") ?? void 0,
1657
- image: void 0,
1791
+ image: metaStr(variant.metadata, "image") != null ? FileId(metaStr(variant.metadata, "image")) : void 0,
1658
1792
  pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1659
1793
  children
1660
1794
  };
@@ -1691,7 +1825,10 @@ function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix) {
1691
1825
  const tabDetails = uniqueDetails(scopeSegs, "tab");
1692
1826
  const children = tabDetails.map((tab) => {
1693
1827
  const tabType = metaStr(tab.metadata, "tab_type");
1694
- const tabSlug = asSlug(scopeSlugPrefix(scopePrefix, tab));
1828
+ const rawTabSlug = detailSlug(tab);
1829
+ const versionDetail = scopeSegs[0]?.seg.version;
1830
+ const versionSlugStr = versionDetail != null ? detailSlug(versionDetail) : void 0;
1831
+ const tabSlug = versionSlugStr != null && rawTabSlug !== "" && (rawTabSlug === versionSlugStr || rawTabSlug.startsWith(versionSlugStr + "/")) ? asSlug(rawTabSlug) : asSlug(scopeSlugPrefix(scopePrefix, tab));
1695
1832
  if (tabType === "link") {
1696
1833
  return {
1697
1834
  type: "link",
@@ -1700,7 +1837,7 @@ function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix) {
1700
1837
  title: tab.displayName,
1701
1838
  icon: tab.icon ?? void 0,
1702
1839
  url: Url(metaStr(tab.metadata, "url") ?? ""),
1703
- target: void 0
1840
+ target: metaStr(tab.metadata, "target")
1704
1841
  };
1705
1842
  }
1706
1843
  if (tabType === "changelog") {
@@ -1788,7 +1925,7 @@ function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix) {
1788
1925
  default: detailIsDefault(version),
1789
1926
  versionId: VersionId(version.id),
1790
1927
  availability: void 0,
1791
- landingPage: void 0,
1928
+ landingPage: buildVersionLandingPage(ctx, versionSegs, asSlug(slug)),
1792
1929
  announcement: void 0,
1793
1930
  pointsTo: metaStr(version.metadata, "pointsTo") != null ? pointsToSlug(metaStr(version.metadata, "pointsTo")) : void 0,
1794
1931
  // The version's full slug roots structural sections so the whole
@@ -1800,6 +1937,7 @@ function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix) {
1800
1937
  }
1801
1938
  return node;
1802
1939
  });
1940
+ markCrossVersionCanonicalSlugs(children);
1803
1941
  return {
1804
1942
  type: "versioned",
1805
1943
  id: ctx.nodeId(`versioned:${productPrefix ?? "root"}`),
@@ -1825,6 +1963,111 @@ function markDefaultVersionCanonicalSlugs(node, pruneSlug, versionSlug) {
1825
1963
  return;
1826
1964
  });
1827
1965
  }
1966
+ function unversionedParents(parents) {
1967
+ let versionIdx = -1;
1968
+ for (let i = parents.length - 1; i >= 0; i--) {
1969
+ if (parents[i].type === "version") {
1970
+ versionIdx = i;
1971
+ break;
1972
+ }
1973
+ }
1974
+ return versionIdx >= 0 ? parents.slice(versionIdx + 1) : parents;
1975
+ }
1976
+ function crossVersionDedupKeys(node, parents) {
1977
+ const keys = [];
1978
+ const uParents = unversionedParents(parents);
1979
+ const pid = getPageId(node);
1980
+ if (pid != null) {
1981
+ keys.push(`pid:${pid}`);
1982
+ }
1983
+ if (node.type === "endpoint" || node.type === "webSocket" || node.type === "webhook" || node.type === "grpc" || node.type === "graphql") {
1984
+ const apiParentTitles = uParents.filter(
1985
+ (p) => p.type === "apiReference"
1986
+ ).map((p) => p.title.replaceAll(" ", ""));
1987
+ const apiPrefix = apiParentTitles.join(":");
1988
+ if (node.type === "endpoint") {
1989
+ keys.push(`${apiPrefix}:api:endpoint:${node.method}:${node.endpointId}`);
1990
+ } else if (node.type === "webSocket") {
1991
+ keys.push(`${apiPrefix}:api:websocket:${node.webSocketId}`);
1992
+ } else if (node.type === "webhook") {
1993
+ keys.push(`${apiPrefix}:api:webhook:${node.method}:${node.webhookId}`);
1994
+ } else if (node.type === "grpc") {
1995
+ keys.push(`${apiPrefix}:api:grpc:${node.method}:${node.grpcId}`);
1996
+ } else if (node.type === "graphql") {
1997
+ keys.push(`${apiPrefix}:api:graphql:${node.id}`);
1998
+ }
1999
+ }
2000
+ const parentTitles = [];
2001
+ for (const p of uParents) {
2002
+ if (hasMetadata(p)) {
2003
+ parentTitles.push(p.title);
2004
+ }
2005
+ }
2006
+ keys.push([...parentTitles, node.title].join("###"));
2007
+ return keys;
2008
+ }
2009
+ function buildVersionLandingPage(ctx, versionSegs, versionSlug) {
2010
+ const tablessSegs = versionSegs.filter((s) => s.seg.tab == null);
2011
+ if (tablessSegs.length === 0) {
2012
+ return void 0;
2013
+ }
2014
+ for (const s of tablessSegs) {
2015
+ for (const r of s.nav) {
2016
+ if (r.type === "markdown" && r.fullPath != null) {
2017
+ const md = r.metadata;
2018
+ const pageId = metaStr(md, "pageId") ?? "";
2019
+ const slug = ctx.contentSlug(r.fullPath);
2020
+ return {
2021
+ type: "landingPage",
2022
+ ...withMetadataDefaults({
2023
+ id: ctx.nodeId(`landing:${slug}`),
2024
+ title: metaStr(md, "title") ?? "",
2025
+ slug,
2026
+ icon: metaStr(md, "icon"),
2027
+ hidden: r.hidden,
2028
+ viewers: toViewers(metaStrArr(md, "viewers"))
2029
+ }),
2030
+ pageId: PageId(pageId),
2031
+ noindex: metaBool(md, "noindex")
2032
+ };
2033
+ }
2034
+ }
2035
+ }
2036
+ return void 0;
2037
+ }
2038
+ function markCrossVersionCanonicalSlugs(versionNodes) {
2039
+ const keyToCanonical = /* @__PURE__ */ new Map();
2040
+ const sorted = [...versionNodes].sort((a, b) => {
2041
+ if (a.default !== b.default) {
2042
+ return a.default ? -1 : 1;
2043
+ }
2044
+ return 0;
2045
+ });
2046
+ for (const version of sorted) {
2047
+ traverseDF(version, (child, parents) => {
2048
+ if (hasMetadata(child) && isPage(child)) {
2049
+ const keys = crossVersionDedupKeys(child, parents);
2050
+ let matched = false;
2051
+ for (const key of keys) {
2052
+ const canonical = keyToCanonical.get(key);
2053
+ if (canonical != null && !version.default) {
2054
+ child.canonicalSlug = canonical;
2055
+ matched = true;
2056
+ break;
2057
+ }
2058
+ }
2059
+ if (!matched) {
2060
+ const canonical = child.canonicalSlug ?? child.slug;
2061
+ for (const key of keys) {
2062
+ if (!keyToCanonical.has(key)) {
2063
+ keyToCanonical.set(key, canonical);
2064
+ }
2065
+ }
2066
+ }
2067
+ }
2068
+ });
2069
+ }
2070
+ }
1828
2071
  function buildProductGroup(ctx, products, scoped, rootSlug) {
1829
2072
  const children = products.map((product) => {
1830
2073
  const productSegs = scoped.filter((s) => s.seg.product?.id === product.id);
@@ -1850,7 +2093,7 @@ function buildProductGroup(ctx, products, scoped, rootSlug) {
1850
2093
  // here; sourcing it from the hash makes that filter match nothing.
1851
2094
  productId: ProductId(product.displayName),
1852
2095
  subtitle: metaStr(product.metadata, "subtitle") ?? "",
1853
- image: void 0,
2096
+ image: metaStr(product.metadata, "image") != null ? FileId(metaStr(product.metadata, "image")) : void 0,
1854
2097
  announcement: void 0,
1855
2098
  pointsTo: metaStr(product.metadata, "pointsTo") != null ? pointsToSlug(metaStr(product.metadata, "pointsTo")) : void 0,
1856
2099
  child: productChild