Initial commit - Event Planner application

This commit is contained in:
mberlin
2026-03-18 14:55:56 -03:00
commit 86d779eb4d
7548 changed files with 1006324 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
import { ArgumentMetadata, PipeTransform } from '../interfaces/features/pipe-transform.interface';
/**
* Defines the built-in DefaultValue Pipe
*
* @see [Built-in Pipes](https://docs.nestjs.com/pipes#built-in-pipes)
*
* @publicApi
*/
export declare class DefaultValuePipe<T = any, R = any> implements PipeTransform<T, T | R> {
protected readonly defaultValue: R;
constructor(defaultValue: R);
transform(value?: T, _metadata?: ArgumentMetadata): T | R;
}

View File

@@ -0,0 +1,30 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DefaultValuePipe = void 0;
const tslib_1 = require("tslib");
const injectable_decorator_1 = require("../decorators/core/injectable.decorator");
const shared_utils_1 = require("../utils/shared.utils");
/**
* Defines the built-in DefaultValue Pipe
*
* @see [Built-in Pipes](https://docs.nestjs.com/pipes#built-in-pipes)
*
* @publicApi
*/
let DefaultValuePipe = class DefaultValuePipe {
constructor(defaultValue) {
this.defaultValue = defaultValue;
}
transform(value, _metadata) {
if ((0, shared_utils_1.isNil)(value) ||
((0, shared_utils_1.isNumber)(value) && isNaN(value))) {
return this.defaultValue;
}
return value;
}
};
exports.DefaultValuePipe = DefaultValuePipe;
exports.DefaultValuePipe = DefaultValuePipe = tslib_1.__decorate([
(0, injectable_decorator_1.Injectable)(),
tslib_1.__metadata("design:paramtypes", [Object])
], DefaultValuePipe);

View File

@@ -0,0 +1,62 @@
import { FileValidatorContext } from './file-validator-context.interface';
import { FileValidator } from './file-validator.interface';
import { IFile } from './interfaces';
type FileTypeValidatorContext = FileValidatorContext<Omit<FileTypeValidatorOptions, 'errorMessage'>>;
export type FileTypeValidatorOptions = {
/**
* Expected file type(s) for validation. Can be a string (MIME type)
* or a regular expression to match multiple types.
*
* @example
* // Match a single MIME type
* fileType: 'image/png'
*
* @example
* // Match multiple types using RegExp
* fileType: /^image\/(png|jpeg)$/
*/
fileType: string | RegExp;
/**
* Custom error message displayed when file type validation fails
* Can be provided as a static string, or as a factory function
* that receives the validation context (file and validator configuration)
* and returns a dynamic error message.
*
* @example
* // Static message
* new FileTypeValidator({ fileType: 'image/png', errorMessage: 'Only PNG allowed' })
*
* @example
* // Dynamic message based on file object and validator configuration
* new FileTypeValidator({
* fileType: 'image/png',
* errorMessage: ctx => `Received file type '${ctx.file?.mimetype}', but expected '${ctx.config.fileType}'`
* })
*/
errorMessage?: string | ((ctx: FileTypeValidatorContext) => string);
/**
* If `true`, the validator will skip the magic numbers validation.
* This can be useful when you can't identify some files as there are no common magic numbers available for some file types.
* @default false
*/
skipMagicNumbersValidation?: boolean;
/**
* If `true`, and magic number check fails, fallback to mimetype comparison.
* @default false
*/
fallbackToMimetype?: boolean;
};
/**
* Defines the built-in FileTypeValidator. It validates incoming files by examining
* their magic numbers using the file-type package, providing more reliable file type validation
* than just checking the mimetype string.
*
* @see [File Validators](https://docs.nestjs.com/techniques/file-upload#validators)
*
* @publicApi
*/
export declare class FileTypeValidator extends FileValidator<FileTypeValidatorOptions, IFile> {
buildErrorMessage(file?: IFile): string;
isValid(file?: IFile): Promise<boolean>;
}
export {};

View File

@@ -0,0 +1,102 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FileTypeValidator = void 0;
const url_1 = require("url");
const logger_service_1 = require("../../services/logger.service");
const file_validator_interface_1 = require("./file-validator.interface");
const load_esm_1 = require("load-esm");
const logger = new logger_service_1.Logger('FileTypeValidator');
/**
* Defines the built-in FileTypeValidator. It validates incoming files by examining
* their magic numbers using the file-type package, providing more reliable file type validation
* than just checking the mimetype string.
*
* @see [File Validators](https://docs.nestjs.com/techniques/file-upload#validators)
*
* @publicApi
*/
class FileTypeValidator extends file_validator_interface_1.FileValidator {
buildErrorMessage(file) {
const { errorMessage, ...config } = this.validationOptions;
if (errorMessage) {
return typeof errorMessage === 'function'
? errorMessage({ file, config })
: errorMessage;
}
if (file?.mimetype) {
const baseMessage = `Validation failed (current file type is ${file.mimetype}, expected type is ${this.validationOptions.fileType})`;
/**
* If fallbackToMimetype is enabled, this means the validator failed to detect the file type
* via magic number inspection (e.g. due to an unknown or too short buffer),
* and instead used the mimetype string provided by the client as a fallback.
*
* This message clarifies that fallback logic was used, in case users rely on file signatures.
*/
if (this.validationOptions.fallbackToMimetype) {
return `${baseMessage} - magic number detection failed, used mimetype fallback`;
}
return baseMessage;
}
return `Validation failed (expected type is ${this.validationOptions.fileType})`;
}
async isValid(file) {
if (!this.validationOptions) {
return true;
}
const isFileValid = !!file && 'mimetype' in file;
// Skip magic number validation if set
if (this.validationOptions.skipMagicNumbersValidation) {
return (isFileValid && !!file.mimetype.match(this.validationOptions.fileType));
}
if (!isFileValid)
return false;
if (!file.buffer) {
if (this.validationOptions.fallbackToMimetype) {
return !!file.mimetype.match(this.validationOptions.fileType);
}
return false;
}
try {
let fileTypeModule;
try {
const resolvedPath = require.resolve('file-type');
fileTypeModule = (0, url_1.pathToFileURL)(resolvedPath).href;
}
catch {
fileTypeModule = 'file-type';
}
const { fileTypeFromBuffer } = await (0, load_esm_1.loadEsm)(fileTypeModule);
const fileType = await fileTypeFromBuffer(file.buffer);
if (fileType) {
// Match detected mime type against allowed type
return !!fileType.mime.match(this.validationOptions.fileType);
}
/**
* Fallback logic: If file-type cannot detect magic number (e.g. file too small),
* Optionally fall back to mimetype string for compatibility.
* This is useful for plain text, CSVs, or files without recognizable signatures.
*/
if (this.validationOptions.fallbackToMimetype) {
return !!file.mimetype.match(this.validationOptions.fileType);
}
return false;
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
// Check for common ESM loading issues
if (errorMessage.includes('ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING') ||
errorMessage.includes('Cannot find module') ||
errorMessage.includes('ERR_MODULE_NOT_FOUND')) {
logger.warn(`Failed to load the "file-type" package for magic number validation. ` +
`If you are using Jest, run it with NODE_OPTIONS="--experimental-vm-modules". ` +
`Error: ${errorMessage}`);
}
// Fallback to mimetype if enabled
if (this.validationOptions.fallbackToMimetype) {
return !!file.mimetype.match(this.validationOptions.fileType);
}
return false;
}
}
}
exports.FileTypeValidator = FileTypeValidator;

View File

@@ -0,0 +1,5 @@
import { IFile } from './interfaces';
export type FileValidatorContext<TConfig> = {
file?: IFile;
config: TConfig;
};

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,21 @@
import { IFile } from './interfaces';
/**
* Interface describing FileValidators, which can be added to a ParseFilePipe
*
* @see {ParseFilePipe}
* @publicApi
*/
export declare abstract class FileValidator<TValidationOptions = Record<string, any>, TFile extends IFile = IFile> {
protected readonly validationOptions: TValidationOptions;
constructor(validationOptions: TValidationOptions);
/**
* Indicates if this file should be considered valid, according to the options passed in the constructor.
* @param file the file from the request object
*/
abstract isValid(file?: TFile | TFile[] | Record<string, TFile[]>): boolean | Promise<boolean>;
/**
* Builds an error message in case the validation fails.
* @param file the file from the request object
*/
abstract buildErrorMessage(file: any): string;
}

