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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@simapi/simapi

v0.0.10

Published

Build frontend features against real API behavior — before your backend exists.

Downloads

1,034

Readme

Build frontend features against real API behavior — before your backend exists. SimAPI lets you define endpoints as plain TypeScript objects, generate realistic fake data with faker-js, validate requests with Zod, and log everything to a database.

Install

Scaffold a new project in one command:

npx @simapi/simapi@latest init my-api
cd my-api
npm run serve

Or add SimAPI to an existing project:

npm install @simapi/simapi

Project structure

my-api/
├── src/
│   ├── endpoints/      # Logical endpoint groups (e.g. users.ts, pets.ts)
│   ├── models/         # TypeScript types and mock factories (e.g. User.ts)
│   └── requests/       # Zod validation shapes (e.g. UserRequest.ts)
├── simapi.config.ts
└── package.json

Defining endpoints

An endpoint is a plain TypeScript object. Export it and SimAPI discovers it automatically.

// src/endpoints/posts.ts
import { z, AppResponse, type EndpointDefinition } from "@simapi/simapi";
import { makePost } from "@/models/post.js";

export const listPosts: EndpointDefinition = {
  path: "/api/posts",
  method: "GET",
  type: "open",
  handler: () => AppResponse.success({ data: AppResponse.array(10, makePost) }),
};

export const getPost: EndpointDefinition = {
  path: "/api/posts/:id",
  method: "GET",
  type: "open",
  handler: (req) => AppResponse.success({ data: makePost() }),
};

export const createPost: EndpointDefinition = {
  path: "/api/posts",
  method: "POST",
  type: "secure",          // runs authHandler before the handler
  request: {
    body: {
      title: z.string().min(3),
      body:  z.string().min(10),
    },
  },
  handler: (req) => {
    req.errors.throwValidationError();   // throws 422 only when validation failed
    return AppResponse.created({ data: makePost() });
  },
};

EndpointDefinition fields

| Field | Required | Description | | ------------- | -------- | ---------------------------------------------------------------- | | path | ✓ | Hono-style route pattern — :param, /nested/path | | method | ✓ | GET POST PUT PATCH DELETE HEAD OPTIONS | | type | ✓ | "open" (no auth) or "secure" (runs authHandler first) | | handler | ✓ | (req: AppRequest) => AppResponse | | request | | RequestDefinition — Zod shapes for body, form, query, headers | | title | | Display name — shown in Console and exported OpenAPI | | description | | Longer description — same | | authHandler | | Per-endpoint auth check (runs after global handler) | | failRate | | 01 probability of returning a simulated 500 | | delay | | Milliseconds to wait before the handler runs |


Fake data

faker (powered by faker-js) is re-exported directly from @simapi/simapi:

// models/post.ts
import { faker } from "@simapi/simapi";

export interface Post {
  id:        string;
  title:     string;
  body:      string;
  published: boolean;
  author:    string;
}

export function makePost(): Post {
  return {
    id:        faker.string.ulid(),
    title:     faker.lorem.sentence(),
    body:      faker.lorem.paragraphs(2),
    published: faker.datatype.boolean(),
    author:    faker.person.fullName(),
  };
}

Use AppResponse.array(count, factory) to generate a list where every item gets independently generated values:

handler: () => AppResponse.success({ data: AppResponse.array(10, makePost) }),

Responses

All responses are created with static factory methods on AppResponse:

AppResponse.success({ data: { id: 1 } })         // 200
AppResponse.created({ data: { id: 42 } })        // 201
AppResponse.noContent()                          // 204
AppResponse.redirect(url, status)                // 301/302/307/308
AppResponse.unauthenticated({ message: "..." })  // 401
AppResponse.unauthorised({ message: "..." })     // 403
AppResponse.notFound({ message: "..." })         // 404
AppResponse.error({ message: "..." })            // 500

Validation

Add a request field with Zod shapes for body, query, and/or headers:

import { z } from "@simapi/simapi";

request: {
  body: {
    email:    z.string().email(),
    password: z.string().min(8),
    role:     z.enum(["admin", "member"]).optional(),
  },
  query: {
    page: z.coerce.number().int().min(1).optional(),
  },
},
handler: (req) => {
  req.errors.throwValidationError("laravel");  // throws 422 only when hasError is true
  return AppResponse.created({ data: {} });
},

z is re-exported directly from @simapi/simapi — no separate zod install needed.

Define shared RequestDefinition objects in src/requests/ to reuse validation logic across endpoints. SimAPI supports body (JSON), form (multipart/urlencoded), query, and headers:

// src/requests/postRequest.ts
import { z, type RequestDefinition } from "@simapi/simapi";

