mindoodb-app-sdk 0.0.13 → 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,21 +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
- data: { title: "Meeting notes", content: "..." },
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
- data: { title: "Updated title" },
343
+ set: { title: "Updated title" },
344
+ unset: ["legacyField"],
345
+ });
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
+ ],
331
361
  });
332
362
 
333
363
  // Delete
334
364
  await db.documents.delete(docId);
365
+
366
+ // Undelete (resurrect a deleted document)
367
+ await db.documents.undelete(docId);
335
368
  ```
336
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
+
337
372
  `documents.list()` is backed by Haven's internal changefeed, not by a positional offset. The query object supports:
338
373
 
339
374
  | Field | Meaning |
@@ -348,22 +383,187 @@ await db.documents.delete(docId);
348
383
 
349
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`.
350
385
 
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.
393
+
351
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.
352
395
 
353
396
  ### Document history
354
397
 
355
- 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.
356
399
 
357
400
  ```ts
358
401
  // List all revisions
359
402
  const history = await db.documents.listHistory(docId);
360
- // 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
+ ```
431
+
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
+ └────────────────────────────────────────────────────┘
462
+ ```
361
463
 
362
- // Load the document state at a specific point in time
363
- const snapshot = await db.documents.getAtTimestamp(docId, history[0]!.timestamp);
364
- // { id, timestamp, state: "exists" | "deleted" | "missing", data }
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
365
500
  ```
366
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
+
367
567
  ### Incremental sync
368
568
 
369
569
  The changefeed-backed `documents.list()` API is also the right primitive for app-side indexes, search, and other derived caches.
@@ -454,6 +654,26 @@ await writer.close();
454
654
  await db.attachments.remove(docId, "old-file.txt");
455
655
  ```
456
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
+
457
677
  ### Attachment previews
458
678
 
459
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.
@@ -482,10 +702,12 @@ You can also preview attachments from a **historical document snapshot**:
482
702
 
483
703
  ```ts
484
704
  await db.attachments.openPreview(docId, "report.pdf", {
485
- timestamp: historyEntry.timestamp,
705
+ revisionId: historyEntry.revisionId,
486
706
  });
487
707
  ```
488
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
+
489
711
  **Check preview support locally** before showing a preview button:
490
712
 
491
713
  ```ts
@@ -726,21 +948,42 @@ Connect options: `launchId?`, `targetOrigin?`, `connectTimeoutMs?`.
726
948
  | `create(input)` | `Promise<MindooDBAppDocument>` |
727
949
  | `update(docId, patch)` | `Promise<MindooDBAppDocument>` |
728
950
  | `delete(docId)` | `Promise<{ ok: true }>` |
951
+ | `undelete(docId)` | `Promise<{ ok: true }>` |
729
952
  | `listHistory(docId)` | `Promise<MindooDBAppDocumentHistoryEntry[]>` |
730
953
  | `getAtTimestamp(docId, timestamp)` | `Promise<MindooDBAppHistoricalDocument>` |
954
+ | `getAtRevision(docId, revisionId)` | `Promise<MindooDBAppHistoricalDocument>` |
731
955
 
732
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.
733
957
 
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).
973
+
734
974
  ### MindooDBAppAttachmentApi
735
975
 
736
976
  | Method | Returns |
737
977
  |---|---|
738
- | `list(docId)` | `Promise<MindooDBAppAttachmentInfo[]>` |
978
+ | `list(docId, options?)` | `Promise<MindooDBAppAttachmentInfo[]>` |
739
979
  | `remove(docId, attachmentName)` | `Promise<{ ok: true }>` |
740
- | `openReadStream(docId, attachmentName)` | `Promise<MindooDBAppReadableAttachmentStream>` |
980
+ | `openReadStream(docId, attachmentName, options?)` | `Promise<MindooDBAppReadableAttachmentStream>` |
741
981
  | `openWriteStream(docId, attachmentName, contentType?)` | `Promise<MindooDBAppWritableAttachmentStream>` |
982
+ | `preparePreviewSession(docId, attachmentName, options?)` | `Promise<MindooDBAppAttachmentPreviewSession>` |
742
983
  | `openPreview(docId, attachmentName, options?)` | `Promise<{ ok: true }>` |
743
984
 
985
+ `options` accepts `{ timestamp?: number; revisionId?: string }` for read-only historical attachment access. Mutation methods (`openWriteStream`, `remove`) always target the current document.
986
+
744
987
  ### MindooDBAppViewNavigator
