Skip to content

Commit 75922f8

Browse files
authored
Merge pull request #434 from objectstack-ai/copilot/upgrade-objectstack-client
2 parents 28150a9 + 771fd19 commit 75922f8

18 files changed

Lines changed: 519 additions & 228 deletions

File tree

OBJECTSTACK_CLIENT_EVALUATION.md

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# @objectstack/client Evaluation for Low-Code App UI Development
22

33
> **Date:** February 10, 2026
4-
> **Spec Version:** @objectstack/spec v2.0.1
5-
> **Client Version:** @objectstack/client v2.0.1
4+
> **Spec Version:** @objectstack/spec v2.0.4
5+
> **Client Version:** @objectstack/client v2.0.4
6+
> **Auth Plugin Version:** @objectstack/plugin-auth v2.0.3
67
> **ObjectUI Version:** v0.5.x
78
> **Scope:** Evaluate whether @objectstack/client can fully support developing a complete low-code application UI based on the @objectstack/spec protocol
89
@@ -104,6 +105,7 @@ The @objectstack/spec defines `ActionSchema` with 5 action types:
104105

105106
| Capability | Implementation | Client Dependency | Status |
106107
|------------|---------------|-------------------|--------|
108+
| **Server-Side Auth** | `@objectstack/plugin-auth` (AuthPlugin) | ObjectKernel plugin | ✅ Complete |
107109
| **Token Authentication** | `ObjectStackAdapter({ token })` | Client constructor | ✅ Complete |
108110
| **Dynamic Token Injection** | `ObjectStackAdapter({ fetch })` | Custom fetch wrapper | ✅ Complete |
109111
| **Session Management** | `@object-ui/auth` (AuthProvider) | better-auth integration | ✅ Complete |
@@ -114,7 +116,7 @@ The @objectstack/spec defines `ActionSchema` with 5 action types:
114116
| **OAuth/SSO** | better-auth plugins | External auth providers | ✅ Complete |
115117
| **Multi-Factor Auth** | better-auth 2FA plugin | External auth providers | ✅ Available |
116118

117-
**Auth Assessment: 100% — Full auth stack is implemented via @object-ui/auth + better-auth.**
119+
**Auth Assessment: 100% — Full auth stack is implemented. Server-side via @objectstack/plugin-auth (better-auth powered, ObjectQL persistence). Client-side via @object-ui/auth + better-auth.**
118120

119121
### 2.6 Multi-Tenancy
120122

