Skip to content

Commit 514d8fe

Browse files
committed
[fix] misc bug fixes, code quality improvements, remove some dead code
1 parent c88e16b commit 514d8fe

File tree

25 files changed

+809
-606
lines changed

25 files changed

+809
-606
lines changed

packages/commons/docs-loader/src/editable-docs-loader.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,20 @@ interface DocsYmlError {
114114
error: DocsYmlErrors;
115115
}
116116

117+
interface GetDocsYmlAndReferencesSuccess {
118+
type: "ok";
119+
result: Map<string, string>;
120+
}
121+
122+
export type GetDocsYmlAndReferencesResult = GetDocsYmlAndReferencesSuccess | DocsYmlError;
123+
117124
interface GetDocsYmlSuccess {
118125
type: "ok";
119-
result: string | Map<string, string>;
126+
result: string;
127+
metadata: {
128+
path: string;
129+
defaultBranch: string;
130+
};
120131
}
121132

122133
export type GetDocsYmlResult = GetDocsYmlSuccess | DocsYmlError;

packages/fern-dashboard/src/app/[orgName]/(visual-editor)/editor/[docsUrl]/[branch]/[...slug]/@sidebar/CreatePageButton.tsx

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
"use client";
22

33
import type { SerializableFoundNode } from "@fern-docs/components/navigation";
4-
import { useNavigation } from "@fern-docs/components/navigation";
5-
64
import { DashboardTooltip } from "@/components/editor/DashboardTooltip";
75
import { Icon } from "@/components/icon/Icon";
86
import { Button } from "@/components/ui/button";
97
import { useEditingDisabled } from "@/hooks/useEditingDisabled";
108
import { useGitPrInfo } from "@/providers/GitPRContext";
11-
import { UI_MESSAGES } from "@/utils/messages";
129

1310
import { CreateClientPage } from "./CreateClientPage";
1411

