@mengine/medeo-client 2.0.0 → 2.0.1-alpha.0
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 +12 -0
- package/dist/index.d.ts +20 -2
- package/dist/index.js +37 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -8,6 +8,18 @@ This package owns the shared `VideoDocument` contract, semantic editing layer, a
|
|
|
8
8
|
|
|
9
9
|
`getState().loaded` means the first local load completed. Once loaded, `loadedFromLocal` reports whether that load imported a snapshot, including a valid empty document. It stays unchanged by later edits and remote updates. Document readiness does not depend on metadata or nonempty tracks.
|
|
10
10
|
|
|
11
|
+
## Local persistence
|
|
12
|
+
|
|
13
|
+
Browser hosts can inject `IndexedDBDocStorage` through `localStorage`. An optional `initialSnapshot` merges a freshly fetched server snapshot into that storage before DocManager loads it; it never replaces locally saved, unconfirmed edits. The host can require a successful online fetch before constructing the session.
|
|
14
|
+
|
|
15
|
+
`getLocalSaveState()` / `subscribeLocalSaveState()` report `{ status: 'saving' | 'saved' | 'failed', error }` for this session's local commits. This is separate from `getSyncState()` and server confirmation. The storage adapter determines durability: IndexedDB resolves only after its transaction commits; MemoryDocStorage remains in memory. Failed saves retain their causal order and retry without blocking other documents.
|
|
16
|
+
|
|
17
|
+
`waitForLocalSave({ timeoutMs? })` waits for the commits present at invocation (default deadline: 15 seconds). Later edits do not extend that target. Timing out only stops the wait; persistence continues. This does not wait for server acknowledgement.
|
|
18
|
+
|
|
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
|
+
|
|
21
|
+
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
|
+
|
|
11
23
|
## Session undo/redo
|
|
12
24
|
|
|
13
25
|
After `await session.start()`, `session.undo(options?)` and `session.redo(options?)` synchronously apply local history and return whether they produced a document update. `options` accepts the same actor/intent metadata as semantic edits. Read the resulting document through `session.snapshot()`; use `waitForServerAck()` only when durable confirmation is required.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { $ as VideoDraft, A as assertValidVideoDocument, B as CaptionPart, C as index_d_exports, D as VideoDocumentMirrorSchema, E as VideoDocumentDraft, F as buildSpeechHostMap, G as Timeline, H as PartKind, I as derivePositionFromAbs, J as TrackItemTimePosition, K as Track, L as fromVideoDocument, M as buildInitialVideoDocument, N as DerivedItemPosition, O as videoDocumentMirrorSchema, P as SpeechHostMap, Q as VideoDocumentValidationIssueCode, R as toVideoDocument, S as ValidationError, T as TrackItemDraft, U as PartUnion, V as DEFAULT_UNIT_TIME_MS, W as SpeechPart, X as VideoDocument, Y as VideoClipPart, Z as VideoDocumentValidationIssue, _ as PlannedSemanticOpKind, a as MirrorVideoDocumentOptions, at as PartAggregation, b as SchemaValidator, c as CommitOptions, ct as Track$1, d as SemanticEditor, et as VideoDraftContent, f as SemanticOpInput, g as ImplementedSemanticOpKind, h as IMPLEMENTED_SEMANTIC_OP_KINDS, i as MirrorVideoDocumentAdapter, it as CaptionStyle, j as validateVideoDocument, k as VideoDocumentValidationError, l as OpActor, lt as TrackItem$1, m as TransactAudit, n as videoDocumentSchema, nt as Attachment, o as createMirrorVideoDocument, ot as SpeedShift, p as SemanticOpName, q as TrackItem, r as readVideoDocumentFromDraft, rt as CaptionPart$1, s as createMirrorVideoDocumentAdapter, st as Timeline$1, t as partUnionSchema, tt as VideoDraftPartUnion, u as SemanticDocumentAdapter, v as SemanticOpKind, w as TrackDraft, x as SnapshotReadable, y as isImplementedSemanticOpKind, z as BgmPart } from "./index-CnZ9l3rb.js";
|
|
2
2
|
import { LoroDoc, PeerID } from "loro-crdt";
|
|
3
|
-
import { DocState } from "@mengine/sync";
|
|
3
|
+
import { DocState, LocalSaveState } from "@mengine/sync";
|
|
4
4
|
import { BaseDocStorage, Connection, DocDiff, DocPushReceipt, DocSnapshotRecord, DocStorage, DocStorageOptions, DocUpdate, DocUpdateRecord } from "@mengine/storage";
|
|
5
5
|
|
|
6
6
|
//#region src/client/base64.d.ts
|
|
@@ -628,6 +628,11 @@ declare class MengineAckFailedError extends Error {
|
|
|
628
628
|
readonly cause: Error | undefined;
|
|
629
629
|
constructor(reason: 'timeout' | 'rejected' | 'failed', code: string | undefined, cause: Error | undefined, message: string);
|
|
630
630
|
}
|
|
631
|
+
type MengineLocalSaveState = LocalSaveState;
|
|
632
|
+
interface WaitForLocalSaveOptions {
|
|
633
|
+
/** Only limits waiting, never cancels persistence. */
|
|
634
|
+
timeoutMs?: number;
|
|
635
|
+
}
|
|
631
636
|
interface WaitForServerAckOptions {
|
|
632
637
|
/** Deadline in ms. Rejects with reason `timeout` when it elapses. */
|
|
633
638
|
timeoutMs?: number;
|
|
@@ -649,6 +654,9 @@ interface MengineDocSessionOptions {
|
|
|
649
654
|
* Browsers should pass an `IndexedDBDocStorage` for refresh/cross-tab support.
|
|
650
655
|
*/
|
|
651
656
|
localStorage?: DocStorageLike;
|
|
657
|
+
/** A freshly fetched remote snapshot to merge into storage before loading.
|
|
658
|
+
* Existing local changes are retained; the host owns any online startup gate. */
|
|
659
|
+
initialSnapshot?: Uint8Array;
|
|
652
660
|
sseReconnectDelayMs?: number;
|
|
653
661
|
}
|
|
654
662
|
/**
|
|
@@ -685,6 +693,7 @@ declare class MengineDocSession {
|
|
|
685
693
|
private started;
|
|
686
694
|
private startTask;
|
|
687
695
|
private destroyed;
|
|
696
|
+
private closeTask;
|
|
688
697
|
private lifetime;
|
|
689
698
|
private hasConnected;
|
|
690
699
|
private initialVersionValue;
|
|
@@ -778,6 +787,15 @@ declare class MengineDocSession {
|
|
|
778
787
|
*/
|
|
779
788
|
start(): Promise<VideoDocument>;
|
|
780
789
|
private open;
|
|
790
|
+
getLocalSaveState(): MengineLocalSaveState;
|
|
791
|
+
/** Immediately reports local transaction state; independent of server confirmation. */
|
|
792
|
+
subscribeLocalSaveState(cb: (state: MengineLocalSaveState) => void): () => void;
|
|
793
|
+
/** Waits for commits present now to reach local storage. Does not wait for the network. */
|
|
794
|
+
waitForLocalSave(options?: WaitForLocalSaveOptions): Promise<void>;
|
|
795
|
+
/** Stop accepting edits and drain local persistence before releasing resources.
|
|
796
|
+
* A failed local write keeps retrying, even after the host has unmounted.
|
|
797
|
+
* Hosts should use this for normal teardown; destroy() is immediate cancellation. */
|
|
798
|
+
close(): Promise<void>;
|
|
781
799
|
getSyncState(): MengineDocSyncState;
|
|
782
800
|
private confirmationTarget;
|
|
783
801
|
/** Immediately supplies current state; unsubscribe when the host changes docs. */
|
|
@@ -1115,4 +1133,4 @@ declare function hostForAbsMs(ranges: MainClipRange[], absMs: number): MainClipR
|
|
|
1115
1133
|
*/
|
|
1116
1134
|
declare function relativePositionForAbs(ranges: MainClipRange[], absMs: number): TrackItemTimePosition;
|
|
1117
1135
|
//#endregion
|
|
1118
|
-
export { type Aggregation, type Attachment, type BgmPart, type CaptionPart, type CaptionStyle, type CommitOptions, DEFAULT_UNIT_TIME_MS, type DerivedItemPosition, type DocStorageLike, type DocVersionMark, IMPLEMENTED_SEMANTIC_OP_KINDS, type ImplementedSemanticOpKind, LANE_KINDS_IN_STACK_ORDER, type LaneKind, type MainClipRange, type MakeEmptyPart, ManualSyncDoc, type ManualSyncDocOptions, MedeoHttpDocStorage, type MedeoHttpDocStorageOptions, MemoryDocStorage, MengineAckFailedError, type MengineAuditEntry, type MengineAuditResponse, MengineDocSession, type MengineDocSessionOptions, type MengineDocSessionUpdateEvent, type MengineDocSyncState, type MengineDocumentVersion, type MengineEventStreamOptions, MengineHttpClient, type MengineHttpClientOptions, MengineHttpRequestError, MenginePushRejectedError, type MenginePushResponse, type MenginePushUpdateResponse, type MengineRejectedResponse, type MengineSnapshotResponse, type MengineSseUpdateEvent, type MengineSyncResponse, type MengineUndoState, type MengineUpdateMeta, MirrorVideoDocumentAdapter, type MirrorVideoDocumentOptions, type OpActor, type PartAggregation, type PartKind, type PartUnion, type PlannedSemanticOpKind, type PullFailureReason, type PullResult, type PushOutcome, type PushOutcomeKind, type PushResult, type PushResultKind, SchemaValidator, type SemanticDocumentAdapter, SemanticEditor, type SemanticOpInput, type SemanticOpKind, type SemanticOpName, type SnapshotReadable, type SolvedVideoDocument, type SpeechHostMap, type SpeechPart, type SpeedShift, TIMELINE_SKELETON_DURATION_MS, type Timeline, type TimelineDoc, type TimelineItem, type Track, type TrackDraft, type TrackItem, type TrackItemDraft, type TrackItemTimePosition, type TransactAudit, ValidationError, type VideoClipPart, type VideoDocument, type VideoDocumentDraft, type VideoDocumentMirrorSchema, VideoDocumentValidationError, type VideoDocumentValidationIssue, type VideoDocumentValidationIssueCode, type VideoDraft, type CaptionPart$1 as VideoDraftCaptionPart, type VideoDraftContent, type VideoDraftPartUnion, type Timeline$1 as VideoDraftTimeline, type Track$1 as VideoDraftTrack, type TrackItem$1 as VideoDraftTrackItem, type WaitForServerAckOptions, arrangeMainTrackSeamlessly, assertValidVideoDocument, base64ToBytes, buildInitialVideoDocument, buildSpeechHostMap, bytesToBase64, cascadeAfterVideoClipChanges, createMirrorVideoDocument, createMirrorVideoDocumentAdapter, decodeDocVersionMark, derivePositionFromAbs, encodeDocVersionMark, ensureLaneTrack, fillMainTrackTimeGaps, findLaneTrack, fromVideoDocument, generatePartId, getAt, hostForAbsMs, isEmptyVideoClip, isImplementedSemanticOpKind, isMap, laneTrackId, mainTrackRanges, partDurationMs, partUnionSchema, readMainTrackItems, readMengineEventStream, readPart, readPartDurationMs, readVideoDocumentFromDraft, reassignSpeechesToVideoClipsByTime, recalculateTimelineDuration, relativePositionForAbs, resolveAllSpeechOverlaps, resolveSpeechOverlapByShiftingVideos, safeDurationMs, index_d_exports as schemas, snapshotToPlain, solveVideoDocument, syncAggregatedClipsTimePosition, toVideoDocument, validateVideoDocument, videoDocumentMirrorSchema, videoDocumentSchema };
|
|
1136
|
+
export { type Aggregation, type Attachment, type BgmPart, type CaptionPart, type CaptionStyle, type CommitOptions, DEFAULT_UNIT_TIME_MS, type DerivedItemPosition, type DocStorageLike, type DocVersionMark, IMPLEMENTED_SEMANTIC_OP_KINDS, type ImplementedSemanticOpKind, LANE_KINDS_IN_STACK_ORDER, type LaneKind, type MainClipRange, type MakeEmptyPart, ManualSyncDoc, type ManualSyncDocOptions, MedeoHttpDocStorage, type MedeoHttpDocStorageOptions, MemoryDocStorage, MengineAckFailedError, type MengineAuditEntry, type MengineAuditResponse, MengineDocSession, type MengineDocSessionOptions, type MengineDocSessionUpdateEvent, type MengineDocSyncState, type MengineDocumentVersion, type MengineEventStreamOptions, MengineHttpClient, type MengineHttpClientOptions, MengineHttpRequestError, type MengineLocalSaveState, MenginePushRejectedError, type MenginePushResponse, type MenginePushUpdateResponse, type MengineRejectedResponse, type MengineSnapshotResponse, type MengineSseUpdateEvent, type MengineSyncResponse, type MengineUndoState, type MengineUpdateMeta, MirrorVideoDocumentAdapter, type MirrorVideoDocumentOptions, type OpActor, type PartAggregation, type PartKind, type PartUnion, type PlannedSemanticOpKind, type PullFailureReason, type PullResult, type PushOutcome, type PushOutcomeKind, type PushResult, type PushResultKind, SchemaValidator, type SemanticDocumentAdapter, SemanticEditor, type SemanticOpInput, type SemanticOpKind, type SemanticOpName, type SnapshotReadable, type SolvedVideoDocument, type SpeechHostMap, type SpeechPart, type SpeedShift, TIMELINE_SKELETON_DURATION_MS, type Timeline, type TimelineDoc, type TimelineItem, type Track, type TrackDraft, type TrackItem, type TrackItemDraft, type TrackItemTimePosition, type TransactAudit, ValidationError, type VideoClipPart, type VideoDocument, type VideoDocumentDraft, type VideoDocumentMirrorSchema, VideoDocumentValidationError, type VideoDocumentValidationIssue, type VideoDocumentValidationIssueCode, type VideoDraft, type CaptionPart$1 as VideoDraftCaptionPart, type VideoDraftContent, type VideoDraftPartUnion, type Timeline$1 as VideoDraftTimeline, type Track$1 as VideoDraftTrack, type TrackItem$1 as VideoDraftTrackItem, type WaitForLocalSaveOptions, type WaitForServerAckOptions, arrangeMainTrackSeamlessly, assertValidVideoDocument, base64ToBytes, buildInitialVideoDocument, buildSpeechHostMap, bytesToBase64, cascadeAfterVideoClipChanges, createMirrorVideoDocument, createMirrorVideoDocumentAdapter, decodeDocVersionMark, derivePositionFromAbs, encodeDocVersionMark, ensureLaneTrack, fillMainTrackTimeGaps, findLaneTrack, fromVideoDocument, generatePartId, getAt, hostForAbsMs, isEmptyVideoClip, isImplementedSemanticOpKind, isMap, laneTrackId, mainTrackRanges, partDurationMs, partUnionSchema, readMainTrackItems, readMengineEventStream, readPart, readPartDurationMs, readVideoDocumentFromDraft, reassignSpeechesToVideoClipsByTime, recalculateTimelineDuration, relativePositionForAbs, resolveAllSpeechOverlaps, resolveSpeechOverlapByShiftingVideos, safeDurationMs, index_d_exports as schemas, snapshotToPlain, solveVideoDocument, syncAggregatedClipsTimePosition, toVideoDocument, validateVideoDocument, videoDocumentMirrorSchema, videoDocumentSchema };
|
package/dist/index.js
CHANGED
|
@@ -2705,6 +2705,7 @@ var MengineDocSession = class {
|
|
|
2705
2705
|
started = false;
|
|
2706
2706
|
startTask = null;
|
|
2707
2707
|
destroyed = false;
|
|
2708
|
+
closeTask = null;
|
|
2708
2709
|
lifetime = null;
|
|
2709
2710
|
hasConnected = false;
|
|
2710
2711
|
initialVersionValue = null;
|
|
@@ -2904,6 +2905,13 @@ var MengineDocSession = class {
|
|
|
2904
2905
|
this.local.connection.connect();
|
|
2905
2906
|
await this.local.connection.waitForConnected().abortOn(this.lifetime.signal);
|
|
2906
2907
|
if (this.destroyed) throw new Error("mengine doc session destroyed");
|
|
2908
|
+
if (this.options.initialSnapshot) {
|
|
2909
|
+
await this.local.pushDocUpdate({
|
|
2910
|
+
docId: this.docId,
|
|
2911
|
+
data: this.options.initialSnapshot
|
|
2912
|
+
}, "initial-snapshot");
|
|
2913
|
+
if (this.destroyed) throw new Error("mengine doc session destroyed");
|
|
2914
|
+
}
|
|
2907
2915
|
this.server.connection.connect();
|
|
2908
2916
|
this.synchronizer.start();
|
|
2909
2917
|
this.manager.start();
|
|
@@ -2936,6 +2944,35 @@ var MengineDocSession = class {
|
|
|
2936
2944
|
this.emitSyncState();
|
|
2937
2945
|
return this.snapshot();
|
|
2938
2946
|
}
|
|
2947
|
+
getLocalSaveState() {
|
|
2948
|
+
return this.getState().localSave;
|
|
2949
|
+
}
|
|
2950
|
+
/** Immediately reports local transaction state; independent of server confirmation. */
|
|
2951
|
+
subscribeLocalSaveState(cb) {
|
|
2952
|
+
const off = this.events.on("state", () => cb(this.getLocalSaveState()));
|
|
2953
|
+
cb(this.getLocalSaveState());
|
|
2954
|
+
return off;
|
|
2955
|
+
}
|
|
2956
|
+
/** Waits for commits present now to reach local storage. Does not wait for the network. */
|
|
2957
|
+
async waitForLocalSave(options = {}) {
|
|
2958
|
+
if (!this.editorValue || this.destroyed) throw new Error("mengine doc session is not started");
|
|
2959
|
+
await this.manager.waitForLocalSave(this.docId).timeout(options.timeoutMs ?? 15e3);
|
|
2960
|
+
}
|
|
2961
|
+
/** Stop accepting edits and drain local persistence before releasing resources.
|
|
2962
|
+
* A failed local write keeps retrying, even after the host has unmounted.
|
|
2963
|
+
* Hosts should use this for normal teardown; destroy() is immediate cancellation. */
|
|
2964
|
+
close() {
|
|
2965
|
+
if (this.closeTask) return this.closeTask;
|
|
2966
|
+
if (this.destroyed || !this.editorValue) {
|
|
2967
|
+
this.destroy();
|
|
2968
|
+
return Promise.resolve();
|
|
2969
|
+
}
|
|
2970
|
+
this.mutationGuard.close();
|
|
2971
|
+
this.synchronizer.stop();
|
|
2972
|
+
this.server.connection.disconnect();
|
|
2973
|
+
this.closeTask = this.manager.waitForLocalSave(this.docId).then(() => this.destroy());
|
|
2974
|
+
return this.closeTask;
|
|
2975
|
+
}
|
|
2939
2976
|
getSyncState() {
|
|
2940
2977
|
const state = this.getState();
|
|
2941
2978
|
const target = this.confirmationTarget();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mengine/medeo-client",
|
|
3
|
-
"version": "2.0.0",
|
|
3
|
+
"version": "2.0.1-alpha.0",
|
|
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/
|
|
29
|
-
"@mengine/
|
|
30
|
-
"@mengine/
|
|
28
|
+
"@mengine/storage": "2.0.1-alpha.0",
|
|
29
|
+
"@mengine/sync": "2.0.1-alpha.0",
|
|
30
|
+
"@mengine/utils": "2.0.1-alpha.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@types/node": "^25.9.1",
|