@bloomneo/appkit 1.2.9 โ 1.5.2
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/AGENTS.md +195 -0
- package/CHANGELOG.md +253 -0
- package/README.md +147 -799
- package/bin/commands/generate.js +7 -7
- package/cookbook/README.md +26 -0
- package/cookbook/api-key-service.ts +106 -0
- package/cookbook/auth-protected-crud.ts +112 -0
- package/cookbook/file-upload-pipeline.ts +113 -0
- package/cookbook/multi-tenant-saas.ts +87 -0
- package/cookbook/real-time-chat.ts +121 -0
- package/dist/auth/auth.d.ts +21 -4
- package/dist/auth/auth.d.ts.map +1 -1
- package/dist/auth/auth.js +56 -44
- package/dist/auth/auth.js.map +1 -1
- package/dist/auth/defaults.d.ts +1 -1
- package/dist/auth/defaults.js +35 -35
- package/dist/cache/cache.d.ts +29 -6
- package/dist/cache/cache.d.ts.map +1 -1
- package/dist/cache/cache.js +72 -44
- package/dist/cache/cache.js.map +1 -1
- package/dist/cache/defaults.js +29 -29
- package/dist/cache/index.d.ts +19 -10
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +21 -18
- package/dist/cache/index.js.map +1 -1
- package/dist/config/defaults.d.ts +1 -1
- package/dist/config/defaults.js +11 -11
- package/dist/config/index.d.ts +3 -3
- package/dist/config/index.js +4 -4
- package/dist/database/adapters/mongoose.d.ts +4 -4
- package/dist/database/adapters/mongoose.js +7 -7
- package/dist/database/adapters/prisma.d.ts +4 -4
- package/dist/database/adapters/prisma.js +7 -7
- package/dist/database/defaults.d.ts +1 -1
- package/dist/database/defaults.js +4 -4
- package/dist/database/index.js +2 -2
- package/dist/database/index.js.map +1 -1
- package/dist/email/defaults.js +26 -26
- package/dist/email/index.js +7 -7
- package/dist/email/strategies/resend.js +1 -1
- package/dist/error/defaults.d.ts +1 -1
- package/dist/error/defaults.js +13 -13
- package/dist/error/error.d.ts +12 -0
- package/dist/error/error.d.ts.map +1 -1
- package/dist/error/error.js +19 -0
- package/dist/error/error.js.map +1 -1
- package/dist/error/index.d.ts +14 -3
- package/dist/error/index.d.ts.map +1 -1
- package/dist/error/index.js +14 -3
- package/dist/error/index.js.map +1 -1
- package/dist/event/defaults.js +35 -35
- package/dist/event/index.js +7 -7
- package/dist/logger/defaults.d.ts +1 -1
- package/dist/logger/defaults.js +40 -40
- package/dist/logger/index.d.ts +1 -0
- package/dist/logger/index.d.ts.map +1 -1
- package/dist/logger/index.js.map +1 -1
- package/dist/logger/logger.d.ts +8 -0
- package/dist/logger/logger.d.ts.map +1 -1
- package/dist/logger/logger.js +13 -3
- package/dist/logger/logger.js.map +1 -1
- package/dist/logger/transports/console.js +2 -2
- package/dist/logger/transports/http.d.ts +1 -1
- package/dist/logger/transports/http.js +2 -2
- package/dist/logger/transports/webhook.d.ts +1 -1
- package/dist/logger/transports/webhook.js +3 -3
- package/dist/queue/defaults.d.ts +2 -2
- package/dist/queue/defaults.js +38 -38
- package/dist/security/defaults.d.ts +1 -1
- package/dist/security/defaults.js +30 -30
- package/dist/security/index.d.ts +1 -1
- package/dist/security/index.js +3 -3
- package/dist/security/security.d.ts +1 -1
- package/dist/security/security.js +4 -4
- package/dist/storage/defaults.js +26 -26
- package/dist/storage/index.js +3 -3
- package/dist/util/defaults.d.ts +1 -1
- package/dist/util/defaults.js +41 -41
- package/dist/util/env.d.ts +35 -0
- package/dist/util/env.d.ts.map +1 -0
- package/dist/util/env.js +50 -0
- package/dist/util/env.js.map +1 -0
- package/dist/util/errors.d.ts +52 -0
- package/dist/util/errors.d.ts.map +1 -0
- package/dist/util/errors.js +82 -0
- package/dist/util/errors.js.map +1 -0
- package/dist/util/util.js +1 -1
- package/examples/.env.example +80 -0
- package/examples/README.md +16 -0
- package/examples/auth.ts +228 -0
- package/examples/cache.ts +36 -0
- package/examples/config.ts +45 -0
- package/examples/database.ts +69 -0
- package/examples/email.ts +53 -0
- package/examples/error.ts +50 -0
- package/examples/event.ts +42 -0
- package/examples/logger.ts +41 -0
- package/examples/queue.ts +58 -0
- package/examples/security.ts +46 -0
- package/examples/storage.ts +44 -0
- package/examples/util.ts +47 -0
- package/llms.txt +591 -0
- package/package.json +19 -10
- package/src/auth/README.md +850 -0
- package/src/cache/README.md +756 -0
- package/src/config/README.md +604 -0
- package/src/database/README.md +818 -0
- package/src/email/README.md +759 -0
- package/src/error/README.md +660 -0
- package/src/event/README.md +729 -0
- package/src/logger/README.md +435 -0
- package/src/queue/README.md +851 -0
- package/src/security/README.md +612 -0
- package/src/storage/README.md +1008 -0
- package/src/util/README.md +955 -0
- package/bin/templates/backend/docs/APPKIT_CLI.md +0 -507
- package/bin/templates/backend/docs/APPKIT_COMMENTS_GUIDELINES.md +0 -61
- package/bin/templates/backend/docs/APPKIT_LLM_GUIDE.md +0 -2539
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
# @bloomneo/appkit/logging
|
|
2
|
+
|
|
3
|
+
> **Ultra-simple logging that just works** - One function, five transports, zero
|
|
4
|
+
> headaches
|
|
5
|
+
|
|
6
|
+
[](https://www.npmjs.com/package/@bloomneo/appkit)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
|
|
9
|
+
## ๐ Why Choose This?
|
|
10
|
+
|
|
11
|
+
- **โก One Function** - Just `loggerClass.get()`, everything else is automatic
|
|
12
|
+
- **๐ฏ Five Transports** - Console, file, database, HTTP, webhook - all
|
|
13
|
+
auto-detected
|
|
14
|
+
- **๐ง Zero Configuration** - Smart defaults with environment variable override
|
|
15
|
+
- **๐ Environment-First** - Auto-detects from `BLOOM_LOGGER_*` variables
|
|
16
|
+
- **๐จ Visual Error Display** - Enhanced error formatting in development
|
|
17
|
+
- **๐ค AI-Ready** - Optimized for LLM code generation
|
|
18
|
+
|
|
19
|
+
## ๐ฆ Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @bloomneo/appkit
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## ๐โโ๏ธ Quick Start (30 seconds)
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { loggerClass } from '@bloomneo/appkit/logger';
|
|
29
|
+
|
|
30
|
+
const log = loggerClass.get();
|
|
31
|
+
log.info('๐ App started');
|
|
32
|
+
log.error('๐ฅ Something broke', { userId: 123, error: 'timeout' });
|
|
33
|
+
|
|
34
|
+
// Component logging
|
|
35
|
+
const dbLog = loggerClass.get('database');
|
|
36
|
+
dbLog.warn('โ ๏ธ Connection slow', { latency: '2s' });
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**That's it!** No configuration, no setup, production-ready.
|
|
40
|
+
|
|
41
|
+
## โจ Auto-Transport Detection
|
|
42
|
+
|
|
43
|
+
The logger **automatically detects** what you need:
|
|
44
|
+
|
|
45
|
+
| Environment Variable | Transport Enabled | What You Get |
|
|
46
|
+
| -------------------------- | ------------------ | ----------------------- |
|
|
47
|
+
| _Nothing_ | Console + File | Development logging |
|
|
48
|
+
| `DATABASE_URL` | + Database | Centralized storage |
|
|
49
|
+
| `BLOOM_LOGGER_HTTP_URL` | + External service | Professional monitoring |
|
|
50
|
+
| `BLOOM_LOGGER_WEBHOOK_URL` | + Slack alerts | Real-time notifications |
|
|
51
|
+
|
|
52
|
+
**Set environment variables, get enterprise features. No code changes.**
|
|
53
|
+
|
|
54
|
+
## ๐ค LLM Quick Reference - Copy These Patterns
|
|
55
|
+
|
|
56
|
+
### **Basic Setup (Copy Exactly)**
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
// โ
CORRECT - Basic pattern
|
|
60
|
+
import { loggerClass } from '@bloomneo/appkit/logger';
|
|
61
|
+
|
|
62
|
+
const log = loggerClass.get();
|
|
63
|
+
const apiLog = loggerClass.get('api');
|
|
64
|
+
const dbLog = loggerClass.get('database');
|
|
65
|
+
|
|
66
|
+
log.info('User registered', { userId: 123, email: 'user@example.com' });
|
|
67
|
+
log.error('Database error', { table: 'users', operation: 'INSERT' });
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### **Framework Patterns (Copy These)**
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
// โ
EXPRESS - Request logging
|
|
74
|
+
app.use((req, res, next) => {
|
|
75
|
+
req.log = loggerClass.get('api').child({ requestId: crypto.randomUUID() });
|
|
76
|
+
req.log.info('Request started');
|
|
77
|
+
next();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// โ
FASTIFY - Hook pattern
|
|
81
|
+
fastify.addHook('onRequest', async (request) => {
|
|
82
|
+
request.log = loggerClass
|
|
83
|
+
.get('api')
|
|
84
|
+
.child({ requestId: crypto.randomUUID() });
|
|
85
|
+
request.log.info('Request started');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// โ
NEXT.JS - API routes
|
|
89
|
+
export default function handler(req, res) {
|
|
90
|
+
const log = loggerClass.get('api').child({ requestId: crypto.randomUUID() });
|
|
91
|
+
log.info('API request started');
|
|
92
|
+
// Handle request...
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### **Context Logging (Copy These)**
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
// โ
CORRECT - Child loggers with context
|
|
100
|
+
const userLog = log.child({ userId: 123, sessionId: 'abc-123' });
|
|
101
|
+
const requestLog = log.child({ requestId: 'req-456', traceId: 'trace-789' });
|
|
102
|
+
const jobLog = loggerClass.get('worker').child({ jobId: job.id, attempt: 1 });
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## โ ๏ธ Common LLM Mistakes - Avoid These
|
|
106
|
+
|
|
107
|
+
### **Wrong Usage**
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// โ WRONG - Don't use console.log
|
|
111
|
+
console.log('User registered:', user);
|
|
112
|
+
|
|
113
|
+
// โ
CORRECT - Use structured logging
|
|
114
|
+
log.info('User registered', { userId: user.id, email: user.email });
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### **Missing Context**
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
// โ WRONG - Generic logging
|
|
121
|
+
log.info('Operation completed');
|
|
122
|
+
|
|
123
|
+
// โ
CORRECT - Rich context
|
|
124
|
+
log.info('User registration completed', {
|
|
125
|
+
userId: user.id,
|
|
126
|
+
email: user.email,
|
|
127
|
+
duration: Date.now() - startTime,
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### **Wrong Log Levels**
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
// โ WRONG - Wrong levels
|
|
135
|
+
log.error('User not found'); // Should be warn
|
|
136
|
+
log.debug('Payment failed'); // Should be error
|
|
137
|
+
|
|
138
|
+
// โ
CORRECT - Appropriate levels
|
|
139
|
+
log.warn('User not found', { userId: id });
|
|
140
|
+
log.error('Payment failed', { orderId, error });
|
|
141
|
+
log.info('User logged in', { userId });
|
|
142
|
+
log.debug('Cache hit', { key, value });
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### **Sensitive Data**
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
// โ WRONG - Logging sensitive data
|
|
149
|
+
log.info('User login', { password: user.password });
|
|
150
|
+
|
|
151
|
+
// โ
CORRECT - Safe logging
|
|
152
|
+
log.info('User login', {
|
|
153
|
+
userId: user.id,
|
|
154
|
+
loginMethod: 'password',
|
|
155
|
+
cardLast4: user.creditCard?.slice(-4),
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## ๐จ Error Handling Patterns
|
|
160
|
+
|
|
161
|
+
### **Startup Validation**
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
try {
|
|
165
|
+
const log = loggerClass.get();
|
|
166
|
+
log.info('โ
Logging initialized', {
|
|
167
|
+
transports: loggerClass.getActiveTransports(),
|
|
168
|
+
});
|
|
169
|
+
} catch (error) {
|
|
170
|
+
console.error('โ Logging setup failed:', error.message);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### **Global Error Handler**
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
process.on('uncaughtException', (error) => {
|
|
179
|
+
loggerClass.get('error').error('๐จ Uncaught exception', {
|
|
180
|
+
error: error.message,
|
|
181
|
+
stack: error.stack,
|
|
182
|
+
});
|
|
183
|
+
process.exit(1);
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### **Service Error Pattern**
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
async function createUser(userData) {
|
|
191
|
+
const log = loggerClass.get('user-service');
|
|
192
|
+
|
|
193
|
+
try {
|
|
194
|
+
log.debug('Creating user', { email: userData.email });
|
|
195
|
+
const user = await saveUser(userData);
|
|
196
|
+
log.info('User created', { userId: user.id });
|
|
197
|
+
return user;
|
|
198
|
+
} catch (error) {
|
|
199
|
+
log.error('User creation failed', { error: error.message });
|
|
200
|
+
throw error;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## ๐ Environment Variables
|
|
206
|
+
|
|
207
|
+
### **Basic Configuration**
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
# Auto-detected log level
|
|
211
|
+
BLOOM_LOGGER_LEVEL=debug|info|warn|error # Default: auto-detected
|
|
212
|
+
BLOOM_LOGGER_SCOPE=minimal|full # Default: minimal
|
|
213
|
+
|
|
214
|
+
# Service identification
|
|
215
|
+
BLOOM_SERVICE_NAME=my-app # Default: package.json name
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### **Transport Control**
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
# Database (auto-enabled if DATABASE_URL exists)
|
|
222
|
+
DATABASE_URL=postgres://user:pass@localhost/app
|
|
223
|
+
|
|
224
|
+
# HTTP (Datadog, Elasticsearch, etc.)
|
|
225
|
+
BLOOM_LOGGER_HTTP_URL=https://logs.datadog.com/api/v1/logs
|
|
226
|
+
|
|
227
|
+
# Webhook (Slack alerts)
|
|
228
|
+
BLOOM_LOGGER_WEBHOOK_URL=https://hooks.slack.com/services/xxx
|
|
229
|
+
BLOOM_LOGGER_WEBHOOK_LEVEL=error # Default: error only
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## ๐ Production Deployment
|
|
233
|
+
|
|
234
|
+
### **Environment Setup**
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# โ
Production settings
|
|
238
|
+
NODE_ENV=production
|
|
239
|
+
BLOOM_LOGGER_SCOPE=minimal
|
|
240
|
+
BLOOM_LOGGER_LEVEL=warn
|
|
241
|
+
|
|
242
|
+
# โ
Required transports
|
|
243
|
+
DATABASE_URL=postgres://prod-user:pass@prod-db/app
|
|
244
|
+
BLOOM_LOGGER_HTTP_URL=https://logs.datadog.com/api/v1/logs
|
|
245
|
+
BLOOM_LOGGER_WEBHOOK_URL=https://hooks.slack.com/services/xxx
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### **Security Validation**
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
// โ
Startup validation
|
|
252
|
+
const log = loggerClass.get();
|
|
253
|
+
const config = loggerClass.getConfig();
|
|
254
|
+
|
|
255
|
+
console.log('โ
Logging validation passed');
|
|
256
|
+
console.log(`Transports: ${loggerClass.getActiveTransports().join(', ')}`);
|
|
257
|
+
|
|
258
|
+
if (config.environment === 'production' && config.scope !== 'minimal') {
|
|
259
|
+
console.warn('โ ๏ธ Production should use minimal scope');
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## ๐ Complete API Reference
|
|
264
|
+
|
|
265
|
+
### **Core Function**
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
const log = loggerClass.get(); // Main logger
|
|
269
|
+
const log = loggerClass.get('component'); // Component logger
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### **Log Methods**
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
log.info(message, meta?); // Normal events
|
|
276
|
+
log.warn(message, meta?); // Potential issues
|
|
277
|
+
log.error(message, meta?); // Errors (triggers alerts)
|
|
278
|
+
log.debug(message, meta?); // Development info
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### **Context Methods**
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
log.child(bindings); // Add context
|
|
285
|
+
log.flush(); // Ensure written
|
|
286
|
+
log.close(); // Close transports
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### **Utility Methods**
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
loggerClass.getActiveTransports(); // ['console', 'file', 'database']
|
|
293
|
+
loggerClass.gethasTransport('database'); // true/false
|
|
294
|
+
loggerClass.getConfig(); // Debug configuration
|
|
295
|
+
loggerClass.getclear(); // Clear state (testing)
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## ๐ก Simple Examples
|
|
299
|
+
|
|
300
|
+
### **API Logging**
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
app.post('/users', async (req, res) => {
|
|
304
|
+
const log = loggerClass.get('api').child({ requestId: crypto.randomUUID() });
|
|
305
|
+
|
|
306
|
+
try {
|
|
307
|
+
log.info('Creating user', { email: req.body.email });
|
|
308
|
+
const user = await createUser(req.body);
|
|
309
|
+
log.info('User created', { userId: user.id });
|
|
310
|
+
res.json({ user });
|
|
311
|
+
} catch (error) {
|
|
312
|
+
log.error('User creation failed', { error: error.message });
|
|
313
|
+
res.status(500).json({ error: 'Failed to create user' });
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### **Background Job**
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
async function processJob(job) {
|
|
322
|
+
const log = loggerClass.get('worker').child({ jobId: job.id });
|
|
323
|
+
|
|
324
|
+
log.info('Job started');
|
|
325
|
+
|
|
326
|
+
try {
|
|
327
|
+
await processData(job.data);
|
|
328
|
+
log.info('Job completed');
|
|
329
|
+
} catch (error) {
|
|
330
|
+
log.error('Job failed', { error: error.message });
|
|
331
|
+
throw error;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### **Database Service**
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
class DatabaseService {
|
|
340
|
+
constructor() {
|
|
341
|
+
this.log = loggerClass.get('database');
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
async connect() {
|
|
345
|
+
this.log.info('Connecting to database');
|
|
346
|
+
|
|
347
|
+
try {
|
|
348
|
+
this.db = await createConnection();
|
|
349
|
+
this.log.info('Database connected');
|
|
350
|
+
} catch (error) {
|
|
351
|
+
this.log.error('Connection failed', { error: error.message });
|
|
352
|
+
throw error;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## ๐ง External Services
|
|
359
|
+
|
|
360
|
+
### **Datadog**
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
BLOOM_LOGGER_HTTP_URL=https://http-intake.logs.datadoghq.com/api/v1/input/YOUR_API_KEY
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### **Slack Alerts**
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
BLOOM_LOGGER_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
## ๐ Output Examples
|
|
373
|
+
|
|
374
|
+
### **Development Console**
|
|
375
|
+
|
|
376
|
+
```
|
|
377
|
+
10:30:45 ๐ Server ready [api]
|
|
378
|
+
10:30:46 โ ERROR Payment failed [payment]
|
|
379
|
+
Card declined
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### **Production File (JSON)**
|
|
383
|
+
|
|
384
|
+
```json
|
|
385
|
+
{"timestamp":"2024-01-15T10:30:45.123Z","level":"info","message":"Server ready","component":"api"}
|
|
386
|
+
{"timestamp":"2024-01-15T10:30:46.456Z","level":"error","message":"Payment failed","component":"payment"}
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
## ๐งช Testing
|
|
390
|
+
|
|
391
|
+
```typescript
|
|
392
|
+
import { loggerClass } from '@bloomneo/appkit/logger';
|
|
393
|
+
|
|
394
|
+
describe('Payment Service', () => {
|
|
395
|
+
afterEach(async () => {
|
|
396
|
+
await loggerClass.getclear(); // Clear state between tests
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
test('should log payment success', async () => {
|
|
400
|
+
const log = loggerClass.get('test');
|
|
401
|
+
log.info('Test started');
|
|
402
|
+
|
|
403
|
+
const result = await processPayment('order-123', 99.99);
|
|
404
|
+
expect(result.success).toBe(true);
|
|
405
|
+
});
|
|
406
|
+
});
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
## ๐ Performance
|
|
410
|
+
|
|
411
|
+
- **Startup**: < 10ms initialization
|
|
412
|
+
- **Memory**: < 5MB baseline usage
|
|
413
|
+
- **Throughput**: 10,000+ logs/second
|
|
414
|
+
- **File I/O**: Batched writes, no blocking
|
|
415
|
+
- **Network**: Smart batching for external services
|
|
416
|
+
|
|
417
|
+
## ๐ TypeScript Support
|
|
418
|
+
|
|
419
|
+
```typescript
|
|
420
|
+
import type { LoggingConfig, LogMeta, Logger } from '@bloomneo/appkit/logging';
|
|
421
|
+
|
|
422
|
+
const log: Logger = loggerClass.get();
|
|
423
|
+
const meta: LogMeta = { userId: 123, action: 'login' };
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
## ๐ License
|
|
427
|
+
|
|
428
|
+
MIT ยฉ [Bloomneo](https://github.com/bloomneo)
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
<p align="center">
|
|
433
|
+
<strong>Built with โค๏ธ by the <a href="https://github.com/bloomneo/appkit">Bloomneo Team</a></strong><br>
|
|
434
|
+
Because logging should be simple, not a PhD thesis.
|
|
435
|
+
</p>
|