Skip to content

Commit

Permalink
Updated build & README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
ClickerMonkey committed Jun 6, 2016
1 parent ca01ea2 commit 5858909
Show file tree
Hide file tree
Showing 6 changed files with 450 additions and 224 deletions.
45 changes: 30 additions & 15 deletions Gulpfile.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

var fs = require('fs');
var pkg = JSON.parse( fs.readFileSync('./package.json') );
var gulp = require('gulp');
var sourcemaps = require('gulp-sourcemaps');
var plugins = require('gulp-load-plugins')();
Expand All @@ -9,6 +11,8 @@ var shell = require('gulp-shell');
var merge = require('merge-stream');
var size = require('gulp-check-filesize');
var jshint = require('gulp-jshint');
var rename = require('gulp-rename');
var insert = require('gulp-insert');

var build = {
filename: 'rekord-validation.js',
Expand All @@ -21,14 +25,19 @@ var build = {
]
};

var comments = [
"/*", pkg.name, pkg.version, '-', pkg.description, 'by', pkg.author, "*/\n"
];

var executeMinifiedBuild = function(props)
{
return function() {
return gulp
.src( props.include )
.src( props.output + props.filename )
.pipe( rename( props.minified ) )
.pipe( sourcemaps.init() )
.pipe( plugins.concat( props.minified ) )
.pipe( plugins.uglify().on('error', gutil.log) )
.pipe( insert.prepend( comments.join(' ') ) )
.pipe( sourcemaps.write('.') )
.pipe( size({enableGzip: true}) )
.pipe( gulp.dest( props.output ) )
Expand All @@ -42,35 +51,41 @@ var executeBuild = function(props)
return gulp
.src( props.include )
.pipe( plugins.concat( props.filename ) )
.pipe( insert.prepend( comments.join(' ') ) )
.pipe( size({enableGzip: true}) )
.pipe( gulp.dest( props.output ) )
.pipe(jshint())
.pipe(jshint.reporter('default'))
.pipe(jshint.reporter('fail'))
.pipe( jshint() )
.pipe( jshint.reporter('default') )
.pipe( jshint.reporter('fail') )
;
};
};

var executeTest = function(file)
{
return function() {
return gulp.src( file ).pipe( qunit() );
return gulp
.src( file )
.pipe( qunit() )
;
};
};

gulp.task('lint', function() {
return gulp
.src(build.output + build.filename)
.pipe(jshint())
.pipe(jshint.reporter('default'))
.pipe(jshint.reporter('fail'))
.src( build.output + build.filename )
.pipe( jshint() )
.pipe( jshint.reporter('default') )
.pipe( jshint.reporter('fail') )
;
});

gulp.task( 'js', executeBuild( build ) );
gulp.task( 'js:min', ['js'], executeMinifiedBuild( build ) );

gulp.task( 'default', ['js:min']);

gulp.task( 'test', ['js'], executeTest( './test/index.html' ) );

gulp.task( 'docs', shell.task(['./node_modules/.bin/jsdoc -c jsdoc.json']));
gulp.task( 'clean', shell.task(['rm -rf build/*.js', 'rm -rf build/*.map']));
gulp.task( 'test', executeTest( './test/index.html' ) );

gulp.task( 'js:min', executeMinifiedBuild( build ) );
gulp.task( 'js', executeBuild( build ) );
gulp.task( 'default', ['js:min', 'js']);
211 changes: 209 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,212 @@ rekord-validation adds rules, expressions, transforms, and custom validation fun

The easiest way to install rekord-validation is through bower via `bower install rekord-validation`.

- rekord-validation.js is `46KB` (`7.55KB` gzipped)
- rekord-validation.min.js is `18KB` (`5.24KB` gzipped)
- rekord-validation.js is `45KB` (`7.6KB` gzipped)
- rekord-validation.min.js is `18KB` (`5.3KB` gzipped)

### Example

