@hashtree/worker 0.1.1

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.
Files changed (151) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -0
  3. package/dist/capabilities/blossomBandwidthTracker.d.ts +26 -0
  4. package/dist/capabilities/blossomBandwidthTracker.d.ts.map +1 -0
  5. package/dist/capabilities/blossomBandwidthTracker.js +53 -0
  6. package/dist/capabilities/blossomBandwidthTracker.js.map +1 -0
  7. package/dist/capabilities/blossomTransport.d.ts +22 -0
  8. package/dist/capabilities/blossomTransport.d.ts.map +1 -0
  9. package/dist/capabilities/blossomTransport.js +124 -0
  10. package/dist/capabilities/blossomTransport.js.map +1 -0
  11. package/dist/capabilities/connectivity.d.ts +3 -0
  12. package/dist/capabilities/connectivity.d.ts.map +1 -0
  13. package/dist/capabilities/connectivity.js +49 -0
  14. package/dist/capabilities/connectivity.js.map +1 -0
  15. package/dist/capabilities/idbStorage.d.ts +25 -0
  16. package/dist/capabilities/idbStorage.d.ts.map +1 -0
  17. package/dist/capabilities/idbStorage.js +73 -0
  18. package/dist/capabilities/idbStorage.js.map +1 -0
  19. package/dist/client.d.ts +54 -0
  20. package/dist/client.d.ts.map +1 -0
  21. package/dist/client.js +336 -0
  22. package/dist/client.js.map +1 -0
  23. package/dist/entry.d.ts +2 -0
  24. package/dist/entry.d.ts.map +1 -0
  25. package/dist/entry.js +2 -0
  26. package/dist/entry.js.map +1 -0
  27. package/dist/index.d.ts +6 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +3 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/iris/identity.d.ts +36 -0
  32. package/dist/iris/identity.d.ts.map +1 -0
  33. package/dist/iris/identity.js +78 -0
  34. package/dist/iris/identity.js.map +1 -0
  35. package/dist/iris/mediaHandler.d.ts +16 -0
  36. package/dist/iris/mediaHandler.d.ts.map +1 -0
  37. package/dist/iris/mediaHandler.js +529 -0
  38. package/dist/iris/mediaHandler.js.map +1 -0
  39. package/dist/iris/ndk.d.ts +95 -0
  40. package/dist/iris/ndk.d.ts.map +1 -0
  41. package/dist/iris/ndk.js +496 -0
  42. package/dist/iris/ndk.js.map +1 -0
  43. package/dist/iris/nostr-wasm.d.ts +14 -0
  44. package/dist/iris/nostr-wasm.d.ts.map +1 -0
  45. package/dist/iris/nostr-wasm.js +246 -0
  46. package/dist/iris/nostr-wasm.js.map +1 -0
  47. package/dist/iris/nostr.d.ts +60 -0
  48. package/dist/iris/nostr.d.ts.map +1 -0
  49. package/dist/iris/nostr.js +207 -0
  50. package/dist/iris/nostr.js.map +1 -0
  51. package/dist/iris/protocol.d.ts +574 -0
  52. package/dist/iris/protocol.d.ts.map +1 -0
  53. package/dist/iris/protocol.js +16 -0
  54. package/dist/iris/protocol.js.map +1 -0
  55. package/dist/iris/signing.d.ts +50 -0
  56. package/dist/iris/signing.d.ts.map +1 -0
  57. package/dist/iris/signing.js +299 -0
  58. package/dist/iris/signing.js.map +1 -0
  59. package/dist/iris/treeRootCache.d.ts +73 -0
  60. package/dist/iris/treeRootCache.d.ts.map +1 -0
  61. package/dist/iris/treeRootCache.js +191 -0
  62. package/dist/iris/treeRootCache.js.map +1 -0
  63. package/dist/iris/treeRootSubscription.d.ts +49 -0
  64. package/dist/iris/treeRootSubscription.d.ts.map +1 -0
  65. package/dist/iris/treeRootSubscription.js +185 -0
  66. package/dist/iris/treeRootSubscription.js.map +1 -0
  67. package/dist/iris/utils/constants.d.ts +76 -0
  68. package/dist/iris/utils/constants.d.ts.map +1 -0
  69. package/dist/iris/utils/constants.js +113 -0
  70. package/dist/iris/utils/constants.js.map +1 -0
  71. package/dist/iris/utils/errorMessage.d.ts +5 -0
  72. package/dist/iris/utils/errorMessage.d.ts.map +1 -0
  73. package/dist/iris/utils/errorMessage.js +8 -0
  74. package/dist/iris/utils/errorMessage.js.map +1 -0
  75. package/dist/iris/utils/lruCache.d.ts +26 -0
  76. package/dist/iris/utils/lruCache.d.ts.map +1 -0
  77. package/dist/iris/utils/lruCache.js +66 -0
  78. package/dist/iris/utils/lruCache.js.map +1 -0
  79. package/dist/iris/webrtc.d.ts +2 -0
  80. package/dist/iris/webrtc.d.ts.map +1 -0
  81. package/dist/iris/webrtc.js +3 -0
  82. package/dist/iris/webrtc.js.map +1 -0
  83. package/dist/iris/webrtcSignaling.d.ts +37 -0
  84. package/dist/iris/webrtcSignaling.d.ts.map +1 -0
  85. package/dist/iris/webrtcSignaling.js +86 -0
  86. package/dist/iris/webrtcSignaling.js.map +1 -0
  87. package/dist/iris/worker.d.ts +12 -0
  88. package/dist/iris/worker.d.ts.map +1 -0
  89. package/dist/iris/worker.js +1582 -0
  90. package/dist/iris/worker.js.map +1 -0
  91. package/dist/iris-entry.d.ts +2 -0
  92. package/dist/iris-entry.d.ts.map +1 -0
  93. package/dist/iris-entry.js +2 -0
  94. package/dist/iris-entry.js.map +1 -0
  95. package/dist/mediaStreaming.d.ts +7 -0
  96. package/dist/mediaStreaming.d.ts.map +1 -0
  97. package/dist/mediaStreaming.js +48 -0
  98. package/dist/mediaStreaming.js.map +1 -0
  99. package/dist/p2p/boundedQueue.d.ts +74 -0
  100. package/dist/p2p/boundedQueue.d.ts.map +1 -0
  101. package/dist/p2p/boundedQueue.js +112 -0
  102. package/dist/p2p/boundedQueue.js.map +1 -0
  103. package/dist/p2p/errorMessage.d.ts +5 -0
  104. package/dist/p2p/errorMessage.d.ts.map +1 -0
  105. package/dist/p2p/errorMessage.js +7 -0
  106. package/dist/p2p/errorMessage.js.map +1 -0
  107. package/dist/p2p/index.d.ts +7 -0
  108. package/dist/p2p/index.d.ts.map +1 -0
  109. package/dist/p2p/index.js +5 -0
  110. package/dist/p2p/index.js.map +1 -0
  111. package/dist/p2p/lruCache.d.ts +26 -0
  112. package/dist/p2p/lruCache.d.ts.map +1 -0
  113. package/dist/p2p/lruCache.js +65 -0
  114. package/dist/p2p/lruCache.js.map +1 -0
  115. package/dist/p2p/protocol.d.ts +10 -0
  116. package/dist/p2p/protocol.d.ts.map +1 -0
  117. package/dist/p2p/protocol.js +2 -0
  118. package/dist/p2p/protocol.js.map +1 -0
  119. package/dist/p2p/queryForwardingMachine.d.ts +46 -0
  120. package/dist/p2p/queryForwardingMachine.d.ts.map +1 -0
  121. package/dist/p2p/queryForwardingMachine.js +144 -0
  122. package/dist/p2p/queryForwardingMachine.js.map +1 -0
  123. package/dist/p2p/signaling.d.ts +63 -0
  124. package/dist/p2p/signaling.d.ts.map +1 -0
  125. package/dist/p2p/signaling.js +165 -0
  126. package/dist/p2p/signaling.js.map +1 -0
  127. package/dist/p2p/webrtcController.d.ts +152 -0
  128. package/dist/p2p/webrtcController.d.ts.map +1 -0
  129. package/dist/p2p/webrtcController.js +813 -0
  130. package/dist/p2p/webrtcController.js.map +1 -0
  131. package/dist/p2p/webrtcProxy.d.ts +55 -0
  132. package/dist/p2p/webrtcProxy.d.ts.map +1 -0
  133. package/dist/p2p/webrtcProxy.js +386 -0
  134. package/dist/p2p/webrtcProxy.js.map +1 -0
  135. package/dist/privacyGuards.d.ts +14 -0
  136. package/dist/privacyGuards.d.ts.map +1 -0
  137. package/dist/privacyGuards.js +27 -0
  138. package/dist/privacyGuards.js.map +1 -0
  139. package/dist/protocol.d.ts +171 -0
  140. package/dist/protocol.d.ts.map +1 -0
  141. package/dist/protocol.js +2 -0
  142. package/dist/protocol.js.map +1 -0
  143. package/dist/types.d.ts +2 -0
  144. package/dist/types.d.ts.map +1 -0
  145. package/dist/types.js +2 -0
  146. package/dist/types.js.map +1 -0
  147. package/dist/worker.d.ts +2 -0
  148. package/dist/worker.d.ts.map +1 -0
  149. package/dist/worker.js +616 -0
  150. package/dist/worker.js.map +1 -0
  151. package/package.json +64 -0
