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

spinx

v0.1.3

Published

Minimal, fast monorepo manager with advanced dependency resolution

Readme

🚀 spinx 🚀

A minimal, fast monorepo manager for Node.js/TypeScript projects with advanced dependency resolution.

Main Features

  • Central node_modules - Single installation point via pnpm
  • Cross-version resolution - Different workspaces can use different package versions
  • Alias imports - Use @orders/utils/helper style imports
  • Parallel execution - Run tasks concurrently with dependency awareness
  • Dependency graph - Automatic topological ordering and cycle detection
  • Simple configuration - One spinx.config.js file
  • Clean CLI - Easy-to-use commands

Installation

npm install -g spinx
# or
pnpm add -g spinx

🚀 Quick Start

1. Create spinx.config.js

/** @type {import('spinx/types').spinxConfig} */
module.exports = {
  manager: "pnpm",
  concurrency: 4,
  workspace: [
    {
      path: "./packages/utils",
      alias: "@utils",
      command: {
        build: "npm run build",
        customcommand: "echo 'k xa bro ?'",
      },
    },
    {
      path: "./services/orders",
      alias: "@orders",
      dependsOn: ["@utils"],
      command: {
        build: "npm run build",
        start: "npm run dev",
        live: "npm run start:prod",
        customcommand: "echo 'Hi from Nirikshan'",
      },
    },
    {
      path: "./services/cart",
      alias: "@cart",
      dependsOn: ["@orders", "@utils"],
      command: {
        build: "npm run build",
        start: "npm run dev",
        live: "npm run start:prod",
        customcommand: "echo 'Hey This is Nirikshan Bhusal'",
      },
    },
  ],
  defaults: {
    build: "npm run build",
    start: "npm run dev",
  },
};

2. Create pnpm-workspace.yaml

packages:
  - "packages/*"
  - "services/*"

3. Install dependencies

pnpm install

4. Build everything

spinx build

📚 Commands

Build

Build all workspaces in dependency order:

spinx build

Build only changed workspaces since a git ref:

spinx build --since=origin/main

Build specific workspaces:

spinx build --filter=@orders,@cart

Start

Start a workspace in development mode:

spinx start @orders

Start with dependencies:

spinx start @orders --with-deps

Live

Run all workspaces in production mode:

spinx live

Add Dependencies

Add workspace-to-workspace dependency:

spinx add @cart @orders

Add npm package:

spinx add @orders [email protected] --exact
spinx add @cart lodash --dev

Remove Dependencies

spinx remove @cart @orders
spinx rm @orders express

View Conflicts

See package version conflicts:

spinx conflicts

Explain Resolution

See how a package is resolved:

spinx explain @orders express

View Graph

Display dependency graph:

spinx graph

🔧 Advanced: Cross-Version Resolution

spinx's killer feature is cross-version resolution. Different workspaces can depend on different versions of the same package:

// @orders uses express 5.x
{
  "dependencies": {
    "express": "^5.0.0"
  }
}

// @cart uses express 4.x
{
  "dependencies": {
    "express": "^4.18.0"
  }
}

Both will work correctly at runtime! spinx:

  1. Analyzes all workspace dependencies
  2. Generates a resolution map (.spinx/resolutions.json)
  3. Creates a custom Node.js resolver hook (.spinx/resolver.js)
  4. Automatically loads the hook when running your code

The resolver intercepts require() and import calls to load the correct version for each workspace.

How it works

Workspace Request Flow:
┌─────────────┐
│   @orders   │ import express  →  express 5.0.0
└─────────────┘

┌─────────────┐
│    @cart    │ import express  →  express 4.18.3
└─────────────┘

Both packages installed in node_modules, correct version loaded per workspace!

View conflicts

$ spinx conflicts

⚠️  Found 1 package(s) with version conflicts:

📦 express
   5.0.0:
      - @orders
   4.18.3:
      - @cart

