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

@trapi/cli

v2.0.0

Published

CLI for generating REST-API metadata and OpenAPI / Swagger specifications.

Readme

@trapi/cli ⚡

main codecov Known Vulnerabilities npm version

A command-line wrapper around @trapi/metadata and @trapi/swagger. Point it at your sources and it emits an OpenAPI / Swagger document — config-file driven for non-trivial setups, single-flag invocations for quick scripts.

Built on citty--help is wired up automatically and arguments are validated up-front.

Table of Contents

Installation

npm install --save-dev @trapi/cli

The CLI ships a trapi bin. Install it in the project that owns the controllers — @trapi/metadata and @trapi/swagger are pulled in transitively, but you'll typically also install the preset you want to use (e.g. @trapi/preset-decorators-express or @trapi/preset-typescript-rest).

Quick Start

npx trapi generate \
  --preset @trapi/preset-decorators-express \
  --entry-point 'src/**/*.ts' \
  --output docs/openapi.json \
  --version 3.1

The example above:

  1. Loads the @trapi/preset-decorators-express preset.
  2. Scans every .ts file under src/ for decorated controllers.
  3. Generates an OpenAPI 3.1 document.
  4. Writes it to docs/openapi.json (the .json extension picks the format automatically).

Pass --format yaml or use a .yaml/.yml extension to emit YAML instead. Both --version 3.1 and --version v3.1 are accepted.

Configuration File

Anything beyond a one-liner is easier in a config file. The CLI auto-discovers trapi.config.{ts,mts,cts,mjs,cjs,js,json} (or a trapi field in package.json) in the working directory.

// trapi.config.ts
import { defineConfig } from '@trapi/cli';

export default defineConfig({
    metadata: {
        entryPoint: 'src/controllers/**/*.ts',
        preset: '@trapi/preset-decorators-express',
        tsconfig: 'tsconfig.json',
        ignore: ['**/*.spec.ts'],
        cache: true,
    },
    swagger: {
        version: 'v3.2',
        data: {
            name: 'My API',
            servers: ['https://api.example.com'],
            securityDefinitions: {
                bearer: { type: 'apiKey', name: 'Authorization', in: 'header' },
            },
        },
    },
    output: {
        path: 'docs/openapi.json',
    },
});

defineConfig is an identity helper — pass any TrapiConfig and you get IDE autocompletion + type checking. The shape mirrors the underlying option types (MetadataGenerateOptions, SwaggerGenerateData, DocumentFormat), so anything those accept is reachable from config.

CLI flags override config

CLI flags always win. Drop a config in your repo for the common case, then override per-invocation:

trapi generate --version v3.1 --output docs/openapi.v3.1.json

Use --config <path> to point at a non-discovered file, or --no-config to skip discovery entirely.

Multi-target output

Export an array to emit several specs from one metadata pass — entries with identical metadata options share extraction:

// trapi.config.ts
import { defineConfig } from '@trapi/cli';

const shared = {
    metadata: {
        entryPoint: 'src/controllers/**/*.ts',
        preset: '@trapi/preset-decorators-express',
    },
};

export default defineConfig([
    { ...shared, swagger: { version: 'v3.2' }, output: { path: 'dist/openapi.v3.2.json' } },
    { ...shared, swagger: { version: 'v2'   }, output: { path: 'dist/openapi.v2.yaml'  } },
]);

Commands

trapi generate

Generate an OpenAPI / Swagger specification from decorated TypeScript sources.

trapi generate [OPTIONS]

