Skip to content

Commit 817849d

Browse files
authored
Merge pull request #155 from objectstack-ai/copilot/refactor-core-engine-plugin-structure
2 parents ff5525c + 2e92746 commit 817849d

File tree

12 files changed

+474
-178
lines changed

12 files changed

+474
-178
lines changed

packages/foundation/core/README.md

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,35 @@
11
# @objectql/core
22

3-
The core ORM and runtime engine for ObjectQL. This package handles object querying, CRUD operations, database driver coordination, transaction management, and **metadata-driven validation**.
3+
The core ORM and runtime engine for ObjectQL. This package handles object querying, CRUD operations, database driver coordination, transaction management, and **metadata-driven validation**. As of version 4.0.0, it wraps the **ObjectStackKernel** for plugin architecture and lifecycle management.
44

55
## Features
66

7-
- **Unified Query Language**: A generic way to query data across different databases (SQL, Mongo, etc.).
8-
- **Repository Pattern**: `ObjectRepository` for managing object records.
9-
- **Driver Agnostic**: Abstraction layer for database drivers.
10-
- **Dynamic Schema**: Loads object definitions from metadata.
11-
- **Hooks & Actions**: Runtime logic injection.
12-
- **Validation Engine**: Metadata-driven validation with field-level, cross-field, and state machine rules.
7+
- **Plugin Architecture**: Built on top of `@objectstack/runtime` with kernel-based plugin system
8+
- **Unified Query Language**: A generic way to query data across different databases (SQL, Mongo, etc.)
9+
- **Repository Pattern**: `ObjectRepository` for managing object records
10+
- **Driver Agnostic**: Abstraction layer for database drivers
11+
- **Dynamic Schema**: Loads object definitions from metadata
12+
- **Hooks & Actions**: Runtime logic injection
13+
- **Validation Engine**: Metadata-driven validation with field-level, cross-field, and state machine rules
14+
- **Formula Engine**: Computed fields with dynamic formulas
15+
- **AI Integration**: Built-in AI agent capabilities
1316

1417
## Installation
1518

1619
```bash
17-
npm install @objectql/core @objectql/types
20+
npm install @objectql/core @objectql/types @objectstack/runtime @objectstack/spec
1821
```
1922

23+
## Architecture
24+
25+
ObjectQL now wraps the `ObjectStackKernel` from `@objectstack/runtime`, providing:
26+
27+
- **Kernel-based lifecycle management**: Initialization, startup, and shutdown
28+
- **Plugin system**: Extensible architecture with `ObjectQLPlugin`
29+
- **Enhanced features**: Repository, Validator, Formula, and AI capabilities as plugins
30+
31+
See [RUNTIME_INTEGRATION.md](./RUNTIME_INTEGRATION.md) for detailed architecture documentation.
32+
2033
## Usage
2134

2235
### Basic Setup
@@ -31,7 +44,7 @@ const objectql = new ObjectQL({
3144
}
3245
});
3346

34-
await objectql.init();
47+
await objectql.init(); // Initializes the kernel and all plugins
3548

3649
// Use context for operations
3750
const ctx = objectql.createContext({ userId: 'u-1' });
@@ -40,6 +53,15 @@ const projects = await ctx.object('project').find({
4053
});
4154
```
4255

56+
### Accessing the Kernel
57+
58+
For advanced use cases, you can access the underlying kernel:
59+
60+
```typescript
61+
const kernel = objectql.getKernel();
62+
// Use kernel methods if needed
63+
```
64+
4365
### Validation System
4466

4567
The validation system allows you to define validation rules in your object metadata and execute them programmatically.

packages/foundation/core/RUNTIME_INTEGRATION.md

Lines changed: 136 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,39 +4,63 @@ This document explains the integration of `@objectstack/runtime` and `@objectsta
44

55
## Overview
66

7-
As of version 3.0.1, ObjectQL core natively uses the ObjectStack runtime packages:
7+
As of version 4.0.0, ObjectQL core uses the ObjectStack runtime packages with plugin architecture:
88

