Framework-agnostic OpenAPI generation orchestration service for multi-source documentation
npm install @bernierllc/openapi-generatorFramework-agnostic OpenAPI generation orchestration service for multi-source documentation.
@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.
- 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)
``bash`
npm install @bernierllc/openapi-generator
`typescript
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);
}
`
`typescript
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();
`
`typescript`
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
}
});
`typescript
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);
}
`
`typescript
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();
`
`typescript
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');
`
`typescript
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');
`
`typescript
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);
`
`typescript
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');
}
`
`typescript
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);
`
`typescript
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
`
When NeverHub is available, the generator automatically publishes lifecycle events:
- openapi.generation.started - Generation beginsopenapi.generation.progress
- - Step progress updatesopenapi.source.processed
- - Each source processedopenapi.validation.completed
- - Validation completeopenapi.optimization.completed
- - Optimization completeopenapi.generation.completed
- - Generation successfulopenapi.generation.failed
- - Generation failed
NeverHub integration is automatic and gracefully degrades when unavailable.
Main class for generating OpenAPI specifications.
#### Constructor
`typescript`
constructor(config: OpenAPIGeneratorConfig)
#### Methods
##### initialize(logger?: Logger): Promise
Initialize the generator with optional logger and NeverHub integration.
##### generate(): Promise
Generate OpenAPI specification from all configured sources.
##### processJSDocSource(config: SourceConfig): Promise
Process a JSDoc/TSDoc source.
##### processZodSource(config: SourceConfig): Promise
Process a Zod schema source.
##### processTSOASource(config: SourceConfig): Promise
Process a TSOA decorator source.
##### processCustomSource(config: SourceConfig): Promise
Process a custom source.
##### generateJSON(spec: OpenAPIObject): string
Generate JSON representation of specification.
##### generateYAML(spec: OpenAPIObject): Promise
Generate YAML representation of specification.
##### generateTypes(spec: OpenAPIObject, options?: TypeGenerationOptions): Promise
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
Generate based on incremental file changes.
Manages complex generation workflows.
#### Constructor
`typescript`
constructor(logger?: Logger)
#### Methods
##### registerWorkflow(workflow: GenerationWorkflow): void
Register a generation workflow.
##### executeWorkflow(workflowId: string): Promise
Execute a registered workflow.
##### scheduleWorkflow(workflowId: string, schedule: string): void
Schedule a workflow to run periodically.
##### processBatch(configs: OpenAPIGeneratorConfig[]): Promise
Process multiple configurations in batch.
##### generateForMonorepo(rootPath: string, options: MonorepoOptions): Promise
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.
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.
`typescript`
import { generationAnalyzer } from '@bernierllc/openapi-generator';
`typescript`
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
}
`typescript`
interface SourceConfig {
type: 'jsdoc' | 'zod' | 'tsoa' | 'custom';
paths: string[]; // Paths to scan
options?: Record
priority?: number; // Merge priority (higher wins)
enabled?: boolean; // Enable/disable source
}
`typescript`
interface OutputConfig {
json?: string; // JSON output path
yaml?: string; // YAML output path
types?: string; // TypeScript types output path
pretty?: boolean; // Pretty print output
}
`typescript`
interface MergeConfig {
strategy: 'merge-deep' | 'override' | 'fail-on-conflict';
deduplicateComponents?: boolean;
mergeTags?: boolean;
onConflict?: (path: string, values: unknown[]) => unknown;
}
- 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)
- OpenAPI schema construction
- @bernierllc/openapi-merger - Specification merging
- @bernierllc/jsdoc-openapi-parser - JSDoc/TSDoc parsing
- @bernierllc/zod-openapi-converter - Zod schema conversion$3
- @bernierllc/file-handler - File system operations
- @bernierllc/logger - Logging functionality
- @bernierllc/neverhub-adapter - Event publishing$3
- yaml - YAML generation
- swagger2openapi - OpenAPI version conversion
- chokidar - File watchingTypeScript
This package is written in TypeScript and includes complete type definitions.
`typescript
import type {
OpenAPIGeneratorConfig,
GenerationResult,
WorkflowContext,
AnalysisReport
} from '@bernierllc/openapi-generator';
`Testing
`bash
Run tests
npm testRun tests in watch mode
npm run test:watchRun 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 metricsCopyright (c) 2025 Bernier LLC. All rights reserved.
This package is licensed under a limited-use license. See LICENSE file for details.