Comments (19)
here is how it will look like: #20
from class-validator.
Looks good to me, the upgrade for me to 0.4.0 was relatively straight forward, only complexity was in dealing with the new container
from class-validator.
really? it was only one-line change
from class-validator.
From memory the difference was that now everything is retrieved from the container (previously just instantiated), and I was providing my own container, but it had no reference to Validator
for example. So I had to extend my container to fall back to instantiation.
from class-validator.
The only way to make that simpler would be do do the following:
Change
export function useContainer(iocContainer: { get(someClass: any): any }) {
container = iocContainer;
}
To
export function useContainer(iocContainer: { get(someClass: any): any }) {
const originalContainer = container;
container = {
get: (someClass: any) => {
try {
return iocContainer.get(someClass);
} catch () {
return originalContainer.get(someClass);
}
}
}
}
(The above is a crude proof of concept to demonstrate the point, it should be a cleaner implementation where the original container is a class that can have a container passed to it to try first)
from class-validator.
Actually you could probably use my implementation directly:
interface InjectableClass<T> {
new (...args: any[]): T
}
interface IOCContainer {
get(someClass: any): any
}
class Container implements IOCContainer {
protected externalInjector: IOCContainer;
protected instances: WeakMap<InjectableClass<any>, any> = new WeakMap();
/**
* Get the instance of a class when there is no dependency
* @param staticClass
* @returns {any}
*/
public noDependencyGet<T>(staticClass: InjectableClass<T>): T {
if (!this.instances.has(staticClass)) {
this.instances.set(staticClass, new staticClass());
}
return this.instances.get(staticClass);
}
public get<T>(staticClass: InjectableClass<T>): T {
if (!this.externalInjector) {
return this.noDependencyGet(staticClass);
}
try {
return this.externalInjector.get(staticClass);
} catch (e) {
return this.noDependencyGet(staticClass);
}
}
public setContainer(iocContainer: IOCContainer): this {
this.externalInjector = iocContainer;
return this;
}
}
from class-validator.
as I understood, your container cannot simply return instance of the class it received, thats why fallback to original container is required. But I thought most containers working like this: you send them refrenece to the class / token and they return you instance of this class, without complaining
from class-validator.
Yep thats the problem, I guess not all containers do that - I'm just using the Angular 2 injector, so probably a fairly common use case. The Angular 2 injector stores a reference of all provided Token
s, and if there is no provider for that token it throws a NoProvider exception
from class-validator.
I guess it will not give you instance of the class, until you explicitly "provide" it?
from class-validator.
Correct, and providing tokens is done when the injector instance is created.
For example:
import { ReflectiveInjector } from '@angular/core';
const providers = ReflectiveInjector.resolve([
{provide: Validator, useClass: MyValidator}
]);
const injector = ReflectiveInjector.fromResolvedProviders(providers);
from class-validator.
got it.
the reason why angular's container works differently then others, I think mostly because it was designed to work with tree-like components. And this design works fine with tree-like components when you can provide any instance on any level of the tree - I like this concept when designing view components
from class-validator.
Yea, also the Angular container can handle hierarchical dependencies - the injected class can be dependent on other injected classes.
I actually have a unit test showing this working with a custom validator having external dependencies, see https://github.com/ubiquits/ubiquits/blob/master/src/common/stores/store.spec.ts#L16-71
from class-validator.
so, about fallback, probably I need not only catch an exceptions, but also check for null/undefined references?
get: (someClass: any) => {
try {
const instance = iocContainer.get(someClass);
if (instance)
return instance;
} catch (error) {
}
return originalContainer.get(someClass);
}
and what shall I do with error? is it a really good to catch errors and completely ignore them? can be a situation when there is some another error, that you user should be aware of?
from class-validator.
Yea thats probably a good idea to check if defined. Good point on the error, maybe if a setContainerFallbackCondition((error:Error):boolean):this
could be added?
try {
const instance = iocContainer.get(someClass);
if (instance) {
return instance;
}
} catch (error) {
if (this.containerFallbackCondition && !this.containerFallbackCondition(error)) {
throw error;
}
}
return originalContainer.get(someClass);
from class-validator.
this makes it complicated, I think this kind of logic should be resolved on client side. Maybe something simple like this:
useContainer(container, { fallback: true, fallbackOnErrors: true });
interface UseContainerOptions {
/**
* If set to true, then default container will be used in the case if given container haven't returned anything.
*/
fallback?: boolean;
/**
* If set to true, then default container will be used in the case if given container thrown an exception.
*/
fallbackOnErrors?: boolean;
}
from class-validator.
Maybe if fallbackOnErrors
could be fallbackOnErrors?: boolean | (error:Error):boolean
? Best of both worlds?
from class-validator.
It will be same as
const instance = iocContainer.get(someClass);
if (instance) {
return instance;
}
return originalContainer.get(someClass);
e.g. without try/catch. Without fallback: true
it will work like now, .e.g without any fallback at all.
Maybe if fallbackOnErrors could be fallbackOnErrors?: boolean | (error:Error):boolean ? Best of both worlds?
I think it overcomplicates it - "handing error based on some function that returns true or false for this error" - seems very specific feature, and if needed user should handle it by themself, by passing a custom container that handle it.
from class-validator.
Yea sorry I misread the comments in the interface, understood now
from class-validator.
released https://github.com/pleerock/class-validator/releases/tag/0.4.0
from class-validator.
Related Issues (20)
- fix: class-validators and nest.js: Global custom validator with imports from two different modules is only triggered in one of the two modules
- feature: traverse ValidationError.children HOT 1
- feature: add @IsTime HOT 3
- always: false doesn't take any effect
- question: How annotations are inherited ? HOT 1
- question: How can I validate a union of strings? HOT 1
- fix: @IsDateString() accepts wrong date format HOT 2
- fix: Cannot find namespace 'ValidatorJS' in 0.14.x HOT 8
- question: Could someone also bump the package.json version from 0.14.0 to 0.14.1? HOT 5
- fix: options for @IsBase64 decorator are ignored HOT 1
- docs: add changelog for 0.14.1
- Class-level validators
- question: How do I set a default error message for my decorator? HOT 2
- question: Default definition "strong password" is unclear HOT 3
- question: isPhoneNumber validation input without country code HOT 1
- question: nested validation but discriminated depending on a field value in the root dto HOT 3
- feature: return promise from validation only if necessary and validate sync if possible
- fix: Typo in MaxDate comment HOT 2
- question: get constrains in decorators and not the message HOT 1
- fix please: class level decorator makes bug HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from class-validator.