9-
- **@objectstack/spec@0.1.2**: Protocol specification with standard `DriverInterface`
10-
- **@objectstack/objectql@0.1.1**: Core ObjectQL engine with driver management
11-
- **@objectstack/runtime@0.1.1**: Runtime kernel with application lifecycle orchestration
9+
- **@objectstack/spec@0.2.0**: Protocol specification with standard `DriverInterface`
10+
- **@objectstack/objectql@0.2.0**: Core ObjectQL engine with driver management
11+
- **@objectstack/runtime@0.2.0**: Runtime kernel with application lifecycle orchestration and plugin system
1212

1313
## Architecture
1414

1515
### Package Relationship
1616

1717
```
1818
@objectql/core (this package)
19+
├── Wraps ObjectStackKernel from @objectstack/runtime
20+
├── Implements ObjectQLPlugin for enhanced features
1921
├── Uses @objectstack/objectql for driver management
2022
├── Natively uses @objectstack/spec.DriverInterface (no wrapper)
2123
└── Re-exports types from @objectstack/runtime
2224
```
2325

24-
### Driver Management Integration
26+
### Plugin Architecture (v4.0.0)
2527

26-
**Breaking Change (v3.0.1):** The core package now **natively uses** `DriverInterface` from `@objectstack/spec`:
28+
**Breaking Change (v4.0.0):** The core package now **wraps `ObjectStackKernel`** and uses a plugin architecture:
2729

2830
```typescript
29-
import { ObjectQL } from '@objectql/core';
31+
import { ObjectQL, ObjectQLPlugin } from '@objectql/core';
3032
import type { DriverInterface } from '@objectstack/spec';
3133

32-
// Drivers must implement DriverInterface from @objectstack/spec
34+
// ObjectQL now wraps ObjectStackKernel internally
3335
const app = new ObjectQL({
3436
datasources: {
3537
default: myDriver // Must be DriverInterface
3638
}
3739
});
3840

39-
await app.init();
41+
// Access the kernel if needed
42+
const kernel = app.getKernel();
43+
44+
await app.init(); // This calls kernel.start() internally
45+
```
46+
47+
### ObjectQLPlugin
48+
49+
The new `ObjectQLPlugin` class implements the `RuntimePlugin` interface from `@objectstack/runtime`:
50+
51+
```typescript
52+
import { ObjectQLPlugin, ObjectQLPluginConfig } from '@objectql/core';
53+
54+
// Configure the plugin
55+
const plugin = new ObjectQLPlugin({
56+
enableRepository: true,
57+
enableValidator: true,
58+
enableFormulas: true,
59+
enableAI: true
60+
});
61+
62+
// The plugin is automatically registered when you create an ObjectQL instance
63+
const app = new ObjectQL({ datasources: {} });
4064
```
4165

4266
### Type Exports
@@ -76,6 +100,7 @@ The current `ObjectQL` class in this package is a **production-ready, feature-ri
76100
- Repository pattern
77101
- Formula engine
78102
- AI integration
103+
- **Wraps ObjectStackKernel for plugin architecture**
79104
- **Native driver management via @objectstack/objectql**
80105

81106
The `ObjectQLEngine` from `@objectstack/objectql` is a **simpler, lightweight** implementation suitable for:
@@ -84,6 +109,46 @@ The `ObjectQLEngine` from `@objectstack/objectql` is a **simpler, lightweight**
84109
- Simple driver management
85110
- Minimal runtime overhead
86111

112+
### Kernel Integration
113+
114+
ObjectQL now wraps the `ObjectStackKernel` to provide plugin architecture and lifecycle management:
115+
116+
```typescript
117+
// In @objectql/core
118+
import { ObjectStackKernel } from '@objectstack/runtime';
119+
import { ObjectQLPlugin } from './plugin';
120+
121+
export class ObjectQL implements IObjectQL {
122+
private kernel: ObjectStackKernel;
123+
private kernelPlugins: any[] = [];
124+
125+
constructor(config: ObjectQLConfig) {
126+
// Add the ObjectQL plugin to provide enhanced features
127+
this.kernelPlugins.push(new ObjectQLPlugin());
128+
129+
// Create the kernel instance
130+
this.kernel = new ObjectStackKernel(this.kernelPlugins);
131+
}
132+
133+
async init() {
134+
console.log('[ObjectQL] Initializing with ObjectStackKernel...');
135+
136+
// Start the kernel first - this will install and start all plugins
137+
await this.kernel.start();
138+
139+
// Continue with legacy initialization...
140+
}
141+
142+
/**
143+
* Get the underlying ObjectStackKernel instance
144+
* for advanced usage scenarios
145+
*/
146+
getKernel(): ObjectStackKernel {
147+
return this.kernel;
148+
}
149+
}
150+
```
151+
87152
### Driver Management (No Compatibility Layer)
88153

