feat(gateway): add plugin host module
Some checks failed
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline was successful

This commit is contained in:
2026-03-13 12:04:42 -05:00
parent 9eb48e1d9b
commit 280c5351e2
7 changed files with 147 additions and 0 deletions

View File

@@ -0,0 +1,90 @@
import {
Global,
Inject,
Logger,
Module,
type OnModuleDestroy,
type OnModuleInit,
} from '@nestjs/common';
import { DiscordPlugin } from '@mosaic/discord-plugin';
import { PluginService } from './plugin.service.js';
import type { IChannelPlugin } from './plugin.interface.js';
export const PLUGIN_REGISTRY = Symbol('PLUGIN_REGISTRY');
class DiscordChannelPluginAdapter implements IChannelPlugin {
readonly name = 'discord';
constructor(private readonly plugin: DiscordPlugin) {}
async start(): Promise<void> {
await this.plugin.start();
}
async stop(): Promise<void> {
await this.plugin.stop();
}
}
const DEFAULT_GATEWAY_URL = 'http://localhost:4000';
function createPluginRegistry(logger: Logger): IChannelPlugin[] {
const plugins: IChannelPlugin[] = [];
const discordToken = process.env['DISCORD_BOT_TOKEN'];
const discordGuildId = process.env['DISCORD_GUILD_ID'];
const discordGatewayUrl = process.env['DISCORD_GATEWAY_URL'] ?? DEFAULT_GATEWAY_URL;
if (discordToken) {
plugins.push(
new DiscordChannelPluginAdapter(
new DiscordPlugin({
token: discordToken,
guildId: discordGuildId,
gatewayUrl: discordGatewayUrl,
}),
),
);
}
const telegramToken = process.env['TELEGRAM_BOT_TOKEN'];
const telegramGatewayUrl = process.env['TELEGRAM_GATEWAY_URL'] ?? DEFAULT_GATEWAY_URL;
if (telegramToken) {
logger.warn(
`Telegram plugin requested for ${telegramGatewayUrl}, but @mosaic/telegram-plugin is not implemented yet.`,
);
}
return plugins;
}
@Global()
@Module({
providers: [
{
provide: PLUGIN_REGISTRY,
useFactory: (): IChannelPlugin[] => createPluginRegistry(new Logger('PluginModule')),
},
PluginService,
],
exports: [PluginService, PLUGIN_REGISTRY],
})
export class PluginModule implements OnModuleInit, OnModuleDestroy {
private readonly logger = new Logger(PluginModule.name);
constructor(@Inject(PLUGIN_REGISTRY) private readonly plugins: IChannelPlugin[]) {}
async onModuleInit(): Promise<void> {
for (const plugin of this.plugins) {
this.logger.log(`Starting plugin: ${plugin.name}`);
await plugin.start();
}
}
async onModuleDestroy(): Promise<void> {
for (const plugin of [...this.plugins].reverse()) {
this.logger.log(`Stopping plugin: ${plugin.name}`);
await plugin.stop();
}
}
}