mirror of
https://github.com/nestjs/nest.git
synced 2026-02-24 00:02:56 +00:00
Compare commits
6 Commits
v10.4.6
...
feat/parse
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
676461ff4e | ||
|
|
cd7079bcc0 | ||
|
|
bc4667c15a | ||
|
|
a544552f72 | ||
|
|
954616da7d | ||
|
|
c6b95f54a7 |
@@ -94,7 +94,7 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
<td><a href="https://www.mercedes-benz.com/" target="_blank"><img src="https://nestjs.com/img/logos/mercedes-logo.png" width="100" valign="middle" /></a></td>
|
||||
<td><a href="https://www.dinii.jp/" target="_blank"><img src="https://nestjs.com/img/logos/dinii-logo.png" width="65" valign="middle" /></a></td>
|
||||
<td><a href="https://bloodycase.com/?promocode=NEST" target="_blank"><img src="https://nestjs.com/img/logos/bloodycase-logo.png" width="65" valign="middle" /></a></td>
|
||||
<td><a href="https://handsontable.com/docs/react-data-grid/?utm_source=NestJS_GH&utm_medium=sponsorship&utm_campaign=library_sponsorship_2024" target="_blank"><img src="https://nestjs.com/img/logos/handsontable-logo.svg" width="150" valign="middle" /></a></td>
|
||||
<td><a href="https://handsontable.com/docs/react-data-grid/?utm_source=NestJS_GH&utm_medium=sponsorship&utm_campaign=library_sponsorship_2024" target="_blank"><img src="https://nestjs.com/img/logos/handsontable-dark-logo.svg#2" width="150" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.itflashcards.com/" target="_blank"><img src="https://nestjs.com/img/logos/it_flashcards-logo.png" width="170" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://arcjet.com/?ref=nestjs" target="_blank"><img src="https://nestjs.com/img/logos/arcjet-logo.svg" width="170" valign="middle" /></a></td>
|
||||
</tr>
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "10.4.6"
|
||||
"version": "10.4.7"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/common",
|
||||
"version": "10.4.6",
|
||||
"version": "10.4.7",
|
||||
"description": "Nest - modern, fast, powerful node.js web framework (@common)",
|
||||
"author": "Kamil Mysliwiec",
|
||||
"homepage": "https://nestjs.com",
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
export * from './default-value.pipe';
|
||||
export * from './file';
|
||||
export * from './parse-array.pipe';
|
||||
export * from './parse-bool.pipe';
|
||||
export * from './parse-int.pipe';
|
||||
export * from './parse-float.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';
|
||||
export * from './file';
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
PipeTransform,
|
||||
} from '../interfaces/features/pipe-transform.interface';
|
||||
import { HttpErrorByCode } from '../utils/http-error-by-code.util';
|
||||
import { isNil, isUndefined, isString } from '../utils/shared.utils';
|
||||
import { isNil, isString, isUndefined } from '../utils/shared.utils';
|
||||
import { ValidationPipe, ValidationPipeOptions } from './validation.pipe';
|
||||
|
||||
const VALIDATION_ERROR_MESSAGE = 'Validation failed (parsable array expected)';
|
||||
@@ -21,9 +21,26 @@ export interface ParseArrayOptions
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,21 @@ import { isNil } from '../utils/shared.utils';
|
||||
* @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;
|
||||
}
|
||||
|
||||
|
||||
74
packages/common/pipes/parse-date.pipe.ts
Normal file
74
packages/common/pipes/parse-date.pipe.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { Injectable } from '../decorators/core/injectable.decorator';
|
||||
import { HttpStatus } from '../enums/http-status.enum';
|
||||
import { PipeTransform } from '../interfaces/features/pipe-transform.interface';
|
||||
import {
|
||||
ErrorHttpStatusCode,
|
||||
HttpErrorByCode,
|
||||
} from '../utils/http-error-by-code.util';
|
||||
import { isNil } from '../utils/shared.utils';
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class ParseDatePipe
|
||||
implements PipeTransform<string | number | undefined | null>
|
||||
{
|
||||
protected exceptionFactory: (error: string) => any;
|
||||
|
||||
constructor(private readonly options: ParseDatePipeOptions = {}) {
|
||||
const { exceptionFactory, errorHttpStatusCode = HttpStatus.BAD_REQUEST } =
|
||||
options;
|
||||
|
||||
this.exceptionFactory =
|
||||
exceptionFactory ||
|
||||
(error => new 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: string | number | undefined | null): Date {
|
||||
if (this.options.optional && isNil(value)) {
|
||||
return this.options.default
|
||||
? this.options.default()
|
||||
: (value as undefined | null);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,21 @@ import { isNil } from '../utils/shared.utils';
|
||||
* @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;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,21 @@ import { isNil } from '../utils/shared.utils';
|
||||
* @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;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,21 @@ import { isNil } from '../utils/shared.utils';
|
||||
* @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;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,25 @@ import { isNil, isString } from '../utils/shared.utils';
|
||||
* @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;
|
||||
}
|
||||
|
||||
|
||||
71
packages/common/test/pipes/parse-date.pipe.spec.ts
Normal file
71
packages/common/test/pipes/parse-date.pipe.spec.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { expect } from 'chai';
|
||||
import { BadRequestException } from '../../exceptions';
|
||||
import { ParseDatePipe } from '../../pipes/parse-date.pipe';
|
||||
|
||||
describe('ParseDatePipe', () => {
|
||||
let target: ParseDatePipe;
|
||||
|
||||
beforeEach(() => {
|
||||
target = new ParseDatePipe();
|
||||
});
|
||||
|
||||
describe('transform', () => {
|
||||
describe('when validation passes', () => {
|
||||
it('should return a valid date object', () => {
|
||||
const date = new Date().toISOString();
|
||||
|
||||
const transformedDate = target.transform(date);
|
||||
expect(transformedDate).to.be.instanceOf(Date);
|
||||
expect(transformedDate.toISOString()).to.equal(date);
|
||||
|
||||
const asNumber = transformedDate.getTime();
|
||||
const transformedNumber = target.transform(asNumber);
|
||||
expect(transformedNumber).to.be.instanceOf(Date);
|
||||
expect(transformedNumber.getTime()).to.equal(asNumber);
|
||||
});
|
||||
|
||||
it('should not throw an error if the value is undefined/null and optional is true', () => {
|
||||
const target = new ParseDatePipe({ optional: true });
|
||||
const value = target.transform(undefined);
|
||||
expect(value).to.equal(undefined);
|
||||
});
|
||||
});
|
||||
describe('when default value is provided', () => {
|
||||
it('should return the default value if the value is undefined/null', () => {
|
||||
const defaultValue = new Date();
|
||||
const target = new ParseDatePipe({
|
||||
optional: true,
|
||||
default: () => defaultValue,
|
||||
});
|
||||
const value = target.transform(undefined);
|
||||
expect(value).to.equal(defaultValue);
|
||||
});
|
||||
});
|
||||
describe('when validation fails', () => {
|
||||
it('should throw an error', () => {
|
||||
try {
|
||||
target.transform('123abc');
|
||||
expect.fail();
|
||||
} catch (error) {
|
||||
expect(error).to.be.instanceOf(BadRequestException);
|
||||
expect(error.message).to.equal(
|
||||
'Validation failed (invalid date format)',
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
describe('when empty value', () => {
|
||||
it('should throw an error', () => {
|
||||
try {
|
||||
target.transform('');
|
||||
expect.fail();
|
||||
} catch (error) {
|
||||
expect(error).to.be.instanceOf(BadRequestException);
|
||||
expect(error.message).to.equal(
|
||||
'Validation failed (no Date provided)',
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/core",
|
||||
"version": "10.4.6",
|
||||
"version": "10.4.7",
|
||||
"description": "Nest - modern, fast, powerful node.js web framework (@core)",
|
||||
"author": "Kamil Mysliwiec",
|
||||
"license": "MIT",
|
||||
@@ -36,7 +36,7 @@
|
||||
"uid": "2.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/common": "10.4.6"
|
||||
"@nestjs/common": "10.4.7"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nestjs/common": "^10.0.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/microservices",
|
||||
"version": "10.4.6",
|
||||
"version": "10.4.7",
|
||||
"description": "Nest - modern, fast, powerful node.js web framework (@microservices)",
|
||||
"author": "Kamil Mysliwiec",
|
||||
"license": "MIT",
|
||||
@@ -22,8 +22,8 @@
|
||||
"tslib": "2.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/common": "10.4.6",
|
||||
"@nestjs/core": "10.4.6"
|
||||
"@nestjs/common": "10.4.7",
|
||||
"@nestjs/core": "10.4.7"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@grpc/grpc-js": "*",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/platform-express",
|
||||
"version": "10.4.6",
|
||||
"version": "10.4.7",
|
||||
"description": "Nest - modern, fast, powerful node.js web framework (@platform-express)",
|
||||
"author": "Kamil Mysliwiec",
|
||||
"license": "MIT",
|
||||
@@ -25,8 +25,8 @@
|
||||
"tslib": "2.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/common": "10.4.6",
|
||||
"@nestjs/core": "10.4.6"
|
||||
"@nestjs/common": "10.4.7",
|
||||
"@nestjs/core": "10.4.7"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nestjs/common": "^10.0.0",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { INestApplication, HttpServer } from '@nestjs/common';
|
||||
import { HttpServer, INestApplication } from '@nestjs/common';
|
||||
import {
|
||||
FastifyBodyParser,
|
||||
FastifyInstance,
|
||||
@@ -7,14 +7,14 @@ import {
|
||||
FastifyPluginCallback,
|
||||
FastifyPluginOptions,
|
||||
FastifyRegisterOptions,
|
||||
FastifyRequest,
|
||||
FastifyReply,
|
||||
FastifyRequest,
|
||||
RawServerBase,
|
||||
RawServerDefault,
|
||||
} from 'fastify';
|
||||
import {
|
||||
Chain as LightMyRequestChain,
|
||||
InjectOptions,
|
||||
Chain as LightMyRequestChain,
|
||||
Response as LightMyRequestResponse,
|
||||
} from 'light-my-request';
|
||||
import { FastifyStaticOptions, FastifyViewOptions } from './external';
|
||||
@@ -98,33 +98,19 @@ export interface NestFastifyApplication<
|
||||
opts: FastifyListenOptions,
|
||||
callback?: (err: Error | null, address: string) => void,
|
||||
): Promise<TServer>;
|
||||
listen(
|
||||
opts?: FastifyListenOptions,
|
||||
): Promise<TServer>;
|
||||
listen(opts?: FastifyListenOptions): Promise<TServer>;
|
||||
listen(
|
||||
callback?: (err: Error | null, address: string) => void,
|
||||
): Promise<TServer>;
|
||||
/**
|
||||
* @deprecated Variadic listen method is deprecated. Please use `.listen(optionsObject, callback)` instead. The variadic signature will be removed in `fastify@5`
|
||||
* @see https://github.com/fastify/fastify/pull/3712
|
||||
*/
|
||||
listen(
|
||||
port: number | string,
|
||||
callback?: (err: Error | null, address: string) => void,
|
||||
): Promise<TServer>;
|
||||
/**
|
||||
* @deprecated Variadic listen method is deprecated. Please use `.listen(optionsObject, callback)` instead. The variadic signature will be removed in `fastify@5`
|
||||
* @see https://github.com/fastify/fastify/pull/3712
|
||||
*/
|
||||
listen(
|
||||
port: number | string,
|
||||
address: string,
|
||||
callback?: (err: Error | null, address: string) => void,
|
||||
): Promise<TServer>;
|
||||
/**
|
||||
* @deprecated Variadic listen method is deprecated. Please use `.listen(optionsObject, callback)` instead. The variadic signature will be removed in `fastify@5`
|
||||
* @see https://github.com/fastify/fastify/pull/3712
|
||||
*/
|
||||
listen(
|
||||
port: number | string,
|
||||
address: string,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/platform-fastify",
|
||||
"version": "10.4.6",
|
||||
"version": "10.4.7",
|
||||
"description": "Nest - modern, fast, powerful node.js web framework (@platform-fastify)",
|
||||
"author": "Kamil Mysliwiec",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/platform-socket.io",
|
||||
"version": "10.4.6",
|
||||
"version": "10.4.7",
|
||||
"description": "Nest - modern, fast, powerful node.js web framework (@platform-socket.io)",
|
||||
"author": "Kamil Mysliwiec",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/platform-ws",
|
||||
"version": "10.4.6",
|
||||
"version": "10.4.7",
|
||||
"description": "Nest - modern, fast, powerful node.js web framework (@platform-ws)",
|
||||
"author": "Kamil Mysliwiec",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/testing",
|
||||
"version": "10.4.6",
|
||||
"version": "10.4.7",
|
||||
"description": "Nest - modern, fast, powerful node.js web framework (@testing)",
|
||||
"author": "Kamil Mysliwiec",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/websockets",
|
||||
"version": "10.4.6",
|
||||
"version": "10.4.7",
|
||||
"description": "Nest - modern, fast, powerful node.js web framework (@websockets)",
|
||||
"author": "Kamil Mysliwiec",
|
||||
"license": "MIT",
|
||||
@@ -18,8 +18,8 @@
|
||||
"tslib": "2.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/common": "10.4.6",
|
||||
"@nestjs/core": "10.4.6"
|
||||
"@nestjs/common": "10.4.7",
|
||||
"@nestjs/core": "10.4.7"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nestjs/common": "^10.0.0",
|
||||
|
||||
Reference in New Issue
Block a user