@agentshouse/mdruntime 0.1.0-cb2e390ee7b89 → 0.1.0-cb3bb3b233fa1

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 (407) hide show
  1. package/README.md +24 -19
  2. package/dist/acceptance.d.ts +3 -0
  3. package/dist/acceptance.d.ts.map +1 -0
  4. package/dist/acceptance.js +299 -0
  5. package/dist/act-lanes.d.ts +30 -0
  6. package/dist/act-lanes.d.ts.map +1 -0
  7. package/dist/act-lanes.js +225 -0
  8. package/dist/actions.d.ts +26 -0
  9. package/dist/actions.d.ts.map +1 -0
  10. package/dist/actions.js +302 -0
  11. package/dist/adapter.d.ts +214 -123
  12. package/dist/adapter.d.ts.map +1 -1
  13. package/dist/attached-model.d.ts +6 -10
  14. package/dist/attached-model.d.ts.map +1 -1
  15. package/dist/attached-model.js +35 -41
  16. package/dist/authored.d.ts +88 -0
  17. package/dist/authored.d.ts.map +1 -0
  18. package/dist/authored.js +345 -0
  19. package/dist/binary.d.ts +0 -5
  20. package/dist/binary.d.ts.map +1 -1
  21. package/dist/binary.js +1 -1
  22. package/dist/bootstrap.d.ts +30 -11
  23. package/dist/bootstrap.d.ts.map +1 -1
  24. package/dist/bootstrap.js +309 -113
  25. package/dist/cell.d.ts +6 -0
  26. package/dist/cell.d.ts.map +1 -0
  27. package/dist/cell.js +9 -0
  28. package/dist/chain.d.ts +12 -0
  29. package/dist/chain.d.ts.map +1 -0
  30. package/dist/chain.js +64 -0
  31. package/dist/change-set.d.ts +13 -16
  32. package/dist/change-set.d.ts.map +1 -1
  33. package/dist/change-set.js +17 -89
  34. package/dist/change.d.ts +36 -1
  35. package/dist/change.d.ts.map +1 -1
  36. package/dist/change.js +17 -3
  37. package/dist/chat-types.d.ts +3 -0
  38. package/dist/chat-types.d.ts.map +1 -0
  39. package/dist/chat-types.js +11 -0
  40. package/dist/client.d.ts +39 -25
  41. package/dist/client.d.ts.map +1 -1
  42. package/dist/client.js +117 -23
  43. package/dist/collection.d.ts +32 -21
  44. package/dist/collection.d.ts.map +1 -1
  45. package/dist/collection.js +53 -288
  46. package/dist/column.d.ts +5 -0
  47. package/dist/column.d.ts.map +1 -0
  48. package/dist/column.js +9 -0
  49. package/dist/compile.d.ts +18 -0
  50. package/dist/compile.d.ts.map +1 -0
  51. package/dist/compile.js +723 -0
  52. package/dist/connection.d.ts +7 -134
  53. package/dist/connection.d.ts.map +1 -1
  54. package/dist/connection.js +109 -3606
  55. package/dist/context.d.ts +2 -0
  56. package/dist/context.d.ts.map +1 -0
  57. package/dist/{chat/context.js → context.js} +2 -5
  58. package/dist/conversation-live.d.ts +150 -0
  59. package/dist/conversation-live.d.ts.map +1 -0
  60. package/dist/conversation-live.js +259 -0
  61. package/dist/conversation-row.d.ts +40 -0
  62. package/dist/conversation-row.d.ts.map +1 -0
  63. package/dist/conversation-row.js +66 -0
  64. package/dist/conversation.d.ts +80 -50
  65. package/dist/conversation.d.ts.map +1 -1
  66. package/dist/conversation.js +1037 -793
  67. package/dist/declaration.d.ts +10 -0
  68. package/dist/declaration.d.ts.map +1 -0
  69. package/dist/declaration.js +24 -0
  70. package/dist/digest.d.ts +7 -0
  71. package/dist/digest.d.ts.map +1 -0
  72. package/dist/digest.js +113 -0
  73. package/dist/discovery.d.ts +10 -0
  74. package/dist/discovery.d.ts.map +1 -0
  75. package/dist/discovery.js +150 -0
  76. package/dist/durability.d.ts +20 -4
  77. package/dist/durability.d.ts.map +1 -1
  78. package/dist/durability.js +9 -0
  79. package/dist/entry.d.ts +5 -2
  80. package/dist/entry.d.ts.map +1 -1
  81. package/dist/entry.js +33 -28
  82. package/dist/expectation.d.ts +26 -13
  83. package/dist/expectation.d.ts.map +1 -1
  84. package/dist/expectation.js +72 -19
  85. package/dist/failure.d.ts +3 -0
  86. package/dist/failure.d.ts.map +1 -1
  87. package/dist/failure.js +6 -0
  88. package/dist/figures.d.ts +49 -0
  89. package/dist/figures.d.ts.map +1 -0
  90. package/dist/figures.js +199 -0
  91. package/dist/file.d.ts +2 -19
  92. package/dist/file.d.ts.map +1 -1
  93. package/dist/file.js +8 -122
  94. package/dist/holdings.d.ts +29 -0
  95. package/dist/holdings.d.ts.map +1 -0
  96. package/dist/holdings.js +95 -0
  97. package/dist/host.d.ts +21 -11
  98. package/dist/host.d.ts.map +1 -1
  99. package/dist/host.js +126 -53
  100. package/dist/identity.d.ts +0 -2
  101. package/dist/identity.d.ts.map +1 -1
  102. package/dist/identity.js +0 -6
  103. package/dist/index.d.ts +41 -16
  104. package/dist/index.d.ts.map +1 -1
  105. package/dist/index.js +19 -4
  106. package/dist/install.d.ts +60 -0
  107. package/dist/install.d.ts.map +1 -0
  108. package/dist/install.js +537 -0
  109. package/dist/lifecycle.d.ts +7 -0
  110. package/dist/lifecycle.d.ts.map +1 -0
  111. package/dist/lifecycle.js +282 -0
  112. package/dist/listing.d.ts +52 -0
  113. package/dist/listing.d.ts.map +1 -0
  114. package/dist/listing.js +152 -0
  115. package/dist/live.d.ts +25 -0
  116. package/dist/live.d.ts.map +1 -0
  117. package/dist/live.js +206 -0
  118. package/dist/loaded.d.ts +5 -0
  119. package/dist/loaded.d.ts.map +1 -0
  120. package/dist/loaded.js +40 -0
  121. package/dist/locks.d.ts +7 -0
  122. package/dist/locks.d.ts.map +1 -0
  123. package/dist/locks.js +32 -0
  124. package/dist/lost.d.ts +5 -0
  125. package/dist/lost.d.ts.map +1 -0
  126. package/dist/lost.js +49 -0
  127. package/dist/media.d.ts +13 -0
  128. package/dist/media.d.ts.map +1 -0
  129. package/dist/media.js +269 -0
  130. package/dist/memory.d.ts +20 -8
  131. package/dist/memory.d.ts.map +1 -1
  132. package/dist/memory.js +311 -121
  133. package/dist/messages.d.ts +58 -0
  134. package/dist/messages.d.ts.map +1 -0
  135. package/dist/messages.js +160 -0
  136. package/dist/model.d.ts +8 -11
  137. package/dist/model.d.ts.map +1 -1
  138. package/dist/model.js +6 -23
  139. package/dist/models.d.ts +10 -0
  140. package/dist/models.d.ts.map +1 -0
  141. package/dist/models.js +153 -0
  142. package/dist/name.d.ts +4 -0
  143. package/dist/name.d.ts.map +1 -0
  144. package/dist/name.js +122 -0
  145. package/dist/observation.d.ts +38 -10
  146. package/dist/observation.d.ts.map +1 -1
  147. package/dist/observation.js +232 -44
  148. package/dist/opened.d.ts +22 -0
  149. package/dist/opened.d.ts.map +1 -0
  150. package/dist/opened.js +107 -0
  151. package/dist/opening.d.ts +4 -0
  152. package/dist/opening.d.ts.map +1 -0
  153. package/dist/opening.js +53 -0
  154. package/dist/outcome.d.ts +57 -10
  155. package/dist/outcome.d.ts.map +1 -1
  156. package/dist/outcome.js +71 -2
  157. package/dist/overlay.d.ts +8 -6
  158. package/dist/overlay.d.ts.map +1 -1
  159. package/dist/overlay.js +121 -182
  160. package/dist/page-metadata.d.ts +8 -0
  161. package/dist/page-metadata.d.ts.map +1 -0
  162. package/dist/page-metadata.js +19 -0
  163. package/dist/parts.d.ts +4 -0
  164. package/dist/parts.d.ts.map +1 -0
  165. package/dist/parts.js +13 -0
  166. package/dist/paths.d.ts +2 -0
  167. package/dist/paths.d.ts.map +1 -1
  168. package/dist/paths.js +26 -0
  169. package/dist/preparation.d.ts +41 -0
  170. package/dist/preparation.d.ts.map +1 -0
  171. package/dist/preparation.js +314 -0
  172. package/dist/presence.d.ts +58 -0
  173. package/dist/presence.d.ts.map +1 -0
  174. package/dist/presence.js +231 -0
  175. package/dist/queries.d.ts +16 -0
  176. package/dist/queries.d.ts.map +1 -0
  177. package/dist/queries.js +308 -0
  178. package/dist/query.d.ts +21 -203
  179. package/dist/query.d.ts.map +1 -1
  180. package/dist/query.js +3 -491
  181. package/dist/{chat/questions.d.ts → questions.d.ts} +6 -7
  182. package/dist/questions.d.ts.map +1 -0
  183. package/dist/{chat/questions.js → questions.js} +12 -7
  184. package/dist/queue.d.ts +40 -0
  185. package/dist/queue.d.ts.map +1 -0
  186. package/dist/queue.js +480 -0
  187. package/dist/reach.d.ts +21 -11
  188. package/dist/reach.d.ts.map +1 -1
  189. package/dist/reach.js +358 -111
  190. package/dist/react.d.ts +19 -5
  191. package/dist/react.d.ts.map +1 -1
  192. package/dist/react.js +35 -15
  193. package/dist/{chat/read.d.ts → read.d.ts} +2 -0
  194. package/dist/read.d.ts.map +1 -0
  195. package/dist/{chat/read.js → read.js} +4 -0
  196. package/dist/readiness.d.ts +22 -20
  197. package/dist/readiness.d.ts.map +1 -1
  198. package/dist/readiness.js +5 -13
  199. package/dist/reads.d.ts +38 -10
  200. package/dist/reads.d.ts.map +1 -1
  201. package/dist/reads.js +163 -83
  202. package/dist/recovery.d.ts +5 -2
  203. package/dist/recovery.d.ts.map +1 -1
  204. package/dist/recovery.js +65 -8
  205. package/dist/refresh.d.ts +18 -15
  206. package/dist/refresh.d.ts.map +1 -1
  207. package/dist/refresh.js +145 -60
  208. package/dist/refusal.d.ts +5 -0
  209. package/dist/refusal.d.ts.map +1 -0
  210. package/dist/refusal.js +55 -0
  211. package/dist/replica.d.ts +49 -36
  212. package/dist/replica.d.ts.map +1 -1
  213. package/dist/replica.js +322 -198
  214. package/dist/retried.d.ts +30 -0
  215. package/dist/retried.d.ts.map +1 -0
  216. package/dist/retried.js +72 -0
  217. package/dist/room-draft.d.ts +55 -13
  218. package/dist/room-draft.d.ts.map +1 -1
  219. package/dist/room-draft.js +416 -122
  220. package/dist/room-drafts.d.ts +24 -0
  221. package/dist/room-drafts.d.ts.map +1 -0
  222. package/dist/room-drafts.js +220 -0
  223. package/dist/room-list.d.ts +10 -0
  224. package/dist/room-list.d.ts.map +1 -0
  225. package/dist/room-list.js +45 -0
  226. package/dist/rows.d.ts +32 -30
  227. package/dist/rows.d.ts.map +1 -1
  228. package/dist/rows.js +60 -120
  229. package/dist/runtime.d.ts +34 -0
  230. package/dist/runtime.d.ts.map +1 -0
  231. package/dist/runtime.js +1 -0
  232. package/dist/save.d.ts +43 -49
  233. package/dist/save.d.ts.map +1 -1
  234. package/dist/save.js +736 -304
  235. package/dist/saves.d.ts +34 -0
  236. package/dist/saves.d.ts.map +1 -0
  237. package/dist/saves.js +437 -0
  238. package/dist/search.d.ts +12 -95
  239. package/dist/search.d.ts.map +1 -1
  240. package/dist/search.js +10 -266
  241. package/dist/seed.d.ts +11 -2
  242. package/dist/seed.d.ts.map +1 -1
  243. package/dist/seed.js +71 -1
  244. package/dist/shared.d.ts +6 -7
  245. package/dist/shared.d.ts.map +1 -1
  246. package/dist/shared.js +75 -104
  247. package/dist/shown.d.ts +33 -0
  248. package/dist/shown.d.ts.map +1 -0
  249. package/dist/shown.js +309 -0
  250. package/dist/socket/admission.d.ts +7 -0
  251. package/dist/socket/admission.d.ts.map +1 -0
  252. package/dist/socket/admission.js +39 -0
  253. package/dist/socket/answers.d.ts +6 -0
  254. package/dist/socket/answers.d.ts.map +1 -0
  255. package/dist/socket/answers.js +20 -0
  256. package/dist/socket/lanes.d.ts +28 -0
  257. package/dist/socket/lanes.d.ts.map +1 -0
  258. package/dist/socket/lanes.js +103 -0
  259. package/dist/socket/reads.d.ts +10 -0
  260. package/dist/socket/reads.d.ts.map +1 -0
  261. package/dist/socket/reads.js +31 -0
  262. package/dist/socket/session.d.ts +38 -0
  263. package/dist/socket/session.d.ts.map +1 -0
  264. package/dist/socket/session.js +23 -0
  265. package/dist/socket.d.ts +67 -0
  266. package/dist/socket.d.ts.map +1 -0
  267. package/dist/socket.js +164 -0
  268. package/dist/source.d.ts +59 -0
  269. package/dist/source.d.ts.map +1 -0
  270. package/dist/source.js +93 -0
  271. package/dist/status.d.ts +4 -5
  272. package/dist/status.d.ts.map +1 -1
  273. package/dist/status.js +3 -7
  274. package/dist/store/installs.d.ts +30 -0
  275. package/dist/store/installs.d.ts.map +1 -0
  276. package/dist/store/installs.js +40 -0
  277. package/dist/store/readiness.d.ts +11 -0
  278. package/dist/store/readiness.d.ts.map +1 -0
  279. package/dist/store/readiness.js +68 -0
  280. package/dist/store/records.d.ts +223 -0
  281. package/dist/store/records.d.ts.map +1 -0
  282. package/dist/store/records.js +465 -0
  283. package/dist/store/room-held.d.ts +8 -0
  284. package/dist/store/room-held.d.ts.map +1 -0
  285. package/dist/store/room-held.js +17 -0
  286. package/dist/store/rooms-shown.d.ts +8 -0
  287. package/dist/store/rooms-shown.d.ts.map +1 -0
  288. package/dist/store/rooms-shown.js +13 -0
  289. package/dist/store/space.d.ts +11 -0
  290. package/dist/store/space.d.ts.map +1 -0
  291. package/dist/store/space.js +41 -0
  292. package/dist/store/watchers.d.ts +17 -0
  293. package/dist/store/watchers.d.ts.map +1 -0
  294. package/dist/store/watchers.js +56 -0
  295. package/dist/store/writes.d.ts +24 -0
  296. package/dist/store/writes.d.ts.map +1 -0
  297. package/dist/store/writes.js +125 -0
  298. package/dist/store.d.ts +114 -163
  299. package/dist/store.d.ts.map +1 -1
  300. package/dist/store.js +163 -754
  301. package/dist/stored.d.ts +167 -0
  302. package/dist/stored.d.ts.map +1 -0
  303. package/dist/stored.js +700 -0
  304. package/dist/surface.d.ts +90 -0
  305. package/dist/surface.d.ts.map +1 -0
  306. package/dist/surface.js +225 -0
  307. package/dist/sync.d.ts +19 -0
  308. package/dist/sync.d.ts.map +1 -0
  309. package/dist/sync.js +536 -0
  310. package/dist/tables.d.ts +376 -0
  311. package/dist/tables.d.ts.map +1 -0
  312. package/dist/tables.js +499 -0
  313. package/dist/tallies.d.ts +18 -0
  314. package/dist/tallies.d.ts.map +1 -0
  315. package/dist/tallies.js +128 -0
  316. package/dist/transfer.d.ts +0 -5
  317. package/dist/transfer.d.ts.map +1 -1
  318. package/dist/turn.d.ts +5 -3
  319. package/dist/turn.d.ts.map +1 -1
  320. package/dist/turn.js +51 -21
  321. package/dist/validation.d.ts +29 -0
  322. package/dist/validation.d.ts.map +1 -0
  323. package/dist/validation.js +98 -0
  324. package/dist/windows.d.ts +9 -16
  325. package/dist/windows.d.ts.map +1 -1
  326. package/dist/windows.js +11 -75
  327. package/dist/wire.d.ts +91 -9
  328. package/dist/wire.d.ts.map +1 -1
  329. package/dist/wire.js +31 -6
  330. package/package.json +19 -19
  331. package/AGENTS.md +0 -299
  332. package/dist/acquisition.d.ts +0 -14
  333. package/dist/acquisition.d.ts.map +0 -1
  334. package/dist/acquisition.js +0 -24
  335. package/dist/attempt.d.ts +0 -16
  336. package/dist/attempt.d.ts.map +0 -1
  337. package/dist/attempt.js +0 -70
  338. package/dist/chat/acts.d.ts +0 -33
  339. package/dist/chat/acts.d.ts.map +0 -1
  340. package/dist/chat/acts.js +0 -36
  341. package/dist/chat/context.d.ts +0 -3
  342. package/dist/chat/context.d.ts.map +0 -1
  343. package/dist/chat/earlier.d.ts +0 -10
  344. package/dist/chat/earlier.d.ts.map +0 -1
  345. package/dist/chat/earlier.js +0 -54
  346. package/dist/chat/input.d.ts +0 -9
  347. package/dist/chat/input.d.ts.map +0 -1
  348. package/dist/chat/input.js +0 -99
  349. package/dist/chat/kit.d.ts +0 -61
  350. package/dist/chat/kit.d.ts.map +0 -1
  351. package/dist/chat/kit.js +0 -123
  352. package/dist/chat/lasting.d.ts +0 -6
  353. package/dist/chat/lasting.d.ts.map +0 -1
  354. package/dist/chat/lasting.js +0 -19
  355. package/dist/chat/list.d.ts +0 -27
  356. package/dist/chat/list.d.ts.map +0 -1
  357. package/dist/chat/list.js +0 -99
  358. package/dist/chat/markdown.d.ts +0 -20
  359. package/dist/chat/markdown.d.ts.map +0 -1
  360. package/dist/chat/markdown.js +0 -188
  361. package/dist/chat/message.d.ts +0 -6
  362. package/dist/chat/message.d.ts.map +0 -1
  363. package/dist/chat/message.js +0 -192
  364. package/dist/chat/messages.d.ts +0 -22
  365. package/dist/chat/messages.d.ts.map +0 -1
  366. package/dist/chat/messages.js +0 -155
  367. package/dist/chat/name.d.ts +0 -6
  368. package/dist/chat/name.d.ts.map +0 -1
  369. package/dist/chat/name.js +0 -37
  370. package/dist/chat/opened.d.ts +0 -11
  371. package/dist/chat/opened.d.ts.map +0 -1
  372. package/dist/chat/opened.js +0 -17
  373. package/dist/chat/overlay.d.ts +0 -31
  374. package/dist/chat/overlay.d.ts.map +0 -1
  375. package/dist/chat/overlay.js +0 -97
  376. package/dist/chat/parts.d.ts +0 -57
  377. package/dist/chat/parts.d.ts.map +0 -1
  378. package/dist/chat/parts.js +0 -119
  379. package/dist/chat/process.d.ts +0 -20
  380. package/dist/chat/process.d.ts.map +0 -1
  381. package/dist/chat/process.js +0 -32
  382. package/dist/chat/provider.d.ts +0 -63
  383. package/dist/chat/provider.d.ts.map +0 -1
  384. package/dist/chat/provider.js +0 -635
  385. package/dist/chat/question.d.ts +0 -9
  386. package/dist/chat/question.d.ts.map +0 -1
  387. package/dist/chat/question.js +0 -69
  388. package/dist/chat/questions.d.ts.map +0 -1
  389. package/dist/chat/read.d.ts.map +0 -1
  390. package/dist/chat/ready.d.ts +0 -34
  391. package/dist/chat/ready.d.ts.map +0 -1
  392. package/dist/chat/ready.js +0 -91
  393. package/dist/chat/style.d.ts +0 -4
  394. package/dist/chat/style.d.ts.map +0 -1
  395. package/dist/chat/style.js +0 -302
  396. package/dist/chat.d.ts +0 -14
  397. package/dist/chat.d.ts.map +0 -1
  398. package/dist/chat.js +0 -8
  399. package/dist/fence.d.ts +0 -6
  400. package/dist/fence.d.ts.map +0 -1
  401. package/dist/fence.js +0 -10
  402. package/dist/log.d.ts +0 -5
  403. package/dist/log.d.ts.map +0 -1
  404. package/dist/log.js +0 -14
  405. package/dist/read-side.d.ts +0 -25
  406. package/dist/read-side.d.ts.map +0 -1
  407. package/dist/read-side.js +0 -761
