@wovin/core 0.1.33 → 0.1.35
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.min.js +1 -1
- package/dist/{chunk-3PE2HQMQ.min.js → chunk-2Y2PYHGR.min.js} +2 -2
- package/dist/{chunk-2UDZBFG2.min.js → chunk-BRC7LSM6.min.js} +2 -2
- package/dist/{chunk-Y36HRPR3.min.js → chunk-COXXILXC.min.js} +8 -6
- package/dist/{chunk-Y36HRPR3.min.js.map → chunk-COXXILXC.min.js.map} +1 -1
- package/dist/{chunk-CDYQMETJ.min.js → chunk-GDX2OO7L.min.js} +22 -9
- package/dist/{chunk-CDYQMETJ.min.js.map → chunk-GDX2OO7L.min.js.map} +1 -1
- package/dist/{chunk-7HS5JGSX.min.js → chunk-H3VQJP56.min.js} +3 -3
- package/dist/{chunk-JGPJTVG4.min.js → chunk-KXMTKPF4.min.js} +2 -2
- package/dist/{chunk-U5TJTVXW.min.js → chunk-WXLCBTHX.min.js} +3 -3
- package/dist/index.min.js +7 -7
- package/dist/ipfs.min.js +4 -4
- package/dist/pubsub.min.js +4 -4
- package/dist/query/basic.d.ts.map +1 -1
- package/dist/query.min.js +3 -3
- package/dist/retrieve.min.js +4 -4
- package/dist/thread/basic.d.ts +2 -1
- package/dist/thread/basic.d.ts.map +1 -1
- package/dist/thread/mapped.d.ts +1 -1
- package/dist/thread/mapped.d.ts.map +1 -1
- package/dist/thread.min.js +1 -1
- package/package.json +1 -1
- /package/dist/{chunk-3PE2HQMQ.min.js.map → chunk-2Y2PYHGR.min.js.map} +0 -0
- /package/dist/{chunk-2UDZBFG2.min.js.map → chunk-BRC7LSM6.min.js.map} +0 -0
- /package/dist/{chunk-7HS5JGSX.min.js.map → chunk-H3VQJP56.min.js.map} +0 -0
- /package/dist/{chunk-JGPJTVG4.min.js.map → chunk-KXMTKPF4.min.js.map} +0 -0
- /package/dist/{chunk-U5TJTVXW.min.js.map → chunk-WXLCBTHX.min.js.map} +0 -0
package/dist/applog.min.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
createDebugName,
|
|
5
5
|
g,
|
|
6
6
|
observableArrayMap
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-GDX2OO7L.min.js";
|
|
8
8
|
import {
|
|
9
9
|
autorun,
|
|
10
10
|
comparer,
|
|
@@ -62,4 +62,4 @@ export {
|
|
|
62
62
|
includes,
|
|
63
63
|
includedIn
|
|
64
64
|
};
|
|
65
|
-
//# sourceMappingURL=chunk-
|
|
65
|
+
//# sourceMappingURL=chunk-2Y2PYHGR.min.js.map
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
cyrb53hash,
|
|
3
3
|
ensureTsPvAndFinalizeApplog,
|
|
4
4
|
g
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-GDX2OO7L.min.js";
|
|
6
6
|
|
|
7
7
|
// src/pubsub/pub-pull.ts
|
|
8
8
|
var { WARN, LOG, DEBUG, VERBOSE, ERROR } = g.setup(g.INFO);
|
|
@@ -37,4 +37,4 @@ export {
|
|
|
37
37
|
isSubscription,
|
|
38
38
|
agentToShortHash
|
|
39
39
|
};
|
|
40
|
-
//# sourceMappingURL=chunk-
|
|
40
|
+
//# sourceMappingURL=chunk-BRC7LSM6.min.js.map
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
rollingMapper,
|
|
17
17
|
sortApplogsByTs,
|
|
18
18
|
wrapper_default
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-GDX2OO7L.min.js";
|
|
20
20
|
import {
|
|
21
21
|
action,
|
|
22
22
|
autorun,
|
|
@@ -351,7 +351,7 @@ var agentsOfThread = computedFnDeepCompare("agentsOfThread", function agentsOfTh
|
|
|
351
351
|
LOG(`agentsOfThread<${thread.nameAndSizeUntracked}> processed event`, { event, mapped });
|
|
352
352
|
});
|
|
353
353
|
onEvent({ init: thread.applogs });
|
|
354
|
-
const unsubscribe = thread.subscribe(onEvent);
|
|
354
|
+
const unsubscribe = thread.subscribe(onEvent, "derived");
|
|
355
355
|
onBecomeUnobserved(mapped, unsubscribe);
|
|
356
356
|
return mapped;
|
|
357
357
|
});
|
|
@@ -464,9 +464,11 @@ function threadFromMaybeArray(threadOrLogs, name) {
|
|
|
464
464
|
function withTimeout(timeoutMilliseconds, func) {
|
|
465
465
|
if (globalQueryTimeoutTime) throw ERROR(`Nested timeout not supported`);
|
|
466
466
|
globalQueryTimeoutTime = performance.now() + timeoutMilliseconds;
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
467
|
+
try {
|
|
468
|
+
return func();
|
|
469
|
+
} finally {
|
|
470
|
+
globalQueryTimeoutTime = null;
|
|
471
|
+
}
|
|
470
472
|
}
|
|
471
473
|
function throwOnTimeout() {
|
|
472
474
|
if (globalQueryTimeoutTime == null) return;
|
|
@@ -507,4 +509,4 @@ export {
|
|
|
507
509
|
withTimeout,
|
|
508
510
|
throwOnTimeout
|
|
509
511
|
};
|
|
510
|
-
//# sourceMappingURL=chunk-
|
|
512
|
+
//# sourceMappingURL=chunk-COXXILXC.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/query/types.ts","../src/query/basic.ts"],"sourcesContent":["import { computed, makeObservable, untracked } from 'mobx'\nimport { joinThreads } from '../applog/applog-helpers'\nimport { SearchContext } from '../applog/datom-types'\nimport { observableArrayMap } from '../mobx/mobx-utils'\nimport type { Thread } from '../thread/basic'\nimport { ReadonlyObservableArray } from '../types/typescript-utils'\n\nexport class QueryNode {\n\tconstructor(\n\t\treadonly logsOfThisNode: Thread,\n\t\treadonly variables: SearchContext,\n\t\treadonly prevNode: QueryNode | null = null,\n\t) {\n\t\tmakeObservable(this, {\n\t\t\tthreadOfTrail: computed, // ? intuitively only put the ones here that felt expensive to compute (join)\n\t\t})\n\t}\n\tget record() {\n\t\treturn this.variables // alias for end-user consumption\n\t}\n\n\tget threadOfTrail() {\n\t\tif (!this.prevNode) return this.logsOfThisNode\n\t\treturn joinThreads([\n\t\t\tthis.logsOfThisNode,\n\t\t\tthis.prevNode.threadOfTrail,\n\t\t])\n\t}\n\tget trailLogs() {\n\t\treturn this.threadOfTrail.applogs\n\t}\n}\n/**\n * The result of a query (-step)\n */\nexport class QueryResult {\n\tconstructor(\n\t\tpublic nodes: ReadonlyObservableArray<QueryNode>,\n\t) {\n\t\tmakeObservable(this, {\n\t\t\tthreadOfAllTrails: computed, // ? intuitively only put the ones here that felt expensive to compute (join)\n\t\t\tsize: computed, // ... or cheap to cache\n\t\t\tisEmpty: computed,\n\t\t})\n\t}\n\n\tget size() {\n\t\treturn this.records.length\n\t}\n\tget isEmpty() {\n\t\treturn this.records.length === 0\n\t}\n\tget untrackedSize() {\n\t\treturn untracked(() => this.records.length)\n\t}\n\n\tget records() {\n\t\treturn observableArrayMap(() => this.nodes.map(({ variables }) => variables), { name: 'QueryResult.records' })\n\t}\n\tget leafNodeThread() {\n\t\treturn joinThreads(\n\t\t\tobservableArrayMap(() => this.nodes.map(({ logsOfThisNode: thread }) => thread), { name: 'QueryResult.leafNodeThread' }),\n\t\t)\n\t}\n\tget leafNodeLogSet() {\n\t\treturn observableArrayMap(() => this.nodes.map(({ logsOfThisNode: thread }) => thread.applogs), { name: 'QueryResult.leafNodeLogSet' })\n\t}\n\tget leafNodeLogs() {\n\t\treturn observableArrayMap(() => this.nodes.flatMap(({ logsOfThisNode: thread }) => thread.applogs), {\n\t\t\tname: 'QueryResult.leafNodeLogs',\n\t\t})\n\t}\n\t// get trailThreads() {\n\t// \treturn observableArrayMap(() => this.nodes.map(({ trailThread }) => trailThread))\n\t// }\n\tget threadOfAllTrails() {\n\t\treturn joinThreads(observableArrayMap(() => this.nodes.map(node => node.threadOfTrail), { name: 'QueryResult.threadOfAllTrails' }))\n\t}\n\tget thread() {\n\t\treturn this.threadOfAllTrails // alias\n\t}\n\tget allApplogs() {\n\t\treturn this.threadOfAllTrails.applogs // mostly for easy logging\n\t}\n}\n","import { AgentHash, Applog, ApplogValue, DatalogQueryPattern, EntityID, SearchContext, ValueOrMatcher } from '../applog/datom-types'\n\nimport { Logger } from 'besonders-logger'\nimport { action, autorun, comparer, computed, makeObservable, observable, onBecomeObserved, onBecomeUnobserved, toJS, untracked } from 'mobx'\n\nimport { isEmpty } from 'lodash-es'\nimport stringify from 'safe-stable-stringify'\nimport { resolveOrRemoveVariables, sortApplogsByTs } from '../applog/applog-utils'\nimport {\n\tapplogThreadComparer,\n\tcomputedFnDeepCompare,\n\tcomputedStructuralComparer,\n\tcreateDebugName,\n\tobservableArrayMap,\n\tobservableSetMap,\n\tqueryNodesComparer,\n} from '../mobx/mobx-utils'\nimport { isInitEvent, StaticThread, Thread, ThreadEvent } from '../thread/basic'\nimport { rollingFilter, rollingMapper, ThreadOnlyCurrent } from '../thread/filters'\nimport { MappedThread } from '../thread/mapped'\nimport { ThreadInMemory } from '../thread/writeable'\nimport { QueryNode, QueryResult } from './types'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO, { prefix: '[q]' }) // eslint-disable-line no-unused-vars\n\nlet globalQueryTimeoutTime = null\n\n// util.inspect.defaultOptions.depth = 5;\n\n// export interface QueryExecutorArguments {\n// db: Thread\n// // applogs: AppLog[]\n// nodes: SearchContextWithLog[]\n// }\n// export interface QueryExecutorResult {\n// // applogs: AppLog[]\n// nodes: SearchContextWithLog[]\n// }\n// export type QueryExecutor = (args: QueryExecutorArguments) => QueryExecutorResult\n\n/////////////\n// QUERIES //\n/////////////\n\n/**\n * Keep only the latest logs for each en&at (= last write wins)\n */\nexport const lastWriteWins = computedFnDeepCompare('lastWriteWins', function lastWriteWins(\n\tthread: Thread,\n\t{ inverseToOnlyReturnFirstLogs, tolerateAlreadyFiltered }: {\n\t\tinverseToOnlyReturnFirstLogs?: boolean\n\t\ttolerateAlreadyFiltered?: boolean\n\t} = {},\n): ThreadOnlyCurrent {\n\tVERBOSE(`lastWriteWins${inverseToOnlyReturnFirstLogs ? '.inversed' : ''} < ${thread.nameAndSizeUntracked} > initializing`)\n\t// if (thread.name.includes('lastWriteWins')) WARN(`thread already contains lastWriteWins:`, thread.name)\n\tif (thread.filters.includes('lastWriteWins')) {\n\t\tif (tolerateAlreadyFiltered) {\n\t\t\tDEBUG(`[lastWriteWins] already filtered, but tolerateAlreadyFiltered=true, so returning`)\n\t\t\treturn thread as ThreadOnlyCurrent\n\t\t}\n\t\tthrow ERROR(`thread already filtered lastWriteWins:`, thread.filters, { name: thread.name })\n\t}\n\n\tlet rollingMap: Map<string, Applog>\n\tconst mappedThread = rollingMapper(thread, function lastWriteWinsMapper(event, sourceThread) {\n\t\tconst isInitial = isInitEvent(event)\n\n\t\tlet newLogs: readonly Applog[]\n\t\tconst toAdd = [] as Applog[]\n\t\tconst toRemove = isInitial ? null : [] as Applog[]\n\t\tif (isInitial) {\n\t\t\trollingMap = new Map()\n\t\t\tnewLogs = event.init\n\t\t} else {\n\t\t\tnewLogs = event.added\n\t\t}\n\n\t\tlet tsCheck: string\n\t\tfor (\n\t\t\tlet i = inverseToOnlyReturnFirstLogs ? 0 : newLogs.length - 1;\n\t\t\tinverseToOnlyReturnFirstLogs ? i < newLogs.length : i >= 0;\n\t\t\tinverseToOnlyReturnFirstLogs ? i++ : i--\n\t\t) {\n\t\t\tconst log = newLogs[i]\n\t\t\tconst key = log.en + '|' + log.at // stringify([log.en, log.at]) - less efficient\n\n\t\t\t// TODO: use isoDateStrCompare ?\n\t\t\tif (tsCheck && (inverseToOnlyReturnFirstLogs ? tsCheck > log.ts : tsCheck < log.ts)) {\n\t\t\t\tthrow ERROR(`lastWriteWins.mapper logs not sorted:`, tsCheck, inverseToOnlyReturnFirstLogs ? '>' : '<', log.ts, {\n\t\t\t\t\tlog,\n\t\t\t\t\ti,\n\t\t\t\t\tnewLogs,\n\t\t\t\t\tinverseToOnlyReturnFirstLogs,\n\t\t\t\t})\n\t\t\t}\n\t\t\ttsCheck = log.ts\n\n\t\t\tconst existing = rollingMap.get(key)\n\t\t\tif (!existing || (inverseToOnlyReturnFirstLogs ? (existing.ts > log.ts) : (existing.ts < log.ts))) {\n\t\t\t\tif (existing && !isInitial) toRemove.push(existing)\n\t\t\t\ttoAdd.push(log)\n\t\t\t\trollingMap.set(key, log)\n\t\t\t}\n\t\t}\n\t\tsortApplogsByTs(toAdd) // HACK: find logical solution\n\t\tVERBOSE.isDisabled ||\n\t\t\tVERBOSE(\n\t\t\t\t`lastWriteWins${inverseToOnlyReturnFirstLogs ? '.inversed' : ''}<${thread.nameAndSizeUntracked}> mapped event`,\n\t\t\t\tisInitial ?\n\t\t\t\t\t{ ...Object.fromEntries(Object.entries(event).map(([k, v]) => [k, v?.length])), toAdd: toAdd.length, toRemove } :\n\t\t\t\t\t{ ...event, toAdd, toRemove },\n\t\t\t)\n\t\treturn isInitial ?\n\t\t\t{ init: toAdd }\n\t\t\t: { added: toAdd, removed: toRemove }\n\t}, { name: `lastWriteWins${inverseToOnlyReturnFirstLogs ? '.inversed' : ''}`, extraFilterName: 'lastWriteWins' })\n\tVERBOSE.isDisabled || autorun(() => {\n\t\tVERBOSE(`lastWriteWins<${thread.nameAndSizeUntracked}> filtered down to`, mappedThread.applogs.length) // using applogs.length, as size might not change, but we still want a log\n\t})\n\treturn mappedThread as ThreadOnlyCurrent\n\t// const filtered = observableArrayMap(() => {\n\t// VERBOSE(`lastWriteWins thread deps:`, getDependencyTree(thread.applogs), thread)\n\t// thread.applogs.forEach(applog => {\n\t// const key = stringify([applog.en, applog.at])\n\t// const existing = mapped.get(key)\n\t// if (!existing || existing.ts < applog.ts)\n\t// mapped.set(key, applog)\n\t// })\n\t// VERBOSE(`[lastWriteWins] mapped:`, mapped.size)\n\t// return Array.from(mapped.values())\n\t// }, { name: obsArrMapName })\n\t// VERBOSE(`lastWriteWins deps of filteredArr:`, getDependencyTree(filtered))\n\t// return new MappedThread(thread, filtered, `${thread.name} | lastWriteWins`)\n}, { equals: applogThreadComparer, argsDebugName: (thread) => createDebugName({ caller: 'lastWriteWins', thread }) })\n\n/**\n * Remove all applogs for entities that have an applog: { at: `isDeleted`, val: true }\n * ! WARNING: If not based on lastWriteWins, it will not respect un-deletions yet (isDeleted: false)\n */\nexport const withoutDeleted = computedFnDeepCompare('withoutDeleted', function withoutDeleted(\n\tthread: Thread,\n) {\n\tif (VERBOSE.isEnabled) VERBOSE(`withoutDeleted<${thread.nameAndSizeUntracked}>`)\n\t// if (thread.name.includes('withoutDeleted')) WARN(`thread already contains withoutDeleted:`, withoutDeleted)\n\tif (thread.filters.includes('withoutDeleted')) {\n\t\tthrow ERROR(`thread already filtered withoutDeleted:`, thread.filters, { name: thread.name })\n\t}\n\n\tconst deletionLogs = rollingFilter(\n\t\tthread, // TODO: handle un-delection\n\t\t{ at: ['isDeleted', 'relation/isDeleted', 'block/isDeleted'], vl: true },\n\t\t{ name: 'isDeleted' },\n\t)\n\tVERBOSE.isEnabled &&\n\t\tVERBOSE(\n\t\t\t`withoutDeleted<${thread.nameAndSizeUntracked}> deletionLogs:`,\n\t\t\tuntracked(function expensiveAssUntrackedVerboseFx() {\n\t\t\t\treturn [...deletionLogs.applogs]\n\t\t\t}),\n\t\t)\n\tconst obsArrMapName = createDebugName({ caller: 'allDeletedEntities', thread })\n\tconst deleted = observableSetMap(function observableSetMapForDeleted() {\n\t\treturn deletionLogs.map(log => log.en)\n\t}, { name: obsArrMapName })\n\t// if (VERBOSE.isEnabled) VERBOSE(`withoutDeleted<${db.nameAndSize}> deleted:`, untracked(() => [...deleted]))\n\tif (VERBOSE.isEnabled) {\n\t\tautorun(() => {\n\t\t\tVERBOSE(`withoutDeleted<${thread.nameAndSizeUntracked}> deleted:`, [...deleted])\n\t\t})\n\t}\n\n\treturn rollingFilter(thread, { '!en': deleted }, { name: `withoutDeleted`, extraFilterName: 'withoutDeleted' })\n}, { equals: applogThreadComparer })\n\n// export const filterStatic = computedFnDeepCompare('filterStatic', function filterStatic(\n// thread: Thread,\n// pattern: DatalogQueryPattern,\n// opts: { name?: string } = {},\n// ) {\n// VERBOSE(`filterStatic<${thread.nameAndSizeUntracked}>:`, pattern)\n// if (!Object.entries(pattern).length) throw new Error(`Pattern is empty`)\n// //TODO: deprecaate in favor of rollingFilter ?\n// return new Thread(thread, thread.applogs.filter(applog => {\n// for (const [field, patternValue] of Object.entries(pattern)) {\n// const applogValue = applog[field.startsWith('!') ? field.slice(1) : field]\n// if (!matchPartStatic(field, patternValue, applogValue))\n// return false\n// }\n// return true\n// }), `${thread.name} | ${opts.name || `filterStatic{${stringify(pattern)}}`}`)\n// }, { equals: applogThreadComparer })\n\nexport const query = computedFnDeepCompare('query', function query(\n\tthreadOrLogs: Thread | Applog[],\n\tpatternOrPatterns: DatalogQueryPattern | DatalogQueryPattern[],\n\tstartVariables: SearchContext = {},\n\topts: { debug?: boolean } = {},\n) {\n\tthrowOnTimeout()\n\tconst thread = threadFromMaybeArray(threadOrLogs)\n\tDEBUG(`query<${thread.nameAndSizeUntracked}>:`, patternOrPatterns)\n\tconst patterns = (Array.isArray(patternOrPatterns) ? patternOrPatterns : [patternOrPatterns]) as DatalogQueryPattern[]\n\n\tlet nodes: QueryResult | null\n\tif (patterns.length === 1) {\n\t\t// We are the first step, so start from scratch\n\t\tnodes = null\n\t} else {\n\t\t// Run the previous step(s) first (= recursion)\n\t\tconst pattersExceptLast = patterns.slice(0, -1)\n\t\t// recursively call this function to have partial queries cacheable\n\t\tnodes = query(thread, pattersExceptLast, startVariables, opts)\n\t}\n\tconst lastPattern = patterns[patterns.length - 1]\n\tconst stepResult = queryStep(thread, nodes, lastPattern, opts)\n\tVERBOSE.isDisabled || autorun(() => VERBOSE(`query result:`, toJS(stepResult)))\n\treturn stepResult\n}, {\n\tequals: queryNodesComparer,\n\targsDebugName: (thread, pattern, startVars) =>\n\t\tcreateDebugName({ caller: 'query', thread, args: startVars ? { pattern, startVars } : pattern }),\n})\n\nexport const queryStep = computedFnDeepCompare('queryStep', function queryStep(\n\tthread: Thread,\n\tnodeSet: QueryResult | null,\n\tpattern: DatalogQueryPattern,\n\t// variables: SearchContext = {},\n\topts: { debug?: boolean } = {},\n) {\n\tDEBUG(`queryStep<${thread.nameAndSizeUntracked}> with`, nodeSet?.untrackedSize ?? 'all', 'nodes, pattern:', pattern)\n\tif (!Object.entries(pattern).length) throw new Error(`Pattern is empty`)\n\n\tfunction doQuery(node: QueryNode | null) {\n\t\tconst [patternWithResolvedVars, variablesToFill] = resolveOrRemoveVariables(pattern, node?.variables ?? {})\n\t\tVERBOSE(`[queryStep.doQuery] patternWithoutVars: `, patternWithResolvedVars)\n\t\tconst applogsMatchingStatic = rollingFilter(thread, patternWithResolvedVars)\n\t\tconst varMapper = createObjMapper(variablesToFill)\n\t\tconst resultNodes = observableArrayMap(function queryStepDoStep() {\n\t\t\tconst newVarsAndTheirLog = applogsMatchingStatic.map(log => ({ log, vars: varMapper(log) }))\n\t\t\tif (VERBOSE.isEnabled) {\n\t\t\t\tVERBOSE(\n\t\t\t\t\t`[queryStep.doQuery] step node:`,\n\t\t\t\t\tnode?.variables,\n\t\t\t\t\t' =>',\n\t\t\t\t\tnewVarsAndTheirLog,\n\t\t\t\t\t'from:',\n\t\t\t\t\tuntracked(() => applogsMatchingStatic.applogs),\n\t\t\t\t)\n\t\t\t}\n\n\t\t\treturn newVarsAndTheirLog.map(({ log, vars }) => {\n\t\t\t\tconst nodeVars = Object.assign({}, node?.variables, vars)\n\t\t\t\treturn new QueryNode(\n\t\t\t\t\t// TODO: ? Make single result nodes reactive using MappedThread - only really relevant if a result had multiple logs (or different paths would lead to the same result?)\n\t\t\t\t\t// ThreadInMemory.fromArray(\n\t\t\t\t\tStaticThread.fromArray(\n\t\t\t\t\t\t[log],\n\t\t\t\t\t\tcreateDebugName({\n\t\t\t\t\t\t\tcaller: 'QueryNode',\n\t\t\t\t\t\t\tthread: applogsMatchingStatic,\n\t\t\t\t\t\t\tpattern: `${stringify(nodeVars)}@${stringify(patternWithResolvedVars)}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t\t// true,\n\t\t\t\t\t),\n\t\t\t\t\tnodeVars,\n\t\t\t\t\tnode,\n\t\t\t\t)\n\t\t\t})\n\t\t}, { name: createDebugName({ caller: 'doQuery.mapNodes', thread: applogsMatchingStatic, pattern }) })\n\t\tif (VERBOSE.isEnabled) autorun(() => VERBOSE(`[queryStep.doQuery] resultNodes:`, [...resultNodes]))\n\t\tif (opts.debug) {\n\t\t\tLOG(\n\t\t\t\t`[queryStep] step result:`,\n\t\t\t\tuntracked(() =>\n\t\t\t\t\tresultNodes.map(({ variables, logsOfThisNode: thread }) => ({\n\t\t\t\t\t\tvariables,\n\t\t\t\t\t\tthread, // : /* util.inspect( */ thread.applogs, /* , { showHidden: false, depth: null }) */\n\t\t\t\t\t}))\n\t\t\t\t),\n\t\t\t)\n\t\t}\n\t\treturn resultNodes\n\t}\n\tconst observableResultNodes = observableArrayMap(\n\t\tfunction queryStepGetResults() {\n\t\t\tDEBUG(`[queryStep] Running with ${nodeSet?.nodes?.length} input nodes:`)\n\t\t\tif (!nodeSet) {\n\t\t\t\t// first query step\n\t\t\t\treturn [...doQuery(null)] // HACK copy array bc otherwise the observableArrayMap doesn't seem to depend on the contents somehow\n\t\t\t} else {\n\t\t\t\t// subsequent query steps\n\t\t\t\treturn [...nodeSet.nodes.flatMap(doQuery)]\n\t\t\t}\n\t\t},\n\t\t{ name: createDebugName({ caller: 'queryStep', thread, pattern }) },\n\t)\n\n\tif (VERBOSE.isEnabled) autorun(() => VERBOSE(`[queryStep] observableResultNodes:`, [...observableResultNodes]))\n\treturn new QueryResult(observableResultNodes)\n}, { equals: queryNodesComparer, argsDebugName: (thread, _nodes, pattern) => createDebugName({ caller: 'queryStep', thread, pattern }) })\n\nexport const queryNot = computedFnDeepCompare('queryNot', function queryNot( // TODO: update old-style query\n\tthread: Thread,\n\tstartNodes: QueryResult,\n\tpatternOrPatterns: DatalogQueryPattern | DatalogQueryPattern[],\n\topts: { debug?: boolean } = {},\n) {\n\tlet nodes = startNodes.nodes\n\tDEBUG(`queryNot<${thread.nameAndSizeUntracked}> from: ${nodes.length} nodes`)\n\tconst patterns = (Array.isArray(patternOrPatterns) ? patternOrPatterns : [patternOrPatterns]) as DatalogQueryPattern[]\n\n\tfor (const pattern of patterns) {\n\t\tif (!Object.entries(patternOrPatterns).length) throw new Error(`Pattern is empty`)\n\t\tnodes = nodes.filter(function innerNodeFilter({ /* applogs, */ variables }) {\n\t\t\tconst [patternWithResolvedVars, _variablesToFill] = resolveOrRemoveVariables(pattern, variables ?? {})\n\t\t\tVERBOSE(`[queryNot] patternWithoutVars: `, patternWithResolvedVars)\n\t\t\tconst newApplogs = rollingFilter(thread, patternWithResolvedVars)\n\t\t\tVERBOSE(`[queryNot] step node:`, variables, ' =>', newApplogs.size, 'applogs')\n\t\t\tVERBOSE.isDisabled || VERBOSE(`[queryNot] step node:`, variables, ' => empty?', untracked(() => newApplogs.applogs))\n\n\t\t\tif (opts.debug) LOG(`[queryNot] node result:`, variables, '=>', newApplogs.applogs)\n\t\t\treturn newApplogs.isEmpty\n\t\t})\n\t}\n\treturn new QueryResult(nodes)\n}, { equals: queryNodesComparer, argsDebugName: (thread, nodes, pattern) => createDebugName({ caller: 'queryNot', thread, pattern }) })\n\n// export function or(queries: QueryExecutor[]) {\n// return tagged(\n// `or{${stringify(queries)} } `,\n// function orExecutor(args: QueryExecutorArguments) {\n// const { db, nodes: contexts } = args\n// VERBOSE('[or]', { queries, contexts })\n// let results = []\n// for (const query of queries) {\n// const res = query(args)\n// VERBOSE('[or] query', query, 'result =>', res)\n// results.push(...res.nodes)\n// }\n// return { contexts: results }\n// }\n// )\n// }\n\n// export type Tagged<T> = T & { tag: string }\n// export function tagged<T>(tag: string, thing: T): Tagged<T> {\n// const e = thing as (T & { tag: string })\n// e.tag = tag\n// return e\n// }\n\n//////////////////////\n// COMPOSED QUERIES //\n//////////////////////\n// createDebugName({ caller: 'useKidRelations' }, true)\nexport const filterAndMap = computedFnDeepCompare('filterAndMap', function filterAndMap<R>(\n\tthread: Thread,\n\tpattern: DatalogQueryPattern,\n\tmapper: (keyof Applog) | (Partial<{ [key in keyof Applog]: string }>) | ((applog: Applog) => R),\n) {\n\tDEBUG(`filterAndMap<${thread.nameAndSizeUntracked}>`, pattern)\n\n\tconst filtered = rollingFilter(thread, pattern)\n\tif (VERBOSE.isEnabled) {\n\t\tVERBOSE(`[filterAndMap] filtered:`, filtered.untrackedSize)\n\t\tautorun(() => VERBOSE(`[filterAndMap] filtered:`, filtered.applogs))\n\t}\n\n\tconst name = createDebugName({ thread, pattern, caller: 'filterAndMap' })\n\tconst mapped = observableArrayMap<ApplogValue | any>(() => mapThreadWith(filtered, mapper), { name }) // TODO typing:? Record<string, ApplogValue> ?\n\tVERBOSE.isDisabled || autorun(() => VERBOSE(`[filterAndMap] mapped:`, mapped))\n\treturn mapped\n}, { equals: comparer.structural, argsDebugName: (thread, pattern) => createDebugName({ caller: 'filterAndMap', thread, pattern }) })\n\nexport const queryAndMap = computedFnDeepCompare('queryAndMap', function queryAndMap<R>(\n\tthreadOrLogs: Thread | Applog[],\n\tpatternOrPatterns: Parameters<typeof query>[1],\n\tmapDef: string | (Partial<{ [key in keyof SearchContext]: string }>) | ((record: SearchContext) => R),\n\tvariables: SearchContext = {},\n) {\n\tconst thread = threadFromMaybeArray(threadOrLogs)\n\tDEBUG(`queryAndMap<${thread.nameAndSizeUntracked}>`, { patternOrPatterns, variables, map: mapDef })\n\tconst debugName = createDebugName({ thread, caller: 'queryAndMap' })\n\n\tconst queryResult = query(thread, patternOrPatterns)\n\tVERBOSE(`[queryAndMap] filtered count:`, queryResult.untrackedSize)\n\tconst mapped = observableArrayMap<ApplogValue | any>(\n\t\t() => mapQueryResultWith(queryResult, mapDef),\n\t\t{ name: debugName },\n\t)\n\tVERBOSE.isDisabled || autorun(() => VERBOSE(`[queryAndMap] result:`, toJS(mapped)))\n\treturn mapped\n}, { equals: comparer.structural, argsDebugName: (thread, pattern) => createDebugName({ caller: 'queryAndMap', thread, pattern }) })\n\nexport const queryEntity = computedFnDeepCompare('queryEntity', function queryEntity(\n\tthread: Thread,\n\tname: string,\n\tentityID: EntityID,\n\tattributes: readonly string[],\n) {\n\tDEBUG(`queryEntity<${thread.nameAndSizeUntracked}>`, entityID, name)\n\n\tconst filtered = rollingFilter(thread, { en: entityID, at: prefixAttrs(name, attributes) })\n\tVERBOSE(`queryEntity applogs:`, filtered.applogs)\n\treturn computed(() =>\n\t\tfiltered.isEmpty ? null : Object.fromEntries(\n\t\t\tfiltered.map(({ at, vl }) => [at.slice(name.length + 1), vl]),\n\t\t)\n\t)\n}, {\n\tequals: computedStructuralComparer,\n\targsDebugName: (thread, name, entityID) => createDebugName({ caller: 'queryEntity', thread, args: { name, entityID } }),\n})\n\nexport const agentsOfThread = computedFnDeepCompare('agentsOfThread', function agentsOfThread(\n\tthread: Thread,\n) {\n\tDEBUG(`agentsOfThread<${thread.nameAndSizeUntracked}>`)\n\n\tconst mapped = observable.map<string, number>()\n\tconst onEvent = action((event: ThreadEvent) => {\n\t\tfor (const log of (isInitEvent(event) ? event.init : event.added)) {\n\t\t\tconst prev = mapped.get(log.ag) ?? 0\n\t\t\tmapped.set(log.ag, prev + 1)\n\t\t}\n\t\tfor (const log of (!isInitEvent(event) && event.removed || [])) {\n\t\t\tconst prev = mapped.get(log.ag)\n\t\t\tif (!prev || prev < 1) throw ERROR(`[agentsOfThread] number is now negative`, { log, event, mapped, prev })\n\t\t\tmapped.set(log.ag, prev - 1)\n\t\t}\n\t\tLOG(`agentsOfThread<${thread.nameAndSizeUntracked}> processed event`, { event, mapped })\n\t})\n\n\tonEvent({ init: thread.applogs })\n\tconst unsubscribe = thread.subscribe(onEvent)\n\tonBecomeUnobserved(mapped, unsubscribe) // FIX: cleanup when UNobserved, not when observed\n\n\treturn mapped\n})\n\nexport const entityOverlap = computedFnDeepCompare('entityOverlap', function entityOverlapCount(\n\tthreadA: Thread,\n\tthreadB: Thread,\n) {\n\tLOG(`entityOverlap<${threadA.nameAndSizeUntracked}, ${threadB.nameAndSizeUntracked}>`)\n\n\treturn computed(() => {\n\t\tconst entitiesA = new Set(threadA.map(log => log.en))\n\t\tconst entitiesB = new Set(threadB.map(log => log.en))\n\t\treturn [...entitiesA].filter(en => entitiesB.has(en))\n\t})\n})\n\nexport const entityOverlapMap = function entityOverlapMap(\n\tthreadA: Thread,\n\tthreadB: Thread,\n\tthreadAName = 'incoming',\n\tthreadBName = 'current',\n) {\n\tconst useInferredVM = (en, thread: Thread) => en\n\tconst overlapping = entityOverlap(threadA, threadB).get()\n\tconst mapped = new Map()\n\toverlapping.forEach(eachEntityID => (\n\t\tmapped.set(eachEntityID, {\n\t\t\t[threadAName]: useInferredVM(eachEntityID, threadA),\n\t\t\t[threadBName]: useInferredVM(eachEntityID, threadB),\n\t\t})\n\t))\n}\n\nexport const entityOverlapCount = computedFnDeepCompare(\n\t'entityOverlapCount',\n\tfunction entityOverlapCount(threadA: Thread, threadB: Thread) {\n\t\treturn computed(() => entityOverlap(threadA, threadB).get().length)\n\t},\n)\nexport const querySingle = computedFnDeepCompare('querySingle', function querySingle(\n\tthreadOrLogs: Thread | Applog[],\n\tpatternOrPatterns: Parameters<typeof query>[1],\n\tvariables: SearchContext = {},\n) {\n\tconst result = query(threadOrLogs, patternOrPatterns, variables)\n\treturn computed(() => {\n\t\tif (result.isEmpty) return null\n\t\tif (result.size > 1) throw ERROR(`[querySingle] got`, result.size, `results:`, result)\n\t\tconst logsOfThisNode = result.nodes[0].logsOfThisNode\n\t\tif (logsOfThisNode.size != 1) throw ERROR(`[querySingle] single result, but got`, logsOfThisNode.size, `logs:`, logsOfThisNode.applogs)\n\t\treturn logsOfThisNode.applogs[0]\n\t})\n}, {\n\tequals: comparer.structural,\n\targsDebugName: (thread, pattern) => createDebugName({ caller: 'querySingle', thread, pattern }),\n})\n\nexport const querySingleAndMap = computedFnDeepCompare(\n\t'querySingleAndMap',\n\tfunction querySingleAndMap<MAP extends (keyof Applog | (Partial<{ [key in keyof Applog]: string }>))>(\n\t\tthreadOrLogs: Thread | Applog[],\n\t\tpatternOrPatterns: Parameters<typeof query>[1],\n\t\tmapDef: MAP,\n\t\tvariables: SearchContext = {},\n\t) {\n\t\tconst resultBox = querySingle(threadOrLogs, patternOrPatterns, variables)\n\t\treturn computed<ApplogValue | { [key in keyof MAP]: ApplogValue } | null>(() => {\n\t\t\tconst log = resultBox.get()\n\t\t\tif (!log) return undefined\n\t\t\tif (typeof mapDef === 'string') {\n\t\t\t\treturn log[mapDef as string]\n\t\t\t} else {\n\t\t\t\treturn createObjMapper(mapDef)(log)\n\t\t\t}\n\t\t})\n\t},\n\t{\n\t\tequals: comparer.structural,\n\t\targsDebugName: (thread, pattern) => createDebugName({ caller: 'querySingleAndMap', thread, pattern }),\n\t},\n)\n/////////////\n// HELPERS //\n/////////////\n\nexport const mapThreadWith = function filterAndMapGetterFx<R>(\n\tthread: Thread,\n\tmapDef: (keyof Applog) | (Partial<{ [key in keyof Applog]: string }>) | ((applog: Applog) => R),\n) {\n\tif (typeof mapDef === 'function') {\n\t\treturn thread.map(mapDef)\n\t} else if (typeof mapDef === 'string') {\n\t\treturn thread.map(log => log[mapDef])\n\t} else {\n\t\treturn thread.map(createObjMapper(mapDef))\n\t}\n}\nexport const mapQueryResultWith = function filterAndMapGetterFx<R>(\n\tqueryResult: QueryResult,\n\tmapDef: string | (Partial<{ [key in keyof SearchContext]: string }>) | ((record: SearchContext) => R),\n) {\n\tif (typeof mapDef === 'function') {\n\t\treturn queryResult.records.map(mapDef)\n\t} else if (typeof mapDef === 'string') {\n\t\treturn queryResult.nodes.map((node) => {\n\t\t\tif (!Object.hasOwn(node.record, mapDef)) {\n\t\t\t\tif (node.logsOfThisNode.size !== 1) {\n\t\t\t\t\tthrow ERROR(`not sure what to map (it's not a var and a result node log count of ${node.logsOfThisNode.size})`)\n\t\t\t\t}\n\t\t\t\treturn node.logsOfThisNode.firstLog[mapDef]\n\t\t\t}\n\t\t\treturn node.record[mapDef]\n\t\t})\n\t} else {\n\t\treturn queryResult.nodes.map((node) => {\n\t\t\treturn createObjMapper(mapDef)(queryResult)\n\t\t})\n\t}\n}\n/**\n * Map Applog to custom named record, e.g.:\n * { en: 'movieID', vl: 'movieName' }\n * will map the applog to { movieID: .., movieName: .. }\n */\nexport function createObjMapper<FROM extends string, TO extends string>(applogFieldMap: Partial<{ [key in FROM]: TO }>) {\n\treturn (applog: { [key in FROM]: any }) => {\n\t\treturn Object.entries(applogFieldMap).reduce((acc, [key, value]) => {\n\t\t\tacc[value as TO] = applog[key]\n\t\t\treturn acc\n\t\t}, {} as Partial<{ [key in TO]: ApplogValue }>)\n\t}\n}\n\nexport function startsWith(str: string) {\n\treturn (value) => value.startsWith(str)\n}\n\nexport function prefixAttrs(prefix: string, attrs: readonly string[]) {\n\treturn attrs.map(at => prefixAt(prefix, at))\n}\nexport function prefixAt(prefix: string, attr: string) {\n\treturn `${prefix}/${attr}`\n}\nexport function threadFromMaybeArray(threadOrLogs: Thread | Applog[], name?: string) {\n\tif (!Array.isArray(threadOrLogs)) {\n\t\treturn threadOrLogs\n\t}\n\treturn ThreadInMemory.fromArray(threadOrLogs, name || `threadFromArray[${threadOrLogs.length}]`, true)\n}\nexport function withTimeout<R>(timeoutMilliseconds: number, func: () => R) {\n\tif (globalQueryTimeoutTime) throw ERROR(`Nested timeout not supported`)\n\tglobalQueryTimeoutTime = performance.now() + timeoutMilliseconds\n\tconst result = func()\n\n\tglobalQueryTimeoutTime = null\n\treturn result\n}\nexport function throwOnTimeout() {\n\tif (globalQueryTimeoutTime == null) return\n\tif (performance.now() >= globalQueryTimeoutTime) {\n\t\tthrow new QueryTimeoutError(globalQueryTimeoutTime)\n\t}\n}\nclass QueryTimeoutError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message)\n\t}\n}\n"],"mappings":"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","names":["lastWriteWins","withoutDeleted","query","queryStep","thread","queryNot","filterAndMap","queryAndMap","queryEntity","agentsOfThread","entityOverlapMap","entityOverlapCount","querySingle","querySingleAndMap","filterAndMapGetterFx"]}
|
|
1
|
+
{"version":3,"sources":["../src/query/types.ts","../src/query/basic.ts"],"sourcesContent":["import { computed, makeObservable, untracked } from 'mobx'\nimport { joinThreads } from '../applog/applog-helpers'\nimport { SearchContext } from '../applog/datom-types'\nimport { observableArrayMap } from '../mobx/mobx-utils'\nimport type { Thread } from '../thread/basic'\nimport { ReadonlyObservableArray } from '../types/typescript-utils'\n\nexport class QueryNode {\n\tconstructor(\n\t\treadonly logsOfThisNode: Thread,\n\t\treadonly variables: SearchContext,\n\t\treadonly prevNode: QueryNode | null = null,\n\t) {\n\t\tmakeObservable(this, {\n\t\t\tthreadOfTrail: computed, // ? intuitively only put the ones here that felt expensive to compute (join)\n\t\t})\n\t}\n\tget record() {\n\t\treturn this.variables // alias for end-user consumption\n\t}\n\n\tget threadOfTrail() {\n\t\tif (!this.prevNode) return this.logsOfThisNode\n\t\treturn joinThreads([\n\t\t\tthis.logsOfThisNode,\n\t\t\tthis.prevNode.threadOfTrail,\n\t\t])\n\t}\n\tget trailLogs() {\n\t\treturn this.threadOfTrail.applogs\n\t}\n}\n/**\n * The result of a query (-step)\n */\nexport class QueryResult {\n\tconstructor(\n\t\tpublic nodes: ReadonlyObservableArray<QueryNode>,\n\t) {\n\t\tmakeObservable(this, {\n\t\t\tthreadOfAllTrails: computed, // ? intuitively only put the ones here that felt expensive to compute (join)\n\t\t\tsize: computed, // ... or cheap to cache\n\t\t\tisEmpty: computed,\n\t\t})\n\t}\n\n\tget size() {\n\t\treturn this.records.length\n\t}\n\tget isEmpty() {\n\t\treturn this.records.length === 0\n\t}\n\tget untrackedSize() {\n\t\treturn untracked(() => this.records.length)\n\t}\n\n\tget records() {\n\t\treturn observableArrayMap(() => this.nodes.map(({ variables }) => variables), { name: 'QueryResult.records' })\n\t}\n\tget leafNodeThread() {\n\t\treturn joinThreads(\n\t\t\tobservableArrayMap(() => this.nodes.map(({ logsOfThisNode: thread }) => thread), { name: 'QueryResult.leafNodeThread' }),\n\t\t)\n\t}\n\tget leafNodeLogSet() {\n\t\treturn observableArrayMap(() => this.nodes.map(({ logsOfThisNode: thread }) => thread.applogs), { name: 'QueryResult.leafNodeLogSet' })\n\t}\n\tget leafNodeLogs() {\n\t\treturn observableArrayMap(() => this.nodes.flatMap(({ logsOfThisNode: thread }) => thread.applogs), {\n\t\t\tname: 'QueryResult.leafNodeLogs',\n\t\t})\n\t}\n\t// get trailThreads() {\n\t// \treturn observableArrayMap(() => this.nodes.map(({ trailThread }) => trailThread))\n\t// }\n\tget threadOfAllTrails() {\n\t\treturn joinThreads(observableArrayMap(() => this.nodes.map(node => node.threadOfTrail), { name: 'QueryResult.threadOfAllTrails' }))\n\t}\n\tget thread() {\n\t\treturn this.threadOfAllTrails // alias\n\t}\n\tget allApplogs() {\n\t\treturn this.threadOfAllTrails.applogs // mostly for easy logging\n\t}\n}\n","import { AgentHash, Applog, ApplogValue, DatalogQueryPattern, EntityID, SearchContext, ValueOrMatcher } from '../applog/datom-types'\n\nimport { Logger } from 'besonders-logger'\nimport { action, autorun, comparer, computed, makeObservable, observable, onBecomeObserved, onBecomeUnobserved, toJS, untracked } from 'mobx'\n\nimport { isEmpty } from 'lodash-es'\nimport stringify from 'safe-stable-stringify'\nimport { resolveOrRemoveVariables, sortApplogsByTs } from '../applog/applog-utils'\nimport {\n\tapplogThreadComparer,\n\tcomputedFnDeepCompare,\n\tcomputedStructuralComparer,\n\tcreateDebugName,\n\tobservableArrayMap,\n\tobservableSetMap,\n\tqueryNodesComparer,\n} from '../mobx/mobx-utils'\nimport { isInitEvent, StaticThread, Thread, ThreadEvent } from '../thread/basic'\nimport { rollingFilter, rollingMapper, ThreadOnlyCurrent } from '../thread/filters'\nimport { MappedThread } from '../thread/mapped'\nimport { ThreadInMemory } from '../thread/writeable'\nimport { QueryNode, QueryResult } from './types'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO, { prefix: '[q]' }) // eslint-disable-line no-unused-vars\n\nlet globalQueryTimeoutTime = null\n\n// util.inspect.defaultOptions.depth = 5;\n\n// export interface QueryExecutorArguments {\n// db: Thread\n// // applogs: AppLog[]\n// nodes: SearchContextWithLog[]\n// }\n// export interface QueryExecutorResult {\n// // applogs: AppLog[]\n// nodes: SearchContextWithLog[]\n// }\n// export type QueryExecutor = (args: QueryExecutorArguments) => QueryExecutorResult\n\n/////////////\n// QUERIES //\n/////////////\n\n/**\n * Keep only the latest logs for each en&at (= last write wins)\n */\nexport const lastWriteWins = computedFnDeepCompare('lastWriteWins', function lastWriteWins(\n\tthread: Thread,\n\t{ inverseToOnlyReturnFirstLogs, tolerateAlreadyFiltered }: {\n\t\tinverseToOnlyReturnFirstLogs?: boolean\n\t\ttolerateAlreadyFiltered?: boolean\n\t} = {},\n): ThreadOnlyCurrent {\n\tVERBOSE(`lastWriteWins${inverseToOnlyReturnFirstLogs ? '.inversed' : ''} < ${thread.nameAndSizeUntracked} > initializing`)\n\t// if (thread.name.includes('lastWriteWins')) WARN(`thread already contains lastWriteWins:`, thread.name)\n\tif (thread.filters.includes('lastWriteWins')) {\n\t\tif (tolerateAlreadyFiltered) {\n\t\t\tDEBUG(`[lastWriteWins] already filtered, but tolerateAlreadyFiltered=true, so returning`)\n\t\t\treturn thread as ThreadOnlyCurrent\n\t\t}\n\t\tthrow ERROR(`thread already filtered lastWriteWins:`, thread.filters, { name: thread.name })\n\t}\n\n\tlet rollingMap: Map<string, Applog>\n\tconst mappedThread = rollingMapper(thread, function lastWriteWinsMapper(event, sourceThread) {\n\t\tconst isInitial = isInitEvent(event)\n\n\t\tlet newLogs: readonly Applog[]\n\t\tconst toAdd = [] as Applog[]\n\t\tconst toRemove = isInitial ? null : [] as Applog[]\n\t\tif (isInitial) {\n\t\t\trollingMap = new Map()\n\t\t\tnewLogs = event.init\n\t\t} else {\n\t\t\tnewLogs = event.added\n\t\t}\n\n\t\tlet tsCheck: string\n\t\tfor (\n\t\t\tlet i = inverseToOnlyReturnFirstLogs ? 0 : newLogs.length - 1;\n\t\t\tinverseToOnlyReturnFirstLogs ? i < newLogs.length : i >= 0;\n\t\t\tinverseToOnlyReturnFirstLogs ? i++ : i--\n\t\t) {\n\t\t\tconst log = newLogs[i]\n\t\t\tconst key = log.en + '|' + log.at // stringify([log.en, log.at]) - less efficient\n\n\t\t\t// TODO: use isoDateStrCompare ?\n\t\t\tif (tsCheck && (inverseToOnlyReturnFirstLogs ? tsCheck > log.ts : tsCheck < log.ts)) {\n\t\t\t\tthrow ERROR(`lastWriteWins.mapper logs not sorted:`, tsCheck, inverseToOnlyReturnFirstLogs ? '>' : '<', log.ts, {\n\t\t\t\t\tlog,\n\t\t\t\t\ti,\n\t\t\t\t\tnewLogs,\n\t\t\t\t\tinverseToOnlyReturnFirstLogs,\n\t\t\t\t})\n\t\t\t}\n\t\t\ttsCheck = log.ts\n\n\t\t\tconst existing = rollingMap.get(key)\n\t\t\tif (!existing || (inverseToOnlyReturnFirstLogs ? (existing.ts > log.ts) : (existing.ts < log.ts))) {\n\t\t\t\tif (existing && !isInitial) toRemove.push(existing)\n\t\t\t\ttoAdd.push(log)\n\t\t\t\trollingMap.set(key, log)\n\t\t\t}\n\t\t}\n\t\tsortApplogsByTs(toAdd) // HACK: find logical solution\n\t\tVERBOSE.isDisabled ||\n\t\t\tVERBOSE(\n\t\t\t\t`lastWriteWins${inverseToOnlyReturnFirstLogs ? '.inversed' : ''}<${thread.nameAndSizeUntracked}> mapped event`,\n\t\t\t\tisInitial ?\n\t\t\t\t\t{ ...Object.fromEntries(Object.entries(event).map(([k, v]) => [k, v?.length])), toAdd: toAdd.length, toRemove } :\n\t\t\t\t\t{ ...event, toAdd, toRemove },\n\t\t\t)\n\t\treturn isInitial ?\n\t\t\t{ init: toAdd }\n\t\t\t: { added: toAdd, removed: toRemove }\n\t}, { name: `lastWriteWins${inverseToOnlyReturnFirstLogs ? '.inversed' : ''}`, extraFilterName: 'lastWriteWins' })\n\tVERBOSE.isDisabled || autorun(() => {\n\t\tVERBOSE(`lastWriteWins<${thread.nameAndSizeUntracked}> filtered down to`, mappedThread.applogs.length) // using applogs.length, as size might not change, but we still want a log\n\t})\n\treturn mappedThread as ThreadOnlyCurrent\n\t// const filtered = observableArrayMap(() => {\n\t// VERBOSE(`lastWriteWins thread deps:`, getDependencyTree(thread.applogs), thread)\n\t// thread.applogs.forEach(applog => {\n\t// const key = stringify([applog.en, applog.at])\n\t// const existing = mapped.get(key)\n\t// if (!existing || existing.ts < applog.ts)\n\t// mapped.set(key, applog)\n\t// })\n\t// VERBOSE(`[lastWriteWins] mapped:`, mapped.size)\n\t// return Array.from(mapped.values())\n\t// }, { name: obsArrMapName })\n\t// VERBOSE(`lastWriteWins deps of filteredArr:`, getDependencyTree(filtered))\n\t// return new MappedThread(thread, filtered, `${thread.name} | lastWriteWins`)\n}, { equals: applogThreadComparer, argsDebugName: (thread) => createDebugName({ caller: 'lastWriteWins', thread }) })\n\n/**\n * Remove all applogs for entities that have an applog: { at: `isDeleted`, val: true }\n * ! WARNING: If not based on lastWriteWins, it will not respect un-deletions yet (isDeleted: false)\n */\nexport const withoutDeleted = computedFnDeepCompare('withoutDeleted', function withoutDeleted(\n\tthread: Thread,\n) {\n\tif (VERBOSE.isEnabled) VERBOSE(`withoutDeleted<${thread.nameAndSizeUntracked}>`)\n\t// if (thread.name.includes('withoutDeleted')) WARN(`thread already contains withoutDeleted:`, withoutDeleted)\n\tif (thread.filters.includes('withoutDeleted')) {\n\t\tthrow ERROR(`thread already filtered withoutDeleted:`, thread.filters, { name: thread.name })\n\t}\n\n\tconst deletionLogs = rollingFilter(\n\t\tthread, // TODO: handle un-delection\n\t\t{ at: ['isDeleted', 'relation/isDeleted', 'block/isDeleted'], vl: true },\n\t\t{ name: 'isDeleted' },\n\t)\n\tVERBOSE.isEnabled &&\n\t\tVERBOSE(\n\t\t\t`withoutDeleted<${thread.nameAndSizeUntracked}> deletionLogs:`,\n\t\t\tuntracked(function expensiveAssUntrackedVerboseFx() {\n\t\t\t\treturn [...deletionLogs.applogs]\n\t\t\t}),\n\t\t)\n\tconst obsArrMapName = createDebugName({ caller: 'allDeletedEntities', thread })\n\tconst deleted = observableSetMap(function observableSetMapForDeleted() {\n\t\treturn deletionLogs.map(log => log.en)\n\t}, { name: obsArrMapName })\n\t// if (VERBOSE.isEnabled) VERBOSE(`withoutDeleted<${db.nameAndSize}> deleted:`, untracked(() => [...deleted]))\n\tif (VERBOSE.isEnabled) {\n\t\tautorun(() => {\n\t\t\tVERBOSE(`withoutDeleted<${thread.nameAndSizeUntracked}> deleted:`, [...deleted])\n\t\t})\n\t}\n\n\treturn rollingFilter(thread, { '!en': deleted }, { name: `withoutDeleted`, extraFilterName: 'withoutDeleted' })\n}, { equals: applogThreadComparer })\n\n// export const filterStatic = computedFnDeepCompare('filterStatic', function filterStatic(\n// thread: Thread,\n// pattern: DatalogQueryPattern,\n// opts: { name?: string } = {},\n// ) {\n// VERBOSE(`filterStatic<${thread.nameAndSizeUntracked}>:`, pattern)\n// if (!Object.entries(pattern).length) throw new Error(`Pattern is empty`)\n// //TODO: deprecaate in favor of rollingFilter ?\n// return new Thread(thread, thread.applogs.filter(applog => {\n// for (const [field, patternValue] of Object.entries(pattern)) {\n// const applogValue = applog[field.startsWith('!') ? field.slice(1) : field]\n// if (!matchPartStatic(field, patternValue, applogValue))\n// return false\n// }\n// return true\n// }), `${thread.name} | ${opts.name || `filterStatic{${stringify(pattern)}}`}`)\n// }, { equals: applogThreadComparer })\n\nexport const query = computedFnDeepCompare('query', function query(\n\tthreadOrLogs: Thread | Applog[],\n\tpatternOrPatterns: DatalogQueryPattern | DatalogQueryPattern[],\n\tstartVariables: SearchContext = {},\n\topts: { debug?: boolean } = {},\n) {\n\tthrowOnTimeout()\n\tconst thread = threadFromMaybeArray(threadOrLogs)\n\tDEBUG(`query<${thread.nameAndSizeUntracked}>:`, patternOrPatterns)\n\tconst patterns = (Array.isArray(patternOrPatterns) ? patternOrPatterns : [patternOrPatterns]) as DatalogQueryPattern[]\n\n\tlet nodes: QueryResult | null\n\tif (patterns.length === 1) {\n\t\t// We are the first step, so start from scratch\n\t\tnodes = null\n\t} else {\n\t\t// Run the previous step(s) first (= recursion)\n\t\tconst pattersExceptLast = patterns.slice(0, -1)\n\t\t// recursively call this function to have partial queries cacheable\n\t\tnodes = query(thread, pattersExceptLast, startVariables, opts)\n\t}\n\tconst lastPattern = patterns[patterns.length - 1]\n\tconst stepResult = queryStep(thread, nodes, lastPattern, opts)\n\tVERBOSE.isDisabled || autorun(() => VERBOSE(`query result:`, toJS(stepResult)))\n\treturn stepResult\n}, {\n\tequals: queryNodesComparer,\n\targsDebugName: (thread, pattern, startVars) =>\n\t\tcreateDebugName({ caller: 'query', thread, args: startVars ? { pattern, startVars } : pattern }),\n})\n\nexport const queryStep = computedFnDeepCompare('queryStep', function queryStep(\n\tthread: Thread,\n\tnodeSet: QueryResult | null,\n\tpattern: DatalogQueryPattern,\n\t// variables: SearchContext = {},\n\topts: { debug?: boolean } = {},\n) {\n\tDEBUG(`queryStep<${thread.nameAndSizeUntracked}> with`, nodeSet?.untrackedSize ?? 'all', 'nodes, pattern:', pattern)\n\tif (!Object.entries(pattern).length) throw new Error(`Pattern is empty`)\n\n\tfunction doQuery(node: QueryNode | null) {\n\t\tconst [patternWithResolvedVars, variablesToFill] = resolveOrRemoveVariables(pattern, node?.variables ?? {})\n\t\tVERBOSE(`[queryStep.doQuery] patternWithoutVars: `, patternWithResolvedVars)\n\t\tconst applogsMatchingStatic = rollingFilter(thread, patternWithResolvedVars)\n\t\tconst varMapper = createObjMapper(variablesToFill)\n\t\tconst resultNodes = observableArrayMap(function queryStepDoStep() {\n\t\t\tconst newVarsAndTheirLog = applogsMatchingStatic.map(log => ({ log, vars: varMapper(log) }))\n\t\t\tif (VERBOSE.isEnabled) {\n\t\t\t\tVERBOSE(\n\t\t\t\t\t`[queryStep.doQuery] step node:`,\n\t\t\t\t\tnode?.variables,\n\t\t\t\t\t' =>',\n\t\t\t\t\tnewVarsAndTheirLog,\n\t\t\t\t\t'from:',\n\t\t\t\t\tuntracked(() => applogsMatchingStatic.applogs),\n\t\t\t\t)\n\t\t\t}\n\n\t\t\treturn newVarsAndTheirLog.map(({ log, vars }) => {\n\t\t\t\tconst nodeVars = Object.assign({}, node?.variables, vars)\n\t\t\t\treturn new QueryNode(\n\t\t\t\t\t// TODO: ? Make single result nodes reactive using MappedThread - only really relevant if a result had multiple logs (or different paths would lead to the same result?)\n\t\t\t\t\t// ThreadInMemory.fromArray(\n\t\t\t\t\tStaticThread.fromArray(\n\t\t\t\t\t\t[log],\n\t\t\t\t\t\tcreateDebugName({\n\t\t\t\t\t\t\tcaller: 'QueryNode',\n\t\t\t\t\t\t\tthread: applogsMatchingStatic,\n\t\t\t\t\t\t\tpattern: `${stringify(nodeVars)}@${stringify(patternWithResolvedVars)}`,\n\t\t\t\t\t\t}),\n\t\t\t\t\t\t// true,\n\t\t\t\t\t),\n\t\t\t\t\tnodeVars,\n\t\t\t\t\tnode,\n\t\t\t\t)\n\t\t\t})\n\t\t}, { name: createDebugName({ caller: 'doQuery.mapNodes', thread: applogsMatchingStatic, pattern }) })\n\t\tif (VERBOSE.isEnabled) autorun(() => VERBOSE(`[queryStep.doQuery] resultNodes:`, [...resultNodes]))\n\t\tif (opts.debug) {\n\t\t\tLOG(\n\t\t\t\t`[queryStep] step result:`,\n\t\t\t\tuntracked(() =>\n\t\t\t\t\tresultNodes.map(({ variables, logsOfThisNode: thread }) => ({\n\t\t\t\t\t\tvariables,\n\t\t\t\t\t\tthread, // : /* util.inspect( */ thread.applogs, /* , { showHidden: false, depth: null }) */\n\t\t\t\t\t}))\n\t\t\t\t),\n\t\t\t)\n\t\t}\n\t\treturn resultNodes\n\t}\n\tconst observableResultNodes = observableArrayMap(\n\t\tfunction queryStepGetResults() {\n\t\t\tDEBUG(`[queryStep] Running with ${nodeSet?.nodes?.length} input nodes:`)\n\t\t\tif (!nodeSet) {\n\t\t\t\t// first query step\n\t\t\t\treturn [...doQuery(null)] // HACK copy array bc otherwise the observableArrayMap doesn't seem to depend on the contents somehow\n\t\t\t} else {\n\t\t\t\t// subsequent query steps\n\t\t\t\treturn [...nodeSet.nodes.flatMap(doQuery)]\n\t\t\t}\n\t\t},\n\t\t{ name: createDebugName({ caller: 'queryStep', thread, pattern }) },\n\t)\n\n\tif (VERBOSE.isEnabled) autorun(() => VERBOSE(`[queryStep] observableResultNodes:`, [...observableResultNodes]))\n\treturn new QueryResult(observableResultNodes)\n}, { equals: queryNodesComparer, argsDebugName: (thread, _nodes, pattern) => createDebugName({ caller: 'queryStep', thread, pattern }) })\n\nexport const queryNot = computedFnDeepCompare('queryNot', function queryNot( // TODO: update old-style query\n\tthread: Thread,\n\tstartNodes: QueryResult,\n\tpatternOrPatterns: DatalogQueryPattern | DatalogQueryPattern[],\n\topts: { debug?: boolean } = {},\n) {\n\tlet nodes = startNodes.nodes\n\tDEBUG(`queryNot<${thread.nameAndSizeUntracked}> from: ${nodes.length} nodes`)\n\tconst patterns = (Array.isArray(patternOrPatterns) ? patternOrPatterns : [patternOrPatterns]) as DatalogQueryPattern[]\n\n\tfor (const pattern of patterns) {\n\t\tif (!Object.entries(patternOrPatterns).length) throw new Error(`Pattern is empty`)\n\t\tnodes = nodes.filter(function innerNodeFilter({ /* applogs, */ variables }) {\n\t\t\tconst [patternWithResolvedVars, _variablesToFill] = resolveOrRemoveVariables(pattern, variables ?? {})\n\t\t\tVERBOSE(`[queryNot] patternWithoutVars: `, patternWithResolvedVars)\n\t\t\tconst newApplogs = rollingFilter(thread, patternWithResolvedVars)\n\t\t\tVERBOSE(`[queryNot] step node:`, variables, ' =>', newApplogs.size, 'applogs')\n\t\t\tVERBOSE.isDisabled || VERBOSE(`[queryNot] step node:`, variables, ' => empty?', untracked(() => newApplogs.applogs))\n\n\t\t\tif (opts.debug) LOG(`[queryNot] node result:`, variables, '=>', newApplogs.applogs)\n\t\t\treturn newApplogs.isEmpty\n\t\t})\n\t}\n\treturn new QueryResult(nodes)\n}, { equals: queryNodesComparer, argsDebugName: (thread, nodes, pattern) => createDebugName({ caller: 'queryNot', thread, pattern }) })\n\n// export function or(queries: QueryExecutor[]) {\n// return tagged(\n// `or{${stringify(queries)} } `,\n// function orExecutor(args: QueryExecutorArguments) {\n// const { db, nodes: contexts } = args\n// VERBOSE('[or]', { queries, contexts })\n// let results = []\n// for (const query of queries) {\n// const res = query(args)\n// VERBOSE('[or] query', query, 'result =>', res)\n// results.push(...res.nodes)\n// }\n// return { contexts: results }\n// }\n// )\n// }\n\n// export type Tagged<T> = T & { tag: string }\n// export function tagged<T>(tag: string, thing: T): Tagged<T> {\n// const e = thing as (T & { tag: string })\n// e.tag = tag\n// return e\n// }\n\n//////////////////////\n// COMPOSED QUERIES //\n//////////////////////\n// createDebugName({ caller: 'useKidRelations' }, true)\nexport const filterAndMap = computedFnDeepCompare('filterAndMap', function filterAndMap<R>(\n\tthread: Thread,\n\tpattern: DatalogQueryPattern,\n\tmapper: (keyof Applog) | (Partial<{ [key in keyof Applog]: string }>) | ((applog: Applog) => R),\n) {\n\tDEBUG(`filterAndMap<${thread.nameAndSizeUntracked}>`, pattern)\n\n\tconst filtered = rollingFilter(thread, pattern)\n\tif (VERBOSE.isEnabled) {\n\t\tVERBOSE(`[filterAndMap] filtered:`, filtered.untrackedSize)\n\t\tautorun(() => VERBOSE(`[filterAndMap] filtered:`, filtered.applogs))\n\t}\n\n\tconst name = createDebugName({ thread, pattern, caller: 'filterAndMap' })\n\tconst mapped = observableArrayMap<ApplogValue | any>(() => mapThreadWith(filtered, mapper), { name }) // TODO typing:? Record<string, ApplogValue> ?\n\tVERBOSE.isDisabled || autorun(() => VERBOSE(`[filterAndMap] mapped:`, mapped))\n\treturn mapped\n}, { equals: comparer.structural, argsDebugName: (thread, pattern) => createDebugName({ caller: 'filterAndMap', thread, pattern }) })\n\nexport const queryAndMap = computedFnDeepCompare('queryAndMap', function queryAndMap<R>(\n\tthreadOrLogs: Thread | Applog[],\n\tpatternOrPatterns: Parameters<typeof query>[1],\n\tmapDef: string | (Partial<{ [key in keyof SearchContext]: string }>) | ((record: SearchContext) => R),\n\tvariables: SearchContext = {},\n) {\n\tconst thread = threadFromMaybeArray(threadOrLogs)\n\tDEBUG(`queryAndMap<${thread.nameAndSizeUntracked}>`, { patternOrPatterns, variables, map: mapDef })\n\tconst debugName = createDebugName({ thread, caller: 'queryAndMap' })\n\n\tconst queryResult = query(thread, patternOrPatterns)\n\tVERBOSE(`[queryAndMap] filtered count:`, queryResult.untrackedSize)\n\tconst mapped = observableArrayMap<ApplogValue | any>(\n\t\t() => mapQueryResultWith(queryResult, mapDef),\n\t\t{ name: debugName },\n\t)\n\tVERBOSE.isDisabled || autorun(() => VERBOSE(`[queryAndMap] result:`, toJS(mapped)))\n\treturn mapped\n}, { equals: comparer.structural, argsDebugName: (thread, pattern) => createDebugName({ caller: 'queryAndMap', thread, pattern }) })\n\nexport const queryEntity = computedFnDeepCompare('queryEntity', function queryEntity(\n\tthread: Thread,\n\tname: string,\n\tentityID: EntityID,\n\tattributes: readonly string[],\n) {\n\tDEBUG(`queryEntity<${thread.nameAndSizeUntracked}>`, entityID, name)\n\n\tconst filtered = rollingFilter(thread, { en: entityID, at: prefixAttrs(name, attributes) })\n\tVERBOSE(`queryEntity applogs:`, filtered.applogs)\n\treturn computed(() =>\n\t\tfiltered.isEmpty ? null : Object.fromEntries(\n\t\t\tfiltered.map(({ at, vl }) => [at.slice(name.length + 1), vl]),\n\t\t)\n\t)\n}, {\n\tequals: computedStructuralComparer,\n\targsDebugName: (thread, name, entityID) => createDebugName({ caller: 'queryEntity', thread, args: { name, entityID } }),\n})\n\nexport const agentsOfThread = computedFnDeepCompare('agentsOfThread', function agentsOfThread(\n\tthread: Thread,\n) {\n\tDEBUG(`agentsOfThread<${thread.nameAndSizeUntracked}>`)\n\n\tconst mapped = observable.map<string, number>()\n\tconst onEvent = action((event: ThreadEvent) => {\n\t\tfor (const log of (isInitEvent(event) ? event.init : event.added)) {\n\t\t\tconst prev = mapped.get(log.ag) ?? 0\n\t\t\tmapped.set(log.ag, prev + 1)\n\t\t}\n\t\tfor (const log of (!isInitEvent(event) && event.removed || [])) {\n\t\t\tconst prev = mapped.get(log.ag)\n\t\t\tif (!prev || prev < 1) throw ERROR(`[agentsOfThread] number is now negative`, { log, event, mapped, prev })\n\t\t\tmapped.set(log.ag, prev - 1)\n\t\t}\n\t\tLOG(`agentsOfThread<${thread.nameAndSizeUntracked}> processed event`, { event, mapped })\n\t})\n\n\tonEvent({ init: thread.applogs })\n\tconst unsubscribe = thread.subscribe(onEvent, 'derived')\n\tonBecomeUnobserved(mapped, unsubscribe) // FIX: cleanup when UNobserved, not when observed\n\n\treturn mapped\n})\n\nexport const entityOverlap = computedFnDeepCompare('entityOverlap', function entityOverlapCount(\n\tthreadA: Thread,\n\tthreadB: Thread,\n) {\n\tLOG(`entityOverlap<${threadA.nameAndSizeUntracked}, ${threadB.nameAndSizeUntracked}>`)\n\n\treturn computed(() => {\n\t\tconst entitiesA = new Set(threadA.map(log => log.en))\n\t\tconst entitiesB = new Set(threadB.map(log => log.en))\n\t\treturn [...entitiesA].filter(en => entitiesB.has(en))\n\t})\n})\n\nexport const entityOverlapMap = function entityOverlapMap(\n\tthreadA: Thread,\n\tthreadB: Thread,\n\tthreadAName = 'incoming',\n\tthreadBName = 'current',\n) {\n\tconst useInferredVM = (en, thread: Thread) => en\n\tconst overlapping = entityOverlap(threadA, threadB).get()\n\tconst mapped = new Map()\n\toverlapping.forEach(eachEntityID => (\n\t\tmapped.set(eachEntityID, {\n\t\t\t[threadAName]: useInferredVM(eachEntityID, threadA),\n\t\t\t[threadBName]: useInferredVM(eachEntityID, threadB),\n\t\t})\n\t))\n}\n\nexport const entityOverlapCount = computedFnDeepCompare(\n\t'entityOverlapCount',\n\tfunction entityOverlapCount(threadA: Thread, threadB: Thread) {\n\t\treturn computed(() => entityOverlap(threadA, threadB).get().length)\n\t},\n)\nexport const querySingle = computedFnDeepCompare('querySingle', function querySingle(\n\tthreadOrLogs: Thread | Applog[],\n\tpatternOrPatterns: Parameters<typeof query>[1],\n\tvariables: SearchContext = {},\n) {\n\tconst result = query(threadOrLogs, patternOrPatterns, variables)\n\treturn computed(() => {\n\t\tif (result.isEmpty) return null\n\t\tif (result.size > 1) throw ERROR(`[querySingle] got`, result.size, `results:`, result)\n\t\tconst logsOfThisNode = result.nodes[0].logsOfThisNode\n\t\tif (logsOfThisNode.size != 1) throw ERROR(`[querySingle] single result, but got`, logsOfThisNode.size, `logs:`, logsOfThisNode.applogs)\n\t\treturn logsOfThisNode.applogs[0]\n\t})\n}, {\n\tequals: comparer.structural,\n\targsDebugName: (thread, pattern) => createDebugName({ caller: 'querySingle', thread, pattern }),\n})\n\nexport const querySingleAndMap = computedFnDeepCompare(\n\t'querySingleAndMap',\n\tfunction querySingleAndMap<MAP extends (keyof Applog | (Partial<{ [key in keyof Applog]: string }>))>(\n\t\tthreadOrLogs: Thread | Applog[],\n\t\tpatternOrPatterns: Parameters<typeof query>[1],\n\t\tmapDef: MAP,\n\t\tvariables: SearchContext = {},\n\t) {\n\t\tconst resultBox = querySingle(threadOrLogs, patternOrPatterns, variables)\n\t\treturn computed<ApplogValue | { [key in keyof MAP]: ApplogValue } | null>(() => {\n\t\t\tconst log = resultBox.get()\n\t\t\tif (!log) return undefined\n\t\t\tif (typeof mapDef === 'string') {\n\t\t\t\treturn log[mapDef as string]\n\t\t\t} else {\n\t\t\t\treturn createObjMapper(mapDef)(log)\n\t\t\t}\n\t\t})\n\t},\n\t{\n\t\tequals: comparer.structural,\n\t\targsDebugName: (thread, pattern) => createDebugName({ caller: 'querySingleAndMap', thread, pattern }),\n\t},\n)\n/////////////\n// HELPERS //\n/////////////\n\nexport const mapThreadWith = function filterAndMapGetterFx<R>(\n\tthread: Thread,\n\tmapDef: (keyof Applog) | (Partial<{ [key in keyof Applog]: string }>) | ((applog: Applog) => R),\n) {\n\tif (typeof mapDef === 'function') {\n\t\treturn thread.map(mapDef)\n\t} else if (typeof mapDef === 'string') {\n\t\treturn thread.map(log => log[mapDef])\n\t} else {\n\t\treturn thread.map(createObjMapper(mapDef))\n\t}\n}\nexport const mapQueryResultWith = function filterAndMapGetterFx<R>(\n\tqueryResult: QueryResult,\n\tmapDef: string | (Partial<{ [key in keyof SearchContext]: string }>) | ((record: SearchContext) => R),\n) {\n\tif (typeof mapDef === 'function') {\n\t\treturn queryResult.records.map(mapDef)\n\t} else if (typeof mapDef === 'string') {\n\t\treturn queryResult.nodes.map((node) => {\n\t\t\tif (!Object.hasOwn(node.record, mapDef)) {\n\t\t\t\tif (node.logsOfThisNode.size !== 1) {\n\t\t\t\t\tthrow ERROR(`not sure what to map (it's not a var and a result node log count of ${node.logsOfThisNode.size})`)\n\t\t\t\t}\n\t\t\t\treturn node.logsOfThisNode.firstLog[mapDef]\n\t\t\t}\n\t\t\treturn node.record[mapDef]\n\t\t})\n\t} else {\n\t\treturn queryResult.nodes.map((node) => {\n\t\t\treturn createObjMapper(mapDef)(queryResult)\n\t\t})\n\t}\n}\n/**\n * Map Applog to custom named record, e.g.:\n * { en: 'movieID', vl: 'movieName' }\n * will map the applog to { movieID: .., movieName: .. }\n */\nexport function createObjMapper<FROM extends string, TO extends string>(applogFieldMap: Partial<{ [key in FROM]: TO }>) {\n\treturn (applog: { [key in FROM]: any }) => {\n\t\treturn Object.entries(applogFieldMap).reduce((acc, [key, value]) => {\n\t\t\tacc[value as TO] = applog[key]\n\t\t\treturn acc\n\t\t}, {} as Partial<{ [key in TO]: ApplogValue }>)\n\t}\n}\n\nexport function startsWith(str: string) {\n\treturn (value) => value.startsWith(str)\n}\n\nexport function prefixAttrs(prefix: string, attrs: readonly string[]) {\n\treturn attrs.map(at => prefixAt(prefix, at))\n}\nexport function prefixAt(prefix: string, attr: string) {\n\treturn `${prefix}/${attr}`\n}\nexport function threadFromMaybeArray(threadOrLogs: Thread | Applog[], name?: string) {\n\tif (!Array.isArray(threadOrLogs)) {\n\t\treturn threadOrLogs\n\t}\n\treturn ThreadInMemory.fromArray(threadOrLogs, name || `threadFromArray[${threadOrLogs.length}]`, true)\n}\nexport function withTimeout<R>(timeoutMilliseconds: number, func: () => R) {\n\tif (globalQueryTimeoutTime) throw ERROR(`Nested timeout not supported`)\n\tglobalQueryTimeoutTime = performance.now() + timeoutMilliseconds\n\ttry {\n\t\treturn func()\n\t} finally {\n\t\tglobalQueryTimeoutTime = null\n\t}\n}\nexport function throwOnTimeout() {\n\tif (globalQueryTimeoutTime == null) return\n\tif (performance.now() >= globalQueryTimeoutTime) {\n\t\tthrow new QueryTimeoutError(globalQueryTimeoutTime)\n\t}\n}\nclass QueryTimeoutError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message)\n\t}\n}\n"],"mappings":"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","names":["lastWriteWins","withoutDeleted","query","queryStep","thread","queryNot","filterAndMap","queryAndMap","queryEntity","agentsOfThread","entityOverlapMap","entityOverlapCount","querySingle","querySingleAndMap","filterAndMapGetterFx"]}
|
|
@@ -6215,6 +6215,7 @@ var Thread = class {
|
|
|
6215
6215
|
}
|
|
6216
6216
|
filters;
|
|
6217
6217
|
parents;
|
|
6218
|
+
_derivedSubscribers = [];
|
|
6218
6219
|
_subscribers = [];
|
|
6219
6220
|
get readOnly() {
|
|
6220
6221
|
if (this.parents.length !== 1) return true;
|
|
@@ -6232,18 +6233,27 @@ var Thread = class {
|
|
|
6232
6233
|
if (this.parents?.length !== 1) throw ERROR2(`[Thread] insertRaw() called on thread with multiple parents:`, this.nameAndSizeUntracked);
|
|
6233
6234
|
return this.parents[0].insertRaw(appLogsToInsert);
|
|
6234
6235
|
}
|
|
6235
|
-
subscribe(callback) {
|
|
6236
|
-
this._subscribers
|
|
6236
|
+
subscribe(callback, type) {
|
|
6237
|
+
const list = type === "derived" ? this._derivedSubscribers : this._subscribers;
|
|
6238
|
+
list.push(callback);
|
|
6237
6239
|
return this.unsubscribe.bind(this, callback);
|
|
6238
6240
|
}
|
|
6239
6241
|
unsubscribe(callback) {
|
|
6242
|
+
const derivedIndex = this._derivedSubscribers.indexOf(callback);
|
|
6243
|
+
if (derivedIndex !== -1) {
|
|
6244
|
+
this._derivedSubscribers.splice(derivedIndex, 1);
|
|
6245
|
+
return;
|
|
6246
|
+
}
|
|
6240
6247
|
const index = this._subscribers.indexOf(callback);
|
|
6241
6248
|
if (index !== -1) {
|
|
6242
6249
|
this._subscribers.splice(index, 1);
|
|
6243
6250
|
} else WARN2(`unsubscribe called for non-existent`, callback);
|
|
6244
6251
|
}
|
|
6245
6252
|
notifySubscribers(event) {
|
|
6246
|
-
DEBUG2(`[thread: ${this.name}] notifying`, this._subscribers.length, "subscribers of", { ...event, subs: this._subscribers });
|
|
6253
|
+
DEBUG2(`[thread: ${this.name}] notifying`, this._derivedSubscribers.length, "derived +", this._subscribers.length, "subscribers of", { ...event, subs: this._subscribers });
|
|
6254
|
+
for (const subscriber of this._derivedSubscribers) {
|
|
6255
|
+
subscriber(event);
|
|
6256
|
+
}
|
|
6247
6257
|
for (const subscriber of this._subscribers) {
|
|
6248
6258
|
subscriber(event);
|
|
6249
6259
|
}
|
|
@@ -8437,10 +8447,13 @@ var MappedThread = class _MappedThread extends Thread {
|
|
|
8437
8447
|
const unseen = /* @__PURE__ */ new Set([...this._parentSubscriptions.keys()]);
|
|
8438
8448
|
for (const p of this.parents) {
|
|
8439
8449
|
let existed = unseen.delete(p);
|
|
8440
|
-
if (existed)
|
|
8450
|
+
if (existed) {
|
|
8451
|
+
VERBOSE6(`[MappedThread: ${this.name}] Skipping re-sub to parent`, p.nameAndSizeUntracked);
|
|
8452
|
+
continue;
|
|
8453
|
+
}
|
|
8441
8454
|
VERBOSE6(`[MappedThread: ${this.name}] sub to new parent`, p.nameAndSizeUntracked);
|
|
8442
8455
|
const sub = this.onParentUpdate.bind(this, p);
|
|
8443
|
-
const unsubscribe = p.subscribe(sub);
|
|
8456
|
+
const unsubscribe = p.subscribe(sub, "derived");
|
|
8444
8457
|
this._parentSubscriptions.set(p, unsubscribe);
|
|
8445
8458
|
}
|
|
8446
8459
|
for (const p of unseen) {
|
|
@@ -8451,11 +8464,11 @@ var MappedThread = class _MappedThread extends Thread {
|
|
|
8451
8464
|
}
|
|
8452
8465
|
});
|
|
8453
8466
|
}
|
|
8454
|
-
subscribe(callback) {
|
|
8467
|
+
subscribe(callback, type) {
|
|
8455
8468
|
if (!this._parentSubscriptions) {
|
|
8456
8469
|
this.subscribeToParents();
|
|
8457
8470
|
}
|
|
8458
|
-
return super.subscribe(callback);
|
|
8471
|
+
return super.subscribe(callback, type);
|
|
8459
8472
|
}
|
|
8460
8473
|
// ? same on unsubscribe?
|
|
8461
8474
|
/**
|
|
@@ -8598,7 +8611,7 @@ var rollingAcc = computedFnDeepCompare(
|
|
|
8598
8611
|
eventMapperAction({ init: thread.applogs }, acc);
|
|
8599
8612
|
thread.subscribe((event) => {
|
|
8600
8613
|
eventMapperAction(event, acc);
|
|
8601
|
-
});
|
|
8614
|
+
}, "derived");
|
|
8602
8615
|
return acc;
|
|
8603
8616
|
},
|
|
8604
8617
|
{ argsDebugName: (thread, _acc, _mapper, opts) => `rollingAcc{${thread.nameAndSizeUntracked}${opts?.name ? ` | ${opts?.name}` : ""}}` }
|
|
@@ -9064,4 +9077,4 @@ lodash-es/lodash.js:
|
|
|
9064
9077
|
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
|
9065
9078
|
*)
|
|
9066
9079
|
*/
|
|
9067
|
-
//# sourceMappingURL=chunk-
|
|
9080
|
+
//# sourceMappingURL=chunk-GDX2OO7L.min.js.map
|