Skip to content

A modular plugin architecture demo for low-code platforms using Node.js with plugin loader, manifest, registry and hook/event execution

Notifications You must be signed in to change notification settings

nivedhapalani96/lowcode-plugin-architecture-demo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Low-Code Plugin Architecture Demo

Enterprise-Grade Modular Plugin System - A production-ready, extensible plugin architecture designed for low-code platforms, featuring dependency management, lifecycle tracking, priority-based execution, and comprehensive error handling.

Node.js Version License

πŸ“– Read the detailed blog post: Designing a Modular Plugin Architecture for Low-Code Platforms

🎯 Overview

This repository demonstrates a production-ready plugin architecture suitable for building extensible low-code platforms, content management systems, and any application requiring a robust plugin ecosystem. The architecture emphasizes:

  • πŸ”Œ Modular Design: Clean separation of concerns with pluggable components
  • πŸ”„ Lifecycle Management: Complete plugin lifecycle from discovery to shutdown
  • πŸ”— Dependency Resolution: Automatic dependency ordering and circular dependency detection
  • ⚑ Priority-Based Execution: Control plugin execution order via priority system
  • πŸ›‘οΈ Error Isolation: Plugin failures don't crash the entire system
  • πŸ“Š Observability: Built-in metrics, logging, and event history
  • πŸ”’ Sandboxed APIs: Secure plugin execution with capability-based access control

πŸ“‹ Table of Contents

πŸ—οΈ Architecture

System Components

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    PluginPlatform                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
β”‚  β”‚  EventBus    β”‚  β”‚   Registry   β”‚  β”‚    Loader    β”‚     β”‚
β”‚  β”‚              β”‚  β”‚              β”‚  β”‚              β”‚     β”‚
β”‚  β”‚ - Priority   β”‚  β”‚ - Lifecycle  β”‚  β”‚ - Discovery  β”‚     β”‚
β”‚  β”‚ - Middleware β”‚  β”‚ - Dependenciesβ”‚ β”‚ - Validation β”‚     β”‚
β”‚  β”‚ - History    β”‚  β”‚ - Stats      β”‚  β”‚ - Sandboxing β”‚     β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                          β”‚
                          β–Ό
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚         Plugin Instances             β”‚
        β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
        β”‚  β”‚ Plugin A β”‚  β”‚ Plugin B β”‚  ...   β”‚
        β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Component Responsibilities

PluginPlatform (Main Orchestrator)

  • Coordinates plugin discovery, loading, and registration
  • Manages platform lifecycle (init, shutdown)
  • Provides unified API for event emission and plugin access
  • Tracks platform-wide statistics and metrics

