@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,299 @@
1
+ // @ts-nocheck
2
+ /**
3
+ * Worker Signing & Encryption
4
+ *
5
+ * Provides signing, encryption, and gift wrap functions.
6
+ * Uses nsec directly when available, delegates to main thread otherwise.
7
+ */
8
+ import { generateSecretKey, finalizeEvent, nip44 } from 'nostr-tools';
9
+ import { getSecretKey, getPubkey, getEphemeralSecretKey } from './identity';
10
+ // Pending NIP-07 requests (waiting for main thread)
11
+ const pendingSignRequests = new Map();
12
+ const pendingEncryptRequests = new Map();
13
+ const pendingDecryptRequests = new Map();
14
+ // Response sender (set by worker.ts)
15
+ let postResponse = null;
16
+ export function setResponseSender(fn) {
17
+ postResponse = fn;
18
+ }
19
+ function bytesToHex(bytes) {
20
+ let hex = '';
21
+ for (const byte of bytes) {
22
+ hex += byte.toString(16).padStart(2, '0');
23
+ }
24
+ return hex;
25
+ }
26
+ function normalizeTagValue(value) {
27
+ if (typeof value === 'string')
28
+ return value;
29
+ if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') {
30
+ return String(value);
31
+ }
32
+ if (value == null)
33
+ return '';
34
+ if (value instanceof Uint8Array)
35
+ return bytesToHex(value);
36
+ if (ArrayBuffer.isView(value)) {
37
+ return bytesToHex(new Uint8Array(value.buffer, value.byteOffset, value.byteLength));
38
+ }
39
+ if (value instanceof ArrayBuffer)
40
+ return bytesToHex(new Uint8Array(value));
41
+ try {
42
+ return JSON.stringify(value);
43
+ }
44
+ catch {
45
+ return String(value);
46
+ }
47
+ }
48
+ function sanitizeTags(tags) {
49
+ if (!Array.isArray(tags))
50
+ return [];
51
+ let needsSanitize = false;
52
+ for (const tag of tags) {
53
+ if (!Array.isArray(tag)) {
54
+ needsSanitize = true;
55
+ break;
56
+ }
57
+ for (const value of tag) {
58
+ if (typeof value !== 'string') {
59
+ needsSanitize = true;
60
+ break;
61
+ }
62
+ }
63
+ if (needsSanitize)
64
+ break;
65
+ }
66
+ if (!needsSanitize)
67
+ return tags;
68
+ const sanitized = [];
69
+ for (const tag of tags) {
70
+ if (!Array.isArray(tag))
71
+ continue;
72
+ const normalized = [];
73
+ for (const value of tag) {
74
+ normalized.push(normalizeTagValue(value));
75
+ }
76
+ sanitized.push(normalized);
77
+ }
78
+ return sanitized;
79
+ }
80
+ // ============================================================================
81
+ // Signing
82
+ // ============================================================================
83
+ /**
84
+ * Sign an event with user's real identity.
85
+ * - For nsec login: signs directly with secret key
86
+ * - For extension login: delegates to main thread via NIP-07
87
+ */
88
+ export async function signEvent(template) {
89
+ template.tags = sanitizeTags(template.tags ?? []);
90
+ const secretKey = getSecretKey();
91
+ if (secretKey) {
92
+ const event = finalizeEvent(template, secretKey);
93
+ return {
94
+ id: event.id,
95
+ pubkey: event.pubkey,
96
+ kind: event.kind,
97
+ content: event.content,
98
+ tags: event.tags,
99
+ created_at: event.created_at,
100
+ sig: event.sig,
101
+ };
102
+ }
103
+ else {
104
+ return requestSign({
105
+ kind: template.kind,
106
+ created_at: template.created_at,
107
+ content: template.content,
108
+ tags: template.tags,
109
+ });
110
+ }
111
+ }
112
+ /**
113
+ * Synchronous sign (only works with nsec, falls back to ephemeral)
114
+ */
115
+ export function signEventSync(template) {
116
+ template.tags = sanitizeTags(template.tags ?? []);
117
+ const secretKey = getSecretKey() || getEphemeralSecretKey();
118
+ if (!secretKey) {
119
+ throw new Error('No signing key available');
120
+ }
121
+ const event = finalizeEvent(template, secretKey);
122
+ return {
123
+ id: event.id,
124
+ pubkey: event.pubkey,
125
+ kind: event.kind,
126
+ content: event.content,
127
+ tags: event.tags,
128
+ created_at: event.created_at,
129
+ sig: event.sig,
130
+ };
131
+ }
132
+ // ============================================================================
133
+ // Encryption
134
+ // ============================================================================
135
+ /**
136
+ * Encrypt plaintext for a recipient using NIP-44
137
+ */
138
+ export async function encrypt(recipientPubkey, plaintext) {
139
+ const secretKey = getSecretKey();
140
+ if (secretKey) {
141
+ const conversationKey = nip44.v2.utils.getConversationKey(secretKey, recipientPubkey);
142
+ return nip44.v2.encrypt(plaintext, conversationKey);
143
+ }
144
+ else {
145
+ return requestEncrypt(recipientPubkey, plaintext);
146
+ }
147
+ }
148
+ /**
149
+ * Decrypt ciphertext from a sender using NIP-44
150
+ */
151
+ export async function decrypt(senderPubkey, ciphertext) {
152
+ const secretKey = getSecretKey();
153
+ if (secretKey) {
154
+ const conversationKey = nip44.v2.utils.getConversationKey(secretKey, senderPubkey);
155
+ return nip44.v2.decrypt(ciphertext, conversationKey);
156
+ }
157
+ else {
158
+ return requestDecrypt(senderPubkey, ciphertext);
159
+ }
160
+ }
161
+ /**
162
+ * Gift wrap an event for private delivery.
163
+ */
164
+ export async function giftWrap(innerEvent, recipientPubkey) {
165
+ const myPubkey = getPubkey();
166
+ if (!myPubkey)
167
+ throw new Error('No pubkey available');
168
+ const seal = {
169
+ pubkey: myPubkey,
170
+ kind: innerEvent.kind,
171
+ content: innerEvent.content,
172
+ tags: innerEvent.tags,
173
+ };
174
+ // Generate ephemeral keypair for the wrapper
175
+ const ephemeralSk = generateSecretKey();
176
+ // Encrypt the seal for the recipient
177
+ const conversationKey = nip44.v2.utils.getConversationKey(ephemeralSk, recipientPubkey);
178
+ const encryptedContent = nip44.v2.encrypt(JSON.stringify(seal), conversationKey);
179
+ const createdAt = Math.floor(Date.now() / 1000);
180
+ const expiration = createdAt + 5 * 60;
181
+ const event = finalizeEvent({
182
+ kind: 25050,
183
+ created_at: createdAt,
184
+ tags: [
185
+ ['p', recipientPubkey],
186
+ ['expiration', expiration.toString()],
187
+ ],
188
+ content: encryptedContent,
189
+ }, ephemeralSk);
190
+ return {
191
+ id: event.id,
192
+ pubkey: event.pubkey,
193
+ kind: event.kind,
194
+ content: event.content,
195
+ tags: event.tags,
196
+ created_at: event.created_at,
197
+ sig: event.sig,
198
+ };
199
+ }
200
+ /**
201
+ * Unwrap a gift wrapped event.
202
+ */
203
+ export async function giftUnwrap(event) {
204
+ try {
205
+ const decrypted = await decrypt(event.pubkey, event.content);
206
+ return JSON.parse(decrypted);
207
+ }
208
+ catch {
209
+ return null;
210
+ }
211
+ }
212
+ // ============================================================================
213
+ // NIP-07 Delegation (for extension login)
214
+ // ============================================================================
215
+ async function requestSign(event) {
216
+ const id = `sign_${Date.now()}_${Math.random().toString(36).slice(2)}`;
217
+ return new Promise((resolve, reject) => {
218
+ pendingSignRequests.set(id, (signed, error) => {
219
+ if (error)
220
+ reject(new Error(error));
221
+ else if (signed)
222
+ resolve(signed);
223
+ else
224
+ reject(new Error('Signing failed'));
225
+ });
226
+ postResponse?.({ type: 'signEvent', id, event });
227
+ setTimeout(() => {
228
+ if (pendingSignRequests.has(id)) {
229
+ pendingSignRequests.delete(id);
230
+ reject(new Error('Signing timeout'));
231
+ }
232
+ }, 60000);
233
+ });
234
+ }
235
+ async function requestEncrypt(pubkey, plaintext) {
236
+ const id = `enc_${Date.now()}_${Math.random().toString(36).slice(2)}`;
237
+ return new Promise((resolve, reject) => {
238
+ pendingEncryptRequests.set(id, (ciphertext, error) => {
239
+ if (error)
240
+ reject(new Error(error));
241
+ else if (ciphertext)
242
+ resolve(ciphertext);
243
+ else
244
+ reject(new Error('Encryption failed'));
245
+ });
246
+ postResponse?.({ type: 'nip44Encrypt', id, pubkey, plaintext });
247
+ setTimeout(() => {
248
+ if (pendingEncryptRequests.has(id)) {
249
+ pendingEncryptRequests.delete(id);
250
+ reject(new Error('Encryption timeout'));
251
+ }
252
+ }, 30000);
253
+ });
254
+ }
255
+ async function requestDecrypt(pubkey, ciphertext) {
256
+ const id = `dec_${Date.now()}_${Math.random().toString(36).slice(2)}`;
257
+ return new Promise((resolve, reject) => {
258
+ pendingDecryptRequests.set(id, (plaintext, error) => {
259
+ if (error)
260
+ reject(new Error(error));
261
+ else if (plaintext)
262
+ resolve(plaintext);
263
+ else
264
+ reject(new Error('Decryption failed'));
265
+ });
266
+ postResponse?.({ type: 'nip44Decrypt', id, pubkey, ciphertext });
267
+ setTimeout(() => {
268
+ if (pendingDecryptRequests.has(id)) {
269
+ pendingDecryptRequests.delete(id);
270
+ reject(new Error('Decryption timeout'));
271
+ }
272
+ }, 30000);
273
+ });
274
+ }
275
+ // ============================================================================
276
+ // Response Handlers (called by worker.ts when main thread responds)
277
+ // ============================================================================
278
+ export function handleSignedResponse(id, event, error) {
279
+ const resolver = pendingSignRequests.get(id);
280
+ if (resolver) {
281
+ pendingSignRequests.delete(id);
282
+ resolver(event || null, error);
283
+ }
284
+ }
285
+ export function handleEncryptedResponse(id, ciphertext, error) {
286
+ const resolver = pendingEncryptRequests.get(id);
287
+ if (resolver) {
288
+ pendingEncryptRequests.delete(id);
289
+ resolver(ciphertext || null, error);
290
+ }
291
+ }
292
+ export function handleDecryptedResponse(id, plaintext, error) {
293
+ const resolver = pendingDecryptRequests.get(id);
294
+ if (resolver) {
295
+ pendingDecryptRequests.delete(id);
296
+ resolver(plaintext || null, error);
297
+ }
298
+ }
299
+ //# sourceMappingURL=signing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signing.js","sourceRoot":"","sources":["../../src/iris/signing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Tree Root Cache
3
+ *
4
+ * Persists npub/treeName → CID mappings using any Store implementation.
5
+ * This allows quick resolution of tree roots without waiting for Nostr.
6
+ *
7
+ * Storage format:
8
+ * - Key prefix: "root:" (to distinguish from content chunks)
9
+ * - Key: SHA256("root:" + npub + "/" + treeName)
10
+ * - Value: MessagePack { hash, key?, visibility, updatedAt }
11
+ */
12
+ import type { CID, Store, TreeVisibility } from '@hashtree/core';
13
+ interface CachedRoot {
14
+ hash: Uint8Array;
15
+ key?: Uint8Array;
16
+ visibility: TreeVisibility;
17
+ updatedAt: number;
18
+ encryptedKey?: string;
19
+ keyId?: string;
20
+ selfEncryptedKey?: string;
21
+ selfEncryptedLinkKey?: string;
22
+ }
23
+ /**
24
+ * Initialize the cache with a store
25
+ */
26
+ export declare function initTreeRootCache(storeImpl: Store): void;
27
+ /**
28
+ * Get a cached tree root
29
+ */
30
+ export declare function getCachedRoot(npub: string, treeName: string): Promise<CID | null>;
31
+ /**
32
+ * Get full cached root info (including visibility)
33
+ */
34
+ export declare function getCachedRootInfo(npub: string, treeName: string): Promise<CachedRoot | null>;
35
+ /**
36
+ * Cache a tree root
37
+ */
38
+ export declare function setCachedRoot(npub: string, treeName: string, cid: CID, visibility?: TreeVisibility, options?: {
39
+ encryptedKey?: string;
40
+ keyId?: string;
41
+ selfEncryptedKey?: string;
42
+ selfEncryptedLinkKey?: string;
43
+ }): Promise<void>;
44
+ /**
45
+ * Merge a decrypted key into an existing cache entry (if hash matches).
46
+ */
47
+ export declare function mergeCachedRootKey(npub: string, treeName: string, hash: Uint8Array, key: Uint8Array): Promise<boolean>;
48
+ /**
49
+ * Remove a cached tree root
50
+ */
51
+ export declare function removeCachedRoot(npub: string, treeName: string): Promise<void>;
52
+ /**
53
+ * List all cached roots for an npub
54
+ * Note: This scans memory cache only - persistent lookup requires iteration
55
+ */
56
+ export declare function listCachedRoots(npub: string): Array<{
57
+ treeName: string;
58
+ cid: CID;
59
+ visibility: TreeVisibility;
60
+ updatedAt: number;
61
+ }>;
62
+ /**
63
+ * Clear all cached roots (memory only)
64
+ */
65
+ export declare function clearMemoryCache(): void;
66
+ /**
67
+ * Get cache stats
68
+ */
69
+ export declare function getCacheStats(): {
70
+ memoryEntries: number;
71
+ };
72
+ export {};
73
+ //# sourceMappingURL=treeRootCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"treeRootCache.d.ts","sourceRoot":"","sources":["../../src/iris/treeRootCache.ts"],"names":[],"mappings":"AACA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAMjE,UAAU,UAAU;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,UAAU,EAAE,cAAc,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AASD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,KAAK,GAAG,IAAI,CAExD;AAUD;;GAEG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAwBvF;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAqBlG;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,GAAG,EACR,UAAU,GAAE,cAAyB,EACrC,OAAO,CAAC,EAAE;IACR,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,GACA,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,UAAU,GACd,OAAO,CAAC,OAAO,CAAC,CAsBlB;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAWpF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IACnD,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,GAAG,CAAC;IACT,UAAU,EAAE,cAAc,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC,CAsBD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,CAIzD"}
@@ -0,0 +1,191 @@
1
+ // @ts-nocheck
2
+ /**
3
+ * Tree Root Cache
4
+ *
5
+ * Persists npub/treeName → CID mappings using any Store implementation.
6
+ * This allows quick resolution of tree roots without waiting for Nostr.
7
+ *
8
+ * Storage format:
9
+ * - Key prefix: "root:" (to distinguish from content chunks)
10
+ * - Key: SHA256("root:" + npub + "/" + treeName)
11
+ * - Value: MessagePack { hash, key?, visibility, updatedAt }
12
+ */
13
+ import { sha256 } from '@hashtree/core';
14
+ import { encode, decode } from '@msgpack/msgpack';
15
+ import { LRUCache } from './utils/lruCache';
16
+ // In-memory LRU cache for fast lookups (limited to 1000 entries to prevent memory leak)
17
+ // Data is backed by persistent store so eviction is safe
18
+ const memoryCache = new LRUCache(1000);
19
+ // Store reference
20
+ let store = null;
21
+ /**
22
+ * Initialize the cache with a store
23
+ */
24
+ export function initTreeRootCache(storeImpl) {
25
+ store = storeImpl;
26
+ }
27
+ /**
28
+ * Generate storage key for a tree root
29
+ */
30
+ async function makeStorageKey(npub, treeName) {
31
+ const keyStr = `root:${npub}/${treeName}`;
32
+ return sha256(new TextEncoder().encode(keyStr));
33
+ }
34
+ /**
35
+ * Get a cached tree root
36
+ */
37
+ export async function getCachedRoot(npub, treeName) {
38
+ const cacheKey = `${npub}/${treeName}`;
39
+ // Check memory cache first
40
+ const memCached = memoryCache.get(cacheKey);
41
+ if (memCached) {
42
+ return { hash: memCached.hash, key: memCached.key };
43
+ }
44
+ // Check persistent store
45
+ if (!store)
46
+ return null;
47
+ const storageKey = await makeStorageKey(npub, treeName);
48
+ const data = await store.get(storageKey);
49
+ if (!data)
50
+ return null;
51
+ try {
52
+ const cached = decode(data);
53
+ // Update memory cache
54
+ memoryCache.set(cacheKey, cached);
55
+ return { hash: cached.hash, key: cached.key };
56
+ }
57
+ catch {
58
+ return null;
59
+ }
60
+ }
61
+ /**
62
+ * Get full cached root info (including visibility)
63
+ */
64
+ export async function getCachedRootInfo(npub, treeName) {
65
+ const cacheKey = `${npub}/${treeName}`;
66
+ // Check memory cache first
67
+ const memCached = memoryCache.get(cacheKey);
68
+ if (memCached)
69
+ return memCached;
70
+ // Check persistent store
71
+ if (!store)
72
+ return null;
73
+ const storageKey = await makeStorageKey(npub, treeName);
74
+ const data = await store.get(storageKey);
75
+ if (!data)
76
+ return null;
77
+ try {
78
+ const cached = decode(data);
79
+ memoryCache.set(cacheKey, cached);
80
+ return cached;
81
+ }
82
+ catch {
83
+ return null;
84
+ }
85
+ }
86
+ /**
87
+ * Cache a tree root
88
+ */
89
+ export async function setCachedRoot(npub, treeName, cid, visibility = 'public', options) {
90
+ const cacheKey = `${npub}/${treeName}`;
91
+ const now = Math.floor(Date.now() / 1000);
92
+ const cached = {
93
+ hash: cid.hash,
94
+ key: cid.key,
95
+ visibility,
96
+ updatedAt: now,
97
+ encryptedKey: options?.encryptedKey,
98
+ keyId: options?.keyId,
99
+ selfEncryptedKey: options?.selfEncryptedKey,
100
+ selfEncryptedLinkKey: options?.selfEncryptedLinkKey,
101
+ };
102
+ // Update memory cache
103
+ memoryCache.set(cacheKey, cached);
104
+ // Persist to store
105
+ if (store) {
106
+ const storageKey = await makeStorageKey(npub, treeName);
107
+ const data = encode(cached);
108
+ await store.put(storageKey, new Uint8Array(data));
109
+ }
110
+ }
111
+ /**
112
+ * Merge a decrypted key into an existing cache entry (if hash matches).
113
+ */
114
+ export async function mergeCachedRootKey(npub, treeName, hash, key) {
115
+ const cacheKey = `${npub}/${treeName}`;
116
+ const cached = await getCachedRootInfo(npub, treeName);
117
+ if (!cached)
118
+ return false;
119
+ if (cached.key)
120
+ return false;
121
+ if (!hashEquals(cached.hash, hash))
122
+ return false;
123
+ const merged = {
124
+ ...cached,
125
+ key,
126
+ };
127
+ memoryCache.set(cacheKey, merged);
128
+ if (store) {
129
+ const storageKey = await makeStorageKey(npub, treeName);
130
+ const data = encode(merged);
131
+ await store.put(storageKey, new Uint8Array(data));
132
+ }
133
+ return true;
134
+ }
135
+ /**
136
+ * Remove a cached tree root
137
+ */
138
+ export async function removeCachedRoot(npub, treeName) {
139
+ const cacheKey = `${npub}/${treeName}`;
140
+ // Remove from memory cache
141
+ memoryCache.delete(cacheKey);
142
+ // Remove from persistent store
143
+ if (store) {
144
+ const storageKey = await makeStorageKey(npub, treeName);
145
+ await store.delete(storageKey);
146
+ }
147
+ }
148
+ /**
149
+ * List all cached roots for an npub
150
+ * Note: This scans memory cache only - persistent lookup requires iteration
151
+ */
152
+ export function listCachedRoots(npub) {
153
+ const prefix = `${npub}/`;
154
+ const results = [];
155
+ for (const [key, cached] of memoryCache) {
156
+ if (key.startsWith(prefix)) {
157
+ const treeName = key.slice(prefix.length);
158
+ results.push({
159
+ treeName,
160
+ cid: { hash: cached.hash, key: cached.key },
161
+ visibility: cached.visibility,
162
+ updatedAt: cached.updatedAt,
163
+ });
164
+ }
165
+ }
166
+ return results;
167
+ }
168
+ /**
169
+ * Clear all cached roots (memory only)
170
+ */
171
+ export function clearMemoryCache() {
172
+ memoryCache.clear();
173
+ }
174
+ /**
175
+ * Get cache stats
176
+ */
177
+ export function getCacheStats() {
178
+ return {
179
+ memoryEntries: memoryCache.size,
180
+ };
181
+ }
182
+ function hashEquals(a, b) {
183
+ if (a.length !== b.length)
184
+ return false;
185
+ for (let i = 0; i < a.length; i += 1) {
186
+ if (a[i] !== b[i])
187
+ return false;
188
+ }
189
+ return true;
190
+ }
191
+ //# sourceMappingURL=treeRootCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"treeRootCache.js","sourceRoot":"","sources":["../../src/iris/treeRootCache.ts"],"names":[],"mappings":"AAAA,cAAc;AACd;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAc5C,wFAAwF;AACxF,yDAAyD;AACzD,MAAM,WAAW,GAAG,IAAI,QAAQ,CAAqB,IAAI,CAAC,CAAC;AAE3D,kBAAkB;AAClB,IAAI,KAAK,GAAiB,IAAI,CAAC;AAE/B;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAgB;IAChD,KAAK,GAAG,SAAS,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,cAAc,CAAC,IAAY,EAAE,QAAgB;IAC1D,MAAM,MAAM,GAAG,QAAQ,IAAI,IAAI,QAAQ,EAAE,CAAC;IAC1C,OAAO,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY,EAAE,QAAgB;IAChE,MAAM,QAAQ,GAAG,GAAG,IAAI,IAAI,QAAQ,EAAE,CAAC;IAEvC,2BAA2B;IAC3B,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC5C,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,CAAC;IACtD,CAAC;IAED,yBAAyB;IACzB,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACxD,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACzC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAe,CAAC;QAC1C,sBAAsB;QACtB,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAClC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAY,EAAE,QAAgB;IACpE,MAAM,QAAQ,GAAG,GAAG,IAAI,IAAI,QAAQ,EAAE,CAAC;IAEvC,2BAA2B;IAC3B,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC5C,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC;IAEhC,yBAAyB;IACzB,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACxD,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACzC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAe,CAAC;QAC1C,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAClC,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAY,EACZ,QAAgB,EAChB,GAAQ,EACR,aAA6B,QAAQ,EACrC,OAKC;IAED,MAAM,QAAQ,GAAG,GAAG,IAAI,IAAI,QAAQ,EAAE,CAAC;IACvC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAE1C,MAAM,MAAM,GAAe;QACzB,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,UAAU;QACV,SAAS,EAAE,GAAG;QACd,YAAY,EAAE,OAAO,EAAE,YAAY;QACnC,KAAK,EAAE,OAAO,EAAE,KAAK;QACrB,gBAAgB,EAAE,OAAO,EAAE,gBAAgB;QAC3C,oBAAoB,EAAE,OAAO,EAAE,oBAAoB;KACpD,CAAC;IAEF,sBAAsB;IACtB,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAElC,mBAAmB;IACnB,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACxD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5B,MAAM,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IACpD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAY,EACZ,QAAgB,EAChB,IAAgB,EAChB,GAAe;IAEf,MAAM,QAAQ,GAAG,GAAG,IAAI,IAAI,QAAQ,EAAE,CAAC;IAEvC,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACvD,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,IAAI,MAAM,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IAC7B,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAEjD,MAAM,MAAM,GAAe;QACzB,GAAG,MAAM;QACT,GAAG;KACJ,CAAC;IAEF,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAElC,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACxD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5B,MAAM,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAY,EAAE,QAAgB;IACnE,MAAM,QAAQ,GAAG,GAAG,IAAI,IAAI,QAAQ,EAAE,CAAC;IAEvC,2BAA2B;IAC3B,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAE7B,+BAA+B;IAC/B,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACxD,MAAM,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACjC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAM1C,MAAM,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC;IAC1B,MAAM,OAAO,GAKR,EAAE,CAAC;IAER,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QACxC,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC1C,OAAO,CAAC,IAAI,CAAC;gBACX,QAAQ;gBACR,GAAG,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE;gBAC3C,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,SAAS,EAAE,MAAM,CAAC,SAAS;aAC5B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB;IAC9B,WAAW,CAAC,KAAK,EAAE,CAAC;AACtB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO;QACL,aAAa,EAAE,WAAW,CAAC,IAAI;KAChC,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,CAAa,EAAE,CAAa;IAC9C,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;IAClC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Tree Root Subscription Handler
3
+ *
4
+ * Worker subscribes directly to tree root events (kind 30078 with #l=hashtree).
5
+ * Updates local cache and notifies main thread of changes.
6
+ */
7
+ import type { SignedEvent, TreeVisibility } from './protocol';
8
+ export interface TreeRootRecord {
9
+ hash: Uint8Array;
10
+ key?: Uint8Array;
11
+ visibility: TreeVisibility;
12
+ updatedAt: number;
13
+ encryptedKey?: string;
14
+ keyId?: string;
15
+ selfEncryptedKey?: string;
16
+ selfEncryptedLinkKey?: string;
17
+ }
18
+ export interface ParsedTreeRootEvent {
19
+ hash: string;
20
+ key?: string;
21
+ visibility: TreeVisibility;
22
+ encryptedKey?: string;
23
+ keyId?: string;
24
+ selfEncryptedKey?: string;
25
+ selfEncryptedLinkKey?: string;
26
+ }
27
+ export declare function parseTreeRootEvent(event: SignedEvent): ParsedTreeRootEvent | null;
28
+ /**
29
+ * Set callback to notify main thread of tree root updates
30
+ */
31
+ export declare function setNotifyCallback(callback: (npub: string, treeName: string, record: TreeRootRecord) => void): void;
32
+ /**
33
+ * Subscribe to tree roots for a specific pubkey
34
+ */
35
+ export declare function subscribeToTreeRoots(pubkeyHex: string): () => void;
36
+ /**
37
+ * Unsubscribe from tree roots for a specific pubkey
38
+ */
39
+ export declare function unsubscribeFromTreeRoots(pubkeyHex: string): void;
40
+ export declare function handleTreeRootEvent(event: SignedEvent): Promise<void>;
41
+ /**
42
+ * Check if an event is a tree root event
43
+ */
44
+ export declare function isTreeRootEvent(event: SignedEvent): boolean;
45
+ /**
46
+ * Get all active subscription pubkeys
47
+ */
48
+ export declare function getActiveSubscriptions(): string[];
49
+ //# sourceMappingURL=treeRootSubscription.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"treeRootSubscription.d.ts","sourceRoot":"","sources":["../../src/iris/treeRootSubscription.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAS9D,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,UAAU,CAAC;IACjB,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,UAAU,EAAE,cAAc,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAYD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,cAAc,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AA+BD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,mBAAmB,GAAG,IAAI,CAoCjF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,KAAK,IAAI,GACzE,IAAI,CAEN;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,IAAI,CAelE;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAMhE;AAcD,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA4C3E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAI3D;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,EAAE,CAEjD"}