5.0.23 • Published 1 month ago

n4s v5.0.23

Weekly downloads
58
License
MIT
Repository
github
Last release
1 month ago

Enforce

Enforce is a validation assertions library. It allows you to run your data against rules and conditions and test whether it passes your validations. It is intended for validation logic that gets repeated over and over again and should not be written manually. It comes with a wide-variety of pre-built rules, but it can also be extended to support your own repeated custom logic.

The way Enforce operates is similar to most common assertion libraries - if the validation fails, it throws an Error, and if the validation succeeds, it returns the current instance of Enforce to allow chaining more rules.

import enforce from 'n4s'

enforce(4).isNumber();
// passes

enforce(4).lessThan(2);
// throws an error

Content

Chaining enforce rules

All of enforce's rules are chainable and can be used more than once in the same chain. When chained, all blocks share an AND relationship, meaning that if one block fails, the whole test fails as well.

The following are valid uses of enforce.

enforce([1,2,3,4,5,6]).longerThan(5).isArray();

enforce('North Dakota, por favor').shorterThan(10).longerThan(6);

enforce('Toto, I\'ve a feeling we\'re not in Kansas anymore').notMatches(/0-9/);

Enforce exposes all predefined and custom rules. You may use chaining to make multiple enfocements for the same value.

Custom enforce rules

To make it easier to reuse logic across your application, sometimes you would want to encapsulate bits of logic in rules that you can use later on, for example, "what's considered a valid email".

Your custom rules are essentially a single javascript object containing your rules.

const myCustomRules = {
    isValidEmail: (value) => value.indexOf('@') > -1,
    hasKey: (value, {key}) => value.hasOwnProperty(key),
    passwordsMatch: (passConfirm, options) => passConfirm === options.passConfirm && options.passIsValid
}

Just like the predefined rules, your custom rules can accepts two parameters:

  • value The actual value you are testing against.
  • args (optional) the arguments which you pass on when running your tests.

You can extend enforce with your custom rules by creating a new instance of Enforce and adding the rules object as the argument.

import Enforce from 'n4s';

const myCustomRules = {
    isValidEmail: (value) => value.indexOf('@') > -1,
    hasKey: (value, key) => value.hasOwnProperty(key),
    passwordsMatch: (passConfirm, options) => passConfirm === options.passConfirm && options.passIsValid
}

const enforce = new Enforce(myCustomRules);

enforce(user.email).isValidEmail();

enforce rules

Enforce rules are functions that allow you to test your data against different criteria. The following rules are supported out-of-the-box

equals

Description

Checks if your enforced value strictly equals (===) another.

It is not recommended to use this rule to compare arrays or objects, as it does not perform any sort of deep comparison on the value.

For numeric value comparison, you should use numberEquals, which coerces numeric strings into numbers before comparing.

Arguments

  • value: Any value you wish to check your enforced value against

Usage examples:

Passing

enforce(1).equals(1);

enforce('hello').equals('hello');

const a = [1, 2, 3];

enforce(a).equals(a);

failing

enforce('1').equals(1);

enforce([1, 2, 3]).equals([1, 2, 3]);

notEquals

Description

Checks if your enforced value does not strictly equal (===) another.

Reverse implementation of equals.

Usage examples:

Passing

enforce('1').notEquals(1);

enforce([1, 2, 3]).notEquals([1, 2, 3]);

failing

enforce(1).notEquals(1);

enforce('hello').notEquals('hello');

const a = [1, 2, 3];

enforce(a).notEquals(a);

isEmpty

Description

Checks if your enforced value is empty, false, zero, null or undefined.

Expected results are:

  • object: checks against count of keys (0 is empty)
  • array/string: checks against length. (0 is empty)
  • number: checks the value of the number. (0 and NaN are empty)
  • boolean: false is empty.
  • undefined/null: are both empty.

Arguments

NameTypeRequired?Description
expectBooleanNowhen passed false, the negative result will be tested

Usage examples:

enforce([]).isEmpty();
enforce('').isEmpty();
enforce({}).isEmpty();
enforce(0).isEmpty();
enforce(NaN).isEmpty();
enforce(undefined).isEmpty();
enforce(null).isEmpty();
enforce(false).isEmpty();
// passes
enforce([1]).isEmpty();
enforce('1').isEmpty();
enforce({1:1}).isEmpty();
enforce(1).isEmpty();
enforce(true).isEmpty();
// throws

isNotEmpty

Description

