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

@abdokouta/react-application

v0.0.1

Published

Application kernel for orchestrating @abdokouta packages with boot lifecycle, dependency ordering, and cross-package communication

Readme

@abdokouta/application

Application kernel for orchestrating @abdokouta packages with boot lifecycle, dependency ordering, and cross-package communication.

Features

  • 🚀 Fluent Builder API - Chain package registration with .use()
  • 📦 Automatic Dependency Resolution - Topological sort ensures correct boot order
  • 🔄 Lifecycle Hooks - onBoot(), onReady(), onShutdown() for each package
  • 📡 Event System - Monitor boot progress with typed events
  • ⚛️ React Integration - Provider and hooks for component access
  • 💉 DI Container - Seamless integration with @abdokouta/react-di

Installation

pnpm add @abdokouta/application

Quick Start

1. Create and Boot the Application

// main.tsx
import "reflect-metadata";
import { Application, ApplicationProvider } from "@abdokouta/application";
import { AuthPackage } from "@abdokouta/auth";
import { RefinePackage } from "@abdokouta/refine";

// Create and boot BEFORE React renders
const app = Application.create({
  name: "MNGO Platform",
  logLevel: import.meta.env.DEV ? "debug" : "info",
})
  .use(AuthPackage.forRoot({ session: { lockAfterSeconds: 900 } }))
  .use(RefinePackage.forRoot({ dataProvider: myDataProvider }))
  .boot();

// Wrap React with the provider
ReactDOM.createRoot(root).render(
  <ApplicationProvider app={app}>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </ApplicationProvider>
);

2. Access in Components

import { useApplication, usePackage, useBootPhase } from "@abdokouta/application";
import { useInject } from "@abdokouta/react-di";

function MyComponent() {
  // Access the Application
  const { app } = useApplication();

  // Check boot phase
  const phase = useBootPhase();

  // Get package info
  const { isBooted, version } = usePackage("@abdokouta/auth");

  // Inject services (from @abdokouta/react-di)
  const sessionService = useInject(SessionService);

  return (
    <div>
      <p>Phase: {phase}</p>
      <p>
        Auth v{version}: {isBooted ? "Ready" : "Loading"}
      </p>
    </div>
  );
}

Creating a Package

Packages can participate in the Application lifecycle by implementing the IBootable interface:

// packages/my-package/src/my-package.package.ts
import {
  Package,
  IBootable,
  IPackageRegistration,
  Application,
} from "@abdokouta/application";
import { MyModule } from "./my.module";

@Package({
  name: "@abdokouta/my-package",
  version: "1.0.0",
  dependencies: ["@abdokouta/react-di"],
})
export class MyPackage implements IBootable {
  private options: MyOptions;

  constructor(options: MyOptions = {}) {
    this.options = options;
  }

  /**
   * Factory method for registration
   */
  static forRoot(options?: MyOptions): IPackageRegistration {
    return {
      manifest: {
        name: "@abdokouta/my-package",
        version: "1.0.0",
        dependencies: ["@abdokouta/react-di"],
        module: MyModule,
      },
      dynamicModule: MyModule.forRoot(options),
      bootable: new MyPackage(options),
    };
  }

  /**
   * Called when the package is being initialized.
   * Other packages may not be ready yet.
   */
  onBoot(app: Application): void {
    // Register built-in components
    myRegistry.register("default", DefaultComponent);
    console.log("[MyPackage] Booted");
  }

  /**
   * Called after ALL packages have booted.
   * Safe to resolve cross-package dependencies.
   */
  onReady(app: Application): void {
    // Access services from other packages
    const authConfig = app.resolve(AUTH_MODULE_CONFIG);
    console.log("[MyPackage] Ready");
  }

  /**
   * Called when the application is shutting down.
   */
  onShutdown(app: Application): void {
    // Cleanup resources
    console.log("[MyPackage] Shutdown");
  }
}

API Reference

Application

Application.create(options?)

Creates a new Application instance.

const app = Application.create({
  name: "My App", // Display name for logging
  version: "1.0.0", // App version
  logLevel: "debug", // 'none' | 'info' | 'debug'
  defaultScope: "Singleton", // DI scope
  strict: true, // Throw on errors
  bootTimeout: 30000, // Timeout for async operations
  onError: (error, pkg) => {}, // Error handler
});

.use(registration)

Register a package.

app.use(AuthPackage.forRoot({ ... }));

.on(event, callback)

Subscribe to lifecycle events.

app.on("packageBooted", ({ manifest, duration }) => {
  console.log(`${manifest.name} booted in ${duration}ms`);
});

.boot()

Boot the application. Must be called before React renders.

app.boot();

.resolve(identifier)

Resolve a service from the DI container.

const service = app.resolve(MyService);
const config = app.resolve(MY_CONFIG_TOKEN);

.shutdown(reason?)

Shutdown the application gracefully.

await app.shutdown("User logged out");

Hooks

useApplication()

Access the Application instance.

const { app } = useApplication();

useBootPhase()

Get the current boot phase.

const phase = useBootPhase();
// BootPhase.READY

usePackage(name)

Get information about a registered package.

const { isBooted, version, bootDuration } = usePackage("@abdokouta/auth");

Events

| Event | Payload | Description | | ------------------- | ------------------------------------------ | ----------------------------- | | phaseChange | { from, to, timestamp } | Boot phase changed | | packageRegistered | { manifest, totalRegistered } | Package registered | | packageBooting | { manifest, order, total } | Package starting to boot | | packageBooted | { manifest, duration } | Package finished booting | | packageFailed | { manifest, error } | Package failed to boot | | ready | { totalPackages, totalDuration } | All packages ready | | shuttingDown | { reason? } | Shutdown started | | terminated | { duration } | Shutdown complete | | error | { error, phase, packageName? } | Error occurred |

Boot Phases

enum BootPhase {
  IDLE = "idle", // Initial state
  REGISTERING = "registering", // Packages being registered
  RESOLVING = "resolving", // Dependency graph being resolved
  BOOTING = "booting", // Packages executing onBoot()
  READY = "ready", // All packages ready
  SHUTTING_DOWN = "shutting_down", // Shutdown in progress
  TERMINATED = "terminated", // Shutdown complete
}

Dependency Resolution

The Application automatically resolves package dependencies using topological sort:

// These can be registered in any order
app
  .use(AuthPackage.forRoot()) // depends on: ['@abdokouta/react-di']
  .use(RefinePackage.forRoot()) // depends on: ['@abdokouta/react-di']
  .use(TenantPackage.forRoot()) // depends on: ['@abdokouta/auth']
  .boot();

// Boot order will be:
// 1. @abdokouta/react-di (no deps)
// 2. @abdokouta/auth (depends on react-di)
// 3. @abdokouta/refine (depends on react-di)
// 4. @abdokouta/tenant (depends on auth)

Circular dependencies are detected and throw an error:

DependencyResolverError: Circular dependency detected: A → B → C → A

License

MIT © Abdo Kouta