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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@zyrohub/core

v1.1.1

Published

The core module of ZyroHub ecosystem.

Readme

ZyroHub - Core

Table of Contents

Getting Started

To install the core module, use one of the following package managers:

NPM Repository

# npm
npm install @zyrohub/core
# yarn
yarn add @zyrohub/core
# pnpm
pnpm add @zyrohub/core
# bun
bun add @zyrohub/core

TypeScript Configuration

⚠️ Important: To use the Dependency Injection system, you must enable emitDecoratorMetadata in your tsconfig.json.

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

Basic Usage

Creating a Core Instance

The modules are automatically initialized in order when the core instance is created.

import { Core } from '@zyrohub/core';

import { MyModule } from './modules/MyModule.js';

const core = new Core({
	modules: [MyModule]
});

await core.init();

Cluster Support

You can also create a Clustered Core instance to take advantage of multi-core systems. The clustered core will automatically manage worker processes and restart them if they fail.

import { ClusteredCore } from '@zyrohub/core';

import { MyModule } from './modules/MyModule.js';

const core = new ClusteredCore({
	core: {
		modules: [MyModule]
	},
	settings: {
		workers: {
			autoRestart: { enabled: true, delay: 5000 }
		}
	}
});

await core.init();

Modules

Modules are the building blocks of your application. Use the @Module() decorator to register a class as a module.

Creating a Module (@Module)

import { BaseModule, Module, type Core } from '@zyrohub/core';
import { Terminal } from '@zyrohub/utilities';

@Module()
export class DatabaseModule extends BaseModule {
	async init(data: { core: Core }) {
		Terminal.success('DB', 'Database connected.');
	}

	// Called when the application is shutting down
	async shutdown() {
		Terminal.info('DB', 'Closing connections...');
	}
}

Configuration with .mount()

To pass options to a module before initialization, use the static mount method. These options are accessible in the init method via data.options.

export interface HttpOptions {
	port: number;
}

@Module()
export class HttpModule extends BaseModule {
	static options: HttpOptions;

	// Options passed in .mount() are received here
	async init(data: { core: Core; options: HttpOptions }) {
		const { port } = data.options;
		console.log(`Server starting on port ${port}`);
	}
}

// Usage
const core = new Core({
	modules: [
		// Pass the configuration object here
		HttpModule.mount({ port: 3000 })
	]
});

Dependency Injection (DI)

The @zyrohub/core has a DI container that resolves dependencies automatically. Modules are automatically registered as providers.

Creating Services (@Injectable)

Use the @Injectable() decorator to mark a class as a provider that can be injected.

import { Injectable } from '@zyrohub/core';

@Injectable()
export class UserService {
	getAll() {
		return ['User 1', 'User 2'];
	}
}

Injecting Dependencies

You can inject services or other modules directly into the constructor.

import { Module, BaseModule } from '@zyrohub/core';

import { UserService } from './services/UserService.js';

@Module()
export class UserModule extends BaseModule {
	// UserService is automatically injected here
	constructor(private userService: UserService) {
		super();
	}

	async init() {
		console.log(this.userService.getAll());
	}
}

Note: For circular dependencies or modules defined later in the list, use core.getModule(TargetModule) inside the init() method instead of constructor injection.

Token Injection (@Inject)

You can assign a custom token to a module using the second argument of .mount(). This is especially useful for running multiple instances of the same module or injecting specific configurations.

import { Inject, Module, BaseModule } from '@zyrohub/core';

@Module()
export class BotModule extends BaseModule {
	constructor(@Inject('BOT_TOKEN') private token: string) {
		super();
	}
}

// Using .mount(options, token) to register with a custom token
const core = new Core({
	modules: [
		// This module will be registered as 'BOT_SALES' in the provider container
		BotModule.mount({ settings: '...' }, 'BOT_SALES'),

		// This one as 'BOT_SUPPORT'
		BotModule.mount({ settings: '...' }, 'BOT_SUPPORT')
	]
});

To consume these specific instances later:

// Injecting by Token
constructor(@Inject('BOT_SALES') private salesBot: BotModule) {}

// Or resolving manually
const supportBot = core.resolve('BOT_SUPPORT');

To consume these specific instances later:

@Module()
export class SalesController extends BaseModule {
	// Injecting by Token
	constructor(@Inject('BOT_SALES') private salesBot: BotModule) {
		super();
	}

	async init() {
		// Use salesBot instance...
	}
}

// Or resolving manually
const supportBot = core.resolve('BOT_SUPPORT');

Core DI Methods (instantiate & resolve)

The Core exposes methods to interact with the DI container manually, useful for Controllers or external scripts.

// 1. Instantiate: Creates a NEW instance with dependencies injected (Transient)
const userController = core.instantiate(UserController);

// 2. Resolve: Retrieves an EXISTING singleton instance (Service or Module)
const databaseModule = core.resolve(DatabaseModule);

Lifecycle

The framework manages the application lifecycle.

Initialization (init)

  1. Instantiation Phase: All modules are instantiated and registered in the provider container.
  2. Initialization Phase: The init() method of each module is called. It is safe to communicate with other modules here.

Graceful Shutdown (shutdown)

The Core listens for system signals (SIGINT, SIGTERM). When received:

  1. The shutdown() method is called on all modules, in reverse order of initialization.
  2. The application exits gracefully.

Events

The core emits events that you can listen to.

core.on('ready', ({ core }) => {
	console.log('Core is ready!');
});

core.on('moduleInit', ({ module }) => {
	console.log(`Module ${module.getName()} initialized.`);
});

core.on('shutdown', () => {
	console.log('Application shut down.');
});