@fern-api/fdr-sdk 1.2.39-38c6f9a29c → 1.2.39-438fcc7e23

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 (36) hide show
  1. package/dist/js/client/FdrClient.js +28 -7
  2. package/dist/js/client/FdrClient.js.map +1 -1
  3. package/dist/js/client/FdrClient.mjs +28 -7
  4. package/dist/js/client/FdrClient.mjs.map +1 -1
  5. package/dist/js/index.js +28 -7
  6. package/dist/js/index.js.map +1 -1
  7. package/dist/js/index.mjs +28 -7
  8. package/dist/js/index.mjs.map +1 -1
  9. package/dist/js/navigation/ledger-root-builder.js +294 -84
  10. package/dist/js/navigation/ledger-root-builder.js.map +1 -1
  11. package/dist/js/navigation/ledger-root-builder.mjs +294 -84
  12. package/dist/js/navigation/ledger-root-builder.mjs.map +1 -1
  13. package/dist/js/orpc-client.js +30 -7
  14. package/dist/js/orpc-client.js.map +1 -1
  15. package/dist/js/orpc-client.mjs +30 -7
  16. package/dist/js/orpc-client.mjs.map +1 -1
  17. package/dist/tsconfig.tsbuildinfo +1 -1
  18. package/dist/types/navigation/__test__/ledger-root-builder.apiReferenceChildren.test.d.ts +2 -0
  19. package/dist/types/navigation/__test__/ledger-root-builder.apiReferenceChildren.test.d.ts.map +1 -0
  20. package/dist/types/navigation/__test__/ledger-root-builder.landingPage.test.d.ts +2 -0
  21. package/dist/types/navigation/__test__/ledger-root-builder.landingPage.test.d.ts.map +1 -0
  22. package/dist/types/navigation/__test__/ledger-root-builder.metadataPreservation.test.d.ts +2 -0
  23. package/dist/types/navigation/__test__/ledger-root-builder.metadataPreservation.test.d.ts.map +1 -0
  24. package/dist/types/navigation/__test__/ledger-root-builder.rootSlug.test.d.ts +2 -0
  25. package/dist/types/navigation/__test__/ledger-root-builder.rootSlug.test.d.ts.map +1 -0
  26. package/dist/types/navigation/__test__/ledger-root-builder.skipSlugTabs.test.d.ts +2 -0
  27. package/dist/types/navigation/__test__/ledger-root-builder.skipSlugTabs.test.d.ts.map +1 -0
  28. package/dist/types/navigation/__test__/ledger-root-builder.unversionedPointsTo.test.d.ts +2 -0
  29. package/dist/types/navigation/__test__/ledger-root-builder.unversionedPointsTo.test.d.ts.map +1 -0
  30. package/dist/types/navigation/ledger-root-builder.d.ts +12 -0
  31. package/dist/types/navigation/ledger-root-builder.d.ts.map +1 -1
  32. package/dist/types/orpc-client/docs-ledger/contract.d.ts +2190 -170
  33. package/dist/types/orpc-client/docs-ledger/contract.d.ts.map +1 -1
  34. package/dist/types/orpc-client/docs-ledger/ledger-manifest.d.ts +3456 -104
  35. package/dist/types/orpc-client/docs-ledger/ledger-manifest.d.ts.map +1 -1
  36. package/package.json +1 -1
@@ -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
  });
@@ -906,6 +909,13 @@ function metaStrArr(metadata, key) {
906
909
  }
907
910
  return void 0;
908
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
+ }
909
919
  function toViewers(viewers) {
910
920
  if (viewers == null || viewers.length === 0) {
911
921
  return void 0;
@@ -941,17 +951,17 @@ function scopeKey(seg) {
941
951
  return [seg.product?.id ?? "", seg.version?.id ?? "", seg.variant?.id ?? "", seg.tab?.id ?? ""].join("|");
942
952
  }
943
953
  function withMetadataDefaults(base) {
944
- const { viewers, ...rest } = base;
954
+ const { viewers, featureFlags, ...rest } = base;
945
955
  return {
946
956
  ...rest,
947
957
  canonicalSlug: void 0,
948
- authed: void 0,
958
+ authed: base.authed === true ? true : void 0,
949
959
  collapsed: void 0,
950
960
  // Normalise empty arrays to undefined so unrestricted nodes don't add
951
961
  // filter-level noise; a non-empty array engages the RBAC view gate.
952
962
  viewers: viewers != null && viewers.length > 0 ? viewers : void 0,
953
- orphaned: void 0,
954
- featureFlags: void 0
963
+ orphaned: base.orphaned === true ? true : void 0,
964
+ featureFlags: featureFlags != null && featureFlags.length > 0 ? featureFlags : void 0
955
965
  };
956
966
  }
957
967
  function artifactToNode(ctx, route) {
@@ -974,7 +984,10 @@ function artifactToNode(ctx, route) {
974
984
  slug,
975
985
  icon,
976
986
  hidden: route.hidden,
977
- viewers
987
+ authed: metaBool(md, "authed"),
988
+ viewers,
989
+ orphaned: metaBool(md, "orphaned"),
990
+ featureFlags: metaFeatureFlags(md)
978
991
  }),
979
992
  pageId: PageId(pageId),
980
993
  noindex: metaBool(md, "noindex"),
@@ -990,7 +1003,7 @@ function artifactToNode(ctx, route) {
990
1003
  title,
991
1004
  icon,
992
1005
  url: Url(metaStr(md, "url") ?? ""),
993
- target: void 0
1006
+ target: metaStr(md, "target")
994
1007
  };
995
1008
  return node;
996
1009
  }
@@ -1025,7 +1038,10 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
1025
1038
  slug,
1026
1039
  icon,
1027
1040
  hidden: route.hidden,
1028
- viewers
1041
+ authed: metaBool(md, "authed"),
1042
+ viewers,
1043
+ orphaned: metaBool(md, "orphaned"),
1044
+ featureFlags: metaFeatureFlags(md)
1029
1045
  });