Checks that your enforced value is not empty, false, or zero. Reverse implementation of isEmpty.

Usage examples:

enforce([1]).isNotEmpty();
// passes
enforce('1').isNotEmpty();
// passes
enforce({1:1}).isNotEmpty();
// passes
enforce([]).isNotEmpty();
// throws
enforce('').isNotEmpty();
// throws
enforce({}).isNotEmpty();
// throws
enforce(0).isNotEmpty();
// throws

isNumeric

Description

Checks if a value is a representation of a real number

Arguments

NameTypeRequired?Description
expectBooleanNowhen passed false, the negative result will be tested

Usage examples:

enforce(143).isNumeric();
enforce('143').isNumeric();
// passes
enforce(NaN).isNumeric();
enforce('1hello').isNumeric();
enforce('hi').isNumeric();
// throws

isNotNumeric

Description

Checks if a value is not a representation of a real number. Reverse implementation of isNumeric.

Usage examples:

enforce(NaN).isNotNumeric();
enforce('Hello World!').isNotNumeric();
// passes
enforce(731).isNotNumeric();
enforce('42').isNotNumeric();
// throws

greaterThan

  • alias: gt

Description

Checks that your numeric enforced value is larger than a given numeric value.

Arguments

  • value: number | string | A numeric value against which you want to check your enforced value.

Strings are parsed using Number(), values which are non fully numeric always return false;

Usage

Passing examples:

enforce(1).greaterThan(0);
enforce('10').greaterThan(0);
enforce(900).gt('100');

Failing examples:

enforce(100).greaterThan(100);
enforce('100').greaterThan(110);
enforce([100]).gt(1);

greaterThanOrEquals

  • alias: gte()

Description

Checks that your numeric enforced value is larger than or equals to a given numeric value.

Arguments

  • value: number | string | A numeric value against which you want to check your enforced value.

Strings are parsed using Number(), values which are non fully numeric always return false;

Usage

Passing examples:

enforce(1).greaterThanOrEquals(0);
enforce('10').greaterThanOrEquals(0);
enforce(900).greaterThanOrEquals('100');
enforce(100).greaterThanOrEquals('100');
enforce(900).gte('900');
enforce('1337').gte(1337);

Failing examples:

enforce(100).greaterThanOrEquals('120');
enforce('100').greaterThanOrEquals(110);
enforce([100]).gte(1);

lengthEquals

Description

Checks that your enforced value is equal to the given number.

Arguments

  • size: number | the number which you would like your initial value to be tested against.

The value argument can be of the following types:

  • array: checks against length.
  • string: checks against length.

Usage examples:

Passing examples:

enforce([1]).lengthEquals(1);
// passes
enforce('a').lengthEquals(1);
// passes

Failing examples:

enforce([1, 2]).lengthEquals(1);
// throws
enforce('').lengthEquals(1);
// throws

lengthNotEquals

Description

Checks that your enforced value is not equal to the given number. Reverse implementation of lengthEquals.

Arguments

  • size: number | the number which you would like your initial value to be tested against.

The value argument can be of the following types:

  • array: checks against length.
  • string: checks against length.

Usage examples:

Passing examples:

enforce([1]).lengthNotEquals(0);
// passes
enforce('a').lengthNotEquals(3);
// passes

Failing examples:

enforce([1]).lengthNotEquals(1);
// throws
enforce('').lengthNotEquals(0);
// throws

lessThan

  • alias: lt()

Description

Checks that your numeric enforced value is smaller than a given numeric value.

Arguments

  • value: number | string | A numeric value against which you want to check your enforced value.

Strings are parsed using Number(), values which are non fully numeric always return false;

Usage

Passing examples:

enforce(0).lessThan(1);
enforce(2).lessThan('10');
enforce('90').lt(100);

Failing examples:

enforce(100).lessThan(100);
enforce('110').lessThan(100);
enforce([0]).lt(1);

lessThanOrEquals

  • alias: lte()

Description

Checks that your numeric enforced value is smaller than or equals to a given numeric value.

Arguments

  • value: number | string | A numeric value against which you want to check your enforced value.

Strings are parsed using Number(), values which are non fully numeric always return false;

Usage

Passing examples:

enforce(0).lessThanOrEquals(1);
enforce(2).lessThanOrEquals('10');
enforce('90').lte(100);
enforce(100).lte('100');

Failing examples:

enforce(100).lessThanOrEquals(90);
enforce('110').lessThanOrEquals(100);
enforce([0]).lte(1);

