Designing Kubit APIs
Overview
Design APIs by starting with ideal usage in skeleton/, then codifying as types in packages/core/, then documenting in SPEC.md.
When to Use
- Adding new method, decorator, or export to framework
- Modifying existing API signatures
- Defining types in packages/core/*.d.ts
- User asks "how should this API look?"
API Design Flow
digraph api_flow {
"Write usage in skeleton/" -> "Add types to packages/core/" -> "Document in SPEC.md" -> "Verify tsc passes";
}
- Usage First: Write the ideal developer experience in skeleton/
- Types Second: Add ambient types to make it compile
- Spec Third: Document with TypeScript signatures
- Verify: Run
tsc --noEmit in skeleton/
Design Principles
| Principle | Application |
|---|
| DX First | How does this feel to use? Start from skeleton. |
| Type Safety | Can TypeScript catch mistakes at compile time? |
| Conventions | Follow Laravel/Rails patterns where sensible |
| Minimal API | Smallest surface that solves the problem |
| Extensibility | Can users extend without modifying core? |
Patterns in Use
Decorators: @column(), @before(), @property(), @use() - metadata on classes/properties
Method Chaining: router.get('/').name('home') - fluent API for configuration
Controller Tuples: [Controller, 'method'] - type-safe handler references
Lazy Relations: @hasMany(() => Post) - arrow function to avoid circular deps
Static Dispatch: Job.dispatch({}), Mailable.send({}) - class-level entry points
Type Definition Location
All public types go in packages/core/:
| File | Contents |
|---|
kubit.d.ts | defineConfig, env, use |
router.d.ts | router object, handler types |
orm.d.ts | Model, column decorators, relations |
queue.d.ts |
Checklist Before Adding API