@fern-api/fdr-sdk 1.2.39-38c6f9a29c → 1.2.39-3a7bc956ed

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 (55) 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/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 +32 -16
  10. package/dist/js/index.js.map +1 -1
  11. package/dist/js/index.mjs +32 -16
  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 +322 -92
  18. package/dist/js/navigation/ledger-root-builder.js.map +1 -1
  19. package/dist/js/navigation/ledger-root-builder.mjs +322 -92
  20. package/dist/js/navigation/ledger-root-builder.mjs.map +1 -1
  21. package/dist/js/orpc-client.js +30 -7
  22. package/dist/js/orpc-client.js.map +1 -1
  23. package/dist/js/orpc-client.mjs +30 -7
  24. package/dist/js/orpc-client.mjs.map +1 -1
  25. package/dist/tsconfig.tsbuildinfo +1 -1
  26. package/dist/types/navigation/__test__/findNode.authedRedirect.test.d.ts +2 -0
  27. package/dist/types/navigation/__test__/findNode.authedRedirect.test.d.ts.map +1 -0
  28. package/dist/types/navigation/__test__/ledger-root-builder.apiReferenceChildren.test.d.ts +2 -0
  29. package/dist/types/navigation/__test__/ledger-root-builder.apiReferenceChildren.test.d.ts.map +1 -0
  30. package/dist/types/navigation/__test__/ledger-root-builder.collapsedDeterminism.test.d.ts +2 -0
  31. package/dist/types/navigation/__test__/ledger-root-builder.collapsedDeterminism.test.d.ts.map +1 -0
  32. package/dist/types/navigation/__test__/ledger-root-builder.landingPage.test.d.ts +2 -0
  33. package/dist/types/navigation/__test__/ledger-root-builder.landingPage.test.d.ts.map +1 -0
  34. package/dist/types/navigation/__test__/ledger-root-builder.metadataPreservation.test.d.ts +2 -0
  35. package/dist/types/navigation/__test__/ledger-root-builder.metadataPreservation.test.d.ts.map +1 -0
  36. package/dist/types/navigation/__test__/ledger-root-builder.rootSlug.test.d.ts +2 -0
  37. package/dist/types/navigation/__test__/ledger-root-builder.rootSlug.test.d.ts.map +1 -0
  38. package/dist/types/navigation/__test__/ledger-root-builder.skipSlugApiReference.test.d.ts +2 -0
  39. package/dist/types/navigation/__test__/ledger-root-builder.skipSlugApiReference.test.d.ts.map +1 -0
  40. package/dist/types/navigation/__test__/ledger-root-builder.skipSlugTabs.test.d.ts +2 -0
  41. package/dist/types/navigation/__test__/ledger-root-builder.skipSlugTabs.test.d.ts.map +1 -0
  42. package/dist/types/navigation/__test__/ledger-root-builder.unversionedPointsTo.test.d.ts +2 -0
  43. package/dist/types/navigation/__test__/ledger-root-builder.unversionedPointsTo.test.d.ts.map +1 -0
  44. package/dist/types/navigation/__test__/ledger-root-builder.variantSharedSegments.test.d.ts +2 -0
  45. package/dist/types/navigation/__test__/ledger-root-builder.variantSharedSegments.test.d.ts.map +1 -0
  46. package/dist/types/navigation/ledger-root-builder.d.ts +17 -1
  47. package/dist/types/navigation/ledger-root-builder.d.ts.map +1 -1
  48. package/dist/types/navigation/utils/findNode.d.ts +1 -0
  49. package/dist/types/navigation/utils/findNode.d.ts.map +1 -1
  50. package/dist/types/navigation/utils/followRedirect.d.ts.map +1 -1
  51. package/dist/types/orpc-client/docs-ledger/contract.d.ts +2190 -170
  52. package/dist/types/orpc-client/docs-ledger/contract.d.ts.map +1 -1
  53. package/dist/types/orpc-client/docs-ledger/ledger-manifest.d.ts +3456 -104
  54. package/dist/types/orpc-client/docs-ledger/ledger-manifest.d.ts.map +1 -1
  55. package/package.json +3 -3
@@ -94,6 +94,9 @@ var AuthSchemeIdSchema = z2.string();
94
94
  var SubpackageIdSchema = z2.string();
95
95
  var WebSocketMessageIdSchema = z2.string();
