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

@bernierllc/openapi-generator

v1.2.0

Published

Framework-agnostic OpenAPI generation orchestration service for multi-source documentation

Downloads

584

Readme

@bernierllc/openapi-generator

Framework-agnostic OpenAPI generation orchestration service for multi-source documentation.

Overview

@bernierllc/openapi-generator is a service package that orchestrates OpenAPI specification generation from multiple sources (JSDoc, Zod, TSOA, custom) using atomic core packages. It provides a unified interface for generating, validating, and optimizing OpenAPI specifications with intelligent merging and comprehensive workflow management.

Features

  • Multi-Source Support - Generate from JSDoc/TSDoc, Zod schemas, TSOA decorators, and custom sources
  • Intelligent Merging - Priority-based merging with conflict resolution strategies
  • Workflow Management - Configurable generation workflows with hooks and scheduling
  • Watch Mode - Incremental updates on file changes for development
  • Batch Processing - Process multiple APIs and monorepos efficiently
  • Output Formats - Generate JSON, YAML, and TypeScript types
  • Validation - Comprehensive OpenAPI specification validation
  • Optimization - Remove unused components, deduplicate schemas, sort properties
  • Analysis - Coverage metrics, quality scoring, and improvement suggestions
  • NeverHub Integration - Event publishing for generation lifecycle (optional)
  • Logger Integration - Structured logging support (optional)

Installation

npm install @bernierllc/openapi-generator

Quick Start

import { OpenAPIGenerator } from '@bernierllc/openapi-generator';

const generator = new OpenAPIGenerator({
  baseInfo: {
    title: 'My API',
    version: '1.0.0',
    description: 'API documentation'
  },
  sources: [
    {
      type: 'jsdoc',
      paths: ['./src/api/**/*.ts'],
      priority: 1
    },
    {
      type: 'zod',
      paths: ['./src/schemas/**/*.ts'],
      priority: 2
    }
  ],
  output: {
    json: './docs/openapi.json',
    yaml: './docs/openapi.yaml',
    types: './src/types/api.d.ts'
  },
  merge: {
    strategy: 'merge-deep',
    deduplicateComponents: true
  }
});

await generator.initialize();
const result = await generator.generate();

if (result.success) {
  console.log('Generated OpenAPI spec:', result.spec);
  console.log('Output files:', result.outputFiles);
} else {
  console.error('Generation failed:', result.errors);
}

Usage

Basic Generation

import { OpenAPIGenerator } from '@bernierllc/openapi-generator';

const generator = new OpenAPIGenerator({
  baseInfo: {
    title: 'My API',
    version: '1.0.0'
  },
  sources: [
    {
      type: 'jsdoc',
      paths: ['./src/**/*.ts']
    }
  ],
  output: {
    json: './openapi.json'
  }
});

await generator.initialize();
const result = await generator.generate();

Multiple Sources with Priorities

const generator = new OpenAPIGenerator({
  baseInfo: {
    title: 'Multi-Source API',
    version: '1.0.0'
  },
  sources: [
    {
      type: 'jsdoc',
      paths: ['./src/controllers/**/*.ts'],
      priority: 1,
      options: { strictMode: true }
    },
    {
      type: 'zod',
      paths: ['./src/schemas/**/*.ts'],
      priority: 2,
      options: { includeExamples: true }
    },
    {
      type: 'tsoa',
      paths: ['./src/api/**/*.ts'],
      priority: 3
    }
  ],
  output: {
    json: './docs/openapi.json',
    yaml: './docs/openapi.yaml',
    types: './types/api.d.ts',
    pretty: true
  },
  merge: {
    strategy: 'merge-deep',
    deduplicateComponents: true,
    mergeTags: true
  }
});

Validation and Optimization

const generator = new OpenAPIGenerator({
  baseInfo: {
    title: 'Validated API',
    version: '1.0.0'
  },
  sources: [
    {
      type: 'jsdoc',
      paths: ['./src/**/*.ts']
    }
  ],
  output: {
    json: './openapi.json'
  },
  validation: {
    strict: true,
    failOnWarnings: false,
    version: '3.1'
  },
  optimization: {
    removeUnused: true,
    inlineSimpleSchemas: true,
    sortProperties: true
  }
});

