Currently, I am using DTO objects in my controllers and I am pairing them with the class-validator plugin as to parse/validate them. The thing is, I want to assign default values to some of the DTO parameters, but those values should come from configuration. I need some elegant way to inject those default values into the DTO and also get those default values automatically populated in the swagger metainformation for the respective endpoints(I am using the nest swagger plugin to automatically apply the decorators for me). In order to achieve the desired result I see 2 solutions both of which require some unwanted compromises.
Solution 1:
Inject the configuration values into the controller itself and after parsing the DTO in the route handler, passing the parameters and the DTO to a method which will apply them over the DTO. In order to document the default values in the swagger, however, I should manually put '#ApiQuery' attributes over the handler for the default values. First, in this case I use both DTO and also query decorators for the swagger specifically and also I am not sure if that will even work. In short, it is a total mess and I prefer to avoid this 'solution'.
Solution 2:
Entirely skip the DTO approach and go with separate query parameters. I can apply the default values with the default pipe by injecting the configuration into the controller. However, I need to apply the validation rules for each parameter or creating a DTO anyway on which I can apply the validation rules and construct it manually from the query params. Also, I need to manually document all the parameters for swagger to pick-up.
Any better solutions?
You can directly pass default value in ApiProperty decorator like this in your Dto...
#ApiProperty({ default: 'https://www.youtube.com/watch?v=CjG8u6ZZpag' })
#IsString()
#IsNotEmpty()
readonly keyName: string;
You can pass default values from an interceptor and import your default data from your configuration files.
Related
It can be noticed that validating bodies and even route/query params can be much simpler, safer and more readable when you use a DTO instead of, for example, a pipe (depending on the case). As a simple example, I like the idea of using a DTO for validation of the id, like in a findOne() route. So, with a class like this
export class IdDto {
#IsInt()
#IsPositive()
id: number;
}
I can have great validation of the (serial) id. And use it in the route handler like this
findOne(#Param() { id }: IdDto)
The problem is when I have, for example, multiple ids as route params. Obviously I have to name them in a different manner, and then I cannot use this DTO anymore. Unless I create a specific DTO for every case like this one, just renaming the fields. Would there be any way to maintain the usage of this DTO (or any other) in situations like these? Or is there really no alternative?
Of course, I could build my own pipe. It's just that the DTO approach is much simpler, and also class-validator decorators automatically show exactly what step of validation failed. But maybe it's the only option, apart from multiple similar DTOs.
Thanks in advance, and best regards.
P.S.: In the case of multiple ids, that I mentioned, it is a bit more complex. But in the case that I still have just a single id, but want to name it differently in the route? The same question applies, in case it may be simpler.
Generally, decorators on dynamic fields in Typescript doesn't really work because there's no field to (easily) bind to at compile time.
Rather than changing the name of the field, if you are looking for a way to better manage the same decorators across different classes, you could use decorator composition and the applyDecorators method to create a single decorator like
export const IdValidator = applyDecorators(
IsInt(),
IsPositive(),
);
And now use #IdValidator() instead of the others. You still have to make multiple classes, but now have a single source for the entire set of decorators for id validation.
I need to insert an entity using Entity.createQueryBuilder() and get the entity back as one query. .raw returns only excluded fields for some reason and I want the opposite: I want to get the entity with all #Exclude-d fields excluded and others present. How to do this without making a separate query? I know about .returning, but I don't want to manually specify all the fields that I need. Maybe there's something like .returnAllExceptExcluded?
So the answer here is to use .returning('*') and then decorate your controller with ClassSerializerInterceptor, like this:
#UseInterceptors(ClassSerializerInterceptor)
export class UserController {
...
}
`
I would like to have a custom header-enricher that takes the header values to be added and adds them to the header and also, records them in the database. I was trying to create a custom spring tag say: db-recording-header-enricher and use that instead of header-enricher tag wherever I am interested in recording the headers to the database.
And here's what I have so far:
I have custom spring XML name-space with custom element db-recorder-header-enricher correctly configured. I have a test spring integration xml that I am using to test whether the parser is functioning correctly. The test is loading the test XML correctly, except I want to use my custom parser below instead of the HeaderEnricher which it picks up by default as the transformer.
The processor for db-recording-header-enricher looks like:
DbRecorderHeaderEnricherParser implements BeanDefinitionParser {
#Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
BeanDefinition beanDefinition = new StandardHeaderEnricherParser().parse(element, parserContext);
// Set the header Enricher processor to be my custom processor
// beanDefinition.setHeaderEnricherProcessor(dbRecordingHeaderEnricher);
return beanDefinition;
}
}
The problem I am facing is this:
Based on the parser definition above if I use StandardHeaderEnricherParser to parse my xml, I cannot find a way to associate DbRecordingHeaderEnricher as the transformer for the parsing of the header-enricher. Even if I extend StandardHeaderEnricherParser the method below is final, so again I cannot seem to give it my custom parser for transforming purposes.
#Override
protected final String getTransformerClassName() {
return HeaderEnricher.class.getName();
}
All I want to do in my custom parser is associate my custom header enricher (which extends HeaderEnricher class) for the parsing of the headers and creating records into the database for the headers added. If it's not possible the way I am thinking about it, what are some of the other alternatives? Can I use AOP/advice on a transformer?
This is fairly advanced. You will need a schema, a namespace handler that associates the parser with the namespace element and the parser itself.
It might be simpler to use a <transformer/> and simply reference your bean that adds the headers (and stores them).
If you want to learn how to write your own namespace; a good place to get started is the STS project templates which will create all of the boiler plate for you.
EDIT:
In response to your updates...
Since it's still a bean definition, and not yet a bean, you can simply change the beanClassName property...
BeanDefinition beanDefinition = new StandardHeaderEnricherParser().parse(element, parserContext);
beanDefinition.setBeanClassName(Foo.class.getName());
I have a repository class called FooRepository which has the ability to get various objects from a database.
I currently have one business object class called FooObject, which contains all the properties that I care about (Id, Name, CreatedDate, etc)... but my problem is that since ServiceStack only allows one DTO per route, I find myself unable to create more than one API method on my service to get back different types of data from my repository.
So, is it normal in ServiceStack to create a bunch of DTOs that simply return different types of data from the same repository? In ASP/MVC, this is rather easy because there's no route mapping clash going on, and I can simply create 'X' number of methods without the need to tie them to a specific DTO.
Thanks,
-Mario
Yes, each operation should have its own DTO. Keep in mind that the same DTO can be used for different HTTP methods(GET, PUT, POST, DELETE)
we're using Automapper (http://automapper.codeplex.com/) to map between entities and dto's. We have a situation where one property on an entity corresponds to three different properties on the dto, and we need to write some custom logic to do the mapping. Anyone know how we can do that? (We need to map both ways, from entity and from dto).
I notice that AutoMapper supports custom resolvers to do custom mapping logic, but as far as I can tell from the documentation, they only allow you to map a single property to another single property.
Thx
You can create a custom type converter. It allows you to define a converter for an entire type, not just a single property.