Plugin System
Plugin System
Plugins are the primary way to extend ObjectQL. They allow you to bundle behavior, schema modifications, and logic (hooks/actions) into reusable units.
1. Anatomy of a Plugin
A plugin is simply an object that implements the ObjectQLPlugin interface.
2. Execution Lifecycle
Understanding valid execution timing is critical.
-
Phase 1: Construction (
new ObjectQL)- Load Metadata from
packages. - Load Metadata from
sourcedirectories (*.object.yml). - Load Metadata from
config.objects. - Result:
app.metadataholds all static definitions.
- Load Metadata from
-
Phase 2: Initialization (
await app.init())- Step A: Remotes: Fetch metadata from remote services.
- Step B: Plugins (
plugin.setup): <-- YOU ARE HERE- This is the last chance to modify metadata before it touches the DB.
- You can access all objects loaded in Phase 1 & Step A.
- Step C: Drivers: Drivers connect and synchronize schema (create tables, etc.).
3. Creating Plugins
You can define plugins in two styles: Object or Class.
Option A: Object Style (Simpler)
Useful for stateless, simple logic or one-off modifications.
Option B: Class Style (Recommended)
Useful when your plugin needs to maintain internal state, configuration, or complex initialization logic.
3. Loading Plugins
Plugins are passed to the ObjectQL constructor via the plugins array. The loader is very flexible.
Method 1: Inline Instance
Pass the plugin object or class instance directly.
Method 2: NPM Package (String)
You can specify the package name as a string. ObjectQL uses require() (Node.js) to resolve it.
Package Resolution Rules
When loading from a string, ObjectQL tries to find the plugin in the exported module in this order:
- Class Constructor: If the module exports a Class (default or module.exports), it tries to instantiation it (
new Plugin()). - Plugin Object: If the module exports an object with a
setupfunction, it uses it directly. - Default Export: If the module has a
defaultexport, it checks that recursively.
Example Package (node_modules/my-plugin/index.js):
4. What can Plugins do?
The setup(app) method gives you full access to the ObjectQL instance.
A. Manipulate Metadata (Schema)
Plugins have full control over the schema. You can modify existing objects or register new ones.
Example 1: Injecting a global field
Example 2: Registering a new Object Plugins can bundle their own data models (e.g. an audit log table).
Example 3: Scanning a Directory Plugins can also scan a directory to load metadata files, just like the main application. This is useful for bundling a set of objects.
B. Register Global Hooks
Listen to lifecycle events on specific objects or * (wildcard).
C. Register Custom Actions
Add new capabilities to objects.
D. Custom Metadata Loaders
Plugins can register new loaders to scan for custom file types (e.g. *.workflow.yml). This allows ObjectQL to act as a unified metadata engine.
E. Manage Modules
Plugins can dynamically load or unload other modules. This is useful for plugins that act as "features" which bring in a set of dependencies.
5. Scope Isolation
When a plugin is loaded via Package Name (Method 2), ObjectQL automatically marks the hooks and actions registered by that plugin with its package name.
This allows app.removePackage('@objectql/plugin-auth') to cleanly remove all hooks and actions associated with that plugin, without affecting others.