@objectstack/runtime 0.4.2 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # @objectstack/runtime
2
2
 
3
+ ## 0.6.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Patch release for maintenance and stability improvements
8
+ - Updated dependencies
9
+ - @objectstack/spec@0.6.1
10
+ - @objectstack/types@0.6.1
11
+ - @objectstack/core@0.6.1
12
+
13
+ ## 0.6.0
14
+
15
+ ### Minor Changes
16
+
17
+ - b2df5f7: Unified version bump to 0.5.0
18
+
19
+ - Standardized all package versions to 0.5.0 across the monorepo
20
+ - Fixed driver-memory package.json paths for proper module resolution
21
+ - Ensured all packages are in sync for the 0.5.0 release
22
+
23
+ ### Patch Changes
24
+
25
+ - Updated dependencies [b2df5f7]
26
+ - @objectstack/spec@0.6.0
27
+ - @objectstack/objectql@0.6.0
28
+ - @objectstack/types@0.6.0
29
+ - @objectstack/core@0.6.0
30
+
3
31
  ## 0.4.2
4
32
 
5
33
  ### Patch Changes
package/README.md CHANGED
@@ -1,10 +1,16 @@
1
1
  # @objectstack/runtime
2
2
 
3
- ObjectStack Core Runtime & Query Engine
3
+ ObjectStack Standard System Library
4
4
 
5
5
  ## Overview
6
6
 
7
- The runtime package provides the `ObjectStackKernel` - the central orchestrator for ObjectStack applications. It manages the application lifecycle, plugins, and the ObjectQL data engine.
7
+ The runtime package provides the **Standard Library** for the ObjectStack Operating System. It bridges the pure **ObjectKernel** (from `@objectstack/core`) with the **Data Engine** (`@objectstack/objectql`) and provides essential infrastructure adapters.
8
+
9
+ ### Architecture Highlights
10
+
11
+ - **Standard Library**: Contains essential plugins (`AppPlugin`, `DriverPlugin`)
12
+ - **Core Integration**: Re-exports `ObjectKernel` for convenience
13
+ - **Capability Contracts**: Abstract interfaces for HTTP server and data persistence
8
14
 
9
15
  ## Installation
10
16
 
@@ -12,26 +18,29 @@ The runtime package provides the `ObjectStackKernel` - the central orchestrator
12
18
  npm install @objectstack/runtime
13
19
  ```
14
20
 
15
- ## Usage
21
+ ## Quick Start
16
22
 
17
- ### Basic Setup
23
+ ### Basic Setup (Recommended)
18
24
 
19
25
  ```typescript
20
- import { ObjectStackKernel, ObjectQLPlugin } from '@objectstack/runtime';
26
+ import { ObjectKernel } from '@objectstack/core';
27
+ import { DriverPlugin, AppPlugin } from '@objectstack/runtime';
28
+ import { ObjectQLPlugin } from '@objectstack/objectql';
21
29
  import { InMemoryDriver } from '@objectstack/driver-memory';
22
30
 
23
- const kernel = new ObjectStackKernel([
31
+ const kernel = new ObjectKernel();
32
+
33
+ kernel
24
34
  // Register ObjectQL engine
25
- new ObjectQLPlugin(),
35
+ .use(new ObjectQLPlugin())
26
36
 
27
37
  // Add database driver
28
- new InMemoryDriver(),
38
+ .use(new DriverPlugin(new InMemoryDriver(), 'memory'))
29
39
 
30
40
  // Add your app configurations
31
- // appConfig,
32
- ]);
41
+ // .use(new AppPlugin(appConfig));
33
42
 
34
- await kernel.start();
43
+ await kernel.bootstrap();
35
44
  ```
36
45
 
37
46
  ### Custom ObjectQL Instance
@@ -39,7 +48,8 @@ await kernel.start();
39
48
  If you have a separate ObjectQL implementation or need custom configuration:
40
49
 
41
50
  ```typescript
