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

@zodios/express

v10.6.1

Published

Typescript express server

Downloads

60,853

Readme

https://user-images.githubusercontent.com/633115/185851987-554f5686-cb78-4096-8ff5-c8d61b645608.mp4

What is it ?

It's an express adapter for zodios that helps you type your express routes.

  • really simple centralized API declaration
  • router endpoints autocompletion
  • typescript autocompletion for query, path, header and body input parameters (req is fully typed)
  • typescript autocompletion for response body (res.json())
  • input validation thanks to zod
  • openapi specification generation out of the box (using swagger)
  • end to end typesafe APIs (a la tRPC when using both @zodios/express and @zodios/core)

Table of contents:

Install

> npm install @zodios/express

or

> yarn add @zodios/express

How to use it ?

For an almost complete example on how to use zodios and how to split your APIs declarations, take a look at dev.to example.

zodiosApp : Declare your API for fullstack end to end type safety

Here is an example of API declaration with Zodios.

in a common directory (ex: src/common/api.ts) :

import { makeApi } from "@zodios/core";
import { z } from "zod";

const userApi = makeApi([
  {
    method: "get",
    path: "/users/:id", // auto detect :id and ask for it in apiClient get params
    alias: "getUser", // optionnal alias to call this endpoint with it
    description: "Get a user",
    response: z.object({
      id: z.number(),
      name: z.string(),
    }),
  },
]);

in your frontend (ex: src/client/api.ts) :

import { Zodios } from "@zodios/core";
import { userApi } from "../../common/api";

const apiClient = new Zodios(
  "https://jsonplaceholder.typicode.com",
  userApi
);

//   typed                     alias   auto-complete params
//     ▼                        ▼                   ▼
const user = await apiClient.getUser({ params: { id: 1 } });

in your backend (ex: src/server/router.ts) :

import { zodiosApp } from "@zodios/express";
import { userApi } from "../../common/api";

// just an express adapter that is aware of  your api, app is just an express app with type annotations and validation middlewares
const app = zodiosApp(userApi);

//  auto-complete path  fully typed and validated input params (body, query, path, header)
//          ▼           ▼    ▼
app.get("/users/:id", (req, res) => {
  // res.json is typed thanks to zod
  res.json({
    //   auto-complete req.params.id
    //              ▼
    id: req.params.id,
    name: "John Doe",
  });
})

app.listen(3000);

zodiosRouter : Split your application with multiple routers

When organizing your express application, you usually want to split your API declarations into separate Routers. You can use the zodiosRouter to do that with a zodiosApp without APIs attached.

import { zodiosApp, zodiosRouter } from "@zodios/express";

const app = zodiosApp(); // just an axpess app with type annotations
const userRouter = zodiosRouter(userApi); // just an express router with type annotations and validation middlewares
const adminRouter = zodiosRouter(adminApi); // just an express router with type annotations and validation middlewares

const app.use(userRouter,adminRouter);

app.listen(3000);

Error Handling

Zodios express can infer the status code to match your API error response and also have your errors correctly typed.

import { makeApi } from "@zodios/core";
import { zodiosApp } from "@zodios/express";
import { z } from "zod";

const userApi = makeApi([
  {
    method: "get",
    path: "/users/:id", // auto detect :id and ask for it in apiClient get params
    alias: "getUser", // optionnal alias to call this endpoint with it
    description: "Get a user",
    response: z.object({
      id: z.number(),
      name: z.string(),
    }),
    errors: [
      {
        status: 404,
        response: z.object({
          code: z.string(),
          message: z.string(),
          id: z.number(),
        }),
      }, {
        status: 'default', // default status code will be used if error is not 404
        response: z.object({
          code: z.string(),
          message: z.string(),
        }),
      },
    ],
  },
]);

const app = zodiosApp(userApi);
app.get("/users/:id", (req, res) => {
  try {
    const id = +req.params.id;
    const user = service.findUser(id);
    if(!user) {
      // match error 404 schema with auto-completion
      res.status(404).json({
        code: "USER_NOT_FOUND",
        message: "User not found",
        id, // compile time error if you forget to add id
      });
    } else {
      // match response schema with auto-completion
      res.json(user);
    }
  } catch(err) {
    // match default error schema with auto-completion
    res.status(500).json({
      code: "INTERNAL_ERROR",
      message: "Internal error",
    });
  }
})

app.listen(3000);

Roadmap

  • [] add support for swagger/openapi generation
  • [] add utilities to combine api declarations to match the express router api
  • [] add autocompletion for express app.name()