@wovin/core 0.2.0 → 0.2.2
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.
- package/dist/applog/applog-utils.d.ts +15 -0
- package/dist/applog/applog-utils.d.ts.map +1 -1
- package/dist/applog/datom-types.d.ts +63 -7
- package/dist/applog/datom-types.d.ts.map +1 -1
- package/dist/applog.js +7 -1
- package/dist/{chunk-CPSDKFBG.js → chunk-22WDFLXO.js} +5 -14
- package/dist/chunk-22WDFLXO.js.map +1 -0
- package/dist/{chunk-QZXKQCAY.js → chunk-3SUFNJEZ.js} +2 -2
- package/dist/{chunk-3WZVG277.js → chunk-6ALNRM3J.js} +5 -4
- package/dist/chunk-6ALNRM3J.js.map +1 -0
- package/dist/{chunk-3JZMOEOD.js → chunk-BLF5MAWU.js} +2 -2
- package/dist/{chunk-J2FDHGOZ.js → chunk-HUIQ54TT.js} +3 -3
- package/dist/{chunk-PD3C7XUM.js → chunk-OC6Z6CQW.js} +2 -2
- package/dist/{chunk-L5EEEGE6.js → chunk-SHUHRHOT.js} +738 -677
- package/dist/chunk-SHUHRHOT.js.map +1 -0
- package/dist/index.js +17 -9
- package/dist/ipfs.js +4 -4
- package/dist/pubsub/snap-push.d.ts.map +1 -1
- package/dist/pubsub.js +4 -4
- package/dist/query/basic.d.ts +3 -3
- package/dist/query/basic.d.ts.map +1 -1
- package/dist/query/entity-collection.d.ts.map +1 -1
- package/dist/query/matchers.d.ts +12 -1
- package/dist/query/matchers.d.ts.map +1 -1
- package/dist/query.js +7 -5
- package/dist/retrieve.js +4 -4
- package/dist/thread/indexes.d.ts +3 -2
- package/dist/thread/indexes.d.ts.map +1 -1
- package/dist/thread.js +1 -1
- package/package.json +1 -1
- package/src/applog/applog-utils.ts +48 -4
- package/src/applog/datom-types.ts +22 -3
- package/src/applog/object-values.test.ts +106 -0
- package/src/pubsub/snap-push.ts +2 -1
- package/src/query/entity-collection.ts +2 -1
- package/src/query/matchers.ts +23 -1
- package/src/thread/basic.ts +2 -2
- package/src/thread/indexes.ts +15 -9
- package/dist/chunk-3WZVG277.js.map +0 -1
- package/dist/chunk-CPSDKFBG.js.map +0 -1
- package/dist/chunk-L5EEEGE6.js.map +0 -1
- /package/dist/{chunk-QZXKQCAY.js.map → chunk-3SUFNJEZ.js.map} +0 -0
- /package/dist/{chunk-3JZMOEOD.js.map → chunk-BLF5MAWU.js.map} +0 -0
- /package/dist/{chunk-J2FDHGOZ.js.map → chunk-HUIQ54TT.js.map} +0 -0
- /package/dist/{chunk-PD3C7XUM.js.map → chunk-OC6Z6CQW.js.map} +0 -0
|
@@ -3,265 +3,643 @@ 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/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
23
|
-
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
|
|
77
|
-
|
|
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
|
-
|
|
80
|
-
|
|
105
|
+
if (result.length < logs.length) {
|
|
106
|
+
for (const log of logs) if (!visited.has(log.cid)) result.push(log);
|
|
81
107
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
|
140
|
-
|
|
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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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
|
-
|
|
199
|
+
newPattern[patternKey] = patternValue;
|
|
168
200
|
}
|
|
169
201
|
}
|
|
170
|
-
return
|
|
202
|
+
return [newPattern, variablesToFill];
|
|
171
203
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
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
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
return this.parents[0].insertRaw(appLogsToInsert);
|
|
233
|
+
if (field.charAt(0) === "!") {
|
|
234
|
+
return !result;
|
|
235
|
+
} else {
|
|
236
|
+
return result;
|
|
207
237
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
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
|
-
|
|
217
|
-
|
|
218
|
-
|
|
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
|
-
|
|
229
|
-
|
|
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
|
-
|
|
237
|
-
|
|
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
|
-
|
|
240
|
-
return
|
|
257
|
+
if (patternPart && typeof patternPart.has === "function") {
|
|
258
|
+
return patternPart.has(atomPart) ? context : null;
|
|
241
259
|
}
|
|
242
|
-
|
|
243
|
-
|
|
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
|
-
|
|
246
|
-
|
|
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
|
-
|
|
249
|
-
|
|
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
|
-
|
|
252
|
-
|
|
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
|
-
|
|
255
|
-
|
|
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
|
-
|
|
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
|
+
filters;
|
|
565
|
+
parents;
|
|
566
|
+
_derivedSubscribers = [];
|
|
567
|
+
_subscribers = [];
|
|
568
|
+
/** Monotonic counter incremented on every mutation. Used by memoizedFn to invalidate caches. */
|
|
569
|
+
_version = 0;
|
|
570
|
+
get readOnly() {
|
|
571
|
+
if (this.parents.length !== 1) return true;
|
|
572
|
+
return this.parents[0].readOnly;
|
|
573
|
+
}
|
|
574
|
+
insert(appLogsToInsert) {
|
|
575
|
+
if (this.readOnly) throw ERROR2(`[Thread] insert() called on read-only thread:`, this.nameAndSizeUntracked);
|
|
576
|
+
if (!this.parents) throw ERROR2(`[Thread] insert() called on non-writable thread without parents:`, this.nameAndSizeUntracked);
|
|
577
|
+
if (this.parents?.length !== 1) throw ERROR2(`[Thread] insert() called on thread with multiple parents:`, this.nameAndSizeUntracked);
|
|
578
|
+
return this.parents[0].insert(appLogsToInsert);
|
|
579
|
+
}
|
|
580
|
+
insertRaw(appLogsToInsert) {
|
|
581
|
+
if (this.readOnly) throw ERROR2(`[Thread] insertRaw() called on read-only thread:`, this.nameAndSizeUntracked);
|
|
582
|
+
if (!this.parents) throw ERROR2(`[Thread] insertRaw() called on non-writable thread without parents:`, this.nameAndSizeUntracked);
|
|
583
|
+
if (this.parents?.length !== 1) throw ERROR2(`[Thread] insertRaw() called on thread with multiple parents:`, this.nameAndSizeUntracked);
|
|
584
|
+
return this.parents[0].insertRaw(appLogsToInsert);
|
|
585
|
+
}
|
|
586
|
+
subscribe(callback, type) {
|
|
587
|
+
const list = type === "derived" ? this._derivedSubscribers : this._subscribers;
|
|
588
|
+
list.push(callback);
|
|
589
|
+
return () => {
|
|
590
|
+
const idx = list.indexOf(callback);
|
|
591
|
+
if (idx >= 0) list.splice(idx, 1);
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
notifySubscribers(event) {
|
|
595
|
+
this._version++;
|
|
596
|
+
DEBUG2(`[thread: ${this.name}] notifying`, this._derivedSubscribers.length, "derived +", this._subscribers.length, "subscribers of", { ...event, subs: this._subscribers });
|
|
597
|
+
const derived = [...this._derivedSubscribers];
|
|
598
|
+
for (const subscriber of derived) {
|
|
599
|
+
subscriber(event);
|
|
600
|
+
}
|
|
601
|
+
const subs = [...this._subscribers];
|
|
602
|
+
for (const subscriber of subs) {
|
|
603
|
+
subscriber(event);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
// ── SubscribableArray<Applog> ──
|
|
607
|
+
get items() {
|
|
608
|
+
return this._applogs;
|
|
609
|
+
}
|
|
610
|
+
dispose() {
|
|
611
|
+
this._derivedSubscribers.length = 0;
|
|
612
|
+
this._subscribers.length = 0;
|
|
613
|
+
}
|
|
614
|
+
get applogs() {
|
|
615
|
+
return this._applogs;
|
|
616
|
+
}
|
|
617
|
+
get applogsCids() {
|
|
618
|
+
return this._applogs.map((l) => l.cid);
|
|
619
|
+
}
|
|
620
|
+
get applogsCidSet() {
|
|
621
|
+
return new Set(this._applogs.map((l) => l.cid));
|
|
622
|
+
}
|
|
623
|
+
map(fn) {
|
|
624
|
+
return this.applogs.map(fn);
|
|
625
|
+
}
|
|
626
|
+
get findLast() {
|
|
627
|
+
return this.applogs.findLast.bind(this.applogs);
|
|
628
|
+
}
|
|
629
|
+
get findFirst() {
|
|
630
|
+
return this.applogs.find.bind(this.applogs);
|
|
631
|
+
}
|
|
632
|
+
get firstLog() {
|
|
633
|
+
return this.applogs[0];
|
|
634
|
+
}
|
|
635
|
+
get latestLog() {
|
|
258
636
|
return this.applogs[this.applogs.length - 1];
|
|
259
637
|
}
|
|
260
638
|
hasApplog(applog, byRef) {
|
|
261
639
|
if (byRef) {
|
|
262
640
|
return this.applogs.includes(applog);
|
|
263
641
|
} else {
|
|
264
|
-
if (!applog.cid) throw
|
|
642
|
+
if (!applog.cid) throw ERROR2(`[hasApplogs] applog without CID:`, applog);
|
|
265
643
|
return this.hasApplogCid(applog.cid);
|
|
266
644
|
}
|
|
267
645
|
}
|
|
@@ -275,7 +653,7 @@ var Thread = class {
|
|
|
275
653
|
return this.applogsByCid.get(cid.toString());
|
|
276
654
|
}
|
|
277
655
|
hasApplogWithDiffTs(applog) {
|
|
278
|
-
return this.applogs.find((existing) => existing.en === applog.en && existing.at === applog.at && existing.vl
|
|
656
|
+
return this.applogs.find((existing) => existing.en === applog.en && existing.at === applog.at && valueEq(existing.vl, applog.vl) && existing.ag === applog.ag);
|
|
279
657
|
}
|
|
280
658
|
// get stateHash() {
|
|
281
659
|
// blakeHasher.init()
|
|
@@ -329,7 +707,7 @@ import { Logger as Logger4 } from "besonders-logger";
|
|
|
329
707
|
// src/ipfs/ipfs-utils.ts
|
|
330
708
|
import * as dagJson from "@ipld/dag-json";
|
|
331
709
|
import { sha256 } from "@noble/hashes/sha2.js";
|
|
332
|
-
import { Logger as
|
|
710
|
+
import { Logger as Logger3 } from "besonders-logger";
|
|
333
711
|
import { CID, digest as Digest } from "multiformats";
|
|
334
712
|
import { encode as multiformatsEncode } from "multiformats/block";
|
|
335
713
|
|
|
@@ -348,13 +726,23 @@ var CIDTB = Type.String({ format: "CID" });
|
|
|
348
726
|
var isURL = /^http([s]?):\/\/.*\..*/;
|
|
349
727
|
FormatRegistry.Set("URL", (value) => !!value.match(isURL));
|
|
350
728
|
var URL = Type.String({ format: "URL" });
|
|
729
|
+
var JsonValueTB = Type.Recursive(
|
|
730
|
+
(This) => Type.Union([
|
|
731
|
+
Type.String(),
|
|
732
|
+
Type.Number(),
|
|
733
|
+
Type.Boolean(),
|
|
734
|
+
Type.Null(),
|
|
735
|
+
Type.Array(This),
|
|
736
|
+
Type.Record(Type.String(), This)
|
|
737
|
+
])
|
|
738
|
+
);
|
|
351
739
|
var AppLogNoCidTB = Type.Object({
|
|
352
740
|
en: EntityID,
|
|
353
741
|
// EntityID
|
|
354
742
|
at: Type.String(),
|
|
355
743
|
// Attribute
|
|
356
|
-
vl:
|
|
357
|
-
//
|
|
744
|
+
vl: JsonValueTB,
|
|
745
|
+
// ApplogValue (JSON-serializable: primitives, arrays, objects)
|
|
358
746
|
ts: Type.String(),
|
|
359
747
|
// Timestamp
|
|
360
748
|
ag: Type.String(),
|
|
@@ -378,466 +766,111 @@ var isValidApplog = AppLogTBC.Check.bind(AppLogTBC);
|
|
|
378
766
|
// src/ipfs/ipfs-utils.ts
|
|
379
767
|
import { base36 } from "multiformats/bases/base36";
|
|
380
768
|
import { sha256 as sha265Hasher } from "multiformats/hashes/sha2";
|
|
381
|
-
var { WARN:
|
|
769
|
+
var { WARN: WARN3, LOG: LOG3, DEBUG: DEBUG3, VERBOSE: VERBOSE3, ERROR: ERROR3 } = Logger3.setup(Logger3.INFO);
|
|
382
770
|
var MULTICODEC_IPNS_KEY = 114;
|
|
383
771
|
function prepareForPub(log, without = ["cid"]) {
|
|
384
|
-
if (!log) throw
|
|
772
|
+
if (!log) throw ERROR3("falsy log", log);
|
|
385
773
|
let cid = log.cid;
|
|
386
774
|
if (isEncryptedApplog(log)) {
|
|
387
775
|
if (!cid) cid = getCidSync(encodeBlock(log).bytes).toString();
|
|
388
|
-
|
|
389
|
-
return { log, cid };
|
|
390
|
-
}
|
|
391
|
-
const logWithout = {};
|
|
392
|
-
for (let [key, val] of Object.entries(log)) {
|
|
393
|
-
if (val === void 0) {
|
|
394
|
-
|
|
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
|
-
}
|
|
776
|
+
WARN3("preparing an encrypted applog - really?");
|
|
777
|
+
return { log, cid };
|
|
778
|
+
}
|
|
779
|
+
const logWithout = {};
|
|
780
|
+
for (let [key, val] of Object.entries(log)) {
|
|
781
|
+
if (val === void 0) {
|
|
782
|
+
WARN3(`log.${key} is undefined, which is not allowed - encoding as null`, log);
|
|
783
|
+
val = null;
|
|
784
|
+
}
|
|
785
|
+
if (!without.includes(key)) {
|
|
786
|
+
logWithout[key] = val;
|
|
667
787
|
} else {
|
|
668
|
-
|
|
788
|
+
VERBOSE3("excluding app log", { key, val });
|
|
669
789
|
}
|
|
670
790
|
}
|
|
671
|
-
return
|
|
791
|
+
return { log: logWithout, cid };
|
|
672
792
|
}
|
|
673
|
-
function
|
|
674
|
-
|
|
675
|
-
const bound = context[variable];
|
|
676
|
-
const match = matchPart(bound, triplePart, context);
|
|
677
|
-
return match;
|
|
678
|
-
}
|
|
679
|
-
return { ...context, [variable]: triplePart };
|
|
793
|
+
function encodeApplogAndGetCid(log) {
|
|
794
|
+
return getCidSync(encodeApplog(log).bytes);
|
|
680
795
|
}
|
|
681
|
-
function
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
|
|
796
|
+
function encodeApplog(log) {
|
|
797
|
+
return encodeBlock(prepareForPub(log)?.log);
|
|
798
|
+
}
|
|
799
|
+
function getCidSync(bytes) {
|
|
800
|
+
const hash = sha256(bytes);
|
|
801
|
+
const digest = Digest.create(sha265Hasher.code, hash);
|
|
802
|
+
const cid = CID.create(1, dagJson.code, digest);
|
|
803
|
+
VERBOSE3(`[getCidSync]`, { bytes, hash, digest, cid });
|
|
804
|
+
return cid;
|
|
805
|
+
}
|
|
806
|
+
function encodeBlock(jsonObject) {
|
|
807
|
+
DEBUG3("[encodeBlock]", jsonObject);
|
|
808
|
+
try {
|
|
809
|
+
const byteView = dagJson.encode(jsonObject);
|
|
810
|
+
return { bytes: byteView, cid: getCidSync(byteView) };
|
|
811
|
+
} catch (err) {
|
|
812
|
+
throw ERROR3("[encodeBlock] failed to encode:", jsonObject, err);
|
|
698
813
|
}
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
814
|
+
}
|
|
815
|
+
async function encodeBlockOriginal(jsonObject) {
|
|
816
|
+
const encoded = await multiformatsEncode({ value: jsonObject, codec: dagJson, hasher: sha265Hasher });
|
|
817
|
+
const syncVariant = encodeBlock(jsonObject);
|
|
818
|
+
if (syncVariant.cid.toString() !== encoded.cid.toString()) {
|
|
819
|
+
ERROR3(`[encodeBlockOriginal] sync cid mismatch`, { jsonObject, encoded, syncVariant });
|
|
703
820
|
}
|
|
821
|
+
return encoded;
|
|
704
822
|
}
|
|
705
|
-
function
|
|
706
|
-
|
|
707
|
-
|
|
823
|
+
function tryParseCID(cidString) {
|
|
824
|
+
let cid = null;
|
|
825
|
+
let errors = [];
|
|
826
|
+
try {
|
|
827
|
+
cid = CID.parse(cidString);
|
|
828
|
+
} catch (err) {
|
|
829
|
+
VERBOSE3(`[retrieveThread] couldn't parse pubID with default base`);
|
|
830
|
+
errors.push(err);
|
|
708
831
|
}
|
|
709
|
-
if (
|
|
710
|
-
|
|
711
|
-
|
|
832
|
+
if (!cid) {
|
|
833
|
+
try {
|
|
834
|
+
cid = CID.parse(cidString, base36);
|
|
835
|
+
} catch (err) {
|
|
836
|
+
VERBOSE3(`[retrieveThread] couldn't parse pubID with base36`);
|
|
837
|
+
errors.push(err);
|
|
712
838
|
}
|
|
713
839
|
}
|
|
714
|
-
|
|
715
|
-
|
|
840
|
+
return {
|
|
841
|
+
cid,
|
|
842
|
+
errors: cid ? null : errors,
|
|
843
|
+
// we only care about errors if we failed to parse
|
|
844
|
+
isIpns: cid && isIpnsKeyCid(cid)
|
|
845
|
+
};
|
|
846
|
+
}
|
|
847
|
+
function isIpnsKeyCid(cid) {
|
|
848
|
+
return cid.code === MULTICODEC_IPNS_KEY;
|
|
849
|
+
}
|
|
850
|
+
function cidToString(cid) {
|
|
851
|
+
if (cid.code == MULTICODEC_IPNS_KEY) {
|
|
852
|
+
return toIpnsString(cid);
|
|
853
|
+
} else {
|
|
854
|
+
return cid.toString();
|
|
716
855
|
}
|
|
717
|
-
return patternPart === atomPart ? context : null;
|
|
718
856
|
}
|
|
719
|
-
function
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
const patternValT = patternValue;
|
|
723
|
-
return matchPart(patternValT, applogValue, context2);
|
|
724
|
-
}, context);
|
|
857
|
+
function toIpnsString(cid) {
|
|
858
|
+
if (cid.code !== MULTICODEC_IPNS_KEY) throw ERROR3(`Not an IPNS cid (${cid.code}):`, cid.toString());
|
|
859
|
+
return cid.toString(base36);
|
|
725
860
|
}
|
|
726
|
-
function
|
|
727
|
-
return
|
|
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
|
-
}));
|
|
861
|
+
function ensureValidCIDinstance(cidOrStringA) {
|
|
862
|
+
return typeof cidOrStringA === "string" ? CID.parse(cidOrStringA) : typeof cidOrStringA.toV1 != "function" ? CID.decode(cidOrStringA.bytes) : cidOrStringA;
|
|
736
863
|
}
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
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;
|
|
864
|
+
function areCidsEqual(cidOrStringA, cidOrStringB) {
|
|
865
|
+
if (!cidOrStringA || !cidOrStringB) throw new Error(`[areCidsEqual] invalid params: ${cidOrStringA}, ${cidOrStringB}`);
|
|
866
|
+
if (cidOrStringA === cidOrStringB) return true;
|
|
867
|
+
const cidA = ensureValidCIDinstance(cidOrStringA);
|
|
868
|
+
const cidB = ensureValidCIDinstance(cidOrStringB);
|
|
869
|
+
return cidA.toV1().toString() === cidB.toV1().toString();
|
|
837
870
|
}
|
|
838
|
-
function
|
|
839
|
-
|
|
840
|
-
return
|
|
871
|
+
function containsCid(list, needle) {
|
|
872
|
+
if (list instanceof Set) return list.has(typeof needle === "string" ? needle : needle.toV1().toString());
|
|
873
|
+
return list.some((cidOrString) => areCidsEqual(cidOrString, needle));
|
|
841
874
|
}
|
|
842
875
|
|
|
843
876
|
// src/applog/applog-helpers.ts
|
|
@@ -1363,6 +1396,26 @@ var simpleApplogMapper = function simpleApplogMapper2(thread, logMapper, opts =
|
|
|
1363
1396
|
|
|
1364
1397
|
// src/thread/indexes.ts
|
|
1365
1398
|
import { Logger as Logger7 } from "besonders-logger";
|
|
1399
|
+
|
|
1400
|
+
// src/query/matchers.ts
|
|
1401
|
+
function includes(str) {
|
|
1402
|
+
return (vl) => vl?.includes?.(str);
|
|
1403
|
+
}
|
|
1404
|
+
function includedIn(arr) {
|
|
1405
|
+
return (vl) => arr?.includes?.(vl);
|
|
1406
|
+
}
|
|
1407
|
+
function anyOf(...vals) {
|
|
1408
|
+
for (const v of vals) {
|
|
1409
|
+
if (v !== null && typeof v === "object") {
|
|
1410
|
+
throw new Error(
|
|
1411
|
+
`[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)).`
|
|
1412
|
+
);
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
return new Set(vals);
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
// src/thread/indexes.ts
|
|
1366
1419
|
var { WARN: WARN7, LOG: LOG7, DEBUG: DEBUG7, VERBOSE: VERBOSE7, ERROR: ERROR7 } = Logger7.setup(Logger7.INFO);
|
|
1367
1420
|
var applogsByEntity = memoizedFn(
|
|
1368
1421
|
"applogsByEntity",
|
|
@@ -1401,19 +1454,21 @@ var applogsByAttrValue = memoizedFn(
|
|
|
1401
1454
|
function applogsByAttrValue2(thread, attr) {
|
|
1402
1455
|
const map = /* @__PURE__ */ new Map();
|
|
1403
1456
|
const add = (log) => {
|
|
1404
|
-
|
|
1457
|
+
const key = valueKey(log.vl);
|
|
1458
|
+
let arr = map.get(key);
|
|
1405
1459
|
if (!arr) {
|
|
1406
1460
|
arr = [];
|
|
1407
|
-
map.set(
|
|
1461
|
+
map.set(key, arr);
|
|
1408
1462
|
}
|
|
1409
1463
|
arr.push(log);
|
|
1410
1464
|
};
|
|
1411
1465
|
const remove = (log) => {
|
|
1412
|
-
const
|
|
1466
|
+
const key = valueKey(log.vl);
|
|
1467
|
+
const arr = map.get(key);
|
|
1413
1468
|
if (!arr) return;
|
|
1414
1469
|
const idx = arr.indexOf(log);
|
|
1415
1470
|
if (idx >= 0) arr.splice(idx, 1);
|
|
1416
|
-
if (arr.length === 0) map.delete(
|
|
1471
|
+
if (arr.length === 0) map.delete(key);
|
|
1417
1472
|
};
|
|
1418
1473
|
const filtered = rollingFilter2(thread, { at: attr });
|
|
1419
1474
|
for (const log of filtered.applogs) add(log);
|
|
@@ -1509,7 +1564,7 @@ var entityLinkIndex = memoizedFn(
|
|
|
1509
1564
|
bByLink.clear();
|
|
1510
1565
|
for (const log of applogs) processLog(log);
|
|
1511
1566
|
}
|
|
1512
|
-
const filtered = rollingFilter2(thread, { at:
|
|
1567
|
+
const filtered = rollingFilter2(thread, { at: anyOf(attrA, attrB) });
|
|
1513
1568
|
buildFull(filtered.applogs);
|
|
1514
1569
|
const value = { byA, byB };
|
|
1515
1570
|
const result = new SubscribableImpl(
|
|
@@ -1767,6 +1822,7 @@ export {
|
|
|
1767
1822
|
isEncryptedApplog,
|
|
1768
1823
|
CIDTB,
|
|
1769
1824
|
URL,
|
|
1825
|
+
JsonValueTB,
|
|
1770
1826
|
AppLogNoCidTB,
|
|
1771
1827
|
AppLogNoCidTBC,
|
|
1772
1828
|
getApplogNoCidTypeErrors,
|
|
@@ -1789,18 +1845,10 @@ export {
|
|
|
1789
1845
|
ensureValidCIDinstance,
|
|
1790
1846
|
areCidsEqual,
|
|
1791
1847
|
containsCid,
|
|
1792
|
-
SubscribableImpl,
|
|
1793
|
-
isArrayInitEvent,
|
|
1794
|
-
SubscribableArrayImpl,
|
|
1795
|
-
createDebugName,
|
|
1796
|
-
createDebugNameObj,
|
|
1797
|
-
prettifyThreadName,
|
|
1798
|
-
isInitEvent,
|
|
1799
|
-
Thread,
|
|
1800
|
-
getLogsFromThread,
|
|
1801
|
-
StaticThread,
|
|
1802
1848
|
isoDateStrCompare,
|
|
1803
1849
|
objEqualByKeys,
|
|
1850
|
+
valueEq,
|
|
1851
|
+
valueKey,
|
|
1804
1852
|
compareApplogsByTs,
|
|
1805
1853
|
compareApplogsByEnAt,
|
|
1806
1854
|
isLaterByTsAndPv,
|
|
@@ -1823,6 +1871,16 @@ export {
|
|
|
1823
1871
|
cyrb53hash,
|
|
1824
1872
|
arraysContainSameElements,
|
|
1825
1873
|
dateNowIso,
|
|
1874
|
+
SubscribableImpl,
|
|
1875
|
+
isArrayInitEvent,
|
|
1876
|
+
SubscribableArrayImpl,
|
|
1877
|
+
createDebugName,
|
|
1878
|
+
createDebugNameObj,
|
|
1879
|
+
prettifyThreadName,
|
|
1880
|
+
isInitEvent,
|
|
1881
|
+
Thread,
|
|
1882
|
+
getLogsFromThread,
|
|
1883
|
+
StaticThread,
|
|
1826
1884
|
memoizedFn,
|
|
1827
1885
|
refCountedMemoizedFn,
|
|
1828
1886
|
MappedThread,
|
|
@@ -1837,6 +1895,9 @@ export {
|
|
|
1837
1895
|
assertOnlyCurrent,
|
|
1838
1896
|
asReadOnly,
|
|
1839
1897
|
simpleApplogMapper,
|
|
1898
|
+
includes,
|
|
1899
|
+
includedIn,
|
|
1900
|
+
anyOf,
|
|
1840
1901
|
applogsByEntity,
|
|
1841
1902
|
applogsByAttrValue,
|
|
1842
1903
|
entityLinkIndex,
|
|
@@ -1859,4 +1920,4 @@ export {
|
|
|
1859
1920
|
withPvFrom,
|
|
1860
1921
|
joinThreads
|
|
1861
1922
|
};
|
|
1862
|
-
//# sourceMappingURL=chunk-
|
|
1923
|
+
//# sourceMappingURL=chunk-SHUHRHOT.js.map
|