express-zod-api
Advanced tools
Comparing version 0.7.0 to 0.7.1
@@ -5,2 +5,8 @@ # Changelog | ||
### v0.7.1 | ||
- Readme file updates: | ||
- Concept description update. | ||
- Excess property check according to the new features of version 0.7.0. | ||
- Refactoring of `defaultResultHandler` and `ResultHandler` calls in `server.ts`. | ||
### v0.7.0 | ||
@@ -32,3 +38,3 @@ - Zod version is v3.0.0-beta.1 | ||
handler: async ({input, options}) => ({ | ||
transform: 'test' // => in response: { transform: 4 } | ||
value: 'test' // => in response: { value: 4 } | ||
}) | ||
@@ -35,0 +41,0 @@ }); |
@@ -20,2 +20,4 @@ import { Request } from 'express'; | ||
export declare function isLoggerConfig(logger: any): logger is LoggerConfig; | ||
export declare function getMessageFromError(error: Error): string; | ||
export declare function getStatusCodeFromError(error: Error): number; | ||
export {}; |
@@ -14,3 +14,4 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.isLoggerConfig = exports.getInitialInput = exports.combineEndpointAndMiddlewareInputSchemas = exports.extractObjectSchema = void 0; | ||
exports.getStatusCodeFromError = exports.getMessageFromError = exports.isLoggerConfig = exports.getInitialInput = exports.combineEndpointAndMiddlewareInputSchemas = exports.extractObjectSchema = void 0; | ||
var http_errors_1 = require("http-errors"); | ||
var zod_1 = require("zod"); | ||
@@ -63,2 +64,21 @@ var config_type_1 = require("./config-type"); | ||
exports.isLoggerConfig = isLoggerConfig; | ||
function getMessageFromError(error) { | ||
return error instanceof zod_1.z.ZodError | ||
? error.issues.map(function (_a) { | ||
var path = _a.path, message = _a.message; | ||
return path.join('/') + ": " + message; | ||
}).join('; ') | ||
: error.message; | ||
} | ||
exports.getMessageFromError = getMessageFromError; | ||
function getStatusCodeFromError(error) { | ||
if (error instanceof http_errors_1.HttpError) { | ||
return error.statusCode; | ||
} | ||
if (error instanceof zod_1.z.ZodError) { | ||
return 400; | ||
} | ||
return 500; | ||
} | ||
exports.getStatusCodeFromError = getStatusCodeFromError; | ||
//# sourceMappingURL=helpers.js.map |
@@ -12,3 +12,3 @@ import { Request, Response } from 'express'; | ||
export declare type ResultHandler = (params: ResultHandlerParams) => void | Promise<void>; | ||
export declare const defaultResultHandler: ({ error, request, response, input, output, logger }: ResultHandlerParams) => void; | ||
export declare const defaultResultHandler: ResultHandler; | ||
export {}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.defaultResultHandler = void 0; | ||
var http_errors_1 = require("http-errors"); | ||
var zod_1 = require("zod"); | ||
var helpers_1 = require("./helpers"); | ||
var defaultResultHandler = function (_a) { | ||
var error = _a.error, request = _a.request, response = _a.response, input = _a.input, output = _a.output, logger = _a.logger; | ||
var resultJson; | ||
if (error) { | ||
var statusCode = 500; | ||
if (error instanceof http_errors_1.HttpError) { | ||
statusCode = error.statusCode; | ||
} | ||
if (error instanceof zod_1.z.ZodError) { | ||
statusCode = 400; | ||
} | ||
if (statusCode === 500) { | ||
logger.error('Internal server error\n' + | ||
(error.stack + "\n") + | ||
("URL: " + request.url + "\n") + | ||
("Payload: " + JSON.stringify(input, undefined, 2))); | ||
} | ||
response.status(statusCode); | ||
resultJson = { | ||
status: 'error', | ||
error: { | ||
message: error instanceof zod_1.z.ZodError | ||
? error.issues.map(function (_a) { | ||
var path = _a.path, message = _a.message; | ||
return path.join('/') + ": " + message; | ||
}).join('; ') | ||
: error.message, | ||
} | ||
}; | ||
if (!error) { | ||
var result_1 = { status: 'success', data: output }; | ||
response.status(200).json(result_1); | ||
return; | ||
} | ||
else { | ||
response.status(200); | ||
resultJson = { | ||
status: 'success', | ||
data: output | ||
}; | ||
var statusCode = helpers_1.getStatusCodeFromError(error); | ||
if (statusCode === 500) { | ||
logger.error('Internal server error\n' + | ||
(error.stack + "\n") + | ||
("URL: " + request.url + "\n") + | ||
("Payload: " + JSON.stringify(input, undefined, 2))); | ||
} | ||
response.json(resultJson); | ||
var result = { | ||
status: 'error', | ||
error: { message: helpers_1.getMessageFromError(error) } | ||
}; | ||
response.status(statusCode).json(result); | ||
}; | ||
exports.defaultResultHandler = defaultResultHandler; | ||
//# sourceMappingURL=result-handler.js.map |
@@ -19,19 +19,14 @@ "use strict"; | ||
var resultHandler = config.resultHandler || result_handler_1.defaultResultHandler; | ||
app.use([ | ||
config.server.jsonParser || express.json(), | ||
function (error, request, response, next) { | ||
if (error) { | ||
resultHandler({ | ||
error: error, request: request, response: response, logger: logger, | ||
input: request.body, | ||
output: null | ||
}); | ||
} | ||
else { | ||
next(); | ||
} | ||
var jsonParser = config.server.jsonParser || express.json(); | ||
var jsonFailureHandler = function (error, request, response, next) { | ||
if (!error) { | ||
return next(); | ||
} | ||
]); | ||
routing_1.initRouting({ app: app, routing: routing, logger: logger, config: config }); | ||
app.use(function (request, response) { | ||
return resultHandler({ | ||
error: error, request: request, response: response, logger: logger, | ||
input: request.body, | ||
output: null | ||
}); | ||
}; | ||
var lastResortHandler = function (request, response) { | ||
resultHandler({ | ||
@@ -43,3 +38,6 @@ request: request, response: response, logger: logger, | ||
}); | ||
}); | ||
}; | ||
app.use([jsonParser, jsonFailureHandler]); | ||
routing_1.initRouting({ app: app, routing: routing, logger: logger, config: config }); | ||
app.use(lastResortHandler); | ||
return app.listen(config.server.listen, function () { | ||
@@ -46,0 +44,0 @@ logger.info("Listening " + config.server.listen); |
{ | ||
"name": "express-zod-api", | ||
"version": "0.7.0", | ||
"version": "0.7.1", | ||
"description": "Express Zod API", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
@@ -40,10 +40,15 @@ # Express Zod API ![CI](https://github.com/RobinTail/express-zod-api/actions/workflows/node.js.yml/badge.svg) | ||
The API always operates object schemas for input and output. | ||
For GET method it provides `request.query` for middlewares and handler as `input` and all properties are `string | string[]`. | ||
Input schema may also have transformations *(see the example [below](#create-your-first-endpoint))*. | ||
For POST, PUT and PATCH the `input` is `request.body` *(parsed JSON)* so properties may have different types. | ||
Starting with version 0.7.0, union and intersection of object schemas are also supported (`.or()`, `.and()`). | ||
The handler's argument `options` comes from the returns of the middlewares, which can also supplement, transform the `input` argument. | ||
All inputs and outputs are validated against their object schemas and `ResultHandler` handles the output or possible validation errors. | ||
The object being validated is the `request.query` for GET request, the `request.body` for PUT, PATCH and POST requests, or their merging for DELETE requests. | ||
Middlewares can handle validated inputs and the original `request`, for example, to perform the authentication or provide the endpoint's handler with some request properties like the actual method. | ||
The returns of middlewares are combined into the `options` parameter available to the next middlewares and the endpoint's handler. | ||
The handler's parameter `input` combines the validated inputs of all connected middlewares along with the handler's one. | ||
The result that the handler returns goes to the `ResultHandler` which is responsible for transmission of the final response or possible error. | ||
All inputs and outputs are validated and there are also advanced powerful features like transformations and refinements. | ||
The diagram below can give you a better idea of the dataflow. | ||
![Dataflow](dataflow.svg) | ||
@@ -301,3 +306,3 @@ | ||
methods, input, output, | ||
handler: async (): Promise<z.infer<typeof output>> => ({ | ||
handler: async (): Promise<z.input<typeof output>> => ({ | ||
anything: 123, | ||
@@ -304,0 +309,0 @@ excessive: 'something' // error TS2322, ok! |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
88302
311