@@ -0,0 +1,529 @@
1
+ // @ts-nocheck
2
+ /**
3
+ * Media Streaming Handler for Hashtree Worker
4
+ *
5
+ * Handles media requests from the service worker via MessagePort.
6
+ * Supports both direct CID-based requests and path-based requests with live streaming.
7
+ */
8
+ import { getCachedRoot } from './treeRootCache';
9
+ import { subscribeToTreeRoots } from './treeRootSubscription';
10
+ import { getErrorMessage } from './utils/errorMessage';
11
+ import { nhashDecode } from '@hashtree/core';
12
+ import { nip19 } from 'nostr-tools';
13
+ // Thumbnail filename patterns to look for (in priority order)
14
+ const THUMBNAIL_PATTERNS = ['thumbnail.jpg', 'thumbnail.webp', 'thumbnail.png', 'thumbnail.jpeg'];
15
+ // Timeout for considering a stream "done" (no updates)
16
+ const LIVE_STREAM_TIMEOUT = 10000; // 10 seconds
17
+ const ROOT_WAIT_TIMEOUT_MS = 15000;
18
+ const ROOT_WAIT_INTERVAL_MS = 200;
19
+ // Chunk size for streaming to media port
20
+ const MEDIA_CHUNK_SIZE = 256 * 1024; // 256KB chunks - matches videoChunker's firstChunkSize
21
+ const activeMediaStreams = new Map();
22
+ let mediaPort = null;
23
+ let tree = null;
24
+ let mediaDebugEnabled = false;
25
+ function logMediaDebug(event, data) {
26
+ if (!mediaDebugEnabled)
27
+ return;
28
+ if (data) {
29
+ console.log(`[WorkerMedia] ${event}`, data);
30
+ }
31
+ else {
32
+ console.log(`[WorkerMedia] ${event}`);
33
+ }
34
+ }
35
+ /**
36
+ * Initialize the media handler with the HashTree instance
37
+ */
38
+ export function initMediaHandler(hashTree) {
39
+ tree = hashTree;
40
+ }
41
+ /**
42
+ * Register a MessagePort from the service worker for media streaming
43
+ */
44
+ export function registerMediaPort(port, debug) {
45
+ mediaPort = port;
46
+ mediaDebugEnabled = !!debug;
47
+ port.onmessage = async (e) => {
48
+ const req = e.data;
49
+ if (req.type === 'hashtree-file') {
50
+ // SW file request format (direct from service worker)
51
+ await handleSwFileRequest(req);
52
+ }
53
+ else if (req.type === 'media') {
54
+ await handleMediaRequestByCid(req);
55
+ }
56
+ else if (req.type === 'mediaByPath') {
57
+ await handleMediaRequestByPath(req);
58
+ }
59
+ else if (req.type === 'cancelMedia') {
60
+ // Cancel an active stream
61
+ const stream = activeMediaStreams.get(req.requestId);
62
+ if (stream) {
63
+ stream.cancelled = true;
64
+ activeMediaStreams.delete(req.requestId);
65
+ }
66
+ }
67
+ };
68
+ console.log('[Worker] Media port registered');
69
+ logMediaDebug('port:registered', { debug: mediaDebugEnabled });
70
+ }
71
+ /**
72
+ * Handle direct CID-based media request
73
+ */
74
+ async function handleMediaRequestByCid(req) {
75
+ if (!tree || !mediaPort)
76
+ return;
77
+ const { requestId, cid: cidHex, start, end, mimeType } = req;
78
+ try {
79
+ // Convert hex CID to proper CID object
80
+ const hash = new Uint8Array(cidHex.length / 2);
81
+ for (let i = 0; i < hash.length; i++) {
82
+ hash[i] = parseInt(cidHex.substr(i * 2, 2), 16);
83
+ }
84
+ const cid = { hash };
85
+ // Get file size first
86
+ const totalSize = await tree.getSize(hash);
87
+ // Send headers
88
+ mediaPort.postMessage({
89
+ type: 'headers',
90
+ requestId,
91
+ totalSize,
92
+ mimeType: mimeType || 'application/octet-stream',
93
+ isLive: false,
94
+ });
95
+ // Read range and stream chunks
96
+ const data = await tree.readFileRange(cid, start, end);
97
+ if (data) {
98
+ await streamChunksToPort(requestId, data);
99
+ }
100
+ else {
101
+ mediaPort.postMessage({
102
+ type: 'error',
103
+ requestId,
104
+ message: 'File not found',
105
+ });
106
+ }
107
+ }
108
+ catch (err) {
109
+ mediaPort.postMessage({
110
+ type: 'error',
111
+ requestId,
112
+ message: getErrorMessage(err),
113
+ });
114
+ }
115
+ }
116
+ /**
117
+ * Handle npub/path-based media request (supports live streaming)
118
+ */
119
+ async function handleMediaRequestByPath(req) {
120
+ if (!tree || !mediaPort)
121
+ return;
122
+ const { requestId, npub, path, start, mimeType } = req;
123
+ try {
124
+ // Parse path to get tree name
125
+ const pathParts = path.split('/').filter(Boolean);
126
+ const treeName = pathParts[0] || 'public';
127
+ const filePath = pathParts.slice(1).join('/');
128
+ // Resolve npub to current CID
129
+ let cid = await waitForCachedRoot(npub, treeName);
130
+ if (!cid) {
131
+ mediaPort.postMessage({
132
+ type: 'error',
133
+ requestId,
134
+ message: `Tree root not found for ${npub}/${treeName}`,
135
+ });
136
+ return;
137
+ }
138
+ // Navigate to file within tree if path specified
139
+ if (filePath) {
140
+ const resolved = await tree.resolvePath(cid, filePath);
141
+ if (!resolved) {
142
+ mediaPort.postMessage({
143
+ type: 'error',
144
+ requestId,
145
+ message: `File not found: ${filePath}`,
146
+ });
147
+ return;
148
+ }
149
+ cid = resolved.cid;
150
+ }
151
+ // Get file size
152
+ const totalSize = await tree.getSize(cid.hash);
153
+ // Send headers (isLive will be determined by watching for updates)
154
+ mediaPort.postMessage({
155
+ type: 'headers',
156
+ requestId,
157
+ totalSize,
158
+ mimeType: mimeType || 'application/octet-stream',
159
+ isLive: false, // Will update if we detect changes
160
+ });
161
+ // Stream initial content
162
+ const data = await tree.readFileRange(cid, start);
163
+ let offset = start;
164
+ if (data) {
165
+ await streamChunksToPort(requestId, data, false); // Don't close yet
166
+ offset += data.length;
167
+ }
168
+ // Register for live updates
169
+ const streamInfo = {
170
+ requestId,
171
+ npub,
172
+ path,
173
+ offset,
174
+ cancelled: false,
175
+ };
176
+ activeMediaStreams.set(requestId, streamInfo);
177
+ // Set up tree root watcher for this npub
178
+ // When root changes, we'll check if this file has new data
179
+ watchTreeRootForStream(npub, treeName, filePath, streamInfo);
180
+ }
181
+ catch (err) {
182
+ mediaPort.postMessage({
183
+ type: 'error',
184
+ requestId,
185
+ message: getErrorMessage(err),
186
+ });
187
+ }
188
+ }
189
+ /**
190
+ * Stream data chunks to media port
191
+ */
192
+ async function streamChunksToPort(requestId, data, sendDone = true) {
193
+ if (!mediaPort)
194
+ return;
195
+ for (let offset = 0; offset < data.length; offset += MEDIA_CHUNK_SIZE) {
196
+ const chunk = data.slice(offset, offset + MEDIA_CHUNK_SIZE);
197
+ mediaPort.postMessage({ type: 'chunk', requestId, data: chunk }, [chunk.buffer]);
198
+ }
199
+ if (sendDone) {
200
+ mediaPort.postMessage({ type: 'done', requestId });
201
+ }
202
+ }
203
+ /**
204
+ * Watch for tree root updates and push new data to stream
205
+ */
206
+ function watchTreeRootForStream(npub, treeName, filePath, streamInfo) {
207
+ let lastActivity = Date.now();
208
+ let timeoutId = null;
209
+ const checkForUpdates = async () => {
210
+ if (streamInfo.cancelled || !tree || !mediaPort) {
211
+ cleanup();
212
+ return;
213
+ }
214
+ // Check if stream timed out
215
+ if (Date.now() - lastActivity > LIVE_STREAM_TIMEOUT) {
216
+ // No updates for a while, close the stream
217
+ mediaPort.postMessage({
218
+ type: 'done',
219
+ requestId: streamInfo.requestId,
220
+ });
221
+ cleanup();
222
+ return;
223
+ }
224
+ try {
225
+ // Get current root
226
+ const cid = await getCachedRoot(npub, treeName);
227
+ if (!cid) {
228
+ scheduleNext();
229
+ return;
230
+ }
231
+ // Navigate to file
232
+ let fileCid = cid;
233
+ if (filePath) {
234
+ const resolved = await tree.resolvePath(cid, filePath);
235
+ if (!resolved) {
236
+ scheduleNext();
237
+ return;
238
+ }
239
+ fileCid = resolved.cid;
240
+ }
241
+ // Check for new data
242
+ const totalSize = await tree.getSize(fileCid.hash);
243
+ if (totalSize > streamInfo.offset) {
244
+ // New data available!
245
+ lastActivity = Date.now();
246
+ const newData = await tree.readFileRange(fileCid, streamInfo.offset);
247
+ if (newData && newData.length > 0) {
248
+ await streamChunksToPort(streamInfo.requestId, newData, false);
249
+ streamInfo.offset += newData.length;
250
+ }
251
+ }
252
+ }
253
+ catch {
254
+ // Ignore errors, just try again
255
+ }
256
+ scheduleNext();
257
+ };
258
+ const scheduleNext = () => {
259
+ if (!streamInfo.cancelled) {
260
+ timeoutId = setTimeout(checkForUpdates, 1000); // Check every second
261
+ }
262
+ };
263
+ const cleanup = () => {
264
+ if (timeoutId)
265
+ clearTimeout(timeoutId);
266
+ activeMediaStreams.delete(streamInfo.requestId);
267
+ };
268
+ // Start watching
269
+ scheduleNext();
270
+ }
271
+ /**
272
+ * Handle file request from service worker (hashtree-file format)
273
+ * This is the main entry point for direct SW → Worker communication
274
+ */
275
+ async function handleSwFileRequest(req) {
276
+ if (!tree || !mediaPort)
277
+ return;
278
+ const { requestId, npub, nhash, treeName, path, start, end, mimeType, download } = req;
279
+ logMediaDebug('sw:request', {
280
+ requestId,
281
+ npub: npub ?? null,
282
+ nhash: nhash ?? null,
283
+ treeName: treeName ?? null,
284
+ path,
285
+ start,
286
+ end: end ?? null,
287
+ mimeType,
288
+ download: !!download,
289
+ });
290
+ try {
291
+ let cid = null;
292
+ if (nhash) {
293
+ // Direct nhash request - decode to CID
294
+ const rootCid = nhashDecode(nhash);
295
+ // If path provided AND it contains a slash, navigate within the nhash directory
296
+ // Single filename without slashes is just a hint for MIME type - use rootCid directly
297
+ if (path && path.includes('/')) {
298
+ const entry = await tree.resolvePath(rootCid, path);
299
+ if (!entry) {
300
+ sendSwError(requestId, 404, `File not found: ${path}`);
301
+ return;
302
+ }
303
+ cid = entry.cid;
304
+ }
305
+ else if (path && !path.includes('/')) {
306
+ // Try to resolve as file within directory first
307
+ const entry = await tree.resolvePath(rootCid, path);
308
+ cid = entry ? entry.cid : rootCid;
309
+ }
310
+ else {
311
+ cid = rootCid;
312
+ }
313
+ }
314
+ else if (npub && treeName) {
315
+ // Npub-based request - resolve through cached root
316
+ const rootCid = await waitForCachedRoot(npub, treeName);
317
+ if (!rootCid) {
318
+ sendSwError(requestId, 404, 'Tree not found');
319
+ return;
320
+ }
321
+ // Handle thumbnail requests without extension
322
+ let resolvedPath = path || '';
323
+ if (resolvedPath.endsWith('/thumbnail') || resolvedPath === 'thumbnail') {
324
+ const dirPath = resolvedPath.endsWith('/thumbnail')
325
+ ? resolvedPath.slice(0, -'/thumbnail'.length)
326
+ : '';
327
+ const actualPath = await findThumbnailInDir(rootCid, dirPath);
328
+ if (actualPath) {
329
+ resolvedPath = actualPath;
330
+ }
331
+ }
332
+ // Navigate to file
333
+ if (resolvedPath) {
334
+ const entry = await tree.resolvePath(rootCid, resolvedPath);
335
+ if (!entry) {
336
+ sendSwError(requestId, 404, 'File not found');
337
+ return;
338
+ }
339
+ cid = entry.cid;
340
+ }
341
+ else {
342
+ cid = rootCid;
343
+ }
344
+ }
345
+ if (!cid) {
346
+ sendSwError(requestId, 400, 'Invalid request');
347
+ return;
348
+ }
349
+ // Get file size
350
+ const totalSize = await getFileSize(cid);
351
+ if (totalSize === null) {
352
+ sendSwError(requestId, 404, 'File data not found');
353
+ return;
354
+ }
355
+ // Stream the content
356
+ await streamSwResponse(requestId, cid, totalSize, {
357
+ npub,
358
+ path,
359
+ start,
360
+ end,
361
+ mimeType,
362
+ download,
363
+ });
364
+ }
365
+ catch (err) {
366
+ sendSwError(requestId, 500, getErrorMessage(err));
367
+ }
368
+ }
369
+ async function waitForCachedRoot(npub, treeName) {
370
+ let cached = await getCachedRoot(npub, treeName);
371
+ if (cached)
372
+ return cached;
373
+ const pubkey = decodeNpubToPubkey(npub);
374
+ if (pubkey) {
375
+ subscribeToTreeRoots(pubkey);
376
+ }
377
+ const deadline = Date.now() + ROOT_WAIT_TIMEOUT_MS;
378
+ while (Date.now() < deadline) {
379
+ await new Promise((resolve) => setTimeout(resolve, ROOT_WAIT_INTERVAL_MS));
380
+ cached = await getCachedRoot(npub, treeName);
381
+ if (cached)
382
+ return cached;
383
+ }
384
+ logMediaDebug('root:timeout', { npub, treeName });
385
+ return null;
386
+ }
387
+ function decodeNpubToPubkey(npub) {
388
+ if (!npub.startsWith('npub1'))
389
+ return null;
390
+ try {
391
+ const decoded = nip19.decode(npub);
392
+ if (decoded.type !== 'npub')
393
+ return null;
394
+ return decoded.data;
395
+ }
396
+ catch {
397
+ return null;
398
+ }
399
+ }
400
+ /**
401
+ * Send error response to SW
402
+ */
403
+ function sendSwError(requestId, status, message) {
404
+ if (!mediaPort)
405
+ return;
406
+ logMediaDebug('sw:error', { requestId, status, message });
407
+ mediaPort.postMessage({
408
+ type: 'error',
409
+ requestId,
410
+ status,
411
+ message,
412
+ });
413
+ }
414
+ /**
415
+ * Get file size from CID (handles both chunked and single blob files)
416
+ */
417
+ async function getFileSize(cid) {
418
+ if (!tree)
419
+ return null;
420
+ const treeNode = await tree.getTreeNode(cid);
421
+ if (treeNode) {
422
+ // Chunked file - sum link sizes from decrypted tree node
423
+ return treeNode.links.reduce((sum, l) => sum + l.size, 0);
424
+ }
425
+ // Single blob - fetch to check existence and get size
426
+ const blob = await tree.getBlob(cid.hash);
427
+ if (!blob)
428
+ return null;
429
+ // For encrypted blobs, decrypted size = encrypted size - 16 (nonce overhead)
430
+ return cid.key ? Math.max(0, blob.length - 16) : blob.length;
431
+ }
432
+ /**
433
+ * Find actual thumbnail file in a directory
434
+ */
435
+ async function findThumbnailInDir(rootCid, dirPath) {
436
+ if (!tree)
437
+ return null;
438
+ try {
439
+ // Get directory CID
440
+ const dirEntry = dirPath
441
+ ? await tree.resolvePath(rootCid, dirPath)
442
+ : { cid: rootCid };
443
+ if (!dirEntry)
444
+ return null;
445
+ // List directory contents
446
+ const entries = await tree.listDirectory(dirEntry.cid);
447
+ if (!entries)
448
+ return null;
449
+ // Find first matching thumbnail pattern
450
+ for (const pattern of THUMBNAIL_PATTERNS) {
451
+ if (entries.some(e => e.name === pattern)) {
452
+ return dirPath ? `${dirPath}/${pattern}` : pattern;
453
+ }
454
+ }
455
+ return null;
456
+ }
457
+ catch {
458
+ return null;
459
+ }
460
+ }
461
+ /**
462
+ * Stream response to SW with proper HTTP headers
463
+ */
464
+ async function streamSwResponse(requestId, cid, totalSize, options) {
465
+ if (!tree || !mediaPort)
466
+ return;
467
+ const { npub, path, start = 0, end, mimeType = 'application/octet-stream', download } = options;
468
+ const rangeStart = start;
469
+ const rangeEnd = end !== undefined ? Math.min(end, totalSize - 1) : totalSize - 1;
470
+ const contentLength = rangeEnd - rangeStart + 1;
471
+ // Build cache control header
472
+ const isNpubRequest = !!npub;
473
+ const isImage = mimeType.startsWith('image/');
474
+ let cacheControl;
475
+ if (!isNpubRequest) {
476
+ cacheControl = 'public, max-age=31536000, immutable'; // nhash: immutable
477
+ }
478
+ else if (isImage) {
479
+ cacheControl = 'public, max-age=60, stale-while-revalidate=86400';
480
+ }
481
+ else {
482
+ cacheControl = 'no-cache, no-store, must-revalidate';
483
+ }
484
+ // Build headers
485
+ const headers = {
486
+ 'Content-Type': mimeType,
487
+ 'Accept-Ranges': 'bytes',
488
+ 'Cache-Control': cacheControl,
489
+ 'Content-Length': String(contentLength),
490
+ };
491
+ if (download) {
492
+ const filename = path || 'file';
493
+ headers['Content-Disposition'] = `attachment; filename="${filename}"`;
494
+ }
495
+ // Determine status (206 for range requests)
496
+ const isRangeRequest = end !== undefined || start > 0;
497
+ const status = isRangeRequest ? 206 : 200;
498
+ if (isRangeRequest) {
499
+ headers['Content-Range'] = `bytes ${rangeStart}-${rangeEnd}/${totalSize}`;
500
+ }
501
+ logMediaDebug('sw:response', {
502
+ requestId,
503
+ status,
504
+ totalSize,
505
+ rangeStart,
506
+ rangeEnd,
507
+ });
508
+ // Send headers
509
+ mediaPort.postMessage({
510
+ type: 'headers',
511
+ requestId,
512
+ status,
513
+ headers,
514
+ totalSize,
515
+ });
516
+ // Stream chunks
517
+ let offset = rangeStart;
518
+ while (offset <= rangeEnd) {
519
+ const chunkEnd = Math.min(offset + MEDIA_CHUNK_SIZE - 1, rangeEnd);
520
+ const chunk = await tree.readFileRange(cid, offset, chunkEnd + 1);
521
+ if (!chunk)
522
+ break;
523
+ mediaPort.postMessage({ type: 'chunk', requestId, data: chunk }, [chunk.buffer]);
524
+ offset = chunkEnd + 1;
525
+ }
526
+ // Signal done
527
+ mediaPort.postMessage({ type: 'done', requestId });
528
+ }
529
+ //# sourceMappingURL=mediaHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mediaHandler.js","sourceRoot":"","sources":["../../src/iris/mediaHandler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * NDK instance for Worker
3
+ *
4
+ * Runs NDK with:
5
+ * - Real relay connections
6
+ * - ndk-cache (Dexie) for IndexedDB caching
7
+ * - nostr-wasm for fast signature verification
8
+ *
9
+ * Main thread communicates via WorkerAdapter postMessage.
10
+ */
11
+ import type { SignedEvent, NostrFilter } from './protocol';
12
+ /**
13
+ * Initialize NDK with cache and nostr-wasm
14
+ */
15
+ export declare function initNdk(relays: string[], options?: {
16
+ pubkey?: string;
17
+ nsec?: string;
18
+ }): Promise<void>;
19
+ /**
20
+ * Get the NDK instance
21
+ */
22
+ export declare function getNdk(): NDK | null;
23
+ /**
24
+ * Set event callback
25
+ */
26
+ export declare function setOnEvent(callback: (subId: string, event: SignedEvent) => void | Promise<void>): void;
27
+ /**
28
+ * Set EOSE callback
29
+ */
30
+ export declare function setOnEose(callback: (subId: string) => void): void;
31
+ /**
32
+ * Subscribe to events
33
+ */
34
+ export declare function subscribe(subId: string, filters: NostrFilter[]): void;
35
+ /**
36
+ * Unsubscribe
37
+ */
38
+ export declare function unsubscribe(subId: string): void;
39
+ /**
40
+ * Publish an event
41
+ */
42
+ export declare function publish(event: SignedEvent): Promise<void>;
43
+ /**
44
+ * Close NDK and all subscriptions
45
+ */
46
+ export declare function closeNdk(): void;
47
+ /**
48
+ * Update relays dynamically
49
+ * Disconnects old relays and connects to new ones
50
+ */
51
+ export declare function setRelays(relays: string[]): Promise<void>;
52
+ /**
53
+ * Get relay stats
54
+ */
55
+ export declare function getRelayStats(): {
56
+ url: string;
57
+ connected: boolean;
58
+ eventsReceived: number;
59
+ eventsSent: number;
60
+ }[];
61
+ /**
62
+ * Republish all user's hashtree events from cache to relays
63
+ * This helps recover when events exist locally but weren't properly published
64
+ *
65
+ * For unsigned events (never signed), we sign them using the worker's signing flow.
66
+ * For signed events, we republish directly.
67
+ * Also pushes blob data to Blossom servers.
68
+ *
69
+ * @param prefix - Optional URL-encoded prefix to filter trees by d-tag
70
+ */
71
+ export declare function republishTrees(pubkey: string, signFn: (template: {
72
+ kind: number;
73
+ created_at: number;
74
+ content: string;
75
+ tags: string[][];
76
+ }) => Promise<{
77
+ id: string;
78
+ pubkey: string;
79
+ kind: number;
80
+ content: string;
81
+ tags: string[][];
82
+ created_at: number;
83
+ sig: string;
84
+ }>, pushToBlossomFn?: (hash: Uint8Array, key?: Uint8Array, treeName?: string) => Promise<{
85
+ pushed: number;
86
+ skipped: number;
87
+ failed: number;
88
+ }>, prefix?: string): Promise<number>;
89
+ /**
90
+ * Republish a single tree's event from cache to relays
91
+ * This republishes the original event as-is (preserves signature/timestamp)
92
+ * Works for any user's tree, not just own.
93
+ */
94
+ export declare function republishTree(pubkey: string, treeName: string): Promise<boolean>;
95
+ //# sourceMappingURL=ndk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ndk.d.ts","sourceRoot":"","sources":["../../src/iris/ndk.ts"],"names":[],"mappings":"AACA;;;;;;;;;GASG;AAMH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AA2E3D;;GAEG;AACH,wBAAsB,OAAO,CAC3B,MAAM,EAAE,MAAM,EAAE,EAChB,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACV,GACL,OAAO,CAAC,IAAI,CAAC,CAoDf;AAED;;GAEG;AACH,wBAAgB,MAAM,IAAI,GAAG,GAAG,IAAI,CAEnC;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAEtG;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAEjE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI,CAwDrE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAO/C;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAiC/D;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,IAAI,CAgB/B;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA4C/D;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,EAAE,CAejH;AAED;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,CAAC,QAAQ,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAA;CAAE,KAAK,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,EACxN,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,EACzI,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CAqHjB;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA6DtF"}