I made Swagger/OpenAPI type definitions and converter library
Tags: typescript, swagger, openapi, opensource
Published: 2024-04-30 15:52:34

## Outline
I made OpenAPI type definitions and converter library, [`@samchon/openapi`](https://github.com/samchon/openapi).

It supports every versions of Swagger/OpenAPI types, and also support converters to each Swagger/OpenAPI versions. For reference, it has a special type "emended OpenAPI v3.1", and every converters/downgraders intermediates the "emended OpenAPI v3.1" version.

Here is the type definitions of Swagger/OpenAPI specs:

  1. [Swagger v2.0](https://github.com/samchon/openapi/blob/master/src/SwaggerV2.ts)
  2. [OpenAPI v3.0](https://github.com/samchon/openapi/blob/master/src/OpenApiV3.ts)
  3. [OpenAPI v3.1](https://github.com/samchon/openapi/blob/master/src/OpenApiV3_1.ts)
  4. [Emended OpenAPI](https://github.com/samchon/openapi/blob/master/src/OpenApi.ts)

```typescript
import { OpenApi, SwaggerV2, OpenApiV3, OpenApiV3_1 } from "@samchon/openapi";

// original Swagger/OpenAPI document
const input: 
  | SwaggerV2.IDocument
  | OpenApiV3.IDocument
  | OpenApiV3_1.IDocument
  | OpenApi.IDocument = { ... };

// you can convert it to emended OpenAPI v3.1
const output: OpenApi.IDocument = OpenApi.convert(input);

// it is possible to downgrade to Swagger v2 or OpenAPI v3
const v2: SwaggerV2 = OpenApi.downgrade(output, "2.0");
const v3: OpenApiV3 = OpenApi.downgrade(output, "3.0");

// you can utilize it like below
OpenApi.downgrade(OpenApi.convert(v2), "3.0");
OpenApi.downgrade(OpenApi.convert(v3), "2.0");
```




## Why I have made [`@samchon/openapi`](https://github.com/samchon/openapi)?
### [`typia`](https://github.com/samchon/typia)
```typescript
import typia, { tags } from "typia";

console.log(typia.json.application<[IGeometry]>());

interface IGeometry {
  title: string | null;
  position: IPoint<false>;
  size: IPoint<true>;
  scale: IPoint;
  opacity: null | (number & tags.Minimum<0> & tags.Maximum<1>);
}
interface IPoint<Negative extends boolean = false> {
  x: Scalar<Negative>;
  y: Scalar<Negative>;
  z: Scalar<Negative>;
}
type Scalar<Negative extends boolean> = 
  Negative extends true ? number : number & tags.Minimum<0>;
```

> [Typia Playground Link](https://typia.io/playground/?script=JYWwDg9gTgLgBDAnmYBDANHA3g1BzAZzgF84AzKCEOAIiRVRoG4AoFgYwgDsCIAbAKYA6PhDwAKemiEArXlyGowYPsHaoYwbgB4A2gEkA4gKoCYURAF0AfOICUd1i2BcYAqGVTsBcIyZBmFtgscAjAMIIAXHAE5i54cAA+cFwArnx8rKGQBOFaXNH6AAoQLjDannwEAtZZMcAAXgKFJWXa5qk1dQTqUb6trnUQYF7hiNFpGUlw4mkgAEbucABkuIRCALIuoKkg2gAM1itrBJuoAB47ewCM1o4sxM6u7p7e-aWu2gByAngawAA3HwCc5uLgAEyI8wg-AEqC4cAAvORUFUasFQudogBlXqoKDfX7-IG1EJwcZwXGo-GEv6aEl1Bo4vEEn50wFdB4seg+Kl8Gls4nA0ECCFQmGCeFHZFkwX04VgyEIKCdOAAfhSu0WUDgEy1S1WMHwpy2XCuB1qQA)

At first, my library [typia](https://github.com/samchon/typia) has JSON schema generator from TypeScript types. As you know, expression power of TypeScript is extremely wider than other languages, and even greater than JSON schema spec.

Therefore, to make the TypeScript type to JSON schema to work properly, I need very detailed JSON schema's DTO type definitions. However, most of OpenAPI type definition libraries was not such detailed. They have abused `Record<string, any>` types too much, and used `string` type even when clear string literal type be required. Furthermore, have not utilized union type, and just listed up every properties as optional.

This is the 1st reason why I've developed [`@samchon/openapi`](https://github.com/samchon/openapi) with detailed JSON schema definition.

```typescript
export namespace OpenApi {
  export type IJsonSchema =
    | IJsonSchema.IConstant
    | IJsonSchema.IBoolean
    | IJsonSchema.IInteger
    | IJsonSchema.INumber
    | IJsonSchema.IString
    | IJsonSchema.IArray
    | IJsonSchema.ITuple
    | IJsonSchema.IObject
    | IJsonSchema.IReference
    | IJsonSchema.IOneOf
    | IJsonSchema.INull
    | IJsonSchema.IUnknown;
  export namespace IJsonSchema {
    export interface IConstant extends __IAttribute {
      const: boolean | number | string;
    }
    export interface INumber extends __ISignificant<"number"> {
      default?: number;
      minimum?: number;
      maximum?: number;
      exclusiveMinimum?: boolean;
      exclusiveMaximum?: boolean;
      /** @exclusiveMinimum 0 */ multipleOf?: number;
    }
    export interface IString extends __ISignificant<"string"> {
      contentMediaType?: string;
      default?: string;
      format?:
        | "binary"
        | "byte"
        | "password"
        | "regex"
        | "uuid"
        | "email"
        | "hostname"
        | "idn-email"
        | "idn-hostname"
        | "iri"
        | "iri-reference"
        | "ipv4"
        | "ipv6"
        | "uri"
        | "uri-reference"
        | "uri-template"
        | "url"
        | "date-time"
        | "date"
        | "time"
        | "duration"
        | "json-pointer"
        | "relative-json-pointer"
        | (string & {});
      pattern?: string;
      /** @type uint64 */ minLength?: number;
      /** @type uint64 */ maxLength?: number;
    }
  }
}
```

### [`nestia`](https://github.com/samchon/nestia)
![Nestia Editor](https://nestia.io/_next/static/media/stackblitz.173f056f.png)

[`@nestia/editor`](https://nestia.io/docs/editor/) is one of OpenAPI generator that converts Swagger/OpenAPI documents to NestJS project or SDK (Software Development Kit) library for the client developer (one of RFC solution), including mockup simulator like `msw`. Also, it provides enhanced Swagger-UI combined with TypeScript editor like above.

By the way, to accomplish the enough OpenAPI generation, [`@nestia/editor`](https://nestia.io/docs/editor/) had to support every Swagger/OpenAPI versions. I've tried to find proper solution for Swagger/OpenAPI version converter, but all of them had failed to pass my test cases.

Therefore, I've made [`@samchon/openapi`](https://github.com/samchon/openapi) to contain Swagger/OpenAPI converters. Also, as Swagger/OpenAPI specs have too much duplicated expression ways, I have decided to make emended OpenAPI spec that erasing duplicated expressions, and composed converters to transit the emended OpenAI spec.

Here is the example projects generated by `@nestia/editor` and `@samchon/openapi` with many versions of Swagger/OpenAPI specs. Aren't they good to see?

  - BBS (Bullet-in Board System): [SDK & Simulator](https://stackblitz.com/edit/q6tmiu?file=README.md,test%2Fstart.ts&startScript=swagger&startScript=hello) / [NestJS Project](https://stackblitz.com/edit/hxrl8k?file=README.md&startScript=build:test,test)
  - Shopping Mall: [SDK & Simulator](https://stackblitz.com/edit/f655jg?file=README.md,test%2Fstart.ts&startScript=swagger&startScript=hello) / [NestJS Project](https://stackblitz.com/edit/bmssyv?file=README.md&startScript=build:test,test)
  - Clickhouse: [SDK & Simulator](https://stackblitz.com/edit/q4frqj?file=README.md,test%2Fstart.ts&startScript=swagger&startScript=hello) / [NestJS Project](https://stackblitz.com/edit/56cja5-g5hqqs?file=README.md&startScript=build:test,test)
  - Fireblocks: [SDK & Simulator](https://stackblitz.com/edit/pn2u1h?file=README.md,test%2Fstart.ts&startScript=swagger&startScript=hello) / [NestJS Project](https://stackblitz.com/edit/8mhnns?file=README.md&startScript=build:test,test)
  - Uber: [SDK & Simulator](https://stackblitz.com/edit/rzabgy?file=README.md,test%2Fstart.ts&startScript=swagger&startScript=hello) / [NestJS Project](https://stackblitz.com/edit/8px66f?file=README.md&startScript=build:test,test)
  - 아임포트: [SDK & Simulator](https://stackblitz.com/edit/5jpnps?file=README.md,test%2Fstart.ts&startScript=swagger&startScript=hello) / [NestJS Project](https://stackblitz.com/edit/yxdfn7?file=README.md&startScript=build:test,test)
  - 토스페이먼츠: [SDK & Simulator](https://stackblitz.com/edit/kltfqh?file=README.md,test%2Fstart.ts&startScript=swagger&startScript=hello) / [NestJS Project](https://stackblitz.com/edit/y3cpej?file=README.md&startScript=build:test,test)




## Hope your contribution
Developing [`@samchon/openapi`](https://github.com/samchon/openapi), I've accomplished my goal to fully support [`typia`](https://github.com/samchon/typia) and [`nestia`](https://github.com/samchon/nestia) libraries. However, it doesn't mean that [`@samchon/openapi`](https://github.com/samchon/openapi) has fully defined Swagger/OpenAPI types.

I've missed many types, properties that are not required in [`typia`](https://github.com/samchon/typia) and [`nestia`](https://github.com/samchon/nestia) libraries. As those missed features are not essential for Swagger/OpenAPI spec, there may not be big problem for most use cases. 

However, lacking of [`typia`](https://github.com/samchon/typia) and [`nestia`](https://github.com/samchon/nestia) libraries is obvious. If you also need detailed Swagger/OpenAPI spec like me, but you need more detailed types/properties, or found something missed, please take a contribution.