await generator.initialize();
const result = await generator.generate();

if (result.success && result.spec) {
  // Manual validation
  const validation = generator.validateGenerated(result.spec);
  console.log('Valid:', validation.valid);

  // Manual optimization
  const optimization = generator.optimizeSpec(result.spec);
  console.log('Optimization changes:', optimization.changes);
}

Watch Mode for Development

const generator = new OpenAPIGenerator({
  baseInfo: {
    title: 'Dev API',
    version: '1.0.0'
  },
  sources: [
    {
      type: 'jsdoc',
      paths: ['./src/**/*.ts']
    }
  ],
  output: {
    json: './openapi.json'
  }
});

await generator.initialize();

// Watch for file changes
const watcher = generator.watch((result) => {
  if (result.success) {
    console.log('OpenAPI spec updated!');
  } else {
    console.error('Generation failed:', result.errors);
  }
});

// Manually trigger regeneration
await watcher.regenerate();

// Stop watching
watcher.stop();

Workflow-Based Generation

import { OpenAPIWorkflowManager } from '@bernierllc/openapi-generator';

const manager = new OpenAPIWorkflowManager();

manager.registerWorkflow({
  id: 'api-docs',
  name: 'API Documentation Generation',
  sources: [
    { type: 'jsdoc', paths: ['./src/api/**/*.ts'] },
    { type: 'zod', paths: ['./src/schemas/**/*.ts'] }
  ],
  steps: [
    { name: 'discover-routes', action: 'route-discovery' },
    { name: 'parse-sources', action: 'source-parsing' },
    { name: 'merge-specs', action: 'specification-merging' },
    { name: 'validate', action: 'validation' },
    { name: 'optimize', action: 'optimization' },
    { name: 'output', action: 'file-generation' }
  ],
  hooks: {
    preGenerate: async (context) => {
      console.log('Starting generation for', context.workflow.name);
    },
    postGenerate: async (context, result) => {
      console.log('Generated', result.metadata?.pathsGenerated, 'paths');
    },
    onError: async (context, error) => {
      console.error('Generation failed:', error.message);
    }
  }
});

const result = await manager.executeWorkflow('api-docs');

Scheduled Workflows

const manager = new OpenAPIWorkflowManager();

manager.registerWorkflow({
  id: 'nightly-docs',
  name: 'Nightly Documentation',
  sources: [{ type: 'jsdoc', paths: ['./src/**/*.ts'] }],
  steps: [
    { name: 'parse', action: 'source-parsing' },
    { name: 'generate', action: 'file-generation' }
  ],
  hooks: {}
});

// Schedule to run every 60 minutes
manager.scheduleWorkflow('nightly-docs', 'every 60 minutes');

Batch Processing

const manager = new OpenAPIWorkflowManager();

const configs = [
  {
    baseInfo: { title: 'Users API', version: '1.0.0' },
    sources: [{ type: 'jsdoc', paths: ['./src/users/**/*.ts'] }],
    output: { json: './docs/users-api.json' }
  },
  {
    baseInfo: { title: 'Orders API', version: '1.0.0' },
    sources: [{ type: 'jsdoc', paths: ['./src/orders/**/*.ts'] }],
    output: { json: './docs/orders-api.json' }
  },
  {
    baseInfo: { title: 'Products API', version: '1.0.0' },
    sources: [{ type: 'zod', paths: ['./src/products/schemas.ts'] }],
    output: { json: './docs/products-api.json' }
  }
];

const batchResult = await manager.processBatch(configs);

console.log('Batch complete:', batchResult.success);
console.log('Total processed:', batchResult.results.length);
console.log('Failures:', batchResult.failures || 0);

Monorepo Support

const manager = new OpenAPIWorkflowManager();

const result = await manager.generateForMonorepo('./packages', {
  includePackages: ['api-*', 'service-*'],
  excludePackages: ['*-test'],
  outputDir: './docs/api',
  mergeStrategy: 'separate-files' // or 'combined'
});

