Skip to content

Commit

Permalink
Refactor w/ encoding and transport abstractions
Browse files Browse the repository at this point in the history
  • Loading branch information
amckinney committed Aug 5, 2024
1 parent d7c774d commit 50e9def
Show file tree
Hide file tree
Showing 71 changed files with 431 additions and 473 deletions.
3 changes: 3 additions & 0 deletions packages/cli/cli/src/commands/upgrade/updateApiSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ export async function updateApiSpec({
apis = [generatorConfig.api];
}
for (const api of apis) {
if (generatorsYml.isRawProtobufAPIDefinitionSchema(api)) {
continue;
}
if (typeof api !== "string" && api.origin != null) {
cliContext.logger.info(`Origin found, fetching spec from ${api.origin}`);
await fetchAndWriteFile(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
GeneratorInvocation,
GeneratorsConfiguration
} from "./GeneratorsConfiguration";
import { isRawProtobufAPIDefinitionSchema } from "./isRawProtobufAPIDefinitionSchema";
import { GeneratorGroupSchema } from "./schemas/GeneratorGroupSchema";
import { GeneratorInvocationSchema } from "./schemas/GeneratorInvocationSchema";
import { GeneratorOutputSchema } from "./schemas/GeneratorOutputSchema";
Expand Down Expand Up @@ -77,6 +78,13 @@ async function parseAPIConfiguration(
const apiConfiguration = rawGeneratorsConfiguration.api;
const apiDefinitions: APIDefinitionLocation[] = [];
if (apiConfiguration != null) {
if (isRawProtobufAPIDefinitionSchema(apiConfiguration)) {
// TODO: Implement the Protobuf mapper.
return {
type: "singleNamespace",
definitions: apiDefinitions
};
}
if (typeof apiConfiguration === "string") {
apiDefinitions.push({
path: apiConfiguration,
Expand All @@ -87,6 +95,10 @@ async function parseAPIConfiguration(
});
} else if (Array.isArray(apiConfiguration)) {
for (const definition of apiConfiguration) {
if (isRawProtobufAPIDefinitionSchema(definition)) {
// TODO: Implement the Protobuf mapper.
continue;
}
if (typeof definition === "string") {
apiDefinitions.push({
path: definition,
Expand Down
3 changes: 2 additions & 1 deletion packages/cli/configuration/src/generators-yml/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ export {
} from "./GeneratorsConfiguration";
export { getGeneratorNameOrThrow } from "./getGeneratorName";
export { getLatestGeneratorVersion } from "./getGeneratorVersions";
export { isRawProtobufAPIDefinitionSchema } from "./isRawProtobufAPIDefinitionSchema";
export {
getPathToGeneratorsConfiguration,
loadGeneratorsConfiguration,
loadRawGeneratorsConfiguration
} from "./loadGeneratorsConfiguration";
export { type APIConfigurationSchema } from "./schemas/APIConfigurationSchema";
export { type APIConfigurationSchema, type ProtobufAPIDefinitionSchema } from "./schemas/APIConfigurationSchema";
export { type GeneratorInvocationSchema } from "./schemas/GeneratorInvocationSchema";
export { type GeneratorPublishMetadataSchema } from "./schemas/GeneratorPublishMetadataSchema";
export {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { APIConfigurationSchema, ProtobufAPIDefinitionSchema } from "./schemas/APIConfigurationSchema";

export function isRawProtobufAPIDefinitionSchema(
rawApiConfiguration: APIConfigurationSchema
): rawApiConfiguration is ProtobufAPIDefinitionSchema {
return typeof rawApiConfiguration !== "string" && "proto" in rawApiConfiguration;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,8 @@ import { z } from "zod";
*
* @example
* api: asyncapi.yml
*
* @example
* api: ../../proto/user/v1/user.proto
*/
export const APIDefinitionPathSchema = z
.string()
.describe("Path to the OpenAPI, AsyncAPI, Protobuf or Fern Definition");
export const APIDefinitionPathSchema = z.string().describe("Path to the OpenAPI, AsyncAPI or Fern Definition");

export const APIDefinitionSettingsSchema = z.object({
"use-title": z
Expand All @@ -37,10 +32,6 @@ export type APIDefinitionSettingsSchema = z.infer<typeof APIDefinitionSettingsSc
* api:
* path: asyncapi.yml
* overrides: overrides.yml
*
* @example
* api:
* path: ../../proto/user/v1/user.proto
*/
export const APIDefintionWithOverridesSchema = z.object({
path: APIDefinitionPathSchema,
Expand All @@ -54,19 +45,54 @@ export const APIDefintionWithOverridesSchema = z.object({
settings: z.optional(APIDefinitionSettingsSchema)
});

/**
* @example
* api:
* proto:
* root: proto
* target: proto/user/v1/user.proto
*/
export const ProtobufDefinitionSchema = z.strictObject({
root: z.string().describe("The path to the `.proto` directroy root (e.g. `proto`)."),
target: z
.string()
.describe("The path to the target `.proto` file that defines the API (e.g. `proto/user/v1/user.proto`).")
});

export type ProtobufDefinitionSchema = z.infer<typeof ProtobufDefinitionSchema>;

/**
* @example
* api:
* proto:
* root: proto
* target: proto/user/v1/user.proto
*/
export const ProtobufAPIDefinitionSchema = z.strictObject({
proto: ProtobufDefinitionSchema
});

export type ProtobufAPIDefinitionSchema = z.infer<typeof ProtobufAPIDefinitionSchema>;

/**
* @example
* api:
* - path: openapi.yml
* overrides: overrides.yml
* - openapi.yml
* - proto:
* root: proto
* target: proto/user/v1/user.proto
*/
export const APIDefinitionList = z.array(z.union([APIDefinitionPathSchema, APIDefintionWithOverridesSchema]));
export const APIDefinitionList = z.array(
z.union([APIDefinitionPathSchema, APIDefintionWithOverridesSchema, ProtobufAPIDefinitionSchema])
);

export const APIConfigurationSchema = z.union([
APIDefinitionPathSchema,
APIDefintionWithOverridesSchema,
APIDefinitionList
APIDefinitionList,
ProtobufAPIDefinitionSchema
]);

export type APIConfigurationSchema = z.infer<typeof APIConfigurationSchema>;
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { APIConfigurationSchema, APIDefinitionSettingsSchema } from "./APIConfig
import { GeneratorGroupSchema } from "./GeneratorGroupSchema";
import { GeneratorsOpenAPISchema } from "./GeneratorsOpenAPISchema";
import { OutputMetadataSchema } from "./OutputMetadataSchema";
import { ProtobufSchema } from "./ProtobufSchema";
import { ReadmeSchema } from "./ReadmeSchema";
import { ReviewersSchema, REVIEWERS_KEY } from "./ReviewersSchema";
import { WhitelabelConfigurationSchema } from "./WhitelabelConfigurationSchema";
Expand All @@ -24,8 +23,6 @@ export const GeneratorsConfigurationSchema = z.strictObject({

readme: z.optional(ReadmeSchema),

proto: z.optional(ProtobufSchema),

[DEFAULT_GROUP_GENERATORS_CONFIG_KEY]: z.optional(z.string()),
groups: z.optional(z.record(GeneratorGroupSchema)),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,6 @@ export async function generateIntermediateRepresentation({

await visitObject(file.definitionFile, {
imports: noop,
proto: noop,
docs: (docs) => {
if (docs != null) {
packageTreeGenerator.addDocs(file.fernFilepath, docs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,39 +411,28 @@ export const FernOpenAPIExtension = {
FERN_VERSION: "x-fern-version",

/**
* Allows users to specify the Protobuf source information associated with each type.
*
* If specified on the document node, the Protobuf source information applies to _all_ types
* (unless overridden on the individual type node). This is useful for APIs that define their
* entire Protobuf API in a single file.
*
* x-fern-protobuf:
* file: user/v1/user_service.proto
* package-name: user.v1;
* options:
* csharp:
* namespace: User.V1
*
* If specified on a type node, the Protobuf source information can also customize
* the Protobuf source type name.
* Allows users to specify the encoding of the type. For example, suppose you need to configure
* Protobuf-encoding details like the following:
*
* User:
* properties:
* username:
* type: string
* x-fern-protobuf:
* name: User
* x-fern-encoding:
* proto:
* type: user.v1.User
*/
PROTOBUF: "x-fern-protobuf",
ENCODING: "x-fern-encoding",

/**
* Allows users to configure gRPC services. This must be specified on individual service
* declarations.
*
* x-fern-grpc:
* service-name: UserService
* x-fern-transport:
* grpc:
* file: user/v1/user.proto
*/
GRPC: "x-fern-grpc"
TRANSPORT: "x-fern-transport"
} as const;

export type FernOpenAPIExtension = Values<typeof FernOpenAPIExtension>;
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ export class FernDefinitionFileFormatter {
case "errors":
case "webhooks":
case "channel":
case "proto":
return castedKey;
default:
assertNeverNoThrow(castedKey);
Expand Down Expand Up @@ -170,11 +169,6 @@ export class FernDefinitionFileFormatter {
return "channel";
}
return undefined;
case "proto":
if (indent === 1) {
return "proto";
}
return undefined;
default:
assertNever(previousLocation);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ export async function visitDefinitionFileYamlAst(
channel: noop,
errors: async (errors) => {
await visitErrorDeclarations({ errorDeclarations: errors, visitor, nodePath: ["errors"] });
},
proto: noop
}
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export async function visitPackageMarkerYamlAst(
},
navigation: async (navigation) => {
await visitor.navigation?.(navigation, ["navigation"]);
},
proto: noop
}
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export async function visitHttpService({
}
},
idempotent: noop,
grpc: noop
transport: noop
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export async function visitTypeDeclaration({
audiences: noop,
examples: visitExamples,
validation: noop,
proto: noop
encoding: noop
});
}
},
Expand Down Expand Up @@ -118,7 +118,7 @@ export async function visitTypeDeclaration({
["extra-properties"]: noop,
availability: noop,
audiences: noop,
proto: noop,
encoding: noop,
examples: visitExamples
});
},
Expand Down Expand Up @@ -159,7 +159,7 @@ export async function visitTypeDeclaration({
"base-properties": noop,
availability: noop,
audiences: noop,
proto: noop,
encoding: noop,
examples: visitExamples
});
},
Expand All @@ -182,7 +182,7 @@ export async function visitTypeDeclaration({
},
availability: noop,
audiences: noop,
proto: noop,
encoding: noop,
examples: visitExamples
});
},
Expand All @@ -209,7 +209,7 @@ export async function visitTypeDeclaration({
availability: noop,
audiences: noop,
default: noop,
proto: noop,
encoding: noop,
examples: visitExamples
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { z } from "zod";
import { DeclarationSchema } from "./DeclarationSchema";
import { EncodingSchema } from "./EncodingSchema";
import { ExampleTypeSchema } from "./ExampleTypeSchema";
import { ProtobufSourceTypeSchema } from "./ProtobufSourceTypeSchema";

export const BaseTypeDeclarationSchema = DeclarationSchema.extend({
examples: z.optional(z.array(ExampleTypeSchema)),
proto: z.optional(ProtobufSourceTypeSchema)
encoding: z.optional(EncodingSchema)
});

export type BaseTypeDeclarationSchema = z.infer<typeof BaseTypeDeclarationSchema>;
8 changes: 8 additions & 0 deletions packages/cli/yaml/yaml-schema/src/schemas/EncodingSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { z } from "zod";
import { ProtobufTypeSchema } from "./ProtobufTypeSchema";

export const EncodingSchema = z.strictObject({
proto: z.optional(ProtobufTypeSchema)
});

export type EncodingSchema = z.infer<typeof EncodingSchema>;
13 changes: 7 additions & 6 deletions packages/cli/yaml/yaml-schema/src/schemas/GrpcSchema.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { z } from "zod";
import { ProtobufSourceFileSchema } from "./ProtobufSourceFileSchema";

export const GrpcSchema = ProtobufSourceFileSchema.extend(
z.strictObject({
"service-name": z.string().describe("The name of the gRPC service.")
}).shape
);
export const GrpcSchema = z.strictObject({
file: z
.string()
.describe(
"The relative path of the `.proto` source file that defines the gRPC service (e.g. user/v1/user.proto)"
)
});

export type GrpcSchema = z.infer<typeof GrpcSchema>;
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { z } from "zod";
import { DeclarationWithoutDocsSchema } from "./DeclarationSchema";
import { GrpcSchema } from "./GrpcSchema";
import { HttpEndpointSchema } from "./HttpEndpointSchema";
import { HttpHeaderSchema } from "./HttpHeaderSchema";
import { HttpPathParameterSchema } from "./HttpPathParameterSchema";
import { TransportSchema } from "./TransportSchema";

export const HttpServiceSchema = DeclarationWithoutDocsSchema.extend({
auth: z.boolean(),
Expand All @@ -13,7 +13,7 @@ export const HttpServiceSchema = DeclarationWithoutDocsSchema.extend({
"path-parameters": z.optional(z.record(z.string(), HttpPathParameterSchema)),
idempotent: z.optional(z.boolean()),
headers: z.optional(z.record(HttpHeaderSchema)),
grpc: z.optional(GrpcSchema),
transport: z.optional(TransportSchema),
endpoints: z.record(HttpEndpointSchema)
});

Expand Down

This file was deleted.

This file was deleted.

Loading

0 comments on commit 50e9def

Please sign in to comment.