@wovin/core 0.2.2 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/dist/applog/applog-utils.d.ts +25 -1
  2. package/dist/applog/applog-utils.d.ts.map +1 -1
  3. package/dist/applog/datom-types.d.ts.map +1 -1
  4. package/dist/applog.js +5 -3
  5. package/dist/blockstore.js +2 -0
  6. package/dist/blockstore.js.map +1 -1
  7. package/dist/{chunk-SHUHRHOT.js → chunk-4MKPGQIM.js} +17 -18
  8. package/dist/chunk-4MKPGQIM.js.map +1 -0
  9. package/dist/chunk-64EJIJAJ.js +17 -0
  10. package/dist/chunk-64EJIJAJ.js.map +1 -0
  11. package/dist/{chunk-HUIQ54TT.js → chunk-6CSJTSQP.js} +3 -3
  12. package/dist/chunk-7QEGHKR4.js +17 -0
  13. package/dist/chunk-7QEGHKR4.js.map +1 -0
  14. package/dist/{chunk-BLF5MAWU.js → chunk-BIYQEX3N.js} +2 -2
  15. package/dist/{chunk-6ALNRM3J.js → chunk-H3JNNTVP.js} +21 -8
  16. package/dist/chunk-H3JNNTVP.js.map +1 -0
  17. package/dist/{chunk-OC6Z6CQW.js → chunk-H4YVJKB7.js} +2 -2
  18. package/dist/chunk-ICBK7NC4.js +27 -0
  19. package/dist/chunk-ICBK7NC4.js.map +1 -0
  20. package/dist/chunk-N5QPZNKD.js +288 -0
  21. package/dist/chunk-N5QPZNKD.js.map +1 -0
  22. package/dist/{chunk-3SUFNJEZ.js → chunk-N7SEGHU4.js} +7 -2
  23. package/dist/{chunk-3SUFNJEZ.js.map → chunk-N7SEGHU4.js.map} +1 -1
  24. package/dist/chunk-XF4DWOAE.js +25 -0
  25. package/dist/chunk-XF4DWOAE.js.map +1 -0
  26. package/dist/index.js +20 -10
  27. package/dist/ipfs/car.d.ts.map +1 -1
  28. package/dist/ipfs.js +4 -4
  29. package/dist/ipns/gateway-resolver.d.ts +21 -0
  30. package/dist/ipns/gateway-resolver.d.ts.map +1 -0
  31. package/dist/ipns/ipns-record.d.ts +46 -7
  32. package/dist/ipns/ipns-record.d.ts.map +1 -1
  33. package/dist/ipns/ipns-w3name.d.ts +45 -0
  34. package/dist/ipns/ipns-w3name.d.ts.map +1 -0
  35. package/dist/ipns/ipns-watcher.d.ts +190 -0
  36. package/dist/ipns/ipns-watcher.d.ts.map +1 -0
  37. package/dist/ipns.d.ts +3 -0
  38. package/dist/ipns.d.ts.map +1 -1
  39. package/dist/ipns.js +591 -14
  40. package/dist/ipns.js.map +1 -1
  41. package/dist/pubsub/snap-push.d.ts +2 -2
  42. package/dist/pubsub/snap-push.d.ts.map +1 -1
  43. package/dist/pubsub.js +4 -4
  44. package/dist/query/epoch-snapshot.d.ts +205 -0
  45. package/dist/query/epoch-snapshot.d.ts.map +1 -0
  46. package/dist/query.d.ts +1 -0
  47. package/dist/query.d.ts.map +1 -1
  48. package/dist/query.js +12 -4
  49. package/dist/retrieve.js +4 -4
  50. package/dist/thread.js +1 -1
  51. package/dist/viewmodel/adapters/arktype.d.ts +33 -0
  52. package/dist/viewmodel/adapters/arktype.d.ts.map +1 -0
  53. package/dist/viewmodel/adapters/arktype.js +7 -0
  54. package/dist/viewmodel/adapters/arktype.js.map +1 -0
  55. package/dist/viewmodel/adapters/typebox.d.ts +35 -0
  56. package/dist/viewmodel/adapters/typebox.d.ts.map +1 -0
  57. package/dist/viewmodel/adapters/typebox.js +7 -0
  58. package/dist/viewmodel/adapters/typebox.js.map +1 -0
  59. package/dist/viewmodel/adapters/typia.d.ts +40 -0
  60. package/dist/viewmodel/adapters/typia.d.ts.map +1 -0
  61. package/dist/viewmodel/adapters/typia.js +7 -0
  62. package/dist/viewmodel/adapters/typia.js.map +1 -0
  63. package/dist/viewmodel/adapters/zod.d.ts +30 -0
  64. package/dist/viewmodel/adapters/zod.d.ts.map +1 -0
  65. package/dist/viewmodel/adapters/zod.js +7 -0
  66. package/dist/viewmodel/adapters/zod.js.map +1 -0
  67. package/dist/viewmodel/builder.d.ts +40 -0
  68. package/dist/viewmodel/builder.d.ts.map +1 -0
  69. package/dist/viewmodel/examples/all-adapters.d.ts +26 -0
  70. package/dist/viewmodel/examples/all-adapters.d.ts.map +1 -0
  71. package/dist/viewmodel/factory.d.ts +38 -0
  72. package/dist/viewmodel/factory.d.ts.map +1 -0
  73. package/dist/viewmodel/index.d.ts +10 -0
  74. package/dist/viewmodel/index.d.ts.map +1 -0
  75. package/dist/viewmodel/index.js +313 -0
  76. package/dist/viewmodel/index.js.map +1 -0
  77. package/dist/viewmodel/schema-adapter.d.ts +16 -0
  78. package/dist/viewmodel/schema-adapter.d.ts.map +1 -0
  79. package/dist/viewmodel/types.d.ts +97 -0
  80. package/dist/viewmodel/types.d.ts.map +1 -0
  81. package/package.json +29 -3
  82. package/src/applog/applog-utils.test.ts +43 -1
  83. package/src/applog/applog-utils.ts +38 -21
  84. package/src/applog/datom-types.ts +2 -2
  85. package/src/applog/object-values.test.ts +9 -9
  86. package/src/ipfs/car.ts +14 -2
  87. package/src/ipns/gateway-resolver.ts +63 -0
  88. package/src/ipns/ipns-record.ts +158 -29
  89. package/src/ipns/ipns-w3name.ts +207 -0
  90. package/src/ipns/ipns-watcher.ts +608 -0
  91. package/src/ipns.ts +3 -0
  92. package/src/pubsub/snap-push.ts +6 -5
  93. package/src/query/epoch-snapshot.test.ts +594 -0
  94. package/src/query/epoch-snapshot.ts +392 -0
  95. package/src/query.ts +1 -0
  96. package/src/viewmodel/adapters/arktype.ts +44 -0
  97. package/src/viewmodel/adapters/typebox.ts +59 -0
  98. package/src/viewmodel/adapters/typia.ts +50 -0
  99. package/src/viewmodel/adapters/zod.ts +55 -0
  100. package/src/viewmodel/builder.ts +71 -0
  101. package/src/viewmodel/examples/all-adapters.ts +206 -0
  102. package/src/viewmodel/factory.ts +330 -0
  103. package/src/viewmodel/index.ts +22 -0
  104. package/src/viewmodel/schema-adapter.ts +27 -0
  105. package/src/viewmodel/types.ts +152 -0
  106. package/dist/chunk-22WDFLXO.js +0 -138
  107. package/dist/chunk-22WDFLXO.js.map +0 -1
  108. package/dist/chunk-6ALNRM3J.js.map +0 -1
  109. package/dist/chunk-SHUHRHOT.js.map +0 -1
  110. /package/dist/{chunk-HUIQ54TT.js.map → chunk-6CSJTSQP.js.map} +0 -0
  111. /package/dist/{chunk-BLF5MAWU.js.map → chunk-BIYQEX3N.js.map} +0 -0
  112. /package/dist/{chunk-OC6Z6CQW.js.map → chunk-H4YVJKB7.js.map} +0 -0
