@wovin/core 0.2.0 → 0.3.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 (115) hide show
  1. package/dist/applog/applog-utils.d.ts +15 -0
  2. package/dist/applog/applog-utils.d.ts.map +1 -1
  3. package/dist/applog/datom-types.d.ts +63 -7
  4. package/dist/applog/datom-types.d.ts.map +1 -1
  5. package/dist/applog.js +7 -1
  6. package/dist/blockstore.js +2 -0
  7. package/dist/blockstore.js.map +1 -1
  8. package/dist/{chunk-L5EEEGE6.js → chunk-2OXLPZQI.js} +747 -679
  9. package/dist/chunk-2OXLPZQI.js.map +1 -0
  10. package/dist/{chunk-QZXKQCAY.js → chunk-2PJFLZRC.js} +7 -2
  11. package/dist/{chunk-QZXKQCAY.js.map → chunk-2PJFLZRC.js.map} +1 -1
  12. package/dist/chunk-64EJIJAJ.js +17 -0
  13. package/dist/chunk-64EJIJAJ.js.map +1 -0
  14. package/dist/chunk-7QEGHKR4.js +17 -0
  15. package/dist/chunk-7QEGHKR4.js.map +1 -0
  16. package/dist/{chunk-PD3C7XUM.js → chunk-EHO2BFFY.js} +2 -2
  17. package/dist/chunk-ICBK7NC4.js +27 -0
  18. package/dist/chunk-ICBK7NC4.js.map +1 -0
  19. package/dist/{chunk-CPSDKFBG.js → chunk-OKXRRWNS.js} +5 -14
  20. package/dist/chunk-OKXRRWNS.js.map +1 -0
  21. package/dist/{chunk-3WZVG277.js → chunk-Q4EMPWA3.js} +17 -9
  22. package/dist/chunk-Q4EMPWA3.js.map +1 -0
  23. package/dist/{chunk-J2FDHGOZ.js → chunk-VGIACGWX.js} +3 -3
  24. package/dist/{chunk-3JZMOEOD.js → chunk-WVW4YXB5.js} +2 -2
  25. package/dist/chunk-XF4DWOAE.js +25 -0
  26. package/dist/chunk-XF4DWOAE.js.map +1 -0
  27. package/dist/index.js +17 -9
  28. package/dist/ipfs/car.d.ts.map +1 -1
  29. package/dist/ipfs.js +4 -4
  30. package/dist/ipns/gateway-resolver.d.ts +21 -0
  31. package/dist/ipns/gateway-resolver.d.ts.map +1 -0
  32. package/dist/ipns/ipns-record.d.ts +28 -7
  33. package/dist/ipns/ipns-record.d.ts.map +1 -1
  34. package/dist/ipns/ipns-w3name.d.ts +15 -0
  35. package/dist/ipns/ipns-w3name.d.ts.map +1 -0
  36. package/dist/ipns/ipns-watcher.d.ts +190 -0
  37. package/dist/ipns/ipns-watcher.d.ts.map +1 -0
  38. package/dist/ipns.d.ts +3 -0
  39. package/dist/ipns.d.ts.map +1 -1
  40. package/dist/ipns.js +488 -8
  41. package/dist/ipns.js.map +1 -1
  42. package/dist/pubsub/snap-push.d.ts +2 -2
  43. package/dist/pubsub/snap-push.d.ts.map +1 -1
  44. package/dist/pubsub.js +4 -4
  45. package/dist/query/basic.d.ts +3 -3
  46. package/dist/query/basic.d.ts.map +1 -1
  47. package/dist/query/entity-collection.d.ts.map +1 -1
  48. package/dist/query/matchers.d.ts +12 -1
  49. package/dist/query/matchers.d.ts.map +1 -1
  50. package/dist/query.js +7 -5
  51. package/dist/retrieve.js +4 -4
  52. package/dist/thread/indexes.d.ts +3 -2
  53. package/dist/thread/indexes.d.ts.map +1 -1
  54. package/dist/thread.js +1 -1
  55. package/dist/viewmodel/adapters/arktype.d.ts +33 -0
  56. package/dist/viewmodel/adapters/arktype.d.ts.map +1 -0
  57. package/dist/viewmodel/adapters/arktype.js +7 -0
  58. package/dist/viewmodel/adapters/arktype.js.map +1 -0
  59. package/dist/viewmodel/adapters/typebox.d.ts +35 -0
  60. package/dist/viewmodel/adapters/typebox.d.ts.map +1 -0
  61. package/dist/viewmodel/adapters/typebox.js +7 -0
  62. package/dist/viewmodel/adapters/typebox.js.map +1 -0
  63. package/dist/viewmodel/adapters/typia.d.ts +40 -0
  64. package/dist/viewmodel/adapters/typia.d.ts.map +1 -0
  65. package/dist/viewmodel/adapters/typia.js +7 -0
  66. package/dist/viewmodel/adapters/typia.js.map +1 -0
  67. package/dist/viewmodel/adapters/zod.d.ts +30 -0
  68. package/dist/viewmodel/adapters/zod.d.ts.map +1 -0
  69. package/dist/viewmodel/adapters/zod.js +7 -0
  70. package/dist/viewmodel/adapters/zod.js.map +1 -0
  71. package/dist/viewmodel/builder.d.ts +40 -0
  72. package/dist/viewmodel/builder.d.ts.map +1 -0
  73. package/dist/viewmodel/examples/all-adapters.d.ts +26 -0
  74. package/dist/viewmodel/examples/all-adapters.d.ts.map +1 -0
  75. package/dist/viewmodel/factory.d.ts +38 -0
  76. package/dist/viewmodel/factory.d.ts.map +1 -0
  77. package/dist/viewmodel/index.d.ts +10 -0
  78. package/dist/viewmodel/index.d.ts.map +1 -0
  79. package/dist/viewmodel/index.js +313 -0
  80. package/dist/viewmodel/index.js.map +1 -0
  81. package/dist/viewmodel/schema-adapter.d.ts +16 -0
  82. package/dist/viewmodel/schema-adapter.d.ts.map +1 -0
  83. package/dist/viewmodel/types.d.ts +97 -0
  84. package/dist/viewmodel/types.d.ts.map +1 -0
  85. package/package.json +29 -3
  86. package/src/applog/applog-utils.ts +48 -4
  87. package/src/applog/datom-types.ts +24 -5
  88. package/src/applog/object-values.test.ts +106 -0
  89. package/src/ipfs/car.ts +8 -2
  90. package/src/ipns/gateway-resolver.ts +63 -0
  91. package/src/ipns/ipns-record.ts +68 -17
  92. package/src/ipns/ipns-w3name.ts +103 -0
  93. package/src/ipns/ipns-watcher.ts +607 -0
  94. package/src/ipns.ts +3 -0
  95. package/src/pubsub/snap-push.ts +8 -6
  96. package/src/query/entity-collection.ts +2 -1
  97. package/src/query/matchers.ts +23 -1
  98. package/src/thread/basic.ts +2 -2
  99. package/src/thread/indexes.ts +15 -9
  100. package/src/viewmodel/adapters/arktype.ts +44 -0
  101. package/src/viewmodel/adapters/typebox.ts +59 -0
  102. package/src/viewmodel/adapters/typia.ts +50 -0
  103. package/src/viewmodel/adapters/zod.ts +55 -0
  104. package/src/viewmodel/builder.ts +71 -0
  105. package/src/viewmodel/examples/all-adapters.ts +206 -0
  106. package/src/viewmodel/factory.ts +330 -0
  107. package/src/viewmodel/index.ts +22 -0
  108. package/src/viewmodel/schema-adapter.ts +27 -0
  109. package/src/viewmodel/types.ts +152 -0
  110. package/dist/chunk-3WZVG277.js.map +0 -1
  111. package/dist/chunk-CPSDKFBG.js.map +0 -1
  112. package/dist/chunk-L5EEEGE6.js.map +0 -1
  113. /package/dist/{chunk-PD3C7XUM.js.map → chunk-EHO2BFFY.js.map} +0 -0
  114. /package/dist/{chunk-J2FDHGOZ.js.map → chunk-VGIACGWX.js.map} +0 -0
  115. /package/dist/{chunk-3JZMOEOD.js.map → chunk-WVW4YXB5.js.map} +0 -0
