Reputation: 5524
I'm trying to use LocalDate
type from js-joda as parameter on GraphQL query like this:
@Query(() => DataResponse)
async getData(@Args() filter: DataFilter): Promise<DataResponse> { ... }
And here is filter type definition:
@ArgsType()
export class DataFilter {
@Field({ nullable: true })
@IsOptional()
date?: LocalDate;
@Field()
@Min(1)
page: number;
@Field()
@Min(1)
pageSize: number;
}
I've also registered LocalDate
as scalar type and added it to application providers.
@Scalar('LocalDate', (type) => LocalDate)
export class LocalDateScalar implements CustomScalar<string, LocalDate> {
description = 'A date string, such as 2018-07-01, serialized in ISO8601 format';
parseValue(value: string): LocalDate {
return LocalDate.parse(value);
}
serialize(value: LocalDate): string {
return value.toString();
}
parseLiteral(ast: ValueNode): LocalDate {
if (ast.kind === Kind.STRING) {
return LocalDate.parse(ast.value);
}
return null;
}
}
This is the error I'm getting
[Nest] 9973 - 02/16/2022, 5:33:41 PM ERROR [ExceptionsHandler] year must not be null NullPointerException: year must not be null at requireNonNull (/Users/usr/my-app/node_modules/@js-joda/core/src/assert.js:33:15) at new LocalDate (/Users/usr/my-app/node_modules/@js-joda/core/src/LocalDate.js:284:9) at TransformOperationExecutor.transform (/Users/usr/my-app/node_modules/src/TransformOperationExecutor.ts:160:22) at TransformOperationExecutor.transform (/Users/usr/my-app/node_modules/src/TransformOperationExecutor.ts:333:33) at ClassTransformer.plainToInstance (/Users/usr/my-app/node_modules/src/ClassTransformer.ts:77:21) at Object.plainToClass (/Users/usr/my-app/node_modules/src/index.ts:71:27) at ValidationPipe.transform (/Users/usr/my-app/node_modules/@nestjs/common/pipes/validation.pipe.js:51:39) at /Users/usr/my-app/node_modules/@nestjs/core/pipes/pipes-consumer.js:17:33 at processTicksAndRejections (node:internal/process/task_queues:96:5)
I'm not sure why is this exactly happening but from what I've managed to debug, is that LocalDateScalar
defined above is transforming the value from string to LocalDate
correctly, but the problem is that class-transformer
is also trying to transform the value, and since it's already transformed it recognizes it as object
, which is automatically being call through parameterless constructor and it's causing this error.
This is the line from class-transformer that's calling the constructor
newValue = new (targetType as any)();
Is there maybe a way to tell class-transformers which types to ignore? I'm aware of the @Exclude
attribute, but then property is completely excluded, I just need to exclude property being transformed via plainToClass
method of class-transformer. Or this whole situation should be handled differently?
Any suggestion will be well appreciated.
Upvotes: 1
Views: 3558
Reputation: 1404
Not sure if this is the right solution but I had a similar scalar <string, Big>
working with the following decorators:
@Field(() => AmountScalar) // your actual scalar class
@Type(() => String) // the "serialized" type of the scalar
@Transform(({ value }) => {
return Big(value) // custom parse function
})
amount: Big // the "parsed" type of the scalar
The two custom parse functions in the scalar can also contain some validation steps (like moment.isValid()
in your case) since it will be called before class-validator.
Upvotes: 0