Plugins
Creating a Plugin
Build your own Universal Data Layer plugin
Creating Your First Plugin
Creating a UDL plugin is straightforward. A plugin is essentially a package with a udl.config.js file that defines its configuration and behavior.
Plugin Structure
At minimum, a plugin needs:
my-plugin/
├── package.json
├── udl.config.js
└── ... (your plugin code)
Basic Plugin Configuration
Create a udl.config.js file at the root of your plugin:
udl.config.js
export const config = {
type: 'source', // Plugin type: 'source' or 'core'
name: 'my-plugin', // Plugin name
version: '1.0.0', // Plugin version
};
export function onLoad({ options, config }) {
console.log('My plugin loaded!');
console.log('Options:', options);
console.log('App config:', config);
}
Plugin Types
Source Plugin
Source plugins connect to external data sources:
udl.config.js
export const config = {
type: 'source',
name: 'my-data-source',
version: '1.0.0',
};
export function onLoad({ options, config }) {
// Initialize your data source connection
const apiKey = options?.apiKey;
const spaceId = options?.spaceId;
console.log(`Connecting to data source with space: ${spaceId}`);
// Set up data fetching logic, GraphQL schema extensions, etc.
}
The onLoad Hook
The onLoad function is your plugin's initialization point. It receives a context object with:
Context Properties
options (object)
Plugin-specific options passed during registration:
udl.config.js
export function onLoad({ options }) {
const {
apiKey,
environment,
customSetting,
} = options || {};
// Use options to configure your plugin
}
config (object)
The application's UDL configuration:
udl.config.js
export function onLoad({ config }) {
const { port, host, endpoint } = config;
// Access app-level configuration
console.log(`Server will run on ${host}:${port}`);
}
Plugin Best Practices
1. Validate Options
Always validate required options in your onLoad hook:
udl.config.js
export function onLoad({ options }) {
if (!options?.apiKey) {
throw new Error('apiKey is required for my-plugin');
}
if (!options?.spaceId) {
throw new Error('spaceId is required for my-plugin');
}
}
2. Handle Errors Gracefully
Wrap initialization logic in try-catch blocks:
udl.config.js
export async function onLoad({ options }) {
try {
await initializeClient(options);
console.log('Plugin initialized successfully');
} catch (error) {
console.error('Failed to initialize plugin:', error);
throw error;
}
}
3. Use Async/Await
The onLoad hook supports async operations:
udl.config.js
export async function onLoad({ options }) {
// Async initialization
await setupDatabase(options);
await loadSchemaExtensions();
console.log('Async initialization complete');
}
4. Export Type Definitions (TypeScript)
If using TypeScript, export your types:
export interface MyPluginOptions {
apiKey: string;
environment?: 'production' | 'staging';
}
import type { MyPluginOptions } from './types';
export const config = {
type: 'source',
name: 'my-plugin',
version: '1.0.0',
};
export function onLoad({ options }: { options?: MyPluginOptions }) {
const { apiKey, environment = 'production' } = options || {};
// ...
}
Publishing Your Plugin
As an npm Package
- Add UDL as a peer dependency:
package.json
{
"name": "udl-plugin-myservice",
"version": "1.0.0",
"peerDependencies": {
"universal-data-layer": "^0.0.1"
}
}
- Ensure
udl.config.jsis included in published files:
package.json
{
"files": [
"dist",
"udl.config.js"
]
}
- Publish to npm:
Terminal
npm publish
As a Local Plugin
You can also use plugins locally without publishing:
udl.config.js
export const config = {
plugins: [
'./local-plugins/my-plugin', // Relative path
],
};
Next Steps
- Registering Plugins - Learn how to use your plugin
- Lifecycle Methods - Advanced lifecycle hooks