console.log('Packages processed:', result.packages.size);
if (result.combinedSpec) {
  console.log('Combined spec generated');
}

Analysis and Quality Metrics

import { generationAnalyzer } from '@bernierllc/openapi-generator';

const generator = new OpenAPIGenerator({
  baseInfo: { title: 'My API', version: '1.0.0' },
  sources: [{ type: 'jsdoc', paths: ['./src/**/*.ts'] }],
  output: { json: './openapi.json' }
});

await generator.initialize();
const result = await generator.generate();

// Analyze result
const analysis = generationAnalyzer.analyzeResult(result);
console.log('Coverage:', analysis.coverage.percentage + '%');
console.log('Quality Score:', analysis.qualityScore);
console.log('Issues:', analysis.issues);

// Get improvement suggestions
const improvements = generationAnalyzer.identifyImprovements(result);
improvements.forEach(suggestion => {
  console.log(`[${suggestion.impact}] ${suggestion.description}`);
});

// Compare with previous version
const previousResult = /* load previous result */;
const comparison = generationAnalyzer.compareResults(previousResult, result);
console.log('Added paths:', comparison.addedPaths);
console.log('Breaking changes:', comparison.breakingChanges);

Logger Integration

import { OpenAPIGenerator } from '@bernierllc/openapi-generator';
import { Logger } from '@bernierllc/logger';

const logger = new Logger({ level: 'debug' });

const generator = new OpenAPIGenerator({
  baseInfo: { title: 'My API', version: '1.0.0' },
  sources: [{ type: 'jsdoc', paths: ['./src/**/*.ts'] }],
  output: { json: './openapi.json' }
});

// Initialize with logger
await generator.initialize(logger);

const result = await generator.generate();
// All generation steps will be logged

NeverHub Integration

When NeverHub is available, the generator automatically publishes lifecycle events:

  • openapi.generation.started - Generation begins
  • openapi.generation.progress - Step progress updates
  • openapi.source.processed - Each source processed
  • openapi.validation.completed - Validation complete
  • openapi.optimization.completed - Optimization complete
  • openapi.generation.completed - Generation successful
  • openapi.generation.failed - Generation failed

NeverHub integration is automatic and gracefully degrades when unavailable.

API Reference

OpenAPIGenerator

Main class for generating OpenAPI specifications.

Constructor

constructor(config: OpenAPIGeneratorConfig)

Methods

initialize(logger?: Logger): Promise<void>

Initialize the generator with optional logger and NeverHub integration.

generate(): Promise<GenerationResult>

Generate OpenAPI specification from all configured sources.

processJSDocSource(config: SourceConfig): Promise<OpenAPIObject>

Process a JSDoc/TSDoc source.

processZodSource(config: SourceConfig): Promise<OpenAPIObject>

Process a Zod schema source.

processTSOASource(config: SourceConfig): Promise<OpenAPIObject>

Process a TSOA decorator source.

processCustomSource(config: SourceConfig): Promise<OpenAPIObject>

Process a custom source.

generateJSON(spec: OpenAPIObject): string

Generate JSON representation of specification.

generateYAML(spec: OpenAPIObject): Promise<string>

Generate YAML representation of specification.

generateTypes(spec: OpenAPIObject, options?: TypeGenerationOptions): Promise<string>

Generate TypeScript types from specification.

validateGenerated(spec: OpenAPIObject): ValidationResult

Validate a generated specification.

optimizeSpec(spec: OpenAPIObject): OptimizationResult

Optimize a specification.

watch(callback: (result: GenerationResult) => void): WatchInstance

Watch for file changes and regenerate automatically.

generateIncremental(changes: FileChange[]): Promise<GenerationResult>

Generate based on incremental file changes.

OpenAPIWorkflowManager

Manages complex generation workflows.

Constructor

constructor(logger?: Logger)

Methods

registerWorkflow(workflow: GenerationWorkflow): void

Register a generation workflow.

executeWorkflow(workflowId: string): Promise<GenerationResult>

Execute a registered workflow.

scheduleWorkflow(workflowId: string, schedule: string): void

Schedule a workflow to run periodically.

processBatch(configs: OpenAPIGeneratorConfig[]): Promise<BatchResult>