```javascript
// Simplest rule definition
var Task = Rekord({
name: 'task',
fields: ['name', 'done', 'done_at'],
validation: {
rules: {
name: 'required|alpha_dash',
done: 'yesno',
done_at: 'if:done:accepted|required|date_like'
},
required: true // the rules must pass to $save model instances
}
});

var t0 = new Task({name: '^', done: true});
t0.$save();
t0.$valid; // false
t0.$validationMessages; // array of below messages
t0.$validations; /* {
name: 'name should only contain alpha-numeric characters, dashes, and underscores.',
done_at: 'done_at is required.'
} */

// You can use aliases to make messages friendlier
var Task = Rekord({
name: 'task',
fields: ['name', 'done', 'done_at'],
validation: {
rules: {
name: 'required|alpha_dash',
done: 'yesno',
done_at: 'if:done:accepted|required|date_like'
},
aliases: {
name: 'Task name',
done: 'Task completed',
done_at: 'Task completed at'
}
}
});

var t1 = new Task({name: '', done: false});
t1.$save(); /* {
name: 'Task name is required.'
} */

var t2 = new Task({name: 'task2', done: true, done_at: 'not date'});
t2.$save(); /* {
done_at: 'Task completed at must be a valid date.'
} */

// You can specify field level custom messages
var Task = Rekord({
name: 'task',
fields: ['name', 'done', 'done_at'],
validation: {
rules: {
name: 'required|alpha_dash',
done: 'yesno',
done_at: 'if:done:accepted|required|date_like'
},
messages: {
name: 'Task name is required and must be alpha-numeric and can contain dashes and hyphens.',
done_at: 'When a task is completed, the completed date is required.'
}
}
});

var t3 = new Task({name: '?', done: true, done_at: 'not date'});
t3.$save(); /* {
name: 'Task name is required and must be alpha-numeric and can contain dashes and hyphens.',
done_at: 'When a task is completed, the completed date is required.'
} */

// You can specify rule level custom messages
var Task = Rekord({
name: 'task',
fields: ['name', 'done', 'done_at'],
validation: {
rules: {
name: {
'required': false, // defaults to field level - then default
'alpha_dash': 'Task name must be alpha-numeric and can contain dashes and hyphens.'
},
done: 'yesno',
done_at: {
'if:done:accepted': false, // defaults to field level - then default
'required': 'Task completed date is required when the task is complete.',
'date_like': 'Task completed date must be a valid date when the task is complete.'
}
},
aliases: {
name: 'Task name'
}
}
});

var t4 = new Task({name: '?', done: true, done_at: 'not date'});
t4.$save(); /* {
name: 'Task name must be alpha-numeric and can contain dashes and hyphens.',
done_at: 'Task completed date must be a valid date when the task is complete.'
} */

var t5 = new Task({done: true});
t5.$save(); /* {
name: 'Task name is required.',
done_at: 'Task completed date is required when the task is complete.'
} */

// There are even more specific ways to define rules - depending on the rule.
// Check out the tests!

```

### Concepts

- "date like": number (millis since Unix Epoch), Date object, or string that can be parsed with `Date.parse`
- "number like": number or a string that begins with a number

### Rules

