From 425889454bd049aee2a0825fb0bb693c9e12661e Mon Sep 17 00:00:00 2001 From: Rebegea Dragos-Alexandru Date: Wed, 4 Jun 2025 14:33:25 +0300 Subject: [PATCH] plugins compiled code --- src/common/plugins/plugin.service.ts | 77 +++++++++++++++++-- .../plugin.module.ts.template | 39 +++++++++- 2 files changed, 108 insertions(+), 8 deletions(-) diff --git a/src/common/plugins/plugin.service.ts b/src/common/plugins/plugin.service.ts index 317c32e99..8de7c7f8c 100644 --- a/src/common/plugins/plugin.service.ts +++ b/src/common/plugins/plugin.service.ts @@ -1,21 +1,84 @@ -import { Injectable } from "@nestjs/common"; +import { Injectable, Logger } from "@nestjs/common"; import { NestExpressApplication } from "@nestjs/platform-express"; import { AccountDetailed } from "src/endpoints/accounts/entities/account.detailed"; import { About } from "src/endpoints/network/entities/about"; import { Nft } from "src/endpoints/nfts/entities/nft"; import { Transaction } from "src/endpoints/transactions/entities/transaction"; +export interface IPlugin { + name: string; + version: string; + processTransactions?(transactions: Transaction[], withScamInfo?: boolean): Promise; + processTransactionSend?(transaction: any): Promise; + processAccount?(account: AccountDetailed): Promise; + bootstrapPublicApp?(application: NestExpressApplication): Promise; + batchProcessNfts?(nfts: Nft[], withScamInfo?: boolean): Promise; + processAbout?(about: About): Promise; +} + @Injectable() export class PluginService { - async processTransactions(_transactions: Transaction[], _withScamInfo?: boolean): Promise { } + private readonly logger = new Logger(PluginService.name); + private plugins: IPlugin[] = []; + + registerPlugins(plugins: IPlugin[]) { + for (const plugin of plugins) { + try { + if (!plugin.name || !plugin.version) { + throw new Error('Plugin must have name and version'); + } + this.plugins.push(plugin); + this.logger.log(`Registered plugin: ${plugin.name} v${plugin.version}`); + } catch (err) { + this.logger.error(`Failed to register plugin:`, err); + } + } + } + + private async executePluginMethod(methodName: keyof IPlugin, ...args: any[]): Promise { + for (const plugin of this.plugins) { + const method = plugin[methodName] as Function; + if (method) { + try { + await method.apply(plugin, args); + } catch (err) { + this.logger.error(`Error in plugin ${plugin.name} method ${methodName}:`, err); + } + } + } + } + + async processTransactions(transactions: Transaction[], withScamInfo?: boolean): Promise { + await this.executePluginMethod('processTransactions', transactions, withScamInfo); + } - async processTransactionSend(_transaction: any): Promise { } + async processTransactionSend(transaction: any): Promise { + let result = transaction; + for (const plugin of this.plugins) { + if (plugin.processTransactionSend) { + try { + result = await plugin.processTransactionSend(result); + } catch (err) { + this.logger.error(`Error in plugin ${plugin.name} processTransactionSend:`, err); + } + } + } + return result; + } - async processAccount(_account: AccountDetailed): Promise { } + async processAccount(account: AccountDetailed): Promise { + await this.executePluginMethod('processAccount', account); + } - async bootstrapPublicApp(_application: NestExpressApplication): Promise { } + async bootstrapPublicApp(application: NestExpressApplication): Promise { + await this.executePluginMethod('bootstrapPublicApp', application); + } - async batchProcessNfts(_nfts: Nft[], _withScamInfo?: boolean): Promise { } + async batchProcessNfts(nfts: Nft[], withScamInfo?: boolean): Promise { + await this.executePluginMethod('batchProcessNfts', nfts, withScamInfo); + } - async processAbout(_about: About): Promise { } + async processAbout(about: About): Promise { + await this.executePluginMethod('processAbout', about); + } } diff --git a/src/plugins.template/plugin.module.ts.template b/src/plugins.template/plugin.module.ts.template index d2d5acab7..1c733c7c8 100644 --- a/src/plugins.template/plugin.module.ts.template +++ b/src/plugins.template/plugin.module.ts.template @@ -1,8 +1,45 @@ import { Module } from "@nestjs/common"; import { PluginService } from "../common/plugins/plugin.service"; +import * as fs from 'fs'; +import * as path from 'path'; + +// Load compiled plugins +const compiledPluginsPath = path.join(__dirname, 'compiled'); +const loadCompiledPlugins = () => { + const plugins = []; + if (fs.existsSync(compiledPluginsPath)) { + const entries = fs.readdirSync(compiledPluginsPath); + for (const entry of entries) { + const pluginPath = path.join(compiledPluginsPath, entry); + if (fs.statSync(pluginPath).isDirectory()) { + const distPath = path.join(pluginPath, 'dist', 'index.js'); + if (fs.existsSync(distPath)) { + try { + const plugin = require(distPath); + plugins.push(plugin); + } catch (err) { + console.error(`Failed to load compiled plugin ${entry}:`, err); + } + } + } + } + } + return plugins; +}; @Module({ - providers: [PluginService], + providers: [ + { + provide: PluginService, + useFactory: () => { + const service = new PluginService(); + // Load and register compiled plugins + const compiledPlugins = loadCompiledPlugins(); + service.registerPlugins(compiledPlugins); + return service; + }, + }, + ], exports: [PluginService], }) export class PluginModule { }