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/swagger

v2.0.0

Published

Generate Swagger files from a decorator APIs.

Downloads

2,439

Readme

@trapi/swagger ⛱

main codecov Known Vulnerabilities npm version

Transforms TRAPI metadata into an OpenAPI specification (2.0 / Swagger, 3.0, 3.1, or 3.2) and, optionally, writes it to disk as JSON or YAML.

Inspect the CHANGELOG.md in the repository for breaking changes.

Public API

The stable public surface is documented in the API Reference. Anything not listed there should be treated as internal even if it is re-exported, and may change without a major version bump.

Table of Contents

Installation

npm install --save @trapi/swagger

@trapi/swagger only consumes a pre-built Metadata value (the framework-neutral type from @trapi/core). It does not depend on @trapi/metadata or the TypeScript compiler. Install @trapi/metadata separately if you want to extract metadata from TypeScript decorators:

npm install --save @trapi/metadata

You also need a preset matching the decorator library used by your controllers (or your own custom preset). The examples below use @decorators/express via @trapi/preset-decorators-express; install both:

npm install --save @trapi/preset-decorators-express @decorators/express

Usage

generateSwagger() takes a pre-built Metadata value and returns an OpenAPI document. Compose it with generateMetadata from @trapi/metadata for the typical TypeScript-decorator flow:

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

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

const spec = await generateSwagger({
    version: 'v3',
    metadata,
    data: {
        name: 'My API',
        version: '1.0.0',
        description: 'Example service',
        servers: 'https://api.example.com',
    },
});

await saveSwagger(spec, { cwd: './docs', format: 'yaml' });

Reuse the same metadata for multiple emit targets so the TypeScript walk runs once:

const specV3 = await generateSwagger({ version: 'v3', metadata });
const specV2 = await generateSwagger({ version: 'v2', metadata });

You can also bring your own Metadata from any source — a JSON cache file, a Babel-based extractor, or a hand-rolled fixture — without installing @trapi/metadata at all:

import { promises as fs } from 'node:fs';
import type { Metadata } from '@trapi/core';

const metadata: Metadata = JSON.parse(await fs.readFile('cache/metadata.json', 'utf8'));
const spec = await generateSwagger({ version: 'v3', metadata });

Configuration

import type { Metadata } from '@trapi/core';

export type SwaggerGenerateOptions = {
    /**
     * OpenAPI spec version to generate.
     * Accepts 'v2', 'v3', 'v3.1', 'v3.2'.
     */
    version: 'v2' | 'v3' | 'v3.1' | 'v3.2';

    /**
     * Pre-built metadata. Produce it via `generateMetadata` from `@trapi/metadata`,
     * or supply your own `Metadata`-shaped value.
     */
    metadata: Metadata;

    /**
     * Document-level content (info block, servers, security, ...).
     * All fields are optional and default to values read from the nearest package.json where possible.
     */
    data?: SwaggerGenerateData;
};

export type SwaggerGenerateData = {
    name?: string;                                    // info.title
    version?: string;                                 // info.version
    description?: string;                             // info.description
    license?: string;                                 // info.license.name
    servers?: string | string[] | ServerOption | ServerOption[];
    securityDefinitions?: SecurityDefinitions;        // OAuth2, API key, basic auth, ...
    consumes?: string[];                              // default request content types
    produces?: string[];                              // default response content types
    collectionFormat?: 'csv' | 'ssv' | 'tsv' | 'pipes' | 'multi';
    extra?: Record<string, any>;                      // merged into the final spec
};

extra is a raw spec fragment merged onto the generated output. Generated properties take precedence where keys overlap.

Saving to Disk

saveSwagger() writes the spec to cwd/name.{format}. Each call writes exactly one file — call it twice if you want both JSON and YAML. It returns the DocumentFormatData for the written file.

await saveSwagger(spec, {
    cwd: './docs',       // default: process.cwd() (relative paths resolve against it)
    name: 'openapi',     // default: 'swagger' — any trailing .json/.yaml is replaced to match format
    format: 'yaml',      // 'json' | 'yaml' — default: 'json'
});

If you need in-memory output only, skip saveSwagger() and use the value returned by generateSwagger() directly.

Supported Versions

| Version | spec.openapi | Notes | |---------|---------------|-------| | v2 | swagger 2.0 | Uses x-nullable, x-deprecated, flattens intersection types | | v3 | 3.0.0 | Uses nullable, deprecated, allOf for intersections, requestBody; strips $ref siblings for spec compliance | | v3.1 | 3.1.0 | Same emitter as v3; allows $ref siblings (OpenAPI 3.1 relaxed that restriction) | | v3.2 | 3.2.0 | Same emitter as v3.1 |

Version-specific differences that matter most:

  • Nullable types: V2 emits x-nullable: true (non-standard); V3 uses nullable: true.
  • Request body: V2 emits in: body parameters; V3 emits a top-level requestBody.
  • File uploads: V2 uses type: file formData; V3 uses multipart/form-data request bodies.
  • Intersections: V2 flattens all member properties into the object; V3 emits allOf.

Structure

src/
├── core/         # Domain types, config, OpenAPI schema types, errors
│   ├── config/
│   ├── schema/v2, v3
│   └── utils/
├── adapters/     # Emitters (V2Generator, V3Generator)
│   └── generator/abstract.ts, v2/, v3/
├── app/          # Orchestration (generateSwagger, saveSwagger)
└── index.ts      # Public entry point

License

Made with 💚

Published under MIT License.