@fern-api/fdr-sdk 1.2.38-cc77d6a840 → 1.2.39-4f09cc17dc

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,20 @@ 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
1235
  collapsed: metaCollapsed(seg.metadata) ?? defaults.collapsed,
1145
1236
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1146
- noindex: void 0,
1237
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1147
1238
  collapsible: metaBool(seg.metadata, "collapsible") ?? (metaCollapsed(seg.metadata) != null ? true : void 0),
1148
1239
  collapsedByDefault: metaBool(seg.metadata, "collapsedByDefault") ?? (metaCollapsed(seg.metadata) === true ? true : void 0),
1149
- availability: void 0,
1240
+ availability: metaStr(seg.metadata, "availability"),
1150
1241
  pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1151
1242
  children: mergeChildrenByPosition(ctx, nav, sectionChildren)
1152
1243
  };
@@ -1207,7 +1298,12 @@ function apiPackageChildNode(ctx, scoped, scopeSegs, parentApiDefinitionId, scop
1207
1298
  const overview = overviewRoute(nav);
1208
1299
  const overviewPageId = overview != null ? metaStr(overview.metadata, "pageId") : void 0;
1209
1300
  const apiDefinitionId = metaStr(seg.metadata, "apiDefinitionId") ?? parentApiDefinitionId;
1210
- const slug = structuralNodeSlug(ctx, overview?.fullPath, seg.section, scopePrefix);
1301
+ const slug = structuralNodeSlug(
1302
+ ctx,
1303
+ overview?.fullPath,
1304
+ stripLeadingScopePrefix(seg.section, scopePrefix),
1305
+ scopePrefix
1306
+ );
1211
1307
  const metaPointsTo = metaStr(seg.metadata, "pointsTo");
1212
1308
  const children = buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix);
1213
1309
  return {
@@ -1218,12 +1314,15 @@ function apiPackageChildNode(ctx, scoped, scopeSegs, parentApiDefinitionId, scop
1218
1314
  slug,
1219
1315
  icon: metaStr(seg.metadata, "icon"),
1220
1316
  hidden: seg.hidden,
1221
- viewers: toViewers(metaStrArr(seg.metadata, "viewers"))
1317
+ authed: metaBool(seg.metadata, "authed"),
1318
+ viewers: toViewers(metaStrArr(seg.metadata, "viewers")),
1319
+ orphaned: metaBool(seg.metadata, "orphaned"),
1320
+ featureFlags: metaFeatureFlags(seg.metadata)
1222
1321
  }),
1223
1322
  apiDefinitionId: ApiDefinitionId(apiDefinitionId),
1224
1323
  availability: metaStr(seg.metadata, "availability"),
1225
1324
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1226
- noindex: void 0,
1325
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1227
1326
  pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1228
1327
  children,
1229
1328
  playground: void 0
@@ -1286,7 +1385,12 @@ function apiReferenceNode(ctx, scoped, scopeSegs, scopePrefix) {
1286
1385
  const overview = overviewRoute(nav);
1287
1386
  const overviewPageId = overview != null ? metaStr(overview.metadata, "pageId") : void 0;
1288
1387
  const apiDefinitionId = metaStr(seg.metadata, "apiDefinitionId") ?? "";
1289
- const slug = structuralNodeSlug(ctx, overview?.fullPath, seg.section, scopePrefix);
1388
+ const slug = structuralNodeSlug(
1389
+ ctx,
1390
+ overview?.fullPath,
1391
+ stripLeadingScopePrefix(seg.section, scopePrefix),
1392
+ scopePrefix
1393
+ );
1290
1394
  const metaPointsTo = metaStr(seg.metadata, "pointsTo");
1291
1395
  const children = buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix);
1292
1396
  const changelog = attachedApiChangelogNode(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix);
@@ -1298,12 +1402,15 @@ function apiReferenceNode(ctx, scoped, scopeSegs, scopePrefix) {
1298
1402
  slug,
1299
1403
  icon: metaStr(seg.metadata, "icon"),
1300
1404
  hidden: seg.hidden,
1301
- viewers: mergeVariantViewers(seg)
1405
+ authed: metaBool(seg.metadata, "authed"),
1406
+ viewers: mergeVariantViewers(seg),
1407
+ orphaned: metaBool(seg.metadata, "orphaned"),
1408
+ featureFlags: metaFeatureFlags(seg.metadata)
1302
1409
  }),
