npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@eveble/matchist

v1.3.0

Published

Pattern matcher for matching the types and structure of variables

Downloads

24

Readme

Eveble Matchist CircleCI

Pattern matcher useful for matching types and structure of variables.

Table of Contents

Installation

Using yarn:

yarn install @eveble/matchist

Usage

In Node.js:

Import the library

// Cherry-pick methods for smaller bundles(like rollup).
import {
  match,
  isMatching,
  any,
  integer,
  objectIncluding,
  maybe,
  optional,
  oneOf,
  where,
  MatchError,
  InvalidDefinitionError,
} from '@eveble/matchist';

Simple definitions

You can define patterns by simply specifying required value type or expected content:

Type

match(null, null); // true
match(undefined, undefined); // true
match('foo', String); // true
match(1, Number); // true
match(true, Boolean); // true
match(new Date('December 17, 1995 03:24:00'), Date); // true
match(/foo/, RegExp); // true
match(() => {
  return 'foo';
}, Function); // true
match(['foo', 1, true], Array); // true
match(['foo'], [String]); // true
match(['foo', 1], [String, Number]); // true
match({ foo: 'bar' }, Object); // true
match({ foo: 'bar' }, { foo: String }); // true
match({ foo: 'bar', baz: 1 }, { foo: String, baz: Number }); // true
class FooClass {}
match(new FooClass(), FooClass); // true
match([new FooClass()], [FooClass]); // true
match({ foo: new FooClass() }, { foo: FooClass }); // true

Equality

match('foo', 'foo'); // true
match(1, 1); // true
match(true, true); // true
match(
  new Date('December 17, 1995 03:24:00'),
  new Date('December 17, 1995 03:24:00')
); // true
match('foo', /foo/); // true
match(['foo'], ['foo']); // true
match(['foo', 1], ['foo', 1]); // true
match(['foo', 'bar'], ['foo', 'bar']); // true
match({ foo: 'bar', baz: 1 }, { foo: 'bar', baz: 1 }); // true

Simple Patterns

The following patterns can be used to alter or augment definitions while still keeping api simple and easily readable. Please be aware you provide invalid definition for pattern - InvalidDefinitionError will be thrown with detailed information what type of argument is expected.

any

Matches any value.

match(1, any); // true
match('foo', any); // true
match(new Date(), any); // true
match(true, any); // true
match(false, any); // true
match(undefined, any); // true
match(null, any); // true
match(() => {}, any); // true
match([1, 'foo', true, false], [any]); // true
match({ foo: 'bar' }, { foo: any }); // true
match({ foo: 1 }, { foo: any }); // true

Integer

Matches a signed 32-bit integer. Doesn’t match Infinity, -Infinity, NaN.

match(1, Integer);
match(0, Integer);
match(-1, Integer);
match(-2147483648, Integer);
match(2147483647, Integer);
match(Infinity, Integer); // MatchError: Expected Integer, got Number(null)
match(1.2, Integer); // MatchError: Expected Integer, got Number(1.2)
match('foo', Integer); // MatchError: Expected Integer, got String("foo")

objectIncluding

Matches an Object with the given keys; the value may also have other keys with arbitrary values.

class FooClass {}
match({ foo: 'foo' }, objectIncluding({ foo: String })); // true
match({ foo: new FooClass() }, objectIncluding({ foo: FooClass })); // true
match({ foo: 'foo', bar: 'bar' }, objectIncluding({ foo: String })); // true
match({ foo: 'foo', bar: 'bar' }, objectIncluding({ baz: String })); // MatchError: (Key baz in {"foo":"foo","bar":"bar"}) - Expected undefined to be a String

maybe

Matches: undefined, null or provided pattern. When used on Object it matches only if the key is not set as opposed to the value being set to undefined or null.

match(undefined, maybe(String)); // true
match(null, maybe(String)); // true
match({ required: 'value' }, { required: String, maybe: maybe(String) }); // true
match(
  { required: 'value', maybe: undefined },
  { required: String, maybe: maybe(String) }
); // true
match(
  { required: 'value', maybe: null },
  { required: String, maybe: maybe(String) }
); // true

optional

Matches: undefined or provided pattern. When used in an Object, the behavior is identical to maybe.

match(undefined, optional(String));
match(null, optional(String)); // MatchError: Expected null to be a String
match({ required: 'value' }, { required: String, optional: optional(String) }); // true
match(
  { required: 'value', optional: undefined },
  { required: String, optional: optional(String) }
); // true
match(
  { required: 'value', optional: null },
  { required: String, optional: optional(String) }
); // MatchError: (Key optional in {"required":"value","optional":null}) - Expected null to be a String

oneOf

Matches any value that is a valid match for one of the provided arguments(patterns).