96
96
  var FileIdSchema = z2.string();
97
+ function FileId(value) {
98
+ return value;
99
+ }
97
100
  var MultipleAuthTypeSchema = z2.object({
98
101
  schemes: z2.array(AuthSchemeIdSchema)
99
102
  });
@@ -802,6 +805,14 @@ function traverseDF(node, visit) {
802
805
  }
803
806
 
804
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"]);
805
816
  function createBuildContext(basePath) {
806
817
  const seen = /* @__PURE__ */ new Map();
807
818
  const basePrefix = basePath.replace(/^\/+|\/+$/g, "");
@@ -865,6 +876,13 @@ function metaStrArr(metadata, key) {
865
876
  }
866
877
  return void 0;
867
878
  }
879
+ function metaFeatureFlags(metadata) {
880
+ if (metadata != null && typeof metadata === "object" && "featureFlags" in metadata) {
881
+ const v = metadata.featureFlags;
882
+ return Array.isArray(v) && v.length > 0 ? v : void 0;
883
+ }
884
+ return void 0;
885
+ }
868
886
  function toViewers(viewers) {
869
887
  if (viewers == null || viewers.length === 0) {
870
888
  return void 0;
@@ -872,7 +890,7 @@ function toViewers(viewers) {
872
890
  return viewers.map((v) => RoleId(v));
873
891
  }
874
892
  function mergeVariantViewers(seg) {
875
- 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;
876
894
  const variantViewers = seg.variant?.viewers;
877
895
  if ((segViewers == null || segViewers.length === 0) && (variantViewers == null || variantViewers.length === 0)) {
878
896
  return void 0;
@@ -900,17 +918,17 @@ function scopeKey(seg) {
900
918
  return [seg.product?.id ?? "", seg.version?.id ?? "", seg.variant?.id ?? "", seg.tab?.id ?? ""].join("|");
901
919
  }
902
920
  function withMetadataDefaults(base) {
903
- const { viewers, ...rest } = base;
921
+ const { viewers, featureFlags, ...rest } = base;
904
922
  return {
905
923
  ...rest,
906
924
  canonicalSlug: void 0,
907
- authed: void 0,
925
+ authed: base.authed === true ? true : void 0,
908
926
  collapsed: void 0,
909
927
  // Normalise empty arrays to undefined so unrestricted nodes don't add
910
928
  // filter-level noise; a non-empty array engages the RBAC view gate.
911
929
  viewers: viewers != null && viewers.length > 0 ? viewers : void 0,
912
- orphaned: void 0,
913
- featureFlags: void 0
930
+ orphaned: base.orphaned === true ? true : void 0,
931
+ featureFlags: featureFlags != null && featureFlags.length > 0 ? featureFlags : void 0
914
932
  };
915
933
  }
916
934
  function artifactToNode(ctx, route) {
@@ -933,7 +951,10 @@ function artifactToNode(ctx, route) {
933
951
  slug,
934
952
  icon,
935
953
  hidden: route.hidden,
936
- viewers
954
+ authed: metaBool(md, "authed"),
955
+ viewers,
956
+ orphaned: metaBool(md, "orphaned"),
957
+ featureFlags: metaFeatureFlags(md)
937
958
  }),
938
959
  pageId: PageId(pageId),
939
960
  noindex: metaBool(md, "noindex"),
@@ -949,7 +970,7 @@ function artifactToNode(ctx, route) {
949
970
  title,
950
971
  icon,
951
972
  url: Url(metaStr(md, "url") ?? ""),
952
- target: void 0
973
+ target: metaStr(md, "target")
953
974
  };
954
975
  return node;
955
976
  }
@@ -984,7 +1005,10 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
984
1005
  slug,
985
1006
  icon,
986
1007
  hidden: route.hidden,
987
- viewers
1008
+ authed: metaBool(md, "authed"),
1009
+ viewers,
1010
+ orphaned: metaBool(md, "orphaned"),
1011
+ featureFlags: metaFeatureFlags(md)
988
1012
  });
989
1013
  if (route.type === "rest") {
990
1014
  const endpointId = metaStr(md, "endpointId");
@@ -999,7 +1023,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
999
1023
  endpointId: EndpointId(endpointId),
1000
1024
  apiDefinitionId,
1001
1025
  isResponseStream: metaBool(md, "isResponseStream"),
1002
- availability: void 0,
1026
+ availability: metaStr(md, "availability"),
1003
1027
  playground: void 0
1004
1028
  };
1005
1029
  }
