@objectstack/core 1.0.4 → 1.0.5
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/.turbo/turbo-build.log +58 -0
- package/CHANGELOG.md +12 -0
- package/dist/index.cjs +4294 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1777 -0
- package/dist/index.d.ts +1776 -21
- package/dist/index.js +4246 -23
- package/dist/index.js.map +1 -0
- package/package.json +4 -4
- package/tsconfig.json +1 -3
- package/dist/api-registry-plugin.d.ts +0 -54
- package/dist/api-registry-plugin.d.ts.map +0 -1
- package/dist/api-registry-plugin.js +0 -53
- package/dist/api-registry-plugin.test.d.ts +0 -2
- package/dist/api-registry-plugin.test.d.ts.map +0 -1
- package/dist/api-registry-plugin.test.js +0 -334
- package/dist/api-registry.d.ts +0 -259
- package/dist/api-registry.d.ts.map +0 -1
- package/dist/api-registry.js +0 -600
- package/dist/api-registry.test.d.ts +0 -2
- package/dist/api-registry.test.d.ts.map +0 -1
- package/dist/api-registry.test.js +0 -957
- package/dist/contracts/data-engine.d.ts +0 -62
- package/dist/contracts/data-engine.d.ts.map +0 -1
- package/dist/contracts/data-engine.js +0 -1
- package/dist/contracts/http-server.d.ts +0 -119
- package/dist/contracts/http-server.d.ts.map +0 -1
- package/dist/contracts/http-server.js +0 -11
- package/dist/contracts/logger.d.ts +0 -63
- package/dist/contracts/logger.d.ts.map +0 -1
- package/dist/contracts/logger.js +0 -1
- package/dist/dependency-resolver.d.ts +0 -62
- package/dist/dependency-resolver.d.ts.map +0 -1
- package/dist/dependency-resolver.js +0 -317
- package/dist/dependency-resolver.test.d.ts +0 -2
- package/dist/dependency-resolver.test.d.ts.map +0 -1
- package/dist/dependency-resolver.test.js +0 -241
- package/dist/health-monitor.d.ts +0 -65
- package/dist/health-monitor.d.ts.map +0 -1
- package/dist/health-monitor.js +0 -269
- package/dist/health-monitor.test.d.ts +0 -2
- package/dist/health-monitor.test.d.ts.map +0 -1
- package/dist/health-monitor.test.js +0 -68
- package/dist/hot-reload.d.ts +0 -79
- package/dist/hot-reload.d.ts.map +0 -1
- package/dist/hot-reload.js +0 -313
- package/dist/index.d.ts.map +0 -1
- package/dist/kernel-base.d.ts +0 -84
- package/dist/kernel-base.d.ts.map +0 -1
- package/dist/kernel-base.js +0 -219
- package/dist/kernel.d.ts +0 -113
- package/dist/kernel.d.ts.map +0 -1
- package/dist/kernel.js +0 -472
- package/dist/kernel.test.d.ts +0 -2
- package/dist/kernel.test.d.ts.map +0 -1
- package/dist/kernel.test.js +0 -414
- package/dist/lite-kernel.d.ts +0 -55
- package/dist/lite-kernel.d.ts.map +0 -1
- package/dist/lite-kernel.js +0 -112
- package/dist/lite-kernel.test.d.ts +0 -2
- package/dist/lite-kernel.test.d.ts.map +0 -1
- package/dist/lite-kernel.test.js +0 -161
- package/dist/logger.d.ts +0 -71
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js +0 -312
- package/dist/logger.test.d.ts +0 -2
- package/dist/logger.test.d.ts.map +0 -1
- package/dist/logger.test.js +0 -92
- package/dist/plugin-loader.d.ts +0 -164
- package/dist/plugin-loader.d.ts.map +0 -1
- package/dist/plugin-loader.js +0 -319
- package/dist/plugin-loader.test.d.ts +0 -2
- package/dist/plugin-loader.test.d.ts.map +0 -1
- package/dist/plugin-loader.test.js +0 -348
- package/dist/qa/adapter.d.ts +0 -14
- package/dist/qa/adapter.d.ts.map +0 -1
- package/dist/qa/adapter.js +0 -1
- package/dist/qa/http-adapter.d.ts +0 -16
- package/dist/qa/http-adapter.d.ts.map +0 -1
- package/dist/qa/http-adapter.js +0 -107
- package/dist/qa/index.d.ts +0 -4
- package/dist/qa/index.d.ts.map +0 -1
- package/dist/qa/index.js +0 -3
- package/dist/qa/runner.d.ts +0 -27
- package/dist/qa/runner.d.ts.map +0 -1
- package/dist/qa/runner.js +0 -157
- package/dist/security/index.d.ts +0 -17
- package/dist/security/index.d.ts.map +0 -1
- package/dist/security/index.js +0 -17
- package/dist/security/permission-manager.d.ts +0 -96
- package/dist/security/permission-manager.d.ts.map +0 -1
- package/dist/security/permission-manager.js +0 -235
- package/dist/security/permission-manager.test.d.ts +0 -2
- package/dist/security/permission-manager.test.d.ts.map +0 -1
- package/dist/security/permission-manager.test.js +0 -220
- package/dist/security/plugin-config-validator.d.ts +0 -79
- package/dist/security/plugin-config-validator.d.ts.map +0 -1
- package/dist/security/plugin-config-validator.js +0 -166
- package/dist/security/plugin-config-validator.test.d.ts +0 -2
- package/dist/security/plugin-config-validator.test.d.ts.map +0 -1
- package/dist/security/plugin-config-validator.test.js +0 -223
- package/dist/security/plugin-permission-enforcer.d.ts +0 -154
- package/dist/security/plugin-permission-enforcer.d.ts.map +0 -1
- package/dist/security/plugin-permission-enforcer.js +0 -323
- package/dist/security/plugin-permission-enforcer.test.d.ts +0 -2
- package/dist/security/plugin-permission-enforcer.test.d.ts.map +0 -1
- package/dist/security/plugin-permission-enforcer.test.js +0 -205
- package/dist/security/plugin-signature-verifier.d.ts +0 -96
- package/dist/security/plugin-signature-verifier.d.ts.map +0 -1
- package/dist/security/plugin-signature-verifier.js +0 -250
- package/dist/security/sandbox-runtime.d.ts +0 -115
- package/dist/security/sandbox-runtime.d.ts.map +0 -1
- package/dist/security/sandbox-runtime.js +0 -311
- package/dist/security/security-scanner.d.ts +0 -92
- package/dist/security/security-scanner.d.ts.map +0 -1
- package/dist/security/security-scanner.js +0 -273
- package/dist/types.d.ts +0 -89
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -1
- package/dist/utils/env.d.ts +0 -20
- package/dist/utils/env.d.ts.map +0 -1
- package/dist/utils/env.js +0 -46
- package/dist/utils/env.test.d.ts +0 -2
- package/dist/utils/env.test.d.ts.map +0 -1
- package/dist/utils/env.test.js +0 -52
package/dist/lite-kernel.test.js
DELETED
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
-
import { LiteKernel } from './lite-kernel';
|
|
3
|
-
describe('LiteKernel with Configurable Logger', () => {
|
|
4
|
-
let kernel;
|
|
5
|
-
beforeEach(() => {
|
|
6
|
-
kernel = new LiteKernel();
|
|
7
|
-
});
|
|
8
|
-
describe('Logger Configuration', () => {
|
|
9
|
-
it('should create kernel with default logger', () => {
|
|
10
|
-
expect(kernel).toBeDefined();
|
|
11
|
-
});
|
|
12
|
-
it('should create kernel with custom logger config', async () => {
|
|
13
|
-
const customKernel = new LiteKernel({
|
|
14
|
-
logger: {
|
|
15
|
-
level: 'debug',
|
|
16
|
-
format: 'pretty',
|
|
17
|
-
sourceLocation: true
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
expect(customKernel).toBeDefined();
|
|
21
|
-
// Cleanup
|
|
22
|
-
await customKernel.bootstrap();
|
|
23
|
-
await customKernel.shutdown();
|
|
24
|
-
});
|
|
25
|
-
it('should create kernel with file logging config', async () => {
|
|
26
|
-
const fileKernel = new LiteKernel({
|
|
27
|
-
logger: {
|
|
28
|
-
level: 'info',
|
|
29
|
-
format: 'json',
|
|
30
|
-
file: '/tmp/test-kernel.log'
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
expect(fileKernel).toBeDefined();
|
|
34
|
-
// Cleanup
|
|
35
|
-
await fileKernel.bootstrap();
|
|
36
|
-
await fileKernel.shutdown();
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
describe('Plugin Context Logger', () => {
|
|
40
|
-
it('should provide logger to plugins', async () => {
|
|
41
|
-
let loggerReceived = false;
|
|
42
|
-
const testPlugin = {
|
|
43
|
-
name: 'test-plugin',
|
|
44
|
-
init: async (ctx) => {
|
|
45
|
-
if (ctx.logger) {
|
|
46
|
-
loggerReceived = true;
|
|
47
|
-
ctx.logger.info('Plugin initialized', { plugin: 'test-plugin' });
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
kernel.use(testPlugin);
|
|
52
|
-
await kernel.bootstrap();
|
|
53
|
-
expect(loggerReceived).toBe(true);
|
|
54
|
-
await kernel.shutdown();
|
|
55
|
-
});
|
|
56
|
-
it('should allow plugins to use all log levels', async () => {
|
|
57
|
-
const logCalls = [];
|
|
58
|
-
const loggingPlugin = {
|
|
59
|
-
name: 'logging-plugin',
|
|
60
|
-
init: async (ctx) => {
|
|
61
|
-
ctx.logger.debug('Debug message');
|
|
62
|
-
logCalls.push('debug');
|
|
63
|
-
ctx.logger.info('Info message');
|
|
64
|
-
logCalls.push('info');
|
|
65
|
-
ctx.logger.warn('Warning message');
|
|
66
|
-
logCalls.push('warn');
|
|
67
|
-
ctx.logger.error('Error message');
|
|
68
|
-
logCalls.push('error');
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
kernel.use(loggingPlugin);
|
|
72
|
-
await kernel.bootstrap();
|
|
73
|
-
expect(logCalls).toContain('debug');
|
|
74
|
-
expect(logCalls).toContain('info');
|
|
75
|
-
expect(logCalls).toContain('warn');
|
|
76
|
-
expect(logCalls).toContain('error');
|
|
77
|
-
await kernel.shutdown();
|
|
78
|
-
});
|
|
79
|
-
it('should support metadata in logs', async () => {
|
|
80
|
-
const metadataPlugin = {
|
|
81
|
-
name: 'metadata-plugin',
|
|
82
|
-
init: async (ctx) => {
|
|
83
|
-
ctx.logger.info('User action', {
|
|
84
|
-
userId: '123',
|
|
85
|
-
action: 'create',
|
|
86
|
-
resource: 'document'
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
kernel.use(metadataPlugin);
|
|
91
|
-
await kernel.bootstrap();
|
|
92
|
-
await kernel.shutdown();
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
describe('Kernel Lifecycle Logging', () => {
|
|
96
|
-
it('should log bootstrap process', async () => {
|
|
97
|
-
const plugin = {
|
|
98
|
-
name: 'lifecycle-test',
|
|
99
|
-
init: async () => {
|
|
100
|
-
// Init logic
|
|
101
|
-
},
|
|
102
|
-
start: async () => {
|
|
103
|
-
// Start logic
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
kernel.use(plugin);
|
|
107
|
-
await kernel.bootstrap();
|
|
108
|
-
expect(kernel.isRunning()).toBe(true);
|
|
109
|
-
await kernel.shutdown();
|
|
110
|
-
});
|
|
111
|
-
it('should log shutdown process', async () => {
|
|
112
|
-
const plugin = {
|
|
113
|
-
name: 'shutdown-test',
|
|
114
|
-
init: async () => { },
|
|
115
|
-
destroy: async () => {
|
|
116
|
-
// Cleanup
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
kernel.use(plugin);
|
|
120
|
-
await kernel.bootstrap();
|
|
121
|
-
await kernel.shutdown();
|
|
122
|
-
expect(kernel.getState()).toBe('stopped');
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
describe('Environment Compatibility', () => {
|
|
126
|
-
it('should work in Node.js environment', async () => {
|
|
127
|
-
const nodeKernel = new LiteKernel({
|
|
128
|
-
logger: {
|
|
129
|
-
level: 'info',
|
|
130
|
-
format: 'json'
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
const plugin = {
|
|
134
|
-
name: 'node-test',
|
|
135
|
-
init: async (ctx) => {
|
|
136
|
-
ctx.logger.info('Running in Node.js');
|
|
137
|
-
}
|
|
138
|
-
};
|
|
139
|
-
nodeKernel.use(plugin);
|
|
140
|
-
await nodeKernel.bootstrap();
|
|
141
|
-
await nodeKernel.shutdown();
|
|
142
|
-
});
|
|
143
|
-
it('should support browser-friendly logging', async () => {
|
|
144
|
-
const browserKernel = new LiteKernel({
|
|
145
|
-
logger: {
|
|
146
|
-
level: 'info',
|
|
147
|
-
format: 'pretty'
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
const plugin = {
|
|
151
|
-
name: 'browser-test',
|
|
152
|
-
init: async (ctx) => {
|
|
153
|
-
ctx.logger.info('Browser-friendly format');
|
|
154
|
-
}
|
|
155
|
-
};
|
|
156
|
-
browserKernel.use(plugin);
|
|
157
|
-
await browserKernel.bootstrap();
|
|
158
|
-
await browserKernel.shutdown();
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
});
|
package/dist/logger.d.ts
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import type { LoggerConfig } from '@objectstack/spec/system';
|
|
2
|
-
import type { Logger } from '@objectstack/spec/contracts';
|
|
3
|
-
/**
|
|
4
|
-
* Universal Logger Implementation
|
|
5
|
-
*
|
|
6
|
-
* A configurable logger that works in both browser and Node.js environments.
|
|
7
|
-
* - Node.js: Uses Pino for high-performance structured logging
|
|
8
|
-
* - Browser: Simple console-based implementation
|
|
9
|
-
*
|
|
10
|
-
* Features:
|
|
11
|
-
* - Structured logging with multiple formats (json, text, pretty)
|
|
12
|
-
* - Log level filtering
|
|
13
|
-
* - Sensitive data redaction
|
|
14
|
-
* - File logging with rotation (Node.js only via Pino)
|
|
15
|
-
* - Browser console integration
|
|
16
|
-
* - Distributed tracing support (traceId, spanId)
|
|
17
|
-
*/
|
|
18
|
-
export declare class ObjectLogger implements Logger {
|
|
19
|
-
private config;
|
|
20
|
-
private isNode;
|
|
21
|
-
private pinoLogger?;
|
|
22
|
-
private pinoInstance?;
|
|
23
|
-
private require?;
|
|
24
|
-
constructor(config?: Partial<LoggerConfig>);
|
|
25
|
-
/**
|
|
26
|
-
* Initialize Pino logger for Node.js
|
|
27
|
-
*/
|
|
28
|
-
private initPinoLogger;
|
|
29
|
-
/**
|
|
30
|
-
* Redact sensitive keys from context object (for browser)
|
|
31
|
-
*/
|
|
32
|
-
private redactSensitive;
|
|
33
|
-
/**
|
|
34
|
-
* Format log entry for browser
|
|
35
|
-
*/
|
|
36
|
-
private formatBrowserLog;
|
|
37
|
-
/**
|
|
38
|
-
* Log using browser console
|
|
39
|
-
*/
|
|
40
|
-
private logBrowser;
|
|
41
|
-
/**
|
|
42
|
-
* Public logging methods
|
|
43
|
-
*/
|
|
44
|
-
debug(message: string, meta?: Record<string, any>): void;
|
|
45
|
-
info(message: string, meta?: Record<string, any>): void;
|
|
46
|
-
warn(message: string, meta?: Record<string, any>): void;
|
|
47
|
-
error(message: string, errorOrMeta?: Error | Record<string, any>, meta?: Record<string, any>): void;
|
|
48
|
-
fatal(message: string, errorOrMeta?: Error | Record<string, any>, meta?: Record<string, any>): void;
|
|
49
|
-
/**
|
|
50
|
-
* Create a child logger with additional context
|
|
51
|
-
* Note: Child loggers share the parent's Pino instance
|
|
52
|
-
*/
|
|
53
|
-
child(context: Record<string, any>): ObjectLogger;
|
|
54
|
-
/**
|
|
55
|
-
* Set trace context for distributed tracing
|
|
56
|
-
*/
|
|
57
|
-
withTrace(traceId: string, spanId?: string): ObjectLogger;
|
|
58
|
-
/**
|
|
59
|
-
* Cleanup resources
|
|
60
|
-
*/
|
|
61
|
-
destroy(): Promise<void>;
|
|
62
|
-
/**
|
|
63
|
-
* Compatibility method for console.log usage
|
|
64
|
-
*/
|
|
65
|
-
log(message: string, ...args: any[]): void;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Create a logger instance
|
|
69
|
-
*/
|
|
70
|
-
export declare function createLogger(config?: Partial<LoggerConfig>): ObjectLogger;
|
|
71
|
-
//# sourceMappingURL=logger.d.ts.map
|
package/dist/logger.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAY,MAAM,0BAA0B,CAAC;AACvE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAG1D;;;;;;;;;;;;;;GAcG;AACH,qBAAa,YAAa,YAAW,MAAM;IACvC,OAAO,CAAC,MAAM,CAAkJ;IAChK,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,UAAU,CAAC,CAAM;IACzB,OAAO,CAAC,YAAY,CAAC,CAAM;IAC3B,OAAO,CAAC,OAAO,CAAC,CAAM;gBAEV,MAAM,GAAE,OAAO,CAAC,YAAY,CAAM;IAwB9C;;OAEG;IACH,OAAO,CAAC,cAAc;IAuGtB;;OAEG;IACH,OAAO,CAAC,eAAe;IAqBvB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAuCxB;;OAEG;IACH,OAAO,CAAC,UAAU;IAelB;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQxD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQvD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQvD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAmBnG,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAmBnG;;;OAGG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,YAAY;IAYjD;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY;IAIzD;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ9B;;OAEG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;CAG7C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAEzE"}
|
package/dist/logger.js
DELETED
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
import { isNode } from './utils/env.js';
|
|
2
|
-
/**
|
|
3
|
-
* Universal Logger Implementation
|
|
4
|
-
*
|
|
5
|
-
* A configurable logger that works in both browser and Node.js environments.
|
|
6
|
-
* - Node.js: Uses Pino for high-performance structured logging
|
|
7
|
-
* - Browser: Simple console-based implementation
|
|
8
|
-
*
|
|
9
|
-
* Features:
|
|
10
|
-
* - Structured logging with multiple formats (json, text, pretty)
|
|
11
|
-
* - Log level filtering
|
|
12
|
-
* - Sensitive data redaction
|
|
13
|
-
* - File logging with rotation (Node.js only via Pino)
|
|
14
|
-
* - Browser console integration
|
|
15
|
-
* - Distributed tracing support (traceId, spanId)
|
|
16
|
-
*/
|
|
17
|
-
export class ObjectLogger {
|
|
18
|
-
constructor(config = {}) {
|
|
19
|
-
// Detect runtime environment
|
|
20
|
-
this.isNode = isNode;
|
|
21
|
-
// Set defaults
|
|
22
|
-
this.config = {
|
|
23
|
-
name: config.name,
|
|
24
|
-
level: config.level ?? 'info',
|
|
25
|
-
format: config.format ?? (this.isNode ? 'json' : 'pretty'),
|
|
26
|
-
redact: config.redact ?? ['password', 'token', 'secret', 'key'],
|
|
27
|
-
sourceLocation: config.sourceLocation ?? false,
|
|
28
|
-
file: config.file,
|
|
29
|
-
rotation: config.rotation ?? {
|
|
30
|
-
maxSize: '10m',
|
|
31
|
-
maxFiles: 5
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
// Initialize Pino logger for Node.js
|
|
35
|
-
if (this.isNode) {
|
|
36
|
-
this.initPinoLogger();
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Initialize Pino logger for Node.js
|
|
41
|
-
*/
|
|
42
|
-
initPinoLogger() {
|
|
43
|
-
if (!this.isNode)
|
|
44
|
-
return;
|
|
45
|
-
try {
|
|
46
|
-
// Create require function dynamically for Node.js (avoids bundling issues in browser)
|
|
47
|
-
// @ts-ignore - dynamic import of Node.js module
|
|
48
|
-
const { createRequire } = eval('require("module")');
|
|
49
|
-
this.require = createRequire(import.meta.url);
|
|
50
|
-
// Synchronous import for Pino using createRequire (works in ESM)
|
|
51
|
-
const pino = this.require('pino');
|
|
52
|
-
// Build Pino options
|
|
53
|
-
const pinoOptions = {
|
|
54
|
-
level: this.config.level,
|
|
55
|
-
redact: {
|
|
56
|
-
paths: this.config.redact,
|
|
57
|
-
censor: '***REDACTED***'
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
// Add name if provided
|
|
61
|
-
if (this.config.name) {
|
|
62
|
-
pinoOptions.name = this.config.name;
|
|
63
|
-
}
|
|
64
|
-
// Transport configuration for pretty printing or file output
|
|
65
|
-
const targets = [];
|
|
66
|
-
// Console transport
|
|
67
|
-
if (this.config.format === 'pretty') {
|
|
68
|
-
// Check if pino-pretty is available
|
|
69
|
-
let hasPretty = false;
|
|
70
|
-
try {
|
|
71
|
-
this.require.resolve('pino-pretty');
|
|
72
|
-
hasPretty = true;
|
|
73
|
-
}
|
|
74
|
-
catch (e) {
|
|
75
|
-
// ignore
|
|
76
|
-
}
|
|
77
|
-
if (hasPretty) {
|
|
78
|
-
targets.push({
|
|
79
|
-
target: 'pino-pretty',
|
|
80
|
-
options: {
|
|
81
|
-
colorize: true,
|
|
82
|
-
translateTime: 'SYS:standard',
|
|
83
|
-
ignore: 'pid,hostname'
|
|
84
|
-
},
|
|
85
|
-
level: this.config.level
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
console.warn('[Logger] pino-pretty not found. Install it for pretty logging: pnpm add -D pino-pretty');
|
|
90
|
-
// Fallback to text/simple
|
|
91
|
-
targets.push({
|
|
92
|
-
target: 'pino/file',
|
|
93
|
-
options: { destination: 1 },
|
|
94
|
-
level: this.config.level
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
else if (this.config.format === 'json') {
|
|
99
|
-
// JSON to stdout
|
|
100
|
-
targets.push({
|
|
101
|
-
target: 'pino/file',
|
|
102
|
-
options: { destination: 1 }, // stdout
|
|
103
|
-
level: this.config.level
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
// text format (simple)
|
|
108
|
-
targets.push({
|
|
109
|
-
target: 'pino/file',
|
|
110
|
-
options: { destination: 1 },
|
|
111
|
-
level: this.config.level
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
// File transport (if configured)
|
|
115
|
-
if (this.config.file) {
|
|
116
|
-
targets.push({
|
|
117
|
-
target: 'pino/file',
|
|
118
|
-
options: {
|
|
119
|
-
destination: this.config.file,
|
|
120
|
-
mkdir: true
|
|
121
|
-
},
|
|
122
|
-
level: this.config.level
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
// Create transport
|
|
126
|
-
if (targets.length > 0) {
|
|
127
|
-
pinoOptions.transport = targets.length === 1 ? targets[0] : { targets };
|
|
128
|
-
}
|
|
129
|
-
// Create Pino logger
|
|
130
|
-
this.pinoInstance = pino(pinoOptions);
|
|
131
|
-
this.pinoLogger = this.pinoInstance;
|
|
132
|
-
}
|
|
133
|
-
catch (error) {
|
|
134
|
-
// Fallback to console if Pino is not available
|
|
135
|
-
console.warn('[Logger] Pino not available, falling back to console:', error);
|
|
136
|
-
this.pinoLogger = null;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* Redact sensitive keys from context object (for browser)
|
|
141
|
-
*/
|
|
142
|
-
redactSensitive(obj) {
|
|
143
|
-
if (!obj || typeof obj !== 'object')
|
|
144
|
-
return obj;
|
|
145
|
-
const redacted = Array.isArray(obj) ? [...obj] : { ...obj };
|
|
146
|
-
for (const key in redacted) {
|
|
147
|
-
const lowerKey = key.toLowerCase();
|
|
148
|
-
const shouldRedact = this.config.redact.some((pattern) => lowerKey.includes(pattern.toLowerCase()));
|
|
149
|
-
if (shouldRedact) {
|
|
150
|
-
redacted[key] = '***REDACTED***';
|
|
151
|
-
}
|
|
152
|
-
else if (typeof redacted[key] === 'object' && redacted[key] !== null) {
|
|
153
|
-
redacted[key] = this.redactSensitive(redacted[key]);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
return redacted;
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Format log entry for browser
|
|
160
|
-
*/
|
|
161
|
-
formatBrowserLog(level, message, context) {
|
|
162
|
-
if (this.config.format === 'json') {
|
|
163
|
-
return JSON.stringify({
|
|
164
|
-
timestamp: new Date().toISOString(),
|
|
165
|
-
level,
|
|
166
|
-
message,
|
|
167
|
-
...context
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
if (this.config.format === 'text') {
|
|
171
|
-
const parts = [new Date().toISOString(), level.toUpperCase(), message];
|
|
172
|
-
if (context && Object.keys(context).length > 0) {
|
|
173
|
-
parts.push(JSON.stringify(context));
|
|
174
|
-
}
|
|
175
|
-
return parts.join(' | ');
|
|
176
|
-
}
|
|
177
|
-
// Pretty format
|
|
178
|
-
const levelColors = {
|
|
179
|
-
debug: '\x1b[36m', // Cyan
|
|
180
|
-
info: '\x1b[32m', // Green
|
|
181
|
-
warn: '\x1b[33m', // Yellow
|
|
182
|
-
error: '\x1b[31m', // Red
|
|
183
|
-
fatal: '\x1b[35m', // Magenta
|
|
184
|
-
silent: ''
|
|
185
|
-
};
|
|
186
|
-
const reset = '\x1b[0m';
|
|
187
|
-
const color = levelColors[level] || '';
|
|
188
|
-
let output = `${color}[${level.toUpperCase()}]${reset} ${message}`;
|
|
189
|
-
if (context && Object.keys(context).length > 0) {
|
|
190
|
-
output += ` ${JSON.stringify(context, null, 2)}`;
|
|
191
|
-
}
|
|
192
|
-
return output;
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Log using browser console
|
|
196
|
-
*/
|
|
197
|
-
logBrowser(level, message, context, error) {
|
|
198
|
-
const redactedContext = context ? this.redactSensitive(context) : undefined;
|
|
199
|
-
const mergedContext = error ? { ...redactedContext, error: { message: error.message, stack: error.stack } } : redactedContext;
|
|
200
|
-
const formatted = this.formatBrowserLog(level, message, mergedContext);
|
|
201
|
-
const consoleMethod = level === 'debug' ? 'debug' :
|
|
202
|
-
level === 'info' ? 'log' :
|
|
203
|
-
level === 'warn' ? 'warn' :
|
|
204
|
-
level === 'error' || level === 'fatal' ? 'error' :
|
|
205
|
-
'log';
|
|
206
|
-
console[consoleMethod](formatted);
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* Public logging methods
|
|
210
|
-
*/
|
|
211
|
-
debug(message, meta) {
|
|
212
|
-
if (this.isNode && this.pinoLogger) {
|
|
213
|
-
this.pinoLogger.debug(meta || {}, message);
|
|
214
|
-
}
|
|
215
|
-
else {
|
|
216
|
-
this.logBrowser('debug', message, meta);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
info(message, meta) {
|
|
220
|
-
if (this.isNode && this.pinoLogger) {
|
|
221
|
-
this.pinoLogger.info(meta || {}, message);
|
|
222
|
-
}
|
|
223
|
-
else {
|
|
224
|
-
this.logBrowser('info', message, meta);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
warn(message, meta) {
|
|
228
|
-
if (this.isNode && this.pinoLogger) {
|
|
229
|
-
this.pinoLogger.warn(meta || {}, message);
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
this.logBrowser('warn', message, meta);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
error(message, errorOrMeta, meta) {
|
|
236
|
-
let error;
|
|
237
|
-
let context = {};
|
|
238
|
-
if (errorOrMeta instanceof Error) {
|
|
239
|
-
error = errorOrMeta;
|
|
240
|
-
context = meta || {};
|
|
241
|
-
}
|
|
242
|
-
else {
|
|
243
|
-
context = errorOrMeta || {};
|
|
244
|
-
}
|
|
245
|
-
if (this.isNode && this.pinoLogger) {
|
|
246
|
-
const errorContext = error ? { err: error, ...context } : context;
|
|
247
|
-
this.pinoLogger.error(errorContext, message);
|
|
248
|
-
}
|
|
249
|
-
else {
|
|
250
|
-
this.logBrowser('error', message, context, error);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
fatal(message, errorOrMeta, meta) {
|
|
254
|
-
let error;
|
|
255
|
-
let context = {};
|
|
256
|
-
if (errorOrMeta instanceof Error) {
|
|
257
|
-
error = errorOrMeta;
|
|
258
|
-
context = meta || {};
|
|
259
|
-
}
|
|
260
|
-
else {
|
|
261
|
-
context = errorOrMeta || {};
|
|
262
|
-
}
|
|
263
|
-
if (this.isNode && this.pinoLogger) {
|
|
264
|
-
const errorContext = error ? { err: error, ...context } : context;
|
|
265
|
-
this.pinoLogger.fatal(errorContext, message);
|
|
266
|
-
}
|
|
267
|
-
else {
|
|
268
|
-
this.logBrowser('fatal', message, context, error);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* Create a child logger with additional context
|
|
273
|
-
* Note: Child loggers share the parent's Pino instance
|
|
274
|
-
*/
|
|
275
|
-
child(context) {
|
|
276
|
-
const childLogger = new ObjectLogger(this.config);
|
|
277
|
-
// For Node.js with Pino, create a Pino child logger
|
|
278
|
-
if (this.isNode && this.pinoInstance) {
|
|
279
|
-
childLogger.pinoLogger = this.pinoInstance.child(context);
|
|
280
|
-
childLogger.pinoInstance = this.pinoInstance;
|
|
281
|
-
}
|
|
282
|
-
return childLogger;
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* Set trace context for distributed tracing
|
|
286
|
-
*/
|
|
287
|
-
withTrace(traceId, spanId) {
|
|
288
|
-
return this.child({ traceId, spanId });
|
|
289
|
-
}
|
|
290
|
-
/**
|
|
291
|
-
* Cleanup resources
|
|
292
|
-
*/
|
|
293
|
-
async destroy() {
|
|
294
|
-
if (this.pinoLogger && this.pinoLogger.flush) {
|
|
295
|
-
await new Promise((resolve) => {
|
|
296
|
-
this.pinoLogger.flush(() => resolve());
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
/**
|
|
301
|
-
* Compatibility method for console.log usage
|
|
302
|
-
*/
|
|
303
|
-
log(message, ...args) {
|
|
304
|
-
this.info(message, args.length > 0 ? { args } : undefined);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
/**
|
|
308
|
-
* Create a logger instance
|
|
309
|
-
*/
|
|
310
|
-
export function createLogger(config) {
|
|
311
|
-
return new ObjectLogger(config);
|
|
312
|
-
}
|
package/dist/logger.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"logger.test.d.ts","sourceRoot":"","sources":["../src/logger.test.ts"],"names":[],"mappings":""}
|
package/dist/logger.test.js
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import { createLogger } from './logger';
|
|
3
|
-
describe('ObjectLogger', () => {
|
|
4
|
-
let logger;
|
|
5
|
-
beforeEach(() => {
|
|
6
|
-
logger = createLogger();
|
|
7
|
-
});
|
|
8
|
-
afterEach(async () => {
|
|
9
|
-
await logger.destroy();
|
|
10
|
-
});
|
|
11
|
-
describe('Basic Logging', () => {
|
|
12
|
-
it('should create a logger with default config', () => {
|
|
13
|
-
expect(logger).toBeDefined();
|
|
14
|
-
expect(logger.info).toBeDefined();
|
|
15
|
-
expect(logger.debug).toBeDefined();
|
|
16
|
-
expect(logger.warn).toBeDefined();
|
|
17
|
-
expect(logger.error).toBeDefined();
|
|
18
|
-
});
|
|
19
|
-
it('should log info messages', () => {
|
|
20
|
-
expect(() => logger.info('Test message')).not.toThrow();
|
|
21
|
-
});
|
|
22
|
-
it('should log debug messages', () => {
|
|
23
|
-
expect(() => logger.debug('Debug message')).not.toThrow();
|
|
24
|
-
});
|
|
25
|
-
it('should log warn messages', () => {
|
|
26
|
-
expect(() => logger.warn('Warning message')).not.toThrow();
|
|
27
|
-
});
|
|
28
|
-
it('should log error messages', () => {
|
|
29
|
-
const error = new Error('Test error');
|
|
30
|
-
expect(() => logger.error('Error occurred', error)).not.toThrow();
|
|
31
|
-
});
|
|
32
|
-
it('should log with metadata', () => {
|
|
33
|
-
expect(() => logger.info('Message with metadata', { userId: '123', action: 'login' })).not.toThrow();
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
describe('Configuration', () => {
|
|
37
|
-
it('should respect log level configuration', async () => {
|
|
38
|
-
const warnLogger = createLogger({ level: 'warn' });
|
|
39
|
-
// These should not throw but might not output anything
|
|
40
|
-
expect(() => warnLogger.debug('Debug message')).not.toThrow();
|
|
41
|
-
expect(() => warnLogger.info('Info message')).not.toThrow();
|
|
42
|
-
expect(() => warnLogger.warn('Warning message')).not.toThrow();
|
|
43
|
-
await warnLogger.destroy();
|
|
44
|
-
});
|
|
45
|
-
it('should support different formats', async () => {
|
|
46
|
-
const jsonLogger = createLogger({ format: 'json' });
|
|
47
|
-
const textLogger = createLogger({ format: 'text' });
|
|
48
|
-
const prettyLogger = createLogger({ format: 'pretty' });
|
|
49
|
-
expect(() => jsonLogger.info('JSON format')).not.toThrow();
|
|
50
|
-
expect(() => textLogger.info('Text format')).not.toThrow();
|
|
51
|
-
expect(() => prettyLogger.info('Pretty format')).not.toThrow();
|
|
52
|
-
await jsonLogger.destroy();
|
|
53
|
-
await textLogger.destroy();
|
|
54
|
-
await prettyLogger.destroy();
|
|
55
|
-
});
|
|
56
|
-
it('should redact sensitive keys', async () => {
|
|
57
|
-
const logger = createLogger({ redact: ['password', 'apiKey'] });
|
|
58
|
-
// This should work without exposing the password
|
|
59
|
-
expect(() => logger.info('User login', {
|
|
60
|
-
username: 'john',
|
|
61
|
-
password: 'secret123',
|
|
62
|
-
apiKey: 'key-12345'
|
|
63
|
-
})).not.toThrow();
|
|
64
|
-
await logger.destroy();
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
describe('Child Loggers', () => {
|
|
68
|
-
it('should create child logger with context', () => {
|
|
69
|
-
const childLogger = logger.child({ service: 'api', requestId: '123' });
|
|
70
|
-
expect(childLogger).toBeDefined();
|
|
71
|
-
expect(() => childLogger.info('Child log message')).not.toThrow();
|
|
72
|
-
});
|
|
73
|
-
it('should support trace context', () => {
|
|
74
|
-
const tracedLogger = logger.withTrace('trace-123', 'span-456');
|
|
75
|
-
expect(tracedLogger).toBeDefined();
|
|
76
|
-
expect(() => tracedLogger.info('Traced message')).not.toThrow();
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
describe('Environment Detection', () => {
|
|
80
|
-
it('should detect Node.js environment', async () => {
|
|
81
|
-
// This test runs in Node.js, so logger should detect it
|
|
82
|
-
const nodeLogger = createLogger({ format: 'json' });
|
|
83
|
-
expect(() => nodeLogger.info('Node environment')).not.toThrow();
|
|
84
|
-
await nodeLogger.destroy();
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
describe('Compatibility', () => {
|
|
88
|
-
it('should support console.log compatibility', () => {
|
|
89
|
-
expect(() => logger.log('Compatible log')).not.toThrow();
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
});
|