|
|
@@ -0,0 +1,145 @@
|
|
|
+import chalk from 'chalk';
|
|
|
+
|
|
|
+import { Logger, LogLevel, VendureLogger } from './vendure-logger';
|
|
|
+
|
|
|
+const DEFAULT_CONTEXT = 'Vendure Server';
|
|
|
+
|
|
|
+/**
|
|
|
+ * @description
|
|
|
+ * The default logger, which logs to the console (stdout) with optional timestamps. Since this logger is part of the
|
|
|
+ * default Vendure configuration, you do not need to specify it explicitly in your server config. You would only need
|
|
|
+ * to specify it if you wish to change the log level (which defaults to `LogLevel.Info`) or remove the timestamp.
|
|
|
+ *
|
|
|
+ * @example
|
|
|
+ * ```ts
|
|
|
+ * import { DefaultLogger, LogLevel, VendureConfig } from '@vendure/core';
|
|
|
+ *
|
|
|
+ * export config: VendureConfig = {
|
|
|
+ * // ...
|
|
|
+ * logger: new DefaultLogger({ level: LogLevel.Debug, timestamp: false }),
|
|
|
+ * }
|
|
|
+ * ```
|
|
|
+ *
|
|
|
+ * @docsCategory Logger
|
|
|
+ */
|
|
|
+export class DefaultLogger implements VendureLogger {
|
|
|
+ level: LogLevel = LogLevel.Info;
|
|
|
+ private readonly timestamp: boolean;
|
|
|
+ private readonly localeStringOptions = {
|
|
|
+ year: '2-digit',
|
|
|
+ hour: 'numeric',
|
|
|
+ minute: 'numeric',
|
|
|
+ day: 'numeric',
|
|
|
+ month: 'numeric',
|
|
|
+ };
|
|
|
+ private static originalLogLevel: LogLevel;
|
|
|
+
|
|
|
+ constructor(options?: { level?: LogLevel; timestamp?: boolean; }) {
|
|
|
+ this.level = options && options.level || LogLevel.Info;
|
|
|
+ this.timestamp = options && options.timestamp !== undefined ? options.timestamp : true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @description
|
|
|
+ * A work-around to hide the info-level logs generated by Nest when bootstrapping the AppModule.
|
|
|
+ * To be run directly before the `NestFactory.create()` call in the `bootstrap()` function.
|
|
|
+ *
|
|
|
+ * See https://github.com/nestjs/nest/issues/1838
|
|
|
+ */
|
|
|
+ static hideNestBoostrapLogs(): void {
|
|
|
+ const { logger } = Logger;
|
|
|
+ if (logger instanceof DefaultLogger) {
|
|
|
+ if (logger.level === LogLevel.Info) {
|
|
|
+ this.originalLogLevel = LogLevel.Info;
|
|
|
+ logger.level = LogLevel.Warn;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @description
|
|
|
+ * If the log level was changed by `hideNestBoostrapLogs()`, this method will restore the
|
|
|
+ * original log level. To be run directly after the `NestFactory.create()` call in the
|
|
|
+ * `bootstrap()` function.
|
|
|
+ *
|
|
|
+ * See https://github.com/nestjs/nest/issues/1838
|
|
|
+ */
|
|
|
+ static restoreOriginalLogLevel(): void {
|
|
|
+ const { logger } = Logger;
|
|
|
+ if (logger instanceof DefaultLogger && DefaultLogger.originalLogLevel !== undefined) {
|
|
|
+ logger.level = DefaultLogger.originalLogLevel;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ error(message: string, context: string | undefined = DEFAULT_CONTEXT, trace?: string | undefined): void {
|
|
|
+ if (this.level >= LogLevel.Error) {
|
|
|
+ this.logMessage(
|
|
|
+ chalk.red(`error`),
|
|
|
+ chalk.red(message + trace ? ` trace: \n${trace}` : ''),
|
|
|
+ context,
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ warn(message: string, context: string | undefined = DEFAULT_CONTEXT): void {
|
|
|
+ if (this.level >= LogLevel.Warn) {
|
|
|
+ this.logMessage(
|
|
|
+ chalk.yellow(`warn`),
|
|
|
+ chalk.yellow(message),
|
|
|
+ context,
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ info(message: string, context: string | undefined = DEFAULT_CONTEXT): void {
|
|
|
+ if (this.level >= LogLevel.Info) {
|
|
|
+ this.logMessage(
|
|
|
+ chalk.blue(`info`),
|
|
|
+ message,
|
|
|
+ context,
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ verbose(message: string, context: string | undefined = DEFAULT_CONTEXT): void {
|
|
|
+ if (this.level >= LogLevel.Verbose) {
|
|
|
+ this.logMessage(
|
|
|
+ chalk.magenta(`verbose`),
|
|
|
+ message,
|
|
|
+ context,
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ debug(message: string, context: string | undefined = DEFAULT_CONTEXT): void {
|
|
|
+ if (this.level >= LogLevel.Debug) {
|
|
|
+ this.logMessage(
|
|
|
+ chalk.magenta(`debug`),
|
|
|
+ message,
|
|
|
+ context,
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private logMessage(prefix: string, message: string, context?: string) {
|
|
|
+ process.stdout.write([
|
|
|
+ prefix,
|
|
|
+ this.logTimestamp(),
|
|
|
+ this.logContext(context),
|
|
|
+ message,
|
|
|
+ '\n',
|
|
|
+ ].join(' '));
|
|
|
+ }
|
|
|
+
|
|
|
+ private logContext(context?: string) {
|
|
|
+ return chalk.cyan(`[${context || DEFAULT_CONTEXT}]`);
|
|
|
+ }
|
|
|
+
|
|
|
+ private logTimestamp() {
|
|
|
+ if (this.timestamp) {
|
|
|
+ const timestamp = new Date(Date.now()).toLocaleString(
|
|
|
+ undefined,
|
|
|
+ this.localeStringOptions,
|
|
|
+ );
|
|
|
+ return chalk.gray(timestamp + ' -');
|
|
|
+ } else {
|
|
|
+ return '';
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|