@jaypie/express 1.1.17 → 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.
- package/dist/cjs/__tests__/constants.spec.d.ts +1 -0
- package/dist/cjs/__tests__/cors.helper.spec.d.ts +1 -0
- package/dist/cjs/__tests__/cors.helper.supertest.spec.d.ts +1 -0
- package/dist/cjs/__tests__/decorateResponse.helper.spec.d.ts +1 -0
- package/dist/cjs/__tests__/echo.handler.spec.d.ts +1 -0
- package/dist/cjs/__tests__/expressHandler.spec.d.ts +1 -0
- package/dist/cjs/__tests__/getCurrentInvokeUuid.adapter.spec.d.ts +1 -0
- package/dist/cjs/__tests__/http.handler.spec.d.ts +1 -0
- package/dist/cjs/__tests__/index.spec.d.ts +1 -0
- package/dist/cjs/__tests__/routes.spec.d.ts +1 -0
- package/dist/cjs/__tests__/summarizeRequest.helper.spec.d.ts +1 -0
- package/dist/cjs/__tests__/summarizeResponse.helper.spec.d.ts +1 -0
- package/dist/cjs/__tests__/supertest.spec.d.ts +1 -0
- package/dist/cjs/constants.d.ts +8 -0
- package/dist/cjs/cors.helper.d.ts +9 -0
- package/dist/cjs/decorateResponse.helper.d.ts +7 -0
- package/dist/cjs/echo.handler.d.ts +8 -0
- package/dist/cjs/expressHandler.d.ts +14 -0
- package/dist/cjs/getCurrentInvokeUuid.adapter.d.ts +2 -0
- package/dist/cjs/http.handler.d.ts +4 -0
- package/dist/cjs/index.cjs +632 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/{src/index.js → dist/cjs/index.d.ts} +2 -0
- package/dist/cjs/routes.d.ts +8 -0
- package/dist/cjs/summarizeRequest.helper.d.ts +11 -0
- package/dist/cjs/summarizeResponse.helper.d.ts +9 -0
- package/dist/esm/__tests__/constants.spec.d.ts +1 -0
- package/dist/esm/__tests__/cors.helper.spec.d.ts +1 -0
- package/dist/esm/__tests__/cors.helper.supertest.spec.d.ts +1 -0
- package/dist/esm/__tests__/decorateResponse.helper.spec.d.ts +1 -0
- package/dist/esm/__tests__/echo.handler.spec.d.ts +1 -0
- package/dist/esm/__tests__/expressHandler.spec.d.ts +1 -0
- package/dist/esm/__tests__/getCurrentInvokeUuid.adapter.spec.d.ts +1 -0
- package/dist/esm/__tests__/http.handler.spec.d.ts +1 -0
- package/dist/esm/__tests__/index.spec.d.ts +1 -0
- package/dist/esm/__tests__/routes.spec.d.ts +1 -0
- package/dist/esm/__tests__/summarizeRequest.helper.spec.d.ts +1 -0
- package/dist/esm/__tests__/summarizeResponse.helper.spec.d.ts +1 -0
- package/dist/esm/__tests__/supertest.spec.d.ts +1 -0
- package/dist/esm/constants.d.ts +8 -0
- package/dist/esm/cors.helper.d.ts +9 -0
- package/dist/esm/decorateResponse.helper.d.ts +7 -0
- package/dist/esm/echo.handler.d.ts +8 -0
- package/dist/esm/expressHandler.d.ts +14 -0
- package/dist/esm/getCurrentInvokeUuid.adapter.d.ts +2 -0
- package/dist/esm/http.handler.d.ts +4 -0
- package/dist/esm/index.d.ts +7 -0
- package/dist/esm/index.js +619 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/routes.d.ts +8 -0
- package/dist/esm/summarizeRequest.helper.d.ts +11 -0
- package/dist/esm/summarizeResponse.helper.d.ts +9 -0
- package/package.json +30 -24
- package/index.d.ts +0 -68
- package/rollup.config.mjs +0 -22
- package/src/constants.js +0 -12
- package/src/cors.helper.js +0 -110
- package/src/decorateResponse.helper.js +0 -90
- package/src/echo.handler.js +0 -31
- package/src/expressHandler.js +0 -346
- package/src/getCurrentInvokeUuid.adapter.js +0 -33
- package/src/http.handler.js +0 -73
- package/src/routes.js +0 -43
- package/src/summarizeRequest.helper.js +0 -28
- package/src/summarizeResponse.helper.js +0 -25
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/constants.ts","../../../src/cors.helper.ts","../../../src/getCurrentInvokeUuid.adapter.ts","../../../src/decorateResponse.helper.ts","../../../src/summarizeRequest.helper.ts","../../../src/summarizeResponse.helper.ts","../../../src/expressHandler.ts","../../../src/http.handler.ts","../../../src/echo.handler.ts","../../../src/routes.ts"],"sourcesContent":["//\n//\n// Constants\n//\n\nexport const EXPRESS = {\n PATH: {\n ANY: \"*\",\n ID: \"/:id\",\n ROOT: /^\\/?$/,\n },\n} as const;\n\nexport type ExpressConstants = typeof EXPRESS;\n","import type { Request, Response, NextFunction } from \"express\";\nimport { CorsError } from \"@jaypie/errors\";\nimport { envBoolean, force } from \"@jaypie/core\";\nimport expressCors from \"cors\";\n\n//\n//\n// Constants\n//\n\nconst HTTP_PROTOCOL = \"http://\";\nconst HTTPS_PROTOCOL = \"https://\";\nconst SANDBOX_ENV = \"sandbox\";\n\n//\n//\n// Types\n//\n\nexport interface CorsConfig {\n origin?: string | string[];\n overrides?: Record<string, unknown>;\n}\n\ntype CorsCallback = (err: Error | null, allow?: boolean) => void;\n\n//\n//\n// Helper Functions\n//\n\nconst ensureProtocol = (url: string | undefined): string | undefined => {\n if (!url) return url;\n if (url.startsWith(HTTP_PROTOCOL) || url.startsWith(HTTPS_PROTOCOL))\n return url;\n return HTTPS_PROTOCOL + url;\n};\n\nexport const dynamicOriginCallbackHandler = (\n origin?: string | string[],\n): ((requestOrigin: string | undefined, callback: CorsCallback) => void) => {\n return (requestOrigin: string | undefined, callback: CorsCallback) => {\n // Handle wildcard origin\n if (origin === \"*\") {\n callback(null, true);\n return;\n }\n\n // Allow requests with no origin (like mobile apps, curl, etc)\n if (!requestOrigin) {\n callback(null, true);\n return;\n }\n\n const allowedOrigins: (string | RegExp)[] = [];\n if (process.env.BASE_URL) {\n allowedOrigins.push(ensureProtocol(process.env.BASE_URL) as string);\n }\n if (process.env.PROJECT_BASE_URL) {\n allowedOrigins.push(\n ensureProtocol(process.env.PROJECT_BASE_URL) as string,\n );\n }\n if (origin) {\n const additionalOrigins = force.array<string>(origin);\n allowedOrigins.push(...additionalOrigins);\n }\n\n // Add localhost origins in sandbox\n if (\n process.env.PROJECT_ENV === SANDBOX_ENV ||\n envBoolean(\"PROJECT_SANDBOX_MODE\")\n ) {\n allowedOrigins.push(\"http://localhost\");\n allowedOrigins.push(/^http:\\/\\/localhost:\\d+$/);\n }\n\n const isAllowed = allowedOrigins.some((allowed) => {\n if (allowed instanceof RegExp) {\n return allowed.test(requestOrigin);\n }\n return requestOrigin.includes(allowed);\n });\n\n if (isAllowed) {\n callback(null, true);\n } else {\n callback(new CorsError());\n }\n };\n};\n\n//\n//\n// Main\n//\n\nconst corsHelper = (\n config: CorsConfig = {},\n): ReturnType<typeof expressCors> => {\n const { origin, overrides = {} } = config;\n\n const options = {\n origin: dynamicOriginCallbackHandler(origin),\n // * The default behavior is to allow any headers and methods so they are not included here\n ...overrides,\n };\n\n return expressCors(options);\n};\n\n//\n//\n// Export\n//\n\ninterface CorsErrorWithBody extends Error {\n status: number;\n body: () => Record<string, unknown>;\n}\n\nexport default (\n config?: CorsConfig,\n): ((req: Request, res: Response, next: NextFunction) => void) => {\n const cors = corsHelper(config);\n return (req: Request, res: Response, next: NextFunction) => {\n cors(req, res, (error?: Error | null) => {\n if (error) {\n const corsError = error as CorsErrorWithBody;\n res.status(corsError.status);\n res.setHeader(\"Content-Type\", \"application/json\");\n return res.json(corsError.body());\n }\n next();\n });\n };\n};\n","import { getCurrentInvoke } from \"@codegenie/serverless-express\";\n\n//\n//\n// Helper Functions\n//\n\n// Adapter for the \"@codegenie/serverless-express\" uuid\nfunction getServerlessExpressUuid(): string | undefined {\n const currentInvoke = getCurrentInvoke();\n if (\n currentInvoke &&\n currentInvoke.context &&\n currentInvoke.context.awsRequestId\n ) {\n return currentInvoke.context.awsRequestId;\n }\n return undefined;\n}\n\n//\n//\n// Main\n//\n\nconst getCurrentInvokeUuid = (): string | undefined =>\n getServerlessExpressUuid();\n\n//\n//\n// Export\n//\n\nexport default getCurrentInvokeUuid;\n","import type { Response } from \"express\";\nimport { HTTP, JAYPIE, log as publicLogger } from \"@jaypie/core\";\n\nimport getCurrentInvokeUuid from \"./getCurrentInvokeUuid.adapter.js\";\n\n//\n//\n// Types\n//\n\ninterface DecorateResponseOptions {\n handler?: string;\n version?: string;\n}\n\n//\n//\n// Main\n//\n\nconst decorateResponse = (\n res: Response,\n {\n handler = \"\",\n version = process.env.PROJECT_VERSION,\n }: DecorateResponseOptions = {},\n): void => {\n const log = publicLogger.lib({\n lib: JAYPIE.LIB.EXPRESS,\n });\n\n //\n //\n // Validate\n //\n if (typeof res !== \"object\" || res === null) {\n log.warn(\"decorateResponse called but response is not an object\");\n return;\n }\n\n try {\n //\n //\n // Decorate Headers\n //\n\n // X-Powered-By, override \"Express\" but nothing else\n if (\n !res.get(HTTP.HEADER.POWERED_BY) ||\n res.get(HTTP.HEADER.POWERED_BY) === \"Express\"\n ) {\n res.set(HTTP.HEADER.POWERED_BY, JAYPIE.LIB.EXPRESS);\n }\n\n // X-Project-Environment\n if (process.env.PROJECT_ENV) {\n res.set(HTTP.HEADER.PROJECT.ENVIRONMENT, process.env.PROJECT_ENV);\n }\n\n // X-Project-Handler\n if (handler) {\n res.set(HTTP.HEADER.PROJECT.HANDLER, handler);\n }\n\n // X-Project-Invocation\n const currentInvoke = getCurrentInvokeUuid();\n if (currentInvoke) {\n res.set(HTTP.HEADER.PROJECT.INVOCATION, currentInvoke);\n }\n\n // X-Project-Key\n if (process.env.PROJECT_KEY) {\n res.set(HTTP.HEADER.PROJECT.KEY, process.env.PROJECT_KEY);\n }\n\n // X-Project-Version\n if (version) {\n res.set(HTTP.HEADER.PROJECT.VERSION, version);\n }\n\n //\n //\n // Error Handling\n //\n } catch (error) {\n log.warn(\"decorateResponse caught an internal error\");\n log.var({ error });\n }\n};\n\n//\n//\n// Export\n//\n\nexport default decorateResponse;\n\n//\n//\n// Footnotes\n//\n\n// This is a \"utility\" function but it needs a lot of \"context\"\n// about the environment's secret parameters, the special adapter,\n// HTTP, etc. There must be a better way to organize this\n","import type { Request } from \"express\";\n\n//\n//\n// Types\n//\n\nexport interface RequestSummary {\n baseUrl: string;\n body: unknown;\n headers: Request[\"headers\"];\n method: string;\n query: Request[\"query\"];\n url: string;\n}\n\n//\n//\n// Function Definition\n//\n\nfunction summarizeRequest(req: Request): RequestSummary {\n // If body is a buffer, convert it to a string\n let { body } = req;\n if (Buffer.isBuffer(body)) {\n body = body.toString();\n }\n\n return {\n baseUrl: req.baseUrl,\n body,\n headers: req.headers,\n method: req.method,\n query: req.query,\n url: req.url,\n };\n}\n\n//\n//\n// Export\n//\n\nexport default summarizeRequest;\n","import type { Response } from \"express\";\n\n//\n//\n// Types\n//\n\nexport interface ResponseSummary {\n statusCode: number;\n statusMessage: string;\n headers?: ReturnType<Response[\"getHeaders\"]>;\n [key: string]: unknown;\n}\n\n//\n//\n// Function Definition\n//\n\nfunction summarizeResponse(\n res: Response,\n extras?: Record<string, unknown>,\n): ResponseSummary {\n const response: ResponseSummary = {\n statusCode: res.statusCode,\n statusMessage: res.statusMessage,\n };\n if (typeof res.getHeaders === \"function\") {\n response.headers = res.getHeaders();\n }\n if (typeof extras === \"object\" && extras !== null) {\n Object.assign(response, extras);\n }\n return response;\n}\n\n//\n//\n// Export\n//\n\nexport default summarizeResponse;\n","import type { Request, Response } from \"express\";\nimport {\n force,\n getHeaderFrom,\n HTTP,\n JAYPIE,\n jaypieHandler,\n log as publicLogger,\n UnhandledError,\n validate as validateIs,\n} from \"@jaypie/core\";\nimport { DATADOG, hasDatadogEnv, submitMetric } from \"@jaypie/datadog\";\n\nimport getCurrentInvokeUuid from \"./getCurrentInvokeUuid.adapter.js\";\nimport decorateResponse from \"./decorateResponse.helper.js\";\nimport summarizeRequest from \"./summarizeRequest.helper.js\";\nimport summarizeResponse from \"./summarizeResponse.helper.js\";\n\n//\n//\n// Types\n//\n\n// Extended logger interface for features not in the base type definitions\ninterface ExtendedLogger {\n init: () => void;\n level: string;\n debug: {\n (...args: unknown[]): void;\n var(key: string | Record<string, unknown>, value?: unknown): void;\n };\n error: {\n (...args: unknown[]): void;\n var(key: string | Record<string, unknown>, value?: unknown): void;\n };\n fatal: {\n (...args: unknown[]): void;\n var(key: string | Record<string, unknown>, value?: unknown): void;\n };\n info: {\n (...args: unknown[]): void;\n var(key: string | Record<string, unknown>, value?: unknown): void;\n };\n trace: {\n (...args: unknown[]): void;\n var(key: string | Record<string, unknown>, value?: unknown): void;\n };\n warn: {\n (...args: unknown[]): void;\n var(key: string | Record<string, unknown>, value?: unknown): void;\n };\n var(key: string | Record<string, unknown>, value?: unknown): void;\n tag(\n key: string | string[] | Record<string, unknown> | null,\n value?: string,\n ): void;\n untag(tags: string | string[] | Record<string, unknown> | null): void;\n lib(options: {\n level?: string;\n lib?: string;\n tags?: Record<string, unknown>;\n }): ExtendedLogger;\n}\n\nexport interface ExpressHandlerOptions {\n chaos?: string;\n locals?: Record<\n string,\n unknown | ((req: Request, res: Response) => Promise<unknown>)\n >;\n name?: string;\n setup?:\n | ((req: Request, res: Response) => Promise<void>)[]\n | ((req: Request, res: Response) => Promise<void>);\n teardown?:\n | ((req: Request, res: Response) => Promise<void>)[]\n | ((req: Request, res: Response) => Promise<void>);\n unavailable?: boolean;\n validate?:\n | ((req: Request, res: Response) => Promise<boolean> | boolean)[]\n | ((req: Request, res: Response) => Promise<boolean> | boolean);\n}\n\ninterface ExtendedRequest extends Request {\n locals: Record<string, unknown> & {\n _jaypie?: Record<string, unknown>;\n };\n}\n\ninterface ExtendedResponse extends Response {\n locals: Record<string, unknown> & {\n _jaypie?: Record<string, unknown>;\n };\n}\n\ntype ExpressHandler<T> = (\n req: Request,\n res: Response,\n ...params: unknown[]\n) => Promise<T>;\n\ninterface JaypieError extends Error {\n status?: number;\n json?: () => Record<string, unknown>;\n}\n\ninterface ResponseWithJson {\n json: () => Record<string, unknown>;\n}\n\n// Cast logger to extended interface for runtime features not in type definitions\nconst logger = publicLogger as unknown as ExtendedLogger;\n\n//\n//\n// Main\n//\n\n/* eslint-disable no-redeclare */\nfunction expressHandler<T>(\n handler: ExpressHandler<T>,\n options?: ExpressHandlerOptions,\n): ExpressHandler<T>;\nfunction expressHandler<T>(\n options: ExpressHandlerOptions,\n handler: ExpressHandler<T>,\n): ExpressHandler<T>;\nfunction expressHandler<T>(\n handlerOrOptions: ExpressHandler<T> | ExpressHandlerOptions,\n optionsOrHandler?: ExpressHandlerOptions | ExpressHandler<T>,\n): ExpressHandler<T> {\n /* eslint-enable no-redeclare */\n let handler: ExpressHandler<T>;\n let options: ExpressHandlerOptions;\n\n // If handler is an object and options is a function, swap them\n if (\n typeof handlerOrOptions === \"object\" &&\n typeof optionsOrHandler === \"function\"\n ) {\n handler = optionsOrHandler as ExpressHandler<T>;\n options = handlerOrOptions as ExpressHandlerOptions;\n } else {\n handler = handlerOrOptions as ExpressHandler<T>;\n options = (optionsOrHandler || {}) as ExpressHandlerOptions;\n }\n\n //\n //\n // Validate\n //\n let {\n chaos,\n locals,\n name,\n setup = [],\n teardown = [],\n unavailable,\n validate,\n } = options;\n validateIs.function(handler);\n validateIs.optional.object(locals);\n setup = force.array(setup) as ((\n req: Request,\n res: Response,\n ) => Promise<void>)[]; // allows a single item\n teardown = force.array(teardown) as ((\n req: Request,\n res: Response,\n ) => Promise<void>)[]; // allows a single item\n\n //\n //\n // Setup\n //\n\n let jaypieFunction: ReturnType<typeof jaypieHandler>;\n\n return async (\n req: Request,\n res: Response,\n ...params: unknown[]\n ): Promise<T> => {\n // * This is the first line of code that runs when a request is received\n const extReq = req as ExtendedRequest;\n const extRes = res as ExtendedResponse;\n\n // Set default chaos value\n if (chaos === undefined) {\n chaos =\n process.env.PROJECT_CHAOS ||\n (getHeaderFrom(\n \"X-Project-Chaos\",\n req as unknown as Record<string, unknown>,\n ) as string | undefined);\n }\n\n // Re-init the logger\n logger.init();\n // Very low-level, internal sub-trace details\n const libLogger = logger.lib({\n lib: JAYPIE.LIB.EXPRESS,\n });\n // Top-level, important details that run at the same level as the main logger\n const log = logger.lib({\n level: logger.level,\n lib: JAYPIE.LIB.EXPRESS,\n });\n\n // Update the public logger with the request ID\n const invokeUuid = getCurrentInvokeUuid();\n if (invokeUuid) {\n logger.tag({ invoke: invokeUuid });\n logger.tag({ shortInvoke: invokeUuid.slice(0, 8) });\n // TODO: in theory this is redundant\n libLogger.tag({ invoke: invokeUuid });\n libLogger.tag({ shortInvoke: invokeUuid.slice(0, 8) });\n log.tag({ invoke: invokeUuid });\n log.tag({ shortInvoke: invokeUuid.slice(0, 8) });\n }\n\n if (!name) {\n // If handler has a name, use it\n if (handler.name) {\n name = handler.name;\n } else {\n name = JAYPIE.UNKNOWN;\n }\n }\n logger.tag({ handler: name });\n // TODO: in theory this is redundant\n libLogger.tag({ handler: name });\n log.tag({ handler: name });\n\n libLogger.trace(\"[jaypie] Express init\");\n\n // Set req.locals if it doesn't exist\n if (!extReq.locals) extReq.locals = {};\n if (!extReq.locals._jaypie) extReq.locals._jaypie = {};\n\n // Set res.locals if it doesn't exist\n if (!extRes.locals) extRes.locals = {};\n if (!extRes.locals._jaypie) extRes.locals._jaypie = {};\n\n const originalRes = {\n attemptedCall: undefined as ((...args: unknown[]) => unknown) | undefined,\n attemptedParams: undefined as unknown[] | undefined,\n end: res.end.bind(res) as typeof res.end,\n json: res.json.bind(res) as typeof res.json,\n send: res.send.bind(res) as typeof res.send,\n status: res.status.bind(res) as typeof res.status,\n statusSent: false as boolean | number,\n };\n\n res.end = ((...endParams: unknown[]) => {\n originalRes.attemptedCall = originalRes.end as unknown as (\n ...args: unknown[]\n ) => unknown;\n originalRes.attemptedParams = endParams;\n log.warn(\n \"[jaypie] Illegal call to res.end(); prefer Jaypie response conventions\",\n );\n return res;\n }) as typeof res.end;\n\n res.json = ((...jsonParams: unknown[]) => {\n originalRes.attemptedCall = originalRes.json;\n originalRes.attemptedParams = jsonParams;\n log.warn(\n \"[jaypie] Illegal call to res.json(); prefer Jaypie response conventions\",\n );\n return res;\n }) as typeof res.json;\n\n res.send = ((...sendParams: unknown[]) => {\n originalRes.attemptedCall = originalRes.send;\n originalRes.attemptedParams = sendParams;\n log.warn(\n \"[jaypie] Illegal call to res.send(); prefer Jaypie response conventions\",\n );\n return res;\n }) as typeof res.send;\n\n res.status = ((...statusParams: [number]) => {\n originalRes.statusSent = statusParams[0];\n return originalRes.status(...statusParams);\n }) as typeof res.status;\n\n //\n //\n // Preprocess\n //\n\n if (locals) {\n // Locals\n const keys = Object.keys(locals);\n if (keys.length > 0) {\n const localsSetup = async (localsReq: Request, localsRes: Response) => {\n const extLocalsReq = localsReq as ExtendedRequest;\n for (let i = 0; i < keys.length; i += 1) {\n const key = keys[i];\n libLogger.trace(`[jaypie] Locals: ${key}`);\n const localValue = locals[key];\n if (typeof localValue === \"function\") {\n extLocalsReq.locals[key] = await localValue(localsReq, localsRes);\n } else {\n extLocalsReq.locals[key] = localValue;\n }\n }\n };\n setup.push(localsSetup);\n }\n }\n\n let response: T | Record<string, unknown> | undefined;\n let status: number = HTTP.CODE.OK;\n\n try {\n log.info.var({ req: summarizeRequest(req) });\n\n // Initialize after logging is set up\n\n jaypieFunction = jaypieHandler(\n handler as unknown as (...args: unknown[]) => unknown,\n {\n chaos,\n name,\n setup,\n teardown,\n unavailable,\n validate,\n } as any,\n );\n\n libLogger.trace(\"[jaypie] Express execution\");\n\n //\n //\n // Process\n //\n\n response = (await jaypieFunction(req, res, ...params)) as\n | T\n | Record<string, unknown>\n | undefined;\n\n //\n //\n // Error Handling\n //\n } catch (error) {\n // In theory jaypieFunction has handled all errors\n const jaypieError = error as JaypieError;\n if (jaypieError.status) {\n status = jaypieError.status;\n }\n if (typeof jaypieError.json === \"function\") {\n response = jaypieError.json();\n } else {\n // This should never happen\n const unhandledError = new UnhandledError();\n response = unhandledError.json();\n status = unhandledError.status;\n }\n }\n\n //\n //\n // Postprocess\n //\n\n // Restore original res functions\n res.end = originalRes.end;\n res.json = originalRes.json;\n res.send = originalRes.send;\n res.status = originalRes.status;\n\n // Decorate response\n decorateResponse(res, { handler: name });\n\n // Allow the sent status to override the status in the response\n if (originalRes.statusSent) {\n status = originalRes.statusSent as number;\n }\n\n // Send response\n try {\n if (!originalRes.attemptedCall) {\n // Body\n if (response) {\n if (typeof response === \"object\") {\n if (\n typeof (response as unknown as ResponseWithJson).json ===\n \"function\"\n ) {\n res.json((response as unknown as ResponseWithJson).json());\n } else {\n res.status(status).json(response);\n }\n } else if (typeof response === \"string\") {\n try {\n res.status(status).json(JSON.parse(response));\n } catch {\n res.status(status).send(response);\n }\n } else if (response === true) {\n res.status(HTTP.CODE.CREATED).send();\n } else {\n res.status(status).send(response as unknown as string);\n }\n } else {\n // No response\n res.status(HTTP.CODE.NO_CONTENT).send();\n }\n } else {\n // Resolve illegal call to res.end(), res.json(), or res.send()\n log.debug(\"[jaypie] Resolving illegal call to res\");\n log.var({\n attemptedCall: {\n name: originalRes.attemptedCall.name,\n params: originalRes.attemptedParams,\n },\n });\n // Call the original function with the original parameters and the original `this` (res)\n (originalRes.attemptedCall as (...args: unknown[]) => unknown).call(\n res,\n ...(originalRes.attemptedParams || []),\n );\n }\n } catch (error) {\n log.fatal(\"Express encountered an error while sending the response\");\n log.var({ responseError: error });\n }\n\n // Log response\n const extras: Record<string, unknown> = {};\n if (response) extras.body = response;\n log.info.var({\n res: summarizeResponse(res, extras),\n });\n\n // Submit metric if Datadog is configured\n if (hasDatadogEnv()) {\n // Construct path from baseUrl and url\n let path = (req.baseUrl || \"\") + (req.url || \"\");\n // Ensure path starts with /\n if (!path.startsWith(\"/\")) {\n path = \"/\" + path;\n }\n // Remove trailing slash unless it's the root path\n if (path.length > 1 && path.endsWith(\"/\")) {\n path = path.slice(0, -1);\n }\n\n // Replace UUIDs with :id for better aggregation\n // Matches standard UUID v4 format (8-4-4-4-12 hex characters)\n path = path.replace(\n /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi,\n \":id\",\n );\n\n // Determine metric name based on environment variables\n let metricPrefix = \"project\";\n if (process.env.PROJECT_SPONSOR) {\n metricPrefix = process.env.PROJECT_SPONSOR;\n } else if (process.env.PROJECT_KEY) {\n metricPrefix = `project.${process.env.PROJECT_KEY}`;\n }\n\n await submitMetric({\n name: `${metricPrefix}.api.response`,\n type: DATADOG.METRIC.TYPE.COUNT,\n value: 1,\n tags: {\n status: String(res.statusCode),\n path,\n },\n });\n }\n\n // Clean up the public logger\n logger.untag(\"handler\");\n\n //\n //\n // Return\n //\n\n return response as T;\n };\n}\n\n//\n//\n// Export\n//\n\nexport default expressHandler;\n","import type { Request, Response } from \"express\";\nimport {\n BadGatewayError,\n BadRequestError,\n ForbiddenError,\n GatewayTimeoutError,\n GoneError,\n HTTP,\n InternalError,\n log,\n MethodNotAllowedError,\n NotFoundError,\n TeapotError,\n UnauthorizedError,\n UnavailableError,\n} from \"@jaypie/core\";\n\nimport expressHandler, { ExpressHandlerOptions } from \"./expressHandler.js\";\n\n//\n//\n// Types\n//\n\ntype ErrorConstructor = new () => Error;\n\n//\n//\n// Main\n//\n\nconst httpHandler = (\n statusCode: number = HTTP.CODE.OK,\n context: ExpressHandlerOptions = {},\n): ((\n req: Request,\n res: Response,\n) => Promise<Record<string, unknown> | null>) => {\n // Give a default name if there isn't one\n if (!context.name) {\n context.name = \"_http\";\n }\n\n // Return a function that will be used as an express route\n return expressHandler(\n async (\n req: Request,\n res: Response,\n ): Promise<Record<string, unknown> | null> => {\n // Map the most throwable status codes to errors and throw them!\n const error: Record<number, ErrorConstructor> = {\n [HTTP.CODE.BAD_REQUEST]: BadRequestError,\n [HTTP.CODE.UNAUTHORIZED]: UnauthorizedError,\n [HTTP.CODE.FORBIDDEN]: ForbiddenError,\n [HTTP.CODE.NOT_FOUND]: NotFoundError,\n [HTTP.CODE.METHOD_NOT_ALLOWED]: MethodNotAllowedError,\n [HTTP.CODE.GONE]: GoneError,\n [HTTP.CODE.TEAPOT]: TeapotError,\n [HTTP.CODE.INTERNAL_ERROR]: InternalError,\n [HTTP.CODE.BAD_GATEWAY]: BadGatewayError,\n [HTTP.CODE.UNAVAILABLE]: UnavailableError,\n [HTTP.CODE.GATEWAY_TIMEOUT]: GatewayTimeoutError,\n };\n\n // If this maps to an error, throw it\n if (error[statusCode]) {\n log.trace(\n `@knowdev/express: gracefully throwing ${statusCode} up to projectHandler`,\n );\n throw new error[statusCode]();\n }\n\n // If this is an error and we didn't get thrown, log a warning\n if (statusCode >= 400) {\n log.warn(\n `@knowdev/express: status code ${statusCode} not mapped as throwable`,\n );\n }\n\n // Send the response\n res.status(statusCode);\n return statusCode === HTTP.CODE.NO_CONTENT ? null : {};\n },\n context,\n );\n};\n\n//\n//\n// Export\n//\n\nexport default httpHandler;\n","import type { Request, Response } from \"express\";\nimport { validate } from \"@jaypie/core\";\n\nimport expressHandler, { ExpressHandlerOptions } from \"./expressHandler.js\";\nimport summarizeRequest from \"./summarizeRequest.helper.js\";\n\n//\n//\n// Types\n//\n\nexport interface EchoResponse {\n req: ReturnType<typeof summarizeRequest>;\n}\n\n//\n//\n// Main\n//\n\nconst echoHandler = (\n context: ExpressHandlerOptions = {},\n): ((req: Request, res: Response) => Promise<EchoResponse>) => {\n validate.object(context);\n // Give a default name if there isn't one\n if (!context.name) {\n context.name = \"_echo\";\n }\n\n // Return a function that will be used as an express route\n return expressHandler(async (req: Request): Promise<EchoResponse> => {\n return {\n req: summarizeRequest(req),\n };\n }, context);\n};\n\n//\n//\n// Export\n//\n\nexport default echoHandler;\n","import { HTTP, NotImplementedError } from \"@jaypie/core\";\n\nimport expressHandler from \"./expressHandler.js\";\nimport httpHandler from \"./http.handler.js\";\nimport echoHandler from \"./echo.handler.js\";\n\n//\n//\n// Functions\n//\n\nconst routes = {\n badRequestRoute: httpHandler(HTTP.CODE.BAD_REQUEST, { name: \"_badRequest\" }),\n echoRoute: echoHandler(),\n forbiddenRoute: httpHandler(HTTP.CODE.FORBIDDEN, { name: \"_forbidden\" }),\n goneRoute: httpHandler(HTTP.CODE.GONE, { name: \"_gone\" }),\n methodNotAllowedRoute: httpHandler(HTTP.CODE.METHOD_NOT_ALLOWED, {\n name: \"_methodNotAllowed\",\n }),\n noContentRoute: httpHandler(HTTP.CODE.NO_CONTENT, { name: \"_noContent\" }),\n notFoundRoute: httpHandler(HTTP.CODE.NOT_FOUND, { name: \"_notFound\" }),\n notImplementedRoute: expressHandler(\n (): never => {\n throw new NotImplementedError();\n },\n { name: \"_notImplemented\" },\n ),\n};\n\n//\n//\n// Export\n//\n\nexport const badRequestRoute = routes.badRequestRoute;\nexport const echoRoute = routes.echoRoute;\nexport const forbiddenRoute = routes.forbiddenRoute;\nexport const goneRoute = routes.goneRoute;\nexport const methodNotAllowedRoute = routes.methodNotAllowedRoute;\nexport const noContentRoute = routes.noContentRoute;\nexport const notFoundRoute = routes.notFoundRoute;\nexport const notImplementedRoute = routes.notImplementedRoute;\n"],"names":["log","publicLogger","validate","validateIs"],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const badRequestRoute: (req: import("express").Request, res: import("express").Response) => Promise<Record<string, unknown> | null>;
|
|
2
|
+
export declare const echoRoute: (req: import("express").Request, res: import("express").Response) => Promise<import("./echo.handler.js").EchoResponse>;
|
|
3
|
+
export declare const forbiddenRoute: (req: import("express").Request, res: import("express").Response) => Promise<Record<string, unknown> | null>;
|
|
4
|
+
export declare const goneRoute: (req: import("express").Request, res: import("express").Response) => Promise<Record<string, unknown> | null>;
|
|
5
|
+
export declare const methodNotAllowedRoute: (req: import("express").Request, res: import("express").Response) => Promise<Record<string, unknown> | null>;
|
|
6
|
+
export declare const noContentRoute: (req: import("express").Request, res: import("express").Response) => Promise<Record<string, unknown> | null>;
|
|
7
|
+
export declare const notFoundRoute: (req: import("express").Request, res: import("express").Response) => Promise<Record<string, unknown> | null>;
|
|
8
|
+
export declare const notImplementedRoute: (req: import("express").Request, res: import("express").Response, ...params: unknown[]) => Promise<unknown>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Request } from "express";
|
|
2
|
+
export interface RequestSummary {
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
body: unknown;
|
|
5
|
+
headers: Request["headers"];
|
|
6
|
+
method: string;
|
|
7
|
+
query: Request["query"];
|
|
8
|
+
url: string;
|
|
9
|
+
}
|
|
10
|
+
declare function summarizeRequest(req: Request): RequestSummary;
|
|
11
|
+
export default summarizeRequest;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Response } from "express";
|
|
2
|
+
export interface ResponseSummary {
|
|
3
|
+
statusCode: number;
|
|
4
|
+
statusMessage: string;
|
|
5
|
+
headers?: ReturnType<Response["getHeaders"]>;
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
}
|
|
8
|
+
declare function summarizeResponse(res: Response, extras?: Record<string, unknown>): ResponseSummary;
|
|
9
|
+
export default summarizeResponse;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jaypie/express",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.18-rc.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/finlaysonstudio/jaypie"
|
|
@@ -10,15 +10,17 @@
|
|
|
10
10
|
"type": "module",
|
|
11
11
|
"exports": {
|
|
12
12
|
".": {
|
|
13
|
-
"types": "./index.d.ts",
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
"default": "./src/index.js"
|
|
17
|
-
}
|
|
13
|
+
"types": "./dist/esm/index.d.ts",
|
|
14
|
+
"import": "./dist/esm/index.js",
|
|
15
|
+
"require": "./dist/cjs/index.cjs"
|
|
18
16
|
}
|
|
19
17
|
},
|
|
20
|
-
"main": "
|
|
21
|
-
"
|
|
18
|
+
"main": "./dist/cjs/index.cjs",
|
|
19
|
+
"module": "./dist/esm/index.js",
|
|
20
|
+
"types": "./dist/esm/index.d.ts",
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
22
24
|
"scripts": {
|
|
23
25
|
"build": "rollup --config",
|
|
24
26
|
"format": "npm run format:package && npm run format:lint",
|
|
@@ -26,19 +28,19 @@
|
|
|
26
28
|
"format:package": "sort-package-json ./package.json",
|
|
27
29
|
"lint": "eslint .",
|
|
28
30
|
"test": "vitest run .",
|
|
29
|
-
"test:spec:constants": "vitest run ./src/__tests__/constants.spec.
|
|
30
|
-
"test:spec:cors.helper": "vitest run ./src/__tests__/cors.helper.spec.
|
|
31
|
-
"test:spec:decorateResponse.helper": "vitest run ./src/__tests__/decorateResponse.helper.spec.
|
|
32
|
-
"test:spec:echo.handler": "vitest run ./src/__tests__/echo.handler.spec.
|
|
33
|
-
"test:spec:expressHandler": "vitest run ./src/__tests__/expressHandler.spec.
|
|
34
|
-
"test:spec:getCurrentInvokeUuid.adapter": "vitest run ./src/__tests__/getCurrentInvokeUuid.adapter.spec.
|
|
35
|
-
"test:spec:http.handler": "vitest run ./src/__tests__/http.handler.spec.
|
|
36
|
-
"test:spec:index": "vitest run ./src/__tests__/index.spec.
|
|
37
|
-
"test:spec:routes": "vitest run ./src/__tests__/routes.spec.
|
|
38
|
-
"test:spec:summarizeRequest.helper": "vitest run ./src/__tests__/summarizeRequest.helper.spec.
|
|
39
|
-
"test:spec:summarizeResponse.helper": "vitest run ./src/__tests__/summarizeResponse.helper.spec.
|
|
40
|
-
"test:spec:supertest": "vitest run ./src/__tests__/supertest.spec.
|
|
41
|
-
"typecheck": "
|
|
31
|
+
"test:spec:constants": "vitest run ./src/__tests__/constants.spec.ts",
|
|
32
|
+
"test:spec:cors.helper": "vitest run ./src/__tests__/cors.helper.spec.ts",
|
|
33
|
+
"test:spec:decorateResponse.helper": "vitest run ./src/__tests__/decorateResponse.helper.spec.ts",
|
|
34
|
+
"test:spec:echo.handler": "vitest run ./src/__tests__/echo.handler.spec.ts",
|
|
35
|
+
"test:spec:expressHandler": "vitest run ./src/__tests__/expressHandler.spec.ts",
|
|
36
|
+
"test:spec:getCurrentInvokeUuid.adapter": "vitest run ./src/__tests__/getCurrentInvokeUuid.adapter.spec.ts",
|
|
37
|
+
"test:spec:http.handler": "vitest run ./src/__tests__/http.handler.spec.ts",
|
|
38
|
+
"test:spec:index": "vitest run ./src/__tests__/index.spec.ts",
|
|
39
|
+
"test:spec:routes": "vitest run ./src/__tests__/routes.spec.ts",
|
|
40
|
+
"test:spec:summarizeRequest.helper": "vitest run ./src/__tests__/summarizeRequest.helper.spec.ts",
|
|
41
|
+
"test:spec:summarizeResponse.helper": "vitest run ./src/__tests__/summarizeResponse.helper.spec.ts",
|
|
42
|
+
"test:spec:supertest": "vitest run ./src/__tests__/supertest.spec.ts",
|
|
43
|
+
"typecheck": "tsc --noEmit"
|
|
42
44
|
},
|
|
43
45
|
"dependencies": {
|
|
44
46
|
"@codegenie/serverless-express": "^4.15.0",
|
|
@@ -48,10 +50,14 @@
|
|
|
48
50
|
"cors": "^2.8.5"
|
|
49
51
|
},
|
|
50
52
|
"devDependencies": {
|
|
51
|
-
"
|
|
53
|
+
"@rollup/plugin-typescript": "^12.1.2",
|
|
54
|
+
"@types/cors": "^2.8.17",
|
|
55
|
+
"@types/express": "^5.0.0",
|
|
56
|
+
"@types/node": "^22.13.1",
|
|
57
|
+
"express": "^4.21.2",
|
|
58
|
+
"typescript": "^5.3.3"
|
|
52
59
|
},
|
|
53
60
|
"publishConfig": {
|
|
54
61
|
"access": "public"
|
|
55
|
-
}
|
|
56
|
-
"gitHead": "c02ee981173e9a905d70acd2294dea3f62316f00"
|
|
62
|
+
}
|
|
57
63
|
}
|
package/index.d.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { Request, Response, NextFunction } from "express";
|
|
2
|
-
import { JaypieHandlerOptions } from "@jaypie/core";
|
|
3
|
-
|
|
4
|
-
export const EXPRESS: {
|
|
5
|
-
PATH: {
|
|
6
|
-
ANY: "*";
|
|
7
|
-
ID: "/:id";
|
|
8
|
-
ROOT: RegExp;
|
|
9
|
-
};
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export interface CorsConfig {
|
|
13
|
-
origin?: string | string[];
|
|
14
|
-
overrides?: Record<string, unknown>;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface ExpressHandlerOptions extends JaypieHandlerOptions {
|
|
18
|
-
locals?: Record<string, unknown>;
|
|
19
|
-
name?: string;
|
|
20
|
-
setup?: ((req: Request, res: Response) => Promise<void>)[];
|
|
21
|
-
teardown?: ((req: Request, res: Response) => Promise<void>)[];
|
|
22
|
-
unavailable?: boolean;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function cors(
|
|
26
|
-
config?: CorsConfig,
|
|
27
|
-
): (req: Request, res: Response, next: NextFunction) => void;
|
|
28
|
-
|
|
29
|
-
export function expressHandler<T>(
|
|
30
|
-
handler: (req: Request, res: Response, ...params: unknown[]) => Promise<T>,
|
|
31
|
-
options?: ExpressHandlerOptions,
|
|
32
|
-
): (req: Request, res: Response, ...params: unknown[]) => Promise<T>;
|
|
33
|
-
|
|
34
|
-
export function expressHttpCodeHandler(
|
|
35
|
-
statusCode?: number,
|
|
36
|
-
context?: ExpressHandlerOptions,
|
|
37
|
-
): (req: Request, res: Response) => Promise<Record<string, unknown> | null>;
|
|
38
|
-
|
|
39
|
-
// Pre-configured routes
|
|
40
|
-
export const badRequestRoute: (
|
|
41
|
-
req: Request,
|
|
42
|
-
res: Response,
|
|
43
|
-
) => Promise<Record<string, unknown>>;
|
|
44
|
-
export const echoRoute: (
|
|
45
|
-
req: Request,
|
|
46
|
-
res: Response,
|
|
47
|
-
) => Promise<Record<string, unknown>>;
|
|
48
|
-
export const forbiddenRoute: (
|
|
49
|
-
req: Request,
|
|
50
|
-
res: Response,
|
|
51
|
-
) => Promise<Record<string, unknown>>;
|
|
52
|
-
export const goneRoute: (
|
|
53
|
-
req: Request,
|
|
54
|
-
res: Response,
|
|
55
|
-
) => Promise<Record<string, unknown>>;
|
|
56
|
-
export const methodNotAllowedRoute: (
|
|
57
|
-
req: Request,
|
|
58
|
-
res: Response,
|
|
59
|
-
) => Promise<Record<string, unknown>>;
|
|
60
|
-
export const noContentRoute: (req: Request, res: Response) => Promise<null>;
|
|
61
|
-
export const notFoundRoute: (
|
|
62
|
-
req: Request,
|
|
63
|
-
res: Response,
|
|
64
|
-
) => Promise<Record<string, unknown>>;
|
|
65
|
-
export const notImplementedRoute: (
|
|
66
|
-
req: Request,
|
|
67
|
-
res: Response,
|
|
68
|
-
) => Promise<never>;
|
package/rollup.config.mjs
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import autoExternal from "rollup-plugin-auto-external";
|
|
2
|
-
import commonjs from "@rollup/plugin-commonjs";
|
|
3
|
-
import resolve from "@rollup/plugin-node-resolve";
|
|
4
|
-
|
|
5
|
-
export default {
|
|
6
|
-
input: "src/index.js", // Path to your main JavaScript file
|
|
7
|
-
output: [
|
|
8
|
-
{
|
|
9
|
-
file: "dist/module.cjs", // Output file for CommonJS
|
|
10
|
-
format: "cjs", // CommonJS format
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
file: "dist/module.esm.js", // Output file for ES Module
|
|
14
|
-
format: "es", // ES Module format
|
|
15
|
-
},
|
|
16
|
-
],
|
|
17
|
-
plugins: [
|
|
18
|
-
autoExternal(), // Automatically exclude dependencies from the bundle
|
|
19
|
-
resolve(), // Tells Rollup how to find node modules
|
|
20
|
-
commonjs(), // Converts CommonJS modules to ES6
|
|
21
|
-
],
|
|
22
|
-
};
|
package/src/constants.js
DELETED
package/src/cors.helper.js
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { CorsError } from "@jaypie/errors";
|
|
2
|
-
import { envBoolean, force } from "@jaypie/core";
|
|
3
|
-
import expressCors from "cors";
|
|
4
|
-
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// Constants
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
const HTTP_PROTOCOL = "http://";
|
|
11
|
-
const HTTPS_PROTOCOL = "https://";
|
|
12
|
-
const SANDBOX_ENV = "sandbox";
|
|
13
|
-
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
// Helper Functions
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
const ensureProtocol = (url) => {
|
|
20
|
-
if (!url) return url;
|
|
21
|
-
if (url.startsWith(HTTP_PROTOCOL) || url.startsWith(HTTPS_PROTOCOL))
|
|
22
|
-
return url;
|
|
23
|
-
return HTTPS_PROTOCOL + url;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export const dynamicOriginCallbackHandler = (origin) => {
|
|
27
|
-
return (requestOrigin, callback) => {
|
|
28
|
-
// Handle wildcard origin
|
|
29
|
-
if (origin === "*") {
|
|
30
|
-
callback(null, true);
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Allow requests with no origin (like mobile apps, curl, etc)
|
|
35
|
-
if (!requestOrigin) {
|
|
36
|
-
callback(null, true);
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const allowedOrigins = [];
|
|
41
|
-
if (process.env.BASE_URL) {
|
|
42
|
-
allowedOrigins.push(ensureProtocol(process.env.BASE_URL));
|
|
43
|
-
}
|
|
44
|
-
if (process.env.PROJECT_BASE_URL) {
|
|
45
|
-
allowedOrigins.push(ensureProtocol(process.env.PROJECT_BASE_URL));
|
|
46
|
-
}
|
|
47
|
-
if (origin) {
|
|
48
|
-
const additionalOrigins = force.array(origin);
|
|
49
|
-
allowedOrigins.push(...additionalOrigins);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Add localhost origins in sandbox
|
|
53
|
-
if (
|
|
54
|
-
process.env.PROJECT_ENV === SANDBOX_ENV ||
|
|
55
|
-
envBoolean("PROJECT_SANDBOX_MODE")
|
|
56
|
-
) {
|
|
57
|
-
allowedOrigins.push("http://localhost");
|
|
58
|
-
allowedOrigins.push(/^http:\/\/localhost:\d+$/);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const isAllowed = allowedOrigins.some((allowed) => {
|
|
62
|
-
if (allowed instanceof RegExp) {
|
|
63
|
-
return allowed.test(requestOrigin);
|
|
64
|
-
}
|
|
65
|
-
return requestOrigin.includes(allowed);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
if (isAllowed) {
|
|
69
|
-
callback(null, true);
|
|
70
|
-
} else {
|
|
71
|
-
callback(new CorsError());
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
// Main
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
const corsHelper = (config = {}) => {
|
|
82
|
-
const { origin, overrides = {} } = config;
|
|
83
|
-
|
|
84
|
-
const options = {
|
|
85
|
-
origin: dynamicOriginCallbackHandler(origin),
|
|
86
|
-
// * The default behavior is to allow any headers and methods so they are not included here
|
|
87
|
-
...overrides,
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
return expressCors(options);
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
//
|
|
94
|
-
//
|
|
95
|
-
// Export
|
|
96
|
-
//
|
|
97
|
-
|
|
98
|
-
export default (config) => {
|
|
99
|
-
const cors = corsHelper(config);
|
|
100
|
-
return (req, res, next) => {
|
|
101
|
-
cors(req, res, (error) => {
|
|
102
|
-
if (error) {
|
|
103
|
-
res.status(error.status);
|
|
104
|
-
res.setHeader("Content-Type", "application/json");
|
|
105
|
-
return res.json(error.body());
|
|
106
|
-
}
|
|
107
|
-
next();
|
|
108
|
-
});
|
|
109
|
-
};
|
|
110
|
-
};
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { HTTP, JAYPIE, log as publicLogger } from "@jaypie/core";
|
|
2
|
-
import getCurrentInvokeUuid from "./getCurrentInvokeUuid.adapter.js";
|
|
3
|
-
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// Main
|
|
7
|
-
//
|
|
8
|
-
|
|
9
|
-
const decorateResponse = (
|
|
10
|
-
res,
|
|
11
|
-
{ handler = "", version = process.env.PROJECT_VERSION } = {},
|
|
12
|
-
) => {
|
|
13
|
-
const log = publicLogger.lib({
|
|
14
|
-
lib: JAYPIE.LIB.EXPRESS,
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
// Validate
|
|
20
|
-
//
|
|
21
|
-
if (typeof res !== "object" || res === null) {
|
|
22
|
-
log.warn("decorateResponse called but response is not an object");
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
try {
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
// Decorate Headers
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
// X-Powered-By, override "Express" but nothing else
|
|
33
|
-
if (
|
|
34
|
-
!res.get(HTTP.HEADER.POWERED_BY) ||
|
|
35
|
-
res.get(HTTP.HEADER.POWERED_BY) === "Express"
|
|
36
|
-
) {
|
|
37
|
-
res.set(HTTP.HEADER.POWERED_BY, JAYPIE.LIB.EXPRESS);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// X-Project-Environment
|
|
41
|
-
if (process.env.PROJECT_ENV) {
|
|
42
|
-
res.set(HTTP.HEADER.PROJECT.ENVIRONMENT, process.env.PROJECT_ENV);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// X-Project-Handler
|
|
46
|
-
if (handler) {
|
|
47
|
-
res.set(HTTP.HEADER.PROJECT.HANDLER, handler);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// X-Project-Invocation
|
|
51
|
-
const currentInvoke = getCurrentInvokeUuid();
|
|
52
|
-
if (currentInvoke) {
|
|
53
|
-
res.set(HTTP.HEADER.PROJECT.INVOCATION, currentInvoke);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// X-Project-Key
|
|
57
|
-
if (process.env.PROJECT_KEY) {
|
|
58
|
-
res.set(HTTP.HEADER.PROJECT.KEY, process.env.PROJECT_KEY);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// X-Project-Version
|
|
62
|
-
if (version) {
|
|
63
|
-
res.set(HTTP.HEADER.PROJECT.VERSION, version);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
// Error Handling
|
|
69
|
-
//
|
|
70
|
-
} catch (error) {
|
|
71
|
-
log.warn("decorateResponse caught an internal error");
|
|
72
|
-
log.var({ error });
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
// Export
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
export default decorateResponse;
|
|
82
|
-
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
// Footnotes
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
// This is a "utility" function but it needs a lot of "context"
|
|
89
|
-
// about the environment's secret parameters, the special adapter,
|
|
90
|
-
// HTTP, etc. There must be a better way to organize this
|
package/src/echo.handler.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { validate } from "@jaypie/core";
|
|
2
|
-
|
|
3
|
-
import expressHandler from "./expressHandler.js";
|
|
4
|
-
import summarizeRequest from "./summarizeRequest.helper.js";
|
|
5
|
-
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// Main
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
const echoHandler = (context = {}) => {
|
|
12
|
-
validate.object(context);
|
|
13
|
-
// Give a default name if there isn't one
|
|
14
|
-
if (!context.name) {
|
|
15
|
-
context.name = "_echo";
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Return a function that will be used as an express route
|
|
19
|
-
return expressHandler(async (req) => {
|
|
20
|
-
return {
|
|
21
|
-
req: summarizeRequest(req),
|
|
22
|
-
};
|
|
23
|
-
}, context);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
// Export
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
export default echoHandler;
|