View File

@@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FileValidator = void 0;
/**
* Interface describing FileValidators, which can be added to a ParseFilePipe
*
* @see {ParseFilePipe}
* @publicApi
*/
class FileValidator {
constructor(validationOptions) {
this.validationOptions = validationOptions;
}
}
exports.FileValidator = FileValidator;

6
node_modules/@nestjs/common/pipes/file/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,6 @@
export * from './file-type.validator';
export * from './file-validator.interface';
export * from './max-file-size.validator';
export * from './parse-file-options.interface';
export * from './parse-file.pipe';
export * from './parse-file-pipe.builder';

9
node_modules/@nestjs/common/pipes/file/index.js generated vendored Normal file
View File

@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("./file-type.validator"), exports);
tslib_1.__exportStar(require("./file-validator.interface"), exports);
tslib_1.__exportStar(require("./max-file-size.validator"), exports);
tslib_1.__exportStar(require("./parse-file-options.interface"), exports);
tslib_1.__exportStar(require("./parse-file.pipe"), exports);
tslib_1.__exportStar(require("./parse-file-pipe.builder"), exports);

View File

@@ -0,0 +1,5 @@
export interface IFile {
mimetype: string;
size: number;
buffer?: Buffer;
}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1 @@
export * from './file.interface';

View File

@@ -0,0 +1,4 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("./file.interface"), exports);

View File

@@ -0,0 +1,44 @@
import { FileValidatorContext } from './file-validator-context.interface';
import { FileValidator } from './file-validator.interface';
import { IFile } from './interfaces';
type MaxFileSizeValidatorContext = FileValidatorContext<Omit<MaxFileSizeValidatorOptions, 'errorMessage' | 'message'>>;
export type MaxFileSizeValidatorOptions = {
/**
* Maximum allowed file size in bytes.
*/
maxSize: number;
/**
* @deprecated Use `errorMessage` instead.
*/
message?: string | ((maxSize: number) => string);
/**
* Custom error message returned when file size validation fails.
* Can be provided as a static string, or as a factory function
* that receives the validation context (file and validator configuration)
* and returns a dynamic error message.
*
* @example
* // Static message
* new MaxFileSizeValidator({ maxSize: 1000, errorMessage: 'File size exceeds the limit' })
*
* @example
* // Dynamic message based on file object and validator configuration
* new MaxFileSizeValidator({
* maxSize: 1000,
* errorMessage: ctx => `Received file size is ${ctx.file?.size}, but it must be smaller than ${ctx.config.maxSize}.`
* })
*/
errorMessage?: string | ((ctx: MaxFileSizeValidatorContext) => string);
};
/**
* Defines the built-in MaxSize File Validator
*
* @see [File Validators](https://docs.nestjs.com/techniques/file-upload#file-validation)
*
* @publicApi
*/
export declare class MaxFileSizeValidator extends FileValidator<MaxFileSizeValidatorOptions, IFile> {
buildErrorMessage(file?: IFile): string;
isValid(file?: IFile): boolean;
}
export {};

View File

@@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MaxFileSizeValidator = void 0;
const file_validator_interface_1 = require("./file-validator.interface");
/**
* Defines the built-in MaxSize File Validator
*
* @see [File Validators](https://docs.nestjs.com/techniques/file-upload#file-validation)
*
* @publicApi
*/
class MaxFileSizeValidator extends file_validator_interface_1.FileValidator {
buildErrorMessage(file) {
const { errorMessage, message, ...config } = this.validationOptions;
if (errorMessage) {
return typeof errorMessage === 'function'
? errorMessage({ file, config })
: errorMessage;
}
if (message) {
return typeof message === 'function'
? message(this.validationOptions.maxSize)
: message;
}
if (file?.size) {
return `Validation failed (current file size is ${file.size}, expected size is less than ${this.validationOptions.maxSize})`;
}
return `Validation failed (expected size is less than ${this.validationOptions.maxSize})`;
}
isValid(file) {
if (!this.validationOptions || !file) {
return true;
}
return 'size' in file && file.size < this.validationOptions.maxSize;
}
}
exports.MaxFileSizeValidator = MaxFileSizeValidator;

View File

@@ -0,0 +1,15 @@
import { ErrorHttpStatusCode } from '../../utils/http-error-by-code.util';
import { FileValidator } from './file-validator.interface';
/**
* @publicApi
*/
export interface ParseFileOptions {
validators?: FileValidator[];
errorHttpStatusCode?: ErrorHttpStatusCode;
exceptionFactory?: (error: string) => any;
/**
* Defines if file parameter is required.
* @default true
*/
fileIsRequired?: boolean;
}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,15 @@
import { FileTypeValidatorOptions } from './file-type.validator';
import { FileValidator } from './file-validator.interface';
import { MaxFileSizeValidatorOptions } from './max-file-size.validator';
import { ParseFileOptions } from './parse-file-options.interface';
import { ParseFilePipe } from './parse-file.pipe';
/**
* @publicApi
*/
export declare class ParseFilePipeBuilder {
private validators;
addMaxSizeValidator(options: MaxFileSizeValidatorOptions): this;
addFileTypeValidator(options: FileTypeValidatorOptions): this;
addValidator(validator: FileValidator): this;
build(additionalOptions?: Omit<ParseFileOptions, 'validators'>): ParseFilePipe;
}

View File

@@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ParseFilePipeBuilder = void 0;
const file_type_validator_1 = require("./file-type.validator");
const max_file_size_validator_1 = require("./max-file-size.validator");
const parse_file_pipe_1 = require("./parse-file.pipe");
/**
* @publicApi
*/
class ParseFilePipeBuilder {
constructor() {
this.validators = [];
}
addMaxSizeValidator(options) {
return this.addValidator(new max_file_size_validator_1.MaxFileSizeValidator(options));
}
addFileTypeValidator(options) {
return this.addValidator(new file_type_validator_1.FileTypeValidator(options));
}
addValidator(validator) {
this.validators.push(validator);
return this;
}
build(additionalOptions) {
const parseFilePipe = new parse_file_pipe_1.ParseFilePipe({
...additionalOptions,
validators: this.validators,
});
this.validators = [];
return parseFilePipe;
}
}
exports.ParseFilePipeBuilder = ParseFilePipeBuilder;

View File

@@ -0,0 +1,28 @@
import { PipeTransform } from '../../interfaces/features/pipe-transform.interface';
import { FileValidator } from './file-validator.interface';
import { ParseFileOptions } from './parse-file-options.interface';
/**
* Defines the built-in ParseFile Pipe. This pipe can be used to validate incoming files
* with `@UploadedFile()` decorator. You can use either other specific built-in validators
* or provide one of your own, simply implementing it through FileValidator interface
* and adding it to ParseFilePipe's constructor.
*
* @see [Built-in Pipes](https://docs.nestjs.com/pipes#built-in-pipes)
*
* @publicApi
*/
export declare class ParseFilePipe implements PipeTransform<any> {
protected exceptionFactory: (error: string) => any;
private readonly validators;
private readonly fileIsRequired;
constructor(options?: ParseFileOptions);
transform(value: any): Promise<any>;
private validateFilesOrFile;
private thereAreNoFilesIn;
protected validate(file: any): Promise<any>;
private validateOrThrow;
/**
* @returns list of validators used in this pipe.
*/
getValidators(): FileValidator<Record<string, any>, import("./interfaces").IFile>[];
}

View File

