Skip to content

Commit 3e0ce62

Browse files
committed
feat: redesign basic api
1 parent 7c33105 commit 3e0ce62

23 files changed

Lines changed: 2103 additions & 1356 deletions

CHANGELOG.md

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [0.1.0] - 2025-12-13
9+
10+
### 🎯 Major Redesign - Observer Pattern & Suspense Integration
11+
12+
This release represents a fundamental redesign of `braided-react` based on lessons learned from building real-world applications. The new design embraces the **Observer Pattern** and **direct closure access**, while integrating seamlessly with React's primitives (Suspense, ErrorBoundary).
13+
14+
### Added
15+
16+
- **Direct Closure Access**: Manager is now passed to `createSystemHooks()`, enabling direct access without Context indirection
17+
- **Automatic Suspense Integration**: `useSystem()` and `useResource()` now suspend (throw Promise) while system is starting
18+
- **Automatic ErrorBoundary Integration**: Hooks throw errors when system startup fails, triggering ErrorBoundary
19+
- **Manual Control Hook**: New `useSystemStatus()` hook for explicit startup control (welcome screens, deferred startup)
20+
- **Config Exposure**: `manager.config` now exposed for inspection and testing
21+
- **SystemProvider**: Renamed from `SystemBridge` for clarity (Context override for testing/DI)
22+
23+
### Changed
24+
25+
- **BREAKING**: `createSystemHooks()` now requires a manager parameter
26+
- **Before**: `createSystemHooks<typeof config>()`
27+
- **After**: `createSystemHooks(manager)`
28+
- **BREAKING**: `SystemBridge` renamed to `SystemProvider`
29+
- More accurately reflects its purpose (Context injection for testing)
30+
- **Resolution Order**: Hooks now check Context first (DI override), then fall back to manager (production)
31+
32+
### Removed
33+
34+
- **BREAKING**: `LazySystemBridge` component removed
35+
- **Replaced by**: `<Suspense>` + `useSystem()` (automatic)
36+
- **Or**: `useSystemStatus()` (manual control)
37+
38+
### Migration Guide
39+
40+
#### Pattern 1: Automatic with Suspense (Recommended)
41+
42+
**Before (v0.0.2):**
43+
```typescript
44+
const { SystemBridge, useSystem } = createSystemHooks<typeof config>()
45+
const manager = createSystemManager(config)
46+
47+
<LazySystemBridge manager={manager} SystemBridge={SystemBridge}>
48+
<App />
49+
</LazySystemBridge>
50+
```
51+
52+
**After (v0.1.0):**
53+
```typescript
54+
const manager = createSystemManager(config)
55+
const { useSystem } = createSystemHooks(manager)
56+
57+
<Suspense fallback={<Loading />}>
58+
<ErrorBoundary FallbackComponent={ErrorScreen}>
59+
<App />
60+
</ErrorBoundary>
61+
</Suspense>
62+
```
63+
64+
#### Pattern 2: Manual Control
65+
66+
**Before (v0.0.2):**
67+
```typescript
68+
// Had to manage state manually outside LazySystemBridge
69+
const [started, setStarted] = useState(false)
70+
71+
if (!started) {
72+
return <WelcomeScreen onStart={() => setStarted(true)} />
73+
}
74+
75+
return (
76+
<LazySystemBridge manager={manager} SystemBridge={SystemBridge}>
77+
<App />
78+
</LazySystemBridge>
79+
)
80+
```
81+
82+
**After (v0.1.0):**
83+
```typescript
84+
const { useSystemStatus } = createSystemHooks(manager)
85+
86+
function App() {
87+
const { isIdle, isLoading, startSystem } = useSystemStatus()
88+
89+
if (isIdle) return <WelcomeScreen onStart={startSystem} />
90+
if (isLoading) return <LoadingScreen />
91+
return <ChatRoom />
92+
}
93+
```
94+
95+
#### Pattern 3: Testing (No Changes!)
96+
97+
Testing with Context injection still works the same way:
98+
99+
```typescript
100+
const { SystemProvider } = createSystemHooks(manager)
101+
102+
test('component works', async () => {
103+
const { system } = await startSystem(mockConfig)
104+
105+
render(
106+
<SystemProvider system={system}>
107+
<Component />
108+
</SystemProvider>
109+
)
110+
})
111+
```
112+
113+
### Design Rationale
114+
115+
#### Why Direct Closure Access?
116+
117+
**Problem**: Context was used to pass system reference to React, but the system already lives in closure space (Z-axis). React can observe it directly through hooks.
118+
119+
**Solution**: Pass manager to `createSystemHooks()`. Hooks access the manager directly from closure.
120+
121+
**Benefits**:
122+
-Simpler mental model (one source of truth)
123+
-Less boilerplate (no wrapper component needed)
124+
-Faster (no context lookup)
125+
-Aligns with Observer Pattern (React observes closure space)
126+
127+
#### Why Suspense Integration?
128+
129+
**Problem**: Loading states were managed via callbacks (`fallback` prop) instead of React's built-in primitives.
130+
131+
**Solution**: `useSystem()` throws Promise when system is starting, triggering Suspense.
132+
133+
**Benefits**:
134+
-Standard React pattern (developers already know this)
135+
-Composable (multiple Suspense boundaries)
136+
-Works with concurrent rendering
137+
-Less code (no manual loading state)
138+
139+
#### Why ErrorBoundary Integration?
140+
141+
**Problem**: Error handling was callback-based (`onError` prop), not composable.
142+
143+
**Solution**: `useSystem()` throws Error when startup fails, triggering ErrorBoundary.
144+
145+
**Benefits**:
146+
-Standard React pattern
147+
-Composable error boundaries
148+
-Centralized error handling
149+
-User-friendly fallbacks
150+
151+
#### Why Keep Context?
152+
153+
**Problem**: Testing needs dependency injection.
154+
155+
**Solution**: Context as optional override, not requirement. Check Context first, then manager.
156+
157+
**Benefits**:
158+
-Flexible testing (mock entire system)
159+
-Multi-tenancy support
160+
-Runtime config changes
161+
-Backward compatible (testing pattern unchanged)
162+
163+
#### Why Manual Control Hook?
164+
165+
**Problem**: Some apps need explicit startup timing (welcome screens, deferred startup).
166+
167+
**Solution**: `useSystemStatus()` hook that doesn't suspend, returns status and manual trigger.
168+
169+
**Benefits**:
170+
-Welcome screens before startup
171+
-Deferred startup until user action
172+
-Custom loading/error UI
173+
-Not prescriptive (use when needed)
174+
175+
### The Z-Axis Model
176+
177+
This redesign fully embraces the **dimensional model**:
178+
179+
- **Z-axis (Closure Space)**: Where systems live independently
180+
- **X-Y Plane (React Tree)**: Where components render
181+
- **Hooks**: Windows between these dimensions
182+
183+
Systems are **module singletons** in closure space. React components observe them through hooks. This separation gives you:
184+
185+
1. **Lifecycle independence** - System outlives React mounts/unmounts
186+
2. **No prop drilling** - Direct access from any component
187+
3. **Testing flexibility** - Context override for dependency injection
188+
4. **Performance** - System lives outside React's render cycle
189+
190+
### Observer Pattern
191+
192+
React components are **observers** of your system. They watch for changes and re-render when needed. But they don't control the system's lifecycle.
193+
194+
**Before**: Context made it seem like React "owned" the system
195+
**After**: Direct closure access makes it clear React is just observing
196+
197+
This is the same pattern used by:
198+
- React Query (for server state)
199+
- Zustand (for client state)
200+
- Jotai (for atomic state)
201+
202+
### Success Criteria
203+
204+
This redesign achieves:
205+
206+
-**Less boilerplate** - Fewer concepts, simpler setup
207+
-**Better integration** - Works with Suspense, ErrorBoundary, DevTools
208+
-**More flexible** - Context still available for DI when needed
209+
-**Type-safe** - Full inference preserved
210+
-**Testable** - Multiple testing patterns supported
211+
-**Performant** - Direct closure access, no context overhead
212+
213+
### Acknowledgments
214+
215+
This redesign was informed by building real-world examples, particularly a WebSocket chat application. The patterns that emerged from that work revealed the true nature of the library: **React observes systems in closure space**.
216+
217+
---
218+
219+
## [0.0.2] - 2024-12-XX
220+
221+
### Added
222+
223+
- Initial release
224+
- `createSystemHooks()` for typed React hooks
225+
- `createSystemManager()` for singleton system management
226+
- `LazySystemBridge` component for lazy initialization
227+
- `SystemBridge` context provider
228+
- Full TypeScript support with type inference
229+
230+
### Documentation
231+
232+
- Basic examples
233+
- README with usage patterns
234+
- API documentation
235+
236+
---
237+
238+
## [0.0.1] - 2024-12-XX
239+
240+
### Added
241+
242+
- Initial prototype
243+
- Core concepts established
244+
245+
---
246+
247+
[0.1.0]: https://github.com/RegiByte/braided-react/compare/v0.0.2...v0.1.0
248+
[0.0.2]: https://github.com/RegiByte/braided-react/compare/v0.0.1...v0.0.2
249+
[0.0.1]: https://github.com/RegiByte/braided-react/releases/tag/v0.0.1
250+

0 commit comments

Comments
 (0)