|
| 1 | +--- |
| 2 | +title: Development & Extension |
| 3 | +description: Extend ObjectStack with plugins, custom widgets, and drivers to build powerful business applications. |
| 4 | +--- |
| 5 | + |
| 6 | +# Development & Extension |
| 7 | + |
| 8 | +ObjectStack is designed for **extensibility at every layer**. Whether you're building a custom field widget, integrating a third-party API, or creating an entirely new database driver, the platform provides clean interfaces and powerful abstractions. |
| 9 | + |
| 10 | +## 🎯 What You Can Extend |
| 11 | + |
| 12 | +<Cards> |
| 13 | + <Card icon="plug" title="Plugins" href="/docs/03-development/writing-plugins"> |
| 14 | + Add new objects, routes, scheduled jobs, and business logic |
| 15 | + </Card> |
| 16 | + |
| 17 | + <Card icon="component" title="Custom Widgets" href="/docs/03-development/custom-widgets"> |
| 18 | + Build React/Vue components for custom field rendering |
| 19 | + </Card> |
| 20 | + |
| 21 | + <Card icon="database" title="Drivers" href="/docs/03-development/server-drivers"> |
| 22 | + Connect to any database or data source (SQL, NoSQL, APIs) |
| 23 | + </Card> |
| 24 | + |
| 25 | + <Card icon="terminal" title="CLI Tools" href="/docs/03-development/cli-tools"> |
| 26 | + Manage projects, generate code, and deploy with objectstack-cli |
| 27 | + </Card> |
| 28 | +</Cards> |
| 29 | + |
| 30 | +--- |
| 31 | + |
| 32 | +## 📐 Architecture Overview |
| 33 | + |
| 34 | +ObjectStack follows a **layered, protocol-driven architecture**: |
| 35 | + |
| 36 | +``` |
| 37 | +┌─────────────────────────────────────────┐ |
| 38 | +│ Your Application Code │ |
| 39 | +│ (Objects, Flows, Views, Plugins) │ |
| 40 | +├─────────────────────────────────────────┤ |
| 41 | +│ ObjectStack Kernel │ |
| 42 | +│ • Plugin System • Event Bus │ |
| 43 | +│ • Lifecycle Mgmt • Dependency DI │ |
| 44 | +├─────────────────────────────────────────┤ |
| 45 | +│ Protocol Layer │ |
| 46 | +│ • ObjectQL • ObjectUI • ObjectOS │ |
| 47 | +├─────────────────────────────────────────┤ |
| 48 | +│ Driver Layer │ |
| 49 | +│ • PostgreSQL • MongoDB • Redis │ |
| 50 | +│ • MySQL • Memory • Custom │ |
| 51 | +└─────────────────────────────────────────┘ |
| 52 | +``` |
| 53 | + |
| 54 | +### Key Principles |
| 55 | + |
| 56 | +1. **Everything is Metadata** - Define structure declaratively, execute dynamically |
| 57 | +2. **Zod-First Design** - All schemas are validated at runtime and compile-time |
| 58 | +3. **Protocol Contracts** - Strict interfaces ensure interoperability |
| 59 | +4. **Local-First** - Own your data, run anywhere |
| 60 | + |
| 61 | +--- |
| 62 | + |
| 63 | +## 🚀 Quick Start Paths |
| 64 | + |
| 65 | +### For Frontend Developers |
| 66 | + |
| 67 | +Start with **Custom Widgets** to enhance the UI layer: |
| 68 | + |
| 69 | +```bash |
| 70 | +npm create @objectstack/widget my-rich-editor |
| 71 | +cd my-rich-editor |
| 72 | +npm install |
| 73 | +npm run dev |
| 74 | +``` |
| 75 | + |
| 76 | +Build React/Vue components that integrate seamlessly with ObjectStack forms and views. |
| 77 | + |
| 78 | +[→ Custom Widgets Guide](/docs/03-development/custom-widgets) |
| 79 | + |
| 80 | +--- |
| 81 | + |
| 82 | +### For Backend Developers |
| 83 | + |
| 84 | +Start with **Plugins** to add business logic: |
| 85 | + |
| 86 | +```bash |
| 87 | +npm create @objectstack/plugin my-api-integration |
| 88 | +cd my-api-integration |
| 89 | +npm install |
| 90 | +npm run build |
| 91 | +``` |
| 92 | + |
| 93 | +Create custom Objects, API routes, scheduled jobs, and event listeners. |
| 94 | + |
| 95 | +[→ Plugin Development Guide](/docs/03-development/writing-plugins) |
| 96 | + |
| 97 | +--- |
| 98 | + |
| 99 | +### For Database Engineers |
| 100 | + |
| 101 | +Start with **Drivers** to connect new data sources: |
| 102 | + |
| 103 | +```bash |
| 104 | +npm create @objectstack/driver my-custom-db |
| 105 | +cd my-custom-db |
| 106 | +npm install |
| 107 | +npm run build |
| 108 | +``` |
| 109 | + |
| 110 | +Implement the `DriverInterface` to bridge ObjectQL with any database. |
| 111 | + |
| 112 | +[→ Driver Development Guide](/docs/03-development/server-drivers) |
| 113 | + |
| 114 | +--- |
| 115 | + |
| 116 | +## 🛠️ Development Workflow |
| 117 | + |
| 118 | +### 1. Project Initialization |
| 119 | + |
| 120 | +```bash |
| 121 | +# Create a new ObjectStack project |
| 122 | +npx @objectstack/cli init my-project |
| 123 | + |
| 124 | +# Or add to existing project |
| 125 | +npm install @objectstack/spec @objectstack/kernel |
| 126 | +``` |
| 127 | + |
| 128 | +### 2. Define Metadata |
| 129 | + |
| 130 | +All ObjectStack resources are defined as **TypeScript files** using Zod schemas: |
| 131 | + |
| 132 | +```typescript |
| 133 | +// src/objects/task.object.ts |
| 134 | +import { ObjectSchema, Field } from '@objectstack/spec'; |
| 135 | + |
| 136 | +export const Task = ObjectSchema.create({ |
| 137 | + name: 'task', |
| 138 | + label: 'Task', |
| 139 | + fields: { |
| 140 | + title: Field.text({ label: 'Title', required: true }), |
| 141 | + status: Field.select({ |
| 142 | + label: 'Status', |
| 143 | + options: [ |
| 144 | + { label: 'To Do', value: 'todo' }, |
| 145 | + { label: 'Done', value: 'done' }, |
| 146 | + ], |
| 147 | + }), |
| 148 | + }, |
| 149 | +}); |
| 150 | +``` |
| 151 | + |
| 152 | +### 3. Build & Deploy |
| 153 | + |
| 154 | +```bash |
| 155 | +# Validate schemas |
| 156 | +npm run validate |
| 157 | + |
| 158 | +# Build for production |
| 159 | +npm run build |
| 160 | + |
| 161 | +# Deploy to ObjectStack Cloud or self-hosted |
| 162 | +objectstack deploy |
| 163 | +``` |
| 164 | + |
| 165 | +--- |
| 166 | + |
| 167 | +## 📦 Extension Types Compared |
| 168 | + |
| 169 | +| Extension Type | Use Case | Language | Runtime | |
| 170 | +|----------------|----------|----------|---------| |
| 171 | +| **Plugin** | Add objects, routes, jobs, logic | TypeScript/JavaScript | Server | |
| 172 | +| **Widget** | Custom field rendering | React, Vue, Svelte | Browser | |
| 173 | +| **Driver** | Database connectivity | TypeScript/JavaScript | Server | |
| 174 | +| **Flow Action** | Custom automation steps | TypeScript/JavaScript | Server | |
| 175 | +| **API Adapter** | External service integration | TypeScript/JavaScript | Server | |
| 176 | + |
| 177 | +--- |
| 178 | + |
| 179 | +## 🎓 Learning Resources |
| 180 | + |
| 181 | +<Steps> |
| 182 | + |
| 183 | +<Step> |
| 184 | +### Understand the Core Protocols |
| 185 | + |
| 186 | +Before building extensions, familiarize yourself with the three core protocols: |
| 187 | + |
| 188 | +- [ObjectQL](/docs/02-protocols/01-objectql) - Data modeling and queries |
| 189 | +- [ObjectUI](/docs/02-protocols/02-objectui) - User interface definitions |
| 190 | +- [ObjectOS](/docs/02-protocols/03-objectos) - System runtime and plugin architecture |
| 191 | + |
| 192 | +</Step> |
| 193 | + |
| 194 | +<Step> |
| 195 | +### Study Examples |
| 196 | + |
| 197 | +Explore reference implementations: |
| 198 | + |
| 199 | +- `examples/plugin-crm` - Full-featured CRM plugin |
| 200 | +- `examples/widget-rich-text` - Custom WYSIWYG editor widget |
| 201 | +- `examples/driver-mongodb` - MongoDB driver implementation |
| 202 | +- `examples/flow-action-email` - Email sending flow action |
| 203 | + |
| 204 | +</Step> |
| 205 | + |
| 206 | +<Step> |
| 207 | +### Build Your Extension |
| 208 | + |
| 209 | +Follow the step-by-step guides for your extension type: |
| 210 | + |
| 211 | +1. [Writing Plugins](/docs/03-development/writing-plugins) |
| 212 | +2. [Custom Widgets](/docs/03-development/custom-widgets) |
| 213 | +3. [Server Drivers](/docs/03-development/server-drivers) |
| 214 | +4. [CLI Tools](/docs/03-development/cli-tools) |
| 215 | + |
| 216 | +</Step> |
| 217 | + |
| 218 | +</Steps> |
| 219 | + |
| 220 | +--- |
| 221 | + |
| 222 | +## 🔐 Security & Best Practices |
| 223 | + |
| 224 | +### Input Validation |
| 225 | + |
| 226 | +Always validate user input using Zod schemas: |
| 227 | + |
| 228 | +```typescript |
| 229 | +import { z } from 'zod'; |
| 230 | + |
| 231 | +const CreateTaskSchema = z.object({ |
| 232 | + title: z.string().min(1).max(200), |
| 233 | + priority: z.enum(['low', 'medium', 'high']), |
| 234 | +}); |
| 235 | + |
| 236 | +// In your plugin |
| 237 | +export default { |
| 238 | + onEnable: async (context) => { |
| 239 | + context.router.post('/api/tasks', async (req, res) => { |
| 240 | + const data = CreateTaskSchema.parse(req.body); // Throws if invalid |
| 241 | + // Safe to use data... |
| 242 | + }); |
| 243 | + }, |
| 244 | +}; |
| 245 | +``` |
| 246 | + |
| 247 | +### Permission Checks |
| 248 | + |
| 249 | +Enforce access control using ObjectStack's permission system: |
| 250 | + |
| 251 | +```typescript |
| 252 | +// Check object-level permissions |
| 253 | +const canCreate = await context.os.checkPermission('task', 'create'); |
| 254 | + |
| 255 | +// Check field-level permissions |
| 256 | +const canEditStatus = await context.os.checkFieldPermission( |
| 257 | + 'task', |
| 258 | + 'status', |
| 259 | + 'edit' |
| 260 | +); |
| 261 | +``` |
| 262 | + |
| 263 | +### Error Handling |
| 264 | + |
| 265 | +Use structured error responses: |
| 266 | + |
| 267 | +```typescript |
| 268 | +import { ObjectStackError } from '@objectstack/kernel'; |
| 269 | + |
| 270 | +throw new ObjectStackError('VALIDATION_ERROR', { |
| 271 | + message: 'Invalid task status', |
| 272 | + field: 'status', |
| 273 | + code: 'INVALID_STATUS', |
| 274 | +}); |
| 275 | +``` |
| 276 | + |
| 277 | +--- |
| 278 | + |
| 279 | +## 🧪 Testing Your Extensions |
| 280 | + |
| 281 | +### Unit Testing |
| 282 | + |
| 283 | +Test your business logic in isolation: |
| 284 | + |
| 285 | +```typescript |
| 286 | +import { describe, it, expect } from 'vitest'; |
| 287 | +import { validateTask } from './validators'; |
| 288 | + |
| 289 | +describe('Task Validation', () => { |
| 290 | + it('should reject empty titles', () => { |
| 291 | + expect(() => validateTask({ title: '' })).toThrow(); |
| 292 | + }); |
| 293 | +}); |
| 294 | +``` |
| 295 | + |
| 296 | +### Integration Testing |
| 297 | + |
| 298 | +Test against a real ObjectStack runtime: |
| 299 | + |
| 300 | +```typescript |
| 301 | +import { createTestContext } from '@objectstack/testing'; |
| 302 | + |
| 303 | +const context = await createTestContext({ |
| 304 | + plugins: ['./my-plugin'], |
| 305 | +}); |
| 306 | + |
| 307 | +const result = await context.ql.object('task').create({ |
| 308 | + title: 'Test Task', |
| 309 | +}); |
| 310 | + |
| 311 | +expect(result.id).toBeDefined(); |
| 312 | +``` |
| 313 | + |
| 314 | +--- |
| 315 | + |
| 316 | +## 🌍 Publishing Extensions |
| 317 | + |
| 318 | +### NPM Packages |
| 319 | + |
| 320 | +Publish plugins and drivers as npm packages: |
| 321 | + |
| 322 | +```json |
| 323 | +{ |
| 324 | + "name": "@mycompany/objectstack-plugin-crm", |
| 325 | + "version": "1.0.0", |
| 326 | + "keywords": ["objectstack", "plugin", "crm"], |
| 327 | + "objectstack": { |
| 328 | + "type": "plugin", |
| 329 | + "entry": "./dist/index.js" |
| 330 | + } |
| 331 | +} |
| 332 | +``` |
| 333 | + |
| 334 | +### ObjectStack Hub |
| 335 | + |
| 336 | +Submit your extension to the official marketplace: |
| 337 | + |
| 338 | +```bash |
| 339 | +objectstack publish --registry hub.objectstack.dev |
| 340 | +``` |
| 341 | + |
| 342 | +--- |
| 343 | + |
| 344 | +## 📚 Next Steps |
| 345 | + |
| 346 | +<Cards> |
| 347 | + <Card icon="book" title="API Reference" href="/docs/99-reference"> |
| 348 | + Complete API documentation for all protocols |
| 349 | + </Card> |
| 350 | + |
| 351 | + <Card icon="code" title="Examples" href="https://github.com/objectstack/examples"> |
| 352 | + Production-ready example projects |
| 353 | + </Card> |
| 354 | + |
| 355 | + <Card icon="message-circle" title="Community" href="https://discord.gg/objectstack"> |
| 356 | + Get help from the community |
| 357 | + </Card> |
| 358 | +</Cards> |
| 359 | + |
| 360 | +--- |
| 361 | + |
| 362 | +## 🆘 Getting Help |
| 363 | + |
| 364 | +- **Documentation**: [docs.objectstack.dev](https://docs.objectstack.dev) |
| 365 | +- **Discord**: [discord.gg/objectstack](https://discord.gg/objectstack) |
| 366 | +- **GitHub Discussions**: [github.com/objectstack/spec/discussions](https://github.com/objectstack/spec/discussions) |
| 367 | +- **Stack Overflow**: Tag your questions with `objectstack` |
| 368 | + |
| 369 | +--- |
| 370 | + |
| 371 | +Ready to start building? Pick your extension type and dive into the guides! 🚀 |
0 commit comments