Skip to content

Commit

Permalink
(feat): wire through api workspaces to docs validator (#4255)
Browse files Browse the repository at this point in the history
  • Loading branch information
dsinghvi authored Aug 10, 2024
1 parent 592d50f commit 758761d
Show file tree
Hide file tree
Showing 23 changed files with 123 additions and 55 deletions.
9 changes: 4 additions & 5 deletions .pnp.cjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion packages/cli/cli/src/commands/docs-dev/devDocsWorkspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ export async function previewDocsWorkspace({
workspace: docsWorkspace,
context,
logWarnings: true,
logSummary: false
logSummary: false,
loadAPIWorkspace: project.loadAPIWorkspace
});
for (const apiWorkspace of project.apiWorkspaces) {
await cliContext.runTaskForWorkspace(apiWorkspace, async (apiWorkspaceContext) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,12 @@ export async function generateDocsWorkspace({
});

await cliContext.runTaskForWorkspace(docsWorkspace, async (context) => {
await validateDocsWorkspaceAndLogIssues({ workspace: docsWorkspace, context, logWarnings: false });
await validateDocsWorkspaceAndLogIssues({
workspace: docsWorkspace,
context,
logWarnings: false,
loadAPIWorkspace: project.loadAPIWorkspace
});

const fernWorkspaces = await Promise.all(
project.apiWorkspaces.map(async (workspace) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,44 @@
import { validateDocsWorkspace } from "@fern-api/docs-validator";
import { APIWorkspaceLoader, validateDocsWorkspace } from "@fern-api/docs-validator";
import { TaskContext } from "@fern-api/task-context";
import { DocsWorkspace } from "@fern-api/workspace-loader";
import { logViolations } from "./logViolations";

export async function validateDocsWorkspaceWithoutExiting({
workspace,
loadAPIWorkspace,
context,
logWarnings,
logSummary = true
}: {
workspace: DocsWorkspace;
loadAPIWorkspace: APIWorkspaceLoader;
context: TaskContext;
logWarnings: boolean;
logSummary?: boolean;
}): Promise<{ hasErrors: boolean }> {
const violations = await validateDocsWorkspace(workspace, context);
const violations = await validateDocsWorkspace(workspace, context, loadAPIWorkspace);
const { hasErrors } = logViolations({ violations, context, logWarnings, logSummary });

return { hasErrors };
}

export async function validateDocsWorkspaceAndLogIssues({
workspace,
loadAPIWorkspace,
context,
logWarnings
}: {
workspace: DocsWorkspace;
loadAPIWorkspace: APIWorkspaceLoader;
context: TaskContext;
logWarnings: boolean;
}): Promise<void> {
const { hasErrors } = await validateDocsWorkspaceWithoutExiting({ workspace, context, logWarnings });
const { hasErrors } = await validateDocsWorkspaceWithoutExiting({
workspace,
context,
logWarnings,
loadAPIWorkspace
});

if (hasErrors) {
context.failAndThrow();
Expand Down
7 changes: 6 additions & 1 deletion packages/cli/cli/src/commands/validate/validateWorkspaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ export async function validateWorkspaces({
const docsWorkspace = project.docsWorkspaces;
if (docsWorkspace != null) {
await cliContext.runTaskForWorkspace(docsWorkspace, async (context) => {
await validateDocsWorkspaceAndLogIssues({ workspace: docsWorkspace, context, logWarnings });
await validateDocsWorkspaceAndLogIssues({
workspace: docsWorkspace,
context,
logWarnings,
loadAPIWorkspace: project.loadAPIWorkspace
});
});
}

Expand Down
3 changes: 2 additions & 1 deletion packages/cli/project-loader/src/Project.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { fernConfigJson } from "@fern-api/configuration";
import { DocsWorkspace, LazyFernWorkspace, OSSWorkspace } from "@fern-api/workspace-loader";
import { APIWorkspace, DocsWorkspace, LazyFernWorkspace, OSSWorkspace } from "@fern-api/workspace-loader";
export interface Project {
config: fernConfigJson.ProjectConfig;
apiWorkspaces: (OSSWorkspace | LazyFernWorkspace)[];
docsWorkspaces: DocsWorkspace | undefined;
loadAPIWorkspace: (name: string | undefined) => APIWorkspace | undefined;
}
8 changes: 7 additions & 1 deletion packages/cli/project-loader/src/loadProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,13 @@ export async function loadProject({
return {
config: await fernConfigJson.loadProjectConfig({ directory: fernDirectory, context }),
apiWorkspaces,
docsWorkspaces: await loadDocsWorkspace({ fernDirectory, context })
docsWorkspaces: await loadDocsWorkspace({ fernDirectory, context }),
loadAPIWorkspace: (name: string | undefined): APIWorkspace | undefined => {
if (name == null) {
return apiWorkspaces[0];
}
return apiWorkspaces.find((workspace) => workspace.workspaceName === name);
}
};
}

Expand Down
2 changes: 2 additions & 0 deletions packages/cli/workspace-loader/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ export {
} from "./types/Workspace";
export * from "./utils";
export * from "./workspaces";
export { AbstractAPIWorkspace } from "./workspaces/AbstractAPIWorkspace";
export { type APIWorkspace } from "./workspaces/APIWorkspace";
4 changes: 4 additions & 0 deletions packages/cli/yaml/docs-validator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
},
"dependencies": {
"@fern-api/configuration": "workspace:*",
"@fern-api/core-utils": "workspace:*",
"@fern-api/docs-markdown-utils": "workspace:*",
"@fern-api/fs-utils": "workspace:*",
"@fern-api/logger": "workspace:*",
"@fern-api/task-context": "workspace:*",
Expand All @@ -36,6 +38,7 @@
"@types/tinycolor2": "^1.4.6",
"chardet": "^2.0.0",
"file-type": "^19.0.0",
"js-yaml": "^4.1.0",
"next-mdx-remote": "^5.0.0",
"rehype-katex": "^7.0.0",
"remark-gfm": "^4.0.0",
Expand All @@ -45,6 +48,7 @@
},
"devDependencies": {
"@types/jest": "^29.5.12",
"@types/js-yaml": "^4.0.8",
"@types/node": "^18.7.18",
"depcheck": "^1.4.6",
"eslint": "^8.56.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/yaml/docs-validator/src/Rule.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Logger } from "@fern-api/logger";
import { DocsWorkspace } from "@fern-api/workspace-loader";
import { DocsConfigFileAstNodeTypes } from "@fern-api/yaml-schema";
import { DocsConfigFileAstNodeTypes } from "./docsAst/DocsConfigFileAstVisitor";

export interface Rule {
name: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { RelativeFilePath } from "@fern-api/fs-utils";
import { NodePath } from "@fern-api/yaml-schema";
import {
DocsConfigFileAstNodeTypes,
DocsConfigFileAstNodeVisitor,
DocsConfigFileAstVisitor,
NodePath
} from "@fern-api/yaml-schema";
DocsConfigFileAstVisitor
} from "./docsAst/DocsConfigFileAstVisitor";
import { RuleVisitor } from "./Rule";
import { ValidationViolation } from "./ValidationViolation";

Expand Down Expand Up @@ -47,6 +47,7 @@ export function createDocsConfigFileAstVisitorForRules({
...createAstNodeVisitor("file"),
...createAstNodeVisitor("filepath"),
...createAstNodeVisitor("markdownPage"),
...createAstNodeVisitor("versionFile")
...createAstNodeVisitor("versionFile"),
...createAstNodeVisitor("apiSection")
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { AbstractAPIWorkspace } from "@fern-api/workspace-loader";

export type APIWorkspaceLoader = (id?: string) => AbstractAPIWorkspace<unknown> | undefined;
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { docsYml } from "@fern-api/configuration";
import { AbsoluteFilePath } from "@fern-api/fs-utils";
import { NodePath } from "../NodePath";
import { AbstractAPIWorkspace } from "@fern-api/workspace-loader";
import { NodePath } from "@fern-api/yaml-schema";

export type DocsConfigFileAstVisitor<R = void | Promise<void>> = {
[K in keyof DocsConfigFileAstNodeTypes]: DocsConfigFileAstNodeVisitor<K, R>;
Expand All @@ -15,6 +16,7 @@ export interface DocsConfigFileAstNodeTypes {
};
markdownPage: { title: string; content: string; absoluteFilepath: AbsoluteFilePath };
versionFile: { path: string; content: unknown };
apiSection: { config: docsYml.RawSchemas.ApiReferenceConfiguration; workspace: AbstractAPIWorkspace<unknown> };
}

export type DocsConfigFileAstNodeVisitor<K extends keyof DocsConfigFileAstNodeTypes, R = void | Promise<void>> = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { docsYml } from "@fern-api/configuration";
import { parseImagePaths, replaceReferencedCode, replaceReferencedMarkdown } from "@fern-api/docs-markdown-utils";
import { AbsoluteFilePath, dirname, doesPathExist, RelativeFilePath, resolve } from "@fern-api/fs-utils";
import { TaskContext } from "@fern-api/task-context";
import { NodePath } from "@fern-api/yaml-schema";
import { readFile } from "fs/promises";
import yaml from "js-yaml";
import path from "path";
import { NodePath } from "../NodePath";
import { APIWorkspaceLoader } from "./APIWorkspaceLoader";
import { DocsConfigFileAstVisitor } from "./DocsConfigFileAstVisitor";
import { validateVersionConfigFileSchema } from "./validateVersionConfig";

Expand All @@ -14,7 +15,8 @@ export async function visitDocsConfigFileYamlAst(
visitor: Partial<DocsConfigFileAstVisitor>,
absoluteFilepathToConfiguration: AbsoluteFilePath,
absolutePathToFernFolder: AbsoluteFilePath,
context: TaskContext
context: TaskContext,
loadAPIWorkspace: APIWorkspaceLoader
): Promise<void> {
await visitor.file?.(
{
Expand Down Expand Up @@ -181,7 +183,8 @@ export async function visitDocsConfigFileYamlAst(
navigation: contents.navigation,
visitor,
nodePath: ["navigation"],
absoluteFilepathToConfiguration
absoluteFilepathToConfiguration,
loadAPIWorkspace
});
}

Expand Down Expand Up @@ -266,7 +269,8 @@ export async function visitDocsConfigFileYamlAst(
navigation: parsedVersionFile.contents.navigation,
visitor,
nodePath: ["navigation"],
absoluteFilepathToConfiguration: absoluteFilepath
absoluteFilepathToConfiguration: absoluteFilepath,
loadAPIWorkspace
});
}
})
Expand Down Expand Up @@ -302,12 +306,14 @@ async function visitNavigation({
navigation,
visitor,
nodePath,
absoluteFilepathToConfiguration
absoluteFilepathToConfiguration,
loadAPIWorkspace
}: {
navigation: docsYml.RawSchemas.NavigationConfig;
visitor: Partial<DocsConfigFileAstVisitor>;
nodePath: NodePath;
absoluteFilepathToConfiguration: AbsoluteFilePath;
loadAPIWorkspace: APIWorkspaceLoader;
}): Promise<void> {
if (navigationConfigIsTabbed(navigation)) {
await Promise.all(
Expand All @@ -319,7 +325,8 @@ async function visitNavigation({
navigationItem: item,
visitor,
nodePath: [...nodePath, `${tabIdx}`, "layout", `${itemIdx}`],
absoluteFilepathToConfiguration
absoluteFilepathToConfiguration,
loadAPIWorkspace
});
})
);
Expand All @@ -333,7 +340,8 @@ async function visitNavigation({
navigationItem: item,
visitor,
nodePath: [...nodePath, `${itemIdx}`],
absoluteFilepathToConfiguration
absoluteFilepathToConfiguration,
loadAPIWorkspace
});
})
);
Expand All @@ -344,12 +352,14 @@ async function visitNavigationItem({
navigationItem,
visitor,
nodePath,
absoluteFilepathToConfiguration
absoluteFilepathToConfiguration,
loadAPIWorkspace
}: {
navigationItem: docsYml.RawSchemas.NavigationItem;
visitor: Partial<DocsConfigFileAstVisitor>;
nodePath: NodePath;
absoluteFilepathToConfiguration: AbsoluteFilePath;
loadAPIWorkspace: APIWorkspaceLoader;
}): Promise<void> {
if (navigationItemIsPage(navigationItem)) {
await visitFilepath({
Expand Down Expand Up @@ -380,11 +390,25 @@ async function visitNavigationItem({
navigationItem: item,
visitor,
nodePath: [...nodePath, "section", "contents", `${itemIdx}`],
absoluteFilepathToConfiguration
absoluteFilepathToConfiguration,
loadAPIWorkspace
});
})
);
}

if (navigationItemIsApi(navigationItem)) {
const workspace = loadAPIWorkspace(navigationItem.apiName != null ? navigationItem.apiName : undefined);
if (workspace != null) {
await visitor.apiSection?.(
{
config: navigationItem,
workspace
},
[...nodePath, "api"]
);
}
}
}

async function visitScript({
Expand Down Expand Up @@ -423,6 +447,13 @@ function navigationItemIsSection(
return (item as docsYml.RawSchemas.SectionConfiguration).section != null;
}

function navigationItemIsApi(
item: docsYml.RawSchemas.NavigationItem
): item is docsYml.RawSchemas.ApiReferenceConfiguration {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
return (item as docsYml.RawSchemas.ApiReferenceConfiguration).api != null;
}

function navigationConfigIsTabbed(
config: docsYml.RawSchemas.NavigationConfig
): config is docsYml.RawSchemas.TabbedNavigationConfig {
Expand Down
8 changes: 8 additions & 0 deletions packages/cli/yaml/docs-validator/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
export {
type DocsConfigFileAstNodeTypes,
type DocsConfigFileAstNodeVisitor,
type DocsConfigFileAstVisitor
} from "./docsAst/DocsConfigFileAstVisitor";
export { validateVersionConfigFileSchema } from "./docsAst/validateVersionConfig";
export { getReferencedMarkdownFiles } from "./rules/valid-markdown-link/valid-markdown-link";
export { FrontmatterSchema } from "./rules/valid-markdown/valid-markdown";
export { validateDocsWorkspace } from "./validateDocsWorkspace";
export { visitDocsConfigFileYamlAst } from "./docsAst/visitDocsConfigFileAst";
export { type APIWorkspaceLoader } from "./docsAst/APIWorkspaceLoader";
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { validateVersionConfigFileSchema } from "@fern-api/yaml-schema";
import { validateVersionConfigFileSchema } from "../../docsAst/validateVersionConfig";
import { Rule } from "../../Rule";

export const ValidateVersionFileRule: Rule = {
Expand Down
Loading

0 comments on commit 758761d

Please sign in to comment.