@@ -3,265 +3,645 @@ import {
3
3
  } from "./chunk-ZAADLBSB.js";
4
4
 
5
5
  // src/thread/basic.ts
6
- import { Logger } from "besonders-logger";
6
+ import { Logger as Logger2 } from "besonders-logger";
7
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);
8
+ // src/applog/applog-utils.ts
9
+ import { Logger } from "besonders-logger";
10
+ import { isBefore } from "date-fns";
11
+ import { partial, pick } from "lodash-es";
12
+ import { isEqual } from "lodash-es";
13
+ import stringify from "safe-stable-stringify";
14
+ var { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO);
15
+ var isoDateStrCompare = (strA, strB, dir = "asc") => dir === "asc" ? strA.localeCompare(strB, "en-US") : strB.localeCompare(strA, "en-US");
16
+ var objEqualByKeys = (keys, objA, objB) => {
17
+ return isEqual(pick(objA, keys), pick(objB, keys));
18
+ };
19
+ var valueEq = (a, b) => isEqual(a, b);
20
+ var valueKey = (vl) => {
21
+ switch (typeof vl) {
22
+ case "string":
23
+ case "number":
24
+ case "boolean":
25
+ return vl;
26
+ default:
27
+ return vl === null ? null : "\0obj:" + stringify(vl);
21
28
  }
22
- get value() {
23
- return this._value;
29
+ };
30
+ var compareApplogsByTs = (logA, logB, dir = "asc") => {
31
+ const tsCmp = isoDateStrCompare(logA.ts, logB.ts, dir);
32
+ if (tsCmp !== 0) return tsCmp;
33
+ return dir === "asc" ? logA.cid.localeCompare(logB.cid) : logB.cid.localeCompare(logA.cid);
34
+ };
35
+ var compareApplogsByEnAt = partial(objEqualByKeys, ["en", "at"]);
36
+ function isLaterByTsAndPv(a, b) {
37
+ const tsCmp = isoDateStrCompare(a.ts, b.ts);
38
+ if (tsCmp !== 0) return tsCmp > 0;
39
+ if (a.en === b.en && a.at === b.at) {
40
+ if (a.pv === b.cid) return true;
41
+ if (b.pv === a.cid) return false;
24
42
  }
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
- };
43
+ return a.cid.localeCompare(b.cid) > 0;
44
+ }
45
+ function sortApplogsByTs(appLogArray, dir = "asc") {
46
+ appLogArray.sort((a, b) => compareApplogsByTs(a, b, dir));
47
+ let i = 0;
48
+ while (i < appLogArray.length) {
49
+ let j = i + 1;
50
+ while (j < appLogArray.length && appLogArray[j].ts === appLogArray[i].ts) j++;
51
+ if (j - i > 1) chainStabilizeCluster(appLogArray, i, j, dir);
52
+ i = j;
41
53
  }
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();
54
+ return appLogArray;
55
+ }
56
+ function chainStabilizeCluster(applogs, from, to, dir) {
57
+ const groups = /* @__PURE__ */ new Map();
58
+ for (let k = from; k < to; k++) {
59
+ const log = applogs[k];
60
+ const key = log.en + "|" + log.at;
61
+ const existing = groups.get(key);
62
+ if (existing) existing.push(log);
63
+ else groups.set(key, [log]);
47
64
  }
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();
65
+ if (groups.size === to - from) return;
66
+ const orderedByGroup = /* @__PURE__ */ new Map();
67
+ for (const [key, logs] of groups) {
68
+ orderedByGroup.set(key, logs.length === 1 ? logs : topoSortByPv(logs, dir));
53
69
  }
54
- dispose() {
55
- this._deactivateUpstream?.();
56
- this._deactivateUpstream = null;
57
- this._derivedSubscribers.length = 0;
58
- this._subscribers.length = 0;
59
- this._upstreamActive = false;
70
+ const cursors = /* @__PURE__ */ new Map();
71
+ for (let k = from; k < to; k++) {
72
+ const key = applogs[k].en + "|" + applogs[k].at;
73
+ const cursor = cursors.get(key) ?? 0;
74
+ applogs[k] = orderedByGroup.get(key)[cursor];
75
+ cursors.set(key, cursor + 1);
60
76
  }
61
- };
62
- function isArrayInitEvent(event) {
63
- return event.init !== void 0;
64
77
  }
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;
78
+ function topoSortByPv(logs, dir) {
79
+ const cidSet = new Set(logs.map((l) => l.cid));
80
+ const childrenByPv = /* @__PURE__ */ new Map();
81
+ const roots = [];
82
+ for (const log of logs) {
83
+ if (log.pv && cidSet.has(log.pv)) {
84
+ const children = childrenByPv.get(log.pv);
85
+ if (children) children.push(log);
86
+ else childrenByPv.set(log.pv, [log]);
87
+ } else {
88
+ roots.push(log);
89
+ }
75
90
  }
76
- get items() {
77
- return this._items;
91
+ const lexCmp = (a, b) => a.cid.localeCompare(b.cid);
92
+ roots.sort(lexCmp);
93
+ for (const children of childrenByPv.values()) children.sort(lexCmp);
94
+ const result = [];
95
+ const visited = /* @__PURE__ */ new Set();
96
+ const stack = [...roots].reverse();
97
+ while (stack.length > 0) {
98
+ const log = stack.pop();
99
+ if (visited.has(log.cid)) continue;
100
+ visited.add(log.cid);
101
+ result.push(log);
102
+ const children = childrenByPv.get(log.cid);
103
+ if (children) for (let i = children.length - 1; i >= 0; i--) stack.push(children[i]);
78
104
  }
79
- get length() {
80
- return this._items.length;
105
+ if (result.length < logs.length) {
106
+ for (const log of logs) if (!visited.has(log.cid)) result.push(log);
81
107
  }
82
- subscribe(cb, type) {
83
- if (!this._upstreamActive && this._activateUpstream) {
84
- this._deactivateUpstream = this._activateUpstream();
85
- this._upstreamActive = true;
108
+ return dir === "desc" ? result.reverse() : result;
109
+ }
110
+ var isTsBefore = (log, logToCompare) => isBefore(new Date(log.ts), new Date(logToCompare.ts));
111
+ var uniqueEnFromAppLogs = (appLogArray) => [...new Set(appLogArray.map((eachLog) => eachLog.en))];
112
+ var areApplogsEqual = (logA, logB) => isEqual(logA, logB);
113
+ var warnMissingRemoveDuplicateMode = () => {
114
+ WARN(`[removeDuplicateAppLogs] mode not set; pass 'safety' or 'cleanup' for optimal behavior`);
115
+ };
116
+ var removeDuplicateAppLogsCleanup = (appLogArray) => {
117
+ const logMap = /* @__PURE__ */ new Map();
118
+ const verboseEnabled = VERBOSE.isEnabled;
119
+ for (const eachLog of appLogArray) {
120
+ if (!eachLog) {
121
+ ERROR(`falsy entry in applogs`, appLogArray);
122
+ throw new Error(`falsy entry in applogs`);
86
123
  }
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);
124
+ if (!eachLog.cid) {
125
+ ERROR(`applog with missing CID`, eachLog);
126
+ throw new Error(`applog with missing CID`);
127
+ }
128
+ const key = eachLog.cid;
129
+ const existing = logMap.get(key);
130
+ if (existing) {
131
+ if (verboseEnabled) VERBOSE(`Skipping duplicate applog:`, [existing, eachLog]);
132
+ } else {
133
+ logMap.set(key, eachLog);
109
134
  }
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
135
  }
136
+ return Array.from(logMap.values());
130
137
  };
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
+ var removeDuplicateAppLogsSafety = (appLogArray) => {
139
+ const seen = /* @__PURE__ */ new Set();
140
+ const verboseEnabled = VERBOSE.isEnabled;
141
+ const existingByCid = verboseEnabled ? /* @__PURE__ */ new Map() : null;
142
+ let result = null;
143
+ let index = 0;
144
+ for (const eachLog of appLogArray) {
145
+ if (!eachLog) {
146
+ ERROR(`falsy entry in applogs`, appLogArray);
147
+ throw new Error(`falsy entry in applogs`);
148
+ }
149
+ if (!eachLog.cid) {
150
+ ERROR(`applog with missing CID`, eachLog);
151
+ throw new Error(`applog with missing CID`);
152
+ }
153
+ const key = eachLog.cid;
154
+ if (seen.has(key)) {
155
+ if (!result) {
156
+ result = appLogArray.slice(0, index);
157
+ }
158
+ if (verboseEnabled) VERBOSE(`Skipping duplicate applog:`, [existingByCid?.get(key), eachLog]);
159
+ } else {
160
+ seen.add(key);
161
+ if (existingByCid) existingByCid.set(key, eachLog);
162
+ if (result) result.push(eachLog);
163
+ }
164
+ index++;
165
+ }
166
+ return result ?? appLogArray;
138
167
  };
139
- var createDebugNameObj = (args) => {
140
- return { name: createDebugName(args) };
168
+ var removeDuplicateAppLogs = (appLogArray, mode) => {
169
+ if (!mode) {
170
+ warnMissingRemoveDuplicateMode();
171
+ return removeDuplicateAppLogsCleanup(appLogArray);
172
+ }
173
+ return mode === "safety" ? removeDuplicateAppLogsSafety(appLogArray) : removeDuplicateAppLogsCleanup(appLogArray);
141
174
  };
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;
175
+ var getHashID = (stringifiable, lngth = 8) => cyrb53hash(stringify(stringifiable), 31, lngth);
176
+ function isVariable(x) {
177
+ return typeof x === "string" && x.startsWith("?");
178
+ }
179
+ function variableNameWithoutQuestionmark(str) {
180
+ return str.slice(1);
181
+ }
182
+ function isStaticPattern(x) {
183
+ if (!["string", "boolean", "number", "function"].includes(typeof x)) WARN(`Unhandled pattern value type:`, typeof x, x);
184
+ return !isVariable(x) && ["string", "boolean", "number"].includes(typeof x);
185
+ }
186
+ function resolveOrRemoveVariables(pattern, candidate) {
187
+ let variablesToFill = {};
188
+ const newPattern = {};
189
+ for (const [patternKey, patternValue] of Object.entries(pattern)) {
190
+ if (isVariable(patternValue)) {
191
+ const varName = variableNameWithoutQuestionmark(patternValue);
192
+ const candidateValue = candidate[varName];
193
+ if (candidateValue) {
194
+ newPattern[patternKey] = candidateValue;
195
+ } else {
196
+ variablesToFill[patternKey] = varName;
197
+ }
166
198
  } else {
167
- result += char;
199
+ newPattern[patternKey] = patternValue;
168
200
  }
169
201
  }
170
- return result;
202
+ return [newPattern, variablesToFill];
171
203
  }
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;
204
+ function matchVariable(variable, triplePart, context) {
205
+ if (context.hasOwnProperty(variable)) {
206
+ const bound = context[variable];
207
+ const match = matchPart(bound, triplePart, context);
208
+ return match;
195
209
  }
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);
210
+ return { ...context, [variable]: triplePart };
211
+ }
212
+ function matchPartStatic(field, patternPart, atomPart) {
213
+ let result;
214
+ if (patternPart) {
215
+ const typ = typeof patternPart;
216
+ if (typ === "string") {
217
+ result = patternPart === atomPart;
218
+ } else if (typ === "function") {
219
+ result = patternPart(atomPart);
220
+ } else if (Array.isArray(patternPart)) {
221
+ throw ERROR(
222
+ `[matchPartStatic] a bare array is not a valid matcher for field '${field}'. Use anyOf(...) for set-membership, or a predicate (v) => isEqual(v, [...]) to match a literal array value.`,
223
+ patternPart
224
+ );
225
+ } else if (typeof patternPart.has === "function") {
226
+ result = patternPart.has(atomPart);
227
+ } else {
228
+ result = valueEq(patternPart, atomPart);
229
+ }
230
+ } else {
231
+ result = patternPart === atomPart;
201
232
  }
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);
233
+ if (field.charAt(0) === "!") {
234
+ return !result;
235
+ } else {
236
+ return result;
207
237
  }
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
- };
238
+ }
239
+ function matchPart(patternPart, atomPart, context) {
240
+ if (!context) {
241
+ return null;
215
242
  }
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);
243
+ if (typeof patternPart === "string") {
244
+ if (isVariable(patternPart)) {
245
+ return matchVariable(patternPart, atomPart, context);
226
246
  }
227
247
  }
228
- // ── SubscribableArray<Applog> ──
229
- get items() {
230
- return this._applogs;
231
- }
232
- dispose() {
233
- this._derivedSubscribers.length = 0;
234
- this._subscribers.length = 0;
248
+ if (typeof patternPart === "function") {
249
+ return patternPart(atomPart) ? context : null;
235
250
  }
236
- get applogs() {
237
- return this._applogs;
251
+ if (Array.isArray(patternPart)) {
252
+ throw ERROR(
253
+ `[matchPart] a bare array is not a valid matcher. Use anyOf(...) for set-membership, or a predicate to match a literal array value.`,
254
+ patternPart
255
+ );
238
256
  }
239
- get applogsCids() {
240
- return this._applogs.map((l) => l.cid);
257
+ if (patternPart && typeof patternPart.has === "function") {
258
+ return patternPart.has(atomPart) ? context : null;
241
259
  }
242
- get applogsCidSet() {
243
- return new Set(this._applogs.map((l) => l.cid));
260
+ return valueEq(patternPart, atomPart) ? context : null;
261
+ }
262
+ function matchPattern(pattern, applog, context) {
263
+ return Object.entries(pattern).reduce((context2, [field, patternValue]) => {
264
+ const applogValue = applog[field];
265
+ const patternValT = patternValue;
266
+ return matchPart(patternValT, applogValue, context2);
267
+ }, context);
268
+ }
269
+ function actualize(context, find) {
270
+ return Object.fromEntries(find.map((findField) => {
271
+ if (context === null) {
272
+ throw new Error(`actualize context is null ${find}`);
273
+ }
274
+ return [
275
+ isVariable(findField) ? findField.replace(/^\?/, "") : findField,
276
+ isVariable(findField) ? context[findField] : findField
277
+ ];
278
+ }));
279
+ }
280
+ var sum = function sum2(array) {
281
+ var num = 0;
282
+ for (var i = 0, l = array.length; i < l; i++) num += array[i];
283
+ return num;
284
+ };
285
+ var mean = function mean2(array) {
286
+ return sum(array) / array.length;
287
+ };
288
+ var arrStats = {
289
+ max: function(array) {
290
+ return Math.max.apply(null, array);
291
+ },
292
+ min: function(array) {
293
+ return Math.min.apply(null, array);
294
+ },
295
+ range: function(array) {
296
+ return arrStats.max(array) - arrStats.min(array);
297
+ },
298
+ midrange: function(array) {
299
+ return arrStats.range(array) / 2;
300
+ },
301
+ sum,
302
+ mean,
303
+ average: mean,
304
+ median: function(array) {
305
+ array.sort(function(a, b) {
306
+ return a - b;
307
+ });
308
+ var mid = array.length / 2;
309
+ return mid % 1 ? array[mid - 0.5] : (array[mid - 1] + array[mid]) / 2;
310
+ },
311
+ modes: function(array) {
312
+ if (!array.length) return [];
313
+ var modeMap = {}, maxCount = 0, modes = [];
314
+ array.forEach(function(val) {
315
+ if (!modeMap[val]) modeMap[val] = 1;
316
+ else modeMap[val]++;
317
+ if (modeMap[val] > maxCount) {
318
+ modes = [val];
319
+ maxCount = modeMap[val];
320
+ } else if (modeMap[val] === maxCount) {
321
+ modes.push(val);
322
+ maxCount = modeMap[val];
323
+ }
324
+ });
325
+ return modes;
326
+ },
327
+ variance: function(array) {
328
+ var mean3 = arrStats.mean(array);
329
+ return arrStats.mean(array.map(function(num) {
330
+ return Math.pow(num - mean3, 2);
331
+ }));
332
+ },
333
+ standardDeviation: function(array) {
334
+ return Math.sqrt(arrStats.variance(array));
335
+ },
336
+ meanAbsoluteDeviation: function(array) {
337
+ var mean3 = arrStats.mean(array);
338
+ return arrStats.mean(array.map(function(num) {
339
+ return Math.abs(num - mean3);
340
+ }));
341
+ },
342
+ zScores: function(array) {
343
+ var mean3 = arrStats.mean(array);
344
+ var standardDeviation = arrStats.standardDeviation(array);
345
+ return array.map(function(num) {
346
+ return (num - mean3) / standardDeviation;
347
+ });
244
348
  }
245
- map(fn) {
246
- return this.applogs.map(fn);
349
+ };
350
+ arrStats.average = arrStats.mean;
351
+ var tsNearlySame = (timeA, timeB) => timeB.startsWith(timeA.slice(0, timeA.length - 4));
352
+ var cyrb53hash = function(str, seed = 13, strLength) {
353
+ if (!str?.length) {
354
+ throw new Error(`Empty string: ${str}`);
247
355
  }
248
- get findLast() {
249
- return this.applogs.findLast.bind(this.applogs);
356
+ let h1 = 3735928559 ^ seed;
357
+ let h2 = 1103547991 ^ seed;
358
+ for (let i = 0, ch; i < str.length; i++) {
359
+ ch = str.charCodeAt(i);
360
+ h1 = Math.imul(h1 ^ ch, 2654435761);
361
+ h2 = Math.imul(h2 ^ ch, 1597334677);
250
362
  }
251
- get findFirst() {
252
- return this.applogs.find.bind(this.applogs);
363
+ h1 = Math.imul(h1 ^ h1 >>> 16, 2246822507) ^ Math.imul(h2 ^ h2 >>> 13, 3266489909);
364
+ h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507) ^ Math.imul(h1 ^ h1 >>> 13, 3266489909);
365
+ const asHex = (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(16);
366
+ return asHex.slice(-strLength).padStart(strLength, "0");
367
+ };
368
+ function arraysContainSameElements(arr1, arr2) {
369
+ if (arr1.length !== arr2.length) {
370
+ return false;
253
371
  }
254
- get firstLog() {
255
- return this.applogs[0];
372
+ const sortedArr1 = [...arr1].sort();
373
+ const sortedArr2 = [...arr2].sort();
374
+ for (let i = 0; i < sortedArr1.length; i++) {
375
+ if (sortedArr1[i] !== sortedArr2[i]) {
376
+ return false;
377
+ }
256
378
  }
257
- get latestLog() {
379
+ return true;
380
+ }
381
+ function dateNowIso() {
382
+ const now = /* @__PURE__ */ new Date();
383
+ return now.toISOString();
384
+ }
385
+
386
+ // src/query/subscribable.ts
387
+ var SubscribableImpl = class {
388
+ _value;
389
+ _derivedSubscribers = [];
390
+ _subscribers = [];
391
+ _upstreamActive = false;
392
+ _activateUpstream;
393
+ _deactivateUpstream = null;
394
+ _equals;
395
+ constructor(initialValue, activateUpstream, opts) {
396
+ this._value = initialValue;
397
+ this._activateUpstream = activateUpstream ?? null;
398
+ this._equals = opts?.equals === false ? () => false : opts?.equals ?? ((a, b) => a === b);
399
+ }
400
+ get value() {
401
+ return this._value;
402
+ }
403
+ subscribe(cb, type) {
404
+ if (!this._upstreamActive && this._activateUpstream) {
405
+ this._deactivateUpstream = this._activateUpstream();
406
+ this._upstreamActive = true;
407
+ }
408
+ const list = type === "derived" ? this._derivedSubscribers : this._subscribers;
409
+ list.push(cb);
410
+ return () => {
411
+ const idx = list.indexOf(cb);
412
+ if (idx >= 0) list.splice(idx, 1);
413
+ if (this._derivedSubscribers.length === 0 && this._subscribers.length === 0 && this._upstreamActive) {
414
+ this._deactivateUpstream?.();
415
+ this._deactivateUpstream = null;
416
+ this._upstreamActive = false;
417
+ }
418
+ };
419
+ }
420
+ /** Update value and notify subscribers (skips if equals check passes) */
421
+ _set(value) {
422
+ if (this._equals(value, this._value)) return;
423
+ this._value = value;
424
+ this._notify();
425
+ }
426
+ _notify() {
427
+ const derived = [...this._derivedSubscribers];
428
+ for (const sub of derived) sub();
429
+ const subs = [...this._subscribers];
430
+ for (const sub of subs) sub();
431
+ }
432
+ dispose() {
433
+ this._deactivateUpstream?.();
434
+ this._deactivateUpstream = null;
435
+ this._derivedSubscribers.length = 0;
436
+ this._subscribers.length = 0;
437
+ this._upstreamActive = false;
438
+ }
439
+ };
440
+ function isArrayInitEvent(event) {
441
+ return event.init !== void 0;
442
+ }
443
+ var SubscribableArrayImpl = class {
444
+ _items;
445
+ _derivedSubscribers = [];
446
+ _subscribers = [];
447
+ _upstreamActive = false;
448
+ _activateUpstream;
449
+ _deactivateUpstream = null;
450
+ constructor(initialItems, activateUpstream) {
451
+ this._items = initialItems;
452
+ this._activateUpstream = activateUpstream ?? null;
453
+ }
454
+ get items() {
455
+ return this._items;
456
+ }
457
+ get length() {
458
+ return this._items.length;
459
+ }
460
+ subscribe(cb, type) {
461
+ if (!this._upstreamActive && this._activateUpstream) {
462
+ this._deactivateUpstream = this._activateUpstream();
463
+ this._upstreamActive = true;
464
+ }
465
+ const list = type === "derived" ? this._derivedSubscribers : this._subscribers;
466
+ list.push(cb);
467
+ return () => {
468
+ const idx = list.indexOf(cb);
469
+ if (idx >= 0) list.splice(idx, 1);
470
+ if (this._derivedSubscribers.length === 0 && this._subscribers.length === 0 && this._upstreamActive) {
471
+ this._deactivateUpstream?.();
472
+ this._deactivateUpstream = null;
473
+ this._upstreamActive = false;
474
+ }
475
+ };
476
+ }
477
+ /** Push items and notify subscribers */
478
+ _push(...items) {
479
+ this._items.push(...items);
480
+ this._notify({ added: items, removed: null });
481
+ }
482
+ /** Remove items and notify subscribers */
483
+ _remove(items) {
484
+ for (const item of items) {
485
+ const idx = this._items.indexOf(item);
486
+ if (idx >= 0) this._items.splice(idx, 1);
487
+ }
488
+ this._notify({ added: [], removed: items });
489
+ }
490
+ /** Full reset — replace all items */
491
+ _reset(items) {
492
+ this._items = items;
493
+ this._notify({ init: [...this._items] });
494
+ }
495
+ _notify(event) {
496
+ const derived = [...this._derivedSubscribers];
497
+ for (const sub of derived) sub(event);
498
+ const subs = [...this._subscribers];
499
+ for (const sub of subs) sub(event);
500
+ }
501
+ dispose() {
502
+ this._deactivateUpstream?.();
503
+ this._deactivateUpstream = null;
504
+ this._derivedSubscribers.length = 0;
505
+ this._subscribers.length = 0;
506
+ this._upstreamActive = false;
507
+ }
508
+ };
509
+
510
+ // src/utils/debug-name.ts
511
+ import stringify2 from "safe-stable-stringify";
512
+ var createDebugName = ({ caller, thread, pattern, args }) => {
513
+ args = args || pattern;
514
+ const str = `${!Array.isArray(thread) && thread?.name ? thread.name + " | " : ""}${caller ?? "caller?"}${args ? `{${typeof args === "string" ? args : stringify2(args)}}` : ""}`;
515
+ return str;
516
+ };
517
+ var createDebugNameObj = (args) => {
518
+ return { name: createDebugName(args) };
519
+ };
520
+ function prettifyThreadName(input) {
521
+ let depth = 0;
522
+ let result = "";
523
+ let insideCurlyBraces = 0;
524
+ for (let i = 0; i < input.length; i++) {
525
+ const char = input[i];
526
+ if (char === "(") {
527
+ result += char + "\n" + " ".repeat(++depth);
528
+ } else if (char === ")") {
529
+ result += "\n" + " ".repeat(--depth) + char;
530
+ } else if (char === "," && insideCurlyBraces === 0) {
531
+ result += char + "\n" + " ".repeat(depth);
532
+ } else if (char === "{" && insideCurlyBraces === 0) {
533
+ insideCurlyBraces++;
534
+ result += char + "\n" + " ".repeat(depth + 1);
535
+ } else if (char === "}" && insideCurlyBraces === 1) {
536
+ insideCurlyBraces--;
537
+ result += "\n" + " ".repeat(depth) + char;
538
+ } else if (char === "{" && insideCurlyBraces > 0) {
539
+ insideCurlyBraces++;
540
+ result += char;
541
+ } else if (char === "}" && insideCurlyBraces > 1) {
542
+ insideCurlyBraces--;
543
+ result += char;
544
+ } else {
545
+ result += char;
546
+ }
547
+ }
548
+ return result;
549
+ }
550
+
551
+ // src/thread/basic.ts
552
+ var { WARN: WARN2, LOG: LOG2, DEBUG: DEBUG2, VERBOSE: VERBOSE2, ERROR: ERROR2 } = Logger2.setup(Logger2.INFO, { prefix: "[thread]" });
553
+ var isInitEvent = isArrayInitEvent;
554
+ var Thread = class {
555
+ constructor(name, parents, filters, _applogs = []) {
556
+ this.name = name;
557
+ this._applogs = _applogs;
558
+ this.parents = parents === null ? null : arrayIfSingle(parents);
559
+ this.filters = filters;
560
+ if (this.parents?.length === 0) {
561
+ WARN2(`[Thread] empty parents array`, name);
562
+ }
563
+ }
564
+ name;
565
+ _applogs;
566
+ filters;
567
+ parents;
568
+ _derivedSubscribers = [];
569
+ _subscribers = [];
570
+ /** Monotonic counter incremented on every mutation. Used by memoizedFn to invalidate caches. */
571
+ _version = 0;
572
+ get readOnly() {
573
+ if (this.parents.length !== 1) return true;
574
+ return this.parents[0].readOnly;
575
+ }
576
+ insert(appLogsToInsert) {
577
+ if (this.readOnly) throw ERROR2(`[Thread] insert() called on read-only thread:`, this.nameAndSizeUntracked);
578
+ if (!this.parents) throw ERROR2(`[Thread] insert() called on non-writable thread without parents:`, this.nameAndSizeUntracked);
579
+ if (this.parents?.length !== 1) throw ERROR2(`[Thread] insert() called on thread with multiple parents:`, this.nameAndSizeUntracked);
580
+ return this.parents[0].insert(appLogsToInsert);
581
+ }
582
+ insertRaw(appLogsToInsert) {
583
+ if (this.readOnly) throw ERROR2(`[Thread] insertRaw() called on read-only thread:`, this.nameAndSizeUntracked);
584
+ if (!this.parents) throw ERROR2(`[Thread] insertRaw() called on non-writable thread without parents:`, this.nameAndSizeUntracked);
585
+ if (this.parents?.length !== 1) throw ERROR2(`[Thread] insertRaw() called on thread with multiple parents:`, this.nameAndSizeUntracked);
586
+ return this.parents[0].insertRaw(appLogsToInsert);
587
+ }
588
+ subscribe(callback, type) {
589
+ const list = type === "derived" ? this._derivedSubscribers : this._subscribers;
590
+ list.push(callback);
591
+ return () => {
592
+ const idx = list.indexOf(callback);
593
+ if (idx >= 0) list.splice(idx, 1);
594
+ };
595
+ }
596
+ notifySubscribers(event) {
597
+ this._version++;
598
+ DEBUG2(`[thread: ${this.name}] notifying`, this._derivedSubscribers.length, "derived +", this._subscribers.length, "subscribers of", { ...event, subs: this._subscribers });
599
+ const derived = [...this._derivedSubscribers];
600
+ for (const subscriber of derived) {
601
+ subscriber(event);
602
+ }
603
+ const subs = [...this._subscribers];
604
+ for (const subscriber of subs) {
605
+ subscriber(event);
606
+ }
607
+ }
608
+ // ── SubscribableArray<Applog> ──
609
+ get items() {
610
+ return this._applogs;
611
+ }
612
+ dispose() {
613
+ this._derivedSubscribers.length = 0;
614
+ this._subscribers.length = 0;
615
+ }
616
+ get applogs() {
617
+ return this._applogs;
618
+ }
619
+ get applogsCids() {
620
+ return this._applogs.map((l) => l.cid);
621
+ }
622
+ get applogsCidSet() {
623
+ return new Set(this._applogs.map((l) => l.cid));
624
+ }
625
+ map(fn) {
626
+ return this.applogs.map(fn);
627
+ }
628
+ get findLast() {
629
+ return this.applogs.findLast.bind(this.applogs);
630
+ }
631
+ get findFirst() {
632
+ return this.applogs.find.bind(this.applogs);
633
+ }
634
+ get firstLog() {
635
+ return this.applogs[0];
636
+ }
637
+ get latestLog() {
258
638
  return this.applogs[this.applogs.length - 1];
259
639
  }
260
640
  hasApplog(applog, byRef) {
261
641
  if (byRef) {
262
642
  return this.applogs.includes(applog);
263
643
  } else {
264
- if (!applog.cid) throw ERROR(`[hasApplogs] applog without CID:`, applog);
644
+ if (!applog.cid) throw ERROR2(`[hasApplogs] applog without CID:`, applog);
265
645
  return this.hasApplogCid(applog.cid);
266
646
  }
267
647
  }
@@ -275,7 +655,7 @@ var Thread = class {
275
655
  return this.applogsByCid.get(cid.toString());
276
656
  }
277
657
  hasApplogWithDiffTs(applog) {
278
- return this.applogs.find((existing) => existing.en === applog.en && existing.at === applog.at && existing.vl === applog.vl && existing.ag === applog.ag);
658
+ return this.applogs.find((existing) => existing.en === applog.en && existing.at === applog.at && valueEq(existing.vl, applog.vl) && existing.ag === applog.ag);
279
659
  }
280
660
  // get stateHash() {
281
661
  // blakeHasher.init()
@@ -329,7 +709,7 @@ import { Logger as Logger4 } from "besonders-logger";
329
709
  // src/ipfs/ipfs-utils.ts
330
710
  import * as dagJson from "@ipld/dag-json";
331
711
  import { sha256 } from "@noble/hashes/sha2.js";
332
- import { Logger as Logger2 } from "besonders-logger";
712
+ import { Logger as Logger3 } from "besonders-logger";
333
713
  import { CID, digest as Digest } from "multiformats";
334
714
  import { encode as multiformatsEncode } from "multiformats/block";
335
715
 
@@ -344,17 +724,27 @@ FormatRegistry.Set("EntityID", (value) => !!value.match(isShortHash) || !!value.
344
724
  var EntityID = Type.String();
345
725
  var isEncryptedApplog = (l) => l?.enc instanceof Uint8Array;
346
726
  FormatRegistry.Set("CID", (value) => !!value.match(isCID));
347
- var CIDTB = Type.String({ format: "CID" });
727
+ var CIDTB = Type.String({ pattern: isCID.source });
348
728
  var isURL = /^http([s]?):\/\/.*\..*/;
349
729
  FormatRegistry.Set("URL", (value) => !!value.match(isURL));
350
- var URL = Type.String({ format: "URL" });
730
+ var URL = Type.String({ pattern: isURL.source });
731
+ var JsonValueTB = Type.Recursive(
732
+ (This) => Type.Union([
733
+ Type.String(),
734
+ Type.Number(),
735
+ Type.Boolean(),
736
+ Type.Null(),
737
+ Type.Array(This),
738
+ Type.Record(Type.String(), This)
739
+ ])
740
+ );
351
741
  var AppLogNoCidTB = Type.Object({
352
742
  en: EntityID,
353
743
  // EntityID
354
744
  at: Type.String(),
355
745
  // Attribute
356
- vl: Nullable(Type.Union([Type.String(), Type.Boolean(), Type.Number()])),
357
- // TODO refactor to semantic typesafe ApplogValue
746
+ vl: JsonValueTB,
747
+ // ApplogValue (JSON-serializable: primitives, arrays, objects)
358
748
  ts: Type.String(),
359
749
  // Timestamp
360
750
  ag: Type.String(),
@@ -378,466 +768,111 @@ var isValidApplog = AppLogTBC.Check.bind(AppLogTBC);
378
768
  // src/ipfs/ipfs-utils.ts
379
769
  import { base36 } from "multiformats/bases/base36";
380
770
  import { sha256 as sha265Hasher } from "multiformats/hashes/sha2";
381
- var { WARN: WARN2, LOG: LOG2, DEBUG: DEBUG2, VERBOSE: VERBOSE2, ERROR: ERROR2 } = Logger2.setup(Logger2.INFO);
771
+ var { WARN: WARN3, LOG: LOG3, DEBUG: DEBUG3, VERBOSE: VERBOSE3, ERROR: ERROR3 } = Logger3.setup(Logger3.INFO);
382
772
  var MULTICODEC_IPNS_KEY = 114;
383
773
  function prepareForPub(log, without = ["cid"]) {
384
- if (!log) throw ERROR2("falsy log", log);
774
+ if (!log) throw ERROR3("falsy log", log);
385
775
  let cid = log.cid;
386
776
  if (isEncryptedApplog(log)) {
387
777
  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
- }
778
+ WARN3("preparing an encrypted applog - really?");
779
+ return { log, cid };
780
+ }
781
+ const logWithout = {};
782
+ for (let [key, val] of Object.entries(log)) {
783
+ if (val === void 0) {
784
+ WARN3(`log.${key} is undefined, which is not allowed - encoding as null`, log);
785
+ val = null;
786
+ }
787
+ if (!without.includes(key)) {
788
+ logWithout[key] = val;
667
789
  } else {
668
- newPattern[patternKey] = patternValue;
790
+ VERBOSE3("excluding app log", { key, val });
669
791
  }
670
792
  }
671
- return [newPattern, variablesToFill];
793
+ return { log: logWithout, cid };
672
794
  }
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 };
795
+ function encodeApplogAndGetCid(log) {
796
+ return getCidSync(encodeApplog(log).bytes);
680
797
  }
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;
798
+ function encodeApplog(log) {
799
+ return encodeBlock(prepareForPub(log)?.log);
800
+ }
801
+ function getCidSync(bytes) {
802
+ const hash = sha256(bytes);
803
+ const digest = Digest.create(sha265Hasher.code, hash);
804
+ const cid = CID.create(1, dagJson.code, digest);
805
+ VERBOSE3(`[getCidSync]`, { bytes, hash, digest, cid });
806
+ return cid;
807
+ }
808
+ function encodeBlock(jsonObject) {
809
+ DEBUG3("[encodeBlock]", jsonObject);
810
+ try {
811
+ const byteView = dagJson.encode(jsonObject);
812
+ return { bytes: byteView, cid: getCidSync(byteView) };
813
+ } catch (err) {
814
+ throw ERROR3("[encodeBlock] failed to encode:", jsonObject, err);
698
815
  }
699
- if (field.charAt(0) === "!") {
700
- return !result;
701
- } else {
702
- return result;
816
+ }
817
+ async function encodeBlockOriginal(jsonObject) {
818
+ const encoded = await multiformatsEncode({ value: jsonObject, codec: dagJson, hasher: sha265Hasher });
819
+ const syncVariant = encodeBlock(jsonObject);
820
+ if (syncVariant.cid.toString() !== encoded.cid.toString()) {
821
+ ERROR3(`[encodeBlockOriginal] sync cid mismatch`, { jsonObject, encoded, syncVariant });
703
822
  }
823
+ return encoded;
704
824
  }
705
- function matchPart(patternPart, atomPart, context) {
706
- if (!context) {
707
- return null;
825
+ function tryParseCID(cidString) {
826
+ let cid = null;
827
+ let errors = [];
828
+ try {
829
+ cid = CID.parse(cidString);
830
+ } catch (err) {
831
+ VERBOSE3(`[retrieveThread] couldn't parse pubID with default base`);
832
+ errors.push(err);
708
833
  }
709
- if (typeof patternPart === "string") {
710
- if (isVariable(patternPart)) {
711
- return matchVariable(patternPart, atomPart, context);
834
+ if (!cid) {
835
+ try {
836
+ cid = CID.parse(cidString, base36);
837
+ } catch (err) {
838
+ VERBOSE3(`[retrieveThread] couldn't parse pubID with base36`);
839
+ errors.push(err);
712
840
  }
713
841
  }
714
- if (typeof patternPart === "function") {
715
- return patternPart(atomPart) ? context : null;
842
+ return {
843
+ cid,
844
+ errors: cid ? null : errors,
845
+ // we only care about errors if we failed to parse
846
+ isIpns: cid && isIpnsKeyCid(cid)
847
+ };
848
+ }
849
+ function isIpnsKeyCid(cid) {
850
+ return cid.code === MULTICODEC_IPNS_KEY;
851
+ }
852
+ function cidToString(cid) {
853
+ if (cid.code == MULTICODEC_IPNS_KEY) {
854
+ return toIpnsString(cid);
855
+ } else {
856
+ return cid.toString();
716
857
  }
717
- return patternPart === atomPart ? context : null;
718
858
  }
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);
859
+ function toIpnsString(cid) {
860
+ if (cid.code !== MULTICODEC_IPNS_KEY) throw ERROR3(`Not an IPNS cid (${cid.code}):`, cid.toString());
861
+ return cid.toString(base36);
725
862
  }
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
- }));
863
+ function ensureValidCIDinstance(cidOrStringA) {
864
+ return typeof cidOrStringA === "string" ? CID.parse(cidOrStringA) : typeof cidOrStringA.toV1 != "function" ? CID.decode(cidOrStringA.bytes) : cidOrStringA;
736
865
  }
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;
866
+ function areCidsEqual(cidOrStringA, cidOrStringB) {
867
+ if (!cidOrStringA || !cidOrStringB) throw new Error(`[areCidsEqual] invalid params: ${cidOrStringA}, ${cidOrStringB}`);
868
+ if (cidOrStringA === cidOrStringB) return true;
869
+ const cidA = ensureValidCIDinstance(cidOrStringA);
870
+ const cidB = ensureValidCIDinstance(cidOrStringB);
871
+ return cidA.toV1().toString() === cidB.toV1().toString();
837
872
  }
838
- function dateNowIso() {
839
- const now = /* @__PURE__ */ new Date();
840
- return now.toISOString();
873
+ function containsCid(list, needle) {
874
+ if (list instanceof Set) return list.has(typeof needle === "string" ? needle : needle.toV1().toString());
875
+ return list.some((cidOrString) => areCidsEqual(cidOrString, needle));
841
876
  }
842
877
 
843
878
  // src/applog/applog-helpers.ts
@@ -1066,6 +1101,10 @@ var MappedThread = class _MappedThread extends Thread {
1066
1101
  this.subscribeToParents();
1067
1102
  }
1068
1103
  }
1104
+ name;
1105
+ _derivation;
1106
+ _writeMapper;
1107
+ _readOnly;
1069
1108
  static mapWrites(parent, name, mapper) {
1070
1109
  return new _MappedThread(
1071
1110
  `${name}<${parent.nameAndSizeUntracked}>`,
@@ -1363,6 +1402,26 @@ var simpleApplogMapper = function simpleApplogMapper2(thread, logMapper, opts =
1363
1402
 
1364
1403
  // src/thread/indexes.ts
1365
1404
  import { Logger as Logger7 } from "besonders-logger";
1405
+
1406
+ // src/query/matchers.ts
1407
+ function includes(str) {
1408
+ return (vl) => vl?.includes?.(str);
1409
+ }
1410
+ function includedIn(arr) {
1411
+ return (vl) => arr?.includes?.(vl);
1412
+ }
1413
+ function anyOf(...vals) {
1414
+ for (const v of vals) {
1415
+ if (v !== null && typeof v === "object") {
1416
+ throw new Error(
1417
+ `[anyOf] object/array members are not supported (referential Set membership would silently never match). Use a predicate matcher instead, e.g. (v) => members.some(m => isEqual(v, m)).`
1418
+ );
1419
+ }
1420
+ }
1421
+ return new Set(vals);
1422
+ }
1423
+
1424
+ // src/thread/indexes.ts
1366
1425
  var { WARN: WARN7, LOG: LOG7, DEBUG: DEBUG7, VERBOSE: VERBOSE7, ERROR: ERROR7 } = Logger7.setup(Logger7.INFO);
1367
1426
  var applogsByEntity = memoizedFn(
1368
1427
  "applogsByEntity",
@@ -1401,19 +1460,21 @@ var applogsByAttrValue = memoizedFn(
1401
1460
  function applogsByAttrValue2(thread, attr) {
1402
1461
  const map = /* @__PURE__ */ new Map();
1403
1462
  const add = (log) => {
1404
- let arr = map.get(log.vl);
1463
+ const key = valueKey(log.vl);
1464
+ let arr = map.get(key);
1405
1465
  if (!arr) {
1406
1466
  arr = [];
1407
- map.set(log.vl, arr);
1467
+ map.set(key, arr);
1408
1468
  }
1409
1469
  arr.push(log);
1410
1470
  };
1411
1471
  const remove = (log) => {
1412
- const arr = map.get(log.vl);
1472
+ const key = valueKey(log.vl);
1473
+ const arr = map.get(key);
1413
1474
  if (!arr) return;
1414
1475
  const idx = arr.indexOf(log);
1415
1476
  if (idx >= 0) arr.splice(idx, 1);
1416
- if (arr.length === 0) map.delete(log.vl);
1477
+ if (arr.length === 0) map.delete(key);
1417
1478
  };
1418
1479
  const filtered = rollingFilter2(thread, { at: attr });
1419
1480
  for (const log of filtered.applogs) add(log);
@@ -1509,7 +1570,7 @@ var entityLinkIndex = memoizedFn(
1509
1570
  bByLink.clear();
1510
1571
  for (const log of applogs) processLog(log);
1511
1572
  }
1512
- const filtered = rollingFilter2(thread, { at: [attrA, attrB] });
1573
+ const filtered = rollingFilter2(thread, { at: anyOf(attrA, attrB) });
1513
1574
  buildFull(filtered.applogs);
1514
1575
  const value = { byA, byB };
1515
1576
  const result = new SubscribableImpl(
@@ -1641,6 +1702,7 @@ var ThreadInMemory = class _ThreadInMemory extends WriteableThread {
1641
1702
  super(name, applogs, filters);
1642
1703
  this._readOnly = _readOnly;
1643
1704
  }
1705
+ _readOnly;
1644
1706
  static empty(name) {
1645
1707
  return _ThreadInMemory.fromArray([], name ?? "empty in-memory", false);
1646
1708
  }
@@ -1767,6 +1829,7 @@ export {
1767
1829
  isEncryptedApplog,
1768
1830
  CIDTB,
1769
1831
  URL,
1832
+ JsonValueTB,
1770
1833
  AppLogNoCidTB,
1771
1834
  AppLogNoCidTBC,
1772
1835
  getApplogNoCidTypeErrors,
@@ -1789,18 +1852,10 @@ export {
1789
1852
  ensureValidCIDinstance,
1790
1853
  areCidsEqual,
1791
1854
  containsCid,
1792
- SubscribableImpl,
1793
- isArrayInitEvent,
1794
- SubscribableArrayImpl,
1795
- createDebugName,
1796
- createDebugNameObj,
1797
- prettifyThreadName,
1798
- isInitEvent,
1799
- Thread,
1800
- getLogsFromThread,
1801
- StaticThread,
1802
1855
  isoDateStrCompare,
1803
1856
  objEqualByKeys,
1857
+ valueEq,
1858
+ valueKey,
1804
1859
  compareApplogsByTs,
1805
1860
  compareApplogsByEnAt,
1806
1861
  isLaterByTsAndPv,
@@ -1823,6 +1878,16 @@ export {
1823
1878
  cyrb53hash,
1824
1879
  arraysContainSameElements,
1825
1880
  dateNowIso,
1881
+ SubscribableImpl,
1882
+ isArrayInitEvent,
1883
+ SubscribableArrayImpl,
1884
+ createDebugName,
1885
+ createDebugNameObj,
1886
+ prettifyThreadName,
1887
+ isInitEvent,
1888
+ Thread,
1889
+ getLogsFromThread,
1890
+ StaticThread,
1826
1891
  memoizedFn,
1827
1892
  refCountedMemoizedFn,
1828
1893
  MappedThread,
@@ -1837,6 +1902,9 @@ export {
1837
1902
  assertOnlyCurrent,
1838
1903
  asReadOnly,
1839
1904
  simpleApplogMapper,
1905
+ includes,
1906
+ includedIn,
1907
+ anyOf,
1840
1908
  applogsByEntity,
1841
1909
  applogsByAttrValue,
1842
1910
  entityLinkIndex,
@@ -1859,4 +1927,4 @@ export {
1859
1927
  withPvFrom,
1860
1928
  joinThreads
1861
1929
  };
1862
- //# sourceMappingURL=chunk-L5EEEGE6.js.map
1930
+ //# sourceMappingURL=chunk-2OXLPZQI.js.map