| Flag | Description | Default | |------|-------------|---------| | --entry-point | Glob pattern matching the source files to scan. Required if not set in config. | config | | --preset | Preset to load (npm package name or local path). | config | | --tsconfig | Path to a tsconfig.json used to compile the sources. | config | | --ignore | Comma-separated globs to skip during the source-file scan. | config | | --allow | Comma-separated globs to include during the source-file scan. | config | | --cache | Cache the generated metadata between runs. | false | | --strict | true warns on unmatched decorators, throw errors out. | off | | --output | Output file path. The extension picks the format unless --format is set. | swagger.json | | --format | Output document format (json | yaml). | inferred from --output | | --version | OpenAPI specification version (v2 | v3 | v3.1 | v3.2). The leading v is optional. | v3 | | --api-name | API name written into the spec info object. | package.json | | --api-version | API version written into the spec info object. | package.json | | --api-description | API description written into the spec info object. | package.json | | --servers | Comma-separated server URLs written into spec.servers. | config | | --security-definitions | JSON string of security scheme definitions. | config | | --cwd | Working directory. Relative paths in config + flags are resolved against it. | process.cwd() | | --config | Path to a config file. Disables discovery. | auto-discover | | --no-config | Skip config discovery and ignore --config. | false | | --log-level | silent | info | debug. | info |

Run trapi generate --help to see this list rendered against the installed version.

Examples

Generate a YAML 3.0 spec from controllers under src/api/:

trapi generate \
  --entry-point 'src/api/**/*.ts' \
  --preset @trapi/preset-decorators-express \
  --output docs/openapi.yaml \
  --version 3

Pass security schemes inline (escape hatch when you don't want a config file):

trapi generate \
  --entry-point 'src/**/*.ts' \
  --preset @trapi/preset-decorators-express \
  --servers https://api.example.com \
  --security-definitions '{"bearer":{"type":"apiKey","name":"Authorization","in":"header"}}'

Treat unmatched decorators as errors (catches typos like @Hiden in CI):

trapi generate --entry-point 'src/**/*.ts' --strict throw

trapi watch

Re-run generate whenever source files or the config change. Accepts the same flags as trapi generate, plus --clear to reset the console between runs.

trapi watch --entry-point 'src/**/*.ts' --preset @trapi/preset-decorators-express

The watcher uses chokidar — atomic writes from editors are handled, and the CLI's own output files are excluded from triggering re-runs.

trapi info

Print version + environment diagnostics for bug reports.

$ trapi info
trapi 0.2.0
node v22.21.1
platform darwin arm64
cwd /path/to/project
config /path/to/project/trapi.config.ts
entries 1
@trapi/core 2.0.0
@trapi/metadata 2.0.0
@trapi/swagger 2.0.0
typescript 5.5.4

trapi cache clean

Delete cached metadata files (.trapi-metadata-*.json).

trapi cache clean                            # wipe the OS tmpdir
trapi cache clean --directory .trapi-cache   # wipe a custom dir
trapi cache clean --max-age 604800000        # only delete files older than 7 days

The metadata cache evicts files older than maxAgeMs automatically after each successful run; this command is for manual cleanup when you want to force a cold rebuild.

Programmatic Usage

The same factory the bin uses is exported from the package:

import { runMain } from 'citty';
import { createCLIEntryPointCommand } from '@trapi/cli';

const command = await createCLIEntryPointCommand();
await runMain(command);

For one-shot programmatic generation, compose @trapi/metadata + @trapi/swagger directly:

import { generateMetadata } from '@trapi/metadata';
import { generateSwagger, saveSwagger } from '@trapi/swagger';

const metadata = await generateMetadata({
    entryPoint: 'src/**/*.ts',
    preset: '@trapi/preset-decorators-express',
});

const spec = await generateSwagger({ version: 'v3.1', metadata });

await saveSwagger(spec, { name: 'openapi', cwd: 'docs' });

Structure

src/
├── bin.ts            # #!/usr/bin/env node — calls runMain()
├── module.ts         # createCLIEntryPointCommand() — root command factory
├── config/           # Config file discovery, defineConfig, merge precedence
├── commands/
│   ├── generate.ts   # `trapi generate`
│   ├── watch.ts      # `trapi watch`
│   ├── info.ts       # `trapi info`
│   ├── cache.ts      # `trapi cache clean`
│   └── utils.ts      # Shared arg parsing + path splitting
├── logger.ts         # Tiny stderr logger + CLIUserError
├── exit.ts           # Exit-code wrapper
├── utils.ts          # readPackageJson() for citty meta
└── index.ts          # Public exports (defineConfig, createLogger, …)

License

Made with 💚

Published under MIT License.