@@ -0,0 +1,76 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ParseFilePipe = void 0;
const tslib_1 = require("tslib");
const core_1 = require("../../decorators/core");
const enums_1 = require("../../enums");
const http_error_by_code_util_1 = require("../../utils/http-error-by-code.util");
const shared_utils_1 = require("../../utils/shared.utils");
/**
* Defines the built-in ParseFile Pipe. This pipe can be used to validate incoming files
* with `@UploadedFile()` decorator. You can use either other specific built-in validators
* or provide one of your own, simply implementing it through FileValidator interface
* and adding it to ParseFilePipe's constructor.
*
* @see [Built-in Pipes](https://docs.nestjs.com/pipes#built-in-pipes)
*
* @publicApi
*/
let ParseFilePipe = class ParseFilePipe {
constructor(options = {}) {
const { exceptionFactory, errorHttpStatusCode = enums_1.HttpStatus.BAD_REQUEST, validators = [], fileIsRequired, } = options;
this.exceptionFactory =
exceptionFactory ||
(error => new http_error_by_code_util_1.HttpErrorByCode[errorHttpStatusCode](error));
this.validators = validators;
this.fileIsRequired = fileIsRequired ?? true;
}
async transform(value) {
const areThereAnyFilesIn = this.thereAreNoFilesIn(value);
if (areThereAnyFilesIn && this.fileIsRequired) {
throw this.exceptionFactory('File is required');
}
if (!areThereAnyFilesIn && this.validators.length) {
await this.validateFilesOrFile(value);
}
return value;
}
async validateFilesOrFile(value) {
if (Array.isArray(value)) {
await Promise.all(value.map(f => this.validate(f)));
}
else {
await this.validate(value);
}
}
thereAreNoFilesIn(value) {
const isEmptyArray = Array.isArray(value) && (0, shared_utils_1.isEmpty)(value);
const isEmptyObject = (0, shared_utils_1.isObject)(value) && (0, shared_utils_1.isEmpty)(Object.keys(value));
return (0, shared_utils_1.isUndefined)(value) || isEmptyArray || isEmptyObject;
}
async validate(file) {
for (const validator of this.validators) {
await this.validateOrThrow(file, validator);
}
return file;
}
async validateOrThrow(file, validator) {
const isValid = await validator.isValid(file);
if (!isValid) {
const errorMessage = validator.buildErrorMessage(file);
throw this.exceptionFactory(errorMessage);
}
}
/**
* @returns list of validators used in this pipe.
*/
getValidators() {
return this.validators;
}
};
exports.ParseFilePipe = ParseFilePipe;
exports.ParseFilePipe = ParseFilePipe = tslib_1.__decorate([
(0, core_1.Injectable)(),
tslib_1.__param(0, (0, core_1.Optional)()),
tslib_1.__metadata("design:paramtypes", [Object])
], ParseFilePipe);

10
node_modules/@nestjs/common/pipes/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,10 @@
export * from './default-value.pipe';
export * from './file';
export * from './parse-array.pipe';
export * from './parse-bool.pipe';
export * from './parse-date.pipe';
export * from './parse-enum.pipe';
export * from './parse-float.pipe';
export * from './parse-int.pipe';
export * from './parse-uuid.pipe';
export * from './validation.pipe';

13
node_modules/@nestjs/common/pipes/index.js generated vendored Normal file
View File

@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("./default-value.pipe"), exports);
tslib_1.__exportStar(require("./file"), exports);
tslib_1.__exportStar(require("./parse-array.pipe"), exports);
tslib_1.__exportStar(require("./parse-bool.pipe"), exports);
tslib_1.__exportStar(require("./parse-date.pipe"), exports);
tslib_1.__exportStar(require("./parse-enum.pipe"), exports);
tslib_1.__exportStar(require("./parse-float.pipe"), exports);
tslib_1.__exportStar(require("./parse-int.pipe"), exports);
tslib_1.__exportStar(require("./parse-uuid.pipe"), exports);
tslib_1.__exportStar(require("./validation.pipe"), exports);

View File

@@ -0,0 +1,52 @@
import { Type } from '../interfaces';
import { ArgumentMetadata, PipeTransform } from '../interfaces/features/pipe-transform.interface';
import { ValidationPipe, ValidationPipeOptions } from './validation.pipe';
/**
* @publicApi
*/
export interface ParseArrayOptions extends Omit<ValidationPipeOptions, 'transform' | 'validateCustomDecorators' | 'exceptionFactory'> {
/**
* Type for items to be converted into
*/
items?: Type<unknown>;
/**
* Items separator to split string by
* @default ','
*/
separator?: string;
/**
* If true, the pipe will return null or undefined if the value is not provided
* @default false
*/
optional?: boolean;
/**
* A factory function that returns an exception object to be thrown
* if validation fails.
* @param error Error message or object
* @returns The exception object
*/
exceptionFactory?: (error: any) => any;
}
/**
* Defines the built-in ParseArray Pipe
*
* @see [Built-in Pipes](https://docs.nestjs.com/pipes#built-in-pipes)
*
* @publicApi
*/
export declare class ParseArrayPipe implements PipeTransform {
protected readonly options: ParseArrayOptions;
protected readonly validationPipe: ValidationPipe;
protected exceptionFactory: (error: string) => any;
constructor(options?: ParseArrayOptions);
/**
* Method that accesses and performs optional transformation on argument for
* in-flight requests.
*
* @param value currently processed route argument
* @param metadata contains metadata about the currently processed route argument
*/
transform(value: any, metadata: ArgumentMetadata): Promise<any>;
protected isExpectedTypePrimitive(): boolean;
protected validatePrimitive(originalValue: any, index?: number): any;
}

148
node_modules/@nestjs/common/pipes/parse-array.pipe.js generated vendored Normal file
View File

@@ -0,0 +1,148 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ParseArrayPipe = void 0;
const tslib_1 = require("tslib");
const injectable_decorator_1 = require("../decorators/core/injectable.decorator");
const optional_decorator_1 = require("../decorators/core/optional.decorator");
const http_status_enum_1 = require("../enums/http-status.enum");
const http_error_by_code_util_1 = require("../utils/http-error-by-code.util");
const shared_utils_1 = require("../utils/shared.utils");
const validation_pipe_1 = require("./validation.pipe");
const VALIDATION_ERROR_MESSAGE = 'Validation failed (parsable array expected)';
const DEFAULT_ARRAY_SEPARATOR = ',';
/**
* Defines the built-in ParseArray Pipe
*
* @see [Built-in Pipes](https://docs.nestjs.com/pipes#built-in-pipes)
*
* @publicApi
*/
let ParseArrayPipe = class ParseArrayPipe {
constructor(options = {}) {
this.options = options;
this.validationPipe = new validation_pipe_1.ValidationPipe({
transform: true,
validateCustomDecorators: true,
...options,
});
const { exceptionFactory, errorHttpStatusCode = http_status_enum_1.HttpStatus.BAD_REQUEST } = options;
this.exceptionFactory =
exceptionFactory ||
(error => new http_error_by_code_util_1.HttpErrorByCode[errorHttpStatusCode](error));
}
/**
* Method that accesses and performs optional transformation on argument for
* in-flight requests.
*
* @param value currently processed route argument
* @param metadata contains metadata about the currently processed route argument
*/
async transform(value, metadata) {
if (!value && !this.options.optional) {
throw this.exceptionFactory(VALIDATION_ERROR_MESSAGE);
}
else if ((0, shared_utils_1.isNil)(value) && this.options.optional) {
return value;
}
if (!Array.isArray(value)) {
if (!(0, shared_utils_1.isString)(value)) {
throw this.exceptionFactory(VALIDATION_ERROR_MESSAGE);
}
else {
try {
value = value
.trim()
.split(this.options.separator || DEFAULT_ARRAY_SEPARATOR);
}
catch {
throw this.exceptionFactory(VALIDATION_ERROR_MESSAGE);
}
}
}
if (this.options.items) {
const validationMetadata = {
metatype: this.options.items,
type: 'query',
};
const isExpectedTypePrimitive = this.isExpectedTypePrimitive();
const toClassInstance = (item, index) => {
if (this.options.items !== String) {
try {
item = JSON.parse(item);
}
catch {
// Do nothing
}
}
if (isExpectedTypePrimitive) {
return this.validatePrimitive(item, index);
}
return this.validationPipe.transform(item, validationMetadata);
};
if (this.options.stopAtFirstError === false) {
// strict compare to "false" to make sure
// that this option is disabled by default
let errors = [];
const targetArray = value;
for (let i = 0; i < targetArray.length; i++) {
try {
targetArray[i] = await toClassInstance(targetArray[i]);
}
catch (err) {
let message;
if (err.getResponse) {
const response = err.getResponse();
if (Array.isArray(response.message)) {
message = response.message.map((item) => `[${i}] ${item}`);
}
else {
message = `[${i}] ${response.message}`;
}
}
else {
message = err;
}
errors = errors.concat(message);
}
}
if (errors.length > 0) {
throw this.exceptionFactory(errors);
}
return targetArray;
}
else {
value = await Promise.all(value.map(toClassInstance));
}
}
return value;
}
isExpectedTypePrimitive() {
return [Boolean, Number, String].includes(this.options.items);
}
validatePrimitive(originalValue, index) {
if (this.options.items === Number) {
const value = originalValue !== null && originalValue !== '' ? +originalValue : NaN;
if (isNaN(value)) {
throw this.exceptionFactory(`${(0, shared_utils_1.isUndefined)(index) ? '' : `[${index}] `}item must be a number`);
}
return value;
}
else if (this.options.items === String) {
if (!(0, shared_utils_1.isString)(originalValue)) {
return `${originalValue}`;
}
}
else if (this.options.items === Boolean) {
if (typeof originalValue !== 'boolean') {
throw this.exceptionFactory(`${(0, shared_utils_1.isUndefined)(index) ? '' : `[${index}] `}item must be a boolean value`);
}
}
return originalValue;
}
};
exports.ParseArrayPipe = ParseArrayPipe;
exports.ParseArrayPipe = ParseArrayPipe = tslib_1.__decorate([
(0, injectable_decorator_1.Injectable)(),
tslib_1.__param(0, (0, optional_decorator_1.Optional)()),
tslib_1.__metadata("design:paramtypes", [Object])
], ParseArrayPipe);

