{"_id":"uri-template-matcher","_rev":"5-a3e7392c096e2f9ce3fbbf13a1301868","name":"uri-template-matcher","dist-tags":{"latest":"1.1.2"},"versions":{"1.0.0":{"name":"uri-template-matcher","version":"1.0.0","keywords":["uri","template","matcher","rfc6570","routing"],"author":"","license":"ISC","_id":"uri-template-matcher@1.0.0","maintainers":[{"name":"pablopang","email":"ricciutipaolo@gmail.com"}],"dist":{"shasum":"33a2ab6b0804a6b25645cde0cd1c0bdafb614fb1","tarball":"https://registry.npmjs.org/uri-template-matcher/-/uri-template-matcher-1.0.0.tgz","fileCount":6,"integrity":"sha512-O5Q85FcILcg6VpdTf5uOP4FV2TzwwyQZna1qVRWpIXjRljqb8Apxo856aQ2ip6/GcpNoJ/sXY/DrwVX9B3EQdw==","signatures":[{"sig":"MEYCIQCTi31Y2zW+jDlw4CpmxLldz9Bn2lIPYZBi6xDs3QWKSQIhAPel7xXhUDyuoIvLsNyuq3PVJ5ih+coj5VPlwjdfto/8","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":23076},"main":"./src/index.js","type":"module","types":"./src/index.d.ts","exports":{".":{"types":"./src/index.d.ts","import":"./src/index.js"}},"scripts":{"lint":"eslint src test","test":"vitest","format":"prettier --write src test","lint:fix":"eslint src test --fix","typecheck":"tsc --noEmit","format:check":"prettier --check src test","test:coverage":"vitest --coverage"},"_npmUser":{"name":"pablopang","actor":{"name":"pablopang","type":"user","email":"ricciutipaolo@gmail.com"},"email":"ricciutipaolo@gmail.com"},"_npmVersion":"11.4.2","description":"A lightweight URI template matcher based on RFC 6570","directories":{},"_nodeVersion":"24.3.0","_hasShrinkwrap":false,"packageManager":"pnpm@10.12.4","devDependencies":{"eslint":"^9.30.1","vitest":"^3.2.4","publint":"^0.3.12","prettier":"^3.6.2","@eslint/js":"^9.30.1","typescript":"^5.8.3","@types/node":"^24.0.12","eslint-config-prettier":"^10.1.5","eslint-plugin-prettier":"^5.5.1","@typescript-eslint/parser":"^8.36.0","@typescript-eslint/eslint-plugin":"^8.36.0"},"_npmOperationalInternal":{"tmp":"tmp/uri-template-matcher_1.0.0_1752092225385_0.2107432757737231","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"uri-template-matcher","version":"1.0.1","keywords":["uri","template","matcher","rfc6570","routing"],"author":"","license":"ISC","_id":"uri-template-matcher@1.0.1","maintainers":[{"name":"pablopang","email":"ricciutipaolo@gmail.com"}],"dist":{"shasum":"d978579e5bfbc2ccce6ec6527fb4d08263cd21c1","tarball":"https://registry.npmjs.org/uri-template-matcher/-/uri-template-matcher-1.0.1.tgz","fileCount":8,"integrity":"sha512-Ll4rcl37gBjekHEWP/Y5tGQ6a4o54Bu6iTSnllC/ap85d58mTScDJsr3MI9I/zOj0lCYtQ2AsUTeC4BCX8qR3w==","signatures":[{"sig":"MEUCIBut4UVc+wne5qF2E5tcHM7M2y68JITQRCSXQI1py2YxAiEAiW1rqnmjSCHPKL/DTy68mwhvtUnaxy3jG1+BoN8grCQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":31642},"main":"./src/index.js","type":"module","_from":"file:uri-template-matcher-1.0.1.tgz","types":"./src/index.d.ts","exports":{".":{"types":"./src/index.d.ts","import":"./src/index.js"}},"scripts":{"lint":"eslint src test","test":"vitest","format":"prettier --write src test","release":"changeset publish","lint:fix":"eslint src test --fix","typecheck":"tsc --noEmit","format:check":"prettier --check src test","test:coverage":"vitest --coverage"},"_npmUser":{"name":"pablopang","actor":{"name":"pablopang","type":"user","email":"ricciutipaolo@gmail.com"},"email":"ricciutipaolo@gmail.com"},"_resolved":"/tmp/e4e94a9ae719d144d71cabd37618001e/uri-template-matcher-1.0.1.tgz","_integrity":"sha512-Ll4rcl37gBjekHEWP/Y5tGQ6a4o54Bu6iTSnllC/ap85d58mTScDJsr3MI9I/zOj0lCYtQ2AsUTeC4BCX8qR3w==","_npmVersion":"10.9.2","description":"A lightweight URI template matcher based on RFC 6570","directories":{},"_nodeVersion":"22.17.0","dependencies":{"@changesets/cli":"^2.29.5"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^9.30.1","vitest":"^3.2.4","publint":"^0.3.12","prettier":"^3.6.2","@eslint/js":"^9.30.1","typescript":"^5.8.3","@types/node":"^24.0.12","eslint-config-prettier":"^10.1.5","eslint-plugin-prettier":"^5.5.1","@typescript-eslint/parser":"^8.36.0","@typescript-eslint/eslint-plugin":"^8.36.0"},"_npmOperationalInternal":{"tmp":"tmp/uri-template-matcher_1.0.1_1752128631660_0.3038206163140429","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"uri-template-matcher","version":"1.1.0","keywords":["uri","template","matcher","rfc6570","routing"],"author":"","license":"ISC","_id":"uri-template-matcher@1.1.0","maintainers":[{"name":"pablopang","email":"ricciutipaolo@gmail.com"}],"dist":{"shasum":"46ac77202ebfda2b335f1b1c5e595f9220f99ee4","tarball":"https://registry.npmjs.org/uri-template-matcher/-/uri-template-matcher-1.1.0.tgz","fileCount":9,"integrity":"sha512-L9A6Ugm0Yyu/rxAdqJYsWs7x766nQc5EOEQCY2Zc5yoLvXe7WZBXwufJVedp+gXVPFZ4cwjxBF65luJVyQnoOQ==","signatures":[{"sig":"MEUCIQCBmzWQRxtRtRPhtU3RORo5LWDzfkH385JEixYJjk7IngIgC1w91rjXiq2tAEUbCivmyJvGTMuBKAlFHvx+ie+SSAg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":49301},"main":"./src/index.js","type":"module","_from":"file:uri-template-matcher-1.1.0.tgz","types":"./src/index.d.ts","exports":{".":{"types":"./src/index.d.ts","import":"./src/index.js"}},"scripts":{"lint":"eslint src test","test":"vitest","check":"pnpm typecheck && pnpm lint && pnpm format:check && npx publint","format":"prettier --write src test","release":"changeset publish","lint:fix":"eslint src test --fix","typecheck":"tsc --noEmit","format:check":"prettier --check src test","test:coverage":"vitest --coverage"},"_npmUser":{"name":"pablopang","actor":{"name":"pablopang","type":"user","email":"ricciutipaolo@gmail.com"},"email":"ricciutipaolo@gmail.com"},"_resolved":"/tmp/12c55babf4f73dc544c8906099dd0180/uri-template-matcher-1.1.0.tgz","_integrity":"sha512-L9A6Ugm0Yyu/rxAdqJYsWs7x766nQc5EOEQCY2Zc5yoLvXe7WZBXwufJVedp+gXVPFZ4cwjxBF65luJVyQnoOQ==","_npmVersion":"10.9.2","description":"A lightweight URI template matcher based on RFC 6570","directories":{},"_nodeVersion":"22.17.0","dependencies":{"@changesets/cli":"^2.29.5"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^9.30.1","vitest":"^3.2.4","publint":"^0.3.12","prettier":"^3.6.2","@eslint/js":"^9.30.1","typescript":"^5.8.3","@types/node":"^24.0.12","eslint-config-prettier":"^10.1.5","eslint-plugin-prettier":"^5.5.1","@typescript-eslint/parser":"^8.36.0","@typescript-eslint/eslint-plugin":"^8.36.0"},"_npmOperationalInternal":{"tmp":"tmp/uri-template-matcher_1.1.0_1752137953040_0.3541591256746366","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"uri-template-matcher","version":"1.1.1","keywords":["uri","template","matcher","rfc6570","routing"],"author":"","license":"ISC","_id":"uri-template-matcher@1.1.1","maintainers":[{"name":"pablopang","email":"ricciutipaolo@gmail.com"}],"dist":{"shasum":"31270e812b63cd88aabf5fc47daa5bd325de0ea1","tarball":"https://registry.npmjs.org/uri-template-matcher/-/uri-template-matcher-1.1.1.tgz","fileCount":9,"integrity":"sha512-ooMjzxaqlquLZZU0Y+Ol+RAp5xav3oJ3qc3gO585QFmB9iX88ip8pflaCKKtkwPd40ro2noB8yQG2OhFddmddg==","signatures":[{"sig":"MEUCICI9LRiRg1EfexAdVqGbGrJ5XJG3QWrZU1k1BtaIxMqcAiEAiGlr/u1cwEIgn4ShAXq84+MmftIXZcgI8zzHrn5kehc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":49277},"main":"./src/index.js","type":"module","_from":"file:uri-template-matcher-1.1.1.tgz","types":"./src/index.d.ts","exports":{".":{"types":"./src/index.d.ts","import":"./src/index.js"}},"scripts":{"lint":"eslint src test","test":"vitest","check":"pnpm typecheck && pnpm lint && pnpm format:check && npx publint","format":"prettier --write src test","release":"changeset publish","lint:fix":"eslint src test --fix","typecheck":"tsc --noEmit","format:check":"prettier --check src test","test:coverage":"vitest --coverage"},"_npmUser":{"name":"pablopang","email":"ricciutipaolo@gmail.com"},"_resolved":"/tmp/c09805b15f8671353daeafdd05cd7473/uri-template-matcher-1.1.1.tgz","_integrity":"sha512-ooMjzxaqlquLZZU0Y+Ol+RAp5xav3oJ3qc3gO585QFmB9iX88ip8pflaCKKtkwPd40ro2noB8yQG2OhFddmddg==","_npmVersion":"10.9.2","description":"A lightweight URI template matcher based on RFC 6570","directories":{},"_nodeVersion":"22.17.1","_hasShrinkwrap":false,"devDependencies":{"eslint":"^9.30.1","vitest":"^3.2.4","publint":"^0.3.12","prettier":"^3.6.2","@eslint/js":"^9.30.1","typescript":"^5.8.3","@types/node":"^24.0.12","@changesets/cli":"^2.29.5","eslint-config-prettier":"^10.1.5","eslint-plugin-prettier":"^5.5.1","@typescript-eslint/parser":"^8.36.0","@typescript-eslint/eslint-plugin":"^8.36.0"},"_npmOperationalInternal":{"tmp":"tmp/uri-template-matcher_1.1.1_1754150100253_0.6831525776825371","host":"s3://npm-registry-packages-npm-production"}},"1.1.2":{"name":"uri-template-matcher","version":"1.1.2","description":"A lightweight URI template matcher based on RFC 6570","repository":{"type":"git","url":"git+https://github.com/paoloricciuti/uri-template-matcher.git"},"type":"module","main":"./src/index.js","types":"./src/index.d.ts","exports":{".":{"types":"./src/index.d.ts","import":"./src/index.js","default":"./src/index.js"}},"keywords":["uri","template","matcher","rfc6570","routing"],"author":"","license":"ISC","devDependencies":{"@changesets/cli":"^2.29.5","@eslint/js":"^9.30.1","@types/node":"^24.0.12","@typescript-eslint/eslint-plugin":"^8.36.0","@typescript-eslint/parser":"^8.36.0","eslint":"^9.30.1","eslint-config-prettier":"^10.1.5","eslint-plugin-prettier":"^5.5.1","prettier":"^3.6.2","publint":"^0.3.12","typescript":"^5.8.3","vitest":"^3.2.4"},"scripts":{"test":"vitest","test:coverage":"vitest --coverage","check":"pnpm typecheck && pnpm lint && pnpm format:check && npx publint","typecheck":"tsc --noEmit","lint":"eslint src test","lint:fix":"eslint src test --fix","format":"prettier --write src test","format:check":"prettier --check src test","release":"changeset publish"},"_id":"uri-template-matcher@1.1.2","bugs":{"url":"https://github.com/paoloricciuti/uri-template-matcher/issues"},"homepage":"https://github.com/paoloricciuti/uri-template-matcher#readme","_integrity":"sha512-uZc1h12jdO3m/R77SfTEOuo6VbMhgWznaawKpBjRGSJb7i91x5PgI37NQJtG+Cerxkk0yr1pylBY2qG1kQ+aEQ==","_resolved":"/tmp/f62038be50dd3582dc4e0b7358f91e16/uri-template-matcher-1.1.2.tgz","_from":"file:uri-template-matcher-1.1.2.tgz","_nodeVersion":"22.20.0","_npmVersion":"10.9.3","dist":{"integrity":"sha512-uZc1h12jdO3m/R77SfTEOuo6VbMhgWznaawKpBjRGSJb7i91x5PgI37NQJtG+Cerxkk0yr1pylBY2qG1kQ+aEQ==","shasum":"fccf60653828f2c3d21a0ebdbf9aa2b7daaf16bd","tarball":"https://registry.npmjs.org/uri-template-matcher/-/uri-template-matcher-1.1.2.tgz","fileCount":9,"unpackedSize":49429,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQD2gkLFsgzuTfkhNi4T8+DH/KfaqQUazLBgu6CcdBNF/gIgGqT9B1E4LLJXHHz37RvzVlewQ5bDvvqIgA8icMytSbw="}]},"_npmUser":{"name":"pablopang","email":"ricciutipaolo@gmail.com"},"directories":{},"maintainers":[{"name":"pablopang","email":"ricciutipaolo@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/uri-template-matcher_1.1.2_1761767965649_0.22009020094955645"},"_hasShrinkwrap":false}},"time":{"created":"2025-07-09T20:17:05.384Z","modified":"2025-10-29T19:59:26.047Z","1.0.0":"2025-07-09T20:17:05.545Z","1.0.1":"2025-07-10T06:23:51.848Z","1.1.0":"2025-07-10T08:59:13.197Z","1.1.1":"2025-08-02T15:55:00.445Z","1.1.2":"2025-10-29T19:59:25.851Z"},"license":"ISC","keywords":["uri","template","matcher","rfc6570","routing"],"description":"A lightweight URI template matcher based on RFC 6570","maintainers":[{"name":"pablopang","email":"ricciutipaolo@gmail.com"}],"readme":"# URI Template Matcher\n\nA lightweight URI template library based on RFC 6570 that supports both matching URIs against templates to extract parameters and expanding templates with variables to generate URIs.\n\n## Installation\n\n```bash\nnpm install uri-template-matcher\n```\n```bash\npnpm add uri-template-matcher\n```\n\n## Usage\n\n### Basic Usage\n\n```javascript\nimport { UriTemplateMatcher } from 'uri-template-matcher';\n\nconst matcher = new UriTemplateMatcher();\n\n// Register URI templates\nmatcher.add('/users/{id}');\nmatcher.add('/posts/{postId}/comments/{commentId}');\n\n// Match URIs and extract parameters\nconst result = matcher.match('/users/123');\nconsole.log(result);\n// Output: { template: '/users/{id}', params: { id: '123' } }\n\nconst result2 = matcher.match('/posts/456/comments/789');\nconsole.log(result2);\n// Output: { \n//   template: '/posts/{postId}/comments/{commentId}', \n//   params: { postId: '456', commentId: '789' } \n// }\n```\n\n### Working with Multiple Templates\n\n```javascript\nconst matcher = new UriTemplateMatcher();\n\n// Add multiple templates\nmatcher.add('/api/users/{id}');\nmatcher.add('/api/posts/{id}');\nmatcher.add('/api/health');\n\n// The matcher returns the first matching template\nconst userMatch = matcher.match('/api/users/123');\nconsole.log(userMatch);\n// Output: { template: '/api/users/{id}', params: { id: '123' } }\n\nconst healthMatch = matcher.match('/api/health');\nconsole.log(healthMatch);\n// Output: { template: '/api/health', params: {} }\n\n// No match returns null\nconst noMatch = matcher.match('/api/unknown');\nconsole.log(noMatch); // Output: null\n```\n\n### URL Encoding Support\n\nThe matcher automatically handles URL encoding and decoding:\n\n```javascript\nconst matcher = new UriTemplateMatcher();\nmatcher.add('/search/{query}');\n\nconst result = matcher.match('/search/hello%20world');\nconsole.log(result);\n// Output: { template: '/search/{query}', params: { query: 'hello world' } }\n```\n\n### RFC 6570 Level 2 - Reserved String Expansion\n\n```javascript\nconst matcher = new UriTemplateMatcher();\n\n// Reserved expansion with '+' operator\nmatcher.add('/files/{+path}');\nconst result = matcher.match('/files/docs/readme.txt');\nconsole.log(result);\n// Output: { template: '/files/{+path}', params: { path: 'docs/readme.txt' } }\n\n// Fragment expansion with '#' operator\nmatcher.add('/page#{section}');\nconst fragmentResult = matcher.match('/page#introduction');\nconsole.log(fragmentResult);\n// Output: { template: '/page#{section}', params: { section: 'introduction' } }\n```\n\n### RFC 6570 Level 3 - Advanced Operators\n\n```javascript\nconst matcher = new UriTemplateMatcher();\n\n// Dot notation\nmatcher.add('/files{.format}');\nconsole.log(matcher.match('/files.json'));\n// Output: { template: '/files{.format}', params: { format: 'json' } }\n\n// Path segments\nmatcher.add('/api{/version}/users');\nconsole.log(matcher.match('/api/v1/users'));\n// Output: { template: '/api{/version}/users', params: { version: 'v1' } }\n\n// Query parameters\nmatcher.add('/search{?q}');\nconsole.log(matcher.match('/search?q=test'));\n// Output: { template: '/search{?q}', params: { q: 'test' } }\n\n// Multiple query parameters\nmatcher.add('/search{?q,limit}');\nconsole.log(matcher.match('/search?q=test&limit=10'));\n// Output: { template: '/search{?q,limit}', params: { q: 'test', limit: '10' } }\n\n// Query continuation\nmatcher.add('/search?type=user{&q}');\nconsole.log(matcher.match('/search?type=user&q=john'));\n// Output: { template: '/search?type=user{&q}', params: { q: 'john' } }\n\n// Semicolon parameters\nmatcher.add('/api{;version}');\nconsole.log(matcher.match('/api;version=v1'));\n// Output: { template: '/api{;version}', params: { version: 'v1' } }\n```\n\n### RFC 6570 Level 4 - Value Modifiers\n\n```javascript\nconst matcher = new UriTemplateMatcher();\n\n// Prefix modifiers\nmatcher.add('/api/{name:3}');\nconsole.log(matcher.match('/api/toolong'));\n// Output: { template: '/api/{name:3}', params: { name: 'too' } }\n\n// Explode modifiers with lists\nmatcher.add('/tags{.tags*}');\nconsole.log(matcher.match('/tags.red.green.blue'));\n// Output: { template: '/tags{.tags*}', params: { tags: ['red', 'green', 'blue'] } }\n\n// Explode modifiers with query parameters\nmatcher.add('/search{?filters*}');\nconsole.log(matcher.match('/search?color=red&size=large'));\n// Output: { template: '/search{?filters*}', params: { filters: ['color=red', 'size=large'] } }\n```\n\n### Managing Templates\n\n```javascript\nconst matcher = new UriTemplateMatcher();\n\n// Add templates\nmatcher.add('/users/{id}');\nmatcher.add('/posts/{id}');\n\n// Get all registered templates\nconsole.log(matcher.all());\n// Output: ['/users/{id}', '/posts/{id}']\n\n// Clear all templates\nmatcher.clear();\nconsole.log(matcher.all());\n// Output: []\n```\n\n### Real-World Examples\n\n#### REST API Routing\n\n```javascript\nconst matcher = new UriTemplateMatcher();\n\n// Register API endpoints\nmatcher.add('/api/v1/users/{id}');\nmatcher.add('/api/v1/users/{id}/posts');\nmatcher.add('/api/v1/posts/{postId}/comments/{commentId}');\n\n// Route incoming requests\nfunction routeRequest(path) {\n  const match = matcher.match(path);\n  \n  if (!match) {\n    return { status: 404, message: 'Not Found' };\n  }\n  \n  return {\n    template: match.template,\n    params: match.params,\n    status: 200\n  };\n}\n\nconsole.log(routeRequest('/api/v1/users/123'));\n// Output: { template: '/api/v1/users/{id}', params: { id: '123' }, status: 200 }\n```\n\n#### GitHub-style URLs\n\n```javascript\nconst matcher = new UriTemplateMatcher();\nmatcher.add('/repos/{owner}/{repo}/issues/{issue_number}');\n\nconst match = matcher.match('/repos/octocat/Hello-World/issues/1');\nconsole.log(match);\n// Output: {\n//   template: '/repos/{owner}/{repo}/issues/{issue_number}',\n//   params: {\n//     owner: 'octocat',\n//     repo: 'Hello-World',\n//     issue_number: '1'\n//   }\n// }\n```\n\n#### File System Paths\n\n```javascript\nconst matcher = new UriTemplateMatcher();\nmatcher.add('file:///{+path}');\n\nconst match = matcher.match('file:///home/user/documents/file.txt');\nconsole.log(match);\n// Output: {\n//   template: 'file:///{+path}',\n//   params: { path: 'home/user/documents/file.txt' }\n// }\n```\n\n## URI Template Expansion\n\nIn addition to matching URIs against templates, this library also supports expanding URI templates with variables according to RFC 6570.\n\n### Basic Expansion\n\n```javascript\nimport { UriTemplateExpander } from 'uri-template-matcher';\n\nconst expander = new UriTemplateExpander('/users/{id}');\nconst uri = expander.expand({ id: '123' });\nconsole.log(uri);\n// Output: '/users/123'\n```\n\n### Expansion with Multiple Variables\n\n```javascript\nconst expander = new UriTemplateExpander('/posts/{postId}/comments/{commentId}');\nconst uri = expander.expand({ postId: '456', commentId: '789' });\nconsole.log(uri);\n// Output: '/posts/456/comments/789'\n```\n\n### Reserved String Expansion\n\n```javascript\nconst expander = new UriTemplateExpander('/files/{+path}');\nconst uri = expander.expand({ path: 'docs/readme.txt' });\nconsole.log(uri);\n// Output: '/files/docs/readme.txt'\n```\n\n### Fragment Expansion\n\n```javascript\nconst expander = new UriTemplateExpander('/page#{section}');\nconst uri = expander.expand({ section: 'introduction' });\nconsole.log(uri);\n// Output: '/page#introduction'\n```\n\n### Query Parameter Expansion\n\n```javascript\n// Single query parameter\nconst expander1 = new UriTemplateExpander('/search{?q}');\nconsole.log(expander1.expand({ q: 'test' }));\n// Output: '/search?q=test'\n\n// Multiple query parameters\nconst expander2 = new UriTemplateExpander('/search{?q,limit}');\nconsole.log(expander2.expand({ q: 'test', limit: '10' }));\n// Output: '/search?q=test&limit=10'\n\n// Query continuation\nconst expander3 = new UriTemplateExpander('/search?type=user{&q}');\nconsole.log(expander3.expand({ q: 'john' }));\n// Output: '/search?type=user&q=john'\n```\n\n### Path and Dot Expansion\n\n```javascript\n// Dot notation\nconst expander1 = new UriTemplateExpander('/files{.format}');\nconsole.log(expander1.expand({ format: 'json' }));\n// Output: '/files.json'\n\n// Path segments\nconst expander2 = new UriTemplateExpander('/api{/version}/users');\nconsole.log(expander2.expand({ version: 'v1' }));\n// Output: '/api/v1/users'\n```\n\n### Value Modifiers\n\n```javascript\n// Prefix modifiers\nconst expander1 = new UriTemplateExpander('/api/{name:3}');\nconsole.log(expander1.expand({ name: 'toolong' }));\n// Output: '/api/too'\n\n// Explode modifiers with arrays\nconst expander2 = new UriTemplateExpander('/tags{.tags*}');\nconsole.log(expander2.expand({ tags: ['red', 'green', 'blue'] }));\n// Output: '/tags.red.green.blue'\n\n// Explode modifiers with objects\nconst expander3 = new UriTemplateExpander('/search{?filters*}');\nconsole.log(expander3.expand({ filters: { color: 'red', size: 'large' } }));\n// Output: '/search?color=red&size=large'\n```\n\n### Working with Complex Variables\n\n```javascript\nconst expander = new UriTemplateExpander('/search{?q,filters*}');\nconst uri = expander.expand({\n  q: 'uri templates',\n  filters: {\n    category: 'technology',\n    lang: 'en'\n  }\n});\nconsole.log(uri);\n// Output: '/search?q=uri%20templates&category=technology&lang=en'\n```\n\n### Undefined Variables\n\nVariables that are undefined, null, or empty arrays/objects are ignored:\n\n```javascript\nconst expander = new UriTemplateExpander('/search{?q,limit,offset}');\nconst uri = expander.expand({ q: 'test' }); // limit and offset are undefined\nconsole.log(uri);\n// Output: '/search?q=test'\n```\n\n### Using the Expand Function Directly\n\nYou can also use the expand function directly without creating an instance:\n\n```javascript\nimport { expand_template } from 'uri-template-matcher';\n\nconst uri = expand_template('/users/{id}', { id: '123' });\nconsole.log(uri);\n// Output: '/users/123'\n```\n\n## API Reference\n\n### Class: UriTemplateMatcher\n\n#### Constructor\n\n```javascript\nnew UriTemplateMatcher()\n```\n\nCreates a new UriTemplateMatcher instance.\n\n#### Methods\n\n##### `add(template: string): void`\n\nAdds a URI template to the matcher.\n\n- `template` - The URI template string to add\n- Throws `Error` if template is invalid\n\n##### `match(uri: string): MatchResult | null`\n\nMatches a URI against all registered templates.\n\n- `uri` - The URI to match\n- Returns `MatchResult` if a match is found, `null` otherwise\n- Throws `Error` if URI is invalid\n\n##### `clear(): void`\n\nClears all registered templates.\n\n##### `all(): string[]`\n\nReturns an array of all registered template strings.\n\n### Class: UriTemplateExpander\n\n#### Constructor\n\n```javascript\nnew UriTemplateExpander(template: string)\n```\n\nCreates a new UriTemplateExpander instance.\n\n- `template` - The URI template string to use for expansion\n- Throws `Error` if template is invalid\n\n#### Methods\n\n##### `expand(variables: Record<string, any>): string`\n\nExpands the template with the given variables.\n\n- `variables` - Object containing variable names and values\n- Returns the expanded URI string\n- Throws `Error` if expansion fails\n\n### Functions\n\n##### `expand_template(template: string, variables: Record<string, any>): string`\n\nExpands a URI template with given variables.\n\n- `template` - The URI template string to expand\n- `variables` - Object containing variable names and values\n- Returns the expanded URI string\n- Throws `Error` if template is invalid or expansion fails\n\n### Types\n\n#### MatchResult\n\n```typescript\ninterface MatchResult {\n  template: string;                    // The matched template\n  params: Record<string, string | string[]>; // Extracted parameters\n}\n```\n\n## RFC 6570 Compliance\n\nThis library implements URI Template matching and expansion based on RFC 6570 with support for:\n\n- **Level 1**: Simple string expansion\n- **Level 2**: Reserved string expansion (`+`) and fragment expansion (`#`)\n- **Level 3**: Multiple variable expansion with operators (`.`, `/`, `;`, `?`, `&`)\n- **Level 4**: Value modifiers including prefix (`:n`) and explode (`*`) modifiers\n\n## License\n\nMIT\n","readmeFilename":"README.md","homepage":"https://github.com/paoloricciuti/uri-template-matcher#readme","repository":{"type":"git","url":"git+https://github.com/paoloricciuti/uri-template-matcher.git"},"bugs":{"url":"https://github.com/paoloricciuti/uri-template-matcher/issues"}}