package/dist/read-side.js DELETED
@@ -1,761 +0,0 @@
1
- import { and, BasicIndex, configureIndexDevMode, count, createCollection, createLiveQueryCollection, deepEquals, eq, inArray, or, toArray, } from '@tanstack/db';
2
- import { ARRAY_INDEX, parse, pointerSegments } from '@agentshouse/mdmodel';
3
- import { documentKey } from './rows.js';
4
- import { after, inUnits, ROW_WEIGHT } from './turn.js';
5
- import { beyond, cursorOf, MAXIMUM_WINDOW, windowed } from './windows.js';
6
- function every(expressions) {
7
- const [first, second, ...rest] = expressions;
8
- return second === undefined ? first : and(first, second, ...rest);
9
- }
10
- function same(held, value) {
11
- return Array.isArray(held) ? held.includes(value) : held === value;
12
- }
13
- function ordered(held, [operator, bound]) {
14
- if (typeof held !== typeof bound || held === null || typeof held === 'object')
15
- return false;
16
- const left = held;
17
- const right = bound;
18
- if (operator === 'gt')
19
- return left > right;
20
- if (operator === 'gte')
21
- return left >= right;
22
- if (operator === 'lt')
23
- return left < right;
24
- return left <= right;
25
- }
26
- function satisfied(test, held) {
27
- if (test.op === 'eq')
28
- return same(held, test.value);
29
- if (test.op === 'ne')
30
- return !same(held, test.value);
31
- if (test.op === 'in')
32
- return test.values.some((value) => same(held, value));
33
- if (test.op === 'nin')
34
- return !test.values.some((value) => same(held, value));
35
- if (test.op === 'range')
36
- return test.bounds.every((bound) => ordered(held, bound));
37
- if (test.op === 'all')
38
- return Array.isArray(held) && test.values.every((value) => same(held, value));
39
- return Array.isArray(held) && held.length === test.size;
40
- }
41
- function tested(test, reached) {
42
- if (test.op === 'exists')
43
- return test.exists === (reached !== undefined);
44
- if (reached === undefined)
45
- return test.op === 'ne' || test.op === 'nin';
46
- return reached.some((held) => satisfied(test, held));
47
- }
48
- function conditioned(condition, row) {
49
- if ('every' in condition)
50
- return condition.every.every((item) => conditioned(item, row));
51
- if ('some' in condition)
52
- return condition.some.some((item) => conditioned(item, row));
53
- return tested(condition.test, row.reached[condition.field]);
54
- }
55
- function narrowed(query, where, alias) {
56
- return where === null ? query : query.fn.where((row) => conditioned(where, row[alias]));
57
- }
58
- function reached(reach, room, document) {
59
- return reach === null
60
- ? []
61
- : [or(inArray(room, [...reach.rooms]), inArray(document, [...reach.documents]))];
62
- }
63
- function scoped(scope, row, rooms, reach, paths = null) {
64
- return every([
65
- eq(row.kind, 'document'),
66
- ...(rooms === null ? [] : [inArray(row.room, [...rooms])]),
67
- ...(paths === null ? [] : [inArray(row.path, [...paths])]),
68
- ...reached(reach, row.room, row.key),
69
- ...(scope.types === null ? [] : [inArray(row.type, [...scope.types])]),
70
- ...(scope.pathPrefix === null ? [] : [inArray(scope.pathPrefix, row.directories)]),
71
- ]);
72
- }
73
- function keyed(key, row) {
74
- return key.of === 'field' ? row.values[key.field] : row[key.of];
75
- }
76
- function live(query) {
77
- return createLiveQueryCollection({
78
- query: query,
79
- startSync: true,
80
- });
81
- }
82
- function related(q, rows, scope, field, kept, reach) {
83
- const matched = kept === 'source' ? 'target' : 'source';
84
- const from = q.from({ r: rows });
85
- const joined = from
86
- .where(({ r }) => every([eq(r.kind, 'reference'), ...(field === null ? [] : [inArray(field, r.forms)])]))
87
- .innerJoin({ m: rows }, ({ r, m }) => eq(r[matched], m.key))
88
- .where(({ m }) => scoped(scope, m, null, reach));
89
- return narrowed(joined, scope.where, 'm')
90
- .groupBy(({ r }) => r[kept])
91
- .select(({ r }) => ({ key: r[kept] }));
92
- }
93
- function filtered(q, rows, plan) {
94
- const from = q.from({ d: rows });
95
- let query = narrowed(from.where(({ d }) => scoped(plan.root, d, plan.rooms, plan.reach, plan.paths)), plan.root.where, 'd');
96
- if (plan.hop !== null) {
97
- const hop = related(q, rows, plan.hop, plan.hop.field, 'source', plan.reach);
98
- query = query.innerJoin({ h: hop }, ({ d, h }) => eq(d.key, h.key));
99
- }
100
- if (plan.backlinks !== null) {
101
- const backlinks = related(q, rows, plan.backlinks, plan.backlinks.field, 'target', plan.reach);
102
- query = query.innerJoin({ k: backlinks }, ({ d, k }) => eq(d.key, k.key));
103
- }
104
- return query;
105
- }
106
- function bodied(shape) {
107
- return shape.sections !== null || shape.preamble || shape.markdown;
108
- }
109
- function orderingOf(options) {
110
- const collated = options.stringSort === 'locale';
111
- return {
112
- direction: options.direction,
113
- nulls: options.nulls ?? 'first',
114
- stringSort: options.stringSort ?? 'locale',
115
- locale: collated ? options.locale : undefined,
116
- localeOptions: collated
117
- ? options.localeOptions
118
- : undefined,
119
- };
120
- }
121
- function storedValue(key, row) {
122
- return key.of === 'field' ? row.values[key.field] : row[key.of];
123
- }
124
- function documentOrder(shape) {
125
- return shape.orderBy.map(({ options }) => orderingOf(options));
126
- }
127
- function documentCursor(shape, row) {
128
- return cursorOf([
129
- ...shape.orderBy.map((_, index) => row[`order${index}`]),
130
- documentKey(row.room, row.path),
131
- ]);
132
- }
133
- function documents(q, rows, plan, shape) {
134
- let query = filtered(q, rows, plan);
135
- const cursor = plan.after?.values ?? null;
136
- if (cursor !== null) {
137
- const orderings = documentOrder(shape);
138
- query = query.fn.where(({ d }) => beyond([...shape.orderBy.map(({ key }) => storedValue(key, d)), d.key], cursor, orderings));
139
- }
140
- for (const { key, options } of shape.orderBy) {
141
- query = query.orderBy(({ d }) => keyed(key, d), options);
142
- }
143
- if (shape.orderBy.length > 0 || plan.limit !== null || plan.after !== null) {
144
- query = query.orderBy(({ d }) => d.key, { stringSort: 'lexical' });
145
- }
146
- if (plan.limit !== null)
147
- query = query.limit(plan.limit + 1);
148
- return query.select(({ d }) => ({
149
- room: d.room,
150
- path: d.path,
151
- type: d.type,
152
- binary: d.binary,
153
- ...Object.fromEntries(shape.orderBy.map(({ key }, index) => [`order${index}`, keyed(key, d)])),
154
- ...(shape.fields === null ? {} : { fields: d.fields }),
155
- ...(bodied(shape) ? { text: d.text } : {}),
156
- ...(shape.backlinks ? { backlinks: toArray(backlinked(q, rows, d, plan.reach)) } : {}),
157
- ...(shape.change ? { change: d.change } : {}),
158
- ...(shape.fileId ? { fileId: d.fileId } : {}),
159
- }));
160
- }
161
- function backlinked(q, rows, document, reach) {
162
- const from = q.from({ r: rows });
163
- return from
164
- .where(({ r }) => every([eq(r.target, document.key), ...reached(reach, r.room, r.source)]))
165
- .orderBy(({ r }) => r.path, { stringSort: 'lexical' })
166
- .orderBy(({ r }) => r.field, { stringSort: 'lexical' })
167
- .select(({ r }) => ({ path: r.path, type: r.type, field: r.field }));
168
- }
169
- function groups(q, stage, shape) {
170
- const keys = shape.groupBy.map((_, index) => `key${index}`);
171
- const from = q.from({ m: stage });
172
- let query = from.groupBy(({ m }) => keys.map((key) => m[key]));
173
- for (const { by, direction } of shape.orderBy) {
174
- query = query.orderBy(({ m }) => (by === 'count' ? count(m.key) : m[keys[by]]), direction);
175
- }
176
- return query.select(({ m }) => ({
177
- ...Object.fromEntries(keys.map((key) => [key, m[key]])),
178
- count: count(m.key),
179
- }));
180
- }
181
- function built(rows, plan) {
182
- const shape = plan.shape;
183
- if (shape.kind === 'documents') {
184
- const collection = live((q) => documents(q, rows, plan, shape));
185
- const count = plan.total
186
- ? live((q) => filtered(q, rows, plan).select(({ d }) => ({ key: d.key })))
187
- : null;
188
- return {
189
- live: collection,
190
- count,
191
- dispose: () => {
192
- void collection.cleanup();
193
- if (count !== null)
194
- void count.cleanup();
195
- },
196
- };
197
- }
198
- const stage = live((q) => filtered(q, rows, plan).select(({ d }) => ({
199
- key: d.key,
200
- ...Object.fromEntries(shape.groupBy.map((key, index) => [`key${index}`, keyed(key, d)])),
201
- })));
202
- const collection = live((q) => groups(q, stage, shape));
203
- return {
204
- live: collection,
205
- count: null,
206
- dispose: () => {
207
- void collection.cleanup();
208
- void stage.cleanup();
209
- },
210
- };
211
- }
212
- function sectionsOf(sections, names) {
213
- if (names === 'all')
214
- return sections;
215
- return Object.fromEntries(names.flatMap((name) => (Object.hasOwn(sections, name) ? [[name, sections[name]]] : [])));
216
- }
217
- function bodyOf(row, key, bodies) {
218
- const text = row.text;
219
- if (text === null)
220
- return null;
221
- const held = bodies?.get(key);
222
- if (held !== undefined && held.text === text)
223
- return held.document;
224
- const read = parse(text, row.path);
225
- const document = read.ok ? read.document : null;
226
- bodies?.set(key, { text, document });
227
- return document;
228
- }
229
- function masked(pointers) {
230
- const root = { whole: false, members: new Map() };
231
- for (const pointer of pointers) {
232
- let mask = root;
233
- for (const token of pointerSegments(pointer)) {
234
- const next = mask.members.get(token) ?? { whole: false, members: new Map() };
235
- mask.members.set(token, next);
236
- mask = next;
237
- }
238
- mask.whole = true;
239
- }
240
- return root;
241
- }
242
- function merged(left, right) {
243
- if (left === undefined)
244
- return right;
245
- const members = new Map(left.members);
246
- for (const [token, mask] of right.members)
247
- members.set(token, merged(members.get(token), mask));
248
- return { whole: left.whole || right.whole, members };
249
- }
250
- function cut(value, mask) {
251
- if (mask.whole)
252
- return value;
253
- if (Array.isArray(value)) {
254
- const each = {
255
- whole: false,
256
- members: new Map([...mask.members].filter(([token]) => !ARRAY_INDEX.test(token))),
257
- };
258
- const kept = [];
259
- value.forEach((item, index) => {
260
- const part = cut(item, merged(mask.members.get(String(index)), each));
261
- if (part !== undefined)
262
- kept[index] = part;
263
- });
264
- return kept.length === 0 ? undefined : kept;
265
- }
266
- if (typeof value !== 'object' || value === null)
267
- return undefined;
268
- const kept = Object.entries(value).flatMap(([key, held]) => {
269
- const member = mask.members.get(key);
270
- const part = member === undefined ? undefined : cut(held, member);
271
- return part === undefined ? [] : [[key, part]];
272
- });
273
- return kept.length === 0 ? undefined : Object.fromEntries(kept);
274
- }
275
- function selected(fields, pointers) {
276
- return (cut(fields, masked(pointers)) ?? {});
277
- }
278
- function documentOf(key, row, shape, bodies) {
279
- if (row.type === null) {
280
- const binary = row.binary;
281
- return {
282
- room: row.room,
283
- path: row.path,
284
- ...(binary === null ? {} : { binaryFile: binary }),
285
- ...(shape.fileId ? { fileId: row.fileId } : {}),
286
- };
287
- }
288
- const body = bodied(shape) ? bodyOf(row, key, bodies) : null;
289
- return {
290
- room: row.room,
291
- path: row.path,
292
- type: row.type,
293
- ...(shape.fields === null
294
- ? {}
295
- : {
296
- fields: shape.fields === 'all'
297
- ? row.fields
298
- : selected(row.fields, shape.fields),
299
- }),
300
- ...(shape.sections === null || body === null
301
- ? {}
302
- : { sections: sectionsOf(body.sections, shape.sections) }),
303
- ...(shape.preamble && body !== null ? { preamble: body.preamble } : {}),
304
- ...(shape.markdown && body !== null ? { markdown: body.content } : {}),
305
- ...(shape.backlinks
306
- ? {
307
- backlinks: row.backlinks
308
- .slice(0, MAXIMUM_WINDOW)
309
- .map(({ path, type, field }) => ({ path, type, field })),
310
- }
311
- : {}),
312
- ...(shape.change ? { change: row.change } : {}),
313
- ...(shape.fileId ? { fileId: row.fileId } : {}),
314
- };
315
- }
316
- function weight(row) {
317
- return ROW_WEIGHT + (typeof row?.text === 'string' ? row.text.length : 0);
318
- }
319
- function groupValues(shape, [key, row]) {
320
- return [...shape.orderBy.map(({ by }) => (by === 'count' ? row.count : row[`key${by}`])), key];
321
- }
322
- function groupOrder(shape) {
323
- return shape.orderBy.map(({ direction }) => ({
324
- direction,
325
- nulls: 'first',
326
- stringSort: 'locale',
327
- locale: undefined,
328
- localeOptions: undefined,
329
- }));
330
- }
331
- function windowOf(plan, entries, total) {
332
- const shape = plan.shape;
333
- if (shape.kind === 'documents') {
334
- return {
335
- ...windowed(entries, plan.limit, plan.after?.text, ([, row]) => documentCursor(shape, row)),
336
- total,
337
- };
338
- }
339
- const cursor = plan.after?.values ?? null;
340
- const orderings = groupOrder(shape);
341
- const following = cursor === null
342
- ? entries
343
- : entries.filter((entry) => beyond(groupValues(shape, entry), cursor, orderings));
344
- return {
345
- ...windowed(following, plan.limit, plan.after?.text, (entry) => cursorOf(groupValues(shape, entry))),
346
- total: plan.total ? entries.length : undefined,
347
- };
348
- }
349
- function framed(rows, { next, total }) {
350
- return {
351
- ...rows,
352
- ...(next === undefined ? {} : { next }),
353
- ...(total === undefined ? {} : { total }),
354
- };
355
- }
356
- function rowsOfPlan(plan, entries, total, bodies, each = (row) => row) {
357
- const shape = plan.shape;
358
- const { kept, ...window } = windowOf(plan, entries, total);
359
- const keys = kept.map(([key]) => key);
360
- if (shape.kind === 'documents') {
361
- const documents = [];
362
- return after(inUnits(kept, ([key, row]) => {
363
- documents.push(each(documentOf(key, row, shape, bodies)));
364
- return weight(row);
365
- }), () => ({ rows: framed({ documents }, window), keys, ...window }));
366
- }
367
- const groups = [];
368
- return after(inUnits(kept, ([, row]) => {
369
- groups.push(each({
370
- key: shape.groupBy.map((_, index) => row[`key${index}`]),
371
- count: row.count,
372
- }));
373
- return ROW_WEIGHT;
374
- }), () => ({ rows: framed({ groups }, window), keys, ...window }));
375
- }
376
- export function reconciled(previous, next) {
377
- const before = previous.result;
378
- const after = next.result;
379
- if ('pending' in before || 'pending' in after) {
380
- if (deepEquals(before, after))
381
- return null;
382
- return { keyed: next, message: next };
383
- }
384
- const earlier = 'groups' in before ? before.groups : before.documents;
385
- const held = new Map(previous.keys.map((key, index) => [key, earlier[index]]));
386
- const changed = [];
387
- const rows = ('groups' in after ? after.groups : after.documents).map((row, index) => {
388
- const key = next.keys[index];
389
- const kept = held.get(key);
390
- if (kept !== undefined && deepEquals(kept, row))
391
- return kept;
392
- changed.push([key, row]);
393
- return row;
394
- });
395
- const present = new Set(next.keys);
396
- const removed = previous.keys.filter((key) => !present.has(key));
397
- const moved = reordered(previous.keys, next.keys, present);
398
- const covered = !deepEquals(before.coverage, after.coverage);
399
- const framing = reframed(before, after);
400
- if (changed.length === 0 && removed.length === 0 && !moved && !covered && framing === null) {
401
- return null;
402
- }
403
- const window = { next: after.next, total: after.total };
404
- return {
405
- keyed: {
406
- result: 'groups' in after
407
- ? framed({ groups: rows, coverage: after.coverage }, window)
408
- : framed({ documents: rows, coverage: after.coverage }, window),
409
- keys: next.keys,
410
- },
411
- message: {
412
- changed,
413
- removed,
414
- order: moved ? next.keys : null,
415
- ...(covered ? { coverage: after.coverage } : {}),
416
- ...framing,
417
- },
418
- };
419
- }
420
- function reframed(before, after) {
421
- const next = before.next === after.next ? {} : { next: after.next ?? null };
422
- const total = before.total === after.total || after.total === undefined ? {} : { total: after.total };
423
- return Object.keys(next).length === 0 && Object.keys(total).length === 0
424
- ? null
425
- : { ...next, ...total };
426
- }
427
- function reordered(previous, next, present) {
428
- let at = 0;
429
- for (const key of previous) {
430
- if (!present.has(key))
431
- continue;
432
- if (next[at] !== key)
433
- return true;
434
- at += 1;
435
- }
436
- return at !== next.length;
437
- }
438
- export function createReadSide() {
439
- configureIndexDevMode({ enabled: false });
440
- let sync;
441
- const rows = createCollection({
442
- getKey: (row) => row.key,
443
- gcTime: 0,
444
- startSync: true,
445
- autoIndex: 'eager',
446
- defaultIndexType: BasicIndex,
447
- sync: {
448
- rowUpdateMode: 'full',
449
- sync: (params) => {
450
- sync = params;
451
- params.markReady();
452
- },
453
- },
454
- });
455
- const shared = new Map();
456
- function searched(row) {
457
- const read = row.text === null ? null : parse(row.text, row.path);
458
- if (read === null || !read.ok)
459
- return null;
460
- return {
461
- room: row.room,
462
- path: row.path,
463
- type: row.type,
464
- fields: row.fields,
465
- preamble: read.document.preamble,
466
- sections: read.document.sections,
467
- };
468
- }
469
- function kept(entry, key, row) {
470
- const held = entry.rows.get(key);
471
- if (held !== undefined && deepEquals(held, row))
472
- return;
473
- entry.rows.set(key, row);
474
- }
475
- function counted(entry) {
476
- return entry.built.count === null ? undefined : entry.built.count.size;
477
- }
478
- function rebuilt(entry) {
479
- return after(rowsOfPlan(entry.plan, [...entry.built.live.entries()], counted(entry), entry.bodies), ({ rows: found, keys, next, total }) => {
480
- const present = new Set(keys);
481
- for (const key of [...entry.rows.keys()])
482
- if (!present.has(key))
483
- entry.rows.delete(key);
484
- for (const key of [...entry.bodies.keys()]) {
485
- if (!present.has(key))
486
- entry.bodies.delete(key);
487
- }
488
- keys.forEach((key, index) => kept(entry, key, rowAt(found, index)));
489
- return { keys, next, total };
490
- });
491
- }
492
- function refreshed(entry, dirty) {
493
- const shape = entry.plan.shape;
494
- const { kept: inWindow, next, total, } = windowOf(entry.plan, [...entry.built.live.entries()], counted(entry));
495
- const keys = inWindow.map(([key]) => key);
496
- const present = new Set(keys);
497
- for (const key of [...entry.rows.keys()]) {
498
- if (present.has(key))
499
- continue;
500
- entry.rows.delete(key);
501
- entry.bodies.delete(key);
502
- }
503
- const values = inWindow.filter(([key]) => dirty.has(key) || !entry.rows.has(key));
504
- const done = inUnits(values, ([key, value]) => {
505
- kept(entry, key, documentOf(key, value, shape, entry.bodies));
506
- return weight(value);
507
- });
508
- return after(done, () => ({ keys, next, total }));
509
- }
510
- function current(entry, found, coverage) {
511
- const rows = found.keys.map((key) => entry.rows.get(key));
512
- return {
513
- result: entry.plan.shape.kind === 'groups'
514
- ? framed({ groups: rows, coverage }, found)
515
- : framed({ documents: rows, coverage }, found),
516
- keys: found.keys,
517
- };
518
- }
519
- function delivered(entry, next) {
520
- const previous = entry.result;
521
- entry.result = next;
522
- const message = previous === undefined ? null : changedFrom(previous, next);
523
- if (message !== null)
524
- for (const listener of entry.ready)
525
- listener(message);
526
- for (const listener of entry.fresh) {
527
- entry.ready.add(listener);
528
- listener(next);
529
- }
530
- entry.fresh.clear();
531
- }
532
- function run(entry) {
533
- while (entry.listeners.size > 0 &&
534
- (entry.whole || entry.dirty.size > 0 || entry.stale || entry.fresh.size > 0)) {
535
- entry.stale = false;
536
- const cover = entry.cover();
537
- if ('pending' in cover) {
538
- entry.whole = true;
539
- entry.dirty.clear();
540
- entry.rows.clear();
541
- entry.bodies.clear();
542
- delivered(entry, { result: cover, keys: [] });
543
- break;
544
- }
545
- const whole = entry.whole ||
546
- entry.plan.shape.kind === 'groups' ||
547
- entry.result === undefined ||
548
- 'pending' in entry.result.result;
549
- const dirty = entry.dirty;
550
- entry.dirty = new Set();
551
- entry.whole = false;
552
- const found = whole ? rebuilt(entry) : refreshed(entry, dirty);
553
- if (found instanceof Promise) {
554
- void found
555
- .then((window) => {
556
- if (entry.listeners.size > 0)
557
- delivered(entry, current(entry, window, cover.coverage));
558
- run(entry);
559
- })
560
- .catch(() => {
561
- entry.running = false;
562
- });
563
- return;
564
- }
565
- delivered(entry, current(entry, found, cover.coverage));
566
- }
567
- entry.running = false;
568
- }
569
- function wake(entry) {
570
- if (entry.subscription === null || entry.running)
571
- return;
572
- entry.running = true;
573
- try {
574
- run(entry);
575
- }
576
- catch (error) {
577
- entry.running = false;
578
- throw error;
579
- }
580
- }
581
- function recover() {
582
- for (const entry of shared.values()) {
583
- if (entry.result === undefined || entry.subscription === null)
584
- continue;
585
- const cover = entry.cover();
586
- const before = entry.result.result;
587
- const held = 'pending' in cover
588
- ? deepEquals(before, cover)
589
- : 'coverage' in before && deepEquals(before.coverage, cover.coverage);
590
- if (held)
591
- continue;
592
- entry.stale = true;
593
- wake(entry);
594
- }
595
- }
596
- return {
597
- apply(set) {
598
- const next = new Map();
599
- for (const change of set.documents) {
600
- for (const row of change.before)
601
- next.set(row.key, null);
602
- for (const row of change.after)
603
- next.set(row.key, row);
604
- }
605
- if (next.size > 0) {
606
- sync.begin();
607
- for (const [key, row] of next) {
608
- if (row === null) {
609
- if (rows.has(key))
610
- sync.write({ type: 'delete', key });
611
- continue;
612
- }
613
- sync.write({ type: rows.has(key) ? 'update' : 'insert', value: row });
614
- }
615
- sync.commit();
616
- }
617
- recover();
618
- },
619
- recover,
620
- async query(plan, at) {
621
- const { live: collection, count, dispose } = built(rows, plan);
622
- try {
623
- await collection.toArrayWhenReady();
624
- if (count !== null)
625
- await count.toArrayWhenReady();
626
- const entries = [...collection.entries()];
627
- const held = at();
628
- const found = await rowsOfPlan(plan, entries, count?.size, null, structuredClone);
629
- return { rows: found.rows, at: held };
630
- }
631
- finally {
632
- dispose();
633
- }
634
- },
635
- watch(plan, identity, cover, deliverTo) {
636
- let entry = shared.get(identity);
637
- if (entry === undefined) {
638
- const created = {
639
- plan,
640
- built: built(rows, plan),
641
- cover,
642
- result: undefined,
643
- rows: new Map(),
644
- bodies: new Map(),
645
- listeners: new Set(),
646
- fresh: new Set(),
647
- ready: new Set(),
648
- subscription: null,
649
- counting: null,
650
- whole: true,
651
- dirty: new Set(),
652
- stale: false,
653
- running: false,
654
- };
655
- created.built.live.on('status:change', ({ status }) => {
656
- if (status === 'cleaned-up' && created.listeners.size === 0)
657
- shared.delete(identity);
658
- });
659
- shared.set(identity, created);
660
- entry = created;
661
- }
662
- const observed = entry;
663
- observed.listeners.add(deliverTo);
664
- const ready = (then) => observed.built.live.onFirstReady(() => observed.built.count === null ? then() : observed.built.count.onFirstReady(then));
665
- const settled = () => {
666
- if (observed.built.count === null)
667
- wake(observed);
668
- else
669
- queueMicrotask(() => wake(observed));
670
- };
671
- ready(() => {
672
- if (!observed.listeners.has(deliverTo))
673
- return;
674
- observed.fresh.add(deliverTo);
675
- if (observed.subscription === null) {
676
- observed.whole = true;
677
- observed.subscription = observed.built.live.subscribeChanges((changes) => {
678
- if (observed.plan.shape.kind === 'groups')
679
- observed.whole = true;
680
- else
681
- for (const { key } of changes)
682
- observed.dirty.add(key);
683
- settled();
684
- }, { includeInitialState: false });
685
- observed.counting =
686
- observed.built.count?.subscribeChanges(() => {
687
- observed.stale = true;
688
- settled();
689
- }, { includeInitialState: false }) ?? null;
690
- }
691
- wake(observed);
692
- });
693
- return () => {
694
- observed.fresh.delete(deliverTo);
695
- observed.ready.delete(deliverTo);
696
- if (!observed.listeners.delete(deliverTo) || observed.listeners.size > 0)
697
- return;
698
- observed.subscription?.unsubscribe();
699
- observed.subscription = null;
700
- observed.counting?.unsubscribe();
701
- observed.counting = null;
702
- observed.result = undefined;
703
- observed.rows.clear();
704
- observed.bodies.clear();
705
- observed.dirty.clear();
706
- observed.whole = true;
707
- };
708
- },
709
- room(room) {
710
- return rows.toArray.flatMap((row) => row.kind !== 'document' || row.type === null || row.room !== room ? [] : [row.path]);
711
- },
712
- document(room, path) {
713
- const row = rows.get(documentKey(room, path));
714
- return row === undefined || row.type === null ? null : searched(row);
715
- },
716
- close() {
717
- for (const entry of shared.values()) {
718
- entry.listeners.clear();
719
- entry.fresh.clear();
720
- entry.ready.clear();
721
- entry.subscription?.unsubscribe();
722
- entry.counting?.unsubscribe();
723
- entry.built.dispose();
724
- }
725
- shared.clear();
726
- void rows.cleanup();
727
- },
728
- };
729
- }
730
- function changedFrom(previous, next) {
731
- const before = previous.result;
732
- const after = next.result;
733
- if ('pending' in before || 'pending' in after)
734
- return deepEquals(before, after) ? null : next;
735
- const earlier = 'groups' in before ? before.groups : before.documents;
736
- const held = new Map(previous.keys.map((key, index) => [key, earlier[index]]));
737
- const later = 'groups' in after ? after.groups : after.documents;
738
- const changed = [];
739
- next.keys.forEach((key, index) => {
740
- if (held.get(key) !== later[index])
741
- changed.push([key, later[index]]);
742
- });
743
- const present = new Set(next.keys);
744
- const removed = previous.keys.filter((key) => !present.has(key));
745
- const moved = reordered(previous.keys, next.keys, present);
746
- const covered = !deepEquals(before.coverage, after.coverage);
747
- const framing = reframed(before, after);
748
- if (changed.length === 0 && removed.length === 0 && !moved && !covered && framing === null) {
749
- return null;
750
- }
751
- return {
752
- changed,
753
- removed,
754
- order: moved ? next.keys : null,
755
- ...(covered ? { coverage: after.coverage } : {}),
756
- ...framing,
757
- };
758
- }
759
- function rowAt(rows, index) {
760
- return 'groups' in rows ? rows.groups[index] : rows.documents[index];
761
- }