@agentshouse/mdruntime 0.1.0-cee9c8aa4cd86 → 0.1.0-cef76ea952695

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 (376) hide show
  1. package/README.md +19 -17
  2. package/dist/acceptance.d.ts +6 -0
  3. package/dist/acceptance.d.ts.map +1 -0
  4. package/dist/acceptance.js +385 -0
  5. package/dist/actions.d.ts +20 -0
  6. package/dist/actions.d.ts.map +1 -0
  7. package/dist/actions.js +251 -0
  8. package/dist/adapter.d.ts +111 -109
  9. package/dist/adapter.d.ts.map +1 -1
  10. package/dist/attached-model.d.ts +5 -11
  11. package/dist/attached-model.d.ts.map +1 -1
  12. package/dist/attached-model.js +36 -47
  13. package/dist/binary.d.ts +0 -5
  14. package/dist/binary.d.ts.map +1 -1
  15. package/dist/binary.js +1 -1
  16. package/dist/bootstrap.d.ts +22 -10
  17. package/dist/bootstrap.d.ts.map +1 -1
  18. package/dist/bootstrap.js +303 -123
  19. package/dist/cell.d.ts +6 -0
  20. package/dist/cell.d.ts.map +1 -0
  21. package/dist/cell.js +9 -0
  22. package/dist/chain.d.ts +2 -1
  23. package/dist/chain.d.ts.map +1 -1
  24. package/dist/change.d.ts +1 -0
  25. package/dist/change.d.ts.map +1 -1
  26. package/dist/change.js +4 -2
  27. package/dist/chat-types.d.ts +5 -0
  28. package/dist/chat-types.d.ts.map +1 -0
  29. package/dist/chat-types.js +13 -0
  30. package/dist/client.d.ts +30 -14
  31. package/dist/client.d.ts.map +1 -1
  32. package/dist/client.js +61 -10
  33. package/dist/collection.d.ts +7 -4
  34. package/dist/collection.d.ts.map +1 -1
  35. package/dist/collection.js +24 -19
  36. package/dist/compile.d.ts +6 -6
  37. package/dist/compile.d.ts.map +1 -1
  38. package/dist/compile.js +290 -297
  39. package/dist/connection.d.ts +6 -142
  40. package/dist/connection.d.ts.map +1 -1
  41. package/dist/connection.js +105 -4827
  42. package/dist/context.d.ts +2 -0
  43. package/dist/context.d.ts.map +1 -0
  44. package/dist/{chat/context.js → context.js} +1 -4
  45. package/dist/conversation-live.d.ts +135 -0
  46. package/dist/conversation-live.d.ts.map +1 -0
  47. package/dist/conversation-live.js +247 -0
  48. package/dist/conversation-row.d.ts +33 -0
  49. package/dist/conversation-row.d.ts.map +1 -0
  50. package/dist/conversation-row.js +53 -0
  51. package/dist/conversation.d.ts +42 -46
  52. package/dist/conversation.d.ts.map +1 -1
  53. package/dist/conversation.js +901 -815
  54. package/dist/discovery.d.ts +10 -0
  55. package/dist/discovery.d.ts.map +1 -0
  56. package/dist/discovery.js +175 -0
  57. package/dist/durability.d.ts +15 -4
  58. package/dist/durability.d.ts.map +1 -1
  59. package/dist/durability.js +5 -0
  60. package/dist/entry.d.ts +3 -2
  61. package/dist/entry.d.ts.map +1 -1
  62. package/dist/entry.js +18 -8
  63. package/dist/expectation.d.ts +4 -2
  64. package/dist/expectation.d.ts.map +1 -1
  65. package/dist/expectation.js +33 -11
  66. package/dist/failure.d.ts +1 -0
  67. package/dist/failure.d.ts.map +1 -1
  68. package/dist/failure.js +3 -0
  69. package/dist/figures.d.ts +49 -0
  70. package/dist/figures.d.ts.map +1 -0
  71. package/dist/figures.js +197 -0
  72. package/dist/file.d.ts +2 -11
  73. package/dist/file.d.ts.map +1 -1
  74. package/dist/file.js +6 -4
  75. package/dist/holdings.d.ts +29 -0
  76. package/dist/holdings.d.ts.map +1 -0
  77. package/dist/holdings.js +95 -0
  78. package/dist/host.d.ts +4 -6
  79. package/dist/host.d.ts.map +1 -1
  80. package/dist/host.js +59 -38
  81. package/dist/identity.d.ts +0 -1
  82. package/dist/identity.d.ts.map +1 -1
  83. package/dist/identity.js +0 -3
  84. package/dist/index.d.ts +30 -13
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js +10 -3
  87. package/dist/install.d.ts +56 -0
  88. package/dist/install.d.ts.map +1 -0
  89. package/dist/install.js +556 -0
  90. package/dist/job.d.ts +5 -0
  91. package/dist/job.d.ts.map +1 -0
  92. package/dist/job.js +7 -0
  93. package/dist/lifecycle.d.ts +7 -0
  94. package/dist/lifecycle.d.ts.map +1 -0
  95. package/dist/lifecycle.js +270 -0
  96. package/dist/listing.d.ts +53 -0
  97. package/dist/listing.d.ts.map +1 -0
  98. package/dist/listing.js +176 -0
  99. package/dist/live.d.ts +5 -4
  100. package/dist/live.d.ts.map +1 -1
  101. package/dist/live.js +63 -21
  102. package/dist/locks.d.ts +9 -0
  103. package/dist/locks.d.ts.map +1 -0
  104. package/dist/locks.js +62 -0
  105. package/dist/log.d.ts +1 -0
  106. package/dist/log.d.ts.map +1 -1
  107. package/dist/lost.d.ts +5 -0
  108. package/dist/lost.d.ts.map +1 -0
  109. package/dist/lost.js +61 -0
  110. package/dist/media.d.ts +8 -0
  111. package/dist/media.d.ts.map +1 -0
  112. package/dist/media.js +218 -0
  113. package/dist/memory.d.ts +13 -6
  114. package/dist/memory.d.ts.map +1 -1
  115. package/dist/memory.js +219 -102
  116. package/dist/messages.d.ts +24 -3
  117. package/dist/messages.d.ts.map +1 -1
  118. package/dist/messages.js +89 -31
  119. package/dist/model.d.ts +8 -10
  120. package/dist/model.d.ts.map +1 -1
  121. package/dist/model.js +6 -18
  122. package/dist/models.d.ts +14 -0
  123. package/dist/models.d.ts.map +1 -0
  124. package/dist/models.js +197 -0
  125. package/dist/observation.d.ts +3 -2
  126. package/dist/observation.d.ts.map +1 -1
  127. package/dist/observation.js +15 -15
  128. package/dist/opened.js +3 -3
  129. package/dist/opening.d.ts +4 -0
  130. package/dist/opening.d.ts.map +1 -0
  131. package/dist/opening.js +60 -0
  132. package/dist/outcome.d.ts +17 -7
  133. package/dist/outcome.d.ts.map +1 -1
  134. package/dist/outcome.js +19 -5
  135. package/dist/overlay.d.ts +1 -0
  136. package/dist/overlay.d.ts.map +1 -1
  137. package/dist/overlay.js +12 -1
  138. package/dist/parts.d.ts +11 -0
  139. package/dist/parts.d.ts.map +1 -0
  140. package/dist/parts.js +21 -0
  141. package/dist/paths.d.ts +2 -0
  142. package/dist/paths.d.ts.map +1 -1
  143. package/dist/paths.js +26 -0
  144. package/dist/preparation.d.ts +20 -0
  145. package/dist/preparation.d.ts.map +1 -0
  146. package/dist/preparation.js +233 -0
  147. package/dist/queries.d.ts +16 -0
  148. package/dist/queries.d.ts.map +1 -0
  149. package/dist/queries.js +272 -0
  150. package/dist/query.d.ts +19 -206
  151. package/dist/query.d.ts.map +1 -1
  152. package/dist/query.js +3 -494
  153. package/dist/{chat/questions.d.ts → questions.d.ts} +5 -2
  154. package/dist/questions.d.ts.map +1 -0
  155. package/dist/{chat/questions.js → questions.js} +13 -2
  156. package/dist/reach.d.ts +20 -13
  157. package/dist/reach.d.ts.map +1 -1
  158. package/dist/reach.js +204 -135
  159. package/dist/react.d.ts +14 -2
  160. package/dist/react.d.ts.map +1 -1
  161. package/dist/react.js +10 -1
  162. package/dist/{chat/read.d.ts → read.d.ts} +2 -0
  163. package/dist/read.d.ts.map +1 -0
  164. package/dist/{chat/read.js → read.js} +4 -0
  165. package/dist/readiness.d.ts +12 -16
  166. package/dist/readiness.d.ts.map +1 -1
  167. package/dist/readiness.js +2 -8
  168. package/dist/reads.d.ts +36 -10
  169. package/dist/reads.d.ts.map +1 -1
  170. package/dist/reads.js +159 -83
  171. package/dist/recovery.d.ts +1 -0
  172. package/dist/recovery.d.ts.map +1 -1
  173. package/dist/recovery.js +35 -1
  174. package/dist/refresh.d.ts +10 -4
  175. package/dist/refresh.d.ts.map +1 -1
  176. package/dist/refresh.js +92 -30
  177. package/dist/refusal.d.ts +5 -0
  178. package/dist/refusal.d.ts.map +1 -0
  179. package/dist/refusal.js +57 -0
  180. package/dist/replica.d.ts +11 -10
  181. package/dist/replica.d.ts.map +1 -1
  182. package/dist/replica.js +56 -23
  183. package/dist/room-draft.d.ts +22 -7
  184. package/dist/room-draft.d.ts.map +1 -1
  185. package/dist/room-draft.js +134 -54
  186. package/dist/room-drafts.d.ts +24 -0
  187. package/dist/room-drafts.d.ts.map +1 -0
  188. package/dist/room-drafts.js +217 -0
  189. package/dist/rows.d.ts +18 -16
  190. package/dist/rows.d.ts.map +1 -1
  191. package/dist/rows.js +45 -153
  192. package/dist/runtime.d.ts +43 -0
  193. package/dist/runtime.d.ts.map +1 -0
  194. package/dist/runtime.js +1 -0
  195. package/dist/save.d.ts +7 -1
  196. package/dist/save.d.ts.map +1 -1
  197. package/dist/save.js +46 -27
  198. package/dist/saves.d.ts +70 -0
  199. package/dist/saves.d.ts.map +1 -0
  200. package/dist/saves.js +1005 -0
  201. package/dist/search.d.ts +12 -63
  202. package/dist/search.d.ts.map +1 -1
  203. package/dist/search.js +9 -52
  204. package/dist/seed.d.ts +11 -2
  205. package/dist/seed.d.ts.map +1 -1
  206. package/dist/seed.js +71 -1
  207. package/dist/shared.d.ts +1 -7
  208. package/dist/shared.d.ts.map +1 -1
  209. package/dist/shared.js +13 -105
  210. package/dist/shown.d.ts +31 -0
  211. package/dist/shown.d.ts.map +1 -0
  212. package/dist/shown.js +290 -0
  213. package/dist/socket/admission.d.ts +7 -0
  214. package/dist/socket/admission.d.ts.map +1 -0
  215. package/dist/socket/admission.js +39 -0
  216. package/dist/socket/answers.d.ts +6 -0
  217. package/dist/socket/answers.d.ts.map +1 -0
  218. package/dist/socket/answers.js +20 -0
  219. package/dist/socket/lanes.d.ts +20 -0
  220. package/dist/socket/lanes.d.ts.map +1 -0
  221. package/dist/socket/lanes.js +77 -0
  222. package/dist/socket/reads.d.ts +10 -0
  223. package/dist/socket/reads.d.ts.map +1 -0
  224. package/dist/socket/reads.js +31 -0
  225. package/dist/socket/rooms.d.ts +44 -0
  226. package/dist/socket/rooms.d.ts.map +1 -0
  227. package/dist/socket/rooms.js +90 -0
  228. package/dist/socket/session.d.ts +38 -0
  229. package/dist/socket/session.d.ts.map +1 -0
  230. package/dist/socket/session.js +23 -0
  231. package/dist/socket.d.ts +70 -0
  232. package/dist/socket.d.ts.map +1 -0
  233. package/dist/socket.js +175 -0
  234. package/dist/source.d.ts +61 -0
  235. package/dist/source.d.ts.map +1 -0
  236. package/dist/source.js +82 -0
  237. package/dist/status.d.ts +4 -5
  238. package/dist/status.d.ts.map +1 -1
  239. package/dist/status.js +3 -7
  240. package/dist/store/fences.d.ts +16 -0
  241. package/dist/store/fences.d.ts.map +1 -0
  242. package/dist/store/fences.js +26 -0
  243. package/dist/store/installs.d.ts +30 -0
  244. package/dist/store/installs.d.ts.map +1 -0
  245. package/dist/store/installs.js +34 -0
  246. package/dist/store/readiness.d.ts +10 -0
  247. package/dist/store/readiness.d.ts.map +1 -0
  248. package/dist/store/readiness.js +52 -0
  249. package/dist/store/records.d.ts +210 -0
  250. package/dist/store/records.d.ts.map +1 -0
  251. package/dist/store/records.js +428 -0
  252. package/dist/store/room-held.d.ts +8 -0
  253. package/dist/store/room-held.d.ts.map +1 -0
  254. package/dist/store/room-held.js +17 -0
  255. package/dist/store/space.d.ts +11 -0
  256. package/dist/store/space.d.ts.map +1 -0
  257. package/dist/store/space.js +41 -0
  258. package/dist/store/watchers.d.ts +17 -0
  259. package/dist/store/watchers.d.ts.map +1 -0
  260. package/dist/store/watchers.js +56 -0
  261. package/dist/store/writes.d.ts +24 -0
  262. package/dist/store/writes.d.ts.map +1 -0
  263. package/dist/store/writes.js +125 -0
  264. package/dist/store.d.ts +105 -149
  265. package/dist/store.d.ts.map +1 -1
  266. package/dist/store.js +143 -390
  267. package/dist/stored.d.ts +67 -49
  268. package/dist/stored.d.ts.map +1 -1
  269. package/dist/stored.js +358 -253
  270. package/dist/surface.d.ts +88 -0
  271. package/dist/surface.d.ts.map +1 -0
  272. package/dist/surface.js +224 -0
  273. package/dist/sync.d.ts +19 -0
  274. package/dist/sync.d.ts.map +1 -0
  275. package/dist/sync.js +532 -0
  276. package/dist/tables.d.ts +140 -60
  277. package/dist/tables.d.ts.map +1 -1
  278. package/dist/tables.js +268 -101
  279. package/dist/tallies.d.ts +18 -0
  280. package/dist/tallies.d.ts.map +1 -0
  281. package/dist/tallies.js +129 -0
  282. package/dist/transfer.d.ts +0 -5
  283. package/dist/transfer.d.ts.map +1 -1
  284. package/dist/validation.d.ts +3 -4
  285. package/dist/validation.d.ts.map +1 -1
  286. package/dist/validation.js +42 -100
  287. package/dist/windows.d.ts +1 -12
  288. package/dist/windows.d.ts.map +1 -1
  289. package/dist/windows.js +2 -75
  290. package/dist/wire.d.ts +22 -10
  291. package/dist/wire.d.ts.map +1 -1
  292. package/dist/wire.js +9 -3
  293. package/package.json +12 -18
  294. package/AGENTS.md +0 -320
  295. package/dist/chat/acts.d.ts +0 -33
  296. package/dist/chat/acts.d.ts.map +0 -1
  297. package/dist/chat/acts.js +0 -36
  298. package/dist/chat/context.d.ts +0 -3
  299. package/dist/chat/context.d.ts.map +0 -1
  300. package/dist/chat/earlier.d.ts +0 -10
  301. package/dist/chat/earlier.d.ts.map +0 -1
  302. package/dist/chat/earlier.js +0 -54
  303. package/dist/chat/house.d.ts +0 -25
  304. package/dist/chat/house.d.ts.map +0 -1
  305. package/dist/chat/house.js +0 -38
  306. package/dist/chat/input.d.ts +0 -11
  307. package/dist/chat/input.d.ts.map +0 -1
  308. package/dist/chat/input.js +0 -92
  309. package/dist/chat/kit.d.ts +0 -61
  310. package/dist/chat/kit.d.ts.map +0 -1
  311. package/dist/chat/kit.js +0 -123
  312. package/dist/chat/lasting.d.ts +0 -6
  313. package/dist/chat/lasting.d.ts.map +0 -1
  314. package/dist/chat/lasting.js +0 -19
  315. package/dist/chat/list.d.ts +0 -28
  316. package/dist/chat/list.d.ts.map +0 -1
  317. package/dist/chat/list.js +0 -103
  318. package/dist/chat/markdown.d.ts +0 -21
  319. package/dist/chat/markdown.d.ts.map +0 -1
  320. package/dist/chat/markdown.js +0 -246
  321. package/dist/chat/message.d.ts +0 -7
  322. package/dist/chat/message.d.ts.map +0 -1
  323. package/dist/chat/message.js +0 -254
  324. package/dist/chat/messages.d.ts +0 -35
  325. package/dist/chat/messages.d.ts.map +0 -1
  326. package/dist/chat/messages.js +0 -210
  327. package/dist/chat/name.d.ts +0 -7
  328. package/dist/chat/name.d.ts.map +0 -1
  329. package/dist/chat/name.js +0 -37
  330. package/dist/chat/opened.d.ts +0 -12
  331. package/dist/chat/opened.d.ts.map +0 -1
  332. package/dist/chat/opened.js +0 -19
  333. package/dist/chat/overlay.d.ts +0 -32
  334. package/dist/chat/overlay.d.ts.map +0 -1
  335. package/dist/chat/overlay.js +0 -103
  336. package/dist/chat/parts.d.ts +0 -58
  337. package/dist/chat/parts.d.ts.map +0 -1
  338. package/dist/chat/parts.js +0 -120
  339. package/dist/chat/pieces.d.ts +0 -62
  340. package/dist/chat/pieces.d.ts.map +0 -1
  341. package/dist/chat/pieces.js +0 -1110
  342. package/dist/chat/process.d.ts +0 -20
  343. package/dist/chat/process.d.ts.map +0 -1
  344. package/dist/chat/process.js +0 -32
  345. package/dist/chat/provider.d.ts +0 -70
  346. package/dist/chat/provider.d.ts.map +0 -1
  347. package/dist/chat/provider.js +0 -635
  348. package/dist/chat/question.d.ts +0 -9
  349. package/dist/chat/question.d.ts.map +0 -1
  350. package/dist/chat/question.js +0 -69
  351. package/dist/chat/questions.d.ts.map +0 -1
  352. package/dist/chat/read.d.ts.map +0 -1
  353. package/dist/chat/ready.d.ts +0 -37
  354. package/dist/chat/ready.d.ts.map +0 -1
  355. package/dist/chat/ready.js +0 -93
  356. package/dist/chat/room-file.d.ts +0 -8
  357. package/dist/chat/room-file.d.ts.map +0 -1
  358. package/dist/chat/room-file.js +0 -72
  359. package/dist/chat/steady.d.ts +0 -3
  360. package/dist/chat/steady.d.ts.map +0 -1
  361. package/dist/chat/steady.js +0 -26
  362. package/dist/chat/style.d.ts +0 -4
  363. package/dist/chat/style.d.ts.map +0 -1
  364. package/dist/chat/style.js +0 -307
  365. package/dist/chat.d.ts +0 -15
  366. package/dist/chat.d.ts.map +0 -1
  367. package/dist/chat.js +0 -8
  368. package/dist/fence.d.ts +0 -6
  369. package/dist/fence.d.ts.map +0 -1
  370. package/dist/fence.js +0 -10
  371. package/dist/fulltext.d.ts +0 -27
  372. package/dist/fulltext.d.ts.map +0 -1
  373. package/dist/fulltext.js +0 -368
  374. package/dist/words.d.ts +0 -19
  375. package/dist/words.d.ts.map +0 -1
  376. package/dist/words.js +0 -150
