mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-24 22:04:56 +00:00
- Deleted all LuaScript CRUD operations from Client and entities. - Removed LuaScript validation functions and related files. - Updated InMemoryStore to remove LuaScript storage. - Cleaned up tests by removing LuaScript related test cases. - Adjusted documentation and quick start guide to reflect the removal of LuaScript functionality.
376 lines
8.5 KiB
Markdown
376 lines
8.5 KiB
Markdown
# DBAL Quick Start Guide
|
|
|
|
## What is Phase 2?
|
|
|
|
Phase 2 implements a complete, production-ready Database Abstraction Layer (DBAL) that:
|
|
- ✅ Works entirely in GitHub Spark (no external services needed)
|
|
- ✅ Provides ACL (access control) and audit logging
|
|
- ✅ Prepares for future C++ daemon integration
|
|
- ✅ Adds ~1ms overhead vs direct database access
|
|
- ✅ Type-safe, error-handled, fully documented
|
|
|
|
## Quick Start (5 minutes)
|
|
|
|
### 1. Install Dependencies
|
|
|
|
The DBAL uses Prisma, which is already installed in MetaBuilder:
|
|
```bash
|
|
# Already done - Prisma is in package.json
|
|
```
|
|
|
|
### 2. Import the DBAL Client
|
|
|
|
```typescript
|
|
import { getDBALClient } from '@/lib/dbal-client'
|
|
import type { User } from '@/lib/level-types'
|
|
|
|
// Get client (with or without user context)
|
|
const client = getDBALClient()
|
|
|
|
// Or with authentication (enables ACL)
|
|
const client = getDBALClient(currentUser, {
|
|
id: 'session_123',
|
|
token: 'abc'
|
|
})
|
|
```
|
|
|
|
### 3. Use CRUD Operations
|
|
|
|
```typescript
|
|
// Create
|
|
const user = await client.users.create({
|
|
username: 'alice',
|
|
email: 'alice@example.com',
|
|
role: 'user'
|
|
})
|
|
|
|
// Read
|
|
const foundUser = await client.users.read(user.id)
|
|
|
|
// Update
|
|
await client.users.update(user.id, {
|
|
email: 'alice.new@example.com'
|
|
})
|
|
|
|
// List with filters
|
|
const admins = await client.users.list({
|
|
filter: { role: 'admin' },
|
|
sort: { createdAt: 'desc' },
|
|
limit: 20
|
|
})
|
|
|
|
// Delete
|
|
await client.users.delete(user.id)
|
|
```
|
|
|
|
### 4. Handle Errors
|
|
|
|
```typescript
|
|
import { DBALError, DBALErrorCode } from '../../dbal/development/src'
|
|
|
|
try {
|
|
await client.users.read('nonexistent_id')
|
|
} catch (error) {
|
|
if (error instanceof DBALError) {
|
|
switch (error.code) {
|
|
case DBALErrorCode.NOT_FOUND:
|
|
toast.error('User not found')
|
|
break
|
|
case DBALErrorCode.FORBIDDEN:
|
|
toast.error('Access denied')
|
|
break
|
|
default:
|
|
toast.error('Database error')
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Key Features
|
|
|
|
### 🔒 Security (ACL)
|
|
|
|
Automatic role-based access control:
|
|
|
|
```typescript
|
|
// User with role 'user' can only read/update their own records
|
|
const client = getDBALClient(currentUser, session)
|
|
await client.users.update(currentUser.id, { email: 'new@example.com' }) // ✅ OK
|
|
await client.users.update(otherUser.id, { email: 'new@example.com' }) // ❌ Forbidden
|
|
|
|
// God/SuperGod can access all records
|
|
const client = getDBALClient(godUser, session)
|
|
await client.users.update(anyUser.id, { email: 'new@example.com' }) // ✅ OK
|
|
```
|
|
|
|
### 📝 Audit Logging
|
|
|
|
All operations are logged automatically:
|
|
|
|
```json
|
|
{
|
|
"timestamp": "2024-01-15T10:30:00.000Z",
|
|
"user": "alice",
|
|
"role": "admin",
|
|
"entity": "User",
|
|
"operation": "create",
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
Check browser console for `[DBAL Audit]` logs.
|
|
|
|
### 🎯 Type Safety
|
|
|
|
Full TypeScript support:
|
|
|
|
```typescript
|
|
import type { User, PageConfig, ComponentNode, Workflow, InstalledPackage, Session } from '../../dbal/development/src'
|
|
|
|
// Type-safe entities
|
|
const user: User = await client.users.create({ ... })
|
|
const page: PageConfig = await client.pageConfigs.create({ ... })
|
|
const component: ComponentNode = await client.componentNodes.create({ ... })
|
|
const workflow: Workflow = await client.workflows.create({ ... })
|
|
const pkg: InstalledPackage = await client.installedPackages.create({ ... })
|
|
const session: Session = await client.sessions.create({ ... })
|
|
|
|
// Type-safe list results
|
|
const result = await client.users.list()
|
|
const users: User[] = result.data
|
|
const total: number = result.total
|
|
const hasMore: boolean = result.hasMore
|
|
```
|
|
|
|
## Available Operations
|
|
|
|
### Users
|
|
```typescript
|
|
client.users.create(data)
|
|
client.users.read(id)
|
|
client.users.update(id, data)
|
|
client.users.delete(id)
|
|
client.users.list(options)
|
|
```
|
|
|
|
### Pages
|
|
```typescript
|
|
client.pageConfigs.create(data)
|
|
client.pageConfigs.read(id)
|
|
client.pageConfigs.readByPath(path) // Special: find by path
|
|
client.pageConfigs.update(id, data)
|
|
client.pageConfigs.delete(id)
|
|
client.pageConfigs.list(options)
|
|
```
|
|
|
|
### Components
|
|
```typescript
|
|
client.componentNodes.create(data)
|
|
client.componentNodes.read(id)
|
|
client.componentNodes.update(id, data)
|
|
client.componentNodes.delete(id)
|
|
client.componentNodes.getTree(pageId) // Special: get all components for a page
|
|
```
|
|
|
|
### Workflows
|
|
```typescript
|
|
client.workflows.create(data)
|
|
client.workflows.read(id)
|
|
client.workflows.update(id, data)
|
|
client.workflows.delete(id)
|
|
client.workflows.list(options)
|
|
```
|
|
|
|
### Packages
|
|
```typescript
|
|
client.installedPackages.create(data)
|
|
client.installedPackages.read(packageId)
|
|
client.installedPackages.update(packageId, data)
|
|
client.installedPackages.delete(packageId)
|
|
client.installedPackages.list(options)
|
|
```
|
|
|
|
### Sessions (system-only)
|
|
```typescript
|
|
client.sessions.create(data)
|
|
client.sessions.read(id)
|
|
client.sessions.update(id, data)
|
|
client.sessions.delete(id)
|
|
client.sessions.list(options)
|
|
```
|
|
|
|
## Common Patterns
|
|
|
|
### List with Pagination
|
|
|
|
```typescript
|
|
const result = await client.users.list({
|
|
filter: { role: 'admin' },
|
|
sort: { createdAt: 'desc' },
|
|
page: 1,
|
|
limit: 20
|
|
})
|
|
|
|
console.log(`Showing ${result.data.length} of ${result.total} users`)
|
|
if (result.hasMore) {
|
|
console.log('More results available')
|
|
}
|
|
```
|
|
|
|
### Conditional ACL
|
|
|
|
```typescript
|
|
// Disable ACL for system operations
|
|
const systemClient = getDBALClient() // No user context
|
|
|
|
// Enable ACL for user operations
|
|
const userClient = getDBALClient(currentUser, session)
|
|
```
|
|
|
|
### Check Capabilities
|
|
|
|
```typescript
|
|
const capabilities = await client.capabilities()
|
|
if (capabilities.transactions) {
|
|
// Use transactions
|
|
}
|
|
if (capabilities.fullTextSearch) {
|
|
// Use full-text search
|
|
}
|
|
```
|
|
|
|
## Migration from Current Code
|
|
|
|
### Before (Direct Database)
|
|
|
|
```typescript
|
|
import { Database } from '@/lib/database'
|
|
|
|
const users = await Database.getUsers()
|
|
const user = await Database.getUserById(id)
|
|
await Database.addUser(newUser)
|
|
await Database.updateUser(id, updates)
|
|
await Database.deleteUser(id)
|
|
```
|
|
|
|
### After (DBAL)
|
|
|
|
```typescript
|
|
import { getDBALClient } from '@/lib/dbal-client'
|
|
|
|
const client = getDBALClient()
|
|
const result = await client.users.list()
|
|
const users = result.data
|
|
const user = await client.users.read(id)
|
|
await client.users.create(newUser)
|
|
await client.users.update(id, updates)
|
|
await client.users.delete(id)
|
|
```
|
|
|
|
## Configuration
|
|
|
|
### Development Mode (default)
|
|
|
|
```typescript
|
|
const client = new DBALClient({
|
|
mode: 'development', // Direct database access
|
|
adapter: 'prisma',
|
|
auth: { user, session },
|
|
security: {
|
|
sandbox: 'strict', // Enable ACL
|
|
enableAuditLog: true // Enable logging
|
|
}
|
|
})
|
|
```
|
|
|
|
### Production Mode (future)
|
|
|
|
```typescript
|
|
const client = new DBALClient({
|
|
mode: 'production', // Connect to C++ daemon
|
|
endpoint: 'wss://daemon.example.com:50051',
|
|
auth: { user, session },
|
|
security: {
|
|
sandbox: 'strict',
|
|
enableAuditLog: true
|
|
}
|
|
})
|
|
```
|
|
|
|
## Performance
|
|
|
|
| Operation | Time | Notes |
|
|
|-----------|------|-------|
|
|
| Create | ~3ms | +0.5ms ACL overhead |
|
|
| Read | ~2.5ms | +0.5ms ACL overhead |
|
|
| Update | ~3ms | +1ms (ACL check + audit) |
|
|
| Delete | ~2.5ms | +1ms (ACL check + audit) |
|
|
| List (20) | ~5ms | +0.5ms ACL overhead |
|
|
|
|
**Total overhead: ~0.5-1ms per operation**
|
|
|
|
## Troubleshooting
|
|
|
|
### "Entity not found" error
|
|
|
|
The entity name must match the Prisma model name:
|
|
```typescript
|
|
// ✅ Correct
|
|
await client.users.create(...) // Maps to User model
|
|
|
|
// ❌ Wrong
|
|
await client.Users.create(...) // Capital U won't work
|
|
```
|
|
|
|
### ACL denies operation
|
|
|
|
Check user role and entity permissions:
|
|
```typescript
|
|
// User role 'user' cannot create other users
|
|
const client = getDBALClient(regularUser, session)
|
|
await client.users.create({ ... }) // ❌ Forbidden
|
|
|
|
// But can update their own record
|
|
await client.users.update(regularUser.id, { ... }) // ✅ OK
|
|
```
|
|
|
|
### Timeout errors
|
|
|
|
Increase query timeout:
|
|
```typescript
|
|
const client = new DBALClient({
|
|
mode: 'development',
|
|
adapter: 'prisma',
|
|
performance: {
|
|
queryTimeout: 60000 // 60 seconds
|
|
}
|
|
})
|
|
```
|
|
|
|
## Next Steps
|
|
|
|
1. **Try it out**: Use DBAL in a new component
|
|
2. **Migrate gradually**: Replace Database calls one at a time
|
|
3. **Monitor logs**: Check browser console for audit logs
|
|
4. **Test ACL**: Try operations with different user roles
|
|
5. **Read docs**: See `PHASE2_IMPLEMENTATION.md` for details
|
|
|
|
## Need Help?
|
|
|
|
- 📖 Full docs: `dbal/PHASE2_IMPLEMENTATION.md`
|
|
- 🏗️ Architecture: `dbal/README.md`
|
|
- 🚀 Future: `dbal/production/PHASE3_DAEMON.md`
|
|
- 🤖 AI Agent guide: `dbal/AGENTS.md`
|
|
|
|
## Summary
|
|
|
|
Phase 2 DBAL is **ready to use** right now in MetaBuilder:
|
|
- ✅ Complete TypeScript implementation
|
|
- ✅ ACL and audit logging
|
|
- ✅ Type-safe APIs
|
|
- ✅ Minimal overhead
|
|
- ✅ GitHub Spark compatible
|
|
- ✅ Prepares for Phase 3 C++ daemon
|
|
|
|
**Just import, use, and enjoy!** 🎉
|