@hashtree/worker 0.2.0 → 0.2.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 (259) hide show
  1. package/package.json +7 -3
  2. package/src/app-runtime.ts +393 -0
  3. package/src/capabilities/blossomBandwidthTracker.ts +74 -0
  4. package/src/capabilities/blossomTransport.ts +179 -0
  5. package/src/capabilities/connectivity.ts +54 -0
  6. package/src/capabilities/idbStorage.ts +94 -0
  7. package/src/capabilities/meshRouterStore.ts +426 -0
  8. package/src/capabilities/rootResolver.ts +497 -0
  9. package/src/client-id.ts +137 -0
  10. package/src/client.ts +501 -0
  11. package/{dist/entry.js → src/entry.ts} +1 -1
  12. package/src/htree-path.ts +53 -0
  13. package/src/htree-url.ts +156 -0
  14. package/src/index.ts +76 -0
  15. package/src/mediaStreaming.ts +64 -0
  16. package/src/p2p/boundedQueue.ts +168 -0
  17. package/src/p2p/errorMessage.ts +6 -0
  18. package/src/p2p/index.ts +48 -0
  19. package/src/p2p/lruCache.ts +78 -0
  20. package/src/p2p/meshQueryRouter.ts +361 -0
  21. package/src/p2p/protocol.ts +11 -0
  22. package/src/p2p/queryForwardingMachine.ts +197 -0
  23. package/src/p2p/signaling.ts +284 -0
  24. package/src/p2p/uploadRateLimiter.ts +85 -0
  25. package/src/p2p/webrtcController.ts +1168 -0
  26. package/src/p2p/webrtcProxy.ts +519 -0
  27. package/src/privacyGuards.ts +31 -0
  28. package/src/protocol.ts +124 -0
  29. package/src/relay/identity.ts +86 -0
  30. package/src/relay/mediaHandler.ts +1633 -0
  31. package/src/relay/ndk.ts +590 -0
  32. package/{dist/relay/nostr-wasm.js → src/relay/nostr-wasm.ts} +4 -1
  33. package/src/relay/nostr.ts +249 -0
  34. package/src/relay/protocol.ts +361 -0
  35. package/src/relay/publicAssetUrl.ts +25 -0
  36. package/src/relay/rootPathResolver.ts +50 -0
  37. package/src/relay/shims.d.ts +17 -0
  38. package/src/relay/signing.ts +332 -0
  39. package/src/relay/treeRootCache.ts +354 -0
  40. package/src/relay/treeRootSubscription.ts +577 -0
  41. package/src/relay/utils/constants.ts +139 -0
  42. package/src/relay/utils/errorMessage.ts +7 -0
  43. package/src/relay/utils/lruCache.ts +79 -0
  44. package/src/relay/webrtc.ts +5 -0
  45. package/src/relay/webrtcSignaling.ts +108 -0
  46. package/src/relay/worker.ts +1787 -0
  47. package/src/relay-client.ts +265 -0
  48. package/src/relay-entry.ts +1 -0
  49. package/src/runtime-network.ts +134 -0
  50. package/src/runtime.ts +153 -0
  51. package/{dist/transferableBytes.js → src/transferableBytes.ts} +2 -3
  52. package/src/tree-root.ts +851 -0
  53. package/src/types.ts +8 -0
  54. package/src/worker.ts +975 -0
  55. package/dist/app-runtime.d.ts +0 -60
  56. package/dist/app-runtime.d.ts.map +0 -1
  57. package/dist/app-runtime.js +0 -271
  58. package/dist/app-runtime.js.map +0 -1
  59. package/dist/capabilities/blossomBandwidthTracker.d.ts +0 -26
  60. package/dist/capabilities/blossomBandwidthTracker.d.ts.map +0 -1
  61. package/dist/capabilities/blossomBandwidthTracker.js +0 -53
  62. package/dist/capabilities/blossomBandwidthTracker.js.map +0 -1
  63. package/dist/capabilities/blossomTransport.d.ts +0 -22
  64. package/dist/capabilities/blossomTransport.d.ts.map +0 -1
  65. package/dist/capabilities/blossomTransport.js +0 -139
  66. package/dist/capabilities/blossomTransport.js.map +0 -1
  67. package/dist/capabilities/connectivity.d.ts +0 -3
  68. package/dist/capabilities/connectivity.d.ts.map +0 -1
  69. package/dist/capabilities/connectivity.js +0 -49
  70. package/dist/capabilities/connectivity.js.map +0 -1
  71. package/dist/capabilities/idbStorage.d.ts +0 -25
  72. package/dist/capabilities/idbStorage.d.ts.map +0 -1
  73. package/dist/capabilities/idbStorage.js +0 -73
  74. package/dist/capabilities/idbStorage.js.map +0 -1
  75. package/dist/capabilities/meshRouterStore.d.ts +0 -71
  76. package/dist/capabilities/meshRouterStore.d.ts.map +0 -1
  77. package/dist/capabilities/meshRouterStore.js +0 -316
  78. package/dist/capabilities/meshRouterStore.js.map +0 -1
  79. package/dist/capabilities/rootResolver.d.ts +0 -10
  80. package/dist/capabilities/rootResolver.d.ts.map +0 -1
  81. package/dist/capabilities/rootResolver.js +0 -392
  82. package/dist/capabilities/rootResolver.js.map +0 -1
  83. package/dist/client-id.d.ts +0 -18
  84. package/dist/client-id.d.ts.map +0 -1
  85. package/dist/client-id.js +0 -98
  86. package/dist/client-id.js.map +0 -1
  87. package/dist/client.d.ts +0 -61
  88. package/dist/client.d.ts.map +0 -1
  89. package/dist/client.js +0 -417
  90. package/dist/client.js.map +0 -1
  91. package/dist/entry.d.ts +0 -2
  92. package/dist/entry.d.ts.map +0 -1
  93. package/dist/entry.js.map +0 -1
  94. package/dist/htree-path.d.ts +0 -13
  95. package/dist/htree-path.d.ts.map +0 -1
  96. package/dist/htree-path.js +0 -38
  97. package/dist/htree-path.js.map +0 -1
  98. package/dist/htree-url.d.ts +0 -22
  99. package/dist/htree-url.d.ts.map +0 -1
  100. package/dist/htree-url.js +0 -118
  101. package/dist/htree-url.js.map +0 -1
  102. package/dist/index.d.ts +0 -17
  103. package/dist/index.d.ts.map +0 -1
  104. package/dist/index.js +0 -8
  105. package/dist/index.js.map +0 -1
  106. package/dist/mediaStreaming.d.ts +0 -7
  107. package/dist/mediaStreaming.d.ts.map +0 -1
  108. package/dist/mediaStreaming.js +0 -48
  109. package/dist/mediaStreaming.js.map +0 -1
  110. package/dist/p2p/boundedQueue.d.ts +0 -79
  111. package/dist/p2p/boundedQueue.d.ts.map +0 -1
  112. package/dist/p2p/boundedQueue.js +0 -134
  113. package/dist/p2p/boundedQueue.js.map +0 -1
  114. package/dist/p2p/errorMessage.d.ts +0 -5
  115. package/dist/p2p/errorMessage.d.ts.map +0 -1
  116. package/dist/p2p/errorMessage.js +0 -7
  117. package/dist/p2p/errorMessage.js.map +0 -1
  118. package/dist/p2p/index.d.ts +0 -8
  119. package/dist/p2p/index.d.ts.map +0 -1
  120. package/dist/p2p/index.js +0 -6
  121. package/dist/p2p/index.js.map +0 -1
  122. package/dist/p2p/lruCache.d.ts +0 -26
  123. package/dist/p2p/lruCache.d.ts.map +0 -1
  124. package/dist/p2p/lruCache.js +0 -65
  125. package/dist/p2p/lruCache.js.map +0 -1
  126. package/dist/p2p/meshQueryRouter.d.ts +0 -57
  127. package/dist/p2p/meshQueryRouter.d.ts.map +0 -1
  128. package/dist/p2p/meshQueryRouter.js +0 -264
  129. package/dist/p2p/meshQueryRouter.js.map +0 -1
  130. package/dist/p2p/protocol.d.ts +0 -10
  131. package/dist/p2p/protocol.d.ts.map +0 -1
  132. package/dist/p2p/protocol.js +0 -2
  133. package/dist/p2p/protocol.js.map +0 -1
  134. package/dist/p2p/queryForwardingMachine.d.ts +0 -46
  135. package/dist/p2p/queryForwardingMachine.d.ts.map +0 -1
  136. package/dist/p2p/queryForwardingMachine.js +0 -144
  137. package/dist/p2p/queryForwardingMachine.js.map +0 -1
  138. package/dist/p2p/signaling.d.ts +0 -63
  139. package/dist/p2p/signaling.d.ts.map +0 -1
  140. package/dist/p2p/signaling.js +0 -185
  141. package/dist/p2p/signaling.js.map +0 -1
  142. package/dist/p2p/uploadRateLimiter.d.ts +0 -21
  143. package/dist/p2p/uploadRateLimiter.d.ts.map +0 -1
  144. package/dist/p2p/uploadRateLimiter.js +0 -62
  145. package/dist/p2p/uploadRateLimiter.js.map +0 -1
  146. package/dist/p2p/webrtcController.d.ts +0 -176
  147. package/dist/p2p/webrtcController.d.ts.map +0 -1
  148. package/dist/p2p/webrtcController.js +0 -938
  149. package/dist/p2p/webrtcController.js.map +0 -1
  150. package/dist/p2p/webrtcProxy.d.ts +0 -62
  151. package/dist/p2p/webrtcProxy.d.ts.map +0 -1
  152. package/dist/p2p/webrtcProxy.js +0 -447
  153. package/dist/p2p/webrtcProxy.js.map +0 -1
  154. package/dist/privacyGuards.d.ts +0 -14
  155. package/dist/privacyGuards.d.ts.map +0 -1
  156. package/dist/privacyGuards.js +0 -27
  157. package/dist/privacyGuards.js.map +0 -1
  158. package/dist/protocol.d.ts +0 -225
  159. package/dist/protocol.d.ts.map +0 -1
  160. package/dist/protocol.js +0 -2
  161. package/dist/protocol.js.map +0 -1
  162. package/dist/relay/identity.d.ts +0 -36
  163. package/dist/relay/identity.d.ts.map +0 -1
  164. package/dist/relay/identity.js +0 -78
  165. package/dist/relay/identity.js.map +0 -1
  166. package/dist/relay/mediaHandler.d.ts +0 -64
  167. package/dist/relay/mediaHandler.d.ts.map +0 -1
  168. package/dist/relay/mediaHandler.js +0 -1285
  169. package/dist/relay/mediaHandler.js.map +0 -1
  170. package/dist/relay/ndk.d.ts +0 -96
  171. package/dist/relay/ndk.d.ts.map +0 -1
  172. package/dist/relay/ndk.js +0 -502
  173. package/dist/relay/ndk.js.map +0 -1
  174. package/dist/relay/nostr-wasm.d.ts +0 -14
  175. package/dist/relay/nostr-wasm.d.ts.map +0 -1
  176. package/dist/relay/nostr-wasm.js.map +0 -1
  177. package/dist/relay/nostr.d.ts +0 -60
  178. package/dist/relay/nostr.d.ts.map +0 -1
  179. package/dist/relay/nostr.js +0 -207
  180. package/dist/relay/nostr.js.map +0 -1
  181. package/dist/relay/protocol.d.ts +0 -592
  182. package/dist/relay/protocol.d.ts.map +0 -1
  183. package/dist/relay/protocol.js +0 -16
  184. package/dist/relay/protocol.js.map +0 -1
  185. package/dist/relay/publicAssetUrl.d.ts +0 -6
  186. package/dist/relay/publicAssetUrl.d.ts.map +0 -1
  187. package/dist/relay/publicAssetUrl.js +0 -14
  188. package/dist/relay/publicAssetUrl.js.map +0 -1
  189. package/dist/relay/rootPathResolver.d.ts +0 -9
  190. package/dist/relay/rootPathResolver.d.ts.map +0 -1
  191. package/dist/relay/rootPathResolver.js +0 -32
  192. package/dist/relay/rootPathResolver.js.map +0 -1
  193. package/dist/relay/signing.d.ts +0 -50
  194. package/dist/relay/signing.d.ts.map +0 -1
  195. package/dist/relay/signing.js +0 -299
  196. package/dist/relay/signing.js.map +0 -1
  197. package/dist/relay/treeRootCache.d.ts +0 -86
  198. package/dist/relay/treeRootCache.d.ts.map +0 -1
  199. package/dist/relay/treeRootCache.js +0 -269
  200. package/dist/relay/treeRootCache.js.map +0 -1
  201. package/dist/relay/treeRootSubscription.d.ts +0 -55
  202. package/dist/relay/treeRootSubscription.d.ts.map +0 -1
  203. package/dist/relay/treeRootSubscription.js +0 -478
  204. package/dist/relay/treeRootSubscription.js.map +0 -1
  205. package/dist/relay/utils/constants.d.ts +0 -76
  206. package/dist/relay/utils/constants.d.ts.map +0 -1
  207. package/dist/relay/utils/constants.js +0 -113
  208. package/dist/relay/utils/constants.js.map +0 -1
  209. package/dist/relay/utils/errorMessage.d.ts +0 -5
  210. package/dist/relay/utils/errorMessage.d.ts.map +0 -1
  211. package/dist/relay/utils/errorMessage.js +0 -8
  212. package/dist/relay/utils/errorMessage.js.map +0 -1
  213. package/dist/relay/utils/lruCache.d.ts +0 -26
  214. package/dist/relay/utils/lruCache.d.ts.map +0 -1
  215. package/dist/relay/utils/lruCache.js +0 -66
  216. package/dist/relay/utils/lruCache.js.map +0 -1
  217. package/dist/relay/webrtc.d.ts +0 -2
  218. package/dist/relay/webrtc.d.ts.map +0 -1
  219. package/dist/relay/webrtc.js +0 -3
  220. package/dist/relay/webrtc.js.map +0 -1
  221. package/dist/relay/webrtcSignaling.d.ts +0 -37
  222. package/dist/relay/webrtcSignaling.d.ts.map +0 -1
  223. package/dist/relay/webrtcSignaling.js +0 -86
  224. package/dist/relay/webrtcSignaling.js.map +0 -1
  225. package/dist/relay/worker.d.ts +0 -12
  226. package/dist/relay/worker.d.ts.map +0 -1
  227. package/dist/relay/worker.js +0 -1540
  228. package/dist/relay/worker.js.map +0 -1
  229. package/dist/relay-client.d.ts +0 -31
  230. package/dist/relay-client.d.ts.map +0 -1
  231. package/dist/relay-client.js +0 -197
  232. package/dist/relay-client.js.map +0 -1
  233. package/dist/relay-entry.d.ts +0 -2
  234. package/dist/relay-entry.d.ts.map +0 -1
  235. package/dist/relay-entry.js +0 -2
  236. package/dist/relay-entry.js.map +0 -1
  237. package/dist/runtime-network.d.ts +0 -23
  238. package/dist/runtime-network.d.ts.map +0 -1
  239. package/dist/runtime-network.js +0 -105
  240. package/dist/runtime-network.js.map +0 -1
  241. package/dist/runtime.d.ts +0 -24
  242. package/dist/runtime.d.ts.map +0 -1
  243. package/dist/runtime.js +0 -126
  244. package/dist/runtime.js.map +0 -1
  245. package/dist/transferableBytes.d.ts +0 -2
  246. package/dist/transferableBytes.d.ts.map +0 -1
  247. package/dist/transferableBytes.js.map +0 -1
  248. package/dist/tree-root.d.ts +0 -201
  249. package/dist/tree-root.d.ts.map +0 -1
  250. package/dist/tree-root.js +0 -632
  251. package/dist/tree-root.js.map +0 -1
  252. package/dist/types.d.ts +0 -2
  253. package/dist/types.d.ts.map +0 -1
  254. package/dist/types.js +0 -2
  255. package/dist/types.js.map +0 -1
  256. package/dist/worker.d.ts +0 -9
  257. package/dist/worker.d.ts.map +0 -1
  258. package/dist/worker.js +0 -792
  259. package/dist/worker.js.map +0 -1