longerThan

Description

Checks that your enforced value is longer than a given number.

Arguments

  • size: number | the number which you would like your initial value to be tested against.

The value argument can be of the following types:

  • array: checks against length.
  • string: checks against length.

Usage examples:

Passing examples:

enforce([1]).longerThan(0);
// passes
enforce('ab').longerThan(1);
// passes

Failing examples:

enforce([1]).longerThan(2);
// throws
enforce('').longerThan(0);
// throws

longerThanOrEquals

Description

Checks that your enforced value is longer than or equals to a given number.

Arguments

  • size: number | the number which you would like your initial value to be tested against.

The value argument can be of the following types:

  • array: checks against length.
  • string: checks against length.

Usage examples:

Passing examples:

enforce([1]).longerThanOrEquals(0);
// passes
enforce('ab').longerThanOrEquals(1);
// passes
enforce([1]).longerThanOrEquals(1);
// passes
enforce('a').longerThanOrEquals(1);
// passes

Failing examples:

enforce([1]).longerThanOrEquals(2);
// throws
enforce('').longerThanOrEquals(1);
// throws

numberEquals

Description

Checks that your numeric enforced value is equals another value.

Arguments

  • value: number | string | A numeric value against which you want to check your enforced value.

Strings are parsed using Number(), values which are non fully numeric always return false;

Usage

Passing examples:

enforce(0).numberEquals(0);
enforce(2).numberEquals('2');

Failing examples:

enforce(100).numberEquals(10);
enforce('110').numberEquals(100);
enforce([0]).numberEquals(1);

numberNotEquals

Description

Checks that your numeric enforced value does not equal another value. Reverse implementation of numberEquals.

Arguments

  • value: number | string | A numeric value against which you want to check your enforced value.

Strings are parsed using Number(), values which are non fully numeric always return false;

Usage

Passing examples:

enforce(2).numberNotEquals(0);
enforce('11').numberNotEquals('10');

Failing examples:

enforce(100).numberNotEquals(100);
enforce('110').numberNotEquals(100);

shorterThan

Description

Checks that your enforced value is shorter than a given number.

Arguments

  • size: number | the number which you would like your initial value to be tested against.

The value argument can be of the following types:

  • array: checks against length.
  • string: checks against length.

Usage examples:

Passing examples:

enforce([]).shorterThan(1);
// passes
enforce('a').shorterThan(2);
// passes

Failing examples:

enforce([1]).shorterThan(0);
// throws
enforce('').shorterThan(0);
// throws

shorterThanOrEquals

Description

Checks that your enforced value is shorter than or equals to a given number.

Arguments

  • size: number | the number which you would like your initial value to be tested against.

The value argument can be of the following types:

  • array: checks against length.
  • string: checks against length.

Usage examples:

Passing examples:

enforce([]).shorterThanOrEquals(1);
// passes
enforce('a').shorterThanOrEquals(2);
// passes
enforce([]).shorterThanOrEquals(0);
// passes
enforce('a').shorterThanOrEquals(1);
// passes

Failing examples:

enforce([1]).shorterThanOrEquals(0);
// throws
enforce('ab').shorterThanOrEquals(1);
// throws

matches

Description

Checks if a value contains a regex match.

Arguments

  • regexp: either a RegExp object, or a RegExp valid string

Usage examples:

enforce(1984).matches(/[0-9]/);
// passes
enforce(1984).matches('[0-9]');
// passes
enforce('1984').matches(/[0-9]/);
// passes
enforce('1984').matches('[0-9]');
// passes
enforce('198four').matches(/[0-9]/);
// passes
enforce('198four').matches('[0-9]');
// passes
enforce('ninety eighty four').matches(/[0-9]/);
// throws
enforce('ninety eighty four').matches('[0-9]');
// throws

notMatches

Description

Checks if a value does not contain a regex match. Reverse implementation of matches.

Usage examples:

enforce(1984).notMatches(/[0-9]/);
// throws
enforce('ninety eighty four').notMatches('[0-9]');
// passes

inside

Description

Checks if your enforced value is contained in another array or string. Your enforced value can be of the following types:

  • string
  • number
  • boolean

Arguments

  • container: a string or an array which may contain the value specified.

Usage examples:

inside: array

Checks for membership in an array.

  • string: checks if a string is an element in an array
enforce('hello').inside(['hello', 'world']);
// passes
enforce('hello!').inside(['hello', 'world']);
// throws
  • number: checks if a number is an element in an array
