@wovin/core 0.0.0-ciao-mobx-955482e8

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 (180) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +3 -0
  3. package/dist/applog/applog-helpers.d.ts +47 -0
  4. package/dist/applog/applog-helpers.d.ts.map +1 -0
  5. package/dist/applog/applog-utils.d.ts +57 -0
  6. package/dist/applog/applog-utils.d.ts.map +1 -0
  7. package/dist/applog/datom-types.d.ts +128 -0
  8. package/dist/applog/datom-types.d.ts.map +1 -0
  9. package/dist/applog.d.ts +4 -0
  10. package/dist/applog.d.ts.map +1 -0
  11. package/dist/applog.js +101 -0
  12. package/dist/applog.js.map +1 -0
  13. package/dist/blockstore/index.d.ts +21 -0
  14. package/dist/blockstore/index.d.ts.map +1 -0
  15. package/dist/blockstore.d.ts +2 -0
  16. package/dist/blockstore.d.ts.map +1 -0
  17. package/dist/blockstore.js +24 -0
  18. package/dist/blockstore.js.map +1 -0
  19. package/dist/chunk-6MQKRL6W.js +86 -0
  20. package/dist/chunk-6MQKRL6W.js.map +1 -0
  21. package/dist/chunk-7MW34UEO.js +40 -0
  22. package/dist/chunk-7MW34UEO.js.map +1 -0
  23. package/dist/chunk-7Z5YDQKK.js +1 -0
  24. package/dist/chunk-7Z5YDQKK.js.map +1 -0
  25. package/dist/chunk-CY4NLISM.js +144 -0
  26. package/dist/chunk-CY4NLISM.js.map +1 -0
  27. package/dist/chunk-E46VTKTZ.js +1 -0
  28. package/dist/chunk-E46VTKTZ.js.map +1 -0
  29. package/dist/chunk-O43W7UW6.js +434 -0
  30. package/dist/chunk-O43W7UW6.js.map +1 -0
  31. package/dist/chunk-XIQSYEV3.js +1604 -0
  32. package/dist/chunk-XIQSYEV3.js.map +1 -0
  33. package/dist/chunk-XVGW4QC3.js +55 -0
  34. package/dist/chunk-XVGW4QC3.js.map +1 -0
  35. package/dist/chunk-YDAKBU6Q.js +9 -0
  36. package/dist/chunk-YDAKBU6Q.js.map +1 -0
  37. package/dist/chunk-ZAADLBSB.js +36 -0
  38. package/dist/chunk-ZAADLBSB.js.map +1 -0
  39. package/dist/chunk-ZXCJRYD7.js +883 -0
  40. package/dist/chunk-ZXCJRYD7.js.map +1 -0
  41. package/dist/index.d.ts +8 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +354 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/ipfs/car.d.ts +59 -0
  46. package/dist/ipfs/car.d.ts.map +1 -0
  47. package/dist/ipfs/fetch-snapshot-chain.d.ts +32 -0
  48. package/dist/ipfs/fetch-snapshot-chain.d.ts.map +1 -0
  49. package/dist/ipfs/ipfs-utils.d.ts +35 -0
  50. package/dist/ipfs/ipfs-utils.d.ts.map +1 -0
  51. package/dist/ipfs.d.ts +4 -0
  52. package/dist/ipfs.d.ts.map +1 -0
  53. package/dist/ipfs.js +60 -0
  54. package/dist/ipfs.js.map +1 -0
  55. package/dist/ipns/ipns-record.d.ts +34 -0
  56. package/dist/ipns/ipns-record.d.ts.map +1 -0
  57. package/dist/ipns.d.ts +2 -0
  58. package/dist/ipns.d.ts.map +1 -0
  59. package/dist/ipns.js +64 -0
  60. package/dist/ipns.js.map +1 -0
  61. package/dist/pubsub/connector.d.ts +9 -0
  62. package/dist/pubsub/connector.d.ts.map +1 -0
  63. package/dist/pubsub/pub-pull.d.ts +14 -0
  64. package/dist/pubsub/pub-pull.d.ts.map +1 -0
  65. package/dist/pubsub/pubsub-types.d.ts +72 -0
  66. package/dist/pubsub/pubsub-types.d.ts.map +1 -0
  67. package/dist/pubsub/snap-push.d.ts +41 -0
  68. package/dist/pubsub/snap-push.d.ts.map +1 -0
  69. package/dist/pubsub/ucan-example.d.ts +3 -0
  70. package/dist/pubsub/ucan-example.d.ts.map +1 -0
  71. package/dist/pubsub/ucan.d.ts +16 -0
  72. package/dist/pubsub/ucan.d.ts.map +1 -0
  73. package/dist/pubsub.d.ts +5 -0
  74. package/dist/pubsub.d.ts.map +1 -0
  75. package/dist/pubsub.js +31 -0
  76. package/dist/pubsub.js.map +1 -0
  77. package/dist/query/basic.d.ts +105 -0
  78. package/dist/query/basic.d.ts.map +1 -0
  79. package/dist/query/divergences.d.ts +12 -0
  80. package/dist/query/divergences.d.ts.map +1 -0
  81. package/dist/query/matchers.d.ts +4 -0
  82. package/dist/query/matchers.d.ts.map +1 -0
  83. package/dist/query/memoized.d.ts +66 -0
  84. package/dist/query/memoized.d.ts.map +1 -0
  85. package/dist/query/query-steps.d.ts +4 -0
  86. package/dist/query/query-steps.d.ts.map +1 -0
  87. package/dist/query/situations.d.ts +80 -0
  88. package/dist/query/situations.d.ts.map +1 -0
  89. package/dist/query/subscribable.d.ts +102 -0
  90. package/dist/query/subscribable.d.ts.map +1 -0
  91. package/dist/query/types.d.ts +70 -0
  92. package/dist/query/types.d.ts.map +1 -0
  93. package/dist/query.d.ts +8 -0
  94. package/dist/query.d.ts.map +1 -0
  95. package/dist/query.js +108 -0
  96. package/dist/query.js.map +1 -0
  97. package/dist/retrieve/index.d.ts +2 -0
  98. package/dist/retrieve/index.d.ts.map +1 -0
  99. package/dist/retrieve/update-thread.d.ts +64 -0
  100. package/dist/retrieve/update-thread.d.ts.map +1 -0
  101. package/dist/retrieve.d.ts +2 -0
  102. package/dist/retrieve.d.ts.map +1 -0
  103. package/dist/retrieve.js +14 -0
  104. package/dist/retrieve.js.map +1 -0
  105. package/dist/thread/basic.d.ts +60 -0
  106. package/dist/thread/basic.d.ts.map +1 -0
  107. package/dist/thread/filters.d.ts +47 -0
  108. package/dist/thread/filters.d.ts.map +1 -0
  109. package/dist/thread/mapped.d.ts +31 -0
  110. package/dist/thread/mapped.d.ts.map +1 -0
  111. package/dist/thread/utils.d.ts +23 -0
  112. package/dist/thread/utils.d.ts.map +1 -0
  113. package/dist/thread/writeable.d.ts +41 -0
  114. package/dist/thread/writeable.d.ts.map +1 -0
  115. package/dist/thread.d.ts +6 -0
  116. package/dist/thread.d.ts.map +1 -0
  117. package/dist/thread.js +54 -0
  118. package/dist/thread.js.map +1 -0
  119. package/dist/types/typescript-utils.d.ts +34 -0
  120. package/dist/types/typescript-utils.d.ts.map +1 -0
  121. package/dist/types.d.ts +2 -0
  122. package/dist/types.d.ts.map +1 -0
  123. package/dist/types.js +26 -0
  124. package/dist/types.js.map +1 -0
  125. package/dist/utils/debug-name.d.ts +13 -0
  126. package/dist/utils/debug-name.d.ts.map +1 -0
  127. package/dist/utils.d.ts +4 -0
  128. package/dist/utils.d.ts.map +1 -0
  129. package/dist/utils.js +9 -0
  130. package/dist/utils.js.map +1 -0
  131. package/package.json +110 -0
  132. package/src/applog/applog-helpers.ts +150 -0
  133. package/src/applog/applog-utils.ts +398 -0
  134. package/src/applog/datom-types.ts +148 -0
  135. package/src/applog.ts +3 -0
  136. package/src/blockstore/index.ts +36 -0
  137. package/src/blockstore.ts +1 -0
  138. package/src/index.ts +8 -0
  139. package/src/ipfs/car.ts +291 -0
  140. package/src/ipfs/fetch-snapshot-chain.ts +135 -0
  141. package/src/ipfs/ipfs-utils.ts +132 -0
  142. package/src/ipfs.ts +3 -0
  143. package/src/ipns/ipns-record.ts +115 -0
  144. package/src/ipns.ts +1 -0
  145. package/src/pubsub/UCAN Specs Overview.md +217 -0
  146. package/src/pubsub/connector.ts +9 -0
  147. package/src/pubsub/pub-pull.ts +31 -0
  148. package/src/pubsub/pubsub-types.ts +90 -0
  149. package/src/pubsub/snap-push.ts +277 -0
  150. package/src/pubsub/ucan-example.ts +61 -0
  151. package/src/pubsub/ucan.ts +56 -0
  152. package/src/pubsub.ts +4 -0
  153. package/src/query/basic.ts +1061 -0
  154. package/src/query/divergences.ts +50 -0
  155. package/src/query/matchers.ts +8 -0
  156. package/src/query/memoized.test.ts +151 -0
  157. package/src/query/memoized.ts +180 -0
  158. package/src/query/query-steps.ts +4 -0
  159. package/src/query/query.test.ts +536 -0
  160. package/src/query/situations.ts +261 -0
  161. package/src/query/subscribable.test.ts +245 -0
  162. package/src/query/subscribable.ts +225 -0
  163. package/src/query/types.ts +155 -0
  164. package/src/query.ts +7 -0
  165. package/src/retrieve/index.ts +1 -0
  166. package/src/retrieve/update-thread.ts +248 -0
  167. package/src/retrieve.ts +1 -0
  168. package/src/test/perf/query.1m.perf.test.ts +94 -0
  169. package/src/test/perf/query.perf.test.ts +389 -0
  170. package/src/test/perf/query.realdata.perf.test.ts +175 -0
  171. package/src/thread/basic.ts +209 -0
  172. package/src/thread/filters.ts +234 -0
  173. package/src/thread/mapped.ts +166 -0
  174. package/src/thread/utils.ts +146 -0
  175. package/src/thread/writeable.ts +163 -0
  176. package/src/thread.ts +5 -0
  177. package/src/types/typescript-utils.ts +64 -0
  178. package/src/types.ts +1 -0
  179. package/src/utils/debug-name.ts +54 -0
  180. package/src/utils.ts +4 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/thread/basic.ts","../src/query/subscribable.ts","../src/utils/debug-name.ts","../src/thread/filters.ts","../src/applog/applog-helpers.ts","../src/ipfs/ipfs-utils.ts","../src/applog/datom-types.ts","../src/applog/applog-utils.ts","../src/query/memoized.ts","../src/thread/mapped.ts","../src/thread/writeable.ts","../src/thread/utils.ts"],"sourcesContent":["import { Logger } from 'besonders-logger'\nimport { createBLAKE3 } from 'hash-wasm'\nimport { pick } from 'lodash-es'\nimport { CID } from 'multiformats'\nimport { arraysContainSameElements } from '../applog/applog-utils.ts'\nimport { areApplogsEqual } from '../applog/applog-utils.ts'\nimport { type Applog, ApplogForInsert, CidString } from '../applog/datom-types.ts'\nimport type { SubscribableArray, ArrayEvent } from '../query/subscribable.ts'\nimport { isArrayInitEvent } from '../query/subscribable.ts'\nimport { areCidsEqual } from '../ipfs/ipfs-utils.ts'\nimport { prettifyThreadName } from '../utils/debug-name.ts'\nimport { arrayIfSingle, ArrayOrSingle } from '../types/typescript-utils.ts'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO, { prefix: '[thread]' })\n\nexport type ThreadEvent = ArrayEvent<Applog>\n/** @deprecated Use isArrayInitEvent from @wovin/core/query */\nexport const isInitEvent = isArrayInitEvent\n\nexport type ApplogsOrThread = Thread | readonly Applog[]\n\n// const blakeHasher = await createBLAKE3()\n\nexport abstract class Thread implements SubscribableArray<Applog> {\n\treadonly filters: readonly string[]\n\treadonly parents: Thread[] | readonly Thread[] | null\n\tprotected _derivedSubscribers: ((event: ThreadEvent) => void)[] = []\n\tprotected _subscribers: ((event: ThreadEvent) => void)[] = []\n\t/** Monotonic counter incremented on every mutation. Used by memoizedFn to invalidate caches. */\n\t_version = 0\n\n\tconstructor(\n\t\treadonly name: string, /* = null */\n\t\tparents: ArrayOrSingle<Thread> | readonly Thread[] | null,\n\t\tfilters: readonly string[],\n\t\tprotected _applogs: Applog[] = [],\n\t) {\n\t\tthis.parents = parents === null ? null : arrayIfSingle(parents) as readonly Thread[]\n\t\tthis.filters = filters // ? uniq([...parents?.map(p => p.filters), filters])\n\t\tif (this.parents?.length === 0) {\n\t\t\tWARN(`[Thread] empty parents array`, name) // just to see where it happens, is actually mostly fine\n\t\t}\n\t}\n\n\tget readOnly() {\n\t\tif (this.parents.length !== 1) return true // ? multi-parent writable stream? - we don't have a use-case for this yet, but could this be a thing?\n\t\treturn this.parents[0].readOnly\n\t}\n\n\tpublic insert(appLogsToInsert: ArrayOrSingle<ApplogForInsert>) {\n\t\tif (this.readOnly) throw ERROR(`[Thread] insert() called on read-only thread:`, this.nameAndSizeUntracked)\n\t\tif (!this.parents) throw ERROR(`[Thread] insert() called on non-writable thread without parents:`, this.nameAndSizeUntracked)\n\t\tif (this.parents?.length !== 1) throw ERROR(`[Thread] insert() called on thread with multiple parents:`, this.nameAndSizeUntracked)\n\t\treturn this.parents[0].insert(appLogsToInsert)\n\t}\n\tpublic insertRaw(appLogsToInsert: readonly Applog[]) {\n\t\tif (this.readOnly) throw ERROR(`[Thread] insertRaw() called on read-only thread:`, this.nameAndSizeUntracked)\n\t\tif (!this.parents) throw ERROR(`[Thread] insertRaw() called on non-writable thread without parents:`, this.nameAndSizeUntracked)\n\t\tif (this.parents?.length !== 1) throw ERROR(`[Thread] insertRaw() called on thread with multiple parents:`, this.nameAndSizeUntracked)\n\t\treturn this.parents[0].insertRaw(appLogsToInsert)\n\t}\n\n\tsubscribe(callback: (event: ThreadEvent) => void, type?: 'derived' | 'reaction') {\n\t\tconst list = type === 'derived' ? this._derivedSubscribers : this._subscribers\n\t\tlist.push(callback)\n\t\treturn () => {\n\t\t\tconst idx = list.indexOf(callback)\n\t\t\tif (idx >= 0) list.splice(idx, 1)\n\t\t}\n\t}\n\n\tprotected notifySubscribers(event: ThreadEvent) {\n\t\tthis._version++\n\t\tDEBUG(`[thread: ${this.name}] notifying`, this._derivedSubscribers.length, 'derived +', this._subscribers.length, 'subscribers of', { ...event, subs: this._subscribers })\n\t\tconst derived = [...this._derivedSubscribers] // snapshot — safe if a subscriber unsubs during iteration\n\t\tfor (const subscriber of derived) {\n\t\t\tsubscriber(event)\n\t\t}\n\t\tconst subs = [...this._subscribers]\n\t\tfor (const subscriber of subs) {\n\t\t\tsubscriber(event)\n\t\t}\n\t}\n\n\t// ── SubscribableArray<Applog> ──\n\tget items(): readonly Applog[] { return this._applogs }\n\n\tdispose() {\n\t\tthis._derivedSubscribers.length = 0\n\t\tthis._subscribers.length = 0\n\t}\n\n\tget applogs(): readonly Applog[] /* (i) only type hint, not actually immutable */ {\n\t\t// VERBOSE.isDisabled || trace()\n\t\treturn this._applogs\n\t}\n\tget applogsCids(): readonly CidString[] {\n\t\treturn this._applogs.map(l => l.cid)\n\t}\n\tget applogsCidSet(): ReadonlySet<CidString> {\n\t\treturn new Set(this._applogs.map(l => l.cid))\n\t}\n\n\tpublic map<R>(fn: (applog: Applog) => R) {\n\t\t// if (!this.applogs.map) throw ERROR(`thread.applogs is not an array?!`, this.applogs)\n\t\treturn this.applogs.map(fn)\n\t}\n\tpublic get findLast() {\n\t\treturn this.applogs.findLast.bind(this.applogs)\n\t}\n\tpublic get findFirst() {\n\t\treturn this.applogs.find.bind(this.applogs)\n\t}\n\n\tget firstLog() {\n\t\treturn this.applogs[0]\n\t}\n\tget latestLog() {\n\t\treturn this.applogs[this.applogs.length - 1]\n\t}\n\tpublic hasApplog(applog: Applog, byRef: boolean) {\n\t\tif (byRef) {\n\t\t\treturn this.applogs.includes(applog)\n\t\t} else {\n\t\t\tif (!applog.cid) throw ERROR(`[hasApplogs] applog without CID:`, applog) // trying to make this be always the case\n\t\t\treturn this.hasApplogCid(applog.cid)\n\t\t\t// const keySet = Object.keys(applog) / / HACK: sanity check to catch bugs\n\t\t\t// return !!this.applogs.find(log => {\n\t\t\t// \tif (!arraysContainSameElements(keySet, Object.keys(log))) {\n\t\t\t// \t\t/* throw */ ERROR(`[hasApplog] field set mismatch:`, { applog, log }) / / HACK: properly handle this\n\t\t\t// \t\treturn comparer.structural(pick(log, ['en', 'at', 'vl', 'ag', 'ts']), pick(applog, ['en', 'at', 'vl', 'ag', 'ts']))\n\t\t\t// \t}\n\t\t\t// \treturn areApplogsEqual(log, applog)\n\t\t\t// })\n\t\t}\n\t}\n\tpublic hasApplogCid(cid: CID | CidString) {\n\t\treturn this.applogsCidSet.has(cid.toString()) // O(1) via Set vs O(n) via includes\n\t}\n\tget applogsByCid() {\n\t\treturn new Map(this.applogs.map(log => [log.cid, log]))\n\t}\n\tpublic getApplog(cid: CID | CidString) {\n\t\treturn this.applogsByCid.get(cid.toString())\n\t\t// \t.find(function findApplogInThread(log) {\n\t\t// \treturn areCidsEqual(log.cid, cid)\n\t\t// })\n\t}\n\n\tpublic hasApplogWithDiffTs(applog: ApplogForInsert) {\n\t\t// HACK this is basically as inefficient as it gets\n\t\treturn this.applogs.find(existing => (\n\t\t\texisting.en === applog.en\n\t\t\t&& existing.at === applog.at\n\t\t\t&& existing.vl === applog.vl\n\t\t\t&& existing.ag === applog.ag\n\t\t))\n\t}\n\n\t// get stateHash() {\n\t// \tblakeHasher.init()\n\t// \tfor (const log of this.applogs) {\n\t// \t\tblakeHasher.update(log.cid)\n\t// \t}\n\t// \treturn blakeHasher.digest()\n\t// }\n\n\tget isEmpty() {\n\t\treturn this.size === 0\n\t}\n\tget size() {\n\t\treturn this.applogs.length\n\t}\n\tget length() {\n\t\treturn this.applogs.length\n\t}\n\tget untrackedSize() {\n\t\treturn this.size\n\t}\n\tget nameAndSizeUntracked() {\n\t\treturn `${this.name} (${this.size})`\n\t}\n\tget prettyName() {\n\t\treturn prettifyThreadName(this.name)\n\t}\n\tget hasParents() {\n\t\treturn !!this.parents?.length\n\t}\n}\n\nexport const getLogsFromThread = (logsOrThread: ApplogsOrThread) => logsOrThread instanceof Thread ? logsOrThread.applogs : logsOrThread\n\nexport class StaticThread extends Thread {\n\tstatic fromArray(applogs: Applog[], name?: string) {\n\t\treturn new StaticThread(name || 'static', null, [], applogs)\n\t}\n\tconstructor(\n\t\tname: string, /* = null */\n\t\tparents: ArrayOrSingle<Thread> | readonly Thread[] | null,\n\t\tfilters: readonly string[],\n\t\t_applogs: Applog[],\n\t) {\n\t\tsuper(name, parents, filters, _applogs)\n\t}\n\n\tget readOnly() {\n\t\treturn true\n\t}\n}\n","/**\n * Push-based subscribable primitives for the query system.\n *\n * Two primitives:\n * - Subscribable<T> — any value + \"changed\" notifications\n * - SubscribableArray<T> — array + incremental delta events (added/removed)\n *\n * Key property: **lazy subscribe** — upstream subscriptions only activate\n * when the first subscriber attaches, and deactivate when the last leaves.\n * This means one-off reads (.value / .items) have zero subscription overhead.\n */\n\nexport type Unsubscribe = () => void\n\n// ═══════════════════════════════════════════════════════════════\n// Subscribable<T> — generic single-value\n// ═══════════════════════════════════════════════════════════════\n\nexport interface Subscribable<T> {\n\t/** Current value — plain read, no side effects */\n\treadonly value: T\n\n\t/**\n\t * Subscribe to change notifications.\n\t * - First call activates upstream subscriptions (lazy).\n\t * - Callback does NOT fire immediately — read .value for current state.\n\t * - Callback fires whenever .value changes.\n\t * - Last unsubscribe deactivates upstream.\n\t */\n\tsubscribe(cb: () => void, type?: 'derived' | 'reaction'): Unsubscribe\n\n\t/** Tear down all internal subscriptions */\n\tdispose(): void\n}\n\n/**\n * Implementation of Subscribable<T> with lazy upstream activation.\n */\nexport class SubscribableImpl<T> implements Subscribable<T> {\n\tprivate _value: T\n\tprivate _derivedSubscribers: (() => void)[] = []\n\tprivate _subscribers: (() => void)[] = []\n\tprivate _upstreamActive = false\n\tprivate _activateUpstream: (() => Unsubscribe) | null\n\tprivate _deactivateUpstream: Unsubscribe | null = null\n\tprivate _equals: (a: T, b: T) => boolean\n\n\tconstructor(\n\t\tinitialValue: T,\n\t\tactivateUpstream?: () => Unsubscribe,\n\t\topts?: { equals?: false | ((a: T, b: T) => boolean) },\n\t) {\n\t\tthis._value = initialValue\n\t\tthis._activateUpstream = activateUpstream ?? null\n\t\tthis._equals = opts?.equals === false ? () => false : (opts?.equals ?? ((a, b) => a === b))\n\t}\n\n\tget value(): T { return this._value }\n\n\tsubscribe(cb: () => void, type?: 'derived' | 'reaction'): Unsubscribe {\n\t\tif (!this._upstreamActive && this._activateUpstream) {\n\t\t\tthis._deactivateUpstream = this._activateUpstream()\n\t\t\tthis._upstreamActive = true\n\t\t}\n\n\t\tconst list = type === 'derived' ? this._derivedSubscribers : this._subscribers\n\t\tlist.push(cb)\n\t\t// No immediate callback — subscriber reads .value for current state\n\n\t\treturn () => {\n\t\t\tconst idx = list.indexOf(cb)\n\t\t\tif (idx >= 0) list.splice(idx, 1)\n\n\t\t\tif (this._derivedSubscribers.length === 0 && this._subscribers.length === 0 && this._upstreamActive) {\n\t\t\t\tthis._deactivateUpstream?.()\n\t\t\t\tthis._deactivateUpstream = null\n\t\t\t\tthis._upstreamActive = false\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Update value and notify subscribers (skips if equals check passes) */\n\t_set(value: T) {\n\t\tif (this._equals(value, this._value)) return\n\t\tthis._value = value\n\t\tthis._notify()\n\t}\n\n\tprivate _notify() {\n\t\tconst derived = [...this._derivedSubscribers]\n\t\tfor (const sub of derived) sub()\n\t\tconst subs = [...this._subscribers]\n\t\tfor (const sub of subs) sub()\n\t}\n\n\tdispose() {\n\t\tthis._deactivateUpstream?.()\n\t\tthis._deactivateUpstream = null\n\t\tthis._derivedSubscribers.length = 0\n\t\tthis._subscribers.length = 0\n\t\tthis._upstreamActive = false\n\t}\n}\n\n// ═══════════════════════════════════════════════════════════════\n// SubscribableArray<T> — array with delta events\n// ═══════════════════════════════════════════════════════════════\n\n/** Delta events — mirrors ThreadEvent shape */\nexport type ArrayEvent<T> =\n\t| { init: readonly T[] }\n\t| { added: readonly T[]; removed: readonly T[] | null }\n\n/** Type guard for init events. Same logic as thread's isInitEvent. */\nexport function isArrayInitEvent<T>(event: ArrayEvent<T>): event is { init: readonly T[] } {\n\treturn (event as any).init !== undefined\n}\n\nexport interface SubscribableArray<T> {\n\t/** Current snapshot — plain readonly array */\n\treadonly items: readonly T[]\n\n\t/** Length shortcut */\n\treadonly length: number\n\n\t/**\n\t * Subscribe to delta events.\n\t * - First call activates upstream subscriptions (lazy).\n\t * - No init event on subscribe — read .items for current state.\n\t * - Receives `{ init }` only on genuine resets (triggerRemap).\n\t * - Last unsubscribe deactivates upstream.\n\t */\n\tsubscribe(cb: (event: ArrayEvent<T>) => void, type?: 'derived' | 'reaction'): Unsubscribe\n\n\t/** Tear down all internal subscriptions */\n\tdispose(): void\n}\n\n/**\n * Implementation of SubscribableArray with lazy upstream activation.\n *\n * Constructor takes initial items (computed synchronously at query time)\n * and an optional activation function that sets up upstream subscriptions.\n * The activation function is only called on first `.subscribe()`.\n */\nexport class SubscribableArrayImpl<T> implements SubscribableArray<T> {\n\tprivate _items: T[]\n\tprivate _derivedSubscribers: ((event: ArrayEvent<T>) => void)[] = []\n\tprivate _subscribers: ((event: ArrayEvent<T>) => void)[] = []\n\tprivate _upstreamActive = false\n\tprivate _activateUpstream: (() => Unsubscribe) | null\n\tprivate _deactivateUpstream: Unsubscribe | null = null\n\n\tconstructor(\n\t\tinitialItems: T[],\n\t\tactivateUpstream?: () => Unsubscribe,\n\t) {\n\t\tthis._items = initialItems\n\t\tthis._activateUpstream = activateUpstream ?? null\n\t}\n\n\tget items(): readonly T[] { return this._items }\n\tget length(): number { return this._items.length }\n\n\tsubscribe(cb: (event: ArrayEvent<T>) => void, type?: 'derived' | 'reaction'): Unsubscribe {\n\t\t// Activate upstream on first subscriber (lazy)\n\t\tif (!this._upstreamActive && this._activateUpstream) {\n\t\t\tthis._deactivateUpstream = this._activateUpstream()\n\t\t\tthis._upstreamActive = true\n\t\t}\n\n\t\tconst list = type === 'derived' ? this._derivedSubscribers : this._subscribers\n\t\tlist.push(cb)\n\t\t// No init event — subscriber reads .items for current state\n\n\t\treturn () => {\n\t\t\tconst idx = list.indexOf(cb)\n\t\t\tif (idx >= 0) list.splice(idx, 1)\n\n\t\t\t// Deactivate upstream when last subscriber leaves\n\t\t\tif (this._derivedSubscribers.length === 0 && this._subscribers.length === 0 && this._upstreamActive) {\n\t\t\t\tthis._deactivateUpstream?.()\n\t\t\t\tthis._deactivateUpstream = null\n\t\t\t\tthis._upstreamActive = false\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Push items and notify subscribers */\n\t_push(...items: T[]) {\n\t\tthis._items.push(...items)\n\t\tthis._notify({ added: items, removed: null })\n\t}\n\n\t/** Remove items and notify subscribers */\n\t_remove(items: readonly T[]) {\n\t\tfor (const item of items) {\n\t\t\tconst idx = this._items.indexOf(item)\n\t\t\tif (idx >= 0) this._items.splice(idx, 1)\n\t\t}\n\t\tthis._notify({ added: [], removed: items })\n\t}\n\n\t/** Full reset — replace all items */\n\t_reset(items: T[]) {\n\t\tthis._items = items\n\t\tthis._notify({ init: [...this._items] })\n\t}\n\n\tprivate _notify(event: ArrayEvent<T>) {\n\t\t// Snapshot: subscriber callbacks may synchronously unsubscribe during iteration\n\t\tconst derived = [...this._derivedSubscribers]\n\t\tfor (const sub of derived) sub(event)\n\t\tconst subs = [...this._subscribers]\n\t\tfor (const sub of subs) sub(event)\n\t}\n\n\tdispose() {\n\t\tthis._deactivateUpstream?.()\n\t\tthis._deactivateUpstream = null\n\t\tthis._derivedSubscribers.length = 0\n\t\tthis._subscribers.length = 0\n\t\tthis._upstreamActive = false\n\t}\n}\n","import stringify from 'safe-stable-stringify'\nimport type { Applog, DatalogQueryPattern } from '../applog/datom-types.ts'\nimport type { Thread } from '../thread/basic.ts'\n\nexport const createDebugName = ({ caller, thread, pattern, args }: {\n\tcaller?: string\n\tthread?: Thread | Applog[]\n\tpattern?: DatalogQueryPattern | DatalogQueryPattern[] | string\n\targs?: any\n}) => {\n\targs = args || pattern\n\tconst str = `${(!Array.isArray(thread) && thread?.name) ? thread.name + ' | ' : ''}`\n\t\t+ `${caller ?? 'caller?'}`\n\t\t+ `${args ? `{${typeof args === 'string' ? args : stringify(args)}}` : ''}`\n\treturn str\n}\n\nexport const createDebugNameObj = (args: Parameters<typeof createDebugName>[0]) => {\n\treturn { name: createDebugName(args) } as const\n}\n\nexport function prettifyThreadName(input: string): string {\n\tlet depth = 0\n\tlet result = ''\n\tlet insideCurlyBraces = 0\n\n\tfor (let i = 0; i < input.length; i++) {\n\t\tconst char = input[i]\n\n\t\tif (char === '(') {\n\t\t\tresult += char + '\\n' + '\\t'.repeat(++depth)\n\t\t} else if (char === ')') {\n\t\t\tresult += '\\n' + '\\t'.repeat(--depth) + char\n\t\t} else if (char === ',' && insideCurlyBraces === 0) {\n\t\t\tresult += char + '\\n' + '\\t'.repeat(depth)\n\t\t} else if (char === '{' && insideCurlyBraces === 0) {\n\t\t\tinsideCurlyBraces++\n\t\t\tresult += char + '\\n' + '\\t'.repeat(depth + 1)\n\t\t} else if (char === '}' && insideCurlyBraces === 1) {\n\t\t\tinsideCurlyBraces--\n\t\t\tresult += '\\n' + '\\t'.repeat(depth) + char\n\t\t} else if (char === '{' && insideCurlyBraces > 0) {\n\t\t\tinsideCurlyBraces++\n\t\t\tresult += char\n\t\t} else if (char === '}' && insideCurlyBraces > 1) {\n\t\t\tinsideCurlyBraces--\n\t\t\tresult += char\n\t\t} else {\n\t\t\tresult += char\n\t\t}\n\t}\n\n\treturn result\n}\n","import { Logger } from 'besonders-logger'\nimport stringify from 'safe-stable-stringify'\nimport { finalizeApplogForInsert } from '../applog/applog-helpers.ts'\nimport { dateNowIso, matchPartStatic } from '../applog/applog-utils.ts'\nimport { Applog, ApplogForInsert, ApplogValue, CidString, DatalogQueryPattern, ValueOrMatcher } from '../applog/datom-types.ts'\nimport { createDebugName } from '../utils/debug-name.ts'\nimport { memoizedFn } from '../query/memoized.ts'\nimport { SubscribableImpl } from '../query/subscribable.ts'\nimport type { Subscribable } from '../query/subscribable.ts'\nimport { isInitEvent, Thread, ThreadEvent } from './basic.ts'\nimport { ApplogEventMapper, MappedThread } from './mapped.ts'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO) // eslint-disable-line no-unused-vars\n\nexport const rollingFilter = memoizedFn('rollingFilter', function rollingFilter(\n\tthread: Thread,\n\tpattern: DatalogQueryPattern,\n\topts: { name?: string; extraFilterName?: string } = {},\n) {\n\tconst filter = makeFilter(pattern)\n\n\tconst initialLogs = filter(thread.applogs)\n\n\tconst handleUpdateEvent: ApplogEventMapper = (event) => {\n\t\tlet mappedEvent: ThreadEvent\n\t\tif (isInitEvent(event)) {\n\t\t\tmappedEvent = { init: filter(event.init) }\n\t\t} else {\n\t\t\tmappedEvent = {\n\t\t\t\tadded: filter(event.added),\n\t\t\t\tremoved: event.removed, // whatever's removed shall be removed\n\t\t\t}\n\t\t}\n\t\tVERBOSE(\n\t\t\t`rollingFilter{${thread.nameAndSizeUntracked} | ${opts.name ? ` '${opts.name}'}` : ''} parentUpdate`,\n\t\t\tpattern,\n\t\t\tevent,\n\t\t\t'=>',\n\t\t\tmappedEvent,\n\t\t)\n\t\treturn mappedEvent\n\t}\n\tconst mappedThread = new MappedThread(\n\t\t`${thread.name} | ${opts.name || `rollingFilter{${stringify(pattern)}}`}`,\n\t\tthread,\n\t\t[...thread.filters, ...(opts.extraFilterName ? [opts.extraFilterName] : [])],\n\t\tinitialLogs,\n\t\thandleUpdateEvent,\n\t)\n\n\treturn mappedThread\n}, {\n\targsDebugName: (thread, pattern, opts) => createDebugName({ caller: 'rollingFilter', thread, pattern, args: opts }),\n})\n\nexport const rollingMapper = memoizedFn('rollingMapper', function rollingMapper(\n\tthread: Thread,\n\teventMapper: ApplogEventMapper,\n\topts: { name?: string; extraFilterName?: string } = {},\n) {\n\tconst initialMapResult = eventMapper.call(null, { init: thread.applogs }, thread)\n\tif (!isInitEvent(initialMapResult)) {\n\t\tthrow ERROR('Initial run must return init event')\n\t}\n\tconst initialLogs = initialMapResult.init\n\n\treturn new MappedThread(\n\t\t`${thread.name} | ${opts.name || `rollingMapper`}`,\n\t\tthread,\n\t\t[...thread.filters, ...(opts.extraFilterName ? [opts.extraFilterName] as const : [] as const)],\n\t\t// @ts-expect-error readonly.... FIXME\n\t\tinitialLogs,\n\t\teventMapper,\n\t)\n}, {\n\targsDebugName: (thread, _mapper, opts) => createDebugName({ caller: 'rollingMapper', thread, args: opts }),\n})\n\nexport const rollingAcc = memoizedFn(\n\t'rollingAcc',\n\tfunction rollingAcc<ACC>(\n\t\tthread: Thread,\n\t\tacc: ACC,\n\t\teventMapper: (event: ThreadEvent, acc: ACC) => void,\n\t\topts: { name?: string } = {},\n\t): Subscribable<ACC> {\n\t\teventMapper({ init: thread.applogs }, acc) // Do initial mapping\n\n\t\tconst result = new SubscribableImpl<ACC>(acc, () =>\n\t\t\tthread.subscribe(event => {\n\t\t\t\teventMapper(event, acc)\n\t\t\t\tresult._set(acc) // notify — same reference but contents mutated\n\t\t\t}, 'derived'),\n\t\t\t{ equals: false }, // accumulator is mutated in-place\n\t\t)\n\n\t\treturn result\n\t},\n\t{ argsDebugName: (thread, _acc, _mapper, opts) => `rollingAcc{${thread.nameAndSizeUntracked}${opts?.name ? ` | ${opts?.name}` : ''}}` },\n)\n\nexport const getUntrackedPattern = function getUntrackedPattern(\n\tpattern: DatalogQueryPattern,\n) {\n\tif (!Object.entries(pattern).length) {\n\t\tthrow new Error(`Pattern is empty`)\n\t}\n\treturn pattern\n}\nexport function makeFilter(\n\tpattern: DatalogQueryPattern,\n) {\n\treturn function madeFilter(logs: readonly Applog[]) {\n\t\treturn logs.filter(function madeFilterSingleLog(applog) {\n\t\t\tfor (const field of Object.keys(pattern)) {\n\t\t\t\tlet patternValue = pattern[field] // (i) not using .entries bc. https://gists.cwidanage.com/2018/06/how-to-iterate-over-object-entries-in.html\n\t\t\t\tif (patternValue === undefined) continue // undefined in pattern means \"no constraint/query on this field\"\n\t\t\t\tconst applogValue = applog[field.startsWith('!') ? field.slice(1) : field]\n\t\t\t\tconst patternValT: ValueOrMatcher<ApplogValue> = patternValue\n\t\t\t\tif (!matchPartStatic(field as keyof Applog, patternValT, applogValue)) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t}\n}\n\n/**\n * // ! think twice before using\n */\nexport const getUntrackedFilterResults = function getUntrackedFilterResults(\n\tthread: Thread,\n\tpattern: DatalogQueryPattern,\n\topts: { name?: string } = {},\n) {\n\tconst untrackedPattern = getUntrackedPattern(pattern)\n\tconst filter = makeFilter(untrackedPattern)\n\treturn filter(thread.applogs)\n}\n\n///////////////////////////\n// FILTERED THREAD TYPES //\n///////////////////////////\nexport type ThreadWithFilter<T extends string> = Thread & {\n\tfilters: readonly T[]\n}\nexport function hasFilter<T extends string>(thread: Thread, filter: T): thread is ThreadWithFilter<T> {\n\treturn thread.filters.includes(filter)\n}\nexport function assertRaw(thread: Thread) /* : thread is ThreadWithoutFilters */ {\n\tif (thread.filters.length) {\n\t\tWARN(`[assertRaw] but '${thread.nameAndSizeUntracked}' has filters:`, thread.filters)\n\t}\n\treturn thread as ThreadWithoutFilters\n}\nexport function assertOnlyCurrent(thread: Thread) /* : thread is ThreadOnlyCurrent */ {\n\tif (\n\t\t!hasFilter(thread, 'lastWriteWins') ||\n\t\t!hasFilter(thread, 'withoutDeleted')\n\t) throw ERROR(`should be filtered thread, but is:`, thread.filters)\n\treturn thread\n}\nexport type ThreadOnlyCurrent = ThreadWithFilter<'lastWriteWins'>\nexport type ThreadNoDeleted = ThreadWithFilter<'withoutDeleted'>\nexport type ThreadOnlyCurrentNoDeleted = ThreadWithFilter<'lastWriteWins' | 'withoutDeleted'>\nexport type ThreadWithoutFilters = Thread & { filters: [] }\n\n/** Re-export for convenience */\nexport const asReadOnly = MappedThread.asReadOnly\n\n//////////////////\n// MISC HELPERS //\n//////////////////\n\nexport type ApplogMapper = (log: Applog, sourceThread: Thread) => ApplogForInsert\nexport const simpleApplogMapper = function simpleApplogMapper(\n\tthread: Thread,\n\tlogMapper: ApplogMapper,\n\topts: { name?: string; extraFilterName?: string } = {},\n) {\n\tconst mappedTo = new Map<CidString, Applog>() // source log CID to result log\n\tconst mapLogs = (applogs: readonly Applog[], thread: Thread) => {\n\t\tconst ts = dateNowIso()\n\t\treturn applogs.map(log => {\n\t\t\tconst mapped = logMapper(log, thread)\n\t\t\tlet mapTo: Applog\n\t\t\tif (mapped === log) {\n\t\t\t\tmapTo = log\n\t\t\t} else {\n\t\t\t\tif ((mapped as Applog).cid === log.cid) {\n\t\t\t\t\tdelete (mapped as Applog).cid // for convenience of not needing to remove it in the mapper\n\t\t\t\t}\n\t\t\t\tmapTo = finalizeApplogForInsert(mapped, {\n\t\t\t\t\tts,\n\t\t\t\t\tthreadForPv: null, // ? should not be inferred, right?\n\t\t\t\t})\n\t\t\t}\n\t\t\tmappedTo.set(log.cid, mapTo)\n\t\t\treturn mapTo\n\t\t})\n\t}\n\n\tconst handleUpdateEvent: ApplogEventMapper = (event) => {\n\t\tlet mappedEvent: ThreadEvent\n\t\tif (isInitEvent(event)) {\n\t\t\tmappedEvent = { init: mapLogs(event.init, thread) }\n\t\t} else {\n\t\t\tmappedEvent = {\n\t\t\t\tadded: mapLogs(event.added, thread),\n\t\t\t\tremoved: event.removed.map(removedSourceLog => {\n\t\t\t\t\tconst mappedLog = mappedTo.get(removedSourceLog.cid)\n\t\t\t\t\tif (!mappedLog) {\n\t\t\t\t\t\tthrow ERROR(`[simpleApplogMapper] Parent remove event for Applog that we don't know about`, { removedSourceLog })\n\t\t\t\t\t}\n\t\t\t\t\tmappedTo.delete(removedSourceLog.cid)\n\t\t\t\t\treturn mappedLog\n\t\t\t\t}),\n\t\t\t}\n\t\t}\n\t\tVERBOSE(\n\t\t\t`simpleApplogMapper{${thread.nameAndSizeUntracked} | ${opts?.name ? ` '${opts?.name}'}` : ''} parentUpdate`,\n\t\t\tevent,\n\t\t\t'=>',\n\t\t\tmappedEvent,\n\t\t)\n\t\t// console.trace('rollingFilter.addFiltered', getObserverTree(observableArr))\n\t\t// trace()\n\t\treturn mappedEvent\n\t}\n\tconst mappedThread = rollingMapper(thread, handleUpdateEvent, opts)\n\tVERBOSE.isDisabled || VERBOSE(`simpleApplogMapper<${thread.nameAndSizeUntracked}> initial mapped to`, mappedThread.applogs)\n\treturn mappedThread\n}\n","import { Logger } from 'besonders-logger'\nimport { encodeApplogAndGetCid } from '../ipfs/ipfs-utils.ts'\nimport { lastWriteWins } from '../query/basic.ts'\nimport { ApplogEventMapper, isInitEvent, MappedThread, rollingFilter, Thread, ThreadOnlyCurrent } from '../thread.ts'\nimport { PartialBy } from '../types/typescript-utils.ts'\nimport { dateNowIso, objEqualByKeys, removeDuplicateAppLogs, sortApplogsByTs } from './applog-utils.ts'\nimport {\n\tApplog,\n\tApplogForInsert,\n\tApplogForInsertOptionalAgent,\n\tApplogNoCid,\n\tAgentHash,\n\tCidString,\n\tgetApplogTypeErrors,\n\tisValidApplog,\n\tTimestamp,\n} from './datom-types.ts'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO) // eslint-disable-line no-unused-vars\n\nexport function ensureTsPvAndFinalizeApplogs(appLogsToInsert: ApplogForInsert[], threadForPv: Thread) {\n\tDEBUG(`[ensureTsPvAndFinalizeApplogs] ENTER - ${appLogsToInsert.length} applogs, thread size=${threadForPv.size}`)\n\tconst ts = dateNowIso()\n\t// const currentThread = lastWriteWins(threadForPv, { tolerateAlreadyFiltered: true }) // HACK to get `pv` from last write\n\tconst currentThread = threadForPv // HACK to not do un-cached lastWriteWins\n\n\tDEBUG(`[ensureTsPvAndFinalizeApplogs] About to map over applogs`)\n\tconst mapped = appLogsToInsert.map((log, idx) => {\n\t\tDEBUG(`[ensureTsPvAndFinalizeApplogs] Processing applog ${idx + 1}/${appLogsToInsert.length}`)\n\t\tconst result = finalizeApplogForInsert(log, { ts, threadForPv: currentThread })\n\t\tDEBUG(`[ensureTsPvAndFinalizeApplogs] Finalized applog ${idx + 1}/${appLogsToInsert.length}`)\n\t\treturn result\n\t})\n\tDEBUG(`[ensureTsPvAndFinalizeApplogs] EXIT - mapped ${mapped.length} applogs`)\n\treturn mapped\n}\nexport function ensureTsPvAndFinalizeApplog(applogToInsert: ApplogForInsert, threadForPv: Thread) {\n\treturn ensureTsPvAndFinalizeApplogs([applogToInsert], threadForPv)[0]\n}\n\nexport function finalizeApplogForInsert(\n\tlog: ApplogForInsert,\n\t{ ts, threadForPv }: { ts?: string; threadForPv?: Thread /*OnlyCurrent*/ } = {},\n) {\n\tDEBUG(`[finalizeApplogForInsert] ENTER - en=${log.en}, at=${log.at}`)\n\tDEBUG(`[finalizeApplogForInsert] About to call withTs`)\n\tconst logWithTs = withTs(log, ts ?? dateNowIso())\n\tDEBUG(`[finalizeApplogForInsert] About to call withPvFrom (thread size=${threadForPv?.size ?? 'null'})`)\n\tconst logWithPv = withPvFrom(logWithTs, threadForPv)\n\tDEBUG(`[finalizeApplogForInsert] About to call encodeApplogAndGetCid`)\n\tconst cid = encodeApplogAndGetCid(logWithPv).toString() as CidString\n\tDEBUG(`[finalizeApplogForInsert] CID created: ${cid}`)\n\tif ((log as Applog).cid && (log as Applog).cid !== cid) WARN(`[finalizeApplogForInsert] overwriting wrong CID`, { log, cid, logWithPv })\n\tconst logWithCid = { ...logWithPv, cid } satisfies Applog\n\tDEBUG(`[finalizeApplogForInsert] About to validate applog`)\n\tif (!isValidApplog(logWithCid)) {\n\t\tthrow ERROR(`Bogus Applog ${JSON.stringify(logWithCid)}`, getApplogTypeErrors(logWithCid))\n\t}\n\tDEBUG(`[finalizeApplogForInsert] EXIT - CID=${cid}`)\n\treturn Object.freeze(logWithCid)\n}\n\nexport function hasAg(log: ApplogForInsertOptionalAgent): log is ApplogForInsert {\n\treturn !!log.ag\n}\nexport function hasTs(log: ApplogForInsert): log is Omit<ApplogForInsert, 'ts'> & { ts: Timestamp } {\n\treturn !!log.ts\n}\nexport function hasPv(log: ApplogForInsert): log is ApplogForInsert & { pv: string } {\n\treturn !!log.pv\n}\n\nexport function withTs(log: ApplogForInsert, ts: Timestamp) {\n\treturn hasTs(log) ? log : { ...log, ts }\n}\nexport function withAg(log: ApplogForInsertOptionalAgent, ag: AgentHash) {\n\treturn hasAg(log) ? log : { ...log, ag }\n}\nexport function withPvFrom(log: PartialBy<ApplogNoCid, 'pv'>, thread: Thread /*OnlyCurrent*/ | null) {\n\tDEBUG(`[withPvFrom] ENTER - en=${log.en}, at=${log.at}, hasPv=${log.pv !== undefined}`)\n\tif (log.pv !== undefined) {\n\t\tDEBUG(`[withPvFrom] EXIT early - pv already set`)\n\t\treturn log as ApplogNoCid // TODO: ? devMode WARN if it's different for catching bugs)\n\t}\n\tif (!thread) {\n\t\tif (!hasPv(log)) throw ERROR(`[withPvFrom] no thread and no pv:`, log)\n\t\tDEBUG(`[withPvFrom] EXIT - no thread, returning log with existing pv`)\n\t\treturn log // satisfies Pick<Applog, 'pv'>\n\t} else {\n\t\tconst { en, at } = log\n\t\tDEBUG(`[withPvFrom] About to call thread.findLast for en=${en}, at=${at}, thread.size=${thread.size}`)\n\t\tconst prevLog = thread.findLast(l => l.en == en && l.at == at) // HACK to not do lastWriteWins calc\n\t\tDEBUG(`[withPvFrom] findLast completed, found=${!!prevLog}`)\n\t\t// const prevLogs = rollingFilter(thread, { en, at }) // ? use some non-reactive filter here?\n\t\t// if (prevLogs.size > 1) throw ERROR(`[withPvFrom] unexpected previous count:`, prevLogs.size, { log, prevLogs, thread }) // `thread` arg must be only current\n\t\t// let prevLog = prevLogs.isEmpty ? null : prevLogs.applogs[0]\n\t\t// const isMatchingPv = prevLog?.cid === log.pv\n\t\tDEBUG(`[withPvFrom] About to check equality`)\n\t\tif (objEqualByKeys(['en', 'at', 'vl', 'ts', 'ag'], log, prevLog)) {\n\t\t\tthrow ERROR(`[withPvFrom] Same as previous:`, { log, pv: prevLog, thread }) // bug catcher\n\t\t}\n\t\t// if (log.pv && !isMatchingPv) { // ineffective bc. shortcut in the beginning of this func\n\t\t// \tWARN(`[withPvFrom] different than pre-set pv:`, { queriedPv: prevLog, logPv: log.pv })\n\t\t// }\n\t\tconst prevLogCid = (log.pv !== undefined ? log.pv : prevLog?.cid) ?? null\n\t\tDEBUG(`[withPvFrom] EXIT - prevLogCid=${prevLogCid}`)\n\t\treturn { ...log, pv: prevLogCid }\n\t}\n}\nexport function joinThreads(threads: ReadonlyArray<Thread>) {\n\tconst fullJoin = () => {\n\t\tif (threads.length < 2) DEBUG(`joinThreads with count=${threads.length}`) // ? EmptyThread\n\t\treturn sortApplogsByTs(\n\t\t\tremoveDuplicateAppLogs(threads.flatMap(s => {\n\t\t\t\tconst logs = s.applogs\n\t\t\t\tif (!logs) {\n\t\t\t\t\tERROR(`falsy applogs of thread`, s)\n\t\t\t\t\tthrow new Error(`falsy applogs of thread`)\n\t\t\t\t}\n\t\t\t\treturn logs\n\t\t\t}), 'cleanup'),\n\t\t)\n\t}\n\tlet initialMergeResult = fullJoin()\n\tconst eventMapper: ApplogEventMapper = function(event, sourceThread) {\n\t\tif (isInitEvent(event)) {\n\t\t\treturn { init: fullJoin() }\n\t\t} else {\n\t\t\t// if (event.removed) WARN(`JoinThreads with parents removing stuff - NOT IMPLEMENTED CORRECTLY`, { event, joined: this, sourceThread }) // TODO: joinTHreads & removed?\n\t\t\treturn {\n\t\t\t\t// TODO: test this stuff\n\t\t\t\tadded: event.added.filter(addedLog => !this.hasApplog(addedLog, true)),\n\t\t\t\tremoved: event.removed?.filter(removedLog => {\n\t\t\t\t\tconst otherParentHasLog = !this.parents.some(parent => {\n\t\t\t\t\t\tif (parent === sourceThread) return false\n\t\t\t\t\t\treturn parent.hasApplog(removedLog, true)\n\t\t\t\t\t})\n\t\t\t\t\treturn !otherParentHasLog\n\t\t\t\t}),\n\t\t\t}\n\t\t}\n\t}\n\treturn new MappedThread(\n\t\t`join(~ ${threads.map(s => s.name).join(', ')})`,\n\t\tthreads,\n\t\t['?'], // HACK this basically says \"we're not sure what filters are applied\"\n\t\tinitialMergeResult,\n\t\teventMapper,\n\t)\n}\n","import * as dagJson from '@ipld/dag-json'\nimport { sha256 } from '@noble/hashes/sha2.js'\nimport { Logger } from 'besonders-logger'\nimport { CID, digest as Digest } from 'multiformats'\nimport { encode as multiformatsEncode } from 'multiformats/block'\n// import { encode } from 'multiformats/block';\nimport { Applog, ApplogEncNoCid, ApplogNoCid, ApplogOfSomeSort, CidString, IpnsString, isEncryptedApplog } from '../applog/datom-types.ts'\n\nimport { base36 } from 'multiformats/bases/base36'\nimport { sha256 as sha265Hasher } from 'multiformats/hashes/sha2'\n\n/* THIS FILE SHOULD NOT DEPEND ON UI STUFF, SO THAT TESTS CAN RUN WITH MINIMAL DEPENDENCIES */\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO) // eslint-disable-line no-unused-vars\n\nexport const MULTICODEC_IPNS_KEY = 0x72\n\nexport function prepareForPub(log: ApplogOfSomeSort, without: string[] = ['cid']) {\n\tif (!log) throw ERROR('falsy log', log)\n\tlet cid = (log as Applog).cid\n\tif (isEncryptedApplog(log)) {\n\t\tif (!cid) cid = getCidSync(encodeBlock(log as ApplogEncNoCid).bytes).toString()\n\t\tWARN('preparing an encrypted applog - really?')\n\t\treturn { log, cid }\n\t}\n\tconst logWithout = {}\n\tfor (let [key, val] of Object.entries(log)) {\n\t\tif (val === undefined) {\n\t\t\tWARN(`log.${key} is undefined, which is not allowed - encoding as null`, log)\n\t\t\tval = null\n\t\t}\n\t\tif (!without.includes(key)) {\n\t\t\tlogWithout[key] = val // && key === 'pv' ? CID.parse(val) : val //HACK: disabled until clarified: https://discuss.ipfs.tech/t/pin-dag-with-open-ends/17612\n\t\t} else {\n\t\t\tVERBOSE('excluding app log', { key, val })\n\t\t}\n\t}\n\treturn { log: logWithout as Applog, cid }\n}\n\nexport function encodeApplogAndGetCid(log: ApplogNoCid) {\n\treturn getCidSync(encodeApplog(log).bytes)\n}\nexport function encodeApplog(log: ApplogNoCid | ApplogEncNoCid): { bytes: dagJson.ByteView<any>; cid: CID } {\n\treturn encodeBlock(prepareForPub(log)?.log)\n}\n\nexport function getCidSync(bytes: dagJson.ByteView<any>) {\n\t// Hacky way to use a sync sha265 lib to create a CID - code inspired by https://github.com/multiformats/js-multiformats#multihash-hashers\n\tconst hash = sha256(bytes)\n\tconst digest = Digest.create(sha265Hasher.code, hash)\n\tconst cid = CID.create(1, dagJson.code, digest)\n\tVERBOSE(`[getCidSync]`, { bytes, hash, digest, cid })\n\treturn cid\n}\n/** encode the json object into an IPLD block */\nexport function encodeBlock(jsonObject: any): { bytes: dagJson.ByteView<any>; cid: CID } {\n\tDEBUG('[encodeBlock]', jsonObject)\n\ttry {\n\t\tconst byteView = dagJson.encode(jsonObject)\n\t\treturn { bytes: byteView, cid: getCidSync(byteView) }\n\t} catch (err) {\n\t\tthrow ERROR('[encodeBlock] failed to encode:', jsonObject, err)\n\t}\n}\n\nexport async function encodeBlockOriginal(jsonObject: any) {\n\t// HACK re-added this to verify the sync variant is sane\n\tconst encoded = await multiformatsEncode({ value: jsonObject, codec: dagJson, hasher: sha265Hasher })\n\tconst syncVariant = encodeBlock(jsonObject)\n\tif (syncVariant.cid.toString() !== encoded.cid.toString()) {\n\t\tERROR(`[encodeBlockOriginal] sync cid mismatch`, { jsonObject, encoded, syncVariant })\n\t}\n\treturn encoded\n}\n\nexport function tryParseCID(cidString: CidString) {\n\tlet cid: CID | null = null\n\tlet errors = []\n\ttry {\n\t\tcid = CID.parse(cidString)\n\t} catch (err) {\n\t\tVERBOSE(`[retrieveThread] couldn't parse pubID with default base`)\n\t\terrors.push(err)\n\t}\n\tif (!cid) {\n\t\ttry {\n\t\t\tcid = CID.parse(cidString, base36) // e.g. for IPNS\n\t\t} catch (err) {\n\t\t\tVERBOSE(`[retrieveThread] couldn't parse pubID with base36`)\n\t\t\terrors.push(err)\n\t\t}\n\t}\n\treturn {\n\t\tcid,\n\t\terrors: cid ? null : errors, // we only care about errors if we failed to parse\n\t\tisIpns: cid && isIpnsKeyCid(cid),\n\t}\n}\nexport function isIpnsKeyCid(cid: CID) {\n\treturn cid.code === MULTICODEC_IPNS_KEY\n}\n\nexport function cidToString(cid: CID) {\n\tif (cid.code == MULTICODEC_IPNS_KEY) {\n\t\treturn toIpnsString(cid)\n\t} else {\n\t\treturn cid.toString()\n\t}\n}\nexport function toIpnsString(cid: CID) {\n\tif (cid.code !== MULTICODEC_IPNS_KEY) throw ERROR(`Not an IPNS cid (${cid.code}):`, cid.toString())\n\treturn cid.toString(base36) as IpnsString\n}\nexport function ensureValidCIDinstance(cidOrStringA: CID | CidString) {\n\treturn typeof cidOrStringA === 'string'\n\t\t? CID.parse(cidOrStringA)\n\t\t: typeof cidOrStringA.toV1 != 'function'\n\t\t? CID.decode(cidOrStringA.bytes)\n\t\t: cidOrStringA\n}\nexport function areCidsEqual(cidOrStringA: CID | CidString, cidOrStringB: CID | CidString) {\n\tif (!cidOrStringA || !cidOrStringB) throw new Error(`[areCidsEqual] invalid params: ${cidOrStringA}, ${cidOrStringB}`)\n\tif (cidOrStringA === cidOrStringB) return true // shortcut if both are strings\n\tconst cidA = ensureValidCIDinstance(cidOrStringA)\n\tconst cidB = ensureValidCIDinstance(cidOrStringB)\n\treturn cidA.toV1().toString() === cidB.toV1().toString()\n}\nexport function containsCid(list: (CID | CidString)[] | Set<CidString>, needle: CID | CidString) {\n\tif (list instanceof Set) return list.has(typeof needle === 'string' ? needle : needle.toV1().toString()) // ? what if the CidString is a different form? (parse and format would cost performance)\n\treturn list.some(cidOrString => areCidsEqual(cidOrString, needle))\n}\n","// import type { AgentHash } from '../pubsub/pubsub-types.ts'\n// import type { CID } from '@oddjs/odd'\nimport { FormatRegistry, Static, TSchema, Type } from '@sinclair/typebox'\nimport { TypeCompiler } from '@sinclair/typebox/compiler'\nimport { CID } from 'multiformats/cid'\nimport type { PartialBy, Tagged } from '../types/typescript-utils.ts'\n\nexport const Nullable = <T extends TSchema>(schema: T) => Type.Union([schema, Type.Null()])\nexport const EntityID_LENGTH = 7\n// const bagu = 'baguqeerav3h4b46j2pyxikqhtm5si5vhzsyrba2duhrtltfutrlmj42anmvq'\n// const k51q = 'k51qzi5uqu5dhe1bxxjxj144bj2a225o1681yobevns26xlxtsfidjgnpwknfd'\nconst isCID = /^(k51qz|baguq)[0-9a-z]{56,57}$/ // FIXME: k51 is not really a CID, is it?\nconst isShortHash = /^[0-9A-Fa-f]{7,8}$/g // TODO awkward why are some 7 and some 8 long\n// engine level: min 6 (lenient within reason)\n// note3 TBD... either fixed for all entity types VS 7 for pub/sub, 8 for tags, 9 for blocks, 10 for relations etc...\n\nFormatRegistry.Set('EntityID', (value) => !!value.match(isShortHash) || !!value.match(isCID))\nexport const EntityID = Type.String() // HACK how to configure ID format?\n/*{ format: 'EntityID' }*/\nexport type EntityID = Static<typeof EntityID>\n\nexport type AgentHash = Tagged<string, 'AgentHash'>\nexport type DatomPart = string // TODO refactor\nexport type CidString = Tagged<string, CID>\nexport type IpnsString = Tagged<CidString, 'IPNS'>\nexport type AgentID = EntityID\nexport type Attribute = string\nexport type ApplogValue = string | boolean | number | null // TODO: use Tagged types\n// ? allow objects? or just as serialized strings? Or serialize everything anyways?\n\nexport interface Atom {\n\ten: EntityID\n\tat: Attribute\n\tvl: ApplogValue\n}\n\nexport type Timestamp = string\nexport interface Applog extends Atom {\n\tcid: CidString\n\tpv: CidString | null // ? | CID\n\tts: Timestamp\n\tag: AgentHash\n}\nexport type ApplogNoCid = Omit<Applog, 'cid'>\nexport type ApplogOptionalCid = PartialBy<Applog, 'cid'>\nexport type ApplogForInsert = PartialBy<ApplogNoCid, 'ts' | 'pv'>\nexport type ApplogForInsertOptionalAgent = PartialBy<ApplogForInsert, 'ag'>\n\nexport interface ApplogEnc {\n\tcid: CidString\n\tenc: Uint8Array\n\tiv?: Uint8Array // iv may be needed if we prefer a different strategy for transmitting iv (odd appends a random iv to the payload via keystoreAES.(en|de)cryptBytes)\n}\nexport type ApplogEncNoCid = Omit<ApplogEnc, 'cid'>\n\nexport type ApplogArrayMaybeEncrypted = (Applog | ApplogEnc)[]\nexport type ApplogArrayMaybeEncryptedRO = readonly (Applog | ApplogEnc)[]\nexport type ApplogArrayNoCIDMaybeEncryptedRO = readonly (ApplogNoCid | ApplogEncNoCid)[]\n\nexport type ApplogOfSomeSort = Applog | ApplogEnc | ApplogNoCid | ApplogEncNoCid | ApplogForInsert\n\nexport const isEncryptedApplog = (l: ApplogOfSomeSort): l is ApplogEnc => (l as ApplogEnc)?.enc instanceof Uint8Array\n\nexport type AtomPattern = Atom | Applog\n\nexport interface DatalogStateIdentifier {\n\tlastTS: Timestamp\n}\n\n// New generic type for fields that can be a value, an array of that, or a function\nexport type ValueOrMatcher<T> = T | readonly T[] | ReadonlySet<T> | ((value: T) => boolean)\n// Generic type that applies ValueOrMatcher to each field of T\nexport type WithMatchers<T extends Record<string, any>> = {\n\t[K in keyof T & string as `${K}` | `!${K}`]?: ValueOrMatcher<T[K]>\n}\n\nexport type DatalogQueryPattern = Partial<WithMatchers<Applog>>\nexport type DatalogQueryPatternArray = DatalogQueryPattern[]\nexport interface DatalogQuery<SELECT extends string> {\n\tfind: readonly SELECT[] // see: https://github.com/microsoft/TypeScript/issues/20965#issuecomment-868981458\n\twhere: DatalogQueryPatternArray\n\tonlyLatest?: boolean\n}\nexport type DatalogQueryResultEntry<SELECT extends string> = Record<\n\t// SELECT,\n\tStripPrefix<'?', SELECT>,\n\tDatomPart\n>\nexport type DatalogQueryResultRows<SELECT extends string> = DatalogQueryResultEntry<SELECT>[]\n// export type StripTest = StripPrefix<'?', '?A' | '?B'>\n// export type DatalogQueryResultEntryTEST = DatalogQueryResultEntry<'?A' | '?B'>\n// export type DatalogQueryResultEntryTESTX = MapKeysStripPrefix<'?A' | '?B', '?'>\n\nexport interface SearchContext {\n\t[key: string]: ApplogValue\n}\nexport interface SearchContextWithLog {\n\tcontext: SearchContext\n\tapplog?: Applog\n}\n\nexport type ResultContext = SearchContext | null\n\n/* https://stackoverflow.com/a/72497461 */\ntype StripPrefix<\n\tTPrefix extends string,\n\tT extends string,\n> = T extends `${TPrefix}${infer R}` ? R : never\n\ntype MapKeysStripPrefix<SELECT extends string, TPrefix extends string> = {\n\t[K in SELECT as StripPrefix<TPrefix, K>]: DatomPart\n}\n\nFormatRegistry.Set('CID', (value) => !!value.match(isCID))\nexport const CIDTB = Type.String({ format: 'CID' })\nexport type CIDTB = Static<typeof EntityID>\n\nconst isURL = /^http([s]?):\\/\\/.*\\..*/\nFormatRegistry.Set('URL', (value) => !!value.match(isURL))\nexport const URL = Type.String({ format: 'URL' })\nexport type URL = Static<typeof URL>\n\nexport const AppLogNoCidTB = Type.Object({\n\ten: EntityID, // EntityID\n\tat: Type.String(), // Attribute\n\tvl: Nullable(Type.Union([Type.String(), Type.Boolean(), Type.Number()])), // TODO refactor to semantic typesafe ApplogValue\n\tts: Type.String(), // Timestamp\n\tag: Type.String(), // AgentHash\n\tpv: Nullable(CIDTB), // CidString\n})\nexport type AppLogNoCidTB = Static<typeof AppLogNoCidTB> // type T = {\n\nexport const AppLogNoCidTBC = TypeCompiler.Compile(AppLogNoCidTB)\nexport const getApplogNoCidTypeErrors = (obj: any) => Array.from(AppLogNoCidTBC.Errors(obj))\nexport const isValidApplogNoCid = AppLogNoCidTBC.Check.bind(AppLogNoCidTBC) // ? Include CID\n\nexport const AppLogTB = Type.Composite([\n\tType.Object({\n\t\tcid: CIDTB,\n\t}),\n\tAppLogNoCidTB,\n])\nexport type AppLogTB = Static<typeof AppLogTB> // type T = {\n\nexport const AppLogTBC = TypeCompiler.Compile(AppLogTB)\nexport const getApplogTypeErrors = (obj: any) => Array.from(AppLogTBC.Errors(obj))\nexport const isValidApplog = AppLogTBC.Check.bind(AppLogTBC) // ? Include CID\n// maybe useful for defaulting https://github.com/sinclairzx81/typebox#cast\n","import { Logger } from 'besonders-logger'\nimport { isBefore } from 'date-fns'\nimport { partial, pick } from 'lodash-es'\nimport { isEqual } from 'lodash-es'\nimport stringify from 'safe-stable-stringify'\nimport type {\n\tApplog,\n\tApplogForInsert,\n\tApplogValue,\n\tDatalogQueryPattern,\n\tDatalogQueryResultEntry,\n\tResultContext,\n\tSearchContext,\n\tValueOrMatcher,\n} from './datom-types.ts'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO) // eslint-disable-line no-unused-vars\n\nexport const isoDateStrCompare = (strA: string, strB: string, dir: 'asc' | 'desc' = 'asc') =>\n\tdir === 'asc'\n\t\t? strA.localeCompare(strB, 'en-US')\n\t\t: strB.localeCompare(strA, 'en-US')\nexport const objEqualByKeys = (keys: string[], objA: object, objB: object) => {\n\treturn isEqual(pick(objA, keys), pick(objB, keys))\n}\n\nexport const compareApplogsByTs = (logA: Applog, logB: Applog, dir: 'asc' | 'desc' = 'asc') => isoDateStrCompare(logA.ts, logB.ts, dir)\nexport const compareApplogsByEnAt = partial(objEqualByKeys, ['en', 'at'])\n\n/** Sort by TS (modifies the array, but also returns for ease of use) */\nexport function sortApplogsByTs(appLogArray: Applog[], dir: 'asc' | 'desc' = 'asc') {\n\treturn appLogArray.sort((a, b) => compareApplogsByTs(a, b, dir))\n}\nexport const isTsBefore = (log: Applog, logToCompare: Applog) => isBefore(new Date(log.ts), new Date(logToCompare.ts))\nexport const uniqueEnFromAppLogs = (appLogArray: Applog[]) => [...new Set(appLogArray.map(eachLog => eachLog.en))]\nexport const areApplogsEqual = (logA: Applog, logB: Applog) => isEqual(logA, logB)\n\nexport type RemoveDuplicateAppLogsMode = 'safety' | 'cleanup'\n\nconst warnMissingRemoveDuplicateMode = () => {\n\tWARN(`[removeDuplicateAppLogs] mode not set; pass 'safety' or 'cleanup' for optimal behavior`)\n}\n\nconst removeDuplicateAppLogsCleanup = (appLogArray: Applog[]) => {\n\tconst logMap = new Map<string, Applog>()\n\tconst verboseEnabled = VERBOSE.isEnabled\n\tfor (const eachLog of appLogArray) {\n\t\tif (!eachLog) {\n\t\t\tERROR(`falsy entry in applogs`, appLogArray)\n\t\t\tthrow new Error(`falsy entry in applogs`)\n\t\t}\n\t\tif (!eachLog.cid) {\n\t\t\tERROR(`applog with missing CID`, eachLog)\n\t\t\tthrow new Error(`applog with missing CID`)\n\t\t}\n\t\tconst key = eachLog.cid\n\t\tconst existing = logMap.get(key)\n\t\tif (existing) {\n\t\t\tif (verboseEnabled) VERBOSE(`Skipping duplicate applog:`, [existing, eachLog])\n\t\t} else {\n\t\t\tlogMap.set(key, eachLog)\n\t\t}\n\t}\n\treturn Array.from(logMap.values())\n}\n\nconst removeDuplicateAppLogsSafety = (appLogArray: Applog[]) => {\n\tconst seen = new Set<string>()\n\tconst verboseEnabled = VERBOSE.isEnabled\n\tconst existingByCid = verboseEnabled ? new Map<string, Applog>() : null\n\tlet result: Applog[] | null = null\n\tlet index = 0\n\tfor (const eachLog of appLogArray) {\n\t\tif (!eachLog) {\n\t\t\tERROR(`falsy entry in applogs`, appLogArray)\n\t\t\tthrow new Error(`falsy entry in applogs`)\n\t\t}\n\t\tif (!eachLog.cid) {\n\t\t\tERROR(`applog with missing CID`, eachLog)\n\t\t\tthrow new Error(`applog with missing CID`)\n\t\t}\n\t\tconst key = eachLog.cid\n\t\tif (seen.has(key)) {\n\t\t\tif (!result) {\n\t\t\t\tresult = appLogArray.slice(0, index)\n\t\t\t}\n\t\t\tif (verboseEnabled) VERBOSE(`Skipping duplicate applog:`, [existingByCid?.get(key), eachLog])\n\t\t} else {\n\t\t\tseen.add(key)\n\t\t\tif (existingByCid) existingByCid.set(key, eachLog)\n\t\t\tif (result) result.push(eachLog)\n\t\t}\n\t\tindex++\n\t}\n\treturn result ?? appLogArray\n}\n\n/**\n * Deduplicate applogs by CID.\n * - safety: fast duplicate check; returns original array if no duplicates found.\n * - cleanup: optimized for merged arrays with likely duplicates.\n */\nexport const removeDuplicateAppLogs = (appLogArray: Applog[], mode?: RemoveDuplicateAppLogsMode) => {\n\tif (!mode) {\n\t\twarnMissingRemoveDuplicateMode()\n\t\treturn removeDuplicateAppLogsCleanup(appLogArray)\n\t}\n\treturn mode === 'safety'\n\t\t? removeDuplicateAppLogsSafety(appLogArray)\n\t\t: removeDuplicateAppLogsCleanup(appLogArray)\n}\n\n// export const removeDuplicateAndMaybeDeletedAppLogs = (ds: Thread, appLogArray: Applog[], removeDeletedEntities = true) => {\n// \tconst logMap = new Map()\n// \tfor (const eachLog of appLogArray) {\n// \t\tif (!removeDeletedEntities || ds.entityIsDeleted(eachLog.en))\n// \t\t\tlogMap.set(stringify(eachLog), eachLog)\n// \t}\n// \treturn Array.from(logMap.values())\n// }\n\nexport const getHashID = (stringifiable: any, lngth = 8) => cyrb53hash(stringify(stringifiable), 31, lngth) as string\n\nexport function isVariable(x: any): x is string {\n\treturn typeof x === 'string' && x.startsWith('?')\n}\nexport function variableNameWithoutQuestionmark(str: string) {\n\treturn str.slice(1)\n}\n// export function isMatcher(x: any): x is string {\n// \treturn\n// }\nexport function isStaticPattern(x: any): x is ApplogValue {\n\tif (!['string', 'boolean', 'number', 'function'].includes(typeof x)) WARN(`Unhandled pattern value type:`, typeof x, x)\n\treturn !isVariable(x) && ['string', 'boolean', 'number'].includes(typeof x)\n}\n// export function isIgnorePattern(x: any): boolean {\n// \treturn x === '_'\n// }\n\n/*\n * In a pattern from a Query:\n * - variables that don't have a value in the search context:\n * - remove from pattern\n * - add to variableToFill as: { en: 'movieID' } (useful for mapTo)\n * - variables that have a value set:\n * - replace placeholder with actual value\n */\nexport function resolveOrRemoveVariables(pattern: DatalogQueryPattern, candidate: SearchContext) {\n\tlet variablesToFill = {} as Partial<{ [key in keyof Applog]: string }>\n\tconst newPattern: DatalogQueryPattern = {}\n\tfor (const [patternKey, patternValue] of Object.entries(pattern)) {\n\t\tif (isVariable(patternValue)) {\n\t\t\tconst varName = variableNameWithoutQuestionmark(patternValue)\n\t\t\tconst candidateValue = candidate[varName]\n\t\t\tif (candidateValue) {\n\t\t\t\tnewPattern[patternKey] = candidateValue\n\t\t\t\t// & not adding it to newPattern\n\t\t\t} else {\n\t\t\t\tvariablesToFill[patternKey] = varName\n\t\t\t}\n\t\t} else {\n\t\t\tnewPattern[patternKey] = patternValue // keep static value\n\t\t}\n\t}\n\n\treturn [newPattern, variablesToFill] as const\n}\n\nfunction matchVariable(variable: string, triplePart: ApplogValue, context: SearchContext): SearchContext {\n\tif (context.hasOwnProperty(variable)) {\n\t\t// TODO: fix lint error with: if (Object.hasOwnProperty.call(context, variable)) {\n\t\tconst bound = context[variable]\n\t\tconst match = matchPart(bound, triplePart, context)\n\t\t// if (VERBOSE.isEnabled) VERBOSE('[matchVariable] match?', variable, bound, match)\n\t\treturn match\n\t}\n\t// if (VERBOSE.isEnabled) VERBOSE('[matchVariable] initializing variable', variable, 'to', triplePart)\n\treturn { ...context, [variable]: triplePart }\n}\n\nexport function matchPartStatic(field: keyof Applog, patternPart: ValueOrMatcher<ApplogValue>, atomPart: ApplogValue): boolean {\n\t// if (VERBOSE.isEnabled) VERBOSE('[matchPartStatic]', field, patternPart, patternPart === atomPart ? '===' : '!==', atomPart)\n\tlet result\n\tif (patternPart) {\n\t\tconst typ = typeof patternPart\n\t\tif (typ === 'string') {\n\t\t\tresult = patternPart === atomPart // shortcut for most common use-case\n\t\t} else if (typ === 'function') {\n\t\t\tresult = (patternPart as Function)(atomPart)\n\t\t} else if (typeof (patternPart as any).has === 'function') {\n\t\t\tresult = (patternPart as Set<any>).has(atomPart)\n\t\t} else if (Array.isArray(patternPart) && !Array.isArray(atomPart) /* ? how to handle array values */) {\n\t\t\tresult = patternPart.includes(atomPart)\n\t\t} // if (field === 'at' && typ === 'string' && patternPart.endsWith('*')) {\n\t\t// \treturn typeof atomPart === 'string' && atomPart.startsWith(patternPart.slice(0, -1))\n\t\t// }\n\t\telse {\n\t\t\tresult = patternPart === atomPart\n\t\t}\n\t} else {\n\t\tresult = patternPart === atomPart\n\t}\n\n\t// if (VERBOSE.isEnabled) VERBOSE('[matchPartStatic] =>', field.startsWith('!') ? '!' : '', result)\n\tif (field.charAt(0) === '!') {\n\t\treturn !result\n\t} else {\n\t\treturn result\n\t}\n}\nexport function matchPart(patternPart: ValueOrMatcher<ApplogValue>, atomPart: ApplogValue, context: SearchContext): ResultContext {\n\tif (!context) {\n\t\t// if (VERBOSE.isEnabled) VERBOSE('[matchPart] no context')\n\t\treturn null\n\t}\n\tif (typeof patternPart === 'string') {\n\t\tif (isVariable(patternPart)) {\n\t\t\treturn matchVariable(patternPart, atomPart, context)\n\t\t} /* TODO: else if (isIgnorePattern(patternPart)) {\n\t\t\treturn matchVariable(patternPart, atomPart, context)\n\t\t} */\n\t}\n\t// if (VERBOSE.isEnabled) VERBOSE('[matchPart]', patternPart, patternPart === atomPart ? '===' : '!==', atomPart)\n\tif (typeof patternPart === 'function') {\n\t\treturn patternPart(atomPart) ? context : null\n\t}\n\treturn patternPart === atomPart ? context : null\n}\n\n/**\n * Check if pattern matches triple with context substitutions\n */\nexport function matchPattern(pattern: DatalogQueryPattern, applog: Applog, context: SearchContext): ResultContext {\n\treturn Object.entries(pattern).reduce((context, [field, patternValue]) => {\n\t\tconst applogValue = applog[field]\n\t\t// @ts-expect-error wtf no idea //HACK: ts weird\n\t\tconst patternValT: ValueOrMatcher<ApplogValue> = patternValue\n\t\treturn matchPart(patternValT, applogValue, context)\n\t}, context)\n}\n\nexport function actualize<SELECT extends string>(context: ResultContext, find: readonly SELECT[]): DatalogQueryResultEntry<SELECT> {\n\treturn Object.fromEntries(find.map((findField) => {\n\t\tif (context === null) {\n\t\t\tthrow new Error(`actualize context is null ${find}`)\n\t\t}\n\t\treturn [\n\t\t\tisVariable(findField) ? findField.replace(/^\\?/, '') : findField,\n\t\t\tisVariable(findField) ? context[findField] : findField,\n\t\t]\n\t})) as DatalogQueryResultEntry<SELECT>\n}\nconst sum = function sum(array: number[]) {\n\tvar num = 0\n\tfor (var i = 0, l = array.length; i < l; i++) num += array[i]\n\treturn num\n}\nconst mean = function mean(array: number[]) {\n\treturn sum(array) / array.length\n}\nexport const arrStats = {\n\tmax: function(array: number[]) {\n\t\treturn Math.max.apply(null, array)\n\t},\n\n\tmin: function(array: number[]) {\n\t\treturn Math.min.apply(null, array)\n\t},\n\n\trange: function(array: number[]) {\n\t\treturn arrStats.max(array) - arrStats.min(array)\n\t},\n\n\tmidrange: function(array: number[]) {\n\t\treturn arrStats.range(array) / 2\n\t},\n\n\tsum,\n\n\tmean,\n\n\taverage: mean,\n\n\tmedian: function(array: number[]) {\n\t\tarray.sort(function(a, b) {\n\t\t\treturn a - b\n\t\t})\n\t\tvar mid = array.length / 2\n\t\treturn mid % 1 ? array[mid - 0.5] : (array[mid - 1] + array[mid]) / 2\n\t},\n\n\tmodes: function(array: number[]) {\n\t\tif (!array.length) return []\n\t\tvar modeMap = {},\n\t\t\tmaxCount = 0,\n\t\t\tmodes = []\n\n\t\tarray.forEach(function(val) {\n\t\t\tif (!modeMap[val]) modeMap[val] = 1\n\t\t\telse modeMap[val]++\n\n\t\t\tif (modeMap[val] > maxCount) {\n\t\t\t\tmodes = [val]\n\t\t\t\tmaxCount = modeMap[val]\n\t\t\t} else if (modeMap[val] === maxCount) {\n\t\t\t\tmodes.push(val)\n\t\t\t\tmaxCount = modeMap[val]\n\t\t\t}\n\t\t})\n\t\treturn modes\n\t},\n\n\tvariance: function(array: number[]) {\n\t\tvar mean = arrStats.mean(array)\n\t\treturn arrStats.mean(array.map(function(num) {\n\t\t\treturn Math.pow(num - mean, 2)\n\t\t}))\n\t},\n\n\tstandardDeviation: function(array: number[]) {\n\t\treturn Math.sqrt(arrStats.variance(array))\n\t},\n\n\tmeanAbsoluteDeviation: function(array: number[]) {\n\t\tvar mean = arrStats.mean(array)\n\t\treturn arrStats.mean(array.map(function(num) {\n\t\t\treturn Math.abs(num - mean)\n\t\t}))\n\t},\n\n\tzScores: function(array: number[]) {\n\t\tvar mean = arrStats.mean(array)\n\t\tvar standardDeviation = arrStats.standardDeviation(array)\n\t\treturn array.map(function(num) {\n\t\t\treturn (num - mean) / standardDeviation\n\t\t})\n\t},\n}\n\n// Function aliases:\narrStats.average = arrStats.mean\n\nexport const tsNearlySame = (timeA: string, timeB: string) => timeB.startsWith(timeA.slice(0, timeA.length - 4)) // HACK: to quickly check if same second\n\n/*\n\t\t\t\tcyrb53 (c) 2018 bryc (github.com/bryc)\n\t\t\t\tA fast and simple hash function with decent collision resistance.\n\t\t\t\tLargely inspired by MurmurHash2/3, but with a focus on speed/simplicity.\n\t\t\t\tPublic domain. Attribution appreciated.\n\n\tripped from https://github.com/bryc/code/blob/mast`er/jshash/experimental/cyrb53.js\n*/\nexport const cyrb53hash = function(\n\tstr: string,\n\tseed = 13,\n\tstrLength: number, /* = 0 */\n) {\n\tif (!str?.length) {\n\t\tthrow new Error(`Empty string: ${str}`)\n\t}\n\n\tlet h1 = 0xdeadbeef ^ seed\n\tlet h2 = 0x41c6ce57 ^ seed\n\tfor (let i = 0, ch; i < str.length; i++) {\n\t\tch = str.charCodeAt(i)\n\t\th1 = Math.imul(h1 ^ ch, 2654435761)\n\t\th2 = Math.imul(h2 ^ ch, 1597334677)\n\t}\n\th1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909)\n\th2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909)\n\t// if (strLength) {\n\tconst asHex = (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(16)\n\treturn asHex.slice(-strLength).padStart(strLength, '0')\n\t// }\n\t// // if not specified return as 16 digit integer\n\t// return 4294967296 * (2097151 & h2) + (h1 >>> 0)\n}\nexport function arraysContainSameElements(arr1, arr2) {\n\tif (arr1.length !== arr2.length) {\n\t\treturn false\n\t}\n\n\tconst sortedArr1 = [...arr1].sort()\n\tconst sortedArr2 = [...arr2].sort()\n\n\tfor (let i = 0; i < sortedArr1.length; i++) {\n\t\tif (sortedArr1[i] !== sortedArr2[i]) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\nexport function dateNowIso(): string {\n\tconst now = new Date()\n\treturn now.toISOString()\n}\n","/**\n * memoizedFn — Simple argument memoization without MobX.\n *\n * Replaces computedFnDeepCompare for query functions.\n * With lazy subscribe (SubscribableArray), there's no urgency to clean up\n * cached entries — unsubscribed entries are just plain arrays in memory.\n *\n * refCountedMemoizedFn — Ref-counted memoization for reactive results.\n * Returns a wrapper that increments a ref count on each call and decrements\n * on dispose(). When refCount hits 0, the entry is cleaned up (with optional\n * grace period).\n */\n\nimport { isEqual } from 'lodash-es'\nimport { Thread } from '../thread/basic.ts'\n\n/** Deep-compare args, but Thread instances by identity (same as MobX version) */\nfunction compareStructural(argsA: any[], argsB: any[], versionsA?: number[]): boolean {\n\tif (argsA.length !== argsB.length) return false\n\tfor (let i = 0; i < argsA.length; i++) {\n\t\tif (argsA[i] instanceof Thread) {\n\t\t\tif (argsB[i] !== argsA[i]) return false\n\t\t\t// Check if thread was mutated since the cache entry was created\n\t\t\tif (versionsA && versionsA[i] !== undefined && argsB[i]._version !== versionsA[i]) return false\n\t\t} else {\n\t\t\tif (!isEqual(argsA[i], argsB[i])) return false\n\t\t}\n\t}\n\treturn true\n}\n\n/** Snapshot Thread._version for each Thread arg */\nfunction snapshotVersions(args: any[]): number[] {\n\treturn args.map(a => a instanceof Thread ? a._version : undefined)\n}\n\ninterface MemoizedFnOptions {\n\targsEqual?: (a: any[], b: any[]) => boolean\n\targsDebugName?: (...args: any[]) => string\n\t/** Max cache entries. Oldest evicted when exceeded. Default: unlimited. */\n\tmaxSize?: number\n}\n\nexport function memoizedFn<T extends (...args: any[]) => any>(\n\tname: string,\n\tfn: T,\n\topts?: MemoizedFnOptions,\n): T {\n\t// TODO: cache grows unboundedly by default — see todo/2026-04-17_ciao-mobx/memoized-cache-cleanup.md for analysis\n\tconst cache: Array<{ args: any[]; versions: number[]; result: any }> = []\n\tconst argsEqual = opts?.argsEqual ?? compareStructural\n\tconst maxSize = opts?.maxSize ?? Infinity\n\n\treturn function (this: any, ...args: any[]) {\n\t\tconst existing = cache.find(entry => argsEqual(entry.args, args, entry.versions))\n\t\tif (existing) return existing.result\n\n\t\tconst result = fn.apply(this, args)\n\n\t\tif (cache.length >= maxSize) {\n\t\t\tcache.shift() // evict oldest\n\t\t}\n\t\tcache.push({ args, versions: snapshotVersions(args), result })\n\t\treturn result\n\t} as any\n}\n\n// ═══════════════════════════════════════════════════════════════\n// refCountedMemoizedFn — ref-counted cache with disposal\n// ═══════════════════════════════════════════════════════════════\n\n/** A result wrapper returned by refCountedMemoizedFn. Call release() when done. */\nexport interface RefCounted<T> {\n\treadonly value: T\n\t/** Decrement ref count. When it reaches 0, the cache entry is cleaned up. */\n\trelease(): void\n}\n\ninterface RefCountedOptions<T extends (...args: any[]) => any> {\n\targsEqual?: (a: any[], b: any[]) => boolean\n\targsDebugName?: (...args: any[]) => string\n\t/**\n\t * Called when the last reference is released and the entry is evicted.\n\t * Use to tear down subscriptions, dispose SubscribableArrays, etc.\n\t */\n\tonCleanup?: (result: ReturnType<T>, ...args: Parameters<T>) => void\n\t/**\n\t * Grace period in ms before actually cleaning up after refCount hits 0.\n\t * If someone re-acquires within this window, the entry is reused.\n\t * Default: 0 (immediate cleanup).\n\t */\n\tgracePeriodMs?: number\n}\n\ninterface CacheEntry<T> {\n\targs: any[]\n\tresult: T\n\trefCount: number\n\tgraceTimer: ReturnType<typeof setTimeout> | null\n}\n\n/**\n * Creates a memoized function whose results are ref-counted.\n *\n * Currently unused — doesn't fit liveQuery's recursive multi-step structure\n * (API break, cache loss on pattern change without grace period).\n * See todo/2026-04-17_ciao-mobx/memoized-cache-cleanup.md for full analysis.\n *\n * Each call returns `RefCounted<ReturnType<fn>>`. Multiple calls with the same\n * args return the same cached result with an incremented ref count.\n * When all holders call `release()`, the cache entry is cleaned up\n * (subject to optional grace period).\n *\n * Usage:\n * ```\n * const getFiltered = refCountedMemoizedFn('rollingFilter', (thread, pattern) => {\n * // ... expensive setup, returns MappedThread\n * }, { onCleanup: (result) => result.dispose() })\n *\n * const ref = getFiltered(myThread, myPattern)\n * // use ref.value (the MappedThread)\n * ref.release() // decrement; when last holder releases, onCleanup fires\n * ```\n */\nexport function refCountedMemoizedFn<T extends (...args: any[]) => any>(\n\tname: string,\n\tfn: T,\n\topts?: RefCountedOptions<T>,\n): (...args: Parameters<T>) => RefCounted<ReturnType<T>> {\n\tconst cache: CacheEntry<ReturnType<T>>[] = []\n\tconst argsEqual = opts?.argsEqual ?? compareStructural\n\tconst gracePeriodMs = opts?.gracePeriodMs ?? 0\n\n\tfunction evict(entry: CacheEntry<ReturnType<T>>, args: any[]) {\n\t\tconst idx = cache.indexOf(entry)\n\t\tif (idx >= 0) cache.splice(idx, 1)\n\t\topts?.onCleanup?.(entry.result, ...args as any)\n\t}\n\n\treturn function (this: any, ...args: Parameters<T>): RefCounted<ReturnType<T>> {\n\t\tlet entry = cache.find(e => argsEqual(e.args, args))\n\n\t\tif (entry) {\n\t\t\t// Cancel pending grace-period cleanup\n\t\t\tif (entry.graceTimer !== null) {\n\t\t\t\tclearTimeout(entry.graceTimer)\n\t\t\t\tentry.graceTimer = null\n\t\t\t}\n\t\t\tentry.refCount++\n\t\t} else {\n\t\t\tconst result = fn.apply(this, args)\n\t\t\tentry = { args, result, refCount: 1, graceTimer: null }\n\t\t\tcache.push(entry)\n\t\t}\n\n\t\tconst capturedEntry = entry\n\t\tlet released = false\n\n\t\treturn {\n\t\t\tget value() { return capturedEntry.result },\n\t\t\trelease() {\n\t\t\t\tif (released) return // idempotent\n\t\t\t\treleased = true\n\t\t\t\tcapturedEntry.refCount--\n\n\t\t\t\tif (capturedEntry.refCount <= 0) {\n\t\t\t\t\tif (gracePeriodMs > 0) {\n\t\t\t\t\t\tcapturedEntry.graceTimer = setTimeout(() => {\n\t\t\t\t\t\t\tif (capturedEntry.refCount <= 0) {\n\t\t\t\t\t\t\t\tevict(capturedEntry, args)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, gracePeriodMs)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tevict(capturedEntry, args)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t}\n\t}\n}\n","import { Logger } from 'besonders-logger'\nimport { DebouncedFunc, pull, sortedIndexBy } from 'lodash-es'\nimport { Applog, ApplogForInsert } from '../applog/datom-types.ts'\nimport { isInitEvent, Thread, ThreadEvent } from './basic.ts'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO) // eslint-disable-line no-unused-vars\n\nexport type ApplogEventMapper = (this: MappedThread, event: ThreadEvent, sourceThread: Thread) => ThreadEvent\n// export type ApplogWriteMapper<T extends Applog[] | ApplogForInsert[]> = (this: MappedThread, applogs: T) => T | null // FIXME: the TS generics don't actually work how I want them to\nexport type ApplogWriteMapper = (this: MappedThread, applogs: Applog[] | ApplogForInsert[]) => Applog[] | ApplogForInsert[] | null\n\nexport class MappedThread extends Thread {\n\tstatic mapWrites(parent: Thread, name: string, mapper: ApplogWriteMapper) {\n\t\treturn new MappedThread(\n\t\t\t`${name}<${parent.nameAndSizeUntracked}>`,\n\t\t\tparent,\n\t\t\tparent.filters,\n\t\t\t// @ts-expect-error ? what's the proper way\n\t\t\tparent._applogs,\n\t\t\tnull,\n\t\t\tmapper,\n\t\t)\n\t}\n\tstatic asReadOnly(parent: Thread) {\n\t\tif (parent.readOnly) return parent // already read-only, no need to wrap\n\t\treturn new MappedThread(\n\t\t\t`readOnly(${parent.name})`,\n\t\t\tparent,\n\t\t\tparent.filters,\n\t\t\t// @ts-expect-error ? what's the proper way\n\t\t\tparent._applogs,\n\t\t\tnull,\n\t\t\tnull,\n\t\t\ttrue, // readOnly\n\t\t)\n\t}\n\tprivate _parentSubscriptions: Map<Thread, (() => void)> = null // mapped to unsubscribe function\n\n\tconstructor(\n\t\treadonly name: string,\n\t\tparents: Thread | readonly Thread[],\n\t\tfilters: readonly string[],\n\t\treadonly _initialLogs: Applog[],\n\t\tprivate _eventMapper: ApplogEventMapper | null,\n\t\tprivate _writeMapper: ApplogWriteMapper = null,\n\t\tprivate _readOnly?: boolean,\n\t) {\n\t\tsuper(\n\t\t\tname,\n\t\t\tparents,\n\t\t\tfilters,\n\t\t\t_eventMapper ?\n\t\t\t\t[..._initialLogs] // clone — mapped thread manages its own array\n\t\t\t\t: _initialLogs, // if we don't map events, we just re-use the array and then don't need to subscribe\n\t\t)\n\n\t\tif (_eventMapper) { // if we don't map events, we just re-use the array and then don't need to subscribe\n\t\t\tthis.subscribeToParents()\n\t\t}\n\t}\n\n\tpublic insert(appLogsToInsert: ApplogForInsert[]) {\n\t\tif (this.readOnly) throw ERROR(`[MappedThread] insert() called on read-only thread:`, this.nameAndSizeUntracked)\n\t\tconst mapped = this._writeMapper ? this._writeMapper(appLogsToInsert) : appLogsToInsert\n\t\tif (this._writeMapper && !mapped) return\n\t\treturn this.parents.forEach(parent => parent.insert(mapped))\n\t}\n\tpublic insertRaw(appLogsToInsert: Applog[]) {\n\t\tif (this.readOnly) throw ERROR(`[MappedThread] insertRaw() called on read-only thread:`, this.nameAndSizeUntracked)\n\t\tconst mapped = this._writeMapper ? this._writeMapper(appLogsToInsert) : appLogsToInsert\n\t\tif (this._writeMapper && !mapped) return\n\t\treturn this.parents.forEach(parent => parent.insertRaw(mapped as Applog[]))\n\t}\n\n\tprivate subscribeToParents() {\n\t\tthis._parentSubscriptions = new Map()\n\t\tif (!this.parents.length) {\n\t\t\tWARN(`MappedThread has no parents`, this)\n\t\t}\n\t\tVERBOSE(`[MappedThread: ${this.name}] subscribing to parents:`, this.parents.map(p => p.name))\n\n\t\tfor (const p of this.parents) {\n\t\t\tVERBOSE(`[MappedThread: ${this.name}] sub to parent`, p.nameAndSizeUntracked)\n\t\t\tconst sub = this.onParentUpdate.bind(this, p)\n\t\t\tconst unsubscribe = p.subscribe(sub, 'derived')\n\t\t\tthis._parentSubscriptions.set(p, unsubscribe)\n\t\t}\n\t}\n\n\t/** Tear down parent subscriptions and clear internal state */\n\tdispose() {\n\t\tif (this._parentSubscriptions) {\n\t\t\tfor (const [, unsubscribe] of this._parentSubscriptions) {\n\t\t\t\tunsubscribe()\n\t\t\t}\n\t\t\tthis._parentSubscriptions = null\n\t\t}\n\t}\n\n\t/** Swap parents at runtime — re-subscribes and recomputes applogs, notifying downstream */\n\tsetParents(newParents: readonly Thread[]) {\n\t\tthis.dispose()\n\t\t;(this as { parents: readonly Thread[] }).parents = newParents\n\t\tthis.subscribeToParents()\n\t\tthis.triggerRemap()\n\t}\n\n\tsubscribe(callback: (event: ThreadEvent) => void, type?: 'derived' | 'reaction') {\n\t\tif (!this._parentSubscriptions) {\n\t\t\tthis.subscribeToParents()\n\t\t}\n\t\treturn super.subscribe(callback, type)\n\t}\n\n\t/**\n\t * // HACK to trigger remap on pattern change in rollingFilter\n\t * should not be used lightly\n\t */\n\ttriggerRemap() {\n\t\tif (!this._eventMapper) throw ERROR(`triggerRemap on a thread that is not actually mapping?!`, this.nameAndSizeUntracked)\n\t\tDEBUG(`MappedThread{${this.nameAndSizeUntracked}} triggerRemap`)\n\t\tif (this.parents.length !== 1) {\n\t\t\tWARN(`MappedThread{${this.nameAndSizeUntracked}} triggerRemap with parentCount=${this.parents.length} - not meant for this`)\n\t\t}\n\t\tthis.parents.forEach(p => {\n\t\t\tthis.onParentUpdate(p, { init: [...p.applogs] })\n\t\t})\n\t}\n\n\tprotected onParentUpdate(thread: Thread, event: ThreadEvent) {\n\t\tVERBOSE(`MappedThread{${this.nameAndSizeUntracked}} parentUpdate`, event)\n\t\tconst mapResult = this._eventMapper ? this._eventMapper(event, thread) : event\n\t\tif (this._eventMapper) {\n\t\t\tVERBOSE(`MappedThread{${this.nameAndSizeUntracked}} parentUpdate => mapped`, mapResult)\n\t\t\tif (isInitEvent(mapResult)) {\n\t\t\t\tthis._applogs.length = 0\n\t\t\t\tthis._applogs.push(...mapResult.init)\n\t\t\t} else {\n\t\t\t\tfor (const log of mapResult.added) {\n\t\t\t\t\t// insert at right location to maintain sort order\n\t\t\t\t\tthis._applogs.splice(sortedIndexBy(this._applogs, log, 'ts'), 0, log)\n\t\t\t\t}\n\t\t\t\tif (mapResult.removed) {\n\t\t\t\t\tfor (const toRemove of mapResult.removed) {\n\t\t\t\t\t\tconst idx = this._applogs.indexOf(toRemove)\n\t\t\t\t\t\tif (idx >= 0) {\n\t\t\t\t\t\t\tthis._applogs.splice(idx, 1)\n\t\t\t\t\t\t} else if (!isInitEvent(event) && event.removed?.includes(toRemove)) {\n\t\t\t\t\t\t\tDEBUG(`Ignoring remove event for non-existent because it was part of parent event's removed`, toRemove, event) // ? convenience? - or is this a code smell?\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthrow ERROR(`MappedThread{${this.name}} toRemove contained log that doesn't exist`, toRemove, {\n\t\t\t\t\t\t\t\tthread: this,\n\t\t\t\t\t\t\t\tevent,\n\t\t\t\t\t\t\t\tmapResult,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} // (i) else, the _applogs is reactive to parent automatically, so no need\n\t\tthis.notifySubscribers(mapResult)\n\t}\n\tget readOnly() {\n\t\treturn this._readOnly ?? false\n\t}\n}\n","import { Logger } from 'besonders-logger'\nimport { ensureTsPvAndFinalizeApplogs } from '../applog/applog-helpers.ts'\nimport { isTsBefore, removeDuplicateAppLogs, sortApplogsByTs } from '../applog/applog-utils.ts'\nimport { type Applog, ApplogForInsert, CidString, isValidApplog } from '../applog/datom-types.ts'\nimport { Thread } from './basic.ts'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO) // eslint-disable-line no-unused-vars\n\nexport abstract class WriteableThread extends Thread {\n\tconstructor(\n\t\tname: string,\n\t\t// parents: Thread | readonly Thread[] | null, // ? would this ever be a thing\n\t\tapplogs: Applog[] = [],\n\t\tfilters: readonly string[],\n\t) {\n\t\tsuper(name, null, filters, applogs)\n\t}\n\n\tpublic purge(cidsToPurge: CidString[]) {\n\t\tconst beforeCount = this.applogs.length\n\t\t// HACK setting readonly\n\t\tthis._applogs = this.applogs.filter(log => !(cidsToPurge.includes(log.cid)))\n\t\treturn beforeCount - this.applogs.length\n\t}\n\tpublic insert(appLogsToInsert: ApplogForInsert[]) {\n\t\tDEBUG(`[WriteableThread.insert] ENTER - ${appLogsToInsert.length} applogs for thread \"${this.name}\"`)\n\t\tDEBUG(`[WriteableThread.insert] About to call ensureTsPvAndFinalizeApplogs`)\n\t\tconst mapped = ensureTsPvAndFinalizeApplogs(appLogsToInsert, this)\n\t\tDEBUG(`[WriteableThread.insert] ensureTsPvAndFinalizeApplogs completed, mapped=${mapped.length} applogs`)\n\t\tDEBUG(`[WriteableThread.insert] About to call insertRaw`)\n\t\tconst result = this.insertRaw(mapped)\n\t\tDEBUG(`[WriteableThread.insert] insertRaw completed`)\n\t\treturn result\n\t}\n\n\t/**\n\t * Insert only applogs not already in this thread.\n\t * @param byRef If true, compares by reference; if false, compares by CID (default)\n\t * @returns The applogs that were actually inserted\n\t */\n\tpublic insertMissing(appLogsToInsert: readonly Applog[], byRef = false): Applog[] {\n\t\tconst missing = appLogsToInsert.filter(log => !this.hasApplog(log, byRef))\n\t\tif (missing.length === 0) {\n\t\t\tVERBOSE(`[insertMissing] no missing applogs`)\n\t\t\treturn []\n\t\t}\n\t\treturn this.insertRaw(missing) ?? []\n\t}\n\n\t/**\n\t * Insert raw applogs directly into the thread.\n\t *\n\t * STRICT VALIDATION: This method throws errors for:\n\t * - Duplicate applogs in input array (programming error)\n\t * - Invalid applogs (missing required fields)\n\t * - Applogs already in thread (programming error)\n\t *\n\t * For external imports where duplicates are expected, use removeDuplicateAppLogs(..., 'cleanup')\n\t * before calling this method.\n\t *\n\t * @param appLogsToInsert Must be deduplicated and validated. Needs to be mutable because it will be sorted\n\t * \t(and if you need to clone it, so do it when you need to) - this is weird as TS is slathering type safety onto ducks\n\t * @throws Error if validation fails\n\t */\n\tpublic insertRaw(appLogsToInsert: Applog[]) {\n\t\tDEBUG(`[WriteableThread.insertRaw] ENTER - ${appLogsToInsert.length} applogs for thread \"${this.name}\"`)\n\t\tDEBUG(`[WriteableThread.insertRaw] About to deduplicate`)\n\t\tconst deduplicated = removeDuplicateAppLogs(appLogsToInsert, 'safety')\n\t\tif (deduplicated.length !== appLogsToInsert.length) {\n\t\t\tthrow ERROR(`[insertRaw] duplicate applogs passed: ${appLogsToInsert.length - deduplicated.length}`, {\n\t\t\t\tappLogsToInsert,\n\t\t\t\tdeduplicated,\n\t\t\t})\n\t\t}\n\t\tDEBUG(`[WriteableThread.insertRaw] Deduplication done`)\n\n\t\tDEBUG(`[WriteableThread.insertRaw] About to validate`)\n\t\tconst bogus = appLogsToInsert.filter(log => !isValidApplog(log))\n\t\tif (bogus.length) {\n\t\t\tthrow ERROR(`[insertRaw] bogus applogs passed: ${bogus.length}`, { bogus })\n\t\t}\n\t\tDEBUG(`[WriteableThread.insertRaw] Validation done`)\n\n\t\tDEBUG(`[WriteableThread.insertRaw] About to check for existing`)\n\t\tconst existing = appLogsToInsert.filter(log => this.hasApplog(log, false))\n\t\tif (existing.length) {\n\t\t\tthrow ERROR(`[insertRaw] already existing applogs passed: ${existing.length}`, { existing })\n\t\t}\n\t\tDEBUG(`[WriteableThread.insertRaw] Existing check done`)\n\n\t\tif (!appLogsToInsert.length) {\n\t\t\tWARN('[insertRaw] skipping empty insert empty logs array')\n\t\t\treturn\n\t\t}\n\n\t\t;(!this.hasParents && !(this instanceof ThreadInMemory) ? LOG : DEBUG)(\n\t\t\t'Inserting:',\n\t\t\tappLogsToInsert.length === 1 ? appLogsToInsert[0] : appLogsToInsert,\n\t\t\t{ ds: this },\n\t\t)\n\t\tDEBUG(`[WriteableThread.insertRaw] About to sort applogs`)\n\t\tsortApplogsByTs(appLogsToInsert)\n\t\tconst sortNeeded = this._applogs.length && isTsBefore(appLogsToInsert[0], this._applogs[this._applogs.length - 1])\n\t\tDEBUG(`[WriteableThread.insertRaw] About to push to _applogs array`)\n\t\t// Chunked push: spread is fast but causes stack overflow with 100k+ items\n\t\t// Chunking keeps us under the limit while using optimized push()\n\t\tconst CHUNK_SIZE = 50_000\n\t\tfor (let i = 0; i < appLogsToInsert.length; i += CHUNK_SIZE) {\n\t\t\tthis._applogs.push(...appLogsToInsert.slice(i, i + CHUNK_SIZE))\n\t\t}\n\t\tif (sortNeeded) {\n\t\t\tDEBUG(`[WriteableThread.insertRaw] About to sort _applogs (sortNeeded=true)`)\n\t\t\tsortApplogsByTs(this._applogs)\n\t\t}\n\t\tDEBUG(`[WriteableThread.insertRaw] About to notify subscribers`)\n\t\tthis.notifySubscribers({ added: appLogsToInsert, removed: null })\n\t\tDEBUG(`[WriteableThread.insertRaw] Subscribers notified`)\n\n\t\t// ? persist sync\n\t\tDEBUG(`[WriteableThread.insertRaw] About to call persist (void - not awaited)`)\n\t\tvoid this.persist(appLogsToInsert)\n\t\tDEBUG(`[WriteableThread.insertRaw] EXIT - returning ${appLogsToInsert.length} applogs`)\n\t\treturn appLogsToInsert\n\t}\n\n\tget readOnly() {\n\t\treturn false\n\t}\n\n\tprotected abstract persist(logs: Applog[]): Promise<void>\n}\nexport class ThreadInMemory extends WriteableThread {\n\tstatic empty(name?: string) {\n\t\treturn ThreadInMemory.fromArray([], name ?? 'empty in-memory', false)\n\t}\n\tstatic fromArray(applogs: Applog[], name?: string, readOnly = false) {\n\t\treturn new ThreadInMemory(name ?? 'in-memory', applogs, [], readOnly)\n\t}\n\tstatic fromReadOnlyArray(applogs: readonly Applog[], name?: string) {\n\t\t// @ts-expect-error readonly conditional drama\n\t\treturn new ThreadInMemory(name ?? 'in-memory', applogs, [], true) \n\t}\n\n\tconstructor(\n\t\tname: string,\n\t\tapplogs: Applog[],\n\t\tfilters: readonly string[],\n\t\treadonly _readOnly: boolean,\n\t) {\n\t\tsuper(name, applogs, filters)\n\t}\n\n\tget readOnly() {\n\t\treturn this._readOnly\n\t}\n\n\tprotected async persist(logs: Applog[]) {\n\t\tVERBOSE(`[InMem.persist] no persist for`, logs)\n\t\tif (this.readOnly) {\n\t\t\tthrow ERROR(`[persist] called for readOnly thread`)\n\t\t}\n\t}\n}\n","import { Logger } from 'besonders-logger'\nimport { curry, debounce, partial, pull, uniq, uniqBy, uniqWith } from 'lodash-es'\n\nimport { CID } from 'multiformats'\nimport { ensureTsPvAndFinalizeApplogs, joinThreads } from '../applog/applog-helpers.ts'\nimport { compareApplogsByEnAt, compareApplogsByTs, objEqualByKeys } from '../applog/applog-utils.ts'\nimport { Applog, ApplogForInsert, CidString, EntityID } from '../applog/datom-types.ts'\nimport { Thread } from './basic.ts'\nimport { MappedThread } from './mapped.ts'\nimport { ThreadInMemory, WriteableThread } from './writeable.ts'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO) // eslint-disable-line no-unused-vars\n\nexport function entityCount(thread: Thread) {\n\treturn allEntityIDs(thread).size // at some point: index size?\n}\nexport function allEntityIDs(thread: Thread) {\n\treturn accumulateLogsToSet(thread, log => log.en)\n}\n\nfunction accumulateLogsToSet<ACC>(\n\tthreadOrLogs: Thread | Applog[],\n\tcallback: (log: Applog, acc: Set<ACC>) => ACC | undefined,\n) {\n\tconst logs = threadOrLogs instanceof Thread ? threadOrLogs.applogs : threadOrLogs\n\tconst set = new Set<ACC>()\n\tfor (const log of logs) {\n\t\tset.add(callback(log, set))\n\t}\n\treturn set\n}\n\nexport function debounceWrites(\n\tthread: Thread,\n\twait = 700,\n\tremoveDuplicatesWith = compareApplogsByEnAt,\n) {\n\tif (thread.readOnly) throw ERROR(`[debounceWrites] but readOnly thread`, thread.name)\n\tlet insertQueue: Array<Applog | ApplogForInsert> = []\n\n\tconst debouncedCommit = debounce(() => {\n\t\tWARN(`Debounce tail`, { thread, mappedThread, insertQueue })\n\t\tconst toInsert = ensureTsPvAndFinalizeApplogs(\n\t\t\t// ? uniq, sure - but which one is used? (update: seems the first one, so reverse)\n\t\t\tuniqWith(insertQueue.reverse(), removeDuplicatesWith),\n\t\t\tthread,\n\t\t)\n\t\tthread.insertRaw(toInsert)\n\t\tinsertQueue.splice(0, insertQueue.length) // clear queue\n\t}, wait)\n\tconst handleInsert = (applogs: Applog[] | ApplogForInsert[]) => {\n\t\tDEBUG(`Debounce input:`, applogs, { thread, mappedThread, insertQueue })\n\t\tinsertQueue.push(...applogs)\n\t\tdebouncedCommit()\n\t\treturn null // don't insert anything\n\t}\n\n\tconst mappedThread = MappedThread.mapWrites(\n\t\tthread,\n\t\t`Debounce(${wait})`,\n\t\thandleInsert,\n\t)\n\treturn mappedThread\n}\n\n/**\n * @param deduplicateHoldItemsWith called with (heldLog, realLog), if it returns true, the held log is skipped\n * @param onFirstWrite called with held logs about to be inserted, if it returns an array, those logs will be inserted instead\n */\nexport function holdTillFirstWrite(\n\tthread: Thread,\n\tapplogsToHold: ApplogForInsert[],\n\topts: {\n\t\tdeduplicateHoldItemsWith?: typeof compareApplogsByEnAt\n\t\tonFirstWrite: (heldLogsToInsert: Applog[]) => Applog[] | undefined\n\t},\n) {\n\tDEBUG(`[holdTillFirstWrite] holding logs:`, { applogsToHold })\n\tif (thread.readOnly) throw ERROR(`[holdTillFirstWrite] but readOnly thread`, thread.nameAndSizeUntracked)\n\tconst heldLogs = ensureTsPvAndFinalizeApplogs([...applogsToHold], thread)\n\tconst heldThread = ThreadInMemory.fromArray(heldLogs)\n\n\tlet hasInserted = false\n\tconst handleInsert = (realApplogs: Applog[] | ApplogForInsert[]) => {\n\t\tif (hasInserted) return realApplogs\n\t\thasInserted = true\n\n\t\tlet toInsert = [...heldLogs]\n\t\t// heldLogs.splice(0, heldLogs.length) // ? joinThread could take care of this\n\t\tif (opts.deduplicateHoldItemsWith) {\n\t\t\ttoInsert = toInsert.filter(heldLog =>\n\t\t\t\t// some duplicate? so don't insert\n\t\t\t\t!realApplogs.some(realLog => opts.deduplicateHoldItemsWith(heldLog, realLog))\n\t\t\t)\n\t\t}\n\t\tif (opts.onFirstWrite) {\n\t\t\tconst callbackResult = opts.onFirstWrite(toInsert)\n\t\t\tif (callbackResult !== undefined) {\n\t\t\t\ttoInsert = callbackResult\n\t\t\t}\n\t\t}\n\t\tDEBUG(`[holdTillFirstWrite] adding hold logs:`, { applogsToHold, heldLogs, toInsert, realApplogs })\n\t\treturn [...toInsert, ...realApplogs]\n\t}\n\tconst joinedThread = joinThreads([thread, heldThread])\n\treturn new MappedThread(\n\t\t`HoldTillFirstWrite[${applogsToHold.length}]<${thread.nameAndSizeUntracked}>`,\n\t\tjoinedThread,\n\t\tthread.filters,\n\t\t// @ts-expect-error ? what's the proper way\n\t\tjoinedThread.applogs,\n\t\tnull,\n\t\t(applogs) => {\n\t\t\tconst logsToInsert = handleInsert(applogs)\n\t\t\tthread.insert(logsToInsert)\n\t\t\treturn null\n\t\t},\n\t)\n}\n\nexport function getAgents(thread: Thread) {\n\treturn uniq(thread.map(l => l.ag))\n}\n\n/**\n * Returns applogs NOT contained in the exclusion set.\n * Uses CID-based comparison (consistent with removeDuplicateAppLogs).\n */\nexport const excludeApplogsContainedIn = (\n\tapplogs: readonly Applog[],\n\texclude: Thread | readonly Applog[] | Set<CID | CidString>,\n): Applog[] => {\n\tconst excludeCids: Set<string> = exclude instanceof Set\n\t\t? new Set([...exclude].map(c => c.toString()))\n\t\t: exclude instanceof Thread\n\t\t\t? new Set(exclude.applogsCids)\n\t\t\t: new Set(exclude.map(a => a.cid))\n\n\treturn applogs.filter(applog => {\n\t\tif (!applog.cid) {\n\t\t\tERROR(`applog with missing CID`, applog)\n\t\t\tthrow new Error(`applog with missing CID`)\n\t\t}\n\t\treturn !excludeCids.has(applog.cid)\n\t})\n}\n"],"mappings":"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","names":["Logger","stringify","Logger","Logger","WARN","LOG","DEBUG","VERBOSE","ERROR","Logger","Logger","stringify","WARN","LOG","DEBUG","VERBOSE","ERROR","context","sum","mean","WARN","LOG","DEBUG","VERBOSE","ERROR","Logger","isEqual","isEqual","Logger","WARN","LOG","DEBUG","VERBOSE","ERROR","Logger","WARN","LOG","DEBUG","VERBOSE","ERROR","Logger","rollingFilter","stringify","rollingMapper","rollingAcc","getUntrackedPattern","getUntrackedFilterResults","simpleApplogMapper","thread","Logger","WARN","LOG","DEBUG","VERBOSE","ERROR","Logger","Logger","WARN","LOG","DEBUG","VERBOSE","ERROR","Logger"]}
