@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
@@ -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
  });
@@ -843,6 +846,14 @@ function traverseDF(node, visit) {
843
846
  }
844
847
 
845
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"]);
846
857
  function createBuildContext(basePath) {
847
858
  const seen = /* @__PURE__ */ new Map();
848
859
  const basePrefix = basePath.replace(/^\/+|\/+$/g, "");
@@ -906,6 +917,13 @@ function metaStrArr(metadata, key) {
906
917
  }
907
918
  return void 0;
908
919
  }
920
+ function metaFeatureFlags(metadata) {
921
+ if (metadata != null && typeof metadata === "object" && "featureFlags" in metadata) {
922
+ const v = metadata.featureFlags;
923
+ return Array.isArray(v) && v.length > 0 ? v : void 0;
924
+ }
925
+ return void 0;
926
+ }
909
927
  function toViewers(viewers) {
910
928
  if (viewers == null || viewers.length === 0) {
911
929
  return void 0;
@@ -913,7 +931,7 @@ function toViewers(viewers) {
913
931
  return viewers.map((v) => RoleId(v));
914
932
  }
915
933
  function mergeVariantViewers(seg) {
916
- 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;
917
935
  const variantViewers = seg.variant?.viewers;
918
936
  if ((segViewers == null || segViewers.length === 0) && (variantViewers == null || variantViewers.length === 0)) {
919
937
  return void 0;
@@ -941,17 +959,17 @@ function scopeKey(seg) {
941
959
  return [seg.product?.id ?? "", seg.version?.id ?? "", seg.variant?.id ?? "", seg.tab?.id ?? ""].join("|");
942
960
  }
943
961
  function withMetadataDefaults(base) {
944
- const { viewers, ...rest } = base;
962
+ const { viewers, featureFlags, ...rest } = base;
945
963
  return {
946
964
  ...rest,
947
965
  canonicalSlug: void 0,
948
- authed: void 0,
966
+ authed: base.authed === true ? true : void 0,
949
967
  collapsed: void 0,
950
968
  // Normalise empty arrays to undefined so unrestricted nodes don't add
951
969
  // filter-level noise; a non-empty array engages the RBAC view gate.
952
970
  viewers: viewers != null && viewers.length > 0 ? viewers : void 0,
953
- orphaned: void 0,
954
- featureFlags: void 0
971
+ orphaned: base.orphaned === true ? true : void 0,
972
+ featureFlags: featureFlags != null && featureFlags.length > 0 ? featureFlags : void 0
955
973
  };
956
974
  }
957
975
  function artifactToNode(ctx, route) {
@@ -974,7 +992,10 @@ function artifactToNode(ctx, route) {
974
992
  slug,
975
993
  icon,
976
994
  hidden: route.hidden,
977
- viewers
995
+ authed: metaBool(md, "authed"),
996
+ viewers,
997
+ orphaned: metaBool(md, "orphaned"),
998
+ featureFlags: metaFeatureFlags(md)
978
999
  }),
979
1000
  pageId: PageId(pageId),
980
1001
  noindex: metaBool(md, "noindex"),
@@ -990,7 +1011,7 @@ function artifactToNode(ctx, route) {
990
1011
  title,
991
1012
  icon,
992
1013
  url: Url(metaStr(md, "url") ?? ""),
993
- target: void 0
1014
+ target: metaStr(md, "target")
994
1015
  };
995
1016
  return node;
996
1017
  }
@@ -1025,7 +1046,10 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
1025
1046
  slug,
1026
1047
  icon,
1027
1048
  hidden: route.hidden,
1028
- viewers
1049
+ authed: metaBool(md, "authed"),
1050
+ viewers,
1051
+ orphaned: metaBool(md, "orphaned"),
1052
+ featureFlags: metaFeatureFlags(md)
1029
1053
  });
1030
1054
  if (route.type === "rest") {
1031
1055
  const endpointId = metaStr(md, "endpointId");
@@ -1040,7 +1064,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
1040
1064
  endpointId: EndpointId(endpointId),
1041
1065
  apiDefinitionId,
1042
1066
  isResponseStream: metaBool(md, "isResponseStream"),
1043
- availability: void 0,
1067
+ availability: metaStr(md, "availability"),
1044
1068
  playground: void 0
1045
1069
  };
1046
1070
  }
