@fern-api/fdr-sdk 1.2.34-9b3482cda6 → 1.2.35-05f18d9a75

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.
@@ -651,6 +651,9 @@ function slugjoin(...parts) {
651
651
  }
652
652
 
653
653
  // src/navigation/ledger-root-builder.ts
654
+ var segMeta = (seg) => seg.metadata ?? {};
655
+ var routeMeta = (route) => route.metadata ?? {};
656
+ var detailMeta = (detail) => detail.metadata ?? {};
654
657
  function createBuildContext(basePath) {
655
658
  const seen = /* @__PURE__ */ new Map();
656
659
  const basePrefix = basePath.replace(/^\/+|\/+$/g, "");
@@ -669,41 +672,6 @@ function createBuildContext(basePath) {
669
672
  function asSlug(path) {
670
673
  return Slug(path.replace(/^\/+|\/+$/g, ""));
671
674
  }
672
- function metaStr(metadata, key) {
673
- if (metadata != null && typeof metadata === "object" && key in metadata) {
674
- const v = metadata[key];
675
- return typeof v === "string" ? v : void 0;
676
- }
677
- return void 0;
678
- }
679
- function metaBool(metadata, key) {
680
- if (metadata != null && typeof metadata === "object" && key in metadata) {
681
- const v = metadata[key];
682
- return typeof v === "boolean" ? v : void 0;
683
- }
684
- return void 0;
685
- }
686
- function metaCollapsed(metadata) {
687
- if (metadata != null && typeof metadata === "object" && "collapsed" in metadata) {
688
- const v = metadata.collapsed;
689
- if (typeof v === "boolean") {
690
- return v;
691
- }
692
- if (v === "open-by-default") {
693
- return "open-by-default";
694
- }
695
- }
696
- return void 0;
697
- }
698
- function metaStrArr(metadata, key) {
699
- if (metadata != null && typeof metadata === "object" && key in metadata) {
700
- const v = metadata[key];
701
- if (Array.isArray(v)) {
702
- return v.filter((x) => typeof x === "string");
703
- }
704
- }
705
- return void 0;
706
- }
707
675
  function toViewers(viewers) {
708
676
  if (viewers == null || viewers.length === 0) {
709
677
  return void 0;
@@ -711,29 +679,17 @@ function toViewers(viewers) {
711
679
  return viewers.map((v) => RoleId(v));
712
680
  }
713
681
  function mergeVariantViewers(seg) {
714
- const segViewers = metaStrArr(seg.metadata, "viewers");
715
- const variantViewers = seg.variant?.viewers;
716
- if ((segViewers == null || segViewers.length === 0) && (variantViewers == null || variantViewers.length === 0)) {
717
- return void 0;
718
- }
719
- const merged = /* @__PURE__ */ new Set();
720
- if (segViewers != null) {
721
- for (const v of segViewers) {
722
- merged.add(v);
723
- }
724
- }
725
- if (variantViewers != null) {
726
- for (const v of variantViewers) {
727
- merged.add(v);
728
- }
729
- }
730
- return merged.size > 0 ? [...merged].map((v) => RoleId(v)) : void 0;
682
+ const all = [...segMeta(seg).viewers ?? [], ...seg.variant?.viewers ?? []];
683
+ return all.length > 0 ? [...new Set(all)].map((v) => RoleId(v)) : void 0;
731
684
  }
732
685
  function detailSlug(detail) {
733
- return metaStr(detail.metadata, "slug") ?? "";
686
+ return detailMeta(detail).slug ?? "";
734
687
  }
735
688
  function detailIsDefault(detail) {
736
- return metaBool(detail.metadata, "default") ?? false;
689
+ return detailMeta(detail).default ?? false;
690
+ }
691
+ function pointsToSlug(ctx, meta) {
692
+ return meta.pointsTo != null ? ctx.contentSlug(meta.pointsTo) : void 0;
737
693
  }
738
694
  function scopeKey(seg) {
739
695
  return [seg.product?.id ?? "", seg.version?.id ?? "", seg.variant?.id ?? "", seg.tab?.id ?? ""].join("|");
@@ -753,240 +709,223 @@ function withMetadataDefaults(base) {
753
709
  };
754
710
  }
755
711
  function artifactToNode(ctx, route) {
756
- const md = route.metadata;
757
- const title = metaStr(md, "title") ?? "";
758
- const icon = metaStr(md, "icon");
759
- const viewers = toViewers(metaStrArr(md, "viewers"));
712
+ const md = routeMeta(route);
760
713
  const slug = ctx.contentSlug(route.fullPath ?? "");
761
714
  switch (route.type) {
762
715
  case "markdown": {
763
- if (metaBool(md, "isOverview")) {
716
+ if (md.isOverview) {
764
717
  return void 0;
765
718
  }
766
- const pageId = metaStr(md, "pageId") ?? "";
767
- const node = {
719
+ return {
768
720
  type: "page",
769
721
  ...withMetadataDefaults({
770
722
  id: ctx.nodeId(`page:${slug}`),
771
- title,
723
+ title: md.title ?? "",
772
724
  slug,
773
- icon,
725
+ icon: md.icon,
774
726
  hidden: route.hidden,
775
- viewers
727
+ viewers: toViewers(md.viewers)
776
728
  }),
777
- pageId: PageId(pageId),
778
- noindex: metaBool(md, "noindex"),
729
+ pageId: PageId(md.pageId ?? ""),
730
+ noindex: md.noindex,
779
731
  availability: void 0
780
732
  };
781
- return node;
782
733
  }
783
734
  case "link": {
784
- const node = {
735
+ return {
785
736
  type: "link",
786
- id: ctx.nodeId(`link:${metaStr(md, "url") ?? route.fullPath ?? ""}`),
737
+ id: ctx.nodeId(`link:${md.url ?? route.fullPath ?? ""}`),
787
738
  collapsed: void 0,
788
- title,
789
- icon,
790
- url: Url(metaStr(md, "url") ?? ""),
739
+ title: md.title ?? "",
740
+ icon: md.icon,
741
+ url: Url(md.url ?? ""),
791
742
  target: void 0
792
743
  };
793
- return node;
794
744
  }
795
745
  // API leaf types are handled by apiReferenceNode (which calls
796
746
  // apiLeafNodeFromNavRouteInternal), not by section-level artifact
797
747
  // conversion. Returning undefined here prevents them from appearing
798
748
  // as duplicate siblings alongside the apiReference node.
799
- case "rest":
800
- case "asyncapi":
801
- case "webhook":
802
- case "grpc":
803
- case "graphql":
804
- return void 0;
805
749
  default:
806
750
  return void 0;
807
751
  }
808
752
  }
809
- function apiLeafNodeFromNavRoute(route, basePath, segmentApiDefinitionId2) {
753
+ function apiLeafNodeFromNavRoute(route, basePath, segmentApiDefId) {
810
754
  const ctx = createBuildContext(basePath);
811
- return apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2);
755
+ return apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefId);
812
756
  }
813
- function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2) {
814
- const md = route.metadata;
815
- const apiDefinitionId = ApiDefinitionId(metaStr(md, "apiDefinitionId") ?? segmentApiDefinitionId2);
757
+ function apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefId) {
758
+ const md = routeMeta(route);
816
759
  const slug = ctx.contentSlug(route.fullPath ?? "");
817
- const title = metaStr(md, "title") ?? "";
818
- const icon = metaStr(md, "icon");
819
- const viewers = toViewers(metaStrArr(md, "viewers"));
820
- const meta = withMetadataDefaults({
821
- id: ctx.nodeId(`api-leaf:${slug}`),
822
- title,
823
- slug,
824
- icon,
825
- hidden: route.hidden,
826
- viewers
827
- });
828
- if (route.type === "rest") {
829
- const endpointId = metaStr(md, "endpointId");
830
- const method = metaStr(md, "method");
831
- if (endpointId == null || method == null) {
832
- return void 0;
833
- }
834
- return {
835
- type: "endpoint",
836
- ...meta,
837
- method,
838
- endpointId: EndpointId(endpointId),
839
- apiDefinitionId,
840
- isResponseStream: metaBool(md, "isResponseStream"),
841
- availability: void 0,
842
- playground: void 0
843
- };
844
- }
845
- if (route.type === "webhook") {
846
- const webhookId = metaStr(md, "webhookId");
847
- const method = metaStr(md, "method");
848
- if (webhookId == null || method == null) {
849
- return void 0;
850
- }
851
- return {
852
- type: "webhook",
853
- ...meta,
854
- method,
855
- webhookId: WebhookId(webhookId),
856
- apiDefinitionId,
857
- availability: void 0
858
- };
859
- }
860
- if (route.type === "asyncapi") {
861
- const webSocketId = metaStr(md, "webSocketId");
862
- if (webSocketId == null) {
863
- return void 0;
864
- }
865
- return {
866
- type: "webSocket",
867
- ...meta,
868
- webSocketId: WebSocketId(webSocketId),
869
- apiDefinitionId,
870
- availability: void 0,
871
- playground: void 0
872
- };
873
- }
874
- if (route.type === "grpc") {
875
- const grpcId = metaStr(md, "grpcId");
876
- const method = metaStr(md, "method");
877
- if (grpcId == null || method == null) {
878
- return void 0;
879
- }
880
- return {
881
- type: "grpc",
882
- ...meta,
883
- method,
884
- grpcId: GrpcId(grpcId),
885
- apiDefinitionId,
886
- availability: void 0
887
- };
888
- }
889
- if (route.type === "graphql") {
890
- const graphqlOperationId = metaStr(md, "graphqlOperationId");
891
- const operationType = metaStr(md, "operationType");
892
- if (graphqlOperationId == null || operationType == null) {
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:
893
828
  return void 0;
894
- }
895
- return {
896
- type: "graphql",
897
- ...meta,
898
- operationType,
899
- graphqlOperationId: GraphQlOperationId(graphqlOperationId),
900
- graphqlOperationIds: void 0,
901
- apiDefinitionId,
902
- availability: void 0,
903
- playground: void 0
904
- };
905
829
  }
906
- return void 0;
907
830
  }
908
- function collectApiLeafNodesFromNav(routes, basePath, segmentApiDefinitionId2) {
831
+ function collectApiLeafNodesFromNav(routes, basePath, segmentApiDefId) {
909
832
  const ctx = createBuildContext(basePath);
910
- return routes.map((route) => apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId2)).filter((node) => node != null);
833
+ return routes.map((route) => apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefId)).filter((node) => node != null);
911
834
  }
912
835
  function segmentApiDefinitionId(metadata) {
913
- return metaStr(metadata, "apiDefinitionId");
836
+ return metadata?.apiDefinitionId;
914
837
  }
915
838
  function overviewRoute(nav) {
916
- return nav.find((r) => r.type === "markdown" && metaBool(r.metadata, "isOverview"));
839
+ 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
+ }
845
+ }
846
+ }
847
+ return void 0;
917
848
  }
918
849
  function sectionNode(ctx, scoped, sectionChildren) {
919
- const { seg, nav } = scoped;
850
+ const { seg, meta: sm, nav } = scoped;
920
851
  const overview = overviewRoute(nav);
921
- const overviewPageId = overview != null ? metaStr(overview.metadata, "pageId") : void 0;
922
- const slug = ctx.contentSlug(overview?.fullPath ?? seg.section);
852
+ const overviewPageId = overview?.meta.pageId;
853
+ const slug = ctx.contentSlug(overview?.route.fullPath ?? seg.section);
923
854
  const leafChildren = nav.map((r) => artifactToNode(ctx, r)).filter((n) => n != null);
924
855
  const defaults = withMetadataDefaults({
925
856
  id: ctx.nodeId(`section:${slug}`),
926
- title: metaStr(seg.metadata, "title") ?? "",
857
+ title: sm.title ?? "",
927
858
  slug,
928
- icon: metaStr(seg.metadata, "icon"),
859
+ icon: sm.icon,
929
860
  hidden: seg.hidden,
930
861
  viewers: mergeVariantViewers(seg)
931
862
  });
932
863
  return {
933
864
  type: "section",
934
865
  ...defaults,
935
- collapsed: metaCollapsed(seg.metadata) ?? defaults.collapsed,
866
+ collapsed: sm.collapsed ?? defaults.collapsed,
936
867
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
937
868
  noindex: void 0,
938
- collapsible: metaBool(seg.metadata, "collapsible"),
939
- collapsedByDefault: metaBool(seg.metadata, "collapsedByDefault"),
869
+ collapsible: sm.collapsible,
870
+ collapsedByDefault: sm.collapsedByDefault,
940
871
  availability: void 0,
941
872
  pointsTo: void 0,
942
873
  children: [...leafChildren, ...sectionChildren]
943
874
  };
944
875
  }
945
- function directChildApiPackages(parentSection, scopeSegs) {
946
- const sectionPaths = new Set(scopeSegs.map((s) => s.seg.section));
947
- return scopeSegs.filter((s) => {
948
- if (metaStr(s.seg.metadata, "type") !== "apiPackage") {
949
- return false;
950
- }
951
- const parent = parentSectionPath(s.seg.section);
952
- if (parent === parentSection) {
953
- return true;
954
- }
955
- if (!sectionPaths.has(parent)) {
956
- return nearestExistingAncestor(s.seg.section, sectionPaths) === parentSection;
876
+ function parentSectionPath(sectionPath) {
877
+ const idx = sectionPath.lastIndexOf("/");
878
+ return idx === -1 ? "" : sectionPath.slice(0, idx);
879
+ }
880
+ function nearestExistingAncestor(sectionPath, existing) {
881
+ let current = parentSectionPath(sectionPath);
882
+ while (current !== "") {
883
+ if (existing.has(current)) {
884
+ return current;
957
885
  }
958
- return false;
959
- }).sort((a, b) => a.seg.sortOrder - b.seg.sortOrder);
886
+ current = parentSectionPath(current);
887
+ }
888
+ return "";
889
+ }
890
+ function isDirectChildOf(sec, parentPath, sectionPaths) {
891
+ const parent = parentSectionPath(sec);
892
+ if (parent === parentPath) {
893
+ return true;
894
+ }
895
+ return !sectionPaths.has(parent) && nearestExistingAncestor(sec, sectionPaths) === parentPath;
960
896
  }
961
- function buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId) {
962
- const { seg, nav } = scoped;
963
- const rawLeafNodes = nav.map((route) => apiLeafNodeFromNavRouteInternal(ctx, route, apiDefinitionId)).filter((node) => node != null);
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);
899
+ }
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);
964
903
  const leafNodes = mergeEndpointPairs(ctx, rawLeafNodes, nav);
