Skip to content

Commit

Permalink
Merge pull request #9 from maxholman/qol20241013
Browse files Browse the repository at this point in the history
chore: switch to openapi3-ts which requires no patches
  • Loading branch information
maxholman authored Oct 13, 2024
2 parents 0cddbd1 + e297284 commit ca5e341
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 52 deletions.
4 changes: 2 additions & 2 deletions lib/build.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { writeFile } from 'node:fs/promises';
import prettierConfig from '@block65/eslint-config/prettier';
import type { OpenAPIV3_1 } from 'openapi-types';
import type { oas31 } from 'openapi3-ts';
import { format as prettier } from 'prettier';
import { processOpenApiDocument } from './process-document.js';

Expand All @@ -11,7 +11,7 @@ export async function build(
) {
const apischema = (await import(inputFile, {
with: { type: 'json' },
})) as { default: OpenAPIV3_1.Document };
})) as { default: oas31.OpenAPIObject };

const banner = `
/**
Expand Down
33 changes: 17 additions & 16 deletions lib/process-document.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable no-restricted-syntax */
import { join, relative } from 'node:path';
import { $RefParser } from '@apidevtools/json-schema-ref-parser';
import type { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';
import type { oas30, oas31 } from 'openapi3-ts';
import toposort from 'toposort';
import {
InterfaceDeclaration,
Expand All @@ -14,6 +14,7 @@ import {
VariableDeclarationKind,
Writers,
} from 'ts-morph';
import type { Simplify } from 'type-fest';
import { registerTypesFromSchema, schemaToType } from './process-schema.js';
import {
castToValidJsIdentifier,
Expand Down Expand Up @@ -60,7 +61,7 @@ function createUnion(...types: (string | undefined)[]) {

export async function processOpenApiDocument(
outputDir: string,
schema: OpenAPIV3_1.Document,
schema: Simplify<oas31.OpenAPIObject>,
tags?: string[] | undefined,
) {
const project = new Project();
Expand Down Expand Up @@ -191,22 +192,22 @@ export async function processOpenApiDocument(
);
}

for (const [path, pathItemObject] of Object.entries(schema.paths || {})) {
for (const [path, pathItemObject] of Object.entries<oas31.PathItemObject>(
schema.paths || {},
)) {
if (pathItemObject) {
for (const [method, operationObject] of Object.entries(
pathItemObject,
).filter(
([, o]) =>
!tags ||
(typeof o === 'object' && 'tags' in o
? o.tags.some((t) => tags.includes(t))
: false),
)) {
for (const [method, operationObject] of Object.entries(pathItemObject)
// ensure op is an object
.filter(
(e): e is [string, oas31.OperationObject] => typeof e[1] === 'object',
)
// tags
.filter(([, o]) => !tags || o.tags?.some((t) => tags?.includes(t)))) {
if (
typeof operationObject === 'object' &&
'operationId' in operationObject
) {
const pathParameters: OpenAPIV3.ParameterObject[] = [];
const pathParameters: oas30.ParameterObject[] = [];

const commandName = pascalCase(
operationObject.operationId.replace(/command$/i, ''),
Expand Down Expand Up @@ -258,13 +259,13 @@ export async function processOpenApiDocument(
? operationObject.requestBody
: undefined;

const queryParameters: OpenAPIV3.ParameterObject[] = [];
const queryParameters: oas30.ParameterObject[] = [];

for (const parameter of [
...(operationObject.parameters || []),
...(pathItemObject.parameters || []),
]) {
const resolvedParameter: OpenAPIV3.ParameterObject =
const resolvedParameter: oas30.ParameterObject =
'$ref' in parameter ? refs.get(parameter.$ref) : parameter;

if (resolvedParameter.in === 'path') {
Expand Down Expand Up @@ -481,7 +482,7 @@ export async function processOpenApiDocument(
}

for (const [statusCode, response] of Object.entries(
operationObject.responses,
operationObject.responses || {},
).filter(([s]) => s.startsWith('2'))) {
// early out if response is 204
if (statusCode === '204') {
Expand Down
41 changes: 22 additions & 19 deletions lib/process-schema.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable no-console */
import type { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';
import type { oas31, oas30 } from 'openapi3-ts';
import {
Writers,
type CodeBlockWriter,
Expand All @@ -24,9 +24,7 @@ function maybeWithNullUnion(type: string | WriterFunction, withNull = false) {
return withNull && type !== 'null' ? Writers.unionType(type, 'null') : type;
}

function schemaTypeIsNull(
schema: OpenAPIV3.SchemaObject | OpenAPIV3_1.SchemaObject,
) {
function schemaTypeIsNull(schema: oas30.SchemaObject | oas31.SchemaObject) {
return (
schema.type === 'null' ||
('nullable' in schema && schema.nullable) ||
Expand Down Expand Up @@ -63,12 +61,9 @@ export function schemaToType(
string,
InterfaceDeclaration | TypeAliasDeclaration | EnumDeclaration
>,
parentSchema: OpenAPIV3_1.SchemaObject | OpenAPIV3.SchemaObject,
parentSchema: oas31.SchemaObject | oas30.SchemaObject,
propertyName: string,
schemaObject:
| OpenAPIV3_1.SchemaObject
| OpenAPIV3.SchemaObject
| OpenAPIV3_1.ReferenceObject,
schemaObject: oas31.SchemaObject | oas30.SchemaObject | oas31.ReferenceObject,
options: {
exactOptionalPropertyTypes?: boolean;
booleanAsStringish?: boolean;
Expand Down Expand Up @@ -127,9 +122,19 @@ export function schemaToType(
},
]
: []),
...(schemaObject.example

// 3
...('example' in schemaObject
? [{ tagName: 'example', text: String(schemaObject.example) }]
: []),

// 3.1
...('examples' in schemaObject
? schemaObject.examples.map((example) => ({
tagName: 'example',
text: JSON.stringify(example),
}))
: []),
...(schemaObject.deprecated ? [{ tagName: 'deprecated' }] : []),
];

Expand Down Expand Up @@ -168,13 +173,11 @@ export function schemaToType(
items: {},
...schemaObject,
type: 'array',
} satisfies
| OpenAPIV3.ArraySchemaObject
| OpenAPIV3_1.ArraySchemaObject)
: {
} satisfies typeof schemaObject)
: ({
...schemaObject,
type,
};
} satisfies typeof schemaObject);

return (
schemaToType(typesAndInterfaces, schemaObject, name, schema).type ||
Expand Down Expand Up @@ -420,10 +423,10 @@ export function registerTypesFromSchema(
typesFile: SourceFile,
schemaName: string,
schemaObject:
| OpenAPIV3.SchemaObject
| OpenAPIV3.ReferenceObject
| OpenAPIV3_1.SchemaObject
| OpenAPIV3_1.ReferenceObject,
| oas30.SchemaObject
| oas30.ReferenceObject
| oas31.SchemaObject
| oas31.ReferenceObject,
) {
// deal with refs
if ('$ref' in schemaObject) {
Expand Down
14 changes: 6 additions & 8 deletions lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import camelcase from 'camelcase';
import type { OpenAPIV3_1 } from 'openapi-types';
import type { oas31 } from 'openapi3-ts';
import wrap from 'word-wrap';

export function maybeJsDocDescription(
Expand All @@ -8,19 +8,17 @@ export function maybeJsDocDescription(
return str.length > 0 ? ['', ...str].filter(Boolean).join(' - ').trim() : '';
}

export function isReferenceObject(
obj: unknown,
): obj is OpenAPIV3_1.ReferenceObject {
export function isReferenceObject(obj: unknown): obj is oas31.ReferenceObject {
return typeof obj === 'object' && obj !== null && '$ref' in obj;
}

export function getDependency(obj: unknown): string | undefined {
return isReferenceObject(obj) ? obj.$ref : undefined;
}

export function isNotReferenceObject<
T extends OpenAPIV3_1.ReferenceObject | unknown,
>(obj: T): obj is Exclude<T, OpenAPIV3_1.ReferenceObject> {
export function isNotReferenceObject<T extends oas31.ReferenceObject | unknown>(
obj: T,
): obj is Exclude<T, oas31.ReferenceObject> {
return !isReferenceObject(obj);
}

Expand All @@ -29,7 +27,7 @@ export function isNotNullOrUndefined<T>(obj: T | null | undefined): obj is T {
}

export function getDependents(
obj: OpenAPIV3_1.ReferenceObject | OpenAPIV3_1.SchemaObject,
obj: oas31.ReferenceObject | oas31.SchemaObject,
): string[] {
const strOnly = (x: string | undefined): x is string => typeof x === 'string';

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"eslint-plugin-react": "^7.37.1",
"eslint-plugin-react-hooks": "^4.6.2",
"js-yaml": "^4.1.0",
"openapi-types": "^12.1.3",
"openapi3-ts": "^4.4.0",
"prettier": "^2.8.8",
"typescript": "^5.6.2",
"undici": "^6.19.8",
Expand Down
21 changes: 15 additions & 6 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit ca5e341

Please sign in to comment.