@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/query/types.ts","../src/query/basic.ts"],"sourcesContent":["import { joinThreads } from '../applog/applog-helpers.ts'\nimport { SearchContext } from '../applog/datom-types.ts'\nimport type { Thread } from '../thread/basic.ts'\nimport { ArrayEvent, SubscribableArray, SubscribableArrayImpl, Unsubscribe } from './subscribable.ts'\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\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/** Shared interface for query results (one-off and live) */\nexport interface IQueryResult {\n\treadonly nodes: readonly QueryNode[]\n\treadonly size: number\n\treadonly isEmpty: boolean\n\treadonly records: readonly SearchContext[]\n\treadonly leafNodeLogs: readonly import('../applog/datom-types').Applog[]\n\treadonly leafNodeThread: Thread\n\treadonly threadOfAllTrails: Thread\n\treadonly thread: Thread\n\treadonly allApplogs: readonly import('../applog/datom-types').Applog[]\n}\n\n/**\n * One-off query result — plain frozen snapshot.\n * No subscribe method. No stale-data risk.\n */\nexport class QueryResult implements IQueryResult {\n\tconstructor(\n\t\treadonly nodes: readonly QueryNode[],\n\t) {}\n\n\tget size() {\n\t\treturn this.nodes.length\n\t}\n\tget isEmpty() {\n\t\treturn this.nodes.length === 0\n\t}\n\tget untrackedSize() {\n\t\treturn this.nodes.length\n\t}\n\n\tget records(): readonly SearchContext[] {\n\t\treturn this.nodes.map(({ variables }) => variables)\n\t}\n\tget leafNodeThread() {\n\t\treturn joinThreads(\n\t\t\tthis.nodes.map(({ logsOfThisNode: thread }) => thread),\n\t\t)\n\t}\n\tget leafNodeLogSet() {\n\t\treturn this.nodes.map(({ logsOfThisNode: thread }) => thread.applogs)\n\t}\n\tget leafNodeLogs() {\n\t\treturn this.nodes.flatMap(({ logsOfThisNode: thread }) => thread.applogs)\n\t}\n\tget threadOfAllTrails() {\n\t\treturn joinThreads(this.nodes.map(node => node.threadOfTrail))\n\t}\n\tget thread() {\n\t\treturn this.threadOfAllTrails // alias\n\t}\n\tget allApplogs() {\n\t\treturn this.threadOfAllTrails.applogs\n\t}\n}\n\n/**\n * Live query result — eagerly activated, always up-to-date.\n *\n * `.nodes` returns the current live view.\n * `.subscribe()` receives future delta events (consistent with current state).\n * Must call `.dispose()` when done to tear down upstream subscriptions.\n */\nexport class LiveQueryResult implements IQueryResult {\n\tconstructor(\n\t\tprivate _source: SubscribableArray<QueryNode>,\n\t\tactivate = true,\n\t) {\n\t\tif (activate) {\n\t\t\t// Eagerly activate: subscribe with a no-op to start upstream.\n\t\t\t// Store unsub so dispose() can tear it down.\n\t\t\tthis._activationUnsub = this._source.subscribe(() => {})\n\t\t}\n\t}\n\n\tprivate _activationUnsub: Unsubscribe | null = null\n\n\t/** Subscribe to node change events. Callback fires on future changes only. */\n\tsubscribe(cb: (event: ArrayEvent<QueryNode>) => void, type?: 'derived' | 'reaction'): Unsubscribe {\n\t\treturn this._source.subscribe(cb, type)\n\t}\n\n\t/** Current nodes — live view, always up-to-date while not disposed */\n\tget nodes(): readonly QueryNode[] {\n\t\treturn this._source.items\n\t}\n\n\tget size() {\n\t\treturn this._source.length\n\t}\n\tget isEmpty() {\n\t\treturn this._source.length === 0\n\t}\n\tget untrackedSize() {\n\t\treturn this._source.length\n\t}\n\n\tget records(): readonly SearchContext[] {\n\t\treturn this.nodes.map(({ variables }) => variables)\n\t}\n\tget leafNodeThread() {\n\t\treturn joinThreads(\n\t\t\tthis.nodes.map(({ logsOfThisNode: thread }) => thread),\n\t\t)\n\t}\n\tget leafNodeLogSet() {\n\t\treturn this.nodes.map(({ logsOfThisNode: thread }) => thread.applogs)\n\t}\n\tget leafNodeLogs() {\n\t\treturn this.nodes.flatMap(({ logsOfThisNode: thread }) => thread.applogs)\n\t}\n\tget threadOfAllTrails() {\n\t\treturn joinThreads(this.nodes.map(node => node.threadOfTrail))\n\t}\n\tget thread() {\n\t\treturn this.threadOfAllTrails // alias\n\t}\n\tget allApplogs() {\n\t\treturn this.threadOfAllTrails.applogs\n\t}\n\n\tdispose() {\n\t\tthis._activationUnsub?.()\n\t\tthis._activationUnsub = null\n\t\tthis._source.dispose()\n\t}\n}\n","import { AgentHash, Applog, ApplogValue, CidString, DatalogQueryPattern, EntityID, SearchContext, ValueOrMatcher } from '../applog/datom-types.ts'\n\nimport { Logger } from 'besonders-logger'\n\nimport { isEmpty } from 'lodash-es'\nimport stringify from 'safe-stable-stringify'\nimport { isLaterByTsAndPv, isoDateStrCompare, isVariable, resolveOrRemoveVariables, sortApplogsByTs } from '../applog/applog-utils.ts'\nimport { createDebugName } from '../utils/debug-name.ts'\nimport { isInitEvent, StaticThread, Thread, ThreadEvent } from '../thread/basic.ts'\nimport { hasFilter, makeFilter, rollingFilter, rollingMapper, ThreadOnlyCurrent } from '../thread/filters.ts'\nimport { applogsByEntity } from '../thread/indexes.ts'\nimport { MappedThread, type ThreadDerivation } from '../thread/mapped.ts'\nimport { ThreadInMemory } from '../thread/writeable.ts'\nimport { memoizedFn } from './memoized.ts'\nimport { isArrayInitEvent, SubscribableArray, SubscribableArrayImpl, SubscribableImpl, Unsubscribe } from './subscribable.ts'\nimport { LiveQueryResult, QueryNode, QueryResult } from './types.ts'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO, { prefix: '[q]' }) // eslint-disable-line no-unused-vars\n\nfunction assertLWW(thread: Thread) {\n\tif (!hasFilter(thread, 'lastWriteWins')) {\n\t\tthrow ERROR(`requires lastWriteWins-filtered thread, got filters:`, thread.filters, { name: thread.name })\n\t}\n}\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 = memoizedFn('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\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\n\t/**\n\t * Iterate `newLogs` (already chain-aware-sorted by `sortApplogsByTs`) updating\n\t * `rollingMap` to hold the LWW winner per (en|at) key. Uses `isLaterByTsAndPv`\n\t * — pairwise pv-aware predicate — so cross-batch comparisons in mapDelta also\n\t * stay deterministic when same-ts chain links collide.\n\t */\n\tconst processLogs = (newLogs: readonly Applog[], toRemove: Applog[] | null): Applog[] => {\n\t\tconst toAdd = [] as Applog[]\n\t\tlet prevTs: string | undefined\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\n\n\t\t\tif (prevTs !== undefined) {\n\t\t\t\tconst cmp = isoDateStrCompare(prevTs, log.ts)\n\t\t\t\tif (inverseToOnlyReturnFirstLogs ? cmp > 0 : cmp < 0) {\n\t\t\t\t\tthrow ERROR(`lastWriteWins.processLogs logs not ts-sorted:`, prevTs, inverseToOnlyReturnFirstLogs ? '>' : '<', log.ts, {\n\t\t\t\t\t\tlog,\n\t\t\t\t\t\ti,\n\t\t\t\t\t\tnewLogs,\n\t\t\t\t\t\tinverseToOnlyReturnFirstLogs,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\tprevTs = log.ts\n\n\t\t\tconst existing = rollingMap.get(key)\n\t\t\tconst replaces = !existing || (inverseToOnlyReturnFirstLogs\n\t\t\t\t? isLaterByTsAndPv(existing, log)\n\t\t\t\t: isLaterByTsAndPv(log, existing))\n\t\t\tif (replaces) {\n\t\t\t\tif (existing && toRemove) 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\treturn toAdd\n\t}\n\n\tconst lwwName = `lastWriteWins${inverseToOnlyReturnFirstLogs ? '.inversed' : ''}`\n\tconst derivation: ThreadDerivation = {\n\t\tcompute(parents) {\n\t\t\tif (parents.length !== 1) {\n\t\t\t\tthrow ERROR(`${lwwName} requires exactly one parent`, { parents: parents.length })\n\t\t\t}\n\t\t\tconst [parent] = parents\n\t\t\trollingMap = new Map()\n\t\t\tconst toAdd = processLogs(parent.applogs, null)\n\t\t\tsortApplogsByTs(toAdd)\n\t\t\tVERBOSE.isDisabled || VERBOSE(`${lwwName}<${thread.nameAndSizeUntracked}> compute`, { toAdd: toAdd.length })\n\t\t\treturn toAdd\n\t\t},\n\t\tmapDelta(delta) {\n\t\t\tconst toRemove = [] as Applog[]\n\t\t\tconst toAdd = processLogs(delta.added, toRemove)\n\t\t\tsortApplogsByTs(toAdd)\n\t\t\tVERBOSE.isDisabled || VERBOSE(`${lwwName}<${thread.nameAndSizeUntracked}> mapDelta`, { ...delta, toAdd, toRemove })\n\t\t\treturn { added: toAdd, removed: toRemove }\n\t\t},\n\t}\n\tconst mappedThread = rollingMapper(thread, derivation, { name: lwwName, extraFilterName: 'lastWriteWins' })\n\tVERBOSE.isDisabled || VERBOSE(`lastWriteWins<${thread.nameAndSizeUntracked}> filtered down to`, mappedThread.applogs.length)\n\treturn mappedThread as ThreadOnlyCurrent\n}, { argsDebugName: (thread) => createDebugName({ caller: 'lastWriteWins', thread }) })\n\nconst isDeletedAttrs = ['isDeleted', 'relation/isDeleted', 'block/isDeleted']\nfunction isDeletionLog(log: Applog) {\n\treturn log.vl === true && isDeletedAttrs.includes(log.at)\n}\n\n/**\n * Remove all applogs for entities that have an applog `{ at: 'isDeleted' | 'relation/isDeleted' | 'block/isDeleted', vl: true }`.\n *\n * Emits synthetic `removed` events for the entity's pre-existing applogs when an\n * entity becomes deleted (and synthetic `added` events for un-deletion).\n *\n * Un-deletion: canonical input is appending `{ at: 'isDeleted', vl: false }`. Requires\n * `lastWriteWins` upstream — without it, the `vl: true` log isn't superseded so we\n * can't observe a transition. Soft-warned at runtime.\n */\nexport const withoutDeleted = memoizedFn('withoutDeleted', function withoutDeleted(\n\tthread: Thread,\n) {\n\tif (VERBOSE.isEnabled) VERBOSE(`withoutDeleted<${thread.nameAndSizeUntracked}>`)\n\tif (thread.filters.includes('withoutDeleted')) {\n\t\tthrow ERROR(`thread already filtered withoutDeleted:`, thread.filters, { name: thread.name })\n\t}\n\tif (!thread.filters.includes('lastWriteWins')) {\n\t\tWARN(`withoutDeleted on non-lastWriteWins thread: un-deletion (isDeleted: false) won't take effect`, { thread: thread.name })\n\t}\n\n\t// FIFO contract: byEntity must subscribe to `thread` BEFORE `result` does, so the index\n\t// is up-to-date when our mapper runs. Calling applogsByEntity here forces that order;\n\t// memoization makes it idempotent if other code already subscribed.\n\tconst byEntity = applogsByEntity(thread)\n\n\t// Per-entity count of currently-active isDeleted-class logs. 0→1 = entity becomes hidden;\n\t// 1→0 = entity becomes visible. Handles multiple isDeleted-class attrs per entity.\n\tconst activeDeletionMarkers = new Map<EntityID, number>()\n\tfor (const log of thread.applogs) {\n\t\tif (isDeletionLog(log)) {\n\t\t\tactiveDeletionMarkers.set(log.en, (activeDeletionMarkers.get(log.en) ?? 0) + 1)\n\t\t}\n\t}\n\tconst isHidden = (en: EntityID) => activeDeletionMarkers.has(en)\n\n\tconst derivation: ThreadDerivation = {\n\t\tcompute(parents) {\n\t\t\tif (parents.length !== 1) throw ERROR(`withoutDeleted requires exactly one parent`, { parents: parents.length })\n\t\t\tconst [parent] = parents\n\t\t\tactiveDeletionMarkers.clear()\n\t\t\tfor (const log of parent.applogs) {\n\t\t\t\tif (isDeletionLog(log)) {\n\t\t\t\t\tactiveDeletionMarkers.set(log.en, (activeDeletionMarkers.get(log.en) ?? 0) + 1)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn parent.applogs.filter(log => !isHidden(log.en))\n\t\t},\n\t\tmapDelta: (delta) => {\n\t\t\t// Snapshot of which entities were hidden BEFORE this delta. Required because\n\t\t\t// pass-through correctness depends on prior visibility (logs of pre-hidden\n\t\t\t// entities were never in result, so they must not appear in `removed`),\n\t\t\t// while the post-mutation `isHidden` state determines whether new content\n\t\t\t// should be admitted. Filtering only on post-mutation state breaks both\n\t\t\t// W→N (stale isDeleted=true log slips into removed → MappedThread crash)\n\t\t\t// and F→D-with-content-removal (legitimate content removal gets filtered).\n\t\t\tconst hiddenBefore = new Set(activeDeletionMarkers.keys())\n\t\t\tconst entitiesNowHidden: EntityID[] = []\n\t\t\tconst entitiesNowVisible: EntityID[] = []\n\n\t\t\tfor (const log of delta.added) {\n\t\t\t\tif (!isDeletionLog(log)) continue\n\t\t\t\tconst prev = activeDeletionMarkers.get(log.en) ?? 0\n\t\t\t\tactiveDeletionMarkers.set(log.en, prev + 1)\n\t\t\t\tif (prev === 0) entitiesNowHidden.push(log.en)\n\t\t\t}\n\t\t\tif (delta.removed) {\n\t\t\t\tfor (const log of delta.removed) {\n\t\t\t\t\tif (!isDeletionLog(log)) continue\n\t\t\t\t\tconst prev = activeDeletionMarkers.get(log.en) ?? 0\n\t\t\t\t\tconst next = prev - 1\n\t\t\t\t\tif (next > 0) activeDeletionMarkers.set(log.en, next)\n\t\t\t\t\telse {\n\t\t\t\t\t\tactiveDeletionMarkers.delete(log.en)\n\t\t\t\t\t\tentitiesNowVisible.push(log.en)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Synthetic removals: applogs of newly-hidden entities currently in result.\n\t\t\t// byEntity index is updated for this tick already (FIFO), so we filter out\n\t\t\t// applogs added in this very tick (they were never in result).\n\t\t\tconst newAddedSet = new Set(delta.added)\n\t\t\tconst syntheticRemovals: Applog[] = []\n\t\t\tfor (const en of entitiesNowHidden) {\n\t\t\t\tconst applogs = byEntity.get(en)\n\t\t\t\tif (!applogs) continue\n\t\t\t\tfor (const log of applogs) {\n\t\t\t\t\tif (!newAddedSet.has(log)) syntheticRemovals.push(log)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Synthetic additions: all current parent applogs of newly-visible entities.\n\t\t\tconst syntheticAdditions: Applog[] = []\n\t\t\tfor (const en of entitiesNowVisible) {\n\t\t\t\tconst applogs = byEntity.get(en)\n\t\t\t\tif (applogs) syntheticAdditions.push(...applogs)\n\t\t\t}\n\n\t\t\t// Pass-through: a parent log goes through to subscribers iff the entity\n\t\t\t// wasn't hidden before AND isn't hidden now. Transitions are owned by the\n\t\t\t// synthetic streams above.\n\t\t\tconst passAdded = delta.added.filter(log =>\n\t\t\t\t!hiddenBefore.has(log.en) && !isHidden(log.en))\n\t\t\tconst passRemoved = delta.removed?.filter(log =>\n\t\t\t\t!hiddenBefore.has(log.en)) ?? []\n\n\t\t\treturn {\n\t\t\t\tadded: [...passAdded, ...syntheticAdditions],\n\t\t\t\tremoved: [...passRemoved, ...syntheticRemovals],\n\t\t\t}\n\t\t},\n\t}\n\tconst result = rollingMapper(thread, derivation, { name: 'withoutDeleted', extraFilterName: 'withoutDeleted' })\n\n\treturn result\n})\n\n///////////////////////////\n// ONE-OFF QUERY (snapshot) //\n///////////////////////////\n\n/** Shared helper: create a QueryNode from a log and its context */\nfunction makeQueryNode(\n\tlog: Applog,\n\tparentNode: QueryNode | null,\n\tvarMapper: (log: Applog) => SearchContext,\n\tthreadName: string,\n): QueryNode {\n\tconst nodeVars = Object.assign({}, parentNode?.variables, varMapper(log))\n\treturn new QueryNode(\n\t\tStaticThread.fromArray([log], threadName),\n\t\tnodeVars,\n\t\tparentNode,\n\t)\n}\n\n/**\n * One-off query — returns a plain snapshot. No subscriptions, no stale-data risk.\n */\nexport const query = memoizedFn('query', function query(\n\tthreadOrLogs: Thread | Applog[],\n\tpatternOrPatterns: DatalogQueryPattern | DatalogQueryPattern[],\n\tstartVariables: SearchContext = {},\n\topts: { debug?: boolean } = {},\n): QueryResult {\n\tthrowOnTimeout()\n\tconst thread = threadFromMaybeArray(threadOrLogs)\n\tDEBUG(`query<${thread.nameAndSizeUntracked}>:`, patternOrPatterns)\n\tconst patterns = (Array.isArray(patternOrPatterns) ? patternOrPatterns : [patternOrPatterns]) as DatalogQueryPattern[]\n\twarnIfDisjointQuerySteps(patterns)\n\n\tlet prevNodes: readonly QueryNode[] | null\n\tif (patterns.length === 1) {\n\t\tprevNodes = null\n\t} else {\n\t\tconst patternsExceptLast = patterns.slice(0, -1)\n\t\tprevNodes = query(thread, patternsExceptLast, startVariables, opts).nodes\n\t}\n\tconst lastPattern = patterns[patterns.length - 1]\n\tconst stepResult = queryStepOnce(thread, prevNodes, lastPattern, opts)\n\tVERBOSE.isDisabled || VERBOSE(`query result:`, stepResult.nodes)\n\treturn stepResult\n}, {\n\targsDebugName: (thread, pattern, startVars) =>\n\t\tcreateDebugName({ caller: 'query', thread, args: startVars ? { pattern, startVars } : pattern }),\n})\n\n/**\n * One-off query step — pure filtering via makeFilter, no subscriptions.\n */\nexport function queryStepOnce(\n\tthread: Thread,\n\tprevNodes: readonly QueryNode[] | null,\n\tpattern: DatalogQueryPattern,\n\topts: { debug?: boolean } = {},\n): QueryResult {\n\tDEBUG(`queryStepOnce<${thread.nameAndSizeUntracked}> with`, prevNodes?.length ?? 'all', 'nodes, pattern:', pattern)\n\tif (!Object.entries(pattern).length) throw new Error(`Pattern is empty`)\n\n\tfunction doQueryOnce(node: QueryNode | null): QueryNode[] {\n\t\tconst [patternWithResolvedVars, variablesToFill] = resolveOrRemoveVariables(pattern, node?.variables ?? {})\n\t\tVERBOSE(`[queryStepOnce.doQuery] patternWithoutVars: `, patternWithResolvedVars)\n\t\tconst filter = makeFilter(patternWithResolvedVars)\n\t\tconst matchingLogs = filter(thread.applogs)\n\t\tconst varMapper = createObjMapper(variablesToFill)\n\n\t\tconst nodes = matchingLogs.map(log => makeQueryNode(\n\t\t\tlog, node, varMapper,\n\t\t\tcreateDebugName({\n\t\t\t\tcaller: 'QueryNode',\n\t\t\t\tthread,\n\t\t\t\tpattern: `${stringify(Object.assign({}, node?.variables, varMapper(log)))}@${stringify(patternWithResolvedVars)}`,\n\t\t\t}),\n\t\t))\n\n\t\tif (VERBOSE.isEnabled) VERBOSE(`[queryStepOnce.doQuery] nodes:`, nodes.map(n => n.variables))\n\t\tif (opts.debug) {\n\t\t\tLOG(`[queryStepOnce] step result:`, nodes.map(({ variables, logsOfThisNode: thread }) => ({\n\t\t\t\tvariables,\n\t\t\t\tthread,\n\t\t\t})))\n\t\t}\n\n\t\treturn nodes\n\t}\n\n\tif (!prevNodes) {\n\t\treturn new QueryResult(doQueryOnce(null))\n\t}\n\n\tconst allNodes = prevNodes.flatMap(inputNode => doQueryOnce(inputNode))\n\treturn new QueryResult(allNodes)\n}\n\n///////////////////////////\n// LIVE QUERY (reactive) //\n///////////////////////////\n\n/**\n * Live query — eagerly activated, always up-to-date.\n * Returns LiveQueryResult with subscribe + dispose.\n */\nexport const liveQuery = memoizedFn('liveQuery', function liveQuery(\n\tthreadOrLogs: Thread | Applog[],\n\tpatternOrPatterns: DatalogQueryPattern | DatalogQueryPattern[],\n\tstartVariables: SearchContext = {},\n\topts: { debug?: boolean } = {},\n): LiveQueryResult {\n\tthrowOnTimeout()\n\tconst thread = threadFromMaybeArray(threadOrLogs)\n\tDEBUG(`liveQuery<${thread.nameAndSizeUntracked}>:`, patternOrPatterns)\n\tconst patterns = (Array.isArray(patternOrPatterns) ? patternOrPatterns : [patternOrPatterns]) as DatalogQueryPattern[]\n\n\tlet prevResult: LiveQueryResult | null\n\tif (patterns.length === 1) {\n\t\tprevResult = null\n\t} else {\n\t\tconst patternsExceptLast = patterns.slice(0, -1)\n\t\tprevResult = liveQuery(thread, patternsExceptLast, startVariables, opts)\n\t}\n\tconst lastPattern = patterns[patterns.length - 1]\n\tconst stepResult = liveQueryStep(thread, prevResult, lastPattern, opts)\n\tVERBOSE.isDisabled || VERBOSE(`liveQuery result:`, stepResult.nodes)\n\treturn stepResult\n}, {\n\targsDebugName: (thread, pattern, startVars) =>\n\t\tcreateDebugName({ caller: 'liveQuery', thread, args: startVars ? { pattern, startVars } : pattern }),\n})\n\nexport const liveQueryStep = memoizedFn('liveQueryStep', function liveQueryStep(\n\tthread: Thread,\n\tnodeSet: LiveQueryResult | null,\n\tpattern: DatalogQueryPattern,\n\topts: { debug?: boolean } = {},\n): LiveQueryResult {\n\tDEBUG(`liveQueryStep<${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): SubscribableArray<QueryNode> {\n\t\tconst [patternWithResolvedVars, variablesToFill] = resolveOrRemoveVariables(pattern, node?.variables ?? {})\n\t\tVERBOSE(`[liveQueryStep.doQuery] patternWithoutVars: `, patternWithResolvedVars)\n\t\tconst applogsMatchingStatic = rollingFilter(thread, patternWithResolvedVars)\n\t\tconst varMapper = createObjMapper(variablesToFill)\n\n\t\tfunction makeNode(log: Applog): QueryNode {\n\t\t\treturn makeQueryNode(\n\t\t\t\tlog, node, varMapper,\n\t\t\t\tcreateDebugName({\n\t\t\t\t\tcaller: 'QueryNode',\n\t\t\t\t\tthread: applogsMatchingStatic,\n\t\t\t\t\tpattern: `${stringify(Object.assign({}, node?.variables, varMapper(log)))}@${stringify(patternWithResolvedVars)}`,\n\t\t\t\t}),\n\t\t\t)\n\t\t}\n\n\t\t// Compute initial result synchronously\n\t\tconst initialNodes = applogsMatchingStatic.applogs.map(makeNode)\n\n\t\tif (VERBOSE.isEnabled) VERBOSE(`[liveQueryStep.doQuery] initial nodes:`, initialNodes.map(n => n.variables))\n\t\tif (opts.debug) {\n\t\t\tLOG(`[liveQueryStep] step result:`, initialNodes.map(({ variables, logsOfThisNode: thread }) => ({\n\t\t\t\tvariables,\n\t\t\t\tthread,\n\t\t\t})))\n\t\t}\n\n\t\t// Upstream subscription activates lazily — only when someone subscribes to us\n\t\tconst result = new SubscribableArrayImpl<QueryNode>(\n\t\t\tinitialNodes,\n\t\t\t() => applogsMatchingStatic.subscribe((event) => {\n\t\t\t\tif (isInitEvent(event)) {\n\t\t\t\t\tresult._reset(event.init.map(makeNode))\n\t\t\t\t} else {\n\t\t\t\t\tif (event.added.length) {\n\t\t\t\t\t\tresult._push(...event.added.map(makeNode))\n\t\t\t\t\t}\n\t\t\t\t\tif (event.removed?.length) {\n\t\t\t\t\t\tconst removedCids = new Set(event.removed.map(log => log.cid))\n\t\t\t\t\t\tconst toRemove = result.items.filter(qn =>\n\t\t\t\t\t\t\tremovedCids.has(qn.logsOfThisNode.applogs[0]?.cid)\n\t\t\t\t\t\t)\n\t\t\t\t\t\tif (toRemove.length) result._remove(toRemove)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}, 'derived'),\n\t\t)\n\t\treturn result\n\t}\n\n\t// ── Single-step query (nodeSet === null) ──────────────────────\n\tif (!nodeSet) {\n\t\treturn new LiveQueryResult(doQuery(null))\n\t}\n\n\t// ── Multi-step query (nodeSet !== null) ────────────────────────\n\n\t// Compute initial result synchronously\n\tconst initialInners = nodeSet.nodes.map(inputNode => ({\n\t\tinputNode,\n\t\tinner: doQuery(inputNode),\n\t}))\n\tconst initialItems = initialInners.flatMap(({ inner }) => [...inner.items])\n\n\t// Lazy activation: upstream subscriptions only created when someone subscribes\n\tconst aggregated = new SubscribableArrayImpl<QueryNode>(\n\t\tinitialItems,\n\t\t() => {\n\t\t\tconst subsByInputNode = new Map<QueryNode, {\n\t\t\t\tinner: SubscribableArray<QueryNode>,\n\t\t\t\tunsub: Unsubscribe,\n\t\t\t\tnodes: QueryNode[],\n\t\t\t}>()\n\n\t\t\tfunction wireInner(inputNode: QueryNode, inner: SubscribableArray<QueryNode>): QueryNode[] {\n\t\t\t\tconst entry = { inner, unsub: null! as Unsubscribe, nodes: [...inner.items] }\n\n\t\t\t\tentry.unsub = inner.subscribe((event) => {\n\t\t\t\t\tif (isArrayInitEvent(event)) {\n\t\t\t\t\t\tif (entry.nodes.length) aggregated._remove(entry.nodes)\n\t\t\t\t\t\tentry.nodes = [...event.init]\n\t\t\t\t\t\tif (entry.nodes.length) aggregated._push(...entry.nodes)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (event.added.length) {\n\t\t\t\t\t\t\tentry.nodes.push(...event.added)\n\t\t\t\t\t\t\taggregated._push(...event.added)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (event.removed?.length) {\n\t\t\t\t\t\t\tfor (const r of event.removed) {\n\t\t\t\t\t\t\t\tconst idx = entry.nodes.indexOf(r)\n\t\t\t\t\t\t\t\tif (idx >= 0) entry.nodes.splice(idx, 1)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\taggregated._remove(event.removed)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}, 'derived')\n\n\t\t\t\tsubsByInputNode.set(inputNode, entry)\n\t\t\t\treturn entry.nodes\n\t\t\t}\n\n\t\t\tfunction addInputNode(inputNode: QueryNode): QueryNode[] {\n\t\t\t\treturn wireInner(inputNode, doQuery(inputNode))\n\t\t\t}\n\n\t\t\tfunction removeInputNode(inputNode: QueryNode): QueryNode[] {\n\t\t\t\tconst entry = subsByInputNode.get(inputNode)\n\t\t\t\tif (!entry) return []\n\t\t\t\tentry.unsub()\n\t\t\t\tentry.inner.dispose()\n\t\t\t\tconst removed = entry.nodes\n\t\t\t\tsubsByInputNode.delete(inputNode)\n\t\t\t\treturn removed\n\t\t\t}\n\n\t\t\t// Reuse pre-computed inners (no re-creation of sub-queries)\n\t\t\tfor (const { inputNode, inner } of initialInners) {\n\t\t\t\twireInner(inputNode, inner)\n\t\t\t}\n\n\t\t\t// Subscribe to previous step for FUTURE changes only (no init)\n\t\t\tconst prevUnsub = nodeSet.subscribe((event) => {\n\t\t\t\tif (isArrayInitEvent(event)) {\n\t\t\t\t\tfor (const [, entry] of subsByInputNode) {\n\t\t\t\t\t\tentry.unsub(); entry.inner.dispose()\n\t\t\t\t\t}\n\t\t\t\t\tsubsByInputNode.clear()\n\t\t\t\t\tconst allNodes: QueryNode[] = []\n\t\t\t\t\tfor (const node of event.init) {\n\t\t\t\t\t\tallNodes.push(...addInputNode(node))\n\t\t\t\t\t}\n\t\t\t\t\taggregated._reset(allNodes)\n\t\t\t\t} else {\n\t\t\t\t\tif (event.added.length) {\n\t\t\t\t\t\tconst allAdded: QueryNode[] = []\n\t\t\t\t\t\tfor (const node of event.added) {\n\t\t\t\t\t\t\tallAdded.push(...addInputNode(node))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (allAdded.length) aggregated._push(...allAdded)\n\t\t\t\t\t}\n\t\t\t\t\tif (event.removed?.length) {\n\t\t\t\t\t\tconst allRemoved: QueryNode[] = []\n\t\t\t\t\t\tfor (const node of event.removed) {\n\t\t\t\t\t\t\tallRemoved.push(...removeInputNode(node))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (allRemoved.length) aggregated._remove(allRemoved)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}, 'derived')\n\n\t\t\treturn () => {\n\t\t\t\tprevUnsub()\n\t\t\t\tfor (const [, entry] of subsByInputNode) {\n\t\t\t\t\tentry.unsub(); entry.inner.dispose()\n\t\t\t\t}\n\t\t\t\tsubsByInputNode.clear()\n\t\t\t}\n\t\t},\n\t)\n\n\tif (VERBOSE.isEnabled) VERBOSE(`[liveQueryStep] aggregated initial:`, [...aggregated.items])\n\treturn new LiveQueryResult(aggregated)\n}, { argsDebugName: (thread, _nodes, pattern) => createDebugName({ caller: 'liveQueryStep', thread, pattern }) })\n\nexport const queryNot = memoizedFn('queryNot', function queryNot(\n\tthread: Thread,\n\tstartNodes: QueryResult,\n\tpatternOrPatterns: DatalogQueryPattern | DatalogQueryPattern[],\n\topts: { debug?: boolean } = {},\n) {\n\tconst nodes = startNodes.nodes\n\tDEBUG(`queryNot<${thread.nameAndSizeUntracked}> from: ${nodes.length} nodes`)\n\tconst patterns = (Array.isArray(patternOrPatterns) ? patternOrPatterns : [patternOrPatterns]) as DatalogQueryPattern[]\n\n\t// For each node, run all patterns as a joined multi-step query.\n\t// Exclude the node if ANY complete binding exists across all steps.\n\tconst filtered = nodes.filter(function innerNodeFilter({ variables }) {\n\t\t// Start with a single binding from the node's variables\n\t\tlet bindings: Record<string, any>[] = [variables ?? {}]\n\n\t\tfor (const pattern of patterns) {\n\t\t\tif (!Object.entries(pattern).length) throw new Error(`Pattern is empty`)\n\t\t\tconst nextBindings: Record<string, any>[] = []\n\n\t\t\tfor (const binding of bindings) {\n\t\t\t\tconst [resolved, varsToFill] = resolveOrRemoveVariables(pattern, binding)\n\t\t\t\tconst filter = makeFilter(resolved)\n\t\t\t\tconst matchingLogs = filter(thread.applogs)\n\t\t\t\tconst varMapper = createObjMapper(varsToFill)\n\n\t\t\t\tfor (const log of matchingLogs) {\n\t\t\t\t\tnextBindings.push({ ...binding, ...varMapper(log) })\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbindings = nextBindings\n\t\t\tif (bindings.length === 0) break // no matches — node is safe, skip remaining patterns\n\t\t}\n\n\t\tVERBOSE(`[queryNot] node:`, variables, '=> bindings:', bindings.length)\n\t\tif (opts.debug) LOG(`[queryNot] node result:`, variables, '=>', bindings)\n\t\treturn bindings.length === 0 // keep node if no complete match found\n\t})\n\treturn new QueryResult([...filtered])\n}, { argsDebugName: (thread, nodes, pattern) => createDebugName({ caller: 'queryNot', thread, pattern }) })\n\n/** Live variant: queryNot with incremental updates.\n * - Thread additions: O(new_applogs × included_nodes) — only checks new applogs\n * - Thread removals/resets: full recompute (rare for append-mostly logs)\n * - Upstream node additions: O(new_nodes × applogs)\n * - Upstream node removals: removed from output\n */\nexport const liveQueryNot = memoizedFn('liveQueryNot', function liveQueryNot(\n\tthread: Thread,\n\tupstream: LiveQueryResult,\n\tpatternOrPatterns: DatalogQueryPattern | DatalogQueryPattern[],\n\topts: { debug?: boolean } = {},\n) {\n\tconst patterns = (Array.isArray(patternOrPatterns) ? patternOrPatterns : [patternOrPatterns]) as DatalogQueryPattern[]\n\n\t/** Check if a node should be excluded (matches the NOT patterns as a joined multi-step query) */\n\tfunction nodeMatchesNot(node: QueryNode, applogs: readonly Applog[]): boolean {\n\t\tlet bindings: Record<string, any>[] = [node.variables ?? {}]\n\t\tfor (const pattern of patterns) {\n\t\t\tconst nextBindings: Record<string, any>[] = []\n\t\t\tfor (const binding of bindings) {\n\t\t\t\tconst [resolved, varsToFill] = resolveOrRemoveVariables(pattern, binding)\n\t\t\t\tconst filter = makeFilter(resolved)\n\t\t\t\tconst varMapper = createObjMapper(varsToFill)\n\t\t\t\tfor (const log of filter(applogs)) {\n\t\t\t\t\tnextBindings.push({ ...binding, ...varMapper(log) })\n\t\t\t\t}\n\t\t\t}\n\t\t\tbindings = nextBindings\n\t\t\tif (bindings.length === 0) return false // no matches — node passes\n\t\t}\n\t\treturn bindings.length > 0 // excluded if any complete binding exists\n\t}\n\n\t/** Full recompute: filter all upstream nodes against all thread applogs */\n\tfunction computeAll(): QueryNode[] {\n\t\treturn upstream.nodes.filter(node => !nodeMatchesNot(node, thread.applogs))\n\t}\n\n\tconst result = new SubscribableArrayImpl<QueryNode>(\n\t\tcomputeAll(),\n\t\t() => {\n\t\t\t// Subscribe to thread changes\n\t\t\tconst threadUnsub = thread.subscribe((event) => {\n\t\t\t\tif (isInitEvent(event)) {\n\t\t\t\t\t// Full reset — recompute everything\n\t\t\t\t\tresult._reset(computeAll())\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif (event.removed?.length) {\n\t\t\t\t\t// Removals: a previously-excluded node might now pass — full recompute\n\t\t\t\t\tresult._reset(computeAll())\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif (event.added.length) {\n\t\t\t\t\t// Additions: only check new applogs against currently-included nodes\n\t\t\t\t\tconst toRemove = result.items.filter(node => nodeMatchesNot(node, event.added))\n\t\t\t\t\tif (toRemove.length > 0) {\n\t\t\t\t\t\tresult._remove(toRemove)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}, 'derived')\n\n\t\t\t// Subscribe to upstream node changes\n\t\t\tconst upstreamUnsub = upstream.subscribe((event) => {\n\t\t\t\tif (isArrayInitEvent(event)) {\n\t\t\t\t\tresult._reset(computeAll())\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// New upstream nodes: check each against full thread\n\t\t\t\tif (event.added.length) {\n\t\t\t\t\tconst passing = event.added.filter(node => !nodeMatchesNot(node, thread.applogs))\n\t\t\t\t\tif (passing.length > 0) result._push(...passing)\n\t\t\t\t}\n\n\t\t\t\t// Removed upstream nodes: remove from our output\n\t\t\t\tif (event.removed?.length) {\n\t\t\t\t\tconst removedSet = new Set(event.removed)\n\t\t\t\t\tconst toRemove = result.items.filter(node => removedSet.has(node))\n\t\t\t\t\tif (toRemove.length > 0) result._remove(toRemove)\n\t\t\t\t}\n\t\t\t}, 'derived')\n\n\t\t\treturn () => { threadUnsub(); upstreamUnsub() }\n\t\t},\n\t)\n\n\treturn new LiveQueryResult(result)\n}, { argsDebugName: (thread, _nodes, pattern) => createDebugName({ caller: 'liveQueryNot', 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\n/** One-off: filter thread by pattern, map to values. Returns plain array. */\nexport const filterAndMap = memoizedFn('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\tconst filter = makeFilter(pattern)\n\tconst filtered = filter(thread.applogs)\n\treturn mapApplogsWith(filtered, mapper)\n}, { argsDebugName: (thread, pattern) => createDebugName({ caller: 'filterAndMap', thread, pattern }) })\n\n/** Live variant: returns SubscribableArray that updates when thread changes. */\nexport const liveFilterAndMap = memoizedFn('liveFilterAndMap', function liveFilterAndMap<R>(\n\tthread: Thread,\n\tpattern: DatalogQueryPattern,\n\tmapper: (keyof Applog) | (Partial<{ [key in keyof Applog]: string }>) | ((applog: Applog) => R),\n) {\n\tDEBUG(`liveFilterAndMap<${thread.nameAndSizeUntracked}>`, pattern)\n\tconst filtered = rollingFilter(thread, pattern)\n\tconst mapFn = makeApplogMapper(mapper)\n\n\tconst cidToMapped = new Map<CidString, R>()\n\tconst mapAndTrack = (log: Applog): R => {\n\t\tconst r = mapFn(log)\n\t\tcidToMapped.set(log.cid, r)\n\t\treturn r\n\t}\n\n\tconst initial = filtered.applogs.map(mapAndTrack)\n\tconst result = new SubscribableArrayImpl<R>(\n\t\tinitial,\n\t\t() => filtered.subscribe((event) => {\n\t\t\tif (isInitEvent(event)) {\n\t\t\t\tcidToMapped.clear()\n\t\t\t\tresult._reset(event.init.map(mapAndTrack))\n\t\t\t} else {\n\t\t\t\tif (event.added.length) result._push(...event.added.map(mapAndTrack))\n\t\t\t\tif (event.removed?.length) {\n\t\t\t\t\tconst toRemove: R[] = []\n\t\t\t\t\tfor (const log of event.removed) {\n\t\t\t\t\t\tconst r = cidToMapped.get(log.cid)\n\t\t\t\t\t\tif (r === undefined) {\n\t\t\t\t\t\t\tWARN(`[liveFilterAndMap] removed log not in cidToMapped`, { log })\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcidToMapped.delete(log.cid)\n\t\t\t\t\t\ttoRemove.push(r)\n\t\t\t\t\t}\n\t\t\t\t\tif (toRemove.length) result._remove(toRemove)\n\t\t\t\t}\n\t\t\t}\n\t\t}, 'derived'),\n\t)\n\treturn result\n}, { argsDebugName: (thread, pattern) => createDebugName({ caller: 'liveFilterAndMap', thread, pattern }) })\n\n/** One-off: query and map results. Returns plain array. */\nexport const queryAndMap = memoizedFn('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 queryResult = query(thread, patternOrPatterns)\n\treturn mapQueryResultWith(queryResult, mapDef)\n}, { argsDebugName: (thread, pattern) => createDebugName({ caller: 'queryAndMap', thread, pattern }) })\n\n/** Live variant: query and map results, returns SubscribableArray that updates reactively. */\nexport const liveQueryAndMap = memoizedFn('liveQueryAndMap', function liveQueryAndMap<R>(\n\tthread: Thread,\n\tpatternOrPatterns: Parameters<typeof liveQuery>[1],\n\tmapDef: string | (Partial<{ [key in keyof SearchContext]: string }>) | ((record: SearchContext) => R),\n) {\n\tDEBUG(`liveQueryAndMap<${thread.nameAndSizeUntracked}>`, { patternOrPatterns, map: mapDef })\n\tconst live = liveQuery(thread, patternOrPatterns)\n\n\tfunction computeAll(): R[] {\n\t\tconst snapshot = new QueryResult(live.nodes)\n\t\treturn mapQueryResultWith(snapshot, mapDef) as R[]\n\t}\n\n\tconst result = new SubscribableArrayImpl<R>(\n\t\tcomputeAll(),\n\t\t() => live.subscribe(() => {\n\t\t\tresult._reset(computeAll())\n\t\t}, 'derived'),\n\t)\n\treturn result\n}, { argsDebugName: (thread, pattern) => createDebugName({ caller: 'liveQueryAndMap', thread, pattern }) })\n\n/** One-off: query entity attributes. Returns Record or null. Requires current-state thread (LWW). */\nexport const queryEntity = memoizedFn('queryEntity', function queryEntity(\n\tthread: Thread,\n\tname: string,\n\tentityID: EntityID,\n\tattributes: readonly string[],\n) {\n\tassertLWW(thread)\n\tDEBUG(`queryEntity<${thread.nameAndSizeUntracked}>`, entityID, name)\n\tconst filter = makeFilter({ en: entityID, at: prefixAttrs(name, attributes) })\n\tconst filtered = filter(thread.applogs)\n\tVERBOSE(`queryEntity applogs:`, filtered)\n\tif (filtered.length === 0) return null\n\treturn Object.fromEntries(\n\t\tfiltered.map(({ at, vl }) => [at.slice(name.length + 1), vl]),\n\t)\n}, {\n\targsDebugName: (thread, name, entityID) => createDebugName({ caller: 'queryEntity', thread, args: { name, entityID } }),\n})\n\n/** Live variant: returns Subscribable that updates when entity attributes change. Requires current-state thread (LWW). */\nexport const liveQueryEntity = memoizedFn('liveQueryEntity', function liveQueryEntity(\n\tthread: Thread,\n\tname: string,\n\tentityID: EntityID,\n\tattributes: readonly string[],\n) {\n\tassertLWW(thread)\n\tDEBUG(`liveQueryEntity<${thread.nameAndSizeUntracked}>`, entityID, name)\n\tconst filtered = rollingFilter(thread, { en: entityID, at: prefixAttrs(name, attributes) })\n\n\tfunction compute() {\n\t\tif (filtered.isEmpty) return null\n\t\treturn Object.fromEntries(\n\t\t\tfiltered.map(({ at, vl }) => [at.slice(name.length + 1), vl]),\n\t\t)\n\t}\n\n\tconst result = new SubscribableImpl<Record<string, ApplogValue> | null>(\n\t\tcompute(),\n\t\t() => filtered.subscribe(() => {\n\t\t\tresult._set(compute())\n\t\t}, 'derived'),\n\t)\n\treturn result\n}, {\n\targsDebugName: (thread, name, entityID) => createDebugName({ caller: 'liveQueryEntity', thread, args: { name, entityID } }),\n})\n\n/** Live single-attribute query. Requires current-state thread (LWW). Returns Subscribable<T | null>. */\nexport const liveEntityAt = memoizedFn('liveEntityAt', function liveEntityAt<T extends ApplogValue>(\n\tthread: Thread,\n\tentityID: EntityID,\n\tat: string,\n) {\n\tassertLWW(thread)\n\tDEBUG(`liveEntityAt<${thread.nameAndSizeUntracked}>`, entityID, at)\n\tconst filtered = rollingFilter(thread, { en: entityID, at })\n\n\tfunction compute(): T | null {\n\t\tif (filtered.isEmpty) return null\n\t\treturn filtered.applogs[filtered.applogs.length - 1].vl as T\n\t}\n\n\tconst result = new SubscribableImpl<T | null>(\n\t\tcompute(),\n\t\t() => filtered.subscribe(() => {\n\t\t\tresult._set(compute())\n\t\t}, 'derived'),\n\t)\n\treturn result\n}, {\n\targsDebugName: (thread, entityID, at) => createDebugName({ caller: 'liveEntityAt', thread, args: { entityID, at } }),\n})\n\nexport const agentsOfThread = memoizedFn('agentsOfThread', function agentsOfThread(\n\tthread: Thread,\n) {\n\tDEBUG(`agentsOfThread<${thread.nameAndSizeUntracked}>`)\n\n\tconst mapped = new Map<string, number>()\n\tconst onEvent = (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\tthread.subscribe(onEvent, 'derived')\n\t// TODO: cleanup via ref-counted disposal when no longer needed\n\n\treturn mapped\n})\n\nexport const entityOverlap = memoizedFn('entityOverlap', function entityOverlapCount(\n\tthreadA: Thread,\n\tthreadB: Thread,\n) {\n\tLOG(`entityOverlap<${threadA.nameAndSizeUntracked}, ${threadB.nameAndSizeUntracked}>`)\n\n\t// Compute once — snapshot, not reactive (TODO: migrate to Subscribable)\n\tconst entitiesA = new Set(threadA.map(log => log.en))\n\tconst entitiesB = new Set(threadB.map(log => log.en))\n\treturn [...entitiesA].filter(en => entitiesB.has(en))\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)\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 = memoizedFn(\n\t'entityOverlapCount',\n\tfunction entityOverlapCount(threadA: Thread, threadB: Thread) {\n\t\treturn entityOverlap(threadA, threadB).length\n\t},\n)\n\n/** Live variant: entity overlap count as Subscribable<number>. */\nexport const liveEntityOverlapCount = memoizedFn(\n\t'liveEntityOverlapCount',\n\tfunction liveEntityOverlapCount(threadA: Thread, threadB: Thread) {\n\t\tfunction compute() {\n\t\t\tconst entitiesA = new Set(threadA.map(log => log.en))\n\t\t\tconst entitiesB = new Set(threadB.map(log => log.en))\n\t\t\treturn [...entitiesA].filter(en => entitiesB.has(en)).length\n\t\t}\n\n\t\tconst result = new SubscribableImpl<number>(\n\t\t\tcompute(),\n\t\t\t() => {\n\t\t\t\tconst unsub1 = threadA.subscribe(() => result._set(compute()), 'derived')\n\t\t\t\tconst unsub2 = threadB.subscribe(() => result._set(compute()), 'derived')\n\t\t\t\treturn () => { unsub1(); unsub2() }\n\t\t\t},\n\t\t)\n\t\treturn result\n\t},\n)\n\nexport const querySingle = memoizedFn('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\t// Snapshot — not reactive (TODO: migrate to Subscribable<Applog | null>)\n\tif (result.isEmpty) return null\n\tif (result.size > 1) throw ERROR(`[querySingle] got`, result.size, `results:`, result)\n\tconst logsOfThisNode = result.nodes[0].logsOfThisNode\n\tif (logsOfThisNode.size != 1) throw ERROR(`[querySingle] single result, but got`, logsOfThisNode.size, `logs:`, logsOfThisNode.applogs)\n\treturn logsOfThisNode.applogs[0]\n}, {\n\targsDebugName: (thread, pattern) => createDebugName({ caller: 'querySingle', thread, pattern }),\n})\n\nexport const querySingleAndMap = memoizedFn(\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 log = querySingle(threadOrLogs, patternOrPatterns, variables)\n\t\t// Snapshot — not reactive (TODO: migrate to Subscribable<T>)\n\t\tif (!log) return undefined\n\t\tif (typeof mapDef === 'string') {\n\t\t\treturn log[mapDef as string]\n\t\t} else {\n\t\t\treturn createObjMapper(mapDef)(log)\n\t\t}\n\t},\n\t{\n\t\targsDebugName: (thread, pattern) => createDebugName({ caller: 'querySingleAndMap', thread, pattern }),\n\t},\n)\n\n/** Live variant: querySingle returning Subscribable<Applog | null>. */\nexport const liveQuerySingle = memoizedFn('liveQuerySingle', function liveQuerySingle(\n\tthread: Thread,\n\tpatternOrPatterns: Parameters<typeof liveQuery>[1],\n) {\n\tDEBUG(`liveQuerySingle<${thread.nameAndSizeUntracked}>`)\n\tconst live = liveQuery(thread, patternOrPatterns)\n\n\tfunction compute(): Applog | null {\n\t\tif (live.isEmpty) return null\n\t\tif (live.size > 1) throw ERROR(`[liveQuerySingle] got`, live.size, `results`)\n\t\tconst logsOfThisNode = live.nodes[0].logsOfThisNode\n\t\tif (logsOfThisNode.size !== 1) throw ERROR(`[liveQuerySingle] single result, but got`, logsOfThisNode.size, `logs`)\n\t\treturn logsOfThisNode.applogs[0]\n\t}\n\n\tconst result = new SubscribableImpl<Applog | null>(\n\t\tcompute(),\n\t\t() => live.subscribe(() => {\n\t\t\tresult._set(compute())\n\t\t}),\n\t)\n\treturn result\n}, {\n\targsDebugName: (thread, pattern) => createDebugName({ caller: 'liveQuerySingle', thread, pattern }),\n})\n\n/** Live variant: querySingleAndMap returning Subscribable<T | undefined>. */\nexport const liveQuerySingleAndMap = memoizedFn(\n\t'liveQuerySingleAndMap',\n\tfunction liveQuerySingleAndMap<MAP extends (keyof Applog | (Partial<{ [key in keyof Applog]: string }>))>(\n\t\tthread: Thread,\n\t\tpatternOrPatterns: Parameters<typeof liveQuery>[1],\n\t\tmapDef: MAP,\n\t) {\n\t\tDEBUG(`liveQuerySingleAndMap<${thread.nameAndSizeUntracked}>`)\n\t\tconst liveSingle = liveQuerySingle(thread, patternOrPatterns)\n\n\t\tfunction compute() {\n\t\t\tconst log = liveSingle.value\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\n\t\tconst result = new SubscribableImpl<any>(\n\t\t\tcompute(),\n\t\t\t() => liveSingle.subscribe(() => {\n\t\t\t\tresult._set(compute())\n\t\t\t}),\n\t\t)\n\t\treturn result\n\t},\n\t{\n\t\targsDebugName: (thread, pattern) => createDebugName({ caller: 'liveQuerySingleAndMap', thread, pattern }),\n\t},\n)\n\n/////////////\n// HELPERS //\n/////////////\n\n/** Create a single-applog mapper function from a mapDef */\nexport function makeApplogMapper<R>(\n\tmapDef: (keyof Applog) | (Partial<{ [key in keyof Applog]: string }>) | ((applog: Applog) => R),\n): (applog: Applog) => R {\n\tif (typeof mapDef === 'function') {\n\t\treturn mapDef as (applog: Applog) => R\n\t} else if (typeof mapDef === 'string') {\n\t\treturn (log: Applog) => log[mapDef] as R\n\t} else {\n\t\treturn createObjMapper(mapDef) as (applog: Applog) => R\n\t}\n}\n\n/** Map an array of applogs using a mapDef */\nexport function mapApplogsWith<R>(\n\tapplogs: readonly Applog[],\n\tmapDef: (keyof Applog) | (Partial<{ [key in keyof Applog]: string }>) | ((applog: Applog) => R),\n) {\n\treturn applogs.map(makeApplogMapper(mapDef))\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\treturn mapApplogsWith(thread.applogs, mapDef)\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)(node.record)\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}\n\n/** Inverse of prefixAt — strips everything up to and including the first `/` */\nexport function stripAtPrefix(attr: string): string {\n\tconst idx = attr.indexOf('/')\n\treturn idx >= 0 ? attr.slice(idx + 1) : attr\n}\n\n/** Create a key mapper from an explicit attribute→key record */\nexport function mapAttributes<A extends string>(mapping: Record<A, string>): (attr: A) => string {\n\treturn (attr) => mapping[attr] ?? attr\n}\n\n/** Resolve key mapping options to a concrete mapper function */\nexport function resolveKeyMapper(opts?: { stripAtPrefix?: true | string; mapKeys?: (attr: string) => string }): (attr: string) => string {\n\tif (!opts) return (attr) => attr\n\tif (opts.mapKeys) return opts.mapKeys\n\tif (opts.stripAtPrefix === true) return stripAtPrefix\n\tif (typeof opts.stripAtPrefix === 'string') {\n\t\tconst prefix = opts.stripAtPrefix + '/'\n\t\treturn (attr) => attr.startsWith(prefix) ? attr.slice(prefix.length) : attr\n\t}\n\treturn (attr) => 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}\nfunction getPatternVariableNames(pattern: DatalogQueryPattern): Set<string> {\n\tconst vars = new Set<string>()\n\tfor (const value of Object.values(pattern)) {\n\t\tif (isVariable(value)) {\n\t\t\tvars.add((value as string).slice(1))\n\t\t}\n\t}\n\treturn vars\n}\n\n/**\n * Warn if a multi-step query has steps that are not connected via shared variables.\n * Disconnected steps produce a cartesian product instead of a join.\n */\nfunction warnIfDisjointQuerySteps(patterns: DatalogQueryPattern[]) {\n\tif (patterns.length < 2) return\n\n\tconst varSets = patterns.map(getPatternVariableNames)\n\tconst reachable = new Set(varSets[0])\n\n\tfor (let i = 1; i < varSets.length; i++) {\n\t\tconst stepVars = varSets[i]\n\t\tif (stepVars.size === 0) {\n\t\t\tWARN(\n\t\t\t\t`[query] Step ${i} has no variables — it produces identical results regardless of previous steps (cartesian product).`,\n\t\t\t\t`Patterns:`, patterns,\n\t\t\t)\n\t\t\tcontinue\n\t\t}\n\t\tconst connected = [...stepVars].some(v => reachable.has(v))\n\t\tif (!connected) {\n\t\t\tWARN(\n\t\t\t\t`[query] Step ${i} is disconnected from previous steps — no shared variable.`,\n\t\t\t\t`This produces a cartesian product instead of a join.`,\n\t\t\t\t`Step ${i} variables: {${[...stepVars].join(', ')}}`,\n\t\t\t\t`Reachable from prior steps: {${[...reachable].join(', ')}}`,\n\t\t\t\t`Patterns:`, patterns,\n\t\t\t)\n\t\t}\n\t\tfor (const v of stepVars) reachable.add(v)\n\t}\n}\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","thread","liveQuery","liveQueryStep","queryNot","liveQueryNot","filterAndMap","liveFilterAndMap","queryAndMap","liveQueryAndMap","queryEntity","liveQueryEntity","liveEntityAt","agentsOfThread","entityOverlapMap","entityOverlapCount","liveEntityOverlapCount","querySingle","querySingleAndMap","liveQuerySingle","liveQuerySingleAndMap","filterAndMapGetterFx"]}
|
|
1
|
+
{"version":3,"sources":["../src/query/types.ts","../src/query/basic.ts"],"sourcesContent":["import { joinThreads } from '../applog/applog-helpers.ts'\nimport { SearchContext } from '../applog/datom-types.ts'\nimport type { Thread } from '../thread/basic.ts'\nimport { ArrayEvent, SubscribableArray, SubscribableArrayImpl, Unsubscribe } from './subscribable.ts'\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\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/** Shared interface for query results (one-off and live) */\nexport interface IQueryResult {\n\treadonly nodes: readonly QueryNode[]\n\treadonly size: number\n\treadonly isEmpty: boolean\n\treadonly records: readonly SearchContext[]\n\treadonly leafNodeLogs: readonly import('../applog/datom-types').Applog[]\n\treadonly leafNodeThread: Thread\n\treadonly threadOfAllTrails: Thread\n\treadonly thread: Thread\n\treadonly allApplogs: readonly import('../applog/datom-types').Applog[]\n}\n\n/**\n * One-off query result — plain frozen snapshot.\n * No subscribe method. No stale-data risk.\n */\nexport class QueryResult implements IQueryResult {\n\tconstructor(\n\t\treadonly nodes: readonly QueryNode[],\n\t) {}\n\n\tget size() {\n\t\treturn this.nodes.length\n\t}\n\tget isEmpty() {\n\t\treturn this.nodes.length === 0\n\t}\n\tget untrackedSize() {\n\t\treturn this.nodes.length\n\t}\n\n\tget records(): readonly SearchContext[] {\n\t\treturn this.nodes.map(({ variables }) => variables)\n\t}\n\tget leafNodeThread() {\n\t\treturn joinThreads(\n\t\t\tthis.nodes.map(({ logsOfThisNode: thread }) => thread),\n\t\t)\n\t}\n\tget leafNodeLogSet() {\n\t\treturn this.nodes.map(({ logsOfThisNode: thread }) => thread.applogs)\n\t}\n\tget leafNodeLogs() {\n\t\treturn this.nodes.flatMap(({ logsOfThisNode: thread }) => thread.applogs)\n\t}\n\tget threadOfAllTrails() {\n\t\treturn joinThreads(this.nodes.map(node => node.threadOfTrail))\n\t}\n\tget thread() {\n\t\treturn this.threadOfAllTrails // alias\n\t}\n\tget allApplogs() {\n\t\treturn this.threadOfAllTrails.applogs\n\t}\n}\n\n/**\n * Live query result — eagerly activated, always up-to-date.\n *\n * `.nodes` returns the current live view.\n * `.subscribe()` receives future delta events (consistent with current state).\n * Must call `.dispose()` when done to tear down upstream subscriptions.\n */\nexport class LiveQueryResult implements IQueryResult {\n\tconstructor(\n\t\tprivate _source: SubscribableArray<QueryNode>,\n\t\tactivate = true,\n\t) {\n\t\tif (activate) {\n\t\t\t// Eagerly activate: subscribe with a no-op to start upstream.\n\t\t\t// Store unsub so dispose() can tear it down.\n\t\t\tthis._activationUnsub = this._source.subscribe(() => {})\n\t\t}\n\t}\n\n\tprivate _activationUnsub: Unsubscribe | null = null\n\n\t/** Subscribe to node change events. Callback fires on future changes only. */\n\tsubscribe(cb: (event: ArrayEvent<QueryNode>) => void, type?: 'derived' | 'reaction'): Unsubscribe {\n\t\treturn this._source.subscribe(cb, type)\n\t}\n\n\t/** Current nodes — live view, always up-to-date while not disposed */\n\tget nodes(): readonly QueryNode[] {\n\t\treturn this._source.items\n\t}\n\n\tget size() {\n\t\treturn this._source.length\n\t}\n\tget isEmpty() {\n\t\treturn this._source.length === 0\n\t}\n\tget untrackedSize() {\n\t\treturn this._source.length\n\t}\n\n\tget records(): readonly SearchContext[] {\n\t\treturn this.nodes.map(({ variables }) => variables)\n\t}\n\tget leafNodeThread() {\n\t\treturn joinThreads(\n\t\t\tthis.nodes.map(({ logsOfThisNode: thread }) => thread),\n\t\t)\n\t}\n\tget leafNodeLogSet() {\n\t\treturn this.nodes.map(({ logsOfThisNode: thread }) => thread.applogs)\n\t}\n\tget leafNodeLogs() {\n\t\treturn this.nodes.flatMap(({ logsOfThisNode: thread }) => thread.applogs)\n\t}\n\tget threadOfAllTrails() {\n\t\treturn joinThreads(this.nodes.map(node => node.threadOfTrail))\n\t}\n\tget thread() {\n\t\treturn this.threadOfAllTrails // alias\n\t}\n\tget allApplogs() {\n\t\treturn this.threadOfAllTrails.applogs\n\t}\n\n\tdispose() {\n\t\tthis._activationUnsub?.()\n\t\tthis._activationUnsub = null\n\t\tthis._source.dispose()\n\t}\n}\n","import { AgentHash, Applog, ApplogValue, CidString, DatalogQueryPattern, EntityID, SearchContext, ValueOrMatcher } from '../applog/datom-types.ts'\n\nimport { Logger } from 'besonders-logger'\n\nimport { isEmpty } from 'lodash-es'\nimport stringify from 'safe-stable-stringify'\nimport { isLaterByTsAndPv, isoDateStrCompare, isVariable, resolveOrRemoveVariables, sortApplogsByTs } from '../applog/applog-utils.ts'\nimport { createDebugName } from '../utils/debug-name.ts'\nimport { isInitEvent, StaticThread, Thread, ThreadEvent } from '../thread/basic.ts'\nimport { hasFilter, makeFilter, rollingFilter, rollingMapper, ThreadOnlyCurrent } from '../thread/filters.ts'\nimport { applogsByEntity } from '../thread/indexes.ts'\nimport { MappedThread, type ThreadDerivation } from '../thread/mapped.ts'\nimport { ThreadInMemory } from '../thread/writeable.ts'\nimport { memoizedFn } from './memoized.ts'\nimport { isArrayInitEvent, SubscribableArray, SubscribableArrayImpl, SubscribableImpl, Unsubscribe } from './subscribable.ts'\nimport { LiveQueryResult, QueryNode, QueryResult } from './types.ts'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO, { prefix: '[q]' }) // eslint-disable-line no-unused-vars\n\nfunction assertLWW(thread: Thread) {\n\tif (!hasFilter(thread, 'lastWriteWins')) {\n\t\tthrow ERROR(`requires lastWriteWins-filtered thread, got filters:`, thread.filters, { name: thread.name })\n\t}\n}\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 = memoizedFn('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\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\n\t/**\n\t * Iterate `newLogs` (already chain-aware-sorted by `sortApplogsByTs`) updating\n\t * `rollingMap` to hold the LWW winner per (en|at) key. Uses `isLaterByTsAndPv`\n\t * — pairwise pv-aware predicate — so cross-batch comparisons in mapDelta also\n\t * stay deterministic when same-ts chain links collide.\n\t */\n\tconst processLogs = (newLogs: readonly Applog[], toRemove: Applog[] | null): Applog[] => {\n\t\tconst toAdd = [] as Applog[]\n\t\tlet prevTs: string | undefined\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\n\n\t\t\tif (prevTs !== undefined) {\n\t\t\t\tconst cmp = isoDateStrCompare(prevTs, log.ts)\n\t\t\t\tif (inverseToOnlyReturnFirstLogs ? cmp > 0 : cmp < 0) {\n\t\t\t\t\tthrow ERROR(`lastWriteWins.processLogs logs not ts-sorted:`, prevTs, inverseToOnlyReturnFirstLogs ? '>' : '<', log.ts, {\n\t\t\t\t\t\tlog,\n\t\t\t\t\t\ti,\n\t\t\t\t\t\tnewLogs,\n\t\t\t\t\t\tinverseToOnlyReturnFirstLogs,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\tprevTs = log.ts\n\n\t\t\tconst existing = rollingMap.get(key)\n\t\t\tconst replaces = !existing || (inverseToOnlyReturnFirstLogs\n\t\t\t\t? isLaterByTsAndPv(existing, log)\n\t\t\t\t: isLaterByTsAndPv(log, existing))\n\t\t\tif (replaces) {\n\t\t\t\tif (existing && toRemove) 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\treturn toAdd\n\t}\n\n\tconst lwwName = `lastWriteWins${inverseToOnlyReturnFirstLogs ? '.inversed' : ''}`\n\tconst derivation: ThreadDerivation = {\n\t\tcompute(parents) {\n\t\t\tif (parents.length !== 1) {\n\t\t\t\tthrow ERROR(`${lwwName} requires exactly one parent`, { parents: parents.length })\n\t\t\t}\n\t\t\tconst [parent] = parents\n\t\t\trollingMap = new Map()\n\t\t\tconst toAdd = processLogs(parent.applogs, null)\n\t\t\tsortApplogsByTs(toAdd)\n\t\t\tVERBOSE.isDisabled || VERBOSE(`${lwwName}<${thread.nameAndSizeUntracked}> compute`, { toAdd: toAdd.length })\n\t\t\treturn toAdd\n\t\t},\n\t\tmapDelta(delta) {\n\t\t\tconst toRemove = [] as Applog[]\n\t\t\tconst toAdd = processLogs(delta.added, toRemove)\n\t\t\tsortApplogsByTs(toAdd)\n\t\t\tVERBOSE.isDisabled || VERBOSE(`${lwwName}<${thread.nameAndSizeUntracked}> mapDelta`, { ...delta, toAdd, toRemove })\n\t\t\treturn { added: toAdd, removed: toRemove }\n\t\t},\n\t}\n\tconst mappedThread = rollingMapper(thread, derivation, { name: lwwName, extraFilterName: 'lastWriteWins' })\n\tVERBOSE.isDisabled || VERBOSE(`lastWriteWins<${thread.nameAndSizeUntracked}> filtered down to`, mappedThread.applogs.length)\n\treturn mappedThread as ThreadOnlyCurrent\n}, { argsDebugName: (thread) => createDebugName({ caller: 'lastWriteWins', thread }) })\n\nconst isDeletedAttrs = ['isDeleted', 'relation/isDeleted', 'block/isDeleted']\nfunction isDeletionLog(log: Applog) {\n\treturn log.vl === true && isDeletedAttrs.includes(log.at)\n}\n\n/**\n * Remove all applogs for entities that have an applog `{ at: 'isDeleted' | 'relation/isDeleted' | 'block/isDeleted', vl: true }`.\n *\n * Emits synthetic `removed` events for the entity's pre-existing applogs when an\n * entity becomes deleted (and synthetic `added` events for un-deletion).\n *\n * Un-deletion: canonical input is appending `{ at: 'isDeleted', vl: false }`. Requires\n * `lastWriteWins` upstream — without it, the `vl: true` log isn't superseded so we\n * can't observe a transition. Soft-warned at runtime.\n */\nexport const withoutDeleted = memoizedFn('withoutDeleted', function withoutDeleted(\n\tthread: Thread,\n) {\n\tif (VERBOSE.isEnabled) VERBOSE(`withoutDeleted<${thread.nameAndSizeUntracked}>`)\n\tif (thread.filters.includes('withoutDeleted')) {\n\t\tthrow ERROR(`thread already filtered withoutDeleted:`, thread.filters, { name: thread.name })\n\t}\n\tif (!thread.filters.includes('lastWriteWins')) {\n\t\tWARN(`withoutDeleted on non-lastWriteWins thread: un-deletion (isDeleted: false) won't take effect`, { thread: thread.name })\n\t}\n\n\t// FIFO contract: byEntity must subscribe to `thread` BEFORE `result` does, so the index\n\t// is up-to-date when our mapper runs. Calling applogsByEntity here forces that order;\n\t// memoization makes it idempotent if other code already subscribed.\n\tconst byEntity = applogsByEntity(thread)\n\n\t// Per-entity count of currently-active isDeleted-class logs. 0→1 = entity becomes hidden;\n\t// 1→0 = entity becomes visible. Handles multiple isDeleted-class attrs per entity.\n\tconst activeDeletionMarkers = new Map<EntityID, number>()\n\tfor (const log of thread.applogs) {\n\t\tif (isDeletionLog(log)) {\n\t\t\tactiveDeletionMarkers.set(log.en, (activeDeletionMarkers.get(log.en) ?? 0) + 1)\n\t\t}\n\t}\n\tconst isHidden = (en: EntityID) => activeDeletionMarkers.has(en)\n\n\tconst derivation: ThreadDerivation = {\n\t\tcompute(parents) {\n\t\t\tif (parents.length !== 1) throw ERROR(`withoutDeleted requires exactly one parent`, { parents: parents.length })\n\t\t\tconst [parent] = parents\n\t\t\tactiveDeletionMarkers.clear()\n\t\t\tfor (const log of parent.applogs) {\n\t\t\t\tif (isDeletionLog(log)) {\n\t\t\t\t\tactiveDeletionMarkers.set(log.en, (activeDeletionMarkers.get(log.en) ?? 0) + 1)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn parent.applogs.filter(log => !isHidden(log.en))\n\t\t},\n\t\tmapDelta: (delta) => {\n\t\t\t// Snapshot of which entities were hidden BEFORE this delta. Required because\n\t\t\t// pass-through correctness depends on prior visibility (logs of pre-hidden\n\t\t\t// entities were never in result, so they must not appear in `removed`),\n\t\t\t// while the post-mutation `isHidden` state determines whether new content\n\t\t\t// should be admitted. Filtering only on post-mutation state breaks both\n\t\t\t// W→N (stale isDeleted=true log slips into removed → MappedThread crash)\n\t\t\t// and F→D-with-content-removal (legitimate content removal gets filtered).\n\t\t\tconst hiddenBefore = new Set(activeDeletionMarkers.keys())\n\t\t\tconst entitiesNowHidden: EntityID[] = []\n\t\t\tconst entitiesNowVisible: EntityID[] = []\n\n\t\t\tfor (const log of delta.added) {\n\t\t\t\tif (!isDeletionLog(log)) continue\n\t\t\t\tconst prev = activeDeletionMarkers.get(log.en) ?? 0\n\t\t\t\tactiveDeletionMarkers.set(log.en, prev + 1)\n\t\t\t\tif (prev === 0) entitiesNowHidden.push(log.en)\n\t\t\t}\n\t\t\tif (delta.removed) {\n\t\t\t\tfor (const log of delta.removed) {\n\t\t\t\t\tif (!isDeletionLog(log)) continue\n\t\t\t\t\tconst prev = activeDeletionMarkers.get(log.en) ?? 0\n\t\t\t\t\tconst next = prev - 1\n\t\t\t\t\tif (next > 0) activeDeletionMarkers.set(log.en, next)\n\t\t\t\t\telse {\n\t\t\t\t\t\tactiveDeletionMarkers.delete(log.en)\n\t\t\t\t\t\tentitiesNowVisible.push(log.en)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Synthetic removals: applogs of newly-hidden entities currently in result.\n\t\t\t// byEntity index is updated for this tick already (FIFO), so we filter out\n\t\t\t// applogs added in this very tick (they were never in result).\n\t\t\tconst newAddedSet = new Set(delta.added)\n\t\t\tconst syntheticRemovals: Applog[] = []\n\t\t\tfor (const en of entitiesNowHidden) {\n\t\t\t\tconst applogs = byEntity.get(en)\n\t\t\t\tif (!applogs) continue\n\t\t\t\tfor (const log of applogs) {\n\t\t\t\t\tif (!newAddedSet.has(log)) syntheticRemovals.push(log)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Synthetic additions: all current parent applogs of newly-visible entities.\n\t\t\tconst syntheticAdditions: Applog[] = []\n\t\t\tfor (const en of entitiesNowVisible) {\n\t\t\t\tconst applogs = byEntity.get(en)\n\t\t\t\tif (applogs) syntheticAdditions.push(...applogs)\n\t\t\t}\n\n\t\t\t// Pass-through: a parent log goes through to subscribers iff the entity\n\t\t\t// wasn't hidden before AND isn't hidden now. Transitions are owned by the\n\t\t\t// synthetic streams above.\n\t\t\tconst passAdded = delta.added.filter(log =>\n\t\t\t\t!hiddenBefore.has(log.en) && !isHidden(log.en))\n\t\t\tconst passRemoved = delta.removed?.filter(log =>\n\t\t\t\t!hiddenBefore.has(log.en)) ?? []\n\n\t\t\treturn {\n\t\t\t\tadded: [...passAdded, ...syntheticAdditions],\n\t\t\t\tremoved: [...passRemoved, ...syntheticRemovals],\n\t\t\t}\n\t\t},\n\t}\n\tconst result = rollingMapper(thread, derivation, { name: 'withoutDeleted', extraFilterName: 'withoutDeleted' })\n\n\treturn result\n})\n\n///////////////////////////\n// ONE-OFF QUERY (snapshot) //\n///////////////////////////\n\n/** Shared helper: create a QueryNode from a log and its context */\nfunction makeQueryNode(\n\tlog: Applog,\n\tparentNode: QueryNode | null,\n\tvarMapper: (log: Applog) => SearchContext,\n\tthreadName: string,\n): QueryNode {\n\tconst nodeVars = Object.assign({}, parentNode?.variables, varMapper(log))\n\treturn new QueryNode(\n\t\tStaticThread.fromArray([log], threadName),\n\t\tnodeVars,\n\t\tparentNode,\n\t)\n}\n\n/**\n * One-off query — returns a plain snapshot. No subscriptions, no stale-data risk.\n */\nexport const query = memoizedFn('query', function query(\n\tthreadOrLogs: Thread | Applog[],\n\tpatternOrPatterns: DatalogQueryPattern | DatalogQueryPattern[],\n\tstartVariables: SearchContext = {},\n\topts: { debug?: boolean } = {},\n): QueryResult {\n\tthrowOnTimeout()\n\tconst thread = threadFromMaybeArray(threadOrLogs)\n\tDEBUG(`query<${thread.nameAndSizeUntracked}>:`, patternOrPatterns)\n\tconst patterns = (Array.isArray(patternOrPatterns) ? patternOrPatterns : [patternOrPatterns]) as DatalogQueryPattern[]\n\twarnIfDisjointQuerySteps(patterns)\n\n\tlet prevNodes: readonly QueryNode[] | null\n\tif (patterns.length === 1) {\n\t\tprevNodes = null\n\t} else {\n\t\tconst patternsExceptLast = patterns.slice(0, -1)\n\t\tprevNodes = query(thread, patternsExceptLast, startVariables, opts).nodes\n\t}\n\tconst lastPattern = patterns[patterns.length - 1]\n\tconst stepResult = queryStepOnce(thread, prevNodes, lastPattern, opts)\n\tVERBOSE.isDisabled || VERBOSE(`query result:`, stepResult.nodes)\n\treturn stepResult\n}, {\n\targsDebugName: (thread, pattern, startVars) =>\n\t\tcreateDebugName({ caller: 'query', thread, args: startVars ? { pattern, startVars } : pattern }),\n})\n\n/**\n * One-off query step — pure filtering via makeFilter, no subscriptions.\n */\nexport function queryStepOnce(\n\tthread: Thread,\n\tprevNodes: readonly QueryNode[] | null,\n\tpattern: DatalogQueryPattern,\n\topts: { debug?: boolean } = {},\n): QueryResult {\n\tDEBUG(`queryStepOnce<${thread.nameAndSizeUntracked}> with`, prevNodes?.length ?? 'all', 'nodes, pattern:', pattern)\n\tif (!Object.entries(pattern).length) throw new Error(`Pattern is empty`)\n\n\tfunction doQueryOnce(node: QueryNode | null): QueryNode[] {\n\t\tconst [patternWithResolvedVars, variablesToFill] = resolveOrRemoveVariables(pattern, node?.variables ?? {})\n\t\tVERBOSE(`[queryStepOnce.doQuery] patternWithoutVars: `, patternWithResolvedVars)\n\t\tconst filter = makeFilter(patternWithResolvedVars)\n\t\tconst matchingLogs = filter(thread.applogs)\n\t\tconst varMapper = createObjMapper(variablesToFill)\n\n\t\tconst nodes = matchingLogs.map(log => makeQueryNode(\n\t\t\tlog, node, varMapper,\n\t\t\tcreateDebugName({\n\t\t\t\tcaller: 'QueryNode',\n\t\t\t\tthread,\n\t\t\t\tpattern: `${stringify(Object.assign({}, node?.variables, varMapper(log)))}@${stringify(patternWithResolvedVars)}`,\n\t\t\t}),\n\t\t))\n\n\t\tif (VERBOSE.isEnabled) VERBOSE(`[queryStepOnce.doQuery] nodes:`, nodes.map(n => n.variables))\n\t\tif (opts.debug) {\n\t\t\tLOG(`[queryStepOnce] step result:`, nodes.map(({ variables, logsOfThisNode: thread }) => ({\n\t\t\t\tvariables,\n\t\t\t\tthread,\n\t\t\t})))\n\t\t}\n\n\t\treturn nodes\n\t}\n\n\tif (!prevNodes) {\n\t\treturn new QueryResult(doQueryOnce(null))\n\t}\n\n\tconst allNodes = prevNodes.flatMap(inputNode => doQueryOnce(inputNode))\n\treturn new QueryResult(allNodes)\n}\n\n///////////////////////////\n// LIVE QUERY (reactive) //\n///////////////////////////\n\n/**\n * Live query — eagerly activated, always up-to-date.\n * Returns LiveQueryResult with subscribe + dispose.\n */\nexport const liveQuery = memoizedFn('liveQuery', function liveQuery(\n\tthreadOrLogs: Thread | Applog[],\n\tpatternOrPatterns: DatalogQueryPattern | DatalogQueryPattern[],\n\tstartVariables: SearchContext = {},\n\topts: { debug?: boolean } = {},\n): LiveQueryResult {\n\tthrowOnTimeout()\n\tconst thread = threadFromMaybeArray(threadOrLogs)\n\tDEBUG(`liveQuery<${thread.nameAndSizeUntracked}>:`, patternOrPatterns)\n\tconst patterns = (Array.isArray(patternOrPatterns) ? patternOrPatterns : [patternOrPatterns]) as DatalogQueryPattern[]\n\n\tlet prevResult: LiveQueryResult | null\n\tif (patterns.length === 1) {\n\t\tprevResult = null\n\t} else {\n\t\tconst patternsExceptLast = patterns.slice(0, -1)\n\t\tprevResult = liveQuery(thread, patternsExceptLast, startVariables, opts)\n\t}\n\tconst lastPattern = patterns[patterns.length - 1]\n\tconst stepResult = liveQueryStep(thread, prevResult, lastPattern, opts)\n\tVERBOSE.isDisabled || VERBOSE(`liveQuery result:`, stepResult.nodes)\n\treturn stepResult\n}, {\n\targsDebugName: (thread, pattern, startVars) =>\n\t\tcreateDebugName({ caller: 'liveQuery', thread, args: startVars ? { pattern, startVars } : pattern }),\n})\n\nexport const liveQueryStep = memoizedFn('liveQueryStep', function liveQueryStep(\n\tthread: Thread,\n\tnodeSet: LiveQueryResult | null,\n\tpattern: DatalogQueryPattern,\n\topts: { debug?: boolean } = {},\n): LiveQueryResult {\n\tDEBUG(`liveQueryStep<${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): SubscribableArray<QueryNode> {\n\t\tconst [patternWithResolvedVars, variablesToFill] = resolveOrRemoveVariables(pattern, node?.variables ?? {})\n\t\tVERBOSE(`[liveQueryStep.doQuery] patternWithoutVars: `, patternWithResolvedVars)\n\t\tconst applogsMatchingStatic = rollingFilter(thread, patternWithResolvedVars)\n\t\tconst varMapper = createObjMapper(variablesToFill)\n\n\t\tfunction makeNode(log: Applog): QueryNode {\n\t\t\treturn makeQueryNode(\n\t\t\t\tlog, node, varMapper,\n\t\t\t\tcreateDebugName({\n\t\t\t\t\tcaller: 'QueryNode',\n\t\t\t\t\tthread: applogsMatchingStatic,\n\t\t\t\t\tpattern: `${stringify(Object.assign({}, node?.variables, varMapper(log)))}@${stringify(patternWithResolvedVars)}`,\n\t\t\t\t}),\n\t\t\t)\n\t\t}\n\n\t\t// Compute initial result synchronously\n\t\tconst initialNodes = applogsMatchingStatic.applogs.map(makeNode)\n\n\t\tif (VERBOSE.isEnabled) VERBOSE(`[liveQueryStep.doQuery] initial nodes:`, initialNodes.map(n => n.variables))\n\t\tif (opts.debug) {\n\t\t\tLOG(`[liveQueryStep] step result:`, initialNodes.map(({ variables, logsOfThisNode: thread }) => ({\n\t\t\t\tvariables,\n\t\t\t\tthread,\n\t\t\t})))\n\t\t}\n\n\t\t// Upstream subscription activates lazily — only when someone subscribes to us\n\t\tconst result = new SubscribableArrayImpl<QueryNode>(\n\t\t\tinitialNodes,\n\t\t\t() => applogsMatchingStatic.subscribe((event) => {\n\t\t\t\tif (isInitEvent(event)) {\n\t\t\t\t\tresult._reset(event.init.map(makeNode))\n\t\t\t\t} else {\n\t\t\t\t\tif (event.added.length) {\n\t\t\t\t\t\tresult._push(...event.added.map(makeNode))\n\t\t\t\t\t}\n\t\t\t\t\tif (event.removed?.length) {\n\t\t\t\t\t\tconst removedCids = new Set(event.removed.map(log => log.cid))\n\t\t\t\t\t\tconst toRemove = result.items.filter(qn =>\n\t\t\t\t\t\t\tremovedCids.has(qn.logsOfThisNode.applogs[0]?.cid)\n\t\t\t\t\t\t)\n\t\t\t\t\t\tif (toRemove.length) result._remove(toRemove)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}, 'derived'),\n\t\t)\n\t\treturn result\n\t}\n\n\t// ── Single-step query (nodeSet === null) ──────────────────────\n\tif (!nodeSet) {\n\t\treturn new LiveQueryResult(doQuery(null))\n\t}\n\n\t// ── Multi-step query (nodeSet !== null) ────────────────────────\n\n\t// Compute initial result synchronously\n\tconst initialInners = nodeSet.nodes.map(inputNode => ({\n\t\tinputNode,\n\t\tinner: doQuery(inputNode),\n\t}))\n\tconst initialItems = initialInners.flatMap(({ inner }) => [...inner.items])\n\n\t// Lazy activation: upstream subscriptions only created when someone subscribes\n\tconst aggregated = new SubscribableArrayImpl<QueryNode>(\n\t\tinitialItems,\n\t\t() => {\n\t\t\tconst subsByInputNode = new Map<QueryNode, {\n\t\t\t\tinner: SubscribableArray<QueryNode>,\n\t\t\t\tunsub: Unsubscribe,\n\t\t\t\tnodes: QueryNode[],\n\t\t\t}>()\n\n\t\t\tfunction wireInner(inputNode: QueryNode, inner: SubscribableArray<QueryNode>): QueryNode[] {\n\t\t\t\tconst entry = { inner, unsub: null! as Unsubscribe, nodes: [...inner.items] }\n\n\t\t\t\tentry.unsub = inner.subscribe((event) => {\n\t\t\t\t\tif (isArrayInitEvent(event)) {\n\t\t\t\t\t\tif (entry.nodes.length) aggregated._remove(entry.nodes)\n\t\t\t\t\t\tentry.nodes = [...event.init]\n\t\t\t\t\t\tif (entry.nodes.length) aggregated._push(...entry.nodes)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (event.added.length) {\n\t\t\t\t\t\t\tentry.nodes.push(...event.added)\n\t\t\t\t\t\t\taggregated._push(...event.added)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (event.removed?.length) {\n\t\t\t\t\t\t\tfor (const r of event.removed) {\n\t\t\t\t\t\t\t\tconst idx = entry.nodes.indexOf(r)\n\t\t\t\t\t\t\t\tif (idx >= 0) entry.nodes.splice(idx, 1)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\taggregated._remove(event.removed)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}, 'derived')\n\n\t\t\t\tsubsByInputNode.set(inputNode, entry)\n\t\t\t\treturn entry.nodes\n\t\t\t}\n\n\t\t\tfunction addInputNode(inputNode: QueryNode): QueryNode[] {\n\t\t\t\treturn wireInner(inputNode, doQuery(inputNode))\n\t\t\t}\n\n\t\t\tfunction removeInputNode(inputNode: QueryNode): QueryNode[] {\n\t\t\t\tconst entry = subsByInputNode.get(inputNode)\n\t\t\t\tif (!entry) return []\n\t\t\t\tentry.unsub()\n\t\t\t\tentry.inner.dispose()\n\t\t\t\tconst removed = entry.nodes\n\t\t\t\tsubsByInputNode.delete(inputNode)\n\t\t\t\treturn removed\n\t\t\t}\n\n\t\t\t// Reuse pre-computed inners (no re-creation of sub-queries)\n\t\t\tfor (const { inputNode, inner } of initialInners) {\n\t\t\t\twireInner(inputNode, inner)\n\t\t\t}\n\n\t\t\t// Subscribe to previous step for FUTURE changes only (no init)\n\t\t\tconst prevUnsub = nodeSet.subscribe((event) => {\n\t\t\t\tif (isArrayInitEvent(event)) {\n\t\t\t\t\tfor (const [, entry] of subsByInputNode) {\n\t\t\t\t\t\tentry.unsub(); entry.inner.dispose()\n\t\t\t\t\t}\n\t\t\t\t\tsubsByInputNode.clear()\n\t\t\t\t\tconst allNodes: QueryNode[] = []\n\t\t\t\t\tfor (const node of event.init) {\n\t\t\t\t\t\tallNodes.push(...addInputNode(node))\n\t\t\t\t\t}\n\t\t\t\t\taggregated._reset(allNodes)\n\t\t\t\t} else {\n\t\t\t\t\tif (event.added.length) {\n\t\t\t\t\t\tconst allAdded: QueryNode[] = []\n\t\t\t\t\t\tfor (const node of event.added) {\n\t\t\t\t\t\t\tallAdded.push(...addInputNode(node))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (allAdded.length) aggregated._push(...allAdded)\n\t\t\t\t\t}\n\t\t\t\t\tif (event.removed?.length) {\n\t\t\t\t\t\tconst allRemoved: QueryNode[] = []\n\t\t\t\t\t\tfor (const node of event.removed) {\n\t\t\t\t\t\t\tallRemoved.push(...removeInputNode(node))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (allRemoved.length) aggregated._remove(allRemoved)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}, 'derived')\n\n\t\t\treturn () => {\n\t\t\t\tprevUnsub()\n\t\t\t\tfor (const [, entry] of subsByInputNode) {\n\t\t\t\t\tentry.unsub(); entry.inner.dispose()\n\t\t\t\t}\n\t\t\t\tsubsByInputNode.clear()\n\t\t\t}\n\t\t},\n\t)\n\n\tif (VERBOSE.isEnabled) VERBOSE(`[liveQueryStep] aggregated initial:`, [...aggregated.items])\n\treturn new LiveQueryResult(aggregated)\n}, { argsDebugName: (thread, _nodes, pattern) => createDebugName({ caller: 'liveQueryStep', thread, pattern }) })\n\nexport const queryNot = memoizedFn('queryNot', function queryNot(\n\tthread: Thread,\n\tstartNodes: QueryResult,\n\tpatternOrPatterns: DatalogQueryPattern | DatalogQueryPattern[],\n\topts: { debug?: boolean } = {},\n) {\n\tconst nodes = startNodes.nodes\n\tDEBUG(`queryNot<${thread.nameAndSizeUntracked}> from: ${nodes.length} nodes`)\n\tconst patterns = (Array.isArray(patternOrPatterns) ? patternOrPatterns : [patternOrPatterns]) as DatalogQueryPattern[]\n\n\t// For each node, run all patterns as a joined multi-step query.\n\t// Exclude the node if ANY complete binding exists across all steps.\n\tconst filtered = nodes.filter(function innerNodeFilter({ variables }) {\n\t\t// Start with a single binding from the node's variables\n\t\tlet bindings: Record<string, any>[] = [variables ?? {}]\n\n\t\tfor (const pattern of patterns) {\n\t\t\tif (!Object.entries(pattern).length) throw new Error(`Pattern is empty`)\n\t\t\tconst nextBindings: Record<string, any>[] = []\n\n\t\t\tfor (const binding of bindings) {\n\t\t\t\tconst [resolved, varsToFill] = resolveOrRemoveVariables(pattern, binding)\n\t\t\t\tconst filter = makeFilter(resolved)\n\t\t\t\tconst matchingLogs = filter(thread.applogs)\n\t\t\t\tconst varMapper = createObjMapper(varsToFill)\n\n\t\t\t\tfor (const log of matchingLogs) {\n\t\t\t\t\tnextBindings.push({ ...binding, ...varMapper(log) })\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbindings = nextBindings\n\t\t\tif (bindings.length === 0) break // no matches — node is safe, skip remaining patterns\n\t\t}\n\n\t\tVERBOSE(`[queryNot] node:`, variables, '=> bindings:', bindings.length)\n\t\tif (opts.debug) LOG(`[queryNot] node result:`, variables, '=>', bindings)\n\t\treturn bindings.length === 0 // keep node if no complete match found\n\t})\n\treturn new QueryResult([...filtered])\n}, { argsDebugName: (thread, nodes, pattern) => createDebugName({ caller: 'queryNot', thread, pattern }) })\n\n/** Live variant: queryNot with incremental updates.\n * - Thread additions: O(new_applogs × included_nodes) — only checks new applogs\n * - Thread removals/resets: full recompute (rare for append-mostly logs)\n * - Upstream node additions: O(new_nodes × applogs)\n * - Upstream node removals: removed from output\n */\nexport const liveQueryNot = memoizedFn('liveQueryNot', function liveQueryNot(\n\tthread: Thread,\n\tupstream: LiveQueryResult,\n\tpatternOrPatterns: DatalogQueryPattern | DatalogQueryPattern[],\n\topts: { debug?: boolean } = {},\n) {\n\tconst patterns = (Array.isArray(patternOrPatterns) ? patternOrPatterns : [patternOrPatterns]) as DatalogQueryPattern[]\n\n\t/** Check if a node should be excluded (matches the NOT patterns as a joined multi-step query) */\n\tfunction nodeMatchesNot(node: QueryNode, applogs: readonly Applog[]): boolean {\n\t\tlet bindings: Record<string, any>[] = [node.variables ?? {}]\n\t\tfor (const pattern of patterns) {\n\t\t\tconst nextBindings: Record<string, any>[] = []\n\t\t\tfor (const binding of bindings) {\n\t\t\t\tconst [resolved, varsToFill] = resolveOrRemoveVariables(pattern, binding)\n\t\t\t\tconst filter = makeFilter(resolved)\n\t\t\t\tconst varMapper = createObjMapper(varsToFill)\n\t\t\t\tfor (const log of filter(applogs)) {\n\t\t\t\t\tnextBindings.push({ ...binding, ...varMapper(log) })\n\t\t\t\t}\n\t\t\t}\n\t\t\tbindings = nextBindings\n\t\t\tif (bindings.length === 0) return false // no matches — node passes\n\t\t}\n\t\treturn bindings.length > 0 // excluded if any complete binding exists\n\t}\n\n\t/** Full recompute: filter all upstream nodes against all thread applogs */\n\tfunction computeAll(): QueryNode[] {\n\t\treturn upstream.nodes.filter(node => !nodeMatchesNot(node, thread.applogs))\n\t}\n\n\tconst result = new SubscribableArrayImpl<QueryNode>(\n\t\tcomputeAll(),\n\t\t() => {\n\t\t\t// Subscribe to thread changes\n\t\t\tconst threadUnsub = thread.subscribe((event) => {\n\t\t\t\tif (isInitEvent(event)) {\n\t\t\t\t\t// Full reset — recompute everything\n\t\t\t\t\tresult._reset(computeAll())\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif (event.removed?.length) {\n\t\t\t\t\t// Removals: a previously-excluded node might now pass — full recompute\n\t\t\t\t\tresult._reset(computeAll())\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif (event.added.length) {\n\t\t\t\t\t// Additions: only check new applogs against currently-included nodes\n\t\t\t\t\tconst toRemove = result.items.filter(node => nodeMatchesNot(node, event.added))\n\t\t\t\t\tif (toRemove.length > 0) {\n\t\t\t\t\t\tresult._remove(toRemove)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}, 'derived')\n\n\t\t\t// Subscribe to upstream node changes\n\t\t\tconst upstreamUnsub = upstream.subscribe((event) => {\n\t\t\t\tif (isArrayInitEvent(event)) {\n\t\t\t\t\tresult._reset(computeAll())\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// New upstream nodes: check each against full thread\n\t\t\t\tif (event.added.length) {\n\t\t\t\t\tconst passing = event.added.filter(node => !nodeMatchesNot(node, thread.applogs))\n\t\t\t\t\tif (passing.length > 0) result._push(...passing)\n\t\t\t\t}\n\n\t\t\t\t// Removed upstream nodes: remove from our output\n\t\t\t\tif (event.removed?.length) {\n\t\t\t\t\tconst removedSet = new Set(event.removed)\n\t\t\t\t\tconst toRemove = result.items.filter(node => removedSet.has(node))\n\t\t\t\t\tif (toRemove.length > 0) result._remove(toRemove)\n\t\t\t\t}\n\t\t\t}, 'derived')\n\n\t\t\treturn () => { threadUnsub(); upstreamUnsub() }\n\t\t},\n\t)\n\n\treturn new LiveQueryResult(result)\n}, { argsDebugName: (thread, _nodes, pattern) => createDebugName({ caller: 'liveQueryNot', 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\n/** One-off: filter thread by pattern, map to values. Returns plain array. */\nexport const filterAndMap = memoizedFn('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\tconst filter = makeFilter(pattern)\n\tconst filtered = filter(thread.applogs)\n\treturn mapApplogsWith(filtered, mapper)\n}, { argsDebugName: (thread, pattern) => createDebugName({ caller: 'filterAndMap', thread, pattern }) })\n\n/** Live variant: returns SubscribableArray that updates when thread changes. */\nexport const liveFilterAndMap = memoizedFn('liveFilterAndMap', function liveFilterAndMap<R>(\n\tthread: Thread,\n\tpattern: DatalogQueryPattern,\n\tmapper: (keyof Applog) | (Partial<{ [key in keyof Applog]: string }>) | ((applog: Applog) => R),\n) {\n\tDEBUG(`liveFilterAndMap<${thread.nameAndSizeUntracked}>`, pattern)\n\tconst filtered = rollingFilter(thread, pattern)\n\tconst mapFn = makeApplogMapper(mapper)\n\n\tconst cidToMapped = new Map<CidString, R>()\n\tconst mapAndTrack = (log: Applog): R => {\n\t\tconst r = mapFn(log)\n\t\tcidToMapped.set(log.cid, r)\n\t\treturn r\n\t}\n\n\tconst initial = filtered.applogs.map(mapAndTrack)\n\tconst result = new SubscribableArrayImpl<R>(\n\t\tinitial,\n\t\t() => filtered.subscribe((event) => {\n\t\t\tif (isInitEvent(event)) {\n\t\t\t\tcidToMapped.clear()\n\t\t\t\tresult._reset(event.init.map(mapAndTrack))\n\t\t\t} else {\n\t\t\t\tif (event.added.length) result._push(...event.added.map(mapAndTrack))\n\t\t\t\tif (event.removed?.length) {\n\t\t\t\t\tconst toRemove: R[] = []\n\t\t\t\t\tfor (const log of event.removed) {\n\t\t\t\t\t\tconst r = cidToMapped.get(log.cid)\n\t\t\t\t\t\tif (r === undefined) {\n\t\t\t\t\t\t\tWARN(`[liveFilterAndMap] removed log not in cidToMapped`, { log })\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcidToMapped.delete(log.cid)\n\t\t\t\t\t\ttoRemove.push(r)\n\t\t\t\t\t}\n\t\t\t\t\tif (toRemove.length) result._remove(toRemove)\n\t\t\t\t}\n\t\t\t}\n\t\t}, 'derived'),\n\t)\n\treturn result\n}, { argsDebugName: (thread, pattern) => createDebugName({ caller: 'liveFilterAndMap', thread, pattern }) })\n\n/** One-off: query and map results. Returns plain array. */\nexport const queryAndMap = memoizedFn('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 queryResult = query(thread, patternOrPatterns)\n\treturn mapQueryResultWith(queryResult, mapDef)\n}, { argsDebugName: (thread, pattern) => createDebugName({ caller: 'queryAndMap', thread, pattern }) })\n\n/** Live variant: query and map results, returns SubscribableArray that updates reactively. */\nexport const liveQueryAndMap = memoizedFn('liveQueryAndMap', function liveQueryAndMap<R>(\n\tthread: Thread,\n\tpatternOrPatterns: Parameters<typeof liveQuery>[1],\n\tmapDef: string | (Partial<{ [key in keyof SearchContext]: string }>) | ((record: SearchContext) => R),\n) {\n\tDEBUG(`liveQueryAndMap<${thread.nameAndSizeUntracked}>`, { patternOrPatterns, map: mapDef })\n\tconst live = liveQuery(thread, patternOrPatterns)\n\n\tfunction computeAll(): R[] {\n\t\tconst snapshot = new QueryResult(live.nodes)\n\t\treturn mapQueryResultWith(snapshot, mapDef) as R[]\n\t}\n\n\tconst result = new SubscribableArrayImpl<R>(\n\t\tcomputeAll(),\n\t\t() => live.subscribe(() => {\n\t\t\tresult._reset(computeAll())\n\t\t}, 'derived'),\n\t)\n\treturn result\n}, { argsDebugName: (thread, pattern) => createDebugName({ caller: 'liveQueryAndMap', thread, pattern }) })\n\n/** One-off: query entity attributes. Returns Record or null. Requires current-state thread (LWW). */\nexport const queryEntity = memoizedFn('queryEntity', function queryEntity(\n\tthread: Thread,\n\tname: string,\n\tentityID: EntityID,\n\tattributes: readonly string[],\n) {\n\tassertLWW(thread)\n\tDEBUG(`queryEntity<${thread.nameAndSizeUntracked}>`, entityID, name)\n\tconst filter = makeFilter({ en: entityID, at: prefixAttrs(name, attributes) })\n\tconst filtered = filter(thread.applogs)\n\tVERBOSE(`queryEntity applogs:`, filtered)\n\tif (filtered.length === 0) return null\n\treturn Object.fromEntries(\n\t\tfiltered.map(({ at, vl }) => [at.slice(name.length + 1), vl]),\n\t)\n}, {\n\targsDebugName: (thread, name, entityID) => createDebugName({ caller: 'queryEntity', thread, args: { name, entityID } }),\n})\n\n/** Live variant: returns Subscribable that updates when entity attributes change. Requires current-state thread (LWW). */\nexport const liveQueryEntity = memoizedFn('liveQueryEntity', function liveQueryEntity(\n\tthread: Thread,\n\tname: string,\n\tentityID: EntityID,\n\tattributes: readonly string[],\n) {\n\tassertLWW(thread)\n\tDEBUG(`liveQueryEntity<${thread.nameAndSizeUntracked}>`, entityID, name)\n\tconst filtered = rollingFilter(thread, { en: entityID, at: prefixAttrs(name, attributes) })\n\n\tfunction compute() {\n\t\tif (filtered.isEmpty) return null\n\t\treturn Object.fromEntries(\n\t\t\tfiltered.map(({ at, vl }) => [at.slice(name.length + 1), vl]),\n\t\t)\n\t}\n\n\tconst result = new SubscribableImpl<Record<string, ApplogValue> | null>(\n\t\tcompute(),\n\t\t() => filtered.subscribe(() => {\n\t\t\tresult._set(compute())\n\t\t}, 'derived'),\n\t)\n\treturn result\n}, {\n\targsDebugName: (thread, name, entityID) => createDebugName({ caller: 'liveQueryEntity', thread, args: { name, entityID } }),\n})\n\n/** Live single-attribute query. Requires current-state thread (LWW). Returns Subscribable<T | null>. */\nexport const liveEntityAt = memoizedFn('liveEntityAt', function liveEntityAt<T extends ApplogValue>(\n\tthread: Thread,\n\tentityID: EntityID,\n\tat: string,\n) {\n\tassertLWW(thread)\n\tDEBUG(`liveEntityAt<${thread.nameAndSizeUntracked}>`, entityID, at)\n\tconst filtered = rollingFilter(thread, { en: entityID, at })\n\n\tfunction compute(): T | null {\n\t\tif (filtered.isEmpty) return null\n\t\treturn filtered.applogs[filtered.applogs.length - 1].vl as T\n\t}\n\n\tconst result = new SubscribableImpl<T | null>(\n\t\tcompute(),\n\t\t() => filtered.subscribe(() => {\n\t\t\tresult._set(compute())\n\t\t}, 'derived'),\n\t)\n\treturn result\n}, {\n\targsDebugName: (thread, entityID, at) => createDebugName({ caller: 'liveEntityAt', thread, args: { entityID, at } }),\n})\n\nexport const agentsOfThread = memoizedFn('agentsOfThread', function agentsOfThread(\n\tthread: Thread,\n) {\n\tDEBUG(`agentsOfThread<${thread.nameAndSizeUntracked}>`)\n\n\tconst mapped = new Map<string, number>()\n\tconst onEvent = (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\tthread.subscribe(onEvent, 'derived')\n\t// TODO: cleanup via ref-counted disposal when no longer needed\n\n\treturn mapped\n})\n\nexport const entityOverlap = memoizedFn('entityOverlap', function entityOverlapCount(\n\tthreadA: Thread,\n\tthreadB: Thread,\n) {\n\tLOG(`entityOverlap<${threadA.nameAndSizeUntracked}, ${threadB.nameAndSizeUntracked}>`)\n\n\t// Compute once — snapshot, not reactive (TODO: migrate to Subscribable)\n\tconst entitiesA = new Set(threadA.map(log => log.en))\n\tconst entitiesB = new Set(threadB.map(log => log.en))\n\treturn [...entitiesA].filter(en => entitiesB.has(en))\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)\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 = memoizedFn(\n\t'entityOverlapCount',\n\tfunction entityOverlapCount(threadA: Thread, threadB: Thread) {\n\t\treturn entityOverlap(threadA, threadB).length\n\t},\n)\n\n/** Live variant: entity overlap count as Subscribable<number>. */\nexport const liveEntityOverlapCount = memoizedFn(\n\t'liveEntityOverlapCount',\n\tfunction liveEntityOverlapCount(threadA: Thread, threadB: Thread) {\n\t\tfunction compute() {\n\t\t\tconst entitiesA = new Set(threadA.map(log => log.en))\n\t\t\tconst entitiesB = new Set(threadB.map(log => log.en))\n\t\t\treturn [...entitiesA].filter(en => entitiesB.has(en)).length\n\t\t}\n\n\t\tconst result = new SubscribableImpl<number>(\n\t\t\tcompute(),\n\t\t\t() => {\n\t\t\t\tconst unsub1 = threadA.subscribe(() => result._set(compute()), 'derived')\n\t\t\t\tconst unsub2 = threadB.subscribe(() => result._set(compute()), 'derived')\n\t\t\t\treturn () => { unsub1(); unsub2() }\n\t\t\t},\n\t\t)\n\t\treturn result\n\t},\n)\n\nexport const querySingle = memoizedFn('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\t// Snapshot — not reactive (TODO: migrate to Subscribable<Applog | null>)\n\tif (result.isEmpty) return null\n\tif (result.size > 1) throw ERROR(`[querySingle] got`, result.size, `results:`, result)\n\tconst logsOfThisNode = result.nodes[0].logsOfThisNode\n\tif (logsOfThisNode.size != 1) throw ERROR(`[querySingle] single result, but got`, logsOfThisNode.size, `logs:`, logsOfThisNode.applogs)\n\treturn logsOfThisNode.applogs[0]\n}, {\n\targsDebugName: (thread, pattern) => createDebugName({ caller: 'querySingle', thread, pattern }),\n})\n\nexport const querySingleAndMap = memoizedFn(\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 log = querySingle(threadOrLogs, patternOrPatterns, variables)\n\t\t// Snapshot — not reactive (TODO: migrate to Subscribable<T>)\n\t\tif (!log) return undefined\n\t\tif (typeof mapDef === 'string') {\n\t\t\treturn log[mapDef as string]\n\t\t} else {\n\t\t\treturn createObjMapper(mapDef)(log)\n\t\t}\n\t},\n\t{\n\t\targsDebugName: (thread, pattern) => createDebugName({ caller: 'querySingleAndMap', thread, pattern }),\n\t},\n)\n\n/** Live variant: querySingle returning Subscribable<Applog | null>. */\nexport const liveQuerySingle = memoizedFn('liveQuerySingle', function liveQuerySingle(\n\tthread: Thread,\n\tpatternOrPatterns: Parameters<typeof liveQuery>[1],\n) {\n\tDEBUG(`liveQuerySingle<${thread.nameAndSizeUntracked}>`)\n\tconst live = liveQuery(thread, patternOrPatterns)\n\n\tfunction compute(): Applog | null {\n\t\tif (live.isEmpty) return null\n\t\tif (live.size > 1) throw ERROR(`[liveQuerySingle] got`, live.size, `results`)\n\t\tconst logsOfThisNode = live.nodes[0].logsOfThisNode\n\t\tif (logsOfThisNode.size !== 1) throw ERROR(`[liveQuerySingle] single result, but got`, logsOfThisNode.size, `logs`)\n\t\treturn logsOfThisNode.applogs[0]\n\t}\n\n\tconst result = new SubscribableImpl<Applog | null>(\n\t\tcompute(),\n\t\t() => live.subscribe(() => {\n\t\t\tresult._set(compute())\n\t\t}),\n\t)\n\treturn result\n}, {\n\targsDebugName: (thread, pattern) => createDebugName({ caller: 'liveQuerySingle', thread, pattern }),\n})\n\n/** Live variant: querySingleAndMap returning Subscribable<T | undefined>. */\nexport const liveQuerySingleAndMap = memoizedFn(\n\t'liveQuerySingleAndMap',\n\tfunction liveQuerySingleAndMap<MAP extends (keyof Applog | (Partial<{ [key in keyof Applog]: string }>))>(\n\t\tthread: Thread,\n\t\tpatternOrPatterns: Parameters<typeof liveQuery>[1],\n\t\tmapDef: MAP,\n\t) {\n\t\tDEBUG(`liveQuerySingleAndMap<${thread.nameAndSizeUntracked}>`)\n\t\tconst liveSingle = liveQuerySingle(thread, patternOrPatterns)\n\n\t\tfunction compute() {\n\t\t\tconst log = liveSingle.value\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\n\t\tconst result = new SubscribableImpl<any>(\n\t\t\tcompute(),\n\t\t\t() => liveSingle.subscribe(() => {\n\t\t\t\tresult._set(compute())\n\t\t\t}),\n\t\t)\n\t\treturn result\n\t},\n\t{\n\t\targsDebugName: (thread, pattern) => createDebugName({ caller: 'liveQuerySingleAndMap', thread, pattern }),\n\t},\n)\n\n/////////////\n// HELPERS //\n/////////////\n\n/** Create a single-applog mapper function from a mapDef */\nexport function makeApplogMapper<R>(\n\tmapDef: (keyof Applog) | (Partial<{ [key in keyof Applog]: string }>) | ((applog: Applog) => R),\n): (applog: Applog) => R {\n\tif (typeof mapDef === 'function') {\n\t\treturn mapDef as (applog: Applog) => R\n\t} else if (typeof mapDef === 'string') {\n\t\treturn (log: Applog) => log[mapDef] as R\n\t} else {\n\t\treturn createObjMapper(mapDef) as (applog: Applog) => R\n\t}\n}\n\n/** Map an array of applogs using a mapDef */\nexport function mapApplogsWith<R>(\n\tapplogs: readonly Applog[],\n\tmapDef: (keyof Applog) | (Partial<{ [key in keyof Applog]: string }>) | ((applog: Applog) => R),\n) {\n\treturn applogs.map(makeApplogMapper(mapDef))\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\treturn mapApplogsWith(thread.applogs, mapDef)\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)(node.record)\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}\n\n/** Inverse of prefixAt — strips everything up to and including the first `/` */\nexport function stripAtPrefix(attr: string): string {\n\tconst idx = attr.indexOf('/')\n\treturn idx >= 0 ? attr.slice(idx + 1) : attr\n}\n\n/** Create a key mapper from an explicit attribute→key record */\nexport function mapAttributes<A extends string>(mapping: Record<A, string>): (attr: A) => string {\n\treturn (attr) => mapping[attr] ?? attr\n}\n\n/** Resolve key mapping options to a concrete mapper function */\nexport function resolveKeyMapper(opts?: { stripAtPrefix?: true | string; mapKeys?: (attr: string) => string }): (attr: string) => string {\n\tif (!opts) return (attr) => attr\n\tif (opts.mapKeys) return opts.mapKeys\n\tif (opts.stripAtPrefix === true) return stripAtPrefix\n\tif (typeof opts.stripAtPrefix === 'string') {\n\t\tconst prefix = opts.stripAtPrefix + '/'\n\t\treturn (attr) => attr.startsWith(prefix) ? attr.slice(prefix.length) : attr\n\t}\n\treturn (attr) => 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}\nfunction getPatternVariableNames(pattern: DatalogQueryPattern): Set<string> {\n\tconst vars = new Set<string>()\n\tfor (const value of Object.values(pattern)) {\n\t\tif (isVariable(value)) {\n\t\t\tvars.add((value as string).slice(1))\n\t\t}\n\t}\n\treturn vars\n}\n\n/**\n * Warn if a multi-step query has steps that are not connected via shared variables.\n * Disconnected steps produce a cartesian product instead of a join.\n */\nfunction warnIfDisjointQuerySteps(patterns: DatalogQueryPattern[]) {\n\tif (patterns.length < 2) return\n\n\tconst varSets = patterns.map(getPatternVariableNames)\n\tconst reachable = new Set(varSets[0])\n\n\tfor (let i = 1; i < varSets.length; i++) {\n\t\tconst stepVars = varSets[i]\n\t\tif (stepVars.size === 0) {\n\t\t\tWARN(\n\t\t\t\t`[query] Step ${i} has no variables — it produces identical results regardless of previous steps (cartesian product).`,\n\t\t\t\t`Patterns:`, patterns,\n\t\t\t)\n\t\t\tcontinue\n\t\t}\n\t\tconst connected = [...stepVars].some(v => reachable.has(v))\n\t\tif (!connected) {\n\t\t\tWARN(\n\t\t\t\t`[query] Step ${i} is disconnected from previous steps — no shared variable.`,\n\t\t\t\t`This produces a cartesian product instead of a join.`,\n\t\t\t\t`Step ${i} variables: {${[...stepVars].join(', ')}}`,\n\t\t\t\t`Reachable from prior steps: {${[...reachable].join(', ')}}`,\n\t\t\t\t`Patterns:`, patterns,\n\t\t\t)\n\t\t}\n\t\tfor (const v of stepVars) reachable.add(v)\n\t}\n}\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","thread","liveQuery","liveQueryStep","queryNot","liveQueryNot","filterAndMap","liveFilterAndMap","queryAndMap","liveQueryAndMap","queryEntity","liveQueryEntity","liveEntityAt","agentsOfThread","entityOverlapMap","entityOverlapCount","liveEntityOverlapCount","querySingle","querySingleAndMap","liveQuerySingle","liveQuerySingleAndMap","filterAndMapGetterFx"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// src/viewmodel/adapters/arktype.ts
|
|
2
|
+
function createArkTypeAdapter(_arkTypeSchema, entityPrefix, options) {
|
|
3
|
+
return {
|
|
4
|
+
getAttributeDefs: () => options?.attributes ?? [],
|
|
5
|
+
getDefaults: () => options?.defaults ?? {},
|
|
6
|
+
getEntityPrefix: () => entityPrefix,
|
|
7
|
+
createValidator: () => (value) => {
|
|
8
|
+
const result = _arkTypeSchema(value);
|
|
9
|
+
return typeof result !== "string";
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
createArkTypeAdapter
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=chunk-64EJIJAJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/viewmodel/adapters/arktype.ts"],"sourcesContent":["import type { ApplogValue } from '../../applog/datom-types.ts'\nimport type { ISchemaAdapter, VMAttributeDef } from '../types.ts'\n\n/**\n * Pattern for creating a schema adapter from an ArkType schema.\n *\n * ArkType is NOT a runtime dependency of @wovin/core, so this adapter\n * works by accepting the ArkType type object directly.\n *\n * Usage:\n * ```ts\n * import { type } from 'arktype'\n * import { createArkTypeAdapter } from '@wovin/core/viewmodel/adapters/arktype'\n *\n * const MySchema = type({\n * name: 'string',\n * age: 'number | undefined',\n * })\n *\n * const adapter = createArkTypeAdapter(MySchema, 'myEntity')\n * ```\n */\nexport function createArkTypeAdapter<T extends Record<string, ApplogValue>>(\n\t_arkTypeSchema: { infer: T; (input: unknown): T | string },\n\tentityPrefix: string,\n\toptions?: {\n\t\t/** Override at-paths for specific attributes */\n\t\tatOverrides?: Record<string, string>\n\t\t/** Attribute definitions (must be provided for ArkType since we can't introspect the type) */\n\t\tattributes: VMAttributeDef[]\n\t\t/** Default values */\n\t\tdefaults?: Partial<T>\n\t},\n): ISchemaAdapter<T> {\n\treturn {\n\t\tgetAttributeDefs: () => options?.attributes ?? [],\n\t\tgetDefaults: () => (options?.defaults ?? {}) as Partial<T>,\n\t\tgetEntityPrefix: () => entityPrefix,\n\t\tcreateValidator: () => (value: unknown): value is T => {\n\t\t\tconst result = _arkTypeSchema(value as any)\n\t\t\treturn typeof result !== 'string'\n\t\t},\n\t}\n}\n"],"mappings":";AAsBO,SAAS,qBACf,gBACA,cACA,SAQoB;AACpB,SAAO;AAAA,IACN,kBAAkB,MAAM,SAAS,cAAc,CAAC;AAAA,IAChD,aAAa,MAAO,SAAS,YAAY,CAAC;AAAA,IAC1C,iBAAiB,MAAM;AAAA,IACvB,iBAAiB,MAAM,CAAC,UAA+B;AACtD,YAAM,SAAS,eAAe,KAAY;AAC1C,aAAO,OAAO,WAAW;AAAA,IAC1B;AAAA,EACD;AACD;","names":[]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// src/viewmodel/adapters/typia.ts
|
|
2
|
+
function createTypiaAdapter(_typiaValidator, entityPrefix, options) {
|
|
3
|
+
return {
|
|
4
|
+
getAttributeDefs: () => options.attributes,
|
|
5
|
+
getDefaults: () => options?.defaults ?? {},
|
|
6
|
+
getEntityPrefix: () => entityPrefix,
|
|
7
|
+
createValidator: () => (value) => {
|
|
8
|
+
const result = _typiaValidator(value);
|
|
9
|
+
return result.success;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
createTypiaAdapter
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=chunk-7QEGHKR4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/viewmodel/adapters/typia.ts"],"sourcesContent":["import type { ApplogValue } from '../../applog/datom-types.ts'\nimport type { ISchemaAdapter, VMAttributeDef } from '../types.ts'\n\n/**\n * Pattern for creating a schema adapter from a Typia-generated schema.\n *\n * Typia is NOT a runtime dependency of @wovin/core, so this adapter\n * works by accepting the Typia type object directly along with the\n * attribute definitions (which must be provided separately since\n * Typia doesn't expose runtime property introspection by default).\n *\n * Usage:\n * ```ts\n * import typia from 'typia'\n * import { createTypiaAdapter } from '@wovin/core/viewmodel/adapters/typia'\n *\n * interface MyEntity { name: string; age?: number }\n *\n * const adapter = createTypiaAdapter<MyEntity>(\n * typia.createValidate<MyEntity>(),\n * 'myEntity',\n * {\n * attributes: [\n * { name: 'name', atPath: 'myEntity/name', optional: false },\n * { name: 'age', atPath: 'myEntity/age', optional: true },\n * ],\n * },\n * )\n * ```\n */\nexport function createTypiaAdapter<T extends Record<string, ApplogValue>>(\n\t_typiaValidator: (input: unknown) => { success: boolean; data: T | null; errors?: any[] },\n\tentityPrefix: string,\n\toptions: {\n\t\t/** Attribute definitions (required for Typia since property introspection is compile-time) */\n\t\tattributes: VMAttributeDef[]\n\t\t/** Default values */\n\t\tdefaults?: Partial<T>\n\t},\n): ISchemaAdapter<T> {\n\treturn {\n\t\tgetAttributeDefs: () => options.attributes,\n\t\tgetDefaults: () => (options?.defaults ?? {}) as Partial<T>,\n\t\tgetEntityPrefix: () => entityPrefix,\n\t\tcreateValidator: () => (value: unknown): value is T => {\n\t\t\tconst result = _typiaValidator(value)\n\t\t\treturn result.success\n\t\t},\n\t}\n}\n"],"mappings":";AA8BO,SAAS,mBACf,iBACA,cACA,SAMoB;AACpB,SAAO;AAAA,IACN,kBAAkB,MAAM,QAAQ;AAAA,IAChC,aAAa,MAAO,SAAS,YAAY,CAAC;AAAA,IAC1C,iBAAiB,MAAM;AAAA,IACvB,iBAAiB,MAAM,CAAC,UAA+B;AACtD,YAAM,SAAS,gBAAgB,KAAK;AACpC,aAAO,OAAO;AAAA,IACf;AAAA,EACD;AACD;","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
cyrb53hash,
|
|
3
3
|
ensureTsPvAndFinalizeApplog
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-2OXLPZQI.js";
|
|
5
5
|
|
|
6
6
|
// src/pubsub/pub-pull.ts
|
|
7
7
|
import { Logger } from "besonders-logger";
|
|
@@ -37,4 +37,4 @@ export {
|
|
|
37
37
|
isSubscription,
|
|
38
38
|
agentToShortHash
|
|
39
39
|
};
|
|
40
|
-
//# sourceMappingURL=chunk-
|
|
40
|
+
//# sourceMappingURL=chunk-EHO2BFFY.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// src/viewmodel/adapters/typebox.ts
|
|
2
|
+
function createTypeBoxAdapter(typeBoxSchema, entityPrefix, options) {
|
|
3
|
+
const properties = typeBoxSchema.properties;
|
|
4
|
+
const toAtPath = options?.toAtPath ?? ((prefix, name) => `${prefix}/${name}`);
|
|
5
|
+
const attributeDefs = Object.entries(properties).map(([name, propSchema]) => {
|
|
6
|
+
const isOptional = propSchema.optional ?? false;
|
|
7
|
+
const wovinAtName = propSchema.wovinAtName;
|
|
8
|
+
const atPath = options?.atOverrides?.[name] ?? wovinAtName ?? toAtPath(entityPrefix, name);
|
|
9
|
+
return {
|
|
10
|
+
name,
|
|
11
|
+
atPath,
|
|
12
|
+
optional: isOptional,
|
|
13
|
+
defaultValue: propSchema.default
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
return {
|
|
17
|
+
getAttributeDefs: () => attributeDefs,
|
|
18
|
+
getDefaults: () => options?.defaults ?? {},
|
|
19
|
+
getEntityPrefix: () => entityPrefix,
|
|
20
|
+
createValidator: options?.validator ? () => options.validator : void 0
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export {
|
|
25
|
+
createTypeBoxAdapter
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=chunk-ICBK7NC4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/viewmodel/adapters/typebox.ts"],"sourcesContent":["import type { ApplogValue } from '../../applog/datom-types.ts'\nimport type { ISchemaAdapter, VMAttributeDef } from '../types.ts'\n\n/**\n * Create a schema adapter from a TypeBox object schema.\n *\n * Usage:\n * ```ts\n * import { Type } from '@sinclair/typebox'\n * import { createTypeBoxAdapter } from '@wovin/core/viewmodel/adapters/typebox'\n *\n * const MySchema = Type.Object({\n * name: Type.String(),\n * age: Type.Optional(Type.Number()),\n * })\n *\n * const adapter = createTypeBoxAdapter(MySchema, 'myEntity')\n * ```\n *\n * The type parameter `T` is the inferred static type of the schema.\n * Can pass a compiled validator separately if runtime validation is needed.\n */\nexport function createTypeBoxAdapter<T extends Record<string, ApplogValue>>(\n\ttypeBoxSchema: { properties: Record<string, any>; type?: string },\n\tentityPrefix: string,\n\toptions?: {\n\t\t/** Override at-paths for specific attributes */\n\t\tatOverrides?: Record<string, string>\n\t\t/** Default values */\n\t\tdefaults?: Partial<T>\n\t\t/** Property name to at-path mapping function */\n\t\ttoAtPath?: (entityPrefix: string, attrName: string) => string\n\t\t/** A pre-compiled validator function (e.g. from TypeCompiler.Compile) */\n\t\tvalidator?: (value: unknown) => value is T\n\t},\n): ISchemaAdapter<T> {\n\tconst properties = typeBoxSchema.properties as Record<string, any>\n\tconst toAtPath = options?.toAtPath ?? ((prefix, name) => `${prefix}/${name}`)\n\n\tconst attributeDefs: VMAttributeDef[] = Object.entries(properties).map(([name, propSchema]: [string, any]) => {\n\t\tconst isOptional = propSchema.optional ?? false\n\t\tconst wovinAtName = propSchema.wovinAtName\n\t\tconst atPath = options?.atOverrides?.[name] ?? wovinAtName ?? toAtPath(entityPrefix, name)\n\n\t\treturn {\n\t\t\tname,\n\t\t\tatPath,\n\t\t\toptional: isOptional,\n\t\t\tdefaultValue: propSchema.default,\n\t\t}\n\t})\n\n\treturn {\n\t\tgetAttributeDefs: () => attributeDefs,\n\t\tgetDefaults: () => (options?.defaults ?? {}) as Partial<T>,\n\t\tgetEntityPrefix: () => entityPrefix,\n\t\tcreateValidator: options?.validator ? () => options.validator! : undefined,\n\t}\n}\n"],"mappings":";AAsBO,SAAS,qBACf,eACA,cACA,SAUoB;AACpB,QAAM,aAAa,cAAc;AACjC,QAAM,WAAW,SAAS,aAAa,CAAC,QAAQ,SAAS,GAAG,MAAM,IAAI,IAAI;AAE1E,QAAM,gBAAkC,OAAO,QAAQ,UAAU,EAAE,IAAI,CAAC,CAAC,MAAM,UAAU,MAAqB;AAC7G,UAAM,aAAa,WAAW,YAAY;AAC1C,UAAM,cAAc,WAAW;AAC/B,UAAM,SAAS,SAAS,cAAc,IAAI,KAAK,eAAe,SAAS,cAAc,IAAI;AAEzF,WAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV,cAAc,WAAW;AAAA,IAC1B;AAAA,EACD,CAAC;AAED,SAAO;AAAA,IACN,kBAAkB,MAAM;AAAA,IACxB,aAAa,MAAO,SAAS,YAAY,CAAC;AAAA,IAC1C,iBAAiB,MAAM;AAAA,IACvB,iBAAiB,SAAS,YAAY,MAAM,QAAQ,YAAa;AAAA,EAClE;AACD;","names":[]}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveKeyMapper
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2PJFLZRC.js";
|
|
4
4
|
import {
|
|
5
5
|
SubscribableImpl,
|
|
6
6
|
ThreadInMemory,
|
|
7
|
+
anyOf,
|
|
7
8
|
createDebugName,
|
|
8
9
|
isInitEvent,
|
|
9
10
|
makeFilter,
|
|
10
11
|
memoizedFn,
|
|
11
12
|
rollingFilter
|
|
12
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-2OXLPZQI.js";
|
|
13
14
|
|
|
14
15
|
// src/query/divergences.ts
|
|
15
16
|
import { Logger } from "besonders-logger";
|
|
@@ -46,14 +47,6 @@ var queryDivergencesByPrev = memoizedFn("queryDivergencesByPrev", function query
|
|
|
46
47
|
return divergences;
|
|
47
48
|
});
|
|
48
49
|
|
|
49
|
-
// src/query/matchers.ts
|
|
50
|
-
function includes(str) {
|
|
51
|
-
return (vl) => vl?.includes?.(str);
|
|
52
|
-
}
|
|
53
|
-
function includedIn(arr) {
|
|
54
|
-
return (vl) => arr?.includes?.(vl);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
50
|
// src/query/entity-collection.ts
|
|
58
51
|
import { Logger as Logger2 } from "besonders-logger";
|
|
59
52
|
var { DEBUG: DEBUG2 } = Logger2.setup(Logger2.INFO);
|
|
@@ -71,7 +64,7 @@ var _liveEntityCollection = memoizedFn(
|
|
|
71
64
|
DEBUG2("liveEntityCollection", discoveryPattern, liveAttributes);
|
|
72
65
|
const discoveryAttr = discoveryPattern.at;
|
|
73
66
|
const allAttrs = /* @__PURE__ */ new Set([discoveryAttr, ...liveAttributes]);
|
|
74
|
-
const filtered = rollingFilter(thread, { at:
|
|
67
|
+
const filtered = rollingFilter(thread, { at: anyOf(...allAttrs) });
|
|
75
68
|
const isDiscoveryMatch = makeFilter(discoveryPattern);
|
|
76
69
|
const attrSet = new Set(liveAttributes);
|
|
77
70
|
const key = resolveKeyMapper(opts);
|
|
@@ -140,8 +133,6 @@ var _liveEntityCollection = memoizedFn(
|
|
|
140
133
|
|
|
141
134
|
export {
|
|
142
135
|
queryDivergencesByPrev,
|
|
143
|
-
includes,
|
|
144
|
-
includedIn,
|
|
145
136
|
liveEntityCollection
|
|
146
137
|
};
|
|
147
|
-
//# sourceMappingURL=chunk-
|
|
138
|
+
//# sourceMappingURL=chunk-OKXRRWNS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/query/divergences.ts","../src/query/entity-collection.ts"],"sourcesContent":["import { Logger } from 'besonders-logger'\nimport stringify from 'safe-stable-stringify'\nimport { Applog, CidString } from '../applog/datom-types.ts'\nimport { createDebugName } from '../utils/debug-name.ts'\nimport { Thread } from '../thread/basic.ts'\nimport { ThreadInMemory } from '../thread/writeable.ts'\nimport { memoizedFn } from './memoized.ts'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO) // eslint-disable-line no-unused-vars\n\nexport interface DivergenceLeaf {\n\tlog: Applog\n\tthread: Thread\n}\n\nexport const queryDivergencesByPrev = memoizedFn('queryDivergencesByPrev', function queryConflictingByPrev(\n\tsourceThread: Thread,\n) {\n\tDEBUG(`queryDivergencesByPrev<${sourceThread.nameAndSizeUntracked}>`)\n\tif (sourceThread.filters.includes('lastWriteWins')) WARN(`queryDivergencesByPrev on thread lastWriteWins`, sourceThread)\n\n\tconst logsForNode = new Map<CidString, Applog[]>()\n\tconst leafs = new Set<CidString>()\n\tVERBOSE('all applogs:', sourceThread.applogs)\n\tfor (const log of sourceThread.applogs) {\n\t\tlet prevLogs\n\t\tif (log.pv) {\n\t\t\tprevLogs = log.pv && logsForNode.get(log.pv.toString())\n\t\t\tleafs.delete(log.pv.toString())\n\t\t}\n\t\tVERBOSE('traversing log', { log, prevLogs, leafs: Array.from(leafs) })\n\t\tlogsForNode.set(log.cid, prevLogs ? [...prevLogs, log] : [log])\n\t\tleafs.add(log.cid)\n\t}\n\tconst divergences = Array.from(leafs).map(leafID => {\n\t\tconst thread = new ThreadInMemory(\n\t\t\tcreateDebugName({\n\t\t\t\tcaller: 'DivergenceLeaf',\n\t\t\t\tthread: sourceThread,\n\t\t\t\tpattern: `leaf: ${leafID}`,\n\t\t\t}),\n\t\t\tlogsForNode.get(leafID),\n\t\t\tsourceThread.filters,\n\t\t\ttrue,\n\t\t)\n\t\treturn ({ log: thread.latestLog, thread })\n\t})\n\t// TODO: migrate to SubscribableArray for reactive updates\n\treturn divergences\n})\n","import { Logger } from 'besonders-logger'\nimport { Applog, ApplogValue, DatalogQueryPattern, EntityID } from '../applog/datom-types.ts'\nimport { isInitEvent, Thread } from '../thread/basic.ts'\nimport { makeFilter, rollingFilter } from '../thread/filters.ts'\nimport { resolveKeyMapper } from './basic.ts'\nimport { anyOf } from './matchers.ts'\nimport { memoizedFn } from './memoized.ts'\nimport { SubscribableImpl } from './subscribable.ts'\nimport type { Subscribable } from './subscribable.ts'\nimport type { StripExplicitPrefix, StripFirstPrefix } from './attr-helpers.ts'\n\nconst { DEBUG } = Logger.setup(Logger.INFO) // eslint-disable-line no-unused-vars\n\nexport function liveEntityCollection<A extends string>(\n\tthread: Thread, discoveryPattern: DatalogQueryPattern, liveAttributes: readonly A[],\n): Subscribable<ReadonlyMap<EntityID, Record<A, ApplogValue | null>>>\nexport function liveEntityCollection<A extends string>(\n\tthread: Thread, discoveryPattern: DatalogQueryPattern, liveAttributes: readonly A[],\n\topts: { stripAtPrefix: true },\n): Subscribable<ReadonlyMap<EntityID, Record<StripFirstPrefix<A>, ApplogValue | null>>>\nexport function liveEntityCollection<A extends string, P extends string>(\n\tthread: Thread, discoveryPattern: DatalogQueryPattern, liveAttributes: readonly A[],\n\topts: { stripAtPrefix: P },\n): Subscribable<ReadonlyMap<EntityID, Record<StripExplicitPrefix<A, P>, ApplogValue | null>>>\nexport function liveEntityCollection<A extends string>(\n\tthread: Thread, discoveryPattern: DatalogQueryPattern, liveAttributes: readonly A[],\n\topts: { mapKeys: (attr: A) => string },\n): Subscribable<ReadonlyMap<EntityID, Record<string, ApplogValue | null>>>\nexport function liveEntityCollection<A extends string>(\n\tthread: Thread, discoveryPattern: DatalogQueryPattern, liveAttributes: readonly A[],\n\topts: { stripAtPrefix?: true | string; mapKeys?: (attr: A) => string },\n): Subscribable<ReadonlyMap<EntityID, Record<string, ApplogValue | null>>>\nexport function liveEntityCollection<A extends string>(\n\tthread: Thread,\n\tdiscoveryPattern: DatalogQueryPattern,\n\tliveAttributes: readonly A[],\n\topts?: { stripAtPrefix?: true | string; mapKeys?: (attr: A) => string },\n): Subscribable<ReadonlyMap<EntityID, Record<string, ApplogValue | null>>> {\n\treturn _liveEntityCollection(thread, discoveryPattern, liveAttributes,\n\t\topts as { stripAtPrefix?: true | string; mapKeys?: (attr: string) => string })\n}\n\nconst _liveEntityCollection = memoizedFn('liveEntityCollection',\n\tfunction liveEntityCollection<A extends string>(\n\t\tthread: Thread,\n\t\tdiscoveryPattern: DatalogQueryPattern,\n\t\tliveAttributes: readonly A[],\n\t\topts?: { stripAtPrefix?: true | string; mapKeys?: (attr: string) => string },\n\t): Subscribable<ReadonlyMap<EntityID, Record<string, ApplogValue | null>>> {\n\t\tDEBUG('liveEntityCollection', discoveryPattern, liveAttributes)\n\t\tconst discoveryAttr = discoveryPattern.at as string\n\t\tconst allAttrs = new Set([discoveryAttr, ...liveAttributes])\n\t\tconst filtered = rollingFilter(thread, { at: anyOf(...allAttrs) })\n\t\tconst isDiscoveryMatch = makeFilter(discoveryPattern)\n\t\tconst attrSet = new Set<string>(liveAttributes)\n\t\tconst key = resolveKeyMapper(opts)\n\n\t\tconst map = new Map<EntityID, Record<string, ApplogValue | null>>()\n\n\t\tfunction makeRecord(entityId: EntityID): Record<string, ApplogValue | null> {\n\t\t\tconst record = {} as Record<string, ApplogValue | null>\n\t\t\tfor (const attr of liveAttributes) record[key(attr)] = null\n\t\t\t// Backfill from current filtered state\n\t\t\tfor (const log of filtered.applogs) {\n\t\t\t\tif (log.en === entityId && attrSet.has(log.at)) {\n\t\t\t\t\trecord[key(log.at)] = log.vl\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn record\n\t\t}\n\n\t\tfunction buildFull(applogs: readonly Applog[]) {\n\t\t\tmap.clear()\n\t\t\tfor (const log of isDiscoveryMatch(applogs)) {\n\t\t\t\tif (!map.has(log.en)) map.set(log.en, makeRecord(log.en))\n\t\t\t}\n\t\t}\n\n\t\tfunction addLog(log: Applog) {\n\t\t\t// Discovery match → ensure entity exists\n\t\t\tif (isDiscoveryMatch([log]).length > 0 && !map.has(log.en)) {\n\t\t\t\tmap.set(log.en, makeRecord(log.en))\n\t\t\t\treturn // makeRecord already backfilled attrs\n\t\t\t}\n\t\t\t// Attribute match → update value\n\t\t\tif (attrSet.has(log.at)) {\n\t\t\t\tconst record = map.get(log.en)\n\t\t\t\tif (record) record[key(log.at)] = log.vl\n\t\t\t}\n\t\t}\n\n\t\tfunction removeLog(log: Applog) {\n\t\t\tif (isDiscoveryMatch([log]).length > 0) {\n\t\t\t\t// Check if entity still has another discovery match\n\t\t\t\tconst stillDiscovered = filtered.applogs.some(\n\t\t\t\t\tl => l.en === log.en && isDiscoveryMatch([l]).length > 0,\n\t\t\t\t)\n\t\t\t\tif (!stillDiscovered) {\n\t\t\t\t\tmap.delete(log.en)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (attrSet.has(log.at)) {\n\t\t\t\tconst record = map.get(log.en)\n\t\t\t\tif (record) {\n\t\t\t\t\t// Find current value from remaining applogs\n\t\t\t\t\tconst current = filtered.applogs.find(l => l.en === log.en && l.at === log.at)\n\t\t\t\t\trecord[key(log.at)] = current?.vl ?? null\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Initial build\n\t\tbuildFull(filtered.applogs)\n\n\t\tconst result = new SubscribableImpl<ReadonlyMap<EntityID, Record<string, ApplogValue | null>>>(\n\t\t\tmap,\n\t\t\t() => filtered.subscribe((event) => {\n\t\t\t\tif (isInitEvent(event)) {\n\t\t\t\t\tbuildFull(event.init)\n\t\t\t\t} else {\n\t\t\t\t\t// Process removes before adds — LWW updates appear as remove+add in same delta\n\t\t\t\t\tif (event.removed) for (const log of event.removed) removeLog(log)\n\t\t\t\t\tfor (const log of event.added) addLog(log)\n\t\t\t\t}\n\t\t\t\tresult._set(map)\n\t\t\t}, 'derived'),\n\t\t\t{ equals: false },\n\t\t)\n\t\treturn result\n\t},\n)\n"],"mappings":"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","names":["Logger","DEBUG","Logger","liveEntityCollection"]}
|