@fern-api/fdr-sdk 1.2.39-99e577b270 → 1.2.39-a23cd4c739

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 (58) hide show
  1. package/dist/js/converters/index.js +4 -9
  2. package/dist/js/converters/index.js.map +1 -1
  3. package/dist/js/converters/index.mjs +4 -9
  4. package/dist/js/converters/index.mjs.map +1 -1
  5. package/dist/js/index.js +4 -9
  6. package/dist/js/index.js.map +1 -1
  7. package/dist/js/index.mjs +4 -9
  8. package/dist/js/index.mjs.map +1 -1
  9. package/dist/js/navigation/index.js +4 -9
  10. package/dist/js/navigation/index.js.map +1 -1
  11. package/dist/js/navigation/index.mjs +4 -9
  12. package/dist/js/navigation/index.mjs.map +1 -1
  13. package/dist/js/navigation/ledger-root-builder.js +30 -8
  14. package/dist/js/navigation/ledger-root-builder.js.map +1 -1
  15. package/dist/js/navigation/ledger-root-builder.mjs +30 -8
  16. package/dist/js/navigation/ledger-root-builder.mjs.map +1 -1
  17. package/dist/navigation/__test__/findNode.authedRedirect.test.d.ts +2 -0
  18. package/dist/navigation/__test__/findNode.authedRedirect.test.d.ts.map +1 -0
  19. package/dist/navigation/__test__/findNode.authedRedirect.test.js +184 -0
  20. package/dist/navigation/__test__/findNode.authedRedirect.test.js.map +1 -0
  21. package/dist/navigation/__test__/ledger-root-builder.collapsedDeterminism.test.d.ts +2 -0
  22. package/dist/navigation/__test__/ledger-root-builder.collapsedDeterminism.test.d.ts.map +1 -0
  23. package/dist/navigation/__test__/ledger-root-builder.collapsedDeterminism.test.js +85 -0
  24. package/dist/navigation/__test__/ledger-root-builder.collapsedDeterminism.test.js.map +1 -0
  25. package/dist/navigation/__test__/ledger-root-builder.skipSlugApiReference.test.d.ts +2 -0
  26. package/dist/navigation/__test__/ledger-root-builder.skipSlugApiReference.test.d.ts.map +1 -0
  27. package/dist/navigation/__test__/ledger-root-builder.skipSlugApiReference.test.js +210 -0
  28. package/dist/navigation/__test__/ledger-root-builder.skipSlugApiReference.test.js.map +1 -0
  29. package/dist/navigation/__test__/ledger-root-builder.variantSharedSegments.test.d.ts +2 -0
  30. package/dist/navigation/__test__/ledger-root-builder.variantSharedSegments.test.d.ts.map +1 -0
  31. package/dist/navigation/__test__/ledger-root-builder.variantSharedSegments.test.js +262 -0
  32. package/dist/navigation/__test__/ledger-root-builder.variantSharedSegments.test.js.map +1 -0
  33. package/dist/navigation/ledger-root-builder.d.ts +5 -1
  34. package/dist/navigation/ledger-root-builder.d.ts.map +1 -1
  35. package/dist/navigation/ledger-root-builder.js +45 -16
  36. package/dist/navigation/ledger-root-builder.js.map +1 -1
  37. package/dist/navigation/utils/findNode.d.ts +1 -0
  38. package/dist/navigation/utils/findNode.d.ts.map +1 -1
  39. package/dist/navigation/utils/findNode.js +3 -11
  40. package/dist/navigation/utils/findNode.js.map +1 -1
  41. package/dist/navigation/utils/followRedirect.d.ts.map +1 -1
  42. package/dist/navigation/utils/followRedirect.js +2 -0
  43. package/dist/navigation/utils/followRedirect.js.map +1 -1
  44. package/dist/tsconfig.tsbuildinfo +1 -1
  45. package/dist/types/navigation/__test__/findNode.authedRedirect.test.d.ts +2 -0
  46. package/dist/types/navigation/__test__/findNode.authedRedirect.test.d.ts.map +1 -0
  47. package/dist/types/navigation/__test__/ledger-root-builder.collapsedDeterminism.test.d.ts +2 -0
  48. package/dist/types/navigation/__test__/ledger-root-builder.collapsedDeterminism.test.d.ts.map +1 -0
  49. package/dist/types/navigation/__test__/ledger-root-builder.skipSlugApiReference.test.d.ts +2 -0
  50. package/dist/types/navigation/__test__/ledger-root-builder.skipSlugApiReference.test.d.ts.map +1 -0
  51. package/dist/types/navigation/__test__/ledger-root-builder.variantSharedSegments.test.d.ts +2 -0
  52. package/dist/types/navigation/__test__/ledger-root-builder.variantSharedSegments.test.d.ts.map +1 -0
  53. package/dist/types/navigation/ledger-root-builder.d.ts +5 -1
  54. package/dist/types/navigation/ledger-root-builder.d.ts.map +1 -1
  55. package/dist/types/navigation/utils/findNode.d.ts +1 -0
  56. package/dist/types/navigation/utils/findNode.d.ts.map +1 -1
  57. package/dist/types/navigation/utils/followRedirect.d.ts.map +1 -1
  58. package/package.json +1 -1