@@ -20,24 +17,17 @@ interface CreatePageButtonProps {
2017
export function CreatePageButton({ baseFoundNode }: CreatePageButtonProps) {
2118
const { prStatus } = useGitPrInfo();
2219
const isEditingDisabled = useEditingDisabled();
23-
const navigation = useNavigation();
24-
25-
// LIMITATION: Page creation is not supported for multi-product or multi-version docs
26-
// These docs have separate docs.yml files for each product/version, and we would need to
27-
// determine which specific file to modify. This is a complex operation that's not yet supported.
28-
const canEditNavigation = navigation.canDirectlyEditDocsYmlNavigation;
2920

30-
const tooltipContent = !canEditNavigation
31-
? UI_MESSAGES.NAVIGATION_EDITS_NOT_SUPPORTED_MULTI_DOCS_YML
32-
: isEditingDisabled && prStatus === "merged"
33-
? "Cannot create page - PR has already been merged"
34-
: isEditingDisabled && prStatus === "closed"
35-
? "Cannot create page - PR has been closed"
36-
: undefined;
21+
const tooltipContent =
22+
isEditingDisabled && prStatus === "merged"
23+
? "Cannot create page - PR has already been merged"
24+
: isEditingDisabled && prStatus === "closed"
25+
? "Cannot create page - PR has been closed"
26+
: undefined;
3727

3828
return (
3929
<DashboardTooltip content={tooltipContent}>
40-
<CreateClientPage baseFoundNode={baseFoundNode} disabled={isEditingDisabled || !canEditNavigation}>
30+
<CreateClientPage baseFoundNode={baseFoundNode} disabled={isEditingDisabled}>
4131
<Button
4232
className="mb-2 flex w-full items-center justify-center gap-2 self-stretch rounded-lg border border-dashed border-[var(--grayscale-a6)] p-2 text-sm text-[var(--grayscale-a11)] hover:bg-[var(--grayscale-a3)] hover:text-[var(--grayscale-a12)]"
4333
variant="ghost"

packages/fern-dashboard/src/app/[orgName]/(visual-editor)/editor/[docsUrl]/[branch]/layout.tsx

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,20 +62,17 @@ export default async function EditorLayout({
6262
const githubLoader = new GitHubLoader(githubUrl);
6363

6464
// Use the repo's default branch by passing preferDefaultBranch=true
65-
const docsYmlResult = await githubLoader.getDocsYml(
65+
const docsYmlAndReferences = await githubLoader.getDocsYmlAndReferences(
6666
sourceRepo.owner,
6767
sourceRepo.repo,
6868
docsUrl,
6969
branch, // fallback branch if default branch logic fails
7070
true // preferDefaultBranch = true
7171
);
72+
const latestDocsYmlAndReferences = docsYmlAndReferences.type === "ok" ? docsYmlAndReferences.result : null;
7273

73-
// Handle both string (single file) and Map (multi-file) results
74-
let initialDocsYmlContent: string | Map<string, string> | null = null;
75-
if (docsYmlResult.type === "ok") {
76-
initialDocsYmlContent = docsYmlResult.result;
77-
} else {
78-
console.error(docsYmlResult.error);
74+
if (docsYmlAndReferences.type !== "ok") {
75+
console.error(docsYmlAndReferences.error);
7976
}
8077

8178
return (
@@ -96,7 +93,7 @@ export default async function EditorLayout({
9693
branchName={branch}
9794
orgName={orgName}
9895
docsUrl={docsUrl}
99-
initialDocsYmlContent={initialDocsYmlContent}
96+
latestDocsYmlAndReferences={latestDocsYmlAndReferences}
10097
>
10198
<CurrentPageProvider>
10299
<ClientMDXProvider>

packages/fern-dashboard/src/app/services/dal/github/createBranchIfNotExists.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ export default async function createBranchIfNotExists(request: {
2626
error: string;
2727
}
2828
> {
29+
console.log("[debug] createBranchIfNotExists: Starting", { branch: request.branch, baseBranch: request.baseBranch });
2930
const session = await getCurrentSession();
3031
if (session == null) {
32+
console.log("[debug] createBranchIfNotExists: No session found");
3133
return { success: false, error: "No session found" };
3234
}
3335

@@ -68,13 +70,15 @@ export default async function createBranchIfNotExists(request: {
6870
});
6971

7072
// Branch exists, return success with existing branch data
73+
console.log("[debug] createBranchIfNotExists: Branch already exists", { branch: request.branch });
7174
return {
7275
success: true,
7376
baseSha: existingBranchResponse.data.object.sha,
7477
response: existingBranchResponse
7578
};
7679
} catch (branchCheckError: any) {
7780
// Branch doesn't exist (404), continue to create it
81+
console.log("[debug] createBranchIfNotExists: Branch doesn't exist, will create", { branch: request.branch, status: branchCheckError.status });
7882
if (branchCheckError.status !== 404) {
7983
throw branchCheckError;
8084
}
@@ -92,19 +96,22 @@ export default async function createBranchIfNotExists(request: {
9296
});
9397

9498
// Create the new branch
99+
console.log("[debug] createBranchIfNotExists: Creating new branch", { branch: request.branch, baseSha });
95100
const response = await octokit.request("POST /repos/{owner}/{repo}/git/refs", {
96101
owner: request.owner,
97102
repo: request.repo,
98103
ref: `refs/heads/${request.branch}`,
99104
sha: baseSha
100105
});
101106

107+
console.log("[debug] createBranchIfNotExists: Branch created successfully", { branch: request.branch });
102108
return {
103109
success: true,
104110
baseSha,
105111
response
106112
};
107113
} catch (error) {
114+
console.error("[debug] createBranchIfNotExists: Error occurred", { error, branch: request.branch });
108115
return {
109116
success: false,
110117
error: `Unknown error occurred: ${error}` // TODO: Add error message

packages/fern-dashboard/src/app/services/github/github-loader.ts

Lines changed: 71 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import "server-only";
22

33
import type {
44
FernProject,
5+
GetDocsYmlAndReferencesResult,
56
GetDocsYmlResult,
67
GetFernConfigJsonResult,
78
GetFernProjectResult,
@@ -31,10 +32,10 @@ interface DocsYmlConfig {
3132
path?: string;
3233
[key: string]: any;
3334
}[];
34-
tabs?: {
35-
path?: string;
36-
[key: string]: any;
37-
}[];
35+
// tabs?: {
36+
// path?: string;
37+
// [key: string]: any;
38+
// }[];
3839
}
3940

4041
/**
@@ -196,7 +197,7 @@ export class GitHubLoader implements GitLoader {
196197
}
197198

198199
/**
199-
* Extracts all referenced yml file paths from versions, tabs, and products sections
200+
* Extracts all referenced yml file paths from products, versions, and tabs
200201
*/
201202
private extractReferencedYmlPaths(yamlContent: string): string[] {
202203
try {
@@ -221,14 +222,14 @@ export class GitHubLoader implements GitLoader {
221222
}
222223
}
223224

224-
// Extract paths from tabs
225-
if (config?.tabs && Array.isArray(config.tabs)) {
226-
for (const tab of config.tabs) {
227-
if (tab?.path && typeof tab.path === "string") {
228-
paths.push(tab.path);
229-
}
230-
}
231-
}
225+
// // Extract paths from tabs
226+
// if (config?.tabs && Array.isArray(config.tabs)) {
227+
// for (const tab of config.tabs) {
228+
// if (tab?.path && typeof tab.path === "string") {
229+
// paths.push(tab.path);
230+
// }
231+
// }
232+
// }
232233

233234
return paths;
234235
} catch (error) {
@@ -401,55 +402,51 @@ export class GitHubLoader implements GitLoader {
401402
}
402403
}
403404

404-
async getDocsYml(
405+
async getDocsYmlAndReferences(
405406
owner: string,
406407
repo: string,
407408
site: string,
408409
ref: string = "main",
409410
preferDefaultBranch: boolean = false
410-
): Promise<GetDocsYmlResult> {
411-
const projectResult = await this.getFernProjectBySite(owner, repo, site);
412-
if (projectResult.type === "error") {
411+
): Promise<GetDocsYmlAndReferencesResult> {
412+
const mainDocsYmlContent = await this.getDocsYml(owner, repo, site, ref, preferDefaultBranch);
413+
if (mainDocsYmlContent.type === "error") {
413414
return {
414415
type: "error",
415-
error: projectResult.error
416+
error: mainDocsYmlContent.error
416417
};
417418
}
418419

419-
// Use the default branch from the repository if requested
420-
const targetRef = preferDefaultBranch ? projectResult.result.defaultBranch : ref;
420+
const docsYmlMap = new Map<string, string>();
421421

422-
const mainDocsYmlPath = projectResult.result.project.docsYmlPath;
423-
const content = await this.getFileContent(owner, repo, targetRef, mainDocsYmlPath);
424-
if (!content) {
425-
return {
426-
type: "error",
427-
error: { type: "DOCS_YML_MISSING" }
428-
};
429-
}
422+
// We consider the main docs.yml to be at the root (referenced files will be relative to it)
423+
docsYmlMap.set("docs.yml", mainDocsYmlContent.result);
430424

431425
// Extract referenced yml file paths
432-
const referencedPaths = this.extractReferencedYmlPaths(content);
426+
const referencedPaths = this.extractReferencedYmlPaths(mainDocsYmlContent.result);
433427

434-
// If no referenced files, return simple string
428+
// If no referenced files, return map with just the main docs.yml
435429
if (referencedPaths.length === 0) {
436430
return {
437431
type: "ok",
438-
result: content
432+
result: docsYmlMap
439433
};
440434
}
441435

442-
// Load all referenced yml files
443-
const docsYmlMap = new Map<string, string>();
444-
docsYmlMap.set("docs.yml", content);
445-
446-
// Resolve relative paths to absolute paths based on main docs.yml location
436+
// Get the full path and directory of the main docs.yml file so we can resolve referenced file paths
437+
const mainDocsYmlPath = mainDocsYmlContent.metadata.path;
447438
const docsYmlDir = mainDocsYmlPath.substring(0, mainDocsYmlPath.lastIndexOf("/"));
448439

440+
// Use the default branch from the repository if requested
441+
const targetRef = preferDefaultBranch ? mainDocsYmlContent.metadata.defaultBranch : ref;
442+
449443
const referencedFilePromises = referencedPaths.map(async (relativePath) => {
450-
// Normalize the path (remove ./ prefix if present)
444+
if (relativePath.startsWith("../")) {
445+
throw new Error(`docs.yml does not allow referencing files outside of its directory: ${relativePath}`);
446+
}
447+
// Normalize the relative path (remove ./ prefix if present)
451448
const normalizedPath = relativePath.startsWith("./") ? relativePath.substring(2) : relativePath;
452-
// Construct absolute path: avoid leading slash when docsYmlDir is empty (root case)
449+
// Construct absolute path (docs.yml location is considered the root directory)
453450
const absolutePath = docsYmlDir ? `${docsYmlDir}/${normalizedPath}` : normalizedPath;
454451

455452
const fileContent = await this.getFileContent(owner, repo, targetRef, absolutePath);
@@ -469,6 +466,42 @@ export class GitHubLoader implements GitLoader {
469466
};
470467
}
471468

469+
async getDocsYml(
470+
owner: string,
471+
repo: string,
472+
site: string,
473+
ref: string = "main",
474+
preferDefaultBranch: boolean = false
475+
): Promise<GetDocsYmlResult> {
476+
const projectResult = await this.getFernProjectBySite(owner, repo, site);
477+
if (projectResult.type === "error") {
478+
return {
479+
type: "error",
480+
error: projectResult.error
481+
};
482+
}
483+
484+
// Use the default branch from the repository if requested
485+
const targetRef = preferDefaultBranch ? projectResult.result.defaultBranch : ref;
486+
487+
const content = await this.getFileContent(owner, repo, targetRef, projectResult.result.project.docsYmlPath);
488+
if (!content) {
489+
return {
490+
type: "error",
491+
error: { type: "DOCS_YML_MISSING" }
492+
};
493+
}
494+
495+
return {
496+
type: "ok",
497+
result: content,
498+
metadata: {
499+
path: projectResult.result.project.docsYmlPath,
500+
defaultBranch: projectResult.result.defaultBranch
501+
}
502+
};
503+
}
504+
472505
async updateDocsYml(
473506
owner: string,
474507
repo: string,

packages/fern-dashboard/src/components/docs-page/visual-editor-section/VisualEditorSectionClient.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,10 @@ export function VisualEditorSectionClient({
5656
);
5757
return (
5858
<Card className="flex flex-col">
59-
<VisualEditorHeader />
59+
<div className="flex items-center justify-between">
60+
<VisualEditorHeader />
61+
<GoToEditorButton docsUrl={docsUrl} session={session} />
62+
</div>
6063
<div className="flex flex-col gap-3">
6164
{loadingRow}
6265
<hr className="border-border" />

packages/fern-dashboard/src/components/editor/BranchInitializer.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export function BranchInitializer({ orgName, site, owner, repo, branch, baseBran
3838
return;
3939
}
4040

41+
console.log("[debug] BranchInitializer: Starting branch initialization", { branch, baseBranch });
4142
createBranchMutation
4243
.mutateAsync({
4344
orgName,
@@ -49,14 +50,18 @@ export function BranchInitializer({ orgName, site, owner, repo, branch, baseBran
4950
})
5051
.then((result) => {
5152
if (!result.success) {
52-
console.error("Failed to create branch:", result.error);
53+
console.error("[debug] BranchInitializer: Failed to create branch:", result.error);
5354
setBranchFailed(true);
5455
setBranchFailureReason(result.error);
56+
} else {
57+
console.log("[debug] BranchInitializer: Branch initialized successfully", { branch });
5558
}
5659
})
5760
.catch((error) => {
58-
console.error("Error creating branch:", {
61+
console.error("[debug] BranchInitializer: Caught error during branch creation:", {
5962
error,
63+
errorMessage: error?.message,
64+
errorStack: error?.stack,
6065
orgName,
6166
owner,
6267
repo,

packages/fern-dashboard/src/components/editor/ClientNavigationProvider.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export interface ClientNavigationProviderProps {
99
branchName: string;
1010
orgName: string;
1111
docsUrl: string;
12-
initialDocsYmlContent: string | Map<string, string> | null;
12+
latestDocsYmlAndReferences: Map<string, string> | null;
1313
}
1414

1515
export function ClientNavigationProvider(props: ClientNavigationProviderProps) {
@@ -22,7 +22,7 @@ export function ClientNavigationProvider(props: ClientNavigationProviderProps) {
2222
branchName={props.branchName}
2323
orgName={props.orgName}
2424
docsUrl={props.docsUrl}
25-
initialDocsYmlContent={props.initialDocsYmlContent}
25+
latestDocsYmlAndReferences={props.latestDocsYmlAndReferences}
2626
deletionToastCallback={deletionToastCallback}
2727
>
2828
{props.children}

0 commit comments

Comments
 (0)