@@ -170,6 +172,19 @@ A complete low-code app built on @objectstack/spec follows this data flow:
170172
│ │ │
171173
│ ▼ │
172174
│ ┌──────────────────────────────────────────────────────────────┐ │
175+
│ │ ObjectStack Server │ │
176+
│ │ │ │
177+
│ │ ObjectKernel │ │
178+
│ │ ├── ObjectQLPlugin (query engine) │ │
179+
│ │ ├── DriverPlugin (data storage) │ │
180+
│ │ ├── AuthPlugin (@objectstack/plugin-auth) │ │
181+
│ │ │ └── better-auth (session, OAuth, 2FA, passkeys) │ │
182+
│ │ ├── HonoServerPlugin (HTTP /api/v1/*) │ │
183+
│ │ └── AppPlugin (stack config) │ │
184+
│ └──────────────────────────────────────────────────────────────┘ │
185+
│ │ │
186+
│ ▼ │
187+
│ ┌──────────────────────────────────────────────────────────────┐ │
173188
│ │ ObjectUI Runtime │ │
174189
│ │ │ │
175190
│ │ AuthProvider → PermissionProvider → TenantProvider │ │
@@ -208,7 +223,7 @@ A complete low-code app built on @objectstack/spec follows this data flow:
208223
| **Validation Rules** | `Data.Validation` | Server + client-side | `@object-ui/core` | ✅ Yes |
209224
| **Permissions/RBAC** | `Security.RBAC` | Role data from server | `@object-ui/permissions` | ✅ Yes |
210225
| **Multi-Tenancy** | `System.Tenant` | X-Tenant-ID header | `@object-ui/tenant` | ✅ Yes |
211-
| **Authentication** | `Identity.Auth` | Token via custom fetch | `@object-ui/auth` | ✅ Yes |
226+
| **Authentication** | `Identity.Auth` | Token via custom fetch | `@object-ui/auth` + `@objectstack/plugin-auth` | ✅ Yes |
212227
| **i18n** | `Shared.i18n` | None (client-side) | `@object-ui/i18n` | ✅ Yes |
213228
| **Theming** | `UI.Theme` | None (client-side) | Theme Provider | ✅ Yes |
214229
| **AI Assistance** | `AI.Config` | AI API endpoints | `plugin-ai` | ✅ Yes |
@@ -291,7 +306,49 @@ export default defineStack({
291306
});
292307
```
293308

294-
### 5.2 Runtime Initialization
309+
### 5.2 Server-Side Setup (with @objectstack/plugin-auth)
310+
311+
```typescript
312+
// server.ts — Bootstrap the ObjectStack server with authentication
313+
import { ObjectKernel } from '@objectstack/core';
314+
import { ObjectQLPlugin } from '@objectstack/objectql';
315+
import { AppPlugin, DriverPlugin } from '@objectstack/runtime';
316+
import { HonoServerPlugin } from '@objectstack/plugin-hono-server';
317+
import { InMemoryDriver } from '@objectstack/driver-memory';
318+
import { AuthPlugin } from '@objectstack/plugin-auth';
319+
import config from './objectstack.config';
320+
321+
async function startServer() {
322+
const kernel = new ObjectKernel();
323+
324+
// Core engine + data driver
325+
await kernel.use(new ObjectQLPlugin());
326+
await kernel.use(new DriverPlugin(new InMemoryDriver()));
327+
328+
// Application stack
329+
await kernel.use(new AppPlugin(config));
330+
331+
// Authentication via @objectstack/plugin-auth
332+
// Provides /api/v1/auth/* endpoints (sign-in, sign-up, session, OAuth, 2FA, etc.)
333+
await kernel.use(new AuthPlugin({
334+
secret: process.env.AUTH_SECRET || 'dev-secret',
335+
baseUrl: 'http://localhost:3000',
336+
providers: [
337+
// Optional: OAuth providers
338+
// { id: 'google', clientId: '...', clientSecret: '...' },
339+
],
340+
}));
341+
342+
// HTTP server
343+
await kernel.use(new HonoServerPlugin({ port: 3000 }));
344+
345+
await kernel.bootstrap();
346+
}
347+
348+
startServer();
349+
```
350+
351+
### 5.3 Runtime Initialization
295352

296353
```typescript
297354
// App.tsx — Bootstrap the low-code runtime
@@ -312,7 +369,7 @@ function App() {
312369
});
313370

314371
return (
315-
<AuthProvider authUrl="/api/auth">
372+
<AuthProvider authUrl="/api/v1/auth">
316373
<TenantProvider>
317374
<PermissionProvider>
318375
<SchemaRenderer
@@ -326,7 +383,7 @@ function App() {
326383
}
327384
```
328385

329-
### 5.3 Object Definition
386+
### 5.4 Object Definition
330387

331388
```typescript
332389
// objects/task.object.ts — Spec-compliant object definition
@@ -382,7 +439,7 @@ export const TaskObject = ObjectSchema.create({
382439
The combination provides:
383440
- **Data Layer**: Complete CRUD, bulk ops, metadata, and caching via ObjectStackAdapter
384441
- **UI Layer**: 35 packages, 91+ components, 13+ view types covering all spec requirements
385-
- **Security**: Auth, RBAC, field/row-level permissions, multi-tenancy
442+
- **Security**: Server-side auth via @objectstack/plugin-auth, client-side via @object-ui/auth, RBAC, field/row-level permissions, multi-tenancy
386443
- **Developer Experience**: TypeScript-first, Shadcn design quality, expression engine
387444
- **Extensibility**: Plugin system, custom widgets, theme customization
388445

apps/console/package.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,19 @@
5050
"@object-ui/plugin-view": "workspace:*",
5151
"@object-ui/react": "workspace:*",
5252
"@object-ui/types": "workspace:*",
53-
"@objectstack/client": "^2.0.1",
54-
"@objectstack/driver-memory": "^2.0.1",
55-
"@objectstack/objectql": "^2.0.1",
56-
"@objectstack/plugin-msw": "^2.0.1",
57-
"@objectstack/runtime": "^2.0.1",
58-
"@objectstack/spec": "^2.0.1",
53+
"@objectstack/client": "^2.0.4",
54+
"@objectstack/driver-memory": "^2.0.4",
55+
"@objectstack/objectql": "^2.0.4",
56+
"@objectstack/plugin-msw": "^2.0.4",
57+
"@objectstack/runtime": "^2.0.4",
58+
"@objectstack/spec": "^2.0.4",
5959
"lucide-react": "^0.563.0",
6060
"react": "^19.2.4",
6161
"react-dom": "^19.2.4",
6262
"react-router-dom": "^7.13.0"
6363
},
6464
"devDependencies": {
65-
"@objectstack/cli": "^2.0.1",
65+
"@objectstack/cli": "^2.0.4",
6666
"@tailwindcss/postcss": "^4.1.18",
6767
"@testing-library/jest-dom": "^6.6.3",
6868
"@testing-library/react": "^16.1.0",

apps/console/vite.config.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ export default defineConfig({
7373
transformMixedEsModules: true
7474
},
7575
rollupOptions: {
76+
// @objectstack/core@2.0.4 statically imports Node.js crypto (for plugin hashing).
77+
// The code already has a browser fallback, so we treat it as external in the browser build.
78+
external: ['crypto'],
79+
output: {
80+
globals: {
81+
crypto: '{}',
82+
},
83+
},
7684
onwarn(warning, warn) {
7785
if (
7886
warning.code === 'UNRESOLVED_IMPORT' &&

examples/crm/package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,14 @@
1515
"start": "tsx server.ts"
1616
},
1717
"dependencies": {
18-
"@objectstack/core": "^2.0.1",
19-
"@objectstack/runtime": "^2.0.1",
20-
"@objectstack/spec": "^2.0.1",
18+
"@objectstack/core": "^2.0.4",
19+
"@objectstack/plugin-auth": "^2.0.3",
20+
"@objectstack/runtime": "^2.0.4",
21+
"@objectstack/spec": "^2.0.4",
2122
"pino": "^8.21.0"
2223
},
2324
"devDependencies": {
24-
"@objectstack/cli": "^2.0.1",
25+
"@objectstack/cli": "^2.0.4",
2526
"typescript": "^5.0.0"
2627
}
2728
}

examples/crm/server.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { ObjectQLPlugin } from '@objectstack/objectql';
44
import { AppPlugin, DriverPlugin } from '@objectstack/runtime';
55
import { HonoServerPlugin } from '@objectstack/plugin-hono-server';
66
import { InMemoryDriver } from '@objectstack/driver-memory';
7+
import { AuthPlugin } from '@objectstack/plugin-auth';
78
import config from './objectstack.config';
89
import { pino } from 'pino';
910
import { ConsolePlugin } from './console-plugin';
@@ -42,11 +43,19 @@ async function startServer() {
4243
const appPlugin = new AppPlugin(config);
4344
await kernel.use(appPlugin);
4445

45-
// 4. HTTP Server
46+
// 4. Authentication (via @objectstack/plugin-auth)
47+
// NOTE: In production, always set AUTH_SECRET env var. The fallback is for local development only.
48+
const authPlugin = new AuthPlugin({
49+
secret: process.env.AUTH_SECRET || 'objectui-dev-secret',
50+
baseUrl: 'http://localhost:3000',
51+
});
52+
await kernel.use(authPlugin);
53+
54+
// 5. HTTP Server
4655
const serverPlugin = new HonoServerPlugin({ port: 3000 });
4756
await kernel.use(serverPlugin);
4857

49-
// 5. Console Plugin
58+
// 6. Console Plugin
5059
const consolePlugin = new ConsolePlugin();
5160
await kernel.use(consolePlugin);
5261

examples/kitchen-sink/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414
"build": "objectstack compile objectstack.config.ts"
1515
},
1616
"dependencies": {
17-
"@objectstack/spec": "^2.0.1"
17+
"@objectstack/spec": "^2.0.4"
1818
},
1919
"devDependencies": {
20-
"@objectstack/cli": "^2.0.1",
20+
"@objectstack/cli": "^2.0.4",
2121
"typescript": "^5.0.0"
2222
}
2323
}

examples/msw-todo/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
},
1212
"dependencies": {
1313
"@object-ui/example-todo": "workspace:*",
14-
"@objectstack/client": "^2.0.1",
15-
"@objectstack/driver-memory": "^2.0.1",
16-
"@objectstack/objectql": "^2.0.1",
17-
"@objectstack/plugin-msw": "^2.0.1",
18-
"@objectstack/runtime": "^2.0.1",
19-
"@objectstack/spec": "^2.0.1",
14+
"@objectstack/client": "^2.0.4",
15+
"@objectstack/driver-memory": "^2.0.4",
16+
"@objectstack/objectql": "^2.0.4",
17+
"@objectstack/plugin-msw": "^2.0.4",
18+
"@objectstack/runtime": "^2.0.4",
19+
"@objectstack/spec": "^2.0.4",
2020
"react": "^18.3.1",
2121
"react-dom": "^18.3.1"
2222
},

examples/msw-todo/vite.config.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,15 @@ export default defineConfig({
3535
return;
3636
}
3737
warn(warning);
38-
}
38+
},
39+
// @objectstack/core@2.0.4 statically imports Node.js crypto (for plugin hashing).
40+
// The code already has a browser fallback, so we treat it as external in the browser build.
41+
external: ['crypto'],
42+
output: {
43+
globals: {
44+
crypto: '{}',
45+
},
46+
},
3947
}
4048
}
4149
});

examples/todo/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212
"build": "objectstack compile objectstack.config.ts"
1313
},
1414
"dependencies": {
15-
"@objectstack/client": "^2.0.1",
16-
"@objectstack/spec": "^2.0.1"
15+
"@objectstack/client": "^2.0.4",
16+
"@objectstack/spec": "^2.0.4"
1717
},
1818
"devDependencies": {
19-
"@objectstack/cli": "^2.0.1",
19+
"@objectstack/cli": "^2.0.4",
2020
"typescript": "^5.0.0"
2121
}
2222
}

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,13 @@
7171
"devDependencies": {
7272
"@changesets/cli": "^2.29.8",
7373
"@eslint/js": "^9.39.1",
74-
"@objectstack/cli": "^2.0.1",
75-
"@objectstack/core": "^2.0.1",
76-
"@objectstack/driver-memory": "^2.0.1",
77-
"@objectstack/objectql": "^2.0.1",
78-
"@objectstack/plugin-msw": "^2.0.1",
79-
"@objectstack/runtime": "^2.0.1",
80-
"@objectstack/spec": "^2.0.1",
74+
"@objectstack/cli": "^2.0.4",
75+
"@objectstack/core": "^2.0.4",
76+
"@objectstack/driver-memory": "^2.0.4",
77+
"@objectstack/objectql": "^2.0.4",
78+
"@objectstack/plugin-msw": "^2.0.4",
79+
"@objectstack/runtime": "^2.0.4",
80+
"@objectstack/spec": "^2.0.4",
8181
"@storybook/addon-essentials": "^8.6.14",
8282
"@storybook/addon-interactions": "^8.6.14",
8383
"@storybook/addon-links": "^8.6.15",
@@ -131,7 +131,7 @@
131131
},
132132
"dependencies": {
133133
"@hono/node-server": "^1.19.9",
134-
"@objectstack/plugin-hono-server": "^2.0.1",
134+
"@objectstack/plugin-hono-server": "^2.0.4",
135135
"coverage-v8": "0.0.1-security",
136136
"hono": "^4.11.9",
137137
"pino": "^8.21.0",

0 commit comments

Comments
 (0)