• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

RobinTail / express-zod-api / 13444086320

20 Feb 2025 08:28PM UTC coverage: 100.0%. First build
13444086320

Pull #2425

github

web-flow
Merge 60a537c42 into 23732b2fe
Pull Request #2425: Fix: async `errorHandler` for not found case

1253 of 1279 branches covered (97.97%)

1 of 1 new or added line in 1 file covered. (100.0%)

4223 of 4223 relevant lines covered (100.0%)

210.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/express-zod-api/src/config-type.ts
1
import type compression from "compression";
2
import { IRouter, Request, RequestHandler } from "express";
3
import type fileUpload from "express-fileupload";
4
import { ServerOptions } from "node:https";
5
import { BuiltinLoggerConfig } from "./builtin-logger";
6
import { AbstractEndpoint } from "./endpoint";
7
import { AbstractLogger, ActualLogger } from "./logger-helpers";
8
import { Method } from "./method";
9
import { AbstractResultHandler } from "./result-handler";
10
import { ListenOptions } from "node:net";
11
import { GetLogger } from "./server-helpers";
12

13
export type InputSource = keyof Pick<
14
  Request,
15
  "query" | "body" | "files" | "params" | "headers"
16
>;
17
export type InputSources = Record<Method, InputSource[]>;
18

19
type Headers = Record<string, string>;
20
type HeadersProvider = (params: {
21
  /** @desc The default headers to be overridden. */
22
  defaultHeaders: Headers;
23
  request: Request;
24
  endpoint: AbstractEndpoint;
25
  logger: ActualLogger;
26
}) => Headers | Promise<Headers>;
27

28
type ChildLoggerProvider = (params: {
29
  request: Request;
30
  parent: ActualLogger;
31
}) => ActualLogger | Promise<ActualLogger>;
32

33
export interface CommonConfig {
34
  /**
35
   * @desc Enables cross-origin resource sharing.
36
   * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
37
   * @desc You can override the default CORS headers by setting up a provider function here.
38
   */
39
  cors: boolean | HeadersProvider;
40
  /**
41
   * @desc How to respond to a request that uses a wrong method to an existing endpoint
42
   * @example 404 — Not found
43
   * @example 405 — Method not allowed, incl. the "Allow" header with a list of methods
44
   * @default 404
45
   * @todo consider changing default to 405 in v23
46
   * */
47
  wrongMethodBehavior?: 404 | 405;
48
  /**
49
   * @desc The ResultHandler to use for handling routing, parsing and upload errors
50
   * @default defaultResultHandler
51
   * @see defaultResultHandler
52
   */
53
  errorHandler?: AbstractResultHandler;
54
  /**
55
   * @desc Built-in logger configuration or an instance of any compatible logger.
56
   * @example { level: "debug", color: true }
57
   * @default { level: NODE_ENV === "production" ? "warn" : "debug", color: isSupported(), depth: 2 }
58
   * */
59
  logger?: Partial<BuiltinLoggerConfig> | AbstractLogger;
60
  /**
61
   * @desc A child logger returned by this function can override the logger in all handlers for each request
62
   * @example ({ parent }) => parent.child({ requestId: uuid() })
63
   * */
64
  childLoggerProvider?: ChildLoggerProvider;
65
  /**
66
   * @desc You can disable the startup logo.
67
   * @default true
68
   */
69
  startupLogo?: boolean;
70
  /**
71
   * @desc Which properties of request are combined into the input for endpoints and middlewares.
72
   * @desc The order matters: priority from lowest to highest
73
   * @default defaultInputSources
74
   * @see defaultInputSources
75
   */
76
  inputSources?: Partial<InputSources>;
77
}
78

79
type BeforeUpload = (params: {
80
  request: Request;
81
  logger: ActualLogger;
82
}) => void | Promise<void>;
83

84
type UploadOptions = Pick<
85
  fileUpload.Options,
86
  | "createParentPath"
87
  | "uriDecodeFileNames"
88
  | "safeFileNames"
