elegant-logger 1.0.1

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/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the same
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # elegant-logs
2
+
3
+ A professional, beautiful, and highly customizable Express request and error logger middleware for Node.js services.
4
+
5
+ ## Features
6
+
7
+ - 🎨 **Colorized Terminal Output**: Beautifully structured logs with ANSI colors based on HTTP method, response time, and status codes.
8
+ - 🔒 **Auto-Redaction**: Automatically redacts sensitive fields from request bodies (e.g., `password`, `token`, `secret`, `apiKey`, `authorization`).
9
+ - ⚡ **Precision Timing**: High-resolution response timers formatted with appropriate units (e.g., microseconds `μs`, milliseconds `ms`, or seconds `s`).
10
+ - ⚙️ **Customizable Log Content**: Optionally include or skip request body, query parameters, or HTTP headers.
11
+ - 🛠️ **Custom Loggers**: Easily hook into your log stream (e.g., to send structured logs to Datadog, Logstash, or Sentry).
12
+ - 🐛 **Elegant Error Logging**: Standardized middleware to print clean error stack traces in development.
13
+ - 📦 **Zero-Configuration Bundling**: Pre-packaged as both ES Module (ESM) and CommonJS (CJS) with full TypeScript definitions.
14
+
15
+ ---
16
+
17
+ ## Installation
18
+
19
+ Install via your preferred package manager:
20
+
21
+ ```bash
22
+ # Using npm
23
+ npm install elegant-logs
24
+
25
+ # Using pnpm
26
+ pnpm add elegant-logs
27
+
28
+ # Using yarn
29
+ yarn add elegant-logs
30
+ ```
31
+
32
+ *Note: Since `elegant-logs` is designed specifically for Express apps, make sure you have `express` installed in your project.*
33
+
34
+ ---
35
+
36
+ ## Getting Started
37
+
38
+ ### 1. Request Logger Middleware
39
+
40
+ Import and use the middleware in your Express application:
41
+
42
+ ```typescript
43
+ import express from 'express';
44
+ import { loggerMiddleware } from 'elegant-logs';
45
+
46
+ const app = express();
47
+
48
+ app.use(express.json());
49
+
50
+ // Apply logger middleware
51
+ app.use(loggerMiddleware({
52
+ includeBody: true, // Log request body (defaults to true)
53
+ includeQuery: true, // Log query parameters (defaults to true)
54
+ includeHeaders: false // Log headers (defaults to false)
55
+ }));
56
+
57
+ app.get('/api/users', (req, res) => {
58
+ res.json({ ok: true });
59
+ });
60
+
61
+ app.listen(3000, () => {
62
+ console.log('Server is running on http://localhost:3000');
63
+ });
64
+ ```
65
+
66
+ ### 2. Error Logger Middleware
67
+
68
+ Add the error logger middleware **after** all of your application routes:
69
+
70
+ ```typescript
71
+ import { errorLoggerMiddleware } from 'elegant-logs';
72
+
73
+ // ... your routes here ...
74
+
75
+ // Apply error logger
76
+ app.use(errorLoggerMiddleware);
77
+ ```
78
+
79
+ ---
80
+
81
+ ## Options
82
+
83
+ `loggerMiddleware` accepts an optional configuration object of type `LoggerOptions`:
84
+
85
+ | Option | Type | Default | Description |
86
+ | :--- | :--- | :--- | :--- |
87
+ | `skip` | `(req, res) => boolean` | `undefined` | A function to determine if a specific request should skip logging. |
88
+ | `includeBody` | `boolean` | `true` | When true, logs the JSON request body (redacting sensitive fields). |
89
+ | `includeQuery` | `boolean` | `true` | When true, logs the request query parameters. |
90
+ | `includeHeaders` | `boolean` | `false` | When true, logs the request headers. |
91
+ | `customLogger` | `(logData: LogData) => void` | `undefined` | A custom function to handle raw structured log objects (disables default console printing). |
92
+
93
+ ### Custom Logger Example
94
+
95
+ If you want to send logs to an external service or a filesytem logger:
96
+
97
+ ```typescript
98
+ app.use(loggerMiddleware({
99
+ customLogger: (logData) => {
100
+ // Send structured data to external metrics/log store
101
+ myTelemetryClient.send(logData);
102
+ }
103
+ }));
104
+ ```
105
+
106
+ ### Log Data Schema
107
+
108
+ When using `customLogger`, your function receives a `LogData` object with the following schema:
109
+
110
+ ```typescript
111
+ interface LogData {
112
+ timestamp: string; // ISO format string (YYYY-MM-DD HH:mm:ss)
113
+ method: string; // HTTP Method (GET, POST, etc.)
114
+ url: string; // The request URL path
115
+ statusCode: number; // The response status code
116
+ responseTime: number; // Response duration in milliseconds
117
+ clientIP: string; // Client IP address (considers X-Forwarded-For)
118
+ userAgent?: string; // The browser or client user agent header
119
+ body?: unknown; // The request body (sanitized)
120
+ query?: unknown; // The request query params
121
+ headers?: unknown; // The request headers
122
+ }
123
+ ```
124
+
125
+ ---
126
+
127
+ ## License
128
+
129
+ ISC License (see [LICENSE](LICENSE) or package details).
@@ -0,0 +1,33 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+
3
+ interface LoggerOptions {
4
+ skip?: (req: Request, res: Response) => boolean;
5
+ includeBody?: boolean;
6
+ includeQuery?: boolean;
7
+ includeHeaders?: boolean;
8
+ customLogger?: (logData: LogData) => void;
9
+ }
10
+ interface LogData {
11
+ timestamp: string;
12
+ method: string;
13
+ url: string;
14
+ statusCode: number;
15
+ responseTime: number;
16
+ clientIP: string;
17
+ userAgent?: string;
18
+ body?: unknown;
19
+ query?: unknown;
20
+ headers?: unknown;
21
+ }
22
+ /**
23
+ * Professional Express logger middleware
24
+ * Logs HTTP requests with colors, timing, and structured data
25
+ */
26
+ declare const loggerMiddleware: (options?: LoggerOptions) => (req: Request, res: Response, next: NextFunction) => void;
27
+ /**
28
+ * Simple error logger middleware
29
+ * Should be used after all routes
30
+ */
31
+ declare const errorLoggerMiddleware: (err: Error, req: Request, res: Response, next: NextFunction) => void;
32
+
33
+ export { type LogData, type LoggerOptions, loggerMiddleware as default, errorLoggerMiddleware, loggerMiddleware };
@@ -0,0 +1,33 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+
3
+ interface LoggerOptions {
4
+ skip?: (req: Request, res: Response) => boolean;
5
+ includeBody?: boolean;
6
+ includeQuery?: boolean;
7
+ includeHeaders?: boolean;
8
+ customLogger?: (logData: LogData) => void;
9
+ }
10
+ interface LogData {
11
+ timestamp: string;
12
+ method: string;
13
+ url: string;
14
+ statusCode: number;
15
+ responseTime: number;
16
+ clientIP: string;
17
+ userAgent?: string;
18
+ body?: unknown;
19
+ query?: unknown;
20
+ headers?: unknown;
21
+ }
22
+ /**
23
+ * Professional Express logger middleware
24
+ * Logs HTTP requests with colors, timing, and structured data
25
+ */
26
+ declare const loggerMiddleware: (options?: LoggerOptions) => (req: Request, res: Response, next: NextFunction) => void;
27
+ /**
28
+ * Simple error logger middleware
29
+ * Should be used after all routes
30
+ */
31
+ declare const errorLoggerMiddleware: (err: Error, req: Request, res: Response, next: NextFunction) => void;
32
+
33
+ export { type LogData, type LoggerOptions, loggerMiddleware as default, errorLoggerMiddleware, loggerMiddleware };
package/dist/index.js ADDED
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ default: () => index_default,
24
+ errorLoggerMiddleware: () => errorLoggerMiddleware,
25
+ loggerMiddleware: () => loggerMiddleware
26
+ });
27
+ module.exports = __toCommonJS(index_exports);
28
+ var colors = {
29
+ reset: "\x1B[0m",
30
+ bright: "\x1B[1m",
31
+ dim: "\x1B[2m",
32
+ // Text colors
33
+ red: "\x1B[31m",
34
+ green: "\x1B[32m",
35
+ yellow: "\x1B[33m",
36
+ blue: "\x1B[34m",
37
+ magenta: "\x1B[35m",
38
+ cyan: "\x1B[36m",
39
+ white: "\x1B[37m",
40
+ gray: "\x1B[90m",
41
+ // Background colors
42
+ bgRed: "\x1B[41m",
43
+ bgGreen: "\x1B[42m",
44
+ bgYellow: "\x1B[43m",
45
+ bgBlue: "\x1B[44m",
46
+ bgMagenta: "\x1B[45m",
47
+ bgCyan: "\x1B[46m"
48
+ };
49
+ var methodColors = {
50
+ GET: colors.green,
51
+ POST: colors.blue,
52
+ PUT: colors.yellow,
53
+ PATCH: colors.magenta,
54
+ DELETE: colors.red,
55
+ OPTIONS: colors.cyan,
56
+ HEAD: colors.gray
57
+ };
58
+ var getStatusColor = (statusCode) => {
59
+ if (statusCode >= 500) return colors.red;
60
+ if (statusCode >= 400) return colors.yellow;
61
+ if (statusCode >= 300) return colors.cyan;
62
+ if (statusCode >= 200) return colors.green;
63
+ return colors.white;
64
+ };
65
+ var formatResponseTime = (ms) => {
66
+ if (ms < 1) return `${(ms * 1e3).toFixed(0)}\u03BCs`;
67
+ if (ms < 1e3) return `${ms.toFixed(0)}ms`;
68
+ return `${(ms / 1e3).toFixed(2)}s`;
69
+ };
70
+ var getTimestamp = () => {
71
+ const now = /* @__PURE__ */ new Date();
72
+ return now.toISOString().replace("T", " ").substring(0, 19);
73
+ };
74
+ var getClientIP = (req) => {
75
+ const forwarded = req.headers["x-forwarded-for"];
76
+ if (typeof forwarded === "string") {
77
+ return forwarded.split(",")[0].trim();
78
+ }
79
+ return req.socket.remoteAddress || "unknown";
80
+ };
81
+ var truncate = (str, maxLength = 100) => {
82
+ if (str.length <= maxLength) return str;
83
+ return str.substring(0, maxLength) + "...";
84
+ };
85
+ var formatBody = (body) => {
86
+ if (!body || typeof body !== "object") return "";
87
+ const bodyObj = body;
88
+ if (Object.keys(bodyObj).length === 0) return "";
89
+ const sanitized = { ...bodyObj };
90
+ const sensitiveFields = [
91
+ "password",
92
+ "token",
93
+ "secret",
94
+ "apiKey",
95
+ "authorization"
96
+ ];
97
+ for (const field of sensitiveFields) {
98
+ if (sanitized[field]) {
99
+ sanitized[field] = "[REDACTED]";
100
+ }
101
+ }
102
+ try {
103
+ return truncate(JSON.stringify(sanitized), 200);
104
+ } catch {
105
+ return "[Unable to stringify body]";
106
+ }
107
+ };
108
+ var loggerMiddleware = (options = {}) => {
109
+ const {
110
+ skip,
111
+ includeBody = true,
112
+ includeQuery = true,
113
+ includeHeaders = false,
114
+ customLogger
115
+ } = options;
116
+ return (req, res, next) => {
117
+ const startTime = process.hrtime.bigint();
118
+ const originalEnd = res.end.bind(res);
119
+ res.end = function(chunk, encodingOrCb, cb) {
120
+ const endTime = process.hrtime.bigint();
121
+ const responseTimeNs = Number(endTime - startTime);
122
+ const responseTimeMs = responseTimeNs / 1e6;
123
+ if (skip && skip(req, res)) {
124
+ return originalEnd(chunk, encodingOrCb, cb);
125
+ }
126
+ const logData = {
127
+ timestamp: getTimestamp(),
128
+ method: req.method,
129
+ url: req.originalUrl || req.url,
130
+ statusCode: res.statusCode,
131
+ responseTime: responseTimeMs,
132
+ clientIP: getClientIP(req),
133
+ userAgent: req.headers["user-agent"]
134
+ };
135
+ if (includeBody && req.body && Object.keys(req.body).length > 0) {
136
+ logData.body = req.body;
137
+ }
138
+ if (includeQuery && req.query && Object.keys(req.query).length > 0) {
139
+ logData.query = req.query;
140
+ }
141
+ if (includeHeaders) {
142
+ logData.headers = req.headers;
143
+ }
144
+ if (customLogger) {
145
+ customLogger(logData);
146
+ } else {
147
+ const methodColor = methodColors[req.method] || colors.white;
148
+ const statusColor = getStatusColor(res.statusCode);
149
+ const timeFormatted = formatResponseTime(responseTimeMs);
150
+ const logParts = [
151
+ `${colors.gray}[${logData.timestamp}]${colors.reset}`,
152
+ `${methodColor}${colors.bright}${req.method.padEnd(7)}${colors.reset}`,
153
+ `${colors.white}${logData.url.padEnd(40)}${colors.reset}`,
154
+ `${statusColor}${colors.bright}${res.statusCode}${colors.reset}`,
155
+ `${colors.dim}${timeFormatted.padEnd(10)}${colors.reset}`,
156
+ `${colors.gray}${logData.clientIP}${colors.reset}`
157
+ ];
158
+ console.log(logParts.join(" \u2502 "));
159
+ if (includeBody && logData.body) {
160
+ console.log(
161
+ `${colors.gray} \u2514\u2500 Body: ${formatBody(logData.body)}${colors.reset}`
162
+ );
163
+ }
164
+ if (includeQuery && logData.query) {
165
+ console.log(
166
+ `${colors.gray} \u2514\u2500 Query: ${JSON.stringify(logData.query)}${colors.reset}`
167
+ );
168
+ }
169
+ }
170
+ return originalEnd(chunk, encodingOrCb, cb);
171
+ };
172
+ next();
173
+ };
174
+ };
175
+ var errorLoggerMiddleware = (err, req, res, next) => {
176
+ const timestamp = getTimestamp();
177
+ console.error(
178
+ `${colors.bgRed}${colors.white}${colors.bright} ERROR ${colors.reset}`,
179
+ `${colors.gray}[${timestamp}]${colors.reset}`,
180
+ `${colors.red}${req.method} ${req.url}${colors.reset}`
181
+ );
182
+ console.error(`${colors.red} \u2514\u2500 ${err.message}${colors.reset}`);
183
+ if (process.env.NODE_ENV !== "production") {
184
+ console.error(`${colors.dim}${err.stack}${colors.reset}`);
185
+ }
186
+ next(err);
187
+ };
188
+ var index_default = loggerMiddleware;
189
+ // Annotate the CommonJS export names for ESM import in node:
190
+ 0 && (module.exports = {
191
+ errorLoggerMiddleware,
192
+ loggerMiddleware
193
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,167 @@
1
+ // index.ts
2
+ var colors = {
3
+ reset: "\x1B[0m",
4
+ bright: "\x1B[1m",
5
+ dim: "\x1B[2m",
6
+ // Text colors
7
+ red: "\x1B[31m",
8
+ green: "\x1B[32m",
9
+ yellow: "\x1B[33m",
10
+ blue: "\x1B[34m",
11
+ magenta: "\x1B[35m",
12
+ cyan: "\x1B[36m",
13
+ white: "\x1B[37m",
14
+ gray: "\x1B[90m",
15
+ // Background colors
16
+ bgRed: "\x1B[41m",
17
+ bgGreen: "\x1B[42m",
18
+ bgYellow: "\x1B[43m",
19
+ bgBlue: "\x1B[44m",
20
+ bgMagenta: "\x1B[45m",
21
+ bgCyan: "\x1B[46m"
22
+ };
23
+ var methodColors = {
24
+ GET: colors.green,
25
+ POST: colors.blue,
26
+ PUT: colors.yellow,
27
+ PATCH: colors.magenta,
28
+ DELETE: colors.red,
29
+ OPTIONS: colors.cyan,
30
+ HEAD: colors.gray
31
+ };
32
+ var getStatusColor = (statusCode) => {
33
+ if (statusCode >= 500) return colors.red;
34
+ if (statusCode >= 400) return colors.yellow;
35
+ if (statusCode >= 300) return colors.cyan;
36
+ if (statusCode >= 200) return colors.green;
37
+ return colors.white;
38
+ };
39
+ var formatResponseTime = (ms) => {
40
+ if (ms < 1) return `${(ms * 1e3).toFixed(0)}\u03BCs`;
41
+ if (ms < 1e3) return `${ms.toFixed(0)}ms`;
42
+ return `${(ms / 1e3).toFixed(2)}s`;
43
+ };
44
+ var getTimestamp = () => {
45
+ const now = /* @__PURE__ */ new Date();
46
+ return now.toISOString().replace("T", " ").substring(0, 19);
47
+ };
48
+ var getClientIP = (req) => {
49
+ const forwarded = req.headers["x-forwarded-for"];
50
+ if (typeof forwarded === "string") {
51
+ return forwarded.split(",")[0].trim();
52
+ }
53
+ return req.socket.remoteAddress || "unknown";
54
+ };
55
+ var truncate = (str, maxLength = 100) => {
56
+ if (str.length <= maxLength) return str;
57
+ return str.substring(0, maxLength) + "...";
58
+ };
59
+ var formatBody = (body) => {
60
+ if (!body || typeof body !== "object") return "";
61
+ const bodyObj = body;
62
+ if (Object.keys(bodyObj).length === 0) return "";
63
+ const sanitized = { ...bodyObj };
64
+ const sensitiveFields = [
65
+ "password",
66
+ "token",
67
+ "secret",
68
+ "apiKey",
69
+ "authorization"
70
+ ];
71
+ for (const field of sensitiveFields) {
72
+ if (sanitized[field]) {
73
+ sanitized[field] = "[REDACTED]";
74
+ }
75
+ }
76
+ try {
77
+ return truncate(JSON.stringify(sanitized), 200);
78
+ } catch {
79
+ return "[Unable to stringify body]";
80
+ }
81
+ };
82
+ var loggerMiddleware = (options = {}) => {
83
+ const {
84
+ skip,
85
+ includeBody = true,
86
+ includeQuery = true,
87
+ includeHeaders = false,
88
+ customLogger
89
+ } = options;
90
+ return (req, res, next) => {
91
+ const startTime = process.hrtime.bigint();
92
+ const originalEnd = res.end.bind(res);
93
+ res.end = function(chunk, encodingOrCb, cb) {
94
+ const endTime = process.hrtime.bigint();
95
+ const responseTimeNs = Number(endTime - startTime);
96
+ const responseTimeMs = responseTimeNs / 1e6;
97
+ if (skip && skip(req, res)) {
98
+ return originalEnd(chunk, encodingOrCb, cb);
99
+ }
100
+ const logData = {
101
+ timestamp: getTimestamp(),
102
+ method: req.method,
103
+ url: req.originalUrl || req.url,
104
+ statusCode: res.statusCode,
105
+ responseTime: responseTimeMs,
106
+ clientIP: getClientIP(req),
107
+ userAgent: req.headers["user-agent"]
108
+ };
109
+ if (includeBody && req.body && Object.keys(req.body).length > 0) {
110
+ logData.body = req.body;
111
+ }
112
+ if (includeQuery && req.query && Object.keys(req.query).length > 0) {
113
+ logData.query = req.query;
114
+ }
115
+ if (includeHeaders) {
116
+ logData.headers = req.headers;
117
+ }
118
+ if (customLogger) {
119
+ customLogger(logData);
120
+ } else {
121
+ const methodColor = methodColors[req.method] || colors.white;
122
+ const statusColor = getStatusColor(res.statusCode);
123
+ const timeFormatted = formatResponseTime(responseTimeMs);
124
+ const logParts = [
125
+ `${colors.gray}[${logData.timestamp}]${colors.reset}`,
126
+ `${methodColor}${colors.bright}${req.method.padEnd(7)}${colors.reset}`,
127
+ `${colors.white}${logData.url.padEnd(40)}${colors.reset}`,
128
+ `${statusColor}${colors.bright}${res.statusCode}${colors.reset}`,
129
+ `${colors.dim}${timeFormatted.padEnd(10)}${colors.reset}`,
130
+ `${colors.gray}${logData.clientIP}${colors.reset}`
131
+ ];
132
+ console.log(logParts.join(" \u2502 "));
133
+ if (includeBody && logData.body) {
134
+ console.log(
135
+ `${colors.gray} \u2514\u2500 Body: ${formatBody(logData.body)}${colors.reset}`
136
+ );
137
+ }
138
+ if (includeQuery && logData.query) {
139
+ console.log(
140
+ `${colors.gray} \u2514\u2500 Query: ${JSON.stringify(logData.query)}${colors.reset}`
141
+ );
142
+ }
143
+ }
144
+ return originalEnd(chunk, encodingOrCb, cb);
145
+ };
146
+ next();
147
+ };
148
+ };
149
+ var errorLoggerMiddleware = (err, req, res, next) => {
150
+ const timestamp = getTimestamp();
151
+ console.error(
152
+ `${colors.bgRed}${colors.white}${colors.bright} ERROR ${colors.reset}`,
153
+ `${colors.gray}[${timestamp}]${colors.reset}`,
154
+ `${colors.red}${req.method} ${req.url}${colors.reset}`
155
+ );
156
+ console.error(`${colors.red} \u2514\u2500 ${err.message}${colors.reset}`);
157
+ if (process.env.NODE_ENV !== "production") {
158
+ console.error(`${colors.dim}${err.stack}${colors.reset}`);
159
+ }
160
+ next(err);
161
+ };
162
+ var index_default = loggerMiddleware;
163
+ export {
164
+ index_default as default,
165
+ errorLoggerMiddleware,
166
+ loggerMiddleware
167
+ };
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "elegant-logger",
3
+ "version": "1.0.1",
4
+ "description": "A professional, beautiful, and highly customizable Express request and error logger middleware for Node.js services.",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "keywords": [
19
+ "express",
20
+ "logger",
21
+ "middleware",
22
+ "typescript",
23
+ "ansi-colors",
24
+ "request-logger"
25
+ ],
26
+ "author": "",
27
+ "license": "ISC",
28
+ "devDependencies": {
29
+ "@types/express": "^5.0.6",
30
+ "express": "^5.2.1",
31
+ "tsup": "^8.5.1",
32
+ "typescript": "^6.0.3"
33
+ },
34
+ "peerDependencies": {
35
+ "express": "^4.0.0 || ^5.0.0"
36
+ },
37
+ "scripts": {
38
+ "build": "tsup index.ts --format cjs,esm --dts --clean",
39
+ "test": "echo \"Error: no test specified\" && exit 1"
40
+ }
41
+ }