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 🙏

© 2025 – Pkg Stats / Ryan Hefner

meebo

v0.3.0

Published

the missing api contract validation for express js

Readme

meebo_logo

The missing API validation library for Express

npm version TypeScript License: ISC

InstallationUsageOpenAPI


Why Meebo?

Express is the most popular Node.js framework, but it was built before TypeScript existed...

Existing solutions require too much:

  • tRPC: Amazing, but requires you to abandon REST...
  • ts-rest: Powerful, but requires defining contracts separately...
  • tsoa: Generates code from decorators, heavy setup...

Meebo takes a different approach: Keep your Express routes exactly as they are and simply add your schema


The Problem

const router = express.Router();

router.post("/users", (req, res) => {
  const user = req.body; // req.body is type any and not validated at runtime
  res.json({ user }); // res.json returns anything and is not validated either
});

The Solution

import { TypedRouter, swagger } from "meebo";
import { z } from "zod";

const router = TypedRouter(express.Router());

const UserSchema = z.object({
  name: z.string(),
  email: z.string().email(),
});

router.post("/users", { request: UserSchema, response: UserSchema }, (req, res) => {
  req.body; // typed + validated using UserSchema ✅
  res.json({ name: "John", email: "[email protected]" }); // typed + validated using UserSchema ✅
});

You now have an API where

  • TypeScript knows the exact shape of req.body, req.query, req.params, and your response
  • Full autocomplete and intellisense on your requests, responses, queries, params, and headers
  • Zod validates everything at runtime, ensuring data matches and gives very helpful errors
  • Swagger UI and OpenAPI json generated from all your endpoints and schema

Install

npm install meebo zod express
npm install -D typescript @types/express @types/node

Requirements: TypeScript, Express 5+, Zod 3 or 4

Usage

// Validate request body, response, query, params, headers
router.get(
  "/users/:id",
  {
    params: z.object({ id: z.string() }),
    query: z.object({ limit: z.coerce.number().optional() }),
    response: UserSchema,
  },
  (req, res) => {
    req.params.id; // string
    req.query.limit; // number | undefined
  },
);

OpenAPI / Swagger

Add swagger() as the last middleware to serve swagger ui docs at /docs:

const app = express();
app.use("/api", router);
app.use(swagger("My API"));

Schema Metadata

Use .openapi() on any Zod schema to add descriptions, examples, and more (powered by zod-to-openapi):

const UserSchema = z
  .object({
    name: z.string().openapi({ example: "John" }),
    email: z.string().email().openapi({ example: "[email protected]" }),
  })
  .openapi({
    description: "A user object",
    example: { name: "John", email: "[email protected]" },
  });

https://github.com/user-attachments/assets/d47bf5c3-a2b5-4ee8-885d-8c9d1db9fcd8

License

ISC