@jaypie/express 1.1.16 → 1.1.18-rc.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.
Files changed (65) hide show
  1. package/dist/cjs/__tests__/constants.spec.d.ts +1 -0
  2. package/dist/cjs/__tests__/cors.helper.spec.d.ts +1 -0
  3. package/dist/cjs/__tests__/cors.helper.supertest.spec.d.ts +1 -0
  4. package/dist/cjs/__tests__/decorateResponse.helper.spec.d.ts +1 -0
  5. package/dist/cjs/__tests__/echo.handler.spec.d.ts +1 -0
  6. package/dist/cjs/__tests__/expressHandler.spec.d.ts +1 -0
  7. package/dist/cjs/__tests__/getCurrentInvokeUuid.adapter.spec.d.ts +1 -0
  8. package/dist/cjs/__tests__/http.handler.spec.d.ts +1 -0
  9. package/dist/cjs/__tests__/index.spec.d.ts +1 -0
  10. package/dist/cjs/__tests__/routes.spec.d.ts +1 -0
  11. package/dist/cjs/__tests__/summarizeRequest.helper.spec.d.ts +1 -0
  12. package/dist/cjs/__tests__/summarizeResponse.helper.spec.d.ts +1 -0
  13. package/dist/cjs/__tests__/supertest.spec.d.ts +1 -0
  14. package/dist/cjs/constants.d.ts +8 -0
  15. package/dist/cjs/cors.helper.d.ts +9 -0
  16. package/dist/cjs/decorateResponse.helper.d.ts +7 -0
  17. package/dist/cjs/echo.handler.d.ts +8 -0
  18. package/dist/cjs/expressHandler.d.ts +14 -0
  19. package/dist/cjs/getCurrentInvokeUuid.adapter.d.ts +2 -0
  20. package/dist/cjs/http.handler.d.ts +4 -0
  21. package/dist/cjs/index.cjs +632 -0
  22. package/dist/cjs/index.cjs.map +1 -0
  23. package/{src/index.js → dist/cjs/index.d.ts} +2 -0
  24. package/dist/cjs/routes.d.ts +8 -0
  25. package/dist/cjs/summarizeRequest.helper.d.ts +11 -0
  26. package/dist/cjs/summarizeResponse.helper.d.ts +9 -0
  27. package/dist/esm/__tests__/constants.spec.d.ts +1 -0
  28. package/dist/esm/__tests__/cors.helper.spec.d.ts +1 -0
  29. package/dist/esm/__tests__/cors.helper.supertest.spec.d.ts +1 -0
  30. package/dist/esm/__tests__/decorateResponse.helper.spec.d.ts +1 -0
  31. package/dist/esm/__tests__/echo.handler.spec.d.ts +1 -0
  32. package/dist/esm/__tests__/expressHandler.spec.d.ts +1 -0
  33. package/dist/esm/__tests__/getCurrentInvokeUuid.adapter.spec.d.ts +1 -0
  34. package/dist/esm/__tests__/http.handler.spec.d.ts +1 -0
  35. package/dist/esm/__tests__/index.spec.d.ts +1 -0
  36. package/dist/esm/__tests__/routes.spec.d.ts +1 -0
  37. package/dist/esm/__tests__/summarizeRequest.helper.spec.d.ts +1 -0
  38. package/dist/esm/__tests__/summarizeResponse.helper.spec.d.ts +1 -0
  39. package/dist/esm/__tests__/supertest.spec.d.ts +1 -0
  40. package/dist/esm/constants.d.ts +8 -0
  41. package/dist/esm/cors.helper.d.ts +9 -0
  42. package/dist/esm/decorateResponse.helper.d.ts +7 -0
  43. package/dist/esm/echo.handler.d.ts +8 -0
  44. package/dist/esm/expressHandler.d.ts +14 -0
  45. package/dist/esm/getCurrentInvokeUuid.adapter.d.ts +2 -0
  46. package/dist/esm/http.handler.d.ts +4 -0
  47. package/dist/esm/index.d.ts +7 -0
  48. package/dist/esm/index.js +619 -0
  49. package/dist/esm/index.js.map +1 -0
  50. package/dist/esm/routes.d.ts +8 -0
  51. package/dist/esm/summarizeRequest.helper.d.ts +11 -0
  52. package/dist/esm/summarizeResponse.helper.d.ts +9 -0
  53. package/package.json +35 -25
  54. package/index.d.ts +0 -68
  55. package/rollup.config.mjs +0 -22
  56. package/src/constants.js +0 -12
  57. package/src/cors.helper.js +0 -110
  58. package/src/decorateResponse.helper.js +0 -90
  59. package/src/echo.handler.js +0 -31
  60. package/src/expressHandler.js +0 -346
  61. package/src/getCurrentInvokeUuid.adapter.js +0 -33
  62. package/src/http.handler.js +0 -73
  63. package/src/routes.js +0 -43
  64. package/src/summarizeRequest.helper.js +0 -28
  65. package/src/summarizeResponse.helper.js +0 -25
