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

@kurai-io/express-router

v0.3.2

Published

Layer-2 framework based on express, which makes it faster and easier to build fault-tolerant backend applications

Downloads

741

Readme

Kurai Foundation Express Router

Layer-2 framework based on express, which makes it faster and easier to build fault-tolerant backend applications

Table of contents

Installation

There is little to describe, the installation process is no different from any other package:

npm add @kurai-io/express-router

Or use any other package manager, the command is just an example, please consult your package manager's documentation for the exact installation command.

pnpm[yarn, etc...] install @kurai-io/express-router

Basic usage

Usage example

Let's create a simple application that can create and return users from the database
while allowing access only to authorized users

First, let's create schemas to validate the content that will go into the handlers

// src/schemas.ts

import { ISchema } from "@kurai-io/express-router"

export const UserCreateSchema: ISchema = {
  body: Joi.object({
    login: Joi.string().min(4).max(24).required(),
    password: Joi.string.min(8).max(128).required()
  })
}

export const UserGetSchema: ISchema = {
  params: Joi.object({
    id: Joi.string().length(24).required()
  })
}

Now let's write the code of the application itself

// src/app.ts

import { Application } from "@kurai-io/express-router"
import { Unauthorized } from "@kurai-io/express-router/exceptions"
import { UserCreateSchema, UserGetSchema } from "./schemas.ts"

const app = new Application()
const builder = app.createRoute({
  root: "/users",
  middleware: request => {
    let autenticated = false

    // Verify that the user has permission to execute requests
    if (request.header("access-token") === process.env.ACCESS_TOKEN) authenticated = true
    
    return { authenticated }
  }
})

// The request argument already contains the "authenticated" field (and is typed)
builder.schema(UserCreateSchema).post("/create", async request => {
  // Here you can either throw or return an exception
  if (!request.authenticated) return Unauthorized("Invalid token")

  // We recommend returning exceptions because it creates 
  // more predictable code than the "throw" syntax. 
  // But the choice is yours, you can use both approaches

  // Insert the user into the database
  // No need for additional validation, because the schema did all the work for us.
  const insertionResult = await database.insertOne({ ...request.body })
  
  return insertionResult.insertedId
})

// Define a GET request to retrieve the user
builder.schema(UserGetSchema).get("/:id", async request => {
  // No need for try/catch or other monstrosities, the router does all the work
  return database.findOne({ _id: new ObjectId(request.params.id) })
})

In the code above, we created several request handlers, but each of them either returned a response (the default response code is 200) or an error. Now let's create a handler that will return code 204 if successful and a custom error if not.

import { Exception } from "@kurai-io/express-router/exceptions"
import { CustomResponse } from "@kurai-io/express-router"

// ...

// Pass null to the schema to disable validation
builder.schema(null).head("/:id", async request => {
  const hasDocument = database.countDocuments({ _id: new ObjectId(request.params.id) })

  if (!hasDocument) {
    // We could use the NotFound error as we did earlier with Unauthorized, 
    // but instead we will create our own error, just for the sake of example. 
    // In most cases we should use predefined errors, as they are predefined for 
    // almost every 4xx and 5xx error code
    
    return new Exception({
      code: 404,
      name: "NotFound",
      message: "Document not found"
    })
  }

  // If the document exists, return 204. Since the response structure is slightly different 
  // for 4xx/5xx and 1xx-3xx responses, do not use exceptions to return the actual content
  return CustomResponse({
    code: 204,
    content: true
  })
})

Here we have created a simple and fail-safe application that knows how to validate, create and find users. It's not hard, right?

Swagger documentation

To enable Swagger documentation, the following packages must be installed:

  • @kurai-io/express-router-swagger - Swagger transformer
  • swagger-ui-express - Swagger UI renderer

Then, in the application configuration, enable integration

const app = new Application({
  enableSwagger: true
})

Optionally, you can customize the display of documentation using the swagger field in the configuration

The documentation will be generated automatically from schemes and registered routes, the names will be set to automatically generated strings.

If desired, the route can be set the exception list and name manually, let's take the code from the last section as an example. We know that this handler can return a 404 error and a 204 response, let's set the metadata to reflect this

import { ResponseFactory } from "@kurai-io/express-router"

builder.schema(null).head("/:id", async request => {
  // ... see previous examle
}).metadata({
  responses: [ResponseFactory(204), NotFound],
  description: "Get user by ID"
})

The 500 Internal server error and the 200 Success response are added automatically.

The 200 Success response will not be added if other 1xx - 3xx responses have been added.

Advanced API

Router builder

RouterBuilder is the main part of the framework that does all the work. In most cases the Application class will provide sufficient functionality, but if it fails, you can manually use RouterBuilder to achieve your tasks

import { RouterBuilder } from "@kurai-io/express-router"

const someRouter = new RouterBuilder()

someRouter.get("/path", null, async req => {
  return {
    result: "success"
  }
})

Routes with JOI schemas

Same, but with JOI schema

import { RouterBuilder } from "@kurai-io/express-router"

const someRouter = new RouterBuilder()

const someSchema = someRouter.generateSchema("params", {
  address: Joi.string().length(42).required()
})

someRouter.get("/path/:address", someSchema, async req => {
  return {
    address: req.params.address
  }
})

Available JOI schema types: params, query, body

License

You can copy and paste the MIT license summary from below.

MIT License

Copyright (c) 2022-2024 Kurai Foundation

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.