@fern-api/fdr-sdk 1.2.39-4ae10c3282 → 1.2.39-4e8e68c5b4

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.
Files changed (102) hide show
  1. package/dist/js/client/FdrClient.js +1 -0
  2. package/dist/js/client/FdrClient.js.map +1 -1
  3. package/dist/js/client/FdrClient.mjs +1 -0
  4. package/dist/js/client/FdrClient.mjs.map +1 -1
  5. package/dist/js/converters/index.js +4 -9
  6. package/dist/js/converters/index.js.map +1 -1
  7. package/dist/js/converters/index.mjs +4 -9
  8. package/dist/js/converters/index.mjs.map +1 -1
  9. package/dist/js/index.js +5 -9
  10. package/dist/js/index.js.map +1 -1
  11. package/dist/js/index.mjs +5 -9
  12. package/dist/js/index.mjs.map +1 -1
  13. package/dist/js/navigation/index.js +4 -9
  14. package/dist/js/navigation/index.js.map +1 -1
  15. package/dist/js/navigation/index.mjs +4 -9
  16. package/dist/js/navigation/index.mjs.map +1 -1
  17. package/dist/js/navigation/ledger-root-builder.js +241 -63
  18. package/dist/js/navigation/ledger-root-builder.js.map +1 -1
  19. package/dist/js/navigation/ledger-root-builder.mjs +241 -63
  20. package/dist/js/navigation/ledger-root-builder.mjs.map +1 -1
  21. package/dist/js/orpc-client.js +1 -0
  22. package/dist/js/orpc-client.js.map +1 -1
  23. package/dist/js/orpc-client.mjs +1 -0
  24. package/dist/js/orpc-client.mjs.map +1 -1
  25. package/dist/navigation/__test__/findNode.authedRedirect.test.d.ts +2 -0
  26. package/dist/navigation/__test__/findNode.authedRedirect.test.d.ts.map +1 -0
  27. package/dist/navigation/__test__/findNode.authedRedirect.test.js +184 -0
  28. package/dist/navigation/__test__/findNode.authedRedirect.test.js.map +1 -0
  29. package/dist/navigation/__test__/ledger-root-builder.apiReferenceChildren.test.d.ts +2 -0
  30. package/dist/navigation/__test__/ledger-root-builder.apiReferenceChildren.test.d.ts.map +1 -0
  31. package/dist/navigation/__test__/ledger-root-builder.apiReferenceChildren.test.js +85 -0
  32. package/dist/navigation/__test__/ledger-root-builder.apiReferenceChildren.test.js.map +1 -0
  33. package/dist/navigation/__test__/ledger-root-builder.collapsedDeterminism.test.d.ts +2 -0
  34. package/dist/navigation/__test__/ledger-root-builder.collapsedDeterminism.test.d.ts.map +1 -0
  35. package/dist/navigation/__test__/ledger-root-builder.collapsedDeterminism.test.js +85 -0
  36. package/dist/navigation/__test__/ledger-root-builder.collapsedDeterminism.test.js.map +1 -0
  37. package/dist/navigation/__test__/ledger-root-builder.landingPage.test.d.ts +2 -0
  38. package/dist/navigation/__test__/ledger-root-builder.landingPage.test.d.ts.map +1 -0
  39. package/dist/navigation/__test__/ledger-root-builder.landingPage.test.js +82 -0
  40. package/dist/navigation/__test__/ledger-root-builder.landingPage.test.js.map +1 -0
  41. package/dist/navigation/__test__/ledger-root-builder.metadataPreservation.test.d.ts +2 -0
  42. package/dist/navigation/__test__/ledger-root-builder.metadataPreservation.test.d.ts.map +1 -0
  43. package/dist/navigation/__test__/ledger-root-builder.metadataPreservation.test.js +1031 -0
  44. package/dist/navigation/__test__/ledger-root-builder.metadataPreservation.test.js.map +1 -0
  45. package/dist/navigation/__test__/ledger-root-builder.rootChildOrder.test.js +22 -9
  46. package/dist/navigation/__test__/ledger-root-builder.rootChildOrder.test.js.map +1 -1
  47. package/dist/navigation/__test__/ledger-root-builder.rootSlug.test.d.ts +2 -0
  48. package/dist/navigation/__test__/ledger-root-builder.rootSlug.test.d.ts.map +1 -0
  49. package/dist/navigation/__test__/ledger-root-builder.rootSlug.test.js +47 -0
  50. package/dist/navigation/__test__/ledger-root-builder.rootSlug.test.js.map +1 -0
  51. package/dist/navigation/__test__/ledger-root-builder.skipSlugApiReference.test.d.ts +2 -0
  52. package/dist/navigation/__test__/ledger-root-builder.skipSlugApiReference.test.d.ts.map +1 -0
  53. package/dist/navigation/__test__/ledger-root-builder.skipSlugApiReference.test.js +210 -0
  54. package/dist/navigation/__test__/ledger-root-builder.skipSlugApiReference.test.js.map +1 -0
  55. package/dist/navigation/__test__/ledger-root-builder.variantSharedSegments.test.d.ts +2 -0
  56. package/dist/navigation/__test__/ledger-root-builder.variantSharedSegments.test.d.ts.map +1 -0
  57. package/dist/navigation/__test__/ledger-root-builder.variantSharedSegments.test.js +262 -0
  58. package/dist/navigation/__test__/ledger-root-builder.variantSharedSegments.test.js.map +1 -0
  59. package/dist/navigation/ledger-root-builder.d.ts +17 -1
  60. package/dist/navigation/ledger-root-builder.d.ts.map +1 -1
  61. package/dist/navigation/ledger-root-builder.js +318 -80
  62. package/dist/navigation/ledger-root-builder.js.map +1 -1
  63. package/dist/navigation/utils/findNode.d.ts +1 -0
  64. package/dist/navigation/utils/findNode.d.ts.map +1 -1
  65. package/dist/navigation/utils/findNode.js +3 -11
  66. package/dist/navigation/utils/findNode.js.map +1 -1
  67. package/dist/navigation/utils/followRedirect.d.ts.map +1 -1
  68. package/dist/navigation/utils/followRedirect.js +2 -0
  69. package/dist/navigation/utils/followRedirect.js.map +1 -1
  70. package/dist/orpc-client/docs-ledger/contract.d.ts +50 -0
  71. package/dist/orpc-client/docs-ledger/contract.d.ts.map +1 -1
  72. package/dist/orpc-client/docs-ledger/contract.js +1 -0
  73. package/dist/orpc-client/docs-ledger/contract.js.map +1 -1
  74. package/dist/orpc-client/docs-ledger/ledger-manifest.d.ts +12 -0
  75. package/dist/orpc-client/docs-ledger/ledger-manifest.d.ts.map +1 -1
  76. package/dist/tsconfig.tsbuildinfo +1 -1
  77. package/dist/types/navigation/__test__/findNode.authedRedirect.test.d.ts +2 -0
  78. package/dist/types/navigation/__test__/findNode.authedRedirect.test.d.ts.map +1 -0
  79. package/dist/types/navigation/__test__/ledger-root-builder.apiReferenceChildren.test.d.ts +2 -0
  80. package/dist/types/navigation/__test__/ledger-root-builder.apiReferenceChildren.test.d.ts.map +1 -0
  81. package/dist/types/navigation/__test__/ledger-root-builder.collapsedDeterminism.test.d.ts +2 -0
  82. package/dist/types/navigation/__test__/ledger-root-builder.collapsedDeterminism.test.d.ts.map +1 -0
  83. package/dist/types/navigation/__test__/ledger-root-builder.landingPage.test.d.ts +2 -0
  84. package/dist/types/navigation/__test__/ledger-root-builder.landingPage.test.d.ts.map +1 -0
  85. package/dist/types/navigation/__test__/ledger-root-builder.metadataPreservation.test.d.ts +2 -0
  86. package/dist/types/navigation/__test__/ledger-root-builder.metadataPreservation.test.d.ts.map +1 -0
  87. package/dist/types/navigation/__test__/ledger-root-builder.rootSlug.test.d.ts +2 -0
  88. package/dist/types/navigation/__test__/ledger-root-builder.rootSlug.test.d.ts.map +1 -0
  89. package/dist/types/navigation/__test__/ledger-root-builder.skipSlugApiReference.test.d.ts +2 -0
  90. package/dist/types/navigation/__test__/ledger-root-builder.skipSlugApiReference.test.d.ts.map +1 -0
  91. package/dist/types/navigation/__test__/ledger-root-builder.variantSharedSegments.test.d.ts +2 -0
  92. package/dist/types/navigation/__test__/ledger-root-builder.variantSharedSegments.test.d.ts.map +1 -0
  93. package/dist/types/navigation/ledger-root-builder.d.ts +17 -1
  94. package/dist/types/navigation/ledger-root-builder.d.ts.map +1 -1
  95. package/dist/types/navigation/utils/findNode.d.ts +1 -0
  96. package/dist/types/navigation/utils/findNode.d.ts.map +1 -1
  97. package/dist/types/navigation/utils/followRedirect.d.ts.map +1 -1
  98. package/dist/types/orpc-client/docs-ledger/contract.d.ts +50 -0
  99. package/dist/types/orpc-client/docs-ledger/contract.d.ts.map +1 -1
  100. package/dist/types/orpc-client/docs-ledger/ledger-manifest.d.ts +12 -0
  101. package/dist/types/orpc-client/docs-ledger/ledger-manifest.d.ts.map +1 -1
  102. package/package.json +1 -1
