This commit is contained in:
seb
2026-09-21 03:19:32 +02:00
parent 5594c59d88
commit 366d2517d6
17 changed files with 467 additions and 269 deletions

View File

@@ -90,6 +90,7 @@ export class Automat<T = any, A = Record<string, Function>> {
dispose(): void; // Unsubs all, revokes blobs, deletes from window registry
static get<T = any, A = any>(name: string): Automat<T, A> | undefined;
static combine<M extends Record<string, Automat<any, any>>>(automats: M): Automat<CombinedState<M>, CombinedActions<M>>;
}
// Fetchers & SSE
@@ -168,6 +169,30 @@ const live = new Automat({}, {
connectSSE(live, '/api/stream');
```
### G. Combine Automats
```js
const app = Automat.combine({
auth: authAutomat,
company: companyAutomat,
});
app.state.auth; // authAutomat.state
app.state.company; // companyAutomat.state
app.actions.auth.login(); // authAutomat.actions.login()
app.actions.company.rename('Acme');
// Notified when either child changes; selectors can isolate a branch.
const unsubscribe = app.subscribe(this, (state) => ({
user: state.auth.user,
companyName: state.company.name,
}));
```
The aggregate is derived: child updates automatically update the matching key. Its
`isReady`, `isDirty`, `ready`, `read()`, `setDirty()`, and `reload()` operations cover
all children. Calling `app.dispose()` only removes aggregate subscriptions; it does
not dispose the child automats.
## 3. Decision Matrix: `setDirty()` vs `reload()`
| Method | `isReady` | State during fetch | Suspense | Unmounted | Use Case |