@nestjs/common 9.0.0-next.1 → 9.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Readme.md CHANGED
@@ -65,19 +65,20 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
65
65
  <td>
66
66
  <a href="https://nx.dev" target="_blank"><img src="https://nestjs.com/img/nx-logo.png" height="45" valign="middle" /></a></td>
67
67
  <td>
68
- <a href="https://valor-software.com/" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/valor-software.png" width="170" valign="middle" /></a></td>
68
+ <a href="https://valor-software.com/" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/valor-software.png" width="170" valign="middle" /></a></td><td>
69
+ <a href="https://amplication.com/" target="_blank"><img src="https://nestjs.com/img/amplication-logo.svg" width="190" valign="middle" /></a></td>
69
70
  </tr></table>
70
71
 
71
72
  #### Gold Sponsors
72
73
 
73
74
  <table style="text-align:center;"><tr><td>
74
- <a href="https://careers.labster.com/departments/platform" target="_blank"><img src="https://nestjs.com/img/labster-logo.png" width="170" valign="middle" /></a></td><td>
75
75
  <a href="https://weld.app/" target="_blank"><img src="https://nestjs.com/img/weld-logo.svg" width="140" valign="middle" /></a></td>
76
76
  <td>
77
77
  <a href="https://intrinsic.ventures/" target="_blank"><img src="https://nestjs.com/img/intrinisic-logo.png" width="210" valign="middle" /></a></td>
78
78
  <td>
79
79
  <a href="https://jetbrains.com/" target="_blank"><img src="https://nestjs.com/img/jetbrains-logo.svg" width="110" valign="middle" /></a></td><td>
80
- <a href="https://snyk.co/nestjs" target="_blank"><img src="https://nestjs.com/img/snyk-logo-black.png" width="185" valign="middle" /></a></td></</tr></table>
80
+ <a href="https://snyk.co/nestjs" target="_blank"><img src="https://nestjs.com/img/snyk-logo-black.png" width="185" valign="middle" /></a></td><td>
81
+ <a href="https://fuseautotech.com/" target="_blank"><img src="https://nestjs.com/img/fuse-logo.svg" width="105" valign="middle" /></a></td></</tr></table>
81
82
 
82
83
  #### Silver Sponsors
83
84
 
@@ -127,6 +128,8 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
127
128
  <td align="center" valign="middle"><a href="https://polygon-software.ch/" target="_blank"><img src="https://nestjs.com/img/polygon-logo.svg" width="120" valign="middle" /></a></td>
128
129
  <td align="center" valign="middle"><a href="https://mobilereality.pl/" target="_blank"><img src="https://nestjs.com/img/mobile-reality-logo.png" width="45" valign="middle" /></a></td>
129
130
  <td align="center" valign="middle"><a href="https://boringowl.io/" target="_blank"><img src="https://nestjs.com/img/boringowl-logo.svg" width="120" valign="middle" /></a></td>
131
+ <td align="center" valign="middle"><a href="https://www.mobilefactory.jp/" target="_blank"><img src="https://nestjs.com/img/mobilefactory-logo.png" width="100" valign="middle" /></a></td>
132
+ <td align="center" valign="middle"><a href="https://db.nordbot.app/" target="_blank"><img src="https://nestjs.com/img/nord-logo.png" width="50" valign="middle" /></a></td>
130
133
  </tr></table>
131
134
 
132
135
  ## Backers