55
node_modules/@nestjs/common/pipes/parse-bool.pipe.d.ts generated vendored Normal file
View File

@@ -0,0 +1,55 @@
import { ArgumentMetadata, PipeTransform } from '../interfaces/features/pipe-transform.interface';
import { ErrorHttpStatusCode } from '../utils/http-error-by-code.util';
/**
* @publicApi
*/
export interface ParseBoolPipeOptions {
/**
* The HTTP status code to be used in the response when the validation fails.
*/
errorHttpStatusCode?: ErrorHttpStatusCode;
/**
* A factory function that returns an exception object to be thrown
* if validation fails.
* @param error Error message
* @returns The exception object
*/
exceptionFactory?: (error: string) => any;
/**
* If true, the pipe will return null or undefined if the value is not provided
* @default false
*/
optional?: boolean;
}
/**
* Defines the built-in ParseBool Pipe
*
* @see [Built-in Pipes](https://docs.nestjs.com/pipes#built-in-pipes)
*
* @publicApi
*/
export declare class ParseBoolPipe implements PipeTransform<string | boolean, Promise<boolean>> {
protected readonly options?: ParseBoolPipeOptions | undefined;
protected exceptionFactory: (error: string) => any;
constructor(options?: ParseBoolPipeOptions | undefined);
/**
* Method that accesses and performs optional transformation on argument for
* in-flight requests.
*
* @param value currently processed route argument
* @param metadata contains metadata about the currently processed route argument
*/
transform(value: string | boolean, metadata: ArgumentMetadata): Promise<boolean>;
/**
* @param value currently processed route argument
* @returns `true` if `value` is said 'true', ie., if it is equal to the boolean
* `true` or the string `"true"`
*/
protected isTrue(value: string | boolean): boolean;
/**
* @param value currently processed route argument
* @returns `true` if `value` is said 'false', ie., if it is equal to the boolean
* `false` or the string `"false"`
*/
protected isFalse(value: string | boolean): boolean;
}

67
node_modules/@nestjs/common/pipes/parse-bool.pipe.js generated vendored Normal file
View File

@@ -0,0 +1,67 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ParseBoolPipe = void 0;
const tslib_1 = require("tslib");
const injectable_decorator_1 = require("../decorators/core/injectable.decorator");
const optional_decorator_1 = require("../decorators/core/optional.decorator");
const http_status_enum_1 = require("../enums/http-status.enum");
const http_error_by_code_util_1 = require("../utils/http-error-by-code.util");
const shared_utils_1 = require("../utils/shared.utils");
/**
* Defines the built-in ParseBool Pipe
*
* @see [Built-in Pipes](https://docs.nestjs.com/pipes#built-in-pipes)
*
* @publicApi
*/
let ParseBoolPipe = class ParseBoolPipe {
constructor(options) {
this.options = options;
options = options || {};
const { exceptionFactory, errorHttpStatusCode = http_status_enum_1.HttpStatus.BAD_REQUEST } = options;
this.exceptionFactory =
exceptionFactory ||
(error => new http_error_by_code_util_1.HttpErrorByCode[errorHttpStatusCode](error));
}
/**
* Method that accesses and performs optional transformation on argument for
* in-flight requests.
*
* @param value currently processed route argument
* @param metadata contains metadata about the currently processed route argument
*/
async transform(value, metadata) {
if ((0, shared_utils_1.isNil)(value) && this.options?.optional) {
return value;
}
if (this.isTrue(value)) {
return true;
}
if (this.isFalse(value)) {
return false;
}
throw this.exceptionFactory('Validation failed (boolean string is expected)');
}
/**
* @param value currently processed route argument
* @returns `true` if `value` is said 'true', ie., if it is equal to the boolean
* `true` or the string `"true"`
*/
isTrue(value) {
return value === true || value === 'true';
}
/**
* @param value currently processed route argument
* @returns `true` if `value` is said 'false', ie., if it is equal to the boolean
* `false` or the string `"false"`
*/
isFalse(value) {
return value === false || value === 'false';
}
};
exports.ParseBoolPipe = ParseBoolPipe;
exports.ParseBoolPipe = ParseBoolPipe = tslib_1.__decorate([
(0, injectable_decorator_1.Injectable)(),
tslib_1.__param(0, (0, optional_decorator_1.Optional)()),
tslib_1.__metadata("design:paramtypes", [Object])
], ParseBoolPipe);

37
node_modules/@nestjs/common/pipes/parse-date.pipe.d.ts generated vendored Normal file
View File

@@ -0,0 +1,37 @@
import { PipeTransform } from '../interfaces/features/pipe-transform.interface';
import { ErrorHttpStatusCode } from '../utils/http-error-by-code.util';
export interface ParseDatePipeOptions {
/**
* If true, the pipe will return null or undefined if the value is not provided
* @default false
*/
optional?: boolean;
/**
* Default value for the date
*/
default?: () => Date;
/**
* The HTTP status code to be used in the response when the validation fails.
*/
errorHttpStatusCode?: ErrorHttpStatusCode;
/**
* A factory function that returns an exception object to be thrown
* if validation fails.
* @param error Error message
* @returns The exception object
*/
exceptionFactory?: (error: string) => any;
}
export declare class ParseDatePipe implements PipeTransform<string | number | undefined | null> {
private readonly options;
protected exceptionFactory: (error: string) => any;
constructor(options?: ParseDatePipeOptions);
/**
* Method that accesses and performs optional transformation on argument for
* in-flight requests.
*
* @param value currently processed route argument
* @param metadata contains metadata about the currently processed route argument
*/
transform(value: string | number | undefined | null): Date | null | undefined;
}

42
node_modules/@nestjs/common/pipes/parse-date.pipe.js generated vendored Normal file
View File

@@ -0,0 +1,42 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ParseDatePipe = void 0;
const tslib_1 = require("tslib");
const injectable_decorator_1 = require("../decorators/core/injectable.decorator");
const http_status_enum_1 = require("../enums/http-status.enum");
const http_error_by_code_util_1 = require("../utils/http-error-by-code.util");
const shared_utils_1 = require("../utils/shared.utils");
let ParseDatePipe = class ParseDatePipe {
constructor(options = {}) {
this.options = options;
const { exceptionFactory, errorHttpStatusCode = http_status_enum_1.HttpStatus.BAD_REQUEST } = options;
this.exceptionFactory =
exceptionFactory ||
(error => new http_error_by_code_util_1.HttpErrorByCode[errorHttpStatusCode](error));
}
/**
* Method that accesses and performs optional transformation on argument for
* in-flight requests.
*
* @param value currently processed route argument
* @param metadata contains metadata about the currently processed route argument
*/
transform(value) {
if (this.options.optional && (0, shared_utils_1.isNil)(value)) {
return this.options.default ? this.options.default() : value;
}
if (!value) {
throw this.exceptionFactory('Validation failed (no Date provided)');
}
const transformedValue = new Date(value);
if (isNaN(transformedValue.getTime())) {
throw this.exceptionFactory('Validation failed (invalid date format)');
}
return transformedValue;
}
};
exports.ParseDatePipe = ParseDatePipe;
exports.ParseDatePipe = ParseDatePipe = tslib_1.__decorate([
(0, injectable_decorator_1.Injectable)(),
tslib_1.__metadata("design:paramtypes", [Object])
], ParseDatePipe);

46
node_modules/@nestjs/common/pipes/parse-enum.pipe.d.ts generated vendored Normal file
View File