1030
1046
  if (route.type === "rest") {
1031
1047
  const endpointId = metaStr(md, "endpointId");
@@ -1040,7 +1056,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
1040
1056
  endpointId: EndpointId(endpointId),
1041
1057
  apiDefinitionId,
1042
1058
  isResponseStream: metaBool(md, "isResponseStream"),
1043
- availability: void 0,
1059
+ availability: metaStr(md, "availability"),
1044
1060
  playground: void 0
1045
1061
  };
1046
1062
  }
@@ -1056,7 +1072,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
1056
1072
  method,
1057
1073
  webhookId: WebhookId(webhookId),
1058
1074
  apiDefinitionId,
1059
- availability: void 0
1075
+ availability: metaStr(md, "availability")
1060
1076
  };
1061
1077
  }
1062
1078
  if (route.type === "asyncapi") {
@@ -1069,7 +1085,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
1069
1085
  ...meta,
1070
1086
  webSocketId: WebSocketId(webSocketId),
1071
1087
  apiDefinitionId,
1072
- availability: void 0,
1088
+ availability: metaStr(md, "availability"),
1073
1089
  playground: void 0
1074
1090
  };
1075
1091
  }
@@ -1085,7 +1101,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
1085
1101
  method,
1086
1102
  grpcId: GrpcId(grpcId),
1087
1103
  apiDefinitionId,
1088
- availability: void 0
1104
+ availability: metaStr(md, "availability")
1089
1105
  };
1090
1106
  }
1091
1107
  if (route.type === "graphql") {
@@ -1101,12 +1117,69 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
1101
1117
  graphqlOperationId: GraphQlOperationId(graphqlOperationId),
1102
1118
  graphqlOperationIds: void 0,
1103
1119
  apiDefinitionId,
1104
- availability: void 0,
1120
+ availability: metaStr(md, "availability"),
1105
1121
  playground: void 0
1106
1122
  };
1107
1123
  }
1108
1124
  return void 0;
1109
1125
  }
1126
+ function apiLeafPositionKey(node) {
1127
+ switch (node.type) {
1128
+ case "endpoint":
1129
+ return `endpoint:${node.endpointId}`;
1130
+ case "webhook":
1131
+ return `webhook:${node.webhookId}`;
1132
+ case "webSocket":
1133
+ return `webSocket:${node.webSocketId}`;
1134
+ case "grpc":
1135
+ return `grpc:${node.grpcId}`;
1136
+ case "graphql":
1137
+ return `graphql:${node.graphqlOperationId}`;
1138
+ }
1139
+ }
1140
+ function apiChildPositionKey(node) {
1141
+ switch (node.type) {
1142
+ case "endpoint":
1143
+ case "webhook":
1144
+ case "webSocket":
1145
+ case "grpc":
1146
+ case "graphql":
1147
+ return apiLeafPositionKey(node);
1148
+ default:
1149
+ return void 0;
1150
+ }
1151
+ }
1152
+ function positionedApiLeafChildren(ctx, nav, apiDefinitionId) {
1153
+ const rawLeafNodes = [];
1154
+ const leafPositions = /* @__PURE__ */ new Map();
1155
+ const nonApiLeafNodes = [];
1156
+ for (let i = 0; i < nav.length; i++) {
1157
+ const route = nav[i];
1158
+ const pos = route.displaySortOrder ?? i;
1159
+ const apiLeaf = apiLeafNodeFromNavRouteInternal(ctx, route, apiDefinitionId);
1160
+ if (apiLeaf != null) {
1161
+ rawLeafNodes.push(apiLeaf);
1162
+ const key = apiLeafPositionKey(apiLeaf);
1163
+ leafPositions.set(key, Math.min(leafPositions.get(key) ?? pos, pos));
1164
+ continue;
1165
+ }
1166
+ const node = artifactToNode(ctx, route);
1167
+ if (node?.type === "page" || node?.type === "link") {
1168
+ nonApiLeafNodes.push({ node, pos });
1169
+ }
1170
+ }
1171
+ const apiLeafNodes = mergeEndpointPairs(ctx, rawLeafNodes, nav);
1172
+ const positionedApiLeafNodes = apiLeafNodes.map((node, index) => {
1173
+ if (node.type === "endpointPair") {
1174
+ const streamPos = leafPositions.get(apiLeafPositionKey(node.stream)) ?? index;
1175
+ const nonStreamPos = leafPositions.get(apiLeafPositionKey(node.nonStream)) ?? index;
1176
+ return { node, pos: Math.min(streamPos, nonStreamPos) };
1177
+ }
1178
+ const key = apiChildPositionKey(node);
1179
+ return { node, pos: key != null ? leafPositions.get(key) ?? index : index };
1180
+ });
1181
+ return [...positionedApiLeafNodes, ...nonApiLeafNodes];
1182
+ }
1110
1183
  function collectApiLeafNodesFromNav(routes, basePath, segmentApiDefinitionId2) {
1111
1184
  const ctx = createBuildContext(basePath);
1112
1185
  return routes.map((route) => apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2)).filter((node) => node != null);