89
  | "preserveExtension"
90
  | "useTempFiles"
91
  | "tempFileDir"
92
  | "debug"
93
  | "uploadTimeout"
94
  | "limits"
95
> & {
96
  /**
97
   * @desc The error to throw when the file exceeds the configured fileSize limit (handled by errorHandler).
98
   * @see limits
99
   * @override limitHandler
100
   * @example createHttpError(413, "The file is too large")
101
   * */
102
  limitError?: Error;
103
  /**
104
   * @desc A handler to execute before uploading — it can be used for restrictions by throwing an error.
105
   * @default undefined
106
   * @example ({ request }) => { throw createHttpError(403, "Not authorized"); }
107
   * */
108
  beforeUpload?: BeforeUpload;
109
};
110

111
type CompressionOptions = Pick<
112
  compression.CompressionOptions,
113
  "threshold" | "level" | "strategy" | "chunkSize" | "memLevel"
114
>;
115

116
interface GracefulOptions {
117
  /**
118
   * @desc Time given to drain ongoing requests before exit.
119
   * @default 1000
120
   * */
121
  timeout?: number;
122
  /**
123
   * @desc Process event (Signal) that triggers the graceful shutdown.
124
   * @see Signals
125
   * @default [SIGINT, SIGTERM]
126
   * */
127
  events?: string[];
128
}
129

130
type BeforeRouting = (params: {
131
  app: IRouter;
132
  /** @desc Returns child logger for the given request (if configured) or the configured logger otherwise */
133
  getLogger: GetLogger;
134
}) => void | Promise<void>;
135

136
export interface HttpConfig {
137
  /** @desc Port, UNIX socket or custom options. */
138
  listen: number | string | ListenOptions;
139
}
140

141
interface HttpsConfig extends HttpConfig {
142
  /** @desc At least "cert" and "key" options required. */
143
  options: ServerOptions;
144
}
145

146
export interface ServerConfig extends CommonConfig {
147
  /** @desc HTTP server configuration. */
148
  http?: HttpConfig;
149
  /** @desc HTTPS server configuration. */
150
  https?: HttpsConfig;
151
  /**
152
   * @desc Custom JSON parser.
153
   * @default express.json()
154
   * @link https://expressjs.com/en/4x/api.html#express.json
155
   * */
156
  jsonParser?: RequestHandler;
157
  /**
158
   * @desc Enable or configure uploads handling.
159
   * @default undefined
160
   * @requires express-fileupload
161
   * */
162
  upload?: boolean | UploadOptions;
163
  /**
164
   * @desc Enable or configure response compression.
165
   * @default undefined
166
   * @requires compression
167
   */
168
  compression?: boolean | CompressionOptions;
169
  /**
170
   * @desc Custom raw parser (assigns Buffer to request body)
171
   * @default express.raw()
172
   * @link https://expressjs.com/en/4x/api.html#express.raw
173
   * */
174
  rawParser?: RequestHandler;
175
  /**
176
   * @desc A code to execute before processing the Routing of your API (and before parsing).
177
   * @desc This can be a good place for express middlewares establishing their own routes.
178
   * @desc It can help to avoid making a DIY solution based on the attachRouting() approach.
179
   * @default undefined
180
   * @example ({ app }) => { app.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument)); }
181
   * */
182
  beforeRouting?: BeforeRouting;
183
  /**
184
   * @desc Rejects new connections and attempts to finish ongoing ones in the specified time before exit.
185
   * @default undefined
186
   * */
187
  gracefulShutdown?: boolean | GracefulOptions;
188
}
189

190
export interface AppConfig extends CommonConfig {
191
  /** @desc Your custom express app or express router instead. */
192
  app: IRouter;
193
}
194

195
export function createConfig(config: ServerConfig): ServerConfig;
196
export function createConfig(config: AppConfig): AppConfig;
197
export function createConfig(config: AppConfig | ServerConfig) {
4✔
198
  return config;
32✔
199
}
32✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc