Skip to content

Commit 2b14f10

Browse files
authored
Merge pull request #378 from objectstack-ai/copilot/prioritize-3-0-upgrade-development
2 parents 7cebb59 + a6f174b commit 2b14f10

10 files changed

Lines changed: 241 additions & 237 deletions

File tree

.github/labeler.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@
2121
- changed-files:
2222
- any-glob-to-any-file: ['packages/drivers/**/*']
2323

24-
'🚀 runtime':
25-
- changed-files:
26-
- any-glob-to-any-file: ['packages/runtime/**/*']
27-
2824
'📝 examples':
2925
- changed-files:
3026
- any-glob-to-any-file: ['examples/**/*']

ROADMAP.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# ObjectQL — 2026 Roadmap
22

33
> Created: 2026-02-08 | Last Updated: 2026-02-12 | Status: **Active**
4-
> Current Version: **4.2.0** (all packages aligned, except `vscode-objectql` at 4.1.0)
5-
> Runtime: `@objectstack/cli` v3.0.0 (Kernel pattern) — `@objectql/server` deprecated, `packages/runtime/` removed.
4+
> Current Version: **4.2.0** (all packages aligned)
5+
> Runtime: `@objectstack/cli` v3.0.0 (Kernel pattern) — `@objectql/server` removed, `packages/runtime/` removed.
66
> @objectstack Platform: **v3.0.0**
77
88
---
@@ -222,16 +222,16 @@ export interface PgWasmDriverConfig {
222222

223223
Technical debt accumulated from the v3 → v4 migration. These are non-breaking cleanups.
224224

225-
| Task | Description | Est. |
226-
|------|-------------|------|
227-
| **H-1** | Delete `packages/runtime/` empty directory | 5min |
228-
| **H-2** | Update `README.md` — remove deprecated packages, add WASM drivers | 1h |
229-
| **H-3** | Replace `@objectql/server` references with Kernel pattern | 1h |
230-
| **H-4** | Clean `cli/src/commands/doctor.ts` — remove `@objectql/server` check | 30min |
231-
| **H-5** | Clean `sdk/README.md` — remove `@objectql/server` reference | 30min |
232-
| **H-6** | Bump `vscode-objectql` from 4.1.0 → 4.2.0 | 1h |
233-
| **H-7** | Update express-server example README | 30min |
234-
| **H-8** | Audit CHANGELOG.md files for deprecated references | 1h |
225+
| Task | Description | Est. | Status |
226+
|------|-------------|------|--------|
227+
| **H-1** | Delete `packages/runtime/` empty directory | 5min | ✅ Done |
228+
| **H-2** | Update `README.md` — remove deprecated packages, add WASM drivers | 1h ||
229+
| **H-3** | Replace `@objectql/server` references with Kernel pattern | 1h | ✅ Done |
230+
| **H-4** | Clean `cli/src/commands/doctor.ts` — remove `@objectql/server` check | 30min | ✅ Done (no refs found) |
231+
| **H-5** | Clean `sdk/README.md` — remove `@objectql/server` reference | 30min | ✅ Done (no refs found) |
232+
| **H-6** | Bump `vscode-objectql` from 4.1.0 → 4.2.0 | 1h | ✅ Done |
233+
| **H-7** | Update express-server example README | 30min | ✅ Done |
234+
| **H-8** | Audit CHANGELOG.md files for deprecated references | 1h | ✅ Skipped (historical) |
235235

236236
### Part B: `@objectql/plugin-workflow` (3 weeks)
237237

content/blog/security-by-design.mdx

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -402,21 +402,29 @@ const record = await repository.findOne({
402402

403403
### 3. Cross-Site Request Forgery (CSRF) Protection
404404

405-
When using `@objectql/server`, CSRF protection is enabled by default:
405+
When using `@objectstack/plugin-hono-server`, CSRF protection is enabled by default:
406406

407407
```typescript
408-
import { createObjectQLServer } from '@objectql/server';
409-
410-
const server = createObjectQLServer({
411-
repository,
412-
security: {
413-
csrf: {
414-
enabled: true,
415-
cookieName: 'csrf_token',
416-
headerName: 'X-CSRF-Token'
408+
import { ObjectStackKernel } from '@objectstack/runtime';
409+
import { HonoServerPlugin } from '@objectstack/plugin-hono-server';
410+
import { ObjectQLPlugin } from '@objectql/core';
411+
import { MemoryDriver } from '@objectql/driver-memory';
412+
413+
const kernel = new ObjectStackKernel([
414+
appConfig,
415+
new MemoryDriver(),
416+
new ObjectQLPlugin(),
417+
new HonoServerPlugin({
418+
port: 3000,
419+
security: {
420+
csrf: {
421+
enabled: true,
422+
cookieName: 'csrf_token',
423+
headerName: 'X-CSRF-Token'
424+
}
417425
}
418-
}
419-
});
426+
})
427+
]);
420428
```
421429

422430
All state-changing requests require a valid CSRF token:

content/docs/reference/api/attachments.mdx

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,43 +1081,51 @@ ObjectQL provides a flexible file storage abstraction that supports multiple bac
10811081
#### Using Local File Storage
10821082

10831083
```typescript
1084-
import { createNodeHandler, LocalFileStorage } from '@objectql/server';
1085-
import { ObjectQL } from '@objectql/core';
1086-
import * as http from 'http';
1087-
1088-
const app = new ObjectQL({ /* ... */ });
1089-
1090-
// Configure local file storage
1091-
const fileStorage = new LocalFileStorage({
1092-
baseDir: './uploads', // or process.env.OBJECTQL_UPLOAD_DIR
1093-
baseUrl: 'http://localhost:3000/api/files' // or process.env.OBJECTQL_BASE_URL
1094-
});
1095-
1096-
// Create HTTP handler with file storage
1097-
const handler = createNodeHandler(app, { fileStorage });
1084+
import { ObjectStackKernel } from '@objectstack/runtime';
1085+
import { HonoServerPlugin } from '@objectstack/plugin-hono-server';
1086+
import { ObjectQLPlugin } from '@objectql/core';
1087+
import { SqlDriver } from '@objectql/driver-sql';
1088+
1089+
const kernel = new ObjectStackKernel([
1090+
appConfig,
1091+
new SqlDriver({ client: 'sqlite3', connection: { filename: ':memory:' } }),
1092+
new ObjectQLPlugin(),
1093+
new HonoServerPlugin({
1094+
port: 3000,
1095+
fileStorage: {
1096+
type: 'local',
1097+
baseDir: './uploads',
1098+
baseUrl: 'http://localhost:3000/api/files'
1099+
}
1100+
})
1101+
]);
10981102

1099-
const server = http.createServer(handler);
1100-
server.listen(3000);
1103+
await kernel.start();
11011104
```
11021105

11031106
#### Using Memory Storage (For Testing)
11041107

11051108
```typescript
1106-
import { MemoryFileStorage } from '@objectql/server';
1107-
1108-
const fileStorage = new MemoryFileStorage({
1109-
baseUrl: 'http://localhost:3000/api/files'
1110-
});
1111-
1112-
const handler = createNodeHandler(app, { fileStorage });
1109+
const kernel = new ObjectStackKernel([
1110+
appConfig,
1111+
new SqlDriver({ client: 'sqlite3', connection: { filename: ':memory:' } }),
1112+
new ObjectQLPlugin(),
1113+
new HonoServerPlugin({
1114+
port: 3000,
1115+
fileStorage: {
1116+
type: 'memory',
1117+
baseUrl: 'http://localhost:3000/api/files'
1118+
}
1119+
})
1120+
]);
11131121
```
11141122

11151123
#### Custom Storage Implementation
11161124

11171125
You can implement custom storage backends by implementing the `IFileStorage` interface:
11181126

11191127
```typescript
1120-
import { IFileStorage, AttachmentData, FileStorageOptions } from '@objectql/server';
1128+
import { IFileStorage, AttachmentData, FileStorageOptions } from '@objectql/types';
11211129

11221130
class S3FileStorage implements IFileStorage {
11231131
async save(

content/docs/reference/api/custom-routes.mdx

Lines changed: 65 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,32 @@ By default, ObjectQL uses these API paths:
2626

2727
### Basic Usage
2828

29-
Configure custom routes when creating handlers:
29+
Configure custom routes when creating the Kernel with protocol plugins:
3030

3131
```typescript
32-
import { createNodeHandler, createRESTHandler, createMetadataHandler } from '@objectql/server';
33-
34-
// Define custom routes
35-
const customRoutes = {
36-
rpc: '/v1/rpc',
37-
data: '/v1/resources',
38-
metadata: '/v1/schema',
39-
files: '/v1/storage'
40-
};
41-
42-
// Create handlers with custom routes
43-
const nodeHandler = createNodeHandler(app, { routes: customRoutes });
44-
const restHandler = createRESTHandler(app, { routes: customRoutes });
45-
const metadataHandler = createMetadataHandler(app, { routes: customRoutes });
32+
import { ObjectStackKernel } from '@objectstack/runtime';
33+
import { HonoServerPlugin } from '@objectstack/plugin-hono-server';
34+
import { ObjectQLPlugin } from '@objectql/core';
35+
import { JSONRPCPlugin } from '@objectql/protocol-json-rpc';
36+
import { MemoryDriver } from '@objectql/driver-memory';
37+
38+
// Define custom routes via plugin configuration
39+
const kernel = new ObjectStackKernel([
40+
appConfig,
41+
new MemoryDriver(),
42+
new ObjectQLPlugin(),
43+
new JSONRPCPlugin({ basePath: '/v1/rpc' }),
44+
new HonoServerPlugin({
45+
port: 3000,
46+
routes: {
47+
data: '/v1/resources',
48+
metadata: '/v1/schema',
49+
files: '/v1/storage'
50+
}
51+
})
52+
]);
53+
54+
await kernel.start();
4655
```
4756

4857
### Route Configuration Interface
@@ -78,62 +87,55 @@ interface ApiRouteConfig {
7887
## Complete Example
7988

8089
```typescript
81-
import express from 'express';
82-
import { ObjectQL } from '@objectql/core';
90+
import { ObjectStackKernel } from '@objectstack/runtime';
91+
import { HonoServerPlugin } from '@objectstack/plugin-hono-server';
92+
import { ObjectQLPlugin } from '@objectql/core';
8393
import { SqlDriver } from '@objectql/driver-sql';
84-
import { createNodeHandler, createRESTHandler, createMetadataHandler } from '@objectql/server';
94+
import { JSONRPCPlugin } from '@objectql/protocol-json-rpc';
8595

8696
async function main() {
87-
// 1. Initialize ObjectQL
88-
const app = new ObjectQL({
89-
datasources: {
90-
default: new SqlDriver({
91-
client: 'sqlite3',
92-
connection: { filename: ':memory:' },
93-
useNullAsDefault: true
94-
})
95-
}
96-
});
97-
98-
// Register your objects
99-
app.registerObject({
100-
name: 'user',
101-
label: 'User',
102-
fields: {
103-
name: { type: 'text', label: 'Name' },
104-
email: { type: 'email', label: 'Email' }
97+
// 1. Define app configuration
98+
const appConfig = {
99+
name: 'my-app',
100+
objects: {
101+
user: {
102+
name: 'user',
103+
label: 'User',
104+
fields: {
105+
name: { type: 'text', label: 'Name' },
106+
email: { type: 'email', label: 'Email' }
107+
}
108+
}
105109
}
106-
});
107-
108-
await app.init();
109-
110-
// 2. Define custom API routes
111-
const customRoutes = {
112-
rpc: '/v1/rpc',
113-
data: '/v1/resources',
114-
metadata: '/v1/schema',
115-
files: '/v1/storage'
116110
};
117111

118-
// 3. Create handlers with custom routes
119-
const nodeHandler = createNodeHandler(app, { routes: customRoutes });
120-
const restHandler = createRESTHandler(app, { routes: customRoutes });
121-
const metadataHandler = createMetadataHandler(app, { routes: customRoutes });
122-
123-
// 4. Setup Express with custom paths
124-
const server = express();
112+
// 2. Create Kernel with custom route configuration
113+
const kernel = new ObjectStackKernel([
114+
appConfig,
115+
new SqlDriver({
116+
client: 'sqlite3',
117+
connection: { filename: ':memory:' },
118+
useNullAsDefault: true
119+
}),
120+
new ObjectQLPlugin(),
121+
new JSONRPCPlugin({ basePath: '/v1/rpc' }),
122+
new HonoServerPlugin({
123+
port: 3000,
124+
routes: {
125+
data: '/v1/resources',
126+
metadata: '/v1/schema',
127+
files: '/v1/storage'
128+
}
129+
})
130+
]);
125131

126-
server.all('/v1/rpc*', nodeHandler);
127-
server.all('/v1/resources/*', restHandler);
128-
server.all('/v1/schema*', metadataHandler);
132+
await kernel.start();
129133

130-
server.listen(3000, () => {
131-
console.log('🚀 Server running with custom routes');
132-
console.log(' JSON-RPC: http://localhost:3000/v1/rpc');
133-
console.log(' REST API: http://localhost:3000/v1/resources');
134-
console.log(' Metadata: http://localhost:3000/v1/schema');
135-
console.log(' Files: http://localhost:3000/v1/storage');
136-
});
134+
console.log('🚀 Server running with custom routes');
135+
console.log(' JSON-RPC: http://localhost:3000/v1/rpc');
136+
console.log(' REST API: http://localhost:3000/v1/resources');
137+
console.log(' Metadata: http://localhost:3000/v1/schema');
138+
console.log(' Files: http://localhost:3000/v1/storage');
137139
}
138140

139141
main().catch(console.error);

content/docs/reference/api/graphql.mdx

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ Both GET and POST methods are supported:
3232

3333
## Installation
3434

35-
The GraphQL adapter is included in `@objectql/server`:
35+
The GraphQL adapter is available as a protocol plugin `@objectql/protocol-graphql`:
3636

3737
```typescript
3838
import { ObjectStackKernel } from '@objectstack/runtime';
@@ -903,17 +903,24 @@ function UserList() {
903903
ObjectQL doesn't include GraphQL Playground by default, but you can easily add it:
904904

905905
```typescript
906-
import express from 'express';
907-
import { graphqlHTTP } from 'express-graphql';
908-
import { createGraphQLHandler, generateGraphQLSchema } from '@objectql/server';
906+
import { ObjectStackKernel } from '@objectstack/runtime';
907+
import { GraphQLPlugin } from '@objectql/protocol-graphql';
908+
import { ObjectQLPlugin } from '@objectql/core';
909+
import { MemoryDriver } from '@objectql/driver-memory';
910+
911+
const kernel = new ObjectStackKernel([
912+
appConfig,
913+
new MemoryDriver(),
914+
new ObjectQLPlugin(),
915+
new GraphQLPlugin({
916+
port: 4000,
917+
introspection: true
918+
})
919+
]);
909920

910-
const app = express();
911-
const schema = generateGraphQLSchema(objectQLApp);
921+
await kernel.start();
912922

913-
app.use('/api/graphql', graphqlHTTP({
914-
schema,
915-
graphiql: true // Enable GraphiQL interface
916-
}));
923+
// GraphQL Playground available via introspection endpoint
917924
```
918925

919926
## Postman

0 commit comments

Comments
 (0)