@@ -0,0 +1,46 @@
import { ArgumentMetadata } from '../index';
import { PipeTransform } from '../interfaces/features/pipe-transform.interface';
import { ErrorHttpStatusCode } from '../utils/http-error-by-code.util';
/**
* @publicApi
*/
export interface ParseEnumPipeOptions {
/**
* If true, the pipe will return null or undefined if the value is not provided
* @default false
*/
optional?: boolean;
/**
* The HTTP status code to be used in the response when the validation fails.
*/
errorHttpStatusCode?: ErrorHttpStatusCode;
/**
* A factory function that returns an exception object to be thrown
* if validation fails.
* @param error Error message
* @returns The exception object
*/
exceptionFactory?: (error: string) => any;
}
/**
* Defines the built-in ParseEnum Pipe
*
* @see [Built-in Pipes](https://docs.nestjs.com/pipes#built-in-pipes)
*
* @publicApi
*/
export declare class ParseEnumPipe<T = any> implements PipeTransform<T> {
protected readonly enumType: T;
protected readonly options?: ParseEnumPipeOptions | undefined;
protected exceptionFactory: (error: string) => any;
constructor(enumType: T, options?: ParseEnumPipeOptions | undefined);
/**
* Method that accesses and performs optional transformation on argument for
* in-flight requests.
*
* @param value currently processed route argument
* @param metadata contains metadata about the currently processed route argument
*/
transform(value: T, metadata: ArgumentMetadata): Promise<T>;
protected isEnum(value: T): boolean;
}

55
node_modules/@nestjs/common/pipes/parse-enum.pipe.js generated vendored Normal file
View File

@@ -0,0 +1,55 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ParseEnumPipe = void 0;
const tslib_1 = require("tslib");
const core_1 = require("../decorators/core");
const index_1 = require("../index");
const http_error_by_code_util_1 = require("../utils/http-error-by-code.util");
const shared_utils_1 = require("../utils/shared.utils");
/**
* Defines the built-in ParseEnum Pipe
*
* @see [Built-in Pipes](https://docs.nestjs.com/pipes#built-in-pipes)
*
* @publicApi
*/
let ParseEnumPipe = class ParseEnumPipe {
constructor(enumType, options) {
this.enumType = enumType;
this.options = options;
if (!enumType) {
throw new Error(`"ParseEnumPipe" requires "enumType" argument specified (to validate input values).`);
}
options = options || {};
const { exceptionFactory, errorHttpStatusCode = index_1.HttpStatus.BAD_REQUEST } = options;
this.exceptionFactory =
exceptionFactory ||
(error => new http_error_by_code_util_1.HttpErrorByCode[errorHttpStatusCode](error));
}
/**
* Method that accesses and performs optional transformation on argument for
* in-flight requests.
*
* @param value currently processed route argument
* @param metadata contains metadata about the currently processed route argument
*/
async transform(value, metadata) {
if ((0, shared_utils_1.isNil)(value) && this.options?.optional) {
return value;
}
if (!this.isEnum(value)) {
throw this.exceptionFactory('Validation failed (enum string is expected)');
}
return value;
}
isEnum(value) {
const enumValues = Object.keys(this.enumType).map(item => this.enumType[item]);
return enumValues.includes(value);
}
};
exports.ParseEnumPipe = ParseEnumPipe;
exports.ParseEnumPipe = ParseEnumPipe = tslib_1.__decorate([
(0, core_1.Injectable)(),
tslib_1.__param(1, (0, core_1.Optional)()),
tslib_1.__metadata("design:paramtypes", [Object, Object])
], ParseEnumPipe);

View File

@@ -0,0 +1,49 @@
import { ArgumentMetadata } from '../index';
import { PipeTransform } from '../interfaces/features/pipe-transform.interface';
import { ErrorHttpStatusCode } from '../utils/http-error-by-code.util';
/**
* @publicApi
*/
export interface ParseFloatPipeOptions {
/**
* The HTTP status code to be used in the response when the validation fails.
*/
errorHttpStatusCode?: ErrorHttpStatusCode;
/**
* A factory function that returns an exception object to be thrown
* if validation fails.
* @param error Error message
* @returns The exception object
*/
exceptionFactory?: (error: string) => any;
/**
* If true, the pipe will return null or undefined if the value is not provided
* @default false
*/
optional?: boolean;
}
/**
* Defines the built-in ParseFloat Pipe
*
* @see [Built-in Pipes](https://docs.nestjs.com/pipes#built-in-pipes)
*
* @publicApi
*/
export declare class ParseFloatPipe implements PipeTransform<string> {
protected readonly options?: ParseFloatPipeOptions | undefined;
protected exceptionFactory: (error: string) => any;
constructor(options?: ParseFloatPipeOptions | undefined);
/**
* Method that accesses and performs optional transformation on argument for
* in-flight requests.
*
* @param value currently processed route argument
* @param metadata contains metadata about the currently processed route argument
*/
transform(value: string, metadata: ArgumentMetadata): Promise<number>;
/**
* @param value currently processed route argument
* @returns `true` if `value` is a valid float number
*/
protected isNumeric(value: string): boolean;
}

56
node_modules/@nestjs/common/pipes/parse-float.pipe.js generated vendored Normal file
View File

@@ -0,0 +1,56 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ParseFloatPipe = void 0;
const tslib_1 = require("tslib");
const core_1 = require("../decorators/core");
const index_1 = require("../index");
const http_error_by_code_util_1 = require("../utils/http-error-by-code.util");
const shared_utils_1 = require("../utils/shared.utils");
/**
* Defines the built-in ParseFloat Pipe
*
* @see [Built-in Pipes](https://docs.nestjs.com/pipes#built-in-pipes)
*
* @publicApi
*/
let ParseFloatPipe = class ParseFloatPipe {
constructor(options) {
this.options = options;
options = options || {};
const { exceptionFactory, errorHttpStatusCode = index_1.HttpStatus.BAD_REQUEST } = options;
this.exceptionFactory =
exceptionFactory ||
(error => new http_error_by_code_util_1.HttpErrorByCode[errorHttpStatusCode](error));
}
/**
* Method that accesses and performs optional transformation on argument for
* in-flight requests.
*
* @param value currently processed route argument
* @param metadata contains metadata about the currently processed route argument
*/
async transform(value, metadata) {
if ((0, shared_utils_1.isNil)(value) && this.options?.optional) {
return value;
}
if (!this.isNumeric(value)) {
throw this.exceptionFactory('Validation failed (numeric string is expected)');
}
return parseFloat(value);
}
/**
* @param value currently processed route argument
* @returns `true` if `value` is a valid float number
*/
isNumeric(value) {
return (['string', 'number'].includes(typeof value) &&
!isNaN(parseFloat(value)) &&
isFinite(value));
}
};
exports.ParseFloatPipe = ParseFloatPipe;
exports.ParseFloatPipe = ParseFloatPipe = tslib_1.__decorate([
(0, core_1.Injectable)(),
tslib_1.__param(0, (0, core_1.Optional)()),
tslib_1.__metadata("design:paramtypes", [Object])
], ParseFloatPipe);

48
node_modules/@nestjs/common/pipes/parse-int.pipe.d.ts generated vendored Normal file
View File

@@ -0,0 +1,48 @@
import { ArgumentMetadata, PipeTransform } from '../interfaces/features/pipe-transform.interface';
import { ErrorHttpStatusCode } from '../utils/http-error-by-code.util';
/**
* @publicApi
*/
export interface ParseIntPipeOptions {
/**
* The HTTP status code to be used in the response when the validation fails.
*/
errorHttpStatusCode?: ErrorHttpStatusCode;
/**
* A factory function that returns an exception object to be thrown
* if validation fails.
* @param error Error message
* @returns The exception object
*/
exceptionFactory?: (error: string) => any;
/**
* If true, the pipe will return null or undefined if the value is not provided
* @default false
*/
optional?: boolean;
}
/**
* Defines the built-in ParseInt Pipe
*
* @see [Built-in Pipes](https://docs.nestjs.com/pipes#built-in-pipes)
*
* @publicApi
*/
export declare class ParseIntPipe implements PipeTransform<string> {
protected readonly options?: ParseIntPipeOptions | undefined;
protected exceptionFactory: (error: string) => any;
constructor(options?: ParseIntPipeOptions | undefined);
/**
* Method that accesses and performs optional transformation on argument for
* in-flight requests.
*
* @param value currently processed route argument
* @param metadata contains metadata about the currently processed route argument
*/
transform(value: string, metadata: ArgumentMetadata): Promise<number>;
/**
* @param value currently processed route argument
* @returns `true` if `value` is a valid integer number
*/
protected isNumeric(value: string): boolean;
}

