{"_id":"unrouting","_rev":"12-e45cf0ec2a23093a379d3b2de72c0897","name":"unrouting","dist-tags":{"latest":"0.3.1"},"versions":{"0.0.0":{"name":"unrouting","version":"0.0.0","author":{"name":"Daniel Roe","email":"daniel@roe.dev"},"_id":"unrouting@0.0.0","maintainers":[{"name":"danielroe","email":"daniel@roe.dev"}],"dist":{"shasum":"7301f81958a60461e25c29e509623d293929e81c","tarball":"https://registry.npmjs.org/unrouting/-/unrouting-0.0.0.tgz","fileCount":2,"integrity":"sha512-/zF2b5FTzyDB353NO6cvL94TSKFX7roiKLTLC/ipkB7el5C3o0iUjEL1Qyr5VjzskwNVJfqT/maHWSNnX3fW/Q==","signatures":[{"sig":"MEYCIQDwPR5Jeah2RIkq59Aii+W/JpRoBZG3Tl/Q+MRpQIOE8wIhAICzgGHv9m/3LwBhx/Qtone2zr09mRx9KtFtoDWloiud","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":119},"gitHead":"fd8425b8bdc158ba00894cfaeed3d885d344b97f","_npmUser":{"name":"danielroe","email":"daniel@roe.dev"},"_npmVersion":"10.2.3","directories":{},"_nodeVersion":"18.19.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/unrouting_0.0.0_1706633309768_0.4119757529337291","host":"s3://npm-registry-packages"}},"0.0.1":{"name":"unrouting","version":"0.0.1","license":"MIT","_id":"unrouting@0.0.1","maintainers":[{"name":"danielroe","email":"daniel@roe.dev"}],"homepage":"https://github.com/unjs/unrouting#readme","bugs":{"url":"https://github.com/unjs/unrouting/issues"},"dist":{"shasum":"6fca13386d71aa27d26724614e72da834702c952","tarball":"https://registry.npmjs.org/unrouting/-/unrouting-0.0.1.tgz","fileCount":5,"integrity":"sha512-N9SkOgBoJPo7/MgllxlF3CaE6Flyi2OVjuE06rQ3c3tAdvYjL5b/nKB3t46S91NTJkr+V50wHnXFQawZHiIwIQ==","signatures":[{"sig":"MEQCICH6E2j+JG/G/rLBG47N0arPngVWF6DCENWgNdzKeYepAiBNnd2LTQHEaFZb0+AyLbVRUOtXkGtsHZIZ6A700tlglg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":11136},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":"./dist/index.js"},"gitHead":"051ba2832cf8fd88e0ae8fb6552314213d23fa6b","scripts":{"dev":"vitest dev","lint":"eslint . --fix","test":"pnpm test:unit && pnpm test:types","build":"unbuild","prepack":"pnpm build","prepare":"simple-git-hooks","release":"pnpm test && bumpp && npm publish","test:unit":"vitest","test:types":"tsc --noEmit","prepublishOnly":"pnpm lint && pnpm test"},"_npmUser":{"name":"danielroe","email":"daniel@roe.dev"},"repository":{"url":"git+https://github.com/unjs/unrouting.git","type":"git"},"_npmVersion":"10.5.0","description":"[![npm version][npm-version-src]][npm-version-href] [![npm downloads][npm-downloads-src]][npm-downloads-href] [![bundle][bundle-src]][bundle-href] [![Codecov][codecov-src]][codecov-href] [![License][license-src]][license-href] [![JSDocs][jsdocs-src]][jsdo","directories":{},"lint-staged":{"*.{js,ts,mjs,cjs,json,.*rc}":["pnpm eslint --fix"]},"resolutions":{"unrouting":"link:."},"sideEffects":false,"_nodeVersion":"20.12.2","dependencies":{"ufo":"^1.3.2","escape-string-regexp":"^5.0.0"},"_hasShrinkwrap":false,"packageManager":"pnpm@9.0.6","devDependencies":{"vite":"latest","bumpp":"^9.4.1","eslint":"latest","radix3":"1.1.2","vitest":"latest","unbuild":"latest","typescript":"latest","vue-router":"4.3.2","@types/node":"20.12.7","lint-staged":"latest","simple-git-hooks":"latest","@vitest/coverage-v8":"latest","@antfu/eslint-config":"latest"},"simple-git-hooks":{"pre-commit":"npx lint-staged"},"_npmOperationalInternal":{"tmp":"tmp/unrouting_0.0.1_1715193441979_0.31796014756526114","host":"s3://npm-registry-packages"}},"0.1.3":{"name":"unrouting","version":"0.1.3","license":"MIT","_id":"unrouting@0.1.3","maintainers":[{"name":"danielroe","email":"daniel@roe.dev"}],"homepage":"https://github.com/unjs/unrouting#readme","bugs":{"url":"https://github.com/unjs/unrouting/issues"},"dist":{"shasum":"a2bc2b5c401caf2376e193c887b39c53c63089e8","tarball":"https://registry.npmjs.org/unrouting/-/unrouting-0.1.3.tgz","fileCount":5,"integrity":"sha512-/cYt6OnDziX5k/cOBcbIVCNq9tG4wYNCf5rHdoZzs2+ph+w/p/pJWN0FScpAaTUVndVQOh5JeoMHZq/Vz83yAw==","signatures":[{"sig":"MEYCIQDLqv05LLOk5ecJTiOGnjgt8+MLPeIytvheplAi/1s4swIhAOD3P6JpusqNkJBovNzu5ILES9FrMRQ4YpdF/KKZzJuP","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/unrouting@0.1.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":43031},"main":"./dist/index.mjs","type":"module","_from":"file:unrouting-0.1.3.tgz","types":"./dist/index.d.mts","module":"./dist/index.mjs","exports":{".":"./dist/index.mjs"},"scripts":{"dev":"vitest dev","lint":"eslint .","test":"pnpm test:unit && pnpm test:types","build":"tsdown","release":"pnpm test && bumpp && npm publish","test:unit":"vitest run","test:types":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4d55f99a-7f10-442e-9575-ad3cb3853873"}},"_resolved":"/tmp/2500fe2580eef22ea7f9c389ee78b30b/unrouting-0.1.3.tgz","_integrity":"sha512-/cYt6OnDziX5k/cOBcbIVCNq9tG4wYNCf5rHdoZzs2+ph+w/p/pJWN0FScpAaTUVndVQOh5JeoMHZq/Vz83yAw==","repository":{"url":"git+https://github.com/unjs/unrouting.git","type":"git"},"_npmVersion":"11.6.2","description":"[![npm version][npm-version-src]][npm-version-href] [![npm downloads][npm-downloads-src]][npm-downloads-href] [![bundle][bundle-src]][bundle-href] [![Codecov][codecov-src]][codecov-href] [![License][license-src]][license-href] [![JSDocs][jsdocs-src]][jsdo","directories":{},"lint-staged":{"*.{js,ts,mjs,cjs,json,.*rc}":["pnpm eslint --fix"]},"resolutions":{"unrouting":"link:."},"sideEffects":false,"_nodeVersion":"24.13.0","dependencies":{"ufo":"^1.6.3","escape-string-regexp":"^5.0.0"},"_hasShrinkwrap":false,"devDependencies":{"rou3":"0.7.12","vite":"7.3.1","bumpp":"10.4.1","eslint":"10.0.0","tsdown":"0.20.3","vitest":"4.0.18","pkg-pr-new":"0.0.63","typescript":"5.9.3","vue-router":"5.0.2","@types/node":"22.19.11","lint-staged":"16.2.7","simple-git-hooks":"2.13.1","@vitest/coverage-v8":"4.0.18","@antfu/eslint-config":"7.4.3"},"simple-git-hooks":{"pre-commit":"npx lint-staged"},"_npmOperationalInternal":{"tmp":"tmp/unrouting_0.1.3_1770940857347_0.6036443218165815","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"unrouting","version":"0.1.4","license":"MIT","_id":"unrouting@0.1.4","maintainers":[{"name":"danielroe","email":"daniel@roe.dev"}],"homepage":"https://github.com/unjs/unrouting#readme","bugs":{"url":"https://github.com/unjs/unrouting/issues"},"dist":{"shasum":"8e1249c6d05d52f2c9f38f4e7cedac487c422a71","tarball":"https://registry.npmjs.org/unrouting/-/unrouting-0.1.4.tgz","fileCount":5,"integrity":"sha512-INBm5DI5W0akn98ZkoqDDMvF2CpYi3Thp+/dGqvizkkDK7xbFuM94P0jdMRc2yUAVNjdQdpWsiGEkgwu7uL4Dg==","signatures":[{"sig":"MEYCIQCT/JUOrchGZTaTeX6gTnz+cXaUbYuZiKZj2LmNZzyy0gIhAMTdHYzqsrNjYDgmjiISVyujePnv7jUXs8vucQhvD+Za","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/unrouting@0.1.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":50599},"main":"./dist/index.mjs","type":"module","_from":"file:unrouting-0.1.4.tgz","types":"./dist/index.d.mts","module":"./dist/index.mjs","exports":{".":"./dist/index.mjs"},"scripts":{"dev":"vitest dev","lint":"eslint .","test":"pnpm test:unit && pnpm test:types","build":"tsdown","release":"pnpm test && bumpp","test:unit":"vitest run","test:types":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4d55f99a-7f10-442e-9575-ad3cb3853873"}},"_resolved":"/tmp/663a5cbbd37e4d40b7ca108e1f84e9b5/unrouting-0.1.4.tgz","_integrity":"sha512-INBm5DI5W0akn98ZkoqDDMvF2CpYi3Thp+/dGqvizkkDK7xbFuM94P0jdMRc2yUAVNjdQdpWsiGEkgwu7uL4Dg==","repository":{"url":"git+https://github.com/unjs/unrouting.git","type":"git"},"_npmVersion":"11.6.2","description":"[![npm version][npm-version-src]][npm-version-href] [![npm downloads][npm-downloads-src]][npm-downloads-href] [![bundle][bundle-src]][bundle-href] [![Codecov][codecov-src]][codecov-href] [![License][license-src]][license-href] [![JSDocs][jsdocs-src]][jsdo","directories":{},"lint-staged":{"*.{js,ts,mjs,cjs,json,.*rc}":["pnpm eslint --fix"]},"resolutions":{"unrouting":"link:."},"sideEffects":false,"_nodeVersion":"24.13.0","dependencies":{"ufo":"^1.6.3","escape-string-regexp":"^5.0.0"},"_hasShrinkwrap":false,"devDependencies":{"rou3":"0.7.12","vite":"7.3.1","bumpp":"10.4.1","eslint":"10.0.0","tsdown":"0.20.3","vitest":"4.0.18","pkg-pr-new":"0.0.63","typescript":"5.9.3","vue-router":"5.0.2","@types/node":"24.10.13","lint-staged":"16.2.7","simple-git-hooks":"2.13.1","@vitest/coverage-v8":"4.0.18","@antfu/eslint-config":"7.4.3"},"simple-git-hooks":{"pre-commit":"npx lint-staged"},"_npmOperationalInternal":{"tmp":"tmp/unrouting_0.1.4_1770976237117_0.6834050758247472","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"unrouting","version":"0.1.5","license":"MIT","_id":"unrouting@0.1.5","maintainers":[{"name":"danielroe","email":"daniel@roe.dev"}],"homepage":"https://github.com/unjs/unrouting#readme","bugs":{"url":"https://github.com/unjs/unrouting/issues"},"dist":{"shasum":"ba2c508c82c148223d5109e5dc530b7898f972b1","tarball":"https://registry.npmjs.org/unrouting/-/unrouting-0.1.5.tgz","fileCount":5,"integrity":"sha512-Z9QCdWmf2dqrlcJ5KMgSRm5sEhhhSS2D7iOh/t3k0bnAKp5K8+AMf6eqfGGZAQCPn3IcM7ABixxy+FBjOvATBQ==","signatures":[{"sig":"MEUCIQCpCN1D7YFq0w0XtQSD6X2K2xJhI76EdDsLlHasyq5lsAIgNorNRRdTKYJ6YLm3E3UYLebLqm9eRuKMEm5RAwyob5g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/unrouting@0.1.5","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":51325},"main":"./dist/index.mjs","type":"module","_from":"file:unrouting-0.1.5.tgz","types":"./dist/index.d.mts","module":"./dist/index.mjs","exports":{".":"./dist/index.mjs"},"scripts":{"dev":"vitest dev","lint":"eslint .","test":"pnpm test:unit && pnpm test:types","build":"tsdown","release":"pnpm test && bumpp","test:unit":"vitest run","test:types":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4d55f99a-7f10-442e-9575-ad3cb3853873"}},"_resolved":"/tmp/749dc1919448e63f24ff5fd7d77d9c8e/unrouting-0.1.5.tgz","_integrity":"sha512-Z9QCdWmf2dqrlcJ5KMgSRm5sEhhhSS2D7iOh/t3k0bnAKp5K8+AMf6eqfGGZAQCPn3IcM7ABixxy+FBjOvATBQ==","repository":{"url":"git+https://github.com/unjs/unrouting.git","type":"git"},"_npmVersion":"11.6.2","description":"[![npm version][npm-version-src]][npm-version-href] [![npm downloads][npm-downloads-src]][npm-downloads-href] [![bundle][bundle-src]][bundle-href] [![Codecov][codecov-src]][codecov-href] [![License][license-src]][license-href] [![JSDocs][jsdocs-src]][jsdo","directories":{},"lint-staged":{"*.{js,ts,mjs,cjs,json,.*rc}":["pnpm eslint --fix"]},"resolutions":{"unrouting":"link:."},"sideEffects":false,"_nodeVersion":"24.13.0","dependencies":{"ufo":"^1.6.3","escape-string-regexp":"^5.0.0"},"_hasShrinkwrap":false,"devDependencies":{"rou3":"0.7.12","vite":"7.3.1","bumpp":"10.4.1","eslint":"10.0.0","tsdown":"0.20.3","vitest":"4.0.18","pkg-pr-new":"0.0.63","typescript":"5.9.3","vue-router":"5.0.2","@types/node":"24.10.13","lint-staged":"16.2.7","simple-git-hooks":"2.13.1","@vitest/coverage-v8":"4.0.18","@antfu/eslint-config":"7.4.3"},"simple-git-hooks":{"pre-commit":"npx lint-staged"},"_npmOperationalInternal":{"tmp":"tmp/unrouting_0.1.5_1770979269351_0.8049143040303548","host":"s3://npm-registry-packages-npm-production"}},"0.1.7":{"name":"unrouting","version":"0.1.7","license":"MIT","_id":"unrouting@0.1.7","maintainers":[{"name":"danielroe","email":"daniel@roe.dev"}],"homepage":"https://github.com/unjs/unrouting#readme","bugs":{"url":"https://github.com/unjs/unrouting/issues"},"dist":{"shasum":"a4754c81c5270093118734dbf0d90a367b211a27","tarball":"https://registry.npmjs.org/unrouting/-/unrouting-0.1.7.tgz","fileCount":5,"integrity":"sha512-+0hfD+CVWtD636rc5Fn9VEjjTEDhdqgMpbwAuVoUmydSHDaMNiFW93SJG4LV++RoGSEAyvQN5uABAscYpDphpQ==","signatures":[{"sig":"MEQCIHnN+6rfP69mOYOeHP5/oguYW4RJfDamstvLJPWjahKuAiBbcQjZbtl8InRwuY0oFM8cOKUzbKRZrgAoBtMnS845nQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/unrouting@0.1.7","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":51302},"main":"./dist/index.mjs","type":"module","_from":"file:unrouting-0.1.7.tgz","types":"./dist/index.d.mts","module":"./dist/index.mjs","exports":{".":"./dist/index.mjs"},"scripts":{"dev":"vitest dev","lint":"eslint .","test":"pnpm test:unit && pnpm test:types","build":"tsdown","release":"pnpm test && bumpp","test:unit":"vitest run","test:types":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:4d55f99a-7f10-442e-9575-ad3cb3853873"}},"_resolved":"/tmp/52edddef2c9f2dd5eb7530789c83c65d/unrouting-0.1.7.tgz","_integrity":"sha512-+0hfD+CVWtD636rc5Fn9VEjjTEDhdqgMpbwAuVoUmydSHDaMNiFW93SJG4LV++RoGSEAyvQN5uABAscYpDphpQ==","repository":{"url":"git+https://github.com/unjs/unrouting.git","type":"git"},"_npmVersion":"11.9.0","description":"[![npm version][npm-version-src]][npm-version-href] [![npm downloads][npm-downloads-src]][npm-downloads-href] [![bundle][bundle-src]][bundle-href] [![Codecov][codecov-src]][codecov-href] [![License][license-src]][license-href] [![JSDocs][jsdocs-src]][jsdo","directories":{},"lint-staged":{"*.{js,ts,mjs,cjs,json,.*rc}":["pnpm eslint --fix"]},"resolutions":{"unrouting":"link:."},"sideEffects":false,"_nodeVersion":"24.14.0","dependencies":{"ufo":"^1.6.3","escape-string-regexp":"^5.0.0"},"_hasShrinkwrap":false,"devDependencies":{"rou3":"0.7.12","vite":"7.3.1","bumpp":"10.4.1","eslint":"10.0.1","tsdown":"0.21.0","vitest":"4.0.18","pkg-pr-new":"0.0.65","typescript":"5.9.3","vue-router":"5.0.3","@types/node":"24.11.0","lint-staged":"16.3.2","simple-git-hooks":"2.13.1","@vitest/coverage-v8":"4.0.18","@antfu/eslint-config":"7.6.1"},"simple-git-hooks":{"pre-commit":"npx lint-staged"},"_npmOperationalInternal":{"tmp":"tmp/unrouting_0.1.7_1773402263029_0.9712664484664582","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"unrouting","version":"0.2.0","license":"MIT","_id":"unrouting@0.2.0","maintainers":[{"name":"danielroe","email":"daniel@roe.dev"}],"homepage":"https://github.com/unjs/unrouting#readme","bugs":{"url":"https://github.com/unjs/unrouting/issues"},"dist":{"shasum":"838edaa24c17ae3804f0a114a921cb7b730461ef","tarball":"https://registry.npmjs.org/unrouting/-/unrouting-0.2.0.tgz","fileCount":5,"integrity":"sha512-/0DyKV3NShmnCWNcU2BEYD0//GTqG36i6YldpYTXV5Rs+FRqs7sFfxUHTuT76dV5f+N1eHIQvnFKtxkB9HMV8g==","signatures":[{"sig":"MEUCIAgQXOcafbxo6gAZS5d0dUn63WExJw92W+7egMFCat1sAiEA7dDwKDQj+dDRFA3TenJ+8MPieCWligZPL6NsPrHGoI4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/unrouting@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":76255},"main":"./dist/index.mjs","type":"module","_from":"file:/home/runner/work/_temp/uppt-tarballs/unrouting-0.2.0.tgz","types":"./dist/index.d.mts","module":"./dist/index.mjs","exports":{".":"./dist/index.mjs"},"scripts":{"dev":"vitest dev","lint":"eslint .","test":"pnpm test:unit && pnpm test:types","build":"tsdown","release":"pnpm test && bumpp","test:unit":"vitest run","test:types":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","approver":{"name":"danielroe","email":"daniel@roe.dev"},"trustedPublisher":{"id":"github","oidcConfigId":"oidc:4575029b-8dbb-4d98-b671-21a952eb8533"}},"_resolved":"/home/runner/work/_temp/uppt-tarballs/unrouting-0.2.0.tgz","_integrity":"sha512-/0DyKV3NShmnCWNcU2BEYD0//GTqG36i6YldpYTXV5Rs+FRqs7sFfxUHTuT76dV5f+N1eHIQvnFKtxkB9HMV8g==","repository":{"url":"git+https://github.com/unjs/unrouting.git","type":"git"},"_npmVersion":"12.0.1","description":"[![npm version][npm-version-src]][npm-version-href] [![npm downloads][npm-downloads-src]][npm-downloads-href] [![bundle][bundle-src]][bundle-href] [![Codecov][codecov-src]][codecov-href] [![License][license-src]][license-href] [![JSDocs][jsdocs-src]][jsdo","directories":{},"lint-staged":{"*.{js,ts,mjs,cjs,json,.*rc}":["pnpm eslint --fix"]},"sideEffects":false,"_nodeVersion":"24.18.0","dependencies":{"ufo":"^1.6.3","escape-string-regexp":"^5.0.0"},"_hasShrinkwrap":false,"devDependencies":{"rou3":"0.9.1","vite":"8.1.5","bumpp":"11.1.0","eslint":"10.7.0","tsdown":"0.22.13","vitest":"4.1.10","pkg-pr-new":"0.0.79","typescript":"6.0.3","vue-router":"5.2.0","@types/node":"24.13.3","lint-staged":"17.1.1","simple-git-hooks":"2.13.1","@vitest/coverage-v8":"4.1.10","@antfu/eslint-config":"9.2.0"},"simple-git-hooks":{"pre-commit":"npx lint-staged"},"_npmOperationalInternal":{"tmp":"tmp/unrouting_0.2.0_1784741770777_0.7607105637984661","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"unrouting","version":"0.2.1","license":"MIT","_id":"unrouting@0.2.1","maintainers":[{"name":"danielroe","email":"daniel@roe.dev"}],"homepage":"https://github.com/unjs/unrouting#readme","bugs":{"url":"https://github.com/unjs/unrouting/issues"},"dist":{"shasum":"64ccdfa0cdbda06b7eba76377461171678075e0b","tarball":"https://registry.npmjs.org/unrouting/-/unrouting-0.2.1.tgz","fileCount":5,"integrity":"sha512-6PPgRNT60lViebJUD/eRdbOd4lS5x+RK5z7IHzAzlYwPqRLFySlzwmoyvvVvpQwrxyyphJ2fSzuWKoCnklilqQ==","signatures":[{"sig":"MEUCIQCIPfQ4nz2OHQuy6xVnt7D8VFeTCqgYpoAqsDiiV5cArwIgUY0e57Vs7R0HhWOy1ybHIUaMXiwgqFWAs3bfFD3D90o=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/unrouting@0.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":77814},"main":"./dist/index.mjs","type":"module","_from":"file:/home/runner/work/_temp/uppt-tarballs/unrouting-0.2.1.tgz","types":"./dist/index.d.mts","module":"./dist/index.mjs","exports":{".":"./dist/index.mjs"},"scripts":{"dev":"vitest dev","lint":"eslint .","test":"pnpm test:unit && pnpm test:types","build":"tsdown","release":"pnpm test && bumpp","test:unit":"vitest run","test:types":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","approver":{"name":"danielroe","email":"daniel@roe.dev"},"trustedPublisher":{"id":"github","oidcConfigId":"oidc:4575029b-8dbb-4d98-b671-21a952eb8533"}},"_resolved":"/home/runner/work/_temp/uppt-tarballs/unrouting-0.2.1.tgz","_integrity":"sha512-6PPgRNT60lViebJUD/eRdbOd4lS5x+RK5z7IHzAzlYwPqRLFySlzwmoyvvVvpQwrxyyphJ2fSzuWKoCnklilqQ==","repository":{"url":"git+https://github.com/unjs/unrouting.git","type":"git"},"_npmVersion":"12.0.1","description":"[![npm version][npm-version-src]][npm-version-href] [![npm downloads][npm-downloads-src]][npm-downloads-href] [![bundle][bundle-src]][bundle-href] [![Codecov][codecov-src]][codecov-href] [![License][license-src]][license-href] [![JSDocs][jsdocs-src]][jsdo","directories":{},"lint-staged":{"*.{js,ts,mjs,cjs,json,.*rc}":["pnpm eslint --fix"]},"sideEffects":false,"_nodeVersion":"24.18.0","dependencies":{"ufo":"^1.6.3","escape-string-regexp":"^5.0.0"},"_hasShrinkwrap":false,"devDependencies":{"rou3":"0.9.1","vite":"8.1.5","bumpp":"11.1.0","eslint":"10.7.0","tsdown":"0.22.13","vitest":"4.1.10","pkg-pr-new":"0.0.79","typescript":"6.0.3","vue-router":"5.2.0","@types/node":"24.13.3","lint-staged":"17.1.1","simple-git-hooks":"2.13.1","@vitest/coverage-v8":"4.1.10","@antfu/eslint-config":"9.2.0"},"simple-git-hooks":{"pre-commit":"npx lint-staged"},"_npmOperationalInternal":{"tmp":"tmp/unrouting_0.2.1_1784744244803_0.4123262678386479","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"unrouting","version":"0.2.2","license":"MIT","_id":"unrouting@0.2.2","maintainers":[{"name":"danielroe","email":"daniel@roe.dev"}],"homepage":"https://github.com/unjs/unrouting#readme","bugs":{"url":"https://github.com/unjs/unrouting/issues"},"dist":{"shasum":"db9c0c890b6d32d746f72dee170b775b240f3c95","tarball":"https://registry.npmjs.org/unrouting/-/unrouting-0.2.2.tgz","fileCount":5,"integrity":"sha512-EoCab68s1o9AWFq9fjKsMEsmjKrPO11SAsvopikks2eEm/KLXgZMCof4cgpVgdy0Vz71OFBJw6DoDqu1oOSFGw==","signatures":[{"sig":"MEUCIGiC8iMu55O9OoHr4XPcnBI47cIkINUWznKvjdd/kEajAiEArgy4YNVWwfjtxlMngCdk7rEeFQmzClBoC8j83SqFws0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/unrouting@0.2.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":77943},"main":"./dist/index.mjs","type":"module","_from":"file:/home/runner/work/_temp/uppt-tarballs/unrouting-0.2.2.tgz","types":"./dist/index.d.mts","module":"./dist/index.mjs","exports":{".":"./dist/index.mjs"},"scripts":{"dev":"vitest dev","lint":"eslint .","test":"pnpm test:unit && pnpm test:types","build":"tsdown","release":"pnpm test && bumpp","test:unit":"vitest run","test:types":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","approver":{"name":"danielroe","email":"daniel@roe.dev"},"trustedPublisher":{"id":"github","oidcConfigId":"oidc:4575029b-8dbb-4d98-b671-21a952eb8533"}},"_resolved":"/home/runner/work/_temp/uppt-tarballs/unrouting-0.2.2.tgz","_integrity":"sha512-EoCab68s1o9AWFq9fjKsMEsmjKrPO11SAsvopikks2eEm/KLXgZMCof4cgpVgdy0Vz71OFBJw6DoDqu1oOSFGw==","repository":{"url":"git+https://github.com/unjs/unrouting.git","type":"git"},"_npmVersion":"12.0.1","description":"[![npm version][npm-version-src]][npm-version-href] [![npm downloads][npm-downloads-src]][npm-downloads-href] [![bundle][bundle-src]][bundle-href] [![Codecov][codecov-src]][codecov-href] [![License][license-src]][license-href] [![JSDocs][jsdocs-src]][jsdo","directories":{},"lint-staged":{"*.{js,ts,mjs,cjs,json,.*rc}":["pnpm eslint --fix"]},"sideEffects":false,"_nodeVersion":"24.18.0","dependencies":{"ufo":"^1.6.3","escape-string-regexp":"^5.0.0"},"_hasShrinkwrap":false,"devDependencies":{"rou3":"0.9.1","vite":"8.1.5","bumpp":"11.1.0","eslint":"10.7.0","tsdown":"0.22.13","vitest":"4.1.10","pkg-pr-new":"0.0.79","typescript":"6.0.3","vue-router":"5.2.0","@types/node":"24.13.3","lint-staged":"17.1.1","simple-git-hooks":"2.13.1","@vitest/coverage-v8":"4.1.10","@antfu/eslint-config":"9.2.0"},"simple-git-hooks":{"pre-commit":"npx lint-staged"},"_npmOperationalInternal":{"tmp":"tmp/unrouting_0.2.2_1784799541635_0.08931429005044556","host":"s3://npm-registry-packages-npm-production"}},"0.2.3":{"name":"unrouting","version":"0.2.3","license":"MIT","_id":"unrouting@0.2.3","maintainers":[{"name":"danielroe","email":"daniel@roe.dev"}],"homepage":"https://github.com/unjs/unrouting#readme","bugs":{"url":"https://github.com/unjs/unrouting/issues"},"dist":{"shasum":"16c7d9326c7251fc73269decc683a65597cc0f1f","tarball":"https://registry.npmjs.org/unrouting/-/unrouting-0.2.3.tgz","fileCount":5,"integrity":"sha512-8wOFT/fBh8YeeDr1aVmkXCqYVTMbQ6vzfNzwzybKmSfXdRhGCq1Y2B1e9YeB0JEf85gbvSwJHAMu3D2IEcLGKA==","signatures":[{"sig":"MEUCIQCNF8wZklgh1yGCMyCpbyeTg+4dce0UyzF93WwkFNs92gIgZIt96p/dD2Xydp7u0C7z/fHjPqu5paOAjYXGnZW5E+o=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/unrouting@0.2.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":78666},"main":"./dist/index.mjs","type":"module","_from":"file:/home/runner/work/_temp/uppt-tarballs/unrouting-0.2.3.tgz","types":"./dist/index.d.mts","module":"./dist/index.mjs","exports":{".":"./dist/index.mjs"},"scripts":{"dev":"vitest dev","lint":"eslint .","test":"pnpm test:unit && pnpm test:types","build":"tsdown","release":"pnpm test && bumpp","test:unit":"vitest run","test:types":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","approver":{"name":"danielroe","email":"daniel@roe.dev"},"trustedPublisher":{"id":"github","oidcConfigId":"oidc:4575029b-8dbb-4d98-b671-21a952eb8533"}},"_resolved":"/home/runner/work/_temp/uppt-tarballs/unrouting-0.2.3.tgz","_integrity":"sha512-8wOFT/fBh8YeeDr1aVmkXCqYVTMbQ6vzfNzwzybKmSfXdRhGCq1Y2B1e9YeB0JEf85gbvSwJHAMu3D2IEcLGKA==","repository":{"url":"git+https://github.com/unjs/unrouting.git","type":"git"},"_npmVersion":"12.0.2","description":"[![npm version][npm-version-src]][npm-version-href] [![npm downloads][npm-downloads-src]][npm-downloads-href] [![bundle][bundle-src]][bundle-href] [![Codecov][codecov-src]][codecov-href] [![License][license-src]][license-href] [![JSDocs][jsdocs-src]][jsdo","directories":{},"lint-staged":{"*.{js,ts,mjs,cjs,json,.*rc}":["pnpm eslint --fix"]},"sideEffects":false,"_nodeVersion":"24.18.0","dependencies":{"ufo":"^1.6.3","escape-string-regexp":"^5.0.0"},"_hasShrinkwrap":false,"devDependencies":{"rou3":"0.9.2","vite":"8.2.1","bumpp":"12.2.0","eslint":"10.8.1","tsdown":"0.22.14","vitest":"4.1.10","pkg-pr-new":"0.0.87","typescript":"6.0.3","vue-router":"5.2.0","@types/node":"24.13.3","lint-staged":"17.3.0","simple-git-hooks":"2.13.1","@vitest/coverage-v8":"4.1.10","@antfu/eslint-config":"9.3.0"},"simple-git-hooks":{"pre-commit":"npx lint-staged"},"_npmOperationalInternal":{"tmp":"tmp/unrouting_0.2.3_1786547246469_0.5370323848369778","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"unrouting","version":"0.3.0","license":"MIT","_id":"unrouting@0.3.0","maintainers":[{"name":"danielroe","email":"daniel@roe.dev"}],"homepage":"https://github.com/unjs/unrouting#readme","bugs":{"url":"https://github.com/unjs/unrouting/issues"},"dist":{"shasum":"f74e26b2b26371dc2c02f76588d6701011cedafb","tarball":"https://registry.npmjs.org/unrouting/-/unrouting-0.3.0.tgz","fileCount":5,"integrity":"sha512-QU3WwdULv/+Upb3aDVHT+mFciHz43Y6sT4+6YUxX0CuiNyD1Oie7f1fRTN04BMXH11qQhn/5irRC2eLmFrl7DQ==","signatures":[{"sig":"MEUCIQDc6wHENNWEMG3aahmpXS1X1/sUYlxLz8Ec+EnZnq9HJAIga1DtY2FTlZsLg2eezmKGUHMt7UIK5pUZU1eLNM7dJk8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/unrouting@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":82735},"main":"./dist/index.mjs","type":"module","_from":"file:/home/runner/work/_temp/uppt-tarballs/unrouting-0.3.0.tgz","types":"./dist/index.d.mts","module":"./dist/index.mjs","exports":{".":"./dist/index.mjs"},"scripts":{"dev":"vitest dev","lint":"eslint .","test":"pnpm test:unit && pnpm test:types","build":"tsdown","release":"pnpm test && bumpp","test:unit":"vitest run","test:types":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","approver":{"name":"danielroe","email":"daniel@roe.dev"},"trustedPublisher":{"id":"github","oidcConfigId":"4575029b-8dbb-4d98-b671-21a952eb8533"}},"_resolved":"/home/runner/work/_temp/uppt-tarballs/unrouting-0.3.0.tgz","_integrity":"sha512-QU3WwdULv/+Upb3aDVHT+mFciHz43Y6sT4+6YUxX0CuiNyD1Oie7f1fRTN04BMXH11qQhn/5irRC2eLmFrl7DQ==","devEngines":{"runtime":{"name":"node","onFail":"download","version":"^24.0.0"},"packageManager":{"name":"pnpm","onFail":"download","version":"12.14.0"}},"repository":{"url":"git+https://github.com/unjs/unrouting.git","type":"git"},"_npmVersion":"12.2.0","description":"[![npm version][npm-version-src]][npm-version-href] [![npm downloads][npm-downloads-src]][npm-downloads-href] [![bundle][bundle-src]][bundle-href] [![Codecov][codecov-src]][codecov-href] [![License][license-src]][license-href] [![JSDocs][jsdocs-src]][jsdo","directories":{},"lint-staged":{"*.{js,ts,mjs,cjs,json,.*rc}":["pnpm eslint --fix"]},"sideEffects":false,"_nodeVersion":"24.21.0","dependencies":{"ufo":"^1.6.3","escape-string-regexp":"^5.0.0"},"_hasShrinkwrap":false,"devDependencies":{"rou3":"1.0.0","vite":"8.3.4","bumpp":"12.3.0","eslint":"10.13.0","radix3":"1.1.2","tsdown":"0.23.1","vitest":"5.0.5","rou3-v0":"npm:rou3@0.9.2","pkg-pr-new":"0.0.91","typescript":"6.0.3","vue-router":"5.4.0","@types/node":"24.19.2","lint-staged":"17.6.0","simple-git-hooks":"2.14.0","@vitest/coverage-v8":"5.0.5","@antfu/eslint-config":"9.5.1"},"simple-git-hooks":{"pre-commit":"pnpm lint-staged"},"_npmOperationalInternal":{"tmp":"tmp/unrouting_0.3.0_1792606545202_0.06459936744801276","host":"s3://npm-registry-packages-npm-production"}},"0.3.1":{"_id":"unrouting@0.3.1","bugs":{"url":"https://github.com/unjs/unrouting/issues"},"dist":{"shasum":"d7890f711600a136b5b22532a8bae63cd6ad2c4a","tarball":"https://registry.npmjs.org/unrouting/-/unrouting-0.3.1.tgz","integrity":"sha512-gBrZaBzhZdvnA6eZiDDAbwx2/5sTslga/LqvqrFbdMg4EDcLsvKZuwLcTaOauv2UnVcVz6pb8FlEXhP4VuEqpw==","fileCount":5,"unpackedSize":83599,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/unrouting@0.3.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQD1dNrTZnQufBkQ70rTNHuuAMCxkvUWUShZ8EfaZ0iJKgIgUosKnYU6fkH3/utqUYH7I8KJMDaYSzqiDVn7LW7Lr54="}]},"main":"./dist/index.mjs","name":"unrouting","type":"module","_from":"file:/home/runner/work/_temp/uppt-tarballs/unrouting-0.3.1.tgz","types":"./dist/index.d.mts","module":"./dist/index.mjs","exports":{".":"./dist/index.mjs"},"license":"MIT","scripts":{"dev":"vitest dev","lint":"eslint .","test":"pnpm test:unit && pnpm test:types","build":"tsdown","release":"pnpm test && bumpp","test:unit":"vitest run","test:types":"tsc --noEmit"},"version":"0.3.1","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"4575029b-8dbb-4d98-b671-21a952eb8533"},"approver":{"name":"danielroe","email":"daniel@roe.dev"}},"homepage":"https://github.com/unjs/unrouting#readme","_resolved":"/home/runner/work/_temp/uppt-tarballs/unrouting-0.3.1.tgz","_integrity":"sha512-gBrZaBzhZdvnA6eZiDDAbwx2/5sTslga/LqvqrFbdMg4EDcLsvKZuwLcTaOauv2UnVcVz6pb8FlEXhP4VuEqpw==","devEngines":{"runtime":{"name":"node","onFail":"download","version":"^24.0.0"},"packageManager":{"name":"pnpm","onFail":"download","version":"12.14.0"}},"repository":{"url":"git+https://github.com/unjs/unrouting.git","type":"git"},"_npmVersion":"12.2.0","description":"[![npm version][npm-version-src]][npm-version-href] [![npm downloads][npm-downloads-src]][npm-downloads-href] [![bundle][bundle-src]][bundle-href] [![Codecov][codecov-src]][codecov-href] [![License][license-src]][license-href] [![JSDocs][jsdocs-src]][jsdo","directories":{},"lint-staged":{"*.{js,ts,mjs,cjs,json,.*rc}":["pnpm eslint --fix"]},"maintainers":[{"name":"danielroe","email":"daniel@roe.dev"}],"sideEffects":false,"_nodeVersion":"24.21.0","dependencies":{"ufo":"^1.6.3","escape-string-regexp":"^5.0.0"},"devDependencies":{"rou3":"1.0.0","vite":"8.3.4","bumpp":"12.3.0","eslint":"10.13.0","radix3":"1.1.2","tsdown":"0.23.1","vitest":"5.0.5","rou3-v0":"npm:rou3@0.9.2","pkg-pr-new":"0.0.91","typescript":"6.0.3","vue-router":"5.4.0","@types/node":"24.19.2","lint-staged":"17.6.0","simple-git-hooks":"2.14.0","@vitest/coverage-v8":"5.0.5","@antfu/eslint-config":"9.5.1"},"simple-git-hooks":{"pre-commit":"pnpm lint-staged"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/unrouting_0.3.1_1792613081504_0.19009585146500885"},"_hasShrinkwrap":false}},"time":{"created":"2024-01-30T16:48:29.652Z","modified":"2026-10-21T20:04:42.061Z","0.0.0":"2024-01-30T16:48:29.914Z","0.0.1":"2024-05-08T18:37:22.170Z","0.1.3":"2026-02-13T00:00:57.494Z","0.1.4":"2026-02-13T09:50:37.288Z","0.1.5":"2026-02-13T10:41:09.504Z","0.1.7":"2026-03-13T11:44:23.212Z","0.2.0":"2026-07-22T17:36:10.859Z","0.2.1":"2026-07-22T18:17:24.886Z","0.2.2":"2026-07-23T09:39:01.713Z","0.2.3":"2026-08-12T15:07:26.557Z","0.3.0":"2026-10-21T18:15:45.293Z","0.3.1":"2026-10-21T20:04:41.606Z"},"bugs":{"url":"https://github.com/unjs/unrouting/issues"},"license":"MIT","homepage":"https://github.com/unjs/unrouting#readme","repository":{"url":"git+https://github.com/unjs/unrouting.git","type":"git"},"description":"[![npm version][npm-version-src]][npm-version-href] [![npm downloads][npm-downloads-src]][npm-downloads-href] [![bundle][bundle-src]][bundle-href] [![Codecov][codecov-src]][codecov-href] [![License][license-src]][license-href] [![JSDocs][jsdocs-src]][jsdo","maintainers":[{"name":"danielroe","email":"daniel@roe.dev"}],"readme":"# 📍 unrouting\n\n[![npm version][npm-version-src]][npm-version-href]\n[![npm downloads][npm-downloads-src]][npm-downloads-href]\n[![bundle][bundle-src]][bundle-href]\n[![Codecov][codecov-src]][codecov-href]\n[![License][license-src]][license-href]\n[![JSDocs][jsdocs-src]][jsdocs-href]\n\n> Universal filesystem routing\n\n`unrouting` parses file paths into a route tree and emits route definitions for any framework router. It handles nested routes, dynamic params, catchalls, optional segments, route groups, layer merging, and more – as a standalone, framework-agnostic library.\n\n## Status\n\nIn active development. The core pipeline (parse, tree, emit) is functional and used by Nuxt.\n\n- [x] Generic route parsing covering major filesystem routing patterns\n  - [x] [Nuxt](https://github.com/nuxt/nuxt) / [unplugin-vue-router](https://github.com/posva/unplugin-vue-router)\n  - [ ] [SvelteKit](https://kit.svelte.dev/docs/routing)\n  - [ ] [Next.js](https://nextjs.org/docs/app/building-your-application/routing)\n- [x] Route tree with nesting, layer merging, group transparency\n- [x] Layer priority (multiple roots with configurable file precedence)\n- [x] Incremental tree updates (`addFile`/`removeFile` for dev server HMR)\n- [x] Pluggable route name generation\n- [x] Route ordering by segment priority (static > dynamic > optional > catchall)\n- [x] Named view support (`@viewName` convention)\n- [x] Mode variant support (`.client`, `.server`, configurable)\n- [x] Duplicate route name detection\n- [x] Emit to framework routers\n  - [x] [`vue-router`](https://router.vuejs.org/) (nested routes, names, files, children, meta, components, modes)\n  - [x] [rou3](http://github.com/h3js/rou3)/[Nitro](https://nitro.unjs.io/)\n  - [x] RegExp patterns\n  - [ ] [SolidStart](https://start.solidjs.com/core-concepts/routing)\n  - [ ] [SvelteKit](https://kit.svelte.dev/docs/routing)\n\n## Install\n\n```sh\n# npm\nnpm install unrouting\n\n# pnpm\npnpm install unrouting\n```\n\n## Usage\n\nThe library has a three-phase pipeline: **parse** file paths into tokens, **build** a route tree, and **emit** to a target format. For most use cases you only need two function calls.\n\n### Quick start\n\n```js\nimport { buildTree, toVueRouter4 } from 'unrouting'\n\nconst tree = buildTree([\n  'pages/index.vue',\n  'pages/about.vue',\n  'pages/users/[id].vue',\n  'pages/users.vue',\n  'pages/[...slug].vue',\n], { roots: ['pages/'] })\n\nconst routes = toVueRouter4(tree)\n// [\n//   { name: 'index', path: '/', file: 'pages/index.vue', children: [] },\n//   { name: 'about', path: '/about', file: 'pages/about.vue', children: [] },\n//   { name: 'users', path: '/users', file: 'pages/users.vue', children: [\n//     { name: 'users-id', path: ':id()', file: 'pages/users/[id].vue', children: [] },\n//   ]},\n//   { name: 'slug', path: '/:slug(.*)*', file: 'pages/[...slug].vue', children: [] },\n// ]\n```\n\n### Nuxt-like usage with layers\n\n```js\nimport { buildTree, toVueRouter4 } from 'unrouting'\n\n// Files from app + layer directories with priority\nconst tree = buildTree([\n  { path: 'pages/index.vue', priority: 0 }, // app layer (wins on collision)\n  { path: 'pages/dashboard.vue', priority: 0 },\n  { path: 'pages/dashboard/settings.vue', priority: 0 },\n  { path: 'layer/pages/dashboard/analytics.vue', priority: 1 }, // extending layer\n  { path: 'layer/pages/index.vue', priority: 1 }, // overridden by app layer\n], {\n  roots: ['pages/', 'layer/pages/'],\n  extensions: ['.vue'],\n  modes: ['client', 'server'],\n  warn: msg => console.warn(msg),\n})\n\nconst routes = toVueRouter4(tree, {\n  onDuplicateRouteName: (name, file, existingFile) => {\n    console.warn(`Duplicate route name \"${name}\": ${file} and ${existingFile}`)\n  },\n})\n```\n\n### Emitting to different formats\n\nAll emitters accept a `RouteTree`:\n\n```js\nimport { buildTree, toRegExp, toRou3, toVueRouter4 } from 'unrouting'\n\nconst tree = buildTree(['users/[id]/posts/[slug].vue'])\n\n// Vue Router 4 – nested routes with names, files, children\nconst vueRoutes = toVueRouter4(tree)\n// [{ name: 'users-id-posts-slug', path: '/users/:id()/posts/:slug()', file: '...', children: [] }]\n\n// rou3/Nitro – flat route patterns\nconst rou3Routes = toRou3(tree)\n// [{ path: '/users/:id/posts/:slug', file: '...' }]\n\n// RegExp – matcher patterns with named groups\nconst regexpRoutes = toRegExp(tree)\n// [{ pattern: /^\\/users\\/(?<id>[^/]+)\\/posts\\/(?<slug>[^/]+)\\/?$/, keys: ['id', 'slug'], file: '...' }]\n```\n\n### Incremental updates (dev server)\n\nThe route tree is mutable. Instead of rebuilding everything when a file changes, use `addFile` and `removeFile` to update the tree in place – avoiding the cost of re-parsing all files and reconstructing the tree from scratch on every change.\n\n```js\nimport { addFile, buildTree, removeFile, toVueRouter4 } from 'unrouting'\n\nconst opts = { roots: ['pages/'], extensions: ['.vue'] }\n\n// Build once at startup\nconst tree = buildTree(initialFiles, opts)\nlet routes = toVueRouter4(tree)\n\n// On file add/remove (e.g., from a watcher callback)\naddFile(tree, 'pages/new-page.vue', opts)\nroutes = toVueRouter4(tree)\n\nremoveFile(tree, 'pages/old-page.vue')\nroutes = toVueRouter4(tree)\n\n// Rename = remove + add\nremoveFile(tree, 'pages/old-name.vue')\naddFile(tree, 'pages/new-name.vue', opts)\nroutes = toVueRouter4(tree)\n```\n\n`addFile` supports the same `InputFile` format as `buildTree` for layer priority:\n\n```js\naddFile(tree, { path: 'layer/pages/about.vue', priority: 1 }, opts)\n```\n\n### Standalone parsing and segment conversion\n\nIf you don't need the full tree pipeline – e.g., you already have resolved routes and only need to convert individual path segments or strings to Vue Router syntax – you can use the parse + convert functions directly:\n\n```js\nimport { parsePath, parseSegment, toVueRouterPath, toVueRouterSegment } from 'unrouting'\n\n// Parse a full file path\nconst [result] = parsePath(['users/[id]/profile.vue'])\n// {\n//   file: 'users/[id]/profile.vue',\n//   segments: [\n//     [{ type: 'static', value: 'users' }],\n//     [{ type: 'dynamic', value: 'id' }],\n//     [{ type: 'static', value: 'profile' }],\n//   ],\n// }\n\n// Convert parsed segments to a Vue Router path\ntoVueRouterPath(result.segments) // => '/users/:id()/profile'\n\n// Parse and convert a single segment (e.g., i18n per-locale route path)\nconst tokens = parseSegment('[...slug]')\n// [{ type: 'catchall', value: 'slug' }]\ntoVueRouterSegment(tokens) // => ':slug(.*)*'\n```\n\n## Supported patterns\n\n| Pattern | Example | Description |\n|---|---|---|\n| Static | `about.vue` | Static route segment |\n| Index | `index.vue` | Index page (maps to `/`) |\n| Dynamic | `[slug].vue` | Required parameter |\n| Optional | `[[slug]].vue` | Optional parameter |\n| Catchall | `[...slug].vue` | Catch-all (zero or more segments) |\n| Repeatable | `[slug]+.vue` | One or more segments |\n| Optional repeatable | `[[slug]]+.vue` | Zero or more segments |\n| Group | `(admin)/dashboard.vue` | Route group (transparent to path, stored in meta) |\n| Mixed | `prefix-[slug]-suffix.vue` | Static and dynamic in one segment |\n| Nested | `parent.vue` + `parent/child.vue` | Parent layout with child routes |\n| Named views | `index@sidebar.vue` | Vue Router named view slots |\n| Modes | `page.client.vue` | Mode variants (configurable suffixes) |\n\n## API\n\n### `buildTree(input, options?)`\n\nBuild a route tree from file paths. Accepts raw strings, `InputFile[]` (with priority), or pre-parsed `ParsedPath[]`.\n\n```ts\nfunction buildTree(\n  input: string[] | InputFile[] | ParsedPath[],\n  options?: BuildTreeOptions\n): RouteTree\n\ninterface InputFile {\n  path: string\n  /** Lower number = higher priority. Default: 0 */\n  priority?: number\n}\n```\n\n**Options** (extends `ParsePathOptions`):\n\n| Option | Type | Description |\n|---|---|---|\n| `roots` | `string[]` | Root paths to strip (e.g., `['pages/', 'layer/pages/']`) |\n| `extensions` | `string[]` | File extensions to strip (default: strip all) |\n| `modes` | `string[]` | Mode suffixes to detect (e.g., `['client', 'server']`) |\n| `warn` | `(msg: string) => void` | Warning callback for invalid characters in dynamic params |\n| `duplicateStrategy` | `'first-wins' \\| 'last-wins' \\| 'error'` | How to handle duplicate paths (default: `'first-wins'`) |\n\nWhen files from different layers collide at the same tree position, the file with the lowest `priority` number wins regardless of insertion order.\n\n### `addFile(tree, filePath, options?)`\n\nAdd a single file to an existing route tree in place. Parses the file and inserts it, avoiding a full rebuild. Accepts a plain string or `InputFile` with priority.\n\n```ts\nfunction addFile(\n  tree: RouteTree,\n  filePath: string | InputFile,\n  options?: BuildTreeOptions\n): void\n```\n\n### `removeFile(tree, filePath)`\n\nRemove a file from an existing route tree by its original file path. Prunes empty structural nodes left behind. Returns `true` if the file was found and removed.\n\n```ts\nfunction removeFile(tree: RouteTree, filePath: string): boolean\n```\n\n### `toVueRouter4(tree, options?)`\n\nEmit Vue Router 4 route definitions from a tree. Handles nested routes, names, index promotion, structural collapse, groups, catchall optimisation, route ordering, named views, and mode variants.\n\n```ts\nfunction toVueRouter4(tree: RouteTree, options?: VueRouterEmitOptions): VueRoute[]\n\ninterface VueRoute {\n  name?: string\n  path: string\n  file?: string\n  /** Named view components. Only present when multiple views exist. */\n  components?: Record<string, string>\n  /** Mode variants. Only present when mode files exist. */\n  modes?: string[]\n  children: VueRoute[]\n  meta?: Record<string, unknown>\n}\n\ninterface VueRouterEmitOptions {\n  /** Custom name generator. Receives raw `/`-separated name, returns final name. */\n  getRouteName?: (rawName: string) => string\n  /** Called when two routes produce the same name. */\n  onDuplicateRouteName?: (name: string, file: string, existingFile: string) => void\n}\n```\n\nRoutes are sorted by segment priority within each level: static segments first, then dynamic, optional, and catchall last.\n\n### `toRou3(tree)`\n\nEmit rou3/Nitro route patterns (rou3 1.0 syntax) from a tree.\n\n```ts\nfunction toRou3(tree: RouteTree): Rou3Route[]\n\ninterface Rou3Route {\n  path: string\n  file: string\n}\n```\n\n### `vueRouterToRou3(path, options?)`\n\nConvert a compiled Vue Router path string (e.g. a route definition's `path`) into one or more rou3 patterns. Useful when you already have resolved Vue Router routes (not files) and need to feed them to rou3/Nitro, for example when a module rewrites paths at runtime.\n\n```ts\nfunction vueRouterToRou3(path: string, options?: VueRouterToRou3Options): VueRouterToRou3Result\n\ninterface VueRouterToRou3Options {\n  /** Expand finite alternation params (`:locale(de|fr)`) into concrete paths. @default true */\n  expand?: boolean\n  /** Max paths a single input may expand to before falling back to a dynamic param. Must be a positive integer or a TypeError is thrown. @default 100 */\n  maxExpansions?: number\n  /** Collapse each result into a canonical pattern of static segments, positional `:_0` params and at most one `**`. @default false */\n  collapse?: boolean\n}\n\ninterface VueRouterToRou3Result {\n  /** The converted rou3 patterns. */\n  patterns: string[]\n  /** One entry per lossy or widening conversion step; empty when the conversion is faithful. */\n  issues: VueRouterToRou3Issue[]\n}\n```\n\nPatterns use rou3 1.0 syntax. Params carrying a finite alternation regexp are expanded into concrete paths; other custom regexps are preserved as rou3 param constraints on plain and optional params. They're dropped on repeatable params, when the regexp contains `/`, and when it uses an anchor, backreference, group, or class set operation, because rou3 can't represent these as constraints. Param names are made valid and unique for rou3 (`/:id/:id` becomes `/:id/:id_1`). rou3 allows one catch-all per route, so a path with several catch-alls (or a repeatable param that shares its segment) collapses into `**` from the first of them, with a `collapsed` issue.\n\n```ts\nimport { vueRouterToRou3 } from 'unrouting'\n\nvueRouterToRou3('/:locale(de|fr)/account/verify').patterns\n// => ['/de/account/verify', '/fr/account/verify']\n\nvueRouterToRou3('/users/:id(\\\\d+)').patterns\n// => ['/users/:id(\\\\d+)']\n\nvueRouterToRou3('/:pathMatch(.*)*').patterns\n// => ['/:pathMatch(.*)']\n```\n\nWith `collapse: true`, each path becomes a canonical pattern built from static segments, positionally named single-segment params (`:_0`, `:_1`, and so on), and at most one trailing `**` catch-all. This is useful for route-rule keys and other targets that care about the shape of a route rather than its param names: `/products/:id` and `/products/:slug` both collapse to `/products/:_0`. A bare whole-segment param (`:id`) maps exactly to a single-segment param, so no issue is reported and later segments stay intact. A bare optional param expands into both variants (`/foo/:id?/bar` becomes `/foo/bar` and `/foo/:_0/bar`). Anything else (a regexp constraint, a partial segment like `prefix-:id`, a repeatable param, or optional params whose variants would exceed `maxExpansions`) collapses into a `**` catch-all from that segment onwards, with a `collapsed` issue. Enumerable params are still expanded first, so the pattern stays as narrow as possible. The output uses no wildcards or modifiers besides `**`, so it matches the same paths in rou3 0.x, rou3 1.x and radix3, except for static text that has to be escaped (`:`, `(`, `)`, `{`, `}`, `*`), which radix3 does not unescape.\n\n```ts\nvueRouterToRou3('/products/:id/edit', { collapse: true }).patterns\n// => ['/products/:_0/edit']\n\nvueRouterToRou3('/blog/:slug?', { collapse: true }).patterns\n// => ['/blog', '/blog/:_0']\n\nvueRouterToRou3('/users/:id(\\\\d+)/edit', { collapse: true }).patterns\n// => ['/users/**']\n\nvueRouterToRou3('/:locale(de|fr)/account/:id', { collapse: true }).patterns\n// => ['/de/account/:_0', '/fr/account/:_0']\n\nvueRouterToRou3('/static/path', { collapse: true }).patterns\n// => ['/static/path']\n```\n\nConversions are best-effort: a collapsed catch-all matches more than the original path, repeatable params lose their regexp constraint, and huge alternations fall back to plain dynamic params. Every such step is recorded in `issues` so callers can surface them to their users:\n\n```ts\nconst { patterns, issues } = vueRouterToRou3('/products/:id(\\\\d+)', { collapse: true })\n// patterns => ['/products/**']\n// issues => [{ type: 'collapsed', message: 'Collapsed \"/products/:id(\\\\d+)\" at segment \":id(\\\\d+)\" into a `**` catch-all, ...' }]\n```\n\n### `toRegExp(tree)`\n\nEmit RegExp matchers from a tree.\n\n```ts\nfunction toRegExp(tree: RouteTree): RegExpRoute[]\n\ninterface RegExpRoute {\n  pattern: RegExp\n  keys: string[]\n  file: string\n}\n```\n\n### `rou3PatternToURLPattern(pattern, options?)`\n\nConvert a single rou3/Nitro route pattern into a URLPattern pathname pattern (e.g. for a [Speculation Rules](https://developer.mozilla.org/en-US/docs/Web/API/Speculation_Rules_API) `href_matches` rule, or `new URLPattern({ pathname })`). rou3 aligns its syntax with URLPattern, so most tokens (`:name`, `:name(regex)`, `:name?`, `:name+`, `*`, `(regex)`, `{...}`) pass through unchanged. Only rou3 `**`/`**:name` (catch-all) has no URLPattern equivalent and becomes `*`.\n\n```ts\nfunction rou3PatternToURLPattern(pattern: string, options?: { segment?: 'strict' | 'loose', wildcard?: 'rest' | 'segment' }): {\n  pattern: string\n  issues: Rou3ToURLPatternIssue[]\n}\n\nrou3PatternToURLPattern('/blog/**').pattern // => '/blog/*'\nrou3PatternToURLPattern('/users/:id').pattern // => '/users/:id'\nrou3PatternToURLPattern('/users/:id(\\\\d+)').pattern // => '/users/:id(\\\\d+)'\n```\n\nPass `{ segment: 'loose' }` to collapse single-segment tokens (`:name`, `(regex)`) to `*` instead, matching Nuxt's historical inline conversion. This over-matches (a single `*` matches across `/`), so each collapse is recorded in `issues`:\n\n```ts\nconst { pattern, issues } = rou3PatternToURLPattern('/users/:id', { segment: 'loose' })\n// pattern => '/users/*'\n// issues => [{ type: 'widened', param: 'id', message: 'Widened \":id\" ...' }]\n```\n\nIn rou3 0.x and radix3 (Nitro v2), a bare `*` matches a single segment rather than the rest of the path. Pass `{ wildcard: 'segment' }` to convert patterns written for those:\n\n```ts\nrou3PatternToURLPattern('/blog/*', { wildcard: 'segment' }).pattern // => '/blog/([^\\/]*)'\n```\n\n### `toVueRouterSegment(tokens, options?)`\n\nConvert a single parsed segment (an array of tokens returned by `parseSegment`) into a Vue Router 4 path segment string. Useful for modules that already have resolved routes and only need segment-level path conversion (e.g., `@nuxtjs/i18n` converting per-locale custom paths).\n\n```ts\nfunction toVueRouterSegment(\n  tokens: ParsedPathSegmentToken[],\n  options?: ToVueRouterSegmentOptions\n): string\n\ninterface ToVueRouterSegmentOptions {\n  /**\n   * Whether non-index segments follow this one.\n   * When true, catchall uses ([^/]*)*; when false (default), uses (.*)*\n   */\n  hasSucceeding?: boolean\n}\n```\n\n```js\nimport { parseSegment, toVueRouterSegment } from 'unrouting'\n\ntoVueRouterSegment(parseSegment('[id]')) // => ':id()'\ntoVueRouterSegment(parseSegment('[[opt]]')) // => ':opt?'\ntoVueRouterSegment(parseSegment('[...slug]')) // => ':slug(.*)*'\ntoVueRouterSegment(parseSegment('prefix-[slug]')) // => 'prefix-:slug()'\n\n// i18n use case – parse a custom locale path segment\nconst tokens = parseSegment('[foo]_[bar]:[...buz]_buz_[[qux]]')\nconst path = `/${toVueRouterSegment(tokens)}`\n// => '/:foo()_:bar()\\::buz(.*)*_buz_:qux?'\n```\n\n### `toVueRouterPath(segments)`\n\nConvert an array of parsed path segments into a full Vue Router 4 path string. Automatically determines `hasSucceeding` per segment so that mid-path catchalls use the restrictive `([^/]*)*` pattern and terminal catchalls use `(.*)*`.\n\n```ts\nfunction toVueRouterPath(segments: ParsedPathSegment[]): string\n```\n\n```js\nimport { parsePath, toVueRouterPath } from 'unrouting'\n\ntoVueRouterPath(parsePath(['users/[id]/posts.vue'])[0].segments)\n// => '/users/:id()/posts'\n\ntoVueRouterPath(parsePath(['[...slug]/suffix.vue'])[0].segments)\n// => '/:slug([^/]*)*/suffix'  (mid-path catchall auto-detected)\n\ntoVueRouterPath(parsePath(['prefix/[...slug].vue'])[0].segments)\n// => '/prefix/:slug(.*)*'     (terminal catchall)\n```\n\n### `parsePath(filePaths, options?)`\n\nParse file paths into segments. Standalone – does not build a tree.\n\n```ts\nfunction parsePath(filePaths: string[], options?: ParsePathOptions): ParsedPath[]\n\ninterface ParsedPath {\n  file: string\n  segments: ParsedPathSegment[]\n  meta?: { modes?: string[], name?: string }\n}\n```\n\n### `compileParsePath(options?)`\n\nPre-compile parsing options into a reusable function. Useful in hot paths (e.g., dev server file watchers) where `parsePath` would otherwise reconstruct the same regexes on every call.\n\n```ts\nfunction compileParsePath(options?: ParsePathOptions): CompiledParsePath\n\ninterface CompiledParsePath {\n  (filePaths: string[]): ParsedPath[]\n}\n```\n\nReturns a callable with the same signature as `parsePath` (minus the options argument). The regexes for root stripping, extension matching, and mode detection are built once at compile time.\n\n```js\nimport { addFile, buildTree, compileParsePath, toVueRouter4 } from 'unrouting'\n\nconst opts = { roots: ['pages/'], modes: ['client', 'server'] }\n\n// Compile once at startup\nconst parse = compileParsePath(opts)\nconst tree = buildTree(initialFiles, opts)\n\n// In a file watcher callback — no regex re-compilation\naddFile(tree, 'pages/new-page.vue', parse)\nconst routes = toVueRouter4(tree)\n```\n\nThe compiled function can be passed directly to `addFile` as the options argument:\n\n```js\n// These are equivalent, but the compiled version avoids re-building regexes:\naddFile(tree, file, parse) // pre-compiled (fast)\naddFile(tree, file, opts) // raw options (re-compiles each call)\n```\n\n### `parseSegment(segment, absolutePath?, warn?)`\n\nParse a single filesystem segment into typed tokens. Useful for modules that need to parse custom paths (e.g., i18n locale-specific routes).\n\n```ts\nfunction parseSegment(\n  segment: string,\n  absolutePath?: string,\n  warn?: (message: string) => void\n): ParsedPathSegmentToken[]\n\n// Token types: 'static' | 'dynamic' | 'optional' | 'catchall' |\n//              'repeatable' | 'optional-repeatable' | 'group'\n```\n\n### `walkTree(tree, visitor)`\n\nWalk all nodes depth-first.\n\n```ts\nfunction walkTree(\n  tree: RouteTree,\n  visitor: (node: RouteNode, depth: number, parent: RouteNode | null) => void\n): void\n```\n\n### `isPageNode(node)`\n\nCheck if a node has files attached (page node vs structural node).\n\n```ts\nfunction isPageNode(node: RouteNode): boolean\n```\n\n## How nesting works\n\nThe tree distinguishes between **page nodes** (have files) and **structural nodes** (directory-only, no files):\n\n- **Page nodes** create nesting boundaries – children get relative paths\n- **Structural nodes** collapse – their path segment is prepended to descendants\n\n```text\nparent.vue + parent/child.vue\n  → { path: '/parent', children: [{ path: 'child' }] }\n\nparent/child.vue  (no parent.vue)\n  → { path: '/parent/child' }  (structural 'parent' collapses)\n```\n\n`index.vue` promotes a structural directory into a page node:\n\n```text\nusers/index.vue + users/[id].vue\n  → { path: '/users', file: 'users/index.vue', children: [{ path: ':id()' }] }\n```\n\nRoute groups `(name)` are transparent – they don't affect paths or nesting, but are stored in `meta.groups`.\n\n## Development\n\n- Clone this repository\n- Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable`\n- Install dependencies using `pnpm install`\n- Run interactive tests using `pnpm dev`\n\n## License\n\nMade with ❤️\n\nPublished under [MIT License](./LICENCE).\n\n<!-- Badges -->\n\n[npm-version-src]: https://npmx.dev/api/registry/badge/version/unrouting\n[npm-version-href]: https://npmx.dev/package/unrouting\n[npm-downloads-src]: https://npmx.dev/api/registry/badge/downloads/unrouting\n[npm-downloads-href]: https://npmx.dev/package/unrouting\n[codecov-src]: https://img.shields.io/codecov/c/gh/unjs/unrouting/main?style=flat&colorA=18181B&colorB=F0DB4F\n[codecov-href]: https://codecov.io/gh/unjs/unrouting\n[bundle-src]: https://img.shields.io/bundlephobia/minzip/unrouting?style=flat&colorA=18181B&colorB=F0DB4F\n[bundle-href]: https://bundlephobia.com/result?p=unrouting\n[license-src]: https://img.shields.io/github/license/unjs/unrouting.svg?style=flat&colorA=18181B&colorB=F0DB4F\n[license-href]: https://github.com/unjs/unrouting/blob/main/LICENSE\n[jsdocs-src]: https://img.shields.io/badge/jsDocs.io-reference-18181B?style=flat&colorA=18181B&colorB=F0DB4F\n[jsdocs-href]: https://www.jsdocs.io/package/unrouting\n","readmeFilename":"README.md"}