├── .editorconfig
├── .gitattributes
├── .github
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── FUNDING.yml
├── ISSUE_TEMPLATE.md
├── PULL_REQUEST_TEMPLATE.md
├── SUPPORT.md
└── workflows
│ └── ci.yml
├── .gitignore
├── .vscode
├── extensions.json
├── launch.json
└── settings.json
├── CHANGELOG.md
├── LICENSE.txt
├── README.md
├── docs
├── README.md
├── api.md
├── getting-started.md
└── redirects.md
├── eslint.config.mjs
├── logo.svg
├── package-lock.json
├── package.json
├── prettier.config.mjs
├── src
├── generate-urls.test.ts
├── generate-urls.ts
├── universal-router-sync.test.ts
├── universal-router-sync.ts
├── universal-router.test.ts
└── universal-router.ts
├── tools
├── README.md
├── build.js
├── install.js
├── tsconfig.cjs.json
└── tsconfig.esm.json
├── tsconfig.json
└── vite.config.mjs
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # http://editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 |
9 | indent_style = space
10 | indent_size = 2
11 | end_of_line = lf
12 | charset = utf-8
13 | trim_trailing_whitespace = true
14 | insert_final_newline = true
15 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Automatically normalize line endings for all text-based files
2 | # https://git-scm.com/docs/gitattributes#_end_of_line_conversion
3 |
4 | * text=auto
5 |
6 | # For the following file types, normalize line endings to LF on
7 | # checkin and prevent conversion to CRLF when they are checked out
8 | # (this is required in order to prevent newline related issues like,
9 | # for example, after the build script is run)
10 |
11 | .* text eol=lf
12 | *.js text eol=lf
13 | *.json text eol=lf
14 | *.md text eol=lf
15 | *.svg text eol=lf
16 | *.ts text eol=lf
17 | *.txt text eol=lf
18 | *.yml text eol=lf
19 |
--------------------------------------------------------------------------------
/.github/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | - Using welcoming and inclusive language
12 | - Being respectful of differing viewpoints and experiences
13 | - Gracefully accepting constructive criticism
14 | - Focusing on what is best for the community
15 | - Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | - The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | - Trolling, insulting/derogatory comments, and personal or political attacks
21 | - Public or private harassment
22 | - Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | - Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Our Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at support@kriasoft.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version]
44 |
45 | [homepage]: https://contributor-covenant.org
46 | [version]: https://contributor-covenant.org/version/1/4/
47 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to Universal Router
2 |
3 | ♥ [Universal Router](https://github.com/kriasoft/universal-router) and want to
4 | get involved? Thanks! There are plenty of ways you can help!
5 |
6 | Please take a moment to review this document in order to make the contribution
7 | process easy and effective for everyone involved.
8 |
9 | Following these guidelines helps to communicate that you respect the time of
10 | the developers managing and developing this open source project. In return,
11 | they should reciprocate that respect in addressing your issue or assessing
12 | patches and features.
13 |
14 | ## Using the issue tracker
15 |
16 | The [issue tracker](https://github.com/kriasoft/universal-router/issues) is
17 | the preferred channel for [bug reports](#bugs), [features requests](#features)
18 | and [submitting pull requests](#pull-requests), but please respect the following
19 | restrictions:
20 |
21 | - Please **do not** use the issue tracker for personal support requests (use
22 | [Gitter](https://gitter.im/kriasoft/universal-router),
23 | [HackHands](https://hackhands.com/koistya) or
24 | [Codementor](https://www.codementor.io/koistya)).
25 |
26 | - Please **do not** derail or troll issues. Keep the discussion on topic and
27 | respect the opinions of others.
28 |
29 | - Please **do not** open issues or pull requests regarding the code in
30 | [`path-to-regexp`](https://github.com/pillarjs/path-to-regexp)
31 | (open them in their respective repositories).
32 |
33 |
34 |
35 | ## Bug reports
36 |
37 | A bug is a _demonstrable problem_ that is caused by the code in the repository.
38 | Good bug reports are extremely helpful - thank you!
39 |
40 | Guidelines for bug reports:
41 |
42 | 1. **Use the GitHub issue search** — check if the issue has already been
43 | reported.
44 |
45 | 2. **Check if the issue has been fixed** — try to reproduce it using the
46 | latest `master` or development branch in the repository.
47 |
48 | 3. **Isolate the problem** — ideally create a [reduced test
49 | case](https://css-tricks.com/reduced-test-cases/) and a live example.
50 |
51 | A good bug report shouldn't leave others needing to chase you up for more
52 | information. Please try to be as detailed as possible in your report. What is
53 | your environment? What steps will reproduce the issue? What browser(s) and OS
54 | experience the problem? What would you expect to be the outcome? All these
55 | details will help people to fix any potential bugs.
56 |
57 | Example:
58 |
59 | > Short and descriptive example bug report title
60 | >
61 | > A summary of the issue and the browser/OS environment in which it occurs. If
62 | > suitable, include the steps required to reproduce the bug.
63 | >
64 | > 1. This is the first step
65 | > 2. This is the second step
66 | > 3. Further steps, etc.
67 | >
68 | > `` - a link to the reduced test case
69 | >
70 | > Any other information you want to share that is relevant to the issue being
71 | > reported. This might include the lines of code that you have identified as
72 | > causing the bug, and potential solutions (and your opinions on their
73 | > merits).
74 |
75 |
76 |
77 | ## Feature requests
78 |
79 | Feature requests are welcome. But take a moment to find out whether your idea
80 | fits with the scope and aims of the project. It's up to _you_ to make a strong
81 | case to convince the project's developers of the merits of this feature. Please
82 | provide as much detail and context as possible.
83 |
84 |
85 |
86 | ## Pull requests
87 |
88 | Good pull requests - patches, improvements, new features - are a fantastic
89 | help. They should remain focused in scope and avoid containing unrelated
90 | commits.
91 |
92 | **Please ask first** before embarking on any significant pull request (e.g.
93 | implementing features, refactoring code, porting to a different language),
94 | otherwise you risk spending a lot of time working on something that the
95 | project's developers might not want to merge into the project.
96 |
97 | Please adhere to the coding conventions used throughout a project (indentation,
98 | accurate comments, etc.) and any other requirements (such as test coverage).
99 |
100 | Adhering to the following process is the best way to get your work
101 | included in the project:
102 |
103 | 1. [Fork](https://help.github.com/articles/fork-a-repo/) the project, clone your
104 | fork, and configure the remotes:
105 |
106 | ```bash
107 | # Clone your fork of the repo into the current directory
108 | git clone https://github.com//universal-router.git
109 | # Navigate to the newly cloned directory
110 | cd universal-router
111 | # Assign the original repo to a remote called "upstream"
112 | git remote add upstream https://github.com/kriasoft/universal-router.git
113 | ```
114 |
115 | 2. If you cloned a while ago, get the latest changes from upstream:
116 |
117 | ```bash
118 | git checkout master
119 | git pull upstream master
120 | ```
121 |
122 | 3. Create a new topic branch (off the main project development branch) to
123 | contain your feature, change, or fix:
124 |
125 | ```bash
126 | git checkout -b
127 | ```
128 |
129 | 4. Commit your changes in logical chunks. Please adhere to these [git commit
130 | message guidelines](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
131 | or your code is unlikely be merged into the main project. Use Git's
132 | [interactive rebase](https://help.github.com/articles/about-git-rebase/)
133 | feature to tidy up your commits before making them public.
134 |
135 | 5. Locally merge (or rebase) the upstream development branch into your topic branch:
136 |
137 | ```bash
138 | git pull [--rebase] upstream master
139 | ```
140 |
141 | 6. Push your topic branch up to your fork:
142 |
143 | ```bash
144 | git push origin
145 | ```
146 |
147 | 7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/)
148 | with a clear title and description.
149 |
150 | **IMPORTANT**: By submitting a patch, you agree to allow the project
151 | owners to license your work under the terms of the
152 | [MIT License](https://github.com/kriasoft/universal-router/blob/master/LICENSE.txt).
153 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | open_collective: universal-router
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | **I'm submitting a ...**
2 |
3 |
4 |
5 | - [ ] bug report
6 | - [ ] feature request
7 | - [ ] other (Please do not submit support requests here (below))
8 |
9 | ## Notes:
10 |
11 | - Please **do not** use the issue tracker for personal support requests (use
12 | [Gitter](https://gitter.im/kriasoft/universal-router),
13 | [HackHands](https://hackhands.com/koistya) or
14 | [Codementor](https://www.codementor.io/koistya)).
15 |
16 | - Please **do not** derail or troll issues. Keep the discussion on topic and
17 | respect the opinions of others.
18 |
19 | - Please **do not** open issues or pull requests regarding the code in
20 | [`path-to-regexp`](https://github.com/pillarjs/path-to-regexp)
21 | (open them in their respective repositories).
22 |
23 | ## Bug reports
24 |
25 | A bug is a _demonstrable problem_ that is caused by the code in the repository.
26 | Good bug reports are extremely helpful - thank you!
27 |
28 | Guidelines for bug reports:
29 |
30 | 1. **Use the GitHub issue search** — check if the issue has already been
31 | reported.
32 |
33 | 2. **Check if the issue has been fixed** — try to reproduce it using the
34 | latest `master` or development branch in the repository.
35 |
36 | 3. **Isolate the problem** — ideally create a [reduced test
37 | case](https://css-tricks.com/reduced-test-cases/) and a live example.
38 |
39 | A good bug report shouldn't leave others needing to chase you up for more
40 | information. Please try to be as detailed as possible in your report. What is
41 | your environment? What steps will reproduce the issue? What browser(s) and OS
42 | experience the problem? What would you expect to be the outcome? All these
43 | details will help people to fix any potential bugs.
44 |
45 | Example:
46 |
47 | > Short and descriptive example bug report title
48 | >
49 | > A summary of the issue and the browser/OS environment in which it occurs. If
50 | > suitable, include the steps required to reproduce the bug.
51 | >
52 | > 1. This is the first step
53 | > 2. This is the second step
54 | > 3. Further steps, etc.
55 | >
56 | > `` - a link to the reduced test case
57 | >
58 | > Any other information you want to share that is relevant to the issue being
59 | > reported. This might include the lines of code that you have identified as
60 | > causing the bug, and potential solutions (and your opinions on their
61 | > merits).
62 |
63 | ## Feature requests
64 |
65 | Feature requests are welcome. But take a moment to find out whether your idea
66 | fits with the scope and aims of the project. It's up to _you_ to make a strong
67 | case to convince the project's developers of the merits of this feature. Please
68 | provide as much detail and context as possible.
69 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Types of changes
2 |
3 |
4 |
5 | - [ ] Bug fix (non-breaking change which fixes an issue)
6 | - [ ] New feature (non-breaking change which adds functionality)
7 | - [ ] Breaking change (fix or feature that would cause existing functionality to change)
8 |
9 | ## Checklist:
10 |
11 |
12 |
13 |
14 | - [ ] My code follows the code style of this project.
15 | - [ ] My change requires a change to the documentation.
16 | - [ ] I have updated the documentation accordingly.
17 | - [ ] I have read the **CONTRIBUTING** document.
18 | - [ ] I have added tests to cover my changes.
19 | - [ ] All new and existing tests passed.
20 |
--------------------------------------------------------------------------------
/.github/SUPPORT.md:
--------------------------------------------------------------------------------
1 | # Support
2 |
3 | For personal support requests with Universal Router please use
4 | [Gitter](https://gitter.im/kriasoft/universal-router),
5 | [HackHands](https://hackhands.com/koistya) or
6 | [Codementor](https://www.codementor.io/koistya).
7 |
8 | Please check the respective repository for support regarding the code in
9 | [`path-to-regexp`](https://github.com/pillarjs/path-to-regexp).
10 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Node.js CI
2 | on: [push, pull_request]
3 | jobs:
4 | build:
5 | runs-on: ubuntu-latest
6 | strategy:
7 | matrix:
8 | node-version: [18.x, 20.x, 22.x]
9 | steps:
10 | - name: Checkout
11 | uses: actions/checkout@v4
12 | - name: Use Node.js ${{ matrix.node-version }}
13 | uses: actions/setup-node@v4
14 | with:
15 | node-version: ${{ matrix.node-version }}
16 | - name: Install dependencies
17 | run: npm ci
18 | - name: Run Tests
19 | run: npm run coverage -- --reporter=junit --outputFile=test-report.junit.xml
20 | - name: Lint code
21 | run: npm run lint
22 | - name: Check types
23 | run: npm run typecheck
24 | - name: Check code formatting
25 | run: npm run formatcheck
26 | - name: Build
27 | run: npm run build
28 | - name: Upload coverage to Codecov
29 | uses: codecov/codecov-action@v4
30 | with:
31 | token: ${{ secrets.CODECOV_TOKEN }}
32 | - name: Upload test results to Codecov
33 | if: ${{ !cancelled() }}
34 | uses: codecov/test-results-action@v1
35 | with:
36 | token: ${{ secrets.CODECOV_TOKEN }}
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files
2 |
3 | # Dependencies
4 | node_modules/
5 | src/path-to-regexp.ts
6 |
7 | # Compiled output
8 | /dist/
9 |
10 | # Test coverage
11 | /coverage/
12 |
13 | # Logs
14 | npm-debug.log*
15 |
16 | # Editors and IDEs
17 | .idea/
18 |
19 | # Misc
20 | .DS_Store
21 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
4 | "recommendations": [
5 | "EditorConfig.EditorConfig",
6 | "esbenp.prettier-vscode",
7 | "dbaeumer.vscode-eslint"
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | // https://vitest.dev/guide/debugging
8 | {
9 | "type": "node",
10 | "request": "launch",
11 | "name": "Debug Current Test File",
12 | "autoAttachChildProcesses": true,
13 | "skipFiles": ["/**", "**/node_modules/**"],
14 | "program": "${workspaceRoot}/node_modules/vitest/vitest.mjs",
15 | "args": ["run", "${relativeFile}"],
16 | "smartStep": true,
17 | "console": "integratedTerminal"
18 | }
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "typescript.tsdk": "./node_modules/typescript/lib",
3 | "editor.rulers": [100, 120],
4 | "[javascript]": { "editor.formatOnSave": false },
5 | "[typescript]": { "editor.formatOnSave": false },
6 | "tslint.enable": false,
7 | "editor.codeActionsOnSave": {
8 | "source.fixAll.eslint": "explicit"
9 | },
10 | "cSpell.words": ["Kriasoft"]
11 | }
12 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Universal Router Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
6 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7 |
8 | ## [10.0.0] - 2025-05-05
9 |
10 | - Updated [path-to-regexp](https://www.npmjs.com/package/path-to-regexp) from v6.2.0 to v8.2.0.
11 | See [changelog](https://github.com/pillarjs/path-to-regexp/releases)
12 | (BREAKING CHANGE [#218](https://github.com/kriasoft/universal-router/pull/218))
13 | - Since [Path To RegExp does not provide an ESM version](https://github.com/pillarjs/path-to-regexp/issues/346),
14 | it is now bundled into the Universal Router package:
15 | ```diff
16 | - const pathToRegexp = require('path-to-regexp')
17 | + import * as pathToRegexp from 'universal-router/path-to-regexp'
18 | ```
19 | - The import path for generating URLs has changed:
20 | ```diff
21 | - import generateUrls from 'universal-router/generateUrls'
22 | + import generateUrls from 'universal-router/generate-urls'
23 | ```
24 |
25 | ## [9.2.1] - 2024-11-22
26 |
27 | - Enable `noPropertyAccessFromIndexSignature` and `noUncheckedIndexedAccess` checks ([#216](https://github.com/kriasoft/universal-router/pull/216))
28 |
29 | ## [9.2.0] - 2023-06-23
30 |
31 | - Bump TypeScript to 4.9.5 and fix types ([#215](https://github.com/kriasoft/universal-router/pull/215))
32 |
33 | ## [9.1.0] - 2021-06-23
34 |
35 | - Add `uniqueRouteNameSep` option to `generateUrls(router, options)` to allow non-unique route names
36 | among different branches of nested routes and access them by uniquely generated name
37 | ([#194](https://github.com/kriasoft/universal-router/pull/194))
38 |
39 | ## [9.0.1] - 2020-03-11
40 |
41 | - Fix typings: `router.resolve()` and `context.next()` always return a promise now
42 | ([#187](https://github.com/kriasoft/universal-router/pull/187))
43 |
44 | ## [9.0.0] - 2020-02-27
45 |
46 | - Update [path-to-regexp](https://github.com/pillarjs/path-to-regexp) from v3 to v6, see
47 | [changelog](https://github.com/pillarjs/path-to-regexp/releases)
48 | (BREAKING CHANGE)
49 | - Remove `context.keys` (BREAKING CHANGE)
50 | - Migrate to [TypeScript](https://www.typescriptlang.org/)
51 | ([#183](https://github.com/kriasoft/universal-router/pull/183))
52 |
53 | ## [8.3.0] - 2019-09-17
54 |
55 | - Make `generateUrls` compatible with `UniversalRouterSync`
56 | ([#172](https://github.com/kriasoft/universal-router/pull/172))
57 |
58 | ## [8.2.1] - 2019-07-20
59 |
60 | - Fix `context.next()` to throw `Route not found` instead of `TypeError`
61 | ([#169](https://github.com/kriasoft/universal-router/pull/169))
62 |
63 | ## [8.2.0] - 2019-05-10
64 |
65 | - Improve TypeScript typings ([#167](https://github.com/kriasoft/universal-router/pull/167))
66 |
67 | ## [8.1.0] - 2019-02-20
68 |
69 | - Add [synchronous mode](https://github.com/kriasoft/universal-router/blob/v8.1.0/docs/api.md#synchronous-mode)
70 | as an add-on ([#164](https://github.com/kriasoft/universal-router/pull/164))
71 |
72 | ## [8.0.0] - 2019-01-15
73 |
74 | - Update [path-to-regexp](https://github.com/pillarjs/path-to-regexp) from v2.4.0 to v3.0.0, see
75 | [changelog](https://github.com/pillarjs/path-to-regexp/blob/4eee1e15ba72d93c996bac4ae649a846eb326562/History.md#300--2019-01-13)
76 | (BREAKING CHANGE [#161](https://github.com/kriasoft/universal-router/pull/161))
77 | - Add [TypeScript](https://www.typescriptlang.org/) typings
78 | ([#159](https://github.com/kriasoft/universal-router/pull/159))
79 |
80 | ## [7.0.0] - 2018-10-11
81 |
82 | - The router no longer mutate errors to avoid issues with non-extensible objects.
83 | (BREAKING CHANGE [#158](https://github.com/kriasoft/universal-router/pull/158)).
84 |
85 | **Migration from v6 to v7:**
86 |
87 | - If your code relies on `error.context` or `error.code` you still can access them
88 | using `errorHandler` option:
89 | ```js
90 | errorHandler(error, context) {
91 | const code = error.status || 500
92 | console.log(error, context, code)
93 | }
94 | ```
95 |
96 | ## [6.0.0] - 2018-02-06
97 |
98 | - No special configuration is required for your bundler anymore (say hi to [parcel.js](https://parceljs.org/)).
99 | - Add an option for global error handling ([#147](https://github.com/kriasoft/universal-router/pull/147)).
100 |
101 | **Migration from v5 to v6:**
102 |
103 | - Use `error.code` instead of `error.status` or `error.statusCode` for error handling.
104 |
105 | ## [5.1.0] - 2018-01-16
106 |
107 | - Allow any string to be a valid route name ([#145](https://github.com/kriasoft/universal-router/pull/145))
108 |
109 | ## [5.0.0] - 2017-10-30
110 |
111 | - Skip nested routes when a middleware route returns `null`
112 | (BREAKING CHANGE [#140](https://github.com/kriasoft/universal-router/pull/140))
113 |
114 | **Migration from v4 to v5:**
115 |
116 | - If you are using `resolveRoute` option for custom route handling logic then you need
117 | to return `undefined` instead of `null` in cases when a route should not match
118 | - Make sure that your middleware routes which return `null` are working as you expect,
119 | child routes are no longer executed in this case
120 |
121 | ## [4.3.0] - 2017-10-22
122 |
123 | - Update [path-to-regexp](https://github.com/pillarjs/path-to-regexp) from v2.0.0 to v2.1.0, see
124 | [changelog](https://github.com/pillarjs/path-to-regexp/blob/b0b9a92663059d7a7d40d81fa811f0d31e2ba877/History.md#210--2017-10-20)
125 | ([#137](https://github.com/kriasoft/universal-router/pull/137))
126 |
127 | ## [4.2.1] - 2017-10-06
128 |
129 | - Fix order of `context.keys` when they preserved from parent routes
130 | (i.e. keys order is the same as they appear in a url)
131 | ([#129](https://github.com/kriasoft/universal-router/pull/129))
132 |
133 | ## [4.2.0] - 2017-09-20
134 |
135 | - Correctly handle trailing slashes in paths of routes
136 | ([#124](https://github.com/kriasoft/universal-router/pull/124))
137 | If you are using trailing slashes in your paths, then the router will match urls only with trailing slashes:
138 | ```js
139 | const routes = [
140 | { path: '/posts', ... }, // matches both "/posts" and "/posts/"
141 | { path: '/posts/', ... }, // matches only "/posts/"
142 | ]
143 | ```
144 | - Generate url from first path for routes with an array of paths
145 | ([#124](https://github.com/kriasoft/universal-router/pull/124))
146 | ```js
147 | const router = new UniversalRouter({
148 | name: 'page',
149 | path: ['/one', '/two', /RegExp/], // only first path is used for url generation
150 | })
151 | const url = generateUrls(router)
152 | url('page') // => /one
153 | ```
154 |
155 | ## [4.1.0] - 2017-09-20
156 |
157 | - Support for using the same param name in array of paths ([#122](https://github.com/kriasoft/universal-router/pull/122))
158 |
159 | ```js
160 | const router = new UniversalRouter({
161 | path: ['/one/:parameter', '/two/:parameter'],
162 | action: (context) => context.params,
163 | })
164 |
165 | router.resolve('/one/a') // => { parameter: 'a' }
166 | router.resolve('/two/b') // => { parameter: 'b' }
167 | ```
168 |
169 | ## [4.0.0] - 2017-09-15
170 |
171 | - Rename `router.resolve({ path })` to `router.resolve({ pathname })`
172 | (BREAKING CHANGE [#114](https://github.com/kriasoft/universal-router/pull/114))
173 | - Rename `context.url` to `context.pathname`
174 | (BREAKING CHANGE [#114](https://github.com/kriasoft/universal-router/pull/114))
175 | - Remove `pretty` option from `generateUrls(router, options)` function in favor of new `encode` option
176 | (BREAKING CHANGE [#111](https://github.com/kriasoft/universal-router/pull/111))
177 | - Update [path-to-regexp](https://github.com/pillarjs/path-to-regexp) to v2.0.0, see
178 | [changelog](https://github.com/pillarjs/path-to-regexp/blob/1bf805251c8486ea44395cd12afc37f77deec95e/History.md#200--2017-08-23)
179 | (BREAKING CHANGE [#111](https://github.com/kriasoft/universal-router/pull/111))
180 | - Explicitly handle trailing delimiters (e.g. `/test/` is now treated as `/test/` instead of `/test` when matching)
181 | - No wildcard asterisk (`*`) - use parameters instead (`(.*)`)
182 | - Add support for repeat parameters ([#116](https://github.com/kriasoft/universal-router/pull/116))
183 | - Add `encode` option to `generateUrls(router, options)` function for pretty encoding
184 | (e.g. pass your own implementation) ([#111](https://github.com/kriasoft/universal-router/pull/111))
185 | - Preserve `context.keys` values from the parent route ([#111](https://github.com/kriasoft/universal-router/pull/111))
186 | - Inherit `context.params` and `queryParams` from
187 | [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)
188 | (e.g. `params.hasOwnProperty()` won't throw an exception anymore)
189 | ([#111](https://github.com/kriasoft/universal-router/pull/111))
190 | - Include the source code of the router in the [npm package](https://www.npmjs.com/package/universal-router)
191 | ([#110](https://github.com/kriasoft/universal-router/pull/110))
192 |
193 | **Migration from v3 to v4:**
194 |
195 | - Change `router.resolve({ path, ... })` to `router.resolve({ pathname, ... })`
196 | - Remove trailing slashes from all paths of your routes, i.e.
197 | - `path: '/posts/:uri/'` => `path: '/posts/:uri'`
198 | - `path: '/posts/'` => `path: '/posts'`
199 | - `path: '/'` => `path: ''`
200 | - etc.
201 | - Replace `path: '*'` with `path: '(.*)'` if any
202 | - If you are using webpack, change [rule](https://webpack.js.org/configuration/module/#rule) (loader)
203 | for `.js` files to include `.mjs` extension, i.e.
204 | - `test: /\.js$/` => `test: /\.m?js$/`
205 |
206 | ## [3.2.0] - 2017-05-10
207 |
208 | - Add `stringifyQueryParams` option to `generateUrls(router, options)` to generate URL with
209 | [query string](http://en.wikipedia.org/wiki/Query_string) from unknown route params
210 | ([#93](https://github.com/kriasoft/universal-router/pull/93))
211 |
212 | ## [3.1.0] - 2017-04-20
213 |
214 | - Fix `context.next()` for multiple nested routes
215 | ([#91](https://github.com/kriasoft/universal-router/pull/91))
216 | - Add `pretty` option for `generateUrls(router, options)` to prettier encoding of URI path segments
217 | ([#88](https://github.com/kriasoft/universal-router/pull/88))
218 | - Add source maps for minified builds ([#87](https://github.com/kriasoft/universal-router/pull/87))
219 | - Include UMD builds to the git repository
220 |
221 | ## [3.0.0] - 2017-03-25
222 |
223 | - Update Router API (BREAKING CHANGE)
224 |
225 | ```js
226 | import Router from 'universal-router'
227 | const router = new Router(routes, options)
228 | router.resolve({ path, ...context }) // => Promise
229 |
230 | // previously
231 | import { resolve } from 'universal-router'
232 | resolve(routes, { path, ...context }) // => Promise
233 | ```
234 |
235 | See [#83](https://github.com/kriasoft/universal-router/pull/83) for more info and examples
236 |
237 | - `context.next()` now iterates only child routes by default (BREAKING CHANGE)
238 | use `context.next(true)` to iterate through the all remaining routes
239 | - Remove `babel-runtime` dependency to decrease library size (BREAKING CHANGE)
240 | Now you need to care about these polyfills yourself:
241 | - [Object.assign](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
242 | - [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
243 | - [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)
244 | - Add support for URL Generation
245 | ```js
246 | import generateUrls from 'universal-router/generate-urls'
247 | const url = generateUrls(router)
248 | url(routeName, params) // => String
249 | ```
250 | - Add support for Dynamic Breadcrumbs, use `context.route.parent` to iterate
251 | - Add support for Declarative Routes, `new Router(routes, { resolveRoute: customResolveRouteFn })`
252 | - Add support for Base URL option, `new Router(routes, { baseUrl: '/base' })`
253 | - Add ability to specify custom context properties once, `new Router(routes, { context: { ... } })`
254 | - Rewrite `matchRoute` function without usage of
255 | [generators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*)
256 | to decrease amount of necessary polyfills
257 | - Remove usage of
258 | [String.prototype.startsWith()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith)
259 | - Add `context.url` with the original url passed to `resolve` method
260 | - Add `context` property to `Route not found` error
261 |
262 | ## [2.0.0] - 2016-10-20
263 |
264 | - Preserve `context.params` values from the parent route ([#57](https://github.com/kriasoft/universal-router/pull/57))
265 | - Throws an error if no route found ([#62](https://github.com/kriasoft/universal-router/pull/62))
266 | - Remove obsolete `context.end()` method ([#60](https://github.com/kriasoft/universal-router/pull/60))
267 | - Remove obsolete `match` alias for `resolve` function ([#59](https://github.com/kriasoft/universal-router/pull/59))
268 | - Do not throw an error for malformed URI params ([#54](https://github.com/kriasoft/universal-router/pull/54))
269 | - Handle `null` the same way as `undefined` ([#51](https://github.com/kriasoft/universal-router/pull/51))
270 | - Return `null` instead of `undefined` to signal no match ([#51](https://github.com/kriasoft/universal-router/pull/51))
271 | - Support `context.next()` across multiple routes ([#49](https://github.com/kriasoft/universal-router/pull/49))
272 | - Sequential execution of asynchronous routes ([#49](https://github.com/kriasoft/universal-router/pull/49))
273 | - Remove errors handler from core ([#48](https://github.com/kriasoft/universal-router/pull/48))
274 | - Drop support of node.js v5 and below ([#47](https://github.com/kriasoft/universal-router/pull/47))
275 |
276 | ## [1.2.2] - 2016-05-31
277 |
278 | - Update UMD build to include missing dependencies ([#33](https://github.com/kriasoft/universal-router/pull/33))
279 |
280 | ## [1.2.1] - 2016-05-12
281 |
282 | - Rename `match()` to `resolve()`. E.g. `import { resovle } from 'universal-router'`
283 | - Fix an issue when the router throws an exception when the top-level route doesn't have `children` property
284 | - Include CommonJS, Harmony Modules, ES5.1 and UMD builds into NPM package
285 | - Include source maps into NPM package
286 |
287 | ## [1.1.0-beta.4] - 2016-04-27
288 |
289 | - Fix optional parameters, e.g. `/products/:id?` ([#27](https://github.com/kriasoft/universal-router/pull/27))
290 |
291 | ## [1.1.0-beta.3] - 2016-04-08
292 |
293 | - Fix `matchRoute()` yielding the same route twice when it matches to both full and base URLs
294 |
295 | ## [1.1.0-beta.2] - 2016-04-08
296 |
297 | - `match(routes, { path, ...context)` now throws an error if a matching route was not found (BREAKING CHANGE)
298 | - If there is a top-level route with path equal to `/error`, it will be used for error handling by convention
299 |
300 | ## [1.1.0-beta.1] - 2016-04-05
301 |
302 | - Remove `Router` class and `router.dispatch()` method in favor of
303 | `match(routes, { path, ...context })`, where `routes` is just a plain JavaScript objects containing
304 | the list of routes (BREAKING CHANGE)
305 | - Add `context.end()` method to be used from inside route actions
306 | - Update documentation and code samples
307 |
308 | ## [1.0.0-beta.1] - 2016-03-25
309 |
310 | - Rename `react-routing` to `universal-router` (BREAKING CHANGE)
311 | - Remove `router.on(path, ...actions)` in favor of `router.route(path, ...actions)` (BREAKING CHANGE)
312 | - Remove `new Router(on => { ... })` initialization option in favor of `new Router(routes)` (BREAKING CHANGE)
313 | - Fix ESLint warnings
314 | - Update unit tests
315 | - Remove build tools related to project's homepage in favor of [Easystatic](https://easystatic.com)
316 | - Refactor project's homepage layout. See `docs/assets`.
317 | - Clean up `package.json`, update Babel and its plug-ins to the latest versions
318 | - Make the library use `babel-runtime` package instead of an inline runtime
319 | - Add [CHANGELOG.md](CHANGELOG.md) file with the notable changes to this project
320 |
321 | ## [0.0.7] - 2015-12-13
322 |
323 | - Small bug fixes and improvements
324 |
325 | [unreleased]: https://github.com/kriasoft/universal-router/compare/v10.0.0...HEAD
326 | [10.0.0]: https://github.com/kriasoft/universal-router/compare/v9.2.1...v10.0.0
327 | [9.2.1]: https://github.com/kriasoft/universal-router/compare/v9.2.0...v9.2.1
328 | [9.2.0]: https://github.com/kriasoft/universal-router/compare/v9.1.0...v9.2.0
329 | [9.1.0]: https://github.com/kriasoft/universal-router/compare/v9.0.1...v9.1.0
330 | [9.0.1]: https://github.com/kriasoft/universal-router/compare/v9.0.0...v9.0.1
331 | [9.0.0]: https://github.com/kriasoft/universal-router/compare/v8.3.0...v9.0.0
332 | [8.3.0]: https://github.com/kriasoft/universal-router/compare/v8.2.1...v8.3.0
333 | [8.2.1]: https://github.com/kriasoft/universal-router/compare/v8.2.0...v8.2.1
334 | [8.2.0]: https://github.com/kriasoft/universal-router/compare/v8.1.0...v8.2.0
335 | [8.1.0]: https://github.com/kriasoft/universal-router/compare/v8.0.0...v8.1.0
336 | [8.0.0]: https://github.com/kriasoft/universal-router/compare/v7.0.0...v8.0.0
337 | [7.0.0]: https://github.com/kriasoft/universal-router/compare/v6.0.0...v7.0.0
338 | [6.0.0]: https://github.com/kriasoft/universal-router/compare/v5.1.0...v6.0.0
339 | [5.1.0]: https://github.com/kriasoft/universal-router/compare/v5.0.0...v5.1.0
340 | [5.0.0]: https://github.com/kriasoft/universal-router/compare/v4.3.0...v5.0.0
341 | [4.3.0]: https://github.com/kriasoft/universal-router/compare/v4.2.1...v4.3.0
342 | [4.2.1]: https://github.com/kriasoft/universal-router/compare/v4.2.0...v4.2.1
343 | [4.2.0]: https://github.com/kriasoft/universal-router/compare/v4.1.0...v4.2.0
344 | [4.1.0]: https://github.com/kriasoft/universal-router/compare/v4.0.0...v4.1.0
345 | [4.0.0]: https://github.com/kriasoft/universal-router/compare/v3.2.0...v4.0.0
346 | [3.2.0]: https://github.com/kriasoft/universal-router/compare/v3.1.0...v3.2.0
347 | [3.1.0]: https://github.com/kriasoft/universal-router/compare/v3.0.0...v3.1.0
348 | [3.0.0]: https://github.com/kriasoft/universal-router/compare/v2.0.0...v3.0.0
349 | [2.0.0]: https://github.com/kriasoft/universal-router/compare/v1.2.2...v2.0.0
350 | [1.2.2]: https://github.com/kriasoft/universal-router/compare/v1.2.1...v1.2.2
351 | [1.2.1]: https://github.com/kriasoft/universal-router/compare/v1.1.0-beta.4...v1.2.1
352 | [1.1.0-beta.4]: https://github.com/kriasoft/universal-router/compare/v1.1.0-beta.3...v1.1.0-beta.4
353 | [1.1.0-beta.3]: https://github.com/kriasoft/universal-router/compare/v1.1.0-beta.2...v1.1.0-beta.3
354 | [1.1.0-beta.2]: https://github.com/kriasoft/universal-router/compare/v1.1.0-beta.1...v1.1.0-beta.2
355 | [1.1.0-beta.1]: https://github.com/kriasoft/universal-router/compare/v1.0.0-beta.1...v1.1.0-beta.1
356 | [1.0.0-beta.1]: https://github.com/kriasoft/universal-router/compare/v0.0.7...v1.0.0-beta.1
357 | [0.0.7]: https://github.com/kriasoft/universal-router/compare/v0.0.6...v0.0.7
358 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2015-present Kriasoft.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Universal Router
2 |
3 | [](https://www.npmjs.com/package/universal-router)
4 | [](https://www.npmjs.com/package/universal-router)
5 | [](https://bundlephobia.com/result?p=universal-router)
6 | [](https://discord.gg/2nKEnKq)
7 |
8 |
9 |
11 |
12 |
13 | A simple middleware-style router that can be used in both client-side and server-side applications.
14 |
15 | Visit **[Quickstart Guide](http://slides.com/koistya/universal-router)** (slides) |
16 | Join **[#universal-router](https://gitter.im/kriasoft/universal-router)** on Gitter to stay up to date
17 |
18 | ## Features
19 |
20 | - It has [simple code](https://github.com/kriasoft/universal-router/blob/master/src/UniversalRouter.ts)
21 | with only single [path-to-regexp](https://github.com/pillarjs/path-to-regexp) dependency.
22 | - It can be used with any JavaScript framework such as
23 | [React](https://reactjs.org/), [Vue](https://vuejs.org/), [Hyperapp](https://hyperapp.dev/) etc.
24 | - It uses the same middleware approach used in [Express](http://expressjs.com/) and [Koa](http://koajs.com/),
25 | making it easy to learn.
26 | - It supports both [imperative](https://en.wikipedia.org/wiki/Imperative_programming) and
27 | [declarative](https://en.wikipedia.org/wiki/Declarative_programming) routing style.
28 | - Routes are plain JavaScript
29 | [objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer)
30 | with which you can interact as you like.
31 |
32 | ## What users say about Universal Router
33 |
34 | > Just switched a project over to universal-router.
35 | > Love that the whole thing is a few hundred lines of flexible, easy-to-read code.
36 | >
37 | > -- [Tweet](https://twitter.com/wincent/status/862115805378494464) by **Greg Hurrell** from Facebook
38 |
39 | > It does a great job at trying to be _universal_ — it's not tied to any framework,
40 | > it can be run on both server and client, and it's not even tied to history.
41 | > It's a great library which does one thing: routing.
42 | >
43 | > -- [Comment on Reddit](https://www.reddit.com/r/reactjs/comments/5xhw3o#form-t1_dejkw4p367)
44 | > by **@everdimension**
45 |
46 | ## Installation
47 |
48 | Using [npm](https://www.npmjs.com/package/universal-router):
49 |
50 | ```bash
51 | npm install universal-router --save
52 | ```
53 |
54 | ## How does it look like?
55 |
56 | ```js
57 | import UniversalRouter from 'https://esm.sh/universal-router'
58 |
59 | const routes = [
60 | {
61 | path: '', // optional
62 | action: () => `