@@ -1208,17 +1281,22 @@ function sectionNode(ctx, scoped, sectionChildren, scopePrefix) {
1208
1281
  slug,
1209
1282
  icon: metaStr(seg.metadata, "icon"),
1210
1283
  hidden: seg.hidden,
1211
- viewers: mergeVariantViewers(seg)
1284
+ authed: metaBool(seg.metadata, "authed"),
1285
+ viewers: mergeVariantViewers(seg),
1286
+ orphaned: metaBool(seg.metadata, "orphaned"),
1287
+ featureFlags: metaFeatureFlags(seg.metadata)
1212
1288
  });
1213
1289
  return {
1214
1290
  type: "section",
1215
1291
  ...defaults,
1216
- collapsed: metaCollapsed(seg.metadata) ?? defaults.collapsed,
1292
+ // V2 convention: collapsed:false in docs.yml maps to "open-by-default"
1293
+ // so getInitiallyOpenByDefaultNodes picks it up and the UI starts open.
1294
+ collapsed: metaCollapsed(seg.metadata) === false ? "open-by-default" : metaCollapsed(seg.metadata) ?? defaults.collapsed,
1217
1295
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1218
- noindex: void 0,
1296
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1219
1297
  collapsible: metaBool(seg.metadata, "collapsible") ?? (metaCollapsed(seg.metadata) != null ? true : void 0),
1220
1298
  collapsedByDefault: metaBool(seg.metadata, "collapsedByDefault") ?? (metaCollapsed(seg.metadata) === true ? true : void 0),
1221
- availability: void 0,
1299
+ availability: metaStr(seg.metadata, "availability"),
1222
1300
  pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1223
1301
  children: mergeChildrenByPosition(ctx, nav, sectionChildren)
1224
1302
  };
@@ -1241,8 +1319,7 @@ function directChildApiPackages(parentSection, scopeSegs) {
1241
1319
  }
1242
1320
  function buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix) {
1243
1321
  const { seg, nav } = scoped;
1244
- const rawLeafNodes = nav.map((route) => apiLeafNodeFromNavRouteInternal(ctx, route, apiDefinitionId)).filter((node) => node != null);
1245
- const leafNodes = mergeEndpointPairs(ctx, rawLeafNodes, nav);
1322
+ const leafNodes = positionedApiLeafChildren(ctx, nav, apiDefinitionId);
1246
1323
  const childPackages = directChildApiPackages(seg.section, scopeSegs);
1247
1324
  const packageNodes = childPackages.map((child) => ({
1248
1325
  node: apiPackageChildNode(
@@ -1256,18 +1333,10 @@ function buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix)
1256
1333
  }));
1257
1334
  const hasChildIndex = packageNodes.some((p) => p.childIndex != null);
1258
1335
  if (!hasChildIndex) {
1259
- return [...leafNodes, ...packageNodes.map((p) => p.node)];
1260
- }
1261
- const leafPositions = [];
1262
- for (const route of nav) {
1263
- if (route.displaySortOrder != null) {
1264
- leafPositions.push(route.displaySortOrder);
1265
- }
1336
+ return [...leafNodes, ...packageNodes.map((p) => ({ node: p.node, pos: Number.MAX_SAFE_INTEGER }))].sort((a, b) => a.pos - b.pos).map((p) => p.node);
1266
1337
  }
1267
1338
  const positioned = [];
1268
- for (let i = 0; i < leafNodes.length; i++) {
1269
- positioned.push({ node: leafNodes[i], pos: leafPositions[i] ?? i });
1270
- }
1339
+ positioned.push(...leafNodes);
1271
1340
  for (const p of packageNodes) {
1272
1341
  positioned.push({ node: p.node, pos: p.childIndex ?? Number.MAX_SAFE_INTEGER });
1273
1342
  }
@@ -1295,12 +1364,15 @@ function apiPackageChildNode(ctx, scoped, scopeSegs, parentApiDefinitionId, scop
1295
1364
  slug,
1296
1365
  icon: metaStr(seg.metadata, "icon"),
1297
1366
  hidden: seg.hidden,
1298
- viewers: toViewers(metaStrArr(seg.metadata, "viewers"))
1367
+ authed: metaBool(seg.metadata, "authed"),
1368
+ viewers: toViewers(metaStrArr(seg.metadata, "viewers")),
1369
+ orphaned: metaBool(seg.metadata, "orphaned"),
1370
+ featureFlags: metaFeatureFlags(seg.metadata)
1299
1371
  }),
