Skip to content

Commit

Permalink
fix: add support for OpenAPI 3.1.1 to experimental parser
Browse files Browse the repository at this point in the history
  • Loading branch information
mrlubos committed Oct 29, 2024
1 parent 8322b39 commit 3a80b9f
Show file tree
Hide file tree
Showing 23 changed files with 213 additions and 38 deletions.
5 changes: 5 additions & 0 deletions .changeset/tender-windows-smile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hey-api/openapi-ts': patch
---

fix: add support for OpenAPI 3.1.1 to experimental parser
4 changes: 2 additions & 2 deletions packages/openapi-ts/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,6 @@ export default {
defineConfig,
};

export type { OpenApiV3_0_3 } from './openApi/3.0.3';
export type { OpenApiV3_1_0 } from './openApi/3.1.0';
export type { OpenApiV3_0_0 } from './openApi/3.0.x';
export type { OpenApiV3_1_0 } from './openApi/3.1.x';
export type { UserConfig } from './types/config';
2 changes: 1 addition & 1 deletion packages/openapi-ts/src/ir/ir.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { JsonSchemaDraft2020_12 } from '../openApi/3.1.0/types/json-schema-draft-2020-12';
import type { JsonSchemaDraft2020_12 } from '../openApi/3.1.x/types/json-schema-draft-2020-12';
import type { IRMediaType } from './mediaType';

