@fern-api/fdr-sdk 1.2.36-eaea1f74f7 → 1.2.37-159d98cf30

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 (52) hide show
  1. package/dist/js/client/FdrClient.js +315 -55
  2. package/dist/js/client/FdrClient.js.map +1 -1
  3. package/dist/js/client/FdrClient.mjs +315 -55
  4. package/dist/js/client/FdrClient.mjs.map +1 -1
  5. package/dist/js/index.js +320 -60
  6. package/dist/js/index.js.map +1 -1
  7. package/dist/js/index.mjs +320 -60
  8. package/dist/js/index.mjs.map +1 -1
  9. package/dist/js/navigation/ledger-root-builder.js +732 -249
  10. package/dist/js/navigation/ledger-root-builder.js.map +1 -1
  11. package/dist/js/navigation/ledger-root-builder.mjs +730 -249
  12. package/dist/js/navigation/ledger-root-builder.mjs.map +1 -1
  13. package/dist/js/orpc-client.js +759 -91
  14. package/dist/js/orpc-client.js.map +1 -1
  15. package/dist/js/orpc-client.mjs +715 -86
  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.changelogSlug.test.d.ts +2 -0
  19. package/dist/types/navigation/__test__/ledger-root-builder.changelogSlug.test.d.ts.map +1 -0
  20. package/dist/types/navigation/__test__/ledger-root-builder.defaultVersionElision.test.d.ts +2 -0
  21. package/dist/types/navigation/__test__/ledger-root-builder.defaultVersionElision.test.d.ts.map +1 -0
  22. package/dist/types/navigation/__test__/ledger-root-builder.linkRepro.test.d.ts +2 -0
  23. package/dist/types/navigation/__test__/ledger-root-builder.linkRepro.test.d.ts.map +1 -0
  24. package/dist/types/navigation/__test__/ledger-root-builder.mergeEndpointPairs.test.d.ts +2 -0
  25. package/dist/types/navigation/__test__/ledger-root-builder.mergeEndpointPairs.test.d.ts.map +1 -0
  26. package/dist/types/navigation/__test__/ledger-root-builder.pointsTo.test.d.ts +2 -0
  27. package/dist/types/navigation/__test__/ledger-root-builder.pointsTo.test.d.ts.map +1 -0
  28. package/dist/types/navigation/__test__/ledger-root-builder.productId.test.d.ts +2 -0
  29. package/dist/types/navigation/__test__/ledger-root-builder.productId.test.d.ts.map +1 -0
  30. package/dist/types/navigation/__test__/ledger-root-builder.rootChildOrder.test.d.ts +2 -0
  31. package/dist/types/navigation/__test__/ledger-root-builder.rootChildOrder.test.d.ts.map +1 -0
  32. package/dist/types/navigation/__test__/ledger-root-builder.rootSectionSlug.test.d.ts +2 -0
  33. package/dist/types/navigation/__test__/ledger-root-builder.rootSectionSlug.test.d.ts.map +1 -0
  34. package/dist/types/navigation/__test__/ledger-root-builder.tabSlug.test.d.ts +2 -0
  35. package/dist/types/navigation/__test__/ledger-root-builder.tabSlug.test.d.ts.map +1 -0
  36. package/dist/types/navigation/ledger-root-builder.d.ts +26 -3
  37. package/dist/types/navigation/ledger-root-builder.d.ts.map +1 -1
  38. package/dist/types/orpc-client/client.d.ts +1 -2
  39. package/dist/types/orpc-client/client.d.ts.map +1 -1
  40. package/dist/types/orpc-client/docs-ledger/client.d.ts +1 -3
  41. package/dist/types/orpc-client/docs-ledger/client.d.ts.map +1 -1
  42. package/dist/types/orpc-client/docs-ledger/config-files.d.ts +16 -0
  43. package/dist/types/orpc-client/docs-ledger/config-files.d.ts.map +1 -0
  44. package/dist/types/orpc-client/docs-ledger/contract.d.ts +60922 -47158
  45. package/dist/types/orpc-client/docs-ledger/contract.d.ts.map +1 -1
  46. package/dist/types/orpc-client/docs-ledger/index.d.ts +3 -0
  47. package/dist/types/orpc-client/docs-ledger/index.d.ts.map +1 -1
  48. package/dist/types/orpc-client/docs-ledger/ledger-manifest.d.ts +37008 -0
  49. package/dist/types/orpc-client/docs-ledger/ledger-manifest.d.ts.map +1 -0
  50. package/dist/types/orpc-client/docs-ledger/stable-stringify.d.ts +18 -0
  51. package/dist/types/orpc-client/docs-ledger/stable-stringify.d.ts.map +1 -0
  52. package/package.json +1 -1
@@ -33,6 +33,8 @@ __export(ledger_root_builder_exports, {
33
33
  apiLeafNodeFromNavRoute: () => apiLeafNodeFromNavRoute,
34
34
  buildFullRootFromSegments: () => buildFullRootFromSegments,
35
35
  collectApiLeafNodesFromNav: () => collectApiLeafNodesFromNav,
36
+ createBuildContext: () => createBuildContext,
37
+ mergeEndpointPairs: () => mergeEndpointPairs,
36
38
  segmentApiDefinitionId: () => segmentApiDefinitionId
37
39
  });
38
40
  module.exports = __toCommonJS(ledger_root_builder_exports);
