@fern-api/fdr-sdk 1.2.42-304ea6b285 → 1.2.42-54880bfeac
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.
- package/dist/js/client/FdrClient.js +1 -0
- package/dist/js/client/FdrClient.js.map +1 -1
- package/dist/js/client/FdrClient.mjs +1 -0
- package/dist/js/client/FdrClient.mjs.map +1 -1
- package/dist/js/index.js +1 -0
- package/dist/js/index.js.map +1 -1
- package/dist/js/index.mjs +1 -0
- package/dist/js/index.mjs.map +1 -1
- package/dist/js/navigation/ledger-root-builder.js +58 -4
- package/dist/js/navigation/ledger-root-builder.js.map +1 -1
- package/dist/js/navigation/ledger-root-builder.mjs +58 -4
- package/dist/js/navigation/ledger-root-builder.mjs.map +1 -1
- package/dist/js/orpc-client.js +1 -0
- package/dist/js/orpc-client.js.map +1 -1
- package/dist/js/orpc-client.mjs +1 -0
- package/dist/js/orpc-client.mjs.map +1 -1
- package/dist/navigation/__test__/ledger-root-builder.crossProductDedup.test.d.ts +2 -0
- package/dist/navigation/__test__/ledger-root-builder.crossProductDedup.test.d.ts.map +1 -0
- package/dist/navigation/__test__/ledger-root-builder.crossProductDedup.test.js +267 -0
- package/dist/navigation/__test__/ledger-root-builder.crossProductDedup.test.js.map +1 -0
- package/dist/navigation/__test__/ledger-root-builder.sidebarDepth.test.d.ts +2 -0
- package/dist/navigation/__test__/ledger-root-builder.sidebarDepth.test.d.ts.map +1 -0
- package/dist/navigation/__test__/ledger-root-builder.sidebarDepth.test.js +273 -0
- package/dist/navigation/__test__/ledger-root-builder.sidebarDepth.test.js.map +1 -0
- package/dist/navigation/__test__/ledger-root-builder.skipSlugGroupOrdering.test.d.ts +2 -0
- package/dist/navigation/__test__/ledger-root-builder.skipSlugGroupOrdering.test.d.ts.map +1 -0
- package/dist/navigation/__test__/ledger-root-builder.skipSlugGroupOrdering.test.js +234 -0
- package/dist/navigation/__test__/ledger-root-builder.skipSlugGroupOrdering.test.js.map +1 -0
- package/dist/navigation/__test__/ledger-root-builder.skipSlugSiblingSection.test.js +105 -1
- package/dist/navigation/__test__/ledger-root-builder.skipSlugSiblingSection.test.js.map +1 -1
- package/dist/navigation/ledger-root-builder.d.ts.map +1 -1
- package/dist/navigation/ledger-root-builder.js +108 -12
- package/dist/navigation/ledger-root-builder.js.map +1 -1
- package/dist/orpc-client/docs-ledger/contract.d.ts +9 -0
- package/dist/orpc-client/docs-ledger/contract.d.ts.map +1 -1
- package/dist/orpc-client/docs-ledger/contract.js +1 -0
- package/dist/orpc-client/docs-ledger/contract.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/navigation/__test__/ledger-root-builder.crossProductDedup.test.d.ts +2 -0
- package/dist/types/navigation/__test__/ledger-root-builder.crossProductDedup.test.d.ts.map +1 -0
- package/dist/types/navigation/__test__/ledger-root-builder.sidebarDepth.test.d.ts +2 -0
- package/dist/types/navigation/__test__/ledger-root-builder.sidebarDepth.test.d.ts.map +1 -0
- package/dist/types/navigation/__test__/ledger-root-builder.skipSlugGroupOrdering.test.d.ts +2 -0
- package/dist/types/navigation/__test__/ledger-root-builder.skipSlugGroupOrdering.test.d.ts.map +1 -0
- package/dist/types/navigation/ledger-root-builder.d.ts.map +1 -1
- package/dist/types/orpc-client/docs-ledger/contract.d.ts +9 -0
- package/dist/types/orpc-client/docs-ledger/contract.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ledger-root-builder.crossProductDedup.test.d.ts","sourceRoot":"","sources":["../../../src/navigation/__test__/ledger-root-builder.crossProductDedup.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import * as FernNavigation from "../index.js";
|
|
3
|
+
import { buildFullRootFromSegments } from "../ledger-root-builder.js";
|
|
4
|
+
function detail(opts) {
|
|
5
|
+
return {
|
|
6
|
+
id: opts.id,
|
|
7
|
+
displayName: opts.name,
|
|
8
|
+
icon: null,
|
|
9
|
+
sortOrder: 0,
|
|
10
|
+
hidden: false,
|
|
11
|
+
viewers: [],
|
|
12
|
+
orphaned: false,
|
|
13
|
+
featureFlags: [],
|
|
14
|
+
metadata: { slug: opts.slug, default: opts.isDefault ?? false, pointsTo: opts.pointsTo }
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function seg(opts) {
|
|
18
|
+
return {
|
|
19
|
+
segmentId: opts.segmentHash,
|
|
20
|
+
segmentHash: opts.segmentHash,
|
|
21
|
+
section: opts.section ?? "",
|
|
22
|
+
locale: "en",
|
|
23
|
+
sortOrder: 0,
|
|
24
|
+
hidden: false,
|
|
25
|
+
metadata: opts.metadata ?? { type: "section" },
|
|
26
|
+
product: opts.product,
|
|
27
|
+
version: null,
|
|
28
|
+
variant: null,
|
|
29
|
+
tab: null
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function mdRoute(opts) {
|
|
33
|
+
return {
|
|
34
|
+
type: "markdown",
|
|
35
|
+
fullPath: opts.fullPath,
|
|
36
|
+
hidden: false,
|
|
37
|
+
metadata: { title: opts.title, pageId: opts.pageId }
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function epRoute(opts) {
|
|
41
|
+
return {
|
|
42
|
+
type: "endpoint-pair",
|
|
43
|
+
fullPath: opts.fullPath,
|
|
44
|
+
stream: null,
|
|
45
|
+
hidden: false,
|
|
46
|
+
metadata: {
|
|
47
|
+
title: opts.title,
|
|
48
|
+
endpointId: opts.endpointId,
|
|
49
|
+
method: opts.method,
|
|
50
|
+
apiDefinitionId: opts.apiDefinitionId,
|
|
51
|
+
isResponseStream: false
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function findCanonicalSlug(root, slug) {
|
|
56
|
+
const result = FernNavigation.utils.findNode(root, FernNavigation.Slug(slug));
|
|
57
|
+
if (result.type === "found") {
|
|
58
|
+
return result.node.canonicalSlug;
|
|
59
|
+
}
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
describe("buildFullRootFromSegments - cross-product canonical slug deduplication", () => {
|
|
63
|
+
it("deduplicates shared pages across products via pageId", () => {
|
|
64
|
+
const defaultProduct = detail({
|
|
65
|
+
id: "p-hris",
|
|
66
|
+
name: "HRIS",
|
|
67
|
+
slug: "hris",
|
|
68
|
+
isDefault: true,
|
|
69
|
+
pointsTo: "hris/authentication"
|
|
70
|
+
});
|
|
71
|
+
const nonDefaultProduct = detail({
|
|
72
|
+
id: "p-accounting",
|
|
73
|
+
name: "Accounting",
|
|
74
|
+
slug: "accounting",
|
|
75
|
+
pointsTo: "accounting/authentication"
|
|
76
|
+
});
|
|
77
|
+
const root = buildFullRootFromSegments({
|
|
78
|
+
basePath: "",
|
|
79
|
+
title: "Merge",
|
|
80
|
+
segments: [
|
|
81
|
+
seg({ segmentHash: "seg-hris", product: defaultProduct }),
|
|
82
|
+
seg({ segmentHash: "seg-accounting", product: nonDefaultProduct })
|
|
83
|
+
],
|
|
84
|
+
navBySegment: new Map([
|
|
85
|
+
[
|
|
86
|
+
"seg-hris",
|
|
87
|
+
[mdRoute({ fullPath: "hris/authentication", title: "Authentication", pageId: "pg-auth" })]
|
|
88
|
+
],
|
|
89
|
+
[
|
|
90
|
+
"seg-accounting",
|
|
91
|
+
[
|
|
92
|
+
mdRoute({ fullPath: "accounting/authentication", title: "Authentication", pageId: "pg-auth" })
|
|
93
|
+
]
|
|
94
|
+
]
|
|
95
|
+
])
|
|
96
|
+
});
|
|
97
|
+
// Default product's page: no cross-product canonicalSlug
|
|
98
|
+
expect(findCanonicalSlug(root, "hris/authentication")).toBeUndefined();
|
|
99
|
+
// Non-default product's shared page points to the default
|
|
100
|
+
expect(findCanonicalSlug(root, "accounting/authentication")).toBe("hris/authentication");
|
|
101
|
+
});
|
|
102
|
+
it("does NOT deduplicate pages with different pageIds", () => {
|
|
103
|
+
const defaultProduct = detail({
|
|
104
|
+
id: "p-hris",
|
|
105
|
+
name: "HRIS",
|
|
106
|
+
slug: "hris",
|
|
107
|
+
isDefault: true,
|
|
108
|
+
pointsTo: "hris/guide"
|
|
109
|
+
});
|
|
110
|
+
const nonDefaultProduct = detail({
|
|
111
|
+
id: "p-accounting",
|
|
112
|
+
name: "Accounting",
|
|
113
|
+
slug: "accounting",
|
|
114
|
+
pointsTo: "accounting/guide"
|
|
115
|
+
});
|
|
116
|
+
const root = buildFullRootFromSegments({
|
|
117
|
+
basePath: "",
|
|
118
|
+
title: "Merge",
|
|
119
|
+
segments: [
|
|
120
|
+
seg({ segmentHash: "seg-hris", product: defaultProduct }),
|
|
121
|
+
seg({ segmentHash: "seg-accounting", product: nonDefaultProduct })
|
|
122
|
+
],
|
|
123
|
+
navBySegment: new Map([
|
|
124
|
+
["seg-hris", [mdRoute({ fullPath: "hris/guide", title: "Guide", pageId: "pg-hris-guide" })]],
|
|
125
|
+
[
|
|
126
|
+
"seg-accounting",
|
|
127
|
+
[mdRoute({ fullPath: "accounting/guide", title: "Guide", pageId: "pg-acct-guide" })]
|
|
128
|
+
]
|
|
129
|
+
])
|
|
130
|
+
});
|
|
131
|
+
expect(findCanonicalSlug(root, "hris/guide")).toBeUndefined();
|
|
132
|
+
expect(findCanonicalSlug(root, "accounting/guide")).toBeUndefined();
|
|
133
|
+
});
|
|
134
|
+
it("does NOT deduplicate API endpoint nodes across products", () => {
|
|
135
|
+
const defaultProduct = detail({
|
|
136
|
+
id: "p-hris",
|
|
137
|
+
name: "HRIS",
|
|
138
|
+
slug: "hris",
|
|
139
|
+
isDefault: true,
|
|
140
|
+
pointsTo: "hris/list-employees"
|
|
141
|
+
});
|
|
142
|
+
const nonDefaultProduct = detail({
|
|
143
|
+
id: "p-accounting",
|
|
144
|
+
name: "Accounting",
|
|
145
|
+
slug: "accounting",
|
|
146
|
+
pointsTo: "accounting/list-accounts"
|
|
147
|
+
});
|
|
148
|
+
const root = buildFullRootFromSegments({
|
|
149
|
+
basePath: "",
|
|
150
|
+
title: "Merge",
|
|
151
|
+
segments: [
|
|
152
|
+
seg({
|
|
153
|
+
segmentHash: "seg-hris-api",
|
|
154
|
+
product: defaultProduct,
|
|
155
|
+
metadata: { type: "apiReference", apiDefinitionId: "api-hris" }
|
|
156
|
+
}),
|
|
157
|
+
seg({
|
|
158
|
+
segmentHash: "seg-acct-api",
|
|
159
|
+
product: nonDefaultProduct,
|
|
160
|
+
metadata: { type: "apiReference", apiDefinitionId: "api-acct" }
|
|
161
|
+
})
|
|
162
|
+
],
|
|
163
|
+
navBySegment: new Map([
|
|
164
|
+
[
|
|
165
|
+
"seg-hris-api",
|
|
166
|
+
[
|
|
167
|
+
epRoute({
|
|
168
|
+
fullPath: "hris/list-employees",
|
|
169
|
+
title: "List Employees",
|
|
170
|
+
endpointId: "list-employees",
|
|
171
|
+
method: "GET",
|
|
172
|
+
apiDefinitionId: "api-hris"
|
|
173
|
+
})
|
|
174
|
+
]
|
|
175
|
+
],
|
|
176
|
+
[
|
|
177
|
+
"seg-acct-api",
|
|
178
|
+
[
|
|
179
|
+
epRoute({
|
|
180
|
+
fullPath: "accounting/list-accounts",
|
|
181
|
+
title: "List Accounts",
|
|
182
|
+
endpointId: "list-accounts",
|
|
183
|
+
method: "GET",
|
|
184
|
+
apiDefinitionId: "api-acct"
|
|
185
|
+
})
|
|
186
|
+
]
|
|
187
|
+
]
|
|
188
|
+
])
|
|
189
|
+
});
|
|
190
|
+
expect(findCanonicalSlug(root, "hris/list-employees")).toBeUndefined();
|
|
191
|
+
expect(findCanonicalSlug(root, "accounting/list-accounts")).toBeUndefined();
|
|
192
|
+
});
|
|
193
|
+
it("deduplicates shared pages across many products (Merge-like fan-out)", () => {
|
|
194
|
+
const productNames = ["hris", "accounting", "ats", "crm"];
|
|
195
|
+
const sharedPageId = "pg-rate-limits";
|
|
196
|
+
const products = productNames.map((name, i) => detail({
|
|
197
|
+
id: `p-${name}`,
|
|
198
|
+
name,
|
|
199
|
+
slug: name,
|
|
200
|
+
isDefault: i === 0,
|
|
201
|
+
pointsTo: `${name}/rate-limits`
|
|
202
|
+
}));
|
|
203
|
+
const segments = productNames.map((name, i) => seg({ segmentHash: `seg-${name}`, product: products[i] }));
|
|
204
|
+
const routes = productNames.map((name) => mdRoute({ fullPath: `${name}/rate-limits`, title: "Rate Limits", pageId: sharedPageId }));
|
|
205
|
+
const root = buildFullRootFromSegments({
|
|
206
|
+
basePath: "",
|
|
207
|
+
title: "Merge",
|
|
208
|
+
segments: segments,
|
|
209
|
+
navBySegment: new Map(productNames.map((name, i) => [`seg-${name}`, [routes[i]]]))
|
|
210
|
+
});
|
|
211
|
+
// Default product (hris): no canonicalSlug
|
|
212
|
+
expect(findCanonicalSlug(root, "hris/rate-limits")).toBeUndefined();
|
|
213
|
+
// All non-default products' shared pages point to the default
|
|
214
|
+
for (const name of productNames.slice(1)) {
|
|
215
|
+
expect(findCanonicalSlug(root, `${name}/rate-limits`)).toBe("hris/rate-limits");
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
it("leaves product-specific pages alone when shared pages are deduped", () => {
|
|
219
|
+
const defaultProduct = detail({
|
|
220
|
+
id: "p-hris",
|
|
221
|
+
name: "HRIS",
|
|
222
|
+
slug: "hris",
|
|
223
|
+
isDefault: true,
|
|
224
|
+
pointsTo: "hris/authentication"
|
|
225
|
+
});
|
|
226
|
+
const nonDefaultProduct = detail({
|
|
227
|
+
id: "p-accounting",
|
|
228
|
+
name: "Accounting",
|
|
229
|
+
slug: "accounting",
|
|
230
|
+
pointsTo: "accounting/authentication"
|
|
231
|
+
});
|
|
232
|
+
const root = buildFullRootFromSegments({
|
|
233
|
+
basePath: "",
|
|
234
|
+
title: "Merge",
|
|
235
|
+
segments: [
|
|
236
|
+
seg({ segmentHash: "seg-hris", product: defaultProduct }),
|
|
237
|
+
seg({ segmentHash: "seg-accounting", product: nonDefaultProduct })
|
|
238
|
+
],
|
|
239
|
+
navBySegment: new Map([
|
|
240
|
+
[
|
|
241
|
+
"seg-hris",
|
|
242
|
+
[
|
|
243
|
+
mdRoute({ fullPath: "hris/authentication", title: "Authentication", pageId: "pg-auth" }),
|
|
244
|
+
mdRoute({ fullPath: "hris/employee-guide", title: "Employee Guide", pageId: "pg-emp-guide" })
|
|
245
|
+
]
|
|
246
|
+
],
|
|
247
|
+
[
|
|
248
|
+
"seg-accounting",
|
|
249
|
+
[
|
|
250
|
+
mdRoute({ fullPath: "accounting/authentication", title: "Authentication", pageId: "pg-auth" }),
|
|
251
|
+
mdRoute({
|
|
252
|
+
fullPath: "accounting/invoice-guide",
|
|
253
|
+
title: "Invoice Guide",
|
|
254
|
+
pageId: "pg-inv-guide"
|
|
255
|
+
})
|
|
256
|
+
]
|
|
257
|
+
]
|
|
258
|
+
])
|
|
259
|
+
});
|
|
260
|
+
// Shared page in non-default product is deduped
|
|
261
|
+
expect(findCanonicalSlug(root, "accounting/authentication")).toBe("hris/authentication");
|
|
262
|
+
// Product-specific pages are untouched
|
|
263
|
+
expect(findCanonicalSlug(root, "hris/employee-guide")).toBeUndefined();
|
|
264
|
+
expect(findCanonicalSlug(root, "accounting/invoice-guide")).toBeUndefined();
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
//# sourceMappingURL=ledger-root-builder.crossProductDedup.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ledger-root-builder.crossProductDedup.test.js","sourceRoot":"","sources":["../../../src/navigation/__test__/ledger-root-builder.crossProductDedup.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ledger-root-builder.sidebarDepth.test.d.ts","sourceRoot":"","sources":["../../../src/navigation/__test__/ledger-root-builder.sidebarDepth.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import * as FernNavigation from "../index.js";
|
|
3
|
+
import { buildFullRootFromSegments } from "../ledger-root-builder.js";
|
|
4
|
+
import { createBreadcrumb } from "../utils/createBreadcrumb.js";
|
|
5
|
+
/**
|
|
6
|
+
* Tests for sidebarDepth-based root section identification.
|
|
7
|
+
*
|
|
8
|
+
* V1 configs define flat root sections (e.g. "Users", "Policies",
|
|
9
|
+
* "Verification") that the decomposer marks as sidebarDepth=0. Without
|
|
10
|
+
* this marker, the builder's slug-derived hierarchy would infer that
|
|
11
|
+
* "users/verification" is a child of "users", creating extra ancestor
|
|
12
|
+
* levels in the breadcrumb.
|
|
13
|
+
*/
|
|
14
|
+
function pageRoute(opts) {
|
|
15
|
+
return {
|
|
16
|
+
type: "markdown",
|
|
17
|
+
fullPath: opts.fullPath,
|
|
18
|
+
hidden: false,
|
|
19
|
+
metadata: { title: opts.title, pageId: `pg-${opts.title.toLowerCase().replace(/\s+/g, "-")}` },
|
|
20
|
+
...(opts.displaySortOrder != null ? { displaySortOrder: opts.displaySortOrder } : {})
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function segment(opts) {
|
|
24
|
+
return {
|
|
25
|
+
segmentId: opts.segmentHash,
|
|
26
|
+
segmentHash: opts.segmentHash,
|
|
27
|
+
section: opts.section,
|
|
28
|
+
locale: "en",
|
|
29
|
+
sortOrder: opts.sortOrder,
|
|
30
|
+
hidden: false,
|
|
31
|
+
metadata: opts.metadata,
|
|
32
|
+
product: null,
|
|
33
|
+
version: null,
|
|
34
|
+
variant: null,
|
|
35
|
+
tab: null
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/** Flatten sidebar-root children (unwrapping sidebarGroups) to section info. */
|
|
39
|
+
function rootSections(root) {
|
|
40
|
+
const unversioned = root.child;
|
|
41
|
+
const sidebar = unversioned.child;
|
|
42
|
+
const result = [];
|
|
43
|
+
for (const child of sidebar.children) {
|
|
44
|
+
const items = child.type === "sidebarGroup"
|
|
45
|
+
? child.children
|
|
46
|
+
: [child];
|
|
47
|
+
for (const item of items) {
|
|
48
|
+
if (item.type === "section") {
|
|
49
|
+
const childTitles = (item.children ?? []).map((c) => c.title ?? "");
|
|
50
|
+
result.push({ title: item.title ?? "", childTitles });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
/** Count all section nodes in the tree via DFS. */
|
|
57
|
+
function countSectionNodes(root) {
|
|
58
|
+
let count = 0;
|
|
59
|
+
FernNavigation.traverseDF(root, (node) => {
|
|
60
|
+
if (node.type === "section") {
|
|
61
|
+
count++;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
return count;
|
|
65
|
+
}
|
|
66
|
+
/** Find a page node by slug and return its breadcrumb. */
|
|
67
|
+
function breadcrumbForSlug(root, slug) {
|
|
68
|
+
const collector = FernNavigation.NodeCollector.collect(root);
|
|
69
|
+
const found = collector.getSlugMapWithParents().get(FernNavigation.Slug(slug));
|
|
70
|
+
if (found == null) {
|
|
71
|
+
throw new Error(`Slug "${slug}" not found in tree`);
|
|
72
|
+
}
|
|
73
|
+
return createBreadcrumb(found.parents);
|
|
74
|
+
}
|
|
75
|
+
// ── Fix #1: sidebarDepth prevents false root section nesting ─────────────────
|
|
76
|
+
describe("buildFullRootFromSegments — sidebarDepth prevents false nesting", () => {
|
|
77
|
+
/**
|
|
78
|
+
* Reproduces the structure that causes extra breadcrumb links:
|
|
79
|
+
*
|
|
80
|
+
* V1 config (flat):
|
|
81
|
+
* Introduction (skipUrlSlug → sec="")
|
|
82
|
+
* Users (sec="users", sidebarDepth=0)
|
|
83
|
+
* Policies (sec="users/policies", sidebarDepth=0)
|
|
84
|
+
* Verification (sec="users/verification", sidebarDepth=0)
|
|
85
|
+
*
|
|
86
|
+
* Without sidebarDepth, the builder would nest Policies and Verification
|
|
87
|
+
* under Users (since parentSectionPath("users/policies") === "users"),
|
|
88
|
+
* creating extra breadcrumb ancestors.
|
|
89
|
+
*
|
|
90
|
+
* With sidebarDepth=0, they remain flat root peers.
|
|
91
|
+
*/
|
|
92
|
+
function buildFlatRoot() {
|
|
93
|
+
return buildFullRootFromSegments({
|
|
94
|
+
basePath: "docs",
|
|
95
|
+
title: "Test",
|
|
96
|
+
segments: [
|
|
97
|
+
segment({
|
|
98
|
+
segmentHash: "seg-root",
|
|
99
|
+
section: "",
|
|
100
|
+
sortOrder: 0,
|
|
101
|
+
metadata: { type: "tabRoot" }
|
|
102
|
+
}),
|
|
103
|
+
// Root section wrapper (Introduction, skipUrlSlug → sec="")
|
|
104
|
+
segment({
|
|
105
|
+
segmentHash: "seg-intro",
|
|
106
|
+
section: "",
|
|
107
|
+
sortOrder: 1,
|
|
108
|
+
metadata: {
|
|
109
|
+
type: "section",
|
|
110
|
+
title: "Introduction",
|
|
111
|
+
sidebarDepth: 0,
|
|
112
|
+
childIndex: 0,
|
|
113
|
+
pointsTo: "docs/guides/e-wallet"
|
|
114
|
+
}
|
|
115
|
+
}),
|
|
116
|
+
// Users — depth 0, should be root peer
|
|
117
|
+
segment({
|
|
118
|
+
segmentHash: "seg-users",
|
|
119
|
+
section: "users",
|
|
120
|
+
sortOrder: 2,
|
|
121
|
+
metadata: {
|
|
122
|
+
type: "section",
|
|
123
|
+
title: "Users",
|
|
124
|
+
sidebarDepth: 0,
|
|
125
|
+
childIndex: 1,
|
|
126
|
+
pointsTo: "docs/guides/users/types"
|
|
127
|
+
}
|
|
128
|
+
}),
|
|
129
|
+
// Policies — depth 0, path is "users/policies" but should NOT
|
|
130
|
+
// be nested under Users
|
|
131
|
+
segment({
|
|
132
|
+
segmentHash: "seg-policies",
|
|
133
|
+
section: "users/policies",
|
|
134
|
+
sortOrder: 3,
|
|
135
|
+
metadata: {
|
|
136
|
+
type: "section",
|
|
137
|
+
title: "Policies",
|
|
138
|
+
sidebarDepth: 0,
|
|
139
|
+
childIndex: 2,
|
|
140
|
+
pointsTo: "docs/guides/users/blocked-users"
|
|
141
|
+
}
|
|
142
|
+
}),
|
|
143
|
+
// Verification — depth 0, path is "users/verification" but
|
|
144
|
+
// should NOT be nested under Users
|
|
145
|
+
segment({
|
|
146
|
+
segmentHash: "seg-verification",
|
|
147
|
+
section: "users/verification",
|
|
148
|
+
sortOrder: 4,
|
|
149
|
+
metadata: {
|
|
150
|
+
type: "section",
|
|
151
|
+
title: "User KYC/KYB verification",
|
|
152
|
+
sidebarDepth: 0,
|
|
153
|
+
childIndex: 3
|
|
154
|
+
}
|
|
155
|
+
}),
|
|
156
|
+
// Nested child under Verification (depth 1)
|
|
157
|
+
segment({
|
|
158
|
+
segmentHash: "seg-hosted",
|
|
159
|
+
section: "users/verification/hosted",
|
|
160
|
+
sortOrder: 5,
|
|
161
|
+
metadata: {
|
|
162
|
+
type: "section",
|
|
163
|
+
title: "Flows per user type",
|
|
164
|
+
sidebarDepth: 1,
|
|
165
|
+
childIndex: 0,
|
|
166
|
+
pointsTo: "docs/guides/users/verification/hosted/natural"
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
],
|
|
170
|
+
navBySegment: new Map([
|
|
171
|
+
[
|
|
172
|
+
"seg-root",
|
|
173
|
+
[pageRoute({ fullPath: "docs/guides/e-wallet", title: "E-wallet system", displaySortOrder: 0 })]
|
|
174
|
+
],
|
|
175
|
+
["seg-intro", []],
|
|
176
|
+
["seg-users", [pageRoute({ fullPath: "docs/guides/users/types", title: "User types" })]],
|
|
177
|
+
["seg-policies", [pageRoute({ fullPath: "docs/guides/users/blocked-users", title: "Blocked users" })]],
|
|
178
|
+
[
|
|
179
|
+
"seg-verification",
|
|
180
|
+
[pageRoute({ fullPath: "docs/guides/users/verification", title: "Verification overview" })]
|
|
181
|
+
],
|
|
182
|
+
[
|
|
183
|
+
"seg-hosted",
|
|
184
|
+
[pageRoute({ fullPath: "docs/guides/users/verification/hosted/natural", title: "Natural persons" })]
|
|
185
|
+
]
|
|
186
|
+
])
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
it("preserves flat root sections instead of nesting by slug hierarchy", () => {
|
|
190
|
+
const root = buildFlatRoot();
|
|
191
|
+
const sections = rootSections(root);
|
|
192
|
+
const titles = sections.map((s) => s.title);
|
|
193
|
+
// All depth-0 sections should appear as root peers
|
|
194
|
+
expect(titles).toContain("Users");
|
|
195
|
+
expect(titles).toContain("Policies");
|
|
196
|
+
expect(titles).toContain("User KYC/KYB verification");
|
|
197
|
+
});
|
|
198
|
+
it("does not create extra breadcrumb ancestors for flat sections", () => {
|
|
199
|
+
const root = buildFlatRoot();
|
|
200
|
+
// The verification section's slug is docs/users/verification.
|
|
201
|
+
// Its page lives at docs/docs/guides/users/verification (basePath + fullPath).
|
|
202
|
+
const bc = breadcrumbForSlug(root, "docs/users/verification");
|
|
203
|
+
// With flat root sections, the verification page should have at most
|
|
204
|
+
// one section ancestor, not extra "Users" + "Policies" ancestors.
|
|
205
|
+
const linkedEntries = bc.filter((item) => item.pointsTo != null);
|
|
206
|
+
expect(linkedEntries.length).toBeLessThanOrEqual(1);
|
|
207
|
+
// Total breadcrumb entries should be 1 (just the verification section)
|
|
208
|
+
// not 3 (Introduction + Policies + Verification)
|
|
209
|
+
expect(bc.length).toBeLessThanOrEqual(1);
|
|
210
|
+
});
|
|
211
|
+
it("still nests depth>0 children under their parent section", () => {
|
|
212
|
+
const root = buildFlatRoot();
|
|
213
|
+
// "Flows per user type" (depth 1, sec="users/verification/hosted")
|
|
214
|
+
// should be nested under "User KYC/KYB verification" (depth 0,
|
|
215
|
+
// sec="users/verification")
|
|
216
|
+
const sections = rootSections(root);
|
|
217
|
+
const verification = sections.find((s) => s.title === "User KYC/KYB verification");
|
|
218
|
+
expect(verification).toBeDefined();
|
|
219
|
+
expect(verification.childTitles).toContain("Flows per user type");
|
|
220
|
+
});
|
|
221
|
+
it("does not produce duplicate section nodes", () => {
|
|
222
|
+
const root = buildFlatRoot();
|
|
223
|
+
const totalSections = countSectionNodes(root);
|
|
224
|
+
// 5 unique sections: Introduction, Users, Policies,
|
|
225
|
+
// User KYC/KYB verification, Flows per user type
|
|
226
|
+
expect(totalSections).toBe(5);
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
// ── Backward compatibility: segments without sidebarDepth ────────────────────
|
|
230
|
+
describe("buildFullRootFromSegments — backward compatibility without sidebarDepth", () => {
|
|
231
|
+
it("falls back to path-based hierarchy when sidebarDepth is absent", () => {
|
|
232
|
+
// Old data without sidebarDepth: "users/verification" is correctly
|
|
233
|
+
// nested under "users" via slug hierarchy.
|
|
234
|
+
const root = buildFullRootFromSegments({
|
|
235
|
+
basePath: "docs",
|
|
236
|
+
title: "Test",
|
|
237
|
+
segments: [
|
|
238
|
+
segment({
|
|
239
|
+
segmentHash: "seg-root",
|
|
240
|
+
section: "",
|
|
241
|
+
sortOrder: 0,
|
|
242
|
+
metadata: { type: "tabRoot" }
|
|
243
|
+
}),
|
|
244
|
+
segment({
|
|
245
|
+
segmentHash: "seg-users",
|
|
246
|
+
section: "users",
|
|
247
|
+
sortOrder: 1,
|
|
248
|
+
metadata: { type: "section", title: "Users", childIndex: 0 }
|
|
249
|
+
}),
|
|
250
|
+
segment({
|
|
251
|
+
segmentHash: "seg-verification",
|
|
252
|
+
section: "users/verification",
|
|
253
|
+
sortOrder: 2,
|
|
254
|
+
metadata: { type: "section", title: "Verification", childIndex: 0 }
|
|
255
|
+
})
|
|
256
|
+
],
|
|
257
|
+
navBySegment: new Map([
|
|
258
|
+
["seg-root", [pageRoute({ fullPath: "docs/overview", title: "Overview", displaySortOrder: 0 })]],
|
|
259
|
+
["seg-users", [pageRoute({ fullPath: "docs/users/types", title: "User types" })]],
|
|
260
|
+
[
|
|
261
|
+
"seg-verification",
|
|
262
|
+
[pageRoute({ fullPath: "docs/users/verification/guide", title: "Verification guide" })]
|
|
263
|
+
]
|
|
264
|
+
])
|
|
265
|
+
});
|
|
266
|
+
// Without sidebarDepth, Verification nests under Users (slug-derived)
|
|
267
|
+
const sections = rootSections(root);
|
|
268
|
+
const users = sections.find((s) => s.title === "Users");
|
|
269
|
+
expect(users).toBeDefined();
|
|
270
|
+
expect(users.childTitles).toContain("Verification");
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
//# sourceMappingURL=ledger-root-builder.sidebarDepth.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ledger-root-builder.sidebarDepth.test.js","sourceRoot":"","sources":["../../../src/navigation/__test__/ledger-root-builder.sidebarDepth.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ledger-root-builder.skipSlugGroupOrdering.test.d.ts","sourceRoot":"","sources":["../../../src/navigation/__test__/ledger-root-builder.skipSlugGroupOrdering.test.ts"],"names":[],"mappings":""}
|