@@ -1056,7 +1080,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
1056
1080
  method,
1057
1081
  webhookId: WebhookId(webhookId),
1058
1082
  apiDefinitionId,
1059
- availability: void 0
1083
+ availability: metaStr(md, "availability")
1060
1084
  };
1061
1085
  }
1062
1086
  if (route.type === "asyncapi") {
@@ -1069,7 +1093,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
1069
1093
  ...meta,
1070
1094
  webSocketId: WebSocketId(webSocketId),
1071
1095
  apiDefinitionId,
1072
- availability: void 0,
1096
+ availability: metaStr(md, "availability"),
1073
1097
  playground: void 0
1074
1098
  };
1075
1099
  }
@@ -1085,7 +1109,7 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
1085
1109
  method,
1086
1110
  grpcId: GrpcId(grpcId),
1087
1111
  apiDefinitionId,
1088
- availability: void 0
1112
+ availability: metaStr(md, "availability")
1089
1113
  };
1090
1114
  }
1091
1115
  if (route.type === "graphql") {
@@ -1101,12 +1125,69 @@ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
1101
1125
  graphqlOperationId: GraphQlOperationId(graphqlOperationId),
1102
1126
  graphqlOperationIds: void 0,
1103
1127
  apiDefinitionId,
1104
- availability: void 0,
1128
+ availability: metaStr(md, "availability"),
1105
1129
  playground: void 0
1106
1130
  };
1107
1131
  }
1108
1132
  return void 0;
1109
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
+ }
1110
1191
  function collectApiLeafNodesFromNav(routes, basePath, segmentApiDefinitionId2) {
1111
1192
  const ctx = createBuildContext(basePath);
1112
1193
  return routes.map((route) => apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2)).filter((node) => node != null);
@@ -1208,17 +1289,20 @@ function sectionNode(ctx, scoped, sectionChildren, scopePrefix) {
1208
1289
  slug,
1209
1290
  icon: metaStr(seg.metadata, "icon"),
1210
1291
  hidden: seg.hidden,
1211
- viewers: mergeVariantViewers(seg)
1292
+ authed: metaBool(seg.metadata, "authed"),
1293
+ viewers: mergeVariantViewers(seg),
1294
+ orphaned: metaBool(seg.metadata, "orphaned"),
1295
+ featureFlags: metaFeatureFlags(seg.metadata)
1212
1296
  });
1213
1297
  return {
1214
1298
  type: "section",
1215
1299
  ...defaults,
1216
1300
  collapsed: metaCollapsed(seg.metadata) ?? defaults.collapsed,
1217
1301
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1218
- noindex: void 0,
1219
- collapsible: metaBool(seg.metadata, "collapsible") ?? (metaCollapsed(seg.metadata) != null ? true : void 0),
1302
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1303
+ collapsible: metaBool(seg.metadata, "collapsible") ?? (metaCollapsed(seg.metadata) === true ? true : void 0),
1220
1304
  collapsedByDefault: metaBool(seg.metadata, "collapsedByDefault") ?? (metaCollapsed(seg.metadata) === true ? true : void 0),
1221
- availability: void 0,
1305
+ availability: metaStr(seg.metadata, "availability"),
1222
1306
  pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1223
1307
  children: mergeChildrenByPosition(ctx, nav, sectionChildren)
1224
1308
  };
@@ -1241,8 +1325,7 @@ function directChildApiPackages(parentSection, scopeSegs) {
1241
1325
  }
1242
1326
  function buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix) {
1243
1327
  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);
1328
+ const leafNodes = positionedApiLeafChildren(ctx, nav, apiDefinitionId);
1246
1329
  const childPackages = directChildApiPackages(seg.section, scopeSegs);
1247
1330
  const packageNodes = childPackages.map((child) => ({
1248
1331
  node: apiPackageChildNode(
@@ -1256,18 +1339,10 @@ function buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix)
1256
1339
  }));
