New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@computerwwwizards/version-inferer

Package Overview
Dependencies
Maintainers
1
Versions
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@computerwwwizards/version-inferer

A flexible, source-agnostic library for inferring and resolving configuration values from multiple sources with configurable precedence and conflict handling strategies

latest
Source
npmnpm
Version
0.0.1
Version published
Maintainers
1
Created
Source

Version Inferers

A flexible, source-agnostic library for inferring and resolving configuration values from multiple sources with configurable precedence and conflict handling strategies.

🎯 Purpose

This library solves the common problem of determining which version or configuration value to use when multiple sources provide conflicting information. Originally designed for Node.js version inference, it has evolved into a generic resolution system applicable to any scenario requiring multi-source orchestration.

Real-world Use Cases

  • 🔧 Node.js Version Management: Automatically detect the correct Node.js version from .nvmrc, package.json, or CI/CD workflows
  • ⚙️ Configuration Resolution: Resolve settings from environment files, config files, and defaults with clear precedence rules
  • 🚀 CI/CD Integration: Ensure your local environment matches your deployment configuration
  • 🔄 Monorepo Management: Coordinate versions across multiple packages and workspaces

✨ Key Features

  • 🔌 Pluggable Sources: Register any number of custom or built-in sources
  • 📊 Configurable Precedence: Define resolution order at runtime
  • ⚠️ Conflict Strategies: Choose how to handle conflicting values (report, error, or use first)
  • 🌊 Stream-based: Efficient file reading with proper resource cleanup
  • 📦 Type-safe: Full TypeScript support with generic types
  • 🧩 Extensible: Easy to add new source types and strategies

🚀 Quick Start

Installation

pnpm install @computerwwwizards/version-inferer

Basic Usage

import inferNodeVersion from '@computerwwwizards/version-inferer';

// Infer Node.js version from project files
const result = await inferNodeVersion();
console.log(`Use Node.js ${result.version}`);

📚 Examples

Example 1: Simple Node Version Detection

Automatically detects Node version from .nvmrc or package.json:

import inferNodeVersion from '@computerwwwizards/version-inferer';

const result = await inferNodeVersion({
  rootPath: '/path/to/project'
});

if (result.version) {
  console.log(`✅ Node version: ${result.version}`);
} else {
  console.log('❌ No version found');
}

// Result includes all checked sources
console.log('Checked sources:', result.data);
// { nvmrc: '20.0.0', 'package.json': null }

Example 2: Include CI/CD Workflow Configuration

Check GitHub Actions workflow files for Node version:

import inferNodeVersion from '@computerwwwizards/version-inferer';

const result = await inferNodeVersion({
  workflowFilePath: '.github/workflows/ci.yml',
  workflowOption: ['jobs', 'test', 'steps', '0', 'with', 'node-version'],
  rootPath: process.cwd()
});

console.log('Version from CI:', result.version);

Example 3: Custom Precedence Order

Prioritize specific sources over others:

import inferNodeVersion, { ConflictStrategy } from '@computerwwwizards/version-inferer';

const result = await inferNodeVersion({
  workflowFilePath: '.github/workflows/deploy.yml',
  workflowOption: ['jobs', 'deploy', 'with', 'node-version'],
  // Prioritize workflow, then package.json, then .nvmrc
  order: ['workflow', 'package.json', 'nvmrc'],
  conflictStrategy: ConflictStrategy.STOP_ON_FIRST
});

console.log(`Using: ${result.version}`);

Example 4: Handle Version Conflicts

Different strategies for handling conflicting versions:

import inferNodeVersion, { ConflictStrategy } from '@computerwwwizards/version-inferer';

// Strategy 1: Report conflicts but continue
const result1 = await inferNodeVersion({
  conflictStrategy: ConflictStrategy.REPORT
});

if (result1.conflicts.length > 0) {
  console.log('⚠️  Version conflicts detected:');
  result1.conflicts.forEach(conflict => {
    console.log(`  ${conflict.sources.join(' vs ')}: ${conflict.values.join(' vs ')}`);
  });
}

// Strategy 2: Throw error on conflict
try {
  const result2 = await inferNodeVersion({
    conflictStrategy: ConflictStrategy.ERROR
  });
} catch (error) {
  console.error('Version conflict error:', error.message);
}

// Strategy 3: Stop at first valid version (default)
const result3 = await inferNodeVersion({
  conflictStrategy: ConflictStrategy.STOP_ON_FIRST
});
console.log('First valid version:', result3.version);