745
988
 
746
989
  | Method | Returns |
@@ -787,6 +1030,7 @@ Connect options: `launchId?`, `targetOrigin?`, `connectTimeoutMs?`.
787
1030
  | Function | Description |
788
1031
  |---|---|
789
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 |
790
1034
  | `canPreviewAttachment(fileName, mimeType)` | Check if Haven can preview a file (returns mode or `null`) |
791
1035
  | `createViewLanguage<T>()` | Create a typed expression builder for view definitions |
792
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-Cqa7AQZl.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-Cqa7AQZl.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-Cqa7AQZl.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>;
@@ -12,6 +12,45 @@ function createBridgeErrorPayload(error, fallbackCode = "bridge-error") {
12
12
  function cloneBytes(chunk) {
13
13
  return new Uint8Array(chunk.buffer.slice(chunk.byteOffset, chunk.byteOffset + chunk.byteLength));
14
14
  }
15
+ function applyDocumentUpdatePatch(current, patch) {
16
+ const next = {
17
+ ...structuredClone(current),
18
+ ...patch.set ? structuredClone(patch.set) : {}
19
+ };
20
+ for (const key of patch.unset ?? []) {
21
+ Reflect.deleteProperty(next, key);
22
+ }
23
+ for (const textPatch of patch.text ?? []) {
24
+ applyMockTextPatch(next, textPatch.path, textPatch.edits);
25
+ }
26
+ return next;
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
+ }
15
54
  function mergeLaunchContext(current, patch) {
16
55
  if (!patch) {
17
56
  return {
@@ -383,6 +422,7 @@ function createDefaultViewNavigator() {
383
422
  }
384
423
  function createDatabaseHandle(definition) {
385
424
  let createCounter = 0;
425
+ let changeCounter = 0;
386
426
  const defaultViewFactory = async () => createDefaultViewNavigator();
387
427
  const storedDocuments = /* @__PURE__ */ new Map();
388
428
  const defaultDocuments = {
@@ -428,16 +468,42 @@ function createDatabaseHandle(definition) {
428
468
  return {
429
469
  id: document.id,
430
470
  data: structuredClone(document.data),
471
+ heads: document.heads ? [...document.heads] : void 0,
431
472
  attachments: document.attachments ? structuredClone(document.attachments) : [],
432
473
  updatedAt: document.updatedAt
433
474
  };
434
475
  },
435
476
  async create(input) {
436
- 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
+ }
437
502
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
438
503
  const created = {
439
- id: `doc-${createCounter}`,
440
- data: { ...input.data },
504
+ id,
505
+ data: { ...input.set },
506
+ heads: [`mock-head-${++changeCounter}`],
441
507
  attachments: [],
442
508
  updatedAt: createdAt
443
509
  };
@@ -456,7 +522,8 @@ function createDatabaseHandle(definition) {
456
522
  const existing = storedDocuments.get(docId);
457
523
  const updated = {
458
524
  id: docId,
459
- data: { ...patch.data },
525
+ data: applyDocumentUpdatePatch(existing?.data ?? {}, patch),
526
+ heads: [`mock-head-${++changeCounter}`],
460
527
  attachments: existing?.attachments ? structuredClone(existing.attachments) : [],
461
528
  updatedAt
462
529
  };
@@ -479,6 +546,18 @@ function createDatabaseHandle(definition) {
479
546
  }
480
547
  return { ok: true };
481
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
+ },
482
561
  async listHistory(_docId) {
483
562
  return [];
484
563
  },
@@ -487,7 +566,19 @@ function createDatabaseHandle(definition) {
487
566
  id: docId,
488
567
  timestamp,
489
568
  state: "missing",
490
- 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: []
491
582
  };
492
583
  }
493
584
  };
@@ -500,13 +591,13 @@ function createDatabaseHandle(definition) {
500
591
  }
501
592
  };
502
593
  const defaultAttachments = {
503
- async list(_docId) {
594
+ async list(_docId, _options) {
504
595
  return [];
505
596
  },
506
597
  async remove(_docId, _attachmentName) {
507
598
  return { ok: true };
508
599
  },
509
- async openReadStream(_docId, _attachmentName) {
600
+ async openReadStream(_docId, _attachmentName, _options) {
510
601
  return createDefaultReadableAttachmentStream();
511
602
  },
512
603
  async openWriteStream(_docId, _attachmentName, _contentType) {
@@ -921,6 +1012,8 @@ function createFakeBridgeHost(options = {}) {
921
1012
  );
922
1013
  case "documents.delete":
923
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));
924
1017
  case "documents.history.list":
925
1018
  return await state.getDatabase(String(params.databaseId)).documents.listHistory(String(params.docId));
926
1019
  case "documents.history.getAtTimestamp":
@@ -928,8 +1021,16 @@ function createFakeBridgeHost(options = {}) {
928
1021
  String(params.docId),
929
1022
  Number(params.timestamp)
930
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
+ );
931
1029
  case "attachments.list":
932
- 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
+ );
933
1034
  case "attachments.remove":
934
1035
  return await state.getDatabase(String(params.databaseId)).attachments.remove(
935
1036
  String(params.docId),
@@ -938,7 +1039,8 @@ function createFakeBridgeHost(options = {}) {
938
1039
  case "attachments.openReadStream": {
939
1040
  const stream = await state.getDatabase(String(params.databaseId)).attachments.openReadStream(
940
1041
  String(params.docId),
941
- String(params.attachmentName)
1042
+ String(params.attachmentName),
1043
+ typeof params.revisionId === "string" ? { revisionId: params.revisionId } : typeof params.timestamp === "number" ? { timestamp: params.timestamp } : void 0
942
1044
  );
943
1045
  const streamId = `read-${streamCounter += 1}`;
944
1046
  readStreams.set(streamId, stream);
@@ -958,13 +1060,13 @@ function createFakeBridgeHost(options = {}) {
958
1060
  return await state.getDatabase(String(params.databaseId)).attachments.openPreview(
959
1061
  String(params.docId),
960
1062
  String(params.attachmentName),
961
- 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
962
1064
  );
963
1065
  case "attachments.preparePreviewSession":
964
1066
  return await state.getDatabase(String(params.databaseId)).attachments.preparePreviewSession(
965
1067
  String(params.docId),
966
1068
  String(params.attachmentName),
967
- 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
968
1070
  );
969
1071
  case "viewNavigators.getDefinition":
970
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 {
@@ -210,15 +222,58 @@ interface MindooDBAppViewCursorDocumentListResult {
210
222
  items: MindooDBAppScopedDocumentSummary[];
211
223
  nextCursor: string | null;
212
224
  }
213
- /** Payload used when creating a new document. */
225
+ /**
226
+ * Payload used when creating a new document.
227
+ *
228
+ * `set` becomes the initial top-level document state, mirroring the update
229
+ * API's field-assignment language while still creating a brand-new document.
230
+ */
214
231
  interface MindooDBAppCreateDocumentInput {
215
- data: Record<string, unknown>;
232
+ set: Record<string, unknown>;
216
233
  /** Optional named document key. Defaults to `"default"` when omitted. */
217
234
  decryptionKeyId?: string;
218
- }
219
- /** Patch payload used when updating an existing document. */
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[];
262
+ }
263
+ /**
264
+ * Sparse patch payload used when updating an existing document.
265
+ *
266
+ * Prefer targeted `set` / `unset` operations over whole-document rewrites so
267
+ * MindooDB can preserve more meaningful change history and Automerge can merge
268
+ * smaller, more intentional updates.
269
+ */
220
270
  interface MindooDBAppUpdateDocumentInput {
221
- data: Record<string, unknown>;
271
+ /** Top-level fields to assign on the document. */
272
+ set?: Record<string, unknown>;
273
+ /** Top-level fields to remove from the document entirely. */
274
+ unset?: string[];
275
+ /** Granular text edits to apply at document paths. */
276
+ text?: MindooDBAppTextPatch[];
222
277
  }
223
278
  /** Query used for history lookups at a specific timestamp. */
224
279
  interface MindooDBAppHistoryQuery {
@@ -230,17 +285,23 @@ interface MindooDBAppBridgeConnectOptions {
230
285
  targetOrigin?: string;
231
286
  connectTimeoutMs?: number;
232
287
  }
233
- /** Initial postMessage handshake sent from the app to the Administrator. */
288
+ /** Initial postMessage handshake sent from the app to the Haven. */
234
289
  interface MindooDBAppBridgeConnectMessage {
235
290
  protocol: "mindoodb-app-bridge";
236
291
  type: "mindoodb-app:connect";
237
292
  launchId: string;
238
293
  }
239
- /** Handshake acknowledgement returned by the Administrator host. */
294
+ /** Handshake acknowledgement returned by the Haven host. */
240
295
  interface MindooDBAppBridgeConnectedMessage {
241
296
  protocol: "mindoodb-app-bridge";
242
297
  type: "mindoodb-app:connected";
243
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
+ }
244
305
  /** Structured error payload transported over bridge RPC or stream messages. */
245
306
  interface MindooDBAppBridgeErrorPayload {
246
307
  code: string;
@@ -322,7 +383,7 @@ interface MindooDBAppBridgeStreamError {
322
383
  }
323
384
  /** Union of all non-RPC stream transport messages. */
324
385
  type MindooDBAppBridgeStreamMessage = MindooDBAppBridgeStreamReadRequest | MindooDBAppBridgeStreamWriteRequest | MindooDBAppBridgeStreamCloseRequest | MindooDBAppBridgeStreamAbortRequest | MindooDBAppAttachmentChunk | MindooDBAppBridgeStreamAck | MindooDBAppBridgeStreamError;
325
- /** Host-pushed event emitted when the Administrator theme changes. */
386
+ /** Host-pushed event emitted when the Haven theme changes. */
326
387
  interface MindooDBAppBridgeThemeChangedMessage {
327
388
  protocol: "mindoodb-app-bridge";
328
389
  kind: "theme-changed";
@@ -431,8 +492,12 @@ interface MindooDBAppDocumentApi {
431
492
  delete(docId: string): Promise<{
432
493
  ok: true;
433
494
  }>;
495
+ undelete(docId: string): Promise<{
496
+ ok: true;
497
+ }>;
434
498
  listHistory(docId: string): Promise<MindooDBAppDocumentHistoryEntry[]>;
435
499
  getAtTimestamp(docId: string, timestamp: number): Promise<MindooDBAppHistoricalDocument>;
500
+ getAtRevision(docId: string, revisionId: MindooDBAppDocumentRevisionId): Promise<MindooDBAppHistoricalDocument>;
436
501
  }
437
502
  type MindooDBAppViewEntryKind = "category" | "document";
438
503
  /** Unique document identity within a multi-source view. */
@@ -556,11 +621,11 @@ interface MindooDBAppViewNavigator {
556
621
  }
557
622
  /** Attachment operations exposed by an opened database handle. */
558
623
  interface MindooDBAppAttachmentApi {
559
- list(docId: string): Promise<MindooDBAppAttachmentInfo[]>;
624
+ list(docId: string, options?: MindooDBAppAttachmentPreviewOptions): Promise<MindooDBAppAttachmentInfo[]>;
560
625
  remove(docId: string, attachmentName: string): Promise<{
561
626
  ok: true;
562
627
  }>;
563
- openReadStream(docId: string, attachmentName: string): Promise<MindooDBAppReadableAttachmentStream>;
628
+ openReadStream(docId: string, attachmentName: string, options?: MindooDBAppAttachmentPreviewOptions): Promise<MindooDBAppReadableAttachmentStream>;
564
629
  openWriteStream(docId: string, attachmentName: string, contentType?: string): Promise<MindooDBAppWritableAttachmentStream>;
565
630
  preparePreviewSession(docId: string, attachmentName: string, options?: MindooDBAppAttachmentPreviewOptions): Promise<MindooDBAppAttachmentPreviewSession>;
566
631
  openPreview(docId: string, attachmentName: string, options?: MindooDBAppAttachmentPreviewOptions): Promise<{
@@ -573,7 +638,7 @@ interface MindooDBAppDatabase {
573
638
  documents: MindooDBAppDocumentApi;
574
639
  attachments: MindooDBAppAttachmentApi;
575
640
  }
576
- /** Connected session between the running app and the Administrator host. */
641
+ /** Connected session between the running app and the Haven host. */
577
642
  interface MindooDBAppSession {
578
643
  getLaunchContext(): Promise<MindooDBAppLaunchContext>;
579
644
  listDatabases(): Promise<MindooDBAppDatabaseInfo[]>;
@@ -592,4 +657,4 @@ interface MindooDBAppBridge {
592
657
  connect(options?: MindooDBAppBridgeConnectOptions): Promise<MindooDBAppSession>;
593
658
  }
594
659
 
595
- 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.13",
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",