npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

named-urls

v2.0.1

Published

Simple named url patterns in Javascript

Downloads

33,382

Readme

Simple named url patterns in JavaScript.

CircleCI Code Coverage PRs Welcome MIT License

Watch on GitHub Star on GitHub Tweet

Implementing a static route config and named routes on top of (react-router) at this point is like a 20 line ordeal. – Ryan Florence

Motivation

Named routes are essential to keep route config DRY and prevent silly errors due to typos. This feature was removed from react-router in 1.0 and I missed it since then as many others.

There're other libs dealing with named routes, some of them provide custom Link, Route routes, some of them have more features to integrate with express. Here's incomplete list of libs I considered before writing these 20 lines of code (and 200+ lines of other files to publish this package):

  • https://github.com/adamziel/react-router-named-routes
  • https://github.com/taion/use-named-routes
  • https://github.com/alubbe/named-routes

NOTE: v2 introduces breaking changes. Please check out the migration guide before upgrading.

Installation

$ npm install named-urls

or

$ yarn add named-urls

Quickstart

Create file with all routes in your application (e.g. routes.js). Use named-urls/include to create namespaced group of routes with common prefix:

// routes.js
import { include } from 'named-urls'

export default {
   // simple route
   profile: '/profile',

   // route with params
   article: '/article/:articleId',

   // route with optional params
   messages: '/messages/:messageId?',

   // Routes with common path prefix
   auth: include('/auth', {
      // Absolute url (ignore /auth prefix)
      login: '/login/',

      // Relative urls (prefixed with /auth)
      passwordReset: 'password/reset/',
      passwordVerify: 'password/verify/',
   }),

   // Routes with params
   messages: include('/messages', {
      all: '',
      unread: 'unread/',

      // nesting of includes is allowed
      detail: include(':messageId/', {
         show: '',
         edit: 'edit/',
         comments: 'comments/',
      })
   })
}

Use routes in Route component from react-router-dom:

// App.js

import React from 'react'
import { Switch, Route } from 'react-router-dom'

import routes from './routes'
import * as scenes from './scenes' // just a convention, could be "pages"

function App() {
   return (
      <Switch>
         <Route path={routes.profile} component={scenes.Profile} />
         <Route path={routes.auth.login} component={scenes.auth.Login} />
         // ...
         <Route path={routes.messages.unread} component={scenes.messages.Unread} />
         <Route path={routes.messages.detail.show} component={scenes.messages.Detail} />
      </Switch>
   )
}

Routes with parameters can be formatted using reverse function:

// Navigation.js
import React from 'react'
import { Link } from 'react-router'
import { reverse } from 'named-urls'

function Navigation({ messages }) {
   return (
      <ul>
         <li><Link to={`${routes.profile}`}>Profile</Link></li>
         // ...
         // Use reverse to replace params in route pattern with values
         {messages.map(message =>
            <li key={message.id}>
               <Link to={reverse(`${routes.messages.detail.show}`, { messageId: message.id })}>
                  Profile
               </Link>
            </li>
         )}
      </ul>
   )
}

Ending slash

Patterns ending with slash are always reversed to URL with ending slash and vice versa: Paterns without ending slash are always reserved to URL without endlish slash:

// pattern with ending slash
reverse('pattern/:optional?', { optional: 42 }) // pattern/42
reverse('pattern/:optional?') // pattern

// pattern without ending slash
reverse('pattern/:optional?/', { optional: 42 }) // pattern/42/
reverse('pattern/:optional?/') // pattern/

Migrating from v1.x.x to v2.x.x

For better compatibility with React Router, v2 uses path-to-regexp to resolve URLs. This means some of your routes may break when you upgrade.

reverse

-reverse('pattern/page:param?', {})
+reverse('pattern/(page:param)?', {})

reverseForce

-reverseForce('pattern/page:param?', {})
+reverseForce('pattern/(page:param)?', {})

To get a full overview of all accepted patterns, consult the path-to-regexp documentation.

Some tricks

Using an "include" route

If you define a route as an include, calling it directly will return you a function. To by-pass that, you have a solution to create an empty route inside, let's call it self:

// routes.js
import { include } from 'named-urls'

export default {
   messages: include('/messages', {
      self: '',

      detail: include(':messageId/', {
         show: '',
         edit: 'edit/',
         comments: 'comments/',
      })
   })
}

so you'll be able to do:

<Route path={routes.messages.self} component={Messages} />

A way to not define a useless route is to use the string way of a route like that:

// routes.js
import { include } from 'named-urls'

export default {
   messages: include('/messages', {
      detail: include(':messageId/', {
         edit: 'edit/',
         comments: 'comments/',
      })
   })
}
<Route path={`${routes.messages}`} component={Messages} />

// OR

<Route path={String(routes.messages)} component={Messages} />

License

MIT