barehttp 2.1.0 → 2.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/README.md +18 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.js +1 -1
- package/lib/logger/index.d.ts +18 -0
- package/lib/logger/index.js +134 -11
- package/lib/server.d.ts +5 -0
- package/lib/server.js +3 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ Full-featured slim webserver for microservices with extremely low overhead and r
|
|
|
16
16
|
## Requirements
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
Node.js >=
|
|
19
|
+
Node.js >= 22
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
## Quick start
|
|
@@ -147,6 +147,23 @@ Default `false`
|
|
|
147
147
|
|
|
148
148
|
Enable request/response logging, format varies from `production` or `development` environments, though to change use e.g. `NODE_ENV=production`
|
|
149
149
|
|
|
150
|
+
#### `logger?` (Object)
|
|
151
|
+
|
|
152
|
+
Configure log outputs for app logs and http request logs.
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
const app = new BareHttp({
|
|
156
|
+
logging: true,
|
|
157
|
+
logger: {
|
|
158
|
+
app: { file: './logs/app.log' },
|
|
159
|
+
http: { file: './logs/http.log' },
|
|
160
|
+
level: 'debug',
|
|
161
|
+
},
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
`app.file` and `http.file` accept a path string or `{ path, sync }`, and `http.file` is used only when `logging: true`. `console` (default `true`) keeps stdout logging, and `pretty` (default `true` outside production) controls colored console output. `level` sets the base level and can be overridden per target with `app.level` or `http.level`. Use `sourceMaps: true` to map log locations back to `.ts` files (requires source maps in your build).
|
|
166
|
+
|
|
150
167
|
#### `ws?` (Boolean)
|
|
151
168
|
|
|
152
169
|
Default `false`
|
package/lib/index.d.ts
CHANGED
|
@@ -2,4 +2,5 @@ export { BareHttp } from './server.js';
|
|
|
2
2
|
export type { BareHttpType } from './server.js';
|
|
3
3
|
export type { BareRequest } from './request.js';
|
|
4
4
|
export { context } from './context/index.js';
|
|
5
|
-
export { logMe } from './logger/index.js';
|
|
5
|
+
export { configureLogger, logMe } from './logger/index.js';
|
|
6
|
+
export type { LoggerConfig } from './logger/index.js';
|
package/lib/index.js
CHANGED
package/lib/logger/index.d.ts
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
|
+
import { type LevelWithSilent } from 'pino';
|
|
1
2
|
import { serializeHttp } from './serializers.js';
|
|
3
|
+
type LoggerFileConfig = {
|
|
4
|
+
path: string;
|
|
5
|
+
sync?: boolean;
|
|
6
|
+
};
|
|
7
|
+
type LoggerTargetConfig = {
|
|
8
|
+
file?: string | LoggerFileConfig;
|
|
9
|
+
level?: LevelWithSilent;
|
|
10
|
+
};
|
|
11
|
+
export type LoggerConfig = {
|
|
12
|
+
console?: boolean;
|
|
13
|
+
pretty?: boolean;
|
|
14
|
+
level?: LevelWithSilent;
|
|
15
|
+
app?: LoggerTargetConfig;
|
|
16
|
+
http?: LoggerTargetConfig;
|
|
17
|
+
sourceMaps?: boolean;
|
|
18
|
+
};
|
|
19
|
+
export declare const configureLogger: (config?: LoggerConfig) => void;
|
|
2
20
|
interface LogMeFn {
|
|
3
21
|
(obj: unknown, ...args: []): void;
|
|
4
22
|
(msg: string, ...args: any[]): void;
|
package/lib/logger/index.js
CHANGED
|
@@ -1,26 +1,149 @@
|
|
|
1
|
-
import pino, { destination } from 'pino';
|
|
1
|
+
import pino, { destination, } from 'pino';
|
|
2
|
+
import { mkdirSync } from 'fs';
|
|
3
|
+
import { dirname } from 'path';
|
|
2
4
|
import { serializeLog, serializeHttp } from './serializers.js';
|
|
3
5
|
import { envs } from '../env.js';
|
|
4
|
-
const
|
|
6
|
+
const defaultPretty = !envs.isProd;
|
|
7
|
+
const defaultFileSync = envs.isProd ? false : true;
|
|
5
8
|
const pinoCommonOptions = {
|
|
6
9
|
timestamp: () => `,"time":"${new Date()[envs.isProd ? 'toISOString' : 'toLocaleTimeString']()}"`,
|
|
7
10
|
formatters: {
|
|
8
11
|
level: (label) => ({ level: label }),
|
|
9
12
|
},
|
|
10
13
|
messageKey: 'message',
|
|
11
|
-
transport: envs.isProd ? undefined : { target: 'pino-pretty', options: { colorize: true } },
|
|
12
14
|
};
|
|
13
|
-
const
|
|
15
|
+
const noop = () => { };
|
|
16
|
+
const noopLogger = {
|
|
17
|
+
trace: noop,
|
|
18
|
+
debug: noop,
|
|
19
|
+
info: noop,
|
|
20
|
+
warn: noop,
|
|
21
|
+
error: noop,
|
|
22
|
+
fatal: noop,
|
|
23
|
+
silent: noop,
|
|
24
|
+
};
|
|
25
|
+
let sourceMapsRegistered = false;
|
|
26
|
+
const enableSourceMaps = (enabled) => {
|
|
27
|
+
if (!enabled || sourceMapsRegistered)
|
|
28
|
+
return;
|
|
29
|
+
sourceMapsRegistered = true;
|
|
30
|
+
void import('source-map-support/register').catch(() => {
|
|
31
|
+
sourceMapsRegistered = false;
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
const normalizeFileConfig = (file) => {
|
|
35
|
+
if (!file)
|
|
36
|
+
return undefined;
|
|
37
|
+
if (typeof file === 'string')
|
|
38
|
+
return { path: file, sync: defaultFileSync };
|
|
39
|
+
return { path: file.path, sync: file.sync ?? defaultFileSync };
|
|
40
|
+
};
|
|
41
|
+
const ensureLogDir = (filePath) => {
|
|
42
|
+
const dir = dirname(filePath);
|
|
43
|
+
if (dir && dir !== '.') {
|
|
44
|
+
mkdirSync(dir, { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const toLoggerLike = (logger) => {
|
|
48
|
+
const call = (method) => (...args) => logger[method](...args);
|
|
49
|
+
return {
|
|
50
|
+
trace: call('trace'),
|
|
51
|
+
debug: call('debug'),
|
|
52
|
+
info: call('info'),
|
|
53
|
+
warn: call('warn'),
|
|
54
|
+
error: call('error'),
|
|
55
|
+
fatal: call('fatal'),
|
|
56
|
+
silent: noop,
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
const buildConsoleLogger = (options, prettyEnabled) => {
|
|
60
|
+
if (prettyEnabled) {
|
|
61
|
+
try {
|
|
62
|
+
const transport = pino.transport({
|
|
63
|
+
targets: [{ target: 'pino-pretty', options: { colorize: true } }],
|
|
64
|
+
});
|
|
65
|
+
return toLoggerLike(pino(options, transport));
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return toLoggerLike(pino(options, destination({ dest: 1, sync: false })));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return toLoggerLike(pino(options, destination({ dest: 1, sync: false })));
|
|
72
|
+
};
|
|
73
|
+
const buildFileLogger = (options, fileConfig) => {
|
|
74
|
+
ensureLogDir(fileConfig.path);
|
|
75
|
+
return toLoggerLike(pino(options, destination({ dest: fileConfig.path, sync: fileConfig.sync ?? defaultFileSync })));
|
|
76
|
+
};
|
|
77
|
+
const combineLoggers = (primary, secondary) => {
|
|
78
|
+
if (!primary && !secondary)
|
|
79
|
+
return noopLogger;
|
|
80
|
+
const first = primary ?? noopLogger;
|
|
81
|
+
const second = secondary ?? noopLogger;
|
|
82
|
+
return {
|
|
83
|
+
trace: (...args) => {
|
|
84
|
+
first.trace(...args);
|
|
85
|
+
second.trace(...args);
|
|
86
|
+
},
|
|
87
|
+
debug: (...args) => {
|
|
88
|
+
first.debug(...args);
|
|
89
|
+
second.debug(...args);
|
|
90
|
+
},
|
|
91
|
+
info: (...args) => {
|
|
92
|
+
first.info(...args);
|
|
93
|
+
second.info(...args);
|
|
94
|
+
},
|
|
95
|
+
warn: (...args) => {
|
|
96
|
+
first.warn(...args);
|
|
97
|
+
second.warn(...args);
|
|
98
|
+
},
|
|
99
|
+
error: (...args) => {
|
|
100
|
+
first.error(...args);
|
|
101
|
+
second.error(...args);
|
|
102
|
+
},
|
|
103
|
+
fatal: (...args) => {
|
|
104
|
+
first.fatal(...args);
|
|
105
|
+
second.fatal(...args);
|
|
106
|
+
},
|
|
107
|
+
silent: noop,
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
const buildLogger = (config, target) => {
|
|
111
|
+
const consoleEnabled = config.console ?? true;
|
|
112
|
+
const prettyEnabled = config.pretty ?? defaultPretty;
|
|
113
|
+
const fileConfig = normalizeFileConfig(target?.file);
|
|
114
|
+
const level = target?.level ?? config.level;
|
|
115
|
+
const options = { ...pinoCommonOptions };
|
|
116
|
+
if (level)
|
|
117
|
+
options.level = level;
|
|
118
|
+
const consoleLogger = consoleEnabled ? buildConsoleLogger(options, prettyEnabled) : undefined;
|
|
119
|
+
const fileLogger = fileConfig ? buildFileLogger(options, fileConfig) : undefined;
|
|
120
|
+
return combineLoggers(consoleLogger, fileLogger);
|
|
121
|
+
};
|
|
122
|
+
let appLogger;
|
|
123
|
+
let httpLogger;
|
|
124
|
+
export const configureLogger = (config = {}) => {
|
|
125
|
+
enableSourceMaps(config.sourceMaps);
|
|
126
|
+
if (config.app || config.http) {
|
|
127
|
+
appLogger = buildLogger(config, config.app);
|
|
128
|
+
httpLogger = buildLogger(config, config.http);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
const shared = buildLogger(config);
|
|
132
|
+
appLogger = shared;
|
|
133
|
+
httpLogger = shared;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
configureLogger();
|
|
14
137
|
export const logHttp = (...params) => {
|
|
15
138
|
const { level, logObject } = serializeHttp(...params);
|
|
16
|
-
|
|
139
|
+
httpLogger[level](logObject);
|
|
17
140
|
};
|
|
18
141
|
// TODO: remove the test condition
|
|
19
142
|
export const logMe = {
|
|
20
|
-
debug: (...args) => !envs.isTest &&
|
|
21
|
-
info: (...args) => !envs.isTest &&
|
|
22
|
-
warn: (...args) => !envs.isTest &&
|
|
23
|
-
error: (...args) => !envs.isTest &&
|
|
24
|
-
fatal: (...args) => !envs.isTest &&
|
|
25
|
-
trace: (...args) => !envs.isTest &&
|
|
143
|
+
debug: (...args) => !envs.isTest && appLogger.debug(serializeLog(...args)),
|
|
144
|
+
info: (...args) => !envs.isTest && appLogger.info(serializeLog(...args)),
|
|
145
|
+
warn: (...args) => !envs.isTest && appLogger.warn(serializeLog(...args)),
|
|
146
|
+
error: (...args) => !envs.isTest && appLogger.error(serializeLog(...args)),
|
|
147
|
+
fatal: (...args) => !envs.isTest && appLogger.fatal(serializeLog(...args)),
|
|
148
|
+
trace: (...args) => !envs.isTest && appLogger.trace(serializeLog(...args)),
|
|
26
149
|
};
|
package/lib/server.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ServerOptions } from 'ws';
|
|
2
2
|
import { Ajv } from 'ajv';
|
|
3
3
|
import { BareRequest, CacheOpts } from './request.js';
|
|
4
|
+
import type { LoggerConfig } from './logger/index.js';
|
|
4
5
|
import { CookiesManagerOptions } from './middlewares/cookies/cookie-manager.js';
|
|
5
6
|
import { HttpMethodsUnion, StatusCodesUnion } from './utils/index.js';
|
|
6
7
|
import { CorsOptions } from './middlewares/cors/cors.js';
|
|
@@ -62,6 +63,10 @@ type BareOptions<A extends IP> = {
|
|
|
62
63
|
* Default `false`
|
|
63
64
|
*/
|
|
64
65
|
logging?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Logger configuration. Controls outputs for app and http logs.
|
|
68
|
+
*/
|
|
69
|
+
logger?: LoggerConfig;
|
|
65
70
|
errorHandlerMiddleware?: ErrorHandler;
|
|
66
71
|
/**
|
|
67
72
|
* Request time format in `seconds` or `milliseconds`
|
package/lib/server.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Router from 'find-my-way';
|
|
2
2
|
import { Ajv } from 'ajv';
|
|
3
3
|
import { BareRequest } from './request.js';
|
|
4
|
-
import { logMe } from './logger/index.js';
|
|
4
|
+
import { configureLogger, logMe } from './logger/index.js';
|
|
5
5
|
import { context, enableContext, newContext } from './context/index.js';
|
|
6
6
|
import { HttpMethods, } from './utils/index.js';
|
|
7
7
|
import { Cors } from './middlewares/cors/cors.js';
|
|
@@ -75,6 +75,8 @@ export class BareServer {
|
|
|
75
75
|
};
|
|
76
76
|
applyLaunchOptions = () => {
|
|
77
77
|
const { bareOptions: bo } = this;
|
|
78
|
+
if (bo.logger)
|
|
79
|
+
configureLogger(bo.logger);
|
|
78
80
|
if (bo.setRandomPort) {
|
|
79
81
|
this.#port = undefined;
|
|
80
82
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "barehttp",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Lightweight and fast Node.js web server",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"lodash": "^4.17.21",
|
|
54
54
|
"pino": "^10.1.0",
|
|
55
55
|
"pino-pretty": "^13.1.3",
|
|
56
|
+
"source-map-support": "^0.5.21",
|
|
56
57
|
"ts-morph": "^27.0.2",
|
|
57
58
|
"ws": "^8.18.3"
|
|
58
59
|
},
|