Skip to content

Commit

Permalink
allow for OpenApi config to be passed to constructor
Browse files Browse the repository at this point in the history
  • Loading branch information
AGalabov committed Apr 14, 2022
1 parent 0951405 commit 618ec46
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 9 deletions.
4 changes: 3 additions & 1 deletion spec/simple.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,9 @@ describe('Simple', () => {
schema,
}));

const { components } = new OpenAPIGenerator(definitions).generate();
const { components } = new OpenAPIGenerator(
definitions
).generateComponents();

expect(components?.['schemas']).toEqual(openAPISchemas);
}
Expand Down
56 changes: 48 additions & 8 deletions src/openapi-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ import {
RequestBodyObject,
PathItemObject,
PathObject,
OpenAPIObject,
InfoObject,
ServerObject,
SecurityRequirementObject,
TagObject,
ExternalDocumentationObject,
ComponentsObject,
} from 'openapi3-ts';
import {
ZodArray,
Expand Down Expand Up @@ -46,17 +53,39 @@ type OpenAPIDefinitions =
| { type: 'parameter'; schema: ZodSchema<any> }
| { type: 'route'; route: RouteConfig };

// This is essentially OpenAPIObject without the components and paths keys.
// Omit does not work, since OpenAPIObject extends ISpecificationExtension
// and is infered as { [key: number]: any; [key: string]: any }
interface OpenAPIObjectConfig {
openapi: string;
info: InfoObject;
servers?: ServerObject[];
security?: SecurityRequirementObject[];
tags?: TagObject[];
externalDocs?: ExternalDocumentationObject;
}

export class OpenAPIGenerator {
private schemaRefs: Record<string, SchemaObject> = {};
private paramRefs: Record<string, ParameterObject> = {};
private pathRefs: Record<string, Record<string, PathObject>> = {};

constructor(private definitions: OpenAPIDefinitions[]) {}
constructor(
private definitions: OpenAPIDefinitions[],
private config?: OpenAPIObjectConfig
) {}

generateDocs(): OpenAPIObject {
if (!this.config) {
throw new Error(
'No config was provided when creating the OpenAPIGenerator'
);
}

generate(): SchemasObject {
this.definitions.forEach((definition) => this.generateSingle(definition));

return {
...this.config,
components: {
schemas: this.schemaRefs,
parameters: this.paramRefs,
Expand All @@ -65,6 +94,17 @@ export class OpenAPIGenerator {
};
}

generateComponents(): ComponentsObject {
this.definitions.forEach((definition) => this.generateSingle(definition));

return {
components: {
schemas: this.schemaRefs,
parameters: this.paramRefs,
},
};
}

private generateSingle(
definition: OpenAPIDefinitions
): SchemaObject | ParameterObject | ReferenceObject {
Expand Down Expand Up @@ -104,20 +144,18 @@ export class OpenAPIGenerator {

const required = !zodSchema.isOptional() && !zodSchema.isNullable();

const schema = this.generateSingleSchema(zodSchema, false);
const schema = this.generateSingleSchema(zodSchema, false, false);

const result: ParameterObject = {
in: 'path',
// TODO: Is this valid? I think so since parameters are only defined from registries
name: schemaName as string,
schema,
required,
// TODO: Fix types and check for possibly wrong data
...(metadata
? (this.buildMetadata(metadata) as Partial<ParameterObject>)
: {}),
// TODO: Is this needed
required,
// allowReserved: true,
};

if (saveIfNew && schemaName) {
Expand All @@ -127,9 +165,11 @@ export class OpenAPIGenerator {
return result;
}

// TODO: Named parameters and smaller functions
private generateSingleSchema(
zodSchema: ZodSchema<any>,
saveIfNew: boolean
saveIfNew: boolean,
withMetaData = true
): SchemaObject | ReferenceObject {
const innerSchema = this.unwrapOptional(zodSchema);
const metadata = zodSchema._def.openapi
Expand All @@ -152,7 +192,7 @@ export class OpenAPIGenerator {
!!metadata?.type,
saveIfNew
),
...(metadata ? this.buildMetadata(metadata) : {}),
...(withMetaData && metadata ? this.buildMetadata(metadata) : {}),
},
isUndefined
);
Expand Down

0 comments on commit 618ec46

Please sign in to comment.