@mks2508/better-logger 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +13 -0
- package/CLAUDE.md +113 -0
- package/dist/assets/index-DxvJByYN.js +183 -0
- package/dist/index.html +334 -0
- package/dist/vite.svg +1 -0
- package/index.html +334 -0
- package/package.json +35 -0
- package/public/vite.svg +1 -0
- package/src/Logger.ts +577 -0
- package/src/Logger.ts.backup +1684 -0
- package/src/cli/CommandProcessor.ts +77 -0
- package/src/cli/commands/ConfigCommand.ts +93 -0
- package/src/cli/commands/ExportCommand.ts +271 -0
- package/src/cli/commands/StatusCommand.ts +111 -0
- package/src/cli/commands/ThemeCommand.ts +88 -0
- package/src/cli/help.ts +127 -0
- package/src/cli/index.ts +59 -0
- package/src/constants.ts +89 -0
- package/src/example.ts +88 -0
- package/src/handlers/AnalyticsLogHandler.ts +22 -0
- package/src/handlers/ExportLogHandler.ts +447 -0
- package/src/handlers/FileLogHandler.ts +30 -0
- package/src/handlers/RemoteLogHandler.ts +42 -0
- package/src/handlers/index.ts +8 -0
- package/src/index.ts +122 -0
- package/src/main.ts +126 -0
- package/src/style.css +96 -0
- package/src/styling/StyleBuilder.ts +305 -0
- package/src/styling/banners.ts +168 -0
- package/src/styling/index.ts +12 -0
- package/src/styling/themes.ts +235 -0
- package/src/types/core.ts +80 -0
- package/src/types/handlers.ts +95 -0
- package/src/types/index.ts +29 -0
- package/src/typescript.svg +1 -0
- package/src/utils/index.ts +18 -0
- package/src/utils/output.ts +127 -0
- package/src/utils/stackTrace.ts +66 -0
- package/src/utils/timestamps.ts +80 -0
- package/src/vite-env.d.ts +1 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview CLI Command processor for Advanced Logger
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { Logger } from '../Logger.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Base interface for CLI commands
|
|
9
|
+
*/
|
|
10
|
+
export interface ICommand {
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
usage: string;
|
|
14
|
+
execute(args: string, logger: Logger): void | Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* CLI command processor
|
|
19
|
+
*/
|
|
20
|
+
export class CommandProcessor {
|
|
21
|
+
private commands: Map<string, ICommand> = new Map();
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Register a command
|
|
25
|
+
*/
|
|
26
|
+
registerCommand(command: ICommand): void {
|
|
27
|
+
this.commands.set(command.name, command);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Get all registered commands
|
|
32
|
+
*/
|
|
33
|
+
getCommands(): ICommand[] {
|
|
34
|
+
return Array.from(this.commands.values());
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Get a specific command
|
|
39
|
+
*/
|
|
40
|
+
getCommand(name: string): ICommand | undefined {
|
|
41
|
+
return this.commands.get(name);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Process a CLI command
|
|
46
|
+
*/
|
|
47
|
+
async processCommand(commandString: string, logger: Logger): Promise<void> {
|
|
48
|
+
if (!commandString.startsWith('/')) {
|
|
49
|
+
logger.error('Invalid command. Commands must start with /');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const parts = commandString.slice(1).split(' ');
|
|
54
|
+
const commandName = parts[0];
|
|
55
|
+
const args = parts.slice(1).join(' ');
|
|
56
|
+
|
|
57
|
+
const command = this.commands.get(commandName);
|
|
58
|
+
if (!command) {
|
|
59
|
+
logger.error(`Unknown command: ${commandName}. Type /help for available commands.`);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
await command.execute(args, logger);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
logger.error(`Command '${commandName}' failed:`, error);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Get command suggestions for partial matches
|
|
72
|
+
*/
|
|
73
|
+
getSuggestions(partial: string): string[] {
|
|
74
|
+
const commandNames = Array.from(this.commands.keys());
|
|
75
|
+
return commandNames.filter(name => name.startsWith(partial));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Configuration commands for Advanced Logger CLI
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ICommand } from '../CommandProcessor.js';
|
|
6
|
+
import type { Logger } from '../../Logger.js';
|
|
7
|
+
import type { ThemeVariant, BannerType, Verbosity } from '../../types/index.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Configuration command handler
|
|
11
|
+
*/
|
|
12
|
+
export class ConfigCommand implements ICommand {
|
|
13
|
+
name = 'config';
|
|
14
|
+
description = 'Show or update logger configuration';
|
|
15
|
+
usage = '/config [json|key=value,...]';
|
|
16
|
+
|
|
17
|
+
execute(args: string, logger: Logger): void {
|
|
18
|
+
if (!args) {
|
|
19
|
+
this.showStatus(logger);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
// Try to parse as JSON first
|
|
25
|
+
if (args.startsWith('{')) {
|
|
26
|
+
const config = JSON.parse(args);
|
|
27
|
+
this.applyConfig(config, logger);
|
|
28
|
+
} else {
|
|
29
|
+
// Parse key=value pairs
|
|
30
|
+
const pairs = args.split(',').map(pair => pair.trim().split('='));
|
|
31
|
+
const config: any = {};
|
|
32
|
+
pairs.forEach(([key, value]) => {
|
|
33
|
+
if (key && value) {
|
|
34
|
+
config[key.trim()] = value.trim().replace(/["']/g, '');
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
this.applyConfig(config, logger);
|
|
38
|
+
}
|
|
39
|
+
} catch (error) {
|
|
40
|
+
logger.error('Invalid config format. Use JSON or key=value pairs:', error);
|
|
41
|
+
logger.info('Examples: /config {"theme":"dark"} or /config theme=neon,verbosity=debug');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private showStatus(logger: Logger): void {
|
|
46
|
+
const statusData = {
|
|
47
|
+
theme: logger.getConfig().theme || 'default',
|
|
48
|
+
verbosity: logger.getConfig().verbosity,
|
|
49
|
+
colors: logger.getConfig().enableColors,
|
|
50
|
+
timestamps: logger.getConfig().enableTimestamps,
|
|
51
|
+
stackTrace: logger.getConfig().enableStackTrace,
|
|
52
|
+
globalPrefix: logger.getConfig().globalPrefix || 'none',
|
|
53
|
+
bannerType: logger.getConfig().bannerType || 'simple',
|
|
54
|
+
handlers: logger.getHandlers().length
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
logger.group('⚙️ Logger Configuration');
|
|
58
|
+
logger.table(statusData);
|
|
59
|
+
logger.groupEnd();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private applyConfig(config: any, logger: Logger): void {
|
|
63
|
+
const validKeys = ['theme', 'verbosity', 'enableColors', 'enableTimestamps', 'enableStackTrace', 'globalPrefix', 'bannerType'];
|
|
64
|
+
const applied: string[] = [];
|
|
65
|
+
|
|
66
|
+
Object.entries(config).forEach(([key, value]) => {
|
|
67
|
+
if (validKeys.includes(key)) {
|
|
68
|
+
if (key === 'theme' && typeof value === 'string') {
|
|
69
|
+
logger.setTheme(value as ThemeVariant);
|
|
70
|
+
applied.push(`${key}=${value}`);
|
|
71
|
+
} else if (key === 'bannerType' && typeof value === 'string') {
|
|
72
|
+
logger.setBannerType(value as BannerType);
|
|
73
|
+
applied.push(`${key}=${value}`);
|
|
74
|
+
} else if (key === 'verbosity') {
|
|
75
|
+
logger.setVerbosity(value as Verbosity);
|
|
76
|
+
applied.push(`${key}=${value}`);
|
|
77
|
+
} else if (key === 'globalPrefix') {
|
|
78
|
+
logger.setGlobalPrefix(value as string);
|
|
79
|
+
applied.push(`${key}=${value}`);
|
|
80
|
+
} else {
|
|
81
|
+
logger.updateConfig({ [key]: value });
|
|
82
|
+
applied.push(`${key}=${value}`);
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
logger.warn(`Invalid config key: ${key}`);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
if (applied.length > 0) {
|
|
90
|
+
logger.success(`Configuration updated: ${applied.join(', ')}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Export and clipboard commands for Advanced Logger CLI
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ICommand } from '../CommandProcessor.js';
|
|
6
|
+
import type { Logger } from '../../Logger.js';
|
|
7
|
+
import type { ExportFormat, ExportFilters, ExportOptions, LogLevel } from '../../types/index.js';
|
|
8
|
+
import { EXPORT_FORMATS } from '../../constants.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Parse command line arguments into filters and options
|
|
12
|
+
*/
|
|
13
|
+
function parseArguments(args: string): { filters: ExportFilters; options: ExportOptions; format?: ExportFormat } {
|
|
14
|
+
const filters: ExportFilters = {};
|
|
15
|
+
const options: ExportOptions = {};
|
|
16
|
+
let format: ExportFormat | undefined;
|
|
17
|
+
|
|
18
|
+
if (!args.trim()) return { filters, options };
|
|
19
|
+
|
|
20
|
+
// Split args by spaces, but keep quoted strings together
|
|
21
|
+
const argParts = args.match(/(?:[^\s"]+|"[^"]*")+/g) || [];
|
|
22
|
+
|
|
23
|
+
for (let i = 0; i < argParts.length; i++) {
|
|
24
|
+
const arg = argParts[i];
|
|
25
|
+
|
|
26
|
+
// Format (first argument without --)
|
|
27
|
+
if (i === 0 && !arg.startsWith('--') && arg in EXPORT_FORMATS) {
|
|
28
|
+
format = arg as ExportFormat;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Parse --flags
|
|
33
|
+
if (arg.startsWith('--')) {
|
|
34
|
+
const [flag, value] = arg.slice(2).split('=');
|
|
35
|
+
|
|
36
|
+
switch (flag) {
|
|
37
|
+
case 'level':
|
|
38
|
+
case 'levels':
|
|
39
|
+
if (value) {
|
|
40
|
+
filters.levels = value.split(',').map(l => l.trim()) as LogLevel[];
|
|
41
|
+
}
|
|
42
|
+
break;
|
|
43
|
+
case 'since':
|
|
44
|
+
if (value) filters.since = value;
|
|
45
|
+
break;
|
|
46
|
+
case 'until':
|
|
47
|
+
if (value) filters.until = value;
|
|
48
|
+
break;
|
|
49
|
+
case 'prefix':
|
|
50
|
+
case 'prefixes':
|
|
51
|
+
if (value) {
|
|
52
|
+
filters.prefixes = value.split(',').map(p => p.trim());
|
|
53
|
+
}
|
|
54
|
+
break;
|
|
55
|
+
case 'exclude-prefix':
|
|
56
|
+
case 'exclude-prefixes':
|
|
57
|
+
if (value) {
|
|
58
|
+
filters.excludePrefixes = value.split(',').map(p => p.trim());
|
|
59
|
+
}
|
|
60
|
+
break;
|
|
61
|
+
case 'last':
|
|
62
|
+
if (value) filters.last = parseInt(value, 10);
|
|
63
|
+
break;
|
|
64
|
+
case 'first':
|
|
65
|
+
if (value) filters.first = parseInt(value, 10);
|
|
66
|
+
break;
|
|
67
|
+
case 'search':
|
|
68
|
+
if (value) filters.search = value.replace(/['"]/g, '');
|
|
69
|
+
break;
|
|
70
|
+
case 'with-stack':
|
|
71
|
+
filters.withStackTrace = true;
|
|
72
|
+
break;
|
|
73
|
+
case 'errors-only':
|
|
74
|
+
filters.errorsOnly = true;
|
|
75
|
+
break;
|
|
76
|
+
case 'group-by':
|
|
77
|
+
if (value) {
|
|
78
|
+
filters.groupBy = value as ExportFilters['groupBy'];
|
|
79
|
+
options.groupBy = value as ExportOptions['groupBy'];
|
|
80
|
+
}
|
|
81
|
+
break;
|
|
82
|
+
case 'minimal':
|
|
83
|
+
options.minimal = true;
|
|
84
|
+
break;
|
|
85
|
+
case 'compact':
|
|
86
|
+
options.compact = true;
|
|
87
|
+
break;
|
|
88
|
+
case 'styled':
|
|
89
|
+
options.styled = true;
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return { filters, options, format };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Export command - export logs in various formats
|
|
100
|
+
*/
|
|
101
|
+
export class ExportCommand implements ICommand {
|
|
102
|
+
name = 'export';
|
|
103
|
+
description = 'Export logs to various formats';
|
|
104
|
+
usage = '/export <format> [--filter=value] [--option]';
|
|
105
|
+
|
|
106
|
+
execute(args: string, logger: Logger): void {
|
|
107
|
+
const exportHandler = logger.getExportHandler();
|
|
108
|
+
if (!exportHandler) {
|
|
109
|
+
logger.error('Export handler not available. Make sure ExportLogHandler is registered.');
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const { filters, options, format } = parseArguments(args);
|
|
114
|
+
|
|
115
|
+
if (!format) {
|
|
116
|
+
logger.error('Format required. Available formats: ' + Object.keys(EXPORT_FORMATS).join(', '));
|
|
117
|
+
logger.info('Usage: /export <format> [--filter=value]');
|
|
118
|
+
logger.info('Example: /export json --level=error,warn --last=50');
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
const result = exportHandler.export(format, filters, options);
|
|
124
|
+
|
|
125
|
+
// Log success with metadata
|
|
126
|
+
logger.success(`✅ Export completed: ${result.metadata.filteredLogs} logs exported in ${format} format`);
|
|
127
|
+
|
|
128
|
+
// Show preview for small exports
|
|
129
|
+
if (result.data.length < 1000) {
|
|
130
|
+
logger.group(`📄 Preview (${format.toUpperCase()})`);
|
|
131
|
+
console.log(result.data);
|
|
132
|
+
logger.groupEnd();
|
|
133
|
+
} else {
|
|
134
|
+
logger.info(`📄 Export size: ${(result.data.length / 1024).toFixed(2)}KB`);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Show metadata
|
|
138
|
+
logger.table({
|
|
139
|
+
format: result.format,
|
|
140
|
+
totalLogs: result.metadata.totalLogs,
|
|
141
|
+
filtered: result.metadata.filteredLogs,
|
|
142
|
+
exported: result.metadata.exportedAt
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
} catch (error) {
|
|
146
|
+
logger.error('Export failed:', error);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Copy command - copy logs to clipboard
|
|
153
|
+
*/
|
|
154
|
+
export class CopyCommand implements ICommand {
|
|
155
|
+
name = 'copy';
|
|
156
|
+
description = 'Copy logs to clipboard';
|
|
157
|
+
usage = '/copy <format> [--filter=value] [--option]';
|
|
158
|
+
|
|
159
|
+
async execute(args: string, logger: Logger): Promise<void> {
|
|
160
|
+
const exportHandler = logger.getExportHandler();
|
|
161
|
+
if (!exportHandler) {
|
|
162
|
+
logger.error('Export handler not available. Make sure ExportLogHandler is registered.');
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const { filters, options, format } = parseArguments(args);
|
|
167
|
+
|
|
168
|
+
if (!format) {
|
|
169
|
+
logger.error('Format required. Available formats: ' + Object.keys(EXPORT_FORMATS).join(', '));
|
|
170
|
+
logger.info('Usage: /copy <format> [--filter=value]');
|
|
171
|
+
logger.info('Example: /copy plain --level=error --last=25');
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
try {
|
|
176
|
+
const success = await exportHandler.copyToClipboard(format, filters, options);
|
|
177
|
+
|
|
178
|
+
if (success) {
|
|
179
|
+
const result = exportHandler.export(format, filters, options);
|
|
180
|
+
logger.success(`📋 Copied ${result.metadata.filteredLogs} logs to clipboard (${format} format)`);
|
|
181
|
+
} else {
|
|
182
|
+
logger.error('Failed to copy to clipboard. Browser may not support clipboard API.');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
} catch (error) {
|
|
186
|
+
logger.error('Copy failed:', error);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Buffer-size command - configure buffer size
|
|
193
|
+
*/
|
|
194
|
+
export class BufferSizeCommand implements ICommand {
|
|
195
|
+
name = 'buffer-size';
|
|
196
|
+
description = 'Set log buffer size';
|
|
197
|
+
usage = '/buffer-size <size>';
|
|
198
|
+
|
|
199
|
+
execute(args: string, logger: Logger): void {
|
|
200
|
+
const exportHandler = logger.getExportHandler();
|
|
201
|
+
if (!exportHandler) {
|
|
202
|
+
logger.error('Export handler not available.');
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const size = parseInt(args.trim(), 10);
|
|
207
|
+
if (isNaN(size) || size <= 0) {
|
|
208
|
+
logger.error('Invalid buffer size. Must be a positive number.');
|
|
209
|
+
logger.info('Example: /buffer-size 2000');
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
exportHandler.setBufferSize(size);
|
|
214
|
+
logger.success(`Buffer size set to ${size}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Clear-buffer command - clear log buffer
|
|
220
|
+
*/
|
|
221
|
+
export class ClearBufferCommand implements ICommand {
|
|
222
|
+
name = 'clear-buffer';
|
|
223
|
+
description = 'Clear the log buffer';
|
|
224
|
+
usage = '/clear-buffer';
|
|
225
|
+
|
|
226
|
+
execute(_args: string, logger: Logger): void {
|
|
227
|
+
const exportHandler = logger.getExportHandler();
|
|
228
|
+
if (!exportHandler) {
|
|
229
|
+
logger.error('Export handler not available.');
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const stats = exportHandler.getBufferStats();
|
|
234
|
+
exportHandler.clearBuffer();
|
|
235
|
+
|
|
236
|
+
logger.success(`✅ Buffer cleared. Removed ${stats.size} log entries.`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Buffer-info command - show buffer information
|
|
242
|
+
*/
|
|
243
|
+
export class BufferInfoCommand implements ICommand {
|
|
244
|
+
name = 'buffer-info';
|
|
245
|
+
description = 'Show buffer statistics and information';
|
|
246
|
+
usage = '/buffer-info';
|
|
247
|
+
|
|
248
|
+
execute(_args: string, logger: Logger): void {
|
|
249
|
+
const exportHandler = logger.getExportHandler();
|
|
250
|
+
if (!exportHandler) {
|
|
251
|
+
logger.error('Export handler not available.');
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const stats = exportHandler.getBufferStats();
|
|
256
|
+
|
|
257
|
+
logger.group('📊 Buffer Information');
|
|
258
|
+
logger.table({
|
|
259
|
+
size: `${stats.size}/${stats.maxSize}`,
|
|
260
|
+
usage: `${stats.usage.toFixed(1)}%`,
|
|
261
|
+
oldestLog: stats.oldestLog?.toLocaleString() || 'None',
|
|
262
|
+
newestLog: stats.newestLog?.toLocaleString() || 'None'
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
logger.group('📈 Log Level Counts');
|
|
266
|
+
logger.table(stats.levelCounts);
|
|
267
|
+
logger.groupEnd();
|
|
268
|
+
|
|
269
|
+
logger.groupEnd();
|
|
270
|
+
}
|
|
271
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Status and demo commands for Advanced Logger CLI
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ICommand } from '../CommandProcessor.js';
|
|
6
|
+
import type { Logger } from '../../Logger.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Status command - show logger configuration and statistics
|
|
10
|
+
*/
|
|
11
|
+
export class StatusCommand implements ICommand {
|
|
12
|
+
name = 'status';
|
|
13
|
+
description = 'Show current logger status and configuration';
|
|
14
|
+
usage = '/status';
|
|
15
|
+
|
|
16
|
+
execute(_args: string, logger: Logger): void {
|
|
17
|
+
const statusData = {
|
|
18
|
+
theme: logger.getConfig().theme || 'default',
|
|
19
|
+
verbosity: logger.getConfig().verbosity,
|
|
20
|
+
colors: logger.getConfig().enableColors,
|
|
21
|
+
timestamps: logger.getConfig().enableTimestamps,
|
|
22
|
+
stackTrace: logger.getConfig().enableStackTrace,
|
|
23
|
+
globalPrefix: logger.getConfig().globalPrefix || 'none',
|
|
24
|
+
bannerType: logger.getConfig().bannerType || 'simple',
|
|
25
|
+
handlers: logger.getHandlers().length,
|
|
26
|
+
bufferSize: logger.getConfig().bufferSize || 1000
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
logger.group('⚙️ Logger Configuration');
|
|
30
|
+
logger.table(statusData);
|
|
31
|
+
logger.groupEnd();
|
|
32
|
+
|
|
33
|
+
// Show buffer stats if ExportLogHandler is present
|
|
34
|
+
const exportHandler = logger.getExportHandler();
|
|
35
|
+
if (exportHandler) {
|
|
36
|
+
const bufferStats = exportHandler.getBufferStats();
|
|
37
|
+
logger.group('📊 Buffer Statistics');
|
|
38
|
+
logger.table({
|
|
39
|
+
size: `${bufferStats.size}/${bufferStats.maxSize}`,
|
|
40
|
+
usage: `${bufferStats.usage.toFixed(1)}%`,
|
|
41
|
+
oldestLog: bufferStats.oldestLog?.toISOString() || 'None',
|
|
42
|
+
newestLog: bufferStats.newestLog?.toISOString() || 'None',
|
|
43
|
+
errorCount: bufferStats.levelCounts.error + bufferStats.levelCounts.critical,
|
|
44
|
+
warningCount: bufferStats.levelCounts.warn
|
|
45
|
+
});
|
|
46
|
+
logger.groupEnd();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Reset command - reset logger to defaults
|
|
53
|
+
*/
|
|
54
|
+
export class ResetCommand implements ICommand {
|
|
55
|
+
name = 'reset';
|
|
56
|
+
description = 'Reset logger configuration to defaults';
|
|
57
|
+
usage = '/reset';
|
|
58
|
+
|
|
59
|
+
execute(_args: string, logger: Logger): void {
|
|
60
|
+
logger.resetConfig();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Demo command - show logger feature demonstration
|
|
66
|
+
*/
|
|
67
|
+
export class DemoCommand implements ICommand {
|
|
68
|
+
name = 'demo';
|
|
69
|
+
description = 'Show comprehensive feature demonstration';
|
|
70
|
+
usage = '/demo';
|
|
71
|
+
|
|
72
|
+
execute(_args: string, logger: Logger): void {
|
|
73
|
+
logger.group('🎪 Advanced Logger Demo');
|
|
74
|
+
|
|
75
|
+
// Basic logging demo
|
|
76
|
+
logger.debug('Debug message with detailed information');
|
|
77
|
+
logger.info('Informational message about system state');
|
|
78
|
+
logger.warn('Warning about deprecated feature');
|
|
79
|
+
logger.error('Error processing user request');
|
|
80
|
+
logger.success('Operation completed successfully');
|
|
81
|
+
logger.critical('Critical system failure detected');
|
|
82
|
+
|
|
83
|
+
// Advanced features demo
|
|
84
|
+
logger.group('📊 Advanced Features Demo');
|
|
85
|
+
|
|
86
|
+
// Table demo
|
|
87
|
+
logger.table([
|
|
88
|
+
{ feature: 'Styled Console', status: '✅ Active', performance: 'Excellent' },
|
|
89
|
+
{ feature: 'Theme System', status: '✅ Active', performance: 'Great' },
|
|
90
|
+
{ feature: 'CLI Interface', status: '✅ Active', performance: 'Good' },
|
|
91
|
+
{ feature: 'Export System', status: '✅ Active', performance: 'Excellent' }
|
|
92
|
+
]);
|
|
93
|
+
|
|
94
|
+
// Timer demo
|
|
95
|
+
logger.time('demo-operation');
|
|
96
|
+
setTimeout(() => {
|
|
97
|
+
logger.timeEnd('demo-operation');
|
|
98
|
+
}, 100);
|
|
99
|
+
|
|
100
|
+
// SVG demo
|
|
101
|
+
logger.logWithSVG('SVG Demo');
|
|
102
|
+
|
|
103
|
+
// Animated demo
|
|
104
|
+
logger.logAnimated('🌟 Animated Logger Demo 🌟', 2);
|
|
105
|
+
|
|
106
|
+
logger.groupEnd();
|
|
107
|
+
logger.groupEnd();
|
|
108
|
+
|
|
109
|
+
logger.info('Demo completed! Check the console for styled output.');
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Theme and banner commands for Advanced Logger CLI
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ICommand } from '../CommandProcessor.js';
|
|
6
|
+
import type { Logger } from '../../Logger.js';
|
|
7
|
+
import type { BannerType } from '../../types/index.js';
|
|
8
|
+
import { THEME_PRESETS, BANNER_VARIANTS } from '../../styling/index.js';
|
|
9
|
+
import { StyleBuilder } from '../../styling/index.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Themes command - show available themes
|
|
13
|
+
*/
|
|
14
|
+
export class ThemesCommand implements ICommand {
|
|
15
|
+
name = 'themes';
|
|
16
|
+
description = 'Show available theme presets';
|
|
17
|
+
usage = '/themes';
|
|
18
|
+
|
|
19
|
+
execute(_args: string, logger: Logger): void {
|
|
20
|
+
logger.group('🎨 Available Themes');
|
|
21
|
+
Object.keys(THEME_PRESETS).forEach(themeName => {
|
|
22
|
+
const preview = (THEME_PRESETS as any)[themeName];
|
|
23
|
+
const previewStyle = new StyleBuilder()
|
|
24
|
+
.bg(preview.info.background)
|
|
25
|
+
.color(preview.info.color)
|
|
26
|
+
.padding('4px 8px')
|
|
27
|
+
.rounded('4px')
|
|
28
|
+
.border(preview.info.border)
|
|
29
|
+
.build();
|
|
30
|
+
|
|
31
|
+
console.log(`%c${themeName}`, previewStyle, `- ${themeName} theme preview`);
|
|
32
|
+
});
|
|
33
|
+
logger.groupEnd();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Banners command - show available banner types
|
|
39
|
+
*/
|
|
40
|
+
export class BannersCommand implements ICommand {
|
|
41
|
+
name = 'banners';
|
|
42
|
+
description = 'Show available banner types';
|
|
43
|
+
usage = '/banners';
|
|
44
|
+
|
|
45
|
+
execute(_args: string, logger: Logger): void {
|
|
46
|
+
logger.group('🖼️ Available Banner Types');
|
|
47
|
+
Object.keys(BANNER_VARIANTS).forEach(bannerName => {
|
|
48
|
+
const banner = (BANNER_VARIANTS as any)[bannerName];
|
|
49
|
+
console.log(`%c${bannerName}`, 'font-weight: bold; color: #667eea;');
|
|
50
|
+
console.log(`%cPreview:`, 'color: #666; font-size: 12px;');
|
|
51
|
+
|
|
52
|
+
// Show a mini preview
|
|
53
|
+
if (bannerName === 'simple') {
|
|
54
|
+
console.log(`%c${banner.text}`, banner.style);
|
|
55
|
+
} else if (bannerName === 'ascii') {
|
|
56
|
+
console.log(`%c${banner.text.split('\n').slice(1, 4).join('\n')}...`, 'font-family: monospace; color: #667eea; font-size: 10px;');
|
|
57
|
+
} else if (bannerName === 'unicode') {
|
|
58
|
+
console.log(`%c${banner.text}`, banner.style);
|
|
59
|
+
} else {
|
|
60
|
+
console.log(`%c${bannerName} banner`, 'color: #666; font-style: italic;');
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
logger.groupEnd();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Banner command - change/show banner type
|
|
69
|
+
*/
|
|
70
|
+
export class BannerCommand implements ICommand {
|
|
71
|
+
name = 'banner';
|
|
72
|
+
description = 'Change or show current banner type';
|
|
73
|
+
usage = '/banner [type]';
|
|
74
|
+
|
|
75
|
+
execute(args: string, logger: Logger): void {
|
|
76
|
+
if (!args) {
|
|
77
|
+
logger.showBanner();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (args in BANNER_VARIANTS) {
|
|
82
|
+
logger.setBannerType(args as BannerType);
|
|
83
|
+
logger.showBanner();
|
|
84
|
+
} else {
|
|
85
|
+
logger.error(`Invalid banner type: ${args}. Available: ${Object.keys(BANNER_VARIANTS).join(', ')}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|