Skip to content

Commit

Permalink
improvement: add a flag to allow python to generate discriminated uni…
Browse files Browse the repository at this point in the history
…ons as undiscriminated unions (#3740)
  • Loading branch information
armandobelardo authored Jun 3, 2024
1 parent f08f122 commit e9d64a0
Show file tree
Hide file tree
Showing 55 changed files with 1,091 additions and 265 deletions.
1 change: 1 addition & 0 deletions .pnp.cjs

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

42 changes: 31 additions & 11 deletions packages/cli/cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,8 @@ function addIrCommand(cli: Argv<GlobalCliOptions>, cliContext: CliContext) {
await generateIrForWorkspaces({
project: await loadProjectAndRegisterWorkspacesWithContext(cliContext, {
commandLineApiWorkspace: argv.api,
defaultToAllApiWorkspaces: false
defaultToAllApiWorkspaces: false,
sdkLanguage: argv.language
}),
irFilepath: resolve(cwd(), argv.pathToOutput),
cliContext,
Expand All @@ -473,6 +474,10 @@ function addOpenAPIIrCommand(cli: Argv<GlobalCliOptions>, cliContext: CliContext
description: "Path to write intermediate representation (IR)",
demandOption: true
})
.option("language", {
choices: Object.values(generatorsYml.GenerationLanguage),
description: "Generate IR for a particular language"
})
.option("api", {
string: true,
description: "Only run the command on the provided API"
Expand All @@ -481,10 +486,12 @@ function addOpenAPIIrCommand(cli: Argv<GlobalCliOptions>, cliContext: CliContext
await generateOpenAPIIrForWorkspaces({
project: await loadProjectAndRegisterWorkspacesWithContext(cliContext, {
commandLineApiWorkspace: argv.api,
defaultToAllApiWorkspaces: false
defaultToAllApiWorkspaces: false,
sdkLanguage: argv.language
}),
irFilepath: resolve(cwd(), argv.pathToOutput),
cliContext
cliContext,
sdkLanguage: argv.language
});
}
);
Expand Down Expand Up @@ -780,6 +787,10 @@ function addTestCommand(cli: Argv<GlobalCliOptions>, cliContext: CliContext) {
.option("command", {
string: true,
description: "The command to run to test your SDK."
})
.option("language", {
choices: Object.values(generatorsYml.GenerationLanguage),
description: "Run the tests configured to a specific language"
}),
async (argv) => {
cliContext.instrumentPostHogEvent({
Expand All @@ -790,9 +801,11 @@ function addTestCommand(cli: Argv<GlobalCliOptions>, cliContext: CliContext) {
project: await loadProjectAndRegisterWorkspacesWithContext(cliContext, {
commandLineApiWorkspace: argv.api,
defaultToAllApiWorkspaces: false,
nameOverride: ".mock"
nameOverride: ".mock",
sdkLanguage: argv.language
}),
testCommand: argv.command
testCommand: argv.command,
generationLanguage: argv.language
});
}
);
Expand Down Expand Up @@ -865,20 +878,27 @@ function addWriteDefinitionCommand(cli: Argv<GlobalCliOptions>, cliContext: CliC
"write-definition",
"Write underlying Fern Definition for OpenAPI specs and API Dependencies.",
(yargs) =>
yargs.option("api", {
string: true,
description: "Only run the command on the provided API"
}),
yargs
.option("api", {
string: true,
description: "Only run the command on the provided API"
})
.option("language", {
choices: Object.values(generatorsYml.GenerationLanguage),
description: "Write the definition for a particular SDK language"
}),
async (argv) => {
cliContext.instrumentPostHogEvent({
command: "fern write-definition"
});
await writeDefinitionForWorkspaces({
project: await loadProjectAndRegisterWorkspacesWithContext(cliContext, {
commandLineApiWorkspace: argv.api,
defaultToAllApiWorkspaces: true
defaultToAllApiWorkspaces: true,
sdkLanguage: argv.language
}),
cliContext
cliContext,
sdkLanguage: argv.language
});
}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export async function generateFdrApiDefinitionForWorkspaces({
await cliContext.runTaskForWorkspace(workspace, async (context) => {
const fernWorkspace =
workspace.type === "oss"
? await convertOpenApiWorkspaceToFernWorkspace(workspace, context)
? await convertOpenApiWorkspaceToFernWorkspace(workspace, context, false, undefined)
: workspace;

const ir = await generateIrForFernWorkspace({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Audiences } from "@fern-api/configuration";
import { Audiences, generatorsYml } from "@fern-api/configuration";
import { AbsoluteFilePath, stringifyLargeObject } from "@fern-api/fs-utils";
import { generatorsYml } from "@fern-api/configuration";
import { migrateIntermediateRepresentationThroughVersion } from "@fern-api/ir-migrations";
import { serialization as IrSerialization } from "@fern-api/ir-sdk";
import { Project } from "@fern-api/project-loader";
Expand Down Expand Up @@ -31,10 +30,28 @@ export async function generateIrForWorkspaces({
await Promise.all(
project.apiWorkspaces.map(async (workspace) => {
await cliContext.runTaskForWorkspace(workspace, async (context) => {
const fernWorkspace =
workspace.type === "oss"
? await convertOpenApiWorkspaceToFernWorkspace(workspace, context)
: workspace;
cliContext.logger.info(`Generating IR for workspace ${workspace.name}`);
let fernWorkspace: FernWorkspace;
if (workspace.type === "fern") {
cliContext.logger.info("Found a fern workspace");
fernWorkspace = workspace;
} else {
workspace.specs = workspace.specs.map((spec) => ({
...spec,
settings: {
audiences: spec.settings?.audiences ?? [],
shouldUseTitleAsName: spec.settings?.shouldUseTitleAsName ?? true,
shouldUseUndiscriminatedUnionsWithLiterals:
spec.settings?.shouldUseUndiscriminatedUnionsWithLiterals ?? false
}
}));
fernWorkspace = await convertOpenApiWorkspaceToFernWorkspace(
workspace,
context,
false,
generationLanguage
);
}

const intermediateRepresentation = await getIntermediateRepresentation({
workspace: fernWorkspace,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { generatorsYml } from "@fern-api/configuration";
import { AbsoluteFilePath, stringifyLargeObject } from "@fern-api/fs-utils";
import { serialization } from "@fern-api/openapi-ir-sdk";
import { parse } from "@fern-api/openapi-parser";
Expand All @@ -9,11 +10,13 @@ import { CliContext } from "../../cli-context/CliContext";
export async function generateOpenAPIIrForWorkspaces({
project,
irFilepath,
cliContext
cliContext,
sdkLanguage
}: {
project: Project;
irFilepath: AbsoluteFilePath;
cliContext: CliContext;
sdkLanguage: generatorsYml.GenerationLanguage | undefined;
}): Promise<void> {
await Promise.all(
project.apiWorkspaces.map(async (workspace) => {
Expand All @@ -23,9 +26,19 @@ export async function generateOpenAPIIrForWorkspaces({
return;
}

workspace.specs = workspace.specs.map((spec) => ({
...spec,
settings: {
audiences: spec.settings?.audiences ?? [],
shouldUseTitleAsName: spec.settings?.shouldUseTitleAsName ?? true,
shouldUseUndiscriminatedUnionsWithLiterals:
spec.settings?.shouldUseUndiscriminatedUnionsWithLiterals ?? false
}
}));
const openAPIIr = await parse({
workspace,
taskContext: context
taskContext: context,
sdkLanguage
});

const irOutputFilePath = path.resolve(irFilepath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ async function writeDefinitionForOpenAPIWorkspace({
workspace: {
specs: [spec]
},
taskContext: context
taskContext: context,
sdkLanguage: undefined
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let existingOverrides: any = {};
Expand Down
59 changes: 10 additions & 49 deletions packages/cli/cli/src/commands/generate/generateAPIWorkspace.ts
Original file line number Diff line number Diff line change
@@ -1,88 +1,49 @@
import { FernToken } from "@fern-api/auth";
import {
DEFAULT_GROUP_GENERATORS_CONFIG_KEY,
fernConfigJson,
GENERATORS_CONFIGURATION_FILENAME
} from "@fern-api/configuration";
import { AbsoluteFilePath } from "@fern-api/fs-utils";
import { fernConfigJson, generatorsYml } from "@fern-api/configuration";
import { runLocalGenerationForWorkspace } from "@fern-api/local-workspace-runner";
import { runRemoteGenerationForAPIWorkspace } from "@fern-api/remote-workspace-runner";
import { TaskContext } from "@fern-api/task-context";
import { FernWorkspace } from "@fern-api/workspace-loader";
import { GROUP_CLI_OPTION } from "../../constants";
import { validateAPIWorkspaceAndLogIssues } from "../validate/validateAPIWorkspaceAndLogIssues";
import { FernWorkspaceMetadata } from "@fern-api/workspace-loader";

export async function generateWorkspace({
organization,
workspace,
projectConfig,
workspaceGetter,
context,
groupName,
version,
shouldLogS3Url,
token,
useLocalDocker,
keepDocker,
absolutePathToPreview
keepDocker
}: {
organization: string;
workspace: FernWorkspace;
workspaceGetter: (
sdkLanguage: generatorsYml.GenerationLanguage | undefined
) => Promise<FernWorkspaceMetadata | undefined>;
projectConfig: fernConfigJson.ProjectConfig;
context: TaskContext;
version: string | undefined;
groupName: string | undefined;
shouldLogS3Url: boolean;
token: FernToken;
useLocalDocker: boolean;
keepDocker: boolean;
absolutePathToPreview: AbsoluteFilePath | undefined;
}): Promise<void> {
if (workspace.generatorsConfiguration == null) {
context.logger.warn("This workspaces has no generators.yml");
return;
}

if (workspace.generatorsConfiguration.groups.length === 0) {
context.logger.warn(`This workspaces has no groups specified in ${GENERATORS_CONFIGURATION_FILENAME}`);
return;
}

const groupNameOrDefault = groupName ?? workspace.generatorsConfiguration.defaultGroup;
if (groupNameOrDefault == null) {
return context.failAndThrow(
`No group specified. Use the --${GROUP_CLI_OPTION} option, or set "${DEFAULT_GROUP_GENERATORS_CONFIG_KEY}" in ${GENERATORS_CONFIGURATION_FILENAME}`
);
}

const group = workspace.generatorsConfiguration.groups.find(
(otherGroup) => otherGroup.groupName === groupNameOrDefault
);
if (group == null) {
return context.failAndThrow(`Group '${groupNameOrDefault}' does not exist.`);
}

await validateAPIWorkspaceAndLogIssues({ workspace, context, logWarnings: false });

if (useLocalDocker) {
await runLocalGenerationForWorkspace({
projectConfig,
workspace,
generatorGroup: group,
workspaceGetter,
keepDocker,
context
});
} else {
await runRemoteGenerationForAPIWorkspace({
projectConfig,
organization,
workspace,
workspaceGetter,
context,
generatorGroup: group,
version,
shouldLogS3Url,
token,
whitelabel: workspace.generatorsConfiguration.whitelabel,
absolutePathToPreview
token
});
}
}
Loading

0 comments on commit e9d64a0

Please sign in to comment.