EventBus (Event System)

  • Priority-based handler execution
  • Middleware support for cross-cutting concerns
  • Error isolation (one handler failure doesn't stop others)
  • Event history and debugging capabilities
  • Timeout support for long-running handlers

PluginRegistry (Plugin Management)

  • Stores plugin metadata and instances
  • Tracks plugin lifecycle states (registered, active, error, disabled)
  • Dependency graph management and validation
  • Topological sorting for dependency-ordered execution
  • Plugin statistics and health monitoring

Loader (Plugin Discovery)

  • Discovers plugins from directory structure
  • Validates manifest schemas and types
  • Loads and initializes plugin modules
  • Creates sandboxed API for each plugin
  • Handles errors gracefully with configurable strategies

🧩 Core Concepts

1. Plugin Manifest

Every plugin must declare a manifest.json file that describes its metadata, capabilities, and behavior:

{
  "name": "my-plugin",
  "version": "1.0.0",
  "description": "Plugin description",
  "entry": "./index.js",
  "hooks": ["beforeSave", "afterSave"],
  "priority": 50,
  "enabled": true,
  "dependencies": ["other-plugin"],
  "capabilities": {
    "readRecord": true,
    "writeRecord": true
  },
  "config": {
    "customSetting": "value"
  }
}

Required Fields:

  • name: Unique plugin identifier
  • version: Semantic version (e.g., "1.0.0")
  • entry: Path to plugin entry point (relative to plugin directory)
  • hooks: Array of hook names this plugin subscribes to

Optional Fields:

  • priority: Execution priority (lower = higher priority, default: 100)
  • enabled: Enable/disable plugin (default: true)
  • dependencies: Array of plugin names this plugin depends on
  • capabilities: Object declaring plugin capabilities
  • config: Plugin-specific configuration object
  • timeout: Handler timeout in milliseconds

2. Plugin Implementation

Plugins export a default function that receives a sandboxed API and returns hook handlers:

export default function myPlugin(api) {
  // Access plugin API
  api.log('Plugin initializing');
  api.warn('Warning message');
  api.error('Error message');
  
  // Access capabilities
  if (api.capabilities.writeRecord) {
    // Safe to write
  }
  
  // Access configuration
  const setting = api.config.customSetting;
  
  // Return hook handlers
  return {
    async beforeSave(record) {
      // Modify record before save
      record.modified = true;
      api.log('Record modified');
    },
    
    async afterSave(record) {
      // Post-save logic
      api.log('Record saved:', record.id);
    }
  };
}

3. Hook System

Hooks are events that plugins can subscribe to. The platform emits hooks at specific lifecycle points:

  • beforeSave: Executed before a record is saved (allows modification)
  • afterSave: Executed after a record is saved (read-only)
  • platform:shutdown: Executed during platform shutdown (cleanup)

Plugins execute in priority order (lower priority number = executes first).

4. Dependency Management

Plugins can declare dependencies on other plugins:

{
  "name": "plugin-b",
  "dependencies": ["plugin-a"]
}

The platform automatically:

  • Validates all dependencies exist
  • Detects circular dependencies
  • Orders plugin execution based on dependency graph
  • Loads dependencies before dependents

πŸš€ Getting Started

Prerequisites

  • Node.js >= 18.0.0
  • npm or yarn

Installation

# Clone the repository
git clone https://github.com/nivedhapalani96/lowcode-plugin-architecture-demo.git
cd lowcode-plugin-architecture-demo

# Install dependencies (none required, but keeps workflow familiar)
npm install

Running Examples

# Run the main demo
npm run demo

# List all discovered plugins
npm run list:plugins

πŸ”§ Plugin Development

Creating a New Plugin

  1. Create plugin directory:

    mkdir -p src/plugins/my-plugin
  2. Create manifest.json:

    {
      "name": "my-plugin",
      "version": "1.0.0",
      "description": "My awesome plugin",
      "entry": "./index.js",
      "hooks": ["beforeSave"],
      "priority": 100
    }
  3. Implement plugin (index.js):

    export default function myPlugin(api) {
      api.log('My plugin loaded');
      
      return {
        async beforeSave(record) {
          // Your logic here
          record.processedBy = 'my-plugin';
        }
      };
    }
  4. Test your plugin:

    npm run demo

Plugin API Reference

The api object provided to plugins includes:

Logging

  • api.log(...args): Log informational messages
  • api.warn(...args): Log warnings
  • api.error(...args): Log errors

Metadata

  • api.manifest: Read-only plugin manifest
  • api.capabilities: Read-only capabilities object
  • api.config: Plugin configuration object

Platform Access

  • api.platform.emit(eventName, payload): Emit custom events
  • api.platform.getPlugin(name): Get another plugin instance

Utilities

  • api.utils.validate(value, schema): Validate values
  • api.utils.clone(obj): Deep clone objects

πŸ“š API Reference

PluginPlatform

Constructor

const platform = new PluginPlatform(options);

Options:

  • pluginsDir (string): Custom plugins directory path
  • eventBus (object): EventBus configuration
    • enableHistory (boolean): Enable event history
    • maxHistorySize (number): Max history entries
    • defaultPriority (number): Default handler priority
  • loader (object): Loader configuration
    • enabledOnly (boolean): Only load enabled plugins
    • validateDependencies (boolean): Validate dependencies
    • onError (string): Error handling strategy ('warn', 'throw', 'skip')

Methods

async init(options)

Initialize the platform and load all plugins.

const result = await platform.init();
// Returns: { initialized, initTime, plugins, loadOrder }
async emit(eventName, payload, options)

Emit an event to all registered handlers.

const result = await platform.emit('beforeSave', record, {
  stopOnError: false,
  timeout: 5000
});
// Returns: { success, executed, errors, duration }
listPlugins()

Get all registered plugin manifests.

const plugins = platform.listPlugins();
getPlugin(name)

Get a specific plugin by name.

const plugin = platform.getPlugin('my-plugin');
getStats()

Get platform statistics.

const stats = platform.getStats();
// Returns: { initTime, totalEvents, totalErrors, plugins }
use(middleware)

Add event bus middleware.

platform.use(async (payload, next) => {
  console.log('Before handlers');
  await next();
  console.log('After handlers');
});
async shutdown()

Shutdown the platform and cleanup.

await platform.shutdown();

🎯 Advanced Features

Priority-Based Execution

Control plugin execution order using the priority field:

{
  "name": "high-priority-plugin",
  "priority": 10,  // Executes first (lower number = higher priority)
  "hooks": ["beforeSave"]
}

Middleware

Add cross-cutting concerns using middleware:

platform.use(async (payload, next) => {
  const start = Date.now();
  await next();
  console.log(`Event took ${Date.now() - start}ms`);
});

Error Handling Strategies

Configure how the loader handles plugin errors:

const platform = new PluginPlatform({
  loader: {
    onError: 'warn'  // Options: 'warn', 'throw', 'skip'
  }
});

Event History

Enable event history for debugging:

const platform = new PluginPlatform({
  eventBus: {
    enableHistory: true,
    maxHistorySize: 100
  }
});

// Access history
const history = platform.eventBus.getHistory();

Dependency Validation

The platform automatically validates dependencies:

// Circular dependency detection
// Missing dependency detection
// Automatic topological sorting

πŸ’‘ Best Practices

1. Plugin Design

  • Single Responsibility: Each plugin should do one thing well
  • Idempotency: Hook handlers should be idempotent when possible
  • Error Handling: Always handle errors gracefully within plugins
  • Logging: Use appropriate log levels (log, warn, error)

2. Performance

  • Async Operations: Use async/await for I/O operations
  • Timeouts: Set reasonable timeouts for long-running operations
  • Priority: Use priority to optimize critical path execution
  • Lazy Loading: Defer heavy initialization until needed

3. Security

  • Capability Checks: Always check capabilities before operations
  • Input Validation: Validate and sanitize inputs
  • Sandboxing: Don't expose sensitive platform internals
  • Dependencies: Minimize plugin dependencies

4. Testing

  • Unit Tests: Test plugin logic in isolation
  • Integration Tests: Test plugin interactions
  • Error Scenarios: Test error handling paths
  • Performance Tests: Monitor plugin performance

5. Documentation

  • Clear Descriptions: Write clear plugin descriptions
  • Hook Documentation: Document what each hook does
  • Configuration: Document configuration options
  • Examples: Provide usage examples

πŸ“– Examples

Example 1: Basic Plugin

// src/plugins/hello-world/index.js
export default function helloWorldPlugin(api) {
  return {
    async beforeSave(record) {
      record.greeting = 'Hello, World!';
      api.log('Added greeting to record');
    }
  };
}

Example 2: Plugin with Dependencies

// src/plugins/advanced-plugin/manifest.json
{
  "name": "advanced-plugin",
  "version": "1.0.0",
  "description": "Depends on another plugin",
  "entry": "./index.js",
  "hooks": ["beforeSave"],
  "dependencies": ["hello-world"],
  "priority": 50
}

Example 3: Plugin with Configuration

// src/plugins/configurable-plugin/index.js
export default function configurablePlugin(api) {
  const prefix = api.config.prefix || 'PREFIX';
  
  return {
    async beforeSave(record) {
      record.id = `${prefix}-${record.id}`;
      api.log(`Prefixed ID with: ${prefix}`);
    }
  };
}

Example 4: Error Handling

export default function robustPlugin(api) {
  return {
    async beforeSave(record) {
      try {
        // Risky operation
        if (!record.data) {
          throw new Error('Missing data');
        }
        // Process record
      } catch (error) {
        api.error('Failed to process record:', error.message);
        // Don't re-throw - allow other plugins to continue
      }
    }
  };
}

🏒 Production Considerations

For production deployments, consider:

  1. Monitoring: Add metrics collection (Prometheus, DataDog, etc.)
  2. Logging: Integrate with centralized logging (ELK, Splunk, etc.)
  3. Security: Implement plugin signing and verification
  4. Performance: Add caching, rate limiting, and resource quotas
  5. Testing: Comprehensive test coverage and CI/CD pipelines
  6. Documentation: API documentation and developer guides
  7. Versioning: Plugin version management and migration strategies
  8. Rollback: Ability to disable/rollback problematic plugins

🀝 Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests if applicable
  5. Submit a pull request

πŸ“„ License

MIT License - see LICENSE file for details

πŸ™ Acknowledgments

This architecture is inspired by:

  • WordPress plugin system
  • VS Code extension architecture
  • Webpack plugin system
  • Modern microservices patterns

Built with ❀️ for extensible platforms

About

A modular plugin architecture demo for low-code platforms using Node.js with plugin loader, manifest, registry and hook/event execution

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •