@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
Maintainers
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 transformerswagger-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.