Skip to content

Commit 22d935f

Browse files
committed
docs: add basic docs for koka-domain and koka-ddd
1 parent 9e9027b commit 22d935f

File tree

2 files changed

+313
-0
lines changed

2 files changed

+313
-0
lines changed

packages/koka-ddd/README.md

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# koka-ddd - Domain Modeling with Effects
2+
3+
Koka DDD provides a domain modeling framework built on Koka's algebraic effects system, featuring:
4+
5+
- **Domain Modeling**: Type-safe domain definitions
6+
- **Store Pattern**: Centralized state management
7+
- **Command/Query Separation**: Clear distinction between writes and reads
8+
- **Effect Integration**: Seamless Koka effects usage
9+
- **Optics Support**: Composable data access patterns
10+
11+
## Installation
12+
13+
```bash
14+
npm install koka-ddd
15+
# or
16+
yarn add koka-ddd
17+
# or
18+
pnpm add koka-ddd
19+
```
20+
21+
## Core Concepts
22+
23+
### Domain Modeling
24+
25+
Define your domain using the `Domain` base class:
26+
27+
```typescript
28+
import { Domain } from 'koka-ddd'
29+
30+
class TodoDomain extends Domain<Todo> {
31+
text = new TextDomain(this.$prop('text'))
32+
done = new BoolDomain(this.$prop('done'))
33+
34+
*updateText(newText: string) {
35+
yield* this.text.updateText(newText)
36+
}
37+
}
38+
```
39+
40+
### Store Pattern
41+
42+
Manage application state with the `Store` class:
43+
44+
```typescript
45+
import { Store } from 'koka-ddd'
46+
47+
const store = new Store({
48+
state: {
49+
todos: [],
50+
filter: 'all',
51+
},
52+
})
53+
```
54+
55+
### Commands and Queries
56+
57+
```typescript
58+
// Query example
59+
const todos = store.get(todoListDomain)
60+
61+
// Command example
62+
store.runCommand(todoDomain.addTodo('New task'))
63+
```
64+
65+
## Complete Todo App Example
66+
67+
```typescript
68+
import { Domain, Store } from 'koka-ddd'
69+
70+
// Define domains
71+
class TodoDomain extends Domain<Todo> {
72+
text = new TextDomain(this.$prop('text'))
73+
done = new BoolDomain(this.$prop('done'))
74+
75+
*toggle() {
76+
yield* this.done.toggle()
77+
}
78+
}
79+
80+
class TodoListDomain extends Domain<Todo[]> {
81+
*addTodo(text: string) {
82+
const newTodo = { id: Date.now(), text, done: false }
83+
yield* set(this, todos => [...todos, newTodo])
84+
}
85+
86+
todo(id: number) {
87+
return new TodoDomain(this.$find(todo => todo.id === id))
88+
}
89+
}
90+
91+
// Create store
92+
const store = new Store({
93+
state: {
94+
todos: []
95+
}
96+
})
97+
98+
// Usage
99+
store.runCommand(todoListDomain.addTodo('Learn Koka DDD'))
100+
store.runCommand(todoListDomain.todo(1).toggle())
101+
```
102+
103+
## Advanced Patterns
104+
105+
### Nested Domains
106+
107+
```typescript
108+
class AppDomain extends Domain<AppState> {
109+
todos = new TodoListDomain(this.$prop('todos'))
110+
user = new UserDomain(this.$prop('user'))
111+
}
112+
```
113+
114+
### Async Operations
115+
116+
```typescript
117+
*loadTodos() {
118+
const response = yield* Eff.await(fetch('/todos'))
119+
const todos = yield* Eff.await(response.json())
120+
yield* set(this, todos)
121+
}
122+
```
123+
124+
## Testing
125+
126+
Tests follow the same patterns as production code:
127+
128+
```typescript
129+
test('should add todo', async () => {
130+
await store.runCommand(todos.addTodo('Test'))
131+
expect(store.getState().todos.length).toBe(1)
132+
})
133+
```
134+
135+
## API Reference
136+
137+
### Domain
138+
139+
- `$prop()`: Create property accessor
140+
- `$find()`: Find item in collection
141+
- `$filter()`: Filter collection
142+
- `$map()`: Transform values
143+
144+
### Store
145+
146+
- `get(domain)`: Query state
147+
- `runCommand(command)`: Execute state mutation
148+
- `subscribe(listener)`: React to changes
149+
150+
## Contributing
151+
152+
1. Ensure tests pass (`npm test`)
153+
2. Update documentation
154+
3. Follow existing patterns
155+
156+
## License
157+
158+
MIT

