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

prototypey

v0.3.7

Published

atproto lexicon typescript toolkit

Readme

prototypey

A fully-featured sdk for developing lexicons with typescript.

Below this is the docs and features of the library. If you'd like the story for why prototypey exists and what it's good for: that's published here

Features

  • atproto spec lexicon authoring with in IDE docs & hints for each attribute (ts => json)
  • CLI to generate json from ts definitions
  • CLI to generate ts from json definitions
  • inference of usage type from full lexicon definition
    • the really cool part of this is that it fills in the refs from the defs all at the type level
  • lx.lexicon(...).validate(data) for validating data using @atproto/lexicon
  • fromJSON() helper for creating lexicons directly from JSON objects with full type inference

Installation

npm install prototypey

Usage

Prototypey provides both a TypeScript library for authoring lexicons and a CLI for code generation.

Authoring Lexicons

what you'll write:

const lex = lx.lexicon("app.bsky.actor.profile", {
  main: lx.record({
    key: "self",
    record: lx.object({
      displayName: lx.string({ maxLength: 64, maxGraphemes: 64 }),
      description: lx.string({ maxLength: 256, maxGraphemes: 256 }),
    }),
  }),
});

generates to:

{
  "lexicon": 1,
  "id": "app.bsky.actor.profile",
  "defs": {
    "main": {
      "type": "record",
      "key": "self",
      "record": {
        "type": "object",
        "properties": {
          "displayName": {
            "type": "string",
            "maxLength": 64,
            "maxGraphemes": 64
          },
          "description": {
            "type": "string",
            "maxLength": 256,
            "maxGraphemes": 256
          }
        }
      }
    }
  }
}

you could also access the json definition with lex.json().

Runtime Validation

Prototypey provides runtime validation using @atproto/lexicon:

const lex = lx.lexicon("app.bsky.actor.profile", {
  main: lx.record({
    key: "self",
    record: lx.object({
      displayName: lx.string({ maxLength: 64, maxGraphemes: 64 }),
      description: lx.string({ maxLength: 256, maxGraphemes: 256 }),
    }),
  }),
});

// Validate data against the schema
const result = lex.validate({
  displayName: "Alice",
  description: "Software engineer",
});

if (result.success) {
  console.log("Valid data:", result.value);
} else {
  console.error("Validation error:", result.error);
}

Validating against specific definitions:

If your lexicon has multiple definitions, you can validate against a specific one:

const lex = lx.lexicon("app.bsky.feed.post", {
  user: lx.object({
    handle: lx.string({ required: true }),
    displayName: lx.string(),
  }),
  main: lx.record({
    key: "tid",
    record: lx.object({
      text: lx.string({ required: true }),
      author: lx.ref("#user", { required: true }),
    }),
  }),
});

// Validate against the "user" definition
const userResult = lex.validate(
  { handle: "alice.bsky.social", displayName: "Alice" },
  "user",
);

// Validate against "main" (default if not specified)
const postResult = lex.validate({
  text: "Hello world",
  author: { handle: "bob.bsky.social" },
});

CLI Commands

The prototypey package includes a CLI with two main commands:

gen-emit - Emit JSON schemas from TypeScript

prototypey gen-emit <outdir> <sources...>

Extracts JSON schemas from TypeScript lexicon definitions.

Example:

prototypey gen-emit ./lexicons ./src/lexicons/**/*.ts

gen-from-json - Generate TypeScript from JSON schemas

prototypey gen-from-json <outdir> <sources...>

Generates TypeScript files from JSON lexicon schemas using the fromJSON helper. This is useful when you have existing lexicon JSON files and want to work with them in TypeScript with full type inference.

Example:

prototypey gen-from-json ./src/lexicons ./lexicons/**/*.json

This will create TypeScript files that export typed lexicon objects:

// Generated file: src/lexicons/app.bsky.feed.post.ts
import { fromJSON } from "prototypey";

export const appBskyFeedPost = fromJSON({
  // ... lexicon JSON
});

Typical Workflows

TypeScript-first workflow

  1. Author lexicons in TypeScript using the library
  2. Emit JSON schemas with gen-emit for runtime validation

Recommended: Add as a script to your package.json:

{
  "scripts": {
    "lexicon:emit": "prototypey gen-emit ./schemas ./src/lexicons/**/*.ts"
  }
}

Then run:

npm run lexicon:emit

JSON-first workflow

  1. Start with JSON lexicon schemas (e.g., from atproto)
  2. Generate TypeScript with gen-from-json for type-safe access

Recommended: Add as a script to your package.json:

{
  "scripts": {
    "lexicon:import": "prototypey gen-from-json ./src/lexicons ./lexicons/**/*.json"
  }
}

Then run:

npm run lexicon:import

Please give any and all feedback. I've not really written many lexicons much myself yet, so this project is at a point of "well I think this makes sense". Both the issues page and discussions are open and ready for y'all 🙂.

Call For Contribution:

We need library art! Please reach out if you'd be willing to contribute some drawings or anything :)