Pustaka TypeScript untuk menggunakan Zod Schemas untuk membuat dokumentasi OpenAPI v3.x
Instal melalui npm
, yarn
atau pnpm
:
npm install zod zod-openapi
# # or
yarn add zod zod-openapi
# # or
pnpm install zod zod-openapi
Ini mengubah Zod untuk menambahkan metode .openapi()
tambahan. Sebut ini di bagian atas titik masuk Anda. Anda dapat mencapainya dengan dua cara berbeda, bergantung pada preferensi Anda.
import 'zod-openapi/extend' ;
import { z } from 'zod' ;
z . string ( ) . openapi ( { description : 'hello world!' , example : 'hello world' } ) ;
Ini berguna jika Anda memiliki instance Zod tertentu atau instance Zod dari perpustakaan lain yang ingin Anda targetkan.
import { z } from 'zod' ;
import { extendZodWithOpenApi } from 'zod-openapi' ;
extendZodWithOpenApi ( z ) ;
z . string ( ) . openapi ( { description : 'hello world!' , example : 'hello world' } ) ;
.openapi()
Gunakan metode .openapi()
untuk menambahkan metadata ke tipe Zod tertentu. Metode .openapi()
mengambil objek dengan opsi berikut:
Pilihan | Keterangan |
---|---|
Opsi OpenAPI | Ini akan mengambil opsi apa pun yang Anda masukkan pada SchemaObject. |
effectType | Gunakan untuk mengganti jenis pembuatan untuk Efek Zod |
header | Gunakan untuk menyediakan metadata untuk header respons |
param | Gunakan untuk menyediakan metadata untuk parameter permintaan |
ref | Gunakan ini untuk mendaftarkan skema secara otomatis sebagai komponen yang dapat digunakan kembali |
refType | Gunakan ini untuk mengatur jenis pembuatan komponen yang tidak direferensikan dalam dokumen. |
type | Gunakan ini untuk mengganti tipe yang dihasilkan. Jika ini disediakan, metadata tidak akan dibuat. |
unionOneOf | Setel ke true untuk memaksa satu ZodUnion mengeluarkan oneOf alih-alih anyOf . Lihat CreateDocumentOptions untuk opsi global |
createDocument
Membuat objek dokumentasi 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
mengambil argumen opsional CreateDocumentOptions
yang dapat digunakan untuk mengubah cara dokumen dibuat.
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
Membuat Objek Skema OpenAPI bersama dengan komponen apa pun yang terdaftar. Objek Skema OpenAPI 3.1.0 sepenuhnya kompatibel dengan Skema 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
menggunakan parameter opsional CreateSchemaOptions
yang juga dapat mengambil opsi yang sama seperti CreateDocumentOptions bersama dengan opsi berikut:
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/
} )
Parameter Kueri, Jalur, Header & Cookie dapat dibuat menggunakan kunci requestParams
di bawah kunci method
sebagai berikut:
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 ( ) } ) ,
} ,
} ,
} ,
} ,
} ) ;
Jika Anda ingin mendeklarasikan parameter dengan cara yang lebih tradisional, Anda juga dapat mendeklarasikannya menggunakan kunci parameter. Semua definisi tersebut kemudian akan digabungkan.
createDocument ( {
paths : {
'/jobs/{a}' : {
put : {
parameters : [
z . string ( ) . openapi ( {
param : {
name : 'job-header' ,
in : 'header' ,
} ,
} ) ,
] ,
} ,
} ,
} ,
} ) ;
Di mana Anda biasanya mendeklarasikan jenis media, atur schema
sebagai Zod Schema Anda sebagai berikut.
createDocument ( {
paths : {
'/jobs' : {
get : {
requestBody : {
content : {
'application/json' : { schema : z . object ( { a : z . string ( ) } ) } ,
} ,
} ,
} ,
} ,
} ,
} ) ;
Jika Anda ingin menggunakan sintaksis OpenAPI untuk skema Anda, cukup tambahkan skema OpenAPI ke bidang schema
.
Mirip dengan Badan Permintaan, cukup atur schema
sebagai Skema Zod Anda sebagai berikut. Anda dapat mengatur header respons menggunakan kunci 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 memungkinkan Anda menentukan komponen yang dapat digunakan kembali dan pustaka ini memungkinkan Anda mereplikasi komponen tersebut dalam dua cara terpisah.
Jika kita mengambil contoh di createDocument
dan membuat title
sebagai berikut
const title = z . string ( ) . openapi ( {
description : 'Job title' ,
example : 'My job' ,
ref : 'jobTitle' , // <- new field
} ) ;
Dimanapun title
digunakan dalam skema di seluruh dokumen, judul tersebut akan dibuat sebagai referensi.
{ "$ref" : " #/components/schemas/jobTitle " }
title
kemudian akan ditampilkan sebagai skema di bagian komponen dokumentasi.
{
"components" : {
"schemas" : {
"jobTitle" : {
"type" : " string " ,
"description" : " Job title " ,
"example" : " My job "
}
}
}
}
Ini bisa menjadi cara yang sangat ampuh untuk membuat dokumentasi Open API yang tidak terlalu berulang. Ada beberapa fitur Open API seperti pemetaan diskriminator yang mengharuskan semua skema di gabungan berisi referensi.
Cara lain untuk mendaftarkan skema alih-alih menambahkan ref
adalah dengan menambahkannya ke komponen secara langsung. Ini akan tetap bekerja dengan cara yang sama seperti ref
. Jadi setiap kali kita menemukan tipe Zod itu kita akan menggantinya dengan referensi.
misalnya.
createDocument ( {
components : {
schemas : {
jobTitle : title , // this will register this Zod Schema as jobTitle unless `ref` in `.openapi()` is specified on the type
} ,
} ,
} ) ;
Sayangnya, sebagai batasan pustaka ini, Anda harus melampirkan bidang .openapi()
atau .describe()
ke skema yang Anda teruskan ke dalam komponen, jika tidak, Anda mungkin tidak mendapatkan kemampuan penuh dalam pembuatan komponen. Oleh karena itu, saya merekomendasikan penggunaan komponen pendaftaran otomatis daripada pendaftaran manual.
Parameter Kueri, Jalur, Header & Cookie dapat didaftarkan dengan cara yang sama:
// 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 ,
} ,
} ,
} ) ;
Header respons dapat didaftarkan dengan cara yang sama:
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 ,
} ,
} ,
} ) ;
Seluruh Tanggapan juga dapat didaftarkan
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 ,
} ,
} ,
} ) ;
Panggilan balik juga dapat didaftarkan
const callback : ZodOpenApiCallbackObject = {
ref : 'some-callback'
post : {
responses : {
200 : {
description : '200 OK' ,
content : {
'application/json' : {
schema : z . object ( { a : z . string ( ) } ) ,
}