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

johanlabs-librarian

v0.2.2

Published

Isolated npm package management for multi-tenant systems

Readme

Librarian 📚

npm version License: ISC

Librarian is a production-ready, multi-tenant workspace manager for Node.js. It provides isolated npm environments for different users (tenants) with enterprise-grade security, atomic operations, and V8 Isolates for safe code execution.

🚀 Key Features

  • 🔒 Enterprise Security: Path traversal protection, input sanitization, and secure command execution
  • ⚡ True Isolation: V8 Isolates with configurable memory limits and CPU time restrictions
  • 🔐 Atomic Operations: Battle-tested file locking with proper-lockfile prevents race conditions
  • 📦 Smart Cleanup: Dependency tree analysis ensures only orphaned packages are removed
  • 🔄 Transaction Safety: Automatic backup/rollback on failures maintains data consistency
  • 📊 Structured Logging: Four log levels (DEBUG, INFO, WARN, ERROR) for observability
  • ⚙️ Fully Configurable: Timeouts, memory limits, and paths can be customized
  • 🎯 Multi-Registry: Support for NPM, Verdaccio, and custom private registries
  • ♻️ Resource Management: Automatic cleanup with dispose() prevents memory leaks
  • 🧩 Context Pooling: Reusable V8 contexts for optimal performance

📦 Installation

npm install johanlabs-librarian

🎯 Quick Start

import { Librarian, LogLevel } from 'johanlabs-librarian';

// Configure logging (optional)
Librarian.setLogLevel(LogLevel.INFO);

// Initialize with custom options
const lib = new Librarian({
  path: './workspaces',
  configName: 'packages.json',  // Custom manifest filename
  lockTimeout: 180000,           // 3 minutes
  installTimeout: 600000,        // 10 minutes
  memoryLimit: 256               // 256MB for isolates
});

// Create a tenant workspace
const tenant = lib.tenant('user-123');

// Add packages
await tenant.addPackage({ name: 'lodash', version: '4.17.21' });
await tenant.addPackage({ name: 'axios', version: '^1.6.0' });

// Configure private registry
tenant.addRegistry({
  type: 'custom',
  url: 'https://registry.company.com',
  auth: { token: 'npm_xxxxx' },
  scopes: ['@company']
});

🔐 Secure Script Execution

Run untrusted code safely in isolated V8 contexts:

// Scripts cannot access host process, require, or file system
const result = await tenant.runScript(`
  const packagesJSON = packages; // Injected as JSON string
  const data = JSON.parse(packagesJSON);
  
  // Your isolated code here
  return JSON.stringify({ status: 'ok', data });
`, {
  timeout: 5000,        // 5 seconds max
  cpuTimeLimit: 100     // 100ms CPU time
});

console.log(result);

📚 Advanced Usage

Direct Package Access (Trusted Environment)

// Access installed packages directly in your main process
const { lodash, axios } = tenant.packages;

const chunked = lodash.chunk(['a', 'b', 'c', 'd'], 2);
const response = await axios.get('https://api.example.com');

Package Management

// List installed packages
const packages = tenant.listPackages();
console.log(packages); // [{ name: 'lodash', version: '4.17.21' }, ...]

// Remove package (auto-cleanup)
await tenant.removePackage('lodash');

// Custom installation directory
await tenant.addPackage(
  { name: 'module-alias', version: '2.2.3' },
  'custom_modules'
);

Registry Management

// NPM Registry
tenant.addRegistry({
  type: 'npm',
  url: 'https://registry.npmjs.org'
});

// Private Registry with Token
tenant.addRegistry({
  type: 'custom',
  url: 'https://npm.company.com',
  auth: { token: 'npm_xxxxxxxxxxxx' },
  scopes: ['@company', '@internal']
});

// Private Registry with Basic Auth
tenant.addRegistry({
  type: 'verdaccio',
  url: 'http://localhost:4873',
  auth: {
    username: 'admin',
    password: 'secret',
    email: '[email protected]'
  }
});

// List all registries
const registries = tenant.listRegistry();

// Remove registry
tenant.removeRegistry('https://npm.company.com');

Resource Management

// Dispose single tenant (releases locks, isolates, cache)
await lib.disposeTenant('user-123');

// Or dispose from tenant instance
await tenant.dispose();

// Dispose all tenants (graceful shutdown)
await lib.disposeAll();

Logging Configuration

import { LogLevel } from 'johanlabs-librarian';

// Set log level globally
Librarian.setLogLevel(LogLevel.DEBUG);  // Most verbose
Librarian.setLogLevel(LogLevel.INFO);   // Default
Librarian.setLogLevel(LogLevel.WARN);   // Warnings only
Librarian.setLogLevel(LogLevel.ERROR);  // Errors only

🏗️ Architecture

