Skip to content

Commit a82980f

Browse files
committed
feat: integrate MemoryDriver and update plugin initialization for ObjectQL compatibility
1 parent d69ff7b commit a82980f

5 files changed

Lines changed: 109 additions & 24 deletions

File tree

objectstack.config.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ import { JSONRPCPlugin } from '@objectql/protocol-json-rpc';
2525
import { HonoServerPlugin } from '@objectstack/plugin-hono-server';
2626
import { ObjectQLPlugin } from '@objectql/core';
2727
import { createApiRegistryPlugin } from '@objectstack/core';
28+
import { MemoryDriver } from '@objectql/driver-memory';
2829
import * as fs from 'fs';
29-
import * as path from 'path';
3030
import * as yaml from 'js-yaml';
3131

3232
function loadObjects(dir: string) {
@@ -70,7 +70,10 @@ export default {
7070
enableQueryService: true,
7171
// Validator and Formula plugins are included by default
7272
enableValidator: true,
73-
enableFormulas: true
73+
enableFormulas: true,
74+
datasources: {
75+
default: new MemoryDriver()
76+
}
7477
}),
7578
new ObjectQLSecurityPlugin({
7679
enableAudit: false

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"@eslint/js": "^9.39.2",
2727
"@objectql/cli": "workspace:*",
2828
"@objectql/core": "workspace:*",
29+
"@objectql/driver-memory": "^4.2.0",
2930
"@objectql/example-enterprise-erp": "workspace:*",
3031
"@objectql/example-project-tracker": "workspace:*",
3132
"@objectql/plugin-security": "workspace:*",

packages/foundation/core/src/plugin.ts

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { QueryAnalyzer } from './query/query-analyzer';
1616
import { ObjectStackProtocolImplementation } from './protocol';
1717
import type { Driver } from '@objectql/types';
1818
import { createDefaultAiRegistry } from './ai';
19+
import { SchemaRegistry } from '@objectstack/objectql';
1920

2021
/**
2122
* Extended kernel with ObjectQL services
@@ -304,33 +305,74 @@ export class ObjectQLPlugin implements RuntimePlugin {
304305
}
305306

306307
// --- Adapter for @objectstack/core compatibility ---
307-
init = async (kernel: any): Promise<void> => {
308-
// The new core passes the kernel instance directly
309-
// We wrap it to match the old RuntimeContext interface
308+
init = async (pluginCtx: any): Promise<void> => {
309+
// The @objectstack/core kernel passes a PluginContext (with registerService, getKernel, etc.)
310+
// We extract the actual kernel and build a RuntimeContext wrapper that proxies registerService.
311+
const actualKernel = typeof pluginCtx.getKernel === 'function'
312+
? pluginCtx.getKernel()
313+
: pluginCtx;
314+
315+
// Create metadata facade on the kernel if not already present.
316+
// The raw ObjectKernel from @objectstack/core has no .metadata property;
317+
// it's normally created by the ObjectQL wrapper (app.ts).
318+
// When running via `objectstack serve`, we must create it here.
319+
if (!actualKernel.metadata) {
320+
const unwrapContent = (item: any) => (item && item.content) ? item.content : item;
321+
actualKernel.metadata = {
322+
register: (type: string, item: any) => SchemaRegistry.registerItem(type, item, item.id ? 'id' : 'name'),
323+
get: (type: string, name: string) => {
324+
const item = SchemaRegistry.getItem(type, name) as any;
325+
return unwrapContent(item);
326+
},
327+
getEntry: (type: string, name: string) => SchemaRegistry.getItem(type, name),
328+
list: (type: string) => {
329+
const items = SchemaRegistry.listItems(type);
330+
return items.map(unwrapContent);
331+
},
332+
unregister: (type: string, name: string) => {
333+
if (typeof SchemaRegistry.unregisterItem === 'function') {
334+
SchemaRegistry.unregisterItem(type, name);
335+
}
336+
},
337+
unregisterPackage: (packageName: string) => {
338+
if (typeof (SchemaRegistry as any).unregisterObjectsByPackage === 'function') {
339+
(SchemaRegistry as any).unregisterObjectsByPackage(packageName);
340+
}
341+
},
342+
};
343+
this.logger.info('Created metadata facade on kernel');
344+
}
345+
310346
const ctx: any = {
311-
engine: kernel,
312-
getKernel: () => kernel
347+
engine: actualKernel,
348+
getKernel: () => actualKernel,
349+
// Proxy registerService from PluginContext so install() can register metadata/data/analytics
350+
registerService: typeof pluginCtx.registerService === 'function'
351+
? pluginCtx.registerService.bind(pluginCtx)
352+
: undefined,
313353
};
314354

315355
// Register Protocol Service
316-
// If kernel supports service registration (PluginContext or ExtendedKernel with custom registry)
317-
if (kernel && typeof kernel.registerService === 'function') {
356+
if (typeof pluginCtx.registerService === 'function') {
318357
this.logger.info('Registering protocol service...');
319-
const protocolShim = new ObjectStackProtocolImplementation(kernel);
320-
kernel.registerService('protocol', protocolShim);
321-
322-
// Register 'objectql' service for AppPlugin compatibility
323-
kernel.registerService('objectql', this);
324-
this.logger.debug('Registered objectql service');
358+
const protocolShim = new ObjectStackProtocolImplementation(actualKernel);
359+
pluginCtx.registerService('protocol', protocolShim);
360+
361+
// Register 'objectql' service for AppPlugin compatibility
362+
pluginCtx.registerService('objectql', this);
363+
this.logger.debug('Registered objectql service');
325364
}
326365

327366
return this.install(ctx);
328367
}
329368

330-
start = async (kernel: any): Promise<void> => {
369+
start = async (pluginCtx: any): Promise<void> => {
370+
const actualKernel = typeof pluginCtx.getKernel === 'function'
371+
? pluginCtx.getKernel()
372+
: pluginCtx;
331373
const ctx: any = {
332-
engine: kernel,
333-
getKernel: () => kernel
374+
engine: actualKernel,
375+
getKernel: () => actualKernel,
334376
};
335377
return this.onStart(ctx);
336378
}

packages/foundation/plugin-security/src/plugin.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,28 @@ export class ObjectQLSecurityPlugin implements RuntimePlugin {
7474
}
7575

7676
// --- Adapter for @objectstack/core compatibility ---
77-
init = async (kernel: any): Promise<void> => {
77+
init = async (pluginCtx: any): Promise<void> => {
78+
// Extract actual kernel from PluginContext and proxy registerService
79+
const actualKernel = typeof pluginCtx.getKernel === 'function'
80+
? pluginCtx.getKernel()
81+
: pluginCtx;
7882
const ctx: any = {
79-
engine: kernel,
80-
getKernel: () => kernel
83+
engine: actualKernel,
84+
getKernel: () => actualKernel,
85+
registerService: typeof pluginCtx.registerService === 'function'
86+
? pluginCtx.registerService.bind(pluginCtx)
87+
: undefined,
88+
hook: typeof pluginCtx.hook === 'function'
89+
? pluginCtx.hook.bind(pluginCtx)
90+
: undefined,
91+
trigger: typeof pluginCtx.trigger === 'function'
92+
? pluginCtx.trigger.bind(pluginCtx)
93+
: undefined,
8194
};
8295
return this.install(ctx);
8396
}
8497

85-
start = async (_kernel: any): Promise<void> => {
98+
start = async (_pluginCtx: any): Promise<void> => {
8699
// Security plugin doesn't have specific start logic yet
87100
return;
88101
}
@@ -161,10 +174,10 @@ export class ObjectQLSecurityPlugin implements RuntimePlugin {
161174
const registerHook = (name: string, handler: any) => {
162175
if (typeof ctx.hook === 'function') {
163176
ctx.hook(name, handler);
164-
} else if (typeof (kernel as any).use === 'function') {
165-
(kernel as any).use(name, handler);
166177
} else if (typeof (kernel as any).hooks?.register === 'function') {
167178
(kernel as any).hooks.register(name, handler);
179+
} else {
180+
this.logger.warn(`Cannot register hook '${name}': no hook registration mechanism available`);
168181
}
169182
};
170183

pnpm-lock.yaml

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)