{"_id":"@alevettih/typed-route-template","_rev":"4-1bfad7b08e547c1f93752a8f032ea0fc","name":"@alevettih/typed-route-template","dist-tags":{"latest":"0.2.0"},"versions":{"0.0.0":{"name":"@alevettih/typed-route-template","version":"0.0.0","keywords":["typescript","routing","urls"],"author":{"name":"Alexandr Tikhonenko","email":"alevettih@ya.ru"},"license":"MIT","_id":"@alevettih/typed-route-template@0.0.0","maintainers":[{"name":"alevet","email":"alevettih@ya.ru"}],"homepage":"https://github.com/Alevettih/typed-route-template","bugs":{"url":"https://github.com/Alevettih/typed-route-template/issues"},"dist":{"shasum":"a137bba9035441b072b02a2d9ff221ef94d08599","tarball":"https://registry.npmjs.org/@alevettih/typed-route-template/-/typed-route-template-0.0.0.tgz","fileCount":20,"integrity":"sha512-qKt49OiDVQ0FAK2J57xI25HVVzMQPWZqaAoK01srIsXEcP7dIcQ/UkAg1jHXSX/ov6iNDLck/PiSATYrU6k8nw==","signatures":[{"sig":"MEQCIFiRBqPCgZwiEZ0xxDf4ieEgIYRyWOXbhJqWa1uVvbtyAiBSbdkXJZ6y9sjEs/gNe6Ilj1OBYMdjSAMkTf2Yneu+PQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":10506},"module":"dist/public-api.js","exports":{".":{"types":"./dist/public-api.d.ts","default":"./dist/public-api.js"},"./package.json":{"default":"./package.json"}},"gitHead":"8fc8f61c219fad0a7c97a617da190d7baf2e6578","scripts":{"lint":"eslint .","test":"jest","format":"prettier --write \"**/*.{ts,html,scss,css,json,md}\"","prepare":"husky","lint:fix":"eslint . --fix","build:dev":"tsc --project src/tsconfig.lib.json","build:prod":"tsc --project src/tsconfig.lib.prod.json","format:check":"prettier --check \"**/*.{ts,html,scss,css,json,md}\""},"typings":"dist/public-api.d.ts","_npmUser":{"name":"alevet","email":"alevettih@ya.ru"},"repository":{"url":"git+https://github.com/Alevettih/typed-route-template.git","type":"github"},"_npmVersion":"11.6.2","description":"A tiny, type-safe helper for building and reusing parameterised URL/route templates in TypeScript. It keeps your runtime API simple while leveraging modern template literal types to prevent mismatched parameters at compile time.","directories":{},"lint-staged":{"*.{ts,html}":["eslint --fix","prettier --write"],"*.{json,md,scss,css}":["prettier --write"]},"_nodeVersion":"24.11.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^30.0.0","husky":"^9.1.0","tslib":"^2.3.0","eslint":"^8.57.0","ts-jest":"29.4.5","prettier":"^3.3.0","typescript":"~5.9.2","@types/jest":"^30.0.0","lint-staged":"^15.2.0","eslint-plugin-import":"^2.31.0","eslint-config-prettier":"^9.1.0","@typescript-eslint/parser":"^8.0.0","eslint-plugin-prefer-arrow":"^1.2.3","@typescript-eslint/eslint-plugin":"^8.0.0"},"_npmOperationalInternal":{"tmp":"tmp/typed-route-template_0.0.0_1762868598760_0.09188662871184383","host":"s3://npm-registry-packages-npm-production"}},"0.0.1":{"name":"@alevettih/typed-route-template","version":"0.0.1","keywords":["typescript","routing","urls"],"author":{"name":"Alexandr Tikhonenko","email":"alevettih@ya.ru"},"license":"MIT","_id":"@alevettih/typed-route-template@0.0.1","maintainers":[{"name":"alevet","email":"alevettih@ya.ru"}],"homepage":"https://github.com/Alevettih/typed-route-template","bugs":{"url":"https://github.com/Alevettih/typed-route-template/issues"},"dist":{"shasum":"1c93b337b3938c5b98ace306b1eb88f4be2fb82f","tarball":"https://registry.npmjs.org/@alevettih/typed-route-template/-/typed-route-template-0.0.1.tgz","fileCount":19,"integrity":"sha512-UgHC4v4ofCJzgAOk2ozYOW5CrfMrx6/XMnFLgCnvodguVnipaRhSEyeNnNiKHXzjL53ysbHdtRR2SSZ7+35MuQ==","signatures":[{"sig":"MEUCIQCldYOB4KLVYl3Zhgzy+PEacm5IbZ3uzbhY+seACqFwLgIgVFHAIa08F2fjNgzQOcZTgpm9y6N/0yTdTuen11vJ9Q4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":10566},"module":"dist/public-api.js","exports":{".":{"types":"./dist/public-api.d.ts","default":"./dist/public-api.js"},"./package.json":{"default":"./package.json"}},"gitHead":"d5e15ee945000ca07b428c71f1e77a4b3fecbc2f","scripts":{"lint":"eslint .","test":"jest","format":"prettier --write \"**/*.{ts,html,scss,css,json,md}\"","prepare":"husky","lint:fix":"eslint . --fix","build:dev":"tsc --project src/tsconfig.lib.json","build:prod":"tsc --project src/tsconfig.lib.prod.json","format:check":"prettier --check \"**/*.{ts,html,scss,css,json,md}\""},"typings":"dist/public-api.d.ts","_npmUser":{"name":"alevet","email":"alevettih@ya.ru"},"repository":{"url":"git+https://github.com/Alevettih/typed-route-template.git","type":"github"},"_npmVersion":"11.6.1","description":"A tiny, type-safe helper for building and reusing parameterised URL/route templates in TypeScript. It keeps your runtime API simple while leveraging modern template literal types to prevent mismatched parameters at compile time.","directories":{},"lint-staged":{"*.{ts,html}":["eslint --fix","prettier --write"],"*.{json,md,scss,css}":["prettier --write"]},"_nodeVersion":"24.11.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^30.0.0","husky":"^9.1.0","tslib":"^2.3.0","eslint":"^8.57.0","ts-jest":"29.4.5","prettier":"^3.3.0","typescript":"~5.9.2","@types/jest":"^30.0.0","lint-staged":"^15.2.0","eslint-plugin-import":"^2.31.0","eslint-config-prettier":"^9.1.0","@typescript-eslint/parser":"^8.0.0","eslint-plugin-prefer-arrow":"^1.2.3","@typescript-eslint/eslint-plugin":"^8.0.0"},"_npmOperationalInternal":{"tmp":"tmp/typed-route-template_0.0.1_1762869025288_0.8590975454132588","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"name":"@alevettih/typed-route-template","version":"0.1.0","keywords":["typescript","routing","urls"],"author":{"name":"Alexandr Tikhonenko","email":"alevettih@ya.ru"},"license":"MIT","_id":"@alevettih/typed-route-template@0.1.0","maintainers":[{"name":"alevet","email":"alevettih@ya.ru"}],"homepage":"https://github.com/Alevettih/typed-route-template","bugs":{"url":"https://github.com/Alevettih/typed-route-template/issues"},"dist":{"shasum":"b625610ccdbbb26566cad063333966dc255cc13e","tarball":"https://registry.npmjs.org/@alevettih/typed-route-template/-/typed-route-template-0.1.0.tgz","fileCount":19,"integrity":"sha512-Mnzw+vrqX1PUVJQRsaAunTAUy8TdgcdOhpl84zIOh+A1AUAVIA5WlxtDuk2b+Lfl9VN/X8oQG+IJ5VtBXrrMeA==","signatures":[{"sig":"MEUCIA2VFb8NX6ULSqIQBrl1iOfpiiu+DG4rfEXqn22EdrP6AiEAwcLh4Awfti8OsGXk3YQYTv2U09U/BZE876XpQE9bqyI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":11036},"module":"dist/public-api.js","exports":{".":{"types":"./dist/public-api.d.ts","default":"./dist/public-api.js"},"./package.json":{"default":"./package.json"}},"gitHead":"55c26e6a9aef13504863dd3698e13b8e714d99dc","scripts":{"lint":"eslint .","test":"vitest run --typecheck.tsconfig src/tsconfig.spec.ts","build":"tsc --project src/tsconfig.lib.json","format":"prettier --write \"**/*.{ts,html,scss,css,json,md}\"","prepare":"husky","lint:fix":"eslint . --fix","format:check":"prettier --check \"**/*.{ts,html,scss,css,json,md}\""},"typings":"dist/public-api.d.ts","_npmUser":{"name":"alevet","email":"alevettih@ya.ru"},"repository":{"url":"git+https://github.com/Alevettih/typed-route-template.git","type":"github"},"_npmVersion":"11.6.2","description":"A tiny, type-safe helper for building and reusing parameterised URL/route templates in TypeScript. It keeps your runtime API simple while leveraging modern template literal types to prevent mismatched parameters at compile time.","directories":{},"lint-staged":{"*.{ts,html}":["eslint --fix","prettier --write"],"*.{json,md,scss,css}":["prettier --write"]},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"husky":"^9.1.0","tslib":"^2.3.0","eslint":"^8.57.0","vitest":"^4.0.13","prettier":"^3.3.0","typescript":"~5.9.2","lint-staged":"^15.2.0","eslint-plugin-import":"^2.31.0","eslint-config-prettier":"^9.1.0","@typescript-eslint/parser":"^8.0.0","eslint-plugin-prefer-arrow":"^1.2.3","@typescript-eslint/eslint-plugin":"^8.0.0"},"_npmOperationalInternal":{"tmp":"tmp/typed-route-template_0.1.0_1771531963780_0.03004000532198048","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@alevettih/typed-route-template","description":"A tiny, type-safe helper for building and reusing parameterised URL/route templates in TypeScript. It keeps your runtime API simple while leveraging modern template literal types to prevent mismatched parameters at compile time.","version":"0.2.0","homepage":"https://github.com/Alevettih/typed-route-template","author":{"name":"Alexandr Tikhonenko","email":"alevettih@ya.ru"},"scripts":{"build":"tsc --project src/tsconfig.lib.json","test":"vitest run --typecheck.tsconfig src/tsconfig.spec.ts","lint":"eslint .","lint:fix":"eslint . --fix","format":"prettier --write \"**/*.{ts,html,scss,css,json,md}\"","format:check":"prettier --check \"**/*.{ts,html,scss,css,json,md}\"","prepare":"husky"},"devDependencies":{"@typescript-eslint/eslint-plugin":"^8.0.0","@typescript-eslint/parser":"^8.0.0","eslint":"^8.57.0","eslint-config-prettier":"^9.1.0","eslint-plugin-import":"^2.31.0","eslint-plugin-prefer-arrow":"^1.2.3","husky":"^9.1.0","lint-staged":"^15.2.0","prettier":"^3.3.0","tslib":"^2.3.0","typescript":"~5.9.2","vitest":"^4.0.13"},"lint-staged":{"*.{ts,html}":["eslint --fix","prettier --write"],"*.{json,md,scss,css}":["prettier --write"]},"license":"MIT","keywords":["typescript","routing","urls"],"repository":{"type":"github","url":"git+https://github.com/Alevettih/typed-route-template.git"},"bugs":{"url":"https://github.com/Alevettih/typed-route-template/issues"},"module":"dist/public-api.js","typings":"dist/public-api.d.ts","exports":{"./package.json":{"default":"./package.json"},".":{"types":"./dist/public-api.d.ts","default":"./dist/public-api.js"}},"gitHead":"feb0304ad5e89460aca7ddcb46b78da44618579a","_id":"@alevettih/typed-route-template@0.2.0","_nodeVersion":"24.13.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-AXmccw2BNDFMcCsK7DBf2NlyftL7i0ejZ4wcekszvg8NyPSezwm7pJnMwK9SWQ6tH/+jalnc6tBoZ6UPKciJAw==","shasum":"b38e455e38405da359169391dc6bcce9cf285880","tarball":"https://registry.npmjs.org/@alevettih/typed-route-template/-/typed-route-template-0.2.0.tgz","fileCount":23,"unpackedSize":13948,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC/pgyj7snrWGZF+RNHRSln3L3T6DVDESGPOH/8Yw67EAIhAPUyWFdioTjJ1pSlDH4ifoGoHxgkSE6AXICjqbhmLKr9"}]},"_npmUser":{"name":"alevet","email":"alevettih@ya.ru"},"directories":{},"maintainers":[{"name":"alevet","email":"alevettih@ya.ru"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/typed-route-template_0.2.0_1771568771091_0.024302202939135098"},"_hasShrinkwrap":false}},"time":{"created":"2025-11-11T13:43:18.699Z","modified":"2026-02-20T06:26:11.368Z","0.0.0":"2025-11-11T13:43:18.940Z","0.0.1":"2025-11-11T13:50:25.504Z","0.1.0":"2026-02-19T20:12:43.920Z","0.2.0":"2026-02-20T06:26:11.234Z"},"bugs":{"url":"https://github.com/Alevettih/typed-route-template/issues"},"author":{"name":"Alexandr Tikhonenko","email":"alevettih@ya.ru"},"license":"MIT","homepage":"https://github.com/Alevettih/typed-route-template","keywords":["typescript","routing","urls"],"repository":{"type":"github","url":"git+https://github.com/Alevettih/typed-route-template.git"},"description":"A tiny, type-safe helper for building and reusing parameterised URL/route templates in TypeScript. It keeps your runtime API simple while leveraging modern template literal types to prevent mismatched parameters at compile time.","maintainers":[{"name":"alevet","email":"alevettih@ya.ru"}],"readme":"# @alevettih/typed-route-template\n\nA tiny, type-safe helper for building and reusing parameterised URL/route templates in TypeScript. It keeps your runtime API simple while leveraging modern template literal types to prevent mismatched parameters at compile time.\n\n## Features\n\n- Runtime API centred on a single `RouteTemplate` class.\n- Compile-time inference of required route parameters from `:param` placeholders.\n- Type-safe `interpolate` that rejects missing params before code runs.\n- **Typed `interpolate` result**: returns a template-literal string type with params substituted.\n- Ability to slice a route from any segment with a typed `get` helper.\n- Zero runtime dependencies, tree-shakeable, written in TypeScript 5.9.\n\n## Installation\n\n```bash\nnpm i @alevettih/typed-route-template\n```\n\nThe package ships precompiled JavaScript (`dist/public-api.js`) and corresponding `.d.ts` types, so it works out of the box in both TS and modern JS toolchains.\n\n## Quick Start\n\n```ts\nimport { RouteTemplate } from '@alevettih/typed-route-template';\n\nconst postRoute = new RouteTemplate('/users/:userId/posts/:postId');\n\n// ✅ Type-safe params inference: { userId: string; postId: string }\nconst href = postRoute.interpolate({ userId: '42', postId: '99' });\n// -> '/users/42/posts/99' (type inferred)\n\n// ✅ Typed slicing: inferred literal \"/users/:userId\"\nconst detailSegment = postRoute.get(0, 3);\n```\n\n### Typed encoding in the return type\n\nAt runtime, values are passed through `encodeURIComponent`. The return type reflects that encoding for string literals:\n\n```ts\nconst searchRoute = new RouteTemplate('/search/:query');\nconst url = searchRoute.interpolate({ query: 'angular router' });\n// -> typed as: \"/search/angular%20router\"\n```\n\n> Note: TypeScript can precisely model encoding only for string literals and a practical subset of characters.\n> If a param value is just `string` (not a literal), the resulting type will naturally widen.\n\nIf you omit a required parameter, TypeScript catches it immediately:\n\n```ts\npostRoute.interpolate({ userId: '42' }); // TS error: postId is missing\n```\n\nAt runtime, `interpolate` also throws when a required value is `null`, `undefined`, or an empty string, helping you surface issues early.\n\n## API\n\n### `class RouteTemplate<T extends string>`\n\nCreates a reusable, typed representation of a colon-delimited route template.\n\n#### Constructor\n\n```ts\nnew RouteTemplate('/path/:segment');\n```\n\nStores the template string and automatically records parameter names for later interpolation.\n\n#### `get(fromIndex?: number, toIndex?: number): string`\n\n- `fromIndex` (optional, default `0`): zero-based index of the segment to start from.\n- `toIndex` (optional, default is the template segment length): zero-based index to end slicing (like `Array.prototype.slice`).\n- Returns either the entire template (when omitted or `0`) or the remaining path slice.\n- A conditional type `SplitAndJoin` ensures literal return types when indices are known at compile time.\n\n#### `interpolate(params): string`\n\n- `params`: object containing all named parameters discovered in the template, inferred from `T`.\n- Returns the template with every `:param` replaced by a URI-encoded value.\n- Throws when a required value is missing, `null`/`undefined`, or an empty string.\n- The return type is a template-literal type `InterpolatedRoute<T, P>` that:\n  - substitutes params into the route string type, and\n  - applies `EncodeURIComponent<...>` to the substituted values in the type system.\n\nExample:\n\n```ts\nconst route = new RouteTemplate('/user/:id/avatar/:id');\nconst href = route.interpolate({ id: 'abc def' });\n// -> \"/user/abc%20def/avatar/abc%20def\"\n```\n\n## Type Utilities\n\nWhile you typically interact only with `RouteTemplate`, the package also exposes advanced literal types that power its inference:\n\n- `ExtractRouteParams<T>` converts a template string into an object type containing all parameter names.\n- `InterpolatedRoute<Template, Params>` produces the typed interpolated route string.\n- `EncodeURIComponent<S>` type-level approximation of `encodeURIComponent` for string literals.\n- `Split`, `Slice`, and `Join` are internal building blocks that let `get` return precise literal slices.\n- `MergeIntersection<T>` is a helper that normalises intersections of inferred types.\n\nThese types are surfaced through the public API so you can compose them in more advanced scenarios if needed.\n\n## Error Handling\n\nCalling `interpolate` with missing values throws a descriptive error (`Param <name> is not defined`). You can catch this and respond with a 400/422 HTTP status, log telemetry, or fallback to a default route.\n\n## Usage Tips\n\n- Keep template strings literal (e.g. `const route = new RouteTemplate('/foo/:bar')`) so TypeScript can infer parameter objects accurately.\n- For best literal inference of the **result**, pass params as an object literal (no extra `as const` needed in typical cases).\n- When working with frameworks like Express, Remix, or Angular, store your route templates centrally and let handlers extract both the typed params and human-friendly URLs from a single source of truth.\n- Because values are URI-encoded automatically, you can safely interpolate strings containing spaces and reserved characters.\n\n## Development\n\nClone the repository and install dependencies:\n\n```bash\ngit clone https://github.com/Alevettih/typed-route-template.git\ncd typed-route-template\nnpm install\n```\n\nAvailable scripts:\n\n- `npm run build:dev` – Type-check and emit the development build.\n- `npm run build:prod` – Produce the production build.\n- `npm test` – Run the Vitest test suite.\n- `npm run lint` – Lint the project with ESLint.\n- `npm run format` – Format sources with Prettier.\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub. Please include tests when fixing bugs or adding features, and run the lint and test suites before submitting a PR.\n\n## License\n\nMIT © Alexandr Tikhonenko\n","readmeFilename":"README.md"}