@livetemplate/client 0.1.0 → 0.4.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.
@@ -0,0 +1,82 @@
1
+ /**
2
+ * UploadHandler - Manages file uploads for LiveTemplate
3
+ *
4
+ * Handles:
5
+ * - File input detection and change events
6
+ * - Chunked uploads to server via WebSocket
7
+ * - External uploads (S3) via presigned URLs
8
+ * - Progress tracking and callbacks
9
+ * - Upload cancellation
10
+ */
11
+ import type { UploadEntry, UploadHandlerOptions, UploadProgressMessage, UploadStartResponse, Uploader } from "./types";
12
+ export declare class UploadHandler {
13
+ private sendMessage;
14
+ private entries;
15
+ private pendingFiles;
16
+ private autoUploadConfig;
17
+ private chunkSize;
18
+ private uploaders;
19
+ private onProgress?;
20
+ private onComplete?;
21
+ private onError?;
22
+ private inputHandlers;
23
+ constructor(sendMessage: (message: any) => void, options?: UploadHandlerOptions);
24
+ /**
25
+ * Initialize upload detection on file inputs with lvt-upload attribute
26
+ */
27
+ initializeFileInputs(container: Element): void;
28
+ /**
29
+ * Start upload process for selected files
30
+ */
31
+ startUpload(uploadName: string, files: File[]): Promise<void>;
32
+ /**
33
+ * Handle upload_start response from server
34
+ */
35
+ handleUploadStartResponse(response: UploadStartResponse): Promise<void>;
36
+ /**
37
+ * Upload file using external uploader (S3, etc.)
38
+ */
39
+ private uploadExternal;
40
+ /**
41
+ * Upload file in chunks via WebSocket
42
+ */
43
+ private uploadChunked;
44
+ /**
45
+ * Handle progress message from server (for chunked uploads)
46
+ */
47
+ handleProgressMessage(message: UploadProgressMessage): void;
48
+ /**
49
+ * Cancel upload
50
+ */
51
+ cancelUpload(entryId: string): void;
52
+ /**
53
+ * Get all entries for an upload name
54
+ */
55
+ getEntries(uploadName: string): UploadEntry[];
56
+ /**
57
+ * Trigger upload for all pending entries (used when autoUpload is false)
58
+ * Called by LiveTemplate client on form submit
59
+ */
60
+ triggerPendingUploads(uploadName: string): void;
61
+ /**
62
+ * Register custom uploader
63
+ */
64
+ registerUploader(name: string, uploader: Uploader): void;
65
+ /**
66
+ * Clear file input to prevent re-upload of the same file
67
+ * Called after successful upload completion
68
+ */
69
+ private clearFileInput;
70
+ /**
71
+ * Clean up completed or errored upload entries to prevent memory leaks
72
+ * Automatically called after completion/error, but can be called manually
73
+ * @param uploadName - Optional upload name to clean specific uploads
74
+ * @param delay - Optional delay in ms before cleanup (default: 5000ms)
75
+ */
76
+ cleanupEntries(uploadName?: string, delay?: number): void;
77
+ /**
78
+ * Convert File/Blob to base64 string
79
+ */
80
+ private fileToBase64;
81
+ }
82
+ //# sourceMappingURL=upload-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload-handler.d.ts","sourceRoot":"","sources":["../../upload/upload-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAKV,WAAW,EACX,oBAAoB,EACpB,qBAAqB,EAErB,mBAAmB,EACnB,QAAQ,EACT,MAAM,SAAS,CAAC;AAEjB,qBAAa,aAAa;IAYtB,OAAO,CAAC,WAAW;IAXrB,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,gBAAgB,CAAmC;IAC3D,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAoC;IACrD,OAAO,CAAC,UAAU,CAAC,CAA+B;IAClD,OAAO,CAAC,UAAU,CAAC,CAAuD;IAC1E,OAAO,CAAC,OAAO,CAAC,CAA8C;IAC9D,OAAO,CAAC,aAAa,CAA2D;gBAGtE,WAAW,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,EAC3C,OAAO,GAAE,oBAAyB;IAWpC;;OAEG;IACH,oBAAoB,CAAC,SAAS,EAAE,OAAO;IA+BvC;;OAEG;IACG,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBnE;;OAEG;IACG,yBAAyB,CAC7B,QAAQ,EAAE,mBAAmB,GAC5B,OAAO,CAAC,IAAI,CAAC;IAyEhB;;OAEG;YACW,cAAc;IA0C5B;;OAEG;YACW,aAAa;IAuE3B;;OAEG;IACH,qBAAqB,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI;IAY3D;;OAEG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAmBnC;;OAEG;IACH,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW,EAAE;IAU7C;;;OAGG;IACH,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAwB/C;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAIxD;;;OAGG;IACH,OAAO,CAAC,cAAc;IAYtB;;;;;OAKG;IACH,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,KAAK,GAAE,MAAa,GAAG,IAAI;IAoB/D;;OAEG;IACH,OAAO,CAAC,YAAY;CAarB"}
@@ -0,0 +1,367 @@
1
+ "use strict";
2
+ /**
3
+ * UploadHandler - Manages file uploads for LiveTemplate
4
+ *
5
+ * Handles:
6
+ * - File input detection and change events
7
+ * - Chunked uploads to server via WebSocket
8
+ * - External uploads (S3) via presigned URLs
9
+ * - Progress tracking and callbacks
10
+ * - Upload cancellation
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.UploadHandler = void 0;
14
+ const s3_uploader_1 = require("./s3-uploader");
15
+ class UploadHandler {
16
+ constructor(sendMessage, options = {}) {
17
+ this.sendMessage = sendMessage;
18
+ this.entries = new Map();
19
+ this.pendingFiles = new Map(); // uploadName -> files
20
+ this.autoUploadConfig = new Map(); // uploadName -> autoUpload
21
+ this.uploaders = new Map();
22
+ this.inputHandlers = new WeakMap();
23
+ this.chunkSize = options.chunkSize || 256 * 1024; // 256KB default
24
+ this.onProgress = options.onProgress;
25
+ this.onComplete = options.onComplete;
26
+ this.onError = options.onError;
27
+ // Register default uploaders
28
+ this.uploaders.set("s3", new s3_uploader_1.S3Uploader());
29
+ }
30
+ /**
31
+ * Initialize upload detection on file inputs with lvt-upload attribute
32
+ */
33
+ initializeFileInputs(container) {
34
+ const inputs = container.querySelectorAll('input[type="file"][lvt-upload]');
35
+ inputs.forEach((input) => {
36
+ const uploadName = input.getAttribute("lvt-upload");
37
+ if (!uploadName)
38
+ return;
39
+ // Remove existing listener if any
40
+ const existingHandler = this.inputHandlers.get(input);
41
+ if (existingHandler) {
42
+ input.removeEventListener("change", existingHandler);
43
+ }
44
+ // Create new handler
45
+ const handler = (e) => {
46
+ const files = e.target.files;
47
+ if (!files || files.length === 0)
48
+ return;
49
+ // Always send upload_start to get validation and config
50
+ // But only proceed with chunks if autoUpload is true
51
+ this.startUpload(uploadName, Array.from(files));
52
+ };
53
+ input.addEventListener("change", handler);
54
+ // Store handler in WeakMap to prevent memory leaks
55
+ this.inputHandlers.set(input, handler);
56
+ });
57
+ }
58
+ /**
59
+ * Start upload process for selected files
60
+ */
61
+ async startUpload(uploadName, files) {
62
+ // Store files temporarily for when server response arrives
63
+ this.pendingFiles.set(uploadName, files);
64
+ // Create file metadata
65
+ const fileMetadata = files.map((file) => ({
66
+ name: file.name,
67
+ type: file.type || "application/octet-stream",
68
+ size: file.size,
69
+ }));
70
+ // Send upload_start message to server
71
+ const startMessage = {
72
+ action: "upload_start",
73
+ upload_name: uploadName,
74
+ files: fileMetadata,
75
+ };
76
+ this.sendMessage(startMessage);
77
+ }
78
+ /**
79
+ * Handle upload_start response from server
80
+ */
81
+ async handleUploadStartResponse(response) {
82
+ const { upload_name, entries: entryInfos } = response;
83
+ // Store autoUpload configuration from first entry
84
+ if (entryInfos.length > 0) {
85
+ this.autoUploadConfig.set(upload_name, entryInfos[0].auto_upload);
86
+ }
87
+ // Get pending files for this upload
88
+ const files = this.pendingFiles.get(upload_name);
89
+ if (!files) {
90
+ console.error(`No pending files found for upload: ${upload_name}`);
91
+ return;
92
+ }
93
+ // Clear pending files
94
+ this.pendingFiles.delete(upload_name);
95
+ // Build a map from file name to file object for lookup
96
+ const fileMap = new Map();
97
+ for (const file of files) {
98
+ fileMap.set(file.name, file);
99
+ }
100
+ // Create upload entries
101
+ const entries = [];
102
+ for (const info of entryInfos) {
103
+ const file = fileMap.get(info.client_name);
104
+ if (!file) {
105
+ console.warn(`No file found for entry ${info.entry_id} (client_name: ${info.client_name})`);
106
+ continue;
107
+ }
108
+ const entry = {
109
+ id: info.entry_id,
110
+ file,
111
+ uploadName: upload_name,
112
+ progress: 0,
113
+ bytesUploaded: 0,
114
+ valid: info.valid,
115
+ done: false,
116
+ error: info.error,
117
+ external: info.external,
118
+ };
119
+ this.entries.set(entry.id, entry);
120
+ entries.push(entry);
121
+ // Handle invalid entries
122
+ if (!info.valid) {
123
+ if (this.onError && info.error) {
124
+ this.onError(entry, info.error);
125
+ }
126
+ continue;
127
+ }
128
+ // Only start upload immediately if autoUpload is true
129
+ // Otherwise, entries are stored and will be uploaded on form submit
130
+ if (info.auto_upload) {
131
+ // Start upload (external or chunked)
132
+ if (info.external) {
133
+ this.uploadExternal(entry, info.external);
134
+ }
135
+ else {
136
+ this.uploadChunked(entry);
137
+ }
138
+ }
139
+ }
140
+ }
141
+ /**
142
+ * Upload file using external uploader (S3, etc.)
143
+ */
144
+ async uploadExternal(entry, meta) {
145
+ try {
146
+ const uploader = this.uploaders.get(meta.uploader);
147
+ if (!uploader) {
148
+ throw new Error(`Unknown uploader: ${meta.uploader}`);
149
+ }
150
+ // Start external upload with progress callback
151
+ await uploader.upload(entry, meta, this.onProgress);
152
+ // Notify server of completion
153
+ const completeMessage = {
154
+ action: "upload_complete",
155
+ upload_name: entry.uploadName,
156
+ entry_ids: [entry.id],
157
+ };
158
+ this.sendMessage(completeMessage);
159
+ if (this.onComplete) {
160
+ this.onComplete(entry.uploadName, [entry]);
161
+ }
162
+ // Clear the file input to prevent re-upload of the same file
163
+ this.clearFileInput(entry.uploadName);
164
+ // Schedule cleanup after completion
165
+ this.cleanupEntries(entry.uploadName);
166
+ }
167
+ catch (error) {
168
+ const errorMsg = error instanceof Error ? error.message : String(error);
169
+ entry.error = errorMsg;
170
+ if (this.onError) {
171
+ this.onError(entry, errorMsg);
172
+ }
173
+ // Schedule cleanup after error
174
+ this.cleanupEntries(entry.uploadName);
175
+ }
176
+ }
177
+ /**
178
+ * Upload file in chunks via WebSocket
179
+ */
180
+ async uploadChunked(entry) {
181
+ const { file, id } = entry;
182
+ let offset = 0;
183
+ // Create abort controller for cancellation
184
+ entry.abortController = new AbortController();
185
+ try {
186
+ while (offset < file.size) {
187
+ // Check if upload was cancelled
188
+ if (entry.abortController.signal.aborted) {
189
+ throw new Error("Upload cancelled");
190
+ }
191
+ // Read chunk
192
+ const end = Math.min(offset + this.chunkSize, file.size);
193
+ const chunk = file.slice(offset, end);
194
+ // Convert to base64
195
+ const base64 = await this.fileToBase64(chunk);
196
+ // Send chunk
197
+ const chunkMessage = {
198
+ action: "upload_chunk",
199
+ entry_id: id,
200
+ chunk_base64: base64,
201
+ offset,
202
+ total: file.size,
203
+ };
204
+ this.sendMessage(chunkMessage);
205
+ // Update progress
206
+ offset = end;
207
+ entry.bytesUploaded = offset;
208
+ entry.progress = Math.round((offset / file.size) * 100);
209
+ if (this.onProgress) {
210
+ this.onProgress(entry);
211
+ }
212
+ }
213
+ // Send complete message
214
+ entry.done = true;
215
+ const completeMessage = {
216
+ action: "upload_complete",
217
+ upload_name: entry.uploadName,
218
+ entry_ids: [id],
219
+ };
220
+ this.sendMessage(completeMessage);
221
+ if (this.onComplete) {
222
+ this.onComplete(entry.uploadName, [entry]);
223
+ }
224
+ // Clear the file input to prevent re-upload of the same file
225
+ this.clearFileInput(entry.uploadName);
226
+ // Schedule cleanup after completion
227
+ this.cleanupEntries(entry.uploadName);
228
+ }
229
+ catch (error) {
230
+ const errorMsg = error instanceof Error ? error.message : String(error);
231
+ entry.error = errorMsg;
232
+ if (this.onError) {
233
+ this.onError(entry, errorMsg);
234
+ }
235
+ // Schedule cleanup after error
236
+ this.cleanupEntries(entry.uploadName);
237
+ }
238
+ }
239
+ /**
240
+ * Handle progress message from server (for chunked uploads)
241
+ */
242
+ handleProgressMessage(message) {
243
+ const entry = this.entries.get(message.entry_id);
244
+ if (!entry)
245
+ return;
246
+ entry.progress = message.progress;
247
+ entry.bytesUploaded = message.bytes_recv;
248
+ if (this.onProgress) {
249
+ this.onProgress(entry);
250
+ }
251
+ }
252
+ /**
253
+ * Cancel upload
254
+ */
255
+ cancelUpload(entryId) {
256
+ const entry = this.entries.get(entryId);
257
+ if (!entry)
258
+ return;
259
+ // Abort external upload if in progress
260
+ if (entry.abortController) {
261
+ entry.abortController.abort();
262
+ }
263
+ // Send cancel message to server
264
+ this.sendMessage({
265
+ action: "cancel_upload",
266
+ entry_id: entryId,
267
+ });
268
+ // Remove entry
269
+ this.entries.delete(entryId);
270
+ }
271
+ /**
272
+ * Get all entries for an upload name
273
+ */
274
+ getEntries(uploadName) {
275
+ const entries = [];
276
+ for (const entry of this.entries.values()) {
277
+ if (entry.uploadName === uploadName) {
278
+ entries.push(entry);
279
+ }
280
+ }
281
+ return entries;
282
+ }
283
+ /**
284
+ * Trigger upload for all pending entries (used when autoUpload is false)
285
+ * Called by LiveTemplate client on form submit
286
+ */
287
+ triggerPendingUploads(uploadName) {
288
+ // Get all entries for this upload that haven't started yet
289
+ const pendingEntries = [];
290
+ for (const entry of this.entries.values()) {
291
+ if (entry.uploadName === uploadName &&
292
+ entry.progress === 0 &&
293
+ !entry.done &&
294
+ !entry.error) {
295
+ pendingEntries.push(entry);
296
+ }
297
+ }
298
+ // Start uploads
299
+ for (const entry of pendingEntries) {
300
+ if (entry.external) {
301
+ this.uploadExternal(entry, entry.external);
302
+ }
303
+ else {
304
+ this.uploadChunked(entry);
305
+ }
306
+ }
307
+ }
308
+ /**
309
+ * Register custom uploader
310
+ */
311
+ registerUploader(name, uploader) {
312
+ this.uploaders.set(name, uploader);
313
+ }
314
+ /**
315
+ * Clear file input to prevent re-upload of the same file
316
+ * Called after successful upload completion
317
+ */
318
+ clearFileInput(uploadName) {
319
+ // Find all file inputs with this upload name
320
+ const inputs = document.querySelectorAll(`input[type="file"][lvt-upload="${uploadName}"]`);
321
+ inputs.forEach((input) => {
322
+ // Clear the file input value
323
+ input.value = '';
324
+ });
325
+ }
326
+ /**
327
+ * Clean up completed or errored upload entries to prevent memory leaks
328
+ * Automatically called after completion/error, but can be called manually
329
+ * @param uploadName - Optional upload name to clean specific uploads
330
+ * @param delay - Optional delay in ms before cleanup (default: 5000ms)
331
+ */
332
+ cleanupEntries(uploadName, delay = 5000) {
333
+ setTimeout(() => {
334
+ const entriesToRemove = [];
335
+ for (const [id, entry] of this.entries) {
336
+ // Skip if uploadName is specified and doesn't match
337
+ if (uploadName && entry.uploadName !== uploadName)
338
+ continue;
339
+ // Remove completed or errored entries
340
+ if (entry.done || entry.error) {
341
+ entriesToRemove.push(id);
342
+ }
343
+ }
344
+ for (const id of entriesToRemove) {
345
+ this.entries.delete(id);
346
+ }
347
+ }, delay);
348
+ }
349
+ /**
350
+ * Convert File/Blob to base64 string
351
+ */
352
+ fileToBase64(blob) {
353
+ return new Promise((resolve, reject) => {
354
+ const reader = new FileReader();
355
+ reader.onload = () => {
356
+ const result = reader.result;
357
+ // Remove data URL prefix
358
+ const base64 = result.split(",")[1];
359
+ resolve(base64);
360
+ };
361
+ reader.onerror = reject;
362
+ reader.readAsDataURL(blob);
363
+ });
364
+ }
365
+ }
366
+ exports.UploadHandler = UploadHandler;
367
+ //# sourceMappingURL=upload-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload-handler.js","sourceRoot":"","sources":["../../upload/upload-handler.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livetemplate/client",
3
- "version": "0.1.0",
3
+ "version": "0.4.0",
4
4
  "description": "TypeScript client for LiveTemplate tree-based updates",
5
5
  "main": "dist/livetemplate-client.js",
6
6
  "browser": "dist/livetemplate-client.browser.js",
@@ -26,12 +26,11 @@
26
26
  "license": "MIT",
27
27
  "repository": {
28
28
  "type": "git",
29
- "url": "https://github.com/livetemplate/livetemplate.git",
30
- "directory": "client"
29
+ "url": "https://github.com/livetemplate/client.git"
31
30
  },
32
- "homepage": "https://github.com/livetemplate/livetemplate#readme",
31
+ "homepage": "https://github.com/livetemplate/client#readme",
33
32
  "bugs": {
34
- "url": "https://github.com/livetemplate/livetemplate/issues"
33
+ "url": "https://github.com/livetemplate/client/issues"
35
34
  },
36
35
  "publishConfig": {
37
36
  "access": "public"
@@ -43,7 +42,7 @@
43
42
  "jest": "^30.1.3",
44
43
  "jest-environment-jsdom": "^30.2.0",
45
44
  "ts-jest": "^29.4.4",
46
- "typescript": "^5.0.0"
45
+ "typescript": "^5.9.3"
47
46
  },
48
47
  "files": [
49
48
  "dist/**/*",