@@ -35,6 +35,15 @@ export declare class HttpException extends Error {
35
35
  * @param status HTTP response status code.
36
36
  */
37
37
  constructor(response: string | Record<string, any>, status: number);
38
+ cause: Error | undefined;
39
+ /**
40
+ * Configures error chaining support
41
+ *
42
+ * See:
43
+ * - https://nodejs.org/en/blog/release/v16.9.0/#error-cause
44
+ * - https://github.com/microsoft/TypeScript/issues/45167
45
+ */
46
+ initCause(): void;
38
47
  initMessage(): void;
39
48
  initName(): void;
40
49
  getResponse(): string | object;
@@ -42,6 +42,19 @@ class HttpException extends Error {
42
42
  this.status = status;
43
43
  this.initMessage();
44
44
  this.initName();
45
+ this.initCause();
46
+ }
47
+ /**
48
+ * Configures error chaining support
49
+ *
50
+ * See:
51
+ * - https://nodejs.org/en/blog/release/v16.9.0/#error-cause
52
+ * - https://github.com/microsoft/TypeScript/issues/45167
53
+ */
54
+ initCause() {
55
+ if (this.response instanceof Error) {
56
+ this.cause = this.response;
57
+ }
45
58
  }
46
59
  initMessage() {
47
60
  if ((0, shared_utils_1.isString)(this.response)) {
@@ -27,8 +27,10 @@ export interface HttpServer<TRequest = any, TResponse = any> {
27
27
  listen(port: number | string, hostname: string, callback?: () => void): any;
28
28
  reply(response: any, body: any, statusCode?: number): any;
29
29
  status(response: any, statusCode: number): any;
30
+ end(response: any, message?: string): any;
30
31
  render(response: any, view: string, options: any): any;
31
32
  redirect(response: any, statusCode: number, url: string): any;
33
+ isHeadersSent(response: any): boolean;
32
34
  setHeader(response: any, name: string, value: string): any;
33
35
  setErrorHandler?(handler: Function, prefix?: string): any;
34
36
  setNotFoundHandler?(handler: Function, prefix?: string): any;
@@ -61,7 +61,7 @@ export interface INestApplicationContext {
61
61
  */
62
62
  enableShutdownHooks(signals?: ShutdownSignal[] | string[]): this;
63
63
  /**
64
- * Initalizes the Nest application.
64
+ * Initializes the Nest application.
65
65
  * Calls the Nest lifecycle events.
66
66
  * It isn't mandatory to call this method directly.
67
67
  *
@@ -12,7 +12,7 @@ export declare type VersionValue = string | typeof VERSION_NEUTRAL | Array<strin
12
12
  export interface VersionOptions {
13
13
  /**
14
14
  * Specifies an optional API Version. When configured, methods
15
- * withing the controller will only be routed if the request version
15
+ * within the controller will only be routed if the request version
16
16
  * matches the specified value.
17
17
  *
18
18
  * Supported only by HTTP-based applications (does not apply to non-HTTP microservices).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestjs/common",
3
- "version": "9.0.0-next.1",
3
+ "version": "9.0.1",
4
4
  "description": "Nest - modern, fast, powerful node.js web framework (@common)",
5
5
  "author": "Kamil Mysliwiec",
6
6
  "homepage": "https://nestjs.com",
@@ -0,0 +1,19 @@
1
+ import { FileValidator } from './file-validator.interface';
2
+ export declare type FileTypeValidatorOptions = {
3
+ fileType: string | RegExp;
4
+ };
5
+ /**
6
+ * Defines the built-in FileType File Validator. It validates incoming files mime-type
7
+ * matching a string or a regular expression. Note that this validator uses a naive strategy
8
+ * to check the mime-type and could be fooled if the client provided a file with renamed extension.
9
+ * (for instance, renaming a 'malicious.bat' to 'malicious.jpeg'). To handle such security issues
10
+ * with more reliability, consider checking against the file's [magic-numbers](https://en.wikipedia.org/wiki/Magic_number_%28programming%29)
11
+ *
12
+ * @see [File Validators](https://docs.nestjs.com/techniques/file-upload#validators)
13
+ *
14
+ * @publicApi
15
+ */
16
+ export declare class FileTypeValidator extends FileValidator<FileTypeValidatorOptions> {
17
+ buildErrorMessage(): string;
18
+ isValid(file: any): boolean;
19
+ }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FileTypeValidator = void 0;
4
+ const file_validator_interface_1 = require("./file-validator.interface");
5
+ /**
6
+ * Defines the built-in FileType File Validator. It validates incoming files mime-type
7
+ * matching a string or a regular expression. Note that this validator uses a naive strategy
8
+ * to check the mime-type and could be fooled if the client provided a file with renamed extension.
9
+ * (for instance, renaming a 'malicious.bat' to 'malicious.jpeg'). To handle such security issues
10
+ * with more reliability, consider checking against the file's [magic-numbers](https://en.wikipedia.org/wiki/Magic_number_%28programming%29)
11
+ *
12
+ * @see [File Validators](https://docs.nestjs.com/techniques/file-upload#validators)
13
+ *
14
+ * @publicApi
15
+ */
16
+ class FileTypeValidator extends file_validator_interface_1.FileValidator {
17
+ buildErrorMessage() {
18
+ return `Validation failed (expected type is ${this.validationOptions.fileType})`;
19
+ }
20
+ isValid(file) {
21
+ if (!this.validationOptions) {
22
+ return true;
23
+ }
24
+ if (!file.mimetype) {
25
+ return false;
26
+ }
27
+ return Boolean(file.mimetype.match(this.validationOptions.fileType));
28
+ }
29
+ }
30
+ exports.FileTypeValidator = FileTypeValidator;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Interface describing FileValidators, which can be added to a {@link ParseFilePipe}.
3
+ */
4
+ export declare abstract class FileValidator<TValidationOptions = Record<string, any>> {
5
+ protected readonly validationOptions: TValidationOptions;
6
+ constructor(validationOptions: TValidationOptions);
7
+ /**
8
+ * Indicates if this file should be considered valid, according to the options passed in the constructor.
9
+ * @param file the file from the request object
10
+ */
11
+ abstract isValid(file?: any): boolean | Promise<boolean>;
12
+ /**
13
+ * Builds an error message in case the validation fails.
14
+ * @param file the file from the request object
15
+ */
16
+ abstract buildErrorMessage(file: any): string;
17
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FileValidator = void 0;
4
+ /**
5
+ * Interface describing FileValidators, which can be added to a {@link ParseFilePipe}.
6
+ */
7
+ class FileValidator {
8
+ constructor(validationOptions) {
9
+ this.validationOptions = validationOptions;
10
+ }
11
+ }
12
+ exports.FileValidator = FileValidator;
@@ -0,0 +1,6 @@
1
+ export * from './file-type.validator';
2
+ export * from './file-validator.interface';
3
+ export * from './max-file-size.validator';
4
+ export * from './parse-file-options.interface';
5
+ export * from './parse-file.pipe';
6
+ export * from './parse-file-pipe.builder';
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./file-type.validator"), exports);
5
+ tslib_1.__exportStar(require("./file-validator.interface"), exports);
6
+ tslib_1.__exportStar(require("./max-file-size.validator"), exports);
7
+ tslib_1.__exportStar(require("./parse-file-options.interface"), exports);
8
+ tslib_1.__exportStar(require("./parse-file.pipe"), exports);
9
+ tslib_1.__exportStar(require("./parse-file-pipe.builder"), exports);
@@ -0,0 +1,15 @@
1
+ import { FileValidator } from './file-validator.interface';
2
+ export declare type MaxFileSizeValidatorOptions = {
3
+ maxSize: number;
4
+ };
5
+ /**
6
+ * Defines the built-in MaxSize File Validator
7
+ *
8
+ * @see [File Validators](https://docs.nestjs.com/techniques/file-upload#validators)
9
+ *
10
+ * @publicApi
11
+ */
12
+ export declare class MaxFileSizeValidator extends FileValidator<MaxFileSizeValidatorOptions> {
13
+ buildErrorMessage(): string;
14
+ isValid(file: any): boolean;
15
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MaxFileSizeValidator = void 0;
4
+ const file_validator_interface_1 = require("./file-validator.interface");
5
+ /**
6
+ * Defines the built-in MaxSize File Validator
7
+ *
8
+ * @see [File Validators](https://docs.nestjs.com/techniques/file-upload#validators)
9
+ *
10
+ * @publicApi
11
+ */
12
+ class MaxFileSizeValidator extends file_validator_interface_1.FileValidator {
13
+ buildErrorMessage() {
14
+ return `Validation failed (expected size is less than ${this.validationOptions.maxSize})`;
15
+ }
16
+ isValid(file) {
17
+ if (!this.validationOptions) {
18
+ return true;
19
+ }
20
+ return file.size < this.validationOptions.maxSize;
21
+ }
22
+ }
23
+ exports.MaxFileSizeValidator = MaxFileSizeValidator;
@@ -0,0 +1,7 @@
1
+ import { ErrorHttpStatusCode } from '../../utils/http-error-by-code.util';
2
+ import { FileValidator } from './file-validator.interface';
3
+ export interface ParseFileOptions {
4
+ validators?: FileValidator[];
5
+ errorHttpStatusCode?: ErrorHttpStatusCode;
6
+ exceptionFactory?: (error: string) => any;
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,10 @@
1
+ import { FileTypeValidatorOptions } from './file-type.validator';
2
+ import { MaxFileSizeValidatorOptions } from './max-file-size.validator';
3
+ import { ParseFileOptions } from './parse-file-options.interface';
4
+ import { ParseFilePipe } from './parse-file.pipe';
5
+ export declare class ParseFilePipeBuilder {
6
+ private validators;
7
+ addMaxSizeValidator(options: MaxFileSizeValidatorOptions): this;
8
+ addFileTypeValidator(options: FileTypeValidatorOptions): this;
9
+ build(additionalOptions?: Omit<ParseFileOptions, 'validators'>): ParseFilePipe;
10
+ }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ParseFilePipeBuilder = void 0;
4
+ const file_type_validator_1 = require("./file-type.validator");
5
+ const max_file_size_validator_1 = require("./max-file-size.validator");
6
+ const parse_file_pipe_1 = require("./parse-file.pipe");
7
+ class ParseFilePipeBuilder {
8
+ constructor() {
9
+ this.validators = [];
10
+ }
11
+ addMaxSizeValidator(options) {
12
+ this.validators.push(new max_file_size_validator_1.MaxFileSizeValidator(options));
13
+ return this;
14
+ }
15
+ addFileTypeValidator(options) {
16
+ this.validators.push(new file_type_validator_1.FileTypeValidator(options));
17
+ return this;
18
+ }
19
+ build(additionalOptions) {
20
+ const parseFilePipe = new parse_file_pipe_1.ParseFilePipe(Object.assign(Object.assign({}, additionalOptions), { validators: this.validators }));
21
+ this.validators = [];
22
+ return parseFilePipe;
23
+ }
24
+ }
25
+ exports.ParseFilePipeBuilder = ParseFilePipeBuilder;
@@ -0,0 +1,25 @@
1
+ import { PipeTransform } from '../../interfaces/features/pipe-transform.interface';
2
+ import { ParseFileOptions } from './parse-file-options.interface';
3
+ import { FileValidator } from './file-validator.interface';
4
+ /**
5
+ * Defines the built-in ParseFile Pipe. This pipe can be used to validate incoming files
6
+ * with `@UploadedFile()` decorator. You can use either other specific built-in validators
7
+ * or provide one of your own, simply implementing it through {@link FileValidator}
8
+ * interface and adding it to ParseFilePipe's constructor.
9
+ *
10
+ * @see [Built-in Pipes](https://docs.nestjs.com/pipes#built-in-pipes)
11
+ *
12
+ * @publicApi
13
+ */
14
+ export declare class ParseFilePipe implements PipeTransform<any> {
15
+ protected exceptionFactory: (error: string) => any;
16
+ private readonly validators;
17
+ constructor(options?: ParseFileOptions);
18
+ transform(value: any): Promise<any>;
19
+ protected validate(file: any): Promise<any>;
20
+ private validateOrThrow;
21
+ /**
22
+ * @returns list of validators used in this pipe.
23
+ */
24
+ getValidators(): FileValidator<Record<string, any>>[];
25
+ }
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ParseFilePipe = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const core_1 = require("../../decorators/core");
6
+ const enums_1 = require("../../enums");
7
+ const http_error_by_code_util_1 = require("../../utils/http-error-by-code.util");
8
+ /**
9
+ * Defines the built-in ParseFile Pipe. This pipe can be used to validate incoming files
10
+ * with `@UploadedFile()` decorator. You can use either other specific built-in validators
11
+ * or provide one of your own, simply implementing it through {@link FileValidator}
12
+ * interface and adding it to ParseFilePipe's constructor.
13
+ *
14
+ * @see [Built-in Pipes](https://docs.nestjs.com/pipes#built-in-pipes)
15
+ *
16
+ * @publicApi
17
+ */
18
+ let ParseFilePipe = class ParseFilePipe {
19
+ constructor(options = {}) {
20
+ const { exceptionFactory, errorHttpStatusCode = enums_1.HttpStatus.BAD_REQUEST, validators = [], } = options;
21
+ this.exceptionFactory =
22
+ exceptionFactory ||
23
+ (error => new http_error_by_code_util_1.HttpErrorByCode[errorHttpStatusCode](error));
24
+ this.validators = validators;
25
+ }
26
+ async transform(value) {
27
+ if (this.validators.length) {
28
+ await this.validate(value);
29
+ }
30
+ return value;
31
+ }
32
+ async validate(file) {
33
+ for (const validator of this.validators) {
34
+ await this.validateOrThrow(file, validator);
35
+ }
36
+ return file;
37
+ }
38
+ async validateOrThrow(file, validator) {
39
+ const isValid = await validator.isValid(file);
40
+ if (!isValid) {
41
+ const errorMessage = validator.buildErrorMessage(file);
42
+ throw this.exceptionFactory(errorMessage);
43
+ }
44
+ }
45
+ /**
46
+ * @returns list of validators used in this pipe.
47
+ */
48
+ getValidators() {
49
+ return this.validators;
50
+ }
51
+ };
52
+ ParseFilePipe = tslib_1.__decorate([
53
+ (0, core_1.Injectable)(),
54
+ tslib_1.__param(0, (0, core_1.Optional)()),
55
+ tslib_1.__metadata("design:paramtypes", [Object])
56
+ ], ParseFilePipe);
57
+ exports.ParseFilePipe = ParseFilePipe;
package/pipes/index.d.ts CHANGED
@@ -6,3 +6,4 @@ export * from './parse-float.pipe';
6
6
  export * from './parse-enum.pipe';
7
7
  export * from './parse-uuid.pipe';
8
8
  export * from './validation.pipe';
9
+ export * from './file';
package/pipes/index.js CHANGED
@@ -9,3 +9,4 @@ tslib_1.__exportStar(require("./parse-float.pipe"), exports);
9
9
  tslib_1.__exportStar(require("./parse-enum.pipe"), exports);
10
10
  tslib_1.__exportStar(require("./parse-uuid.pipe"), exports);
11
11
  tslib_1.__exportStar(require("./validation.pipe"), exports);
12
+ tslib_1.__exportStar(require("./file"), exports);
@@ -34,7 +34,7 @@ export declare class ValidationPipe implements PipeTransform<any> {
34
34
  protected toValidate(metadata: ArgumentMetadata): boolean;
35
35
  protected transformPrimitive(value: any, metadata: ArgumentMetadata): any;
36
36
  protected toEmptyIfNil<T = any, R = any>(value: T): R | {};
37
- protected stripProtoKeys(value: Record<string, any>): void;
37
+ protected stripProtoKeys(value: any): void;
38
38
  protected isPrimitive(value: unknown): boolean;
39
39
  protected validate(object: object, validatorOptions?: ValidatorOptions): Promise<ValidationError[]> | ValidationError[];
40
40
  protected flattenValidationErrors(validationErrors: ValidationError[]): string[];
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ValidationPipe = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const iterare_1 = require("iterare");
6
+ const util_1 = require("util");
6
7
  const decorators_1 = require("../decorators");
7
8
  const core_1 = require("../decorators/core");
8
9
  const http_status_enum_1 = require("../enums/http-status.enum");
@@ -118,11 +119,21 @@ let ValidationPipe = class ValidationPipe {
118
119
  return (0, shared_utils_1.isNil)(value) ? {} : value;
119
120
  }
120
121
  stripProtoKeys(value) {
122
+ if (value == null ||
123
+ typeof value !== 'object' ||
124
+ util_1.types.isTypedArray(value)) {
125
+ return;
126
+ }
127
+ if (Array.isArray(value)) {
128
+ for (const v of value) {
129
+ this.stripProtoKeys(v);
130
+ }
131
+ return;
132
+ }
121
133
  delete value.__proto__;
122
- const keys = Object.keys(value);
123
- (0, iterare_1.iterate)(keys)
124
- .filter(key => (0, shared_utils_1.isObject)(value[key]) && value[key])
125
- .forEach(key => this.stripProtoKeys(value[key]));
134
+ for (const key in value) {
135
+ this.stripProtoKeys(value[key]);
136
+ }
126
137
  }
127
138
  isPrimitive(value) {
128
139
  return ['number', 'boolean', 'string'].includes(typeof value);
@@ -119,8 +119,8 @@ let ConsoleLogger = ConsoleLogger_1 = class ConsoleLogger {
119
119
  const contextMessage = context ? (0, cli_colors_util_1.yellow)(`[${context}] `) : '';
120
120
  const timestampDiff = this.updateAndGetTimestampDiff();
121
121
  const formattedLogLevel = logLevel.toUpperCase().padStart(7, ' ');
122
- const formatedMessage = this.formatMessage(logLevel, message, pidMessage, formattedLogLevel, contextMessage, timestampDiff);
123
- process[writeStreamType !== null && writeStreamType !== void 0 ? writeStreamType : 'stdout'].write(formatedMessage);
122
+ const formattedMessage = this.formatMessage(logLevel, message, pidMessage, formattedLogLevel, contextMessage, timestampDiff);
123
+ process[writeStreamType !== null && writeStreamType !== void 0 ? writeStreamType : 'stdout'].write(formattedMessage);
124
124
  });
125
125
  }
126
126
  formatPid(pid) {
@@ -122,7 +122,7 @@ let Logger = Logger_1 = class Logger {
122
122
  }
123
123
  if ((0, shared_utils_1.isObject)(logger)) {
124
124
  if (logger instanceof Logger_1 && logger.constructor !== Logger_1) {
125
- const errorMessage = `Using the "extends Logger" instruction is not allowed in Nest v8. Please, use "extends ConsoleLogger" instead.`;
125
+ const errorMessage = `Using the "extends Logger" instruction is not allowed in Nest v9. Please, use "extends ConsoleLogger" instead.`;
126
126
  this.staticInstanceRef.error(errorMessage);
127
127
  throw new Error(errorMessage);
128
128
  }
@@ -1,4 +1,5 @@
1
1
  export declare const clc: {
2
+ bold: (text: string) => string;
2
3
  green: (text: string) => string;
3
4
  yellow: (text: string) => string;
4
5
  red: (text: string) => string;
@@ -4,6 +4,7 @@ exports.yellow = exports.clc = void 0;
4
4
  const isColorAllowed = () => !process.env.NO_COLOR;
5
5
  const colorIfAllowed = (colorFn) => (text) => isColorAllowed() ? colorFn(text) : text;
6
6
  exports.clc = {
7
+ bold: colorIfAllowed((text) => `\x1B[1m${text}\x1B[0m`),
7
8
  green: colorIfAllowed((text) => `\x1B[32m${text}\x1B[39m`),
8
9
  yellow: colorIfAllowed((text) => `\x1B[33m${text}\x1B[39m`),
9
10
  red: colorIfAllowed((text) => `\x1B[31m${text}\x1B[39m`),