@fern-api/fdr-sdk 1.2.45-932269c163 → 1.2.46-282936abd4

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 (88) hide show
  1. package/dist/client/docs-types/db.d.ts +47 -0
  2. package/dist/client/docs-types/db.d.ts.map +1 -1
  3. package/dist/client/docs-types/read.d.ts +21 -0
  4. package/dist/client/docs-types/read.d.ts.map +1 -1
  5. package/dist/client/docs-types/shared.d.ts +5 -0
  6. package/dist/client/docs-types/shared.d.ts.map +1 -1
  7. package/dist/client/docs-types/shared.js +5 -1
  8. package/dist/client/docs-types/shared.js.map +1 -1
  9. package/dist/client/docs-types/write.d.ts +12 -0
  10. package/dist/client/docs-types/write.d.ts.map +1 -1
  11. package/dist/js/client/FdrClient.js +3 -1
  12. package/dist/js/client/FdrClient.js.map +1 -1
  13. package/dist/js/client/FdrClient.mjs +3 -1
  14. package/dist/js/client/FdrClient.mjs.map +1 -1
  15. package/dist/js/client/types.js +3 -1
  16. package/dist/js/client/types.js.map +1 -1
  17. package/dist/js/client/types.mjs +3 -1
  18. package/dist/js/client/types.mjs.map +1 -1
  19. package/dist/js/converters/index.js +3 -1
  20. package/dist/js/converters/index.js.map +1 -1
  21. package/dist/js/converters/index.mjs +3 -1
  22. package/dist/js/converters/index.mjs.map +1 -1
  23. package/dist/js/docs/index.js +3 -1
  24. package/dist/js/docs/index.js.map +1 -1
  25. package/dist/js/docs/index.mjs +3 -1
  26. package/dist/js/docs/index.mjs.map +1 -1
  27. package/dist/js/index.js +3 -1
  28. package/dist/js/index.js.map +1 -1
  29. package/dist/js/index.mjs +3 -1
  30. package/dist/js/index.mjs.map +1 -1
  31. package/dist/js/navigation/index.js +3 -1
  32. package/dist/js/navigation/index.js.map +1 -1
  33. package/dist/js/navigation/index.mjs +3 -1
  34. package/dist/js/navigation/index.mjs.map +1 -1
  35. package/dist/js/navigation/ledger-root-builder.js +22 -12
  36. package/dist/js/navigation/ledger-root-builder.js.map +1 -1
  37. package/dist/js/navigation/ledger-root-builder.mjs +22 -12
  38. package/dist/js/navigation/ledger-root-builder.mjs.map +1 -1
  39. package/dist/js/orpc-client.js +3 -1
  40. package/dist/js/orpc-client.js.map +1 -1
  41. package/dist/js/orpc-client.mjs +3 -1
  42. package/dist/js/orpc-client.mjs.map +1 -1
  43. package/dist/navigation/__test__/ledger-root-builder.landingPageRedirect.test.d.ts +2 -0
  44. package/dist/navigation/__test__/ledger-root-builder.landingPageRedirect.test.d.ts.map +1 -0
  45. package/dist/navigation/__test__/ledger-root-builder.landingPageRedirect.test.js +227 -0
  46. package/dist/navigation/__test__/ledger-root-builder.landingPageRedirect.test.js.map +1 -0
  47. package/dist/navigation/__test__/ledger-root-builder.unversionedPointsTo.test.js +59 -1
  48. package/dist/navigation/__test__/ledger-root-builder.unversionedPointsTo.test.js.map +1 -1
  49. package/dist/navigation/ledger-root-builder.d.ts.map +1 -1
  50. package/dist/navigation/ledger-root-builder.js +34 -14
  51. package/dist/navigation/ledger-root-builder.js.map +1 -1
  52. package/dist/orpc-client/docs/v1/read/contract.d.ts +14 -0
  53. package/dist/orpc-client/docs/v1/read/contract.d.ts.map +1 -1
  54. package/dist/orpc-client/docs/v1/write/contract.d.ts +4 -0
  55. package/dist/orpc-client/docs/v1/write/contract.d.ts.map +1 -1
  56. package/dist/orpc-client/docs/v2/read/contract.d.ts +32 -0
  57. package/dist/orpc-client/docs/v2/read/contract.d.ts.map +1 -1
  58. package/dist/orpc-client/docs/v2/write/contract.d.ts +8 -0
  59. package/dist/orpc-client/docs/v2/write/contract.d.ts.map +1 -1
  60. package/dist/orpc-client/docs-ledger/contract.d.ts +56 -0
  61. package/dist/orpc-client/docs-ledger/contract.d.ts.map +1 -1
  62. package/dist/orpc-client/docs-ledger/ledger-manifest.d.ts +14 -0
  63. package/dist/orpc-client/docs-ledger/ledger-manifest.d.ts.map +1 -1
  64. package/dist/tsconfig.tsbuildinfo +1 -1
  65. package/dist/types/client/docs-types/db.d.ts +47 -0
  66. package/dist/types/client/docs-types/db.d.ts.map +1 -1
  67. package/dist/types/client/docs-types/read.d.ts +21 -0
  68. package/dist/types/client/docs-types/read.d.ts.map +1 -1
  69. package/dist/types/client/docs-types/shared.d.ts +5 -0
  70. package/dist/types/client/docs-types/shared.d.ts.map +1 -1
  71. package/dist/types/client/docs-types/write.d.ts +12 -0
  72. package/dist/types/client/docs-types/write.d.ts.map +1 -1
  73. package/dist/types/navigation/__test__/ledger-root-builder.landingPageRedirect.test.d.ts +2 -0
  74. package/dist/types/navigation/__test__/ledger-root-builder.landingPageRedirect.test.d.ts.map +1 -0
  75. package/dist/types/navigation/ledger-root-builder.d.ts.map +1 -1
  76. package/dist/types/orpc-client/docs/v1/read/contract.d.ts +14 -0
  77. package/dist/types/orpc-client/docs/v1/read/contract.d.ts.map +1 -1
  78. package/dist/types/orpc-client/docs/v1/write/contract.d.ts +4 -0
  79. package/dist/types/orpc-client/docs/v1/write/contract.d.ts.map +1 -1
  80. package/dist/types/orpc-client/docs/v2/read/contract.d.ts +32 -0
  81. package/dist/types/orpc-client/docs/v2/read/contract.d.ts.map +1 -1
  82. package/dist/types/orpc-client/docs/v2/write/contract.d.ts +8 -0
  83. package/dist/types/orpc-client/docs/v2/write/contract.d.ts.map +1 -1
  84. package/dist/types/orpc-client/docs-ledger/contract.d.ts +56 -0
  85. package/dist/types/orpc-client/docs-ledger/contract.d.ts.map +1 -1
  86. package/dist/types/orpc-client/docs-ledger/ledger-manifest.d.ts +14 -0
  87. package/dist/types/orpc-client/docs-ledger/ledger-manifest.d.ts.map +1 -1
  88. package/package.json +1 -1
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ledger-root-builder.landingPageRedirect.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger-root-builder.landingPageRedirect.test.d.ts","sourceRoot":"","sources":["../../../src/navigation/__test__/ledger-root-builder.landingPageRedirect.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,227 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import * as FernNavigation from "../index.js";
3
+ import { buildFullRootFromSegments } from "../ledger-root-builder";
4
+ /**
5
+ * Regression test: unversioned sites with tabs + landing page.
6
+ *
7
+ * The V1 (legacy) path computes root.pointsTo via followRedirect(child), which
8
+ * visits unversioned.landingPage before unversioned.child (V1 followRedirect.ts:38):
9
+ *
10
+ * unversioned: (node) => followRedirect(node.landingPage ?? node.child)
11
+ *
12
+ * The V2 (latest) followRedirect does the same via getChildren, which returns
13
+ * [landingPage, child] for unversioned nodes (getChildren.ts:38-39).
14
+ *
15
+ * The ledger builder (buildFullRootFromSegments) bypasses both V1 and the
16
+ * V1→V2 migrator: it builds V2 nodes directly. Before the fix, it seeded
17
+ * root.pointsTo from the first tab's metadata.pointsTo — ignoring the landing
18
+ * page entirely. Then mutableUpdatePointsTo preserved this incorrect value
19
+ * because the target slug existed in the tree.
20
+ *
21
+ * This test reproduces the exact topology of the reported site: an unversioned
22
+ * site with two tabs and a landing page at /welcome. It exercises:
23
+ *
24
+ * 1. The seed value from buildFullRootFromSegments
25
+ * 2. mutableUpdatePointsTo preserving the seed
26
+ * 3. findNode("") returning a redirect to the landing page
27
+ */
28
+ function tabSegment(opts) {
29
+ return {
30
+ segmentId: opts.segmentHash,
31
+ segmentHash: opts.segmentHash,
32
+ section: opts.section,
33
+ locale: "en",
34
+ sortOrder: opts.sortOrder ?? 0,
35
+ hidden: false,
36
+ metadata: { type: "section", title: opts.section || "Root" },
37
+ product: null,
38
+ version: null,
39
+ variant: null,
40
+ tab: {
41
+ id: `tab:${opts.tabSlug}`,
42
+ displayName: opts.tabSlug,
43
+ icon: null,
44
+ sortOrder: opts.sortOrder ?? 0,
45
+ hidden: false,
46
+ viewers: [],
47
+ orphaned: false,
48
+ featureFlags: [],
49
+ metadata: {
50
+ slug: opts.tabSlug,
51
+ tab_type: "tab",
52
+ ...(opts.tabPointsTo != null ? { pointsTo: opts.tabPointsTo } : {})
53
+ }
54
+ }
55
+ };
56
+ }
57
+ function markdownRoute(fullPath, title, pageId) {
58
+ return {
59
+ type: "markdown",
60
+ fullPath,
61
+ hidden: false,
62
+ displaySortOrder: 0,
63
+ metadata: { title, pageId }
64
+ };
65
+ }
66
+ /**
67
+ * Builds a root node mimicking the reported site: unversioned, two tabs
68
+ * ("docs" → /docs/start/about, "api-ref" → /api-ref/functions), plus a
69
+ * landing page at /welcome.
70
+ */
71
+ function buildTabbedSiteWithLandingPage() {
72
+ return buildFullRootFromSegments({
73
+ basePath: "",
74
+ title: "Tabbed Site With Landing Page",
75
+ segments: [
76
+ {
77
+ segmentId: "seg-landing",
78
+ segmentHash: "seg-landing",
79
+ section: "",
80
+ locale: "en",
81
+ sortOrder: 0,
82
+ hidden: false,
83
+ metadata: { type: "tabRoot", landingPage: true },
84
+ product: null,
85
+ version: null,
86
+ variant: null,
87
+ tab: null
88
+ },
89
+ tabSegment({
90
+ segmentHash: "seg-tab-docs",
91
+ section: "start",
92
+ tabSlug: "docs",
93
+ tabPointsTo: "docs/start/about",
94
+ sortOrder: 1
95
+ }),
96
+ tabSegment({
97
+ segmentHash: "seg-tab-api",
98
+ section: "functions",
99
+ tabSlug: "api-ref",
100
+ tabPointsTo: "api-ref/functions",
101
+ sortOrder: 2
102
+ })
103
+ ],
104
+ navBySegment: new Map([
105
+ ["seg-landing", [markdownRoute("welcome", "Welcome", "welcome-page")]],
106
+ ["seg-tab-docs", [markdownRoute("docs/start/about", "About", "about-page")]],
107
+ ["seg-tab-api", [markdownRoute("api-ref/functions", "Functions", "functions-page")]]
108
+ ])
109
+ });
110
+ }
111
+ describe("ledger landing-page redirect regression (ledger vs. legacy parity)", () => {
112
+ it("seeds root.pointsTo to the landing page, not the first tab", () => {
113
+ const root = buildTabbedSiteWithLandingPage();
114
+ expect(root.child.type).toBe("unversioned");
115
+ if (root.child.type !== "unversioned") {
116
+ throw new Error("expected unversioned");
117
+ }
118
+ expect(root.child.landingPage).toBeDefined();
119
+ expect(root.child.landingPage?.slug).toBe("welcome");
120
+ // The ledger builder should seed root.pointsTo to the landing page —
121
+ // matching the V1 legacy behavior (V1 followRedirect visits
122
+ // node.landingPage before node.child).
123
+ expect(root.pointsTo).toBe("welcome");
124
+ // Regression guard: the OLD (broken) seed was the first tab's pointsTo.
125
+ expect(root.pointsTo).not.toBe("docs/start/about");
126
+ });
127
+ it("mutableUpdatePointsTo preserves the landing page as root.pointsTo", () => {
128
+ const root = buildTabbedSiteWithLandingPage();
129
+ // Before update: seed is correct.
130
+ expect(root.pointsTo).toBe("welcome");
131
+ // After update: root.pointsTo should remain "welcome" because the
132
+ // landing page node is present in the slug map.
133
+ FernNavigation.utils.mutableUpdatePointsTo(root);
134
+ expect(root.pointsTo).toBe("welcome");
135
+ });
136
+ it("findNode('') returns redirect to landing page, not first tab page", () => {
137
+ const root = buildTabbedSiteWithLandingPage();
138
+ FernNavigation.utils.mutableUpdatePointsTo(root);
139
+ const result = FernNavigation.utils.findNode(root, FernNavigation.Slug(""));
140
+ // The root URL should redirect to the landing page.
141
+ expect(result.type).toBe("redirect");
142
+ if (result.type === "redirect") {
143
+ expect(result.redirect).toBe("welcome");
144
+ }
145
+ });
146
+ it("findNode('welcome') resolves the landing page as a found node", () => {
147
+ const root = buildTabbedSiteWithLandingPage();
148
+ FernNavigation.utils.mutableUpdatePointsTo(root);
149
+ const result = FernNavigation.utils.findNode(root, FernNavigation.Slug("welcome"));
150
+ expect(result.type).toBe("found");
151
+ if (result.type === "found") {
152
+ expect(result.node.type).toBe("landingPage");
153
+ expect(result.node.slug).toBe("welcome");
154
+ }
155
+ });
156
+ it("findNode still resolves tab pages normally", () => {
157
+ const root = buildTabbedSiteWithLandingPage();
158
+ FernNavigation.utils.mutableUpdatePointsTo(root);
159
+ const docs = FernNavigation.utils.findNode(root, FernNavigation.Slug("docs/start/about"));
160
+ expect(docs.type).toBe("found");
161
+ if (docs.type === "found") {
162
+ expect(docs.node.slug).toBe("docs/start/about");
163
+ }
164
+ const api = FernNavigation.utils.findNode(root, FernNavigation.Slug("api-ref/functions"));
165
+ expect(api.type).toBe("found");
166
+ if (api.type === "found") {
167
+ expect(api.node.slug).toBe("api-ref/functions");
168
+ }
169
+ });
170
+ it("without a landing page, root falls back to first tab's pointsTo", () => {
171
+ const root = buildFullRootFromSegments({
172
+ basePath: "",
173
+ title: "Tabbed Site Without Landing Page",
174
+ segments: [
175
+ tabSegment({
176
+ segmentHash: "seg-tab-docs",
177
+ section: "start",
178
+ tabSlug: "docs",
179
+ tabPointsTo: "docs/start/about",
180
+ sortOrder: 0
181
+ }),
182
+ tabSegment({
183
+ segmentHash: "seg-tab-api",
184
+ section: "functions",
185
+ tabSlug: "api-ref",
186
+ tabPointsTo: "api-ref/functions",
187
+ sortOrder: 1
188
+ })
189
+ ],
190
+ navBySegment: new Map([
191
+ ["seg-tab-docs", [markdownRoute("docs/start/about", "About", "about-page")]],
192
+ ["seg-tab-api", [markdownRoute("api-ref/functions", "Functions", "functions-page")]]
193
+ ])
194
+ });
195
+ // No landing page → falls back to first tab's metadata.pointsTo.
196
+ expect(root.pointsTo).toBe("docs/start/about");
197
+ FernNavigation.utils.mutableUpdatePointsTo(root);
198
+ expect(root.pointsTo).toBe("docs/start/about");
199
+ const result = FernNavigation.utils.findNode(root, FernNavigation.Slug(""));
200
+ expect(result.type).toBe("redirect");
201
+ if (result.type === "redirect") {
202
+ expect(result.redirect).toBe("docs/start/about");
203
+ }
204
+ });
205
+ it("demonstrates the pre-fix bug: manually seeding root.pointsTo to a tab page bypasses the landing page", () => {
206
+ // This test proves the regression existed. If root.pointsTo is
207
+ // incorrectly seeded (as the old code did), the landing page is
208
+ // unreachable from the root URL.
209
+ const root = buildTabbedSiteWithLandingPage();
210
+ // Simulate the OLD (broken) ledger behavior: seed root.pointsTo from
211
+ // the first tab's metadata instead of the landing page.
212
+ root.pointsTo = FernNavigation.Slug("docs/start/about");
213
+ // mutableUpdatePointsTo preserves the broken seed because the slug
214
+ // exists in the tree — it never re-derives from followRedirect.
215
+ FernNavigation.utils.mutableUpdatePointsTo(root);
216
+ expect(root.pointsTo).toBe("docs/start/about");
217
+ // findNode("") follows the broken redirect → wrong page.
218
+ const result = FernNavigation.utils.findNode(root, FernNavigation.Slug(""));
219
+ expect(result.type).toBe("redirect");
220
+ if (result.type === "redirect") {
221
+ expect(result.redirect).toBe("docs/start/about");
222
+ // This is the bug: the user expected "welcome" but got a tab page.
223
+ expect(result.redirect).not.toBe("welcome");
224
+ }
225
+ });
226
+ });
227
+ //# sourceMappingURL=ledger-root-builder.landingPageRedirect.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger-root-builder.landingPageRedirect.test.js","sourceRoot":"","sources":["../../../src/navigation/__test__/ledger-root-builder.landingPageRedirect.test.ts"],"names":[],"mappings":"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"}
@@ -92,7 +92,65 @@ describe("buildFullRootFromSegments — unversioned root.pointsTo", () => {
92
92
  });
