All Projects â†’ etienne-dldc â†’ chemin

etienne-dldc / chemin

Licence: MIT license
🥾 A type-safe pattern builder & route matching library written in TypeScript

Programming Languages

typescript
32286 projects
javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to chemin

Ts Pattern
🎨 A complete Pattern Matching library for TypeScript, with smart type inference.
Stars: ✭ 854 (+2208.11%)
Mutual labels:  matching, pattern, pattern-matching
Pattern Matching Ts
âš¡ Pattern Matching in Typescript
Stars: ✭ 107 (+189.19%)
Mutual labels:  matching, pattern, pattern-matching
Nanomatch
Fast, minimal glob matcher for node.js. Similar to micromatch, minimatch and multimatch, but without support for extended globs (extglobs), posix brackets or braces, and with complete Bash 4.3 wildcard support: ("*", "**", and "?").
Stars: ✭ 79 (+113.51%)
Mutual labels:  pattern, pattern-matching
Sig
The most powerful and customizable binary pattern scanner
Stars: ✭ 131 (+254.05%)
Mutual labels:  pattern, pattern-matching
dir-glob
Convert directories to glob compatible strings
Stars: ✭ 41 (+10.81%)
Mutual labels:  matching, pattern
allot
Parse placeholder and wildcard text commands
Stars: ✭ 51 (+37.84%)
Mutual labels:  matching, pattern
Mach7
Functional programming style pattern-matching library for C++
Stars: ✭ 1,151 (+3010.81%)
Mutual labels:  pattern, pattern-matching
Motif
Recursive, data driven pattern matching for Clojure
Stars: ✭ 63 (+70.27%)
Mutual labels:  matching, pattern
receptacle
minimalistic implementation of the repository pattern
Stars: ✭ 18 (-51.35%)
Mutual labels:  pattern
ST-OpenUri
The ultimate Sublime Text plugin for opening URIs (URLs) in your file.
Stars: ✭ 25 (-32.43%)
Mutual labels:  url
django-slugs-example-app
A basic app to show how to add slugs to models
Stars: ✭ 12 (-67.57%)
Mutual labels:  url
csharp-workshop
NDC London 2019, Workshop: Become a better C# programmer: more Value, more Expressions, no Waiting
Stars: ✭ 21 (-43.24%)
Mutual labels:  pattern-matching
match
Pattern-Matching written by Dan Friedman, Erik Hilsdale and Kent Dybvig
Stars: ✭ 20 (-45.95%)
Mutual labels:  pattern-matching
BinFind
Perform regex pattern matching on binary data. (Regex-like)
Stars: ✭ 31 (-16.22%)
Mutual labels:  pattern
extractacy
Spacy pipeline object for extracting values that correspond to a named entity (e.g., birth dates, account numbers, laboratory results)
Stars: ✭ 47 (+27.03%)
Mutual labels:  pattern-matching
koa-ip-filter
koa middleware to filter request IPs or custom ID with glob patterns, array, string, regexp or matcher function. Support custom 403 Forbidden message and custom ID.
Stars: ✭ 23 (-37.84%)
Mutual labels:  matching
video thumbnail
This plugin generates thumbnail from video file or URL. It returns image in memory or writes into a file. It offers rich options to control the image format, resolution and quality. Supports iOS and Android.
Stars: ✭ 159 (+329.73%)
Mutual labels:  url
node-match-path
Matches a URL against a path. Parameters, wildcards, RegExp.
Stars: ✭ 30 (-18.92%)
Mutual labels:  url
url-normalize
URL normalization for Python
Stars: ✭ 82 (+121.62%)
Mutual labels:  url
ASV
[CVPR16] Accumulated Stability Voting: A Robust Descriptor from Descriptors of Multiple Scales
Stars: ✭ 26 (-29.73%)
Mutual labels:  matching

chemin logo

🥾 Chemin Build Status

A type-safe pattern builder & route matching library written in TypeScript

Gist

import { Chemin } from 'chemin';

const chemin = Chemin.parse('/admin/post/:postId/delete?');

