This document summarizes the implementation of @objectstack/runtime, the micro-kernel architecture for ObjectStack that enables plugin-based extensibility.
✅ Implement plugin loading and service startup using @objectstack/runtime
✅ Follow the micro-kernel architecture pattern from https://protocol.objectstack.ai/docs/developers/micro-kernel
✅ Enable dependency injection and event-driven communication
✅ Provide a clean separation between core functionality and business logic
The implementation follows the micro-kernel architectural pattern where:
- Core Kernel (
ObjectKernel) provides minimal essential services - Plugins implement all business functionality
- Service Registry enables dependency injection
- Event Bus enables inter-plugin communication
- Dependency Resolver ensures correct initialization order
┌─────────────────────────────────────────────────────────┐
│ ObjectKernel (Core Runtime) │
│ • Plugin Lifecycle Manager │
│ • Service Registry (DI Container) │
│ • Event Bus (Hook System) │
│ • Dependency Resolver │
└──────────────┬──────────────────────────────────────────┘
│
┌───────┴────────┬────────────┬──────────┐
│ │ │ │
┌────▼─────┐ ┌─────▼─────┐ ┌──▼───┐ ┌───▼────┐
│ ObjectQL │ │ Driver │ │Server│ │ Custom │
│ Plugin │ │ Plugin │ │Plugin│ │ Plugin │
└──────────┘ └───────────┘ └──────┘ └────────┘
Defines the fundamental interfaces:
-
Plugin: Interface all plugins must implementname: Unique plugin identifierversion?: Optional versiondependencies?: Array of plugin dependenciesinit?(): Registration phasestart?(): Startup phasedestroy?(): Cleanup phase
-
PluginContext: Provides access to kernel services- Service registry methods
- Event bus methods
- Logger instance
-
Logger: Logging interface
The core kernel implementation:
Key Features:
- Plugin registration via
use()method (chainable) - Dependency resolution using topological sort
- Circular dependency detection
- Lifecycle management (init → start → destroy)
- Service registry access
- Event system integration
Public API:
class ObjectKernel {
use(plugin: Plugin): this;
bootstrap(): Promise<void>;
shutdown(): Promise<void>;
getService<T>(name: string): T;
hasService(name: string): boolean;
}Implementation of the plugin context:
Features:
- Service registration and retrieval
- Event hook registration
- Event triggering
- Logger access
Public API:
class PluginContextImpl implements PluginContext {
registerService(name: string, service: any): void;
getService<T>(name: string): T;
hasService(name: string): boolean;
hook(name: string, handler: Function): void;
trigger(name: string, ...args: any[]): Promise<void>;
}Registers ObjectQL as a service in the kernel.
Features:
- Accepts optional custom ObjectQL instance
- Initializes ObjectQL on start
- Registers service as
'objectql'
Usage:
kernel.use(new ObjectQLPlugin());
// or
kernel.use(new ObjectQLPlugin(customQL));Registers database drivers with ObjectQL.
Features:
- Depends on ObjectQLPlugin
- Auto-connects driver on start
- Auto-disconnects on destroy
- Configurable driver name
Usage:
kernel.use(new DriverPlugin(driver, 'postgres'));Simple console-based logger implementation.
Features:
- Debug, Info, Warn, Error levels
- Prefix support for component identification
- Timestamp formatting
-
Registration (
kernel.use())kernel.use(new ObjectQLPlugin()) .use(new DriverPlugin(driver, 'default'));
-
Initialization (
kernel.bootstrap())- Resolves dependencies (topological sort)
- Calls
init()on each plugin in order - Plugins register services and subscribe to events
-
Start
- Calls
start()on each plugin - Plugins connect to databases, start servers, etc.
- Calls
-
Running
- Application is operational
- Services accessible via
kernel.getService()
-
Shutdown (
kernel.shutdown())- Calls
destroy()in reverse order - Cleanup and resource release
- Calls
// 1. Create kernel
const kernel = new ObjectKernel();
// 2. Register plugins
kernel.use(new ObjectQLPlugin())
.use(new DriverPlugin(driver, 'default'));
// 3. Bootstrap (init + start all plugins)
await kernel.bootstrap();
// 4. Use services
const ql = kernel.getService('objectql');
// 5. Shutdown
await kernel.shutdown();The server integration was updated to use the runtime:
Before (Direct instantiation):
const objectos = new ObjectOS({
datasources: { default: driver },
presets: ['@objectos/preset-base']
});
await objectos.init();After (Using ObjectKernel):
const kernel = new ObjectKernel();
const objectos = new ObjectOS({ presets });
kernel.use(new ObjectQLPlugin(objectos))
.use(new DriverPlugin(driver, 'default'));
await kernel.bootstrap();
const ql = kernel.getService('objectql');- 19 tests covering all functionality
- 2 test suites (kernel.test.ts, plugins.test.ts)
- 100% pass rate
-
Plugin Registration
- Register plugins
- Chain registration
- Duplicate prevention
-
Plugin Lifecycle
- Init/start/destroy hooks
- Hook execution order
-
Service Registry
- Register and retrieve services
- Service not found errors
-
Event System
- Hook registration
- Event triggering
- Multiple handlers
-
Dependency Resolution
- Correct initialization order
- Circular dependency detection
- Missing dependency errors
-
Built-in Plugins
- ObjectQLPlugin service registration
- DriverPlugin dependency handling
- Driver connect/disconnect
- Clear separation of concerns
- Easy to add/remove features
- Independent plugin development
- Mock services easily
- Test plugins in isolation
- Integration testing with real kernel
- Add new plugins without modifying core
- Plugin marketplace potential
- Third-party plugin support
- Automatic ordering
- Clear dependency declarations
- Circular dependency prevention
- Full TypeScript support
- Compile-time error detection
- IDE autocomplete
import { ObjectKernel, ObjectQLPlugin, DriverPlugin } from '@objectstack/runtime';
import { KnexDriver } from '@objectql/driver-sql';
const kernel = new ObjectKernel();
const driver = new KnexDriver({
client: 'sqlite3',
connection: { filename: ':memory:' },
useNullAsDefault: true
});
kernel.use(new ObjectQLPlugin())
.use(new DriverPlugin(driver, 'default'));
await kernel.bootstrap();
const ql = kernel.getService('objectql');
// Use ObjectQL...
await kernel.shutdown();import { Plugin, PluginContext } from '@objectstack/runtime';
class MyPlugin implements Plugin {
name = 'com.mycompany.my-plugin';
dependencies = ['com.objectstack.engine.objectql'];
async init(ctx: PluginContext): Promise<void> {
// Register services
ctx.registerService('my-service', { /* ... */ });
// Subscribe to events
ctx.hook('kernel:ready', async () => {
ctx.logger.info('Ready!');
});
}
async start(ctx: PluginContext): Promise<void> {
const ql = ctx.getService('objectql');
// Use other services...
}
}
kernel.use(new MyPlugin());- README.md - Package overview and quick start
- USAGE_EXAMPLE.md - Detailed examples and patterns
- Main README - Updated with architecture diagram
The implementation fully complies with the micro-kernel architecture specification at: https://protocol.objectstack.ai/docs/developers/micro-kernel
✅ ObjectKernel with plugin lifecycle manager
✅ Service Registry (DI Container)
✅ Event Bus (Hook System)
✅ Dependency Resolver
✅ Plugin Interface (name, version, dependencies, init, start, destroy)
✅ PluginContext (registerService, getService, hook, trigger, logger)
✅ ObjectQLPlugin
✅ DriverPlugin
✅ Standard events (kernel:init, kernel:ready, kernel:shutdown)
packages/runtime/
├── src/
│ ├── index.ts # Main exports
│ ├── types.ts # Core type definitions
│ ├── kernel.ts # ObjectKernel implementation
│ ├── plugin-context.ts # PluginContext implementation
│ ├── logger.ts # Logger implementation
│ └── plugins/
│ ├── objectql-plugin.ts # ObjectQL plugin
│ └── driver-plugin.ts # Driver plugin
├── test/
│ ├── kernel.test.ts # Kernel tests
│ └── plugins.test.ts # Plugin tests
├── package.json # Package configuration
├── tsconfig.json # TypeScript configuration
├── jest.config.js # Jest configuration
├── README.md # Package documentation
└── USAGE_EXAMPLE.md # Usage examples
-
Additional Plugins
- HonoServerPlugin for HTTP server
- WorkflowPlugin for business processes
- CachePlugin for caching layer
-
Plugin Configuration
- Load plugins from config files
- Dynamic plugin discovery
- Plugin hot-reload in development
-
Advanced Features
- Plugin versioning and compatibility
- Plugin marketplace
- Plugin sandboxing
-
Performance
- Lazy plugin loading
- Parallel plugin initialization
- Resource pooling
The @objectstack/runtime implementation provides a solid foundation for building extensible, modular applications following the micro-kernel architecture pattern. It enables:
- Clean separation of concerns
- Easy testing and maintainability
- Flexible extensibility through plugins
- Type-safe development
- Protocol compliance
All functionality has been tested and verified to work correctly with the existing ObjectOS server infrastructure.