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

@pandino/pandino

v0.10.0

Published

A TypeScript implementation of the OSGi specification.

Readme

@pandino/pandino

npm version TypeScript License

The core Pandino runtime: an OSGi-style service registry, bundle system, and built-in services for building modular TypeScript applications. Services discover each other dynamically at runtime instead of being statically wired at compile time.

Where it fits in the Pandino ecosystem

 @pandino/decorators            @pandino/rollup-bundle-plugin
 (declare components) ──┐         (auto-package bundles)
                        ▼                     │
              ┌──────────────────────────┐    │
              │   @pandino/pandino       │ ◀──┘
              │   • Service Registry     │
              │   • Bundle Lifecycle     │
              │   • EventAdmin           │     @pandino/react-hooks
              │   • ConfigurationAdmin   │ ──▶ (consume services in React)
              │   • LogService           │
              │   • SCR (runtime)        │
              └──────────────────────────┘

This package is the heart of any Pandino application. Every other package either produces artifacts it consumes (decorators, rollup plugin) or provides an adapter layer to interact with it (react-hooks).

Installation

npm install @pandino/pandino reflect-metadata

If you plan to use decorators, also install @pandino/decorators:

npm install @pandino/decorators

Import reflect-metadata once at your application's entry point:

import 'reflect-metadata';

TypeScript configuration

Enable decorators and metadata emission in tsconfig.json:

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

Core concepts

Services and service references

A service is any object registered in Pandino's central registry under one or more interface names. Consumers don't import service implementations directly — they look them up by interface, optionally filtering by properties.

| Concept | What it is | Analogy | | ----------------------- | ------------------------------------------- | --------------------------- | | Service | The object that does the work | A person you want to call | | Service Reference | A handle used to look up and release access | The phone-book entry | | Service Registration| Handle returned when you publish a service | Your listing in the book |

Bundles

A bundle is a self-contained module with its own lifecycle (install, start, stop, uninstall). Each bundle can publish services, consume services, and register event listeners through a BundleContext. Bundles are the unit of modularity in Pandino.

Dynamic dependencies

Services can appear and disappear at runtime. Dependents are wired automatically as soon as their requirements become available — bundle start-up order does not matter.

Declarative services (SCR)

The Service Component Runtime activates classes annotated with @Component (from @pandino/decorators) and resolves their @Reference dependencies automatically. This eliminates the boilerplate of manual registerService() calls.

Quick start

1. Bootstrap the framework

import 'reflect-metadata';
import { OSGiBootstrap, LogLevel } from '@pandino/pandino';

const bootstrap = new OSGiBootstrap({
  frameworkLogLevel: LogLevel.INFO,
});

const framework = await bootstrap.start();
const context = framework.getBundleContext();

2. Register and consume a service imperatively

interface GreetingService {
  sayHello(name: string): string;
}

class SimpleGreetingService implements GreetingService {
  sayHello(name: string): string {
    return `Hello, ${name}!`;
  }
}

// Publish
const registration = context.registerService('GreetingService', new SimpleGreetingService());

// Look up
const ref = context.getServiceReference<GreetingService>('GreetingService')!;
const service = context.getService(ref)!;
console.log(service.sayHello('World'));

// Clean up
context.ungetService(ref);
registration.unregister();

3. Or declare a component with decorators

import { Component, Service, Reference, Activate } from '@pandino/decorators';
import type { LogService } from '@pandino/pandino';

@Component({ name: 'greeting.service', immediate: true })
@Service({ interfaces: ['GreetingService'] })
export class GreetingServiceImpl implements GreetingService {
  @Reference({ interface: 'LogService' })
  private logger!: LogService;

  @Activate
  activate(): void {
    this.logger.info('GreetingService ready');
  }

  sayHello(name: string): string {
    return `Hello, ${name}!`;
  }
}

Decorated classes are activated by the SCR when they are included in a bundle. See the @pandino/decorators and @pandino/rollup-bundle-plugin documentation for how to ship them as bundles.

Service properties and LDAP filters

Services carry metadata. Consumers can select specific implementations using LDAP filter expressions:

context.registerService('DatabaseService', new MySQLService(), {
  'db.type': 'mysql',
  'db.host': 'localhost',
  'service.ranking': 100,
});

const refs = context.getServiceReferences<DatabaseService>('DatabaseService', '(db.type=mysql)');

Common filter forms:

| Filter | Matches | | --------------------------------------- | ---------------------------------- | | (db.type=mysql) | MySQL database services | | (service.ranking>=100) | High-priority services | | (&(db.host=localhost)(db.port>=3000)) | Local services on ports ≥ 3000 | | (\|(category=urgent)(priority=1)) | Urgent OR priority-1 services |

When multiple services are registered under the same interface, the one with the highest service.ranking wins by default.

Built-in services

These services are registered by the framework itself and are available through the bundle context as soon as it is started.