57
node_modules/@nestjs/common/pipes/parse-int.pipe.js generated vendored Normal file
View File

@@ -0,0 +1,57 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ParseIntPipe = void 0;
const tslib_1 = require("tslib");
const injectable_decorator_1 = require("../decorators/core/injectable.decorator");
const optional_decorator_1 = require("../decorators/core/optional.decorator");
const http_status_enum_1 = require("../enums/http-status.enum");
const http_error_by_code_util_1 = require("../utils/http-error-by-code.util");
const shared_utils_1 = require("../utils/shared.utils");
/**
* Defines the built-in ParseInt Pipe
*
* @see [Built-in Pipes](https://docs.nestjs.com/pipes#built-in-pipes)
*
* @publicApi
*/
let ParseIntPipe = class ParseIntPipe {
constructor(options) {
this.options = options;
options = options || {};
const { exceptionFactory, errorHttpStatusCode = http_status_enum_1.HttpStatus.BAD_REQUEST } = options;
this.exceptionFactory =
exceptionFactory ||
(error => new http_error_by_code_util_1.HttpErrorByCode[errorHttpStatusCode](error));
}
/**
* Method that accesses and performs optional transformation on argument for
* in-flight requests.
*
* @param value currently processed route argument
* @param metadata contains metadata about the currently processed route argument
*/
async transform(value, metadata) {
if ((0, shared_utils_1.isNil)(value) && this.options?.optional) {
return value;
}
if (!this.isNumeric(value)) {
throw this.exceptionFactory('Validation failed (numeric string is expected)');
}
return parseInt(value, 10);
}
/**
* @param value currently processed route argument
* @returns `true` if `value` is a valid integer number
*/
isNumeric(value) {
return (['string', 'number'].includes(typeof value) &&
/^-?\d+$/.test(value) &&
isFinite(value));
}
};
exports.ParseIntPipe = ParseIntPipe;
exports.ParseIntPipe = ParseIntPipe = tslib_1.__decorate([
(0, injectable_decorator_1.Injectable)(),
tslib_1.__param(0, (0, optional_decorator_1.Optional)()),
tslib_1.__metadata("design:paramtypes", [Object])
], ParseIntPipe);

49
node_modules/@nestjs/common/pipes/parse-uuid.pipe.d.ts generated vendored Normal file
View File

@@ -0,0 +1,49 @@
import { ArgumentMetadata, PipeTransform } from '../interfaces/features/pipe-transform.interface';
import { ErrorHttpStatusCode } from '../utils/http-error-by-code.util';
/**
* @publicApi
*/
export interface ParseUUIDPipeOptions {
/**
* UUID version to validate
*/
version?: '3' | '4' | '5' | '7';
/**
* The HTTP status code to be used in the response when the validation fails.
*/
errorHttpStatusCode?: ErrorHttpStatusCode;
/**
* A factory function that returns an exception object to be thrown
* if validation fails.
* @param error Error message
* @returns The exception object
*/
exceptionFactory?: (errors: string) => any;
/**
* If true, the pipe will return null or undefined if the value is not provided
* @default false
*/
optional?: boolean;
}
/**
* Defines the built-in ParseUUID Pipe
*
* @see [Built-in Pipes](https://docs.nestjs.com/pipes#built-in-pipes)
*
* @publicApi
*/
export declare class ParseUUIDPipe implements PipeTransform<string> {
protected readonly options?: ParseUUIDPipeOptions | undefined;
protected static uuidRegExps: {
3: RegExp;
4: RegExp;
5: RegExp;
7: RegExp;
all: RegExp;
};
private readonly version;
protected exceptionFactory: (errors: string) => any;
constructor(options?: ParseUUIDPipeOptions | undefined);
transform(value: string, metadata: ArgumentMetadata): Promise<string>;
protected isUUID(str: unknown, version?: string): any;
}

57
node_modules/@nestjs/common/pipes/parse-uuid.pipe.js generated vendored Normal file
View File

