Giter Site home page Giter Site logo

joselion / ts-routeways Goto Github PK

View Code? Open in Web Editor NEW
6.0 1.0 0.0 6.49 MB

A type-safe solution to define and consume routes

Home Page: https://joselion.github.io/ts-routeways/

License: MIT License

TypeScript 100.00%
codecs querystring router routes typesafe typesafety typescript react type-safe hacktoberfest

ts-routeways's Introduction

CI CodeQL Pages Release NPM version NPM bundle size NPM downloads NPM license GitHub Release Date Known Vulnerabilities

Logo

Lightweight and type-safe! All-in-one solution to define and consume routes

ts-routeways

Why?

"Yet another route library?" you might think. In part you're right, there're a lot of libraries out there designed to create routes, in some of them routes are plain, some do allow nesting; some of them have simple-wide types like any, and some of them have full type-safety and inference through template literals. However, the reality is that none give you the complete solution.

That is to say, once you have some routes defined, you need to consume them! You want to create URLs from them, taking into account path variables and query parameters, and as well parse a URL into an object, so you can safely use the variables and parameters in the current route. Typically, you'd use a separate library to handle query parameters, and maybe another to parse/build URLs. Wouldn't it be nice if you'd have "one ring to rule them all"? With ts-routeways now you can!

Some features of ts-routeways include:

๐Ÿชถ Lightweight implemetation. Zero extra dependencies.

โœ… TypeScript optimized. Static check ensures routes are parse/build as they should be.

๐Ÿฐ Simple API. Allows nesting and spliting into multiple files (useful on bigger apps).

โš™๏ธ Codec based. Parameters are defined with codecs imagination is the limit.

We provide the most commmon codecs in on single Codecs object, which can be extended to add custom codecs of your own.

๐Ÿ”ง Fully agnostic. You can use it with any framework/library, the concepts apply to any web-like router.

(deprecated) We provide optional hook makers for React, just as a convenience. We're open to add more helpers for other libraries if necessary. PRs and suggestions are always welcome!

Install

With NPM:

npm i ts-routeways

With Yarn:

yarn add ts-routeways

Usage

The concept is simple, use the builder to create a Routeways instance that contains your custom routes. Then use that instance to access your routes in the same structured way you define them. Each route can make a raw string URL, or parse a URL to consume the parameters on it.

import { Codecs, Routeways } from "ts-routeways";

export const MainRoutes = Routeways()
  .path({ name: "home", path: "/home" }) // (1)
  .nest({
    name: "users",
    path: "/users",
    subRoutes: Routeways() // (2)
      .path({ name: "view", path: "/view/:userId", pathVars: { userId: Codecs.Number } }) // (3)
      .path({ name "search", path: "/search", queryParams: { byName: Codecs.String, showAll: Codecs.Boolean } }) // (4)
  })
  .build(); // (5)

(1) Nothing else required, no path variables in the path.
(2) On .nest(..) the subRoutes property is required.
(3) A path variable is present in the path (:userId). Now pathVars is required and it must contain a userId property with the codec you prefer.
(4) The queryParams property is optional. Use it to define the query parameters the route supports and the codecs to be used on each one. By definition, query parameters are optional in any URL.
(5) Finally, build an instance of your own Routeways to use it.

With your Routeways defined, you can use them like in the examples below:

import { MainRoutes } from "./MainRoutes";

MainRoutes.home.makeUrl(); // -> /home
MainRoutes.users.makeUrl(); // -> /users

MainRoutes.users.view.makeUrl({ userId: 3 }); // -> /users/view/3
MainRoutes.users.search.makeUrl(); // -> /users/search (query params are always optional)
MainRoutes.users.search.makeUrl({ byName: "foo", showAll: true }); // -> /users/search?byName=foo&showAll=true

const {
  pathVars: {
    userId, // 3 (number)
  },
} = MainRoutes.users.view.parseUrl("/users/view/3");

const {
  pathVars: {
    byName, // john (string)
  },
  queryParams: {
    showAll, // false (boolean)
  },
} = MainRoutes.users.search.parseUrl("/users/search?byName=john&showAll=false")

// #template: useful for 3rd party routing libraries
MainRoutes.home.template(); // -> /home
MainRoutes.users.view.template(); // -> /users/view/:userId

Custom Codecs

Only the most basic data types are priveded by the Codecs helper. Sometimes you'll find yourself in the need of a more complex codec, some specific data type, or aserializable clas instance. With ts-routeways you can use custom codecs, and also use its extension mechanism for the Codecs helper, so you can have all your codecs on one place. You need only to create an object containing a decode and an encode method:

interface Codec<T> {
  decode(text: string): T;
  encode(value: T): string;
}

Optionally, add your codec to the Codecs helper. Also, extend the CodecsType interface to add the types:

declare module "ts-routeways" {

  export interface CodecsType {
    UUID: Codec<UUID>;
  }
}

const UUIDCodec = { /* ... */ };

addCodec("UUID", UUIDCodec);

Codecs.UUID // Ready to use on a router

You can find more details and a complete example of custom codecs in the link bellow:

Custom Codecs โš™๏ธ

Getting your QueryParam types back

Sometimes you'd like to use the queryParam types that are already defined in your router somewhere else. For instance, in the argument of the function in charge of making a request with those same query paramenters. This could be a very common pattern, let's assume we have MainRoutes as in the Usage section, and an API that receives those same byName and showAll query params.

Not so safe, isn't it?

export function searchUsers(params: any): Promise<User[]> {
//                                  ^ What am I supposed to use here?
  return axios.get<User[]>("/api/users", { params })
    .then(({ data }) => data);
}

Instead of that, you can infer the type of the query params of any route using the types helper InferQueryParams<R>, where R is the type your route:

This is better!

import { InferQueryParams } from "ts-routeways";

type UsersQueryParams = InferQueryParams<typeof MainRoutes.users.search>;
//   ^ type = { byName?: string; showAll?: boolean; }

export function searchUsers(params: UsersQueryParams): Promise<User[]> {
  return axios.get<User[]>("/api/users", { params })
    .then(({ data }) => data);
}

Working with ReactJS โš›๏ธ

Although the design of ts-routeways is meant to be agnostic, it provides a few helpers to create custom hooks that will allow you to handle navigation, path variables, and query parameters, all in a ReactJS fashion. You can find further documentation and examples in the link below:

(deprecated) React Interagation Docs ๐Ÿ“˜

Use react-routeways package instead.

API Reference

The library is documented on its JSDocs, which is usully the most usuful place for help. However, if you'd like to see the API reference, you can find them in the link below:

API Reference ๐Ÿ“š

Something's missing?

Suggestions are always welcome! Please create an issue describing the request, feature, or bug. We'll try to look into it as soon as possible ๐Ÿ™‚

Contributions

Contributions are very welcome! To do so, please fork this repository and open a Pull Request to the main branch.

License

MIT License


Attribution: Route icon created by Smashicons - Flaticon

ts-routeways's People

Contributors

dependabot[bot] avatar joselion avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.