packages/koka-domain/README.md

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# koka-domain - Type-Safe Data Accessors
2+
3+
koka-domain provides composable, type-safe data access patterns built on algebraic effects. It enables:
4+
5+
- **Bidirectional transformations**: Get and set values with type safety
6+
- **Optics patterns**: Lenses, prisms, and traversals for structured data
7+
- **Domain modeling**: Structured data access patterns
8+
- **Effect integration**: Works seamlessly with Koka effects
9+
10+
## Installation
11+
12+
```bash
13+
npm install koka-domain
14+
# or
15+
yarn add koka-domain
16+
# or
17+
pnpm add koka-domain
18+
```
19+
20+
## Core Concepts
21+
22+
### Root Domain
23+
24+
```typescript
25+
import { Domain } from 'koka-domain'
26+
27+
// Create root domain for a type
28+
const numberDomain = Domain.root<number>()
29+
30+
// Get value
31+
const result = Eff.runResult(numberDomain.get(42))
32+
// { type: 'ok', value: 42 }
33+
34+
// Set value
35+
const setter = numberDomain.set(function* (n) {
36+
return n + 1
37+
})
38+
Eff.runResult(setter(42)) // 43
39+
```
40+
41+
### Property Access
42+
43+
```typescript
44+
const userDomain = Domain.root<{ name: string }>().$prop('name')
45+
46+
// Get property
47+
Eff.runResult(userDomain.get({ name: 'Alice' })) // 'Alice'
48+
49+
// Set property
50+
const setName = userDomain.set(function* () {
51+
return 'Bob'
52+
})
53+
Eff.runResult(setName({ name: 'Alice' })) // { name: 'Bob' }
54+
```
55+
56+
### Array Operations
57+
58+
```typescript
59+
const todosDomain = Domain.root<Todo[]>()
60+
61+
// Access by index
62+
const firstTodo = todosDomain.$index(0)
63+
64+
// Find item
65+
const importantTodo = todosDomain.$find((todo) => todo.priority === 'high')
66+
67+
// Filter items
68+
const completedTodos = todosDomain.$filter((todo) => todo.completed)
69+
70+
// Map items
71+
const todoTitles = todosDomain.$map((todo) => todo.title)
72+
```
73+
74+
### Type Refinement
75+
76+
```typescript
77+
const numberDomain = Domain.root<string | number>().$match((v): v is number => typeof v === 'number')
78+
79+
Eff.runResult(numberDomain.get(42)) // 42
80+
Eff.runResult(numberDomain.get('test')) // Error
81+
```
82+
83+
### Object Composition
84+
85+
```typescript
86+
const userDomain = Domain.object({
87+
name: Domain.root<{ name: string }>().$prop('name'),
88+
age: Domain.root<{ age: number }>().$prop('age'),
89+
})
90+
91+
Eff.runResult(userDomain.get({ name: 'Alice', age: 30 }))
92+
// { name: 'Alice', age: 30 }
93+
```
94+
95+
## Advanced Usage
96+
97+
### Complex Transformations
98+
99+
```typescript
100+
const complexDomain = Domain.root<{ users: User[] }>()
101+
.$prop('users')
102+
.$filter((user) => user.active)
103+
.$map({
104+
get: (user) => ({
105+
...user,
106+
name: user.name.toUpperCase(),
107+
}),
108+
set: (user) => ({
109+
...user,
110+
name: user.name.toLowerCase(),
111+
}),
112+
})
113+
114+
const result = Eff.runResult(
115+
complexDomain.get({
116+
users: [
117+
{ name: 'Alice', active: true },
118+
{ name: 'Bob', active: false },
119+
],
120+
}),
121+
)
122+
// [{ name: 'ALICE', active: true }]
123+
```
124+
125+
## API Reference
126+
127+
### Core Methods
128+
129+
- `Domain.root<T>()`: Create root domain for type T
130+
- `$prop(key)`: Access object property
131+
- `$index(n)`: Access array index
132+
- `$find(predicate)`: Find array item
133+
- `$filter(predicate)`: Filter array
134+
- `$map(transform)`: Transform values
135+
- `$match(predicate)`: Type refinement
136+
- `$refine(predicate)`: Value validation
137+
- `Domain.object(fields)`: Compose object domains
138+
- `Domain.optional(domain)`: Handle optional values
139+
140+
## Best Practices
141+
142+
1. **Compose domains** for complex data structures
143+
2. **Combine with Koka effects** for async operations
144+
3. **Leverage type system** for safety
145+
146+
## Contributing
147+
148+
1. Write tests for new features
149+
2. Maintain type safety
150+
3. Document changes
151+
4. Follow existing patterns
152+
153+
## License
154+
155+
MIT

0 commit comments

Comments
 (0)