@agentshouse/mdruntime 0.1.0-c49444f2a8fc6 → 0.1.0-c4c5934c45f21

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 (261) hide show
  1. package/README.md +8 -8
  2. package/dist/acceptance.d.ts +3 -0
  3. package/dist/acceptance.d.ts.map +1 -0
  4. package/dist/acceptance.js +308 -0
  5. package/dist/act-lanes.d.ts +33 -0
  6. package/dist/act-lanes.d.ts.map +1 -0
  7. package/dist/act-lanes.js +177 -0
  8. package/dist/actions.d.ts +20 -0
  9. package/dist/actions.d.ts.map +1 -0
  10. package/dist/actions.js +251 -0
  11. package/dist/adapter.d.ts +31 -44
  12. package/dist/adapter.d.ts.map +1 -1
  13. package/dist/bootstrap.d.ts +1 -1
  14. package/dist/bootstrap.d.ts.map +1 -1
  15. package/dist/bootstrap.js +6 -18
  16. package/dist/cell.d.ts +6 -0
  17. package/dist/cell.d.ts.map +1 -0
  18. package/dist/cell.js +9 -0
  19. package/dist/change-set.d.ts +4 -0
  20. package/dist/change-set.d.ts.map +1 -1
  21. package/dist/change-set.js +6 -0
  22. package/dist/change.d.ts.map +1 -1
  23. package/dist/change.js +4 -2
  24. package/dist/chat-types.d.ts +5 -0
  25. package/dist/chat-types.d.ts.map +1 -0
  26. package/dist/chat-types.js +13 -0
  27. package/dist/client.d.ts +19 -13
  28. package/dist/client.d.ts.map +1 -1
  29. package/dist/client.js +30 -14
  30. package/dist/collection.d.ts +22 -4
  31. package/dist/collection.d.ts.map +1 -1
  32. package/dist/collection.js +12 -2
  33. package/dist/compile.d.ts +5 -0
  34. package/dist/compile.d.ts.map +1 -1
  35. package/dist/compile.js +200 -75
  36. package/dist/connection.d.ts +5 -143
  37. package/dist/connection.d.ts.map +1 -1
  38. package/dist/connection.js +104 -5308
  39. package/dist/conversation-live.d.ts +136 -0
  40. package/dist/conversation-live.d.ts.map +1 -0
  41. package/dist/conversation-live.js +249 -0
  42. package/dist/conversation-row.d.ts.map +1 -1
  43. package/dist/conversation-row.js +7 -1
  44. package/dist/conversation.d.ts +43 -44
  45. package/dist/conversation.d.ts.map +1 -1
  46. package/dist/conversation.js +906 -1024
  47. package/dist/declaration.d.ts +10 -0
  48. package/dist/declaration.d.ts.map +1 -0
  49. package/dist/declaration.js +24 -0
  50. package/dist/discovery.d.ts +10 -0
  51. package/dist/discovery.d.ts.map +1 -0
  52. package/dist/discovery.js +148 -0
  53. package/dist/durability.d.ts +9 -0
  54. package/dist/durability.d.ts.map +1 -1
  55. package/dist/expectation.d.ts +4 -2
  56. package/dist/expectation.d.ts.map +1 -1
  57. package/dist/expectation.js +33 -11
  58. package/dist/failure.d.ts +1 -0
  59. package/dist/failure.d.ts.map +1 -1
  60. package/dist/failure.js +3 -0
  61. package/dist/figures.d.ts +49 -0
  62. package/dist/figures.d.ts.map +1 -0
  63. package/dist/figures.js +197 -0
  64. package/dist/holdings.d.ts +29 -0
  65. package/dist/holdings.d.ts.map +1 -0
  66. package/dist/holdings.js +95 -0
  67. package/dist/host.d.ts +18 -2
  68. package/dist/host.d.ts.map +1 -1
  69. package/dist/host.js +45 -12
  70. package/dist/index.d.ts +22 -8
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +7 -2
  73. package/dist/install.d.ts +54 -0
  74. package/dist/install.d.ts.map +1 -0
  75. package/dist/install.js +538 -0
  76. package/dist/lifecycle.d.ts +7 -0
  77. package/dist/lifecycle.d.ts.map +1 -0
  78. package/dist/lifecycle.js +272 -0
  79. package/dist/listing.d.ts +48 -0
  80. package/dist/listing.d.ts.map +1 -0
  81. package/dist/listing.js +139 -0
  82. package/dist/live.d.ts.map +1 -1
  83. package/dist/live.js +3 -3
  84. package/dist/locks.d.ts +7 -0
  85. package/dist/locks.d.ts.map +1 -0
  86. package/dist/locks.js +33 -0
  87. package/dist/log.d.ts +1 -0
  88. package/dist/log.d.ts.map +1 -1
  89. package/dist/lost.d.ts +5 -0
  90. package/dist/lost.d.ts.map +1 -0
  91. package/dist/lost.js +50 -0
  92. package/dist/media.d.ts +1 -1
  93. package/dist/media.d.ts.map +1 -1
  94. package/dist/media.js +4 -4
  95. package/dist/memory.d.ts +4 -2
  96. package/dist/memory.d.ts.map +1 -1
  97. package/dist/memory.js +38 -20
  98. package/dist/messages.d.ts +1 -4
  99. package/dist/messages.d.ts.map +1 -1
  100. package/dist/messages.js +14 -32
  101. package/dist/model.d.ts +0 -1
  102. package/dist/model.d.ts.map +1 -1
  103. package/dist/model.js +0 -5
  104. package/dist/models.d.ts +10 -0
  105. package/dist/models.d.ts.map +1 -0
  106. package/dist/models.js +156 -0
  107. package/dist/observation.d.ts.map +1 -1
  108. package/dist/observation.js +12 -17
  109. package/dist/opened.d.ts +1 -1
  110. package/dist/opened.d.ts.map +1 -1
  111. package/dist/opened.js +5 -5
  112. package/dist/opening.d.ts +4 -0
  113. package/dist/opening.d.ts.map +1 -0
  114. package/dist/opening.js +59 -0
  115. package/dist/outcome.d.ts +4 -1
  116. package/dist/outcome.d.ts.map +1 -1
  117. package/dist/outcome.js +3 -0
  118. package/dist/overlay.d.ts +2 -1
  119. package/dist/overlay.d.ts.map +1 -1
  120. package/dist/overlay.js +32 -21
  121. package/dist/page-metadata.d.ts +8 -0
  122. package/dist/page-metadata.d.ts.map +1 -0
  123. package/dist/page-metadata.js +19 -0
  124. package/dist/parts.d.ts +3 -51
  125. package/dist/parts.d.ts.map +1 -1
  126. package/dist/parts.js +14 -111
  127. package/dist/paths.d.ts +1 -0
  128. package/dist/paths.d.ts.map +1 -1
  129. package/dist/paths.js +22 -0
  130. package/dist/preparation.d.ts +20 -0
  131. package/dist/preparation.d.ts.map +1 -0
  132. package/dist/preparation.js +233 -0
  133. package/dist/presence.d.ts +52 -0
  134. package/dist/presence.d.ts.map +1 -0
  135. package/dist/presence.js +220 -0
  136. package/dist/queries.d.ts +16 -0
  137. package/dist/queries.d.ts.map +1 -0
  138. package/dist/queries.js +270 -0
  139. package/dist/query.d.ts +10 -1
  140. package/dist/query.d.ts.map +1 -1
  141. package/dist/questions.d.ts +2 -0
  142. package/dist/questions.d.ts.map +1 -1
  143. package/dist/questions.js +5 -1
  144. package/dist/queue.d.ts +40 -0
  145. package/dist/queue.d.ts.map +1 -0
  146. package/dist/queue.js +455 -0
  147. package/dist/reach.d.ts +3 -1
  148. package/dist/reach.d.ts.map +1 -1
  149. package/dist/reach.js +38 -8
  150. package/dist/react.d.ts +18 -1
  151. package/dist/react.d.ts.map +1 -1
  152. package/dist/react.js +15 -1
  153. package/dist/readiness.d.ts +0 -1
  154. package/dist/readiness.d.ts.map +1 -1
  155. package/dist/reads.d.ts +37 -0
  156. package/dist/reads.d.ts.map +1 -0
  157. package/dist/reads.js +174 -0
  158. package/dist/refresh.js +2 -2
  159. package/dist/refusal.d.ts +5 -0
  160. package/dist/refusal.d.ts.map +1 -0
  161. package/dist/refusal.js +57 -0
  162. package/dist/replica.d.ts +5 -13
  163. package/dist/replica.d.ts.map +1 -1
  164. package/dist/replica.js +15 -16
  165. package/dist/room-draft.d.ts +4 -6
  166. package/dist/room-draft.d.ts.map +1 -1
  167. package/dist/room-draft.js +36 -52
  168. package/dist/room-drafts.d.ts +24 -0
  169. package/dist/room-drafts.d.ts.map +1 -0
  170. package/dist/room-drafts.js +217 -0
  171. package/dist/rows.d.ts.map +1 -1
  172. package/dist/rows.js +3 -4
  173. package/dist/runtime.d.ts +34 -0
  174. package/dist/runtime.d.ts.map +1 -0
  175. package/dist/runtime.js +1 -0
  176. package/dist/save.d.ts +41 -86
  177. package/dist/save.d.ts.map +1 -1
  178. package/dist/save.js +232 -112
  179. package/dist/saves.d.ts +32 -0
  180. package/dist/saves.d.ts.map +1 -0
  181. package/dist/saves.js +413 -0
  182. package/dist/seed.d.ts +11 -2
  183. package/dist/seed.d.ts.map +1 -1
  184. package/dist/seed.js +71 -1
  185. package/dist/shared.d.ts +1 -6
  186. package/dist/shared.d.ts.map +1 -1
  187. package/dist/shared.js +13 -95
  188. package/dist/shown.d.ts +32 -0
  189. package/dist/shown.d.ts.map +1 -0
  190. package/dist/shown.js +290 -0
  191. package/dist/socket/admission.d.ts +7 -0
  192. package/dist/socket/admission.d.ts.map +1 -0
  193. package/dist/socket/admission.js +39 -0
  194. package/dist/socket/answers.d.ts +6 -0
  195. package/dist/socket/answers.d.ts.map +1 -0
  196. package/dist/socket/answers.js +20 -0
  197. package/dist/socket/lanes.d.ts +20 -0
  198. package/dist/socket/lanes.d.ts.map +1 -0
  199. package/dist/socket/lanes.js +77 -0
  200. package/dist/socket/reads.d.ts +10 -0
  201. package/dist/socket/reads.d.ts.map +1 -0
  202. package/dist/socket/reads.js +31 -0
  203. package/dist/socket/session.d.ts +38 -0
  204. package/dist/socket/session.d.ts.map +1 -0
  205. package/dist/socket/session.js +23 -0
  206. package/dist/socket.d.ts +67 -0
  207. package/dist/socket.d.ts.map +1 -0
  208. package/dist/socket.js +170 -0
  209. package/dist/source.d.ts.map +1 -1
  210. package/dist/source.js +5 -4
  211. package/dist/store/installs.d.ts +30 -0
  212. package/dist/store/installs.d.ts.map +1 -0
  213. package/dist/store/installs.js +34 -0
  214. package/dist/store/readiness.d.ts +10 -0
  215. package/dist/store/readiness.d.ts.map +1 -0
  216. package/dist/store/readiness.js +52 -0
  217. package/dist/store/records.d.ts +212 -0
  218. package/dist/store/records.d.ts.map +1 -0
  219. package/dist/store/records.js +430 -0
  220. package/dist/store/room-held.d.ts +8 -0
  221. package/dist/store/room-held.d.ts.map +1 -0
  222. package/dist/store/room-held.js +17 -0
  223. package/dist/store/space.d.ts +11 -0
  224. package/dist/store/space.d.ts.map +1 -0
  225. package/dist/store/space.js +41 -0
  226. package/dist/store/watchers.d.ts +17 -0
  227. package/dist/store/watchers.d.ts.map +1 -0
  228. package/dist/store/watchers.js +56 -0
  229. package/dist/store/writes.d.ts +24 -0
  230. package/dist/store/writes.d.ts.map +1 -0
  231. package/dist/store/writes.js +125 -0
  232. package/dist/store.d.ts +112 -204
  233. package/dist/store.d.ts.map +1 -1
  234. package/dist/store.js +158 -394
  235. package/dist/stored.d.ts +1 -1
  236. package/dist/stored.d.ts.map +1 -1
  237. package/dist/stored.js +28 -14
  238. package/dist/surface.d.ts +88 -0
  239. package/dist/surface.d.ts.map +1 -0
  240. package/dist/surface.js +223 -0
  241. package/dist/sync.d.ts +19 -0
  242. package/dist/sync.d.ts.map +1 -0
  243. package/dist/sync.js +521 -0
  244. package/dist/tables.d.ts +32 -8
  245. package/dist/tables.d.ts.map +1 -1
  246. package/dist/tables.js +43 -12
  247. package/dist/tallies.d.ts +18 -0
  248. package/dist/tallies.d.ts.map +1 -0
  249. package/dist/tallies.js +129 -0
  250. package/dist/validation.d.ts.map +1 -1
  251. package/dist/validation.js +2 -2
  252. package/dist/wire.d.ts +48 -5
  253. package/dist/wire.d.ts.map +1 -1
  254. package/dist/wire.js +16 -3
  255. package/package.json +3 -2
  256. package/dist/attempt.d.ts +0 -16
  257. package/dist/attempt.d.ts.map +0 -1
  258. package/dist/attempt.js +0 -70
  259. package/dist/job.d.ts +0 -33
  260. package/dist/job.d.ts.map +0 -1
  261. package/dist/job.js +0 -54
