Skip to content

Commit

Permalink
[DI] Implement a plugin registry in ts-inject
Browse files Browse the repository at this point in the history
  • Loading branch information
jcorbett-sc committed Oct 29, 2024
1 parent 60a89bf commit 590a2b7
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 2 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

78 changes: 78 additions & 0 deletions src/PluginRegistry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/**
* A type representing a function that observes a plugin.
*
* @template PluginInterface - The interface that the plugin implements.
* @param plugin - The plugin instance that is being observed.
*/
export type PluginObserver<PluginInterface> = (plugin: PluginInterface) => void;

/**
* A registry for managing plugins and notifying observers about new plugins.
*
* This class allows you to register plugins and observe when new plugins are added.
* It maintains a list of plugins and notifies all registered observers whenever a new plugin is added.
*
* @template PluginInterface - The interface that all plugins must implement.
*
* @example
* // Define a plugin interface
* interface MyPlugin {
* doSomething(): void;
* }
*
* // Create a plugin registry for MyPlugin
* const registry = new PluginRegistry<MyPlugin>();
*
* // Define a plugin that implements MyPlugin
* const plugin: MyPlugin = {
* doSomething() {
* console.log('Plugin is doing something');
* }
* };
*
* // Define an observer
* const observer: PluginObserver<MyPlugin> = (plugin) => {
* console.log('New plugin registered:', plugin);
* };
*
* // Register the observer
* registry.observe(observer);
*
* // Register the plugin
* registry.register(plugin);
* // Output:
* // New plugin registered: { doSomething: [Function: doSomething] }
* // Plugin is doing something
*/
export class PluginRegistry<PluginInterface> {
private plugins: PluginInterface[] = [];
private observers: PluginObserver<PluginInterface>[] = [];

/**
* Registers a new plugin and notifies all observers about the new plugin.
*
* @param plugin - The plugin to be registered, which implements the PluginInterface.
*/
register(plugin: PluginInterface): void {
this.plugins.push(plugin);
this.observers.forEach((observer) => observer(plugin));
}

/**
* Registers an observer to the plugin registry.
*
* @param observer - The observer that will be called when a new plugin is registered.
*/
observe(observer: PluginObserver<PluginInterface>): void {
this.observers.push(observer);
}

/**
* Retrieves the list of registered plugins.
*
* @returns {PluginInterface[]} An array of plugins registered with the registry.
*/
getPlugins(): PluginInterface[] {
return this.plugins;
}
}
33 changes: 33 additions & 0 deletions src/__tests__/PluginRegistry.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { PluginRegistry } from "../PluginRegistry";

interface MockPluginInterface {
mockMethod(): void;
}

describe("PluginRegistry", () => {
let registry: PluginRegistry<MockPluginInterface>;
let plugin: MockPluginInterface;
let observer: jest.Mock;

beforeEach(() => {
registry = new PluginRegistry();
plugin = {
mockMethod: jest.fn(),
};
observer = jest.fn();
});

test("should register a plugin and notify observers", () => {
registry.observe(observer);
registry.register(plugin);

expect(observer).toHaveBeenCalledWith(plugin);
expect(observer).toHaveBeenCalledTimes(1);
});

test("should return the list of registered plugins", () => {
registry.register(plugin);

expect(registry.getPlugins()).toEqual([plugin]);
});
});

0 comments on commit 590a2b7

Please sign in to comment.