1300
1372
  apiDefinitionId: ApiDefinitionId(apiDefinitionId),
1301
1373
  availability: metaStr(seg.metadata, "availability"),
1302
1374
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1303
- noindex: void 0,
1375
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1304
1376
  pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1305
1377
  children,
1306
1378
  playground: void 0
@@ -1380,12 +1452,15 @@ function apiReferenceNode(ctx, scoped, scopeSegs, scopePrefix) {
1380
1452
  slug,
1381
1453
  icon: metaStr(seg.metadata, "icon"),
1382
1454
  hidden: seg.hidden,
1383
- viewers: mergeVariantViewers(seg)
1455
+ authed: metaBool(seg.metadata, "authed"),
1456
+ viewers: mergeVariantViewers(seg),
1457
+ orphaned: metaBool(seg.metadata, "orphaned"),
1458
+ featureFlags: metaFeatureFlags(seg.metadata)
1384
1459
  }),
1385
1460
  apiDefinitionId: ApiDefinitionId(apiDefinitionId),
1386
- availability: void 0,
1461
+ availability: metaStr(seg.metadata, "availability"),
1387
1462
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1388
- noindex: void 0,
1463
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1389
1464
  paginated: true,
1390
1465
  showErrors: metaBool(seg.metadata, "showErrors"),
1391
1466
  hideTitle: metaBool(seg.metadata, "hideTitle"),
@@ -1438,12 +1513,15 @@ function changelogNode(ctx, scoped, scopePrefix) {
1438
1513
  slug: ctx.contentSlug(r.fullPath ?? ""),
1439
1514
  icon: metaStr(r.metadata, "icon"),
1440
1515
  hidden: r.hidden,
1441
- viewers: toViewers(metaStrArr(r.metadata, "viewers"))
1516
+ authed: metaBool(r.metadata, "authed"),
1517
+ viewers: toViewers(metaStrArr(r.metadata, "viewers")),
1518
+ orphaned: metaBool(r.metadata, "orphaned"),
1519
+ featureFlags: metaFeatureFlags(r.metadata)
1442
1520
  }),
1443
1521
  pageId: PageId(metaStr(r.metadata, "pageId") ?? ""),
1444
- noindex: void 0,
1522
+ noindex: metaBool(r.metadata, "noindex"),
1445
1523
  date: dateStr ?? "",
1446
- tags: void 0
1524
+ tags: metaStrArr(r.metadata, "tags")
1447
1525
  };
1448
1526
  let months = byYear.get(year);
1449
1527
  if (months == null) {
@@ -1487,10 +1565,13 @@ function changelogNode(ctx, scoped, scopePrefix) {
1487
1565
  slug: baseSlug,
1488
1566
  icon: metaStr(seg.metadata, "icon"),
1489
1567
  hidden: seg.hidden,
1490
- viewers: mergeVariantViewers(seg)
1568
+ authed: metaBool(seg.metadata, "authed"),
1569
+ viewers: mergeVariantViewers(seg),
1570
+ orphaned: metaBool(seg.metadata, "orphaned"),
1571
+ featureFlags: metaFeatureFlags(seg.metadata)
1491
1572
  }),
1492
1573
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1493
- noindex: void 0,
1574
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1494
1575
  children: years
1495
1576
  };
1496
1577
  }
@@ -1547,17 +1628,55 @@ function buildSectionTree(ctx, scopeSegs, parentPath, scopePrefix, changelogScop
1547
1628
  return { node, childIndex };
1548
1629
  });
1549
1630
  }
