@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-generatorQuick 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 loggedNeverHub Integration
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.
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 generationswagger2openapi- OpenAPI version conversionchokidar- 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:coverageExamples
See the /examples directory for complete working examples:
basic-generation.ts- Simple single-source generationmulti-source.ts- Multiple sources with prioritiesworkflow.ts- Workflow-based generationbatch-processing.ts- Batch and monorepo processingwatch-mode.ts- Development with watch modeanalysis.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.
