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

@amritk/mjst

v0.11.0

Published

Generate TypeScript parsers and type definitions from JSON Schemas.

Readme

@amritk/mjst

Generate TypeScript parsers and type definitions from JSON Schemas.

status  version  license  JSON Schema  node  vibe coded


Overview

@amritk/mjst is the command-line entry point for mjst. Point it at a JSON Schema and it produces TypeScript parsers, validators, and type definitions in the directory of your choice.

Options can be supplied via CLI flags or a JSON config file. CLI flags always take precedence over config file values.

It also carries a lint subcommand — mjst lint <files> — a format-agnostic JSON/YAML style-guide linter powered by @amritk/lint. See Linting.


Installation

npm install --save-dev @amritk/mjst
# or
pnpm add -D @amritk/mjst
# or
yarn add -D @amritk/mjst
# or
bun add -d @amritk/mjst

The package ships a mjst bin that runs under Node ≥ 20 (or Bun), so you can invoke it via npx mjst, pnpm dlx mjst, yarn dlx mjst, bunx mjst, or as a script in package.json.


Usage

CLI

npx mjst --schema ./schema.json --out-dir ./generated

[!NOTE] Every flag accepts both kebab-case and camelCase, so --out-dir and --outDir are equivalent.

Single file

Pass --out-file instead of --out-dir to concatenate every generated definition into one self-contained file. This is currently supported together with --types-only:

npx mjst --schema ./schema.json --out-file ./generated/schema.ts --types-only

Recursive — a whole folder of schemas

Point --schema-dir at a directory of JSON Schemas and mjst generates parsers for every *.json file it finds, mirroring the directory layout under --out-dir:

npx mjst --schema-dir ./schemas --out-dir ./generated
schemas/                  generated/
  user.json        ─▶       user/
  api/                        user.ts, index.ts
    order.json     ─▶       api/order/
                              order.ts, index.ts
                            _helpers/        ← shared runtime helpers (embedded mode)

Each schema lands in its own subdirectory so generated files never collide, and in embedded mode the runtime helpers are emitted once into outDir/_helpers/ — every nested parser imports from that single shared location. --build compiles the whole tree in place. Each schema's root type is named after the schema (its title, else its filename in PascalCase), so user.json yields User / parseUser and api/order.json yields Order / parseOrder.

Running the generated output

By default mjst emits relative imports with the literal .ts extension (e.g. import { parseUser } from './user.ts'), so the generated sources run as-is — no build step — under:

  • Bun (bun run generated/index.ts)
  • Node ≥ 22.6 type stripping (node generated/index.ts; unflagged from 22.18/23, else pass --experimental-strip-types)
  • tsc, provided your tsconfig.json sets "allowImportingTsExtensions": true

If you'd rather compile the output first, pass --build (mjst switches the imports to the NodeNext ./user.js form and runs tsc for you), or generate with --import-ext js to emit the compile-ready form without building. --import-ext ts together with --build is rejected, since tsc cannot emit from .ts specifiers.

[!NOTE] Breaking change (0.9.0): the root type is no longer always named Document. It is derived from the schema title, falling back to the schema filename (spec-plan.jsonSpecPlan, giving parseSpecPlan / validateSpecPlanShape). Pass --root-type <Name> to override it for a single --schema run. Update any imports that referenced Document / parseDocument.

Config file

npx mjst --config ./mjst.config.json

[!NOTE] Validate your config against the bundled JSON Schema: config.schema.json


Linting

mjst lint lints JSON/YAML documents against a ruleset — JSON Schema validation and custom style rules, with exact line:column findings. It has its own flags (and its own --help), independent of the generation flags above.

# Lint files against an explicit ruleset
npx mjst lint "**/*.{yaml,json}" -r .lint.yaml

# Auto-discover a .lint.* ruleset by walking up from each file
npx mjst lint config/

# Lint piped input
cat service.yaml | npx mjst lint --stdin-filepath service.yaml

Findings are printed as a compact, editor-clickable report:

config/service.yaml:2:7  error  config-schema  /port must be integer

✖ 1 problem(s) (1 error(s), 0 warning(s))

With no -r, mjst discovers a .lint.{yaml,yml,json,js,mjs} ruleset by walking up from each linted file. A ruleset maps a JSONPath (given) to a function (then) — schema (JSON Schema), casing, pattern, truthy, and more, plus your own. The @amritk/lint README documents the ruleset format and built-in functions. For machine-readable output (JSON, SARIF, …), call the @amritk/lint library's lintDocument, which returns structured findings.

| Flag | Description | | --- | --- | | <documents..> | Files or globs to lint (positional). | | -r, --ruleset | Path to a ruleset file. Defaults to .lint.* discovery. | | -F, --fail-severity | Minimum severity that fails the run: error (default), warn, info, hint. | | -D, --display-only-failures | Only show findings at or above --fail-severity. | | --stdin-filepath | Path to associate with piped input (labels findings and enables ruleset discovery). | | --concurrency | Max documents linted in parallel (default 8). | | --no-resolve | Skip $ref dereferencing; rules see the raw document. | | --resolve-remote | Fetch http(s) $refs while resolving (off by default; a lint run stays offline). | | --allowed-hosts | Restrict remote $ref fetches to these hosts (implies --resolve-remote). | | --allow-private-hosts | Permit remote $refs to private/loopback hosts (SSRF guard, off by default). | | -q, --quiet | Suppress the findings report (the exit code still reflects findings). |

By default mjst lint dereferences $ref, $dynamicRef/$dynamicAnchor, and $recursiveRef/$recursiveAnchor before running rules, so rules with resolved: true (the ruleset default) see through references. Internal and local cross-file refs resolve from disk — a finding on a cross-file node reports that file's own line:column — while remote refs are only fetched when you opt in with --resolve-remote or --allowed-hosts.

The exit code is 0 when no finding reaches --fail-severity, 1 when one does, and 2 on a usage error. Run mjst lint --help for the full list.


Configuration reference


Config file examples

Minimal — generate parsers and types

{
  "schema": "./schema.json",
  "outDir": "./generated"
}

Types only — skip parser functions

{
  "schema": "./schema.json",
  "outDir": "./generated",
  "typesOnly": true
}

Build — emit .js and .d.ts instead of .ts

{
  "schema": "./schema.json",
  "outDir": "./generated",
  "build": true
}

Log warnings — warn on unknown input properties

{
  "schema": "./schema.json",
  "outDir": "./generated",
  "logWarnings": true
}

Scripts

| Script | Command | |:---|:---| | bun run dev | bun run --conditions=development ./src/cli.ts | | bun run start | bun run ./src/cli.ts | | bun run build | bun run build:code && bun run build:types | | bun run generate-readme | bun run generate-readme |


License

MIT