1631
+ function computeSiblingSortBoundaries(ordered) {
1632
+ const result = /* @__PURE__ */ new Map();
1633
+ const sectionPaths = new Set(ordered.map((s) => s.seg.section));
1634
+ const rootSections = [];
1635
+ for (const s of ordered) {
1636
+ const type = metaStr(s.seg.metadata, "type");
1637
+ const sec = s.seg.section;
1638
+ if (type !== "section" || sec === "") {
1639
+ continue;
1640
+ }
1641
+ const parent = parentSectionPath(sec);
1642
+ const isRootLevel = parent === "" || !sectionPaths.has(parent) && nearestExistingAncestor(sec, sectionPaths) === "";
1643
+ if (isRootLevel) {
1644
+ rootSections.push(s);
1645
+ }
1646
+ }
1647
+ const byPath = /* @__PURE__ */ new Map();
1648
+ for (const s of rootSections) {
1649
+ const group = byPath.get(s.seg.section) ?? [];
1650
+ group.push(s);
1651
+ byPath.set(s.seg.section, group);
1652
+ }
1653
+ for (const [, siblings] of byPath) {
1654
+ if (siblings.length <= 1) {
1655
+ continue;
1656
+ }
1657
+ for (let i = 0; i < siblings.length; i++) {
1658
+ const lo = siblings[i].seg.sortOrder;
1659
+ const hi = i + 1 < siblings.length ? siblings[i + 1].seg.sortOrder : Number.MAX_SAFE_INTEGER;
1660
+ result.set(siblings[i], { lo, hi });
1661
+ }
1662
+ }
1663
+ return result;
1664
+ }
1550
1665
  function buildSidebarRootChildren(ctx, scopeSegs, scopePrefix, changelogScopePrefix) {
1551
1666
  const ordered = [...scopeSegs].sort((a, b) => a.seg.sortOrder - b.seg.sortOrder);
1552
1667
  const sectionPaths = new Set(ordered.map((s) => s.seg.section));
1553
1668
  const annotated = [];
1554
1669
  const hasRootSection = ordered.some((s) => metaStr(s.seg.metadata, "type") === "section" && s.seg.section === "");
1670
+ const siblingBoundaries = computeSiblingSortBoundaries(ordered);
1555
1671
  for (const s of ordered) {
1556
1672
  const type = metaStr(s.seg.metadata, "type");
1557
1673
  const sec = s.seg.section;
1558
1674
  if (hasOwningApiReference(s, scopeSegs)) {
1559
1675
  continue;
1560
1676
  }
1677
+ if (type === "tabRoot" && metaBool(s.seg.metadata, "landingPage") === true) {
1678
+ continue;
1679
+ }
1561
1680
  if (type === "tabRoot" || sec === "" && type !== "section") {
1562
1681
  for (const r of s.nav) {
1563
1682
  const node = artifactToNode(ctx, r);
@@ -1585,14 +1704,21 @@ function buildSidebarRootChildren(ctx, scopeSegs, scopePrefix, changelogScopePre
1585
1704
  } else if (type === "changelog") {
1586
1705
  node = changelogNode(ctx, s, changelogScopePrefix ?? scopePrefix);
1587
1706
  } else {
1707
+ const bounds = siblingBoundaries.get(s);
1708
+ const ownedSegs = bounds != null ? scopeSegs.filter((seg) => seg.seg.sortOrder >= bounds.lo && seg.seg.sortOrder < bounds.hi) : scopeSegs;
1588
1709
  node = sectionNode(
1589
1710
  ctx,
1590
1711
  s,
1591
- buildSectionTree(ctx, scopeSegs, sec, scopePrefix, changelogScopePrefix),
1712
+ buildSectionTree(ctx, ownedSegs, sec, scopePrefix, changelogScopePrefix),
1592
1713
  scopePrefix
1593
1714
  );
1594
1715
  }
1595
- annotated.push({ node, pos: metaNum(s.seg.metadata, "childIndex"), isLeaf: false });
1716
+ const isSharedSection = siblingBoundaries.size > 0 && scopePrefix !== "" && sec !== "" && !sec.startsWith(scopePrefix);
1717
+ annotated.push({
1718
+ node,
1719
+ pos: isSharedSection ? void 0 : metaNum(s.seg.metadata, "childIndex"),
1720
+ isLeaf: false
1721
+ });
1596
1722
  }
1597
1723
  }
1598
1724
  const hasLeafPos = annotated.some((a) => a.isLeaf && a.pos != null);
@@ -1644,13 +1770,13 @@ function buildSidebarRoot(ctx, scopeSegs, scopePrefix, changelogScopePrefix) {
1644
1770
  };
1645
1771
  }
1646
1772
  function buildFullRootFromSegments(options) {
1647
- const { basePath, title, segments, navBySegment } = options;
1773
+ const { basePath, rootSlug: sourceRootSlug, title, segments, navBySegment, skipSharedSectionMerge } = options;
1648
1774
  const ctx = createBuildContext(basePath);
1649
1775
  const scoped = segments.filter((seg) => {
1650
1776
  const t = metaStr(seg.metadata, "type");
1651
1777
  return t !== "files" && t !== "redirects";
1652
1778
  }).map((seg) => ({ seg, nav: navBySegment.get(seg.segmentHash) ?? [] }));
1653
- const rootSlug = asSlug(basePath);
1779
+ const rootSlug = asSlug(sourceRootSlug ?? basePath);
1654
1780
  const scopesByKey = /* @__PURE__ */ new Map();
1655
1781
  for (const s of scoped) {
1656
1782
  const key = scopeKey(s.seg);
@@ -1663,9 +1789,9 @@ function buildFullRootFromSegments(options) {
1663
1789
  const tabs = uniqueDetails(scoped, "tab");
1664
1790
  let child;
1665
1791
  if (products.length > 0) {
1666
- child = buildProductGroup(ctx, products, scoped, rootSlug);
1792
+ child = buildProductGroup(ctx, products, scoped, rootSlug, skipSharedSectionMerge);
1667
1793
  } else if (versions.length > 0) {
1668
- child = buildVersioned(ctx, versions, scoped, rootSlug, void 0);
1794
+ child = buildVersioned(ctx, versions, scoped, rootSlug, void 0, skipSharedSectionMerge);
1669
1795
  } else {
1670
1796
  child = buildUnversioned(ctx, scoped, rootSlug, tabs.length > 0);
1671
1797
  }
@@ -1676,6 +1802,24 @@ function buildFullRootFromSegments(options) {
1676
1802
  } else if (child.type === "versioned") {
1677
1803
  const defaultVersion = child.children.find((v) => v.default) ?? child.children[0];
1678
1804
  rootPointsTo = defaultVersion?.pointsTo;
1805
+ } else if (child.type === "unversioned") {
1806
+ if (tabs.length > 0) {
1807
+ const firstTab = tabs[0];
1808
+ const pt = firstTab != null ? metaStr(firstTab.metadata, "pointsTo") : void 0;
1809
+ rootPointsTo = pt != null ? pointsToSlug(pt) : void 0;
1810
+ } else {
1811
+ const sorted = [...scoped].sort((a, b) => a.seg.sortOrder - b.seg.sortOrder);
1812
+ for (const s of sorted) {
1813
+ if (s.seg.hidden) {
1814
+ continue;
1815
+ }
1816
+ const pt = metaStr(s.seg.metadata, "pointsTo");
1817
+ if (pt != null) {
1818
+ rootPointsTo = pointsToSlug(pt);
1819
+ break;
1820
+ }
1821
+ }
1822
+ }
1679
1823
  }
1680
1824
  const root = {
1681
1825
  type: "root",
@@ -1688,21 +1832,22 @@ function buildFullRootFromSegments(options) {
1688
1832
  return root;
1689
1833
  }
1690
1834
  function uniqueDetails(scoped, dim) {
1691
- const bySlug = /* @__PURE__ */ new Map();
1835
+ const byKey = /* @__PURE__ */ new Map();
1692
1836
  for (const s of scoped) {
1693
1837
  const d = s.seg[dim];
1694
1838
  if (d == null) {
1695
1839
  continue;
1696
1840
  }
1697
1841
  const slug = detailSlug(d);
1698
- const existing = bySlug.get(slug);
1842
+ const key = dim === "tab" ? d.id : slug !== "" ? slug : d.id;
1843
+ const existing = byKey.get(key);
1699
1844
  if (existing == null) {
1700
- bySlug.set(slug, d);
1845
+ byKey.set(key, d);
1701
1846
  } else if (metaStr(d.metadata, "pointsTo") != null && metaStr(existing.metadata, "pointsTo") == null) {
1702
- bySlug.set(slug, d);
1847
+ byKey.set(key, d);
1703
1848
  }
1704
1849
  }
1705
- return [...bySlug.values()].sort((a, b) => a.sortOrder - b.sortOrder);
1850
+ return [...byKey.values()].sort((a, b) => a.sortOrder - b.sortOrder);
1706
1851
  }
1707
1852
  function scopeSlugPrefix(rootSlug, ...details) {
1708
1853
  const parts = [rootSlug];
@@ -1736,7 +1881,7 @@ function buildVariantedNode(ctx, variants, scopeSegs, scopePrefix) {
1736
1881
  default: detailIsDefault(variant),
1737
1882
  variantId: VariantId(String(variant.id)),
1738
1883
  subtitle: metaStr(variant.metadata, "subtitle") ?? void 0,
1739
- image: void 0,
1884
+ image: metaStr(variant.metadata, "image") != null ? FileId(metaStr(variant.metadata, "image")) : void 0,
1740
1885
  pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1741
1886
  children
1742
1887
  };
@@ -1785,7 +1930,7 @@ function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix) {
1785
1930
  title: tab.displayName,
1786
1931
  icon: tab.icon ?? void 0,
1787
1932
  url: Url(metaStr(tab.metadata, "url") ?? ""),
1788
- target: void 0
1933
+ target: metaStr(tab.metadata, "target")
1789
1934
  };
1790
1935
  }
1791
1936
  if (tabType === "changelog") {
@@ -1846,16 +1991,71 @@ function buildUnversioned(ctx, scopeSegs, scopePrefix, tabsPresent) {
1846
1991
  type: "unversioned",
1847
1992
  id: ctx.nodeId(`unversioned:${first?.seg.product?.id ?? "root"}`),
1848
1993
  collapsed: void 0,
1849
- landingPage: void 0,
1994
+ landingPage: buildLandingPage(ctx, scopeSegs),
1850
1995
  // The enclosing scope prefix (product slug, or rootSlug at the top
1851
1996
  // level) roots structural sections so they share the scope's slug
1852
1997
  // namespace.
1853
1998
  child: buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix)
1854
1999
  };
1855
2000
  }
1856
- function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix) {
2001
+ function mergeSharedSections(defaultSegs, allScoped, defaultVersion, versionSlugs) {
2002
+ const defaultTabsByName = /* @__PURE__ */ new Map();
2003
+ for (const s of defaultSegs) {
2004
+ if (s.seg.tab != null) {
2005
+ const tabName = s.seg.tab.displayName;
2006
+ if (!defaultTabsByName.has(tabName)) {
2007
+ defaultTabsByName.set(tabName, s.seg.tab);
2008
+ }
2009
+ }
2010
+ }
2011
+ const existingSections = new Set(
2012
+ defaultSegs.filter((s) => metaStr(s.seg.metadata, "type") === "section").map((s) => s.seg.section)
2013
+ );
2014
+ const maxSortOrder = defaultSegs.reduce((max, s) => Math.max(max, s.seg.sortOrder), 0);
2015
+ let nextSortOrder = maxSortOrder + 1;
2016
+ const merged = [...defaultSegs];
2017
+ for (const s of allScoped) {
2018
+ if (s.seg.version?.id === defaultVersion.id) {
2019
+ continue;
2020
+ }
2021
+ const type = metaStr(s.seg.metadata, "type");
2022
+ if (type !== "section") {
2023
+ continue;
2024
+ }
2025
+ const sectionPath = s.seg.section;
2026
+ if (versionSlugs.some((vs) => sectionPath === vs || sectionPath.startsWith(vs + "/"))) {
2027
+ continue;
2028
+ }
2029
+ if (existingSections.has(sectionPath)) {
2030
+ continue;
2031
+ }
2032
+ const sourceTabName = s.seg.tab?.displayName ?? "";
2033
+ const targetTab = defaultTabsByName.get(sourceTabName);
2034
+ if (targetTab == null) {
2035
+ continue;
2036
+ }
2037
+ const metadata = s.seg.metadata != null ? { ...s.seg.metadata, childIndex: void 0 } : s.seg.metadata;
2038
+ merged.push({
2039
+ seg: {
2040
+ ...s.seg,
2041
+ tab: targetTab,
2042
+ version: defaultVersion,
2043
+ sortOrder: nextSortOrder++,
2044
+ metadata
2045
+ },
2046
+ nav: s.nav
2047
+ });
2048
+ existingSections.add(sectionPath);
2049
+ }
2050
+ return merged;
2051
+ }
2052
+ function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix, skipSharedSectionMerge) {
2053
+ const versionSlugs = versions.map((v) => detailSlug(v)).filter((s) => s !== "");
1857
2054
  const children = versions.map((version) => {
1858
- const versionSegs = scoped.filter((s) => s.seg.version?.id === version.id);
2055
+ let versionSegs = scoped.filter((s) => s.seg.version?.id === version.id);
2056
+ if (detailIsDefault(version) && !skipSharedSectionMerge) {
2057
+ versionSegs = mergeSharedSections(versionSegs, scoped, version, versionSlugs);
2058
+ }
1859
2059
  const tabsPresent = uniqueDetails(versionSegs, "tab").length > 0;
1860
2060
  const prefix = productPrefix != null ? productPrefix : rootSlug;
1861
2061
  const versionSegment = detailSlug(version);
@@ -1873,7 +2073,7 @@ function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix) {
1873
2073
  default: detailIsDefault(version),
1874
2074
  versionId: VersionId(version.id),
1875
2075
  availability: void 0,
1876
- landingPage: buildVersionLandingPage(ctx, versionSegs, asSlug(slug)),
2076
+ landingPage: buildLandingPage(ctx, versionSegs),
1877
2077
  announcement: void 0,
1878
2078
  pointsTo: metaStr(version.metadata, "pointsTo") != null ? pointsToSlug(metaStr(version.metadata, "pointsTo")) : void 0,
1879
2079
  // The version's full slug roots structural sections so the whole
@@ -1954,34 +2154,41 @@ function crossVersionDedupKeys(node, parents) {
1954
2154
  keys.push([...parentTitles, node.title].join("###"));
1955
2155
  return keys;
1956
2156
  }
1957
- function buildVersionLandingPage(ctx, versionSegs, versionSlug) {
1958
- const tablessSegs = versionSegs.filter((s) => s.seg.tab == null);
1959
- if (tablessSegs.length === 0) {
2157
+ function routeToLandingPage(ctx, route) {
2158
+ if (route == null || route.type !== "markdown" || route.fullPath == null) {
1960
2159
  return void 0;
1961
2160
  }
1962
- for (const s of tablessSegs) {
1963
- for (const r of s.nav) {
1964
- if (r.type === "markdown" && r.fullPath != null) {
1965
- const md = r.metadata;
1966
- const pageId = metaStr(md, "pageId") ?? "";
1967
- const slug = ctx.contentSlug(r.fullPath);
1968
- return {
1969
- type: "landingPage",
1970
- ...withMetadataDefaults({
1971
- id: ctx.nodeId(`landing:${slug}`),
1972
- title: metaStr(md, "title") ?? "",
1973
- slug,
1974
- icon: metaStr(md, "icon"),
1975
- hidden: r.hidden,
1976
- viewers: toViewers(metaStrArr(md, "viewers"))
1977
- }),
1978
- pageId: PageId(pageId),
1979
- noindex: metaBool(md, "noindex")
1980
- };
1981
- }
1982
- }
2161
+ const md = route.metadata;
2162
+ const pageId = metaStr(md, "pageId");
2163
+ if (pageId == null) {
2164
+ return void 0;
1983
2165
  }
1984
- return void 0;
2166
+ const slug = ctx.contentSlug(route.fullPath);
2167
+ return {
2168
+ type: "landingPage",
2169
+ ...withMetadataDefaults({
2170
+ id: ctx.nodeId(`landing:${slug}`),
2171
+ title: metaStr(md, "title") ?? "",
2172
+ slug,
2173
+ icon: metaStr(md, "icon"),
2174
+ hidden: route.hidden,
2175
+ authed: metaBool(md, "authed"),
2176
+ viewers: toViewers(metaStrArr(md, "viewers")),
2177
+ orphaned: metaBool(md, "orphaned"),
2178
+ featureFlags: metaFeatureFlags(md)
2179
+ }),
2180
+ pageId: PageId(pageId),
2181
+ noindex: metaBool(md, "noindex")
2182
+ };
2183
+ }
2184
+ function buildLandingPage(ctx, scopeSegs) {
2185
+ const landingSegment = scopeSegs.find(
2186
+ (s) => metaStr(s.seg.metadata, "type") === "tabRoot" && metaBool(s.seg.metadata, "landingPage") === true
2187
+ );
2188
+ return routeToLandingPage(
2189
+ ctx,
2190
+ landingSegment?.nav.find((route) => route.type === "markdown")
2191
+ );
1985
2192
  }
1986
2193
  function markCrossVersionCanonicalSlugs(versionNodes) {
1987
2194
  const keyToCanonical = /* @__PURE__ */ new Map();
@@ -2016,13 +2223,13 @@ function markCrossVersionCanonicalSlugs(versionNodes) {
2016
2223
  });
2017
2224
  }
2018
2225
  }
2019
- function buildProductGroup(ctx, products, scoped, rootSlug) {
2226
+ function buildProductGroup(ctx, products, scoped, rootSlug, skipSharedSectionMerge) {
2020
2227
  const children = products.map((product) => {
2021
2228
  const productSegs = scoped.filter((s) => s.seg.product?.id === product.id);
2022
2229
  const versions = uniqueDetails(productSegs, "version");
2023
2230
  const tabsPresent = uniqueDetails(productSegs, "tab").length > 0;
2024
2231
  const productPrefix = scopeSlugPrefix(rootSlug, product);
2025
- const productChild = versions.length > 0 ? buildVersioned(ctx, versions, productSegs, rootSlug, productPrefix) : buildUnversioned(ctx, productSegs, asSlug(productPrefix), tabsPresent);
2232
+ const productChild = versions.length > 0 ? buildVersioned(ctx, versions, productSegs, rootSlug, productPrefix, skipSharedSectionMerge) : buildUnversioned(ctx, productSegs, asSlug(productPrefix), tabsPresent);
2026
2233
  const node = {
2027
2234
  type: "product",
2028
2235
  ...withMetadataDefaults({
@@ -2041,7 +2248,7 @@ function buildProductGroup(ctx, products, scoped, rootSlug) {
2041
2248
  // here; sourcing it from the hash makes that filter match nothing.
2042
2249
  productId: ProductId(product.displayName),
2043
2250
  subtitle: metaStr(product.metadata, "subtitle") ?? "",
2044
- image: void 0,
2251
+ image: metaStr(product.metadata, "image") != null ? FileId(metaStr(product.metadata, "image")) : void 0,
2045
2252
  announcement: void 0,
2046
2253
  pointsTo: metaStr(product.metadata, "pointsTo") != null ? pointsToSlug(metaStr(product.metadata, "pointsTo")) : void 0,
2047
2254
  child: productChild
@@ -2052,7 +2259,10 @@ function buildProductGroup(ctx, products, scoped, rootSlug) {
2052
2259
  type: "productgroup",
2053
2260
  id: ctx.nodeId("productgroup"),
2054
2261
  collapsed: void 0,
2055
- landingPage: void 0,
2262
+ landingPage: buildLandingPage(
2263
+ ctx,
2264
+ scoped.filter((s) => s.seg.product == null)
2265
+ ),
2056
2266
  children
2057
2267
  };
2058
2268
  }