@agentshouse/mdruntime 0.1.0-c2aaa9c0e3ca4 → 0.1.0-c2e8a6f99866d

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 (214) hide show
  1. package/AGENTS.md +289 -276
  2. package/README.md +9 -8
  3. package/dist/adapter.d.ts +91 -23
  4. package/dist/adapter.d.ts.map +1 -1
  5. package/dist/attached-model.d.ts +4 -1
  6. package/dist/attached-model.d.ts.map +1 -1
  7. package/dist/attached-model.js +13 -3
  8. package/dist/attempt.d.ts.map +1 -1
  9. package/dist/attempt.js +14 -1
  10. package/dist/bootstrap.d.ts +16 -8
  11. package/dist/bootstrap.d.ts.map +1 -1
  12. package/dist/bootstrap.js +102 -47
  13. package/dist/chain.d.ts +11 -0
  14. package/dist/chain.d.ts.map +1 -0
  15. package/dist/chain.js +64 -0
  16. package/dist/change-set.d.ts +9 -8
  17. package/dist/change-set.d.ts.map +1 -1
  18. package/dist/change-set.js +10 -59
  19. package/dist/change.d.ts +31 -1
  20. package/dist/change.d.ts.map +1 -1
  21. package/dist/change.js +10 -1
  22. package/dist/chat/acts.d.ts +3 -4
  23. package/dist/chat/acts.d.ts.map +1 -1
  24. package/dist/chat/acts.js +10 -10
  25. package/dist/chat/earlier.d.ts +10 -0
  26. package/dist/chat/earlier.d.ts.map +1 -0
  27. package/dist/chat/earlier.js +54 -0
  28. package/dist/chat/house.d.ts +25 -0
  29. package/dist/chat/house.d.ts.map +1 -0
  30. package/dist/chat/house.js +38 -0
  31. package/dist/chat/input.d.ts +3 -1
  32. package/dist/chat/input.d.ts.map +1 -1
  33. package/dist/chat/input.js +11 -18
  34. package/dist/chat/kit.d.ts +2 -1
  35. package/dist/chat/kit.d.ts.map +1 -1
  36. package/dist/chat/kit.js +3 -3
  37. package/dist/chat/list.d.ts +9 -1
  38. package/dist/chat/list.d.ts.map +1 -1
  39. package/dist/chat/list.js +53 -9
  40. package/dist/chat/markdown.d.ts +3 -1
  41. package/dist/chat/markdown.d.ts.map +1 -1
  42. package/dist/chat/markdown.js +85 -26
  43. package/dist/chat/message.d.ts +1 -0
  44. package/dist/chat/message.d.ts.map +1 -1
  45. package/dist/chat/message.js +65 -13
  46. package/dist/chat/messages.d.ts +10 -1
  47. package/dist/chat/messages.d.ts.map +1 -1
  48. package/dist/chat/messages.js +70 -23
  49. package/dist/chat/name.d.ts +1 -0
  50. package/dist/chat/name.d.ts.map +1 -1
  51. package/dist/chat/name.js +1 -1
  52. package/dist/chat/opened.d.ts +1 -0
  53. package/dist/chat/opened.d.ts.map +1 -1
  54. package/dist/chat/opened.js +2 -0
  55. package/dist/chat/overlay.d.ts +1 -0
  56. package/dist/chat/overlay.d.ts.map +1 -1
  57. package/dist/chat/overlay.js +11 -5
  58. package/dist/chat/parts.d.ts +1 -0
  59. package/dist/chat/parts.d.ts.map +1 -1
  60. package/dist/chat/parts.js +3 -2
  61. package/dist/chat/pieces.d.ts +62 -0
  62. package/dist/chat/pieces.d.ts.map +1 -0
  63. package/dist/chat/pieces.js +1110 -0
  64. package/dist/chat/provider.d.ts +9 -2
  65. package/dist/chat/provider.d.ts.map +1 -1
  66. package/dist/chat/provider.js +146 -156
  67. package/dist/chat/question.d.ts +1 -1
  68. package/dist/chat/question.d.ts.map +1 -1
  69. package/dist/chat/question.js +7 -18
  70. package/dist/chat/ready.d.ts +5 -1
  71. package/dist/chat/ready.d.ts.map +1 -1
  72. package/dist/chat/ready.js +9 -7
  73. package/dist/chat/room-file.d.ts +8 -0
  74. package/dist/chat/room-file.d.ts.map +1 -0
  75. package/dist/chat/room-file.js +72 -0
  76. package/dist/chat/steady.d.ts +3 -0
  77. package/dist/chat/steady.d.ts.map +1 -0
  78. package/dist/chat/steady.js +26 -0
  79. package/dist/chat/style.d.ts.map +1 -1
  80. package/dist/chat/style.js +8 -4
  81. package/dist/chat.d.ts +3 -2
  82. package/dist/chat.d.ts.map +1 -1
  83. package/dist/chat.js +2 -2
  84. package/dist/client.d.ts +22 -9
  85. package/dist/client.d.ts.map +1 -1
  86. package/dist/client.js +48 -8
  87. package/dist/collection.d.ts +7 -6
  88. package/dist/collection.d.ts.map +1 -1
  89. package/dist/collection.js +31 -77
  90. package/dist/compile.d.ts +11 -0
  91. package/dist/compile.d.ts.map +1 -0
  92. package/dist/compile.js +712 -0
  93. package/dist/connection.d.ts +41 -13
  94. package/dist/connection.d.ts.map +1 -1
  95. package/dist/connection.js +3264 -690
  96. package/dist/conversation.d.ts +28 -9
  97. package/dist/conversation.d.ts.map +1 -1
  98. package/dist/conversation.js +520 -176
  99. package/dist/digest.d.ts +7 -0
  100. package/dist/digest.d.ts.map +1 -0
  101. package/dist/digest.js +113 -0
  102. package/dist/durability.d.ts +8 -1
  103. package/dist/durability.d.ts.map +1 -1
  104. package/dist/entry.d.ts +19 -0
  105. package/dist/entry.d.ts.map +1 -0
  106. package/dist/entry.js +151 -0
  107. package/dist/fence.d.ts +6 -0
  108. package/dist/fence.d.ts.map +1 -0
  109. package/dist/fence.js +10 -0
  110. package/dist/file.d.ts +2 -10
  111. package/dist/file.d.ts.map +1 -1
  112. package/dist/file.js +3 -120
  113. package/dist/host.d.ts +15 -3
  114. package/dist/host.d.ts.map +1 -1
  115. package/dist/host.js +103 -13
  116. package/dist/identity.d.ts +2 -0
  117. package/dist/identity.d.ts.map +1 -1
  118. package/dist/identity.js +6 -0
  119. package/dist/index.d.ts +15 -9
  120. package/dist/index.d.ts.map +1 -1
  121. package/dist/index.js +5 -0
  122. package/dist/live.d.ts +22 -0
  123. package/dist/live.d.ts.map +1 -0
  124. package/dist/live.js +123 -0
  125. package/dist/memory.d.ts +9 -2
  126. package/dist/memory.d.ts.map +1 -1
  127. package/dist/memory.js +55 -12
  128. package/dist/model.d.ts +4 -2
  129. package/dist/model.d.ts.map +1 -1
  130. package/dist/model.js +10 -1
  131. package/dist/name.d.ts +4 -0
  132. package/dist/name.d.ts.map +1 -0
  133. package/dist/name.js +122 -0
  134. package/dist/observation.d.ts +19 -2
  135. package/dist/observation.d.ts.map +1 -1
  136. package/dist/observation.js +113 -12
  137. package/dist/opened.d.ts +22 -0
  138. package/dist/opened.d.ts.map +1 -0
  139. package/dist/opened.js +107 -0
  140. package/dist/outcome.d.ts +39 -4
  141. package/dist/outcome.d.ts.map +1 -1
  142. package/dist/outcome.js +29 -0
  143. package/dist/overlay.d.ts +3 -4
  144. package/dist/overlay.d.ts.map +1 -1
  145. package/dist/overlay.js +99 -181
  146. package/dist/query.d.ts +57 -4
  147. package/dist/query.d.ts.map +1 -1
  148. package/dist/query.js +37 -7
  149. package/dist/reach.d.ts +11 -4
  150. package/dist/reach.d.ts.map +1 -1
  151. package/dist/reach.js +182 -51
  152. package/dist/react.d.ts +8 -6
  153. package/dist/react.d.ts.map +1 -1
  154. package/dist/react.js +7 -17
  155. package/dist/readiness.d.ts +53 -0
  156. package/dist/readiness.d.ts.map +1 -0
  157. package/dist/readiness.js +33 -0
  158. package/dist/reads.d.ts +11 -0
  159. package/dist/reads.d.ts.map +1 -0
  160. package/dist/reads.js +98 -0
  161. package/dist/recovery.d.ts +25 -0
  162. package/dist/recovery.d.ts.map +1 -0
  163. package/dist/recovery.js +198 -0
  164. package/dist/refresh.d.ts +12 -15
  165. package/dist/refresh.d.ts.map +1 -1
  166. package/dist/refresh.js +74 -44
  167. package/dist/replica.d.ts +55 -33
  168. package/dist/replica.d.ts.map +1 -1
  169. package/dist/replica.js +295 -149
  170. package/dist/room-draft.d.ts +16 -2
  171. package/dist/room-draft.d.ts.map +1 -1
  172. package/dist/room-draft.js +32 -25
  173. package/dist/rows.d.ts +28 -37
  174. package/dist/rows.d.ts.map +1 -1
  175. package/dist/rows.js +113 -72
  176. package/dist/save.d.ts +50 -9
  177. package/dist/save.d.ts.map +1 -1
  178. package/dist/save.js +528 -166
  179. package/dist/search.d.ts +50 -7
  180. package/dist/search.d.ts.map +1 -1
  181. package/dist/search.js +273 -45
  182. package/dist/seed.d.ts +16 -0
  183. package/dist/seed.d.ts.map +1 -0
  184. package/dist/seed.js +75 -0
  185. package/dist/shared.d.ts +16 -0
  186. package/dist/shared.d.ts.map +1 -0
  187. package/dist/shared.js +431 -0
  188. package/dist/status.d.ts +4 -0
  189. package/dist/status.d.ts.map +1 -1
  190. package/dist/store.d.ts +128 -67
  191. package/dist/store.d.ts.map +1 -1
  192. package/dist/store.js +537 -432
  193. package/dist/stored.d.ts +143 -0
  194. package/dist/stored.d.ts.map +1 -0
  195. package/dist/stored.js +561 -0
  196. package/dist/tables.d.ts +320 -0
  197. package/dist/tables.d.ts.map +1 -0
  198. package/dist/tables.js +537 -0
  199. package/dist/turn.d.ts +9 -0
  200. package/dist/turn.d.ts.map +1 -0
  201. package/dist/turn.js +75 -0
  202. package/dist/validation.d.ts +30 -0
  203. package/dist/validation.d.ts.map +1 -0
  204. package/dist/validation.js +162 -0
  205. package/dist/windows.d.ts +22 -0
  206. package/dist/windows.d.ts.map +1 -0
  207. package/dist/windows.js +89 -0
  208. package/dist/wire.d.ts +168 -32
  209. package/dist/wire.d.ts.map +1 -1
  210. package/dist/wire.js +56 -31
  211. package/package.json +10 -3
  212. package/dist/read-side.d.ts +0 -18
  213. package/dist/read-side.d.ts.map +0 -1
  214. package/dist/read-side.js +0 -440
