Skip to content

Commit

Permalink
feat(cli): add new openapi-fdr command for direct openapi - fdr parsi…
Browse files Browse the repository at this point in the history
…ng (#5292)

* added new openapi-fdr command

* update import paths

* address comments

* remove erroneous async

* remove fdr dep and install inlined parser package

---------

Co-authored-by: fern-bot <info@buildwithfern.com>
  • Loading branch information
RohinBhargava and fern-support authored Dec 10, 2024
1 parent 04d1b5c commit a5e0009
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 10 deletions.
4 changes: 3 additions & 1 deletion packages/cli/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@
"@fern-api/configuration-loader": "workspace:*",
"@fern-api/core": "workspace:*",
"@fern-api/core-utils": "workspace:*",
"@fern-api/docs-parsers": "^0.0.10",
"@fern-api/docs-preview": "workspace:*",
"@fern-api/docs-resolver": "workspace:*",
"@fern-api/docs-validator": "workspace:*",
"@fern-api/docs-validator": "workspace:*",
"@fern-api/fern-definition-formatter": "workspace:*",
"@fern-api/fern-definition-schema": "workspace:*",
"@fern-api/fern-definition-validator": "workspace:*",
Expand Down Expand Up @@ -105,6 +106,7 @@
"js-yaml": "^4.1.0",
"latest-version": "^9.0.0",
"lodash-es": "^4.17.21",
"openapi-types": "^12.1.3",
"ora": "^7.0.1",
"organize-imports-cli": "^0.10.0",
"prettier": "^2.7.1",
Expand Down
34 changes: 25 additions & 9 deletions packages/cli/cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { generateJsonschemaForWorkspaces } from "./commands/jsonschema/generateJ
import { generateDynamicIrForWorkspaces } from "./commands/generate-dynamic-ir/generateDynamicIrForWorkspaces";
import { writeDocsDefinitionForProject } from "./commands/write-docs-definition/writeDocsDefinitionForProject";
import { RUNTIME } from "@fern-typescript/fetcher";
import { generateOpenApiToFdrApiDefinitionForWorkspaces } from "./commands/generate-openapi-fdr/generateOpenApiToFdrApiDefinitionForWorkspaces";

void runCli();

Expand Down Expand Up @@ -611,17 +612,32 @@ function addFdrCommand(cli: Argv<GlobalCliOptions>, cliContext: CliContext) {
string: true,
default: new Array<string>(),
description: "Filter the FDR API definition for certain audiences"
})
.option("v2", {
boolean: true,
description: "Use v2 format"
}),
async (argv) => {
await generateFdrApiDefinitionForWorkspaces({
project: await loadProjectAndRegisterWorkspacesWithContext(cliContext, {
commandLineApiWorkspace: argv.api,
defaultToAllApiWorkspaces: false
}),
outputFilepath: resolve(cwd(), argv.pathToOutput),
cliContext,
audiences: argv.audience.length > 0 ? { type: "select", audiences: argv.audience } : { type: "all" }
});
if (argv.v2) {
await generateOpenApiToFdrApiDefinitionForWorkspaces({
project: await loadProjectAndRegisterWorkspacesWithContext(cliContext, {
commandLineApiWorkspace: argv.api,
defaultToAllApiWorkspaces: false
}),
outputFilepath: resolve(cwd(), argv.pathToOutput),
cliContext
});
} else {
await generateFdrApiDefinitionForWorkspaces({
project: await loadProjectAndRegisterWorkspacesWithContext(cliContext, {
commandLineApiWorkspace: argv.api,
defaultToAllApiWorkspaces: false
}),
outputFilepath: resolve(cwd(), argv.pathToOutput),
cliContext,
audiences: argv.audience.length > 0 ? { type: "select", audiences: argv.audience } : { type: "all" }
});
}
}
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { AbsoluteFilePath, stringifyLargeObject } from "@fern-api/fs-utils";
import { Project } from "@fern-api/project-loader";
import { writeFile } from "fs/promises";
import path from "path";
import { CliContext } from "../../cli-context/CliContext";
import { getAllOpenAPISpecs, LazyFernWorkspace, OSSWorkspace } from "@fern-api/lazy-fern-workspace";
// TODO: clean up imports
import { OpenApiDocumentConverterNode } from "@fern-api/docs-parsers";
import { ErrorCollector } from "@fern-api/docs-parsers";
import fs from "fs";
import yaml from "js-yaml";
import { BaseOpenApiV3_1ConverterNodeContext } from "@fern-api/docs-parsers";
import { OpenAPIV3_1 } from "openapi-types";

export async function generateOpenApiToFdrApiDefinitionForWorkspaces({
project,
outputFilepath,
cliContext
}: {
project: Project;
outputFilepath: AbsoluteFilePath;
cliContext: CliContext;
}): Promise<void> {
await Promise.all(
project.apiWorkspaces.map(async (workspace) => {
await cliContext.runTaskForWorkspace(workspace, async (context) => {
await cliContext.runTaskForWorkspace(workspace, async (context) => {
if (workspace instanceof LazyFernWorkspace) {
context.logger.info("Skipping, API is specified as a Fern Definition.");
return;
} else if (!(workspace instanceof OSSWorkspace)) {
return;
}
const openApiSpecs = await getAllOpenAPISpecs({ context, specs: workspace.specs });

if (openApiSpecs.length === 0) {
context.logger.error("No OpenAPI specs found in the workspace");
return;
}

if (openApiSpecs.length > 1) {
context.logger.error("Found multiple OpenAPI specs in the workspace.");
return;
}

const openApi = openApiSpecs[0];

if (openApi != null) {
const input = yaml.load(
fs.readFileSync(openApi.absoluteFilepath, "utf8")
) as OpenAPIV3_1.Document;

const oasContext: BaseOpenApiV3_1ConverterNodeContext = {
document: input,
logger: context.logger,
errors: new ErrorCollector()
};

const openApiFdrJson = new OpenApiDocumentConverterNode({
input,
context: oasContext,
accessPath: [],
pathId: workspace.workspaceName ?? "openapi parser"
});

const fdrApiDefinition = openApiFdrJson.convert();

const resolvedOutputFilePath = path.resolve(outputFilepath);
await writeFile(
resolvedOutputFilePath,
await stringifyLargeObject(fdrApiDefinition, { pretty: true })
);
context.logger.info(`Wrote FDR API definition to ${resolvedOutputFilePath}`);
} else {
context.logger.error("No OpenAPI spec found in the workspace");
}
});
});
})
);
}
64 changes: 64 additions & 0 deletions pnpm-lock.yaml

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

0 comments on commit a5e0009

Please sign in to comment.