eleva

Creating a Custom Plugin for Eleva

Version: 1.2.0 Complete guide to creating, testing, and publishing Eleva plugins.

Prerequisites

Plugin development requires a solid understanding of Eleva’s architecture:


Documentation Pages


Quick Start

Here’s a complete, minimal example of creating and registering a custom plugin:

import Eleva from "eleva";

// 1. Define the plugin
const UtilsPlugin = {
  name: "utils",                          // Required: unique identifier
  version: "1.0.0",                       // Required: semantic version string
  install(eleva, options = {}) {          // Required: called when plugin is registered
    // Add utility methods to the Eleva instance
    eleva.utils = {
      formatDate: (date) => new Date(date).toLocaleDateString(),
      capitalize: (str) => str.charAt(0).toUpperCase() + str.slice(1),
      debounce: (fn, delay = 300) => {
        let timer;
        return (...args) => {
          clearTimeout(timer);
          timer = setTimeout(() => fn(...args), delay);
        };
      }
    };
  }
};

// 2. Create Eleva instance
const app = new Eleva("MyApp");

// 3. Register the plugin with app.use()
app.use(UtilsPlugin);                     // Without options
// OR
app.use(UtilsPlugin, { locale: "en-US" }); // With options

// 4. Use the plugin in components
app.component("DateDisplay", {
  setup: () => ({
    formatted: app.utils.formatDate(Date.now())  // Access via app instance
  }),
  template: (ctx) => `<p>Today: ${ctx.formatted}</p>`
});

app.mount(document.getElementById("app"), "DateDisplay");

Prerequisites

Before you start, ensure you have:


Plugin Basics

An Eleva plugin is a JavaScript object that extends the framework’s functionality. Every plugin must have:

  1. A unique name property (string)
  2. A version property following semantic versioning (string)
  3. An install method that receives the Eleva instance and options
const MyPlugin = {
  name: "myPlugin",
  version: "1.0.0",
  install(eleva, options) {
    // Plugin implementation
  }
};
Property Type Required Description
name string Yes Unique identifier for the plugin
version string Yes Semantic version (e.g., “1.0.0”, “2.1.3”)
install function Yes Called with (eleva, options) during registration
uninstall function No Optional cleanup when plugin is removed

Registering Plugins

Plugins are registered using the app.use() method. This method calls the plugin’s install function with the Eleva instance and any provided options.

Basic Registration

import Eleva from "eleva";
import MyPlugin from "./my-plugin.js";

const app = new Eleva("MyApp");

// Register without options
app.use(MyPlugin);

// Register with options
app.use(MyPlugin, { option1: "value1", option2: true });

Registration Order Matters

Plugins are installed in the order they are registered. If plugins depend on each other, register dependencies first:

// Logger should be registered before Analytics (Analytics uses Logger)
app.use(LoggerPlugin);
app.use(AnalyticsPlugin);  // Can now use app.log from LoggerPlugin

Accessing Plugin Features

After registration, plugin features are available on the Eleva instance:

// In your plugin
install(eleva, options) {
  eleva.myFeature = { /* ... */ };
}

// After registration
app.use(MyPlugin);
console.log(app.myFeature);  // Available immediately

// In components via the app instance
app.component("MyComponent", {
  setup: () => ({
    doSomething: () => app.myFeature.someMethod()
  }),
  template: (ctx) => `<button @click="doSomething">Click</button>`
});

Return Values

The app.use() method returns the result of plugin.install(). Use this for plugins that expose an API:

// Plugin that returns an API
const RouterPlugin = {
  name: "router",
  version: "1.0.0",
  install(eleva, options) {
    const router = new Router(eleva, options);
    eleva.router = router;
    return router;  // Return for direct access
  }
};

// Usage
const router = app.use(RouterPlugin, { mount: "#app", routes: [...] });
await router.start();
// The returned router instance provides direct API access

What Happens During Registration

  1. Eleva calls plugin.install(eleva, options)
  2. The plugin modifies the Eleva instance (adds methods, wraps existing methods, etc.)
  3. The plugin is stored internally (prevents duplicate registration)
  4. The return value of install() is returned to the caller

Plugin Cleanup (Uninstall)

Plugins can implement an optional uninstall() method for proper cleanup. This is recommended when your plugin wraps existing methods or adds properties to the Eleva instance.

Basic Cleanup Pattern

const MyPlugin = {
  name: "myPlugin",
  version: "1.0.0",

  install(eleva, options) {
    // Store original method for later restoration
    const originalMount = eleva.mount;
    eleva._myPlugin_originalMount = originalMount;

    // Wrap the method
    eleva.mount = function(...args) {
      console.log("Enhanced mount");
      return originalMount.call(this, ...args);
    };

    // Add new properties
    eleva.myFeature = { /* ... */ };
  },

  uninstall(eleva) {
    // Restore original method
    if (eleva._myPlugin_originalMount) {
      eleva.mount = eleva._myPlugin_originalMount;
      delete eleva._myPlugin_originalMount;
    }

    // Remove added properties
    delete eleva.myFeature;

    // Remove from plugin registry
    if (eleva.plugins) {
      eleva.plugins.delete(this.name);
    }
  }
};

// Usage
app.use(MyPlugin);

// Later, to uninstall:
MyPlugin.uninstall(app);

What to Clean Up

Resource Cleanup Action
Wrapped methods Restore to original functions
Added properties Delete from Eleva instance
Event listeners Remove all subscriptions
Timers/intervals Clear all timers
Plugin registry entry Remove from eleva.plugins Map (if you added metadata)

Uninstall Order (LIFO)

When multiple plugins wrap the same methods, uninstall in reverse order (Last In, First Out):

// Installation order
app.use(PluginA);  // Wraps mount first
app.use(PluginB);  // Wraps mount second

// Uninstall in reverse order
PluginB.uninstall(app);  // Uninstall last plugin first
PluginA.uninstall(app);  // Then earlier plugins

Note: See the Plugin System documentation for details on how plugin cleanup differs from component cleanup.


Next Steps


Learn from Official Plugins

Study how Eleva’s core plugins are built:

Plugin What You’ll Learn
Attr Plugin Attribute handling, configuration options (API)
Router Plugin Complex state management, navigation (Configuration · Guards)
Store Plugin Reactive state, persistence, namespacing (Patterns · Advanced)

See Also


← Back to Examples Development Guide →