@@ -635,6 +637,82 @@ function NodeId(value) {
635
637
  function ProductId(value) {
636
638
  return value;
637
639
  }
640
+ function VariantId(value) {
641
+ return value;
642
+ }
643
+
644
+ // src/navigation/versions/latest/getChildren.ts
645
+ var import_ts_essentials = require("ts-essentials");
646
+
647
+ // src/navigation/versions/latest/NavigationNodeApiLeaf.ts
648
+ function isApiLeaf(node) {
649
+ return node.type === "endpoint" || node.type === "webSocket" || node.type === "webhook" || node.type === "grpc" || node.type === "graphql" || node.type === "graphqlType";
650
+ }
651
+
652
+ // src/navigation/versions/latest/NavigationNodePageLeaf.ts
653
+ function isMarkdownLeaf(node) {
654
+ return node.type === "page" || node.type === "landingPage" || node.type === "changelogEntry";
655
+ }
656
+
657
+ // src/navigation/versions/latest/NavigationNodeLeaf.ts
658
+ function isLeaf(node) {
659
+ return isApiLeaf(node) || isMarkdownLeaf(node) || node.type === "link";
660
+ }
661
+
662
+ // src/navigation/versions/latest/getChildren.ts
663
+ function getChildren(node) {
664
+ if (isLeaf(node)) {
665
+ return [];
666
+ }
667
+ switch (node.type) {
668
+ case "apiPackage":
669
+ case "changelog":
670
+ case "changelogMonth":
671
+ case "changelogYear":
672
+ case "section":
673
+ case "sidebarGroup":
674
+ case "sidebarRoot":
675
+ case "tabbed":
676
+ case "versioned":
677
+ case "varianted":
678
+ return node.children;
679
+ case "product":
680
+ case "root":
681
+ case "tab":
682
+ return [node.child];
683
+ case "productLink":
684
+ return [];
685
+ case "variant":
686
+ return node.children;
687
+ case "apiReference":
688
+ return [...node.children, ...node.changelog ? [node.changelog] : []];
689
+ case "endpointPair":
690
+ return [node.nonStream, node.stream];
691
+ case "productgroup":
692
+ return [...node.landingPage ? [node.landingPage] : [], ...node.children];
693
+ case "unversioned":
694
+ case "version":
695
+ return [...node.landingPage ? [node.landingPage] : [], node.child];
696
+ default:
697
+ throw new import_ts_essentials.UnreachableCaseError(node);
698
+ }
699
+ }
700
+
701
+ // src/navigation/versions/latest/NavigationNodeWithMetadata.ts
702
+ function hasMetadata(node) {
703
+ return typeof node.title === "string" && typeof node.slug === "string";
704
+ }
705
+
706
+ // src/navigation/versions/latest/NavigationNodeWithRedirect.ts
707
+ function hasPointsTo(node) {
708
+ return node.type === "root" || node.type === "product" || node.type === "version" || node.type === "tab" || node.type === "section" || node.type === "apiReference" || node.type === "apiPackage";
709
+ }
710
+ function hasRedirect(node) {
711
+ if (!hasPointsTo(node)) {
712
+ return false;
713
+ }
714
+ return node.pointsTo != null;
715
+ }
638
716
 
639
717
  // ../commons/core-utils/dist/isNonNullish.js
640
718
  function isNonNullish(x) {
@@ -650,10 +728,50 @@ function slugjoin(...parts) {
650
728
  return Slug(normalized);
651
729
  }
652
730
 
731
+ // src/navigation/versions/latest/toDefaultSlug.ts
732
+ var import_string = require("es-toolkit/string");
733
+ function toDefaultSlug(slug, rootSlug, versionSlug) {
734
+ if (slug == null) {
735
+ return void 0;
736
+ }
737
+ if (slug.startsWith(versionSlug)) {
738
+ return Slug(slug.replace(new RegExp(`^${(0, import_string.escapeRegExp)(versionSlug)}`), rootSlug).replace(/^\//, ""));
739
+ }
740
+ return slug;
741
+ }
742
+
743
+ // src/utils/traversers/types.ts
744
+ var SKIP = "skip";
745
+ var STOP = false;
746
+
747
+ // src/utils/traversers/dfs.ts
748
+ function dfs(root, visit, getChildren2, isParent = (node) => true) {
749
+ const stack = [[root, []]];
750
+ while (stack.length > 0) {
751
+ const [node, parents] = stack.pop() ?? [];
752
+ if (!node) {
753
+ continue;
754
+ }
755
+ const next = visit(node, parents ?? []);
756
+ if (next === SKIP) {
757
+ continue;
758
+ } else if (next === STOP) {
759
+ return;
760
+ }
761
+ if (isParent(node)) {
762
+ for (const child of [...getChildren2(node)].reverse()) {
763
+ stack.push([child, [...parents ?? [], node]]);
764
+ }
765
+ }
766
+ }
767
+ }
768
+
769
+ // src/navigation/versions/latest/traverseDF.ts
770
+ function traverseDF(node, visit) {
771
+ return dfs(node, visit, getChildren);
772
+ }
773
+
653
774
  // src/navigation/ledger-root-builder.ts
654
- var segMeta = (seg) => seg.metadata ?? {};
655
- var routeMeta = (route) => route.metadata ?? {};
656
- var detailMeta = (detail) => detail.metadata ?? {};
657
775
  function createBuildContext(basePath) {
658
776
  const seen = /* @__PURE__ */ new Map();
659
777
  const basePrefix = basePath.replace(/^\/+|\/+$/g, "");
@@ -672,6 +790,51 @@ function createBuildContext(basePath) {
672
790
  function asSlug(path) {
673
791
  return Slug(path.replace(/^\/+|\/+$/g, ""));
674
792
  }
793
+ function pointsToSlug(metaPointsTo) {
794
+ return asSlug(metaPointsTo);
795
+ }
796
+ function metaStr(metadata, key) {
797
+ if (metadata != null && typeof metadata === "object" && key in metadata) {
798
+ const v = metadata[key];
799
+ return typeof v === "string" ? v : void 0;
800
+ }
801
+ return void 0;
802
+ }
803
+ function metaBool(metadata, key) {
804
+ if (metadata != null && typeof metadata === "object" && key in metadata) {
805
+ const v = metadata[key];
806
+ return typeof v === "boolean" ? v : void 0;
807
+ }
808
+ return void 0;
809
+ }
810
+ function metaNum(metadata, key) {
811
+ if (metadata != null && typeof metadata === "object" && key in metadata) {
812
+ const v = metadata[key];
813
+ return typeof v === "number" ? v : void 0;
814
+ }
815
+ return void 0;
816
+ }
817
+ function metaCollapsed(metadata) {
818
+ if (metadata != null && typeof metadata === "object" && "collapsed" in metadata) {
819
+ const v = metadata.collapsed;
820
+ if (typeof v === "boolean") {
821
+ return v;
822
+ }
823
+ if (v === "open-by-default") {
824
+ return "open-by-default";
825
+ }
826
+ }
827
+ return void 0;
828
+ }
829
+ function metaStrArr(metadata, key) {
830
+ if (metadata != null && typeof metadata === "object" && key in metadata) {
831
+ const v = metadata[key];
832
+ if (Array.isArray(v)) {
833
+ return v.filter((x) => typeof x === "string");
834
+ }
835
+ }
836
+ return void 0;
837
+ }
675
838
  function toViewers(viewers) {
676
839
  if (viewers == null || viewers.length === 0) {
677
840
  return void 0;
@@ -679,17 +842,29 @@ function toViewers(viewers) {
679
842
  return viewers.map((v) => RoleId(v));
680
843
  }
681
844
  function mergeVariantViewers(seg) {
682
- const all = [...segMeta(seg).viewers ?? [], ...seg.variant?.viewers ?? []];
683
- return all.length > 0 ? [...new Set(all)].map((v) => RoleId(v)) : void 0;
845
+ const segViewers = seg.metadata.type === "section" || seg.metadata.type === "apiReference" || seg.metadata.type === "apiPackage" || seg.metadata.type === "changelog" ? seg.metadata.viewers : void 0;
846
+ const variantViewers = seg.variant?.viewers;
847
+ if ((segViewers == null || segViewers.length === 0) && (variantViewers == null || variantViewers.length === 0)) {
848
+ return void 0;
849
+ }
850
+ const merged = /* @__PURE__ */ new Set();
851
+ if (segViewers != null) {
852
+ for (const v of segViewers) {
853
+ merged.add(v);
854
+ }
855
+ }
856
+ if (variantViewers != null) {
857
+ for (const v of variantViewers) {
858
+ merged.add(v);
859
+ }
860
+ }
861
+ return merged.size > 0 ? [...merged].map((v) => RoleId(v)) : void 0;
684
862
  }
685
863
  function detailSlug(detail) {
686
- return detailMeta(detail).slug ?? "";
864
+ return detail.metadata?.slug ?? "";
687
865
  }
688
866
  function detailIsDefault(detail) {
689
- return detailMeta(detail).default ?? false;
690
- }
691
- function pointsToSlug(ctx, meta) {
692
- return meta.pointsTo != null ? ctx.contentSlug(meta.pointsTo) : void 0;
867
+ return detail.metadata?.default ?? false;
693
868
  }
694
869
  function scopeKey(seg) {
695
870
  return [seg.product?.id ?? "", seg.version?.id ?? "", seg.variant?.id ?? "", seg.tab?.id ?? ""].join("|");
@@ -709,226 +884,347 @@ function withMetadataDefaults(base) {
709
884
  };
710
885
  }
711
886
  function artifactToNode(ctx, route) {
712
- const md = routeMeta(route);
887
+ const md = route.metadata;
888
+ const title = metaStr(md, "title") ?? "";
889
+ const icon = metaStr(md, "icon");
890
+ const viewers = toViewers(metaStrArr(md, "viewers"));
713
891
  const slug = ctx.contentSlug(route.fullPath ?? "");
714
892
  switch (route.type) {
715
893
  case "markdown": {
716
- if (md.isOverview) {
894
+ if (metaBool(md, "isOverview")) {
717
895
  return void 0;
718
896
  }
719
- return {
897
+ const pageId = metaStr(md, "pageId") ?? "";
898
+ const node = {
720
899
  type: "page",
721
900
  ...withMetadataDefaults({
722
901
  id: ctx.nodeId(`page:${slug}`),
723
- title: md.title ?? "",
902
+ title,
724
903
  slug,
725
- icon: md.icon,
904
+ icon,
726
905
  hidden: route.hidden,
727
- viewers: toViewers(md.viewers)
906
+ viewers
728
907
  }),
729
- pageId: PageId(md.pageId ?? ""),
730
- noindex: md.noindex,
908
+ pageId: PageId(pageId),
909
+ noindex: metaBool(md, "noindex"),
731
910
  availability: void 0
732
911
  };
912
+ return node;
733
913
  }
734
914
  case "link": {
735
- return {
915
+ const node = {
736
916
  type: "link",
737
- id: ctx.nodeId(`link:${md.url ?? route.fullPath ?? ""}`),
917
+ id: ctx.nodeId(`link:${metaStr(md, "url") ?? route.fullPath ?? ""}`),
738
918
  collapsed: void 0,
739
- title: md.title ?? "",
740
- icon: md.icon,
741
- url: Url(md.url ?? ""),
919
+ title,
920
+ icon,
921
+ url: Url(metaStr(md, "url") ?? ""),
742
922
  target: void 0
743
923
  };
924
+ return node;
744
925
  }
745
926
  // API leaf types are handled by apiReferenceNode (which calls
746
927
  // apiLeafNodeFromNavRouteInternal), not by section-level artifact
747
928
  // conversion. Returning undefined here prevents them from appearing
748
929
  // as duplicate siblings alongside the apiReference node.
930
+ case "rest":
931
+ case "asyncapi":
932
+ case "webhook":
933
+ case "grpc":
934
+ case "graphql":
935
+ return void 0;
749
936
  default:
750
937
  return void 0;
751
938
  }
752
939
  }
753
- function apiLeafNodeFromNavRoute(route, basePath, segmentApiDefId) {
940
+ function apiLeafNodeFromNavRoute(route, basePath, segmentApiDefinitionId2) {
754
941
  const ctx = createBuildContext(basePath);
755
- return apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefId);
942
+ return apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2);
756
943
  }
757
- function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefId) {
758
- const md = routeMeta(route);
944
+ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
945
+ const md = route.metadata;
946
+ const apiDefinitionId = ApiDefinitionId(metaStr(md, "apiDefinitionId") ?? segmentApiDefinitionId2);
759
947
  const slug = ctx.contentSlug(route.fullPath ?? "");
760
- const base = {
761
- ...withMetadataDefaults({
762
- id: ctx.nodeId(`api-leaf:${slug}`),
763
- title: md.title ?? "",
764
- slug,
765
- icon: md.icon,
766
- hidden: route.hidden,
767
- viewers: toViewers(md.viewers)
768
- }),
769
- apiDefinitionId: ApiDefinitionId(md.apiDefinitionId ?? segmentApiDefId),
770
- availability: void 0
771
- };
772
- switch (route.type) {
773
- case "rest":
774
- if (md.endpointId == null || md.method == null) {
775
- return void 0;
776
- }
777
- return {
778
- type: "endpoint",
779
- ...base,
780
- method: md.method,
781
- endpointId: EndpointId(md.endpointId),
782
- isResponseStream: md.isResponseStream,
783
- playground: void 0
784
- };
785
- case "webhook":
786
- if (md.webhookId == null || md.method == null) {
787
- return void 0;
788
- }
789
- return {
790
- type: "webhook",
791
- ...base,
792
- method: md.method,
793
- webhookId: WebhookId(md.webhookId)
794
- };
795
- case "asyncapi":
796
- if (md.webSocketId == null) {
797
- return void 0;
798
- }
799
- return {
800
- type: "webSocket",
801
- ...base,
802
- webSocketId: WebSocketId(md.webSocketId),
803
- playground: void 0
804
- };
805
- case "grpc":
806
- if (md.grpcId == null || md.method == null) {
807
- return void 0;
808
- }
809
- return {
810
- type: "grpc",
811
- ...base,
812
- method: md.method,
813
- grpcId: GrpcId(md.grpcId)
814
- };
815
- case "graphql":
816
- if (md.graphqlOperationId == null || md.operationType == null) {
817
- return void 0;
818
- }
819
- return {
820
- type: "graphql",
821
- ...base,
822
- operationType: md.operationType,
823
- graphqlOperationId: GraphQlOperationId(md.graphqlOperationId),
824
- graphqlOperationIds: void 0,
825
- playground: void 0
826
- };
827
- default:
948
+ const title = metaStr(md, "title") ?? "";
949
+ const icon = metaStr(md, "icon");
950
+ const viewers = toViewers(metaStrArr(md, "viewers"));
951
+ const meta = withMetadataDefaults({
952
+ id: ctx.nodeId(`api-leaf:${slug}`),
953
+ title,
954
+ slug,
955
+ icon,
956
+ hidden: route.hidden,
957
+ viewers
958
+ });
959
+ if (route.type === "rest") {
960
+ const endpointId = metaStr(md, "endpointId");
961
+ const method = metaStr(md, "method");
962
+ if (endpointId == null || method == null) {
963
+ return void 0;
964
+ }
965
+ return {
966
+ type: "endpoint",
967
+ ...meta,
968
+ method,
969
+ endpointId: EndpointId(endpointId),
970
+ apiDefinitionId,
971
+ isResponseStream: metaBool(md, "isResponseStream"),
972
+ availability: void 0,
973
+ playground: void 0
974
+ };
975
+ }
976
+ if (route.type === "webhook") {
977
+ const webhookId = metaStr(md, "webhookId");
978
+ const method = metaStr(md, "method");
979
+ if (webhookId == null || method == null) {
980
+ return void 0;
981
+ }
982
+ return {
983
+ type: "webhook",
984
+ ...meta,
985
+ method,
986
+ webhookId: WebhookId(webhookId),
987
+ apiDefinitionId,
988
+ availability: void 0
989
+ };
990
+ }
991
+ if (route.type === "asyncapi") {
992
+ const webSocketId = metaStr(md, "webSocketId");
993
+ if (webSocketId == null) {
994
+ return void 0;
995
+ }
996
+ return {
997
+ type: "webSocket",
998
+ ...meta,
999
+ webSocketId: WebSocketId(webSocketId),
1000
+ apiDefinitionId,
1001
+ availability: void 0,
1002
+ playground: void 0
1003
+ };
1004
+ }
1005
+ if (route.type === "grpc") {
1006
+ const grpcId = metaStr(md, "grpcId");
1007
+ const method = metaStr(md, "method");
1008
+ if (grpcId == null || method == null) {
1009
+ return void 0;
1010
+ }
1011
+ return {
1012
+ type: "grpc",
1013
+ ...meta,
1014
+ method,
1015
+ grpcId: GrpcId(grpcId),
1016
+ apiDefinitionId,
1017
+ availability: void 0
1018
+ };
1019
+ }
1020
+ if (route.type === "graphql") {
1021
+ const graphqlOperationId = metaStr(md, "graphqlOperationId");
1022
+ const operationType = metaStr(md, "operationType");
1023
+ if (graphqlOperationId == null || operationType == null) {
828
1024
  return void 0;
1025
+ }
1026
+ return {
1027
+ type: "graphql",
1028
+ ...meta,
1029
+ operationType,
1030
+ graphqlOperationId: GraphQlOperationId(graphqlOperationId),
1031
+ graphqlOperationIds: void 0,
1032
+ apiDefinitionId,
1033
+ availability: void 0,
1034
+ playground: void 0
1035
+ };
829
1036
  }
1037
+ return void 0;
830
1038
  }
831
- function collectApiLeafNodesFromNav(routes, basePath, segmentApiDefId) {
1039
+ function collectApiLeafNodesFromNav(routes, basePath, segmentApiDefinitionId2) {
832
1040
  const ctx = createBuildContext(basePath);
833
- return routes.map((route) => apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefId)).filter((node) => node != null);
1041
+ return routes.map((route) => apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2)).filter((node) => node != null);
834
1042
  }
835
1043
  function segmentApiDefinitionId(metadata) {
836
- return metadata?.apiDefinitionId;
1044
+ switch (metadata.type) {
1045
+ case "apiReference":
1046
+ case "apiPackage":
1047
+ case "changelog":
1048
+ return metadata.apiDefinitionId;
1049
+ default:
1050
+ return void 0;
1051
+ }
837
1052
  }
838
1053
  function overviewRoute(nav) {
1054
+ return nav.find((r) => r.type === "markdown" && metaBool(r.metadata, "isOverview"));
1055
+ }
1056
+ function overviewRouteFromSegmentMeta(seg, nav) {
1057
+ const overviewPageId = metaStr(seg.metadata, "overviewPageId");
1058
+ if (overviewPageId == null) {
1059
+ return void 0;
1060
+ }
1061
+ return nav.find((r) => metaStr(r.metadata, "pageId") === overviewPageId);
1062
+ }
1063
+ function inferSectionSlugFromNav(ctx, nav, scopePrefix) {
1064
+ const scopeStr = String(scopePrefix);
1065
+ const prefix = scopeStr !== "" ? scopeStr + "/" : "";
839
1066
  for (const r of nav) {
840
- if (r.type === "markdown") {
841
- const meta = routeMeta(r);
842
- if (meta.isOverview) {
843
- return { route: r, meta };
844
- }
1067
+ if (r.fullPath == null) {
1068
+ continue;
1069
+ }
1070
+ if (r.type !== "markdown" && r.type !== "page") {
1071
+ continue;
1072
+ }
1073
+ const contentSlug = String(ctx.contentSlug(r.fullPath));
1074
+ const rel = prefix !== "" ? contentSlug.startsWith(prefix) ? contentSlug.slice(prefix.length) : null : contentSlug;
1075
+ if (rel == null) {
1076
+ continue;
1077
+ }
1078
+ const parts = rel.split("/");
1079
+ if (parts.length >= 2 && parts[0] !== "") {
1080
+ return slugjoin(scopePrefix, parts[0]);
845
1081
  }
846
1082
  }
847
1083
  return void 0;
848
1084
  }
849
- function sectionNode(ctx, scoped, sectionChildren) {
850
- const { seg, meta: sm, nav } = scoped;
851
- const overview = overviewRoute(nav);
852
- const overviewPageId = overview?.meta.pageId;
853
- const slug = ctx.contentSlug(overview?.route.fullPath ?? seg.section);
854
- const leafChildren = nav.map((r) => artifactToNode(ctx, r)).filter((n) => n != null);
1085
+ function structuralNodeSlug(ctx, overviewFullPath, section, scopePrefix) {
1086
+ if (overviewFullPath != null) {
1087
+ return ctx.contentSlug(overviewFullPath);
1088
+ }
1089
+ return section !== "" ? slugjoin(scopePrefix, section) : scopePrefix;
1090
+ }
1091
+ function stripLeadingScopePrefix(section, scopePrefix) {
1092
+ const prefix = scopePrefix;
1093
+ if (prefix === "") {
1094
+ return section;
1095
+ }
1096
+ if (section === prefix) {
1097
+ return "";
1098
+ }
1099
+ if (section.startsWith(prefix + "/")) {
1100
+ return section.slice(prefix.length + 1);
1101
+ }
1102
+ return section;
1103
+ }
1104
+ function mergeChildrenByPosition(ctx, nav, sectionChildren) {
1105
+ const leafNodes = [];
1106
+ for (let i = 0; i < nav.length; i++) {
1107
+ const route = nav[i];
1108
+ const node = artifactToNode(ctx, route);
1109
+ if (node != null) {
1110
+ leafNodes.push({ node, pos: route.displaySortOrder ?? i });
1111
+ }
1112
+ }
1113
+ const hasChildIndex = sectionChildren.some((s) => s.childIndex != null);
1114
+ if (!hasChildIndex) {
1115
+ return [...leafNodes.map((l) => l.node), ...sectionChildren.map((s) => s.node)];
1116
+ }
1117
+ const positioned = [...leafNodes];
1118
+ for (const s of sectionChildren) {
1119
+ positioned.push({ node: s.node, pos: s.childIndex ?? Number.MAX_SAFE_INTEGER });
1120
+ }
1121
+ positioned.sort((a, b) => a.pos - b.pos);
1122
+ return positioned.map((p) => p.node);
1123
+ }
1124
+ function sectionNode(ctx, scoped, sectionChildren, scopePrefix) {
1125
+ const { seg, nav } = scoped;
1126
+ const overview = overviewRoute(nav) ?? overviewRouteFromSegmentMeta(seg, nav);
1127
+ const overviewPageId = overview != null ? metaStr(overview.metadata, "pageId") : void 0;
1128
+ let slug = structuralNodeSlug(ctx, overview?.fullPath, seg.section, scopePrefix);
1129
+ if (seg.section === "" && overview?.fullPath == null) {
1130
+ slug = inferSectionSlugFromNav(ctx, nav, scopePrefix) ?? slug;
1131
+ }
1132
+ const metaPointsTo = metaStr(seg.metadata, "pointsTo");
855
1133
  const defaults = withMetadataDefaults({
856
1134
  id: ctx.nodeId(`section:${slug}`),
857
- title: sm.title ?? "",
1135
+ title: metaStr(seg.metadata, "title") ?? "",
858
1136
  slug,
859
- icon: sm.icon,
1137
+ icon: metaStr(seg.metadata, "icon"),
860
1138
  hidden: seg.hidden,
861
1139
  viewers: mergeVariantViewers(seg)
862
1140
  });
863
1141
  return {
864
1142
  type: "section",
865
1143
  ...defaults,
866
- collapsed: sm.collapsed ?? defaults.collapsed,
1144
+ collapsed: metaCollapsed(seg.metadata) ?? defaults.collapsed,
867
1145
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
868
1146
  noindex: void 0,
869
- collapsible: sm.collapsible,
870
- collapsedByDefault: sm.collapsedByDefault,
1147
+ collapsible: metaBool(seg.metadata, "collapsible") ?? (metaCollapsed(seg.metadata) != null ? true : void 0),
1148
+ collapsedByDefault: metaBool(seg.metadata, "collapsedByDefault") ?? (metaCollapsed(seg.metadata) === true ? true : void 0),
871
1149
  availability: void 0,
872
- pointsTo: void 0,
873
- children: [...leafChildren, ...sectionChildren]
1150
+ pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1151
+ children: mergeChildrenByPosition(ctx, nav, sectionChildren)
874
1152
  };
875
1153
  }
876
- function parentSectionPath(sectionPath) {
877
- const idx = sectionPath.lastIndexOf("/");
878
- return idx === -1 ? "" : sectionPath.slice(0, idx);
1154
+ function directChildApiPackages(parentSection, scopeSegs) {
1155
+ const sectionPaths = new Set(scopeSegs.map((s) => s.seg.section));
1156
+ return scopeSegs.filter((s) => {
1157
+ if (metaStr(s.seg.metadata, "type") !== "apiPackage") {
1158
+ return false;
1159
+ }
1160
+ const parent = parentSectionPath(s.seg.section);
1161
+ if (parent === parentSection) {
1162
+ return true;
1163
+ }
1164
+ if (!sectionPaths.has(parent)) {
1165
+ return nearestExistingAncestor(s.seg.section, sectionPaths) === parentSection;
1166
+ }
1167
+ return false;
1168
+ }).sort((a, b) => a.seg.sortOrder - b.seg.sortOrder);
879
1169
  }
880
- function nearestExistingAncestor(sectionPath, existing) {
881
- let current = parentSectionPath(sectionPath);
882
- while (current !== "") {
883
- if (existing.has(current)) {
884
- return current;
1170
+ function buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix) {
1171
+ const { seg, nav } = scoped;
1172
+ const rawLeafNodes = nav.map((route) => apiLeafNodeFromNavRouteInternal(ctx, route, apiDefinitionId)).filter((node) => node != null);
1173
+ const leafNodes = mergeEndpointPairs(ctx, rawLeafNodes, nav);
1174
+ const childPackages = directChildApiPackages(seg.section, scopeSegs);
1175
+ const packageNodes = childPackages.map((child) => ({
1176
+ node: apiPackageChildNode(
1177
+ ctx,
1178
+ child,
1179
+ scopeSegs,
1180
+ apiDefinitionId,
1181
+ scopePrefix
1182
+ ),
1183
+ childIndex: metaNum(child.seg.metadata, "childIndex")
1184
+ }));
1185
+ const hasChildIndex = packageNodes.some((p) => p.childIndex != null);
1186
+ if (!hasChildIndex) {
1187
+ return [...leafNodes, ...packageNodes.map((p) => p.node)];
1188
+ }
1189
+ const leafPositions = [];
1190
+ for (const route of nav) {
1191
+ if (route.displaySortOrder != null) {
1192
+ leafPositions.push(route.displaySortOrder);
885
1193
  }
886
- current = parentSectionPath(current);
887
1194
  }
888
- return "";
889
- }
890
- function isDirectChildOf(sec, parentPath, sectionPaths) {
891
- const parent = parentSectionPath(sec);
892
- if (parent === parentPath) {
893
- return true;
1195
+ const positioned = [];
1196
+ for (let i = 0; i < leafNodes.length; i++) {
1197
+ positioned.push({ node: leafNodes[i], pos: leafPositions[i] ?? i });
894
1198
  }
895
- return !sectionPaths.has(parent) && nearestExistingAncestor(sec, sectionPaths) === parentPath;
896
- }
897
- function directChildApiPackages(parentSection, scopeSegs, sectionPaths) {
898
- return scopeSegs.filter((s) => s.meta.type === "apiPackage" && isDirectChildOf(s.seg.section, parentSection, sectionPaths)).sort((a, b) => a.seg.sortOrder - b.seg.sortOrder);
1199
+ for (const p of packageNodes) {
1200
+ positioned.push({ node: p.node, pos: p.childIndex ?? Number.MAX_SAFE_INTEGER });
1201
+ }
1202
+ positioned.sort((a, b) => a.pos - b.pos);
1203
+ return positioned.map((p) => p.node);
899
1204
  }
900
- function buildApiChildren(ctx, scoped, scopeSegs, apiDefId, sectionPaths) {
901
- const { nav } = scoped;
902
- const rawLeafNodes = nav.map((route) => apiLeafNodeFromNavRouteInternal(ctx, route, apiDefId)).filter((node) => node != null);
903
- const leafNodes = mergeEndpointPairs(ctx, rawLeafNodes, nav);
904
- const childPackages = directChildApiPackages(scoped.seg.section, scopeSegs, sectionPaths);
905
- const packageNodes = childPackages.map(
906
- (child) => apiPackageChildNode(ctx, child, scopeSegs, apiDefId, sectionPaths)
907
- );
908
- return [...leafNodes, ...packageNodes];
909
- }
910
- function apiPackageChildNode(ctx, scoped, scopeSegs, parentApiDefId, sectionPaths) {
911
- const { seg, meta: sm, nav } = scoped;
1205
+ function apiPackageChildNode(ctx, scoped, scopeSegs, parentApiDefinitionId, scopePrefix) {
1206
+ const { seg, nav } = scoped;
912
1207
  const overview = overviewRoute(nav);
913
- const overviewPageId = overview?.meta.pageId;
914
- const apiDefId = sm.apiDefinitionId ?? parentApiDefId;
915
- const slug = ctx.contentSlug(overview?.route.fullPath ?? nav[0]?.fullPath ?? seg.section);
916
- const children = buildApiChildren(ctx, scoped, scopeSegs, apiDefId, sectionPaths);
1208
+ const overviewPageId = overview != null ? metaStr(overview.metadata, "pageId") : void 0;
1209
+ const apiDefinitionId = metaStr(seg.metadata, "apiDefinitionId") ?? parentApiDefinitionId;
1210
+ const slug = structuralNodeSlug(ctx, overview?.fullPath, seg.section, scopePrefix);
1211
+ const metaPointsTo = metaStr(seg.metadata, "pointsTo");
1212
+ const children = buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix);
917
1213
  return {
918
1214
  type: "apiPackage",
919
1215
  ...withMetadataDefaults({
920
1216
  id: ctx.nodeId(`api-pkg:${slug}`),
921
- title: sm.title ?? "",
1217
+ title: metaStr(seg.metadata, "title") ?? "",
922
1218
  slug,
923
- icon: sm.icon,
1219
+ icon: metaStr(seg.metadata, "icon"),
924
1220
  hidden: seg.hidden,
925
- viewers: toViewers(sm.viewers)
1221
+ viewers: toViewers(metaStrArr(seg.metadata, "viewers"))
926
1222
  }),
927
- apiDefinitionId: ApiDefinitionId(apiDefId),
928
- availability: sm.availability,
1223
+ apiDefinitionId: ApiDefinitionId(apiDefinitionId),
1224
+ availability: metaStr(seg.metadata, "availability"),
929
1225
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
930
1226
  noindex: void 0,
931
- pointsTo: void 0,
1227
+ pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
932
1228
  children,
933
1229
  playground: void 0
934
1230
  };
@@ -939,9 +1235,10 @@ function mergeEndpointPairs(ctx, leafNodes, allNav) {
939
1235
  if (route.type !== "rest") {
940
1236
  continue;
941
1237
  }
942
- const md = routeMeta(route);
943
- if (md.endpointPairKey != null && md.endpointId != null) {
944
- endpointIdToPairKey.set(md.endpointId, md.endpointPairKey);
1238
+ const pairKey = metaStr(route.metadata, "endpointPairKey");
1239
+ const endpointId = metaStr(route.metadata, "endpointId");
1240
+ if (pairKey != null && endpointId != null) {
1241
+ endpointIdToPairKey.set(endpointId, pairKey);
945
1242
  }
946
1243
  }
947
1244
  if (endpointIdToPairKey.size === 0) {
@@ -971,6 +1268,7 @@ function mergeEndpointPairs(ctx, leafNodes, allNav) {
971
1268
  }
972
1269
  const stream = node.isResponseStream ? node : first;
973
1270
  const nonStream = node.isResponseStream ? first : node;
1271
+ stream.canonicalSlug = nonStream.slug;
974
1272
  const pairNode = {
975
1273
  id: ctx.nodeId(`endpoint-pair:${pairKey}`),
976
1274
  type: "endpointPair",
@@ -983,61 +1281,86 @@ function mergeEndpointPairs(ctx, leafNodes, allNav) {
983
1281
  }
984
1282
  return result;
985
1283
  }
986
- function apiReferenceNode(ctx, scoped, scopeSegs, sectionPaths) {
987
- const { seg, meta: sm, nav } = scoped;
1284
+ function apiReferenceNode(ctx, scoped, scopeSegs, scopePrefix) {
1285
+ const { seg, nav } = scoped;
988
1286
  const overview = overviewRoute(nav);
989
- const overviewPageId = overview?.meta.pageId;
990
- const apiDefId = sm.apiDefinitionId ?? "";
991
- const slug = ctx.contentSlug(overview?.route.fullPath ?? nav[0]?.fullPath ?? seg.section);
992
- const children = buildApiChildren(ctx, scoped, scopeSegs, apiDefId, sectionPaths);
1287
+ const overviewPageId = overview != null ? metaStr(overview.metadata, "pageId") : void 0;
1288
+ const apiDefinitionId = metaStr(seg.metadata, "apiDefinitionId") ?? "";
1289
+ const slug = structuralNodeSlug(ctx, overview?.fullPath, seg.section, scopePrefix);
1290
+ const metaPointsTo = metaStr(seg.metadata, "pointsTo");
1291
+ const children = buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix);
1292
+ const changelog = attachedApiChangelogNode(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix);
993
1293
  return {
994
1294
  type: "apiReference",
995
1295
  ...withMetadataDefaults({
996
1296
  id: ctx.nodeId(`api:${slug}`),
997
- title: sm.title ?? "",
1297
+ title: metaStr(seg.metadata, "title") ?? "",
998
1298
  slug,
999
- icon: sm.icon,
1299
+ icon: metaStr(seg.metadata, "icon"),
1000
1300
  hidden: seg.hidden,
1001
1301
  viewers: mergeVariantViewers(seg)
1002
1302
  }),
1003
- apiDefinitionId: ApiDefinitionId(apiDefId),
1303
+ apiDefinitionId: ApiDefinitionId(apiDefinitionId),
1004
1304
  availability: void 0,
1005
1305
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1006
1306
  noindex: void 0,
1007
1307
  paginated: true,
1008
- showErrors: sm.showErrors,
1009
- hideTitle: sm.hideTitle,
1010
- pointsTo: void 0,
1308
+ showErrors: metaBool(seg.metadata, "showErrors"),
1309
+ hideTitle: metaBool(seg.metadata, "hideTitle"),
1310
+ pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1011
1311
  children,
1012
- changelog: void 0,
1312
+ changelog,
1013
1313
  playground: void 0,
1014
1314
  postmanCollectionUrl: void 0
1015
1315
  };
1016
1316
  }
1017
- function changelogNode(ctx, scoped) {
1018
- const { seg, meta: sm, nav } = scoped;
1317
+ function attachedApiChangelogNode(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix) {
1318
+ const { seg } = scoped;
1319
+ const candidates = scopeSegs.filter((candidate) => {
1320
+ if (metaStr(candidate.seg.metadata, "type") !== "changelog") {
1321
+ return false;
1322
+ }
1323
+ return metaStr(candidate.seg.metadata, "apiDefinitionId") === apiDefinitionId;
1324
+ });
1325
+ const changelogSeg = candidates.find((candidate) => parentSectionPath(candidate.seg.section) === seg.section) ?? candidates[0];
1326
+ return changelogSeg != null ? changelogNode(ctx, changelogSeg, scopePrefix) : void 0;
1327
+ }
1328
+ function hasOwningApiReference(scoped, scopeSegs) {
1329
+ const apiDefinitionId = metaStr(scoped.seg.metadata, "apiDefinitionId");
1330
+ if (apiDefinitionId == null || metaStr(scoped.seg.metadata, "type") !== "changelog") {
1331
+ return false;
1332
+ }
1333
+ return scopeSegs.some((candidate) => {
1334
+ if (metaStr(candidate.seg.metadata, "type") !== "apiReference") {
1335
+ return false;
1336
+ }
1337
+ return metaStr(candidate.seg.metadata, "apiDefinitionId") === apiDefinitionId;
1338
+ });
1339
+ }
1340
+ function changelogNode(ctx, scoped, scopePrefix) {
1341
+ const { seg, nav } = scoped;
1019
1342
  const overview = overviewRoute(nav);
1020
- const overviewPageId = overview?.meta.pageId;
1343
+ const overviewPageId = overview != null ? metaStr(overview.metadata, "pageId") : void 0;
1021
1344
  const entries = nav.filter((r) => r.type === "changelog");
1022
1345
  const byYear = /* @__PURE__ */ new Map();
1023
1346
  for (const r of entries) {
1024
- const md = routeMeta(r);
1025
- const date = md.date != null ? new Date(md.date) : /* @__PURE__ */ new Date(0);
1347
+ const dateStr = metaStr(r.metadata, "date");
1348
+ const date = dateStr != null ? new Date(dateStr) : /* @__PURE__ */ new Date(0);
1026
1349
  const year = date.getUTCFullYear();
1027
1350
  const month = date.getUTCMonth() + 1;
1028
1351
  const entry = {
1029
1352
  type: "changelogEntry",
1030
1353
  ...withMetadataDefaults({
1031
- id: ctx.nodeId(`cl-entry:${r.fullPath ?? md.pageId ?? ""}`),
1032
- title: md.title ?? "",
1354
+ id: ctx.nodeId(`cl-entry:${r.fullPath ?? metaStr(r.metadata, "pageId") ?? ""}`),
1355
+ title: metaStr(r.metadata, "title") ?? "",
1033
1356
  slug: ctx.contentSlug(r.fullPath ?? ""),
1034
- icon: md.icon,
1357
+ icon: metaStr(r.metadata, "icon"),
1035
1358
  hidden: r.hidden,
1036
- viewers: toViewers(md.viewers)
1359
+ viewers: toViewers(metaStrArr(r.metadata, "viewers"))
1037
1360
  }),
1038
- pageId: PageId(md.pageId ?? ""),
1361
+ pageId: PageId(metaStr(r.metadata, "pageId") ?? ""),
1039
1362
  noindex: void 0,
1040
- date: md.date ?? "",
1363
+ date: dateStr ?? "",
1041
1364
  tags: void 0
1042
1365
  };
1043
1366
  let months = byYear.get(year);
@@ -1049,7 +1372,8 @@ function changelogNode(ctx, scoped) {
1049
1372
  arr.push(entry);
1050
1373
  months.set(month, arr);
1051
1374
  }
1052
- const baseSlug = ctx.contentSlug(overview?.route.fullPath ?? seg.section);
1375
+ const relativeSection = stripLeadingScopePrefix(seg.section, scopePrefix);
1376
+ const baseSlug = structuralNodeSlug(ctx, overview?.fullPath, relativeSection, scopePrefix);
1053
1377
  const years = [...byYear.entries()].sort((a, b) => b[0] - a[0]).map(([year, months]) => ({
1054
1378
  type: "changelogYear",
1055
1379
  ...withMetadataDefaults({
@@ -1077,9 +1401,9 @@ function changelogNode(ctx, scoped) {
1077
1401
  type: "changelog",
1078
1402
  ...withMetadataDefaults({
1079
1403
  id: ctx.nodeId(`changelog:${baseSlug}`),
1080
- title: sm.title ?? "",
1404
+ title: metaStr(seg.metadata, "title") ?? "",
1081
1405
  slug: baseSlug,
1082
- icon: sm.icon,
1406
+ icon: metaStr(seg.metadata, "icon"),
1083
1407
  hidden: seg.hidden,
1084
1408
  viewers: mergeVariantViewers(seg)
1085
1409
  }),
@@ -1088,48 +1412,112 @@ function changelogNode(ctx, scoped) {
1088
1412
  children: years
1089
1413
  };
1090
1414
  }
1091
- function buildSectionTree(ctx, scopeSegs, parentPath, sectionPaths) {
1415
+ function parentSectionPath(sectionPath) {
1416
+ const idx = sectionPath.lastIndexOf("/");
1417
+ return idx === -1 ? "" : sectionPath.slice(0, idx);
1418
+ }
1419
+ function nearestExistingAncestor(sectionPath, existing) {
1420
+ let current = parentSectionPath(sectionPath);
1421
+ while (current !== "") {
1422
+ if (existing.has(current)) {
1423
+ return current;
1424
+ }
1425
+ current = parentSectionPath(current);
1426
+ }
1427
+ return "";
1428
+ }
1429
+ function buildSectionTree(ctx, scopeSegs, parentPath, scopePrefix, changelogScopePrefix) {
1430
+ const sectionPaths = new Set(scopeSegs.map((s) => s.seg.section));
1092
1431
  const direct = scopeSegs.filter((s) => {
1093
1432
  const sec = s.seg.section;
1094
- return sec !== "" && s.meta.type !== "tabRoot" && isDirectChildOf(sec, parentPath, sectionPaths);
1433
+ const type = metaStr(s.seg.metadata, "type");
1434
+ if (sec === "" || type === "tabRoot") {
1435
+ return false;
1436
+ }
1437
+ if (hasOwningApiReference(s, scopeSegs)) {
1438
+ return false;
1439
+ }
1440
+ const parent = parentSectionPath(sec);
1441
+ if (parent === parentPath) {
1442
+ return true;
1443
+ }
1444
+ if (!sectionPaths.has(parent)) {
1445
+ return nearestExistingAncestor(sec, sectionPaths) === parentPath;
1446
+ }
1447
+ return false;
1095
1448
  }).sort((a, b) => a.seg.sortOrder - b.seg.sortOrder);
1096
1449
  return direct.map((s) => {
1097
- const { type } = s.meta;
1450
+ const type = metaStr(s.seg.metadata, "type");
1451
+ const childIndex = metaNum(s.seg.metadata, "childIndex");
1452
+ let node;
1098
1453
  if (type === "apiReference" || type === "apiPackage") {
1099
- return apiReferenceNode(ctx, s, scopeSegs, sectionPaths);
1100
- }
1101
- if (type === "changelog") {
1102
- return changelogNode(ctx, s);
1454
+ node = apiReferenceNode(ctx, s, scopeSegs, scopePrefix);
1455
+ } else if (type === "changelog") {
1456
+ node = changelogNode(ctx, s, changelogScopePrefix ?? scopePrefix);
1457
+ } else {
1458
+ node = sectionNode(
1459
+ ctx,
1460
+ s,
1461
+ buildSectionTree(ctx, scopeSegs, s.seg.section, scopePrefix, changelogScopePrefix),
1462
+ scopePrefix
1463
+ );
1103
1464
  }
1104
- return sectionNode(ctx, s, buildSectionTree(ctx, scopeSegs, s.seg.section, sectionPaths));
1465
+ return { node, childIndex };
1105
1466
  });
1106
1467
  }
1107
- function buildSidebarRootChildren(ctx, scopeSegs) {
1468
+ function buildSidebarRootChildren(ctx, scopeSegs, scopePrefix, changelogScopePrefix) {
1108
1469
  const ordered = [...scopeSegs].sort((a, b) => a.seg.sortOrder - b.seg.sortOrder);
1109
1470
  const sectionPaths = new Set(ordered.map((s) => s.seg.section));
1110
- const flat = [];
1471
+ const annotated = [];
1472
+ const hasRootSection = ordered.some((s) => metaStr(s.seg.metadata, "type") === "section" && s.seg.section === "");
1111
1473
  for (const s of ordered) {
1112
- const { type } = s.meta;
1474
+ const type = metaStr(s.seg.metadata, "type");
1113
1475
  const sec = s.seg.section;
1114
- if (type === "tabRoot" || sec === "") {
1476
+ if (hasOwningApiReference(s, scopeSegs)) {
1477
+ continue;
1478
+ }
1479
+ if (type === "tabRoot" || sec === "" && type !== "section") {
1115
1480
  for (const r of s.nav) {
1116
1481
  const node = artifactToNode(ctx, r);
1117
1482
  if (node != null) {
1118
- flat.push(node);
1483
+ annotated.push({ node, pos: r.displaySortOrder ?? void 0, isLeaf: true });
1119
1484
  }
1120
1485
  }
1121
1486
  continue;
1122
1487
  }
1123
- if (isDirectChildOf(sec, "", sectionPaths)) {
1488
+ if (type === "section" && sec === "") {
1489
+ const sectionChildren = buildSectionTree(ctx, scopeSegs, "", scopePrefix);
1490
+ const node = sectionNode(ctx, s, sectionChildren, scopePrefix);
1491
+ annotated.push({ node, pos: metaNum(s.seg.metadata, "childIndex"), isLeaf: false });
1492
+ continue;
1493
+ }
1494
+ const parent = parentSectionPath(sec);
1495
+ const isRootLevel = parent === "" || !sectionPaths.has(parent) && nearestExistingAncestor(sec, sectionPaths) === "";
1496
+ if (isRootLevel && hasRootSection) {
1497
+ continue;
1498
+ }
1499
+ if (isRootLevel) {
1500
+ let node;
1124
1501
  if (type === "apiReference" || type === "apiPackage") {
1125
- flat.push(apiReferenceNode(ctx, s, scopeSegs, sectionPaths));
1502
+ node = apiReferenceNode(ctx, s, scopeSegs, scopePrefix);
1126
1503
  } else if (type === "changelog") {
1127
- flat.push(changelogNode(ctx, s));
1504
+ node = changelogNode(ctx, s, changelogScopePrefix ?? scopePrefix);
1128
1505
  } else {
1129
- flat.push(sectionNode(ctx, s, buildSectionTree(ctx, scopeSegs, sec, sectionPaths)));
1506
+ node = sectionNode(
1507
+ ctx,
1508
+ s,
1509
+ buildSectionTree(ctx, scopeSegs, sec, scopePrefix, changelogScopePrefix),
1510
+ scopePrefix
1511
+ );
1130
1512
  }
1513
+ annotated.push({ node, pos: metaNum(s.seg.metadata, "childIndex"), isLeaf: false });
1131
1514
  }
1132
1515
  }
1516
+ const hasLeafPos = annotated.some((a) => a.isLeaf && a.pos != null);
1517
+ const hasSegmentPos = annotated.some((a) => !a.isLeaf && a.pos != null);
1518
+ const flat = hasLeafPos && hasSegmentPos ? annotated.map((a, seq) => ({ ...a, seq })).sort(
1519
+ (x, y) => (x.pos ?? Number.MAX_SAFE_INTEGER) - (y.pos ?? Number.MAX_SAFE_INTEGER) || x.seq - y.seq
1520
+ ).map((a) => a.node) : annotated.map((a) => a.node);
1133
1521
  return groupSidebarRootChildren(ctx, flat);
1134
1522
  }
1135
1523
  function groupSidebarRootChildren(ctx, children) {
@@ -1150,9 +1538,13 @@ function groupSidebarRootChildren(ctx, children) {
1150
1538
  if (child.type === "apiReference" || child.type === "varianted") {
1151
1539
  flushRun();
1152
1540
  out.push(child);
1153
- } else if (child.type === "section" && (child.collapsible === false || child.collapsible == null && child.collapsed === false)) {
1541
+ } else if (child.type === "section" && !child.collapsible) {
1154
1542
  flushRun();
1155
1543
  out.push(child);
1544
+ } else if (child.type === "changelog") {
1545
+ flushRun();
1546
+ run.push(child);
1547
+ flushRun();
1156
1548
  } else {
1157
1549
  run.push(child);
1158
1550
  }
@@ -1160,19 +1552,22 @@ function groupSidebarRootChildren(ctx, children) {
1160
1552
  flushRun();
1161
1553
  return out;
1162
1554
  }
1163
- function buildSidebarRoot(ctx, scopeSegs) {
1555
+ function buildSidebarRoot(ctx, scopeSegs, scopePrefix, changelogScopePrefix) {
1164
1556
  const first = scopeSegs[0];
1165
1557
  return {
1166
1558
  type: "sidebarRoot",
1167
1559
  id: ctx.nodeId(`sidebar:${first != null ? scopeKey(first.seg) : "root"}`),
1168
1560
  collapsed: void 0,
1169
- children: buildSidebarRootChildren(ctx, scopeSegs)
1561
+ children: buildSidebarRootChildren(ctx, scopeSegs, scopePrefix, changelogScopePrefix)
1170
1562
  };
1171
1563
  }
1172
1564
  function buildFullRootFromSegments(options) {
1173
1565
  const { basePath, title, segments, navBySegment } = options;
1174
1566
  const ctx = createBuildContext(basePath);
1175
- const scoped = segments.map((seg) => ({ seg, meta: segMeta(seg), nav: navBySegment.get(seg.segmentHash) ?? [] })).filter((s) => s.meta.type !== "files" && s.meta.type !== "redirects");
1567
+ const scoped = segments.filter((seg) => {
1568
+ const t = metaStr(seg.metadata, "type");
1569
+ return t !== "files" && t !== "redirects";
1570
+ }).map((seg) => ({ seg, nav: navBySegment.get(seg.segmentHash) ?? [] }));
1176
1571
  const rootSlug = asSlug(basePath);
1177
1572
  const scopesByKey = /* @__PURE__ */ new Map();
1178
1573
  for (const s of scoped) {
@@ -1190,7 +1585,7 @@ function buildFullRootFromSegments(options) {
1190
1585
  } else if (versions.length > 0) {
1191
1586
  child = buildVersioned(ctx, versions, scoped, rootSlug, void 0);
1192
1587
  } else {
1193
- child = buildUnversioned(ctx, scoped, tabs.length > 0);
1588
+ child = buildUnversioned(ctx, scoped, rootSlug, tabs.length > 0);
1194
1589
  }
1195
1590
  let rootPointsTo;
1196
1591
  if (child.type === "productgroup") {
@@ -1200,20 +1595,15 @@ function buildFullRootFromSegments(options) {
1200
1595
  const defaultVersion = child.children.find((v) => v.default) ?? child.children[0];
1201
1596
  rootPointsTo = defaultVersion?.pointsTo;
1202
1597
  }
1203
- return {
1598
+ const root = {
1204
1599
  type: "root",
1205
1600
  version: "v2",
1206
- ...withMetadataDefaults({
1207
- id: ctx.nodeId("root"),
1208
- title,
1209
- slug: rootSlug,
1210
- icon: void 0,
1211
- hidden: void 0
1212
- }),
1601
+ ...withMetadataDefaults({ id: ctx.nodeId("root"), title, slug: rootSlug, icon: void 0, hidden: void 0 }),
1213
1602
  roles: void 0,
1214
1603
  pointsTo: rootPointsTo,
1215
1604
  child
1216
1605
  };
1606
+ return root;
1217
1607
  }
1218
1608
  function uniqueDetails(scoped, dim) {
1219
1609
  const bySlug = /* @__PURE__ */ new Map();
@@ -1222,14 +1612,15 @@ function uniqueDetails(scoped, dim) {
1222
1612
  if (d == null) {
1223
1613
  continue;
1224
1614
  }
1225
- const dm = detailMeta(d);
1226
- const slug = dm.slug ?? "";
1615
+ const slug = detailSlug(d);
1227
1616
  const existing = bySlug.get(slug);
1228
- if (existing == null || dm.pointsTo != null && existing.meta.pointsTo == null) {
1229
- bySlug.set(slug, { detail: d, meta: dm });
1617
+ if (existing == null) {
1618
+ bySlug.set(slug, d);
1619
+ } else if (metaStr(d.metadata, "pointsTo") != null && metaStr(existing.metadata, "pointsTo") == null) {
1620
+ bySlug.set(slug, d);
1230
1621
  }
1231
1622
  }
1232
- return [...bySlug.values()].map((e) => e.detail).sort((a, b) => a.sortOrder - b.sortOrder);
1623
+ return [...bySlug.values()].sort((a, b) => a.sortOrder - b.sortOrder);
1233
1624
  }
1234
1625
  function scopeSlugPrefix(rootSlug, ...details) {
1235
1626
  const parts = [rootSlug];
@@ -1243,30 +1634,80 @@ function scopeSlugPrefix(rootSlug, ...details) {
1243
1634
  }
1244
1635
  return slugjoin(...parts);
1245
1636
  }
1246
- function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent) {
1637
+ function buildVariantedNode(ctx, variants, scopeSegs, scopePrefix) {
1638
+ const variantChildren = variants.map((variant) => {
1639
+ const variantSegs = scopeSegs.filter((s) => s.seg.variant?.id === variant.id);
1640
+ const variantIndividualSlug = detailSlug(variant);
1641
+ const variantSlug = variantIndividualSlug !== "" ? asSlug(slugjoin(scopePrefix, variantIndividualSlug)) : scopePrefix;
1642
+ const metaPointsTo = metaStr(variant.metadata, "pointsTo");
1643
+ const children = buildSidebarRootChildren(ctx, variantSegs, scopePrefix);
1644
+ return {
1645
+ type: "variant",
1646
+ ...withMetadataDefaults({
1647
+ id: ctx.nodeId(`variant:${variantSlug}`),
1648
+ title: variant.displayName,
1649
+ slug: variantSlug,
1650
+ icon: variant.icon ?? void 0,
1651
+ hidden: variant.hidden,
1652
+ viewers: toViewers(variant.viewers)
1653
+ }),
1654
+ default: detailIsDefault(variant),
1655
+ variantId: VariantId(String(variant.id)),
1656
+ subtitle: metaStr(variant.metadata, "subtitle") ?? void 0,
1657
+ image: void 0,
1658
+ pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1659
+ children
1660
+ };
1661
+ });
1662
+ return {
1663
+ type: "varianted",
1664
+ id: ctx.nodeId(`varianted:${scopeSegs[0] != null ? scopeKey(scopeSegs[0].seg) : "root"}`),
1665
+ collapsed: void 0,
1666
+ children: variantChildren
1667
+ };
1668
+ }
1669
+ function buildSidebarRootWithVariants(ctx, scopeSegs, scopePrefix, changelogScopePrefix) {
1670
+ const variants = uniqueDetails(scopeSegs, "variant");
1671
+ if (variants.length <= 1) {
1672
+ return buildSidebarRoot(ctx, scopeSegs, scopePrefix, changelogScopePrefix);
1673
+ }
1674
+ const variantedNode = buildVariantedNode(ctx, variants, scopeSegs, scopePrefix);
1675
+ const first = scopeSegs[0];
1676
+ return {
1677
+ type: "sidebarRoot",
1678
+ id: ctx.nodeId(`sidebar:${first != null ? scopeKey(first.seg) : "root"}`),
1679
+ collapsed: void 0,
1680
+ children: [variantedNode]
1681
+ };
1682
+ }
1683
+ function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix) {
1247
1684
  if (!tabsPresent) {
1248
- return buildSidebarRoot(ctx, scopeSegs);
1685
+ const variants = uniqueDetails(scopeSegs, "variant");
1686
+ if (variants.length > 1) {
1687
+ return buildVariantedNode(ctx, variants, scopeSegs, scopePrefix);
1688
+ }
1689
+ return buildSidebarRoot(ctx, scopeSegs, scopePrefix);
1249
1690
  }
1250
1691
  const tabDetails = uniqueDetails(scopeSegs, "tab");
1251
1692
  const children = tabDetails.map((tab) => {
1252
- const tm = detailMeta(tab);
1253
- const tabSlug = asSlug(scopeSlugPrefix(Slug(""), tab));
1254
- if (tm.tab_type === "link") {
1693
+ const tabType = metaStr(tab.metadata, "tab_type");
1694
+ const tabSlug = asSlug(scopeSlugPrefix(scopePrefix, tab));
1695
+ if (tabType === "link") {
1255
1696
  return {
1256
1697
  type: "link",
1257
- id: ctx.nodeId(`link:${tm.url ?? tabSlug}`),
1698
+ id: ctx.nodeId(`link:${metaStr(tab.metadata, "url") ?? tabSlug}`),
1258
1699
  collapsed: void 0,
1259
1700
  title: tab.displayName,
1260
1701
  icon: tab.icon ?? void 0,
1261
- url: Url(tm.url ?? ""),
1702
+ url: Url(metaStr(tab.metadata, "url") ?? ""),
1262
1703
  target: void 0
1263
1704
  };
1264
1705
  }
1265
- if (tm.tab_type === "changelog") {
1706
+ if (tabType === "changelog") {
1266
1707
  const tabSegs2 = scopeSegs.filter((s) => s.seg.tab?.id === tab.id);
1267
- const changelogSeg = tabSegs2.find((s) => s.meta.type === "changelog");
1708
+ const changelogSeg = tabSegs2.find((s) => metaStr(s.seg.metadata, "type") === "changelog");
1268
1709
  if (changelogSeg != null) {
1269
- return changelogNode(ctx, changelogSeg);
1710
+ return changelogNode(ctx, changelogSeg, scopePrefix);
1270
1711
  }
1271
1712
  return {
1272
1713
  type: "changelog",
@@ -1284,6 +1725,7 @@ function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent) {
1284
1725
  };
1285
1726
  }
1286
1727
  const tabSegs = scopeSegs.filter((s) => s.seg.tab?.id === tab.id);
1728
+ const metaPointsTo = metaStr(tab.metadata, "pointsTo");
1287
1729
  return {
1288
1730
  type: "tab",
1289
1731
  ...withMetadataDefaults({
@@ -1294,8 +1736,15 @@ function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent) {
1294
1736
  hidden: tab.hidden,
1295
1737
  viewers: toViewers(tab.viewers)
1296
1738
  }),
1297
- pointsTo: pointsToSlug(ctx, tm),
1298
- child: buildSidebarRoot(ctx, tabSegs)
1739
+ pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : void 0,
1740
+ // Structural sections under this tab are rooted at the TAB slug
1741
+ // (`{...}/{version}/{tab}`) so their slugs nest under the tab
1742
+ // (matching v2) while still starting with the version slug, keeping
1743
+ // the subtree inside the default-version prune window (see
1744
+ // {@link structuralNodeSlug}).
1745
+ // Changelog sidebar children use the product/version prefix — v2
1746
+ // roots changelogs at the scope level, not under the tab.
1747
+ child: buildSidebarRootWithVariants(ctx, tabSegs, tabSlug, scopePrefix)
1299
1748
  };
1300
1749
  });
1301
1750
  const first = scopeSegs[0];
@@ -1306,24 +1755,27 @@ function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent) {
1306
1755
  children
1307
1756
  };
1308
1757
  }
1309
- function buildUnversioned(ctx, scopeSegs, tabsPresent) {
1758
+ function buildUnversioned(ctx, scopeSegs, scopePrefix, tabsPresent) {
1310
1759
  const first = scopeSegs[0];
1311
1760
  return {
1312
1761
  type: "unversioned",
1313
1762
  id: ctx.nodeId(`unversioned:${first?.seg.product?.id ?? "root"}`),
1314
1763
  collapsed: void 0,
1315
1764
  landingPage: void 0,
1316
- child: buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent)
1765
+ // The enclosing scope prefix (product slug, or rootSlug at the top
1766
+ // level) roots structural sections so they share the scope's slug
1767
+ // namespace.
1768
+ child: buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix)
1317
1769
  };
1318
1770
  }
1319
1771
  function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix) {
1320
1772
  const children = versions.map((version) => {
1321
- const vm = detailMeta(version);
1322
1773
  const versionSegs = scoped.filter((s) => s.seg.version?.id === version.id);
1323
1774
  const tabsPresent = uniqueDetails(versionSegs, "tab").length > 0;
1324
- const prefix = productPrefix ?? rootSlug;
1325
- const slug = vm.default ? prefix : scopeSlugPrefix(rootSlug, version);
1326
- return {
1775
+ const prefix = productPrefix != null ? productPrefix : rootSlug;
1776
+ const versionSegment = detailSlug(version);
1777
+ const slug = versionSegment !== "" ? slugjoin(asSlug(prefix), versionSegment) : asSlug(prefix);
1778
+ const node = {
1327
1779
  type: "version",
1328
1780
  ...withMetadataDefaults({
1329
1781
  id: ctx.nodeId(`version:${slug}`),
@@ -1333,14 +1785,20 @@ function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix) {
1333
1785
  hidden: version.hidden,
1334
1786
  viewers: toViewers(version.viewers)
1335
1787
  }),
1336
- default: vm.default ?? false,
1788
+ default: detailIsDefault(version),
1337
1789
  versionId: VersionId(version.id),
1338
1790
  availability: void 0,
1339
1791
  landingPage: void 0,
1340
1792
  announcement: void 0,
1341
- pointsTo: pointsToSlug(ctx, vm),
1342
- child: buildTabbedOrSidebar(ctx, versionSegs, tabsPresent)
1793
+ pointsTo: metaStr(version.metadata, "pointsTo") != null ? pointsToSlug(metaStr(version.metadata, "pointsTo")) : void 0,
1794
+ // The version's full slug roots structural sections so the whole
1795
+ // version subtree stays inside the default-version prune window.
1796
+ child: buildTabbedOrSidebar(ctx, versionSegs, tabsPresent, asSlug(slug))
1343
1797
  };
1798
+ if (node.default) {
1799
+ markDefaultVersionCanonicalSlugs(node, productPrefix != null ? asSlug(productPrefix) : rootSlug, node.slug);
1800
+ }
1801
+ return node;
1344
1802
  });
1345
1803
  return {
1346
1804
  type: "versioned",
@@ -1349,15 +1807,32 @@ function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix) {
1349
1807
  children
1350
1808
  };
1351
1809
  }
1810
+ function markDefaultVersionCanonicalSlugs(node, pruneSlug, versionSlug) {
1811
+ traverseDF(node, (child) => {
1812
+ if (hasMetadata(child)) {
1813
+ const canonicalSlug = toDefaultSlug(
1814
+ child.canonicalSlug ?? child.slug,
1815
+ pruneSlug,
1816
+ versionSlug
1817
+ );
1818
+ if (canonicalSlug !== child.slug) {
1819
+ child.canonicalSlug = canonicalSlug;
1820
+ }
1821
+ }
1822
+ if (hasRedirect(child)) {
1823
+ child.pointsTo = toDefaultSlug(child.pointsTo, pruneSlug, versionSlug);
1824
+ }
1825
+ return;
1826
+ });
1827
+ }
1352
1828
  function buildProductGroup(ctx, products, scoped, rootSlug) {
1353
1829
  const children = products.map((product) => {
1354
- const pm = detailMeta(product);
1355
1830
  const productSegs = scoped.filter((s) => s.seg.product?.id === product.id);
1356
1831
  const versions = uniqueDetails(productSegs, "version");
1357
1832
  const tabsPresent = uniqueDetails(productSegs, "tab").length > 0;
1358
1833
  const productPrefix = scopeSlugPrefix(rootSlug, product);
1359
- const productChild = versions.length > 0 ? buildVersioned(ctx, versions, productSegs, rootSlug, productPrefix) : buildUnversioned(ctx, productSegs, tabsPresent);
1360
- return {
1834
+ const productChild = versions.length > 0 ? buildVersioned(ctx, versions, productSegs, rootSlug, productPrefix) : buildUnversioned(ctx, productSegs, asSlug(productPrefix), tabsPresent);
1835
+ const node = {
1361
1836
  type: "product",
1362
1837
  ...withMetadataDefaults({
1363
1838
  id: ctx.nodeId(`product:${productPrefix}`),
@@ -1368,13 +1843,19 @@ function buildProductGroup(ctx, products, scoped, rootSlug) {
1368
1843
  viewers: toViewers(product.viewers)
1369
1844
  }),
1370
1845
  default: detailIsDefault(product),
1371
- productId: ProductId(product.id),
1372
- subtitle: pm.subtitle ?? "",
1846
+ // `product.id` is the content-addressed STORAGE hash (the segment
1847
+ // key). `productId` is the SEMANTIC identifier search/UI key off
1848
+ // (the product-scoped search filter does `product.title:${productId}`,
1849
+ // so it must equal the product title). v2 carries the display name
1850
+ // here; sourcing it from the hash makes that filter match nothing.
1851
+ productId: ProductId(product.displayName),
1852
+ subtitle: metaStr(product.metadata, "subtitle") ?? "",
1373
1853
  image: void 0,
1374
1854
  announcement: void 0,
1375
- pointsTo: pointsToSlug(ctx, pm),
1855
+ pointsTo: metaStr(product.metadata, "pointsTo") != null ? pointsToSlug(metaStr(product.metadata, "pointsTo")) : void 0,
1376
1856
  child: productChild
1377
1857
  };
1858
+ return node;
1378
1859
  });
1379
1860
  return {
1380
1861
  type: "productgroup",
@@ -1389,6 +1870,8 @@ function buildProductGroup(ctx, products, scoped, rootSlug) {
1389
1870
  apiLeafNodeFromNavRoute,
1390
1871
  buildFullRootFromSegments,
1391
1872
  collectApiLeafNodesFromNav,
1873
+ createBuildContext,
1874
+ mergeEndpointPairs,
1392
1875
  segmentApiDefinitionId
1393
1876
  });
1394
1877
  //# sourceMappingURL=ledger-root-builder.js.map