@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
@@ -1,346 +0,0 @@
1
- import {
2
- force,
3
- getHeaderFrom,
4
- HTTP,
5
- JAYPIE,
6
- jaypieHandler,
7
- log as publicLogger,
8
- UnhandledError,
9
- validate as validateIs,
10
- } from "@jaypie/core";
11
- import { DATADOG, hasDatadogEnv, submitMetric } from "@jaypie/datadog";
12
-
13
- import getCurrentInvokeUuid from "./getCurrentInvokeUuid.adapter.js";
14
- import decorateResponse from "./decorateResponse.helper.js";
15
- import summarizeRequest from "./summarizeRequest.helper.js";
16
- import summarizeResponse from "./summarizeResponse.helper.js";
17
-
18
- //
19
- //
20
- // Main
21
- //
22
-
23
- const expressHandler = (handler, options = {}) => {
24
- // If handler is an object and options is a function, swap them
25
- if (typeof handler === "object" && typeof options === "function") {
26
- const temp = handler;
27
- handler = options;
28
- options = temp;
29
- }
30
-
31
- //
32
- //
33
- // Validate
34
- //
35
- let {
36
- chaos,
37
- locals,
38
- name,
39
- setup = [],
40
- teardown = [],
41
- unavailable,
42
- validate,
43
- } = options;
44
- validateIs.function(handler);
45
- validateIs.optional.object(locals);
46
- setup = force.array(setup); // allows a single item
47
- teardown = force.array(teardown); // allows a single item
48
-
49
- //
50
- //
51
- // Setup
52
- //
53
-
54
- let jaypieFunction;
55
-
56
- return async (req, res, ...params) => {
57
- // * This is the first line of code that runs when a request is received
58
-
59
- // Set default chaos value
60
- if (chaos === undefined) {
61
- chaos =
62
- process.env.PROJECT_CHAOS ||
63
- getHeaderFrom(HTTP.HEADER.PROJECT.CHAOS, req);
64
- }
65
-
66
- // Re-init the logger
67
- publicLogger.init();
68
- // Very low-level, internal sub-trace details
69
- const libLogger = publicLogger.lib({
70
- lib: JAYPIE.LIB.EXPRESS,
71
- });
72
- // Top-level, important details that run at the same level as the main logger
73
- const log = publicLogger.lib({
74
- level: publicLogger.level,
75
- lib: JAYPIE.LIB.EXPRESS,
76
- });
77
-
78
- // Update the public logger with the request ID
79
- const invokeUuid = getCurrentInvokeUuid();
80
- if (invokeUuid) {
81
- publicLogger.tag({ invoke: invokeUuid });
82
- publicLogger.tag({ shortInvoke: invokeUuid.slice(0, 8) });
83
- // TODO: in theory this is redundant
84
- libLogger.tag({ invoke: invokeUuid });
85
- libLogger.tag({ shortInvoke: invokeUuid.slice(0, 8) });
86
- log.tag({ invoke: invokeUuid });
87
- log.tag({ shortInvoke: invokeUuid.slice(0, 8) });
88
- }
89
-
90
- if (!name) {
91
- // If handler has a name, use it
92
- if (handler.name) {
93
- name = handler.name;
94
- } else {
95
- name = JAYPIE.UNKNOWN;
96
- }
97
- }
98
- publicLogger.tag({ handler: name });
99
- // TODO: in theory this is redundant
100
- libLogger.tag({ handler: name });
101
- log.tag({ handler: name });
102
-
103
- libLogger.trace("[jaypie] Express init");
104
-
105
- // Set req.locals if it doesn't exist
106
- if (!req.locals) req.locals = {};
107
- if (!req.locals._jaypie) req.locals._jaypie = {};
108
-
109
- // Set res.locals if it doesn't exist
110
- if (!res.locals) res.locals = {};
111
- if (!res.locals._jaypie) res.locals._jaypie = {};
112
-
113
- const originalRes = {
114
- attemptedCall: undefined,
115
- attemptedParams: undefined,
116
- end: res.end,
117
- json: res.json,
118
- send: res.send,
119
- status: res.status,
120
- statusSent: false,
121
- };
122
-
123
- res.end = (...params) => {
124
- originalRes.attemptedCall = originalRes.end;
125
- originalRes.attemptedParams = params;
126
- log.warn(
127
- "[jaypie] Illegal call to res.end(); prefer Jaypie response conventions",
128
- );
129
- };
130
-
131
- res.json = (...params) => {
132
- originalRes.attemptedCall = originalRes.json;
133
- originalRes.attemptedParams = params;
134
- log.warn(
135
- "[jaypie] Illegal call to res.json(); prefer Jaypie response conventions",
136
- );
137
- };
138
-
139
- res.send = (...params) => {
140
- originalRes.attemptedCall = originalRes.send;
141
- originalRes.attemptedParams = params;
142
- log.warn(
143
- "[jaypie] Illegal call to res.send(); prefer Jaypie response conventions",
144
- );
145
- };
146
-
147
- res.status = (...params) => {
148
- originalRes.statusSent = params[0];
149
- return originalRes.status(...params);
150
- };
151
-
152
- //
153
- //
154
- // Preprocess
155
- //
156
-
157
- if (locals) {
158
- // Locals
159
- const keys = Object.keys(locals);
160
- if (keys.length > 0) {
161
- const localsSetup = async (localsReq, localsRes) => {
162
- for (let i = 0; i < keys.length; i += 1) {
163
- const key = keys[i];
164
- libLogger.trace(`[jaypie] Locals: ${key}`);
165
- if (typeof locals[key] === "function") {
166
- localsReq.locals[key] = await locals[key](localsReq, localsRes);
167
- } else {
168
- localsReq.locals[key] = locals[key];
169
- }
170
- }
171
- };
172
- setup.push(localsSetup);
173
- }
174
- }
175
-
176
- let response;
177
- let status = HTTP.CODE.OK;
178
-
179
- try {
180
- log.info.var({ req: summarizeRequest(req) });
181
-
182
- // Initialize after logging is set up
183
- jaypieFunction = jaypieHandler(handler, {
184
- chaos,
185
- name,
186
- setup,
187
- teardown,
188
- unavailable,
189
- validate,
190
- });
191
-
192
- libLogger.trace("[jaypie] Express execution");
193
-
194
- //
195
- //
196
- // Process
197
- //
198
-
199
- response = await jaypieFunction(req, res, ...params);
200
-
201
- //
202
- //
203
- // Error Handling
204
- //
205
- } catch (error) {
206
- // In theory jaypieFunction has handled all errors
207
- if (error.status) {
208
- status = error.status;
209
- }
210
- if (typeof error.json === "function") {
211
- response = error.json();
212
- } else {
213
- // This should never happen
214
- const unhandledError = new UnhandledError();
215
- response = unhandledError.json();
216
- status = unhandledError.status;
217
- }
218
- }
219
-
220
- //
221
- //
222
- // Postprocess
223
- //
224
-
225
- // Restore original res functions
226
- res.end = originalRes.end;
227
- res.json = originalRes.json;
228
- res.send = originalRes.send;
229
- res.status = originalRes.status;
230
-
231
- // Decorate response
232
- decorateResponse(res, { handler: name });
233
-
234
- // Allow the sent status to override the status in the response
235
- if (originalRes.statusSent) {
236
- status = originalRes.statusSent;
237
- }
238
-
239
- // Send response
240
- try {
241
- if (!originalRes.attemptedCall) {
242
- // Body
243
- if (response) {
244
- if (typeof response === "object") {
245
- if (typeof response.json === "function") {
246
- res.json(response.json());
247
- } else {
248
- res.status(status).json(response);
249
- }
250
- } else if (typeof response === "string") {
251
- try {
252
- res.status(status).json(JSON.parse(response));
253
- // eslint-disable-next-line no-unused-vars
254
- } catch (error) {
255
- res.status(status).send(response);
256
- }
257
- } else if (response === true) {
258
- res.status(HTTP.CODE.CREATED).send();
259
- } else {
260
- res.status(status).send(response);
261
- }
262
- } else {
263
- // No response
264
- res.status(HTTP.CODE.NO_CONTENT).send();
265
- }
266
- } else {
267
- // Resolve illegal call to res.end(), res.json(), or res.send()
268
- log.debug("[jaypie] Resolving illegal call to res");
269
- log.var({
270
- attemptedCall: {
271
- name: originalRes.attemptedCall.name,
272
- params: originalRes.attemptedParams,
273
- },
274
- });
275
- // Call the original function with the original parameters and the original `this` (res)
276
- originalRes.attemptedCall.call(res, ...originalRes.attemptedParams);
277
- }
278
- } catch (error) {
279
- log.fatal("Express encountered an error while sending the response");
280
- log.var({ responseError: error });
281
- }
282
-
283
- // Log response
284
- const extras = {};
285
- if (response) extras.body = response;
286
- log.info.var({
287
- res: summarizeResponse(res, extras),
288
- });
289
-
290
- // Submit metric if Datadog is configured
291
- if (hasDatadogEnv()) {
292
- // Construct path from baseUrl and url
293
- let path = (req.baseUrl || "") + (req.url || "");
294
- // Ensure path starts with /
295
- if (!path.startsWith("/")) {
296
- path = "/" + path;
297
- }
298
- // Remove trailing slash unless it's the root path
299
- if (path.length > 1 && path.endsWith("/")) {
300
- path = path.slice(0, -1);
301
- }
302
-
303
- // Replace UUIDs with :id for better aggregation
304
- // Matches standard UUID v4 format (8-4-4-4-12 hex characters)
305
- path = path.replace(
306
- /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi,
307
- ":id",
308
- );
309
-
310
- // Determine metric name based on environment variables
311
- let metricPrefix = "project";
312
- if (process.env.PROJECT_SPONSOR) {
313
- metricPrefix = process.env.PROJECT_SPONSOR;
314
- } else if (process.env.PROJECT_KEY) {
315
- metricPrefix = `project.${process.env.PROJECT_KEY}`;
316
- }
317
-
318
- await submitMetric({
319
- name: `${metricPrefix}.api.response`,
320
- type: DATADOG.METRIC.TYPE.COUNT,
321
- value: 1,
322
- tags: {
323
- status: res.statusCode,
324
- path,
325
- },
326
- });
327
- }
328
-
329
- // Clean up the public logger
330
- publicLogger.untag("handler");
331
-
332
- //
333
- //
334
- // Return
335
- //
336
-
337
- return response;
338
- };
339
- };
340
-
341
- //
342
- //
343
- // Export
344
- //
345
-
346
- export default expressHandler;
@@ -1,33 +0,0 @@
1
- import { getCurrentInvoke } from "@codegenie/serverless-express";
2
-
3
- //
4
- //
5
- // Helper Functions
6
- //
7
-
8
- // Adapter for the "@codegenie/serverless-express" uuid
9
- function getServerlessExpressUuid() {
10
- const currentInvoke = getCurrentInvoke();
11
- if (
12
- currentInvoke &&
13
- currentInvoke.context &&
14
- currentInvoke.context.awsRequestId
15
- ) {
16
- return currentInvoke.context.awsRequestId;
17
- }
18
- return undefined;
19
- }
20
-
21
- //
22
- //
23
- // Main
24
- //
25
-
26
- const getCurrentInvokeUuid = () => getServerlessExpressUuid();
27
-
28
- //
29
- //
30
- // Export
31
- //
32
-
33
- export default getCurrentInvokeUuid;
@@ -1,73 +0,0 @@
1
- import {
2
- BadGatewayError,
3
- BadRequestError,
4
- ForbiddenError,
5
- GatewayTimeoutError,
6
- GoneError,
7
- HTTP,
8
- InternalError,
9
- log,
10
- MethodNotAllowedError,
11
- NotFoundError,
12
- TeapotError,
13
- UnauthorizedError,
14
- UnavailableError,
15
- } from "@jaypie/core";
16
-
17
- import expressHandler from "./expressHandler.js";
18
-
19
- //
20
- //
21
- // Main
22
- //
23
-
24
- const httpHandler = (statusCode = HTTP.CODE.OK, context = {}) => {
25
- // Give a default name if there isn't one
26
- if (!context.name) {
27
- context.name = "_http";
28
- }
29
-
30
- // Return a function that will be used as an express route
31
- return expressHandler(async (req, res) => {
32
- // Map the most throwable status codes to errors and throw them!
33
- const error = {
34
- [HTTP.CODE.BAD_REQUEST]: BadRequestError,
35
- [HTTP.CODE.UNAUTHORIZED]: UnauthorizedError,
36
- [HTTP.CODE.FORBIDDEN]: ForbiddenError,
37
- [HTTP.CODE.NOT_FOUND]: NotFoundError,
38
- [HTTP.CODE.METHOD_NOT_ALLOWED]: MethodNotAllowedError,
39
- [HTTP.CODE.GONE]: GoneError,
40
- [HTTP.CODE.TEAPOT]: TeapotError,
41
- [HTTP.CODE.INTERNAL_ERROR]: InternalError,
42
- [HTTP.CODE.BAD_GATEWAY]: BadGatewayError,
43
- [HTTP.CODE.UNAVAILABLE]: UnavailableError,
44
- [HTTP.CODE.GATEWAY_TIMEOUT]: GatewayTimeoutError,
45
- };
46
-
47
- // If this maps to an error, throw it
48
- if (error[statusCode]) {
49
- log.trace(
50
- `@knowdev/express: gracefully throwing ${statusCode} up to projectHandler`,
51
- );
52
- throw new error[statusCode]();
53
- }
54
-
55
- // If this is an error and we didn't get thrown, log a warning
56
- if (statusCode >= 400) {
57
- log.warn(
58
- `@knowdev/express: status code ${statusCode} not mapped as throwable`,
59
- );
60
- }
61
-
62
- // Send the response
63
- res.status(statusCode);
64
- return statusCode === HTTP.CODE.NO_CONTENT ? null : {};
65
- }, context);
66
- };
67
-
68
- //
69
- //
70
- // Export
71
- //
72
-
73
- export default httpHandler;
package/src/routes.js DELETED
@@ -1,43 +0,0 @@
1
- import { HTTP, NotImplementedError } from "@jaypie/core";
2
- import expressHandler from "./expressHandler.js";
3
- import httpHandler from "./http.handler.js";
4
- import echoHandler from "./echo.handler.js";
5
-
6
- //
7
- //
8
- // Functions
9
- //
10
-
11
- const routes = {
12
- badRequestRoute: httpHandler(HTTP.CODE.BAD_REQUEST, { name: "_badRequest" }),
13
- echoRoute: echoHandler(),
14
- forbiddenRoute: httpHandler(HTTP.CODE.FORBIDDEN, { name: "_forbidden" }),
15
- goneRoute: httpHandler(HTTP.CODE.GONE, { name: "_gone" }),
16
- methodNotAllowedRoute: httpHandler(HTTP.CODE.METHOD_NOT_ALLOWED, {
17
- name: "_methodNotAllowed",
18
- }),
19
- noContentRoute: httpHandler(HTTP.CODE.NO_CONTENT, { name: "_noContent" }),
20
- notFoundRoute: httpHandler(HTTP.CODE.NOT_FOUND, { name: "_notFound" }),
21
- notImplementedRoute: expressHandler(
22
- () => {
23
- throw new NotImplementedError();
24
- },
25
- { name: "_notImplemented" },
26
- ),
27
- };
28
-
29
- //
30
- //
31
- // Export
32
- //
33
-
34
- export const {
35
- badRequestRoute,
36
- echoRoute,
37
- forbiddenRoute,
38
- goneRoute,
39
- methodNotAllowedRoute,
40
- noContentRoute,
41
- notFoundRoute,
42
- notImplementedRoute,
43
- } = routes;
@@ -1,28 +0,0 @@
1
- //
2
- //
3
- // Function Definition
4
- //
5
-
6
- function summarizeRequest(req) {
7
- // If body is a buffer, convert it to a string
8
- let { body } = req;
9
- if (Buffer.isBuffer(body)) {
10
- body = body.toString();
11
- }
12
-
13
- return {
14
- baseUrl: req.baseUrl,
15
- body,
16
- headers: req.headers,
17
- method: req.method,
18
- query: req.query,
19
- url: req.url,
20
- };
21
- }
22
-
23
- //
24
- //
25
- // Export
26
- //
27
-
28
- export default summarizeRequest;
@@ -1,25 +0,0 @@
1
- //
2
- //
3
- // Function Definition
4
- //
5
-
6
- function summarizeResponse(res, extras) {
7
- const response = {
8
- statusCode: res.statusCode,
9
- statusMessage: res.statusMessage,
10
- };
11
- if (typeof res.getHeaders === "function") {
12
- response.headers = res.getHeaders();
13
- }
14
- if (typeof extras === "object" && extras !== null) {
15
- Object.assign(response, extras);
16
- }
17
- return response;
18
- }
19
-
20
- //
21
- //
22
- // Export
23
- //
24
-
25
- export default summarizeResponse;