Plugin System¶
Farm is built with an extensible architecture that uses a Plugin System to manage features and modules. This allows for a modular and maintainable codebase.
Overview¶
The Plugin System is designed to:
- Decouple core platform logic from specific feature modules
- Enable dynamic registration of modules during application startup
- Provide a discovery mechanism for both the backend and frontend
- Facilitate the development of independent, feature-rich plugins
Core Concepts¶
Plugin Interface¶
Each plugin in Farm must implement the FarmPlugin interface, which includes metadata and the corresponding NestJS module.
export interface PluginMetadata {
name: string;
version: string;
description: string;
author?: string;
}
export interface FarmPlugin {
metadata: PluginMetadata;
module: Type<any> | DynamicModule | Promise<DynamicModule> | ForwardReference;
}
Plugin Manager¶
The PluginManagerModule is a global module responsible for:
- Registry: Maintaining a central registry of all active plugins and their metadata.
- Dynamic Loading: Using
forRootto dynamically import and configure plugin modules. - Discovery API: Exposing an endpoint (
GET /api/v1/plugins) that lists all active features and their versions.
Creating a New Plugin¶
To create a new plugin for Farm, follow these steps:
- Create a Feature Module: Develop a standard NestJS module (e.g.,
MyFeatureModule). - Define Metadata: Create a metadata object describing your plugin.
- Register in AppModule: Add your plugin to the
PluginManagerModule.forRootarray inapps/api/src/app.module.ts.
Example¶
// apps/api/src/app.module.ts
@Module({
imports: [
PluginManagerModule.forRoot([
{
metadata: {
name: 'core-auth',
version: '1.0.0',
description: 'User authentication and JWT management',
},
module: AuthModule,
},
{
metadata: {
name: 'core-catalog',
version: '1.0.0',
description: 'Software component registry',
},
module: CatalogModule,
},
{
metadata: {
name: 'core-documentation',
version: '1.0.0',
description: 'Technical documentation management',
},
module: DocumentationModule,
},
{
metadata: {
name: 'core-environments',
version: '1.0.0',
description: 'Deployment environments and tracking',
},
module: EnvironmentsModule,
},
{
metadata: {
name: 'core-teams',
version: '1.0.0',
description: 'Team ownership and membership',
},
module: TeamsModule,
},
{
metadata: {
name: 'core-audit-log',
version: '1.0.0',
description: 'Immutable audit trail for system actions',
},
module: AuditLogModule,
},
{
metadata: {
name: 'my-new-feature',
version: '1.0.0',
description: 'Adds amazing new capabilities to Farm',
},
module: MyFeatureModule,
},
]),
],
})
export class AppModule {}
Best Practices¶
- Independence: Plugins should be as independent as possible. Avoid direct dependencies between feature modules.
- Communication: Use shared providers or an event-driven approach for cross-plugin communication.
- Metadata Accuracy: Ensure the name and version in your plugin metadata reflect its current state.
- Standardization: Follow the NestJS development best practices and the Farm directory structure for all new plugins.