@@ -805,6 +805,14 @@ function traverseDF(node, visit) {
805
805
  }
806
806
 
807
807
  // src/navigation/ledger-root-builder.ts
808
+ var STRUCTURAL_SEGMENT_TYPES = /* @__PURE__ */ new Set([
809
+ "section",
810
+ "apiReference",
811
+ "apiPackage",
812
+ "changelog"
813
+ ]);
814
+ var API_NODE_SEGMENT_TYPES = /* @__PURE__ */ new Set(["apiReference", "apiPackage"]);
815
+ var INFRA_SEGMENT_TYPES = /* @__PURE__ */ new Set(["files", "redirects"]);
808
816
  function createBuildContext(basePath) {
809
817
  const seen = /* @__PURE__ */ new Map();
810
818
  const basePrefix = basePath.replace(/^\/+|\/+$/g, "");
@@ -882,7 +890,7 @@ function toViewers(viewers) {
882
890
  return viewers.map((v) => RoleId(v));
883
891
  }
884
892
  function mergeVariantViewers(seg) {
885
- const segViewers = seg.metadata.type === "section" || seg.metadata.type === "apiReference" || seg.metadata.type === "apiPackage" || seg.metadata.type === "changelog" ? seg.metadata.viewers : void 0;
893
+ const segViewers = STRUCTURAL_SEGMENT_TYPES.has(seg.metadata.type) ? seg.metadata.viewers : void 0;
886
894
  const variantViewers = seg.variant?.viewers;
887
895
  if ((segViewers == null || segViewers.length === 0) && (variantViewers == null || variantViewers.length === 0)) {
888
896
  return void 0;
@@ -1082,6 +1090,63 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
1082
1090
  }
1083
1091
  return void 0;
1084
1092
  }
1093
+ function apiLeafPositionKey(node) {
1094
+ switch (node.type) {
1095
+ case "endpoint":
1096
+ return `endpoint:${node.endpointId}`;
1097
+ case "webhook":
1098
+ return `webhook:${node.webhookId}`;
1099
+ case "webSocket":
1100
+ return `webSocket:${node.webSocketId}`;
1101
+ case "grpc":
1102
+ return `grpc:${node.grpcId}`;
1103
+ case "graphql":
1104
+ return `graphql:${node.graphqlOperationId}`;
1105
+ }
1106
+ }
1107
+ function apiChildPositionKey(node) {
1108
+ switch (node.type) {
1109
+ case "endpoint":
1110
+ case "webhook":
1111
+ case "webSocket":
1112
+ case "grpc":
1113
+ case "graphql":
1114
+ return apiLeafPositionKey(node);
1115
+ default:
1116
+ return void 0;
1117
+ }
1118
+ }
1119
+ function positionedApiLeafChildren(ctx, nav, apiDefinitionId) {
1120
+ const rawLeafNodes = [];
1121
+ const leafPositions = /* @__PURE__ */ new Map();
1122
+ const nonApiLeafNodes = [];
1123
+ for (let i = 0; i < nav.length; i++) {
1124
+ const route = nav[i];
1125
+ const pos = route.displaySortOrder ?? i;
1126
+ const apiLeaf = apiLeafNodeFromNavRouteInternal(ctx, route, apiDefinitionId);
1127
+ if (apiLeaf != null) {
1128
+ rawLeafNodes.push(apiLeaf);
1129
+ const key = apiLeafPositionKey(apiLeaf);
1130
+ leafPositions.set(key, Math.min(leafPositions.get(key) ?? pos, pos));
1131
+ continue;
1132
+ }
1133
+ const node = artifactToNode(ctx, route);
1134
+ if (node?.type === "page" || node?.type === "link") {
1135
+ nonApiLeafNodes.push({ node, pos });
1136
+ }
1137
+ }
1138
+ const apiLeafNodes = mergeEndpointPairs(ctx, rawLeafNodes, nav);
1139
+ const positionedApiLeafNodes = apiLeafNodes.map((node, index) => {
1140
+ if (node.type === "endpointPair") {
1141
+ const streamPos = leafPositions.get(apiLeafPositionKey(node.stream)) ?? index;
1142
+ const nonStreamPos = leafPositions.get(apiLeafPositionKey(node.nonStream)) ?? index;
1143
+ return { node, pos: Math.min(streamPos, nonStreamPos) };
1144
+ }
1145
+ const key = apiChildPositionKey(node);
1146
+ return { node, pos: key != null ? leafPositions.get(key) ?? index : index };
1147
+ });
1148
+ return [...positionedApiLeafNodes, ...nonApiLeafNodes];
1149
+ }
1085
1150
  function collectApiLeafNodesFromNav(routes, basePath, segmentApiDefinitionId2) {
1086
1151
  const ctx = createBuildContext(basePath);
1087
1152
  return routes.map((route) => apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2)).filter((node) => node != null);
@@ -1191,12 +1256,10 @@ function sectionNode(ctx, scoped, sectionChildren, scopePrefix) {
1191
1256
  return {
1192
1257
  type: "section",
1193
1258
  ...defaults,
1194
- // V2 convention: collapsed:false in docs.yml maps to "open-by-default"
1195
- // so getInitiallyOpenByDefaultNodes picks it up and the UI starts open.
1196
- collapsed: metaCollapsed(seg.metadata) === false ? "open-by-default" : metaCollapsed(seg.metadata) ?? defaults.collapsed,
1259
+ collapsed: metaCollapsed(seg.metadata) ?? defaults.collapsed,
1197
1260
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1198
1261
  noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1199
- collapsible: metaBool(seg.metadata, "collapsible") ?? (metaCollapsed(seg.metadata) != null ? true : void 0),
1262
+ collapsible: metaBool(seg.metadata, "collapsible") ?? (metaCollapsed(seg.metadata) === true ? true : void 0),
1200
1263
  collapsedByDefault: metaBool(seg.metadata, "collapsedByDefault") ?? (metaCollapsed(seg.metadata) === true ? true : void 0),
1201
1264
  availability: metaStr(seg.metadata, "availability"),
1202
1265
  pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
@@ -1221,8 +1284,7 @@ function directChildApiPackages(parentSection, scopeSegs) {
1221
1284
  }
1222
1285
  function buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix) {
1223
1286
  const { seg, nav } = scoped;
1224
- const rawLeafNodes = nav.map((route) => apiLeafNodeFromNavRouteInternal(ctx, route, apiDefinitionId)).filter((node) => node != null);
1225
- const leafNodes = mergeEndpointPairs(ctx, rawLeafNodes, nav);
1287
+ const leafNodes = positionedApiLeafChildren(ctx, nav, apiDefinitionId);
1226
1288
  const childPackages = directChildApiPackages(seg.section, scopeSegs);
1227
1289
  const packageNodes = childPackages.map((child) => ({
1228
1290
  node: apiPackageChildNode(
@@ -1236,18 +1298,10 @@ function buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix)
1236
1298
  }));
1237
1299
  const hasChildIndex = packageNodes.some((p) => p.childIndex != null);
1238
1300
  if (!hasChildIndex) {
1239
- return [...leafNodes, ...packageNodes.map((p) => p.node)];
1240
- }
1241
- const leafPositions = [];
1242
- for (const route of nav) {
1243
- if (route.displaySortOrder != null) {
1244
- leafPositions.push(route.displaySortOrder);
1245
- }
1301
+ return [...leafNodes, ...packageNodes.map((p) => ({ node: p.node, pos: Number.MAX_SAFE_INTEGER }))].sort((a, b) => a.pos - b.pos).map((p) => p.node);
1246
1302
  }
1247
1303
  const positioned = [];
1248
- for (let i = 0; i < leafNodes.length; i++) {
1249
- positioned.push({ node: leafNodes[i], pos: leafPositions[i] ?? i });
1250
- }
1304
+ positioned.push(...leafNodes);
1251
1305
  for (const p of packageNodes) {
1252
1306
  positioned.push({ node: p.node, pos: p.childIndex ?? Number.MAX_SAFE_INTEGER });
1253
1307
  }
@@ -1432,7 +1486,7 @@ function changelogNode(ctx, scoped, scopePrefix) {
1432
1486
  pageId: PageId(metaStr(r.metadata, "pageId") ?? ""),
1433
1487
  noindex: metaBool(r.metadata, "noindex"),
1434
1488
  date: dateStr ?? "",
1435
- tags: void 0
1489
+ tags: metaStrArr(r.metadata, "tags")
1436
1490
  };
1437
1491
  let months = byYear.get(year);
1438
1492
  if (months == null) {
@@ -1524,7 +1578,7 @@ function buildSectionTree(ctx, scopeSegs, parentPath, scopePrefix, changelogScop
1524
1578
  const type = metaStr(s.seg.metadata, "type");
1525
1579
  const childIndex = metaNum(s.seg.metadata, "childIndex");
1526
1580
  let node;
1527
- if (type === "apiReference" || type === "apiPackage") {
1581
+ if (API_NODE_SEGMENT_TYPES.has(type ?? "")) {
1528
1582
  node = apiReferenceNode(ctx, s, scopeSegs, scopePrefix);
1529
1583
  } else if (type === "changelog") {
1530
1584
  node = changelogNode(ctx, s, changelogScopePrefix ?? scopePrefix);
@@ -1539,18 +1593,56 @@ function buildSectionTree(ctx, scopeSegs, parentPath, scopePrefix, changelogScop
1539
1593
  return { node, childIndex };
1540
1594
  });
1541
1595
  }
1596
+ function computeSiblingSortBoundaries(ordered) {
1597
+ const result = /* @__PURE__ */ new Map();
1598
+ const sectionPaths = new Set(ordered.map((s) => s.seg.section));
1599
+ const rootSections = [];
1600
+ for (const s of ordered) {
1601
+ const type = metaStr(s.seg.metadata, "type");
1602
+ const sec = s.seg.section;
1603
+ if (type !== "section" || sec === "") {
1604
+ continue;
1605
+ }
1606
+ const parent = parentSectionPath(sec);
1607
+ const isRootLevel = parent === "" || !sectionPaths.has(parent) && nearestExistingAncestor(sec, sectionPaths) === "";
1608
+ if (isRootLevel) {
1609
+ rootSections.push(s);
1610
+ }
1611
+ }
1612
+ const byPath = /* @__PURE__ */ new Map();
1613
+ for (const s of rootSections) {
1614
+ const group = byPath.get(s.seg.section) ?? [];
1615
+ group.push(s);
1616
+ byPath.set(s.seg.section, group);
1617
+ }
1618
+ for (const [, siblings] of byPath) {
1619
+ if (siblings.length <= 1) {
1620
+ continue;
1621
+ }
1622
+ for (let i = 0; i < siblings.length; i++) {
1623
+ const lo = siblings[i].seg.sortOrder;
1624
+ const hi = i + 1 < siblings.length ? siblings[i + 1].seg.sortOrder : Number.MAX_SAFE_INTEGER;
1625
+ result.set(siblings[i], { lo, hi });
1626
+ }
1627
+ }
1628
+ return result;
1629
+ }
1542
1630
  function buildSidebarRootChildren(ctx, scopeSegs, scopePrefix, changelogScopePrefix) {
1543
1631
  const ordered = [...scopeSegs].sort((a, b) => a.seg.sortOrder - b.seg.sortOrder);
1544
1632
  const sectionPaths = new Set(ordered.map((s) => s.seg.section));
1545
1633
  const annotated = [];
1546
1634
  const hasRootSection = ordered.some((s) => metaStr(s.seg.metadata, "type") === "section" && s.seg.section === "");
1635
+ const siblingBoundaries = computeSiblingSortBoundaries(ordered);
1547
1636
  for (const s of ordered) {
1548
1637
  const type = metaStr(s.seg.metadata, "type");
1549
1638
  const sec = s.seg.section;
1550
1639
  if (hasOwningApiReference(s, scopeSegs)) {
1551
1640
  continue;
1552
1641
  }
1553
- if (type === "tabRoot" || sec === "" && type !== "section") {
1642
+ if (type === "tabRoot" && metaBool(s.seg.metadata, "landingPage") === true) {
1643
+ continue;
1644
+ }
1645
+ if (type === "tabRoot" || sec === "" && !STRUCTURAL_SEGMENT_TYPES.has(type ?? "")) {
1554
1646
  for (const r of s.nav) {
1555
1647
  const node = artifactToNode(ctx, r);
1556
1648
  if (node != null) {
@@ -1567,24 +1659,31 @@ function buildSidebarRootChildren(ctx, scopeSegs, scopePrefix, changelogScopePre
1567
1659
  }
1568
1660
  const parent = parentSectionPath(sec);
1569
1661
  const isRootLevel = parent === "" || !sectionPaths.has(parent) && nearestExistingAncestor(sec, sectionPaths) === "";
1570
- if (isRootLevel && hasRootSection) {
1662
+ if (isRootLevel && hasRootSection && sec !== "") {
1571
1663
  continue;
1572
1664
  }
1573
1665
  if (isRootLevel) {
1574
1666
  let node;
1575
- if (type === "apiReference" || type === "apiPackage") {
1667
+ if (API_NODE_SEGMENT_TYPES.has(type ?? "")) {
1576
1668
  node = apiReferenceNode(ctx, s, scopeSegs, scopePrefix);
1577
1669
  } else if (type === "changelog") {
1578
1670
  node = changelogNode(ctx, s, changelogScopePrefix ?? scopePrefix);
1579
1671
  } else {
1672
+ const bounds = siblingBoundaries.get(s);
1673
+ const ownedSegs = bounds != null ? scopeSegs.filter((seg) => seg.seg.sortOrder >= bounds.lo && seg.seg.sortOrder < bounds.hi) : scopeSegs;
1580
1674
  node = sectionNode(
1581
1675
  ctx,
1582
1676
  s,
1583
- buildSectionTree(ctx, scopeSegs, sec, scopePrefix, changelogScopePrefix),
1677
+ buildSectionTree(ctx, ownedSegs, sec, scopePrefix, changelogScopePrefix),
1584
1678
  scopePrefix
1585
1679
  );
1586
1680
  }
1587
- annotated.push({ node, pos: metaNum(s.seg.metadata, "childIndex"), isLeaf: false });
1681
+ const isSharedSection = siblingBoundaries.size > 0 && scopePrefix !== "" && sec !== "" && !sec.startsWith(scopePrefix);
1682
+ annotated.push({
1683
+ node,
1684
+ pos: isSharedSection ? void 0 : metaNum(s.seg.metadata, "childIndex"),
1685
+ isLeaf: false
1686
+ });
1588
1687
  }
1589
1688
  }
1590
1689
  const hasLeafPos = annotated.some((a) => a.isLeaf && a.pos != null);
@@ -1636,13 +1735,13 @@ function buildSidebarRoot(ctx, scopeSegs, scopePrefix, changelogScopePrefix) {
1636
1735
  };
1637
1736
  }
1638
1737
  function buildFullRootFromSegments(options) {
1639
- const { basePath, title, segments, navBySegment } = options;
1738
+ const { basePath, rootSlug: sourceRootSlug, title, segments, navBySegment, skipSharedSectionMerge } = options;
1640
1739
  const ctx = createBuildContext(basePath);
1641
1740
  const scoped = segments.filter((seg) => {
1642
1741
  const t = metaStr(seg.metadata, "type");
1643
- return t !== "files" && t !== "redirects";
1742
+ return !INFRA_SEGMENT_TYPES.has(t ?? "");
1644
1743
  }).map((seg) => ({ seg, nav: navBySegment.get(seg.segmentHash) ?? [] }));
1645
- const rootSlug = asSlug(basePath);
1744
+ const rootSlug = asSlug(sourceRootSlug ?? basePath);
1646
1745
  const scopesByKey = /* @__PURE__ */ new Map();
1647
1746
  for (const s of scoped) {
1648
1747
  const key = scopeKey(s.seg);
@@ -1655,9 +1754,9 @@ function buildFullRootFromSegments(options) {
1655
1754
  const tabs = uniqueDetails(scoped, "tab");
1656
1755
  let child;
1657
1756
  if (products.length > 0) {
1658
- child = buildProductGroup(ctx, products, scoped, rootSlug);
1757
+ child = buildProductGroup(ctx, products, scoped, rootSlug, skipSharedSectionMerge);
1659
1758
  } else if (versions.length > 0) {
1660
- child = buildVersioned(ctx, versions, scoped, rootSlug, void 0);
1759
+ child = buildVersioned(ctx, versions, scoped, rootSlug, void 0, skipSharedSectionMerge);
1661
1760
  } else {
1662
1761
  child = buildUnversioned(ctx, scoped, rootSlug, tabs.length > 0);
1663
1762
  }
@@ -1764,20 +1863,34 @@ function buildSidebarRootWithVariants(ctx, scopeSegs, scopePrefix, changelogScop
1764
1863
  if (variants.length <= 1) {
1765
1864
  return buildSidebarRoot(ctx, scopeSegs, scopePrefix, changelogScopePrefix);
1766
1865
  }
1866
+ const sharedSegs = scopeSegs.filter((s) => s.seg.variant == null);
1767
1867
  const variantedNode = buildVariantedNode(ctx, variants, scopeSegs, scopePrefix);
1868
+ const sharedChildren = sharedSegs.length > 0 ? buildSidebarRootChildren(ctx, sharedSegs, scopePrefix, changelogScopePrefix) : [];
1768
1869
  const first = scopeSegs[0];
1769
1870
  return {
1770
1871
  type: "sidebarRoot",
1771
1872
  id: ctx.nodeId(`sidebar:${first != null ? scopeKey(first.seg) : "root"}`),
1772
1873
  collapsed: void 0,
1773
- children: [variantedNode]
1874
+ children: [...sharedChildren, variantedNode]
1774
1875
  };
1775
1876
  }
1776
1877
  function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix) {
1777
1878
  if (!tabsPresent) {
1778
1879
  const variants = uniqueDetails(scopeSegs, "variant");
1779
1880
  if (variants.length > 1) {
1780
- return buildVariantedNode(ctx, variants, scopeSegs, scopePrefix);
1881
+ const sharedSegs = scopeSegs.filter((s) => s.seg.variant == null);
1882
+ const variantedNode = buildVariantedNode(ctx, variants, scopeSegs, scopePrefix);
1883
+ if (sharedSegs.length > 0) {
1884
+ const sharedChildren = buildSidebarRootChildren(ctx, sharedSegs, scopePrefix);
1885
+ const first2 = scopeSegs[0];
1886
+ return {
1887
+ type: "sidebarRoot",
1888
+ id: ctx.nodeId(`sidebar:${first2 != null ? scopeKey(first2.seg) : "root"}`),
1889
+ collapsed: void 0,
1890
+ children: [...sharedChildren, variantedNode]
1891
+ };
1892
+ }
1893
+ return variantedNode;
1781
1894
  }
1782
1895
  return buildSidebarRoot(ctx, scopeSegs, scopePrefix);
1783
1896
  }
@@ -1857,16 +1970,71 @@ function buildUnversioned(ctx, scopeSegs, scopePrefix, tabsPresent) {
1857
1970
  type: "unversioned",
1858
1971
  id: ctx.nodeId(`unversioned:${first?.seg.product?.id ?? "root"}`),
1859
1972
  collapsed: void 0,
1860
- landingPage: void 0,
1973
+ landingPage: buildLandingPage(ctx, scopeSegs),
1861
1974
  // The enclosing scope prefix (product slug, or rootSlug at the top
1862
1975
  // level) roots structural sections so they share the scope's slug
1863
1976
  // namespace.
1864
1977
  child: buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix)
1865
1978
  };
1866
1979
  }
1867
- function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix) {
1980
+ function mergeSharedSections(defaultSegs, allScoped, defaultVersion, versionSlugs) {
1981
+ const defaultTabsByName = /* @__PURE__ */ new Map();
1982
+ for (const s of defaultSegs) {
1983
+ if (s.seg.tab != null) {
1984
+ const tabName = s.seg.tab.displayName;
1985
+ if (!defaultTabsByName.has(tabName)) {
1986
+ defaultTabsByName.set(tabName, s.seg.tab);
1987
+ }
1988
+ }
1989
+ }
1990
+ const existingSections = new Set(
1991
+ defaultSegs.filter((s) => metaStr(s.seg.metadata, "type") === "section").map((s) => s.seg.section)
1992
+ );
1993
+ const maxSortOrder = defaultSegs.reduce((max, s) => Math.max(max, s.seg.sortOrder), 0);
1994
+ let nextSortOrder = maxSortOrder + 1;
1995
+ const merged = [...defaultSegs];
1996
+ for (const s of allScoped) {
1997
+ if (s.seg.version?.id === defaultVersion.id) {
1998
+ continue;
1999
+ }
2000
+ const type = metaStr(s.seg.metadata, "type");
2001
+ if (type !== "section") {
2002
+ continue;
2003
+ }
2004
+ const sectionPath = s.seg.section;
2005
+ if (versionSlugs.some((vs) => sectionPath === vs || sectionPath.startsWith(vs + "/"))) {
2006
+ continue;
2007
+ }
2008
+ if (existingSections.has(sectionPath)) {
2009
+ continue;
2010
+ }
2011
+ const sourceTabName = s.seg.tab?.displayName ?? "";
2012
+ const targetTab = defaultTabsByName.get(sourceTabName);
2013
+ if (targetTab == null) {
2014
+ continue;
2015
+ }
2016
+ const metadata = s.seg.metadata != null ? { ...s.seg.metadata, childIndex: void 0 } : s.seg.metadata;
2017
+ merged.push({
2018
+ seg: {
2019
+ ...s.seg,
2020
+ tab: targetTab,
2021
+ version: defaultVersion,
2022
+ sortOrder: nextSortOrder++,
2023
+ metadata
2024
+ },
2025
+ nav: s.nav
2026
+ });
2027
+ existingSections.add(sectionPath);
2028
+ }
2029
+ return merged;
2030
+ }
2031
+ function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix, skipSharedSectionMerge) {
2032
+ const versionSlugs = versions.map((v) => detailSlug(v)).filter((s) => s !== "");
1868
2033
  const children = versions.map((version) => {
1869
- const versionSegs = scoped.filter((s) => s.seg.version?.id === version.id);
2034
+ let versionSegs = scoped.filter((s) => s.seg.version?.id === version.id);
2035
+ if (detailIsDefault(version) && !skipSharedSectionMerge) {
2036
+ versionSegs = mergeSharedSections(versionSegs, scoped, version, versionSlugs);
2037
+ }
1870
2038
  const tabsPresent = uniqueDetails(versionSegs, "tab").length > 0;
1871
2039
  const prefix = productPrefix != null ? productPrefix : rootSlug;
1872
2040
  const versionSegment = detailSlug(version);
@@ -1884,7 +2052,7 @@ function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix) {
1884
2052
  default: detailIsDefault(version),
1885
2053
  versionId: VersionId(version.id),
1886
2054
  availability: void 0,
1887
- landingPage: buildVersionLandingPage(ctx, versionSegs, asSlug(slug)),
2055
+ landingPage: buildLandingPage(ctx, versionSegs),
1888
2056
  announcement: void 0,
1889
2057
  pointsTo: metaStr(version.metadata, "pointsTo") != null ? pointsToSlug(metaStr(version.metadata, "pointsTo")) : void 0,
1890
2058
  // The version's full slug roots structural sections so the whole
@@ -1965,34 +2133,41 @@ function crossVersionDedupKeys(node, parents) {
1965
2133
  keys.push([...parentTitles, node.title].join("###"));
1966
2134
  return keys;
1967
2135
  }
1968
- function buildVersionLandingPage(ctx, versionSegs, versionSlug) {
1969
- const tablessSegs = versionSegs.filter((s) => s.seg.tab == null);
1970
- if (tablessSegs.length === 0) {
2136
+ function routeToLandingPage(ctx, route) {
2137
+ if (route == null || route.type !== "markdown" || route.fullPath == null) {
1971
2138
  return void 0;
1972
2139
  }
1973
- for (const s of tablessSegs) {
1974
- for (const r of s.nav) {
1975
- if (r.type === "markdown" && r.fullPath != null) {
1976
- const md = r.metadata;
1977
- const pageId = metaStr(md, "pageId") ?? "";
1978
- const slug = ctx.contentSlug(r.fullPath);
1979
- return {
1980
- type: "landingPage",
1981
- ...withMetadataDefaults({
1982
- id: ctx.nodeId(`landing:${slug}`),
1983
- title: metaStr(md, "title") ?? "",
1984
- slug,
1985
- icon: metaStr(md, "icon"),
1986
- hidden: r.hidden,
1987
- viewers: toViewers(metaStrArr(md, "viewers"))
1988
- }),
1989
- pageId: PageId(pageId),
1990
- noindex: metaBool(md, "noindex")
1991
- };
1992
- }
1993
- }
2140
+ const md = route.metadata;
2141
+ const pageId = metaStr(md, "pageId");
2142
+ if (pageId == null) {
2143
+ return void 0;
1994
2144
  }
1995
- return void 0;
2145
+ const slug = ctx.contentSlug(route.fullPath);
2146
+ return {
2147
+ type: "landingPage",
2148
+ ...withMetadataDefaults({
2149
+ id: ctx.nodeId(`landing:${slug}`),
2150
+ title: metaStr(md, "title") ?? "",
2151
+ slug,
2152
+ icon: metaStr(md, "icon"),
2153
+ hidden: route.hidden,
2154
+ authed: metaBool(md, "authed"),
2155
+ viewers: toViewers(metaStrArr(md, "viewers")),
2156
+ orphaned: metaBool(md, "orphaned"),
2157
+ featureFlags: metaFeatureFlags(md)
2158
+ }),
2159
+ pageId: PageId(pageId),
2160
+ noindex: metaBool(md, "noindex")
2161
+ };
2162
+ }
2163
+ function buildLandingPage(ctx, scopeSegs) {
2164
+ const landingSegment = scopeSegs.find(
2165
+ (s) => metaStr(s.seg.metadata, "type") === "tabRoot" && metaBool(s.seg.metadata, "landingPage") === true
2166
+ );
2167
+ return routeToLandingPage(
2168
+ ctx,
2169
+ landingSegment?.nav.find((route) => route.type === "markdown")
2170
+ );
1996
2171
  }
1997
2172
  function markCrossVersionCanonicalSlugs(versionNodes) {
1998
2173
  const keyToCanonical = /* @__PURE__ */ new Map();
@@ -2027,13 +2202,13 @@ function markCrossVersionCanonicalSlugs(versionNodes) {
2027
2202
  });
2028
2203
  }
2029
2204
  }
2030
- function buildProductGroup(ctx, products, scoped, rootSlug) {
2205
+ function buildProductGroup(ctx, products, scoped, rootSlug, skipSharedSectionMerge) {
2031
2206
  const children = products.map((product) => {
2032
2207
  const productSegs = scoped.filter((s) => s.seg.product?.id === product.id);
2033
2208
  const versions = uniqueDetails(productSegs, "version");
2034
2209
  const tabsPresent = uniqueDetails(productSegs, "tab").length > 0;
2035
2210
  const productPrefix = scopeSlugPrefix(rootSlug, product);
2036
- const productChild = versions.length > 0 ? buildVersioned(ctx, versions, productSegs, rootSlug, productPrefix) : buildUnversioned(ctx, productSegs, asSlug(productPrefix), tabsPresent);
2211
+ const productChild = versions.length > 0 ? buildVersioned(ctx, versions, productSegs, rootSlug, productPrefix, skipSharedSectionMerge) : buildUnversioned(ctx, productSegs, asSlug(productPrefix), tabsPresent);
2037
2212
  const node = {
2038
2213
  type: "product",
2039
2214
  ...withMetadataDefaults({
@@ -2063,7 +2238,10 @@ function buildProductGroup(ctx, products, scoped, rootSlug) {
2063
2238
  type: "productgroup",
2064
2239
  id: ctx.nodeId("productgroup"),
2065
2240
  collapsed: void 0,
2066
- landingPage: void 0,
2241
+ landingPage: buildLandingPage(
2242
+ ctx,
2243
+ scoped.filter((s) => s.seg.product == null)
2244
+ ),
2067
2245
  children
2068
2246
  };
2069
2247
  }