package/dist/shown.js ADDED
@@ -0,0 +1,290 @@
1
+ import { conversationsChanged, conversationsLearned } from './conversation.js';
2
+ import { listingNow, list, patchedListing, shownRooms } from './listing.js';
3
+ import { emitPresentation, publishRoomDrafts } from './room-drafts.js';
4
+ import { same } from './status.js';
5
+ export const ROOMS_TOPIC = 'rooms';
6
+ export const STATUS_TOPIC = 'sync-status';
7
+ export const REFUSAL_TOPIC = 'connection-refusal';
8
+ export const STORAGE_LOSS_TOPIC = 'storage-loss';
9
+ export const SERVICE_MODE_TOPIC = 'service-mode';
10
+ export const MEMBER_TOPIC = 'member';
11
+ export const AUTHORITY_TOPIC = 'authority-changes';
12
+ export const LOCKS_TOPIC = 'locks';
13
+ export const queueTopic = (locator) => `queue\u0000${locator}`;
14
+ async function attended({ store, localSaves }) {
15
+ const isFenced = store.fences.has;
16
+ const held = await (await store.open()).status();
17
+ const attentionRequired = held.returned.flatMap((record) => record.returned === null || isFenced(record.locator)
18
+ ? []
19
+ : [{ room: record.locator, path: record.path, returned: structuredClone(record.returned) }]);
20
+ attentionRequired.sort((left, right) => {
21
+ if (left.room !== right.room)
22
+ return left.room < right.room ? -1 : 1;
23
+ if (left.path !== right.path)
24
+ return left.path < right.path ? -1 : 1;
25
+ return 0;
26
+ });
27
+ const changed = new Map();
28
+ if (!localSaves) {
29
+ for (const change of held.unsent) {
30
+ if (!isFenced(change.room))
31
+ changed.set(`${change.room}\u0000${change.path}`, change);
32
+ }
33
+ }
34
+ const unsent = [...changed]
35
+ .sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
36
+ .map(([, change]) => change);
37
+ return {
38
+ queued: !localSaves && held.queued.some((locator) => !isFenced(locator)),
39
+ lastCompleted: held.lastCompleted,
40
+ attentionRequired,
41
+ unsent,
42
+ reset: held.resets.reduce((earliest, { locator, reset }) => isFenced(locator) || (earliest !== null && earliest <= reset) ? earliest : reset, null),
43
+ };
44
+ }
45
+ async function queuedWork({ store, localSaves }) {
46
+ const held = await (await store.open()).queued();
47
+ return !localSaves && held.some((locator) => !store.fences.has(locator));
48
+ }
49
+ export function recoverReads({ liveQueries, figures }) {
50
+ liveQueries.recover();
51
+ figures.recover();
52
+ }
53
+ export function emitRooms(runtime, changed) {
54
+ recoverReads(runtime);
55
+ runtime.store.readiness.queue();
56
+ return changed === undefined
57
+ ? publishRooms(runtime, 'all')
58
+ : publishRooms(runtime, 'changed', changed);
59
+ }
60
+ export function emitKnownRooms(runtime) {
61
+ conversationsLearned(runtime.conversations);
62
+ if (runtime.store.watching(ROOMS_TOPIC, 'waiting').length === 0)
63
+ return;
64
+ void publishRooms(runtime, 'known');
65
+ }
66
+ function roomsOwedWith(held, mode, touched) {
67
+ if (held === undefined) {
68
+ return {
69
+ all: mode === 'all',
70
+ changed: new Set(mode === 'changed' ? touched : []),
71
+ counted: new Set(mode === 'changed' ? [] : touched),
72
+ };
73
+ }
74
+ held.all ||= mode === 'all';
75
+ for (const locator of touched) {
76
+ (mode === 'changed' ? held.changed : held.counted).add(locator);
77
+ }
78
+ return held;
79
+ }
80
+ async function deliverRooms(runtime, owed) {
81
+ const { store, socket } = runtime;
82
+ const waiting = () => store.watching(ROOMS_TOPIC, 'waiting');
83
+ if (socket.closed() || store.watching(ROOMS_TOPIC).length === 0)
84
+ return;
85
+ const patched = owed.all || owed.changed.size === 0 || waiting().length > 0
86
+ ? null
87
+ : await patchedListing(runtime, new Set([...owed.changed, ...owed.counted]));
88
+ if (patched === null && owed.changed.size > 0)
89
+ owed.all = true;
90
+ if (patched === null && !owed.all && owed.counted.size > 0) {
91
+ const held = await store.covering();
92
+ const { roomsShown } = store.device.now();
93
+ owed.all = [...owed.counted].some((locator) => held.rooms.has(locator) &&
94
+ roomsShown?.get(locator)?.documents !== held.rooms.get(locator).documents);
95
+ if (owed.all) {
96
+ recoverReads(runtime);
97
+ store.readiness.queue();
98
+ }
99
+ else if (waiting().length === 0)
100
+ return;
101
+ }
102
+ const listing = patched ?? (await listingNow(runtime));
103
+ if (socket.closed())
104
+ return;
105
+ const { roomsListed, refusal, moving } = socket.session.now();
106
+ const joining = waiting().length > 0 &&
107
+ (roomsListed || listing.size > 0 || refusal !== null || moving.providerUnreachable);
108
+ if (!owed.all && patched === null && !joining)
109
+ return;
110
+ const value = shownRooms(runtime, listing);
111
+ const { roomsShown } = store.device.now();
112
+ const moved = owed.all ||
113
+ patched !== null ||
114
+ (roomsShown !== null &&
115
+ JSON.stringify(shownRooms(runtime, roomsShown)) !== JSON.stringify(value));
116
+ if (moved)
117
+ for (const watcher of store.watching(ROOMS_TOPIC, 'ready'))
118
+ watcher.answer(value);
119
+ if (joining)
120
+ for (const watcher of waiting())
121
+ watcher.answer(value);
122
+ store.device.set({
123
+ roomsShown: store.watching(ROOMS_TOPIC, 'ready').length === 0 ? null : listing,
124
+ });
125
+ }
126
+ function publishRooms(runtime, mode, touched = []) {
127
+ if (runtime.socket.closed())
128
+ return Promise.resolve();
129
+ return runtime.store.owing(ROOMS_TOPIC, (held) => roomsOwedWith(held, mode, touched), (owed) => deliverRooms(runtime, owed));
130
+ }
131
+ export function emitRefusal(runtime) {
132
+ const { store, socket } = runtime;
133
+ store.readiness.queue();
134
+ store.tell(REFUSAL_TOPIC, socket.session.now().refusal);
135
+ emitKnownRooms(runtime);
136
+ }
137
+ export function emitStorageLoss({ store }) {
138
+ store.readiness.queue();
139
+ store.tell(STORAGE_LOSS_TOPIC, store.device.now().storageLoss);
140
+ }
141
+ export function emitMember({ store }, member) {
142
+ store.tell(MEMBER_TOPIC, member);
143
+ }
144
+ async function deliverStatus(runtime, owed) {
145
+ const { store, socket } = runtime;
146
+ const held = await attended(runtime);
147
+ if (socket.closed())
148
+ return;
149
+ for (const { moving, current } of owed) {
150
+ const state = moving.resting && held.queued ? 'pending' : moving.state;
151
+ const next = {
152
+ state: state === 'synced' && !current ? 'syncing' : state,
153
+ lastCompleted: held.lastCompleted,
154
+ providerUnreachable: moving.providerUnreachable,
155
+ attentionRequired: held.attentionRequired,
156
+ unsent: held.unsent,
157
+ reset: held.reset,
158
+ };
159
+ if (same(store.device.now().status, next))
160
+ continue;
161
+ store.device.set({ status: next });
162
+ store.tell(STATUS_TOPIC, next);
163
+ }
164
+ }
165
+ export function show(runtime) {
166
+ const { store, socket, conversations } = runtime;
167
+ if (socket.closed())
168
+ return Promise.resolve();
169
+ store.readiness.queue();
170
+ emitKnownRooms(runtime);
171
+ const moved = { moving: socket.session.now().moving, current: conversations.current() };
172
+ return store.owing(STATUS_TOPIC, (held) => {
173
+ if (held === undefined)
174
+ return [moved];
175
+ held.push(moved);
176
+ return held;
177
+ }, (owed) => deliverStatus(runtime, owed));
178
+ }
179
+ export function moveTo(runtime, next) {
180
+ if (runtime.socket.closed())
181
+ return Promise.resolve();
182
+ runtime.socket.session.set({ moving: next });
183
+ return show(runtime);
184
+ }
185
+ export function statusShown(runtime) {
186
+ return moveTo(runtime, runtime.socket.session.now().moving);
187
+ }
188
+ export function transferring({ socket }) {
189
+ return { ...socket.session.now().moving, state: 'syncing', resting: false };
190
+ }
191
+ export function pendingShown(runtime) {
192
+ const { socket, localSaves } = runtime;
193
+ if (!localSaves)
194
+ socket.session.set({ recorded: false });
195
+ const { moving } = socket.session.now();
196
+ return moveTo(runtime, localSaves ? moving : { ...moving, state: 'pending', resting: false });
197
+ }
198
+ function entryOf({ localSaves }, states, batch) {
199
+ if (localSaves)
200
+ return Object.freeze({ batch, state: 'local' });
201
+ const state = states.get(batch.id);
202
+ return Object.freeze({ batch, ...(state?.submission ?? { state: 'waiting' }) });
203
+ }
204
+ export async function entriesOf(runtime, locator) {
205
+ const { queue, states } = await runtime.store.work(locator);
206
+ return queue.map((batch) => entryOf(runtime, states, batch));
207
+ }
208
+ function emitQueue(runtime, locator) {
209
+ const { store, socket } = runtime;
210
+ const listening = () => store.watching(queueTopic(locator));
211
+ if (socket.closed() || listening().length === 0)
212
+ return Promise.resolve();
213
+ return store.publication(async () => {
214
+ if (socket.closed() || listening().length === 0)
215
+ return;
216
+ const entries = await entriesOf(runtime, locator);
217
+ if (socket.closed())
218
+ return;
219
+ for (const watcher of listening())
220
+ watcher.answer(entries);
221
+ });
222
+ }
223
+ export function publishChangeSet(runtime, set) {
224
+ const { store, liveQueries, figures, conversations } = runtime;
225
+ liveQueries.touched(set);
226
+ figures.touched(set);
227
+ for (const { locator, path } of set.documents) {
228
+ if (path !== null)
229
+ store.attached.drop(locator, path);
230
+ }
231
+ const shownNow = [];
232
+ if (set.queues.length > 0 || set.drafts.length > 0)
233
+ shownNow.push(show(runtime));
234
+ if (set.rooms.length > 0)
235
+ shownNow.push(emitRooms(runtime, set.rooms));
236
+ else if (set.documents.length > 0) {
237
+ shownNow.push(publishRooms(runtime, 'counted', [...new Set(set.documents.map(({ locator }) => locator))]));
238
+ }
239
+ for (const locator of set.queues)
240
+ shownNow.push(emitQueue(runtime, locator));
241
+ if (set.drafts.length > 0)
242
+ shownNow.push(publishRoomDrafts(runtime, false));
243
+ else if (set.documents.length > 0) {
244
+ shownNow.push(publishRoomDrafts(runtime, false, set.documents));
245
+ }
246
+ for (const app of set.presentations)
247
+ shownNow.push(emitPresentation(runtime, app));
248
+ conversationsChanged(conversations, set);
249
+ return Promise.all(shownNow).then(() => undefined);
250
+ }
251
+ export function roomUnreadable(runtime, room) {
252
+ runtime.socket.rooms.stand(room.locator, { unreadable: true });
253
+ list(runtime, room, false);
254
+ emitRooms(runtime);
255
+ }
256
+ export async function rest(runtime, progress, live = () => !runtime.socket.closed()) {
257
+ const { store, socket } = runtime;
258
+ const { session, lanes, rooms } = socket;
259
+ if (!live())
260
+ return;
261
+ const settled = () => session.now().complete &&
262
+ lanes.roomWork() === 0 &&
263
+ !socket.naming() &&
264
+ rooms.standingWhere(({ stale }) => stale).length === 0;
265
+ let synced = settled();
266
+ if (synced && !session.now().recorded) {
267
+ const queued = await queuedWork(runtime).catch(() => true);
268
+ if (!live())
269
+ return;
270
+ synced = !queued && settled();
271
+ }
272
+ if (synced && !session.now().recorded) {
273
+ const completedAt = new Date().toISOString();
274
+ try {
275
+ await (await store.open()).fact('lastCompleted', completedAt);
276
+ if (!live())
277
+ return;
278
+ session.set({ recorded: true });
279
+ }
280
+ catch {
281
+ synced = false;
282
+ }
283
+ }
284
+ const { complete, moving } = session.now();
285
+ moveTo(runtime, {
286
+ state: synced && complete && lanes.roomWork() === 0 && !socket.naming() ? 'synced' : 'syncing',
287
+ providerUnreachable: progress === null ? moving.providerUnreachable : !progress.reachable,
288
+ resting: true,
289
+ });
290
+ }
@@ -0,0 +1,7 @@
1
+ export type Admission = {
2
+ heldStream(): Promise<() => void>;
3
+ unqueued(): Promise<void>;
4
+ queued(text: number): () => void;
5
+ };
6
+ export declare function createAdmission(): Admission;
7
+ //# sourceMappingURL=admission.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admission.d.ts","sourceRoot":"","sources":["../../src/socket/admission.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,SAAS,GAAG;IACtB,UAAU,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;IAClC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;CAClC,CAAC;AAEF,wBAAgB,eAAe,IAAI,SAAS,CAmC3C"}
@@ -0,0 +1,39 @@
1
+ const STREAMS_HELD = 4;
2
+ const QUEUED_TEXT = 1 << 23;
3
+ export function createAdmission() {
4
+ let streamsFree = STREAMS_HELD;
5
+ let queuedText = 0;
6
+ const installWaiters = [];
7
+ function once(release) {
8
+ let released = false;
9
+ return () => {
10
+ if (released)
11
+ return;
12
+ released = true;
13
+ release();
14
+ for (const admit of installWaiters.splice(0))
15
+ admit();
16
+ };
17
+ }
18
+ return {
19
+ async heldStream() {
20
+ while (streamsFree === 0)
21
+ await new Promise((admit) => installWaiters.push(admit));
22
+ streamsFree -= 1;
23
+ return once(() => {
24
+ streamsFree += 1;
25
+ });
26
+ },
27
+ async unqueued() {
28
+ while (queuedText >= QUEUED_TEXT) {
29
+ await new Promise((admit) => installWaiters.push(admit));
30
+ }
31
+ },
32
+ queued(text) {
33
+ queuedText += text;
34
+ return once(() => {
35
+ queuedText -= text;
36
+ });
37
+ },
38
+ };
39
+ }
@@ -0,0 +1,6 @@
1
+ export type Answers = {
2
+ awaitingAnswer(locator: string): () => void;
3
+ answered(locator: string): Promise<void> | undefined;
4
+ };
5
+ export declare function createAnswers(): Answers;
6
+ //# sourceMappingURL=answers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"answers.d.ts","sourceRoot":"","sources":["../../src/socket/answers.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,OAAO,GAAG;IACpB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;IAC5C,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;CACtD,CAAC;AAEF,wBAAgB,aAAa,IAAI,OAAO,CAkBvC"}
@@ -0,0 +1,20 @@
1
+ export function createAnswers() {
2
+ const answering = new Map();
3
+ return {
4
+ awaitingAnswer(locator) {
5
+ answering.get(locator)?.release();
6
+ let release = () => { };
7
+ const answered = new Promise((resolve) => {
8
+ release = resolve;
9
+ });
10
+ const awaited = { answered, release };
11
+ answering.set(locator, awaited);
12
+ return () => {
13
+ if (answering.get(locator) === awaited)
14
+ answering.delete(locator);
15
+ release();
16
+ };
17
+ },
18
+ answered: (locator) => answering.get(locator)?.answered,
19
+ };
20
+ }
@@ -0,0 +1,20 @@
1
+ export type Live = () => boolean;
2
+ type LaneRules = {
3
+ generation(): number;
4
+ continuing(): boolean;
5
+ stopping(): boolean;
6
+ };
7
+ export type Lanes = {
8
+ task(lane: string, work: (live: Live) => Promise<void>): Promise<void>;
9
+ inRoom<T>(locator: string, work: (live: Live) => Promise<T>): Promise<T>;
10
+ roomTask(locator: string, work: (live: Live) => Promise<void>): Promise<void>;
11
+ roomWork(): number;
12
+ current(): Promise<unknown>;
13
+ finished(): Promise<unknown>;
14
+ calling(operation: string): boolean;
15
+ call(operation: string): void;
16
+ called(operation: string): void;
17
+ };
18
+ export declare function createLanes({ generation, continuing, stopping }: LaneRules): Lanes;
19
+ export {};
20
+ //# sourceMappingURL=lanes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lanes.d.ts","sourceRoot":"","sources":["../../src/socket/lanes.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC;AAIjC,KAAK,SAAS,GAAG;IACf,UAAU,IAAI,MAAM,CAAC;IACrB,UAAU,IAAI,OAAO,CAAC;IACtB,QAAQ,IAAI,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACzE,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,QAAQ,IAAI,MAAM,CAAC;IACnB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5B,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IACpC,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC,CAAC;AAIF,wBAAgB,WAAW,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,SAAS,GAAG,KAAK,CAgFlF"}
@@ -0,0 +1,77 @@
1
+ const ROOM_READS = 256;
2
+ export function createLanes({ generation, continuing, stopping }) {
3
+ const lanes = new Map();
4
+ const roomLanes = new Map();
5
+ const roomReads = { free: ROOM_READS, waiting: [] };
6
+ const working = new Set();
7
+ const calling = new Set();
8
+ let roomWork = 0;
9
+ async function admittedRead(work) {
10
+ while (roomReads.free === 0) {
11
+ await new Promise((admit) => roomReads.waiting.push(admit));
12
+ }
13
+ roomReads.free -= 1;
14
+ try {
15
+ await work();
16
+ }
17
+ finally {
18
+ roomReads.free += 1;
19
+ roomReads.waiting.shift()?.();
20
+ }
21
+ }
22
+ function inRoom(locator, work) {
23
+ roomWork += 1;
24
+ const ran = (roomLanes.get(locator) ?? Promise.resolve()).then(async () => {
25
+ try {
26
+ return await work(continuing);
27
+ }
28
+ finally {
29
+ roomWork -= 1;
30
+ }
31
+ });
32
+ const chain = ran.then(() => undefined, () => undefined);
33
+ roomLanes.set(locator, chain);
34
+ working.add(chain);
35
+ void chain.finally(() => {
36
+ working.delete(chain);
37
+ if (roomLanes.get(locator) === chain)
38
+ roomLanes.delete(locator);
39
+ });
40
+ return ran;
41
+ }
42
+ return {
43
+ task(lane, work) {
44
+ if (stopping())
45
+ return Promise.resolve();
46
+ const held = lanes.get(lane);
47
+ const opened = generation();
48
+ const current = held?.generation === opened ? held : { generation: opened, chain: Promise.resolve() };
49
+ const turn = current.generation;
50
+ const live = () => turn === generation() && continuing();
51
+ const run = current.chain.then(() => work(live)).catch(() => undefined);
52
+ current.chain = run;
53
+ lanes.set(lane, current);
54
+ working.add(run);
55
+ void run.finally(() => working.delete(run));
56
+ return run;
57
+ },
58
+ inRoom,
59
+ roomTask(locator, work) {
60
+ if (stopping())
61
+ return Promise.resolve();
62
+ return inRoom(locator, (live) => admittedRead(() => work(live))).catch(() => undefined);
63
+ },
64
+ roomWork: () => roomWork,
65
+ current: () => Promise.all([...lanes.values()]
66
+ .filter((held) => held.generation === generation())
67
+ .map((held) => held.chain)),
68
+ finished: () => Promise.all(working),
69
+ calling: (operation) => calling.has(operation),
70
+ call(operation) {
71
+ calling.add(operation);
72
+ },
73
+ called(operation) {
74
+ calling.delete(operation);
75
+ },
76
+ };
77
+ }
@@ -0,0 +1,10 @@
1
+ import type { Adapter } from '../adapter.js';
2
+ import type { Reads } from '../bootstrap.js';
3
+ type HeldReads = {
4
+ readonly reads: Reads;
5
+ abort(): void;
6
+ stop(): void;
7
+ };
8
+ export declare function createReads(adapter: Adapter): HeldReads;
9
+ export {};
10
+ //# sourceMappingURL=reads.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reads.d.ts","sourceRoot":"","sources":["../../src/socket/reads.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAiD,MAAM,eAAe,CAAC;AAC5F,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAE7C,KAAK,SAAS,GAAG;IACf,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,IAAI,IAAI,CAAC;CACd,CAAC;AAWF,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,CAuBvD"}
@@ -0,0 +1,31 @@
1
+ function readUntil(read, signal) {
2
+ if (signal.aborted)
3
+ return Promise.resolve({ kind: 'transport-uncertainty' });
4
+ return new Promise((resolve, reject) => {
5
+ const stop = () => resolve({ kind: 'transport-uncertainty' });
6
+ signal.addEventListener('abort', stop, { once: true });
7
+ read.then(resolve, reject).finally(() => signal.removeEventListener('abort', stop));
8
+ });
9
+ }
10
+ export function createReads(adapter) {
11
+ let inFlight = new AbortController();
12
+ const refreshed = adapter.refresh?.bind(adapter);
13
+ return {
14
+ reads: {
15
+ bootstrap: (authorized, request) => readUntil(adapter.bootstrap(authorized, request), inFlight.signal),
16
+ ...(refreshed === undefined
17
+ ? {}
18
+ : {
19
+ refresh: (authorized, request) => readUntil(refreshed(authorized, request), inFlight.signal),
20
+ }),
21
+ reached: (locator, roomVersion, target) => adapter.reached(locator, roomVersion, target),
22
+ },
23
+ abort() {
24
+ inFlight.abort();
25
+ inFlight = new AbortController();
26
+ },
27
+ stop() {
28
+ inFlight.abort();
29
+ },
30
+ };
31
+ }
@@ -0,0 +1,44 @@
1
+ import type { DiscoveredRoom, ProviderRefusal, TypedSelection } from '../adapter.js';
2
+ import type { ModelState } from '../model.js';
3
+ export type RoomDeclaration = Omit<DiscoveredRoom, 'roomVersion' | 'typedSelection'> & {
4
+ typedSelection?: TypedSelection | null;
5
+ };
6
+ export type Declared = {
7
+ readonly room: RoomDeclaration | null;
8
+ readonly available: boolean;
9
+ };
10
+ type RoomStanding = {
11
+ readonly unreadable: boolean;
12
+ readonly refusal: ProviderRefusal | null;
13
+ readonly unheldModel: ModelState | null;
14
+ readonly stale: boolean;
15
+ readonly repairable: {
16
+ readonly reset: string | undefined;
17
+ } | null;
18
+ readonly repairing: boolean;
19
+ readonly reloadDue: boolean;
20
+ readonly confirmed: boolean;
21
+ readonly unpreparable: boolean;
22
+ };
23
+ export type Rooms = {
24
+ declare(locator: string, declared: Declared): void;
25
+ declared(locator: string): Declared | undefined;
26
+ declarations(): ReadonlyMap<string, Declared>;
27
+ discover(room: DiscoveredRoom): void;
28
+ discovered(locator: string): DiscoveredRoom | undefined;
29
+ discoveredRooms(): readonly DiscoveredRoom[];
30
+ undiscoverAll(): void;
31
+ standing(locator: string): RoomStanding;
32
+ stand(locator: string, change: Partial<RoomStanding>): void;
33
+ standingWhere(held: (room: RoomStanding) => boolean): readonly string[];
34
+ standAll(change: Partial<RoomStanding>): void;
35
+ forget(locator: string): void;
36
+ askAgain(locator: string, ask: () => void): void;
37
+ readied(locator: string): void;
38
+ unreadied(): void;
39
+ connectionLost(lapsed: () => void): void;
40
+ connectionLive(): void;
41
+ };
42
+ export declare function createRooms(): Rooms;
43
+ export {};
44
+ //# sourceMappingURL=rooms.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rooms.d.ts","sourceRoot":"","sources":["../../src/socket/rooms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACrF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,cAAc,EAAE,aAAa,GAAG,gBAAgB,CAAC,GAAG;IACrF,cAAc,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC;AAE9F,KAAK,YAAY,GAAG;IAClB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,WAAW,EAAE,UAAU,GAAG,IAAI,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,GAAG,IAAI,CAAC;IACnE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;CAChC,CAAC;AAcF,MAAM,MAAM,KAAK,GAAG;IAClB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IACnD,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;IAChD,YAAY,IAAI,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC9C,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IACrC,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAAC;IACxD,eAAe,IAAI,SAAS,cAAc,EAAE,CAAC;IAC7C,aAAa,IAAI,IAAI,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAAC;IACxC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC;IAC5D,aAAa,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,GAAG,SAAS,MAAM,EAAE,CAAC;IACxE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC;IAC9C,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IACjD,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,SAAS,IAAI,IAAI,CAAC;IAClB,cAAc,CAAC,MAAM,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IACzC,cAAc,IAAI,IAAI,CAAC;CACxB,CAAC;AAQF,wBAAgB,WAAW,IAAI,KAAK,CAsEnC"}
@@ -0,0 +1,90 @@
1
+ const STANDING = {
2
+ unreadable: false,
3
+ refusal: null,
4
+ unheldModel: null,
5
+ stale: false,
6
+ repairable: null,
7
+ repairing: false,
8
+ reloadDue: false,
9
+ confirmed: false,
10
+ unpreparable: false,
11
+ };
12
+ // A Room the Provider answers not ready is asked again after these waits, the last repeating, so a chunk build that catches up within seconds installs at once and a long one is asked every 15 seconds.
13
+ const NOT_READY_MS = [1_000, 2_000, 3_000, 5_000, 8_000, 11_000, 15_000];
14
+ // A Room that locks offline stays readable this long after the connection drops, so a laptop waking or changing network keeps working while a disconnected device locks soon after.
15
+ const LOCK_GRACE_MS = 120_000;
16
+ export function createRooms() {
17
+ const declared = new Map();
18
+ const discovered = new Map();
19
+ const standings = new Map();
20
+ const unready = new Map();
21
+ let lockGrace = null;
22
+ function readied(locator) {
23
+ const held = unready.get(locator);
24
+ if (held === undefined)
25
+ return;
26
+ if (held.timer !== null)
27
+ clearTimeout(held.timer);
28
+ unready.delete(locator);
29
+ }
30
+ return {
31
+ declare(locator, room) {
32
+ declared.set(locator, room);
33
+ },
34
+ declared: (locator) => declared.get(locator),
35
+ declarations: () => declared,
36
+ discover(room) {
37
+ discovered.set(room.locator, room);
38
+ },
39
+ discovered: (locator) => discovered.get(locator),
40
+ discoveredRooms: () => [...discovered.values()],
41
+ undiscoverAll() {
42
+ discovered.clear();
43
+ },
44
+ standing: (locator) => standings.get(locator) ?? STANDING,
45
+ stand(locator, change) {
46
+ standings.set(locator, { ...(standings.get(locator) ?? STANDING), ...change });
47
+ },
48
+ standingWhere: (held) => [...standings].filter(([, room]) => held(room)).map(([locator]) => locator),
49
+ standAll(change) {
50
+ for (const [locator, room] of standings)
51
+ standings.set(locator, { ...room, ...change });
52
+ },
53
+ forget(locator) {
54
+ declared.delete(locator);
55
+ discovered.delete(locator);
56
+ const { repairing, reloadDue } = standings.get(locator) ?? STANDING;
57
+ standings.set(locator, { ...STANDING, repairing, reloadDue });
58
+ },
59
+ askAgain(locator, ask) {
60
+ const held = unready.get(locator) ?? { tries: 0, timer: null };
61
+ unready.set(locator, held);
62
+ if (held.timer !== null)
63
+ return;
64
+ const wait = NOT_READY_MS[Math.min(held.tries, NOT_READY_MS.length - 1)];
65
+ held.tries += 1;
66
+ held.timer = setTimeout(() => {
67
+ held.timer = null;
68
+ ask();
69
+ }, wait);
70
+ },
71
+ readied,
72
+ unreadied() {
73
+ for (const locator of [...unready.keys()])
74
+ readied(locator);
75
+ },
76
+ connectionLost(lapsed) {
77
+ if (lockGrace !== null)
78
+ return;
79
+ lockGrace = setTimeout(() => {
80
+ lockGrace = null;
81
+ lapsed();
82
+ }, LOCK_GRACE_MS);
83
+ },
84
+ connectionLive() {
85
+ if (lockGrace !== null)
86
+ clearTimeout(lockGrace);
87
+ lockGrace = null;
88
+ },
89
+ };
90
+ }