console.log(chemin.match('/no/valid'));
// => false

console.log(chemin.match('/admin/post/e5t89u'));
// => { rest: [], params: { postId: 'e5t89u', delete: false } }

More advanced (and type-safe) patterns

Use the Chemin.create and CheminParam to build more complex type-safe paths !

import { Chemin, CheminParam as P } from 'chemin';

const chemin = Chemin.create('admin', 'post', P.number('postId'), P.optionalConst('delete'));

console.log(chemin.match('/no/valid'));
// => false

const match = chemin.match('/admin/post/45');
console.log(match);
// => { rest: [], params: { postId: 45, delete: false } }

Composition

You can use a Chemin inside another to easily compose your routes !

import { Chemin, CheminParam as P } from 'chemin';

const postFragment = Chemin.create('post', P.number('postId'));
const postAdmin = Chemin.create('admin', P.string('userId'), postFragment, 'edit');

console.log(postAdmin.stringify()); // /admin/:userId/post/:postId(number)/edit

Custom CheminParam

You can create your own CheminParam to better fit your application while keeping full type-safety !

import { Chemin, CheminParam } from 'chemin';

// match only string of 4 char [a-z0-9]
function fourCharStringId<N extends string>(name: N): CheminParam<N, string> {
  const reg = /^[a-z0-9]{4}$/;
  return {
    name,
    match: (...all) => {
      if (all[0].match(reg)) {
        return { match: true, value: all[0], next: all.slice(1) };
      }
      return { match: false, next: all };
    },
    serialize: (value) => value,
    stringify: () => `:${name}(id4)`,
  };
}

const path = Chemin.create('item', fourCharStringId('itemId'));
console.log(path.match('/item/a4e3t')); // false (5 char)
console.log(path.match('/item/A4e3')); // false (Maj)
console.log(path.match('/item/a4e3')); // { rest: [], params: { itemId: 'a4e3' } }

Take a look a the custom-advanced.ts example. and the build-in CheminParam.

API

Chemin.parse(pattern)

Parse a string into a Chemin object

Accepts a string (/admin/:user/edit?) and return a Chemin.

Supported patterns

  • admin: Create a CheminParam.constant('admin')
  • :param: Create a CheminParam.string('param')
  • maybe?: Create a CheminParam.optionalConst('maybe')
  • :maybe?: Create a CheminParam.optionalString('maybe')
Chemin.parse('/admin/:userId/edit?');

Chemin.create(...parts)

Create a Chemin

Accepts any number or arguments of type string, CheminParam or Chemin.

Note: strings are converted to CheminParam.constant.

Chemin.create('admin', CheminParam.number('userId'), CheminParam.optionalConst('edit'));

Chemin.isChemin(maybe)

Test wether an object is a Chemin or not

Accepts one argument and return true if it's a Chemin, false otherwise.

Chemin.isChemin(Chemin.parse('/admin')); // true

chemin.parts

An array of the parts (other Chemins or CheminParams) that make the chemin.

Note: You probably don't need this.

Note 2: You should not mutate this array or any of it's elements !

chemin.serialize(params?, options?)

Serialize a chemin

Accepts some params (an object or null) and an optional option object.

The option object accepts two boolean properties:

  • leadingSlash (default true): Add a slash at the begining
  • trailingSlash (default: false): Add a slash at the end
const chemin = Chemin.create(
  'admin',
  CheminParam.number('userId'),
  CheminParam.optionalConst('edit')
);
chemin.serialize({ userId: 42, edit: true }); // /admin/42/edit

chemin.match(pathname)

Test a chemin against a pathanme

Accepts a pathname and return false or CheminMatchResult.

  • pathname can be either a string (/admin/user/5) or an array of strings (['admin', 'user', '5'])
  • CheminMatchResult is an object with two properties
    • rest: an array of string of the remaining parts of the pathname once the matching is done
    • params: an object of params extracted from the matching

Note: If you want to pass an array to pathname make sure to use splitPathname.