1303
1410
  apiDefinitionId: ApiDefinitionId(apiDefinitionId),
1304
- availability: void 0,
1411
+ availability: metaStr(seg.metadata, "availability"),
1305
1412
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1306
- noindex: void 0,
1413
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1307
1414
  paginated: true,
1308
1415
  showErrors: metaBool(seg.metadata, "showErrors"),
1309
1416
  hideTitle: metaBool(seg.metadata, "hideTitle"),
@@ -1356,10 +1463,13 @@ function changelogNode(ctx, scoped, scopePrefix) {
1356
1463
  slug: ctx.contentSlug(r.fullPath ?? ""),
1357
1464
  icon: metaStr(r.metadata, "icon"),
1358
1465
  hidden: r.hidden,
1359
- viewers: toViewers(metaStrArr(r.metadata, "viewers"))
1466
+ authed: metaBool(r.metadata, "authed"),
1467
+ viewers: toViewers(metaStrArr(r.metadata, "viewers")),
1468
+ orphaned: metaBool(r.metadata, "orphaned"),
1469
+ featureFlags: metaFeatureFlags(r.metadata)
1360
1470
  }),
1361
1471
  pageId: PageId(metaStr(r.metadata, "pageId") ?? ""),
1362
- noindex: void 0,
1472
+ noindex: metaBool(r.metadata, "noindex"),
1363
1473
  date: dateStr ?? "",
1364
1474
  tags: void 0
1365
1475
  };
@@ -1405,10 +1515,13 @@ function changelogNode(ctx, scoped, scopePrefix) {
1405
1515
  slug: baseSlug,
1406
1516
  icon: metaStr(seg.metadata, "icon"),
1407
1517
  hidden: seg.hidden,
1408
- viewers: mergeVariantViewers(seg)
1518
+ authed: metaBool(seg.metadata, "authed"),
1519
+ viewers: mergeVariantViewers(seg),
1520
+ orphaned: metaBool(seg.metadata, "orphaned"),
1521
+ featureFlags: metaFeatureFlags(seg.metadata)
1409
1522
  }),
1410
1523
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1411
- noindex: void 0,
1524
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1412
1525
  children: years
1413
1526
  };
1414
1527
  }
@@ -1594,6 +1707,24 @@ function buildFullRootFromSegments(options) {
1594
1707
  } else if (child.type === "versioned") {
1595
1708
  const defaultVersion = child.children.find((v) => v.default) ?? child.children[0];
1596
1709
  rootPointsTo = defaultVersion?.pointsTo;
1710
+ } else if (child.type === "unversioned") {
1711
+ if (tabs.length > 0) {
1712
+ const firstTab = tabs[0];
1713
+ const pt = firstTab != null ? metaStr(firstTab.metadata, "pointsTo") : void 0;
1714
+ rootPointsTo = pt != null ? pointsToSlug(pt) : void 0;
1715
+ } else {
1716
+ const sorted = [...scoped].sort((a, b) => a.seg.sortOrder - b.seg.sortOrder);
1717
+ for (const s of sorted) {
1718
+ if (s.seg.hidden) {
1719
+ continue;
1720
+ }
1721
+ const pt = metaStr(s.seg.metadata, "pointsTo");
1722
+ if (pt != null) {
1723
+ rootPointsTo = pointsToSlug(pt);
1724
+ break;
1725
+ }
1726
+ }
1727
+ }
1597
1728
  }