@@ -0,0 +1,262 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { buildFullRootFromSegments } from "../ledger-root-builder.js";
3
+ /**
4
+ * When a sidebar scope contains both variant-scoped segments (e.g., API
5
+ * references inside variants) and non-variant segments (e.g., guide sections
6
+ * at the product level), the non-variant segments must appear alongside the
7
+ * VariantedNode — not be silently dropped.
8
+ */
9
+ function pageRoute(opts) {
10
+ return {
11
+ type: "markdown",
12
+ fullPath: opts.fullPath,
13
+ hidden: false,
14
+ metadata: { title: opts.title, pageId: `pg-${opts.title}` },
15
+ ...(opts.displaySortOrder != null ? { displaySortOrder: opts.displaySortOrder } : {})
16
+ };
17
+ }
18
+ function endpointRoute(opts) {
19
+ return {
20
+ type: "rest",
21
+ fullPath: opts.fullPath,
22
+ hidden: false,
23
+ metadata: {
24
+ title: opts.title,
25
+ slug: opts.title.toLowerCase().replace(/\s+/g, "-"),
26
+ apiDefinitionId: opts.apiDefinitionId,
27
+ endpointId: opts.title.toLowerCase().replace(/\s+/g, "-"),
28
+ method: "GET"
29
+ },
30
+ ...(opts.displaySortOrder != null ? { displaySortOrder: opts.displaySortOrder } : {})
31
+ };
32
+ }
33
+ const variantA = {
34
+ id: "variant-a-id",
35
+ displayName: "Accounting",
36
+ icon: undefined,
37
+ sortOrder: 0,
38
+ hidden: false,
39
+ viewers: [],
40
+ orphaned: false,
41
+ featureFlags: [],
42
+ metadata: { slug: "accounting", default: true, pointsTo: "prod/accounting/list-accounts" }
43
+ };
44
+ const variantB = {
45
+ id: "variant-b-id",
46
+ displayName: "HRIS",
47
+ icon: undefined,
48
+ sortOrder: 1,
49
+ hidden: false,
50
+ viewers: [],
51
+ orphaned: false,
52
+ featureFlags: [],
53
+ metadata: { slug: "hris", pointsTo: "prod/hris/list-employees" }
54
+ };
55
+ function segment(opts) {
56
+ return {
57
+ segmentId: opts.segmentHash,
58
+ segmentHash: opts.segmentHash,
59
+ section: opts.section,
60
+ locale: "en",
61
+ sortOrder: opts.sortOrder,
62
+ hidden: false,
63
+ metadata: opts.metadata,
64
+ product: opts.product ?? null,
65
+ version: null,
66
+ variant: opts.variant ?? null,
67
+ tab: null
68
+ };
69
+ }
70
+ /** Collect all page/endpoint slugs from the tree. */
71
+ function collectSlugs(node) {
72
+ const slugs = [];
73
+ function walk(n) {
74
+ if (n == null || typeof n !== "object") {
75
+ return;
76
+ }
77
+ const obj = n;
78
+ const type = obj.type;
79
+ if (type === "page" || type === "endpoint") {
80
+ if (typeof obj.slug === "string") {
81
+ slugs.push(obj.slug);
82
+ }
83
+ }
84
+ if (Array.isArray(obj.children)) {
85
+ for (const c of obj.children) {
86
+ walk(c);
87
+ }
88
+ }
89
+ if (obj.child != null) {
90
+ walk(obj.child);
91
+ }
92
+ }
93
+ walk(node);
94
+ return slugs;
95
+ }
96
+ /** Find all top-level sidebar child types under unversioned. */
97
+ function sidebarChildTypes(root) {
98
+ const unversioned = root.child;
99
+ // child might be sidebarRoot or varianted
100
+ const sidebar = unversioned.child;
101
+ if (sidebar.type === "sidebarRoot") {
102
+ return sidebar.children.map((c) => c.type);
103
+ }
104
+ return [sidebar.type];
105
+ }
106
+ describe("buildFullRootFromSegments — non-variant segments alongside variants", () => {
107
+ it("includes non-variant guide sections when variants are present (no tabs)", () => {
108
+ const root = buildFullRootFromSegments({
109
+ basePath: "",
110
+ title: "Test",
111
+ segments: [
112
+ // Non-variant guide section
113
+ segment({
114
+ segmentHash: "seg-guides",
115
+ section: "guides",
116
+ sortOrder: 0,
117
+ metadata: { type: "section", title: "Guides" }
118
+ }),
119
+ // Variant A: API reference
120
+ segment({
121
+ segmentHash: "seg-acct-api",
122
+ section: "accounting",
123
+ sortOrder: 1,
124
+ metadata: { type: "apiReference", title: "Accounting API", apiDefinitionId: "api-acct" },
125
+ variant: variantA
126
+ }),
127
+ // Variant B: API reference
128
+ segment({
129
+ segmentHash: "seg-hris-api",
130
+ section: "hris",
131
+ sortOrder: 2,
132
+ metadata: { type: "apiReference", title: "HRIS API", apiDefinitionId: "api-hris" },
133
+ variant: variantB
134
+ })
135
+ ],
136
+ navBySegment: new Map([
137
+ [
138
+ "seg-guides",
139
+ [
140
+ pageRoute({ fullPath: "guides/overview", title: "Overview", displaySortOrder: 0 }),
141
+ pageRoute({ fullPath: "guides/quickstart", title: "Quickstart", displaySortOrder: 1 })
142
+ ]
143
+ ],
144
+ [
145
+ "seg-acct-api",
146
+ [
147
+ endpointRoute({
148
+ fullPath: "accounting/list-accounts",
149
+ title: "List Accounts",
150
+ apiDefinitionId: "api-acct",
151
+ displaySortOrder: 0
152
+ })
153
+ ]
154
+ ],
155
+ [
156
+ "seg-hris-api",
157
+ [
158
+ endpointRoute({
159
+ fullPath: "hris/list-employees",
160
+ title: "List Employees",
161
+ apiDefinitionId: "api-hris",
162
+ displaySortOrder: 0
163
+ })
164
+ ]
165
+ ]
166
+ ])
167
+ });
168
+ const slugs = collectSlugs(root);
169
+ // Guide pages from non-variant segment must survive
170
+ expect(slugs).toContain("guides/overview");
171
+ expect(slugs).toContain("guides/quickstart");
172
+ // Variant-scoped endpoints must also survive
173
+ expect(slugs).toContain("accounting/list-accounts");
174
+ expect(slugs).toContain("hris/list-employees");
175
+ // The sidebar should contain both a section and a varianted node
176
+ const types = sidebarChildTypes(root);
177
+ expect(types).toContain("section");
178
+ expect(types).toContain("varianted");
179
+ });
180
+ it("includes non-variant sections when variants exist inside a tab", () => {
181
+ const tab = {
182
+ id: "tab-main",
183
+ displayName: "Main",
184
+ icon: undefined,
185
+ sortOrder: 0,
186
+ hidden: false,
187
+ viewers: [],
188
+ orphaned: false,
189
+ featureFlags: [],
190
+ metadata: { slug: "main" }
191
+ };
192
+ const root = buildFullRootFromSegments({
193
+ basePath: "",
194
+ title: "Test",
195
+ segments: [
196
+ // Non-variant guide section inside tab
197
+ segment({
198
+ segmentHash: "seg-tab-guides",
199
+ section: "guides",
200
+ sortOrder: 0,
201
+ metadata: { type: "section", title: "Guides" },
202
+ variant: undefined
203
+ }),
204
+ // Variant A inside same tab
205
+ segment({
206
+ segmentHash: "seg-tab-acct",
207
+ section: "accounting",
208
+ sortOrder: 1,
209
+ metadata: { type: "apiReference", title: "Accounting API", apiDefinitionId: "api-acct" },
210
+ variant: variantA
211
+ }),
212
+ // Variant B inside same tab
213
+ segment({
214
+ segmentHash: "seg-tab-hris",
215
+ section: "hris",
216
+ sortOrder: 2,
217
+ metadata: { type: "apiReference", title: "HRIS API", apiDefinitionId: "api-hris" },
218
+ variant: variantB
219
+ })
220
+ ].map((s) => ({ ...s, tab })),
221
+ navBySegment: new Map([
222
+ [
223
+ "seg-tab-guides",
224
+ [
225
+ pageRoute({ fullPath: "main/guides/overview", title: "Overview", displaySortOrder: 0 }),
226
+ pageRoute({ fullPath: "main/guides/quickstart", title: "Quickstart", displaySortOrder: 1 })
227
+ ]
228
+ ],
229
+ [
230
+ "seg-tab-acct",
231
+ [
232
+ endpointRoute({
233
+ fullPath: "main/accounting/list-accounts",
234
+ title: "List Accounts",
235
+ apiDefinitionId: "api-acct",
236
+ displaySortOrder: 0
237
+ })
238
+ ]
239
+ ],
240
+ [
241
+ "seg-tab-hris",
242
+ [
243
+ endpointRoute({
244
+ fullPath: "main/hris/list-employees",
245
+ title: "List Employees",
246
+ apiDefinitionId: "api-hris",
247
+ displaySortOrder: 0
248
+ })
249
+ ]
250
+ ]
251
+ ])
252
+ });
253
+ const slugs = collectSlugs(root);
254
+ // Non-variant guide pages must survive inside tab
255
+ expect(slugs).toContain("main/guides/overview");
256
+ expect(slugs).toContain("main/guides/quickstart");
257
+ // Variant-scoped endpoints must also survive
258
+ expect(slugs).toContain("main/accounting/list-accounts");
259
+ expect(slugs).toContain("main/hris/list-employees");
260
+ });
261
+ });
262
+ //# sourceMappingURL=ledger-root-builder.variantSharedSegments.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger-root-builder.variantSharedSegments.test.js","sourceRoot":"","sources":["../../../src/navigation/__test__/ledger-root-builder.variantSharedSegments.test.ts"],"names":[],"mappings":"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"}
@@ -101,7 +101,11 @@ export declare function apiLeafNodeFromNavRoute(route: NavRoute, basePath: strin
101
101
  * @internal Exported for the ledger loader's scoped explorer methods.
102
102
  */
103
103
  export declare function collectApiLeafNodesFromNav(routes: NavRoute[], basePath: string, segmentApiDefinitionId: string): ApiLeafNode[];
104
- /** Read the apiDefinitionId off a segment's metadata, or undefined. */
104
+ /**
105
+ * Read the apiDefinitionId off a segment's metadata, or undefined.
106
+ * The matched types (apiReference, apiPackage, changelog) are the
107
+ * subset of {@link StructuralSegmentType} that carry an apiDefinitionId.
108
+ */
105
109
  export declare function segmentApiDefinitionId(metadata: Segment["metadata"]): string | undefined;
106
110
  /**
107
111
  * Merge endpoint nodes that were originally part of an `endpointPair` in the V1
@@ -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;AAE7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;AAE9C,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;AAmPD;;;;;;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,uEAAuE;AACvE,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,SAAS,CASxF;AAgWD;;;;;;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;AAgiBD;;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;AAE7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;AA+OD;;;;;;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;AAgWD;;;;;;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;AAsiBD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,gBAAgB,GAAG,cAAc,CAAC,QAAQ,CAmF5F"}
@@ -1,4 +1,12 @@
1
1
  import * as FernNavigation from "./index.js";
2
+ const STRUCTURAL_SEGMENT_TYPES = new Set([
3
+ "section",
4
+ "apiReference",
5
+ "apiPackage",
6
+ "changelog"
7
+ ]);
8
+ const API_NODE_SEGMENT_TYPES = new Set(["apiReference", "apiPackage"]);
9
+ const INFRA_SEGMENT_TYPES = new Set(["files", "redirects"]);
2
10
  /** @internal Exported for testing only. */
3
11
  export function createBuildContext(basePath) {
4
12
  // Tracks how many times each id key has been handed out, so collisions get
@@ -109,10 +117,7 @@ function toViewers(viewers) {
109
117
  * cross-variant prev/next links to disclose restricted content.
110
118
  */
111
119
  function mergeVariantViewers(seg) {
112
- const segViewers = seg.metadata.type === "section" ||
113
- seg.metadata.type === "apiReference" ||
114
- seg.metadata.type === "apiPackage" ||
115
- seg.metadata.type === "changelog"
120
+ const segViewers = STRUCTURAL_SEGMENT_TYPES.has(seg.metadata.type)
116
121
  ? seg.metadata.viewers
117
122
  : undefined;
118
123
  const variantViewers = seg.variant?.viewers;
@@ -401,7 +406,11 @@ export function collectApiLeafNodesFromNav(routes, basePath, segmentApiDefinitio
401
406
  .map((route) => apiLeafNodeFromNavRouteInternal(ctx, route, segmentApiDefinitionId))
402
407
  .filter((node) => node != null);
403
408
  }
404
- /** Read the apiDefinitionId off a segment's metadata, or undefined. */
409
+ /**
410
+ * Read the apiDefinitionId off a segment's metadata, or undefined.
411
+ * The matched types (apiReference, apiPackage, changelog) are the
412
+ * subset of {@link StructuralSegmentType} that carry an apiDefinitionId.
413
+ */
405
414
  export function segmentApiDefinitionId(metadata) {
406
415
  switch (metadata.type) {
407
416
  case "apiReference":
@@ -962,7 +971,7 @@ function buildSectionTree(ctx, scopeSegs, parentPath, scopePrefix, changelogScop
962
971
  const type = metaStr(s.seg.metadata, "type");
963
972
  const childIndex = metaNum(s.seg.metadata, "childIndex");
964
973
  let node;
965
- if (type === "apiReference" || type === "apiPackage") {
974
+ if (API_NODE_SEGMENT_TYPES.has(type ?? "")) {
966
975
  node = apiReferenceNode(ctx, s, scopeSegs, scopePrefix);
967
976
  }
968
977
  else if (type === "changelog") {
@@ -1051,7 +1060,7 @@ function buildSidebarRootChildren(ctx, scopeSegs, scopePrefix, changelogScopePre
1051
1060
  //
1052
1061
  // hasRootSection = true
1053
1062
  // │
1054
- // ├─ (A) tabRoot / loose artifacts (sec=="", type!="section")
1063
+ // ├─ (A) tabRoot / loose artifacts (sec=="", !STRUCTURAL_SEGMENT_TYPES)
1055
1064
  // │ → emit pages/links inline at their displaySortOrder
1056
1065
  // │
1057
1066
  // ├─ (B) the root section itself (sec=="", type=="section")
@@ -1080,8 +1089,10 @@ function buildSidebarRootChildren(ctx, scopeSegs, scopePrefix, changelogScopePre
1080
1089
  if (type === "tabRoot" && metaBool(s.seg.metadata, "landingPage") === true) {
1081
1090
  continue;
1082
1091
  }
1083
- // (A) Loose artifacts: tabRoot or non-section segments at section path "".
1084
- if (type === "tabRoot" || (sec === "" && type !== "section")) {
1092
+ // (A) Loose artifacts: tabRoot or non-structural segments at section path "".
1093
+ // Structural types need their own node builders in (B)/(C) even when
1094
+ // their section path is "" (which happens with skip-slug: true).
1095
+ if (type === "tabRoot" || (sec === "" && !STRUCTURAL_SEGMENT_TYPES.has(type ?? ""))) {
1085
1096
  for (const r of s.nav) {
1086
1097
  const node = artifactToNode(ctx, r);
1087
1098
  if (node != null) {
@@ -1101,12 +1112,16 @@ function buildSidebarRootChildren(ctx, scopeSegs, scopePrefix, changelogScopePre
1101
1112
  // adopted by a root section (B).
1102
1113
  const parent = parentSectionPath(sec);
1103
1114
  const isRootLevel = parent === "" || (!sectionPaths.has(parent) && nearestExistingAncestor(sec, sectionPaths) === "");
1104
- if (isRootLevel && hasRootSection) {
1115
+ // Skip depth-0 sections already adopted by the root section wrapper (B),
1116
+ // but NOT structural types with sec="" (skip-slug). buildSectionTree
1117
+ // filters out sec="" segments (line 1249), so they wouldn't be adopted
1118
+ // and must be emitted here directly.
1119
+ if (isRootLevel && hasRootSection && sec !== "") {
1105
1120
  continue;
1106
1121
  }
1107
1122
  if (isRootLevel) {
1108
1123
  let node;
1109
- if (type === "apiReference" || type === "apiPackage") {
1124
+ if (API_NODE_SEGMENT_TYPES.has(type ?? "")) {
1110
1125
  node = apiReferenceNode(ctx, s, scopeSegs, scopePrefix);
1111
1126
  }
1112
1127
  else if (type === "changelog") {
@@ -1223,7 +1238,7 @@ export function buildFullRootFromSegments(options) {
1223
1238
  // but guard here too.
1224
1239
  .filter((seg) => {
1225
1240
  const t = metaStr(seg.metadata, "type");
1226
- return t !== "files" && t !== "redirects";
1241
+ return !INFRA_SEGMENT_TYPES.has(t ?? "");
1227
1242
  })
1228
1243
  .map((seg) => ({ seg, nav: navBySegment.get(seg.segmentHash) ?? [] }));
1229
1244
  const rootSlug = asSlug(sourceRootSlug ?? basePath);
@@ -1398,22 +1413,36 @@ function buildSidebarRootWithVariants(ctx, scopeSegs, scopePrefix, changelogScop
1398
1413
  if (variants.length <= 1) {
1399
1414
  return buildSidebarRoot(ctx, scopeSegs, scopePrefix, changelogScopePrefix);
1400
1415
  }
1416
+ const sharedSegs = scopeSegs.filter((s) => s.seg.variant == null);
1401
1417
  const variantedNode = buildVariantedNode(ctx, variants, scopeSegs, scopePrefix);
1418
+ const sharedChildren = sharedSegs.length > 0 ? buildSidebarRootChildren(ctx, sharedSegs, scopePrefix, changelogScopePrefix) : [];
1402
1419
  const first = scopeSegs[0];
1403
1420
  return {
1404
1421
  type: "sidebarRoot",
1405
1422
  id: ctx.nodeId(`sidebar:${first != null ? scopeKey(first.seg) : "root"}`),
1406
1423
  collapsed: undefined,
1407
- children: [variantedNode]
1424
+ children: [...sharedChildren, variantedNode]
1408
1425
  };
1409
1426
  }
1410
1427
  function buildTabbedOrSidebar(ctx, scopeSegs, tabsPresent, scopePrefix) {
1411
1428
  if (!tabsPresent) {
1412
- // When no tabs exist but variants do, emit a VariantedNode directly
1413
- // so each variant gets its own sidebar scope.
1429
+ // When no tabs exist but variants do, wrap variant-scoped segments
1430
+ // in a VariantedNode and include non-variant segments alongside it.
1414
1431
  const variants = uniqueDetails(scopeSegs, "variant");
1415
1432
  if (variants.length > 1) {
1416
- return buildVariantedNode(ctx, variants, scopeSegs, scopePrefix);
1433
+ const sharedSegs = scopeSegs.filter((s) => s.seg.variant == null);
1434
+ const variantedNode = buildVariantedNode(ctx, variants, scopeSegs, scopePrefix);
1435
+ if (sharedSegs.length > 0) {
1436
+ const sharedChildren = buildSidebarRootChildren(ctx, sharedSegs, scopePrefix);
1437
+ const first = scopeSegs[0];
1438
+ return {
1439
+ type: "sidebarRoot",
1440
+ id: ctx.nodeId(`sidebar:${first != null ? scopeKey(first.seg) : "root"}`),
1441
+ collapsed: undefined,
1442
+ children: [...sharedChildren, variantedNode]
1443
+ };
1444
+ }
1445
+ return variantedNode;
1417
1446
  }
1418
1447
  return buildSidebarRoot(ctx, scopeSegs, scopePrefix);
1419
1448
  }