@@ -0,0 +1,272 @@
1
+ import { catchUpConversations, receiveConversationEvent, reconcileConversations, } from './conversation.js';
2
+ import { declared } from './declaration.js';
3
+ import { uncaught } from './failure.js';
4
+ import { catching, replaced } from './install.js';
5
+ import { connectionLost } from './locks.js';
6
+ import { fenceLive } from './lost.js';
7
+ import { cachedModels, revoked, settleModels } from './models.js';
8
+ import { refuse } from './refusal.js';
9
+ import { moveTo, recoverReads, rest, SERVICE_MODE_TOPIC, show, submissionDue, transferring, } from './shown.js';
10
+ import { applyRoom, changeAuthority, countAuthorityChange, finishOpening, loadRoom, OPENING_LANE, reload, resynchronize, sync, } from './sync.js';
11
+ const CONVERSATION_LANE = 'conversations';
12
+ function closing(runtime, opened) {
13
+ const { store, socket } = runtime;
14
+ return socket.lanes.task(OPENING_LANE, async (live) => {
15
+ if (!live())
16
+ return;
17
+ const local = await store.open();
18
+ if (!opened && !socket.isOpen())
19
+ await cachedModels(runtime, local);
20
+ await rest(runtime, null, live);
21
+ });
22
+ }
23
+ function closedSocket(runtime, lapsed, lost, opened) {
24
+ const { socket, presence, conversations } = runtime;
25
+ const { session } = socket;
26
+ socket.notifyReady();
27
+ presence.stopAsking();
28
+ connectionLost(runtime);
29
+ if (lost)
30
+ conversations.lost();
31
+ if (lapsed) {
32
+ void refuse(runtime, 'revoked-authorization');
33
+ return;
34
+ }
35
+ session.set({ complete: false });
36
+ const { streamed, moving } = session.now();
37
+ if (streamed !== null)
38
+ streamed.complete = false;
39
+ moveTo(runtime, {
40
+ ...moving,
41
+ state: moving.state === 'synced' ? 'syncing' : moving.state,
42
+ providerUnreachable: moving.providerUnreachable || (!opened && lost),
43
+ });
44
+ void closing(runtime, opened);
45
+ }
46
+ function owedReloads(runtime, expired, held) {
47
+ const { store, presence } = runtime;
48
+ const reloading = presence
49
+ .rooms()
50
+ .filter((room) => !expired.includes(room.locator) && revoked(held.get(room.locator)?.record.model))
51
+ .map((room) => room.locator);
52
+ for (const locator of reloading)
53
+ catching(store, locator);
54
+ recoverReads(runtime);
55
+ return reloading;
56
+ }
57
+ async function reloadNow(runtime, replacing, progress, held, installing) {
58
+ const { store, socket, presence } = runtime;
59
+ const { lanes } = socket;
60
+ const discovered = presence.rooms();
61
+ const reloaded = discovered.filter((room) => held.has(room.locator) && !installing.has(room.locator) && replacing(room));
62
+ const acquired = discovered.filter((room) => (!held.has(room.locator) || installing.has(room.locator)) &&
63
+ room.replica.admission === 'admitted' &&
64
+ replacing(room));
65
+ for (const room of reloaded)
66
+ presence.reload(room.locator, true);
67
+ try {
68
+ const local = await store.open();
69
+ const kept = acquired.length === 0 ? new Set() : (await local.held()).staged;
70
+ for (const room of reloaded) {
71
+ void lanes
72
+ .roomTask(room.locator, (live) => reload(runtime, room, local, progress, live))
73
+ .then(() => rest(runtime, progress));
74
+ }
75
+ for (const room of acquired) {
76
+ const unheld = installing.has(room.locator) ? undefined : { staged: kept.has(room.locator) };
77
+ void lanes
78
+ .roomTask(room.locator, (live) => loadRoom(runtime, room, local, progress, live, unheld))
79
+ .then(() => rest(runtime, progress));
80
+ }
81
+ }
82
+ catch {
83
+ for (const room of reloaded)
84
+ presence.reload(room.locator, false);
85
+ progress.reachable = false;
86
+ }
87
+ }
88
+ function caughtUpRooms(runtime, expired) {
89
+ const { store, socket, presence } = runtime;
90
+ const { session } = socket;
91
+ const progress = session.now().underway;
92
+ session.set({ underway: null });
93
+ socket.named();
94
+ const cycle = progress ?? { complete: true, reachable: true };
95
+ replaced(store, expired);
96
+ const installing = store.installs.underway();
97
+ const held = progress === null ? store.rooms(expired) : store.rooms();
98
+ const reloading = progress === null
99
+ ? Promise.resolve([])
100
+ : held.then((stored) => owedReloads(runtime, expired, stored));
101
+ const replacing = Promise.all([held, reloading]).then(([stored, owed]) => reloadNow(runtime, (room) => expired.includes(room.locator) || owed.includes(room.locator), cycle, stored, installing));
102
+ return socket.lanes.task(OPENING_LANE, async (live) => {
103
+ if (!live())
104
+ return;
105
+ if (progress === null) {
106
+ await replacing;
107
+ await rest(runtime, cycle, live);
108
+ return;
109
+ }
110
+ try {
111
+ const local = await store.open();
112
+ await replacing;
113
+ if (progress.reachable) {
114
+ const stored = await held;
115
+ const owed = await reloading;
116
+ await settleModels(runtime, new Map(presence
117
+ .rooms()
118
+ .filter((room) => stored.has(room.locator) &&
119
+ !expired.includes(room.locator) &&
120
+ !owed.includes(room.locator))
121
+ .map((room) => [room.locator, declared(room)])), 'current', local);
122
+ }
123
+ }
124
+ catch {
125
+ progress.complete = false;
126
+ progress.reachable = false;
127
+ }
128
+ if (live())
129
+ await finishOpening(runtime, progress, live);
130
+ });
131
+ }
132
+ function signalled(runtime, mode) {
133
+ const { store, socket, journal } = runtime;
134
+ const { session } = socket;
135
+ const { closed, serviceMode, haltedRefusal, openSignals } = session.now();
136
+ if (closed)
137
+ return;
138
+ if (mode === 'open')
139
+ session.set({ openSignals: openSignals + 1 });
140
+ const releasing = mode === 'open' && (haltedRefusal || serviceMode === 'write-halted');
141
+ if (mode === 'open')
142
+ session.set({ haltedRefusal: false });
143
+ if (mode !== serviceMode) {
144
+ session.set({ serviceMode: mode });
145
+ store.readiness.queue();
146
+ journal.record(`service mode ${mode}`);
147
+ store.tell(SERVICE_MODE_TOPIC, mode);
148
+ }
149
+ if (releasing)
150
+ void submissionDue(runtime);
151
+ }
152
+ async function runCurrency(runtime, live) {
153
+ const { socket, conversations } = runtime;
154
+ const { session } = socket;
155
+ if (session.now().currencyQueued === socket.generation())
156
+ session.set({ currencyQueued: null });
157
+ if (!live())
158
+ return;
159
+ await reconcileConversations(conversations);
160
+ if (conversations.current()) {
161
+ show(runtime);
162
+ return;
163
+ }
164
+ const progress = {
165
+ complete: false,
166
+ reachable: !session.now().moving.providerUnreachable,
167
+ };
168
+ moveTo(runtime, transferring(runtime));
169
+ try {
170
+ await catchUpConversations(conversations, progress);
171
+ }
172
+ catch {
173
+ progress.reachable = false;
174
+ }
175
+ await rest(runtime, progress, live);
176
+ }
177
+ export function scheduleCurrency(runtime) {
178
+ const { socket } = runtime;
179
+ const { session } = socket;
180
+ if (session.now().currencyQueued === socket.generation() || socket.closed() || socket.stopping())
181
+ return;
182
+ session.set({ currencyQueued: socket.generation() });
183
+ void socket.lanes.task(CONVERSATION_LANE, (live) => runCurrency(runtime, live));
184
+ }
185
+ export function spaceFreed(runtime) {
186
+ const { store, socket, journal } = runtime;
187
+ store.prepareAgain();
188
+ journal.record('space freed');
189
+ store.readiness.queue();
190
+ const { closed, authorization } = socket.session.now();
191
+ if (closed || authorization === undefined)
192
+ return;
193
+ if (!socket.streamed)
194
+ void sync(runtime, 'unstreamed', null);
195
+ else
196
+ void resynchronize(runtime);
197
+ }
198
+ export function close({ store, socket, presence, conversations, recovery, liveQueries, figures, }) {
199
+ if (socket.closed())
200
+ return;
201
+ socket.close();
202
+ presence.close();
203
+ conversations.close();
204
+ void recovery.retire();
205
+ liveQueries.close();
206
+ figures.close();
207
+ store.close();
208
+ }
209
+ export async function stop(runtime) {
210
+ const { store, socket, presence, recovery } = runtime;
211
+ socket.session.set({ stopping: true });
212
+ presence.stopAsking();
213
+ socket.stopReads();
214
+ await recovery.retire();
215
+ await socket.lanes.finished();
216
+ await store.written();
217
+ close(runtime);
218
+ }
219
+ export function start(runtime, signal) {
220
+ const { store, socket, presence, conversations, lastAnswers, recovery } = runtime;
221
+ const closeRuntime = () => close(runtime);
222
+ socket.observeServiceMode((mode) => signalled(runtime, mode));
223
+ socket.observeConversations((event) => {
224
+ if (event.kind === 'list' || event.kind === 'listed' || event.kind === 'unlisted')
225
+ store.readiness.queue();
226
+ receiveConversationEvent(conversations, event);
227
+ if (event.kind !== 'gap' || conversations.current())
228
+ return;
229
+ show(runtime);
230
+ scheduleCurrency(runtime);
231
+ });
232
+ signal?.addEventListener('abort', closeRuntime, { once: true });
233
+ if (signal?.aborted)
234
+ closeRuntime();
235
+ socket.observe((event) => {
236
+ if (event.kind === 'opened') {
237
+ presence.connectionLive();
238
+ conversations.reopened();
239
+ lastAnswers.reopened();
240
+ recovery.resume();
241
+ }
242
+ else if (event.kind === 'discovered') {
243
+ if (event.missed)
244
+ countAuthorityChange(runtime);
245
+ void sync(runtime, 'opened', event.discovery);
246
+ }
247
+ else if (event.kind === 'closed') {
248
+ closedSocket(runtime, event.revoked, event.lost, event.opened);
249
+ }
250
+ else if (event.kind === 'caught-up')
251
+ void caughtUpRooms(runtime, event.expired);
252
+ else if (event.kind === 'authority-changed') {
253
+ if (socket.isAnnounced() && socket.isOpen())
254
+ fenceLive(runtime, event.left);
255
+ void changeAuthority(runtime, event);
256
+ }
257
+ else
258
+ void applyRoom(runtime, event);
259
+ });
260
+ void store
261
+ .open()
262
+ .then(async (local) => {
263
+ if ((await local.facts()).capabilities.length > 0)
264
+ socket.readyFromStore();
265
+ })
266
+ .catch((error) => {
267
+ socket.readyFromStore();
268
+ uncaught(error);
269
+ });
270
+ if (!socket.streamed)
271
+ void sync(runtime, 'unstreamed', null);
272
+ }
@@ -0,0 +1,48 @@
1
+ import type { HeldRooms } from '@agentshouse/mdmodel';
2
+ import type { DiscoveredRoom, HeldRoom, OperationScopes, ProviderRefusal, ReplicaAdmission, RoomDeclaration } from './adapter.js';
3
+ import type { Composition } from './collection.js';
4
+ import { type ModelState, type TypesResult } from './model.js';
5
+ import { type PortReach } from './reach.js';
6
+ import type { ReplicaRecord } from './replica.js';
7
+ import type { Runtime } from './runtime.js';
8
+ import type { Stored } from './store.js';
9
+ export type AppTypedSelection = {
10
+ roots: readonly string[];
11
+ model: TypesResult;
12
+ };
13
+ export type AppRoom = {
14
+ name: string;
15
+ locator: string;
16
+ handle: string;
17
+ operations: OperationScopes;
18
+ replica: ReplicaAdmission;
19
+ model: TypesResult;
20
+ typedSelection: AppTypedSelection | null;
21
+ providerOwnedPaths: readonly string[];
22
+ authoredPaths: readonly string[];
23
+ roomVersion: string | null;
24
+ documents: number;
25
+ synchronizationAvailable: boolean;
26
+ refusal: ProviderRefusal | null;
27
+ locked: boolean;
28
+ };
29
+ type ListedRoom = Omit<AppRoom, 'documents' | 'locked'>;
30
+ type ListedEntry = ListedRoom & {
31
+ readonly documents: number;
32
+ };
33
+ export type Listing = ReadonlyMap<string, ListedEntry>;
34
+ export declare function modelIn({ socket, presence }: Runtime, locator: string, stored: Stored | undefined): ModelState;
35
+ export declare function compositionFor(runtime: Runtime, record: ReplicaRecord): Composition;
36
+ export declare function declarationOf({ presence }: Runtime, locator: string, stored: Stored | undefined): {
37
+ readonly room: RoomDeclaration;
38
+ readonly available: boolean;
39
+ } | undefined;
40
+ export declare function listedLocators({ presence }: Runtime, held: ReadonlyMap<string, unknown>): string[];
41
+ export declare function patchedListing(runtime: Runtime, changed: ReadonlySet<string>): Promise<Listing | null>;
42
+ export declare function listingNow(runtime: Runtime): Promise<Listing>;
43
+ export declare function shownRooms({ presence }: Runtime, listing: Listing): readonly AppRoom[];
44
+ export declare function roomFacts(runtime: Runtime, reach?: PortReach | null): Promise<HeldRooms>;
45
+ export declare function heldRooms({ store }: Runtime, listed: readonly DiscoveredRoom[]): Promise<HeldRoom[]>;
46
+ export declare function name(runtime: Runtime, locator: string): Promise<void>;
47
+ export {};
48
+ //# sourceMappingURL=listing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listing.d.ts","sourceRoot":"","sources":["../src/listing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,139 @@
1
+ import { declared } from './declaration.js';
2
+ import { modelTypes, NO_MODEL } from './model.js';
3
+ import { governs, holds } from './reach.js';
4
+ export function modelIn({ socket, presence }, locator, stored) {
5
+ if (socket.session.now().refusal?.code === 'revoked-authorization')
6
+ return { status: 'unavailable', reason: 'revoked' };
7
+ return stored?.record.model ?? presence.unheldModel(locator) ?? NO_MODEL;
8
+ }
9
+ export function compositionFor(runtime, record) {
10
+ return runtime.store.composed({
11
+ ...record,
12
+ model: modelIn(runtime, record.locator, { record, indexed: true, documents: 0 }),
13
+ });
14
+ }
15
+ export function declarationOf({ presence }, locator, stored) {
16
+ const listed = presence.room(locator);
17
+ const room = stored?.record.declaration ?? (listed === undefined ? undefined : declared(listed));
18
+ if (room === undefined)
19
+ return undefined;
20
+ return {
21
+ room,
22
+ available: presence.available(locator, stored?.record.declaration.replica.selection),
23
+ };
24
+ }
25
+ export function listedLocators({ presence }, held) {
26
+ const listed = presence.rooms().map(({ locator }) => locator);
27
+ return [...new Set([...listed, ...held.keys()])];
28
+ }
29
+ function selectionModel({ socket, builtIn }) {
30
+ return socket.session.now().refusal?.code === 'revoked-authorization'
31
+ ? { status: 'unavailable', reason: 'revoked' }
32
+ : builtIn;
33
+ }
34
+ function listedRoom(runtime, locator, stored) {
35
+ const declaration = declarationOf(runtime, locator, stored);
36
+ if (declaration === undefined)
37
+ return undefined;
38
+ const { room, available } = declaration;
39
+ const selection = room.typedSelection;
40
+ return {
41
+ name: room.name,
42
+ locator,
43
+ handle: room.handle,
44
+ operations: room.operations,
45
+ replica: room.replica,
46
+ model: modelTypes(modelIn(runtime, locator, stored)),
47
+ typedSelection: selection === null
48
+ ? null
49
+ : { roots: selection.roots, model: modelTypes(selectionModel(runtime)) },
50
+ providerOwnedPaths: room.providerOwnedPaths,
51
+ authoredPaths: room.authoredPaths,
52
+ roomVersion: stored?.record.roomVersion ?? null,
53
+ synchronizationAvailable: available,
54
+ refusal: runtime.presence.refusal(locator),
55
+ documents: stored?.documents ?? 0,
56
+ };
57
+ }
58
+ function listingOf(runtime, held) {
59
+ const listing = new Map();
60
+ for (const locator of listedLocators(runtime, held)) {
61
+ const room = listedRoom(runtime, locator, held.get(locator));
62
+ if (room !== undefined)
63
+ listing.set(locator, room);
64
+ }
65
+ return listing;
66
+ }
67
+ export async function patchedListing(runtime, changed) {
68
+ const { store } = runtime;
69
+ const { roomsShown } = store.device.now();
70
+ if (roomsShown === null)
71
+ return null;
72
+ const held = await store.rooms([...changed]);
73
+ const listing = new Map(roomsShown);
74
+ for (const locator of changed) {
75
+ const room = listedRoom(runtime, locator, held.get(locator));
76
+ if (room === undefined || !listing.has(locator))
77
+ return null;
78
+ listing.set(locator, room);
79
+ }
80
+ return listing;
81
+ }
82
+ export async function listingNow(runtime) {
83
+ return listingOf(runtime, await runtime.store.rooms());
84
+ }
85
+ export function shownRooms({ presence }, listing) {
86
+ const locked = new Set(presence.lockedAmong(new Map([...listing].map(([locator, room]) => [locator, room.replica.offline]))));
87
+ return structuredClone([...listing.values()].map(({ documents, ...room }) => locked.has(room.locator)
88
+ ? {
89
+ ...room,
90
+ model: modelTypes(NO_MODEL),
91
+ typedSelection: null,
92
+ documents: 0,
93
+ locked: true,
94
+ }
95
+ : { ...room, documents, locked: false }));
96
+ }
97
+ export async function roomFacts(runtime, reach = null) {
98
+ const { store, socket, builtIn } = runtime;
99
+ const held = await store.rooms();
100
+ const rooms = [...listingOf(runtime, held).values()]
101
+ .filter((room) => holds(reach, room.locator))
102
+ .map((room) => {
103
+ const governed = governs(reach, room);
104
+ const attached = [
105
+ ...(governed.collection ? [modelIn(runtime, room.locator, held.get(room.locator))] : []),
106
+ ...(governed.selection ? [builtIn] : []),
107
+ ];
108
+ return {
109
+ locator: room.locator,
110
+ available: attached.every((model) => model.status !== 'unavailable'),
111
+ types: attached.flatMap((model) => model.status === 'unavailable' ? [] : Object.values(model.types)),
112
+ };
113
+ });
114
+ return { listed: socket.session.now().roomsListed, rooms };
115
+ }
116
+ export async function heldRooms({ store }, listed) {
117
+ const stored = await store.rooms(listed.map((room) => room.locator));
118
+ return listed.flatMap((room) => {
119
+ const record = stored.get(room.locator)?.record;
120
+ if (record === undefined) {
121
+ return room.replica.admission === 'admitted'
122
+ ? [{ locator: room.locator, roomVersion: null }]
123
+ : [];
124
+ }
125
+ if (record.declaration.replica.selection !== room.replica.selection)
126
+ return [];
127
+ return [{ locator: room.locator, roomVersion: record.roomVersion }];
128
+ });
129
+ }
130
+ export async function name(runtime, locator) {
131
+ const { socket, presence } = runtime;
132
+ const room = presence.room(locator);
133
+ if (!socket.streamed || room === undefined || !socket.isOpen() || !socket.isHanded())
134
+ return;
135
+ const [held] = await heldRooms(runtime, [room]);
136
+ if (held === undefined || !socket.isOpen() || !socket.isHanded())
137
+ return;
138
+ socket.name(held);
139
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../src/live.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,KAAK,GAAG;IAAE,QAAQ,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,SAAS,SAAS,EAAE,CAAA;CAAE,GAAG,aAAa,CAAC;AAE7F,MAAM,MAAM,GAAG,GAAG,WAAW,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAA;CAAE,CAAC;AAEpE,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;AAE5E,KAAK,QAAQ,GAAG,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;AAchD,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;IAC3B,OAAO,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IAC9B,OAAO,IAAI,IAAI,CAAC;IAChB,KAAK,CACH,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,KAAK,EACzB,OAAO,EAAE,QAAQ,EACjB,MAAM,EAAE,IAAI,GACX,MAAM,IAAI,CAAC;IACd,KAAK,IAAI,IAAI,CAAC;CACf,CAAC;AAmCF,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CA4HxF"}
1
+ {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../src/live.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,KAAK,GAAG;IAAE,QAAQ,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,SAAS,SAAS,EAAE,CAAA;CAAE,GAAG,aAAa,CAAC;AAE7F,MAAM,MAAM,GAAG,GAAG,WAAW,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAA;CAAE,CAAC;AAEpE,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;AAE5E,KAAK,QAAQ,GAAG,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;AAchD,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;IAC3B,OAAO,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IAC9B,OAAO,IAAI,IAAI,CAAC;IAChB,KAAK,CACH,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,KAAK,EACzB,OAAO,EAAE,QAAQ,EACjB,MAAM,EAAE,IAAI,GACX,MAAM,IAAI,CAAC;IACd,KAAK,IAAI,IAAI,CAAC;CACf,CAAC;AAmCF,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CA2HxF"}
package/dist/live.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { changeOf, digestOf, } from './observation.js';
2
+ import { uncaught } from './failure.js';
2
3
  import { roomOfKey } from './rows.js';
3
4
  function narrowed(plan) {
4
5
  return (plan.paths !== null &&
@@ -76,7 +77,6 @@ export function createLiveQueries(run, holding) {
76
77
  }
77
78
  }
78
79
  catch (error) {
79
- entry.dirty = false;
80
80
  const unanswered = [...entry.fresh.values()];
81
81
  entry.fresh.clear();
82
82
  for (const failed of unanswered)
@@ -113,8 +113,8 @@ export function createLiveQueries(run, holding) {
113
113
  }
114
114
  } while (recoverAgain && !closed);
115
115
  }
116
- catch {
117
- recoverAgain = false;
116
+ catch (error) {
117
+ uncaught(error);
118
118
  }
119
119
  finally {
120
120
  recovering = false;
@@ -0,0 +1,7 @@
1
+ import type { Runtime } from './runtime.js';
2
+ export declare function locked({ store, presence }: Runtime, locator: string): Promise<boolean>;
3
+ export declare function lockedRooms({ store, presence }: Runtime): Promise<readonly string[]>;
4
+ export declare function relocked(runtime: Runtime, before: readonly string[]): Promise<void>;
5
+ export declare function connectionLost(runtime: Runtime): void;
6
+ export declare function watchLocks({ store }: Runtime, notify: () => void): () => void;
7
+ //# sourceMappingURL=locks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locks.d.ts","sourceRoot":"","sources":["../src/locks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAG5C,wBAAsB,MAAM,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAE5F;AAED,wBAAsB,WAAW,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAK1F;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,iBAMzE;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,QAU9C;AAED,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAE7E"}
package/dist/locks.js ADDED
@@ -0,0 +1,33 @@
1
+ import { uncaught } from './failure.js';
2
+ import { emitRooms, LOCKS_TOPIC } from './shown.js';
3
+ export async function locked({ store, presence }, locator) {
4
+ return presence.locked(locator, async () => (await store.open()).offline(locator));
5
+ }
6
+ export async function lockedRooms({ store, presence }) {
7
+ const held = (await store.covering()).rooms;
8
+ return presence.lockedAmong(new Map([...held].map(([locator, { offline }]) => [locator, offline])));
9
+ }
10
+ export async function relocked(runtime, before) {
11
+ const after = await lockedRooms(runtime);
12
+ if (JSON.stringify(after) === JSON.stringify(before))
13
+ return;
14
+ runtime.journal.record(`locked ${after.length}`);
15
+ emitRooms(runtime);
16
+ runtime.store.tell(LOCKS_TOPIC, undefined);
17
+ }
18
+ export function connectionLost(runtime) {
19
+ const { socket, presence } = runtime;
20
+ if (socket.closed())
21
+ return;
22
+ presence.connectionLost(() => {
23
+ if (socket.isOpen() || socket.closed())
24
+ return;
25
+ void lockedRooms(runtime).then((before) => {
26
+ presence.lapse();
27
+ return relocked(runtime, before);
28
+ }, uncaught);
29
+ });
30
+ }
31
+ export function watchLocks({ store }, notify) {
32
+ return store.watch(LOCKS_TOPIC, notify).stop;
33
+ }
package/dist/log.d.ts CHANGED
@@ -2,4 +2,5 @@ export declare function createLog(): {
2
2
  record(event: string): void;
3
3
  export(): string;
4
4
  };
5
+ export type Log = ReturnType<typeof createLog>;
5
6
  //# sourceMappingURL=log.d.ts.map
package/dist/log.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAEA,wBAAgB,SAAS;IAGrB,MAAM,QAAQ,MAAM;IAIpB,MAAM;EAIT"}
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAEA,wBAAgB,SAAS;IAGrB,MAAM,QAAQ,MAAM;IAIpB,MAAM;EAIT;AAED,MAAM,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC"}
package/dist/lost.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import type { Runtime } from './runtime.js';
2
+ export declare function eraseFenced({ store }: Runtime, locators: readonly string[]): Promise<void>;
3
+ export declare function fenceLive(runtime: Runtime, locators: readonly string[]): void;
4
+ export declare function loseRooms(runtime: Runtime, locators: readonly string[]): Promise<void>;
5
+ //# sourceMappingURL=lost.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lost.d.ts","sourceRoot":"","sources":["../src/lost.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAK5C,wBAAsB,WAAW,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,iBAIhF;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,QAOtE;AAED,wBAAsB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,iBA+B5E"}
package/dist/lost.js ADDED
@@ -0,0 +1,50 @@
1
+ import { changeSet, mergeChangeSets } from './change-set.js';
2
+ import { ERASE_BATCH } from './install.js';
3
+ import { unpair } from './queue.js';
4
+ import { recoverReads } from './shown.js';
5
+ import { yielded } from './turn.js';
6
+ export async function eraseFenced({ store }, locators) {
7
+ for (const locator of locators) {
8
+ while (await store.durably((local) => local.erase(locator, ERASE_BATCH)))
9
+ await yielded();
10
+ }
11
+ }
12
+ export function fenceLive(runtime, locators) {
13
+ const { store, socket, presence, journal } = runtime;
14
+ for (const locator of new Set(locators)) {
15
+ if (!presence.lose(locator, socket.session.now().discoveries))
16
+ continue;
17
+ store.forget(locator);
18
+ journal.record(`room lost ${locator}`);
19
+ }
20
+ }
21
+ export async function loseRooms(runtime, locators) {
22
+ const { store, presence } = runtime;
23
+ fenceLive(runtime, locators);
24
+ const fresh = [...new Set(locators)].filter((locator) => presence.writing(locator));
25
+ if (fresh.length === 0)
26
+ return;
27
+ let held = [];
28
+ try {
29
+ await store.durably(async (local) => {
30
+ held = await local.roomDrafts();
31
+ await local.fence(fresh);
32
+ });
33
+ }
34
+ catch (error) {
35
+ for (const locator of fresh)
36
+ presence.unwritten(locator);
37
+ throw error;
38
+ }
39
+ finally {
40
+ store.changed(mergeChangeSets(fresh.map((locator) => changeSet(locator, {
41
+ documents: null,
42
+ room: true,
43
+ queue: true,
44
+ drafts: held.filter((draft) => draft.locator === locator).map(({ path }) => path),
45
+ }))));
46
+ recoverReads(runtime);
47
+ }
48
+ await unpair(runtime);
49
+ await eraseFenced(runtime, fresh);
50
+ }
package/dist/media.d.ts CHANGED
@@ -3,6 +3,6 @@ import { type ShownAnswer } from './outcome.js';
3
3
  export declare const ROOM_MEDIA = "room-media";
4
4
  type Show = (room: string, path: string, revision?: string) => Promise<ShownAnswer>;
5
5
  export declare function shownBy(show: Show, client: MdRuntimeClient): MdRuntimeClient;
6
- export declare function defineRoomMedia(client: Promise<MdRuntimeClient> | MdRuntimeClient, registry?: CustomElementRegistry): void;
6
+ export declare function defineRoomMedia(client: Promise<MdRuntimeClient> | MdRuntimeClient): void;
7
7
  export {};
8
8
  //# sourceMappingURL=media.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../src/media.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3D,eAAO,MAAM,UAAU,eAAe,CAAC;AAwBvC,KAAK,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;AAIpF,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,GAAG,eAAe,CAG5E;AAsBD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,eAAe,EAClD,QAAQ,GAAE,qBAAsC,GAC/C,IAAI,CA0LN"}
1
+ {"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../src/media.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3D,eAAO,MAAM,UAAU,eAAe,CAAC;AAwBvC,KAAK,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;AAIpF,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,GAAG,eAAe,CAG5E;AAsBD,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,eAAe,GAAG,IAAI,CA0LxF"}
package/dist/media.js CHANGED
@@ -37,8 +37,8 @@ function drawnFor(mediaType) {
37
37
  return 'audio';
38
38
  return null;
39
39
  }
40
- export function defineRoomMedia(client, registry = customElements) {
41
- if (registry.get(ROOM_MEDIA) !== undefined)
40
+ export function defineRoomMedia(client) {
41
+ if (customElements.get(ROOM_MEDIA) !== undefined)
42
42
  return;
43
43
  const connected = Promise.resolve(client);
44
44
  class RoomMedia extends HTMLElement {
@@ -179,7 +179,7 @@ export function defineRoomMedia(client, registry = customElements) {
179
179
  if (drawn instanceof HTMLMediaElement) {
180
180
  drawn.controls = true;
181
181
  drawn.preload = 'metadata';
182
- if (drawn instanceof HTMLVideoElement)
182
+ if (drawn instanceof HTMLVideoElement && 'playsInline' in drawn)
183
183
  drawn.playsInline = true;
184
184
  }
185
185
  drawn.addEventListener(drawn instanceof HTMLImageElement ? 'load' : 'loadedmetadata', () => {
@@ -214,5 +214,5 @@ export function defineRoomMedia(client, registry = customElements) {
214
214
  void this.#load();
215
215
  }
216
216
  }
217
- registry.define(ROOM_MEDIA, RoomMedia);
217
+ customElements.define(ROOM_MEDIA, RoomMedia);
218
218
  }