Example 5: Advanced - Custom Version Sources

Build your own resolver with custom sources:

import VersionPrecedenceResolver from '@computerwwwizards/version-inferer';

const resolver = new VersionPrecedenceResolver();

// Add custom sources
resolver
  .registerSource('envVar', async () => process.env.NODE_VERSION || null)
  .registerSource('defaultConfig', async () => '18.0.0')
  .registerSource('userPreference', {
    getVersion: async () => {
      // Read from database, API, etc.
      return '20.0.0';
    }
  });

const result = await resolver.resolveVersion({
  order: ['userPreference', 'envVar', 'defaultConfig']
});

console.log('Resolved version:', result.version);

Example 6: CI/CD Integration Script

Create a script to ensure environment matches CI:

#!/usr/bin/env node
import inferNodeVersion from '@computerwwwizards/version-inferer';
import { execSync } from 'child_process';

async function ensureNodeVersion() {
  const result = await inferNodeVersion({
    workflowFilePath: '.github/workflows/ci.yml',
    workflowOption: ['jobs', 'test', 'strategy', 'matrix', 'node-version', '0'],
    order: ['workflow', 'nvmrc', 'package.json']
  });

  if (!result.version) {
    console.error('❌ No Node version specified');
    process.exit(1);
  }

  const currentVersion = execSync('node -v').toString().trim();
  const requiredVersion = `v${result.version}`;

  if (currentVersion !== requiredVersion) {
    console.log(`⚠️  Version mismatch: ${currentVersion} !== ${requiredVersion}`);
    console.log(`Run: nvm use ${result.version}`);
    process.exit(1);
  }

  console.log(`✅ Using correct Node version: ${currentVersion}`);
}

ensureNodeVersion();

🏗️ Architecture

Built-in Sources

  • NvmrcStreamSource: Reads .nvmrc files
  • PackageJsonStreamSource: Extracts engines.node from package.json
  • CiYamlStreamSource: Parses YAML files (GitHub Actions, GitLab CI, etc.)

Conflict Strategies

StrategyBehavior
STOP_ON_FIRSTReturns first non-null value (default)
REPORTCollects conflicts but continues resolution
ERRORThrows error if conflicts detected

Stream Factory Pattern

All sources use a factory pattern to ensure proper resource management:

import { createReadStream } from 'fs';
import { NvmrcStreamSource } from '@computerwwwizards/version-inferer';

// ✅ Good: Stream created on-demand and auto-cleaned
const source = new NvmrcStreamSource(() => createReadStream('.nvmrc'));

// ❌ Bad: Pre-created stream may leak or lock
const stream = createReadStream('.nvmrc');
const source = new NvmrcStreamSource(stream); // Old API

🔮 Future Directions

This library is evolving toward:

  • Multi-value Resolution: Support for resolving multiple related values (Node + npm versions)
  • Caching Strategies: Optional caching for expensive source reads
  • Validation Rules: Built-in version constraint validation
  • Plugin System: Marketplace for community-contributed sources
  • Language Agnostic: Extend to Python, Ruby, Java version management
  • Web API: REST interface for version resolution services

🛠️ Development

Setup

Install dependencies:

pnpm install

Build

pnpm build

Development (watch mode)

pnpm dev

Run Tests

pnpm test

Format Code

pnpm format

📖 API Reference

inferNodeVersion(options?)

Main function for Node.js version inference.

Options:

{
  workflowFilePath?: string;        // Path to CI/CD workflow file
  workflowOption?: string[];        // YAML path to version field
  rootPath?: string;                // Project root (default: process.cwd())
  order?: string[];                 // Source precedence order
  conflictStrategy?: ConflictStrategy; // How to handle conflicts
}

Returns: Promise<ResolveResult>

{
  version: string | null;           // Resolved version
  data: Record<string, string | null>; // All source values
  conflicts: Conflict[];            // Detected conflicts
}

VersionPrecedenceResolver

Generic resolver class for custom implementations.

See Precedence Resolver Documentation for detailed architecture and design decisions.

📄 License

MIT License - see the LICENSE file for details.

Copyright (c) 2025 ComputerWWWizards

🤝 Contributing

Contributions welcome! Please read our contributing guidelines before submitting PRs.

Keywords

version

FAQs

Package last updated on 27 Dec 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts