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

apiryner

v0.4.4

Published

Official TypeScript SDK, CLI, and MCP server for Apiryner — JSON layout-based random data generation API

Readme

apiryner

한국어

Official TypeScript SDK, CLI, and MCP server for Apiryner — a JSON layout-based random data generation API. Define a layout once, then pull realistic, reproducible mock data as JSON or CSV.

npm install apiryner

Zero runtime dependencies. Node.js 18+ (uses global fetch).

SDK

import { Apiryner } from "apiryner";

const api = new Apiryner({ apiKey: process.env.APIRYNER_KEY });

const users = await api.generate("user-profile", {
  count: 100,
  seed: 42,      // same seed → same data
  locale: "ko",
});

An API key is read-only, so it answers generate, getSnapshot, and the list* calls. Anything that writes — createLayout, createSnapshot, createBundle, and the update*/delete* calls — needs an OAuth bearer token with the write scope.

Extra entry points:

  • apiryner/mock — offline mock generation from a schema, no API calls
  • apiryner/webhook — webhook signature verification helpers
  • apiryner/react, apiryner/vue — data-fetching adapters

Snapshots

A snapshot pins a generated result and serves it unchanged. shape decides what gets stored:

await api.createSnapshot({
  layout_slug: "user-profile",
  name: "Checkout fixture",
  slug: "checkout-fixture",
  count: 1,
  seed: 42,
  shape: "object",  // "auto" (default) follows the layout; "object" and "array" override it
});

auto is the historical rule and stays the default — a non-array layout, or a request for a single record, pins a bare object rather than a one-element array.

CLI

npx apiryner login                                  # or: export APIRYNER_API_KEY=ak_...
npx apiryner generate user-profile -n 100 --seed 42 --format csv -o fixtures/users.csv
npx apiryner quick '{"id":"sequence","email":"email","age":"integer:18-65"}' -n 10 --locale ko
npx apiryner import openapi.yaml --type openapi --schema User   # JSON or YAML
npx apiryner codegen --lang typescript -o types/    # every layout on the account
npx apiryner serve --port 4000                      # local mock server from .apiryner.json
npx apiryner seed --layout users -n 500 --db postgres://localhost/dev

Commands

| Command | What it does | |---------|--------------| | login / logout / whoami | OAuth login in the browser, drop the saved session, print the current account | | config set\|get\|unset\|list <key> [value] | Read and write ~/.apiryner/config.json | | generate <slug> | Generate records from a saved layout | | quick <schema-json> | quick -f <file> | Generate from a schema without an account | | init | Interview you for fields and write .apiryner.json | | layouts list\|pull\|push\|diff\|validate | Keep local schema files and the account in sync | | import <file> | Turn a sample JSON, JSON Schema, OpenAPI, or SQL file into a layout | | export <slug> | Export a saved layout as JSON Schema | | codegen [slug\|file] | Generate TypeScript, Zod, Prisma, Swift, or Kotlin types | | serve | Run a local mock server from a schema file | | mcp | Run the MCP server on stdio (see below) | | seed --layout <slug> | Emit or insert PostgreSQL rows | | fixture [file] | Write fixture files from a manifest | | bundle list\|generate\|preview <slug> | Work with bundles of related layouts | | snapshot <slug> | Fetch a pinned snapshot |

Shared options: -n/--count, --seed, --locale, --format json|csv, -o/--out, -f/--file, --key, --base-url, -h/--help, -v/--version. Run npx apiryner --help for the rest.

The exit code is 0 on success, 1 when a request or the runtime fails, and 2 when the command line itself is wrong — so CI can tell a bad flag from a bad response.

Authentication and config

apiryner login runs an OAuth PKCE flow in your browser and stores the session in ~/.apiryner/credentials; expired access tokens are refreshed automatically on the next command. It needs a client ID, from --client-id, $APIRYNER_CLIENT_ID, or apiryner config set client-id <id>.

Credentials are resolved in this order: --key or $APIRYNER_API_KEY, then the OAuth session, then the API key in ~/.apiryner/config.json. apiryner config manages that file — list redacts anything that looks like a key, token, secret, or password, and get refuses to print those keys at all. base-url is the useful non-secret entry, pointing every command at a different API host.

Layouts as files

init asks for a name, a slug, and then field:type lines — email:email, age:integer — and offers the options each type supports (a range for integer, values for enum, a target for reference, …), recursing into object and array fields. It writes .apiryner.json, which is what serve reads by default. Outside a TTY it writes a starter schema instead of prompting.

npx apiryner layouts list                       # slugs and schemas on the account
npx apiryner layouts pull user-profile          # writes user-profile.json
npx apiryner layouts push user-profile.json     # creates, or updates when the slug exists
npx apiryner layouts diff user-profile          # local file vs. remote schema
npx apiryner layouts validate user-profile.json # offline schema check

diff compares against <slug>.json unless you pass a path, and normalizes key order so only real differences show up. push validates before sending.

Schema import, export, and codegen