match({ foo: new MyClass() }, objectIncluding({ foo: MyClass })); // true
match('foo', oneOf(String, Number)); // true
match(10, oneOf(String, Number)); // true
match([1, 2, 3], oneOf([String], [Number])); // true
match(['foo', 'bar'], oneOf([String], [Number])); // true
match(1, oneOf(1, 2)); // true
match(new Date('December 17, 1995 03:24:00'), oneOf(String, Date)); // true
match('foo', oneOf('foo', 'bar')); // true
match('qux', oneOf('foo', 'bar')); // MatchError: Expected String("qux") to be one of: String("foo"), String("bar")
match(null, oneOf(null, undefined)); // true
match(undefined, oneOf(null, undefined)); // true
match(true, oneOf(true, false)); // true
match(false, oneOf(true, false)); // true
match(new MyClass(), oneOf(String, MyClass)); // true
match(MyClass, oneOf(String, MyClass)); // true
match('foo', oneOf('foo', 'bar')); // true
match('foo', oneOf('bar', /^foo$/g)); // true
match({ foo: 'bar' }, { foo: oneOf('bar', 'baz') }); // true
match({ foo: 'baz' }, { foo: oneOf('bar', 'baz') }); // true
match({ foo: 'qux' }, { foo: oneOf('bar', 'baz') }); // MatchError: (Key foo in {"foo":"qux"}) - Expected String("qux") to be one of: String("bar"), String("baz")

where

Calls the function with the value as the argument. If returns true, this match is valid. If condition throws a MatchError or returns false, this fails.

match(
  'foo',
  where(value => {
    return value === 'foo';
  })
); // true
match(
  'not-foo',
  where(value => {
    return value === 'foo';
  })
); // Failed WherePattern validation
match(
  `Luke, I'm your father!`,
  where(value => {
    const isValid = value === `Luke, I'm your father!`;
    if (!isValid) {
      throw new MatchError(`nooooooooo!`);
    }
    return isValid;
  })
); // MatchError: nooooooooo!
match(
  { foo: 'foo' },
  {
    foo: where(value => {
      return value === 'foo';
    }),
  }
); // true

Explicit Patterns

instanceOf

Matches if provided value is instance of specific type.

match(null, instanceOf(null)); // true
match(undefined, instanceOf(undefined)); // true
match('foo', instanceOf(String)); // true
match(1, instanceOf(Number)); // true
match(true, instanceOf(Boolean)); // true
match(new Date('December 17, 1995 03:24:00'), instanceOf(Date)); // true
match(/foo/, instanceOf(RegExp)); // true
match(() => {
  return 'foo';
}, instanceOf(Function)); // true
match(['foo'], instanceOf(Array)); // true
match({ foo: 'bar' }, instanceOf(Object)); // true

equals

Matches value content(for Array use ArrayPattern, for Objects use ObjectPattern or just use simple pattern definition(implicit) - otherwise MatchError will be thrown).

match('foo', equals('foo')); // true
match(1, equals(1)); // true
match(true, equals(true)); // true
match(
  new Date('December 17, 1995 03:24:00'),
  equals(new Date('December 17, 1995 03:24:00'))
); // true
match('foo', equals(/foo/)); // true

ArrayPattern

Matches value patterns inside Array.

match(['foo', 1, true], new ArrayPattern(Array)); // true
match(['foo'], new ArrayPattern([String])); // true
match(['foo', 1], new ArrayPattern([String, Number])); // true
match(['foo'], new ArrayPattern(['foo'])); // true
match(['foo', 1], new ArrayPattern(['foo', 1])); // true

ObjectPattern

Matches key:value pairs inside Object.

match({ foo: 'bar' }, new ObjectPattern({ foo: String })); // true
match({ foo: 'bar', baz: 1 }, new ObjectPattern({ foo: String, baz: Number })); // true
match(
  { foo: 'bar', baz: 'qux' },
  new ObjectPattern({ foo: 'bar', baz: 'qux' })
); // true

You can always use instantiation way to define patterns instead of using simple api:

| Simple API | Instantiation API | | ------------------- | ------------------------------ | | any() | new AnythingPattern() | | equals() | new EqualityPattern() | | Integer() | new IntegerPattern() | | objectIncluding() | new ObjectIncludingPattern() | | oneOf() | new OneOfPattern() | | maybe() | new MaybePattern() | | optional() | new OptionalPattern() | | instanceOf() | new TypePattern() | | where() | new WherePattern() |

API

Package supports two ways of validating values:

match

match will return true upon value matching pattern or throw MatchError with human readable error message that can be shown back to the user.

match(value, patternOrDef, isStrict); // true or throws MatchError

import { match } from '@eveble/matchist';

| ARGUMENTS | | | | --------------- | ------------ | -------------------------------------------------------------------- | | value | Any | The value to check | | patternOrDef | Pattern|Any | The Pattern instance or implicit definition to match value against | | [isStrict=true] | Boolean | Flag indicating that evaluation should be done in strict mode. |

isMatching

isMatching will return boolean on successful or failed matching pattern.

isMatching(value, pattern, isStrict); // true or false

import { isMatching } from '@eveble/matchist';

| ARGUMENTS | | | | --------------- | ------------ | -------------------------------------------------------------------- | | value | Any | The value to check | | patternOrDef | Pattern|Any | The Pattern instance or implicit definition to match value against | | [isStrict=true] | Boolean | Flag indicating that evaluation should be done in strict mode. |

Testing

Using yarn:

yarn test

License

The MIT License (MIT)

Copyright (c)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.