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-merger

v1.2.2

Published

OpenAPI specification merging, deduplication, and conflict resolution utilities

Readme

@bernierllc/openapi-merger

OpenAPI specification merging and deduplication utilities that combine multiple documents into a single coherent contract while preserving lineage and resolving conflicts.

Features

  • Deterministic merge strategies including first-wins, last-wins, and deep merge
  • Intelligent component deduplication with reference updates
  • Conflict detection for paths, components, info metadata, and security requirements
  • Source tracking annotations for merged artifacts
  • Component optimization helpers for schema consolidation and integrity checks

Installation

npm install @bernierllc/openapi-merger

Usage

import { MergeStrategy, OpenAPIMerger } from '@bernierllc/openapi-merger';

const merger = new OpenAPIMerger({
  strategy: MergeStrategy.MERGE_DEEP,
  deduplicateComponents: true,
  validateOutput: true
});

const result = merger.merge([specA, specB, specC]);

console.log(result.merged.paths);
console.log(result.conflicts);
console.log(result.deduplicated);

API Reference

OpenAPIMerger Class

The main class for merging OpenAPI specifications with configurable strategies and options.

Constructor

const merger = new OpenAPIMerger(config?: MergerConfig);

Configuration Options:

  • strategy - Merge strategy (FIRST_WINS, LAST_WINS, MERGE_DEEP, FAIL_ON_CONFLICT, CUSTOM)
  • deduplicateComponents - Enable automatic component deduplication (default: true)
  • validateOutput - Validate merged output for integrity (default: true)
  • preserveOrder - Maintain source order in merged output (default: false)
  • conflictResolver - Custom resolver function for CUSTOM strategy

merge(specs: OpenAPIObject[]): MergeResult

Merges multiple OpenAPI specifications into a single coherent document.

const result = merger.merge([specA, specB, specC]);

console.log(result.merged);      // Merged OpenAPI specification
console.log(result.conflicts);   // Array of detected conflicts
console.log(result.deduplicated); // Deduplication statistics
console.log(result.warnings);    // Validation warnings

Returns:

  • merged - Combined OpenAPI specification
  • conflicts - Array of conflict descriptions
  • deduplicated - Component deduplication statistics
  • warnings - Validation warnings and notices

detectConflicts(specs: OpenAPIObject[]): ConflictReport

Analyzes specifications for conflicts without performing the merge.

const conflicts = merger.detectConflicts([specA, specB]);

conflicts.forEach(conflict => {
  console.log(`Conflict in ${conflict.type}: ${conflict.description}`);
});

Merge Strategies

FIRST_WINS

First occurrence wins for conflicts:

const merger = new OpenAPIMerger({ strategy: MergeStrategy.FIRST_WINS });
const result = merger.merge([spec1, spec2, spec3]);
// spec1 values preserved on conflict

LAST_WINS

Last occurrence wins for conflicts:

const merger = new OpenAPIMerger({ strategy: MergeStrategy.LAST_WINS });
const result = merger.merge([spec1, spec2, spec3]);
// spec3 values override earlier specs

MERGE_DEEP

Deep merge with intelligent conflict resolution:

const merger = new OpenAPIMerger({ strategy: MergeStrategy.MERGE_DEEP });
const result = merger.merge([spec1, spec2, spec3]);
// Deep merges objects, concatenates arrays

FAIL_ON_CONFLICT

Strict mode that fails on any conflict:

const merger = new OpenAPIMerger({ strategy: MergeStrategy.FAIL_ON_CONFLICT });
try {
  const result = merger.merge([spec1, spec2, spec3]);
} catch (error) {
  console.error('Merge failed due to conflicts:', error);
}

CUSTOM

Custom resolution logic:

const merger = new OpenAPIMerger({
  strategy: MergeStrategy.CUSTOM,
  conflictResolver: (path, values) => {
    // Custom logic to resolve conflicts
    return values[0]; // Example: use first value
  }
});

Component Optimization

optimizeSchemaRefs(spec: OpenAPIObject): OptimizationResult

Replaces duplicate schemas with references to canonical definitions:

import { componentOptimizer } from '@bernierllc/openapi-merger';