💡 These conflicts will be automatically resolved at runtime.

Configuration

spinxConfig

interface spinxConfig {
  manager: "pnpm";
  concurrency?: number; // Max parallel tasks (default: # of workspaces)
  workspace: Workspace[];
  defaults?: Partial<Commands>; // Fallback commands
  watch?: {
    include?: string[];
    ignore?: string[];
  };
}

interface Workspace {
  path: string; // Path to workspace
  alias?: string; // Import alias (e.g., "@orders")
  dependsOn?: string[]; // Workspace dependencies
  command?: Commands; // Override commands
}

interface Commands {
  build?: string;
  start?: string;
  live?: string;
}

🎯 Use Cases

Microservices Monorepo

Perfect for:

  • Multiple services with shared packages
  • Services that need different versions of dependencies
  • Gradual migrations (e.g., Express 4 → 5)

Library Monorepo

Great for:

  • Multiple packages that depend on each other
  • Testing packages together
  • Version management across packages

Example Project Structure

my-monorepo/
├── spinx.config.js
├── pnpm-workspace.yaml
├── package.json
├── packages/
│   ├── utils/
│   │   ├── package.json
│   │   └── src/
│   └── shared/
│       ├── package.json
│       └── src/
└── services/
    ├── orders/
    │   ├── package.json
    │   └── src/
    └── cart/
        ├── package.json
        └── src/

Core Features

  1. Central node_modules with Version Management

    • Single node_modules via pnpm
    • Advanced package resolution for conflicting versions
    • Automatic resolution map generation
    • Runtime resolver hook that intercepts require() and import
    • Each workspace gets the correct package version automatically
  2. Alias Support

    • Use @orders/utils/helper.ts style imports
    • Clean, readable import statements
    • Automatic path mapping
  3. Parallel Execution

    • Dependency-aware parallel builds
    • Configurable concurrency
    • Batched execution respecting dependency graph
    • Smart topological ordering
  4. Conflict Resolution

    • Automatic detection of version conflicts
    • Visual conflict display via spinx conflicts
    • Detailed resolution explanation with spinx explain
    • Works seamlessly at runtime

Project Structure

spinx/
├── src/
│   ├── cli.ts           # Main CLI entry point
│   ├── config.ts        # Configuration loader & validator
│   ├── graph.ts         # Dependency graph (DAG, cycles, topo sort)
│   ├── resolution.ts    # Version conflict resolution system ⭐
│   ├── tasks.ts         # Parallel task execution
│   ├── add.ts           # Dependency management
│   └── utils.ts         # Helper functions
├── types.d.ts           # TypeScript definitions
├── package.json
├── tsconfig.json
└── README.md            # Main documentation

Generated at runtime:
.spinx/
├── resolutions.json     # Package version mappings
└── resolver.js          # Runtime resolver hook

You can also design your own structure

How the Version Resolution Works 🎯

This is the killer feature. Here's how it works:

1. Analysis Phase

// spinx analyzes all workspace package.json files
@orders → [email protected]
@cart   → [email protected]

2. Resolution Map Generation

// .spinx/resolutions.json
{
  "@orders": {
    "express": {
      "version": "5.0.0",
      "resolvedPath": "/node_modules/.pnpm/[email protected]/..."
    }
  },
  "@cart": {
    "express": {
      "version": "4.18.3",
      "resolvedPath": "/node_modules/.pnpm/[email protected]/..."
    }
  }
}

3. Runtime Resolution

// .spinx/resolver.js intercepts require()
Module._resolveFilename = function (request, parent) {
  // Determine which workspace is calling
  const workspace = findWorkspace(parent.filename);

  // Look up correct version for that workspace
  const resolution = resolutions[workspace][request];

  // Return correct path
  return resolution.resolvedPath;
};

4. Result

// In @orders/src/index.ts
import express from "express"; // Gets express 5.0.0 ✅

// In @cart/src/index.ts
import express from "express"; // Gets express 4.18.3 ✅

