@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
@@ -846,6 +846,14 @@ function traverseDF(node, visit) {
846
846
  }
847
847
 
848
848
  // src/navigation/ledger-root-builder.ts
849
+ var STRUCTURAL_SEGMENT_TYPES = /* @__PURE__ */ new Set([
850
+ "section",
851
+ "apiReference",
852
+ "apiPackage",
853
+ "changelog"
854
+ ]);
855
+ var API_NODE_SEGMENT_TYPES = /* @__PURE__ */ new Set(["apiReference", "apiPackage"]);
856
+ var INFRA_SEGMENT_TYPES = /* @__PURE__ */ new Set(["files", "redirects"]);
849
857
  function createBuildContext(basePath) {
850
858
  const seen = /* @__PURE__ */ new Map();
851
859
  const basePrefix = basePath.replace(/^\/+|\/+$/g, "");
@@ -923,7 +931,7 @@ function toViewers(viewers) {
923
931
  return viewers.map((v) => RoleId(v));
924
932
  }
925
933
  function mergeVariantViewers(seg) {
926
- const segViewers = seg.metadata.type === "section" || seg.metadata.type === "apiReference" || seg.metadata.type === "apiPackage" || seg.metadata.type === "changelog" ? seg.metadata.viewers : void 0;
934
+ const segViewers = STRUCTURAL_SEGMENT_TYPES.has(seg.metadata.type) ? seg.metadata.viewers : void 0;
927
935
  const variantViewers = seg.variant?.viewers;
928
936
  if ((segViewers == null || segViewers.length === 0) && (variantViewers == null || variantViewers.length === 0)) {
929
937
  return void 0;
@@ -1123,6 +1131,63 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
1123
1131
  }
1124
1132
  return void 0;
1125
1133
  }
1134
+ function apiLeafPositionKey(node) {
1135
+ switch (node.type) {
1136
+ case "endpoint":
1137
+ return `endpoint:${node.endpointId}`;
1138
+ case "webhook":
1139
+ return `webhook:${node.webhookId}`;
1140
+ case "webSocket":
1141
+ return `webSocket:${node.webSocketId}`;
1142
+ case "grpc":
1143
+ return `grpc:${node.grpcId}`;
1144
+ case "graphql":
1145
+ return `graphql:${node.graphqlOperationId}`;
1146
+ }
1147
+ }
1148
+ function apiChildPositionKey(node) {
1149
+ switch (node.type) {
1150
+ case "endpoint":
1151
+ case "webhook":
1152
+ case "webSocket":
1153
+ case "grpc":
1154
+ case "graphql":
1155
+ return apiLeafPositionKey(node);
1156
+ default:
1157
+ return void 0;
1158
+ }
1159
+ }
1160
+ function positionedApiLeafChildren(ctx, nav, apiDefinitionId) {
1161
+ const rawLeafNodes = [];
1162
+ const leafPositions = /* @__PURE__ */ new Map();
1163
+ const nonApiLeafNodes = [];
1164
+ for (let i = 0; i < nav.length; i++) {
1165
+ const route = nav[i];
1166
+ const pos = route.displaySortOrder ?? i;
1167
+ const apiLeaf = apiLeafNodeFromNavRouteInternal(ctx, route, apiDefinitionId);
1168
+ if (apiLeaf != null) {
1169
+ rawLeafNodes.push(apiLeaf);
1170
+ const key = apiLeafPositionKey(apiLeaf);
1171
+ leafPositions.set(key, Math.min(leafPositions.get(key) ?? pos, pos));
1172
+ continue;
1173
+ }
1174
+ const node = artifactToNode(ctx, route);
1175
+ if (node?.type === "page" || node?.type === "link") {
1176
+ nonApiLeafNodes.push({ node, pos });
1177
+ }
1178
+ }
1179
+ const apiLeafNodes = mergeEndpointPairs(ctx, rawLeafNodes, nav);
1180
+ const positionedApiLeafNodes = apiLeafNodes.map((node, index) => {
1181
+ if (node.type === "endpointPair") {
1182
+ const streamPos = leafPositions.get(apiLeafPositionKey(node.stream)) ?? index;
1183
+ const nonStreamPos = leafPositions.get(apiLeafPositionKey(node.nonStream)) ?? index;
1184
+ return { node, pos: Math.min(streamPos, nonStreamPos) };
1185
+ }
1186
+ const key = apiChildPositionKey(node);
1187
+ return { node, pos: key != null ? leafPositions.get(key) ?? index : index };
1188
+ });
1189
+ return [...positionedApiLeafNodes, ...nonApiLeafNodes];
1190
+ }
1126
1191
  function collectApiLeafNodesFromNav(routes, basePath, segmentApiDefinitionId2) {
1127
1192
  const ctx = createBuildContext(basePath);
1128
1193
  return routes.map((route) => apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2)).filter((node) => node != null);
@@ -1232,12 +1297,10 @@ function sectionNode(ctx, scoped, sectionChildren, scopePrefix) {
1232
1297
  return {
1233
1298
  type: "section",
1234
1299
  ...defaults,
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,
1300
+ collapsed: metaCollapsed(seg.metadata) ?? defaults.collapsed,
1238
1301
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1239
1302
  noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1240
- collapsible: metaBool(seg.metadata, "collapsible") ?? (metaCollapsed(seg.metadata) != null ? true : void 0),
1303
+ collapsible: metaBool(seg.metadata, "collapsible") ?? (metaCollapsed(seg.metadata) === true ? true : void 0),
1241
1304
  collapsedByDefault: metaBool(seg.metadata, "collapsedByDefault") ?? (metaCollapsed(seg.metadata) === true ? true : void 0),
1242
1305
  availability: metaStr(seg.metadata, "availability"),
1243
1306
  pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
@@ -1262,8 +1325,7 @@ function directChildApiPackages(parentSection, scopeSegs) {
1262
1325
  }
1263
1326
  function buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix) {
1264
1327
  const { seg, nav } = scoped;
1265
- const rawLeafNodes = nav.map((route) => apiLeafNodeFromNavRouteInternal(ctx, route, apiDefinitionId)).filter((node) => node != null);
1266
- const leafNodes = mergeEndpointPairs(ctx, rawLeafNodes, nav);
1328
+ const leafNodes = positionedApiLeafChildren(ctx, nav, apiDefinitionId);
1267
1329
  const childPackages = directChildApiPackages(seg.section, scopeSegs);
1268
1330
  const packageNodes = childPackages.map((child) => ({
1269
1331
  node: apiPackageChildNode(
@@ -1277,18 +1339,10 @@ function buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix)
1277
1339
  }));
1278
1340
  const hasChildIndex = packageNodes.some((p) => p.childIndex != null);
1279
1341
  if (!hasChildIndex) {
1280
- return [...leafNodes, ...packageNodes.map((p) => p.node)];
1281
- }
1282
- const leafPositions = [];
1283
- for (const route of nav) {
1284
- if (route.displaySortOrder != null) {
1285
- leafPositions.push(route.displaySortOrder);
1286
- }
1342
+ return [...leafNodes, ...packageNodes.map((p) => ({ node: p.node, pos: Number.MAX_SAFE_INTEGER }))].sort((a, b) => a.pos - b.pos).map((p) => p.node);
1287
1343
  }
1288
1344
  const positioned = [];
1289
- for (let i = 0; i < leafNodes.length; i++) {
1290
- positioned.push({ node: leafNodes[i], pos: leafPositions[i] ?? i });
1291
- }
1345
+ positioned.push(...leafNodes);
1292
1346
  for (const p of packageNodes) {
1293
1347
  positioned.push({ node: p.node, pos: p.childIndex ?? Number.MAX_SAFE_INTEGER });
1294
1348
  }
@@ -1473,7 +1527,7 @@ function changelogNode(ctx, scoped, scopePrefix) {
1473
1527
  pageId: PageId(metaStr(r.metadata, "pageId") ?? ""),
1474
1528
  noindex: metaBool(r.metadata, "noindex"),
1475
1529
  date: dateStr ?? "",
1476
- tags: void 0
1530
+ tags: metaStrArr(r.metadata, "tags")
1477
1531
  };
1478
1532
  let months = byYear.get(year);
1479
1533
  if (months == null) {
@@ -1565,7 +1619,7 @@ function buildSectionTree(ctx, scopeSegs, parentPath, scopePrefix, changelogScop
1565
1619
  const type = metaStr(s.seg.metadata, "type");
1566
1620
  const childIndex = metaNum(s.seg.metadata, "childIndex");
1567
1621
  let node;
1568
- if (type === "apiReference" || type === "apiPackage") {
1622
+ if (API_NODE_SEGMENT_TYPES.has(type ?? "")) {
1569
1623
  node = apiReferenceNode(ctx, s, scopeSegs, scopePrefix);
1570
1624
  } else if (type === "changelog") {
1571
1625
  node = changelogNode(ctx, s, changelogScopePrefix ?? scopePrefix);
@@ -1580,18 +1634,56 @@ function buildSectionTree(ctx, scopeSegs, parentPath, scopePrefix, changelogScop
1580
1634
  return { node, childIndex };
1581
1635
  });
1582
1636
  }
1637
+ function computeSiblingSortBoundaries(ordered) {
1638
+ const result = /* @__PURE__ */ new Map();
1639
+ const sectionPaths = new Set(ordered.map((s) => s.seg.section));
1640
+ const rootSections = [];
1641
+ for (const s of ordered) {
1642
+ const type = metaStr(s.seg.metadata, "type");
1643
+ const sec = s.seg.section;
1644
+ if (type !== "section" || sec === "") {
1645
+ continue;
1646
+ }
1647
+ const parent = parentSectionPath(sec);
1648
+ const isRootLevel = parent === "" || !sectionPaths.has(parent) && nearestExistingAncestor(sec, sectionPaths) === "";
1649
+ if (isRootLevel) {
1650
+ rootSections.push(s);
1651
+ }
1652
+ }
1653
+ const byPath = /* @__PURE__ */ new Map();
1654
+ for (const s of rootSections) {
1655
+ const group = byPath.get(s.seg.section) ?? [];
1656
+ group.push(s);
1657
+ byPath.set(s.seg.section, group);
1658
+ }
1659
+ for (const [, siblings] of byPath) {
1660
+ if (siblings.length <= 1) {
1661
+ continue;
1662
+ }
1663
+ for (let i = 0; i < siblings.length; i++) {
1664
+ const lo = siblings[i].seg.sortOrder;
1665
+ const hi = i + 1 < siblings.length ? siblings[i + 1].seg.sortOrder : Number.MAX_SAFE_INTEGER;
1666
+ result.set(siblings[i], { lo, hi });
1667
+ }
1668
+ }
1669
+ return result;
1670
+ }
1583
1671
  function buildSidebarRootChildren(ctx, scopeSegs, scopePrefix, changelogScopePrefix) {
1584
1672
  const ordered = [...scopeSegs].sort((a, b) => a.seg.sortOrder - b.seg.sortOrder);
1585
1673
  const sectionPaths = new Set(ordered.map((s) => s.seg.section));
1586
1674
  const annotated = [];
1587
1675
  const hasRootSection = ordered.some((s) => metaStr(s.seg.metadata, "type") === "section" && s.seg.section === "");
1676
+ const siblingBoundaries = computeSiblingSortBoundaries(ordered);
1588
1677
  for (const s of ordered) {
1589
1678
  const type = metaStr(s.seg.metadata, "type");
1590
1679
  const sec = s.seg.section;
1591
1680
  if (hasOwningApiReference(s, scopeSegs)) {
1592
1681
  continue;
1593
1682
  }
1594
- if (type === "tabRoot" || sec === "" && type !== "section") {
1683
+ if (type === "tabRoot" && metaBool(s.seg.metadata, "landingPage") === true) {
1684
+ continue;
1685
+ }
1686
+ if (type === "tabRoot" || sec === "" && !STRUCTURAL_SEGMENT_TYPES.has(type ?? "")) {
1595
1687
  for (const r of s.nav) {
1596
1688
  const node = artifactToNode(ctx, r);
1597
1689
  if (node != null) {
@@ -1608,24 +1700,31 @@ function buildSidebarRootChildren(ctx, scopeSegs, scopePrefix, changelogScopePre
1608
1700
  }
1609
1701
  const parent = parentSectionPath(sec);
1610
1702
  const isRootLevel = parent === "" || !sectionPaths.has(parent) && nearestExistingAncestor(sec, sectionPaths) === "";
1611
- if (isRootLevel && hasRootSection) {
1703
+ if (isRootLevel && hasRootSection && sec !== "") {
1612
1704
  continue;
1613
1705
  }
1614
1706
  if (isRootLevel) {
1615
1707
  let node;
1616
- if (type === "apiReference" || type === "apiPackage") {
1708
+ if (API_NODE_SEGMENT_TYPES.has(type ?? "")) {
1617
1709
  node = apiReferenceNode(ctx, s, scopeSegs, scopePrefix);
1618
1710
  } else if (type === "changelog") {
1619
1711
  node = changelogNode(ctx, s, changelogScopePrefix ?? scopePrefix);
1620
1712
  } else {
1713
+ const bounds = siblingBoundaries.get(s);
1714
+ const ownedSegs = bounds != null ? scopeSegs.filter((seg) => seg.seg.sortOrder >= bounds.lo && seg.seg.sortOrder < bounds.hi) : scopeSegs;
1621
1715
  node = sectionNode(
1622
1716
  ctx,
1623
1717
  s,
1624
- buildSectionTree(ctx, scopeSegs, sec, scopePrefix, changelogScopePrefix),
1718
+ buildSectionTree(ctx, ownedSegs, sec, scopePrefix, changelogScopePrefix),
1625
1719
  scopePrefix
1626
1720
  );
1627
1721
  }
1628
- annotated.push({ node, pos: metaNum(s.seg.metadata, "childIndex"), isLeaf: false });
1722
+ const isSharedSection = siblingBoundaries.size > 0 && scopePrefix !== "" && sec !== "" && !sec.startsWith(scopePrefix);
1723
+ annotated.push({
1724
+ node,
1725
+ pos: isSharedSection ? void 0 : metaNum(s.seg.metadata, "childIndex"),
1726
+ isLeaf: false
1727
+ });
1629
1728
  }
1630
1729
  }
1631
1730
  const hasLeafPos = annotated.some((a) => a.isLeaf && a.pos != null);
@@ -1677,13 +1776,13 @@ function buildSidebarRoot(ctx, scopeSegs, scopePrefix, changelogScopePrefix) {
1677
1776
  };
1678
1777
  }
1679
1778
  function buildFullRootFromSegments(options) {
1680
- const { basePath, title, segments, navBySegment } = options;
1779
+ const { basePath, rootSlug: sourceRootSlug, title, segments, navBySegment, skipSharedSectionMerge } = options;
1681
1780
  const ctx = createBuildContext(basePath);
1682
1781
  const scoped = segments.filter((seg) => {
1683
1782
  const t = metaStr(seg.metadata, "type");
1684
- return t !== "files" && t !== "redirects";
1783
+ return !INFRA_SEGMENT_TYPES.has(t ?? "");
1685
1784
  }).map((seg) => ({ seg, nav: navBySegment.get(seg.segmentHash) ?? [] }));
1686
- const rootSlug = asSlug(basePath);
1785
+ const rootSlug = asSlug(sourceRootSlug ?? basePath);
1687
1786
  const scopesByKey = /* @__PURE__ */ new Map();
1688
1787
  for (const s of scoped) {
1689
1788
  const key = scopeKey(s.seg);
@@ -1696,9 +1795,9 @@ function buildFullRootFromSegments(options) {
1696
1795
  const tabs = uniqueDetails(scoped, "tab");
1697
1796
  let child;
1698
1797
  if (products.length > 0) {
1699
- child = buildProductGroup(ctx, products, scoped, rootSlug);
1798
+ child = buildProductGroup(ctx, products, scoped, rootSlug, skipSharedSectionMerge);
1700
1799
  } else if (versions.length > 0) {
1701
- child = buildVersioned(ctx, versions, scoped, rootSlug, void 0);
1800
+ child = buildVersioned(ctx, versions, scoped, rootSlug, void 0, skipSharedSectionMerge);
1702
1801
  } else {
1703
1802
  child = buildUnversioned(ctx, scoped, rootSlug, tabs.length > 0);
1704
1803
  }
@@ -1805,20 +1904,34 @@ function buildSidebarRootWithVariants(ctx, scopeSegs, scopePrefix, changelogScop
1805
1904
  if (variants.length <= 1) {
1806
1905
  return buildSidebarRoot(ctx, scopeSegs, scopePrefix, changelogScopePrefix);
1807
1906
  }
1907
+ const sharedSegs = scopeSegs.filter((s) => s.seg.variant == null);
1808
1908
  const variantedNode = buildVariantedNode(ctx, variants, scopeSegs, scopePrefix);
1909
+ const sharedChildren = sharedSegs.length > 0 ? buildSidebarRootChildren(ctx, sharedSegs, scopePrefix, changelogScopePrefix) : [];
1809
1910
  const first = scopeSegs[0];
1810
1911
  return {
1811
1912
  type: "sidebarRoot",
1812
1913
  id: ctx.nodeId(`sidebar:${first != null ? scopeKey(first.seg) : "root"}`),
1813
1914
  collapsed: void 0,
1814
- children: [variantedNode]
1915
+ children: [...sharedChildren, variantedNode]
1815
1916
  };
1816
1917
  }
1817
1918
  function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix) {
1818
1919
  if (!tabsPresent) {
1819
1920
  const variants = uniqueDetails(scopeSegs, "variant");
1820
1921
  if (variants.length > 1) {
1821
- return buildVariantedNode(ctx, variants, scopeSegs, scopePrefix);
1922
+ const sharedSegs = scopeSegs.filter((s) => s.seg.variant == null);
1923
+ const variantedNode = buildVariantedNode(ctx, variants, scopeSegs, scopePrefix);
1924
+ if (sharedSegs.length > 0) {
1925
+ const sharedChildren = buildSidebarRootChildren(ctx, sharedSegs, scopePrefix);
1926
+ const first2 = scopeSegs[0];
1927
+ return {
1928
+ type: "sidebarRoot",
1929
+ id: ctx.nodeId(`sidebar:${first2 != null ? scopeKey(first2.seg) : "root"}`),
1930
+ collapsed: void 0,
1931
+ children: [...sharedChildren, variantedNode]
1932
+ };
1933
+ }
1934
+ return variantedNode;
1822
1935
  }
1823
1936
  return buildSidebarRoot(ctx, scopeSegs, scopePrefix);
1824
1937
  }
@@ -1898,16 +2011,71 @@ function buildUnversioned(ctx, scopeSegs, scopePrefix, tabsPresent) {
1898
2011
  type: "unversioned",
1899
2012
  id: ctx.nodeId(`unversioned:${first?.seg.product?.id ?? "root"}`),
1900
2013
  collapsed: void 0,
1901
- landingPage: void 0,
2014
+ landingPage: buildLandingPage(ctx, scopeSegs),
1902
2015
  // The enclosing scope prefix (product slug, or rootSlug at the top
1903
2016
  // level) roots structural sections so they share the scope's slug
1904
2017
  // namespace.
1905
2018
  child: buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix)
1906
2019
  };
1907
2020
  }
1908
- function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix) {
2021
+ function mergeSharedSections(defaultSegs, allScoped, defaultVersion, versionSlugs) {
2022
+ const defaultTabsByName = /* @__PURE__ */ new Map();
2023
+ for (const s of defaultSegs) {
2024
+ if (s.seg.tab != null) {
2025
+ const tabName = s.seg.tab.displayName;
2026
+ if (!defaultTabsByName.has(tabName)) {
2027
+ defaultTabsByName.set(tabName, s.seg.tab);
2028
+ }
2029
+ }
2030
+ }
2031
+ const existingSections = new Set(
2032
+ defaultSegs.filter((s) => metaStr(s.seg.metadata, "type") === "section").map((s) => s.seg.section)
2033
+ );
2034
+ const maxSortOrder = defaultSegs.reduce((max, s) => Math.max(max, s.seg.sortOrder), 0);
2035
+ let nextSortOrder = maxSortOrder + 1;
2036
+ const merged = [...defaultSegs];
2037
+ for (const s of allScoped) {
2038
+ if (s.seg.version?.id === defaultVersion.id) {
2039
+ continue;
2040
+ }
2041
+ const type = metaStr(s.seg.metadata, "type");
2042
+ if (type !== "section") {
2043
+ continue;
2044
+ }
2045
+ const sectionPath = s.seg.section;
2046
+ if (versionSlugs.some((vs) => sectionPath === vs || sectionPath.startsWith(vs + "/"))) {
2047
+ continue;
2048
+ }
2049
+ if (existingSections.has(sectionPath)) {
2050
+ continue;
2051
+ }
2052
+ const sourceTabName = s.seg.tab?.displayName ?? "";
2053
+ const targetTab = defaultTabsByName.get(sourceTabName);
2054
+ if (targetTab == null) {
2055
+ continue;
2056
+ }
2057
+ const metadata = s.seg.metadata != null ? { ...s.seg.metadata, childIndex: void 0 } : s.seg.metadata;
2058
+ merged.push({
2059
+ seg: {
2060
+ ...s.seg,
2061
+ tab: targetTab,
2062
+ version: defaultVersion,
2063
+ sortOrder: nextSortOrder++,
2064
+ metadata
2065
+ },
2066
+ nav: s.nav
2067
+ });
2068
+ existingSections.add(sectionPath);
2069
+ }
2070
+ return merged;
2071
+ }
2072
+ function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix, skipSharedSectionMerge) {
2073
+ const versionSlugs = versions.map((v) => detailSlug(v)).filter((s) => s !== "");
1909
2074
  const children = versions.map((version) => {
1910
- const versionSegs = scoped.filter((s) => s.seg.version?.id === version.id);
2075
+ let versionSegs = scoped.filter((s) => s.seg.version?.id === version.id);
2076
+ if (detailIsDefault(version) && !skipSharedSectionMerge) {
2077
+ versionSegs = mergeSharedSections(versionSegs, scoped, version, versionSlugs);
2078
+ }
1911
2079
  const tabsPresent = uniqueDetails(versionSegs, "tab").length > 0;
1912
2080
  const prefix = productPrefix != null ? productPrefix : rootSlug;
1913
2081
  const versionSegment = detailSlug(version);
@@ -1925,7 +2093,7 @@ function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix) {
1925
2093
  default: detailIsDefault(version),
1926
2094
  versionId: VersionId(version.id),
1927
2095
  availability: void 0,
1928
- landingPage: buildVersionLandingPage(ctx, versionSegs, asSlug(slug)),
2096
+ landingPage: buildLandingPage(ctx, versionSegs),
1929
2097
  announcement: void 0,
1930
2098
  pointsTo: metaStr(version.metadata, "pointsTo") != null ? pointsToSlug(metaStr(version.metadata, "pointsTo")) : void 0,
1931
2099
  // The version's full slug roots structural sections so the whole
@@ -2006,34 +2174,41 @@ function crossVersionDedupKeys(node, parents) {
2006
2174
  keys.push([...parentTitles, node.title].join("###"));
2007
2175
  return keys;
2008
2176
  }
2009
- function buildVersionLandingPage(ctx, versionSegs, versionSlug) {
2010
- const tablessSegs = versionSegs.filter((s) => s.seg.tab == null);
2011
- if (tablessSegs.length === 0) {
2177
+ function routeToLandingPage(ctx, route) {
2178
+ if (route == null || route.type !== "markdown" || route.fullPath == null) {
2012
2179
  return void 0;
2013
2180
  }
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
- }
2181
+ const md = route.metadata;
2182
+ const pageId = metaStr(md, "pageId");
2183
+ if (pageId == null) {
2184
+ return void 0;
2035
2185
  }
2036
- return void 0;
2186
+ const slug = ctx.contentSlug(route.fullPath);
2187
+ return {
2188
+ type: "landingPage",
2189
+ ...withMetadataDefaults({
2190
+ id: ctx.nodeId(`landing:${slug}`),
2191
+ title: metaStr(md, "title") ?? "",
2192
+ slug,
2193
+ icon: metaStr(md, "icon"),
2194
+ hidden: route.hidden,
2195
+ authed: metaBool(md, "authed"),
2196
+ viewers: toViewers(metaStrArr(md, "viewers")),
2197
+ orphaned: metaBool(md, "orphaned"),
2198
+ featureFlags: metaFeatureFlags(md)
2199
+ }),
2200
+ pageId: PageId(pageId),
2201
+ noindex: metaBool(md, "noindex")
2202
+ };
2203
+ }
2204
+ function buildLandingPage(ctx, scopeSegs) {
2205
+ const landingSegment = scopeSegs.find(
2206
+ (s) => metaStr(s.seg.metadata, "type") === "tabRoot" && metaBool(s.seg.metadata, "landingPage") === true
2207
+ );
2208
+ return routeToLandingPage(
2209
+ ctx,
2210
+ landingSegment?.nav.find((route) => route.type === "markdown")
2211
+ );
2037
2212
  }
2038
2213
  function markCrossVersionCanonicalSlugs(versionNodes) {
2039
2214
  const keyToCanonical = /* @__PURE__ */ new Map();
@@ -2068,13 +2243,13 @@ function markCrossVersionCanonicalSlugs(versionNodes) {
2068
2243
  });
2069
2244
  }
2070
2245
  }
2071
- function buildProductGroup(ctx, products, scoped, rootSlug) {
2246
+ function buildProductGroup(ctx, products, scoped, rootSlug, skipSharedSectionMerge) {
2072
2247
  const children = products.map((product) => {
2073
2248
  const productSegs = scoped.filter((s) => s.seg.product?.id === product.id);
2074
2249
  const versions = uniqueDetails(productSegs, "version");
2075
2250
  const tabsPresent = uniqueDetails(productSegs, "tab").length > 0;
2076
2251
  const productPrefix = scopeSlugPrefix(rootSlug, product);
2077
- const productChild = versions.length > 0 ? buildVersioned(ctx, versions, productSegs, rootSlug, productPrefix) : buildUnversioned(ctx, productSegs, asSlug(productPrefix), tabsPresent);
2252
+ const productChild = versions.length > 0 ? buildVersioned(ctx, versions, productSegs, rootSlug, productPrefix, skipSharedSectionMerge) : buildUnversioned(ctx, productSegs, asSlug(productPrefix), tabsPresent);
2078
2253
  const node = {
2079
2254
  type: "product",
2080
2255
  ...withMetadataDefaults({
@@ -2104,7 +2279,10 @@ function buildProductGroup(ctx, products, scoped, rootSlug) {
2104
2279
  type: "productgroup",
2105
2280
  id: ctx.nodeId("productgroup"),
2106
2281
  collapsed: void 0,
2107
- landingPage: void 0,
2282
+ landingPage: buildLandingPage(
2283
+ ctx,
2284
+ scoped.filter((s) => s.seg.product == null)
2285
+ ),
2108
2286
  children
2109
2287
  };
2110
2288
  }