enforce(1).inside([1, 2]);
// passes
enforce(3).inside([1, 2]);
// throws
  • boolean: checks if a number is an element in an array
enforce(false).inside([true, false]);
// passes
enforce(true).inside([1,2,3]);
// throws

inside: string

  • string: checks if a string is inside another string
enforce('da').inside('tru dat.');
// passes
enforce('ad').inside('tru dat.');
// throws

notInside

Description

Checks if a given value is not contained in another array or string. Reverse implementation of inside.

Usage examples:

enforce('ad').notInside('tru dat.');
enforce('hello!').notInside(['hello', 'world']);
// passes
enforce('hello').notInside(['hello', 'world']);
enforce('da').notInside('tru dat.');
// throws

isTruthy

Description

Checks if a value is truthy; Meaning: if it can be coerced into boolean true. Anything not in the following list is considered to be truthy.

  • undefined
  • null
  • false
  • 0
  • NaN
  • empty string ("")

Arguments

NameTypeRequired?Description
expectBooleanNowhen passed false, the negative result will be tested

Usage examples:

enforce("hello").isTruthy();
enforce(true).isTruthy();
enforce(1).isTruthy();
// passes
enforce(false).isTruthy();
enforce(null).isTruthy();
enforce(undefined).isTruthy();
enforce(0).isTruthy();
enforce(NaN).isTruthy();
enforce("").isTruthy();
// throws

isFalsy

Description

Checks if a value is falsy; Meaning: if it can be coerced into boolean false. Reverse implementation of isTruthy.

Anything not in the following list is considered to be truthy:

  • undefined
  • null
  • false
  • 0
  • NaN
  • empty string ("")

Usage examples:

enforce(1).isFalsy();
// throws
enforce(true).isFalsy();
// throws
enforce('hi').isFalsy();
// throws
enforce(false).isFalsy();
// passes
enforce(0).isFalsy();
// passes
enforce(undefined).isFalsy();
// passes

isArray

Description

Checks if a value is of type Array.

Arguments

NameTypeRequired?Description
expectBooleanNowhen passed false, the negative result will be tested

Usage examples:

enforce(['hello']).isArray();
// passes
enforce('hello').isArray();
// throws

isNotArray

Description

Checks if a value is of any type other than Array. Reverse implementation of isArray.

Usage examples:

enforce(['hello']).isNotArray();
// throws
enforce('hello').isNotArray();
// passes

isNumber

Description

Checks if a value is of type number.

Arguments

NameTypeRequired?Description
expectBooleanNowhen passed false, the negative result will be tested

Usage examples:

enforce(143).isNumber();
enforce(NaN).isNumber(); // (NaN is of type 'number!')
// passes
enforce([]).isNumber();
enforce("143").isNumber();
// throws

isNotNumber

Description

Checks if a value is of any type other than number. Reverse implementation of isNumber.

Usage examples:

enforce(143).isNotNumber();
// throws
enforce(NaN).isNotNumber();
// throws (NaN is of type 'number!')
enforce('143').isNotNumber();
// passes
enforce(143).isNotNumber();
// passes

isString

Description

Checks if a value is of type String.

Arguments

NameTypeRequired?Description
expectBooleanNowhen passed false, the negative result will be tested

Usage examples:

enforce('hello').isString();
// passes
enforce(['hello']).isString();
enforce(1984).isString();
// throws

isNotString

Description

Checks if a value is of any type other than String. Reverse implementation of isString.

Usage examples:

enforce('hello').isNotString();
// throws
enforce(['hello']).isNotString();
// passes

isOdd

Description

Checks if a value is an odd numeric value.

Usage examples:

enforce('1').isOdd();
enforce(9).isOdd();
// passes
enforce(2).isOdd();
enforce('4').isOdd();
enforce('1withNumber').isOdd();
enforce([1]).isOdd();
// throws

isEven

Description

Checks if a value is an even numeric value.

Usage examples:

enforce(0).isEven();
enforce('2').isEven();
// passes
enforce(1).isEven();
enforce('3').isEven();
enforce('2withNumber').isEven();
enforce([0]).isEven();
// throws
5.0.23

1 month ago

5.0.22

1 month ago

5.0.21

2 months ago

5.0.20

3 months ago

5.0.19

3 months ago

5.0.18

4 months ago

5.0.17

4 months ago

5.0.15

4 months ago

5.0.16

4 months ago

5.0.14

5 months ago

5.0.9

6 months ago

5.0.8

