@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 +28 -0
- package/README.md +198 -81
- package/dist/app-plugin.d.ts +18 -0
- package/dist/app-plugin.js +52 -0
- package/dist/driver-plugin.d.ts +23 -0
- package/dist/driver-plugin.js +31 -0
- package/dist/index.d.ts +4 -5
- package/dist/index.js +7 -6
- package/package.json +5 -4
- package/src/app-plugin.ts +69 -0
- package/src/driver-plugin.ts +40 -0
- package/src/index.ts +9 -6
- package/dist/kernel.d.ts +0 -147
- package/dist/kernel.js +0 -173
- package/dist/objectql-plugin.d.ts +0 -27
- package/dist/objectql-plugin.js +0 -41
- package/dist/protocol.d.ts +0 -68
- package/dist/protocol.js +0 -108
- package/dist/types.d.ts +0 -9
- package/dist/types.js +0 -1
- package/src/kernel.ts +0 -203
- package/src/objectql-plugin.ts +0 -47
- package/src/protocol.ts +0 -129
- package/src/types.ts +0 -11
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
|
|
3
|
+
ObjectStack Standard System Library
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
The runtime package provides the
|
|
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
|
-
##
|
|
21
|
+
## Quick Start
|
|
16
22
|
|
|
17
|
-
### Basic Setup
|
|
23
|
+
### Basic Setup (Recommended)
|
|
18
24
|
|
|
19
25
|
```typescript
|
|
20
|
-
import {
|
|
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
|
|
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.
|
|
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 {
|
|
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
|
|
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
|
-
//
|
|
60
|
-
|
|
71
|
+
// Add driver
|
|
72
|
+
.use(new DriverPlugin(new InMemoryDriver(), 'memory'));
|
|
73
|
+
|
|
74
|
+
await kernel.bootstrap();
|
|
61
75
|
|
|
62
|
-
|
|
76
|
+
// Access ObjectQL via service registry
|
|
77
|
+
const objectql = kernel.getService('objectql');
|
|
63
78
|
```
|
|
64
79
|
|
|
65
|
-
|
|
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
|
-
|
|
92
|
+
#### ObjectQLPlugin
|
|
93
|
+
Registers the ObjectQL data engine as a service.
|
|
68
94
|
|
|
69
95
|
```typescript
|
|
70
|
-
//
|
|
71
|
-
|
|
72
|
-
|
|
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
|
-
|
|
101
|
+
**Services**: `'objectql'`
|
|
78
102
|
|
|
79
|
-
|
|
103
|
+
#### DriverPlugin
|
|
104
|
+
Registers a data driver with ObjectQL.
|
|
80
105
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
- Coordinating the ObjectQL engine
|
|
85
|
-
- Handling data operations
|
|
106
|
+
```typescript
|
|
107
|
+
new DriverPlugin(driver, 'driver-name')
|
|
108
|
+
```
|
|
86
109
|
|
|
87
|
-
|
|
110
|
+
**Dependencies**: `['com.objectstack.engine.objectql']`
|
|
88
111
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
-
###
|
|
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
|
-
|
|
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
|
-
- `
|
|
106
|
-
- `
|
|
107
|
-
- `
|
|
108
|
-
- `
|
|
109
|
-
- `
|
|
110
|
-
- `
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
|
|
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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
- `
|
|
250
|
+
- `test-mini-kernel.ts` - Comprehensive kernel test suite
|
|
251
|
+
- `packages/runtime/src/
|
|
131
252
|
|
|
132
|
-
##
|
|
253
|
+
## Benefits of MiniKernel
|
|
133
254
|
|
|
134
|
-
|
|
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
|
-
|
|
137
|
-
```typescript
|
|
138
|
-
const kernel = new ObjectStackKernel([appConfig, driver]);
|
|
139
|
-
```
|
|
263
|
+
## Best Practices
|
|
140
264
|
|
|
141
|
-
**
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
-
|
|
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 {
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
4
|
-
export
|
|
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
|
|
2
|
-
export {
|
|
3
|
-
|
|
4
|
-
export {
|
|
5
|
-
export {
|
|
6
|
-
|
|
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.
|
|
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/
|
|
9
|
-
"@objectstack/types": "0.
|
|
10
|
-
"@objectstack/spec": "0.
|
|
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
|
+
}
|