@ngxs/logger-plugin
Version:
logger plugin for @ngxs/store
195 lines (185 loc) • 7.28 kB
JavaScript
import * as i0 from '@angular/core';
import { InjectionToken, inject, Injector, runInInjectionContext, Injectable, NgModule, makeEnvironmentProviders } from '@angular/core';
import { Store, withNgxsPlugin } from '@ngxs/store';
import { tap, catchError } from 'rxjs';
import { getActionTypeFromInstance } from '@ngxs/store/plugins';
class LogWriter {
constructor(options) {
this.options = options;
this.options = this.options || {};
this.logger = options.logger || console;
}
startGroup(message) {
const startGroupFn = this.options.collapsed
? this.logger.groupCollapsed
: this.logger.group;
try {
startGroupFn.call(this.logger, message);
}
catch (e) {
console.log(message);
}
}
endGroup() {
try {
this.logger.groupEnd();
}
catch (e) {
this.logger.log('—— log end ——');
}
}
logGrey(title, payload) {
const greyStyle = 'color: #9E9E9E; font-weight: bold';
this.log(title, greyStyle, payload);
}
logGreen(title, payload) {
const greenStyle = 'color: #4CAF50; font-weight: bold';
this.log(title, greenStyle, payload);
}
logRedish(title, payload) {
const redishStyle = 'color: #FD8182; font-weight: bold';
this.log(title, redishStyle, payload);
}
log(title, color, payload) {
this.logger.log('%c ' + title, color, payload);
}
}
const repeat = (str, times) => new Array(times + 1).join(str);
const pad = (num, maxLength) => repeat('0', maxLength - num.toString().length) + num;
function formatTime(time) {
return (pad(time.getHours(), 2) +
`:` +
pad(time.getMinutes(), 2) +
`:` +
pad(time.getSeconds(), 2) +
`.` +
pad(time.getMilliseconds(), 3));
}
class ActionLogger {
constructor(action, store, logWriter) {
this.action = action;
this.store = store;
this.logWriter = logWriter;
}
dispatched(state) {
const actionName = getActionTypeFromInstance(this.action);
const formattedTime = formatTime(new Date());
const message = `action ${actionName} @ ${formattedTime}`;
this.logWriter.startGroup(message);
// print payload only if at least one property is supplied
if (this._hasPayload(this.action)) {
this.logWriter.logGrey('payload', { ...this.action });
}
this.logWriter.logGrey('prev state', state);
}
completed(nextState) {
this.logWriter.logGreen('next state', nextState);
this.logWriter.endGroup();
}
errored(error) {
this.logWriter.logRedish('next state after error', this.store.snapshot());
this.logWriter.logRedish('error', error);
this.logWriter.endGroup();
}
_hasPayload(event) {
const nonEmptyProperties = this._getNonEmptyProperties(event);
return nonEmptyProperties.length > 0;
}
_getNonEmptyProperties(event) {
const keys = Object.keys(event);
const values = keys.map(key => event[key]);
return values.filter(value => value !== undefined);
}
}
const NGXS_LOGGER_PLUGIN_OPTIONS = new InjectionToken('NGXS_LOGGER_PLUGIN_OPTIONS');
class NgxsLoggerPlugin {
constructor() {
this._options = inject(NGXS_LOGGER_PLUGIN_OPTIONS);
this._injector = inject(Injector);
}
handle(state, event, next) {
if (this._options.disabled || this._skipLogging(state, event)) {
return next(state, event);
}
this._logWriter ||= new LogWriter(this._options);
// Retrieve lazily to avoid cyclic dependency exception
this._store ||= this._injector.get(Store);
const actionLogger = new ActionLogger(event, this._store, this._logWriter);
actionLogger.dispatched(state);
return next(state, event).pipe(tap(nextState => {
actionLogger.completed(nextState);
}), catchError(error => {
actionLogger.errored(error);
throw error;
}));
}
_skipLogging(state, event) {
// Run the `filter: () => ...` function within the injection context so
// that the user can access the dependency injection and inject services
// to retrieve properties. This will help determine whether or not to log the action.
const allowLogging = runInInjectionContext(this._injector, () => this._options.filter(event, state));
return !allowLogging;
}
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: NgxsLoggerPlugin, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: NgxsLoggerPlugin }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: NgxsLoggerPlugin, decorators: [{
type: Injectable
}] });
const USER_OPTIONS = new InjectionToken('LOGGER_USER_OPTIONS');
function loggerOptionsFactory(options) {
const defaultLoggerOptions = {
logger: console,
collapsed: false,
disabled: false,
filter: () => true
};
return {
...defaultLoggerOptions,
...options
};
}
class NgxsLoggerPluginModule {
static forRoot(options) {
return {
ngModule: NgxsLoggerPluginModule,
providers: [
withNgxsPlugin(NgxsLoggerPlugin),
{
provide: USER_OPTIONS,
useValue: options
},
{
provide: NGXS_LOGGER_PLUGIN_OPTIONS,
useFactory: loggerOptionsFactory,
deps: [USER_OPTIONS]
}
]
};
}
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: NgxsLoggerPluginModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
/** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.0", ngImport: i0, type: NgxsLoggerPluginModule }); }
/** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: NgxsLoggerPluginModule }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: NgxsLoggerPluginModule, decorators: [{
type: NgModule
}] });
function withNgxsLoggerPlugin(options) {
return makeEnvironmentProviders([
withNgxsPlugin(NgxsLoggerPlugin),
{ provide: USER_OPTIONS, useValue: options },
{
provide: NGXS_LOGGER_PLUGIN_OPTIONS,
useFactory: loggerOptionsFactory,
deps: [USER_OPTIONS]
}
]);
}
/**
* The public api for consumers of @ngxs/logger-plugin
*/
/**
* Generated bundle index. Do not edit.
*/
export { NGXS_LOGGER_PLUGIN_OPTIONS, NgxsLoggerPlugin, NgxsLoggerPluginModule, withNgxsLoggerPlugin };
//# sourceMappingURL=ngxs-logger-plugin.mjs.map