@lucaapp/service-utils 1.30.1 → 1.32.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/dist/lib/api/api.d.ts +15 -5
- package/dist/lib/api/api.js +17 -8
- package/dist/lib/api/endpoint.d.ts +3 -2
- package/dist/lib/api/endpoint.js +92 -49
- package/dist/lib/api/response.d.ts +13 -24
- package/dist/lib/api/response.js +5 -8
- package/dist/lib/api/send.d.ts +5 -8
- package/dist/lib/api/send.js +5 -8
- package/dist/lib/api/types/endpoint.d.ts +11 -12
- package/dist/lib/api/types/http.d.ts +17 -0
- package/dist/lib/api/types/http.js +21 -0
- package/dist/lib/api/types/middleware.d.ts +16 -16
- package/dist/lib/api/types/utils.d.ts +2 -0
- package/package.json +1 -1
package/dist/lib/api/api.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import 'express-async-errors';
|
|
|
3
3
|
import { OpenAPIRegistry } from '@asteasolutions/zod-to-openapi';
|
|
4
4
|
import { EndpointHandler, EndpointOptions } from './types/endpoint';
|
|
5
5
|
import { Middleware, EndpointResponseSchema } from './types/middleware';
|
|
6
|
+
import { ZodObjectSchemaOrUndefined } from './types/utils';
|
|
6
7
|
type OpenApiVersion = '3.0.0' | '3.0.1' | '3.0.2' | '3.0.3' | '3.1.0';
|
|
7
8
|
type ApiConstructorOptions = {
|
|
8
9
|
prefixPath?: string;
|
|
@@ -11,6 +12,13 @@ type ApiConstructorOptions = {
|
|
|
11
12
|
apiTitle?: string;
|
|
12
13
|
apiDescription?: string;
|
|
13
14
|
debug?: boolean;
|
|
15
|
+
tags?: string[];
|
|
16
|
+
registry?: OpenAPIRegistry;
|
|
17
|
+
router?: Router;
|
|
18
|
+
};
|
|
19
|
+
type ApiChildOptions = {
|
|
20
|
+
prefixPath?: string;
|
|
21
|
+
tags?: string[];
|
|
14
22
|
};
|
|
15
23
|
export declare class Api {
|
|
16
24
|
router: Router;
|
|
@@ -21,12 +29,14 @@ export declare class Api {
|
|
|
21
29
|
apiDescription: string;
|
|
22
30
|
private prefixPath;
|
|
23
31
|
debug: boolean;
|
|
32
|
+
tags: string[];
|
|
24
33
|
constructor(options?: ApiConstructorOptions);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
34
|
+
child(options: ApiChildOptions): Api;
|
|
35
|
+
get<TResponseSchemas extends ReadonlyArray<EndpointResponseSchema>, TRequestBodySchema extends ZodObjectSchemaOrUndefined = undefined, TRequestParamsSchema extends ZodObjectSchemaOrUndefined = undefined, TRequestQuerySchema extends ZodObjectSchemaOrUndefined = undefined, TRequestHeadersSchema extends ZodObjectSchemaOrUndefined = undefined, TMiddlewares extends ReadonlyArray<Middleware<any, any, any, any, any, any>> | undefined = undefined>(path: string, summary: string, options: EndpointOptions<TResponseSchemas, TRequestBodySchema, TRequestParamsSchema, TRequestQuerySchema, TRequestHeadersSchema, TMiddlewares>, handler: EndpointHandler<TResponseSchemas, TRequestBodySchema, TRequestParamsSchema, TRequestQuerySchema, TRequestHeadersSchema, TMiddlewares>): void;
|
|
36
|
+
post<TResponseSchemas extends ReadonlyArray<EndpointResponseSchema>, TRequestBodySchema extends ZodObjectSchemaOrUndefined = undefined, TRequestParamsSchema extends ZodObjectSchemaOrUndefined = undefined, TRequestQuerySchema extends ZodObjectSchemaOrUndefined = undefined, TRequestHeadersSchema extends ZodObjectSchemaOrUndefined = undefined, TMiddlewares extends ReadonlyArray<Middleware<any, any, any, any, any, any>> | undefined = undefined>(path: string, summary: string, options: EndpointOptions<TResponseSchemas, TRequestBodySchema, TRequestParamsSchema, TRequestQuerySchema, TRequestHeadersSchema, TMiddlewares>, handler: EndpointHandler<TResponseSchemas, TRequestBodySchema, TRequestParamsSchema, TRequestQuerySchema, TRequestHeadersSchema, TMiddlewares>): void;
|
|
37
|
+
patch<TResponseSchemas extends ReadonlyArray<EndpointResponseSchema>, TRequestBodySchema extends ZodObjectSchemaOrUndefined = undefined, TRequestParamsSchema extends ZodObjectSchemaOrUndefined = undefined, TRequestQuerySchema extends ZodObjectSchemaOrUndefined = undefined, TRequestHeadersSchema extends ZodObjectSchemaOrUndefined = undefined, TMiddlewares extends ReadonlyArray<Middleware<any, any, any, any, any, any>> | undefined = undefined>(path: string, summary: string, options: EndpointOptions<TResponseSchemas, TRequestBodySchema, TRequestParamsSchema, TRequestQuerySchema, TRequestHeadersSchema, TMiddlewares>, handler: EndpointHandler<TResponseSchemas, TRequestBodySchema, TRequestParamsSchema, TRequestQuerySchema, TRequestHeadersSchema, TMiddlewares>): void;
|
|
38
|
+
put<TResponseSchemas extends ReadonlyArray<EndpointResponseSchema>, TRequestBodySchema extends ZodObjectSchemaOrUndefined = undefined, TRequestParamsSchema extends ZodObjectSchemaOrUndefined = undefined, TRequestQuerySchema extends ZodObjectSchemaOrUndefined = undefined, TRequestHeadersSchema extends ZodObjectSchemaOrUndefined = undefined, TMiddlewares extends ReadonlyArray<Middleware<any, any, any, any, any, any>> | undefined = undefined>(path: string, summary: string, options: EndpointOptions<TResponseSchemas, TRequestBodySchema, TRequestParamsSchema, TRequestQuerySchema, TRequestHeadersSchema, TMiddlewares>, handler: EndpointHandler<TResponseSchemas, TRequestBodySchema, TRequestParamsSchema, TRequestQuerySchema, TRequestHeadersSchema, TMiddlewares>): void;
|
|
39
|
+
delete<TResponseSchemas extends ReadonlyArray<EndpointResponseSchema>, TRequestBodySchema extends ZodObjectSchemaOrUndefined = undefined, TRequestParamsSchema extends ZodObjectSchemaOrUndefined = undefined, TRequestQuerySchema extends ZodObjectSchemaOrUndefined = undefined, TRequestHeadersSchema extends ZodObjectSchemaOrUndefined = undefined, TMiddlewares extends ReadonlyArray<Middleware<any, any, any, any, any, any>> | undefined = undefined>(path: string, summary: string, options: EndpointOptions<TResponseSchemas, TRequestBodySchema, TRequestParamsSchema, TRequestQuerySchema, TRequestHeadersSchema, TMiddlewares>, handler: EndpointHandler<TResponseSchemas, TRequestBodySchema, TRequestParamsSchema, TRequestQuerySchema, TRequestHeadersSchema, TMiddlewares>): void;
|
|
30
40
|
generateOpenAPISpec(): import("openapi3-ts").OpenAPIObject;
|
|
31
41
|
mountSwaggerMiddlewares(): void;
|
|
32
42
|
}
|
package/dist/lib/api/api.js
CHANGED
|
@@ -11,35 +11,44 @@ const zod_to_openapi_1 = require("@asteasolutions/zod-to-openapi");
|
|
|
11
11
|
const endpoint_1 = require("./endpoint");
|
|
12
12
|
class Api {
|
|
13
13
|
constructor(options = {}) {
|
|
14
|
-
this.router = (0, express_1.Router)();
|
|
15
|
-
this.registry = new zod_to_openapi_1.OpenAPIRegistry();
|
|
14
|
+
this.router = options.router || (0, express_1.Router)();
|
|
15
|
+
this.registry = options.registry || new zod_to_openapi_1.OpenAPIRegistry();
|
|
16
16
|
this.prefixPath = options.prefixPath || '';
|
|
17
17
|
this.openApiVersion = options.openApiVersion || '3.0.0';
|
|
18
18
|
this.apiVersion = options.apiVersion || '1.0.0';
|
|
19
19
|
this.apiTitle = options.apiTitle || 'API';
|
|
20
20
|
this.apiDescription = options.apiDescription || '';
|
|
21
21
|
this.debug = options.debug || false;
|
|
22
|
-
this.
|
|
22
|
+
this.tags = options.tags || [];
|
|
23
|
+
}
|
|
24
|
+
child(options) {
|
|
25
|
+
return new Api({
|
|
26
|
+
prefixPath: this.prefixPath + (options.prefixPath || ''),
|
|
27
|
+
debug: this.debug,
|
|
28
|
+
tags: [...this.tags, ...(options.tags || [])],
|
|
29
|
+
registry: this.registry,
|
|
30
|
+
router: this.router,
|
|
31
|
+
});
|
|
23
32
|
}
|
|
24
33
|
get(path, summary, options, handler) {
|
|
25
34
|
(0, endpoint_1.mountEndpoint)(this.router, 'get', path, options, handler, this.debug);
|
|
26
|
-
(0, endpoint_1.registerEndpoint)(this.registry, 'get', this.prefixPath, path, summary, options);
|
|
35
|
+
(0, endpoint_1.registerEndpoint)(this.registry, 'get', this.prefixPath, path, summary, options, this.tags, this.debug);
|
|
27
36
|
}
|
|
28
37
|
post(path, summary, options, handler) {
|
|
29
38
|
(0, endpoint_1.mountEndpoint)(this.router, 'post', path, options, handler, this.debug);
|
|
30
|
-
(0, endpoint_1.registerEndpoint)(this.registry, 'post', this.prefixPath, path, summary, options);
|
|
39
|
+
(0, endpoint_1.registerEndpoint)(this.registry, 'post', this.prefixPath, path, summary, options, this.tags, this.debug);
|
|
31
40
|
}
|
|
32
41
|
patch(path, summary, options, handler) {
|
|
33
42
|
(0, endpoint_1.mountEndpoint)(this.router, 'patch', path, options, handler, this.debug);
|
|
34
|
-
(0, endpoint_1.registerEndpoint)(this.registry, 'patch', this.prefixPath, path, summary, options);
|
|
43
|
+
(0, endpoint_1.registerEndpoint)(this.registry, 'patch', this.prefixPath, path, summary, options, this.tags, this.debug);
|
|
35
44
|
}
|
|
36
45
|
put(path, summary, options, handler) {
|
|
37
46
|
(0, endpoint_1.mountEndpoint)(this.router, 'put', path, options, handler, this.debug);
|
|
38
|
-
(0, endpoint_1.registerEndpoint)(this.registry, 'put', this.prefixPath, path, summary, options);
|
|
47
|
+
(0, endpoint_1.registerEndpoint)(this.registry, 'put', this.prefixPath, path, summary, options, this.tags, this.debug);
|
|
39
48
|
}
|
|
40
49
|
delete(path, summary, options, handler) {
|
|
41
50
|
(0, endpoint_1.mountEndpoint)(this.router, 'delete', path, options, handler, this.debug);
|
|
42
|
-
(0, endpoint_1.registerEndpoint)(this.registry, 'delete', this.prefixPath, path, summary, options);
|
|
51
|
+
(0, endpoint_1.registerEndpoint)(this.registry, 'delete', this.prefixPath, path, summary, options, this.tags, this.debug);
|
|
43
52
|
}
|
|
44
53
|
generateOpenAPISpec() {
|
|
45
54
|
const generator = new zod_to_openapi_1.OpenAPIGenerator(this.registry.definitions, this.openApiVersion);
|
|
@@ -2,7 +2,8 @@ import { Router } from 'express';
|
|
|
2
2
|
import { OpenAPIRegistry } from '@asteasolutions/zod-to-openapi';
|
|
3
3
|
import { Middleware, EndpointResponseSchema } from './types/middleware';
|
|
4
4
|
import { EndpointOptions, EndpointHandler } from './types/endpoint';
|
|
5
|
+
import { ZodObjectSchemaOrUndefined } from './types/utils';
|
|
5
6
|
type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch';
|
|
6
|
-
export declare const mountEndpoint: <TResponseSchemas extends readonly EndpointResponseSchema[],
|
|
7
|
-
export declare const registerEndpoint: (registry: OpenAPIRegistry, method: HttpMethod, prefixPath: string, path: string, summary: string, options: EndpointOptions<any, any, any, any, any, any
|
|
7
|
+
export declare const mountEndpoint: <TResponseSchemas extends readonly EndpointResponseSchema[], TRequestBodySchema extends ZodObjectSchemaOrUndefined, TRequestParamsSchema extends ZodObjectSchemaOrUndefined, TRequestQuerySchema extends ZodObjectSchemaOrUndefined, TRequestHeadersSchema extends ZodObjectSchemaOrUndefined, TMiddlewares extends readonly Middleware<any, any, any, any, any, any>[] | undefined = undefined>(router: Router, method: HttpMethod, path: string, options: EndpointOptions<TResponseSchemas, TRequestBodySchema, TRequestParamsSchema, TRequestQuerySchema, TRequestHeadersSchema, TMiddlewares>, handler: EndpointHandler<TResponseSchemas, TRequestBodySchema, TRequestParamsSchema, TRequestQuerySchema, TRequestHeadersSchema, TMiddlewares>, debug: boolean) => void;
|
|
8
|
+
export declare const registerEndpoint: (registry: OpenAPIRegistry, method: HttpMethod, prefixPath: string, path: string, summary: string, options: EndpointOptions<any, any, any, any, any, any>, tags: string[], debug: boolean) => void;
|
|
8
9
|
export {};
|
package/dist/lib/api/endpoint.js
CHANGED
|
@@ -6,7 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.registerEndpoint = exports.mountEndpoint = void 0;
|
|
7
7
|
const zod_1 = require("zod");
|
|
8
8
|
const assert_1 = __importDefault(require("assert"));
|
|
9
|
-
const
|
|
9
|
+
const http_1 = require("./types/http");
|
|
10
|
+
const mapExpressParamsToOpenAPIParams = (path) => path.replaceAll(/\:([^\:\/]+)/g, '{$1}');
|
|
10
11
|
const buildResponseConfig = (responseOptions) => {
|
|
11
12
|
const responses = {};
|
|
12
13
|
responseOptions.forEach(response => {
|
|
@@ -66,6 +67,27 @@ const validateAndSendResponse = async (expressResponse, response, validResponses
|
|
|
66
67
|
}
|
|
67
68
|
expressResponse.status(response.status).send(validatedResponseBody);
|
|
68
69
|
};
|
|
70
|
+
const sendBadResponseError = (response, error) => {
|
|
71
|
+
return response.status(500).send({
|
|
72
|
+
error: http_1.HTTPStatus.INTERNAL_SERVER_ERROR,
|
|
73
|
+
message: 'Invalid Response',
|
|
74
|
+
issues: error.issues,
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
const sendKnownErrorResponse = (response, statusCode, error, debug) => {
|
|
78
|
+
response.status(statusCode).send({
|
|
79
|
+
error: error.type,
|
|
80
|
+
message: error.message,
|
|
81
|
+
...(debug && { stack: error.stack }),
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
const sendBadRequestError = (response, error) => {
|
|
85
|
+
return response.status(400).send({
|
|
86
|
+
error: http_1.HTTPStatus.BAD_REQUEST,
|
|
87
|
+
message: error.message,
|
|
88
|
+
issues: error.issues,
|
|
89
|
+
});
|
|
90
|
+
};
|
|
69
91
|
const handleMiddleware = async (middleware, context, request, response, debug) => new Promise(async (resolve, reject) => {
|
|
70
92
|
try {
|
|
71
93
|
const handlerRequestBody = ((await middleware.options.schemas?.body?.parseAsync(request.body)) ||
|
|
@@ -91,10 +113,9 @@ const handleMiddleware = async (middleware, context, request, response, debug) =
|
|
|
91
113
|
resolve(false);
|
|
92
114
|
}
|
|
93
115
|
catch (error) {
|
|
94
|
-
if (error instanceof
|
|
95
|
-
(
|
|
96
|
-
|
|
97
|
-
});
|
|
116
|
+
if (error instanceof zod_1.ZodError) {
|
|
117
|
+
sendBadResponseError(response, error);
|
|
118
|
+
return resolve(false);
|
|
98
119
|
}
|
|
99
120
|
reject(error);
|
|
100
121
|
}
|
|
@@ -105,27 +126,27 @@ const handleMiddleware = async (middleware, context, request, response, debug) =
|
|
|
105
126
|
resolve(true);
|
|
106
127
|
}
|
|
107
128
|
catch (error) {
|
|
108
|
-
if (error instanceof
|
|
109
|
-
(
|
|
110
|
-
|
|
111
|
-
});
|
|
129
|
+
if (error instanceof zod_1.ZodError) {
|
|
130
|
+
sendBadResponseError(response, error);
|
|
131
|
+
return resolve(false);
|
|
112
132
|
}
|
|
113
133
|
reject(error);
|
|
114
134
|
}
|
|
115
135
|
});
|
|
116
136
|
}
|
|
117
137
|
catch (error) {
|
|
138
|
+
if (error instanceof zod_1.ZodError) {
|
|
139
|
+
sendBadRequestError(response, error);
|
|
140
|
+
return resolve(false);
|
|
141
|
+
}
|
|
118
142
|
if (isTypedError(error) &&
|
|
119
143
|
middleware.options.errors &&
|
|
120
144
|
middleware.options.errors[error.type]) {
|
|
121
145
|
const statusCode = middleware.options.errors[error.type];
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
error: error.type,
|
|
125
|
-
message: error.message,
|
|
126
|
-
...(debug && { stack: error.stack }),
|
|
127
|
-
});
|
|
146
|
+
sendKnownErrorResponse(response, statusCode, error, debug);
|
|
147
|
+
return resolve(false);
|
|
128
148
|
}
|
|
149
|
+
// bubble up unknown errors
|
|
129
150
|
reject(error);
|
|
130
151
|
}
|
|
131
152
|
});
|
|
@@ -159,38 +180,41 @@ const mountEndpoint = (router, method, path, options, handler, debug) => {
|
|
|
159
180
|
await validateAndSendResponse(response, controllerResponse, options.responses);
|
|
160
181
|
}
|
|
161
182
|
catch (error) {
|
|
162
|
-
if (error instanceof
|
|
163
|
-
(
|
|
164
|
-
statusCode: 500,
|
|
165
|
-
});
|
|
183
|
+
if (error instanceof zod_1.ZodError) {
|
|
184
|
+
return sendBadResponseError(response, error);
|
|
166
185
|
}
|
|
167
186
|
next(error);
|
|
168
187
|
}
|
|
169
188
|
});
|
|
170
189
|
}
|
|
171
190
|
catch (error) {
|
|
172
|
-
if (error instanceof zod_1.
|
|
173
|
-
return response
|
|
191
|
+
if (error instanceof zod_1.ZodError) {
|
|
192
|
+
return sendBadRequestError(response, error);
|
|
174
193
|
}
|
|
175
194
|
if (isTypedError(error) &&
|
|
176
195
|
options.errors &&
|
|
177
196
|
options.errors[error.type]) {
|
|
178
197
|
const statusCode = options.errors[error.type];
|
|
179
|
-
return response
|
|
180
|
-
|
|
181
|
-
|
|
198
|
+
return sendKnownErrorResponse(response, statusCode, error, debug);
|
|
199
|
+
}
|
|
200
|
+
if (error instanceof Error) {
|
|
201
|
+
return response.status(500).send({
|
|
202
|
+
error: http_1.HTTPStatus.INTERNAL_SERVER_ERROR,
|
|
182
203
|
message: error.message,
|
|
183
204
|
...(debug && { stack: error.stack }),
|
|
184
205
|
});
|
|
185
206
|
}
|
|
186
|
-
|
|
207
|
+
return response.status(500).send({
|
|
208
|
+
error: http_1.HTTPStatus.INTERNAL_SERVER_ERROR,
|
|
209
|
+
message: 'Unknown Error',
|
|
210
|
+
});
|
|
187
211
|
}
|
|
188
212
|
});
|
|
189
213
|
};
|
|
190
214
|
exports.mountEndpoint = mountEndpoint;
|
|
191
215
|
const registerEndpoint = (registry, method, prefixPath, path, summary,
|
|
192
216
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
193
|
-
options) => {
|
|
217
|
+
options, tags, debug) => {
|
|
194
218
|
let bodySchema = options.schemas?.body || undefined;
|
|
195
219
|
let paramsSchema = options.schemas?.params || undefined;
|
|
196
220
|
let querySchema = options.schemas?.query || undefined;
|
|
@@ -199,17 +223,14 @@ options) => {
|
|
|
199
223
|
if (options.errors) {
|
|
200
224
|
for (const errorType of Object.keys(options.errors)) {
|
|
201
225
|
const statusCode = options.errors[errorType];
|
|
202
|
-
responseSchemas
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}),
|
|
211
|
-
},
|
|
212
|
-
]);
|
|
226
|
+
responseSchemas.push({
|
|
227
|
+
status: statusCode,
|
|
228
|
+
description: errorType,
|
|
229
|
+
schema: zod_1.z.object({
|
|
230
|
+
error: zod_1.z.literal(errorType),
|
|
231
|
+
message: zod_1.z.string(),
|
|
232
|
+
}),
|
|
233
|
+
});
|
|
213
234
|
}
|
|
214
235
|
}
|
|
215
236
|
for (const middleware of options.middlewares || []) {
|
|
@@ -239,25 +260,47 @@ options) => {
|
|
|
239
260
|
if (middleware.options.errors) {
|
|
240
261
|
for (const errorType of Object.keys(middleware.options.errors)) {
|
|
241
262
|
const statusCode = middleware.options.errors[errorType];
|
|
242
|
-
responseSchemas
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}),
|
|
251
|
-
},
|
|
252
|
-
]);
|
|
263
|
+
responseSchemas.push({
|
|
264
|
+
status: statusCode,
|
|
265
|
+
description: errorType,
|
|
266
|
+
schema: zod_1.z.object({
|
|
267
|
+
error: zod_1.z.literal(errorType),
|
|
268
|
+
message: zod_1.z.string(),
|
|
269
|
+
}),
|
|
270
|
+
});
|
|
253
271
|
}
|
|
254
272
|
}
|
|
255
273
|
}
|
|
274
|
+
// Add ZodError response
|
|
275
|
+
responseSchemas.push({
|
|
276
|
+
status: 400,
|
|
277
|
+
description: 'Bad Request',
|
|
278
|
+
schema: zod_1.z.object({
|
|
279
|
+
error: zod_1.z.literal(http_1.HTTPStatus.BAD_REQUEST),
|
|
280
|
+
message: zod_1.z.string(),
|
|
281
|
+
issues: zod_1.z.array(zod_1.z
|
|
282
|
+
.object({
|
|
283
|
+
message: zod_1.z.string(),
|
|
284
|
+
})
|
|
285
|
+
.openapi({ additionalProperties: true })),
|
|
286
|
+
}),
|
|
287
|
+
});
|
|
288
|
+
// Add UnknownError response
|
|
289
|
+
responseSchemas.push({
|
|
290
|
+
status: 500,
|
|
291
|
+
description: 'Internal Server Error',
|
|
292
|
+
schema: zod_1.z.object({
|
|
293
|
+
error: zod_1.z.literal(http_1.HTTPStatus.INTERNAL_SERVER_ERROR),
|
|
294
|
+
message: zod_1.z.string(),
|
|
295
|
+
...(debug && { stack: zod_1.z.string().optional() }),
|
|
296
|
+
}),
|
|
297
|
+
});
|
|
256
298
|
const responseMap = buildResponseConfig(responseSchemas);
|
|
257
299
|
registry.registerPath({
|
|
258
300
|
method,
|
|
259
|
-
path: (prefixPath + path)
|
|
301
|
+
path: mapExpressParamsToOpenAPIParams(prefixPath + path),
|
|
260
302
|
summary,
|
|
303
|
+
tags,
|
|
261
304
|
// description: summary,
|
|
262
305
|
request: {
|
|
263
306
|
...(bodySchema && {
|
|
@@ -1,56 +1,45 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { HTTPStatus } from './types/http';
|
|
2
3
|
declare const noContentSchema: z.ZodVoid;
|
|
3
4
|
declare const badRequestErrorSchema: z.ZodObject<{
|
|
4
|
-
|
|
5
|
-
error: z.ZodString;
|
|
5
|
+
error: z.ZodLiteral<HTTPStatus.BAD_REQUEST>;
|
|
6
6
|
message: z.ZodString;
|
|
7
7
|
}, "strip", z.ZodTypeAny, {
|
|
8
8
|
message: string;
|
|
9
|
-
error:
|
|
10
|
-
statusCode: 400;
|
|
9
|
+
error: HTTPStatus.BAD_REQUEST;
|
|
11
10
|
}, {
|
|
12
11
|
message: string;
|
|
13
|
-
error:
|
|
14
|
-
statusCode: 400;
|
|
12
|
+
error: HTTPStatus.BAD_REQUEST;
|
|
15
13
|
}>;
|
|
16
14
|
declare const unauthorizedErrorSchema: z.ZodObject<{
|
|
17
|
-
|
|
18
|
-
error: z.ZodString;
|
|
15
|
+
error: z.ZodLiteral<HTTPStatus.UNAUTHORIZED>;
|
|
19
16
|
message: z.ZodString;
|
|
20
17
|
}, "strip", z.ZodTypeAny, {
|
|
21
18
|
message: string;
|
|
22
|
-
error:
|
|
23
|
-
statusCode: 401;
|
|
19
|
+
error: HTTPStatus.UNAUTHORIZED;
|
|
24
20
|
}, {
|
|
25
21
|
message: string;
|
|
26
|
-
error:
|
|
27
|
-
statusCode: 401;
|
|
22
|
+
error: HTTPStatus.UNAUTHORIZED;
|
|
28
23
|
}>;
|
|
29
24
|
declare const forbiddenErrorSchema: z.ZodObject<{
|
|
30
|
-
|
|
31
|
-
error: z.ZodString;
|
|
25
|
+
error: z.ZodLiteral<HTTPStatus.FORBIDDEN>;
|
|
32
26
|
message: z.ZodString;
|
|
33
27
|
}, "strip", z.ZodTypeAny, {
|
|
34
28
|
message: string;
|
|
35
|
-
error:
|
|
36
|
-
statusCode: 403;
|
|
29
|
+
error: HTTPStatus.FORBIDDEN;
|
|
37
30
|
}, {
|
|
38
31
|
message: string;
|
|
39
|
-
error:
|
|
40
|
-
statusCode: 403;
|
|
32
|
+
error: HTTPStatus.FORBIDDEN;
|
|
41
33
|
}>;
|
|
42
34
|
declare const notFoundErrorSchema: z.ZodObject<{
|
|
43
|
-
|
|
44
|
-
error: z.ZodString;
|
|
35
|
+
error: z.ZodLiteral<HTTPStatus.NOT_FOUND>;
|
|
45
36
|
message: z.ZodString;
|
|
46
37
|
}, "strip", z.ZodTypeAny, {
|
|
47
38
|
message: string;
|
|
48
|
-
error:
|
|
49
|
-
statusCode: 404;
|
|
39
|
+
error: HTTPStatus.NOT_FOUND;
|
|
50
40
|
}, {
|
|
51
41
|
message: string;
|
|
52
|
-
error:
|
|
53
|
-
statusCode: 404;
|
|
42
|
+
error: HTTPStatus.NOT_FOUND;
|
|
54
43
|
}>;
|
|
55
44
|
export declare const okResponse: <T>(schema: z.ZodType<T, z.ZodTypeDef, T>) => {
|
|
56
45
|
status: 200;
|
package/dist/lib/api/response.js
CHANGED
|
@@ -3,27 +3,24 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.notFoundResponse = exports.forbiddenResponse = exports.unauthorizedResponse = exports.badRequestResponse = exports.noContentResponse = exports.okResponse = void 0;
|
|
4
4
|
const zod_to_openapi_1 = require("@asteasolutions/zod-to-openapi");
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
|
+
const http_1 = require("./types/http");
|
|
6
7
|
(0, zod_to_openapi_1.extendZodWithOpenApi)(zod_1.z);
|
|
7
8
|
// response schemas
|
|
8
9
|
const noContentSchema = zod_1.z.void();
|
|
9
10
|
const badRequestErrorSchema = zod_1.z.object({
|
|
10
|
-
|
|
11
|
-
error: zod_1.z.string(),
|
|
11
|
+
error: zod_1.z.literal(http_1.HTTPStatus.BAD_REQUEST),
|
|
12
12
|
message: zod_1.z.string(),
|
|
13
13
|
});
|
|
14
14
|
const unauthorizedErrorSchema = zod_1.z.object({
|
|
15
|
-
|
|
16
|
-
error: zod_1.z.string(),
|
|
15
|
+
error: zod_1.z.literal(http_1.HTTPStatus.UNAUTHORIZED),
|
|
17
16
|
message: zod_1.z.string(),
|
|
18
17
|
});
|
|
19
18
|
const forbiddenErrorSchema = zod_1.z.object({
|
|
20
|
-
|
|
21
|
-
error: zod_1.z.string(),
|
|
19
|
+
error: zod_1.z.literal(http_1.HTTPStatus.FORBIDDEN),
|
|
22
20
|
message: zod_1.z.string(),
|
|
23
21
|
});
|
|
24
22
|
const notFoundErrorSchema = zod_1.z.object({
|
|
25
|
-
|
|
26
|
-
error: zod_1.z.string(),
|
|
23
|
+
error: zod_1.z.literal(http_1.HTTPStatus.NOT_FOUND),
|
|
27
24
|
message: zod_1.z.string(),
|
|
28
25
|
});
|
|
29
26
|
// response functions
|
package/dist/lib/api/send.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HTTPStatus } from './types/http';
|
|
1
2
|
export declare const ok: <T>(body: T) => {
|
|
2
3
|
status: 200;
|
|
3
4
|
body: T;
|
|
@@ -9,32 +10,28 @@ export declare const noContent: () => {
|
|
|
9
10
|
export declare const badRequest: (message?: string) => {
|
|
10
11
|
status: 400;
|
|
11
12
|
body: {
|
|
12
|
-
|
|
13
|
-
error: string;
|
|
13
|
+
error: HTTPStatus.BAD_REQUEST;
|
|
14
14
|
message: string;
|
|
15
15
|
};
|
|
16
16
|
};
|
|
17
17
|
export declare const unauthorized: (message?: string) => {
|
|
18
18
|
status: 401;
|
|
19
19
|
body: {
|
|
20
|
-
|
|
21
|
-
error: string;
|
|
20
|
+
error: HTTPStatus.UNAUTHORIZED;
|
|
22
21
|
message: string;
|
|
23
22
|
};
|
|
24
23
|
};
|
|
25
24
|
export declare const forbidden: (message?: string) => {
|
|
26
25
|
status: 403;
|
|
27
26
|
body: {
|
|
28
|
-
|
|
29
|
-
error: string;
|
|
27
|
+
error: HTTPStatus.FORBIDDEN;
|
|
30
28
|
message: string;
|
|
31
29
|
};
|
|
32
30
|
};
|
|
33
31
|
export declare const notFound: (message?: string) => {
|
|
34
32
|
status: 404;
|
|
35
33
|
body: {
|
|
36
|
-
|
|
37
|
-
error: string;
|
|
34
|
+
error: HTTPStatus.NOT_FOUND;
|
|
38
35
|
message: string;
|
|
39
36
|
};
|
|
40
37
|
};
|
package/dist/lib/api/send.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.notFound = exports.forbidden = exports.unauthorized = exports.badRequest = exports.noContent = exports.ok = void 0;
|
|
4
|
+
const http_1 = require("./types/http");
|
|
4
5
|
const ok = (body) => ({
|
|
5
6
|
status: 200,
|
|
6
7
|
body,
|
|
@@ -14,8 +15,7 @@ exports.noContent = noContent;
|
|
|
14
15
|
const badRequest = (message) => ({
|
|
15
16
|
status: 400,
|
|
16
17
|
body: {
|
|
17
|
-
|
|
18
|
-
error: 'Bad request',
|
|
18
|
+
error: http_1.HTTPStatus.BAD_REQUEST,
|
|
19
19
|
message: message || 'Bad request',
|
|
20
20
|
},
|
|
21
21
|
});
|
|
@@ -23,8 +23,7 @@ exports.badRequest = badRequest;
|
|
|
23
23
|
const unauthorized = (message) => ({
|
|
24
24
|
status: 401,
|
|
25
25
|
body: {
|
|
26
|
-
|
|
27
|
-
error: 'Unauthorized',
|
|
26
|
+
error: http_1.HTTPStatus.UNAUTHORIZED,
|
|
28
27
|
message: message || 'Unauthorized',
|
|
29
28
|
},
|
|
30
29
|
});
|
|
@@ -32,8 +31,7 @@ exports.unauthorized = unauthorized;
|
|
|
32
31
|
const forbidden = (message) => ({
|
|
33
32
|
status: 403,
|
|
34
33
|
body: {
|
|
35
|
-
|
|
36
|
-
error: 'Forbidden',
|
|
34
|
+
error: http_1.HTTPStatus.FORBIDDEN,
|
|
37
35
|
message: message || 'Forbidden',
|
|
38
36
|
},
|
|
39
37
|
});
|
|
@@ -41,8 +39,7 @@ exports.forbidden = forbidden;
|
|
|
41
39
|
const notFound = (message) => ({
|
|
42
40
|
status: 404,
|
|
43
41
|
body: {
|
|
44
|
-
|
|
45
|
-
error: 'Not found',
|
|
42
|
+
error: http_1.HTTPStatus.NOT_FOUND,
|
|
46
43
|
message: message || 'Not found',
|
|
47
44
|
},
|
|
48
45
|
});
|
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
1
|
import { Middleware, EndpointResponseSchema } from './middleware';
|
|
3
|
-
import { ArrayToUnion, ExtractZodOutput, ExtractZodOutputFromMiddleware, Always, Merge } from './utils';
|
|
4
|
-
export type EndpointHandler<TResponse,
|
|
5
|
-
body:
|
|
6
|
-
params:
|
|
7
|
-
query:
|
|
8
|
-
headers:
|
|
2
|
+
import { ArrayToUnion, ExtractZodOutput, ExtractZodOutputFromMiddleware, Always, Merge, ZodSchemaOuput } from './utils';
|
|
3
|
+
export type EndpointHandler<TResponse, TRequestBodySchema, TRequestParamsSchema, TRequestQuerySchema, TRequestHeadersSchema, TMiddlewares> = (request: {
|
|
4
|
+
body: ZodSchemaOuput<TRequestBodySchema>;
|
|
5
|
+
params: ZodSchemaOuput<TRequestParamsSchema>;
|
|
6
|
+
query: ZodSchemaOuput<TRequestQuerySchema>;
|
|
7
|
+
headers: ZodSchemaOuput<TRequestHeadersSchema>;
|
|
9
8
|
}, context: Merge<Always<ExtractZodOutputFromMiddleware<ArrayToUnion<TMiddlewares>>>>, send: (response: ExtractZodOutput<ArrayToUnion<TResponse>>) => void) => Promise<void>;
|
|
10
|
-
export type EndpointOptions<TResponseSchemas extends ReadonlyArray<EndpointResponseSchema>,
|
|
9
|
+
export type EndpointOptions<TResponseSchemas extends ReadonlyArray<EndpointResponseSchema>, TRequestBodySchema, TRequestParamsSchema, TRequestQuerySchema, TRequestHeadersSchema, TMiddlewares extends ReadonlyArray<Middleware<any, any, any, any, any, any>> | undefined> = {
|
|
11
10
|
schemas?: {
|
|
12
|
-
body?:
|
|
13
|
-
params?:
|
|
14
|
-
query?:
|
|
15
|
-
headers?:
|
|
11
|
+
body?: TRequestBodySchema;
|
|
12
|
+
params?: TRequestParamsSchema;
|
|
13
|
+
query?: TRequestQuerySchema;
|
|
14
|
+
headers?: TRequestHeadersSchema;
|
|
16
15
|
};
|
|
17
16
|
middlewares?: TMiddlewares;
|
|
18
17
|
responses: TResponseSchemas;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare enum HTTPStatus {
|
|
2
|
+
'OK' = "OK",
|
|
3
|
+
'CREATED' = "CREATED",
|
|
4
|
+
'ACCEPTED' = "ACCEPTED",
|
|
5
|
+
'NO_CONTENT' = "NO_CONTENT",
|
|
6
|
+
'BAD_REQUEST' = "BAD_REQUEST",
|
|
7
|
+
'UNAUTHORIZED' = "UNAUTHORIZED",
|
|
8
|
+
'FORBIDDEN' = "FORBIDDEN",
|
|
9
|
+
'NOT_FOUND' = "NOT_FOUND",
|
|
10
|
+
'CONFLICT' = "CONFLICT",
|
|
11
|
+
'GONE' = "GONE",
|
|
12
|
+
'TOO_MANY_REQUESTS' = "TOO_MANY_REQUESTS",
|
|
13
|
+
'INTERNAL_SERVER_ERROR' = "INTERNAL_SERVER_ERROR",
|
|
14
|
+
'NOT_IMPLEMENTED' = "NOT_IMPLEMENTED",
|
|
15
|
+
'BAD_GATEWAY' = "BAD_GATEWAY",
|
|
16
|
+
'SERVICE_UNAVAILABLE' = "SERVICE_UNAVAILABLE"
|
|
17
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HTTPStatus = void 0;
|
|
4
|
+
var HTTPStatus;
|
|
5
|
+
(function (HTTPStatus) {
|
|
6
|
+
HTTPStatus["OK"] = "OK";
|
|
7
|
+
HTTPStatus["CREATED"] = "CREATED";
|
|
8
|
+
HTTPStatus["ACCEPTED"] = "ACCEPTED";
|
|
9
|
+
HTTPStatus["NO_CONTENT"] = "NO_CONTENT";
|
|
10
|
+
HTTPStatus["BAD_REQUEST"] = "BAD_REQUEST";
|
|
11
|
+
HTTPStatus["UNAUTHORIZED"] = "UNAUTHORIZED";
|
|
12
|
+
HTTPStatus["FORBIDDEN"] = "FORBIDDEN";
|
|
13
|
+
HTTPStatus["NOT_FOUND"] = "NOT_FOUND";
|
|
14
|
+
HTTPStatus["CONFLICT"] = "CONFLICT";
|
|
15
|
+
HTTPStatus["GONE"] = "GONE";
|
|
16
|
+
HTTPStatus["TOO_MANY_REQUESTS"] = "TOO_MANY_REQUESTS";
|
|
17
|
+
HTTPStatus["INTERNAL_SERVER_ERROR"] = "INTERNAL_SERVER_ERROR";
|
|
18
|
+
HTTPStatus["NOT_IMPLEMENTED"] = "NOT_IMPLEMENTED";
|
|
19
|
+
HTTPStatus["BAD_GATEWAY"] = "BAD_GATEWAY";
|
|
20
|
+
HTTPStatus["SERVICE_UNAVAILABLE"] = "SERVICE_UNAVAILABLE";
|
|
21
|
+
})(HTTPStatus = exports.HTTPStatus || (exports.HTTPStatus = {}));
|
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { ArrayToUnion, ExtractZodOutput } from './utils';
|
|
2
|
+
import { ArrayToUnion, ExtractZodOutput, ZodSchemaOuput } from './utils';
|
|
3
3
|
export type EndpointResponseSchema = {
|
|
4
4
|
status: number;
|
|
5
5
|
description: string;
|
|
6
6
|
schema: z.ZodSchema<any> | z.ZodVoid;
|
|
7
7
|
};
|
|
8
|
-
export type MiddlewareHandler<TResponseSchema,
|
|
9
|
-
body:
|
|
10
|
-
params:
|
|
11
|
-
query:
|
|
12
|
-
headers:
|
|
8
|
+
export type MiddlewareHandler<TResponseSchema, TRequestBodySchema, TRequestParamsSchema, TRequestQuerySchema, TRequestHeadersSchema, TContextSchema> = (request: {
|
|
9
|
+
body: ZodSchemaOuput<TRequestBodySchema>;
|
|
10
|
+
params: ZodSchemaOuput<TRequestParamsSchema>;
|
|
11
|
+
query: ZodSchemaOuput<TRequestQuerySchema>;
|
|
12
|
+
headers: ZodSchemaOuput<TRequestHeadersSchema>;
|
|
13
13
|
ip: string;
|
|
14
14
|
baseUrl: string;
|
|
15
15
|
path: string;
|
|
16
16
|
method: string;
|
|
17
|
-
}, send: (response: ExtractZodOutput<ArrayToUnion<TResponseSchema>>) => void, next: (context:
|
|
18
|
-
export type MiddlewareOptions<TResponseSchemas extends ReadonlyArray<EndpointResponseSchema>,
|
|
17
|
+
}, send: (response: ExtractZodOutput<ArrayToUnion<TResponseSchema>>) => void, next: (context: ZodSchemaOuput<TContextSchema>) => void) => Promise<void>;
|
|
18
|
+
export type MiddlewareOptions<TResponseSchemas extends ReadonlyArray<EndpointResponseSchema>, TRequestBodySchema, TRequestParamsSchema, TRequestQuerySchema, TRequestHeadersSchema, TContextSchema> = {
|
|
19
19
|
schemas?: {
|
|
20
|
-
body?:
|
|
21
|
-
params?:
|
|
22
|
-
query?:
|
|
23
|
-
headers?:
|
|
24
|
-
context?:
|
|
20
|
+
body?: TRequestBodySchema;
|
|
21
|
+
params?: TRequestParamsSchema;
|
|
22
|
+
query?: TRequestQuerySchema;
|
|
23
|
+
headers?: TRequestHeadersSchema;
|
|
24
|
+
context?: TContextSchema;
|
|
25
25
|
};
|
|
26
26
|
responses: TResponseSchemas;
|
|
27
27
|
errors?: Record<string, number>;
|
|
28
28
|
};
|
|
29
|
-
export type Middleware<TResponseSchemas extends ReadonlyArray<EndpointResponseSchema>,
|
|
30
|
-
options: MiddlewareOptions<TResponseSchemas,
|
|
31
|
-
handler: MiddlewareHandler<TResponseSchemas,
|
|
29
|
+
export type Middleware<TResponseSchemas extends ReadonlyArray<EndpointResponseSchema>, TRequestBodySchema, TRequestParamsSchema, TRequestQuerySchema, TRequestHeadersSchema, TContextSchema> = {
|
|
30
|
+
options: MiddlewareOptions<TResponseSchemas, TRequestBodySchema, TRequestParamsSchema, TRequestQuerySchema, TRequestHeadersSchema, TContextSchema>;
|
|
31
|
+
handler: MiddlewareHandler<TResponseSchemas, TRequestBodySchema, TRequestParamsSchema, TRequestQuerySchema, TRequestHeadersSchema, TContextSchema>;
|
|
32
32
|
};
|
|
@@ -7,6 +7,8 @@ export type ExtractZodOutput<T> = T extends {
|
|
|
7
7
|
status: Z;
|
|
8
8
|
body: V;
|
|
9
9
|
} : never;
|
|
10
|
+
export type ZodObjectSchemaOrUndefined = z.ZodObject<any> | undefined;
|
|
11
|
+
export type ZodSchemaOuput<T> = T extends z.ZodSchema<any> ? z.infer<T> : undefined;
|
|
10
12
|
export type ExtractZodOutputFromMiddleware<T> = T extends {
|
|
11
13
|
options: {
|
|
12
14
|
schemas?: {
|