@mengine/medeo-client 2.0.1-alpha.0 → 2.0.1-alpha.1

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
@@ -18,6 +18,8 @@ Browser hosts can inject `IndexedDBDocStorage` through `localStorage`. An option
18
18
 
19
19
  For normal teardown, use `await session.close()`. It immediately rejects new edits and stops synchronization, then keeps local persistence alive until pending commits are saved before releasing connections. Storage failures remain retryable while closing. `destroy()` is immediate cancellation for exceptional teardown, including failed startup; it can discard unpersisted in-memory work. Neither API can guarantee a save after the browser process is forcibly terminated. Only completed local saves survive reopening.
20
20
 
21
+ Edits received from another local-storage peer also remain unconfirmed until covered by an authoritative server version. Receiving a cross-tab notification is not a server acknowledgement.
22
+
21
23
  Reopening uses the stored Loro history and the server's version vector to derive missing updates, without replaying semantic operations or their external side effects. Undo history remains limited to the current session.
22
24
 
23
25
  ## Session undo/redo
package/dist/index.d.ts CHANGED
@@ -639,7 +639,7 @@ interface WaitForServerAckOptions {
639
639
  }
640
640
  /** Document-level confirmation is independent of local operation completion. */
641
641
  interface MengineDocSyncState {
642
- /** Remote-only imports do not create a new local confirmation obligation. */
642
+ /** Server-originated imports do not create a new local confirmation obligation. */
643
643
  readonly confirmation: 'unknown' | 'pending' | 'confirmed';
644
644
  /** Transport/activity phase. Idle does not imply confirmation; failure details
645
645
  * remain available through push outcomes and confirmation wait errors. */
@@ -797,6 +797,7 @@ declare class MengineDocSession {
797
797
  * Hosts should use this for normal teardown; destroy() is immediate cancellation. */
798
798
  close(): Promise<void>;
799
799
  getSyncState(): MengineDocSyncState;
800
+ private trackLocalVersion;
800
801
  private confirmationTarget;
801
802
  /** Immediately supplies current state; unsubscribe when the host changes docs. */
802
803
  subscribeSyncState(cb: (state: MengineDocSyncState) => void): () => void;
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { t as __exportAll } from "./chunk-D7D4PA-g.js";
2
2
  import { A as isEmptyVideoClip, C as fillMainTrackTimeGaps, D as resolveSpeechOverlapByShiftingVideos, E as resolveAllSpeechOverlaps, F as partUnionToDraft, I as recordEntries, L as videoDocumentMirrorSchema, M as safeDurationMs, N as DEFAULT_UNIT_TIME_MS, O as syncAggregatedClipsTimePosition, P as effectiveVideoClipDurationMs, R as base64ToBytes, S as arrangeMainTrackSeamlessly, T as recalculateTimelineDuration, _ as ensureLaneTrack, a as DocumentMutationGuard, b as solveVideoDocument, c as derivePositionFromAbs, d as VideoDocumentValidationError, f as assertValidVideoDocument, g as LANE_KINDS_IN_STACK_ORDER, h as videoDocumentSchema, i as readVideoDocumentFromDraft, j as partDurationMs, k as TIMELINE_SKELETON_DURATION_MS, l as fromVideoDocument, m as partUnionSchema, n as createMirrorVideoDocument, o as buildInitialVideoDocument, p as validateVideoDocument, r as createMirrorVideoDocumentAdapter, s as buildSpeechHostMap, t as MirrorVideoDocumentAdapter, u as toVideoDocument, v as findLaneTrack, w as reassignSpeechesToVideoClipsByTime, x as cascadeAfterVideoClipChanges, y as laneTrackId, z as bytesToBase64 } from "./document-CmjJwOba.js";
3
3
  import { z } from "zod";
4
- import { LoroDoc, UndoManager, VersionVector } from "loro-crdt";
4
+ import { LoroDoc, UndoManager, VersionVector, decodeImportBlobMeta } from "loro-crdt";
5
5
  import { ClientServerSynchronizer, DocManager } from "@mengine/sync";
6
6
  import { DisposableSet, EventBus, Task } from "@mengine/utils";
7
7
  import { BaseDocStorage, DummyConnection } from "@mengine/storage";
@@ -2923,7 +2923,7 @@ var MengineDocSession = class {
2923
2923
  this.adapterValue = new MirrorVideoDocumentAdapter(doc, this.mutationGuard);
2924
2924
  const unsubscribe = doc.subscribe((event) => {
2925
2925
  if (this.adapterValue == null) return;
2926
- if (event.by === "local") this.localVersionValue = doc.version();
2926
+ if (event.by === "local") this.trackLocalVersion(doc.version());
2927
2927
  this.emitSyncState();
2928
2928
  this.events.emit("update", {
2929
2929
  source: event.by === "local" ? "local" : "remote",
@@ -2931,6 +2931,10 @@ var MengineDocSession = class {
2931
2931
  });
2932
2932
  });
2933
2933
  this.disposables.add(unsubscribe);
2934
+ this.disposables.add(this.manager.onLocalUpdateReceived(this.docId, (update) => {
2935
+ this.trackLocalVersion(decodeImportBlobMeta(update, true).partialEndVersionVector);
2936
+ this.emitSyncState();
2937
+ }));
2934
2938
  this.disposables.add(this.manager.onDocStateChange(this.docId, (state) => {
2935
2939
  this.events.emit("state", state);
2936
2940
  this.emitSyncState();
@@ -2941,6 +2945,7 @@ var MengineDocSession = class {
2941
2945
  this.undoManagerValue = new DocumentUndoManager(doc, this.mutationGuard, () => this.events.emit("undoState"));
2942
2946
  this.editorValue = new SemanticEditor(this.adapterValue);
2943
2947
  this.initialVersionValue = doc.version();
2948
+ if (this.localVersionValue) this.trackLocalVersion(this.initialVersionValue);
2944
2949
  this.emitSyncState();
2945
2950
  return this.snapshot();
2946
2951
  }
@@ -2983,6 +2988,14 @@ var MengineDocSession = class {
2983
2988
  phase: connection === "disconnected" ? "offline" : this.pushErrorValue != null || state.error != null ? "failed" : connection === "connecting" ? "connecting" : state.syncing ? "syncing" : "idle"
2984
2989
  };
2985
2990
  }
2991
+ trackLocalVersion(version) {
2992
+ const target = VersionVector.parseJSON(this.confirmationTarget()?.toJSON() ?? /* @__PURE__ */ new Map());
2993
+ for (const [peer, counter] of version.toJSON()) if ((target.get(peer) ?? 0) < counter) target.setEnd({
2994
+ peer,
2995
+ counter
2996
+ });
2997
+ this.localVersionValue = target;
2998
+ }
2986
2999
  confirmationTarget() {
2987
3000
  return this.localVersionValue ?? this.initialVersionValue;
2988
3001
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mengine/medeo-client",
3
- "version": "2.0.1-alpha.0",
3
+ "version": "2.0.1-alpha.1",
4
4
  "license": "UNLICENSED",
5
5
  "repository": {
6
6
  "type": "git",
@@ -25,9 +25,9 @@
25
25
  "dependencies": {
26
26
  "loro-mirror": "^2.3.3",
27
27
  "zod": "^4.4.3",
28
- "@mengine/storage": "2.0.1-alpha.0",
29
- "@mengine/sync": "2.0.1-alpha.0",
30
- "@mengine/utils": "2.0.1-alpha.0"
28
+ "@mengine/storage": "2.0.1-alpha.1",
29
+ "@mengine/sync": "2.0.1-alpha.1",
30
+ "@mengine/utils": "2.0.1-alpha.1"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/node": "^25.9.1",