@@ -18,7 +18,7 @@ import {
18
18
  rollingFilter,
19
19
  rollingMapper,
20
20
  sortApplogsByTs
21
- } from "./chunk-SHUHRHOT.js";
21
+ } from "./chunk-4MKPGQIM.js";
22
22
 
23
23
  // src/query/types.ts
24
24
  var QueryNode = class {
@@ -27,6 +27,9 @@ var QueryNode = class {
27
27
  this.variables = variables;
28
28
  this.prevNode = prevNode;
29
29
  }
30
+ logsOfThisNode;
31
+ variables;
32
+ prevNode;
30
33
  get record() {
31
34
  return this.variables;
32
35
  }
@@ -45,6 +48,7 @@ var QueryResult = class {
45
48
  constructor(nodes) {
46
49
  this.nodes = nodes;
47
50
  }
51
+ nodes;
48
52
  get size() {
49
53
  return this.nodes.length;
50
54
  }
@@ -86,6 +90,7 @@ var LiveQueryResult = class {
86
90
  });
87
91
  }
88
92
  }
93
+ _source;
89
94
  _activationUnsub = null;
90
95
  /** Subscribe to node change events. Callback fires on future changes only. */
91
96
  subscribe(cb, type) {
@@ -1023,4 +1028,4 @@ export {
1023
1028
  withTimeout,
1024
1029
  throwOnTimeout
1025
1030
  };
1026
- //# sourceMappingURL=chunk-3SUFNJEZ.js.map
1031
+ //# sourceMappingURL=chunk-N7SEGHU4.js.map
@@ -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,25 @@
1
+ // src/viewmodel/adapters/zod.ts
2
+ function createZodAdapter(zodSchema, entityPrefix, options) {
3
+ const shape = zodSchema.shape;
4
+ const toAtPath = options?.toAtPath ?? ((prefix, name) => `${prefix}/${name}`);
5
+ const attributeDefs = Object.entries(shape).map(([name, fieldSchema]) => {
6
+ const isOptional = fieldSchema.isOptional() || fieldSchema.isNullable();
7
+ const atPath = options?.atOverrides?.[name] ?? toAtPath(entityPrefix, name);
8
+ return {
9
+ name,
10
+ atPath,
11
+ optional: isOptional
12
+ };
13
+ });
14
+ return {
15
+ getAttributeDefs: () => attributeDefs,
16
+ getDefaults: () => options?.defaults ?? {},
17
+ getEntityPrefix: () => entityPrefix,
18
+ createValidator: () => (value) => zodSchema.safeParse(value).success
19
+ };
20
+ }
21
+
22
+ export {
23
+ createZodAdapter
24
+ };
25
+ //# sourceMappingURL=chunk-XF4DWOAE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/viewmodel/adapters/zod.ts"],"sourcesContent":["import type { ApplogValue } from '../../applog/datom-types.ts'\nimport type { ISchemaAdapter, VMAttributeDef } from '../types.ts'\nimport type { ZodObject, ZodType, ZodTypeAny } from 'zod'\n\n/**\n * Create a schema adapter from a Zod object schema.\n *\n * Usage:\n * ```ts\n * import { z } from 'zod'\n * import { createZodAdapter } from '@wovin/core/viewmodel/adapters/zod'\n *\n * const MySchema = z.object({\n * name: z.string(),\n * age: z.number().optional(),\n * })\n *\n * const adapter = createZodAdapter(MySchema, 'myEntity')\n * ```\n *\n * The type parameter `T` is the inferred type of the schema.\n */\nexport function createZodAdapter<T extends Record<string, ApplogValue> = Record<string, ApplogValue>>(\n\tzodSchema: ZodObject<Record<string, ZodTypeAny>>,\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},\n): ISchemaAdapter<T> {\n\tconst shape = zodSchema.shape as Record<string, ZodTypeAny>\n\tconst toAtPath = options?.toAtPath ?? ((prefix, name) => `${prefix}/${name}`)\n\n\tconst attributeDefs: VMAttributeDef[] = Object.entries(shape).map(([name, fieldSchema]: [string, ZodTypeAny]) => {\n\t\tconst isOptional = fieldSchema.isOptional() || fieldSchema.isNullable()\n\t\tconst atPath = options?.atOverrides?.[name] ?? toAtPath(entityPrefix, name)\n\n\t\treturn {\n\t\t\tname,\n\t\t\tatPath,\n\t\t\toptional: isOptional,\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: () => (value: unknown): value is T => zodSchema.safeParse(value).success,\n\t}\n}\n"],"mappings":";AAsBO,SAAS,iBACf,WACA,cACA,SAQoB;AACpB,QAAM,QAAQ,UAAU;AACxB,QAAM,WAAW,SAAS,aAAa,CAAC,QAAQ,SAAS,GAAG,MAAM,IAAI,IAAI;AAE1E,QAAM,gBAAkC,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,MAAM,WAAW,MAA4B;AAChH,UAAM,aAAa,YAAY,WAAW,KAAK,YAAY,WAAW;AACtE,UAAM,SAAS,SAAS,cAAc,IAAI,KAAK,SAAS,cAAc,IAAI;AAE1E,WAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA,UAAU;AAAA,IACX;AAAA,EACD,CAAC;AAED,SAAO;AAAA,IACN,kBAAkB,MAAM;AAAA,IACxB,aAAa,MAAO,SAAS,YAAY,CAAC;AAAA,IAC1C,iBAAiB,MAAM;AAAA,IACvB,iBAAiB,MAAM,CAAC,UAA+B,UAAU,UAAU,KAAK,EAAE;AAAA,EACnF;AACD;","names":[]}
package/dist/index.js CHANGED
@@ -2,21 +2,25 @@ import "./chunk-E46VTKTZ.js";
2
2
  import "./chunk-7Z5YDQKK.js";
3
3
  import {
4
4
  fetchSnapshotChainUntil
5
- } from "./chunk-BLF5MAWU.js";
5
+ } from "./chunk-BIYQEX3N.js";
6
6
  import {
7
7
  agentToShortHash,
8
8
  integratePub,
9
9
  isShare,
10
10
  isSubscription
11
- } from "./chunk-OC6Z6CQW.js";
11
+ } from "./chunk-H4YVJKB7.js";
12
12
  import {
13
+ createEpochSnapshot,
13
14
  liveEntityCollection,
14
- queryDivergencesByPrev
15
- } from "./chunk-22WDFLXO.js";
15
+ purgeHistory,
16
+ queryDivergencesByPrev,
17
+ resolveTimeSpec,
18
+ serializeEpochSnapshot
19
+ } from "./chunk-N5QPZNKD.js";
16
20
  import {
17
21
  updateThreadFromSnapshot,
18
22
  withBlockCache
19
- } from "./chunk-HUIQ54TT.js";
23
+ } from "./chunk-6CSJTSQP.js";
20
24
  import {
21
25
  carFromBlob,
22
26
  chunkApplogs,
@@ -33,7 +37,7 @@ import {
33
37
  prepareSnapshotForPush,
34
38
  streamReaderToIterable,
35
39
  unchunkApplogsBlock
36
- } from "./chunk-6ALNRM3J.js";
40
+ } from "./chunk-H3JNNTVP.js";
37
41
  import "./chunk-YDAKBU6Q.js";