1257
1340
  const hasChildIndex = packageNodes.some((p) => p.childIndex != null);
1258
1341
  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
- }
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);
1266
1343
  }
1267
1344
  const positioned = [];
1268
- for (let i = 0; i < leafNodes.length; i++) {
1269
- positioned.push({ node: leafNodes[i], pos: leafPositions[i] ?? i });
1270
- }
1345
+ positioned.push(...leafNodes);
1271
1346
  for (const p of packageNodes) {
1272
1347
  positioned.push({ node: p.node, pos: p.childIndex ?? Number.MAX_SAFE_INTEGER });
1273
1348
  }
@@ -1295,12 +1370,15 @@ function apiPackageChildNode(ctx, scoped, scopeSegs, parentApiDefinitionId, scop
1295
1370
  slug,
1296
1371
  icon: metaStr(seg.metadata, "icon"),
1297
1372
  hidden: seg.hidden,
1298
- viewers: toViewers(metaStrArr(seg.metadata, "viewers"))
1373
+ authed: metaBool(seg.metadata, "authed"),
1374
+ viewers: toViewers(metaStrArr(seg.metadata, "viewers")),
1375
+ orphaned: metaBool(seg.metadata, "orphaned"),
1376
+ featureFlags: metaFeatureFlags(seg.metadata)
1299
1377
  }),
1300
1378
  apiDefinitionId: ApiDefinitionId(apiDefinitionId),
1301
1379
  availability: metaStr(seg.metadata, "availability"),
1302
1380
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1303
- noindex: void 0,
1381
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1304
1382
  pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1305
1383
  children,
1306
1384
  playground: void 0
@@ -1380,12 +1458,15 @@ function apiReferenceNode(ctx, scoped, scopeSegs, scopePrefix) {
1380
1458
  slug,
1381
1459
  icon: metaStr(seg.metadata, "icon"),
1382
1460
  hidden: seg.hidden,
1383
- viewers: mergeVariantViewers(seg)
1461
+ authed: metaBool(seg.metadata, "authed"),
1462
+ viewers: mergeVariantViewers(seg),
1463
+ orphaned: metaBool(seg.metadata, "orphaned"),
1464
+ featureFlags: metaFeatureFlags(seg.metadata)
1384
1465
  }),
1385
1466
  apiDefinitionId: ApiDefinitionId(apiDefinitionId),
1386
- availability: void 0,
1467
+ availability: metaStr(seg.metadata, "availability"),
1387
1468
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1388
- noindex: void 0,
1469
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1389
1470
  paginated: true,
1390
1471
  showErrors: metaBool(seg.metadata, "showErrors"),
1391
1472
  hideTitle: metaBool(seg.metadata, "hideTitle"),
@@ -1438,12 +1519,15 @@ function changelogNode(ctx, scoped, scopePrefix) {
1438
1519
  slug: ctx.contentSlug(r.fullPath ?? ""),
1439
1520
  icon: metaStr(r.metadata, "icon"),
1440
1521
  hidden: r.hidden,
1441
- viewers: toViewers(metaStrArr(r.metadata, "viewers"))
1522
+ authed: metaBool(r.metadata, "authed"),
1523
+ viewers: toViewers(metaStrArr(r.metadata, "viewers")),
1524
+ orphaned: metaBool(r.metadata, "orphaned"),
1525
+ featureFlags: metaFeatureFlags(r.metadata)
1442
1526
  }),
1443
1527
  pageId: PageId(metaStr(r.metadata, "pageId") ?? ""),
1444
- noindex: void 0,
1528
+ noindex: metaBool(r.metadata, "noindex"),
1445
1529
  date: dateStr ?? "",
1446
- tags: void 0
1530
+ tags: metaStrArr(r.metadata, "tags")
1447
1531
  };
1448
1532
  let months = byYear.get(year);
