@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.
- 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/blockstore.js +2 -0
- package/dist/blockstore.js.map +1 -1
- package/dist/{chunk-L5EEEGE6.js → chunk-2OXLPZQI.js} +747 -679
- package/dist/chunk-2OXLPZQI.js.map +1 -0
- package/dist/{chunk-QZXKQCAY.js → chunk-2PJFLZRC.js} +7 -2
- package/dist/{chunk-QZXKQCAY.js.map → chunk-2PJFLZRC.js.map} +1 -1
- package/dist/chunk-64EJIJAJ.js +17 -0
- package/dist/chunk-64EJIJAJ.js.map +1 -0
- package/dist/chunk-7QEGHKR4.js +17 -0
- package/dist/chunk-7QEGHKR4.js.map +1 -0
- package/dist/{chunk-PD3C7XUM.js → chunk-EHO2BFFY.js} +2 -2
- package/dist/chunk-ICBK7NC4.js +27 -0
- package/dist/chunk-ICBK7NC4.js.map +1 -0
- package/dist/{chunk-CPSDKFBG.js → chunk-OKXRRWNS.js} +5 -14
- package/dist/chunk-OKXRRWNS.js.map +1 -0
- package/dist/{chunk-3WZVG277.js → chunk-Q4EMPWA3.js} +17 -9
- package/dist/chunk-Q4EMPWA3.js.map +1 -0
- package/dist/{chunk-J2FDHGOZ.js → chunk-VGIACGWX.js} +3 -3
- package/dist/{chunk-3JZMOEOD.js → chunk-WVW4YXB5.js} +2 -2
- package/dist/chunk-XF4DWOAE.js +25 -0
- package/dist/chunk-XF4DWOAE.js.map +1 -0
- package/dist/index.js +17 -9
- package/dist/ipfs/car.d.ts.map +1 -1
- package/dist/ipfs.js +4 -4
- package/dist/ipns/gateway-resolver.d.ts +21 -0
- package/dist/ipns/gateway-resolver.d.ts.map +1 -0
- package/dist/ipns/ipns-record.d.ts +28 -7
- package/dist/ipns/ipns-record.d.ts.map +1 -1
- package/dist/ipns/ipns-w3name.d.ts +15 -0
- package/dist/ipns/ipns-w3name.d.ts.map +1 -0
- package/dist/ipns/ipns-watcher.d.ts +190 -0
- package/dist/ipns/ipns-watcher.d.ts.map +1 -0
- package/dist/ipns.d.ts +3 -0
- package/dist/ipns.d.ts.map +1 -1
- package/dist/ipns.js +488 -8
- package/dist/ipns.js.map +1 -1
- package/dist/pubsub/snap-push.d.ts +2 -2
- 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/dist/viewmodel/adapters/arktype.d.ts +33 -0
- package/dist/viewmodel/adapters/arktype.d.ts.map +1 -0
- package/dist/viewmodel/adapters/arktype.js +7 -0
- package/dist/viewmodel/adapters/arktype.js.map +1 -0
- package/dist/viewmodel/adapters/typebox.d.ts +35 -0
- package/dist/viewmodel/adapters/typebox.d.ts.map +1 -0
- package/dist/viewmodel/adapters/typebox.js +7 -0
- package/dist/viewmodel/adapters/typebox.js.map +1 -0
- package/dist/viewmodel/adapters/typia.d.ts +40 -0
- package/dist/viewmodel/adapters/typia.d.ts.map +1 -0
- package/dist/viewmodel/adapters/typia.js +7 -0
- package/dist/viewmodel/adapters/typia.js.map +1 -0
- package/dist/viewmodel/adapters/zod.d.ts +30 -0
- package/dist/viewmodel/adapters/zod.d.ts.map +1 -0
- package/dist/viewmodel/adapters/zod.js +7 -0
- package/dist/viewmodel/adapters/zod.js.map +1 -0
- package/dist/viewmodel/builder.d.ts +40 -0
- package/dist/viewmodel/builder.d.ts.map +1 -0
- package/dist/viewmodel/examples/all-adapters.d.ts +26 -0
- package/dist/viewmodel/examples/all-adapters.d.ts.map +1 -0
- package/dist/viewmodel/factory.d.ts +38 -0
- package/dist/viewmodel/factory.d.ts.map +1 -0
- package/dist/viewmodel/index.d.ts +10 -0
- package/dist/viewmodel/index.d.ts.map +1 -0
- package/dist/viewmodel/index.js +313 -0
- package/dist/viewmodel/index.js.map +1 -0
- package/dist/viewmodel/schema-adapter.d.ts +16 -0
- package/dist/viewmodel/schema-adapter.d.ts.map +1 -0
- package/dist/viewmodel/types.d.ts +97 -0
- package/dist/viewmodel/types.d.ts.map +1 -0
- package/package.json +29 -3
- package/src/applog/applog-utils.ts +48 -4
- package/src/applog/datom-types.ts +24 -5
- package/src/applog/object-values.test.ts +106 -0
- package/src/ipfs/car.ts +8 -2
- package/src/ipns/gateway-resolver.ts +63 -0
- package/src/ipns/ipns-record.ts +68 -17
- package/src/ipns/ipns-w3name.ts +103 -0
- package/src/ipns/ipns-watcher.ts +607 -0
- package/src/ipns.ts +3 -0
- package/src/pubsub/snap-push.ts +8 -6
- 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/src/viewmodel/adapters/arktype.ts +44 -0
- package/src/viewmodel/adapters/typebox.ts +59 -0
- package/src/viewmodel/adapters/typia.ts +50 -0
- package/src/viewmodel/adapters/zod.ts +55 -0
- package/src/viewmodel/builder.ts +71 -0
- package/src/viewmodel/examples/all-adapters.ts +206 -0
- package/src/viewmodel/factory.ts +330 -0
- package/src/viewmodel/index.ts +22 -0
- package/src/viewmodel/schema-adapter.ts +27 -0
- package/src/viewmodel/types.ts +152 -0
- 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-PD3C7XUM.js.map → chunk-EHO2BFFY.js.map} +0 -0
- /package/dist/{chunk-J2FDHGOZ.js.map → chunk-VGIACGWX.js.map} +0 -0
- /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/
|
|
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
|
+
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
|
|
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
|
|
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
|
|
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({
|
|
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({
|
|
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:
|
|
357
|
-
//
|
|
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:
|
|
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
|
|
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
|
-
|
|
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
|
-
}
|
|
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
|
-
|
|
790
|
+
VERBOSE3("excluding app log", { key, val });
|
|
669
791
|
}
|
|
670
792
|
}
|
|
671
|
-
return
|
|
793
|
+
return { log: logWithout, cid };
|
|
672
794
|
}
|
|
673
|
-
function
|
|
674
|
-
|
|
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
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
|
|
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
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
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
|
|
706
|
-
|
|
707
|
-
|
|
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 (
|
|
710
|
-
|
|
711
|
-
|
|
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
|
-
|
|
715
|
-
|
|
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
|
|
720
|
-
|
|
721
|
-
|
|
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
|
|
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
|
-
}));
|
|
863
|
+
function ensureValidCIDinstance(cidOrStringA) {
|
|
864
|
+
return typeof cidOrStringA === "string" ? CID.parse(cidOrStringA) : typeof cidOrStringA.toV1 != "function" ? CID.decode(cidOrStringA.bytes) : cidOrStringA;
|
|
736
865
|
}
|
|
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;
|
|
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
|
|
839
|
-
|
|
840
|
-
return
|
|
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
|
-
|
|
1463
|
+
const key = valueKey(log.vl);
|
|
1464
|
+
let arr = map.get(key);
|
|
1405
1465
|
if (!arr) {
|
|
1406
1466
|
arr = [];
|
|
1407
|
-
map.set(
|
|
1467
|
+
map.set(key, arr);
|
|
1408
1468
|
}
|
|
1409
1469
|
arr.push(log);
|
|
1410
1470
|
};
|
|
1411
1471
|
const remove = (log) => {
|
|
1412
|
-
const
|
|
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(
|
|
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:
|
|
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-
|
|
1930
|
+
//# sourceMappingURL=chunk-2OXLPZQI.js.map
|