1598
1729
  const root = {
1599
1730
  type: "root",
@@ -1654,7 +1785,7 @@ function buildVariantedNode(ctx, variants, scopeSegs, scopePrefix) {
1654
1785
  default: detailIsDefault(variant),
1655
1786
  variantId: VariantId(String(variant.id)),
1656
1787
  subtitle: metaStr(variant.metadata, "subtitle") ?? void 0,
1657
- image: void 0,
1788
+ image: metaStr(variant.metadata, "image") != null ? FileId(metaStr(variant.metadata, "image")) : void 0,
1658
1789
  pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1659
1790
  children
1660
1791
  };
@@ -1691,7 +1822,10 @@ function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix) {
1691
1822
  const tabDetails = uniqueDetails(scopeSegs, "tab");
1692
1823
  const children = tabDetails.map((tab) => {
1693
1824
  const tabType = metaStr(tab.metadata, "tab_type");
1694
- const tabSlug = asSlug(scopeSlugPrefix(scopePrefix, tab));
1825
+ const rawTabSlug = detailSlug(tab);
1826
+ const versionDetail = scopeSegs[0]?.seg.version;
1827
+ const versionSlugStr = versionDetail != null ? detailSlug(versionDetail) : void 0;
1828
+ const tabSlug = versionSlugStr != null && rawTabSlug !== "" && (rawTabSlug === versionSlugStr || rawTabSlug.startsWith(versionSlugStr + "/")) ? asSlug(rawTabSlug) : asSlug(scopeSlugPrefix(scopePrefix, tab));
1695
1829
  if (tabType === "link") {
1696
1830
  return {
1697
1831
  type: "link",
@@ -1700,7 +1834,7 @@ function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix) {
1700
1834
  title: tab.displayName,
1701
1835
  icon: tab.icon ?? void 0,
1702
1836
  url: Url(metaStr(tab.metadata, "url") ?? ""),
1703
- target: void 0
1837
+ target: metaStr(tab.metadata, "target")
1704
1838
  };
1705
1839
  }
1706
1840
  if (tabType === "changelog") {
@@ -1788,7 +1922,7 @@ function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix) {
1788
1922
  default: detailIsDefault(version),
1789
1923
  versionId: VersionId(version.id),
1790
1924
  availability: void 0,
1791
- landingPage: void 0,
1925
+ landingPage: buildVersionLandingPage(ctx, versionSegs, asSlug(slug)),
1792
1926
  announcement: void 0,
1793
1927
  pointsTo: metaStr(version.metadata, "pointsTo") != null ? pointsToSlug(metaStr(version.metadata, "pointsTo")) : void 0,
1794
1928
  // The version's full slug roots structural sections so the whole
@@ -1800,6 +1934,7 @@ function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix) {
1800
1934
  }
1801
1935
  return node;
1802
1936
  });
1937
+ markCrossVersionCanonicalSlugs(children);
1803
1938
  return {
1804
1939
  type: "versioned",
1805
1940
  id: ctx.nodeId(`versioned:${productPrefix ?? "root"}`),
@@ -1825,6 +1960,111 @@ function markDefaultVersionCanonicalSlugs(node, pruneSlug, versionSlug) {
1825
1960
  return;
1826
1961
  });
1827
1962
  }