89154
ObjectQL now directly uses drivers conforming to `@objectstack/spec.DriverInterface`:
@@ -174,12 +239,73 @@ app.registerDriver('mydb', new MyCustomDriver(), false);
174239

175240
## Breaking Changes
176241

242+
### v4.0.0: Plugin Architecture
243+
244+
**What Changed:**
245+
- `ObjectQL` now wraps `ObjectStackKernel` from `@objectstack/runtime`
246+
- New `ObjectQLPlugin` class implements `RuntimePlugin` interface
247+
- Initialization process now calls `kernel.start()` which installs and starts all plugins
248+
- Dependencies updated to `@objectstack/*@0.2.0`
249+
- New `getKernel()` method provides access to the underlying kernel
250+
- **Removed legacy plugin support** - all plugins must now implement the `RuntimePlugin` interface
251+
252+
**Migration Guide:**
253+
254+
The ObjectQL API remains the same:
255+
```typescript
256+
import { ObjectQL } from '@objectql/core';
257+
import { MyDriver } from './my-driver';
258+
259+
const app = new ObjectQL({
260+
datasources: {
261+
default: new MyDriver()
262+
}
263+
});
264+
265+
await app.init(); // Calls kernel.start() internally
266+
```
267+
268+
Access the kernel for advanced use cases:
269+
```typescript
270+
const kernel = app.getKernel(); // Must call after init()
271+
```
272+
273+
**Plugin Migration:**
274+
275+
Old plugins with `onEnable` hook are no longer supported. Migrate to `RuntimePlugin`:
276+
277+
```typescript
278+
// Old (no longer supported)
279+
const plugin = {
280+
id: 'my-plugin',
281+
onEnable: async (context) => {
282+
// initialization logic
283+
}
284+
};
285+
286+
// New (required)
287+
import type { RuntimePlugin, RuntimeContext } from '@objectstack/runtime';
288+
289+
class MyPlugin implements RuntimePlugin {
290+
name = 'my-plugin';
291+
292+
async install(ctx: RuntimeContext): Promise<void> {
293+
// installation logic
294+
}
295+
296+
async onStart(ctx: RuntimeContext): Promise<void> {
297+
// startup logic
298+
}
299+
}
300+
301+
const plugin = new MyPlugin();
302+
```
303+
177304
### v3.0.1: Native DriverInterface Adoption
178305

179306
**What Changed:**
180307
- `ObjectQLConfig.datasources` now requires `Record<string, DriverInterface>` (from `@objectstack/spec`)
181308
- Removed compatibility wrapper for old `Driver` type
182-
- `app.registerDriver()` now accepts `DriverInterface` instead of legacy `Driver`
183309
- `app.datasource()` now returns `DriverInterface`
184310
- Driver lifecycle is fully managed by ObjectStack engine
185311

packages/foundation/core/jest.config.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,18 @@ module.exports = {
1212
testMatch: ['**/test/**/*.test.ts'],
1313
moduleNameMapper: {
1414
'^@objectql/(.*)$': '<rootDir>/../$1/src',
15+
'^@objectstack/runtime$': '<rootDir>/test/__mocks__/@objectstack/runtime.ts',
1516
},
1617
transform: {
1718
'^.+\\.ts$': ['ts-jest', {
1819
isolatedModules: true,
20+
tsconfig: {
21+
esModuleInterop: true,
22+
allowSyntheticDefaultImports: true,
23+
}
1924
}],
2025
},
26+
transformIgnorePatterns: [
27+
'node_modules/(?!(@objectstack))',
28+
],
2129
};

packages/foundation/core/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
"dependencies": {
2525
"@objectql/types": "workspace:*",
2626
"@objectstack/spec": "^0.2.0",
27-
"@objectstack/runtime": "^0.1.1",
28-
"@objectstack/objectql": "^0.1.1",
27+
"@objectstack/runtime": "^0.2.0",
28+
"@objectstack/objectql": "^0.2.0",
2929
"js-yaml": "^4.1.0",
3030
"openai": "^4.28.0"
3131
},

0 commit comments

Comments
 (0)