Zod スキーマを使用して OpenAPI v3.x ドキュメントを作成するための Typescript ライブラリ
npm
、 yarn
またはpnpm
経由でインストールします。
npm install zod zod-openapi
# # or
yarn add zod zod-openapi
# # or
pnpm install zod zod-openapi
これにより、Zod が変更され、追加の.openapi()
メソッドが追加されます。これをエントリ ポイントの先頭で呼び出します。これは、好みに応じて 2 つの異なる方法で実現できます。
import 'zod-openapi/extend' ;
import { z } from 'zod' ;
z . string ( ) . openapi ( { description : 'hello world!' , example : 'hello world' } ) ;
これは、ターゲットとする Zod の特定のインスタンス、または別のライブラリの Zod インスタンスがある場合に便利です。
import { z } from 'zod' ;
import { extendZodWithOpenApi } from 'zod-openapi' ;
extendZodWithOpenApi ( z ) ;
z . string ( ) . openapi ( { description : 'hello world!' , example : 'hello world' } ) ;
.openapi()
.openapi()
メソッドを使用して、特定の Zod タイプにメタデータを追加します。 .openapi()
メソッドは、次のオプションを持つオブジェクトを受け取ります。
オプション | 説明 |
---|---|
OpenAPI オプション | これには、SchemaObject に設定する任意のオプションが適用されます。 |
effectType | Zod エフェクトの作成タイプをオーバーライドするために使用します。 |
header | 応答ヘッダーのメタデータを提供するために使用します |
param | リクエストパラメータのメタデータを提供するために使用します |
ref | これを使用して、スキーマを再利用可能なコンポーネントとして自動登録します。 |
refType | これを使用して、ドキュメント内で参照されていないコンポーネントの作成タイプを設定します。 |
type | これを使用して、生成された型をオーバーライドします。これを指定すると、メタデータは生成されません。 |
unionOneOf | true に設定すると、単一の ZodUnion がanyOf ではなくoneOf 出力します。グローバル オプションについては、「CreateDocumentOptions」を参照してください。 |
createDocument
OpenAPI ドキュメント オブジェクトを作成します
import 'zod-openapi/extend' ;
import { z } from 'zod' ;
import { createDocument } from 'zod-openapi' ;
const jobId = z . string ( ) . openapi ( {
description : 'A unique identifier for a job' ,
example : '12345' ,
ref : 'jobId' ,
} ) ;
const title = z . string ( ) . openapi ( {
description : 'Job title' ,
example : 'My job' ,
} ) ;
const document = createDocument ( {
openapi : '3.1.0' ,
info : {
title : 'My API' ,
version : '1.0.0' ,
} ,
paths : {
'/jobs/{jobId}' : {
put : {
requestParams : { path : z . object ( { jobId } ) } ,
requestBody : {
content : {
'application/json' : { schema : z . object ( { title } ) } ,
} ,
} ,
responses : {
'200' : {
description : '200 OK' ,
content : {
'application/json' : { schema : z . object ( { jobId , title } ) } ,
} ,
} ,
} ,
} ,
} ,
} ,
} ) ;
{
"openapi" : " 3.1.0 " ,
"info" : {
"title" : " My API " ,
"version" : " 1.0.0 "
},
"paths" : {
"/jobs/{jobId}" : {
"put" : {
"parameters" : [
{
"in" : " path " ,
"name" : " jobId " ,
"description" : " A unique identifier for a job " ,
"schema" : {
"$ref" : " #/components/schemas/jobId "
}
}
],
"requestBody" : {
"content" : {
"application/json" : {
"schema" : {
"type" : " object " ,
"properties" : {
"title" : {
"type" : " string " ,
"description" : " Job title " ,
"example" : " My job "
}
},
"required" : [ " title " ]
}
}
}
},
"responses" : {
"200" : {
"description" : " 200 OK " ,
"content" : {
"application/json" : {
"schema" : {
"type" : " object " ,
"properties" : {
"jobId" : {
"$ref" : " #/components/schemas/jobId "
},
"title" : {
"type" : " string " ,
"description" : " Job title " ,
"example" : " My job "
}
},
"required" : [ " jobId " , " title " ]
}
}
}
}
}
}
}
},
"components" : {
"schemas" : {
"jobId" : {
"type" : " string " ,
"description" : " A unique identifier for a job " ,
"example" : " 12345 "
}
}
}
}
createDocument
ドキュメントの作成方法を変更するために使用できるオプションのCreateDocumentOptions
引数を取ります。
const document = createDocument ( details , {
defaultDateSchema : { type : 'string' , format : 'date-time' } , // defaults to { type: 'string' }
unionOneOf : true , // defaults to false. Forces all ZodUnions to output oneOf instead of anyOf. An `.openapi()` `unionOneOf` value takes precedence over this one.
} ) ;
createSchema
登録されているコンポーネントとともに OpenAPI スキーマ オブジェクトを作成します。 OpenAPI 3.1.0 スキーマ オブジェクトは、JSON スキーマと完全な互換性があります。
import 'zod-openapi/extend' ;
import { z } from 'zod' ;
import { createSchema } from 'zod-openapi' ;
const jobId = z . string ( ) . openapi ( {
description : 'A unique identifier for a job' ,
example : '12345' ,
ref : 'jobId' ,
} ) ;
const title = z . string ( ) . openapi ( {
description : 'Job title' ,
example : 'My job' ,
} ) ;
const job = z . object ( {
jobId ,
title ,
} ) ;
const { schema , components } = createSchema ( job ) ;
{
"schema" : {
"type" : " object " ,
"properties" : {
"jobId" : {
"$ref" : " #/components/schemas/jobId "
},
"title" : {
"type" : " string " ,
"description" : " Job title " ,
"example" : " My job "
}
},
"required" : [ " jobId " , " title " ]
},
"components" : {
"jobId" : {
"type" : " string " ,
"description" : " A unique identifier for a job " ,
"example" : " 12345 "
}
}
}
createSchema
オプションのCreateSchemaOptions
パラメーターを受け取ります。このパラメーターは、次のオプションとともに CreateDocumentOptions と同じオプションも受け取ることができます。
const { schema , components } = createSchema ( job , {
schemaType : 'input' ; // This controls whether this should be rendered as a request (`input`) or response (`output`). Defaults to `output`
openapi: '3.0.0' ; // OpenAPI version to use, defaults to `'3.1.0'`
components: { jobId : z . string ( ) } // Additional components to use and create while rendering the schema
componentRefPath: '#/definitions/' // Defaults to #/components/schemas/
} )
クエリ、パス、ヘッダー、および Cookie パラメータは、次のようにmethod
キーの下のrequestParams
キーを使用して作成できます。
createDocument ( {
paths : {
'/jobs/{a}' : {
put : {
requestParams : {
path : z . object ( { a : z . string ( ) } ) ,
query : z . object ( { b : z . string ( ) } ) ,
cookie : z . object ( { cookie : z . string ( ) } ) ,
header : z . object ( { 'custom-header' : z . string ( ) } ) ,
} ,
} ,
} ,
} ,
} ) ;
より伝統的な方法でパラメータを宣言したい場合は、parameters キーを使用してパラメータを宣言することもできます。その後、定義がすべて結合されます。
createDocument ( {
paths : {
'/jobs/{a}' : {
put : {
parameters : [
z . string ( ) . openapi ( {
param : {
name : 'job-header' ,
in : 'header' ,
} ,
} ) ,
] ,
} ,
} ,
} ,
} ) ;
通常はメディア タイプを宣言する場所で、次のようにschema
Zod スキーマとして設定します。
createDocument ( {
paths : {
'/jobs' : {
get : {
requestBody : {
content : {
'application/json' : { schema : z . object ( { a : z . string ( ) } ) } ,
} ,
} ,
} ,
} ,
} ,
} ) ;
スキーマに OpenAPI 構文を使用する場合は、代わりに OpenAPI スキーマをschema
フィールドに追加するだけです。
リクエスト本文と同様に、次のようにschema
Zod スキーマとして設定するだけです。 headers
キーを使用して応答ヘッダーを設定できます。
createDocument ( {
paths : {
'/jobs' : {
get : {
responses : {
200 : {
description : '200 OK' ,
content : {
'application/json' : { schema : z . object ( { a : z . string ( ) } ) } ,
} ,
headers : z . object ( {
'header-key' : z . string ( ) ,
} ) ,
} ,
} ,
} ,
} ,
} ,
} ) ;
createDocument ( {
paths : {
'/jobs' : {
get : {
callbacks : {
onData : {
'{$request.query.callbackUrl}/data' : {
post : {
requestBody : {
content : {
'application/json' : { schema : z . object ( { a : z . string ( ) } ) } ,
} ,
} ,
responses : {
200 : {
description : '200 OK' ,
content : {
'application/json' : {
schema : z . object ( { a : z . string ( ) } ) ,
} ,
} ,
} ,
} ,
} ,
} ,
} ,
} ,
} ,
} ,
} ,
} ) ;
OpenAPI を使用すると、再利用可能なコンポーネントを定義でき、このライブラリを使用すると、それを 2 つの異なる方法で複製できます。
createDocument
の例を使用し、代わりに次のようにtitle
を作成するとします。
const title = z . string ( ) . openapi ( {
description : 'Job title' ,
example : 'My job' ,
ref : 'jobTitle' , // <- new field
} ) ;
ドキュメント全体のスキーマでtitle
が使用されている場合は、代わりに参照として作成されます。
{ "$ref" : " #/components/schemas/jobTitle " }
title
、ドキュメントのコンポーネント セクション内のスキーマとして出力されます。
{
"components" : {
"schemas" : {
"jobTitle" : {
"type" : " string " ,
"description" : " Job title " ,
"example" : " My job "
}
}
}
}
これは、繰り返しの少ない Open API ドキュメントを作成するための非常に強力な方法となります。識別子マッピングのようないくつかの Open API 機能では、共用体のすべてのスキーマに ref が含まれる必要があります。
ref
追加する代わりにスキーマを登録するもう 1 つの方法は、スキーマをコンポーネントに直接追加することです。これはref
と同じように機能します。したがって、その Zod タイプに遭遇するたびに、それを参照に置き換えます。
例えば。
createDocument ( {
components : {
schemas : {
jobTitle : title , // this will register this Zod Schema as jobTitle unless `ref` in `.openapi()` is specified on the type
} ,
} ,
} ) ;
残念ながら、このライブラリの制限として、コンポーネントに渡すスキーマに.openapi()
フィールドまたは.describe()
を添付する必要があります。そうしないと、コンポーネント生成の能力を最大限に活用できない可能性があります。そのため、手動登録ではなく自動登録コンポーネントを利用することをお勧めします。
クエリ、パス、ヘッダー、Cookie パラメータも同様に登録できます。
// Easy auto registration
const jobId = z . string ( ) . openapi ( {
description : 'Job ID' ,
example : '1234' ,
param : { ref : 'jobRef' } ,
} ) ;
createDocument ( {
paths : {
'/jobs/{jobId}' : {
put : {
requestParams : {
header : z . object ( {
jobId ,
} ) ,
} ,
} ,
} ,
} ,
} ) ;
// or more verbose auto registration
const jobId = z . string ( ) . openapi ( {
description : 'Job ID' ,
example : '1234' ,
param : { in : 'header' , name : 'jobId' , ref : 'jobRef' } ,
} ) ;
createDocument ( {
paths : {
'/jobs/{jobId}' : {
put : {
parameters : [ jobId ] ,
} ,
} ,
} ,
} ) ;
// or manual registeration
const otherJobId = z . string ( ) . openapi ( {
description : 'Job ID' ,
example : '1234' ,
param : { in : 'header' , name : 'jobId' } ,
} ) ;
createDocument ( {
components : {
parameters : {
jobRef : jobId ,
} ,
} ,
} ) ;
応答ヘッダーも同様に登録できます。
const header = z . string ( ) . openapi ( {
description : 'Job ID' ,
example : '1234' ,
header : { ref : 'some-header' } ,
} ) ;
// or
const jobIdHeader = z . string ( ) . openapi ( {
description : 'Job ID' ,
example : '1234' ,
} ) ;
createDocument ( {
components : {
headers : {
someHeaderRef : jobIdHeader ,
} ,
} ,
} ) ;
回答全体を登録することも可能
const response : ZodOpenApiResponseObject = {
description : '200 OK' ,
content : {
'application/json' : {
schema : z . object ( { a : z . string ( ) } ) ,
} ,
} ,
ref : 'some-response' ,
} ;
//or
const response : ZodOpenApiResponseObject = {
description : '200 OK' ,
content : {
'application/json' : {
schema : z . object ( { a : z . string ( ) } ) ,
} ,
} ,
} ;
createDocument ( {
components : {
responses : {
'some-response' : response ,
} ,
} ,
} ) ;
コールバックも登録可能
const callback : ZodOpenApiCallbackObject = {
ref : 'some-callback'
post : {
responses : {
200 : {
description : '200 OK' ,
content : {
'application/json' : {
schema : z . object ( { a : z . string ( ) } ) ,
}