-
Notifications
You must be signed in to change notification settings - Fork 2
Define RuntimePlugin interface and update protocol plugins for conformance #238
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
2daebbe
e4e7d84
96f61be
def23a7
8af15c0
3cc6c12
53276a0
bb4651c
402d787
efb4e92
37c9206
39e71de
c120d44
4b7d9c2
2ad8ce0
6f2aceb
fa451b4
baf4595
59d2e9b
151f5c8
f6e0263
5aee50a
e0be034
88f13ba
3577dfb
5f47876
d672491
98a79cd
e817770
c96726e
8ee0239
3990425
ceb33b4
2a6edbe
3fce480
d1a638e
98ee42e
e654b8e
c7d9471
5cbd979
1b6526e
d94fa24
e91d15a
ba06716
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| # RuntimePlugin Interface Implementation - Summary | ||
|
|
||
| ## Issue | ||
| The GraphQL, OData V4, and JSON-RPC protocol plugins were not formally implementing a standard `RuntimePlugin` interface, leading to architectural inconsistency issues. | ||
|
|
||
| ## Solution | ||
| We have successfully implemented the `RuntimePlugin` interface specification and updated all three protocol plugins to conform to it. | ||
|
|
||
| ## Changes Made | ||
|
|
||
| ### 1. RuntimePlugin Interface Definition (`@objectql/types`) | ||
|
|
||
| Created `/packages/foundation/types/src/plugin.ts` defining: | ||
|
|
||
| #### RuntimePlugin Interface | ||
| ```typescript | ||
| export interface RuntimePlugin { | ||
| name: string; | ||
| version?: string; | ||
| install?(ctx: RuntimeContext): void | Promise<void>; | ||
| onStart?(ctx: RuntimeContext): void | Promise<void>; | ||
| onStop?(ctx: RuntimeContext): void | Promise<void>; | ||
| } | ||
| ``` | ||
|
|
||
| #### RuntimeContext Interface | ||
| ```typescript | ||
| export interface RuntimeContext { | ||
| engine: any; | ||
| getKernel?: () => any; | ||
| } | ||
| ``` | ||
|
|
||
| ### 2. Protocol Plugin Updates | ||
|
|
||
| #### GraphQL Plugin (`@objectql/protocol-graphql`) | ||
| - ✅ Implements `RuntimePlugin` interface | ||
| - ✅ Removed dependency on `@objectstack/runtime` | ||
| - ✅ Added helper methods for metadata and CRUD operations | ||
| - ✅ Direct engine access via RuntimeContext | ||
|
|
||
| #### OData V4 Plugin (`@objectql/protocol-odata-v4`) | ||
| - ✅ Implements `RuntimePlugin` interface | ||
| - ✅ Removed dependency on `@objectstack/runtime` | ||
| - ✅ Added helper methods for metadata and CRUD operations | ||
| - ✅ Direct engine access via RuntimeContext | ||
|
|
||
| #### JSON-RPC Plugin (`@objectql/protocol-json-rpc`) | ||
| - ✅ Implements `RuntimePlugin` interface | ||
| - ✅ Removed dependency on `@objectstack/runtime` | ||
| - ✅ Added helper methods for metadata and CRUD operations | ||
| - ✅ Direct engine access via RuntimeContext | ||
|
|
||
| ### 3. Package Dependencies | ||
|
|
||
| Updated all three plugin `package.json` files to: | ||
| - Remove `@objectstack/runtime` dependency | ||
| - Use only `@objectql/types` for interface definitions | ||
|
|
||
| ### 4. Tests | ||
|
|
||
| Added comprehensive test suite in `/packages/foundation/types/test/plugin.test.ts`: | ||
| - RuntimePlugin interface conformance tests | ||
| - RuntimeContext functionality tests | ||
| - Lifecycle hook execution order tests | ||
| - Sync/async hook support tests | ||
|
|
||
| ### 5. Documentation | ||
|
|
||
| Updated `/packages/protocols/README.md`: | ||
| - Documented RuntimePlugin interface | ||
| - Documented RuntimeContext | ||
| - Updated plugin implementation pattern | ||
| - Added Engine API documentation | ||
| - Removed references to deprecated ObjectStackRuntimeProtocol | ||
|
|
||
| ## Architecture Compliance | ||
|
|
||
| ### ✅ Standard Lifecycle Hooks | ||
| All plugins now implement: | ||
| 1. **install(ctx)** - Called during kernel initialization | ||
| 2. **onStart(ctx)** - Called when kernel starts | ||
| 3. **onStop(ctx)** - Called when kernel stops | ||
|
|
||
| ### ✅ Consistent Interface | ||
| All plugins implement the same `RuntimePlugin` interface from `@objectql/types`, ensuring: | ||
| - Uniform plugin architecture | ||
| - Predictable lifecycle management | ||
| - Easy plugin discovery and validation | ||
| - Type-safe plugin development | ||
|
|
||
| ### ✅ Direct Engine Access | ||
| Plugins no longer depend on a separate protocol bridge layer. Instead: | ||
| - They access the kernel/engine directly via RuntimeContext | ||
| - They implement their own helper methods for common operations | ||
| - They maintain full control over their data access patterns | ||
|
|
||
| ## Impact | ||
|
|
||
| ### Architecture Consistency ✅ | ||
| - All protocol plugins follow the same interface | ||
| - Clear lifecycle management | ||
| - Consistent error handling | ||
|
|
||
| ### Plugin Extensibility ✅ | ||
| - Easy to add new protocol plugins | ||
| - Clear contract to implement | ||
| - Type-safe development | ||
|
|
||
| ### Maintenance Cost ✅ | ||
| - Reduced dependency on non-existent packages | ||
| - Simpler architecture | ||
| - Better testability | ||
|
|
||
| ## Testing Results | ||
|
|
||
| - ✅ RuntimePlugin interface tests pass | ||
| - ✅ Existing plugin lifecycle tests remain valid | ||
| - ✅ No breaking changes to plugin APIs | ||
| - ✅ TypeScript compilation successful (modulo external dependencies) | ||
|
|
||
| ## Next Steps | ||
|
|
||
| The implementation is complete and ready for use. Protocol plugins can now be: | ||
| 1. Instantiated with their configuration | ||
| 2. Passed to the kernel/runtime | ||
| 3. Initialized via the install hook | ||
| 4. Started via the onStart hook | ||
| 5. Stopped via the onStop hook | ||
|
|
||
| All three plugins (GraphQL, OData V4, JSON-RPC) are now fully compliant with the ObjectStack RuntimePlugin specification. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| /** | ||
| * ObjectQL Plugin System | ||
| * Copyright (c) 2026-present ObjectStack Inc. | ||
| * | ||
| * This source code is licensed under the MIT license found in the | ||
| * LICENSE file in the root directory of this source tree. | ||
| */ | ||
|
|
||
| /** | ||
| * Runtime context passed to plugin lifecycle hooks | ||
| * | ||
| * This context provides access to the kernel/engine instance | ||
| * and allows plugins to interact with the ObjectStack runtime. | ||
| */ | ||
| export interface RuntimeContext { | ||
| /** | ||
| * The ObjectStack kernel/engine instance | ||
| * | ||
| * This provides access to: | ||
| * - metadata registry | ||
| * - hook manager | ||
| * - action manager | ||
| * - CRUD operations | ||
| */ | ||
| engine: any; // Using 'any' to avoid circular dependency | ||
|
|
||
| /** | ||
| * Get the kernel instance (alternative accessor) | ||
| * Some implementations may use getKernel() instead of engine | ||
|
Comment on lines
+25
to
+29
|
||
| */ | ||
| getKernel?: () => any; | ||
| } | ||
|
|
||
| /** | ||
| * RuntimePlugin Interface | ||
| * | ||
| * Defines the standard plugin contract for ObjectStack/ObjectQL ecosystem. | ||
| * All plugins (protocol adapters, data drivers, feature extensions) should | ||
| * implement this interface to ensure consistent lifecycle management. | ||
| * | ||
| * Lifecycle Order: | ||
| * 1. install() - Called during kernel initialization | ||
| * 2. onStart() - Called when kernel starts | ||
| * 3. onStop() - Called when kernel stops/shuts down | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * export class MyPlugin implements RuntimePlugin { | ||
| * name = '@myorg/my-plugin'; | ||
| * version = '1.0.0'; | ||
| * | ||
| * async install(ctx: RuntimeContext): Promise<void> { | ||
| * // Register hooks, load configuration | ||
| * console.log('Plugin installed'); | ||
| * } | ||
| * | ||
| * async onStart(ctx: RuntimeContext): Promise<void> { | ||
| * // Start servers, connect to services | ||
| * console.log('Plugin started'); | ||
| * } | ||
| * | ||
| * async onStop(ctx: RuntimeContext): Promise<void> { | ||
| * // Cleanup resources, disconnect | ||
| * console.log('Plugin stopped'); | ||
| * } | ||
| * } | ||
| * ``` | ||
| */ | ||
| export interface RuntimePlugin { | ||
| /** | ||
| * Unique plugin identifier | ||
| * | ||
| * Should follow npm package naming convention | ||
| * Examples: '@objectql/plugin-security', '@myorg/my-plugin' | ||
| */ | ||
| name: string; | ||
|
|
||
| /** | ||
| * Plugin version (semantic versioning) | ||
| * | ||
| * Optional but recommended for debugging and compatibility tracking | ||
| * Example: '1.0.0', '2.1.3-beta' | ||
| */ | ||
| version?: string; | ||
|
|
||
| /** | ||
| * Install hook - called during kernel initialization | ||
| * | ||
| * Use this phase to: | ||
| * - Register hooks and event handlers | ||
| * - Initialize plugin state | ||
| * - Load configuration | ||
| * - Register metadata (objects, fields, actions) | ||
| * - Validate dependencies | ||
| * | ||
| * This is called BEFORE the kernel starts, so services may not be available yet. | ||
| * | ||
| * @param ctx - Runtime context with access to kernel/engine | ||
| */ | ||
| install?(ctx: RuntimeContext): void | Promise<void>; | ||
|
|
||
| /** | ||
| * Start hook - called when kernel starts | ||
| * | ||
| * Use this phase to: | ||
| * - Start background processes (servers, workers, schedulers) | ||
| * - Connect to external services (databases, APIs, message queues) | ||
| * - Initialize runtime resources | ||
| * - Perform health checks | ||
| * | ||
| * This is called AFTER install() and AFTER all plugins are installed. | ||
| * | ||
| * @param ctx - Runtime context with access to kernel/engine | ||
| */ | ||
| onStart?(ctx: RuntimeContext): void | Promise<void>; | ||
|
|
||
| /** | ||
| * Stop hook - called when kernel stops/shuts down | ||
| * | ||
| * Use this phase to: | ||
| * - Stop background processes | ||
| * - Disconnect from external services | ||
| * - Cleanup resources (file handles, connections, timers) | ||
| * - Flush pending operations | ||
| * - Save state if needed | ||
| * | ||
| * This is called during graceful shutdown. Ensure cleanup completes quickly. | ||
| * | ||
| * @param ctx - Runtime context with access to kernel/engine | ||
| */ | ||
| onStop?(ctx: RuntimeContext): void | Promise<void>; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RuntimeContextexposesengine: any(andgetKernelreturningany), which leaksanyinto every plugin and defeats the goal of type-safety. If you need to avoid circular deps, consider typingengineasunknown(narrowed by guards) or exporting a minimalRuntimeEngineinterface from@objectql/types(metadata + CRUD surface) instead ofany.