@asteasolutions/zod-to-openapi
Advanced tools
Comparing version 1.0.0-rc.1 to 1.0.0-rc.2
export * from './zod-extensions'; | ||
export { OpenAPIGenerator } from './openapi-generator'; | ||
export { OpenAPIRegistry } from './openapi-registry'; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -23,2 +23,1 @@ "use strict"; | ||
Object.defineProperty(exports, "OpenAPIRegistry", { enumerable: true, get: function () { return openapi_registry_1.OpenAPIRegistry; } }); | ||
//# sourceMappingURL=index.js.map |
@@ -10,2 +10,1 @@ export declare function isUndefined<T>(value: any): value is undefined; | ||
}>>(object: T, predicate: (val: T[keyof T]) => boolean): Result; | ||
//# sourceMappingURL=lodash.d.ts.map |
@@ -40,2 +40,1 @@ "use strict"; | ||
exports.omitBy = omitBy; | ||
//# sourceMappingURL=lodash.js.map |
@@ -45,2 +45,1 @@ import { OpenAPIObject, InfoObject, ServerObject, SecurityRequirementObject, TagObject, ExternalDocumentationObject, ComponentsObject } from 'openapi3-ts'; | ||
export {}; | ||
//# sourceMappingURL=openapi-generator.d.ts.map |
@@ -373,2 +373,1 @@ "use strict"; | ||
exports.OpenAPIGenerator = OpenAPIGenerator; | ||
//# sourceMappingURL=openapi-generator.js.map |
@@ -52,2 +52,1 @@ import { OperationObject } from 'openapi3-ts'; | ||
export {}; | ||
//# sourceMappingURL=openapi-registry.d.ts.map |
@@ -47,2 +47,1 @@ "use strict"; | ||
exports.OpenAPIRegistry = OpenAPIRegistry; | ||
//# sourceMappingURL=openapi-registry.js.map |
@@ -16,2 +16,1 @@ import { ParameterObject, SchemaObject } from 'openapi3-ts'; | ||
export declare function extendZodWithOpenApi(zod: typeof z): void; | ||
//# sourceMappingURL=zod-extensions.d.ts.map |
@@ -35,2 +35,1 @@ "use strict"; | ||
exports.extendZodWithOpenApi = extendZodWithOpenApi; | ||
//# sourceMappingURL=zod-extensions.js.map |
{ | ||
"name": "@asteasolutions/zod-to-openapi", | ||
"version": "1.0.0-rc.1", | ||
"version": "1.0.0-rc.2", | ||
"description": "Builds OpenAPI schemas from Zod schemas", | ||
@@ -12,7 +12,22 @@ "main": "dist/index.js", | ||
], | ||
"keywords": [ | ||
"typescript", | ||
"schema", | ||
"type", | ||
"openapi", | ||
"zod" | ||
], | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/asteasolutions/zod-to-openapi" | ||
}, | ||
"homepage": "https://github.com/asteasolutions/zod-to-openapi", | ||
"scripts": { | ||
"build": "tsc", | ||
"build": "tsc -p tsconfig.build.json", | ||
"test": "jest", | ||
"prepublishOnly": "npm run build" | ||
}, | ||
"dependencies": { | ||
"openapi3-ts": "^2.0.2" | ||
}, | ||
"peerDependencies": { | ||
@@ -26,3 +41,2 @@ "zod": "~3.14.4" | ||
"jest": "^27.5.1", | ||
"openapi3-ts": "^2.0.2", | ||
"ts-jest": "^27.1.4", | ||
@@ -29,0 +43,0 @@ "typescript": "^4.6.3", |
256
README.md
# Zod to OpenAPI | ||
A library that uses zod schemas to generate an Open API Swagger documentation. | ||
1. [Purpose](#purpose) | ||
2. [Usage](#usage) | ||
1. [Installation](#installation) | ||
2. [Expanding the zod functionalities](#expanding-the-zod-functionalities) | ||
3. [Generating components](#generating-components) | ||
4. [Registering schema definitions](#registering-schema-definitions) | ||
5. [Registering parameter definitions](#registering-parameter-definitions) | ||
6. [Generating a full OpenAPI document](#generating-a-full-openapi-document) | ||
- [Registering a path](#registering-a-path) | ||
7. [A full example](#a-full-example) | ||
8. [Adding it as part of your build](#adding-it-as-part-of-your-build) | ||
3. [Technologies](#technologies) | ||
<!-- TODO: Something about a CHANGELOG --> | ||
## Purpose | ||
We at [Astea Solutions](https://asteasolutions.com/) made this library because of the duplication of work when creating a documentation for an API that uses `zod` to validate request input and output. | ||
## Usage | ||
### Installation | ||
```shell | ||
npm install @asteasolutions/zod-to-openapi | ||
# or | ||
yarn add @asteasolutions/zod-to-openapi | ||
``` | ||
### Expanding the zod functionalities | ||
In order to specify some OpenAPI specific metadata you should use the exported `extendZodWithOpenApi` | ||
function with your own instance of `zod`. | ||
Note: This should be done only once in a common-entrypoint file of your project (for example an `index.ts`/`app.ts`) | ||
```ts | ||
import { extendZodWithOpenApi } from '@asteasolutions/zod-to-openapi'; | ||
import { z } from 'zod'; | ||
extendZodWithOpenApi(z); | ||
// We can now use `.openapi()` to specify OpenAPI metadata | ||
z.string().openapi({ description: 'Some string' }); | ||
``` | ||
### Generating components | ||
The `OpenAPIRegistry` class is used as a utility for creating definitions that are then to be used to | ||
generate the OpenAPI document using the `OpenAPIGenerator` class. In order to generate components the `generateComponents` method should be used. | ||
```ts | ||
import { | ||
OpenAPIRegistry, | ||
OpenAPIGenerator, | ||
} from '@asteasolutions/zod-to-openapi'; | ||
const registry = new OpenAPIRegistry(); | ||
// Register definitions here | ||
const generator = new OpenAPIGenerator(registry.definitions); | ||
return generator.generateComponents(); | ||
``` | ||
### Registering schema definitions | ||
An OpenAPI schema should be registered using the `register` method of an `OpenAPIRegistry` instance. | ||
```ts | ||
const UserSchema = registry.register( | ||
'User', | ||
z.object({ | ||
id: z.string().openapi({ | ||
example: '1212121', | ||
}), | ||
name: z.string().openapi({ | ||
example: 'John Doe', | ||
}), | ||
age: z.number().openapi({ | ||
example: 42, | ||
}), | ||
}) | ||
); | ||
``` | ||
The YAML equivalent of the schema above would be: | ||
```yaml | ||
User: | ||
type: object | ||
properties: | ||
id: | ||
type: string | ||
example: '1212121' | ||
name: | ||
type: string | ||
example: John Doe | ||
age: | ||
type: number | ||
example: 42 | ||
required: | ||
- id | ||
- name | ||
- age | ||
``` | ||
Note: All properties defined inside `.openapi` of a single zod schema are applied at their appropriate schema level. | ||
The result would be an object like `{ components: { schemas: { User: {...} } } }`. The key for the object is the value of the first argument passed to `.register` (in this case - `User`). | ||
The resulting schema can then be referenced by using `$ref: #/components/schemas/User` in an existing OpenAPI JSON. | ||
### Registering parameter definitions | ||
An OpenAPI parameter (query/path/header) should be registered using the `registerParameter` method of an `OpenAPIRegistry` instance. | ||
```ts | ||
const UserIdSchema = registry.registerParameter( | ||
'UserId', | ||
z.string().openapi({ | ||
param: { | ||
name: 'id', | ||
in: 'path', | ||
}, | ||
example: '1212121', | ||
}) | ||
); | ||
``` | ||
Note: Parameter properties are more specific to those of an OpenAPI schema. In order to define properties that apply to the parameter itself, use the `param` property of `.openapi`. Any properties provided outside of `param` would be applied to the schema for this parameter. | ||
The YAML equivalent of the schema above would be: | ||
```yaml | ||
UserId: | ||
in: path | ||
name: id | ||
schema: | ||
type: string | ||
example: '1212121' | ||
required: true | ||
``` | ||
The result would be an object like `{ components: { parameters: { UserId: {...} } } }`. The key for the object is the value of the first argument passed to `.registerParameter` (in this case - `UserId`). | ||
The resulting schema can then be referenced by using `$ref: #/components/parameters/UserId` in an existing OpenAPI JSON. | ||
### Generating a full OpenAPI document | ||
A full OpenAPI document can be generated using the `generateDocument` method of an `OpenAPIGenerator` instance. It takes one argument - the document config. It may look something like this: | ||
```ts | ||
return generator.generateDocument({ | ||
openapi: '3.0.0', | ||
info: { | ||
version: '1.0.0', | ||
title: 'My API', | ||
description: 'This is the API', | ||
}, | ||
servers: [{ url: 'v1' }], | ||
}); | ||
``` | ||
#### Registering a path | ||
An OpenAPI path should be registered using the `registerPath` method of an `OpenAPIRegistry` instance. | ||
```ts | ||
registry.registerPath({ | ||
method: 'get', | ||
path: '/users/{id}', | ||
description: 'Get user data by its id', | ||
summary: 'Get a single user', | ||
request: { | ||
params: z.object({ id: UserIdSchema }), | ||
}, | ||
responses: { | ||
200: { | ||
mediaType: 'application/json', | ||
schema: UserSchema.openapi({ | ||
description: 'Object with user data.', | ||
}), | ||
}, | ||
204: z.void(), | ||
}, | ||
}); | ||
``` | ||
The YAML equivalent of the schema above would be: | ||
```yaml | ||
'/users/{id}': | ||
get: | ||
description: Get user data by its id | ||
summary: Get a single user | ||
parameters: | ||
- in: path | ||
name: id | ||
schema: | ||
type: string | ||
example: '1212121' | ||
required: true | ||
responses: | ||
'200': | ||
description: Object with user data. | ||
content: | ||
application/json: | ||
schema: | ||
$ref: '#/components/schemas/User' | ||
'204': | ||
description: No content - successful operation | ||
``` | ||
The library specific properties for `registerPath` are `method`, `path`, `request` and `responses`. Everything else gets directly appended to the path definition. | ||
- `method` - One of `get`, `post`, `put`, `delete` and `patch`; | ||
- `path` - a string - being the path of the endpoint; | ||
- `request` - an optional object with optional `body`, `params`, `query` and `headers` keys, | ||
- `query`, `params` - being instances of `ZodObject` | ||
- `body` - being any `zod` instance | ||
- `headers` - an array of `zod` instances | ||
- `responses` - an object where the key is the status code or `default` and the value is either: | ||
- an instance of `ZodVoid` - meaning a no content response | ||
- an object with `mediaType` (a string like `application/json`) and a `schema` of any zod type | ||
### A full example | ||
A full example code can be found [here](./example/index.ts). And the YAML representation of its result - [here](./example/openapi-docs.yml) | ||
### Adding it as part of your build | ||
In a file inside your project you can have a file like so: | ||
```ts | ||
export const registry = new OpenAPIRegistry(); | ||
export function generateOpenAPI() { | ||
const config = {...}; // your config comes here | ||
return new OpenAPIGenerator(schemas.definitions).generateDocument(config); | ||
} | ||
``` | ||
You then use the exported `registry` object to register all schemas, parameters and routes where appropriate. | ||
Then you can create a script that can execute the exported `generateOpenAPI` function. This script can be executed as a part of your build step so that it can write the result to some file like `openapi-docs.json`. | ||
## Technologies | ||
- [Typescript](https://www.typescriptlang.org/) | ||
- [Zod 3.x](https://github.com/colinhacks/zod) | ||
- [OpenAPI 3.x](https://github.com/metadevpro/openapi3-ts) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
8
1
259
0
0
37252
2
13
+ Addedopenapi3-ts@^2.0.2
+ Addedopenapi3-ts@2.0.2(transitive)
+ Addedyaml@1.10.2(transitive)