package/dist/memory.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { sameChange } from './overlay.js';
2
2
  const FIXTURE_RETENTION = {
3
3
  history: { kind: 'duration', seconds: 1 },
4
- outcome: 1,
4
+ outcome: 604_800,
5
5
  refreshHorizon: 1,
6
6
  };
7
7
  function declaredRetention(value) {
@@ -55,6 +55,7 @@ export function createMemoryAdapter(options = {}) {
55
55
  const scripted = new Map();
56
56
  const unsealed = new Map();
57
57
  const sealed = new Set();
58
+ const sentTurns = new Map();
58
59
  const historyPageSize = options.historyPageSize;
59
60
  let held = [];
60
61
  let expiring = [];
@@ -121,17 +122,32 @@ export function createMemoryAdapter(options = {}) {
121
122
  ...(opening ? { models: modelsOf(room) } : {}),
122
123
  documents: named(room.documents ?? {}, taken),
123
124
  revisions: named(room.revisions ?? {}, [...taken, ...targets]),
125
+ ...(room.fileIds === undefined
126
+ ? {}
127
+ : { fileIds: named(room.fileIds, [...taken, ...targets]) }),
124
128
  changes: named(room.changes ?? {}, [...taken, ...targets]),
125
129
  binaryFiles: named(room.binaryFiles ?? {}, targets),
130
+ ...(opening && room.folders !== undefined ? { folders: room.folders } : {}),
126
131
  ...(next < paths.length ? { pageToken: taken.at(-1) } : {}),
127
132
  };
128
133
  }
134
+ function foldersMoved(room, from) {
135
+ const now = new Set(room.folders ?? []);
136
+ const before = new Set(from.folders ?? []);
137
+ const folders = [...now].filter((folder) => !before.has(folder)).sort();
138
+ const folderRemovals = [...before].filter((folder) => !now.has(folder)).sort();
139
+ return {
140
+ ...(folders.length === 0 ? {} : { folders }),
141
+ ...(folderRemovals.length === 0 ? {} : { folderRemovals }),
142
+ };
143
+ }
129
144
  function advancement(room, from, at) {
130
145
  const current = room.documents ?? {};
131
146
  const previous = from.documents ?? {};
132
147
  const currentTargets = new Set(Object.keys(room.binaryFiles ?? {}));
133
148
  const previousTargets = new Set(Object.keys(from.binaryFiles ?? {}));
134
149
  const headMoved = (path) => room.revisions?.[path] !== from.revisions?.[path] ||
150
+ room.fileIds?.[path] !== from.fileIds?.[path] ||
135
151
  !sameChange(room.changes?.[path], from.changes?.[path]);
136
152
  const changed = Object.keys(current)
137
153
  .filter((path) => current[path] !== previous[path] || headMoved(path))
@@ -153,8 +169,12 @@ export function createMemoryAdapter(options = {}) {
153
169
  ...(models === undefined ? {} : { models }),
154
170
  documents: named(current, taken),
155
171
  revisions: named(room.revisions ?? {}, [...taken, ...targets]),
172
+ ...(room.fileIds === undefined
173
+ ? {}
174
+ : { fileIds: named(room.fileIds, [...taken, ...targets]) }),
156
175
  changes: named(room.changes ?? {}, [...taken, ...targets]),
157
176
  binaryFiles: named(room.binaryFiles ?? {}, targets),
177
+ ...(opening ? foldersMoved(room, from) : {}),
158
178
  removals: opening
159
179
  ? [
160
180
  ...Object.keys(previous).filter((path) => !(path in current) && !currentTargets.has(path)),
@@ -220,9 +240,15 @@ export function createMemoryAdapter(options = {}) {
220
240
  if (outcome !== undefined)
221
241
  return outcome;
222
242
  if (name === 'conversation.send') {
243
+ const operation = typeof input.operation_id === 'string' ? input.operation_id : null;
244
+ const answered = operation === null ? undefined : sentTurns.get(operation);
245
+ if (answered !== undefined)
246
+ return { kind: 'action', result: { turn: answered } };
223
247
  issued += 1;
224
248
  const turn = `turn-${issued}`;
225
249
  unsealed.set(turn, named);
250
+ if (operation !== null)
251
+ sentTurns.set(operation, turn);
226
252
  return { kind: 'action', result: { turn } };
227
253
  }
228
254
  if (name === 'conversation.cancel') {
@@ -253,6 +279,7 @@ export function createMemoryAdapter(options = {}) {
253
279
  };
254
280
  }
255
281
  return {
282
+ ...(options.exhaustiveDiscovery === undefined ? {} : { exhaustiveDiscovery: true }),
256
283
  setRooms(next) {
257
284
  rooms = [...next];
258
285
  retain(rooms);
@@ -265,9 +292,9 @@ export function createMemoryAdapter(options = {}) {
265
292
  for (const observer of observers)
266
293
  observer({ kind: 'opened' });
267
294
  },
268
- close(revoked = false) {
295
+ close({ revoked = false, lost = !revoked } = {}) {
269
296
  for (const observer of observers)
270
- observer({ kind: 'closed', revoked });
297
+ observer({ kind: 'closed', revoked, lost });
271
298
  },
272
299
  expire(locators) {
273
300
  expiring = [...locators];
@@ -276,6 +303,13 @@ export function createMemoryAdapter(options = {}) {
276
303
  for (const observer of observers)
277
304
  observer({ kind: 'room-version', locator, roomVersion });
278
305
  },
306
+ notifyAuthorityChanged(scope) {
307
+ for (const observer of observers) {
308
+ observer(scope === undefined
309
+ ? { kind: 'authority-changed' }
310
+ : { kind: 'authority-changed', scope });
311
+ }
312
+ },
279
313
  notifyConversation(event) {
280
314
  if (event.kind === 'accepted-message') {
281
315
  sealed.add(event.message.turn);
@@ -336,17 +370,19 @@ export function createMemoryAdapter(options = {}) {
336
370
  },
337
371
  reopen() {
338
372
  queueMicrotask(() => {
339
- for (const observer of observers)
340
- observer({ kind: 'closed', revoked: false });
373
+ for (const observer of observers) {
374
+ observer({ kind: 'closed', revoked: false, lost: false });
375
+ }
341
376
  });
342
377
  },
378
+ published() { },
343
379
  observe(notify) {
344
380
  observers.add(notify);
345
381
  queueMicrotask(() => {
346
382
  if (!observers.has(notify))
347
383
  return;
348
384
  if (options.unopened === true) {
349
- notify({ kind: 'closed', revoked: false });
385
+ notify({ kind: 'closed', revoked: false, lost: true });
350
386
  return;
351
387
  }
352
388
  announceList();
@@ -429,7 +465,13 @@ export function createMemoryAdapter(options = {}) {
429
465
  retryable: false,
430
466
  affected: {},
431
467
  };
432
- }, request).then((answer) => note(request.locator, answer));
468
+ }, request).then((answer) => {
469
+ const destination = request.changeBatch.between?.destination.room;
470
+ if (answer.kind === 'accepted' && answer.destination !== undefined && destination) {
471
+ note(destination, answer.destination);
472
+ }
473
+ return note(request.locator, answer);
474
+ });
433
475
  },
434
476
  async history(_authorization, request) {
435
477
  return resolveScript(scripts.history, () => {
@@ -454,18 +496,19 @@ export function createMemoryAdapter(options = {}) {
454
496
  const blob = room.blobs?.[request.path];
455
497
  return blob === undefined
456
498
  ? { kind: 'rejected', code: 'file_not_found', fields: {}, retryable: false }
457
- : { kind: 'binary', blob };
499
+ : { kind: 'binary', body: blob.stream(), mediaType: blob.type };
458
500
  }, request);
459
501
  },
502
+ async link(_authorization, request) {
503
+ return resolveScript(scripts.link, () => ({ kind: 'rejected', code: 'unscripted-link', fields: {}, retryable: false }), request);
504
+ },
460
505
  referrerScope(referrer) {
461
506
  if (typeof referrer !== 'object' || referrer === null)
462
507
  return null;
463
- const { room, path, message } = referrer;
464
- if (typeof message === 'string')
465
- return { kind: 'conversations' };
508
+ const { room, path } = referrer;
466
509
  if (typeof room !== 'string')
467
510
  return null;
468
- return { kind: 'room', locator: room, ...(typeof path === 'string' ? { path } : {}) };
511
+ return { locator: room, ...(typeof path === 'string' ? { path } : {}) };
469
512
  },
470
513
  async action(_authorization, request) {
471
514
  return resolveScript(scripts.action, () => {
package/dist/model.d.ts CHANGED
@@ -29,12 +29,13 @@ export type ModelState = {
29
29
  types: VerifiedModel['types'];
30
30
  };
31
31
  export type TypesResult = {
32
- status: 'unavailable';
32
+ status: Open<'unavailable'>;
33
33
  reason: ModelUnavailableReason;
34
+ types: null;
34
35
  schema?: string | null;
35
36
  revision?: string | null;
36
37
  } | {
37
- status: 'current' | 'cached';
38
+ status: Open<'current' | 'cached'>;
38
39
  identity: string;
39
40
  version: string;
40
41
  verifiedWith: ModelIdentity;
@@ -52,5 +53,6 @@ export declare function definitionOf(state: ModelState, type: string | undefined
52
53
  export declare function modelTypes(state: ModelState): TypesResult;
53
54
  export declare function cached(state: ModelState): ModelState;
54
55
  export declare function sameModel(left: ModelIdentity, right: ModelIdentity): boolean;
56
+ export declare function sameTyping(left: ModelState, right: ModelState): boolean;
55
57
  export declare function referenceField(facts: ValueFacts | undefined): boolean;
56
58
  //# sourceMappingURL=model.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,MAAM,aAAa,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAClE,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG;IAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAC/F,MAAM,MAAM,sBAAsB,GAAG,IAAI,CAAC,cAAc,GAAG,SAAS,GAAG,cAAc,GAAG,SAAS,CAAC,CAAC;AACnG,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,MAAM,EAAE,sBAAsB,CAAA;CAAE,CAAC;AAClE,MAAM,MAAM,MAAM,GAAG,UAAU,CAAC;AAChC,MAAM,MAAM,UAAU,GAClB;IACE,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,sBAAsB,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,GACD;IACE,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC7B,QAAQ,EAAE,aAAa,CAAC;IACxB,YAAY,EAAE,aAAa,CAAC;IAC5B,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;CAC/B,CAAC;AACN,MAAM,MAAM,WAAW,GACnB;IACE,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,sBAAsB,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,GACD;IACE,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,aAAa,CAAC;IAC5B,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;AACN,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,CAAC;CACpC,CAAC;AACF,eAAO,MAAM,QAAQ,EAAE,UAA8D,CAAC;AACtF,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAGhG;AACD,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,CAgBzD;AACD,wBAAgB,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAEpD;AACD,wBAAgB,SAAS,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAE5E;AACD,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,CAErE"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,MAAM,aAAa,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAClE,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG;IAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAC/F,MAAM,MAAM,sBAAsB,GAAG,IAAI,CAAC,cAAc,GAAG,SAAS,GAAG,cAAc,GAAG,SAAS,CAAC,CAAC;AACnG,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,MAAM,EAAE,sBAAsB,CAAA;CAAE,CAAC;AAClE,MAAM,MAAM,MAAM,GAAG,UAAU,CAAC;AAChC,MAAM,MAAM,UAAU,GAClB;IACE,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,sBAAsB,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,GACD;IACE,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC7B,QAAQ,EAAE,aAAa,CAAC;IACxB,YAAY,EAAE,aAAa,CAAC;IAC5B,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;CAC/B,CAAC;AACN,MAAM,MAAM,WAAW,GACnB;IACE,MAAM,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;IAC5B,MAAM,EAAE,sBAAsB,CAAC;IAC/B,KAAK,EAAE,IAAI,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,GACD;IACE,MAAM,EAAE,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,CAAC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,aAAa,CAAC;IAC5B,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;AACN,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,CAAC;CACpC,CAAC;AACF,eAAO,MAAM,QAAQ,EAAE,UAA8D,CAAC;AACtF,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAGhG;AACD,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,CAgBzD;AACD,wBAAgB,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAEpD;AACD,wBAAgB,SAAS,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAE5E;AACD,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CASvE;AACD,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,CAErE"}
package/dist/model.js CHANGED
@@ -6,7 +6,7 @@ export function definitionOf(state, type) {
6
6
  }
7
7
  export function modelTypes(state) {
8
8
  return state.status === 'unavailable'
9
- ? { ...state }
9
+ ? { ...state, types: null }
10
10
  : {
11
11
  status: state.status,
12
12
  identity: state.snapshot.identity,
@@ -23,6 +23,15 @@ export function cached(state) {
23
23
  export function sameModel(left, right) {
24
24
  return left.identity === right.identity && left.version === right.version;
25
25
  }
26
+ export function sameTyping(left, right) {
27
+ if (left === right)
28
+ return true;
29
+ if (left.status === 'unavailable' || right.status === 'unavailable') {
30
+ return left.status === right.status;
31
+ }
32
+ return (left.snapshot.schema === right.snapshot.schema &&
33
+ sameModel(left.verifiedWith, right.verifiedWith));
34
+ }
26
35
  export function referenceField(facts) {
27
36
  return facts?.reference !== undefined || facts?.items?.reference !== undefined;
28
37
  }
package/dist/name.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export declare function transliterated(text: string): string;
2
+ export declare function nameFrom(title: string): string;
3
+ export declare function cutName(name: string, most: number): string;
4
+ //# sourceMappingURL=name.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"name.d.ts","sourceRoot":"","sources":["../src/name.ts"],"names":[],"mappings":"AAgHA,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAK9C;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE1D"}
package/dist/name.js ADDED
@@ -0,0 +1,122 @@
1
+ const LETTERS = {
2
+ а: 'a',
3
+ б: 'b',
4
+ в: 'v',
5
+ г: 'g',
6
+ ґ: 'g',
7
+ д: 'd',
8
+ ђ: 'dj',
9
+ ѓ: 'gj',
10
+ е: 'e',
11
+ ё: 'yo',
12
+ є: 'ye',
13
+ ж: 'zh',
14
+ з: 'z',
15
+ ѕ: 'dz',
16
+ и: 'i',
17
+ і: 'i',
18
+ ї: 'yi',
19
+ й: 'y',
20
+ ј: 'j',
21
+ к: 'k',
22
+ ќ: 'kj',
23
+ л: 'l',
24
+ љ: 'lj',
25
+ м: 'm',
26
+ н: 'n',
27
+ њ: 'nj',
28
+ о: 'o',
29
+ п: 'p',
30
+ р: 'r',
31
+ с: 's',
32
+ т: 't',
33
+ ћ: 'c',
34
+ у: 'u',
35
+ ў: 'u',
36
+ ф: 'f',
37
+ х: 'kh',
38
+ ц: 'ts',
39
+ ч: 'ch',
40
+ џ: 'dz',
41
+ ш: 'sh',
42
+ щ: 'shch',
43
+ ъ: '',
44
+ ы: 'y',
45
+ ь: '',
46
+ э: 'e',
47
+ ю: 'yu',
48
+ я: 'ya',
49
+ α: 'a',
50
+ β: 'v',
51
+ γ: 'g',
52
+ δ: 'd',
53
+ ε: 'e',
54
+ ζ: 'z',
55
+ η: 'i',
56
+ θ: 'th',
57
+ ι: 'i',
58
+ κ: 'k',
59
+ λ: 'l',
60
+ μ: 'm',
61
+ ν: 'n',
62
+ ξ: 'x',
63
+ ο: 'o',
64
+ π: 'p',
65
+ ρ: 'r',
66
+ σ: 's',
67
+ ς: 's',
68
+ τ: 't',
69
+ υ: 'y',
70
+ φ: 'f',
71
+ χ: 'ch',
72
+ ψ: 'ps',
73
+ ω: 'o',
74
+ ß: 'ss',
75
+ æ: 'ae',
76
+ œ: 'oe',
77
+ ø: 'o',
78
+ đ: 'd',
79
+ ð: 'd',
80
+ þ: 'th',
81
+ ł: 'l',
82
+ ı: 'i',
83
+ };
84
+ const MARKS = /\p{M}/gu;
85
+ const ADMITTED = /^[a-z0-9]$/;
86
+ const WORDLIKE = /^[\p{L}\p{N}]$/u;
87
+ function lowerLetterOf(character) {
88
+ const known = LETTERS[character];
89
+ if (known !== undefined)
90
+ return known;
91
+ const bare = character.normalize('NFKD').replace(MARKS, '');
92
+ const mapped = LETTERS[bare];
93
+ if (mapped !== undefined)
94
+ return mapped;
95
+ return [...bare].every((one) => ADMITTED.test(one)) ? bare : null;
96
+ }
97
+ function codePoint(character) {
98
+ return WORDLIKE.test(character) ? `-u${character.codePointAt(0)?.toString(16) ?? ''}-` : '-';
99
+ }
100
+ function latin(text, unknown) {
101
+ return [...text]
102
+ .map((character) => {
103
+ if ((character.codePointAt(0) ?? 0) < 0x80)
104
+ return character;
105
+ const lower = character.toLowerCase();
106
+ const letter = lowerLetterOf(lower) ?? unknown(lower);
107
+ return lower === character ? letter : `${letter.charAt(0).toUpperCase()}${letter.slice(1)}`;
108
+ })
109
+ .join('');
110
+ }
111
+ export function transliterated(text) {
112
+ return latin(text, () => '-');
113
+ }
114
+ export function nameFrom(title) {
115
+ return latin(title, codePoint)
116
+ .toLowerCase()
117
+ .replace(/[^a-z0-9]+/g, '-')
118
+ .replace(/^-+|-+$/g, '');
119
+ }
120
+ export function cutName(name, most) {
121
+ return name.slice(0, most).replace(/-+$/, '');
122
+ }
@@ -1,4 +1,4 @@
1
- import type { QueryDocument, QueryGroup, QueryResult } from './query.js';
1
+ import type { QueryCoverage, QueryDocument, QueryGroup, QueryResult } from './query.js';
2
2
  export type Observation<T> = {
3
3
  current(): T;
4
4
  subscribe(listener: (value: T) => void): () => void;
@@ -13,15 +13,32 @@ export type QueryChange = {
13
13
  changed: readonly (readonly [RowKey, QueryDocument | QueryGroup])[];
14
14
  removed: readonly RowKey[];
15
15
  order: readonly RowKey[] | null;
16
+ coverage?: QueryCoverage;
17
+ next?: string | null;
18
+ total?: number;
16
19
  };
20
+ export type QueryMessage = KeyedResult | QueryChange;
17
21
  export type Observed = {
18
22
  observation: Observation<unknown>;
19
23
  receive(message: unknown): void;
20
24
  end(): void;
21
25
  };
22
26
  export declare function rowsOf(result: QueryResult): readonly (QueryDocument | QueryGroup)[];
23
- export declare function applied(keyed: KeyedResult, change: QueryChange): KeyedResult;
27
+ export declare function whole(message: QueryMessage): message is KeyedResult;
28
+ export declare function applied(keyed: KeyedResult, message: QueryMessage): KeyedResult;
24
29
  export declare function observed(first: unknown, stop: () => void, keyed: boolean): Observed;
25
30
  export declare function opened(watch: (deliver: (message: unknown) => void) => () => void, keyed: boolean): Promise<Observation<unknown>>;
26
31
  export declare function observing<Topic extends string>(watch: (topic: Topic, input: readonly unknown[], deliver: (message: unknown) => void) => () => void): (topic: Topic, ...input: unknown[]) => Promise<Observation<unknown>>;
32
+ export type Digest = {
33
+ readonly pending: string;
34
+ } | {
35
+ readonly keys: readonly RowKey[];
36
+ readonly rows: ReadonlyMap<RowKey, number>;
37
+ readonly coverage: string;
38
+ readonly next: string | undefined;
39
+ readonly total: number | undefined;
40
+ };
41
+ export declare function digestOf({ result, keys }: KeyedResult): Digest;
42
+ export declare function digestApplied(digest: Digest, message: QueryMessage): Digest;
43
+ export declare function changeOf(previous: Digest, next: KeyedResult): QueryMessage | null;
27
44
  //# sourceMappingURL=observation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"observation.d.ts","sourceRoot":"","sources":["../src/observation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzE,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;IAC3B,OAAO,IAAI,CAAC,CAAC;IACb,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACpD,KAAK,IAAI,IAAI,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAErC,MAAM,MAAM,WAAW,GAAG;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAE3E,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,aAAa,GAAG,UAAU,CAAC,CAAC,EAAE,CAAC;IACpE,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAClC,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAChC,GAAG,IAAI,IAAI,CAAC;CACb,CAAC;AAEF,wBAAgB,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC,aAAa,GAAG,UAAU,CAAC,EAAE,CAEnF;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,GAAG,WAAW,CAc5E;AAiBD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,EAAE,KAAK,EAAE,OAAO,GAAG,QAAQ,CAkCnF;AAED,wBAAgB,MAAM,CACpB,KAAK,EAAE,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,KAAK,MAAM,IAAI,EAC1D,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAiB/B;AAED,wBAAgB,SAAS,CAAC,KAAK,SAAS,MAAM,EAC5C,KAAK,EAAE,CACL,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,SAAS,OAAO,EAAE,EACzB,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,KAChC,MAAM,IAAI,WAEA,KAAK,YAAY,OAAO,EAAE,KAAG,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAQ1E"}
1
+ {"version":3,"file":"observation.d.ts","sourceRoot":"","sources":["../src/observation.ts"],"names":[],"mappings":"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"}
@@ -1,19 +1,36 @@
1
1
  export function rowsOf(result) {
2
- return 'groups' in result ? result.groups : result.documents;
2
+ if ('groups' in result)
3
+ return result.groups;
4
+ return 'documents' in result ? result.documents : [];
3
5
  }
4
- export function applied(keyed, change) {
5
- const rows = rowsOf(keyed.result);
6
+ export function whole(message) {
7
+ return 'result' in message;
8
+ }
9
+ export function applied(keyed, message) {
10
+ if (whole(message))
11
+ return message;
12
+ const result = keyed.result;
13
+ if ('pending' in result)
14
+ return keyed;
15
+ const rows = rowsOf(result);
6
16
  const byKey = new Map(keyed.keys.map((key, index) => [key, rows[index]]));
7
- for (const key of change.removed)
17
+ for (const key of message.removed)
8
18
  byKey.delete(key);
9
- for (const [key, row] of change.changed)
19
+ for (const [key, row] of message.changed)
10
20
  byKey.set(key, row);
11
- const keys = change.order ?? keyed.keys.filter((key) => byKey.has(key));
12
- const next = keys.map((key) => byKey.get(key));
21
+ const keys = message.order ?? keyed.keys.filter((key) => byKey.has(key));
22
+ const kept = keys.map((key) => byKey.get(key));
23
+ const coverage = message.coverage ?? result.coverage;
24
+ const next = message.next === undefined ? result.next : (message.next ?? undefined);
25
+ const total = message.total ?? result.total;
26
+ const window = {
27
+ ...(next === undefined ? {} : { next }),
28
+ ...(total === undefined ? {} : { total }),
29
+ };
13
30
  return {
14
- result: 'groups' in keyed.result
15
- ? { groups: next }
16
- : { documents: next },
31
+ result: 'groups' in result
32
+ ? { groups: kept, coverage, ...window }
33
+ : { documents: kept, coverage, ...window },
17
34
  keys,
18
35
  };
19
36
  }
@@ -27,11 +44,11 @@ function keyedResult(first) {
27
44
  },
28
45
  };
29
46
  }
30
- function whole(first) {
47
+ function replaced(first) {
31
48
  return { value: first, next: (message) => message };
32
49
  }
33
50
  export function observed(first, stop, keyed) {
34
- const reducer = keyed ? keyedResult(first) : whole(first);
51
+ const reducer = keyed ? keyedResult(first) : replaced(first);
35
52
  let value = reducer.value;
36
53
  let open = true;
37
54
  const listeners = new Set();
@@ -93,3 +110,87 @@ export function observing(watch) {
93
110
  deliver(structuredClone(message));
94
111
  }), topic === 'query');
95
112
  }
113
+ function hashed(text) {
114
+ let first = 0xdeadbeef;
115
+ let second = 0x41c6ce57;
116
+ for (let index = 0; index < text.length; index += 1) {
117
+ const code = text.charCodeAt(index);
118
+ first = Math.imul(first ^ code, 2654435761);
119
+ second = Math.imul(second ^ code, 1597334677);
120
+ }
121
+ first =
122
+ Math.imul(first ^ (first >>> 16), 2246822507) ^ Math.imul(second ^ (second >>> 13), 3266489909);
123
+ second =
124
+ Math.imul(second ^ (second >>> 16), 2246822507) ^ Math.imul(first ^ (first >>> 13), 3266489909);
125
+ return 4294967296 * (2097151 & second) + (first >>> 0);
126
+ }
127
+ function rowDigest(row) {
128
+ return hashed(JSON.stringify(row));
129
+ }
130
+ export function digestOf({ result, keys }) {
131
+ if ('pending' in result)
132
+ return { pending: JSON.stringify(result) };
133
+ const rows = rowsOf(result);
134
+ return {
135
+ keys,
136
+ rows: new Map(keys.map((key, index) => [key, rowDigest(rows[index])])),
137
+ coverage: JSON.stringify(result.coverage),
138
+ next: result.next,
139
+ total: result.total,
140
+ };
141
+ }
142
+ export function digestApplied(digest, message) {
143
+ if (whole(message) || 'pending' in digest)
144
+ return whole(message) ? digestOf(message) : digest;
145
+ const rows = new Map(digest.rows);
146
+ for (const key of message.removed)
147
+ rows.delete(key);
148
+ for (const [key, row] of message.changed)
149
+ rows.set(key, rowDigest(row));
150
+ return {
151
+ keys: message.order ?? digest.keys.filter((key) => rows.has(key)),
152
+ rows,
153
+ coverage: message.coverage === undefined ? digest.coverage : JSON.stringify(message.coverage),
154
+ next: message.next === undefined ? digest.next : (message.next ?? undefined),
155
+ total: message.total ?? digest.total,
156
+ };
157
+ }
158
+ export function changeOf(previous, next) {
159
+ const after = next.result;
160
+ if ('pending' in previous || 'pending' in after) {
161
+ return 'pending' in previous && 'pending' in after && previous.pending === JSON.stringify(after)
162
+ ? null
163
+ : next;
164
+ }
165
+ const later = rowsOf(after);
166
+ const present = new Set(next.keys);
167
+ const changed = [];
168
+ next.keys.forEach((key, index) => {
169
+ const row = later[index];
170
+ if (previous.rows.get(key) !== rowDigest(row))
171
+ changed.push([key, row]);
172
+ });
173
+ const removed = previous.keys.filter((key) => !present.has(key));
174
+ const kept = previous.keys.filter((key) => present.has(key));
175
+ const moved = kept.length !== next.keys.length || kept.some((key, index) => next.keys[index] !== key);
176
+ const coverage = JSON.stringify(after.coverage);
177
+ const covered = previous.coverage !== coverage;
178
+ const framing = reframed(previous, after);
179
+ if (changed.length === 0 && removed.length === 0 && !moved && !covered && framing === null) {
180
+ return null;
181
+ }
182
+ return {
183
+ changed,
184
+ removed,
185
+ order: moved ? next.keys : null,
186
+ ...(covered ? { coverage: after.coverage } : {}),
187
+ ...framing,
188
+ };
189
+ }
190
+ function reframed(before, after) {
191
+ const next = before.next === after.next ? {} : { next: after.next ?? null };
192
+ const total = before.total === after.total || after.total === undefined ? {} : { total: after.total };
193
+ return Object.keys(next).length === 0 && Object.keys(total).length === 0
194
+ ? null
195
+ : { ...next, ...total };
196
+ }
@@ -0,0 +1,22 @@
1
+ import type { BinaryResult } from './adapter.js';
2
+ import { type RuntimeDatabase } from './tables.js';
3
+ export type OpenedName = {
4
+ readonly locator: string;
5
+ readonly path: string;
6
+ readonly revision: string;
7
+ };
8
+ export type KeptBinary = {
9
+ readonly kind: 'binary';
10
+ readonly file: string;
11
+ readonly byteLength: number;
12
+ readonly mediaType: string;
13
+ };
14
+ export type KeptResult = KeptBinary | Exclude<BinaryResult, {
15
+ kind: 'binary';
16
+ }>;
17
+ export type OpenedFiles = {
18
+ find(name: OpenedName): Promise<KeptBinary | null>;
19
+ fetch(name: OpenedName, read: () => Promise<BinaryResult>): Promise<KeptResult>;
20
+ };
21
+ export declare function openedFiles(database: RuntimeDatabase, fenced: (locator: string) => boolean): OpenedFiles;
22
+ //# sourceMappingURL=opened.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opened.d.ts","sourceRoot":"","sources":["../src/opened.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGjD,OAAO,EAAoC,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAErF,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC,YAAY,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,CAAC;AAEhF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACnD,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CACjF,CAAC;AAsBF,wBAAgB,WAAW,CACzB,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,GACnC,WAAW,CAsFb"}