chemin.matchExact(pathname)

Accepts the same arguments as chemin.match but return false if the path does not match or if rest is not empty, otherwise it returns the params object directly.

chemin.extract()

Return an array of all the Chemin it contains (as well as the Chemin itself).

import { Chemin } from 'chemin';

const admin = Chemin.create('admin');
const adminUser = Chemin.create(admin, 'user');

adminUser.extract(); // [adminUser, admin];

chemin.stringify()

Return a string representation of the chemin.

import { Chemin, CheminParam as P } from 'chemin';

const postFragment = Chemin.create('post', P.number('postId'));
const postAdmin = Chemin.create('admin', P.string('userId'), postFragment, 'edit');

console.log(postAdmin.stringify()); // /admin/:userId/post/:postId(number)/edit

splitPathname(pathname)

Split a pathname and prevent empty parts

Accepts a string and returns an array od strings.

splitPathname('/admin/user/5'); // ['admin', 'user', '5']

CheminParam

The CheminParam object contains the build-in CheminParam.

CheminParam.number(name)

A number using parseFloat(x)

const chemin = Chemin.create(CheminParam.number('myNum'));
Chemin.matchExact(chemin, '/3.1415'); // { myNum: 3.1415 }

NOTE: Because it uses parseFloat this will also accept Infinity, 10e2...

CheminParam.integer(name, options?)

A integer using parseInt(x, 10)

const chemin = Chemin.create(CheminParam.integer('myInt'));
Chemin.matchExact(chemin, '/42'); // { myInt: 42 }

By default it will only match if the parsed number is the same as the raw value. You can pass an option object with strict: false to allow any valid parseInt:

const chemin = Chemin.create(CheminParam.integer('myInt', { strict: false }));
Chemin.matchExact(chemin, '/42fooo'); // { myInt: 42 }

CheminParam.string(name)

Any non-empty string

const chemin = Chemin.create(CheminParam.string('myStr'));
Chemin.matchExact(chemin, '/cat'); // { myStr: 'cat' }

CheminParam.constant(name)

A constant string

const chemin = Chemin.create(CheminParam.constant('edit'));
Chemin.matchExact(chemin, '/edit'); // {}
Chemin.matchExact(chemin, '/'); // false

CheminParam.optional(cheminParam)

Make any CheminParam optional

const chemin = Chemin.create(CheminParam.optional(CheminParam.integer('myInt')));
Chemin.matchExact(chemin, '/42'); // { myInt: { present: true, value: 42 } }
Chemin.matchExact(chemin, '/'); // { myInt: { present: false } }

CheminParam.optionalConst(name, path?)

An optional contant string

const chemin = Chemin.create(CheminParam.optionalConst('isEditing', 'edit'));
Chemin.matchExact(chemin, '/edit'); // { isEditing: true }
Chemin.matchExact(chemin, '/'); // { isEditing: false }

If path is omitted then the name is used as the path.

const chemin = Chemin.create(CheminParam.optionalConst('edit'));
Chemin.matchExact(chemin, '/edit'); // { edit: true }
Chemin.matchExact(chemin, '/'); // { edit: false }

CheminParam.optionalString(name)

An optional string parameter

const chemin = Chemin.create(CheminParam.optionalString('name'));
Chemin.matchExact(chemin, '/paul'); // { name: 'paul' }
Chemin.matchExact(chemin, '/'); // { name: false }

CheminParam.multiple(cheminParam, atLeastOne?)

Allow a params to be repeated any number of time

const chemin = Chemin.create(CheminParam.multiple(CheminParam.string('categories')));
Chemin.matchExact(chemin, '/'); // { categories: [] }
Chemin.matchExact(chemin, '/foo/bar'); // { categories: ['foo', 'bar'] }
const chemin = Chemin.create(CheminParam.multiple(CheminParam.string('categories'), true));
Chemin.matchExact(chemin, '/'); // false because atLeastOne is true
Chemin.matchExact(chemin, '/foo/bar'); // { categories: ['foo', 'bar'] }
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].