@@ -0,0 +1,55 @@
1
+ import {
2
+ ThreadInMemory,
3
+ createDebugName,
4
+ memoizedFn
5
+ } from "./chunk-XIQSYEV3.js";
6
+
7
+ // src/query/divergences.ts
8
+ import { Logger } from "besonders-logger";
9
+ var { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO);
10
+ var queryDivergencesByPrev = memoizedFn("queryDivergencesByPrev", function queryConflictingByPrev(sourceThread) {
11
+ DEBUG(`queryDivergencesByPrev<${sourceThread.nameAndSizeUntracked}>`);
12
+ if (sourceThread.filters.includes("lastWriteWins")) WARN(`queryDivergencesByPrev on thread lastWriteWins`, sourceThread);
13
+ const logsForNode = /* @__PURE__ */ new Map();
14
+ const leafs = /* @__PURE__ */ new Set();
15
+ VERBOSE("all applogs:", sourceThread.applogs);
16
+ for (const log of sourceThread.applogs) {
17
+ let prevLogs;
18
+ if (log.pv) {
19
+ prevLogs = log.pv && logsForNode.get(log.pv.toString());
20
+ leafs.delete(log.pv.toString());
21
+ }
22
+ VERBOSE("traversing log", { log, prevLogs, leafs: Array.from(leafs) });
23
+ logsForNode.set(log.cid, prevLogs ? [...prevLogs, log] : [log]);
24
+ leafs.add(log.cid);
25
+ }
26
+ const divergences = Array.from(leafs).map((leafID) => {
27
+ const thread = new ThreadInMemory(
28
+ createDebugName({
29
+ caller: "DivergenceLeaf",
30
+ thread: sourceThread,
31
+ pattern: `leaf: ${leafID}`
32
+ }),
33
+ logsForNode.get(leafID),
34
+ sourceThread.filters,
35
+ true
36
+ );
37
+ return { log: thread.latestLog, thread };
38
+ });
39
+ return divergences;
40
+ });
41
+
42
+ // src/query/matchers.ts
43
+ function includes(str) {
44
+ return (vl) => vl?.includes?.(str);
45
+ }
46
+ function includedIn(arr) {
47
+ return (vl) => arr?.includes?.(vl);
48
+ }
49
+
50
+ export {
51
+ queryDivergencesByPrev,
52
+ includes,
53
+ includedIn
54
+ };
55
+ //# sourceMappingURL=chunk-XVGW4QC3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/query/divergences.ts","../src/query/matchers.ts"],"sourcesContent":["import { Logger } from 'besonders-logger'\nimport stringify from 'safe-stable-stringify'\nimport { Applog, CidString } from '../applog/datom-types.ts'\nimport { createDebugName } from '../utils/debug-name.ts'\nimport { Thread } from '../thread/basic.ts'\nimport { ThreadInMemory } from '../thread/writeable.ts'\nimport { memoizedFn } from './memoized.ts'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO) // eslint-disable-line no-unused-vars\n\nexport interface DivergenceLeaf {\n\tlog: Applog\n\tthread: Thread\n}\n\nexport const queryDivergencesByPrev = memoizedFn('queryDivergencesByPrev', function queryConflictingByPrev(\n\tsourceThread: Thread,\n) {\n\tDEBUG(`queryDivergencesByPrev<${sourceThread.nameAndSizeUntracked}>`)\n\tif (sourceThread.filters.includes('lastWriteWins')) WARN(`queryDivergencesByPrev on thread lastWriteWins`, sourceThread)\n\n\tconst logsForNode = new Map<CidString, Applog[]>()\n\tconst leafs = new Set<CidString>()\n\tVERBOSE('all applogs:', sourceThread.applogs)\n\tfor (const log of sourceThread.applogs) {\n\t\tlet prevLogs\n\t\tif (log.pv) {\n\t\t\tprevLogs = log.pv && logsForNode.get(log.pv.toString())\n\t\t\tleafs.delete(log.pv.toString())\n\t\t}\n\t\tVERBOSE('traversing log', { log, prevLogs, leafs: Array.from(leafs) })\n\t\tlogsForNode.set(log.cid, prevLogs ? [...prevLogs, log] : [log])\n\t\tleafs.add(log.cid)\n\t}\n\tconst divergences = Array.from(leafs).map(leafID => {\n\t\tconst thread = new ThreadInMemory(\n\t\t\tcreateDebugName({\n\t\t\t\tcaller: 'DivergenceLeaf',\n\t\t\t\tthread: sourceThread,\n\t\t\t\tpattern: `leaf: ${leafID}`,\n\t\t\t}),\n\t\t\tlogsForNode.get(leafID),\n\t\t\tsourceThread.filters,\n\t\t\ttrue,\n\t\t)\n\t\treturn ({ log: thread.latestLog, thread })\n\t})\n\t// TODO: migrate to SubscribableArray for reactive updates\n\treturn divergences\n})\n","import { DatomPart } from '../applog/datom-types.ts'\n\nexport function includes(str: string) {\n\treturn (vl: DatomPart) => vl?.includes?.(str)\n}\nexport function includedIn(arr: string[]) {\n\treturn (vl: DatomPart) => arr?.includes?.(vl)\n}\n"],"mappings":";;;;;;;AAAA,SAAS,cAAc;AAQvB,IAAM,EAAE,MAAM,KAAK,OAAO,SAAS,MAAM,IAAI,OAAO,MAAM,OAAO,IAAI;AAO9D,IAAM,yBAAyB,WAAW,0BAA0B,SAAS,uBACnF,cACC;AACD,QAAM,0BAA0B,aAAa,oBAAoB,GAAG;AACpE,MAAI,aAAa,QAAQ,SAAS,eAAe,EAAG,MAAK,kDAAkD,YAAY;AAEvH,QAAM,cAAc,oBAAI,IAAyB;AACjD,QAAM,QAAQ,oBAAI,IAAe;AACjC,UAAQ,gBAAgB,aAAa,OAAO;AAC5C,aAAW,OAAO,aAAa,SAAS;AACvC,QAAI;AACJ,QAAI,IAAI,IAAI;AACX,iBAAW,IAAI,MAAM,YAAY,IAAI,IAAI,GAAG,SAAS,CAAC;AACtD,YAAM,OAAO,IAAI,GAAG,SAAS,CAAC;AAAA,IAC/B;AACA,YAAQ,kBAAkB,EAAE,KAAK,UAAU,OAAO,MAAM,KAAK,KAAK,EAAE,CAAC;AACrE,gBAAY,IAAI,IAAI,KAAK,WAAW,CAAC,GAAG,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC;AAC9D,UAAM,IAAI,IAAI,GAAG;AAAA,EAClB;AACA,QAAM,cAAc,MAAM,KAAK,KAAK,EAAE,IAAI,YAAU;AACnD,UAAM,SAAS,IAAI;AAAA,MAClB,gBAAgB;AAAA,QACf,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,SAAS,SAAS,MAAM;AAAA,MACzB,CAAC;AAAA,MACD,YAAY,IAAI,MAAM;AAAA,MACtB,aAAa;AAAA,MACb;AAAA,IACD;AACA,WAAQ,EAAE,KAAK,OAAO,WAAW,OAAO;AAAA,EACzC,CAAC;AAED,SAAO;AACR,CAAC;;;AC/CM,SAAS,SAAS,KAAa;AACrC,SAAO,CAAC,OAAkB,IAAI,WAAW,GAAG;AAC7C;AACO,SAAS,WAAW,KAAe;AACzC,SAAO,CAAC,OAAkB,KAAK,WAAW,EAAE;AAC7C;","names":[]}
@@ -0,0 +1,9 @@
1
+ // src/utils.ts
2
+ var isTruthy = (l) => !!l;
3
+ var keepTruthy = (arr) => arr.filter(isTruthy);
4
+
5
+ export {
6
+ isTruthy,
7
+ keepTruthy
8
+ };
9
+ //# sourceMappingURL=chunk-YDAKBU6Q.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils.ts"],"sourcesContent":["import { Applog, ApplogEncNoCid } from './applog/datom-types.ts'\n\nexport const isTruthy = (l: Applog | ApplogEncNoCid): boolean => !!l\nexport const keepTruthy = (arr: readonly any[]): any[] => arr.filter(isTruthy)\n"],"mappings":";AAEO,IAAM,WAAW,CAAC,MAAwC,CAAC,CAAC;AAC5D,IAAM,aAAa,CAAC,QAA+B,IAAI,OAAO,QAAQ;","names":[]}
@@ -0,0 +1,36 @@
1
+ // src/types/typescript-utils.ts
2
+ import { Type as T } from "@sinclair/typebox";
3
+ var { String: StringTB, Optional: OptionalTB, Boolean: BooleanTB, Object: ObjectTB, Number: NumberTB } = T;
4
+ var Str = StringTB.bind(T);
5
+ var Num = NumberTB.bind(T);
6
+ var Obj = ObjectTB.bind(T);
7
+ var Opt = OptionalTB.bind(T);
8
+ var Bool = BooleanTB.bind(T);
9
+ var STR = Str();
10
+ var NUM = Num();
11
+ var BOOL = Bool();
12
+ function checkParityTB() {
13
+ const s1 = Str();
14
+ const s2 = Str();
15
+ const n1 = Num();
16
+ const n2 = Num();
17
+ console.log({ s1, s2, n1, n2 });
18
+ }
19
+ function arrayIfSingle(arrOrSingle) {
20
+ if (Array.isArray(arrOrSingle)) return arrOrSingle;
21
+ else return [arrOrSingle];
22
+ }
23
+
24
+ export {
25
+ Str,
26
+ Num,
27
+ Obj,
28
+ Opt,
29
+ Bool,
30
+ STR,
31
+ NUM,
32
+ BOOL,
33
+ checkParityTB,
34
+ arrayIfSingle
35
+ };
36
+ //# sourceMappingURL=chunk-ZAADLBSB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types/typescript-utils.ts"],"sourcesContent":["import { Type as T } from '@sinclair/typebox'\n// import { Thread } from '../thread/basic.ts'\n\n// ! circular import\n// export const ThreadTB = TypeSystem.Type<Thread>('Thread', (options, value) => {\n// \treturn value instanceof Thread\n// })()\nconst { String: StringTB, Optional: OptionalTB, Boolean: BooleanTB, Object: ObjectTB, Number: NumberTB } = T\nexport const Str: typeof StringTB = StringTB.bind(T)\nexport const Num: typeof NumberTB = NumberTB.bind(T)\nexport const Obj: typeof ObjectTB = ObjectTB.bind(T)\nexport const Opt: typeof OptionalTB = OptionalTB.bind(T)\nexport const Bool: typeof BooleanTB = BooleanTB.bind(T)\n\nexport const STR: ReturnType<typeof T.String> = Str()\nexport const NUM: ReturnType<typeof T.Number> = Num()\nexport const BOOL: ReturnType<typeof T.Boolean> = Bool()\n\nexport type GenericObject = Record<string, any>\nexport type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>\nexport type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>\nexport type PromiseType<T extends Promise<any>> = T extends Promise<infer U> ? U : never\n\nexport type CoerceToString<T> = T extends string ? T : never\n\n/**\n * Define nominal type of U based on type of T. Similar to Opaque types in Flow\n */\nexport type Tagged<T, Tag> = T & { tag?: Tag }\n\n// export interface Service {\n// \tendpoint?: URL\n// \ttoken: string\n// \trateLimiter?: RateLimiter\n// \tfetch?: typeof _fetch\n// }\n\n// https://stackoverflow.com/a/76276541\nexport type LastElementOf<T extends readonly unknown[]> = T extends readonly [...unknown[], infer Last] ? Last : never\n\nexport function checkParityTB() {\n\t/* Most examples are constantly calling Type.*() - needed to check if its really needed\n https://github.com/sinclairzx81/typebox/issues/587#issuecomment-1712457623\n */\n\tconst s1 = Str()\n\tconst s2 = Str()\n\tconst n1 = Num()\n\tconst n2 = Num()\n\tconsole.log({ s1, s2, n1, n2 })\n}\n\n/** solidjs Setter requires returning something, which I often don't */\nexport type GenericSetter<T> = (newValue: T) => void\n\nexport type ArrayOrSingle<T> = T | T[] | readonly T[]\nexport function arrayIfSingle<T>(arrOrSingle: ArrayOrSingle<T>): readonly T[] {\n\tif (Array.isArray(arrOrSingle)) return arrOrSingle\n\telse return [arrOrSingle] as readonly T[]\n}\nexport type ArrayType<T> = T extends (infer U)[] ? U : T\nexport type ArrayElementType<T> = T extends readonly (infer U)[] ? Extract<U, string> : never\nexport type ConstructorType<T, S = {}> = {\n\tnew(...args: any[]): T\n} & S\n"],"mappings":";AAAA,SAAS,QAAQ,SAAS;AAO1B,IAAM,EAAE,QAAQ,UAAU,UAAU,YAAY,SAAS,WAAW,QAAQ,UAAU,QAAQ,SAAS,IAAI;AACpG,IAAM,MAAuB,SAAS,KAAK,CAAC;AAC5C,IAAM,MAAuB,SAAS,KAAK,CAAC;AAC5C,IAAM,MAAuB,SAAS,KAAK,CAAC;AAC5C,IAAM,MAAyB,WAAW,KAAK,CAAC;AAChD,IAAM,OAAyB,UAAU,KAAK,CAAC;AAE/C,IAAM,MAAmC,IAAI;AAC7C,IAAM,MAAmC,IAAI;AAC7C,IAAM,OAAqC,KAAK;AAwBhD,SAAS,gBAAgB;AAI/B,QAAM,KAAK,IAAI;AACf,QAAM,KAAK,IAAI;AACf,QAAM,KAAK,IAAI;AACf,QAAM,KAAK,IAAI;AACf,UAAQ,IAAI,EAAE,IAAI,IAAI,IAAI,GAAG,CAAC;AAC/B;AAMO,SAAS,cAAiB,aAA6C;AAC7E,MAAI,MAAM,QAAQ,WAAW,EAAG,QAAO;AAAA,MAClC,QAAO,CAAC,WAAW;AACzB;","names":[]}