@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 +145 -0
- package/dist/index.d.ts +608 -151
- package/dist/index.js +2373 -880
- package/dist/index.js.map +1 -1
- package/package.json +11 -4
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
|