Socket
Book a DemoInstallSign in
Socket

@andywer/srv

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@andywer/srv

Node.js server rethought. Functional, clean, performant.

latest
Source
npmnpm
Version
0.3.0
Version published
Maintainers
1
Created
Source

SRV

Node.js servers rethought: Functional, lean, performant.

Travis build status Travis build status


What if we were to write express from scratch in 2019...

Would we use async functions and promises? Would we make it more functional? With TypeScript in mind?

Sure we would! So here we go.

  • Built for modern JavaScript / TypeScript
  • Functional - Take a request, return a response
  • Explicit - Clear static types
  • Few dependencies & less than 1000 lines of code

⚠️ Status: Experimental ⚠️

At a glance

import {
  Response,
  Route,
  Router,
  Service
} from "@andywer/srv"

const greet = Route.GET("/welcome", async (request) => {
  const name = request.query.name

  return Response.JSON({
    name: "Greeting service",
    welcome: name ? `Hello, ${name}!` : `Hi there!`
  })
})

const service = Service(Router([ greet ]))

service.listen(8080)
  .catch(console.error)

Documentation

Find some documentation and sample code here. Work in progress right now.

Features

Async functions

No callbacks. Leverage modern day features instead for an optimal developer experience.

import { Response, Route } from "@andywer/srv"

const greet = Route.GET("/health", async () => {
  try {
    const stats = await fetchHealthMetrics()
    return Response.JSON({
      operational: true,
      stats
    })
  } catch (error) {
    return Response.JSON(500, {
      operational: false
    })
  }
})
Functional route handlers

Take a request, return a response. Lean, clean, easy to test and debug.

import { Response, Route, Router } from "@andywer/srv"
import { queryUserByID } from "./database/users"

const getUser = Route.GET("/user/:id", async request => {
  const userID = request.params.id
  const user = await queryUserByID(userID)

  if (!user) {
    return Response.JSON(404, {
      message: `User ${userID} not found`
    })
  }

  const headers = {
    "Last-Modified": user.updated_at || user.created_at
  }
  return Response.JSON(200, headers, user)
})

export const router = Router([
  getUser
])
No mutations

Stop passing data from middlewares to route handlers by dumping it in an untypeable context. Take the request object, extend it, pass it down to the route handler.

By applying middlewares in a direct and explicit manner, the passed requests and responses are completely type-safe, even if customized by middlewares.

import { Middleware, Request, RequestHandler, Service } from "@andywer/srv"
import { Logger } from "./logger"

export default function LoggingMiddleware(logger: Logger): Middleware {
  return async (request: Request, next: RequestHandler) => {
    const requestWithLogger = request.derive({
      log: logger
    })
    // typeof requestWithLogger.log === Logger
    return next(requestWithLogger)
  }
}
import { composeMiddlewares, Service } from "@andywer/srv"
import logger from "./logger"
import router from "./routes"

const applyMiddlewares = composeMiddlewares(
  LoggingMiddleware(logger),
  SomeOtherMiddleware()
)

const service = Service(applyMiddlewares(router))
Everything is a function

The code base is relatively simple. Middlewares, routes and routers, they are all just implementations of the following function type:

type RequestHandler = (request: Request, next?: NextCallback) => Response | Promise<Response>
type NextCallback = (req: Request) => Response | Promise<Response>

Debugging

Set the DEBUG environment variable to srv:* to get some debug logging:

$ DEBUG=srv:* node ./dist/my-server

License

MIT

FAQs

Package last updated on 19 Oct 2019

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts