Merge pull request #6444 from dflor003/library/decorum

DanilF - Added typings for decorum library.
This commit is contained in:
Masahiro Wakame
2015-10-27 08:06:04 +09:00
3 changed files with 396 additions and 0 deletions
+102
View File
@@ -0,0 +1,102 @@
/// <reference path="./decorum.d.ts" />
import {Required} from 'decorum';
import {Email} from 'decorum';
import {MinLength} from 'decorum';
import {MaxLength} from 'decorum';
import {Length} from 'decorum';
import {FieldName} from 'decorum';
import {Validation} from 'decorum';
import {Pattern} from 'decorum';
import {Validator} from 'decorum';
import {BaseValidator} from 'decorum';
class MyModel {
@FieldName('User name')
@Required()
@MaxLength(50)
username = '';
@FieldName('Email address')
@Email()
@Required('Your email address will be used to send you a confirmation email. You must fill it out')
emailAddress = '';
@Required()
@MinLength(10)
@MaxLength(30)
password = '';
@FieldName('Confirm password')
@Validation<MyModel>(
'The passwords do not match.',
(pwd, model) => model.password === pwd
)
confirmPassword = '';
@Pattern(/^[a-z0-9-]+$/i, 'Must be a valid slug tag')
slug = 'foo';
@Length(6, 'Alias must be 6 characters long')
alias: string;
}
// ES6-style
class MyController {
model = new MyModel();
validator = Validator.new(this.model);
doStuff(): void {
var opts = this.validator.getValidationOptions('alias');
var fieldName = opts.getFieldName();
var errs = opts.validateValue('foo', this.model);
opts.setFieldName('Foo');
opts.addValidator(null);
var validators = opts.getValidators();
}
validate(): void {
var result = this.validator.validate();
if (!result.isValid) {
for(var i = 0; i < result.errors.length; i++) {
var current = result.errors[i];
console.error(current.fieldName, current.errors);
}
}
}
}
// ES5-style
function MyOtherModel() {
this.foo = '';
this.bar = '';
}
Validator.decorate(MyOtherModel, {
foo: [
Required()
],
bar: [
Pattern(/^[a-z][0-9]$/i)
]
});
var otherValidator = Validator.new(new MyOtherModel());
otherValidator.validateField('foo', '');
// Custom validator
class MyValidator extends BaseValidator {
validatesEmptyValue(): boolean {
return false;
}
getMessage(fieldName: string, fieldValue: any): string {
return 'No!';
}
isValid(value: any, model: any): boolean {
return false;
}
}
+2
View File
@@ -0,0 +1,2 @@
--experimentalDecorators
--target ES5
+292
View File
@@ -0,0 +1,292 @@
// Type definitions for Decorum JS v0.1.2
// Project: https://github.com/dflor003/decorum
// Definitions by: Danil Flores <https://github.com/dflor003>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
declare module 'decorum' {
/**
* A generic custom validation. Takes a predicate that will receive the proposed value as the first parameter and the
* current model state as the second.
* @param message The message to display when the predicate fails.
* @param predicate A lambda expression/function that determines if the value is valid. If it returns a falsy value, the
* field will be considered invalid and will return the passed error message upon validation.
* @returns {function(Object, string): void} A field validation decorator.
*/
export function Validation<TModel>(message: string, predicate: (value: any, model: TModel) => boolean): PropertyDecorator;
/**
* Validate's that the field is a valid email address. The format used is the same as the webkit browser's internal
* email validation format. For looser or stricter formats, use your own validation based on the @Pattern decorator.
* @param message [Optional] Overrides the default validation error message.
* @returns {function(Object, string): void} A field validation decorator.
*/
export function Email(message?: string): PropertyDecorator;
/**
* Sets the field's "friendly" name in validation error messages.
* @param name The field's friendly name
* @returns {function(Object, string): void} A field validation decorator.
*/
export function FieldName(name: string): PropertyDecorator;
/**
* Validate's a field's EXACT length. Validation fails if the field is not EXACTLY the length passed.
* @param length The exact length the field must be.
* @param message [Optional] Overrides the default validation error message.
* @returns {function(Object, string): void} A field validation decorator.
*/
export function Length(length: number, message?: string): PropertyDecorator;
/**
* Validates a field's maximum length.
* @param maxLength The field's maximum length. Must be a positive integer greater than 1.
* @param message [Optional] Overrides the default validation error message.
* @returns {function(Object, string): void} A field validation decorator.
*/
export function MaxLength(maxLength: number, message?: string): PropertyDecorator;
/**
* Validates the field's minimum length.
* @param minLength The field's minimum length. Must be a positive integer greater than 0
* @param message [Optional] Overrides the default validation error message.
* @returns {function(Object, string): void} A field validation decorator.
*/
export function MinLength(minLength: number, message?: string): PropertyDecorator;
/**
* Validates the field against a regular expression pattern.
* @param regex The regex to validate against. Should be a valid JavaScript {RegExp} instance.
* @param message [Optional] Overrides the default validation error message.
* @returns {function(Object, string): void} A field validation decorator.
*/
export function Pattern(regex: RegExp, message?: string): PropertyDecorator;
/**
* Marks the field as required.
* @param message [Optional] Overrides the default validation error message.
* @returns {function(Object, string): void} A field validation decorator.
*/
export function Required(message?: string): PropertyDecorator;
/**
* A map from field name to array of field validation decorators.
*/
export type ValidationDefinitions = {
[field: string]: PropertyDecorator[];
};
/**
* Static container for convenience methods related to field validation.
*/
export class Validator {
/**
* Creates a new model validator for the given model. Model should be a valid class that has a valid constructor
* and a prototype.
* @param model The model to create the validator for.
* @returns {ModelValidator} An instance of {ModelValidator}
*/
static new(model: any): ModelValidator;
/**
* Decorates the passed class with model validations. Use this when you do not have access to ES7 decorators.
* The object passed should be a valid class (ES6 class or ES5 function constructor).
* @param objectType The class to decorate.
* @param definitions One or more field validation definitions of the form { "fieldName": [ decorators ] }.
*/
static decorate(objectType: any, definitions: ValidationDefinitions): void;
/**
* Creates an anonymous validator, immediately validates the model, and returns any validation errors on the model
* as a result.
* @param model The model to validate.
*/
static validate(model: any): IValidationResult;
}
/**
* Details about validation errors on a field.
*/
export interface IFieldValidationError {
/**
* The property name of the field on the model.
*/
field: string;
/**
* The "friendly" name of the field. If not set on the model via @FieldName(...), it will default to "Field".
*/
fieldName: string;
/**
* One or more field validation errors. Empty if no errors.
*/
errors: string[];
}
/**
* Result returned when a model is validated.
*/
export interface IValidationResult {
/**
* Whether or not the model is valid.
*/
isValid: boolean;
/**
* A map of field name to validation errors.
*/
errors: IFieldValidationError[];
}
/**
* Wraps a model to allow the consuming class to call validation methods.
*/
export class ModelValidator {
/**
* Creates a new model validator.
* @param model The model to validate. Should be a class that has a valid constructor function and prototype.
*/
constructor(model: any);
/**
* Gets the validation options for the given field name.
* @param fieldKey The name of the field to get options for.
* @returns {FieldOptions} The field options associated with that field or null if no validations defined
* for the field.
*/
getValidationOptions(fieldKey: string): FieldOptions;
/**
* Validates the given field on this {ModelValidator}'s model. If a proposed value is passed, validate
* against that passed value; otherwise, use the field's current value on the model.
* @param fieldKey The name of the field to validate.
* @param proposedValue [Optional] The proposed value to set on the field.
* @returns {string[]} An array of field validation error messages if the field is invalid; otherwise,
* an empty array.
*/
validateField(fieldKey: string, proposedValue?: any): string[];
/**
* Validate the entire model and return a result that indicates whether the model is valid or not and any errors
* that have occurred in an object indexed by field name on the model.
* @returns {IValidationResult} An object that contains whether the model is valid or not and errors by field name.
*/
validate(): IValidationResult;
}
/**
* Callback invoked when a validation needs to return an error. Parameters include field name,
* field value, and any other properties relating to the field validation itself.
*/
export type MessageHandler = (fieldName: string, fieldValue: any, ...args: any[]) => string;
/**
* A map of validation "key" (unique name for a given type of validation) to message handler callback.
*/
export interface IMessageHandlerMap {
[key: string]: MessageHandler;
}
/**
* Mechanism for overriding validation errors to provide for custom or localized error messages.
* @type {{IMessageHandlerMap}}
*/
let MessageHandlers: IMessageHandlerMap;
/**
* Validation options for a given field including actual validators and meta data such as the field name.
*/
export class FieldOptions {
/**
* Gets the "friendly" name of the field for use in validation error messages. Defaults to just "Field".
* @returns {string}
*/
getFieldName(): string;
/**
* Sets the "friendly" name of the field for use in validation error messages. This name will be used in the text
* of validation errors.
* @param name The new name to set.
*/
setFieldName(name: string): void;
/**
* Add a validator to the list of validators for this field.
* @param validator The validator to add. Should be a class that extends from {BaseValidator}.
*/
addValidator(validator: BaseValidator): void;
/**
* Gets the validators assigned to this field.
* @returns {BaseValidator[]} The validators for this field.
*/
getValidators(): BaseValidator[];
/**
* Runs through all of the validators for the field given a particular value and returns any validation errors that
* may have occurred.
* @param value The value to validate.
* @param model The rest of the model. Used in custom cross-field validations.
* @returns {string[]} Any validation errors that may have occurred or an empty array if the value passed is valid
* for the field.
*/
validateValue(value: any, model: any): string[];
}
/**
* Base abstract class for all validators. Methods that must be overridden:
* getMessage(...) - Get error message to return when field is invalid.
* isValid(...) - Check validity of field given proposed value and the rest of the model.
*/
abstract class BaseValidator {
/**
* Initializes the {BaseValidator}
* @param validatorKey A unique "key" by which to identify this field validator i.e. length, maxlength, required.
* Should be a valid JS property name.
* @param message A custom error message to return. Should be passed down from concrete class' constructors to enable
* customizing error messages.
*/
constructor(validatorKey: string, message: string);
/**
* Returns true if the validator instance was passed a custom error message.
*/
hasCustomMessage: boolean;
/**
* Check whether this validator should process an "empty" value (i.e. null, undefined, empty string). Override
* this in derived classes to skip validators if the field value hasn't been set. Things like email, min/max length,
* and pattern should return false for this to ensure they don't get fired when the model is initially empty
* before a user has had a chance to input a value. Things like required should override this to true so that
* they are fired for empty values. Base implementation defaults to false
* @returns {boolean}
*/
validatesEmptyValue(): boolean;
/**
* Gets the custom error message set on this validator.
* @returns {string} The custom error message or null if none has been set.
*/
getCustomMessage(): string;
/**
* Gets the unique name for this validator.
* @returns {string} The unique name for this validator.
*/
getKey(): string;
/**
* [Abstract] Gets the error message to display when a field fails validation by this validator.
* @param fieldName The "friendly" name set for the field.
* @param fieldValue The field's current value.
*/
abstract getMessage(fieldName: string, fieldValue: any): string;
/**
* [Abstract] Checks the passed value for validity.
* @param value The field's proposed value.
* @param model The rest of the model if cross-field validity checks are necessary.
*/
abstract isValid(value: any, model: any): boolean;
}
}