42
- import { ObjectStackKernel, ObjectQLPlugin, ObjectQL } from '@objectstack/runtime';
51
+ import { ObjectKernel, DriverPlugin } from '@objectstack/runtime';
52
+ import { ObjectQLPlugin, ObjectQL } from '@objectstack/objectql';
43
53
 
44
54
  // Create custom ObjectQL instance
45
55
  const customQL = new ObjectQL({
@@ -52,111 +62,218 @@ customQL.registerHook('beforeInsert', async (ctx) => {
52
62
  console.log(`Inserting into ${ctx.object}`);
53
63
  });
54
64
 
55
- const kernel = new ObjectStackKernel([
65
+ const kernel = new ObjectKernel();
66
+
67
+ kernel
56
68
  // Use your custom ObjectQL instance
57
- new ObjectQLPlugin(customQL),
69
+ .use(new ObjectQLPlugin(customQL))
58
70
 
59
- // ... other plugins
60
- ]);
71
+ // Add driver
72
+ .use(new DriverPlugin(new InMemoryDriver(), 'memory'));
73
+
74
+ await kernel.bootstrap();
61
75
 
62
- await kernel.start();
76
+ // Access ObjectQL via service registry
77
+ const objectql = kernel.getService('objectql');
63
78
  ```
64
79
 
65
- ### Backward Compatibility
80
+ ## Architecture
81
+
82
+ ### ObjectKernel (MiniKernel)
83
+
84
+ The kernel provides:
85
+ - **Plugin Lifecycle Management**: init → start → destroy phases
86
+ - **Service Registry**: Dependency injection container
87
+ - **Event/Hook System**: Inter-plugin communication
88
+ - **Dependency Resolution**: Topological sort for plugin dependencies
89
+
90
+ ### Built-in Plugins
66
91
 
67
- For backward compatibility, the kernel will automatically initialize ObjectQL if no `ObjectQLPlugin` is provided:
92
+ #### ObjectQLPlugin
93
+ Registers the ObjectQL data engine as a service.
68
94
 
69
95
  ```typescript
70
- // This still works, but will show a deprecation warning
71
- const kernel = new ObjectStackKernel([
72
- new InMemoryDriver(),
73
- // ... other plugins
74
- ]);
96
+ new ObjectQLPlugin() // Default instance
97
+ new ObjectQLPlugin(customQL) // Custom instance
98
+ new ObjectQLPlugin(undefined, { env: 'prod' }) // With context
75
99
  ```
76
100
 
77
- ## Architecture
101
+ **Services**: `'objectql'`
78
102
 
79
- ### ObjectStackKernel
103
+ #### DriverPlugin
104
+ Registers a data driver with ObjectQL.
80
105
 
81
- The kernel is responsible for:
82
- - Orchestrating application lifecycle
83
- - Managing plugins
84
- - Coordinating the ObjectQL engine
85
- - Handling data operations
106
+ ```typescript
107
+ new DriverPlugin(driver, 'driver-name')
108
+ ```
86
109
 
87
- ### ObjectQLPlugin
110
+ **Dependencies**: `['com.objectstack.engine.objectql']`
88
111
 
89
- The `ObjectQLPlugin` provides:
90
- - Explicit ObjectQL engine registration
91
- - Support for custom ObjectQL instances
92
- - Clean separation of concerns
93
- - Better testability
112
+ #### AppPlugin
113
+ Wraps ObjectStack app manifests (objectstack.config.ts) as plugins.
114
+
115
+ ```typescript
116
+ new AppPlugin(appConfig)
117
+ ```
118
+
119
+ **Services**: `'app.{id}'`
94
120
 
95
121
  ## API Reference
96
122
 
97
- ### ObjectStackKernel
123
+ ### Capability Contract Interfaces
124
+
125
+ #### IHttpServer
126
+
127
+ Abstract interface for HTTP server capabilities. Allows plugins to work with any HTTP framework (Express, Fastify, Hono, etc.) without tight coupling.
98
128
 
99
- #### Constructor
100
129
  ```typescript
101
- constructor(plugins: any[] = [])
130
+ import { IHttpServer, IHttpRequest, IHttpResponse } from '@objectstack/runtime';
131
+
132
+ // In your HTTP server plugin
133
+ class MyHttpServerPlugin implements Plugin {
134
+ name = 'http-server';
135
+
136
+ async init(ctx: PluginContext) {
137
+ const server: IHttpServer = createMyServer(); // Express, Hono, etc.
138
+ ctx.registerService('http-server', server);
139
+ }
140
+ }
141
+
142
+ // In your API plugin
143
+ class MyApiPlugin implements Plugin {
144
+ name = 'api';
145
+ dependencies = ['http-server'];
146
+
147
+ async start(ctx: PluginContext) {
148
+ const server = ctx.getService<IHttpServer>('http-server');
149
+
150
+ // Register routes - works with any HTTP framework
151
+ server.get('/api/users', async (req, res) => {
152
+ res.json({ users: [] });
153
+ });
154
+ }
155
+ }
102
156
  ```
103
157
 
158
+ **Interface Methods:**
159
+ - `get(path, handler)` - Register GET route
160
+ - `post(path, handler)` - Register POST route
161
+ - `put(path, handler)` - Register PUT route
162
+ - `delete(path, handler)` - Register DELETE route
163
+ - `patch(path, handler)` - Register PATCH route
164
+ - `use(path, handler?)` - Register middleware
165
+ - `listen(port)` - Start server
166
+ - `close()` - Stop server (optional)
167
+
168
+ #### IDataEngine
169
+
170
+ Abstract interface for data persistence. Allows plugins to work with any data layer (ObjectQL, Prisma, TypeORM, etc.) without tight coupling.
171
+
172
+ ```typescript
173
+ import { IDataEngine } from '@objectstack/runtime';
174
+
175
+ // In your data plugin
176
+ class MyDataPlugin implements Plugin {
177
+ name = 'data';
178
+
179
+ async init(ctx: PluginContext) {
180
+ const engine: IDataEngine = createMyDataEngine(); // ObjectQL, Prisma, etc.
181
+ ctx.registerService('data-engine', engine);
182
+ }
183
+ }
184
+
185
+ // In your business logic plugin
186
+ class MyBusinessPlugin implements Plugin {
187
+ name = 'business';
188
+ dependencies = ['data'];
189
+
190
+ async start(ctx: PluginContext) {
191
+ const engine = ctx.getService<IDataEngine>('data-engine');
192
+
193
+ // CRUD operations - works with any data layer
194
+ const user = await engine.insert('user', { name: 'John' });
195
+ const users = await engine.find('user', { filter: { active: true } });
196
+ await engine.update('user', user.id, { name: 'Jane' });
197
+ await engine.delete('user', user.id);
198
+ }
199
+ }
200
+ ```
201
+
202
+ **Interface Methods:**
203
+ - `insert(objectName, data)` - Create a record
204
+ - `find(objectName, query?)` - Query records
205
+ - `update(objectName, id, data)` - Update a record
206
+ - `delete(objectName, id)` - Delete a record
207
+
208
+ ### ObjectKernel
209
+
104
210
  #### Methods
105
- - `start()`: Initialize and start the kernel
106
- - `find(objectName, query)`: Query data
107
- - `get(objectName, id)`: Get single record
108
- - `create(objectName, data)`: Create record
109
- - `update(objectName, id, data)`: Update record
110
- - `delete(objectName, id)`: Delete record
111
- - `getMetadata(objectName)`: Get object metadata
112
- - `getView(objectName, viewType)`: Get UI view definition
113
-
114
- ### ObjectQLPlugin
115
-
116
- #### Constructor
211
+ - `use(plugin: Plugin)`: Register a plugin
212
+ - `bootstrap()`: Initialize and start all plugins
213
+ - `shutdown()`: Stop all plugins in reverse order
214
+ - `getService<T>(name: string)`: Get a service from registry
215
+ - `isRunning()`: Check if kernel is running
216
+ - `getState()`: Get current kernel state
217
+
218
+ ### Plugin Interface
219
+
117
220
  ```typescript
118
- constructor(ql?: ObjectQL, hostContext?: Record<string, any>)
221
+ interface Plugin {
222
+ name: string; // Unique identifier
223
+ version?: string; // Plugin version
224
+ dependencies?: string[]; // Required plugin names
225
+
226
+ init(ctx: PluginContext): Promise<void>; // Register services
227
+ start?(ctx: PluginContext): Promise<void>; // Execute business logic
228
+ destroy?(): Promise<void>; // Cleanup
229
+ }
119
230
  ```
120
231
 
121
- #### Parameters
122
- - `ql` (optional): Custom ObjectQL instance
123
- - `hostContext` (optional): Host context configuration
232
+ ### PluginContext
233
+
234
+ ```typescript
235
+ interface PluginContext {
236
+ registerService(name: string, service: any): void;
237
+ getService<T>(name: string): T;
238
+ hook(name: string, handler: Function): void;
239
+ trigger(name: string, ...args: any[]): Promise<void>;
240
+ logger: Console;
241
+ getKernel?(): any;
242
+ }
243
+ ```
124
244
 
125
245
  ## Examples
126
246
 
127
247
  See the `examples/` directory for complete examples:
128
248
  - `examples/host/` - Full server setup with Hono
129
249
  - `examples/msw-react-crud/` - Browser-based setup with MSW
130
- - `examples/custom-objectql-example.ts` - Custom ObjectQL instance
250
+ - `test-mini-kernel.ts` - Comprehensive kernel test suite
251
+ - `packages/runtime/src/
131
252
 
132
- ## Migration Guide
253
+ ## Benefits of MiniKernel
133
254
 
134
- ### From Hardcoded ObjectQL to Plugin-Based
255
+ 1. **True Modularity**: Each plugin is independent and reusable
256
+ 2. **Capability Contracts**: Plugins depend on interfaces, not implementations
257
+ 3. **Testability**: Mock services easily in tests
258
+ 4. **Flexibility**: Load plugins conditionally, swap implementations
259
+ 5. **Extensibility**: Add new plugins without modifying kernel
260
+ 6. **Clear Dependencies**: Explicit dependency declarations
261
+ 7. **Better Architecture**: Separation of concerns with Dependency Inversion
135
262
 
136
- **Before:**
137
- ```typescript
138
- const kernel = new ObjectStackKernel([appConfig, driver]);
139
- ```
263
+ ## Best Practices
140
264
 
141
- **After (Recommended):**
142
- ```typescript
143
- const kernel = new ObjectStackKernel([
144
- new ObjectQLPlugin(),
145
- appConfig,
146
- driver
147
- ]);
148
- ```
265
+ 1. **Keep plugins focused**: One responsibility per plugin
266
+ 2. **Use services**: Share functionality via service registry
267
+ 3. **Declare dependencies**: Make plugin requirements explicit
268
+ 4. **Use hooks**: Decouple plugins with event system
269
+ 5. **Handle errors**: Implement proper error handling in lifecycle methods
149
270
 
150
- **After (Custom Instance):**
151
- ```typescript
152
- const customQL = new ObjectQL({ /* config */ });
153
- const kernel = new ObjectStackKernel([
154
- new ObjectQLPlugin(customQL),
155
- appConfig,
156
- driver
157
- ]);
158
- ```
271
+ ## Documentation
272
+
273
+ - [MiniKernel Guide](../../MINI_KERNEL_GUIDE.md) - Complete API documentation and patterns
274
+ - [MiniKernel Architecture](../../MINI_KERNEL_ARCHITECTURE.md) - Architecture diagrams and flows
275
+ - [MiniKernel Implementation](../../MINI_KERNEL_IMPLEMENTATION.md) - Implementation details
159
276
 
160
277
  ## License
161
278
 
162
- MIT
279
+ Apache-2.0
@@ -0,0 +1,18 @@
1
+ import { Plugin, PluginContext } from '@objectstack/core';
2
+ /**
3
+ * AppPlugin
4
+ *
5
+ * Adapts a generic App Bundle (Manifest + Runtime Code) into a Kernel Plugin.
6
+ *
7
+ * Responsibilities:
8
+ * 1. Register App Manifest as a service (for ObjectQL discovery)
9
+ * 2. Execute Runtime `onEnable` hook (for code logic)
10
+ */
11
+ export declare class AppPlugin implements Plugin {
12
+ name: string;
13
+ version?: string;
14
+ private bundle;
15
+ constructor(bundle: any);
16
+ init(ctx: PluginContext): Promise<void>;
17
+ start(ctx: PluginContext): Promise<void>;
18
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * AppPlugin
3
+ *
4
+ * Adapts a generic App Bundle (Manifest + Runtime Code) into a Kernel Plugin.
5
+ *
6
+ * Responsibilities:
7
+ * 1. Register App Manifest as a service (for ObjectQL discovery)
8
+ * 2. Execute Runtime `onEnable` hook (for code logic)
9
+ */
10
+ export class AppPlugin {
11
+ constructor(bundle) {
12
+ this.bundle = bundle;
13
+ // Support both direct manifest (legacy) and Stack Definition (nested manifest)
14
+ const sys = bundle.manifest || bundle;
15
+ const appId = sys.id || sys.name || 'unnamed-app';
16
+ this.name = `plugin.app.${appId}`;
17
+ this.version = sys.version;
18
+ }
19
+ async init(ctx) {
20
+ const sys = this.bundle.manifest || this.bundle;
21
+ const appId = sys.id || sys.name;
22
+ ctx.logger?.log(`[AppPlugin] Registering App Service: ${appId}`);
23
+ // Register the app manifest as a service
24
+ // ObjectQLPlugin will discover this and call ql.registerApp()
25
+ const serviceName = `app.${appId}`;
26
+ ctx.registerService(serviceName, this.bundle.manifest || this.bundle);
27
+ }
28
+ async start(ctx) {
29
+ // Execute Runtime Step
30
+ // Retrieve ObjectQL engine from services
31
+ // We cast to any/ObjectQL because ctx.getService returns unknown
32
+ const ql = ctx.getService('objectql');
33
+ if (!ql) {
34
+ ctx.logger?.warn(`[AppPlugin] ObjectQL engine service not found for app: ${this.name}`);
35
+ return;
36
+ }
37
+ const runtime = this.bundle.default || this.bundle;
38
+ if (runtime && typeof runtime.onEnable === 'function') {
39
+ ctx.logger?.log(`[AppPlugin] Executing runtime.onEnable for: ${this.name}`);
40
+ // Construct the Host Context (mirroring old ObjectQL.use logic)
41
+ const hostContext = {
42
+ ...ctx,
43
+ ql,
44
+ logger: ctx.logger || console,
45
+ drivers: {
46
+ register: (driver) => ql.registerDriver(driver)
47
+ },
48
+ };
49
+ await runtime.onEnable(hostContext);
50
+ }
51
+ }
52
+ }
@@ -0,0 +1,23 @@
1
+ import { Plugin, PluginContext } from '@objectstack/core';
2
+ /**
3
+ * Driver Plugin
4
+ *
5
+ * Generic plugin wrapper for ObjectQL drivers.
6
+ * Registers a driver with the ObjectQL engine.
7
+ *
8
+ * Dependencies: None (Registers service for ObjectQL to discover)
9
+ * Services: driver.{name}
10
+ *
11
+ * @example
12
+ * const memoryDriver = new InMemoryDriver();
13
+ * const driverPlugin = new DriverPlugin(memoryDriver, 'memory');
14
+ * kernel.use(driverPlugin);
15
+ */
16
+ export declare class DriverPlugin implements Plugin {
17
+ name: string;
18
+ version: string;
19
+ private driver;
20
+ constructor(driver: any, driverName?: string);
21
+ init(ctx: PluginContext): Promise<void>;
22
+ start(ctx: PluginContext): Promise<void>;
23
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Driver Plugin
3
+ *
4
+ * Generic plugin wrapper for ObjectQL drivers.
5
+ * Registers a driver with the ObjectQL engine.
6
+ *
7
+ * Dependencies: None (Registers service for ObjectQL to discover)
8
+ * Services: driver.{name}
9
+ *
10
+ * @example
11
+ * const memoryDriver = new InMemoryDriver();
12
+ * const driverPlugin = new DriverPlugin(memoryDriver, 'memory');
13
+ * kernel.use(driverPlugin);
14
+ */
15
+ export class DriverPlugin {
16
+ constructor(driver, driverName) {
17
+ this.version = '1.0.0';
18
+ this.driver = driver;
19
+ this.name = `com.objectstack.driver.${driverName || driver.name || 'unknown'}`;
20
+ }
21
+ async init(ctx) {
22
+ // Register driver as a service instead of directly to objectql
23
+ const serviceName = `driver.${this.driver.name || 'unknown'}`;
24
+ ctx.registerService(serviceName, this.driver);
25
+ ctx.logger.log(`[DriverPlugin] Registered driver service: ${serviceName}`);
26
+ }
27
+ async start(ctx) {
28
+ // Drivers don't need start phase, initialization happens in init
29
+ ctx.logger.log(`[DriverPlugin] Driver ready: ${this.driver.name || 'unknown'}`);
30
+ }
31
+ }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- export { ObjectQL, SchemaRegistry } from '@objectstack/objectql';
2
- export { ObjectStackKernel } from './kernel';
3
- export { ObjectQLPlugin } from './objectql-plugin';
4
- export { ObjectStackRuntimeProtocol } from './protocol';
5
- export * from './types';
1
+ export { ObjectKernel } from '@objectstack/core';
2
+ export { DriverPlugin } from './driver-plugin';
3
+ export { AppPlugin } from './app-plugin';
4
+ export * from '@objectstack/core';
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
- // Export core engine
2
- export { ObjectQL, SchemaRegistry } from '@objectstack/objectql';
3
- export { ObjectStackKernel } from './kernel';
4
- export { ObjectQLPlugin } from './objectql-plugin';
5
- export { ObjectStackRuntimeProtocol } from './protocol';
6
- export * from './types';
1
+ // Export Kernels
2
+ export { ObjectKernel } from '@objectstack/core';
3
+ // Export Plugins
4
+ export { DriverPlugin } from './driver-plugin';
5
+ export { AppPlugin } from './app-plugin';
6
+ // Export Types
7
+ export * from '@objectstack/core';
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@objectstack/runtime",
3
- "version": "0.4.2",
3
+ "version": "0.6.1",
4
4
  "description": "ObjectStack Core Runtime & Query Engine",
5
+ "type": "module",
5
6
  "main": "dist/index.js",
6
7
  "types": "dist/index.d.ts",
7
8
  "dependencies": {
8
- "@objectstack/objectql": "0.4.2",
9
- "@objectstack/types": "0.4.2",
10
- "@objectstack/spec": "0.4.2"
9
+ "@objectstack/core": "0.6.1",
10
+ "@objectstack/types": "0.6.1",
11
+ "@objectstack/spec": "0.6.1"
11
12
  },
12
13
  "devDependencies": {
13
14
  "typescript": "^5.0.0"
@@ -0,0 +1,69 @@
1
+ import { Plugin, PluginContext } from '@objectstack/core';
2
+
3
+ /**
4
+ * AppPlugin
5
+ *
6
+ * Adapts a generic App Bundle (Manifest + Runtime Code) into a Kernel Plugin.
7
+ *
8
+ * Responsibilities:
9
+ * 1. Register App Manifest as a service (for ObjectQL discovery)
10
+ * 2. Execute Runtime `onEnable` hook (for code logic)
11
+ */
12
+ export class AppPlugin implements Plugin {
13
+ name: string;
14
+ version?: string;
15
+
16
+ private bundle: any;
17
+
18
+ constructor(bundle: any) {
19
+ this.bundle = bundle;
20
+ // Support both direct manifest (legacy) and Stack Definition (nested manifest)
21
+ const sys = bundle.manifest || bundle;
22
+ const appId = sys.id || sys.name || 'unnamed-app';
23
+
24
+ this.name = `plugin.app.${appId}`;
25
+ this.version = sys.version;
26
+ }
27
+
28
+ async init(ctx: PluginContext) {
29
+ const sys = this.bundle.manifest || this.bundle;
30
+ const appId = sys.id || sys.name;
31
+
32
+ ctx.logger?.log(`[AppPlugin] Registering App Service: ${appId}`);
33
+
34
+ // Register the app manifest as a service
35
+ // ObjectQLPlugin will discover this and call ql.registerApp()
36
+ const serviceName = `app.${appId}`;
37
+ ctx.registerService(serviceName, this.bundle.manifest || this.bundle);
38
+ }
39
+
40
+ async start(ctx: PluginContext) {
41
+ // Execute Runtime Step
42
+ // Retrieve ObjectQL engine from services
43
+ // We cast to any/ObjectQL because ctx.getService returns unknown
44
+ const ql = ctx.getService('objectql') as any;
45
+
46
+ if (!ql) {
47
+ ctx.logger?.warn(`[AppPlugin] ObjectQL engine service not found for app: ${this.name}`);
48
+ return;
49
+ }
50
+
51
+ const runtime = this.bundle.default || this.bundle;
52
+
53
+ if (runtime && typeof runtime.onEnable === 'function') {
54
+ ctx.logger?.log(`[AppPlugin] Executing runtime.onEnable for: ${this.name}`);
55
+
56
+ // Construct the Host Context (mirroring old ObjectQL.use logic)
57
+ const hostContext = {
58
+ ...ctx,
59
+ ql,
60
+ logger: ctx.logger || console,
61
+ drivers: {
62
+ register: (driver: any) => ql.registerDriver(driver)
63
+ },
64
+ };
65
+
66
+ await runtime.onEnable(hostContext);
67
+ }
68
+ }
69
+ }
@@ -0,0 +1,40 @@
1
+ import { Plugin, PluginContext } from '@objectstack/core';
2
+
3
+ /**
4
+ * Driver Plugin
5
+ *
6
+ * Generic plugin wrapper for ObjectQL drivers.
7
+ * Registers a driver with the ObjectQL engine.
8
+ *
9
+ * Dependencies: None (Registers service for ObjectQL to discover)
10
+ * Services: driver.{name}
11
+ *
12
+ * @example
13
+ * const memoryDriver = new InMemoryDriver();
14
+ * const driverPlugin = new DriverPlugin(memoryDriver, 'memory');
15
+ * kernel.use(driverPlugin);
16
+ */
17
+ export class DriverPlugin implements Plugin {
18
+ name: string;
19
+ version = '1.0.0';
20
+ // dependencies = ['com.objectstack.engine.objectql']; // Removed: Driver is a producer, not strictly a consumer during init
21
+
22
+ private driver: any;
23
+
24
+ constructor(driver: any, driverName?: string) {
25
+ this.driver = driver;
26
+ this.name = `com.objectstack.driver.${driverName || driver.name || 'unknown'}`;
27
+ }
28
+
29
+ async init(ctx: PluginContext) {
30
+ // Register driver as a service instead of directly to objectql
31
+ const serviceName = `driver.${this.driver.name || 'unknown'}`;
32
+ ctx.registerService(serviceName, this.driver);
33
+ ctx.logger.log(`[DriverPlugin] Registered driver service: ${serviceName}`);
34
+ }
35
+
36
+ async start(ctx: PluginContext) {
37
+ // Drivers don't need start phase, initialization happens in init
38
+ ctx.logger.log(`[DriverPlugin] Driver ready: ${this.driver.name || 'unknown'}`);
39
+ }
40
+ }