@@ -1015,7 +1039,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
1015
1039
  method,
1016
1040
  webhookId: WebhookId(webhookId),
1017
1041
  apiDefinitionId,
1018
- availability: void 0
1042
+ availability: metaStr(md, "availability")
1019
1043
  };
1020
1044
  }
1021
1045
  if (route.type === "asyncapi") {
@@ -1028,7 +1052,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
1028
1052
  ...meta,
1029
1053
  webSocketId: WebSocketId(webSocketId),
1030
1054
  apiDefinitionId,
1031
- availability: void 0,
1055
+ availability: metaStr(md, "availability"),
1032
1056
  playground: void 0
1033
1057
  };
1034
1058
  }
@@ -1044,7 +1068,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
1044
1068
  method,
1045
1069
  grpcId: GrpcId(grpcId),
1046
1070
  apiDefinitionId,
1047
- availability: void 0
1071
+ availability: metaStr(md, "availability")
1048
1072
  };
1049
1073
  }
1050
1074
  if (route.type === "graphql") {
@@ -1060,12 +1084,69 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
1060
1084
  graphqlOperationId: GraphQlOperationId(graphqlOperationId),
1061
1085
  graphqlOperationIds: void 0,
1062
1086
  apiDefinitionId,
1063
- availability: void 0,
1087
+ availability: metaStr(md, "availability"),
1064
1088
  playground: void 0
1065
1089
  };
1066
1090
  }
1067
1091
  return void 0;
1068
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
+ }
1069
1150
  function collectApiLeafNodesFromNav(routes, basePath, segmentApiDefinitionId2) {
1070
1151
  const ctx = createBuildContext(basePath);
1071
1152
  return routes.map((route) => apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2)).filter((node) => node != null);
@@ -1167,17 +1248,20 @@ function sectionNode(ctx, scoped, sectionChildren, scopePrefix) {
1167
1248
  slug,
1168
1249
  icon: metaStr(seg.metadata, "icon"),
1169
1250
  hidden: seg.hidden,
1170
- viewers: mergeVariantViewers(seg)
1251
+ authed: metaBool(seg.metadata, "authed"),
1252
+ viewers: mergeVariantViewers(seg),
1253
+ orphaned: metaBool(seg.metadata, "orphaned"),
1254
+ featureFlags: metaFeatureFlags(seg.metadata)
1171
1255
  });
1172
1256
  return {
1173
1257
  type: "section",
1174
1258
  ...defaults,
1175
1259
  collapsed: metaCollapsed(seg.metadata) ?? defaults.collapsed,
1176
1260
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1177
- noindex: void 0,
1178
- collapsible: metaBool(seg.metadata, "collapsible") ?? (metaCollapsed(seg.metadata) != null ? true : void 0),
1261
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1262
+ collapsible: metaBool(seg.metadata, "collapsible") ?? (metaCollapsed(seg.metadata) === true ? true : void 0),
1179
1263
  collapsedByDefault: metaBool(seg.metadata, "collapsedByDefault") ?? (metaCollapsed(seg.metadata) === true ? true : void 0),
1180
- availability: void 0,
1264
+ availability: metaStr(seg.metadata, "availability"),
1181
1265
  pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1182
1266
  children: mergeChildrenByPosition(ctx, nav, sectionChildren)
1183
1267
  };
@@ -1200,8 +1284,7 @@ function directChildApiPackages(parentSection, scopeSegs) {
1200
1284
  }
1201
1285
  function buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix) {
1202
1286
  const { seg, nav } = scoped;
1203
- const rawLeafNodes = nav.map((route) => apiLeafNodeFromNavRouteInternal(ctx, route, apiDefinitionId)).filter((node) => node != null);
1204
- const leafNodes = mergeEndpointPairs(ctx, rawLeafNodes, nav);
1287
+ const leafNodes = positionedApiLeafChildren(ctx, nav, apiDefinitionId);
1205
1288
  const childPackages = directChildApiPackages(seg.section, scopeSegs);
1206
1289
  const packageNodes = childPackages.map((child) => ({
1207
1290
  node: apiPackageChildNode(
@@ -1215,18 +1298,10 @@ function buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix)
1215
1298
  }));
1216
1299
  const hasChildIndex = packageNodes.some((p) => p.childIndex != null);
1217
1300
  if (!hasChildIndex) {
1218
- return [...leafNodes, ...packageNodes.map((p) => p.node)];
1219
- }
1220
- const leafPositions = [];
1221
- for (const route of nav) {
1222
- if (route.displaySortOrder != null) {
1223
- leafPositions.push(route.displaySortOrder);
1224
- }
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);
1225
1302
  }