@@ -0,0 +1,632 @@
1
+ 'use strict';
2
+
3
+ var errors = require('@jaypie/errors');
4
+ var core = require('@jaypie/core');
5
+ var expressCors = require('cors');
6
+ var datadog = require('@jaypie/datadog');
7
+ var serverlessExpress = require('@codegenie/serverless-express');
8
+
9
+ //
10
+ //
11
+ // Constants
12
+ //
13
+ const EXPRESS = {
14
+ PATH: {
15
+ ANY: "*",
16
+ ID: "/:id",
17
+ ROOT: /^\/?$/,
18
+ },
19
+ };
20
+
21
+ //
22
+ //
23
+ // Constants
24
+ //
25
+ const HTTP_PROTOCOL = "http://";
26
+ const HTTPS_PROTOCOL = "https://";
27
+ const SANDBOX_ENV = "sandbox";
28
+ //
29
+ //
30
+ // Helper Functions
31
+ //
32
+ const ensureProtocol = (url) => {
33
+ if (!url)
34
+ return url;
35
+ if (url.startsWith(HTTP_PROTOCOL) || url.startsWith(HTTPS_PROTOCOL))
36
+ return url;
37
+ return HTTPS_PROTOCOL + url;
38
+ };
39
+ const dynamicOriginCallbackHandler = (origin) => {
40
+ return (requestOrigin, callback) => {
41
+ // Handle wildcard origin
42
+ if (origin === "*") {
43
+ callback(null, true);
44
+ return;
45
+ }
46
+ // Allow requests with no origin (like mobile apps, curl, etc)
47
+ if (!requestOrigin) {
48
+ callback(null, true);
49
+ return;
50
+ }
51
+ const allowedOrigins = [];
52
+ if (process.env.BASE_URL) {
53
+ allowedOrigins.push(ensureProtocol(process.env.BASE_URL));
54
+ }
55
+ if (process.env.PROJECT_BASE_URL) {
56
+ allowedOrigins.push(ensureProtocol(process.env.PROJECT_BASE_URL));
57
+ }
58
+ if (origin) {
59
+ const additionalOrigins = core.force.array(origin);
60
+ allowedOrigins.push(...additionalOrigins);
61
+ }
62
+ // Add localhost origins in sandbox
63
+ if (process.env.PROJECT_ENV === SANDBOX_ENV ||
64
+ core.envBoolean("PROJECT_SANDBOX_MODE")) {
65
+ allowedOrigins.push("http://localhost");
66
+ allowedOrigins.push(/^http:\/\/localhost:\d+$/);
67
+ }
68
+ const isAllowed = allowedOrigins.some((allowed) => {
69
+ if (allowed instanceof RegExp) {
70
+ return allowed.test(requestOrigin);
71
+ }
72
+ return requestOrigin.includes(allowed);
73
+ });
74
+ if (isAllowed) {
75
+ callback(null, true);
76
+ }
77
+ else {
78
+ callback(new errors.CorsError());
79
+ }
80
+ };
81
+ };
82
+ //
83
+ //
84
+ // Main
85
+ //
86
+ const corsHelper = (config = {}) => {
87
+ const { origin, overrides = {} } = config;
88
+ const options = {
89
+ origin: dynamicOriginCallbackHandler(origin),
90
+ // * The default behavior is to allow any headers and methods so they are not included here
91
+ ...overrides,
92
+ };
93
+ return expressCors(options);
94
+ };
95
+ var cors_helper = (config) => {
96
+ const cors = corsHelper(config);
97
+ return (req, res, next) => {
98
+ cors(req, res, (error) => {
99
+ if (error) {
100
+ const corsError = error;
101
+ res.status(corsError.status);
102
+ res.setHeader("Content-Type", "application/json");
103
+ return res.json(corsError.body());
104
+ }
105
+ next();
106
+ });
107
+ };
108
+ };
109
+
110
+ //
111
+ //
112
+ // Helper Functions
113
+ //
114
+ // Adapter for the "@codegenie/serverless-express" uuid
115
+ function getServerlessExpressUuid() {
116
+ const currentInvoke = serverlessExpress.getCurrentInvoke();
117
+ if (currentInvoke &&
118
+ currentInvoke.context &&
119
+ currentInvoke.context.awsRequestId) {
120
+ return currentInvoke.context.awsRequestId;
121
+ }
122
+ return undefined;
123
+ }
124
+ //
125
+ //
126
+ // Main
127
+ //
128
+ const getCurrentInvokeUuid = () => getServerlessExpressUuid();
129
+
130
+ //
131
+ //
132
+ // Main
133
+ //
134
+ const decorateResponse = (res, { handler = "", version = process.env.PROJECT_VERSION, } = {}) => {
135
+ const log = core.log.lib({
136
+ lib: core.JAYPIE.LIB.EXPRESS,
137
+ });
138
+ //
139
+ //
140
+ // Validate
141
+ //
142
+ if (typeof res !== "object" || res === null) {
143
+ log.warn("decorateResponse called but response is not an object");
144
+ return;
145
+ }
146
+ try {
147
+ //
148
+ //
149
+ // Decorate Headers
150
+ //
151
+ // X-Powered-By, override "Express" but nothing else
152
+ if (!res.get(core.HTTP.HEADER.POWERED_BY) ||
153
+ res.get(core.HTTP.HEADER.POWERED_BY) === "Express") {
154
+ res.set(core.HTTP.HEADER.POWERED_BY, core.JAYPIE.LIB.EXPRESS);
155
+ }
156
+ // X-Project-Environment
157
+ if (process.env.PROJECT_ENV) {
158
+ res.set(core.HTTP.HEADER.PROJECT.ENVIRONMENT, process.env.PROJECT_ENV);
159
+ }
160
+ // X-Project-Handler
161
+ if (handler) {
162
+ res.set(core.HTTP.HEADER.PROJECT.HANDLER, handler);
163
+ }
164
+ // X-Project-Invocation
165
+ const currentInvoke = getCurrentInvokeUuid();
166
+ if (currentInvoke) {
167
+ res.set(core.HTTP.HEADER.PROJECT.INVOCATION, currentInvoke);
168
+ }
169
+ // X-Project-Key
170
+ if (process.env.PROJECT_KEY) {
171
+ res.set(core.HTTP.HEADER.PROJECT.KEY, process.env.PROJECT_KEY);
172
+ }
173
+ // X-Project-Version
174
+ if (version) {
175
+ res.set(core.HTTP.HEADER.PROJECT.VERSION, version);
176
+ }
177
+ //
178
+ //
179
+ // Error Handling
180
+ //
181
+ }
182
+ catch (error) {
183
+ log.warn("decorateResponse caught an internal error");
184
+ log.var({ error });
185
+ }
186
+ };
187
+ //
188
+ //
189
+ // Footnotes
190
+ //
191
+ // This is a "utility" function but it needs a lot of "context"
192
+ // about the environment's secret parameters, the special adapter,
193
+ // HTTP, etc. There must be a better way to organize this
194
+
195
+ //
196
+ //
197
+ // Function Definition
198
+ //
199
+ function summarizeRequest(req) {
200
+ // If body is a buffer, convert it to a string
201
+ let { body } = req;
202
+ if (Buffer.isBuffer(body)) {
203
+ body = body.toString();
204
+ }
205
+ return {
206
+ baseUrl: req.baseUrl,
207
+ body,
208
+ headers: req.headers,
209
+ method: req.method,
210
+ query: req.query,
211
+ url: req.url,
212
+ };
213
+ }
214
+
215
+ //
216
+ //
217
+ // Function Definition
218
+ //
219
+ function summarizeResponse(res, extras) {
220
+ const response = {
221
+ statusCode: res.statusCode,
222
+ statusMessage: res.statusMessage,
223
+ };
224
+ if (typeof res.getHeaders === "function") {
225
+ response.headers = res.getHeaders();
226
+ }
227
+ if (typeof extras === "object" && extras !== null) {
228
+ Object.assign(response, extras);
229
+ }
230
+ return response;
231
+ }
232
+
233
+ // Cast logger to extended interface for runtime features not in type definitions
234
+ const logger = core.log;
235
+ function expressHandler(handlerOrOptions, optionsOrHandler) {
236
+ /* eslint-enable no-redeclare */
237
+ let handler;
238
+ let options;
239
+ // If handler is an object and options is a function, swap them
240
+ if (typeof handlerOrOptions === "object" &&
241
+ typeof optionsOrHandler === "function") {
242
+ handler = optionsOrHandler;
243
+ options = handlerOrOptions;
244
+ }
245
+ else {
246
+ handler = handlerOrOptions;
247
+ options = (optionsOrHandler || {});
248
+ }
249
+ //
250
+ //
251
+ // Validate
252
+ //
253
+ let { chaos, locals, name, setup = [], teardown = [], unavailable, validate, } = options;
254
+ core.validate.function(handler);
255
+ core.validate.optional.object(locals);
256
+ setup = core.force.array(setup); // allows a single item
257
+ teardown = core.force.array(teardown); // allows a single item
258
+ //
259
+ //
260
+ // Setup
261
+ //
262
+ let jaypieFunction;
263
+ return async (req, res, ...params) => {
264
+ // * This is the first line of code that runs when a request is received
265
+ const extReq = req;
266
+ const extRes = res;
267
+ // Set default chaos value
268
+ if (chaos === undefined) {
269
+ chaos =
270
+ process.env.PROJECT_CHAOS ||
271
+ core.getHeaderFrom("X-Project-Chaos", req);
272
+ }
273
+ // Re-init the logger
274
+ logger.init();
275
+ // Very low-level, internal sub-trace details
276
+ const libLogger = logger.lib({
277
+ lib: core.JAYPIE.LIB.EXPRESS,
278
+ });
279
+ // Top-level, important details that run at the same level as the main logger
280
+ const log = logger.lib({
281
+ level: logger.level,
282
+ lib: core.JAYPIE.LIB.EXPRESS,
283
+ });
284
+ // Update the public logger with the request ID
285
+ const invokeUuid = getCurrentInvokeUuid();
286
+ if (invokeUuid) {
287
+ logger.tag({ invoke: invokeUuid });
288
+ logger.tag({ shortInvoke: invokeUuid.slice(0, 8) });
289
+ // TODO: in theory this is redundant
290
+ libLogger.tag({ invoke: invokeUuid });
291
+ libLogger.tag({ shortInvoke: invokeUuid.slice(0, 8) });
292
+ log.tag({ invoke: invokeUuid });
293
+ log.tag({ shortInvoke: invokeUuid.slice(0, 8) });
294
+ }
295
+ if (!name) {
296
+ // If handler has a name, use it
297
+ if (handler.name) {
298
+ name = handler.name;
299
+ }
300
+ else {
301
+ name = core.JAYPIE.UNKNOWN;
302
+ }
303
+ }
304
+ logger.tag({ handler: name });
305
+ // TODO: in theory this is redundant
306
+ libLogger.tag({ handler: name });
307
+ log.tag({ handler: name });
308
+ libLogger.trace("[jaypie] Express init");
309
+ // Set req.locals if it doesn't exist
310
+ if (!extReq.locals)
311
+ extReq.locals = {};
312
+ if (!extReq.locals._jaypie)
313
+ extReq.locals._jaypie = {};
314
+ // Set res.locals if it doesn't exist
315
+ if (!extRes.locals)
316
+ extRes.locals = {};
317
+ if (!extRes.locals._jaypie)
318
+ extRes.locals._jaypie = {};
319
+ const originalRes = {
320
+ attemptedCall: undefined,
321
+ attemptedParams: undefined,
322
+ end: res.end.bind(res),
323
+ json: res.json.bind(res),
324
+ send: res.send.bind(res),
325
+ status: res.status.bind(res),
326
+ statusSent: false,
327
+ };
328
+ res.end = ((...endParams) => {
329
+ originalRes.attemptedCall = originalRes.end;
330
+ originalRes.attemptedParams = endParams;
331
+ log.warn("[jaypie] Illegal call to res.end(); prefer Jaypie response conventions");
332
+ return res;
333
+ });
334
+ res.json = ((...jsonParams) => {
335
+ originalRes.attemptedCall = originalRes.json;
336
+ originalRes.attemptedParams = jsonParams;
337
+ log.warn("[jaypie] Illegal call to res.json(); prefer Jaypie response conventions");
338
+ return res;
339
+ });
340
+ res.send = ((...sendParams) => {
341
+ originalRes.attemptedCall = originalRes.send;
342
+ originalRes.attemptedParams = sendParams;
343
+ log.warn("[jaypie] Illegal call to res.send(); prefer Jaypie response conventions");
344
+ return res;
345
+ });
346
+ res.status = ((...statusParams) => {
347
+ originalRes.statusSent = statusParams[0];
348
+ return originalRes.status(...statusParams);
349
+ });
350
+ //
351
+ //
352
+ // Preprocess
353
+ //
354
+ if (locals) {
355
+ // Locals
356
+ const keys = Object.keys(locals);
357
+ if (keys.length > 0) {
358
+ const localsSetup = async (localsReq, localsRes) => {
359
+ const extLocalsReq = localsReq;
360
+ for (let i = 0; i < keys.length; i += 1) {
361
+ const key = keys[i];
362
+ libLogger.trace(`[jaypie] Locals: ${key}`);
363
+ const localValue = locals[key];
364
+ if (typeof localValue === "function") {
365
+ extLocalsReq.locals[key] = await localValue(localsReq, localsRes);
366
+ }
367
+ else {
368
+ extLocalsReq.locals[key] = localValue;
369
+ }
370
+ }
371
+ };
372
+ setup.push(localsSetup);
373
+ }
374
+ }
375
+ let response;
376
+ let status = core.HTTP.CODE.OK;
377
+ try {
378
+ log.info.var({ req: summarizeRequest(req) });
379
+ // Initialize after logging is set up
380
+ jaypieFunction = core.jaypieHandler(handler, {
381
+ chaos,
382
+ name,
383
+ setup,
384
+ teardown,
385
+ unavailable,
386
+ validate,
387
+ });
388
+ libLogger.trace("[jaypie] Express execution");
389
+ //
390
+ //
391
+ // Process
392
+ //
393
+ response = (await jaypieFunction(req, res, ...params));
394
+ //
395
+ //
396
+ // Error Handling
397
+ //
398
+ }
399
+ catch (error) {
400
+ // In theory jaypieFunction has handled all errors
401
+ const jaypieError = error;
402
+ if (jaypieError.status) {
403
+ status = jaypieError.status;
404
+ }
405
+ if (typeof jaypieError.json === "function") {
406
+ response = jaypieError.json();
407
+ }
408
+ else {
409
+ // This should never happen
410
+ const unhandledError = new core.UnhandledError();
411
+ response = unhandledError.json();
412
+ status = unhandledError.status;
413
+ }
414
+ }
415
+ //
416
+ //
417
+ // Postprocess
418
+ //
419
+ // Restore original res functions
420
+ res.end = originalRes.end;
421
+ res.json = originalRes.json;
422
+ res.send = originalRes.send;
423
+ res.status = originalRes.status;
424
+ // Decorate response
425
+ decorateResponse(res, { handler: name });
426
+ // Allow the sent status to override the status in the response
427
+ if (originalRes.statusSent) {
428
+ status = originalRes.statusSent;
429
+ }
430
+ // Send response
431
+ try {
432
+ if (!originalRes.attemptedCall) {
433
+ // Body
434
+ if (response) {
435
+ if (typeof response === "object") {
436
+ if (typeof response.json ===
437
+ "function") {
438
+ res.json(response.json());
439
+ }
440
+ else {
441
+ res.status(status).json(response);
442
+ }
443
+ }
444
+ else if (typeof response === "string") {
445
+ try {
446
+ res.status(status).json(JSON.parse(response));
447
+ }
448
+ catch {
449
+ res.status(status).send(response);
450
+ }
451
+ }
452
+ else if (response === true) {
453
+ res.status(core.HTTP.CODE.CREATED).send();
454
+ }
455
+ else {
456
+ res.status(status).send(response);
457
+ }
458
+ }
459
+ else {
460
+ // No response
461
+ res.status(core.HTTP.CODE.NO_CONTENT).send();
462
+ }
463
+ }
464
+ else {
465
+ // Resolve illegal call to res.end(), res.json(), or res.send()
466
+ log.debug("[jaypie] Resolving illegal call to res");
467
+ log.var({
468
+ attemptedCall: {
469
+ name: originalRes.attemptedCall.name,
470
+ params: originalRes.attemptedParams,
471
+ },
472
+ });
473
+ // Call the original function with the original parameters and the original `this` (res)
474
+ originalRes.attemptedCall.call(res, ...(originalRes.attemptedParams || []));
475
+ }
476
+ }
477
+ catch (error) {
478
+ log.fatal("Express encountered an error while sending the response");
479
+ log.var({ responseError: error });
480
+ }
481
+ // Log response
482
+ const extras = {};
483
+ if (response)
484
+ extras.body = response;
485
+ log.info.var({
486
+ res: summarizeResponse(res, extras),
487
+ });
488
+ // Submit metric if Datadog is configured
489
+ if (datadog.hasDatadogEnv()) {
490
+ // Construct path from baseUrl and url
491
+ let path = (req.baseUrl || "") + (req.url || "");
492
+ // Ensure path starts with /
493
+ if (!path.startsWith("/")) {
494
+ path = "/" + path;
495
+ }
496
+ // Remove trailing slash unless it's the root path
497
+ if (path.length > 1 && path.endsWith("/")) {
498
+ path = path.slice(0, -1);
499
+ }
500
+ // Replace UUIDs with :id for better aggregation
501
+ // Matches standard UUID v4 format (8-4-4-4-12 hex characters)
502
+ path = path.replace(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, ":id");
503
+ // Determine metric name based on environment variables
504
+ let metricPrefix = "project";
505
+ if (process.env.PROJECT_SPONSOR) {
506
+ metricPrefix = process.env.PROJECT_SPONSOR;
507
+ }
508
+ else if (process.env.PROJECT_KEY) {
509
+ metricPrefix = `project.${process.env.PROJECT_KEY}`;
510
+ }
511
+ await datadog.submitMetric({
512
+ name: `${metricPrefix}.api.response`,
513
+ type: datadog.DATADOG.METRIC.TYPE.COUNT,
514
+ value: 1,
515
+ tags: {
516
+ status: String(res.statusCode),
517
+ path,
518
+ },
519
+ });
520
+ }
521
+ // Clean up the public logger
522
+ logger.untag("handler");
523
+ //
524
+ //
525
+ // Return
526
+ //
527
+ return response;
528
+ };
529
+ }
530
+
531
+ //
532
+ //
533
+ // Main
534
+ //
535
+ const httpHandler = (statusCode = core.HTTP.CODE.OK, context = {}) => {
536
+ // Give a default name if there isn't one
537
+ if (!context.name) {
538
+ context.name = "_http";
539
+ }
540
+ // Return a function that will be used as an express route
541
+ return expressHandler(async (req, res) => {
542
+ // Map the most throwable status codes to errors and throw them!
543
+ const error = {
544
+ [core.HTTP.CODE.BAD_REQUEST]: core.BadRequestError,
545
+ [core.HTTP.CODE.UNAUTHORIZED]: core.UnauthorizedError,
546
+ [core.HTTP.CODE.FORBIDDEN]: core.ForbiddenError,
547
+ [core.HTTP.CODE.NOT_FOUND]: core.NotFoundError,
548
+ [core.HTTP.CODE.METHOD_NOT_ALLOWED]: core.MethodNotAllowedError,
549
+ [core.HTTP.CODE.GONE]: core.GoneError,
550
+ [core.HTTP.CODE.TEAPOT]: core.TeapotError,
551
+ [core.HTTP.CODE.INTERNAL_ERROR]: core.InternalError,
552
+ [core.HTTP.CODE.BAD_GATEWAY]: core.BadGatewayError,
553
+ [core.HTTP.CODE.UNAVAILABLE]: core.UnavailableError,
554
+ [core.HTTP.CODE.GATEWAY_TIMEOUT]: core.GatewayTimeoutError,
555
+ };
556
+ // If this maps to an error, throw it
557
+ if (error[statusCode]) {
558
+ core.log.trace(`@knowdev/express: gracefully throwing ${statusCode} up to projectHandler`);
559
+ throw new error[statusCode]();
560
+ }
561
+ // If this is an error and we didn't get thrown, log a warning
562
+ if (statusCode >= 400) {
563
+ core.log.warn(`@knowdev/express: status code ${statusCode} not mapped as throwable`);
564
+ }
565
+ // Send the response
566
+ res.status(statusCode);
567
+ return statusCode === core.HTTP.CODE.NO_CONTENT ? null : {};
568
+ }, context);
569
+ };
570
+
571
+ //
572
+ //
573
+ // Main
574
+ //
575
+ const echoHandler = (context = {}) => {
576
+ core.validate.object(context);
577
+ // Give a default name if there isn't one
578
+ if (!context.name) {
579
+ context.name = "_echo";
580
+ }
581
+ // Return a function that will be used as an express route
582
+ return expressHandler(async (req) => {
583
+ return {
584
+ req: summarizeRequest(req),
585
+ };
586
+ }, context);
587
+ };
588
+
589
+ //
590
+ //
591
+ // Functions
592
+ //
593
+ const routes = {
594
+ badRequestRoute: httpHandler(core.HTTP.CODE.BAD_REQUEST, { name: "_badRequest" }),
595
+ echoRoute: echoHandler(),
596
+ forbiddenRoute: httpHandler(core.HTTP.CODE.FORBIDDEN, { name: "_forbidden" }),
597
+ goneRoute: httpHandler(core.HTTP.CODE.GONE, { name: "_gone" }),
598
+ methodNotAllowedRoute: httpHandler(core.HTTP.CODE.METHOD_NOT_ALLOWED, {
599
+ name: "_methodNotAllowed",
600
+ }),
601
+ noContentRoute: httpHandler(core.HTTP.CODE.NO_CONTENT, { name: "_noContent" }),
602
+ notFoundRoute: httpHandler(core.HTTP.CODE.NOT_FOUND, { name: "_notFound" }),
603
+ notImplementedRoute: expressHandler(() => {
604
+ throw new core.NotImplementedError();
605
+ }, { name: "_notImplemented" }),
606
+ };
607
+ //
608
+ //
609
+ // Export
610
+ //
611
+ const badRequestRoute = routes.badRequestRoute;
612
+ const echoRoute = routes.echoRoute;
613
+ const forbiddenRoute = routes.forbiddenRoute;
614
+ const goneRoute = routes.goneRoute;
615
+ const methodNotAllowedRoute = routes.methodNotAllowedRoute;
616
+ const noContentRoute = routes.noContentRoute;
617
+ const notFoundRoute = routes.notFoundRoute;
618
+ const notImplementedRoute = routes.notImplementedRoute;
619
+
620
+ exports.EXPRESS = EXPRESS;
621
+ exports.badRequestRoute = badRequestRoute;
622
+ exports.cors = cors_helper;
623
+ exports.echoRoute = echoRoute;
624
+ exports.expressHandler = expressHandler;
625
+ exports.expressHttpCodeHandler = httpHandler;
626
+ exports.forbiddenRoute = forbiddenRoute;
627
+ exports.goneRoute = goneRoute;
628
+ exports.methodNotAllowedRoute = methodNotAllowedRoute;
629
+ exports.noContentRoute = noContentRoute;
630
+ exports.notFoundRoute = notFoundRoute;
631
+ exports.notImplementedRoute = notImplementedRoute;
632
+ //# sourceMappingURL=index.cjs.map