Skip to content

Generating a Spec ​

generateSwagger() is the entry point. It takes a single options object — including a pre-built Metadata value — and returns an in-memory OpenAPI document. @trapi/swagger does not depend on @trapi/metadata or the TypeScript compiler; produce the metadata however you like.

Minimal Call ​

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

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

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

generateMetadata (TypeScript-based extractor) and generateSwagger (OpenAPI emitter) compose. Reuse the same metadata for multiple emit targets so the TypeScript walk runs once:

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

Bringing Your Own Metadata ​

generateSwagger only requires a value matching the framework-neutral Metadata shape ({ controllers, referenceTypes }). You can supply one from any source — a JSON cache file, a Babel-based extractor, or a hand-rolled fixture for testing — without installing @trapi/metadata:

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

const metadata: Metadata = JSON.parse(await fs.readFile('cache/metadata.json', 'utf8'));

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

Choosing a Version ​

versionspec.openapi / headerEmitter
'v2'swagger 2.0V2Generator
'v3''3.0.0'V3Generator in 3.0 mode
'v3.1''3.1.0'V3Generator in 3.1-or-later mode
'v3.2''3.2.0'V3Generator in 3.1-or-later mode

The v3.x values all use the same V3Generator class but with minor behavioural differences — most visibly, 'v3.1' and 'v3.2' allow $ref siblings (OpenAPI 3.1 relaxed that restriction), while 'v3' strips them for spec compliance. The version parameter is type-narrowing: the return type of generateSwagger is SpecV2 for 'v2' and SpecV3 for any v3.x value.

Supplying Document Data ​

Everything on the OpenAPI info block, servers, securityDefinitions, and default content types goes through data:

typescript
await generateSwagger({
    version: 'v3',
    metadata,
    data: {
        name: 'Example API',
        version: '1.0.0',
        description: 'REST API for example service',
        license: 'MIT',
        servers: ['https://api.example.com', 'https://staging.example.com'],
    },
});

See Document Data for every field.

Defaults from package.json ​

If you omit name, version, description, or license, TRAPI reads them from the nearest package.json. This is convenient during development but easy to overlook — an explicit data object is more predictable in CI.

In-Memory vs Saving ​

generateSwagger() returns the spec as a plain object. You can:

  • write it yourself (fs.writeFileSync(path, JSON.stringify(spec)))
  • pass it to saveSwagger() for JSON/YAML output to a directory
  • feed it to an in-process renderer (Swagger UI, Redoc)
  • serve it directly from an HTTP handler
typescript
// Served from an Express handler
app.get('/openapi.json', (_, res) => res.json(spec));

For file output, see Saving Output.