1226
1303
  const positioned = [];
1227
- for (let i = 0; i < leafNodes.length; i++) {
1228
- positioned.push({ node: leafNodes[i], pos: leafPositions[i] ?? i });
1229
- }
1304
+ positioned.push(...leafNodes);
1230
1305
  for (const p of packageNodes) {
1231
1306
  positioned.push({ node: p.node, pos: p.childIndex ?? Number.MAX_SAFE_INTEGER });
1232
1307
  }
@@ -1254,12 +1329,15 @@ function apiPackageChildNode(ctx, scoped, scopeSegs, parentApiDefinitionId, scop
1254
1329
  slug,
1255
1330
  icon: metaStr(seg.metadata, "icon"),
1256
1331
  hidden: seg.hidden,
1257
- viewers: toViewers(metaStrArr(seg.metadata, "viewers"))
1332
+ authed: metaBool(seg.metadata, "authed"),
1333
+ viewers: toViewers(metaStrArr(seg.metadata, "viewers")),
1334
+ orphaned: metaBool(seg.metadata, "orphaned"),
1335
+ featureFlags: metaFeatureFlags(seg.metadata)
1258
1336
  }),
1259
1337
  apiDefinitionId: ApiDefinitionId(apiDefinitionId),
1260
1338
  availability: metaStr(seg.metadata, "availability"),
1261
1339
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1262
- noindex: void 0,
1340
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1263
1341
  pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1264
1342
  children,
1265
1343
  playground: void 0
@@ -1339,12 +1417,15 @@ function apiReferenceNode(ctx, scoped, scopeSegs, scopePrefix) {
1339
1417
  slug,
1340
1418
  icon: metaStr(seg.metadata, "icon"),
1341
1419
  hidden: seg.hidden,
1342
- viewers: mergeVariantViewers(seg)
1420
+ authed: metaBool(seg.metadata, "authed"),
1421
+ viewers: mergeVariantViewers(seg),
1422
+ orphaned: metaBool(seg.metadata, "orphaned"),
1423
+ featureFlags: metaFeatureFlags(seg.metadata)
1343
1424
  }),
1344
1425
  apiDefinitionId: ApiDefinitionId(apiDefinitionId),
1345
- availability: void 0,
1426
+ availability: metaStr(seg.metadata, "availability"),
1346
1427
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1347
- noindex: void 0,
1428
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1348
1429
  paginated: true,
1349
1430
  showErrors: metaBool(seg.metadata, "showErrors"),
1350
1431
  hideTitle: metaBool(seg.metadata, "hideTitle"),
@@ -1397,12 +1478,15 @@ function changelogNode(ctx, scoped, scopePrefix) {
1397
1478
  slug: ctx.contentSlug(r.fullPath ?? ""),
1398
1479
  icon: metaStr(r.metadata, "icon"),
1399
1480
  hidden: r.hidden,
1400
- viewers: toViewers(metaStrArr(r.metadata, "viewers"))
1481
+ authed: metaBool(r.metadata, "authed"),
1482
+ viewers: toViewers(metaStrArr(r.metadata, "viewers")),
1483
+ orphaned: metaBool(r.metadata, "orphaned"),
1484
+ featureFlags: metaFeatureFlags(r.metadata)
1401
1485
  }),
1402
1486
  pageId: PageId(metaStr(r.metadata, "pageId") ?? ""),
1403
- noindex: void 0,
1487
+ noindex: metaBool(r.metadata, "noindex"),
1404
1488
  date: dateStr ?? "",
1405
- tags: void 0
1489
+ tags: metaStrArr(r.metadata, "tags")
1406
1490
  };
1407
1491
  let months = byYear.get(year);