📦 Librarian
├── 🏢 Librarian.ts          - Main factory, tenant orchestration
├── 👤 Tenant.ts             - Tenant workspace manager
├── 📦 package/
│   ├── PackageStore.ts      - Manifest + npm install (async, transactional)
│   └── PackageCleaner.ts    - Dependency tree cleanup
├── 🔐 lock/
│   └── TenantLock.ts        - Atomic file locking (proper-lockfile)
├── 🌐 registry/
│   ├── RegistryManager.ts   - Registry validation & management
│   └── NpmRcWriter.ts       - .npmrc generation
├── 🎭 isolate/
│   └── IsolateManager.ts    - V8 isolates + context pooling
└── 🛠️ utils/
    ├── Logger.ts            - Structured logging
    └── PathValidator.ts     - Security validations

🔒 Security Features

Path Traversal Protection

// ❌ Throws error
lib.tenant('../../etc/passwd');

// ✅ Safe
lib.tenant('user-123');

Command Injection Prevention

// spawn() uses shell: false and validates inputs
// No way to inject shell commands

Input Validation

// Invalid URLs rejected
tenant.addRegistry({ url: 'javascript:alert(1)' }); // ❌ Error

// Invalid scopes rejected
tenant.addRegistry({ scopes: ['no-at-sign'] }); // ❌ Error

⚡ Performance Features

  • Async I/O: All file operations use fs/promises
  • Context Pooling: Reuses up to 5 V8 contexts
  • Smart Caching: Package cache with invalidation
  • Dependency Tree: Only scans when needed
  • Atomic Locks: Minimal lock duration

🧪 Quick Test

import { Librarian, LogLevel } from 'johanlabs-librarian';

Librarian.setLogLevel(LogLevel.DEBUG);

const lib = new Librarian({ path: './test-workspaces' });
const tenant = lib.tenant('test-user');

try {
  // Test package installation
  console.log('Installing lodash...');
  await tenant.addPackage({ name: 'lodash', version: '4.17.21' });
  
  // Test direct access
  const { lodash } = tenant.packages;
  console.log('Lodash chunk:', lodash.chunk([1, 2, 3, 4], 2));
  
  // Test isolated execution
  const result = await tenant.runScript(`
    const pkgs = JSON.parse(packages);
    'Packages: ' + Object.keys(pkgs).join(', ');
  `);
  console.log('Script result:', result);
  
  // Cleanup
  await tenant.dispose();
  console.log('✅ All tests passed!');
} catch (err) {
  console.error('❌ Test failed:', err);
}

📊 Production Checklist

  • ✅ Configure appropriate timeouts
  • ✅ Set production log level (INFO or WARN)
  • ✅ Implement graceful shutdown with disposeAll()
  • ✅ Monitor lock timeouts in logs
  • ✅ Set memory limits based on workload
  • ✅ Use error handling around all async operations
  • ✅ Validate tenant IDs from user input
  • ✅ Consider rate limiting per tenant

🤝 API Reference

Librarian Class

class Librarian {
  constructor(options?: LibrarianOptions)
  static setLogLevel(level: LogLevel): void
  tenant(id: string): Tenant
  async disposeTenant(id: string): Promise<void>
  async disposeAll(): Promise<void>
}

Tenant Class

class Tenant {
  async addPackage(pkg: ManagedPackage, targetDir?: string): Promise<Tenant>
  async removePackage(name: string): Promise<Tenant>
  async runScript(code: string, options?: ScriptOptions): Promise<any>
  addRegistry(registry: RegistryConfig): Tenant
  removeRegistry(url: string): Tenant
  listRegistry(): RegistryConfig[]
  listPackages(): ManagedPackage[]
  get packages(): Record<string, any>
  async dispose(): Promise<void>
}

Types

interface LibrarianOptions {
  path?: string;           // Default: process.cwd()
  configName?: string;     // Default: 'list.json'
  lockTimeout?: number;    // Default: 120000 (2 min)
  installTimeout?: number; // Default: 300000 (5 min)
  memoryLimit?: number;    // Default: 128 (MB)
}

interface ManagedPackage {
  name: string;
  version: string;
  targetDir?: string;
}

interface RegistryConfig {
  type: 'npm' | 'verdaccio' | 'custom';
  url: string;
  auth?: RegistryAuth;
  scopes?: string[];
}

interface RegistryAuth {
  token?: string;
  username?: string;
  password?: string;
  email?: string;
}

enum LogLevel {
  DEBUG = 0,
  INFO = 1,
  WARN = 2,
  ERROR = 3
}

📄 License

ISC License - see LICENSE file for details.

🙋 Support

For issues, questions, or contributions, please visit the GitHub repository.

🔄 Changelog

v0.2.0 (Production-Ready)

  • ✅ Security: Path traversal protection, input validation
  • ✅ Stability: proper-lockfile integration, transaction rollback
  • ✅ Performance: Async I/O, context pooling, smart caching
  • ✅ Observability: Structured logging with 4 levels
  • ✅ Reliability: Dependency tree cleanup, timeout controls
  • ✅ API: Resource management with dispose()

v0.1.0 (Initial Release)

  • Basic multi-tenant package management
  • V8 Isolates integration
  • Registry support