mindoodb-app-sdk 0.0.19 → 0.0.20
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 +124 -1
- package/dist/chunk-QGM4M3NI.js +37 -0
- package/dist/index.d.ts +8 -5
- package/dist/index.js +83 -7
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.js +3931 -8
- package/dist/{types-nFt-aryL.d.ts → types-CQt2ObMu.d.ts} +110 -2
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -772,7 +772,126 @@ Like the text buffer, the rich-text handle always sends the original `baseHeads`
|
|
|
772
772
|
|
|
773
773
|
#### End-to-end sample
|
|
774
774
|
|
|
775
|
-
The Word/.docx mode in [`mindoodb-app-teamedit`](https://github.com/klehmann/mindoodb-app-teamedit)
|
|
775
|
+
The Word/.docx mode in [`mindoodb-app-teamedit`](https://github.com/klehmann/mindoodb-app-teamedit) is the **only supported in-repo use case** for the Automerge binary sync API below — it needs a local replica and binary flush because `set`/`unset` and the JSON patch APIs are not sufficient for that editor. For span-only rich-text apps, use `createMindooDBRichTextHandle` instead.
|
|
776
|
+
|
|
777
|
+
### Automerge binary sync (advanced)
|
|
778
|
+
|
|
779
|
+
> **Avoid these APIs unless you have no alternative.** For normal app editing, use `documents.update({ set })`, `documents.update({ unset })`, and the JSON patch operations (`text`, `richText`, `json`) documented above. `getAutomergeSnapshot` and `applyAutomergeChanges` were added as an **escape hatch** for the one case where those APIs are not enough: TeamEdit's Word/.docx mode, which hosts a local `@automerge/automerge` replica and flushes raw change bytes on save. Do not adopt binary sync for new features unless you have the same constraint — you take on an Automerge dependency, manual replica lifecycle, and a much harder integration path.
|
|
780
|
+
|
|
781
|
+
If you must use binary sync, Haven decrypts the canonical document, merges incoming change batches with `Automerge.applyChanges`, and persists the result. Your app never sends encrypted blobs or sync metadata; it only sends the same binary change format Automerge produces locally.
|
|
782
|
+
|
|
783
|
+
Typical flow:
|
|
784
|
+
|
|
785
|
+
```
|
|
786
|
+
┌────────────────────────────────────────────────────┐
|
|
787
|
+
open ──► │ getAutomergeSnapshot → load local replica │
|
|
788
|
+
└─────────────────────────┬──────────────────────────┘
|
|
789
|
+
│
|
|
790
|
+
edit ──► │ Local Automerge doc (or span edits applied locally) │
|
|
791
|
+
└─────────────────────────┬──────────────────────────┘
|
|
792
|
+
│ getChangesSince(baseHeads)
|
|
793
|
+
▼
|
|
794
|
+
┌────────────────────────────────────────────────────┐
|
|
795
|
+
save ──► │ applyAutomergeChanges({ baseHeads, replicaHeads, │
|
|
796
|
+
│ changes }) │
|
|
797
|
+
└─────────────────────────┬──────────────────────────┘
|
|
798
|
+
│ Haven merges + persists
|
|
799
|
+
▼
|
|
800
|
+
┌────────────────────────────────────────────────────┐
|
|
801
|
+
│ Apply result.changesSince locally (or skip if empty) │
|
|
802
|
+
└────────────────────────────────────────────────────┘
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
Bridge RPCs: `documents.automerge.getSnapshot` and `documents.automerge.applyChanges`.
|
|
806
|
+
|
|
807
|
+
#### `getAutomergeSnapshot`
|
|
808
|
+
|
|
809
|
+
Export the full internal Automerge document as a binary snapshot plus the current document heads:
|
|
810
|
+
|
|
811
|
+
```ts
|
|
812
|
+
const snapshot = await db.documents.getAutomergeSnapshot(docId);
|
|
813
|
+
// snapshot = { binary: Uint8Array, heads: string[] }
|
|
814
|
+
|
|
815
|
+
const localDoc = Automerge.load(snapshot.binary);
|
|
816
|
+
const baseHeads = [...snapshot.heads];
|
|
817
|
+
```
|
|
818
|
+
|
|
819
|
+
Options:
|
|
820
|
+
|
|
821
|
+
```ts
|
|
822
|
+
interface MindooDBAppAutomergeGetOptions {
|
|
823
|
+
revisionId?: MindooDBAppDocumentRevisionId; // historical read via documents.listHistory()
|
|
824
|
+
}
|
|
825
|
+
```
|
|
826
|
+
|
|
827
|
+
Only call this when binary sync is unavoidable — e.g. opening a local replica, refreshing after `applyAutomergeChanges`, or read-only historical preview at a `revisionId`. For normal reads, use `getRichText` or `documents.get`.
|
|
828
|
+
|
|
829
|
+
#### `applyAutomergeChanges`
|
|
830
|
+
|
|
831
|
+
Merge a batch of raw Automerge change bytes into the canonical document on Haven:
|
|
832
|
+
|
|
833
|
+
```ts
|
|
834
|
+
const changes = Automerge.getChangesSince(localDoc, baseHeads as Automerge.Heads);
|
|
835
|
+
const replicaHeads = Automerge.getHeads(localDoc);
|
|
836
|
+
|
|
837
|
+
const result = await db.documents.applyAutomergeChanges(docId, {
|
|
838
|
+
baseHeads, // optional metadata: heads when the local batch was authored
|
|
839
|
+
replicaHeads, // local heads after authoring; enables incremental catch-up in the response
|
|
840
|
+
changes: changes.map((change) => new Uint8Array(change)),
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
// result.document — updated MindooDBAppDocument snapshot (includes merged data + heads)
|
|
844
|
+
// result.heads — new Automerge heads after the merge
|
|
845
|
+
// result.changesSince — incremental bytes to reconcile the local replica (when replicaHeads was sent)
|
|
846
|
+
if (result.changesSince?.changes.length) {
|
|
847
|
+
[localDoc] = Automerge.applyChanges(
|
|
848
|
+
localDoc,
|
|
849
|
+
result.changesSince.changes.map((change) => new Uint8Array(change)),
|
|
850
|
+
);
|
|
851
|
+
}
|
|
852
|
+
baseHeads = [...result.heads];
|
|
853
|
+
```
|
|
854
|
+
|
|
855
|
+
Patch and result types:
|
|
856
|
+
|
|
857
|
+
```ts
|
|
858
|
+
interface MindooDBAppAutomergeChangesPatch {
|
|
859
|
+
baseHeads?: string[]; // correlation only; merge is not rejected when Haven moved on
|
|
860
|
+
replicaHeads?: string[]; // local heads after authoring `changes`; enables `changesSince` in the response
|
|
861
|
+
changes: Uint8Array[]; // from Automerge.getChangesSince (or equivalent)
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
interface MindooDBAppAutomergeChangesSince {
|
|
865
|
+
sinceHeads: string[]; // echo of `replicaHeads`
|
|
866
|
+
changes: Uint8Array[]; // apply locally with Automerge.applyChanges
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
interface MindooDBAppAutomergePatchResult {
|
|
870
|
+
document: MindooDBAppDocument;
|
|
871
|
+
heads: string[];
|
|
872
|
+
changesSince?: MindooDBAppAutomergeChangesSince;
|
|
873
|
+
}
|
|
874
|
+
```
|
|
875
|
+
|
|
876
|
+
Haven applies `changes` with `Automerge.applyChanges` against its **current** document, so concurrent edits from other clients are merged by Automerge's CRDT logic rather than rejected. `baseHeads` is optional logging metadata — it does not gate the merge.
|
|
877
|
+
|
|
878
|
+
When you include `replicaHeads` (the local replica's heads after authoring your batch), the response includes `changesSince`: the incremental change bytes your replica still needs after the merge. Apply them locally with `Automerge.applyChanges` and set `baseHeads = result.heads`. When there was no concurrent edit, `changesSince.changes` is empty and your local doc is already up to date — no full snapshot download needed. Omit `replicaHeads` only if you plan to reload via `getAutomergeSnapshot` instead.
|
|
879
|
+
|
|
880
|
+
#### When to use binary sync vs JSON patches
|
|
881
|
+
|
|
882
|
+
| Approach | App sends | When to use |
|
|
883
|
+
| -------- | --------- | ----------- |
|
|
884
|
+
| `documents.update({ set })` / `{ unset }` | Field paths | **Default** for structured document data |
|
|
885
|
+
| `documents.update({ richText })` | JSON span snapshots | **Default** for rich-text fields |
|
|
886
|
+
| `documents.update({ text })` | Text splices | Plain markdown / string fields |
|
|
887
|
+
| `documents.update({ json })` | JSON Patch (RFC 6902) | Arbitrary nested JSON paths |
|
|
888
|
+
| `applyAutomergeChanges` | Binary change bytes | **Last resort only** — TeamEdit Word/.docx with a local Automerge replica |
|
|
889
|
+
|
|
890
|
+
Requires the `update` capability (same as other write operations). For historical reads, prefer `getRichText(..., { revisionId })`; only use `getAutomergeSnapshot(..., { revisionId })` when you truly need the full binary at a revision.
|
|
891
|
+
|
|
892
|
+
#### Reference implementation (not a template)
|
|
893
|
+
|
|
894
|
+
TeamEdit's Word/.docx mode is why these RPCs exist — see `wordAutomergeHandle.ts` in [`mindoodb-app-teamedit`](https://github.com/klehmann/mindoodb-app-teamedit). Treat it as a reference for an unsupported edge case, not as a pattern to copy into new apps.
|
|
776
895
|
|
|
777
896
|
### Incremental sync
|
|
778
897
|
|
|
@@ -1208,6 +1327,8 @@ Connect options: `launchId?`, `targetOrigin?`, `connectTimeoutMs?`.
|
|
|
1208
1327
|
| `list(query?)` | `Promise<MindooDBAppDocumentListResult>` |
|
|
1209
1328
|
| `get(docId)` | `Promise<MindooDBAppDocument \| null>` |
|
|
1210
1329
|
| `getRichText(docId, path, opts?)` | `Promise<MindooDBAppRichTextSnapshot>` |
|
|
1330
|
+
| `getAutomergeSnapshot(docId, opts?)` | `Promise<MindooDBAppAutomergeSnapshot>` |
|
|
1331
|
+
| `applyAutomergeChanges(docId, patch)` | `Promise<MindooDBAppAutomergePatchResult>` |
|
|
1211
1332
|
| `create(input)` | `Promise<MindooDBAppDocument>` |
|
|
1212
1333
|
| `update(docId, patch)` | `Promise<MindooDBAppDocument>` |
|
|
1213
1334
|
| `delete(docId)` | `Promise<{ ok: true }>` |
|
|
@@ -1216,6 +1337,8 @@ Connect options: `launchId?`, `targetOrigin?`, `connectTimeoutMs?`.
|
|
|
1216
1337
|
| `getAtTimestamp(docId, timestamp)` | `Promise<MindooDBAppHistoricalDocument>` |
|
|
1217
1338
|
| `getAtRevision(docId, revisionId)` | `Promise<MindooDBAppHistoricalDocument>` |
|
|
1218
1339
|
|
|
1340
|
+
`getAutomergeSnapshot` and `applyAutomergeChanges` are **discouraged** escape-hatch APIs for binary Automerge sync. Prefer `set`/`unset` and JSON patches (`text`, `richText`, `json`) instead. See [Automerge binary sync (advanced)](#automerge-binary-sync-advanced).
|
|
1341
|
+
|
|
1219
1342
|
`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.
|
|
1220
1343
|
|
|
1221
1344
|
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.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
8
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
9
|
+
}) : x)(function(x) {
|
|
10
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
11
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
12
|
+
});
|
|
13
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
14
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
15
|
+
};
|
|
16
|
+
var __copyProps = (to, from, except, desc) => {
|
|
17
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
18
|
+
for (let key of __getOwnPropNames(from))
|
|
19
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
20
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
21
|
+
}
|
|
22
|
+
return to;
|
|
23
|
+
};
|
|
24
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
25
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
26
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
27
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
28
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
29
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
30
|
+
mod
|
|
31
|
+
));
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
__require,
|
|
35
|
+
__commonJS,
|
|
36
|
+
__toESM
|
|
37
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { M as MindooDBAppAttachmentPreviewMode, a as MindooDBAppBridge, b as MindooDBAppDatabase, c as MindooDBAppDocument, d as MindooDBAppRichTextSpan, e as MindooDBAppRichTextSnapshot } from './types-
|
|
2
|
-
export { f as MindooDBAppAttachmentApi, g as MindooDBAppAttachmentChunk, h as MindooDBAppAttachmentInfo, i as MindooDBAppAttachmentPreviewOptions, j as MindooDBAppAttachmentPreviewSession, k as
|
|
1
|
+
import { M as MindooDBAppAttachmentPreviewMode, a as MindooDBAppBridge, b as MindooDBAppDatabase, c as MindooDBAppDocument, d as MindooDBAppRichTextSpan, e as MindooDBAppRichTextSnapshot } from './types-CQt2ObMu.js';
|
|
2
|
+
export { f as MindooDBAppAttachmentApi, g as MindooDBAppAttachmentChunk, h as MindooDBAppAttachmentInfo, i as MindooDBAppAttachmentPreviewOptions, j as MindooDBAppAttachmentPreviewSession, k as MindooDBAppAutomergeChangesPatch, l as MindooDBAppAutomergeChangesSince, m as MindooDBAppAutomergeGetOptions, n as MindooDBAppAutomergePatchResult, o as MindooDBAppAutomergeSnapshot, p as MindooDBAppBridgeConnectMessage, q as MindooDBAppBridgeConnectOptions, r as MindooDBAppBridgeConnectedMessage, s as MindooDBAppBridgeErrorPayload, t as MindooDBAppBridgeHandshakeErrorMessage, u as MindooDBAppBridgePortMessage, v as MindooDBAppBridgeRpcError, w as MindooDBAppBridgeRpcMessage, x as MindooDBAppBridgeRpcRequest, y as MindooDBAppBridgeRpcSuccess, z as MindooDBAppBridgeStreamAbortRequest, A as MindooDBAppBridgeStreamAck, B as MindooDBAppBridgeStreamCloseRequest, C as MindooDBAppBridgeStreamError, D as MindooDBAppBridgeStreamMessage, E as MindooDBAppBridgeStreamOpenResult, F as MindooDBAppBridgeStreamReadRequest, G as MindooDBAppBridgeStreamWriteRequest, H as MindooDBAppBridgeThemeChangedMessage, I as MindooDBAppBridgeUiPreferencesChangedMessage, J as MindooDBAppBridgeViewportChangedMessage, K as MindooDBAppCapability, L as MindooDBAppConfiguredViewCategorizationStyle, N as MindooDBAppConfiguredViewColumn, O as MindooDBAppConfiguredViewColumnRole, P as MindooDBAppConfiguredViewExpressionMode, Q as MindooDBAppConfiguredViewFieldExpression, R as MindooDBAppConfiguredViewFilterDefinition, S as MindooDBAppConfiguredViewFilterMode, T as MindooDBAppConfiguredViewFilterRule, U as MindooDBAppConfiguredViewFormulaExpression, V as MindooDBAppConfiguredViewFormulaFilterDefinition, W as MindooDBAppConfiguredViewPreviewMode, X as MindooDBAppConfiguredViewRuleFilterDefinition, Y as MindooDBAppConfiguredViewRuleMatchMode, Z as MindooDBAppConfiguredViewRuleOperator, _ as MindooDBAppConfiguredViewValueExpression, $ as MindooDBAppCreateDocumentInput, a0 as MindooDBAppCreateViewInput, a1 as MindooDBAppCreateViewNavigatorInput, a2 as MindooDBAppDatabaseInfo, a3 as MindooDBAppDocumentApi, a4 as MindooDBAppDocumentHeadCursorResult, a5 as MindooDBAppDocumentHistoryEntry, a6 as MindooDBAppDocumentListQuery, a7 as MindooDBAppDocumentListResult, a8 as MindooDBAppDocumentRevisionId, a9 as MindooDBAppDocumentScanPreset, aa as MindooDBAppDocumentSummary, ab as MindooDBAppHistoricalDocument, ac as MindooDBAppHistoryQuery, ad as MindooDBAppHostTheme, ae as MindooDBAppJsonListDeletePatch, af as MindooDBAppJsonListInsertPatch, ag as MindooDBAppJsonPatch, ah as MindooDBAppJsonSetPatch, ai as MindooDBAppJsonTextMarkPatch, aj as MindooDBAppJsonTextSplicePatch, ak as MindooDBAppJsonTextUnmarkPatch, al as MindooDBAppJsonUnsetPatch, am as MindooDBAppLaunchContext, an as MindooDBAppMenuAnchor, ao as MindooDBAppMenuApi, ap as MindooDBAppMenuCommandItem, aq as MindooDBAppMenuDismissReason, ar as MindooDBAppMenuDismissedResult, as as MindooDBAppMenuItem, at as MindooDBAppMenuKind, au as MindooDBAppMenuPlacement, av as MindooDBAppMenuPointAnchor, aw as MindooDBAppMenuRect, ax as MindooDBAppMenuRectAnchor, ay as MindooDBAppMenuSelectionResult, az as MindooDBAppMenuSeparatorItem, aA as MindooDBAppReadableAttachmentStream, aB as MindooDBAppResolvedViewDefinition, aC as MindooDBAppResolvedViewSource, aD as MindooDBAppRichTextBlockSpan, aE as MindooDBAppRichTextGetOptions, aF as MindooDBAppRichTextImmutableString, aG as MindooDBAppRichTextMarkRange, aH as MindooDBAppRichTextMaterializeValue, aI as MindooDBAppRichTextPatch, aJ as MindooDBAppRichTextScalar, aK as MindooDBAppRichTextSpliceStep, aL as MindooDBAppRichTextStep, aM as MindooDBAppRichTextStepPatch, aN as MindooDBAppRichTextTextSpan, aO as MindooDBAppRuntime, aP as MindooDBAppScanAttachmentOptions, aQ as MindooDBAppScanAttachmentResult, aR as MindooDBAppScopedDocId, aS as MindooDBAppScopedDocumentSummary, aT as MindooDBAppSession, aU as MindooDBAppShowMenuInput, aV as MindooDBAppShowMenuResult, aW as MindooDBAppTextEdit, aX as MindooDBAppTextPatch, aY as MindooDBAppThemeMode, aZ as MindooDBAppUiPreferences, a_ as MindooDBAppUpdateDocumentInput, a$ as MindooDBAppViewCursorDocumentListResult, b0 as MindooDBAppViewCursorResult, b1 as MindooDBAppViewEntry, b2 as MindooDBAppViewEntryKind, b3 as MindooDBAppViewNavigator, b4 as MindooDBAppViewNavigatorExpansionState, b5 as MindooDBAppViewNavigatorOpenOptions, b6 as MindooDBAppViewNavigatorPageOptions, b7 as MindooDBAppViewNavigatorPageResult, b8 as MindooDBAppViewNavigatorRangeQuery, b9 as MindooDBAppViewNavigatorSelectionState, ba as MindooDBAppViewport, bb as MindooDBAppWritableAttachmentStream } from './types-CQt2ObMu.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
|
/**
|
|
@@ -53,13 +53,15 @@ type MindooDBRichTextHandleChangeListener = (snapshot: MindooDBAppRichTextSnapsh
|
|
|
53
53
|
/**
|
|
54
54
|
* Local rich-text span buffer for SDK apps.
|
|
55
55
|
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
56
|
+
* Mirrors `MindooDBTextBuffer`: track edits against a base snapshot, then flush
|
|
57
|
+
* with causal `baseHeads`. Text edits prefer positional `richTextSteps` so
|
|
58
|
+
* concurrent saves merge like plain-text splices; formatting-only or structural
|
|
59
|
+
* changes fall back to full `richText` span snapshots.
|
|
59
60
|
*/
|
|
60
61
|
declare class MindooDBRichTextHandle {
|
|
61
62
|
private readonly options;
|
|
62
63
|
private spansInternal;
|
|
64
|
+
private baseMaterializedText;
|
|
63
65
|
private heads;
|
|
64
66
|
private dirtyInternal;
|
|
65
67
|
private listeners;
|
|
@@ -77,6 +79,7 @@ declare class MindooDBRichTextHandle {
|
|
|
77
79
|
refresh(): Promise<MindooDBAppRichTextSnapshot>;
|
|
78
80
|
pollOnce(): Promise<boolean>;
|
|
79
81
|
flush(updateSpansConfig?: Record<string, unknown>): Promise<MindooDBRichTextHandleFlushResult>;
|
|
82
|
+
private flushTextSteps;
|
|
80
83
|
private emitChange;
|
|
81
84
|
}
|
|
82
85
|
declare function createMindooDBRichTextHandle(options: CreateMindooDBRichTextHandleOptions): MindooDBRichTextHandle;
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import "./chunk-QGM4M3NI.js";
|
|
2
|
+
|
|
1
3
|
// src/attachmentPreview.ts
|
|
2
4
|
function canPreviewAttachment(fileName, mimeType) {
|
|
3
5
|
const normalizedMimeType = mimeType.toLowerCase();
|
|
@@ -732,6 +734,16 @@ var MindooDBAppDatabaseImpl = class {
|
|
|
732
734
|
path,
|
|
733
735
|
revisionId: options?.revisionId
|
|
734
736
|
}),
|
|
737
|
+
getAutomergeSnapshot: async (docId, options) => await this.rpc.call("documents.automerge.getSnapshot", {
|
|
738
|
+
databaseId: this.databaseId,
|
|
739
|
+
docId,
|
|
740
|
+
revisionId: options?.revisionId
|
|
741
|
+
}),
|
|
742
|
+
applyAutomergeChanges: async (docId, patch) => await this.rpc.call("documents.automerge.applyChanges", {
|
|
743
|
+
databaseId: this.databaseId,
|
|
744
|
+
docId,
|
|
745
|
+
patch
|
|
746
|
+
}),
|
|
735
747
|
create: async (input) => await this.rpc.call("documents.create", {
|
|
736
748
|
databaseId: this.databaseId,
|
|
737
749
|
input
|
|
@@ -997,11 +1009,18 @@ function createMindooDBAppBridge() {
|
|
|
997
1009
|
var MindooDBRichTextHandle = class {
|
|
998
1010
|
constructor(options) {
|
|
999
1011
|
this.options = options;
|
|
1000
|
-
|
|
1012
|
+
const initialSpans = cloneSpans(options.spans ?? []);
|
|
1013
|
+
this.spansInternal = initialSpans;
|
|
1014
|
+
this.baseMaterializedText = readMaterializedRichTextText(
|
|
1015
|
+
options.document.data,
|
|
1016
|
+
options.path,
|
|
1017
|
+
initialSpans
|
|
1018
|
+
);
|
|
1001
1019
|
this.heads = options.document.heads ? [...options.document.heads] : [];
|
|
1002
1020
|
}
|
|
1003
1021
|
options;
|
|
1004
1022
|
spansInternal;
|
|
1023
|
+
baseMaterializedText;
|
|
1005
1024
|
heads;
|
|
1006
1025
|
dirtyInternal = false;
|
|
1007
1026
|
listeners = /* @__PURE__ */ new Set();
|
|
@@ -1041,6 +1060,7 @@ var MindooDBRichTextHandle = class {
|
|
|
1041
1060
|
reconcile(document, snapshot) {
|
|
1042
1061
|
const previous = JSON.stringify(this.spansInternal);
|
|
1043
1062
|
this.spansInternal = cloneSpans(snapshot.spans);
|
|
1063
|
+
this.baseMaterializedText = spansToPlainText(snapshot.spans);
|
|
1044
1064
|
this.heads = snapshot.heads ?? document.heads ?? [];
|
|
1045
1065
|
this.dirtyInternal = false;
|
|
1046
1066
|
const changed = JSON.stringify(this.spansInternal) !== previous;
|
|
@@ -1081,14 +1101,16 @@ var MindooDBRichTextHandle = class {
|
|
|
1081
1101
|
reconciled: false
|
|
1082
1102
|
};
|
|
1083
1103
|
}
|
|
1084
|
-
const localSpansAtFlush =
|
|
1085
|
-
const
|
|
1104
|
+
const localSpansAtFlush = cloneSpans(this.spansInternal);
|
|
1105
|
+
const localTextAtFlush = spansToPlainText(localSpansAtFlush);
|
|
1106
|
+
const textChanged = localTextAtFlush !== this.baseMaterializedText;
|
|
1107
|
+
const document = textChanged ? await this.flushTextSteps(localTextAtFlush) : await this.options.database.documents.update(
|
|
1086
1108
|
this.options.document.id,
|
|
1087
1109
|
{
|
|
1088
1110
|
richText: [{
|
|
1089
1111
|
path: this.options.path,
|
|
1090
1112
|
baseHeads: this.heads,
|
|
1091
|
-
spans:
|
|
1113
|
+
spans: localSpansAtFlush,
|
|
1092
1114
|
updateSpansConfig
|
|
1093
1115
|
}]
|
|
1094
1116
|
}
|
|
@@ -1097,8 +1119,9 @@ var MindooDBRichTextHandle = class {
|
|
|
1097
1119
|
this.options.document.id,
|
|
1098
1120
|
this.options.path
|
|
1099
1121
|
);
|
|
1100
|
-
const reconciled = JSON.stringify(snapshot.spans) !== localSpansAtFlush;
|
|
1122
|
+
const reconciled = JSON.stringify(snapshot.spans) !== JSON.stringify(localSpansAtFlush);
|
|
1101
1123
|
this.spansInternal = cloneSpans(snapshot.spans);
|
|
1124
|
+
this.baseMaterializedText = spansToPlainText(snapshot.spans);
|
|
1102
1125
|
this.heads = snapshot.heads ?? document.heads ?? [];
|
|
1103
1126
|
this.dirtyInternal = false;
|
|
1104
1127
|
if (reconciled) {
|
|
@@ -1110,6 +1133,21 @@ var MindooDBRichTextHandle = class {
|
|
|
1110
1133
|
reconciled
|
|
1111
1134
|
};
|
|
1112
1135
|
}
|
|
1136
|
+
async flushTextSteps(localTextAtFlush) {
|
|
1137
|
+
const edit = computeSingleSplice(this.baseMaterializedText, localTextAtFlush);
|
|
1138
|
+
return this.options.database.documents.update(this.options.document.id, {
|
|
1139
|
+
richTextSteps: [{
|
|
1140
|
+
path: this.options.path,
|
|
1141
|
+
baseHeads: this.heads,
|
|
1142
|
+
steps: [{
|
|
1143
|
+
type: "splice",
|
|
1144
|
+
index: edit.index,
|
|
1145
|
+
deleteCount: edit.deleteCount,
|
|
1146
|
+
insert: edit.insert ?? ""
|
|
1147
|
+
}]
|
|
1148
|
+
}]
|
|
1149
|
+
});
|
|
1150
|
+
}
|
|
1113
1151
|
emitChange() {
|
|
1114
1152
|
const snapshot = {
|
|
1115
1153
|
path: [...this.options.path],
|
|
@@ -1127,6 +1165,44 @@ function createMindooDBRichTextHandle(options) {
|
|
|
1127
1165
|
function cloneSpans(spans) {
|
|
1128
1166
|
return structuredClone(spans);
|
|
1129
1167
|
}
|
|
1168
|
+
function spansToPlainText(spans) {
|
|
1169
|
+
return spans.filter((span) => span.type === "text").map((span) => span.type === "text" ? span.value : "").join("");
|
|
1170
|
+
}
|
|
1171
|
+
function readMaterializedRichTextText(data, path, fallbackSpans) {
|
|
1172
|
+
let value = data;
|
|
1173
|
+
for (const segment of path) {
|
|
1174
|
+
if (value == null || typeof value !== "object") {
|
|
1175
|
+
return spansToPlainText(fallbackSpans);
|
|
1176
|
+
}
|
|
1177
|
+
value = value[segment];
|
|
1178
|
+
}
|
|
1179
|
+
if (typeof value === "string") {
|
|
1180
|
+
return value.replace(/\uFFFC/g, "");
|
|
1181
|
+
}
|
|
1182
|
+
if (Array.isArray(value)) {
|
|
1183
|
+
return spansToPlainText(value);
|
|
1184
|
+
}
|
|
1185
|
+
return spansToPlainText(fallbackSpans);
|
|
1186
|
+
}
|
|
1187
|
+
function computeSingleSplice(previous, next) {
|
|
1188
|
+
let prefixLength = 0;
|
|
1189
|
+
const maxPrefix = Math.min(previous.length, next.length);
|
|
1190
|
+
while (prefixLength < maxPrefix && previous[prefixLength] === next[prefixLength]) {
|
|
1191
|
+
prefixLength += 1;
|
|
1192
|
+
}
|
|
1193
|
+
let suffixLength = 0;
|
|
1194
|
+
const previousRemaining = previous.length - prefixLength;
|
|
1195
|
+
const nextRemaining = next.length - prefixLength;
|
|
1196
|
+
const maxSuffix = Math.min(previousRemaining, nextRemaining);
|
|
1197
|
+
while (suffixLength < maxSuffix && previous[previous.length - 1 - suffixLength] === next[next.length - 1 - suffixLength]) {
|
|
1198
|
+
suffixLength += 1;
|
|
1199
|
+
}
|
|
1200
|
+
return {
|
|
1201
|
+
index: prefixLength,
|
|
1202
|
+
deleteCount: previous.length - prefixLength - suffixLength,
|
|
1203
|
+
insert: next.slice(prefixLength, next.length - suffixLength)
|
|
1204
|
+
};
|
|
1205
|
+
}
|
|
1130
1206
|
|
|
1131
1207
|
// src/textBuffer.ts
|
|
1132
1208
|
var MindooDBTextBuffer = class {
|
|
@@ -1181,7 +1257,7 @@ var MindooDBTextBuffer = class {
|
|
|
1181
1257
|
if (nextValue === this.valueInternal) {
|
|
1182
1258
|
return;
|
|
1183
1259
|
}
|
|
1184
|
-
const edit =
|
|
1260
|
+
const edit = computeSingleSplice2(this.valueInternal, nextValue);
|
|
1185
1261
|
this.splice(edit.index, edit.deleteCount, edit.insert ?? "");
|
|
1186
1262
|
}
|
|
1187
1263
|
/**
|
|
@@ -1248,7 +1324,7 @@ function readTextAtPath(data, path) {
|
|
|
1248
1324
|
}
|
|
1249
1325
|
return typeof value === "string" ? value : "";
|
|
1250
1326
|
}
|
|
1251
|
-
function
|
|
1327
|
+
function computeSingleSplice2(previous, next) {
|
|
1252
1328
|
let prefixLength = 0;
|
|
1253
1329
|
const maxPrefix = Math.min(previous.length, next.length);
|
|
1254
1330
|
while (prefixLength < maxPrefix && previous[prefixLength] === next[prefixLength]) {
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { am as MindooDBAppLaunchContext, a2 as MindooDBAppDatabaseInfo, a3 as MindooDBAppDocumentApi, a1 as MindooDBAppCreateViewNavigatorInput, b3 as MindooDBAppViewNavigator, b5 as MindooDBAppViewNavigatorOpenOptions, f as MindooDBAppAttachmentApi, a as MindooDBAppBridge, aT as MindooDBAppSession, x as MindooDBAppBridgeRpcRequest, ad as MindooDBAppHostTheme, ba as MindooDBAppViewport, aZ as MindooDBAppUiPreferences, u as MindooDBAppBridgePortMessage } from '../types-CQt2ObMu.js';
|
|
2
2
|
import 'mindoodb-view-language';
|
|
3
3
|
|
|
4
4
|
type MaybePromise<T> = T | Promise<T>;
|