6 months ago

5.0.7

7 months ago

5.0.6

8 months ago

5.0.10

6 months ago

5.0.11

5 months ago

5.0.12

5 months ago

5.0.13

5 months ago

5.0.5

8 months ago

5.0.4

8 months ago

5.0.3

8 months ago

5.0.2

8 months ago

5.0.0-next-470211

12 months ago

5.0.0-next-70dac5

12 months ago

5.0.0-next-25c20e

11 months ago

5.0.0-next-83f17b

11 months ago

5.0.0-next-cc6009

11 months ago

5.0.0-next-a084e9

11 months ago

5.0.0-next-04eea9

11 months ago

5.0.0-dev-ae6b14

12 months ago

5.0.0-next-979ab9

11 months ago

5.0.0-next-1b0637

11 months ago

5.0.0-dev-ec989a

12 months ago

5.0.0-next-ed535b

12 months ago

5.0.0-next-2cf993

11 months ago

5.0.0-next-1de937

12 months ago

5.0.0-next-df4840

12 months ago

4.3.6

1 year ago

4.3.7

1 year ago

5.0.0-next-9e961f

12 months ago

5.0.0-next-0fe843

12 months ago

5.0.0-next-8222e6

12 months ago

5.0.0-next-ac1cf9

12 months ago

4.3.5

1 year ago

4.3.4

1 year ago

4.3.2

2 years ago

4.3.3

2 years ago

4.1.8

2 years ago

4.1.9

2 years ago

4.2.2-dev-b07a89

2 years ago

4.1.8-dev-d13b14

2 years ago

5.0.0

2 years ago

4.2.2-dev-310818

2 years ago

4.3.1

2 years ago

4.3.0

2 years ago

5.0.0-dev-781e21

2 years ago

4.1.9-dev-c786f7

2 years ago

4.1.9-dev-9b46fb

2 years ago

4.2.3

2 years ago

4.2.2

2 years ago

4.2.1

2 years ago

4.2.0

2 years ago

4.1.8-dev-ae93bf

2 years ago

4.3.0-dev-c4ba9b

2 years ago

4.1.8-dev-afe5de

2 years ago

4.3.0-dev-f30a30

2 years ago

4.2.2-dev-b9b126

2 years ago

4.2.2-dev-fcaa09

2 years ago

5.0.0-dev-040354

2 years ago

4.1.7

2 years ago

4.1.6

2 years ago

4.1.4

2 years ago

4.1.3

2 years ago

4.1.5

2 years ago

4.0.0-dev-031d95

2 years ago

4.0.1

2 years ago

5.0.1

2 years ago

4.0.0-dev-e266d9

2 years ago

4.0.0-dev-cc2a13

2 years ago

4.1.1-dev-0bdac6

2 years ago

4.0.0-dev-1aae50

2 years ago

4.1.1-dev-950c8e

2 years ago

4.0.0-dev-fc2efe

2 years ago

4.1.0

2 years ago

4.1.2

2 years ago

4.1.1

2 years ago

3.1.0

3 years ago

3.0.0

3 years ago

4.0.0

3 years ago

2.1.2-dev-1aaf06

4 years ago

2.1.2-dev-c4124c

4 years ago

2.1.2-dev-3e4fa1

4 years ago

2.1.2-dev-8e6e76

4 years ago

2.2.0-rc.1

4 years ago

2.1.2-dev-661ec4

4 years ago

2.1.2-dev-7a0221

4 years ago

2.1.2-dev-bb7a82

4 years ago

2.1.2-dev-b3b059

4 years ago

2.1.2-dev-65c4a3

4 years ago

2.1.2-dev-e33f88

4 years ago

2.1.2-dev-ee22a6

4 years ago

2.1.2-dev-30ec94

4 years ago

2.1.2-dev-42047a

4 years ago

2.1.2-dev-edac4f

4 years ago

2.1.2-dev-aa2cb1

4 years ago

2.1.2-dev-afc096

4 years ago

2.1.2-dev-6f98b9

4 years ago

2.1.2-dev-3430bd

4 years ago

2.1.2-dev-1b95dc

4 years ago

2.1.2-dev-32c368

4 years ago

2.1.2-dev-fe0186

4 years ago

2.1.2-dev-29745f

4 years ago

2.1.2-dev-2a40d2

4 years ago

2.1.2-dev-046792

4 years ago

2.1.2-dev-476dde

4 years ago

2.1.2-dev-51d4d8

4 years ago

