@wovin/core 0.1.36 → 0.2.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.
Files changed (212) hide show
  1. package/README.md +0 -12
  2. package/dist/applog/applog-helpers.d.ts +12 -12
  3. package/dist/applog/applog-helpers.d.ts.map +1 -1
  4. package/dist/applog/applog-utils.d.ts +25 -6
  5. package/dist/applog/applog-utils.d.ts.map +1 -1
  6. package/dist/applog/datom-types.d.ts +4 -5
  7. package/dist/applog/datom-types.d.ts.map +1 -1
  8. package/dist/applog.d.ts +3 -3
  9. package/dist/applog.d.ts.map +1 -1
  10. package/dist/{applog.min.js → applog.js} +6 -7
  11. package/dist/blockstore.d.ts +1 -1
  12. package/dist/blockstore.d.ts.map +1 -1
  13. package/dist/{blockstore.min.js → blockstore.js} +1 -3
  14. package/dist/{blockstore.min.js.map → blockstore.js.map} +1 -1
  15. package/dist/{chunk-KXMTKPF4.min.js → chunk-3JZMOEOD.js} +8 -8
  16. package/dist/chunk-3JZMOEOD.js.map +1 -0
  17. package/dist/chunk-3WZVG277.js +434 -0
  18. package/dist/chunk-3WZVG277.js.map +1 -0
  19. package/dist/chunk-7Z5YDQKK.js +1 -0
  20. package/dist/chunk-CPSDKFBG.js +147 -0
  21. package/dist/chunk-CPSDKFBG.js.map +1 -0
  22. package/dist/chunk-E46VTKTZ.js +1 -0
  23. package/dist/{chunk-H3VQJP56.min.js → chunk-J2FDHGOZ.js} +9 -9
  24. package/dist/chunk-J2FDHGOZ.js.map +1 -0
  25. package/dist/chunk-L5EEEGE6.js +1862 -0
  26. package/dist/chunk-L5EEEGE6.js.map +1 -0
  27. package/dist/{chunk-BRC7LSM6.min.js → chunk-PD3C7XUM.js} +5 -5
  28. package/dist/chunk-PD3C7XUM.js.map +1 -0
  29. package/dist/chunk-QZXKQCAY.js +1026 -0
  30. package/dist/chunk-QZXKQCAY.js.map +1 -0
  31. package/dist/{chunk-QPGEBDMJ.min.js → chunk-YDAKBU6Q.js} +1 -1
  32. package/dist/chunk-YDAKBU6Q.js.map +1 -0
  33. package/dist/chunk-ZAADLBSB.js +36 -0
  34. package/dist/chunk-ZAADLBSB.js.map +1 -0
  35. package/dist/index.d.ts +7 -7
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/{index.min.js → index.js} +73 -46
  38. package/dist/ipfs/car.d.ts +11 -11
  39. package/dist/ipfs/car.d.ts.map +1 -1
  40. package/dist/ipfs/ipfs-utils.d.ts +2 -2
  41. package/dist/ipfs/ipfs-utils.d.ts.map +1 -1
  42. package/dist/ipfs.d.ts +3 -3
  43. package/dist/ipfs.d.ts.map +1 -1
  44. package/dist/{ipfs.min.js → ipfs.js} +7 -10
  45. package/dist/ipns.d.ts +1 -1
  46. package/dist/ipns.d.ts.map +1 -1
  47. package/dist/ipns.js +64 -0
  48. package/dist/ipns.js.map +1 -0
  49. package/dist/pubsub/pub-pull.d.ts +3 -3
  50. package/dist/pubsub/pub-pull.d.ts.map +1 -1
  51. package/dist/pubsub/pubsub-types.d.ts +3 -3
  52. package/dist/pubsub/pubsub-types.d.ts.map +1 -1
  53. package/dist/pubsub/snap-push.d.ts +4 -4
  54. package/dist/pubsub/snap-push.d.ts.map +1 -1
  55. package/dist/pubsub/ucan.d.ts +1 -1
  56. package/dist/pubsub/ucan.d.ts.map +1 -1
  57. package/dist/pubsub.d.ts +4 -4
  58. package/dist/pubsub.d.ts.map +1 -1
  59. package/dist/{pubsub.min.js → pubsub.js} +7 -10
  60. package/dist/query/attr-helpers.d.ts +5 -0
  61. package/dist/query/attr-helpers.d.ts.map +1 -0
  62. package/dist/query/basic.d.ts +85 -21
  63. package/dist/query/basic.d.ts.map +1 -1
  64. package/dist/query/divergences.d.ts +5 -5
  65. package/dist/query/divergences.d.ts.map +1 -1
  66. package/dist/query/entity-collection.d.ts +19 -0
  67. package/dist/query/entity-collection.d.ts.map +1 -0
  68. package/dist/query/matchers.d.ts +1 -1
  69. package/dist/query/matchers.d.ts.map +1 -1
  70. package/dist/query/memoized.d.ts +66 -0
  71. package/dist/query/memoized.d.ts.map +1 -0
  72. package/dist/query/situations.d.ts +2 -1
  73. package/dist/query/situations.d.ts.map +1 -1
  74. package/dist/query/subscribable.d.ts +111 -0
  75. package/dist/query/subscribable.d.ts.map +1 -0
  76. package/dist/query/types.d.ts +54 -14
  77. package/dist/query/types.d.ts.map +1 -1
  78. package/dist/query.d.ts +9 -5
  79. package/dist/query.d.ts.map +1 -1
  80. package/dist/{query.min.js → query.js} +51 -32
  81. package/dist/retrieve/index.d.ts +1 -1
  82. package/dist/retrieve/index.d.ts.map +1 -1
  83. package/dist/retrieve/update-thread.d.ts +3 -3
  84. package/dist/retrieve/update-thread.d.ts.map +1 -1
  85. package/dist/retrieve.d.ts +1 -1
  86. package/dist/retrieve.d.ts.map +1 -1
  87. package/dist/retrieve.js +14 -0
  88. package/dist/thread/basic.d.ts +15 -19
  89. package/dist/thread/basic.d.ts.map +1 -1
  90. package/dist/thread/filters.d.ts +8 -10
  91. package/dist/thread/filters.d.ts.map +1 -1
  92. package/dist/thread/indexes.d.ts +56 -0
  93. package/dist/thread/indexes.d.ts.map +1 -0
  94. package/dist/thread/mapped.d.ts +40 -11
  95. package/dist/thread/mapped.d.ts.map +1 -1
  96. package/dist/thread/utils.d.ts +5 -5
  97. package/dist/thread/utils.d.ts.map +1 -1
  98. package/dist/thread/writeable.d.ts +2 -2
  99. package/dist/thread/writeable.d.ts.map +1 -1
  100. package/dist/thread.d.ts +6 -5
  101. package/dist/thread.d.ts.map +1 -1
  102. package/dist/{thread.min.js → thread.js} +9 -6
  103. package/dist/types/typescript-utils.d.ts +6 -5
  104. package/dist/types/typescript-utils.d.ts.map +1 -1
  105. package/dist/types.d.ts +1 -1
  106. package/dist/types.d.ts.map +1 -1
  107. package/dist/{types.min.js → types.js} +3 -4
  108. package/dist/utils/debug-name.d.ts +13 -0
  109. package/dist/utils/debug-name.d.ts.map +1 -0
  110. package/dist/utils.d.ts +1 -1
  111. package/dist/utils.d.ts.map +1 -1
  112. package/dist/utils.js +9 -0
  113. package/package.json +32 -23
  114. package/src/applog/applog-helpers.ts +155 -0
  115. package/src/applog/applog-utils.test.ts +108 -0
  116. package/src/applog/applog-utils.ts +507 -0
  117. package/src/applog/datom-types.ts +148 -0
  118. package/src/applog.ts +3 -0
  119. package/src/blockstore/index.ts +36 -0
  120. package/src/blockstore.ts +1 -0
  121. package/src/index.ts +8 -0
  122. package/src/ipfs/car.ts +291 -0
  123. package/src/ipfs/fetch-snapshot-chain.ts +135 -0
  124. package/src/ipfs/ipfs-utils.ts +132 -0
  125. package/src/ipfs.ts +3 -0
  126. package/src/ipns/ipns-record.ts +115 -0
  127. package/src/ipns.ts +1 -0
  128. package/src/pubsub/UCAN Specs Overview.md +217 -0
  129. package/src/pubsub/connector.ts +9 -0
  130. package/src/pubsub/pub-pull.ts +31 -0
  131. package/src/pubsub/pubsub-types.ts +90 -0
  132. package/src/pubsub/snap-push.ts +277 -0
  133. package/src/pubsub/ucan-example.ts +61 -0
  134. package/src/pubsub/ucan.ts +56 -0
  135. package/src/pubsub.ts +4 -0
  136. package/src/query/attr-helpers.ts +5 -0
  137. package/src/query/basic.ts +1245 -0
  138. package/src/query/divergences.ts +50 -0
  139. package/src/query/entity-collection.ts +131 -0
  140. package/src/query/liveFilterAndMap.test.ts +102 -0
  141. package/src/query/matchers.ts +8 -0
  142. package/src/query/memoized.test.ts +151 -0
  143. package/src/query/memoized.ts +180 -0
  144. package/src/query/query-steps.ts +4 -0
  145. package/src/query/query.test.ts +538 -0
  146. package/src/query/situations.ts +261 -0
  147. package/src/query/subscribable.test.ts +245 -0
  148. package/src/query/subscribable.ts +234 -0
  149. package/src/query/types.ts +155 -0
  150. package/src/query/withoutDeleted.test.ts +204 -0
  151. package/src/query.ts +9 -0
  152. package/src/retrieve/index.ts +1 -0
  153. package/src/retrieve/update-thread.ts +248 -0
  154. package/src/retrieve.ts +1 -0
  155. package/src/test/perf/query.1m.perf.test.ts +94 -0
  156. package/src/test/perf/query.perf.test.ts +389 -0
  157. package/src/test/perf/query.realdata.perf.test.ts +182 -0
  158. package/src/thread/basic.ts +209 -0
  159. package/src/thread/filters.ts +227 -0
  160. package/src/thread/indexes.ts +250 -0
  161. package/src/thread/joinThreads.test.ts +304 -0
  162. package/src/thread/mapped.ts +226 -0
  163. package/src/thread/utils.ts +144 -0
  164. package/src/thread/writeable.ts +163 -0
  165. package/src/thread.ts +6 -0
  166. package/src/types/typescript-utils.ts +64 -0
  167. package/src/types.ts +1 -0
  168. package/src/utils/debug-name.ts +54 -0
  169. package/src/utils.ts +4 -0
  170. package/dist/chunk-2Y2PYHGR.min.js +0 -65
  171. package/dist/chunk-2Y2PYHGR.min.js.map +0 -1
  172. package/dist/chunk-5MMGBK2U.min.js +0 -1
  173. package/dist/chunk-7IDQIMQO.min.js +0 -1
  174. package/dist/chunk-BRC7LSM6.min.js.map +0 -1
  175. package/dist/chunk-COXXILXC.min.js +0 -512
  176. package/dist/chunk-COXXILXC.min.js.map +0 -1
  177. package/dist/chunk-GDX2OO7L.min.js +0 -9080
  178. package/dist/chunk-GDX2OO7L.min.js.map +0 -1
  179. package/dist/chunk-H3VQJP56.min.js.map +0 -1
  180. package/dist/chunk-HYMC7W6S.min.js +0 -1549
  181. package/dist/chunk-HYMC7W6S.min.js.map +0 -1
  182. package/dist/chunk-KEHU7HGZ.min.js +0 -5216
  183. package/dist/chunk-KEHU7HGZ.min.js.map +0 -1
  184. package/dist/chunk-KXMTKPF4.min.js.map +0 -1
  185. package/dist/chunk-PHITDXZT.min.js +0 -36
  186. package/dist/chunk-QO2KMGDN.min.js +0 -3771
  187. package/dist/chunk-QO2KMGDN.min.js.map +0 -1
  188. package/dist/chunk-QPGEBDMJ.min.js.map +0 -1
  189. package/dist/chunk-WXLCBTHX.min.js +0 -1606
  190. package/dist/chunk-WXLCBTHX.min.js.map +0 -1
  191. package/dist/ipns.min.js +0 -6419
  192. package/dist/ipns.min.js.map +0 -1
  193. package/dist/mobx/mobx-utils.d.ts +0 -82
  194. package/dist/mobx/mobx-utils.d.ts.map +0 -1
  195. package/dist/mobx.d.ts +0 -2
  196. package/dist/mobx.d.ts.map +0 -1
  197. package/dist/mobx.min.js +0 -141
  198. package/dist/retrieve.min.js +0 -17
  199. package/dist/types.min.js.map +0 -1
  200. package/dist/utils.min.js +0 -10
  201. package/dist/utils.min.js.map +0 -1
  202. /package/dist/{applog.min.js.map → applog.js.map} +0 -0
  203. /package/dist/{chunk-5MMGBK2U.min.js.map → chunk-7Z5YDQKK.js.map} +0 -0
  204. /package/dist/{chunk-7IDQIMQO.min.js.map → chunk-E46VTKTZ.js.map} +0 -0
  205. /package/dist/{chunk-PHITDXZT.min.js.map → index.js.map} +0 -0
  206. /package/dist/{index.min.js.map → ipfs.js.map} +0 -0
  207. /package/dist/{ipfs.min.js.map → pubsub.js.map} +0 -0
  208. /package/dist/{mobx.min.js.map → query.js.map} +0 -0
  209. /package/dist/{pubsub.min.js.map → retrieve.js.map} +0 -0
  210. /package/dist/{query.min.js.map → thread.js.map} +0 -0
  211. /package/dist/{retrieve.min.js.map → types.js.map} +0 -0
  212. /package/dist/{thread.min.js.map → utils.js.map} +0 -0
