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

mlm-core

v1.0.6

Published

MLM module loader core

Readme

MLM Core

A lightweight, modular microkernel for building extensible JavaScript applications through dynamic unit loading and dependency injection.

Overview

MLM Core provides a plugin architecture that allows applications to be composed from independent, reusable units. Each unit can declare dependencies, provide services, and participate in a shared application lifecycle.

Installation

npm install mlm-core

Quick Start

import mlm from 'mlm-core';

// Create MLM instance
const app = mlm();

// Install and start units
await app.install('database');
await app.install('web-server');
await app.start();

Core Concepts

Units

Units are modular components that export a factory function and metadata:

// units/logger.js
export const info = {
  provides: ['#logging'],
  description: 'Application logging service'
};

export default mlm => ({
  'define.logger': () => ({
    info: (msg) => console.log(`[INFO] ${msg}`),
    error: (msg) => console.error(`[ERROR] ${msg}`)
  }),
  onStart: () => mlm.log('Logger started')
});

Dependencies

Units declare what they require and provide:

export const info = {
  requires: ['database', '#logging'],  // Install these first
  provides: ['#users'],               // This unit provides user functionality
  description: 'User management service'
};

Context System

The context provides dependency injection between units:

export default mlm => ({
  'define.userService': () => ({
    createUser: async (data) => {
      mlm.logger.info('Creating user');
      return mlm.database.users.create(data);
    }
  })
});

API Reference

MLM Instance

mlm(options?)

Creates a new MLM instance.

Options:

  • import: Custom module importer function
  • resolveModule: Custom module path resolver
const app = mlm({
  resolveModule: (name) => `./plugins/${name}/index.js`
});

install(unitName)

Installs a unit and its dependencies.

await app.install('web-server');

start(config?)

Starts all installed units.

await app.start({ port: 3000 });

stop()

Gracefully stops the application.

await app.stop();

repl(context?, options?)

Starts an interactive REPL with access to the application context.

await app.repl({ customVar: 'value' }, { screen: true });

Unit Configuration

Units export a factory function that returns a configuration object:

export default function(mlm) {
  return {
    // Lifecycle hooks
    onBeforeLoad: async (mlm) => { /* ... */ },
    onPrepare: async (mlm) => { /* ... */ },
    onReady: async (mlm) => { /* ... */ },
    onStart: async (config) => { /* ... */ },
    onStop: async () => { /* ... */ },
    onShutdown: async () => { /* ... */ },
    
    // Context definitions
    define: {
      serviceName: () => serviceInstance,
      configValue: { value: 'data' }
    },
    
    // Custom loaders
    register: {
      customLoader: async (config, unit) => { /* ... */ }
    }
  };
}

Unit Metadata

The info export describes the unit:

export const info = {
  requires: ['dependency1', '#feature-tag'],
  provides: ['#my-feature'],
  description: 'Unit description',
  npm: { /* npm dependencies */ },
  version: '1.0.0',
  author: 'Author Name'
};

Lifecycle

  1. Install Phase

    • onBeforeLoad: Prepare for installation
    • Dependency resolution and installation
    • Feature tag registration
    • onPrepare: Setup internal state
    • Context property definition
    • Custom loader registration
    • onReady: Finalize installation
  2. Start Phase

    • onStart: Initialize runtime services
    • System marked as started
  3. Stop Phase

    • onStop: Graceful shutdown of services
    • onShutdown: Final cleanup (reverse order)

Advanced Features

Custom Module Resolution

import { pathToFileURL } from 'node:url';

const app = mlm({
  resolveModule: (name) => {
    if (name.startsWith('@')) {
      return pathToFileURL(`./scoped/${name.slice(1)}.js`).href;
    }
    return pathToFileURL(`./units/${name}.js`).href;
  }
});

Feature Tags

Units can provide feature tags that other units can depend on:

// Provider
export const info = {
  provides: ['#database']
};

// Consumer  
export const info = {
  requires: ['#database']  // Any unit providing #database
};

Custom Loaders

Units can register custom processing steps. There are two equivalent syntaxes:

// Canonical arrow function syntax
export default mlm => ({
  'register.middleware': async (middlewareConfig, unit) => {
    mlm.app.use(middlewareConfig);
  }
});

// Traditional function syntax (useful when you need local variables)
export default function(mlm) {
  const localConfig = computeConfig();
  
  return {
    register: {
      middleware: async (middlewareConfig, unit) => {
        mlm.app.use(middlewareConfig);
      }
    }
  };
}

// Use the loader
export default mlm => ({
  middleware: {
    path: '/api',
    handler: (req, res) => res.json({ status: 'ok' })
  }
});

Dotted Key Notation

MLM Core supports dotted key notation as a convenience syntax. Dotted keys are processed before unit installation, so 'define.serviceName' is exactly equivalent to define: { serviceName: ... }. This allows for cleaner, flatter configuration objects:

// These are equivalent:
export default mlm => ({
  'define.logger': () => loggerService,
  'register.middleware': middlewareLoader
});

export default mlm => ({
  define: {
    logger: () => loggerService
  },
  register: {
    middleware: middlewareLoader
  }
});

Error Handling

MLM Core includes comprehensive error handling:

  • State validation: Operations are validated against current lifecycle state
  • Type checking: Runtime validation of unit configurations
  • Dependency cycles: Automatic detection of circular dependencies
  • Concurrent installs: Prevention of race conditions during unit loading

Development

REPL

Access the application state interactively:

await app.repl();
// mlm > mlm.logger.info('Hello from REPL')
// mlm > mlmInstance.units

Debugging

Enable detailed logging by accessing unit contexts:

// Each unit gets a context with logging
export default function(mlm) {
  mlm.log('Unit initialized');
  mlm.assert(condition, 'Assertion message');
  return { /* ... */ };
}

License

LGPL-3.0-or-later