#### Simple
- `accepted`: The field must be an accepted value (1, yes, on, y, or true)
- `after:date`: If the field is like a date, it must be after the given `date` expression
- `after_on:date`: If the field is like a date, it must be on or after the given `date` expression
- `before:date`: If the field is like a date, it must be before the given `date` expression
- `before_on:date`: If the field is like a date, it must be on or before the given `date` expression
- `date_like`: The field must look like a date (Date, number, or valid date string)
- `required_if:field,value0,valueN`: The field is required is another `field` has any of the given values
- `required_unless:field,value0,valueN`: The field is required if another `field` does not have any of the given values
- `confirmed:field`: The field must match another `field`
- `different:field`: The field must NOT match another `field`
- `if_valid:field0,fieldN`: The rules following this one for this field will not be executed if any of the `field`s are invalid at this point in time in validation
- `required_with:field0,fieldN`: The field is required if any of the `field`s have a non-empty value
- `required_with_all:field0,fieldN`: The field is required if all of the `field`s have a non-empty value
- `required_without:field0,fieldN`: The field is required if any of the `field`s have an empty value
- `required_without_all:field0,fieldN`: The field is required if all of the `field`s have an empty value
- `exists` `exists:models` `exists:models,field`: The field value must exist in the given database (`models` - or this if none specified) in the given `field` (this field if not given)
- `unique` `unique:models` `unique:models,field`: The field value must NOT exist in the given database (`models` - or this if none specified) in the given `field` (this field if not given)
- `if:rule0\|ruleN`: The rules following this one for this field will not be executed unless all `rule`s pass
- `if_any:rule0\|ruleN`: The rules following this one for this field will not be executed unless at lease one `rule` passes
- `if_not:rule0\|ruleN`: The rules following this one for this field will only be executed if all `rule`s fail
- `in:value0,valueN`: This field must have a value in the given `value`s
- `not_in:value0,valueN`: This field must NOT have a value in the given `value`s
- `between:start,end`: This field must have a size between (inclusive) the `start` and `end` (string, number, array, or object)
- `not_between:start,end`: This field must NOT have a size between (inclusive) the `start` and `end` (works with strings, numbers, arrays, object keys)
- `alpha`: The field should only contain alphabetic characters
- `alpha_dash`: The field should only contain alpha-numeric characters, dashes, and underscores
- `alpha_num`: The field should only contain alpha-numeric characters
- `email`: The field should look like an email
- `url`: The field should look like a URL
- `uri`: The field should look like a URI
- `phone`: The field should look like a phone number
- `regex:/rgx/`: The field should pass the regular expression
- `required`: The field must be a non-empty value
- `min:number`: The field must be at least `number` in size (string, number, array, or object)
- `greater_than:number`: The field must be greater than `number` in size (string, number, array, or object)
- `max:number`: The field must be no more than `number` in size (string, number, array, or object)
- `less_than:number`: The field must be less than `number` in size (string, number, array, or object)
- `equal:number`: The field must be equal to `number` in size (string, number, array, or object)
- `not_equal:number`: The field must not be equal to `number` in size (string, number, array, or object)
- `array`: The field must be an instance of Array
- `object`: The field must be an object (arrays count as objects)
- `string`: The field must be a string
- `number`: The field must be a number
- `boolean`: The field must be a boolean
- `model`: The field must be a model instance
- `whole`: The field must look like a whole number
- `numeric`: The field must look like a number
- `yesno`: The field must look like a boolean (true, t, yes, y, 1, false, f, no, n, 0)

#### Relationship
- `contains:field,value`: The relation field must contain a model with at least one `field` matching the given `value`
- `not_contains:field,value`: The relation field must NOT contain a model with at least one `field` matching the given `value`
- `validate`: The relation field must contain all valid models

### Expressions
Expressions can be passed to rules (like date rules) and are generated on validation

- `MM/dd/yyyy`: Parses to a date time
- `field`: Takes a field value from the model being validated
- `-1 day`: Relative amount of time from current time (+-)N (ms,s,min,hr,day,month,wk,yr)
- `today`: Todays date (start of day)
- `tomorrow`: Tomorrows date (start of day)
- `yesterday`: Yesterdays date (start of day)

### Transforms
Transforms modify the value being validated so all subsequent rules use the modified values. Some transforms can apply the modified value back to the model after validation.

- `trim`: If the field value is a string, return the trimmed value
- `abs`: If the field value looks like a number, parse it and return the absolute value
- `ceil`: If the field value looks like a number, parse it and return the ceiling value
- `floor`: If the field value looks like a number, parse it and return the floored value
- `round`: If the field value looks like a number, parse it and return the rounded value
- `endOfDay`: If the field value looks like a date, return its end of day
- `startOfDay`: If the field value looks like a date, return its start of day
- `base64`: Base64 encode the current value
- `unbase64`: Un-base64 the current value
- `filter`: If the field value is an array or object, remove the null and undefined properties/elements
- `mod:number`: If the field value looks like a number, parse it and return the remainder to the division between the field value and `number`

- `null`: Apply null back to the model (can be used in conjuction with `if`)
- `apply`: Apply the currently transformed value back to the model
Loading

0 comments on commit 5858909

Please sign in to comment.