-
-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathconfig-type.ts
207 lines (192 loc) · 6.38 KB
/
config-type.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
import type compression from "compression";
import { IRouter, Request, RequestHandler } from "express";
import type fileUpload from "express-fileupload";
import { ServerOptions } from "node:https";
import { BuiltinLoggerConfig } from "./builtin-logger";
import { AbstractEndpoint } from "./endpoint";
import { AbstractLogger, ActualLogger } from "./logger-helpers";
import { Method } from "./method";
import { AbstractResultHandler } from "./result-handler";
import { ListenOptions } from "node:net";
import { GetLogger } from "./server-helpers";
export type InputSource = keyof Pick<
Request,
"query" | "body" | "files" | "params" | "headers"
>;
export type InputSources = Record<Method, InputSource[]>;
type Headers = Record<string, string>;
type HeadersProvider = (params: {
/** @desc The default headers to be overridden. */
defaultHeaders: Headers;
request: Request;
endpoint: AbstractEndpoint;
logger: ActualLogger;
}) => Headers | Promise<Headers>;
export type TagsConfig<TAG extends string> = Record<
TAG,
string | { description: string; url?: string }
>;
type ChildLoggerProvider = (params: {
request: Request;
parent: ActualLogger;
}) => ActualLogger | Promise<ActualLogger>;
export interface CommonConfig<TAG extends string = string> {
/**
* @desc Enables cross-origin resource sharing.
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
* @desc You can override the default CORS headers by setting up a provider function here.
*/
cors: boolean | HeadersProvider;
/**
* @desc The ResultHandler to use for handling routing, parsing and upload errors
* @default defaultResultHandler
* @see defaultResultHandler
*/
errorHandler?: AbstractResultHandler;
/**
* @desc Built-in logger configuration or an instance of any compatible logger.
* @example { level: "debug", color: true }
* @default { level: NODE_ENV === "production" ? "warn" : "debug", color: isSupported(), depth: 2 }
* */
logger?: Partial<BuiltinLoggerConfig> | AbstractLogger;
/**
* @desc A child logger returned by this function can override the logger in all handlers for each request
* @example ({ parent }) => parent.child({ requestId: uuid() })
* */
childLoggerProvider?: ChildLoggerProvider;
/**
* @desc You can disable the startup logo.
* @default true
*/
startupLogo?: boolean;
/**
* @desc Which properties of request are combined into the input for endpoints and middlewares.
* @desc The order matters: priority from lowest to highest
* @default defaultInputSources
* @see defaultInputSources
*/
inputSources?: Partial<InputSources>;
/**
* @desc Optional endpoints tagging configuration.
* @example: { users: "Everything about the users" }
*/
tags?: TagsConfig<TAG>;
}
type BeforeUpload = (params: {
request: Request;
logger: ActualLogger;
}) => void | Promise<void>;
type UploadOptions = Pick<
fileUpload.Options,
| "createParentPath"
| "uriDecodeFileNames"
| "safeFileNames"
| "preserveExtension"
| "useTempFiles"
| "tempFileDir"
| "debug"
| "uploadTimeout"
| "limits"
> & {
/**
* @desc The error to throw when the file exceeds the configured fileSize limit (handled by errorHandler).
* @see limits
* @override limitHandler
* @example createHttpError(413, "The file is too large")
* */
limitError?: Error;
/**
* @desc A handler to execute before uploading — it can be used for restrictions by throwing an error.
* @default undefined
* @example ({ request }) => { throw createHttpError(403, "Not authorized"); }
* */
beforeUpload?: BeforeUpload;
};
type CompressionOptions = Pick<
compression.CompressionOptions,
"threshold" | "level" | "strategy" | "chunkSize" | "memLevel"
>;
interface GracefulOptions {
/**
* @desc Time given to drain ongoing requests before exit.
* @default 1000
* */
timeout?: number;
/**
* @desc Process event (Signal) that triggers the graceful shutdown.
* @see Signals
* @default [SIGINT, SIGTERM]
* */
events?: string[];
}
type BeforeRouting = (params: {
app: IRouter;
/** @desc Returns child logger for the given request (if configured) or the configured logger otherwise */
getLogger: GetLogger;
}) => void | Promise<void>;
export interface HttpConfig {
/** @desc Port, UNIX socket or custom options. */
listen: number | string | ListenOptions;
}
interface HttpsConfig extends HttpConfig {
/** @desc At least "cert" and "key" options required. */
options: ServerOptions;
}
export interface ServerConfig<TAG extends string = string>
extends CommonConfig<TAG> {
/** @desc HTTP server configuration. */
http?: HttpConfig;
/** @desc HTTPS server configuration. */
https?: HttpsConfig;
/**
* @desc Custom JSON parser.
* @default express.json()
* @link https://expressjs.com/en/4x/api.html#express.json
* */
jsonParser?: RequestHandler;
/**
* @desc Enable or configure uploads handling.
* @default undefined
* @requires express-fileupload
* */
upload?: boolean | UploadOptions;
/**
* @desc Enable or configure response compression.
* @default undefined
* @requires compression
*/
compression?: boolean | CompressionOptions;
/**
* @desc Custom raw parser (assigns Buffer to request body)
* @default express.raw()
* @link https://expressjs.com/en/4x/api.html#express.raw
* */
rawParser?: RequestHandler;
/**
* @desc A code to execute before processing the Routing of your API (and before parsing).
* @desc This can be a good place for express middlewares establishing their own routes.
* @desc It can help to avoid making a DIY solution based on the attachRouting() approach.
* @default undefined
* @example ({ app }) => { app.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument)); }
* */
beforeRouting?: BeforeRouting;
/**
* @desc Rejects new connections and attempts to finish ongoing ones in the specified time before exit.
* @default undefined
* */
gracefulShutdown?: boolean | GracefulOptions;
}
export interface AppConfig<TAG extends string = string>
extends CommonConfig<TAG> {
/** @desc Your custom express app or express router instead. */
app: IRouter;
}
export function createConfig<TAG extends string>(
config: ServerConfig<TAG>,
): ServerConfig<TAG>;
export function createConfig<TAG extends string>(
config: AppConfig<TAG>,
): AppConfig<TAG>;
export function createConfig(config: AppConfig | ServerConfig) {
return config;
}