1963
+ function unversionedParents(parents) {
1964
+ let versionIdx = -1;
1965
+ for (let i = parents.length - 1; i >= 0; i--) {
1966
+ if (parents[i].type === "version") {
1967
+ versionIdx = i;
1968
+ break;
1969
+ }
1970
+ }
1971
+ return versionIdx >= 0 ? parents.slice(versionIdx + 1) : parents;
1972
+ }
1973
+ function crossVersionDedupKeys(node, parents) {
1974
+ const keys = [];
1975
+ const uParents = unversionedParents(parents);
1976
+ const pid = getPageId(node);
1977
+ if (pid != null) {
1978
+ keys.push(`pid:${pid}`);
1979
+ }
1980
+ if (node.type === "endpoint" || node.type === "webSocket" || node.type === "webhook" || node.type === "grpc" || node.type === "graphql") {
1981
+ const apiParentTitles = uParents.filter(
1982
+ (p) => p.type === "apiReference"
1983
+ ).map((p) => p.title.replaceAll(" ", ""));
1984
+ const apiPrefix = apiParentTitles.join(":");
1985
+ if (node.type === "endpoint") {
1986
+ keys.push(`${apiPrefix}:api:endpoint:${node.method}:${node.endpointId}`);
1987
+ } else if (node.type === "webSocket") {
1988
+ keys.push(`${apiPrefix}:api:websocket:${node.webSocketId}`);
1989
+ } else if (node.type === "webhook") {
1990
+ keys.push(`${apiPrefix}:api:webhook:${node.method}:${node.webhookId}`);
1991
+ } else if (node.type === "grpc") {
1992
+ keys.push(`${apiPrefix}:api:grpc:${node.method}:${node.grpcId}`);
1993
+ } else if (node.type === "graphql") {
1994
+ keys.push(`${apiPrefix}:api:graphql:${node.id}`);
1995
+ }
1996
+ }
1997
+ const parentTitles = [];
1998
+ for (const p of uParents) {
1999
+ if (hasMetadata(p)) {
2000
+ parentTitles.push(p.title);
2001
+ }
2002
+ }
2003
+ keys.push([...parentTitles, node.title].join("###"));
2004
+ return keys;
2005
+ }
2006
+ function buildVersionLandingPage(ctx, versionSegs, versionSlug) {
2007
+ const tablessSegs = versionSegs.filter((s) => s.seg.tab == null);
2008
+ if (tablessSegs.length === 0) {
2009
+ return void 0;
2010
+ }
2011
+ for (const s of tablessSegs) {
2012
+ for (const r of s.nav) {
2013
+ if (r.type === "markdown" && r.fullPath != null) {
2014
+ const md = r.metadata;
2015
+ const pageId = metaStr(md, "pageId") ?? "";
2016
+ const slug = ctx.contentSlug(r.fullPath);
2017
+ return {
2018
+ type: "landingPage",
2019
+ ...withMetadataDefaults({
2020
+ id: ctx.nodeId(`landing:${slug}`),
2021
+ title: metaStr(md, "title") ?? "",
2022
+ slug,
2023
+ icon: metaStr(md, "icon"),
2024
+ hidden: r.hidden,
2025
+ viewers: toViewers(metaStrArr(md, "viewers"))
2026
+ }),
2027
+ pageId: PageId(pageId),
2028
+ noindex: metaBool(md, "noindex")
2029
+ };
2030
+ }
2031
+ }
2032
+ }
2033
+ return void 0;
2034
+ }
2035
+ function markCrossVersionCanonicalSlugs(versionNodes) {
2036
+ const keyToCanonical = /* @__PURE__ */ new Map();
2037
+ const sorted = [...versionNodes].sort((a, b) => {
2038
+ if (a.default !== b.default) {
2039
+ return a.default ? -1 : 1;
2040
+ }
2041
+ return 0;
2042
+ });
2043
+ for (const version of sorted) {
2044
+ traverseDF(version, (child, parents) => {
2045
+ if (hasMetadata(child) && isPage(child)) {
2046
+ const keys = crossVersionDedupKeys(child, parents);
2047
+ let matched = false;
2048
+ for (const key of keys) {
2049
+ const canonical = keyToCanonical.get(key);
2050
+ if (canonical != null && !version.default) {
2051
+ child.canonicalSlug = canonical;
2052
+ matched = true;
2053
+ break;
2054
+ }
2055
+ }
2056
+ if (!matched) {
2057
+ const canonical = child.canonicalSlug ?? child.slug;
2058
+ for (const key of keys) {
2059
+ if (!keyToCanonical.has(key)) {
2060
+ keyToCanonical.set(key, canonical);
2061
+ }
2062
+ }
2063
+ }
2064
+ }
2065
+ });
2066
+ }
2067
+ }
1828
2068
  function buildProductGroup(ctx, products, scoped, rootSlug) {
1829
2069
  const children = products.map((product) => {
1830
2070
  const productSegs = scoped.filter((s) => s.seg.product?.id === product.id);
@@ -1850,7 +2090,7 @@ function buildProductGroup(ctx, products, scoped, rootSlug) {
1850
2090
  // here; sourcing it from the hash makes that filter match nothing.
1851
2091
  productId: ProductId(product.displayName),
1852
2092
  subtitle: metaStr(product.metadata, "subtitle") ?? "",
1853
- image: void 0,
2093
+ image: metaStr(product.metadata, "image") != null ? FileId(metaStr(product.metadata, "image")) : void 0,
1854
2094
  announcement: void 0,
1855
2095
  pointsTo: metaStr(product.metadata, "pointsTo") != null ? pointsToSlug(metaStr(product.metadata, "pointsTo")) : void 0,
1856
2096
  child: productChild