1408
1492
  if (months == null) {
@@ -1446,10 +1530,13 @@ function changelogNode(ctx, scoped, scopePrefix) {
1446
1530
  slug: baseSlug,
1447
1531
  icon: metaStr(seg.metadata, "icon"),
1448
1532
  hidden: seg.hidden,
1449
- viewers: mergeVariantViewers(seg)
1533
+ authed: metaBool(seg.metadata, "authed"),
1534
+ viewers: mergeVariantViewers(seg),
1535
+ orphaned: metaBool(seg.metadata, "orphaned"),
1536
+ featureFlags: metaFeatureFlags(seg.metadata)
1450
1537
  }),
1451
1538
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1452
- noindex: void 0,
1539
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1453
1540
  children: years
1454
1541
  };
1455
1542
  }
@@ -1491,7 +1578,7 @@ function buildSectionTree(ctx, scopeSegs, parentPath, scopePrefix, changelogScop
1491
1578
  const type = metaStr(s.seg.metadata, "type");
1492
1579
  const childIndex = metaNum(s.seg.metadata, "childIndex");
1493
1580
  let node;
1494
- if (type === "apiReference" || type === "apiPackage") {
1581
+ if (API_NODE_SEGMENT_TYPES.has(type ?? "")) {
1495
1582
  node = apiReferenceNode(ctx, s, scopeSegs, scopePrefix);
1496
1583
  } else if (type === "changelog") {
1497
1584
  node = changelogNode(ctx, s, changelogScopePrefix ?? scopePrefix);
@@ -1506,18 +1593,56 @@ function buildSectionTree(ctx, scopeSegs, parentPath, scopePrefix, changelogScop
1506
1593
  return { node, childIndex };
1507
1594
  });
1508
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
+ }
1509
1630
  function buildSidebarRootChildren(ctx, scopeSegs, scopePrefix, changelogScopePrefix) {
1510
1631
  const ordered = [...scopeSegs].sort((a, b) => a.seg.sortOrder - b.seg.sortOrder);
1511
1632
  const sectionPaths = new Set(ordered.map((s) => s.seg.section));
1512
1633
  const annotated = [];
1513
1634
  const hasRootSection = ordered.some((s) => metaStr(s.seg.metadata, "type") === "section" && s.seg.section === "");
1635
+ const siblingBoundaries = computeSiblingSortBoundaries(ordered);
1514
1636
  for (const s of ordered) {
1515
1637
  const type = metaStr(s.seg.metadata, "type");
1516
1638
  const sec = s.seg.section;
1517
1639
  if (hasOwningApiReference(s, scopeSegs)) {
1518
1640
  continue;
1519
1641
  }
1520
- 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 ?? "")) {
1521
1646
  for (const r of s.nav) {
1522
1647
  const node = artifactToNode(ctx, r);
1523
1648
  if (node != null) {
@@ -1534,24 +1659,31 @@ function buildSidebarRootChildren(ctx, scopeSegs, scopePrefix, changelogScopePre
1534
1659
  }
1535
1660
  const parent = parentSectionPath(sec);
1536
1661
  const isRootLevel = parent === "" || !sectionPaths.has(parent) && nearestExistingAncestor(sec, sectionPaths) === "";
1537
- if (isRootLevel && hasRootSection) {
1662
+ if (isRootLevel && hasRootSection && sec !== "") {
1538
1663
  continue;
1539
1664
  }
1540
1665
  if (isRootLevel) {
1541
1666
  let node;
1542
- if (type === "apiReference" || type === "apiPackage") {
1667
+ if (API_NODE_SEGMENT_TYPES.has(type ?? "")) {
1543
1668
  node = apiReferenceNode(ctx, s, scopeSegs, scopePrefix);
1544
1669
  } else if (type === "changelog") {
1545
1670
  node = changelogNode(ctx, s, changelogScopePrefix ?? scopePrefix);
1546
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;
1547
1674
  node = sectionNode(
1548
1675
  ctx,
1549
1676
  s,
1550
- buildSectionTree(ctx, scopeSegs, sec, scopePrefix, changelogScopePrefix),
1677
+ buildSectionTree(ctx, ownedSegs, sec, scopePrefix, changelogScopePrefix),
1551
1678
  scopePrefix
1552
1679
  );
1553
1680
  }
1554
- 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
+ });
1555
1687
  }
1556
1688
  }
1557
1689
  const hasLeafPos = annotated.some((a) => a.isLeaf && a.pos != null);
@@ -1603,13 +1735,13 @@ function buildSidebarRoot(ctx, scopeSegs, scopePrefix, changelogScopePrefix) {
1603
1735
  };
1604
1736
  }
1605
1737
  function buildFullRootFromSegments(options) {
1606
- const { basePath, title, segments, navBySegment } = options;
1738
+ const { basePath, rootSlug: sourceRootSlug, title, segments, navBySegment, skipSharedSectionMerge } = options;
1607
1739
  const ctx = createBuildContext(basePath);
1608
1740
  const scoped = segments.filter((seg) => {
1609
1741
  const t = metaStr(seg.metadata, "type");
1610
- return t !== "files" && t !== "redirects";
1742
+ return !INFRA_SEGMENT_TYPES.has(t ?? "");
1611
1743
  }).map((seg) => ({ seg, nav: navBySegment.get(seg.segmentHash) ?? [] }));
1612
- const rootSlug = asSlug(basePath);
1744
+ const rootSlug = asSlug(sourceRootSlug ?? basePath);
1613
1745
  const scopesByKey = /* @__PURE__ */ new Map();
1614
1746
  for (const s of scoped) {
1615
1747
  const key = scopeKey(s.seg);
@@ -1622,9 +1754,9 @@ function buildFullRootFromSegments(options) {
1622
1754
  const tabs = uniqueDetails(scoped, "tab");
1623
1755
  let child;
1624
1756
  if (products.length > 0) {
1625
- child = buildProductGroup(ctx, products, scoped, rootSlug);
1757
+ child = buildProductGroup(ctx, products, scoped, rootSlug, skipSharedSectionMerge);
1626
1758
  } else if (versions.length > 0) {
1627
- child = buildVersioned(ctx, versions, scoped, rootSlug, void 0);
1759
+ child = buildVersioned(ctx, versions, scoped, rootSlug, void 0, skipSharedSectionMerge);
1628
1760
  } else {
1629
1761
  child = buildUnversioned(ctx, scoped, rootSlug, tabs.length > 0);
1630
1762
  }
@@ -1635,6 +1767,24 @@ function buildFullRootFromSegments(options) {
1635
1767
  } else if (child.type === "versioned") {
1636
1768
  const defaultVersion = child.children.find((v) => v.default) ?? child.children[0];
1637
1769
  rootPointsTo = defaultVersion?.pointsTo;
1770
+ } else if (child.type === "unversioned") {
1771
+ if (tabs.length > 0) {
1772
+ const firstTab = tabs[0];
1773
+ const pt = firstTab != null ? metaStr(firstTab.metadata, "pointsTo") : void 0;
1774
+ rootPointsTo = pt != null ? pointsToSlug(pt) : void 0;
1775
+ } else {
1776
+ const sorted = [...scoped].sort((a, b) => a.seg.sortOrder - b.seg.sortOrder);
1777
+ for (const s of sorted) {
1778
+ if (s.seg.hidden) {
1779
+ continue;
1780
+ }
1781
+ const pt = metaStr(s.seg.metadata, "pointsTo");
1782
+ if (pt != null) {
1783
+ rootPointsTo = pointsToSlug(pt);
1784
+ break;
1785
+ }
1786
+ }
1787
+ }
1638
1788
  }
1639
1789
  const root = {
1640
1790
  type: "root",
@@ -1647,21 +1797,22 @@ function buildFullRootFromSegments(options) {
1647
1797
  return root;
1648
1798
  }
1649
1799
  function uniqueDetails(scoped, dim) {
1650
- const bySlug = /* @__PURE__ */ new Map();
1800
+ const byKey = /* @__PURE__ */ new Map();
1651
1801
  for (const s of scoped) {
1652
1802
  const d = s.seg[dim];
1653
1803
  if (d == null) {
1654
1804
  continue;
1655
1805
  }
1656
1806
  const slug = detailSlug(d);
1657
- const existing = bySlug.get(slug);
1807
+ const key = dim === "tab" ? d.id : slug !== "" ? slug : d.id;
1808
+ const existing = byKey.get(key);
1658
1809
  if (existing == null) {
1659
- bySlug.set(slug, d);
1810
+ byKey.set(key, d);
1660
1811
  } else if (metaStr(d.metadata, "pointsTo") != null && metaStr(existing.metadata, "pointsTo") == null) {
1661
- bySlug.set(slug, d);
1812
+ byKey.set(key, d);
1662
1813
  }
1663
1814
  }
1664
- return [...bySlug.values()].sort((a, b) => a.sortOrder - b.sortOrder);
1815
+ return [...byKey.values()].sort((a, b) => a.sortOrder - b.sortOrder);
1665
1816
  }
1666
1817
  function scopeSlugPrefix(rootSlug, ...details) {
1667
1818
  const parts = [rootSlug];
@@ -1695,7 +1846,7 @@ function buildVariantedNode(ctx, variants, scopeSegs, scopePrefix) {
1695
1846
  default: detailIsDefault(variant),
1696
1847
  variantId: VariantId(String(variant.id)),
1697
1848
  subtitle: metaStr(variant.metadata, "subtitle") ?? void 0,
1698
- image: void 0,
1849
+ image: metaStr(variant.metadata, "image") != null ? FileId(metaStr(variant.metadata, "image")) : void 0,
1699
1850
  pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1700
1851
  children
1701
1852
  };
@@ -1712,20 +1863,34 @@ function buildSidebarRootWithVariants(ctx, scopeSegs, scopePrefix, changelogScop
1712
1863
  if (variants.length <= 1) {
1713
1864
  return buildSidebarRoot(ctx, scopeSegs, scopePrefix, changelogScopePrefix);
1714
1865
  }
1866
+ const sharedSegs = scopeSegs.filter((s) => s.seg.variant == null);
1715
1867
  const variantedNode = buildVariantedNode(ctx, variants, scopeSegs, scopePrefix);
1868
+ const sharedChildren = sharedSegs.length > 0 ? buildSidebarRootChildren(ctx, sharedSegs, scopePrefix, changelogScopePrefix) : [];
1716
1869
  const first = scopeSegs[0];
1717
1870
  return {
1718
1871
  type: "sidebarRoot",
1719
1872
  id: ctx.nodeId(`sidebar:${first != null ? scopeKey(first.seg) : "root"}`),
1720
1873
  collapsed: void 0,
1721
- children: [variantedNode]
1874
+ children: [...sharedChildren, variantedNode]
1722
1875
  };
1723
1876
  }
1724
1877
  function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix) {
1725
1878
  if (!tabsPresent) {
1726
1879
  const variants = uniqueDetails(scopeSegs, "variant");
1727
1880
  if (variants.length > 1) {
1728
- 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;
1729
1894
  }
1730
1895
  return buildSidebarRoot(ctx, scopeSegs, scopePrefix);
1731
1896
  }
@@ -1744,7 +1909,7 @@ function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix) {
1744
1909
  title: tab.displayName,
1745
1910
  icon: tab.icon ?? void 0,
1746
1911
  url: Url(metaStr(tab.metadata, "url") ?? ""),
1747
- target: void 0
1912
+ target: metaStr(tab.metadata, "target")
1748
1913
  };
1749
1914
  }
1750
1915
  if (tabType === "changelog") {
@@ -1805,16 +1970,71 @@ function buildUnversioned(ctx, scopeSegs, scopePrefix, tabsPresent) {
1805
1970
  type: "unversioned",
1806
1971
  id: ctx.nodeId(`unversioned:${first?.seg.product?.id ?? "root"}`),
1807
1972
  collapsed: void 0,
1808
- landingPage: void 0,
1973
+ landingPage: buildLandingPage(ctx, scopeSegs),
1809
1974
  // The enclosing scope prefix (product slug, or rootSlug at the top
1810
1975
  // level) roots structural sections so they share the scope's slug
1811
1976
  // namespace.
1812
1977
  child: buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix)
1813
1978
  };
1814
1979
  }
1815
- 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 !== "");
1816
2033
  const children = versions.map((version) => {
1817
- 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
+ }
1818
2038
  const tabsPresent = uniqueDetails(versionSegs, "tab").length > 0;
1819
2039
  const prefix = productPrefix != null ? productPrefix : rootSlug;
1820
2040
  const versionSegment = detailSlug(version);
@@ -1832,7 +2052,7 @@ function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix) {
1832
2052
  default: detailIsDefault(version),
1833
2053
  versionId: VersionId(version.id),
1834
2054
  availability: void 0,
1835
- landingPage: buildVersionLandingPage(ctx, versionSegs, asSlug(slug)),
2055
+ landingPage: buildLandingPage(ctx, versionSegs),
1836
2056
  announcement: void 0,
1837
2057
  pointsTo: metaStr(version.metadata, "pointsTo") != null ? pointsToSlug(metaStr(version.metadata, "pointsTo")) : void 0,
1838
2058
  // The version's full slug roots structural sections so the whole
@@ -1913,34 +2133,41 @@ function crossVersionDedupKeys(node, parents) {
1913
2133
  keys.push([...parentTitles, node.title].join("###"));
1914
2134
  return keys;
1915
2135
  }
1916
- function buildVersionLandingPage(ctx, versionSegs, versionSlug) {
1917
- const tablessSegs = versionSegs.filter((s) => s.seg.tab == null);
1918
- if (tablessSegs.length === 0) {
2136
+ function routeToLandingPage(ctx, route) {
2137
+ if (route == null || route.type !== "markdown" || route.fullPath == null) {
1919
2138
  return void 0;
1920
2139
  }
1921
- for (const s of tablessSegs) {
1922
- for (const r of s.nav) {
1923
- if (r.type === "markdown" && r.fullPath != null) {
1924
- const md = r.metadata;
1925
- const pageId = metaStr(md, "pageId") ?? "";
1926
- const slug = ctx.contentSlug(r.fullPath);
1927
- return {
1928
- type: "landingPage",
1929
- ...withMetadataDefaults({
1930
- id: ctx.nodeId(`landing:${slug}`),
1931
- title: metaStr(md, "title") ?? "",
1932
- slug,
1933
- icon: metaStr(md, "icon"),
1934
- hidden: r.hidden,
1935
- viewers: toViewers(metaStrArr(md, "viewers"))
1936
- }),
1937
- pageId: PageId(pageId),
1938
- noindex: metaBool(md, "noindex")
1939
- };
1940
- }
1941
- }
2140
+ const md = route.metadata;
2141
+ const pageId = metaStr(md, "pageId");
2142
+ if (pageId == null) {
2143
+ return void 0;
1942
2144
  }
1943
- 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
+ );
1944
2171
  }
1945
2172
  function markCrossVersionCanonicalSlugs(versionNodes) {
1946
2173
  const keyToCanonical = /* @__PURE__ */ new Map();
@@ -1975,13 +2202,13 @@ function markCrossVersionCanonicalSlugs(versionNodes) {
1975
2202
  });
1976
2203
  }
1977
2204
  }
1978
- function buildProductGroup(ctx, products, scoped, rootSlug) {
2205
+ function buildProductGroup(ctx, products, scoped, rootSlug, skipSharedSectionMerge) {
1979
2206
  const children = products.map((product) => {
1980
2207
  const productSegs = scoped.filter((s) => s.seg.product?.id === product.id);
1981
2208
  const versions = uniqueDetails(productSegs, "version");
1982
2209
  const tabsPresent = uniqueDetails(productSegs, "tab").length > 0;
1983
2210
  const productPrefix = scopeSlugPrefix(rootSlug, product);
1984
- 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);
1985
2212
  const node = {
1986
2213
  type: "product",
1987
2214
  ...withMetadataDefaults({
@@ -2000,7 +2227,7 @@ function buildProductGroup(ctx, products, scoped, rootSlug) {
2000
2227
  // here; sourcing it from the hash makes that filter match nothing.
2001
2228
  productId: ProductId(product.displayName),
2002
2229
  subtitle: metaStr(product.metadata, "subtitle") ?? "",
2003
- image: void 0,
2230
+ image: metaStr(product.metadata, "image") != null ? FileId(metaStr(product.metadata, "image")) : void 0,
2004
2231
  announcement: void 0,
2005
2232
  pointsTo: metaStr(product.metadata, "pointsTo") != null ? pointsToSlug(metaStr(product.metadata, "pointsTo")) : void 0,
2006
2233
  child: productChild
@@ -2011,7 +2238,10 @@ function buildProductGroup(ctx, products, scoped, rootSlug) {
2011
2238
  type: "productgroup",
2012
2239
  id: ctx.nodeId("productgroup"),
2013
2240
  collapsed: void 0,
2014
- landingPage: void 0,
2241
+ landingPage: buildLandingPage(
2242
+ ctx,
2243
+ scoped.filter((s) => s.seg.product == null)
2244
+ ),
2015
2245
  children
2016
2246
  };
2017
2247
  }