Skip to content

Commit 2ddb8bd

Browse files
fix(common): mark parse date pipe options as optional (#17780)
`ParseDatePipe` is the only built-in pipe whose constructor argument is not decorated with `@Optional()`. The `= {}` default does not cover this, because the injector never calls the constructor with a missing argument: it resolves parameters from `design:paramtypes`, which is `Object` for an interface, and then fails to find a provider for it. As a result, passing the pipe by class — the form used throughout the docs for every other pipe — throws at bootstrap: @get() find(@query('v', ParseDatePipe) v: Date) {} Nest can't resolve dependencies of the ParseDatePipe (?). Please make sure that the argument at index [0] is available in the current module. `@Query('v', ParseBoolPipe)` works, so the failure looks arbitrary and the only workaround is to instantiate the pipe manually (`new ParseDatePipe()`). Decorate the argument with `@Optional()` so the injector passes `undefined` and the existing default value applies. Also widen `private` to `protected` to match every other pipe and this class's own `exceptionFactory`.
1 parent 10ee9b3 commit 2ddb8bd

2 files changed

Lines changed: 22 additions & 1 deletion

File tree

packages/common/pipes/parse-date.pipe.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Injectable } from '../decorators/core/injectable.decorator.js';
2+
import { Optional } from '../decorators/core/optional.decorator.js';
23
import { HttpStatus } from '../enums/http-status.enum.js';
34
import { PipeTransform } from '../interfaces/features/pipe-transform.interface.js';
45
import {
@@ -40,7 +41,9 @@ export interface ParseDatePipeOptions {
4041
export class ParseDatePipe implements PipeTransform {
4142
protected exceptionFactory: (error: string) => any;
4243

43-
constructor(private readonly options: ParseDatePipeOptions = {}) {
44+
constructor(
45+
@Optional() protected readonly options: ParseDatePipeOptions = {},
46+
) {
4447
const { exceptionFactory, errorHttpStatusCode = HttpStatus.BAD_REQUEST } =
4548
options;
4649

packages/common/test/pipes/parse-date.pipe.spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { OPTIONAL_DEPS_METADATA } from '../../constants.js';
12
import { BadRequestException } from '../../exceptions/index.js';
23
import { ParseDatePipe } from '../../pipes/parse-date.pipe.js';
34

@@ -58,4 +59,21 @@ describe('ParseDatePipe', () => {
5859
});
5960
});
6061
});
62+
63+
describe('dependency injection', () => {
64+
it('should mark the options argument as optional', () => {
65+
// Without this metadata the injector cannot instantiate the pipe when it
66+
// is passed by class, e.g. `@Query('date', ParseDatePipe)`.
67+
const metadata = Reflect.getMetadata(
68+
OPTIONAL_DEPS_METADATA,
69+
ParseDatePipe,
70+
);
71+
expect(metadata).toEqual([0]);
72+
});
73+
74+
it('should fall back to the default options when none are injected', () => {
75+
const target = new ParseDatePipe(undefined as any);
76+
expect(() => target.transform('')).toThrow(BadRequestException);
77+
});
78+
});
6179
});

0 commit comments

Comments
 (0)