@fluxstack/live 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,145 @@
1
+ # @fluxstack/live
2
+
3
+ Framework-agnostic core for real-time server-client state synchronization.
4
+
5
+ Live Components turn server-side classes into reactive state that syncs automatically with connected clients over WebSocket. Write your logic once on the server, and clients receive state updates in real-time.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ bun add @fluxstack/live
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```typescript
16
+ import { LiveServer, LiveComponent } from '@fluxstack/live'
17
+
18
+ // 1. Define a component
19
+ class Counter extends LiveComponent<{ count: number }> {
20
+ static componentName = 'Counter'
21
+ static defaultState = { count: 0 }
22
+ static publicActions = ['increment', 'decrement'] as const
23
+
24
+ increment() {
25
+ this.count++
26
+ }
27
+
28
+ decrement() {
29
+ this.count--
30
+ }
31
+ }
32
+
33
+ // 2. Create server with your transport adapter
34
+ import { ElysiaTransport } from '@fluxstack/live-elysia'
35
+
36
+ const server = new LiveServer({
37
+ transport: new ElysiaTransport(app),
38
+ componentsPath: './src/components',
39
+ })
40
+
41
+ await server.start()
42
+ ```
43
+
44
+ ## Features
45
+
46
+ - **LiveComponent** — Base class with reactive state proxy, auto-sync, and lifecycle hooks
47
+ - **LiveServer** — Orchestrator that wires transport, components, auth, rooms, and cluster
48
+ - **ComponentRegistry** — Auto-discovers components from a directory or manual registration
49
+ - **Rooms** — Built-in room system with typed events and cross-instance pub/sub
50
+ - **Auth** — Per-component and per-action authorization (`static auth`, `static actionAuth`)
51
+ - **State Signing** — HMAC-SHA256 state signing with hybrid nonce replay protection
52
+ - **Rate Limiting** — Token bucket rate limiter per connection
53
+ - **Security** — Payload sanitization against prototype pollution, message size limits
54
+ - **Binary Delta** — Efficient binary state diffs for high-frequency updates
55
+ - **File Upload** — Chunked file upload over WebSocket
56
+ - **Cluster** — `IClusterAdapter` interface for horizontal scaling (singleton coordination, action forwarding, state mirroring)
57
+ - **Monitoring** — Performance monitor with per-component metrics
58
+
59
+ ## Transport Adapters
60
+
61
+ This package is framework-agnostic. Use it with any transport adapter:
62
+
63
+ | Adapter | Package |
64
+ |---------|---------|
65
+ | Elysia | `@fluxstack/live-elysia` |
66
+ | Express | `@fluxstack/live-express` |
67
+ | Fastify | `@fluxstack/live-fastify` |
68
+
69
+ ## LiveComponent
70
+
71
+ ```typescript
72
+ import { LiveComponent } from '@fluxstack/live'
73
+
74
+ export class TodoList extends LiveComponent<typeof TodoList.defaultState> {
75
+ static componentName = 'TodoList'
76
+ static singleton = true
77
+ static publicActions = ['addTodo', 'toggleTodo'] as const
78
+ static defaultState = {
79
+ todos: [] as { id: string; text: string; done: boolean }[]
80
+ }
81
+
82
+ declare todos: typeof TodoList.defaultState['todos']
83
+
84
+ addTodo(payload: { text: string }) {
85
+ this.todos = [...this.todos, { id: crypto.randomUUID(), text: payload.text, done: false }]
86
+ }
87
+
88
+ toggleTodo(payload: { id: string }) {
89
+ this.todos = this.todos.map(t =>
90
+ t.id === payload.id ? { ...t, done: !t.done } : t
91
+ )
92
+ }
93
+ }
94
+ ```
95
+
96
+ ### Lifecycle Hooks
97
+
98
+ ```typescript
99
+ class MyComponent extends LiveComponent<State> {
100
+ protected onConnect() { } // WebSocket connected
101
+ protected async onMount() { } // Component fully mounted (async)
102
+ protected onRehydrate(prev) { } // State restored from client
103
+ protected onStateChange(changes) { } // After state mutation
104
+ protected onRoomJoin(roomId) { } // Joined a room
105
+ protected onRoomLeave(roomId) { } // Left a room
106
+ protected onAction(action, payload) { } // Before action (return false to cancel)
107
+ protected onDisconnect() { } // Connection lost
108
+ protected onDestroy() { } // Before cleanup (sync)
109
+ }
110
+ ```
111
+
112
+ ## LiveServer Options
113
+
114
+ ```typescript
115
+ new LiveServer({
116
+ transport, // Required: transport adapter
117
+ componentsPath: './components', // Auto-discover components
118
+ wsPath: '/api/live/ws', // WebSocket endpoint (default)
119
+ debug: false, // Debug mode
120
+ cluster: clusterAdapter, // IClusterAdapter for horizontal scaling
121
+ roomPubSub: roomAdapter, // IRoomPubSubAdapter for cross-instance rooms
122
+ allowedOrigins: ['https://...'], // CSRF protection
123
+ rateLimitMaxTokens: 100, // Rate limiter max tokens
124
+ rateLimitRefillRate: 10, // Tokens refilled per second
125
+ httpPrefix: '/api/live', // HTTP monitoring routes
126
+ })
127
+ ```
128
+
129
+ ## Horizontal Scaling
130
+
131
+ ```typescript
132
+ import { RedisClusterAdapter, RedisRoomAdapter } from '@fluxstack/live-redis'
133
+
134
+ const server = new LiveServer({
135
+ transport,
136
+ cluster: new RedisClusterAdapter({ redis }),
137
+ roomPubSub: new RedisRoomAdapter({ redis }),
138
+ })
139
+ ```
140
+
141
+ See `@fluxstack/live-redis` for details.
142
+
143
+ ## License
144
+
145
+ MIT