@@ -0,0 +1,57 @@
"use strict";
var ParseUUIDPipe_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ParseUUIDPipe = void 0;
const tslib_1 = require("tslib");
const injectable_decorator_1 = require("../decorators/core/injectable.decorator");
const optional_decorator_1 = require("../decorators/core/optional.decorator");
const http_status_enum_1 = require("../enums/http-status.enum");
const http_error_by_code_util_1 = require("../utils/http-error-by-code.util");
const shared_utils_1 = require("../utils/shared.utils");
/**
* Defines the built-in ParseUUID Pipe
*
* @see [Built-in Pipes](https://docs.nestjs.com/pipes#built-in-pipes)
*
* @publicApi
*/
let ParseUUIDPipe = ParseUUIDPipe_1 = class ParseUUIDPipe {
constructor(options) {
this.options = options;
options = options || {};
const { exceptionFactory, errorHttpStatusCode = http_status_enum_1.HttpStatus.BAD_REQUEST, version, } = options;
this.version = version;
this.exceptionFactory =
exceptionFactory ||
(error => new http_error_by_code_util_1.HttpErrorByCode[errorHttpStatusCode](error));
}
async transform(value, metadata) {
if ((0, shared_utils_1.isNil)(value) && this.options?.optional) {
return value;
}
if (!this.isUUID(value, this.version)) {
throw this.exceptionFactory(`Validation failed (uuid${this.version ? ` v ${this.version}` : ''} is expected)`);
}
return value;
}
isUUID(str, version = 'all') {
if (!(0, shared_utils_1.isString)(str)) {
throw this.exceptionFactory('The value passed as UUID is not a string');
}
const pattern = ParseUUIDPipe_1.uuidRegExps[version];
return pattern?.test(str);
}
};
exports.ParseUUIDPipe = ParseUUIDPipe;
ParseUUIDPipe.uuidRegExps = {
3: /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,
4: /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
5: /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
7: /^[0-9A-F]{8}-[0-9A-F]{4}-7[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
all: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i,
};
exports.ParseUUIDPipe = ParseUUIDPipe = ParseUUIDPipe_1 = tslib_1.__decorate([
(0, injectable_decorator_1.Injectable)(),
tslib_1.__param(0, (0, optional_decorator_1.Optional)()),
tslib_1.__metadata("design:paramtypes", [Object])
], ParseUUIDPipe);

View File

@@ -0,0 +1,86 @@
import type { StandardSchemaV1 } from '@standard-schema/spec';
import { ArgumentMetadata, PipeTransform } from '../interfaces/features/pipe-transform.interface.js';
import { ErrorHttpStatusCode } from '../utils/http-error-by-code.util.js';
/**
* @publicApi
*/
export interface StandardSchemaValidationPipeOptions {
/**
* If true, the pipe will return the value produced by the schema
* (which may differ from the input if the schema coerces/transforms values).
* If false, the original input value is returned after successful validation.
* @default true
*/
transform?: boolean;
/**
* If true, the pipe will also validate parameters decorated with custom decorators
* (created with `createParamDecorator`). When false, custom parameters are skipped.
* @default false
*/
validateCustomDecorators?: boolean;
/**
* Options to pass to the standard schema `validate` function.
* These options are forwarded as the second argument to the schema's `~standard.validate` method.
*/
validateOptions?: Record<string, unknown>;
/**
* The HTTP status code to be used in the response when the validation fails.
* @default HttpStatus.BAD_REQUEST
*/
errorHttpStatusCode?: ErrorHttpStatusCode;
/**
* A factory function that returns an exception object to be thrown
* if validation fails.
* @param issues The issues returned by the standard schema validation
* @returns The exception object
*/
exceptionFactory?: (issues: readonly StandardSchemaV1.Issue[]) => any;
}
/**
* Defines the built-in StandardSchemaValidation Pipe.
*
* Uses a standard schema object (conforming to the Standard Schema spec)
* attached to the parameter metadata to validate incoming values.
*
* @see [Standard Schema](https://github.com/standard-schema/standard-schema)
*
* @publicApi
*/
export declare class StandardSchemaValidationPipe implements PipeTransform {
protected readonly options?: StandardSchemaValidationPipeOptions | undefined;
protected isTransformEnabled: boolean;
protected validateCustomDecorators: boolean;
protected validateOptions: Record<string, unknown> | undefined;
protected exceptionFactory: (issues: readonly StandardSchemaV1.Issue[]) => any;
constructor(options?: StandardSchemaValidationPipeOptions | undefined);
/**
* Method that validates the incoming value against the standard schema
* provided in the parameter metadata.
*
* @param value currently processed route argument
* @param metadata contains metadata about the currently processed route argument
*/
transform<T = any>(value: T, metadata: ArgumentMetadata): Promise<T>;
/**
* Determines whether validation should be performed for the given metadata.
* Skips validation for custom decorators unless `validateCustomDecorators` is enabled.
*
* @param metadata contains metadata about the currently processed route argument
* @returns `true` if validation should be performed
*/
protected toValidate(metadata: ArgumentMetadata): boolean;
/**
* Validates a value against a standard schema.
* Can be overridden to customize validation behavior.
*
* @param value The value to validate
* @param schema The standard schema to validate against
* @param options Optional options forwarded to the schema's validate method
* @returns The validation result
*/
protected validate<T = unknown>(value: unknown, schema: StandardSchemaV1, options?: Record<string, unknown>): Promise<StandardSchemaV1.Result<T>> | StandardSchemaV1.Result<T>;
/**
* Strips dangerous prototype pollution keys from an object.
*/
protected stripProtoKeys(value: any): void;
}

View File

@@ -0,0 +1,120 @@
import { __decorate, __metadata, __param } from "tslib";
import { types } from 'util';
import { Injectable } from '../decorators/core/injectable.decorator.js';
import { Optional } from '../decorators/core/optional.decorator.js';
import { HttpStatus } from '../enums/http-status.enum.js';
import { HttpErrorByCode, } from '../utils/http-error-by-code.util.js';
/**
* Built-in JavaScript types that should be excluded from prototype stripping
* to avoid conflicts with test frameworks like Jest's useFakeTimers
*/
const BUILT_IN_TYPES = [Date, RegExp, Error, Map, Set, WeakMap, WeakSet];
/**
* Defines the built-in StandardSchemaValidation Pipe.
*
* Uses a standard schema object (conforming to the Standard Schema spec)
* attached to the parameter metadata to validate incoming values.
*
* @see [Standard Schema](https://github.com/standard-schema/standard-schema)
*
* @publicApi
*/
let StandardSchemaValidationPipe = class StandardSchemaValidationPipe {
options;
isTransformEnabled;
validateCustomDecorators;
validateOptions;
exceptionFactory;
constructor(options) {
this.options = options;
const { transform = true, validateCustomDecorators = false, validateOptions, exceptionFactory, errorHttpStatusCode = HttpStatus.BAD_REQUEST, } = options || {};
this.isTransformEnabled = transform;
this.validateCustomDecorators = validateCustomDecorators;
this.validateOptions = validateOptions;
this.exceptionFactory =
exceptionFactory ||
(issues => {
const messages = issues.map(issue => issue.message);
return new HttpErrorByCode[errorHttpStatusCode](messages);
});
}
/**
* Method that validates the incoming value against the standard schema
* provided in the parameter metadata.
*
* @param value currently processed route argument
* @param metadata contains metadata about the currently processed route argument
*/
async transform(value, metadata) {
const schema = metadata.schema;
if (!schema || !this.toValidate(metadata)) {
return value;
}
this.stripProtoKeys(value);
const result = await this.validate(value, schema, this.validateOptions);
if (result.issues) {
throw this.exceptionFactory(result.issues);
}
return this.isTransformEnabled ? result.value : value;
}
/**
* Determines whether validation should be performed for the given metadata.
* Skips validation for custom decorators unless `validateCustomDecorators` is enabled.
*
* @param metadata contains metadata about the currently processed route argument
* @returns `true` if validation should be performed
*/
toValidate(metadata) {
const { type } = metadata;
if (type === 'custom' && !this.validateCustomDecorators) {
return false;
}
return true;
}
/**
* Validates a value against a standard schema.
* Can be overridden to customize validation behavior.
*
* @param value The value to validate
* @param schema The standard schema to validate against
* @param options Optional options forwarded to the schema's validate method
* @returns The validation result
*/
validate(value, schema, options) {
return schema['~standard'].validate(value, options);
}
/**
* Strips dangerous prototype pollution keys from an object.
*/
stripProtoKeys(value) {
if (value == null ||
typeof value !== 'object' ||
types.isTypedArray(value)) {
return;
}
if (BUILT_IN_TYPES.some(type => value instanceof type)) {
return;
}
if (Array.isArray(value)) {
for (const v of value) {
this.stripProtoKeys(v);
}
return;
}
delete value.__proto__;
delete value.prototype;
const constructorType = value?.constructor;
if (constructorType && !BUILT_IN_TYPES.includes(constructorType)) {
delete value.constructor;
}
for (const key in value) {
this.stripProtoKeys(value[key]);
}
}
};
StandardSchemaValidationPipe = __decorate([
Injectable(),
__param(0, Optional()),
__metadata("design:paramtypes", [Object])
], StandardSchemaValidationPipe);
export { StandardSchemaValidationPipe };

51
node_modules/@nestjs/common/pipes/validation.pipe.d.ts generated vendored Normal file
View File

@@ -0,0 +1,51 @@
import { ClassTransformOptions } from '../interfaces/external/class-transform-options.interface';
import { TransformerPackage } from '../interfaces/external/transformer-package.interface';
import { ValidationError } from '../interfaces/external/validation-error.interface';
import { ValidatorOptions } from '../interfaces/external/validator-options.interface';
import { ValidatorPackage } from '../interfaces/external/validator-package.interface';
import { ArgumentMetadata, PipeTransform } from '../interfaces/features/pipe-transform.interface';
import { Type } from '../interfaces/type.interface';
import { ErrorHttpStatusCode } from '../utils/http-error-by-code.util';
/**
* @publicApi
*/
export interface ValidationPipeOptions extends ValidatorOptions {
transform?: boolean;
disableErrorMessages?: boolean;
transformOptions?: ClassTransformOptions;
errorHttpStatusCode?: ErrorHttpStatusCode;
exceptionFactory?: (errors: ValidationError[]) => any;
validateCustomDecorators?: boolean;
expectedType?: Type<any>;
validatorPackage?: ValidatorPackage;
transformerPackage?: TransformerPackage;
}
/**
* @see [Validation](https://docs.nestjs.com/techniques/validation)
*
* @publicApi
*/
export declare class ValidationPipe implements PipeTransform<any> {
protected isTransformEnabled: boolean;
protected isDetailedOutputDisabled?: boolean;
protected validatorOptions: ValidatorOptions;
protected transformOptions: ClassTransformOptions | undefined;
protected errorHttpStatusCode: ErrorHttpStatusCode;
protected expectedType: Type<any> | undefined;
protected exceptionFactory: (errors: ValidationError[]) => any;
protected validateCustomDecorators: boolean;
constructor(options?: ValidationPipeOptions);
protected loadValidator(validatorPackage?: ValidatorPackage): ValidatorPackage;
protected loadTransformer(transformerPackage?: TransformerPackage): TransformerPackage;
transform(value: any, metadata: ArgumentMetadata): Promise<any>;
createExceptionFactory(): (validationErrors?: ValidationError[]) => unknown;
protected toValidate(metadata: ArgumentMetadata): boolean;
protected transformPrimitive(value: any, metadata: ArgumentMetadata): any;
protected toEmptyIfNil<T = any, R = T>(value: T, metatype: Type<unknown> | object): R | object | string;
protected stripProtoKeys(value: any): void;
protected isPrimitive(value: unknown): boolean;
protected validate(object: object, validatorOptions?: ValidatorOptions): Promise<ValidationError[]> | ValidationError[];
protected flattenValidationErrors(validationErrors: ValidationError[]): string[];
protected mapChildrenToValidationErrors(error: ValidationError, parentPath?: string): ValidationError[];
protected prependConstraintsWithParentProp(parentPath: string, error: ValidationError): ValidationError;
}

245
node_modules/@nestjs/common/pipes/validation.pipe.js generated vendored Normal file
View File

@@ -0,0 +1,245 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ValidationPipe = void 0;
const tslib_1 = require("tslib");
const iterare_1 = require("iterare");
const util_1 = require("util");
const decorators_1 = require("../decorators");
const core_1 = require("../decorators/core");
const http_status_enum_1 = require("../enums/http-status.enum");
const http_error_by_code_util_1 = require("../utils/http-error-by-code.util");
const load_package_util_1 = require("../utils/load-package.util");
const shared_utils_1 = require("../utils/shared.utils");
let classValidator = {};
let classTransformer = {};
/**
* Built-in JavaScript types that should be excluded from prototype stripping
* to avoid conflicts with test frameworks like Jest's useFakeTimers
*/
const BUILT_IN_TYPES = [Date, RegExp, Error, Map, Set, WeakMap, WeakSet];
/**
* @see [Validation](https://docs.nestjs.com/techniques/validation)
*
* @publicApi
*/
let ValidationPipe = class ValidationPipe {
constructor(options) {
options = options || {};
const { transform, disableErrorMessages, errorHttpStatusCode, expectedType, transformOptions, validateCustomDecorators, ...validatorOptions } = options;
// @see [https://github.com/nestjs/nest/issues/10683#issuecomment-1413690508](https://github.com/nestjs/nest/issues/10683#issuecomment-1413690508)
this.validatorOptions = { forbidUnknownValues: false, ...validatorOptions };
this.isTransformEnabled = !!transform;
this.transformOptions = transformOptions;
this.isDetailedOutputDisabled = disableErrorMessages;
this.validateCustomDecorators = validateCustomDecorators || false;
this.errorHttpStatusCode = errorHttpStatusCode || http_status_enum_1.HttpStatus.BAD_REQUEST;
this.expectedType = expectedType;
this.exceptionFactory =
options.exceptionFactory || this.createExceptionFactory();
classValidator = this.loadValidator(options.validatorPackage);
classTransformer = this.loadTransformer(options.transformerPackage);
}
loadValidator(validatorPackage) {
return (validatorPackage ??
(0, load_package_util_1.loadPackage)('class-validator', 'ValidationPipe', () => require('class-validator')));
}
loadTransformer(transformerPackage) {
return (transformerPackage ??
(0, load_package_util_1.loadPackage)('class-transformer', 'ValidationPipe', () => require('class-transformer')));
}
async transform(value, metadata) {
if (this.expectedType) {
metadata = { ...metadata, metatype: this.expectedType };
}
const metatype = metadata.metatype;
if (!metatype || !this.toValidate(metadata)) {
return this.isTransformEnabled
? this.transformPrimitive(value, metadata)
: value;
}
const originalValue = value;
value = this.toEmptyIfNil(value, metatype);
const isNil = value !== originalValue;
const isPrimitive = this.isPrimitive(value);
this.stripProtoKeys(value);
let entity = classTransformer.plainToInstance(metatype, value, this.transformOptions);
const originalEntity = entity;
const isCtorNotEqual = entity.constructor !== metatype;
if (isCtorNotEqual && !isPrimitive) {
entity.constructor = metatype;
}
else if (isCtorNotEqual) {
// when "entity" is a primitive value, we have to temporarily
// replace the entity to perform the validation against the original
// metatype defined inside the handler
entity = { constructor: metatype };
}
const errors = await this.validate(entity, this.validatorOptions);
if (errors.length > 0) {
throw await this.exceptionFactory(errors);
}
if (originalValue === undefined && originalEntity === '') {
// Since SWC requires empty string for validation (to avoid an error),
// a fallback is needed to revert to the original value (when undefined).
// @see [https://github.com/nestjs/nest/issues/14430](https://github.com/nestjs/nest/issues/14430)
return originalValue;
}
if (isPrimitive) {
// if the value is a primitive value and the validation process has been successfully completed
// we have to revert the original value passed through the pipe
entity = originalEntity;
}
if (this.isTransformEnabled) {
return entity;
}
if (isNil) {
// if the value was originally undefined or null, revert it back
return originalValue;
}
// we check if the number of keys of the "validatorOptions" is higher than 1 (instead of 0)
// because the "forbidUnknownValues" now fallbacks to "false" (in case it wasn't explicitly specified)
const shouldTransformToPlain = Object.keys(this.validatorOptions).length > 1;
return shouldTransformToPlain
? classTransformer.classToPlain(entity, this.transformOptions)
: value;
}
createExceptionFactory() {
return (validationErrors = []) => {
if (this.isDetailedOutputDisabled) {
return new http_error_by_code_util_1.HttpErrorByCode[this.errorHttpStatusCode]();
}
const errors = this.flattenValidationErrors(validationErrors);
return new http_error_by_code_util_1.HttpErrorByCode[this.errorHttpStatusCode](errors);
};
}
toValidate(metadata) {
const { metatype, type } = metadata;
if (type === 'custom' && !this.validateCustomDecorators) {
return false;
}
const types = [String, Boolean, Number, Array, Object, Buffer, Date];
return !types.some(t => metatype === t) && !(0, shared_utils_1.isNil)(metatype);
}
transformPrimitive(value, metadata) {
if (!metadata.data) {
// leave top-level query/param objects unmodified
return value;
}
const { type, metatype } = metadata;
if (type !== 'param' && type !== 'query') {
return value;
}
if (metatype === Boolean) {
if ((0, shared_utils_1.isUndefined)(value)) {
// This is an workaround to deal with optional boolean values since
// optional booleans shouldn't be parsed to a valid boolean when
// they were not defined
return undefined;
}
// Any fasly value but `undefined` will be parsed to `false`
return value === true || value === 'true';
}
if (metatype === Number) {
if ((0, shared_utils_1.isUndefined)(value)) {
// This is a workaround to deal with optional numeric values since
// optional numerics shouldn't be parsed to a valid number when
// they were not defined
return undefined;
}
return +value;
}
if (metatype === String && !(0, shared_utils_1.isUndefined)(value)) {
return String(value);
}
return value;
}
toEmptyIfNil(value, metatype) {
if (!(0, shared_utils_1.isNil)(value)) {
return value;
}
if (typeof metatype === 'function' ||
(metatype && 'prototype' in metatype && metatype.prototype?.constructor)) {
return {};
}
// SWC requires empty string to be returned instead of an empty object
// when the value is nil and the metatype is not a class instance, but a plain object (enum, for example).
// Otherwise, the error will be thrown.
// @see [https://github.com/nestjs/nest/issues/12680](https://github.com/nestjs/nest/issues/12680)
return '';
}
stripProtoKeys(value) {
if (value == null ||
typeof value !== 'object' ||
util_1.types.isTypedArray(value)) {
return;
}
// Skip built-in JavaScript primitives to avoid Jest useFakeTimers conflicts
if (BUILT_IN_TYPES.some(type => value instanceof type)) {
return;
}
if (Array.isArray(value)) {
for (const v of value) {
this.stripProtoKeys(v);
}
return;
}
// Delete dangerous prototype pollution keys
delete value.__proto__;
delete value.prototype;
// Only delete constructor if it's NOT a built-in type
const constructorType = value?.constructor;
if (constructorType && !BUILT_IN_TYPES.includes(constructorType)) {
delete value.constructor;
}
for (const key in value) {
this.stripProtoKeys(value[key]);
}
}
isPrimitive(value) {
return ['number', 'boolean', 'string'].includes(typeof value);
}
validate(object, validatorOptions) {
return classValidator.validate(object, validatorOptions);
}
flattenValidationErrors(validationErrors) {
return (0, iterare_1.iterate)(validationErrors)
.map(error => this.mapChildrenToValidationErrors(error))
.flatten()
.filter(item => !!item.constraints)
.map(item => Object.values(item.constraints))
.flatten()
.toArray();
}
mapChildrenToValidationErrors(error, parentPath) {
if (!(error.children && error.children.length)) {
return [error];
}
const validationErrors = [];
parentPath = parentPath
? `${parentPath}.${error.property}`
: error.property;
for (const item of error.children) {
if (item.children && item.children.length) {
validationErrors.push(...this.mapChildrenToValidationErrors(item, parentPath));
}
validationErrors.push(this.prependConstraintsWithParentProp(parentPath, item));
}
return validationErrors;
}
prependConstraintsWithParentProp(parentPath, error) {
const constraints = {};
for (const key in error.constraints) {
constraints[key] = `${parentPath}.${error.constraints[key]}`;
}
return {
...error,
constraints,
};
}
};
exports.ValidationPipe = ValidationPipe;
exports.ValidationPipe = ValidationPipe = tslib_1.__decorate([
(0, core_1.Injectable)(),
tslib_1.__param(0, (0, decorators_1.Optional)()),
tslib_1.__metadata("design:paramtypes", [Object])
], ValidationPipe);