Validation pipe adds missing properties to the dto object - node.js

I am using NestJS. When I used node version 12.13, my data transfer objects had optional fields and validation pipe would just skip them. However, after I updated to node 12.20, if request body corresponding to dto doesn't contain some property, pipe will automatically add this property to object and set it as undefined, which can cause some problems later in my code. Is there a way to avoid this?

This is a side effect of class-transformer to whom your DTO gets passed during validation. You can re-activate the original behavior by passing the following option to your ValidationPipe.
new ValidationPipe({ transformOptions: { exposeUnsetFields: false } })

Related

What is the proper way of parsing query parameters using nestJS?

Let's say we make the following GET API call to our REST API running with NestJS (and fastify):
http://localhost:5000/api/test?arrayParam=["abc","def"]&anotherParam="value"
Without parsing anything, the query object on the backend looks like this:
{
arrayParam: '["abc","def"]',
anotherParam: '"value"'
}
We can see that parameter values are strings, but in the case of arrayParam we would obviously like to work with the actual array.
I come from an expressJS background, and coming from there, there are a couple of approaches. First would be just using a JSON parser middleware, like body-parser. Or just using JSON.parse().
But what is the "proper", NestJS approach? I thought about using type decorators defined in a DTO, and assumed they would be automatically parsed to the type that I defined. But that doesn't work like I assumed it would.
I defined it like this:
#IsOptional()
#IsArray()
arrayParam?: string[];
But validation fails, since arrayParam is a string and not an array. So I assume this is not the correct approach
You are sending it incorrectly
http://localhost:5000/api/test?arrayParam[]=abc&arrayParam[]=def&anotherParam

Calling methods with Node/Expressjs

I have a controller that has a method that uses GET to return an object (json format). I want to call it from another controller.
In order to make it easier to understand, let's call the controllers controllerSrc (source) and controllerTgt (target).
First, I import the controller and instantiate the variable of the method.
const controllerSrc = require('controllerSrc')
const controllerSrcGET= controllerSrc.get
In theory, the controllerSrcGET returns a json object, so when I try to do:
console.log(controlerSrcGET._id)
I should have there the id of the object and work arount it. However, I get undefined.
Extra info
I am working with Morgan, and I've noticed that the GET request that should be printed is not. So I'm guessing that it is not enough to instantiate the controllerSrcGET(?)

Build a validation parameter decorator in typescript

I read the doc, been there, done that. Still no clue how to write a decorator I need in a way that makes common sense.
In brief: Got an interceptor that executes before the validation layer. That simply means that invalid data can get in the interceptor and break the app. To avoid that I would like to use a decorator on some methods, and to be more accurate on parameters of such methods.
public async getUserById(#IsIntNumber() userId: number): Promise<UserEntity>
{
// method logic
}
Here #IsIntNumber() is a custom decorator that validates the userId parameter.
As a matter of fact I'd like to have a little library of mine in the application holding a bunch a that kinds of validation decorators that I could apply to different parameters.
Is there some legal method to do this without shedding too much blood and too many tears?
I know it's a difficult question.
In the docs they sort of say:
The #required decorator adds a metadata entry that marks the parameter
as required. The #validate decorator then wraps the existing greet
method in a function that validates the arguments before invoking the
original method.
Meaning I've got to pack all my validation logic into that validate function or what? Really?
Does it mean that we don't have adequate parameter decorators in TS? Cos if I understand this right, these ones are absolutely, totally unusable.

mongodb / node - ignore certain object properties

Is there a way to tell MongoClient that there are some properties I don't want to store? For example, I have some properties that are cyclic dependencies which fail to serialize - this causes a few problems. I'd rather not have to set them to null before I save them every time, then re-instate those variables when the insert has finished.
One way to do this is with a little help from the omit method of the underscore (or lodash) library. That will cleanly create a copy of your object without the problematic properties.
var objectToInsert = _.omit(fullObject, 'badField1', 'badField2');
collection.insert(objectToInsert, callback);
Another way to go is to use Mongoose which lets you define schemas for your collections so that only those fields in the schema get included when saved.

JsConfig<MyClass>.ExcludePropertyNames example, not working for me

Trying to exclude properties from a model from being included during serialization.
I am using the following syntax:
JsConfig<MyTestClass>.ExcludePropertyNames = new[] { "ShortDescription" };
Just after that I have the following:
return (from o in __someProvider.GetAll() select (new
{
o.Name,
o.ShortDescription
o.InsertDate
}).TranslateTo<MyTestClass>()).ToList()
However once result is returned from the method, it still contains "ShortDescription" field in the Json. Am I doing something wrong?
JsConfig<T>.ExcludePropertyNames appears to be checked only once for each type, in a static constructor for TypeConfig<T>. Thus, if you are configuring ExcludePropertyNames in your service class, just before returning your response, it might be too late -- the TypeConfig properties may already be set up and cached for MyTestClass. I was able to reproduce this.
A more reliable alternative is to move all of your JsConfig<T> configuration to your AppHost setup code.
If you really do need to do this in your service class, e.g. if you are only conditionally excluding property names, then an alternative approach would be to ensure that JsConfig.IncludeNullValues is false (I believe it is by default) and in your service code set ShortDescription to null when appropriate.

Resources