@@ -0,0 +1,1862 @@
1
+ import {
2
+ arrayIfSingle
3
+ } from "./chunk-ZAADLBSB.js";
4
+
5
+ // src/thread/basic.ts
6
+ import { Logger } from "besonders-logger";
7
+
8
+ // src/query/subscribable.ts
9
+ var SubscribableImpl = class {
10
+ _value;
11
+ _derivedSubscribers = [];
12
+ _subscribers = [];
13
+ _upstreamActive = false;
14
+ _activateUpstream;
15
+ _deactivateUpstream = null;
16
+ _equals;
17
+ constructor(initialValue, activateUpstream, opts) {
18
+ this._value = initialValue;
19
+ this._activateUpstream = activateUpstream ?? null;
20
+ this._equals = opts?.equals === false ? () => false : opts?.equals ?? ((a, b) => a === b);
21
+ }
22
+ get value() {
23
+ return this._value;
24
+ }
25
+ subscribe(cb, type) {
26
+ if (!this._upstreamActive && this._activateUpstream) {
27
+ this._deactivateUpstream = this._activateUpstream();
28
+ this._upstreamActive = true;
29
+ }
30
+ const list = type === "derived" ? this._derivedSubscribers : this._subscribers;
31
+ list.push(cb);
32
+ return () => {
33
+ const idx = list.indexOf(cb);
34
+ if (idx >= 0) list.splice(idx, 1);
35
+ if (this._derivedSubscribers.length === 0 && this._subscribers.length === 0 && this._upstreamActive) {
36
+ this._deactivateUpstream?.();
37
+ this._deactivateUpstream = null;
38
+ this._upstreamActive = false;
39
+ }
40
+ };
41
+ }
42
+ /** Update value and notify subscribers (skips if equals check passes) */
43
+ _set(value) {
44
+ if (this._equals(value, this._value)) return;
45
+ this._value = value;
46
+ this._notify();
47
+ }
48
+ _notify() {
49
+ const derived = [...this._derivedSubscribers];
50
+ for (const sub of derived) sub();
51
+ const subs = [...this._subscribers];
52
+ for (const sub of subs) sub();
53
+ }
54
+ dispose() {
55
+ this._deactivateUpstream?.();
56
+ this._deactivateUpstream = null;
57
+ this._derivedSubscribers.length = 0;
58
+ this._subscribers.length = 0;
59
+ this._upstreamActive = false;
60
+ }
61
+ };
62
+ function isArrayInitEvent(event) {
63
+ return event.init !== void 0;
64
+ }
65
+ var SubscribableArrayImpl = class {
66
+ _items;
67
+ _derivedSubscribers = [];
68
+ _subscribers = [];
69
+ _upstreamActive = false;
70
+ _activateUpstream;
71
+ _deactivateUpstream = null;
72
+ constructor(initialItems, activateUpstream) {
73
+ this._items = initialItems;
74
+ this._activateUpstream = activateUpstream ?? null;
75
+ }
76
+ get items() {
77
+ return this._items;
78
+ }
79
+ get length() {
80
+ return this._items.length;
81
+ }
82
+ subscribe(cb, type) {
83
+ if (!this._upstreamActive && this._activateUpstream) {
84
+ this._deactivateUpstream = this._activateUpstream();
85
+ this._upstreamActive = true;
86
+ }
87
+ const list = type === "derived" ? this._derivedSubscribers : this._subscribers;
88
+ list.push(cb);
89
+ return () => {
90
+ const idx = list.indexOf(cb);
91
+ if (idx >= 0) list.splice(idx, 1);
92
+ if (this._derivedSubscribers.length === 0 && this._subscribers.length === 0 && this._upstreamActive) {
93
+ this._deactivateUpstream?.();
94
+ this._deactivateUpstream = null;
95
+ this._upstreamActive = false;
96
+ }
97
+ };
98
+ }
99
+ /** Push items and notify subscribers */
100
+ _push(...items) {
101
+ this._items.push(...items);
102
+ this._notify({ added: items, removed: null });
103
+ }
104
+ /** Remove items and notify subscribers */
105
+ _remove(items) {
106
+ for (const item of items) {
107
+ const idx = this._items.indexOf(item);
108
+ if (idx >= 0) this._items.splice(idx, 1);
109
+ }
110
+ this._notify({ added: [], removed: items });
111
+ }
112
+ /** Full reset — replace all items */
113
+ _reset(items) {
114
+ this._items = items;
115
+ this._notify({ init: [...this._items] });
116
+ }
117
+ _notify(event) {
118
+ const derived = [...this._derivedSubscribers];
119
+ for (const sub of derived) sub(event);
120
+ const subs = [...this._subscribers];
121
+ for (const sub of subs) sub(event);
122
+ }
123
+ dispose() {
124
+ this._deactivateUpstream?.();
125
+ this._deactivateUpstream = null;
126
+ this._derivedSubscribers.length = 0;
127
+ this._subscribers.length = 0;
128
+ this._upstreamActive = false;
129
+ }
130
+ };
131
+
132
+ // src/utils/debug-name.ts
133
+ import stringify from "safe-stable-stringify";
134
+ var createDebugName = ({ caller, thread, pattern, args }) => {
135
+ args = args || pattern;
136
+ const str = `${!Array.isArray(thread) && thread?.name ? thread.name + " | " : ""}${caller ?? "caller?"}${args ? `{${typeof args === "string" ? args : stringify(args)}}` : ""}`;
137
+ return str;
138
+ };
139
+ var createDebugNameObj = (args) => {
140
+ return { name: createDebugName(args) };
141
+ };
142
+ function prettifyThreadName(input) {
143
+ let depth = 0;
144
+ let result = "";
145
+ let insideCurlyBraces = 0;
146
+ for (let i = 0; i < input.length; i++) {
147
+ const char = input[i];
148
+ if (char === "(") {
149
+ result += char + "\n" + " ".repeat(++depth);
150
+ } else if (char === ")") {
151
+ result += "\n" + " ".repeat(--depth) + char;
152
+ } else if (char === "," && insideCurlyBraces === 0) {
153
+ result += char + "\n" + " ".repeat(depth);
154
+ } else if (char === "{" && insideCurlyBraces === 0) {
155
+ insideCurlyBraces++;
156
+ result += char + "\n" + " ".repeat(depth + 1);
157
+ } else if (char === "}" && insideCurlyBraces === 1) {
158
+ insideCurlyBraces--;
159
+ result += "\n" + " ".repeat(depth) + char;
160
+ } else if (char === "{" && insideCurlyBraces > 0) {
161
+ insideCurlyBraces++;
162
+ result += char;
163
+ } else if (char === "}" && insideCurlyBraces > 1) {
164
+ insideCurlyBraces--;
165
+ result += char;
166
+ } else {
167
+ result += char;
168
+ }
169
+ }
170
+ return result;
171
+ }
172
+
173
+ // src/thread/basic.ts
174
+ var { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO, { prefix: "[thread]" });
175
+ var isInitEvent = isArrayInitEvent;
176
+ var Thread = class {
177
+ constructor(name, parents, filters, _applogs = []) {
178
+ this.name = name;
179
+ this._applogs = _applogs;
180
+ this.parents = parents === null ? null : arrayIfSingle(parents);
181
+ this.filters = filters;
182
+ if (this.parents?.length === 0) {
183
+ WARN(`[Thread] empty parents array`, name);
184
+ }
185
+ }
186
+ filters;
187
+ parents;
188
+ _derivedSubscribers = [];
189
+ _subscribers = [];
190
+ /** Monotonic counter incremented on every mutation. Used by memoizedFn to invalidate caches. */
191
+ _version = 0;
192
+ get readOnly() {
193
+ if (this.parents.length !== 1) return true;
194
+ return this.parents[0].readOnly;
195
+ }
196
+ insert(appLogsToInsert) {
197
+ if (this.readOnly) throw ERROR(`[Thread] insert() called on read-only thread:`, this.nameAndSizeUntracked);
198
+ if (!this.parents) throw ERROR(`[Thread] insert() called on non-writable thread without parents:`, this.nameAndSizeUntracked);
199
+ if (this.parents?.length !== 1) throw ERROR(`[Thread] insert() called on thread with multiple parents:`, this.nameAndSizeUntracked);
200
+ return this.parents[0].insert(appLogsToInsert);
201
+ }
202
+ insertRaw(appLogsToInsert) {
203
+ if (this.readOnly) throw ERROR(`[Thread] insertRaw() called on read-only thread:`, this.nameAndSizeUntracked);
204
+ if (!this.parents) throw ERROR(`[Thread] insertRaw() called on non-writable thread without parents:`, this.nameAndSizeUntracked);
205
+ if (this.parents?.length !== 1) throw ERROR(`[Thread] insertRaw() called on thread with multiple parents:`, this.nameAndSizeUntracked);
206
+ return this.parents[0].insertRaw(appLogsToInsert);
207
+ }
208
+ subscribe(callback, type) {
209
+ const list = type === "derived" ? this._derivedSubscribers : this._subscribers;
210
+ list.push(callback);
211
+ return () => {
212
+ const idx = list.indexOf(callback);
213
+ if (idx >= 0) list.splice(idx, 1);
214
+ };
215
+ }
216
+ notifySubscribers(event) {
217
+ this._version++;
218
+ DEBUG(`[thread: ${this.name}] notifying`, this._derivedSubscribers.length, "derived +", this._subscribers.length, "subscribers of", { ...event, subs: this._subscribers });
219
+ const derived = [...this._derivedSubscribers];
220
+ for (const subscriber of derived) {
221
+ subscriber(event);
222
+ }
223
+ const subs = [...this._subscribers];
224
+ for (const subscriber of subs) {
225
+ subscriber(event);
226
+ }
227
+ }
228
+ // ── SubscribableArray<Applog> ──
229
+ get items() {
230
+ return this._applogs;
231
+ }
232
+ dispose() {
233
+ this._derivedSubscribers.length = 0;
234
+ this._subscribers.length = 0;
235
+ }
236
+ get applogs() {
237
+ return this._applogs;
238
+ }
239
+ get applogsCids() {
240
+ return this._applogs.map((l) => l.cid);
241
+ }
242
+ get applogsCidSet() {
243
+ return new Set(this._applogs.map((l) => l.cid));
244
+ }
245
+ map(fn) {
246
+ return this.applogs.map(fn);
247
+ }
248
+ get findLast() {
249
+ return this.applogs.findLast.bind(this.applogs);
250
+ }
251
+ get findFirst() {
252
+ return this.applogs.find.bind(this.applogs);
253
+ }
254
+ get firstLog() {
255
+ return this.applogs[0];
256
+ }
257
+ get latestLog() {
258
+ return this.applogs[this.applogs.length - 1];
259
+ }
260
+ hasApplog(applog, byRef) {
261
+ if (byRef) {
262
+ return this.applogs.includes(applog);
263
+ } else {
264
+ if (!applog.cid) throw ERROR(`[hasApplogs] applog without CID:`, applog);
265
+ return this.hasApplogCid(applog.cid);
266
+ }
267
+ }
268
+ hasApplogCid(cid) {
269
+ return this.applogsCidSet.has(cid.toString());
270
+ }
271
+ get applogsByCid() {
272
+ return new Map(this.applogs.map((log) => [log.cid, log]));
273
+ }
274
+ getApplog(cid) {
275
+ return this.applogsByCid.get(cid.toString());
276
+ }
277
+ hasApplogWithDiffTs(applog) {
278
+ return this.applogs.find((existing) => existing.en === applog.en && existing.at === applog.at && existing.vl === applog.vl && existing.ag === applog.ag);
279
+ }
280
+ // get stateHash() {
281
+ // blakeHasher.init()
282
+ // for (const log of this.applogs) {
283
+ // blakeHasher.update(log.cid)
284
+ // }
285
+ // return blakeHasher.digest()
286
+ // }
287
+ get isEmpty() {
288
+ return this.size === 0;
289
+ }
290
+ get size() {
291
+ return this.applogs.length;
292
+ }
293
+ get length() {
294
+ return this.applogs.length;
295
+ }
296
+ get untrackedSize() {
297
+ return this.size;
298
+ }
299
+ get nameAndSizeUntracked() {
300
+ return `${this.name} (${this.size})`;
301
+ }
302
+ get prettyName() {
303
+ return prettifyThreadName(this.name);
304
+ }
305
+ get hasParents() {
306
+ return !!this.parents?.length;
307
+ }
308
+ };
309
+ var getLogsFromThread = (logsOrThread) => logsOrThread instanceof Thread ? logsOrThread.applogs : logsOrThread;
310
+ var StaticThread = class _StaticThread extends Thread {
311
+ static fromArray(applogs, name) {
312
+ return new _StaticThread(name || "static", null, [], applogs);
313
+ }
314
+ constructor(name, parents, filters, _applogs) {
315
+ super(name, parents, filters, _applogs);
316
+ }
317
+ get readOnly() {
318
+ return true;
319
+ }
320
+ };
321
+
322
+ // src/thread/filters.ts
323
+ import { Logger as Logger6 } from "besonders-logger";
324
+ import stringify3 from "safe-stable-stringify";
325
+
326
+ // src/applog/applog-helpers.ts
327
+ import { Logger as Logger4 } from "besonders-logger";
328
+
329
+ // src/ipfs/ipfs-utils.ts
330
+ import * as dagJson from "@ipld/dag-json";
331
+ import { sha256 } from "@noble/hashes/sha2.js";
332
+ import { Logger as Logger2 } from "besonders-logger";
333
+ import { CID, digest as Digest } from "multiformats";
334
+ import { encode as multiformatsEncode } from "multiformats/block";
335
+
336
+ // src/applog/datom-types.ts
337
+ import { FormatRegistry, Type } from "@sinclair/typebox";
338
+ import { TypeCompiler } from "@sinclair/typebox/compiler";
339
+ var Nullable = (schema) => Type.Union([schema, Type.Null()]);
340
+ var EntityID_LENGTH = 7;
341
+ var isCID = /^(k51qz|baguq)[0-9a-z]{56,57}$/;
342
+ var isShortHash = /^[0-9A-Fa-f]{7,8}$/g;
343
+ FormatRegistry.Set("EntityID", (value) => !!value.match(isShortHash) || !!value.match(isCID));
344
+ var EntityID = Type.String();
345
+ var isEncryptedApplog = (l) => l?.enc instanceof Uint8Array;
346
+ FormatRegistry.Set("CID", (value) => !!value.match(isCID));
347
+ var CIDTB = Type.String({ format: "CID" });
348
+ var isURL = /^http([s]?):\/\/.*\..*/;
349
+ FormatRegistry.Set("URL", (value) => !!value.match(isURL));
350
+ var URL = Type.String({ format: "URL" });
351
+ var AppLogNoCidTB = Type.Object({
352
+ en: EntityID,
353
+ // EntityID
354
+ at: Type.String(),
355
+ // Attribute
356
+ vl: Nullable(Type.Union([Type.String(), Type.Boolean(), Type.Number()])),
357
+ // TODO refactor to semantic typesafe ApplogValue
358
+ ts: Type.String(),
359
+ // Timestamp
360
+ ag: Type.String(),
361
+ // AgentHash
362
+ pv: Nullable(CIDTB)
363
+ // CidString
364
+ });
365
+ var AppLogNoCidTBC = TypeCompiler.Compile(AppLogNoCidTB);
366
+ var getApplogNoCidTypeErrors = (obj) => Array.from(AppLogNoCidTBC.Errors(obj));
367
+ var isValidApplogNoCid = AppLogNoCidTBC.Check.bind(AppLogNoCidTBC);
368
+ var AppLogTB = Type.Composite([
369
+ Type.Object({
370
+ cid: CIDTB
371
+ }),
372
+ AppLogNoCidTB
373
+ ]);
374
+ var AppLogTBC = TypeCompiler.Compile(AppLogTB);
375
+ var getApplogTypeErrors = (obj) => Array.from(AppLogTBC.Errors(obj));
376
+ var isValidApplog = AppLogTBC.Check.bind(AppLogTBC);
377
+
378
+ // src/ipfs/ipfs-utils.ts
379
+ import { base36 } from "multiformats/bases/base36";
380
+ import { sha256 as sha265Hasher } from "multiformats/hashes/sha2";
381
+ var { WARN: WARN2, LOG: LOG2, DEBUG: DEBUG2, VERBOSE: VERBOSE2, ERROR: ERROR2 } = Logger2.setup(Logger2.INFO);
382
+ var MULTICODEC_IPNS_KEY = 114;
383
+ function prepareForPub(log, without = ["cid"]) {
384
+ if (!log) throw ERROR2("falsy log", log);
385
+ let cid = log.cid;
386
+ if (isEncryptedApplog(log)) {
387
+ if (!cid) cid = getCidSync(encodeBlock(log).bytes).toString();
388
+ WARN2("preparing an encrypted applog - really?");
389
+ return { log, cid };
390
+ }
391
+ const logWithout = {};
392
+ for (let [key, val] of Object.entries(log)) {
393
+ if (val === void 0) {
394
+ WARN2(`log.${key} is undefined, which is not allowed - encoding as null`, log);
395
+ val = null;
396
+ }
397
+ if (!without.includes(key)) {
398
+ logWithout[key] = val;
399
+ } else {
400
+ VERBOSE2("excluding app log", { key, val });
401
+ }
402
+ }
403
+ return { log: logWithout, cid };
404
+ }
405
+ function encodeApplogAndGetCid(log) {
406
+ return getCidSync(encodeApplog(log).bytes);
407
+ }
408
+ function encodeApplog(log) {
409
+ return encodeBlock(prepareForPub(log)?.log);
410
+ }
411
+ function getCidSync(bytes) {
412
+ const hash = sha256(bytes);
413
+ const digest = Digest.create(sha265Hasher.code, hash);
414
+ const cid = CID.create(1, dagJson.code, digest);
415
+ VERBOSE2(`[getCidSync]`, { bytes, hash, digest, cid });
416
+ return cid;
417
+ }
418
+ function encodeBlock(jsonObject) {
419
+ DEBUG2("[encodeBlock]", jsonObject);
420
+ try {
421
+ const byteView = dagJson.encode(jsonObject);
422
+ return { bytes: byteView, cid: getCidSync(byteView) };
423
+ } catch (err) {
424
+ throw ERROR2("[encodeBlock] failed to encode:", jsonObject, err);
425
+ }
426
+ }
427
+ async function encodeBlockOriginal(jsonObject) {
428
+ const encoded = await multiformatsEncode({ value: jsonObject, codec: dagJson, hasher: sha265Hasher });
429
+ const syncVariant = encodeBlock(jsonObject);
430
+ if (syncVariant.cid.toString() !== encoded.cid.toString()) {
431
+ ERROR2(`[encodeBlockOriginal] sync cid mismatch`, { jsonObject, encoded, syncVariant });
432
+ }
433
+ return encoded;
434
+ }
435
+ function tryParseCID(cidString) {
436
+ let cid = null;
437
+ let errors = [];
438
+ try {
439
+ cid = CID.parse(cidString);
440
+ } catch (err) {
441
+ VERBOSE2(`[retrieveThread] couldn't parse pubID with default base`);
442
+ errors.push(err);
443
+ }
444
+ if (!cid) {
445
+ try {
446
+ cid = CID.parse(cidString, base36);
447
+ } catch (err) {
448
+ VERBOSE2(`[retrieveThread] couldn't parse pubID with base36`);
449
+ errors.push(err);
450
+ }
451
+ }
452
+ return {
453
+ cid,
454
+ errors: cid ? null : errors,
455
+ // we only care about errors if we failed to parse
456
+ isIpns: cid && isIpnsKeyCid(cid)
457
+ };
458
+ }
459
+ function isIpnsKeyCid(cid) {
460
+ return cid.code === MULTICODEC_IPNS_KEY;
461
+ }
462
+ function cidToString(cid) {
463
+ if (cid.code == MULTICODEC_IPNS_KEY) {
464
+ return toIpnsString(cid);
465
+ } else {
466
+ return cid.toString();
467
+ }
468
+ }
469
+ function toIpnsString(cid) {
470
+ if (cid.code !== MULTICODEC_IPNS_KEY) throw ERROR2(`Not an IPNS cid (${cid.code}):`, cid.toString());
471
+ return cid.toString(base36);
472
+ }
473
+ function ensureValidCIDinstance(cidOrStringA) {
474
+ return typeof cidOrStringA === "string" ? CID.parse(cidOrStringA) : typeof cidOrStringA.toV1 != "function" ? CID.decode(cidOrStringA.bytes) : cidOrStringA;
475
+ }
476
+ function areCidsEqual(cidOrStringA, cidOrStringB) {
477
+ if (!cidOrStringA || !cidOrStringB) throw new Error(`[areCidsEqual] invalid params: ${cidOrStringA}, ${cidOrStringB}`);
478
+ if (cidOrStringA === cidOrStringB) return true;
479
+ const cidA = ensureValidCIDinstance(cidOrStringA);
480
+ const cidB = ensureValidCIDinstance(cidOrStringB);
481
+ return cidA.toV1().toString() === cidB.toV1().toString();
482
+ }
483
+ function containsCid(list, needle) {
484
+ if (list instanceof Set) return list.has(typeof needle === "string" ? needle : needle.toV1().toString());
485
+ return list.some((cidOrString) => areCidsEqual(cidOrString, needle));
486
+ }
487
+
488
+ // src/applog/applog-utils.ts
489
+ import { Logger as Logger3 } from "besonders-logger";
490
+ import { isBefore } from "date-fns";
491
+ import { partial, pick } from "lodash-es";
492
+ import { isEqual } from "lodash-es";
493
+ import stringify2 from "safe-stable-stringify";
494
+ var { WARN: WARN3, LOG: LOG3, DEBUG: DEBUG3, VERBOSE: VERBOSE3, ERROR: ERROR3 } = Logger3.setup(Logger3.INFO);
495
+ var isoDateStrCompare = (strA, strB, dir = "asc") => dir === "asc" ? strA.localeCompare(strB, "en-US") : strB.localeCompare(strA, "en-US");
496
+ var objEqualByKeys = (keys, objA, objB) => {
497
+ return isEqual(pick(objA, keys), pick(objB, keys));
498
+ };
499
+ var compareApplogsByTs = (logA, logB, dir = "asc") => {
500
+ const tsCmp = isoDateStrCompare(logA.ts, logB.ts, dir);
501
+ if (tsCmp !== 0) return tsCmp;
502
+ return dir === "asc" ? logA.cid.localeCompare(logB.cid) : logB.cid.localeCompare(logA.cid);
503
+ };
504
+ var compareApplogsByEnAt = partial(objEqualByKeys, ["en", "at"]);
505
+ function isLaterByTsAndPv(a, b) {
506
+ const tsCmp = isoDateStrCompare(a.ts, b.ts);
507
+ if (tsCmp !== 0) return tsCmp > 0;
508
+ if (a.en === b.en && a.at === b.at) {
509
+ if (a.pv === b.cid) return true;
510
+ if (b.pv === a.cid) return false;
511
+ }
512
+ return a.cid.localeCompare(b.cid) > 0;
513
+ }
514
+ function sortApplogsByTs(appLogArray, dir = "asc") {
515
+ appLogArray.sort((a, b) => compareApplogsByTs(a, b, dir));
516
+ let i = 0;
517
+ while (i < appLogArray.length) {
518
+ let j = i + 1;
519
+ while (j < appLogArray.length && appLogArray[j].ts === appLogArray[i].ts) j++;
520
+ if (j - i > 1) chainStabilizeCluster(appLogArray, i, j, dir);
521
+ i = j;
522
+ }
523
+ return appLogArray;
524
+ }
525
+ function chainStabilizeCluster(applogs, from, to, dir) {
526
+ const groups = /* @__PURE__ */ new Map();
527
+ for (let k = from; k < to; k++) {
528
+ const log = applogs[k];
529
+ const key = log.en + "|" + log.at;
530
+ const existing = groups.get(key);
531
+ if (existing) existing.push(log);
532
+ else groups.set(key, [log]);
533
+ }
534
+ if (groups.size === to - from) return;
535
+ const orderedByGroup = /* @__PURE__ */ new Map();
536
+ for (const [key, logs] of groups) {
537
+ orderedByGroup.set(key, logs.length === 1 ? logs : topoSortByPv(logs, dir));
538
+ }
539
+ const cursors = /* @__PURE__ */ new Map();
540
+ for (let k = from; k < to; k++) {
541
+ const key = applogs[k].en + "|" + applogs[k].at;
542
+ const cursor = cursors.get(key) ?? 0;
543
+ applogs[k] = orderedByGroup.get(key)[cursor];
544
+ cursors.set(key, cursor + 1);
545
+ }
546
+ }
547
+ function topoSortByPv(logs, dir) {
548
+ const cidSet = new Set(logs.map((l) => l.cid));
549
+ const childrenByPv = /* @__PURE__ */ new Map();
550
+ const roots = [];
551
+ for (const log of logs) {
552
+ if (log.pv && cidSet.has(log.pv)) {
553
+ const children = childrenByPv.get(log.pv);
554
+ if (children) children.push(log);
555
+ else childrenByPv.set(log.pv, [log]);
556
+ } else {
557
+ roots.push(log);
558
+ }
559
+ }
560
+ const lexCmp = (a, b) => a.cid.localeCompare(b.cid);
561
+ roots.sort(lexCmp);
562
+ for (const children of childrenByPv.values()) children.sort(lexCmp);
563
+ const result = [];
564
+ const visited = /* @__PURE__ */ new Set();
565
+ const stack = [...roots].reverse();
566
+ while (stack.length > 0) {
567
+ const log = stack.pop();
568
+ if (visited.has(log.cid)) continue;
569
+ visited.add(log.cid);
570
+ result.push(log);
571
+ const children = childrenByPv.get(log.cid);
572
+ if (children) for (let i = children.length - 1; i >= 0; i--) stack.push(children[i]);
573
+ }
574
+ if (result.length < logs.length) {
575
+ for (const log of logs) if (!visited.has(log.cid)) result.push(log);
576
+ }
577
+ return dir === "desc" ? result.reverse() : result;
578
+ }
579
+ var isTsBefore = (log, logToCompare) => isBefore(new Date(log.ts), new Date(logToCompare.ts));
580
+ var uniqueEnFromAppLogs = (appLogArray) => [...new Set(appLogArray.map((eachLog) => eachLog.en))];
581
+ var areApplogsEqual = (logA, logB) => isEqual(logA, logB);
582
+ var warnMissingRemoveDuplicateMode = () => {
583
+ WARN3(`[removeDuplicateAppLogs] mode not set; pass 'safety' or 'cleanup' for optimal behavior`);
584
+ };
585
+ var removeDuplicateAppLogsCleanup = (appLogArray) => {
586
+ const logMap = /* @__PURE__ */ new Map();
587
+ const verboseEnabled = VERBOSE3.isEnabled;
588
+ for (const eachLog of appLogArray) {
589
+ if (!eachLog) {
590
+ ERROR3(`falsy entry in applogs`, appLogArray);
591
+ throw new Error(`falsy entry in applogs`);
592
+ }
593
+ if (!eachLog.cid) {
594
+ ERROR3(`applog with missing CID`, eachLog);
595
+ throw new Error(`applog with missing CID`);
596
+ }
597
+ const key = eachLog.cid;
598
+ const existing = logMap.get(key);
599
+ if (existing) {
600
+ if (verboseEnabled) VERBOSE3(`Skipping duplicate applog:`, [existing, eachLog]);
601
+ } else {
602
+ logMap.set(key, eachLog);
603
+ }
604
+ }
605
+ return Array.from(logMap.values());
606
+ };
607
+ var removeDuplicateAppLogsSafety = (appLogArray) => {
608
+ const seen = /* @__PURE__ */ new Set();
609
+ const verboseEnabled = VERBOSE3.isEnabled;
610
+ const existingByCid = verboseEnabled ? /* @__PURE__ */ new Map() : null;
611
+ let result = null;
612
+ let index = 0;
613
+ for (const eachLog of appLogArray) {
614
+ if (!eachLog) {
615
+ ERROR3(`falsy entry in applogs`, appLogArray);
616
+ throw new Error(`falsy entry in applogs`);
617
+ }
618
+ if (!eachLog.cid) {
619
+ ERROR3(`applog with missing CID`, eachLog);
620
+ throw new Error(`applog with missing CID`);
621
+ }
622
+ const key = eachLog.cid;
623
+ if (seen.has(key)) {
624
+ if (!result) {
625
+ result = appLogArray.slice(0, index);
626
+ }
627
+ if (verboseEnabled) VERBOSE3(`Skipping duplicate applog:`, [existingByCid?.get(key), eachLog]);
628
+ } else {
629
+ seen.add(key);
630
+ if (existingByCid) existingByCid.set(key, eachLog);
631
+ if (result) result.push(eachLog);
632
+ }
633
+ index++;
634
+ }
635
+ return result ?? appLogArray;
636
+ };
637
+ var removeDuplicateAppLogs = (appLogArray, mode) => {
638
+ if (!mode) {
639
+ warnMissingRemoveDuplicateMode();
640
+ return removeDuplicateAppLogsCleanup(appLogArray);
641
+ }
642
+ return mode === "safety" ? removeDuplicateAppLogsSafety(appLogArray) : removeDuplicateAppLogsCleanup(appLogArray);
643
+ };
644
+ var getHashID = (stringifiable, lngth = 8) => cyrb53hash(stringify2(stringifiable), 31, lngth);
645
+ function isVariable(x) {
646
+ return typeof x === "string" && x.startsWith("?");
647
+ }
648
+ function variableNameWithoutQuestionmark(str) {
649
+ return str.slice(1);
650
+ }
651
+ function isStaticPattern(x) {
652
+ if (!["string", "boolean", "number", "function"].includes(typeof x)) WARN3(`Unhandled pattern value type:`, typeof x, x);
653
+ return !isVariable(x) && ["string", "boolean", "number"].includes(typeof x);
654
+ }
655
+ function resolveOrRemoveVariables(pattern, candidate) {
656
+ let variablesToFill = {};
657
+ const newPattern = {};
658
+ for (const [patternKey, patternValue] of Object.entries(pattern)) {
659
+ if (isVariable(patternValue)) {
660
+ const varName = variableNameWithoutQuestionmark(patternValue);
661
+ const candidateValue = candidate[varName];
662
+ if (candidateValue) {
663
+ newPattern[patternKey] = candidateValue;
664
+ } else {
665
+ variablesToFill[patternKey] = varName;
666
+ }
667
+ } else {
668
+ newPattern[patternKey] = patternValue;
669
+ }
670
+ }
671
+ return [newPattern, variablesToFill];
672
+ }
673
+ function matchVariable(variable, triplePart, context) {
674
+ if (context.hasOwnProperty(variable)) {
675
+ const bound = context[variable];
676
+ const match = matchPart(bound, triplePart, context);
677
+ return match;
678
+ }
679
+ return { ...context, [variable]: triplePart };
680
+ }
681
+ function matchPartStatic(field, patternPart, atomPart) {
682
+ let result;
683
+ if (patternPart) {
684
+ const typ = typeof patternPart;
685
+ if (typ === "string") {
686
+ result = patternPart === atomPart;
687
+ } else if (typ === "function") {
688
+ result = patternPart(atomPart);
689
+ } else if (typeof patternPart.has === "function") {
690
+ result = patternPart.has(atomPart);
691
+ } else if (Array.isArray(patternPart) && !Array.isArray(atomPart)) {
692
+ result = patternPart.includes(atomPart);
693
+ } else {
694
+ result = patternPart === atomPart;
695
+ }
696
+ } else {
697
+ result = patternPart === atomPart;
698
+ }
699
+ if (field.charAt(0) === "!") {
700
+ return !result;
701
+ } else {
702
+ return result;
703
+ }
704
+ }
705
+ function matchPart(patternPart, atomPart, context) {
706
+ if (!context) {
707
+ return null;
708
+ }
709
+ if (typeof patternPart === "string") {
710
+ if (isVariable(patternPart)) {
711
+ return matchVariable(patternPart, atomPart, context);
712
+ }
713
+ }
714
+ if (typeof patternPart === "function") {
715
+ return patternPart(atomPart) ? context : null;
716
+ }
717
+ return patternPart === atomPart ? context : null;
718
+ }
719
+ function matchPattern(pattern, applog, context) {
720
+ return Object.entries(pattern).reduce((context2, [field, patternValue]) => {
721
+ const applogValue = applog[field];
722
+ const patternValT = patternValue;
723
+ return matchPart(patternValT, applogValue, context2);
724
+ }, context);
725
+ }
726
+ function actualize(context, find) {
727
+ return Object.fromEntries(find.map((findField) => {
728
+ if (context === null) {
729
+ throw new Error(`actualize context is null ${find}`);
730
+ }
731
+ return [
732
+ isVariable(findField) ? findField.replace(/^\?/, "") : findField,
733
+ isVariable(findField) ? context[findField] : findField
734
+ ];
735
+ }));
736
+ }
737
+ var sum = function sum2(array) {
738
+ var num = 0;
739
+ for (var i = 0, l = array.length; i < l; i++) num += array[i];
740
+ return num;
741
+ };
742
+ var mean = function mean2(array) {
743
+ return sum(array) / array.length;
744
+ };
745
+ var arrStats = {
746
+ max: function(array) {
747
+ return Math.max.apply(null, array);
748
+ },
749
+ min: function(array) {
750
+ return Math.min.apply(null, array);
751
+ },
752
+ range: function(array) {
753
+ return arrStats.max(array) - arrStats.min(array);
754
+ },
755
+ midrange: function(array) {
756
+ return arrStats.range(array) / 2;
757
+ },
758
+ sum,
759
+ mean,
760
+ average: mean,
761
+ median: function(array) {
762
+ array.sort(function(a, b) {
763
+ return a - b;
764
+ });
765
+ var mid = array.length / 2;
766
+ return mid % 1 ? array[mid - 0.5] : (array[mid - 1] + array[mid]) / 2;
767
+ },
768
+ modes: function(array) {
769
+ if (!array.length) return [];
770
+ var modeMap = {}, maxCount = 0, modes = [];
771
+ array.forEach(function(val) {
772
+ if (!modeMap[val]) modeMap[val] = 1;
773
+ else modeMap[val]++;
774
+ if (modeMap[val] > maxCount) {
775
+ modes = [val];
776
+ maxCount = modeMap[val];
777
+ } else if (modeMap[val] === maxCount) {
778
+ modes.push(val);
779
+ maxCount = modeMap[val];
780
+ }
781
+ });
782
+ return modes;
783
+ },
784
+ variance: function(array) {
785
+ var mean3 = arrStats.mean(array);
786
+ return arrStats.mean(array.map(function(num) {
787
+ return Math.pow(num - mean3, 2);
788
+ }));
789
+ },
790
+ standardDeviation: function(array) {
791
+ return Math.sqrt(arrStats.variance(array));
792
+ },
793
+ meanAbsoluteDeviation: function(array) {
794
+ var mean3 = arrStats.mean(array);
795
+ return arrStats.mean(array.map(function(num) {
796
+ return Math.abs(num - mean3);
797
+ }));
798
+ },
799
+ zScores: function(array) {
800
+ var mean3 = arrStats.mean(array);
801
+ var standardDeviation = arrStats.standardDeviation(array);
802
+ return array.map(function(num) {
803
+ return (num - mean3) / standardDeviation;
804
+ });
805
+ }
806
+ };
807
+ arrStats.average = arrStats.mean;
808
+ var tsNearlySame = (timeA, timeB) => timeB.startsWith(timeA.slice(0, timeA.length - 4));
809
+ var cyrb53hash = function(str, seed = 13, strLength) {
810
+ if (!str?.length) {
811
+ throw new Error(`Empty string: ${str}`);
812
+ }
813
+ let h1 = 3735928559 ^ seed;
814
+ let h2 = 1103547991 ^ seed;
815
+ for (let i = 0, ch; i < str.length; i++) {
816
+ ch = str.charCodeAt(i);
817
+ h1 = Math.imul(h1 ^ ch, 2654435761);
818
+ h2 = Math.imul(h2 ^ ch, 1597334677);
819
+ }
820
+ h1 = Math.imul(h1 ^ h1 >>> 16, 2246822507) ^ Math.imul(h2 ^ h2 >>> 13, 3266489909);
821
+ h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507) ^ Math.imul(h1 ^ h1 >>> 13, 3266489909);
822
+ const asHex = (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(16);
823
+ return asHex.slice(-strLength).padStart(strLength, "0");
824
+ };
825
+ function arraysContainSameElements(arr1, arr2) {
826
+ if (arr1.length !== arr2.length) {
827
+ return false;
828
+ }
829
+ const sortedArr1 = [...arr1].sort();
830
+ const sortedArr2 = [...arr2].sort();
831
+ for (let i = 0; i < sortedArr1.length; i++) {
832
+ if (sortedArr1[i] !== sortedArr2[i]) {
833
+ return false;
834
+ }
835
+ }
836
+ return true;
837
+ }
838
+ function dateNowIso() {
839
+ const now = /* @__PURE__ */ new Date();
840
+ return now.toISOString();
841
+ }
842
+
843
+ // src/applog/applog-helpers.ts
844
+ var { WARN: WARN4, LOG: LOG4, DEBUG: DEBUG4, VERBOSE: VERBOSE4, ERROR: ERROR4 } = Logger4.setup(Logger4.INFO);
845
+ function ensureTsPvAndFinalizeApplogs(appLogsToInsert, threadForPv) {
846
+ DEBUG4(`[ensureTsPvAndFinalizeApplogs] ENTER - ${appLogsToInsert.length} applogs, thread size=${threadForPv.size}`);
847
+ const ts = dateNowIso();
848
+ const currentThread = threadForPv;
849
+ const seenInBatch = /* @__PURE__ */ new Set();
850
+ for (const log of appLogsToInsert) {
851
+ const key = log.en + "|" + log.at;
852
+ if (seenInBatch.has(key)) {
853
+ WARN4(
854
+ `[ensureTsPvAndFinalizeApplogs] within-batch duplicate (en, at)=(${log.en}, ${log.at}) \u2014 chain-pv won't link these; consider separate insert calls`,
855
+ { log }
856
+ );
857
+ break;
858
+ }
859
+ seenInBatch.add(key);
860
+ }
861
+ DEBUG4(`[ensureTsPvAndFinalizeApplogs] About to map over applogs`);
862
+ const mapped = appLogsToInsert.map((log, idx) => {
863
+ DEBUG4(`[ensureTsPvAndFinalizeApplogs] Processing applog ${idx + 1}/${appLogsToInsert.length}`);
864
+ const result = finalizeApplogForInsert(log, { ts, threadForPv: currentThread });
865
+ DEBUG4(`[ensureTsPvAndFinalizeApplogs] Finalized applog ${idx + 1}/${appLogsToInsert.length}`);
866
+ return result;
867
+ });
868
+ DEBUG4(`[ensureTsPvAndFinalizeApplogs] EXIT - mapped ${mapped.length} applogs`);
869
+ return mapped;
870
+ }
871
+ function ensureTsPvAndFinalizeApplog(applogToInsert, threadForPv) {
872
+ return ensureTsPvAndFinalizeApplogs([applogToInsert], threadForPv)[0];
873
+ }
874
+ function finalizeApplogForInsert(log, { ts, threadForPv } = {}) {
875
+ DEBUG4(`[finalizeApplogForInsert] ENTER - en=${log.en}, at=${log.at}`);
876
+ DEBUG4(`[finalizeApplogForInsert] About to call withTs`);
877
+ const logWithTs = withTs(log, ts ?? dateNowIso());
878
+ DEBUG4(`[finalizeApplogForInsert] About to call withPvFrom (thread size=${threadForPv?.size ?? "null"})`);
879
+ const logWithPv = withPvFrom(logWithTs, threadForPv);
880
+ DEBUG4(`[finalizeApplogForInsert] About to call encodeApplogAndGetCid`);
881
+ const cid = encodeApplogAndGetCid(logWithPv).toString();
882
+ DEBUG4(`[finalizeApplogForInsert] CID created: ${cid}`);
883
+ if (log.cid && log.cid !== cid) WARN4(`[finalizeApplogForInsert] overwriting wrong CID`, { log, cid, logWithPv });
884
+ const logWithCid = { ...logWithPv, cid };
885
+ DEBUG4(`[finalizeApplogForInsert] About to validate applog`);
886
+ if (!isValidApplog(logWithCid)) {
887
+ throw ERROR4(`Bogus Applog ${JSON.stringify(logWithCid)}`, getApplogTypeErrors(logWithCid));
888
+ }
889
+ DEBUG4(`[finalizeApplogForInsert] EXIT - CID=${cid}`);
890
+ return Object.freeze(logWithCid);
891
+ }
892
+ function hasAg(log) {
893
+ return !!log.ag;
894
+ }
895
+ function hasTs(log) {
896
+ return !!log.ts;
897
+ }
898
+ function hasPv(log) {
899
+ return !!log.pv;
900
+ }
901
+ function withTs(log, ts) {
902
+ return hasTs(log) ? log : { ...log, ts };
903
+ }
904
+ function withAg(log, ag) {
905
+ return hasAg(log) ? log : { ...log, ag };
906
+ }
907
+ function withPvFrom(log, thread) {
908
+ DEBUG4(`[withPvFrom] ENTER - en=${log.en}, at=${log.at}, hasPv=${log.pv !== void 0}`);
909
+ if (log.pv !== void 0) {
910
+ DEBUG4(`[withPvFrom] EXIT early - pv already set`);
911
+ return log;
912
+ }
913
+ if (!thread) {
914
+ if (!hasPv(log)) throw ERROR4(`[withPvFrom] no thread and no pv:`, log);
915
+ DEBUG4(`[withPvFrom] EXIT - no thread, returning log with existing pv`);
916
+ return log;
917
+ } else {
918
+ const { en, at } = log;
919
+ DEBUG4(`[withPvFrom] About to call thread.findLast for en=${en}, at=${at}, thread.size=${thread.size}`);
920
+ const prevLog = thread.findLast((l) => l.en == en && l.at == at);
921
+ DEBUG4(`[withPvFrom] findLast completed, found=${!!prevLog}`);
922
+ DEBUG4(`[withPvFrom] About to check equality`);
923
+ if (objEqualByKeys(["en", "at", "vl", "ts", "ag"], log, prevLog)) {
924
+ throw ERROR4(`[withPvFrom] Same as previous:`, { log, pv: prevLog, thread });
925
+ }
926
+ const prevLogCid = (log.pv !== void 0 ? log.pv : prevLog?.cid) ?? null;
927
+ DEBUG4(`[withPvFrom] EXIT - prevLogCid=${prevLogCid}`);
928
+ return { ...log, pv: prevLogCid };
929
+ }
930
+ }
931
+ function joinThreads(threads) {
932
+ const derivation = {
933
+ compute(parents) {
934
+ if (parents.length < 2) DEBUG4(`joinThreads with count=${parents.length}`);
935
+ return sortApplogsByTs(
936
+ removeDuplicateAppLogs(parents.flatMap((s) => {
937
+ const logs = s.applogs;
938
+ if (!logs) {
939
+ ERROR4(`falsy applogs of thread`, s);
940
+ throw new Error(`falsy applogs of thread`);
941
+ }
942
+ return logs;
943
+ }), "cleanup")
944
+ );
945
+ },
946
+ mapDelta: (delta, { source, parents, state }) => ({
947
+ added: delta.added.filter((log) => !state.includes(log)),
948
+ removed: delta.removed?.filter(
949
+ (log) => state.includes(log) && !parents.some((p) => p !== source && p.hasApplog(log, true))
950
+ )
951
+ })
952
+ };
953
+ return new MappedThread(
954
+ `join(~ ${threads.map((s) => s.name).join(", ")})`,
955
+ threads,
956
+ ["?"],
957
+ // HACK this basically says "we're not sure what filters are applied"
958
+ derivation
959
+ );
960
+ }
961
+
962
+ // src/query/memoized.ts
963
+ import { isEqual as isEqual2 } from "lodash-es";
964
+ function compareStructural(argsA, argsB, versionsA) {
965
+ if (argsA.length !== argsB.length) return false;
966
+ for (let i = 0; i < argsA.length; i++) {
967
+ if (argsA[i] instanceof Thread) {
968
+ if (argsB[i] !== argsA[i]) return false;
969
+ if (versionsA && versionsA[i] !== void 0 && argsB[i]._version !== versionsA[i]) return false;
970
+ } else {
971
+ if (!isEqual2(argsA[i], argsB[i])) return false;
972
+ }
973
+ }
974
+ return true;
975
+ }
976
+ function snapshotVersions(args) {
977
+ return args.map((a) => a instanceof Thread ? a._version : void 0);
978
+ }
979
+ function memoizedFn(name, fn, opts) {
980
+ const cache = [];
981
+ const argsEqual = opts?.argsEqual ?? compareStructural;
982
+ const maxSize = opts?.maxSize ?? Infinity;
983
+ return function(...args) {
984
+ const existing = cache.find((entry) => argsEqual(entry.args, args, entry.versions));
985
+ if (existing) return existing.result;
986
+ const result = fn.apply(this, args);
987
+ if (cache.length >= maxSize) {
988
+ cache.shift();
989
+ }
990
+ cache.push({ args, versions: snapshotVersions(args), result });
991
+ return result;
992
+ };
993
+ }
994
+ function refCountedMemoizedFn(name, fn, opts) {
995
+ const cache = [];
996
+ const argsEqual = opts?.argsEqual ?? compareStructural;
997
+ const gracePeriodMs = opts?.gracePeriodMs ?? 0;
998
+ function evict(entry, args) {
999
+ const idx = cache.indexOf(entry);
1000
+ if (idx >= 0) cache.splice(idx, 1);
1001
+ opts?.onCleanup?.(entry.result, ...args);
1002
+ }
1003
+ return function(...args) {
1004
+ let entry = cache.find((e) => argsEqual(e.args, args));
1005
+ if (entry) {
1006
+ if (entry.graceTimer !== null) {
1007
+ clearTimeout(entry.graceTimer);
1008
+ entry.graceTimer = null;
1009
+ }
1010
+ entry.refCount++;
1011
+ } else {
1012
+ const result = fn.apply(this, args);
1013
+ entry = { args, result, refCount: 1, graceTimer: null };
1014
+ cache.push(entry);
1015
+ }
1016
+ const capturedEntry = entry;
1017
+ let released = false;
1018
+ return {
1019
+ get value() {
1020
+ return capturedEntry.result;
1021
+ },
1022
+ release() {
1023
+ if (released) return;
1024
+ released = true;
1025
+ capturedEntry.refCount--;
1026
+ if (capturedEntry.refCount <= 0) {
1027
+ if (gracePeriodMs > 0) {
1028
+ capturedEntry.graceTimer = setTimeout(() => {
1029
+ if (capturedEntry.refCount <= 0) {
1030
+ evict(capturedEntry, args);
1031
+ }
1032
+ }, gracePeriodMs);
1033
+ } else {
1034
+ evict(capturedEntry, args);
1035
+ }
1036
+ }
1037
+ }
1038
+ };
1039
+ };
1040
+ }
1041
+
1042
+ // src/thread/mapped.ts
1043
+ import { Logger as Logger5 } from "besonders-logger";
1044
+ import { sortedIndexBy } from "lodash-es";
1045
+ var { WARN: WARN5, LOG: LOG5, DEBUG: DEBUG5, VERBOSE: VERBOSE5, ERROR: ERROR5 } = Logger5.setup(Logger5.INFO);
1046
+ var MappedThread = class _MappedThread extends Thread {
1047
+ // mapped to unsubscribe function
1048
+ constructor(name, parents, filters, _derivation, _writeMapper = null, _readOnly) {
1049
+ const parentArr = arrayIfSingle(parents);
1050
+ if (!_derivation && parentArr.length > 1) {
1051
+ throw new Error(`MappedThread without derivation must have exactly one parent`);
1052
+ }
1053
+ const initialLogs = _derivation ? _derivation.compute(parentArr) : parentArr[0]._applogs;
1054
+ super(
1055
+ name,
1056
+ parents,
1057
+ filters,
1058
+ _derivation ? [...initialLogs] : initialLogs
1059
+ // clone if derived, share if not
1060
+ );
1061
+ this.name = name;
1062
+ this._derivation = _derivation;
1063
+ this._writeMapper = _writeMapper;
1064
+ this._readOnly = _readOnly;
1065
+ if (_derivation) {
1066
+ this.subscribeToParents();
1067
+ }
1068
+ }
1069
+ static mapWrites(parent, name, mapper) {
1070
+ return new _MappedThread(
1071
+ `${name}<${parent.nameAndSizeUntracked}>`,
1072
+ parent,
1073
+ parent.filters,
1074
+ null,
1075
+ // no derivation — share parent array
1076
+ mapper
1077
+ );
1078
+ }
1079
+ static asReadOnly(parent) {
1080
+ if (parent.readOnly) return parent;
1081
+ return new _MappedThread(
1082
+ `readOnly(${parent.name})`,
1083
+ parent,
1084
+ parent.filters,
1085
+ null,
1086
+ // no derivation — share parent array
1087
+ null,
1088
+ true
1089
+ // readOnly
1090
+ );
1091
+ }
1092
+ _parentSubscriptions = null;
1093
+ insert(appLogsToInsert) {
1094
+ if (this.readOnly) throw ERROR5(`[MappedThread] insert() called on read-only thread:`, this.nameAndSizeUntracked);
1095
+ const mapped = this._writeMapper ? this._writeMapper(appLogsToInsert) : appLogsToInsert;
1096
+ if (this._writeMapper && !mapped) return;
1097
+ return this.parents.forEach((parent) => parent.insert(mapped));
1098
+ }
1099
+ insertRaw(appLogsToInsert) {
1100
+ if (this.readOnly) throw ERROR5(`[MappedThread] insertRaw() called on read-only thread:`, this.nameAndSizeUntracked);
1101
+ const mapped = this._writeMapper ? this._writeMapper(appLogsToInsert) : appLogsToInsert;
1102
+ if (this._writeMapper && !mapped) return;
1103
+ return this.parents.forEach((parent) => parent.insertRaw(mapped));
1104
+ }
1105
+ subscribeToParents() {
1106
+ this._parentSubscriptions = /* @__PURE__ */ new Map();
1107
+ if (!this.parents.length) {
1108
+ WARN5(`MappedThread has no parents`, this);
1109
+ }
1110
+ VERBOSE5(`[MappedThread: ${this.name}] subscribing to parents:`, this.parents.map((p) => p.name));
1111
+ for (const p of this.parents) {
1112
+ VERBOSE5(`[MappedThread: ${this.name}] sub to parent`, p.nameAndSizeUntracked);
1113
+ const sub = this.onParentUpdate.bind(this, p);
1114
+ const unsubscribe = p.subscribe(sub, "derived");
1115
+ this._parentSubscriptions.set(p, unsubscribe);
1116
+ }
1117
+ }
1118
+ /** Tear down parent subscriptions and clear internal state */
1119
+ dispose() {
1120
+ if (this._parentSubscriptions) {
1121
+ for (const [, unsubscribe] of this._parentSubscriptions) {
1122
+ unsubscribe();
1123
+ }
1124
+ this._parentSubscriptions = null;
1125
+ }
1126
+ }
1127
+ /** Swap parents at runtime — re-subscribes and recomputes applogs, notifying downstream */
1128
+ setParents(newParents) {
1129
+ this.dispose();
1130
+ this.parents = newParents;
1131
+ this.subscribeToParents();
1132
+ this.triggerRemap();
1133
+ }
1134
+ subscribe(callback, type) {
1135
+ if (this._derivation && !this._parentSubscriptions) {
1136
+ this.subscribeToParents();
1137
+ }
1138
+ return super.subscribe(callback, type);
1139
+ }
1140
+ /** Recompute full state from parents via compute() */
1141
+ triggerRemap() {
1142
+ if (!this._derivation) throw ERROR5(`triggerRemap on a thread without derivation`, this.nameAndSizeUntracked);
1143
+ DEBUG5(`MappedThread{${this.nameAndSizeUntracked}} triggerRemap`);
1144
+ const newLogs = this._derivation.compute(this.parents);
1145
+ this._applogs.length = 0;
1146
+ this._applogs.push(...newLogs);
1147
+ this.notifySubscribers({ init: newLogs });
1148
+ }
1149
+ onParentUpdate(sourceThread, event) {
1150
+ if (!this._derivation) return;
1151
+ VERBOSE5(`MappedThread{${this.nameAndSizeUntracked}} parentUpdate`, event);
1152
+ let result;
1153
+ if (isInitEvent(event)) {
1154
+ const newLogs = this._derivation.compute(this.parents);
1155
+ result = { init: newLogs };
1156
+ } else if (this._derivation.mapDelta) {
1157
+ const ctx = {
1158
+ source: sourceThread,
1159
+ parents: this.parents,
1160
+ state: this._applogs
1161
+ };
1162
+ const mapped = this._derivation.mapDelta(event, ctx);
1163
+ if (mapped === null) {
1164
+ const newLogs = this._derivation.compute(this.parents);
1165
+ result = { init: newLogs };
1166
+ } else {
1167
+ result = mapped;
1168
+ }
1169
+ } else {
1170
+ const newLogs = this._derivation.compute(this.parents);
1171
+ result = { init: newLogs };
1172
+ }
1173
+ if (isInitEvent(result)) {
1174
+ this._applogs.length = 0;
1175
+ this._applogs.push(...result.init);
1176
+ } else {
1177
+ VERBOSE5(`MappedThread{${this.nameAndSizeUntracked}} parentUpdate => mapped`, result);
1178
+ for (const log of result.added) {
1179
+ this._applogs.splice(sortedIndexBy(this._applogs, log, "ts"), 0, log);
1180
+ }
1181
+ if (result.removed) {
1182
+ for (const toRemove of result.removed) {
1183
+ const idx = this._applogs.indexOf(toRemove);
1184
+ if (idx >= 0) {
1185
+ this._applogs.splice(idx, 1);
1186
+ } else {
1187
+ throw ERROR5(`MappedThread{${this.name}} toRemove: log not found`, toRemove, {
1188
+ thread: this,
1189
+ event,
1190
+ result
1191
+ });
1192
+ }
1193
+ }
1194
+ }
1195
+ }
1196
+ this.notifySubscribers(result);
1197
+ }
1198
+ get readOnly() {
1199
+ return this._readOnly ?? false;
1200
+ }
1201
+ };
1202
+
1203
+ // src/thread/filters.ts
1204
+ var { WARN: WARN6, LOG: LOG6, DEBUG: DEBUG6, VERBOSE: VERBOSE6, ERROR: ERROR6 } = Logger6.setup(Logger6.INFO);
1205
+ var rollingFilter2 = memoizedFn("rollingFilter", function rollingFilter3(thread, pattern, opts = {}) {
1206
+ const filter = makeFilter(pattern);
1207
+ const derivation = {
1208
+ compute: (parents) => {
1209
+ if (parents.length !== 1) {
1210
+ throw ERROR6(`rollingFilter requires exactly one parent`, { parents: parents.length });
1211
+ }
1212
+ return filter(parents[0].applogs);
1213
+ },
1214
+ mapDelta: (delta, { state }) => {
1215
+ const mappedDelta = {
1216
+ added: filter(delta.added),
1217
+ removed: delta.removed?.filter((log) => state.includes(log))
1218
+ };
1219
+ VERBOSE6(
1220
+ `rollingFilter{${thread.nameAndSizeUntracked} | ${opts.name ? ` '${opts.name}'}` : ""} parentUpdate`,
1221
+ pattern,
1222
+ delta,
1223
+ "=>",
1224
+ mappedDelta
1225
+ );
1226
+ return mappedDelta;
1227
+ }
1228
+ };
1229
+ return new MappedThread(
1230
+ `${thread.name} | ${opts.name || `rollingFilter{${stringify3(pattern)}}`}`,
1231
+ thread,
1232
+ [...thread.filters, ...opts.extraFilterName ? [opts.extraFilterName] : []],
1233
+ derivation
1234
+ );
1235
+ }, {
1236
+ argsDebugName: (thread, pattern, opts) => createDebugName({ caller: "rollingFilter", thread, pattern, args: opts })
1237
+ });
1238
+ var rollingMapper = memoizedFn("rollingMapper", function rollingMapper2(thread, derivation, opts = {}) {
1239
+ return new MappedThread(
1240
+ `${thread.name} | ${opts.name || `rollingMapper`}`,
1241
+ thread,
1242
+ [...thread.filters, ...opts.extraFilterName ? [opts.extraFilterName] : []],
1243
+ derivation
1244
+ );
1245
+ }, {
1246
+ argsDebugName: (thread, _derivation, opts) => createDebugName({ caller: "rollingMapper", thread, args: opts })
1247
+ });
1248
+ var rollingAcc = memoizedFn(
1249
+ "rollingAcc",
1250
+ function rollingAcc2(thread, acc, eventMapper, opts = {}) {
1251
+ eventMapper({ init: thread.applogs }, acc);
1252
+ const result = new SubscribableImpl(
1253
+ acc,
1254
+ () => thread.subscribe((event) => {
1255
+ eventMapper(event, acc);
1256
+ result._set(acc);
1257
+ }, "derived"),
1258
+ { equals: false }
1259
+ // accumulator is mutated in-place
1260
+ );
1261
+ return result;
1262
+ },
1263
+ { argsDebugName: (thread, _acc, _mapper, opts) => `rollingAcc{${thread.nameAndSizeUntracked}${opts?.name ? ` | ${opts?.name}` : ""}}` }
1264
+ );
1265
+ var getUntrackedPattern = function getUntrackedPattern2(pattern) {
1266
+ if (!Object.entries(pattern).length) {
1267
+ throw new Error(`Pattern is empty`);
1268
+ }
1269
+ return pattern;
1270
+ };
1271
+ function makeFilter(pattern) {
1272
+ return function madeFilter(logs) {
1273
+ return logs.filter(function madeFilterSingleLog(applog) {
1274
+ for (const field of Object.keys(pattern)) {
1275
+ let patternValue = pattern[field];
1276
+ if (patternValue === void 0) continue;
1277
+ const applogValue = applog[field.startsWith("!") ? field.slice(1) : field];
1278
+ const patternValT = patternValue;
1279
+ if (!matchPartStatic(field, patternValT, applogValue)) {
1280
+ return false;
1281
+ }
1282
+ }
1283
+ return true;
1284
+ });
1285
+ };
1286
+ }
1287
+ var getUntrackedFilterResults = function getUntrackedFilterResults2(thread, pattern, opts = {}) {
1288
+ const untrackedPattern = getUntrackedPattern(pattern);
1289
+ const filter = makeFilter(untrackedPattern);
1290
+ return filter(thread.applogs);
1291
+ };
1292
+ function hasFilter(thread, filter) {
1293
+ return thread.filters.includes(filter);
1294
+ }
1295
+ function assertRaw(thread) {
1296
+ if (thread.filters.length) {
1297
+ WARN6(`[assertRaw] but '${thread.nameAndSizeUntracked}' has filters:`, thread.filters);
1298
+ }
1299
+ return thread;
1300
+ }
1301
+ function assertOnlyCurrent(thread) {
1302
+ if (!hasFilter(thread, "lastWriteWins") || !hasFilter(thread, "withoutDeleted")) throw ERROR6(`should be filtered thread, but is:`, thread.filters);
1303
+ return thread;
1304
+ }
1305
+ var asReadOnly = MappedThread.asReadOnly;
1306
+ var simpleApplogMapper = function simpleApplogMapper2(thread, logMapper, opts = {}) {
1307
+ const mappedTo = /* @__PURE__ */ new Map();
1308
+ const mapLogs = (applogs, thread2) => {
1309
+ const ts = dateNowIso();
1310
+ return applogs.map((log) => {
1311
+ const mapped = logMapper(log, thread2);
1312
+ let mapTo;
1313
+ if (mapped === log) {
1314
+ mapTo = log;
1315
+ } else {
1316
+ if (mapped.cid === log.cid) {
1317
+ delete mapped.cid;
1318
+ }
1319
+ mapTo = finalizeApplogForInsert(mapped, {
1320
+ ts,
1321
+ threadForPv: null
1322
+ // ? should not be inferred, right?
1323
+ });
1324
+ }
1325
+ mappedTo.set(log.cid, mapTo);
1326
+ return mapTo;
1327
+ });
1328
+ };
1329
+ const derivation = {
1330
+ compute(parents) {
1331
+ if (parents.length !== 1) {
1332
+ throw ERROR6(`simpleApplogMapper requires exactly one parent`, { parents: parents.length });
1333
+ }
1334
+ const [parent] = parents;
1335
+ mappedTo.clear();
1336
+ return mapLogs(parent.applogs, parent);
1337
+ },
1338
+ mapDelta: (delta, { state }) => {
1339
+ const mappedDelta = {
1340
+ added: mapLogs(delta.added, thread),
1341
+ removed: delta.removed?.map((removedSourceLog) => {
1342
+ const mappedLog = mappedTo.get(removedSourceLog.cid);
1343
+ if (!mappedLog) {
1344
+ throw ERROR6(`[simpleApplogMapper] Parent remove event for Applog that we don't know about`, { removedSourceLog });
1345
+ }
1346
+ mappedTo.delete(removedSourceLog.cid);
1347
+ return mappedLog;
1348
+ }).filter((log) => state.includes(log))
1349
+ };
1350
+ VERBOSE6(
1351
+ `simpleApplogMapper{${thread.nameAndSizeUntracked} | ${opts?.name ? ` '${opts?.name}'}` : ""} parentUpdate`,
1352
+ delta,
1353
+ "=>",
1354
+ mappedDelta
1355
+ );
1356
+ return mappedDelta;
1357
+ }
1358
+ };
1359
+ const mappedThread = rollingMapper(thread, derivation, opts);
1360
+ VERBOSE6.isDisabled || VERBOSE6(`simpleApplogMapper<${thread.nameAndSizeUntracked}> initial mapped to`, mappedThread.applogs);
1361
+ return mappedThread;
1362
+ };
1363
+
1364
+ // src/thread/indexes.ts
1365
+ import { Logger as Logger7 } from "besonders-logger";
1366
+ var { WARN: WARN7, LOG: LOG7, DEBUG: DEBUG7, VERBOSE: VERBOSE7, ERROR: ERROR7 } = Logger7.setup(Logger7.INFO);
1367
+ var applogsByEntity = memoizedFn(
1368
+ "applogsByEntity",
1369
+ function applogsByEntity2(thread) {
1370
+ const map = /* @__PURE__ */ new Map();
1371
+ const add = (log) => {
1372
+ let arr = map.get(log.en);
1373
+ if (!arr) {
1374
+ arr = [];
1375
+ map.set(log.en, arr);
1376
+ }
1377
+ arr.push(log);
1378
+ };
1379
+ const remove = (log) => {
1380
+ const arr = map.get(log.en);
1381
+ if (!arr) return;
1382
+ const idx = arr.indexOf(log);
1383
+ if (idx >= 0) arr.splice(idx, 1);
1384
+ if (arr.length === 0) map.delete(log.en);
1385
+ };
1386
+ for (const log of thread.applogs) add(log);
1387
+ thread.subscribe((event) => {
1388
+ if (isInitEvent(event)) {
1389
+ map.clear();
1390
+ for (const log of event.init) add(log);
1391
+ } else {
1392
+ for (const log of event.added) add(log);
1393
+ if (event.removed) for (const log of event.removed) remove(log);
1394
+ }
1395
+ }, "derived");
1396
+ return map;
1397
+ }
1398
+ );
1399
+ var applogsByAttrValue = memoizedFn(
1400
+ "applogsByAttrValue",
1401
+ function applogsByAttrValue2(thread, attr) {
1402
+ const map = /* @__PURE__ */ new Map();
1403
+ const add = (log) => {
1404
+ let arr = map.get(log.vl);
1405
+ if (!arr) {
1406
+ arr = [];
1407
+ map.set(log.vl, arr);
1408
+ }
1409
+ arr.push(log);
1410
+ };
1411
+ const remove = (log) => {
1412
+ const arr = map.get(log.vl);
1413
+ if (!arr) return;
1414
+ const idx = arr.indexOf(log);
1415
+ if (idx >= 0) arr.splice(idx, 1);
1416
+ if (arr.length === 0) map.delete(log.vl);
1417
+ };
1418
+ const filtered = rollingFilter2(thread, { at: attr });
1419
+ for (const log of filtered.applogs) add(log);
1420
+ const result = new SubscribableImpl(
1421
+ map,
1422
+ () => filtered.subscribe((event) => {
1423
+ if (isInitEvent(event)) {
1424
+ map.clear();
1425
+ for (const log of event.init) add(log);
1426
+ } else {
1427
+ if (event.removed) for (const log of event.removed) remove(log);
1428
+ for (const log of event.added) add(log);
1429
+ }
1430
+ result._set(map);
1431
+ }, "derived"),
1432
+ { equals: false }
1433
+ );
1434
+ return result;
1435
+ }
1436
+ );
1437
+ var entityLinkIndex = memoizedFn(
1438
+ "entityLinkIndex",
1439
+ function entityLinkIndex2(thread, attrA, attrB) {
1440
+ const byA = /* @__PURE__ */ new Map();
1441
+ const byB = /* @__PURE__ */ new Map();
1442
+ const aByLink = /* @__PURE__ */ new Map();
1443
+ const bByLink = /* @__PURE__ */ new Map();
1444
+ function addLink(linkId, aValue, bValue) {
1445
+ const entry = { linkId, aValue, bValue };
1446
+ let arrA = byA.get(aValue);
1447
+ if (!arrA) {
1448
+ arrA = [];
1449
+ byA.set(aValue, arrA);
1450
+ }
1451
+ arrA.push(entry);
1452
+ let arrB = byB.get(bValue);
1453
+ if (!arrB) {
1454
+ arrB = [];
1455
+ byB.set(bValue, arrB);
1456
+ }
1457
+ arrB.push(entry);
1458
+ }
1459
+ function removeLink(linkId, aValue, bValue) {
1460
+ const arrA = byA.get(aValue);
1461
+ if (arrA) {
1462
+ const idx = arrA.findIndex((e) => e.linkId === linkId);
1463
+ if (idx >= 0) arrA.splice(idx, 1);
1464
+ if (arrA.length === 0) byA.delete(aValue);
1465
+ }
1466
+ const arrB = byB.get(bValue);
1467
+ if (arrB) {
1468
+ const idx = arrB.findIndex((e) => e.linkId === linkId);
1469
+ if (idx >= 0) arrB.splice(idx, 1);
1470
+ if (arrB.length === 0) byB.delete(bValue);
1471
+ }
1472
+ }
1473
+ function processLog(log) {
1474
+ if (log.at === attrA) {
1475
+ aByLink.set(log.en, log.vl);
1476
+ const bVal = bByLink.get(log.en);
1477
+ if (bVal !== void 0) {
1478
+ addLink(log.en, log.vl, bVal);
1479
+ }
1480
+ } else if (log.at === attrB) {
1481
+ bByLink.set(log.en, log.vl);
1482
+ const aVal = aByLink.get(log.en);
1483
+ if (aVal !== void 0) {
1484
+ addLink(log.en, aVal, log.vl);
1485
+ }
1486
+ }
1487
+ }
1488
+ function removeLog(log) {
1489
+ if (log.at === attrA) {
1490
+ const aVal = aByLink.get(log.en);
1491
+ const bVal = bByLink.get(log.en);
1492
+ if (aVal !== void 0 && bVal !== void 0) {
1493
+ removeLink(log.en, aVal, bVal);
1494
+ }
1495
+ aByLink.delete(log.en);
1496
+ } else if (log.at === attrB) {
1497
+ const aVal = aByLink.get(log.en);
1498
+ const bVal = bByLink.get(log.en);
1499
+ if (aVal !== void 0 && bVal !== void 0) {
1500
+ removeLink(log.en, aVal, bVal);
1501
+ }
1502
+ bByLink.delete(log.en);
1503
+ }
1504
+ }
1505
+ function buildFull(applogs) {
1506
+ byA.clear();
1507
+ byB.clear();
1508
+ aByLink.clear();
1509
+ bByLink.clear();
1510
+ for (const log of applogs) processLog(log);
1511
+ }
1512
+ const filtered = rollingFilter2(thread, { at: [attrA, attrB] });
1513
+ buildFull(filtered.applogs);
1514
+ const value = { byA, byB };
1515
+ const result = new SubscribableImpl(
1516
+ value,
1517
+ () => filtered.subscribe((event) => {
1518
+ if (isInitEvent(event)) {
1519
+ buildFull(event.init);
1520
+ } else {
1521
+ if (event.removed) for (const log of event.removed) removeLog(log);
1522
+ for (const log of event.added) processLog(log);
1523
+ }
1524
+ result._set(value);
1525
+ }, "derived"),
1526
+ { equals: false }
1527
+ );
1528
+ return result;
1529
+ }
1530
+ );
1531
+
1532
+ // src/thread/writeable.ts
1533
+ import { Logger as Logger8 } from "besonders-logger";
1534
+ var { WARN: WARN8, LOG: LOG8, DEBUG: DEBUG8, VERBOSE: VERBOSE8, ERROR: ERROR8 } = Logger8.setup(Logger8.INFO);
1535
+ var WriteableThread = class extends Thread {
1536
+ constructor(name, applogs = [], filters) {
1537
+ super(name, null, filters, applogs);
1538
+ }
1539
+ purge(cidsToPurge) {
1540
+ const beforeCount = this.applogs.length;
1541
+ this._applogs = this.applogs.filter((log) => !cidsToPurge.includes(log.cid));
1542
+ return beforeCount - this.applogs.length;
1543
+ }
1544
+ insert(appLogsToInsert) {
1545
+ DEBUG8(`[WriteableThread.insert] ENTER - ${appLogsToInsert.length} applogs for thread "${this.name}"`);
1546
+ DEBUG8(`[WriteableThread.insert] About to call ensureTsPvAndFinalizeApplogs`);
1547
+ const mapped = ensureTsPvAndFinalizeApplogs(appLogsToInsert, this);
1548
+ DEBUG8(`[WriteableThread.insert] ensureTsPvAndFinalizeApplogs completed, mapped=${mapped.length} applogs`);
1549
+ DEBUG8(`[WriteableThread.insert] About to call insertRaw`);
1550
+ const result = this.insertRaw(mapped);
1551
+ DEBUG8(`[WriteableThread.insert] insertRaw completed`);
1552
+ return result;
1553
+ }
1554
+ /**
1555
+ * Insert only applogs not already in this thread.
1556
+ * @param byRef If true, compares by reference; if false, compares by CID (default)
1557
+ * @returns The applogs that were actually inserted
1558
+ */
1559
+ insertMissing(appLogsToInsert, byRef = false) {
1560
+ const missing = appLogsToInsert.filter((log) => !this.hasApplog(log, byRef));
1561
+ if (missing.length === 0) {
1562
+ VERBOSE8(`[insertMissing] no missing applogs`);
1563
+ return [];
1564
+ }
1565
+ return this.insertRaw(missing) ?? [];
1566
+ }
1567
+ /**
1568
+ * Insert raw applogs directly into the thread.
1569
+ *
1570
+ * STRICT VALIDATION: This method throws errors for:
1571
+ * - Duplicate applogs in input array (programming error)
1572
+ * - Invalid applogs (missing required fields)
1573
+ * - Applogs already in thread (programming error)
1574
+ *
1575
+ * For external imports where duplicates are expected, use removeDuplicateAppLogs(..., 'cleanup')
1576
+ * before calling this method.
1577
+ *
1578
+ * @param appLogsToInsert Must be deduplicated and validated. Needs to be mutable because it will be sorted
1579
+ * (and if you need to clone it, so do it when you need to) - this is weird as TS is slathering type safety onto ducks
1580
+ * @throws Error if validation fails
1581
+ */
1582
+ insertRaw(appLogsToInsert) {
1583
+ DEBUG8(`[WriteableThread.insertRaw] ENTER - ${appLogsToInsert.length} applogs for thread "${this.name}"`);
1584
+ DEBUG8(`[WriteableThread.insertRaw] About to deduplicate`);
1585
+ const deduplicated = removeDuplicateAppLogs(appLogsToInsert, "safety");
1586
+ if (deduplicated.length !== appLogsToInsert.length) {
1587
+ throw ERROR8(`[insertRaw] duplicate applogs passed: ${appLogsToInsert.length - deduplicated.length}`, {
1588
+ appLogsToInsert,
1589
+ deduplicated
1590
+ });
1591
+ }
1592
+ DEBUG8(`[WriteableThread.insertRaw] Deduplication done`);
1593
+ DEBUG8(`[WriteableThread.insertRaw] About to validate`);
1594
+ const bogus = appLogsToInsert.filter((log) => !isValidApplog(log));
1595
+ if (bogus.length) {
1596
+ throw ERROR8(`[insertRaw] bogus applogs passed: ${bogus.length}`, { bogus });
1597
+ }
1598
+ DEBUG8(`[WriteableThread.insertRaw] Validation done`);
1599
+ DEBUG8(`[WriteableThread.insertRaw] About to check for existing`);
1600
+ const existing = appLogsToInsert.filter((log) => this.hasApplog(log, false));
1601
+ if (existing.length) {
1602
+ throw ERROR8(`[insertRaw] already existing applogs passed: ${existing.length}`, { existing });
1603
+ }
1604
+ DEBUG8(`[WriteableThread.insertRaw] Existing check done`);
1605
+ if (!appLogsToInsert.length) {
1606
+ WARN8("[insertRaw] skipping empty insert empty logs array");
1607
+ return;
1608
+ }
1609
+ ;
1610
+ (!this.hasParents && !(this instanceof ThreadInMemory) ? LOG8 : DEBUG8)(
1611
+ "Inserting:",
1612
+ appLogsToInsert.length === 1 ? appLogsToInsert[0] : appLogsToInsert,
1613
+ { ds: this }
1614
+ );
1615
+ DEBUG8(`[WriteableThread.insertRaw] About to sort applogs`);
1616
+ sortApplogsByTs(appLogsToInsert);
1617
+ const sortNeeded = this._applogs.length && isTsBefore(appLogsToInsert[0], this._applogs[this._applogs.length - 1]);
1618
+ DEBUG8(`[WriteableThread.insertRaw] About to push to _applogs array`);
1619
+ const CHUNK_SIZE = 5e4;
1620
+ for (let i = 0; i < appLogsToInsert.length; i += CHUNK_SIZE) {
1621
+ this._applogs.push(...appLogsToInsert.slice(i, i + CHUNK_SIZE));
1622
+ }
1623
+ if (sortNeeded) {
1624
+ DEBUG8(`[WriteableThread.insertRaw] About to sort _applogs (sortNeeded=true)`);
1625
+ sortApplogsByTs(this._applogs);
1626
+ }
1627
+ DEBUG8(`[WriteableThread.insertRaw] About to notify subscribers`);
1628
+ this.notifySubscribers({ added: appLogsToInsert, removed: null });
1629
+ DEBUG8(`[WriteableThread.insertRaw] Subscribers notified`);
1630
+ DEBUG8(`[WriteableThread.insertRaw] About to call persist (void - not awaited)`);
1631
+ void this.persist(appLogsToInsert);
1632
+ DEBUG8(`[WriteableThread.insertRaw] EXIT - returning ${appLogsToInsert.length} applogs`);
1633
+ return appLogsToInsert;
1634
+ }
1635
+ get readOnly() {
1636
+ return false;
1637
+ }
1638
+ };
1639
+ var ThreadInMemory = class _ThreadInMemory extends WriteableThread {
1640
+ constructor(name, applogs, filters, _readOnly) {
1641
+ super(name, applogs, filters);
1642
+ this._readOnly = _readOnly;
1643
+ }
1644
+ static empty(name) {
1645
+ return _ThreadInMemory.fromArray([], name ?? "empty in-memory", false);
1646
+ }
1647
+ static fromArray(applogs, name, readOnly = false) {
1648
+ return new _ThreadInMemory(name ?? "in-memory", applogs, [], readOnly);
1649
+ }
1650
+ static fromReadOnlyArray(applogs, name) {
1651
+ return new _ThreadInMemory(name ?? "in-memory", applogs, [], true);
1652
+ }
1653
+ get readOnly() {
1654
+ return this._readOnly;
1655
+ }
1656
+ async persist(logs) {
1657
+ VERBOSE8(`[InMem.persist] no persist for`, logs);
1658
+ if (this.readOnly) {
1659
+ throw ERROR8(`[persist] called for readOnly thread`);
1660
+ }
1661
+ }
1662
+ };
1663
+
1664
+ // src/thread/utils.ts
1665
+ import { Logger as Logger9 } from "besonders-logger";
1666
+ import { debounce, uniq, uniqWith } from "lodash-es";
1667
+ var { WARN: WARN9, LOG: LOG9, DEBUG: DEBUG9, VERBOSE: VERBOSE9, ERROR: ERROR9 } = Logger9.setup(Logger9.INFO);
1668
+ function entityCount(thread) {
1669
+ return allEntityIDs(thread).size;
1670
+ }
1671
+ function allEntityIDs(thread) {
1672
+ return accumulateLogsToSet(thread, (log) => log.en);
1673
+ }
1674
+ function accumulateLogsToSet(threadOrLogs, callback) {
1675
+ const logs = threadOrLogs instanceof Thread ? threadOrLogs.applogs : threadOrLogs;
1676
+ const set = /* @__PURE__ */ new Set();
1677
+ for (const log of logs) {
1678
+ set.add(callback(log, set));
1679
+ }
1680
+ return set;
1681
+ }
1682
+ function debounceWrites(thread, wait = 700, removeDuplicatesWith = compareApplogsByEnAt) {
1683
+ if (thread.readOnly) throw ERROR9(`[debounceWrites] but readOnly thread`, thread.name);
1684
+ let insertQueue = [];
1685
+ const debouncedCommit = debounce(() => {
1686
+ WARN9(`Debounce tail`, { thread, mappedThread, insertQueue });
1687
+ const toInsert = ensureTsPvAndFinalizeApplogs(
1688
+ // ? uniq, sure - but which one is used? (update: seems the first one, so reverse)
1689
+ uniqWith(insertQueue.reverse(), removeDuplicatesWith),
1690
+ thread
1691
+ );
1692
+ thread.insertRaw(toInsert);
1693
+ insertQueue.splice(0, insertQueue.length);
1694
+ }, wait);
1695
+ const handleInsert = (applogs) => {
1696
+ DEBUG9(`Debounce input:`, applogs, { thread, mappedThread, insertQueue });
1697
+ insertQueue.push(...applogs);
1698
+ debouncedCommit();
1699
+ return null;
1700
+ };
1701
+ const mappedThread = MappedThread.mapWrites(
1702
+ thread,
1703
+ `Debounce(${wait})`,
1704
+ handleInsert
1705
+ );
1706
+ return mappedThread;
1707
+ }
1708
+ function holdTillFirstWrite(thread, applogsToHold, opts) {
1709
+ DEBUG9(`[holdTillFirstWrite] holding logs:`, { applogsToHold });
1710
+ if (thread.readOnly) throw ERROR9(`[holdTillFirstWrite] but readOnly thread`, thread.nameAndSizeUntracked);
1711
+ const heldLogs = ensureTsPvAndFinalizeApplogs([...applogsToHold], thread);
1712
+ const heldThread = ThreadInMemory.fromArray(heldLogs);
1713
+ let hasInserted = false;
1714
+ const handleInsert = (realApplogs) => {
1715
+ if (hasInserted) return realApplogs;
1716
+ hasInserted = true;
1717
+ let toInsert = [...heldLogs];
1718
+ if (opts.deduplicateHoldItemsWith) {
1719
+ toInsert = toInsert.filter(
1720
+ (heldLog) => (
1721
+ // some duplicate? so don't insert
1722
+ !realApplogs.some((realLog) => opts.deduplicateHoldItemsWith(heldLog, realLog))
1723
+ )
1724
+ );
1725
+ }
1726
+ if (opts.onFirstWrite) {
1727
+ const callbackResult = opts.onFirstWrite(toInsert);
1728
+ if (callbackResult !== void 0) {
1729
+ toInsert = callbackResult;
1730
+ }
1731
+ }
1732
+ DEBUG9(`[holdTillFirstWrite] adding hold logs:`, { applogsToHold, heldLogs, toInsert, realApplogs });
1733
+ return [...toInsert, ...realApplogs];
1734
+ };
1735
+ const joinedThread = joinThreads([thread, heldThread]);
1736
+ return new MappedThread(
1737
+ `HoldTillFirstWrite[${applogsToHold.length}]<${thread.nameAndSizeUntracked}>`,
1738
+ joinedThread,
1739
+ thread.filters,
1740
+ null,
1741
+ // no derivation — shares joinedThread's array
1742
+ (applogs) => {
1743
+ const logsToInsert = handleInsert(applogs);
1744
+ thread.insert(logsToInsert);
1745
+ return null;
1746
+ }
1747
+ );
1748
+ }
1749
+ function getAgents(thread) {
1750
+ return uniq(thread.map((l) => l.ag));
1751
+ }
1752
+ var excludeApplogsContainedIn = (applogs, exclude) => {
1753
+ const excludeCids = exclude instanceof Set ? new Set([...exclude].map((c) => c.toString())) : exclude instanceof Thread ? new Set(exclude.applogsCids) : new Set(exclude.map((a) => a.cid));
1754
+ return applogs.filter((applog) => {
1755
+ if (!applog.cid) {
1756
+ ERROR9(`applog with missing CID`, applog);
1757
+ throw new Error(`applog with missing CID`);
1758
+ }
1759
+ return !excludeCids.has(applog.cid);
1760
+ });
1761
+ };
1762
+
1763
+ export {
1764
+ Nullable,
1765
+ EntityID_LENGTH,
1766
+ EntityID,
1767
+ isEncryptedApplog,
1768
+ CIDTB,
1769
+ URL,
1770
+ AppLogNoCidTB,
1771
+ AppLogNoCidTBC,
1772
+ getApplogNoCidTypeErrors,
1773
+ isValidApplogNoCid,
1774
+ AppLogTB,
1775
+ AppLogTBC,
1776
+ getApplogTypeErrors,
1777
+ isValidApplog,
1778
+ MULTICODEC_IPNS_KEY,
1779
+ prepareForPub,
1780
+ encodeApplogAndGetCid,
1781
+ encodeApplog,
1782
+ getCidSync,
1783
+ encodeBlock,
1784
+ encodeBlockOriginal,
1785
+ tryParseCID,
1786
+ isIpnsKeyCid,
1787
+ cidToString,
1788
+ toIpnsString,
1789
+ ensureValidCIDinstance,
1790
+ areCidsEqual,
1791
+ containsCid,
1792
+ SubscribableImpl,
1793
+ isArrayInitEvent,
1794
+ SubscribableArrayImpl,
1795
+ createDebugName,
1796
+ createDebugNameObj,
1797
+ prettifyThreadName,
1798
+ isInitEvent,
1799
+ Thread,
1800
+ getLogsFromThread,
1801
+ StaticThread,
1802
+ isoDateStrCompare,
1803
+ objEqualByKeys,
1804
+ compareApplogsByTs,
1805
+ compareApplogsByEnAt,
1806
+ isLaterByTsAndPv,
1807
+ sortApplogsByTs,
1808
+ isTsBefore,
1809
+ uniqueEnFromAppLogs,
1810
+ areApplogsEqual,
1811
+ removeDuplicateAppLogs,
1812
+ getHashID,
1813
+ isVariable,
1814
+ variableNameWithoutQuestionmark,
1815
+ isStaticPattern,
1816
+ resolveOrRemoveVariables,
1817
+ matchPartStatic,
1818
+ matchPart,
1819
+ matchPattern,
1820
+ actualize,
1821
+ arrStats,
1822
+ tsNearlySame,
1823
+ cyrb53hash,
1824
+ arraysContainSameElements,
1825
+ dateNowIso,
1826
+ memoizedFn,
1827
+ refCountedMemoizedFn,
1828
+ MappedThread,
1829
+ rollingFilter2 as rollingFilter,
1830
+ rollingMapper,
1831
+ rollingAcc,
1832
+ getUntrackedPattern,
1833
+ makeFilter,
1834
+ getUntrackedFilterResults,
1835
+ hasFilter,
1836
+ assertRaw,
1837
+ assertOnlyCurrent,
1838
+ asReadOnly,
1839
+ simpleApplogMapper,
1840
+ applogsByEntity,
1841
+ applogsByAttrValue,
1842
+ entityLinkIndex,
1843
+ WriteableThread,
1844
+ ThreadInMemory,
1845
+ entityCount,
1846
+ allEntityIDs,
1847
+ debounceWrites,
1848
+ holdTillFirstWrite,
1849
+ getAgents,
1850
+ excludeApplogsContainedIn,
1851
+ ensureTsPvAndFinalizeApplogs,
1852
+ ensureTsPvAndFinalizeApplog,
1853
+ finalizeApplogForInsert,
1854
+ hasAg,
1855
+ hasTs,
1856
+ hasPv,
1857
+ withTs,
1858
+ withAg,
1859
+ withPvFrom,
1860
+ joinThreads
1861
+ };
1862
+ //# sourceMappingURL=chunk-L5EEEGE6.js.map