export const postRequest: RequestDefinition = {
  body: { // for application/json
    title: z.string().min(3),
    body:  z.string().min(10),
  },
  form: { // for multipart/form-data or application/x-www-form-urlencoded
    category: z.string().optional(),
  },
};

Auto-throw

Set autoThrowValidationErrors in your config to skip the manual call entirely:

export default defineConfig({
  name: "my-api",
  autoThrowValidationErrors: "laravel",  // or "zod"
});

Error formats

Laravel ("laravel", default):

{ "message": "The given data was invalid.", "errors": { "email": ["Invalid email"] } }

Zod ("zod"):

{ "issues": [{ "path": ["email"], "message": "Invalid email" }] }

Authentication

Set authHandler in your config to protect all type: "secure" endpoints. SimAPI ships ready-made factories for common schemes:

import { defineConfig, AuthHandlers } from "@simapi/simapi";

export default defineConfig({
  name: "my-api",
  authHandler: AuthHandlers.bearer(),   // requires Authorization: Bearer <token>
});

Built-in handlers: bearer(), jwt(), basic(), apiKey(name, via), cookie(name), oauth2(), hmac(), digest().

Or write your own:

import { defineConfig, AppResponse, type AuthHandler } from "@simapi/simapi";

const authHandler: AuthHandler = (req) => {
  if (!req.header("Authorization"))
    return AppResponse.unauthenticated({ message: "Missing token" });
};

export default defineConfig({ name: "my-api", authHandler });

Simulating failures and latency

export const getOrders: EndpointDefinition = {
  path: "/api/orders",
  method: "GET",
  type: "open",
  failRate: 0.1,   // 10% chance of a simulated 500
  delay: 300,      // 300ms artificial latency on every request
  handler: () => AppResponse.success({ data: [] }),
};

Configuration

Create simapi.config.ts at your project root:

import { defineConfig } from "@simapi/simapi";

export default defineConfig({
  name: "my-api",
  port: 3000,
  endpointsDir: "./endpoints",
  consoleLog: false,
  autoThrowValidationErrors: "laravel",
  database: {
    type: "sqlite",
    path: "./.simapi/db.sqlite",
  },
});

Database adapters

| Adapter | Config | | ---------------- | ----------------------------------------------------------- | | SQLite (default) | { type: "sqlite", path: "./.simapi/db.sqlite" } | | libSQL / Turso | { type: "libsql", url: "libsql://...", authToken: "..." } | | Postgres | { type: "postgres", url: process.env.DATABASE_URL } | | None | { type: "none" } |


OpenAPI

SimAPI features a sophisticated OpenAPI 3.0/3.1 engine powered by @simapi/openapi.

Import — generate a structured architecture of endpoints, requests, and models from a spec:

npx @simapi/openapi import openapi.yaml -o ./src
  • Modular Output: Automatically organizes code into endpoints/, requests/, and models/.
  • Mock Factories: Generates recursive make{Model} functions using @faker-js/faker.
  • OAS 3.1 Support: Full support for the latest specs, including complex schema dialects.
  • Typed Codegen: Generates Zod validation for constraints like min, max, email, uuid.

Export — produce a high-quality OpenAPI 3 spec from your endpoints:

npx @simapi/openapi export -o docs/api.yaml

Debug console

Install the optional browser UI to inspect live requests, browse your schema, and fire test requests:

npx simapi console:add

Then open http://localhost:3000/__simapi/console/ while simapi serve is running.

Version 0.0.8+: The console now persists your Authentication state and custom Headers to localStorage and supports switching between JSON and Form inputs for testing.

See @simapi/console for details.


CLI reference

| Command | Description | | ----------------------- | -------------------------------------------------------- | | simapi serve | Start dev server with live TypeScript reload | | simapi dev | Start dev server with file watching — auto-restarts | | simapi build | Compile project to .simapi/dist/server.mjs | | simapi start | Run the compiled production server | | simapi init [name] | Scaffold a new SimAPI project | | simapi interactive | Menu-driven CLI — setup, console, import/export | | simapi import <spec> | Generate endpoint stubs from an OpenAPI spec | | simapi export | Export endpoints as an OpenAPI 3 spec | | simapi setup <target> | Generate config files (docker, vercel, netlify) | | simapi console:add | Install @simapi/console | | simapi console:remove | Uninstall @simapi/console |


Contributing

@simapi/simapi is open source and contributions are welcome and appreciated — whether it's a bug report, a feature suggestion, a doc fix, or a pull request.

See CONTRIBUTING.md for local setup, development workflow, code style, and how to submit a PR.


License

MIT