import reads --type json-sample (the default — it infers types from a sample document), jsonschema, openapi, or sql, and prints a layout ready for layouts push. OpenAPI documents hold many schemas, so --schema User picks one out of components.schemas. --name and --slug override what is derived from the filename. export <slug> --type jsonschema goes the other way.

npx apiryner import users.sql --type sql -o users.json
npx apiryner codegen user-profile --lang swift -o Models/User.swift
npx apiryner codegen ./user-profile.json --lang zod   # local file, no account needed

codegen takes a slug, a local schema file, or nothing at all — with no argument it generates every layout on the account. Pass a directory (-o types/) and each layout lands in its own file with the extension its language expects.

Bundles and snapshots

npx apiryner bundle list
npx apiryner bundle generate ecommerce-set          # every layout in the bundle, references intact
npx apiryner bundle preview ecommerce-set --tree    # reference graph as a tree
npx apiryner snapshot checkout-fixture              # pinned data, unchanged between calls

bundle <slug> on its own is shorthand for bundle generate <slug>.

Offline generation and locales

quick and serve generate in-process, so they need no account — and neither do the schema-only commands init, import, layouts validate, and codegen <file>. fixture and seed do call the API, so they need credentials like generate does. --locale accepts en, ja, ko, zh, and random (a language per record); the mock server also reads ?locale= per request. Offline pools are smaller than the API's, so use the API when you need variety.

Seeding a database

seed prints PostgreSQL INSERT statements by default. Pass --db postgres://… to insert directly — that path needs pg installed alongside the CLI (npm install pg) and runs in one transaction, so a failure rolls the whole batch back. --dry-run prints the SQL instead of connecting, and --name overrides the table name when it differs from the layout slug.

Fixture manifests

fixture reads .apiryner.yml (or --config <file>) written in ordinary block YAML — nested mappings, sequences, flow collections, quoted strings, block scalars, and comments. Anchors, aliases, tags, and multi-document files are rejected rather than silently misread.

MCP server

apiryner mcp runs a Model Context Protocol server on stdio, so AI coding agents (Claude Code, Cursor, Claude Desktop, …) can generate mock data and read your layouts as tool calls instead of shelling out.

claude mcp add apiryner -- npx apiryner mcp

For clients configured through JSON (mcpServers):

{
  "mcpServers": {
    "apiryner": {
      "command": "npx",
      "args": ["apiryner", "mcp"],
      "env": { "APIRYNER_API_KEY": "ak_..." }
    }
  }
}

Tools

| Tool | Auth | Arguments | |------|------|-----------| | list_types | optional | — | | validate_schema | — | schema (required) | | infer_schema | — | input (required), type: json-sample (default) / json-schema / openapi / sql | | quick_generate | — | schema (required), count, seed | | list_layouts | required | limit, offset | | create_layout | required | name, slug, schema (all required), locale, is_array, array_count | | update_layout | required | slug (required), plus at least one of name, schema, locale, is_array, array_count | | generate | required | slug (required), count, seed, locale, format: json / csv | | generate_bundle | required | slug (required) | | get_snapshot | required | slug (required) |

validate_schema, infer_schema, and quick_generate run entirely in the local process — no account, no network — so an agent can produce fixtures or turn an OpenAPI file into a layout schema before you have signed up. Pass the same seed to get identical records across calls.

list_types is what keeps an agent from inventing field types. Authenticated, it returns the full catalog from the API with each type's description, category, and supported locales; unauthenticated, it falls back to the type names compiled into this package rather than failing, so the agent always has a real list to work from.

// quick_generate
{
  "schema": { "id": "sequence", "name": { "type": "name" }, "age": "integer:18-65" },
  "count": 5,
  "seed": 42
}

The account-backed tools call api.apiryner.com against your saved layouts. Have the agent run list_layouts first to discover slugs. generate_bundle returns several related layouts in one call with reference fields resolved, so seeded records line up across layouts; get_snapshot returns pinned data that never changes between calls.

create_layout and update_layout write to your account — update_layout overwrites the fields it is given on an existing layout. Both validate the schema locally first, so a malformed schema fails before any request is sent.

Authentication

Credentials are resolved once, lazily, on the first tool call that needs the API — in this order:

  1. --key <key> passed after apiryner mcp, or $APIRYNER_API_KEY
  2. the OAuth session from apiryner login (refreshed automatically when expired)
  3. the API key stored by apiryner config set api-key <key>

Starting the server unauthenticated is fine: the account-backed tools return an isError result explaining what is missing, and they start working as soon as you log in — no restart needed. --base-url (or apiryner config set base-url <url>) points the server at a different API host.

Notes

  • stdio transport only, tools capability only; protocol versions 2025-06-18, 2025-03-26, 2024-11-05.
  • stdout carries nothing but JSON-RPC messages — the startup banner goes to stderr.
  • The server is implemented in-package with no MCP SDK dependency, so it inherits the zero-dependency install.

Documentation

Full API reference and guides: https://apiryner.com/docs

License

MIT