Skip to content

Korrigans/meteor-k-check

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

51 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

meteor-k-check

koriggans:k-check

Korrigans's own argument checking and general pattern matching package and function K.check. Mostly compatible with native check package (see limitations).

Offers better error reporting and extensibility than the native package.

Table of Contents

Installation

In your Meteor app directory, enter:

$ meteor add koriggans:k-check

In your package:

api.use('korrigans:k-check@0.1.0');

Use

Use the package through K.check:

K.check(42, Number);

You can use almost all legacy check patterns.

These pass:

K.check('foo', String);
K.check(new Error('message'), Error);
K.check(20, Match.Where(value => value % 5 === 0));
K.check('exact value', 'exact value');
K.check(true, Match.OneOf(42, true));
K.check({ foo : 0 }, { foo : Number });
K.check([3, 6, 9], [Number]);

These fail:

// Error: [K.check] Expected number, got "foo".
K.check('foo', Number);

// Error: [K.check] Expected 42, got 0.
K.check(0, 42);

// Error: [K.check] Expected Match.OneOf(string, number, 42), got null.
K.check(null, Match.OneOf(String, Number, 42));
// Legacy error:
// Error: Match error: Failed Match.OneOf or Match.Optional validation
check(null, Match.OneOf(String, Number, 42));

// Error: [K.check] Expected { foo: string, bar: number, korrigans: function },
// got { foo: "foo", bar: 0, baz: true } (excess: baz; missing: korrigans).
K.check({
  foo: 'foo',
  bar: 0,
  baz: true
}, {
  foo: String,
  bar: Number,
  korrigans: Function
});
// Legacy error:
// Error: Match error: Unknown key in field baz

// Error: [K.check] Expected number,
// got "foo" at index 3 of [5, 10, 15, "foo"] against [number].
K.check([5, 10, 15, 'foo'], [Number]);
// Legacy error:
// Error: Match error: Expected number, got string in field [3]

You can also extend the possibilities of K.check by defining your own patterns and test functions.

Advanced

Custom patterns

To allow the use of custom functions K.check provides a Symbol (basically a hidden property) to be placed on objects: K.check.custom. K.check expects a function to be set on this specific symbol. To use custom tests use this Symbol on objects:

myObject[K.check.custom] = value => runTest(value);
// Or:
myObject[K.check.custom] = runTest;

You may then use your object as a pattern:

K.check('some value', myObject);

The custom function overrides all native behaviours of K.check.
If the function throws an error, it is propagated.
Contrary to Match.Where the return value is discarded. Returning a falsey value (or not returning at all) will not fail the test.

Example use:

const percentagePattern = {
  min: 0,
  max: 100,
  // Magic happens here:
  [K.check.custom](value) {
    if (!Number.isFinite(value)) {
      throw new Error('value not finite number');
    }
    if (value < this.min) {
      throw new Error('number too small');
    }
    if (value > this.max) {
      throw new Error('number too big');
    }
    // Return value is discarded, no need to provide one
  }
};

// These pass
K.check(42, percentagePattern);
K.check(0, percentagePattern);
K.check(Math.PI, percentagePattern);

// Error: value not finite number
K.check('foo', percentagePattern);
K.check(NaN, percentagePattern);
K.check(Infinity, percentagePattern);

// Error: number too small
K.check(-1, percentagePattern);

// Error: number too big
K.check(9001, percentagePattern);

Using an existing object:

const todayPattern = new Date();

todayPattern[K.check.custom] = function createdToday(value) {
  if (!_.isObject(value) || !_.has(value, 'creationDate')) {
    throw new Error('value is not a document with creationDate property');
  }
  if (value.creationDate.getDate() !== this.getDate()) {
    throw new Error('document was not created today');
  }
};

// This passes
const today = Date.now();
K.check({
  creationDate: today
}, todayPattern);

// These fail
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
K.check({
  creationDate: yesterday
}, todayPattern);

K.check('foo', todayPattern);

K.ErrorLog

Some patterns can generate very lengthy error messages:

K.check({
  foo: {
    bar: {
      baz: [3, 6, 9, 'dwarf']
    }
  }
}, {
  foo: {
    bar: {
      baz: [Number]
    }
  }
});
// Error: [K.check] Expected number, got "dwarf"
// at index 3 of [3, 6, 9, "dwarf"] against [number] (K.ErrorLog.Check[0]).

The full path is not in the error message as it would get very long.
Instead only last path is reported.

Here, full path is stored at log indicated at end of error message:

K.ErrorLog.Check[0]

This log has following structure:

{
  message: 'Expected number, got "dwarf" at index 3 of [3, 6, 9, "dwarf"] against [number]',
  path : [
    'key foo of { foo: { bar: { baz: [3, 6, 9, "dwarf"] } } } against { foo: { bar: { baz: [number] } } }',
    'key bar of { bar: { baz: [3, 6, 9, "dwarf"] } } against { bar: { baz: [number] } }',
    'key baz of { baz: [3, 6, 9, "dwarf"] } against { baz: [number] }'
  ]
}

This is a complete trace of each recursive call run by K.check.
It provides exact error message in message field, and each step of validation in path. path is an array ordered from outer to inner of value and pattern.

Limitations

Match.Optional, Match.ObjectIncluding and Match.ObjectWithValues are not supported.

K.check uses duck typing to figure out which legacy patterns are passed. For example, if a passed pattern has a condition method then it is probably a Match.Where instance. This is not possible with the three above legacy patterns. All three shadow each other with the same pattern field. Due to this limitation, they are indistinguishable from the outside.

Dependants

Testing

In your Meteor app directory, clone the package files in packages folder:

$ git clone https://github.com/Korrigans/meteor-k-check ./packages/meteor-k-check

Then start the tests:

$ set VELOCITY_TEST_PACKAGES=1
$ meteor test-packages --driver-package velocity:html-reporter korrigans:k-check

Contributors

License

MIT

About

Meteor package to replace Meteor's check

Resources

License

Stars

Watchers

Forks

Packages

No packages published