965
- const childPackages = directChildApiPackages(seg.section, scopeSegs);
904
+ const childPackages = directChildApiPackages(scoped.seg.section, scopeSegs, sectionPaths);
966
905
  const packageNodes = childPackages.map(
967
- (child) => apiPackageChildNode(ctx, child, scopeSegs, apiDefinitionId)
906
+ (child) => apiPackageChildNode(ctx, child, scopeSegs, apiDefId, sectionPaths)
968
907
  );
969
908
  return [...leafNodes, ...packageNodes];
970
909
  }
971
- function apiPackageChildNode(ctx, scoped, scopeSegs, parentApiDefinitionId) {
972
- const { seg, nav } = scoped;
910
+ function apiPackageChildNode(ctx, scoped, scopeSegs, parentApiDefId, sectionPaths) {
911
+ const { seg, meta: sm, nav } = scoped;
973
912
  const overview = overviewRoute(nav);
974
- const overviewPageId = overview != null ? metaStr(overview.metadata, "pageId") : void 0;
975
- const apiDefinitionId = metaStr(seg.metadata, "apiDefinitionId") ?? parentApiDefinitionId;
976
- const slug = ctx.contentSlug(overview?.fullPath ?? nav[0]?.fullPath ?? seg.section);
977
- const children = buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId);
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);
978
917
  return {
979
918
  type: "apiPackage",
980
919
  ...withMetadataDefaults({
981
920
  id: ctx.nodeId(`api-pkg:${slug}`),
982
- title: metaStr(seg.metadata, "title") ?? "",
921
+ title: sm.title ?? "",
983
922
  slug,
984
- icon: metaStr(seg.metadata, "icon"),
923
+ icon: sm.icon,
985
924
  hidden: seg.hidden,
986
- viewers: toViewers(metaStrArr(seg.metadata, "viewers"))
925
+ viewers: toViewers(sm.viewers)
987
926
  }),
988
- apiDefinitionId: ApiDefinitionId(apiDefinitionId),
989
- availability: metaStr(seg.metadata, "availability"),
927
+ apiDefinitionId: ApiDefinitionId(apiDefId),
928
+ availability: sm.availability,
990
929
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
991
930
  noindex: void 0,
992
931
  pointsTo: void 0,
@@ -1000,10 +939,9 @@ function mergeEndpointPairs(ctx, leafNodes, allNav) {
1000
939
  if (route.type !== "rest") {
1001
940
  continue;
1002
941
  }
1003
- const pairKey = metaStr(route.metadata, "endpointPairKey");
1004
- const endpointId = metaStr(route.metadata, "endpointId");
1005
- if (pairKey != null && endpointId != null) {
1006
- endpointIdToPairKey.set(endpointId, pairKey);
942
+ const md = routeMeta(route);
943
+ if (md.endpointPairKey != null && md.endpointId != null) {
944
+ endpointIdToPairKey.set(md.endpointId, md.endpointPairKey);
1007
945
  }
1008
946
  }
1009
947
  if (endpointIdToPairKey.size === 0) {
@@ -1045,30 +983,30 @@ function mergeEndpointPairs(ctx, leafNodes, allNav) {
1045
983
  }
1046
984
  return result;
1047
985
  }
1048
- function apiReferenceNode(ctx, scoped, scopeSegs) {
1049
- const { seg, nav } = scoped;
986
+ function apiReferenceNode(ctx, scoped, scopeSegs, sectionPaths) {
987
+ const { seg, meta: sm, nav } = scoped;
1050
988
  const overview = overviewRoute(nav);
1051
- const overviewPageId = overview != null ? metaStr(overview.metadata, "pageId") : void 0;
1052
- const apiDefinitionId = metaStr(seg.metadata, "apiDefinitionId") ?? "";
1053
- const slug = ctx.contentSlug(overview?.fullPath ?? nav[0]?.fullPath ?? seg.section);
1054
- const children = buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId);
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);
1055
993
  return {
1056
994
  type: "apiReference",
1057
995
  ...withMetadataDefaults({
1058
996
  id: ctx.nodeId(`api:${slug}`),
1059
- title: metaStr(seg.metadata, "title") ?? "",
997
+ title: sm.title ?? "",
1060
998
  slug,
1061
- icon: metaStr(seg.metadata, "icon"),
999
+ icon: sm.icon,
1062
1000
  hidden: seg.hidden,
1063
1001
  viewers: mergeVariantViewers(seg)
1064
1002
  }),
1065
- apiDefinitionId: ApiDefinitionId(apiDefinitionId),
1003
+ apiDefinitionId: ApiDefinitionId(apiDefId),
1066
1004
  availability: void 0,
1067
1005
  overviewPageId: overviewPageId != null ? PageId(overviewPageId) : void 0,
1068
1006
  noindex: void 0,
1069
1007
  paginated: true,
1070
- showErrors: metaBool(seg.metadata, "showErrors"),
1071
- hideTitle: metaBool(seg.metadata, "hideTitle"),
1008
+ showErrors: sm.showErrors,
1009
+ hideTitle: sm.hideTitle,
1072
1010
  pointsTo: void 0,
1073
1011
  children,
1074
1012
  changelog: void 0,
@@ -1077,29 +1015,29 @@ function apiReferenceNode(ctx, scoped, scopeSegs) {
1077
1015
  };
1078
1016
  }
1079
1017
  function changelogNode(ctx, scoped) {
1080
- const { seg, nav } = scoped;
1018
+ const { seg, meta: sm, nav } = scoped;
1081
1019
  const overview = overviewRoute(nav);
1082
- const overviewPageId = overview != null ? metaStr(overview.metadata, "pageId") : void 0;
1020
+ const overviewPageId = overview?.meta.pageId;
1083
1021
  const entries = nav.filter((r) => r.type === "changelog");
1084
1022
  const byYear = /* @__PURE__ */ new Map();
1085
1023
  for (const r of entries) {
1086
- const dateStr = metaStr(r.metadata, "date");
1087
- const date = dateStr != null ? new Date(dateStr) : /* @__PURE__ */ new Date(0);
1024
+ const md = routeMeta(r);
1025
+ const date = md.date != null ? new Date(md.date) : /* @__PURE__ */ new Date(0);
1088
1026
  const year = date.getUTCFullYear();
1089
1027
  const month = date.getUTCMonth() + 1;
1090
1028
  const entry = {
1091
1029
  type: "changelogEntry",
1092
1030
  ...withMetadataDefaults({
1093
- id: ctx.nodeId(`cl-entry:${r.fullPath ?? metaStr(r.metadata, "pageId") ?? ""}`),
1094
- title: metaStr(r.metadata, "title") ?? "",
1031
+ id: ctx.nodeId(`cl-entry:${r.fullPath ?? md.pageId ?? ""}`),
1032
+ title: md.title ?? "",
1095
1033
  slug: ctx.contentSlug(r.fullPath ?? ""),
1096
- icon: metaStr(r.metadata, "icon"),
1034
+ icon: md.icon,
1097
1035
  hidden: r.hidden,
1098
- viewers: toViewers(metaStrArr(r.metadata, "viewers"))
1036
+ viewers: toViewers(md.viewers)
1099
1037
  }),
1100
- pageId: PageId(metaStr(r.metadata, "pageId") ?? ""),
1038
+ pageId: PageId(md.pageId ?? ""),
1101
1039
  noindex: void 0,
1102
- date: dateStr ?? "",
1040
+ date: md.date ?? "",
1103
1041
  tags: void 0
1104
1042
  };
1105
1043
  let months = byYear.get(year);
@@ -1111,7 +1049,7 @@ function changelogNode(ctx, scoped) {
1111
1049
  arr.push(entry);
1112
1050
  months.set(month, arr);
1113
1051
  }
1114
- const baseSlug = ctx.contentSlug(overview?.fullPath ?? seg.section);
1052
+ const baseSlug = ctx.contentSlug(overview?.route.fullPath ?? seg.section);
1115
1053
  const years = [...byYear.entries()].sort((a, b) => b[0] - a[0]).map(([year, months]) => ({
1116
1054
  type: "changelogYear",
1117
1055
  ...withMetadataDefaults({
@@ -1139,9 +1077,9 @@ function changelogNode(ctx, scoped) {
1139
1077
  type: "changelog",
1140
1078
  ...withMetadataDefaults({
1141
1079
  id: ctx.nodeId(`changelog:${baseSlug}`),
1142
- title: metaStr(seg.metadata, "title") ?? "",
1080
+ title: sm.title ?? "",
1143
1081
  slug: baseSlug,
1144
- icon: metaStr(seg.metadata, "icon"),
1082
+ icon: sm.icon,
1145
1083
  hidden: seg.hidden,
1146
1084
  viewers: mergeVariantViewers(seg)
1147
1085
  }),
@@ -1150,46 +1088,20 @@ function changelogNode(ctx, scoped) {
1150
1088
  children: years
1151
1089
  };
1152
1090
  }
1153
- function parentSectionPath(sectionPath) {
1154
- const idx = sectionPath.lastIndexOf("/");
1155
- return idx === -1 ? "" : sectionPath.slice(0, idx);
1156
- }
1157
- function nearestExistingAncestor(sectionPath, existing) {
1158
- let current = parentSectionPath(sectionPath);
1159
- while (current !== "") {
1160
- if (existing.has(current)) {
1161
- return current;
1162
- }
1163
- current = parentSectionPath(current);
1164
- }
1165
- return "";
1166
- }
1167
- function buildSectionTree(ctx, scopeSegs, parentPath) {
1168
- const sectionPaths = new Set(scopeSegs.map((s) => s.seg.section));
1091
+ function buildSectionTree(ctx, scopeSegs, parentPath, sectionPaths) {
1169
1092
  const direct = scopeSegs.filter((s) => {
1170
1093
  const sec = s.seg.section;
1171
- const type = metaStr(s.seg.metadata, "type");
1172
- if (sec === "" || type === "tabRoot") {
1173
- return false;
1174
- }
1175
- const parent = parentSectionPath(sec);
1176
- if (parent === parentPath) {
1177
- return true;
1178
- }
1179
- if (!sectionPaths.has(parent)) {
1180
- return nearestExistingAncestor(sec, sectionPaths) === parentPath;
1181
- }
1182
- return false;
1094
+ return sec !== "" && s.meta.type !== "tabRoot" && isDirectChildOf(sec, parentPath, sectionPaths);
1183
1095
  }).sort((a, b) => a.seg.sortOrder - b.seg.sortOrder);
1184
1096
  return direct.map((s) => {
1185
- const type = metaStr(s.seg.metadata, "type");
1097
+ const { type } = s.meta;
1186
1098
  if (type === "apiReference" || type === "apiPackage") {
1187
- return apiReferenceNode(ctx, s, scopeSegs);
1099
+ return apiReferenceNode(ctx, s, scopeSegs, sectionPaths);
1188
1100
  }
1189
1101
  if (type === "changelog") {
1190
1102
  return changelogNode(ctx, s);
1191
1103
  }
1192
- return sectionNode(ctx, s, buildSectionTree(ctx, scopeSegs, s.seg.section));
1104
+ return sectionNode(ctx, s, buildSectionTree(ctx, scopeSegs, s.seg.section, sectionPaths));
1193
1105
  });
1194
1106
  }
1195
1107
  function buildSidebarRootChildren(ctx, scopeSegs) {
@@ -1197,7 +1109,7 @@ function buildSidebarRootChildren(ctx, scopeSegs) {
1197
1109
  const sectionPaths = new Set(ordered.map((s) => s.seg.section));
1198
1110
  const flat = [];
1199
1111
  for (const s of ordered) {
1200
- const type = metaStr(s.seg.metadata, "type");
1112
+ const { type } = s.meta;
1201
1113
  const sec = s.seg.section;
1202
1114
  if (type === "tabRoot" || sec === "") {
1203
1115
  for (const r of s.nav) {
@@ -1208,15 +1120,13 @@ function buildSidebarRootChildren(ctx, scopeSegs) {
1208
1120
  }
1209
1121
  continue;
1210
1122
  }
1211
- const parent = parentSectionPath(sec);
1212
- const isRootLevel = parent === "" || !sectionPaths.has(parent) && nearestExistingAncestor(sec, sectionPaths) === "";
1213
- if (isRootLevel) {
1123
+ if (isDirectChildOf(sec, "", sectionPaths)) {
1214
1124
  if (type === "apiReference" || type === "apiPackage") {
1215
- flat.push(apiReferenceNode(ctx, s, scopeSegs));
1125
+ flat.push(apiReferenceNode(ctx, s, scopeSegs, sectionPaths));
1216
1126
  } else if (type === "changelog") {
1217
1127
  flat.push(changelogNode(ctx, s));
1218
1128
  } else {
1219
- flat.push(sectionNode(ctx, s, buildSectionTree(ctx, scopeSegs, sec)));
1129
+ flat.push(sectionNode(ctx, s, buildSectionTree(ctx, scopeSegs, sec, sectionPaths)));
1220
1130
  }
1221
1131
  }
1222
1132
  }
@@ -1262,10 +1172,7 @@ function buildSidebarRoot(ctx, scopeSegs) {
1262
1172
  function buildFullRootFromSegments(options) {
1263
1173
  const { basePath, title, segments, navBySegment } = options;
1264
1174
  const ctx = createBuildContext(basePath);
1265
- const scoped = segments.filter((seg) => {
1266
- const t = metaStr(seg.metadata, "type");
1267
- return t !== "files" && t !== "redirects";
1268
- }).map((seg) => ({ seg, nav: navBySegment.get(seg.segmentHash) ?? [] }));
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");
1269
1176
  const rootSlug = asSlug(basePath);
1270
1177
  const scopesByKey = /* @__PURE__ */ new Map();
1271
1178
  for (const s of scoped) {
@@ -1283,7 +1190,7 @@ function buildFullRootFromSegments(options) {
1283
1190
  } else if (versions.length > 0) {
1284
1191
  child = buildVersioned(ctx, versions, scoped, rootSlug, void 0);
1285
1192
  } else {
1286
- child = buildUnversioned(ctx, scoped, rootSlug, tabs.length > 0);
1193
+ child = buildUnversioned(ctx, scoped, tabs.length > 0);
1287
1194
  }
1288
1195
  let rootPointsTo;
1289
1196
  if (child.type === "productgroup") {
@@ -1293,15 +1200,20 @@ function buildFullRootFromSegments(options) {
1293
1200
  const defaultVersion = child.children.find((v) => v.default) ?? child.children[0];
1294
1201
  rootPointsTo = defaultVersion?.pointsTo;
1295
1202
  }
1296
- const root = {
1203
+ return {
1297
1204
  type: "root",
1298
1205
  version: "v2",
1299
- ...withMetadataDefaults({ id: ctx.nodeId("root"), title, slug: rootSlug, icon: void 0, hidden: void 0 }),
1206
+ ...withMetadataDefaults({
1207
+ id: ctx.nodeId("root"),
1208
+ title,
1209
+ slug: rootSlug,
1210
+ icon: void 0,
1211
+ hidden: void 0
1212
+ }),
1300
1213
  roles: void 0,
1301
1214
  pointsTo: rootPointsTo,
1302
1215
  child
1303
1216
  };
1304
- return root;
1305
1217
  }
1306
1218
  function uniqueDetails(scoped, dim) {
1307
1219
  const bySlug = /* @__PURE__ */ new Map();
@@ -1310,15 +1222,14 @@ function uniqueDetails(scoped, dim) {
1310
1222
  if (d == null) {
1311
1223
  continue;
1312
1224
  }
1313
- const slug = detailSlug(d);
1225
+ const dm = detailMeta(d);
1226
+ const slug = dm.slug ?? "";
1314
1227
  const existing = bySlug.get(slug);
1315
- if (existing == null) {
1316
- bySlug.set(slug, d);
1317
- } else if (metaStr(d.metadata, "pointsTo") != null && metaStr(existing.metadata, "pointsTo") == null) {
1318
- bySlug.set(slug, d);
1228
+ if (existing == null || dm.pointsTo != null && existing.meta.pointsTo == null) {
1229
+ bySlug.set(slug, { detail: d, meta: dm });
1319
1230
  }
1320
1231
  }
1321
- return [...bySlug.values()].sort((a, b) => a.sortOrder - b.sortOrder);
1232
+ return [...bySlug.values()].map((e) => e.detail).sort((a, b) => a.sortOrder - b.sortOrder);
1322
1233
  }
1323
1234
  function scopeSlugPrefix(rootSlug, ...details) {
1324
1235
  const parts = [rootSlug];
@@ -1338,22 +1249,22 @@ function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent) {
1338
1249
  }
1339
1250
  const tabDetails = uniqueDetails(scopeSegs, "tab");
1340
1251
  const children = tabDetails.map((tab) => {
1341
- const tabType = metaStr(tab.metadata, "tab_type");
1252
+ const tm = detailMeta(tab);
1342
1253
  const tabSlug = asSlug(scopeSlugPrefix(Slug(""), tab));
1343
- if (tabType === "link") {
1254
+ if (tm.tab_type === "link") {
1344
1255
  return {
1345
1256
  type: "link",
1346
- id: ctx.nodeId(`link:${metaStr(tab.metadata, "url") ?? tabSlug}`),
1257
+ id: ctx.nodeId(`link:${tm.url ?? tabSlug}`),
1347
1258
  collapsed: void 0,
1348
1259
  title: tab.displayName,
1349
1260
  icon: tab.icon ?? void 0,
1350
- url: Url(metaStr(tab.metadata, "url") ?? ""),
1261
+ url: Url(tm.url ?? ""),
1351
1262
  target: void 0
1352
1263
  };
1353
1264
  }
1354
- if (tabType === "changelog") {
1265
+ if (tm.tab_type === "changelog") {
1355
1266
  const tabSegs2 = scopeSegs.filter((s) => s.seg.tab?.id === tab.id);
1356
- const changelogSeg = tabSegs2.find((s) => metaStr(s.seg.metadata, "type") === "changelog");
1267
+ const changelogSeg = tabSegs2.find((s) => s.meta.type === "changelog");
1357
1268
  if (changelogSeg != null) {
1358
1269
  return changelogNode(ctx, changelogSeg);
1359
1270
  }
@@ -1373,7 +1284,6 @@ function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent) {
1373
1284
  };
1374
1285
  }
1375
1286
  const tabSegs = scopeSegs.filter((s) => s.seg.tab?.id === tab.id);
1376
- const metaPointsTo = metaStr(tab.metadata, "pointsTo");
1377
1287
  return {
1378
1288
  type: "tab",
1379
1289
  ...withMetadataDefaults({
@@ -1384,7 +1294,7 @@ function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent) {
1384
1294
  hidden: tab.hidden,
1385
1295
  viewers: toViewers(tab.viewers)
1386
1296
  }),
1387
- pointsTo: metaPointsTo != null ? ctx.contentSlug(metaPointsTo) : void 0,
1297
+ pointsTo: pointsToSlug(ctx, tm),
1388
1298
  child: buildSidebarRoot(ctx, tabSegs)
1389
1299
  };
1390
1300
  });
@@ -1396,8 +1306,7 @@ function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent) {
1396
1306
  children
1397
1307
  };
1398
1308
  }
1399
- function buildUnversioned(ctx, scopeSegs, rootSlug, tabsPresent) {
1400
- void rootSlug;
1309
+ function buildUnversioned(ctx, scopeSegs, tabsPresent) {
1401
1310
  const first = scopeSegs[0];
1402
1311
  return {
1403
1312
  type: "unversioned",
@@ -1409,11 +1318,12 @@ function buildUnversioned(ctx, scopeSegs, rootSlug, tabsPresent) {
1409
1318
  }
1410
1319
  function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix) {
1411
1320
  const children = versions.map((version) => {
1321
+ const vm = detailMeta(version);
1412
1322
  const versionSegs = scoped.filter((s) => s.seg.version?.id === version.id);
1413
1323
  const tabsPresent = uniqueDetails(versionSegs, "tab").length > 0;
1414
- const prefix = productPrefix != null ? productPrefix : rootSlug;
1415
- const slug = version.metadata != null && detailIsDefault(version) ? prefix : scopeSlugPrefix(rootSlug, version);
1416
- const node = {
1324
+ const prefix = productPrefix ?? rootSlug;
1325
+ const slug = vm.default ? prefix : scopeSlugPrefix(rootSlug, version);
1326
+ return {
1417
1327
  type: "version",
1418
1328
  ...withMetadataDefaults({
1419
1329
  id: ctx.nodeId(`version:${slug}`),
@@ -1423,15 +1333,14 @@ function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix) {
1423
1333
  hidden: version.hidden,
1424
1334
  viewers: toViewers(version.viewers)
1425
1335
  }),
1426
- default: detailIsDefault(version),
1336
+ default: vm.default ?? false,
1427
1337
  versionId: VersionId(version.id),
1428
1338
  availability: void 0,
1429
1339
  landingPage: void 0,
1430
1340
  announcement: void 0,
1431
- pointsTo: metaStr(version.metadata, "pointsTo") != null ? ctx.contentSlug(metaStr(version.metadata, "pointsTo")) : void 0,
1341
+ pointsTo: pointsToSlug(ctx, vm),
1432
1342
  child: buildTabbedOrSidebar(ctx, versionSegs, tabsPresent)
1433
1343
  };
1434
- return node;
1435
1344
  });
1436
1345
  return {
1437
1346
  type: "versioned",
@@ -1442,12 +1351,13 @@ function buildVersioned(ctx, versions, scoped, rootSlug, productPrefix) {
1442
1351
  }
1443
1352
  function buildProductGroup(ctx, products, scoped, rootSlug) {
1444
1353
  const children = products.map((product) => {
1354
+ const pm = detailMeta(product);
1445
1355
  const productSegs = scoped.filter((s) => s.seg.product?.id === product.id);
1446
1356
  const versions = uniqueDetails(productSegs, "version");
1447
1357
  const tabsPresent = uniqueDetails(productSegs, "tab").length > 0;
1448
1358
  const productPrefix = scopeSlugPrefix(rootSlug, product);
1449
- const productChild = versions.length > 0 ? buildVersioned(ctx, versions, productSegs, rootSlug, productPrefix) : buildUnversioned(ctx, productSegs, rootSlug, tabsPresent);
1450
- const node = {
1359
+ const productChild = versions.length > 0 ? buildVersioned(ctx, versions, productSegs, rootSlug, productPrefix) : buildUnversioned(ctx, productSegs, tabsPresent);
1360
+ return {
1451
1361
  type: "product",
1452
1362
  ...withMetadataDefaults({
1453
1363
  id: ctx.nodeId(`product:${productPrefix}`),
@@ -1459,13 +1369,12 @@ function buildProductGroup(ctx, products, scoped, rootSlug) {
1459
1369
  }),
1460
1370
  default: detailIsDefault(product),
1461
1371
  productId: ProductId(product.id),
1462
- subtitle: metaStr(product.metadata, "subtitle") ?? "",
1372
+ subtitle: pm.subtitle ?? "",
1463
1373
  image: void 0,
1464
1374
  announcement: void 0,
1465
- pointsTo: metaStr(product.metadata, "pointsTo") != null ? ctx.contentSlug(metaStr(product.metadata, "pointsTo")) : void 0,
1375
+ pointsTo: pointsToSlug(ctx, pm),
1466
1376
  child: productChild
1467
1377
  };
1468
- return node;
1469
1378
  });
1470
1379
  return {
1471
1380
  type: "productgroup",