UNPKG

ngx-logger

Version:

[![npm version](https://badge.fury.io/js/ngx-logger.svg)](https://www.npmjs.com/package/ngx-logger)

876 lines (852 loc) 41.9 kB
import { HttpRequest, HttpResponse, HttpBackend, HttpHeaders, HttpParams } from '@angular/common/http'; import { ɵɵinject, ɵɵdefineInjectable, ɵsetClassMetadata, Injectable, Optional, PLATFORM_ID, Inject, ɵɵdefineNgModule, ɵɵdefineInjector, ɵɵsetNgModuleScope, NgModule } from '@angular/core'; import { of, throwError } from 'rxjs'; import { filter, map, retry, shareReplay, catchError, take } from 'rxjs/operators'; import { decode } from 'vlq'; import { DatePipe, isPlatformBrowser, CommonModule } from '@angular/common'; /** * Injection token of logger config */ const TOKEN_LOGGER_CONFIG = 'TOKEN_LOGGER_CONFIG'; class NGXLoggerConfigEngine { constructor(config) { this.config = this._clone(config); } /** Get a readonly access to the level configured for the NGXLogger */ get level() { return this.config.level; } /** Get a readonly access to the serverLogLevel configured for the NGXLogger */ get serverLogLevel() { return this.config.serverLogLevel; } updateConfig(config) { this.config = this._clone(config); } getConfig() { return this._clone(this.config); } // TODO: This is a shallow clone, If the config ever becomes hierarchical we must make this a deep clone _clone(object) { const cloneConfig = { level: null }; Object.keys(object).forEach((key) => { cloneConfig[key] = object[key]; }); return cloneConfig; } } /** * Injection token of logger config engine factory */ const TOKEN_LOGGER_CONFIG_ENGINE_FACTORY = 'TOKEN_LOGGER_CONFIG_ENGINE_FACTORY'; class NGXLoggerConfigEngineFactory { provideConfigEngine(config) { return new NGXLoggerConfigEngine(config); } } /** * Injection token of logger mapper service */ const TOKEN_LOGGER_MAPPER_SERVICE = 'TOKEN_LOGGER_MAPPER_SERVICE'; class NGXLoggerMapperService { constructor(httpBackend) { this.httpBackend = httpBackend; /** cache for source maps, key is source map location, ie. 'http://localhost:4200/main.js.map' */ this.sourceMapCache = new Map(); /** cache for specific log position, key is the dist position, ie 'main.js:339:21' */ this.logPositionCache = new Map(); } /** * Returns the log position of the caller * If sourceMaps are enabled, it attemps to get the source map from the server, and use that to parse the position * @param config * @param metadata * @returns */ getLogPosition(config, metadata) { const stackLine = this.getStackLine(config); // if we were not able to parse the stackLine, just return an empty Log Position if (!stackLine) { return of({ fileName: '', lineNumber: 0, columnNumber: 0 }); } const logPosition = this.getLocalPosition(stackLine); if (!config.enableSourceMaps) { return of(logPosition); } const sourceMapLocation = this.getSourceMapLocation(stackLine); return this.getSourceMap(sourceMapLocation, logPosition); } /** * Get the stackline of the original caller * @param config * @returns null if stackline was not found */ getStackLine(config) { const error = new Error(); try { // noinspection ExceptionCaughtLocallyJS throw error; } catch (e) { try { // Here are different examples of stacktrace // Firefox (last line is the user code, the 4 first are ours): // getStackLine@http://localhost:4200/main.js:358:23 // getCallerDetails@http://localhost:4200/main.js:557:44 // _log@http://localhost:4200/main.js:830:28 // debug@http://localhost:4200/main.js:652:14 // handleLog@http://localhost:4200/main.js:1158:29 // Chrome and Edge (last line is the user code): // Error // at Function.getStackLine (ngx-logger.js:329) // at NGXMapperService.getCallerDetails (ngx-logger.js:528) // at NGXLogger._log (ngx-logger.js:801) // at NGXLogger.info (ngx-logger.js:631) // at AppComponent.handleLog (app.component.ts:38) let defaultProxy = 4; // We make 4 functions call before getting here const firstStackLine = error.stack.split('\n')[0]; if (!firstStackLine.includes('.js:')) { // The stacktrace starts with no function call (example in Chrome or Edge) defaultProxy = defaultProxy + 1; } return error.stack.split('\n')[(defaultProxy + (config.proxiedSteps || 0))]; } catch (e) { return null; } } } /** * Get position of caller without using sourceMaps * @param stackLine * @returns */ getLocalPosition(stackLine) { // strip base path, then parse filename, line, and column, stackline looks like this : // Firefox // handleLog@http://localhost:4200/main.js:1158:29 // Chrome and Edge // at AppComponent.handleLog (app.component.ts:38) const positionStartIndex = stackLine.lastIndexOf('\/'); let positionEndIndex = stackLine.indexOf(')'); if (positionEndIndex < 0) { positionEndIndex = undefined; } const position = stackLine.substring(positionStartIndex + 1, positionEndIndex); const dataArray = position.split(':'); if (dataArray.length === 3) { return { fileName: dataArray[0], lineNumber: +dataArray[1], columnNumber: +dataArray[2] }; } return { fileName: 'unknown', lineNumber: 0, columnNumber: 0 }; } getTranspileLocation(stackLine) { // Example stackLine: // Firefox : getStackLine@http://localhost:4200/main.js:358:23 // Chrome and Edge : at Function.getStackLine (ngx-logger.js:329) let locationStartIndex = stackLine.indexOf('('); if (locationStartIndex < 0) { locationStartIndex = stackLine.lastIndexOf('@'); if (locationStartIndex < 0) { locationStartIndex = stackLine.lastIndexOf(' '); } } let locationEndIndex = stackLine.indexOf(')'); if (locationEndIndex < 0) { locationEndIndex = undefined; } return stackLine.substring(locationStartIndex + 1, locationEndIndex); } /** * Gets the URL of the sourcemap (the URL can be relative or absolute, it is browser dependant) * @param stackLine * @returns */ getSourceMapLocation(stackLine) { const file = this.getTranspileLocation(stackLine); const mapFullPath = file.substring(0, file.lastIndexOf(':')); return mapFullPath.substring(0, mapFullPath.lastIndexOf(':')) + '.map'; } getMapping(sourceMap, position) { // => ';' indicates end of a line // => ',' separates mappings in a line // decoded mapping => [ generatedCodeColumn, sourceFileIndex, sourceCodeLine, sourceCodeColumn, nameIndex ] let sourceFileIndex = 0, // second field sourceCodeLine = 0, // third field sourceCodeColumn = 0; // fourth field const lines = sourceMap.mappings.split(';'); for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) { // reset column position to 0 after each line let generatedCodeColumn = 0; // decode sections in line const columns = lines[lineIndex].split(','); for (let columnIndex = 0; columnIndex < columns.length; columnIndex++) { const decodedSection = decode(columns[columnIndex]); if (decodedSection.length >= 4) { // update relative positions generatedCodeColumn += decodedSection[0]; sourceFileIndex += decodedSection[1]; sourceCodeLine += decodedSection[2]; sourceCodeColumn += decodedSection[3]; } // check if matching map if (lineIndex === position.lineNumber) { if (generatedCodeColumn === position.columnNumber) { // matching column and line found return { fileName: sourceMap.sources[sourceFileIndex], lineNumber: sourceCodeLine, columnNumber: sourceCodeColumn }; } else if (columnIndex + 1 === columns.length) { // matching column not found, but line is correct return { fileName: sourceMap.sources[sourceFileIndex], lineNumber: sourceCodeLine, columnNumber: 0 }; } } } } // failed if reached return { fileName: 'unknown', lineNumber: 0, columnNumber: 0 }; } /** * does the http get request to get the source map * @param sourceMapLocation * @param distPosition */ getSourceMap(sourceMapLocation, distPosition) { const req = new HttpRequest('GET', sourceMapLocation); const distPositionKey = `${distPosition.fileName}:${distPosition.lineNumber}:${distPosition.columnNumber}`; // if the specific log position is already in cache return it if (this.logPositionCache.has(distPositionKey)) { return this.logPositionCache.get(distPositionKey); } // otherwise check if the source map is already cached for given source map location if (!this.sourceMapCache.has(sourceMapLocation)) { if (!this.httpBackend) { console.error('NGXLogger : Can\'t get sourcemap because HttpBackend is not provided. You need to import HttpClientModule'); this.sourceMapCache.set(sourceMapLocation, of(null)); } else { // obtain the source map if not cached this.sourceMapCache.set(sourceMapLocation, this.httpBackend.handle(req).pipe(filter((e) => e instanceof HttpResponse), map((httpResponse) => httpResponse.body), retry(3), shareReplay(1))); } } // at this point the source map is cached, use it to get specific log position mapping const logPosition$ = this.sourceMapCache.get(sourceMapLocation).pipe(map((sourceMap) => { // sourceMap can be null if HttpBackend is not provided for example if (!sourceMap) { return distPosition; } // map generated position to source position return this.getMapping(sourceMap, distPosition); }), catchError(() => of(distPosition)), shareReplay(1)); // store specific log position in cache for given dest position and return it this.logPositionCache.set(distPositionKey, logPosition$); return logPosition$; } } /** @nocollapse */ NGXLoggerMapperService.ɵfac = function NGXLoggerMapperService_Factory(t) { return new (t || NGXLoggerMapperService)(ɵɵinject(HttpBackend, 8)); }; /** @nocollapse */ NGXLoggerMapperService.ɵprov = ɵɵdefineInjectable({ token: NGXLoggerMapperService, factory: NGXLoggerMapperService.ɵfac }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵsetClassMetadata(NGXLoggerMapperService, [{ type: Injectable }], function () { return [{ type: HttpBackend, decorators: [{ type: Optional }] }]; }, null); })(); /** * Injection token of logger metadata service */ const TOKEN_LOGGER_METADATA_SERVICE = 'TOKEN_LOGGER_METADATA_SERVICE'; class NGXLoggerMetadataService { constructor(datePipe) { this.datePipe = datePipe; } computeTimestamp(config) { const defaultTimestamp = () => new Date().toISOString(); if (config.timestampFormat) { if (!this.datePipe) { console.error('NGXLogger : Can\'t use timeStampFormat because DatePipe is not provided. You need to provide DatePipe'); return defaultTimestamp(); } else { return this.datePipe.transform(new Date(), config.timestampFormat); } } return defaultTimestamp(); } getMetadata(level, config, message, additional) { const metadata = { level: level, additional: additional, }; // The user can send a function // This is useful in order to compute string concatenation only when the log will actually be written if (message && typeof message === 'function') { metadata.message = message(); } else { metadata.message = message; } metadata.timestamp = this.computeTimestamp(config); return metadata; } } /** @nocollapse */ NGXLoggerMetadataService.ɵfac = function NGXLoggerMetadataService_Factory(t) { return new (t || NGXLoggerMetadataService)(ɵɵinject(DatePipe, 8)); }; /** @nocollapse */ NGXLoggerMetadataService.ɵprov = ɵɵdefineInjectable({ token: NGXLoggerMetadataService, factory: NGXLoggerMetadataService.ɵfac }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵsetClassMetadata(NGXLoggerMetadataService, [{ type: Injectable }], function () { return [{ type: DatePipe, decorators: [{ type: Optional }] }]; }, null); })(); // I kept this class alive only to avoid a breaking change with the old version // This class does not implement anything so it is useless and the interface is enough /** * @deprecated this class does not implement anything thus being useless, you should rather implements @see INGXLoggerMonitor */ class NGXLoggerMonitor { } /** * Injection token of logger metadata service */ const TOKEN_LOGGER_RULES_SERVICE = 'TOKEN_LOGGER_RULES_SERVICE'; class NGXLoggerRulesService { shouldCallWriter(level, config, message, additional) { return !config.disableConsoleLogging && level >= config.level; } shouldCallServer(level, config, message, additional) { return !!config.serverLoggingUrl && level >= config.serverLogLevel; } shouldCallMonitor(level, config, message, additional) { // The default behavior is to call the monitor only if the writer or the server is called return this.shouldCallWriter(level, config, message, additional) || this.shouldCallServer(level, config, message, additional); } } /** @nocollapse */ NGXLoggerRulesService.ɵfac = function NGXLoggerRulesService_Factory(t) { return new (t || NGXLoggerRulesService)(); }; /** @nocollapse */ NGXLoggerRulesService.ɵprov = ɵɵdefineInjectable({ token: NGXLoggerRulesService, factory: NGXLoggerRulesService.ɵfac }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵsetClassMetadata(NGXLoggerRulesService, [{ type: Injectable }], null, null); })(); /** * Injection token of logger server service */ const TOKEN_LOGGER_SERVER_SERVICE = 'TOKEN_LOGGER_SERVER_SERVICE'; class NGXLoggerServerService { constructor(httpBackend) { this.httpBackend = httpBackend; } /** * Transforms an error object into a readable string (taking only the stack) * This is needed because JSON.stringify would return "{}" * @param err the error object * @returns The stack of the error */ secureErrorObject(err) { return err === null || err === void 0 ? void 0 : err.stack; } /** * Transforms the additional parameters to avoid any json error when sending the data to the server * Basically it just replaces unstringifiable object to a string mentioning an error * @param additional The additional data to be sent * @returns The additional data secured */ secureAdditionalParameters(additional) { if (additional === null || additional === undefined) { return null; } return additional.map((next, idx) => { try { if (next instanceof Error) { return this.secureErrorObject(next); } // We just want to make sure the JSON can be parsed, we do not want to actually change the type if (typeof next === 'object') { JSON.stringify(next); } return next; } catch (e) { return `The additional[${idx}] value could not be parsed using JSON.stringify().`; } }); } /** * Transforms the message so that it can be sent to the server * @param message the message to be sent * @returns the message secured */ secureMessage(message) { try { if (message instanceof Error) { return this.secureErrorObject(message); } if (typeof message !== 'string') { message = JSON.stringify(message, null, 2); } } catch (e) { message = 'The provided "message" value could not be parsed with JSON.stringify().'; } return message; } logOnServer(url, logContent, options) { // HttpBackend skips all HttpInterceptors // They may log errors using this service causing circular calls const req = new HttpRequest('POST', url, logContent, options || {}); if (!this.httpBackend) { console.error('NGXLogger : Can\'t log on server because HttpBackend is not provided. You need to import HttpClientModule'); return of(null); } return this.httpBackend.handle(req).pipe(filter(e => e instanceof HttpResponse), map((httpResponse) => httpResponse.body)); } /** * Customise the data sent to the API * @param metadata the data provided by NGXLogger * @returns the data that will be sent to the API in the body */ customiseRequestBody(metadata) { // In our API the body is not customised return metadata; } sendToServer(metadata, config) { // Copying metadata locally because we don't want to change the object for the caller const localMetadata = Object.assign({}, metadata); localMetadata.additional = this.secureAdditionalParameters(localMetadata.additional); localMetadata.message = this.secureMessage(localMetadata.message); // Allow users to customise the data sent to the API const requestBody = this.customiseRequestBody(localMetadata); const headers = config.customHttpHeaders || new HttpHeaders(); if (!headers.has('Content-Type')) { headers.set('Content-Type', 'application/json'); } this.logOnServer(config.serverLoggingUrl, requestBody, { headers, params: config.customHttpParams || new HttpParams(), responseType: config.httpResponseType || 'json', withCredentials: config.withCredentials || false, }).pipe(catchError(err => { // Do not use NGXLogger here because this could cause an infinite loop console.error('NGXLogger: Failed to log on server', err); return throwError(err); })).subscribe(); } } /** @nocollapse */ NGXLoggerServerService.ɵfac = function NGXLoggerServerService_Factory(t) { return new (t || NGXLoggerServerService)(ɵɵinject(HttpBackend, 8)); }; /** @nocollapse */ NGXLoggerServerService.ɵprov = ɵɵdefineInjectable({ token: NGXLoggerServerService, factory: NGXLoggerServerService.ɵfac }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵsetClassMetadata(NGXLoggerServerService, [{ type: Injectable }], function () { return [{ type: HttpBackend, decorators: [{ type: Optional }] }]; }, null); })(); /** * Injection token of logger writer service */ const TOKEN_LOGGER_WRITER_SERVICE = 'TOKEN_LOGGER_WRITER_SERVICE'; var NgxLoggerLevel; (function (NgxLoggerLevel) { NgxLoggerLevel[NgxLoggerLevel["TRACE"] = 0] = "TRACE"; NgxLoggerLevel[NgxLoggerLevel["DEBUG"] = 1] = "DEBUG"; NgxLoggerLevel[NgxLoggerLevel["INFO"] = 2] = "INFO"; NgxLoggerLevel[NgxLoggerLevel["LOG"] = 3] = "LOG"; NgxLoggerLevel[NgxLoggerLevel["WARN"] = 4] = "WARN"; NgxLoggerLevel[NgxLoggerLevel["ERROR"] = 5] = "ERROR"; NgxLoggerLevel[NgxLoggerLevel["FATAL"] = 6] = "FATAL"; NgxLoggerLevel[NgxLoggerLevel["OFF"] = 7] = "OFF"; })(NgxLoggerLevel || (NgxLoggerLevel = {})); const DEFAULT_COLOR_SCHEME = [ 'purple', 'teal', 'gray', 'gray', 'red', 'red', 'red' ]; class NGXLoggerWriterService { constructor(platformId) { this.platformId = platformId; this.isIE = isPlatformBrowser(platformId) && navigator && navigator.userAgent && !!(navigator.userAgent.indexOf('MSIE') !== -1 || navigator.userAgent.match(/Trident\//) || navigator.userAgent.match(/Edge\//)); this.logFunc = this.isIE ? this.logIE.bind(this) : this.logModern.bind(this); } /** Generate a "meta" string that is displayed before the content sent to the log function */ prepareMetaString(metadata, config) { const fileDetails = config.disableFileDetails === true ? '' : `[${metadata.fileName}:${metadata.lineNumber}:${metadata.columnNumber}]`; return `${metadata.timestamp} ${NgxLoggerLevel[metadata.level]} ${fileDetails}`; } /** Get the color to use when writing to console */ getColor(metadata, config) { var _a; const configColorScheme = (_a = config.colorScheme) !== null && _a !== void 0 ? _a : DEFAULT_COLOR_SCHEME; // this is needed to avoid a build error if (metadata.level === NgxLoggerLevel.OFF) { return undefined; } return configColorScheme[metadata.level]; } /** Log to the console specifically for IE */ logIE(metadata, config, metaString) { // Coloring doesn't work in IE // make sure additional isn't null or undefined so that ...additional doesn't error const additional = metadata.additional || []; switch (metadata.level) { case NgxLoggerLevel.WARN: console.warn(`${metaString} `, metadata.message, ...additional); break; case NgxLoggerLevel.ERROR: case NgxLoggerLevel.FATAL: console.error(`${metaString} `, metadata.message, ...additional); break; case NgxLoggerLevel.INFO: console.info(`${metaString} `, metadata.message, ...additional); break; default: console.log(`${metaString} `, metadata.message, ...additional); } } /** Log to the console */ logModern(metadata, config, metaString) { const color = this.getColor(metadata, config); // make sure additional isn't null or undefined so that ...additional doesn't error const additional = metadata.additional || []; switch (metadata.level) { case NgxLoggerLevel.WARN: console.warn(`%c${metaString}`, `color:${color}`, metadata.message, ...additional); break; case NgxLoggerLevel.ERROR: case NgxLoggerLevel.FATAL: console.error(`%c${metaString}`, `color:${color}`, metadata.message, ...additional); break; case NgxLoggerLevel.INFO: console.info(`%c${metaString}`, `color:${color}`, metadata.message, ...additional); break; // Disabling console.trace since the stack trace is not helpful. it is showing the stack trace of // the console.trace statement // case NgxLoggerLevel.TRACE: // console.trace(`%c${metaString}`, `color:${color}`, message, ...additional); // break; case NgxLoggerLevel.DEBUG: console.debug(`%c${metaString}`, `color:${color}`, metadata.message, ...additional); break; default: console.log(`%c${metaString}`, `color:${color}`, metadata.message, ...additional); } } /** Write the content sent to the log function to the console */ writeMessage(metadata, config) { const metaString = this.prepareMetaString(metadata, config); this.logFunc(metadata, config, metaString); } } /** @nocollapse */ NGXLoggerWriterService.ɵfac = function NGXLoggerWriterService_Factory(t) { return new (t || NGXLoggerWriterService)(ɵɵinject(PLATFORM_ID)); }; /** @nocollapse */ NGXLoggerWriterService.ɵprov = ɵɵdefineInjectable({ token: NGXLoggerWriterService, factory: NGXLoggerWriterService.ɵfac }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵsetClassMetadata(NGXLoggerWriterService, [{ type: Injectable }], function () { return [{ type: undefined, decorators: [{ type: Inject, args: [PLATFORM_ID] }] }]; }, null); })(); class NGXLogger { constructor(config, configEngineFactory, metadataService, ruleService, mapperService, writerService, serverService) { this.metadataService = metadataService; this.ruleService = ruleService; this.mapperService = mapperService; this.writerService = writerService; this.serverService = serverService; this.configEngine = configEngineFactory.provideConfigEngine(config); } /** Get a readonly access to the level configured for the NGXLogger */ get level() { return this.configEngine.level; } /** Get a readonly access to the serverLogLevel configured for the NGXLogger */ get serverLogLevel() { return this.configEngine.serverLogLevel; } trace(message, ...additional) { this._log(NgxLoggerLevel.TRACE, message, additional); } debug(message, ...additional) { this._log(NgxLoggerLevel.DEBUG, message, additional); } info(message, ...additional) { this._log(NgxLoggerLevel.INFO, message, additional); } log(message, ...additional) { this._log(NgxLoggerLevel.LOG, message, additional); } warn(message, ...additional) { this._log(NgxLoggerLevel.WARN, message, additional); } error(message, ...additional) { this._log(NgxLoggerLevel.ERROR, message, additional); } fatal(message, ...additional) { this._log(NgxLoggerLevel.FATAL, message, additional); } /** @deprecated customHttpHeaders is now part of the config, this should be updated via @see updateConfig */ setCustomHttpHeaders(headers) { const config = this.getConfigSnapshot(); config.customHttpHeaders = headers; this.updateConfig(config); } /** @deprecated customHttpParams is now part of the config, this should be updated via @see updateConfig */ setCustomParams(params) { const config = this.getConfigSnapshot(); config.customHttpParams = params; this.updateConfig(config); } /** @deprecated withCredentials is now part of the config, this should be updated via @see updateConfig */ setWithCredentialsOptionValue(withCredentials) { const config = this.getConfigSnapshot(); config.withCredentials = withCredentials; this.updateConfig(config); } /** * Register a INGXLoggerMonitor that will be trigger when a log is either written or sent to server * * There is only one monitor, registering one will overwrite the last one if there was one * @param monitor */ registerMonitor(monitor) { this._loggerMonitor = monitor; } /** Set config of logger * * Warning : This overwrites all the config, if you want to update only one property, you should use @see getConfigSnapshot before */ updateConfig(config) { this.configEngine.updateConfig(config); } /** Get config of logger */ getConfigSnapshot() { return this.configEngine.getConfig(); } _log(level, message, additional = []) { const config = this.configEngine.getConfig(); const shouldCallWriter = this.ruleService.shouldCallWriter(level, config, message, additional); const shouldCallServer = this.ruleService.shouldCallServer(level, config, message, additional); const shouldCallMonitor = this.ruleService.shouldCallMonitor(level, config, message, additional); if (!shouldCallWriter && !shouldCallServer && !shouldCallMonitor) { // If nothing is to be called we return return; } const metadata = this.metadataService.getMetadata(level, config, message, additional); this.mapperService.getLogPosition(config, metadata).pipe(take(1)).subscribe(logPosition => { if (logPosition) { metadata.fileName = logPosition.fileName; metadata.lineNumber = logPosition.lineNumber; metadata.columnNumber = logPosition.columnNumber; } if (shouldCallMonitor && this._loggerMonitor) { this._loggerMonitor.onLog(metadata, config); } if (shouldCallWriter) { this.writerService.writeMessage(metadata, config); } if (shouldCallServer) { this.serverService.sendToServer(metadata, config); } }); } } /** @nocollapse */ NGXLogger.ɵfac = function NGXLogger_Factory(t) { return new (t || NGXLogger)(ɵɵinject(TOKEN_LOGGER_CONFIG), ɵɵinject(TOKEN_LOGGER_CONFIG_ENGINE_FACTORY), ɵɵinject(TOKEN_LOGGER_METADATA_SERVICE), ɵɵinject(TOKEN_LOGGER_RULES_SERVICE), ɵɵinject(TOKEN_LOGGER_MAPPER_SERVICE), ɵɵinject(TOKEN_LOGGER_WRITER_SERVICE), ɵɵinject(TOKEN_LOGGER_SERVER_SERVICE)); }; /** @nocollapse */ NGXLogger.ɵprov = ɵɵdefineInjectable({ token: NGXLogger, factory: NGXLogger.ɵfac, providedIn: 'root' }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵsetClassMetadata(NGXLogger, [{ type: Injectable, args: [{ providedIn: 'root' }] }], function () { return [{ type: undefined, decorators: [{ type: Inject, args: [TOKEN_LOGGER_CONFIG] }] }, { type: undefined, decorators: [{ type: Inject, args: [TOKEN_LOGGER_CONFIG_ENGINE_FACTORY] }] }, { type: undefined, decorators: [{ type: Inject, args: [TOKEN_LOGGER_METADATA_SERVICE] }] }, { type: undefined, decorators: [{ type: Inject, args: [TOKEN_LOGGER_RULES_SERVICE] }] }, { type: undefined, decorators: [{ type: Inject, args: [TOKEN_LOGGER_MAPPER_SERVICE] }] }, { type: undefined, decorators: [{ type: Inject, args: [TOKEN_LOGGER_WRITER_SERVICE] }] }, { type: undefined, decorators: [{ type: Inject, args: [TOKEN_LOGGER_SERVER_SERVICE] }] }]; }, null); })(); // Keeping this to avoid any breaking change for now, this class should be removed later /** * CustomNGXLoggerService is designed to allow users to get a new instance of a logger * @deprecated The logger is now fully customisable so this class is now useless */ class CustomNGXLoggerService { constructor(configEngineFactory, metadataService, ruleService, mapperService, writerService, serverService) { this.configEngineFactory = configEngineFactory; this.metadataService = metadataService; this.ruleService = ruleService; this.mapperService = mapperService; this.writerService = writerService; this.serverService = serverService; } /** * Create an instance of a logger * @deprecated The logger is now fully customisable so this function is now useless, if you want a specific instance of NGXLogger, either use the new keyword or Angular dependency injection * @param config * @param serverService * @param logMonitor * @param mapperService * @returns */ create(config, serverService, logMonitor, mapperService) { const logger = new NGXLogger(config, this.configEngineFactory, this.metadataService, this.ruleService, mapperService || this.mapperService, this.writerService, serverService || this.serverService); if (logMonitor) { logger.registerMonitor(logMonitor); } return logger; } } /** @nocollapse */ CustomNGXLoggerService.ɵfac = function CustomNGXLoggerService_Factory(t) { return new (t || CustomNGXLoggerService)(ɵɵinject(TOKEN_LOGGER_CONFIG_ENGINE_FACTORY), ɵɵinject(TOKEN_LOGGER_METADATA_SERVICE), ɵɵinject(TOKEN_LOGGER_RULES_SERVICE), ɵɵinject(TOKEN_LOGGER_MAPPER_SERVICE), ɵɵinject(TOKEN_LOGGER_WRITER_SERVICE), ɵɵinject(TOKEN_LOGGER_SERVER_SERVICE)); }; /** @nocollapse */ CustomNGXLoggerService.ɵprov = ɵɵdefineInjectable({ token: CustomNGXLoggerService, factory: CustomNGXLoggerService.ɵfac, providedIn: 'root' }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵsetClassMetadata(CustomNGXLoggerService, [{ type: Injectable, args: [{ providedIn: 'root' }] }], function () { return [{ type: undefined, decorators: [{ type: Inject, args: [TOKEN_LOGGER_CONFIG_ENGINE_FACTORY] }] }, { type: undefined, decorators: [{ type: Inject, args: [TOKEN_LOGGER_METADATA_SERVICE] }] }, { type: undefined, decorators: [{ type: Inject, args: [TOKEN_LOGGER_RULES_SERVICE] }] }, { type: undefined, decorators: [{ type: Inject, args: [TOKEN_LOGGER_MAPPER_SERVICE] }] }, { type: undefined, decorators: [{ type: Inject, args: [TOKEN_LOGGER_WRITER_SERVICE] }] }, { type: undefined, decorators: [{ type: Inject, args: [TOKEN_LOGGER_SERVER_SERVICE] }] }]; }, null); })(); class LoggerModule { static forRoot(config, customProvider) { if (!customProvider) { customProvider = {}; } // default config provider if (!customProvider.configProvider) { customProvider.configProvider = { provide: TOKEN_LOGGER_CONFIG, useValue: config || {} }; } else { // if the user provided its own config, we just make sure the injection token is correct if (customProvider.configProvider.provide !== TOKEN_LOGGER_CONFIG) { throw new Error(`Wrong injection token for configProvider, it should be ${TOKEN_LOGGER_CONFIG} and you used ${customProvider.configProvider.provide}`); } } // default configEngine provider if (!customProvider.configEngineFactoryProvider) { customProvider.configEngineFactoryProvider = { provide: TOKEN_LOGGER_CONFIG_ENGINE_FACTORY, useClass: NGXLoggerConfigEngineFactory }; } else { // if the user provided its own configEngineFactory, we just make sure the injection token is correct if (customProvider.configEngineFactoryProvider.provide !== TOKEN_LOGGER_CONFIG_ENGINE_FACTORY) { throw new Error(`Wrong injection token for configEngineFactoryProvider, it should be '${TOKEN_LOGGER_CONFIG_ENGINE_FACTORY}' and you used '${customProvider.configEngineFactoryProvider.provide}'`); } } // default metadata provider if (!customProvider.metadataProvider) { customProvider.metadataProvider = { provide: TOKEN_LOGGER_METADATA_SERVICE, useClass: NGXLoggerMetadataService }; } else { // if the user provided its own metadataService, we just make sure the injection token is correct if (customProvider.metadataProvider.provide !== TOKEN_LOGGER_METADATA_SERVICE) { throw new Error(`Wrong injection token for metadataProvider, it should be '${TOKEN_LOGGER_METADATA_SERVICE}' and you used '${customProvider.metadataProvider.provide}'`); } } // default rule provider if (!customProvider.ruleProvider) { customProvider.ruleProvider = { provide: TOKEN_LOGGER_RULES_SERVICE, useClass: NGXLoggerRulesService }; } else { // if the user provided its own ruleService, we just make sure the injection token is correct if (customProvider.ruleProvider.provide !== TOKEN_LOGGER_RULES_SERVICE) { throw new Error(`Wrong injection token for ruleProvider, it should be '${TOKEN_LOGGER_RULES_SERVICE}' and you used '${customProvider.ruleProvider.provide}'`); } } // default mapper provider if (!customProvider.mapperProvider) { customProvider.mapperProvider = { provide: TOKEN_LOGGER_MAPPER_SERVICE, useClass: NGXLoggerMapperService }; } else { // if the user provided its own mapperService, we just make sure the injection token is correct if (customProvider.mapperProvider.provide !== TOKEN_LOGGER_MAPPER_SERVICE) { throw new Error(`Wrong injection token for mapperProvider, it should be '${TOKEN_LOGGER_MAPPER_SERVICE}' and you used '${customProvider.mapperProvider.provide}'`); } } // default writer provider if (!customProvider.writerProvider) { customProvider.writerProvider = { provide: TOKEN_LOGGER_WRITER_SERVICE, useClass: NGXLoggerWriterService }; } else { // if the user provided its own writerService, we just make sure the injection token is correct if (customProvider.writerProvider.provide !== TOKEN_LOGGER_WRITER_SERVICE) { throw new Error(`Wrong injection token for writerProvider, it should be '${TOKEN_LOGGER_WRITER_SERVICE}' and you used '${customProvider.writerProvider.provide}'`); } } // default server provider if (!customProvider.serverProvider) { customProvider.serverProvider = { provide: TOKEN_LOGGER_SERVER_SERVICE, useClass: NGXLoggerServerService }; } else { // if the user provided its own serverService, we just make sure the injection token is correct if (customProvider.serverProvider.provide !== TOKEN_LOGGER_SERVER_SERVICE) { throw new Error(`Wrong injection token for serverProvider, it should be '${TOKEN_LOGGER_SERVER_SERVICE}' and you used '${customProvider.writerProvider.provide}'`); } } return { ngModule: LoggerModule, providers: [ NGXLogger, customProvider.configProvider, customProvider.configEngineFactoryProvider, customProvider.metadataProvider, customProvider.ruleProvider, customProvider.mapperProvider, customProvider.writerProvider, customProvider.serverProvider, CustomNGXLoggerService, ] }; } static forChild() { // todo : this forChild is useless for now because nothing is different from forRoot. // This should be implemented so that user can change the providers in the forChild return { ngModule: LoggerModule, }; } } /** @nocollapse */ LoggerModule.ɵfac = function LoggerModule_Factory(t) { return new (t || LoggerModule)(); }; /** @nocollapse */ LoggerModule.ɵmod = ɵɵdefineNgModule({ type: LoggerModule }); /** @nocollapse */ LoggerModule.ɵinj = ɵɵdefineInjector({ imports: [[ CommonModule ]] }); (function () { (typeof ngJitMode === "undefined" || ngJitMode) && ɵɵsetNgModuleScope(LoggerModule, { imports: [CommonModule] }); })(); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵsetClassMetadata(LoggerModule, [{ type: NgModule, args: [{ imports: [ CommonModule ], }] }], null, null); })(); /* * Public API Surface of ngx-logger */ /** * Generated bundle index. Do not edit. */ export { CustomNGXLoggerService, DEFAULT_COLOR_SCHEME, LoggerModule, NGXLogger, NGXLoggerConfigEngine, NGXLoggerConfigEngineFactory, NGXLoggerMapperService, NGXLoggerMetadataService, NGXLoggerMonitor, NGXLoggerRulesService, NGXLoggerServerService, NGXLoggerWriterService, NgxLoggerLevel, TOKEN_LOGGER_CONFIG, TOKEN_LOGGER_CONFIG_ENGINE_FACTORY, TOKEN_LOGGER_MAPPER_SERVICE, TOKEN_LOGGER_METADATA_SERVICE, TOKEN_LOGGER_RULES_SERVICE, TOKEN_LOGGER_SERVER_SERVICE, TOKEN_LOGGER_WRITER_SERVICE }; //# sourceMappingURL=ngx-logger.js.map