mindoodb-app-sdk 0.0.14 → 0.0.17

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/dist/index.js CHANGED
@@ -142,6 +142,7 @@ var PortRpcClient = class {
142
142
  this.port.addEventListener("message", this.handleMessage);
143
143
  this.port.start();
144
144
  }
145
+ port;
145
146
  pending = /* @__PURE__ */ new Map();
146
147
  listeners = /* @__PURE__ */ new Set();
147
148
  requestCounter = 0;
@@ -232,7 +233,10 @@ var PortRpcClient = class {
232
233
  var PROTOCOL2 = "mindoodb-app-bridge";
233
234
  var DEFAULT_CONNECT_TIMEOUT_MS = 1e4;
234
235
  function toTransferableArrayBuffer(chunk) {
235
- return chunk.buffer.slice(chunk.byteOffset, chunk.byteOffset + chunk.byteLength);
236
+ return chunk.buffer.slice(
237
+ chunk.byteOffset,
238
+ chunk.byteOffset + chunk.byteLength
239
+ );
236
240
  }
237
241
  function isStreamChunkFor(streamId, message) {
238
242
  return message.kind === "stream-chunk" && message.streamId === streamId;
@@ -262,7 +266,9 @@ function resolveLaunchId(options) {
262
266
  return options.launchId;
263
267
  }
264
268
  if (typeof window === "undefined") {
265
- throw new Error("A launchId must be provided when connecting outside the browser.");
269
+ throw new Error(
270
+ "A launchId must be provided when connecting outside the browser."
271
+ );
266
272
  }
267
273
  const search = new URLSearchParams(window.location.search);
268
274
  const launchId = search.get("mindoodbAppLaunchId");
@@ -271,9 +277,17 @@ function resolveLaunchId(options) {
271
277
  }
272
278
  return launchId;
273
279
  }
280
+ function shouldUseWindowedHostTab() {
281
+ if (typeof window === "undefined") {
282
+ return false;
283
+ }
284
+ return window.parent === window && Boolean(window.opener);
285
+ }
274
286
  function resolveTargetWindow() {
275
287
  if (typeof window === "undefined") {
276
- throw new Error("The MindooDB app bridge is only available in the browser.");
288
+ throw new Error(
289
+ "The MindooDB app bridge is only available in the browser."
290
+ );
277
291
  }
278
292
  if (window.parent && window.parent !== window) {
279
293
  return window.parent;
@@ -281,7 +295,7 @@ function resolveTargetWindow() {
281
295
  if (window.opener) {
282
296
  return window.opener;
283
297
  }
284
- throw new Error("Could not find a MindooDB Administrator host window.");
298
+ throw new Error("Could not find a MindooDB Haven host window.");
285
299
  }
286
300
  function waitForConnectedPort(options, launchId) {
287
301
  const targetWindow = resolveTargetWindow();
@@ -294,20 +308,36 @@ function waitForConnectedPort(options, launchId) {
294
308
  if (timeoutId !== null) {
295
309
  window.clearTimeout(timeoutId);
296
310
  }
297
- channel.port1.removeEventListener("message", handleMessage);
311
+ channel.port1.removeEventListener(
312
+ "message",
313
+ handleMessage
314
+ );
298
315
  };
299
316
  const handleMessage = (event) => {
300
317
  const payload = event.data;
301
- if (!payload || payload.protocol !== PROTOCOL2 || payload.type !== "mindoodb-app:connected") {
318
+ if (!payload || payload.protocol !== PROTOCOL2) {
302
319
  return;
303
320
  }
304
- cleanup();
305
- resolve(channel.port1);
321
+ if (payload.type === "mindoodb-app:connected") {
322
+ cleanup();
323
+ resolve(channel.port1);
324
+ return;
325
+ }
326
+ if (payload.type === "mindoodb-app:error") {
327
+ cleanup();
328
+ channel.port1.close();
329
+ const message2 = typeof payload.error === "string" && payload.error.trim() ? payload.error : "MindooDB Haven bridge connection failed.";
330
+ reject(new Error(message2));
331
+ }
306
332
  };
307
333
  timeoutId = window.setTimeout(() => {
308
334
  cleanup();
309
335
  channel.port1.close();
310
- reject(new Error(`Timed out while connecting to the MindooDB Administrator bridge for launch ${launchId}.`));
336
+ reject(
337
+ new Error(
338
+ `Timed out while connecting to the MindooDB Haven bridge for launch ${launchId}.`
339
+ )
340
+ );
311
341
  }, timeoutMs);
312
342
  channel.port1.addEventListener("message", handleMessage);
313
343
  channel.port1.start();
@@ -325,6 +355,9 @@ var MindooDBAppViewNavigatorImpl = class {
325
355
  this.navigatorId = navigatorId;
326
356
  this.viewCursor = viewCursor;
327
357
  }
358
+ rpc;
359
+ navigatorId;
360
+ viewCursor;
328
361
  /** Shorthand: call an RPC method with the navigator ID automatically injected. */
329
362
  async call(method, params = {}) {
330
363
  return await this.rpc.call(method, {
@@ -339,7 +372,9 @@ var MindooDBAppViewNavigatorImpl = class {
339
372
  return this.viewCursor;
340
373
  }
341
374
  async refresh() {
342
- const result = await this.call("viewNavigators.refresh");
375
+ const result = await this.call(
376
+ "viewNavigators.refresh"
377
+ );
343
378
  this.viewCursor = result.viewCursor;
344
379
  return this.viewCursor;
345
380
  }
@@ -383,10 +418,14 @@ var MindooDBAppViewNavigatorImpl = class {
383
418
  return await this.call("viewNavigators.category.findByParts", { parts });
384
419
  }
385
420
  async entriesForward(options) {
386
- return await this.call("viewNavigators.entries.forward", { options: options ?? {} });
421
+ return await this.call("viewNavigators.entries.forward", {
422
+ options: options ?? {}
423
+ });
387
424
  }
388
425
  async entriesBackward(options) {
389
- return await this.call("viewNavigators.entries.backward", { options: options ?? {} });
426
+ return await this.call("viewNavigators.entries.backward", {
427
+ options: options ?? {}
428
+ });
390
429
  }
391
430
  async gotoNextSelected() {
392
431
  return await this.call("viewNavigators.goto.nextSelected");
@@ -411,7 +450,10 @@ var MindooDBAppViewNavigatorImpl = class {
411
450
  await this.call("viewNavigators.selection.deselectAll");
412
451
  }
413
452
  async isSelected(origin, docId) {
414
- return await this.call("viewNavigators.selection.isSelected", { origin, docId });
453
+ return await this.call("viewNavigators.selection.isSelected", {
454
+ origin,
455
+ docId
456
+ });
415
457
  }
416
458
  async getSelectionState() {
417
459
  return await this.call("viewNavigators.selection.get");
@@ -444,13 +486,22 @@ var MindooDBAppViewNavigatorImpl = class {
444
486
  await this.call("viewNavigators.expansion.set", { state });
445
487
  }
446
488
  async childEntries(entryKey, descending) {
447
- return await this.call("viewNavigators.children.entries", { entryKey, descending });
489
+ return await this.call("viewNavigators.children.entries", {
490
+ entryKey,
491
+ descending
492
+ });
448
493
  }
449
494
  async childCategories(entryKey, descending) {
450
- return await this.call("viewNavigators.children.categories", { entryKey, descending });
495
+ return await this.call("viewNavigators.children.categories", {
496
+ entryKey,
497
+ descending
498
+ });
451
499
  }
452
500
  async childDocuments(entryKey, descending) {
453
- return await this.call("viewNavigators.children.documents", { entryKey, descending });
501
+ return await this.call("viewNavigators.children.documents", {
502
+ entryKey,
503
+ descending
504
+ });
454
505
  }
455
506
  async childCategoriesByKey(entryKey, key, exact, descending) {
456
507
  return await this.call("viewNavigators.children.categoriesByKey", {
@@ -469,16 +520,28 @@ var MindooDBAppViewNavigatorImpl = class {
469
520
  });
470
521
  }
471
522
  async childCategoriesBetween(entryKey, range) {
472
- return await this.call("viewNavigators.children.categoriesBetween", { entryKey, range });
523
+ return await this.call("viewNavigators.children.categoriesBetween", {
524
+ entryKey,
525
+ range
526
+ });
473
527
  }
474
528
  async childDocumentsBetween(entryKey, range) {
475
- return await this.call("viewNavigators.children.documentsBetween", { entryKey, range });
529
+ return await this.call("viewNavigators.children.documentsBetween", {
530
+ entryKey,
531
+ range
532
+ });
476
533
  }
477
534
  async getSortedDocIds(descending) {
478
- return await this.call("viewNavigators.sortedDocIds.get", { descending });
535
+ return await this.call(
536
+ "viewNavigators.sortedDocIds.get",
537
+ { descending }
538
+ );
479
539
  }
480
540
  async getSortedDocIdsScoped(entryKey, descending) {
481
- return await this.call("viewNavigators.sortedDocIds.scoped", { entryKey, descending });
541
+ return await this.call(
542
+ "viewNavigators.sortedDocIds.scoped",
543
+ { entryKey, descending }
544
+ );
482
545
  }
483
546
  async dispose() {
484
547
  await this.call("viewNavigators.dispose");
@@ -495,7 +558,9 @@ var MindooDBAppReadableAttachmentStreamImpl = class {
495
558
  if (!pending) {
496
559
  return;
497
560
  }
498
- pending.resolve(message.done ? null : new Uint8Array(message.chunk ?? new ArrayBuffer(0)));
561
+ pending.resolve(
562
+ message.done ? null : new Uint8Array(message.chunk ?? new ArrayBuffer(0))
563
+ );
499
564
  if (message.done) {
500
565
  this.closed = true;
501
566
  this.unsubscribe();
@@ -511,6 +576,8 @@ var MindooDBAppReadableAttachmentStreamImpl = class {
511
576
  }
512
577
  });
513
578
  }
579
+ rpc;
580
+ streamId;
514
581
  unsubscribe;
515
582
  closed = false;
516
583
  pendingRead = null;
@@ -520,7 +587,9 @@ var MindooDBAppReadableAttachmentStreamImpl = class {
520
587
  return null;
521
588
  }
522
589
  if (this.pendingRead) {
523
- throw new Error("A read() call is already in progress for this attachment stream.");
590
+ throw new Error(
591
+ "A read() call is already in progress for this attachment stream."
592
+ );
524
593
  }
525
594
  return await new Promise((resolve, reject) => {
526
595
  this.pendingRead = { resolve, reject };
@@ -567,6 +636,8 @@ var MindooDBAppWritableAttachmentStreamImpl = class {
567
636
  }
568
637
  });
569
638
  }
639
+ rpc;
640
+ streamId;
570
641
  unsubscribe;
571
642
  closed = false;
572
643
  inflight = null;
@@ -592,12 +663,15 @@ var MindooDBAppWritableAttachmentStreamImpl = class {
592
663
  return await this.enqueue(async () => {
593
664
  const buffer = toTransferableArrayBuffer(chunk);
594
665
  await this.waitForAck(() => {
595
- this.rpc.postMessage({
596
- protocol: PROTOCOL2,
597
- kind: "stream-write",
598
- streamId: this.streamId,
599
- chunk: buffer
600
- }, [buffer]);
666
+ this.rpc.postMessage(
667
+ {
668
+ protocol: PROTOCOL2,
669
+ kind: "stream-write",
670
+ streamId: this.streamId,
671
+ chunk: buffer
672
+ },
673
+ [buffer]
674
+ );
601
675
  });
602
676
  });
603
677
  }
@@ -665,6 +739,10 @@ var MindooDBAppDatabaseImpl = class {
665
739
  databaseId: this.databaseId,
666
740
  docId
667
741
  }),
742
+ undelete: async (docId) => await this.rpc.call("documents.undelete", {
743
+ databaseId: this.databaseId,
744
+ docId
745
+ }),
668
746
  listHistory: async (docId) => await this.rpc.call("documents.history.list", {
669
747
  databaseId: this.databaseId,
670
748
  docId
@@ -673,49 +751,130 @@ var MindooDBAppDatabaseImpl = class {
673
751
  databaseId: this.databaseId,
674
752
  docId,
675
753
  timestamp
754
+ }),
755
+ getAtRevision: async (docId, revisionId) => await this.rpc.call("documents.history.getAtRevision", {
756
+ databaseId: this.databaseId,
757
+ docId,
758
+ revisionId
676
759
  })
677
760
  };
678
761
  this.attachments = {
679
- list: async (docId) => await this.rpc.call("attachments.list", {
762
+ list: async (docId, options) => await this.rpc.call("attachments.list", {
680
763
  databaseId: this.databaseId,
681
- docId
764
+ docId,
765
+ timestamp: options?.timestamp,
766
+ revisionId: options?.revisionId
682
767
  }),
683
768
  remove: async (docId, attachmentName) => await this.rpc.call("attachments.remove", {
684
769
  databaseId: this.databaseId,
685
770
  docId,
686
771
  attachmentName
687
772
  }),
688
- openReadStream: async (docId, attachmentName) => {
689
- const result = await this.rpc.call("attachments.openReadStream", {
690
- databaseId: this.databaseId,
691
- docId,
692
- attachmentName
693
- });
694
- return new MindooDBAppReadableAttachmentStreamImpl(this.rpc, result.streamId);
773
+ openReadStream: async (docId, attachmentName, options) => {
774
+ const result = await this.rpc.call(
775
+ "attachments.openReadStream",
776
+ {
777
+ databaseId: this.databaseId,
778
+ docId,
779
+ attachmentName,
780
+ timestamp: options?.timestamp,
781
+ revisionId: options?.revisionId
782
+ }
783
+ );
784
+ return new MindooDBAppReadableAttachmentStreamImpl(
785
+ this.rpc,
786
+ result.streamId
787
+ );
695
788
  },
696
789
  openWriteStream: async (docId, attachmentName, contentType) => {
697
- const result = await this.rpc.call("attachments.openWriteStream", {
698
- databaseId: this.databaseId,
699
- docId,
700
- attachmentName,
701
- contentType
702
- });
703
- return new MindooDBAppWritableAttachmentStreamImpl(this.rpc, result.streamId);
790
+ const result = await this.rpc.call(
791
+ "attachments.openWriteStream",
792
+ {
793
+ databaseId: this.databaseId,
794
+ docId,
795
+ attachmentName,
796
+ contentType
797
+ }
798
+ );
799
+ return new MindooDBAppWritableAttachmentStreamImpl(
800
+ this.rpc,
801
+ result.streamId
802
+ );
803
+ },
804
+ scan: async (docId, options) => {
805
+ const scannerTab = shouldUseWindowedHostTab() ? window.open("", "_blank") : null;
806
+ if (scannerTab) {
807
+ try {
808
+ scannerTab.document.title = "Opening document scanner...";
809
+ const preparedSession = await this.rpc.call("attachments.prepareScanSession", {
810
+ databaseId: this.databaseId,
811
+ docId,
812
+ defaultFileName: options?.defaultFileName,
813
+ preset: options?.preset,
814
+ mimeType: options?.mimeType
815
+ });
816
+ scannerTab.location.href = preparedSession.scanUrl;
817
+ return await this.rpc.call(
818
+ "attachments.awaitScanSession",
819
+ {
820
+ databaseId: this.databaseId,
821
+ sessionId: preparedSession.sessionId
822
+ }
823
+ );
824
+ } catch (error) {
825
+ scannerTab.close();
826
+ throw error;
827
+ }
828
+ }
829
+ return await this.rpc.call(
830
+ "attachments.scanAndWrite",
831
+ {
832
+ databaseId: this.databaseId,
833
+ docId,
834
+ defaultFileName: options?.defaultFileName,
835
+ preset: options?.preset,
836
+ mimeType: options?.mimeType
837
+ }
838
+ );
704
839
  },
705
840
  preparePreviewSession: async (docId, attachmentName, options) => await this.rpc.call("attachments.preparePreviewSession", {
706
841
  databaseId: this.databaseId,
707
842
  docId,
708
843
  attachmentName,
709
- timestamp: options?.timestamp
844
+ timestamp: options?.timestamp,
845
+ revisionId: options?.revisionId
710
846
  }),
711
- openPreview: async (docId, attachmentName, options) => await this.rpc.call("attachments.openPreview", {
712
- databaseId: this.databaseId,
713
- docId,
714
- attachmentName,
715
- timestamp: options?.timestamp
716
- })
847
+ openPreview: async (docId, attachmentName, options) => {
848
+ const previewTab = shouldUseWindowedHostTab() ? window.open("", "_blank") : null;
849
+ if (previewTab) {
850
+ try {
851
+ previewTab.document.title = "Opening attachment preview...";
852
+ const previewSession = await this.rpc.call("attachments.preparePreviewSession", {
853
+ databaseId: this.databaseId,
854
+ docId,
855
+ attachmentName,
856
+ timestamp: options?.timestamp,
857
+ revisionId: options?.revisionId
858
+ });
859
+ previewTab.location.href = previewSession.previewUrl;
860
+ return { ok: true };
861
+ } catch (error) {
862
+ previewTab.close();
863
+ throw error;
864
+ }
865
+ }
866
+ return await this.rpc.call("attachments.openPreview", {
867
+ databaseId: this.databaseId,
868
+ docId,
869
+ attachmentName,
870
+ timestamp: options?.timestamp,
871
+ revisionId: options?.revisionId
872
+ });
873
+ }
717
874
  };
718
875
  }
876
+ rpc;
877
+ databaseId;
719
878
  documents;
720
879
  attachments;
721
880
  /** Returns database metadata for the currently opened binding. */
@@ -735,8 +894,9 @@ var MindooDBAppSessionImpl = class {
735
894
  }
736
895
  };
737
896
  }
897
+ rpc;
738
898
  menus;
739
- /** Returns the launch context provided by the Administrator host. */
899
+ /** Returns the launch context provided by the Haven host. */
740
900
  async getLaunchContext() {
741
901
  return await this.rpc.call("session.getLaunchContext", {});
742
902
  }
@@ -750,7 +910,9 @@ var MindooDBAppSessionImpl = class {
750
910
  return new MindooDBAppDatabaseImpl(this.rpc, databaseId);
751
911
  }
752
912
  async listDocumentsSinceViewCursor(cursor) {
753
- return await this.rpc.call("session.listDocumentsSinceViewCursor", { cursor });
913
+ return await this.rpc.call("session.listDocumentsSinceViewCursor", {
914
+ cursor
915
+ });
754
916
  }
755
917
  /**
756
918
  * Create a navigator from an ad-hoc view definition and one or more database bindings.
@@ -761,7 +923,11 @@ var MindooDBAppSessionImpl = class {
761
923
  */
762
924
  async createViewNavigator(input) {
763
925
  const result = await this.rpc.call("session.createViewNavigator", input);
764
- return new MindooDBAppViewNavigatorImpl(this.rpc, result.navigatorId, result.viewCursor);
926
+ return new MindooDBAppViewNavigatorImpl(
927
+ this.rpc,
928
+ result.navigatorId,
929
+ result.viewCursor
930
+ );
765
931
  }
766
932
  /**
767
933
  * Open a navigator for a preconfigured view that the host already knows about.
@@ -771,7 +937,11 @@ var MindooDBAppSessionImpl = class {
771
937
  */
772
938
  async openViewNavigator(viewId, options) {
773
939
  const result = await this.rpc.call("session.openViewNavigator", { viewId, options: options ?? {} });
774
- return new MindooDBAppViewNavigatorImpl(this.rpc, result.navigatorId, result.viewCursor);
940
+ return new MindooDBAppViewNavigatorImpl(
941
+ this.rpc,
942
+ result.navigatorId,
943
+ result.viewCursor
944
+ );
775
945
  }
776
946
  /** Subscribe to host-pushed theme changes (dark/light mode, color tokens). */
777
947
  onThemeChange(listener) {
@@ -817,6 +987,146 @@ function createMindooDBAppBridge() {
817
987
  };
818
988
  }
819
989
 
990
+ // src/textBuffer.ts
991
+ var MindooDBTextBuffer = class {
992
+ constructor(options) {
993
+ this.options = options;
994
+ this.valueInternal = readTextAtPath(options.document.data, options.path);
995
+ this.heads = options.document.heads ? [...options.document.heads] : [];
996
+ }
997
+ options;
998
+ valueInternal;
999
+ heads;
1000
+ pendingEdits = [];
1001
+ get value() {
1002
+ return this.valueInternal;
1003
+ }
1004
+ /** Whether there are local edits that have not been flushed yet. */
1005
+ get dirty() {
1006
+ return this.pendingEdits.length > 0;
1007
+ }
1008
+ /** Number of pending text operations currently buffered. */
1009
+ get pendingCount() {
1010
+ return this.pendingEdits.length;
1011
+ }
1012
+ /** Return the current local text value. */
1013
+ toString() {
1014
+ return this.valueInternal;
1015
+ }
1016
+ /**
1017
+ * Apply an exact local text splice and queue it for the next flush.
1018
+ *
1019
+ * Offsets use JavaScript string indexing. The delete count is clamped to the
1020
+ * remaining local text length so callers can safely delete to the end.
1021
+ */
1022
+ splice(index, deleteCount, insert = "") {
1023
+ if (!Number.isInteger(index) || index < 0 || index > this.valueInternal.length) {
1024
+ throw new RangeError("Text splice index is out of range");
1025
+ }
1026
+ if (!Number.isInteger(deleteCount) || deleteCount < 0) {
1027
+ throw new RangeError("Text splice deleteCount must be a non-negative integer");
1028
+ }
1029
+ const clampedDeleteCount = Math.min(deleteCount, this.valueInternal.length - index);
1030
+ this.valueInternal = this.valueInternal.slice(0, index) + insert + this.valueInternal.slice(index + clampedDeleteCount);
1031
+ this.pendingEdits.push({ index, deleteCount: clampedDeleteCount, insert });
1032
+ }
1033
+ /**
1034
+ * Replace the current local text value and queue the change as one splice.
1035
+ *
1036
+ * This is useful for editors such as Milkdown that can produce the full
1037
+ * markdown string after each transaction but do not expose raw text splices.
1038
+ */
1039
+ replaceText(nextValue) {
1040
+ if (nextValue === this.valueInternal) {
1041
+ return;
1042
+ }
1043
+ const edit = computeSingleSplice(this.valueInternal, nextValue);
1044
+ this.splice(edit.index, edit.deleteCount, edit.insert ?? "");
1045
+ }
1046
+ /**
1047
+ * Replace local state from a fresh document snapshot and clear pending edits.
1048
+ *
1049
+ * Returns whether the text value changed. Use this after an external refresh
1050
+ * or after receiving a document update through another app-level mechanism.
1051
+ */
1052
+ reconcile(document) {
1053
+ const nextValue = readTextAtPath(document.data, this.options.path);
1054
+ const changed = nextValue !== this.valueInternal;
1055
+ this.valueInternal = nextValue;
1056
+ this.heads = document.heads ? [...document.heads] : [];
1057
+ this.pendingEdits = [];
1058
+ return changed;
1059
+ }
1060
+ /**
1061
+ * Flush pending edits to Haven using `documents.update({ text: ... })`.
1062
+ *
1063
+ * The request includes the document heads this buffer is based on, allowing
1064
+ * Haven to apply the text operations at the original causal version and merge
1065
+ * them with any concurrent document changes. After a successful flush the
1066
+ * buffer adopts the returned canonical value and heads, and clears the
1067
+ * pending edit queue.
1068
+ */
1069
+ async flush() {
1070
+ if (this.pendingEdits.length === 0) {
1071
+ return {
1072
+ document: this.options.document,
1073
+ value: this.valueInternal,
1074
+ reconciled: false
1075
+ };
1076
+ }
1077
+ const localValueAtFlush = this.valueInternal;
1078
+ const document = await this.options.database.documents.update(this.options.document.id, {
1079
+ text: [{
1080
+ path: this.options.path,
1081
+ baseHeads: this.heads,
1082
+ edits: this.pendingEdits.map((edit) => ({ ...edit }))
1083
+ }]
1084
+ });
1085
+ const nextValue = readTextAtPath(document.data, this.options.path);
1086
+ const reconciled = nextValue !== localValueAtFlush;
1087
+ this.valueInternal = nextValue;
1088
+ this.heads = document.heads ? [...document.heads] : [];
1089
+ this.pendingEdits = [];
1090
+ return {
1091
+ document,
1092
+ value: this.valueInternal,
1093
+ reconciled
1094
+ };
1095
+ }
1096
+ };
1097
+ function createMindooDBTextBuffer(options) {
1098
+ return new MindooDBTextBuffer(options);
1099
+ }
1100
+ function readTextAtPath(data, path) {
1101
+ let value = data;
1102
+ for (const segment of path) {
1103
+ if (value == null || typeof value !== "object") {
1104
+ return "";
1105
+ }
1106
+ value = value[segment];
1107
+ }
1108
+ return typeof value === "string" ? value : "";
1109
+ }
1110
+ function computeSingleSplice(previous, next) {
1111
+ let prefixLength = 0;
1112
+ const maxPrefix = Math.min(previous.length, next.length);
1113
+ while (prefixLength < maxPrefix && previous[prefixLength] === next[prefixLength]) {
1114
+ prefixLength += 1;
1115
+ }
1116
+ let suffixLength = 0;
1117
+ const previousRemaining = previous.length - prefixLength;
1118
+ const nextRemaining = next.length - prefixLength;
1119
+ const maxSuffix = Math.min(previousRemaining, nextRemaining);
1120
+ while (suffixLength < maxSuffix && previous[previous.length - 1 - suffixLength] === next[next.length - 1 - suffixLength]) {
1121
+ suffixLength += 1;
1122
+ }
1123
+ return {
1124
+ index: prefixLength,
1125
+ deleteCount: previous.length - prefixLength - suffixLength,
1126
+ insert: next.slice(prefixLength, next.length - suffixLength)
1127
+ };
1128
+ }
1129
+
820
1130
  // src/viewLanguage.ts
821
1131
  import {
822
1132
  createViewLanguage,
@@ -825,9 +1135,11 @@ import {
825
1135
  mindooDBViewLanguageHelpersByName
826
1136
  } from "mindoodb-view-language";
827
1137
  export {
1138
+ MindooDBTextBuffer,
828
1139
  abbreviateCanonicalName,
829
1140
  canPreviewAttachment,
830
1141
  createMindooDBAppBridge,
1142
+ createMindooDBTextBuffer,
831
1143
  createViewLanguage,
832
1144
  expandAbbreviatedName
833
1145
  };
@@ -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 { ac as MindooDBAppLaunchContext, X as MindooDBAppDatabaseInfo, Y as MindooDBAppDocumentApi, W as MindooDBAppCreateViewNavigatorInput, aK as MindooDBAppViewNavigator, aM as MindooDBAppViewNavigatorOpenOptions, d as MindooDBAppAttachmentApi, a as MindooDBAppBridge, ay as MindooDBAppSession, q as MindooDBAppBridgeRpcRequest, a6 as MindooDBAppHostTheme, aR as MindooDBAppViewport, aE as MindooDBAppUiPreferences, n as MindooDBAppBridgePortMessage } from '../types-Dw6YRApH.js';
2
2
  import 'mindoodb-view-language';
3
3
 
4
4
  type MaybePromise<T> = T | Promise<T>;