Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
225 changes: 225 additions & 0 deletions OBJECTQL_PLUGIN_QUICKSTART.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
# ObjectQL Plugin - Quick Reference

## Installation

```bash
npm install @objectstack/runtime
```

## Basic Usage

### Default ObjectQL (Recommended)

```typescript
import { ObjectStackKernel, ObjectQLPlugin } from '@objectstack/runtime';

const kernel = new ObjectStackKernel([
new ObjectQLPlugin(),
// ... other plugins
]);

await kernel.start();
```

### Custom ObjectQL Instance

```typescript
import { ObjectStackKernel, ObjectQLPlugin, ObjectQL } from '@objectstack/runtime';

// Create custom instance
const customQL = new ObjectQL({
env: 'production',
// custom options
});

// Configure as needed
customQL.registerHook('beforeInsert', async (ctx) => {
console.log(`Inserting into ${ctx.object}`);
});

// Use in kernel
const kernel = new ObjectStackKernel([
new ObjectQLPlugin(customQL),
// ... other plugins
]);

await kernel.start();
```

### Backward Compatible (Legacy)

```typescript
// Still works without ObjectQLPlugin, but shows warning
const kernel = new ObjectStackKernel([
// ... plugins
]);
```

## API Reference

### ObjectQLPlugin Constructor

```typescript
new ObjectQLPlugin(ql?: ObjectQL, hostContext?: Record<string, any>)
```

**Parameters:**
- `ql` (optional): Custom ObjectQL instance to use
- `hostContext` (optional): Configuration for new ObjectQL instance (ignored if `ql` provided)

**Note:** If both parameters are provided, `hostContext` is ignored with a warning.

### Examples

```typescript
// Create with default settings
new ObjectQLPlugin()

// Use custom instance
const custom = new ObjectQL({ env: 'prod' });
new ObjectQLPlugin(custom)

// Create with custom context
new ObjectQLPlugin(undefined, { env: 'prod', debug: true })
```

## Migration Guide

### From Hardcoded to Plugin-Based

**Before:**
```typescript
const kernel = new ObjectStackKernel([appConfig, driver]);
```

**After:**
```typescript
const kernel = new ObjectStackKernel([
new ObjectQLPlugin(), // Add this line
appConfig,
driver
]);
```

## Common Patterns

### Testing with Mock ObjectQL

```typescript
import { ObjectQLPlugin } from '@objectstack/runtime';
import { MockObjectQL } from './mocks';

const mockQL = new MockObjectQL();
const kernel = new ObjectStackKernel([
new ObjectQLPlugin(mockQL),
// ... test config
]);
```

### Multiple Environments

```typescript
// Production
const prodQL = new ObjectQL({ env: 'production', cache: true });
const prodKernel = new ObjectStackKernel([
new ObjectQLPlugin(prodQL),
// ... production plugins
]);

// Development
const devKernel = new ObjectStackKernel([
new ObjectQLPlugin(undefined, { env: 'development', debug: true }),
// ... dev plugins
]);
```

### Custom ObjectQL from Separate Project

```typescript
// Your custom implementation
import { MyCustomObjectQL } from '@mycompany/custom-objectql';

const customQL = new MyCustomObjectQL({
specialFeature: true,
// custom options
});

const kernel = new ObjectStackKernel([
new ObjectQLPlugin(customQL),
// ... other plugins
]);
```

## Troubleshooting

### Error: "ObjectQL engine not initialized"

This means the kernel tried to use ObjectQL before it was set up. Make sure:
1. You include `ObjectQLPlugin` in your plugins array, OR
2. The kernel has backward compatibility enabled

### Warning: "No ObjectQL plugin found..."

This is a deprecation warning. Your code will work, but consider migrating to:

```typescript
new ObjectStackKernel([
new ObjectQLPlugin(), // Add this
// ... other plugins
]);
```

### Warning: "Both ql and hostContext provided..."

You passed both a custom ObjectQL instance and host context:

```typescript
// ❌ Don't do this
new ObjectQLPlugin(customQL, { env: 'prod' }) // hostContext ignored

// ✅ Do this instead
new ObjectQLPlugin(customQL) // Use custom instance

// ✅ Or this
new ObjectQLPlugin(undefined, { env: 'prod' }) // Create with context
```