LogService

Centralised logging with bundle-aware context.

const logRef = context.getServiceReference<LogService>('LogService')!;
const logger = context.getService(logRef)!;

logger.info('Server starting', undefined, { port: 8080 });

EventAdmin

Topic-based publish–subscribe messaging.

import { EventAdmin, Event } from '@pandino/pandino';

const eventAdmin = context.getService(context.getServiceReference<EventAdmin>('EventAdmin')!)!;

// Publish
eventAdmin.sendEvent(new Event('user/login', { userId: '123' }));

// Subscribe
context.registerService('EventHandler', {
  handleEvent: (event) => console.log(event.getTopic(), event.getProperty('userId')),
}, {
  'event.topics': 'user/*',
});

ConfigurationAdmin

Runtime configuration updates delivered to ManagedService instances.

import type { ConfigurationAdmin, ManagedService } from '@pandino/pandino';

const configAdmin = context.getService(context.getServiceReference<ConfigurationAdmin>('ConfigurationAdmin')!)!;

const config = await configAdmin.getConfiguration('database.connection');
await config.update({ host: 'localhost', port: 5432 });

// Services can receive updates by implementing ManagedService
class DatabaseService implements ManagedService {
  updated(props: Record<string, any> | null): void {
    if (props) this.reconnect(props);
  }
}
context.registerService('DatabaseService', new DatabaseService(), {
  'service.pid': 'database.connection',
});

ServiceTracker

A helper that tracks the availability of services matching an interface or filter.

import { ServiceTracker } from '@pandino/pandino';

const tracker = new ServiceTracker<DatabaseService>(context, 'DatabaseService', {
  addingService: (ref) => context.getService(ref),
  removedService: (ref) => context.ungetService(ref),
});

tracker.open();
const current = tracker.getService();

ServiceComponentRuntime (SCR)

Activates and manages declaratively defined components. You usually don't interact with it directly — bundles register their components via SCR automatically. For manual control:

import type { BundleActivator, BundleContext, ServiceComponentRuntime } from '@pandino/pandino';

const activator: BundleActivator = {
  async start(context: BundleContext) {
    const scr = context.getService(context.getServiceReference<ServiceComponentRuntime>('ServiceComponentRuntime')!)!;
    const bundleId = context.getBundle().getBundleId();
    await scr.registerComponent(GreetingServiceImpl, bundleId);
  },
};

Writing a bundle

A bundle is a plain module whose default export describes itself:

import type { BundleActivator, BundleContext } from '@pandino/pandino';

class DatabaseService {
  query(sql: string) { /* ... */ }
}

const activator: BundleActivator = {
  async start(context: BundleContext) {
    context.registerService('DatabaseService', new DatabaseService());
  },
  async stop() {
    // optional manual cleanup; services registered via the context are released automatically
  },
};

export default {
  headers: {
    bundleSymbolicName: 'com.example.database',
    bundleVersion: '1.0.0',
    bundleName: 'Database Bundle',
  },
  activator,
  components: [
    // classes decorated with @Component — optional
  ],
};

Bundles can be loaded at startup by passing them to the bootstrap, installed via context.installBundle(), or produced automatically by the @pandino/rollup-bundle-plugin.

Fragment bundles

A fragment is a bundle that attaches to a host and contributes components or resources without its own lifecycle. Typical uses: localisation packs, platform-specific overrides, theming.

export default {
  headers: {
    bundleSymbolicName: 'com.example.database.german',
    bundleVersion: '1.0.0',
    fragmentHost: 'com.example.database',
  },
  activator: { start: async () => {}, stop: async () => {} },
  components: [{ name: 'GermanTranslations', translations: {/* ... */} }],
};

More details in the Fragment Pattern documentation.

Recommended patterns

Common architectural patterns used with Pandino bundles:

Public API cheatsheet

| Export | Purpose | | ------------------------------ | ------------------------------------------------------ | | OSGiBootstrap | Start and stop the framework | | OSGiFramework | The running framework instance | | BundleContext | Register / look up services, install bundles | | Bundle, BundleActivator | Bundle lifecycle model | | ServiceReference<T> | Handle used to look up and release a service | | ServiceRegistration<T> | Handle to unregister or update a registered service | | ServiceTracker<T> | Tracks service availability with customiser callbacks | | EventAdmin, Event, EventHandler | Publish/subscribe messaging | | ConfigurationAdmin, ManagedService, ManagedServiceFactory | Runtime configuration | | LogService, LogLevel | Framework-provided logger | | ServiceComponentRuntime, ComponentContext | Declarative-service runtime | | BUNDLE_STATES, SERVICE_EVENT_TYPES | Lifecycle / event enumerations | | getDecoratorInfo(ClassRef) | Inspect decorator metadata on a component class |

Related packages

License

Eclipse Public License - v 2.0