@qodalis/cli-server-logs
Version:
An Angular CLI extension for server logs.
180 lines (174 loc) • 7.33 kB
JavaScript
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