mindoodb-app-sdk 0.0.14 → 0.0.16

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.
package/README.md CHANGED
@@ -319,22 +319,56 @@ const window = await db.documents.list({
319
319
  // Read
320
320
  const doc = await db.documents.get(docId);
321
321
 
322
- // Create (optionally with a named document key)
322
+ // Create (MindooDB generates a UUID7 id; optionally use a named document key)
323
323
  const created = await db.documents.create({
324
324
  set: { title: "Meeting notes", content: "..." },
325
325
  decryptionKeyId: "team-key", // omit to use "default"
326
326
  });
327
327
 
328
- // Update
328
+ // Create with a caller-provided id (e.g. a known well-known document the app
329
+ // always loads on launch, or migrating an id from another system).
330
+ const settings = await db.documents.create({
331
+ id: "AppSettings",
332
+ set: { theme: "dark" },
333
+ });
334
+ // Subsequent calls with the same id return the existing document and DO NOT
335
+ // overwrite `set`, so `documents.create({ id })` is safe to call on every app
336
+ // launch as a "create-if-missing" primitive. Custom ids must match
337
+ // /^[A-Za-z][A-Za-z0-9_]*$/ (first char must be a letter, subsequent chars
338
+ // may be letters, digits, or `_`). Documents created with the same custom id
339
+ // on different replicas merge correctly when synced.
340
+
341
+ // Update top-level fields
329
342
  const updated = await db.documents.update(docId, {
330
343
  set: { title: "Updated title" },
331
344
  unset: ["legacyField"],
332
345
  });
333
346
 
347
+ // Update with a granular text patch (see "Collaborative text editing" below).
348
+ // `baseHeads` is the document version this edit was authored against; Haven
349
+ // merges these splices with any concurrent changes since `baseHeads`.
350
+ const merged = await db.documents.update(docId, {
351
+ text: [
352
+ {
353
+ path: ["body"],
354
+ baseHeads: doc!.heads,
355
+ edits: [
356
+ { index: 0, deleteCount: 0, insert: "Hello, " },
357
+ { index: 12, deleteCount: 5, insert: "team" },
358
+ ],
359
+ },
360
+ ],
361
+ });
362
+
334
363
  // Delete
335
364
  await db.documents.delete(docId);
365
+
366
+ // Undelete (resurrect a deleted document)
367
+ await db.documents.undelete(docId);
336
368
  ```
337
369
 
370
+ Every `MindooDBAppDocument` snapshot also exposes a `heads?: string[]` field. Those heads identify the document's current Automerge version and are the value you pass to `baseHeads` when issuing the next text patch. After Haven applies and merges your patch, the returned document carries the new `heads` you should use for the following edit cycle.
371
+
338
372
  `documents.list()` is backed by Haven's internal changefeed, not by a positional offset. The query object supports:
339
373
 
340
374
  | Field | Meaning |
@@ -349,24 +383,187 @@ await db.documents.delete(docId);
349
383
 
350
384
  `nextCursor` is the latest checkpoint reached by the page. Persist it after each successful call when you are building your own index or sync loop. If there were no changes after the supplied cursor, `nextCursor` is `null`.
351
385
 
352
- `documents.update()` accepts top-level `set` and `unset` operations. Prefer sending small, intentional field-level changes instead of rewriting whole documents when only a few fields changed. This keeps MindooDB change tracking more meaningful and helps Automerge produce cleaner merge results.
386
+ `documents.update()` accepts three independent operations on the same call:
387
+
388
+ - `set` -- assign top-level fields (shallow JSON merge).
389
+ - `unset` -- remove top-level fields entirely.
390
+ - `text` -- one or more **granular text patches** applied to specific JSON paths. Each patch carries the `baseHeads` version it was authored against and is merged on the Haven side with any concurrent changes that arrived since. This is the recommended way to edit collaborative text fields like a markdown body. See [Collaborative text editing](#collaborative-text-editing) below.
391
+
392
+ Prefer sending small, intentional field-level changes instead of rewriting whole documents when only a few fields changed. This keeps MindooDB change tracking more meaningful and helps Automerge produce cleaner merge results.
353
393
 
354
394
  When Haven can resolve the signing identity from the tenant directory, list items may also include `identityLabel` and `publicKeyFingerprint` for the latest visible change. Apps can use this to show who last touched a document without loading the full revision history first.
355
395
 
356
396
  ### Document history
357
397
 
358
- When the `history` capability is granted, you can walk the full revision timeline of any document:
398
+ When the `history` capability is granted, you can walk the document revision list and load historical snapshots. Prefer `revisionId` for follow-up reads: it is a stable, DAG-backed identifier for the exact document revision, while timestamps are mainly useful for display and backwards-compatible point-in-time lookups.
359
399
 
360
400
  ```ts
361
401
  // List all revisions
362
402
  const history = await db.documents.listHistory(docId);
363
- // Each entry: { timestamp, publicKey, identityLabel?, isDeleted, isCurrent, summary? }
403
+ // Each entry:
404
+ // {
405
+ // revisionId,
406
+ // timestamp,
407
+ // heads?,
408
+ // publicKey,
409
+ // identityLabel?,
410
+ // isDeleted,
411
+ // isCurrent,
412
+ // summary?
413
+ // }
414
+
415
+ // Load the document state at an exact DAG revision
416
+ const snapshot = await db.documents.getAtRevision(docId, history[0]!.revisionId);
417
+ // {
418
+ // id,
419
+ // revisionId,
420
+ // timestamp,
421
+ // heads?,
422
+ // state: "exists" | "deleted" | "missing",
423
+ // data,
424
+ // attachments?,
425
+ // attachmentSnapshotRevisionId?
426
+ // }
427
+
428
+ // Timestamp lookup is still available when all you have is a timestamp.
429
+ const pointInTime = await db.documents.getAtTimestamp(docId, history[0]!.timestamp);
430
+ ```
364
431
 
365
- // Load the document state at a specific point in time
366
- const snapshot = await db.documents.getAtTimestamp(docId, history[0]!.timestamp);
367
- // { id, timestamp, state: "exists" | "deleted" | "missing", data }
432
+ Historical snapshots include the document data payload as it existed at that revision. When the snapshot has attachments, `attachments` reflects the historical `_attachments` array for that same revision, including the attachment reference that Haven needs to stop at the correct historical `lastChunkId`.
433
+
434
+ ### Collaborative text editing
435
+
436
+ MindooDB stores collaborative text fields as Automerge text CRDTs internally, but apps never touch Automerge directly -- the SDK bridge is JSON-only. Instead, your app describes text changes as **granular splice operations** against a known document version, and Haven applies and merges them on its side.
437
+
438
+ Two layers are available:
439
+
440
+ - **Low level**: raw text patches via `documents.update({ text: [...] })`.
441
+ - **High level**: `createMindooDBTextBuffer(...)` -- a small editor-friendly helper that tracks local edits and flushes them as one patch.
442
+
443
+ The end-to-end flow is the same in both cases:
444
+
445
+ ```
446
+ ┌────────────────────────────────────────────────────┐
447
+ edit ───► │ App buffer (local string + pending splices) │ ──► flush
448
+ └─────────────────────────┬──────────────────────────┘
449
+ │ documents.update({
450
+ │ text: [{ path, baseHeads, edits }]
451
+ │ })
452
+ ▼
453
+ ┌────────────────────────────────────────────────────┐
454
+ │ Haven applies edits at `baseHeads` and merges with │
455
+ │ concurrent changes via Automerge │
456
+ └─────────────────────────┬──────────────────────────┘
457
+ │ canonical merged document
458
+ ▼
459
+ ┌────────────────────────────────────────────────────┐
460
+ │ App reconciles its editor with the canonical text │
461
+ └────────────────────────────────────────────────────┘
368
462
  ```
369
463
 
464
+ #### Text patch shape
465
+
466
+ ```ts
467
+ interface MindooDBAppTextEdit {
468
+ index: number; // 0-based position in the current string at baseHeads
469
+ deleteCount: number; // number of characters to remove at `index`
470
+ insert?: string; // text to insert at `index` after deletion
471
+ }
472
+
473
+ interface MindooDBAppTextPatch {
474
+ path: Array<string | number>; // path inside `document.data`, e.g. ["body"]
475
+ baseHeads?: string[]; // document version the edits were authored against
476
+ edits: MindooDBAppTextEdit[]; // applied in order
477
+ }
478
+ ```
479
+
480
+ Each edit is a JavaScript-style `splice(index, deleteCount, insert)`. Multiple patches in a single `update()` call are applied atomically.
481
+
482
+ #### Low-level: `documents.update({ text: [...] })`
483
+
484
+ If your editor already exposes raw text operations (e.g. ProseMirror or CodeMirror transactions), forward them directly:
485
+
486
+ ```ts
487
+ const doc = await db.documents.get(docId);
488
+
489
+ // User typed "Hello, " at the beginning of the body.
490
+ const result = await db.documents.update(docId, {
491
+ text: [{
492
+ path: ["body"],
493
+ baseHeads: doc!.heads,
494
+ edits: [{ index: 0, deleteCount: 0, insert: "Hello, " }],
495
+ }],
496
+ });
497
+
498
+ // `result.data.body` -- canonical merged text
499
+ // `result.heads` -- new heads to use as `baseHeads` next time
500
+ ```
501
+
502
+ When two app instances send patches concurrently against the same `baseHeads`, Haven merges both via Automerge and returns the canonical text. If the merged result differs from what your editor currently displays, replace the editor content with `result.data[path]`.
503
+
504
+ #### High-level: `createMindooDBTextBuffer`
505
+
506
+ For WYSIWYG editors that emit a full markdown / plain-text string after each transaction (Milkdown, TinyMCE, etc.), the SDK ships a small buffer helper that does the splice diffing and flush bookkeeping for you:
507
+
508
+ ```ts
509
+ import { createMindooDBTextBuffer } from "mindoodb-app-sdk";
510
+
511
+ const doc = await db.documents.get(docId);
512
+ const buffer = createMindooDBTextBuffer({
513
+ database: db,
514
+ document: doc!,
515
+ path: ["body"], // string field inside `document.data`
516
+ });
517
+
518
+ editor.value = buffer.value;
519
+
520
+ // Editor reports a new full markdown value -- the buffer turns it into one splice.
521
+ editor.on("update", (next: string) => {
522
+ buffer.replaceText(next);
523
+ });
524
+
525
+ // On save (e.g. Cmd+S), flush all pending edits to Haven.
526
+ async function save() {
527
+ const result = await buffer.flush();
528
+ if (result.reconciled) {
529
+ // Haven merged in concurrent changes; show the canonical merged text.
530
+ editor.value = result.value;
531
+ }
532
+ }
533
+
534
+ // Re-read the document without saving (e.g. a Refresh button).
535
+ async function refresh() {
536
+ const fresh = await db.documents.get(docId);
537
+ if (fresh && buffer.reconcile(fresh)) {
538
+ editor.value = buffer.value;
539
+ }
540
+ }
541
+ ```
542
+
543
+ Buffer API at a glance:
544
+
545
+ | Member | Description |
546
+ |---|---|
547
+ | `value` / `toString()` | Current local text value |
548
+ | `dirty` / `pendingCount` | Whether/how many local splices are buffered |
549
+ | `splice(index, deleteCount, insert?)` | Record an exact text operation |
550
+ | `replaceText(next)` | Diff `value` against `next` and record one minimal splice |
551
+ | `reconcile(document)` | Adopt a fresh document snapshot, drop pending edits |
552
+ | `flush()` | Send pending edits to Haven; resolves to `{ document, value, reconciled }` |
553
+
554
+ `flush()` always sends the original `baseHeads` captured when the buffer was created (or last reconciled), so two windows editing the same document at the same heads will both produce a clean merge -- they will not overwrite each other.
555
+
556
+ #### Concurrent-edit walkthrough
557
+
558
+ 1. Window A and window B both `documents.get(docId)` and create a buffer at the same `baseHeads`.
559
+ 2. Window A inserts text at the top, window B deletes a paragraph in the middle.
560
+ 3. Window A calls `buffer.flush()` first. Haven applies its patch, advances the document heads, and returns the canonical text to A.
561
+ 4. Window B calls `buffer.flush()` next. Haven still applies B's patch causally at B's original `baseHeads`, then merges with A's already-stored change. B's `result.reconciled` is `true` and `result.value` contains both A's and B's edits.
562
+
563
+ #### End-to-end sample
564
+
565
+ The [`mindoodb-app-teamedit`](https://github.com/klehmann/mindoodb-app-teamedit) sample wires `MindooDBTextBuffer` to a Milkdown markdown editor with Save / Refresh / preview pane, and is the recommended starting point for building your own collaborative text app.
566
+
370
567
  ### Incremental sync
371
568
 
372
569
  The changefeed-backed `documents.list()` API is also the right primitive for app-side indexes, search, and other derived caches.
@@ -457,6 +654,26 @@ await writer.close();
457
654
  await db.attachments.remove(docId, "old-file.txt");
458
655
  ```
459
656
 
657
+ For historical reads, pass the same `revisionId` you received from `documents.listHistory()` or from a `MindooDBAppHistoricalDocument`. This tells Haven to resolve the attachment from that revision's document payload instead of the latest document state:
658
+
659
+ ```ts
660
+ const history = await db.documents.listHistory(docId);
661
+ const revisionId = history[0]!.revisionId;
662
+ const historical = await db.documents.getAtRevision(docId, revisionId);
663
+
664
+ const historicalFiles = await db.attachments.list(docId, {
665
+ revisionId,
666
+ });
667
+
668
+ const historicalReader = await db.attachments.openReadStream(
669
+ docId,
670
+ historicalFiles[0]!.fileName,
671
+ { revisionId },
672
+ );
673
+ ```
674
+
675
+ Use `revisionId` instead of `timestamp` whenever possible. Attachment blobs can grow over time by appending chunks and changing the attachment's `lastChunkId` in newer document revisions; `revisionId` ensures Haven reads from the historical attachment reference and does not accidentally include chunks added later.
676
+
460
677
  ### Attachment previews
461
678
 
462
679
  Haven includes a **built-in file viewer** that your app can open for common attachment formats. This is one of the most powerful SDK features -- it works with both online and offline data, and media formats support streaming playback with skip/seek.
@@ -485,10 +702,12 @@ You can also preview attachments from a **historical document snapshot**:
485
702
 
486
703
  ```ts
487
704
  await db.attachments.openPreview(docId, "report.pdf", {
488
- timestamp: historyEntry.timestamp,
705
+ revisionId: historyEntry.revisionId,
489
706
  });
490
707
  ```
491
708
 
709
+ `timestamp` is still accepted in attachment options for compatibility, but `revisionId` is the preferred identifier because it targets an exact DAG revision.
710
+
492
711
  **Check preview support locally** before showing a preview button:
493
712
 
494
713
  ```ts
@@ -729,23 +948,42 @@ Connect options: `launchId?`, `targetOrigin?`, `connectTimeoutMs?`.
729
948
  | `create(input)` | `Promise<MindooDBAppDocument>` |
730
949
  | `update(docId, patch)` | `Promise<MindooDBAppDocument>` |
731
950
  | `delete(docId)` | `Promise<{ ok: true }>` |
951
+ | `undelete(docId)` | `Promise<{ ok: true }>` |
732
952
  | `listHistory(docId)` | `Promise<MindooDBAppDocumentHistoryEntry[]>` |
733
953
  | `getAtTimestamp(docId, timestamp)` | `Promise<MindooDBAppHistoricalDocument>` |
954
+ | `getAtRevision(docId, revisionId)` | `Promise<MindooDBAppHistoricalDocument>` |
734
955
 
735
956
  `list(query?)` accepts the changefeed query options documented above. The `cursor` value is an opaque checkpoint string managed by Haven and should be stored and passed back unchanged.
736
957
 
737
- For `update(docId, patch)`, use `{ set?: Record<string, unknown>; unset?: string[] }`. Both operations are shallow and apply to top-level document fields only.
958
+ For `create(input)`, use `MindooDBAppCreateDocumentInput` with shape `{ set: Record<string, unknown>; decryptionKeyId?: string; id?: string }`. The optional `id` lets the app pick the document id instead of letting MindooDB generate a UUID7; when provided it must match `/^[A-Za-z][A-Za-z0-9_]*$/` and existing live documents with that id are returned as-is (idempotent create-if-missing). If an existing custom-id document is deleted, `create({ id })` undeletes it and preserves the previous document body. Documents created with the same custom id on different replicas converge correctly when synced.
959
+
960
+ `delete(docId)` writes a lifecycle tombstone; it does not erase the document body from the append-only history. Use `undelete(docId)` to make the latest document state live again. If you want to record a deletion reason, first call `update(docId, { set: { intendedDeletionReason: "..." } })`, then call `delete(docId)`.
961
+
962
+ For `update(docId, patch)`, use `MindooDBAppUpdateDocumentInput`:
963
+
964
+ ```ts
965
+ interface MindooDBAppUpdateDocumentInput {
966
+ set?: Record<string, unknown>; // shallow assign top-level fields
967
+ unset?: string[]; // remove top-level fields entirely
968
+ text?: MindooDBAppTextPatch[]; // granular collaborative text edits
969
+ }
970
+ ```
971
+
972
+ `set` and `unset` apply to top-level fields only. `text` patches operate on string fields at any JSON path inside `document.data` and are merged on the Haven side using the document's Automerge heads. See [Collaborative text editing](#collaborative-text-editing).
738
973
 
739
974
  ### MindooDBAppAttachmentApi
740
975
 
741
976
  | Method | Returns |
742
977
  |---|---|
743
- | `list(docId)` | `Promise<MindooDBAppAttachmentInfo[]>` |
978
+ | `list(docId, options?)` | `Promise<MindooDBAppAttachmentInfo[]>` |
744
979
  | `remove(docId, attachmentName)` | `Promise<{ ok: true }>` |
745
- | `openReadStream(docId, attachmentName)` | `Promise<MindooDBAppReadableAttachmentStream>` |
980
+ | `openReadStream(docId, attachmentName, options?)` | `Promise<MindooDBAppReadableAttachmentStream>` |
746
981
  | `openWriteStream(docId, attachmentName, contentType?)` | `Promise<MindooDBAppWritableAttachmentStream>` |
982
+ | `preparePreviewSession(docId, attachmentName, options?)` | `Promise<MindooDBAppAttachmentPreviewSession>` |
747
983
  | `openPreview(docId, attachmentName, options?)` | `Promise<{ ok: true }>` |
748
984
 
985
+ `options` accepts `{ timestamp?: number; revisionId?: string }` for read-only historical attachment access. Mutation methods (`openWriteStream`, `remove`) always target the current document.
986
+
749
987
  ### MindooDBAppViewNavigator
750
988
 
751
989
  | Method | Returns |
@@ -792,6 +1030,7 @@ For `update(docId, patch)`, use `{ set?: Record<string, unknown>; unset?: string
792
1030
  | Function | Description |
793
1031
  |---|---|
794
1032
  | `createMindooDBAppBridge()` | Create the bridge object used to connect to Haven |
1033
+ | `createMindooDBTextBuffer(options)` | Create an editor-friendly buffer for granular collaborative text edits on a document field |
795
1034
  | `canPreviewAttachment(fileName, mimeType)` | Check if Haven can preview a file (returns mode or `null`) |
796
1035
  | `createViewLanguage<T>()` | Create a typed expression builder for view definitions |
797
1036
  | `abbreviateCanonicalName(value)` | Convert a canonical Notes-style name like `cn=Jane/ou=Dev/o=Mindoo` to `Jane/Dev/Mindoo` |
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { M as MindooDBAppAttachmentPreviewMode, a as MindooDBAppBridge } from './types-B1iKRIuy.js';
2
- export { b as MindooDBAppAttachmentApi, c as MindooDBAppAttachmentChunk, d as MindooDBAppAttachmentInfo, e as MindooDBAppAttachmentPreviewOptions, f as MindooDBAppAttachmentPreviewSession, g as MindooDBAppBridgeConnectMessage, h as MindooDBAppBridgeConnectOptions, i as MindooDBAppBridgeConnectedMessage, j as MindooDBAppBridgeErrorPayload, k as MindooDBAppBridgePortMessage, l as MindooDBAppBridgeRpcError, m as MindooDBAppBridgeRpcMessage, n as MindooDBAppBridgeRpcRequest, o as MindooDBAppBridgeRpcSuccess, p as MindooDBAppBridgeStreamAbortRequest, q as MindooDBAppBridgeStreamAck, r as MindooDBAppBridgeStreamCloseRequest, s as MindooDBAppBridgeStreamError, t as MindooDBAppBridgeStreamMessage, u as MindooDBAppBridgeStreamOpenResult, v as MindooDBAppBridgeStreamReadRequest, w as MindooDBAppBridgeStreamWriteRequest, x as MindooDBAppBridgeThemeChangedMessage, y as MindooDBAppBridgeUiPreferencesChangedMessage, z as MindooDBAppBridgeViewportChangedMessage, A as MindooDBAppCapability, B as MindooDBAppConfiguredViewCategorizationStyle, C as MindooDBAppConfiguredViewColumn, D as MindooDBAppConfiguredViewColumnRole, E as MindooDBAppConfiguredViewExpressionMode, F as MindooDBAppConfiguredViewFieldExpression, G as MindooDBAppConfiguredViewFilterDefinition, H as MindooDBAppConfiguredViewFilterMode, I as MindooDBAppConfiguredViewFilterRule, J as MindooDBAppConfiguredViewFormulaExpression, K as MindooDBAppConfiguredViewFormulaFilterDefinition, L as MindooDBAppConfiguredViewPreviewMode, N as MindooDBAppConfiguredViewRuleFilterDefinition, O as MindooDBAppConfiguredViewRuleMatchMode, P as MindooDBAppConfiguredViewRuleOperator, Q as MindooDBAppConfiguredViewValueExpression, R as MindooDBAppCreateDocumentInput, S as MindooDBAppCreateViewInput, T as MindooDBAppCreateViewNavigatorInput, U as MindooDBAppDatabase, V as MindooDBAppDatabaseInfo, W as MindooDBAppDocument, X as MindooDBAppDocumentApi, Y as MindooDBAppDocumentHeadCursorResult, Z as MindooDBAppDocumentHistoryEntry, _ as MindooDBAppDocumentListQuery, $ as MindooDBAppDocumentListResult, a0 as MindooDBAppDocumentSummary, a1 as MindooDBAppHistoricalDocument, a2 as MindooDBAppHistoryQuery, a3 as MindooDBAppHostTheme, a4 as MindooDBAppLaunchContext, a5 as MindooDBAppMenuAnchor, a6 as MindooDBAppMenuApi, a7 as MindooDBAppMenuCommandItem, a8 as MindooDBAppMenuDismissReason, a9 as MindooDBAppMenuDismissedResult, aa as MindooDBAppMenuItem, ab as MindooDBAppMenuKind, ac as MindooDBAppMenuPlacement, ad as MindooDBAppMenuPointAnchor, ae as MindooDBAppMenuRect, af as MindooDBAppMenuRectAnchor, ag as MindooDBAppMenuSelectionResult, ah as MindooDBAppMenuSeparatorItem, ai as MindooDBAppReadableAttachmentStream, aj as MindooDBAppResolvedViewDefinition, ak as MindooDBAppResolvedViewSource, al as MindooDBAppRuntime, am as MindooDBAppScopedDocId, an as MindooDBAppScopedDocumentSummary, ao as MindooDBAppSession, ap as MindooDBAppShowMenuInput, aq as MindooDBAppShowMenuResult, ar as MindooDBAppThemeMode, as as MindooDBAppUiPreferences, at as MindooDBAppUpdateDocumentInput, au as MindooDBAppViewCursorDocumentListResult, av as MindooDBAppViewCursorResult, aw as MindooDBAppViewEntry, ax as MindooDBAppViewEntryKind, ay as MindooDBAppViewNavigator, az as MindooDBAppViewNavigatorExpansionState, aA as MindooDBAppViewNavigatorOpenOptions, aB as MindooDBAppViewNavigatorPageOptions, aC as MindooDBAppViewNavigatorPageResult, aD as MindooDBAppViewNavigatorRangeQuery, aE as MindooDBAppViewNavigatorSelectionState, aF as MindooDBAppViewport, aG as MindooDBAppWritableAttachmentStream } from './types-B1iKRIuy.js';
1
+ import { M as MindooDBAppAttachmentPreviewMode, a as MindooDBAppBridge, b as MindooDBAppDatabase, c as MindooDBAppDocument } from './types-D0vtIHBf.js';
2
+ export { d as MindooDBAppAttachmentApi, e as MindooDBAppAttachmentChunk, f as MindooDBAppAttachmentInfo, g as MindooDBAppAttachmentPreviewOptions, h as MindooDBAppAttachmentPreviewSession, i as MindooDBAppBridgeConnectMessage, j as MindooDBAppBridgeConnectOptions, k as MindooDBAppBridgeConnectedMessage, l as MindooDBAppBridgeErrorPayload, m as MindooDBAppBridgeHandshakeErrorMessage, n as MindooDBAppBridgePortMessage, o as MindooDBAppBridgeRpcError, p as MindooDBAppBridgeRpcMessage, q as MindooDBAppBridgeRpcRequest, r as MindooDBAppBridgeRpcSuccess, s as MindooDBAppBridgeStreamAbortRequest, t as MindooDBAppBridgeStreamAck, u as MindooDBAppBridgeStreamCloseRequest, v as MindooDBAppBridgeStreamError, w as MindooDBAppBridgeStreamMessage, x as MindooDBAppBridgeStreamOpenResult, y as MindooDBAppBridgeStreamReadRequest, z as MindooDBAppBridgeStreamWriteRequest, A as MindooDBAppBridgeThemeChangedMessage, B as MindooDBAppBridgeUiPreferencesChangedMessage, C as MindooDBAppBridgeViewportChangedMessage, D as MindooDBAppCapability, E as MindooDBAppConfiguredViewCategorizationStyle, F as MindooDBAppConfiguredViewColumn, G as MindooDBAppConfiguredViewColumnRole, H as MindooDBAppConfiguredViewExpressionMode, I as MindooDBAppConfiguredViewFieldExpression, J as MindooDBAppConfiguredViewFilterDefinition, K as MindooDBAppConfiguredViewFilterMode, L as MindooDBAppConfiguredViewFilterRule, N as MindooDBAppConfiguredViewFormulaExpression, O as MindooDBAppConfiguredViewFormulaFilterDefinition, P as MindooDBAppConfiguredViewPreviewMode, Q as MindooDBAppConfiguredViewRuleFilterDefinition, R as MindooDBAppConfiguredViewRuleMatchMode, S as MindooDBAppConfiguredViewRuleOperator, T as MindooDBAppConfiguredViewValueExpression, U as MindooDBAppCreateDocumentInput, V as MindooDBAppCreateViewInput, W as MindooDBAppCreateViewNavigatorInput, X as MindooDBAppDatabaseInfo, Y as MindooDBAppDocumentApi, Z as MindooDBAppDocumentHeadCursorResult, _ as MindooDBAppDocumentHistoryEntry, $ as MindooDBAppDocumentListQuery, a0 as MindooDBAppDocumentListResult, a1 as MindooDBAppDocumentRevisionId, a2 as MindooDBAppDocumentSummary, a3 as MindooDBAppHistoricalDocument, a4 as MindooDBAppHistoryQuery, a5 as MindooDBAppHostTheme, a6 as MindooDBAppLaunchContext, a7 as MindooDBAppMenuAnchor, a8 as MindooDBAppMenuApi, a9 as MindooDBAppMenuCommandItem, aa as MindooDBAppMenuDismissReason, ab as MindooDBAppMenuDismissedResult, ac as MindooDBAppMenuItem, ad as MindooDBAppMenuKind, ae as MindooDBAppMenuPlacement, af as MindooDBAppMenuPointAnchor, ag as MindooDBAppMenuRect, ah as MindooDBAppMenuRectAnchor, ai as MindooDBAppMenuSelectionResult, aj as MindooDBAppMenuSeparatorItem, ak as MindooDBAppReadableAttachmentStream, al as MindooDBAppResolvedViewDefinition, am as MindooDBAppResolvedViewSource, an as MindooDBAppRuntime, ao as MindooDBAppScopedDocId, ap as MindooDBAppScopedDocumentSummary, aq as MindooDBAppSession, ar as MindooDBAppShowMenuInput, as as MindooDBAppShowMenuResult, at as MindooDBAppTextEdit, au as MindooDBAppTextPatch, av as MindooDBAppThemeMode, aw as MindooDBAppUiPreferences, ax as MindooDBAppUpdateDocumentInput, ay as MindooDBAppViewCursorDocumentListResult, az as MindooDBAppViewCursorResult, aA as MindooDBAppViewEntry, aB as MindooDBAppViewEntryKind, aC as MindooDBAppViewNavigator, aD as MindooDBAppViewNavigatorExpansionState, aE as MindooDBAppViewNavigatorOpenOptions, aF as MindooDBAppViewNavigatorPageOptions, aG as MindooDBAppViewNavigatorPageResult, aH as MindooDBAppViewNavigatorRangeQuery, aI as MindooDBAppViewNavigatorSelectionState, aJ as MindooDBAppViewport, aK as MindooDBAppWritableAttachmentStream } from './types-D0vtIHBf.js';
3
3
  export { MindooDBAppBooleanExpression, MindooDBAppExpression, MindooDBAppFilterDefinition, MindooDBAppViewCategoryChildrenPageRequest, MindooDBAppViewColumn, MindooDBAppViewColumnRole, MindooDBAppViewDefinition, MindooDBAppViewExpansionState, MindooDBAppViewExpressionBase, MindooDBAppViewExpressionDatePart, MindooDBAppViewExpressionOperation, MindooDBAppViewFieldExpression, MindooDBAppViewIfExpression, MindooDBAppViewLetExpression, MindooDBAppViewLiteralExpression, MindooDBAppViewLookupByPath, MindooDBAppViewOperationExpression, MindooDBAppViewOriginExpression, MindooDBAppViewPageRequest, MindooDBAppViewPageResult, MindooDBAppViewRow, MindooDBAppViewSortDirection, MindooDBAppViewTotalMode, MindooDBAppViewValueExpressionRef, MindooDBAppViewVariableExpression, createViewLanguage } from 'mindoodb-view-language';
4
4
 
5
5
  /**
@@ -32,9 +32,102 @@ declare function expandAbbreviatedName(value: string): string;
32
32
  * Creates the browser-side bridge entry point used by MindooDB apps.
33
33
  *
34
34
  * The returned object performs the initial postMessage handshake with the
35
- * Administrator host and exposes a session with document, view, and attachment
35
+ * Haven host and exposes a session with document, view, and attachment
36
36
  * APIs over a dedicated `MessagePort`.
37
37
  */
38
38
  declare function createMindooDBAppBridge(): MindooDBAppBridge;
39
39
 
40
- export { MindooDBAppAttachmentPreviewMode, MindooDBAppBridge, abbreviateCanonicalName, canPreviewAttachment, createMindooDBAppBridge, expandAbbreviatedName };
40
+ /**
41
+ * Options used to create a text buffer for one string field in a MindooDB
42
+ * document.
43
+ *
44
+ * The buffer keeps a local editable string and records text operations that can
45
+ * later be flushed over the JSON bridge. `path` points to the string inside
46
+ * `document.data`, for example `["body"]` for a markdown body field.
47
+ */
48
+ interface CreateMindooDBTextBufferOptions {
49
+ /** Open database handle used when `flush()` sends the buffered text patch. */
50
+ database: MindooDBAppDatabase;
51
+ /** Document snapshot the local editor state is based on. */
52
+ document: MindooDBAppDocument;
53
+ /** Path to the string field inside `document.data`. */
54
+ path: Array<string | number>;
55
+ }
56
+ /**
57
+ * Result returned after flushing pending text edits.
58
+ */
59
+ interface MindooDBTextBufferFlushResult {
60
+ /** Updated document returned by Haven after applying and reconciling edits. */
61
+ document: MindooDBAppDocument;
62
+ /** Canonical text value at the configured path after the flush. */
63
+ value: string;
64
+ /**
65
+ * `true` when the canonical value returned by Haven differs from the local
66
+ * value that was flushed. This usually means concurrent edits from another
67
+ * app instance or sync source were merged during save and the editor should
68
+ * replace its visible content with `value`.
69
+ */
70
+ reconciled: boolean;
71
+ }
72
+ /**
73
+ * Local text editing buffer for SDK apps.
74
+ *
75
+ * `MindooDBTextBuffer` is intentionally not an Automerge document. It is a
76
+ * small app-side helper that behaves like a mutable string, keeps track of
77
+ * local text edits, and flushes those edits as JSON-safe operations to Haven.
78
+ * Haven then applies the operations against the real Automerge document using
79
+ * the document heads captured when this buffer was created or last reconciled.
80
+ *
81
+ * Use `splice()` when your editor can report exact text operations. Use
82
+ * `replaceText()` for WYSIWYG or markdown editors that expose only the full
83
+ * current text value; the buffer computes a minimal single-splice diff.
84
+ */
85
+ declare class MindooDBTextBuffer {
86
+ private readonly options;
87
+ private valueInternal;
88
+ private heads;
89
+ private pendingEdits;
90
+ constructor(options: CreateMindooDBTextBufferOptions);
91
+ get value(): string;
92
+ /** Whether there are local edits that have not been flushed yet. */
93
+ get dirty(): boolean;
94
+ /** Number of pending text operations currently buffered. */
95
+ get pendingCount(): number;
96
+ /** Return the current local text value. */
97
+ toString(): string;
98
+ /**
99
+ * Apply an exact local text splice and queue it for the next flush.
100
+ *
101
+ * Offsets use JavaScript string indexing. The delete count is clamped to the
102
+ * remaining local text length so callers can safely delete to the end.
103
+ */
104
+ splice(index: number, deleteCount: number, insert?: string): void;
105
+ /**
106
+ * Replace the current local text value and queue the change as one splice.
107
+ *
108
+ * This is useful for editors such as Milkdown that can produce the full
109
+ * markdown string after each transaction but do not expose raw text splices.
110
+ */
111
+ replaceText(nextValue: string): void;
112
+ /**
113
+ * Replace local state from a fresh document snapshot and clear pending edits.
114
+ *
115
+ * Returns whether the text value changed. Use this after an external refresh
116
+ * or after receiving a document update through another app-level mechanism.
117
+ */
118
+ reconcile(document: MindooDBAppDocument): boolean;
119
+ /**
120
+ * Flush pending edits to Haven using `documents.update({ text: ... })`.
121
+ *
122
+ * The request includes the document heads this buffer is based on, allowing
123
+ * Haven to apply the text operations at the original causal version and merge
124
+ * them with any concurrent document changes. After a successful flush the
125
+ * buffer adopts the returned canonical value and heads, and clears the
126
+ * pending edit queue.
127
+ */
128
+ flush(): Promise<MindooDBTextBufferFlushResult>;
129
+ }
130
+ /** Create a local text buffer for one string field in a document. */
131
+ declare function createMindooDBTextBuffer(options: CreateMindooDBTextBufferOptions): MindooDBTextBuffer;
132
+
133
+ export { type CreateMindooDBTextBufferOptions, MindooDBAppAttachmentPreviewMode, MindooDBAppBridge, MindooDBAppDatabase, MindooDBAppDocument, MindooDBTextBuffer, type MindooDBTextBufferFlushResult, abbreviateCanonicalName, canPreviewAttachment, createMindooDBAppBridge, createMindooDBTextBuffer, expandAbbreviatedName };
package/dist/index.js CHANGED
@@ -281,7 +281,7 @@ function resolveTargetWindow() {
281
281
  if (window.opener) {
282
282
  return window.opener;
283
283
  }
284
- throw new Error("Could not find a MindooDB Administrator host window.");
284
+ throw new Error("Could not find a MindooDB Haven host window.");
285
285
  }
286
286
  function waitForConnectedPort(options, launchId) {
287
287
  const targetWindow = resolveTargetWindow();
@@ -298,16 +298,25 @@ function waitForConnectedPort(options, launchId) {
298
298
  };
299
299
  const handleMessage = (event) => {
300
300
  const payload = event.data;
301
- if (!payload || payload.protocol !== PROTOCOL2 || payload.type !== "mindoodb-app:connected") {
301
+ if (!payload || payload.protocol !== PROTOCOL2) {
302
302
  return;
303
303
  }
304
- cleanup();
305
- resolve(channel.port1);
304
+ if (payload.type === "mindoodb-app:connected") {
305
+ cleanup();
306
+ resolve(channel.port1);
307
+ return;
308
+ }
309
+ if (payload.type === "mindoodb-app:error") {
310
+ cleanup();
311
+ channel.port1.close();
312
+ const message2 = typeof payload.error === "string" && payload.error.trim() ? payload.error : "MindooDB Haven bridge connection failed.";
313
+ reject(new Error(message2));
314
+ }
306
315
  };
307
316
  timeoutId = window.setTimeout(() => {
308
317
  cleanup();
309
318
  channel.port1.close();
310
- reject(new Error(`Timed out while connecting to the MindooDB Administrator bridge for launch ${launchId}.`));
319
+ reject(new Error(`Timed out while connecting to the MindooDB Haven bridge for launch ${launchId}.`));
311
320
  }, timeoutMs);
312
321
  channel.port1.addEventListener("message", handleMessage);
313
322
  channel.port1.start();
@@ -665,6 +674,10 @@ var MindooDBAppDatabaseImpl = class {
665
674
  databaseId: this.databaseId,
666
675
  docId
667
676
  }),
677
+ undelete: async (docId) => await this.rpc.call("documents.undelete", {
678
+ databaseId: this.databaseId,
679
+ docId
680
+ }),
668
681
  listHistory: async (docId) => await this.rpc.call("documents.history.list", {
669
682
  databaseId: this.databaseId,
670
683
  docId
@@ -673,23 +686,32 @@ var MindooDBAppDatabaseImpl = class {
673
686
  databaseId: this.databaseId,
674
687
  docId,
675
688
  timestamp
689
+ }),
690
+ getAtRevision: async (docId, revisionId) => await this.rpc.call("documents.history.getAtRevision", {
691
+ databaseId: this.databaseId,
692
+ docId,
693
+ revisionId
676
694
  })
677
695
  };
678
696
  this.attachments = {
679
- list: async (docId) => await this.rpc.call("attachments.list", {
697
+ list: async (docId, options) => await this.rpc.call("attachments.list", {
680
698
  databaseId: this.databaseId,
681
- docId
699
+ docId,
700
+ timestamp: options?.timestamp,
701
+ revisionId: options?.revisionId
682
702
  }),
683
703
  remove: async (docId, attachmentName) => await this.rpc.call("attachments.remove", {
684
704
  databaseId: this.databaseId,
685
705
  docId,
686
706
  attachmentName
687
707
  }),
688
- openReadStream: async (docId, attachmentName) => {
708
+ openReadStream: async (docId, attachmentName, options) => {
689
709
  const result = await this.rpc.call("attachments.openReadStream", {
690
710
  databaseId: this.databaseId,
691
711
  docId,
692
- attachmentName
712
+ attachmentName,
713
+ timestamp: options?.timestamp,
714
+ revisionId: options?.revisionId
693
715
  });
694
716
  return new MindooDBAppReadableAttachmentStreamImpl(this.rpc, result.streamId);
695
717
  },
@@ -706,13 +728,15 @@ var MindooDBAppDatabaseImpl = class {
706
728
  databaseId: this.databaseId,
707
729
  docId,
708
730
  attachmentName,
709
- timestamp: options?.timestamp
731
+ timestamp: options?.timestamp,
732
+ revisionId: options?.revisionId
710
733
  }),
711
734
  openPreview: async (docId, attachmentName, options) => await this.rpc.call("attachments.openPreview", {
712
735
  databaseId: this.databaseId,
713
736
  docId,
714
737
  attachmentName,
715
- timestamp: options?.timestamp
738
+ timestamp: options?.timestamp,
739
+ revisionId: options?.revisionId
716
740
  })
717
741
  };
718
742
  }
@@ -736,7 +760,7 @@ var MindooDBAppSessionImpl = class {
736
760
  };
737
761
  }
738
762
  menus;
739
- /** Returns the launch context provided by the Administrator host. */
763
+ /** Returns the launch context provided by the Haven host. */
740
764
  async getLaunchContext() {
741
765
  return await this.rpc.call("session.getLaunchContext", {});
742
766
  }
@@ -817,6 +841,145 @@ function createMindooDBAppBridge() {
817
841
  };
818
842
  }
819
843
 
844
+ // src/textBuffer.ts
845
+ var MindooDBTextBuffer = class {
846
+ constructor(options) {
847
+ this.options = options;
848
+ this.valueInternal = readTextAtPath(options.document.data, options.path);
849
+ this.heads = options.document.heads ? [...options.document.heads] : [];
850
+ }
851
+ valueInternal;
852
+ heads;
853
+ pendingEdits = [];
854
+ get value() {
855
+ return this.valueInternal;
856
+ }
857
+ /** Whether there are local edits that have not been flushed yet. */
858
+ get dirty() {
859
+ return this.pendingEdits.length > 0;
860
+ }
861
+ /** Number of pending text operations currently buffered. */
862
+ get pendingCount() {
863
+ return this.pendingEdits.length;
864
+ }
865
+ /** Return the current local text value. */
866
+ toString() {
867
+ return this.valueInternal;
868
+ }
869
+ /**
870
+ * Apply an exact local text splice and queue it for the next flush.
871
+ *
872
+ * Offsets use JavaScript string indexing. The delete count is clamped to the
873
+ * remaining local text length so callers can safely delete to the end.
874
+ */
875
+ splice(index, deleteCount, insert = "") {
876
+ if (!Number.isInteger(index) || index < 0 || index > this.valueInternal.length) {
877
+ throw new RangeError("Text splice index is out of range");
878
+ }
879
+ if (!Number.isInteger(deleteCount) || deleteCount < 0) {
880
+ throw new RangeError("Text splice deleteCount must be a non-negative integer");
881
+ }
882
+ const clampedDeleteCount = Math.min(deleteCount, this.valueInternal.length - index);
883
+ this.valueInternal = this.valueInternal.slice(0, index) + insert + this.valueInternal.slice(index + clampedDeleteCount);
884
+ this.pendingEdits.push({ index, deleteCount: clampedDeleteCount, insert });
885
+ }
886
+ /**
887
+ * Replace the current local text value and queue the change as one splice.
888
+ *
889
+ * This is useful for editors such as Milkdown that can produce the full
890
+ * markdown string after each transaction but do not expose raw text splices.
891
+ */
892
+ replaceText(nextValue) {
893
+ if (nextValue === this.valueInternal) {
894
+ return;
895
+ }
896
+ const edit = computeSingleSplice(this.valueInternal, nextValue);
897
+ this.splice(edit.index, edit.deleteCount, edit.insert ?? "");
898
+ }
899
+ /**
900
+ * Replace local state from a fresh document snapshot and clear pending edits.
901
+ *
902
+ * Returns whether the text value changed. Use this after an external refresh
903
+ * or after receiving a document update through another app-level mechanism.
904
+ */
905
+ reconcile(document) {
906
+ const nextValue = readTextAtPath(document.data, this.options.path);
907
+ const changed = nextValue !== this.valueInternal;
908
+ this.valueInternal = nextValue;
909
+ this.heads = document.heads ? [...document.heads] : [];
910
+ this.pendingEdits = [];
911
+ return changed;
912
+ }
913
+ /**
914
+ * Flush pending edits to Haven using `documents.update({ text: ... })`.
915
+ *
916
+ * The request includes the document heads this buffer is based on, allowing
917
+ * Haven to apply the text operations at the original causal version and merge
918
+ * them with any concurrent document changes. After a successful flush the
919
+ * buffer adopts the returned canonical value and heads, and clears the
920
+ * pending edit queue.
921
+ */
922
+ async flush() {
923
+ if (this.pendingEdits.length === 0) {
924
+ return {
925
+ document: this.options.document,
926
+ value: this.valueInternal,
927
+ reconciled: false
928
+ };
929
+ }
930
+ const localValueAtFlush = this.valueInternal;
931
+ const document = await this.options.database.documents.update(this.options.document.id, {
932
+ text: [{
933
+ path: this.options.path,
934
+ baseHeads: this.heads,
935
+ edits: this.pendingEdits.map((edit) => ({ ...edit }))
936
+ }]
937
+ });
938
+ const nextValue = readTextAtPath(document.data, this.options.path);
939
+ const reconciled = nextValue !== localValueAtFlush;
940
+ this.valueInternal = nextValue;
941
+ this.heads = document.heads ? [...document.heads] : [];
942
+ this.pendingEdits = [];
943
+ return {
944
+ document,
945
+ value: this.valueInternal,
946
+ reconciled
947
+ };
948
+ }
949
+ };
950
+ function createMindooDBTextBuffer(options) {
951
+ return new MindooDBTextBuffer(options);
952
+ }
953
+ function readTextAtPath(data, path) {
954
+ let value = data;
955
+ for (const segment of path) {
956
+ if (value == null || typeof value !== "object") {
957
+ return "";
958
+ }
959
+ value = value[segment];
960
+ }
961
+ return typeof value === "string" ? value : "";
962
+ }
963
+ function computeSingleSplice(previous, next) {
964
+ let prefixLength = 0;
965
+ const maxPrefix = Math.min(previous.length, next.length);
966
+ while (prefixLength < maxPrefix && previous[prefixLength] === next[prefixLength]) {
967
+ prefixLength += 1;
968
+ }
969
+ let suffixLength = 0;
970
+ const previousRemaining = previous.length - prefixLength;
971
+ const nextRemaining = next.length - prefixLength;
972
+ const maxSuffix = Math.min(previousRemaining, nextRemaining);
973
+ while (suffixLength < maxSuffix && previous[previous.length - 1 - suffixLength] === next[next.length - 1 - suffixLength]) {
974
+ suffixLength += 1;
975
+ }
976
+ return {
977
+ index: prefixLength,
978
+ deleteCount: previous.length - prefixLength - suffixLength,
979
+ insert: next.slice(prefixLength, next.length - suffixLength)
980
+ };
981
+ }
982
+
820
983
  // src/viewLanguage.ts
821
984
  import {
822
985
  createViewLanguage,
@@ -825,9 +988,11 @@ import {
825
988
  mindooDBViewLanguageHelpersByName
826
989
  } from "mindoodb-view-language";
827
990
  export {
991
+ MindooDBTextBuffer,
828
992
  abbreviateCanonicalName,
829
993
  canPreviewAttachment,
830
994
  createMindooDBAppBridge,
995
+ createMindooDBTextBuffer,
831
996
  createViewLanguage,
832
997
  expandAbbreviatedName
833
998
  };
@@ -1,4 +1,4 @@
1
- import { a4 as MindooDBAppLaunchContext, V as MindooDBAppDatabaseInfo, X as MindooDBAppDocumentApi, T as MindooDBAppCreateViewNavigatorInput, ay as MindooDBAppViewNavigator, aA as MindooDBAppViewNavigatorOpenOptions, b as MindooDBAppAttachmentApi, a as MindooDBAppBridge, ao as MindooDBAppSession, n as MindooDBAppBridgeRpcRequest, a3 as MindooDBAppHostTheme, aF as MindooDBAppViewport, as as MindooDBAppUiPreferences, k as MindooDBAppBridgePortMessage } from '../types-B1iKRIuy.js';
1
+ import { a6 as MindooDBAppLaunchContext, X as MindooDBAppDatabaseInfo, Y as MindooDBAppDocumentApi, W as MindooDBAppCreateViewNavigatorInput, aC as MindooDBAppViewNavigator, aE as MindooDBAppViewNavigatorOpenOptions, d as MindooDBAppAttachmentApi, a as MindooDBAppBridge, aq as MindooDBAppSession, q as MindooDBAppBridgeRpcRequest, a5 as MindooDBAppHostTheme, aJ as MindooDBAppViewport, aw as MindooDBAppUiPreferences, n as MindooDBAppBridgePortMessage } from '../types-D0vtIHBf.js';
2
2
  import 'mindoodb-view-language';
3
3
 
4
4
  type MaybePromise<T> = T | Promise<T>;
@@ -20,8 +20,37 @@ function applyDocumentUpdatePatch(current, patch) {
20
20
  for (const key of patch.unset ?? []) {
21
21
  Reflect.deleteProperty(next, key);
22
22
  }
23
+ for (const textPatch of patch.text ?? []) {
24
+ applyMockTextPatch(next, textPatch.path, textPatch.edits);
25
+ }
23
26
  return next;
24
27
  }
28
+ function applyMockTextPatch(target, path, edits) {
29
+ if (path.length === 0) {
30
+ throw new Error("Text patch path must contain at least one segment");
31
+ }
32
+ let parent = target;
33
+ for (let index = 0; index < path.length - 1; index += 1) {
34
+ const segment = path[index];
35
+ const nextSegment = path[index + 1];
36
+ if (parent[segment] == null) {
37
+ parent[segment] = typeof nextSegment === "number" ? [] : {};
38
+ }
39
+ parent = parent[segment];
40
+ }
41
+ const leaf = path[path.length - 1];
42
+ let value = parent[leaf];
43
+ if (value == null) {
44
+ value = "";
45
+ }
46
+ if (typeof value !== "string") {
47
+ throw new Error(`Cannot apply text patch to non-string value at ${path.map(String).join(".")}`);
48
+ }
49
+ for (const edit of edits) {
50
+ value = value.slice(0, edit.index) + (edit.insert ?? "") + value.slice(edit.index + edit.deleteCount);
51
+ }
52
+ parent[leaf] = value;
53
+ }
25
54
  function mergeLaunchContext(current, patch) {
26
55
  if (!patch) {
27
56
  return {
@@ -393,6 +422,7 @@ function createDefaultViewNavigator() {
393
422
  }
394
423
  function createDatabaseHandle(definition) {
395
424
  let createCounter = 0;
425
+ let changeCounter = 0;
396
426
  const defaultViewFactory = async () => createDefaultViewNavigator();
397
427
  const storedDocuments = /* @__PURE__ */ new Map();
398
428
  const defaultDocuments = {
@@ -438,16 +468,42 @@ function createDatabaseHandle(definition) {
438
468
  return {
439
469
  id: document.id,
440
470
  data: structuredClone(document.data),
471
+ heads: document.heads ? [...document.heads] : void 0,
441
472
  attachments: document.attachments ? structuredClone(document.attachments) : [],
442
473
  updatedAt: document.updatedAt
443
474
  };
444
475
  },
445
476
  async create(input) {
446
- createCounter += 1;
477
+ const callerId = typeof input.id === "string" && input.id.length > 0 ? input.id : null;
478
+ if (callerId) {
479
+ const existing = storedDocuments.get(callerId);
480
+ if (existing) {
481
+ if (existing.isDeleted) {
482
+ existing.isDeleted = false;
483
+ existing.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
484
+ existing.heads = [`mock-head-${++changeCounter}`];
485
+ }
486
+ return {
487
+ id: existing.id,
488
+ data: structuredClone(existing.data),
489
+ heads: existing.heads ? [...existing.heads] : void 0,
490
+ attachments: existing.attachments ? structuredClone(existing.attachments) : [],
491
+ updatedAt: existing.updatedAt
492
+ };
493
+ }
494
+ }
495
+ let id;
496
+ if (callerId) {
497
+ id = callerId;
498
+ } else {
499
+ createCounter += 1;
500
+ id = `doc-${createCounter}`;
501
+ }
447
502
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
448
503
  const created = {
449
- id: `doc-${createCounter}`,
504
+ id,
450
505
  data: { ...input.set },
506
+ heads: [`mock-head-${++changeCounter}`],
451
507
  attachments: [],
452
508
  updatedAt: createdAt
453
509
  };
@@ -467,6 +523,7 @@ function createDatabaseHandle(definition) {
467
523
  const updated = {
468
524
  id: docId,
469
525
  data: applyDocumentUpdatePatch(existing?.data ?? {}, patch),
526
+ heads: [`mock-head-${++changeCounter}`],
470
527
  attachments: existing?.attachments ? structuredClone(existing.attachments) : [],
471
528
  updatedAt
472
529
  };
@@ -489,6 +546,18 @@ function createDatabaseHandle(definition) {
489
546
  }
490
547
  return { ok: true };
491
548
  },
549
+ async undelete(_docId) {
550
+ const existing = storedDocuments.get(_docId);
551
+ if (existing) {
552
+ storedDocuments.set(_docId, {
553
+ ...existing,
554
+ isDeleted: false,
555
+ heads: [`mock-head-${++changeCounter}`],
556
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
557
+ });
558
+ }
559
+ return { ok: true };
560
+ },
492
561
  async listHistory(_docId) {
493
562
  return [];
494
563
  },
@@ -497,7 +566,19 @@ function createDatabaseHandle(definition) {
497
566
  id: docId,
498
567
  timestamp,
499
568
  state: "missing",
500
- data: null
569
+ data: null,
570
+ attachments: []
571
+ };
572
+ },
573
+ async getAtRevision(docId, revisionId) {
574
+ return {
575
+ id: docId,
576
+ revisionId,
577
+ timestamp: Date.now(),
578
+ heads: [],
579
+ state: "missing",
580
+ data: null,
581
+ attachments: []
501
582
  };
502
583
  }
503
584
  };
@@ -510,13 +591,13 @@ function createDatabaseHandle(definition) {
510
591
  }
511
592
  };
512
593
  const defaultAttachments = {
513
- async list(_docId) {
594
+ async list(_docId, _options) {
514
595
  return [];
515
596
  },
516
597
  async remove(_docId, _attachmentName) {
517
598
  return { ok: true };
518
599
  },
519
- async openReadStream(_docId, _attachmentName) {
600
+ async openReadStream(_docId, _attachmentName, _options) {
520
601
  return createDefaultReadableAttachmentStream();
521
602
  },
522
603
  async openWriteStream(_docId, _attachmentName, _contentType) {
@@ -931,6 +1012,8 @@ function createFakeBridgeHost(options = {}) {
931
1012
  );
932
1013
  case "documents.delete":
933
1014
  return await state.getDatabase(String(params.databaseId)).documents.delete(String(params.docId));
1015
+ case "documents.undelete":
1016
+ return await state.getDatabase(String(params.databaseId)).documents.undelete(String(params.docId));
934
1017
  case "documents.history.list":
935
1018
  return await state.getDatabase(String(params.databaseId)).documents.listHistory(String(params.docId));
936
1019
  case "documents.history.getAtTimestamp":
@@ -938,8 +1021,16 @@ function createFakeBridgeHost(options = {}) {
938
1021
  String(params.docId),
939
1022
  Number(params.timestamp)
940
1023
  );
1024
+ case "documents.history.getAtRevision":
1025
+ return await state.getDatabase(String(params.databaseId)).documents.getAtRevision(
1026
+ String(params.docId),
1027
+ String(params.revisionId)
1028
+ );
941
1029
  case "attachments.list":
942
- return await state.getDatabase(String(params.databaseId)).attachments.list(String(params.docId));
1030
+ return await state.getDatabase(String(params.databaseId)).attachments.list(
1031
+ String(params.docId),
1032
+ typeof params.revisionId === "string" ? { revisionId: params.revisionId } : typeof params.timestamp === "number" ? { timestamp: params.timestamp } : void 0
1033
+ );
943
1034
  case "attachments.remove":
944
1035
  return await state.getDatabase(String(params.databaseId)).attachments.remove(
945
1036
  String(params.docId),
@@ -948,7 +1039,8 @@ function createFakeBridgeHost(options = {}) {
948
1039
  case "attachments.openReadStream": {
949
1040
  const stream = await state.getDatabase(String(params.databaseId)).attachments.openReadStream(
950
1041
  String(params.docId),
951
- String(params.attachmentName)
1042
+ String(params.attachmentName),
1043
+ typeof params.revisionId === "string" ? { revisionId: params.revisionId } : typeof params.timestamp === "number" ? { timestamp: params.timestamp } : void 0
952
1044
  );
953
1045
  const streamId = `read-${streamCounter += 1}`;
954
1046
  readStreams.set(streamId, stream);
@@ -968,13 +1060,13 @@ function createFakeBridgeHost(options = {}) {
968
1060
  return await state.getDatabase(String(params.databaseId)).attachments.openPreview(
969
1061
  String(params.docId),
970
1062
  String(params.attachmentName),
971
- typeof params.timestamp === "number" ? { timestamp: params.timestamp } : void 0
1063
+ typeof params.revisionId === "string" ? { revisionId: params.revisionId } : typeof params.timestamp === "number" ? { timestamp: params.timestamp } : void 0
972
1064
  );
973
1065
  case "attachments.preparePreviewSession":
974
1066
  return await state.getDatabase(String(params.databaseId)).attachments.preparePreviewSession(
975
1067
  String(params.docId),
976
1068
  String(params.attachmentName),
977
- typeof params.timestamp === "number" ? { timestamp: params.timestamp } : void 0
1069
+ typeof params.revisionId === "string" ? { revisionId: params.revisionId } : typeof params.timestamp === "number" ? { timestamp: params.timestamp } : void 0
978
1070
  );
979
1071
  case "viewNavigators.getDefinition":
980
1072
  return await (await resolveViewNavigator(String(params.navigatorId))).getDefinition();
@@ -1,8 +1,8 @@
1
1
  import { MindooDBAppBooleanExpression, MindooDBAppExpression, MindooDBAppViewSortDirection, MindooDBAppViewTotalMode, MindooDBAppViewDefinition } from 'mindoodb-view-language';
2
2
 
3
- /** Launch target used by the Administrator when opening an app. */
3
+ /** Launch target used by the Haven when opening an app. */
4
4
  type MindooDBAppRuntime = "iframe" | "window";
5
- /** Theme mode currently active in the Administrator host UI. */
5
+ /** Theme mode currently active in the Haven host UI. */
6
6
  type MindooDBAppThemeMode = "light" | "dark";
7
7
  /** Host theme snapshot exposed to running apps. */
8
8
  interface MindooDBAppHostTheme {
@@ -130,6 +130,8 @@ type MindooDBAppAttachmentPreviewMode = "image" | "pdf" | "text" | "markdown" |
130
130
  interface MindooDBAppAttachmentPreviewOptions {
131
131
  /** Historical snapshot timestamp previously obtained from `documents.history.getAtTimestamp()`. */
132
132
  timestamp?: number;
133
+ /** Stable revision id previously obtained from `documents.listHistory()`. */
134
+ revisionId?: MindooDBAppDocumentRevisionId;
133
135
  }
134
136
  /** Resolved Haven preview session prepared for opening in a separate tab or window. */
135
137
  interface MindooDBAppAttachmentPreviewSession {
@@ -157,12 +159,18 @@ interface MindooDBAppDocumentSummary {
157
159
  interface MindooDBAppDocument {
158
160
  id: string;
159
161
  data: Record<string, unknown>;
162
+ /** Current Automerge heads for causal text edit reconciliation. */
163
+ heads?: string[];
160
164
  attachments?: MindooDBAppAttachmentInfo[];
161
165
  updatedAt?: string;
162
166
  }
167
+ /** Opaque persisted id for a document revision in the MindooDB DAG. */
168
+ type MindooDBAppDocumentRevisionId = string;
163
169
  /** One entry in the document history timeline. */
164
170
  interface MindooDBAppDocumentHistoryEntry {
171
+ revisionId: MindooDBAppDocumentRevisionId;
165
172
  timestamp: number;
173
+ heads?: string[];
166
174
  publicKey: string;
167
175
  publicKeyFingerprint?: string;
168
176
  identityLabel?: string;
@@ -173,9 +181,13 @@ interface MindooDBAppDocumentHistoryEntry {
173
181
  /** Historical snapshot returned for a document at a specific timestamp. */
174
182
  interface MindooDBAppHistoricalDocument {
175
183
  id: string;
184
+ revisionId?: MindooDBAppDocumentRevisionId;
176
185
  timestamp: number;
186
+ heads?: string[];
177
187
  state: "missing" | "deleted" | "exists";
178
188
  data: Record<string, unknown> | null;
189
+ attachments?: MindooDBAppAttachmentInfo[];
190
+ attachmentSnapshotRevisionId?: MindooDBAppDocumentRevisionId | null;
179
191
  }
180
192
  /** Query options for paging through changefeed-backed document listings in a database. */
181
193
  interface MindooDBAppDocumentListQuery {
@@ -220,6 +232,33 @@ interface MindooDBAppCreateDocumentInput {
220
232
  set: Record<string, unknown>;
221
233
  /** Optional named document key. Defaults to `"default"` when omitted. */
222
234
  decryptionKeyId?: string;
235
+ /**
236
+ * Optional caller-provided document id. When omitted, MindooDB generates a
237
+ * UUID7. When provided, the id must match `^[A-Za-z][A-Za-z0-9_]*$`: the
238
+ * first character is an ASCII letter and subsequent characters may be ASCII
239
+ * letters, ASCII digits, or `_`.
240
+ *
241
+ * If a document with this id already exists locally, MindooDB returns the
242
+ * existing document instead of creating a new one (idempotent create), and
243
+ * the values in `set` are NOT applied. Caller-provided ids are useful for
244
+ * loading a known well-known document directly without first building a
245
+ * view, and for migrations that want to preserve external ids.
246
+ *
247
+ * Documents created with the same caller-provided id on independent replicas
248
+ * share Automerge ancestry, so subsequent edits on either replica still
249
+ * merge correctly when the replicas sync.
250
+ */
251
+ id?: string;
252
+ }
253
+ interface MindooDBAppTextEdit {
254
+ index: number;
255
+ deleteCount: number;
256
+ insert?: string;
257
+ }
258
+ interface MindooDBAppTextPatch {
259
+ path: Array<string | number>;
260
+ baseHeads?: string[];
261
+ edits: MindooDBAppTextEdit[];
223
262
  }
224
263
  /**
225
264
  * Sparse patch payload used when updating an existing document.
@@ -233,6 +272,8 @@ interface MindooDBAppUpdateDocumentInput {
233
272
  set?: Record<string, unknown>;
234
273
  /** Top-level fields to remove from the document entirely. */
235
274
  unset?: string[];
275
+ /** Granular text edits to apply at document paths. */
276
+ text?: MindooDBAppTextPatch[];
236
277
  }
237
278
  /** Query used for history lookups at a specific timestamp. */
238
279
  interface MindooDBAppHistoryQuery {
@@ -244,17 +285,23 @@ interface MindooDBAppBridgeConnectOptions {
244
285
  targetOrigin?: string;
245
286
  connectTimeoutMs?: number;
246
287
  }
247
- /** Initial postMessage handshake sent from the app to the Administrator. */
288
+ /** Initial postMessage handshake sent from the app to the Haven. */
248
289
  interface MindooDBAppBridgeConnectMessage {
249
290
  protocol: "mindoodb-app-bridge";
250
291
  type: "mindoodb-app:connect";
251
292
  launchId: string;
252
293
  }
253
- /** Handshake acknowledgement returned by the Administrator host. */
294
+ /** Handshake acknowledgement returned by the Haven host. */
254
295
  interface MindooDBAppBridgeConnectedMessage {
255
296
  protocol: "mindoodb-app-bridge";
256
297
  type: "mindoodb-app:connected";
257
298
  }
299
+ /** Handshake error returned when the Haven host rejects a launch. */
300
+ interface MindooDBAppBridgeHandshakeErrorMessage {
301
+ protocol: "mindoodb-app-bridge";
302
+ type: "mindoodb-app:error";
303
+ error: string;
304
+ }
258
305
  /** Structured error payload transported over bridge RPC or stream messages. */
259
306
  interface MindooDBAppBridgeErrorPayload {
260
307
  code: string;
@@ -336,7 +383,7 @@ interface MindooDBAppBridgeStreamError {
336
383
  }
337
384
  /** Union of all non-RPC stream transport messages. */
338
385
  type MindooDBAppBridgeStreamMessage = MindooDBAppBridgeStreamReadRequest | MindooDBAppBridgeStreamWriteRequest | MindooDBAppBridgeStreamCloseRequest | MindooDBAppBridgeStreamAbortRequest | MindooDBAppAttachmentChunk | MindooDBAppBridgeStreamAck | MindooDBAppBridgeStreamError;
339
- /** Host-pushed event emitted when the Administrator theme changes. */
386
+ /** Host-pushed event emitted when the Haven theme changes. */
340
387
  interface MindooDBAppBridgeThemeChangedMessage {
341
388
  protocol: "mindoodb-app-bridge";
342
389
  kind: "theme-changed";
@@ -445,8 +492,12 @@ interface MindooDBAppDocumentApi {
445
492
  delete(docId: string): Promise<{
446
493
  ok: true;
447
494
  }>;
495
+ undelete(docId: string): Promise<{
496
+ ok: true;
497
+ }>;
448
498
  listHistory(docId: string): Promise<MindooDBAppDocumentHistoryEntry[]>;
449
499
  getAtTimestamp(docId: string, timestamp: number): Promise<MindooDBAppHistoricalDocument>;
500
+ getAtRevision(docId: string, revisionId: MindooDBAppDocumentRevisionId): Promise<MindooDBAppHistoricalDocument>;
450
501
  }
451
502
  type MindooDBAppViewEntryKind = "category" | "document";
452
503
  /** Unique document identity within a multi-source view. */
@@ -570,11 +621,11 @@ interface MindooDBAppViewNavigator {
570
621
  }
571
622
  /** Attachment operations exposed by an opened database handle. */
572
623
  interface MindooDBAppAttachmentApi {
573
- list(docId: string): Promise<MindooDBAppAttachmentInfo[]>;
624
+ list(docId: string, options?: MindooDBAppAttachmentPreviewOptions): Promise<MindooDBAppAttachmentInfo[]>;
574
625
  remove(docId: string, attachmentName: string): Promise<{
575
626
  ok: true;
576
627
  }>;
577
- openReadStream(docId: string, attachmentName: string): Promise<MindooDBAppReadableAttachmentStream>;
628
+ openReadStream(docId: string, attachmentName: string, options?: MindooDBAppAttachmentPreviewOptions): Promise<MindooDBAppReadableAttachmentStream>;
578
629
  openWriteStream(docId: string, attachmentName: string, contentType?: string): Promise<MindooDBAppWritableAttachmentStream>;
579
630
  preparePreviewSession(docId: string, attachmentName: string, options?: MindooDBAppAttachmentPreviewOptions): Promise<MindooDBAppAttachmentPreviewSession>;
580
631
  openPreview(docId: string, attachmentName: string, options?: MindooDBAppAttachmentPreviewOptions): Promise<{
@@ -587,7 +638,7 @@ interface MindooDBAppDatabase {
587
638
  documents: MindooDBAppDocumentApi;
588
639
  attachments: MindooDBAppAttachmentApi;
589
640
  }
590
- /** Connected session between the running app and the Administrator host. */
641
+ /** Connected session between the running app and the Haven host. */
591
642
  interface MindooDBAppSession {
592
643
  getLaunchContext(): Promise<MindooDBAppLaunchContext>;
593
644
  listDatabases(): Promise<MindooDBAppDatabaseInfo[]>;
@@ -606,4 +657,4 @@ interface MindooDBAppBridge {
606
657
  connect(options?: MindooDBAppBridgeConnectOptions): Promise<MindooDBAppSession>;
607
658
  }
608
659
 
609
- export type { MindooDBAppDocumentListResult as $, MindooDBAppCapability as A, MindooDBAppConfiguredViewCategorizationStyle as B, MindooDBAppConfiguredViewColumn as C, MindooDBAppConfiguredViewColumnRole as D, MindooDBAppConfiguredViewExpressionMode as E, MindooDBAppConfiguredViewFieldExpression as F, MindooDBAppConfiguredViewFilterDefinition as G, MindooDBAppConfiguredViewFilterMode as H, MindooDBAppConfiguredViewFilterRule as I, MindooDBAppConfiguredViewFormulaExpression as J, MindooDBAppConfiguredViewFormulaFilterDefinition as K, MindooDBAppConfiguredViewPreviewMode as L, MindooDBAppAttachmentPreviewMode as M, MindooDBAppConfiguredViewRuleFilterDefinition as N, MindooDBAppConfiguredViewRuleMatchMode as O, MindooDBAppConfiguredViewRuleOperator as P, MindooDBAppConfiguredViewValueExpression as Q, MindooDBAppCreateDocumentInput as R, MindooDBAppCreateViewInput as S, MindooDBAppCreateViewNavigatorInput as T, MindooDBAppDatabase as U, MindooDBAppDatabaseInfo as V, MindooDBAppDocument as W, MindooDBAppDocumentApi as X, MindooDBAppDocumentHeadCursorResult as Y, MindooDBAppDocumentHistoryEntry as Z, MindooDBAppDocumentListQuery as _, MindooDBAppBridge as a, MindooDBAppDocumentSummary as a0, MindooDBAppHistoricalDocument as a1, MindooDBAppHistoryQuery as a2, MindooDBAppHostTheme as a3, MindooDBAppLaunchContext as a4, MindooDBAppMenuAnchor as a5, MindooDBAppMenuApi as a6, MindooDBAppMenuCommandItem as a7, MindooDBAppMenuDismissReason as a8, MindooDBAppMenuDismissedResult as a9, MindooDBAppViewNavigatorOpenOptions as aA, MindooDBAppViewNavigatorPageOptions as aB, MindooDBAppViewNavigatorPageResult as aC, MindooDBAppViewNavigatorRangeQuery as aD, MindooDBAppViewNavigatorSelectionState as aE, MindooDBAppViewport as aF, MindooDBAppWritableAttachmentStream as aG, MindooDBAppMenuItem as aa, MindooDBAppMenuKind as ab, MindooDBAppMenuPlacement as ac, MindooDBAppMenuPointAnchor as ad, MindooDBAppMenuRect as ae, MindooDBAppMenuRectAnchor as af, MindooDBAppMenuSelectionResult as ag, MindooDBAppMenuSeparatorItem as ah, MindooDBAppReadableAttachmentStream as ai, MindooDBAppResolvedViewDefinition as aj, MindooDBAppResolvedViewSource as ak, MindooDBAppRuntime as al, MindooDBAppScopedDocId as am, MindooDBAppScopedDocumentSummary as an, MindooDBAppSession as ao, MindooDBAppShowMenuInput as ap, MindooDBAppShowMenuResult as aq, MindooDBAppThemeMode as ar, MindooDBAppUiPreferences as as, MindooDBAppUpdateDocumentInput as at, MindooDBAppViewCursorDocumentListResult as au, MindooDBAppViewCursorResult as av, MindooDBAppViewEntry as aw, MindooDBAppViewEntryKind as ax, MindooDBAppViewNavigator as ay, MindooDBAppViewNavigatorExpansionState as az, MindooDBAppAttachmentApi as b, MindooDBAppAttachmentChunk as c, MindooDBAppAttachmentInfo as d, MindooDBAppAttachmentPreviewOptions as e, MindooDBAppAttachmentPreviewSession as f, MindooDBAppBridgeConnectMessage as g, MindooDBAppBridgeConnectOptions as h, MindooDBAppBridgeConnectedMessage as i, MindooDBAppBridgeErrorPayload as j, MindooDBAppBridgePortMessage as k, MindooDBAppBridgeRpcError as l, MindooDBAppBridgeRpcMessage as m, MindooDBAppBridgeRpcRequest as n, MindooDBAppBridgeRpcSuccess as o, MindooDBAppBridgeStreamAbortRequest as p, MindooDBAppBridgeStreamAck as q, MindooDBAppBridgeStreamCloseRequest as r, MindooDBAppBridgeStreamError as s, MindooDBAppBridgeStreamMessage as t, MindooDBAppBridgeStreamOpenResult as u, MindooDBAppBridgeStreamReadRequest as v, MindooDBAppBridgeStreamWriteRequest as w, MindooDBAppBridgeThemeChangedMessage as x, MindooDBAppBridgeUiPreferencesChangedMessage as y, MindooDBAppBridgeViewportChangedMessage as z };
660
+ export type { MindooDBAppDocumentListQuery as $, MindooDBAppBridgeThemeChangedMessage as A, MindooDBAppBridgeUiPreferencesChangedMessage as B, MindooDBAppBridgeViewportChangedMessage as C, MindooDBAppCapability as D, MindooDBAppConfiguredViewCategorizationStyle as E, MindooDBAppConfiguredViewColumn as F, MindooDBAppConfiguredViewColumnRole as G, MindooDBAppConfiguredViewExpressionMode as H, MindooDBAppConfiguredViewFieldExpression as I, MindooDBAppConfiguredViewFilterDefinition as J, MindooDBAppConfiguredViewFilterMode as K, MindooDBAppConfiguredViewFilterRule as L, MindooDBAppAttachmentPreviewMode as M, MindooDBAppConfiguredViewFormulaExpression as N, MindooDBAppConfiguredViewFormulaFilterDefinition as O, MindooDBAppConfiguredViewPreviewMode as P, MindooDBAppConfiguredViewRuleFilterDefinition as Q, MindooDBAppConfiguredViewRuleMatchMode as R, MindooDBAppConfiguredViewRuleOperator as S, MindooDBAppConfiguredViewValueExpression as T, MindooDBAppCreateDocumentInput as U, MindooDBAppCreateViewInput as V, MindooDBAppCreateViewNavigatorInput as W, MindooDBAppDatabaseInfo as X, MindooDBAppDocumentApi as Y, MindooDBAppDocumentHeadCursorResult as Z, MindooDBAppDocumentHistoryEntry as _, MindooDBAppBridge as a, MindooDBAppDocumentListResult as a0, MindooDBAppDocumentRevisionId as a1, MindooDBAppDocumentSummary as a2, MindooDBAppHistoricalDocument as a3, MindooDBAppHistoryQuery as a4, MindooDBAppHostTheme as a5, MindooDBAppLaunchContext as a6, MindooDBAppMenuAnchor as a7, MindooDBAppMenuApi as a8, MindooDBAppMenuCommandItem as a9, MindooDBAppViewEntry as aA, MindooDBAppViewEntryKind as aB, MindooDBAppViewNavigator as aC, MindooDBAppViewNavigatorExpansionState as aD, MindooDBAppViewNavigatorOpenOptions as aE, MindooDBAppViewNavigatorPageOptions as aF, MindooDBAppViewNavigatorPageResult as aG, MindooDBAppViewNavigatorRangeQuery as aH, MindooDBAppViewNavigatorSelectionState as aI, MindooDBAppViewport as aJ, MindooDBAppWritableAttachmentStream as aK, MindooDBAppMenuDismissReason as aa, MindooDBAppMenuDismissedResult as ab, MindooDBAppMenuItem as ac, MindooDBAppMenuKind as ad, MindooDBAppMenuPlacement as ae, MindooDBAppMenuPointAnchor as af, MindooDBAppMenuRect as ag, MindooDBAppMenuRectAnchor as ah, MindooDBAppMenuSelectionResult as ai, MindooDBAppMenuSeparatorItem as aj, MindooDBAppReadableAttachmentStream as ak, MindooDBAppResolvedViewDefinition as al, MindooDBAppResolvedViewSource as am, MindooDBAppRuntime as an, MindooDBAppScopedDocId as ao, MindooDBAppScopedDocumentSummary as ap, MindooDBAppSession as aq, MindooDBAppShowMenuInput as ar, MindooDBAppShowMenuResult as as, MindooDBAppTextEdit as at, MindooDBAppTextPatch as au, MindooDBAppThemeMode as av, MindooDBAppUiPreferences as aw, MindooDBAppUpdateDocumentInput as ax, MindooDBAppViewCursorDocumentListResult as ay, MindooDBAppViewCursorResult as az, MindooDBAppDatabase as b, MindooDBAppDocument as c, MindooDBAppAttachmentApi as d, MindooDBAppAttachmentChunk as e, MindooDBAppAttachmentInfo as f, MindooDBAppAttachmentPreviewOptions as g, MindooDBAppAttachmentPreviewSession as h, MindooDBAppBridgeConnectMessage as i, MindooDBAppBridgeConnectOptions as j, MindooDBAppBridgeConnectedMessage as k, MindooDBAppBridgeErrorPayload as l, MindooDBAppBridgeHandshakeErrorMessage as m, MindooDBAppBridgePortMessage as n, MindooDBAppBridgeRpcError as o, MindooDBAppBridgeRpcMessage as p, MindooDBAppBridgeRpcRequest as q, MindooDBAppBridgeRpcSuccess as r, MindooDBAppBridgeStreamAbortRequest as s, MindooDBAppBridgeStreamAck as t, MindooDBAppBridgeStreamCloseRequest as u, MindooDBAppBridgeStreamError as v, MindooDBAppBridgeStreamMessage as w, MindooDBAppBridgeStreamOpenResult as x, MindooDBAppBridgeStreamReadRequest as y, MindooDBAppBridgeStreamWriteRequest as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mindoodb-app-sdk",
3
- "version": "0.0.14",
3
+ "version": "0.0.16",
4
4
  "description": "MindooDB app SDK for building apps that connect to the Haven host bridge",
5
5
  "license": "ISC",
6
6
  "author": "Mindoo GmbH",
@@ -40,7 +40,7 @@
40
40
  "prepublishOnly": "npm run build && npm run test"
41
41
  },
42
42
  "dependencies": {
43
- "mindoodb-view-language": "0.0.10"
43
+ "mindoodb-view-language": "0.0.11"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@types/node": "^25.5.0",