2.1.2-dev-9c54f5

4 years ago

2.1.2-dev-c23dd4

4 years ago

2.1.2-dev-5d3b11

4 years ago

2.1.2-dev-7a965c

4 years ago

2.1.2-dev-2a6bf2

4 years ago

2.1.2-dev-ee5d5e

4 years ago

2.1.2-dev-12d646

4 years ago

2.1.1

4 years ago

2.1.1-dev-2a5ed4

4 years ago

2.1.1-dev-11c21c

4 years ago

2.1.1-dev-e1e9c5

4 years ago

2.1.1-dev-ee1118

4 years ago

2.1.0-dev-e35626

4 years ago

2.0.1-dev-cfc4c9

4 years ago

2.0.1-dev-8be60f

4 years ago

2.1.0

4 years ago

2.0.1-dev-2c6f61

4 years ago

2.0.1-dev-884d67

4 years ago

2.0.1-dev-e3e248

4 years ago

2.0.1-dev-c9398f

4 years ago

2.0.1-dev-d2323c

4 years ago

2.0.1-dev-668bcd

4 years ago

2.0.1-dev-1a9d85

4 years ago

2.0.1-dev-408f5c

4 years ago

2.0.1-dev-34090b

4 years ago

2.0.1-dev-44a51a

4 years ago

2.0.1-dev-84ee90

4 years ago

2.0.1-dev-27551e

4 years ago

2.0.1-dev-b858db

4 years ago

2.0.1-dev-344f51

4 years ago

2.0.1-dev-a72f2d

4 years ago

2.0.1-dev-1ccd91

4 years ago

2.0.1-dev-26179c

4 years ago

2.0.1-dev-c26756

4 years ago

2.0.1-dev-0d6620

4 years ago

2.0.1-dev-8f422a

4 years ago

2.0.1-dev-f26e8e

4 years ago

2.0.1-dev-6b2a08

4 years ago

2.0.1-dev-5fdcf6

4 years ago

2.0.1-dev-33d8cc

4 years ago

2.0.1-dev-fdae91

4 years ago

2.0.1-dev-73392b

4 years ago

2.0.1-dev-50f109

4 years ago

2.0.1-dev-4a4969

4 years ago

2.0.1-dev-d57cb7

4 years ago

2.0.1-dev-4b6363

4 years ago

2.0.1-dev-f73330

4 years ago

2.0.1-dev-0404d6

4 years ago

2.0.1-dev-28fad3

4 years ago

2.0.1-dev-0960d2

4 years ago

2.0.1-dev-4e62c0

4 years ago

2.0.1-dev-c5f11e

4 years ago

2.0.1-dev-4aaeef

4 years ago

2.0.1-dev-91dbfd

4 years ago

2.0.1-dev-823e2b

4 years ago

2.0.1-dev-777aa8

4 years ago

2.0.1-dev-ee0460

4 years ago

2.0.1-dev-caed57

4 years ago

2.0.1-dev-1a83ec

4 years ago

2.0.1-dev-136161

4 years ago

2.0.1-dev-6acd5e

4 years ago

2.0.1-dev-f88f66

4 years ago

2.0.1-dev-d6ea96

4 years ago

2.0.1-dev-ae870f

4 years ago

2.0.1-dev-60d48a

4 years ago

2.0.1-dev-dab0b6

4 years ago

2.0.1-dev-02149e

4 years ago

2.0.1-dev-c12c4e

4 years ago

2.0.1-dev-af6c11

4 years ago

2.0.1-dev-661601

4 years ago

2.0.1-dev-489a2f

4 years ago

2.0.1-dev-ee3302

4 years ago

2.0.0

4 years ago

1.0.0

4 years ago

1.0.0-dev-ab55f4

4 years ago

1.0.0-dev-103d63

4 years ago

0.4.6

4 years ago

0.4.5

4 years ago

0.4.5-rc.1

4 years ago

0.4.4

4 years ago

0.4.3

4 years ago

0.4.2

4 years ago

0.4.1

5 years ago

0.4.0

5 years ago

0.3.0

5 years ago

0.2.0

5 years ago

0.1.3

5 years ago

0.1.1-rc.3

5 years ago

0.1.1-rc.2

5 years ago

0.1.1-rc.1

5 years ago

0.1.0

5 years ago

0.0.5-rc.2

5 years ago

0.0.5-rc.1

5 years ago

0.0.3

5 years ago

0.0.2

5 years ago

0.0.1

5 years ago