barehttp 1.0.0 → 2.0.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 +185 -28
- package/lib/context/execution.d.ts +7 -0
- package/lib/context/execution.js +14 -0
- package/lib/context/index.d.ts +10 -0
- package/lib/context/index.js +46 -0
- package/lib/env.d.ts +5 -0
- package/lib/env.js +5 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +3 -0
- package/lib/logger/index.d.ts +16 -0
- package/lib/logger/index.js +26 -0
- package/lib/logger/serializers.d.ts +28 -0
- package/lib/logger/serializers.js +78 -0
- package/lib/middlewares/cookies/cookie-manager.d.ts +25 -0
- package/lib/middlewares/cookies/cookie-manager.js +68 -0
- package/lib/middlewares/cookies/signer.d.ts +8 -0
- package/lib/middlewares/cookies/signer.js +25 -0
- package/lib/middlewares/cors/cors.d.ts +38 -0
- package/lib/middlewares/cors/cors.js +164 -0
- package/lib/request.d.ts +84 -0
- package/lib/request.js +260 -0
- package/lib/schemas/custom-schema.d.ts +32 -0
- package/lib/schemas/custom-schema.js +62 -0
- package/lib/schemas/dirty-tsm.d.ts +1 -0
- package/lib/schemas/dirty-tsm.js +199 -0
- package/lib/schemas/generator.d.ts +7 -0
- package/lib/schemas/generator.js +179 -0
- package/lib/schemas/helpers.d.ts +27 -0
- package/lib/schemas/helpers.js +40 -0
- package/lib/schemas/json-schema.d.ts +2 -0
- package/lib/schemas/json-schema.js +48 -0
- package/lib/schemas/openami-schema.d.ts +2 -0
- package/lib/schemas/openami-schema.js +59 -0
- package/lib/schemas/project.d.ts +1 -0
- package/lib/schemas/project.js +1 -0
- package/lib/server.d.ts +154 -0
- package/lib/server.js +396 -0
- package/lib/utils/content-type.d.ts +54 -0
- package/lib/utils/content-type.js +54 -0
- package/lib/utils/http-methods.d.ts +11 -0
- package/lib/utils/http-methods.js +9 -0
- package/lib/utils/index.d.ts +4 -0
- package/lib/utils/index.js +4 -0
- package/lib/utils/safe-json.d.ts +2 -0
- package/lib/utils/safe-json.js +18 -0
- package/lib/utils/status-codes.d.ts +339 -0
- package/lib/utils/status-codes.js +339 -0
- package/lib/utils/status-phrases.d.ts +338 -0
- package/lib/utils/status-phrases.js +339 -0
- package/lib/websocket.d.ts +36 -0
- package/lib/websocket.js +176 -0
- package/package.json +64 -32
- package/.eslintrc.js +0 -47
- package/.github/workflows/release.yml +0 -27
- package/.jest-setup.js +0 -1
- package/jest.config.js +0 -8
- package/prettier.config.js +0 -6
- package/src/context/context.test.ts +0 -30
- package/src/context/execution.ts +0 -17
- package/src/context/index.ts +0 -61
- package/src/env.ts +0 -5
- package/src/examples/bare-http.ts +0 -36
- package/src/examples/express.ts +0 -11
- package/src/examples/fastify.ts +0 -18
- package/src/index.ts +0 -4
- package/src/logger/index.ts +0 -67
- package/src/logger/serializers.test.ts +0 -186
- package/src/logger/serializers.ts +0 -109
- package/src/middlewares/cookies/cookie-manager.ts +0 -86
- package/src/middlewares/cookies/signer.ts +0 -30
- package/src/report.ts +0 -25
- package/src/request.test.ts +0 -143
- package/src/request.ts +0 -277
- package/src/server.integration.test.ts +0 -296
- package/src/server.middlewares.test.ts +0 -93
- package/src/server.routes.test.ts +0 -71
- package/src/server.ts +0 -450
- package/src/utils/content-type.ts +0 -59
- package/src/utils/index.ts +0 -2
- package/src/utils/safe-json.ts +0 -17
- package/src/utils/status-codes.ts +0 -339
- package/src/utils/status-phrases.ts +0 -339
- package/tsconfig.json +0 -24
package/src/server.ts
DELETED
|
@@ -1,450 +0,0 @@
|
|
|
1
|
-
import Router from 'find-my-way';
|
|
2
|
-
|
|
3
|
-
import { BareRequest, CacheOpts } from './request';
|
|
4
|
-
import { logMe } from './logger';
|
|
5
|
-
import { context, enableContext, newContext } from './context';
|
|
6
|
-
import { generateReport } from './report';
|
|
7
|
-
import { CookieManagerOptions } from './middlewares/cookies/cookie-manager';
|
|
8
|
-
import { StatusCodes } from './utils';
|
|
9
|
-
|
|
10
|
-
import dns from 'dns';
|
|
11
|
-
import { createServer, IncomingMessage, ServerResponse, Server } from 'http';
|
|
12
|
-
import { Writable } from 'stream';
|
|
13
|
-
|
|
14
|
-
type Middleware = (flow: BareRequest) => Promise<void> | void;
|
|
15
|
-
type Handler = (flow: BareRequest) => any;
|
|
16
|
-
|
|
17
|
-
type RouteOpts<C> = {
|
|
18
|
-
disableCache?: C extends true ? C : undefined;
|
|
19
|
-
cache?: C extends true ? undefined : CacheOpts;
|
|
20
|
-
/**
|
|
21
|
-
* Request timeout handler in `ms`
|
|
22
|
-
*/
|
|
23
|
-
timeout?: number;
|
|
24
|
-
};
|
|
25
|
-
interface HandlerExposed {
|
|
26
|
-
<R extends `/${string}`, C>(setUp: {
|
|
27
|
-
route: R;
|
|
28
|
-
options?: RouteOpts<C>;
|
|
29
|
-
handler: Handler;
|
|
30
|
-
}): BareServer<any>;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
type ErrorHandler = (
|
|
34
|
-
err: any,
|
|
35
|
-
flow: BareRequest,
|
|
36
|
-
status?: typeof StatusCodes[keyof typeof StatusCodes],
|
|
37
|
-
) => void;
|
|
38
|
-
|
|
39
|
-
type BareOptions<A extends `${number}.${number}.${number}.${number}`> = {
|
|
40
|
-
middlewares?: Array<Middleware>;
|
|
41
|
-
serverPort?: number;
|
|
42
|
-
/**
|
|
43
|
-
* Address to bind the web server to
|
|
44
|
-
* Default '0.0.0.0'
|
|
45
|
-
*/
|
|
46
|
-
serverAddress?: A | 'localhost';
|
|
47
|
-
/**
|
|
48
|
-
* Enable request context storage
|
|
49
|
-
* Default `false`
|
|
50
|
-
*/
|
|
51
|
-
context?: boolean;
|
|
52
|
-
/**
|
|
53
|
-
* Enable request/response predefined logging
|
|
54
|
-
* Default `false`
|
|
55
|
-
*/
|
|
56
|
-
logging?: boolean;
|
|
57
|
-
errorHandlerMiddleware?: ErrorHandler;
|
|
58
|
-
/**
|
|
59
|
-
* Request time format in `seconds` or `milliseconds`
|
|
60
|
-
* Default 's' - seconds
|
|
61
|
-
*/
|
|
62
|
-
requestTimeFormat?: 's' | 'ms';
|
|
63
|
-
/**
|
|
64
|
-
* Control over cookies.
|
|
65
|
-
* This will enable automatic cookies decoding
|
|
66
|
-
*/
|
|
67
|
-
cookies?: boolean;
|
|
68
|
-
cookiesOptions?: CookieManagerOptions;
|
|
69
|
-
/**
|
|
70
|
-
* Log the resolved reverse DNS first hop for remote ip of the client (first proxy)
|
|
71
|
-
*/
|
|
72
|
-
reverseDns?: boolean;
|
|
73
|
-
/**
|
|
74
|
-
* Exposes a report with the routes usage.
|
|
75
|
-
* Default `false`
|
|
76
|
-
*/
|
|
77
|
-
statisticReport?: boolean;
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
type Methods = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
|
|
81
|
-
const HttpMethods = {
|
|
82
|
-
get: 'GET',
|
|
83
|
-
post: 'POST',
|
|
84
|
-
put: 'PUT',
|
|
85
|
-
delete: 'DELETE',
|
|
86
|
-
patch: 'PATCH',
|
|
87
|
-
options: 'OPTIONS',
|
|
88
|
-
head: 'HEAD',
|
|
89
|
-
} as const;
|
|
90
|
-
|
|
91
|
-
export type RouteReport = { hits: number; success: number; fails: number };
|
|
92
|
-
|
|
93
|
-
export class BareServer<A extends `${number}.${number}.${number}.${number}`> {
|
|
94
|
-
server: Server;
|
|
95
|
-
#middlewares: Array<Middleware> = [];
|
|
96
|
-
#routes: Map<string, RouteReport> = new Map();
|
|
97
|
-
#router = Router({ ignoreTrailingSlash: true });
|
|
98
|
-
#flows: Map<string, BareRequest> = new Map();
|
|
99
|
-
#errorHandler: ErrorHandler;
|
|
100
|
-
|
|
101
|
-
#runMiddlewaresSequence: (flow: BareRequest) => void = (_) => _;
|
|
102
|
-
|
|
103
|
-
constructor(private bareOptions: BareOptions<A> = {}) {
|
|
104
|
-
// init
|
|
105
|
-
this.server = createServer(this.#listener.bind(this));
|
|
106
|
-
this.attachGracefulHandlers();
|
|
107
|
-
|
|
108
|
-
// context setting
|
|
109
|
-
if (bareOptions.context) enableContext();
|
|
110
|
-
|
|
111
|
-
// middlewares settings
|
|
112
|
-
this.#errorHandler = bareOptions?.errorHandlerMiddleware || this.basicErrorHandler;
|
|
113
|
-
this.#middlewares.push(...(bareOptions?.middlewares || []));
|
|
114
|
-
if (bareOptions.statisticReport) this.registerReport();
|
|
115
|
-
|
|
116
|
-
return this;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
#listener = (request: IncomingMessage, response: ServerResponse) => {
|
|
120
|
-
const { requestTimeFormat, logging } = this.bareOptions;
|
|
121
|
-
|
|
122
|
-
const flow = new BareRequest(request, response, logging);
|
|
123
|
-
|
|
124
|
-
// init and attach request uuid to the context
|
|
125
|
-
if (this.bareOptions.context) {
|
|
126
|
-
newContext('request');
|
|
127
|
-
context.current?.store.set('id', flow.uuid);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (requestTimeFormat) flow['setTimeFormat'](requestTimeFormat);
|
|
131
|
-
|
|
132
|
-
// listener to remove already finished flow from the memory storage
|
|
133
|
-
request.on('close', () => this.#flows.delete(flow.uuid));
|
|
134
|
-
|
|
135
|
-
// attach a flow to the flow memory storage
|
|
136
|
-
this.#flows.set(flow.uuid, flow);
|
|
137
|
-
this.applyMiddlewares(flow.uuid).catch((e) => this.#errorHandler(e, flow, 400));
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* This function generates previously defined middlewares for the sequential execution
|
|
142
|
-
*/
|
|
143
|
-
#writeMiddlewares = () => {
|
|
144
|
-
const lines: string[] = [];
|
|
145
|
-
let order = 0;
|
|
146
|
-
const maxOrder = this.#middlewares.length;
|
|
147
|
-
|
|
148
|
-
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor;
|
|
149
|
-
|
|
150
|
-
if (maxOrder > 0) {
|
|
151
|
-
while (order <= maxOrder - 1) {
|
|
152
|
-
lines.push(`if (flow.sent) return;`);
|
|
153
|
-
lines.push(`await this.resolveMiddleware(${order}, flow);`);
|
|
154
|
-
order++;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const text = lines.join('\n');
|
|
159
|
-
|
|
160
|
-
this.#runMiddlewaresSequence = new AsyncFunction('flow', text);
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
private async applyMiddlewares(flowId: string) {
|
|
164
|
-
const flow = this.#flows.get(flowId);
|
|
165
|
-
if (!flow) {
|
|
166
|
-
throw new Error(`No flow been found for id ${flowId}, theres a sync mistake in the server.`); // should NEVER happen
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// invoke body stream consumption
|
|
170
|
-
await flow['readBody']();
|
|
171
|
-
|
|
172
|
-
// attach cookies middleware
|
|
173
|
-
if (this.bareOptions.cookies) {
|
|
174
|
-
flow['attachCookieManager'](this.bareOptions.cookiesOptions);
|
|
175
|
-
flow['populateCookies']();
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// to test in cloud provider
|
|
179
|
-
// this should resolve the name of the first hop from the dns chain
|
|
180
|
-
if (this.bareOptions.reverseDns) {
|
|
181
|
-
const remoteClient = await dns.promises.reverse(flow.remoteIp!);
|
|
182
|
-
flow['setRemoteClient'](remoteClient[0]);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if (this.#middlewares.length) await this.#runMiddlewaresSequence(flow);
|
|
186
|
-
|
|
187
|
-
// now route the request if middlewares did not send the response back
|
|
188
|
-
if (!flow.sent) {
|
|
189
|
-
this.#router.lookup(flow._originalRequest, flow._originalResponse);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* This handler is used in async generated middlewares runtime function
|
|
195
|
-
*/
|
|
196
|
-
private async resolveMiddleware(order: number, flow: BareRequest) {
|
|
197
|
-
try {
|
|
198
|
-
const response = this.#middlewares[order](flow);
|
|
199
|
-
if (response instanceof Promise) await response;
|
|
200
|
-
} catch (e) {
|
|
201
|
-
this.#errorHandler(e, flow);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
private setRoute(method: Methods, route: string, handler: Handler, opts?: RouteOpts<any>) {
|
|
206
|
-
const encode = this.encodeRoute(method, route);
|
|
207
|
-
this.#routes.set(encode, { hits: 0, fails: 0, success: 0 });
|
|
208
|
-
|
|
209
|
-
this.#router.on(method, route, (req, _, routeParams) => {
|
|
210
|
-
this.#routes.get(encode)!.hits++;
|
|
211
|
-
this.handleRoute(req, checkParams(routeParams), handler, encode, opts);
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
private registerReport() {
|
|
216
|
-
this.setRoute('GET', '/_report', (flow) => {
|
|
217
|
-
flow.setHeader('content-type', 'text/html');
|
|
218
|
-
flow.send(generateReport(this.#routes));
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
private handleRoute(
|
|
223
|
-
req: IncomingMessage,
|
|
224
|
-
routeParams: { [k: string]: string | undefined },
|
|
225
|
-
handle: Handler,
|
|
226
|
-
encodedRoute: string,
|
|
227
|
-
opts?: RouteOpts<any>,
|
|
228
|
-
) {
|
|
229
|
-
const flow = this.#flows.get((req as any).id)!;
|
|
230
|
-
|
|
231
|
-
// apply possible route options
|
|
232
|
-
if (opts?.disableCache) flow.disableCache();
|
|
233
|
-
if (opts?.cache) flow.setCache(opts.cache);
|
|
234
|
-
if (opts?.timeout) flow['attachTimeout'](opts.timeout);
|
|
235
|
-
|
|
236
|
-
// populate with route params
|
|
237
|
-
if (routeParams) flow['setParams'](routeParams);
|
|
238
|
-
|
|
239
|
-
// attach a general statistic reports counter
|
|
240
|
-
if (this.bareOptions.statisticReport) {
|
|
241
|
-
flow._originalRequest.on('close', () => {
|
|
242
|
-
if (flow.statusToSend < 300 && flow.statusToSend >= 200) {
|
|
243
|
-
this.#routes.get(encodedRoute)!.success++;
|
|
244
|
-
} else {
|
|
245
|
-
this.#routes.get(encodedRoute)!.fails++;
|
|
246
|
-
}
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
try {
|
|
251
|
-
const routeReturn = handle.bind(undefined)(flow);
|
|
252
|
-
if (routeReturn instanceof Promise) {
|
|
253
|
-
routeReturn
|
|
254
|
-
.catch((e) => this.#errorHandler(e, flow))
|
|
255
|
-
.then((result) => this.soundRouteReturn(result, flow));
|
|
256
|
-
} else {
|
|
257
|
-
this.soundRouteReturn(routeReturn, flow);
|
|
258
|
-
}
|
|
259
|
-
} catch (e) {
|
|
260
|
-
this.#errorHandler(e, flow);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
private soundRouteReturn(response: any, flow: BareRequest) {
|
|
265
|
-
if (flow.sent) return;
|
|
266
|
-
if (!response) flow.send();
|
|
267
|
-
|
|
268
|
-
switch (response.constructor) {
|
|
269
|
-
case Uint8Array:
|
|
270
|
-
case Uint16Array:
|
|
271
|
-
case Uint32Array:
|
|
272
|
-
case Buffer:
|
|
273
|
-
case String:
|
|
274
|
-
flow.send(response);
|
|
275
|
-
break;
|
|
276
|
-
case Boolean:
|
|
277
|
-
case Number:
|
|
278
|
-
flow.send('' + response);
|
|
279
|
-
case Writable:
|
|
280
|
-
flow.stream(response);
|
|
281
|
-
break;
|
|
282
|
-
case Object:
|
|
283
|
-
flow.json(response);
|
|
284
|
-
break;
|
|
285
|
-
default:
|
|
286
|
-
logMe.warn('Unknown type to send');
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
private encodeRoute(method: string, route: string) {
|
|
291
|
-
return `${method} ${route}`;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
private basicErrorHandler(
|
|
295
|
-
e: any,
|
|
296
|
-
flow: BareRequest,
|
|
297
|
-
status?: typeof StatusCodes[keyof typeof StatusCodes],
|
|
298
|
-
) {
|
|
299
|
-
flow.status(status ?? 500);
|
|
300
|
-
flow.json({ ...e, message: e.message, stack: e.stack });
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
private attachGracefulHandlers() {
|
|
304
|
-
const graceful = async (code = 0) => {
|
|
305
|
-
await this.stop();
|
|
306
|
-
process.exit(code);
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
// Stop graceful
|
|
310
|
-
process.on('uncaughtException', (err) => {
|
|
311
|
-
console.error(err);
|
|
312
|
-
graceful(1);
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
process.on('unhandledRejection', (err) => {
|
|
316
|
-
console.error(err);
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
process.on('SIGTERM', graceful);
|
|
320
|
-
process.on('SIGINT', graceful);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// ========= PUBLIC APIS ==========
|
|
324
|
-
|
|
325
|
-
start(cb?: (address: string) => void) {
|
|
326
|
-
this.#writeMiddlewares();
|
|
327
|
-
|
|
328
|
-
const port = this.bareOptions?.serverPort || process.env.PORT || 3000;
|
|
329
|
-
const address = this.bareOptions?.serverAddress || '0.0.0.0';
|
|
330
|
-
|
|
331
|
-
// https://nodejs.org/api/net.html#net_server_listen_port_host_backlog_callback
|
|
332
|
-
return new Promise<void>((res) =>
|
|
333
|
-
this.server.listen(+port, address, undefined, () => {
|
|
334
|
-
cb ? cb(`http://0.0.0.0:${port}`) : void 0;
|
|
335
|
-
res();
|
|
336
|
-
}),
|
|
337
|
-
);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
stop(cb?: (e?: Error) => void) {
|
|
341
|
-
for (const flow of this.#flows.values()) {
|
|
342
|
-
if (!flow.sent) {
|
|
343
|
-
flow.status(500);
|
|
344
|
-
flow.send('Server terminated');
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
return new Promise<void>((res, rej) => {
|
|
348
|
-
this.server?.close((e) => {
|
|
349
|
-
if (e) {
|
|
350
|
-
rej(e);
|
|
351
|
-
cb?.(e);
|
|
352
|
-
} else {
|
|
353
|
-
cb?.();
|
|
354
|
-
res();
|
|
355
|
-
}
|
|
356
|
-
});
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
use(middleware: Middleware) {
|
|
361
|
-
this.#middlewares.push(middleware);
|
|
362
|
-
return this;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
getMiddlewares(): Middleware[] {
|
|
366
|
-
return this.#middlewares;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
setCustomErrorHandler(eh: ErrorHandler) {
|
|
370
|
-
this.#errorHandler = eh;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
getRoutes() {
|
|
374
|
-
return [...this.#routes.keys()];
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
get route() {
|
|
378
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
379
|
-
const self = this;
|
|
380
|
-
return new Proxy(
|
|
381
|
-
{},
|
|
382
|
-
{
|
|
383
|
-
get(_, key) {
|
|
384
|
-
if (typeof key === 'symbol') return self;
|
|
385
|
-
|
|
386
|
-
if (Object.keys(HttpMethods).includes(key as string)) {
|
|
387
|
-
return function (routeSetUp: any) {
|
|
388
|
-
checkRouteSetUp(routeSetUp, key);
|
|
389
|
-
self.setRoute(
|
|
390
|
-
HttpMethods[key],
|
|
391
|
-
routeSetUp.route,
|
|
392
|
-
routeSetUp.handler,
|
|
393
|
-
routeSetUp.options,
|
|
394
|
-
);
|
|
395
|
-
return self;
|
|
396
|
-
};
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
return self;
|
|
400
|
-
},
|
|
401
|
-
},
|
|
402
|
-
) as Readonly<
|
|
403
|
-
{
|
|
404
|
-
[K in keyof typeof HttpMethods]: HandlerExposed;
|
|
405
|
-
}
|
|
406
|
-
>;
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
function checkRouteSetUp(routeSetUp: { [setting: string]: any }, key: string) {
|
|
411
|
-
if (typeof routeSetUp.route !== 'string') {
|
|
412
|
-
throw new TypeError(`A route path for the method ${key} is not a a string`);
|
|
413
|
-
} else if (routeSetUp.route[0] !== '/') {
|
|
414
|
-
throw new SyntaxError(
|
|
415
|
-
`A route path should start with '/' for route ${routeSetUp.route} for method ${key}`,
|
|
416
|
-
);
|
|
417
|
-
} else if (routeSetUp.route[1] === '/') {
|
|
418
|
-
throw new SyntaxError(
|
|
419
|
-
`Declared route ${routeSetUp.route} for method ${key} is not correct, review the syntax`,
|
|
420
|
-
);
|
|
421
|
-
} else if (typeof routeSetUp.handler !== 'function') {
|
|
422
|
-
throw new TypeError(
|
|
423
|
-
`Handler for the route ${routeSetUp.route} for method ${key} is not a function`,
|
|
424
|
-
);
|
|
425
|
-
} else if (
|
|
426
|
-
routeSetUp.options?.timeout &&
|
|
427
|
-
typeof routeSetUp.options.timeout !== 'number' &&
|
|
428
|
-
!Number.isFinite(routeSetUp.options.timeout)
|
|
429
|
-
) {
|
|
430
|
-
throw new TypeError(
|
|
431
|
-
`Only numeric values are valid per-route timeout, submitted ${routeSetUp.options.timeout}`,
|
|
432
|
-
);
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
function checkParams(params: { [param: string]: string | undefined }) {
|
|
437
|
-
if (!params || Object.keys(params).length === 0) return params;
|
|
438
|
-
for (const [param, value] of Object.entries(params)) {
|
|
439
|
-
if (value === undefined) continue;
|
|
440
|
-
|
|
441
|
-
if (/(\.\/)(\.\.)(\\.)/.test(decodeURI(value))) {
|
|
442
|
-
logMe.warn(
|
|
443
|
-
`Param ${param} value ${value} was redacted because contained dangerous characters`,
|
|
444
|
-
);
|
|
445
|
-
param[param] = 'REDACTED';
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
return params;
|
|
450
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
export const ContentType = {
|
|
2
|
-
'application/EDI-X12': 'application/EDI-X12',
|
|
3
|
-
'application/EDIFACT': 'application/EDIFACT',
|
|
4
|
-
'application/javascript': 'application/javascript',
|
|
5
|
-
'application/octet-stream': 'application/octet-stream',
|
|
6
|
-
'application/ogg': 'application/ogg',
|
|
7
|
-
'application/pdf': 'application/pdf',
|
|
8
|
-
'application/xhtml+xml': 'application/xhtml+xml',
|
|
9
|
-
'application/x-shockwave-flash': 'application/x-shockwave-flash',
|
|
10
|
-
'application/json': 'application/json',
|
|
11
|
-
'application/ld+json': 'application/ld+json',
|
|
12
|
-
'application/xml': 'application/xml',
|
|
13
|
-
'application/zip': 'application/zip',
|
|
14
|
-
'application/x-www-form-urlencoded': 'application/x-www-form-urlencoded',
|
|
15
|
-
'audio/mpeg': 'audio/mpeg',
|
|
16
|
-
'audio/x-ms-wma': 'audio/x-ms-wma',
|
|
17
|
-
'audio/vnd.rn-realaudio': 'audio/vnd.rn-realaudio',
|
|
18
|
-
'audio/x-wav': 'audio/x-wav',
|
|
19
|
-
'image/gif': 'image/gif',
|
|
20
|
-
'image/jpeg': 'image/jpeg',
|
|
21
|
-
'image/png': 'image/png',
|
|
22
|
-
'image/tiff': 'image/tiff',
|
|
23
|
-
'image/vnd.microsoft.icon': 'image/vnd.microsoft.icon',
|
|
24
|
-
'image/x-icon': 'image/x-icon',
|
|
25
|
-
'image/vnd.djvu': 'image/vnd.djvu',
|
|
26
|
-
'image/svg+xml': 'image/svg+xml',
|
|
27
|
-
'multipart/mixed': 'multipart/mixed',
|
|
28
|
-
'multipart/alternative': 'multipart/alternative',
|
|
29
|
-
'multipart/related': 'multipart/related', // (using by MHTML (HTML mail).)
|
|
30
|
-
'multipart/form-data': 'multipart/form-data',
|
|
31
|
-
'text/css': 'text/css',
|
|
32
|
-
'text/csv': 'text/csv',
|
|
33
|
-
'text/html': 'text/html',
|
|
34
|
-
'text/plain': 'text/plain',
|
|
35
|
-
'text/xml': 'text/xml',
|
|
36
|
-
'video/mpeg': 'video/mpeg',
|
|
37
|
-
'video/mp4': 'video/mp4',
|
|
38
|
-
'video/quicktime': 'video/quicktime',
|
|
39
|
-
'video/x-ms-wmv': 'video/x-ms-wmv',
|
|
40
|
-
'video/x-msvideo': 'video/x-msvideo',
|
|
41
|
-
'video/x-flv': 'video/x-flv',
|
|
42
|
-
'video/webm': 'video/webm',
|
|
43
|
-
'application/vnd.oasis.opendocument.text': 'application/vnd.oasis.opendocument.text',
|
|
44
|
-
'application/vnd.oasis.opendocument.spreadsheet':
|
|
45
|
-
'application/vnd.oasis.opendocument.spreadsheet',
|
|
46
|
-
'application/vnd.oasis.opendocument.presentation':
|
|
47
|
-
'application/vnd.oasis.opendocument.presentation',
|
|
48
|
-
'application/vnd.oasis.opendocument.graphics': 'application/vnd.oasis.opendocument.graphics',
|
|
49
|
-
'application/vnd.ms-excel': 'application/vnd.ms-excel',
|
|
50
|
-
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
|
|
51
|
-
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
52
|
-
'application/vnd.ms-powerpoint': 'application/vnd.ms-powerpoint',
|
|
53
|
-
'application/vnd.openxmlformats-officedocument.presentationml.presentation':
|
|
54
|
-
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
|
55
|
-
'application/msword': 'application/msword',
|
|
56
|
-
'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
|
|
57
|
-
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
58
|
-
'application/vnd.mozilla.xul+xml': 'application/vnd.mozilla.xul+xml',
|
|
59
|
-
} as const;
|
package/src/utils/index.ts
DELETED
package/src/utils/safe-json.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export const JSONStringify = (data: any) => {
|
|
2
|
-
try {
|
|
3
|
-
return JSON.stringify(data);
|
|
4
|
-
} catch (e) {
|
|
5
|
-
console.log('Error stringifying, data not serializable', e);
|
|
6
|
-
return null;
|
|
7
|
-
}
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export const JSONParse = (data: any) => {
|
|
11
|
-
try {
|
|
12
|
-
return JSON.parse(data);
|
|
13
|
-
} catch (e) {
|
|
14
|
-
console.log('Error parsing, data not deserializable', e);
|
|
15
|
-
return e;
|
|
16
|
-
}
|
|
17
|
-
};
|