38
42
  import {
39
43
  LiveQueryResult,
@@ -77,7 +81,7 @@ import {
77
81
  throwOnTimeout,
78
82
  withTimeout,
79
83
  withoutDeleted
80
- } from "./chunk-3SUFNJEZ.js";
84
+ } from "./chunk-N7SEGHU4.js";
81
85
  import {
82
86
  AppLogNoCidTB,
83
87
  AppLogNoCidTBC,
@@ -118,6 +122,7 @@ import {
118
122
  cyrb53hash,
119
123
  dateNowIso,
120
124
  debounceWrites,
125
+ deriveDeterministicEntityID,
121
126
  encodeApplog,
122
127
  encodeApplogAndGetCid,
123
128
  encodeBlock,
@@ -133,7 +138,6 @@ import {
133
138
  getApplogNoCidTypeErrors,
134
139
  getApplogTypeErrors,
135
140
  getCidSync,
136
- getHashID,
137
141
  getLogsFromThread,
138
142
  getUntrackedFilterResults,
139
143
  getUntrackedPattern,
@@ -161,6 +165,7 @@ import {
161
165
  matchPartStatic,
162
166
  matchPattern,
163
167
  memoizedFn,
168
+ mintNewEntity,
164
169
  objEqualByKeys,
165
170
  prepareForPub,
166
171
  prettifyThreadName,
@@ -182,7 +187,7 @@ import {
182
187
  withAg,
183
188
  withPvFrom,
184
189
  withTs
185
- } from "./chunk-SHUHRHOT.js";
190
+ } from "./chunk-4MKPGQIM.js";
186
191
  import {
187
192
  BOOL,
188
193
  Bool,
@@ -250,12 +255,14 @@ export {
250
255
  containsCid,
251
256
  createDebugName,
252
257
  createDebugNameObj,
258
+ createEpochSnapshot,
253
259
  createObjMapper,
254
260
  cyrb53hash,
255
261
  dateNowIso,
256
262
  debounceWrites,
257
263
  decodePubFromBlocks,
258
264
  decodePubFromCar,
265
+ deriveDeterministicEntityID,
259
266
  encodeApplog,
260
267
  encodeApplogAndGetCid,
261
268
  encodeBlock,
@@ -280,7 +287,6 @@ export {
280
287
  getBlocksOfCar,
281
288
  getCidSync,
282
289
  getDecodedBlock,
283
- getHashID,
284
290
  getLogsFromThread,
285
291
  getUntrackedFilterResults,
286
292
  getUntrackedPattern,
@@ -331,12 +337,14 @@ export {
331
337
  matchPartStatic,
332
338
  matchPattern,
333
339
  memoizedFn,
340
+ mintNewEntity,
334
341
  objEqualByKeys,
335
342
  prefixAt,
336
343
  prefixAttrs,
337
344
  prepareForPub,
338
345
  prepareSnapshotForPush,
339
346
  prettifyThreadName,
347
+ purgeHistory,
340
348
  query,
341
349
  queryAndMap,
342
350
  queryDivergencesByPrev,
@@ -349,9 +357,11 @@ export {
349
357
  removeDuplicateAppLogs,
350
358
  resolveKeyMapper,
351
359
  resolveOrRemoveVariables,
360
+ resolveTimeSpec,
352
361
  rollingAcc,
353
362
  rollingFilter,
354
363
  rollingMapper,
364
+ serializeEpochSnapshot,
355
365
  simpleApplogMapper,
356
366
  sortApplogsByTs,
357
367
  startsWith,
@@ -1 +1 @@
1
- {"version":3,"file":"car.d.ts","sourceRoot":"","sources":["../../src/ipfs/car.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAGhD,OAAO,EAAa,GAAG,EAAE,MAAM,cAAc,CAAA;AAE7C,OAAO,EAAU,yBAAyB,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAOvF,MAAM,MAAM,SAAS,GAAG,GAAG,CAAA;AAC3B,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAEzD,MAAM,WAAW,aAAa;IAC7B,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,WAAW,CAAC,UAAU,CAAC,CAAA;CACtC;AAED,MAAM,WAAW,UAAU;IAC1B,OAAO,EAAE,GAAG,CAAA;IAEZ,UAAU,EAAE,aAAa,CAAA;CACzB;AAED,0CAA0C;AAC1C,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,SAAS;;;;;;;;;;;;;;;GAGpD;AAED,wBAAsB,mBAAmB,CACxC,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,UAAU,EACnC,eAAe,GAAE,GAAG,EAAO,EAAG,+DAA+D;AAC7F,SAAS,CAAC,EAAE,GAAG;;;;;;;;;;;;;;;GAgHf;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,SAAS;;;;;GAmBlD;AACD,wBAAsB,eAAe,CAAC,UAAU,EAAE,aAAa,EAAE,GAAG,EAAE,GAAG,oBAYxE;AAGD,wBAAsB,UAAU,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,uDASvE,CAAC,iEAAiE;AAWnE,wBAAsB,WAAW,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,iBAQxE;AACD,wBAAsB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,CAEvE;AAWD,wBAAsB,gBAAgB,CACrC,QAAQ,EAAE,GAAG,EACb,UAAU,EAAE,aAAa,GACvB,OAAO,CAAC,WAAW,EAAE,CAAC,CAiDxB;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,2BAA2B,CAAC,UAAU,CAAC,GAAG,aAAa,CAAC,UAAU,CAAC,CAWrH"}
1
+ {"version":3,"file":"car.d.ts","sourceRoot":"","sources":["../../src/ipfs/car.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAGhD,OAAO,EAAa,GAAG,EAAE,MAAM,cAAc,CAAA;AAE7C,OAAO,EAAU,yBAAyB,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAOvF,MAAM,MAAM,SAAS,GAAG,GAAG,CAAA;AAC3B,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAEzD,MAAM,WAAW,aAAa;IAC7B,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,WAAW,CAAC,UAAU,CAAC,CAAA;CACtC;AAED,MAAM,WAAW,UAAU;IAC1B,OAAO,EAAE,GAAG,CAAA;IAEZ,UAAU,EAAE,aAAa,CAAA;CACzB;AAED,0CAA0C;AAC1C,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,SAAS;;;;;;;;;;;;;;;GAGpD;AAED,wBAAsB,mBAAmB,CACxC,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,UAAU,EACnC,eAAe,GAAE,GAAG,EAAO,EAAG,+DAA+D;AAC7F,SAAS,CAAC,EAAE,GAAG;;;;;;;;;;;;;;;GA4Hf;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,SAAS;;;;;GAmBlD;AACD,wBAAsB,eAAe,CAAC,UAAU,EAAE,aAAa,EAAE,GAAG,EAAE,GAAG,oBAYxE;AAGD,wBAAsB,UAAU,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,uDASvE,CAAC,iEAAiE;AAWnE,wBAAsB,WAAW,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,iBAQxE;AACD,wBAAsB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,CAEvE;AAWD,wBAAsB,gBAAgB,CACrC,QAAQ,EAAE,GAAG,EACb,UAAU,EAAE,aAAa,GACvB,OAAO,CAAC,WAAW,EAAE,CAAC,CAiDxB;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,2BAA2B,CAAC,UAAU,CAAC,GAAG,aAAa,CAAC,UAAU,CAAC,CAWrH"}