Process multiple configurations in batch.

generateForMonorepo(rootPath: string, options: MonorepoOptions): Promise<MonorepoResult>

Generate OpenAPI specs for all packages in a monorepo.

onPreGenerate(callback: PreGenerateHook): void

Register a pre-generate hook.

onPostGenerate(callback: PostGenerateHook): void

Register a post-generate hook.

onError(callback: ErrorHook): void

Register an error hook.

unregisterWorkflow(workflowId: string): void

Unregister a workflow.

getWorkflows(): GenerationWorkflow[]

Get all registered workflows.

getWorkflow(workflowId: string): GenerationWorkflow | undefined

Get a specific workflow by ID.

cleanup(): void

Cleanup all scheduled workflows.

GenerationAnalyzer

Analyzes generation results and provides quality metrics.

Methods

analyzeResult(result: GenerationResult): AnalysisReport

Analyze a generation result.

compareResults(previous: GenerationResult, current: GenerationResult): ComparisonReport

Compare two generation results.

identifyImprovements(result: GenerationResult): ImprovementSuggestion[]

Identify potential improvements.

Singleton Instance

import { generationAnalyzer } from '@bernierllc/openapi-generator';

Configuration

OpenAPIGeneratorConfig

interface OpenAPIGeneratorConfig {
  baseInfo: InfoObject;                // Base API information
  sources: SourceConfig[];             // Documentation sources
  output: OutputConfig;                // Output configuration
  merge?: MergeConfig;                 // Merge strategy
  validation?: ValidationConfig;       // Validation settings
  optimization?: OptimizationConfig;   // Optimization settings
}

SourceConfig

interface SourceConfig {
  type: 'jsdoc' | 'zod' | 'tsoa' | 'custom';
  paths: string[];                     // Paths to scan
  options?: Record<string, unknown>;   // Source-specific options
  priority?: number;                   // Merge priority (higher wins)
  enabled?: boolean;                   // Enable/disable source
}

OutputConfig

interface OutputConfig {
  json?: string;       // JSON output path
  yaml?: string;       // YAML output path
  types?: string;      // TypeScript types output path
  pretty?: boolean;    // Pretty print output
}

MergeConfig

interface MergeConfig {
  strategy: 'merge-deep' | 'override' | 'fail-on-conflict';
  deduplicateComponents?: boolean;
  mergeTags?: boolean;
  onConflict?: (path: string, values: unknown[]) => unknown;
}

Integration Status

  • Logger: Integrated - Structured logging throughout generation lifecycle
  • Docs-Suite: Ready - Exports markdown documentation and API reference
  • NeverHub: Integrated - Event publishing for generation lifecycle (optional, graceful degradation)

Dependencies

Core Packages

  • @bernierllc/openapi-schema-builder - OpenAPI schema construction
  • @bernierllc/openapi-merger - Specification merging
  • @bernierllc/jsdoc-openapi-parser - JSDoc/TSDoc parsing
  • @bernierllc/zod-openapi-converter - Zod schema conversion

Service Packages

  • @bernierllc/file-handler - File system operations
  • @bernierllc/logger - Logging functionality
  • @bernierllc/neverhub-adapter - Event publishing

External Dependencies

  • yaml - YAML generation
  • swagger2openapi - OpenAPI version conversion
  • chokidar - File watching

TypeScript

This package is written in TypeScript and includes complete type definitions.

import type {
  OpenAPIGeneratorConfig,
  GenerationResult,
  WorkflowContext,
  AnalysisReport
} from '@bernierllc/openapi-generator';

Testing

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Run tests with coverage
npm run test:coverage

Examples

See the /examples directory for complete working examples:

  • basic-generation.ts - Simple single-source generation
  • multi-source.ts - Multiple sources with priorities
  • workflow.ts - Workflow-based generation
  • batch-processing.ts - Batch and monorepo processing
  • watch-mode.ts - Development with watch mode
  • analysis.ts - Result analysis and quality metrics

License

Copyright (c) 2025 Bernier LLC. All rights reserved.

This package is licensed under a limited-use license. See LICENSE file for details.