Skip to content

Commit

Permalink
(chore): introduce x-fern-groups and x-fern-display-name to plumb…
Browse files Browse the repository at this point in the history
… through display name (#3290)

* (chore): introduce  to plumb through display name

* fix
  • Loading branch information
dsinghvi authored Mar 29, 2024
1 parent 1ad0473 commit c562a2f
Show file tree
Hide file tree
Showing 16 changed files with 135 additions and 5 deletions.
9 changes: 9 additions & 0 deletions packages/cli/openapi-ir-sdk/fern/definition/finalIr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ types:
title: optional<string>
description: optional<string>
servers: list<commons.Server>
groups:
docs: |
Top level group information populated through `x-fern-groups`.
type: map<string, SdkGroupInfo>
tags: Tags
hasEndpointsMarkedInternal: boolean
endpoints: list<Endpoint>
Expand All @@ -22,6 +26,11 @@ types:
securitySchemes: map<commons.SecuritySchemeId, commons.SecurityScheme>
globalHeaders: optional<list<GlobalHeader>>

SdkGroupInfo:
properties:
summary: optional<string>
description: optional<string>

GlobalHeader:
properties:
header: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export interface OpenApiIntermediateRepresentation {
title: string | undefined;
description: string | undefined;
servers: FernOpenapiIr.Server[];
/** Top level group information populated through `x-fern-groups`. */
groups: Record<string, FernOpenapiIr.SdkGroupInfo>;
tags: FernOpenapiIr.Tags;
hasEndpointsMarkedInternal: boolean;
endpoints: FernOpenapiIr.Endpoint[];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* This file was auto-generated by Fern from our API Definition.
*/

export interface SdkGroupInfo {
summary: string | undefined;
description: string | undefined;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from "./OpenApiIntermediateRepresentation";
export * from "./SdkGroupInfo";
export * from "./GlobalHeader";
export * from "./Tags";
export * from "./HttpError";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ export const OpenApiIntermediateRepresentation: core.serialization.ObjectSchema<
title: core.serialization.string().optional(),
description: core.serialization.string().optional(),
servers: core.serialization.list(core.serialization.lazyObject(async () => (await import("../../..")).Server)),
groups: core.serialization.record(
core.serialization.string(),
core.serialization.lazyObject(async () => (await import("../../..")).SdkGroupInfo)
),
tags: core.serialization.lazyObject(async () => (await import("../../..")).Tags),
hasEndpointsMarkedInternal: core.serialization.boolean(),
endpoints: core.serialization.list(core.serialization.lazyObject(async () => (await import("../../..")).Endpoint)),
Expand Down Expand Up @@ -49,6 +53,7 @@ export declare namespace OpenApiIntermediateRepresentation {
title?: string | null;
description?: string | null;
servers: serializers.Server.Raw[];
groups: Record<string, serializers.SdkGroupInfo.Raw>;
tags: serializers.Tags.Raw;
hasEndpointsMarkedInternal: boolean;
endpoints: serializers.Endpoint.Raw[];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* This file was auto-generated by Fern from our API Definition.
*/

import * as serializers from "../../..";
import * as FernOpenapiIr from "../../../../api";
import * as core from "../../../../core";

export const SdkGroupInfo: core.serialization.ObjectSchema<serializers.SdkGroupInfo.Raw, FernOpenapiIr.SdkGroupInfo> =
core.serialization.objectWithoutOptionalProperties({
summary: core.serialization.string().optional(),
description: core.serialization.string().optional(),
});

export declare namespace SdkGroupInfo {
interface Raw {
summary?: string | null;
description?: string | null;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from "./OpenApiIntermediateRepresentation";
export * from "./SdkGroupInfo";
export * from "./GlobalHeader";
export * from "./Tags";
export * from "./HttpError";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ describe("Fern Definition Builder", () => {
nonRequestReferencedSchemas: new Set(),
securitySchemes: {},
globalHeaders: [],
groups: {},
channel: []
},
true
Expand Down
4 changes: 4 additions & 0 deletions packages/cli/openapi-ir-to-fern/src/buildChannel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ export function buildChannel({
auth: false
};

if (channel.summary != null) {
convertedChannel["display-name"] = channel.summary;
}

const queryParameters: Record<string, RawSchemas.HttpQueryParameterSchema> = {};
if (channel.handshake.queryParameters.length > 0) {
for (const queryParameter of channel.handshake.queryParameters) {
Expand Down
18 changes: 16 additions & 2 deletions packages/cli/openapi-ir-to-fern/src/buildServices.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { FernOpenapiIr } from "@fern-api/openapi-ir-sdk";
import { buildEndpoint } from "./buildEndpoint";
import { OpenApiIrConverterContext } from "./OpenApiIrConverterContext";
import { getEndpointLocation } from "./utils/getEndpointLocation";
Expand All @@ -15,6 +16,19 @@ export function buildServices(context: OpenApiIrConverterContext): {
if (sdkGroup != null) {
sdkGroups.add(sdkGroup);
}
let group = undefined;
if (endpoint.sdkName != null) {
const groupInfo: Record<string, FernOpenapiIr.SdkGroupInfo> = context.ir.groups;
for (const groupName of endpoint.sdkName.groupName) {
const value = groupInfo[groupName];
if (value == null) {
break;
} else if (value.summary != null || value.description != null) {
group = groupInfo[groupName];
break;
}
}
}
const irTag = tag == null ? undefined : tags.tagsById[tag];
const convertedEndpoint = buildEndpoint({
context,
Expand All @@ -28,8 +42,8 @@ export function buildServices(context: OpenApiIrConverterContext): {
});
if (irTag?.id != null || irTag?.description != null) {
context.builder.setServiceInfo(file, {
displayName: irTag?.id,
docs: irTag?.description ?? undefined
displayName: group?.summary ?? irTag?.id,
docs: group?.description ?? irTag?.description ?? undefined
});
}
}
Expand Down
5 changes: 5 additions & 0 deletions packages/cli/openapi-parser/src/asyncapi/fernExtensions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { Values } from "@fern-api/core-utils";

export const FernAsyncAPIExtension = {
/**
* The x-fern-summary allows you to specify a display name for the websocket channel.
*/
FERN_DISPLAY_NAME: "x-fern-display-name",

/**
* The x-fern-examples allows you to specify examples for the websocket session.
*
Expand Down
4 changes: 3 additions & 1 deletion packages/cli/openapi-parser/src/asyncapi/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ import {
} from "@fern-api/openapi-ir-sdk";
import { TaskContext } from "@fern-api/task-context";
import { OpenAPIV3 } from "openapi-types";
import { getExtension } from "../getExtension";
import { convertSchema } from "../schema/convertSchemas";
import { convertUndiscriminatedOneOf } from "../schema/convertUndiscriminatedOneOf";
import { convertSchemaWithExampleToSchema } from "../schema/utils/convertSchemaWithExampleToSchema";
import { isReferenceObject } from "../schema/utils/isReferenceObject";
import { AsyncAPIV2ParserContext } from "./AsyncAPIParserContext";
import { ExampleWebsocketSessionFactory } from "./ExampleWebsocketSessionFactory";
import { FernAsyncAPIExtension } from "./fernExtensions";
import { getFernExamples, WebsocketSessionExampleExtension } from "./getFernExamples";
import { AsyncAPIV2 } from "./v2";

Expand Down Expand Up @@ -156,7 +158,7 @@ export function parseAsyncAPI({
publish: publishSchema != null ? convertSchemaWithExampleToSchema(publishSchema) : publishSchema,
subscribe:
subscribeSchema != null ? convertSchemaWithExampleToSchema(subscribeSchema) : subscribeSchema,
summary: undefined,
summary: getExtension<string | undefined>(channel, FernAsyncAPIExtension.FERN_DISPLAY_NAME),
path: channelPath,
description: undefined,
examples
Expand Down
9 changes: 7 additions & 2 deletions packages/cli/openapi-parser/src/openapi/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ export async function parse({
variables: {},
nonRequestReferencedSchemas: new Set(),
securitySchemes: {},
globalHeaders: []
globalHeaders: [],
groups: {}
};

for (const spec of workspace.specs) {
Expand Down Expand Up @@ -142,7 +143,11 @@ function merge(
...ir1.securitySchemes,
...ir2.securitySchemes
},
globalHeaders: ir1.globalHeaders != null ? [...ir1.globalHeaders, ...(ir2.globalHeaders ?? [])] : undefined
globalHeaders: ir1.globalHeaders != null ? [...ir1.globalHeaders, ...(ir2.globalHeaders ?? [])] : undefined,
groups: {
...ir1.groups,
...ir2.groups
}
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { TypedExtensionId } from "./id";
export const FernOpenAPIExtension = {
SDK_METHOD_NAME: TypedExtensionId.of<string>("x-fern-sdk-method-name"),
SDK_GROUP_NAME: TypedExtensionId.of<string | string[]>("x-fern-sdk-group-name"),

REQUEST_NAME_V1: "x-request-name",
REQUEST_NAME_V2: "x-fern-request-name",
TYPE_NAME: "x-fern-type-name",
Expand All @@ -12,6 +13,21 @@ export const FernOpenAPIExtension = {
SERVER_NAME_V1: "x-name",
SERVER_NAME_V2: "x-fern-server-name",

/**
* Should align with the OpenAPI spec's `x-fern-sdk-group-name` extension.
* This is a place where you can specify any display names related to the
* configured SDK group names. These display names and descriptions will
* come through in the docs.
*
* x-fern-groups:
* group1:
* display-name: Group 1
* description: This is group 1
* groups:
* group2 # add child groups
*/
GROUPS: TypedExtensionId.of<string | string[]>("x-fern-groups"),

/**
* Filepath that contains any OpenAPI overrides
* that you wan't Fern to add on top of your existing spec.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { OpenAPIV3 } from "openapi-types";
import { z } from "zod";
import { getExtensionAndValidate } from "../../../getExtension";
import { OpenAPIV3ParserContext } from "../OpenAPIV3ParserContext";
import { FernOpenAPIExtension } from "./fernExtensions";

export const XFernGroupsSchema = z.record(
z.string(),
z.object({
summary: z.string().optional(),
description: z.string().optional()
})
);
export type XFernGroupsSchema = z.infer<typeof XFernGroupsSchema>;

export function getFernGroups({
document,
context
}: {
document: OpenAPIV3.Document;
context: OpenAPIV3ParserContext;
}): XFernGroupsSchema | undefined {
return getExtensionAndValidate<XFernGroupsSchema>(
document,
FernOpenAPIExtension.GROUPS,
XFernGroupsSchema,
context
);
}
8 changes: 8 additions & 0 deletions packages/cli/openapi-parser/src/openapi/v3/generateIr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { convertServer } from "./converters/convertServer";
import { ERROR_NAMES } from "./converters/convertToHttpError";
import { ExampleEndpointFactory } from "./converters/ExampleEndpointFactory";
import { FernOpenAPIExtension } from "./extensions/fernExtensions";
import { getFernGroups } from "./extensions/getFernGroups";
import { getGlobalHeaders } from "./extensions/getGlobalHeaders";
import { getVariableDefinitions } from "./extensions/getVariableDefinitions";
import { hasIncompleteExample } from "./hasIncompleteExample";
Expand Down Expand Up @@ -195,9 +196,16 @@ export function generateIr({
taskContext.logger.debug(`Converted schema ${key}`);
}

const groupInfo = getFernGroups({ document: openApi, context });

const ir: OpenApiIntermediateRepresentation = {
title: openApi.info.title,
description: openApi.info.description,
groups: Object.fromEntries(
Object.entries(groupInfo ?? {}).map(([key, value]) => {
return [key, { summary: value.summary ?? undefined, description: value.description ?? undefined }];
})
),
servers: (openApi.servers ?? []).map((server) => convertServer(server)),
tags: {
tagsById: Object.fromEntries(
Expand Down

0 comments on commit c562a2f

Please sign in to comment.