93
93
  expect(root.pointsTo).toBe("visible/intro");
94
94
  });
95
- it("seeds root.pointsTo from the first tab's metadata (unversioned with tabs)", () => {
95
+ it("seeds root.pointsTo from landing page slug when tabbed site has a landing page", () => {
96
+ const root = buildFullRootFromSegments({
97
+ basePath: "",
98
+ title: "Tabbed Site With Landing",
99
+ segments: [
100
+ // Landing page segment (type: tabRoot with landingPage: true)
101
+ {
102
+ segmentId: "seg-landing",
103
+ segmentHash: "seg-landing",
104
+ section: "",
105
+ locale: "en",
106
+ sortOrder: 0,
107
+ hidden: false,
108
+ metadata: { type: "tabRoot", landingPage: true },
109
+ product: null,
110
+ version: null,
111
+ variant: null,
112
+ tab: null
113
+ },
114
+ tabSegment({
115
+ segmentHash: "seg-tab1",
116
+ section: "start",
117
+ tabSlug: "docs",
118
+ tabPointsTo: "docs/start/about",
119
+ sortOrder: 1
120
+ }),
121
+ tabSegment({
122
+ segmentHash: "seg-tab2",
123
+ section: "functions",
124
+ tabSlug: "api-ref",
125
+ tabPointsTo: "api-ref/functions",
126
+ sortOrder: 2
127
+ })
128
+ ],
129
+ navBySegment: new Map([
130
+ [
131
+ "seg-landing",
132
+ [
133
+ {
134
+ type: "markdown",
135
+ fullPath: "welcome",
136
+ hidden: false,
137
+ displaySortOrder: 0,
138
+ metadata: { title: "Welcome", pageId: "welcome-page" }
139
+ }
140
+ ]
141
+ ]
142
+ ])
143
+ });
144
+ expect(root.child.type).toBe("unversioned");
145
+ if (root.child.type !== "unversioned") {
146
+ throw new Error("expected unversioned root child");
147
+ }
148
+ expect(root.child.landingPage).toBeDefined();
149
+ expect(root.child.landingPage?.slug).toBe("welcome");
150
+ // Root should redirect to the landing page, not the first tab
151
+ expect(root.pointsTo).toBe("welcome");
152
+ });
153
+ it("falls back to first tab's metadata when no landing page exists (unversioned with tabs)", () => {
96
154
  const root = buildFullRootFromSegments({
97
155
  basePath: "",
98
156
  title: "Tabbed Site",
@@ -1 +1 @@
1
- {"version":3,"file":"ledger-root-builder.unversionedPointsTo.test.js","sourceRoot":"","sources":["../../../src/navigation/__test__/ledger-root-builder.unversionedPointsTo.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ledger-root-builder.unversionedPointsTo.test.js","sourceRoot":"","sources":["../../../src/navigation/__test__/ledger-root-builder.unversionedPointsTo.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ledger-root-builder.d.ts","sourceRoot":"","sources":["../../src/navigation/ledger-root-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACnG,OAAO,KAAK,cAAc,MAAM,YAAY,CAAC;AAG7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,KAAK,OAAO,GAAG,uBAAuB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,KAAK,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;AA6B9C,MAAM,WAAW,gBAAgB;IAC7B,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;IACjB,yGAAyG;IACzG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,4EAA4E;IAC5E,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,6DAA6D;IAC7D,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IACtC;;;;;;;;OAQG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CACpC;AAID;;;;;;GAMG;AACH,UAAU,YAAY;IAClB,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,cAAc,CAAC,MAAM,CAAC;IAC/C,kFAAkF;IAClF,WAAW,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,cAAc,CAAC,IAAI,CAAC;CAC9D;AAED,2CAA2C;AAC3C,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CAuBjE;AAoRD;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GACjB,cAAc,CAAC,YAAY,GAC3B,cAAc,CAAC,WAAW,GAC1B,cAAc,CAAC,aAAa,GAC5B,cAAc,CAAC,QAAQ,GACvB,cAAc,CAAC,WAAW,CAAC;AAOjC;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACnC,KAAK,EAAE,QAAQ,EACf,QAAQ,EAAE,MAAM,EAChB,sBAAsB,EAAE,MAAM,GAC/B,WAAW,GAAG,SAAS,CAGzB;AA+KD;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACtC,MAAM,EAAE,QAAQ,EAAE,EAClB,QAAQ,EAAE,MAAM,EAChB,sBAAsB,EAAE,MAAM,GAC/B,WAAW,EAAE,CAKf;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,SAAS,CASxF;AAibD;;;;;;GAMG;AACH,2CAA2C;AAC3C,wBAAgB,kBAAkB,CAC9B,GAAG,EAAE,YAAY,EACjB,SAAS,EAAE,WAAW,EAAE,EACxB,MAAM,EAAE,QAAQ,EAAE,GACnB,cAAc,CAAC,eAAe,EAAE,CAsElC;AAyzBD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,gBAAgB,GAAG,cAAc,CAAC,QAAQ,CAmF5F"}
1
+ {"version":3,"file":"ledger-root-builder.d.ts","sourceRoot":"","sources":["../../src/navigation/ledger-root-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACnG,OAAO,KAAK,cAAc,MAAM,YAAY,CAAC;AAG7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,KAAK,OAAO,GAAG,uBAAuB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,KAAK,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;AA6B9C,MAAM,WAAW,gBAAgB;IAC7B,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;IACjB,yGAAyG;IACzG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,4EAA4E;IAC5E,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,6DAA6D;IAC7D,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IACtC;;;;;;;;OAQG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CACpC;AAID;;;;;;GAMG;AACH,UAAU,YAAY;IAClB,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,cAAc,CAAC,MAAM,CAAC;IAC/C,kFAAkF;IAClF,WAAW,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,cAAc,CAAC,IAAI,CAAC;CAC9D;AAED,2CAA2C;AAC3C,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CAuBjE;AAoRD;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GACjB,cAAc,CAAC,YAAY,GAC3B,cAAc,CAAC,WAAW,GAC1B,cAAc,CAAC,aAAa,GAC5B,cAAc,CAAC,QAAQ,GACvB,cAAc,CAAC,WAAW,CAAC;AAOjC;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACnC,KAAK,EAAE,QAAQ,EACf,QAAQ,EAAE,MAAM,EAChB,sBAAsB,EAAE,MAAM,GAC/B,WAAW,GAAG,SAAS,CAGzB;AA+KD;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACtC,MAAM,EAAE,QAAQ,EAAE,EAClB,QAAQ,EAAE,MAAM,EAChB,sBAAsB,EAAE,MAAM,GAC/B,WAAW,EAAE,CAKf;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,SAAS,CASxF;AAwbD;;;;;;GAMG;AACH,2CAA2C;AAC3C,wBAAgB,kBAAkB,CAC9B,GAAG,EAAE,YAAY,EACjB,SAAS,EAAE,WAAW,EAAE,EACxB,MAAM,EAAE,QAAQ,EAAE,GACnB,cAAc,CAAC,eAAe,EAAE,CAsElC;AA4zBD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,gBAAgB,GAAG,cAAc,CAAC,QAAQ,CA0F5F"}
@@ -623,7 +623,10 @@ function mergeChildrenByPosition(ctx, nav, sectionChildren) {
623
623
  function sectionNode(ctx, scoped, sectionChildren, scopePrefix) {
624
624
  const { seg, nav } = scoped;
625
625
  const overview = overviewRoute(nav) ?? overviewRouteFromSegmentMeta(seg, nav);
626
- const overviewPageId = overview != null ? metaStr(overview.metadata, "pageId") : undefined;
626
+ // Only set overviewPageId from explicit segment metadata, matching v2
627
+ // where overviewPageId comes directly from the config. The isOverview
628
+ // flag discovered by overviewRoute() is still used for slug/noindex.
629
+ const overviewPageId = metaStr(seg.metadata, "overviewPageId");
627
630
  // Strip the leading scope prefix to prevent double-prefixing when the
628
631
  // section path already includes the scope (e.g. section="2026-02-09"
629
632
  // with scopePrefix="2026-02-09" would produce "2026-02-09/2026-02-09").
@@ -647,7 +650,6 @@ function sectionNode(ctx, scoped, sectionChildren, scopePrefix) {
647
650
  }
648
651
  }
649
652
  }
650
- const metaPointsTo = metaStr(seg.metadata, "pointsTo");
651
653
  const defaults = withMetadataDefaults({
652
654
  id: ctx.nodeId(`section:${slug}`),
653
655
  title: metaStr(seg.metadata, "title") ?? "",
@@ -668,7 +670,10 @@ function sectionNode(ctx, scoped, sectionChildren, scopePrefix) {
668
670
  collapsible: metaBool(seg.metadata, "collapsible") ?? (metaCollapsed(seg.metadata) === true ? true : undefined),
669
671
  collapsedByDefault: metaBool(seg.metadata, "collapsedByDefault") ?? (metaCollapsed(seg.metadata) === true ? true : undefined),
670
672
  availability: metaAvailability(seg.metadata),
671
- pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : undefined,
673
+ // Don't read pointsTo from metadata for sections; let
674
+ // mutableUpdatePointsTo compute it via followRedirect so that
675
+ // self-referencing redirects are cleared, matching v2 behavior.
676
+ pointsTo: undefined,
672
677
  children: mergeChildrenByPosition(ctx, nav, sectionChildren)
673
678
  };
674
679
  }
@@ -764,12 +769,13 @@ function buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix)
764
769
  function apiPackageChildNode(ctx, scoped, scopeSegs, parentApiDefinitionId, scopePrefix) {
765
770
  const { seg, nav } = scoped;
766
771
  const overview = overviewRoute(nav);
767
- const overviewPageId = overview != null ? metaStr(overview.metadata, "pageId") : undefined;
772
+ // Only set overviewPageId from explicit segment metadata, matching v2
773
+ // where overviewPageId comes directly from the config.
774
+ const overviewPageId = metaStr(seg.metadata, "overviewPageId");
768
775
  const apiDefinitionId = metaStr(seg.metadata, "apiDefinitionId") ?? parentApiDefinitionId;
769
776
  // Use structuralNodeSlug so the package gets its own slug (matching V2)
770
777
  // rather than inheriting the first endpoint's path.
771
778
  const slug = structuralNodeSlug(ctx, overview?.fullPath, stripLeadingScopePrefix(seg.section, scopePrefix), scopePrefix);
772
- const metaPointsTo = metaStr(seg.metadata, "pointsTo");
773
779
  const children = buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix);
774
780
  return {
775
781
  type: "apiPackage",
@@ -788,7 +794,9 @@ function apiPackageChildNode(ctx, scoped, scopeSegs, parentApiDefinitionId, scop
788
794
  availability: metaAvailability(seg.metadata),
789
795
  overviewPageId: overviewPageId != null ? FernNavigation.PageId(overviewPageId) : undefined,
790
796
  noindex: metaBool(overview?.metadata, "noindex") ?? metaBool(seg.metadata, "noindex"),
791
- pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : undefined,
797
+ // Don't read pointsTo from metadata; let mutableUpdatePointsTo
798
+ // compute it via followRedirect, matching v2 behavior.
799
+ pointsTo: undefined,
792
800
  children,
793
801
  playground: undefined
794
802
  };
@@ -867,7 +875,9 @@ export function mergeEndpointPairs(ctx, leafNodes, allNav) {
867
875
  function apiReferenceNode(ctx, scoped, scopeSegs, scopePrefix) {
868
876
  const { seg, nav } = scoped;
869
877
  const overview = overviewRoute(nav);
870
- const overviewPageId = overview != null ? metaStr(overview.metadata, "pageId") : undefined;
878
+ // Only set overviewPageId from explicit segment metadata, matching v2
879
+ // where overviewPageId comes directly from the config.
880
+ const overviewPageId = metaStr(seg.metadata, "overviewPageId");
871
881
  const apiDefinitionId = metaStr(seg.metadata, "apiDefinitionId") ?? "";
872
882
  // Slug: prefer the overview route, else a structural slug rooted at the
873
883
  // enclosing scope (so the subtree stays inside the default-version prune
@@ -878,7 +888,6 @@ function apiReferenceNode(ctx, scoped, scopeSegs, scopePrefix) {
878
888
  // mutableUpdatePointsTo clears pointsTo (slug === redirect target),
879
889
  // breaking the breadcrumb link.
880
890
  const slug = structuralNodeSlug(ctx, overview?.fullPath, stripLeadingScopePrefix(seg.section, scopePrefix), scopePrefix);
881
- const metaPointsTo = metaStr(seg.metadata, "pointsTo");
882
891
  const children = buildApiChildren(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix);
883
892
  const changelog = attachedApiChangelogNode(ctx, scoped, scopeSegs, apiDefinitionId, scopePrefix);
884
893
  return {
@@ -901,7 +910,9 @@ function apiReferenceNode(ctx, scoped, scopeSegs, scopePrefix) {
901
910
  paginated: metaBool(seg.metadata, "paginated"),
902
911
  showErrors: metaBool(seg.metadata, "showErrors"),
903
912
  hideTitle: metaBool(seg.metadata, "hideTitle"),
904
- pointsTo: metaPointsTo != null ? pointsToSlug(metaPointsTo) : undefined,
913
+ // Don't read pointsTo from metadata; let mutableUpdatePointsTo
914
+ // compute it via followRedirect, matching v2 behavior.
915
+ pointsTo: undefined,
905
916
  children,
906
917
  changelog,
907
918
  playground: undefined,
@@ -1616,17 +1627,26 @@ export function buildFullRootFromSegments(options) {
1616
1627
  // on structure-only roots where the traversal is intentionally skipped.
1617
1628
  let rootPointsTo;
1618
1629
  if (child.type === "productgroup") {
1619
- const defaultProduct = child.children.find((p) => p.default) ?? child.children[0];
1620
- rootPointsTo = defaultProduct?.type === "product" ? defaultProduct.pointsTo : undefined;
1630
+ if (child.landingPage != null && !child.landingPage.hidden) {
1631
+ rootPointsTo = child.landingPage.slug;
1632
+ }
1633
+ else {
1634
+ const defaultProduct = child.children.find((p) => p.default) ?? child.children[0];
1635
+ rootPointsTo = defaultProduct?.type === "product" ? defaultProduct.pointsTo : undefined;
1636
+ }
1621
1637
  }
1622
1638
  else if (child.type === "versioned") {
1623
1639
  const defaultVersion = child.children.find((v) => v.default) ?? child.children[0];
1624
1640
  rootPointsTo = defaultVersion?.pointsTo;
1625
1641
  }
1626
1642
  else if (child.type === "unversioned") {
1627
- // Unversioned sites have no product/version metadata to seed pointsTo.
1628
- // Derive from the first tab's or first section segment's metadata.
1629
- if (tabs.length > 0) {
1643
+ // Landing pages take priority: when the unversioned child has a
1644
+ // visible landing page the root should redirect there, not to the
1645
+ // first tab's content page.
1646
+ if (child.landingPage != null && !child.landingPage.hidden) {
1647
+ rootPointsTo = child.landingPage.slug;
1648
+ }
1649
+ else if (tabs.length > 0) {
1630
1650
  const firstTab = tabs[0];
1631
1651
  const pt = firstTab != null ? metaStr(firstTab.metadata, "pointsTo") : undefined;
1632
1652
  rootPointsTo = pt != null ? pointsToSlug(pt) : undefined;