@livetemplate/client 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/LICENSE +21 -0
- package/README.md +171 -115
- package/dist/livetemplate-client.browser.js +5 -5
- package/dist/livetemplate-client.browser.js.map +4 -4
- package/dist/livetemplate-client.d.ts +5 -0
- package/dist/livetemplate-client.d.ts.map +1 -1
- package/dist/livetemplate-client.js +66 -0
- package/dist/livetemplate-client.js.map +1 -1
- package/dist/tests/test-reconstruction.test.js +1 -1
- package/dist/tests/test-reconstruction.test.js.map +1 -1
- package/dist/upload/s3-uploader.d.ts +11 -0
- package/dist/upload/s3-uploader.d.ts.map +1 -0
- package/dist/upload/s3-uploader.js +71 -0
- package/dist/upload/s3-uploader.js.map +1 -0
- package/dist/upload/types.d.ts +96 -0
- package/dist/upload/types.d.ts.map +1 -0
- package/dist/upload/types.js +6 -0
- package/dist/upload/types.js.map +1 -0
- package/dist/upload/upload-handler.d.ts +71 -0
- package/dist/upload/upload-handler.d.ts.map +1 -0
- package/dist/upload/upload-handler.js +315 -0
- package/dist/upload/upload-handler.js.map +1 -0
- package/package.json +5 -6
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Adnaan Badr
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,179 +1,235 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @livetemplate/client
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
TypeScript/JavaScript client library for LiveTemplate - reactive HTML over the wire.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Overview
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- **Static Structure Caching**: Cache static HTML structure client-side for maximum efficiency
|
|
9
|
-
- **Phoenix LiveView Compatible**: Only dynamic values transmitted after initial render
|
|
10
|
-
- **Bandwidth Optimization**: 75%+ reduction in update payload sizes
|
|
11
|
-
- **Type Safety**: Full TypeScript support with type definitions
|
|
7
|
+
The LiveTemplate client enables reactive web applications by efficiently applying tree-based HTML updates from the server. It uses DOM morphing, intelligent static content caching, and WebSocket transport for real-time interactivity.
|
|
12
8
|
|
|
13
|
-
##
|
|
9
|
+
## Features
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
- **Tree-based Updates**: Efficiently applies minimal JSON updates to the DOM
|
|
12
|
+
- **Static Structure Caching**: Client caches static HTML, receives only dynamic changes
|
|
13
|
+
- **DOM Morphing**: Uses morphdom for efficient, minimal DOM updates
|
|
14
|
+
- **WebSocket Transport**: Real-time bidirectional communication
|
|
15
|
+
- **Focus Management**: Preserves focus during updates
|
|
16
|
+
- **Form Lifecycle**: Automatic form state management
|
|
17
|
+
- **Event Delegation**: Efficient event handling
|
|
18
|
+
- **Modal Management**: Built-in modal support
|
|
19
|
+
- **TypeScript**: Full type safety and IDE support
|
|
19
20
|
|
|
20
|
-
##
|
|
21
|
+
## Installation
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
### npm
|
|
23
24
|
|
|
24
25
|
```bash
|
|
25
|
-
|
|
26
|
-
npm run test:optimization
|
|
27
|
-
|
|
28
|
-
# Run HTML reconstruction tests
|
|
29
|
-
npm run test:reconstruction
|
|
30
|
-
|
|
31
|
-
# Run all tests
|
|
32
|
-
npm run test:all
|
|
26
|
+
npm install @livetemplate/client
|
|
33
27
|
```
|
|
34
28
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
Current optimization performance:
|
|
29
|
+
### CDN
|
|
38
30
|
|
|
39
|
-
|
|
40
|
-
-
|
|
41
|
-
|
|
42
|
-
- **Static Structure**: Successfully excluded from updates โ
|
|
31
|
+
```html
|
|
32
|
+
<script src="https://cdn.jsdelivr.net/npm/@livetemplate/client@0.1.0/dist/livetemplate-client.browser.js"></script>
|
|
33
|
+
```
|
|
43
34
|
|
|
44
|
-
##
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
### Browser (via CDN)
|
|
38
|
+
|
|
39
|
+
```html
|
|
40
|
+
<!DOCTYPE html>
|
|
41
|
+
<html>
|
|
42
|
+
<head>
|
|
43
|
+
<script src="https://cdn.jsdelivr.net/npm/@livetemplate/client@0.1.0/dist/livetemplate-client.browser.js"></script>
|
|
44
|
+
</head>
|
|
45
|
+
<body>
|
|
46
|
+
<div id="app"></div>
|
|
47
|
+
<script>
|
|
48
|
+
const client = new LiveTemplateClient.LiveTemplateClient({
|
|
49
|
+
targetSelector: "#app",
|
|
50
|
+
wsUrl: "ws://localhost:8080/ws",
|
|
51
|
+
httpUrl: "http://localhost:8080"
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
client.connect();
|
|
55
|
+
</script>
|
|
56
|
+
</body>
|
|
57
|
+
</html>
|
|
58
|
+
```
|
|
45
59
|
|
|
46
|
-
###
|
|
60
|
+
### TypeScript/ES Modules
|
|
47
61
|
|
|
48
62
|
```typescript
|
|
49
|
-
import { LiveTemplateClient } from "
|
|
63
|
+
import { LiveTemplateClient } from "@livetemplate/client";
|
|
50
64
|
|
|
51
|
-
const client = new LiveTemplateClient(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
s: ["<h1>", "</h1><p>Count: ", "</p>"], // Static HTML segments
|
|
56
|
-
"0": "Hello World", // Dynamic content
|
|
57
|
-
"1": "42", // Dynamic content
|
|
65
|
+
const client = new LiveTemplateClient({
|
|
66
|
+
targetSelector: "#app",
|
|
67
|
+
wsUrl: "ws://localhost:8080/ws",
|
|
68
|
+
httpUrl: "http://localhost:8080"
|
|
58
69
|
});
|
|
59
70
|
|
|
60
|
-
|
|
71
|
+
client.connect();
|
|
72
|
+
```
|
|
61
73
|
|
|
62
|
-
|
|
63
|
-
const updateResult = client.applyUpdate({
|
|
64
|
-
"1": "43", // Only the changed value
|
|
65
|
-
});
|
|
74
|
+
## Configuration Options
|
|
66
75
|
|
|
67
|
-
|
|
68
|
-
|
|
76
|
+
```typescript
|
|
77
|
+
interface LiveTemplateClientOptions {
|
|
78
|
+
// Required
|
|
79
|
+
targetSelector: string; // CSS selector for target element
|
|
80
|
+
wsUrl: string; // WebSocket URL
|
|
81
|
+
httpUrl: string; // HTTP URL for initial render
|
|
82
|
+
|
|
83
|
+
// Optional
|
|
84
|
+
debug?: boolean; // Enable debug logging (default: false)
|
|
85
|
+
reconnectInterval?: number; // Reconnect interval in ms (default: 3000)
|
|
86
|
+
maxReconnectAttempts?: number;// Max reconnect attempts (default: 10)
|
|
87
|
+
}
|
|
69
88
|
```
|
|
70
89
|
|
|
71
|
-
|
|
90
|
+
## API
|
|
91
|
+
|
|
92
|
+
### Client Methods
|
|
72
93
|
|
|
73
94
|
```typescript
|
|
74
|
-
|
|
95
|
+
// Connect to server
|
|
96
|
+
client.connect(): void
|
|
97
|
+
|
|
98
|
+
// Disconnect from server
|
|
99
|
+
client.disconnect(): void
|
|
75
100
|
|
|
76
|
-
|
|
101
|
+
// Send event to server
|
|
102
|
+
client.sendEvent(event: string, data: any): void
|
|
77
103
|
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
console.log(result.html);
|
|
104
|
+
// Set debug mode
|
|
105
|
+
client.setDebug(enabled: boolean): void
|
|
81
106
|
```
|
|
82
107
|
|
|
83
|
-
###
|
|
108
|
+
### Events
|
|
109
|
+
|
|
110
|
+
The client emits events you can listen to:
|
|
84
111
|
|
|
85
112
|
```typescript
|
|
86
|
-
|
|
113
|
+
// Connection established
|
|
114
|
+
window.addEventListener("livetemplate:connected", (e) => {
|
|
115
|
+
console.log("Connected to server");
|
|
116
|
+
});
|
|
87
117
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
118
|
+
// Connection closed
|
|
119
|
+
window.addEventListener("livetemplate:disconnected", (e) => {
|
|
120
|
+
console.log("Disconnected from server");
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Update received
|
|
124
|
+
window.addEventListener("livetemplate:update", (e) => {
|
|
125
|
+
console.log("Received update:", e.detail);
|
|
126
|
+
});
|
|
94
127
|
```
|
|
95
128
|
|
|
96
|
-
##
|
|
129
|
+
## How It Works
|
|
97
130
|
|
|
98
|
-
|
|
131
|
+
1. **Initial Render**: Client fetches full HTML from server, caches static structure
|
|
132
|
+
2. **Updates**: Server sends only changed dynamic values as tree updates
|
|
133
|
+
3. **DOM Morphing**: Client applies updates using morphdom for minimal DOM changes
|
|
134
|
+
4. **Caching**: Static HTML structure is cached, never re-transmitted
|
|
99
135
|
|
|
100
|
-
|
|
136
|
+
This results in **~75% reduction** in update payload sizes compared to full HTML updates.
|
|
101
137
|
|
|
102
|
-
|
|
103
|
-
2. **Dynamic Values** (numbered keys): Only the values that change between updates
|
|
104
|
-
3. **Segment Interleaving**: Client reconstructs HTML by interleaving static + dynamic
|
|
138
|
+
## Development
|
|
105
139
|
|
|
106
|
-
|
|
140
|
+
### Setup
|
|
107
141
|
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
"1": "42" // Dynamic: counter value
|
|
113
|
-
}
|
|
114
|
-
```
|
|
142
|
+
```bash
|
|
143
|
+
# Clone repository
|
|
144
|
+
git clone https://github.com/livetemplate/client.git
|
|
145
|
+
cd client
|
|
115
146
|
|
|
116
|
-
|
|
147
|
+
# Install dependencies
|
|
148
|
+
npm install
|
|
117
149
|
|
|
118
|
-
|
|
150
|
+
# Run tests
|
|
151
|
+
npm test
|
|
119
152
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
- **DOM Morphing**: Let morphdom handle efficient DOM updates
|
|
153
|
+
# Build
|
|
154
|
+
npm run build
|
|
155
|
+
```
|
|
124
156
|
|
|
125
|
-
|
|
157
|
+
### Project Structure
|
|
126
158
|
|
|
127
|
-
|
|
159
|
+
```
|
|
160
|
+
client/
|
|
161
|
+
โโโ livetemplate-client.ts # Main client
|
|
162
|
+
โโโ dom/ # DOM utilities
|
|
163
|
+
โ โโโ directives.ts
|
|
164
|
+
โ โโโ event-delegation.ts
|
|
165
|
+
โ โโโ focus-manager.ts
|
|
166
|
+
โ โโโ form-disabler.ts
|
|
167
|
+
โ โโโ loading-indicator.ts
|
|
168
|
+
โ โโโ modal-manager.ts
|
|
169
|
+
โ โโโ observer-manager.ts
|
|
170
|
+
โโโ state/ # State management
|
|
171
|
+
โ โโโ form-lifecycle-manager.ts
|
|
172
|
+
โ โโโ tree-renderer.ts
|
|
173
|
+
โโโ transport/ # Network layer
|
|
174
|
+
โ โโโ websocket.ts
|
|
175
|
+
โโโ utils/ # Utilities
|
|
176
|
+
โ โโโ logger.ts
|
|
177
|
+
โ โโโ rate-limit.ts
|
|
178
|
+
โ โโโ testing.ts
|
|
179
|
+
โโโ tests/ # Test suite
|
|
180
|
+
```
|
|
128
181
|
|
|
129
|
-
|
|
130
|
-
- `testdata/e2e/update_02_remove_todo.json` - Subsequent update (128 bytes)
|
|
131
|
-
- `testdata/e2e/rendered_*.html` - Expected HTML output for comparison
|
|
182
|
+
### Running Tests
|
|
132
183
|
|
|
133
|
-
|
|
184
|
+
```bash
|
|
185
|
+
# Run all tests
|
|
186
|
+
npm test
|
|
134
187
|
|
|
135
|
-
|
|
188
|
+
# Run specific test
|
|
189
|
+
npm test -- focus-manager
|
|
136
190
|
|
|
137
|
-
|
|
191
|
+
# Run with coverage
|
|
192
|
+
npm test -- --coverage
|
|
193
|
+
```
|
|
138
194
|
|
|
139
|
-
|
|
195
|
+
### Building
|
|
140
196
|
|
|
141
|
-
|
|
142
|
-
|
|
197
|
+
```bash
|
|
198
|
+
# Build TypeScript and browser bundle
|
|
199
|
+
npm run build
|
|
143
200
|
|
|
144
|
-
|
|
201
|
+
# Build browser bundle only
|
|
202
|
+
npm run build:browser
|
|
145
203
|
|
|
146
|
-
|
|
204
|
+
# Clean build artifacts
|
|
205
|
+
npm run clean
|
|
206
|
+
```
|
|
147
207
|
|
|
148
|
-
|
|
208
|
+
## Related Projects
|
|
149
209
|
|
|
150
|
-
|
|
210
|
+
- **[LiveTemplate Core](https://github.com/livetemplate/livetemplate)** - Go library for server-side rendering
|
|
211
|
+
- **[LVT CLI](https://github.com/livetemplate/lvt)** - Code generator and development server
|
|
212
|
+
- **[Examples](https://github.com/livetemplate/examples)** - Example applications
|
|
151
213
|
|
|
152
|
-
|
|
214
|
+
## Version Synchronization
|
|
153
215
|
|
|
154
|
-
|
|
216
|
+
This client library follows the LiveTemplate core library's major.minor version. For example:
|
|
155
217
|
|
|
156
|
-
|
|
218
|
+
- Core: `v0.1.5` โ Client: `v0.1.x` (any patch version)
|
|
219
|
+
- Core: `v0.2.0` โ Client: `v0.2.0` (must match major.minor)
|
|
157
220
|
|
|
158
|
-
|
|
221
|
+
Patch versions are independent and can be incremented for client-specific fixes.
|
|
159
222
|
|
|
160
|
-
|
|
223
|
+
## Contributing
|
|
161
224
|
|
|
162
|
-
|
|
225
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for development guidelines.
|
|
163
226
|
|
|
164
|
-
|
|
227
|
+
## License
|
|
165
228
|
|
|
166
|
-
|
|
167
|
-
| ------------ | ------------ | ----------------- |
|
|
168
|
-
| Full HTML | ~600 | 0% (baseline) |
|
|
169
|
-
| Optimized #1 | 168 | 72% |
|
|
170
|
-
| Optimized #2 | 128 | 79% |
|
|
171
|
-
| **Average** | **148** | **~75.3%** |
|
|
229
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
172
230
|
|
|
173
|
-
##
|
|
231
|
+
## Support
|
|
174
232
|
|
|
175
|
-
-
|
|
176
|
-
-
|
|
177
|
-
-
|
|
178
|
-
- Advanced diff algorithms for complex nested structures
|
|
179
|
-
- Performance monitoring and metrics
|
|
233
|
+
- **Issues**: [GitHub Issues](https://github.com/livetemplate/client/issues)
|
|
234
|
+
- **Discussions**: [GitHub Discussions](https://github.com/livetemplate/client/discussions)
|
|
235
|
+
- **Documentation**: [LiveTemplate Docs](https://github.com/livetemplate/livetemplate)
|