@hono/zod-openapi 0.1.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -5
- package/dist/index.cjs +11 -24
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +11 -25
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -4,11 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
_Note: This is not standalone middleware but is hosted on the monorepo "[github.com/honojs/middleware](https://github.com/honojs/middleware)"._
|
|
6
6
|
|
|
7
|
-
## Limitations
|
|
8
|
-
|
|
9
|
-
- Currently, it does not support validation of _headers_ and _cookies_.
|
|
10
|
-
- An instance of Zod OpenAPI Hono cannot be used as a "subApp" in conjunction with `rootApp.route('/api', subApp)`.
|
|
11
|
-
|
|
12
7
|
## Usage
|
|
13
8
|
|
|
14
9
|
### Installation
|
|
@@ -179,6 +174,14 @@ app.openapi(
|
|
|
179
174
|
)
|
|
180
175
|
```
|
|
181
176
|
|
|
177
|
+
### The Registry
|
|
178
|
+
|
|
179
|
+
You can access the [`OpenAPIRegistry`](https://github.com/asteasolutions/zod-to-openapi#the-registry) object via `app.openAPIRegistry`:
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
const registry = app.openAPIRegistry
|
|
183
|
+
```
|
|
184
|
+
|
|
182
185
|
### Middleware
|
|
183
186
|
|
|
184
187
|
Zod OpenAPI Hono is an extension of Hono, so you can use Hono's middleware in the same way:
|
|
@@ -209,6 +212,47 @@ const appRoutes = app.openapi(route, (c) => {
|
|
|
209
212
|
const client = hc<typeof appRoutes>('http://localhost:8787/')
|
|
210
213
|
```
|
|
211
214
|
|
|
215
|
+
## Limitations
|
|
216
|
+
|
|
217
|
+
An instance of Zod OpenAPI Hono cannot be used as a "subApp" in conjunction with `rootApp.route('/api', subApp)`.
|
|
218
|
+
Use `app.mount('/api', subApp.fetch)` instead.
|
|
219
|
+
|
|
220
|
+
```ts
|
|
221
|
+
const api = OpenAPIHono()
|
|
222
|
+
|
|
223
|
+
// ...
|
|
224
|
+
|
|
225
|
+
// Set the `/api` as a base path in the document.
|
|
226
|
+
api.get('/doc', (c) => {
|
|
227
|
+
const url = new URL(c.req.url)
|
|
228
|
+
url.pathname = '/api'
|
|
229
|
+
url.search = ''
|
|
230
|
+
|
|
231
|
+
return c.json(
|
|
232
|
+
// `api.getOpenAPIDocument()` will return a JSON object of the docs.
|
|
233
|
+
api.getOpenAPIDocument({
|
|
234
|
+
openapi: '3.0.0',
|
|
235
|
+
info: {
|
|
236
|
+
version: '1.0.0',
|
|
237
|
+
title: 'My API',
|
|
238
|
+
},
|
|
239
|
+
servers: [
|
|
240
|
+
{
|
|
241
|
+
url: `${url.toString()}`,
|
|
242
|
+
},
|
|
243
|
+
],
|
|
244
|
+
})
|
|
245
|
+
)
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
const app = new Hono()
|
|
249
|
+
|
|
250
|
+
// Mount the Open API app to `/api` in the main app.
|
|
251
|
+
app.mount('/api', api.fetch)
|
|
252
|
+
|
|
253
|
+
export default app
|
|
254
|
+
```
|
|
255
|
+
|
|
212
256
|
## References
|
|
213
257
|
|
|
214
258
|
- [Hono](https://hono.dev/)
|
package/dist/index.cjs
CHANGED
|
@@ -16,24 +16,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
16
|
return to;
|
|
17
17
|
};
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var __accessCheck = (obj, member, msg) => {
|
|
20
|
-
if (!member.has(obj))
|
|
21
|
-
throw TypeError("Cannot " + msg);
|
|
22
|
-
};
|
|
23
|
-
var __privateGet = (obj, member, getter) => {
|
|
24
|
-
__accessCheck(obj, member, "read from private field");
|
|
25
|
-
return getter ? getter.call(obj) : member.get(obj);
|
|
26
|
-
};
|
|
27
|
-
var __privateAdd = (obj, member, value) => {
|
|
28
|
-
if (member.has(obj))
|
|
29
|
-
throw TypeError("Cannot add the same private member more than once");
|
|
30
|
-
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
31
|
-
};
|
|
32
|
-
var __privateSet = (obj, member, value, setter) => {
|
|
33
|
-
__accessCheck(obj, member, "write to private field");
|
|
34
|
-
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
35
|
-
return value;
|
|
36
|
-
};
|
|
37
19
|
|
|
38
20
|
// src/index.ts
|
|
39
21
|
var src_exports = {};
|
|
@@ -48,13 +30,11 @@ var import_zod_to_openapi2 = require("@asteasolutions/zod-to-openapi");
|
|
|
48
30
|
var import_zod_validator = require("@hono/zod-validator");
|
|
49
31
|
var import_hono = require("hono");
|
|
50
32
|
var import_zod = require("zod");
|
|
51
|
-
var _registry;
|
|
52
33
|
var OpenAPIHono = class extends import_hono.Hono {
|
|
53
34
|
constructor() {
|
|
54
35
|
super();
|
|
55
|
-
__privateAdd(this, _registry, void 0);
|
|
56
36
|
this.openapi = (route, handler, hook) => {
|
|
57
|
-
|
|
37
|
+
this.openAPIRegistry.registerPath(route);
|
|
58
38
|
const validators = [];
|
|
59
39
|
if (route.request?.query) {
|
|
60
40
|
const validator = (0, import_zod_validator.zValidator)("query", route.request.query, hook);
|
|
@@ -64,6 +44,14 @@ var OpenAPIHono = class extends import_hono.Hono {
|
|
|
64
44
|
const validator = (0, import_zod_validator.zValidator)("param", route.request.params, hook);
|
|
65
45
|
validators.push(validator);
|
|
66
46
|
}
|
|
47
|
+
if (route.request?.headers) {
|
|
48
|
+
const validator = (0, import_zod_validator.zValidator)("header", route.request.headers, hook);
|
|
49
|
+
validators.push(validator);
|
|
50
|
+
}
|
|
51
|
+
if (route.request?.cookies) {
|
|
52
|
+
const validator = (0, import_zod_validator.zValidator)("cookie", route.request.cookies, hook);
|
|
53
|
+
validators.push(validator);
|
|
54
|
+
}
|
|
67
55
|
const bodyContent = route.request?.body?.content;
|
|
68
56
|
if (bodyContent) {
|
|
69
57
|
for (const mediaType of Object.keys(bodyContent)) {
|
|
@@ -87,7 +75,7 @@ var OpenAPIHono = class extends import_hono.Hono {
|
|
|
87
75
|
return this;
|
|
88
76
|
};
|
|
89
77
|
this.getOpenAPIDocument = (config) => {
|
|
90
|
-
const generator = new import_zod_to_openapi.OpenApiGeneratorV3(
|
|
78
|
+
const generator = new import_zod_to_openapi.OpenApiGeneratorV3(this.openAPIRegistry.definitions);
|
|
91
79
|
const document = generator.generateDocument(config);
|
|
92
80
|
return document;
|
|
93
81
|
};
|
|
@@ -97,10 +85,9 @@ var OpenAPIHono = class extends import_hono.Hono {
|
|
|
97
85
|
return c.json(document);
|
|
98
86
|
});
|
|
99
87
|
};
|
|
100
|
-
|
|
88
|
+
this.openAPIRegistry = new import_zod_to_openapi.OpenAPIRegistry();
|
|
101
89
|
}
|
|
102
90
|
};
|
|
103
|
-
_registry = new WeakMap();
|
|
104
91
|
var createRoute = (routeConfig) => routeConfig;
|
|
105
92
|
(0, import_zod_to_openapi2.extendZodWithOpenApi)(import_zod.z);
|
|
106
93
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as openapi3_ts_oas30 from 'openapi3-ts/oas30';
|
|
2
|
-
import { RouteConfig, ZodRequestBody, ZodContentObject, ResponseConfig } from '@asteasolutions/zod-to-openapi';
|
|
2
|
+
import { OpenAPIRegistry, RouteConfig, ZodRequestBody, ZodContentObject, ResponseConfig } from '@asteasolutions/zod-to-openapi';
|
|
3
3
|
import { OpenAPIObjectConfig } from '@asteasolutions/zod-to-openapi/dist/v3.0/openapi-generator';
|
|
4
4
|
import { Env, Schema, Hono, Input, Handler, ToSchema, Context, TypedResponse } from 'hono';
|
|
5
5
|
import { AnyZodObject, z, ZodSchema, ZodError, ZodType } from 'zod';
|
|
@@ -48,10 +48,11 @@ type Hook<T, E extends Env, P extends string, O> = (result: {
|
|
|
48
48
|
error: ZodError;
|
|
49
49
|
}, c: Context<E, P>) => TypedResponse<O> | Promise<TypedResponse<T>> | void;
|
|
50
50
|
type ConvertPathType<T extends string> = T extends `${infer _}/{${infer Param}}${infer _}` ? `/:${Param}` : T;
|
|
51
|
+
type HandlerResponse<O> = TypedResponse<O> | Promise<TypedResponse<O>>;
|
|
51
52
|
declare class OpenAPIHono<E extends Env = Env, S extends Schema = {}, BasePath extends string = '/'> extends Hono<E, S, BasePath> {
|
|
52
|
-
|
|
53
|
+
openAPIRegistry: OpenAPIRegistry;
|
|
53
54
|
constructor();
|
|
54
|
-
openapi: <R extends RouteConfig, I extends Input = InputTypeBase<R, "params", "param"> & InputTypeBase<R, "query", "query"> & InputTypeForm<R> & InputTypeJson<R>, P extends string = ConvertPathType<R["path"]>>(route: R, handler: Handler<E, P, I, OutputType<R
|
|
55
|
+
openapi: <R extends RouteConfig, I extends Input = InputTypeBase<R, "params", "param"> & InputTypeBase<R, "query", "query"> & InputTypeBase<R, "headers", "header"> & InputTypeBase<R, "cookies", "cookie"> & InputTypeForm<R> & InputTypeJson<R>, P extends string = ConvertPathType<R["path"]>>(route: R, handler: Handler<E, P, I, HandlerResponse<OutputType<R>>>, hook?: Hook<I, E, P, OutputType<R>> | undefined) => Hono<E, ToSchema<R["method"], P, I["in"], OutputType<R>>, BasePath>;
|
|
55
56
|
getOpenAPIDocument: (config: OpenAPIObjectConfig) => openapi3_ts_oas30.OpenAPIObject;
|
|
56
57
|
doc: (path: string, config: OpenAPIObjectConfig) => void;
|
|
57
58
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as openapi3_ts_oas30 from 'openapi3-ts/oas30';
|
|
2
|
-
import { RouteConfig, ZodRequestBody, ZodContentObject, ResponseConfig } from '@asteasolutions/zod-to-openapi';
|
|
2
|
+
import { OpenAPIRegistry, RouteConfig, ZodRequestBody, ZodContentObject, ResponseConfig } from '@asteasolutions/zod-to-openapi';
|
|
3
3
|
import { OpenAPIObjectConfig } from '@asteasolutions/zod-to-openapi/dist/v3.0/openapi-generator';
|
|
4
4
|
import { Env, Schema, Hono, Input, Handler, ToSchema, Context, TypedResponse } from 'hono';
|
|
5
5
|
import { AnyZodObject, z, ZodSchema, ZodError, ZodType } from 'zod';
|
|
@@ -48,10 +48,11 @@ type Hook<T, E extends Env, P extends string, O> = (result: {
|
|
|
48
48
|
error: ZodError;
|
|
49
49
|
}, c: Context<E, P>) => TypedResponse<O> | Promise<TypedResponse<T>> | void;
|
|
50
50
|
type ConvertPathType<T extends string> = T extends `${infer _}/{${infer Param}}${infer _}` ? `/:${Param}` : T;
|
|
51
|
+
type HandlerResponse<O> = TypedResponse<O> | Promise<TypedResponse<O>>;
|
|
51
52
|
declare class OpenAPIHono<E extends Env = Env, S extends Schema = {}, BasePath extends string = '/'> extends Hono<E, S, BasePath> {
|
|
52
|
-
|
|
53
|
+
openAPIRegistry: OpenAPIRegistry;
|
|
53
54
|
constructor();
|
|
54
|
-
openapi: <R extends RouteConfig, I extends Input = InputTypeBase<R, "params", "param"> & InputTypeBase<R, "query", "query"> & InputTypeForm<R> & InputTypeJson<R>, P extends string = ConvertPathType<R["path"]>>(route: R, handler: Handler<E, P, I, OutputType<R
|
|
55
|
+
openapi: <R extends RouteConfig, I extends Input = InputTypeBase<R, "params", "param"> & InputTypeBase<R, "query", "query"> & InputTypeBase<R, "headers", "header"> & InputTypeBase<R, "cookies", "cookie"> & InputTypeForm<R> & InputTypeJson<R>, P extends string = ConvertPathType<R["path"]>>(route: R, handler: Handler<E, P, I, HandlerResponse<OutputType<R>>>, hook?: Hook<I, E, P, OutputType<R>> | undefined) => Hono<E, ToSchema<R["method"], P, I["in"], OutputType<R>>, BasePath>;
|
|
55
56
|
getOpenAPIDocument: (config: OpenAPIObjectConfig) => openapi3_ts_oas30.OpenAPIObject;
|
|
56
57
|
doc: (path: string, config: OpenAPIObjectConfig) => void;
|
|
57
58
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,35 +1,14 @@
|
|
|
1
|
-
var __accessCheck = (obj, member, msg) => {
|
|
2
|
-
if (!member.has(obj))
|
|
3
|
-
throw TypeError("Cannot " + msg);
|
|
4
|
-
};
|
|
5
|
-
var __privateGet = (obj, member, getter) => {
|
|
6
|
-
__accessCheck(obj, member, "read from private field");
|
|
7
|
-
return getter ? getter.call(obj) : member.get(obj);
|
|
8
|
-
};
|
|
9
|
-
var __privateAdd = (obj, member, value) => {
|
|
10
|
-
if (member.has(obj))
|
|
11
|
-
throw TypeError("Cannot add the same private member more than once");
|
|
12
|
-
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
13
|
-
};
|
|
14
|
-
var __privateSet = (obj, member, value, setter) => {
|
|
15
|
-
__accessCheck(obj, member, "write to private field");
|
|
16
|
-
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
17
|
-
return value;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
1
|
// src/index.ts
|
|
21
2
|
import { OpenApiGeneratorV3, OpenAPIRegistry } from "@asteasolutions/zod-to-openapi";
|
|
22
3
|
import { extendZodWithOpenApi } from "@asteasolutions/zod-to-openapi";
|
|
23
4
|
import { zValidator } from "@hono/zod-validator";
|
|
24
5
|
import { Hono } from "hono";
|
|
25
6
|
import { z, ZodType } from "zod";
|
|
26
|
-
var _registry;
|
|
27
7
|
var OpenAPIHono = class extends Hono {
|
|
28
8
|
constructor() {
|
|
29
9
|
super();
|
|
30
|
-
__privateAdd(this, _registry, void 0);
|
|
31
10
|
this.openapi = (route, handler, hook) => {
|
|
32
|
-
|
|
11
|
+
this.openAPIRegistry.registerPath(route);
|
|
33
12
|
const validators = [];
|
|
34
13
|
if (route.request?.query) {
|
|
35
14
|
const validator = zValidator("query", route.request.query, hook);
|
|
@@ -39,6 +18,14 @@ var OpenAPIHono = class extends Hono {
|
|
|
39
18
|
const validator = zValidator("param", route.request.params, hook);
|
|
40
19
|
validators.push(validator);
|
|
41
20
|
}
|
|
21
|
+
if (route.request?.headers) {
|
|
22
|
+
const validator = zValidator("header", route.request.headers, hook);
|
|
23
|
+
validators.push(validator);
|
|
24
|
+
}
|
|
25
|
+
if (route.request?.cookies) {
|
|
26
|
+
const validator = zValidator("cookie", route.request.cookies, hook);
|
|
27
|
+
validators.push(validator);
|
|
28
|
+
}
|
|
42
29
|
const bodyContent = route.request?.body?.content;
|
|
43
30
|
if (bodyContent) {
|
|
44
31
|
for (const mediaType of Object.keys(bodyContent)) {
|
|
@@ -62,7 +49,7 @@ var OpenAPIHono = class extends Hono {
|
|
|
62
49
|
return this;
|
|
63
50
|
};
|
|
64
51
|
this.getOpenAPIDocument = (config) => {
|
|
65
|
-
const generator = new OpenApiGeneratorV3(
|
|
52
|
+
const generator = new OpenApiGeneratorV3(this.openAPIRegistry.definitions);
|
|
66
53
|
const document = generator.generateDocument(config);
|
|
67
54
|
return document;
|
|
68
55
|
};
|
|
@@ -72,10 +59,9 @@ var OpenAPIHono = class extends Hono {
|
|
|
72
59
|
return c.json(document);
|
|
73
60
|
});
|
|
74
61
|
};
|
|
75
|
-
|
|
62
|
+
this.openAPIRegistry = new OpenAPIRegistry();
|
|
76
63
|
}
|
|
77
64
|
};
|
|
78
|
-
_registry = new WeakMap();
|
|
79
65
|
var createRoute = (routeConfig) => routeConfig;
|
|
80
66
|
extendZodWithOpenApi(z);
|
|
81
67
|
export {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hono/zod-openapi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "A wrapper class of Hono which supports OpenAPI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"zod": "3.*"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"hono": "^3.5.
|
|
34
|
+
"hono": "^3.5.8",
|
|
35
35
|
"zod": "^3.22.1"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
@@ -41,4 +41,4 @@
|
|
|
41
41
|
"engines": {
|
|
42
42
|
"node": ">=16.0.0"
|
|
43
43
|
}
|
|
44
|
-
}
|
|
44
|
+
}
|