{"id":50621996,"url":"https://github.com/the-cookbook/pathkit","last_synced_at":"2026-06-06T13:00:53.380Z","repository":{"id":358631639,"uuid":"1241365422","full_name":"the-cookbook/pathkit","owner":"the-cookbook","description":"A lightweight route pattern parser, matcher and compiler for TypeScript.","archived":false,"fork":false,"pushed_at":"2026-06-04T07:30:09.000Z","size":147,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-04T09:14:09.730Z","etag":null,"topics":["developer-tools","javascript","node","params","path","path-to-regexp","route-compiler","route-constraints","route-match","route-parser","router","routing","typescript","url-generator","url-routing","validation","zero-dependencies"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/the-cookbook.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-17T09:46:26.000Z","updated_at":"2026-06-04T07:30:13.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/the-cookbook/pathkit","commit_stats":null,"previous_names":["the-cookbook/pathkit"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/the-cookbook/pathkit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/the-cookbook%2Fpathkit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/the-cookbook%2Fpathkit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/the-cookbook%2Fpathkit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/the-cookbook%2Fpathkit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/the-cookbook","download_url":"https://codeload.github.com/the-cookbook/pathkit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/the-cookbook%2Fpathkit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33983046,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-06T02:00:07.033Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["developer-tools","javascript","node","params","path","path-to-regexp","route-compiler","route-constraints","route-match","route-parser","router","routing","typescript","url-generator","url-routing","validation","zero-dependencies"],"created_at":"2026-06-06T13:00:32.822Z","updated_at":"2026-06-06T13:00:53.367Z","avatar_url":"https://github.com/the-cookbook.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `@cookbook/pathkit`\n\n[![npm version](https://img.shields.io/npm/v/@cookbook/pathkit.svg)](https://www.npmjs.com/package/@cookbook/pathkit)\n[![npm downloads](https://img.shields.io/npm/dm/@cookbook/pathkit.svg)](https://www.npmjs.com/package/@cookbook/pathkit)\n[![Bundle size](https://img.shields.io/bundlephobia/minzip/@cookbook/pathkit)](https://bundlephobia.com/package/@cookbook/pathkit)\n[![CI](https://github.com/the-cookbook/pathkit/actions/workflows/ci.yml/badge.svg)](https://github.com/the-cookbook/pathkit/actions/workflows/ci.yml)\n\nA lightweight route compiler, matcher, tokenizer, and validation toolkit for JavaScript and TypeScript.\n\n`@cookbook/pathkit` provides a predictable and extensible route pattern system with support for:\n\n- Route compilation\n- Route matching\n- Route tokenization\n- Route validation\n- Optional parameters\n- Wildcard parameters\n- Runtime constraints\n- Custom constraints\n- Custom delimiters\n- Parameter type enforcement\n- Strict match validation\n- TypeScript support\n- ESM and CommonJS\n\n---\n\n# Table of Contents\n\n- [Installation](#installation)\n- [Inspiration](#inspiration)\n- [Comparison with `path-to-regexp`](#comparison-with-path-to-regexp)\n- [Features](#features)\n- [Route Syntax](#route-syntax)\n  - [Named Parameters](#named-parameters)\n  - [Optional Parameters](#optional-parameters)\n  - [Wildcard Parameters](#wildcard-parameters)\n  - [Optional Wildcards](#optional-wildcards)\n  - [Constraints](#constraints)\n  - [Multiple Constraints](#multiple-constraints)\n- [API](#api)\n  - [compile()](#compile)\n    - [Signature](#signature)\n    - [Example](#example)\n    - [Optional Parameters](#optional-parameters-1)\n    - [Wildcards](#wildcards)\n    - [Constraints](#constraints-1)\n  - [Compile Options](#compile-options)\n    - [delimiter](#delimiter)\n    - [prune](#prune)\n  - [match()](#match)\n    - [Signature](#signature-1)\n    - [Example](#example-1)\n    - [Failed Match](#failed-match)\n    - [Strict Match](#strict-match)\n    - [Optional Parameters](#optional-parameters-2)\n    - [Wildcards](#wildcards-1)\n  - [Match Options](#match-options)\n    - [delimiter](#delimiter-1)\n    - [trailing](#trailing)\n    - [strict](#strict)\n  - [tokenize()](#tokenize)\n    - [Signature](#signature-2)\n    - [Example](#example-2)\n  - [validateRoute()](#validateroute)\n    - [Signature](#signature-3)\n    - [Example](#example-3)\n- [Built-in Constraints](#built-in-constraints)\n  - [ConstraintValidation API](#constraintvalidation-api)\n  - [decimal](#decimal)\n  - [int](#int)\n  - [range](#range)\n  - [list](#list)\n  - [regex](#regex)\n- [Custom Constraints](#custom-constraints)\n  - [createConstraint](#createConstraint)\n  - [registerConstraint()](#registerconstraint)\n  - [unregisterConstraint()](#unregisterconstraint)\n  - [hasConstraint()](#hasconstraint)\n  - [getConstraint()](#getconstraint)\n  - [resetConstraints()](#resetconstraints)\n- [TypeScript](#typescript)\n  - [Route Segments](#route-segments)\n  - [Constraints](#constraints-2)\n  - [Match Results](#match-results)\n- [Module Imports](#module-imports)\n  - [Root Import](#root-import)\n  - [Constraint Namespace](#constraint-namespace)\n  - [Deep Imports](#deep-imports)\n- [Error Handling](#error-handling)\n- [Examples](#examples)\n- [Design Goals](#design-goals)\n- [License](#license)\n\n---\n\n# Installation\n\n```bash\npnpm add @cookbook/pathkit\n```\n\n```bash\nnpm install @cookbook/pathkit\n```\n\n```bash\nyarn add @cookbook/pathkit\n```\n\n---\n\n# Inspiration\n\n`@cookbook/pathkit` is heavily inspired by the Microsoft ASP.NET route template syntax and route constraint system.\n\nReference:\n\n- ASP.NET Core Route Constraints Documentation\n  [https://learn.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-9.0#route-constraints](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-9.0#route-constraints)\n\nExamples:\n\n```txt\n/users/{id}\n/users/{id:int}\n/files/{*path}\n/posts/{slug:regex([a-z0-9-]+)}\n```\n\nThe goal is to provide a powerful and expressive route syntax for JavaScript and TypeScript applications while keeping the implementation lightweight and framework agnostic.\n\n---\n\n# Comparison with `path-to-regexp`\n\n| Feature                            | @cookbook/pathkit | path-to-regexp                  |\n| ---------------------------------- | ----------------- | ------------------------------- |\n| Route compilation                  | Yes               | Yes                             |\n| Route matching                     | Yes               | Yes                             |\n| Route tokenization                 | Yes               | Partial                         |\n| Route validation                   | Yes               | No                              |\n| Runtime constraint system          | Yes               | No                              |\n| Built-in constraints               | Yes               | No                              |\n| Custom constraints                 | Yes               | Limited/custom parsing required |\n| Optional parameters                | Yes               | Yes                             |\n| Wildcard parameters                | Yes               | Yes                             |\n| Parameter type enforcement         | Yes               | No                              |\n| Strict match validation            | Yes               | No                              |\n| TypeScript-first API               | Yes               | Partial                         |\n| Framework agnostic                 | Yes               | Yes                             |\n| Zero dependencies                  | Yes               | No                              |\n| Runtime-safe constraint validation | Yes               | No                              |\n\n`path-to-regexp` focuses primarily on transforming path patterns into regular expressions.\n\n`@cookbook/pathkit` focuses on complete route tooling:\n\n- Route parsing\n- Validation\n- Runtime-safe constraints\n- Typed route segments\n- Route compilation\n- Route matching\n- Extensibility through runtime constraint registration\n\n---\n\n# Features\n\n- Zero dependencies\n- Small runtime footprint\n- Runtime-safe route validation\n- Extensible constraint registry\n- Functional API\n- Framework agnostic\n- SSR compatible\n- ESM + CommonJS exports\n- Strong TypeScript support\n- Optional strict matching for debugging constraint failures\n\n---\n\n# Route Syntax\n\n## Named Parameters\n\n```txt\n/users/{id}\n```\n\n## Optional Parameters\n\n```txt\n/users/{id?}\n```\n\n## Wildcard Parameters\n\n```txt\n/files/{*path}\n```\n\n## Optional Wildcards\n\n```txt\n/files/{*path?}\n```\n\n## Constraints\n\n```txt\n/users/{id:int}\n/posts/{slug:regex([a-z0-9-]+)}\n/search/{type:list(view|expanded|details)}\n```\n\n## Multiple Constraints\n\n```txt\n/users/{id:int:range(1,100)}\n```\n\n---\n\n# API\n\n# compile()\n\nCompiles a route pattern into a function.\n\n## Signature\n\n```ts\ninterface CompileOptions {\n  delimiter?: string;\n  prune?: 'all' | 'duplication' | 'trailing' | false;\n}\n\ntype TypeOrArray\u003cT\u003e = T | T[];\n\ninterface CompileParams {\n  [key: string]: TypeOrArray\u003cstring | number | boolean\u003e | null | undefined;\n}\n\ndeclare const compile: (\n  route: string,\n  options?: CompileOptions,\n) =\u003e (params?: CompileParams) =\u003e string;\n```\n\n## Example\n\n```ts\nimport { compile } from '@cookbook/pathkit';\n\nconst toUser = compile('/users/{id}');\n\ntoUser({ id: 10 });\n\n// /users/10\n```\n\n---\n\n## Optional Parameters\n\n```ts\nconst toSearch = compile('/search/{term?}');\n\ntoSearch();\n\n// /search\n\ntoSearch({ term: 'hello' });\n\n// /search/hello\n```\n\n---\n\n## Wildcards\n\n```ts\nconst toFile = compile('/files/{*path}');\n\ntoFile({\n  path: ['users', 'john', 'avatar.png'],\n});\n\n// /files/users/john/avatar.png\n```\n\n---\n\n## Constraints\n\n```ts\nconst toPage = compile('/page/{type:list(home|dashboard)}');\n\ntoPage({ type: 'home' });\n\n// /page/home\n```\n\nInvalid values throw:\n\n```ts\ntoPage({ type: 'settings' });\n\n// Error:\n// Parameter \"type\" must be one of: home, dashboard\n```\n\n---\n\n# Compile Options\n\n## delimiter\n\nChanges the route segment delimiter used for wildcard joins and route normalization.\n\n```ts\ncompile('namespace.{*path}', {\n  delimiter: '.',\n})({\n  path: ['frontend', 'typescript', 'routing'],\n});\n\n// namespace.frontend.typescript.routing\n```\n\nThis is useful for non-slash route styles such as:\n\n- dot-separated namespaces\n- event routing\n- CLI command patterns\n- message topics\n- internal identifiers\n\n---\n\n## prune\n\nControls route cleanup behavior after compilation.\n\nAvailable values:\n\n```ts\n'all';\n'duplication';\n'trailing';\nfalse;\n```\n\n### `'all'`\n\nRemoves duplicated delimiters and trailing delimiters.\n\n```ts\ncompile('/hello//world/', {\n  prune: 'all',\n})();\n\n// /hello/world\n```\n\n---\n\n### `'duplication'`\n\nRemoves only duplicated delimiters.\n\n```ts\ncompile('/hello//world/', {\n  prune: 'duplication',\n})();\n\n// /hello/world/\n```\n\n---\n\n### `'trailing'`\n\nRemoves only trailing delimiters.\n\n```ts\ncompile('/hello//world/', {\n  prune: 'trailing',\n})();\n\n// /hello//world\n```\n\n---\n\n### `false`\n\nDisables all cleanup behavior.\n\n```ts\ncompile('/hello//world/', {\n  prune: false,\n})();\n\n// /hello//world/\n```\n\n---\n\n# match()\n\nMatches a route pattern against a path.\n\nBy default, `match()` is router-safe: constraint validation failures return a failed match instead of throwing. This makes it suitable for trying multiple route candidates.\n\nUse `strict: true` when you want constraint validation errors to be thrown for debugging or development tooling.\n\n## Signature\n\n```ts\ninterface MatchOptions {\n  delimiter?: string;\n  trailing?: boolean;\n  strict?: boolean;\n}\n\ntype MatchedParam = Record\u003cstring, string | string[] | null | undefined\u003e;\n\ninterface MatchResult {\n  match: boolean;\n  params: MatchedParam | null;\n}\n\ndeclare const match: (route: string, options?: MatchOptions) =\u003e (path: string) =\u003e MatchResult;\n```\n\n## Example\n\n```ts\nimport { match } from '@cookbook/pathkit';\n\nconst matcher = match('/users/{id:int}');\n\nmatcher('/users/42');\n```\n\nReturns:\n\n```ts\n{\n  match: true,\n  params: {\n    id: '42',\n  },\n}\n```\n\n---\n\n## Failed Match\n\n```ts\nmatcher('/users/abc');\n```\n\nReturns:\n\n```ts\n{\n  match: false,\n  params: null,\n}\n```\n\n---\n\n## Strict Match\n\nBy default, invalid constrained values return a failed match:\n\n```ts\nconst matcher = match('/users/{id:int}');\n\nmatcher('/users/abc');\n```\n\nReturns:\n\n```ts\n{\n  match: false,\n  params: null,\n}\n```\n\nEnable `strict` mode to throw constraint validation errors:\n\n```ts\nconst strictMatcher = match('/users/{id:int}', {\n  strict: true,\n});\n\nstrictMatcher('/users/abc');\n```\n\nThrows:\n\n```txt\n[Constraint] Parameter \"id\" must be a number, instead got 'string'\n```\n\nThis is useful for development tools, tests, debugging, and cases where an invalid constrained value should be treated as an application error instead of a non-match.\n\n---\n\n## Optional Parameters\n\n```ts\nconst matcher = match('/search/{term?}');\n\nmatcher('/search');\n```\n\nReturns:\n\n```ts\n{\n  match: true,\n  params: {},\n}\n```\n\n---\n\n## Wildcards\n\n```ts\nconst matcher = match('/files/{*path}');\n\nmatcher('/files/users/john/avatar.png');\n```\n\nReturns:\n\n```ts\n{\n  match: true,\n  params: {\n    path: 'users/john/avatar.png',\n  },\n}\n```\n\n---\n\n# Match Options\n\n## delimiter\n\nSupports non-slash route styles.\n\n```ts\nconst matcher = match('.users.{id}', {\n  delimiter: '.',\n});\n\nmatcher('.users.10');\n```\n\n---\n\n## trailing\n\nControls trailing delimiter matching.\n\n```ts\nmatch('/hello/{name}', {\n  trailing: false,\n});\n```\n\n---\n\n## strict\n\nControls whether constraint validation errors are thrown.\n\nDefault:\n\n```ts\nstrict: false;\n```\n\nWhen `strict` is disabled, constraint validation failures return:\n\n```ts\n{\n  match: false,\n  params: null,\n}\n```\n\nWhen `strict` is enabled, constraint validation failures are thrown:\n\n```ts\nmatch('/users/{id:int}', {\n  strict: true,\n})('/users/abc');\n```\n\nThrows:\n\n```txt\n[Constraint] Parameter \"id\" must be a number, instead got 'string'\n```\n\n---\n\n# tokenize()\n\nTokenizes a route pattern into route segments.\n\n## Signature\n\n```ts\ntype TokenType = 'literal' | 'parameter';\n\ninterface Constraint {\n  type: string;\n  params: string;\n}\n\ninterface LiteralSegment {\n  type: 'literal';\n  value: string;\n}\n\ninterface ParameterSegment {\n  type: 'parameter';\n  name: string;\n  wildcard: boolean;\n  optional: boolean;\n  constraints: Constraint[];\n}\n\ntype RouteSegment = LiteralSegment | ParameterSegment;\n\ndeclare const tokenize: (route: string) =\u003e RouteSegment[];\n```\n\n## Example\n\n```ts\nimport { tokenize } from '@cookbook/pathkit';\n\ntokenize('/users/{id:int}');\n```\n\nReturns:\n\n```ts\n[\n  {\n    type: 'literal',\n    value: '/users/',\n  },\n  {\n    type: 'parameter',\n    name: 'id',\n    wildcard: false,\n    optional: false,\n    constraints: [\n      {\n        type: 'int',\n        params: '',\n      },\n    ],\n  },\n];\n```\n\n---\n\n# validateRoute()\n\nValidates route patterns before runtime usage.\n\n## Signature\n\n```ts\ndeclare const validateRoute: (route: string) =\u003e void;\n```\n\n## Example\n\n```ts\nimport { validateRoute } from '@cookbook/pathkit';\n\nvalidateRoute('/users/{id:int}');\n```\n\nInvalid routes throw descriptive errors.\n\n```ts\nvalidateRoute('/users/{id:unknown}');\n\n// Error:\n// [Constraint]: Unknown constraint type: \"unknown\"\n```\n\n---\n\n# Built-in Constraints\n\nConstraints validate parameter values during `compile()` and `match()`.\n\nEach constraint can also provide:\n\n- `verify()` to validate the route constraint configuration itself\n- `toRegExp()` to generate the matching pattern used by `match()`\n\n---\n\n## ConstraintValidation API\n\n```ts\ninterface ConstraintValidation {\n  (paramName: string, value: string | number | boolean | undefined, params: string): void;\n\n  verify(paramName: string, params: string): void;\n\n  toRegExp(params: string): string;\n}\n```\n\n---\n\n## `decimal`\n\nValidates that a parameter is a decimal.\n\n### Syntax\n\n```txt\n{price:decimal}\n```\n\n### Example\n\n```txt\n/products/by-price/{price:decimal}\n```\n\n### Valid\n\n```txt\n/products/1\n/products/1.5\n/products/42\n/products/9000\n/products/200.99\n```\n\n### Invalid\n\n```txt\n/products/abc\n/products/foo-1\n```\n\n### Notes\n\n- Does not accept constraint parameters\n\n---\n\n## `int`\n\nValidates that a parameter is an integer.\n\n### Syntax\n\n```txt\n{id:int}\n```\n\n### Example\n\n```txt\n/users/{id:int}\n```\n\n### Valid\n\n```txt\n/users/1\n/users/42\n/users/9000\n```\n\n### Invalid\n\n```txt\n/users/abc\n/users/1.5\n/users/foo-1\n```\n\n### Notes\n\n- Does not accept constraint parameters\n- Uses `\\d+` as its match pattern\n- Runtime validation is also applied during `compile()` and during `match()` when a path candidate matches the generated pattern\n\n---\n\n## `range`\n\nValidates that a numeric parameter is inside an inclusive range.\n\n### Syntax\n\n```txt\n{id:range(min,max)}\n```\n\n### Example\n\n```txt\n/users/{id:range(1,100)}\n```\n\n### Valid\n\n```txt\n/users/1\n/users/50\n/users/100\n```\n\n### Invalid\n\n```txt\n/users/0\n/users/101\n/users/abc\n```\n\n### Notes\n\n- `min` and `max` are required\n- The range is inclusive\n- Values are validated numerically\n\n---\n\n## `list`\n\nValidates that a parameter matches one item from a pipe-separated list.\n\n### Syntax\n\n```txt\n{param:list(item1|item2|item3)}\n```\n\n### Example\n\n```txt\n/search/{type:list(view|expanded|details)}\n```\n\n### Valid\n\n```txt\n/search/view\n/search/expanded\n/search/details\n```\n\n### Invalid\n\n```txt\n/search/grid\n/search/detail\n```\n\n### Notes\n\n- Items are separated with `|`\n- Matching is exact\n- List values are also used to generate the matcher RegExp\n\n---\n\n## `regex`\n\nValidates that a parameter matches a custom regular expression.\n\n### Syntax\n\n```txt\n{param:regex(pattern)}\n```\n\n### Example\n\n```txt\n/posts/{slug:regex([a-z0-9-]+)}\n```\n\n### Valid\n\n```txt\n/posts/hello-world\n/posts/post-123\n```\n\n### Invalid\n\n```txt\n/posts/HelloWorld\n/posts/hello_world\n```\n\n### Notes\n\n- The regex is used by both `compile()` validation and `match()` route matching\n- Do not include route delimiters unless the parameter is intended to match them\n- For cross-segment matching, use a wildcard parameter instead\n\n---\n\n# Custom Constraints\n\nCustom constraints are registered globally at runtime.\n\nA custom constraint must be created using `createConstraint`.\n\n## `createConstraint`\n\nCreates a custom parameter constraint implementation.\n\n### Signature\n\n```ts\ndeclare const createConstraint = ({\n  parse,\n  verify,\n  toRegExp,\n}: {\n  parse: (...args: Parameters\u003cConstraintValidation\u003e) =\u003e void;\n  verify: ConstraintValidation['verify'];\n  toRegExp: ConstraintValidation['toRegExp'];\n}) =\u003e ConstraintValidation;\n```\n\n### Methods\n\n#### `parse`\n\nImplements the runtime validation logic for the parameter value.\n\nThis method is executed when the route parameter is matched and receives:\n\n- `paramName`: parameter name\n- `value`: extracted parameter value\n- `params`: constraint configuration value\n\nThrow an error if the parameter value is invalid.\n\n#### `verify`\n\nValidates the constraint configuration itself.\n\nUse this method to ensure the constraint declaration is valid and correctly formatted before `parse` is executed.\n\nTypical use cases include:\n\n- validating constraint arguments\n- rejecting unsupported parameters\n- validating parameter formatting\n\n#### `toRegExp`\n\nReturns the regular expression pattern used to extract and match the parameter value from the route.\n\nThe returned value must be a valid regex pattern string without delimiters.\n\n### Example\n\n```ts\nimport { createConstraint } from '@cookbook/pathkit';\n\nconst slug = createConstraint({\n  parse: (paramName, value) =\u003e {\n    if (typeof value !== 'string') {\n      throw new Error(`Parameter \"${paramName}\" must be a string`);\n    }\n\n    if (!/^[a-z0-9-]+$/.test(value)) {\n      throw new Error(`Parameter \"${paramName}\" must be a valid slug`);\n    }\n  },\n\n  verify: (paramName, params) =\u003e {\n    if (params.trim().length) {\n      throw new Error(\n        `[Constraint] Constraint 'slug' declared for '${paramName}' does not accept parameters, ` +\n          `but received '${params}'.`,\n      );\n    }\n  },\n\n  toRegExp: () =\u003e '[a-z0-9-]+',\n});\n```\n\nNote: `verify` is called automatically before `parse` is executed.\n\n---\n\n## registerConstraint()\n\nRegisters or replaces a constraint.\n\n### Signature\n\n```ts\ndeclare const registerConstraint: (name: string, constraint: ConstraintValidation) =\u003e void;\n```\n\nIf a constraint with the same name already exists, it is replaced.\n\n### Example\n\n```ts\nimport { match, registerConstraint } from '@cookbook/pathkit';\n\nregisterConstraint('slug', slug);\n\nconst matcher = match('/posts/{slug:slug}');\n\nmatcher('/posts/hello-world');\n```\n\nReturns:\n\n```ts\n{\n  match: true,\n  params: {\n    slug: 'hello-world',\n  },\n}\n```\n\nInvalid values return a failed match by default:\n\n```ts\nmatcher('/posts/heiß');\n```\n\nReturns:\n\n```ts\n{\n  match: false,\n  params: null,\n}\n```\n\nUse strict mode to throw the custom constraint error:\n\n```ts\nconst strictMatcher = match('/posts/{slug:slug}', {\n  strict: true,\n});\n\nstrictMatcher('/posts/heiß');\n```\n\nThrows:\n\n```txt\nParameter \"slug\" must be a valid slug\n```\n\n---\n\n## unregisterConstraint()\n\nRemoves a runtime constraint.\n\n### Signature\n\n```ts\ndeclare const unregisterConstraint: (name: string) =\u003e void;\n```\n\n### Example\n\n```ts\nimport { unregisterConstraint } from '@cookbook/pathkit';\n\nunregisterConstraint('slug');\n```\n\n---\n\n## hasConstraint()\n\nChecks whether a constraint exists.\n\n### Signature\n\n```ts\ndeclare const hasConstraint: (name: string) =\u003e boolean;\n```\n\n### Example\n\n```ts\nimport { hasConstraint } from '@cookbook/pathkit';\n\nhasConstraint('slug');\n```\n\n---\n\n## getConstraint()\n\nReturns a registered constraint.\n\n### Signature\n\n```ts\ndeclare const getConstraint: (name: string) =\u003e ConstraintValidation | undefined;\n```\n\n### Example\n\n```ts\nimport { getConstraint } from '@cookbook/pathkit';\n\nconst constraint = getConstraint('slug');\n```\n\n---\n\n## resetConstraints()\n\nRestores the built-in constraint registry and removes runtime customizations.\n\nUseful for tests.\n\n### Signature\n\n```ts\ndeclare const resetConstraints: () =\u003e void;\n```\n\n---\n\n# TypeScript\n\n## Route Segments\n\n```ts\nimport type { RouteSegment, LiteralSegment, ParameterSegment } from '@cookbook/pathkit';\n```\n\n---\n\n## Constraints\n\n```ts\nimport type { Constraint, ConstraintValidation } from '@cookbook/pathkit';\n```\n\n---\n\n## Match Results\n\n```ts\nimport type { MatchedParam } from '@cookbook/pathkit';\n```\n\n---\n\n# Module Imports\n\n## Root Import\n\n```ts\nimport { compile, match, tokenize, validateRoute } from '@cookbook/pathkit';\n```\n\n---\n\n## Constraint Namespace\n\n```ts\nimport { constraints } from '@cookbook/pathkit';\n\nconstraints.registerConstraint(...);\n```\n\n---\n\n## Deep Imports\n\n```ts\nimport match from '@cookbook/pathkit/match';\nimport compile from '@cookbook/pathkit/compile';\n```\n\n---\n\n# Error Handling\n\nAll validation and parsing errors use standard `Error` instances with descriptive messages.\n\n## compile()\n\n`compile()` throws when required params are missing or provided params do not satisfy constraints.\n\n```txt\n[Compile] Missing required parameter: id\n```\n\n```txt\nParameter \"page\" must be one of: home, dashboard\n```\n\n## match()\n\n`match()` returns failed matches by default when a path does not match the route or does not satisfy route constraints.\n\n```ts\n{\n  match: false,\n  params: null,\n}\n```\n\nWith `strict: true`, constraint validation errors are thrown instead of being converted into failed matches.\n\n```txt\n[Constraint] Parameter \"id\" must be a number, instead got 'string'\n```\n\n## tokenize() / validateRoute()\n\nInvalid route patterns and invalid constraint declarations throw.\n\n```txt\n[Tokenize] Invalid route pattern: Unexpected token\n```\n\n```txt\n[Constraint]: Unknown constraint type: \"unknown\"\n```\n\n---\n\n# Examples\n\nSee the [`examples`](./examples) directory for complete real-world usage examples.\n\n---\n\n# Design Goals\n\n- Predictable behavior\n- Minimal abstractions\n- Runtime safety\n- Composable APIs\n- Framework independence\n- Extensibility through constraints\n- Small API surface\n\n---\n\n# License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthe-cookbook%2Fpathkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthe-cookbook%2Fpathkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthe-cookbook%2Fpathkit/lists"}