Skip to content

Commit

Permalink
Merge branch 'main' into amckinney/openapi/v2
Browse files Browse the repository at this point in the history
  • Loading branch information
amckinney committed Dec 5, 2024
2 parents 65b8fa1 + 4673aec commit 438df69
Show file tree
Hide file tree
Showing 27 changed files with 292 additions and 277 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
<br/>
<div align="center">
<a href="https://www.buildwithfern.com/?utm_source=github&utm_medium=readme&utm_campaign=fern&utm_content=logo">
<img src="/fern/images/logo-primary.svg" height="80" align="center" alt="header" />
<picture>
<source media="(prefers-color-scheme: dark)" srcset="/fern/images/logo-white.svg">
<source media="(prefers-color-scheme: light)" srcset="/fern/images/logo-primary.svg">
<img alt="logo" src="/fern/images/logo-primary.svg" height="80" align="center">
</picture>
</a>
<br/>

Expand Down
2 changes: 1 addition & 1 deletion fern/images/logo-white.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions fern/pages/changelogs/cli/2024-12-05.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
## 0.45.3
**`(fix):`** Unknown schemas are no longer incorrectly marked as `additionalProperties: true`.


Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { type ParseOpenAPIOptions } from "./options";
export { parse, type Document, type OpenAPIDocument, type SpecImportSettings } from "./parse";
export { type ParseOpenAPIOptions, getParseOptions } from "./options";
export { parse, type Document, type OpenAPIDocument } from "./parse";
export { FernOpenAPIExtension, XFernStreaming, FERN_TYPE_EXTENSIONS } from "./openapi/v3/extensions/fernExtensions";
export * from "./asyncapi/v2";
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,16 @@ export abstract class AbstractOpenAPIV3ParserContext implements SchemaParserCont
for (const key of keys) {
if (typeof resolvedSchema !== "object" || resolvedSchema == null) {
return {
"x-fern-type": "unknown",
additionalProperties: true
"x-fern-type": "unknown"
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any as OpenAPIV3.SchemaObject;
}
resolvedSchema = resolvedSchema[key];
}
if (resolvedSchema == null) {
this.logger.warn(`Encountered undefined reference: ${schema.$ref}`);
return {
"x-fern-type": "unknown",
additionalProperties: true
"x-fern-type": "unknown"
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any as OpenAPIV3.SchemaObject;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export interface ParseOpenAPIOptions {
/* Whether or not to disable OpenAPI example generation */
disableExamples: boolean;
/*
* Parses discriminated unions as undiscriminated unions with literals.
Expand All @@ -21,6 +22,14 @@ export interface ParseOpenAPIOptions {
inlinePathParameters: boolean;
/* Whether or not to preserve original schema Ids in the IR */
preserveSchemaIds: boolean;
/* Whether or not to parse object query parameters. */
objectQueryParameters: boolean;
/* Whether or not to use undiscriminated unions with literals. */
shouldUseUndiscriminatedUnionsWithLiterals: boolean;

// For now, we include an AsyncAPI-specific option here, but this is better
// handled with a discriminated union.
asyncApiNaming: "v1" | "v2";
}

export const DEFAULT_PARSE_OPENAPI_SETTINGS: ParseOpenAPIOptions = {
Expand All @@ -33,5 +42,58 @@ export const DEFAULT_PARSE_OPENAPI_SETTINGS: ParseOpenAPIOptions = {
respectReadonlySchemas: false,
onlyIncludeReferencedSchemas: false,
inlinePathParameters: false,
preserveSchemaIds: false
preserveSchemaIds: false,
objectQueryParameters: false,
shouldUseUndiscriminatedUnionsWithLiterals: false,
asyncApiNaming: "v1"
};

export function getParseOptions({
options,
overrides
}: {
options?: ParseOpenAPIOptions;
overrides?: Partial<ParseOpenAPIOptions>;
}): ParseOpenAPIOptions {
return {
disableExamples: overrides?.disableExamples ?? DEFAULT_PARSE_OPENAPI_SETTINGS.disableExamples,
discriminatedUnionV2:
overrides?.discriminatedUnionV2 ??
options?.discriminatedUnionV2 ??
DEFAULT_PARSE_OPENAPI_SETTINGS.discriminatedUnionV2,
useTitlesAsName:
overrides?.useTitlesAsName ?? options?.useTitlesAsName ?? DEFAULT_PARSE_OPENAPI_SETTINGS.useTitlesAsName,
audiences: overrides?.audiences ?? options?.audiences ?? DEFAULT_PARSE_OPENAPI_SETTINGS.audiences,
optionalAdditionalProperties:
overrides?.optionalAdditionalProperties ??
options?.optionalAdditionalProperties ??
DEFAULT_PARSE_OPENAPI_SETTINGS.optionalAdditionalProperties,
cooerceEnumsToLiterals:
overrides?.cooerceEnumsToLiterals ??
options?.cooerceEnumsToLiterals ??
DEFAULT_PARSE_OPENAPI_SETTINGS.cooerceEnumsToLiterals,
respectReadonlySchemas:
overrides?.respectReadonlySchemas ??
options?.respectReadonlySchemas ??
DEFAULT_PARSE_OPENAPI_SETTINGS.respectReadonlySchemas,
onlyIncludeReferencedSchemas:
overrides?.onlyIncludeReferencedSchemas ??
options?.onlyIncludeReferencedSchemas ??
DEFAULT_PARSE_OPENAPI_SETTINGS.onlyIncludeReferencedSchemas,
inlinePathParameters:
overrides?.inlinePathParameters ??
options?.inlinePathParameters ??
DEFAULT_PARSE_OPENAPI_SETTINGS.inlinePathParameters,
preserveSchemaIds: overrides?.preserveSchemaIds ?? DEFAULT_PARSE_OPENAPI_SETTINGS.preserveSchemaIds,
shouldUseUndiscriminatedUnionsWithLiterals:
overrides?.shouldUseUndiscriminatedUnionsWithLiterals ??
options?.shouldUseUndiscriminatedUnionsWithLiterals ??
DEFAULT_PARSE_OPENAPI_SETTINGS.shouldUseUndiscriminatedUnionsWithLiterals,
objectQueryParameters:
overrides?.objectQueryParameters ??
options?.objectQueryParameters ??
DEFAULT_PARSE_OPENAPI_SETTINGS.objectQueryParameters,
asyncApiNaming:
overrides?.asyncApiNaming ?? options?.asyncApiNaming ?? DEFAULT_PARSE_OPENAPI_SETTINGS.asyncApiNaming
};
}
73 changes: 9 additions & 64 deletions packages/cli/api-importers/openapi/openapi-ir-parser/src/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { DEFAULT_PARSE_ASYNCAPI_SETTINGS, ParseAsyncAPIOptions } from "./asyncap
import { parseAsyncAPI } from "./asyncapi/parse";
import { AsyncAPIV2 } from "./asyncapi/v2";
import { generateIr as generateIrFromV3 } from "./openapi/v3/generateIr";
import { DEFAULT_PARSE_OPENAPI_SETTINGS, ParseOpenAPIOptions } from "./options";
import { getParseOptions, ParseOpenAPIOptions } from "./options";

export type Document = OpenAPIDocument | AsyncAPIDocument;

Expand All @@ -15,28 +15,15 @@ export interface OpenAPIDocument {
value: OpenAPIV3.Document;
source?: OpenApiIrSource;
namespace?: string;
settings?: SpecImportSettings;
settings?: ParseOpenAPIOptions;
}

export interface AsyncAPIDocument {
type: "asyncapi";
value: AsyncAPIV2.Document;
source?: OpenApiIrSource;
namespace?: string;
settings?: SpecImportSettings;
}

export interface SpecImportSettings {
audiences: string[];
shouldUseTitleAsName: boolean;
shouldUseUndiscriminatedUnionsWithLiterals: boolean;
asyncApiNaming?: "v1" | "v2";
optionalAdditionalProperties: boolean;
cooerceEnumsToLiterals: boolean;
objectQueryParameters: boolean;
respectReadonlySchemas: boolean;
onlyIncludeReferencedSchemas: boolean;
inlinePathParameters: boolean;
settings?: ParseOpenAPIOptions;
}

export async function parse({
Expand Down Expand Up @@ -80,7 +67,7 @@ export async function parse({
const openapiIr = generateIrFromV3({
taskContext: context,
openApi: document.value,
options: getParseOptions({ specSettings: document.settings, overrides: options }),
options: getParseOptions({ options: document.settings, overrides: options }),
source,
namespace: document.namespace
});
Expand All @@ -91,9 +78,9 @@ export async function parse({
const parsedAsyncAPI = parseAsyncAPI({
document: document.value,
taskContext: context,
options: getParseOptions({ specSettings: document.settings }),
options: getParseOptions({ options: document.settings, overrides: options }),
source,
asyncApiOptions: getParseAsyncOptions({ specSettings: document.settings }),
asyncApiOptions: getParseAsyncOptions({ options: document.settings }),
namespace: document.namespace
});
if (parsedAsyncAPI.channel != null) {
Expand All @@ -114,57 +101,15 @@ export async function parse({
return ir;
}

export function getParseOptions({
specSettings,
overrides
}: {
specSettings?: SpecImportSettings;
overrides?: Partial<ParseOpenAPIOptions>;
}): ParseOpenAPIOptions {
return {
disableExamples: overrides?.disableExamples ?? DEFAULT_PARSE_OPENAPI_SETTINGS.disableExamples,
discriminatedUnionV2:
overrides?.discriminatedUnionV2 ??
specSettings?.shouldUseUndiscriminatedUnionsWithLiterals ??
DEFAULT_PARSE_OPENAPI_SETTINGS.discriminatedUnionV2,
useTitlesAsName:
overrides?.useTitlesAsName ??
specSettings?.shouldUseTitleAsName ??
DEFAULT_PARSE_OPENAPI_SETTINGS.useTitlesAsName,
audiences: overrides?.audiences ?? specSettings?.audiences ?? DEFAULT_PARSE_OPENAPI_SETTINGS.audiences,
optionalAdditionalProperties:
overrides?.optionalAdditionalProperties ??
specSettings?.optionalAdditionalProperties ??
DEFAULT_PARSE_OPENAPI_SETTINGS.optionalAdditionalProperties,
cooerceEnumsToLiterals:
overrides?.cooerceEnumsToLiterals ??
specSettings?.cooerceEnumsToLiterals ??
DEFAULT_PARSE_OPENAPI_SETTINGS.cooerceEnumsToLiterals,
respectReadonlySchemas:
overrides?.respectReadonlySchemas ??
specSettings?.respectReadonlySchemas ??
DEFAULT_PARSE_OPENAPI_SETTINGS.respectReadonlySchemas,
onlyIncludeReferencedSchemas:
overrides?.onlyIncludeReferencedSchemas ??
specSettings?.onlyIncludeReferencedSchemas ??
DEFAULT_PARSE_OPENAPI_SETTINGS.onlyIncludeReferencedSchemas,
inlinePathParameters:
overrides?.inlinePathParameters ??
specSettings?.inlinePathParameters ??
DEFAULT_PARSE_OPENAPI_SETTINGS.inlinePathParameters,
preserveSchemaIds: overrides?.preserveSchemaIds ?? DEFAULT_PARSE_OPENAPI_SETTINGS.preserveSchemaIds
};
}

function getParseAsyncOptions({
specSettings,
options,
overrides
}: {
specSettings?: SpecImportSettings;
options?: ParseOpenAPIOptions;
overrides?: Partial<ParseAsyncAPIOptions>;
}): ParseAsyncAPIOptions {
return {
naming: overrides?.naming ?? specSettings?.asyncApiNaming ?? DEFAULT_PARSE_ASYNCAPI_SETTINGS.naming
naming: overrides?.naming ?? options?.asyncApiNaming ?? DEFAULT_PARSE_ASYNCAPI_SETTINGS.naming
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
export interface ConvertOpenAPIOptions {
/**
* If true, each error will be made unique per endpoint. This is the preferred behavior for Docs.
* If false, error codes will be shared across endpoints. The side effect is that if more than one error schema is detected for each error code, then the error schema will default to unknown. This is the preferred behavior for SDKs.
*/
enableUniqueErrorsPerEndpoint: boolean;

/**
* If true, the converter will detect frequently headers and add extract them as global headers within
* the IR. This is primarily used for generating SDKs, but disabled for docs as it allows the documentation
*/
detectGlobalHeaders: boolean;

/**
* If true, the converter will generate complex query parameters in the generated Fern Definition.
*/
objectQueryParameters: boolean;

/**
* If true, the converter will respect readonly properties in OpenAPI schemas.
*/
respectReadonlySchemas: boolean;

/**
* If true, the converter will only include schemas referenced by endpoints.
*/
onlyIncludeReferencedSchemas: boolean;

/**
* If true, the converter will include path parameters in the in-lined request.
*/
inlinePathParameters: boolean;
}

export const DEFAULT_CONVERT_OPENAPI_OPTIONS: ConvertOpenAPIOptions = {
enableUniqueErrorsPerEndpoint: false,
detectGlobalHeaders: true,
objectQueryParameters: false,
respectReadonlySchemas: false,
onlyIncludeReferencedSchemas: false,
inlinePathParameters: false
};

export function getConvertOptions({
options,
overrides
}: {
options?: ConvertOpenAPIOptions;
overrides?: Partial<ConvertOpenAPIOptions>;
}): ConvertOpenAPIOptions {
return {
enableUniqueErrorsPerEndpoint:
overrides?.enableUniqueErrorsPerEndpoint ??
options?.enableUniqueErrorsPerEndpoint ??
DEFAULT_CONVERT_OPENAPI_OPTIONS.enableUniqueErrorsPerEndpoint,
detectGlobalHeaders:
overrides?.detectGlobalHeaders ??
options?.detectGlobalHeaders ??
DEFAULT_CONVERT_OPENAPI_OPTIONS.detectGlobalHeaders,
objectQueryParameters:
overrides?.objectQueryParameters ??
options?.objectQueryParameters ??
DEFAULT_CONVERT_OPENAPI_OPTIONS.objectQueryParameters,
respectReadonlySchemas:
overrides?.respectReadonlySchemas ??
options?.respectReadonlySchemas ??
DEFAULT_CONVERT_OPENAPI_OPTIONS.respectReadonlySchemas,
onlyIncludeReferencedSchemas:
overrides?.onlyIncludeReferencedSchemas ??
options?.onlyIncludeReferencedSchemas ??
DEFAULT_CONVERT_OPENAPI_OPTIONS.onlyIncludeReferencedSchemas,
inlinePathParameters:
overrides?.inlinePathParameters ??
options?.inlinePathParameters ??
DEFAULT_CONVERT_OPENAPI_OPTIONS.inlinePathParameters
};
}
Loading

0 comments on commit 438df69

Please sign in to comment.