const result = componentOptimizer.optimizeSchemaRefs(spec);

console.log(result.duplicatesRemoved);  // Count of removed duplicates
console.log(result.referencesUpdated);  // Count of updated references
console.log(result.optimized);          // Optimized specification

validateComponentIntegrity(spec: OpenAPIObject): IntegrityReport

Validates component references and identifies issues:

const integrity = componentOptimizer.validateComponentIntegrity(spec);

console.log(integrity.missingRefs);  // References to non-existent components
console.log(integrity.unusedComponents); // Unused component definitions
console.log(integrity.valid);        // Overall validity status

Source Tracking

Track lineage of merged components:

import { SourceTracker } from '@bernierllc/openapi-merger';

const tracker = new SourceTracker();
tracker.track('/paths/users', 'source-api-v1.yaml');
tracker.track('/paths/products', 'source-api-v2.yaml');

const sourceMap = tracker.getSourceMap();
console.log(sourceMap); // Maps each path to its source file

Utility Functions

normalizeComponentNames(components: Components): Components

Sanitizes component names for consistency:

import { OpenAPIMerger } from '@bernierllc/openapi-merger';

const normalized = OpenAPIMerger.normalizeComponentNames({
  'User Schema': { type: 'object' },
  'product-model': { type: 'object' }
});

// Returns:
// {
//   'UserSchema': { type: 'object' },
//   'productModel': { type: 'object' }
// }

Examples

Basic Merge

import { OpenAPIMerger, MergeStrategy } from '@bernierllc/openapi-merger';

const merger = new OpenAPIMerger({
  strategy: MergeStrategy.MERGE_DEEP,
  deduplicateComponents: true
});

const spec1 = {
  openapi: '3.0.0',
  info: { title: 'API v1', version: '1.0.0' },
  paths: {
    '/users': { get: { /* ... */ } }
  }
};

const spec2 = {
  openapi: '3.0.0',
  info: { title: 'API v2', version: '2.0.0' },
  paths: {
    '/products': { get: { /* ... */ } }
  }
};

const result = merger.merge([spec1, spec2]);
console.log(result.merged.paths); // Contains both /users and /products

Conflict Detection

const conflicts = merger.detectConflicts([spec1, spec2, spec3]);

if (conflicts.length > 0) {
  console.log('Found conflicts:');
  conflicts.forEach(conflict => {
    console.log(`- ${conflict.type}: ${conflict.path}`);
    console.log(`  Description: ${conflict.description}`);
  });
}

Component Optimization

import { componentOptimizer } from '@bernierllc/openapi-merger';

// First merge specs
const merged = merger.merge([spec1, spec2, spec3]);

// Then optimize the result
const optimized = componentOptimizer.optimizeSchemaRefs(merged.merged);

console.log(`Removed ${optimized.duplicatesRemoved} duplicate schemas`);
console.log(`Updated ${optimized.referencesUpdated} references`);

Source Tracking

import { SourceTracker } from '@bernierllc/openapi-merger';

const tracker = new SourceTracker();

// Track during merge
const merger = new OpenAPIMerger({
  strategy: MergeStrategy.MERGE_DEEP,
  sourceTracker: tracker
});

const result = merger.merge([
  { source: 'api-v1.yaml', spec: spec1 },
  { source: 'api-v2.yaml', spec: spec2 }
]);

// Get source information
const sourceMap = tracker.getSourceMap();
console.log(sourceMap['/paths/users']); // 'api-v1.yaml'
console.log(sourceMap['/paths/products']); // 'api-v2.yaml'

Testing

npm test

Integration Status

  • Logger integration: not-applicable - This is a pure utility package with no runtime logging requirements. Does not use @bernierllc/logger as it has no logging needs. The detectLogger pattern is not applicable to this pure transformation utility.
  • Docs-Suite: ready - Exports TypeDoc-compatible API documentation
  • NeverHub integration: not-applicable - Pure transformation utility with no service discovery or event bus requirements. Does not use @bernierllc/neverhub-adapter as it has no event bus needs. The detectNeverHub pattern is not applicable to this stateless utility.

License

UNLICENSED – Internal Bernier LLC package.