UNPKG

@qodalis/cli-server-logs

Version:

An Angular CLI extension for server logs.

180 lines (174 loc) 7.33 kB
import * as i0 from '@angular/core'; import { Injectable, NgModule } from '@angular/core'; import { resolveCommandProcessorProvider } from '@qodalis/angular-cli'; import * as signalR from '@microsoft/signalr'; import { DefaultLibraryAuthor, toQueryString, highlightTextWithBg } from '@qodalis/cli-core'; const levels = ['verbose', 'debug', 'information', 'warning', 'error', 'fatal']; class CliLogsCommandProcessor { constructor() { this.command = 'server-logs'; this.description = 'Show live logs'; this.processors = []; this.metadata = { requireServer: true, }; this.parameters = [ { name: 'pattern', type: 'string', description: 'The regex pattern to search for in the logs', required: false, validator: (value) => { const isValid = this.isValidRegex(value); return { valid: isValid, message: isValid ? undefined : 'Invalid regex pattern provided', }; }, }, { name: 'level', type: 'string', description: 'The log level to filter by, e.g. ' + levels.join(', '), required: false, validator: (value) => { const isValid = levels.includes(value); return { valid: isValid, message: isValid ? undefined : 'Invalid log level provided, must be one of: ' + levels.join(', '), }; }, }, { name: 'server', type: 'string', description: 'The server to connect to, e.g. "http://localhost:5000"', required: false, }, { name: 'hub', type: 'string', description: 'The hub to connect to, e.g. "loghub" (default) or "loghub2"', required: false, }, { name: 'file', type: 'boolean', description: 'Export logs to a file', required: false, }, ]; this.author = DefaultLibraryAuthor; this.processors?.push({ command: 'live', description: this.description, parameters: this.parameters, processCommand: this.processCommand.bind(this), writeDescription: this.writeDescription.bind(this), }); } async processCommand(command, context) { let qs = '?'; const args = this.excludeKeys(command.args, ['server', 'hub', 'file']); if (Object.keys(args).length > 0) { qs += toQueryString(args); } const hub = command.args['hub'] || 'loghub'; let server = command.args['server'] || ''; server = server.replace(/\/+$/, ''); const url = `${server}/${hub}${qs}`; console.log('Connecting to:', url); this.hubConnection = new signalR.HubConnectionBuilder() .withUrl(url) .build(); const buffer = []; await this.hubConnection .start() .then(() => { console.log('SignalR connection started'); context.writer.writeWarning('Connected to live logs'); if (qs.length) { Object.keys(args).forEach((key) => { context.writer.writeWarning(`Filtering logs by: ${key}=${command.args[key]}`); }); } let firstLog = true; let index = 0; this.hubConnection.on('log', (log) => { if (firstLog) { context.writer.writeln(''); } buffer.push(log); context.writer.writeln(`\x1b[33m${++index}\x1b[0m. ` + (command.args['pattern'] ? highlightTextWithBg(log, new RegExp(command.args['pattern'], 'g')) : log)); firstLog = false; }); const subscription = context.onAbort.subscribe(() => { this.hubConnection.stop(); context.writer.writeWarning('Disconnected from live logs'); if (command.args['file']) { const filename = `logs-${new Date().toISOString()}.txt`; context.writer.writeToFile(filename, buffer.join('\n')); } subscription.unsubscribe(); }); }) .catch((err) => { console.error('Error starting SignalR connection:', err); context.writer.writeError('Failed to connect to live logs'); context.writer.writeError(err?.toString()); }); } writeDescription(context) { context.writer.writeln('Show live logs'); } excludeKeys(record, keysToExclude) { return Object.fromEntries(Object.entries(record).filter(([key]) => !keysToExclude.includes(key))); } isValidRegex(pattern) { try { new RegExp(pattern); return true; } catch (e) { return false; } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliLogsCommandProcessor, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliLogsCommandProcessor, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliLogsCommandProcessor, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }], ctorParameters: function () { return []; } }); class CliServerLogsModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliServerLogsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: CliServerLogsModule }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliServerLogsModule, providers: [resolveCommandProcessorProvider(CliLogsCommandProcessor)] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliServerLogsModule, decorators: [{ type: NgModule, args: [{ declarations: [], imports: [], exports: [], providers: [resolveCommandProcessorProvider(CliLogsCommandProcessor)], }] }] }); /* * Public API Surface of server-logs */ /** * Generated bundle index. Do not edit. */ export { CliServerLogsModule }; //# sourceMappingURL=qodalis-cli-server-logs.mjs.map