1449
1533
  if (months == null) {
@@ -1487,10 +1571,13 @@ function changelogNode(ctx, scoped, scopePrefix) {
1487
1571
  slug: baseSlug,
1488
1572
  icon: metaStr(seg.metadata, "icon"),
1489
1573
  hidden: seg.hidden,
1490
- viewers: mergeVariantViewers(seg)
1574
+ authed: metaBool(seg.metadata, "authed"),
1575
+ viewers: mergeVariantViewers(seg),
1576
+ orphaned: metaBool(seg.metadata, "orphaned"),
1577
+ featureFlags: metaFeatureFlags(seg.metadata)
1491
1578
  }),
1492
1579
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1493
- noindex: void 0,
1580
+ noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
1494
1581
  children: years
1495
1582
  };
1496
1583
  }
@@ -1532,7 +1619,7 @@ function buildSectionTree(ctx, scopeSegs, parentPath, scopePrefix, changelogScop
1532
1619
  const type = metaStr(s.seg.metadata, "type");
1533
1620
  const childIndex = metaNum(s.seg.metadata, "childIndex");
1534
1621
  let node;
1535
- if (type === "apiReference" || type === "apiPackage") {
1622
+ if (API_NODE_SEGMENT_TYPES.has(type ?? "")) {
1536
1623
  node = apiReferenceNode(ctx, s, scopeSegs, scopePrefix);
1537
1624
  } else if (type === "changelog") {
1538
1625
  node = changelogNode(ctx, s, changelogScopePrefix ?? scopePrefix);
@@ -1547,18 +1634,56 @@ function buildSectionTree(ctx, scopeSegs, parentPath, scopePrefix, changelogScop
1547
1634
  return { node, childIndex };
1548
1635
  });
1549
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
+ }
1550
1671
  function buildSidebarRootChildren(ctx, scopeSegs, scopePrefix, changelogScopePrefix) {
1551
1672
  const ordered = [...scopeSegs].sort((a, b) => a.seg.sortOrder - b.seg.sortOrder);
1552
1673
  const sectionPaths = new Set(ordered.map((s) => s.seg.section));
1553
1674
  const annotated = [];
1554
1675
  const hasRootSection = ordered.some((s) => metaStr(s.seg.metadata, "type") === "section" && s.seg.section === "");
1676
+ const siblingBoundaries = computeSiblingSortBoundaries(ordered);
1555
1677
  for (const s of ordered) {
1556
1678
  const type = metaStr(s.seg.metadata, "type");
1557
1679
  const sec = s.seg.section;
1558
1680
  if (hasOwningApiReference(s, scopeSegs)) {
1559
1681
  continue;
1560
1682
  }
1561
- 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 ?? "")) {
1562
1687
  for (const r of s.nav) {
1563
1688
  const node = artifactToNode(ctx, r);
1564
1689
  if (node != null) {
@@ -1575,24 +1700,31 @@ function buildSidebarRootChildren(ctx, scopeSegs, scopePrefix, changelogScopePre
1575
1700
  }
1576
1701
  const parent = parentSectionPath(sec);
1577
1702
  const isRootLevel = parent === "" || !sectionPaths.has(parent) && nearestExistingAncestor(sec, sectionPaths) === "";
1578
- if (isRootLevel && hasRootSection) {
1703
+ if (isRootLevel && hasRootSection && sec !== "") {
1579
1704
  continue;
1580
1705
  }
1581
1706
  if (isRootLevel) {
1582
1707
  let node;
1583
- if (type === "apiReference" || type === "apiPackage") {
1708
+ if (API_NODE_SEGMENT_TYPES.has(type ?? "")) {
1584
1709
  node = apiReferenceNode(ctx, s, scopeSegs, scopePrefix);
1585
1710
  } else if (type === "changelog") {
1586
1711
  node = changelogNode(ctx, s, changelogScopePrefix ?? scopePrefix);
1587
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;
1588
1715
  node = sectionNode(
1589
1716
  ctx,
1590
1717
  s,
1591
- buildSectionTree(ctx, scopeSegs, sec, scopePrefix, changelogScopePrefix),
1718
+ buildSectionTree(ctx, ownedSegs, sec, scopePrefix, changelogScopePrefix),
1592
1719
  scopePrefix
1593
1720
  );
1594
1721
  }
1595
- 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
+ });
1596
1728
  }
1597
1729
  }
1598
1730
  const hasLeafPos = annotated.some((a) => a.isLeaf && a.pos != null);
@@ -1644,13 +1776,13 @@ function buildSidebarRoot(ctx, scopeSegs, scopePrefix, changelogScopePrefix) {
1644
1776
  };
1645
1777
  }
1646
1778
  function buildFullRootFromSegments(options) {
1647
- const { basePath, title, segments, navBySegment } = options;
1779
+ const { basePath, rootSlug: sourceRootSlug, title, segments, navBySegment, skipSharedSectionMerge } = options;
1648
1780
  const ctx = createBuildContext(basePath);
1649
1781
  const scoped = segments.filter((seg) => {
1650
1782
  const t = metaStr(seg.metadata, "type");
1651
- return t !== "files" && t !== "redirects";
1783
+ return !INFRA_SEGMENT_TYPES.has(t ?? "");
1652
1784
  }).map((seg) => ({ seg, nav: navBySegment.get(seg.segmentHash) ?? [] }));
1653
- const rootSlug = asSlug(basePath);
1785
+ const rootSlug = asSlug(sourceRootSlug ?? basePath);
1654
1786
  const scopesByKey = /* @__PURE__ */ new Map();
1655
1787
  for (const s of scoped) {
1656
1788
  const key = scopeKey(s.seg);
@@ -1663,9 +1795,9 @@ function buildFullRootFromSegments(options) {
1663
1795
  const tabs = uniqueDetails(scoped, "tab");
1664
1796
  let child;
1665
1797
  if (products.length > 0) {
1666
- child = buildProductGroup(ctx, products, scoped, rootSlug);
1798
+ child = buildProductGroup(ctx, products, scoped, rootSlug, skipSharedSectionMerge);
1667
1799
  } else if (versions.length > 0) {
1668
- child = buildVersioned(ctx, versions, scoped, rootSlug, void 0);
1800
+ child = buildVersioned(ctx, versions, scoped, rootSlug, void 0, skipSharedSectionMerge);
1669
1801
  } else {
1670
1802
  child = buildUnversioned(ctx, scoped, rootSlug, tabs.length > 0);
1671
1803
  }
@@ -1676,6 +1808,24 @@ function buildFullRootFromSegments(options) {
1676
1808
  } else if (child.type === "versioned") {
1677
1809
  const defaultVersion = child.children.find((v) => v.default) ?? child.children[0];
1678
1810
  rootPointsTo = defaultVersion?.pointsTo;
1811
+ } else if (child.type === "unversioned") {
1812
+ if (tabs.length > 0) {
1813
+ const firstTab = tabs[0];
1814
+ const pt = firstTab != null ? metaStr(firstTab.metadata, "pointsTo") : void 0;
1815
+ rootPointsTo = pt != null ? pointsToSlug(pt) : void 0;
1816
+ } else {
1817
+ const sorted = [...scoped].sort((a, b) => a.seg.sortOrder - b.seg.sortOrder);
1818
+ for (const s of sorted) {
1819
+ if (s.seg.hidden) {
1820
+ continue;
1821
+ }
1822
+ const pt = metaStr(s.seg.metadata, "pointsTo");
1823
+ if (pt != null) {
1824
+ rootPointsTo = pointsToSlug(pt);
1825
+ break;
1826
+ }
1827
+ }
1828
+ }
1679
1829
  }
1680
1830
  const root = {
1681
1831
  type: "root",
@@ -1688,21 +1838,22 @@ function buildFullRootFromSegments(options) {
1688
1838
  return root;
1689
1839
  }
1690
1840
  function uniqueDetails(scoped, dim) {
1691
- const bySlug = /* @__PURE__ */ new Map();
1841
+ const byKey = /* @__PURE__ */ new Map();
1692
1842
  for (const s of scoped) {
1693
1843
  const d = s.seg[dim];
1694
1844
  if (d == null) {
1695
1845
  continue;
1696
1846
  }
1697
1847
  const slug = detailSlug(d);
1698
- const existing = bySlug.get(slug);
1848
+ const key = dim === "tab" ? d.id : slug !== "" ? slug : d.id;
1849
+ const existing = byKey.get(key);
1699
1850
  if (existing == null) {
1700
- bySlug.set(slug, d);
1851
+ byKey.set(key, d);
1701
1852
  } else if (metaStr(d.metadata, "pointsTo") != null && metaStr(existing.metadata, "pointsTo") == null) {
1702
- bySlug.set(slug, d);
1853
+ byKey.set(key, d);
1703
1854
  }
1704
1855
  }
1705
- return [...bySlug.values()].sort((a, b) => a.sortOrder - b.sortOrder);
1856
+ return [...byKey.values()].sort((a, b) => a.sortOrder - b.sortOrder);
1706
1857
  }
1707
1858
  function scopeSlugPrefix(rootSlug, ...details) {
1708
1859
  const parts = [rootSlug];
@@ -1736,7 +1887,7 @@ function buildVariantedNode(ctx, variants, scopeSegs, scopePrefix) {
1736
1887
  default: detailIsDefault(variant),
1737
1888
  variantId: VariantId(String(variant.id)),
1738
1889
  subtitle: metaStr(variant.metadata, "subtitle") ?? void 0,
1739
- image: void 0,
1890
+ image: metaStr(variant.metadata, "image") != null ? FileId(metaStr(variant.metadata, "image")) : void 0,
1740
1891
  pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1741
1892
  children
1742
1893
  };
@@ -1753,20 +1904,34 @@ function buildSidebarRootWithVariants(ctx, scopeSegs, scopePrefix, changelogScop
1753
1904
  if (variants.length <= 1) {
1754
1905
  return buildSidebarRoot(ctx, scopeSegs, scopePrefix, changelogScopePrefix);
1755
1906
  }
1907
+ const sharedSegs = scopeSegs.filter((s) => s.seg.variant == null);
1756
1908
  const variantedNode = buildVariantedNode(ctx, variants, scopeSegs, scopePrefix);
1909
+ const sharedChildren = sharedSegs.length > 0 ? buildSidebarRootChildren(ctx, sharedSegs, scopePrefix, changelogScopePrefix) : [];
1757
1910
  const first = scopeSegs[0];
1758
1911
  return {
1759
1912
  type: "sidebarRoot",
1760
1913
  id: ctx.nodeId(`sidebar:${first != null ? scopeKey(first.seg) : "root"}`),
1761
1914
  collapsed: void 0,
1762
- children: [variantedNode]
1915
+ children: [...sharedChildren, variantedNode]
1763
1916
  };
1764
1917
  }
1765
1918
  function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix) {
1766
1919
  if (!tabsPresent) {
1767
1920
  const variants = uniqueDetails(scopeSegs, "variant");
1768
1921
  if (variants.length > 1) {
1769
- 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;
1770
1935
  }
1771
1936
  return buildSidebarRoot(ctx, scopeSegs, scopePrefix);
1772
1937
  }
@@ -1785,7 +1950,7 @@ function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix) {
1785
1950
  title: tab.displayName,
1786
1951
  icon: tab.icon ?? void 0,
1787
1952
  url: Url(metaStr(tab.metadata, "url") ?? ""),
1788
- target: void 0
1953
+ target: metaStr(tab.metadata, "target")
1789
1954
  };
1790
1955
  }
1791
1956
  if (tabType === "changelog") {
@@ -1846,16 +2011,71 @@ function buildUnversioned(ctx, scopeSegs, scopePrefix, tabsPresent) {
1846
2011
  type: "unversioned",
1847
2012
  id: ctx.nodeId(`unversioned:${first?.seg.product?.id ?? "root"}`),
1848
2013
  collapsed: void 0,
1849
- landingPage: void 0,
2014
+ landingPage: buildLandingPage(ctx, scopeSegs),
1850
2015
  // The enclosing scope prefix (product slug, or rootSlug at the top
1851
2016
  // level) roots structural sections so they share the scope's slug
1852
2017
  // namespace.
1853
2018
  child: buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix)
1854
2019
  };
1855
2020
  }
1856
- 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 !== "");
1857
2074
  const children = versions.map((version) => {
1858
- 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
+ }
1859
2079
  const tabsPresent = uniqueDetails(versionSegs, "tab").length > 0;
1860
2080
  const prefix = productPrefix != null ? productPrefix : rootSlug;
1861
2081
  const versionSegment = detailSlug(version);
@@ -1873,7 +2093,7 @@ function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix) {
1873
2093
  default: detailIsDefault(version),
1874
2094
  versionId: VersionId(version.id),
1875
2095
  availability: void 0,
1876
- landingPage: buildVersionLandingPage(ctx, versionSegs, asSlug(slug)),
2096
+ landingPage: buildLandingPage(ctx, versionSegs),
1877
2097
  announcement: void 0,
1878
2098
  pointsTo: metaStr(version.metadata, "pointsTo") != null ? pointsToSlug(metaStr(version.metadata, "pointsTo")) : void 0,
1879
2099
  // The version's full slug roots structural sections so the whole
@@ -1954,34 +2174,41 @@ function crossVersionDedupKeys(node, parents) {
1954
2174
  keys.push([...parentTitles, node.title].join("###"));
1955
2175
  return keys;
1956
2176
  }
1957
- function buildVersionLandingPage(ctx, versionSegs, versionSlug) {
1958
- const tablessSegs = versionSegs.filter((s) => s.seg.tab == null);
1959
- if (tablessSegs.length === 0) {
2177
+ function routeToLandingPage(ctx, route) {
2178
+ if (route == null || route.type !== "markdown" || route.fullPath == null) {
1960
2179
  return void 0;
1961
2180
  }
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
- }
2181
+ const md = route.metadata;
2182
+ const pageId = metaStr(md, "pageId");
2183
+ if (pageId == null) {
2184
+ return void 0;
1983
2185
  }
1984
- 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
+ );
1985
2212
  }
1986
2213
  function markCrossVersionCanonicalSlugs(versionNodes) {
1987
2214
  const keyToCanonical = /* @__PURE__ */ new Map();
@@ -2016,13 +2243,13 @@ function markCrossVersionCanonicalSlugs(versionNodes) {
2016
2243
  });
2017
2244
  }
2018
2245
  }
2019
- function buildProductGroup(ctx, products, scoped, rootSlug) {
2246
+ function buildProductGroup(ctx, products, scoped, rootSlug, skipSharedSectionMerge) {
2020
2247
  const children = products.map((product) => {
2021
2248
  const productSegs = scoped.filter((s) => s.seg.product?.id === product.id);
2022
2249
  const versions = uniqueDetails(productSegs, "version");
2023
2250
  const tabsPresent = uniqueDetails(productSegs, "tab").length > 0;
2024
2251
  const productPrefix = scopeSlugPrefix(rootSlug, product);
2025
- 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);
2026
2253
  const node = {
2027
2254
  type: "product",
2028
2255
  ...withMetadataDefaults({
@@ -2041,7 +2268,7 @@ function buildProductGroup(ctx, products, scoped, rootSlug) {
2041
2268
  // here; sourcing it from the hash makes that filter match nothing.
2042
2269
  productId: ProductId(product.displayName),
2043
2270
  subtitle: metaStr(product.metadata, "subtitle") ?? "",
2044
- image: void 0,
2271
+ image: metaStr(product.metadata, "image") != null ? FileId(metaStr(product.metadata, "image")) : void 0,
2045
2272
  announcement: void 0,
2046
2273
  pointsTo: metaStr(product.metadata, "pointsTo") != null ? pointsToSlug(metaStr(product.metadata, "pointsTo")) : void 0,
2047
2274
  child: productChild
@@ -2052,7 +2279,10 @@ function buildProductGroup(ctx, products, scoped, rootSlug) {
2052
2279
  type: "productgroup",
2053
2280
  id: ctx.nodeId("productgroup"),
2054
2281
  collapsed: void 0,
2055
- landingPage: void 0,
2282
+ landingPage: buildLandingPage(
2283
+ ctx,
2284
+ scoped.filter((s) => s.seg.product == null)
2285
+ ),
2056
2286
  children
2057
2287
  };
2058
2288
  }