
Research
/Security News
DuckDB npm Account Compromised in Continuing Supply Chain Attack
Ongoing npm supply chain attack spreads to DuckDB: multiple packages compromised with the same wallet-drainer malware.
A type-safe pattern builder & route matching library written in TypeScript
A type-safe pattern builder & route matching library written in TypeScript
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 } }
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 } }
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
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.
Parse a string into a
Chemin
object
Accepts a string
(/admin/:user/edit?
) and return a Chemin
.
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?');
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'));
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
An array of the parts (other
Chemin
s orCheminParam
s) 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 !
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 beginingtrailingSlash
(default: false
): Add a slash at the endconst chemin = Chemin.create(
'admin',
CheminParam.number('userId'),
CheminParam.optionalConst('edit')
);
chemin.serialize({ userId: 42, edit: true }); // /admin/42/edit
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 doneparams
: an object of params extracted from the matchingNote: If you want to pass an array to pathname
make sure to use splitPathname
.
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.
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];
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
Split a pathname and prevent empty parts
Accepts a string and returns an array od strings.
splitPathname('/admin/user/5'); // ['admin', 'user', '5']
The CheminParam
object contains the build-in CheminParam
.
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
...
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 }
Any non-empty string
const chemin = Chemin.create(CheminParam.string('myStr'));
Chemin.matchExact(chemin, '/cat'); // { myStr: 'cat' }
A constant string
const chemin = Chemin.create(CheminParam.constant('edit'));
Chemin.matchExact(chemin, '/edit'); // {}
Chemin.matchExact(chemin, '/'); // false
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 } }
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 }
An optional string parameter
const chemin = Chemin.create(CheminParam.optionalString('name'));
Chemin.matchExact(chemin, '/paul'); // { name: 'paul' }
Chemin.matchExact(chemin, '/'); // { name: false }
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'] }
FAQs
A type-safe pattern builder & route matching library written in TypeScript
The npm package chemin receives a total of 71 weekly downloads. As such, chemin popularity was classified as not popular.
We found that chemin demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
/Security News
Ongoing npm supply chain attack spreads to DuckDB: multiple packages compromised with the same wallet-drainer malware.
Security News
The MCP Steering Committee has launched the official MCP Registry in preview, a central hub for discovering and publishing MCP servers.
Product
Socket’s new Pull Request Stories give security teams clear visibility into dependency risks and outcomes across scanned pull requests.