## Advanced

### Type-Based Detection

ObjectQLPlugin uses a `type` field for reliable detection:

```typescript
// Check if a plugin is an ObjectQL plugin
const isObjectQLPlugin = plugin && plugin.type === 'objectql';
```

The plugin sets `type = 'objectql'` which aligns with the manifest schema that supports package types: 'app', 'plugin', 'driver', 'module', 'objectql', 'gateway', 'adapter'.

### Type Safety

The kernel's `ql` property is typed as optional:

```typescript
export class ObjectStackKernel {
public ql?: ObjectQL;

private ensureObjectQL(): ObjectQL {
if (!this.ql) {
throw new Error('ObjectQL engine not initialized');
}
return this.ql;
}
}
```

## Resources

- [Full Documentation](./packages/runtime/README.md)
- [Implementation Summary](./OBJECTQL_PLUGIN_SUMMARY.md)
- [Custom ObjectQL Example](./examples/custom-objectql-example.ts)

## License

Apache-2.0
2 changes: 1 addition & 1 deletion content/docs/references/system/manifest/Manifest.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ description: Manifest Schema Reference
| :--- | :--- | :--- | :--- |
| **id** | `string` | ✅ | Unique package identifier (reverse domain style) |
| **version** | `string` | ✅ | Package version (semantic versioning) |
| **type** | `Enum<'app' \| 'plugin' \| 'driver' \| 'module'>` | ✅ | Type of package |
| **type** | `Enum<'app' \| 'plugin' \| 'driver' \| 'module' \| 'objectql' \| 'gateway' \| 'adapter'>` | ✅ | Type of package |
| **name** | `string` | ✅ | Human-readable package name |
| **description** | `string` | optional | Package description |
| **permissions** | `string[]` | optional | Array of required permission strings |
Expand Down
44 changes: 44 additions & 0 deletions examples/custom-objectql-example.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* Example: Custom ObjectQL Instance
*
* This demonstrates how to use a custom ObjectQL instance with the kernel.
* This is useful when you have a separate ObjectQL implementation or need
* custom configuration.
*/

import { ObjectStackKernel, ObjectQLPlugin, ObjectQL } from '@objectstack/runtime';
import { InMemoryDriver } from '@objectstack/driver-memory';

(async () => {
console.log('🚀 Example: Custom ObjectQL Instance...');

// Create a custom ObjectQL instance with specific configuration
const customQL = new ObjectQL({
env: 'development',
// Add any custom host context here
customFeature: true,
debug: true
});

// You can also pre-configure the ObjectQL instance
// For example, register custom hooks
customQL.registerHook('beforeInsert', async (ctx) => {
console.log(`[Custom Hook] Before inserting into ${ctx.object}`);
});

// Create kernel with the custom ObjectQL instance
const kernel = new ObjectStackKernel([
// Register your custom ObjectQL instance
new ObjectQLPlugin(customQL),

// Add your driver
new InMemoryDriver(),

// Add other plugins and app configs as needed
]);

await kernel.start();

console.log('✅ Kernel started with custom ObjectQL instance');
console.log('ObjectQL instance:', kernel.ql);
})();
3 changes: 2 additions & 1 deletion examples/host/debug-registry.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

import { ObjectStackKernel } from '@objectstack/runtime';
import { ObjectStackKernel, ObjectQLPlugin } from '@objectstack/runtime';
import { SchemaRegistry, ObjectQL } from '@objectstack/objectql';
import { InMemoryDriver } from '@objectstack/driver-memory';

Expand All @@ -11,6 +11,7 @@ import TodoApp from '@objectstack/example-todo/objectstack.config';
console.log('Objects inside App:', TodoApp.objects?.map((o: any) => o.name));

const kernel = new ObjectStackKernel([
new ObjectQLPlugin(),
TodoApp,
new InMemoryDriver()
]);
Expand Down
16 changes: 15 additions & 1 deletion examples/host/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ObjectStackKernel } from '@objectstack/runtime';
import { ObjectStackKernel, ObjectQLPlugin, ObjectQL } from '@objectstack/runtime';

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused import ObjectQL.