export interface IR {
Expand Down
2 changes: 0 additions & 2 deletions packages/openapi-ts/src/openApi/3.0.3/index.ts

This file was deleted.

7 changes: 0 additions & 7 deletions packages/openapi-ts/src/openApi/3.0.3/parser/index.ts

This file was deleted.

7 changes: 0 additions & 7 deletions packages/openapi-ts/src/openApi/3.0.3/types/spec.d.ts

This file was deleted.

2 changes: 2 additions & 0 deletions packages/openapi-ts/src/openApi/3.0.x/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { parseV3_0_0 } from './parser';
export type { OpenApiV3_0_0 } from './types/spec';
7 changes: 7 additions & 0 deletions packages/openapi-ts/src/openApi/3.0.x/parser/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { IRContext } from '../../../ir/context';
import type { OpenApiV3_0_0 } from '../types/spec';

export const parseV3_0_0 = (context: IRContext<OpenApiV3_0_0>) => {
// TODO
console.log(context.spec);
};

Check warning on line 7 in packages/openapi-ts/src/openApi/3.0.x/parser/index.ts

View check run for this annotation

Codecov / codecov/patch

packages/openapi-ts/src/openApi/3.0.x/parser/index.ts#L5-L7

Added lines #L5 - L7 were not covered by tests
22 changes: 22 additions & 0 deletions packages/openapi-ts/src/openApi/3.0.x/types/spec.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* This is the root object of the {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.4.md#openapi-description OpenAPI Description}.
*
* This object MAY be extended with {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.4.md#specification-extensions Specification Extensions}.
*/
export interface OpenApiV3_0_0 {
/**
* An element to hold various Objects for the OpenAPI Description.
*/
components?: ComponentsObject;
/**
* **REQUIRED**. This string MUST be the {@link https://semver.org/spec/v2.0.0.html semantic version number} of the {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#versions OpenAPI Specification version} that the OpenAPI document uses. The `openapi` field SHOULD be used by tooling specifications and clients to interpret the OpenAPI document. This is _not_ related to the API {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#infoVersion `info.version`} string.
*/
openapi: '3.0.0' | '3.0.1' | '3.0.2' | '3.0.3' | '3.0.4';
// TODO
}

// TODO
export interface ComponentsObject {}

// TODO
export interface SchemaObject {}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export interface OpenApiV3_1_0 {
/**
* **REQUIRED**. This string MUST be the {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#versions version number} of the OpenAPI Specification that the OpenAPI document uses. The `openapi` field SHOULD be used by tooling to interpret the OpenAPI document. This is _not_ related to the API {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#infoVersion `info.version`} string.
*/
openapi: '3.1.0';
openapi: '3.1.0' | '3.1.1';
/**
* The available paths and operations for the API.
*/
Expand Down
138 changes: 137 additions & 1 deletion packages/openapi-ts/src/openApi/__tests__/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
import { afterEach, describe, expect, it, vi } from 'vitest';

import { type OpenApi, parseLegacy } from '..';
import { type OpenApi, parseExperimental, parseLegacy } from '..';
import type { OpenApiV3_0_0 } from '../3.0.x';
import { parseV3_0_0 } from '../3.0.x';
import type { OpenApiV3_1_0 } from '../3.1.x';
import { parseV3_1_0 } from '../3.1.x';
import type { ParserConfig } from '../config';
import * as parseV2 from '../v2';
import * as parseV3 from '../v3';

vi.mock('../3.0.x', () => ({
parseV3_0_0: vi.fn(),
}));
vi.mock('../3.1.x', () => ({
parseV3_1_0: vi.fn(),
}));

const parserConfig: ParserConfig = {
filterFn: {
operation: () => true,
Expand Down Expand Up @@ -93,3 +104,128 @@ describe('parse', () => {
);
});
});

describe('experimentalParser', () => {
afterEach(() => {
vi.restoreAllMocks();
});

it('handles OpenAPI 3.0.0', () => {
const spec: OpenApiV3_0_0 = {
// info: {
// title: '',
// version: '1',
// },
openapi: '3.0.0',
};
parseExperimental({
// @ts-ignore
config: {},
parserConfig,
spec,
});
expect(parseV3_0_0).toHaveBeenCalled();
});

it('handles OpenAPI 3.0.1', () => {
const spec: OpenApiV3_0_0 = {
// info: {
// title: '',
// version: '1',
// },
openapi: '3.0.1',
};
parseExperimental({
// @ts-ignore
config: {},
parserConfig,
spec,
});
expect(parseV3_0_0).toHaveBeenCalled();
});

it('handles OpenAPI 3.0.2', () => {
const spec: OpenApiV3_0_0 = {
// info: {
// title: '',
// version: '1',
// },
openapi: '3.0.2',
};
parseExperimental({
// @ts-ignore
config: {},
parserConfig,
spec,
});
expect(parseV3_0_0).toHaveBeenCalled();
});

it('handles OpenAPI 3.0.3', () => {
const spec: OpenApiV3_0_0 = {
// info: {
// title: '',
// version: '1',
// },
openapi: '3.0.3',
};
parseExperimental({
// @ts-ignore
config: {},
parserConfig,
spec,
});
expect(parseV3_0_0).toHaveBeenCalled();
});

it('handles OpenAPI 3.0.4', () => {
const spec: OpenApiV3_0_0 = {
// info: {
// title: '',
// version: '1',
// },
openapi: '3.0.4',
};
parseExperimental({
// @ts-ignore
config: {},
parserConfig,
spec,
});
expect(parseV3_0_0).toHaveBeenCalled();
});

it('handles OpenAPI 3.1.0', () => {
const spec: OpenApiV3_1_0 = {
info: {
title: '',
version: '1',
},
openapi: '3.1.0',
};
parseExperimental({
// @ts-ignore
config: {},
parserConfig,
spec,
});
expect(parseV3_1_0).toHaveBeenCalled();
});

it('handles OpenAPI 3.1.1', () => {
const spec: OpenApiV3_1_0 = {
info: {
title: '',
version: '1',
},
openapi: '3.1.1',
};
parseExperimental({
// @ts-ignore
config: {},
parserConfig,
spec,
});
expect(parseV3_1_0).toHaveBeenCalled();
});
});
19 changes: 12 additions & 7 deletions packages/openapi-ts/src/openApi/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { IRContext } from '../ir/context';
import type { Config } from '../types/config';
import { type OpenApiV3_0_3, parseV3_0_3 } from './3.0.3';
import { type OpenApiV3_1_0, parseV3_1_0 } from './3.1.0';
import { type OpenApiV3_0_0, parseV3_0_0 } from './3.0.x';
import { type OpenApiV3_1_0, parseV3_1_0 } from './3.1.x';
import type { Client } from './common/interfaces/client';
import type { OpenApi } from './common/interfaces/OpenApi';
import type { ParserConfig } from './config';
Expand Down Expand Up @@ -57,8 +57,6 @@ export function parseLegacy({
);
}

export type ParserOpenApiSpec = OpenApiV3_0_3 | OpenApiV3_1_0;

// TODO: parser - add JSDoc comment
export const parseExperimental = ({
config,
Expand All @@ -72,14 +70,21 @@ export const parseExperimental = ({
const context = new IRContext({
config,
parserConfig,
spec: spec as ParserOpenApiSpec,
spec: spec as Record<string, any>,
});

switch (context.spec.openapi) {
const ctx = context as IRContext<OpenApiV3_0_0 | OpenApiV3_1_0>;
switch (ctx.spec.openapi) {
// TODO: parser - handle Swagger 2.0
case '3.0.0':
case '3.0.1':
case '3.0.2':
case '3.0.3':
parseV3_0_3(context as IRContext<OpenApiV3_0_3>);
case '3.0.4':
parseV3_0_0(context as IRContext<OpenApiV3_0_0>);
break;
case '3.1.0':
case '3.1.1':
parseV3_1_0(context as IRContext<OpenApiV3_1_0>);
break;
default:
Expand Down
30 changes: 21 additions & 9 deletions packages/openapi-ts/src/plugins/@hey-api/schemas/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { compiler } from '../../../compiler';
import type { IRContext } from '../../../ir/context';
import {
ensureValidTypeScriptJavaScriptIdentifier,
type ParserOpenApiSpec,
} from '../../../openApi';
import type { OpenApiV3_1_0 } from '../../../openApi/3.1.0';
import type { SchemaObject as OpenApiV3_1_0SchemaObject } from '../../../openApi/3.1.0/types/spec';
import { ensureValidTypeScriptJavaScriptIdentifier } from '../../../openApi';
import type { OpenApiV3_0_0 } from '../../../openApi/3.0.x';
import type { OpenApiV3_1_0 } from '../../../openApi/3.1.x';
// import type { SchemaObject as OpenApiV3_0_0SchemaObject } from '../../../openApi/3.0.x/types/spec';
import type { SchemaObject as OpenApiV3_1_0SchemaObject } from '../../../openApi/3.1.x/types/spec';
import type { PluginHandler } from '../../types';
import type { Config } from './types';

Expand Down Expand Up @@ -154,6 +153,14 @@ const schemaName = ({
return `${validName}Schema`;
};

const schemasV3_0_0 = (context: IRContext<OpenApiV3_0_0>) => {
if (!context.spec.components) {
return;
}

// TODO: parser - handle OpenAPI 3.0.x
};

Check warning on line 162 in packages/openapi-ts/src/plugins/@hey-api/schemas/plugin.ts

View check run for this annotation

Codecov / codecov/patch

packages/openapi-ts/src/plugins/@hey-api/schemas/plugin.ts#L157-L162

Added lines #L157 - L162 were not covered by tests

const schemasV3_1_0 = (context: IRContext<OpenApiV3_1_0>) => {
if (!context.spec.components) {
return;
Expand Down Expand Up @@ -182,13 +189,18 @@ export const handler: PluginHandler<Config> = ({ context }) => {
});

if (context.spec.openapi) {
const ctx = context as IRContext<ParserOpenApiSpec>;
// TODO: parser - copy-pasted from experimental parser for now
const ctx = context as IRContext<OpenApiV3_0_0 | OpenApiV3_1_0>;
switch (ctx.spec.openapi) {
// TODO: parser - handle Swagger 2.0
case '3.0.0':
case '3.0.1':
case '3.0.2':
case '3.0.3':
// ...
case '3.0.4':
schemasV3_0_0(context as IRContext<OpenApiV3_0_0>);

Check warning on line 200 in packages/openapi-ts/src/plugins/@hey-api/schemas/plugin.ts

View check run for this annotation

Codecov / codecov/patch

packages/openapi-ts/src/plugins/@hey-api/schemas/plugin.ts#L200

Added line #L200 was not covered by tests
break;
case '3.1.0':
case '3.1.1':
schemasV3_1_0(context as IRContext<OpenApiV3_1_0>);
break;
default:
Expand Down
4 changes: 3 additions & 1 deletion packages/openapi-ts/src/plugins/@hey-api/schemas/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { OpenApiV2Schema, OpenApiV3Schema } from '../../../openApi';
import type { SchemaObject as OpenApiV3_1_0SchemaObject } from '../../../openApi/3.1.0/types/spec';
// TODO: parser - add new parser schema object to `nameBuilder`
// import type { SchemaObject as OpenApiV3_0_0SchemaObject } from '../../../openApi/3.0.x/types/spec';
import type { SchemaObject as OpenApiV3_1_0SchemaObject } from '../../../openApi/3.1.x/types/spec';
import type { PluginName } from '../../types';

export interface Config extends PluginName<'@hey-api/schemas'> {
Expand Down

0 comments on commit 3a80b9f

Please sign in to comment.