Skip to content

Commit

Permalink
fix(cli): docs generation now preserves original model schema names.
Browse files Browse the repository at this point in the history
  • Loading branch information
eyw520 committed Nov 22, 2024
1 parent d594089 commit b9e968a
Show file tree
Hide file tree
Showing 18 changed files with 87 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export function convertParameters({
const availability = convertAvailability(resolvedParameter);

const parameterBreadcrumbs = [...requestBreadcrumbs, resolvedParameter.name];
const generatedName = getGeneratedTypeName(parameterBreadcrumbs);
const generatedName = getGeneratedTypeName(parameterBreadcrumbs, context.options.preserveSchemaIds);

let schema =
resolvedParameter.schema != null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export function convertAsyncSyncOperation({
name: headerToIgnore,
schema: SchemaWithExample.literal({
nameOverride: undefined,
generatedName: getGeneratedTypeName([headerToIgnore]),
generatedName: getGeneratedTypeName([headerToIgnore], context.options.preserveSchemaIds),
title: undefined,
description: undefined,
availability: undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export function convertHttpOperation({
queryParameters: convertedParameters.queryParameters,
headers: convertedParameters.headers,
requestNameOverride: requestNameOverride ?? undefined,
generatedRequestName: getGeneratedTypeName(requestBreadcrumbs),
generatedRequestName: getGeneratedTypeName(requestBreadcrumbs, context.options.preserveSchemaIds),
request: convertedRequest,
response: convertedResponse.value,
errors: convertedResponse.errors,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export function convertWebhookOperation({
operationId: operation.operationId,
tags: context.resolveTagsToTagIds(operation.tags),
headers: convertedParameters.headers,
generatedPayloadName: getGeneratedTypeName(payloadBreadcrumbs),
generatedPayloadName: getGeneratedTypeName(payloadBreadcrumbs, context.options.preserveSchemaIds),
payload: convertedPayload.schema,
description: operation.description,
examples: convertWebhookExamples(convertedPayload.fullExamples),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import { getDefaultAsString } from "../../../schema/defaults/getDefault";
import { getGeneratedTypeName } from "../../../schema/utils/getSchemaName";
import { FernOpenAPIExtension } from "./fernExtensions";

export function getVariableDefinitions(document: OpenAPIV3.Document): Record<string, PrimitiveSchema> {
export function getVariableDefinitions(
document: OpenAPIV3.Document,
preserveSchemaIds: boolean
): Record<string, PrimitiveSchema> {
const variables = getExtension<Record<string, OpenAPIV3.SchemaObject>>(
document,
FernOpenAPIExtension.SDK_VARIABLES
Expand All @@ -22,7 +25,7 @@ export function getVariableDefinitions(document: OpenAPIV3.Document): Record<str
variableName,
{
nameOverride: undefined,
generatedName: getGeneratedTypeName([variableName]),
generatedName: getGeneratedTypeName([variableName], preserveSchemaIds),
title: schema.title,
schema: PrimitiveSchemaValue.string({
default: getDefaultAsString(schema),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export function generateIr({
source,
namespace
});
const variables = getVariableDefinitions(openApi);
const variables = getVariableDefinitions(openApi, options.preserveSchemaIds);
const globalHeaders = getGlobalHeaders(openApi);
const idempotencyHeaders = getIdempotencyHeaders(openApi);

Expand Down Expand Up @@ -465,7 +465,10 @@ function maybeAddBackDiscriminantsFromSchemas(
...property,
schema: SchemaWithExample.literal({
nameOverride: undefined,
generatedName: getGeneratedTypeName([schema.generatedName, discriminantValue]),
generatedName: getGeneratedTypeName(
[schema.generatedName, discriminantValue],
context.options.preserveSchemaIds
),
title: undefined,
value: LiteralSchemaValue.string(discriminantValue),
groupName: undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export interface ParseOpenAPIOptions {
onlyIncludeReferencedSchemas: boolean;
/* Whether or not to include path parameters in the in-lined request */
inlinePathParameters: boolean;
/* Whether or not to preserve original schema Ids in the IR */
preserveSchemaIds: boolean;
}

export const DEFAULT_PARSE_OPENAPI_SETTINGS: ParseOpenAPIOptions = {
Expand All @@ -30,5 +32,6 @@ export const DEFAULT_PARSE_OPENAPI_SETTINGS: ParseOpenAPIOptions = {
cooerceEnumsToLiterals: true,
respectReadonlySchemas: false,
onlyIncludeReferencedSchemas: false,
inlinePathParameters: false
inlinePathParameters: false,
preserveSchemaIds: false
};
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,8 @@ function getParseOptions({
inlinePathParameters:
overrides?.inlinePathParameters ??
specSettings?.inlinePathParameters ??
DEFAULT_PARSE_OPENAPI_SETTINGS.inlinePathParameters
DEFAULT_PARSE_OPENAPI_SETTINGS.inlinePathParameters,
preserveSchemaIds: overrides?.preserveSchemaIds ?? DEFAULT_PARSE_OPENAPI_SETTINGS.preserveSchemaIds
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,12 @@ export function convertObject({
}
parents.push({
schemaId,
convertedSchema: convertToReferencedSchema(allOfElement, [schemaId], source),
convertedSchema: convertToReferencedSchema(
allOfElement,
[schemaId],
source,
context.options.preserveSchemaIds
),
properties: getAllProperties({ schema: allOfElement, context, breadcrumbs, source, namespace })
});
context.markSchemaAsReferencedByNonRequest(schemaId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,14 @@ export function convertReferenceObject(
namespace,
new Set()
)
: SchemaWithExample.reference(convertToReferencedSchema(schema, breadcrumbs, source));
: SchemaWithExample.reference(
convertToReferencedSchema(schema, breadcrumbs, source, context.options.preserveSchemaIds)
);
if (wrapAsNullable) {
return SchemaWithExample.nullable({
title: undefined,
nameOverride: undefined,
generatedName: getGeneratedTypeName(breadcrumbs),
generatedName: getGeneratedTypeName(breadcrumbs, context.options.preserveSchemaIds),
value: referenceSchema,
description: undefined,
availability: undefined,
Expand Down Expand Up @@ -166,7 +168,7 @@ export function convertSchemaObject(
let groupName: SdkGroupName = (typeof mixedGroupName === "string" ? [mixedGroupName] : mixedGroupName) ?? [];
groupName = context.resolveGroupName(groupName);

const generatedName = getGeneratedTypeName(breadcrumbs);
const generatedName = getGeneratedTypeName(breadcrumbs, context.options.preserveSchemaIds);
const title = schema.title;
const description = schema.description;
const availability = convertAvailability(schema);
Expand Down Expand Up @@ -935,10 +937,11 @@ export function getSchemaIdFromReference(ref: OpenAPIV3.ReferenceObject): string
export function convertToReferencedSchema(
schema: OpenAPIV3.ReferenceObject,
breadcrumbs: string[],
source: Source
source: Source,
preserveSchemaIds: boolean
): ReferencedSchema {
const nameOverride = getExtension<string>(schema, FernOpenAPIExtension.TYPE_NAME);
const generatedName = getGeneratedTypeName(breadcrumbs);
const generatedName = getGeneratedTypeName(breadcrumbs, preserveSchemaIds);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const description = (schema as any).description;
const availability = convertAvailability(schema);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export function convertUndiscriminatedOneOf({
return schema.enum.map((enumValue) => {
return SchemaWithExample.literal({
nameOverride: undefined,
generatedName: getGeneratedTypeName([generatedName, enumValue]),
generatedName: getGeneratedTypeName([generatedName, enumValue], context.options.preserveSchemaIds),
title: undefined,
value: LiteralSchemaValue.string(enumValue),
groupName: undefined,
Expand Down Expand Up @@ -201,7 +201,10 @@ export function convertUndiscriminatedOneOfWithDiscriminant({
subtypeReference.properties = {
[discriminator.propertyName]: SchemaWithExample.literal({
nameOverride: undefined,
generatedName: getGeneratedTypeName([generatedName, discriminantValue]),
generatedName: getGeneratedTypeName(
[generatedName, discriminantValue],
context.options.preserveSchemaIds
),
title: undefined,
value: LiteralSchemaValue.string(discriminantValue),
groupName: undefined,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
import { camelCase, upperFirst } from "lodash-es";
import { camelCase, upperFirst, lowerFirst } from "lodash-es";
import { replaceStartingNumber } from "./replaceStartingNumber";

export function getGeneratedTypeName(breadcrumbs: string[]): string {
const underscoreDelimeted = breadcrumbs.join("_");
const name = upperFirst(camelCase(underscoreDelimeted));
function customCamelCase(input: string): string {
const tokens = input.split("_");
const processedTokens = tokens.map((token, index) => {
if (/^[a-zA-Z0-9]+$/.test(token)) {
return index === 0 ? lowerFirst(token) : upperFirst(token);
}
return token;
});
return processedTokens.join("");
}

export function getGeneratedTypeName(breadcrumbs: string[], useOriginalSchemaIds: boolean): string {
const camelCaseFn = useOriginalSchemaIds ? customCamelCase : camelCase;
const underscoreDelimited = breadcrumbs.join("_");
const name = upperFirst(camelCaseFn(underscoreDelimited));
if (/^\d/.test(name)) {
return replaceStartingNumber(name) ?? name;
}
return name;
}

export function getGeneratedPropertyName(breadcrumbs: string[]): string {
const underscoreDelimeted = breadcrumbs.join("_");
return camelCase(underscoreDelimeted);
const underscoreDelimited = breadcrumbs.join("_");
return camelCase(underscoreDelimited);
}
11 changes: 9 additions & 2 deletions packages/cli/cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -929,19 +929,26 @@ function addWriteDefinitionCommand(cli: Argv<GlobalCliOptions>, cliContext: CliC
.option("language", {
choices: Object.values(generatorsYml.GenerationLanguage),
description: "Write the definition for a particular SDK language"
})
.option("preserve-schemas", {
string: true,
description: "Preserve potentially unsafe schema Ids in the generated fern definition"
}),
async (argv) => {
const preserveSchemaIds = argv.preserveSchemas != null;
await cliContext.instrumentPostHogEvent({
command: "fern write-definition"
});
await writeDefinitionForWorkspaces({
project: await loadProjectAndRegisterWorkspacesWithContext(cliContext, {
commandLineApiWorkspace: argv.api,
defaultToAllApiWorkspaces: true,
sdkLanguage: argv.language
sdkLanguage: argv.language,
preserveSchemaIds
}),
cliContext,
sdkLanguage: argv.language
sdkLanguage: argv.language,
preserveSchemaIds
});
}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export async function generateDocsWorkspace({
project.apiWorkspaces.map(async (workspace) => {
return workspace.toFernWorkspace(
{ context },
{ enableUniqueErrorsPerEndpoint: true, detectGlobalHeaders: false }
{ enableUniqueErrorsPerEndpoint: true, detectGlobalHeaders: false, preserveSchemaIds: true }
);
})
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ import { CliContext } from "../../cli-context/CliContext";
export async function writeDefinitionForWorkspaces({
project,
cliContext,
sdkLanguage
sdkLanguage,
preserveSchemaIds
}: {
project: Project;
cliContext: CliContext;
sdkLanguage: generatorsYml.GenerationLanguage | undefined;
preserveSchemaIds: boolean;
}): Promise<void> {
await Promise.all(
project.apiWorkspaces.map(async (workspace) => {
Expand All @@ -26,7 +28,7 @@ export async function writeDefinitionForWorkspaces({
await writeDefinitionForFernWorkspace({ workspace, context });
} else {
await writeDefinitionForNonFernWorkspace({
workspace: await workspace.toFernWorkspace({ context }),
workspace: await workspace.toFernWorkspace({ context }, { preserveSchemaIds }),
context
});
}
Expand Down
7 changes: 7 additions & 0 deletions packages/cli/cli/versions.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
- changelogEntry:
- summary: |
Docs generation now preserves original model schema names.
type: fix
irVersion: 53
version: 0.45.0-rc54

- changelogEntry:
- summary: |
Add support for the `smart-casing` flags in the IR commands.
Expand Down
9 changes: 8 additions & 1 deletion packages/cli/lazy-fern-workspace/src/OSSWorkspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,13 @@ export declare namespace OSSWorkspace {
*/
cooerceEnumsToLiterals?: boolean;
/*
* Whehter or not to parse object query parameters.
* Whether or not to parse object query parameters.
*/
objectQueryParameters?: boolean;
/*
* Whether or not to preserve original schema ids.
*/
preserveSchemaIds?: boolean;
}
}

Expand Down Expand Up @@ -302,5 +306,8 @@ function getOptionsOverridesFromSettings(settings?: OSSWorkspace.Settings): Part
if (settings.cooerceEnumsToLiterals) {
result.cooerceEnumsToLiterals = true;
}
if (settings.preserveSchemaIds) {
result.preserveSchemaIds = true;
}
return result;
}
1 change: 1 addition & 0 deletions packages/cli/project-loader/src/loadProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export declare namespace loadProject {
context: TaskContext;
nameOverride?: string;
sdkLanguage?: generatorsYml.GenerationLanguage;
preserveSchemaIds?: boolean;
}

export interface LoadProjectFromDirectoryArgs extends Args {
Expand Down

0 comments on commit b9e968a

Please sign in to comment.