Lifecycle Methods
Plugin Lifecycle
The Universal Data Layer plugin system provides lifecycle hooks that allow plugins to execute code at specific points during the application's initialization and runtime.
Available Lifecycle Hooks
Currently, UDL provides one main lifecycle hook:
onLoad
The onLoad hook is called when a plugin is loaded and initialized. This is where you perform setup, initialize connections, and configure your plugin.
export function onLoad({ options, config }) {
// Plugin initialization code
}
The onLoad Hook
When It's Called
The onLoad hook is executed:
- After the application's
udl.config.jsis loaded - For each plugin in the
pluginsarray, in order - Before the GraphQL server starts
Execution Flow
1. Load app config (udl.config.js)
↓
2. Execute app's onLoad hook (if defined)
↓
3. For each plugin:
- Resolve plugin path
- Load plugin's udl.config.js
- Execute plugin's onLoad hook
↓
4. Start GraphQL server
Context Object
The onLoad hook receives a context object with two properties:
options
Plugin-specific configuration passed during registration:
export const config = {
plugins: [
{
name: 'my-plugin',
options: {
apiKey: 'secret',
timeout: 5000,
},
},
],
};
// Plugin's onLoad receives these options
export function onLoad({ options }) {
console.log(options.apiKey); // 'secret'
console.log(options.timeout); // 5000
}
config
The entire application configuration:
export const config = {
port: 4000,
host: 'localhost',
endpoint: 'http://localhost:4000/graphql',
plugins: ['my-plugin'],
};
// Plugin's onLoad receives the full config
export function onLoad({ config }) {
console.log(config.port); // 4000
console.log(config.host); // 'localhost'
console.log(config.endpoint); // 'http://localhost:4000/graphql'
}
Async Lifecycle Hooks
The onLoad hook supports async operations. UDL will wait for the promise to resolve before continuing:
export async function onLoad({ options }) {
// Async initialization
await connectToDatabase(options.connectionString);
await loadDataSchema();
await warmupCache();
console.log('Plugin fully initialized');
}
Error Handling
Throwing Errors
If a plugin's onLoad fails, it should throw an error:
export function onLoad({ options }) {
if (!options?.apiKey) {
throw new Error('API key is required');
}
if (!validateApiKey(options.apiKey)) {
throw new Error('Invalid API key format');
}
}
Graceful Degradation
For non-critical failures, log warnings instead:
export async function onLoad({ options }) {
try {
await warmupCache();
} catch (error) {
console.warn('Cache warmup failed, continuing anyway:', error);
}
}
Async Error Handling
Handle async errors properly:
export async function onLoad({ options }) {
try {
await initializeService(options);
} catch (error) {
console.error('Failed to initialize service:', error);
throw new Error(`Plugin initialization failed: ${error.message}`);
}
}
Best Practices
1. Validate Required Options Early
export function onLoad({ options }) {
const required = ['apiKey', 'secretKey', 'endpoint'];
for (const key of required) {
if (!options?.[key]) {
throw new Error(`Missing required option: ${key}`);
}
}
// Continue with initialization
}
2. Use Async/Await for I/O Operations
export async function onLoad({ options }) {
await Promise.all([
connectToDatabase(options),
loadRemoteSchema(options),
initializeCache(options),
]);
}
3. Provide Detailed Logging
export async function onLoad({ options }) {
console.log(`[${config.name}] Initializing...`);
await setupClient(options);
console.log(`[${config.name}] Client configured`);
await loadSchema();
console.log(`[${config.name}] Schema loaded`);
console.log(`[${config.name}] Ready`);
}
4. Export Utility Functions
Make plugin functionality accessible:
let client;
export async function onLoad({ options }) {
client = await createClient(options);
}
// Export for use by other plugins or app code
export function getClient() {
return client;
}
export async function query(query) {
return client.query(query);
}
Next Steps
- Plugin Overview - Understanding the plugin system
- Creating a Plugin - Build your own plugin
- Registering Plugins - Configure plugins in your app