Copilot Autofix

AI 2 months ago

In general, unused imports should be removed from the import list so that only actually used symbols are imported. This improves readability, avoids misleading future maintainers about dependencies, and can help with tree-shaking and tooling.

The best minimal fix here is to adjust the import statement on line 1 in examples/host/src/index.ts so that it only imports ObjectStackKernel and ObjectQLPlugin, removing ObjectQL. No other lines need to change, since all references to ObjectQL in the file are commented out and do not affect functionality. This preserves all existing behavior while resolving the CodeQL warning.

Concretely, in examples/host/src/index.ts, edit the import on line 1 from:

import { ObjectStackKernel, ObjectQLPlugin, ObjectQL } from '@objectstack/runtime';

to:

import { ObjectStackKernel, ObjectQLPlugin } from '@objectstack/runtime';

No new methods, definitions, or imports are required.

Suggested changeset 1
examples/host/src/index.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/examples/host/src/index.ts b/examples/host/src/index.ts
--- a/examples/host/src/index.ts
+++ b/examples/host/src/index.ts
@@ -1,4 +1,4 @@
-import { ObjectStackKernel, ObjectQLPlugin, ObjectQL } from '@objectstack/runtime';
+import { ObjectStackKernel, ObjectQLPlugin } from '@objectstack/runtime';
 import { InMemoryDriver } from '@objectstack/driver-memory';
 import { HonoServerPlugin } from '@objectstack/plugin-hono-server';
 
EOF
@@ -1,4 +1,4 @@
import { ObjectStackKernel, ObjectQLPlugin, ObjectQL } from '@objectstack/runtime';
import { ObjectStackKernel, ObjectQLPlugin } from '@objectstack/runtime';
import { InMemoryDriver } from '@objectstack/driver-memory';
import { HonoServerPlugin } from '@objectstack/plugin-hono-server';

Copilot is powered by AI and may make mistakes. Always verify output.
Copy link

Copilot AI Jan 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import ObjectQL.

Suggested change
import { ObjectStackKernel, ObjectQLPlugin, ObjectQL } from '@objectstack/runtime';
import { ObjectStackKernel, ObjectQLPlugin } from '@objectstack/runtime';

Copilot uses AI. Check for mistakes.
import { InMemoryDriver } from '@objectstack/driver-memory';
import { HonoServerPlugin } from '@objectstack/plugin-hono-server';

Expand All @@ -9,10 +9,17 @@
(async () => {
console.log('🚀 Booting Kernel...');

// Option 1: Use default ObjectQL via plugin (recommended)
const kernel = new ObjectStackKernel([
// Register ObjectQL engine explicitly via plugin
new ObjectQLPlugin(),

// App manifests
CrmApp,
TodoApp,
BiPluginManifest,

// Database driver
new InMemoryDriver(),

// Load the Hono Server Plugin
Expand All @@ -22,5 +29,12 @@
})
]);

// Option 2: Use custom ObjectQL instance
// const customQL = new ObjectQL({ env: 'production', customConfig: true });
// const kernel = new ObjectStackKernel([
// new ObjectQLPlugin(customQL),
// ...other plugins
// ]);

await kernel.start();
})();
5 changes: 4 additions & 1 deletion examples/msw-react-crud/src/mocks/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* and the MSW Plugin which automatically exposes the API.
*/

import { ObjectStackKernel } from '@objectstack/runtime';
import { ObjectStackKernel, ObjectQLPlugin } from '@objectstack/runtime';
import { InMemoryDriver } from '@objectstack/driver-memory';
import { MSWPlugin } from '@objectstack/plugin-msw';
// import appConfig from '../../objectstack.config';
Expand All @@ -24,6 +24,9 @@ export async function startMockServer() {
// We use the data defined in the Todo App config

kernel = new ObjectStackKernel([
// Register ObjectQL engine explicitly
new ObjectQLPlugin(),

// Todo App Config (contains objects and data)
todoConfig,

Expand Down
Loading
Loading