Getting Started

Option 1: Quick Setup (Recommended)

cd spinx
npm install
npm run build

# Create a test project
cd ..
mkdir test-monorepo && cd test-monorepo
../spinx/scripts/quickstart.sh

# Start using it!
pnpm install
npx spinx build
npx spinx start @orders

Option 2: Install Globally

cd spinx
npm install
npm run build
npm link

# Now use anywhere
cd /path/to/your/project
spinx init
spinx build

Key Commands

# View version
spinx -v

# Build everything
spinx build

# Build only changed
spinx build --since=origin/main

# Start a service
spinx start @orders
spinx start @orders --with-deps

# Production mode
spinx live

# Manage dependencies
spinx add @cart @orders              # Link workspaces
spinx add @orders [email protected] -E   # Add npm package

# Check conflicts
spinx conflicts
spinx explain @orders express

# View graph
spinx graph

# Run your custom command
spinx run <command key from spinup.config.js > workspace > command object >

Example Scenario: Version Conflict

The Problem

Your monorepo:
├── @new-api (wants Express 5.x - new async/await API)
└── @legacy-api (stuck on Express 4.x - old callbacks)

Traditional approach: Either migrate everything at once (risky!)
or split into separate repos (overhead!)

The spinx Solution

# 1. Set up both services with different Express versions
cd services/new-api
pnpm add [email protected]

cd ../legacy-api
pnpm add [email protected]

# 2. Check conflicts
spinx conflicts
# ⚠️  express: 5.0.0 (@new-api), 4.18.3 (@legacy-api)

# 3. Build and run - it just works!
spinx build
spinx start @new-api    # Uses Express 5 ✅
spinx start @legacy-api # Uses Express 4 ✅

# 4. Gradually migrate at your own pace
# No rush, no breaking changes, both services work perfectly

Architecture Highlights

1. Dependency Graph (graph.ts)

  • Uses Kahn's algorithm for topological sort
  • Detects cycles with full path display
  • Calculates affected workspaces
  • Generates parallel execution batches

2. Resolution System (resolution.ts)

  • Scans all workspace dependencies
  • Detects version conflicts automatically
  • Generates resolution map
  • Creates runtime resolver hook
  • Fast path for non-conflicting packages

3. Task Runner (tasks.ts)

  • Parallel execution with p-limit
  • Respects dependency order
  • Configurable concurrency
  • Streams output with colored prefixes
  • Fail-fast or continue on error

4. Smart Config (config.ts)

  • Zod schema validation
  • Helpful error messages
  • Workspace validation
  • Default command fallbacks

Testing

cd spinx
npm install
npm test

# Run specific test
npm test graph.test.ts

Comparison

| Feature | spinx | Nx | Turborepo | Lerna | | ------------------------ | -------------- | ---------- | --------- | --------- | | Cross-version resolution | ✅ Unique! | ❌ | ❌ | ❌ | | Config simplicity | ✅ Simple | ❌ Complex | ✅ Simple | ⚠️ Medium | | Learning curve | ✅ Low | ❌ High | ✅ Low | ⚠️ Medium | | Parallel builds | ✅ | ✅ | ✅ | ✅ | | Dependency graph | ✅ | ✅ | ✅ | ✅ | | TypeScript support | ✅ | ✅ | ✅ | ✅ |

Contributing

Looking for future enhancements for following features :

  • [ ] Watch mode with hot reload
  • [ ] TUI dashboard (spinx view)
  • [ ] Cache system for faster builds
  • [ ] Remote cache support ( Contact Me )
  • [ ] Better TypeScript project references

My core focus for this project was: ✅ Central dependency management
✅ Version conflict resolution
✅ Parallel execution
✅ Clean aliases

Contributing

Contributions welcome! Please read our contributing guidelines.

License

MIT

Repository

GitHub: https://github.com/nirikshan/spinx

Credits

Built with: