@loglayer/express 1.1.0 → 1.2.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/index.cjs +2 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value:
|
|
2
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
2
|
//#region src/plugin.ts
|
|
4
3
|
function resolveGroupConfig(group) {
|
|
5
4
|
if (!group) return {
|
|
@@ -147,8 +146,8 @@ function expressLogLayerErrorHandler(config) {
|
|
|
147
146
|
next(err);
|
|
148
147
|
};
|
|
149
148
|
}
|
|
150
|
-
|
|
151
149
|
//#endregion
|
|
152
150
|
exports.expressLogLayer = expressLogLayer;
|
|
153
151
|
exports.expressLogLayerErrorHandler = expressLogLayerErrorHandler;
|
|
152
|
+
|
|
154
153
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["import type { ErrorRequestHandler, NextFunction, Request, Response } from \"express\";\nimport type { ILogLayer } from \"loglayer\";\nimport type {\n ExpressAutoLoggingConfig,\n ExpressLogLayerConfig,\n ExpressRequestLoggingConfig,\n ExpressResponseLoggingConfig,\n} from \"./types.js\";\n\nfunction resolveGroupConfig(group: ExpressLogLayerConfig[\"group\"]) {\n if (!group) return { nameGroup: undefined, requestGroup: undefined, responseGroup: undefined };\n if (group === true)\n return { nameGroup: \"express\", requestGroup: \"express.request\", responseGroup: \"express.response\" };\n return {\n nameGroup: group.name ?? \"express\",\n requestGroup: group.request ?? \"express.request\",\n responseGroup: group.response ?? \"express.response\",\n };\n}\n\nfunction shouldIgnorePath(path: string, ignore?: Array<string | RegExp>): boolean {\n if (!ignore || ignore.length === 0) return false;\n\n for (const pattern of ignore) {\n if (typeof pattern === \"string\") {\n if (path === pattern) return true;\n } else if (pattern.test(path)) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction getRequestId(request: Request, requestIdConfig: ExpressLogLayerConfig[\"requestId\"]): string | undefined {\n if (requestIdConfig === false) return undefined;\n if (typeof requestIdConfig === \"function\") return requestIdConfig(request);\n return crypto.randomUUID();\n}\n\nfunction resolveLoggingConfig<T>(value: boolean | T | undefined, defaultEnabled: boolean): T | false {\n if (value === undefined) return defaultEnabled ? ({} as T) : false;\n if (value === true) return {} as T;\n if (value === false) return false;\n return value;\n}\n\n/**\n * Creates an Express middleware that integrates LogLayer for request-scoped logging.\n *\n * The middleware attaches a child LogLayer instance to `req.log` for each request.\n *\n * @example\n * ```typescript\n * import express from \"express\";\n * import { LogLayer, ConsoleTransport } from \"loglayer\";\n * import { expressLogLayer } from \"@loglayer/express\";\n *\n * const log = new LogLayer({ transport: new ConsoleTransport() });\n *\n * const app = express();\n * app.use(expressLogLayer({ instance: log }));\n *\n * app.get(\"/\", (req, res) => {\n * req.log.info(\"Hello from route!\");\n * res.send(\"Hello World!\");\n * });\n * ```\n */\nexport function expressLogLayer(config: ExpressLogLayerConfig) {\n const {\n instance,\n requestId: requestIdConfig = true,\n autoLogging: autoLoggingConfig = true,\n contextFn,\n group: groupConfig,\n } = config;\n const { requestGroup, responseGroup } = resolveGroupConfig(groupConfig);\n\n const autoLogging: ExpressAutoLoggingConfig | false =\n autoLoggingConfig === true ? {} : autoLoggingConfig === false ? false : autoLoggingConfig;\n\n // Resolve auto-logging configs once\n const requestConfig = autoLogging\n ? resolveLoggingConfig<ExpressRequestLoggingConfig>(autoLogging.request, true)\n : false;\n const responseConfig = autoLogging\n ? resolveLoggingConfig<ExpressResponseLoggingConfig>(autoLogging.response, true)\n : false;\n\n const defaultLogLevel = autoLogging ? (autoLogging.logLevel ?? \"info\") : \"info\";\n const requestLogLevel = requestConfig ? (requestConfig.logLevel ?? defaultLogLevel) : defaultLogLevel;\n const responseLogLevel = responseConfig ? (responseConfig.logLevel ?? defaultLogLevel) : defaultLogLevel;\n\n return (req: Request, res: Response, next: NextFunction) => {\n const context: Record<string, any> = {};\n\n const reqId = getRequestId(req, requestIdConfig);\n if (reqId) {\n context.requestId = reqId;\n }\n\n if (contextFn) {\n const additionalContext = contextFn(req);\n if (additionalContext) {\n Object.assign(context, additionalContext);\n }\n }\n\n // Create child logger and attach to req.log\n const childLogger = instance.child().withContext(context) as ILogLayer;\n (req as any).log = childLogger;\n\n const startTime = Date.now();\n const ignorePath = autoLogging ? shouldIgnorePath(req.path, autoLogging.ignore) : true;\n\n // Log incoming request\n if (requestConfig && !ignorePath) {\n let builder = childLogger.withMetadata({\n req: {\n method: req.method,\n url: req.originalUrl || req.url,\n remoteAddress: req.ip,\n },\n });\n if (requestGroup) builder = builder.withGroup(requestGroup);\n builder[requestLogLevel](\"incoming request\");\n }\n\n // Log response on completion (listen on close, finish, and error for reliability)\n if (responseConfig && !ignorePath) {\n const onResponseComplete = () => {\n res.removeListener(\"close\", onResponseComplete);\n res.removeListener(\"finish\", onResponseComplete);\n res.removeListener(\"error\", onResponseComplete);\n\n const responseTime = Date.now() - startTime;\n let builder = childLogger.withMetadata({\n req: {\n method: req.method,\n url: req.originalUrl || req.url,\n remoteAddress: req.ip,\n },\n res: {\n statusCode: res.statusCode,\n },\n responseTime,\n });\n if (responseGroup) builder = builder.withGroup(responseGroup);\n builder[responseLogLevel](\"request completed\");\n };\n\n res.on(\"close\", onResponseComplete);\n res.on(\"finish\", onResponseComplete);\n res.on(\"error\", onResponseComplete);\n }\n\n next();\n };\n}\n\n/**\n * Creates an Express error-handling middleware that logs errors via LogLayer.\n *\n * This middleware should be registered after all routes. It logs the error\n * using `req.log` (set by `expressLogLayer`) and passes the error to the\n * next error handler via `next(err)`.\n *\n * @example\n * ```typescript\n * import express from \"express\";\n * import { expressLogLayer, expressLogLayerErrorHandler } from \"@loglayer/express\";\n *\n * const app = express();\n * app.use(expressLogLayer({ instance: log }));\n *\n * // ... routes ...\n *\n * app.use(expressLogLayerErrorHandler());\n * app.use((err, req, res, next) => {\n * res.status(500).send(\"Internal Server Error\");\n * });\n * ```\n */\nexport function expressLogLayerErrorHandler(config?: { group?: ExpressLogLayerConfig[\"group\"] }): ErrorRequestHandler {\n const { nameGroup } = resolveGroupConfig(config?.group);\n\n return (err: Error, req: Request, _res: Response, next: NextFunction) => {\n if ((req as any).log) {\n let builder = ((req as any).log as ILogLayer).withError(err).withMetadata({ url: req.originalUrl || req.url });\n if (nameGroup) builder = builder.withGroup(nameGroup);\n builder.error(\"Request error\");\n }\n next(err);\n };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["import type { ErrorRequestHandler, NextFunction, Request, Response } from \"express\";\nimport type { ILogLayer } from \"loglayer\";\nimport type {\n ExpressAutoLoggingConfig,\n ExpressLogLayerConfig,\n ExpressRequestLoggingConfig,\n ExpressResponseLoggingConfig,\n} from \"./types.js\";\n\nfunction resolveGroupConfig(group: ExpressLogLayerConfig[\"group\"]) {\n if (!group) return { nameGroup: undefined, requestGroup: undefined, responseGroup: undefined };\n if (group === true)\n return { nameGroup: \"express\", requestGroup: \"express.request\", responseGroup: \"express.response\" };\n return {\n nameGroup: group.name ?? \"express\",\n requestGroup: group.request ?? \"express.request\",\n responseGroup: group.response ?? \"express.response\",\n };\n}\n\nfunction shouldIgnorePath(path: string, ignore?: Array<string | RegExp>): boolean {\n if (!ignore || ignore.length === 0) return false;\n\n for (const pattern of ignore) {\n if (typeof pattern === \"string\") {\n if (path === pattern) return true;\n } else if (pattern.test(path)) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction getRequestId(request: Request, requestIdConfig: ExpressLogLayerConfig[\"requestId\"]): string | undefined {\n if (requestIdConfig === false) return undefined;\n if (typeof requestIdConfig === \"function\") return requestIdConfig(request);\n return crypto.randomUUID();\n}\n\nfunction resolveLoggingConfig<T>(value: boolean | T | undefined, defaultEnabled: boolean): T | false {\n if (value === undefined) return defaultEnabled ? ({} as T) : false;\n if (value === true) return {} as T;\n if (value === false) return false;\n return value;\n}\n\n/**\n * Creates an Express middleware that integrates LogLayer for request-scoped logging.\n *\n * The middleware attaches a child LogLayer instance to `req.log` for each request.\n *\n * @example\n * ```typescript\n * import express from \"express\";\n * import { LogLayer, ConsoleTransport } from \"loglayer\";\n * import { expressLogLayer } from \"@loglayer/express\";\n *\n * const log = new LogLayer({ transport: new ConsoleTransport() });\n *\n * const app = express();\n * app.use(expressLogLayer({ instance: log }));\n *\n * app.get(\"/\", (req, res) => {\n * req.log.info(\"Hello from route!\");\n * res.send(\"Hello World!\");\n * });\n * ```\n */\nexport function expressLogLayer(config: ExpressLogLayerConfig) {\n const {\n instance,\n requestId: requestIdConfig = true,\n autoLogging: autoLoggingConfig = true,\n contextFn,\n group: groupConfig,\n } = config;\n const { requestGroup, responseGroup } = resolveGroupConfig(groupConfig);\n\n const autoLogging: ExpressAutoLoggingConfig | false =\n autoLoggingConfig === true ? {} : autoLoggingConfig === false ? false : autoLoggingConfig;\n\n // Resolve auto-logging configs once\n const requestConfig = autoLogging\n ? resolveLoggingConfig<ExpressRequestLoggingConfig>(autoLogging.request, true)\n : false;\n const responseConfig = autoLogging\n ? resolveLoggingConfig<ExpressResponseLoggingConfig>(autoLogging.response, true)\n : false;\n\n const defaultLogLevel = autoLogging ? (autoLogging.logLevel ?? \"info\") : \"info\";\n const requestLogLevel = requestConfig ? (requestConfig.logLevel ?? defaultLogLevel) : defaultLogLevel;\n const responseLogLevel = responseConfig ? (responseConfig.logLevel ?? defaultLogLevel) : defaultLogLevel;\n\n return (req: Request, res: Response, next: NextFunction) => {\n const context: Record<string, any> = {};\n\n const reqId = getRequestId(req, requestIdConfig);\n if (reqId) {\n context.requestId = reqId;\n }\n\n if (contextFn) {\n const additionalContext = contextFn(req);\n if (additionalContext) {\n Object.assign(context, additionalContext);\n }\n }\n\n // Create child logger and attach to req.log\n const childLogger = instance.child().withContext(context) as ILogLayer;\n (req as any).log = childLogger;\n\n const startTime = Date.now();\n const ignorePath = autoLogging ? shouldIgnorePath(req.path, autoLogging.ignore) : true;\n\n // Log incoming request\n if (requestConfig && !ignorePath) {\n let builder = childLogger.withMetadata({\n req: {\n method: req.method,\n url: req.originalUrl || req.url,\n remoteAddress: req.ip,\n },\n });\n if (requestGroup) builder = builder.withGroup(requestGroup);\n builder[requestLogLevel](\"incoming request\");\n }\n\n // Log response on completion (listen on close, finish, and error for reliability)\n if (responseConfig && !ignorePath) {\n const onResponseComplete = () => {\n res.removeListener(\"close\", onResponseComplete);\n res.removeListener(\"finish\", onResponseComplete);\n res.removeListener(\"error\", onResponseComplete);\n\n const responseTime = Date.now() - startTime;\n let builder = childLogger.withMetadata({\n req: {\n method: req.method,\n url: req.originalUrl || req.url,\n remoteAddress: req.ip,\n },\n res: {\n statusCode: res.statusCode,\n },\n responseTime,\n });\n if (responseGroup) builder = builder.withGroup(responseGroup);\n builder[responseLogLevel](\"request completed\");\n };\n\n res.on(\"close\", onResponseComplete);\n res.on(\"finish\", onResponseComplete);\n res.on(\"error\", onResponseComplete);\n }\n\n next();\n };\n}\n\n/**\n * Creates an Express error-handling middleware that logs errors via LogLayer.\n *\n * This middleware should be registered after all routes. It logs the error\n * using `req.log` (set by `expressLogLayer`) and passes the error to the\n * next error handler via `next(err)`.\n *\n * @example\n * ```typescript\n * import express from \"express\";\n * import { expressLogLayer, expressLogLayerErrorHandler } from \"@loglayer/express\";\n *\n * const app = express();\n * app.use(expressLogLayer({ instance: log }));\n *\n * // ... routes ...\n *\n * app.use(expressLogLayerErrorHandler());\n * app.use((err, req, res, next) => {\n * res.status(500).send(\"Internal Server Error\");\n * });\n * ```\n */\nexport function expressLogLayerErrorHandler(config?: { group?: ExpressLogLayerConfig[\"group\"] }): ErrorRequestHandler {\n const { nameGroup } = resolveGroupConfig(config?.group);\n\n return (err: Error, req: Request, _res: Response, next: NextFunction) => {\n if ((req as any).log) {\n let builder = ((req as any).log as ILogLayer).withError(err).withMetadata({ url: req.originalUrl || req.url });\n if (nameGroup) builder = builder.withGroup(nameGroup);\n builder.error(\"Request error\");\n }\n next(err);\n };\n}\n"],"mappings":"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"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["import type { ErrorRequestHandler, NextFunction, Request, Response } from \"express\";\nimport type { ILogLayer } from \"loglayer\";\nimport type {\n ExpressAutoLoggingConfig,\n ExpressLogLayerConfig,\n ExpressRequestLoggingConfig,\n ExpressResponseLoggingConfig,\n} from \"./types.js\";\n\nfunction resolveGroupConfig(group: ExpressLogLayerConfig[\"group\"]) {\n if (!group) return { nameGroup: undefined, requestGroup: undefined, responseGroup: undefined };\n if (group === true)\n return { nameGroup: \"express\", requestGroup: \"express.request\", responseGroup: \"express.response\" };\n return {\n nameGroup: group.name ?? \"express\",\n requestGroup: group.request ?? \"express.request\",\n responseGroup: group.response ?? \"express.response\",\n };\n}\n\nfunction shouldIgnorePath(path: string, ignore?: Array<string | RegExp>): boolean {\n if (!ignore || ignore.length === 0) return false;\n\n for (const pattern of ignore) {\n if (typeof pattern === \"string\") {\n if (path === pattern) return true;\n } else if (pattern.test(path)) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction getRequestId(request: Request, requestIdConfig: ExpressLogLayerConfig[\"requestId\"]): string | undefined {\n if (requestIdConfig === false) return undefined;\n if (typeof requestIdConfig === \"function\") return requestIdConfig(request);\n return crypto.randomUUID();\n}\n\nfunction resolveLoggingConfig<T>(value: boolean | T | undefined, defaultEnabled: boolean): T | false {\n if (value === undefined) return defaultEnabled ? ({} as T) : false;\n if (value === true) return {} as T;\n if (value === false) return false;\n return value;\n}\n\n/**\n * Creates an Express middleware that integrates LogLayer for request-scoped logging.\n *\n * The middleware attaches a child LogLayer instance to `req.log` for each request.\n *\n * @example\n * ```typescript\n * import express from \"express\";\n * import { LogLayer, ConsoleTransport } from \"loglayer\";\n * import { expressLogLayer } from \"@loglayer/express\";\n *\n * const log = new LogLayer({ transport: new ConsoleTransport() });\n *\n * const app = express();\n * app.use(expressLogLayer({ instance: log }));\n *\n * app.get(\"/\", (req, res) => {\n * req.log.info(\"Hello from route!\");\n * res.send(\"Hello World!\");\n * });\n * ```\n */\nexport function expressLogLayer(config: ExpressLogLayerConfig) {\n const {\n instance,\n requestId: requestIdConfig = true,\n autoLogging: autoLoggingConfig = true,\n contextFn,\n group: groupConfig,\n } = config;\n const { requestGroup, responseGroup } = resolveGroupConfig(groupConfig);\n\n const autoLogging: ExpressAutoLoggingConfig | false =\n autoLoggingConfig === true ? {} : autoLoggingConfig === false ? false : autoLoggingConfig;\n\n // Resolve auto-logging configs once\n const requestConfig = autoLogging\n ? resolveLoggingConfig<ExpressRequestLoggingConfig>(autoLogging.request, true)\n : false;\n const responseConfig = autoLogging\n ? resolveLoggingConfig<ExpressResponseLoggingConfig>(autoLogging.response, true)\n : false;\n\n const defaultLogLevel = autoLogging ? (autoLogging.logLevel ?? \"info\") : \"info\";\n const requestLogLevel = requestConfig ? (requestConfig.logLevel ?? defaultLogLevel) : defaultLogLevel;\n const responseLogLevel = responseConfig ? (responseConfig.logLevel ?? defaultLogLevel) : defaultLogLevel;\n\n return (req: Request, res: Response, next: NextFunction) => {\n const context: Record<string, any> = {};\n\n const reqId = getRequestId(req, requestIdConfig);\n if (reqId) {\n context.requestId = reqId;\n }\n\n if (contextFn) {\n const additionalContext = contextFn(req);\n if (additionalContext) {\n Object.assign(context, additionalContext);\n }\n }\n\n // Create child logger and attach to req.log\n const childLogger = instance.child().withContext(context) as ILogLayer;\n (req as any).log = childLogger;\n\n const startTime = Date.now();\n const ignorePath = autoLogging ? shouldIgnorePath(req.path, autoLogging.ignore) : true;\n\n // Log incoming request\n if (requestConfig && !ignorePath) {\n let builder = childLogger.withMetadata({\n req: {\n method: req.method,\n url: req.originalUrl || req.url,\n remoteAddress: req.ip,\n },\n });\n if (requestGroup) builder = builder.withGroup(requestGroup);\n builder[requestLogLevel](\"incoming request\");\n }\n\n // Log response on completion (listen on close, finish, and error for reliability)\n if (responseConfig && !ignorePath) {\n const onResponseComplete = () => {\n res.removeListener(\"close\", onResponseComplete);\n res.removeListener(\"finish\", onResponseComplete);\n res.removeListener(\"error\", onResponseComplete);\n\n const responseTime = Date.now() - startTime;\n let builder = childLogger.withMetadata({\n req: {\n method: req.method,\n url: req.originalUrl || req.url,\n remoteAddress: req.ip,\n },\n res: {\n statusCode: res.statusCode,\n },\n responseTime,\n });\n if (responseGroup) builder = builder.withGroup(responseGroup);\n builder[responseLogLevel](\"request completed\");\n };\n\n res.on(\"close\", onResponseComplete);\n res.on(\"finish\", onResponseComplete);\n res.on(\"error\", onResponseComplete);\n }\n\n next();\n };\n}\n\n/**\n * Creates an Express error-handling middleware that logs errors via LogLayer.\n *\n * This middleware should be registered after all routes. It logs the error\n * using `req.log` (set by `expressLogLayer`) and passes the error to the\n * next error handler via `next(err)`.\n *\n * @example\n * ```typescript\n * import express from \"express\";\n * import { expressLogLayer, expressLogLayerErrorHandler } from \"@loglayer/express\";\n *\n * const app = express();\n * app.use(expressLogLayer({ instance: log }));\n *\n * // ... routes ...\n *\n * app.use(expressLogLayerErrorHandler());\n * app.use((err, req, res, next) => {\n * res.status(500).send(\"Internal Server Error\");\n * });\n * ```\n */\nexport function expressLogLayerErrorHandler(config?: { group?: ExpressLogLayerConfig[\"group\"] }): ErrorRequestHandler {\n const { nameGroup } = resolveGroupConfig(config?.group);\n\n return (err: Error, req: Request, _res: Response, next: NextFunction) => {\n if ((req as any).log) {\n let builder = ((req as any).log as ILogLayer).withError(err).withMetadata({ url: req.originalUrl || req.url });\n if (nameGroup) builder = builder.withGroup(nameGroup);\n builder.error(\"Request error\");\n }\n next(err);\n };\n}\n"],"mappings":";AASA,SAAS,mBAAmB,OAAuC;
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["import type { ErrorRequestHandler, NextFunction, Request, Response } from \"express\";\nimport type { ILogLayer } from \"loglayer\";\nimport type {\n ExpressAutoLoggingConfig,\n ExpressLogLayerConfig,\n ExpressRequestLoggingConfig,\n ExpressResponseLoggingConfig,\n} from \"./types.js\";\n\nfunction resolveGroupConfig(group: ExpressLogLayerConfig[\"group\"]) {\n if (!group) return { nameGroup: undefined, requestGroup: undefined, responseGroup: undefined };\n if (group === true)\n return { nameGroup: \"express\", requestGroup: \"express.request\", responseGroup: \"express.response\" };\n return {\n nameGroup: group.name ?? \"express\",\n requestGroup: group.request ?? \"express.request\",\n responseGroup: group.response ?? \"express.response\",\n };\n}\n\nfunction shouldIgnorePath(path: string, ignore?: Array<string | RegExp>): boolean {\n if (!ignore || ignore.length === 0) return false;\n\n for (const pattern of ignore) {\n if (typeof pattern === \"string\") {\n if (path === pattern) return true;\n } else if (pattern.test(path)) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction getRequestId(request: Request, requestIdConfig: ExpressLogLayerConfig[\"requestId\"]): string | undefined {\n if (requestIdConfig === false) return undefined;\n if (typeof requestIdConfig === \"function\") return requestIdConfig(request);\n return crypto.randomUUID();\n}\n\nfunction resolveLoggingConfig<T>(value: boolean | T | undefined, defaultEnabled: boolean): T | false {\n if (value === undefined) return defaultEnabled ? ({} as T) : false;\n if (value === true) return {} as T;\n if (value === false) return false;\n return value;\n}\n\n/**\n * Creates an Express middleware that integrates LogLayer for request-scoped logging.\n *\n * The middleware attaches a child LogLayer instance to `req.log` for each request.\n *\n * @example\n * ```typescript\n * import express from \"express\";\n * import { LogLayer, ConsoleTransport } from \"loglayer\";\n * import { expressLogLayer } from \"@loglayer/express\";\n *\n * const log = new LogLayer({ transport: new ConsoleTransport() });\n *\n * const app = express();\n * app.use(expressLogLayer({ instance: log }));\n *\n * app.get(\"/\", (req, res) => {\n * req.log.info(\"Hello from route!\");\n * res.send(\"Hello World!\");\n * });\n * ```\n */\nexport function expressLogLayer(config: ExpressLogLayerConfig) {\n const {\n instance,\n requestId: requestIdConfig = true,\n autoLogging: autoLoggingConfig = true,\n contextFn,\n group: groupConfig,\n } = config;\n const { requestGroup, responseGroup } = resolveGroupConfig(groupConfig);\n\n const autoLogging: ExpressAutoLoggingConfig | false =\n autoLoggingConfig === true ? {} : autoLoggingConfig === false ? false : autoLoggingConfig;\n\n // Resolve auto-logging configs once\n const requestConfig = autoLogging\n ? resolveLoggingConfig<ExpressRequestLoggingConfig>(autoLogging.request, true)\n : false;\n const responseConfig = autoLogging\n ? resolveLoggingConfig<ExpressResponseLoggingConfig>(autoLogging.response, true)\n : false;\n\n const defaultLogLevel = autoLogging ? (autoLogging.logLevel ?? \"info\") : \"info\";\n const requestLogLevel = requestConfig ? (requestConfig.logLevel ?? defaultLogLevel) : defaultLogLevel;\n const responseLogLevel = responseConfig ? (responseConfig.logLevel ?? defaultLogLevel) : defaultLogLevel;\n\n return (req: Request, res: Response, next: NextFunction) => {\n const context: Record<string, any> = {};\n\n const reqId = getRequestId(req, requestIdConfig);\n if (reqId) {\n context.requestId = reqId;\n }\n\n if (contextFn) {\n const additionalContext = contextFn(req);\n if (additionalContext) {\n Object.assign(context, additionalContext);\n }\n }\n\n // Create child logger and attach to req.log\n const childLogger = instance.child().withContext(context) as ILogLayer;\n (req as any).log = childLogger;\n\n const startTime = Date.now();\n const ignorePath = autoLogging ? shouldIgnorePath(req.path, autoLogging.ignore) : true;\n\n // Log incoming request\n if (requestConfig && !ignorePath) {\n let builder = childLogger.withMetadata({\n req: {\n method: req.method,\n url: req.originalUrl || req.url,\n remoteAddress: req.ip,\n },\n });\n if (requestGroup) builder = builder.withGroup(requestGroup);\n builder[requestLogLevel](\"incoming request\");\n }\n\n // Log response on completion (listen on close, finish, and error for reliability)\n if (responseConfig && !ignorePath) {\n const onResponseComplete = () => {\n res.removeListener(\"close\", onResponseComplete);\n res.removeListener(\"finish\", onResponseComplete);\n res.removeListener(\"error\", onResponseComplete);\n\n const responseTime = Date.now() - startTime;\n let builder = childLogger.withMetadata({\n req: {\n method: req.method,\n url: req.originalUrl || req.url,\n remoteAddress: req.ip,\n },\n res: {\n statusCode: res.statusCode,\n },\n responseTime,\n });\n if (responseGroup) builder = builder.withGroup(responseGroup);\n builder[responseLogLevel](\"request completed\");\n };\n\n res.on(\"close\", onResponseComplete);\n res.on(\"finish\", onResponseComplete);\n res.on(\"error\", onResponseComplete);\n }\n\n next();\n };\n}\n\n/**\n * Creates an Express error-handling middleware that logs errors via LogLayer.\n *\n * This middleware should be registered after all routes. It logs the error\n * using `req.log` (set by `expressLogLayer`) and passes the error to the\n * next error handler via `next(err)`.\n *\n * @example\n * ```typescript\n * import express from \"express\";\n * import { expressLogLayer, expressLogLayerErrorHandler } from \"@loglayer/express\";\n *\n * const app = express();\n * app.use(expressLogLayer({ instance: log }));\n *\n * // ... routes ...\n *\n * app.use(expressLogLayerErrorHandler());\n * app.use((err, req, res, next) => {\n * res.status(500).send(\"Internal Server Error\");\n * });\n * ```\n */\nexport function expressLogLayerErrorHandler(config?: { group?: ExpressLogLayerConfig[\"group\"] }): ErrorRequestHandler {\n const { nameGroup } = resolveGroupConfig(config?.group);\n\n return (err: Error, req: Request, _res: Response, next: NextFunction) => {\n if ((req as any).log) {\n let builder = ((req as any).log as ILogLayer).withError(err).withMetadata({ url: req.originalUrl || req.url });\n if (nameGroup) builder = builder.withGroup(nameGroup);\n builder.error(\"Request error\");\n }\n next(err);\n };\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loglayer/express",
|
|
3
3
|
"description": "Express integration for LogLayer with request-scoped logging, auto request logging, and error handling.",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -34,18 +34,18 @@
|
|
|
34
34
|
],
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/express": "5.0.6",
|
|
37
|
-
"@types/node": "25.
|
|
38
|
-
"@types/supertest": "
|
|
37
|
+
"@types/node": "25.9.1",
|
|
38
|
+
"@types/supertest": "7.2.0",
|
|
39
39
|
"express": "5.2.1",
|
|
40
40
|
"serialize-error": "13.0.1",
|
|
41
41
|
"supertest": "7.2.2",
|
|
42
|
-
"tsdown": "0.
|
|
43
|
-
"tsx": "4.
|
|
44
|
-
"typescript": "
|
|
45
|
-
"vitest": "4.
|
|
42
|
+
"tsdown": "0.22.1",
|
|
43
|
+
"tsx": "4.22.3",
|
|
44
|
+
"typescript": "6.0.3",
|
|
45
|
+
"vitest": "4.1.7",
|
|
46
46
|
"@internal/tsconfig": "2.1.0",
|
|
47
|
-
"@loglayer/transport-simple-pretty-terminal": "3.
|
|
48
|
-
"loglayer": "9.
|
|
47
|
+
"@loglayer/transport-simple-pretty-terminal": "3.2.0",
|
|
48
|
+
"loglayer": "9.3.0"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"express": ">=4.0.0",
|