package/src/index.ts ADDED
@@ -0,0 +1,76 @@
1
+ export { HashtreeWorkerClient } from './client.js';
2
+ export type { WorkerFactory, P2PFetchHandler } from './client.js';
3
+ export { RelayWorkerClient } from './relay-client.js';
4
+ export type {
5
+ TreeRootInfo as RelayTreeRootInfo,
6
+ TreeRootUpdate as RelayTreeRootUpdate,
7
+ RelayWorkerConfig,
8
+ RelayWorkerRequest,
9
+ RelayWorkerResponse,
10
+ } from './relay-client.js';
11
+ export {
12
+ canUseInjectedHtreeServerUrl,
13
+ canUseSameOriginHtreeProtocolStreaming,
14
+ getInjectedHtreeServerUrl,
15
+ resolveRuntimeHtreeBaseUrl,
16
+ shouldEagerLoadMediaInNativeChildRuntime,
17
+ shouldPreferSameOriginHtreeRoutes,
18
+ } from './runtime.js';
19
+ export type {
20
+ HtreeRuntimeLocationLike,
21
+ HtreeRuntimeWindowLike,
22
+ ResolveRuntimeHtreeBaseUrlOptions,
23
+ } from './runtime.js';
24
+ export {
25
+ resolveRuntimeEndpoints,
26
+ } from './runtime-network.js';
27
+ export type {
28
+ ResolveRuntimeEndpointsOptions,
29
+ RuntimeEndpoints,
30
+ } from './runtime-network.js';
31
+ export { createHtreeRuntime } from './app-runtime.js';
32
+ export type {
33
+ HtreeRuntime,
34
+ HtreeRuntimeEndpointOverrides,
35
+ HtreeRuntimeMediaPortOptions,
36
+ HtreeRuntimeMediaUrlOptions,
37
+ HtreeRuntimeOptions,
38
+ HtreeRuntimeRequestUrlOptions,
39
+ HtreeRuntimeWorkerConfigOptions,
40
+ RuntimeValueSource,
41
+ } from './app-runtime.js';
42
+ export {
43
+ buildHtreeRequestPath,
44
+ parseHtreeUrl,
45
+ resolveHtreeRequestUrl,
46
+ } from './htree-url.js';
47
+ export type {
48
+ MutableHtreeRequestStyle,
49
+ ParsedHtreeUrl,
50
+ ResolveHtreeRequestUrlOptions,
51
+ } from './htree-url.js';
52
+ export type { HtreeClientIdStorageLike } from './client-id.js';
53
+ export type {
54
+ BlossomServerConfig,
55
+ WorkerConfig,
56
+ WorkerRequest,
57
+ WorkerResponse,
58
+ RootResolveOptions,
59
+ ConnectivityState,
60
+ UploadProgressState,
61
+ WorkerDiagnosticEvent,
62
+ WorkerDiagnosticLevel,
63
+ BlossomBandwidthState,
64
+ BlossomBandwidthServerStats,
65
+ BlobSource,
66
+ } from './protocol.js';
67
+
68
+ export {
69
+ WebRTCController,
70
+ WebRTCProxy,
71
+ initWebRTCProxy,
72
+ getWebRTCProxy,
73
+ closeWebRTCProxy,
74
+ } from './p2p/index.js';
75
+
76
+ export type { WebRTCControllerConfig } from './p2p/index.js';
@@ -0,0 +1,64 @@
1
+ import type { CID, HashTree } from '@hashtree/core';
2
+
3
+ const DEFAULT_PREFETCH = 2;
4
+
5
+ /**
6
+ * Stream a bounded byte range from a CID without materializing the whole range in memory.
7
+ * Output chunks are capped at `chunkSize` bytes.
8
+ */
9
+ export async function* streamFileRangeChunks(
10
+ tree: Pick<HashTree, 'readFileStream'>,
11
+ cid: CID,
12
+ start: number,
13
+ endInclusive: number,
14
+ chunkSize: number,
15
+ prefetch: number = DEFAULT_PREFETCH
16
+ ): AsyncGenerator<Uint8Array> {
17
+ if (chunkSize <= 0) {
18
+ throw new Error('chunkSize must be > 0');
19
+ }
20
+ if (endInclusive < start) {
21
+ return;
22
+ }
23
+
24
+ let remaining = endInclusive - start + 1;
25
+ let pending = new Uint8Array(chunkSize);
26
+ let pendingLength = 0;
27
+
28
+ for await (const sourceChunk of tree.readFileStream(cid, { offset: start, prefetch })) {
29
+ if (remaining <= 0) break;
30
+ if (sourceChunk.byteLength === 0) continue;
31
+
32
+ const consumed = Math.min(sourceChunk.byteLength, remaining);
33
+ const source = consumed === sourceChunk.byteLength ? sourceChunk : sourceChunk.subarray(0, consumed);
34
+ remaining -= consumed;
35
+
36
+ let cursor = 0;
37
+ while (cursor < source.byteLength) {
38
+ const available = source.byteLength - cursor;
39
+
40
+ if (pendingLength === 0 && available >= chunkSize) {
41
+ // Emit direct full-size chunks with independent buffers for transfer.
42
+ yield source.slice(cursor, cursor + chunkSize);
43
+ cursor += chunkSize;
44
+ continue;
45
+ }
46
+
47
+ const toCopy = Math.min(chunkSize - pendingLength, available);
48
+ pending.set(source.subarray(cursor, cursor + toCopy), pendingLength);
49
+ pendingLength += toCopy;
50
+ cursor += toCopy;
51
+
52
+ if (pendingLength === chunkSize) {
53
+ yield pending;
54
+ pending = new Uint8Array(chunkSize);
55
+ pendingLength = 0;
56
+ }
57
+ }
58
+ }
59
+
60
+ if (pendingLength > 0) {
61
+ yield pending.slice(0, pendingLength);
62
+ }
63
+ }
64
+
@@ -0,0 +1,168 @@
1
+ /**
2
+ * BoundedQueue - Memory-safe queue with size limits
3
+ *
4
+ * Prevents memory blowup by enforcing both item count and byte limits.
5
+ * When limits are exceeded, oldest items are dropped (FIFO eviction).
6
+ *
7
+ * Use this instead of plain arrays for queues that could grow unbounded,
8
+ * especially for network buffers, send queues, and work queues.
9
+ */
10
+
11
+ export interface BoundedQueueOptions<T> {
12
+ /** Maximum number of items in queue */
13
+ maxItems: number;
14
+ /** Maximum total bytes in queue */
15
+ maxBytes: number;
16
+ /** Function to get byte size of an item */
17
+ getBytes: (item: T) => number;
18
+ /** Optional callback when items are dropped due to overflow */
19
+ onDrop?: (item: T, reason: 'items' | 'bytes') => void;
20
+ }
21
+
22
+ export class BoundedQueue<T> {
23
+ private items: T[] = [];
24
+ private bytesUsed = 0;
25
+ private readonly maxItems: number;
26
+ private readonly maxBytes: number;
27
+ private readonly getBytes: (item: T) => number;
28
+ private readonly onDrop?: (item: T, reason: 'items' | 'bytes') => void;
29
+
30
+ constructor(options: BoundedQueueOptions<T>) {
31
+ this.maxItems = options.maxItems;
32
+ this.maxBytes = options.maxBytes;
33
+ this.getBytes = options.getBytes;
34
+ this.onDrop = options.onDrop;
35
+ }
36
+
37
+ /**
38
+ * Add item to queue, dropping oldest items if limits exceeded
39
+ * @returns Number of items dropped to make room
40
+ */
41
+ push(item: T): number {
42
+ const itemBytes = this.getBytes(item);
43
+ let dropped = 0;
44
+
45
+ // Drop oldest items until we have room
46
+ while (
47
+ this.items.length > 0 &&
48
+ (this.items.length >= this.maxItems || this.bytesUsed + itemBytes > this.maxBytes)
49
+ ) {
50
+ const droppedItem = this.items.shift()!;
51
+ const droppedBytes = this.getBytes(droppedItem);
52
+ this.bytesUsed -= droppedBytes;
53
+ dropped++;
54
+
55
+ if (this.onDrop) {
56
+ const reason = this.items.length >= this.maxItems ? 'items' : 'bytes';
57
+ this.onDrop(droppedItem, reason);
58
+ }
59
+ }
60
+
61
+ this.items.push(item);
62
+ this.bytesUsed += itemBytes;
63
+ return dropped;
64
+ }
65
+
66
+ /**
67
+ * Add item to the front of the queue, dropping items from the back if limits are exceeded.
68
+ * Useful for urgent control messages that should overtake bulk background traffic.
69
+ */
70
+ unshift(item: T): number {
71
+ const itemBytes = this.getBytes(item);
72
+ let dropped = 0;
73
+
74
+ while (
75
+ this.items.length > 0 &&
76
+ (this.items.length >= this.maxItems || this.bytesUsed + itemBytes > this.maxBytes)
77
+ ) {
78
+ const droppedItem = this.items.pop()!;
79
+ const droppedBytes = this.getBytes(droppedItem);
80
+ this.bytesUsed -= droppedBytes;
81
+ dropped++;
82
+
83
+ if (this.onDrop) {
84
+ const reason = this.items.length >= this.maxItems ? 'items' : 'bytes';
85
+ this.onDrop(droppedItem, reason);
86
+ }
87
+ }
88
+
89
+ this.items.unshift(item);
90
+ this.bytesUsed += itemBytes;
91
+ return dropped;
92
+ }
93
+
94
+ /**
95
+ * Remove and return oldest item, or undefined if empty
96
+ */
97
+ shift(): T | undefined {
98
+ const item = this.items.shift();
99
+ if (item !== undefined) {
100
+ this.bytesUsed -= this.getBytes(item);
101
+ }
102
+ return item;
103
+ }
104
+
105
+ /**
106
+ * Peek at oldest item without removing
107
+ */
108
+ peek(): T | undefined {
109
+ return this.items[0];
110
+ }
111
+
112
+ /**
113
+ * Clear all items
114
+ */
115
+ clear(): void {
116
+ this.items = [];
117
+ this.bytesUsed = 0;
118
+ }
119
+
120
+ /**
121
+ * Get current item count
122
+ */
123
+ get length(): number {
124
+ return this.items.length;
125
+ }
126
+
127
+ /**
128
+ * Get current byte usage
129
+ */
130
+ get bytes(): number {
131
+ return this.bytesUsed;
132
+ }
133
+
134
+ /**
135
+ * Check if queue is empty
136
+ */
137
+ get isEmpty(): boolean {
138
+ return this.items.length === 0;
139
+ }
140
+
141
+ /**
142
+ * Check if queue is at item capacity
143
+ */
144
+ get isFullItems(): boolean {
145
+ return this.items.length >= this.maxItems;
146
+ }
147
+
148
+ /**
149
+ * Check if queue is at byte capacity
150
+ */
151
+ get isFullBytes(): boolean {
152
+ return this.bytesUsed >= this.maxBytes;
153
+ }
154
+
155
+ /**
156
+ * Iterate over items (does not remove them)
157
+ */
158
+ *[Symbol.iterator](): Iterator<T> {
159
+ yield* this.items;
160
+ }
161
+
162
+ /**
163
+ * Get all items as array (for iteration/reduce operations)
164
+ */
165
+ toArray(): T[] {
166
+ return [...this.items];
167
+ }
168
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Extract error message from unknown error type
3
+ */
4
+ export function getErrorMessage(err: unknown): string {
5
+ return err instanceof Error ? err.message : String(err);
6
+ }
@@ -0,0 +1,48 @@
1
+ export {
2
+ WebRTCController,
3
+ type WebRTCControllerConfig,
4
+ } from './webrtcController.js';
5
+
6
+ export {
7
+ MeshQueryRouter,
8
+ encodeForwardRequest,
9
+ type MeshQueryRouterConfig,
10
+ type MeshQueryRouterPeer,
11
+ } from './meshQueryRouter.js';
12
+
13
+ export {
14
+ QueryForwardingMachine,
15
+ type QueryForwardingMachineConfig,
16
+ type ForwardDecision,
17
+ type ForwardTimeoutEvent,
18
+ } from './queryForwardingMachine.js';
19
+
20
+ export {
21
+ WebRTCProxy,
22
+ initWebRTCProxy,
23
+ getWebRTCProxy,
24
+ closeWebRTCProxy,
25
+ } from './webrtcProxy.js';
26
+
27
+ export type {
28
+ WebRTCCommand,
29
+ WebRTCEvent,
30
+ } from './protocol.js';
31
+
32
+ export {
33
+ SIGNALING_KIND,
34
+ HELLO_TAG,
35
+ MAX_EVENT_AGE_SEC,
36
+ createSignalingFilters,
37
+ sendSignalingMessage,
38
+ decodeSignalingEvent,
39
+ } from './signaling.js';
40
+
41
+ export type {
42
+ SignalingEventLike,
43
+ GiftSeal,
44
+ SignalingTemplate,
45
+ SignalingInnerEvent,
46
+ SignalingFilters,
47
+ DecodedSignalingEvent,
48
+ } from './signaling.js';
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Simple LRU Cache implementation
3
+ */
4
+ export class LRUCache<K, V> {
5
+ private cache = new Map<K, V>();
6
+ private maxSize: number;
7
+
8
+ constructor(maxSize: number = 100) {
9
+ this.maxSize = maxSize;
10
+ }
11
+
12
+ get(key: K): V | undefined {
13
+ const value = this.cache.get(key);
14
+ if (value !== undefined) {
15
+ // Move to end (most recently used)
16
+ this.cache.delete(key);
17
+ this.cache.set(key, value);
18
+ }
19
+ return value;
20
+ }
21
+
22
+ set(key: K, value: V): void {
23
+ // Delete first to reset position if exists
24
+ this.cache.delete(key);
25
+
26
+ // Evict oldest if at capacity
27
+ if (this.cache.size >= this.maxSize) {
28
+ const oldest = this.cache.keys().next().value;
29
+ if (oldest !== undefined) {
30
+ this.cache.delete(oldest);
31
+ }
32
+ }
33
+
34
+ this.cache.set(key, value);
35
+ }
36
+
37
+ has(key: K): boolean {
38
+ return this.cache.has(key);
39
+ }
40
+
41
+ delete(key: K): boolean {
42
+ return this.cache.delete(key);
43
+ }
44
+
45
+ clear(): void {
46
+ this.cache.clear();
47
+ }
48
+
49
+ get size(): number {
50
+ return this.cache.size;
51
+ }
52
+
53
+ keys(): IterableIterator<K> {
54
+ return this.cache.keys();
55
+ }
56
+
57
+ values(): IterableIterator<V> {
58
+ return this.cache.values();
59
+ }
60
+
61
+ /**
62
+ * Iterate over all entries (note: does not update LRU order)
63
+ */
64
+ *entries(): IterableIterator<[K, V]> {
65
+ yield* this.cache.entries();
66
+ }
67
+
68
+ forEach(callback: (value: V, key: K) => void): void {
69
+ this.cache.forEach(callback);
70
+ }
71
+
72
+ /**
73
+ * Make the cache iterable
74
+ */
75
+ [Symbol.iterator](): IterableIterator<[K, V]> {
76
+ return this.entries();
77
+ }
78
+ }