zario 0.2.6 → 0.2.9
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 +190 -161
- package/README.npm.md +190 -161
- package/dist/core/Logger.d.ts +4 -2
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -3
- package/dist/index.mjs +3 -3
- package/dist/transports/FileTransport.d.ts +16 -0
- package/dist/transports/HttpTransport.d.ts +24 -0
- package/dist/transports/index.d.ts +25 -0
- package/package.json +9 -4
package/README.md
CHANGED
|
@@ -1,161 +1,190 @@
|
|
|
1
|
-
# zario
|
|
2
|
-
|
|
3
|
-
A minimal, fast logging library for Node.js with TypeScript support.
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
|
41
|
-
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
|
46
|
-
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
]
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
logger.
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
1
|
+
# zario
|
|
2
|
+
|
|
3
|
+
A minimal, fast logging library for Node.js with TypeScript support.
|
|
4
|
+
|
|
5
|
+
## UPDATE 2.9
|
|
6
|
+
|
|
7
|
+
- Added HTTP transport support with new HttpTransport class
|
|
8
|
+
- Added log batching functionality for efficient writes
|
|
9
|
+
- Added compression support (.gz for gzip, .zz for deflate) for rotated files
|
|
10
|
+
- Enhanced rotation with maxSize, maxFiles, and configurable compression
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install zario
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
import { Logger, ConsoleTransport } from "zario";
|
|
22
|
+
|
|
23
|
+
const logger = new Logger({
|
|
24
|
+
level: "info",
|
|
25
|
+
colorize: true,
|
|
26
|
+
transports: [new ConsoleTransport()],
|
|
27
|
+
prefix: "[MyApp]",
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Start logging
|
|
31
|
+
logger.info("🚀 Server started on port 3000");
|
|
32
|
+
logger.warn("⚠️ High memory usage detected");
|
|
33
|
+
logger.error("❌ Database connection failed", { code: 500 });
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## API Documentation
|
|
37
|
+
|
|
38
|
+
### Logger Constructor Options
|
|
39
|
+
|
|
40
|
+
| Option | Type | Description |
|
|
41
|
+
| -------------- | -------- | ----------------------- |
|
|
42
|
+
| **level** | `string` | Log level threshold |
|
|
43
|
+
| **json** | `boolean`| Output in JSON format |
|
|
44
|
+
| **timestamp** | `boolean`| Include timestamps |
|
|
45
|
+
| **prefix** | `string` | Prepended label |
|
|
46
|
+
| **transports** | `array` | Where logs are written (with transport-specific options like `path`, `maxSize`, `maxFiles`, `compression`, `batchInterval`, `compressOldFiles` for file transport) |
|
|
47
|
+
| **customLevels** | `object` | Define custom log levels and their priorities |
|
|
48
|
+
| **customColors** | `object` | Assign colors to custom log levels |
|
|
49
|
+
|
|
50
|
+
### Log Levels
|
|
51
|
+
|
|
52
|
+
| Level | Method | Use Case |
|
|
53
|
+
|----------|---------------|----------------------------|
|
|
54
|
+
| 🔍 DEBUG | `logger.debug()` | Detailed debugging info |
|
|
55
|
+
| ✨ INFO | `logger.info()` | General information |
|
|
56
|
+
| ⚠️ WARN | `logger.warn()` | Warning messages |
|
|
57
|
+
| ❌ ERROR | `logger.error()` | Error messages |
|
|
58
|
+
| 🤫 SILENT | `logger.silent()`| Not output to console |
|
|
59
|
+
| 📝 BORING | `logger.boring()`| Lowest priority messages |
|
|
60
|
+
|
|
61
|
+
### Transports
|
|
62
|
+
|
|
63
|
+
#### Console Transport
|
|
64
|
+
```js
|
|
65
|
+
import { Logger, ConsoleTransport } from "zario";
|
|
66
|
+
|
|
67
|
+
const logger = new Logger({
|
|
68
|
+
transports: [
|
|
69
|
+
new ConsoleTransport({ colorize: true })
|
|
70
|
+
]
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
#### File Transport
|
|
75
|
+
```js
|
|
76
|
+
import { Logger, FileTransport } from "zario";
|
|
77
|
+
|
|
78
|
+
const logger = new Logger({
|
|
79
|
+
transports: [
|
|
80
|
+
new FileTransport({
|
|
81
|
+
path: './logs/app.log',
|
|
82
|
+
maxSize: 10485760, // 10MB in bytes
|
|
83
|
+
maxFiles: 5,
|
|
84
|
+
compression: 'gzip', // 'gzip', 'deflate', or 'none' (default: 'none')
|
|
85
|
+
batchInterval: 1000, // Batch interval in ms (0 to disable, default: 0)
|
|
86
|
+
compressOldFiles: true // Whether to compress old files during rotation (default: true)
|
|
87
|
+
})
|
|
88
|
+
]
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### HTTP Transport
|
|
93
|
+
```js
|
|
94
|
+
import { Logger, HttpTransport } from "zario";
|
|
95
|
+
|
|
96
|
+
const logger = new Logger({
|
|
97
|
+
transports: [
|
|
98
|
+
new HttpTransport({
|
|
99
|
+
url: 'https://api.example.com/logs',
|
|
100
|
+
method: 'POST',
|
|
101
|
+
headers: {
|
|
102
|
+
'Content-Type': 'application/json',
|
|
103
|
+
'Authorization': 'Bearer your-token-here'
|
|
104
|
+
},
|
|
105
|
+
timeout: 10000, // Request timeout in ms
|
|
106
|
+
retries: 3 // Number of retry attempts
|
|
107
|
+
})
|
|
108
|
+
]
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Methods
|
|
113
|
+
|
|
114
|
+
- `logger.debug(message, metadata?)` - Debug level logging
|
|
115
|
+
- `logger.info(message, metadata?)` - Info level logging
|
|
116
|
+
- `logger.warn(message, metadata?)` - Warning level logging
|
|
117
|
+
- `logger.error(message, metadata?)` - Error level logging
|
|
118
|
+
- `logger.createChild(options)` - Creates a child logger with inherited settings
|
|
119
|
+
- `logger.setLevel(level)` - Change the logger level at runtime
|
|
120
|
+
- `logger.setFormat(format)` - Set the output format to text or json
|
|
121
|
+
|
|
122
|
+
## Usage Examples
|
|
123
|
+
|
|
124
|
+
### Basic Usage
|
|
125
|
+
```js
|
|
126
|
+
import { Logger, ConsoleTransport } from "zario";
|
|
127
|
+
|
|
128
|
+
const logger = new Logger({
|
|
129
|
+
level: "info",
|
|
130
|
+
colorize: true,
|
|
131
|
+
transports: [new ConsoleTransport()]
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
logger.info("Application started");
|
|
135
|
+
logger.error("Something went wrong", { userId: 123 });
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### JSON Format
|
|
139
|
+
```js
|
|
140
|
+
const logger = new Logger({ json: true });
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Custom Levels & Colors
|
|
144
|
+
```js
|
|
145
|
+
import { Logger, ConsoleTransport } from "zario";
|
|
146
|
+
|
|
147
|
+
const logger = new Logger({
|
|
148
|
+
level: 'info',
|
|
149
|
+
customLevels: {
|
|
150
|
+
'success': 6, // Higher priority than error (5).
|
|
151
|
+
'verbose': 1, // Lower priority than debug (2).
|
|
152
|
+
'critical': 7, // Highest priority.
|
|
153
|
+
},
|
|
154
|
+
customColors: {
|
|
155
|
+
'success': 'green',
|
|
156
|
+
'verbose': 'cyan',
|
|
157
|
+
'critical': 'brightRed',
|
|
158
|
+
},
|
|
159
|
+
transports: [
|
|
160
|
+
new ConsoleTransport()
|
|
161
|
+
]
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// Using custom levels.
|
|
165
|
+
logger.logWithLevel('success', 'This is a success message in green!');
|
|
166
|
+
logger.logWithLevel('verbose', 'This is a verbose message in cyan');
|
|
167
|
+
logger.logWithLevel('critical', 'This is a critical message in bright red');
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Child Loggers
|
|
171
|
+
```js
|
|
172
|
+
const main = new Logger({ prefix: "[APP]" });
|
|
173
|
+
const db = main.createChild({ prefix: "[DB]" });
|
|
174
|
+
|
|
175
|
+
main.info("App initialized");
|
|
176
|
+
db.error("Connection timeout");
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Multiple Transports
|
|
180
|
+
```js
|
|
181
|
+
import { Logger, ConsoleTransport, FileTransport } from "zario";
|
|
182
|
+
|
|
183
|
+
const logger = new Logger({
|
|
184
|
+
level: 'info',
|
|
185
|
+
transports: [
|
|
186
|
+
new ConsoleTransport(),
|
|
187
|
+
new FileTransport({ path: './logs/app.log' })
|
|
188
|
+
]
|
|
189
|
+
});
|
|
190
|
+
```
|
package/README.npm.md
CHANGED
|
@@ -1,161 +1,190 @@
|
|
|
1
|
-
# zario
|
|
2
|
-
|
|
3
|
-
A minimal, fast logging library for Node.js with TypeScript support.
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
|
41
|
-
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
|
46
|
-
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
]
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
logger.
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
1
|
+
# zario
|
|
2
|
+
|
|
3
|
+
A minimal, fast logging library for Node.js with TypeScript support.
|
|
4
|
+
|
|
5
|
+
## UPDATE 2.9
|
|
6
|
+
|
|
7
|
+
- Added HTTP transport support with new HttpTransport class
|
|
8
|
+
- Added log batching functionality for efficient writes
|
|
9
|
+
- Added compression support (.gz for gzip, .zz for deflate) for rotated files
|
|
10
|
+
- Enhanced rotation with maxSize, maxFiles, and configurable compression
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install zario
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
import { Logger, ConsoleTransport } from "zario";
|
|
22
|
+
|
|
23
|
+
const logger = new Logger({
|
|
24
|
+
level: "info",
|
|
25
|
+
colorize: true,
|
|
26
|
+
transports: [new ConsoleTransport()],
|
|
27
|
+
prefix: "[MyApp]",
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Start logging
|
|
31
|
+
logger.info("🚀 Server started on port 3000");
|
|
32
|
+
logger.warn("⚠️ High memory usage detected");
|
|
33
|
+
logger.error("❌ Database connection failed", { code: 500 });
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## API Documentation
|
|
37
|
+
|
|
38
|
+
### Logger Constructor Options
|
|
39
|
+
|
|
40
|
+
| Option | Type | Description |
|
|
41
|
+
| -------------- | -------- | ----------------------- |
|
|
42
|
+
| **level** | `string` | Log level threshold |
|
|
43
|
+
| **json** | `boolean`| Output in JSON format |
|
|
44
|
+
| **timestamp** | `boolean`| Include timestamps |
|
|
45
|
+
| **prefix** | `string` | Prepended label |
|
|
46
|
+
| **transports** | `array` | Where logs are written (with transport-specific options like `path`, `maxSize`, `maxFiles`, `compression`, `batchInterval`, `compressOldFiles` for file transport) |
|
|
47
|
+
| **customLevels** | `object` | Define custom log levels and their priorities |
|
|
48
|
+
| **customColors** | `object` | Assign colors to custom log levels |
|
|
49
|
+
|
|
50
|
+
### Log Levels
|
|
51
|
+
|
|
52
|
+
| Level | Method | Use Case |
|
|
53
|
+
|----------|---------------|----------------------------|
|
|
54
|
+
| 🔍 DEBUG | `logger.debug()` | Detailed debugging info |
|
|
55
|
+
| ✨ INFO | `logger.info()` | General information |
|
|
56
|
+
| ⚠️ WARN | `logger.warn()` | Warning messages |
|
|
57
|
+
| ❌ ERROR | `logger.error()` | Error messages |
|
|
58
|
+
| 🤫 SILENT | `logger.silent()`| Not output to console |
|
|
59
|
+
| 📝 BORING | `logger.boring()`| Lowest priority messages |
|
|
60
|
+
|
|
61
|
+
### Transports
|
|
62
|
+
|
|
63
|
+
#### Console Transport
|
|
64
|
+
```js
|
|
65
|
+
import { Logger, ConsoleTransport } from "zario";
|
|
66
|
+
|
|
67
|
+
const logger = new Logger({
|
|
68
|
+
transports: [
|
|
69
|
+
new ConsoleTransport({ colorize: true })
|
|
70
|
+
]
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
#### File Transport
|
|
75
|
+
```js
|
|
76
|
+
import { Logger, FileTransport } from "zario";
|
|
77
|
+
|
|
78
|
+
const logger = new Logger({
|
|
79
|
+
transports: [
|
|
80
|
+
new FileTransport({
|
|
81
|
+
path: './logs/app.log',
|
|
82
|
+
maxSize: 10485760, // 10MB in bytes
|
|
83
|
+
maxFiles: 5,
|
|
84
|
+
compression: 'gzip', // 'gzip', 'deflate', or 'none' (default: 'none')
|
|
85
|
+
batchInterval: 1000, // Batch interval in ms (0 to disable, default: 0)
|
|
86
|
+
compressOldFiles: true // Whether to compress old files during rotation (default: true)
|
|
87
|
+
})
|
|
88
|
+
]
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### HTTP Transport
|
|
93
|
+
```js
|
|
94
|
+
import { Logger, HttpTransport } from "zario";
|
|
95
|
+
|
|
96
|
+
const logger = new Logger({
|
|
97
|
+
transports: [
|
|
98
|
+
new HttpTransport({
|
|
99
|
+
url: 'https://api.example.com/logs',
|
|
100
|
+
method: 'POST',
|
|
101
|
+
headers: {
|
|
102
|
+
'Content-Type': 'application/json',
|
|
103
|
+
'Authorization': 'Bearer your-token-here'
|
|
104
|
+
},
|
|
105
|
+
timeout: 10000, // Request timeout in ms
|
|
106
|
+
retries: 3 // Number of retry attempts
|
|
107
|
+
})
|
|
108
|
+
]
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Methods
|
|
113
|
+
|
|
114
|
+
- `logger.debug(message, metadata?)` - Debug level logging
|
|
115
|
+
- `logger.info(message, metadata?)` - Info level logging
|
|
116
|
+
- `logger.warn(message, metadata?)` - Warning level logging
|
|
117
|
+
- `logger.error(message, metadata?)` - Error level logging
|
|
118
|
+
- `logger.createChild(options)` - Creates a child logger with inherited settings
|
|
119
|
+
- `logger.setLevel(level)` - Change the logger level at runtime
|
|
120
|
+
- `logger.setFormat(format)` - Set the output format to text or json
|
|
121
|
+
|
|
122
|
+
## Usage Examples
|
|
123
|
+
|
|
124
|
+
### Basic Usage
|
|
125
|
+
```js
|
|
126
|
+
import { Logger, ConsoleTransport } from "zario";
|
|
127
|
+
|
|
128
|
+
const logger = new Logger({
|
|
129
|
+
level: "info",
|
|
130
|
+
colorize: true,
|
|
131
|
+
transports: [new ConsoleTransport()]
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
logger.info("Application started");
|
|
135
|
+
logger.error("Something went wrong", { userId: 123 });
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### JSON Format
|
|
139
|
+
```js
|
|
140
|
+
const logger = new Logger({ json: true });
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Custom Levels & Colors
|
|
144
|
+
```js
|
|
145
|
+
import { Logger, ConsoleTransport } from "zario";
|
|
146
|
+
|
|
147
|
+
const logger = new Logger({
|
|
148
|
+
level: 'info',
|
|
149
|
+
customLevels: {
|
|
150
|
+
'success': 6, // Higher priority than error (5).
|
|
151
|
+
'verbose': 1, // Lower priority than debug (2).
|
|
152
|
+
'critical': 7, // Highest priority.
|
|
153
|
+
},
|
|
154
|
+
customColors: {
|
|
155
|
+
'success': 'green',
|
|
156
|
+
'verbose': 'cyan',
|
|
157
|
+
'critical': 'brightRed',
|
|
158
|
+
},
|
|
159
|
+
transports: [
|
|
160
|
+
new ConsoleTransport()
|
|
161
|
+
]
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// Using custom levels.
|
|
165
|
+
logger.logWithLevel('success', 'This is a success message in green!');
|
|
166
|
+
logger.logWithLevel('verbose', 'This is a verbose message in cyan');
|
|
167
|
+
logger.logWithLevel('critical', 'This is a critical message in bright red');
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Child Loggers
|
|
171
|
+
```js
|
|
172
|
+
const main = new Logger({ prefix: "[APP]" });
|
|
173
|
+
const db = main.createChild({ prefix: "[DB]" });
|
|
174
|
+
|
|
175
|
+
main.info("App initialized");
|
|
176
|
+
db.error("Connection timeout");
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Multiple Transports
|
|
180
|
+
```js
|
|
181
|
+
import { Logger, ConsoleTransport, FileTransport } from "zario";
|
|
182
|
+
|
|
183
|
+
const logger = new Logger({
|
|
184
|
+
level: 'info',
|
|
185
|
+
transports: [
|
|
186
|
+
new ConsoleTransport(),
|
|
187
|
+
new FileTransport({ path: './logs/app.log' })
|
|
188
|
+
]
|
|
189
|
+
});
|
|
190
|
+
```
|
package/dist/core/Logger.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { LogLevel } from "./LogLevel";
|
|
2
2
|
import { Transport } from "../transports";
|
|
3
|
-
import {
|
|
3
|
+
import { TransportConfig } from "../types";
|
|
4
4
|
export interface LoggerOptions {
|
|
5
5
|
level?: LogLevel;
|
|
6
6
|
colorize?: boolean;
|
|
7
7
|
json?: boolean;
|
|
8
|
-
transports?:
|
|
8
|
+
transports?: TransportConfig[];
|
|
9
9
|
timestampFormat?: string;
|
|
10
10
|
prefix?: string;
|
|
11
11
|
timestamp?: boolean;
|
|
@@ -40,6 +40,8 @@ export declare class Logger {
|
|
|
40
40
|
private getDefaultTransports;
|
|
41
41
|
private getDefaultAsyncMode;
|
|
42
42
|
private initTransports;
|
|
43
|
+
private isLegacyTransportOptions;
|
|
44
|
+
private isTransport;
|
|
43
45
|
private shouldLog;
|
|
44
46
|
private getLevelPriority;
|
|
45
47
|
private log;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Logger } from './core/Logger';
|
|
2
2
|
import { LogLevel } from './core/LogLevel';
|
|
3
|
-
import { ConsoleTransport, FileTransport, Transport } from './transports';
|
|
4
|
-
import {
|
|
3
|
+
import { ConsoleTransport, FileTransport, HttpTransport, Transport, consoleT, fileT, httpT } from './transports';
|
|
4
|
+
import { TransportConfig, LoggerConfig } from './types/index';
|
|
5
5
|
import { CustomLogLevelConfig } from './core/CustomLogLevel';
|
|
6
|
-
export { Logger, ConsoleTransport, FileTransport };
|
|
7
|
-
export type { LogLevel, Transport,
|
|
6
|
+
export { Logger, ConsoleTransport, FileTransport, HttpTransport, consoleT, fileT, httpT };
|
|
7
|
+
export type { LogLevel, Transport, TransportConfig, LoggerConfig, CustomLogLevelConfig };
|
|
8
8
|
export default Logger;
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
`;
|
|
3
|
-
`;await new Promise((o,l)=>{n.appendFile(this.filePath,r,p=>{if(p){l(p);return}o()})}),await this.rotateIfNeededAsync()}rotateIfNeeded(){if(n.existsSync(this.filePath))try{n.statSync(this.filePath).size>=this.maxSize&&this.rotateFiles()}catch(t){console.error("Error checking file size for rotation:",t)}}async rotateIfNeededAsync(){if(n.existsSync(this.filePath))try{n.statSync(this.filePath).size>=this.maxSize&&await this.rotateFilesAsync()}catch(t){console.error("Error during rotation check:",t)}}rotateFiles(){try{let t="";n.existsSync(this.filePath)&&(t=n.readFileSync(this.filePath,"utf8"));let e=this.getRotatedFilePath();n.writeFileSync(e,t,"utf8"),n.writeFileSync(this.filePath,"","utf8"),this.cleanupOldFiles()}catch(t){console.error("Error during file rotation:",t)}}async rotateFilesAsync(){try{let t="";n.existsSync(this.filePath)&&(t=await n.promises.readFile(this.filePath,"utf8"));let e=this.getRotatedFilePath();await n.promises.writeFile(e,t,"utf8"),await n.promises.writeFile(this.filePath,"","utf8"),await this.cleanupOldFilesAsync()}catch(t){console.error("Error during async file rotation:",t)}}getRotatedFilePath(){let t=h.dirname(this.filePath),e=h.basename(this.filePath),i=Date.now();return h.join(t,`${e}.${i}`)}cleanupOldFiles(){try{let t=h.dirname(this.filePath),e=h.basename(this.filePath);try{n.accessSync(t,n.constants.F_OK)}catch{return}let r=n.readdirSync(t).filter(o=>!o||o===e?!1:new RegExp(`^${e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\.\\d+$`).test(o)).sort((o,l)=>{let p=parseInt(o.split(".").pop()||"0");return parseInt(l.split(".").pop()||"0")-p});for(let o=this.maxFiles;o<r.length;o++){let l=r[o];if(l){if(l.includes("../")||l.includes("..\\")||l.startsWith(".."))continue;let p=h.join(t,l),m=h.resolve(p),f=h.resolve(t);if(!m.startsWith(f+h.sep)&&m!==f)continue;try{n.unlinkSync(p)}catch(c){console.error(`Failed to delete old log file ${p}:`,c)}}}}catch(t){console.error("Error during cleanup of old files:",t)}}async cleanupOldFilesAsync(){try{let t=h.dirname(this.filePath),e=h.basename(this.filePath);try{await n.promises.access(t,n.constants.F_OK)}catch{return}let r=(await n.promises.readdir(t)).filter(l=>!l||l===e?!1:new RegExp(`^${e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\.\\d+$`).test(l)).sort((l,p)=>{let m=parseInt(l.split(".").pop()||"0");return parseInt(p.split(".").pop()||"0")-m}),o=[];for(let l=this.maxFiles;l<r.length;l++){let p=r[l];if(p){if(p.includes("../")||p.includes("..\\")||p.startsWith(".."))continue;let m=h.join(t,p),f=h.resolve(m),c=h.resolve(t);if(!f.startsWith(c+h.sep)&&f!==c)continue;o.push(n.promises.access(m,n.constants.F_OK).then(()=>n.promises.unlink(m)).catch(s=>{s.code!=="ENOENT"&&console.error(`Failed to delete old log file ${m}:`,s)}))}}await Promise.all(o)}catch(t){console.error("Error during async cleanup of old files:",t)}}};var y=class a{constructor(t={}){this.transports=[];let{level:e,colorize:i,json:r,transports:o=[],timestampFormat:l="YYYY-MM-DD HH:mm:ss",prefix:p,timestamp:m,context:f={},parent:c,asyncMode:s,customLevels:g={},customColors:T={}}=t;if(this.parent=c,this.context={...f},this.customLevels=g,this.asyncMode=!1,this.parent){this.level=e??this.parent.level,this.prefix=p??this.parent.prefix,this.timestamp=m??this.parent.timestamp,this.asyncMode=s??this.parent.asyncMode,this.transports=o&&o.length>0?this.initTransports(o,this.getDefaultColorizeValue(i)):this.parent.transports;let u={...this.parent.formatter.getCustomColors(),...T};this.formatter=new b({colorize:this.getDefaultColorizeValue(i)??this.parent.formatter.isColorized(),json:r??this.parent.formatter.isJson(),timestampFormat:l??this.parent.formatter.getTimestampFormat(),timestamp:m??this.parent.formatter.hasTimestamp(),customColors:u}),this.context={...this.parent.context,...this.context},this.customLevels={...this.parent.customLevels,...g}}else{let u=this.isProductionEnvironment();this.level=e??this.getDefaultLevel(u),this.prefix=p??"",this.timestamp=m??this.getDefaultTimestamp(u);let R=o&&o.length>0?o:this.getDefaultTransports(u);this.asyncMode=s??this.getDefaultAsyncMode(u),this.transports=this.initTransports(R,this.getDefaultColorizeValue(i)),this.formatter=new b({colorize:this.getDefaultColorizeValue(i),json:r??this.getDefaultJson(u),timestampFormat:l,timestamp:this.getDefaultTimestamp(u),customColors:T})}a._global||(a._global=this)}static{this.LEVEL_PRIORITIES={silent:0,boring:1,debug:2,info:3,warn:4,error:5}}isProductionEnvironment(){let t=process.env.NODE_ENV?.toLowerCase();return t==="production"||t==="prod"}getDefaultLevel(t){return t?"warn":"debug"}getDefaultColorizeValue(t){return t!==void 0?t:!this.isProductionEnvironment()}getDefaultJson(t){return t}getDefaultTimestamp(t){return!0}getDefaultTransports(t){return t?[{type:"console"},{type:"file",options:{path:"./logs/app.log"}}]:[{type:"console"}]}getDefaultAsyncMode(t){return t}initTransports(t,e){let i=[];for(let r of t)if(r.type==="console"){let o=new d({colorize:r.options?.colorize??e});i.push(o)}else if(r.type==="file"){if(r.options?.path){let o={path:r.options.path};r.options.maxSize!==void 0&&(o.maxSize=r.options.maxSize),r.options.maxFiles!==void 0&&(o.maxFiles=r.options.maxFiles);let l=new v(o);i.push(l)}}else r.type==="custom"&&r.instance&&i.push(r.instance);return i}shouldLog(t){let e=this.getLevelPriority(this.level);return this.getLevelPriority(t)>=e}getLevelPriority(t){if(a.LEVEL_PRIORITIES.hasOwnProperty(t))return a.LEVEL_PRIORITIES[t];if(this.customLevels&&t in this.customLevels){let e=this.customLevels[t];return e!==void 0?e:999}return 999}log(t,e,i){if(this.shouldLog(t)&&t!=="silent")if(this.asyncMode)this.logAsyncDirect(t,e,i);else{let r=new Date,o;this.context&&Object.keys(this.context).length>0?i?o={...this.context,...i}:o=this.context:i&&(o=i);let l={level:t,message:e,timestamp:r,metadata:o&&Object.keys(o).length>0?o:void 0,prefix:this.prefix};for(let p of this.transports)p.write(l,this.formatter)}}logAsyncDirect(t,e,i){if(!this.shouldLog(t)||t==="silent")return;let r=new Date,o;this.context&&Object.keys(this.context).length>0?i?o={...this.context,...i}:o=this.context:i&&(o=i);let l={level:t,message:e,timestamp:r,metadata:o&&Object.keys(o).length>0?o:void 0,prefix:this.prefix};for(let p of this.transports)p.writeAsync?p.writeAsync(l,this.formatter).catch(m=>{console.error("Error during async logging:",m)}):setImmediate(()=>{p.write(l,this.formatter)})}debug(t,e){this.log("debug",t,e)}info(t,e){this.log("info",t,e)}warn(t,e){this.log("warn",t,e)}error(t,e){this.log("error",t,e)}silent(t,e){this.log("silent",t,e)}boring(t,e){this.log("boring",t,e)}logWithLevel(t,e,i){this.log(t,e,i)}setLevel(t){this.level=t}setFormat(t){this.formatter.setJson(t==="json")}setAsyncMode(t){this.asyncMode=t}addTransport(t){this.transports.push(t)}getTimestampSetting(){return this.timestamp}static get global(){return a._global||(a._global=new a),a._global}createChild(t={}){return new a({...t,parent:this})}startTimer(t){let{Timer:e}=(z(),w(C));return new e(t,i=>this.info(i))}};var N=y;0&&(module.exports={ConsoleTransport,FileTransport,Logger});
|
|
1
|
+
"use strict";var N=Object.create;var F=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var Y=Object.getOwnPropertyNames;var B=Object.getPrototypeOf,q=Object.prototype.hasOwnProperty;var J=(a,t)=>()=>(a&&(t=a(a=0)),t);var z=(a,t)=>{for(var e in t)F(a,e,{get:t[e],enumerable:!0})},D=(a,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Y(t))!q.call(a,o)&&o!==e&&F(a,o,{get:()=>t[o],enumerable:!(s=k(t,o))||s.enumerable});return a};var y=(a,t,e)=>(e=a!=null?N(B(a)):{},D(t||!a||!a.__esModule?F(e,"default",{value:a,enumerable:!0}):e,a)),R=a=>D(F({},"__esModule",{value:!0}),a);var M={};z(M,{Timer:()=>S});var S,H=J(()=>{"use strict";S=class{constructor(t,e){this.hasEnded=!1;this.name=t,this.logFn=e,this.startTime=Date.now()}end(){if(this.hasEnded)return;let e=Date.now()-this.startTime;this.logFn(`${this.name} took ${e}ms`),this.hasEnded=!0}}});var K={};z(K,{ConsoleTransport:()=>f,FileTransport:()=>d,HttpTransport:()=>T,Logger:()=>x,consoleT:()=>E,default:()=>_,fileT:()=>A,httpT:()=>$});module.exports=R(K);var w=class{static format(t,e){if(e==="ISO")return t.toISOString();if(e==="UTC")return t.toUTCString();if(e==="LOCAL")return t.toLocaleString();let s=t.getFullYear(),o=t.getMonth()+1,r=t.getDate(),n=t.getHours(),p=t.getMinutes(),c=t.getSeconds(),u=t.getMilliseconds(),h=[],i=0,g=0;for(;i<e.length;)e[i]==="Y"&&i+3<e.length&&e.slice(i,i+4)==="YYYY"?(h.push(e.substring(g,i)),h.push(s.toString().padStart(4,"0")),i+=4,g=i):e[i]==="M"&&i+1<e.length&&e.slice(i,i+2)==="MM"?(h.push(e.substring(g,i)),h.push(o.toString().padStart(2,"0")),i+=2,g=i):e[i]==="D"&&i+1<e.length&&e.slice(i,i+2)==="DD"?(h.push(e.substring(g,i)),h.push(r.toString().padStart(2,"0")),i+=2,g=i):e[i]==="H"&&i+1<e.length&&e.slice(i,i+2)==="HH"?(h.push(e.substring(g,i)),h.push(n.toString().padStart(2,"0")),i+=2,g=i):e[i]==="m"&&i+1<e.length&&e.slice(i,i+2)==="mm"?(h.push(e.substring(g,i)),h.push(p.toString().padStart(2,"0")),i+=2,g=i):e[i]==="s"&&i+1<e.length&&e.slice(i,i+2)==="ss"?(h.push(e.substring(g,i)),h.push(c.toString().padStart(2,"0")),i+=2,g=i):e[i]==="S"&&i+2<e.length&&e.slice(i,i+3)==="SSS"?(h.push(e.substring(g,i)),h.push(u.toString().padStart(3,"0")),i+=3,g=i):i++;return h.push(e.substring(g)),h.join("")}};var O=class a{static{this.ANSI_COLORS={black:"\x1B[30m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",cyan:"\x1B[36m",white:"\x1B[37m",brightRed:"\x1B[91m",brightGreen:"\x1B[92m",brightYellow:"\x1B[93m",brightBlue:"\x1B[94m",brightMagenta:"\x1B[95m",brightCyan:"\x1B[96m",brightWhite:"\x1B[97m",info:"\x1B[32m",warn:"\x1B[33m",error:"\x1B[31m",debug:"\x1B[36m",boring:"\x1B[37m",reset:"\x1B[0m"}}static colorize(t,e){return process.env.FORCE_COLOR!=="0"&&(process.stdout.isTTY||process.env.FORCE_COLOR==="1")?`${a.ANSI_COLORS[e]||a.ANSI_COLORS.reset}${t}${a.ANSI_COLORS.reset}`:t}};var L=class{constructor(t={}){let{colorize:e=!0,json:s=!1,timestampFormat:o="YYYY-MM-DD HH:mm:ss",timestamp:r=!1,customColors:n={}}=t;this.colorize=e,this.json=s,this.timestampFormat=o,this.timestamp=r,this.customColors=n}format(t){return this.json?this.formatAsJson(t):this.formatAsText(t)}formatAsJson(t){let e={...t.metadata,level:t.level,message:t.message};return this.timestamp&&(e.timestamp=t.timestamp.toISOString()),t.prefix&&(e.prefix=t.prefix),JSON.stringify(e)}formatAsText(t){let e=[];if(this.timestamp){let o=w.format(t.timestamp,this.timestampFormat);e.push(`[${o}] `)}t.prefix&&e.push(`${t.prefix} `);let s=t.level.toUpperCase();if(this.colorize){let o=this.customColors[t.level]||t.level;s=O.colorize(s,o)}return e.push(`[${s}] `),e.push(t.message),t.metadata&&e.push(` ${JSON.stringify(t.metadata)}`),e.join("")}setJson(t){this.json=t}isColorized(){return this.colorize}isJson(){return this.json}getTimestampFormat(){return this.timestampFormat}hasTimestamp(){return this.timestamp}getCustomColors(){return{...this.customColors}}};var f=class{constructor(t={}){let{colorize:e=!0}=t;this.colorize=e}write(t,e){let s=e.colorize;this.colorize!==s&&(e.colorize=this.colorize);let o=e.format(t);switch(this.colorize!==s&&(e.colorize=s),t.level){case"error":console.error(o);break;case"warn":console.warn(o);break;default:console.log(o);break}}async writeAsync(t,e){return setImmediate(()=>{this.write(t,e)}),Promise.resolve()}};var l=y(require("fs"),1),m=y(require("path"),1),b=y(require("zlib"),1),C=require("util"),Q=(0,C.promisify)(b.gzip),V=(0,C.promisify)(b.deflate),d=class{constructor(t){this.batchQueue=[];this.batchTimer=null;let{path:e,maxSize:s=10*1024*1024,maxFiles:o=5,compression:r="none",batchInterval:n=0,compressOldFiles:p=!0}=t;this.filePath=e,this.maxSize=s,this.maxFiles=o,this.compression=r,this.batchInterval=n,this.compressOldFiles=p;let c=m.dirname(this.filePath);l.existsSync(c)||l.mkdirSync(c,{recursive:!0}),l.existsSync(this.filePath)||l.writeFileSync(this.filePath,"","utf8"),n>0&&this.startBatching()}write(t,e){let o=e.format(t)+`
|
|
2
|
+
`;this.batchInterval>0?this.batchQueue.push({data:o,timestamp:new Date}):(l.appendFileSync(this.filePath,o),this.rotateIfNeeded())}async writeAsync(t,e){let o=e.format(t)+`
|
|
3
|
+
`;this.batchInterval>0?this.batchQueue.push({data:o,timestamp:new Date}):(await new Promise((r,n)=>{l.appendFile(this.filePath,o,p=>{if(p){n(p);return}r()})}),await this.rotateIfNeededAsync())}rotateIfNeeded(){if(l.existsSync(this.filePath))try{l.statSync(this.filePath).size>=this.maxSize&&this.rotateFiles()}catch(t){console.error("Error checking file size for rotation:",t)}}async rotateIfNeededAsync(){if(l.existsSync(this.filePath))try{l.statSync(this.filePath).size>=this.maxSize&&await this.rotateFilesAsync()}catch(t){console.error("Error during rotation check:",t)}}rotateFiles(){try{let t="";l.existsSync(this.filePath)&&(t=l.readFileSync(this.filePath,"utf8"));let e=this.getRotatedFilePath();if(this.compression!=="none"&&this.compressOldFiles){e=`${e}.${this.compression==="gzip"?"gz":"zz"}`;let s=this.compression==="gzip"?b.gzipSync(t):b.deflateSync(t);l.writeFileSync(e,s)}else l.writeFileSync(e,t,"utf8");l.writeFileSync(this.filePath,"","utf8"),this.cleanupOldFiles()}catch(t){console.error("Error during file rotation:",t)}}async rotateFilesAsync(){try{let t="";l.existsSync(this.filePath)&&(t=await l.promises.readFile(this.filePath,"utf8"));let e=this.getRotatedFilePath();if(this.compression!=="none"&&this.compressOldFiles){e=`${e}.${this.compression==="gzip"?"gz":"zz"}`;let s=this.compression==="gzip"?await Q(t):await V(t);await l.promises.writeFile(e,s)}else await l.promises.writeFile(e,t,"utf8");await l.promises.writeFile(this.filePath,"","utf8"),await this.cleanupOldFilesAsync()}catch(t){console.error("Error during async file rotation:",t)}}getRotatedFilePath(){let t=m.dirname(this.filePath),e=m.basename(this.filePath),s=Date.now();return m.join(t,`${e}.${s}`)}cleanupOldFiles(){try{let t=m.dirname(this.filePath),e=m.basename(this.filePath);try{l.accessSync(t,l.constants.F_OK)}catch{return}let o=l.readdirSync(t).filter(r=>!r||r===e?!1:new RegExp(`^${e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\.\\d+(\\.gz|\\.zz)?$`).test(r)).sort((r,n)=>{let p=parseInt(r.slice(e.length+1).split(".")[0]||"0");return parseInt(n.slice(e.length+1).split(".")[0]||"0")-p});for(let r=this.maxFiles;r<o.length;r++){let n=o[r];if(n){if(n.includes("../")||n.includes("..\\")||n.startsWith(".."))continue;let p=m.join(t,n),c=m.resolve(p),u=m.resolve(t);if(!c.startsWith(u+m.sep)&&c!==u)continue;try{l.unlinkSync(p)}catch(h){console.error(`Failed to delete old log file ${p}:`,h)}}}}catch(t){console.error("Error during cleanup of old files:",t)}}async cleanupOldFilesAsync(){try{let t=m.dirname(this.filePath),e=m.basename(this.filePath);try{await l.promises.access(t,l.constants.F_OK)}catch{return}let o=(await l.promises.readdir(t)).filter(n=>!n||n===e?!1:new RegExp(`^${e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\.\\d+(\\.gz|\\.zz)?$`).test(n)).sort((n,p)=>{let c=parseInt(n.slice(e.length+1).split(".")[0]||"0");return parseInt(p.slice(e.length+1).split(".")[0]||"0")-c}),r=[];for(let n=this.maxFiles;n<o.length;n++){let p=o[n];if(p){if(p.includes("../")||p.includes("..\\")||p.startsWith(".."))continue;let c=m.join(t,p),u=m.resolve(c),h=m.resolve(t);if(!u.startsWith(h+m.sep)&&u!==h)continue;r.push(l.promises.access(c,l.constants.F_OK).then(()=>l.promises.unlink(c)).catch(i=>{i.code!=="ENOENT"&&console.error(`Failed to delete old log file ${c}:`,i)}))}}await Promise.all(r)}catch(t){console.error("Error during async cleanup of old files:",t)}}startBatching(){this.batchInterval>0&&(this.batchTimer=setInterval(()=>{this.processBatch().catch(t=>{console.error("Error in batch processing timer:",t)})},this.batchInterval))}async processBatch(){if(this.batchQueue.length===0)return;let t=this.batchQueue;this.batchQueue=[];let e=t.map(s=>s.data).join("");try{await new Promise((s,o)=>{l.appendFile(this.filePath,e,r=>{if(r){o(r);return}s()})}),await this.rotateIfNeededAsync()}catch(s){console.error("Error processing log batch:",s),this.batchQueue=[...t,...this.batchQueue]}}async destroy(){if(this.batchTimer&&(clearInterval(this.batchTimer),this.batchTimer=null),this.batchQueue.length>0)try{await this.processBatch()}catch(t){console.error("Error processing final batch:",t)}}};var W=y(require("http"),1),U=y(require("https"),1),I=y(require("url"),1),T=class{constructor(t){let{url:e,method:s="POST",headers:o={},timeout:r=5e3,retries:n=3}=t;if(!e)throw new Error("HttpTransport requires a URL option");this.url=e,this.method=s.toUpperCase(),this.headers={...o},this.timeout=r,this.retries=n,!this.headers["Content-Type"]&&!this.headers["content-type"]&&(this.headers["Content-Type"]="application/json")}write(t,e){let s=this.parseFormattedData(t),o=JSON.stringify(s);setImmediate(()=>{this.sendHttpRequestWithRetry(o,0).catch(r=>{console.error("HttpTransport error (sync mode):",r.message)})})}async writeAsync(t,e){let s=this.parseFormattedData(t),o=JSON.stringify(s);await this.sendHttpRequestWithRetry(o,this.retries)}parseFormattedData(t){return{level:t.level,message:t.message,timestamp:t.timestamp.toISOString(),...t.prefix&&{prefix:t.prefix},...t.metadata&&{metadata:t.metadata}}}async sendHttpRequestWithRetry(t,e){let s=null;for(let o=0;o<=e;o++)try{await this.sendHttpRequest(t);return}catch(r){if(s=r,o===e)break;await this.delay(Math.pow(2,o)*1e3)}if(s)throw s}sendHttpRequest(t){return new Promise((e,s)=>{let o=new I.URL(this.url),n=o.protocol==="https:"?U:W,p={hostname:o.hostname,port:o.port,path:o.pathname+o.search,method:this.method,headers:{...this.headers,"Content-Length":Buffer.byteLength(t,"utf8")},timeout:this.timeout},c=n.request(p,u=>{let h="";u.on("data",i=>{h+=i}),u.on("end",()=>{u.statusCode&&u.statusCode>=200&&u.statusCode<300?e():s(new Error(`HTTP request failed with status ${u.statusCode}: ${h}`))})});c.on("error",u=>{s(u)}),c.on("timeout",()=>{c.destroy(),s(new Error("Request timeout"))}),c.write(t),c.end()})}delay(t){return new Promise(e=>setTimeout(e,t))}};function E(a){return new f(a)}function A(a){return new d(a)}function $(a){return new T(a)}var x=class a{constructor(t={}){this.transports=[];let{level:e,colorize:s,json:o,transports:r=[],timestampFormat:n="YYYY-MM-DD HH:mm:ss",prefix:p,timestamp:c,context:u={},parent:h,asyncMode:i,customLevels:g={},customColors:P={}}=t;if(this.parent=h,this.context={...u},this.customLevels=g,this.asyncMode=!1,this.parent){this.level=e??this.parent.level,this.prefix=p??this.parent.prefix,this.timestamp=c??this.parent.timestamp,this.asyncMode=i??this.parent.asyncMode,this.transports=r&&r.length>0?this.initTransports(r,this.getDefaultColorizeValue(s)):this.parent.transports;let v={...this.parent.formatter.getCustomColors(),...P};this.formatter=new L({colorize:this.getDefaultColorizeValue(s)??this.parent.formatter.isColorized(),json:o??this.parent.formatter.isJson(),timestampFormat:n??this.parent.formatter.getTimestampFormat(),timestamp:c??this.parent.formatter.hasTimestamp(),customColors:v}),this.context={...this.parent.context,...this.context},this.customLevels={...this.parent.customLevels,...g}}else{let v=this.isProductionEnvironment();this.level=e??this.getDefaultLevel(v),this.prefix=p??"",this.timestamp=c??this.getDefaultTimestamp(v);let j=r&&r.length>0?r:this.getDefaultTransports(v);this.asyncMode=i??this.getDefaultAsyncMode(v),this.transports=this.initTransports(j,this.getDefaultColorizeValue(s)),this.formatter=new L({colorize:this.getDefaultColorizeValue(s),json:o??this.getDefaultJson(v),timestampFormat:n,timestamp:this.getDefaultTimestamp(v),customColors:P})}a._global||(a._global=this)}static{this.LEVEL_PRIORITIES={silent:0,boring:1,debug:2,info:3,warn:4,error:5}}isProductionEnvironment(){let t=process.env.NODE_ENV?.toLowerCase();return t==="production"||t==="prod"}getDefaultLevel(t){return t?"warn":"debug"}getDefaultColorizeValue(t){return t!==void 0?t:!this.isProductionEnvironment()}getDefaultJson(t){return t}getDefaultTimestamp(t){return!0}getDefaultTransports(t){return t?[new f,new d({path:"./logs/app.log"})]:[new f]}getDefaultAsyncMode(t){return t}initTransports(t,e){let s=[];for(let o of t)if(this.isLegacyTransportOptions(o)){let r=o;if(r.type==="console"){let n=new f({colorize:r.options?.colorize??e});s.push(n)}else if(r.type==="file"){if(r.options?.path){let n={path:r.options.path};r.options.maxSize!==void 0&&(n.maxSize=r.options.maxSize),r.options.maxFiles!==void 0&&(n.maxFiles=r.options.maxFiles),r.options.compression!==void 0&&(n.compression=r.options.compression),r.options.batchInterval!==void 0&&(n.batchInterval=r.options.batchInterval),r.options.compressOldFiles!==void 0&&(n.compressOldFiles=r.options.compressOldFiles);let p=new d(n);s.push(p)}}else r.type==="custom"&&r.instance&&s.push(r.instance)}else this.isTransport(o)&&s.push(o);return s}isLegacyTransportOptions(t){return typeof t=="object"&&t!==null&&"type"in t}isTransport(t){return t&&typeof t.write=="function"&&(typeof t.writeAsync=="function"||t.writeAsync===void 0)}shouldLog(t){let e=this.getLevelPriority(this.level);return this.getLevelPriority(t)>=e}getLevelPriority(t){if(a.LEVEL_PRIORITIES.hasOwnProperty(t))return a.LEVEL_PRIORITIES[t];if(this.customLevels&&t in this.customLevels){let e=this.customLevels[t];return e!==void 0?e:999}return 999}log(t,e,s){if(this.shouldLog(t)&&t!=="silent")if(this.asyncMode)this.logAsyncDirect(t,e,s);else{let o=new Date,r;this.context&&Object.keys(this.context).length>0?s?r={...this.context,...s}:r=this.context:s&&(r=s);let n={level:t,message:e,timestamp:o,metadata:r&&Object.keys(r).length>0?r:void 0,prefix:this.prefix};for(let p of this.transports)p.write(n,this.formatter)}}logAsyncDirect(t,e,s){if(!this.shouldLog(t)||t==="silent")return;let o=new Date,r;this.context&&Object.keys(this.context).length>0?s?r={...this.context,...s}:r=this.context:s&&(r=s);let n={level:t,message:e,timestamp:o,metadata:r&&Object.keys(r).length>0?r:void 0,prefix:this.prefix};for(let p of this.transports)p.writeAsync?p.writeAsync(n,this.formatter).catch(c=>{console.error("Error during async logging:",c)}):setImmediate(()=>{p.write(n,this.formatter)})}debug(t,e){this.log("debug",t,e)}info(t,e){this.log("info",t,e)}warn(t,e){this.log("warn",t,e)}error(t,e){this.log("error",t,e)}silent(t,e){this.log("silent",t,e)}boring(t,e){this.log("boring",t,e)}logWithLevel(t,e,s){this.log(t,e,s)}setLevel(t){this.level=t}setFormat(t){this.formatter.setJson(t==="json")}setAsyncMode(t){this.asyncMode=t}addTransport(t){this.transports.push(t)}getTimestampSetting(){return this.timestamp}static get global(){return a._global||(a._global=new a),a._global}createChild(t={}){return new a({...t,parent:this})}startTimer(t){let{Timer:e}=(H(),R(M));return new e(t,s=>this.info(s))}};var _=x;0&&(module.exports={ConsoleTransport,FileTransport,HttpTransport,Logger,consoleT,fileT,httpT});
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
2
|
-
`;
|
|
3
|
-
`;await new Promise((o,a)=>{n.appendFile(this.filePath,r,p=>{if(p){a(p);return}o()})}),await this.rotateIfNeededAsync()}rotateIfNeeded(){if(n.existsSync(this.filePath))try{n.statSync(this.filePath).size>=this.maxSize&&this.rotateFiles()}catch(t){console.error("Error checking file size for rotation:",t)}}async rotateIfNeededAsync(){if(n.existsSync(this.filePath))try{n.statSync(this.filePath).size>=this.maxSize&&await this.rotateFilesAsync()}catch(t){console.error("Error during rotation check:",t)}}rotateFiles(){try{let t="";n.existsSync(this.filePath)&&(t=n.readFileSync(this.filePath,"utf8"));let e=this.getRotatedFilePath();n.writeFileSync(e,t,"utf8"),n.writeFileSync(this.filePath,"","utf8"),this.cleanupOldFiles()}catch(t){console.error("Error during file rotation:",t)}}async rotateFilesAsync(){try{let t="";n.existsSync(this.filePath)&&(t=await n.promises.readFile(this.filePath,"utf8"));let e=this.getRotatedFilePath();await n.promises.writeFile(e,t,"utf8"),await n.promises.writeFile(this.filePath,"","utf8"),await this.cleanupOldFilesAsync()}catch(t){console.error("Error during async file rotation:",t)}}getRotatedFilePath(){let t=h.dirname(this.filePath),e=h.basename(this.filePath),i=Date.now();return h.join(t,`${e}.${i}`)}cleanupOldFiles(){try{let t=h.dirname(this.filePath),e=h.basename(this.filePath);try{n.accessSync(t,n.constants.F_OK)}catch{return}let r=n.readdirSync(t).filter(o=>!o||o===e?!1:new RegExp(`^${e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\.\\d+$`).test(o)).sort((o,a)=>{let p=parseInt(o.split(".").pop()||"0");return parseInt(a.split(".").pop()||"0")-p});for(let o=this.maxFiles;o<r.length;o++){let a=r[o];if(a){if(a.includes("../")||a.includes("..\\")||a.startsWith(".."))continue;let p=h.join(t,a),m=h.resolve(p),f=h.resolve(t);if(!m.startsWith(f+h.sep)&&m!==f)continue;try{n.unlinkSync(p)}catch(c){console.error(`Failed to delete old log file ${p}:`,c)}}}}catch(t){console.error("Error during cleanup of old files:",t)}}async cleanupOldFilesAsync(){try{let t=h.dirname(this.filePath),e=h.basename(this.filePath);try{await n.promises.access(t,n.constants.F_OK)}catch{return}let r=(await n.promises.readdir(t)).filter(a=>!a||a===e?!1:new RegExp(`^${e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\.\\d+$`).test(a)).sort((a,p)=>{let m=parseInt(a.split(".").pop()||"0");return parseInt(p.split(".").pop()||"0")-m}),o=[];for(let a=this.maxFiles;a<r.length;a++){let p=r[a];if(p){if(p.includes("../")||p.includes("..\\")||p.startsWith(".."))continue;let m=h.join(t,p),f=h.resolve(m),c=h.resolve(t);if(!f.startsWith(c+h.sep)&&f!==c)continue;o.push(n.promises.access(m,n.constants.F_OK).then(()=>n.promises.unlink(m)).catch(s=>{s.code!=="ENOENT"&&console.error(`Failed to delete old log file ${m}:`,s)}))}}await Promise.all(o)}catch(t){console.error("Error during async cleanup of old files:",t)}}};var L=class l{constructor(t={}){this.transports=[];let{level:e,colorize:i,json:r,transports:o=[],timestampFormat:a="YYYY-MM-DD HH:mm:ss",prefix:p,timestamp:m,context:f={},parent:c,asyncMode:s,customLevels:g={},customColors:T={}}=t;if(this.parent=c,this.context={...f},this.customLevels=g,this.asyncMode=!1,this.parent){this.level=e??this.parent.level,this.prefix=p??this.parent.prefix,this.timestamp=m??this.parent.timestamp,this.asyncMode=s??this.parent.asyncMode,this.transports=o&&o.length>0?this.initTransports(o,this.getDefaultColorizeValue(i)):this.parent.transports;let u={...this.parent.formatter.getCustomColors(),...T};this.formatter=new d({colorize:this.getDefaultColorizeValue(i)??this.parent.formatter.isColorized(),json:r??this.parent.formatter.isJson(),timestampFormat:a??this.parent.formatter.getTimestampFormat(),timestamp:m??this.parent.formatter.hasTimestamp(),customColors:u}),this.context={...this.parent.context,...this.context},this.customLevels={...this.parent.customLevels,...g}}else{let u=this.isProductionEnvironment();this.level=e??this.getDefaultLevel(u),this.prefix=p??"",this.timestamp=m??this.getDefaultTimestamp(u);let D=o&&o.length>0?o:this.getDefaultTransports(u);this.asyncMode=s??this.getDefaultAsyncMode(u),this.transports=this.initTransports(D,this.getDefaultColorizeValue(i)),this.formatter=new d({colorize:this.getDefaultColorizeValue(i),json:r??this.getDefaultJson(u),timestampFormat:a,timestamp:this.getDefaultTimestamp(u),customColors:T})}l._global||(l._global=this)}static{this.LEVEL_PRIORITIES={silent:0,boring:1,debug:2,info:3,warn:4,error:5}}isProductionEnvironment(){let t=process.env.NODE_ENV?.toLowerCase();return t==="production"||t==="prod"}getDefaultLevel(t){return t?"warn":"debug"}getDefaultColorizeValue(t){return t!==void 0?t:!this.isProductionEnvironment()}getDefaultJson(t){return t}getDefaultTimestamp(t){return!0}getDefaultTransports(t){return t?[{type:"console"},{type:"file",options:{path:"./logs/app.log"}}]:[{type:"console"}]}getDefaultAsyncMode(t){return t}initTransports(t,e){let i=[];for(let r of t)if(r.type==="console"){let o=new v({colorize:r.options?.colorize??e});i.push(o)}else if(r.type==="file"){if(r.options?.path){let o={path:r.options.path};r.options.maxSize!==void 0&&(o.maxSize=r.options.maxSize),r.options.maxFiles!==void 0&&(o.maxFiles=r.options.maxFiles);let a=new b(o);i.push(a)}}else r.type==="custom"&&r.instance&&i.push(r.instance);return i}shouldLog(t){let e=this.getLevelPriority(this.level);return this.getLevelPriority(t)>=e}getLevelPriority(t){if(l.LEVEL_PRIORITIES.hasOwnProperty(t))return l.LEVEL_PRIORITIES[t];if(this.customLevels&&t in this.customLevels){let e=this.customLevels[t];return e!==void 0?e:999}return 999}log(t,e,i){if(this.shouldLog(t)&&t!=="silent")if(this.asyncMode)this.logAsyncDirect(t,e,i);else{let r=new Date,o;this.context&&Object.keys(this.context).length>0?i?o={...this.context,...i}:o=this.context:i&&(o=i);let a={level:t,message:e,timestamp:r,metadata:o&&Object.keys(o).length>0?o:void 0,prefix:this.prefix};for(let p of this.transports)p.write(a,this.formatter)}}logAsyncDirect(t,e,i){if(!this.shouldLog(t)||t==="silent")return;let r=new Date,o;this.context&&Object.keys(this.context).length>0?i?o={...this.context,...i}:o=this.context:i&&(o=i);let a={level:t,message:e,timestamp:r,metadata:o&&Object.keys(o).length>0?o:void 0,prefix:this.prefix};for(let p of this.transports)p.writeAsync?p.writeAsync(a,this.formatter).catch(m=>{console.error("Error during async logging:",m)}):setImmediate(()=>{p.write(a,this.formatter)})}debug(t,e){this.log("debug",t,e)}info(t,e){this.log("info",t,e)}warn(t,e){this.log("warn",t,e)}error(t,e){this.log("error",t,e)}silent(t,e){this.log("silent",t,e)}boring(t,e){this.log("boring",t,e)}logWithLevel(t,e,i){this.log(t,e,i)}setLevel(t){this.level=t}setFormat(t){this.formatter.setJson(t==="json")}setAsyncMode(t){this.asyncMode=t}addTransport(t){this.transports.push(t)}getTimestampSetting(){return this.timestamp}static get global(){return l._global||(l._global=new l),l._global}createChild(t={}){return new l({...t,parent:this})}startTimer(t){let{Timer:e}=(P(),I(O));return new e(t,i=>this.info(i))}};var et=L;export{v as ConsoleTransport,b as FileTransport,L as Logger,et as default};
|
|
1
|
+
var w=Object.defineProperty;var I=Object.getOwnPropertyDescriptor;var E=Object.getOwnPropertyNames;var A=Object.prototype.hasOwnProperty;var $=(l,t)=>()=>(l&&(t=l(l=0)),t);var M=(l,t)=>{for(var e in t)w(l,e,{get:t[e],enumerable:!0})},H=(l,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of E(t))!A.call(l,o)&&o!==e&&w(l,o,{get:()=>t[o],enumerable:!(s=I(t,o))||s.enumerable});return l};var j=l=>H(w({},"__esModule",{value:!0}),l);var z={};M(z,{Timer:()=>O});var O,D=$(()=>{"use strict";O=class{constructor(t,e){this.hasEnded=!1;this.name=t,this.logFn=e,this.startTime=Date.now()}end(){if(this.hasEnded)return;let e=Date.now()-this.startTime;this.logFn(`${this.name} took ${e}ms`),this.hasEnded=!0}}});var L=class{static format(t,e){if(e==="ISO")return t.toISOString();if(e==="UTC")return t.toUTCString();if(e==="LOCAL")return t.toLocaleString();let s=t.getFullYear(),o=t.getMonth()+1,r=t.getDate(),n=t.getHours(),p=t.getMinutes(),c=t.getSeconds(),u=t.getMilliseconds(),h=[],i=0,g=0;for(;i<e.length;)e[i]==="Y"&&i+3<e.length&&e.slice(i,i+4)==="YYYY"?(h.push(e.substring(g,i)),h.push(s.toString().padStart(4,"0")),i+=4,g=i):e[i]==="M"&&i+1<e.length&&e.slice(i,i+2)==="MM"?(h.push(e.substring(g,i)),h.push(o.toString().padStart(2,"0")),i+=2,g=i):e[i]==="D"&&i+1<e.length&&e.slice(i,i+2)==="DD"?(h.push(e.substring(g,i)),h.push(r.toString().padStart(2,"0")),i+=2,g=i):e[i]==="H"&&i+1<e.length&&e.slice(i,i+2)==="HH"?(h.push(e.substring(g,i)),h.push(n.toString().padStart(2,"0")),i+=2,g=i):e[i]==="m"&&i+1<e.length&&e.slice(i,i+2)==="mm"?(h.push(e.substring(g,i)),h.push(p.toString().padStart(2,"0")),i+=2,g=i):e[i]==="s"&&i+1<e.length&&e.slice(i,i+2)==="ss"?(h.push(e.substring(g,i)),h.push(c.toString().padStart(2,"0")),i+=2,g=i):e[i]==="S"&&i+2<e.length&&e.slice(i,i+3)==="SSS"?(h.push(e.substring(g,i)),h.push(u.toString().padStart(3,"0")),i+=3,g=i):i++;return h.push(e.substring(g)),h.join("")}};var x=class l{static{this.ANSI_COLORS={black:"\x1B[30m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",cyan:"\x1B[36m",white:"\x1B[37m",brightRed:"\x1B[91m",brightGreen:"\x1B[92m",brightYellow:"\x1B[93m",brightBlue:"\x1B[94m",brightMagenta:"\x1B[95m",brightCyan:"\x1B[96m",brightWhite:"\x1B[97m",info:"\x1B[32m",warn:"\x1B[33m",error:"\x1B[31m",debug:"\x1B[36m",boring:"\x1B[37m",reset:"\x1B[0m"}}static colorize(t,e){return process.env.FORCE_COLOR!=="0"&&(process.stdout.isTTY||process.env.FORCE_COLOR==="1")?`${l.ANSI_COLORS[e]||l.ANSI_COLORS.reset}${t}${l.ANSI_COLORS.reset}`:t}};var y=class{constructor(t={}){let{colorize:e=!0,json:s=!1,timestampFormat:o="YYYY-MM-DD HH:mm:ss",timestamp:r=!1,customColors:n={}}=t;this.colorize=e,this.json=s,this.timestampFormat=o,this.timestamp=r,this.customColors=n}format(t){return this.json?this.formatAsJson(t):this.formatAsText(t)}formatAsJson(t){let e={...t.metadata,level:t.level,message:t.message};return this.timestamp&&(e.timestamp=t.timestamp.toISOString()),t.prefix&&(e.prefix=t.prefix),JSON.stringify(e)}formatAsText(t){let e=[];if(this.timestamp){let o=L.format(t.timestamp,this.timestampFormat);e.push(`[${o}] `)}t.prefix&&e.push(`${t.prefix} `);let s=t.level.toUpperCase();if(this.colorize){let o=this.customColors[t.level]||t.level;s=x.colorize(s,o)}return e.push(`[${s}] `),e.push(t.message),t.metadata&&e.push(` ${JSON.stringify(t.metadata)}`),e.join("")}setJson(t){this.json=t}isColorized(){return this.colorize}isJson(){return this.json}getTimestampFormat(){return this.timestampFormat}hasTimestamp(){return this.timestamp}getCustomColors(){return{...this.customColors}}};var f=class{constructor(t={}){let{colorize:e=!0}=t;this.colorize=e}write(t,e){let s=e.colorize;this.colorize!==s&&(e.colorize=this.colorize);let o=e.format(t);switch(this.colorize!==s&&(e.colorize=s),t.level){case"error":console.error(o);break;case"warn":console.warn(o);break;default:console.log(o);break}}async writeAsync(t,e){return setImmediate(()=>{this.write(t,e)}),Promise.resolve()}};import*as a from"fs";import*as m from"path";import*as b from"zlib";import{promisify as S}from"util";var N=S(b.gzip),k=S(b.deflate),v=class{constructor(t){this.batchQueue=[];this.batchTimer=null;let{path:e,maxSize:s=10*1024*1024,maxFiles:o=5,compression:r="none",batchInterval:n=0,compressOldFiles:p=!0}=t;this.filePath=e,this.maxSize=s,this.maxFiles=o,this.compression=r,this.batchInterval=n,this.compressOldFiles=p;let c=m.dirname(this.filePath);a.existsSync(c)||a.mkdirSync(c,{recursive:!0}),a.existsSync(this.filePath)||a.writeFileSync(this.filePath,"","utf8"),n>0&&this.startBatching()}write(t,e){let o=e.format(t)+`
|
|
2
|
+
`;this.batchInterval>0?this.batchQueue.push({data:o,timestamp:new Date}):(a.appendFileSync(this.filePath,o),this.rotateIfNeeded())}async writeAsync(t,e){let o=e.format(t)+`
|
|
3
|
+
`;this.batchInterval>0?this.batchQueue.push({data:o,timestamp:new Date}):(await new Promise((r,n)=>{a.appendFile(this.filePath,o,p=>{if(p){n(p);return}r()})}),await this.rotateIfNeededAsync())}rotateIfNeeded(){if(a.existsSync(this.filePath))try{a.statSync(this.filePath).size>=this.maxSize&&this.rotateFiles()}catch(t){console.error("Error checking file size for rotation:",t)}}async rotateIfNeededAsync(){if(a.existsSync(this.filePath))try{a.statSync(this.filePath).size>=this.maxSize&&await this.rotateFilesAsync()}catch(t){console.error("Error during rotation check:",t)}}rotateFiles(){try{let t="";a.existsSync(this.filePath)&&(t=a.readFileSync(this.filePath,"utf8"));let e=this.getRotatedFilePath();if(this.compression!=="none"&&this.compressOldFiles){e=`${e}.${this.compression==="gzip"?"gz":"zz"}`;let s=this.compression==="gzip"?b.gzipSync(t):b.deflateSync(t);a.writeFileSync(e,s)}else a.writeFileSync(e,t,"utf8");a.writeFileSync(this.filePath,"","utf8"),this.cleanupOldFiles()}catch(t){console.error("Error during file rotation:",t)}}async rotateFilesAsync(){try{let t="";a.existsSync(this.filePath)&&(t=await a.promises.readFile(this.filePath,"utf8"));let e=this.getRotatedFilePath();if(this.compression!=="none"&&this.compressOldFiles){e=`${e}.${this.compression==="gzip"?"gz":"zz"}`;let s=this.compression==="gzip"?await N(t):await k(t);await a.promises.writeFile(e,s)}else await a.promises.writeFile(e,t,"utf8");await a.promises.writeFile(this.filePath,"","utf8"),await this.cleanupOldFilesAsync()}catch(t){console.error("Error during async file rotation:",t)}}getRotatedFilePath(){let t=m.dirname(this.filePath),e=m.basename(this.filePath),s=Date.now();return m.join(t,`${e}.${s}`)}cleanupOldFiles(){try{let t=m.dirname(this.filePath),e=m.basename(this.filePath);try{a.accessSync(t,a.constants.F_OK)}catch{return}let o=a.readdirSync(t).filter(r=>!r||r===e?!1:new RegExp(`^${e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\.\\d+(\\.gz|\\.zz)?$`).test(r)).sort((r,n)=>{let p=parseInt(r.slice(e.length+1).split(".")[0]||"0");return parseInt(n.slice(e.length+1).split(".")[0]||"0")-p});for(let r=this.maxFiles;r<o.length;r++){let n=o[r];if(n){if(n.includes("../")||n.includes("..\\")||n.startsWith(".."))continue;let p=m.join(t,n),c=m.resolve(p),u=m.resolve(t);if(!c.startsWith(u+m.sep)&&c!==u)continue;try{a.unlinkSync(p)}catch(h){console.error(`Failed to delete old log file ${p}:`,h)}}}}catch(t){console.error("Error during cleanup of old files:",t)}}async cleanupOldFilesAsync(){try{let t=m.dirname(this.filePath),e=m.basename(this.filePath);try{await a.promises.access(t,a.constants.F_OK)}catch{return}let o=(await a.promises.readdir(t)).filter(n=>!n||n===e?!1:new RegExp(`^${e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\.\\d+(\\.gz|\\.zz)?$`).test(n)).sort((n,p)=>{let c=parseInt(n.slice(e.length+1).split(".")[0]||"0");return parseInt(p.slice(e.length+1).split(".")[0]||"0")-c}),r=[];for(let n=this.maxFiles;n<o.length;n++){let p=o[n];if(p){if(p.includes("../")||p.includes("..\\")||p.startsWith(".."))continue;let c=m.join(t,p),u=m.resolve(c),h=m.resolve(t);if(!u.startsWith(h+m.sep)&&u!==h)continue;r.push(a.promises.access(c,a.constants.F_OK).then(()=>a.promises.unlink(c)).catch(i=>{i.code!=="ENOENT"&&console.error(`Failed to delete old log file ${c}:`,i)}))}}await Promise.all(r)}catch(t){console.error("Error during async cleanup of old files:",t)}}startBatching(){this.batchInterval>0&&(this.batchTimer=setInterval(()=>{this.processBatch().catch(t=>{console.error("Error in batch processing timer:",t)})},this.batchInterval))}async processBatch(){if(this.batchQueue.length===0)return;let t=this.batchQueue;this.batchQueue=[];let e=t.map(s=>s.data).join("");try{await new Promise((s,o)=>{a.appendFile(this.filePath,e,r=>{if(r){o(r);return}s()})}),await this.rotateIfNeededAsync()}catch(s){console.error("Error processing log batch:",s),this.batchQueue=[...t,...this.batchQueue]}}async destroy(){if(this.batchTimer&&(clearInterval(this.batchTimer),this.batchTimer=null),this.batchQueue.length>0)try{await this.processBatch()}catch(t){console.error("Error processing final batch:",t)}}};import*as Y from"http";import*as B from"https";import*as P from"url";var T=class{constructor(t){let{url:e,method:s="POST",headers:o={},timeout:r=5e3,retries:n=3}=t;if(!e)throw new Error("HttpTransport requires a URL option");this.url=e,this.method=s.toUpperCase(),this.headers={...o},this.timeout=r,this.retries=n,!this.headers["Content-Type"]&&!this.headers["content-type"]&&(this.headers["Content-Type"]="application/json")}write(t,e){let s=this.parseFormattedData(t),o=JSON.stringify(s);setImmediate(()=>{this.sendHttpRequestWithRetry(o,0).catch(r=>{console.error("HttpTransport error (sync mode):",r.message)})})}async writeAsync(t,e){let s=this.parseFormattedData(t),o=JSON.stringify(s);await this.sendHttpRequestWithRetry(o,this.retries)}parseFormattedData(t){return{level:t.level,message:t.message,timestamp:t.timestamp.toISOString(),...t.prefix&&{prefix:t.prefix},...t.metadata&&{metadata:t.metadata}}}async sendHttpRequestWithRetry(t,e){let s=null;for(let o=0;o<=e;o++)try{await this.sendHttpRequest(t);return}catch(r){if(s=r,o===e)break;await this.delay(Math.pow(2,o)*1e3)}if(s)throw s}sendHttpRequest(t){return new Promise((e,s)=>{let o=new P.URL(this.url),n=o.protocol==="https:"?B:Y,p={hostname:o.hostname,port:o.port,path:o.pathname+o.search,method:this.method,headers:{...this.headers,"Content-Length":Buffer.byteLength(t,"utf8")},timeout:this.timeout},c=n.request(p,u=>{let h="";u.on("data",i=>{h+=i}),u.on("end",()=>{u.statusCode&&u.statusCode>=200&&u.statusCode<300?e():s(new Error(`HTTP request failed with status ${u.statusCode}: ${h}`))})});c.on("error",u=>{s(u)}),c.on("timeout",()=>{c.destroy(),s(new Error("Request timeout"))}),c.write(t),c.end()})}delay(t){return new Promise(e=>setTimeout(e,t))}};function q(l){return new f(l)}function J(l){return new v(l)}function Q(l){return new T(l)}var F=class l{constructor(t={}){this.transports=[];let{level:e,colorize:s,json:o,transports:r=[],timestampFormat:n="YYYY-MM-DD HH:mm:ss",prefix:p,timestamp:c,context:u={},parent:h,asyncMode:i,customLevels:g={},customColors:C={}}=t;if(this.parent=h,this.context={...u},this.customLevels=g,this.asyncMode=!1,this.parent){this.level=e??this.parent.level,this.prefix=p??this.parent.prefix,this.timestamp=c??this.parent.timestamp,this.asyncMode=i??this.parent.asyncMode,this.transports=r&&r.length>0?this.initTransports(r,this.getDefaultColorizeValue(s)):this.parent.transports;let d={...this.parent.formatter.getCustomColors(),...C};this.formatter=new y({colorize:this.getDefaultColorizeValue(s)??this.parent.formatter.isColorized(),json:o??this.parent.formatter.isJson(),timestampFormat:n??this.parent.formatter.getTimestampFormat(),timestamp:c??this.parent.formatter.hasTimestamp(),customColors:d}),this.context={...this.parent.context,...this.context},this.customLevels={...this.parent.customLevels,...g}}else{let d=this.isProductionEnvironment();this.level=e??this.getDefaultLevel(d),this.prefix=p??"",this.timestamp=c??this.getDefaultTimestamp(d);let R=r&&r.length>0?r:this.getDefaultTransports(d);this.asyncMode=i??this.getDefaultAsyncMode(d),this.transports=this.initTransports(R,this.getDefaultColorizeValue(s)),this.formatter=new y({colorize:this.getDefaultColorizeValue(s),json:o??this.getDefaultJson(d),timestampFormat:n,timestamp:this.getDefaultTimestamp(d),customColors:C})}l._global||(l._global=this)}static{this.LEVEL_PRIORITIES={silent:0,boring:1,debug:2,info:3,warn:4,error:5}}isProductionEnvironment(){let t=process.env.NODE_ENV?.toLowerCase();return t==="production"||t==="prod"}getDefaultLevel(t){return t?"warn":"debug"}getDefaultColorizeValue(t){return t!==void 0?t:!this.isProductionEnvironment()}getDefaultJson(t){return t}getDefaultTimestamp(t){return!0}getDefaultTransports(t){return t?[new f,new v({path:"./logs/app.log"})]:[new f]}getDefaultAsyncMode(t){return t}initTransports(t,e){let s=[];for(let o of t)if(this.isLegacyTransportOptions(o)){let r=o;if(r.type==="console"){let n=new f({colorize:r.options?.colorize??e});s.push(n)}else if(r.type==="file"){if(r.options?.path){let n={path:r.options.path};r.options.maxSize!==void 0&&(n.maxSize=r.options.maxSize),r.options.maxFiles!==void 0&&(n.maxFiles=r.options.maxFiles),r.options.compression!==void 0&&(n.compression=r.options.compression),r.options.batchInterval!==void 0&&(n.batchInterval=r.options.batchInterval),r.options.compressOldFiles!==void 0&&(n.compressOldFiles=r.options.compressOldFiles);let p=new v(n);s.push(p)}}else r.type==="custom"&&r.instance&&s.push(r.instance)}else this.isTransport(o)&&s.push(o);return s}isLegacyTransportOptions(t){return typeof t=="object"&&t!==null&&"type"in t}isTransport(t){return t&&typeof t.write=="function"&&(typeof t.writeAsync=="function"||t.writeAsync===void 0)}shouldLog(t){let e=this.getLevelPriority(this.level);return this.getLevelPriority(t)>=e}getLevelPriority(t){if(l.LEVEL_PRIORITIES.hasOwnProperty(t))return l.LEVEL_PRIORITIES[t];if(this.customLevels&&t in this.customLevels){let e=this.customLevels[t];return e!==void 0?e:999}return 999}log(t,e,s){if(this.shouldLog(t)&&t!=="silent")if(this.asyncMode)this.logAsyncDirect(t,e,s);else{let o=new Date,r;this.context&&Object.keys(this.context).length>0?s?r={...this.context,...s}:r=this.context:s&&(r=s);let n={level:t,message:e,timestamp:o,metadata:r&&Object.keys(r).length>0?r:void 0,prefix:this.prefix};for(let p of this.transports)p.write(n,this.formatter)}}logAsyncDirect(t,e,s){if(!this.shouldLog(t)||t==="silent")return;let o=new Date,r;this.context&&Object.keys(this.context).length>0?s?r={...this.context,...s}:r=this.context:s&&(r=s);let n={level:t,message:e,timestamp:o,metadata:r&&Object.keys(r).length>0?r:void 0,prefix:this.prefix};for(let p of this.transports)p.writeAsync?p.writeAsync(n,this.formatter).catch(c=>{console.error("Error during async logging:",c)}):setImmediate(()=>{p.write(n,this.formatter)})}debug(t,e){this.log("debug",t,e)}info(t,e){this.log("info",t,e)}warn(t,e){this.log("warn",t,e)}error(t,e){this.log("error",t,e)}silent(t,e){this.log("silent",t,e)}boring(t,e){this.log("boring",t,e)}logWithLevel(t,e,s){this.log(t,e,s)}setLevel(t){this.level=t}setFormat(t){this.formatter.setJson(t==="json")}setAsyncMode(t){this.asyncMode=t}addTransport(t){this.transports.push(t)}getTimestampSetting(){return this.timestamp}static get global(){return l._global||(l._global=new l),l._global}createChild(t={}){return new l({...t,parent:this})}startTimer(t){let{Timer:e}=(D(),j(z));return new e(t,s=>this.info(s))}};var xt=F;export{f as ConsoleTransport,v as FileTransport,T as HttpTransport,F as Logger,q as consoleT,xt as default,J as fileT,Q as httpT};
|
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
import { Transport } from "./Transport";
|
|
2
2
|
import { LogData } from "../types";
|
|
3
3
|
import { Formatter } from "../core/Formatter";
|
|
4
|
+
export type CompressionType = "gzip" | "deflate" | "none";
|
|
4
5
|
export interface FileTransportOptions {
|
|
5
6
|
path: string;
|
|
6
7
|
maxSize?: number;
|
|
7
8
|
maxFiles?: number;
|
|
9
|
+
compression?: CompressionType;
|
|
10
|
+
batchInterval?: number;
|
|
11
|
+
compressOldFiles?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface BatchLogEntry {
|
|
14
|
+
data: string;
|
|
15
|
+
timestamp: Date;
|
|
8
16
|
}
|
|
9
17
|
export declare class FileTransport implements Transport {
|
|
10
18
|
private filePath;
|
|
11
19
|
private maxSize;
|
|
12
20
|
private maxFiles;
|
|
21
|
+
private compression;
|
|
22
|
+
private batchInterval;
|
|
23
|
+
private compressOldFiles;
|
|
24
|
+
private batchQueue;
|
|
25
|
+
private batchTimer;
|
|
13
26
|
constructor(options: FileTransportOptions);
|
|
14
27
|
write(data: LogData, formatter: Formatter): void;
|
|
15
28
|
writeAsync(data: LogData, formatter: Formatter): Promise<void>;
|
|
@@ -20,4 +33,7 @@ export declare class FileTransport implements Transport {
|
|
|
20
33
|
private getRotatedFilePath;
|
|
21
34
|
private cleanupOldFiles;
|
|
22
35
|
private cleanupOldFilesAsync;
|
|
36
|
+
private startBatching;
|
|
37
|
+
private processBatch;
|
|
38
|
+
destroy(): Promise<void>;
|
|
23
39
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Transport } from "./Transport";
|
|
2
|
+
import { LogData } from "../types";
|
|
3
|
+
import { Formatter } from "../core/Formatter";
|
|
4
|
+
export interface HttpTransportOptions {
|
|
5
|
+
url: string;
|
|
6
|
+
method?: string;
|
|
7
|
+
headers?: Record<string, string>;
|
|
8
|
+
timeout?: number;
|
|
9
|
+
retries?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare class HttpTransport implements Transport {
|
|
12
|
+
private url;
|
|
13
|
+
private method;
|
|
14
|
+
private headers;
|
|
15
|
+
private timeout;
|
|
16
|
+
private retries;
|
|
17
|
+
constructor(options: HttpTransportOptions);
|
|
18
|
+
write(data: LogData, formatter: Formatter): void;
|
|
19
|
+
writeAsync(data: LogData, formatter: Formatter): Promise<void>;
|
|
20
|
+
private parseFormattedData;
|
|
21
|
+
private sendHttpRequestWithRetry;
|
|
22
|
+
private sendHttpRequest;
|
|
23
|
+
private delay;
|
|
24
|
+
}
|
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
import { ConsoleTransport, ConsoleTransportOptions } from "./ConsoleTransport";
|
|
2
|
+
import { FileTransport, FileTransportOptions } from "./FileTransport";
|
|
3
|
+
import { HttpTransport, HttpTransportOptions } from "./HttpTransport";
|
|
1
4
|
export * from "./Transport";
|
|
2
5
|
export * from "./ConsoleTransport";
|
|
3
6
|
export * from "./FileTransport";
|
|
7
|
+
export * from "./HttpTransport";
|
|
8
|
+
/**
|
|
9
|
+
* Create a ConsoleTransport instance configured with the given options.
|
|
10
|
+
*
|
|
11
|
+
* @param options - Configuration options for the console transport
|
|
12
|
+
* @returns A `ConsoleTransport` instance
|
|
13
|
+
*/
|
|
14
|
+
export declare function consoleT(options?: ConsoleTransportOptions): ConsoleTransport;
|
|
15
|
+
/**
|
|
16
|
+
* Create a FileTransport configured with the provided options.
|
|
17
|
+
*
|
|
18
|
+
* @param options - Options to configure the FileTransport
|
|
19
|
+
* @returns A new `FileTransport` instance configured according to `options`
|
|
20
|
+
*/
|
|
21
|
+
export declare function fileT(options: FileTransportOptions): FileTransport;
|
|
22
|
+
/**
|
|
23
|
+
* Creates an HttpTransport using the provided configuration.
|
|
24
|
+
*
|
|
25
|
+
* @param options - Configuration options for the HttpTransport
|
|
26
|
+
* @returns The constructed `HttpTransport` instance
|
|
27
|
+
*/
|
|
28
|
+
export declare function httpT(options: HttpTransportOptions): HttpTransport;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zario",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.9",
|
|
4
4
|
"description": "A minimal, fast logging library for Node.js.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"homepage": "https://github.com/Dev-Dami/zario#readme",
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/jest": "^30.0.0",
|
|
43
|
-
"@types/node": "^24.10.
|
|
43
|
+
"@types/node": "^24.10.1",
|
|
44
44
|
"@typescript-eslint/eslint-plugin": "^8.46.4",
|
|
45
45
|
"@typescript-eslint/parser": "^8.46.4",
|
|
46
46
|
"esbuild": "^0.27.0",
|
|
@@ -53,5 +53,10 @@
|
|
|
53
53
|
"dist/**/*",
|
|
54
54
|
"README.md",
|
|
55
55
|
"README.npm.md"
|
|
56
|
-
]
|
|
57
|
-
|
|
56
|
+
],
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"@types/express": "^5.0.6",
|
|
59
|
+
"express": "^5.2.1",
|
|
60
|
+
"fastify": "^5.6.2"
|
|
61
|
+
}
|
|
62
|
+
}
|